1
Arm queue; not huge but I figured I might as well send it out since
1
Hi; here's a queue of arm patches (plus a few elf2dmp changes);
2
I've been doing code review today and there's no queue of unprocessed
2
mostly these are minor cleanups and bugfixes.
3
pullreqs...
4
3
5
thanks
4
thanks
6
-- PMM
5
-- PMM
7
6
8
The following changes since commit b3f846c59d8405bb87c551187721fc92ff2f1b92:
7
The following changes since commit deaca3fd30d3a8829160f8d3705d65ad83176800:
9
8
10
Merge remote-tracking branch 'remotes/huth-gitlab/tags/pull-request-2021-01-11v2' into staging (2021-01-11 15:15:35 +0000)
9
Merge tag 'pull-vfio-20231018' of https://github.com/legoater/qemu into staging (2023-10-18 06:21:15 -0400)
11
10
12
are available in the Git repository at:
11
are available in the Git repository at:
13
12
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210112
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20231019
15
14
16
for you to fetch changes up to 19d131395ccaf503db21dadd8257e6dc9fc1d7de:
15
for you to fetch changes up to 2a052b4ee01b3c413cef2ef49cb780cde17d4ba1:
17
16
18
ui/cocoa: Fix openFile: deprecation on Big Sur (2021-01-12 11:38:37 +0000)
17
contrib/elf2dmp: Use g_malloc(), g_new() and g_free() (2023-10-19 14:32:13 +0100)
19
18
20
----------------------------------------------------------------
19
----------------------------------------------------------------
21
target-arm queue:
20
target-arm queue:
22
* arm: Support emulation of ARMv8.4-TTST extension
21
* hw/arm: Move raspberrypi-fw-defs.h to the include/hw/arm/ folder
23
* arm: Update cpu.h ID register field definitions
22
* hw/arm/exynos4210: Get arm_boot_info declaration from 'hw/arm/boot'
24
* arm: Fix breakage of XScale instruction emulation
23
* xlnx devices: remove deprecated device reset
25
* hw/net/lan9118: Fix RX Status FIFO PEEK value
24
* xlnx-bbram: hw/nvram: Use dot in device type name
26
* npcm7xx: Add ADC and PWM emulation
25
* elf2dmp: fix coverity issues
27
* ui/cocoa: Make "open docs" help menu entry work again when binary
26
* elf2dmp: convert to g_malloc, g_new and g_free
28
is run from the build tree
27
* target/arm: Fix CNTPCT_EL0 trapping from EL0 when HCR_EL2.E2H is 0
29
* ui/cocoa: Fix openFile: deprecation on Big Sur
28
* hw/arm: refactor virt PPI logic
30
* docs: Add qemu-storage-daemon(1) manpage to meson.build
29
* arm/kvm: convert to kvm_set_one_reg, kvm_get_one_reg
31
* docs: Build and install all the docs in a single manual
30
* target/arm: Permit T32 LDM with single register
31
* smmuv3: Advertise SMMUv3.1-XNX
32
* target/arm: Implement FEAT_HPMN0
33
* Remove some unnecessary include lines
34
* target/arm/arm-powerctl: Correctly init CPUs when powered on to lower EL
35
* hw/timer/npcm7xx_timer: Prevent timer from counting down past zero
32
36
33
----------------------------------------------------------------
37
----------------------------------------------------------------
34
Hao Wu (6):
38
Chris Rauer (1):
35
hw/misc: Add clock converter in NPCM7XX CLK module
39
hw/timer/npcm7xx_timer: Prevent timer from counting down past zero
36
hw/timer: Refactor NPCM7XX Timer to use CLK clock
37
hw/adc: Add an ADC module for NPCM7XX
38
hw/misc: Add a PWM module for NPCM7XX
39
hw/misc: Add QTest for NPCM7XX PWM Module
40
hw/*: Use type casting for SysBusDevice in NPCM7XX
41
40
42
Leif Lindholm (6):
41
Cornelia Huck (2):
43
target/arm: fix typo in cpu.h ID_AA64PFR1 field name
42
arm/kvm: convert to kvm_set_one_reg
44
target/arm: make ARMCPU.clidr 64-bit
43
arm/kvm: convert to kvm_get_one_reg
45
target/arm: make ARMCPU.ctr 64-bit
46
target/arm: add descriptions of CLIDR_EL1, CCSIDR_EL1, CTR_EL0 to cpu.h
47
target/arm: add aarch64 ID register fields to cpu.h
48
target/arm: add aarch32 ID register fields to cpu.h
49
44
50
Peter Maydell (5):
45
Leif Lindholm (3):
51
docs: Add qemu-storage-daemon(1) manpage to meson.build
46
{include/}hw/arm: refactor virt PPI logic
52
docs: Build and install all the docs in a single manual
47
include/hw/arm: move BSA definitions to bsa.h
53
target/arm: Don't decode insns in the XScale/iWMMXt space as cp insns
48
hw/arm/sbsa-ref: use bsa.h for PPI definitions
54
hw/net/lan9118: Fix RX Status FIFO PEEK value
55
hw/net/lan9118: Add symbolic constants for register offsets
56
49
57
Roman Bolshakov (2):
50
Michal Orzel (1):
58
ui/cocoa: Update path to docs in build tree
51
target/arm: Fix CNTPCT_EL0 trapping from EL0 when HCR_EL2.E2H is 0
59
ui/cocoa: Fix openFile: deprecation on Big Sur
60
52
61
Rémi Denis-Courmont (2):
53
Peter Maydell (8):
62
target/arm: ARMv8.4-TTST extension
54
target/arm: Permit T32 LDM with single register
63
target/arm: enable Small Translation tables in max CPU
55
hw/arm/smmuv3: Update ID register bit field definitions
56
hw/arm/smmuv3: Sort ID register setting into field order
57
hw/arm/smmuv3: Advertise SMMUv3.1-XNX feature
58
target/arm: Implement FEAT_HPMN0
59
target/arm/kvm64.c: Remove unused include
60
target/arm/common-semi-target.h: Remove unnecessary boot.h include
61
target/arm/arm-powerctl: Correctly init CPUs when powered on to lower EL
64
62
65
docs/conf.py | 46 ++-
63
Philippe Mathieu-Daudé (1):
66
docs/devel/conf.py | 15 -
64
hw/arm/exynos4210: Get arm_boot_info declaration from 'hw/arm/boot.h'
67
docs/index.html.in | 17 -
68
docs/interop/conf.py | 28 --
69
docs/meson.build | 65 ++--
70
docs/specs/conf.py | 16 -
71
docs/system/arm/nuvoton.rst | 4 +-
72
docs/system/conf.py | 28 --
73
docs/tools/conf.py | 37 --
74
docs/user/conf.py | 15 -
75
meson.build | 1 +
76
hw/adc/trace.h | 1 +
77
include/hw/adc/npcm7xx_adc.h | 69 ++++
78
include/hw/arm/npcm7xx.h | 4 +
79
include/hw/misc/npcm7xx_clk.h | 146 ++++++-
80
include/hw/misc/npcm7xx_pwm.h | 105 +++++
81
include/hw/timer/npcm7xx_timer.h | 1 +
82
target/arm/cpu.h | 85 ++++-
83
hw/adc/npcm7xx_adc.c | 301 +++++++++++++++
84
hw/arm/npcm7xx.c | 55 ++-
85
hw/arm/npcm7xx_boards.c | 2 +-
86
hw/mem/npcm7xx_mc.c | 2 +-
87
hw/misc/npcm7xx_clk.c | 807 ++++++++++++++++++++++++++++++++++++++-
88
hw/misc/npcm7xx_gcr.c | 2 +-
89
hw/misc/npcm7xx_pwm.c | 550 ++++++++++++++++++++++++++
90
hw/misc/npcm7xx_rng.c | 2 +-
91
hw/net/lan9118.c | 26 +-
92
hw/nvram/npcm7xx_otp.c | 2 +-
93
hw/ssi/npcm7xx_fiu.c | 2 +-
94
hw/timer/npcm7xx_timer.c | 39 +-
95
target/arm/cpu64.c | 1 +
96
target/arm/helper.c | 15 +-
97
target/arm/translate.c | 7 +
98
tests/qtest/npcm7xx_adc-test.c | 377 ++++++++++++++++++
99
tests/qtest/npcm7xx_pwm-test.c | 490 ++++++++++++++++++++++++
100
hw/adc/meson.build | 1 +
101
hw/adc/trace-events | 5 +
102
hw/misc/meson.build | 1 +
103
hw/misc/trace-events | 6 +
104
tests/qtest/meson.build | 4 +-
105
ui/cocoa.m | 7 +-
106
41 files changed, 3124 insertions(+), 263 deletions(-)
107
delete mode 100644 docs/devel/conf.py
108
delete mode 100644 docs/index.html.in
109
delete mode 100644 docs/interop/conf.py
110
delete mode 100644 docs/specs/conf.py
111
delete mode 100644 docs/system/conf.py
112
delete mode 100644 docs/tools/conf.py
113
delete mode 100644 docs/user/conf.py
114
create mode 100644 hw/adc/trace.h
115
create mode 100644 include/hw/adc/npcm7xx_adc.h
116
create mode 100644 include/hw/misc/npcm7xx_pwm.h
117
create mode 100644 hw/adc/npcm7xx_adc.c
118
create mode 100644 hw/misc/npcm7xx_pwm.c
119
create mode 100644 tests/qtest/npcm7xx_adc-test.c
120
create mode 100644 tests/qtest/npcm7xx_pwm-test.c
121
create mode 100644 hw/adc/trace-events
122
65
66
Suraj Shirvankar (1):
67
contrib/elf2dmp: Use g_malloc(), g_new() and g_free()
68
69
Thomas Huth (1):
70
hw/arm: Move raspberrypi-fw-defs.h to the include/hw/arm/ folder
71
72
Tong Ho (4):
73
xlnx-bbram: hw/nvram: Remove deprecated device reset
74
xlnx-zynqmp-efuse: hw/nvram: Remove deprecated device reset
75
xlnx-versal-efuse: hw/nvram: Remove deprecated device reset
76
xlnx-bbram: hw/nvram: Use dot in device type name
77
78
Viktor Prutyanov (2):
79
elf2dmp: limit print length for sign_rsds
80
elf2dmp: check array bounds in pdb_get_file_size
81
82
MAINTAINERS | 2 +-
83
docs/system/arm/emulation.rst | 1 +
84
hw/arm/smmuv3-internal.h | 38 ++++++++
85
include/hw/arm/bsa.h | 35 +++++++
86
include/hw/arm/exynos4210.h | 2 +-
87
include/hw/{misc => arm}/raspberrypi-fw-defs.h | 0
88
include/hw/arm/virt.h | 12 +--
89
include/hw/nvram/xlnx-bbram.h | 2 +-
90
target/arm/common-semi-target.h | 4 +-
91
target/arm/cpu-qom.h | 2 -
92
target/arm/cpu.h | 22 +++++
93
contrib/elf2dmp/addrspace.c | 7 +-
94
contrib/elf2dmp/main.c | 11 +--
95
contrib/elf2dmp/pdb.c | 32 ++++---
96
contrib/elf2dmp/qemu_elf.c | 7 +-
97
hw/arm/boot.c | 95 +++++--------------
98
hw/arm/sbsa-ref.c | 21 ++---
99
hw/arm/smmuv3.c | 8 +-
100
hw/arm/virt-acpi-build.c | 12 +--
101
hw/arm/virt.c | 24 +++--
102
hw/misc/bcm2835_property.c | 2 +-
103
hw/nvram/xlnx-bbram.c | 8 +-
104
hw/nvram/xlnx-versal-efuse-ctrl.c | 8 +-
105
hw/nvram/xlnx-zynqmp-efuse.c | 8 +-
106
hw/timer/npcm7xx_timer.c | 3 +
107
target/arm/arm-powerctl.c | 53 +----------
108
target/arm/cpu.c | 95 +++++++++++++++++++
109
target/arm/helper.c | 19 +---
110
target/arm/kvm.c | 28 ++----
111
target/arm/kvm64.c | 124 +++++++------------------
112
target/arm/tcg/cpu32.c | 4 +
113
target/arm/tcg/cpu64.c | 1 +
114
target/arm/tcg/translate.c | 37 +++++---
115
33 files changed, 368 insertions(+), 359 deletions(-)
116
create mode 100644 include/hw/arm/bsa.h
117
rename include/hw/{misc => arm}/raspberrypi-fw-defs.h (100%)
118
diff view generated by jsdifflib
1
A copy-and-paste error meant that the return value for register offset 0x44
1
From: Thomas Huth <thuth@redhat.com>
2
(the RX Status FIFO PEEK register) returned a byte from a bogus offset in
3
the rx status FIFO. Fix the typo.
4
2
5
Cc: qemu-stable@nongnu.org
3
The file is obviously related to the raspberrypi machine, so
6
Fixes: https://bugs.launchpad.net/qemu/+bug/1904954
4
it should reside in hw/arm/ instead of hw/misc/. And while we're
5
at it, also adjust the wildcard in MAINTAINERS so that it covers
6
this file, too.
7
8
Signed-off-by: Thomas Huth <thuth@redhat.com>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
Acked-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Message-id: 20231012073458.860187-1-thuth@redhat.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20210108180401.2263-2-peter.maydell@linaro.org
10
---
13
---
11
hw/net/lan9118.c | 2 +-
14
MAINTAINERS | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
15
include/hw/{misc => arm}/raspberrypi-fw-defs.h | 0
16
hw/misc/bcm2835_property.c | 2 +-
17
3 files changed, 2 insertions(+), 2 deletions(-)
18
rename include/hw/{misc => arm}/raspberrypi-fw-defs.h (100%)
13
19
14
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
20
diff --git a/MAINTAINERS b/MAINTAINERS
15
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/net/lan9118.c
22
--- a/MAINTAINERS
17
+++ b/hw/net/lan9118.c
23
+++ b/MAINTAINERS
18
@@ -XXX,XX +XXX,XX @@ static uint64_t lan9118_readl(void *opaque, hwaddr offset,
24
@@ -XXX,XX +XXX,XX @@ S: Odd Fixes
19
case 0x40:
25
F: hw/arm/raspi.c
20
return rx_status_fifo_pop(s);
26
F: hw/arm/raspi_platform.h
21
case 0x44:
27
F: hw/*/bcm283*
22
- return s->rx_status_fifo[s->tx_status_fifo_head];
28
-F: include/hw/arm/raspi*
23
+ return s->rx_status_fifo[s->rx_status_fifo_head];
29
+F: include/hw/arm/rasp*
24
case 0x48:
30
F: include/hw/*/bcm283*
25
return tx_status_fifo_pop(s);
31
F: docs/system/arm/raspi.rst
26
case 0x4c:
32
33
diff --git a/include/hw/misc/raspberrypi-fw-defs.h b/include/hw/arm/raspberrypi-fw-defs.h
34
similarity index 100%
35
rename from include/hw/misc/raspberrypi-fw-defs.h
36
rename to include/hw/arm/raspberrypi-fw-defs.h
37
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/misc/bcm2835_property.c
40
+++ b/hw/misc/bcm2835_property.c
41
@@ -XXX,XX +XXX,XX @@
42
#include "migration/vmstate.h"
43
#include "hw/irq.h"
44
#include "hw/misc/bcm2835_mbox_defs.h"
45
-#include "hw/misc/raspberrypi-fw-defs.h"
46
+#include "hw/arm/raspberrypi-fw-defs.h"
47
#include "sysemu/dma.h"
48
#include "qemu/log.h"
49
#include "qemu/module.h"
27
--
50
--
28
2.20.1
51
2.34.1
29
52
30
53
diff view generated by jsdifflib
1
From: Leif Lindholm <leif@nuviainc.com>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
Add entries present in ARM DDI 0487F.c (August 2020).
3
struct arm_boot_info is declared in "hw/arm/boot.h".
4
By including the correct header we don't need to declare
5
it again in "target/arm/cpu-qom.h".
4
6
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
9
Message-id: 20231013130214.95742-1-philmd@linaro.org
8
Message-id: 20210108185154.8108-7-leif@nuviainc.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
---
11
target/arm/cpu.h | 28 ++++++++++++++++++++++++++++
12
include/hw/arm/exynos4210.h | 2 +-
12
1 file changed, 28 insertions(+)
13
target/arm/cpu-qom.h | 2 --
14
2 files changed, 1 insertion(+), 3 deletions(-)
13
15
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
18
--- a/include/hw/arm/exynos4210.h
17
+++ b/target/arm/cpu.h
19
+++ b/include/hw/arm/exynos4210.h
18
@@ -XXX,XX +XXX,XX @@ FIELD(ID_ISAR6, DP, 4, 4)
20
@@ -XXX,XX +XXX,XX @@
19
FIELD(ID_ISAR6, FHM, 8, 4)
21
#include "hw/intc/exynos4210_gic.h"
20
FIELD(ID_ISAR6, SB, 12, 4)
22
#include "hw/intc/exynos4210_combiner.h"
21
FIELD(ID_ISAR6, SPECRES, 16, 4)
23
#include "hw/core/split-irq.h"
22
+FIELD(ID_ISAR6, BF16, 20, 4)
24
-#include "target/arm/cpu-qom.h"
23
+FIELD(ID_ISAR6, I8MM, 24, 4)
25
+#include "hw/arm/boot.h"
24
26
#include "qom/object.h"
25
FIELD(ID_MMFR0, VMSA, 0, 4)
27
26
FIELD(ID_MMFR0, PMSA, 4, 4)
28
#define EXYNOS4210_NCPUS 2
27
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR0, AUXREG, 20, 4)
29
diff --git a/target/arm/cpu-qom.h b/target/arm/cpu-qom.h
28
FIELD(ID_MMFR0, FCSE, 24, 4)
30
index XXXXXXX..XXXXXXX 100644
29
FIELD(ID_MMFR0, INNERSHR, 28, 4)
31
--- a/target/arm/cpu-qom.h
30
32
+++ b/target/arm/cpu-qom.h
31
+FIELD(ID_MMFR1, L1HVDVA, 0, 4)
33
@@ -XXX,XX +XXX,XX @@
32
+FIELD(ID_MMFR1, L1UNIVA, 4, 4)
34
#include "hw/core/cpu.h"
33
+FIELD(ID_MMFR1, L1HVDSW, 8, 4)
35
#include "qom/object.h"
34
+FIELD(ID_MMFR1, L1UNISW, 12, 4)
36
35
+FIELD(ID_MMFR1, L1HVD, 16, 4)
37
-struct arm_boot_info;
36
+FIELD(ID_MMFR1, L1UNI, 20, 4)
38
-
37
+FIELD(ID_MMFR1, L1TSTCLN, 24, 4)
39
#define TYPE_ARM_CPU "arm-cpu"
38
+FIELD(ID_MMFR1, BPRED, 28, 4)
40
39
+
41
OBJECT_DECLARE_CPU_TYPE(ARMCPU, ARMCPUClass, ARM_CPU)
40
+FIELD(ID_MMFR2, L1HVDFG, 0, 4)
41
+FIELD(ID_MMFR2, L1HVDBG, 4, 4)
42
+FIELD(ID_MMFR2, L1HVDRNG, 8, 4)
43
+FIELD(ID_MMFR2, HVDTLB, 12, 4)
44
+FIELD(ID_MMFR2, UNITLB, 16, 4)
45
+FIELD(ID_MMFR2, MEMBARR, 20, 4)
46
+FIELD(ID_MMFR2, WFISTALL, 24, 4)
47
+FIELD(ID_MMFR2, HWACCFLG, 28, 4)
48
+
49
FIELD(ID_MMFR3, CMAINTVA, 0, 4)
50
FIELD(ID_MMFR3, CMAINTSW, 4, 4)
51
FIELD(ID_MMFR3, BPMAINT, 8, 4)
52
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR4, LSM, 20, 4)
53
FIELD(ID_MMFR4, CCIDX, 24, 4)
54
FIELD(ID_MMFR4, EVT, 28, 4)
55
56
+FIELD(ID_MMFR5, ETS, 0, 4)
57
+
58
FIELD(ID_PFR0, STATE0, 0, 4)
59
FIELD(ID_PFR0, STATE1, 4, 4)
60
FIELD(ID_PFR0, STATE2, 8, 4)
61
@@ -XXX,XX +XXX,XX @@ FIELD(ID_PFR1, SEC_FRAC, 20, 4)
62
FIELD(ID_PFR1, VIRT_FRAC, 24, 4)
63
FIELD(ID_PFR1, GIC, 28, 4)
64
65
+FIELD(ID_PFR2, CSV3, 0, 4)
66
+FIELD(ID_PFR2, SSBS, 4, 4)
67
+FIELD(ID_PFR2, RAS_FRAC, 8, 4)
68
+
69
FIELD(ID_AA64ISAR0, AES, 4, 4)
70
FIELD(ID_AA64ISAR0, SHA1, 8, 4)
71
FIELD(ID_AA64ISAR0, SHA2, 12, 4)
72
@@ -XXX,XX +XXX,XX @@ FIELD(ID_DFR0, MPROFDBG, 20, 4)
73
FIELD(ID_DFR0, PERFMON, 24, 4)
74
FIELD(ID_DFR0, TRACEFILT, 28, 4)
75
76
+FIELD(ID_DFR1, MTPMU, 0, 4)
77
+
78
FIELD(DBGDIDR, SE_IMP, 12, 1)
79
FIELD(DBGDIDR, NSUHD_IMP, 14, 1)
80
FIELD(DBGDIDR, VERSION, 16, 4)
81
--
42
--
82
2.20.1
43
2.34.1
83
44
84
45
diff view generated by jsdifflib
1
From: Leif Lindholm <leif@nuviainc.com>
1
From: Tong Ho <tong.ho@amd.com>
2
2
3
Add entries present in ARM DDI 0487F.c (August 2020).
3
This change implements the ResettableClass interface for the device.
4
4
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
5
Signed-off-by: Tong Ho <tong.ho@amd.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
7
Message-id: 20231003052345.199725-1-tong.ho@amd.com
8
Message-id: 20210108185154.8108-6-leif@nuviainc.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
9
---
11
target/arm/cpu.h | 15 +++++++++++++++
10
hw/nvram/xlnx-bbram.c | 8 +++++---
12
1 file changed, 15 insertions(+)
11
1 file changed, 5 insertions(+), 3 deletions(-)
13
12
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
diff --git a/hw/nvram/xlnx-bbram.c b/hw/nvram/xlnx-bbram.c
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
15
--- a/hw/nvram/xlnx-bbram.c
17
+++ b/target/arm/cpu.h
16
+++ b/hw/nvram/xlnx-bbram.c
18
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64ISAR1, GPI, 28, 4)
17
@@ -XXX,XX +XXX,XX @@
19
FIELD(ID_AA64ISAR1, FRINTTS, 32, 4)
18
* QEMU model of the Xilinx BBRAM Battery Backed RAM
20
FIELD(ID_AA64ISAR1, SB, 36, 4)
19
*
21
FIELD(ID_AA64ISAR1, SPECRES, 40, 4)
20
* Copyright (c) 2014-2021 Xilinx Inc.
22
+FIELD(ID_AA64ISAR1, BF16, 44, 4)
21
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
23
+FIELD(ID_AA64ISAR1, DGH, 48, 4)
22
*
24
+FIELD(ID_AA64ISAR1, I8MM, 52, 4)
23
* Permission is hereby granted, free of charge, to any person obtaining a copy
25
24
* of this software and associated documentation files (the "Software"), to deal
26
FIELD(ID_AA64PFR0, EL0, 0, 4)
25
@@ -XXX,XX +XXX,XX @@ static RegisterAccessInfo bbram_ctrl_regs_info[] = {
27
FIELD(ID_AA64PFR0, EL1, 4, 4)
26
}
28
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64PFR0, ADVSIMD, 20, 4)
27
};
29
FIELD(ID_AA64PFR0, GIC, 24, 4)
28
30
FIELD(ID_AA64PFR0, RAS, 28, 4)
29
-static void bbram_ctrl_reset(DeviceState *dev)
31
FIELD(ID_AA64PFR0, SVE, 32, 4)
30
+static void bbram_ctrl_reset_hold(Object *obj)
32
+FIELD(ID_AA64PFR0, SEL2, 36, 4)
31
{
33
+FIELD(ID_AA64PFR0, MPAM, 40, 4)
32
- XlnxBBRam *s = XLNX_BBRAM(dev);
34
+FIELD(ID_AA64PFR0, AMU, 44, 4)
33
+ XlnxBBRam *s = XLNX_BBRAM(obj);
35
+FIELD(ID_AA64PFR0, DIT, 48, 4)
34
unsigned int i;
36
+FIELD(ID_AA64PFR0, CSV2, 56, 4)
35
37
+FIELD(ID_AA64PFR0, CSV3, 60, 4)
36
for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
38
37
@@ -XXX,XX +XXX,XX @@ static Property bbram_ctrl_props[] = {
39
FIELD(ID_AA64PFR1, BT, 0, 4)
38
static void bbram_ctrl_class_init(ObjectClass *klass, void *data)
40
FIELD(ID_AA64PFR1, SSBS, 4, 4)
39
{
41
FIELD(ID_AA64PFR1, MTE, 8, 4)
40
DeviceClass *dc = DEVICE_CLASS(klass);
42
FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
41
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
43
+FIELD(ID_AA64PFR1, MPAM_FRAC, 16, 4)
42
44
43
- dc->reset = bbram_ctrl_reset;
45
FIELD(ID_AA64MMFR0, PARANGE, 0, 4)
44
+ rc->phases.hold = bbram_ctrl_reset_hold;
46
FIELD(ID_AA64MMFR0, ASIDBITS, 4, 4)
45
dc->realize = bbram_ctrl_realize;
47
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64MMFR0, TGRAN16_2, 32, 4)
46
dc->vmsd = &vmstate_bbram_ctrl;
48
FIELD(ID_AA64MMFR0, TGRAN64_2, 36, 4)
47
device_class_set_props(dc, bbram_ctrl_props);
49
FIELD(ID_AA64MMFR0, TGRAN4_2, 40, 4)
50
FIELD(ID_AA64MMFR0, EXS, 44, 4)
51
+FIELD(ID_AA64MMFR0, FGT, 56, 4)
52
+FIELD(ID_AA64MMFR0, ECV, 60, 4)
53
54
FIELD(ID_AA64MMFR1, HAFDBS, 0, 4)
55
FIELD(ID_AA64MMFR1, VMIDBITS, 4, 4)
56
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64MMFR1, LO, 16, 4)
57
FIELD(ID_AA64MMFR1, PAN, 20, 4)
58
FIELD(ID_AA64MMFR1, SPECSEI, 24, 4)
59
FIELD(ID_AA64MMFR1, XNX, 28, 4)
60
+FIELD(ID_AA64MMFR1, TWED, 32, 4)
61
+FIELD(ID_AA64MMFR1, ETS, 36, 4)
62
63
FIELD(ID_AA64MMFR2, CNP, 0, 4)
64
FIELD(ID_AA64MMFR2, UAO, 4, 4)
65
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64DFR0, CTX_CMPS, 28, 4)
66
FIELD(ID_AA64DFR0, PMSVER, 32, 4)
67
FIELD(ID_AA64DFR0, DOUBLELOCK, 36, 4)
68
FIELD(ID_AA64DFR0, TRACEFILT, 40, 4)
69
+FIELD(ID_AA64DFR0, MTPMU, 48, 4)
70
71
FIELD(ID_DFR0, COPDBG, 0, 4)
72
FIELD(ID_DFR0, COPSDBG, 4, 4)
73
--
48
--
74
2.20.1
49
2.34.1
75
50
76
51
diff view generated by jsdifflib
New patch
1
From: Tong Ho <tong.ho@amd.com>
1
2
3
This change implements the ResettableClass interface for the device.
4
5
Signed-off-by: Tong Ho <tong.ho@amd.com>
6
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
7
Message-id: 20231004055713.324009-1-tong.ho@amd.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
hw/nvram/xlnx-zynqmp-efuse.c | 8 +++++---
11
1 file changed, 5 insertions(+), 3 deletions(-)
12
13
diff --git a/hw/nvram/xlnx-zynqmp-efuse.c b/hw/nvram/xlnx-zynqmp-efuse.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/nvram/xlnx-zynqmp-efuse.c
16
+++ b/hw/nvram/xlnx-zynqmp-efuse.c
17
@@ -XXX,XX +XXX,XX @@
18
* QEMU model of the ZynqMP eFuse
19
*
20
* Copyright (c) 2015 Xilinx Inc.
21
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
22
*
23
* Written by Edgar E. Iglesias <edgari@xilinx.com>
24
*
25
@@ -XXX,XX +XXX,XX @@ static void zynqmp_efuse_register_reset(RegisterInfo *reg)
26
register_reset(reg);
27
}
28
29
-static void zynqmp_efuse_reset(DeviceState *dev)
30
+static void zynqmp_efuse_reset_hold(Object *obj)
31
{
32
- XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(dev);
33
+ XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(obj);
34
unsigned int i;
35
36
for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
37
@@ -XXX,XX +XXX,XX @@ static Property zynqmp_efuse_props[] = {
38
static void zynqmp_efuse_class_init(ObjectClass *klass, void *data)
39
{
40
DeviceClass *dc = DEVICE_CLASS(klass);
41
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
42
43
- dc->reset = zynqmp_efuse_reset;
44
+ rc->phases.hold = zynqmp_efuse_reset_hold;
45
dc->realize = zynqmp_efuse_realize;
46
dc->vmsd = &vmstate_efuse;
47
device_class_set_props(dc, zynqmp_efuse_props);
48
--
49
2.34.1
diff view generated by jsdifflib
1
From: Leif Lindholm <leif@nuviainc.com>
1
From: Tong Ho <tong.ho@amd.com>
2
2
3
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
3
This change implements the ResettableClass interface for the device.
4
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
4
5
Message-id: 20210108185154.8108-5-leif@nuviainc.com
5
Signed-off-by: Tong Ho <tong.ho@amd.com>
6
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
7
Message-id: 20231004055339.323833-1-tong.ho@amd.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
9
---
8
target/arm/cpu.h | 31 +++++++++++++++++++++++++++++++
10
hw/nvram/xlnx-versal-efuse-ctrl.c | 8 +++++---
9
1 file changed, 31 insertions(+)
11
1 file changed, 5 insertions(+), 3 deletions(-)
10
12
11
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
diff --git a/hw/nvram/xlnx-versal-efuse-ctrl.c b/hw/nvram/xlnx-versal-efuse-ctrl.c
12
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/cpu.h
15
--- a/hw/nvram/xlnx-versal-efuse-ctrl.c
14
+++ b/target/arm/cpu.h
16
+++ b/hw/nvram/xlnx-versal-efuse-ctrl.c
15
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_FPCCR, ASPEN, 31, 1)
17
@@ -XXX,XX +XXX,XX @@
16
/*
18
* QEMU model of the Versal eFuse controller
17
* System register ID fields.
19
*
18
*/
20
* Copyright (c) 2020 Xilinx Inc.
19
+FIELD(CLIDR_EL1, CTYPE1, 0, 3)
21
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
20
+FIELD(CLIDR_EL1, CTYPE2, 3, 3)
22
*
21
+FIELD(CLIDR_EL1, CTYPE3, 6, 3)
23
* Permission is hereby granted, free of charge, to any person obtaining a copy
22
+FIELD(CLIDR_EL1, CTYPE4, 9, 3)
24
* of this software and associated documentation files (the "Software"), to deal
23
+FIELD(CLIDR_EL1, CTYPE5, 12, 3)
25
@@ -XXX,XX +XXX,XX @@ static void efuse_ctrl_register_reset(RegisterInfo *reg)
24
+FIELD(CLIDR_EL1, CTYPE6, 15, 3)
26
register_reset(reg);
25
+FIELD(CLIDR_EL1, CTYPE7, 18, 3)
27
}
26
+FIELD(CLIDR_EL1, LOUIS, 21, 3)
28
27
+FIELD(CLIDR_EL1, LOC, 24, 3)
29
-static void efuse_ctrl_reset(DeviceState *dev)
28
+FIELD(CLIDR_EL1, LOUU, 27, 3)
30
+static void efuse_ctrl_reset_hold(Object *obj)
29
+FIELD(CLIDR_EL1, ICB, 30, 3)
31
{
30
+
32
- XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(dev);
31
+/* When FEAT_CCIDX is implemented */
33
+ XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(obj);
32
+FIELD(CCSIDR_EL1, CCIDX_LINESIZE, 0, 3)
34
unsigned int i;
33
+FIELD(CCSIDR_EL1, CCIDX_ASSOCIATIVITY, 3, 21)
35
34
+FIELD(CCSIDR_EL1, CCIDX_NUMSETS, 32, 24)
36
for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
35
+
37
@@ -XXX,XX +XXX,XX @@ static Property efuse_ctrl_props[] = {
36
+/* When FEAT_CCIDX is not implemented */
38
static void efuse_ctrl_class_init(ObjectClass *klass, void *data)
37
+FIELD(CCSIDR_EL1, LINESIZE, 0, 3)
39
{
38
+FIELD(CCSIDR_EL1, ASSOCIATIVITY, 3, 10)
40
DeviceClass *dc = DEVICE_CLASS(klass);
39
+FIELD(CCSIDR_EL1, NUMSETS, 13, 15)
41
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
40
+
42
41
+FIELD(CTR_EL0, IMINLINE, 0, 4)
43
- dc->reset = efuse_ctrl_reset;
42
+FIELD(CTR_EL0, L1IP, 14, 2)
44
+ rc->phases.hold = efuse_ctrl_reset_hold;
43
+FIELD(CTR_EL0, DMINLINE, 16, 4)
45
dc->realize = efuse_ctrl_realize;
44
+FIELD(CTR_EL0, ERG, 20, 4)
46
dc->vmsd = &vmstate_efuse_ctrl;
45
+FIELD(CTR_EL0, CWG, 24, 4)
47
device_class_set_props(dc, efuse_ctrl_props);
46
+FIELD(CTR_EL0, IDC, 28, 1)
47
+FIELD(CTR_EL0, DIC, 29, 1)
48
+FIELD(CTR_EL0, TMINLINE, 32, 6)
49
+
50
FIELD(MIDR_EL1, REVISION, 0, 4)
51
FIELD(MIDR_EL1, PARTNUM, 4, 12)
52
FIELD(MIDR_EL1, ARCHITECTURE, 16, 4)
53
--
48
--
54
2.20.1
49
2.34.1
55
56
diff view generated by jsdifflib
1
From: Leif Lindholm <leif@nuviainc.com>
1
From: Tong Ho <tong.ho@amd.com>
2
2
3
When FEAT_MTE is implemented, the AArch64 view of CTR_EL0 adds the
3
This replaces the comma (,) to dot (.) in the device type name
4
TminLine field in bits [37:32].
4
so the name can be used with the 'driver=' command line option.
5
Extend the ctr field to be able to hold this context.
6
5
7
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
6
Signed-off-by: Tong Ho <tong.ho@amd.com>
8
Reviewed-by: Hao Wu <wuhaotsh@google.com>
7
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20231003052139.199665-1-tong.ho@amd.com
10
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
11
Message-id: 20210108185154.8108-4-leif@nuviainc.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
10
---
14
target/arm/cpu.h | 2 +-
11
include/hw/nvram/xlnx-bbram.h | 2 +-
15
1 file changed, 1 insertion(+), 1 deletion(-)
12
1 file changed, 1 insertion(+), 1 deletion(-)
16
13
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/include/hw/nvram/xlnx-bbram.h b/include/hw/nvram/xlnx-bbram.h
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
16
--- a/include/hw/nvram/xlnx-bbram.h
20
+++ b/target/arm/cpu.h
17
+++ b/include/hw/nvram/xlnx-bbram.h
21
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
18
@@ -XXX,XX +XXX,XX @@
22
uint64_t midr;
19
23
uint32_t revidr;
20
#define RMAX_XLNX_BBRAM ((0x4c / 4) + 1)
24
uint32_t reset_fpsid;
21
25
- uint32_t ctr;
22
-#define TYPE_XLNX_BBRAM "xlnx,bbram-ctrl"
26
+ uint64_t ctr;
23
+#define TYPE_XLNX_BBRAM "xlnx.bbram-ctrl"
27
uint32_t reset_sctlr;
24
OBJECT_DECLARE_SIMPLE_TYPE(XlnxBBRam, XLNX_BBRAM);
28
uint64_t pmceid0;
25
29
uint64_t pmceid1;
26
struct XlnxBBRam {
30
--
27
--
31
2.20.1
28
2.34.1
32
33
diff view generated by jsdifflib
1
From: Leif Lindholm <leif@nuviainc.com>
1
From: Viktor Prutyanov <viktor@daynix.com>
2
2
3
The AArch64 view of CLIDR_EL1 extends the ICB field to include also bit
3
String sign_rsds isn't terminated, so the print length must be limited.
4
32, as well as adding a Ttype<n> field when FEAT_MTE is implemented.
5
Extend the clidr field to be able to hold this context.
6
4
7
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
5
Fixes: Coverity CID 1521598
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Viktor Prutyanov <viktor@daynix.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
10
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
8
Message-id: 20230930235317.11469-2-viktor@daynix.com
11
Message-id: 20210108185154.8108-3-leif@nuviainc.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
10
---
14
target/arm/cpu.h | 2 +-
11
contrib/elf2dmp/main.c | 2 +-
15
1 file changed, 1 insertion(+), 1 deletion(-)
12
1 file changed, 1 insertion(+), 1 deletion(-)
16
13
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
16
--- a/contrib/elf2dmp/main.c
20
+++ b/target/arm/cpu.h
17
+++ b/contrib/elf2dmp/main.c
21
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
18
@@ -XXX,XX +XXX,XX @@ static bool pe_check_pdb_name(uint64_t base, void *start_addr,
22
uint32_t id_afr0;
19
}
23
uint64_t id_aa64afr0;
20
24
uint64_t id_aa64afr1;
21
if (memcmp(&rsds->Signature, sign_rsds, sizeof(sign_rsds))) {
25
- uint32_t clidr;
22
- eprintf("CodeView signature is \'%.4s\', \'%s\' expected\n",
26
+ uint64_t clidr;
23
+ eprintf("CodeView signature is \'%.4s\', \'%.4s\' expected\n",
27
uint64_t mp_affinity; /* MP ID without feature bits */
24
rsds->Signature, sign_rsds);
28
/* The elements of this array are the CCSIDR values for each cache,
25
return false;
29
* in the order L1DCache, L1ICache, L2DCache, L2ICache, etc.
26
}
30
--
27
--
31
2.20.1
28
2.34.1
32
33
diff view generated by jsdifflib
1
From: Leif Lindholm <leif@nuviainc.com>
1
From: Viktor Prutyanov <viktor@daynix.com>
2
2
3
SBSS -> SSBS
3
Index in file_size array must be checked against num_files, because the
4
entries we are looking for may be absent in the PDB.
4
5
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
6
Fixes: Coverity CID 1521597
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Signed-off-by: Viktor Prutyanov <viktor@daynix.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
8
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Message-id: 20210108185154.8108-2-leif@nuviainc.com
10
Message-id: 20230930235317.11469-3-viktor@daynix.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
target/arm/cpu.h | 2 +-
13
contrib/elf2dmp/pdb.c | 13 +++++++++----
13
1 file changed, 1 insertion(+), 1 deletion(-)
14
1 file changed, 9 insertions(+), 4 deletions(-)
14
15
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
diff --git a/contrib/elf2dmp/pdb.c b/contrib/elf2dmp/pdb.c
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
18
--- a/contrib/elf2dmp/pdb.c
18
+++ b/target/arm/cpu.h
19
+++ b/contrib/elf2dmp/pdb.c
19
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64PFR0, RAS, 28, 4)
20
@@ -XXX,XX +XXX,XX @@
20
FIELD(ID_AA64PFR0, SVE, 32, 4)
21
21
22
static uint32_t pdb_get_file_size(const struct pdb_reader *r, unsigned idx)
22
FIELD(ID_AA64PFR1, BT, 0, 4)
23
{
23
-FIELD(ID_AA64PFR1, SBSS, 4, 4)
24
+ if (idx >= r->ds.toc->num_files) {
24
+FIELD(ID_AA64PFR1, SSBS, 4, 4)
25
+ return 0;
25
FIELD(ID_AA64PFR1, MTE, 8, 4)
26
+ }
26
FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
27
+
27
28
return r->ds.toc->file_size[idx];
29
}
30
31
@@ -XXX,XX +XXX,XX @@ static void *pdb_ds_read_file(struct pdb_reader* r, uint32_t file_number)
32
33
static int pdb_init_segments(struct pdb_reader *r)
34
{
35
- char *segs;
36
unsigned stream_idx = r->segments;
37
38
- segs = pdb_ds_read_file(r, stream_idx);
39
- if (!segs) {
40
+ r->segs = pdb_ds_read_file(r, stream_idx);
41
+ if (!r->segs) {
42
return 1;
43
}
44
45
- r->segs = segs;
46
r->segs_size = pdb_get_file_size(r, stream_idx);
47
+ if (!r->segs_size) {
48
+ return 1;
49
+ }
50
51
return 0;
52
}
28
--
53
--
29
2.20.1
54
2.34.1
30
55
31
56
diff view generated by jsdifflib
1
From: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
1
From: Michal Orzel <michal.orzel@amd.com>
2
2
3
This adds for the Small Translation tables extension in AArch64 state.
3
On an attempt to access CNTPCT_EL0 from EL0 using a guest running on top
4
of Xen, a trap from EL2 was observed which is something not reproducible
5
on HW (also, Xen does not trap accesses to physical counter).
4
6
5
Signed-off-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
7
This is because gt_counter_access() checks for an incorrect bit (1
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
instead of 0) of CNTHCTL_EL2 if HCR_EL2.E2H is 0 and access is made to
9
physical counter. Refer ARM ARM DDI 0487J.a, D19.12.2:
10
When HCR_EL2.E2H is 0:
11
- EL1PCTEN, bit [0]: refers to physical counter
12
- EL1PCEN, bit [1]: refers to physical timer registers
13
14
Drop entire block "if (hcr & HCR_E2H) {...} else {...}" from EL0 case
15
and fall through to EL1 case, given that after fixing checking for the
16
correct bit, the handling is the same.
17
18
Fixes: 5bc8437136fb ("target/arm: Update timer access for VHE")
19
Signed-off-by: Michal Orzel <michal.orzel@amd.com>
20
Tested-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
21
Message-id: 20230928094404.20802-1-michal.orzel@amd.com
22
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
24
---
9
target/arm/cpu.h | 5 +++++
25
target/arm/helper.c | 17 +----------------
10
target/arm/helper.c | 15 +++++++++++++--
26
1 file changed, 1 insertion(+), 16 deletions(-)
11
2 files changed, 18 insertions(+), 2 deletions(-)
12
27
13
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu.h
16
+++ b/target/arm/cpu.h
17
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_uao(const ARMISARegisters *id)
18
return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0;
19
}
20
21
+static inline bool isar_feature_aa64_st(const ARMISARegisters *id)
22
+{
23
+ return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, ST) != 0;
24
+}
25
+
26
static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
27
{
28
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
29
diff --git a/target/arm/helper.c b/target/arm/helper.c
28
diff --git a/target/arm/helper.c b/target/arm/helper.c
30
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/helper.c
30
--- a/target/arm/helper.c
32
+++ b/target/arm/helper.c
31
+++ b/target/arm/helper.c
33
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
32
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_counter_access(CPUARMState *env, int timeridx,
34
{
33
if (!extract32(env->cp15.c14_cntkctl, timeridx, 1)) {
35
uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
34
return CP_ACCESS_TRAP;
36
bool epd, hpd, using16k, using64k;
37
- int select, tsz, tbi;
38
+ int select, tsz, tbi, max_tsz;
39
40
if (!regime_has_2_ranges(mmu_idx)) {
41
select = 0;
42
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
43
hpd = extract64(tcr, 42, 1);
44
}
35
}
45
}
36
-
46
- tsz = MIN(tsz, 39); /* TODO: ARMv8.4-TTST */
37
- /* If HCR_EL2.<E2H,TGE> == '10': check CNTHCTL_EL2.EL1PCTEN. */
47
+
38
- if (hcr & HCR_E2H) {
48
+ if (cpu_isar_feature(aa64_st, env_archcpu(env))) {
39
- if (timeridx == GTIMER_PHYS &&
49
+ max_tsz = 48 - using64k;
40
- !extract32(env->cp15.cnthctl_el2, 10, 1)) {
50
+ } else {
41
- return CP_ACCESS_TRAP_EL2;
51
+ max_tsz = 39;
42
- }
52
+ }
43
- } else {
53
+
44
- /* If HCR_EL2.<E2H> == 0: check CNTHCTL_EL2.EL1PCEN. */
54
+ tsz = MIN(tsz, max_tsz);
45
- if (has_el2 && timeridx == GTIMER_PHYS &&
55
tsz = MAX(tsz, 16); /* TODO: ARMv8.2-LVA */
46
- !extract32(env->cp15.cnthctl_el2, 1, 1)) {
56
47
- return CP_ACCESS_TRAP_EL2;
57
/* Present TBI as a composite with TBID. */
48
- }
58
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
49
- }
59
if (!aarch64 || stride == 9) {
50
- break;
60
/* AArch32 or 4KB pages */
51
-
61
startlevel = 2 - sl0;
52
+ /* fall through */
62
+
53
case 1:
63
+ if (cpu_isar_feature(aa64_st, cpu)) {
54
/* Check CNTHCTL_EL2.EL1PCTEN, which changes location based on E2H. */
64
+ startlevel &= 3;
55
if (has_el2 && timeridx == GTIMER_PHYS &&
65
+ }
66
} else {
67
/* 16KB or 64KB pages */
68
startlevel = 3 - sl0;
69
--
56
--
70
2.20.1
57
2.34.1
71
72
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Leif Lindholm <quic_llindhol@quicinc.com>
2
2
3
The PWM module is part of NPCM7XX module. Each NPCM7XX module has two
3
GIC Private Peripheral Interrupts (PPI) are defined as GIC INTID 16-31.
4
identical PWM modules. Each module contains 4 PWM entries. Each PWM has
4
As in, PPI0 is INTID16 .. PPI15 is INTID31.
5
two outputs: frequency and duty_cycle. Both are computed using inputs
5
Arm's Base System Architecture specification (BSA) lists the mandated and
6
from software side.
6
recommended private interrupt IDs by INTID, not by PPI index. But current
7
definitions in virt define them by PPI index, complicating cross
8
referencing.
7
9
8
This module does not model detail pulse signals since it is expensive.
10
Meanwhile, the PPI(x) macro counterintuitively adds 16 to the input value,
9
It also does not model interrupts and watchdogs that are dependant on
11
converting a PPI index to an INTID.
10
the detail models. The interfaces for these are left in the module so
11
that anyone in need for these functionalities can implement on their
12
own.
13
12
14
The user can read the duty cycle and frequency using qom-get command.
13
Resolve this by redefining the BSA-allocated PPIs by their INTIDs,
14
and replacing the PPI(x) macro with an INTID_TO_PPI(x) one where required.
15
15
16
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
16
Signed-off-by: Leif Lindholm <quic_llindhol@quicinc.com>
17
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
17
Message-id: 20230919090229.188092-2-quic_llindhol@quicinc.com
18
Signed-off-by: Hao Wu <wuhaotsh@google.com>
19
Message-id: 20210108190945.949196-5-wuhaotsh@google.com
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
20
---
23
docs/system/arm/nuvoton.rst | 2 +-
21
include/hw/arm/virt.h | 14 +++++++-------
24
include/hw/arm/npcm7xx.h | 2 +
22
hw/arm/virt-acpi-build.c | 12 ++++++------
25
include/hw/misc/npcm7xx_pwm.h | 105 +++++++
23
hw/arm/virt.c | 24 ++++++++++++++----------
26
hw/arm/npcm7xx.c | 26 +-
24
3 files changed, 27 insertions(+), 23 deletions(-)
27
hw/misc/npcm7xx_pwm.c | 550 ++++++++++++++++++++++++++++++++++
28
hw/misc/meson.build | 1 +
29
hw/misc/trace-events | 6 +
30
7 files changed, 689 insertions(+), 3 deletions(-)
31
create mode 100644 include/hw/misc/npcm7xx_pwm.h
32
create mode 100644 hw/misc/npcm7xx_pwm.c
33
25
34
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
26
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
35
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
36
--- a/docs/system/arm/nuvoton.rst
28
--- a/include/hw/arm/virt.h
37
+++ b/docs/system/arm/nuvoton.rst
29
+++ b/include/hw/arm/virt.h
38
@@ -XXX,XX +XXX,XX @@ Supported devices
30
@@ -XXX,XX +XXX,XX @@
39
* USB host (USBH)
31
#define NUM_VIRTIO_TRANSPORTS 32
40
* GPIO controller
32
#define NUM_SMMU_IRQS 4
41
* Analog to Digital Converter (ADC)
33
42
+ * Pulse Width Modulation (PWM)
34
-#define ARCH_GIC_MAINT_IRQ 9
43
35
+#define ARCH_GIC_MAINT_IRQ 25
44
Missing devices
36
45
---------------
37
-#define ARCH_TIMER_VIRT_IRQ 11
46
@@ -XXX,XX +XXX,XX @@ Missing devices
38
-#define ARCH_TIMER_S_EL1_IRQ 13
47
* Peripheral SPI controller (PSPI)
39
-#define ARCH_TIMER_NS_EL1_IRQ 14
48
* SD/MMC host
40
-#define ARCH_TIMER_NS_EL2_IRQ 10
49
* PECI interface
41
+#define ARCH_TIMER_VIRT_IRQ 27
50
- * Pulse Width Modulation (PWM)
42
+#define ARCH_TIMER_S_EL1_IRQ 29
51
* Tachometer
43
+#define ARCH_TIMER_NS_EL1_IRQ 30
52
* PCI and PCIe root complex and bridges
44
+#define ARCH_TIMER_NS_EL2_IRQ 26
53
* VDM and MCTP support
45
54
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
46
-#define VIRTUAL_PMU_IRQ 7
47
+#define VIRTUAL_PMU_IRQ 23
48
49
-#define PPI(irq) ((irq) + 16)
50
+#define INTID_TO_PPI(irq) ((irq) - 16)
51
52
/* See Linux kernel arch/arm64/include/asm/pvclock-abi.h */
53
#define PVTIME_SIZE_PER_CPU 64
54
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
55
index XXXXXXX..XXXXXXX 100644
55
index XXXXXXX..XXXXXXX 100644
56
--- a/include/hw/arm/npcm7xx.h
56
--- a/hw/arm/virt-acpi-build.c
57
+++ b/include/hw/arm/npcm7xx.h
57
+++ b/hw/arm/virt-acpi-build.c
58
@@ -XXX,XX +XXX,XX @@
58
@@ -XXX,XX +XXX,XX @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
59
#include "hw/mem/npcm7xx_mc.h"
59
* The interrupt values are the same with the device tree when adding 16
60
#include "hw/misc/npcm7xx_clk.h"
60
*/
61
#include "hw/misc/npcm7xx_gcr.h"
61
/* Secure EL1 timer GSIV */
62
+#include "hw/misc/npcm7xx_pwm.h"
62
- build_append_int_noprefix(table_data, ARCH_TIMER_S_EL1_IRQ + 16, 4);
63
#include "hw/misc/npcm7xx_rng.h"
63
+ build_append_int_noprefix(table_data, ARCH_TIMER_S_EL1_IRQ, 4);
64
#include "hw/nvram/npcm7xx_otp.h"
64
/* Secure EL1 timer Flags */
65
#include "hw/timer/npcm7xx_timer.h"
65
build_append_int_noprefix(table_data, irqflags, 4);
66
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
66
/* Non-Secure EL1 timer GSIV */
67
NPCM7xxCLKState clk;
67
- build_append_int_noprefix(table_data, ARCH_TIMER_NS_EL1_IRQ + 16, 4);
68
NPCM7xxTimerCtrlState tim[3];
68
+ build_append_int_noprefix(table_data, ARCH_TIMER_NS_EL1_IRQ, 4);
69
NPCM7xxADCState adc;
69
/* Non-Secure EL1 timer Flags */
70
+ NPCM7xxPWMState pwm[2];
70
build_append_int_noprefix(table_data, irqflags |
71
NPCM7xxOTPState key_storage;
71
1UL << 2, /* Always-on Capability */
72
NPCM7xxOTPState fuse_array;
72
4);
73
NPCM7xxMCState mc;
73
/* Virtual timer GSIV */
74
diff --git a/include/hw/misc/npcm7xx_pwm.h b/include/hw/misc/npcm7xx_pwm.h
74
- build_append_int_noprefix(table_data, ARCH_TIMER_VIRT_IRQ + 16, 4);
75
new file mode 100644
75
+ build_append_int_noprefix(table_data, ARCH_TIMER_VIRT_IRQ, 4);
76
index XXXXXXX..XXXXXXX
76
/* Virtual Timer Flags */
77
--- /dev/null
77
build_append_int_noprefix(table_data, irqflags, 4);
78
+++ b/include/hw/misc/npcm7xx_pwm.h
78
/* Non-Secure EL2 timer GSIV */
79
@@ -XXX,XX +XXX,XX @@
79
- build_append_int_noprefix(table_data, ARCH_TIMER_NS_EL2_IRQ + 16, 4);
80
+/*
80
+ build_append_int_noprefix(table_data, ARCH_TIMER_NS_EL2_IRQ, 4);
81
+ * Nuvoton NPCM7xx PWM Module
81
/* Non-Secure EL2 timer Flags */
82
+ *
82
build_append_int_noprefix(table_data, irqflags, 4);
83
+ * Copyright 2020 Google LLC
83
/* CntReadBase Physical address */
84
+ *
84
@@ -XXX,XX +XXX,XX @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
85
+ * This program is free software; you can redistribute it and/or modify it
85
for (i = 0; i < MACHINE(vms)->smp.cpus; i++) {
86
+ * under the terms of the GNU General Public License as published by the
86
ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i));
87
+ * Free Software Foundation; either version 2 of the License, or
87
uint64_t physical_base_address = 0, gich = 0, gicv = 0;
88
+ * (at your option) any later version.
88
- uint32_t vgic_interrupt = vms->virt ? PPI(ARCH_GIC_MAINT_IRQ) : 0;
89
+ *
89
+ uint32_t vgic_interrupt = vms->virt ? ARCH_GIC_MAINT_IRQ : 0;
90
+ * This program is distributed in the hope that it will be useful, but WITHOUT
90
uint32_t pmu_interrupt = arm_feature(&armcpu->env, ARM_FEATURE_PMU) ?
91
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
91
- PPI(VIRTUAL_PMU_IRQ) : 0;
92
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
92
+ VIRTUAL_PMU_IRQ : 0;
93
+ * for more details.
93
94
+ */
94
if (vms->gic_version == VIRT_GIC_VERSION_2) {
95
+#ifndef NPCM7XX_PWM_H
95
physical_base_address = memmap[VIRT_GIC_CPU].base;
96
+#define NPCM7XX_PWM_H
96
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
97
+
98
+#include "hw/clock.h"
99
+#include "hw/sysbus.h"
100
+#include "hw/irq.h"
101
+
102
+/* Each PWM module holds 4 PWM channels. */
103
+#define NPCM7XX_PWM_PER_MODULE 4
104
+
105
+/*
106
+ * Number of registers in one pwm module. Don't change this without increasing
107
+ * the version_id in vmstate.
108
+ */
109
+#define NPCM7XX_PWM_NR_REGS (0x54 / sizeof(uint32_t))
110
+
111
+/*
112
+ * The maximum duty values. Each duty unit represents 1/NPCM7XX_PWM_MAX_DUTY
113
+ * cycles. For example, if NPCM7XX_PWM_MAX_DUTY=1,000,000 and a PWM has a duty
114
+ * value of 100,000 the duty cycle for that PWM is 10%.
115
+ */
116
+#define NPCM7XX_PWM_MAX_DUTY 1000000
117
+
118
+typedef struct NPCM7xxPWMState NPCM7xxPWMState;
119
+
120
+/**
121
+ * struct NPCM7xxPWM - The state of a single PWM channel.
122
+ * @module: The PWM module that contains this channel.
123
+ * @irq: GIC interrupt line to fire on expiration if enabled.
124
+ * @running: Whether this PWM channel is generating output.
125
+ * @inverted: Whether this PWM channel is inverted.
126
+ * @index: The index of this PWM channel.
127
+ * @cnr: The counter register.
128
+ * @cmr: The comparator register.
129
+ * @pdr: The data register.
130
+ * @pwdr: The watchdog register.
131
+ * @freq: The frequency of this PWM channel.
132
+ * @duty: The duty cycle of this PWM channel. One unit represents
133
+ * 1/NPCM7XX_MAX_DUTY cycles.
134
+ */
135
+typedef struct NPCM7xxPWM {
136
+ NPCM7xxPWMState *module;
137
+
138
+ qemu_irq irq;
139
+
140
+ bool running;
141
+ bool inverted;
142
+
143
+ uint8_t index;
144
+ uint32_t cnr;
145
+ uint32_t cmr;
146
+ uint32_t pdr;
147
+ uint32_t pwdr;
148
+
149
+ uint32_t freq;
150
+ uint32_t duty;
151
+} NPCM7xxPWM;
152
+
153
+/**
154
+ * struct NPCM7xxPWMState - Pulse Width Modulation device state.
155
+ * @parent: System bus device.
156
+ * @iomem: Memory region through which registers are accessed.
157
+ * @clock: The PWM clock.
158
+ * @pwm: The PWM channels owned by this module.
159
+ * @ppr: The prescaler register.
160
+ * @csr: The clock selector register.
161
+ * @pcr: The control register.
162
+ * @pier: The interrupt enable register.
163
+ * @piir: The interrupt indication register.
164
+ */
165
+struct NPCM7xxPWMState {
166
+ SysBusDevice parent;
167
+
168
+ MemoryRegion iomem;
169
+
170
+ Clock *clock;
171
+ NPCM7xxPWM pwm[NPCM7XX_PWM_PER_MODULE];
172
+
173
+ uint32_t ppr;
174
+ uint32_t csr;
175
+ uint32_t pcr;
176
+ uint32_t pier;
177
+ uint32_t piir;
178
+};
179
+
180
+#define TYPE_NPCM7XX_PWM "npcm7xx-pwm"
181
+#define NPCM7XX_PWM(obj) \
182
+ OBJECT_CHECK(NPCM7xxPWMState, (obj), TYPE_NPCM7XX_PWM)
183
+
184
+#endif /* NPCM7XX_PWM_H */
185
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
186
index XXXXXXX..XXXXXXX 100644
97
index XXXXXXX..XXXXXXX 100644
187
--- a/hw/arm/npcm7xx.c
98
--- a/hw/arm/virt.c
188
+++ b/hw/arm/npcm7xx.c
99
+++ b/hw/arm/virt.c
189
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
100
@@ -XXX,XX +XXX,XX @@ static void fdt_add_timer_nodes(const VirtMachineState *vms)
190
NPCM7XX_WDG2_IRQ, /* Timer Module 2 Watchdog */
191
NPCM7XX_EHCI_IRQ = 61,
192
NPCM7XX_OHCI_IRQ = 62,
193
+ NPCM7XX_PWM0_IRQ = 93, /* PWM module 0 */
194
+ NPCM7XX_PWM1_IRQ, /* PWM module 1 */
195
NPCM7XX_GPIO0_IRQ = 116,
196
NPCM7XX_GPIO1_IRQ,
197
NPCM7XX_GPIO2_IRQ,
198
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_fiu3_flash_addr[] = {
199
0xb8000000, /* CS3 */
200
};
201
202
+/* Register base address for each PWM Module */
203
+static const hwaddr npcm7xx_pwm_addr[] = {
204
+ 0xf0103000,
205
+ 0xf0104000,
206
+};
207
+
208
static const struct {
209
hwaddr regs_addr;
210
uint32_t unconnected_pins;
211
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
212
object_initialize_child(obj, npcm7xx_fiu[i].name, &s->fiu[i],
213
TYPE_NPCM7XX_FIU);
214
}
101
}
215
+
102
qemu_fdt_setprop(ms->fdt, "/timer", "always-on", NULL, 0);
216
+ for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
103
qemu_fdt_setprop_cells(ms->fdt, "/timer", "interrupts",
217
+ object_initialize_child(obj, "pwm[*]", &s->pwm[i], TYPE_NPCM7XX_PWM);
104
- GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_S_EL1_IRQ, irqflags,
218
+ }
105
- GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL1_IRQ, irqflags,
106
- GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_VIRT_IRQ, irqflags,
107
- GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL2_IRQ, irqflags);
108
+ GIC_FDT_IRQ_TYPE_PPI,
109
+ INTID_TO_PPI(ARCH_TIMER_S_EL1_IRQ), irqflags,
110
+ GIC_FDT_IRQ_TYPE_PPI,
111
+ INTID_TO_PPI(ARCH_TIMER_NS_EL1_IRQ), irqflags,
112
+ GIC_FDT_IRQ_TYPE_PPI,
113
+ INTID_TO_PPI(ARCH_TIMER_VIRT_IRQ), irqflags,
114
+ GIC_FDT_IRQ_TYPE_PPI,
115
+ INTID_TO_PPI(ARCH_TIMER_NS_EL2_IRQ), irqflags);
219
}
116
}
220
117
221
static void npcm7xx_realize(DeviceState *dev, Error **errp)
118
static void fdt_add_cpu_nodes(const VirtMachineState *vms)
222
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
119
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
223
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ohci), 0,
120
*/
224
npcm7xx_irq(s, NPCM7XX_OHCI_IRQ));
121
for (i = 0; i < smp_cpus; i++) {
225
122
DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
226
+ /* PWM Modules. Cannot fail. */
123
- int ppibase = NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
227
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_pwm_addr) != ARRAY_SIZE(s->pwm));
124
+ int intidbase = NUM_IRQS + i * GIC_INTERNAL;
228
+ for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
125
/* Mapping from the output timer irq lines from the CPU to the
229
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->pwm[i]);
126
* GIC PPI inputs we use for the virt board.
230
+
127
*/
231
+ qdev_connect_clock_in(DEVICE(&s->pwm[i]), "clock", qdev_get_clock_out(
128
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
232
+ DEVICE(&s->clk), "apb3-clock"));
129
for (unsigned irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
233
+ sysbus_realize(sbd, &error_abort);
130
qdev_connect_gpio_out(cpudev, irq,
234
+ sysbus_mmio_map(sbd, 0, npcm7xx_pwm_addr[i]);
131
qdev_get_gpio_in(vms->gic,
235
+ sysbus_connect_irq(sbd, i, npcm7xx_irq(s, NPCM7XX_PWM0_IRQ + i));
132
- ppibase + timer_irq[irq]));
236
+ }
133
+ intidbase + timer_irq[irq]));
237
+
134
}
238
/*
135
239
* Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
136
if (vms->gic_version != VIRT_GIC_VERSION_2) {
240
* specified, but this is a programming error.
137
qemu_irq irq = qdev_get_gpio_in(vms->gic,
241
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
138
- ppibase + ARCH_GIC_MAINT_IRQ);
242
create_unimplemented_device("npcm7xx.peci", 0xf0100000, 4 * KiB);
139
+ intidbase + ARCH_GIC_MAINT_IRQ);
243
create_unimplemented_device("npcm7xx.siox[1]", 0xf0101000, 4 * KiB);
140
qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
244
create_unimplemented_device("npcm7xx.siox[2]", 0xf0102000, 4 * KiB);
141
0, irq);
245
- create_unimplemented_device("npcm7xx.pwm[0]", 0xf0103000, 4 * KiB);
142
} else if (vms->virt) {
246
- create_unimplemented_device("npcm7xx.pwm[1]", 0xf0104000, 4 * KiB);
143
qemu_irq irq = qdev_get_gpio_in(vms->gic,
247
create_unimplemented_device("npcm7xx.mft[0]", 0xf0180000, 4 * KiB);
144
- ppibase + ARCH_GIC_MAINT_IRQ);
248
create_unimplemented_device("npcm7xx.mft[1]", 0xf0181000, 4 * KiB);
145
+ intidbase + ARCH_GIC_MAINT_IRQ);
249
create_unimplemented_device("npcm7xx.mft[2]", 0xf0182000, 4 * KiB);
146
sysbus_connect_irq(gicbusdev, i + 4 * smp_cpus, irq);
250
diff --git a/hw/misc/npcm7xx_pwm.c b/hw/misc/npcm7xx_pwm.c
147
}
251
new file mode 100644
148
252
index XXXXXXX..XXXXXXX
149
qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
253
--- /dev/null
150
- qdev_get_gpio_in(vms->gic, ppibase
254
+++ b/hw/misc/npcm7xx_pwm.c
151
+ qdev_get_gpio_in(vms->gic, intidbase
255
@@ -XXX,XX +XXX,XX @@
152
+ VIRTUAL_PMU_IRQ));
256
+/*
153
257
+ * Nuvoton NPCM7xx PWM Module
154
sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
258
+ *
155
@@ -XXX,XX +XXX,XX @@ static void virt_cpu_post_init(VirtMachineState *vms, MemoryRegion *sysmem)
259
+ * Copyright 2020 Google LLC
156
if (pmu) {
260
+ *
157
assert(arm_feature(&ARM_CPU(cpu)->env, ARM_FEATURE_PMU));
261
+ * This program is free software; you can redistribute it and/or modify it
158
if (kvm_irqchip_in_kernel()) {
262
+ * under the terms of the GNU General Public License as published by the
159
- kvm_arm_pmu_set_irq(cpu, PPI(VIRTUAL_PMU_IRQ));
263
+ * Free Software Foundation; either version 2 of the License, or
160
+ kvm_arm_pmu_set_irq(cpu, VIRTUAL_PMU_IRQ);
264
+ * (at your option) any later version.
161
}
265
+ *
162
kvm_arm_pmu_init(cpu);
266
+ * This program is distributed in the hope that it will be useful, but WITHOUT
163
}
267
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
268
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
269
+ * for more details.
270
+ */
271
+
272
+#include "qemu/osdep.h"
273
+#include "hw/irq.h"
274
+#include "hw/qdev-clock.h"
275
+#include "hw/qdev-properties.h"
276
+#include "hw/misc/npcm7xx_pwm.h"
277
+#include "hw/registerfields.h"
278
+#include "migration/vmstate.h"
279
+#include "qemu/bitops.h"
280
+#include "qemu/error-report.h"
281
+#include "qemu/log.h"
282
+#include "qemu/module.h"
283
+#include "qemu/units.h"
284
+#include "trace.h"
285
+
286
+REG32(NPCM7XX_PWM_PPR, 0x00);
287
+REG32(NPCM7XX_PWM_CSR, 0x04);
288
+REG32(NPCM7XX_PWM_PCR, 0x08);
289
+REG32(NPCM7XX_PWM_CNR0, 0x0c);
290
+REG32(NPCM7XX_PWM_CMR0, 0x10);
291
+REG32(NPCM7XX_PWM_PDR0, 0x14);
292
+REG32(NPCM7XX_PWM_CNR1, 0x18);
293
+REG32(NPCM7XX_PWM_CMR1, 0x1c);
294
+REG32(NPCM7XX_PWM_PDR1, 0x20);
295
+REG32(NPCM7XX_PWM_CNR2, 0x24);
296
+REG32(NPCM7XX_PWM_CMR2, 0x28);
297
+REG32(NPCM7XX_PWM_PDR2, 0x2c);
298
+REG32(NPCM7XX_PWM_CNR3, 0x30);
299
+REG32(NPCM7XX_PWM_CMR3, 0x34);
300
+REG32(NPCM7XX_PWM_PDR3, 0x38);
301
+REG32(NPCM7XX_PWM_PIER, 0x3c);
302
+REG32(NPCM7XX_PWM_PIIR, 0x40);
303
+REG32(NPCM7XX_PWM_PWDR0, 0x44);
304
+REG32(NPCM7XX_PWM_PWDR1, 0x48);
305
+REG32(NPCM7XX_PWM_PWDR2, 0x4c);
306
+REG32(NPCM7XX_PWM_PWDR3, 0x50);
307
+
308
+/* Register field definitions. */
309
+#define NPCM7XX_PPR(rv, index) extract32((rv), npcm7xx_ppr_base[index], 8)
310
+#define NPCM7XX_CSR(rv, index) extract32((rv), npcm7xx_csr_base[index], 3)
311
+#define NPCM7XX_CH(rv, index) extract32((rv), npcm7xx_ch_base[index], 4)
312
+#define NPCM7XX_CH_EN BIT(0)
313
+#define NPCM7XX_CH_INV BIT(2)
314
+#define NPCM7XX_CH_MOD BIT(3)
315
+
316
+/* Offset of each PWM channel's prescaler in the PPR register. */
317
+static const int npcm7xx_ppr_base[] = { 0, 0, 8, 8 };
318
+/* Offset of each PWM channel's clock selector in the CSR register. */
319
+static const int npcm7xx_csr_base[] = { 0, 4, 8, 12 };
320
+/* Offset of each PWM channel's control variable in the PCR register. */
321
+static const int npcm7xx_ch_base[] = { 0, 8, 12, 16 };
322
+
323
+static uint32_t npcm7xx_pwm_calculate_freq(NPCM7xxPWM *p)
324
+{
325
+ uint32_t ppr;
326
+ uint32_t csr;
327
+ uint32_t freq;
328
+
329
+ if (!p->running) {
330
+ return 0;
331
+ }
332
+
333
+ csr = NPCM7XX_CSR(p->module->csr, p->index);
334
+ ppr = NPCM7XX_PPR(p->module->ppr, p->index);
335
+ freq = clock_get_hz(p->module->clock);
336
+ freq /= ppr + 1;
337
+ /* csr can only be 0~4 */
338
+ if (csr > 4) {
339
+ qemu_log_mask(LOG_GUEST_ERROR,
340
+ "%s: invalid csr value %u\n",
341
+ __func__, csr);
342
+ csr = 4;
343
+ }
344
+ /* freq won't be changed if csr == 4. */
345
+ if (csr < 4) {
346
+ freq >>= csr + 1;
347
+ }
348
+
349
+ return freq / (p->cnr + 1);
350
+}
351
+
352
+static uint32_t npcm7xx_pwm_calculate_duty(NPCM7xxPWM *p)
353
+{
354
+ uint64_t duty;
355
+
356
+ if (p->running) {
357
+ if (p->cnr == 0) {
358
+ duty = 0;
359
+ } else if (p->cmr >= p->cnr) {
360
+ duty = NPCM7XX_PWM_MAX_DUTY;
361
+ } else {
362
+ duty = NPCM7XX_PWM_MAX_DUTY * (p->cmr + 1) / (p->cnr + 1);
363
+ }
364
+ } else {
365
+ duty = 0;
366
+ }
367
+
368
+ if (p->inverted) {
369
+ duty = NPCM7XX_PWM_MAX_DUTY - duty;
370
+ }
371
+
372
+ return duty;
373
+}
374
+
375
+static void npcm7xx_pwm_update_freq(NPCM7xxPWM *p)
376
+{
377
+ uint32_t freq = npcm7xx_pwm_calculate_freq(p);
378
+
379
+ if (freq != p->freq) {
380
+ trace_npcm7xx_pwm_update_freq(DEVICE(p->module)->canonical_path,
381
+ p->index, p->freq, freq);
382
+ p->freq = freq;
383
+ }
384
+}
385
+
386
+static void npcm7xx_pwm_update_duty(NPCM7xxPWM *p)
387
+{
388
+ uint32_t duty = npcm7xx_pwm_calculate_duty(p);
389
+
390
+ if (duty != p->duty) {
391
+ trace_npcm7xx_pwm_update_duty(DEVICE(p->module)->canonical_path,
392
+ p->index, p->duty, duty);
393
+ p->duty = duty;
394
+ }
395
+}
396
+
397
+static void npcm7xx_pwm_update_output(NPCM7xxPWM *p)
398
+{
399
+ npcm7xx_pwm_update_freq(p);
400
+ npcm7xx_pwm_update_duty(p);
401
+}
402
+
403
+static void npcm7xx_pwm_write_ppr(NPCM7xxPWMState *s, uint32_t new_ppr)
404
+{
405
+ int i;
406
+ uint32_t old_ppr = s->ppr;
407
+
408
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_ppr_base) != NPCM7XX_PWM_PER_MODULE);
409
+ s->ppr = new_ppr;
410
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
411
+ if (NPCM7XX_PPR(old_ppr, i) != NPCM7XX_PPR(new_ppr, i)) {
412
+ npcm7xx_pwm_update_freq(&s->pwm[i]);
413
+ }
414
+ }
415
+}
416
+
417
+static void npcm7xx_pwm_write_csr(NPCM7xxPWMState *s, uint32_t new_csr)
418
+{
419
+ int i;
420
+ uint32_t old_csr = s->csr;
421
+
422
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_csr_base) != NPCM7XX_PWM_PER_MODULE);
423
+ s->csr = new_csr;
424
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
425
+ if (NPCM7XX_CSR(old_csr, i) != NPCM7XX_CSR(new_csr, i)) {
426
+ npcm7xx_pwm_update_freq(&s->pwm[i]);
427
+ }
428
+ }
429
+}
430
+
431
+static void npcm7xx_pwm_write_pcr(NPCM7xxPWMState *s, uint32_t new_pcr)
432
+{
433
+ int i;
434
+ bool inverted;
435
+ uint32_t pcr;
436
+ NPCM7xxPWM *p;
437
+
438
+ s->pcr = new_pcr;
439
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_ch_base) != NPCM7XX_PWM_PER_MODULE);
440
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
441
+ p = &s->pwm[i];
442
+ pcr = NPCM7XX_CH(new_pcr, i);
443
+ inverted = pcr & NPCM7XX_CH_INV;
444
+
445
+ /*
446
+ * We only run a PWM channel with toggle mode. Single-shot mode does not
447
+ * generate frequency and duty-cycle values.
448
+ */
449
+ if ((pcr & NPCM7XX_CH_EN) && (pcr & NPCM7XX_CH_MOD)) {
450
+ if (p->running) {
451
+ /* Re-run this PWM channel if inverted changed. */
452
+ if (p->inverted ^ inverted) {
453
+ p->inverted = inverted;
454
+ npcm7xx_pwm_update_duty(p);
455
+ }
456
+ } else {
457
+ /* Run this PWM channel. */
458
+ p->running = true;
459
+ p->inverted = inverted;
460
+ npcm7xx_pwm_update_output(p);
461
+ }
462
+ } else {
463
+ /* Clear this PWM channel. */
464
+ p->running = false;
465
+ p->inverted = inverted;
466
+ npcm7xx_pwm_update_output(p);
467
+ }
468
+ }
469
+
470
+}
471
+
472
+static hwaddr npcm7xx_cnr_index(hwaddr offset)
473
+{
474
+ switch (offset) {
475
+ case A_NPCM7XX_PWM_CNR0:
476
+ return 0;
477
+ case A_NPCM7XX_PWM_CNR1:
478
+ return 1;
479
+ case A_NPCM7XX_PWM_CNR2:
480
+ return 2;
481
+ case A_NPCM7XX_PWM_CNR3:
482
+ return 3;
483
+ default:
484
+ g_assert_not_reached();
485
+ }
486
+}
487
+
488
+static hwaddr npcm7xx_cmr_index(hwaddr offset)
489
+{
490
+ switch (offset) {
491
+ case A_NPCM7XX_PWM_CMR0:
492
+ return 0;
493
+ case A_NPCM7XX_PWM_CMR1:
494
+ return 1;
495
+ case A_NPCM7XX_PWM_CMR2:
496
+ return 2;
497
+ case A_NPCM7XX_PWM_CMR3:
498
+ return 3;
499
+ default:
500
+ g_assert_not_reached();
501
+ }
502
+}
503
+
504
+static hwaddr npcm7xx_pdr_index(hwaddr offset)
505
+{
506
+ switch (offset) {
507
+ case A_NPCM7XX_PWM_PDR0:
508
+ return 0;
509
+ case A_NPCM7XX_PWM_PDR1:
510
+ return 1;
511
+ case A_NPCM7XX_PWM_PDR2:
512
+ return 2;
513
+ case A_NPCM7XX_PWM_PDR3:
514
+ return 3;
515
+ default:
516
+ g_assert_not_reached();
517
+ }
518
+}
519
+
520
+static hwaddr npcm7xx_pwdr_index(hwaddr offset)
521
+{
522
+ switch (offset) {
523
+ case A_NPCM7XX_PWM_PWDR0:
524
+ return 0;
525
+ case A_NPCM7XX_PWM_PWDR1:
526
+ return 1;
527
+ case A_NPCM7XX_PWM_PWDR2:
528
+ return 2;
529
+ case A_NPCM7XX_PWM_PWDR3:
530
+ return 3;
531
+ default:
532
+ g_assert_not_reached();
533
+ }
534
+}
535
+
536
+static uint64_t npcm7xx_pwm_read(void *opaque, hwaddr offset, unsigned size)
537
+{
538
+ NPCM7xxPWMState *s = opaque;
539
+ uint64_t value = 0;
540
+
541
+ switch (offset) {
542
+ case A_NPCM7XX_PWM_CNR0:
543
+ case A_NPCM7XX_PWM_CNR1:
544
+ case A_NPCM7XX_PWM_CNR2:
545
+ case A_NPCM7XX_PWM_CNR3:
546
+ value = s->pwm[npcm7xx_cnr_index(offset)].cnr;
547
+ break;
548
+
549
+ case A_NPCM7XX_PWM_CMR0:
550
+ case A_NPCM7XX_PWM_CMR1:
551
+ case A_NPCM7XX_PWM_CMR2:
552
+ case A_NPCM7XX_PWM_CMR3:
553
+ value = s->pwm[npcm7xx_cmr_index(offset)].cmr;
554
+ break;
555
+
556
+ case A_NPCM7XX_PWM_PDR0:
557
+ case A_NPCM7XX_PWM_PDR1:
558
+ case A_NPCM7XX_PWM_PDR2:
559
+ case A_NPCM7XX_PWM_PDR3:
560
+ value = s->pwm[npcm7xx_pdr_index(offset)].pdr;
561
+ break;
562
+
563
+ case A_NPCM7XX_PWM_PWDR0:
564
+ case A_NPCM7XX_PWM_PWDR1:
565
+ case A_NPCM7XX_PWM_PWDR2:
566
+ case A_NPCM7XX_PWM_PWDR3:
567
+ value = s->pwm[npcm7xx_pwdr_index(offset)].pwdr;
568
+ break;
569
+
570
+ case A_NPCM7XX_PWM_PPR:
571
+ value = s->ppr;
572
+ break;
573
+
574
+ case A_NPCM7XX_PWM_CSR:
575
+ value = s->csr;
576
+ break;
577
+
578
+ case A_NPCM7XX_PWM_PCR:
579
+ value = s->pcr;
580
+ break;
581
+
582
+ case A_NPCM7XX_PWM_PIER:
583
+ value = s->pier;
584
+ break;
585
+
586
+ case A_NPCM7XX_PWM_PIIR:
587
+ value = s->piir;
588
+ break;
589
+
590
+ default:
591
+ qemu_log_mask(LOG_GUEST_ERROR,
592
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
593
+ __func__, offset);
594
+ break;
595
+ }
596
+
597
+ trace_npcm7xx_pwm_read(DEVICE(s)->canonical_path, offset, value);
598
+ return value;
599
+}
600
+
601
+static void npcm7xx_pwm_write(void *opaque, hwaddr offset,
602
+ uint64_t v, unsigned size)
603
+{
604
+ NPCM7xxPWMState *s = opaque;
605
+ NPCM7xxPWM *p;
606
+ uint32_t value = v;
607
+
608
+ trace_npcm7xx_pwm_write(DEVICE(s)->canonical_path, offset, value);
609
+ switch (offset) {
610
+ case A_NPCM7XX_PWM_CNR0:
611
+ case A_NPCM7XX_PWM_CNR1:
612
+ case A_NPCM7XX_PWM_CNR2:
613
+ case A_NPCM7XX_PWM_CNR3:
614
+ p = &s->pwm[npcm7xx_cnr_index(offset)];
615
+ p->cnr = value;
616
+ npcm7xx_pwm_update_output(p);
617
+ break;
618
+
619
+ case A_NPCM7XX_PWM_CMR0:
620
+ case A_NPCM7XX_PWM_CMR1:
621
+ case A_NPCM7XX_PWM_CMR2:
622
+ case A_NPCM7XX_PWM_CMR3:
623
+ p = &s->pwm[npcm7xx_cmr_index(offset)];
624
+ p->cmr = value;
625
+ npcm7xx_pwm_update_output(p);
626
+ break;
627
+
628
+ case A_NPCM7XX_PWM_PDR0:
629
+ case A_NPCM7XX_PWM_PDR1:
630
+ case A_NPCM7XX_PWM_PDR2:
631
+ case A_NPCM7XX_PWM_PDR3:
632
+ qemu_log_mask(LOG_GUEST_ERROR,
633
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
634
+ __func__, offset);
635
+ break;
636
+
637
+ case A_NPCM7XX_PWM_PWDR0:
638
+ case A_NPCM7XX_PWM_PWDR1:
639
+ case A_NPCM7XX_PWM_PWDR2:
640
+ case A_NPCM7XX_PWM_PWDR3:
641
+ qemu_log_mask(LOG_UNIMP,
642
+ "%s: register @ 0x%04" HWADDR_PRIx " is not implemented\n",
643
+ __func__, offset);
644
+ break;
645
+
646
+ case A_NPCM7XX_PWM_PPR:
647
+ npcm7xx_pwm_write_ppr(s, value);
648
+ break;
649
+
650
+ case A_NPCM7XX_PWM_CSR:
651
+ npcm7xx_pwm_write_csr(s, value);
652
+ break;
653
+
654
+ case A_NPCM7XX_PWM_PCR:
655
+ npcm7xx_pwm_write_pcr(s, value);
656
+ break;
657
+
658
+ case A_NPCM7XX_PWM_PIER:
659
+ qemu_log_mask(LOG_UNIMP,
660
+ "%s: register @ 0x%04" HWADDR_PRIx " is not implemented\n",
661
+ __func__, offset);
662
+ break;
663
+
664
+ case A_NPCM7XX_PWM_PIIR:
665
+ qemu_log_mask(LOG_UNIMP,
666
+ "%s: register @ 0x%04" HWADDR_PRIx " is not implemented\n",
667
+ __func__, offset);
668
+ break;
669
+
670
+ default:
671
+ qemu_log_mask(LOG_GUEST_ERROR,
672
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
673
+ __func__, offset);
674
+ break;
675
+ }
676
+}
677
+
678
+static const struct MemoryRegionOps npcm7xx_pwm_ops = {
679
+ .read = npcm7xx_pwm_read,
680
+ .write = npcm7xx_pwm_write,
681
+ .endianness = DEVICE_LITTLE_ENDIAN,
682
+ .valid = {
683
+ .min_access_size = 4,
684
+ .max_access_size = 4,
685
+ .unaligned = false,
686
+ },
687
+};
688
+
689
+static void npcm7xx_pwm_enter_reset(Object *obj, ResetType type)
690
+{
691
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
692
+ int i;
693
+
694
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
695
+ NPCM7xxPWM *p = &s->pwm[i];
696
+
697
+ p->cnr = 0x00000000;
698
+ p->cmr = 0x00000000;
699
+ p->pdr = 0x00000000;
700
+ p->pwdr = 0x00000000;
701
+ }
702
+
703
+ s->ppr = 0x00000000;
704
+ s->csr = 0x00000000;
705
+ s->pcr = 0x00000000;
706
+ s->pier = 0x00000000;
707
+ s->piir = 0x00000000;
708
+}
709
+
710
+static void npcm7xx_pwm_hold_reset(Object *obj)
711
+{
712
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
713
+ int i;
714
+
715
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
716
+ qemu_irq_lower(s->pwm[i].irq);
717
+ }
718
+}
719
+
720
+static void npcm7xx_pwm_init(Object *obj)
721
+{
722
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
723
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
724
+ int i;
725
+
726
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
727
+ NPCM7xxPWM *p = &s->pwm[i];
728
+ p->module = s;
729
+ p->index = i;
730
+ sysbus_init_irq(sbd, &p->irq);
731
+ }
732
+
733
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_pwm_ops, s,
734
+ TYPE_NPCM7XX_PWM, 4 * KiB);
735
+ sysbus_init_mmio(sbd, &s->iomem);
736
+ s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL);
737
+
738
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
739
+ object_property_add_uint32_ptr(obj, "freq[*]",
740
+ &s->pwm[i].freq, OBJ_PROP_FLAG_READ);
741
+ object_property_add_uint32_ptr(obj, "duty[*]",
742
+ &s->pwm[i].duty, OBJ_PROP_FLAG_READ);
743
+ }
744
+}
745
+
746
+static const VMStateDescription vmstate_npcm7xx_pwm = {
747
+ .name = "npcm7xx-pwm",
748
+ .version_id = 0,
749
+ .minimum_version_id = 0,
750
+ .fields = (VMStateField[]) {
751
+ VMSTATE_BOOL(running, NPCM7xxPWM),
752
+ VMSTATE_BOOL(inverted, NPCM7xxPWM),
753
+ VMSTATE_UINT8(index, NPCM7xxPWM),
754
+ VMSTATE_UINT32(cnr, NPCM7xxPWM),
755
+ VMSTATE_UINT32(cmr, NPCM7xxPWM),
756
+ VMSTATE_UINT32(pdr, NPCM7xxPWM),
757
+ VMSTATE_UINT32(pwdr, NPCM7xxPWM),
758
+ VMSTATE_UINT32(freq, NPCM7xxPWM),
759
+ VMSTATE_UINT32(duty, NPCM7xxPWM),
760
+ VMSTATE_END_OF_LIST(),
761
+ },
762
+};
763
+
764
+static const VMStateDescription vmstate_npcm7xx_pwm_module = {
765
+ .name = "npcm7xx-pwm-module",
766
+ .version_id = 0,
767
+ .minimum_version_id = 0,
768
+ .fields = (VMStateField[]) {
769
+ VMSTATE_CLOCK(clock, NPCM7xxPWMState),
770
+ VMSTATE_STRUCT_ARRAY(pwm, NPCM7xxPWMState,
771
+ NPCM7XX_PWM_PER_MODULE, 0, vmstate_npcm7xx_pwm,
772
+ NPCM7xxPWM),
773
+ VMSTATE_UINT32(ppr, NPCM7xxPWMState),
774
+ VMSTATE_UINT32(csr, NPCM7xxPWMState),
775
+ VMSTATE_UINT32(pcr, NPCM7xxPWMState),
776
+ VMSTATE_UINT32(pier, NPCM7xxPWMState),
777
+ VMSTATE_UINT32(piir, NPCM7xxPWMState),
778
+ VMSTATE_END_OF_LIST(),
779
+ },
780
+};
781
+
782
+static void npcm7xx_pwm_class_init(ObjectClass *klass, void *data)
783
+{
784
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
785
+ DeviceClass *dc = DEVICE_CLASS(klass);
786
+
787
+ dc->desc = "NPCM7xx PWM Controller";
788
+ dc->vmsd = &vmstate_npcm7xx_pwm_module;
789
+ rc->phases.enter = npcm7xx_pwm_enter_reset;
790
+ rc->phases.hold = npcm7xx_pwm_hold_reset;
791
+}
792
+
793
+static const TypeInfo npcm7xx_pwm_info = {
794
+ .name = TYPE_NPCM7XX_PWM,
795
+ .parent = TYPE_SYS_BUS_DEVICE,
796
+ .instance_size = sizeof(NPCM7xxPWMState),
797
+ .class_init = npcm7xx_pwm_class_init,
798
+ .instance_init = npcm7xx_pwm_init,
799
+};
800
+
801
+static void npcm7xx_pwm_register_type(void)
802
+{
803
+ type_register_static(&npcm7xx_pwm_info);
804
+}
805
+type_init(npcm7xx_pwm_register_type);
806
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
807
index XXXXXXX..XXXXXXX 100644
808
--- a/hw/misc/meson.build
809
+++ b/hw/misc/meson.build
810
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
811
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
812
'npcm7xx_clk.c',
813
'npcm7xx_gcr.c',
814
+ 'npcm7xx_pwm.c',
815
'npcm7xx_rng.c',
816
))
817
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files(
818
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
819
index XXXXXXX..XXXXXXX 100644
820
--- a/hw/misc/trace-events
821
+++ b/hw/misc/trace-events
822
@@ -XXX,XX +XXX,XX @@ npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " valu
823
npcm7xx_rng_read(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
824
npcm7xx_rng_write(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
825
826
+# npcm7xx_pwm.c
827
+npcm7xx_pwm_read(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
828
+npcm7xx_pwm_write(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
829
+npcm7xx_pwm_update_freq(const char *id, uint8_t index, uint32_t old_value, uint32_t new_value) "%s pwm[%u] Update Freq: old_freq: %u, new_freq: %u"
830
+npcm7xx_pwm_update_duty(const char *id, uint8_t index, uint32_t old_value, uint32_t new_value) "%s pwm[%u] Update Duty: old_duty: %u, new_duty: %u"
831
+
832
# stm32f4xx_syscfg.c
833
stm32f4xx_syscfg_set_irq(int gpio, int line, int level) "Interupt: GPIO: %d, Line: %d; Level: %d"
834
stm32f4xx_pulse_exti(int irq) "Pulse EXTI: %d"
835
--
164
--
836
2.20.1
165
2.34.1
837
838
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Leif Lindholm <quic_llindhol@quicinc.com>
2
2
3
The ADC is part of NPCM7XX Module. Its behavior is controled by the
3
virt.h defines a number of IRQs that are ultimately described by Arm's
4
ADC_CON register. It converts one of the eight analog inputs into a
4
Base System Architecture specification. Move these to a dedicated header
5
digital input and stores it in the ADC_DATA register when enabled.
5
so that they can be reused by other platforms that do the same.
6
Include that header from virt.h to minimise churn.
6
7
7
Users can alter input value by using qom-set QMP command.
8
While we're moving the definitions, sort them into numerical order,
9
and add the ARCH_TIMER_NS_EL2_VIRT_IRQ definition used by sbsa-ref
10
and which will eventually be needed by virt also.
8
11
9
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
12
Signed-off-by: Leif Lindholm <quic_llindhol@quicinc.com>
10
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
13
Message-id: 20230919090229.188092-3-quic_llindhol@quicinc.com
11
Signed-off-by: Hao Wu <wuhaotsh@google.com>
14
[PMM: Remove unused PPI_TO_INTID macro; sort numerically;
12
Message-id: 20210108190945.949196-4-wuhaotsh@google.com
15
add ARCH_TIMER_NS_EL2_VIRT_IRQ]
13
[PMM: Added missing hw/adc/trace.h file]
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
18
---
17
docs/system/arm/nuvoton.rst | 2 +-
19
include/hw/arm/bsa.h | 35 +++++++++++++++++++++++++++++++++++
18
meson.build | 1 +
20
include/hw/arm/virt.h | 12 +-----------
19
hw/adc/trace.h | 1 +
21
2 files changed, 36 insertions(+), 11 deletions(-)
20
include/hw/adc/npcm7xx_adc.h | 69 ++++++
22
create mode 100644 include/hw/arm/bsa.h
21
include/hw/arm/npcm7xx.h | 2 +
22
hw/adc/npcm7xx_adc.c | 301 ++++++++++++++++++++++++++
23
hw/arm/npcm7xx.c | 24 ++-
24
tests/qtest/npcm7xx_adc-test.c | 377 +++++++++++++++++++++++++++++++++
25
hw/adc/meson.build | 1 +
26
hw/adc/trace-events | 5 +
27
tests/qtest/meson.build | 3 +-
28
11 files changed, 783 insertions(+), 3 deletions(-)
29
create mode 100644 hw/adc/trace.h
30
create mode 100644 include/hw/adc/npcm7xx_adc.h
31
create mode 100644 hw/adc/npcm7xx_adc.c
32
create mode 100644 tests/qtest/npcm7xx_adc-test.c
33
create mode 100644 hw/adc/trace-events
34
23
35
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
24
diff --git a/include/hw/arm/bsa.h b/include/hw/arm/bsa.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/docs/system/arm/nuvoton.rst
38
+++ b/docs/system/arm/nuvoton.rst
39
@@ -XXX,XX +XXX,XX @@ Supported devices
40
* Random Number Generator (RNG)
41
* USB host (USBH)
42
* GPIO controller
43
+ * Analog to Digital Converter (ADC)
44
45
Missing devices
46
---------------
47
@@ -XXX,XX +XXX,XX @@ Missing devices
48
* USB device (USBD)
49
* SMBus controller (SMBF)
50
* Peripheral SPI controller (PSPI)
51
- * Analog to Digital Converter (ADC)
52
* SD/MMC host
53
* PECI interface
54
* Pulse Width Modulation (PWM)
55
diff --git a/meson.build b/meson.build
56
index XXXXXXX..XXXXXXX 100644
57
--- a/meson.build
58
+++ b/meson.build
59
@@ -XXX,XX +XXX,XX @@ if have_system
60
'chardev',
61
'hw/9pfs',
62
'hw/acpi',
63
+ 'hw/adc',
64
'hw/alpha',
65
'hw/arm',
66
'hw/audio',
67
diff --git a/hw/adc/trace.h b/hw/adc/trace.h
68
new file mode 100644
25
new file mode 100644
69
index XXXXXXX..XXXXXXX
26
index XXXXXXX..XXXXXXX
70
--- /dev/null
27
--- /dev/null
71
+++ b/hw/adc/trace.h
28
+++ b/include/hw/arm/bsa.h
72
@@ -0,0 +1 @@
73
+#include "trace/trace-hw_adc.h"
74
diff --git a/include/hw/adc/npcm7xx_adc.h b/include/hw/adc/npcm7xx_adc.h
75
new file mode 100644
76
index XXXXXXX..XXXXXXX
77
--- /dev/null
78
+++ b/include/hw/adc/npcm7xx_adc.h
79
@@ -XXX,XX +XXX,XX @@
29
@@ -XXX,XX +XXX,XX @@
80
+/*
30
+/*
81
+ * Nuvoton NPCM7xx ADC Module
31
+ * Common definitions for Arm Base System Architecture (BSA) platforms.
82
+ *
32
+ *
83
+ * Copyright 2020 Google LLC
33
+ * Copyright (c) 2015 Linaro Limited
34
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
84
+ *
35
+ *
85
+ * This program is free software; you can redistribute it and/or modify it
36
+ * This program is free software; you can redistribute it and/or modify it
86
+ * under the terms of the GNU General Public License as published by the
37
+ * under the terms and conditions of the GNU General Public License,
87
+ * Free Software Foundation; either version 2 of the License, or
38
+ * version 2 or later, as published by the Free Software Foundation.
88
+ * (at your option) any later version.
89
+ *
39
+ *
90
+ * This program is distributed in the hope that it will be useful, but WITHOUT
40
+ * This program is distributed in the hope it will be useful, but WITHOUT
91
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
41
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
92
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
42
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
93
+ * for more details.
43
+ * more details.
94
+ */
95
+#ifndef NPCM7XX_ADC_H
96
+#define NPCM7XX_ADC_H
97
+
98
+#include "hw/clock.h"
99
+#include "hw/irq.h"
100
+#include "hw/sysbus.h"
101
+#include "qemu/timer.h"
102
+
103
+#define NPCM7XX_ADC_NUM_INPUTS 8
104
+/**
105
+ * This value should not be changed unless write_adc_calibration function in
106
+ * hw/arm/npcm7xx.c is also changed.
107
+ */
108
+#define NPCM7XX_ADC_NUM_CALIB 2
109
+
110
+/**
111
+ * struct NPCM7xxADCState - Analog to Digital Converter Module device state.
112
+ * @parent: System bus device.
113
+ * @iomem: Memory region through which registers are accessed.
114
+ * @conv_timer: The timer counts down remaining cycles for the conversion.
115
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
116
+ * @con: The Control Register.
117
+ * @data: The Data Buffer.
118
+ * @clock: The ADC Clock.
119
+ * @adci: The input voltage in units of uV. 1uv = 1e-6V.
120
+ * @vref: The external reference voltage.
121
+ * @iref: The internal reference voltage, initialized at launch time.
122
+ * @rv: The calibrated output values of 0.5V and 1.5V for the ADC.
123
+ */
124
+typedef struct {
125
+ SysBusDevice parent;
126
+
127
+ MemoryRegion iomem;
128
+
129
+ QEMUTimer conv_timer;
130
+
131
+ qemu_irq irq;
132
+ uint32_t con;
133
+ uint32_t data;
134
+ Clock *clock;
135
+
136
+ /* Voltages are in unit of uV. 1V = 1000000uV. */
137
+ uint32_t adci[NPCM7XX_ADC_NUM_INPUTS];
138
+ uint32_t vref;
139
+ uint32_t iref;
140
+
141
+ uint16_t calibration_r_values[NPCM7XX_ADC_NUM_CALIB];
142
+} NPCM7xxADCState;
143
+
144
+#define TYPE_NPCM7XX_ADC "npcm7xx-adc"
145
+#define NPCM7XX_ADC(obj) \
146
+ OBJECT_CHECK(NPCM7xxADCState, (obj), TYPE_NPCM7XX_ADC)
147
+
148
+#endif /* NPCM7XX_ADC_H */
149
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
150
index XXXXXXX..XXXXXXX 100644
151
--- a/include/hw/arm/npcm7xx.h
152
+++ b/include/hw/arm/npcm7xx.h
153
@@ -XXX,XX +XXX,XX @@
154
#define NPCM7XX_H
155
156
#include "hw/boards.h"
157
+#include "hw/adc/npcm7xx_adc.h"
158
#include "hw/cpu/a9mpcore.h"
159
#include "hw/gpio/npcm7xx_gpio.h"
160
#include "hw/mem/npcm7xx_mc.h"
161
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
162
NPCM7xxGCRState gcr;
163
NPCM7xxCLKState clk;
164
NPCM7xxTimerCtrlState tim[3];
165
+ NPCM7xxADCState adc;
166
NPCM7xxOTPState key_storage;
167
NPCM7xxOTPState fuse_array;
168
NPCM7xxMCState mc;
169
diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c
170
new file mode 100644
171
index XXXXXXX..XXXXXXX
172
--- /dev/null
173
+++ b/hw/adc/npcm7xx_adc.c
174
@@ -XXX,XX +XXX,XX @@
175
+/*
176
+ * Nuvoton NPCM7xx ADC Module
177
+ *
44
+ *
178
+ * Copyright 2020 Google LLC
45
+ * You should have received a copy of the GNU General Public License along with
46
+ * this program. If not, see <http://www.gnu.org/licenses/>.
179
+ *
47
+ *
180
+ * This program is free software; you can redistribute it and/or modify it
181
+ * under the terms of the GNU General Public License as published by the
182
+ * Free Software Foundation; either version 2 of the License, or
183
+ * (at your option) any later version.
184
+ *
185
+ * This program is distributed in the hope that it will be useful, but WITHOUT
186
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
187
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
188
+ * for more details.
189
+ */
48
+ */
190
+
49
+
191
+#include "qemu/osdep.h"
50
+#ifndef QEMU_ARM_BSA_H
192
+#include "hw/adc/npcm7xx_adc.h"
51
+#define QEMU_ARM_BSA_H
193
+#include "hw/qdev-clock.h"
194
+#include "hw/qdev-properties.h"
195
+#include "hw/registerfields.h"
196
+#include "migration/vmstate.h"
197
+#include "qemu/log.h"
198
+#include "qemu/module.h"
199
+#include "qemu/timer.h"
200
+#include "qemu/units.h"
201
+#include "trace.h"
202
+
52
+
203
+REG32(NPCM7XX_ADC_CON, 0x0)
53
+/* These are architectural INTID values */
204
+REG32(NPCM7XX_ADC_DATA, 0x4)
54
+#define VIRTUAL_PMU_IRQ 23
55
+#define ARCH_GIC_MAINT_IRQ 25
56
+#define ARCH_TIMER_NS_EL2_IRQ 26
57
+#define ARCH_TIMER_VIRT_IRQ 27
58
+#define ARCH_TIMER_NS_EL2_VIRT_IRQ 28
59
+#define ARCH_TIMER_S_EL1_IRQ 29
60
+#define ARCH_TIMER_NS_EL1_IRQ 30
205
+
61
+
206
+/* Register field definitions. */
62
+#define INTID_TO_PPI(irq) ((irq) - 16)
207
+#define NPCM7XX_ADC_CON_MUX(rv) extract32(rv, 24, 4)
208
+#define NPCM7XX_ADC_CON_INT_EN BIT(21)
209
+#define NPCM7XX_ADC_CON_REFSEL BIT(19)
210
+#define NPCM7XX_ADC_CON_INT BIT(18)
211
+#define NPCM7XX_ADC_CON_EN BIT(17)
212
+#define NPCM7XX_ADC_CON_RST BIT(16)
213
+#define NPCM7XX_ADC_CON_CONV BIT(14)
214
+#define NPCM7XX_ADC_CON_DIV(rv) extract32(rv, 1, 8)
215
+
63
+
216
+#define NPCM7XX_ADC_MAX_RESULT 1023
64
+#endif /* QEMU_ARM_BSA_H */
217
+#define NPCM7XX_ADC_DEFAULT_IREF 2000000
65
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
218
+#define NPCM7XX_ADC_CONV_CYCLES 20
219
+#define NPCM7XX_ADC_RESET_CYCLES 10
220
+#define NPCM7XX_ADC_R0_INPUT 500000
221
+#define NPCM7XX_ADC_R1_INPUT 1500000
222
+
223
+static void npcm7xx_adc_reset(NPCM7xxADCState *s)
224
+{
225
+ timer_del(&s->conv_timer);
226
+ s->con = 0x000c0001;
227
+ s->data = 0x00000000;
228
+}
229
+
230
+static uint32_t npcm7xx_adc_convert(uint32_t input, uint32_t ref)
231
+{
232
+ uint32_t result;
233
+
234
+ result = input * (NPCM7XX_ADC_MAX_RESULT + 1) / ref;
235
+ if (result > NPCM7XX_ADC_MAX_RESULT) {
236
+ result = NPCM7XX_ADC_MAX_RESULT;
237
+ }
238
+
239
+ return result;
240
+}
241
+
242
+static uint32_t npcm7xx_adc_prescaler(NPCM7xxADCState *s)
243
+{
244
+ return 2 * (NPCM7XX_ADC_CON_DIV(s->con) + 1);
245
+}
246
+
247
+static void npcm7xx_adc_start_timer(Clock *clk, QEMUTimer *timer,
248
+ uint32_t cycles, uint32_t prescaler)
249
+{
250
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
251
+ int64_t ticks = cycles;
252
+ int64_t ns;
253
+
254
+ ticks *= prescaler;
255
+ ns = clock_ticks_to_ns(clk, ticks);
256
+ ns += now;
257
+ timer_mod(timer, ns);
258
+}
259
+
260
+static void npcm7xx_adc_start_convert(NPCM7xxADCState *s)
261
+{
262
+ uint32_t prescaler = npcm7xx_adc_prescaler(s);
263
+
264
+ npcm7xx_adc_start_timer(s->clock, &s->conv_timer, NPCM7XX_ADC_CONV_CYCLES,
265
+ prescaler);
266
+}
267
+
268
+static void npcm7xx_adc_convert_done(void *opaque)
269
+{
270
+ NPCM7xxADCState *s = opaque;
271
+ uint32_t input = NPCM7XX_ADC_CON_MUX(s->con);
272
+ uint32_t ref = (s->con & NPCM7XX_ADC_CON_REFSEL)
273
+ ? s->iref : s->vref;
274
+
275
+ if (input >= NPCM7XX_ADC_NUM_INPUTS) {
276
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid input: %u\n",
277
+ __func__, input);
278
+ return;
279
+ }
280
+ s->data = npcm7xx_adc_convert(s->adci[input], ref);
281
+ if (s->con & NPCM7XX_ADC_CON_INT_EN) {
282
+ s->con |= NPCM7XX_ADC_CON_INT;
283
+ qemu_irq_raise(s->irq);
284
+ }
285
+ s->con &= ~NPCM7XX_ADC_CON_CONV;
286
+}
287
+
288
+static void npcm7xx_adc_calibrate(NPCM7xxADCState *adc)
289
+{
290
+ adc->calibration_r_values[0] = npcm7xx_adc_convert(NPCM7XX_ADC_R0_INPUT,
291
+ adc->iref);
292
+ adc->calibration_r_values[1] = npcm7xx_adc_convert(NPCM7XX_ADC_R1_INPUT,
293
+ adc->iref);
294
+}
295
+
296
+static void npcm7xx_adc_write_con(NPCM7xxADCState *s, uint32_t new_con)
297
+{
298
+ uint32_t old_con = s->con;
299
+
300
+ /* Write ADC_INT to 1 to clear it */
301
+ if (new_con & NPCM7XX_ADC_CON_INT) {
302
+ new_con &= ~NPCM7XX_ADC_CON_INT;
303
+ qemu_irq_lower(s->irq);
304
+ } else if (old_con & NPCM7XX_ADC_CON_INT) {
305
+ new_con |= NPCM7XX_ADC_CON_INT;
306
+ }
307
+
308
+ s->con = new_con;
309
+
310
+ if (s->con & NPCM7XX_ADC_CON_RST) {
311
+ npcm7xx_adc_reset(s);
312
+ return;
313
+ }
314
+
315
+ if ((s->con & NPCM7XX_ADC_CON_EN)) {
316
+ if (s->con & NPCM7XX_ADC_CON_CONV) {
317
+ if (!(old_con & NPCM7XX_ADC_CON_CONV)) {
318
+ npcm7xx_adc_start_convert(s);
319
+ }
320
+ } else {
321
+ timer_del(&s->conv_timer);
322
+ }
323
+ }
324
+}
325
+
326
+static uint64_t npcm7xx_adc_read(void *opaque, hwaddr offset, unsigned size)
327
+{
328
+ uint64_t value = 0;
329
+ NPCM7xxADCState *s = opaque;
330
+
331
+ switch (offset) {
332
+ case A_NPCM7XX_ADC_CON:
333
+ value = s->con;
334
+ break;
335
+
336
+ case A_NPCM7XX_ADC_DATA:
337
+ value = s->data;
338
+ break;
339
+
340
+ default:
341
+ qemu_log_mask(LOG_GUEST_ERROR,
342
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
343
+ __func__, offset);
344
+ break;
345
+ }
346
+
347
+ trace_npcm7xx_adc_read(DEVICE(s)->canonical_path, offset, value);
348
+ return value;
349
+}
350
+
351
+static void npcm7xx_adc_write(void *opaque, hwaddr offset, uint64_t v,
352
+ unsigned size)
353
+{
354
+ NPCM7xxADCState *s = opaque;
355
+
356
+ trace_npcm7xx_adc_write(DEVICE(s)->canonical_path, offset, v);
357
+ switch (offset) {
358
+ case A_NPCM7XX_ADC_CON:
359
+ npcm7xx_adc_write_con(s, v);
360
+ break;
361
+
362
+ case A_NPCM7XX_ADC_DATA:
363
+ qemu_log_mask(LOG_GUEST_ERROR,
364
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
365
+ __func__, offset);
366
+ break;
367
+
368
+ default:
369
+ qemu_log_mask(LOG_GUEST_ERROR,
370
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
371
+ __func__, offset);
372
+ break;
373
+ }
374
+
375
+}
376
+
377
+static const struct MemoryRegionOps npcm7xx_adc_ops = {
378
+ .read = npcm7xx_adc_read,
379
+ .write = npcm7xx_adc_write,
380
+ .endianness = DEVICE_LITTLE_ENDIAN,
381
+ .valid = {
382
+ .min_access_size = 4,
383
+ .max_access_size = 4,
384
+ .unaligned = false,
385
+ },
386
+};
387
+
388
+static void npcm7xx_adc_enter_reset(Object *obj, ResetType type)
389
+{
390
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
391
+
392
+ npcm7xx_adc_reset(s);
393
+}
394
+
395
+static void npcm7xx_adc_hold_reset(Object *obj)
396
+{
397
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
398
+
399
+ qemu_irq_lower(s->irq);
400
+}
401
+
402
+static void npcm7xx_adc_init(Object *obj)
403
+{
404
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
405
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
406
+ int i;
407
+
408
+ sysbus_init_irq(sbd, &s->irq);
409
+
410
+ timer_init_ns(&s->conv_timer, QEMU_CLOCK_VIRTUAL,
411
+ npcm7xx_adc_convert_done, s);
412
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_adc_ops, s,
413
+ TYPE_NPCM7XX_ADC, 4 * KiB);
414
+ sysbus_init_mmio(sbd, &s->iomem);
415
+ s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL);
416
+
417
+ for (i = 0; i < NPCM7XX_ADC_NUM_INPUTS; ++i) {
418
+ object_property_add_uint32_ptr(obj, "adci[*]",
419
+ &s->adci[i], OBJ_PROP_FLAG_WRITE);
420
+ }
421
+ object_property_add_uint32_ptr(obj, "vref",
422
+ &s->vref, OBJ_PROP_FLAG_WRITE);
423
+ npcm7xx_adc_calibrate(s);
424
+}
425
+
426
+static const VMStateDescription vmstate_npcm7xx_adc = {
427
+ .name = "npcm7xx-adc",
428
+ .version_id = 0,
429
+ .minimum_version_id = 0,
430
+ .fields = (VMStateField[]) {
431
+ VMSTATE_TIMER(conv_timer, NPCM7xxADCState),
432
+ VMSTATE_UINT32(con, NPCM7xxADCState),
433
+ VMSTATE_UINT32(data, NPCM7xxADCState),
434
+ VMSTATE_CLOCK(clock, NPCM7xxADCState),
435
+ VMSTATE_UINT32_ARRAY(adci, NPCM7xxADCState, NPCM7XX_ADC_NUM_INPUTS),
436
+ VMSTATE_UINT32(vref, NPCM7xxADCState),
437
+ VMSTATE_UINT32(iref, NPCM7xxADCState),
438
+ VMSTATE_UINT16_ARRAY(calibration_r_values, NPCM7xxADCState,
439
+ NPCM7XX_ADC_NUM_CALIB),
440
+ VMSTATE_END_OF_LIST(),
441
+ },
442
+};
443
+
444
+static Property npcm7xx_timer_properties[] = {
445
+ DEFINE_PROP_UINT32("iref", NPCM7xxADCState, iref, NPCM7XX_ADC_DEFAULT_IREF),
446
+ DEFINE_PROP_END_OF_LIST(),
447
+};
448
+
449
+static void npcm7xx_adc_class_init(ObjectClass *klass, void *data)
450
+{
451
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
452
+ DeviceClass *dc = DEVICE_CLASS(klass);
453
+
454
+ dc->desc = "NPCM7xx ADC Module";
455
+ dc->vmsd = &vmstate_npcm7xx_adc;
456
+ rc->phases.enter = npcm7xx_adc_enter_reset;
457
+ rc->phases.hold = npcm7xx_adc_hold_reset;
458
+
459
+ device_class_set_props(dc, npcm7xx_timer_properties);
460
+}
461
+
462
+static const TypeInfo npcm7xx_adc_info = {
463
+ .name = TYPE_NPCM7XX_ADC,
464
+ .parent = TYPE_SYS_BUS_DEVICE,
465
+ .instance_size = sizeof(NPCM7xxADCState),
466
+ .class_init = npcm7xx_adc_class_init,
467
+ .instance_init = npcm7xx_adc_init,
468
+};
469
+
470
+static void npcm7xx_adc_register_types(void)
471
+{
472
+ type_register_static(&npcm7xx_adc_info);
473
+}
474
+
475
+type_init(npcm7xx_adc_register_types);
476
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
477
index XXXXXXX..XXXXXXX 100644
66
index XXXXXXX..XXXXXXX 100644
478
--- a/hw/arm/npcm7xx.c
67
--- a/include/hw/arm/virt.h
479
+++ b/hw/arm/npcm7xx.c
68
+++ b/include/hw/arm/virt.h
480
@@ -XXX,XX +XXX,XX @@
69
@@ -XXX,XX +XXX,XX @@
481
#define NPCM7XX_EHCI_BA (0xf0806000)
70
#include "qemu/notify.h"
482
#define NPCM7XX_OHCI_BA (0xf0807000)
71
#include "hw/boards.h"
483
72
#include "hw/arm/boot.h"
484
+/* ADC Module */
73
+#include "hw/arm/bsa.h"
485
+#define NPCM7XX_ADC_BA (0xf000c000)
74
#include "hw/block/flash.h"
486
+
75
#include "sysemu/kvm.h"
487
/* Internal AHB SRAM */
76
#include "hw/intc/arm_gicv3_common.h"
488
#define NPCM7XX_RAM3_BA (0xc0008000)
489
#define NPCM7XX_RAM3_SZ (4 * KiB)
490
@@ -XXX,XX +XXX,XX @@
77
@@ -XXX,XX +XXX,XX @@
491
#define NPCM7XX_ROM_BA (0xffff0000)
78
#define NUM_VIRTIO_TRANSPORTS 32
492
#define NPCM7XX_ROM_SZ (64 * KiB)
79
#define NUM_SMMU_IRQS 4
493
80
494
+
81
-#define ARCH_GIC_MAINT_IRQ 25
495
/* Clock configuration values to be fixed up when bypassing bootloader */
82
-
496
83
-#define ARCH_TIMER_VIRT_IRQ 27
497
/* Run PLL1 at 1600 MHz */
84
-#define ARCH_TIMER_S_EL1_IRQ 29
498
@@ -XXX,XX +XXX,XX @@
85
-#define ARCH_TIMER_NS_EL1_IRQ 30
499
* interrupts.
86
-#define ARCH_TIMER_NS_EL2_IRQ 26
500
*/
87
-
501
enum NPCM7xxInterrupt {
88
-#define VIRTUAL_PMU_IRQ 23
502
+ NPCM7XX_ADC_IRQ = 0,
89
-
503
NPCM7XX_UART0_IRQ = 2,
90
-#define INTID_TO_PPI(irq) ((irq) - 16)
504
NPCM7XX_UART1_IRQ,
91
-
505
NPCM7XX_UART2_IRQ,
92
/* See Linux kernel arch/arm64/include/asm/pvclock-abi.h */
506
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init_fuses(NPCM7xxState *s)
93
#define PVTIME_SIZE_PER_CPU 64
507
sizeof(value));
94
508
}
509
510
+static void npcm7xx_write_adc_calibration(NPCM7xxState *s)
511
+{
512
+ /* Both ADC and the fuse array must have realized. */
513
+ QEMU_BUILD_BUG_ON(sizeof(s->adc.calibration_r_values) != 4);
514
+ npcm7xx_otp_array_write(&s->fuse_array, s->adc.calibration_r_values,
515
+ NPCM7XX_FUSE_ADC_CALIB, sizeof(s->adc.calibration_r_values));
516
+}
517
+
518
static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n)
519
{
520
return qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
521
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
522
TYPE_NPCM7XX_FUSE_ARRAY);
523
object_initialize_child(obj, "mc", &s->mc, TYPE_NPCM7XX_MC);
524
object_initialize_child(obj, "rng", &s->rng, TYPE_NPCM7XX_RNG);
525
+ object_initialize_child(obj, "adc", &s->adc, TYPE_NPCM7XX_ADC);
526
527
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
528
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
529
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
530
sysbus_realize(SYS_BUS_DEVICE(&s->mc), &error_abort);
531
sysbus_mmio_map(SYS_BUS_DEVICE(&s->mc), 0, NPCM7XX_MC_BA);
532
533
+ /* ADC Modules. Cannot fail. */
534
+ qdev_connect_clock_in(DEVICE(&s->adc), "clock", qdev_get_clock_out(
535
+ DEVICE(&s->clk), "adc-clock"));
536
+ sysbus_realize(SYS_BUS_DEVICE(&s->adc), &error_abort);
537
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->adc), 0, NPCM7XX_ADC_BA);
538
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0,
539
+ npcm7xx_irq(s, NPCM7XX_ADC_IRQ));
540
+ npcm7xx_write_adc_calibration(s);
541
+
542
/* Timer Modules (TIM). Cannot fail. */
543
QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
544
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
545
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
546
create_unimplemented_device("npcm7xx.vdmx", 0xe0800000, 4 * KiB);
547
create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * KiB);
548
create_unimplemented_device("npcm7xx.kcs", 0xf0007000, 4 * KiB);
549
- create_unimplemented_device("npcm7xx.adc", 0xf000c000, 4 * KiB);
550
create_unimplemented_device("npcm7xx.gfxi", 0xf000e000, 4 * KiB);
551
create_unimplemented_device("npcm7xx.gpio[0]", 0xf0010000, 4 * KiB);
552
create_unimplemented_device("npcm7xx.gpio[1]", 0xf0011000, 4 * KiB);
553
diff --git a/tests/qtest/npcm7xx_adc-test.c b/tests/qtest/npcm7xx_adc-test.c
554
new file mode 100644
555
index XXXXXXX..XXXXXXX
556
--- /dev/null
557
+++ b/tests/qtest/npcm7xx_adc-test.c
558
@@ -XXX,XX +XXX,XX @@
559
+/*
560
+ * QTests for Nuvoton NPCM7xx ADCModules.
561
+ *
562
+ * Copyright 2020 Google LLC
563
+ *
564
+ * This program is free software; you can redistribute it and/or modify it
565
+ * under the terms of the GNU General Public License as published by the
566
+ * Free Software Foundation; either version 2 of the License, or
567
+ * (at your option) any later version.
568
+ *
569
+ * This program is distributed in the hope that it will be useful, but WITHOUT
570
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
571
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
572
+ * for more details.
573
+ */
574
+
575
+#include "qemu/osdep.h"
576
+#include "qemu/bitops.h"
577
+#include "qemu/timer.h"
578
+#include "libqos/libqtest.h"
579
+#include "qapi/qmp/qdict.h"
580
+
581
+#define REF_HZ (25000000)
582
+
583
+#define CON_OFFSET 0x0
584
+#define DATA_OFFSET 0x4
585
+
586
+#define NUM_INPUTS 8
587
+#define DEFAULT_IREF 2000000
588
+#define CONV_CYCLES 20
589
+#define RESET_CYCLES 10
590
+#define R0_INPUT 500000
591
+#define R1_INPUT 1500000
592
+#define MAX_RESULT 1023
593
+
594
+#define DEFAULT_CLKDIV 5
595
+
596
+#define FUSE_ARRAY_BA 0xf018a000
597
+#define FCTL_OFFSET 0x14
598
+#define FST_OFFSET 0x0
599
+#define FADDR_OFFSET 0x4
600
+#define FDATA_OFFSET 0x8
601
+#define ADC_CALIB_ADDR 24
602
+#define FUSE_READ 0x2
603
+
604
+/* Register field definitions. */
605
+#define CON_MUX(rv) ((rv) << 24)
606
+#define CON_INT_EN BIT(21)
607
+#define CON_REFSEL BIT(19)
608
+#define CON_INT BIT(18)
609
+#define CON_EN BIT(17)
610
+#define CON_RST BIT(16)
611
+#define CON_CONV BIT(14)
612
+#define CON_DIV(rv) extract32(rv, 1, 8)
613
+
614
+#define FST_RDST BIT(1)
615
+#define FDATA_MASK 0xff
616
+
617
+#define MAX_ERROR 10000
618
+#define MIN_CALIB_INPUT 100000
619
+#define MAX_CALIB_INPUT 1800000
620
+
621
+static const uint32_t input_list[] = {
622
+ 100000,
623
+ 500000,
624
+ 1000000,
625
+ 1500000,
626
+ 1800000,
627
+ 2000000,
628
+};
629
+
630
+static const uint32_t vref_list[] = {
631
+ 2000000,
632
+ 2200000,
633
+ 2500000,
634
+};
635
+
636
+static const uint32_t iref_list[] = {
637
+ 1800000,
638
+ 1900000,
639
+ 2000000,
640
+ 2100000,
641
+ 2200000,
642
+};
643
+
644
+static const uint32_t div_list[] = {0, 1, 3, 7, 15};
645
+
646
+typedef struct ADC {
647
+ int irq;
648
+ uint64_t base_addr;
649
+} ADC;
650
+
651
+ADC adc = {
652
+ .irq = 0,
653
+ .base_addr = 0xf000c000
654
+};
655
+
656
+static uint32_t adc_read_con(QTestState *qts, const ADC *adc)
657
+{
658
+ return qtest_readl(qts, adc->base_addr + CON_OFFSET);
659
+}
660
+
661
+static void adc_write_con(QTestState *qts, const ADC *adc, uint32_t value)
662
+{
663
+ qtest_writel(qts, adc->base_addr + CON_OFFSET, value);
664
+}
665
+
666
+static uint32_t adc_read_data(QTestState *qts, const ADC *adc)
667
+{
668
+ return qtest_readl(qts, adc->base_addr + DATA_OFFSET);
669
+}
670
+
671
+static uint32_t adc_calibrate(uint32_t measured, uint32_t *rv)
672
+{
673
+ return R0_INPUT + (R1_INPUT - R0_INPUT) * (int32_t)(measured - rv[0])
674
+ / (int32_t)(rv[1] - rv[0]);
675
+}
676
+
677
+static void adc_qom_set(QTestState *qts, const ADC *adc,
678
+ const char *name, uint32_t value)
679
+{
680
+ QDict *response;
681
+ const char *path = "/machine/soc/adc";
682
+
683
+ g_test_message("Setting properties %s of %s with value %u",
684
+ name, path, value);
685
+ response = qtest_qmp(qts, "{ 'execute': 'qom-set',"
686
+ " 'arguments': { 'path': %s, 'property': %s, 'value': %u}}",
687
+ path, name, value);
688
+ /* The qom set message returns successfully. */
689
+ g_assert_true(qdict_haskey(response, "return"));
690
+}
691
+
692
+static void adc_write_input(QTestState *qts, const ADC *adc,
693
+ uint32_t index, uint32_t value)
694
+{
695
+ char name[100];
696
+
697
+ sprintf(name, "adci[%u]", index);
698
+ adc_qom_set(qts, adc, name, value);
699
+}
700
+
701
+static void adc_write_vref(QTestState *qts, const ADC *adc, uint32_t value)
702
+{
703
+ adc_qom_set(qts, adc, "vref", value);
704
+}
705
+
706
+static uint32_t adc_calculate_output(uint32_t input, uint32_t ref)
707
+{
708
+ uint32_t output;
709
+
710
+ g_assert_cmpuint(input, <=, ref);
711
+ output = (input * (MAX_RESULT + 1)) / ref;
712
+ if (output > MAX_RESULT) {
713
+ output = MAX_RESULT;
714
+ }
715
+
716
+ return output;
717
+}
718
+
719
+static uint32_t adc_prescaler(QTestState *qts, const ADC *adc)
720
+{
721
+ uint32_t div = extract32(adc_read_con(qts, adc), 1, 8);
722
+
723
+ return 2 * (div + 1);
724
+}
725
+
726
+static int64_t adc_calculate_steps(uint32_t cycles, uint32_t prescale,
727
+ uint32_t clkdiv)
728
+{
729
+ return (NANOSECONDS_PER_SECOND / (REF_HZ >> clkdiv)) * cycles * prescale;
730
+}
731
+
732
+static void adc_wait_conv_finished(QTestState *qts, const ADC *adc,
733
+ uint32_t clkdiv)
734
+{
735
+ uint32_t prescaler = adc_prescaler(qts, adc);
736
+
737
+ /*
738
+ * ADC should takes roughly 20 cycles to convert one sample. So we assert it
739
+ * should take 10~30 cycles here.
740
+ */
741
+ qtest_clock_step(qts, adc_calculate_steps(CONV_CYCLES / 2, prescaler,
742
+ clkdiv));
743
+ /* ADC is still converting. */
744
+ g_assert_true(adc_read_con(qts, adc) & CON_CONV);
745
+ qtest_clock_step(qts, adc_calculate_steps(CONV_CYCLES, prescaler, clkdiv));
746
+ /* ADC has finished conversion. */
747
+ g_assert_false(adc_read_con(qts, adc) & CON_CONV);
748
+}
749
+
750
+/* Check ADC can be reset to default value. */
751
+static void test_init(gconstpointer adc_p)
752
+{
753
+ const ADC *adc = adc_p;
754
+
755
+ QTestState *qts = qtest_init("-machine quanta-gsj");
756
+ adc_write_con(qts, adc, CON_REFSEL | CON_INT);
757
+ g_assert_cmphex(adc_read_con(qts, adc), ==, CON_REFSEL);
758
+ qtest_quit(qts);
759
+}
760
+
761
+/* Check ADC can convert from an internal reference. */
762
+static void test_convert_internal(gconstpointer adc_p)
763
+{
764
+ const ADC *adc = adc_p;
765
+ uint32_t index, input, output, expected_output;
766
+ QTestState *qts = qtest_init("-machine quanta-gsj");
767
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
768
+
769
+ for (index = 0; index < NUM_INPUTS; ++index) {
770
+ for (size_t i = 0; i < ARRAY_SIZE(input_list); ++i) {
771
+ input = input_list[i];
772
+ expected_output = adc_calculate_output(input, DEFAULT_IREF);
773
+
774
+ adc_write_input(qts, adc, index, input);
775
+ adc_write_con(qts, adc, CON_MUX(index) | CON_REFSEL | CON_INT |
776
+ CON_EN | CON_CONV);
777
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
778
+ g_assert_cmphex(adc_read_con(qts, adc), ==, CON_MUX(index) |
779
+ CON_REFSEL | CON_EN);
780
+ g_assert_false(qtest_get_irq(qts, adc->irq));
781
+ output = adc_read_data(qts, adc);
782
+ g_assert_cmpuint(output, ==, expected_output);
783
+ }
784
+ }
785
+
786
+ qtest_quit(qts);
787
+}
788
+
789
+/* Check ADC can convert from an external reference. */
790
+static void test_convert_external(gconstpointer adc_p)
791
+{
792
+ const ADC *adc = adc_p;
793
+ uint32_t index, input, vref, output, expected_output;
794
+ QTestState *qts = qtest_init("-machine quanta-gsj");
795
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
796
+
797
+ for (index = 0; index < NUM_INPUTS; ++index) {
798
+ for (size_t i = 0; i < ARRAY_SIZE(input_list); ++i) {
799
+ for (size_t j = 0; j < ARRAY_SIZE(vref_list); ++j) {
800
+ input = input_list[i];
801
+ vref = vref_list[j];
802
+ expected_output = adc_calculate_output(input, vref);
803
+
804
+ adc_write_input(qts, adc, index, input);
805
+ adc_write_vref(qts, adc, vref);
806
+ adc_write_con(qts, adc, CON_MUX(index) | CON_INT | CON_EN |
807
+ CON_CONV);
808
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
809
+ g_assert_cmphex(adc_read_con(qts, adc), ==,
810
+ CON_MUX(index) | CON_EN);
811
+ g_assert_false(qtest_get_irq(qts, adc->irq));
812
+ output = adc_read_data(qts, adc);
813
+ g_assert_cmpuint(output, ==, expected_output);
814
+ }
815
+ }
816
+ }
817
+
818
+ qtest_quit(qts);
819
+}
820
+
821
+/* Check ADC interrupt files if and only if CON_INT_EN is set. */
822
+static void test_interrupt(gconstpointer adc_p)
823
+{
824
+ const ADC *adc = adc_p;
825
+ uint32_t index, input, output, expected_output;
826
+ QTestState *qts = qtest_init("-machine quanta-gsj");
827
+
828
+ index = 1;
829
+ input = input_list[1];
830
+ expected_output = adc_calculate_output(input, DEFAULT_IREF);
831
+
832
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
833
+ adc_write_input(qts, adc, index, input);
834
+ g_assert_false(qtest_get_irq(qts, adc->irq));
835
+ adc_write_con(qts, adc, CON_MUX(index) | CON_INT_EN | CON_REFSEL | CON_INT
836
+ | CON_EN | CON_CONV);
837
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
838
+ g_assert_cmphex(adc_read_con(qts, adc), ==, CON_MUX(index) | CON_INT_EN
839
+ | CON_REFSEL | CON_INT | CON_EN);
840
+ g_assert_true(qtest_get_irq(qts, adc->irq));
841
+ output = adc_read_data(qts, adc);
842
+ g_assert_cmpuint(output, ==, expected_output);
843
+
844
+ qtest_quit(qts);
845
+}
846
+
847
+/* Check ADC is reset after setting ADC_RST for 10 ADC cycles. */
848
+static void test_reset(gconstpointer adc_p)
849
+{
850
+ const ADC *adc = adc_p;
851
+ QTestState *qts = qtest_init("-machine quanta-gsj");
852
+
853
+ for (size_t i = 0; i < ARRAY_SIZE(div_list); ++i) {
854
+ uint32_t div = div_list[i];
855
+
856
+ adc_write_con(qts, adc, CON_INT | CON_EN | CON_RST | CON_DIV(div));
857
+ qtest_clock_step(qts, adc_calculate_steps(RESET_CYCLES,
858
+ adc_prescaler(qts, adc), DEFAULT_CLKDIV));
859
+ g_assert_false(adc_read_con(qts, adc) & CON_EN);
860
+ }
861
+ qtest_quit(qts);
862
+}
863
+
864
+/* Check ADC Calibration works as desired. */
865
+static void test_calibrate(gconstpointer adc_p)
866
+{
867
+ int i, j;
868
+ const ADC *adc = adc_p;
869
+
870
+ for (j = 0; j < ARRAY_SIZE(iref_list); ++j) {
871
+ uint32_t iref = iref_list[j];
872
+ uint32_t expected_rv[] = {
873
+ adc_calculate_output(R0_INPUT, iref),
874
+ adc_calculate_output(R1_INPUT, iref),
875
+ };
876
+ char buf[100];
877
+ QTestState *qts;
878
+
879
+ sprintf(buf, "-machine quanta-gsj -global npcm7xx-adc.iref=%u", iref);
880
+ qts = qtest_init(buf);
881
+
882
+ /* Check the converted value is correct using the calibration value. */
883
+ for (i = 0; i < ARRAY_SIZE(input_list); ++i) {
884
+ uint32_t input;
885
+ uint32_t output;
886
+ uint32_t expected_output;
887
+ uint32_t calibrated_voltage;
888
+ uint32_t index = 0;
889
+
890
+ input = input_list[i];
891
+ /* Calibration only works for input range 0.1V ~ 1.8V. */
892
+ if (input < MIN_CALIB_INPUT || input > MAX_CALIB_INPUT) {
893
+ continue;
894
+ }
895
+ expected_output = adc_calculate_output(input, iref);
896
+
897
+ adc_write_input(qts, adc, index, input);
898
+ adc_write_con(qts, adc, CON_MUX(index) | CON_REFSEL | CON_INT |
899
+ CON_EN | CON_CONV);
900
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
901
+ g_assert_cmphex(adc_read_con(qts, adc), ==,
902
+ CON_REFSEL | CON_MUX(index) | CON_EN);
903
+ output = adc_read_data(qts, adc);
904
+ g_assert_cmpuint(output, ==, expected_output);
905
+
906
+ calibrated_voltage = adc_calibrate(output, expected_rv);
907
+ g_assert_cmpuint(calibrated_voltage, >, input - MAX_ERROR);
908
+ g_assert_cmpuint(calibrated_voltage, <, input + MAX_ERROR);
909
+ }
910
+
911
+ qtest_quit(qts);
912
+ }
913
+}
914
+
915
+static void adc_add_test(const char *name, const ADC* wd,
916
+ GTestDataFunc fn)
917
+{
918
+ g_autofree char *full_name = g_strdup_printf("npcm7xx_adc/%s", name);
919
+ qtest_add_data_func(full_name, wd, fn);
920
+}
921
+#define add_test(name, td) adc_add_test(#name, td, test_##name)
922
+
923
+int main(int argc, char **argv)
924
+{
925
+ g_test_init(&argc, &argv, NULL);
926
+
927
+ add_test(init, &adc);
928
+ add_test(convert_internal, &adc);
929
+ add_test(convert_external, &adc);
930
+ add_test(interrupt, &adc);
931
+ add_test(reset, &adc);
932
+ add_test(calibrate, &adc);
933
+
934
+ return g_test_run();
935
+}
936
diff --git a/hw/adc/meson.build b/hw/adc/meson.build
937
index XXXXXXX..XXXXXXX 100644
938
--- a/hw/adc/meson.build
939
+++ b/hw/adc/meson.build
940
@@ -1 +1,2 @@
941
softmmu_ss.add(when: 'CONFIG_STM32F2XX_ADC', if_true: files('stm32f2xx_adc.c'))
942
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_adc.c'))
943
diff --git a/hw/adc/trace-events b/hw/adc/trace-events
944
new file mode 100644
945
index XXXXXXX..XXXXXXX
946
--- /dev/null
947
+++ b/hw/adc/trace-events
948
@@ -XXX,XX +XXX,XX @@
949
+# See docs/devel/tracing.txt for syntax documentation.
950
+
951
+# npcm7xx_adc.c
952
+npcm7xx_adc_read(const char *id, uint64_t offset, uint32_t value) " %s offset: 0x%04" PRIx64 " value 0x%04" PRIx32
953
+npcm7xx_adc_write(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value 0x%04" PRIx32
954
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
955
index XXXXXXX..XXXXXXX 100644
956
--- a/tests/qtest/meson.build
957
+++ b/tests/qtest/meson.build
958
@@ -XXX,XX +XXX,XX @@ qtests_sparc64 = \
959
['prom-env-test', 'boot-serial-test']
960
961
qtests_npcm7xx = \
962
- ['npcm7xx_gpio-test',
963
+ ['npcm7xx_adc-test',
964
+ 'npcm7xx_gpio-test',
965
'npcm7xx_rng-test',
966
'npcm7xx_timer-test',
967
'npcm7xx_watchdog_timer-test']
968
--
95
--
969
2.20.1
96
2.34.1
970
971
diff view generated by jsdifflib
1
From: Roman Bolshakov <r.bolshakov@yadro.com>
1
From: Leif Lindholm <quic_llindhol@quicinc.com>
2
2
3
QEMU documentation can't be opened if QEMU is run from build tree
3
Use the private peripheral interrupt definitions from bsa.h instead of
4
because executables are placed in the top of build tree after conversion
4
defining them locally. Refactor to use the INTIDs defined there instead
5
to meson.
5
of the PPI# used previously.
6
6
7
Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com>
7
Signed-off-by: Leif Lindholm <quic_llindhol@quicinc.com>
8
Reported-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20230919090229.188092-4-quic_llindhol@quicinc.com
9
Message-id: 20210108213815.64678-1-r.bolshakov@yadro.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
11
---
13
ui/cocoa.m | 2 +-
12
hw/arm/sbsa-ref.c | 21 +++++++++------------
14
1 file changed, 1 insertion(+), 1 deletion(-)
13
1 file changed, 9 insertions(+), 12 deletions(-)
15
14
16
diff --git a/ui/cocoa.m b/ui/cocoa.m
15
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/ui/cocoa.m
17
--- a/hw/arm/sbsa-ref.c
19
+++ b/ui/cocoa.m
18
+++ b/hw/arm/sbsa-ref.c
20
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
19
@@ -XXX,XX +XXX,XX @@
21
- (void) openDocumentation: (NSString *) filename
20
* ARM SBSA Reference Platform emulation
22
{
21
*
23
/* Where to look for local files */
22
* Copyright (c) 2018 Linaro Limited
24
- NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"../docs/"};
23
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
25
+ NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"docs/"};
24
* Written by Hongbo Zhang <hongbo.zhang@linaro.org>
26
NSString *full_file_path;
25
*
27
26
* This program is free software; you can redistribute it and/or modify it
28
/* iterate thru the possible paths until the file is found */
27
@@ -XXX,XX +XXX,XX @@
28
#include "exec/hwaddr.h"
29
#include "kvm_arm.h"
30
#include "hw/arm/boot.h"
31
+#include "hw/arm/bsa.h"
32
#include "hw/arm/fdt.h"
33
#include "hw/arm/smmuv3.h"
34
#include "hw/block/flash.h"
35
@@ -XXX,XX +XXX,XX @@
36
#define NUM_SMMU_IRQS 4
37
#define NUM_SATA_PORTS 6
38
39
-#define VIRTUAL_PMU_IRQ 7
40
-#define ARCH_GIC_MAINT_IRQ 9
41
-#define ARCH_TIMER_VIRT_IRQ 11
42
-#define ARCH_TIMER_S_EL1_IRQ 13
43
-#define ARCH_TIMER_NS_EL1_IRQ 14
44
-#define ARCH_TIMER_NS_EL2_IRQ 10
45
-#define ARCH_TIMER_NS_EL2_VIRT_IRQ 12
46
-
47
enum {
48
SBSA_FLASH,
49
SBSA_MEM,
50
@@ -XXX,XX +XXX,XX @@ static void create_gic(SBSAMachineState *sms, MemoryRegion *mem)
51
*/
52
for (i = 0; i < smp_cpus; i++) {
53
DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
54
- int ppibase = NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
55
+ int intidbase = NUM_IRQS + i * GIC_INTERNAL;
56
int irq;
57
/*
58
* Mapping from the output timer irq lines from the CPU to the
59
@@ -XXX,XX +XXX,XX @@ static void create_gic(SBSAMachineState *sms, MemoryRegion *mem)
60
for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
61
qdev_connect_gpio_out(cpudev, irq,
62
qdev_get_gpio_in(sms->gic,
63
- ppibase + timer_irq[irq]));
64
+ intidbase + timer_irq[irq]));
65
}
66
67
qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", 0,
68
- qdev_get_gpio_in(sms->gic, ppibase
69
+ qdev_get_gpio_in(sms->gic,
70
+ intidbase
71
+ ARCH_GIC_MAINT_IRQ));
72
+
73
qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
74
- qdev_get_gpio_in(sms->gic, ppibase
75
+ qdev_get_gpio_in(sms->gic,
76
+ intidbase
77
+ VIRTUAL_PMU_IRQ));
78
79
sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
29
--
80
--
30
2.20.1
81
2.34.1
31
32
diff view generated by jsdifflib
1
From: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
1
From: Cornelia Huck <cohuck@redhat.com>
2
2
3
Signed-off-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
3
We can neaten the code by switching to the kvm_set_one_reg function.
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
5
Reviewed-by: Gavin Shan <gshan@redhat.com>
6
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20231010142453.224369-2-cohuck@redhat.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
---
11
---
7
target/arm/cpu64.c | 1 +
12
target/arm/kvm.c | 13 +++------
8
1 file changed, 1 insertion(+)
13
target/arm/kvm64.c | 66 +++++++++++++---------------------------------
9
14
2 files changed, 21 insertions(+), 58 deletions(-)
10
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
15
16
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
11
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
12
--- a/target/arm/cpu64.c
18
--- a/target/arm/kvm.c
13
+++ b/target/arm/cpu64.c
19
+++ b/target/arm/kvm.c
14
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
20
@@ -XXX,XX +XXX,XX @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level)
15
t = cpu->isar.id_aa64mmfr2;
21
bool ok = true;
16
t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1);
22
17
t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* TTCNP */
23
for (i = 0; i < cpu->cpreg_array_len; i++) {
18
+ t = FIELD_DP64(t, ID_AA64MMFR2, ST, 1); /* TTST */
24
- struct kvm_one_reg r;
19
cpu->isar.id_aa64mmfr2 = t;
25
uint64_t regidx = cpu->cpreg_indexes[i];
20
26
uint32_t v32;
21
/* Replicate the same data to the 32-bit id registers. */
27
int ret;
28
@@ -XXX,XX +XXX,XX @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level)
29
continue;
30
}
31
32
- r.id = regidx;
33
switch (regidx & KVM_REG_SIZE_MASK) {
34
case KVM_REG_SIZE_U32:
35
v32 = cpu->cpreg_values[i];
36
- r.addr = (uintptr_t)&v32;
37
+ ret = kvm_set_one_reg(cs, regidx, &v32);
38
break;
39
case KVM_REG_SIZE_U64:
40
- r.addr = (uintptr_t)(cpu->cpreg_values + i);
41
+ ret = kvm_set_one_reg(cs, regidx, cpu->cpreg_values + i);
42
break;
43
default:
44
g_assert_not_reached();
45
}
46
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
47
if (ret) {
48
/* We might fail for "unknown register" and also for
49
* "you tried to set a register which is constant with
50
@@ -XXX,XX +XXX,XX @@ void kvm_arm_get_virtual_time(CPUState *cs)
51
void kvm_arm_put_virtual_time(CPUState *cs)
52
{
53
ARMCPU *cpu = ARM_CPU(cs);
54
- struct kvm_one_reg reg = {
55
- .id = KVM_REG_ARM_TIMER_CNT,
56
- .addr = (uintptr_t)&cpu->kvm_vtime,
57
- };
58
int ret;
59
60
if (!cpu->kvm_vtime_dirty) {
61
return;
62
}
63
64
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
65
+ ret = kvm_set_one_reg(cs, KVM_REG_ARM_TIMER_CNT, &cpu->kvm_vtime);
66
if (ret) {
67
error_report("Failed to set KVM_REG_ARM_TIMER_CNT");
68
abort();
69
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
70
index XXXXXXX..XXXXXXX 100644
71
--- a/target/arm/kvm64.c
72
+++ b/target/arm/kvm64.c
73
@@ -XXX,XX +XXX,XX @@ static int kvm_arm_sve_set_vls(CPUState *cs)
74
{
75
ARMCPU *cpu = ARM_CPU(cs);
76
uint64_t vls[KVM_ARM64_SVE_VLS_WORDS] = { cpu->sve_vq.map };
77
- struct kvm_one_reg reg = {
78
- .id = KVM_REG_ARM64_SVE_VLS,
79
- .addr = (uint64_t)&vls[0],
80
- };
81
82
assert(cpu->sve_max_vq <= KVM_ARM64_SVE_VQ_MAX);
83
84
- return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
85
+ return kvm_set_one_reg(cs, KVM_REG_ARM64_SVE_VLS, &vls[0]);
86
}
87
88
#define ARM_CPU_ID_MPIDR 3, 0, 0, 0, 5
89
@@ -XXX,XX +XXX,XX @@ static void kvm_inject_arm_sea(CPUState *c)
90
static int kvm_arch_put_fpsimd(CPUState *cs)
91
{
92
CPUARMState *env = &ARM_CPU(cs)->env;
93
- struct kvm_one_reg reg;
94
int i, ret;
95
96
for (i = 0; i < 32; i++) {
97
uint64_t *q = aa64_vfp_qreg(env, i);
98
#if HOST_BIG_ENDIAN
99
uint64_t fp_val[2] = { q[1], q[0] };
100
- reg.addr = (uintptr_t)fp_val;
101
+ ret = kvm_set_one_reg(cs, AARCH64_SIMD_CORE_REG(fp_regs.vregs[i]),
102
+ fp_val);
103
#else
104
- reg.addr = (uintptr_t)q;
105
+ ret = kvm_set_one_reg(cs, AARCH64_SIMD_CORE_REG(fp_regs.vregs[i]), q);
106
#endif
107
- reg.id = AARCH64_SIMD_CORE_REG(fp_regs.vregs[i]);
108
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
109
if (ret) {
110
return ret;
111
}
112
@@ -XXX,XX +XXX,XX @@ static int kvm_arch_put_sve(CPUState *cs)
113
CPUARMState *env = &cpu->env;
114
uint64_t tmp[ARM_MAX_VQ * 2];
115
uint64_t *r;
116
- struct kvm_one_reg reg;
117
int n, ret;
118
119
for (n = 0; n < KVM_ARM64_SVE_NUM_ZREGS; ++n) {
120
r = sve_bswap64(tmp, &env->vfp.zregs[n].d[0], cpu->sve_max_vq * 2);
121
- reg.addr = (uintptr_t)r;
122
- reg.id = KVM_REG_ARM64_SVE_ZREG(n, 0);
123
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
124
+ ret = kvm_set_one_reg(cs, KVM_REG_ARM64_SVE_ZREG(n, 0), r);
125
if (ret) {
126
return ret;
127
}
128
@@ -XXX,XX +XXX,XX @@ static int kvm_arch_put_sve(CPUState *cs)
129
for (n = 0; n < KVM_ARM64_SVE_NUM_PREGS; ++n) {
130
r = sve_bswap64(tmp, r = &env->vfp.pregs[n].p[0],
131
DIV_ROUND_UP(cpu->sve_max_vq * 2, 8));
132
- reg.addr = (uintptr_t)r;
133
- reg.id = KVM_REG_ARM64_SVE_PREG(n, 0);
134
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
135
+ ret = kvm_set_one_reg(cs, KVM_REG_ARM64_SVE_PREG(n, 0), r);
136
if (ret) {
137
return ret;
138
}
139
@@ -XXX,XX +XXX,XX @@ static int kvm_arch_put_sve(CPUState *cs)
140
141
r = sve_bswap64(tmp, &env->vfp.pregs[FFR_PRED_NUM].p[0],
142
DIV_ROUND_UP(cpu->sve_max_vq * 2, 8));
143
- reg.addr = (uintptr_t)r;
144
- reg.id = KVM_REG_ARM64_SVE_FFR(0);
145
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
146
+ ret = kvm_set_one_reg(cs, KVM_REG_ARM64_SVE_FFR(0), r);
147
if (ret) {
148
return ret;
149
}
150
@@ -XXX,XX +XXX,XX @@ static int kvm_arch_put_sve(CPUState *cs)
151
152
int kvm_arch_put_registers(CPUState *cs, int level)
153
{
154
- struct kvm_one_reg reg;
155
uint64_t val;
156
uint32_t fpr;
157
int i, ret;
158
@@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level)
159
}
160
161
for (i = 0; i < 31; i++) {
162
- reg.id = AARCH64_CORE_REG(regs.regs[i]);
163
- reg.addr = (uintptr_t) &env->xregs[i];
164
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
165
+ ret = kvm_set_one_reg(cs, AARCH64_CORE_REG(regs.regs[i]),
166
+ &env->xregs[i]);
167
if (ret) {
168
return ret;
169
}
170
@@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level)
171
*/
172
aarch64_save_sp(env, 1);
173
174
- reg.id = AARCH64_CORE_REG(regs.sp);
175
- reg.addr = (uintptr_t) &env->sp_el[0];
176
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
177
+ ret = kvm_set_one_reg(cs, AARCH64_CORE_REG(regs.sp), &env->sp_el[0]);
178
if (ret) {
179
return ret;
180
}
181
182
- reg.id = AARCH64_CORE_REG(sp_el1);
183
- reg.addr = (uintptr_t) &env->sp_el[1];
184
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
185
+ ret = kvm_set_one_reg(cs, AARCH64_CORE_REG(sp_el1), &env->sp_el[1]);
186
if (ret) {
187
return ret;
188
}
189
@@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level)
190
} else {
191
val = cpsr_read(env);
192
}
193
- reg.id = AARCH64_CORE_REG(regs.pstate);
194
- reg.addr = (uintptr_t) &val;
195
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
196
+ ret = kvm_set_one_reg(cs, AARCH64_CORE_REG(regs.pstate), &val);
197
if (ret) {
198
return ret;
199
}
200
201
- reg.id = AARCH64_CORE_REG(regs.pc);
202
- reg.addr = (uintptr_t) &env->pc;
203
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
204
+ ret = kvm_set_one_reg(cs, AARCH64_CORE_REG(regs.pc), &env->pc);
205
if (ret) {
206
return ret;
207
}
208
209
- reg.id = AARCH64_CORE_REG(elr_el1);
210
- reg.addr = (uintptr_t) &env->elr_el[1];
211
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
212
+ ret = kvm_set_one_reg(cs, AARCH64_CORE_REG(elr_el1), &env->elr_el[1]);
213
if (ret) {
214
return ret;
215
}
216
@@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level)
217
218
/* KVM 0-4 map to QEMU banks 1-5 */
219
for (i = 0; i < KVM_NR_SPSR; i++) {
220
- reg.id = AARCH64_CORE_REG(spsr[i]);
221
- reg.addr = (uintptr_t) &env->banked_spsr[i + 1];
222
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
223
+ ret = kvm_set_one_reg(cs, AARCH64_CORE_REG(spsr[i]),
224
+ &env->banked_spsr[i + 1]);
225
if (ret) {
226
return ret;
227
}
228
@@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level)
229
return ret;
230
}
231
232
- reg.addr = (uintptr_t)(&fpr);
233
fpr = vfp_get_fpsr(env);
234
- reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpsr);
235
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
236
+ ret = kvm_set_one_reg(cs, AARCH64_SIMD_CTRL_REG(fp_regs.fpsr), &fpr);
237
if (ret) {
238
return ret;
239
}
240
241
- reg.addr = (uintptr_t)(&fpr);
242
fpr = vfp_get_fpcr(env);
243
- reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpcr);
244
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
245
+ ret = kvm_set_one_reg(cs, AARCH64_SIMD_CTRL_REG(fp_regs.fpcr), &fpr);
246
if (ret) {
247
return ret;
248
}
22
--
249
--
23
2.20.1
250
2.34.1
24
251
25
252
diff view generated by jsdifflib
1
From: Roman Bolshakov <r.bolshakov@yadro.com>
1
From: Cornelia Huck <cohuck@redhat.com>
2
2
3
ui/cocoa.m:1188:44: warning: 'openFile:' is deprecated: first deprecated in macOS 11.0 - Use -[NSWorkspace openURL:] instead.
3
We can neaten the code by switching the callers that work on a
4
[-Wdeprecated-declarations]
4
CPUstate to the kvm_get_one_reg function.
5
if ([[NSWorkspace sharedWorkspace] openFile: full_file_path] == YES) {
5
6
^
6
Reviewed-by: Gavin Shan <gshan@redhat.com>
7
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSWorkspace.h:350:1: note:
7
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
8
'openFile:' has been explicitly marked deprecated here
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
- (BOOL)openFile:(NSString *)fullPath API_DEPRECATED("Use -[NSWorkspace openURL:] instead.", macos(10.0, 11.0));
9
Message-id: 20231010142453.224369-3-cohuck@redhat.com
10
^
11
12
Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20210102150718.47618-1-r.bolshakov@yadro.com
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
12
---
17
ui/cocoa.m | 5 ++++-
13
target/arm/kvm.c | 15 +++---------
18
1 file changed, 4 insertions(+), 1 deletion(-)
14
target/arm/kvm64.c | 57 ++++++++++++----------------------------------
19
15
2 files changed, 18 insertions(+), 54 deletions(-)
20
diff --git a/ui/cocoa.m b/ui/cocoa.m
16
17
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
21
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
22
--- a/ui/cocoa.m
19
--- a/target/arm/kvm.c
23
+++ b/ui/cocoa.m
20
+++ b/target/arm/kvm.c
24
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
21
@@ -XXX,XX +XXX,XX @@ bool write_kvmstate_to_list(ARMCPU *cpu)
25
/* Where to look for local files */
22
bool ok = true;
26
NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"docs/"};
23
27
NSString *full_file_path;
24
for (i = 0; i < cpu->cpreg_array_len; i++) {
28
+ NSURL *full_file_url;
25
- struct kvm_one_reg r;
29
26
uint64_t regidx = cpu->cpreg_indexes[i];
30
/* iterate thru the possible paths until the file is found */
27
uint32_t v32;
31
int index;
28
int ret;
32
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
29
33
full_file_path = [full_file_path stringByDeletingLastPathComponent];
30
- r.id = regidx;
34
full_file_path = [NSString stringWithFormat: @"%@/%@%@", full_file_path,
31
-
35
path_array[index], filename];
32
switch (regidx & KVM_REG_SIZE_MASK) {
36
- if ([[NSWorkspace sharedWorkspace] openFile: full_file_path] == YES) {
33
case KVM_REG_SIZE_U32:
37
+ full_file_url = [NSURL fileURLWithPath: full_file_path
34
- r.addr = (uintptr_t)&v32;
38
+ isDirectory: false];
35
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
39
+ if ([[NSWorkspace sharedWorkspace] openURL: full_file_url] == YES) {
36
+ ret = kvm_get_one_reg(cs, regidx, &v32);
40
return;
37
if (!ret) {
41
}
38
cpu->cpreg_values[i] = v32;
39
}
40
break;
41
case KVM_REG_SIZE_U64:
42
- r.addr = (uintptr_t)(cpu->cpreg_values + i);
43
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
44
+ ret = kvm_get_one_reg(cs, regidx, cpu->cpreg_values + i);
45
break;
46
default:
47
g_assert_not_reached();
48
@@ -XXX,XX +XXX,XX @@ int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu)
49
void kvm_arm_get_virtual_time(CPUState *cs)
50
{
51
ARMCPU *cpu = ARM_CPU(cs);
52
- struct kvm_one_reg reg = {
53
- .id = KVM_REG_ARM_TIMER_CNT,
54
- .addr = (uintptr_t)&cpu->kvm_vtime,
55
- };
56
int ret;
57
58
if (cpu->kvm_vtime_dirty) {
59
return;
60
}
61
62
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
63
+ ret = kvm_get_one_reg(cs, KVM_REG_ARM_TIMER_CNT, &cpu->kvm_vtime);
64
if (ret) {
65
error_report("Failed to get KVM_REG_ARM_TIMER_CNT");
66
abort();
67
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/target/arm/kvm64.c
70
+++ b/target/arm/kvm64.c
71
@@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level)
72
static int kvm_arch_get_fpsimd(CPUState *cs)
73
{
74
CPUARMState *env = &ARM_CPU(cs)->env;
75
- struct kvm_one_reg reg;
76
int i, ret;
77
78
for (i = 0; i < 32; i++) {
79
uint64_t *q = aa64_vfp_qreg(env, i);
80
- reg.id = AARCH64_SIMD_CORE_REG(fp_regs.vregs[i]);
81
- reg.addr = (uintptr_t)q;
82
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
83
+ ret = kvm_get_one_reg(cs, AARCH64_SIMD_CORE_REG(fp_regs.vregs[i]), q);
84
if (ret) {
85
return ret;
86
} else {
87
@@ -XXX,XX +XXX,XX @@ static int kvm_arch_get_sve(CPUState *cs)
88
{
89
ARMCPU *cpu = ARM_CPU(cs);
90
CPUARMState *env = &cpu->env;
91
- struct kvm_one_reg reg;
92
uint64_t *r;
93
int n, ret;
94
95
for (n = 0; n < KVM_ARM64_SVE_NUM_ZREGS; ++n) {
96
r = &env->vfp.zregs[n].d[0];
97
- reg.addr = (uintptr_t)r;
98
- reg.id = KVM_REG_ARM64_SVE_ZREG(n, 0);
99
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
100
+ ret = kvm_get_one_reg(cs, KVM_REG_ARM64_SVE_ZREG(n, 0), r);
101
if (ret) {
102
return ret;
103
}
104
@@ -XXX,XX +XXX,XX @@ static int kvm_arch_get_sve(CPUState *cs)
105
106
for (n = 0; n < KVM_ARM64_SVE_NUM_PREGS; ++n) {
107
r = &env->vfp.pregs[n].p[0];
108
- reg.addr = (uintptr_t)r;
109
- reg.id = KVM_REG_ARM64_SVE_PREG(n, 0);
110
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
111
+ ret = kvm_get_one_reg(cs, KVM_REG_ARM64_SVE_PREG(n, 0), r);
112
if (ret) {
113
return ret;
114
}
115
@@ -XXX,XX +XXX,XX @@ static int kvm_arch_get_sve(CPUState *cs)
116
}
117
118
r = &env->vfp.pregs[FFR_PRED_NUM].p[0];
119
- reg.addr = (uintptr_t)r;
120
- reg.id = KVM_REG_ARM64_SVE_FFR(0);
121
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
122
+ ret = kvm_get_one_reg(cs, KVM_REG_ARM64_SVE_FFR(0), r);
123
if (ret) {
124
return ret;
125
}
126
@@ -XXX,XX +XXX,XX @@ static int kvm_arch_get_sve(CPUState *cs)
127
128
int kvm_arch_get_registers(CPUState *cs)
129
{
130
- struct kvm_one_reg reg;
131
uint64_t val;
132
unsigned int el;
133
uint32_t fpr;
134
@@ -XXX,XX +XXX,XX @@ int kvm_arch_get_registers(CPUState *cs)
135
CPUARMState *env = &cpu->env;
136
137
for (i = 0; i < 31; i++) {
138
- reg.id = AARCH64_CORE_REG(regs.regs[i]);
139
- reg.addr = (uintptr_t) &env->xregs[i];
140
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
141
+ ret = kvm_get_one_reg(cs, AARCH64_CORE_REG(regs.regs[i]),
142
+ &env->xregs[i]);
143
if (ret) {
144
return ret;
145
}
146
}
147
148
- reg.id = AARCH64_CORE_REG(regs.sp);
149
- reg.addr = (uintptr_t) &env->sp_el[0];
150
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
151
+ ret = kvm_get_one_reg(cs, AARCH64_CORE_REG(regs.sp), &env->sp_el[0]);
152
if (ret) {
153
return ret;
154
}
155
156
- reg.id = AARCH64_CORE_REG(sp_el1);
157
- reg.addr = (uintptr_t) &env->sp_el[1];
158
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
159
+ ret = kvm_get_one_reg(cs, AARCH64_CORE_REG(sp_el1), &env->sp_el[1]);
160
if (ret) {
161
return ret;
162
}
163
164
- reg.id = AARCH64_CORE_REG(regs.pstate);
165
- reg.addr = (uintptr_t) &val;
166
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
167
+ ret = kvm_get_one_reg(cs, AARCH64_CORE_REG(regs.pstate), &val);
168
if (ret) {
169
return ret;
170
}
171
@@ -XXX,XX +XXX,XX @@ int kvm_arch_get_registers(CPUState *cs)
172
*/
173
aarch64_restore_sp(env, 1);
174
175
- reg.id = AARCH64_CORE_REG(regs.pc);
176
- reg.addr = (uintptr_t) &env->pc;
177
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
178
+ ret = kvm_get_one_reg(cs, AARCH64_CORE_REG(regs.pc), &env->pc);
179
if (ret) {
180
return ret;
181
}
182
@@ -XXX,XX +XXX,XX @@ int kvm_arch_get_registers(CPUState *cs)
183
aarch64_sync_64_to_32(env);
184
}
185
186
- reg.id = AARCH64_CORE_REG(elr_el1);
187
- reg.addr = (uintptr_t) &env->elr_el[1];
188
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
189
+ ret = kvm_get_one_reg(cs, AARCH64_CORE_REG(elr_el1), &env->elr_el[1]);
190
if (ret) {
191
return ret;
192
}
193
@@ -XXX,XX +XXX,XX @@ int kvm_arch_get_registers(CPUState *cs)
194
* KVM SPSRs 0-4 map to QEMU banks 1-5
195
*/
196
for (i = 0; i < KVM_NR_SPSR; i++) {
197
- reg.id = AARCH64_CORE_REG(spsr[i]);
198
- reg.addr = (uintptr_t) &env->banked_spsr[i + 1];
199
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
200
+ ret = kvm_get_one_reg(cs, AARCH64_CORE_REG(spsr[i]),
201
+ &env->banked_spsr[i + 1]);
202
if (ret) {
203
return ret;
204
}
205
@@ -XXX,XX +XXX,XX @@ int kvm_arch_get_registers(CPUState *cs)
206
return ret;
207
}
208
209
- reg.addr = (uintptr_t)(&fpr);
210
- reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpsr);
211
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
212
+ ret = kvm_get_one_reg(cs, AARCH64_SIMD_CTRL_REG(fp_regs.fpsr), &fpr);
213
if (ret) {
214
return ret;
215
}
216
vfp_set_fpsr(env, fpr);
217
218
- reg.addr = (uintptr_t)(&fpr);
219
- reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpcr);
220
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
221
+ ret = kvm_get_one_reg(cs, AARCH64_SIMD_CTRL_REG(fp_regs.fpcr), &fpr);
222
if (ret) {
223
return ret;
42
}
224
}
43
--
225
--
44
2.20.1
226
2.34.1
45
227
46
228
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
For the Thumb T32 encoding of LDM, if only a single register is
2
specified in the register list this instruction is UNPREDICTABLE,
3
with the following choices:
4
* instruction UNDEFs
5
* instruction is a NOP
6
* instruction loads a single register
7
* instruction loads an unspecified set of registers
2
8
3
A device shouldn't access its parent object which is QOM internal.
9
Currently we choose to UNDEF (a behaviour chosen in commit
4
Instead it should use type cast for this purporse. This patch fixes this
10
4b222545dbf30 in 2019; previously we treated it as "load the
5
issue for all NPCM7XX Devices.
11
specified single register").
6
12
7
Signed-off-by: Hao Wu <wuhaotsh@google.com>
13
Unfortunately there is real world code out there (which shipped in at
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
least Android 11, 12 and 13) which incorrectly uses this
9
Message-id: 20210108190945.949196-7-wuhaotsh@google.com
15
UNPREDICTABLE insn on the assumption that it does a single register
16
load, which is (presumably) what it happens to do on real hardware,
17
and is also what it does on the equivalent A32 encoding.
18
19
Revert to the pre-4b222545dbf30 behaviour of not UNDEFing
20
for this T32 encoding.
21
22
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1799
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
26
Message-id: 20230927101853.39288-1-peter.maydell@linaro.org
11
---
27
---
12
hw/arm/npcm7xx_boards.c | 2 +-
28
target/arm/tcg/translate.c | 37 +++++++++++++++++++++++--------------
13
hw/mem/npcm7xx_mc.c | 2 +-
29
1 file changed, 23 insertions(+), 14 deletions(-)
14
hw/misc/npcm7xx_clk.c | 2 +-
15
hw/misc/npcm7xx_gcr.c | 2 +-
16
hw/misc/npcm7xx_rng.c | 2 +-
17
hw/nvram/npcm7xx_otp.c | 2 +-
18
hw/ssi/npcm7xx_fiu.c | 2 +-
19
7 files changed, 7 insertions(+), 7 deletions(-)
20
30
21
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
31
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
22
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/npcm7xx_boards.c
33
--- a/target/arm/tcg/translate.c
24
+++ b/hw/arm/npcm7xx_boards.c
34
+++ b/target/arm/tcg/translate.c
25
@@ -XXX,XX +XXX,XX @@ static NPCM7xxState *npcm7xx_create_soc(MachineState *machine,
35
@@ -XXX,XX +XXX,XX @@ static void op_addr_block_post(DisasContext *s, arg_ldst_block *a,
26
uint32_t hw_straps)
36
}
37
}
38
39
-static bool op_stm(DisasContext *s, arg_ldst_block *a, int min_n)
40
+static bool op_stm(DisasContext *s, arg_ldst_block *a)
27
{
41
{
28
NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_GET_CLASS(machine);
42
int i, j, n, list, mem_idx;
29
- MachineClass *mc = &nmc->parent;
43
bool user = a->u;
30
+ MachineClass *mc = MACHINE_CLASS(nmc);
44
@@ -XXX,XX +XXX,XX @@ static bool op_stm(DisasContext *s, arg_ldst_block *a, int min_n)
31
Object *obj;
45
32
46
list = a->list;
33
if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
47
n = ctpop16(list);
34
diff --git a/hw/mem/npcm7xx_mc.c b/hw/mem/npcm7xx_mc.c
48
- if (n < min_n || a->rn == 15) {
35
index XXXXXXX..XXXXXXX 100644
49
+ /*
36
--- a/hw/mem/npcm7xx_mc.c
50
+ * This is UNPREDICTABLE for n < 1 in all encodings, and we choose
37
+++ b/hw/mem/npcm7xx_mc.c
51
+ * to UNDEF. In the T32 STM encoding n == 1 is also UNPREDICTABLE,
38
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_mc_realize(DeviceState *dev, Error **errp)
52
+ * but hardware treats it like the A32 version and implements the
39
53
+ * single-register-store, and some in-the-wild (buggy) software
40
memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_mc_ops, s, "regs",
54
+ * assumes that, so we don't UNDEF on that case.
41
NPCM7XX_MC_REGS_SIZE);
55
+ */
42
- sysbus_init_mmio(&s->parent, &s->mmio);
56
+ if (n < 1 || a->rn == 15) {
43
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio);
57
unallocated_encoding(s);
58
return true;
59
}
60
@@ -XXX,XX +XXX,XX @@ static bool op_stm(DisasContext *s, arg_ldst_block *a, int min_n)
61
62
static bool trans_STM(DisasContext *s, arg_ldst_block *a)
63
{
64
- /* BitCount(list) < 1 is UNPREDICTABLE */
65
- return op_stm(s, a, 1);
66
+ return op_stm(s, a);
44
}
67
}
45
68
46
static void npcm7xx_mc_class_init(ObjectClass *klass, void *data)
69
static bool trans_STM_t32(DisasContext *s, arg_ldst_block *a)
47
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
70
@@ -XXX,XX +XXX,XX @@ static bool trans_STM_t32(DisasContext *s, arg_ldst_block *a)
48
index XXXXXXX..XXXXXXX 100644
71
unallocated_encoding(s);
49
--- a/hw/misc/npcm7xx_clk.c
72
return true;
50
+++ b/hw/misc/npcm7xx_clk.c
73
}
51
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_init(Object *obj)
74
- /* BitCount(list) < 2 is UNPREDICTABLE */
52
75
- return op_stm(s, a, 2);
53
memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
76
+ return op_stm(s, a);
54
TYPE_NPCM7XX_CLK, 4 * KiB);
55
- sysbus_init_mmio(&s->parent, &s->iomem);
56
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
57
}
77
}
58
78
59
static int npcm7xx_clk_post_load(void *opaque, int version_id)
79
-static bool do_ldm(DisasContext *s, arg_ldst_block *a, int min_n)
60
diff --git a/hw/misc/npcm7xx_gcr.c b/hw/misc/npcm7xx_gcr.c
80
+static bool do_ldm(DisasContext *s, arg_ldst_block *a)
61
index XXXXXXX..XXXXXXX 100644
81
{
62
--- a/hw/misc/npcm7xx_gcr.c
82
int i, j, n, list, mem_idx;
63
+++ b/hw/misc/npcm7xx_gcr.c
83
bool loaded_base;
64
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_gcr_init(Object *obj)
84
@@ -XXX,XX +XXX,XX @@ static bool do_ldm(DisasContext *s, arg_ldst_block *a, int min_n)
65
85
66
memory_region_init_io(&s->iomem, obj, &npcm7xx_gcr_ops, s,
86
list = a->list;
67
TYPE_NPCM7XX_GCR, 4 * KiB);
87
n = ctpop16(list);
68
- sysbus_init_mmio(&s->parent, &s->iomem);
88
- if (n < min_n || a->rn == 15) {
69
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
89
+ /*
90
+ * This is UNPREDICTABLE for n < 1 in all encodings, and we choose
91
+ * to UNDEF. In the T32 LDM encoding n == 1 is also UNPREDICTABLE,
92
+ * but hardware treats it like the A32 version and implements the
93
+ * single-register-load, and some in-the-wild (buggy) software
94
+ * assumes that, so we don't UNDEF on that case.
95
+ */
96
+ if (n < 1 || a->rn == 15) {
97
unallocated_encoding(s);
98
return true;
99
}
100
@@ -XXX,XX +XXX,XX @@ static bool trans_LDM_a32(DisasContext *s, arg_ldst_block *a)
101
unallocated_encoding(s);
102
return true;
103
}
104
- /* BitCount(list) < 1 is UNPREDICTABLE */
105
- return do_ldm(s, a, 1);
106
+ return do_ldm(s, a);
70
}
107
}
71
108
72
static const VMStateDescription vmstate_npcm7xx_gcr = {
109
static bool trans_LDM_t32(DisasContext *s, arg_ldst_block *a)
73
diff --git a/hw/misc/npcm7xx_rng.c b/hw/misc/npcm7xx_rng.c
110
@@ -XXX,XX +XXX,XX @@ static bool trans_LDM_t32(DisasContext *s, arg_ldst_block *a)
74
index XXXXXXX..XXXXXXX 100644
111
unallocated_encoding(s);
75
--- a/hw/misc/npcm7xx_rng.c
112
return true;
76
+++ b/hw/misc/npcm7xx_rng.c
113
}
77
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_rng_init(Object *obj)
114
- /* BitCount(list) < 2 is UNPREDICTABLE */
78
115
- return do_ldm(s, a, 2);
79
memory_region_init_io(&s->iomem, obj, &npcm7xx_rng_ops, s, "regs",
116
+ return do_ldm(s, a);
80
NPCM7XX_RNG_REGS_SIZE);
81
- sysbus_init_mmio(&s->parent, &s->iomem);
82
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
83
}
117
}
84
118
85
static const VMStateDescription vmstate_npcm7xx_rng = {
119
static bool trans_LDM_t16(DisasContext *s, arg_ldst_block *a)
86
diff --git a/hw/nvram/npcm7xx_otp.c b/hw/nvram/npcm7xx_otp.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/hw/nvram/npcm7xx_otp.c
89
+++ b/hw/nvram/npcm7xx_otp.c
90
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_otp_realize(DeviceState *dev, Error **errp)
91
{
120
{
92
NPCM7xxOTPClass *oc = NPCM7XX_OTP_GET_CLASS(dev);
121
/* Writeback is conditional on the base register not being loaded. */
93
NPCM7xxOTPState *s = NPCM7XX_OTP(dev);
122
a->w = !(a->list & (1 << a->rn));
94
- SysBusDevice *sbd = &s->parent;
123
- /* BitCount(list) < 1 is UNPREDICTABLE */
95
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
124
- return do_ldm(s, a, 1);
96
125
+ return do_ldm(s, a);
97
memset(s->array, 0, sizeof(s->array));
126
}
98
127
99
diff --git a/hw/ssi/npcm7xx_fiu.c b/hw/ssi/npcm7xx_fiu.c
128
static bool trans_CLRM(DisasContext *s, arg_CLRM *a)
100
index XXXXXXX..XXXXXXX 100644
101
--- a/hw/ssi/npcm7xx_fiu.c
102
+++ b/hw/ssi/npcm7xx_fiu.c
103
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_fiu_hold_reset(Object *obj)
104
static void npcm7xx_fiu_realize(DeviceState *dev, Error **errp)
105
{
106
NPCM7xxFIUState *s = NPCM7XX_FIU(dev);
107
- SysBusDevice *sbd = &s->parent;
108
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
109
int i;
110
111
if (s->cs_count <= 0) {
112
--
129
--
113
2.20.1
130
2.34.1
114
131
115
132
diff view generated by jsdifflib
1
The lan9118 code mostly uses symbolic constants for register offsets;
1
Update the SMMUv3 ID register bit field definitions to the
2
the exceptions are those which the datasheet doesn't give an official
2
set in the most recent specification (IHI0700 F.a).
3
symbolic name to.
4
5
Add some names for the registers which don't already have them, based
6
on the longer names they are given in the memory map.
7
3
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210108180401.2263-3-peter.maydell@linaro.org
6
Reviewed-by: Mostafa Saleh <smostafa@google.com>
7
Reviewed-by: Eric Auger <eric.auger@redhat.com>
8
Message-id: 20230914145705.1648377-2-peter.maydell@linaro.org
11
---
9
---
12
hw/net/lan9118.c | 24 ++++++++++++++++++------
10
hw/arm/smmuv3-internal.h | 38 ++++++++++++++++++++++++++++++++++++++
13
1 file changed, 18 insertions(+), 6 deletions(-)
11
1 file changed, 38 insertions(+)
14
12
15
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
13
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/net/lan9118.c
15
--- a/hw/arm/smmuv3-internal.h
18
+++ b/hw/net/lan9118.c
16
+++ b/hw/arm/smmuv3-internal.h
19
@@ -XXX,XX +XXX,XX @@ do { hw_error("lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
17
@@ -XXX,XX +XXX,XX @@ REG32(IDR0, 0x0)
20
do { fprintf(stderr, "lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
18
FIELD(IDR0, S1P, 1 , 1)
21
#endif
19
FIELD(IDR0, TTF, 2 , 2)
22
20
FIELD(IDR0, COHACC, 4 , 1)
23
+/* The tx and rx fifo ports are a range of aliased 32-bit registers */
21
+ FIELD(IDR0, BTM, 5 , 1)
24
+#define RX_DATA_FIFO_PORT_FIRST 0x00
22
+ FIELD(IDR0, HTTU, 6 , 2)
25
+#define RX_DATA_FIFO_PORT_LAST 0x1f
23
+ FIELD(IDR0, DORMHINT, 8 , 1)
26
+#define TX_DATA_FIFO_PORT_FIRST 0x20
24
+ FIELD(IDR0, HYP, 9 , 1)
27
+#define TX_DATA_FIFO_PORT_LAST 0x3f
25
+ FIELD(IDR0, ATS, 10, 1)
26
+ FIELD(IDR0, NS1ATS, 11, 1)
27
FIELD(IDR0, ASID16, 12, 1)
28
+ FIELD(IDR0, MSI, 13, 1)
29
+ FIELD(IDR0, SEV, 14, 1)
30
+ FIELD(IDR0, ATOS, 15, 1)
31
+ FIELD(IDR0, PRI, 16, 1)
32
+ FIELD(IDR0, VMW, 17, 1)
33
FIELD(IDR0, VMID16, 18, 1)
34
+ FIELD(IDR0, CD2L, 19, 1)
35
+ FIELD(IDR0, VATOS, 20, 1)
36
FIELD(IDR0, TTENDIAN, 21, 2)
37
+ FIELD(IDR0, ATSRECERR, 23, 1)
38
FIELD(IDR0, STALL_MODEL, 24, 2)
39
FIELD(IDR0, TERM_MODEL, 26, 1)
40
FIELD(IDR0, STLEVEL, 27, 2)
41
+ FIELD(IDR0, RME_IMPL, 30, 1)
42
43
REG32(IDR1, 0x4)
44
FIELD(IDR1, SIDSIZE, 0 , 6)
45
+ FIELD(IDR1, SSIDSIZE, 6 , 5)
46
+ FIELD(IDR1, PRIQS, 11, 5)
47
FIELD(IDR1, EVENTQS, 16, 5)
48
FIELD(IDR1, CMDQS, 21, 5)
49
+ FIELD(IDR1, ATTR_PERMS_OVR, 26, 1)
50
+ FIELD(IDR1, ATTR_TYPES_OVR, 27, 1)
51
+ FIELD(IDR1, REL, 28, 1)
52
+ FIELD(IDR1, QUEUES_PRESET, 29, 1)
53
+ FIELD(IDR1, TABLES_PRESET, 30, 1)
54
+ FIELD(IDR1, ECMDQ, 31, 1)
55
56
#define SMMU_IDR1_SIDSIZE 16
57
#define SMMU_CMDQS 19
58
#define SMMU_EVENTQS 19
59
60
REG32(IDR2, 0x8)
61
+ FIELD(IDR2, BA_VATOS, 0, 10)
28
+
62
+
29
+#define RX_STATUS_FIFO_PORT 0x40
63
REG32(IDR3, 0xc)
30
+#define RX_STATUS_FIFO_PEEK 0x44
64
FIELD(IDR3, HAD, 2, 1);
31
+#define TX_STATUS_FIFO_PORT 0x48
65
+ FIELD(IDR3, PBHA, 3, 1);
32
+#define TX_STATUS_FIFO_PEEK 0x4c
66
+ FIELD(IDR3, XNX, 4, 1);
67
+ FIELD(IDR3, PPS, 5, 1);
68
+ FIELD(IDR3, MPAM, 7, 1);
69
+ FIELD(IDR3, FWB, 8, 1);
70
+ FIELD(IDR3, STT, 9, 1);
71
FIELD(IDR3, RIL, 10, 1);
72
FIELD(IDR3, BBML, 11, 2);
73
+ FIELD(IDR3, E0PD, 13, 1);
74
+ FIELD(IDR3, PTWNNC, 14, 1);
75
+ FIELD(IDR3, DPT, 15, 1);
33
+
76
+
34
#define CSR_ID_REV 0x50
77
REG32(IDR4, 0x10)
35
#define CSR_IRQ_CFG 0x54
78
+
36
#define CSR_INT_STS 0x58
79
REG32(IDR5, 0x14)
37
@@ -XXX,XX +XXX,XX @@ static void lan9118_writel(void *opaque, hwaddr offset,
80
FIELD(IDR5, OAS, 0, 3);
38
offset &= 0xff;
81
FIELD(IDR5, GRAN4K, 4, 1);
39
82
FIELD(IDR5, GRAN16K, 5, 1);
40
//DPRINTF("Write reg 0x%02x = 0x%08x\n", (int)offset, val);
83
FIELD(IDR5, GRAN64K, 6, 1);
41
- if (offset >= 0x20 && offset < 0x40) {
84
+ FIELD(IDR5, VAX, 10, 2);
42
+ if (offset >= TX_DATA_FIFO_PORT_FIRST &&
85
+ FIELD(IDR5, STALL_MAX, 16, 16);
43
+ offset <= TX_DATA_FIFO_PORT_LAST) {
86
44
/* TX FIFO */
87
#define SMMU_IDR5_OAS 4
45
tx_fifo_push(s, val);
88
46
return;
47
@@ -XXX,XX +XXX,XX @@ static uint64_t lan9118_readl(void *opaque, hwaddr offset,
48
lan9118_state *s = (lan9118_state *)opaque;
49
50
//DPRINTF("Read reg 0x%02x\n", (int)offset);
51
- if (offset < 0x20) {
52
+ if (offset <= RX_DATA_FIFO_PORT_LAST) {
53
/* RX FIFO */
54
return rx_fifo_pop(s);
55
}
56
switch (offset) {
57
- case 0x40:
58
+ case RX_STATUS_FIFO_PORT:
59
return rx_status_fifo_pop(s);
60
- case 0x44:
61
+ case RX_STATUS_FIFO_PEEK:
62
return s->rx_status_fifo[s->rx_status_fifo_head];
63
- case 0x48:
64
+ case TX_STATUS_FIFO_PORT:
65
return tx_status_fifo_pop(s);
66
- case 0x4c:
67
+ case TX_STATUS_FIFO_PEEK:
68
return s->tx_status_fifo[s->tx_status_fifo_head];
69
case CSR_ID_REV:
70
return 0x01180001;
71
--
89
--
72
2.20.1
90
2.34.1
73
74
diff view generated by jsdifflib
New patch
1
In smmuv3_init_regs() when we set the various bits in the ID
2
registers, we do this almost in order of the fields in the
3
registers, but not quite. Move the initialization of
4
SMMU_IDR3.RIL and SMMU_IDR5.OAS into their correct places.
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Mostafa Saleh <smostafa@google.com>
9
Reviewed-by: Eric Auger <eric.auger@redhat.com>
10
Message-id: 20230914145705.1648377-3-peter.maydell@linaro.org
11
---
12
hw/arm/smmuv3.c | 4 ++--
13
1 file changed, 2 insertions(+), 2 deletions(-)
14
15
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/smmuv3.c
18
+++ b/hw/arm/smmuv3.c
19
@@ -XXX,XX +XXX,XX @@ static void smmuv3_init_regs(SMMUv3State *s)
20
s->idr[1] = FIELD_DP32(s->idr[1], IDR1, EVENTQS, SMMU_EVENTQS);
21
s->idr[1] = FIELD_DP32(s->idr[1], IDR1, CMDQS, SMMU_CMDQS);
22
23
- s->idr[3] = FIELD_DP32(s->idr[3], IDR3, RIL, 1);
24
s->idr[3] = FIELD_DP32(s->idr[3], IDR3, HAD, 1);
25
+ s->idr[3] = FIELD_DP32(s->idr[3], IDR3, RIL, 1);
26
s->idr[3] = FIELD_DP32(s->idr[3], IDR3, BBML, 2);
27
28
+ s->idr[5] = FIELD_DP32(s->idr[5], IDR5, OAS, SMMU_IDR5_OAS); /* 44 bits */
29
/* 4K, 16K and 64K granule support */
30
s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN4K, 1);
31
s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN16K, 1);
32
s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN64K, 1);
33
- s->idr[5] = FIELD_DP32(s->idr[5], IDR5, OAS, SMMU_IDR5_OAS); /* 44 bits */
34
35
s->cmdq.base = deposit64(s->cmdq.base, 0, 5, SMMU_CMDQS);
36
s->cmdq.prod = 0;
37
--
38
2.34.1
diff view generated by jsdifflib
New patch
1
The SMMUv3.1-XNX feature is mandatory for an SMMUv3.1 if S2P is
2
supported, so we should theoretically have implemented it as part of
3
the recent S2P work. Fortunately, for us the implementation is a
4
no-op.
1
5
6
This feature is about interpretation of the stage 2 page table
7
descriptor XN bits, which control execute permissions.
8
9
For QEMU, the permission bits passed to an IOMMU (via MemTxAttrs and
10
IOMMUAccessFlags) only indicate read and write; we do not distinguish
11
data reads from instruction reads outside the CPU proper. In the
12
SMMU architecture's terms, our interconnect between the client device
13
and the SMMU doesn't have the ability to convey the INST attribute,
14
and we therefore use the default value of "data" for this attribute.
15
16
We also do not support the bits in the Stream Table Entry that can
17
override the on-the-bus transaction attribute permissions (we do not
18
set SMMU_IDR1.ATTR_PERMS_OVR=1).
19
20
These two things together mean that for our implementation, it never
21
has to deal with transactions with the INST attribute, and so it can
22
correctly ignore the XN bits entirely. So we already implement
23
FEAT_XNX's "XN field is now 2 bits, not 1" behaviour to the extent
24
that we need to.
25
26
Advertise the presence of the feature in SMMU_IDR3.XNX.
27
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
30
Reviewed-by: Mostafa Saleh <smostafa@google.com>
31
Reviewed-by: Eric Auger <eric.auger@redhat.com>
32
Message-id: 20230914145705.1648377-4-peter.maydell@linaro.org
33
---
34
hw/arm/smmuv3.c | 4 ++++
35
1 file changed, 4 insertions(+)
36
37
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/arm/smmuv3.c
40
+++ b/hw/arm/smmuv3.c
41
@@ -XXX,XX +XXX,XX @@ static void smmuv3_init_regs(SMMUv3State *s)
42
s->idr[1] = FIELD_DP32(s->idr[1], IDR1, CMDQS, SMMU_CMDQS);
43
44
s->idr[3] = FIELD_DP32(s->idr[3], IDR3, HAD, 1);
45
+ if (FIELD_EX32(s->idr[0], IDR0, S2P)) {
46
+ /* XNX is a stage-2-specific feature */
47
+ s->idr[3] = FIELD_DP32(s->idr[3], IDR3, XNX, 1);
48
+ }
49
s->idr[3] = FIELD_DP32(s->idr[3], IDR3, RIL, 1);
50
s->idr[3] = FIELD_DP32(s->idr[3], IDR3, BBML, 2);
51
52
--
53
2.34.1
diff view generated by jsdifflib
1
When we first converted our documentation to Sphinx, we split it into
1
FEAT_HPMN0 is a small feature which defines that it is valid for
2
multiple manuals (system, interop, tools, etc), which are all built
2
MDCR_EL2.HPMN to be set to 0, meaning "no PMU event counters provided
3
separately. The primary driver for this was wanting to be able to
3
to an EL1 guest" (previously this setting was reserved). QEMU's
4
avoid shipping the 'devel' manual to end-users. However, this is
4
implementation almost gets HPMN == 0 right, but we need to fix
5
working against the grain of the way Sphinx wants to be used and
5
one check in pmevcntr_is_64_bit(). That is enough for us to
6
causes some annoyances:
6
advertise the feature in the 'max' CPU.
7
* Cross-references between documents become much harder or
8
possibly impossible
9
* There is no single index to the whole documentation
10
* Within one manual there's no links or table-of-contents info
11
that lets you easily navigate to the others
12
* The devel manual doesn't get published on the QEMU website
13
(it would be nice to able to refer to it there)
14
7
15
Merely hiding our developer documentation from end users seems like
8
(We don't need to make the behaviour conditional on feature
16
it's not enough benefit for these costs. Combine all the
9
presence, because the FEAT_HPMN0 behaviour is within the range
17
documentation into a single manual (the same way that the readthedocs
10
of permitted UNPREDICTABLE behaviour for a non-FEAT_HPMN0
18
site builds it) and install the whole thing. The previous manual
11
implementation.)
19
divisions remain as the new top level sections in the manual.
20
21
* The per-manual conf.py files are no longer needed
22
* The man_pages[] specifications previously in each per-manual
23
conf.py move to the top level conf.py
24
* docs/meson.build logic is simplified as we now only need to run
25
Sphinx once for the HTML and then once for the manpages5B
26
* The old index.html.in that produced the top-level page with
27
links to each manual is no longer needed
28
29
Unfortunately this means that we now have to build the HTML
30
documentation into docs/manual in the build tree rather than directly
31
into docs/; otherwise it is too awkward to ensure we install only the
32
built manual and not also the dependency info, stamp file, etc. The
33
manual still ends up in the same place in the final installed
34
directory, but anybody who was consulting documentation from within
35
the build tree will have to adjust where they're looking.
36
12
37
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
38
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
39
Message-id: 20210108161416.21129-3-peter.maydell@linaro.org
15
Message-id: 20230921185445.3339214-1-peter.maydell@linaro.org
40
---
16
---
41
docs/conf.py | 46 ++++++++++++++++++++++++++++++-
17
docs/system/arm/emulation.rst | 1 +
42
docs/devel/conf.py | 15 -----------
18
target/arm/helper.c | 2 +-
43
docs/index.html.in | 17 ------------
19
target/arm/tcg/cpu32.c | 4 ++++
44
docs/interop/conf.py | 28 -------------------
20
target/arm/tcg/cpu64.c | 1 +
45
docs/meson.build | 64 +++++++++++++++++---------------------------
21
4 files changed, 7 insertions(+), 1 deletion(-)
46
docs/specs/conf.py | 16 -----------
47
docs/system/conf.py | 28 -------------------
48
docs/tools/conf.py | 37 -------------------------
49
docs/user/conf.py | 15 -----------
50
9 files changed, 70 insertions(+), 196 deletions(-)
51
delete mode 100644 docs/devel/conf.py
52
delete mode 100644 docs/index.html.in
53
delete mode 100644 docs/interop/conf.py
54
delete mode 100644 docs/specs/conf.py
55
delete mode 100644 docs/system/conf.py
56
delete mode 100644 docs/tools/conf.py
57
delete mode 100644 docs/user/conf.py
58
22
59
diff --git a/docs/conf.py b/docs/conf.py
23
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
60
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
61
--- a/docs/conf.py
25
--- a/docs/system/arm/emulation.rst
62
+++ b/docs/conf.py
26
+++ b/docs/system/arm/emulation.rst
63
@@ -XXX,XX +XXX,XX @@ latex_documents = [
27
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
64
28
- FEAT_HCX (Support for the HCRX_EL2 register)
65
# -- Options for manual page output ---------------------------------------
29
- FEAT_HPDS (Hierarchical permission disables)
66
# Individual manual/conf.py can override this to create man pages
30
- FEAT_HPDS2 (Translation table page-based hardware attributes)
67
-man_pages = []
31
+- FEAT_HPMN0 (Setting of MDCR_EL2.HPMN to zero)
68
+man_pages = [
32
- FEAT_I8MM (AArch64 Int8 matrix multiplication instructions)
69
+ ('interop/qemu-ga', 'qemu-ga',
33
- FEAT_IDST (ID space trap handling)
70
+ 'QEMU Guest Agent',
34
- FEAT_IESB (Implicit error synchronization event)
71
+ ['Michael Roth <mdroth@linux.vnet.ibm.com>'], 8),
35
diff --git a/target/arm/helper.c b/target/arm/helper.c
72
+ ('interop/qemu-ga-ref', 'qemu-ga-ref',
73
+ 'QEMU Guest Agent Protocol Reference',
74
+ [], 7),
75
+ ('interop/qemu-qmp-ref', 'qemu-qmp-ref',
76
+ 'QEMU QMP Reference Manual',
77
+ [], 7),
78
+ ('interop/qemu-storage-daemon-qmp-ref', 'qemu-storage-daemon-qmp-ref',
79
+ 'QEMU Storage Daemon QMP Reference Manual',
80
+ [], 7),
81
+ ('system/qemu-manpage', 'qemu',
82
+ 'QEMU User Documentation',
83
+ ['Fabrice Bellard'], 1),
84
+ ('system/qemu-block-drivers', 'qemu-block-drivers',
85
+ 'QEMU block drivers reference',
86
+ ['Fabrice Bellard and the QEMU Project developers'], 7),
87
+ ('system/qemu-cpu-models', 'qemu-cpu-models',
88
+ 'QEMU CPU Models',
89
+ ['The QEMU Project developers'], 7),
90
+ ('tools/qemu-img', 'qemu-img',
91
+ 'QEMU disk image utility',
92
+ ['Fabrice Bellard'], 1),
93
+ ('tools/qemu-nbd', 'qemu-nbd',
94
+ 'QEMU Disk Network Block Device Server',
95
+ ['Anthony Liguori <anthony@codemonkey.ws>'], 8),
96
+ ('tools/qemu-pr-helper', 'qemu-pr-helper',
97
+ 'QEMU persistent reservation helper',
98
+ [], 8),
99
+ ('tools/qemu-storage-daemon', 'qemu-storage-daemon',
100
+ 'QEMU storage daemon',
101
+ [], 1),
102
+ ('tools/qemu-trace-stap', 'qemu-trace-stap',
103
+ 'QEMU SystemTap trace tool',
104
+ [], 1),
105
+ ('tools/virtfs-proxy-helper', 'virtfs-proxy-helper',
106
+ 'QEMU 9p virtfs proxy filesystem helper',
107
+ ['M. Mohan Kumar'], 1),
108
+ ('tools/virtiofsd', 'virtiofsd',
109
+ 'QEMU virtio-fs shared file system daemon',
110
+ ['Stefan Hajnoczi <stefanha@redhat.com>',
111
+ 'Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>'], 1),
112
+]
113
114
# -- Options for Texinfo output -------------------------------------------
115
116
diff --git a/docs/devel/conf.py b/docs/devel/conf.py
117
deleted file mode 100644
118
index XXXXXXX..XXXXXXX
119
--- a/docs/devel/conf.py
120
+++ /dev/null
121
@@ -XXX,XX +XXX,XX @@
122
-# -*- coding: utf-8 -*-
123
-#
124
-# QEMU documentation build configuration file for the 'devel' manual.
125
-#
126
-# This includes the top level conf file and then makes any necessary tweaks.
127
-import sys
128
-import os
129
-
130
-qemu_docdir = os.path.abspath("..")
131
-parent_config = os.path.join(qemu_docdir, "conf.py")
132
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
133
-
134
-# This slightly misuses the 'description', but is the best way to get
135
-# the manual title to appear in the sidebar.
136
-html_theme_options['description'] = u'Developer''s Guide'
137
diff --git a/docs/index.html.in b/docs/index.html.in
138
deleted file mode 100644
139
index XXXXXXX..XXXXXXX
140
--- a/docs/index.html.in
141
+++ /dev/null
142
@@ -XXX,XX +XXX,XX @@
143
-<!DOCTYPE html>
144
-<html lang="en">
145
- <head>
146
- <meta charset="UTF-8">
147
- <title>QEMU @VERSION@ Documentation</title>
148
- </head>
149
- <body>
150
- <h1>QEMU @VERSION@ Documentation</h1>
151
- <ul>
152
- <li><a href="system/index.html">System Emulation User's Guide</a></li>
153
- <li><a href="user/index.html">User Mode Emulation User's Guide</a></li>
154
- <li><a href="tools/index.html">Tools Guide</a></li>
155
- <li><a href="interop/index.html">System Emulation Management and Interoperability Guide</a></li>
156
- <li><a href="specs/index.html">System Emulation Guest Hardware Specifications</a></li>
157
- </ul>
158
- </body>
159
-</html>
160
diff --git a/docs/interop/conf.py b/docs/interop/conf.py
161
deleted file mode 100644
162
index XXXXXXX..XXXXXXX
163
--- a/docs/interop/conf.py
164
+++ /dev/null
165
@@ -XXX,XX +XXX,XX @@
166
-# -*- coding: utf-8 -*-
167
-#
168
-# QEMU documentation build configuration file for the 'interop' manual.
169
-#
170
-# This includes the top level conf file and then makes any necessary tweaks.
171
-import sys
172
-import os
173
-
174
-qemu_docdir = os.path.abspath("..")
175
-parent_config = os.path.join(qemu_docdir, "conf.py")
176
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
177
-
178
-# This slightly misuses the 'description', but is the best way to get
179
-# the manual title to appear in the sidebar.
180
-html_theme_options['description'] = u'System Emulation Management and Interoperability Guide'
181
-
182
-# One entry per manual page. List of tuples
183
-# (source start file, name, description, authors, manual section).
184
-man_pages = [
185
- ('qemu-ga', 'qemu-ga', u'QEMU Guest Agent',
186
- ['Michael Roth <mdroth@linux.vnet.ibm.com>'], 8),
187
- ('qemu-ga-ref', 'qemu-ga-ref', 'QEMU Guest Agent Protocol Reference',
188
- [], 7),
189
- ('qemu-qmp-ref', 'qemu-qmp-ref', 'QEMU QMP Reference Manual',
190
- [], 7),
191
- ('qemu-storage-daemon-qmp-ref', 'qemu-storage-daemon-qmp-ref',
192
- 'QEMU Storage Daemon QMP Reference Manual', [], 7),
193
-]
194
diff --git a/docs/meson.build b/docs/meson.build
195
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
196
--- a/docs/meson.build
37
--- a/target/arm/helper.c
197
+++ b/docs/meson.build
38
+++ b/target/arm/helper.c
198
@@ -XXX,XX +XXX,XX @@ if build_docs
39
@@ -XXX,XX +XXX,XX @@ static bool pmevcntr_is_64_bit(CPUARMState *env, int counter)
199
meson.source_root() / 'docs/sphinx/qmp_lexer.py',
40
bool hlp = env->cp15.mdcr_el2 & MDCR_HLP;
200
qapi_gen_depends ]
41
int hpmn = env->cp15.mdcr_el2 & MDCR_HPMN;
201
42
202
- configure_file(output: 'index.html',
43
- if (hpmn != 0 && counter >= hpmn) {
203
- input: files('index.html.in'),
44
+ if (counter >= hpmn) {
204
- configuration: {'VERSION': meson.project_version()},
45
return hlp;
205
- install_dir: qemu_docdir)
46
}
206
- manuals = [ 'devel', 'interop', 'tools', 'specs', 'system', 'user' ]
47
}
207
man_pages = {
48
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
208
- 'interop' : {
49
index XXXXXXX..XXXXXXX 100644
209
'qemu-ga.8': (have_tools ? 'man8' : ''),
50
--- a/target/arm/tcg/cpu32.c
210
'qemu-ga-ref.7': 'man7',
51
+++ b/target/arm/tcg/cpu32.c
211
'qemu-qmp-ref.7': 'man7',
52
@@ -XXX,XX +XXX,XX @@ void aa32_max_features(ARMCPU *cpu)
212
'qemu-storage-daemon-qmp-ref.7': (have_tools ? 'man7' : ''),
53
t = FIELD_DP32(t, ID_DFR0, COPSDBG, 9); /* FEAT_Debugv8p4 */
213
- },
54
t = FIELD_DP32(t, ID_DFR0, PERFMON, 6); /* FEAT_PMUv3p5 */
214
- 'tools': {
55
cpu->isar.id_dfr0 = t;
215
'qemu-img.1': (have_tools ? 'man1' : ''),
216
'qemu-nbd.8': (have_tools ? 'man8' : ''),
217
'qemu-pr-helper.8': (have_tools ? 'man8' : ''),
218
@@ -XXX,XX +XXX,XX @@ if build_docs
219
'qemu-trace-stap.1': (config_host.has_key('CONFIG_TRACE_SYSTEMTAP') ? 'man1' : ''),
220
'virtfs-proxy-helper.1': (have_virtfs_proxy_helper ? 'man1' : ''),
221
'virtiofsd.1': (have_virtiofsd ? 'man1' : ''),
222
- },
223
- 'system': {
224
'qemu.1': 'man1',
225
'qemu-block-drivers.7': 'man7',
226
'qemu-cpu-models.7': 'man7'
227
- },
228
}
229
230
sphinxdocs = []
231
sphinxmans = []
232
- foreach manual : manuals
233
- private_dir = meson.current_build_dir() / (manual + '.p')
234
- output_dir = meson.current_build_dir() / manual
235
- input_dir = meson.current_source_dir() / manual
236
237
- this_manual = custom_target(manual + ' manual',
238
+ private_dir = meson.current_build_dir() / 'manual.p'
239
+ output_dir = meson.current_build_dir() / 'manual'
240
+ input_dir = meson.current_source_dir()
241
+
56
+
242
+ this_manual = custom_target('QEMU manual',
57
+ t = cpu->isar.id_dfr1;
243
build_by_default: build_docs,
58
+ t = FIELD_DP32(t, ID_DFR1, HPMN0, 1); /* FEAT_HPMN0 */
244
- output: [manual + '.stamp'],
59
+ cpu->isar.id_dfr1 = t;
245
- input: [files('conf.py'), files(manual / 'conf.py')],
60
}
246
- depfile: manual + '.d',
61
247
+ output: 'docs.stamp',
62
/* CPU models. These are not needed for the AArch64 linux-user build. */
248
+ input: files('conf.py'),
63
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
249
+ depfile: 'docs.d',
64
index XXXXXXX..XXXXXXX 100644
250
depend_files: sphinx_extn_depends,
65
--- a/target/arm/tcg/cpu64.c
251
command: [SPHINX_ARGS, '-Ddepfile=@DEPFILE@',
66
+++ b/target/arm/tcg/cpu64.c
252
'-Ddepfile_stamp=@OUTPUT0@',
67
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
253
'-b', 'html', '-d', private_dir,
68
t = cpu->isar.id_aa64dfr0;
254
input_dir, output_dir])
69
t = FIELD_DP64(t, ID_AA64DFR0, DEBUGVER, 9); /* FEAT_Debugv8p4 */
255
- sphinxdocs += this_manual
70
t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 6); /* FEAT_PMUv3p5 */
256
- if build_docs and manual != 'devel'
71
+ t = FIELD_DP64(t, ID_AA64DFR0, HPMN0, 1); /* FEAT_HPMN0 */
257
- install_subdir(output_dir, install_dir: qemu_docdir)
72
cpu->isar.id_aa64dfr0 = t;
258
- endif
73
259
+ sphinxdocs += this_manual
74
t = cpu->isar.id_aa64smfr0;
260
+ install_subdir(output_dir, install_dir: qemu_docdir, strip_directory: true)
261
262
- these_man_pages = []
263
- install_dirs = []
264
- foreach page, section : man_pages.get(manual, {})
265
- these_man_pages += page
266
- install_dirs += section == '' ? false : get_option('mandir') / section
267
- endforeach
268
- if these_man_pages.length() > 0
269
- sphinxmans += custom_target(manual + ' man pages',
270
- build_by_default: build_docs,
271
- output: these_man_pages,
272
- input: this_manual,
273
- install: build_docs,
274
- install_dir: install_dirs,
275
- command: [SPHINX_ARGS, '-b', 'man', '-d', private_dir,
276
- input_dir, meson.current_build_dir()])
277
- endif
278
+ these_man_pages = []
279
+ install_dirs = []
280
+ foreach page, section : man_pages
281
+ these_man_pages += page
282
+ install_dirs += section == '' ? false : get_option('mandir') / section
283
endforeach
284
+
285
+ sphinxmans += custom_target('QEMU man pages',
286
+ build_by_default: build_docs,
287
+ output: these_man_pages,
288
+ input: this_manual,
289
+ install: build_docs,
290
+ install_dir: install_dirs,
291
+ command: [SPHINX_ARGS, '-b', 'man', '-d', private_dir,
292
+ input_dir, meson.current_build_dir()])
293
+
294
alias_target('sphinxdocs', sphinxdocs)
295
alias_target('html', sphinxdocs)
296
alias_target('man', sphinxmans)
297
diff --git a/docs/specs/conf.py b/docs/specs/conf.py
298
deleted file mode 100644
299
index XXXXXXX..XXXXXXX
300
--- a/docs/specs/conf.py
301
+++ /dev/null
302
@@ -XXX,XX +XXX,XX @@
303
-# -*- coding: utf-8 -*-
304
-#
305
-# QEMU documentation build configuration file for the 'specs' manual.
306
-#
307
-# This includes the top level conf file and then makes any necessary tweaks.
308
-import sys
309
-import os
310
-
311
-qemu_docdir = os.path.abspath("..")
312
-parent_config = os.path.join(qemu_docdir, "conf.py")
313
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
314
-
315
-# This slightly misuses the 'description', but is the best way to get
316
-# the manual title to appear in the sidebar.
317
-html_theme_options['description'] = \
318
- u'System Emulation Guest Hardware Specifications'
319
diff --git a/docs/system/conf.py b/docs/system/conf.py
320
deleted file mode 100644
321
index XXXXXXX..XXXXXXX
322
--- a/docs/system/conf.py
323
+++ /dev/null
324
@@ -XXX,XX +XXX,XX @@
325
-# -*- coding: utf-8 -*-
326
-#
327
-# QEMU documentation build configuration file for the 'system' manual.
328
-#
329
-# This includes the top level conf file and then makes any necessary tweaks.
330
-import sys
331
-import os
332
-
333
-qemu_docdir = os.path.abspath("..")
334
-parent_config = os.path.join(qemu_docdir, "conf.py")
335
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
336
-
337
-# This slightly misuses the 'description', but is the best way to get
338
-# the manual title to appear in the sidebar.
339
-html_theme_options['description'] = u'System Emulation User''s Guide'
340
-
341
-# One entry per manual page. List of tuples
342
-# (source start file, name, description, authors, manual section).
343
-man_pages = [
344
- ('qemu-manpage', 'qemu', u'QEMU User Documentation',
345
- ['Fabrice Bellard'], 1),
346
- ('qemu-block-drivers', 'qemu-block-drivers',
347
- u'QEMU block drivers reference',
348
- ['Fabrice Bellard and the QEMU Project developers'], 7),
349
- ('qemu-cpu-models', 'qemu-cpu-models',
350
- u'QEMU CPU Models',
351
- ['The QEMU Project developers'], 7)
352
-]
353
diff --git a/docs/tools/conf.py b/docs/tools/conf.py
354
deleted file mode 100644
355
index XXXXXXX..XXXXXXX
356
--- a/docs/tools/conf.py
357
+++ /dev/null
358
@@ -XXX,XX +XXX,XX @@
359
-# -*- coding: utf-8 -*-
360
-#
361
-# QEMU documentation build configuration file for the 'tools' manual.
362
-#
363
-# This includes the top level conf file and then makes any necessary tweaks.
364
-import sys
365
-import os
366
-
367
-qemu_docdir = os.path.abspath("..")
368
-parent_config = os.path.join(qemu_docdir, "conf.py")
369
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
370
-
371
-# This slightly misuses the 'description', but is the best way to get
372
-# the manual title to appear in the sidebar.
373
-html_theme_options['description'] = \
374
- u'Tools Guide'
375
-
376
-# One entry per manual page. List of tuples
377
-# (source start file, name, description, authors, manual section).
378
-man_pages = [
379
- ('qemu-img', 'qemu-img', u'QEMU disk image utility',
380
- ['Fabrice Bellard'], 1),
381
- ('qemu-storage-daemon', 'qemu-storage-daemon', u'QEMU storage daemon',
382
- [], 1),
383
- ('qemu-nbd', 'qemu-nbd', u'QEMU Disk Network Block Device Server',
384
- ['Anthony Liguori <anthony@codemonkey.ws>'], 8),
385
- ('qemu-pr-helper', 'qemu-pr-helper', 'QEMU persistent reservation helper',
386
- [], 8),
387
- ('qemu-trace-stap', 'qemu-trace-stap', u'QEMU SystemTap trace tool',
388
- [], 1),
389
- ('virtfs-proxy-helper', 'virtfs-proxy-helper',
390
- u'QEMU 9p virtfs proxy filesystem helper',
391
- ['M. Mohan Kumar'], 1),
392
- ('virtiofsd', 'virtiofsd', u'QEMU virtio-fs shared file system daemon',
393
- ['Stefan Hajnoczi <stefanha@redhat.com>',
394
- 'Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>'], 1),
395
-]
396
diff --git a/docs/user/conf.py b/docs/user/conf.py
397
deleted file mode 100644
398
index XXXXXXX..XXXXXXX
399
--- a/docs/user/conf.py
400
+++ /dev/null
401
@@ -XXX,XX +XXX,XX @@
402
-# -*- coding: utf-8 -*-
403
-#
404
-# QEMU documentation build configuration file for the 'user' manual.
405
-#
406
-# This includes the top level conf file and then makes any necessary tweaks.
407
-import sys
408
-import os
409
-
410
-qemu_docdir = os.path.abspath("..")
411
-parent_config = os.path.join(qemu_docdir, "conf.py")
412
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
413
-
414
-# This slightly misuses the 'description', but is the best way to get
415
-# the manual title to appear in the sidebar.
416
-html_theme_options['description'] = u'User Mode Emulation User''s Guide'
417
--
75
--
418
2.20.1
76
2.34.1
419
420
diff view generated by jsdifflib
1
In commit 1982e1602d15 we added a new qemu-storage-daemon(1) manpage.
1
The include of hw/arm/virt.h in kvm64.c is unnecessary and also a
2
At the moment new manpages have to be listed both in the conf.py for
2
layering violation since the generic KVM code shouldn't need to know
3
Sphinx and also in docs/meson.build for Meson. We forgot the second
3
anything about board-specifics. The include line is an accidental
4
of those -- correct the omission.
4
leftover from commit 15613357ba53a4763, where we cleaned up the code
5
to not depend on virt board internals but forgot to also remove the
6
now-redundant include line.
5
7
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Reviewed-by: Gavin Shan <gshan@redhat.com>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Message-id: 20210108161416.21129-2-peter.maydell@linaro.org
11
Message-id: 20230925110429.3917202-1-peter.maydell@linaro.org
10
---
12
---
11
docs/meson.build | 1 +
13
target/arm/kvm64.c | 1 -
12
1 file changed, 1 insertion(+)
14
1 file changed, 1 deletion(-)
13
15
14
diff --git a/docs/meson.build b/docs/meson.build
16
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/docs/meson.build
18
--- a/target/arm/kvm64.c
17
+++ b/docs/meson.build
19
+++ b/target/arm/kvm64.c
18
@@ -XXX,XX +XXX,XX @@ if build_docs
20
@@ -XXX,XX +XXX,XX @@
19
'qemu-img.1': (have_tools ? 'man1' : ''),
21
#include "internals.h"
20
'qemu-nbd.8': (have_tools ? 'man8' : ''),
22
#include "hw/acpi/acpi.h"
21
'qemu-pr-helper.8': (have_tools ? 'man8' : ''),
23
#include "hw/acpi/ghes.h"
22
+ 'qemu-storage-daemon.1': (have_tools ? 'man1' : ''),
24
-#include "hw/arm/virt.h"
23
'qemu-trace-stap.1': (config_host.has_key('CONFIG_TRACE_SYSTEMTAP') ? 'man1' : ''),
25
24
'virtfs-proxy-helper.1': (have_virtfs_proxy_helper ? 'man1' : ''),
26
static bool have_guest_debug;
25
'virtiofsd.1': (have_virtiofsd ? 'man1' : ''),
27
26
--
28
--
27
2.20.1
29
2.34.1
28
30
29
31
diff view generated by jsdifflib
1
In commit cd8be50e58f63413c0 we converted the A32 coprocessor
1
The hw/arm/boot.h include in common-semi-target.h is not actually
2
insns to decodetree. This accidentally broke XScale/iWMMXt insns,
2
needed, and it's a bit odd because it pulls a hw/arm header into a
3
because it moved the handling of "cp insns which are handled
3
target/arm file.
4
by looking up the cp register in the hashtable" from after the
5
call to the legacy disas_xscale_insn() decode to before it,
6
with the result that all XScale/iWMMXt insns now UNDEF.
7
4
8
Update valid_cp() so that it knows that on XScale cp 0 and 1
5
This include was originally needed because the semihosting code used
9
are not standard coprocessor instructions; this will cause
6
the arm_boot_info struct to get the base address of the RAM in system
10
the decodetree trans_ functions to ignore them, so that
7
emulation, to use in a (bad) heuristic for the return values for the
11
execution will correctly get through to the legacy decode again.
8
SYS_HEAPINFO semihosting call. We've since overhauled how we
9
calculate the HEAPINFO values in system emulation, and the code no
10
longer uses the arm_boot_info struct.
12
11
13
Cc: qemu-stable@nongnu.org
12
Remove the now-redundant include line, and instead directly include
14
Reported-by: Guenter Roeck <linux@roeck-us.net>
13
the cpu-qom.h header that we were previously getting via boot.h.
14
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Tested-by: Guenter Roeck <linux@roeck-us.net>
17
Message-id: 20230925112219.3919261-1-peter.maydell@linaro.org
18
Message-id: 20210108195157.32067-1-peter.maydell@linaro.org
19
---
18
---
20
target/arm/translate.c | 7 +++++++
19
target/arm/common-semi-target.h | 4 +---
21
1 file changed, 7 insertions(+)
20
1 file changed, 1 insertion(+), 3 deletions(-)
22
21
23
diff --git a/target/arm/translate.c b/target/arm/translate.c
22
diff --git a/target/arm/common-semi-target.h b/target/arm/common-semi-target.h
24
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/translate.c
24
--- a/target/arm/common-semi-target.h
26
+++ b/target/arm/translate.c
25
+++ b/target/arm/common-semi-target.h
27
@@ -XXX,XX +XXX,XX @@ static bool valid_cp(DisasContext *s, int cp)
26
@@ -XXX,XX +XXX,XX @@
28
* only cp14 and cp15 are valid, and other values aren't considered
27
#ifndef TARGET_ARM_COMMON_SEMI_TARGET_H
29
* to be in the coprocessor-instruction space at all. v8M still
28
#define TARGET_ARM_COMMON_SEMI_TARGET_H
30
* permits coprocessors 0..7.
29
31
+ * For XScale, we must not decode the XScale cp0, cp1 space as
30
-#ifndef CONFIG_USER_ONLY
32
+ * a standard coprocessor insn, because we want to fall through to
31
-#include "hw/arm/boot.h"
33
+ * the legacy disas_xscale_insn() decoder after decodetree is done.
32
-#endif
34
*/
33
+#include "target/arm/cpu-qom.h"
35
+ if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cp == 0 || cp == 1)) {
34
36
+ return false;
35
static inline target_ulong common_semi_arg(CPUState *cs, int argno)
37
+ }
36
{
38
+
39
if (arm_dc_feature(s, ARM_FEATURE_V8) &&
40
!arm_dc_feature(s, ARM_FEATURE_M)) {
41
return cp >= 14;
42
--
37
--
43
2.20.1
38
2.34.1
44
45
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
The code for powering on a CPU in arm-powerctl.c has two separate
2
2
use cases:
3
We add a qtest for the PWM in the previous patch. It proves it works as
3
* emulation of a real hardware power controller
4
expected.
4
* emulation of firmware interfaces (primarily PSCI) with
5
5
CPU on/off APIs
6
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
6
7
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
7
For the first case, we only need to reset the CPU and set its
8
Signed-off-by: Hao Wu <wuhaotsh@google.com>
8
starting PC and X0. For the second case, because we're emulating the
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
firmware we need to ensure that it's in the state that the firmware
10
Message-id: 20210108190945.949196-6-wuhaotsh@google.com
10
provides. In particular, when we reset to a lower EL than the
11
highest one we are emulating, we need to put the CPU into a state
12
that permits correct running at that lower EL. We already do a
13
little of this in arm-powerctl.c (for instance we set SCR_HCE to
14
enable the HVC insn) but we don't do enough of it. This means that
15
in the case where we are emulating EL3 but also providing emulated
16
PSCI the guest will crash when a secondary core tries to use a
17
feature that needs an SCR_EL3 bit to be set, such as MTE or PAuth.
18
19
The hw/arm/boot.c code also has to support this "start guest code in
20
an EL that's lower than the highest emulated EL" case in order to do
21
direct guest kernel booting; it has all the necessary initialization
22
code to set the SCR_EL3 bits. Pull the relevant boot.c code out into
23
a separate function so we can share it between there and
24
arm-powerctl.c.
25
26
This refactoring has a few code changes that look like they
27
might be behaviour changes but aren't:
28
* if info->secure_boot is false and info->secure_board_setup is
29
true, then the old code would start the first CPU in Hyp
30
mode but without changing SCR.NS and NSACR.{CP11,CP10}.
31
This was wrong behaviour because there's no such thing
32
as Secure Hyp mode. The new code will leave the CPU in SVC.
33
(There is no board which sets secure_boot to false and
34
secure_board_setup to true, so this isn't a behaviour
35
change for any of our boards.)
36
* we don't explicitly clear SCR.NS when arm-powerctl.c
37
does a CPU-on to EL3. This was a no-op because CPU reset
38
will reset to NS == 0.
39
40
And some real behaviour changes:
41
* we no longer set HCR_EL2.RW when booting into EL2: the guest
42
can and should do that themselves before dropping into their
43
EL1 code. (arm-powerctl and boot did this differently; I
44
opted to use the logic from arm-powerctl, which only sets
45
HCR_EL2.RW when it's directly starting the guest in EL1,
46
because it's more correct, and I don't expect guests to be
47
accidentally depending on our having set the RW bit for them.)
48
* if we are booting a CPU into AArch32 Secure SVC then we won't
49
set SCR.HCE any more. This affects only the vexpress-a15 and
50
raspi2b machine types. Guests booting in this case will either:
51
- be able to set SCR.HCE themselves as part of moving from
52
Secure SVC into NS Hyp mode
53
- will move from Secure SVC to NS SVC, and won't care about
54
behaviour of the HVC insn
55
- will stay in Secure SVC, and won't care about HVC
56
* on an arm-powerctl CPU-on we will now set the SCR bits for
57
pauth/mte/sve/sme/hcx/fgt features
58
59
The first two of these are very minor and I don't expect guest
60
code to trip over them, so I didn't judge it worth convoluting
61
the code in an attempt to keep exactly the same boot.c behaviour.
62
The third change fixes issue 1899.
63
64
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1899
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
65
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
66
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
67
Message-id: 20230926155619.4028618-1-peter.maydell@linaro.org
12
---
68
---
13
tests/qtest/npcm7xx_pwm-test.c | 490 +++++++++++++++++++++++++++++++++
69
target/arm/cpu.h | 22 +++++++++
14
tests/qtest/meson.build | 1 +
70
hw/arm/boot.c | 95 ++++++++++-----------------------------
15
2 files changed, 491 insertions(+)
71
target/arm/arm-powerctl.c | 53 +---------------------
16
create mode 100644 tests/qtest/npcm7xx_pwm-test.c
72
target/arm/cpu.c | 95 +++++++++++++++++++++++++++++++++++++++
17
73
4 files changed, 141 insertions(+), 124 deletions(-)
18
diff --git a/tests/qtest/npcm7xx_pwm-test.c b/tests/qtest/npcm7xx_pwm-test.c
74
19
new file mode 100644
75
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
index XXXXXXX..XXXXXXX
76
index XXXXXXX..XXXXXXX 100644
21
--- /dev/null
77
--- a/target/arm/cpu.h
22
+++ b/tests/qtest/npcm7xx_pwm-test.c
78
+++ b/target/arm/cpu.h
23
@@ -XXX,XX +XXX,XX @@
79
@@ -XXX,XX +XXX,XX @@ int arm_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
24
+/*
80
int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
25
+ * QTests for Nuvoton NPCM7xx PWM Modules.
81
int cpuid, DumpState *s);
82
83
+/**
84
+ * arm_emulate_firmware_reset: Emulate firmware CPU reset handling
85
+ * @cpu: CPU (which must have been freshly reset)
86
+ * @target_el: exception level to put the CPU into
87
+ * @secure: whether to put the CPU in secure state
26
+ *
88
+ *
27
+ * Copyright 2020 Google LLC
89
+ * When QEMU is directly running a guest kernel at a lower level than
90
+ * EL3 it implicitly emulates some aspects of the guest firmware.
91
+ * This includes that on reset we need to configure the parts of the
92
+ * CPU corresponding to EL3 so that the real guest code can run at its
93
+ * lower exception level. This function does that post-reset CPU setup,
94
+ * for when we do direct boot of a guest kernel, and for when we
95
+ * emulate PSCI and similar firmware interfaces starting a CPU at a
96
+ * lower exception level.
28
+ *
97
+ *
29
+ * This program is free software; you can redistribute it and/or modify it
98
+ * @target_el must be an EL implemented by the CPU between 1 and 3.
30
+ * under the terms of the GNU General Public License as published by the
99
+ * We do not support dropping into a Secure EL other than 3.
31
+ * Free Software Foundation; either version 2 of the License, or
32
+ * (at your option) any later version.
33
+ *
100
+ *
34
+ * This program is distributed in the hope that it will be useful, but WITHOUT
101
+ * It is the responsibility of the caller to call arm_rebuild_hflags().
35
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
36
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
37
+ * for more details.
38
+ */
102
+ */
39
+
103
+void arm_emulate_firmware_reset(CPUState *cpustate, int target_el);
40
+#include "qemu/osdep.h"
104
+
41
+#include "qemu/bitops.h"
105
#ifdef TARGET_AARCH64
42
+#include "libqos/libqtest.h"
106
int aarch64_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
43
+#include "qapi/qmp/qdict.h"
107
int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
44
+#include "qapi/qmp/qnum.h"
108
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
45
+
109
index XXXXXXX..XXXXXXX 100644
46
+#define REF_HZ 25000000
110
--- a/hw/arm/boot.c
47
+
111
+++ b/hw/arm/boot.c
48
+/* Register field definitions. */
112
@@ -XXX,XX +XXX,XX @@ static void do_cpu_reset(void *opaque)
49
+#define CH_EN BIT(0)
113
50
+#define CH_INV BIT(2)
114
cpu_set_pc(cs, entry);
51
+#define CH_MOD BIT(3)
115
} else {
52
+
116
- /* If we are booting Linux then we need to check whether we are
53
+/* Registers shared between all PWMs in a module */
117
- * booting into secure or non-secure state and adjust the state
54
+#define PPR 0x00
118
- * accordingly. Out of reset, ARM is defined to be in secure state
55
+#define CSR 0x04
119
- * (SCR.NS = 0), we change that here if non-secure boot has been
56
+#define PCR 0x08
120
- * requested.
57
+#define PIER 0x3c
121
+ /*
58
+#define PIIR 0x40
122
+ * If we are booting Linux then we might need to do so at:
59
+
123
+ * - AArch64 NS EL2 or NS EL1
60
+/* CLK module related */
124
+ * - AArch32 Secure SVC (EL3)
61
+#define CLK_BA 0xf0801000
125
+ * - AArch32 NS Hyp (EL2)
62
+#define CLKSEL 0x04
126
+ * - AArch32 NS SVC (EL1)
63
+#define CLKDIV1 0x08
127
+ * Configure the CPU in the way boot firmware would do to
64
+#define CLKDIV2 0x2c
128
+ * drop us down to the appropriate level.
65
+#define PLLCON0 0x0c
129
*/
66
+#define PLLCON1 0x10
130
- if (arm_feature(env, ARM_FEATURE_EL3)) {
67
+#define PLL_INDV(rv) extract32((rv), 0, 6)
131
- /* AArch64 is defined to come out of reset into EL3 if enabled.
68
+#define PLL_FBDV(rv) extract32((rv), 16, 12)
132
- * If we are booting Linux then we need to adjust our EL as
69
+#define PLL_OTDV1(rv) extract32((rv), 8, 3)
133
- * Linux expects us to be in EL2 or EL1. AArch32 resets into
70
+#define PLL_OTDV2(rv) extract32((rv), 13, 3)
134
- * SVC, which Linux expects, so no privilege/exception level to
71
+#define APB3CKDIV(rv) extract32((rv), 28, 2)
135
- * adjust.
72
+#define CLK2CKDIV(rv) extract32((rv), 0, 1)
136
- */
73
+#define CLK4CKDIV(rv) extract32((rv), 26, 2)
137
- if (env->aarch64) {
74
+#define CPUCKSEL(rv) extract32((rv), 0, 2)
138
- env->cp15.scr_el3 |= SCR_RW;
75
+
139
- if (arm_feature(env, ARM_FEATURE_EL2)) {
76
+#define MAX_DUTY 1000000
140
- env->cp15.hcr_el2 |= HCR_RW;
77
+
141
- env->pstate = PSTATE_MODE_EL2h;
78
+typedef struct PWMModule {
142
- } else {
79
+ int irq;
143
- env->pstate = PSTATE_MODE_EL1h;
80
+ uint64_t base_addr;
144
- }
81
+} PWMModule;
145
- if (cpu_isar_feature(aa64_pauth, cpu)) {
82
+
146
- env->cp15.scr_el3 |= SCR_API | SCR_APK;
83
+typedef struct PWM {
147
- }
84
+ uint32_t cnr_offset;
148
- if (cpu_isar_feature(aa64_mte, cpu)) {
85
+ uint32_t cmr_offset;
149
- env->cp15.scr_el3 |= SCR_ATA;
86
+ uint32_t pdr_offset;
150
- }
87
+ uint32_t pwdr_offset;
151
- if (cpu_isar_feature(aa64_sve, cpu)) {
88
+} PWM;
152
- env->cp15.cptr_el[3] |= R_CPTR_EL3_EZ_MASK;
89
+
153
- env->vfp.zcr_el[3] = 0xf;
90
+typedef struct TestData {
154
- }
91
+ const PWMModule *module;
155
- if (cpu_isar_feature(aa64_sme, cpu)) {
92
+ const PWM *pwm;
156
- env->cp15.cptr_el[3] |= R_CPTR_EL3_ESM_MASK;
93
+} TestData;
157
- env->cp15.scr_el3 |= SCR_ENTP2;
94
+
158
- env->vfp.smcr_el[3] = 0xf;
95
+static const PWMModule pwm_module_list[] = {
159
- }
96
+ {
160
- if (cpu_isar_feature(aa64_hcx, cpu)) {
97
+ .irq = 93,
161
- env->cp15.scr_el3 |= SCR_HXEN;
98
+ .base_addr = 0xf0103000
162
- }
99
+ },
163
- if (cpu_isar_feature(aa64_fgt, cpu)) {
100
+ {
164
- env->cp15.scr_el3 |= SCR_FGTEN;
101
+ .irq = 94,
165
- }
102
+ .base_addr = 0xf0104000
166
+ int target_el = arm_feature(env, ARM_FEATURE_EL2) ? 2 : 1;
103
+ }
167
104
+};
168
- /* AArch64 kernels never boot in secure mode */
105
+
169
- assert(!info->secure_boot);
106
+static const PWM pwm_list[] = {
170
- /* This hook is only supported for AArch32 currently:
107
+ {
171
- * bootloader_aarch64[] will not call the hook, and
108
+ .cnr_offset = 0x0c,
172
- * the code above has already dropped us into EL2 or EL1.
109
+ .cmr_offset = 0x10,
173
- */
110
+ .pdr_offset = 0x14,
174
- assert(!info->secure_board_setup);
111
+ .pwdr_offset = 0x44,
175
- }
112
+ },
176
-
113
+ {
177
- if (arm_feature(env, ARM_FEATURE_EL2)) {
114
+ .cnr_offset = 0x18,
178
- /* If we have EL2 then Linux expects the HVC insn to work */
115
+ .cmr_offset = 0x1c,
179
- env->cp15.scr_el3 |= SCR_HCE;
116
+ .pdr_offset = 0x20,
180
- }
117
+ .pwdr_offset = 0x48,
181
-
118
+ },
182
- /* Set to non-secure if not a secure boot */
119
+ {
183
- if (!info->secure_boot &&
120
+ .cnr_offset = 0x24,
184
- (cs != first_cpu || !info->secure_board_setup)) {
121
+ .cmr_offset = 0x28,
185
- /* Linux expects non-secure state */
122
+ .pdr_offset = 0x2c,
186
- env->cp15.scr_el3 |= SCR_NS;
123
+ .pwdr_offset = 0x4c,
187
- /* Set NSACR.{CP11,CP10} so NS can access the FPU */
124
+ },
188
- env->cp15.nsacr |= 3 << 10;
125
+ {
189
- }
126
+ .cnr_offset = 0x30,
190
- }
127
+ .cmr_offset = 0x34,
191
-
128
+ .pdr_offset = 0x38,
192
- if (!env->aarch64 && !info->secure_boot &&
129
+ .pwdr_offset = 0x50,
193
- arm_feature(env, ARM_FEATURE_EL2)) {
130
+ },
194
+ if (env->aarch64) {
131
+};
195
/*
132
+
196
- * This is an AArch32 boot not to Secure state, and
133
+static const int ppr_base[] = { 0, 0, 8, 8 };
197
- * we have Hyp mode available, so boot the kernel into
134
+static const int csr_base[] = { 0, 4, 8, 12 };
198
- * Hyp mode. This is not how the CPU comes out of reset,
135
+static const int pcr_base[] = { 0, 8, 12, 16 };
199
- * so we need to manually put it there.
136
+
200
+ * AArch64 kernels never boot in secure mode, and we don't
137
+static const uint32_t ppr_list[] = {
201
+ * support the secure_board_setup hook for AArch64.
138
+ 0,
202
*/
139
+ 1,
203
- cpsr_write(env, ARM_CPU_MODE_HYP, CPSR_M, CPSRWriteRaw);
140
+ 10,
204
+ assert(!info->secure_boot);
141
+ 100,
205
+ assert(!info->secure_board_setup);
142
+ 255, /* Max possible value. */
206
+ } else {
143
+};
207
+ if (arm_feature(env, ARM_FEATURE_EL3) &&
144
+
208
+ (info->secure_boot ||
145
+static const uint32_t csr_list[] = {
209
+ (info->secure_board_setup && cs == first_cpu))) {
146
+ 0,
210
+ /* Start this CPU in Secure SVC */
147
+ 1,
211
+ target_el = 3;
148
+ 2,
212
+ }
149
+ 3,
213
}
150
+ 4, /* Max possible value. */
214
151
+};
215
+ arm_emulate_firmware_reset(cs, target_el);
152
+
216
+
153
+static const uint32_t cnr_list[] = {
217
if (cs == first_cpu) {
154
+ 0,
218
AddressSpace *as = arm_boot_address_space(cpu, info);
155
+ 1,
219
156
+ 50,
220
diff --git a/target/arm/arm-powerctl.c b/target/arm/arm-powerctl.c
157
+ 100,
221
index XXXXXXX..XXXXXXX 100644
158
+ 150,
222
--- a/target/arm/arm-powerctl.c
159
+ 200,
223
+++ b/target/arm/arm-powerctl.c
160
+ 1000,
224
@@ -XXX,XX +XXX,XX @@ static void arm_set_cpu_on_async_work(CPUState *target_cpu_state,
161
+ 10000,
225
162
+ 65535, /* Max possible value. */
226
/* Initialize the cpu we are turning on */
163
+};
227
cpu_reset(target_cpu_state);
164
+
228
+ arm_emulate_firmware_reset(target_cpu_state, info->target_el);
165
+static const uint32_t cmr_list[] = {
229
target_cpu_state->halted = 0;
166
+ 0,
230
167
+ 1,
231
- if (info->target_aa64) {
168
+ 10,
232
- if ((info->target_el < 3) && arm_feature(&target_cpu->env,
169
+ 50,
233
- ARM_FEATURE_EL3)) {
170
+ 100,
234
- /*
171
+ 150,
235
- * As target mode is AArch64, we need to set lower
172
+ 200,
236
- * exception level (the requested level 2) to AArch64
173
+ 1000,
237
- */
174
+ 10000,
238
- target_cpu->env.cp15.scr_el3 |= SCR_RW;
175
+ 65535, /* Max possible value. */
239
- }
176
+};
240
-
177
+
241
- if ((info->target_el < 2) && arm_feature(&target_cpu->env,
178
+/* Returns the index of the PWM module. */
242
- ARM_FEATURE_EL2)) {
179
+static int pwm_module_index(const PWMModule *module)
243
- /*
244
- * As target mode is AArch64, we need to set lower
245
- * exception level (the requested level 1) to AArch64
246
- */
247
- target_cpu->env.cp15.hcr_el2 |= HCR_RW;
248
- }
249
-
250
- target_cpu->env.pstate = aarch64_pstate_mode(info->target_el, true);
251
- } else {
252
- /* We are requested to boot in AArch32 mode */
253
- static const uint32_t mode_for_el[] = { 0,
254
- ARM_CPU_MODE_SVC,
255
- ARM_CPU_MODE_HYP,
256
- ARM_CPU_MODE_SVC };
257
-
258
- cpsr_write(&target_cpu->env, mode_for_el[info->target_el], CPSR_M,
259
- CPSRWriteRaw);
260
- }
261
-
262
- if (info->target_el == 3) {
263
- /* Processor is in secure mode */
264
- target_cpu->env.cp15.scr_el3 &= ~SCR_NS;
265
- } else {
266
- /* Processor is not in secure mode */
267
- target_cpu->env.cp15.scr_el3 |= SCR_NS;
268
-
269
- /* Set NSACR.{CP11,CP10} so NS can access the FPU */
270
- target_cpu->env.cp15.nsacr |= 3 << 10;
271
-
272
- /*
273
- * If QEMU is providing the equivalent of EL3 firmware, then we need
274
- * to make sure a CPU targeting EL2 comes out of reset with a
275
- * functional HVC insn.
276
- */
277
- if (arm_feature(&target_cpu->env, ARM_FEATURE_EL3)
278
- && info->target_el == 2) {
279
- target_cpu->env.cp15.scr_el3 |= SCR_HCE;
280
- }
281
- }
282
-
283
/* We check if the started CPU is now at the correct level */
284
assert(info->target_el == arm_current_el(&target_cpu->env));
285
286
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
287
index XXXXXXX..XXXXXXX 100644
288
--- a/target/arm/cpu.c
289
+++ b/target/arm/cpu.c
290
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset_hold(Object *obj)
291
}
292
}
293
294
+void arm_emulate_firmware_reset(CPUState *cpustate, int target_el)
180
+{
295
+{
181
+ ptrdiff_t diff = module - pwm_module_list;
296
+ ARMCPU *cpu = ARM_CPU(cpustate);
182
+
297
+ CPUARMState *env = &cpu->env;
183
+ g_assert_true(diff >= 0 && diff < ARRAY_SIZE(pwm_module_list));
298
+ bool have_el3 = arm_feature(env, ARM_FEATURE_EL3);
184
+
299
+ bool have_el2 = arm_feature(env, ARM_FEATURE_EL2);
185
+ return diff;
300
+
186
+}
301
+ /*
187
+
302
+ * Check we have the EL we're aiming for. If that is the
188
+/* Returns the index of the PWM entry. */
303
+ * highest implemented EL, then cpu_reset has already done
189
+static int pwm_index(const PWM *pwm)
304
+ * all the work.
190
+{
305
+ */
191
+ ptrdiff_t diff = pwm - pwm_list;
306
+ switch (target_el) {
192
+
307
+ case 3:
193
+ g_assert_true(diff >= 0 && diff < ARRAY_SIZE(pwm_list));
308
+ assert(have_el3);
194
+
309
+ return;
195
+ return diff;
310
+ case 2:
196
+}
311
+ assert(have_el2);
197
+
312
+ if (!have_el3) {
198
+static uint64_t pwm_qom_get(QTestState *qts, const char *path, const char *name)
313
+ return;
199
+{
314
+ }
200
+ QDict *response;
201
+
202
+ g_test_message("Getting properties %s from %s", name, path);
203
+ response = qtest_qmp(qts, "{ 'execute': 'qom-get',"
204
+ " 'arguments': { 'path': %s, 'property': %s}}",
205
+ path, name);
206
+ /* The qom set message returns successfully. */
207
+ g_assert_true(qdict_haskey(response, "return"));
208
+ return qnum_get_uint(qobject_to(QNum, qdict_get(response, "return")));
209
+}
210
+
211
+static uint64_t pwm_get_freq(QTestState *qts, int module_index, int pwm_index)
212
+{
213
+ char path[100];
214
+ char name[100];
215
+
216
+ sprintf(path, "/machine/soc/pwm[%d]", module_index);
217
+ sprintf(name, "freq[%d]", pwm_index);
218
+
219
+ return pwm_qom_get(qts, path, name);
220
+}
221
+
222
+static uint64_t pwm_get_duty(QTestState *qts, int module_index, int pwm_index)
223
+{
224
+ char path[100];
225
+ char name[100];
226
+
227
+ sprintf(path, "/machine/soc/pwm[%d]", module_index);
228
+ sprintf(name, "duty[%d]", pwm_index);
229
+
230
+ return pwm_qom_get(qts, path, name);
231
+}
232
+
233
+static uint32_t get_pll(uint32_t con)
234
+{
235
+ return REF_HZ * PLL_FBDV(con) / (PLL_INDV(con) * PLL_OTDV1(con)
236
+ * PLL_OTDV2(con));
237
+}
238
+
239
+static uint64_t read_pclk(QTestState *qts)
240
+{
241
+ uint64_t freq = REF_HZ;
242
+ uint32_t clksel = qtest_readl(qts, CLK_BA + CLKSEL);
243
+ uint32_t pllcon;
244
+ uint32_t clkdiv1 = qtest_readl(qts, CLK_BA + CLKDIV1);
245
+ uint32_t clkdiv2 = qtest_readl(qts, CLK_BA + CLKDIV2);
246
+
247
+ switch (CPUCKSEL(clksel)) {
248
+ case 0:
249
+ pllcon = qtest_readl(qts, CLK_BA + PLLCON0);
250
+ freq = get_pll(pllcon);
251
+ break;
315
+ break;
252
+ case 1:
316
+ case 1:
253
+ pllcon = qtest_readl(qts, CLK_BA + PLLCON1);
317
+ if (!have_el3 && !have_el2) {
254
+ freq = get_pll(pllcon);
318
+ return;
255
+ break;
319
+ }
256
+ case 2:
257
+ break;
258
+ case 3:
259
+ break;
320
+ break;
260
+ default:
321
+ default:
261
+ g_assert_not_reached();
322
+ g_assert_not_reached();
262
+ }
323
+ }
263
+
324
+
264
+ freq >>= (CLK2CKDIV(clkdiv1) + CLK4CKDIV(clkdiv1) + APB3CKDIV(clkdiv2));
325
+ if (have_el3) {
265
+
326
+ /*
266
+ return freq;
327
+ * Set the EL3 state so code can run at EL2. This should match
267
+}
328
+ * the requirements set by Linux in its booting spec.
268
+
329
+ */
269
+static uint32_t pwm_selector(uint32_t csr)
330
+ if (env->aarch64) {
270
+{
331
+ env->cp15.scr_el3 |= SCR_RW;
271
+ switch (csr) {
332
+ if (cpu_isar_feature(aa64_pauth, cpu)) {
272
+ case 0:
333
+ env->cp15.scr_el3 |= SCR_API | SCR_APK;
273
+ return 2;
334
+ }
274
+ case 1:
335
+ if (cpu_isar_feature(aa64_mte, cpu)) {
275
+ return 4;
336
+ env->cp15.scr_el3 |= SCR_ATA;
276
+ case 2:
337
+ }
277
+ return 8;
338
+ if (cpu_isar_feature(aa64_sve, cpu)) {
278
+ case 3:
339
+ env->cp15.cptr_el[3] |= R_CPTR_EL3_EZ_MASK;
279
+ return 16;
340
+ env->vfp.zcr_el[3] = 0xf;
280
+ case 4:
341
+ }
281
+ return 1;
342
+ if (cpu_isar_feature(aa64_sme, cpu)) {
282
+ default:
343
+ env->cp15.cptr_el[3] |= R_CPTR_EL3_ESM_MASK;
283
+ g_assert_not_reached();
344
+ env->cp15.scr_el3 |= SCR_ENTP2;
345
+ env->vfp.smcr_el[3] = 0xf;
346
+ }
347
+ if (cpu_isar_feature(aa64_hcx, cpu)) {
348
+ env->cp15.scr_el3 |= SCR_HXEN;
349
+ }
350
+ if (cpu_isar_feature(aa64_fgt, cpu)) {
351
+ env->cp15.scr_el3 |= SCR_FGTEN;
352
+ }
353
+ }
354
+
355
+ if (target_el == 2) {
356
+ /* If the guest is at EL2 then Linux expects the HVC insn to work */
357
+ env->cp15.scr_el3 |= SCR_HCE;
358
+ }
359
+
360
+ /* Put CPU into non-secure state */
361
+ env->cp15.scr_el3 |= SCR_NS;
362
+ /* Set NSACR.{CP11,CP10} so NS can access the FPU */
363
+ env->cp15.nsacr |= 3 << 10;
364
+ }
365
+
366
+ if (have_el2 && target_el < 2) {
367
+ /* Set EL2 state so code can run at EL1. */
368
+ if (env->aarch64) {
369
+ env->cp15.hcr_el2 |= HCR_RW;
370
+ }
371
+ }
372
+
373
+ /* Set the CPU to the desired state */
374
+ if (env->aarch64) {
375
+ env->pstate = aarch64_pstate_mode(target_el, true);
376
+ } else {
377
+ static const uint32_t mode_for_el[] = {
378
+ 0,
379
+ ARM_CPU_MODE_SVC,
380
+ ARM_CPU_MODE_HYP,
381
+ ARM_CPU_MODE_SVC,
382
+ };
383
+
384
+ cpsr_write(env, mode_for_el[target_el], CPSR_M, CPSRWriteRaw);
284
+ }
385
+ }
285
+}
386
+}
286
+
387
+
287
+static uint64_t pwm_compute_freq(QTestState *qts, uint32_t ppr, uint32_t csr,
388
+
288
+ uint32_t cnr)
389
#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY)
289
+{
390
290
+ return read_pclk(qts) / ((ppr + 1) * pwm_selector(csr) * (cnr + 1));
391
static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
291
+}
292
+
293
+static uint64_t pwm_compute_duty(uint32_t cnr, uint32_t cmr, bool inverted)
294
+{
295
+ uint64_t duty;
296
+
297
+ if (cnr == 0) {
298
+ /* PWM is stopped. */
299
+ duty = 0;
300
+ } else if (cmr >= cnr) {
301
+ duty = MAX_DUTY;
302
+ } else {
303
+ duty = MAX_DUTY * (cmr + 1) / (cnr + 1);
304
+ }
305
+
306
+ if (inverted) {
307
+ duty = MAX_DUTY - duty;
308
+ }
309
+
310
+ return duty;
311
+}
312
+
313
+static uint32_t pwm_read(QTestState *qts, const TestData *td, unsigned offset)
314
+{
315
+ return qtest_readl(qts, td->module->base_addr + offset);
316
+}
317
+
318
+static void pwm_write(QTestState *qts, const TestData *td, unsigned offset,
319
+ uint32_t value)
320
+{
321
+ qtest_writel(qts, td->module->base_addr + offset, value);
322
+}
323
+
324
+static uint32_t pwm_read_ppr(QTestState *qts, const TestData *td)
325
+{
326
+ return extract32(pwm_read(qts, td, PPR), ppr_base[pwm_index(td->pwm)], 8);
327
+}
328
+
329
+static void pwm_write_ppr(QTestState *qts, const TestData *td, uint32_t value)
330
+{
331
+ pwm_write(qts, td, PPR, value << ppr_base[pwm_index(td->pwm)]);
332
+}
333
+
334
+static uint32_t pwm_read_csr(QTestState *qts, const TestData *td)
335
+{
336
+ return extract32(pwm_read(qts, td, CSR), csr_base[pwm_index(td->pwm)], 3);
337
+}
338
+
339
+static void pwm_write_csr(QTestState *qts, const TestData *td, uint32_t value)
340
+{
341
+ pwm_write(qts, td, CSR, value << csr_base[pwm_index(td->pwm)]);
342
+}
343
+
344
+static uint32_t pwm_read_pcr(QTestState *qts, const TestData *td)
345
+{
346
+ return extract32(pwm_read(qts, td, PCR), pcr_base[pwm_index(td->pwm)], 4);
347
+}
348
+
349
+static void pwm_write_pcr(QTestState *qts, const TestData *td, uint32_t value)
350
+{
351
+ pwm_write(qts, td, PCR, value << pcr_base[pwm_index(td->pwm)]);
352
+}
353
+
354
+static uint32_t pwm_read_cnr(QTestState *qts, const TestData *td)
355
+{
356
+ return pwm_read(qts, td, td->pwm->cnr_offset);
357
+}
358
+
359
+static void pwm_write_cnr(QTestState *qts, const TestData *td, uint32_t value)
360
+{
361
+ pwm_write(qts, td, td->pwm->cnr_offset, value);
362
+}
363
+
364
+static uint32_t pwm_read_cmr(QTestState *qts, const TestData *td)
365
+{
366
+ return pwm_read(qts, td, td->pwm->cmr_offset);
367
+}
368
+
369
+static void pwm_write_cmr(QTestState *qts, const TestData *td, uint32_t value)
370
+{
371
+ pwm_write(qts, td, td->pwm->cmr_offset, value);
372
+}
373
+
374
+/* Check pwm registers can be reset to default value */
375
+static void test_init(gconstpointer test_data)
376
+{
377
+ const TestData *td = test_data;
378
+ QTestState *qts = qtest_init("-machine quanta-gsj");
379
+ int module = pwm_module_index(td->module);
380
+ int pwm = pwm_index(td->pwm);
381
+
382
+ g_assert_cmpuint(pwm_get_freq(qts, module, pwm), ==, 0);
383
+ g_assert_cmpuint(pwm_get_duty(qts, module, pwm), ==, 0);
384
+
385
+ qtest_quit(qts);
386
+}
387
+
388
+/* One-shot mode should not change frequency and duty cycle. */
389
+static void test_oneshot(gconstpointer test_data)
390
+{
391
+ const TestData *td = test_data;
392
+ QTestState *qts = qtest_init("-machine quanta-gsj");
393
+ int module = pwm_module_index(td->module);
394
+ int pwm = pwm_index(td->pwm);
395
+ uint32_t ppr, csr, pcr;
396
+ int i, j;
397
+
398
+ pcr = CH_EN;
399
+ for (i = 0; i < ARRAY_SIZE(ppr_list); ++i) {
400
+ ppr = ppr_list[i];
401
+ pwm_write_ppr(qts, td, ppr);
402
+
403
+ for (j = 0; j < ARRAY_SIZE(csr_list); ++j) {
404
+ csr = csr_list[j];
405
+ pwm_write_csr(qts, td, csr);
406
+ pwm_write_pcr(qts, td, pcr);
407
+
408
+ g_assert_cmpuint(pwm_read_ppr(qts, td), ==, ppr);
409
+ g_assert_cmpuint(pwm_read_csr(qts, td), ==, csr);
410
+ g_assert_cmpuint(pwm_read_pcr(qts, td), ==, pcr);
411
+ g_assert_cmpuint(pwm_get_freq(qts, module, pwm), ==, 0);
412
+ g_assert_cmpuint(pwm_get_duty(qts, module, pwm), ==, 0);
413
+ }
414
+ }
415
+
416
+ qtest_quit(qts);
417
+}
418
+
419
+/* In toggle mode, the PWM generates correct outputs. */
420
+static void test_toggle(gconstpointer test_data)
421
+{
422
+ const TestData *td = test_data;
423
+ QTestState *qts = qtest_init("-machine quanta-gsj");
424
+ int module = pwm_module_index(td->module);
425
+ int pwm = pwm_index(td->pwm);
426
+ uint32_t ppr, csr, pcr, cnr, cmr;
427
+ int i, j, k, l;
428
+ uint64_t expected_freq, expected_duty;
429
+
430
+ pcr = CH_EN | CH_MOD;
431
+ for (i = 0; i < ARRAY_SIZE(ppr_list); ++i) {
432
+ ppr = ppr_list[i];
433
+ pwm_write_ppr(qts, td, ppr);
434
+
435
+ for (j = 0; j < ARRAY_SIZE(csr_list); ++j) {
436
+ csr = csr_list[j];
437
+ pwm_write_csr(qts, td, csr);
438
+
439
+ for (k = 0; k < ARRAY_SIZE(cnr_list); ++k) {
440
+ cnr = cnr_list[k];
441
+ pwm_write_cnr(qts, td, cnr);
442
+
443
+ for (l = 0; l < ARRAY_SIZE(cmr_list); ++l) {
444
+ cmr = cmr_list[l];
445
+ pwm_write_cmr(qts, td, cmr);
446
+ expected_freq = pwm_compute_freq(qts, ppr, csr, cnr);
447
+ expected_duty = pwm_compute_duty(cnr, cmr, false);
448
+
449
+ pwm_write_pcr(qts, td, pcr);
450
+ g_assert_cmpuint(pwm_read_ppr(qts, td), ==, ppr);
451
+ g_assert_cmpuint(pwm_read_csr(qts, td), ==, csr);
452
+ g_assert_cmpuint(pwm_read_pcr(qts, td), ==, pcr);
453
+ g_assert_cmpuint(pwm_read_cnr(qts, td), ==, cnr);
454
+ g_assert_cmpuint(pwm_read_cmr(qts, td), ==, cmr);
455
+ g_assert_cmpuint(pwm_get_duty(qts, module, pwm),
456
+ ==, expected_duty);
457
+ if (expected_duty != 0 && expected_duty != 100) {
458
+ /* Duty cycle with 0 or 100 doesn't need frequency. */
459
+ g_assert_cmpuint(pwm_get_freq(qts, module, pwm),
460
+ ==, expected_freq);
461
+ }
462
+
463
+ /* Test inverted mode */
464
+ expected_duty = pwm_compute_duty(cnr, cmr, true);
465
+ pwm_write_pcr(qts, td, pcr | CH_INV);
466
+ g_assert_cmpuint(pwm_read_pcr(qts, td), ==, pcr | CH_INV);
467
+ g_assert_cmpuint(pwm_get_duty(qts, module, pwm),
468
+ ==, expected_duty);
469
+ if (expected_duty != 0 && expected_duty != 100) {
470
+ /* Duty cycle with 0 or 100 doesn't need frequency. */
471
+ g_assert_cmpuint(pwm_get_freq(qts, module, pwm),
472
+ ==, expected_freq);
473
+ }
474
+
475
+ }
476
+ }
477
+ }
478
+ }
479
+
480
+ qtest_quit(qts);
481
+}
482
+
483
+static void pwm_add_test(const char *name, const TestData* td,
484
+ GTestDataFunc fn)
485
+{
486
+ g_autofree char *full_name = g_strdup_printf(
487
+ "npcm7xx_pwm/module[%d]/pwm[%d]/%s", pwm_module_index(td->module),
488
+ pwm_index(td->pwm), name);
489
+ qtest_add_data_func(full_name, td, fn);
490
+}
491
+#define add_test(name, td) pwm_add_test(#name, td, test_##name)
492
+
493
+int main(int argc, char **argv)
494
+{
495
+ TestData test_data_list[ARRAY_SIZE(pwm_module_list) * ARRAY_SIZE(pwm_list)];
496
+
497
+ g_test_init(&argc, &argv, NULL);
498
+
499
+ for (int i = 0; i < ARRAY_SIZE(pwm_module_list); ++i) {
500
+ for (int j = 0; j < ARRAY_SIZE(pwm_list); ++j) {
501
+ TestData *td = &test_data_list[i * ARRAY_SIZE(pwm_list) + j];
502
+
503
+ td->module = &pwm_module_list[i];
504
+ td->pwm = &pwm_list[j];
505
+
506
+ add_test(init, td);
507
+ add_test(oneshot, td);
508
+ add_test(toggle, td);
509
+ }
510
+ }
511
+
512
+ return g_test_run();
513
+}
514
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
515
index XXXXXXX..XXXXXXX 100644
516
--- a/tests/qtest/meson.build
517
+++ b/tests/qtest/meson.build
518
@@ -XXX,XX +XXX,XX @@ qtests_sparc64 = \
519
qtests_npcm7xx = \
520
['npcm7xx_adc-test',
521
'npcm7xx_gpio-test',
522
+ 'npcm7xx_pwm-test',
523
'npcm7xx_rng-test',
524
'npcm7xx_timer-test',
525
'npcm7xx_watchdog_timer-test']
526
--
392
--
527
2.20.1
393
2.34.1
528
529
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Chris Rauer <crauer@google.com>
2
2
3
This patch makes NPCM7XX Timer to use a the timer clock generated by the
3
The counter register is only 24-bits and counts down. If the timer is
4
CLK module instead of the magic number TIMER_REF_HZ.
4
running but the qtimer to reset it hasn't fired off yet, there is a chance
5
the regster read can return an invalid result.
5
6
6
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
7
Signed-off-by: Chris Rauer <crauer@google.com>
7
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
8
Message-id: 20230922181411.2697135-1-crauer@google.com
8
Signed-off-by: Hao Wu <wuhaotsh@google.com>
9
Message-id: 20210108190945.949196-3-wuhaotsh@google.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
11
---
13
include/hw/misc/npcm7xx_clk.h | 6 -----
12
hw/timer/npcm7xx_timer.c | 3 +++
14
include/hw/timer/npcm7xx_timer.h | 1 +
13
1 file changed, 3 insertions(+)
15
hw/arm/npcm7xx.c | 5 ++++
16
hw/timer/npcm7xx_timer.c | 39 +++++++++++++++-----------------
17
4 files changed, 24 insertions(+), 27 deletions(-)
18
14
19
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/misc/npcm7xx_clk.h
22
+++ b/include/hw/misc/npcm7xx_clk.h
23
@@ -XXX,XX +XXX,XX @@
24
#include "hw/clock.h"
25
#include "hw/sysbus.h"
26
27
-/*
28
- * The reference clock frequency for the timer modules, and the SECCNT and
29
- * CNTR25M registers in this module, is always 25 MHz.
30
- */
31
-#define NPCM7XX_TIMER_REF_HZ (25000000)
32
-
33
/*
34
* Number of registers in our device state structure. Don't change this without
35
* incrementing the version_id in the vmstate.
36
diff --git a/include/hw/timer/npcm7xx_timer.h b/include/hw/timer/npcm7xx_timer.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/hw/timer/npcm7xx_timer.h
39
+++ b/include/hw/timer/npcm7xx_timer.h
40
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxTimerCtrlState {
41
42
uint32_t tisr;
43
44
+ Clock *clock;
45
NPCM7xxTimer timer[NPCM7XX_TIMERS_PER_CTRL];
46
NPCM7xxWatchdogTimer watchdog_timer;
47
};
48
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/arm/npcm7xx.c
51
+++ b/hw/arm/npcm7xx.c
52
@@ -XXX,XX +XXX,XX @@
53
#include "hw/char/serial.h"
54
#include "hw/loader.h"
55
#include "hw/misc/unimp.h"
56
+#include "hw/qdev-clock.h"
57
#include "hw/qdev-properties.h"
58
#include "qapi/error.h"
59
#include "qemu/units.h"
60
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
61
int first_irq;
62
int j;
63
64
+ /* Connect the timer clock. */
65
+ qdev_connect_clock_in(DEVICE(&s->tim[i]), "clock", qdev_get_clock_out(
66
+ DEVICE(&s->clk), "timer-clock"));
67
+
68
sysbus_realize(sbd, &error_abort);
69
sysbus_mmio_map(sbd, 0, npcm7xx_tim_addr[i]);
70
71
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
15
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
72
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
73
--- a/hw/timer/npcm7xx_timer.c
17
--- a/hw/timer/npcm7xx_timer.c
74
+++ b/hw/timer/npcm7xx_timer.c
18
+++ b/hw/timer/npcm7xx_timer.c
75
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ static int64_t npcm7xx_timer_count_to_ns(NPCM7xxTimer *t, uint32_t count)
76
#include "qemu/osdep.h"
77
78
#include "hw/irq.h"
79
+#include "hw/qdev-clock.h"
80
#include "hw/qdev-properties.h"
81
-#include "hw/misc/npcm7xx_clk.h"
82
#include "hw/timer/npcm7xx_timer.h"
83
#include "migration/vmstate.h"
84
#include "qemu/bitops.h"
85
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_tcsr_prescaler(uint32_t tcsr)
86
/* Convert a timer cycle count to a time interval in nanoseconds. */
87
static int64_t npcm7xx_timer_count_to_ns(NPCM7xxTimer *t, uint32_t count)
88
{
89
- int64_t ns = count;
90
+ int64_t ticks = count;
91
92
- ns *= NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ;
93
- ns *= npcm7xx_tcsr_prescaler(t->tcsr);
94
+ ticks *= npcm7xx_tcsr_prescaler(t->tcsr);
95
96
- return ns;
97
+ return clock_ticks_to_ns(t->ctrl->clock, ticks);
98
}
99
100
/* Convert a time interval in nanoseconds to a timer cycle count. */
20
/* Convert a time interval in nanoseconds to a timer cycle count. */
101
static uint32_t npcm7xx_timer_ns_to_count(NPCM7xxTimer *t, int64_t ns)
21
static uint32_t npcm7xx_timer_ns_to_count(NPCM7xxTimer *t, int64_t ns)
102
{
22
{
103
- int64_t count;
23
+ if (ns < 0) {
104
-
24
+ return 0;
105
- count = ns / (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ);
25
+ }
106
- count /= npcm7xx_tcsr_prescaler(t->tcsr);
26
return clock_ns_to_ticks(t->ctrl->clock, ns) /
107
-
27
npcm7xx_tcsr_prescaler(t->tcsr);
108
- return count;
109
+ return ns / clock_ticks_to_ns(t->ctrl->clock,
110
+ npcm7xx_tcsr_prescaler(t->tcsr));
111
}
28
}
112
113
static uint32_t npcm7xx_watchdog_timer_prescaler(const NPCM7xxWatchdogTimer *t)
114
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_watchdog_timer_prescaler(const NPCM7xxWatchdogTimer *t)
115
static void npcm7xx_watchdog_timer_reset_cycles(NPCM7xxWatchdogTimer *t,
116
int64_t cycles)
117
{
118
- uint32_t prescaler = npcm7xx_watchdog_timer_prescaler(t);
119
- int64_t ns = (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ) * cycles;
120
+ int64_t ticks = cycles * npcm7xx_watchdog_timer_prescaler(t);
121
+ int64_t ns = clock_ticks_to_ns(t->ctrl->clock, ticks);
122
123
/*
124
* The reset function always clears the current timer. The caller of the
125
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_watchdog_timer_reset_cycles(NPCM7xxWatchdogTimer *t,
126
*/
127
npcm7xx_timer_clear(&t->base_timer);
128
129
- ns *= prescaler;
130
t->base_timer.remaining_ns = ns;
131
}
132
133
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_hold_reset(Object *obj)
134
qemu_irq_lower(s->watchdog_timer.irq);
135
}
136
137
-static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
138
+static void npcm7xx_timer_init(Object *obj)
139
{
140
- NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(dev);
141
- SysBusDevice *sbd = &s->parent;
142
+ NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(obj);
143
+ DeviceState *dev = DEVICE(obj);
144
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
145
int i;
146
NPCM7xxWatchdogTimer *w;
147
148
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
149
npcm7xx_watchdog_timer_expired, w);
150
sysbus_init_irq(sbd, &w->irq);
151
152
- memory_region_init_io(&s->iomem, OBJECT(s), &npcm7xx_timer_ops, s,
153
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_timer_ops, s,
154
TYPE_NPCM7XX_TIMER, 4 * KiB);
155
sysbus_init_mmio(sbd, &s->iomem);
156
qdev_init_gpio_out_named(dev, &w->reset_signal,
157
NPCM7XX_WATCHDOG_RESET_GPIO_OUT, 1);
158
+ s->clock = qdev_init_clock_in(dev, "clock", NULL, NULL);
159
}
160
161
static const VMStateDescription vmstate_npcm7xx_base_timer = {
162
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_npcm7xx_watchdog_timer = {
163
164
static const VMStateDescription vmstate_npcm7xx_timer_ctrl = {
165
.name = "npcm7xx-timer-ctrl",
166
- .version_id = 1,
167
- .minimum_version_id = 1,
168
+ .version_id = 2,
169
+ .minimum_version_id = 2,
170
.fields = (VMStateField[]) {
171
VMSTATE_UINT32(tisr, NPCM7xxTimerCtrlState),
172
+ VMSTATE_CLOCK(clock, NPCM7xxTimerCtrlState),
173
VMSTATE_STRUCT_ARRAY(timer, NPCM7xxTimerCtrlState,
174
NPCM7XX_TIMERS_PER_CTRL, 0, vmstate_npcm7xx_timer,
175
NPCM7xxTimer),
176
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_class_init(ObjectClass *klass, void *data)
177
QEMU_BUILD_BUG_ON(NPCM7XX_TIMER_REGS_END > NPCM7XX_TIMER_NR_REGS);
178
179
dc->desc = "NPCM7xx Timer Controller";
180
- dc->realize = npcm7xx_timer_realize;
181
dc->vmsd = &vmstate_npcm7xx_timer_ctrl;
182
rc->phases.enter = npcm7xx_timer_enter_reset;
183
rc->phases.hold = npcm7xx_timer_hold_reset;
184
@@ -XXX,XX +XXX,XX @@ static const TypeInfo npcm7xx_timer_info = {
185
.parent = TYPE_SYS_BUS_DEVICE,
186
.instance_size = sizeof(NPCM7xxTimerCtrlState),
187
.class_init = npcm7xx_timer_class_init,
188
+ .instance_init = npcm7xx_timer_init,
189
};
190
191
static void npcm7xx_timer_register_type(void)
192
--
29
--
193
2.20.1
30
2.34.1
194
195
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Suraj Shirvankar <surajshirvankar@gmail.com>
2
2
3
This patch allows NPCM7XX CLK module to compute clocks that are used by
3
QEMU coding style uses the glib memory allocation APIs, not
4
other NPCM7XX modules.
4
the raw libc malloc/free. Switch the allocation and free
5
calls in elf2dmp to use these functions (dropping the now-unneeded
6
checks for failure).
5
7
6
Add a new struct NPCM7xxClockConverterState which represents a
8
Signed-off-by: Suraj Shirvankar <surajshirvankar@gmail.com>
7
single converter. Each clock converter in CLK module represents one
9
Message-id: 169753938460.23804.11418813007617535750-1@git.sr.ht
8
converter in NPCM7XX CLK Module(PLL, SEL or Divider). Each converter
10
[PMM: also remove NULL checks from g_malloc() calls;
9
takes one or more input clocks and converts them into one output clock.
11
beef up commit message]
10
They form a clock hierarchy in the CLK module and are responsible for
11
outputing clocks for various other modules in an NPCM7XX SoC.
12
13
Each converter has a function pointer called "convert" which represents
14
the unique logic for that converter.
15
16
The clock contains two initialization information: ConverterInitInfo and
17
ConverterConnectionInfo. They represent the vertices and edges in the
18
clock diagram respectively.
19
20
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
21
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
22
Signed-off-by: Hao Wu <wuhaotsh@google.com>
23
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
24
Message-id: 20210108190945.949196-2-wuhaotsh@google.com
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
---
14
---
27
include/hw/misc/npcm7xx_clk.h | 140 +++++-
15
contrib/elf2dmp/addrspace.c | 7 ++-----
28
hw/misc/npcm7xx_clk.c | 805 +++++++++++++++++++++++++++++++++-
16
contrib/elf2dmp/main.c | 9 +++------
29
2 files changed, 932 insertions(+), 13 deletions(-)
17
contrib/elf2dmp/pdb.c | 19 ++++++++-----------
18
contrib/elf2dmp/qemu_elf.c | 7 ++-----
19
4 files changed, 15 insertions(+), 27 deletions(-)
30
20
31
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
21
diff --git a/contrib/elf2dmp/addrspace.c b/contrib/elf2dmp/addrspace.c
32
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
33
--- a/include/hw/misc/npcm7xx_clk.h
23
--- a/contrib/elf2dmp/addrspace.c
34
+++ b/include/hw/misc/npcm7xx_clk.h
24
+++ b/contrib/elf2dmp/addrspace.c
35
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ int pa_space_create(struct pa_space *ps, QEMU_Elf *qemu_elf)
36
#define NPCM7XX_CLK_H
26
}
37
27
}
38
#include "exec/memory.h"
28
39
+#include "hw/clock.h"
29
- ps->block = malloc(sizeof(*ps->block) * ps->block_nr);
40
#include "hw/sysbus.h"
30
- if (!ps->block) {
41
31
- return 1;
42
/*
32
- }
43
@@ -XXX,XX +XXX,XX @@
33
+ ps->block = g_new(struct pa_block, ps->block_nr);
44
34
45
#define NPCM7XX_WATCHDOG_RESET_GPIO_IN "npcm7xx-clk-watchdog-reset-gpio-in"
35
for (i = 0; i < phdr_nr; i++) {
46
36
if (phdr[i].p_type == PT_LOAD) {
47
-typedef struct NPCM7xxCLKState {
37
@@ -XXX,XX +XXX,XX @@ int pa_space_create(struct pa_space *ps, QEMU_Elf *qemu_elf)
48
+/* Maximum amount of clock inputs in a SEL module. */
38
void pa_space_destroy(struct pa_space *ps)
49
+#define NPCM7XX_CLK_SEL_MAX_INPUT 5
39
{
50
+
40
ps->block_nr = 0;
51
+/* PLLs in CLK module. */
41
- free(ps->block);
52
+typedef enum NPCM7xxClockPLL {
42
+ g_free(ps->block);
53
+ NPCM7XX_CLOCK_PLL0,
43
}
54
+ NPCM7XX_CLOCK_PLL1,
44
55
+ NPCM7XX_CLOCK_PLL2,
45
void va_space_set_dtb(struct va_space *vs, uint64_t dtb)
56
+ NPCM7XX_CLOCK_PLLG,
46
diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c
57
+ NPCM7XX_CLOCK_NR_PLLS,
58
+} NPCM7xxClockPLL;
59
+
60
+/* SEL/MUX in CLK module. */
61
+typedef enum NPCM7xxClockSEL {
62
+ NPCM7XX_CLOCK_PIXCKSEL,
63
+ NPCM7XX_CLOCK_MCCKSEL,
64
+ NPCM7XX_CLOCK_CPUCKSEL,
65
+ NPCM7XX_CLOCK_CLKOUTSEL,
66
+ NPCM7XX_CLOCK_UARTCKSEL,
67
+ NPCM7XX_CLOCK_TIMCKSEL,
68
+ NPCM7XX_CLOCK_SDCKSEL,
69
+ NPCM7XX_CLOCK_GFXMSEL,
70
+ NPCM7XX_CLOCK_SUCKSEL,
71
+ NPCM7XX_CLOCK_NR_SELS,
72
+} NPCM7xxClockSEL;
73
+
74
+/* Dividers in CLK module. */
75
+typedef enum NPCM7xxClockDivider {
76
+ NPCM7XX_CLOCK_PLL1D2, /* PLL1/2 */
77
+ NPCM7XX_CLOCK_PLL2D2, /* PLL2/2 */
78
+ NPCM7XX_CLOCK_MC_DIVIDER,
79
+ NPCM7XX_CLOCK_AXI_DIVIDER,
80
+ NPCM7XX_CLOCK_AHB_DIVIDER,
81
+ NPCM7XX_CLOCK_AHB3_DIVIDER,
82
+ NPCM7XX_CLOCK_SPI0_DIVIDER,
83
+ NPCM7XX_CLOCK_SPIX_DIVIDER,
84
+ NPCM7XX_CLOCK_APB1_DIVIDER,
85
+ NPCM7XX_CLOCK_APB2_DIVIDER,
86
+ NPCM7XX_CLOCK_APB3_DIVIDER,
87
+ NPCM7XX_CLOCK_APB4_DIVIDER,
88
+ NPCM7XX_CLOCK_APB5_DIVIDER,
89
+ NPCM7XX_CLOCK_CLKOUT_DIVIDER,
90
+ NPCM7XX_CLOCK_UART_DIVIDER,
91
+ NPCM7XX_CLOCK_TIMER_DIVIDER,
92
+ NPCM7XX_CLOCK_ADC_DIVIDER,
93
+ NPCM7XX_CLOCK_MMC_DIVIDER,
94
+ NPCM7XX_CLOCK_SDHC_DIVIDER,
95
+ NPCM7XX_CLOCK_GFXM_DIVIDER, /* divide by 3 */
96
+ NPCM7XX_CLOCK_UTMI_DIVIDER,
97
+ NPCM7XX_CLOCK_NR_DIVIDERS,
98
+} NPCM7xxClockConverter;
99
+
100
+typedef struct NPCM7xxCLKState NPCM7xxCLKState;
101
+
102
+/**
103
+ * struct NPCM7xxClockPLLState - A PLL module in CLK module.
104
+ * @name: The name of the module.
105
+ * @clk: The CLK module that owns this module.
106
+ * @clock_in: The input clock of this module.
107
+ * @clock_out: The output clock of this module.
108
+ * @reg: The control registers for this PLL module.
109
+ */
110
+typedef struct NPCM7xxClockPLLState {
111
+ DeviceState parent;
112
+
113
+ const char *name;
114
+ NPCM7xxCLKState *clk;
115
+ Clock *clock_in;
116
+ Clock *clock_out;
117
+
118
+ int reg;
119
+} NPCM7xxClockPLLState;
120
+
121
+/**
122
+ * struct NPCM7xxClockSELState - A SEL module in CLK module.
123
+ * @name: The name of the module.
124
+ * @clk: The CLK module that owns this module.
125
+ * @input_size: The size of inputs of this module.
126
+ * @clock_in: The input clocks of this module.
127
+ * @clock_out: The output clocks of this module.
128
+ * @offset: The offset of this module in the control register.
129
+ * @len: The length of this module in the control register.
130
+ */
131
+typedef struct NPCM7xxClockSELState {
132
+ DeviceState parent;
133
+
134
+ const char *name;
135
+ NPCM7xxCLKState *clk;
136
+ uint8_t input_size;
137
+ Clock *clock_in[NPCM7XX_CLK_SEL_MAX_INPUT];
138
+ Clock *clock_out;
139
+
140
+ int offset;
141
+ int len;
142
+} NPCM7xxClockSELState;
143
+
144
+/**
145
+ * struct NPCM7xxClockDividerState - A Divider module in CLK module.
146
+ * @name: The name of the module.
147
+ * @clk: The CLK module that owns this module.
148
+ * @clock_in: The input clock of this module.
149
+ * @clock_out: The output clock of this module.
150
+ * @divide: The function the divider uses to divide the input.
151
+ * @reg: The index of the control register that contains the divisor.
152
+ * @offset: The offset of the divisor in the control register.
153
+ * @len: The length of the divisor in the control register.
154
+ * @divisor: The divisor for a constant divisor
155
+ */
156
+typedef struct NPCM7xxClockDividerState {
157
+ DeviceState parent;
158
+
159
+ const char *name;
160
+ NPCM7xxCLKState *clk;
161
+ Clock *clock_in;
162
+ Clock *clock_out;
163
+
164
+ uint32_t (*divide)(struct NPCM7xxClockDividerState *s);
165
+ union {
166
+ struct {
167
+ int reg;
168
+ int offset;
169
+ int len;
170
+ };
171
+ int divisor;
172
+ };
173
+} NPCM7xxClockDividerState;
174
+
175
+struct NPCM7xxCLKState {
176
SysBusDevice parent;
177
178
MemoryRegion iomem;
179
180
+ /* Clock converters */
181
+ NPCM7xxClockPLLState plls[NPCM7XX_CLOCK_NR_PLLS];
182
+ NPCM7xxClockSELState sels[NPCM7XX_CLOCK_NR_SELS];
183
+ NPCM7xxClockDividerState dividers[NPCM7XX_CLOCK_NR_DIVIDERS];
184
+
185
uint32_t regs[NPCM7XX_CLK_NR_REGS];
186
187
/* Time reference for SECCNT and CNTR25M, initialized by power on reset */
188
int64_t ref_ns;
189
-} NPCM7xxCLKState;
190
+
191
+ /* The incoming reference clock. */
192
+ Clock *clkref;
193
+};
194
195
#define TYPE_NPCM7XX_CLK "npcm7xx-clk"
196
#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_NPCM7XX_CLK)
197
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
198
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
199
--- a/hw/misc/npcm7xx_clk.c
48
--- a/contrib/elf2dmp/main.c
200
+++ b/hw/misc/npcm7xx_clk.c
49
+++ b/contrib/elf2dmp/main.c
201
@@ -XXX,XX +XXX,XX @@
50
@@ -XXX,XX +XXX,XX @@ static KDDEBUGGER_DATA64 *get_kdbg(uint64_t KernBase, struct pdb_reader *pdb,
202
51
}
203
#include "hw/misc/npcm7xx_clk.h"
52
}
204
#include "hw/timer/npcm7xx_timer.h"
53
205
+#include "hw/qdev-clock.h"
54
- kdbg = malloc(kdbg_hdr.Size);
206
#include "migration/vmstate.h"
55
- if (!kdbg) {
207
#include "qemu/error-report.h"
56
- return NULL;
208
#include "qemu/log.h"
57
- }
209
@@ -XXX,XX +XXX,XX @@
58
+ kdbg = g_malloc(kdbg_hdr.Size);
210
#include "trace.h"
59
211
#include "sysemu/watchdog.h"
60
if (va_space_rw(vs, KdDebuggerDataBlock, kdbg, kdbg_hdr.Size, 0)) {
212
61
eprintf("Failed to extract entire KDBG\n");
213
+/*
62
- free(kdbg);
214
+ * The reference clock hz, and the SECCNT and CNTR25M registers in this module,
63
+ g_free(kdbg);
215
+ * is always 25 MHz.
64
return NULL;
216
+ */
65
}
217
+#define NPCM7XX_CLOCK_REF_HZ (25000000)
66
218
+
67
@@ -XXX,XX +XXX,XX @@ int main(int argc, char *argv[])
219
+/* Register Field Definitions */
68
}
220
+#define NPCM7XX_CLK_WDRCR_CA9C BIT(0) /* Cortex A9 Cores */
69
221
+
70
out_kdbg:
222
#define PLLCON_LOKI BIT(31)
71
- free(kdbg);
223
#define PLLCON_LOKS BIT(30)
72
+ g_free(kdbg);
224
#define PLLCON_PWDEN BIT(12)
73
out_pdb:
225
+#define PLLCON_FBDV(con) extract32((con), 16, 12)
74
pdb_exit(&pdb);
226
+#define PLLCON_OTDV2(con) extract32((con), 13, 3)
75
out_pdb_file:
227
+#define PLLCON_OTDV1(con) extract32((con), 8, 3)
76
diff --git a/contrib/elf2dmp/pdb.c b/contrib/elf2dmp/pdb.c
228
+#define PLLCON_INDV(con) extract32((con), 0, 6)
77
index XXXXXXX..XXXXXXX 100644
229
78
--- a/contrib/elf2dmp/pdb.c
230
enum NPCM7xxCLKRegisters {
79
+++ b/contrib/elf2dmp/pdb.c
231
NPCM7XX_CLK_CLKEN1,
80
@@ -XXX,XX +XXX,XX @@ uint64_t pdb_resolve(uint64_t img_base, struct pdb_reader *r, const char *name)
232
@@ -XXX,XX +XXX,XX @@ static const uint32_t cold_reset_values[NPCM7XX_CLK_NR_REGS] = {
81
233
[NPCM7XX_CLK_AHBCKFI] = 0x000000c8,
82
static void pdb_reader_ds_exit(struct pdb_reader *r)
234
};
235
236
-/* Register Field Definitions */
237
-#define NPCM7XX_CLK_WDRCR_CA9C BIT(0) /* Cortex A9 Cores */
238
-
239
/* The number of watchdogs that can trigger a reset. */
240
#define NPCM7XX_NR_WATCHDOGS (3)
241
242
+/* Clock converter functions */
243
+
244
+#define TYPE_NPCM7XX_CLOCK_PLL "npcm7xx-clock-pll"
245
+#define NPCM7XX_CLOCK_PLL(obj) OBJECT_CHECK(NPCM7xxClockPLLState, \
246
+ (obj), TYPE_NPCM7XX_CLOCK_PLL)
247
+#define TYPE_NPCM7XX_CLOCK_SEL "npcm7xx-clock-sel"
248
+#define NPCM7XX_CLOCK_SEL(obj) OBJECT_CHECK(NPCM7xxClockSELState, \
249
+ (obj), TYPE_NPCM7XX_CLOCK_SEL)
250
+#define TYPE_NPCM7XX_CLOCK_DIVIDER "npcm7xx-clock-divider"
251
+#define NPCM7XX_CLOCK_DIVIDER(obj) OBJECT_CHECK(NPCM7xxClockDividerState, \
252
+ (obj), TYPE_NPCM7XX_CLOCK_DIVIDER)
253
+
254
+static void npcm7xx_clk_update_pll(void *opaque)
255
+{
256
+ NPCM7xxClockPLLState *s = opaque;
257
+ uint32_t con = s->clk->regs[s->reg];
258
+ uint64_t freq;
259
+
260
+ /* The PLL is grounded if it is not locked yet. */
261
+ if (con & PLLCON_LOKI) {
262
+ freq = clock_get_hz(s->clock_in);
263
+ freq *= PLLCON_FBDV(con);
264
+ freq /= PLLCON_INDV(con) * PLLCON_OTDV1(con) * PLLCON_OTDV2(con);
265
+ } else {
266
+ freq = 0;
267
+ }
268
+
269
+ clock_update_hz(s->clock_out, freq);
270
+}
271
+
272
+static void npcm7xx_clk_update_sel(void *opaque)
273
+{
274
+ NPCM7xxClockSELState *s = opaque;
275
+ uint32_t index = extract32(s->clk->regs[NPCM7XX_CLK_CLKSEL], s->offset,
276
+ s->len);
277
+
278
+ if (index >= s->input_size) {
279
+ qemu_log_mask(LOG_GUEST_ERROR,
280
+ "%s: SEL index: %u out of range\n",
281
+ __func__, index);
282
+ index = 0;
283
+ }
284
+ clock_update_hz(s->clock_out, clock_get_hz(s->clock_in[index]));
285
+}
286
+
287
+static void npcm7xx_clk_update_divider(void *opaque)
288
+{
289
+ NPCM7xxClockDividerState *s = opaque;
290
+ uint32_t freq;
291
+
292
+ freq = s->divide(s);
293
+ clock_update_hz(s->clock_out, freq);
294
+}
295
+
296
+static uint32_t divide_by_constant(NPCM7xxClockDividerState *s)
297
+{
298
+ return clock_get_hz(s->clock_in) / s->divisor;
299
+}
300
+
301
+static uint32_t divide_by_reg_divisor(NPCM7xxClockDividerState *s)
302
+{
303
+ return clock_get_hz(s->clock_in) /
304
+ (extract32(s->clk->regs[s->reg], s->offset, s->len) + 1);
305
+}
306
+
307
+static uint32_t divide_by_reg_divisor_times_2(NPCM7xxClockDividerState *s)
308
+{
309
+ return divide_by_reg_divisor(s) / 2;
310
+}
311
+
312
+static uint32_t shift_by_reg_divisor(NPCM7xxClockDividerState *s)
313
+{
314
+ return clock_get_hz(s->clock_in) >>
315
+ extract32(s->clk->regs[s->reg], s->offset, s->len);
316
+}
317
+
318
+static NPCM7xxClockPLL find_pll_by_reg(enum NPCM7xxCLKRegisters reg)
319
+{
320
+ switch (reg) {
321
+ case NPCM7XX_CLK_PLLCON0:
322
+ return NPCM7XX_CLOCK_PLL0;
323
+ case NPCM7XX_CLK_PLLCON1:
324
+ return NPCM7XX_CLOCK_PLL1;
325
+ case NPCM7XX_CLK_PLLCON2:
326
+ return NPCM7XX_CLOCK_PLL2;
327
+ case NPCM7XX_CLK_PLLCONG:
328
+ return NPCM7XX_CLOCK_PLLG;
329
+ default:
330
+ g_assert_not_reached();
331
+ }
332
+}
333
+
334
+static void npcm7xx_clk_update_all_plls(NPCM7xxCLKState *clk)
335
+{
336
+ int i;
337
+
338
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
339
+ npcm7xx_clk_update_pll(&clk->plls[i]);
340
+ }
341
+}
342
+
343
+static void npcm7xx_clk_update_all_sels(NPCM7xxCLKState *clk)
344
+{
345
+ int i;
346
+
347
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
348
+ npcm7xx_clk_update_sel(&clk->sels[i]);
349
+ }
350
+}
351
+
352
+static void npcm7xx_clk_update_all_dividers(NPCM7xxCLKState *clk)
353
+{
354
+ int i;
355
+
356
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
357
+ npcm7xx_clk_update_divider(&clk->dividers[i]);
358
+ }
359
+}
360
+
361
+static void npcm7xx_clk_update_all_clocks(NPCM7xxCLKState *clk)
362
+{
363
+ clock_update_hz(clk->clkref, NPCM7XX_CLOCK_REF_HZ);
364
+ npcm7xx_clk_update_all_plls(clk);
365
+ npcm7xx_clk_update_all_sels(clk);
366
+ npcm7xx_clk_update_all_dividers(clk);
367
+}
368
+
369
+/* Types of clock sources. */
370
+typedef enum ClockSrcType {
371
+ CLKSRC_REF,
372
+ CLKSRC_PLL,
373
+ CLKSRC_SEL,
374
+ CLKSRC_DIV,
375
+} ClockSrcType;
376
+
377
+typedef struct PLLInitInfo {
378
+ const char *name;
379
+ ClockSrcType src_type;
380
+ int src_index;
381
+ int reg;
382
+ const char *public_name;
383
+} PLLInitInfo;
384
+
385
+typedef struct SELInitInfo {
386
+ const char *name;
387
+ uint8_t input_size;
388
+ ClockSrcType src_type[NPCM7XX_CLK_SEL_MAX_INPUT];
389
+ int src_index[NPCM7XX_CLK_SEL_MAX_INPUT];
390
+ int offset;
391
+ int len;
392
+ const char *public_name;
393
+} SELInitInfo;
394
+
395
+typedef struct DividerInitInfo {
396
+ const char *name;
397
+ ClockSrcType src_type;
398
+ int src_index;
399
+ uint32_t (*divide)(NPCM7xxClockDividerState *s);
400
+ int reg; /* not used when type == CONSTANT */
401
+ int offset; /* not used when type == CONSTANT */
402
+ int len; /* not used when type == CONSTANT */
403
+ int divisor; /* used only when type == CONSTANT */
404
+ const char *public_name;
405
+} DividerInitInfo;
406
+
407
+static const PLLInitInfo pll_init_info_list[] = {
408
+ [NPCM7XX_CLOCK_PLL0] = {
409
+ .name = "pll0",
410
+ .src_type = CLKSRC_REF,
411
+ .reg = NPCM7XX_CLK_PLLCON0,
412
+ },
413
+ [NPCM7XX_CLOCK_PLL1] = {
414
+ .name = "pll1",
415
+ .src_type = CLKSRC_REF,
416
+ .reg = NPCM7XX_CLK_PLLCON1,
417
+ },
418
+ [NPCM7XX_CLOCK_PLL2] = {
419
+ .name = "pll2",
420
+ .src_type = CLKSRC_REF,
421
+ .reg = NPCM7XX_CLK_PLLCON2,
422
+ },
423
+ [NPCM7XX_CLOCK_PLLG] = {
424
+ .name = "pllg",
425
+ .src_type = CLKSRC_REF,
426
+ .reg = NPCM7XX_CLK_PLLCONG,
427
+ },
428
+};
429
+
430
+static const SELInitInfo sel_init_info_list[] = {
431
+ [NPCM7XX_CLOCK_PIXCKSEL] = {
432
+ .name = "pixcksel",
433
+ .input_size = 2,
434
+ .src_type = {CLKSRC_PLL, CLKSRC_REF},
435
+ .src_index = {NPCM7XX_CLOCK_PLLG, 0},
436
+ .offset = 5,
437
+ .len = 1,
438
+ .public_name = "pixel-clock",
439
+ },
440
+ [NPCM7XX_CLOCK_MCCKSEL] = {
441
+ .name = "mccksel",
442
+ .input_size = 4,
443
+ .src_type = {CLKSRC_DIV, CLKSRC_REF, CLKSRC_REF,
444
+ /*MCBPCK, shouldn't be used in normal operation*/
445
+ CLKSRC_REF},
446
+ .src_index = {NPCM7XX_CLOCK_PLL1D2, 0, 0, 0},
447
+ .offset = 12,
448
+ .len = 2,
449
+ .public_name = "mc-phy-clock",
450
+ },
451
+ [NPCM7XX_CLOCK_CPUCKSEL] = {
452
+ .name = "cpucksel",
453
+ .input_size = 4,
454
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF,
455
+ /*SYSBPCK, shouldn't be used in normal operation*/
456
+ CLKSRC_REF},
457
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0, 0},
458
+ .offset = 0,
459
+ .len = 2,
460
+ .public_name = "system-clock",
461
+ },
462
+ [NPCM7XX_CLOCK_CLKOUTSEL] = {
463
+ .name = "clkoutsel",
464
+ .input_size = 5,
465
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF,
466
+ CLKSRC_PLL, CLKSRC_DIV},
467
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
468
+ NPCM7XX_CLOCK_PLLG, NPCM7XX_CLOCK_PLL2D2},
469
+ .offset = 18,
470
+ .len = 3,
471
+ .public_name = "tock",
472
+ },
473
+ [NPCM7XX_CLOCK_UARTCKSEL] = {
474
+ .name = "uartcksel",
475
+ .input_size = 4,
476
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
477
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
478
+ NPCM7XX_CLOCK_PLL2D2},
479
+ .offset = 8,
480
+ .len = 2,
481
+ },
482
+ [NPCM7XX_CLOCK_TIMCKSEL] = {
483
+ .name = "timcksel",
484
+ .input_size = 4,
485
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
486
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
487
+ NPCM7XX_CLOCK_PLL2D2},
488
+ .offset = 14,
489
+ .len = 2,
490
+ },
491
+ [NPCM7XX_CLOCK_SDCKSEL] = {
492
+ .name = "sdcksel",
493
+ .input_size = 4,
494
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
495
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
496
+ NPCM7XX_CLOCK_PLL2D2},
497
+ .offset = 6,
498
+ .len = 2,
499
+ },
500
+ [NPCM7XX_CLOCK_GFXMSEL] = {
501
+ .name = "gfxmksel",
502
+ .input_size = 2,
503
+ .src_type = {CLKSRC_REF, CLKSRC_PLL},
504
+ .src_index = {0, NPCM7XX_CLOCK_PLL2},
505
+ .offset = 21,
506
+ .len = 1,
507
+ },
508
+ [NPCM7XX_CLOCK_SUCKSEL] = {
509
+ .name = "sucksel",
510
+ .input_size = 4,
511
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
512
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
513
+ NPCM7XX_CLOCK_PLL2D2},
514
+ .offset = 10,
515
+ .len = 2,
516
+ },
517
+};
518
+
519
+static const DividerInitInfo divider_init_info_list[] = {
520
+ [NPCM7XX_CLOCK_PLL1D2] = {
521
+ .name = "pll1d2",
522
+ .src_type = CLKSRC_PLL,
523
+ .src_index = NPCM7XX_CLOCK_PLL1,
524
+ .divide = divide_by_constant,
525
+ .divisor = 2,
526
+ },
527
+ [NPCM7XX_CLOCK_PLL2D2] = {
528
+ .name = "pll2d2",
529
+ .src_type = CLKSRC_PLL,
530
+ .src_index = NPCM7XX_CLOCK_PLL2,
531
+ .divide = divide_by_constant,
532
+ .divisor = 2,
533
+ },
534
+ [NPCM7XX_CLOCK_MC_DIVIDER] = {
535
+ .name = "mc-divider",
536
+ .src_type = CLKSRC_SEL,
537
+ .src_index = NPCM7XX_CLOCK_MCCKSEL,
538
+ .divide = divide_by_constant,
539
+ .divisor = 2,
540
+ .public_name = "mc-clock"
541
+ },
542
+ [NPCM7XX_CLOCK_AXI_DIVIDER] = {
543
+ .name = "axi-divider",
544
+ .src_type = CLKSRC_SEL,
545
+ .src_index = NPCM7XX_CLOCK_CPUCKSEL,
546
+ .divide = shift_by_reg_divisor,
547
+ .reg = NPCM7XX_CLK_CLKDIV1,
548
+ .offset = 0,
549
+ .len = 1,
550
+ .public_name = "clk2"
551
+ },
552
+ [NPCM7XX_CLOCK_AHB_DIVIDER] = {
553
+ .name = "ahb-divider",
554
+ .src_type = CLKSRC_DIV,
555
+ .src_index = NPCM7XX_CLOCK_AXI_DIVIDER,
556
+ .divide = divide_by_reg_divisor,
557
+ .reg = NPCM7XX_CLK_CLKDIV1,
558
+ .offset = 26,
559
+ .len = 2,
560
+ .public_name = "clk4"
561
+ },
562
+ [NPCM7XX_CLOCK_AHB3_DIVIDER] = {
563
+ .name = "ahb3-divider",
564
+ .src_type = CLKSRC_DIV,
565
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
566
+ .divide = divide_by_reg_divisor,
567
+ .reg = NPCM7XX_CLK_CLKDIV1,
568
+ .offset = 6,
569
+ .len = 5,
570
+ .public_name = "ahb3-spi3-clock"
571
+ },
572
+ [NPCM7XX_CLOCK_SPI0_DIVIDER] = {
573
+ .name = "spi0-divider",
574
+ .src_type = CLKSRC_DIV,
575
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
576
+ .divide = divide_by_reg_divisor,
577
+ .reg = NPCM7XX_CLK_CLKDIV3,
578
+ .offset = 6,
579
+ .len = 5,
580
+ .public_name = "spi0-clock",
581
+ },
582
+ [NPCM7XX_CLOCK_SPIX_DIVIDER] = {
583
+ .name = "spix-divider",
584
+ .src_type = CLKSRC_DIV,
585
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
586
+ .divide = divide_by_reg_divisor,
587
+ .reg = NPCM7XX_CLK_CLKDIV3,
588
+ .offset = 1,
589
+ .len = 5,
590
+ .public_name = "spix-clock",
591
+ },
592
+ [NPCM7XX_CLOCK_APB1_DIVIDER] = {
593
+ .name = "apb1-divider",
594
+ .src_type = CLKSRC_DIV,
595
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
596
+ .divide = shift_by_reg_divisor,
597
+ .reg = NPCM7XX_CLK_CLKDIV2,
598
+ .offset = 24,
599
+ .len = 2,
600
+ .public_name = "apb1-clock",
601
+ },
602
+ [NPCM7XX_CLOCK_APB2_DIVIDER] = {
603
+ .name = "apb2-divider",
604
+ .src_type = CLKSRC_DIV,
605
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
606
+ .divide = shift_by_reg_divisor,
607
+ .reg = NPCM7XX_CLK_CLKDIV2,
608
+ .offset = 26,
609
+ .len = 2,
610
+ .public_name = "apb2-clock",
611
+ },
612
+ [NPCM7XX_CLOCK_APB3_DIVIDER] = {
613
+ .name = "apb3-divider",
614
+ .src_type = CLKSRC_DIV,
615
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
616
+ .divide = shift_by_reg_divisor,
617
+ .reg = NPCM7XX_CLK_CLKDIV2,
618
+ .offset = 28,
619
+ .len = 2,
620
+ .public_name = "apb3-clock",
621
+ },
622
+ [NPCM7XX_CLOCK_APB4_DIVIDER] = {
623
+ .name = "apb4-divider",
624
+ .src_type = CLKSRC_DIV,
625
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
626
+ .divide = shift_by_reg_divisor,
627
+ .reg = NPCM7XX_CLK_CLKDIV2,
628
+ .offset = 30,
629
+ .len = 2,
630
+ .public_name = "apb4-clock",
631
+ },
632
+ [NPCM7XX_CLOCK_APB5_DIVIDER] = {
633
+ .name = "apb5-divider",
634
+ .src_type = CLKSRC_DIV,
635
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
636
+ .divide = shift_by_reg_divisor,
637
+ .reg = NPCM7XX_CLK_CLKDIV2,
638
+ .offset = 22,
639
+ .len = 2,
640
+ .public_name = "apb5-clock",
641
+ },
642
+ [NPCM7XX_CLOCK_CLKOUT_DIVIDER] = {
643
+ .name = "clkout-divider",
644
+ .src_type = CLKSRC_SEL,
645
+ .src_index = NPCM7XX_CLOCK_CLKOUTSEL,
646
+ .divide = divide_by_reg_divisor,
647
+ .reg = NPCM7XX_CLK_CLKDIV2,
648
+ .offset = 16,
649
+ .len = 5,
650
+ .public_name = "clkout",
651
+ },
652
+ [NPCM7XX_CLOCK_UART_DIVIDER] = {
653
+ .name = "uart-divider",
654
+ .src_type = CLKSRC_SEL,
655
+ .src_index = NPCM7XX_CLOCK_UARTCKSEL,
656
+ .divide = divide_by_reg_divisor,
657
+ .reg = NPCM7XX_CLK_CLKDIV1,
658
+ .offset = 16,
659
+ .len = 5,
660
+ .public_name = "uart-clock",
661
+ },
662
+ [NPCM7XX_CLOCK_TIMER_DIVIDER] = {
663
+ .name = "timer-divider",
664
+ .src_type = CLKSRC_SEL,
665
+ .src_index = NPCM7XX_CLOCK_TIMCKSEL,
666
+ .divide = divide_by_reg_divisor,
667
+ .reg = NPCM7XX_CLK_CLKDIV1,
668
+ .offset = 21,
669
+ .len = 5,
670
+ .public_name = "timer-clock",
671
+ },
672
+ [NPCM7XX_CLOCK_ADC_DIVIDER] = {
673
+ .name = "adc-divider",
674
+ .src_type = CLKSRC_DIV,
675
+ .src_index = NPCM7XX_CLOCK_TIMER_DIVIDER,
676
+ .divide = shift_by_reg_divisor,
677
+ .reg = NPCM7XX_CLK_CLKDIV1,
678
+ .offset = 28,
679
+ .len = 3,
680
+ .public_name = "adc-clock",
681
+ },
682
+ [NPCM7XX_CLOCK_MMC_DIVIDER] = {
683
+ .name = "mmc-divider",
684
+ .src_type = CLKSRC_SEL,
685
+ .src_index = NPCM7XX_CLOCK_SDCKSEL,
686
+ .divide = divide_by_reg_divisor,
687
+ .reg = NPCM7XX_CLK_CLKDIV1,
688
+ .offset = 11,
689
+ .len = 5,
690
+ .public_name = "mmc-clock",
691
+ },
692
+ [NPCM7XX_CLOCK_SDHC_DIVIDER] = {
693
+ .name = "sdhc-divider",
694
+ .src_type = CLKSRC_SEL,
695
+ .src_index = NPCM7XX_CLOCK_SDCKSEL,
696
+ .divide = divide_by_reg_divisor_times_2,
697
+ .reg = NPCM7XX_CLK_CLKDIV2,
698
+ .offset = 0,
699
+ .len = 4,
700
+ .public_name = "sdhc-clock",
701
+ },
702
+ [NPCM7XX_CLOCK_GFXM_DIVIDER] = {
703
+ .name = "gfxm-divider",
704
+ .src_type = CLKSRC_SEL,
705
+ .src_index = NPCM7XX_CLOCK_GFXMSEL,
706
+ .divide = divide_by_constant,
707
+ .divisor = 3,
708
+ .public_name = "gfxm-clock",
709
+ },
710
+ [NPCM7XX_CLOCK_UTMI_DIVIDER] = {
711
+ .name = "utmi-divider",
712
+ .src_type = CLKSRC_SEL,
713
+ .src_index = NPCM7XX_CLOCK_SUCKSEL,
714
+ .divide = divide_by_reg_divisor,
715
+ .reg = NPCM7XX_CLK_CLKDIV2,
716
+ .offset = 8,
717
+ .len = 5,
718
+ .public_name = "utmi-clock",
719
+ },
720
+};
721
+
722
+static void npcm7xx_clk_pll_init(Object *obj)
723
+{
724
+ NPCM7xxClockPLLState *pll = NPCM7XX_CLOCK_PLL(obj);
725
+
726
+ pll->clock_in = qdev_init_clock_in(DEVICE(pll), "clock-in",
727
+ npcm7xx_clk_update_pll, pll);
728
+ pll->clock_out = qdev_init_clock_out(DEVICE(pll), "clock-out");
729
+}
730
+
731
+static void npcm7xx_clk_sel_init(Object *obj)
732
+{
733
+ int i;
734
+ NPCM7xxClockSELState *sel = NPCM7XX_CLOCK_SEL(obj);
735
+
736
+ for (i = 0; i < NPCM7XX_CLK_SEL_MAX_INPUT; ++i) {
737
+ sel->clock_in[i] = qdev_init_clock_in(DEVICE(sel),
738
+ g_strdup_printf("clock-in[%d]", i),
739
+ npcm7xx_clk_update_sel, sel);
740
+ }
741
+ sel->clock_out = qdev_init_clock_out(DEVICE(sel), "clock-out");
742
+}
743
+static void npcm7xx_clk_divider_init(Object *obj)
744
+{
745
+ NPCM7xxClockDividerState *div = NPCM7XX_CLOCK_DIVIDER(obj);
746
+
747
+ div->clock_in = qdev_init_clock_in(DEVICE(div), "clock-in",
748
+ npcm7xx_clk_update_divider, div);
749
+ div->clock_out = qdev_init_clock_out(DEVICE(div), "clock-out");
750
+}
751
+
752
+static void npcm7xx_init_clock_pll(NPCM7xxClockPLLState *pll,
753
+ NPCM7xxCLKState *clk, const PLLInitInfo *init_info)
754
+{
755
+ pll->name = init_info->name;
756
+ pll->clk = clk;
757
+ pll->reg = init_info->reg;
758
+ if (init_info->public_name != NULL) {
759
+ qdev_alias_clock(DEVICE(pll), "clock-out", DEVICE(clk),
760
+ init_info->public_name);
761
+ }
762
+}
763
+
764
+static void npcm7xx_init_clock_sel(NPCM7xxClockSELState *sel,
765
+ NPCM7xxCLKState *clk, const SELInitInfo *init_info)
766
+{
767
+ int input_size = init_info->input_size;
768
+
769
+ sel->name = init_info->name;
770
+ sel->clk = clk;
771
+ sel->input_size = init_info->input_size;
772
+ g_assert(input_size <= NPCM7XX_CLK_SEL_MAX_INPUT);
773
+ sel->offset = init_info->offset;
774
+ sel->len = init_info->len;
775
+ if (init_info->public_name != NULL) {
776
+ qdev_alias_clock(DEVICE(sel), "clock-out", DEVICE(clk),
777
+ init_info->public_name);
778
+ }
779
+}
780
+
781
+static void npcm7xx_init_clock_divider(NPCM7xxClockDividerState *div,
782
+ NPCM7xxCLKState *clk, const DividerInitInfo *init_info)
783
+{
784
+ div->name = init_info->name;
785
+ div->clk = clk;
786
+
787
+ div->divide = init_info->divide;
788
+ if (div->divide == divide_by_constant) {
789
+ div->divisor = init_info->divisor;
790
+ } else {
791
+ div->reg = init_info->reg;
792
+ div->offset = init_info->offset;
793
+ div->len = init_info->len;
794
+ }
795
+ if (init_info->public_name != NULL) {
796
+ qdev_alias_clock(DEVICE(div), "clock-out", DEVICE(clk),
797
+ init_info->public_name);
798
+ }
799
+}
800
+
801
+static Clock *npcm7xx_get_clock(NPCM7xxCLKState *clk, ClockSrcType type,
802
+ int index)
803
+{
804
+ switch (type) {
805
+ case CLKSRC_REF:
806
+ return clk->clkref;
807
+ case CLKSRC_PLL:
808
+ return clk->plls[index].clock_out;
809
+ case CLKSRC_SEL:
810
+ return clk->sels[index].clock_out;
811
+ case CLKSRC_DIV:
812
+ return clk->dividers[index].clock_out;
813
+ default:
814
+ g_assert_not_reached();
815
+ }
816
+}
817
+
818
+static void npcm7xx_connect_clocks(NPCM7xxCLKState *clk)
819
+{
820
+ int i, j;
821
+ Clock *src;
822
+
823
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
824
+ src = npcm7xx_get_clock(clk, pll_init_info_list[i].src_type,
825
+ pll_init_info_list[i].src_index);
826
+ clock_set_source(clk->plls[i].clock_in, src);
827
+ }
828
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
829
+ for (j = 0; j < sel_init_info_list[i].input_size; ++j) {
830
+ src = npcm7xx_get_clock(clk, sel_init_info_list[i].src_type[j],
831
+ sel_init_info_list[i].src_index[j]);
832
+ clock_set_source(clk->sels[i].clock_in[j], src);
833
+ }
834
+ }
835
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
836
+ src = npcm7xx_get_clock(clk, divider_init_info_list[i].src_type,
837
+ divider_init_info_list[i].src_index);
838
+ clock_set_source(clk->dividers[i].clock_in, src);
839
+ }
840
+}
841
+
842
static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size)
843
{
83
{
844
uint32_t reg = offset / sizeof(uint32_t);
84
- free(r->ds.toc);
845
@@ -XXX,XX +XXX,XX @@ static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size)
85
+ g_free(r->ds.toc);
846
*
847
* The 4 LSBs are always zero: (1e9 / 640) << 4 = 25000000.
848
*/
849
- value = (((now_ns - s->ref_ns) / 640) << 4) % NPCM7XX_TIMER_REF_HZ;
850
+ value = (((now_ns - s->ref_ns) / 640) << 4) % NPCM7XX_CLOCK_REF_HZ;
851
break;
852
853
default:
854
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_write(void *opaque, hwaddr offset,
855
value |= (value & PLLCON_LOKS);
856
}
857
}
858
+ /* Only update PLL when it is locked. */
859
+ if (value & PLLCON_LOKI) {
860
+ npcm7xx_clk_update_pll(&s->plls[find_pll_by_reg(reg)]);
861
+ }
862
+ break;
863
+
864
+ case NPCM7XX_CLK_CLKSEL:
865
+ npcm7xx_clk_update_all_sels(s);
866
+ break;
867
+
868
+ case NPCM7XX_CLK_CLKDIV1:
869
+ case NPCM7XX_CLK_CLKDIV2:
870
+ case NPCM7XX_CLK_CLKDIV3:
871
+ npcm7xx_clk_update_all_dividers(s);
872
break;
873
874
case NPCM7XX_CLK_CNTR25M:
875
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_enter_reset(Object *obj, ResetType type)
876
case RESET_TYPE_COLD:
877
memcpy(s->regs, cold_reset_values, sizeof(cold_reset_values));
878
s->ref_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
879
+ npcm7xx_clk_update_all_clocks(s);
880
return;
881
}
882
883
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_enter_reset(Object *obj, ResetType type)
884
__func__, type);
885
}
86
}
886
87
887
+static void npcm7xx_clk_init_clock_hierarchy(NPCM7xxCLKState *s)
88
static void pdb_exit_symbols(struct pdb_reader *r)
888
+{
889
+ int i;
890
+
891
+ s->clkref = qdev_init_clock_in(DEVICE(s), "clkref", NULL, NULL);
892
+
893
+ /* First pass: init all converter modules */
894
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(pll_init_info_list) != NPCM7XX_CLOCK_NR_PLLS);
895
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(sel_init_info_list) != NPCM7XX_CLOCK_NR_SELS);
896
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(divider_init_info_list)
897
+ != NPCM7XX_CLOCK_NR_DIVIDERS);
898
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
899
+ object_initialize_child(OBJECT(s), pll_init_info_list[i].name,
900
+ &s->plls[i], TYPE_NPCM7XX_CLOCK_PLL);
901
+ npcm7xx_init_clock_pll(&s->plls[i], s,
902
+ &pll_init_info_list[i]);
903
+ }
904
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
905
+ object_initialize_child(OBJECT(s), sel_init_info_list[i].name,
906
+ &s->sels[i], TYPE_NPCM7XX_CLOCK_SEL);
907
+ npcm7xx_init_clock_sel(&s->sels[i], s,
908
+ &sel_init_info_list[i]);
909
+ }
910
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
911
+ object_initialize_child(OBJECT(s), divider_init_info_list[i].name,
912
+ &s->dividers[i], TYPE_NPCM7XX_CLOCK_DIVIDER);
913
+ npcm7xx_init_clock_divider(&s->dividers[i], s,
914
+ &divider_init_info_list[i]);
915
+ }
916
+
917
+ /* Second pass: connect converter modules */
918
+ npcm7xx_connect_clocks(s);
919
+
920
+ clock_update_hz(s->clkref, NPCM7XX_CLOCK_REF_HZ);
921
+}
922
+
923
static void npcm7xx_clk_init(Object *obj)
924
{
89
{
925
NPCM7xxCLKState *s = NPCM7XX_CLK(obj);
90
- free(r->modimage);
926
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_init(Object *obj)
91
- free(r->symbols);
927
memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
92
+ g_free(r->modimage);
928
TYPE_NPCM7XX_CLK, 4 * KiB);
93
+ g_free(r->symbols);
929
sysbus_init_mmio(&s->parent, &s->iomem);
930
- qdev_init_gpio_in_named(DEVICE(s), npcm7xx_clk_perform_watchdog_reset,
931
- NPCM7XX_WATCHDOG_RESET_GPIO_IN, NPCM7XX_NR_WATCHDOGS);
932
}
94
}
933
95
934
-static const VMStateDescription vmstate_npcm7xx_clk = {
96
static void pdb_exit_segments(struct pdb_reader *r)
935
- .name = "npcm7xx-clk",
936
+static int npcm7xx_clk_post_load(void *opaque, int version_id)
937
+{
938
+ if (version_id >= 1) {
939
+ NPCM7xxCLKState *clk = opaque;
940
+
941
+ npcm7xx_clk_update_all_clocks(clk);
942
+ }
943
+
944
+ return 0;
945
+}
946
+
947
+static void npcm7xx_clk_realize(DeviceState *dev, Error **errp)
948
+{
949
+ int i;
950
+ NPCM7xxCLKState *s = NPCM7XX_CLK(dev);
951
+
952
+ qdev_init_gpio_in_named(DEVICE(s), npcm7xx_clk_perform_watchdog_reset,
953
+ NPCM7XX_WATCHDOG_RESET_GPIO_IN, NPCM7XX_NR_WATCHDOGS);
954
+ npcm7xx_clk_init_clock_hierarchy(s);
955
+
956
+ /* Realize child devices */
957
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
958
+ if (!qdev_realize(DEVICE(&s->plls[i]), NULL, errp)) {
959
+ return;
960
+ }
961
+ }
962
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
963
+ if (!qdev_realize(DEVICE(&s->sels[i]), NULL, errp)) {
964
+ return;
965
+ }
966
+ }
967
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
968
+ if (!qdev_realize(DEVICE(&s->dividers[i]), NULL, errp)) {
969
+ return;
970
+ }
971
+ }
972
+}
973
+
974
+static const VMStateDescription vmstate_npcm7xx_clk_pll = {
975
+ .name = "npcm7xx-clock-pll",
976
.version_id = 0,
977
.minimum_version_id = 0,
978
- .fields = (VMStateField[]) {
979
- VMSTATE_UINT32_ARRAY(regs, NPCM7xxCLKState, NPCM7XX_CLK_NR_REGS),
980
- VMSTATE_INT64(ref_ns, NPCM7xxCLKState),
981
+ .fields = (VMStateField[]) {
982
+ VMSTATE_CLOCK(clock_in, NPCM7xxClockPLLState),
983
VMSTATE_END_OF_LIST(),
984
},
985
};
986
987
+static const VMStateDescription vmstate_npcm7xx_clk_sel = {
988
+ .name = "npcm7xx-clock-sel",
989
+ .version_id = 0,
990
+ .minimum_version_id = 0,
991
+ .fields = (VMStateField[]) {
992
+ VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(clock_in, NPCM7xxClockSELState,
993
+ NPCM7XX_CLK_SEL_MAX_INPUT, 0, vmstate_clock, Clock),
994
+ VMSTATE_END_OF_LIST(),
995
+ },
996
+};
997
+
998
+static const VMStateDescription vmstate_npcm7xx_clk_divider = {
999
+ .name = "npcm7xx-clock-divider",
1000
+ .version_id = 0,
1001
+ .minimum_version_id = 0,
1002
+ .fields = (VMStateField[]) {
1003
+ VMSTATE_CLOCK(clock_in, NPCM7xxClockDividerState),
1004
+ VMSTATE_END_OF_LIST(),
1005
+ },
1006
+};
1007
+
1008
+static const VMStateDescription vmstate_npcm7xx_clk = {
1009
+ .name = "npcm7xx-clk",
1010
+ .version_id = 1,
1011
+ .minimum_version_id = 1,
1012
+ .post_load = npcm7xx_clk_post_load,
1013
+ .fields = (VMStateField[]) {
1014
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxCLKState, NPCM7XX_CLK_NR_REGS),
1015
+ VMSTATE_INT64(ref_ns, NPCM7xxCLKState),
1016
+ VMSTATE_CLOCK(clkref, NPCM7xxCLKState),
1017
+ VMSTATE_END_OF_LIST(),
1018
+ },
1019
+};
1020
+
1021
+static void npcm7xx_clk_pll_class_init(ObjectClass *klass, void *data)
1022
+{
1023
+ DeviceClass *dc = DEVICE_CLASS(klass);
1024
+
1025
+ dc->desc = "NPCM7xx Clock PLL Module";
1026
+ dc->vmsd = &vmstate_npcm7xx_clk_pll;
1027
+}
1028
+
1029
+static void npcm7xx_clk_sel_class_init(ObjectClass *klass, void *data)
1030
+{
1031
+ DeviceClass *dc = DEVICE_CLASS(klass);
1032
+
1033
+ dc->desc = "NPCM7xx Clock SEL Module";
1034
+ dc->vmsd = &vmstate_npcm7xx_clk_sel;
1035
+}
1036
+
1037
+static void npcm7xx_clk_divider_class_init(ObjectClass *klass, void *data)
1038
+{
1039
+ DeviceClass *dc = DEVICE_CLASS(klass);
1040
+
1041
+ dc->desc = "NPCM7xx Clock Divider Module";
1042
+ dc->vmsd = &vmstate_npcm7xx_clk_divider;
1043
+}
1044
+
1045
static void npcm7xx_clk_class_init(ObjectClass *klass, void *data)
1046
{
97
{
1047
ResettableClass *rc = RESETTABLE_CLASS(klass);
98
- free(r->segs);
1048
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_class_init(ObjectClass *klass, void *data)
99
+ g_free(r->segs);
1049
1050
dc->desc = "NPCM7xx Clock Control Registers";
1051
dc->vmsd = &vmstate_npcm7xx_clk;
1052
+ dc->realize = npcm7xx_clk_realize;
1053
rc->phases.enter = npcm7xx_clk_enter_reset;
1054
}
100
}
1055
101
1056
+static const TypeInfo npcm7xx_clk_pll_info = {
102
static void *pdb_ds_read(const PDB_DS_HEADER *header,
1057
+ .name = TYPE_NPCM7XX_CLOCK_PLL,
103
@@ -XXX,XX +XXX,XX @@ static void *pdb_ds_read(const PDB_DS_HEADER *header,
1058
+ .parent = TYPE_DEVICE,
104
1059
+ .instance_size = sizeof(NPCM7xxClockPLLState),
105
nBlocks = (size + header->block_size - 1) / header->block_size;
1060
+ .instance_init = npcm7xx_clk_pll_init,
106
1061
+ .class_init = npcm7xx_clk_pll_class_init,
107
- buffer = malloc(nBlocks * header->block_size);
1062
+};
108
- if (!buffer) {
1063
+
109
- return NULL;
1064
+static const TypeInfo npcm7xx_clk_sel_info = {
110
- }
1065
+ .name = TYPE_NPCM7XX_CLOCK_SEL,
111
+ buffer = g_malloc(nBlocks * header->block_size);
1066
+ .parent = TYPE_DEVICE,
112
1067
+ .instance_size = sizeof(NPCM7xxClockSELState),
113
for (i = 0; i < nBlocks; i++) {
1068
+ .instance_init = npcm7xx_clk_sel_init,
114
memcpy(buffer + i * header->block_size, (const char *)header +
1069
+ .class_init = npcm7xx_clk_sel_class_init,
115
@@ -XXX,XX +XXX,XX @@ static int pdb_init_symbols(struct pdb_reader *r)
1070
+};
116
return 0;
1071
+
117
1072
+static const TypeInfo npcm7xx_clk_divider_info = {
118
out_symbols:
1073
+ .name = TYPE_NPCM7XX_CLOCK_DIVIDER,
119
- free(symbols);
1074
+ .parent = TYPE_DEVICE,
120
+ g_free(symbols);
1075
+ .instance_size = sizeof(NPCM7xxClockDividerState),
121
1076
+ .instance_init = npcm7xx_clk_divider_init,
122
return err;
1077
+ .class_init = npcm7xx_clk_divider_class_init,
123
}
1078
+};
124
@@ -XXX,XX +XXX,XX @@ static int pdb_reader_init(struct pdb_reader *r, void *data)
1079
+
125
out_sym:
1080
static const TypeInfo npcm7xx_clk_info = {
126
pdb_exit_symbols(r);
1081
.name = TYPE_NPCM7XX_CLK,
127
out_root:
1082
.parent = TYPE_SYS_BUS_DEVICE,
128
- free(r->ds.root);
1083
@@ -XXX,XX +XXX,XX @@ static const TypeInfo npcm7xx_clk_info = {
129
+ g_free(r->ds.root);
1084
130
out_ds:
1085
static void npcm7xx_clk_register_type(void)
131
pdb_reader_ds_exit(r);
132
133
@@ -XXX,XX +XXX,XX @@ static void pdb_reader_exit(struct pdb_reader *r)
1086
{
134
{
1087
+ type_register_static(&npcm7xx_clk_pll_info);
135
pdb_exit_segments(r);
1088
+ type_register_static(&npcm7xx_clk_sel_info);
136
pdb_exit_symbols(r);
1089
+ type_register_static(&npcm7xx_clk_divider_info);
137
- free(r->ds.root);
1090
type_register_static(&npcm7xx_clk_info);
138
+ g_free(r->ds.root);
139
pdb_reader_ds_exit(r);
1091
}
140
}
1092
type_init(npcm7xx_clk_register_type);
141
142
diff --git a/contrib/elf2dmp/qemu_elf.c b/contrib/elf2dmp/qemu_elf.c
143
index XXXXXXX..XXXXXXX 100644
144
--- a/contrib/elf2dmp/qemu_elf.c
145
+++ b/contrib/elf2dmp/qemu_elf.c
146
@@ -XXX,XX +XXX,XX @@ static int init_states(QEMU_Elf *qe)
147
148
printf("%zu CPU states has been found\n", cpu_nr);
149
150
- qe->state = malloc(sizeof(*qe->state) * cpu_nr);
151
- if (!qe->state) {
152
- return 1;
153
- }
154
+ qe->state = g_new(QEMUCPUState*, cpu_nr);
155
156
cpu_nr = 0;
157
158
@@ -XXX,XX +XXX,XX @@ static int init_states(QEMU_Elf *qe)
159
160
static void exit_states(QEMU_Elf *qe)
161
{
162
- free(qe->state);
163
+ g_free(qe->state);
164
}
165
166
static bool check_ehdr(QEMU_Elf *qe)
1093
--
167
--
1094
2.20.1
168
2.34.1
1095
1096
diff view generated by jsdifflib