1
The big thing here is RTH's patchset implementing ARMv8.1-VHE
1
arm queue; dunno if this will be the last before softfreeze
2
emulation; otherwise just a handful of smaller fixes.
2
or not, but anyway probably the last large one. New orangepi-pc
3
board model is the big item here.
3
4
4
thanks
5
thanks
5
-- PMM
6
-- PMM
6
7
7
The following changes since commit 346ed3151f1c43e72c40cb55b392a1d4cface62c:
8
The following changes since commit 67d9ef7d541c3d21a25796c51c26da096a433565:
8
9
9
Merge remote-tracking branch 'remotes/awilliam/tags/vfio-update-20200206.0' into staging (2020-02-07 11:52:15 +0000)
10
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-docs-20200312' into staging (2020-03-12 15:20:52 +0000)
10
11
11
are available in the Git repository at:
12
are available in the Git repository at:
12
13
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200207
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200312
14
15
15
for you to fetch changes up to af6c91b490e9b1bce7a168f8a9c848f3e60f616e:
16
for you to fetch changes up to aca53be34ac3e7cac5f39396a51a338860a5a837:
16
17
17
stellaris: delay timer_new to avoid memleaks (2020-02-07 14:04:28 +0000)
18
target/arm: kvm: Inject events at the last stage of sync (2020-03-12 16:31:10 +0000)
18
19
19
----------------------------------------------------------------
20
----------------------------------------------------------------
20
target-arm queue:
21
target-arm queue:
21
* monitor: fix query-cpu-model-expansion crash when using machine type none
22
* Fix various bugs that might result in an assert() due to
22
* Support emulation of the ARMv8.1-VHE architecture feature
23
incorrect hflags for M-profile CPUs
23
* bcm2835_dma: fix bugs in TD mode handling
24
* Fix Aspeed SMC Controller user-mode select handling
24
* docs/arm-cpu-features: Make kvm-no-adjvtime comment clearer
25
* Report correct (with-tag) address in fault address register
25
* stellaris, stm32f2xx_timer, armv7m_systick: fix minor memory leaks
26
when TBI is enabled
27
* cubieboard: make sure SOC object isn't leaked
28
* fsl-imx25: Wire up eSDHC controllers
29
* fsl-imx25: Wire up USB controllers
30
* New board model: orangepi-pc (OrangePi PC)
31
* ARM/KVM: if user doesn't select GIC version and the
32
host kernel can only provide GICv3, use that, rather
33
than defaulting to "fail because GICv2 isn't possible"
34
* kvm: Only do KVM_SET_VCPU_EVENTS at the last stage of sync
26
35
27
----------------------------------------------------------------
36
----------------------------------------------------------------
28
Alex Bennée (1):
37
Beata Michalska (1):
29
target/arm: check TGE and E2H flags for EL0 pauth traps
38
target/arm: kvm: Inject events at the last stage of sync
30
39
31
Liang Yan (1):
40
Cédric Le Goater (2):
32
target/arm/monitor: query-cpu-model-expansion crashed qemu when using machine type none
41
aspeed/smc: Add some tracing
42
aspeed/smc: Fix User mode select/unselect scheme
33
43
34
Pan Nengyuan (3):
44
Eric Auger (6):
35
armv7m_systick: delay timer_new to avoid memleaks
45
hw/arm/virt: Document 'max' value in gic-version property description
36
stm32f2xx_timer: delay timer_new to avoid memleaks
46
hw/arm/virt: Introduce VirtGICType enum type
37
stellaris: delay timer_new to avoid memleaks
47
hw/arm/virt: Introduce finalize_gic_version()
48
target/arm/kvm: Let kvm_arm_vgic_probe() return a bitmap
49
hw/arm/virt: kvm: Restructure finalize_gic_version()
50
hw/arm/virt: kvm: allow gicv3 by default if v2 cannot work
38
51
39
Philippe Mathieu-Daudé (1):
52
Guenter Roeck (2):
40
docs/arm-cpu-features: Make kvm-no-adjvtime comment clearer
53
hw/arm/fsl-imx25: Wire up eSDHC controllers
54
hw/arm/fsl-imx25: Wire up USB controllers
41
55
42
Rene Stange (2):
56
Igor Mammedov (1):
43
bcm2835_dma: Fix the ylen loop in TD mode
57
hw/arm/cubieboard: make sure SOC object isn't leaked
44
bcm2835_dma: Re-initialize xlen in TD mode
45
58
46
Richard Henderson (40):
59
Niek Linnenbank (13):
47
target/arm: Define isar_feature_aa64_vh
60
hw/arm: add Allwinner H3 System-on-Chip
48
target/arm: Enable HCR_E2H for VHE
61
hw/arm: add Xunlong Orange Pi PC machine
49
target/arm: Add CONTEXTIDR_EL2
62
hw/arm/allwinner-h3: add Clock Control Unit
50
target/arm: Add TTBR1_EL2
63
hw/arm/allwinner-h3: add USB host controller
51
target/arm: Update CNTVCT_EL0 for VHE
64
hw/arm/allwinner-h3: add System Control module
52
target/arm: Split out vae1_tlbmask
65
hw/arm/allwinner: add CPU Configuration module
53
target/arm: Split out alle1_tlbmask
66
hw/arm/allwinner: add Security Identifier device
54
target/arm: Simplify tlb_force_broadcast alternatives
67
hw/arm/allwinner: add SD/MMC host controller
55
target/arm: Rename ARMMMUIdx*_S12NSE* to ARMMMUIdx*_E10_*
68
hw/arm/allwinner-h3: add EMAC ethernet device
56
target/arm: Rename ARMMMUIdx_S2NS to ARMMMUIdx_Stage2
69
hw/arm/allwinner-h3: add Boot ROM support
57
target/arm: Rename ARMMMUIdx_S1NSE* to ARMMMUIdx_Stage1_E*
70
hw/arm/allwinner-h3: add SDRAM controller device
58
target/arm: Rename ARMMMUIdx_S1SE[01] to ARMMMUIdx_SE10_[01]
71
hw/arm/allwinner: add RTC device support
59
target/arm: Rename ARMMMUIdx*_S1E3 to ARMMMUIdx*_SE3
72
docs: add Orange Pi PC document
60
target/arm: Rename ARMMMUIdx_S1E2 to ARMMMUIdx_E2
61
target/arm: Recover 4 bits from TBFLAGs
62
target/arm: Expand TBFLAG_ANY.MMUIDX to 4 bits
63
target/arm: Rearrange ARMMMUIdxBit
64
target/arm: Tidy ARMMMUIdx m-profile definitions
65
target/arm: Reorganize ARMMMUIdx
66
target/arm: Add regime_has_2_ranges
67
target/arm: Update arm_mmu_idx for VHE
68
target/arm: Update arm_sctlr for VHE
69
target/arm: Update aa64_zva_access for EL2
70
target/arm: Update ctr_el0_access for EL2
71
target/arm: Add the hypervisor virtual counter
72
target/arm: Update timer access for VHE
73
target/arm: Update define_one_arm_cp_reg_with_opaque for VHE
74
target/arm: Add VHE system register redirection and aliasing
75
target/arm: Add VHE timer register redirection and aliasing
76
target/arm: Flush tlb for ASID changes in EL2&0 translation regime
77
target/arm: Flush tlbs for E2&0 translation regime
78
target/arm: Update arm_phys_excp_target_el for TGE
79
target/arm: Update {fp,sve}_exception_el for VHE
80
target/arm: Update get_a64_user_mem_index for VHE
81
target/arm: Update arm_cpu_do_interrupt_aarch64 for VHE
82
target/arm: Enable ARMv8.1-VHE in -cpu max
83
target/arm: Move arm_excp_unmasked to cpu.c
84
target/arm: Pass more cpu state to arm_excp_unmasked
85
target/arm: Use bool for unmasked in arm_excp_unmasked
86
target/arm: Raise only one interrupt in arm_cpu_exec_interrupt
87
73
88
target/arm/cpu-param.h | 2 +-
74
Peter Maydell (4):
89
target/arm/cpu-qom.h | 1 +
75
hw/intc/armv7m_nvic: Rebuild hflags on reset
90
target/arm/cpu.h | 423 ++++++----------
76
target/arm: Update hflags in trans_CPS_v7m()
91
target/arm/internals.h | 73 ++-
77
target/arm: Recalculate hflags correctly after writes to CONTROL
92
target/arm/translate.h | 4 +-
78
target/arm: Fix some comment typos
93
hw/arm/stellaris.c | 7 +-
94
hw/dma/bcm2835_dma.c | 8 +-
95
hw/timer/armv7m_systick.c | 6 +
96
hw/timer/stm32f2xx_timer.c | 5 +
97
target/arm/cpu.c | 162 +++++-
98
target/arm/cpu64.c | 1 +
99
target/arm/debug_helper.c | 50 +-
100
target/arm/helper-a64.c | 2 +-
101
target/arm/helper.c | 1211 ++++++++++++++++++++++++++++++++------------
102
target/arm/monitor.c | 15 +-
103
target/arm/pauth_helper.c | 14 +-
104
target/arm/translate-a64.c | 47 +-
105
target/arm/translate.c | 74 +--
106
docs/arm-cpu-features.rst | 2 +-
107
19 files changed, 1415 insertions(+), 692 deletions(-)
108
79
80
Philippe Mathieu-Daudé (5):
81
tests/boot_linux_console: Add a quick test for the OrangePi PC board
82
tests/boot_linux_console: Add initrd test for the Orange Pi PC board
83
tests/boot_linux_console: Add a SD card test for the OrangePi PC board
84
tests/boot_linux_console: Add a SLOW test booting Ubuntu on OrangePi PC
85
tests/boot_linux_console: Test booting NetBSD via U-Boot on OrangePi PC
86
87
Richard Henderson (2):
88
target/arm: Check addresses for disabled regimes
89
target/arm: Disable clean_data_tbi for system mode
90
91
Makefile.objs | 1 +
92
hw/arm/Makefile.objs | 1 +
93
hw/misc/Makefile.objs | 5 +
94
hw/net/Makefile.objs | 1 +
95
hw/rtc/Makefile.objs | 1 +
96
hw/sd/Makefile.objs | 1 +
97
hw/usb/hcd-ehci.h | 1 +
98
include/hw/arm/allwinner-a10.h | 4 +
99
include/hw/arm/allwinner-h3.h | 161 ++++++
100
include/hw/arm/fsl-imx25.h | 18 +
101
include/hw/arm/virt.h | 12 +-
102
include/hw/misc/allwinner-cpucfg.h | 52 ++
103
include/hw/misc/allwinner-h3-ccu.h | 66 +++
104
include/hw/misc/allwinner-h3-dramc.h | 106 ++++
105
include/hw/misc/allwinner-h3-sysctrl.h | 67 +++
106
include/hw/misc/allwinner-sid.h | 60 +++
107
include/hw/net/allwinner-sun8i-emac.h | 99 ++++
108
include/hw/rtc/allwinner-rtc.h | 134 +++++
109
include/hw/sd/allwinner-sdhost.h | 135 +++++
110
target/arm/helper.h | 1 +
111
target/arm/kvm_arm.h | 3 +
112
hw/arm/allwinner-a10.c | 19 +
113
hw/arm/allwinner-h3.c | 465 ++++++++++++++++++
114
hw/arm/cubieboard.c | 18 +
115
hw/arm/fsl-imx25.c | 56 +++
116
hw/arm/imx25_pdk.c | 16 +
117
hw/arm/orangepi.c | 130 +++++
118
hw/arm/virt.c | 145 ++++--
119
hw/intc/armv7m_nvic.c | 6 +
120
hw/misc/allwinner-cpucfg.c | 282 +++++++++++
121
hw/misc/allwinner-h3-ccu.c | 242 +++++++++
122
hw/misc/allwinner-h3-dramc.c | 358 ++++++++++++++
123
hw/misc/allwinner-h3-sysctrl.c | 140 ++++++
124
hw/misc/allwinner-sid.c | 168 +++++++
125
hw/net/allwinner-sun8i-emac.c | 871 +++++++++++++++++++++++++++++++++
126
hw/rtc/allwinner-rtc.c | 411 ++++++++++++++++
127
hw/sd/allwinner-sdhost.c | 854 ++++++++++++++++++++++++++++++++
128
hw/ssi/aspeed_smc.c | 56 ++-
129
hw/usb/hcd-ehci-sysbus.c | 17 +
130
target/arm/helper.c | 49 +-
131
target/arm/kvm.c | 14 +-
132
target/arm/kvm32.c | 15 +-
133
target/arm/kvm64.c | 15 +-
134
target/arm/translate-a64.c | 11 +
135
target/arm/translate.c | 14 +-
136
MAINTAINERS | 9 +
137
default-configs/arm-softmmu.mak | 1 +
138
docs/system/arm/orangepi.rst | 253 ++++++++++
139
docs/system/target-arm.rst | 2 +
140
hw/arm/Kconfig | 12 +
141
hw/misc/trace-events | 19 +
142
hw/net/Kconfig | 3 +
143
hw/net/trace-events | 10 +
144
hw/rtc/trace-events | 4 +
145
hw/sd/trace-events | 7 +
146
hw/ssi/trace-events | 10 +
147
tests/acceptance/boot_linux_console.py | 230 +++++++++
148
57 files changed, 5787 insertions(+), 74 deletions(-)
149
create mode 100644 include/hw/arm/allwinner-h3.h
150
create mode 100644 include/hw/misc/allwinner-cpucfg.h
151
create mode 100644 include/hw/misc/allwinner-h3-ccu.h
152
create mode 100644 include/hw/misc/allwinner-h3-dramc.h
153
create mode 100644 include/hw/misc/allwinner-h3-sysctrl.h
154
create mode 100644 include/hw/misc/allwinner-sid.h
155
create mode 100644 include/hw/net/allwinner-sun8i-emac.h
156
create mode 100644 include/hw/rtc/allwinner-rtc.h
157
create mode 100644 include/hw/sd/allwinner-sdhost.h
158
create mode 100644 hw/arm/allwinner-h3.c
159
create mode 100644 hw/arm/orangepi.c
160
create mode 100644 hw/misc/allwinner-cpucfg.c
161
create mode 100644 hw/misc/allwinner-h3-ccu.c
162
create mode 100644 hw/misc/allwinner-h3-dramc.c
163
create mode 100644 hw/misc/allwinner-h3-sysctrl.c
164
create mode 100644 hw/misc/allwinner-sid.c
165
create mode 100644 hw/net/allwinner-sun8i-emac.c
166
create mode 100644 hw/rtc/allwinner-rtc.c
167
create mode 100644 hw/sd/allwinner-sdhost.c
168
create mode 100644 docs/system/arm/orangepi.rst
169
create mode 100644 hw/ssi/trace-events
170
diff view generated by jsdifflib
Deleted patch
1
From: Liang Yan <lyan@suse.com>
2
1
3
Commit e19afd566781 mentioned that target-arm only supports queryable
4
cpu models 'max', 'host', and the current type when KVM is in use.
5
The logic works well until using machine type none.
6
7
For machine type none, cpu_type will be null if cpu option is not
8
set by command line, strlen(cpu_type) will terminate process.
9
So We add a check above it.
10
11
This won't affect i386 and s390x since they do not use current_cpu.
12
13
Signed-off-by: Liang Yan <lyan@suse.com>
14
Message-id: 20200203134251.12986-1-lyan@suse.com
15
Reviewed-by: Andrew Jones <drjones@redhat.com>
16
Tested-by: Andrew Jones <drjones@redhat.com>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
target/arm/monitor.c | 15 +++++++++------
20
1 file changed, 9 insertions(+), 6 deletions(-)
21
22
diff --git a/target/arm/monitor.c b/target/arm/monitor.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/monitor.c
25
+++ b/target/arm/monitor.c
26
@@ -XXX,XX +XXX,XX @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
27
}
28
29
if (kvm_enabled()) {
30
- const char *cpu_type = current_machine->cpu_type;
31
- int len = strlen(cpu_type) - strlen(ARM_CPU_TYPE_SUFFIX);
32
bool supported = false;
33
34
if (!strcmp(model->name, "host") || !strcmp(model->name, "max")) {
35
/* These are kvmarm's recommended cpu types */
36
supported = true;
37
- } else if (strlen(model->name) == len &&
38
- !strncmp(model->name, cpu_type, len)) {
39
- /* KVM is enabled and we're using this type, so it works. */
40
- supported = true;
41
+ } else if (current_machine->cpu_type) {
42
+ const char *cpu_type = current_machine->cpu_type;
43
+ int len = strlen(cpu_type) - strlen(ARM_CPU_TYPE_SUFFIX);
44
+
45
+ if (strlen(model->name) == len &&
46
+ !strncmp(model->name, cpu_type, len)) {
47
+ /* KVM is enabled and we're using this type, so it works. */
48
+ supported = true;
49
+ }
50
}
51
if (!supported) {
52
error_setg(errp, "We cannot guarantee the CPU type '%s' works "
53
--
54
2.20.1
55
56
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Tested-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200206105448.4726-2-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
target/arm/cpu.h | 5 +++++
10
1 file changed, 5 insertions(+)
11
12
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.h
15
+++ b/target/arm/cpu.h
16
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_sve(const ARMISARegisters *id)
17
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0;
18
}
19
20
+static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
21
+{
22
+ return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
23
+}
24
+
25
static inline bool isar_feature_aa64_lor(const ARMISARegisters *id)
26
{
27
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, LO) != 0;
28
--
29
2.20.1
30
31
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Tested-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200206105448.4726-3-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
target/arm/cpu.h | 7 -------
10
target/arm/helper.c | 6 +++++-
11
2 files changed, 5 insertions(+), 8 deletions(-)
12
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 void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
18
#define HCR_ATA (1ULL << 56)
19
#define HCR_DCT (1ULL << 57)
20
21
-/*
22
- * When we actually implement ARMv8.1-VHE we should add HCR_E2H to
23
- * HCR_MASK and then clear it again if the feature bit is not set in
24
- * hcr_write().
25
- */
26
-#define HCR_MASK ((1ULL << 34) - 1)
27
-
28
#define SCR_NS (1U << 0)
29
#define SCR_IRQ (1U << 1)
30
#define SCR_FIQ (1U << 2)
31
diff --git a/target/arm/helper.c b/target/arm/helper.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/helper.c
34
+++ b/target/arm/helper.c
35
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_no_el2_v8_cp_reginfo[] = {
36
static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
37
{
38
ARMCPU *cpu = env_archcpu(env);
39
- uint64_t valid_mask = HCR_MASK;
40
+ /* Begin with bits defined in base ARMv8.0. */
41
+ uint64_t valid_mask = MAKE_64BIT_MASK(0, 34);
42
43
if (arm_feature(env, ARM_FEATURE_EL3)) {
44
valid_mask &= ~HCR_HCD;
45
@@ -XXX,XX +XXX,XX @@ static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
46
*/
47
valid_mask &= ~HCR_TSC;
48
}
49
+ if (cpu_isar_feature(aa64_vh, cpu)) {
50
+ valid_mask |= HCR_E2H;
51
+ }
52
if (cpu_isar_feature(aa64_lor, cpu)) {
53
valid_mask |= HCR_TLOR;
54
}
55
--
56
2.20.1
57
58
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Some of an M-profile CPU's cached hflags state depends on state that's
2
in our NVIC object. We already do an hflags rebuild when the NVIC
3
registers are written, but we also need to do this on NVIC reset,
4
because there's no guarantee that this will happen before the
5
CPU reset.
2
6
3
The EL1&0 regime is the only one that uses 2-stage translation.
7
This fixes an assertion due to mismatched hflags which happens if
8
the CPU is reset from inside a HardFault handler.
4
9
5
Tested-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200206105448.4726-11-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20200303174950.3298-2-peter.maydell@linaro.org
10
---
13
---
11
target/arm/cpu.h | 4 +--
14
hw/intc/armv7m_nvic.c | 6 ++++++
12
target/arm/internals.h | 2 +-
15
1 file changed, 6 insertions(+)
13
target/arm/helper.c | 57 ++++++++++++++++++++------------------
14
target/arm/translate-a64.c | 2 +-
15
target/arm/translate.c | 2 +-
16
5 files changed, 35 insertions(+), 32 deletions(-)
17
16
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
19
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.h
19
--- a/hw/intc/armv7m_nvic.c
21
+++ b/target/arm/cpu.h
20
+++ b/hw/intc/armv7m_nvic.c
22
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdx {
21
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_reset(DeviceState *dev)
23
ARMMMUIdx_S1E3 = 3 | ARM_MMU_IDX_A,
22
s->itns[i] = true;
24
ARMMMUIdx_S1SE0 = 4 | ARM_MMU_IDX_A,
25
ARMMMUIdx_S1SE1 = 5 | ARM_MMU_IDX_A,
26
- ARMMMUIdx_S2NS = 6 | ARM_MMU_IDX_A,
27
+ ARMMMUIdx_Stage2 = 6 | ARM_MMU_IDX_A,
28
ARMMMUIdx_MUser = 0 | ARM_MMU_IDX_M,
29
ARMMMUIdx_MPriv = 1 | ARM_MMU_IDX_M,
30
ARMMMUIdx_MUserNegPri = 2 | ARM_MMU_IDX_M,
31
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdxBit {
32
ARMMMUIdxBit_S1E3 = 1 << 3,
33
ARMMMUIdxBit_S1SE0 = 1 << 4,
34
ARMMMUIdxBit_S1SE1 = 1 << 5,
35
- ARMMMUIdxBit_S2NS = 1 << 6,
36
+ ARMMMUIdxBit_Stage2 = 1 << 6,
37
ARMMMUIdxBit_MUser = 1 << 0,
38
ARMMMUIdxBit_MPriv = 1 << 1,
39
ARMMMUIdxBit_MUserNegPri = 1 << 2,
40
diff --git a/target/arm/internals.h b/target/arm/internals.h
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/internals.h
43
+++ b/target/arm/internals.h
44
@@ -XXX,XX +XXX,XX @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
45
case ARMMMUIdx_S1NSE0:
46
case ARMMMUIdx_S1NSE1:
47
case ARMMMUIdx_S1E2:
48
- case ARMMMUIdx_S2NS:
49
+ case ARMMMUIdx_Stage2:
50
case ARMMMUIdx_MPrivNegPri:
51
case ARMMMUIdx_MUserNegPri:
52
case ARMMMUIdx_MPriv:
53
diff --git a/target/arm/helper.c b/target/arm/helper.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/helper.c
56
+++ b/target/arm/helper.c
57
@@ -XXX,XX +XXX,XX @@ static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri,
58
tlb_flush_by_mmuidx(cs,
59
ARMMMUIdxBit_E10_1 |
60
ARMMMUIdxBit_E10_0 |
61
- ARMMMUIdxBit_S2NS);
62
+ ARMMMUIdxBit_Stage2);
63
}
64
65
static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
66
@@ -XXX,XX +XXX,XX @@ static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
67
tlb_flush_by_mmuidx_all_cpus_synced(cs,
68
ARMMMUIdxBit_E10_1 |
69
ARMMMUIdxBit_E10_0 |
70
- ARMMMUIdxBit_S2NS);
71
+ ARMMMUIdxBit_Stage2);
72
}
73
74
static void tlbiipas2_write(CPUARMState *env, const ARMCPRegInfo *ri,
75
@@ -XXX,XX +XXX,XX @@ static void tlbiipas2_write(CPUARMState *env, const ARMCPRegInfo *ri,
76
77
pageaddr = sextract64(value << 12, 0, 40);
78
79
- tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_S2NS);
80
+ tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_Stage2);
81
}
82
83
static void tlbiipas2_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
84
@@ -XXX,XX +XXX,XX @@ static void tlbiipas2_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
85
pageaddr = sextract64(value << 12, 0, 40);
86
87
tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
88
- ARMMMUIdxBit_S2NS);
89
+ ARMMMUIdxBit_Stage2);
90
}
91
92
static void tlbiall_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
93
@@ -XXX,XX +XXX,XX @@ static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
94
ARMCPU *cpu = env_archcpu(env);
95
CPUState *cs = CPU(cpu);
96
97
- /* Accesses to VTTBR may change the VMID so we must flush the TLB. */
98
+ /*
99
+ * A change in VMID to the stage2 page table (Stage2) invalidates
100
+ * the combined stage 1&2 tlbs (EL10_1 and EL10_0).
101
+ */
102
if (raw_read(env, ri) != value) {
103
tlb_flush_by_mmuidx(cs,
104
ARMMMUIdxBit_E10_1 |
105
ARMMMUIdxBit_E10_0 |
106
- ARMMMUIdxBit_S2NS);
107
+ ARMMMUIdxBit_Stage2);
108
raw_write(env, ri, value);
109
}
110
}
111
@@ -XXX,XX +XXX,XX @@ static int alle1_tlbmask(CPUARMState *env)
112
if (arm_is_secure_below_el3(env)) {
113
return ARMMMUIdxBit_S1SE1 | ARMMMUIdxBit_S1SE0;
114
} else if (arm_feature(env, ARM_FEATURE_EL2)) {
115
- return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0 | ARMMMUIdxBit_S2NS;
116
+ return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0 | ARMMMUIdxBit_Stage2;
117
} else {
118
return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0;
119
}
120
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_ipas2e1_write(CPUARMState *env, const ARMCPRegInfo *ri,
121
122
pageaddr = sextract64(value << 12, 0, 48);
123
124
- tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_S2NS);
125
+ tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_Stage2);
126
}
127
128
static void tlbi_aa64_ipas2e1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
129
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_ipas2e1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
130
pageaddr = sextract64(value << 12, 0, 48);
131
132
tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
133
- ARMMMUIdxBit_S2NS);
134
+ ARMMMUIdxBit_Stage2);
135
}
136
137
static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri,
138
@@ -XXX,XX +XXX,XX @@ void arm_cpu_do_interrupt(CPUState *cs)
139
static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
140
{
141
switch (mmu_idx) {
142
- case ARMMMUIdx_S2NS:
143
+ case ARMMMUIdx_Stage2:
144
case ARMMMUIdx_S1E2:
145
return 2;
146
case ARMMMUIdx_S1E3:
147
@@ -XXX,XX +XXX,XX @@ static inline bool regime_translation_disabled(CPUARMState *env,
148
}
23
}
149
}
24
}
150
25
+
151
- if (mmu_idx == ARMMMUIdx_S2NS) {
26
+ /*
152
+ if (mmu_idx == ARMMMUIdx_Stage2) {
27
+ * We updated state that affects the CPU's MMUidx and thus its hflags;
153
/* HCR.DC means HCR.VM behaves as 1 */
28
+ * and we can't guarantee that we run before the CPU reset function.
154
return (env->cp15.hcr_el2 & (HCR_DC | HCR_VM)) == 0;
29
+ */
155
}
30
+ arm_rebuild_hflags(&s->cpu->env);
156
@@ -XXX,XX +XXX,XX @@ static inline bool regime_translation_big_endian(CPUARMState *env,
157
static inline uint64_t regime_ttbr(CPUARMState *env, ARMMMUIdx mmu_idx,
158
int ttbrn)
159
{
160
- if (mmu_idx == ARMMMUIdx_S2NS) {
161
+ if (mmu_idx == ARMMMUIdx_Stage2) {
162
return env->cp15.vttbr_el2;
163
}
164
if (ttbrn == 0) {
165
@@ -XXX,XX +XXX,XX @@ static inline uint64_t regime_ttbr(CPUARMState *env, ARMMMUIdx mmu_idx,
166
/* Return the TCR controlling this translation regime */
167
static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
168
{
169
- if (mmu_idx == ARMMMUIdx_S2NS) {
170
+ if (mmu_idx == ARMMMUIdx_Stage2) {
171
return &env->cp15.vtcr_el2;
172
}
173
return &env->cp15.tcr_el[regime_el(env, mmu_idx)];
174
@@ -XXX,XX +XXX,XX @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
175
bool have_wxn;
176
int wxn = 0;
177
178
- assert(mmu_idx != ARMMMUIdx_S2NS);
179
+ assert(mmu_idx != ARMMMUIdx_Stage2);
180
181
user_rw = simple_ap_to_rw_prot_is_user(ap, true);
182
if (is_user) {
183
@@ -XXX,XX +XXX,XX @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
184
ARMMMUFaultInfo *fi)
185
{
186
if ((mmu_idx == ARMMMUIdx_S1NSE0 || mmu_idx == ARMMMUIdx_S1NSE1) &&
187
- !regime_translation_disabled(env, ARMMMUIdx_S2NS)) {
188
+ !regime_translation_disabled(env, ARMMMUIdx_Stage2)) {
189
target_ulong s2size;
190
hwaddr s2pa;
191
int s2prot;
192
@@ -XXX,XX +XXX,XX @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
193
pcacheattrs = &cacheattrs;
194
}
195
196
- ret = get_phys_addr_lpae(env, addr, 0, ARMMMUIdx_S2NS, &s2pa,
197
+ ret = get_phys_addr_lpae(env, addr, 0, ARMMMUIdx_Stage2, &s2pa,
198
&txattrs, &s2prot, &s2size, fi, pcacheattrs);
199
if (ret) {
200
assert(fi->type != ARMFault_None);
201
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
202
tsz = extract32(tcr, 0, 6);
203
using64k = extract32(tcr, 14, 1);
204
using16k = extract32(tcr, 15, 1);
205
- if (mmu_idx == ARMMMUIdx_S2NS) {
206
+ if (mmu_idx == ARMMMUIdx_Stage2) {
207
/* VTCR_EL2 */
208
tbi = tbid = hpd = false;
209
} else {
210
@@ -XXX,XX +XXX,XX @@ static ARMVAParameters aa32_va_parameters(CPUARMState *env, uint32_t va,
211
int select, tsz;
212
bool epd, hpd;
213
214
- if (mmu_idx == ARMMMUIdx_S2NS) {
215
+ if (mmu_idx == ARMMMUIdx_Stage2) {
216
/* VTCR */
217
bool sext = extract32(tcr, 4, 1);
218
bool sign = extract32(tcr, 3, 1);
219
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
220
level = 1;
221
/* There is no TTBR1 for EL2 */
222
ttbr1_valid = (el != 2);
223
- addrsize = (mmu_idx == ARMMMUIdx_S2NS ? 40 : 32);
224
+ addrsize = (mmu_idx == ARMMMUIdx_Stage2 ? 40 : 32);
225
inputsize = addrsize - param.tsz;
226
}
227
228
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
229
goto do_fault;
230
}
231
232
- if (mmu_idx != ARMMMUIdx_S2NS) {
233
+ if (mmu_idx != ARMMMUIdx_Stage2) {
234
/* The starting level depends on the virtual address size (which can
235
* be up to 48 bits) and the translation granule size. It indicates
236
* the number of strides (stride bits at a time) needed to
237
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
238
attrs = extract64(descriptor, 2, 10)
239
| (extract64(descriptor, 52, 12) << 10);
240
241
- if (mmu_idx == ARMMMUIdx_S2NS) {
242
+ if (mmu_idx == ARMMMUIdx_Stage2) {
243
/* Stage 2 table descriptors do not include any attribute fields */
244
break;
245
}
246
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
247
ap = extract32(attrs, 4, 2);
248
xn = extract32(attrs, 12, 1);
249
250
- if (mmu_idx == ARMMMUIdx_S2NS) {
251
+ if (mmu_idx == ARMMMUIdx_Stage2) {
252
ns = true;
253
*prot = get_S2prot(env, ap, xn);
254
} else {
255
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
256
}
257
258
if (cacheattrs != NULL) {
259
- if (mmu_idx == ARMMMUIdx_S2NS) {
260
+ if (mmu_idx == ARMMMUIdx_Stage2) {
261
cacheattrs->attrs = convert_stage2_attrs(env,
262
extract32(attrs, 0, 4));
263
} else {
264
@@ -XXX,XX +XXX,XX @@ do_fault:
265
fi->type = fault_type;
266
fi->level = level;
267
/* Tag the error as S2 for failed S1 PTW at S2 or ordinary S2. */
268
- fi->stage2 = fi->s1ptw || (mmu_idx == ARMMMUIdx_S2NS);
269
+ fi->stage2 = fi->s1ptw || (mmu_idx == ARMMMUIdx_Stage2);
270
return true;
271
}
31
}
272
32
273
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
33
static void nvic_systick_trigger(void *opaque, int n, int level)
274
prot, page_size, fi, cacheattrs);
275
276
/* If S1 fails or S2 is disabled, return early. */
277
- if (ret || regime_translation_disabled(env, ARMMMUIdx_S2NS)) {
278
+ if (ret || regime_translation_disabled(env, ARMMMUIdx_Stage2)) {
279
*phys_ptr = ipa;
280
return ret;
281
}
282
283
/* S1 is done. Now do S2 translation. */
284
- ret = get_phys_addr_lpae(env, ipa, access_type, ARMMMUIdx_S2NS,
285
+ ret = get_phys_addr_lpae(env, ipa, access_type, ARMMMUIdx_Stage2,
286
phys_ptr, attrs, &s2_prot,
287
page_size, fi,
288
cacheattrs != NULL ? &cacheattrs2 : NULL);
289
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
290
/* Fast Context Switch Extension. This doesn't exist at all in v8.
291
* In v7 and earlier it affects all stage 1 translations.
292
*/
293
- if (address < 0x02000000 && mmu_idx != ARMMMUIdx_S2NS
294
+ if (address < 0x02000000 && mmu_idx != ARMMMUIdx_Stage2
295
&& !arm_feature(env, ARM_FEATURE_V8)) {
296
if (regime_el(env, mmu_idx) == 3) {
297
address += env->cp15.fcseidr_s;
298
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
299
index XXXXXXX..XXXXXXX 100644
300
--- a/target/arm/translate-a64.c
301
+++ b/target/arm/translate-a64.c
302
@@ -XXX,XX +XXX,XX @@ static inline int get_a64_user_mem_index(DisasContext *s)
303
case ARMMMUIdx_S1SE1:
304
useridx = ARMMMUIdx_S1SE0;
305
break;
306
- case ARMMMUIdx_S2NS:
307
+ case ARMMMUIdx_Stage2:
308
g_assert_not_reached();
309
default:
310
useridx = s->mmu_idx;
311
diff --git a/target/arm/translate.c b/target/arm/translate.c
312
index XXXXXXX..XXXXXXX 100644
313
--- a/target/arm/translate.c
314
+++ b/target/arm/translate.c
315
@@ -XXX,XX +XXX,XX @@ static inline int get_a32_user_mem_index(DisasContext *s)
316
case ARMMMUIdx_MSUserNegPri:
317
case ARMMMUIdx_MSPrivNegPri:
318
return arm_to_core_mmu_idx(ARMMMUIdx_MSUserNegPri);
319
- case ARMMMUIdx_S2NS:
320
+ case ARMMMUIdx_Stage2:
321
default:
322
g_assert_not_reached();
323
}
324
--
34
--
325
2.20.1
35
2.20.1
326
36
327
37
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
For M-profile CPUs, the FAULTMASK value affects the CPU's MMU index
2
(it changes the NegPri bit). We update the hflags after calls
3
to the v7m_msr helper in trans_MSR_v7m() but forgot to do so
4
in trans_CPS_v7m().
2
5
3
This is part of a reorganization to the set of mmu_idx.
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
This emphasizes that they apply to the Secure EL1&0 regime.
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200303174950.3298-3-peter.maydell@linaro.org
9
---
10
target/arm/translate.c | 5 ++++-
11
1 file changed, 4 insertions(+), 1 deletion(-)
5
12
6
Tested-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200206105448.4726-13-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/cpu.h | 8 ++++----
13
target/arm/internals.h | 4 ++--
14
target/arm/translate.h | 2 +-
15
target/arm/helper.c | 26 +++++++++++++-------------
16
target/arm/translate-a64.c | 4 ++--
17
target/arm/translate.c | 6 +++---
18
6 files changed, 25 insertions(+), 25 deletions(-)
19
20
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.h
23
+++ b/target/arm/cpu.h
24
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdx {
25
ARMMMUIdx_E10_1 = 1 | ARM_MMU_IDX_A,
26
ARMMMUIdx_S1E2 = 2 | ARM_MMU_IDX_A,
27
ARMMMUIdx_S1E3 = 3 | ARM_MMU_IDX_A,
28
- ARMMMUIdx_S1SE0 = 4 | ARM_MMU_IDX_A,
29
- ARMMMUIdx_S1SE1 = 5 | ARM_MMU_IDX_A,
30
+ ARMMMUIdx_SE10_0 = 4 | ARM_MMU_IDX_A,
31
+ ARMMMUIdx_SE10_1 = 5 | ARM_MMU_IDX_A,
32
ARMMMUIdx_Stage2 = 6 | ARM_MMU_IDX_A,
33
ARMMMUIdx_MUser = 0 | ARM_MMU_IDX_M,
34
ARMMMUIdx_MPriv = 1 | ARM_MMU_IDX_M,
35
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdxBit {
36
ARMMMUIdxBit_E10_1 = 1 << 1,
37
ARMMMUIdxBit_S1E2 = 1 << 2,
38
ARMMMUIdxBit_S1E3 = 1 << 3,
39
- ARMMMUIdxBit_S1SE0 = 1 << 4,
40
- ARMMMUIdxBit_S1SE1 = 1 << 5,
41
+ ARMMMUIdxBit_SE10_0 = 1 << 4,
42
+ ARMMMUIdxBit_SE10_1 = 1 << 5,
43
ARMMMUIdxBit_Stage2 = 1 << 6,
44
ARMMMUIdxBit_MUser = 1 << 0,
45
ARMMMUIdxBit_MPriv = 1 << 1,
46
diff --git a/target/arm/internals.h b/target/arm/internals.h
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/internals.h
49
+++ b/target/arm/internals.h
50
@@ -XXX,XX +XXX,XX @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
51
case ARMMMUIdx_MUser:
52
return false;
53
case ARMMMUIdx_S1E3:
54
- case ARMMMUIdx_S1SE0:
55
- case ARMMMUIdx_S1SE1:
56
+ case ARMMMUIdx_SE10_0:
57
+ case ARMMMUIdx_SE10_1:
58
case ARMMMUIdx_MSPrivNegPri:
59
case ARMMMUIdx_MSUserNegPri:
60
case ARMMMUIdx_MSPriv:
61
diff --git a/target/arm/translate.h b/target/arm/translate.h
62
index XXXXXXX..XXXXXXX 100644
63
--- a/target/arm/translate.h
64
+++ b/target/arm/translate.h
65
@@ -XXX,XX +XXX,XX @@ static inline int default_exception_el(DisasContext *s)
66
* exceptions can only be routed to ELs above 1, so we target the higher of
67
* 1 or the current EL.
68
*/
69
- return (s->mmu_idx == ARMMMUIdx_S1SE0 && s->secure_routed_to_el3)
70
+ return (s->mmu_idx == ARMMMUIdx_SE10_0 && s->secure_routed_to_el3)
71
? 3 : MAX(1, s->current_el);
72
}
73
74
diff --git a/target/arm/helper.c b/target/arm/helper.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/target/arm/helper.c
77
+++ b/target/arm/helper.c
78
@@ -XXX,XX +XXX,XX @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
79
mmu_idx = ARMMMUIdx_Stage1_E1;
80
break;
81
case 1:
82
- mmu_idx = secure ? ARMMMUIdx_S1SE1 : ARMMMUIdx_Stage1_E1;
83
+ mmu_idx = secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_Stage1_E1;
84
break;
85
default:
86
g_assert_not_reached();
87
@@ -XXX,XX +XXX,XX @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
88
/* stage 1 current state PL0: ATS1CUR, ATS1CUW */
89
switch (el) {
90
case 3:
91
- mmu_idx = ARMMMUIdx_S1SE0;
92
+ mmu_idx = ARMMMUIdx_SE10_0;
93
break;
94
case 2:
95
mmu_idx = ARMMMUIdx_Stage1_E0;
96
break;
97
case 1:
98
- mmu_idx = secure ? ARMMMUIdx_S1SE0 : ARMMMUIdx_Stage1_E0;
99
+ mmu_idx = secure ? ARMMMUIdx_SE10_0 : ARMMMUIdx_Stage1_E0;
100
break;
101
default:
102
g_assert_not_reached();
103
@@ -XXX,XX +XXX,XX @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
104
case 0:
105
switch (ri->opc1) {
106
case 0: /* AT S1E1R, AT S1E1W */
107
- mmu_idx = secure ? ARMMMUIdx_S1SE1 : ARMMMUIdx_Stage1_E1;
108
+ mmu_idx = secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_Stage1_E1;
109
break;
110
case 4: /* AT S1E2R, AT S1E2W */
111
mmu_idx = ARMMMUIdx_S1E2;
112
@@ -XXX,XX +XXX,XX @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
113
}
114
break;
115
case 2: /* AT S1E0R, AT S1E0W */
116
- mmu_idx = secure ? ARMMMUIdx_S1SE0 : ARMMMUIdx_Stage1_E0;
117
+ mmu_idx = secure ? ARMMMUIdx_SE10_0 : ARMMMUIdx_Stage1_E0;
118
break;
119
case 4: /* AT S12E1R, AT S12E1W */
120
- mmu_idx = secure ? ARMMMUIdx_S1SE1 : ARMMMUIdx_E10_1;
121
+ mmu_idx = secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_E10_1;
122
break;
123
case 6: /* AT S12E0R, AT S12E0W */
124
- mmu_idx = secure ? ARMMMUIdx_S1SE0 : ARMMMUIdx_E10_0;
125
+ mmu_idx = secure ? ARMMMUIdx_SE10_0 : ARMMMUIdx_E10_0;
126
break;
127
default:
128
g_assert_not_reached();
129
@@ -XXX,XX +XXX,XX @@ static CPAccessResult aa64_cacheop_access(CPUARMState *env,
130
static int vae1_tlbmask(CPUARMState *env)
131
{
132
if (arm_is_secure_below_el3(env)) {
133
- return ARMMMUIdxBit_S1SE1 | ARMMMUIdxBit_S1SE0;
134
+ return ARMMMUIdxBit_SE10_1 | ARMMMUIdxBit_SE10_0;
135
} else {
136
return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0;
137
}
138
@@ -XXX,XX +XXX,XX @@ static int alle1_tlbmask(CPUARMState *env)
139
* stage 1 translations.
140
*/
141
if (arm_is_secure_below_el3(env)) {
142
- return ARMMMUIdxBit_S1SE1 | ARMMMUIdxBit_S1SE0;
143
+ return ARMMMUIdxBit_SE10_1 | ARMMMUIdxBit_SE10_0;
144
} else if (arm_feature(env, ARM_FEATURE_EL2)) {
145
return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0 | ARMMMUIdxBit_Stage2;
146
} else {
147
@@ -XXX,XX +XXX,XX @@ static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
148
return 2;
149
case ARMMMUIdx_S1E3:
150
return 3;
151
- case ARMMMUIdx_S1SE0:
152
+ case ARMMMUIdx_SE10_0:
153
return arm_el_is_aa64(env, 3) ? 1 : 3;
154
- case ARMMMUIdx_S1SE1:
155
+ case ARMMMUIdx_SE10_1:
156
case ARMMMUIdx_Stage1_E0:
157
case ARMMMUIdx_Stage1_E1:
158
case ARMMMUIdx_MPrivNegPri:
159
@@ -XXX,XX +XXX,XX @@ bool arm_s1_regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx)
160
static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
161
{
162
switch (mmu_idx) {
163
- case ARMMMUIdx_S1SE0:
164
+ case ARMMMUIdx_SE10_0:
165
case ARMMMUIdx_Stage1_E0:
166
case ARMMMUIdx_MUser:
167
case ARMMMUIdx_MSUser:
168
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
169
}
170
171
if (el < 2 && arm_is_secure_below_el3(env)) {
172
- return ARMMMUIdx_S1SE0 + el;
173
+ return ARMMMUIdx_SE10_0 + el;
174
} else {
175
return ARMMMUIdx_E10_0 + el;
176
}
177
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
178
index XXXXXXX..XXXXXXX 100644
179
--- a/target/arm/translate-a64.c
180
+++ b/target/arm/translate-a64.c
181
@@ -XXX,XX +XXX,XX @@ static inline int get_a64_user_mem_index(DisasContext *s)
182
case ARMMMUIdx_E10_1:
183
useridx = ARMMMUIdx_E10_0;
184
break;
185
- case ARMMMUIdx_S1SE1:
186
- useridx = ARMMMUIdx_S1SE0;
187
+ case ARMMMUIdx_SE10_1:
188
+ useridx = ARMMMUIdx_SE10_0;
189
break;
190
case ARMMMUIdx_Stage2:
191
g_assert_not_reached();
192
diff --git a/target/arm/translate.c b/target/arm/translate.c
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
193
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
194
--- a/target/arm/translate.c
15
--- a/target/arm/translate.c
195
+++ b/target/arm/translate.c
16
+++ b/target/arm/translate.c
196
@@ -XXX,XX +XXX,XX @@ static inline int get_a32_user_mem_index(DisasContext *s)
17
@@ -XXX,XX +XXX,XX @@ static bool trans_CPS(DisasContext *s, arg_CPS *a)
197
case ARMMMUIdx_E10_1:
18
198
return arm_to_core_mmu_idx(ARMMMUIdx_E10_0);
19
static bool trans_CPS_v7m(DisasContext *s, arg_CPS_v7m *a)
199
case ARMMMUIdx_S1E3:
20
{
200
- case ARMMMUIdx_S1SE0:
21
- TCGv_i32 tmp, addr;
201
- case ARMMMUIdx_S1SE1:
22
+ TCGv_i32 tmp, addr, el;
202
- return arm_to_core_mmu_idx(ARMMMUIdx_S1SE0);
23
203
+ case ARMMMUIdx_SE10_0:
24
if (!arm_dc_feature(s, ARM_FEATURE_M)) {
204
+ case ARMMMUIdx_SE10_1:
25
return false;
205
+ return arm_to_core_mmu_idx(ARMMMUIdx_SE10_0);
26
@@ -XXX,XX +XXX,XX @@ static bool trans_CPS_v7m(DisasContext *s, arg_CPS_v7m *a)
206
case ARMMMUIdx_MUser:
27
gen_helper_v7m_msr(cpu_env, addr, tmp);
207
case ARMMMUIdx_MPriv:
28
tcg_temp_free_i32(addr);
208
return arm_to_core_mmu_idx(ARMMMUIdx_MUser);
29
}
30
+ el = tcg_const_i32(s->current_el);
31
+ gen_helper_rebuild_hflags_m32(cpu_env, el);
32
+ tcg_temp_free_i32(el);
33
tcg_temp_free_i32(tmp);
34
gen_lookup_tb(s);
35
return true;
209
--
36
--
210
2.20.1
37
2.20.1
211
38
212
39
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
A write to the CONTROL register can change our current EL (by
2
writing to the nPRIV bit). That means that we can't assume
3
that s->current_el is still valid in trans_MSR_v7m() when
4
we try to rebuild the hflags.
2
5
3
This is part of a reorganization to the set of mmu_idx.
6
Add a new helper rebuild_hflags_m32_newel() which, like the
4
The EL3 regime only has a single stage translation, and
7
existing rebuild_hflags_a32_newel(), recalculates the current
5
is always secure.
8
EL from scratch, and use it in trans_MSR_v7m().
6
9
7
Tested-by: Alex Bennée <alex.bennee@linaro.org>
10
This fixes an assertion about an hflags mismatch when the
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
guest changes privilege by writing to CONTROL.
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
10
Message-id: 20200206105448.4726-14-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20200303174950.3298-4-peter.maydell@linaro.org
12
---
16
---
13
target/arm/cpu.h | 4 ++--
17
target/arm/helper.h | 1 +
14
target/arm/internals.h | 2 +-
18
target/arm/helper.c | 12 ++++++++++++
15
target/arm/helper.c | 14 +++++++-------
19
target/arm/translate.c | 7 +++----
16
target/arm/translate.c | 2 +-
20
3 files changed, 16 insertions(+), 4 deletions(-)
17
4 files changed, 11 insertions(+), 11 deletions(-)
18
21
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
22
diff --git a/target/arm/helper.h b/target/arm/helper.h
20
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.h
24
--- a/target/arm/helper.h
22
+++ b/target/arm/cpu.h
25
+++ b/target/arm/helper.h
23
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdx {
26
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_4(msr_banked, void, env, i32, i32, i32)
24
ARMMMUIdx_E10_0 = 0 | ARM_MMU_IDX_A,
27
DEF_HELPER_2(get_user_reg, i32, env, i32)
25
ARMMMUIdx_E10_1 = 1 | ARM_MMU_IDX_A,
28
DEF_HELPER_3(set_user_reg, void, env, i32, i32)
26
ARMMMUIdx_S1E2 = 2 | ARM_MMU_IDX_A,
29
27
- ARMMMUIdx_S1E3 = 3 | ARM_MMU_IDX_A,
30
+DEF_HELPER_FLAGS_1(rebuild_hflags_m32_newel, TCG_CALL_NO_RWG, void, env)
28
+ ARMMMUIdx_SE3 = 3 | ARM_MMU_IDX_A,
31
DEF_HELPER_FLAGS_2(rebuild_hflags_m32, TCG_CALL_NO_RWG, void, env, int)
29
ARMMMUIdx_SE10_0 = 4 | ARM_MMU_IDX_A,
32
DEF_HELPER_FLAGS_1(rebuild_hflags_a32_newel, TCG_CALL_NO_RWG, void, env)
30
ARMMMUIdx_SE10_1 = 5 | ARM_MMU_IDX_A,
33
DEF_HELPER_FLAGS_2(rebuild_hflags_a32, TCG_CALL_NO_RWG, void, env, int)
31
ARMMMUIdx_Stage2 = 6 | ARM_MMU_IDX_A,
32
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdxBit {
33
ARMMMUIdxBit_E10_0 = 1 << 0,
34
ARMMMUIdxBit_E10_1 = 1 << 1,
35
ARMMMUIdxBit_S1E2 = 1 << 2,
36
- ARMMMUIdxBit_S1E3 = 1 << 3,
37
+ ARMMMUIdxBit_SE3 = 1 << 3,
38
ARMMMUIdxBit_SE10_0 = 1 << 4,
39
ARMMMUIdxBit_SE10_1 = 1 << 5,
40
ARMMMUIdxBit_Stage2 = 1 << 6,
41
diff --git a/target/arm/internals.h b/target/arm/internals.h
42
index XXXXXXX..XXXXXXX 100644
43
--- a/target/arm/internals.h
44
+++ b/target/arm/internals.h
45
@@ -XXX,XX +XXX,XX @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
46
case ARMMMUIdx_MPriv:
47
case ARMMMUIdx_MUser:
48
return false;
49
- case ARMMMUIdx_S1E3:
50
+ case ARMMMUIdx_SE3:
51
case ARMMMUIdx_SE10_0:
52
case ARMMMUIdx_SE10_1:
53
case ARMMMUIdx_MSPrivNegPri:
54
diff --git a/target/arm/helper.c b/target/arm/helper.c
34
diff --git a/target/arm/helper.c b/target/arm/helper.c
55
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
56
--- a/target/arm/helper.c
36
--- a/target/arm/helper.c
57
+++ b/target/arm/helper.c
37
+++ b/target/arm/helper.c
58
@@ -XXX,XX +XXX,XX @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
38
@@ -XXX,XX +XXX,XX @@ void arm_rebuild_hflags(CPUARMState *env)
59
/* stage 1 current state PL1: ATS1CPR, ATS1CPW */
39
env->hflags = rebuild_hflags_internal(env);
60
switch (el) {
61
case 3:
62
- mmu_idx = ARMMMUIdx_S1E3;
63
+ mmu_idx = ARMMMUIdx_SE3;
64
break;
65
case 2:
66
mmu_idx = ARMMMUIdx_Stage1_E1;
67
@@ -XXX,XX +XXX,XX @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
68
mmu_idx = ARMMMUIdx_S1E2;
69
break;
70
case 6: /* AT S1E3R, AT S1E3W */
71
- mmu_idx = ARMMMUIdx_S1E3;
72
+ mmu_idx = ARMMMUIdx_SE3;
73
break;
74
default:
75
g_assert_not_reached();
76
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_alle3_write(CPUARMState *env, const ARMCPRegInfo *ri,
77
ARMCPU *cpu = env_archcpu(env);
78
CPUState *cs = CPU(cpu);
79
80
- tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_S1E3);
81
+ tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_SE3);
82
}
40
}
83
41
84
static void tlbi_aa64_alle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
42
+/*
85
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_alle3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
43
+ * If we have triggered a EL state change we can't rely on the
44
+ * translator having passed it to us, we need to recompute.
45
+ */
46
+void HELPER(rebuild_hflags_m32_newel)(CPUARMState *env)
47
+{
48
+ int el = arm_current_el(env);
49
+ int fp_el = fp_exception_el(env, el);
50
+ ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
51
+ env->hflags = rebuild_hflags_m32(env, fp_el, mmu_idx);
52
+}
53
+
54
void HELPER(rebuild_hflags_m32)(CPUARMState *env, int el)
86
{
55
{
87
CPUState *cs = env_cpu(env);
56
int fp_el = fp_exception_el(env, el);
88
89
- tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_S1E3);
90
+ tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_SE3);
91
}
92
93
static void tlbi_aa64_vae2_write(CPUARMState *env, const ARMCPRegInfo *ri,
94
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae3_write(CPUARMState *env, const ARMCPRegInfo *ri,
95
CPUState *cs = CPU(cpu);
96
uint64_t pageaddr = sextract64(value << 12, 0, 56);
97
98
- tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_S1E3);
99
+ tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_SE3);
100
}
101
102
static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
103
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
104
uint64_t pageaddr = sextract64(value << 12, 0, 56);
105
106
tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
107
- ARMMMUIdxBit_S1E3);
108
+ ARMMMUIdxBit_SE3);
109
}
110
111
static void tlbi_aa64_ipas2e1_write(CPUARMState *env, const ARMCPRegInfo *ri,
112
@@ -XXX,XX +XXX,XX @@ static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
113
case ARMMMUIdx_Stage2:
114
case ARMMMUIdx_S1E2:
115
return 2;
116
- case ARMMMUIdx_S1E3:
117
+ case ARMMMUIdx_SE3:
118
return 3;
119
case ARMMMUIdx_SE10_0:
120
return arm_el_is_aa64(env, 3) ? 1 : 3;
121
diff --git a/target/arm/translate.c b/target/arm/translate.c
57
diff --git a/target/arm/translate.c b/target/arm/translate.c
122
index XXXXXXX..XXXXXXX 100644
58
index XXXXXXX..XXXXXXX 100644
123
--- a/target/arm/translate.c
59
--- a/target/arm/translate.c
124
+++ b/target/arm/translate.c
60
+++ b/target/arm/translate.c
125
@@ -XXX,XX +XXX,XX @@ static inline int get_a32_user_mem_index(DisasContext *s)
61
@@ -XXX,XX +XXX,XX @@ static bool trans_MRS_v7m(DisasContext *s, arg_MRS_v7m *a)
126
case ARMMMUIdx_E10_0:
62
127
case ARMMMUIdx_E10_1:
63
static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a)
128
return arm_to_core_mmu_idx(ARMMMUIdx_E10_0);
64
{
129
- case ARMMMUIdx_S1E3:
65
- TCGv_i32 addr, reg, el;
130
+ case ARMMMUIdx_SE3:
66
+ TCGv_i32 addr, reg;
131
case ARMMMUIdx_SE10_0:
67
132
case ARMMMUIdx_SE10_1:
68
if (!arm_dc_feature(s, ARM_FEATURE_M)) {
133
return arm_to_core_mmu_idx(ARMMMUIdx_SE10_0);
69
return false;
70
@@ -XXX,XX +XXX,XX @@ static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a)
71
gen_helper_v7m_msr(cpu_env, addr, reg);
72
tcg_temp_free_i32(addr);
73
tcg_temp_free_i32(reg);
74
- el = tcg_const_i32(s->current_el);
75
- gen_helper_rebuild_hflags_m32(cpu_env, el);
76
- tcg_temp_free_i32(el);
77
+ /* If we wrote to CONTROL, the EL might have changed */
78
+ gen_helper_rebuild_hflags_m32_newel(cpu_env);
79
gen_lookup_tb(s);
80
return true;
81
}
134
--
82
--
135
2.20.1
83
2.20.1
136
84
137
85
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Fix a couple of comment typos.
2
2
3
This is part of a reorganization to the set of mmu_idx.
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
The non-secure EL2 regime only has a single stage translation;
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
there is no point in pointing out that the idx is for stage1.
5
Message-id: 20200303174950.3298-5-peter.maydell@linaro.org
6
---
7
target/arm/helper.c | 2 +-
8
target/arm/translate.c | 2 +-
9
2 files changed, 2 insertions(+), 2 deletions(-)
6
10
7
Tested-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20200206105448.4726-15-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
target/arm/cpu.h | 4 ++--
14
target/arm/internals.h | 2 +-
15
target/arm/helper.c | 22 +++++++++++-----------
16
target/arm/translate.c | 2 +-
17
4 files changed, 15 insertions(+), 15 deletions(-)
18
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.h
22
+++ b/target/arm/cpu.h
23
@@ -XXX,XX +XXX,XX @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
24
typedef enum ARMMMUIdx {
25
ARMMMUIdx_E10_0 = 0 | ARM_MMU_IDX_A,
26
ARMMMUIdx_E10_1 = 1 | ARM_MMU_IDX_A,
27
- ARMMMUIdx_S1E2 = 2 | ARM_MMU_IDX_A,
28
+ ARMMMUIdx_E2 = 2 | ARM_MMU_IDX_A,
29
ARMMMUIdx_SE3 = 3 | ARM_MMU_IDX_A,
30
ARMMMUIdx_SE10_0 = 4 | ARM_MMU_IDX_A,
31
ARMMMUIdx_SE10_1 = 5 | ARM_MMU_IDX_A,
32
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdx {
33
typedef enum ARMMMUIdxBit {
34
ARMMMUIdxBit_E10_0 = 1 << 0,
35
ARMMMUIdxBit_E10_1 = 1 << 1,
36
- ARMMMUIdxBit_S1E2 = 1 << 2,
37
+ ARMMMUIdxBit_E2 = 1 << 2,
38
ARMMMUIdxBit_SE3 = 1 << 3,
39
ARMMMUIdxBit_SE10_0 = 1 << 4,
40
ARMMMUIdxBit_SE10_1 = 1 << 5,
41
diff --git a/target/arm/internals.h b/target/arm/internals.h
42
index XXXXXXX..XXXXXXX 100644
43
--- a/target/arm/internals.h
44
+++ b/target/arm/internals.h
45
@@ -XXX,XX +XXX,XX @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
46
case ARMMMUIdx_E10_1:
47
case ARMMMUIdx_Stage1_E0:
48
case ARMMMUIdx_Stage1_E1:
49
- case ARMMMUIdx_S1E2:
50
+ case ARMMMUIdx_E2:
51
case ARMMMUIdx_Stage2:
52
case ARMMMUIdx_MPrivNegPri:
53
case ARMMMUIdx_MUserNegPri:
54
diff --git a/target/arm/helper.c b/target/arm/helper.c
11
diff --git a/target/arm/helper.c b/target/arm/helper.c
55
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
56
--- a/target/arm/helper.c
13
--- a/target/arm/helper.c
57
+++ b/target/arm/helper.c
14
+++ b/target/arm/helper.c
58
@@ -XXX,XX +XXX,XX @@ static void tlbiall_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
15
@@ -XXX,XX +XXX,XX @@ void HELPER(rebuild_hflags_m32)(CPUARMState *env, int el)
16
17
/*
18
* If we have triggered a EL state change we can't rely on the
19
- * translator having passed it too us, we need to recompute.
20
+ * translator having passed it to us, we need to recompute.
21
*/
22
void HELPER(rebuild_hflags_a32_newel)(CPUARMState *env)
59
{
23
{
60
CPUState *cs = env_cpu(env);
61
62
- tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_S1E2);
63
+ tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E2);
64
}
65
66
static void tlbiall_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
67
@@ -XXX,XX +XXX,XX @@ static void tlbiall_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
68
{
69
CPUState *cs = env_cpu(env);
70
71
- tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_S1E2);
72
+ tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_E2);
73
}
74
75
static void tlbimva_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
76
@@ -XXX,XX +XXX,XX @@ static void tlbimva_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
77
CPUState *cs = env_cpu(env);
78
uint64_t pageaddr = value & ~MAKE_64BIT_MASK(0, 12);
79
80
- tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_S1E2);
81
+ tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E2);
82
}
83
84
static void tlbimva_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
85
@@ -XXX,XX +XXX,XX @@ static void tlbimva_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
86
uint64_t pageaddr = value & ~MAKE_64BIT_MASK(0, 12);
87
88
tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
89
- ARMMMUIdxBit_S1E2);
90
+ ARMMMUIdxBit_E2);
91
}
92
93
static const ARMCPRegInfo cp_reginfo[] = {
94
@@ -XXX,XX +XXX,XX @@ static void ats1h_write(CPUARMState *env, const ARMCPRegInfo *ri,
95
MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD;
96
uint64_t par64;
97
98
- par64 = do_ats_write(env, value, access_type, ARMMMUIdx_S1E2);
99
+ par64 = do_ats_write(env, value, access_type, ARMMMUIdx_E2);
100
101
A32_BANKED_CURRENT_REG_SET(env, par, par64);
102
}
103
@@ -XXX,XX +XXX,XX @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
104
mmu_idx = secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_Stage1_E1;
105
break;
106
case 4: /* AT S1E2R, AT S1E2W */
107
- mmu_idx = ARMMMUIdx_S1E2;
108
+ mmu_idx = ARMMMUIdx_E2;
109
break;
110
case 6: /* AT S1E3R, AT S1E3W */
111
mmu_idx = ARMMMUIdx_SE3;
112
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_alle2_write(CPUARMState *env, const ARMCPRegInfo *ri,
113
ARMCPU *cpu = env_archcpu(env);
114
CPUState *cs = CPU(cpu);
115
116
- tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_S1E2);
117
+ tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E2);
118
}
119
120
static void tlbi_aa64_alle3_write(CPUARMState *env, const ARMCPRegInfo *ri,
121
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_alle2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
122
{
123
CPUState *cs = env_cpu(env);
124
125
- tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_S1E2);
126
+ tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_E2);
127
}
128
129
static void tlbi_aa64_alle3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
130
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae2_write(CPUARMState *env, const ARMCPRegInfo *ri,
131
CPUState *cs = CPU(cpu);
132
uint64_t pageaddr = sextract64(value << 12, 0, 56);
133
134
- tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_S1E2);
135
+ tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E2);
136
}
137
138
static void tlbi_aa64_vae3_write(CPUARMState *env, const ARMCPRegInfo *ri,
139
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
140
uint64_t pageaddr = sextract64(value << 12, 0, 56);
141
142
tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
143
- ARMMMUIdxBit_S1E2);
144
+ ARMMMUIdxBit_E2);
145
}
146
147
static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
148
@@ -XXX,XX +XXX,XX @@ static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
149
{
150
switch (mmu_idx) {
151
case ARMMMUIdx_Stage2:
152
- case ARMMMUIdx_S1E2:
153
+ case ARMMMUIdx_E2:
154
return 2;
155
case ARMMMUIdx_SE3:
156
return 3;
157
diff --git a/target/arm/translate.c b/target/arm/translate.c
24
diff --git a/target/arm/translate.c b/target/arm/translate.c
158
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
159
--- a/target/arm/translate.c
26
--- a/target/arm/translate.c
160
+++ b/target/arm/translate.c
27
+++ b/target/arm/translate.c
161
@@ -XXX,XX +XXX,XX @@ static inline int get_a32_user_mem_index(DisasContext *s)
28
@@ -XXX,XX +XXX,XX @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
162
* otherwise, access as if at PL0.
29
163
*/
30
if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
164
switch (s->mmu_idx) {
31
/*
165
- case ARMMMUIdx_S1E2: /* this one is UNPREDICTABLE */
32
- * A write to any coprocessor regiser that ends a TB
166
+ case ARMMMUIdx_E2: /* this one is UNPREDICTABLE */
33
+ * A write to any coprocessor register that ends a TB
167
case ARMMMUIdx_E10_0:
34
* must rebuild the hflags for the next TB.
168
case ARMMMUIdx_E10_1:
35
*/
169
return arm_to_core_mmu_idx(ARMMMUIdx_E10_0);
36
TCGv_i32 tcg_el = tcg_const_i32(s->current_el);
170
--
37
--
171
2.20.1
38
2.20.1
172
39
173
40
diff view generated by jsdifflib
1
From: Pan Nengyuan <pannengyuan@huawei.com>
1
From: Cédric Le Goater <clg@kaod.org>
2
2
3
There is a memory leak when we call 'device_list_properties' with typename = stellaris-gptm. It's easy to reproduce as follow:
3
Signed-off-by: Cédric Le Goater <clg@kaod.org>
4
4
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
5
virsh qemu-monitor-command vm1 --pretty '{"execute": "device-list-properties", "arguments": {"typename": "stellaris-gptm"}}'
5
Reviewed-by: Joel Stanley <joel@jms.id.au>
6
7
This patch delay timer_new in realize to fix it.
8
9
Reported-by: Euler Robot <euler.robot@huawei.com>
10
Signed-off-by: Pan Nengyuan <pannengyuan@huawei.com>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Message-id: 20200205070659.22488-4-pannengyuan@huawei.com
7
Message-id: 20200206112645.21275-2-clg@kaod.org
13
Cc: qemu-arm@nongnu.org
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
9
---
17
hw/arm/stellaris.c | 7 ++++++-
10
Makefile.objs | 1 +
18
1 file changed, 6 insertions(+), 1 deletion(-)
11
hw/ssi/aspeed_smc.c | 17 +++++++++++++++++
12
hw/ssi/trace-events | 9 +++++++++
13
3 files changed, 27 insertions(+)
14
create mode 100644 hw/ssi/trace-events
19
15
20
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
16
diff --git a/Makefile.objs b/Makefile.objs
21
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/arm/stellaris.c
18
--- a/Makefile.objs
23
+++ b/hw/arm/stellaris.c
19
+++ b/Makefile.objs
24
@@ -XXX,XX +XXX,XX @@ static void stellaris_gptm_init(Object *obj)
20
@@ -XXX,XX +XXX,XX @@ trace-events-subdirs += hw/scsi
25
sysbus_init_mmio(sbd, &s->iomem);
21
trace-events-subdirs += hw/sd
26
22
trace-events-subdirs += hw/sparc
27
s->opaque[0] = s->opaque[1] = s;
23
trace-events-subdirs += hw/sparc64
28
+}
24
+trace-events-subdirs += hw/ssi
25
trace-events-subdirs += hw/timer
26
trace-events-subdirs += hw/tpm
27
trace-events-subdirs += hw/usb
28
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/ssi/aspeed_smc.c
31
+++ b/hw/ssi/aspeed_smc.c
32
@@ -XXX,XX +XXX,XX @@
33
#include "qapi/error.h"
34
#include "exec/address-spaces.h"
35
#include "qemu/units.h"
36
+#include "trace.h"
37
38
#include "hw/irq.h"
39
#include "hw/qdev-properties.h"
40
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_flash_set_segment(AspeedSMCState *s, int cs,
41
42
s->ctrl->reg_to_segment(s, new, &seg);
43
44
+ trace_aspeed_smc_flash_set_segment(cs, new, seg.addr, seg.addr + seg.size);
29
+
45
+
30
+static void stellaris_gptm_realize(DeviceState *dev, Error **errp)
46
/* The start address of CS0 is read-only */
31
+{
47
if (cs == 0 && seg.addr != s->ctrl->flash_window_base) {
32
+ gptm_state *s = STELLARIS_GPTM(dev);
48
qemu_log_mask(LOG_GUEST_ERROR,
33
s->timer[0] = timer_new_ns(QEMU_CLOCK_VIRTUAL, gptm_tick, &s->opaque[0]);
49
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_smc_flash_read(void *opaque, hwaddr addr, unsigned size)
34
s->timer[1] = timer_new_ns(QEMU_CLOCK_VIRTUAL, gptm_tick, &s->opaque[1]);
50
__func__, aspeed_smc_flash_mode(fl));
51
}
52
53
+ trace_aspeed_smc_flash_read(fl->id, addr, size, ret,
54
+ aspeed_smc_flash_mode(fl));
55
return ret;
35
}
56
}
36
57
37
-
58
@@ -XXX,XX +XXX,XX @@ static bool aspeed_smc_do_snoop(AspeedSMCFlash *fl, uint64_t data,
38
/* System controller. */
59
AspeedSMCState *s = fl->controller;
39
60
uint8_t addr_width = aspeed_smc_flash_is_4byte(fl) ? 4 : 3;
40
typedef struct {
61
41
@@ -XXX,XX +XXX,XX @@ static void stellaris_gptm_class_init(ObjectClass *klass, void *data)
62
+ trace_aspeed_smc_do_snoop(fl->id, s->snoop_index, s->snoop_dummies,
42
DeviceClass *dc = DEVICE_CLASS(klass);
63
+ (uint8_t) data & 0xff);
43
64
+
44
dc->vmsd = &vmstate_stellaris_gptm;
65
if (s->snoop_index == SNOOP_OFF) {
45
+ dc->realize = stellaris_gptm_realize;
66
return false; /* Do nothing */
46
}
67
47
68
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_flash_write(void *opaque, hwaddr addr, uint64_t data,
48
static const TypeInfo stellaris_gptm_info = {
69
AspeedSMCState *s = fl->controller;
70
int i;
71
72
+ trace_aspeed_smc_flash_write(fl->id, addr, size, data,
73
+ aspeed_smc_flash_mode(fl));
74
+
75
if (!aspeed_smc_is_writable(fl)) {
76
qemu_log_mask(LOG_GUEST_ERROR, "%s: flash is not writable at 0x%"
77
HWADDR_PRIx "\n", __func__, addr);
78
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
79
(s->ctrl->has_dma && addr == R_DMA_CHECKSUM) ||
80
(addr >= R_SEG_ADDR0 && addr < R_SEG_ADDR0 + s->ctrl->max_slaves) ||
81
(addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->ctrl->max_slaves)) {
82
+
83
+ trace_aspeed_smc_read(addr, size, s->regs[addr]);
84
+
85
return s->regs[addr];
86
} else {
87
qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n",
88
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
89
__func__, s->regs[R_DMA_FLASH_ADDR]);
90
return;
91
}
92
+ trace_aspeed_smc_dma_checksum(s->regs[R_DMA_FLASH_ADDR], data);
93
94
/*
95
* When the DMA is on-going, the DMA registers are updated
96
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
97
98
addr >>= 2;
99
100
+ trace_aspeed_smc_write(addr, size, data);
101
+
102
if (addr == s->r_conf ||
103
(addr >= s->r_timings &&
104
addr < s->r_timings + s->ctrl->nregs_timings) ||
105
diff --git a/hw/ssi/trace-events b/hw/ssi/trace-events
106
new file mode 100644
107
index XXXXXXX..XXXXXXX
108
--- /dev/null
109
+++ b/hw/ssi/trace-events
110
@@ -XXX,XX +XXX,XX @@
111
+# aspeed_smc.c
112
+
113
+aspeed_smc_flash_set_segment(int cs, uint64_t reg, uint64_t start, uint64_t end) "CS%d segreg=0x%"PRIx64" [ 0x%"PRIx64" - 0x%"PRIx64" ]"
114
+aspeed_smc_flash_read(int cs, uint64_t addr, uint32_t size, uint64_t data, int mode) "CS%d @0x%" PRIx64 " size %u: 0x%" PRIx64" mode:%d"
115
+aspeed_smc_do_snoop(int cs, int index, int dummies, int data) "CS%d index:0x%x dummies:%d data:0x%x"
116
+aspeed_smc_flash_write(int cs, uint64_t addr, uint32_t size, uint64_t data, int mode) "CS%d @0x%" PRIx64 " size %u: 0x%" PRIx64" mode:%d"
117
+aspeed_smc_read(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
118
+aspeed_smc_dma_checksum(uint32_t addr, uint32_t data) "0x%08x: 0x%08x"
119
+aspeed_smc_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
49
--
120
--
50
2.20.1
121
2.20.1
51
122
52
123
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Cédric Le Goater <clg@kaod.org>
2
2
3
This is part of a reorganization to the set of mmu_idx.
3
The Aspeed SMC Controller can operate in different modes : Read, Fast
4
This emphasizes that they apply to the EL1&0 regime.
4
Read, Write and User modes. When the User mode is configured, it
5
selects automatically the SPI slave device until the CE_STOP_ACTIVE
6
bit is set to 1. When any other modes are configured the device is
7
unselected. The HW logic handles the chip select automatically when
8
the flash is accessed through its AHB window.
5
9
6
The ultimate goal is
10
When configuring the CEx Control Register, the User mode logic to
11
select and unselect the slave is incorrect and data corruption can be
12
seen on machines using two chips, witherspoon and romulus.
7
13
8
-- Non-secure regimes:
14
Rework the handler setting the CEx Control Register to fix this issue.
9
ARMMMUIdx_E10_0,
10
ARMMMUIdx_E20_0,
11
ARMMMUIdx_E10_1,
12
ARMMMUIdx_E2,
13
ARMMMUIdx_E20_2,
14
15
15
-- Secure regimes:
16
Fixes: 7c1c69bca43c ("ast2400: add SMC controllers (FMC and SPI)")
16
ARMMMUIdx_SE10_0,
17
Signed-off-by: Cédric Le Goater <clg@kaod.org>
17
ARMMMUIdx_SE10_1,
18
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
18
ARMMMUIdx_SE3,
19
Message-id: 20200206112645.21275-3-clg@kaod.org
19
20
-- Helper mmu_idx for non-secure EL1&0 stage1 and stage2
21
ARMMMUIdx_Stage2,
22
ARMMMUIdx_Stage1_E0,
23
ARMMMUIdx_Stage1_E1,
24
25
The 'S' prefix is reserved for "Secure". Unless otherwise specified,
26
each mmu_idx represents all stages of translation.
27
28
Tested-by: Alex Bennée <alex.bennee@linaro.org>
29
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
30
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
31
Message-id: 20200206105448.4726-10-richard.henderson@linaro.org
32
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
33
---
21
---
34
target/arm/cpu.h | 8 ++++----
22
hw/ssi/aspeed_smc.c | 39 +++++++++++++++++++++++----------------
35
target/arm/internals.h | 4 ++--
23
hw/ssi/trace-events | 1 +
36
target/arm/helper.c | 40 +++++++++++++++++++-------------------
24
2 files changed, 24 insertions(+), 16 deletions(-)
37
target/arm/translate-a64.c | 4 ++--
38
target/arm/translate.c | 6 +++---
39
5 files changed, 31 insertions(+), 31 deletions(-)
40
25
41
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
26
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
42
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
43
--- a/target/arm/cpu.h
28
--- a/hw/ssi/aspeed_smc.c
44
+++ b/target/arm/cpu.h
29
+++ b/hw/ssi/aspeed_smc.c
45
@@ -XXX,XX +XXX,XX @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
30
@@ -XXX,XX +XXX,XX @@ static inline int aspeed_smc_flash_is_4byte(const AspeedSMCFlash *fl)
46
#define ARM_MMU_IDX_COREIDX_MASK 0x7
47
48
typedef enum ARMMMUIdx {
49
- ARMMMUIdx_S12NSE0 = 0 | ARM_MMU_IDX_A,
50
- ARMMMUIdx_S12NSE1 = 1 | ARM_MMU_IDX_A,
51
+ ARMMMUIdx_E10_0 = 0 | ARM_MMU_IDX_A,
52
+ ARMMMUIdx_E10_1 = 1 | ARM_MMU_IDX_A,
53
ARMMMUIdx_S1E2 = 2 | ARM_MMU_IDX_A,
54
ARMMMUIdx_S1E3 = 3 | ARM_MMU_IDX_A,
55
ARMMMUIdx_S1SE0 = 4 | ARM_MMU_IDX_A,
56
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdx {
57
* for use when calling tlb_flush_by_mmuidx() and friends.
58
*/
59
typedef enum ARMMMUIdxBit {
60
- ARMMMUIdxBit_S12NSE0 = 1 << 0,
61
- ARMMMUIdxBit_S12NSE1 = 1 << 1,
62
+ ARMMMUIdxBit_E10_0 = 1 << 0,
63
+ ARMMMUIdxBit_E10_1 = 1 << 1,
64
ARMMMUIdxBit_S1E2 = 1 << 2,
65
ARMMMUIdxBit_S1E3 = 1 << 3,
66
ARMMMUIdxBit_S1SE0 = 1 << 4,
67
diff --git a/target/arm/internals.h b/target/arm/internals.h
68
index XXXXXXX..XXXXXXX 100644
69
--- a/target/arm/internals.h
70
+++ b/target/arm/internals.h
71
@@ -XXX,XX +XXX,XX @@ static inline void arm_call_el_change_hook(ARMCPU *cpu)
72
static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
73
{
74
switch (mmu_idx) {
75
- case ARMMMUIdx_S12NSE0:
76
- case ARMMMUIdx_S12NSE1:
77
+ case ARMMMUIdx_E10_0:
78
+ case ARMMMUIdx_E10_1:
79
case ARMMMUIdx_S1NSE0:
80
case ARMMMUIdx_S1NSE1:
81
case ARMMMUIdx_S1E2:
82
diff --git a/target/arm/helper.c b/target/arm/helper.c
83
index XXXXXXX..XXXXXXX 100644
84
--- a/target/arm/helper.c
85
+++ b/target/arm/helper.c
86
@@ -XXX,XX +XXX,XX @@ static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri,
87
CPUState *cs = env_cpu(env);
88
89
tlb_flush_by_mmuidx(cs,
90
- ARMMMUIdxBit_S12NSE1 |
91
- ARMMMUIdxBit_S12NSE0 |
92
+ ARMMMUIdxBit_E10_1 |
93
+ ARMMMUIdxBit_E10_0 |
94
ARMMMUIdxBit_S2NS);
95
}
96
97
@@ -XXX,XX +XXX,XX @@ static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
98
CPUState *cs = env_cpu(env);
99
100
tlb_flush_by_mmuidx_all_cpus_synced(cs,
101
- ARMMMUIdxBit_S12NSE1 |
102
- ARMMMUIdxBit_S12NSE0 |
103
+ ARMMMUIdxBit_E10_1 |
104
+ ARMMMUIdxBit_E10_0 |
105
ARMMMUIdxBit_S2NS);
106
}
107
108
@@ -XXX,XX +XXX,XX @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
109
format64 = arm_s1_regime_using_lpae_format(env, mmu_idx);
110
111
if (arm_feature(env, ARM_FEATURE_EL2)) {
112
- if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) {
113
+ if (mmu_idx == ARMMMUIdx_E10_0 || mmu_idx == ARMMMUIdx_E10_1) {
114
format64 |= env->cp15.hcr_el2 & (HCR_VM | HCR_DC);
115
} else {
116
format64 |= arm_current_el(env) == 2;
117
@@ -XXX,XX +XXX,XX @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
118
break;
119
case 4:
120
/* stage 1+2 NonSecure PL1: ATS12NSOPR, ATS12NSOPW */
121
- mmu_idx = ARMMMUIdx_S12NSE1;
122
+ mmu_idx = ARMMMUIdx_E10_1;
123
break;
124
case 6:
125
/* stage 1+2 NonSecure PL0: ATS12NSOUR, ATS12NSOUW */
126
- mmu_idx = ARMMMUIdx_S12NSE0;
127
+ mmu_idx = ARMMMUIdx_E10_0;
128
break;
129
default:
130
g_assert_not_reached();
131
@@ -XXX,XX +XXX,XX @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
132
mmu_idx = secure ? ARMMMUIdx_S1SE0 : ARMMMUIdx_S1NSE0;
133
break;
134
case 4: /* AT S12E1R, AT S12E1W */
135
- mmu_idx = secure ? ARMMMUIdx_S1SE1 : ARMMMUIdx_S12NSE1;
136
+ mmu_idx = secure ? ARMMMUIdx_S1SE1 : ARMMMUIdx_E10_1;
137
break;
138
case 6: /* AT S12E0R, AT S12E0W */
139
- mmu_idx = secure ? ARMMMUIdx_S1SE0 : ARMMMUIdx_S12NSE0;
140
+ mmu_idx = secure ? ARMMMUIdx_S1SE0 : ARMMMUIdx_E10_0;
141
break;
142
default:
143
g_assert_not_reached();
144
@@ -XXX,XX +XXX,XX @@ static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
145
/* Accesses to VTTBR may change the VMID so we must flush the TLB. */
146
if (raw_read(env, ri) != value) {
147
tlb_flush_by_mmuidx(cs,
148
- ARMMMUIdxBit_S12NSE1 |
149
- ARMMMUIdxBit_S12NSE0 |
150
+ ARMMMUIdxBit_E10_1 |
151
+ ARMMMUIdxBit_E10_0 |
152
ARMMMUIdxBit_S2NS);
153
raw_write(env, ri, value);
154
}
155
@@ -XXX,XX +XXX,XX @@ static int vae1_tlbmask(CPUARMState *env)
156
if (arm_is_secure_below_el3(env)) {
157
return ARMMMUIdxBit_S1SE1 | ARMMMUIdxBit_S1SE0;
158
} else {
159
- return ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0;
160
+ return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0;
161
}
31
}
162
}
32
}
163
33
164
@@ -XXX,XX +XXX,XX @@ static int alle1_tlbmask(CPUARMState *env)
34
-static inline bool aspeed_smc_is_ce_stop_active(const AspeedSMCFlash *fl)
165
if (arm_is_secure_below_el3(env)) {
35
+static void aspeed_smc_flash_do_select(AspeedSMCFlash *fl, bool unselect)
166
return ARMMMUIdxBit_S1SE1 | ARMMMUIdxBit_S1SE0;
36
{
167
} else if (arm_feature(env, ARM_FEATURE_EL2)) {
37
- const AspeedSMCState *s = fl->controller;
168
- return ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0 | ARMMMUIdxBit_S2NS;
38
+ AspeedSMCState *s = fl->controller;
169
+ return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0 | ARMMMUIdxBit_S2NS;
39
170
} else {
40
- return s->regs[s->r_ctrl0 + fl->id] & CTRL_CE_STOP_ACTIVE;
171
- return ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0;
41
+ trace_aspeed_smc_flash_select(fl->id, unselect ? "un" : "");
172
+ return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0;
42
+
173
}
43
+ qemu_set_irq(s->cs_lines[fl->id], unselect);
174
}
44
}
175
45
176
@@ -XXX,XX +XXX,XX @@ static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
46
static void aspeed_smc_flash_select(AspeedSMCFlash *fl)
177
*/
178
static inline ARMMMUIdx stage_1_mmu_idx(ARMMMUIdx mmu_idx)
179
{
47
{
180
- if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) {
48
- AspeedSMCState *s = fl->controller;
181
- mmu_idx += (ARMMMUIdx_S1NSE0 - ARMMMUIdx_S12NSE0);
49
-
182
+ if (mmu_idx == ARMMMUIdx_E10_0 || mmu_idx == ARMMMUIdx_E10_1) {
50
- s->regs[s->r_ctrl0 + fl->id] &= ~CTRL_CE_STOP_ACTIVE;
183
+ mmu_idx += (ARMMMUIdx_S1NSE0 - ARMMMUIdx_E10_0);
51
- qemu_set_irq(s->cs_lines[fl->id], aspeed_smc_is_ce_stop_active(fl));
184
}
52
+ aspeed_smc_flash_do_select(fl, false);
185
return mmu_idx;
186
}
53
}
187
@@ -XXX,XX +XXX,XX @@ static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
54
188
return true;
55
static void aspeed_smc_flash_unselect(AspeedSMCFlash *fl)
189
default:
56
{
190
return false;
57
- AspeedSMCState *s = fl->controller;
191
- case ARMMMUIdx_S12NSE0:
58
-
192
- case ARMMMUIdx_S12NSE1:
59
- s->regs[s->r_ctrl0 + fl->id] |= CTRL_CE_STOP_ACTIVE;
193
+ case ARMMMUIdx_E10_0:
60
- qemu_set_irq(s->cs_lines[fl->id], aspeed_smc_is_ce_stop_active(fl));
194
+ case ARMMMUIdx_E10_1:
61
+ aspeed_smc_flash_do_select(fl, true);
195
g_assert_not_reached();
196
}
197
}
62
}
198
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
63
199
target_ulong *page_size,
64
static uint32_t aspeed_smc_check_segment_addr(const AspeedSMCFlash *fl,
200
ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs)
65
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps aspeed_smc_flash_ops = {
66
},
67
};
68
69
-static void aspeed_smc_flash_update_cs(AspeedSMCFlash *fl)
70
+static void aspeed_smc_flash_update_ctrl(AspeedSMCFlash *fl, uint32_t value)
201
{
71
{
202
- if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) {
72
AspeedSMCState *s = fl->controller;
203
+ if (mmu_idx == ARMMMUIdx_E10_0 || mmu_idx == ARMMMUIdx_E10_1) {
73
+ bool unselect;
204
/* Call ourselves recursively to do the stage 1 and then stage 2
74
205
* translations.
75
- s->snoop_index = aspeed_smc_is_ce_stop_active(fl) ? SNOOP_OFF : SNOOP_START;
206
*/
76
+ /* User mode selects the CS, other modes unselect */
207
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
77
+ unselect = (value & CTRL_CMD_MODE_MASK) != CTRL_USERMODE;
208
if (el < 2 && arm_is_secure_below_el3(env)) {
78
209
return ARMMMUIdx_S1SE0 + el;
79
- qemu_set_irq(s->cs_lines[fl->id], aspeed_smc_is_ce_stop_active(fl));
210
} else {
80
+ /* A change of CTRL_CE_STOP_ACTIVE from 0 to 1, unselects the CS */
211
- return ARMMMUIdx_S12NSE0 + el;
81
+ if (!(s->regs[s->r_ctrl0 + fl->id] & CTRL_CE_STOP_ACTIVE) &&
212
+ return ARMMMUIdx_E10_0 + el;
82
+ value & CTRL_CE_STOP_ACTIVE) {
213
}
83
+ unselect = true;
84
+ }
85
+
86
+ s->regs[s->r_ctrl0 + fl->id] = value;
87
+
88
+ s->snoop_index = unselect ? SNOOP_OFF : SNOOP_START;
89
+
90
+ aspeed_smc_flash_do_select(fl, unselect);
214
}
91
}
215
92
216
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
93
static void aspeed_smc_reset(DeviceState *d)
94
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
95
s->regs[addr] = value;
96
} else if (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs) {
97
int cs = addr - s->r_ctrl0;
98
- s->regs[addr] = value;
99
- aspeed_smc_flash_update_cs(&s->flashes[cs]);
100
+ aspeed_smc_flash_update_ctrl(&s->flashes[cs], value);
101
} else if (addr >= R_SEG_ADDR0 &&
102
addr < R_SEG_ADDR0 + s->ctrl->max_slaves) {
103
int cs = addr - R_SEG_ADDR0;
104
diff --git a/hw/ssi/trace-events b/hw/ssi/trace-events
217
index XXXXXXX..XXXXXXX 100644
105
index XXXXXXX..XXXXXXX 100644
218
--- a/target/arm/translate-a64.c
106
--- a/hw/ssi/trace-events
219
+++ b/target/arm/translate-a64.c
107
+++ b/hw/ssi/trace-events
220
@@ -XXX,XX +XXX,XX @@ static inline int get_a64_user_mem_index(DisasContext *s)
108
@@ -XXX,XX +XXX,XX @@ aspeed_smc_flash_write(int cs, uint64_t addr, uint32_t size, uint64_t data, int
221
ARMMMUIdx useridx;
109
aspeed_smc_read(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
222
110
aspeed_smc_dma_checksum(uint32_t addr, uint32_t data) "0x%08x: 0x%08x"
223
switch (s->mmu_idx) {
111
aspeed_smc_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
224
- case ARMMMUIdx_S12NSE1:
112
+aspeed_smc_flash_select(int cs, const char *prefix) "CS%d %sselect"
225
- useridx = ARMMMUIdx_S12NSE0;
226
+ case ARMMMUIdx_E10_1:
227
+ useridx = ARMMMUIdx_E10_0;
228
break;
229
case ARMMMUIdx_S1SE1:
230
useridx = ARMMMUIdx_S1SE0;
231
diff --git a/target/arm/translate.c b/target/arm/translate.c
232
index XXXXXXX..XXXXXXX 100644
233
--- a/target/arm/translate.c
234
+++ b/target/arm/translate.c
235
@@ -XXX,XX +XXX,XX @@ static inline int get_a32_user_mem_index(DisasContext *s)
236
*/
237
switch (s->mmu_idx) {
238
case ARMMMUIdx_S1E2: /* this one is UNPREDICTABLE */
239
- case ARMMMUIdx_S12NSE0:
240
- case ARMMMUIdx_S12NSE1:
241
- return arm_to_core_mmu_idx(ARMMMUIdx_S12NSE0);
242
+ case ARMMMUIdx_E10_0:
243
+ case ARMMMUIdx_E10_1:
244
+ return arm_to_core_mmu_idx(ARMMMUIdx_E10_0);
245
case ARMMMUIdx_S1E3:
246
case ARMMMUIdx_S1SE0:
247
case ARMMMUIdx_S1SE1:
248
--
113
--
249
2.20.1
114
2.20.1
250
115
251
116
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Tested-by: Alex Bennée <alex.bennee@linaro.org>
3
We fail to validate the upper bits of a virtual address on a
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
translation disabled regime, as per AArch64.TranslateAddressS1Off.
5
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200206105448.4726-27-richard.henderson@linaro.org
7
Message-id: 20200308012946.16303-2-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
10
---
9
target/arm/helper.c | 102 +++++++++++++++++++++++++++++++++++---------
11
target/arm/helper.c | 35 ++++++++++++++++++++++++++++++++++-
10
1 file changed, 81 insertions(+), 21 deletions(-)
12
1 file changed, 34 insertions(+), 1 deletion(-)
11
13
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/helper.c
16
--- a/target/arm/helper.c
15
+++ b/target/arm/helper.c
17
+++ b/target/arm/helper.c
16
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_cntfrq_access(CPUARMState *env, const ARMCPRegInfo *ri,
18
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
17
* Writable only at the highest implemented exception level.
19
/* Definitely a real MMU, not an MPU */
18
*/
20
19
int el = arm_current_el(env);
21
if (regime_translation_disabled(env, mmu_idx)) {
20
+ uint64_t hcr;
22
- /* MMU disabled. */
21
+ uint32_t cntkctl;
23
+ /*
22
24
+ * MMU disabled. S1 addresses within aa64 translation regimes are
23
switch (el) {
25
+ * still checked for bounds -- see AArch64.TranslateAddressS1Off.
24
case 0:
26
+ */
25
- if (!extract32(env->cp15.c14_cntkctl, 0, 2)) {
27
+ if (mmu_idx != ARMMMUIdx_Stage2) {
26
+ hcr = arm_hcr_el2_eff(env);
28
+ int r_el = regime_el(env, mmu_idx);
27
+ if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
29
+ if (arm_el_is_aa64(env, r_el)) {
28
+ cntkctl = env->cp15.cnthctl_el2;
30
+ int pamax = arm_pamax(env_archcpu(env));
29
+ } else {
31
+ uint64_t tcr = env->cp15.tcr_el[r_el].raw_tcr;
30
+ cntkctl = env->cp15.c14_cntkctl;
32
+ int addrtop, tbi;
31
+ }
32
+ if (!extract32(cntkctl, 0, 2)) {
33
return CP_ACCESS_TRAP;
34
}
35
break;
36
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_counter_access(CPUARMState *env, int timeridx,
37
{
38
unsigned int cur_el = arm_current_el(env);
39
bool secure = arm_is_secure(env);
40
+ uint64_t hcr = arm_hcr_el2_eff(env);
41
42
- /* CNT[PV]CT: not visible from PL0 if ELO[PV]CTEN is zero */
43
- if (cur_el == 0 &&
44
- !extract32(env->cp15.c14_cntkctl, timeridx, 1)) {
45
- return CP_ACCESS_TRAP;
46
- }
47
+ switch (cur_el) {
48
+ case 0:
49
+ /* If HCR_EL2.<E2H,TGE> == '11': check CNTHCTL_EL2.EL0[PV]CTEN. */
50
+ if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
51
+ return (extract32(env->cp15.cnthctl_el2, timeridx, 1)
52
+ ? CP_ACCESS_OK : CP_ACCESS_TRAP_EL2);
53
+ }
54
55
- if (arm_feature(env, ARM_FEATURE_EL2) &&
56
- timeridx == GTIMER_PHYS && !secure && cur_el < 2 &&
57
- !extract32(env->cp15.cnthctl_el2, 0, 1)) {
58
- return CP_ACCESS_TRAP_EL2;
59
+ /* CNT[PV]CT: not visible from PL0 if EL0[PV]CTEN is zero */
60
+ if (!extract32(env->cp15.c14_cntkctl, timeridx, 1)) {
61
+ return CP_ACCESS_TRAP;
62
+ }
63
+
33
+
64
+ /* If HCR_EL2.<E2H,TGE> == '10': check CNTHCTL_EL2.EL1PCTEN. */
34
+ tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
65
+ if (hcr & HCR_E2H) {
35
+ if (access_type == MMU_INST_FETCH) {
66
+ if (timeridx == GTIMER_PHYS &&
36
+ tbi &= ~aa64_va_parameter_tbid(tcr, mmu_idx);
67
+ !extract32(env->cp15.cnthctl_el2, 10, 1)) {
37
+ }
68
+ return CP_ACCESS_TRAP_EL2;
38
+ tbi = (tbi >> extract64(address, 55, 1)) & 1;
69
+ }
39
+ addrtop = (tbi ? 55 : 63);
70
+ } else {
40
+
71
+ /* If HCR_EL2.<E2H> == 0: check CNTHCTL_EL2.EL1PCEN. */
41
+ if (extract64(address, pamax, addrtop - pamax + 1) != 0) {
72
+ if (arm_feature(env, ARM_FEATURE_EL2) &&
42
+ fi->type = ARMFault_AddressSize;
73
+ timeridx == GTIMER_PHYS && !secure &&
43
+ fi->level = 0;
74
+ !extract32(env->cp15.cnthctl_el2, 1, 1)) {
44
+ fi->stage2 = false;
75
+ return CP_ACCESS_TRAP_EL2;
45
+ return 1;
46
+ }
47
+
48
+ /*
49
+ * When TBI is disabled, we've just validated that all of the
50
+ * bits above PAMax are zero, so logically we only need to
51
+ * clear the top byte for TBI. But it's clearer to follow
52
+ * the pseudocode set of addrdesc.paddress.
53
+ */
54
+ address = extract64(address, 0, 52);
76
+ }
55
+ }
77
+ }
56
+ }
78
+ break;
57
*phys_ptr = address;
79
+
58
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
80
+ case 1:
59
*page_size = TARGET_PAGE_SIZE;
81
+ /* Check CNTHCTL_EL2.EL1PCTEN, which changes location based on E2H. */
82
+ if (arm_feature(env, ARM_FEATURE_EL2) &&
83
+ timeridx == GTIMER_PHYS && !secure &&
84
+ (hcr & HCR_E2H
85
+ ? !extract32(env->cp15.cnthctl_el2, 10, 1)
86
+ : !extract32(env->cp15.cnthctl_el2, 0, 1))) {
87
+ return CP_ACCESS_TRAP_EL2;
88
+ }
89
+ break;
90
}
91
return CP_ACCESS_OK;
92
}
93
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_timer_access(CPUARMState *env, int timeridx,
94
{
95
unsigned int cur_el = arm_current_el(env);
96
bool secure = arm_is_secure(env);
97
+ uint64_t hcr = arm_hcr_el2_eff(env);
98
99
- /* CNT[PV]_CVAL, CNT[PV]_CTL, CNT[PV]_TVAL: not visible from PL0 if
100
- * EL0[PV]TEN is zero.
101
- */
102
- if (cur_el == 0 &&
103
- !extract32(env->cp15.c14_cntkctl, 9 - timeridx, 1)) {
104
- return CP_ACCESS_TRAP;
105
- }
106
+ switch (cur_el) {
107
+ case 0:
108
+ if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
109
+ /* If HCR_EL2.<E2H,TGE> == '11': check CNTHCTL_EL2.EL0[PV]TEN. */
110
+ return (extract32(env->cp15.cnthctl_el2, 9 - timeridx, 1)
111
+ ? CP_ACCESS_OK : CP_ACCESS_TRAP_EL2);
112
+ }
113
114
- if (arm_feature(env, ARM_FEATURE_EL2) &&
115
- timeridx == GTIMER_PHYS && !secure && cur_el < 2 &&
116
- !extract32(env->cp15.cnthctl_el2, 1, 1)) {
117
- return CP_ACCESS_TRAP_EL2;
118
+ /*
119
+ * CNT[PV]_CVAL, CNT[PV]_CTL, CNT[PV]_TVAL: not visible from
120
+ * EL0 if EL0[PV]TEN is zero.
121
+ */
122
+ if (!extract32(env->cp15.c14_cntkctl, 9 - timeridx, 1)) {
123
+ return CP_ACCESS_TRAP;
124
+ }
125
+ /* fall through */
126
+
127
+ case 1:
128
+ if (arm_feature(env, ARM_FEATURE_EL2) &&
129
+ timeridx == GTIMER_PHYS && !secure) {
130
+ if (hcr & HCR_E2H) {
131
+ /* If HCR_EL2.<E2H,TGE> == '10': check CNTHCTL_EL2.EL1PTEN. */
132
+ if (!extract32(env->cp15.cnthctl_el2, 11, 1)) {
133
+ return CP_ACCESS_TRAP_EL2;
134
+ }
135
+ } else {
136
+ /* If HCR_EL2.<E2H> == 0: check CNTHCTL_EL2.EL1PCEN. */
137
+ if (!extract32(env->cp15.cnthctl_el2, 1, 1)) {
138
+ return CP_ACCESS_TRAP_EL2;
139
+ }
140
+ }
141
+ }
142
+ break;
143
}
144
return CP_ACCESS_OK;
145
}
146
--
60
--
147
2.20.1
61
2.20.1
148
62
149
63
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The EL2&0 translation regime is affected by Load Register (unpriv).
3
We must include the tag in the FAR_ELx register when raising
4
an addressing exception. Which means that we should not clear
5
out the tag during translation.
4
6
5
The code structure used here will facilitate later changes in this
7
We cannot at present comply with this for user mode, so we
6
area for implementing UAO and NV.
8
retain the clean_data_tbi function for the moment, though it
9
no longer does what it says on the tin for system mode. This
10
function is to be replaced with MTE, so don't worry about the
11
slight misnaming.
7
12
8
Tested-by: Alex Bennée <alex.bennee@linaro.org>
13
Buglink: https://bugs.launchpad.net/qemu/+bug/1867072
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20200308012946.16303-3-richard.henderson@linaro.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20200206105448.4726-36-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
18
---
14
target/arm/cpu.h | 9 ++++----
19
target/arm/translate-a64.c | 11 +++++++++++
15
target/arm/translate.h | 2 ++
20
1 file changed, 11 insertions(+)
16
target/arm/helper.c | 22 +++++++++++++++++++
17
target/arm/translate-a64.c | 44 ++++++++++++++++++++++++--------------
18
4 files changed, 57 insertions(+), 20 deletions(-)
19
21
20
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.h
23
+++ b/target/arm/cpu.h
24
@@ -XXX,XX +XXX,XX @@ typedef ARMCPU ArchCPU;
25
* | | | TBFLAG_A32 | |
26
* | | +-----+----------+ TBFLAG_AM32 |
27
* | TBFLAG_ANY | |TBFLAG_M32| |
28
- * | | +-------------------------|
29
- * | | | TBFLAG_A64 |
30
- * +--------------+-----------+-------------------------+
31
- * 31 20 14 0
32
+ * | | +-+----------+--------------|
33
+ * | | | TBFLAG_A64 |
34
+ * +--------------+---------+---------------------------+
35
+ * 31 20 15 0
36
*
37
* Unless otherwise noted, these bits are cached in env->hflags.
38
*/
39
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A64, PAUTH_ACTIVE, 8, 1)
40
FIELD(TBFLAG_A64, BT, 9, 1)
41
FIELD(TBFLAG_A64, BTYPE, 10, 2) /* Not cached. */
42
FIELD(TBFLAG_A64, TBID, 12, 2)
43
+FIELD(TBFLAG_A64, UNPRIV, 14, 1)
44
45
static inline bool bswap_code(bool sctlr_b)
46
{
47
diff --git a/target/arm/translate.h b/target/arm/translate.h
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/translate.h
50
+++ b/target/arm/translate.h
51
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
52
* ie A64 LDX*, LDAX*, A32/T32 LDREX*, LDAEX*.
53
*/
54
bool is_ldex;
55
+ /* True if AccType_UNPRIV should be used for LDTR et al */
56
+ bool unpriv;
57
/* True if v8.3-PAuth is active. */
58
bool pauth_active;
59
/* True with v8.5-BTI and SCTLR_ELx.BT* set. */
60
diff --git a/target/arm/helper.c b/target/arm/helper.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/helper.c
63
+++ b/target/arm/helper.c
64
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
65
}
66
}
67
68
+ /* Compute the condition for using AccType_UNPRIV for LDTR et al. */
69
+ /* TODO: ARMv8.2-UAO */
70
+ switch (mmu_idx) {
71
+ case ARMMMUIdx_E10_1:
72
+ case ARMMMUIdx_SE10_1:
73
+ /* TODO: ARMv8.3-NV */
74
+ flags = FIELD_DP32(flags, TBFLAG_A64, UNPRIV, 1);
75
+ break;
76
+ case ARMMMUIdx_E20_2:
77
+ /* TODO: ARMv8.4-SecEL2 */
78
+ /*
79
+ * Note that E20_2 is gated by HCR_EL2.E2H == 1, but E20_0 is
80
+ * gated by HCR_EL2.<E2H,TGE> == '11', and so is LDTR.
81
+ */
82
+ if (env->cp15.hcr_el2 & HCR_TGE) {
83
+ flags = FIELD_DP32(flags, TBFLAG_A64, UNPRIV, 1);
84
+ }
85
+ break;
86
+ default:
87
+ break;
88
+ }
89
+
90
return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
91
}
92
93
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
22
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
94
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
95
--- a/target/arm/translate-a64.c
24
--- a/target/arm/translate-a64.c
96
+++ b/target/arm/translate-a64.c
25
+++ b/target/arm/translate-a64.c
97
@@ -XXX,XX +XXX,XX @@ void a64_translate_init(void)
26
@@ -XXX,XX +XXX,XX @@ static void gen_a64_set_pc(DisasContext *s, TCGv_i64 src)
98
offsetof(CPUARMState, exclusive_high), "exclusive_high");
27
static TCGv_i64 clean_data_tbi(DisasContext *s, TCGv_i64 addr)
28
{
29
TCGv_i64 clean = new_tmp_a64(s);
30
+ /*
31
+ * In order to get the correct value in the FAR_ELx register,
32
+ * we must present the memory subsystem with the "dirty" address
33
+ * including the TBI. In system mode we can make this work via
34
+ * the TLB, dropping the TBI during translation. But for user-only
35
+ * mode we don't have that option, and must remove the top byte now.
36
+ */
37
+#ifdef CONFIG_USER_ONLY
38
gen_top_byte_ignore(s, clean, addr, s->tbid);
39
+#else
40
+ tcg_gen_mov_i64(clean, addr);
41
+#endif
42
return clean;
99
}
43
}
100
44
101
-static inline int get_a64_user_mem_index(DisasContext *s)
102
+/*
103
+ * Return the core mmu_idx to use for A64 "unprivileged load/store" insns
104
+ */
105
+static int get_a64_user_mem_index(DisasContext *s)
106
{
107
- /* Return the core mmu_idx to use for A64 "unprivileged load/store" insns:
108
- * if EL1, access as if EL0; otherwise access at current EL
109
+ /*
110
+ * If AccType_UNPRIV is not used, the insn uses AccType_NORMAL,
111
+ * which is the usual mmu_idx for this cpu state.
112
*/
113
- ARMMMUIdx useridx;
114
+ ARMMMUIdx useridx = s->mmu_idx;
115
116
- switch (s->mmu_idx) {
117
- case ARMMMUIdx_E10_1:
118
- useridx = ARMMMUIdx_E10_0;
119
- break;
120
- case ARMMMUIdx_SE10_1:
121
- useridx = ARMMMUIdx_SE10_0;
122
- break;
123
- case ARMMMUIdx_Stage2:
124
- g_assert_not_reached();
125
- default:
126
- useridx = s->mmu_idx;
127
- break;
128
+ if (s->unpriv) {
129
+ /*
130
+ * We have pre-computed the condition for AccType_UNPRIV.
131
+ * Therefore we should never get here with a mmu_idx for
132
+ * which we do not know the corresponding user mmu_idx.
133
+ */
134
+ switch (useridx) {
135
+ case ARMMMUIdx_E10_1:
136
+ useridx = ARMMMUIdx_E10_0;
137
+ break;
138
+ case ARMMMUIdx_E20_2:
139
+ useridx = ARMMMUIdx_E20_0;
140
+ break;
141
+ case ARMMMUIdx_SE10_1:
142
+ useridx = ARMMMUIdx_SE10_0;
143
+ break;
144
+ default:
145
+ g_assert_not_reached();
146
+ }
147
}
148
return arm_to_core_mmu_idx(useridx);
149
}
150
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
151
dc->pauth_active = FIELD_EX32(tb_flags, TBFLAG_A64, PAUTH_ACTIVE);
152
dc->bt = FIELD_EX32(tb_flags, TBFLAG_A64, BT);
153
dc->btype = FIELD_EX32(tb_flags, TBFLAG_A64, BTYPE);
154
+ dc->unpriv = FIELD_EX32(tb_flags, TBFLAG_A64, UNPRIV);
155
dc->vec_len = 0;
156
dc->vec_stride = 0;
157
dc->cp_regs = arm_cpu->cp_regs;
158
--
45
--
159
2.20.1
46
2.20.1
160
47
161
48
diff view generated by jsdifflib
1
From: Pan Nengyuan <pannengyuan@huawei.com>
1
From: Igor Mammedov <imammedo@redhat.com>
2
2
3
There is a memory leak when we call 'device_list_properties' with typename = stm32f2xx_timer. It's easy to reproduce as follow:
3
SOC object returned by object_new() is leaked in current code.
4
Set SOC parent explicitly to board and then unref to SOC object
5
to make sure that refererence returned by object_new() is taken
6
care of.
4
7
5
virsh qemu-monitor-command vm1 --pretty '{"execute": "device-list-properties", "arguments": {"typename": "stm32f2xx_timer"}}'
8
The SOC object will be kept alive by its parent (machine) and
9
will be automatically freed when MachineState is destroyed.
6
10
7
This patch delay timer_new to fix this memleaks.
11
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
8
12
Reported-by: Andrew Jones <drjones@redhat.com>
9
Reported-by: Euler Robot <euler.robot@huawei.com>
13
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
10
Signed-off-by: Pan Nengyuan <pannengyuan@huawei.com>
14
Message-id: 20200303091254.22373-1-imammedo@redhat.com
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
13
Message-id: 20200205070659.22488-3-pannengyuan@huawei.com
14
Cc: Alistair Francis <alistair@alistair23.me>
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
17
---
18
hw/timer/stm32f2xx_timer.c | 5 +++++
18
hw/arm/cubieboard.c | 3 +++
19
1 file changed, 5 insertions(+)
19
1 file changed, 3 insertions(+)
20
20
21
diff --git a/hw/timer/stm32f2xx_timer.c b/hw/timer/stm32f2xx_timer.c
21
diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
22
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/timer/stm32f2xx_timer.c
23
--- a/hw/arm/cubieboard.c
24
+++ b/hw/timer/stm32f2xx_timer.c
24
+++ b/hw/arm/cubieboard.c
25
@@ -XXX,XX +XXX,XX @@ static void stm32f2xx_timer_init(Object *obj)
25
@@ -XXX,XX +XXX,XX @@ static void cubieboard_init(MachineState *machine)
26
memory_region_init_io(&s->iomem, obj, &stm32f2xx_timer_ops, s,
26
}
27
"stm32f2xx_timer", 0x400);
27
28
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
28
a10 = AW_A10(object_new(TYPE_AW_A10));
29
+}
29
+ object_property_add_child(OBJECT(machine), "soc", OBJECT(a10),
30
30
+ &error_abort);
31
+static void stm32f2xx_timer_realize(DeviceState *dev, Error **errp)
31
+ object_unref(OBJECT(a10));
32
+{
32
33
+ STM32F2XXTimerState *s = STM32F2XXTIMER(dev);
33
object_property_set_int(OBJECT(&a10->emac), 1, "phy-addr", &err);
34
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, stm32f2xx_timer_interrupt, s);
34
if (err != NULL) {
35
}
36
37
@@ -XXX,XX +XXX,XX @@ static void stm32f2xx_timer_class_init(ObjectClass *klass, void *data)
38
dc->reset = stm32f2xx_timer_reset;
39
device_class_set_props(dc, stm32f2xx_timer_properties);
40
dc->vmsd = &vmstate_stm32f2xx_timer;
41
+ dc->realize = stm32f2xx_timer_realize;
42
}
43
44
static const TypeInfo stm32f2xx_timer_info = {
45
--
35
--
46
2.20.1
36
2.20.1
47
37
48
38
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Guenter Roeck <linux@roeck-us.net>
2
2
3
Since we only support a single ASID, flush the tlb when it changes.
3
Wire up eSDHC controllers in fsl-imx25. For imx25-pdk, connect drives
4
provided on the command line to available eSDHC controllers.
4
5
5
Note that TCR_EL2, like TCR_EL1, has the A1 bit that chooses between
6
This patch enables booting the imx25-pdk emulation from SD card.
6
the two TTBR* registers for the location of the ASID.
7
7
8
Tested-by: Alex Bennée <alex.bennee@linaro.org>
8
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
9
Message-id: 20200310215146.19688-2-linux@roeck-us.net
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
[PMM: made commit subject consistent with other patch]
11
Message-id: 20200206105448.4726-31-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
13
---
14
target/arm/helper.c | 22 +++++++++++++++-------
14
include/hw/arm/fsl-imx25.h | 9 +++++++++
15
1 file changed, 15 insertions(+), 7 deletions(-)
15
hw/arm/fsl-imx25.c | 32 ++++++++++++++++++++++++++++++++
16
hw/arm/imx25_pdk.c | 16 ++++++++++++++++
17
3 files changed, 57 insertions(+)
16
18
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
diff --git a/include/hw/arm/fsl-imx25.h b/include/hw/arm/fsl-imx25.h
18
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.c
21
--- a/include/hw/arm/fsl-imx25.h
20
+++ b/target/arm/helper.c
22
+++ b/include/hw/arm/fsl-imx25.h
21
@@ -XXX,XX +XXX,XX @@ static void vmsa_ttbcr_reset(CPUARMState *env, const ARMCPRegInfo *ri)
23
@@ -XXX,XX +XXX,XX @@
22
tcr->base_mask = 0xffffc000u;
24
#include "hw/misc/imx_rngc.h"
25
#include "hw/i2c/imx_i2c.h"
26
#include "hw/gpio/imx_gpio.h"
27
+#include "hw/sd/sdhci.h"
28
#include "exec/memory.h"
29
#include "target/arm/cpu.h"
30
31
@@ -XXX,XX +XXX,XX @@
32
#define FSL_IMX25_NUM_EPITS 2
33
#define FSL_IMX25_NUM_I2CS 3
34
#define FSL_IMX25_NUM_GPIOS 4
35
+#define FSL_IMX25_NUM_ESDHCS 2
36
37
typedef struct FslIMX25State {
38
/*< private >*/
39
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX25State {
40
IMXRNGCState rngc;
41
IMXI2CState i2c[FSL_IMX25_NUM_I2CS];
42
IMXGPIOState gpio[FSL_IMX25_NUM_GPIOS];
43
+ SDHCIState esdhc[FSL_IMX25_NUM_ESDHCS];
44
MemoryRegion rom[2];
45
MemoryRegion iram;
46
MemoryRegion iram_alias;
47
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX25State {
48
#define FSL_IMX25_GPIO3_SIZE 0x4000
49
#define FSL_IMX25_RNGC_ADDR 0x53FB0000
50
#define FSL_IMX25_RNGC_SIZE 0x4000
51
+#define FSL_IMX25_ESDHC1_ADDR 0x53FB4000
52
+#define FSL_IMX25_ESDHC1_SIZE 0x4000
53
+#define FSL_IMX25_ESDHC2_ADDR 0x53FB8000
54
+#define FSL_IMX25_ESDHC2_SIZE 0x4000
55
#define FSL_IMX25_GPIO1_ADDR 0x53FCC000
56
#define FSL_IMX25_GPIO1_SIZE 0x4000
57
#define FSL_IMX25_GPIO2_ADDR 0x53FD0000
58
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX25State {
59
#define FSL_IMX25_GPIO2_IRQ 51
60
#define FSL_IMX25_GPIO3_IRQ 16
61
#define FSL_IMX25_GPIO4_IRQ 23
62
+#define FSL_IMX25_ESDHC1_IRQ 9
63
+#define FSL_IMX25_ESDHC2_IRQ 8
64
65
#endif /* FSL_IMX25_H */
66
diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/hw/arm/fsl-imx25.c
69
+++ b/hw/arm/fsl-imx25.c
70
@@ -XXX,XX +XXX,XX @@
71
#include "hw/qdev-properties.h"
72
#include "chardev/char.h"
73
74
+#define IMX25_ESDHC_CAPABILITIES 0x07e20000
75
+
76
static void fsl_imx25_init(Object *obj)
77
{
78
FslIMX25State *s = FSL_IMX25(obj);
79
@@ -XXX,XX +XXX,XX @@ static void fsl_imx25_init(Object *obj)
80
sysbus_init_child_obj(obj, "gpio[*]", &s->gpio[i], sizeof(s->gpio[i]),
81
TYPE_IMX_GPIO);
82
}
83
+
84
+ for (i = 0; i < FSL_IMX25_NUM_ESDHCS; i++) {
85
+ sysbus_init_child_obj(obj, "sdhc[*]", &s->esdhc[i], sizeof(s->esdhc[i]),
86
+ TYPE_IMX_USDHC);
87
+ }
23
}
88
}
24
89
25
-static void vmsa_tcr_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
90
static void fsl_imx25_realize(DeviceState *dev, Error **errp)
26
+static void vmsa_tcr_el12_write(CPUARMState *env, const ARMCPRegInfo *ri,
91
@@ -XXX,XX +XXX,XX @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
27
uint64_t value)
92
gpio_table[i].irq));
28
{
93
}
29
ARMCPU *cpu = env_archcpu(env);
94
30
@@ -XXX,XX +XXX,XX @@ static void vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
95
+ /* Initialize all SDHC */
31
static void vmsa_tcr_ttbr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
96
+ for (i = 0; i < FSL_IMX25_NUM_ESDHCS; i++) {
32
uint64_t value)
97
+ static const struct {
33
{
98
+ hwaddr addr;
34
- /* TODO: There are ASID fields in here with HCR_EL2.E2H */
99
+ unsigned int irq;
35
+ /*
100
+ } esdhc_table[FSL_IMX25_NUM_ESDHCS] = {
36
+ * If we are running with E2&0 regime, then an ASID is active.
101
+ { FSL_IMX25_ESDHC1_ADDR, FSL_IMX25_ESDHC1_IRQ },
37
+ * Flush if that might be changing. Note we're not checking
102
+ { FSL_IMX25_ESDHC2_ADDR, FSL_IMX25_ESDHC2_IRQ },
38
+ * TCR_EL2.A1 to know if this is really the TTBRx_EL2 that
103
+ };
39
+ * holds the active ASID, only checking the field that might.
104
+
40
+ */
105
+ object_property_set_uint(OBJECT(&s->esdhc[i]), 2, "sd-spec-version",
41
+ if (extract64(raw_read(env, ri) ^ value, 48, 16) &&
106
+ &err);
42
+ (arm_hcr_el2_eff(env) & HCR_E2H)) {
107
+ object_property_set_uint(OBJECT(&s->esdhc[i]), IMX25_ESDHC_CAPABILITIES,
43
+ tlb_flush_by_mmuidx(env_cpu(env),
108
+ "capareg", &err);
44
+ ARMMMUIdxBit_E20_2 | ARMMMUIdxBit_E20_0);
109
+ object_property_set_bool(OBJECT(&s->esdhc[i]), true, "realized", &err);
110
+ if (err) {
111
+ error_propagate(errp, err);
112
+ return;
113
+ }
114
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->esdhc[i]), 0, esdhc_table[i].addr);
115
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->esdhc[i]), 0,
116
+ qdev_get_gpio_in(DEVICE(&s->avic),
117
+ esdhc_table[i].irq));
45
+ }
118
+ }
46
raw_write(env, ri, value);
119
+
47
}
120
/* initialize 2 x 16 KB ROM */
48
121
memory_region_init_rom(&s->rom[0], NULL,
49
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = {
122
"imx25.rom0", FSL_IMX25_ROM0_SIZE, &err);
50
offsetof(CPUARMState, cp15.ttbr1_ns) } },
123
diff --git a/hw/arm/imx25_pdk.c b/hw/arm/imx25_pdk.c
51
{ .name = "TCR_EL1", .state = ARM_CP_STATE_AA64,
124
index XXXXXXX..XXXXXXX 100644
52
.opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2,
125
--- a/hw/arm/imx25_pdk.c
53
- .access = PL1_RW, .writefn = vmsa_tcr_el1_write,
126
+++ b/hw/arm/imx25_pdk.c
54
+ .access = PL1_RW, .writefn = vmsa_tcr_el12_write,
127
@@ -XXX,XX +XXX,XX @@
55
.resetfn = vmsa_ttbcr_reset, .raw_writefn = raw_write,
128
#include "qemu/osdep.h"
56
.fieldoffset = offsetof(CPUARMState, cp15.tcr_el[1]) },
129
#include "qapi/error.h"
57
{ .name = "TTBCR", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2,
130
#include "cpu.h"
58
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
131
+#include "hw/qdev-properties.h"
59
.resetvalue = 0 },
132
#include "hw/arm/fsl-imx25.h"
60
{ .name = "TCR_EL2", .state = ARM_CP_STATE_BOTH,
133
#include "hw/boards.h"
61
.opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 2,
134
#include "qemu/error-report.h"
62
- .access = PL2_RW,
135
@@ -XXX,XX +XXX,XX @@ static void imx25_pdk_init(MachineState *machine)
63
- /* no .writefn needed as this can't cause an ASID change;
136
imx25_pdk_binfo.board_id = 1771,
64
- * no .raw_writefn or .resetfn needed as we never use mask/base_mask
137
imx25_pdk_binfo.nb_cpus = 1;
65
- */
138
66
+ .access = PL2_RW, .writefn = vmsa_tcr_el12_write,
139
+ for (i = 0; i < FSL_IMX25_NUM_ESDHCS; i++) {
67
+ /* no .raw_writefn or .resetfn needed as we never use mask/base_mask */
140
+ BusState *bus;
68
.fieldoffset = offsetof(CPUARMState, cp15.tcr_el[2]) },
141
+ DeviceState *carddev;
69
{ .name = "VTCR", .state = ARM_CP_STATE_AA32,
142
+ DriveInfo *di;
70
.cp = 15, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 2,
143
+ BlockBackend *blk;
144
+
145
+ di = drive_get_next(IF_SD);
146
+ blk = di ? blk_by_legacy_dinfo(di) : NULL;
147
+ bus = qdev_get_child_bus(DEVICE(&s->soc.esdhc[i]), "sd-bus");
148
+ carddev = qdev_create(bus, TYPE_SD_CARD);
149
+ qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
150
+ object_property_set_bool(OBJECT(carddev), true,
151
+ "realized", &error_fatal);
152
+ }
153
+
154
/*
155
* We test explicitly for qtest here as it is not done (yet?) in
156
* arm_load_kernel(). Without this the "make check" command would
71
--
157
--
72
2.20.1
158
2.20.1
73
159
74
160
diff view generated by jsdifflib
1
From: Pan Nengyuan <pannengyuan@huawei.com>
1
From: Guenter Roeck <linux@roeck-us.net>
2
2
3
There is a memory leak when we call 'device_list_properties' with typename = armv7m_systick. It's easy to reproduce as follow:
3
i.MX25 supports two USB controllers. Let's wire them up.
4
4
5
virsh qemu-monitor-command vm1 --pretty '{"execute": "device-list-properties", "arguments": {"typename": "armv7m_systick"}}'
5
With this patch, imx25-pdk can boot from both USB ports.
6
6
7
This patch delay timer_new to fix this memleaks.
7
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
8
8
Message-id: 20200310215146.19688-3-linux@roeck-us.net
9
Reported-by: Euler Robot <euler.robot@huawei.com>
10
Signed-off-by: Pan Nengyuan <pannengyuan@huawei.com>
11
Message-id: 20200205070659.22488-2-pannengyuan@huawei.com
12
Cc: qemu-arm@nongnu.org
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
11
---
16
hw/timer/armv7m_systick.c | 6 ++++++
12
include/hw/arm/fsl-imx25.h | 9 +++++++++
17
1 file changed, 6 insertions(+)
13
hw/arm/fsl-imx25.c | 24 ++++++++++++++++++++++++
14
2 files changed, 33 insertions(+)
18
15
19
diff --git a/hw/timer/armv7m_systick.c b/hw/timer/armv7m_systick.c
16
diff --git a/include/hw/arm/fsl-imx25.h b/include/hw/arm/fsl-imx25.h
20
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/timer/armv7m_systick.c
18
--- a/include/hw/arm/fsl-imx25.h
22
+++ b/hw/timer/armv7m_systick.c
19
+++ b/include/hw/arm/fsl-imx25.h
23
@@ -XXX,XX +XXX,XX @@ static void systick_instance_init(Object *obj)
20
@@ -XXX,XX +XXX,XX @@
24
memory_region_init_io(&s->iomem, obj, &systick_ops, s, "systick", 0xe0);
21
#include "hw/i2c/imx_i2c.h"
25
sysbus_init_mmio(sbd, &s->iomem);
22
#include "hw/gpio/imx_gpio.h"
26
sysbus_init_irq(sbd, &s->irq);
23
#include "hw/sd/sdhci.h"
27
+}
24
+#include "hw/usb/chipidea.h"
25
#include "exec/memory.h"
26
#include "target/arm/cpu.h"
27
28
@@ -XXX,XX +XXX,XX @@
29
#define FSL_IMX25_NUM_I2CS 3
30
#define FSL_IMX25_NUM_GPIOS 4
31
#define FSL_IMX25_NUM_ESDHCS 2
32
+#define FSL_IMX25_NUM_USBS 2
33
34
typedef struct FslIMX25State {
35
/*< private >*/
36
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX25State {
37
IMXI2CState i2c[FSL_IMX25_NUM_I2CS];
38
IMXGPIOState gpio[FSL_IMX25_NUM_GPIOS];
39
SDHCIState esdhc[FSL_IMX25_NUM_ESDHCS];
40
+ ChipideaState usb[FSL_IMX25_NUM_USBS];
41
MemoryRegion rom[2];
42
MemoryRegion iram;
43
MemoryRegion iram_alias;
44
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX25State {
45
#define FSL_IMX25_GPIO1_SIZE 0x4000
46
#define FSL_IMX25_GPIO2_ADDR 0x53FD0000
47
#define FSL_IMX25_GPIO2_SIZE 0x4000
48
+#define FSL_IMX25_USB1_ADDR 0x53FF4000
49
+#define FSL_IMX25_USB1_SIZE 0x0200
50
+#define FSL_IMX25_USB2_ADDR 0x53FF4400
51
+#define FSL_IMX25_USB2_SIZE 0x0200
52
#define FSL_IMX25_AVIC_ADDR 0x68000000
53
#define FSL_IMX25_AVIC_SIZE 0x4000
54
#define FSL_IMX25_IRAM_ADDR 0x78000000
55
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX25State {
56
#define FSL_IMX25_GPIO4_IRQ 23
57
#define FSL_IMX25_ESDHC1_IRQ 9
58
#define FSL_IMX25_ESDHC2_IRQ 8
59
+#define FSL_IMX25_USB1_IRQ 37
60
+#define FSL_IMX25_USB2_IRQ 35
61
62
#endif /* FSL_IMX25_H */
63
diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/arm/fsl-imx25.c
66
+++ b/hw/arm/fsl-imx25.c
67
@@ -XXX,XX +XXX,XX @@ static void fsl_imx25_init(Object *obj)
68
sysbus_init_child_obj(obj, "sdhc[*]", &s->esdhc[i], sizeof(s->esdhc[i]),
69
TYPE_IMX_USDHC);
70
}
28
+
71
+
29
+static void systick_realize(DeviceState *dev, Error **errp)
72
+ for (i = 0; i < FSL_IMX25_NUM_USBS; i++) {
30
+{
73
+ sysbus_init_child_obj(obj, "usb[*]", &s->usb[i], sizeof(s->usb[i]),
31
+ SysTickState *s = SYSTICK(dev);
74
+ TYPE_CHIPIDEA);
32
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, systick_timer_tick, s);
75
+ }
76
+
33
}
77
}
34
78
35
@@ -XXX,XX +XXX,XX @@ static void systick_class_init(ObjectClass *klass, void *data)
79
static void fsl_imx25_realize(DeviceState *dev, Error **errp)
36
80
@@ -XXX,XX +XXX,XX @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
37
dc->vmsd = &vmstate_systick;
81
esdhc_table[i].irq));
38
dc->reset = systick_reset;
82
}
39
+ dc->realize = systick_realize;
83
40
}
84
+ /* USB */
41
85
+ for (i = 0; i < FSL_IMX25_NUM_USBS; i++) {
42
static const TypeInfo armv7m_systick_info = {
86
+ static const struct {
87
+ hwaddr addr;
88
+ unsigned int irq;
89
+ } usb_table[FSL_IMX25_NUM_USBS] = {
90
+ { FSL_IMX25_USB1_ADDR, FSL_IMX25_USB1_IRQ },
91
+ { FSL_IMX25_USB2_ADDR, FSL_IMX25_USB2_IRQ },
92
+ };
93
+
94
+ object_property_set_bool(OBJECT(&s->usb[i]), true, "realized",
95
+ &error_abort);
96
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0, usb_table[i].addr);
97
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i]), 0,
98
+ qdev_get_gpio_in(DEVICE(&s->avic),
99
+ usb_table[i].irq));
100
+ }
101
+
102
/* initialize 2 x 16 KB ROM */
103
memory_region_init_rom(&s->rom[0], NULL,
104
"imx25.rom0", FSL_IMX25_ROM0_SIZE, &err);
43
--
105
--
44
2.20.1
106
2.20.1
45
107
46
108
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
No functional change, but unify code sequences.
3
The Allwinner H3 is a System on Chip containing four ARM Cortex A7
4
processor cores. Features and specifications include DDR2/DDR3 memory,
5
SD/MMC storage cards, 10/100/1000Mbit Ethernet, USB 2.0, HDMI and
6
various I/O modules. This commit adds support for the Allwinner H3
7
System on Chip.
4
8
5
Tested-by: Alex Bennée <alex.bennee@linaro.org>
9
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 20200206105448.4726-7-richard.henderson@linaro.org
13
Message-id: 20200311221854.30370-2-nieklinnenbank@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
15
---
12
target/arm/helper.c | 32 +++++++++++++-------------------
16
hw/arm/Makefile.objs | 1 +
13
1 file changed, 13 insertions(+), 19 deletions(-)
17
include/hw/arm/allwinner-h3.h | 106 +++++++++++
18
hw/arm/allwinner-h3.c | 327 ++++++++++++++++++++++++++++++++
19
MAINTAINERS | 7 +
20
default-configs/arm-softmmu.mak | 1 +
21
hw/arm/Kconfig | 8 +
22
6 files changed, 450 insertions(+)
23
create mode 100644 include/hw/arm/allwinner-h3.h
24
create mode 100644 hw/arm/allwinner-h3.c
14
25
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
26
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
16
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
28
--- a/hw/arm/Makefile.objs
18
+++ b/target/arm/helper.c
29
+++ b/hw/arm/Makefile.objs
19
@@ -XXX,XX +XXX,XX @@ static CPAccessResult aa64_cacheop_access(CPUARMState *env,
30
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_DIGIC) += digic.o
20
* Page D4-1736 (DDI0487A.b)
31
obj-$(CONFIG_OMAP) += omap1.o omap2.o
21
*/
32
obj-$(CONFIG_STRONGARM) += strongarm.o
22
33
obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
23
+static int vae1_tlbmask(CPUARMState *env)
34
+obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3.o
35
obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
36
obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
37
obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o
38
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
39
new file mode 100644
40
index XXXXXXX..XXXXXXX
41
--- /dev/null
42
+++ b/include/hw/arm/allwinner-h3.h
43
@@ -XXX,XX +XXX,XX @@
44
+/*
45
+ * Allwinner H3 System on Chip emulation
46
+ *
47
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
48
+ *
49
+ * This program is free software: you can redistribute it and/or modify
50
+ * it under the terms of the GNU General Public License as published by
51
+ * the Free Software Foundation, either version 2 of the License, or
52
+ * (at your option) any later version.
53
+ *
54
+ * This program is distributed in the hope that it will be useful,
55
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
56
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57
+ * GNU General Public License for more details.
58
+ *
59
+ * You should have received a copy of the GNU General Public License
60
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
61
+ */
62
+
63
+/*
64
+ * The Allwinner H3 is a System on Chip containing four ARM Cortex A7
65
+ * processor cores. Features and specifications include DDR2/DDR3 memory,
66
+ * SD/MMC storage cards, 10/100/1000Mbit Ethernet, USB 2.0, HDMI and
67
+ * various I/O modules.
68
+ *
69
+ * This implementation is based on the following datasheet:
70
+ *
71
+ * https://linux-sunxi.org/File:Allwinner_H3_Datasheet_V1.2.pdf
72
+ *
73
+ * The latest datasheet and more info can be found on the Linux Sunxi wiki:
74
+ *
75
+ * https://linux-sunxi.org/H3
76
+ */
77
+
78
+#ifndef HW_ARM_ALLWINNER_H3_H
79
+#define HW_ARM_ALLWINNER_H3_H
80
+
81
+#include "qom/object.h"
82
+#include "hw/arm/boot.h"
83
+#include "hw/timer/allwinner-a10-pit.h"
84
+#include "hw/intc/arm_gic.h"
85
+#include "target/arm/cpu.h"
86
+
87
+/**
88
+ * Allwinner H3 device list
89
+ *
90
+ * This enumeration is can be used refer to a particular device in the
91
+ * Allwinner H3 SoC. For example, the physical memory base address for
92
+ * each device can be found in the AwH3State object in the memmap member
93
+ * using the device enum value as index.
94
+ *
95
+ * @see AwH3State
96
+ */
97
+enum {
98
+ AW_H3_SRAM_A1,
99
+ AW_H3_SRAM_A2,
100
+ AW_H3_SRAM_C,
101
+ AW_H3_PIT,
102
+ AW_H3_UART0,
103
+ AW_H3_UART1,
104
+ AW_H3_UART2,
105
+ AW_H3_UART3,
106
+ AW_H3_GIC_DIST,
107
+ AW_H3_GIC_CPU,
108
+ AW_H3_GIC_HYP,
109
+ AW_H3_GIC_VCPU,
110
+ AW_H3_SDRAM
111
+};
112
+
113
+/** Total number of CPU cores in the H3 SoC */
114
+#define AW_H3_NUM_CPUS (4)
115
+
116
+/**
117
+ * Allwinner H3 object model
118
+ * @{
119
+ */
120
+
121
+/** Object type for the Allwinner H3 SoC */
122
+#define TYPE_AW_H3 "allwinner-h3"
123
+
124
+/** Convert input object to Allwinner H3 state object */
125
+#define AW_H3(obj) OBJECT_CHECK(AwH3State, (obj), TYPE_AW_H3)
126
+
127
+/** @} */
128
+
129
+/**
130
+ * Allwinner H3 object
131
+ *
132
+ * This struct contains the state of all the devices
133
+ * which are currently emulated by the H3 SoC code.
134
+ */
135
+typedef struct AwH3State {
136
+ /*< private >*/
137
+ DeviceState parent_obj;
138
+ /*< public >*/
139
+
140
+ ARMCPU cpus[AW_H3_NUM_CPUS];
141
+ const hwaddr *memmap;
142
+ AwA10PITState timer;
143
+ GICState gic;
144
+ MemoryRegion sram_a1;
145
+ MemoryRegion sram_a2;
146
+ MemoryRegion sram_c;
147
+} AwH3State;
148
+
149
+#endif /* HW_ARM_ALLWINNER_H3_H */
150
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
151
new file mode 100644
152
index XXXXXXX..XXXXXXX
153
--- /dev/null
154
+++ b/hw/arm/allwinner-h3.c
155
@@ -XXX,XX +XXX,XX @@
156
+/*
157
+ * Allwinner H3 System on Chip emulation
158
+ *
159
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
160
+ *
161
+ * This program is free software: you can redistribute it and/or modify
162
+ * it under the terms of the GNU General Public License as published by
163
+ * the Free Software Foundation, either version 2 of the License, or
164
+ * (at your option) any later version.
165
+ *
166
+ * This program is distributed in the hope that it will be useful,
167
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
168
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
169
+ * GNU General Public License for more details.
170
+ *
171
+ * You should have received a copy of the GNU General Public License
172
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
173
+ */
174
+
175
+#include "qemu/osdep.h"
176
+#include "exec/address-spaces.h"
177
+#include "qapi/error.h"
178
+#include "qemu/error-report.h"
179
+#include "qemu/module.h"
180
+#include "qemu/units.h"
181
+#include "hw/qdev-core.h"
182
+#include "cpu.h"
183
+#include "hw/sysbus.h"
184
+#include "hw/char/serial.h"
185
+#include "hw/misc/unimp.h"
186
+#include "sysemu/sysemu.h"
187
+#include "hw/arm/allwinner-h3.h"
188
+
189
+/* Memory map */
190
+const hwaddr allwinner_h3_memmap[] = {
191
+ [AW_H3_SRAM_A1] = 0x00000000,
192
+ [AW_H3_SRAM_A2] = 0x00044000,
193
+ [AW_H3_SRAM_C] = 0x00010000,
194
+ [AW_H3_PIT] = 0x01c20c00,
195
+ [AW_H3_UART0] = 0x01c28000,
196
+ [AW_H3_UART1] = 0x01c28400,
197
+ [AW_H3_UART2] = 0x01c28800,
198
+ [AW_H3_UART3] = 0x01c28c00,
199
+ [AW_H3_GIC_DIST] = 0x01c81000,
200
+ [AW_H3_GIC_CPU] = 0x01c82000,
201
+ [AW_H3_GIC_HYP] = 0x01c84000,
202
+ [AW_H3_GIC_VCPU] = 0x01c86000,
203
+ [AW_H3_SDRAM] = 0x40000000
204
+};
205
+
206
+/* List of unimplemented devices */
207
+struct AwH3Unimplemented {
208
+ const char *device_name;
209
+ hwaddr base;
210
+ hwaddr size;
211
+} unimplemented[] = {
212
+ { "d-engine", 0x01000000, 4 * MiB },
213
+ { "d-inter", 0x01400000, 128 * KiB },
214
+ { "syscon", 0x01c00000, 4 * KiB },
215
+ { "dma", 0x01c02000, 4 * KiB },
216
+ { "nfdc", 0x01c03000, 4 * KiB },
217
+ { "ts", 0x01c06000, 4 * KiB },
218
+ { "keymem", 0x01c0b000, 4 * KiB },
219
+ { "lcd0", 0x01c0c000, 4 * KiB },
220
+ { "lcd1", 0x01c0d000, 4 * KiB },
221
+ { "ve", 0x01c0e000, 4 * KiB },
222
+ { "mmc0", 0x01c0f000, 4 * KiB },
223
+ { "mmc1", 0x01c10000, 4 * KiB },
224
+ { "mmc2", 0x01c11000, 4 * KiB },
225
+ { "sid", 0x01c14000, 1 * KiB },
226
+ { "crypto", 0x01c15000, 4 * KiB },
227
+ { "msgbox", 0x01c17000, 4 * KiB },
228
+ { "spinlock", 0x01c18000, 4 * KiB },
229
+ { "usb0-otg", 0x01c19000, 4 * KiB },
230
+ { "usb0-phy", 0x01c1a000, 4 * KiB },
231
+ { "usb1-phy", 0x01c1b000, 4 * KiB },
232
+ { "usb2-phy", 0x01c1c000, 4 * KiB },
233
+ { "usb3-phy", 0x01c1d000, 4 * KiB },
234
+ { "smc", 0x01c1e000, 4 * KiB },
235
+ { "ccu", 0x01c20000, 1 * KiB },
236
+ { "pio", 0x01c20800, 1 * KiB },
237
+ { "owa", 0x01c21000, 1 * KiB },
238
+ { "pwm", 0x01c21400, 1 * KiB },
239
+ { "keyadc", 0x01c21800, 1 * KiB },
240
+ { "pcm0", 0x01c22000, 1 * KiB },
241
+ { "pcm1", 0x01c22400, 1 * KiB },
242
+ { "pcm2", 0x01c22800, 1 * KiB },
243
+ { "audio", 0x01c22c00, 2 * KiB },
244
+ { "smta", 0x01c23400, 1 * KiB },
245
+ { "ths", 0x01c25000, 1 * KiB },
246
+ { "uart0", 0x01c28000, 1 * KiB },
247
+ { "uart1", 0x01c28400, 1 * KiB },
248
+ { "uart2", 0x01c28800, 1 * KiB },
249
+ { "uart3", 0x01c28c00, 1 * KiB },
250
+ { "twi0", 0x01c2ac00, 1 * KiB },
251
+ { "twi1", 0x01c2b000, 1 * KiB },
252
+ { "twi2", 0x01c2b400, 1 * KiB },
253
+ { "scr", 0x01c2c400, 1 * KiB },
254
+ { "emac", 0x01c30000, 64 * KiB },
255
+ { "gpu", 0x01c40000, 64 * KiB },
256
+ { "hstmr", 0x01c60000, 4 * KiB },
257
+ { "dramcom", 0x01c62000, 4 * KiB },
258
+ { "dramctl0", 0x01c63000, 4 * KiB },
259
+ { "dramphy0", 0x01c65000, 4 * KiB },
260
+ { "spi0", 0x01c68000, 4 * KiB },
261
+ { "spi1", 0x01c69000, 4 * KiB },
262
+ { "csi", 0x01cb0000, 320 * KiB },
263
+ { "tve", 0x01e00000, 64 * KiB },
264
+ { "hdmi", 0x01ee0000, 128 * KiB },
265
+ { "rtc", 0x01f00000, 1 * KiB },
266
+ { "r_timer", 0x01f00800, 1 * KiB },
267
+ { "r_intc", 0x01f00c00, 1 * KiB },
268
+ { "r_wdog", 0x01f01000, 1 * KiB },
269
+ { "r_prcm", 0x01f01400, 1 * KiB },
270
+ { "r_twd", 0x01f01800, 1 * KiB },
271
+ { "r_cpucfg", 0x01f01c00, 1 * KiB },
272
+ { "r_cir-rx", 0x01f02000, 1 * KiB },
273
+ { "r_twi", 0x01f02400, 1 * KiB },
274
+ { "r_uart", 0x01f02800, 1 * KiB },
275
+ { "r_pio", 0x01f02c00, 1 * KiB },
276
+ { "r_pwm", 0x01f03800, 1 * KiB },
277
+ { "core-dbg", 0x3f500000, 128 * KiB },
278
+ { "tsgen-ro", 0x3f506000, 4 * KiB },
279
+ { "tsgen-ctl", 0x3f507000, 4 * KiB },
280
+ { "ddr-mem", 0x40000000, 2 * GiB },
281
+ { "n-brom", 0xffff0000, 32 * KiB },
282
+ { "s-brom", 0xffff0000, 64 * KiB }
283
+};
284
+
285
+/* Per Processor Interrupts */
286
+enum {
287
+ AW_H3_GIC_PPI_MAINT = 9,
288
+ AW_H3_GIC_PPI_HYPTIMER = 10,
289
+ AW_H3_GIC_PPI_VIRTTIMER = 11,
290
+ AW_H3_GIC_PPI_SECTIMER = 13,
291
+ AW_H3_GIC_PPI_PHYSTIMER = 14
292
+};
293
+
294
+/* Shared Processor Interrupts */
295
+enum {
296
+ AW_H3_GIC_SPI_UART0 = 0,
297
+ AW_H3_GIC_SPI_UART1 = 1,
298
+ AW_H3_GIC_SPI_UART2 = 2,
299
+ AW_H3_GIC_SPI_UART3 = 3,
300
+ AW_H3_GIC_SPI_TIMER0 = 18,
301
+ AW_H3_GIC_SPI_TIMER1 = 19,
302
+};
303
+
304
+/* Allwinner H3 general constants */
305
+enum {
306
+ AW_H3_GIC_NUM_SPI = 128
307
+};
308
+
309
+static void allwinner_h3_init(Object *obj)
24
+{
310
+{
25
+ if (arm_is_secure_below_el3(env)) {
311
+ AwH3State *s = AW_H3(obj);
26
+ return ARMMMUIdxBit_S1SE1 | ARMMMUIdxBit_S1SE0;
312
+
27
+ } else {
313
+ s->memmap = allwinner_h3_memmap;
28
+ return ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0;
314
+
315
+ for (int i = 0; i < AW_H3_NUM_CPUS; i++) {
316
+ object_initialize_child(obj, "cpu[*]", &s->cpus[i], sizeof(s->cpus[i]),
317
+ ARM_CPU_TYPE_NAME("cortex-a7"),
318
+ &error_abort, NULL);
319
+ }
320
+
321
+ sysbus_init_child_obj(obj, "gic", &s->gic, sizeof(s->gic),
322
+ TYPE_ARM_GIC);
323
+
324
+ sysbus_init_child_obj(obj, "timer", &s->timer, sizeof(s->timer),
325
+ TYPE_AW_A10_PIT);
326
+ object_property_add_alias(obj, "clk0-freq", OBJECT(&s->timer),
327
+ "clk0-freq", &error_abort);
328
+ object_property_add_alias(obj, "clk1-freq", OBJECT(&s->timer),
329
+ "clk1-freq", &error_abort);
330
+}
331
+
332
+static void allwinner_h3_realize(DeviceState *dev, Error **errp)
333
+{
334
+ AwH3State *s = AW_H3(dev);
335
+ unsigned i;
336
+
337
+ /* CPUs */
338
+ for (i = 0; i < AW_H3_NUM_CPUS; i++) {
339
+
340
+ /* Provide Power State Coordination Interface */
341
+ qdev_prop_set_int32(DEVICE(&s->cpus[i]), "psci-conduit",
342
+ QEMU_PSCI_CONDUIT_HVC);
343
+
344
+ /* Disable secondary CPUs */
345
+ qdev_prop_set_bit(DEVICE(&s->cpus[i]), "start-powered-off",
346
+ i > 0);
347
+
348
+ /* All exception levels required */
349
+ qdev_prop_set_bit(DEVICE(&s->cpus[i]), "has_el3", true);
350
+ qdev_prop_set_bit(DEVICE(&s->cpus[i]), "has_el2", true);
351
+
352
+ /* Mark realized */
353
+ qdev_init_nofail(DEVICE(&s->cpus[i]));
354
+ }
355
+
356
+ /* Generic Interrupt Controller */
357
+ qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", AW_H3_GIC_NUM_SPI +
358
+ GIC_INTERNAL);
359
+ qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 2);
360
+ qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", AW_H3_NUM_CPUS);
361
+ qdev_prop_set_bit(DEVICE(&s->gic), "has-security-extensions", false);
362
+ qdev_prop_set_bit(DEVICE(&s->gic), "has-virtualization-extensions", true);
363
+ qdev_init_nofail(DEVICE(&s->gic));
364
+
365
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 0, s->memmap[AW_H3_GIC_DIST]);
366
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 1, s->memmap[AW_H3_GIC_CPU]);
367
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 2, s->memmap[AW_H3_GIC_HYP]);
368
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 3, s->memmap[AW_H3_GIC_VCPU]);
369
+
370
+ /*
371
+ * Wire the outputs from each CPU's generic timer and the GICv3
372
+ * maintenance interrupt signal to the appropriate GIC PPI inputs,
373
+ * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs.
374
+ */
375
+ for (i = 0; i < AW_H3_NUM_CPUS; i++) {
376
+ DeviceState *cpudev = DEVICE(&s->cpus[i]);
377
+ int ppibase = AW_H3_GIC_NUM_SPI + i * GIC_INTERNAL + GIC_NR_SGIS;
378
+ int irq;
379
+ /*
380
+ * Mapping from the output timer irq lines from the CPU to the
381
+ * GIC PPI inputs used for this board.
382
+ */
383
+ const int timer_irq[] = {
384
+ [GTIMER_PHYS] = AW_H3_GIC_PPI_PHYSTIMER,
385
+ [GTIMER_VIRT] = AW_H3_GIC_PPI_VIRTTIMER,
386
+ [GTIMER_HYP] = AW_H3_GIC_PPI_HYPTIMER,
387
+ [GTIMER_SEC] = AW_H3_GIC_PPI_SECTIMER,
388
+ };
389
+
390
+ /* Connect CPU timer outputs to GIC PPI inputs */
391
+ for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
392
+ qdev_connect_gpio_out(cpudev, irq,
393
+ qdev_get_gpio_in(DEVICE(&s->gic),
394
+ ppibase + timer_irq[irq]));
395
+ }
396
+
397
+ /* Connect GIC outputs to CPU interrupt inputs */
398
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i,
399
+ qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
400
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + AW_H3_NUM_CPUS,
401
+ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
402
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + (2 * AW_H3_NUM_CPUS),
403
+ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
404
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + (3 * AW_H3_NUM_CPUS),
405
+ qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
406
+
407
+ /* GIC maintenance signal */
408
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + (4 * AW_H3_NUM_CPUS),
409
+ qdev_get_gpio_in(DEVICE(&s->gic),
410
+ ppibase + AW_H3_GIC_PPI_MAINT));
411
+ }
412
+
413
+ /* Timer */
414
+ qdev_init_nofail(DEVICE(&s->timer));
415
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->timer), 0, s->memmap[AW_H3_PIT]);
416
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer), 0,
417
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_TIMER0));
418
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer), 1,
419
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_TIMER1));
420
+
421
+ /* SRAM */
422
+ memory_region_init_ram(&s->sram_a1, OBJECT(dev), "sram A1",
423
+ 64 * KiB, &error_abort);
424
+ memory_region_init_ram(&s->sram_a2, OBJECT(dev), "sram A2",
425
+ 32 * KiB, &error_abort);
426
+ memory_region_init_ram(&s->sram_c, OBJECT(dev), "sram C",
427
+ 44 * KiB, &error_abort);
428
+ memory_region_add_subregion(get_system_memory(), s->memmap[AW_H3_SRAM_A1],
429
+ &s->sram_a1);
430
+ memory_region_add_subregion(get_system_memory(), s->memmap[AW_H3_SRAM_A2],
431
+ &s->sram_a2);
432
+ memory_region_add_subregion(get_system_memory(), s->memmap[AW_H3_SRAM_C],
433
+ &s->sram_c);
434
+
435
+ /* UART0. For future clocktree API: All UARTS are connected to APB2_CLK. */
436
+ serial_mm_init(get_system_memory(), s->memmap[AW_H3_UART0], 2,
437
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART0),
438
+ 115200, serial_hd(0), DEVICE_NATIVE_ENDIAN);
439
+ /* UART1 */
440
+ serial_mm_init(get_system_memory(), s->memmap[AW_H3_UART1], 2,
441
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART1),
442
+ 115200, serial_hd(1), DEVICE_NATIVE_ENDIAN);
443
+ /* UART2 */
444
+ serial_mm_init(get_system_memory(), s->memmap[AW_H3_UART2], 2,
445
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART2),
446
+ 115200, serial_hd(2), DEVICE_NATIVE_ENDIAN);
447
+ /* UART3 */
448
+ serial_mm_init(get_system_memory(), s->memmap[AW_H3_UART3], 2,
449
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART3),
450
+ 115200, serial_hd(3), DEVICE_NATIVE_ENDIAN);
451
+
452
+ /* Unimplemented devices */
453
+ for (i = 0; i < ARRAY_SIZE(unimplemented); i++) {
454
+ create_unimplemented_device(unimplemented[i].device_name,
455
+ unimplemented[i].base,
456
+ unimplemented[i].size);
29
+ }
457
+ }
30
+}
458
+}
31
+
459
+
32
static void tlbi_aa64_vmalle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
460
+static void allwinner_h3_class_init(ObjectClass *oc, void *data)
33
uint64_t value)
461
+{
34
{
462
+ DeviceClass *dc = DEVICE_CLASS(oc);
35
CPUState *cs = env_cpu(env);
463
+
36
- bool sec = arm_is_secure_below_el3(env);
464
+ dc->realize = allwinner_h3_realize;
37
+ int mask = vae1_tlbmask(env);
465
+ /* Reason: uses serial_hd() in realize function */
38
466
+ dc->user_creatable = false;
39
- if (sec) {
467
+}
40
- tlb_flush_by_mmuidx_all_cpus_synced(cs,
468
+
41
- ARMMMUIdxBit_S1SE1 |
469
+static const TypeInfo allwinner_h3_type_info = {
42
- ARMMMUIdxBit_S1SE0);
470
+ .name = TYPE_AW_H3,
43
- } else {
471
+ .parent = TYPE_DEVICE,
44
- tlb_flush_by_mmuidx_all_cpus_synced(cs,
472
+ .instance_size = sizeof(AwH3State),
45
- ARMMMUIdxBit_S12NSE1 |
473
+ .instance_init = allwinner_h3_init,
46
- ARMMMUIdxBit_S12NSE0);
474
+ .class_init = allwinner_h3_class_init,
47
- }
475
+};
48
+ tlb_flush_by_mmuidx_all_cpus_synced(cs, mask);
476
+
49
}
477
+static void allwinner_h3_register_types(void)
50
478
+{
51
static void tlbi_aa64_vmalle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
479
+ type_register_static(&allwinner_h3_type_info);
52
uint64_t value)
480
+}
53
{
481
+
54
CPUState *cs = env_cpu(env);
482
+type_init(allwinner_h3_register_types)
55
+ int mask = vae1_tlbmask(env);
483
diff --git a/MAINTAINERS b/MAINTAINERS
56
484
index XXXXXXX..XXXXXXX 100644
57
if (tlb_force_broadcast(env)) {
485
--- a/MAINTAINERS
58
tlbi_aa64_vmalle1is_write(env, NULL, value);
486
+++ b/MAINTAINERS
59
return;
487
@@ -XXX,XX +XXX,XX @@ F: hw/*/allwinner*
60
}
488
F: include/hw/*/allwinner*
61
489
F: hw/arm/cubieboard.c
62
- if (arm_is_secure_below_el3(env)) {
490
63
- tlb_flush_by_mmuidx(cs,
491
+Allwinner-h3
64
- ARMMMUIdxBit_S1SE1 |
492
+M: Niek Linnenbank <nieklinnenbank@gmail.com>
65
- ARMMMUIdxBit_S1SE0);
493
+L: qemu-arm@nongnu.org
66
- } else {
494
+S: Maintained
67
- tlb_flush_by_mmuidx(cs,
495
+F: hw/*/allwinner-h3*
68
- ARMMMUIdxBit_S12NSE1 |
496
+F: include/hw/*/allwinner-h3*
69
- ARMMMUIdxBit_S12NSE0);
497
+
70
- }
498
ARM PrimeCell and CMSDK devices
71
+ tlb_flush_by_mmuidx(cs, mask);
499
M: Peter Maydell <peter.maydell@linaro.org>
72
}
500
L: qemu-arm@nongnu.org
73
501
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
74
static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
502
index XXXXXXX..XXXXXXX 100644
503
--- a/default-configs/arm-softmmu.mak
504
+++ b/default-configs/arm-softmmu.mak
505
@@ -XXX,XX +XXX,XX @@ CONFIG_FSL_IMX25=y
506
CONFIG_FSL_IMX7=y
507
CONFIG_FSL_IMX6UL=y
508
CONFIG_SEMIHOSTING=y
509
+CONFIG_ALLWINNER_H3=y
510
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
511
index XXXXXXX..XXXXXXX 100644
512
--- a/hw/arm/Kconfig
513
+++ b/hw/arm/Kconfig
514
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10
515
select SERIAL
516
select UNIMP
517
518
+config ALLWINNER_H3
519
+ bool
520
+ select ALLWINNER_A10_PIT
521
+ select SERIAL
522
+ select ARM_TIMER
523
+ select ARM_GIC
524
+ select UNIMP
525
+
526
config RASPI
527
bool
528
select FRAMEBUFFER
75
--
529
--
76
2.20.1
530
2.20.1
77
531
78
532
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
Tested-by: Alex Bennée <alex.bennee@linaro.org>
3
The Xunlong Orange Pi PC is an Allwinner H3 System on Chip
4
based embedded computer with mainline support in both U-Boot
5
and Linux. The board comes with a Quad Core Cortex A7 @ 1.3GHz,
6
1GiB RAM, 100Mbit ethernet, USB, SD/MMC, USB, HDMI and
7
various other I/O. This commit add support for the Xunlong
8
Orange Pi PC machine.
9
10
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
11
Tested-by: KONRAD Frederic <frederic.konrad@adacore.com>
12
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
14
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
Acked-by: Igor Mammedov <imammedo@redhat.com>
6
Message-id: 20200206105448.4726-26-richard.henderson@linaro.org
16
Message-id: 20200311221854.30370-3-nieklinnenbank@gmail.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
18
---
9
target/arm/cpu-qom.h | 1 +
19
hw/arm/Makefile.objs | 2 +-
10
target/arm/cpu.h | 11 +++++----
20
hw/arm/orangepi.c | 92 ++++++++++++++++++++++++++++++++++++++++++++
11
target/arm/cpu.c | 3 ++-
21
MAINTAINERS | 1 +
12
target/arm/helper.c | 56 ++++++++++++++++++++++++++++++++++++++++++++
22
3 files changed, 94 insertions(+), 1 deletion(-)
13
4 files changed, 65 insertions(+), 6 deletions(-)
23
create mode 100644 hw/arm/orangepi.c
14
24
15
diff --git a/target/arm/cpu-qom.h b/target/arm/cpu-qom.h
25
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
16
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu-qom.h
27
--- a/hw/arm/Makefile.objs
18
+++ b/target/arm/cpu-qom.h
28
+++ b/hw/arm/Makefile.objs
19
@@ -XXX,XX +XXX,XX @@ void arm_gt_ptimer_cb(void *opaque);
29
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_DIGIC) += digic.o
20
void arm_gt_vtimer_cb(void *opaque);
30
obj-$(CONFIG_OMAP) += omap1.o omap2.o
21
void arm_gt_htimer_cb(void *opaque);
31
obj-$(CONFIG_STRONGARM) += strongarm.o
22
void arm_gt_stimer_cb(void *opaque);
32
obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
23
+void arm_gt_hvtimer_cb(void *opaque);
33
-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3.o
24
34
+obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3.o orangepi.o
25
#define ARM_AFF0_SHIFT 0
35
obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
26
#define ARM_AFF0_MASK (0xFFULL << ARM_AFF0_SHIFT)
36
obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
27
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
37
obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o
28
index XXXXXXX..XXXXXXX 100644
38
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
29
--- a/target/arm/cpu.h
39
new file mode 100644
30
+++ b/target/arm/cpu.h
40
index XXXXXXX..XXXXXXX
31
@@ -XXX,XX +XXX,XX @@ typedef struct ARMGenericTimer {
41
--- /dev/null
32
uint64_t ctl; /* Timer Control register */
42
+++ b/hw/arm/orangepi.c
33
} ARMGenericTimer;
43
@@ -XXX,XX +XXX,XX @@
34
44
+/*
35
-#define GTIMER_PHYS 0
45
+ * Orange Pi emulation
36
-#define GTIMER_VIRT 1
46
+ *
37
-#define GTIMER_HYP 2
47
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
38
-#define GTIMER_SEC 3
48
+ *
39
-#define NUM_GTIMERS 4
49
+ * This program is free software: you can redistribute it and/or modify
40
+#define GTIMER_PHYS 0
50
+ * it under the terms of the GNU General Public License as published by
41
+#define GTIMER_VIRT 1
51
+ * the Free Software Foundation, either version 2 of the License, or
42
+#define GTIMER_HYP 2
52
+ * (at your option) any later version.
43
+#define GTIMER_SEC 3
53
+ *
44
+#define GTIMER_HYPVIRT 4
54
+ * This program is distributed in the hope that it will be useful,
45
+#define NUM_GTIMERS 5
55
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
46
56
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47
typedef struct {
57
+ * GNU General Public License for more details.
48
uint64_t raw_tcr;
58
+ *
49
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
59
+ * You should have received a copy of the GNU General Public License
50
index XXXXXXX..XXXXXXX 100644
60
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
51
--- a/target/arm/cpu.c
61
+ */
52
+++ b/target/arm/cpu.c
62
+
53
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
63
+#include "qemu/osdep.h"
54
}
64
+#include "qemu/units.h"
55
}
65
+#include "exec/address-spaces.h"
56
66
+#include "qapi/error.h"
57
-
67
+#include "cpu.h"
58
{
68
+#include "hw/sysbus.h"
59
uint64_t scale;
69
+#include "hw/boards.h"
60
70
+#include "hw/qdev-properties.h"
61
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
71
+#include "hw/arm/allwinner-h3.h"
62
arm_gt_htimer_cb, cpu);
72
+#include "sysemu/sysemu.h"
63
cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
73
+
64
arm_gt_stimer_cb, cpu);
74
+static struct arm_boot_info orangepi_binfo = {
65
+ cpu->gt_timer[GTIMER_HYPVIRT] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
75
+ .nb_cpus = AW_H3_NUM_CPUS,
66
+ arm_gt_hvtimer_cb, cpu);
76
+};
67
}
77
+
68
#endif
78
+static void orangepi_init(MachineState *machine)
69
70
diff --git a/target/arm/helper.c b/target/arm/helper.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/target/arm/helper.c
73
+++ b/target/arm/helper.c
74
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
75
76
switch (timeridx) {
77
case GTIMER_VIRT:
78
+ case GTIMER_HYPVIRT:
79
offset = gt_virt_cnt_offset(env);
80
break;
81
}
82
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
83
84
switch (timeridx) {
85
case GTIMER_VIRT:
86
+ case GTIMER_HYPVIRT:
87
offset = gt_virt_cnt_offset(env);
88
break;
89
}
90
@@ -XXX,XX +XXX,XX @@ static void gt_sec_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
91
gt_ctl_write(env, ri, GTIMER_SEC, value);
92
}
93
94
+static void gt_hv_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
95
+{
79
+{
96
+ gt_timer_reset(env, ri, GTIMER_HYPVIRT);
80
+ AwH3State *h3;
81
+
82
+ /* BIOS is not supported by this board */
83
+ if (bios_name) {
84
+ error_report("BIOS not supported for this machine");
85
+ exit(1);
86
+ }
87
+
88
+ /* This board has fixed size RAM */
89
+ if (machine->ram_size != 1 * GiB) {
90
+ error_report("This machine can only be used with 1GiB of RAM");
91
+ exit(1);
92
+ }
93
+
94
+ /* Only allow Cortex-A7 for this board */
95
+ if (strcmp(machine->cpu_type, ARM_CPU_TYPE_NAME("cortex-a7")) != 0) {
96
+ error_report("This board can only be used with cortex-a7 CPU");
97
+ exit(1);
98
+ }
99
+
100
+ h3 = AW_H3(object_new(TYPE_AW_H3));
101
+ object_property_add_child(OBJECT(machine), "soc", OBJECT(h3),
102
+ &error_abort);
103
+ object_unref(OBJECT(h3));
104
+
105
+ /* Setup timer properties */
106
+ object_property_set_int(OBJECT(h3), 32768, "clk0-freq",
107
+ &error_abort);
108
+ object_property_set_int(OBJECT(h3), 24 * 1000 * 1000, "clk1-freq",
109
+ &error_abort);
110
+
111
+ /* Mark H3 object realized */
112
+ object_property_set_bool(OBJECT(h3), true, "realized", &error_abort);
113
+
114
+ /* SDRAM */
115
+ memory_region_add_subregion(get_system_memory(), h3->memmap[AW_H3_SDRAM],
116
+ machine->ram);
117
+
118
+ orangepi_binfo.loader_start = h3->memmap[AW_H3_SDRAM];
119
+ orangepi_binfo.ram_size = machine->ram_size;
120
+ arm_load_kernel(ARM_CPU(first_cpu), machine, &orangepi_binfo);
97
+}
121
+}
98
+
122
+
99
+static void gt_hv_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
123
+static void orangepi_machine_init(MachineClass *mc)
100
+ uint64_t value)
101
+{
124
+{
102
+ gt_cval_write(env, ri, GTIMER_HYPVIRT, value);
125
+ mc->desc = "Orange Pi PC";
126
+ mc->init = orangepi_init;
127
+ mc->min_cpus = AW_H3_NUM_CPUS;
128
+ mc->max_cpus = AW_H3_NUM_CPUS;
129
+ mc->default_cpus = AW_H3_NUM_CPUS;
130
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a7");
131
+ mc->default_ram_size = 1 * GiB;
132
+ mc->default_ram_id = "orangepi.ram";
103
+}
133
+}
104
+
134
+
105
+static uint64_t gt_hv_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
135
+DEFINE_MACHINE("orangepi-pc", orangepi_machine_init)
106
+{
136
diff --git a/MAINTAINERS b/MAINTAINERS
107
+ return gt_tval_read(env, ri, GTIMER_HYPVIRT);
137
index XXXXXXX..XXXXXXX 100644
108
+}
138
--- a/MAINTAINERS
109
+
139
+++ b/MAINTAINERS
110
+static void gt_hv_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
140
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
111
+ uint64_t value)
141
S: Maintained
112
+{
142
F: hw/*/allwinner-h3*
113
+ gt_tval_write(env, ri, GTIMER_HYPVIRT, value);
143
F: include/hw/*/allwinner-h3*
114
+}
144
+F: hw/arm/orangepi.c
115
+
145
116
+static void gt_hv_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
146
ARM PrimeCell and CMSDK devices
117
+ uint64_t value)
147
M: Peter Maydell <peter.maydell@linaro.org>
118
+{
119
+ gt_ctl_write(env, ri, GTIMER_HYPVIRT, value);
120
+}
121
+
122
void arm_gt_ptimer_cb(void *opaque)
123
{
124
ARMCPU *cpu = opaque;
125
@@ -XXX,XX +XXX,XX @@ void arm_gt_stimer_cb(void *opaque)
126
gt_recalc_timer(cpu, GTIMER_SEC);
127
}
128
129
+void arm_gt_hvtimer_cb(void *opaque)
130
+{
131
+ ARMCPU *cpu = opaque;
132
+
133
+ gt_recalc_timer(cpu, GTIMER_HYPVIRT);
134
+}
135
+
136
static void arm_gt_cntfrq_reset(CPUARMState *env, const ARMCPRegInfo *opaque)
137
{
138
ARMCPU *cpu = env_archcpu(env);
139
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
140
.opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 1,
141
.access = PL2_RW, .writefn = vmsa_tcr_ttbr_el2_write,
142
.fieldoffset = offsetof(CPUARMState, cp15.ttbr1_el[2]) },
143
+#ifndef CONFIG_USER_ONLY
144
+ { .name = "CNTHV_CVAL_EL2", .state = ARM_CP_STATE_AA64,
145
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 3, .opc2 = 2,
146
+ .fieldoffset =
147
+ offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYPVIRT].cval),
148
+ .type = ARM_CP_IO, .access = PL2_RW,
149
+ .writefn = gt_hv_cval_write, .raw_writefn = raw_write },
150
+ { .name = "CNTHV_TVAL_EL2", .state = ARM_CP_STATE_BOTH,
151
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 3, .opc2 = 0,
152
+ .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL2_RW,
153
+ .resetfn = gt_hv_timer_reset,
154
+ .readfn = gt_hv_tval_read, .writefn = gt_hv_tval_write },
155
+ { .name = "CNTHV_CTL_EL2", .state = ARM_CP_STATE_BOTH,
156
+ .type = ARM_CP_IO,
157
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 3, .opc2 = 1,
158
+ .access = PL2_RW,
159
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYPVIRT].ctl),
160
+ .writefn = gt_hv_ctl_write, .raw_writefn = raw_write },
161
+#endif
162
REGINFO_SENTINEL
163
};
164
165
--
148
--
166
2.20.1
149
2.20.1
167
150
168
151
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
The virtual offset may be 0 depending on EL, E2H and TGE.
3
The Clock Control Unit is responsible for clock signal generation,
4
configuration and distribution in the Allwinner H3 System on Chip.
5
This commit adds support for the Clock Control Unit which emulates
6
a simple read/write register interface.
4
7
5
Tested-by: Alex Bennée <alex.bennee@linaro.org>
8
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Message-id: 20200206105448.4726-6-richard.henderson@linaro.org
12
Message-id: 20200311221854.30370-4-nieklinnenbank@gmail.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
14
---
11
target/arm/helper.c | 40 +++++++++++++++++++++++++++++++++++++---
15
hw/misc/Makefile.objs | 1 +
12
1 file changed, 37 insertions(+), 3 deletions(-)
16
include/hw/arm/allwinner-h3.h | 3 +
17
include/hw/misc/allwinner-h3-ccu.h | 66 ++++++++
18
hw/arm/allwinner-h3.c | 9 +-
19
hw/misc/allwinner-h3-ccu.c | 242 +++++++++++++++++++++++++++++
20
5 files changed, 320 insertions(+), 1 deletion(-)
21
create mode 100644 include/hw/misc/allwinner-h3-ccu.h
22
create mode 100644 hw/misc/allwinner-h3-ccu.c
13
23
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
24
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
15
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
26
--- a/hw/misc/Makefile.objs
17
+++ b/target/arm/helper.c
27
+++ b/hw/misc/Makefile.objs
18
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
28
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_MACIO) += macio/
19
return gt_get_countervalue(env);
29
30
common-obj-$(CONFIG_IVSHMEM_DEVICE) += ivshmem.o
31
32
+common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-ccu.o
33
common-obj-$(CONFIG_REALVIEW) += arm_sysctl.o
34
common-obj-$(CONFIG_NSERIES) += cbus.o
35
common-obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
36
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/hw/arm/allwinner-h3.h
39
+++ b/include/hw/arm/allwinner-h3.h
40
@@ -XXX,XX +XXX,XX @@
41
#include "hw/arm/boot.h"
42
#include "hw/timer/allwinner-a10-pit.h"
43
#include "hw/intc/arm_gic.h"
44
+#include "hw/misc/allwinner-h3-ccu.h"
45
#include "target/arm/cpu.h"
46
47
/**
48
@@ -XXX,XX +XXX,XX @@ enum {
49
AW_H3_SRAM_A1,
50
AW_H3_SRAM_A2,
51
AW_H3_SRAM_C,
52
+ AW_H3_CCU,
53
AW_H3_PIT,
54
AW_H3_UART0,
55
AW_H3_UART1,
56
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
57
ARMCPU cpus[AW_H3_NUM_CPUS];
58
const hwaddr *memmap;
59
AwA10PITState timer;
60
+ AwH3ClockCtlState ccu;
61
GICState gic;
62
MemoryRegion sram_a1;
63
MemoryRegion sram_a2;
64
diff --git a/include/hw/misc/allwinner-h3-ccu.h b/include/hw/misc/allwinner-h3-ccu.h
65
new file mode 100644
66
index XXXXXXX..XXXXXXX
67
--- /dev/null
68
+++ b/include/hw/misc/allwinner-h3-ccu.h
69
@@ -XXX,XX +XXX,XX @@
70
+/*
71
+ * Allwinner H3 Clock Control Unit emulation
72
+ *
73
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
74
+ *
75
+ * This program is free software: you can redistribute it and/or modify
76
+ * it under the terms of the GNU General Public License as published by
77
+ * the Free Software Foundation, either version 2 of the License, or
78
+ * (at your option) any later version.
79
+ *
80
+ * This program is distributed in the hope that it will be useful,
81
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
82
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
83
+ * GNU General Public License for more details.
84
+ *
85
+ * You should have received a copy of the GNU General Public License
86
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
87
+ */
88
+
89
+#ifndef HW_MISC_ALLWINNER_H3_CCU_H
90
+#define HW_MISC_ALLWINNER_H3_CCU_H
91
+
92
+#include "qom/object.h"
93
+#include "hw/sysbus.h"
94
+
95
+/**
96
+ * @name Constants
97
+ * @{
98
+ */
99
+
100
+/** Size of register I/O address space used by CCU device */
101
+#define AW_H3_CCU_IOSIZE (0x400)
102
+
103
+/** Total number of known registers */
104
+#define AW_H3_CCU_REGS_NUM (AW_H3_CCU_IOSIZE / sizeof(uint32_t))
105
+
106
+/** @} */
107
+
108
+/**
109
+ * @name Object model
110
+ * @{
111
+ */
112
+
113
+#define TYPE_AW_H3_CCU "allwinner-h3-ccu"
114
+#define AW_H3_CCU(obj) \
115
+ OBJECT_CHECK(AwH3ClockCtlState, (obj), TYPE_AW_H3_CCU)
116
+
117
+/** @} */
118
+
119
+/**
120
+ * Allwinner H3 CCU object instance state.
121
+ */
122
+typedef struct AwH3ClockCtlState {
123
+ /*< private >*/
124
+ SysBusDevice parent_obj;
125
+ /*< public >*/
126
+
127
+ /** Maps I/O registers in physical memory */
128
+ MemoryRegion iomem;
129
+
130
+ /** Array of hardware registers */
131
+ uint32_t regs[AW_H3_CCU_REGS_NUM];
132
+
133
+} AwH3ClockCtlState;
134
+
135
+#endif /* HW_MISC_ALLWINNER_H3_CCU_H */
136
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
137
index XXXXXXX..XXXXXXX 100644
138
--- a/hw/arm/allwinner-h3.c
139
+++ b/hw/arm/allwinner-h3.c
140
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
141
[AW_H3_SRAM_A1] = 0x00000000,
142
[AW_H3_SRAM_A2] = 0x00044000,
143
[AW_H3_SRAM_C] = 0x00010000,
144
+ [AW_H3_CCU] = 0x01c20000,
145
[AW_H3_PIT] = 0x01c20c00,
146
[AW_H3_UART0] = 0x01c28000,
147
[AW_H3_UART1] = 0x01c28400,
148
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
149
{ "usb2-phy", 0x01c1c000, 4 * KiB },
150
{ "usb3-phy", 0x01c1d000, 4 * KiB },
151
{ "smc", 0x01c1e000, 4 * KiB },
152
- { "ccu", 0x01c20000, 1 * KiB },
153
{ "pio", 0x01c20800, 1 * KiB },
154
{ "owa", 0x01c21000, 1 * KiB },
155
{ "pwm", 0x01c21400, 1 * KiB },
156
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
157
"clk0-freq", &error_abort);
158
object_property_add_alias(obj, "clk1-freq", OBJECT(&s->timer),
159
"clk1-freq", &error_abort);
160
+
161
+ sysbus_init_child_obj(obj, "ccu", &s->ccu, sizeof(s->ccu),
162
+ TYPE_AW_H3_CCU);
20
}
163
}
21
164
22
+static uint64_t gt_virt_cnt_offset(CPUARMState *env)
165
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
23
+{
166
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
24
+ uint64_t hcr;
167
memory_region_add_subregion(get_system_memory(), s->memmap[AW_H3_SRAM_C],
25
+
168
&s->sram_c);
26
+ switch (arm_current_el(env)) {
169
27
+ case 2:
170
+ /* Clock Control Unit */
28
+ hcr = arm_hcr_el2_eff(env);
171
+ qdev_init_nofail(DEVICE(&s->ccu));
29
+ if (hcr & HCR_E2H) {
172
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccu), 0, s->memmap[AW_H3_CCU]);
30
+ return 0;
173
+
174
/* UART0. For future clocktree API: All UARTS are connected to APB2_CLK. */
175
serial_mm_init(get_system_memory(), s->memmap[AW_H3_UART0], 2,
176
qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART0),
177
diff --git a/hw/misc/allwinner-h3-ccu.c b/hw/misc/allwinner-h3-ccu.c
178
new file mode 100644
179
index XXXXXXX..XXXXXXX
180
--- /dev/null
181
+++ b/hw/misc/allwinner-h3-ccu.c
182
@@ -XXX,XX +XXX,XX @@
183
+/*
184
+ * Allwinner H3 Clock Control Unit emulation
185
+ *
186
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
187
+ *
188
+ * This program is free software: you can redistribute it and/or modify
189
+ * it under the terms of the GNU General Public License as published by
190
+ * the Free Software Foundation, either version 2 of the License, or
191
+ * (at your option) any later version.
192
+ *
193
+ * This program is distributed in the hope that it will be useful,
194
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
195
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
196
+ * GNU General Public License for more details.
197
+ *
198
+ * You should have received a copy of the GNU General Public License
199
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
200
+ */
201
+
202
+#include "qemu/osdep.h"
203
+#include "qemu/units.h"
204
+#include "hw/sysbus.h"
205
+#include "migration/vmstate.h"
206
+#include "qemu/log.h"
207
+#include "qemu/module.h"
208
+#include "hw/misc/allwinner-h3-ccu.h"
209
+
210
+/* CCU register offsets */
211
+enum {
212
+ REG_PLL_CPUX = 0x0000, /* PLL CPUX Control */
213
+ REG_PLL_AUDIO = 0x0008, /* PLL Audio Control */
214
+ REG_PLL_VIDEO = 0x0010, /* PLL Video Control */
215
+ REG_PLL_VE = 0x0018, /* PLL VE Control */
216
+ REG_PLL_DDR = 0x0020, /* PLL DDR Control */
217
+ REG_PLL_PERIPH0 = 0x0028, /* PLL Peripherals 0 Control */
218
+ REG_PLL_GPU = 0x0038, /* PLL GPU Control */
219
+ REG_PLL_PERIPH1 = 0x0044, /* PLL Peripherals 1 Control */
220
+ REG_PLL_DE = 0x0048, /* PLL Display Engine Control */
221
+ REG_CPUX_AXI = 0x0050, /* CPUX/AXI Configuration */
222
+ REG_APB1 = 0x0054, /* ARM Peripheral Bus 1 Config */
223
+ REG_APB2 = 0x0058, /* ARM Peripheral Bus 2 Config */
224
+ REG_DRAM_CFG = 0x00F4, /* DRAM Configuration */
225
+ REG_MBUS = 0x00FC, /* MBUS Reset */
226
+ REG_PLL_TIME0 = 0x0200, /* PLL Stable Time 0 */
227
+ REG_PLL_TIME1 = 0x0204, /* PLL Stable Time 1 */
228
+ REG_PLL_CPUX_BIAS = 0x0220, /* PLL CPUX Bias */
229
+ REG_PLL_AUDIO_BIAS = 0x0224, /* PLL Audio Bias */
230
+ REG_PLL_VIDEO_BIAS = 0x0228, /* PLL Video Bias */
231
+ REG_PLL_VE_BIAS = 0x022C, /* PLL VE Bias */
232
+ REG_PLL_DDR_BIAS = 0x0230, /* PLL DDR Bias */
233
+ REG_PLL_PERIPH0_BIAS = 0x0234, /* PLL Peripherals 0 Bias */
234
+ REG_PLL_GPU_BIAS = 0x023C, /* PLL GPU Bias */
235
+ REG_PLL_PERIPH1_BIAS = 0x0244, /* PLL Peripherals 1 Bias */
236
+ REG_PLL_DE_BIAS = 0x0248, /* PLL Display Engine Bias */
237
+ REG_PLL_CPUX_TUNING = 0x0250, /* PLL CPUX Tuning */
238
+ REG_PLL_DDR_TUNING = 0x0260, /* PLL DDR Tuning */
239
+};
240
+
241
+#define REG_INDEX(offset) (offset / sizeof(uint32_t))
242
+
243
+/* CCU register flags */
244
+enum {
245
+ REG_DRAM_CFG_UPDATE = (1 << 16),
246
+};
247
+
248
+enum {
249
+ REG_PLL_ENABLE = (1 << 31),
250
+ REG_PLL_LOCK = (1 << 28),
251
+};
252
+
253
+
254
+/* CCU register reset values */
255
+enum {
256
+ REG_PLL_CPUX_RST = 0x00001000,
257
+ REG_PLL_AUDIO_RST = 0x00035514,
258
+ REG_PLL_VIDEO_RST = 0x03006207,
259
+ REG_PLL_VE_RST = 0x03006207,
260
+ REG_PLL_DDR_RST = 0x00001000,
261
+ REG_PLL_PERIPH0_RST = 0x00041811,
262
+ REG_PLL_GPU_RST = 0x03006207,
263
+ REG_PLL_PERIPH1_RST = 0x00041811,
264
+ REG_PLL_DE_RST = 0x03006207,
265
+ REG_CPUX_AXI_RST = 0x00010000,
266
+ REG_APB1_RST = 0x00001010,
267
+ REG_APB2_RST = 0x01000000,
268
+ REG_DRAM_CFG_RST = 0x00000000,
269
+ REG_MBUS_RST = 0x80000000,
270
+ REG_PLL_TIME0_RST = 0x000000FF,
271
+ REG_PLL_TIME1_RST = 0x000000FF,
272
+ REG_PLL_CPUX_BIAS_RST = 0x08100200,
273
+ REG_PLL_AUDIO_BIAS_RST = 0x10100000,
274
+ REG_PLL_VIDEO_BIAS_RST = 0x10100000,
275
+ REG_PLL_VE_BIAS_RST = 0x10100000,
276
+ REG_PLL_DDR_BIAS_RST = 0x81104000,
277
+ REG_PLL_PERIPH0_BIAS_RST = 0x10100010,
278
+ REG_PLL_GPU_BIAS_RST = 0x10100000,
279
+ REG_PLL_PERIPH1_BIAS_RST = 0x10100010,
280
+ REG_PLL_DE_BIAS_RST = 0x10100000,
281
+ REG_PLL_CPUX_TUNING_RST = 0x0A101000,
282
+ REG_PLL_DDR_TUNING_RST = 0x14880000,
283
+};
284
+
285
+static uint64_t allwinner_h3_ccu_read(void *opaque, hwaddr offset,
286
+ unsigned size)
287
+{
288
+ const AwH3ClockCtlState *s = AW_H3_CCU(opaque);
289
+ const uint32_t idx = REG_INDEX(offset);
290
+
291
+ switch (offset) {
292
+ case 0x308 ... AW_H3_CCU_IOSIZE:
293
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
294
+ __func__, (uint32_t)offset);
295
+ return 0;
296
+ }
297
+
298
+ return s->regs[idx];
299
+}
300
+
301
+static void allwinner_h3_ccu_write(void *opaque, hwaddr offset,
302
+ uint64_t val, unsigned size)
303
+{
304
+ AwH3ClockCtlState *s = AW_H3_CCU(opaque);
305
+ const uint32_t idx = REG_INDEX(offset);
306
+
307
+ switch (offset) {
308
+ case REG_DRAM_CFG: /* DRAM Configuration */
309
+ val &= ~REG_DRAM_CFG_UPDATE;
310
+ break;
311
+ case REG_PLL_CPUX: /* PLL CPUX Control */
312
+ case REG_PLL_AUDIO: /* PLL Audio Control */
313
+ case REG_PLL_VIDEO: /* PLL Video Control */
314
+ case REG_PLL_VE: /* PLL VE Control */
315
+ case REG_PLL_DDR: /* PLL DDR Control */
316
+ case REG_PLL_PERIPH0: /* PLL Peripherals 0 Control */
317
+ case REG_PLL_GPU: /* PLL GPU Control */
318
+ case REG_PLL_PERIPH1: /* PLL Peripherals 1 Control */
319
+ case REG_PLL_DE: /* PLL Display Engine Control */
320
+ if (val & REG_PLL_ENABLE) {
321
+ val |= REG_PLL_LOCK;
31
+ }
322
+ }
32
+ break;
323
+ break;
33
+ case 0:
324
+ case 0x308 ... AW_H3_CCU_IOSIZE:
34
+ hcr = arm_hcr_el2_eff(env);
325
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
35
+ if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
326
+ __func__, (uint32_t)offset);
36
+ return 0;
327
+ break;
37
+ }
328
+ default:
329
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented write offset 0x%04x\n",
330
+ __func__, (uint32_t)offset);
38
+ break;
331
+ break;
39
+ }
332
+ }
40
+
333
+
41
+ return env->cp15.cntvoff_el2;
334
+ s->regs[idx] = (uint32_t) val;
42
+}
335
+}
43
+
336
+
44
static uint64_t gt_virt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
337
+static const MemoryRegionOps allwinner_h3_ccu_ops = {
45
{
338
+ .read = allwinner_h3_ccu_read,
46
- return gt_get_countervalue(env) - env->cp15.cntvoff_el2;
339
+ .write = allwinner_h3_ccu_write,
47
+ return gt_get_countervalue(env) - gt_virt_cnt_offset(env);
340
+ .endianness = DEVICE_NATIVE_ENDIAN,
48
}
341
+ .valid = {
49
342
+ .min_access_size = 4,
50
static void gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
343
+ .max_access_size = 4,
51
@@ -XXX,XX +XXX,XX @@ static void gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
344
+ },
52
static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
345
+ .impl.min_access_size = 4,
53
int timeridx)
346
+};
54
{
347
+
55
- uint64_t offset = timeridx == GTIMER_VIRT ? env->cp15.cntvoff_el2 : 0;
348
+static void allwinner_h3_ccu_reset(DeviceState *dev)
56
+ uint64_t offset = 0;
349
+{
57
+
350
+ AwH3ClockCtlState *s = AW_H3_CCU(dev);
58
+ switch (timeridx) {
351
+
59
+ case GTIMER_VIRT:
352
+ /* Set default values for registers */
60
+ offset = gt_virt_cnt_offset(env);
353
+ s->regs[REG_INDEX(REG_PLL_CPUX)] = REG_PLL_CPUX_RST;
61
+ break;
354
+ s->regs[REG_INDEX(REG_PLL_AUDIO)] = REG_PLL_AUDIO_RST;
355
+ s->regs[REG_INDEX(REG_PLL_VIDEO)] = REG_PLL_VIDEO_RST;
356
+ s->regs[REG_INDEX(REG_PLL_VE)] = REG_PLL_VE_RST;
357
+ s->regs[REG_INDEX(REG_PLL_DDR)] = REG_PLL_DDR_RST;
358
+ s->regs[REG_INDEX(REG_PLL_PERIPH0)] = REG_PLL_PERIPH0_RST;
359
+ s->regs[REG_INDEX(REG_PLL_GPU)] = REG_PLL_GPU_RST;
360
+ s->regs[REG_INDEX(REG_PLL_PERIPH1)] = REG_PLL_PERIPH1_RST;
361
+ s->regs[REG_INDEX(REG_PLL_DE)] = REG_PLL_DE_RST;
362
+ s->regs[REG_INDEX(REG_CPUX_AXI)] = REG_CPUX_AXI_RST;
363
+ s->regs[REG_INDEX(REG_APB1)] = REG_APB1_RST;
364
+ s->regs[REG_INDEX(REG_APB2)] = REG_APB2_RST;
365
+ s->regs[REG_INDEX(REG_DRAM_CFG)] = REG_DRAM_CFG_RST;
366
+ s->regs[REG_INDEX(REG_MBUS)] = REG_MBUS_RST;
367
+ s->regs[REG_INDEX(REG_PLL_TIME0)] = REG_PLL_TIME0_RST;
368
+ s->regs[REG_INDEX(REG_PLL_TIME1)] = REG_PLL_TIME1_RST;
369
+ s->regs[REG_INDEX(REG_PLL_CPUX_BIAS)] = REG_PLL_CPUX_BIAS_RST;
370
+ s->regs[REG_INDEX(REG_PLL_AUDIO_BIAS)] = REG_PLL_AUDIO_BIAS_RST;
371
+ s->regs[REG_INDEX(REG_PLL_VIDEO_BIAS)] = REG_PLL_VIDEO_BIAS_RST;
372
+ s->regs[REG_INDEX(REG_PLL_VE_BIAS)] = REG_PLL_VE_BIAS_RST;
373
+ s->regs[REG_INDEX(REG_PLL_DDR_BIAS)] = REG_PLL_DDR_BIAS_RST;
374
+ s->regs[REG_INDEX(REG_PLL_PERIPH0_BIAS)] = REG_PLL_PERIPH0_BIAS_RST;
375
+ s->regs[REG_INDEX(REG_PLL_GPU_BIAS)] = REG_PLL_GPU_BIAS_RST;
376
+ s->regs[REG_INDEX(REG_PLL_PERIPH1_BIAS)] = REG_PLL_PERIPH1_BIAS_RST;
377
+ s->regs[REG_INDEX(REG_PLL_DE_BIAS)] = REG_PLL_DE_BIAS_RST;
378
+ s->regs[REG_INDEX(REG_PLL_CPUX_TUNING)] = REG_PLL_CPUX_TUNING_RST;
379
+ s->regs[REG_INDEX(REG_PLL_DDR_TUNING)] = REG_PLL_DDR_TUNING_RST;
380
+}
381
+
382
+static void allwinner_h3_ccu_init(Object *obj)
383
+{
384
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
385
+ AwH3ClockCtlState *s = AW_H3_CCU(obj);
386
+
387
+ /* Memory mapping */
388
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_h3_ccu_ops, s,
389
+ TYPE_AW_H3_CCU, AW_H3_CCU_IOSIZE);
390
+ sysbus_init_mmio(sbd, &s->iomem);
391
+}
392
+
393
+static const VMStateDescription allwinner_h3_ccu_vmstate = {
394
+ .name = "allwinner-h3-ccu",
395
+ .version_id = 1,
396
+ .minimum_version_id = 1,
397
+ .fields = (VMStateField[]) {
398
+ VMSTATE_UINT32_ARRAY(regs, AwH3ClockCtlState, AW_H3_CCU_REGS_NUM),
399
+ VMSTATE_END_OF_LIST()
62
+ }
400
+ }
63
401
+};
64
return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
402
+
65
(gt_get_countervalue(env) - offset));
403
+static void allwinner_h3_ccu_class_init(ObjectClass *klass, void *data)
66
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
404
+{
67
int timeridx,
405
+ DeviceClass *dc = DEVICE_CLASS(klass);
68
uint64_t value)
406
+
69
{
407
+ dc->reset = allwinner_h3_ccu_reset;
70
- uint64_t offset = timeridx == GTIMER_VIRT ? env->cp15.cntvoff_el2 : 0;
408
+ dc->vmsd = &allwinner_h3_ccu_vmstate;
71
+ uint64_t offset = 0;
409
+}
72
+
410
+
73
+ switch (timeridx) {
411
+static const TypeInfo allwinner_h3_ccu_info = {
74
+ case GTIMER_VIRT:
412
+ .name = TYPE_AW_H3_CCU,
75
+ offset = gt_virt_cnt_offset(env);
413
+ .parent = TYPE_SYS_BUS_DEVICE,
76
+ break;
414
+ .instance_init = allwinner_h3_ccu_init,
77
+ }
415
+ .instance_size = sizeof(AwH3ClockCtlState),
78
416
+ .class_init = allwinner_h3_ccu_class_init,
79
trace_arm_gt_tval_write(timeridx, value);
417
+};
80
env->cp15.c14_timer[timeridx].cval = gt_get_countervalue(env) - offset +
418
+
419
+static void allwinner_h3_ccu_register(void)
420
+{
421
+ type_register_static(&allwinner_h3_ccu_info);
422
+}
423
+
424
+type_init(allwinner_h3_ccu_register)
81
--
425
--
82
2.20.1
426
2.20.1
83
427
84
428
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
No functional change, but unify code sequences.
3
The Allwinner H3 System on Chip contains multiple USB 2.0 bus
4
connections which provide software access using the Enhanced
5
Host Controller Interface (EHCI) and Open Host Controller
6
Interface (OHCI) interfaces. This commit adds support for
7
both interfaces in the Allwinner H3 System on Chip.
4
8
5
Tested-by: Alex Bennée <alex.bennee@linaro.org>
9
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
10
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 20200206105448.4726-8-richard.henderson@linaro.org
14
Message-id: 20200311221854.30370-5-nieklinnenbank@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
16
---
12
target/arm/helper.c | 86 +++++++++++++--------------------------------
17
hw/usb/hcd-ehci.h | 1 +
13
1 file changed, 24 insertions(+), 62 deletions(-)
18
include/hw/arm/allwinner-h3.h | 8 +++++++
19
hw/arm/allwinner-h3.c | 44 +++++++++++++++++++++++++++++++++++
20
hw/usb/hcd-ehci-sysbus.c | 17 ++++++++++++++
21
hw/arm/Kconfig | 2 ++
22
5 files changed, 72 insertions(+)
14
23
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
24
diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
16
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
26
--- a/hw/usb/hcd-ehci.h
18
+++ b/target/arm/helper.c
27
+++ b/hw/usb/hcd-ehci.h
19
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vmalle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
28
@@ -XXX,XX +XXX,XX @@ typedef struct EHCIPCIState {
20
tlb_flush_by_mmuidx(cs, mask);
29
#define TYPE_SYS_BUS_EHCI "sysbus-ehci-usb"
21
}
30
#define TYPE_PLATFORM_EHCI "platform-ehci-usb"
22
31
#define TYPE_EXYNOS4210_EHCI "exynos4210-ehci-usb"
23
-static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
32
+#define TYPE_AW_H3_EHCI "aw-h3-ehci-usb"
24
- uint64_t value)
33
#define TYPE_TEGRA2_EHCI "tegra2-ehci-usb"
25
+static int alle1_tlbmask(CPUARMState *env)
34
#define TYPE_PPC4xx_EHCI "ppc4xx-ehci-usb"
26
{
35
#define TYPE_FUSBH200_EHCI "fusbh200-ehci-usb"
27
- /* Note that the 'ALL' scope must invalidate both stage 1 and
36
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
28
+ /*
37
index XXXXXXX..XXXXXXX 100644
29
+ * Note that the 'ALL' scope must invalidate both stage 1 and
38
--- a/include/hw/arm/allwinner-h3.h
30
* stage 2 translations, whereas most other scopes only invalidate
39
+++ b/include/hw/arm/allwinner-h3.h
31
* stage 1 translations.
40
@@ -XXX,XX +XXX,XX @@ enum {
32
*/
41
AW_H3_SRAM_A1,
33
- ARMCPU *cpu = env_archcpu(env);
42
AW_H3_SRAM_A2,
34
- CPUState *cs = CPU(cpu);
43
AW_H3_SRAM_C,
35
-
44
+ AW_H3_EHCI0,
36
if (arm_is_secure_below_el3(env)) {
45
+ AW_H3_OHCI0,
37
- tlb_flush_by_mmuidx(cs,
46
+ AW_H3_EHCI1,
38
- ARMMMUIdxBit_S1SE1 |
47
+ AW_H3_OHCI1,
39
- ARMMMUIdxBit_S1SE0);
48
+ AW_H3_EHCI2,
40
+ return ARMMMUIdxBit_S1SE1 | ARMMMUIdxBit_S1SE0;
49
+ AW_H3_OHCI2,
41
+ } else if (arm_feature(env, ARM_FEATURE_EL2)) {
50
+ AW_H3_EHCI3,
42
+ return ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0 | ARMMMUIdxBit_S2NS;
51
+ AW_H3_OHCI3,
43
} else {
52
AW_H3_CCU,
44
- if (arm_feature(env, ARM_FEATURE_EL2)) {
53
AW_H3_PIT,
45
- tlb_flush_by_mmuidx(cs,
54
AW_H3_UART0,
46
- ARMMMUIdxBit_S12NSE1 |
55
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
47
- ARMMMUIdxBit_S12NSE0 |
56
index XXXXXXX..XXXXXXX 100644
48
- ARMMMUIdxBit_S2NS);
57
--- a/hw/arm/allwinner-h3.c
49
- } else {
58
+++ b/hw/arm/allwinner-h3.c
50
- tlb_flush_by_mmuidx(cs,
59
@@ -XXX,XX +XXX,XX @@
51
- ARMMMUIdxBit_S12NSE1 |
60
#include "hw/sysbus.h"
52
- ARMMMUIdxBit_S12NSE0);
61
#include "hw/char/serial.h"
53
- }
62
#include "hw/misc/unimp.h"
54
+ return ARMMMUIdxBit_S12NSE1 | ARMMMUIdxBit_S12NSE0;
63
+#include "hw/usb/hcd-ehci.h"
55
}
64
#include "sysemu/sysemu.h"
56
}
65
#include "hw/arm/allwinner-h3.h"
57
66
58
+static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
67
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
59
+ uint64_t value)
68
[AW_H3_SRAM_A1] = 0x00000000,
69
[AW_H3_SRAM_A2] = 0x00044000,
70
[AW_H3_SRAM_C] = 0x00010000,
71
+ [AW_H3_EHCI0] = 0x01c1a000,
72
+ [AW_H3_OHCI0] = 0x01c1a400,
73
+ [AW_H3_EHCI1] = 0x01c1b000,
74
+ [AW_H3_OHCI1] = 0x01c1b400,
75
+ [AW_H3_EHCI2] = 0x01c1c000,
76
+ [AW_H3_OHCI2] = 0x01c1c400,
77
+ [AW_H3_EHCI3] = 0x01c1d000,
78
+ [AW_H3_OHCI3] = 0x01c1d400,
79
[AW_H3_CCU] = 0x01c20000,
80
[AW_H3_PIT] = 0x01c20c00,
81
[AW_H3_UART0] = 0x01c28000,
82
@@ -XXX,XX +XXX,XX @@ enum {
83
AW_H3_GIC_SPI_UART3 = 3,
84
AW_H3_GIC_SPI_TIMER0 = 18,
85
AW_H3_GIC_SPI_TIMER1 = 19,
86
+ AW_H3_GIC_SPI_EHCI0 = 72,
87
+ AW_H3_GIC_SPI_OHCI0 = 73,
88
+ AW_H3_GIC_SPI_EHCI1 = 74,
89
+ AW_H3_GIC_SPI_OHCI1 = 75,
90
+ AW_H3_GIC_SPI_EHCI2 = 76,
91
+ AW_H3_GIC_SPI_OHCI2 = 77,
92
+ AW_H3_GIC_SPI_EHCI3 = 78,
93
+ AW_H3_GIC_SPI_OHCI3 = 79,
94
};
95
96
/* Allwinner H3 general constants */
97
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
98
qdev_init_nofail(DEVICE(&s->ccu));
99
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccu), 0, s->memmap[AW_H3_CCU]);
100
101
+ /* Universal Serial Bus */
102
+ sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI0],
103
+ qdev_get_gpio_in(DEVICE(&s->gic),
104
+ AW_H3_GIC_SPI_EHCI0));
105
+ sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI1],
106
+ qdev_get_gpio_in(DEVICE(&s->gic),
107
+ AW_H3_GIC_SPI_EHCI1));
108
+ sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI2],
109
+ qdev_get_gpio_in(DEVICE(&s->gic),
110
+ AW_H3_GIC_SPI_EHCI2));
111
+ sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI3],
112
+ qdev_get_gpio_in(DEVICE(&s->gic),
113
+ AW_H3_GIC_SPI_EHCI3));
114
+
115
+ sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_OHCI0],
116
+ qdev_get_gpio_in(DEVICE(&s->gic),
117
+ AW_H3_GIC_SPI_OHCI0));
118
+ sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_OHCI1],
119
+ qdev_get_gpio_in(DEVICE(&s->gic),
120
+ AW_H3_GIC_SPI_OHCI1));
121
+ sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_OHCI2],
122
+ qdev_get_gpio_in(DEVICE(&s->gic),
123
+ AW_H3_GIC_SPI_OHCI2));
124
+ sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_OHCI3],
125
+ qdev_get_gpio_in(DEVICE(&s->gic),
126
+ AW_H3_GIC_SPI_OHCI3));
127
+
128
/* UART0. For future clocktree API: All UARTS are connected to APB2_CLK. */
129
serial_mm_init(get_system_memory(), s->memmap[AW_H3_UART0], 2,
130
qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART0),
131
diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c
132
index XXXXXXX..XXXXXXX 100644
133
--- a/hw/usb/hcd-ehci-sysbus.c
134
+++ b/hw/usb/hcd-ehci-sysbus.c
135
@@ -XXX,XX +XXX,XX @@ static const TypeInfo ehci_exynos4210_type_info = {
136
.class_init = ehci_exynos4210_class_init,
137
};
138
139
+static void ehci_aw_h3_class_init(ObjectClass *oc, void *data)
60
+{
140
+{
61
+ CPUState *cs = env_cpu(env);
141
+ SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
62
+ int mask = alle1_tlbmask(env);
142
+ DeviceClass *dc = DEVICE_CLASS(oc);
63
+
143
+
64
+ tlb_flush_by_mmuidx(cs, mask);
144
+ sec->capsbase = 0x0;
145
+ sec->opregbase = 0x10;
146
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
65
+}
147
+}
66
+
148
+
67
static void tlbi_aa64_alle2_write(CPUARMState *env, const ARMCPRegInfo *ri,
149
+static const TypeInfo ehci_aw_h3_type_info = {
68
uint64_t value)
150
+ .name = TYPE_AW_H3_EHCI,
151
+ .parent = TYPE_SYS_BUS_EHCI,
152
+ .class_init = ehci_aw_h3_class_init,
153
+};
154
+
155
static void ehci_tegra2_class_init(ObjectClass *oc, void *data)
69
{
156
{
70
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_alle3_write(CPUARMState *env, const ARMCPRegInfo *ri,
157
SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
71
static void tlbi_aa64_alle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
158
@@ -XXX,XX +XXX,XX @@ static void ehci_sysbus_register_types(void)
72
uint64_t value)
159
type_register_static(&ehci_type_info);
73
{
160
type_register_static(&ehci_platform_type_info);
74
- /* Note that the 'ALL' scope must invalidate both stage 1 and
161
type_register_static(&ehci_exynos4210_type_info);
75
- * stage 2 translations, whereas most other scopes only invalidate
162
+ type_register_static(&ehci_aw_h3_type_info);
76
- * stage 1 translations.
163
type_register_static(&ehci_tegra2_type_info);
77
- */
164
type_register_static(&ehci_ppc4xx_type_info);
78
CPUState *cs = env_cpu(env);
165
type_register_static(&ehci_fusbh200_type_info);
79
- bool sec = arm_is_secure_below_el3(env);
166
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
80
- bool has_el2 = arm_feature(env, ARM_FEATURE_EL2);
167
index XXXXXXX..XXXXXXX 100644
81
+ int mask = alle1_tlbmask(env);
168
--- a/hw/arm/Kconfig
82
169
+++ b/hw/arm/Kconfig
83
- if (sec) {
170
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_H3
84
- tlb_flush_by_mmuidx_all_cpus_synced(cs,
171
select ARM_TIMER
85
- ARMMMUIdxBit_S1SE1 |
172
select ARM_GIC
86
- ARMMMUIdxBit_S1SE0);
173
select UNIMP
87
- } else if (has_el2) {
174
+ select USB_OHCI
88
- tlb_flush_by_mmuidx_all_cpus_synced(cs,
175
+ select USB_EHCI_SYSBUS
89
- ARMMMUIdxBit_S12NSE1 |
176
90
- ARMMMUIdxBit_S12NSE0 |
177
config RASPI
91
- ARMMMUIdxBit_S2NS);
178
bool
92
- } else {
93
- tlb_flush_by_mmuidx_all_cpus_synced(cs,
94
- ARMMMUIdxBit_S12NSE1 |
95
- ARMMMUIdxBit_S12NSE0);
96
- }
97
+ tlb_flush_by_mmuidx_all_cpus_synced(cs, mask);
98
}
99
100
static void tlbi_aa64_alle2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
101
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae3_write(CPUARMState *env, const ARMCPRegInfo *ri,
102
static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
103
uint64_t value)
104
{
105
- ARMCPU *cpu = env_archcpu(env);
106
- CPUState *cs = CPU(cpu);
107
- bool sec = arm_is_secure_below_el3(env);
108
+ CPUState *cs = env_cpu(env);
109
+ int mask = vae1_tlbmask(env);
110
uint64_t pageaddr = sextract64(value << 12, 0, 56);
111
112
- if (sec) {
113
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
114
- ARMMMUIdxBit_S1SE1 |
115
- ARMMMUIdxBit_S1SE0);
116
- } else {
117
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
118
- ARMMMUIdxBit_S12NSE1 |
119
- ARMMMUIdxBit_S12NSE0);
120
- }
121
+ tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
122
}
123
124
static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
125
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
126
* since we don't support flush-for-specific-ASID-only or
127
* flush-last-level-only.
128
*/
129
- ARMCPU *cpu = env_archcpu(env);
130
- CPUState *cs = CPU(cpu);
131
+ CPUState *cs = env_cpu(env);
132
+ int mask = vae1_tlbmask(env);
133
uint64_t pageaddr = sextract64(value << 12, 0, 56);
134
135
if (tlb_force_broadcast(env)) {
136
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
137
return;
138
}
139
140
- if (arm_is_secure_below_el3(env)) {
141
- tlb_flush_page_by_mmuidx(cs, pageaddr,
142
- ARMMMUIdxBit_S1SE1 |
143
- ARMMMUIdxBit_S1SE0);
144
- } else {
145
- tlb_flush_page_by_mmuidx(cs, pageaddr,
146
- ARMMMUIdxBit_S12NSE1 |
147
- ARMMMUIdxBit_S12NSE0);
148
- }
149
+ tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
150
}
151
152
static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
153
--
179
--
154
2.20.1
180
2.20.1
155
181
156
182
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
Create a predicate to indicate whether the regime has
3
The Allwinner H3 System on Chip has an System Control
4
both positive and negative addresses.
4
module that provides system wide generic controls and
5
5
device information. This commit adds support for the
6
Tested-by: Alex Bennée <alex.bennee@linaro.org>
6
Allwinner H3 System Control module.
7
8
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 20200206105448.4726-21-richard.henderson@linaro.org
12
Message-id: 20200311221854.30370-6-nieklinnenbank@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
14
---
12
target/arm/internals.h | 18 ++++++++++++++++++
15
hw/misc/Makefile.objs | 1 +
13
target/arm/helper.c | 23 ++++++-----------------
16
include/hw/arm/allwinner-h3.h | 3 +
14
target/arm/translate-a64.c | 3 +--
17
include/hw/misc/allwinner-h3-sysctrl.h | 67 ++++++++++++
15
3 files changed, 25 insertions(+), 19 deletions(-)
18
hw/arm/allwinner-h3.c | 9 +-
16
19
hw/misc/allwinner-h3-sysctrl.c | 140 +++++++++++++++++++++++++
17
diff --git a/target/arm/internals.h b/target/arm/internals.h
20
5 files changed, 219 insertions(+), 1 deletion(-)
21
create mode 100644 include/hw/misc/allwinner-h3-sysctrl.h
22
create mode 100644 hw/misc/allwinner-h3-sysctrl.c
23
24
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
18
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/internals.h
26
--- a/hw/misc/Makefile.objs
20
+++ b/target/arm/internals.h
27
+++ b/hw/misc/Makefile.objs
21
@@ -XXX,XX +XXX,XX @@ static inline void arm_call_el_change_hook(ARMCPU *cpu)
28
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_MACIO) += macio/
22
}
29
common-obj-$(CONFIG_IVSHMEM_DEVICE) += ivshmem.o
30
31
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-ccu.o
32
+common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-sysctrl.o
33
common-obj-$(CONFIG_REALVIEW) += arm_sysctl.o
34
common-obj-$(CONFIG_NSERIES) += cbus.o
35
common-obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
36
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/hw/arm/allwinner-h3.h
39
+++ b/include/hw/arm/allwinner-h3.h
40
@@ -XXX,XX +XXX,XX @@
41
#include "hw/timer/allwinner-a10-pit.h"
42
#include "hw/intc/arm_gic.h"
43
#include "hw/misc/allwinner-h3-ccu.h"
44
+#include "hw/misc/allwinner-h3-sysctrl.h"
45
#include "target/arm/cpu.h"
46
47
/**
48
@@ -XXX,XX +XXX,XX @@ enum {
49
AW_H3_SRAM_A1,
50
AW_H3_SRAM_A2,
51
AW_H3_SRAM_C,
52
+ AW_H3_SYSCTRL,
53
AW_H3_EHCI0,
54
AW_H3_OHCI0,
55
AW_H3_EHCI1,
56
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
57
const hwaddr *memmap;
58
AwA10PITState timer;
59
AwH3ClockCtlState ccu;
60
+ AwH3SysCtrlState sysctrl;
61
GICState gic;
62
MemoryRegion sram_a1;
63
MemoryRegion sram_a2;
64
diff --git a/include/hw/misc/allwinner-h3-sysctrl.h b/include/hw/misc/allwinner-h3-sysctrl.h
65
new file mode 100644
66
index XXXXXXX..XXXXXXX
67
--- /dev/null
68
+++ b/include/hw/misc/allwinner-h3-sysctrl.h
69
@@ -XXX,XX +XXX,XX @@
70
+/*
71
+ * Allwinner H3 System Control emulation
72
+ *
73
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
74
+ *
75
+ * This program is free software: you can redistribute it and/or modify
76
+ * it under the terms of the GNU General Public License as published by
77
+ * the Free Software Foundation, either version 2 of the License, or
78
+ * (at your option) any later version.
79
+ *
80
+ * This program is distributed in the hope that it will be useful,
81
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
82
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
83
+ * GNU General Public License for more details.
84
+ *
85
+ * You should have received a copy of the GNU General Public License
86
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
87
+ */
88
+
89
+#ifndef HW_MISC_ALLWINNER_H3_SYSCTRL_H
90
+#define HW_MISC_ALLWINNER_H3_SYSCTRL_H
91
+
92
+#include "qom/object.h"
93
+#include "hw/sysbus.h"
94
+
95
+/**
96
+ * @name Constants
97
+ * @{
98
+ */
99
+
100
+/** Highest register address used by System Control device */
101
+#define AW_H3_SYSCTRL_REGS_MAXADDR (0x30)
102
+
103
+/** Total number of known registers */
104
+#define AW_H3_SYSCTRL_REGS_NUM ((AW_H3_SYSCTRL_REGS_MAXADDR / \
105
+ sizeof(uint32_t)) + 1)
106
+
107
+/** @} */
108
+
109
+/**
110
+ * @name Object model
111
+ * @{
112
+ */
113
+
114
+#define TYPE_AW_H3_SYSCTRL "allwinner-h3-sysctrl"
115
+#define AW_H3_SYSCTRL(obj) \
116
+ OBJECT_CHECK(AwH3SysCtrlState, (obj), TYPE_AW_H3_SYSCTRL)
117
+
118
+/** @} */
119
+
120
+/**
121
+ * Allwinner H3 System Control object instance state
122
+ */
123
+typedef struct AwH3SysCtrlState {
124
+ /*< private >*/
125
+ SysBusDevice parent_obj;
126
+ /*< public >*/
127
+
128
+ /** Maps I/O registers in physical memory */
129
+ MemoryRegion iomem;
130
+
131
+ /** Array of hardware registers */
132
+ uint32_t regs[AW_H3_SYSCTRL_REGS_NUM];
133
+
134
+} AwH3SysCtrlState;
135
+
136
+#endif /* HW_MISC_ALLWINNER_H3_SYSCTRL_H */
137
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
138
index XXXXXXX..XXXXXXX 100644
139
--- a/hw/arm/allwinner-h3.c
140
+++ b/hw/arm/allwinner-h3.c
141
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
142
[AW_H3_SRAM_A1] = 0x00000000,
143
[AW_H3_SRAM_A2] = 0x00044000,
144
[AW_H3_SRAM_C] = 0x00010000,
145
+ [AW_H3_SYSCTRL] = 0x01c00000,
146
[AW_H3_EHCI0] = 0x01c1a000,
147
[AW_H3_OHCI0] = 0x01c1a400,
148
[AW_H3_EHCI1] = 0x01c1b000,
149
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
150
} unimplemented[] = {
151
{ "d-engine", 0x01000000, 4 * MiB },
152
{ "d-inter", 0x01400000, 128 * KiB },
153
- { "syscon", 0x01c00000, 4 * KiB },
154
{ "dma", 0x01c02000, 4 * KiB },
155
{ "nfdc", 0x01c03000, 4 * KiB },
156
{ "ts", 0x01c06000, 4 * KiB },
157
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
158
159
sysbus_init_child_obj(obj, "ccu", &s->ccu, sizeof(s->ccu),
160
TYPE_AW_H3_CCU);
161
+
162
+ sysbus_init_child_obj(obj, "sysctrl", &s->sysctrl, sizeof(s->sysctrl),
163
+ TYPE_AW_H3_SYSCTRL);
23
}
164
}
24
165
25
+/* Return true if this address translation regime has two ranges. */
166
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
26
+static inline bool regime_has_2_ranges(ARMMMUIdx mmu_idx)
167
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
27
+{
168
qdev_init_nofail(DEVICE(&s->ccu));
28
+ switch (mmu_idx) {
169
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccu), 0, s->memmap[AW_H3_CCU]);
29
+ case ARMMMUIdx_Stage1_E0:
170
30
+ case ARMMMUIdx_Stage1_E1:
171
+ /* System Control */
31
+ case ARMMMUIdx_E10_0:
172
+ qdev_init_nofail(DEVICE(&s->sysctrl));
32
+ case ARMMMUIdx_E10_1:
173
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctrl), 0, s->memmap[AW_H3_SYSCTRL]);
33
+ case ARMMMUIdx_E20_0:
174
+
34
+ case ARMMMUIdx_E20_2:
175
/* Universal Serial Bus */
35
+ case ARMMMUIdx_SE10_0:
176
sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI0],
36
+ case ARMMMUIdx_SE10_1:
177
qdev_get_gpio_in(DEVICE(&s->gic),
37
+ return true;
178
diff --git a/hw/misc/allwinner-h3-sysctrl.c b/hw/misc/allwinner-h3-sysctrl.c
179
new file mode 100644
180
index XXXXXXX..XXXXXXX
181
--- /dev/null
182
+++ b/hw/misc/allwinner-h3-sysctrl.c
183
@@ -XXX,XX +XXX,XX @@
184
+/*
185
+ * Allwinner H3 System Control emulation
186
+ *
187
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
188
+ *
189
+ * This program is free software: you can redistribute it and/or modify
190
+ * it under the terms of the GNU General Public License as published by
191
+ * the Free Software Foundation, either version 2 of the License, or
192
+ * (at your option) any later version.
193
+ *
194
+ * This program is distributed in the hope that it will be useful,
195
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
196
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
197
+ * GNU General Public License for more details.
198
+ *
199
+ * You should have received a copy of the GNU General Public License
200
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
201
+ */
202
+
203
+#include "qemu/osdep.h"
204
+#include "qemu/units.h"
205
+#include "hw/sysbus.h"
206
+#include "migration/vmstate.h"
207
+#include "qemu/log.h"
208
+#include "qemu/module.h"
209
+#include "hw/misc/allwinner-h3-sysctrl.h"
210
+
211
+/* System Control register offsets */
212
+enum {
213
+ REG_VER = 0x24, /* Version */
214
+ REG_EMAC_PHY_CLK = 0x30, /* EMAC PHY Clock */
215
+};
216
+
217
+#define REG_INDEX(offset) (offset / sizeof(uint32_t))
218
+
219
+/* System Control register reset values */
220
+enum {
221
+ REG_VER_RST = 0x0,
222
+ REG_EMAC_PHY_CLK_RST = 0x58000,
223
+};
224
+
225
+static uint64_t allwinner_h3_sysctrl_read(void *opaque, hwaddr offset,
226
+ unsigned size)
227
+{
228
+ const AwH3SysCtrlState *s = AW_H3_SYSCTRL(opaque);
229
+ const uint32_t idx = REG_INDEX(offset);
230
+
231
+ if (idx >= AW_H3_SYSCTRL_REGS_NUM) {
232
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
233
+ __func__, (uint32_t)offset);
234
+ return 0;
235
+ }
236
+
237
+ return s->regs[idx];
238
+}
239
+
240
+static void allwinner_h3_sysctrl_write(void *opaque, hwaddr offset,
241
+ uint64_t val, unsigned size)
242
+{
243
+ AwH3SysCtrlState *s = AW_H3_SYSCTRL(opaque);
244
+ const uint32_t idx = REG_INDEX(offset);
245
+
246
+ if (idx >= AW_H3_SYSCTRL_REGS_NUM) {
247
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
248
+ __func__, (uint32_t)offset);
249
+ return;
250
+ }
251
+
252
+ switch (offset) {
253
+ case REG_VER: /* Version */
254
+ break;
38
+ default:
255
+ default:
39
+ return false;
256
+ s->regs[idx] = (uint32_t) val;
257
+ break;
40
+ }
258
+ }
41
+}
259
+}
42
+
260
+
43
/* Return true if this address translation regime is secure */
261
+static const MemoryRegionOps allwinner_h3_sysctrl_ops = {
44
static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
262
+ .read = allwinner_h3_sysctrl_read,
45
{
263
+ .write = allwinner_h3_sysctrl_write,
46
diff --git a/target/arm/helper.c b/target/arm/helper.c
264
+ .endianness = DEVICE_NATIVE_ENDIAN,
47
index XXXXXXX..XXXXXXX 100644
265
+ .valid = {
48
--- a/target/arm/helper.c
266
+ .min_access_size = 4,
49
+++ b/target/arm/helper.c
267
+ .max_access_size = 4,
50
@@ -XXX,XX +XXX,XX @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
268
+ },
51
}
269
+ .impl.min_access_size = 4,
52
270
+};
53
if (is_aa64) {
271
+
54
- switch (regime_el(env, mmu_idx)) {
272
+static void allwinner_h3_sysctrl_reset(DeviceState *dev)
55
- case 1:
273
+{
56
- if (!is_user) {
274
+ AwH3SysCtrlState *s = AW_H3_SYSCTRL(dev);
57
- xn = pxn || (user_rw & PAGE_WRITE);
275
+
58
- }
276
+ /* Set default values for registers */
59
- break;
277
+ s->regs[REG_INDEX(REG_VER)] = REG_VER_RST;
60
- case 2:
278
+ s->regs[REG_INDEX(REG_EMAC_PHY_CLK)] = REG_EMAC_PHY_CLK_RST;
61
- case 3:
279
+}
62
- break;
280
+
63
+ if (regime_has_2_ranges(mmu_idx) && !is_user) {
281
+static void allwinner_h3_sysctrl_init(Object *obj)
64
+ xn = pxn || (user_rw & PAGE_WRITE);
282
+{
65
}
283
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
66
} else if (arm_feature(env, ARM_FEATURE_V7)) {
284
+ AwH3SysCtrlState *s = AW_H3_SYSCTRL(obj);
67
switch (regime_el(env, mmu_idx)) {
285
+
68
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
286
+ /* Memory mapping */
69
ARMMMUIdx mmu_idx)
287
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_h3_sysctrl_ops, s,
70
{
288
+ TYPE_AW_H3_SYSCTRL, 4 * KiB);
71
uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
289
+ sysbus_init_mmio(sbd, &s->iomem);
72
- uint32_t el = regime_el(env, mmu_idx);
290
+}
73
bool tbi, tbid, epd, hpd, using16k, using64k;
291
+
74
int select, tsz;
292
+static const VMStateDescription allwinner_h3_sysctrl_vmstate = {
75
293
+ .name = "allwinner-h3-sysctrl",
76
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
294
+ .version_id = 1,
77
*/
295
+ .minimum_version_id = 1,
78
select = extract64(va, 55, 1);
296
+ .fields = (VMStateField[]) {
79
297
+ VMSTATE_UINT32_ARRAY(regs, AwH3SysCtrlState, AW_H3_SYSCTRL_REGS_NUM),
80
- if (el > 1) {
298
+ VMSTATE_END_OF_LIST()
81
+ if (!regime_has_2_ranges(mmu_idx)) {
299
+ }
82
tsz = extract32(tcr, 0, 6);
300
+};
83
using64k = extract32(tcr, 14, 1);
301
+
84
using16k = extract32(tcr, 15, 1);
302
+static void allwinner_h3_sysctrl_class_init(ObjectClass *klass, void *data)
85
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
303
+{
86
param = aa64_va_parameters(env, address, mmu_idx,
304
+ DeviceClass *dc = DEVICE_CLASS(klass);
87
access_type != MMU_INST_FETCH);
305
+
88
level = 0;
306
+ dc->reset = allwinner_h3_sysctrl_reset;
89
- /* If we are in 64-bit EL2 or EL3 then there is no TTBR1, so mark it
307
+ dc->vmsd = &allwinner_h3_sysctrl_vmstate;
90
- * invalid.
308
+}
91
- */
309
+
92
- ttbr1_valid = (el < 2);
310
+static const TypeInfo allwinner_h3_sysctrl_info = {
93
+ ttbr1_valid = regime_has_2_ranges(mmu_idx);
311
+ .name = TYPE_AW_H3_SYSCTRL,
94
addrsize = 64 - 8 * param.tbi;
312
+ .parent = TYPE_SYS_BUS_DEVICE,
95
inputsize = 64 - param.tsz;
313
+ .instance_init = allwinner_h3_sysctrl_init,
96
} else {
314
+ .instance_size = sizeof(AwH3SysCtrlState),
97
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
315
+ .class_init = allwinner_h3_sysctrl_class_init,
98
316
+};
99
flags = FIELD_DP32(flags, TBFLAG_ANY, AARCH64_STATE, 1);
317
+
100
318
+static void allwinner_h3_sysctrl_register(void)
101
- /* FIXME: ARMv8.1-VHE S2 translation regime. */
319
+{
102
- if (regime_el(env, stage1) < 2) {
320
+ type_register_static(&allwinner_h3_sysctrl_info);
103
+ /* Get control bits for tagged addresses. */
321
+}
104
+ if (regime_has_2_ranges(mmu_idx)) {
322
+
105
ARMVAParameters p1 = aa64_va_parameters_both(env, -1, stage1);
323
+type_init(allwinner_h3_sysctrl_register)
106
tbid = (p1.tbi << 1) | p0.tbi;
107
tbii = tbid & ~((p1.tbid << 1) | p0.tbid);
108
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
109
index XXXXXXX..XXXXXXX 100644
110
--- a/target/arm/translate-a64.c
111
+++ b/target/arm/translate-a64.c
112
@@ -XXX,XX +XXX,XX @@ static void gen_top_byte_ignore(DisasContext *s, TCGv_i64 dst,
113
if (tbi == 0) {
114
/* Load unmodified address */
115
tcg_gen_mov_i64(dst, src);
116
- } else if (s->current_el >= 2) {
117
- /* FIXME: ARMv8.1-VHE S2 translation regime. */
118
+ } else if (!regime_has_2_ranges(s->mmu_idx)) {
119
/* Force tag byte to all zero */
120
tcg_gen_extract_i64(dst, src, 0, 56);
121
} else {
122
--
324
--
123
2.20.1
325
2.20.1
124
326
125
327
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
Apart from the wholesale redirection that HCR_EL2.E2H performs
3
Various Allwinner System on Chip designs contain multiple processors
4
for EL2, there's a separate redirection specific to the timers
4
that can be configured and reset using the generic CPU Configuration
5
that happens for EL0 when running in the EL2&0 regime.
5
module interface. This commit adds support for the Allwinner CPU
6
6
configuration interface which emulates the following features:
7
Tested-by: Alex Bennée <alex.bennee@linaro.org>
7
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
* CPU reset
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
* CPU status
10
Message-id: 20200206105448.4726-30-richard.henderson@linaro.org
10
11
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
Message-id: 20200311221854.30370-7-nieklinnenbank@gmail.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
15
---
13
target/arm/helper.c | 181 +++++++++++++++++++++++++++++++++++++++++---
16
hw/misc/Makefile.objs | 1 +
14
1 file changed, 169 insertions(+), 12 deletions(-)
17
include/hw/arm/allwinner-h3.h | 3 +
15
18
include/hw/misc/allwinner-cpucfg.h | 52 ++++++
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
hw/arm/allwinner-h3.c | 9 +-
20
hw/misc/allwinner-cpucfg.c | 282 +++++++++++++++++++++++++++++
21
hw/misc/trace-events | 5 +
22
6 files changed, 351 insertions(+), 1 deletion(-)
23
create mode 100644 include/hw/misc/allwinner-cpucfg.h
24
create mode 100644 hw/misc/allwinner-cpucfg.c
25
26
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
17
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.c
28
--- a/hw/misc/Makefile.objs
19
+++ b/target/arm/helper.c
29
+++ b/hw/misc/Makefile.objs
20
@@ -XXX,XX +XXX,XX @@ static void gt_phys_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
30
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_MACIO) += macio/
21
gt_ctl_write(env, ri, GTIMER_PHYS, value);
31
common-obj-$(CONFIG_IVSHMEM_DEVICE) += ivshmem.o
32
33
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-ccu.o
34
+obj-$(CONFIG_ALLWINNER_H3) += allwinner-cpucfg.o
35
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-sysctrl.o
36
common-obj-$(CONFIG_REALVIEW) += arm_sysctl.o
37
common-obj-$(CONFIG_NSERIES) += cbus.o
38
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/include/hw/arm/allwinner-h3.h
41
+++ b/include/hw/arm/allwinner-h3.h
42
@@ -XXX,XX +XXX,XX @@
43
#include "hw/timer/allwinner-a10-pit.h"
44
#include "hw/intc/arm_gic.h"
45
#include "hw/misc/allwinner-h3-ccu.h"
46
+#include "hw/misc/allwinner-cpucfg.h"
47
#include "hw/misc/allwinner-h3-sysctrl.h"
48
#include "target/arm/cpu.h"
49
50
@@ -XXX,XX +XXX,XX @@ enum {
51
AW_H3_GIC_CPU,
52
AW_H3_GIC_HYP,
53
AW_H3_GIC_VCPU,
54
+ AW_H3_CPUCFG,
55
AW_H3_SDRAM
56
};
57
58
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
59
const hwaddr *memmap;
60
AwA10PITState timer;
61
AwH3ClockCtlState ccu;
62
+ AwCpuCfgState cpucfg;
63
AwH3SysCtrlState sysctrl;
64
GICState gic;
65
MemoryRegion sram_a1;
66
diff --git a/include/hw/misc/allwinner-cpucfg.h b/include/hw/misc/allwinner-cpucfg.h
67
new file mode 100644
68
index XXXXXXX..XXXXXXX
69
--- /dev/null
70
+++ b/include/hw/misc/allwinner-cpucfg.h
71
@@ -XXX,XX +XXX,XX @@
72
+/*
73
+ * Allwinner CPU Configuration Module emulation
74
+ *
75
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
76
+ *
77
+ * This program is free software: you can redistribute it and/or modify
78
+ * it under the terms of the GNU General Public License as published by
79
+ * the Free Software Foundation, either version 2 of the License, or
80
+ * (at your option) any later version.
81
+ *
82
+ * This program is distributed in the hope that it will be useful,
83
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
84
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
85
+ * GNU General Public License for more details.
86
+ *
87
+ * You should have received a copy of the GNU General Public License
88
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
89
+ */
90
+
91
+#ifndef HW_MISC_ALLWINNER_CPUCFG_H
92
+#define HW_MISC_ALLWINNER_CPUCFG_H
93
+
94
+#include "qom/object.h"
95
+#include "hw/sysbus.h"
96
+
97
+/**
98
+ * Object model
99
+ * @{
100
+ */
101
+
102
+#define TYPE_AW_CPUCFG "allwinner-cpucfg"
103
+#define AW_CPUCFG(obj) \
104
+ OBJECT_CHECK(AwCpuCfgState, (obj), TYPE_AW_CPUCFG)
105
+
106
+/** @} */
107
+
108
+/**
109
+ * Allwinner CPU Configuration Module instance state
110
+ */
111
+typedef struct AwCpuCfgState {
112
+ /*< private >*/
113
+ SysBusDevice parent_obj;
114
+ /*< public >*/
115
+
116
+ MemoryRegion iomem;
117
+ uint32_t gen_ctrl;
118
+ uint32_t super_standby;
119
+ uint32_t entry_addr;
120
+
121
+} AwCpuCfgState;
122
+
123
+#endif /* HW_MISC_ALLWINNER_CPUCFG_H */
124
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
125
index XXXXXXX..XXXXXXX 100644
126
--- a/hw/arm/allwinner-h3.c
127
+++ b/hw/arm/allwinner-h3.c
128
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
129
[AW_H3_GIC_CPU] = 0x01c82000,
130
[AW_H3_GIC_HYP] = 0x01c84000,
131
[AW_H3_GIC_VCPU] = 0x01c86000,
132
+ [AW_H3_CPUCFG] = 0x01f01c00,
133
[AW_H3_SDRAM] = 0x40000000
134
};
135
136
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
137
{ "r_wdog", 0x01f01000, 1 * KiB },
138
{ "r_prcm", 0x01f01400, 1 * KiB },
139
{ "r_twd", 0x01f01800, 1 * KiB },
140
- { "r_cpucfg", 0x01f01c00, 1 * KiB },
141
{ "r_cir-rx", 0x01f02000, 1 * KiB },
142
{ "r_twi", 0x01f02400, 1 * KiB },
143
{ "r_uart", 0x01f02800, 1 * KiB },
144
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
145
146
sysbus_init_child_obj(obj, "sysctrl", &s->sysctrl, sizeof(s->sysctrl),
147
TYPE_AW_H3_SYSCTRL);
148
+
149
+ sysbus_init_child_obj(obj, "cpucfg", &s->cpucfg, sizeof(s->cpucfg),
150
+ TYPE_AW_CPUCFG);
22
}
151
}
23
152
24
+static int gt_phys_redir_timeridx(CPUARMState *env)
153
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
25
+{
154
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
26
+ switch (arm_mmu_idx(env)) {
155
qdev_init_nofail(DEVICE(&s->sysctrl));
27
+ case ARMMMUIdx_E20_0:
156
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctrl), 0, s->memmap[AW_H3_SYSCTRL]);
28
+ case ARMMMUIdx_E20_2:
157
29
+ return GTIMER_HYP;
158
+ /* CPU Configuration */
159
+ qdev_init_nofail(DEVICE(&s->cpucfg));
160
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->cpucfg), 0, s->memmap[AW_H3_CPUCFG]);
161
+
162
/* Universal Serial Bus */
163
sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI0],
164
qdev_get_gpio_in(DEVICE(&s->gic),
165
diff --git a/hw/misc/allwinner-cpucfg.c b/hw/misc/allwinner-cpucfg.c
166
new file mode 100644
167
index XXXXXXX..XXXXXXX
168
--- /dev/null
169
+++ b/hw/misc/allwinner-cpucfg.c
170
@@ -XXX,XX +XXX,XX @@
171
+/*
172
+ * Allwinner CPU Configuration Module emulation
173
+ *
174
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
175
+ *
176
+ * This program is free software: you can redistribute it and/or modify
177
+ * it under the terms of the GNU General Public License as published by
178
+ * the Free Software Foundation, either version 2 of the License, or
179
+ * (at your option) any later version.
180
+ *
181
+ * This program is distributed in the hope that it will be useful,
182
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
183
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
184
+ * GNU General Public License for more details.
185
+ *
186
+ * You should have received a copy of the GNU General Public License
187
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
188
+ */
189
+
190
+#include "qemu/osdep.h"
191
+#include "qemu/units.h"
192
+#include "hw/sysbus.h"
193
+#include "migration/vmstate.h"
194
+#include "qemu/log.h"
195
+#include "qemu/module.h"
196
+#include "qemu/error-report.h"
197
+#include "qemu/timer.h"
198
+#include "hw/core/cpu.h"
199
+#include "target/arm/arm-powerctl.h"
200
+#include "target/arm/cpu.h"
201
+#include "hw/misc/allwinner-cpucfg.h"
202
+#include "trace.h"
203
+
204
+/* CPUCFG register offsets */
205
+enum {
206
+ REG_CPUS_RST_CTRL = 0x0000, /* CPUs Reset Control */
207
+ REG_CPU0_RST_CTRL = 0x0040, /* CPU#0 Reset Control */
208
+ REG_CPU0_CTRL = 0x0044, /* CPU#0 Control */
209
+ REG_CPU0_STATUS = 0x0048, /* CPU#0 Status */
210
+ REG_CPU1_RST_CTRL = 0x0080, /* CPU#1 Reset Control */
211
+ REG_CPU1_CTRL = 0x0084, /* CPU#1 Control */
212
+ REG_CPU1_STATUS = 0x0088, /* CPU#1 Status */
213
+ REG_CPU2_RST_CTRL = 0x00C0, /* CPU#2 Reset Control */
214
+ REG_CPU2_CTRL = 0x00C4, /* CPU#2 Control */
215
+ REG_CPU2_STATUS = 0x00C8, /* CPU#2 Status */
216
+ REG_CPU3_RST_CTRL = 0x0100, /* CPU#3 Reset Control */
217
+ REG_CPU3_CTRL = 0x0104, /* CPU#3 Control */
218
+ REG_CPU3_STATUS = 0x0108, /* CPU#3 Status */
219
+ REG_CPU_SYS_RST = 0x0140, /* CPU System Reset */
220
+ REG_CLK_GATING = 0x0144, /* CPU Clock Gating */
221
+ REG_GEN_CTRL = 0x0184, /* General Control */
222
+ REG_SUPER_STANDBY = 0x01A0, /* Super Standby Flag */
223
+ REG_ENTRY_ADDR = 0x01A4, /* Reset Entry Address */
224
+ REG_DBG_EXTERN = 0x01E4, /* Debug External */
225
+ REG_CNT64_CTRL = 0x0280, /* 64-bit Counter Control */
226
+ REG_CNT64_LOW = 0x0284, /* 64-bit Counter Low */
227
+ REG_CNT64_HIGH = 0x0288, /* 64-bit Counter High */
228
+};
229
+
230
+/* CPUCFG register flags */
231
+enum {
232
+ CPUX_RESET_RELEASED = ((1 << 1) | (1 << 0)),
233
+ CPUX_STATUS_SMP = (1 << 0),
234
+ CPU_SYS_RESET_RELEASED = (1 << 0),
235
+ CLK_GATING_ENABLE = ((1 << 8) | 0xF),
236
+};
237
+
238
+/* CPUCFG register reset values */
239
+enum {
240
+ REG_CLK_GATING_RST = 0x0000010F,
241
+ REG_GEN_CTRL_RST = 0x00000020,
242
+ REG_SUPER_STANDBY_RST = 0x0,
243
+ REG_CNT64_CTRL_RST = 0x0,
244
+};
245
+
246
+/* CPUCFG constants */
247
+enum {
248
+ CPU_EXCEPTION_LEVEL_ON_RESET = 3, /* EL3 */
249
+};
250
+
251
+static void allwinner_cpucfg_cpu_reset(AwCpuCfgState *s, uint8_t cpu_id)
252
+{
253
+ int ret;
254
+
255
+ trace_allwinner_cpucfg_cpu_reset(cpu_id, s->entry_addr);
256
+
257
+ ARMCPU *target_cpu = ARM_CPU(arm_get_cpu_by_id(cpu_id));
258
+ if (!target_cpu) {
259
+ /*
260
+ * Called with a bogus value for cpu_id. Guest error will
261
+ * already have been logged, we can simply return here.
262
+ */
263
+ return;
264
+ }
265
+ bool target_aa64 = arm_feature(&target_cpu->env, ARM_FEATURE_AARCH64);
266
+
267
+ ret = arm_set_cpu_on(cpu_id, s->entry_addr, 0,
268
+ CPU_EXCEPTION_LEVEL_ON_RESET, target_aa64);
269
+ if (ret != QEMU_ARM_POWERCTL_RET_SUCCESS) {
270
+ error_report("%s: failed to bring up CPU %d: err %d",
271
+ __func__, cpu_id, ret);
272
+ return;
273
+ }
274
+}
275
+
276
+static uint64_t allwinner_cpucfg_read(void *opaque, hwaddr offset,
277
+ unsigned size)
278
+{
279
+ const AwCpuCfgState *s = AW_CPUCFG(opaque);
280
+ uint64_t val = 0;
281
+
282
+ switch (offset) {
283
+ case REG_CPUS_RST_CTRL: /* CPUs Reset Control */
284
+ case REG_CPU_SYS_RST: /* CPU System Reset */
285
+ val = CPU_SYS_RESET_RELEASED;
286
+ break;
287
+ case REG_CPU0_RST_CTRL: /* CPU#0 Reset Control */
288
+ case REG_CPU1_RST_CTRL: /* CPU#1 Reset Control */
289
+ case REG_CPU2_RST_CTRL: /* CPU#2 Reset Control */
290
+ case REG_CPU3_RST_CTRL: /* CPU#3 Reset Control */
291
+ val = CPUX_RESET_RELEASED;
292
+ break;
293
+ case REG_CPU0_CTRL: /* CPU#0 Control */
294
+ case REG_CPU1_CTRL: /* CPU#1 Control */
295
+ case REG_CPU2_CTRL: /* CPU#2 Control */
296
+ case REG_CPU3_CTRL: /* CPU#3 Control */
297
+ val = 0;
298
+ break;
299
+ case REG_CPU0_STATUS: /* CPU#0 Status */
300
+ case REG_CPU1_STATUS: /* CPU#1 Status */
301
+ case REG_CPU2_STATUS: /* CPU#2 Status */
302
+ case REG_CPU3_STATUS: /* CPU#3 Status */
303
+ val = CPUX_STATUS_SMP;
304
+ break;
305
+ case REG_CLK_GATING: /* CPU Clock Gating */
306
+ val = CLK_GATING_ENABLE;
307
+ break;
308
+ case REG_GEN_CTRL: /* General Control */
309
+ val = s->gen_ctrl;
310
+ break;
311
+ case REG_SUPER_STANDBY: /* Super Standby Flag */
312
+ val = s->super_standby;
313
+ break;
314
+ case REG_ENTRY_ADDR: /* Reset Entry Address */
315
+ val = s->entry_addr;
316
+ break;
317
+ case REG_DBG_EXTERN: /* Debug External */
318
+ case REG_CNT64_CTRL: /* 64-bit Counter Control */
319
+ case REG_CNT64_LOW: /* 64-bit Counter Low */
320
+ case REG_CNT64_HIGH: /* 64-bit Counter High */
321
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented register at 0x%04x\n",
322
+ __func__, (uint32_t)offset);
323
+ break;
30
+ default:
324
+ default:
31
+ return GTIMER_PHYS;
325
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
326
+ __func__, (uint32_t)offset);
327
+ break;
32
+ }
328
+ }
33
+}
329
+
34
+
330
+ trace_allwinner_cpucfg_read(offset, val, size);
35
+static int gt_virt_redir_timeridx(CPUARMState *env)
331
+
36
+{
332
+ return val;
37
+ switch (arm_mmu_idx(env)) {
333
+}
38
+ case ARMMMUIdx_E20_0:
334
+
39
+ case ARMMMUIdx_E20_2:
335
+static void allwinner_cpucfg_write(void *opaque, hwaddr offset,
40
+ return GTIMER_HYPVIRT;
336
+ uint64_t val, unsigned size)
337
+{
338
+ AwCpuCfgState *s = AW_CPUCFG(opaque);
339
+
340
+ trace_allwinner_cpucfg_write(offset, val, size);
341
+
342
+ switch (offset) {
343
+ case REG_CPUS_RST_CTRL: /* CPUs Reset Control */
344
+ case REG_CPU_SYS_RST: /* CPU System Reset */
345
+ break;
346
+ case REG_CPU0_RST_CTRL: /* CPU#0 Reset Control */
347
+ case REG_CPU1_RST_CTRL: /* CPU#1 Reset Control */
348
+ case REG_CPU2_RST_CTRL: /* CPU#2 Reset Control */
349
+ case REG_CPU3_RST_CTRL: /* CPU#3 Reset Control */
350
+ if (val) {
351
+ allwinner_cpucfg_cpu_reset(s, (offset - REG_CPU0_RST_CTRL) >> 6);
352
+ }
353
+ break;
354
+ case REG_CPU0_CTRL: /* CPU#0 Control */
355
+ case REG_CPU1_CTRL: /* CPU#1 Control */
356
+ case REG_CPU2_CTRL: /* CPU#2 Control */
357
+ case REG_CPU3_CTRL: /* CPU#3 Control */
358
+ case REG_CPU0_STATUS: /* CPU#0 Status */
359
+ case REG_CPU1_STATUS: /* CPU#1 Status */
360
+ case REG_CPU2_STATUS: /* CPU#2 Status */
361
+ case REG_CPU3_STATUS: /* CPU#3 Status */
362
+ case REG_CLK_GATING: /* CPU Clock Gating */
363
+ break;
364
+ case REG_GEN_CTRL: /* General Control */
365
+ s->gen_ctrl = val;
366
+ break;
367
+ case REG_SUPER_STANDBY: /* Super Standby Flag */
368
+ s->super_standby = val;
369
+ break;
370
+ case REG_ENTRY_ADDR: /* Reset Entry Address */
371
+ s->entry_addr = val;
372
+ break;
373
+ case REG_DBG_EXTERN: /* Debug External */
374
+ case REG_CNT64_CTRL: /* 64-bit Counter Control */
375
+ case REG_CNT64_LOW: /* 64-bit Counter Low */
376
+ case REG_CNT64_HIGH: /* 64-bit Counter High */
377
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented register at 0x%04x\n",
378
+ __func__, (uint32_t)offset);
379
+ break;
41
+ default:
380
+ default:
42
+ return GTIMER_VIRT;
381
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
382
+ __func__, (uint32_t)offset);
383
+ break;
43
+ }
384
+ }
44
+}
385
+}
45
+
386
+
46
+static uint64_t gt_phys_redir_cval_read(CPUARMState *env,
387
+static const MemoryRegionOps allwinner_cpucfg_ops = {
47
+ const ARMCPRegInfo *ri)
388
+ .read = allwinner_cpucfg_read,
48
+{
389
+ .write = allwinner_cpucfg_write,
49
+ int timeridx = gt_phys_redir_timeridx(env);
390
+ .endianness = DEVICE_NATIVE_ENDIAN,
50
+ return env->cp15.c14_timer[timeridx].cval;
391
+ .valid = {
51
+}
392
+ .min_access_size = 4,
52
+
393
+ .max_access_size = 4,
53
+static void gt_phys_redir_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
394
+ },
54
+ uint64_t value)
395
+ .impl.min_access_size = 4,
55
+{
396
+};
56
+ int timeridx = gt_phys_redir_timeridx(env);
397
+
57
+ gt_cval_write(env, ri, timeridx, value);
398
+static void allwinner_cpucfg_reset(DeviceState *dev)
58
+}
399
+{
59
+
400
+ AwCpuCfgState *s = AW_CPUCFG(dev);
60
+static uint64_t gt_phys_redir_tval_read(CPUARMState *env,
401
+
61
+ const ARMCPRegInfo *ri)
402
+ /* Set default values for registers */
62
+{
403
+ s->gen_ctrl = REG_GEN_CTRL_RST;
63
+ int timeridx = gt_phys_redir_timeridx(env);
404
+ s->super_standby = REG_SUPER_STANDBY_RST;
64
+ return gt_tval_read(env, ri, timeridx);
405
+ s->entry_addr = 0;
65
+}
406
+}
66
+
407
+
67
+static void gt_phys_redir_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
408
+static void allwinner_cpucfg_init(Object *obj)
68
+ uint64_t value)
409
+{
69
+{
410
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
70
+ int timeridx = gt_phys_redir_timeridx(env);
411
+ AwCpuCfgState *s = AW_CPUCFG(obj);
71
+ gt_tval_write(env, ri, timeridx, value);
412
+
72
+}
413
+ /* Memory mapping */
73
+
414
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_cpucfg_ops, s,
74
+static uint64_t gt_phys_redir_ctl_read(CPUARMState *env,
415
+ TYPE_AW_CPUCFG, 1 * KiB);
75
+ const ARMCPRegInfo *ri)
416
+ sysbus_init_mmio(sbd, &s->iomem);
76
+{
417
+}
77
+ int timeridx = gt_phys_redir_timeridx(env);
418
+
78
+ return env->cp15.c14_timer[timeridx].ctl;
419
+static const VMStateDescription allwinner_cpucfg_vmstate = {
79
+}
420
+ .name = "allwinner-cpucfg",
80
+
421
+ .version_id = 1,
81
+static void gt_phys_redir_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
422
+ .minimum_version_id = 1,
82
+ uint64_t value)
423
+ .fields = (VMStateField[]) {
83
+{
424
+ VMSTATE_UINT32(gen_ctrl, AwCpuCfgState),
84
+ int timeridx = gt_phys_redir_timeridx(env);
425
+ VMSTATE_UINT32(super_standby, AwCpuCfgState),
85
+ gt_ctl_write(env, ri, timeridx, value);
426
+ VMSTATE_UINT32(entry_addr, AwCpuCfgState),
86
+}
427
+ VMSTATE_END_OF_LIST()
87
+
88
static void gt_virt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
89
{
90
gt_timer_reset(env, ri, GTIMER_VIRT);
91
@@ -XXX,XX +XXX,XX @@ static void gt_cntvoff_write(CPUARMState *env, const ARMCPRegInfo *ri,
92
gt_recalc_timer(cpu, GTIMER_VIRT);
93
}
94
95
+static uint64_t gt_virt_redir_cval_read(CPUARMState *env,
96
+ const ARMCPRegInfo *ri)
97
+{
98
+ int timeridx = gt_virt_redir_timeridx(env);
99
+ return env->cp15.c14_timer[timeridx].cval;
100
+}
101
+
102
+static void gt_virt_redir_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
103
+ uint64_t value)
104
+{
105
+ int timeridx = gt_virt_redir_timeridx(env);
106
+ gt_cval_write(env, ri, timeridx, value);
107
+}
108
+
109
+static uint64_t gt_virt_redir_tval_read(CPUARMState *env,
110
+ const ARMCPRegInfo *ri)
111
+{
112
+ int timeridx = gt_virt_redir_timeridx(env);
113
+ return gt_tval_read(env, ri, timeridx);
114
+}
115
+
116
+static void gt_virt_redir_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
117
+ uint64_t value)
118
+{
119
+ int timeridx = gt_virt_redir_timeridx(env);
120
+ gt_tval_write(env, ri, timeridx, value);
121
+}
122
+
123
+static uint64_t gt_virt_redir_ctl_read(CPUARMState *env,
124
+ const ARMCPRegInfo *ri)
125
+{
126
+ int timeridx = gt_virt_redir_timeridx(env);
127
+ return env->cp15.c14_timer[timeridx].ctl;
128
+}
129
+
130
+static void gt_virt_redir_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
131
+ uint64_t value)
132
+{
133
+ int timeridx = gt_virt_redir_timeridx(env);
134
+ gt_ctl_write(env, ri, timeridx, value);
135
+}
136
+
137
static void gt_hyp_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
138
{
139
gt_timer_reset(env, ri, GTIMER_HYP);
140
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
141
.accessfn = gt_ptimer_access,
142
.fieldoffset = offsetoflow32(CPUARMState,
143
cp15.c14_timer[GTIMER_PHYS].ctl),
144
- .writefn = gt_phys_ctl_write, .raw_writefn = raw_write,
145
+ .readfn = gt_phys_redir_ctl_read, .raw_readfn = raw_read,
146
+ .writefn = gt_phys_redir_ctl_write, .raw_writefn = raw_write,
147
},
148
{ .name = "CNTP_CTL_S",
149
.cp = 15, .crn = 14, .crm = 2, .opc1 = 0, .opc2 = 1,
150
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
151
.accessfn = gt_ptimer_access,
152
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].ctl),
153
.resetvalue = 0,
154
- .writefn = gt_phys_ctl_write, .raw_writefn = raw_write,
155
+ .readfn = gt_phys_redir_ctl_read, .raw_readfn = raw_read,
156
+ .writefn = gt_phys_redir_ctl_write, .raw_writefn = raw_write,
157
},
158
{ .name = "CNTV_CTL", .cp = 15, .crn = 14, .crm = 3, .opc1 = 0, .opc2 = 1,
159
.type = ARM_CP_IO | ARM_CP_ALIAS, .access = PL0_RW,
160
.accessfn = gt_vtimer_access,
161
.fieldoffset = offsetoflow32(CPUARMState,
162
cp15.c14_timer[GTIMER_VIRT].ctl),
163
- .writefn = gt_virt_ctl_write, .raw_writefn = raw_write,
164
+ .readfn = gt_virt_redir_ctl_read, .raw_readfn = raw_read,
165
+ .writefn = gt_virt_redir_ctl_write, .raw_writefn = raw_write,
166
},
167
{ .name = "CNTV_CTL_EL0", .state = ARM_CP_STATE_AA64,
168
.opc0 = 3, .opc1 = 3, .crn = 14, .crm = 3, .opc2 = 1,
169
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
170
.accessfn = gt_vtimer_access,
171
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].ctl),
172
.resetvalue = 0,
173
- .writefn = gt_virt_ctl_write, .raw_writefn = raw_write,
174
+ .readfn = gt_virt_redir_ctl_read, .raw_readfn = raw_read,
175
+ .writefn = gt_virt_redir_ctl_write, .raw_writefn = raw_write,
176
},
177
/* TimerValue views: a 32 bit downcounting view of the underlying state */
178
{ .name = "CNTP_TVAL", .cp = 15, .crn = 14, .crm = 2, .opc1 = 0, .opc2 = 0,
179
.secure = ARM_CP_SECSTATE_NS,
180
.type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL0_RW,
181
.accessfn = gt_ptimer_access,
182
- .readfn = gt_phys_tval_read, .writefn = gt_phys_tval_write,
183
+ .readfn = gt_phys_redir_tval_read, .writefn = gt_phys_redir_tval_write,
184
},
185
{ .name = "CNTP_TVAL_S",
186
.cp = 15, .crn = 14, .crm = 2, .opc1 = 0, .opc2 = 0,
187
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
188
.opc0 = 3, .opc1 = 3, .crn = 14, .crm = 2, .opc2 = 0,
189
.type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL0_RW,
190
.accessfn = gt_ptimer_access, .resetfn = gt_phys_timer_reset,
191
- .readfn = gt_phys_tval_read, .writefn = gt_phys_tval_write,
192
+ .readfn = gt_phys_redir_tval_read, .writefn = gt_phys_redir_tval_write,
193
},
194
{ .name = "CNTV_TVAL", .cp = 15, .crn = 14, .crm = 3, .opc1 = 0, .opc2 = 0,
195
.type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL0_RW,
196
.accessfn = gt_vtimer_access,
197
- .readfn = gt_virt_tval_read, .writefn = gt_virt_tval_write,
198
+ .readfn = gt_virt_redir_tval_read, .writefn = gt_virt_redir_tval_write,
199
},
200
{ .name = "CNTV_TVAL_EL0", .state = ARM_CP_STATE_AA64,
201
.opc0 = 3, .opc1 = 3, .crn = 14, .crm = 3, .opc2 = 0,
202
.type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL0_RW,
203
.accessfn = gt_vtimer_access, .resetfn = gt_virt_timer_reset,
204
- .readfn = gt_virt_tval_read, .writefn = gt_virt_tval_write,
205
+ .readfn = gt_virt_redir_tval_read, .writefn = gt_virt_redir_tval_write,
206
},
207
/* The counter itself */
208
{ .name = "CNTPCT", .cp = 15, .crm = 14, .opc1 = 0,
209
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
210
.type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_ALIAS,
211
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
212
.accessfn = gt_ptimer_access,
213
- .writefn = gt_phys_cval_write, .raw_writefn = raw_write,
214
+ .readfn = gt_phys_redir_cval_read, .raw_readfn = raw_read,
215
+ .writefn = gt_phys_redir_cval_write, .raw_writefn = raw_write,
216
},
217
{ .name = "CNTP_CVAL_S", .cp = 15, .crm = 14, .opc1 = 2,
218
.secure = ARM_CP_SECSTATE_S,
219
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
220
.type = ARM_CP_IO,
221
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
222
.resetvalue = 0, .accessfn = gt_ptimer_access,
223
- .writefn = gt_phys_cval_write, .raw_writefn = raw_write,
224
+ .readfn = gt_phys_redir_cval_read, .raw_readfn = raw_read,
225
+ .writefn = gt_phys_redir_cval_write, .raw_writefn = raw_write,
226
},
227
{ .name = "CNTV_CVAL", .cp = 15, .crm = 14, .opc1 = 3,
228
.access = PL0_RW,
229
.type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_ALIAS,
230
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
231
.accessfn = gt_vtimer_access,
232
- .writefn = gt_virt_cval_write, .raw_writefn = raw_write,
233
+ .readfn = gt_virt_redir_cval_read, .raw_readfn = raw_read,
234
+ .writefn = gt_virt_redir_cval_write, .raw_writefn = raw_write,
235
},
236
{ .name = "CNTV_CVAL_EL0", .state = ARM_CP_STATE_AA64,
237
.opc0 = 3, .opc1 = 3, .crn = 14, .crm = 3, .opc2 = 2,
238
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
239
.type = ARM_CP_IO,
240
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
241
.resetvalue = 0, .accessfn = gt_vtimer_access,
242
- .writefn = gt_virt_cval_write, .raw_writefn = raw_write,
243
+ .readfn = gt_virt_redir_cval_read, .raw_readfn = raw_read,
244
+ .writefn = gt_virt_redir_cval_write, .raw_writefn = raw_write,
245
},
246
/* Secure timer -- this is actually restricted to only EL3
247
* and configurably Secure-EL1 via the accessfn.
248
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
249
REGINFO_SENTINEL
250
};
251
252
+static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
253
+ bool isread)
254
+{
255
+ if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
256
+ return CP_ACCESS_TRAP;
257
+ }
428
+ }
258
+ return CP_ACCESS_OK;
429
+};
259
+}
430
+
260
+
431
+static void allwinner_cpucfg_class_init(ObjectClass *klass, void *data)
261
#else
432
+{
262
433
+ DeviceClass *dc = DEVICE_CLASS(klass);
263
/* In user-mode most of the generic timer registers are inaccessible
434
+
264
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
435
+ dc->reset = allwinner_cpucfg_reset;
265
.access = PL2_RW,
436
+ dc->vmsd = &allwinner_cpucfg_vmstate;
266
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYPVIRT].ctl),
437
+}
267
.writefn = gt_hv_ctl_write, .raw_writefn = raw_write },
438
+
268
+ { .name = "CNTP_CTL_EL02", .state = ARM_CP_STATE_AA64,
439
+static const TypeInfo allwinner_cpucfg_info = {
269
+ .opc0 = 3, .opc1 = 5, .crn = 14, .crm = 2, .opc2 = 1,
440
+ .name = TYPE_AW_CPUCFG,
270
+ .type = ARM_CP_IO | ARM_CP_ALIAS,
441
+ .parent = TYPE_SYS_BUS_DEVICE,
271
+ .access = PL2_RW, .accessfn = e2h_access,
442
+ .instance_init = allwinner_cpucfg_init,
272
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].ctl),
443
+ .instance_size = sizeof(AwCpuCfgState),
273
+ .writefn = gt_phys_ctl_write, .raw_writefn = raw_write },
444
+ .class_init = allwinner_cpucfg_class_init,
274
+ { .name = "CNTV_CTL_EL02", .state = ARM_CP_STATE_AA64,
445
+};
275
+ .opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 1,
446
+
276
+ .type = ARM_CP_IO | ARM_CP_ALIAS,
447
+static void allwinner_cpucfg_register(void)
277
+ .access = PL2_RW, .accessfn = e2h_access,
448
+{
278
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].ctl),
449
+ type_register_static(&allwinner_cpucfg_info);
279
+ .writefn = gt_virt_ctl_write, .raw_writefn = raw_write },
450
+}
280
+ { .name = "CNTP_TVAL_EL02", .state = ARM_CP_STATE_AA64,
451
+
281
+ .opc0 = 3, .opc1 = 5, .crn = 14, .crm = 2, .opc2 = 0,
452
+type_init(allwinner_cpucfg_register)
282
+ .type = ARM_CP_NO_RAW | ARM_CP_IO | ARM_CP_ALIAS,
453
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
283
+ .access = PL2_RW, .accessfn = e2h_access,
454
index XXXXXXX..XXXXXXX 100644
284
+ .readfn = gt_phys_tval_read, .writefn = gt_phys_tval_write },
455
--- a/hw/misc/trace-events
285
+ { .name = "CNTV_TVAL_EL02", .state = ARM_CP_STATE_AA64,
456
+++ b/hw/misc/trace-events
286
+ .opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 0,
457
@@ -XXX,XX +XXX,XX @@
287
+ .type = ARM_CP_NO_RAW | ARM_CP_IO | ARM_CP_ALIAS,
458
# See docs/devel/tracing.txt for syntax documentation.
288
+ .access = PL2_RW, .accessfn = e2h_access,
459
289
+ .readfn = gt_virt_tval_read, .writefn = gt_virt_tval_write },
460
+# allwinner-cpucfg.c
290
+ { .name = "CNTP_CVAL_EL02", .state = ARM_CP_STATE_AA64,
461
+allwinner_cpucfg_cpu_reset(uint8_t cpu_id, uint32_t reset_addr) "id %u, reset_addr 0x%" PRIu32
291
+ .opc0 = 3, .opc1 = 5, .crn = 14, .crm = 2, .opc2 = 2,
462
+allwinner_cpucfg_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
292
+ .type = ARM_CP_IO | ARM_CP_ALIAS,
463
+allwinner_cpucfg_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
293
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
464
+
294
+ .access = PL2_RW, .accessfn = e2h_access,
465
# eccmemctl.c
295
+ .writefn = gt_phys_cval_write, .raw_writefn = raw_write },
466
ecc_mem_writel_mer(uint32_t val) "Write memory enable 0x%08x"
296
+ { .name = "CNTV_CVAL_EL02", .state = ARM_CP_STATE_AA64,
467
ecc_mem_writel_mdr(uint32_t val) "Write memory delay 0x%08x"
297
+ .opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 2,
298
+ .type = ARM_CP_IO | ARM_CP_ALIAS,
299
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
300
+ .access = PL2_RW, .accessfn = e2h_access,
301
+ .writefn = gt_virt_cval_write, .raw_writefn = raw_write },
302
#endif
303
REGINFO_SENTINEL
304
};
305
--
468
--
306
2.20.1
469
2.20.1
307
470
308
471
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
Prepare for, but do not yet implement, the EL2&0 regime.
3
The Security Identifier device found in various Allwinner System on Chip
4
This involves adding the new MMUIdx enumerators and adjusting
4
designs gives applications a per-board unique identifier. This commit
5
some of the MMUIdx related predicates to match.
5
adds support for the Allwinner Security Identifier using a 128-bit
6
6
UUID value as input.
7
Tested-by: Alex Bennée <alex.bennee@linaro.org>
7
8
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20200311221854.30370-8-nieklinnenbank@gmail.com
10
Message-id: 20200206105448.4726-20-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
12
---
13
target/arm/cpu-param.h | 2 +-
13
hw/misc/Makefile.objs | 1 +
14
target/arm/cpu.h | 134 ++++++++++++++++++-----------------------
14
include/hw/arm/allwinner-h3.h | 3 +
15
target/arm/internals.h | 35 +++++++++++
15
include/hw/misc/allwinner-sid.h | 60 ++++++++++++
16
target/arm/helper.c | 66 +++++++++++++++++---
16
hw/arm/allwinner-h3.c | 11 ++-
17
target/arm/translate.c | 1 -
17
hw/arm/orangepi.c | 8 ++
18
5 files changed, 152 insertions(+), 86 deletions(-)
18
hw/misc/allwinner-sid.c | 168 ++++++++++++++++++++++++++++++++
19
19
hw/misc/trace-events | 4 +
20
diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
20
7 files changed, 254 insertions(+), 1 deletion(-)
21
index XXXXXXX..XXXXXXX 100644
21
create mode 100644 include/hw/misc/allwinner-sid.h
22
--- a/target/arm/cpu-param.h
22
create mode 100644 hw/misc/allwinner-sid.c
23
+++ b/target/arm/cpu-param.h
23
24
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
25
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/misc/Makefile.objs
27
+++ b/hw/misc/Makefile.objs
28
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_IVSHMEM_DEVICE) += ivshmem.o
29
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-ccu.o
30
obj-$(CONFIG_ALLWINNER_H3) += allwinner-cpucfg.o
31
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-sysctrl.o
32
+common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-sid.o
33
common-obj-$(CONFIG_REALVIEW) += arm_sysctl.o
34
common-obj-$(CONFIG_NSERIES) += cbus.o
35
common-obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
36
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/hw/arm/allwinner-h3.h
39
+++ b/include/hw/arm/allwinner-h3.h
24
@@ -XXX,XX +XXX,XX @@
40
@@ -XXX,XX +XXX,XX @@
25
# define TARGET_PAGE_BITS_MIN 10
41
#include "hw/misc/allwinner-h3-ccu.h"
26
#endif
42
#include "hw/misc/allwinner-cpucfg.h"
27
43
#include "hw/misc/allwinner-h3-sysctrl.h"
28
-#define NB_MMU_MODES 8
44
+#include "hw/misc/allwinner-sid.h"
29
+#define NB_MMU_MODES 9
45
#include "target/arm/cpu.h"
30
46
31
#endif
32
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/cpu.h
35
+++ b/target/arm/cpu.h
36
@@ -XXX,XX +XXX,XX @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
37
* + NonSecure EL1 & 0 stage 1
38
* + NonSecure EL1 & 0 stage 2
39
* + NonSecure EL2
40
- * + Secure EL1 & EL0
41
+ * + NonSecure EL2 & 0 (ARMv8.1-VHE)
42
+ * + Secure EL1 & 0
43
* + Secure EL3
44
* If EL3 is 32-bit:
45
* + NonSecure PL1 & 0 stage 1
46
* + NonSecure PL1 & 0 stage 2
47
* + NonSecure PL2
48
- * + Secure PL0 & PL1
49
+ * + Secure PL0
50
+ * + Secure PL1
51
* (reminder: for 32 bit EL3, Secure PL1 is *EL3*, not EL1.)
52
*
53
* For QEMU, an mmu_idx is not quite the same as a translation regime because:
54
- * 1. we need to split the "EL1 & 0" regimes into two mmu_idxes, because they
55
- * may differ in access permissions even if the VA->PA map is the same
56
+ * 1. we need to split the "EL1 & 0" and "EL2 & 0" regimes into two mmu_idxes,
57
+ * because they may differ in access permissions even if the VA->PA map is
58
+ * the same
59
* 2. we want to cache in our TLB the full VA->IPA->PA lookup for a stage 1+2
60
* translation, which means that we have one mmu_idx that deals with two
61
* concatenated translation regimes [this sort of combined s1+2 TLB is
62
@@ -XXX,XX +XXX,XX @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
63
* 4. we can also safely fold together the "32 bit EL3" and "64 bit EL3"
64
* translation regimes, because they map reasonably well to each other
65
* and they can't both be active at the same time.
66
- * This gives us the following list of mmu_idx values:
67
+ * 5. we want to be able to use the TLB for accesses done as part of a
68
+ * stage1 page table walk, rather than having to walk the stage2 page
69
+ * table over and over.
70
*
71
- * NS EL0 (aka NS PL0) stage 1+2
72
- * NS EL1 (aka NS PL1) stage 1+2
73
+ * This gives us the following list of cases:
74
+ *
75
+ * NS EL0 EL1&0 stage 1+2 (aka NS PL0)
76
+ * NS EL1 EL1&0 stage 1+2 (aka NS PL1)
77
+ * NS EL0 EL2&0
78
+ * NS EL2 EL2&0
79
* NS EL2 (aka NS PL2)
80
+ * S EL0 EL1&0 (aka S PL0)
81
+ * S EL1 EL1&0 (not used if EL3 is 32 bit)
82
* S EL3 (aka S PL1)
83
- * S EL0 (aka S PL0)
84
- * S EL1 (not used if EL3 is 32 bit)
85
- * NS EL0+1 stage 2
86
+ * NS EL1&0 stage 2
87
*
88
- * (The last of these is an mmu_idx because we want to be able to use the TLB
89
- * for the accesses done as part of a stage 1 page table walk, rather than
90
- * having to walk the stage 2 page table over and over.)
91
+ * for a total of 9 different mmu_idx.
92
*
93
* R profile CPUs have an MPU, but can use the same set of MMU indexes
94
* as A profile. They only need to distinguish NS EL0 and NS EL1 (and
95
@@ -XXX,XX +XXX,XX @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
96
* For M profile we arrange them to have a bit for priv, a bit for negpri
97
* and a bit for secure.
98
*/
99
-#define ARM_MMU_IDX_A 0x10 /* A profile */
100
-#define ARM_MMU_IDX_NOTLB 0x20 /* does not have a TLB */
101
-#define ARM_MMU_IDX_M 0x40 /* M profile */
102
+#define ARM_MMU_IDX_A 0x10 /* A profile */
103
+#define ARM_MMU_IDX_NOTLB 0x20 /* does not have a TLB */
104
+#define ARM_MMU_IDX_M 0x40 /* M profile */
105
106
-/* meanings of the bits for M profile mmu idx values */
107
-#define ARM_MMU_IDX_M_PRIV 0x1
108
+/* Meanings of the bits for M profile mmu idx values */
109
+#define ARM_MMU_IDX_M_PRIV 0x1
110
#define ARM_MMU_IDX_M_NEGPRI 0x2
111
-#define ARM_MMU_IDX_M_S 0x4
112
+#define ARM_MMU_IDX_M_S 0x4 /* Secure */
113
114
-#define ARM_MMU_IDX_TYPE_MASK (~0x7)
115
-#define ARM_MMU_IDX_COREIDX_MASK 0x7
116
+#define ARM_MMU_IDX_TYPE_MASK \
117
+ (ARM_MMU_IDX_A | ARM_MMU_IDX_M | ARM_MMU_IDX_NOTLB)
118
+#define ARM_MMU_IDX_COREIDX_MASK 0xf
119
120
typedef enum ARMMMUIdx {
121
- ARMMMUIdx_E10_0 = 0 | ARM_MMU_IDX_A,
122
- ARMMMUIdx_E10_1 = 1 | ARM_MMU_IDX_A,
123
- ARMMMUIdx_E2 = 2 | ARM_MMU_IDX_A,
124
- ARMMMUIdx_SE3 = 3 | ARM_MMU_IDX_A,
125
- ARMMMUIdx_SE10_0 = 4 | ARM_MMU_IDX_A,
126
- ARMMMUIdx_SE10_1 = 5 | ARM_MMU_IDX_A,
127
- ARMMMUIdx_Stage2 = 6 | ARM_MMU_IDX_A,
128
+ /*
129
+ * A-profile.
130
+ */
131
+ ARMMMUIdx_E10_0 = 0 | ARM_MMU_IDX_A,
132
+ ARMMMUIdx_E20_0 = 1 | ARM_MMU_IDX_A,
133
+
134
+ ARMMMUIdx_E10_1 = 2 | ARM_MMU_IDX_A,
135
+
136
+ ARMMMUIdx_E2 = 3 | ARM_MMU_IDX_A,
137
+ ARMMMUIdx_E20_2 = 4 | ARM_MMU_IDX_A,
138
+
139
+ ARMMMUIdx_SE10_0 = 5 | ARM_MMU_IDX_A,
140
+ ARMMMUIdx_SE10_1 = 6 | ARM_MMU_IDX_A,
141
+ ARMMMUIdx_SE3 = 7 | ARM_MMU_IDX_A,
142
+
143
+ ARMMMUIdx_Stage2 = 8 | ARM_MMU_IDX_A,
144
+
145
+ /*
146
+ * These are not allocated TLBs and are used only for AT system
147
+ * instructions or for the first stage of an S12 page table walk.
148
+ */
149
+ ARMMMUIdx_Stage1_E0 = 0 | ARM_MMU_IDX_NOTLB,
150
+ ARMMMUIdx_Stage1_E1 = 1 | ARM_MMU_IDX_NOTLB,
151
+
152
+ /*
153
+ * M-profile.
154
+ */
155
ARMMMUIdx_MUser = ARM_MMU_IDX_M,
156
ARMMMUIdx_MPriv = ARM_MMU_IDX_M | ARM_MMU_IDX_M_PRIV,
157
ARMMMUIdx_MUserNegPri = ARMMMUIdx_MUser | ARM_MMU_IDX_M_NEGPRI,
158
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdx {
159
ARMMMUIdx_MSPriv = ARMMMUIdx_MPriv | ARM_MMU_IDX_M_S,
160
ARMMMUIdx_MSUserNegPri = ARMMMUIdx_MUserNegPri | ARM_MMU_IDX_M_S,
161
ARMMMUIdx_MSPrivNegPri = ARMMMUIdx_MPrivNegPri | ARM_MMU_IDX_M_S,
162
- /* Indexes below here don't have TLBs and are used only for AT system
163
- * instructions or for the first stage of an S12 page table walk.
164
- */
165
- ARMMMUIdx_Stage1_E0 = 0 | ARM_MMU_IDX_NOTLB,
166
- ARMMMUIdx_Stage1_E1 = 1 | ARM_MMU_IDX_NOTLB,
167
} ARMMMUIdx;
168
169
/*
170
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdx {
171
172
typedef enum ARMMMUIdxBit {
173
TO_CORE_BIT(E10_0),
174
+ TO_CORE_BIT(E20_0),
175
TO_CORE_BIT(E10_1),
176
TO_CORE_BIT(E2),
177
+ TO_CORE_BIT(E20_2),
178
TO_CORE_BIT(SE10_0),
179
TO_CORE_BIT(SE10_1),
180
TO_CORE_BIT(SE3),
181
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdxBit {
182
183
#define MMU_USER_IDX 0
184
185
-static inline int arm_to_core_mmu_idx(ARMMMUIdx mmu_idx)
186
-{
187
- return mmu_idx & ARM_MMU_IDX_COREIDX_MASK;
188
-}
189
-
190
-static inline ARMMMUIdx core_to_arm_mmu_idx(CPUARMState *env, int mmu_idx)
191
-{
192
- if (arm_feature(env, ARM_FEATURE_M)) {
193
- return mmu_idx | ARM_MMU_IDX_M;
194
- } else {
195
- return mmu_idx | ARM_MMU_IDX_A;
196
- }
197
-}
198
-
199
-/* Return the exception level we're running at if this is our mmu_idx */
200
-static inline int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
201
-{
202
- switch (mmu_idx & ARM_MMU_IDX_TYPE_MASK) {
203
- case ARM_MMU_IDX_A:
204
- return mmu_idx & 3;
205
- case ARM_MMU_IDX_M:
206
- return mmu_idx & ARM_MMU_IDX_M_PRIV;
207
- default:
208
- g_assert_not_reached();
209
- }
210
-}
211
-
212
-/*
213
- * Return the MMU index for a v7M CPU with all relevant information
214
- * manually specified.
215
- */
216
-ARMMMUIdx arm_v7m_mmu_idx_all(CPUARMState *env,
217
- bool secstate, bool priv, bool negpri);
218
-
219
-/* Return the MMU index for a v7M CPU in the specified security and
220
- * privilege state.
221
- */
222
-ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env,
223
- bool secstate, bool priv);
224
-
225
-/* Return the MMU index for a v7M CPU in the specified security state */
226
-ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate);
227
-
228
/**
47
/**
229
* cpu_mmu_index:
48
@@ -XXX,XX +XXX,XX @@ enum {
230
* @env: The cpu environment
49
AW_H3_SRAM_A2,
231
diff --git a/target/arm/internals.h b/target/arm/internals.h
50
AW_H3_SRAM_C,
232
index XXXXXXX..XXXXXXX 100644
51
AW_H3_SYSCTRL,
233
--- a/target/arm/internals.h
52
+ AW_H3_SID,
234
+++ b/target/arm/internals.h
53
AW_H3_EHCI0,
235
@@ -XXX,XX +XXX,XX @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
54
AW_H3_OHCI0,
236
MMUAccessType access_type, int mmu_idx,
55
AW_H3_EHCI1,
237
bool probe, uintptr_t retaddr);
56
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
238
57
AwH3ClockCtlState ccu;
239
+static inline int arm_to_core_mmu_idx(ARMMMUIdx mmu_idx)
58
AwCpuCfgState cpucfg;
240
+{
59
AwH3SysCtrlState sysctrl;
241
+ return mmu_idx & ARM_MMU_IDX_COREIDX_MASK;
60
+ AwSidState sid;
242
+}
61
GICState gic;
243
+
62
MemoryRegion sram_a1;
244
+static inline ARMMMUIdx core_to_arm_mmu_idx(CPUARMState *env, int mmu_idx)
63
MemoryRegion sram_a2;
245
+{
64
diff --git a/include/hw/misc/allwinner-sid.h b/include/hw/misc/allwinner-sid.h
246
+ if (arm_feature(env, ARM_FEATURE_M)) {
65
new file mode 100644
247
+ return mmu_idx | ARM_MMU_IDX_M;
66
index XXXXXXX..XXXXXXX
248
+ } else {
67
--- /dev/null
249
+ return mmu_idx | ARM_MMU_IDX_A;
68
+++ b/include/hw/misc/allwinner-sid.h
69
@@ -XXX,XX +XXX,XX @@
70
+/*
71
+ * Allwinner Security ID emulation
72
+ *
73
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
74
+ *
75
+ * This program is free software: you can redistribute it and/or modify
76
+ * it under the terms of the GNU General Public License as published by
77
+ * the Free Software Foundation, either version 2 of the License, or
78
+ * (at your option) any later version.
79
+ *
80
+ * This program is distributed in the hope that it will be useful,
81
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
82
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
83
+ * GNU General Public License for more details.
84
+ *
85
+ * You should have received a copy of the GNU General Public License
86
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
87
+ */
88
+
89
+#ifndef HW_MISC_ALLWINNER_SID_H
90
+#define HW_MISC_ALLWINNER_SID_H
91
+
92
+#include "qom/object.h"
93
+#include "hw/sysbus.h"
94
+#include "qemu/uuid.h"
95
+
96
+/**
97
+ * Object model
98
+ * @{
99
+ */
100
+
101
+#define TYPE_AW_SID "allwinner-sid"
102
+#define AW_SID(obj) \
103
+ OBJECT_CHECK(AwSidState, (obj), TYPE_AW_SID)
104
+
105
+/** @} */
106
+
107
+/**
108
+ * Allwinner Security ID object instance state
109
+ */
110
+typedef struct AwSidState {
111
+ /*< private >*/
112
+ SysBusDevice parent_obj;
113
+ /*< public >*/
114
+
115
+ /** Maps I/O registers in physical memory */
116
+ MemoryRegion iomem;
117
+
118
+ /** Control register defines how and what to read */
119
+ uint32_t control;
120
+
121
+ /** RdKey register contains the data retrieved by the device */
122
+ uint32_t rdkey;
123
+
124
+ /** Stores the emulated device identifier */
125
+ QemuUUID identifier;
126
+
127
+} AwSidState;
128
+
129
+#endif /* HW_MISC_ALLWINNER_SID_H */
130
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/hw/arm/allwinner-h3.c
133
+++ b/hw/arm/allwinner-h3.c
134
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
135
[AW_H3_SRAM_A2] = 0x00044000,
136
[AW_H3_SRAM_C] = 0x00010000,
137
[AW_H3_SYSCTRL] = 0x01c00000,
138
+ [AW_H3_SID] = 0x01c14000,
139
[AW_H3_EHCI0] = 0x01c1a000,
140
[AW_H3_OHCI0] = 0x01c1a400,
141
[AW_H3_EHCI1] = 0x01c1b000,
142
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
143
{ "mmc0", 0x01c0f000, 4 * KiB },
144
{ "mmc1", 0x01c10000, 4 * KiB },
145
{ "mmc2", 0x01c11000, 4 * KiB },
146
- { "sid", 0x01c14000, 1 * KiB },
147
{ "crypto", 0x01c15000, 4 * KiB },
148
{ "msgbox", 0x01c17000, 4 * KiB },
149
{ "spinlock", 0x01c18000, 4 * KiB },
150
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
151
152
sysbus_init_child_obj(obj, "cpucfg", &s->cpucfg, sizeof(s->cpucfg),
153
TYPE_AW_CPUCFG);
154
+
155
+ sysbus_init_child_obj(obj, "sid", &s->sid, sizeof(s->sid),
156
+ TYPE_AW_SID);
157
+ object_property_add_alias(obj, "identifier", OBJECT(&s->sid),
158
+ "identifier", &error_abort);
159
}
160
161
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
162
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
163
qdev_init_nofail(DEVICE(&s->cpucfg));
164
sysbus_mmio_map(SYS_BUS_DEVICE(&s->cpucfg), 0, s->memmap[AW_H3_CPUCFG]);
165
166
+ /* Security Identifier */
167
+ qdev_init_nofail(DEVICE(&s->sid));
168
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->sid), 0, s->memmap[AW_H3_SID]);
169
+
170
/* Universal Serial Bus */
171
sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI0],
172
qdev_get_gpio_in(DEVICE(&s->gic),
173
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
174
index XXXXXXX..XXXXXXX 100644
175
--- a/hw/arm/orangepi.c
176
+++ b/hw/arm/orangepi.c
177
@@ -XXX,XX +XXX,XX @@ static void orangepi_init(MachineState *machine)
178
object_property_set_int(OBJECT(h3), 24 * 1000 * 1000, "clk1-freq",
179
&error_abort);
180
181
+ /* Setup SID properties. Currently using a default fixed SID identifier. */
182
+ if (qemu_uuid_is_null(&h3->sid.identifier)) {
183
+ qdev_prop_set_string(DEVICE(h3), "identifier",
184
+ "02c00081-1111-2222-3333-000044556677");
185
+ } else if (ldl_be_p(&h3->sid.identifier.data[0]) != 0x02c00081) {
186
+ warn_report("Security Identifier value does not include H3 prefix");
250
+ }
187
+ }
251
+}
188
+
252
+
189
/* Mark H3 object realized */
253
+int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx);
190
object_property_set_bool(OBJECT(h3), true, "realized", &error_abort);
254
+
191
192
diff --git a/hw/misc/allwinner-sid.c b/hw/misc/allwinner-sid.c
193
new file mode 100644
194
index XXXXXXX..XXXXXXX
195
--- /dev/null
196
+++ b/hw/misc/allwinner-sid.c
197
@@ -XXX,XX +XXX,XX @@
255
+/*
198
+/*
256
+ * Return the MMU index for a v7M CPU with all relevant information
199
+ * Allwinner Security ID emulation
257
+ * manually specified.
200
+ *
201
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
202
+ *
203
+ * This program is free software: you can redistribute it and/or modify
204
+ * it under the terms of the GNU General Public License as published by
205
+ * the Free Software Foundation, either version 2 of the License, or
206
+ * (at your option) any later version.
207
+ *
208
+ * This program is distributed in the hope that it will be useful,
209
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
210
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
211
+ * GNU General Public License for more details.
212
+ *
213
+ * You should have received a copy of the GNU General Public License
214
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
258
+ */
215
+ */
259
+ARMMMUIdx arm_v7m_mmu_idx_all(CPUARMState *env,
216
+
260
+ bool secstate, bool priv, bool negpri);
217
+#include "qemu/osdep.h"
261
+
218
+#include "qemu/units.h"
262
+/*
219
+#include "hw/sysbus.h"
263
+ * Return the MMU index for a v7M CPU in the specified security and
220
+#include "migration/vmstate.h"
264
+ * privilege state.
221
+#include "qemu/log.h"
265
+ */
222
+#include "qemu/module.h"
266
+ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env,
223
+#include "qemu/guest-random.h"
267
+ bool secstate, bool priv);
224
+#include "qapi/error.h"
268
+
225
+#include "hw/qdev-properties.h"
269
+/* Return the MMU index for a v7M CPU in the specified security state */
226
+#include "hw/misc/allwinner-sid.h"
270
+ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate);
227
+#include "trace.h"
271
+
228
+
272
/* Return true if the stage 1 translation regime is using LPAE format page
229
+/* SID register offsets */
273
* tables */
230
+enum {
274
bool arm_s1_regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx);
231
+ REG_PRCTL = 0x40, /* Control */
275
@@ -XXX,XX +XXX,XX @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
232
+ REG_RDKEY = 0x60, /* Read Key */
276
switch (mmu_idx) {
233
+};
277
case ARMMMUIdx_E10_0:
234
+
278
case ARMMMUIdx_E10_1:
235
+/* SID register flags */
279
+ case ARMMMUIdx_E20_0:
236
+enum {
280
+ case ARMMMUIdx_E20_2:
237
+ REG_PRCTL_WRITE = 0x0002, /* Unknown write flag */
281
case ARMMMUIdx_Stage1_E0:
238
+ REG_PRCTL_OP_LOCK = 0xAC00, /* Lock operation */
282
case ARMMMUIdx_Stage1_E1:
239
+};
283
case ARMMMUIdx_E2:
240
+
284
diff --git a/target/arm/helper.c b/target/arm/helper.c
241
+static uint64_t allwinner_sid_read(void *opaque, hwaddr offset,
285
index XXXXXXX..XXXXXXX 100644
242
+ unsigned size)
286
--- a/target/arm/helper.c
243
+{
287
+++ b/target/arm/helper.c
244
+ const AwSidState *s = AW_SID(opaque);
288
@@ -XXX,XX +XXX,XX @@ void arm_cpu_do_interrupt(CPUState *cs)
245
+ uint64_t val = 0;
289
#endif /* !CONFIG_USER_ONLY */
246
+
290
247
+ switch (offset) {
291
/* Return the exception level which controls this address translation regime */
248
+ case REG_PRCTL: /* Control */
292
-static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
249
+ val = s->control;
293
+static uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
250
+ break;
294
{
251
+ case REG_RDKEY: /* Read Key */
295
switch (mmu_idx) {
252
+ val = s->rdkey;
296
+ case ARMMMUIdx_E20_0:
253
+ break;
297
+ case ARMMMUIdx_E20_2:
298
case ARMMMUIdx_Stage2:
299
case ARMMMUIdx_E2:
300
return 2;
301
@@ -XXX,XX +XXX,XX @@ static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
302
case ARMMMUIdx_SE10_1:
303
case ARMMMUIdx_Stage1_E0:
304
case ARMMMUIdx_Stage1_E1:
305
+ case ARMMMUIdx_E10_0:
306
+ case ARMMMUIdx_E10_1:
307
case ARMMMUIdx_MPrivNegPri:
308
case ARMMMUIdx_MUserNegPri:
309
case ARMMMUIdx_MPriv:
310
@@ -XXX,XX +XXX,XX @@ static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
311
*/
312
static inline ARMMMUIdx stage_1_mmu_idx(ARMMMUIdx mmu_idx)
313
{
314
- if (mmu_idx == ARMMMUIdx_E10_0 || mmu_idx == ARMMMUIdx_E10_1) {
315
- mmu_idx += (ARMMMUIdx_Stage1_E0 - ARMMMUIdx_E10_0);
316
+ switch (mmu_idx) {
317
+ case ARMMMUIdx_E10_0:
318
+ return ARMMMUIdx_Stage1_E0;
319
+ case ARMMMUIdx_E10_1:
320
+ return ARMMMUIdx_Stage1_E1;
321
+ default:
254
+ default:
322
+ return mmu_idx;
255
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
323
}
256
+ __func__, (uint32_t)offset);
324
- return mmu_idx;
257
+ return 0;
325
}
326
327
/* Return true if the translation regime is using LPAE format page tables */
328
@@ -XXX,XX +XXX,XX @@ static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
329
{
330
switch (mmu_idx) {
331
case ARMMMUIdx_SE10_0:
332
+ case ARMMMUIdx_E20_0:
333
case ARMMMUIdx_Stage1_E0:
334
case ARMMMUIdx_MUser:
335
case ARMMMUIdx_MSUser:
336
@@ -XXX,XX +XXX,XX @@ int fp_exception_el(CPUARMState *env, int cur_el)
337
return 0;
338
}
339
340
+/* Return the exception level we're running at if this is our mmu_idx */
341
+int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
342
+{
343
+ if (mmu_idx & ARM_MMU_IDX_M) {
344
+ return mmu_idx & ARM_MMU_IDX_M_PRIV;
345
+ }
258
+ }
346
+
259
+
347
+ switch (mmu_idx) {
260
+ trace_allwinner_sid_read(offset, val, size);
348
+ case ARMMMUIdx_E10_0:
261
+
349
+ case ARMMMUIdx_E20_0:
262
+ return val;
350
+ case ARMMMUIdx_SE10_0:
263
+}
351
+ return 0;
264
+
352
+ case ARMMMUIdx_E10_1:
265
+static void allwinner_sid_write(void *opaque, hwaddr offset,
353
+ case ARMMMUIdx_SE10_1:
266
+ uint64_t val, unsigned size)
354
+ return 1;
267
+{
355
+ case ARMMMUIdx_E2:
268
+ AwSidState *s = AW_SID(opaque);
356
+ case ARMMMUIdx_E20_2:
269
+
357
+ return 2;
270
+ trace_allwinner_sid_write(offset, val, size);
358
+ case ARMMMUIdx_SE3:
271
+
359
+ return 3;
272
+ switch (offset) {
273
+ case REG_PRCTL: /* Control */
274
+ s->control = val;
275
+
276
+ if ((s->control & REG_PRCTL_OP_LOCK) &&
277
+ (s->control & REG_PRCTL_WRITE)) {
278
+ uint32_t id = s->control >> 16;
279
+
280
+ if (id <= sizeof(QemuUUID) - sizeof(s->rdkey)) {
281
+ s->rdkey = ldl_be_p(&s->identifier.data[id]);
282
+ }
283
+ }
284
+ s->control &= ~REG_PRCTL_WRITE;
285
+ break;
286
+ case REG_RDKEY: /* Read Key */
287
+ break;
360
+ default:
288
+ default:
361
+ g_assert_not_reached();
289
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
290
+ __func__, (uint32_t)offset);
291
+ break;
362
+ }
292
+ }
363
+}
293
+}
364
+
294
+
365
#ifndef CONFIG_TCG
295
+static const MemoryRegionOps allwinner_sid_ops = {
366
ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate)
296
+ .read = allwinner_sid_read,
367
{
297
+ .write = allwinner_sid_write,
368
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
298
+ .endianness = DEVICE_NATIVE_ENDIAN,
369
return arm_v7m_mmu_idx_for_secstate(env, env->v7m.secure);
299
+ .valid = {
370
}
300
+ .min_access_size = 4,
371
301
+ .max_access_size = 4,
372
- if (el < 2 && arm_is_secure_below_el3(env)) {
302
+ },
373
- return ARMMMUIdx_SE10_0 + el;
303
+ .impl.min_access_size = 4,
374
- } else {
304
+};
375
- return ARMMMUIdx_E10_0 + el;
305
+
376
+ switch (el) {
306
+static void allwinner_sid_reset(DeviceState *dev)
377
+ case 0:
307
+{
378
+ /* TODO: ARMv8.1-VHE */
308
+ AwSidState *s = AW_SID(dev);
379
+ if (arm_is_secure_below_el3(env)) {
309
+
380
+ return ARMMMUIdx_SE10_0;
310
+ /* Set default values for registers */
381
+ }
311
+ s->control = 0;
382
+ return ARMMMUIdx_E10_0;
312
+ s->rdkey = 0;
383
+ case 1:
313
+}
384
+ if (arm_is_secure_below_el3(env)) {
314
+
385
+ return ARMMMUIdx_SE10_1;
315
+static void allwinner_sid_init(Object *obj)
386
+ }
316
+{
387
+ return ARMMMUIdx_E10_1;
317
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
388
+ case 2:
318
+ AwSidState *s = AW_SID(obj);
389
+ /* TODO: ARMv8.1-VHE */
319
+
390
+ /* TODO: ARMv8.4-SecEL2 */
320
+ /* Memory mapping */
391
+ return ARMMMUIdx_E2;
321
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_sid_ops, s,
392
+ case 3:
322
+ TYPE_AW_SID, 1 * KiB);
393
+ return ARMMMUIdx_SE3;
323
+ sysbus_init_mmio(sbd, &s->iomem);
394
+ default:
324
+}
395
+ g_assert_not_reached();
325
+
396
}
326
+static Property allwinner_sid_properties[] = {
397
}
327
+ DEFINE_PROP_UUID_NODEFAULT("identifier", AwSidState, identifier),
398
328
+ DEFINE_PROP_END_OF_LIST()
399
diff --git a/target/arm/translate.c b/target/arm/translate.c
329
+};
400
index XXXXXXX..XXXXXXX 100644
330
+
401
--- a/target/arm/translate.c
331
+static const VMStateDescription allwinner_sid_vmstate = {
402
+++ b/target/arm/translate.c
332
+ .name = "allwinner-sid",
403
@@ -XXX,XX +XXX,XX @@ static inline int get_a32_user_mem_index(DisasContext *s)
333
+ .version_id = 1,
404
case ARMMMUIdx_MSUserNegPri:
334
+ .minimum_version_id = 1,
405
case ARMMMUIdx_MSPrivNegPri:
335
+ .fields = (VMStateField[]) {
406
return arm_to_core_mmu_idx(ARMMMUIdx_MSUserNegPri);
336
+ VMSTATE_UINT32(control, AwSidState),
407
- case ARMMMUIdx_Stage2:
337
+ VMSTATE_UINT32(rdkey, AwSidState),
408
default:
338
+ VMSTATE_UINT8_ARRAY_V(identifier.data, AwSidState, sizeof(QemuUUID), 1),
409
g_assert_not_reached();
339
+ VMSTATE_END_OF_LIST()
410
}
340
+ }
341
+};
342
+
343
+static void allwinner_sid_class_init(ObjectClass *klass, void *data)
344
+{
345
+ DeviceClass *dc = DEVICE_CLASS(klass);
346
+
347
+ dc->reset = allwinner_sid_reset;
348
+ dc->vmsd = &allwinner_sid_vmstate;
349
+ device_class_set_props(dc, allwinner_sid_properties);
350
+}
351
+
352
+static const TypeInfo allwinner_sid_info = {
353
+ .name = TYPE_AW_SID,
354
+ .parent = TYPE_SYS_BUS_DEVICE,
355
+ .instance_init = allwinner_sid_init,
356
+ .instance_size = sizeof(AwSidState),
357
+ .class_init = allwinner_sid_class_init,
358
+};
359
+
360
+static void allwinner_sid_register(void)
361
+{
362
+ type_register_static(&allwinner_sid_info);
363
+}
364
+
365
+type_init(allwinner_sid_register)
366
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
367
index XXXXXXX..XXXXXXX 100644
368
--- a/hw/misc/trace-events
369
+++ b/hw/misc/trace-events
370
@@ -XXX,XX +XXX,XX @@ allwinner_cpucfg_cpu_reset(uint8_t cpu_id, uint32_t reset_addr) "id %u, reset_ad
371
allwinner_cpucfg_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
372
allwinner_cpucfg_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
373
374
+# allwinner-sid.c
375
+allwinner_sid_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
376
+allwinner_sid_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
377
+
378
# eccmemctl.c
379
ecc_mem_writel_mer(uint32_t val) "Write memory enable 0x%08x"
380
ecc_mem_writel_mdr(uint32_t val) "Write memory delay 0x%08x"
411
--
381
--
412
2.20.1
382
2.20.1
413
383
414
384
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
This inline function has one user in cpu.c, and need not be exposed
3
The Allwinner System on Chip families sun4i and above contain
4
otherwise. Code movement only, with fixups for checkpatch.
4
an integrated storage controller for Secure Digital (SD) and
5
Multi Media Card (MMC) interfaces. This commit adds support
6
for the Allwinner SD/MMC storage controller with the following
7
emulated features:
5
8
6
Tested-by: Alex Bennée <alex.bennee@linaro.org>
9
* DMA transfers
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
* Direct FIFO I/O
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
* Short/Long format command responses
9
Message-id: 20200206105448.4726-39-richard.henderson@linaro.org
12
* Auto-Stop command (CMD12)
13
* Insert & remove card detection
14
15
The following boards are extended with the SD host controller:
16
17
* Cubieboard (hw/arm/cubieboard.c)
18
* Orange Pi PC (hw/arm/orangepi.c)
19
20
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
21
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
22
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
23
Message-id: 20200311221854.30370-9-nieklinnenbank@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
25
---
12
target/arm/cpu.h | 111 -------------------------------------------
26
hw/sd/Makefile.objs | 1 +
13
target/arm/cpu.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++
27
include/hw/arm/allwinner-a10.h | 2 +
14
2 files changed, 119 insertions(+), 111 deletions(-)
28
include/hw/arm/allwinner-h3.h | 3 +
29
include/hw/sd/allwinner-sdhost.h | 135 +++++
30
hw/arm/allwinner-a10.c | 11 +
31
hw/arm/allwinner-h3.c | 15 +-
32
hw/arm/cubieboard.c | 15 +
33
hw/arm/orangepi.c | 16 +
34
hw/sd/allwinner-sdhost.c | 854 +++++++++++++++++++++++++++++++
35
hw/arm/Kconfig | 1 +
36
hw/sd/trace-events | 7 +
37
11 files changed, 1059 insertions(+), 1 deletion(-)
38
create mode 100644 include/hw/sd/allwinner-sdhost.h
39
create mode 100644 hw/sd/allwinner-sdhost.c
15
40
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
41
diff --git a/hw/sd/Makefile.objs b/hw/sd/Makefile.objs
17
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
43
--- a/hw/sd/Makefile.objs
19
+++ b/target/arm/cpu.h
44
+++ b/hw/sd/Makefile.objs
20
@@ -XXX,XX +XXX,XX @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
45
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_SD) += sd.o core.o sdmmc-internal.o
21
#define ARM_CPUID_TI915T 0x54029152
46
common-obj-$(CONFIG_SDHCI) += sdhci.o
22
#define ARM_CPUID_TI925T 0x54029252
47
common-obj-$(CONFIG_SDHCI_PCI) += sdhci-pci.o
23
48
24
-static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
49
+common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-sdhost.o
25
- unsigned int target_el)
50
common-obj-$(CONFIG_MILKYMIST) += milkymist-memcard.o
26
-{
51
common-obj-$(CONFIG_OMAP) += omap_mmc.o
27
- CPUARMState *env = cs->env_ptr;
52
common-obj-$(CONFIG_PXA2XX) += pxa2xx_mmci.o
28
- unsigned int cur_el = arm_current_el(env);
53
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
29
- bool secure = arm_is_secure(env);
30
- bool pstate_unmasked;
31
- int8_t unmasked = 0;
32
- uint64_t hcr_el2;
33
-
34
- /* Don't take exceptions if they target a lower EL.
35
- * This check should catch any exceptions that would not be taken but left
36
- * pending.
37
- */
38
- if (cur_el > target_el) {
39
- return false;
40
- }
41
-
42
- hcr_el2 = arm_hcr_el2_eff(env);
43
-
44
- switch (excp_idx) {
45
- case EXCP_FIQ:
46
- pstate_unmasked = !(env->daif & PSTATE_F);
47
- break;
48
-
49
- case EXCP_IRQ:
50
- pstate_unmasked = !(env->daif & PSTATE_I);
51
- break;
52
-
53
- case EXCP_VFIQ:
54
- if (secure || !(hcr_el2 & HCR_FMO) || (hcr_el2 & HCR_TGE)) {
55
- /* VFIQs are only taken when hypervized and non-secure. */
56
- return false;
57
- }
58
- return !(env->daif & PSTATE_F);
59
- case EXCP_VIRQ:
60
- if (secure || !(hcr_el2 & HCR_IMO) || (hcr_el2 & HCR_TGE)) {
61
- /* VIRQs are only taken when hypervized and non-secure. */
62
- return false;
63
- }
64
- return !(env->daif & PSTATE_I);
65
- default:
66
- g_assert_not_reached();
67
- }
68
-
69
- /* Use the target EL, current execution state and SCR/HCR settings to
70
- * determine whether the corresponding CPSR bit is used to mask the
71
- * interrupt.
72
- */
73
- if ((target_el > cur_el) && (target_el != 1)) {
74
- /* Exceptions targeting a higher EL may not be maskable */
75
- if (arm_feature(env, ARM_FEATURE_AARCH64)) {
76
- /* 64-bit masking rules are simple: exceptions to EL3
77
- * can't be masked, and exceptions to EL2 can only be
78
- * masked from Secure state. The HCR and SCR settings
79
- * don't affect the masking logic, only the interrupt routing.
80
- */
81
- if (target_el == 3 || !secure) {
82
- unmasked = 1;
83
- }
84
- } else {
85
- /* The old 32-bit-only environment has a more complicated
86
- * masking setup. HCR and SCR bits not only affect interrupt
87
- * routing but also change the behaviour of masking.
88
- */
89
- bool hcr, scr;
90
-
91
- switch (excp_idx) {
92
- case EXCP_FIQ:
93
- /* If FIQs are routed to EL3 or EL2 then there are cases where
94
- * we override the CPSR.F in determining if the exception is
95
- * masked or not. If neither of these are set then we fall back
96
- * to the CPSR.F setting otherwise we further assess the state
97
- * below.
98
- */
99
- hcr = hcr_el2 & HCR_FMO;
100
- scr = (env->cp15.scr_el3 & SCR_FIQ);
101
-
102
- /* When EL3 is 32-bit, the SCR.FW bit controls whether the
103
- * CPSR.F bit masks FIQ interrupts when taken in non-secure
104
- * state. If SCR.FW is set then FIQs can be masked by CPSR.F
105
- * when non-secure but only when FIQs are only routed to EL3.
106
- */
107
- scr = scr && !((env->cp15.scr_el3 & SCR_FW) && !hcr);
108
- break;
109
- case EXCP_IRQ:
110
- /* When EL3 execution state is 32-bit, if HCR.IMO is set then
111
- * we may override the CPSR.I masking when in non-secure state.
112
- * The SCR.IRQ setting has already been taken into consideration
113
- * when setting the target EL, so it does not have a further
114
- * affect here.
115
- */
116
- hcr = hcr_el2 & HCR_IMO;
117
- scr = false;
118
- break;
119
- default:
120
- g_assert_not_reached();
121
- }
122
-
123
- if ((scr || hcr) && !secure) {
124
- unmasked = 1;
125
- }
126
- }
127
- }
128
-
129
- /* The PSTATE bits only mask the interrupt if we have not overriden the
130
- * ability above.
131
- */
132
- return unmasked || pstate_unmasked;
133
-}
134
-
135
#define ARM_CPU_TYPE_SUFFIX "-" TYPE_ARM_CPU
136
#define ARM_CPU_TYPE_NAME(name) (name ARM_CPU_TYPE_SUFFIX)
137
#define CPU_RESOLVING_TYPE TYPE_ARM_CPU
138
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
139
index XXXXXXX..XXXXXXX 100644
54
index XXXXXXX..XXXXXXX 100644
140
--- a/target/arm/cpu.c
55
--- a/include/hw/arm/allwinner-a10.h
141
+++ b/target/arm/cpu.c
56
+++ b/include/hw/arm/allwinner-a10.h
142
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
57
@@ -XXX,XX +XXX,XX @@
143
arm_rebuild_hflags(env);
58
#include "hw/timer/allwinner-a10-pit.h"
59
#include "hw/intc/allwinner-a10-pic.h"
60
#include "hw/net/allwinner_emac.h"
61
+#include "hw/sd/allwinner-sdhost.h"
62
#include "hw/ide/ahci.h"
63
#include "hw/usb/hcd-ohci.h"
64
#include "hw/usb/hcd-ehci.h"
65
@@ -XXX,XX +XXX,XX @@ typedef struct AwA10State {
66
AwA10PICState intc;
67
AwEmacState emac;
68
AllwinnerAHCIState sata;
69
+ AwSdHostState mmc0;
70
MemoryRegion sram_a;
71
EHCISysBusState ehci[AW_A10_NUM_USB];
72
OHCISysBusState ohci[AW_A10_NUM_USB];
73
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
74
index XXXXXXX..XXXXXXX 100644
75
--- a/include/hw/arm/allwinner-h3.h
76
+++ b/include/hw/arm/allwinner-h3.h
77
@@ -XXX,XX +XXX,XX @@
78
#include "hw/misc/allwinner-cpucfg.h"
79
#include "hw/misc/allwinner-h3-sysctrl.h"
80
#include "hw/misc/allwinner-sid.h"
81
+#include "hw/sd/allwinner-sdhost.h"
82
#include "target/arm/cpu.h"
83
84
/**
85
@@ -XXX,XX +XXX,XX @@ enum {
86
AW_H3_SRAM_A2,
87
AW_H3_SRAM_C,
88
AW_H3_SYSCTRL,
89
+ AW_H3_MMC0,
90
AW_H3_SID,
91
AW_H3_EHCI0,
92
AW_H3_OHCI0,
93
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
94
AwCpuCfgState cpucfg;
95
AwH3SysCtrlState sysctrl;
96
AwSidState sid;
97
+ AwSdHostState mmc0;
98
GICState gic;
99
MemoryRegion sram_a1;
100
MemoryRegion sram_a2;
101
diff --git a/include/hw/sd/allwinner-sdhost.h b/include/hw/sd/allwinner-sdhost.h
102
new file mode 100644
103
index XXXXXXX..XXXXXXX
104
--- /dev/null
105
+++ b/include/hw/sd/allwinner-sdhost.h
106
@@ -XXX,XX +XXX,XX @@
107
+/*
108
+ * Allwinner (sun4i and above) SD Host Controller emulation
109
+ *
110
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
111
+ *
112
+ * This program is free software: you can redistribute it and/or modify
113
+ * it under the terms of the GNU General Public License as published by
114
+ * the Free Software Foundation, either version 2 of the License, or
115
+ * (at your option) any later version.
116
+ *
117
+ * This program is distributed in the hope that it will be useful,
118
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
119
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
120
+ * GNU General Public License for more details.
121
+ *
122
+ * You should have received a copy of the GNU General Public License
123
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
124
+ */
125
+
126
+#ifndef HW_SD_ALLWINNER_SDHOST_H
127
+#define HW_SD_ALLWINNER_SDHOST_H
128
+
129
+#include "qom/object.h"
130
+#include "hw/sysbus.h"
131
+#include "hw/sd/sd.h"
132
+
133
+/**
134
+ * Object model types
135
+ * @{
136
+ */
137
+
138
+/** Generic Allwinner SD Host Controller (abstract) */
139
+#define TYPE_AW_SDHOST "allwinner-sdhost"
140
+
141
+/** Allwinner sun4i family (A10, A12) */
142
+#define TYPE_AW_SDHOST_SUN4I TYPE_AW_SDHOST "-sun4i"
143
+
144
+/** Allwinner sun5i family and newer (A13, H2+, H3, etc) */
145
+#define TYPE_AW_SDHOST_SUN5I TYPE_AW_SDHOST "-sun5i"
146
+
147
+/** @} */
148
+
149
+/**
150
+ * Object model macros
151
+ * @{
152
+ */
153
+
154
+#define AW_SDHOST(obj) \
155
+ OBJECT_CHECK(AwSdHostState, (obj), TYPE_AW_SDHOST)
156
+#define AW_SDHOST_CLASS(klass) \
157
+ OBJECT_CLASS_CHECK(AwSdHostClass, (klass), TYPE_AW_SDHOST)
158
+#define AW_SDHOST_GET_CLASS(obj) \
159
+ OBJECT_GET_CLASS(AwSdHostClass, (obj), TYPE_AW_SDHOST)
160
+
161
+/** @} */
162
+
163
+/**
164
+ * Allwinner SD Host Controller object instance state.
165
+ */
166
+typedef struct AwSdHostState {
167
+ /*< private >*/
168
+ SysBusDevice busdev;
169
+ /*< public >*/
170
+
171
+ /** Secure Digital (SD) bus, which connects to SD card (if present) */
172
+ SDBus sdbus;
173
+
174
+ /** Maps I/O registers in physical memory */
175
+ MemoryRegion iomem;
176
+
177
+ /** Interrupt output signal to notify CPU */
178
+ qemu_irq irq;
179
+
180
+ /** Number of bytes left in current DMA transfer */
181
+ uint32_t transfer_cnt;
182
+
183
+ /**
184
+ * @name Hardware Registers
185
+ * @{
186
+ */
187
+
188
+ uint32_t global_ctl; /**< Global Control */
189
+ uint32_t clock_ctl; /**< Clock Control */
190
+ uint32_t timeout; /**< Timeout */
191
+ uint32_t bus_width; /**< Bus Width */
192
+ uint32_t block_size; /**< Block Size */
193
+ uint32_t byte_count; /**< Byte Count */
194
+
195
+ uint32_t command; /**< Command */
196
+ uint32_t command_arg; /**< Command Argument */
197
+ uint32_t response[4]; /**< Command Response */
198
+
199
+ uint32_t irq_mask; /**< Interrupt Mask */
200
+ uint32_t irq_status; /**< Raw Interrupt Status */
201
+ uint32_t status; /**< Status */
202
+
203
+ uint32_t fifo_wlevel; /**< FIFO Water Level */
204
+ uint32_t fifo_func_sel; /**< FIFO Function Select */
205
+ uint32_t debug_enable; /**< Debug Enable */
206
+ uint32_t auto12_arg; /**< Auto Command 12 Argument */
207
+ uint32_t newtiming_set; /**< SD New Timing Set */
208
+ uint32_t newtiming_debug; /**< SD New Timing Debug */
209
+ uint32_t hardware_rst; /**< Hardware Reset */
210
+ uint32_t dmac; /**< Internal DMA Controller Control */
211
+ uint32_t desc_base; /**< Descriptor List Base Address */
212
+ uint32_t dmac_status; /**< Internal DMA Controller Status */
213
+ uint32_t dmac_irq; /**< Internal DMA Controller IRQ Enable */
214
+ uint32_t card_threshold; /**< Card Threshold Control */
215
+ uint32_t startbit_detect; /**< eMMC DDR Start Bit Detection Control */
216
+ uint32_t response_crc; /**< Response CRC */
217
+ uint32_t data_crc[8]; /**< Data CRC */
218
+ uint32_t status_crc; /**< Status CRC */
219
+
220
+ /** @} */
221
+
222
+} AwSdHostState;
223
+
224
+/**
225
+ * Allwinner SD Host Controller class-level struct.
226
+ *
227
+ * This struct is filled by each sunxi device specific code
228
+ * such that the generic code can use this struct to support
229
+ * all devices.
230
+ */
231
+typedef struct AwSdHostClass {
232
+ /*< private >*/
233
+ SysBusDeviceClass parent_class;
234
+ /*< public >*/
235
+
236
+ /** Maximum buffer size in bytes per DMA descriptor */
237
+ size_t max_desc_size;
238
+
239
+} AwSdHostClass;
240
+
241
+#endif /* HW_SD_ALLWINNER_SDHOST_H */
242
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
243
index XXXXXXX..XXXXXXX 100644
244
--- a/hw/arm/allwinner-a10.c
245
+++ b/hw/arm/allwinner-a10.c
246
@@ -XXX,XX +XXX,XX @@
247
#include "hw/boards.h"
248
#include "hw/usb/hcd-ohci.h"
249
250
+#define AW_A10_MMC0_BASE 0x01c0f000
251
#define AW_A10_PIC_REG_BASE 0x01c20400
252
#define AW_A10_PIT_REG_BASE 0x01c20c00
253
#define AW_A10_UART0_REG_BASE 0x01c28000
254
@@ -XXX,XX +XXX,XX @@ static void aw_a10_init(Object *obj)
255
sizeof(s->ohci[i]), TYPE_SYSBUS_OHCI);
256
}
257
}
258
+
259
+ sysbus_init_child_obj(obj, "mmc0", &s->mmc0, sizeof(s->mmc0),
260
+ TYPE_AW_SDHOST_SUN4I);
144
}
261
}
145
262
146
+static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
263
static void aw_a10_realize(DeviceState *dev, Error **errp)
147
+ unsigned int target_el)
264
@@ -XXX,XX +XXX,XX @@ static void aw_a10_realize(DeviceState *dev, Error **errp)
148
+{
265
qdev_get_gpio_in(dev, 64 + i));
149
+ CPUARMState *env = cs->env_ptr;
266
}
150
+ unsigned int cur_el = arm_current_el(env);
267
}
151
+ bool secure = arm_is_secure(env);
268
+
152
+ bool pstate_unmasked;
269
+ /* SD/MMC */
153
+ int8_t unmasked = 0;
270
+ qdev_init_nofail(DEVICE(&s->mmc0));
154
+ uint64_t hcr_el2;
271
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->mmc0), 0, AW_A10_MMC0_BASE);
155
+
272
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc0), 0, qdev_get_gpio_in(dev, 32));
156
+ /*
273
+ object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->mmc0),
157
+ * Don't take exceptions if they target a lower EL.
274
+ "sd-bus", &error_abort);
158
+ * This check should catch any exceptions that would not be taken
275
}
159
+ * but left pending.
276
160
+ */
277
static void aw_a10_class_init(ObjectClass *oc, void *data)
161
+ if (cur_el > target_el) {
278
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
162
+ return false;
279
index XXXXXXX..XXXXXXX 100644
163
+ }
280
--- a/hw/arm/allwinner-h3.c
164
+
281
+++ b/hw/arm/allwinner-h3.c
165
+ hcr_el2 = arm_hcr_el2_eff(env);
282
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
166
+
283
[AW_H3_SRAM_A2] = 0x00044000,
167
+ switch (excp_idx) {
284
[AW_H3_SRAM_C] = 0x00010000,
168
+ case EXCP_FIQ:
285
[AW_H3_SYSCTRL] = 0x01c00000,
169
+ pstate_unmasked = !(env->daif & PSTATE_F);
286
+ [AW_H3_MMC0] = 0x01c0f000,
170
+ break;
287
[AW_H3_SID] = 0x01c14000,
171
+
288
[AW_H3_EHCI0] = 0x01c1a000,
172
+ case EXCP_IRQ:
289
[AW_H3_OHCI0] = 0x01c1a400,
173
+ pstate_unmasked = !(env->daif & PSTATE_I);
290
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
174
+ break;
291
{ "lcd0", 0x01c0c000, 4 * KiB },
175
+
292
{ "lcd1", 0x01c0d000, 4 * KiB },
176
+ case EXCP_VFIQ:
293
{ "ve", 0x01c0e000, 4 * KiB },
177
+ if (secure || !(hcr_el2 & HCR_FMO) || (hcr_el2 & HCR_TGE)) {
294
- { "mmc0", 0x01c0f000, 4 * KiB },
178
+ /* VFIQs are only taken when hypervized and non-secure. */
295
{ "mmc1", 0x01c10000, 4 * KiB },
179
+ return false;
296
{ "mmc2", 0x01c11000, 4 * KiB },
297
{ "crypto", 0x01c15000, 4 * KiB },
298
@@ -XXX,XX +XXX,XX @@ enum {
299
AW_H3_GIC_SPI_UART3 = 3,
300
AW_H3_GIC_SPI_TIMER0 = 18,
301
AW_H3_GIC_SPI_TIMER1 = 19,
302
+ AW_H3_GIC_SPI_MMC0 = 60,
303
AW_H3_GIC_SPI_EHCI0 = 72,
304
AW_H3_GIC_SPI_OHCI0 = 73,
305
AW_H3_GIC_SPI_EHCI1 = 74,
306
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
307
TYPE_AW_SID);
308
object_property_add_alias(obj, "identifier", OBJECT(&s->sid),
309
"identifier", &error_abort);
310
+
311
+ sysbus_init_child_obj(obj, "mmc0", &s->mmc0, sizeof(s->mmc0),
312
+ TYPE_AW_SDHOST_SUN5I);
313
}
314
315
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
316
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
317
qdev_init_nofail(DEVICE(&s->sid));
318
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sid), 0, s->memmap[AW_H3_SID]);
319
320
+ /* SD/MMC */
321
+ qdev_init_nofail(DEVICE(&s->mmc0));
322
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->mmc0), 0, s->memmap[AW_H3_MMC0]);
323
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc0), 0,
324
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_MMC0));
325
+
326
+ object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->mmc0),
327
+ "sd-bus", &error_abort);
328
+
329
/* Universal Serial Bus */
330
sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI0],
331
qdev_get_gpio_in(DEVICE(&s->gic),
332
diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
333
index XXXXXXX..XXXXXXX 100644
334
--- a/hw/arm/cubieboard.c
335
+++ b/hw/arm/cubieboard.c
336
@@ -XXX,XX +XXX,XX @@
337
#include "sysemu/sysemu.h"
338
#include "hw/sysbus.h"
339
#include "hw/boards.h"
340
+#include "hw/qdev-properties.h"
341
#include "hw/arm/allwinner-a10.h"
342
343
static struct arm_boot_info cubieboard_binfo = {
344
@@ -XXX,XX +XXX,XX @@ static void cubieboard_init(MachineState *machine)
345
{
346
AwA10State *a10;
347
Error *err = NULL;
348
+ DriveInfo *di;
349
+ BlockBackend *blk;
350
+ BusState *bus;
351
+ DeviceState *carddev;
352
353
/* BIOS is not supported by this board */
354
if (bios_name) {
355
@@ -XXX,XX +XXX,XX @@ static void cubieboard_init(MachineState *machine)
356
exit(1);
357
}
358
359
+ /* Retrieve SD bus */
360
+ di = drive_get_next(IF_SD);
361
+ blk = di ? blk_by_legacy_dinfo(di) : NULL;
362
+ bus = qdev_get_child_bus(DEVICE(a10), "sd-bus");
363
+
364
+ /* Plug in SD card */
365
+ carddev = qdev_create(bus, TYPE_SD_CARD);
366
+ qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
367
+ object_property_set_bool(OBJECT(carddev), true, "realized", &error_fatal);
368
+
369
memory_region_add_subregion(get_system_memory(), AW_A10_SDRAM_BASE,
370
machine->ram);
371
372
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
373
index XXXXXXX..XXXXXXX 100644
374
--- a/hw/arm/orangepi.c
375
+++ b/hw/arm/orangepi.c
376
@@ -XXX,XX +XXX,XX @@ static struct arm_boot_info orangepi_binfo = {
377
static void orangepi_init(MachineState *machine)
378
{
379
AwH3State *h3;
380
+ DriveInfo *di;
381
+ BlockBackend *blk;
382
+ BusState *bus;
383
+ DeviceState *carddev;
384
385
/* BIOS is not supported by this board */
386
if (bios_name) {
387
@@ -XXX,XX +XXX,XX @@ static void orangepi_init(MachineState *machine)
388
/* Mark H3 object realized */
389
object_property_set_bool(OBJECT(h3), true, "realized", &error_abort);
390
391
+ /* Retrieve SD bus */
392
+ di = drive_get_next(IF_SD);
393
+ blk = di ? blk_by_legacy_dinfo(di) : NULL;
394
+ bus = qdev_get_child_bus(DEVICE(h3), "sd-bus");
395
+
396
+ /* Plug in SD card */
397
+ carddev = qdev_create(bus, TYPE_SD_CARD);
398
+ qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
399
+ object_property_set_bool(OBJECT(carddev), true, "realized", &error_fatal);
400
+
401
/* SDRAM */
402
memory_region_add_subregion(get_system_memory(), h3->memmap[AW_H3_SDRAM],
403
machine->ram);
404
@@ -XXX,XX +XXX,XX @@ static void orangepi_machine_init(MachineClass *mc)
405
{
406
mc->desc = "Orange Pi PC";
407
mc->init = orangepi_init;
408
+ mc->block_default_type = IF_SD;
409
+ mc->units_per_default_bus = 1;
410
mc->min_cpus = AW_H3_NUM_CPUS;
411
mc->max_cpus = AW_H3_NUM_CPUS;
412
mc->default_cpus = AW_H3_NUM_CPUS;
413
diff --git a/hw/sd/allwinner-sdhost.c b/hw/sd/allwinner-sdhost.c
414
new file mode 100644
415
index XXXXXXX..XXXXXXX
416
--- /dev/null
417
+++ b/hw/sd/allwinner-sdhost.c
418
@@ -XXX,XX +XXX,XX @@
419
+/*
420
+ * Allwinner (sun4i and above) SD Host Controller emulation
421
+ *
422
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
423
+ *
424
+ * This program is free software: you can redistribute it and/or modify
425
+ * it under the terms of the GNU General Public License as published by
426
+ * the Free Software Foundation, either version 2 of the License, or
427
+ * (at your option) any later version.
428
+ *
429
+ * This program is distributed in the hope that it will be useful,
430
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
431
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
432
+ * GNU General Public License for more details.
433
+ *
434
+ * You should have received a copy of the GNU General Public License
435
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
436
+ */
437
+
438
+#include "qemu/osdep.h"
439
+#include "qemu/log.h"
440
+#include "qemu/module.h"
441
+#include "qemu/units.h"
442
+#include "sysemu/blockdev.h"
443
+#include "hw/irq.h"
444
+#include "hw/sd/allwinner-sdhost.h"
445
+#include "migration/vmstate.h"
446
+#include "trace.h"
447
+
448
+#define TYPE_AW_SDHOST_BUS "allwinner-sdhost-bus"
449
+#define AW_SDHOST_BUS(obj) \
450
+ OBJECT_CHECK(SDBus, (obj), TYPE_AW_SDHOST_BUS)
451
+
452
+/* SD Host register offsets */
453
+enum {
454
+ REG_SD_GCTL = 0x00, /* Global Control */
455
+ REG_SD_CKCR = 0x04, /* Clock Control */
456
+ REG_SD_TMOR = 0x08, /* Timeout */
457
+ REG_SD_BWDR = 0x0C, /* Bus Width */
458
+ REG_SD_BKSR = 0x10, /* Block Size */
459
+ REG_SD_BYCR = 0x14, /* Byte Count */
460
+ REG_SD_CMDR = 0x18, /* Command */
461
+ REG_SD_CAGR = 0x1C, /* Command Argument */
462
+ REG_SD_RESP0 = 0x20, /* Response Zero */
463
+ REG_SD_RESP1 = 0x24, /* Response One */
464
+ REG_SD_RESP2 = 0x28, /* Response Two */
465
+ REG_SD_RESP3 = 0x2C, /* Response Three */
466
+ REG_SD_IMKR = 0x30, /* Interrupt Mask */
467
+ REG_SD_MISR = 0x34, /* Masked Interrupt Status */
468
+ REG_SD_RISR = 0x38, /* Raw Interrupt Status */
469
+ REG_SD_STAR = 0x3C, /* Status */
470
+ REG_SD_FWLR = 0x40, /* FIFO Water Level */
471
+ REG_SD_FUNS = 0x44, /* FIFO Function Select */
472
+ REG_SD_DBGC = 0x50, /* Debug Enable */
473
+ REG_SD_A12A = 0x58, /* Auto command 12 argument */
474
+ REG_SD_NTSR = 0x5C, /* SD NewTiming Set */
475
+ REG_SD_SDBG = 0x60, /* SD newTiming Set Debug */
476
+ REG_SD_HWRST = 0x78, /* Hardware Reset Register */
477
+ REG_SD_DMAC = 0x80, /* Internal DMA Controller Control */
478
+ REG_SD_DLBA = 0x84, /* Descriptor List Base Address */
479
+ REG_SD_IDST = 0x88, /* Internal DMA Controller Status */
480
+ REG_SD_IDIE = 0x8C, /* Internal DMA Controller IRQ Enable */
481
+ REG_SD_THLDC = 0x100, /* Card Threshold Control */
482
+ REG_SD_DSBD = 0x10C, /* eMMC DDR Start Bit Detection Control */
483
+ REG_SD_RES_CRC = 0x110, /* Response CRC from card/eMMC */
484
+ REG_SD_DATA7_CRC = 0x114, /* CRC Data 7 from card/eMMC */
485
+ REG_SD_DATA6_CRC = 0x118, /* CRC Data 6 from card/eMMC */
486
+ REG_SD_DATA5_CRC = 0x11C, /* CRC Data 5 from card/eMMC */
487
+ REG_SD_DATA4_CRC = 0x120, /* CRC Data 4 from card/eMMC */
488
+ REG_SD_DATA3_CRC = 0x124, /* CRC Data 3 from card/eMMC */
489
+ REG_SD_DATA2_CRC = 0x128, /* CRC Data 2 from card/eMMC */
490
+ REG_SD_DATA1_CRC = 0x12C, /* CRC Data 1 from card/eMMC */
491
+ REG_SD_DATA0_CRC = 0x130, /* CRC Data 0 from card/eMMC */
492
+ REG_SD_CRC_STA = 0x134, /* CRC status from card/eMMC during write */
493
+ REG_SD_FIFO = 0x200, /* Read/Write FIFO */
494
+};
495
+
496
+/* SD Host register flags */
497
+enum {
498
+ SD_GCTL_FIFO_AC_MOD = (1 << 31),
499
+ SD_GCTL_DDR_MOD_SEL = (1 << 10),
500
+ SD_GCTL_CD_DBC_ENB = (1 << 8),
501
+ SD_GCTL_DMA_ENB = (1 << 5),
502
+ SD_GCTL_INT_ENB = (1 << 4),
503
+ SD_GCTL_DMA_RST = (1 << 2),
504
+ SD_GCTL_FIFO_RST = (1 << 1),
505
+ SD_GCTL_SOFT_RST = (1 << 0),
506
+};
507
+
508
+enum {
509
+ SD_CMDR_LOAD = (1 << 31),
510
+ SD_CMDR_CLKCHANGE = (1 << 21),
511
+ SD_CMDR_WRITE = (1 << 10),
512
+ SD_CMDR_AUTOSTOP = (1 << 12),
513
+ SD_CMDR_DATA = (1 << 9),
514
+ SD_CMDR_RESPONSE_LONG = (1 << 7),
515
+ SD_CMDR_RESPONSE = (1 << 6),
516
+ SD_CMDR_CMDID_MASK = (0x3f),
517
+};
518
+
519
+enum {
520
+ SD_RISR_CARD_REMOVE = (1 << 31),
521
+ SD_RISR_CARD_INSERT = (1 << 30),
522
+ SD_RISR_SDIO_INTR = (1 << 16),
523
+ SD_RISR_AUTOCMD_DONE = (1 << 14),
524
+ SD_RISR_DATA_COMPLETE = (1 << 3),
525
+ SD_RISR_CMD_COMPLETE = (1 << 2),
526
+ SD_RISR_NO_RESPONSE = (1 << 1),
527
+};
528
+
529
+enum {
530
+ SD_STAR_CARD_PRESENT = (1 << 8),
531
+};
532
+
533
+enum {
534
+ SD_IDST_INT_SUMMARY = (1 << 8),
535
+ SD_IDST_RECEIVE_IRQ = (1 << 1),
536
+ SD_IDST_TRANSMIT_IRQ = (1 << 0),
537
+ SD_IDST_IRQ_MASK = (1 << 1) | (1 << 0) | (1 << 8),
538
+ SD_IDST_WR_MASK = (0x3ff),
539
+};
540
+
541
+/* SD Host register reset values */
542
+enum {
543
+ REG_SD_GCTL_RST = 0x00000300,
544
+ REG_SD_CKCR_RST = 0x0,
545
+ REG_SD_TMOR_RST = 0xFFFFFF40,
546
+ REG_SD_BWDR_RST = 0x0,
547
+ REG_SD_BKSR_RST = 0x00000200,
548
+ REG_SD_BYCR_RST = 0x00000200,
549
+ REG_SD_CMDR_RST = 0x0,
550
+ REG_SD_CAGR_RST = 0x0,
551
+ REG_SD_RESP_RST = 0x0,
552
+ REG_SD_IMKR_RST = 0x0,
553
+ REG_SD_MISR_RST = 0x0,
554
+ REG_SD_RISR_RST = 0x0,
555
+ REG_SD_STAR_RST = 0x00000100,
556
+ REG_SD_FWLR_RST = 0x000F0000,
557
+ REG_SD_FUNS_RST = 0x0,
558
+ REG_SD_DBGC_RST = 0x0,
559
+ REG_SD_A12A_RST = 0x0000FFFF,
560
+ REG_SD_NTSR_RST = 0x00000001,
561
+ REG_SD_SDBG_RST = 0x0,
562
+ REG_SD_HWRST_RST = 0x00000001,
563
+ REG_SD_DMAC_RST = 0x0,
564
+ REG_SD_DLBA_RST = 0x0,
565
+ REG_SD_IDST_RST = 0x0,
566
+ REG_SD_IDIE_RST = 0x0,
567
+ REG_SD_THLDC_RST = 0x0,
568
+ REG_SD_DSBD_RST = 0x0,
569
+ REG_SD_RES_CRC_RST = 0x0,
570
+ REG_SD_DATA_CRC_RST = 0x0,
571
+ REG_SD_CRC_STA_RST = 0x0,
572
+ REG_SD_FIFO_RST = 0x0,
573
+};
574
+
575
+/* Data transfer descriptor for DMA */
576
+typedef struct TransferDescriptor {
577
+ uint32_t status; /* Status flags */
578
+ uint32_t size; /* Data buffer size */
579
+ uint32_t addr; /* Data buffer address */
580
+ uint32_t next; /* Physical address of next descriptor */
581
+} TransferDescriptor;
582
+
583
+/* Data transfer descriptor flags */
584
+enum {
585
+ DESC_STATUS_HOLD = (1 << 31), /* Set when descriptor is in use by DMA */
586
+ DESC_STATUS_ERROR = (1 << 30), /* Set when DMA transfer error occurred */
587
+ DESC_STATUS_CHAIN = (1 << 4), /* Indicates chained descriptor. */
588
+ DESC_STATUS_FIRST = (1 << 3), /* Set on the first descriptor */
589
+ DESC_STATUS_LAST = (1 << 2), /* Set on the last descriptor */
590
+ DESC_STATUS_NOIRQ = (1 << 1), /* Skip raising interrupt after transfer */
591
+ DESC_SIZE_MASK = (0xfffffffc)
592
+};
593
+
594
+static void allwinner_sdhost_update_irq(AwSdHostState *s)
595
+{
596
+ uint32_t irq;
597
+
598
+ if (s->global_ctl & SD_GCTL_INT_ENB) {
599
+ irq = s->irq_status & s->irq_mask;
600
+ } else {
601
+ irq = 0;
602
+ }
603
+
604
+ trace_allwinner_sdhost_update_irq(irq);
605
+ qemu_set_irq(s->irq, irq);
606
+}
607
+
608
+static void allwinner_sdhost_update_transfer_cnt(AwSdHostState *s,
609
+ uint32_t bytes)
610
+{
611
+ if (s->transfer_cnt > bytes) {
612
+ s->transfer_cnt -= bytes;
613
+ } else {
614
+ s->transfer_cnt = 0;
615
+ }
616
+
617
+ if (!s->transfer_cnt) {
618
+ s->irq_status |= SD_RISR_DATA_COMPLETE;
619
+ }
620
+}
621
+
622
+static void allwinner_sdhost_set_inserted(DeviceState *dev, bool inserted)
623
+{
624
+ AwSdHostState *s = AW_SDHOST(dev);
625
+
626
+ trace_allwinner_sdhost_set_inserted(inserted);
627
+
628
+ if (inserted) {
629
+ s->irq_status |= SD_RISR_CARD_INSERT;
630
+ s->irq_status &= ~SD_RISR_CARD_REMOVE;
631
+ s->status |= SD_STAR_CARD_PRESENT;
632
+ } else {
633
+ s->irq_status &= ~SD_RISR_CARD_INSERT;
634
+ s->irq_status |= SD_RISR_CARD_REMOVE;
635
+ s->status &= ~SD_STAR_CARD_PRESENT;
636
+ }
637
+
638
+ allwinner_sdhost_update_irq(s);
639
+}
640
+
641
+static void allwinner_sdhost_send_command(AwSdHostState *s)
642
+{
643
+ SDRequest request;
644
+ uint8_t resp[16];
645
+ int rlen;
646
+
647
+ /* Auto clear load flag */
648
+ s->command &= ~SD_CMDR_LOAD;
649
+
650
+ /* Clock change does not actually interact with the SD bus */
651
+ if (!(s->command & SD_CMDR_CLKCHANGE)) {
652
+
653
+ /* Prepare request */
654
+ request.cmd = s->command & SD_CMDR_CMDID_MASK;
655
+ request.arg = s->command_arg;
656
+
657
+ /* Send request to SD bus */
658
+ rlen = sdbus_do_command(&s->sdbus, &request, resp);
659
+ if (rlen < 0) {
660
+ goto error;
180
+ }
661
+ }
181
+ return !(env->daif & PSTATE_F);
662
+
182
+ case EXCP_VIRQ:
663
+ /* If the command has a response, store it in the response registers */
183
+ if (secure || !(hcr_el2 & HCR_IMO) || (hcr_el2 & HCR_TGE)) {
664
+ if ((s->command & SD_CMDR_RESPONSE)) {
184
+ /* VIRQs are only taken when hypervized and non-secure. */
665
+ if (rlen == 4 && !(s->command & SD_CMDR_RESPONSE_LONG)) {
185
+ return false;
666
+ s->response[0] = ldl_be_p(&resp[0]);
186
+ }
667
+ s->response[1] = s->response[2] = s->response[3] = 0;
187
+ return !(env->daif & PSTATE_I);
668
+
188
+ default:
669
+ } else if (rlen == 16 && (s->command & SD_CMDR_RESPONSE_LONG)) {
189
+ g_assert_not_reached();
670
+ s->response[0] = ldl_be_p(&resp[12]);
190
+ }
671
+ s->response[1] = ldl_be_p(&resp[8]);
191
+
672
+ s->response[2] = ldl_be_p(&resp[4]);
192
+ /*
673
+ s->response[3] = ldl_be_p(&resp[0]);
193
+ * Use the target EL, current execution state and SCR/HCR settings to
674
+ } else {
194
+ * determine whether the corresponding CPSR bit is used to mask the
675
+ goto error;
195
+ * interrupt.
196
+ */
197
+ if ((target_el > cur_el) && (target_el != 1)) {
198
+ /* Exceptions targeting a higher EL may not be maskable */
199
+ if (arm_feature(env, ARM_FEATURE_AARCH64)) {
200
+ /*
201
+ * 64-bit masking rules are simple: exceptions to EL3
202
+ * can't be masked, and exceptions to EL2 can only be
203
+ * masked from Secure state. The HCR and SCR settings
204
+ * don't affect the masking logic, only the interrupt routing.
205
+ */
206
+ if (target_el == 3 || !secure) {
207
+ unmasked = 1;
208
+ }
209
+ } else {
210
+ /*
211
+ * The old 32-bit-only environment has a more complicated
212
+ * masking setup. HCR and SCR bits not only affect interrupt
213
+ * routing but also change the behaviour of masking.
214
+ */
215
+ bool hcr, scr;
216
+
217
+ switch (excp_idx) {
218
+ case EXCP_FIQ:
219
+ /*
220
+ * If FIQs are routed to EL3 or EL2 then there are cases where
221
+ * we override the CPSR.F in determining if the exception is
222
+ * masked or not. If neither of these are set then we fall back
223
+ * to the CPSR.F setting otherwise we further assess the state
224
+ * below.
225
+ */
226
+ hcr = hcr_el2 & HCR_FMO;
227
+ scr = (env->cp15.scr_el3 & SCR_FIQ);
228
+
229
+ /*
230
+ * When EL3 is 32-bit, the SCR.FW bit controls whether the
231
+ * CPSR.F bit masks FIQ interrupts when taken in non-secure
232
+ * state. If SCR.FW is set then FIQs can be masked by CPSR.F
233
+ * when non-secure but only when FIQs are only routed to EL3.
234
+ */
235
+ scr = scr && !((env->cp15.scr_el3 & SCR_FW) && !hcr);
236
+ break;
237
+ case EXCP_IRQ:
238
+ /*
239
+ * When EL3 execution state is 32-bit, if HCR.IMO is set then
240
+ * we may override the CPSR.I masking when in non-secure state.
241
+ * The SCR.IRQ setting has already been taken into consideration
242
+ * when setting the target EL, so it does not have a further
243
+ * affect here.
244
+ */
245
+ hcr = hcr_el2 & HCR_IMO;
246
+ scr = false;
247
+ break;
248
+ default:
249
+ g_assert_not_reached();
250
+ }
251
+
252
+ if ((scr || hcr) && !secure) {
253
+ unmasked = 1;
254
+ }
676
+ }
255
+ }
677
+ }
256
+ }
678
+ }
257
+
679
+
680
+ /* Set interrupt status bits */
681
+ s->irq_status |= SD_RISR_CMD_COMPLETE;
682
+ return;
683
+
684
+error:
685
+ s->irq_status |= SD_RISR_NO_RESPONSE;
686
+}
687
+
688
+static void allwinner_sdhost_auto_stop(AwSdHostState *s)
689
+{
258
+ /*
690
+ /*
259
+ * The PSTATE bits only mask the interrupt if we have not overriden the
691
+ * The stop command (CMD12) ensures the SD bus
260
+ * ability above.
692
+ * returns to the transfer state.
261
+ */
693
+ */
262
+ return unmasked || pstate_unmasked;
694
+ if ((s->command & SD_CMDR_AUTOSTOP) && (s->transfer_cnt == 0)) {
263
+}
695
+ /* First save current command registers */
264
+
696
+ uint32_t saved_cmd = s->command;
265
bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
697
+ uint32_t saved_arg = s->command_arg;
266
{
698
+
267
CPUClass *cc = CPU_GET_CLASS(cs);
699
+ /* Prepare stop command (CMD12) */
700
+ s->command &= ~SD_CMDR_CMDID_MASK;
701
+ s->command |= 12; /* CMD12 */
702
+ s->command_arg = 0;
703
+
704
+ /* Put the command on SD bus */
705
+ allwinner_sdhost_send_command(s);
706
+
707
+ /* Restore command values */
708
+ s->command = saved_cmd;
709
+ s->command_arg = saved_arg;
710
+
711
+ /* Set IRQ status bit for automatic stop done */
712
+ s->irq_status |= SD_RISR_AUTOCMD_DONE;
713
+ }
714
+}
715
+
716
+static uint32_t allwinner_sdhost_process_desc(AwSdHostState *s,
717
+ hwaddr desc_addr,
718
+ TransferDescriptor *desc,
719
+ bool is_write, uint32_t max_bytes)
720
+{
721
+ AwSdHostClass *klass = AW_SDHOST_GET_CLASS(s);
722
+ uint32_t num_done = 0;
723
+ uint32_t num_bytes = max_bytes;
724
+ uint8_t buf[1024];
725
+
726
+ /* Read descriptor */
727
+ cpu_physical_memory_read(desc_addr, desc, sizeof(*desc));
728
+ if (desc->size == 0) {
729
+ desc->size = klass->max_desc_size;
730
+ } else if (desc->size > klass->max_desc_size) {
731
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA descriptor buffer size "
732
+ " is out-of-bounds: %" PRIu32 " > %zu",
733
+ __func__, desc->size, klass->max_desc_size);
734
+ desc->size = klass->max_desc_size;
735
+ }
736
+ if (desc->size < num_bytes) {
737
+ num_bytes = desc->size;
738
+ }
739
+
740
+ trace_allwinner_sdhost_process_desc(desc_addr, desc->size,
741
+ is_write, max_bytes);
742
+
743
+ while (num_done < num_bytes) {
744
+ /* Try to completely fill the local buffer */
745
+ uint32_t buf_bytes = num_bytes - num_done;
746
+ if (buf_bytes > sizeof(buf)) {
747
+ buf_bytes = sizeof(buf);
748
+ }
749
+
750
+ /* Write to SD bus */
751
+ if (is_write) {
752
+ cpu_physical_memory_read((desc->addr & DESC_SIZE_MASK) + num_done,
753
+ buf, buf_bytes);
754
+
755
+ for (uint32_t i = 0; i < buf_bytes; i++) {
756
+ sdbus_write_data(&s->sdbus, buf[i]);
757
+ }
758
+
759
+ /* Read from SD bus */
760
+ } else {
761
+ for (uint32_t i = 0; i < buf_bytes; i++) {
762
+ buf[i] = sdbus_read_data(&s->sdbus);
763
+ }
764
+ cpu_physical_memory_write((desc->addr & DESC_SIZE_MASK) + num_done,
765
+ buf, buf_bytes);
766
+ }
767
+ num_done += buf_bytes;
768
+ }
769
+
770
+ /* Clear hold flag and flush descriptor */
771
+ desc->status &= ~DESC_STATUS_HOLD;
772
+ cpu_physical_memory_write(desc_addr, desc, sizeof(*desc));
773
+
774
+ return num_done;
775
+}
776
+
777
+static void allwinner_sdhost_dma(AwSdHostState *s)
778
+{
779
+ TransferDescriptor desc;
780
+ hwaddr desc_addr = s->desc_base;
781
+ bool is_write = (s->command & SD_CMDR_WRITE);
782
+ uint32_t bytes_done = 0;
783
+
784
+ /* Check if DMA can be performed */
785
+ if (s->byte_count == 0 || s->block_size == 0 ||
786
+ !(s->global_ctl & SD_GCTL_DMA_ENB)) {
787
+ return;
788
+ }
789
+
790
+ /*
791
+ * For read operations, data must be available on the SD bus
792
+ * If not, it is an error and we should not act at all
793
+ */
794
+ if (!is_write && !sdbus_data_ready(&s->sdbus)) {
795
+ return;
796
+ }
797
+
798
+ /* Process the DMA descriptors until all data is copied */
799
+ while (s->byte_count > 0) {
800
+ bytes_done = allwinner_sdhost_process_desc(s, desc_addr, &desc,
801
+ is_write, s->byte_count);
802
+ allwinner_sdhost_update_transfer_cnt(s, bytes_done);
803
+
804
+ if (bytes_done <= s->byte_count) {
805
+ s->byte_count -= bytes_done;
806
+ } else {
807
+ s->byte_count = 0;
808
+ }
809
+
810
+ if (desc.status & DESC_STATUS_LAST) {
811
+ break;
812
+ } else {
813
+ desc_addr = desc.next;
814
+ }
815
+ }
816
+
817
+ /* Raise IRQ to signal DMA is completed */
818
+ s->irq_status |= SD_RISR_DATA_COMPLETE | SD_RISR_SDIO_INTR;
819
+
820
+ /* Update DMAC bits */
821
+ s->dmac_status |= SD_IDST_INT_SUMMARY;
822
+
823
+ if (is_write) {
824
+ s->dmac_status |= SD_IDST_TRANSMIT_IRQ;
825
+ } else {
826
+ s->dmac_status |= SD_IDST_RECEIVE_IRQ;
827
+ }
828
+}
829
+
830
+static uint64_t allwinner_sdhost_read(void *opaque, hwaddr offset,
831
+ unsigned size)
832
+{
833
+ AwSdHostState *s = AW_SDHOST(opaque);
834
+ uint32_t res = 0;
835
+
836
+ switch (offset) {
837
+ case REG_SD_GCTL: /* Global Control */
838
+ res = s->global_ctl;
839
+ break;
840
+ case REG_SD_CKCR: /* Clock Control */
841
+ res = s->clock_ctl;
842
+ break;
843
+ case REG_SD_TMOR: /* Timeout */
844
+ res = s->timeout;
845
+ break;
846
+ case REG_SD_BWDR: /* Bus Width */
847
+ res = s->bus_width;
848
+ break;
849
+ case REG_SD_BKSR: /* Block Size */
850
+ res = s->block_size;
851
+ break;
852
+ case REG_SD_BYCR: /* Byte Count */
853
+ res = s->byte_count;
854
+ break;
855
+ case REG_SD_CMDR: /* Command */
856
+ res = s->command;
857
+ break;
858
+ case REG_SD_CAGR: /* Command Argument */
859
+ res = s->command_arg;
860
+ break;
861
+ case REG_SD_RESP0: /* Response Zero */
862
+ res = s->response[0];
863
+ break;
864
+ case REG_SD_RESP1: /* Response One */
865
+ res = s->response[1];
866
+ break;
867
+ case REG_SD_RESP2: /* Response Two */
868
+ res = s->response[2];
869
+ break;
870
+ case REG_SD_RESP3: /* Response Three */
871
+ res = s->response[3];
872
+ break;
873
+ case REG_SD_IMKR: /* Interrupt Mask */
874
+ res = s->irq_mask;
875
+ break;
876
+ case REG_SD_MISR: /* Masked Interrupt Status */
877
+ res = s->irq_status & s->irq_mask;
878
+ break;
879
+ case REG_SD_RISR: /* Raw Interrupt Status */
880
+ res = s->irq_status;
881
+ break;
882
+ case REG_SD_STAR: /* Status */
883
+ res = s->status;
884
+ break;
885
+ case REG_SD_FWLR: /* FIFO Water Level */
886
+ res = s->fifo_wlevel;
887
+ break;
888
+ case REG_SD_FUNS: /* FIFO Function Select */
889
+ res = s->fifo_func_sel;
890
+ break;
891
+ case REG_SD_DBGC: /* Debug Enable */
892
+ res = s->debug_enable;
893
+ break;
894
+ case REG_SD_A12A: /* Auto command 12 argument */
895
+ res = s->auto12_arg;
896
+ break;
897
+ case REG_SD_NTSR: /* SD NewTiming Set */
898
+ res = s->newtiming_set;
899
+ break;
900
+ case REG_SD_SDBG: /* SD newTiming Set Debug */
901
+ res = s->newtiming_debug;
902
+ break;
903
+ case REG_SD_HWRST: /* Hardware Reset Register */
904
+ res = s->hardware_rst;
905
+ break;
906
+ case REG_SD_DMAC: /* Internal DMA Controller Control */
907
+ res = s->dmac;
908
+ break;
909
+ case REG_SD_DLBA: /* Descriptor List Base Address */
910
+ res = s->desc_base;
911
+ break;
912
+ case REG_SD_IDST: /* Internal DMA Controller Status */
913
+ res = s->dmac_status;
914
+ break;
915
+ case REG_SD_IDIE: /* Internal DMA Controller Interrupt Enable */
916
+ res = s->dmac_irq;
917
+ break;
918
+ case REG_SD_THLDC: /* Card Threshold Control */
919
+ res = s->card_threshold;
920
+ break;
921
+ case REG_SD_DSBD: /* eMMC DDR Start Bit Detection Control */
922
+ res = s->startbit_detect;
923
+ break;
924
+ case REG_SD_RES_CRC: /* Response CRC from card/eMMC */
925
+ res = s->response_crc;
926
+ break;
927
+ case REG_SD_DATA7_CRC: /* CRC Data 7 from card/eMMC */
928
+ case REG_SD_DATA6_CRC: /* CRC Data 6 from card/eMMC */
929
+ case REG_SD_DATA5_CRC: /* CRC Data 5 from card/eMMC */
930
+ case REG_SD_DATA4_CRC: /* CRC Data 4 from card/eMMC */
931
+ case REG_SD_DATA3_CRC: /* CRC Data 3 from card/eMMC */
932
+ case REG_SD_DATA2_CRC: /* CRC Data 2 from card/eMMC */
933
+ case REG_SD_DATA1_CRC: /* CRC Data 1 from card/eMMC */
934
+ case REG_SD_DATA0_CRC: /* CRC Data 0 from card/eMMC */
935
+ res = s->data_crc[((offset - REG_SD_DATA7_CRC) / sizeof(uint32_t))];
936
+ break;
937
+ case REG_SD_CRC_STA: /* CRC status from card/eMMC in write operation */
938
+ res = s->status_crc;
939
+ break;
940
+ case REG_SD_FIFO: /* Read/Write FIFO */
941
+ if (sdbus_data_ready(&s->sdbus)) {
942
+ res = sdbus_read_data(&s->sdbus);
943
+ res |= sdbus_read_data(&s->sdbus) << 8;
944
+ res |= sdbus_read_data(&s->sdbus) << 16;
945
+ res |= sdbus_read_data(&s->sdbus) << 24;
946
+ allwinner_sdhost_update_transfer_cnt(s, sizeof(uint32_t));
947
+ allwinner_sdhost_auto_stop(s);
948
+ allwinner_sdhost_update_irq(s);
949
+ } else {
950
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: no data ready on SD bus\n",
951
+ __func__);
952
+ }
953
+ break;
954
+ default:
955
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset %"
956
+ HWADDR_PRIx"\n", __func__, offset);
957
+ res = 0;
958
+ break;
959
+ }
960
+
961
+ trace_allwinner_sdhost_read(offset, res, size);
962
+ return res;
963
+}
964
+
965
+static void allwinner_sdhost_write(void *opaque, hwaddr offset,
966
+ uint64_t value, unsigned size)
967
+{
968
+ AwSdHostState *s = AW_SDHOST(opaque);
969
+
970
+ trace_allwinner_sdhost_write(offset, value, size);
971
+
972
+ switch (offset) {
973
+ case REG_SD_GCTL: /* Global Control */
974
+ s->global_ctl = value;
975
+ s->global_ctl &= ~(SD_GCTL_DMA_RST | SD_GCTL_FIFO_RST |
976
+ SD_GCTL_SOFT_RST);
977
+ allwinner_sdhost_update_irq(s);
978
+ break;
979
+ case REG_SD_CKCR: /* Clock Control */
980
+ s->clock_ctl = value;
981
+ break;
982
+ case REG_SD_TMOR: /* Timeout */
983
+ s->timeout = value;
984
+ break;
985
+ case REG_SD_BWDR: /* Bus Width */
986
+ s->bus_width = value;
987
+ break;
988
+ case REG_SD_BKSR: /* Block Size */
989
+ s->block_size = value;
990
+ break;
991
+ case REG_SD_BYCR: /* Byte Count */
992
+ s->byte_count = value;
993
+ s->transfer_cnt = value;
994
+ break;
995
+ case REG_SD_CMDR: /* Command */
996
+ s->command = value;
997
+ if (value & SD_CMDR_LOAD) {
998
+ allwinner_sdhost_send_command(s);
999
+ allwinner_sdhost_dma(s);
1000
+ allwinner_sdhost_auto_stop(s);
1001
+ }
1002
+ allwinner_sdhost_update_irq(s);
1003
+ break;
1004
+ case REG_SD_CAGR: /* Command Argument */
1005
+ s->command_arg = value;
1006
+ break;
1007
+ case REG_SD_RESP0: /* Response Zero */
1008
+ s->response[0] = value;
1009
+ break;
1010
+ case REG_SD_RESP1: /* Response One */
1011
+ s->response[1] = value;
1012
+ break;
1013
+ case REG_SD_RESP2: /* Response Two */
1014
+ s->response[2] = value;
1015
+ break;
1016
+ case REG_SD_RESP3: /* Response Three */
1017
+ s->response[3] = value;
1018
+ break;
1019
+ case REG_SD_IMKR: /* Interrupt Mask */
1020
+ s->irq_mask = value;
1021
+ allwinner_sdhost_update_irq(s);
1022
+ break;
1023
+ case REG_SD_MISR: /* Masked Interrupt Status */
1024
+ case REG_SD_RISR: /* Raw Interrupt Status */
1025
+ s->irq_status &= ~value;
1026
+ allwinner_sdhost_update_irq(s);
1027
+ break;
1028
+ case REG_SD_STAR: /* Status */
1029
+ s->status &= ~value;
1030
+ allwinner_sdhost_update_irq(s);
1031
+ break;
1032
+ case REG_SD_FWLR: /* FIFO Water Level */
1033
+ s->fifo_wlevel = value;
1034
+ break;
1035
+ case REG_SD_FUNS: /* FIFO Function Select */
1036
+ s->fifo_func_sel = value;
1037
+ break;
1038
+ case REG_SD_DBGC: /* Debug Enable */
1039
+ s->debug_enable = value;
1040
+ break;
1041
+ case REG_SD_A12A: /* Auto command 12 argument */
1042
+ s->auto12_arg = value;
1043
+ break;
1044
+ case REG_SD_NTSR: /* SD NewTiming Set */
1045
+ s->newtiming_set = value;
1046
+ break;
1047
+ case REG_SD_SDBG: /* SD newTiming Set Debug */
1048
+ s->newtiming_debug = value;
1049
+ break;
1050
+ case REG_SD_HWRST: /* Hardware Reset Register */
1051
+ s->hardware_rst = value;
1052
+ break;
1053
+ case REG_SD_DMAC: /* Internal DMA Controller Control */
1054
+ s->dmac = value;
1055
+ allwinner_sdhost_update_irq(s);
1056
+ break;
1057
+ case REG_SD_DLBA: /* Descriptor List Base Address */
1058
+ s->desc_base = value;
1059
+ break;
1060
+ case REG_SD_IDST: /* Internal DMA Controller Status */
1061
+ s->dmac_status &= (~SD_IDST_WR_MASK) | (~value & SD_IDST_WR_MASK);
1062
+ allwinner_sdhost_update_irq(s);
1063
+ break;
1064
+ case REG_SD_IDIE: /* Internal DMA Controller Interrupt Enable */
1065
+ s->dmac_irq = value;
1066
+ allwinner_sdhost_update_irq(s);
1067
+ break;
1068
+ case REG_SD_THLDC: /* Card Threshold Control */
1069
+ s->card_threshold = value;
1070
+ break;
1071
+ case REG_SD_DSBD: /* eMMC DDR Start Bit Detection Control */
1072
+ s->startbit_detect = value;
1073
+ break;
1074
+ case REG_SD_FIFO: /* Read/Write FIFO */
1075
+ sdbus_write_data(&s->sdbus, value & 0xff);
1076
+ sdbus_write_data(&s->sdbus, (value >> 8) & 0xff);
1077
+ sdbus_write_data(&s->sdbus, (value >> 16) & 0xff);
1078
+ sdbus_write_data(&s->sdbus, (value >> 24) & 0xff);
1079
+ allwinner_sdhost_update_transfer_cnt(s, sizeof(uint32_t));
1080
+ allwinner_sdhost_auto_stop(s);
1081
+ allwinner_sdhost_update_irq(s);
1082
+ break;
1083
+ case REG_SD_RES_CRC: /* Response CRC from card/eMMC */
1084
+ case REG_SD_DATA7_CRC: /* CRC Data 7 from card/eMMC */
1085
+ case REG_SD_DATA6_CRC: /* CRC Data 6 from card/eMMC */
1086
+ case REG_SD_DATA5_CRC: /* CRC Data 5 from card/eMMC */
1087
+ case REG_SD_DATA4_CRC: /* CRC Data 4 from card/eMMC */
1088
+ case REG_SD_DATA3_CRC: /* CRC Data 3 from card/eMMC */
1089
+ case REG_SD_DATA2_CRC: /* CRC Data 2 from card/eMMC */
1090
+ case REG_SD_DATA1_CRC: /* CRC Data 1 from card/eMMC */
1091
+ case REG_SD_DATA0_CRC: /* CRC Data 0 from card/eMMC */
1092
+ case REG_SD_CRC_STA: /* CRC status from card/eMMC in write operation */
1093
+ break;
1094
+ default:
1095
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset %"
1096
+ HWADDR_PRIx"\n", __func__, offset);
1097
+ break;
1098
+ }
1099
+}
1100
+
1101
+static const MemoryRegionOps allwinner_sdhost_ops = {
1102
+ .read = allwinner_sdhost_read,
1103
+ .write = allwinner_sdhost_write,
1104
+ .endianness = DEVICE_NATIVE_ENDIAN,
1105
+ .valid = {
1106
+ .min_access_size = 4,
1107
+ .max_access_size = 4,
1108
+ },
1109
+ .impl.min_access_size = 4,
1110
+};
1111
+
1112
+static const VMStateDescription vmstate_allwinner_sdhost = {
1113
+ .name = "allwinner-sdhost",
1114
+ .version_id = 1,
1115
+ .minimum_version_id = 1,
1116
+ .fields = (VMStateField[]) {
1117
+ VMSTATE_UINT32(global_ctl, AwSdHostState),
1118
+ VMSTATE_UINT32(clock_ctl, AwSdHostState),
1119
+ VMSTATE_UINT32(timeout, AwSdHostState),
1120
+ VMSTATE_UINT32(bus_width, AwSdHostState),
1121
+ VMSTATE_UINT32(block_size, AwSdHostState),
1122
+ VMSTATE_UINT32(byte_count, AwSdHostState),
1123
+ VMSTATE_UINT32(transfer_cnt, AwSdHostState),
1124
+ VMSTATE_UINT32(command, AwSdHostState),
1125
+ VMSTATE_UINT32(command_arg, AwSdHostState),
1126
+ VMSTATE_UINT32_ARRAY(response, AwSdHostState, 4),
1127
+ VMSTATE_UINT32(irq_mask, AwSdHostState),
1128
+ VMSTATE_UINT32(irq_status, AwSdHostState),
1129
+ VMSTATE_UINT32(status, AwSdHostState),
1130
+ VMSTATE_UINT32(fifo_wlevel, AwSdHostState),
1131
+ VMSTATE_UINT32(fifo_func_sel, AwSdHostState),
1132
+ VMSTATE_UINT32(debug_enable, AwSdHostState),
1133
+ VMSTATE_UINT32(auto12_arg, AwSdHostState),
1134
+ VMSTATE_UINT32(newtiming_set, AwSdHostState),
1135
+ VMSTATE_UINT32(newtiming_debug, AwSdHostState),
1136
+ VMSTATE_UINT32(hardware_rst, AwSdHostState),
1137
+ VMSTATE_UINT32(dmac, AwSdHostState),
1138
+ VMSTATE_UINT32(desc_base, AwSdHostState),
1139
+ VMSTATE_UINT32(dmac_status, AwSdHostState),
1140
+ VMSTATE_UINT32(dmac_irq, AwSdHostState),
1141
+ VMSTATE_UINT32(card_threshold, AwSdHostState),
1142
+ VMSTATE_UINT32(startbit_detect, AwSdHostState),
1143
+ VMSTATE_UINT32(response_crc, AwSdHostState),
1144
+ VMSTATE_UINT32_ARRAY(data_crc, AwSdHostState, 8),
1145
+ VMSTATE_UINT32(status_crc, AwSdHostState),
1146
+ VMSTATE_END_OF_LIST()
1147
+ }
1148
+};
1149
+
1150
+static void allwinner_sdhost_init(Object *obj)
1151
+{
1152
+ AwSdHostState *s = AW_SDHOST(obj);
1153
+
1154
+ qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
1155
+ TYPE_AW_SDHOST_BUS, DEVICE(s), "sd-bus");
1156
+
1157
+ memory_region_init_io(&s->iomem, obj, &allwinner_sdhost_ops, s,
1158
+ TYPE_AW_SDHOST, 4 * KiB);
1159
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
1160
+ sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
1161
+}
1162
+
1163
+static void allwinner_sdhost_reset(DeviceState *dev)
1164
+{
1165
+ AwSdHostState *s = AW_SDHOST(dev);
1166
+
1167
+ s->global_ctl = REG_SD_GCTL_RST;
1168
+ s->clock_ctl = REG_SD_CKCR_RST;
1169
+ s->timeout = REG_SD_TMOR_RST;
1170
+ s->bus_width = REG_SD_BWDR_RST;
1171
+ s->block_size = REG_SD_BKSR_RST;
1172
+ s->byte_count = REG_SD_BYCR_RST;
1173
+ s->transfer_cnt = 0;
1174
+
1175
+ s->command = REG_SD_CMDR_RST;
1176
+ s->command_arg = REG_SD_CAGR_RST;
1177
+
1178
+ for (int i = 0; i < ARRAY_SIZE(s->response); i++) {
1179
+ s->response[i] = REG_SD_RESP_RST;
1180
+ }
1181
+
1182
+ s->irq_mask = REG_SD_IMKR_RST;
1183
+ s->irq_status = REG_SD_RISR_RST;
1184
+ s->status = REG_SD_STAR_RST;
1185
+
1186
+ s->fifo_wlevel = REG_SD_FWLR_RST;
1187
+ s->fifo_func_sel = REG_SD_FUNS_RST;
1188
+ s->debug_enable = REG_SD_DBGC_RST;
1189
+ s->auto12_arg = REG_SD_A12A_RST;
1190
+ s->newtiming_set = REG_SD_NTSR_RST;
1191
+ s->newtiming_debug = REG_SD_SDBG_RST;
1192
+ s->hardware_rst = REG_SD_HWRST_RST;
1193
+ s->dmac = REG_SD_DMAC_RST;
1194
+ s->desc_base = REG_SD_DLBA_RST;
1195
+ s->dmac_status = REG_SD_IDST_RST;
1196
+ s->dmac_irq = REG_SD_IDIE_RST;
1197
+ s->card_threshold = REG_SD_THLDC_RST;
1198
+ s->startbit_detect = REG_SD_DSBD_RST;
1199
+ s->response_crc = REG_SD_RES_CRC_RST;
1200
+
1201
+ for (int i = 0; i < ARRAY_SIZE(s->data_crc); i++) {
1202
+ s->data_crc[i] = REG_SD_DATA_CRC_RST;
1203
+ }
1204
+
1205
+ s->status_crc = REG_SD_CRC_STA_RST;
1206
+}
1207
+
1208
+static void allwinner_sdhost_bus_class_init(ObjectClass *klass, void *data)
1209
+{
1210
+ SDBusClass *sbc = SD_BUS_CLASS(klass);
1211
+
1212
+ sbc->set_inserted = allwinner_sdhost_set_inserted;
1213
+}
1214
+
1215
+static void allwinner_sdhost_class_init(ObjectClass *klass, void *data)
1216
+{
1217
+ DeviceClass *dc = DEVICE_CLASS(klass);
1218
+
1219
+ dc->reset = allwinner_sdhost_reset;
1220
+ dc->vmsd = &vmstate_allwinner_sdhost;
1221
+}
1222
+
1223
+static void allwinner_sdhost_sun4i_class_init(ObjectClass *klass, void *data)
1224
+{
1225
+ AwSdHostClass *sc = AW_SDHOST_CLASS(klass);
1226
+ sc->max_desc_size = 8 * KiB;
1227
+}
1228
+
1229
+static void allwinner_sdhost_sun5i_class_init(ObjectClass *klass, void *data)
1230
+{
1231
+ AwSdHostClass *sc = AW_SDHOST_CLASS(klass);
1232
+ sc->max_desc_size = 64 * KiB;
1233
+}
1234
+
1235
+static TypeInfo allwinner_sdhost_info = {
1236
+ .name = TYPE_AW_SDHOST,
1237
+ .parent = TYPE_SYS_BUS_DEVICE,
1238
+ .instance_init = allwinner_sdhost_init,
1239
+ .instance_size = sizeof(AwSdHostState),
1240
+ .class_init = allwinner_sdhost_class_init,
1241
+ .class_size = sizeof(AwSdHostClass),
1242
+ .abstract = true,
1243
+};
1244
+
1245
+static const TypeInfo allwinner_sdhost_sun4i_info = {
1246
+ .name = TYPE_AW_SDHOST_SUN4I,
1247
+ .parent = TYPE_AW_SDHOST,
1248
+ .class_init = allwinner_sdhost_sun4i_class_init,
1249
+};
1250
+
1251
+static const TypeInfo allwinner_sdhost_sun5i_info = {
1252
+ .name = TYPE_AW_SDHOST_SUN5I,
1253
+ .parent = TYPE_AW_SDHOST,
1254
+ .class_init = allwinner_sdhost_sun5i_class_init,
1255
+};
1256
+
1257
+static const TypeInfo allwinner_sdhost_bus_info = {
1258
+ .name = TYPE_AW_SDHOST_BUS,
1259
+ .parent = TYPE_SD_BUS,
1260
+ .instance_size = sizeof(SDBus),
1261
+ .class_init = allwinner_sdhost_bus_class_init,
1262
+};
1263
+
1264
+static void allwinner_sdhost_register_types(void)
1265
+{
1266
+ type_register_static(&allwinner_sdhost_info);
1267
+ type_register_static(&allwinner_sdhost_sun4i_info);
1268
+ type_register_static(&allwinner_sdhost_sun5i_info);
1269
+ type_register_static(&allwinner_sdhost_bus_info);
1270
+}
1271
+
1272
+type_init(allwinner_sdhost_register_types)
1273
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
1274
index XXXXXXX..XXXXXXX 100644
1275
--- a/hw/arm/Kconfig
1276
+++ b/hw/arm/Kconfig
1277
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_H3
1278
select UNIMP
1279
select USB_OHCI
1280
select USB_EHCI_SYSBUS
1281
+ select SD
1282
1283
config RASPI
1284
bool
1285
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
1286
index XXXXXXX..XXXXXXX 100644
1287
--- a/hw/sd/trace-events
1288
+++ b/hw/sd/trace-events
1289
@@ -XXX,XX +XXX,XX @@
1290
# See docs/devel/tracing.txt for syntax documentation.
1291
1292
+# allwinner-sdhost.c
1293
+allwinner_sdhost_set_inserted(bool inserted) "inserted %u"
1294
+allwinner_sdhost_process_desc(uint64_t desc_addr, uint32_t desc_size, bool is_write, uint32_t max_bytes) "desc_addr 0x%" PRIx64 " desc_size %" PRIu32 " is_write %u max_bytes %" PRIu32
1295
+allwinner_sdhost_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
1296
+allwinner_sdhost_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
1297
+allwinner_sdhost_update_irq(uint32_t irq) "IRQ bits 0x%" PRIx32
1298
+
1299
# bcm2835_sdhost.c
1300
bcm2835_sdhost_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
1301
bcm2835_sdhost_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
268
--
1302
--
269
2.20.1
1303
2.20.1
270
1304
271
1305
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
Avoid redundant computation of cpu state by passing it in
3
The Allwinner Sun8i System on Chip family includes an Ethernet MAC (EMAC)
4
from the caller, which has already computed it for itself.
4
which provides 10M/100M/1000M Ethernet connectivity. This commit
5
adds support for the Allwinner EMAC from the Sun8i family (H2+, H3, A33, etc),
6
including emulation for the following functionality:
5
7
6
Tested-by: Alex Bennée <alex.bennee@linaro.org>
8
* DMA transfers
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
* MII interface
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
* Transmit CRC calculation
9
Message-id: 20200206105448.4726-40-richard.henderson@linaro.org
11
12
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
13
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
14
Message-id: 20200311221854.30370-10-nieklinnenbank@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
16
---
12
target/arm/cpu.c | 22 ++++++++++++----------
17
hw/net/Makefile.objs | 1 +
13
1 file changed, 12 insertions(+), 10 deletions(-)
18
include/hw/arm/allwinner-h3.h | 3 +
19
include/hw/net/allwinner-sun8i-emac.h | 99 +++
20
hw/arm/allwinner-h3.c | 16 +-
21
hw/arm/orangepi.c | 3 +
22
hw/net/allwinner-sun8i-emac.c | 871 ++++++++++++++++++++++++++
23
hw/arm/Kconfig | 1 +
24
hw/net/Kconfig | 3 +
25
hw/net/trace-events | 10 +
26
9 files changed, 1006 insertions(+), 1 deletion(-)
27
create mode 100644 include/hw/net/allwinner-sun8i-emac.h
28
create mode 100644 hw/net/allwinner-sun8i-emac.c
14
29
15
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
30
diff --git a/hw/net/Makefile.objs b/hw/net/Makefile.objs
16
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.c
32
--- a/hw/net/Makefile.objs
18
+++ b/target/arm/cpu.c
33
+++ b/hw/net/Makefile.objs
19
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
34
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_XGMAC) += xgmac.o
35
common-obj-$(CONFIG_MIPSNET) += mipsnet.o
36
common-obj-$(CONFIG_XILINX_AXI) += xilinx_axienet.o
37
common-obj-$(CONFIG_ALLWINNER_EMAC) += allwinner_emac.o
38
+common-obj-$(CONFIG_ALLWINNER_SUN8I_EMAC) += allwinner-sun8i-emac.o
39
common-obj-$(CONFIG_IMX_FEC) += imx_fec.o
40
41
common-obj-$(CONFIG_CADENCE) += cadence_gem.o
42
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
43
index XXXXXXX..XXXXXXX 100644
44
--- a/include/hw/arm/allwinner-h3.h
45
+++ b/include/hw/arm/allwinner-h3.h
46
@@ -XXX,XX +XXX,XX @@
47
#include "hw/misc/allwinner-h3-sysctrl.h"
48
#include "hw/misc/allwinner-sid.h"
49
#include "hw/sd/allwinner-sdhost.h"
50
+#include "hw/net/allwinner-sun8i-emac.h"
51
#include "target/arm/cpu.h"
52
53
/**
54
@@ -XXX,XX +XXX,XX @@ enum {
55
AW_H3_UART1,
56
AW_H3_UART2,
57
AW_H3_UART3,
58
+ AW_H3_EMAC,
59
AW_H3_GIC_DIST,
60
AW_H3_GIC_CPU,
61
AW_H3_GIC_HYP,
62
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
63
AwH3SysCtrlState sysctrl;
64
AwSidState sid;
65
AwSdHostState mmc0;
66
+ AwSun8iEmacState emac;
67
GICState gic;
68
MemoryRegion sram_a1;
69
MemoryRegion sram_a2;
70
diff --git a/include/hw/net/allwinner-sun8i-emac.h b/include/hw/net/allwinner-sun8i-emac.h
71
new file mode 100644
72
index XXXXXXX..XXXXXXX
73
--- /dev/null
74
+++ b/include/hw/net/allwinner-sun8i-emac.h
75
@@ -XXX,XX +XXX,XX @@
76
+/*
77
+ * Allwinner Sun8i Ethernet MAC emulation
78
+ *
79
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
80
+ *
81
+ * This program is free software: you can redistribute it and/or modify
82
+ * it under the terms of the GNU General Public License as published by
83
+ * the Free Software Foundation, either version 2 of the License, or
84
+ * (at your option) any later version.
85
+ *
86
+ * This program is distributed in the hope that it will be useful,
87
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
88
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
89
+ * GNU General Public License for more details.
90
+ *
91
+ * You should have received a copy of the GNU General Public License
92
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
93
+ */
94
+
95
+#ifndef HW_NET_ALLWINNER_SUN8I_EMAC_H
96
+#define HW_NET_ALLWINNER_SUN8I_EMAC_H
97
+
98
+#include "qom/object.h"
99
+#include "net/net.h"
100
+#include "hw/sysbus.h"
101
+
102
+/**
103
+ * Object model
104
+ * @{
105
+ */
106
+
107
+#define TYPE_AW_SUN8I_EMAC "allwinner-sun8i-emac"
108
+#define AW_SUN8I_EMAC(obj) \
109
+ OBJECT_CHECK(AwSun8iEmacState, (obj), TYPE_AW_SUN8I_EMAC)
110
+
111
+/** @} */
112
+
113
+/**
114
+ * Allwinner Sun8i EMAC object instance state
115
+ */
116
+typedef struct AwSun8iEmacState {
117
+ /*< private >*/
118
+ SysBusDevice parent_obj;
119
+ /*< public >*/
120
+
121
+ /** Maps I/O registers in physical memory */
122
+ MemoryRegion iomem;
123
+
124
+ /** Interrupt output signal to notify CPU */
125
+ qemu_irq irq;
126
+
127
+ /** Generic Network Interface Controller (NIC) for networking API */
128
+ NICState *nic;
129
+
130
+ /** Generic Network Interface Controller (NIC) configuration */
131
+ NICConf conf;
132
+
133
+ /**
134
+ * @name Media Independent Interface (MII)
135
+ * @{
136
+ */
137
+
138
+ uint8_t mii_phy_addr; /**< PHY address */
139
+ uint32_t mii_cr; /**< Control */
140
+ uint32_t mii_st; /**< Status */
141
+ uint32_t mii_adv; /**< Advertised Abilities */
142
+
143
+ /** @} */
144
+
145
+ /**
146
+ * @name Hardware Registers
147
+ * @{
148
+ */
149
+
150
+ uint32_t basic_ctl0; /**< Basic Control 0 */
151
+ uint32_t basic_ctl1; /**< Basic Control 1 */
152
+ uint32_t int_en; /**< Interrupt Enable */
153
+ uint32_t int_sta; /**< Interrupt Status */
154
+ uint32_t frm_flt; /**< Receive Frame Filter */
155
+
156
+ uint32_t rx_ctl0; /**< Receive Control 0 */
157
+ uint32_t rx_ctl1; /**< Receive Control 1 */
158
+ uint32_t rx_desc_head; /**< Receive Descriptor List Address */
159
+ uint32_t rx_desc_curr; /**< Current Receive Descriptor Address */
160
+
161
+ uint32_t tx_ctl0; /**< Transmit Control 0 */
162
+ uint32_t tx_ctl1; /**< Transmit Control 1 */
163
+ uint32_t tx_desc_head; /**< Transmit Descriptor List Address */
164
+ uint32_t tx_desc_curr; /**< Current Transmit Descriptor Address */
165
+ uint32_t tx_flowctl; /**< Transmit Flow Control */
166
+
167
+ uint32_t mii_cmd; /**< Management Interface Command */
168
+ uint32_t mii_data; /**< Management Interface Data */
169
+
170
+ /** @} */
171
+
172
+} AwSun8iEmacState;
173
+
174
+#endif /* HW_NET_ALLWINNER_SUN8I_H */
175
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
176
index XXXXXXX..XXXXXXX 100644
177
--- a/hw/arm/allwinner-h3.c
178
+++ b/hw/arm/allwinner-h3.c
179
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
180
[AW_H3_UART1] = 0x01c28400,
181
[AW_H3_UART2] = 0x01c28800,
182
[AW_H3_UART3] = 0x01c28c00,
183
+ [AW_H3_EMAC] = 0x01c30000,
184
[AW_H3_GIC_DIST] = 0x01c81000,
185
[AW_H3_GIC_CPU] = 0x01c82000,
186
[AW_H3_GIC_HYP] = 0x01c84000,
187
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
188
{ "twi1", 0x01c2b000, 1 * KiB },
189
{ "twi2", 0x01c2b400, 1 * KiB },
190
{ "scr", 0x01c2c400, 1 * KiB },
191
- { "emac", 0x01c30000, 64 * KiB },
192
{ "gpu", 0x01c40000, 64 * KiB },
193
{ "hstmr", 0x01c60000, 4 * KiB },
194
{ "dramcom", 0x01c62000, 4 * KiB },
195
@@ -XXX,XX +XXX,XX @@ enum {
196
AW_H3_GIC_SPI_OHCI2 = 77,
197
AW_H3_GIC_SPI_EHCI3 = 78,
198
AW_H3_GIC_SPI_OHCI3 = 79,
199
+ AW_H3_GIC_SPI_EMAC = 82
200
};
201
202
/* Allwinner H3 general constants */
203
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
204
205
sysbus_init_child_obj(obj, "mmc0", &s->mmc0, sizeof(s->mmc0),
206
TYPE_AW_SDHOST_SUN5I);
207
+
208
+ sysbus_init_child_obj(obj, "emac", &s->emac, sizeof(s->emac),
209
+ TYPE_AW_SUN8I_EMAC);
20
}
210
}
21
211
22
static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
212
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
23
- unsigned int target_el)
213
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
24
+ unsigned int target_el,
214
object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->mmc0),
25
+ unsigned int cur_el, bool secure,
215
"sd-bus", &error_abort);
26
+ uint64_t hcr_el2)
216
27
{
217
+ /* EMAC */
28
CPUARMState *env = cs->env_ptr;
218
+ if (nd_table[0].used) {
29
- unsigned int cur_el = arm_current_el(env);
219
+ qemu_check_nic_model(&nd_table[0], TYPE_AW_SUN8I_EMAC);
30
- bool secure = arm_is_secure(env);
220
+ qdev_set_nic_properties(DEVICE(&s->emac), &nd_table[0]);
31
bool pstate_unmasked;
221
+ }
32
int8_t unmasked = 0;
222
+ qdev_init_nofail(DEVICE(&s->emac));
33
- uint64_t hcr_el2;
223
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->emac), 0, s->memmap[AW_H3_EMAC]);
34
224
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->emac), 0,
35
/*
225
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_EMAC));
36
* Don't take exceptions if they target a lower EL.
226
+
37
@@ -XXX,XX +XXX,XX @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
227
/* Universal Serial Bus */
38
return false;
228
sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI0],
229
qdev_get_gpio_in(DEVICE(&s->gic),
230
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
231
index XXXXXXX..XXXXXXX 100644
232
--- a/hw/arm/orangepi.c
233
+++ b/hw/arm/orangepi.c
234
@@ -XXX,XX +XXX,XX @@ static void orangepi_init(MachineState *machine)
235
warn_report("Security Identifier value does not include H3 prefix");
39
}
236
}
40
237
41
- hcr_el2 = arm_hcr_el2_eff(env);
238
+ /* Setup EMAC properties */
42
-
239
+ object_property_set_int(OBJECT(&h3->emac), 1, "phy-addr", &error_abort);
43
switch (excp_idx) {
240
+
44
case EXCP_FIQ:
241
/* Mark H3 object realized */
45
pstate_unmasked = !(env->daif & PSTATE_F);
242
object_property_set_bool(OBJECT(h3), true, "realized", &error_abort);
46
@@ -XXX,XX +XXX,XX @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
243
47
CPUARMState *env = cs->env_ptr;
244
diff --git a/hw/net/allwinner-sun8i-emac.c b/hw/net/allwinner-sun8i-emac.c
48
uint32_t cur_el = arm_current_el(env);
245
new file mode 100644
49
bool secure = arm_is_secure(env);
246
index XXXXXXX..XXXXXXX
50
+ uint64_t hcr_el2 = arm_hcr_el2_eff(env);
247
--- /dev/null
51
uint32_t target_el;
248
+++ b/hw/net/allwinner-sun8i-emac.c
52
uint32_t excp_idx;
249
@@ -XXX,XX +XXX,XX @@
53
bool ret = false;
250
+/*
54
@@ -XXX,XX +XXX,XX @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
251
+ * Allwinner Sun8i Ethernet MAC emulation
55
if (interrupt_request & CPU_INTERRUPT_FIQ) {
252
+ *
56
excp_idx = EXCP_FIQ;
253
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
57
target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure);
254
+ *
58
- if (arm_excp_unmasked(cs, excp_idx, target_el)) {
255
+ * This program is free software: you can redistribute it and/or modify
59
+ if (arm_excp_unmasked(cs, excp_idx, target_el,
256
+ * it under the terms of the GNU General Public License as published by
60
+ cur_el, secure, hcr_el2)) {
257
+ * the Free Software Foundation, either version 2 of the License, or
61
cs->exception_index = excp_idx;
258
+ * (at your option) any later version.
62
env->exception.target_el = target_el;
259
+ *
63
cc->do_interrupt(cs);
260
+ * This program is distributed in the hope that it will be useful,
64
@@ -XXX,XX +XXX,XX @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
261
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
65
if (interrupt_request & CPU_INTERRUPT_HARD) {
262
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
66
excp_idx = EXCP_IRQ;
263
+ * GNU General Public License for more details.
67
target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure);
264
+ *
68
- if (arm_excp_unmasked(cs, excp_idx, target_el)) {
265
+ * You should have received a copy of the GNU General Public License
69
+ if (arm_excp_unmasked(cs, excp_idx, target_el,
266
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
70
+ cur_el, secure, hcr_el2)) {
267
+ */
71
cs->exception_index = excp_idx;
268
+
72
env->exception.target_el = target_el;
269
+#include "qemu/osdep.h"
73
cc->do_interrupt(cs);
270
+#include "qemu/units.h"
74
@@ -XXX,XX +XXX,XX @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
271
+#include "hw/sysbus.h"
75
if (interrupt_request & CPU_INTERRUPT_VIRQ) {
272
+#include "migration/vmstate.h"
76
excp_idx = EXCP_VIRQ;
273
+#include "net/net.h"
77
target_el = 1;
274
+#include "hw/irq.h"
78
- if (arm_excp_unmasked(cs, excp_idx, target_el)) {
275
+#include "hw/qdev-properties.h"
79
+ if (arm_excp_unmasked(cs, excp_idx, target_el,
276
+#include "qemu/log.h"
80
+ cur_el, secure, hcr_el2)) {
277
+#include "trace.h"
81
cs->exception_index = excp_idx;
278
+#include "net/checksum.h"
82
env->exception.target_el = target_el;
279
+#include "qemu/module.h"
83
cc->do_interrupt(cs);
280
+#include "exec/cpu-common.h"
84
@@ -XXX,XX +XXX,XX @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
281
+#include "hw/net/allwinner-sun8i-emac.h"
85
if (interrupt_request & CPU_INTERRUPT_VFIQ) {
282
+
86
excp_idx = EXCP_VFIQ;
283
+/* EMAC register offsets */
87
target_el = 1;
284
+enum {
88
- if (arm_excp_unmasked(cs, excp_idx, target_el)) {
285
+ REG_BASIC_CTL_0 = 0x0000, /* Basic Control 0 */
89
+ if (arm_excp_unmasked(cs, excp_idx, target_el,
286
+ REG_BASIC_CTL_1 = 0x0004, /* Basic Control 1 */
90
+ cur_el, secure, hcr_el2)) {
287
+ REG_INT_STA = 0x0008, /* Interrupt Status */
91
cs->exception_index = excp_idx;
288
+ REG_INT_EN = 0x000C, /* Interrupt Enable */
92
env->exception.target_el = target_el;
289
+ REG_TX_CTL_0 = 0x0010, /* Transmit Control 0 */
93
cc->do_interrupt(cs);
290
+ REG_TX_CTL_1 = 0x0014, /* Transmit Control 1 */
291
+ REG_TX_FLOW_CTL = 0x001C, /* Transmit Flow Control */
292
+ REG_TX_DMA_DESC_LIST = 0x0020, /* Transmit Descriptor List Address */
293
+ REG_RX_CTL_0 = 0x0024, /* Receive Control 0 */
294
+ REG_RX_CTL_1 = 0x0028, /* Receive Control 1 */
295
+ REG_RX_DMA_DESC_LIST = 0x0034, /* Receive Descriptor List Address */
296
+ REG_FRM_FLT = 0x0038, /* Receive Frame Filter */
297
+ REG_RX_HASH_0 = 0x0040, /* Receive Hash Table 0 */
298
+ REG_RX_HASH_1 = 0x0044, /* Receive Hash Table 1 */
299
+ REG_MII_CMD = 0x0048, /* Management Interface Command */
300
+ REG_MII_DATA = 0x004C, /* Management Interface Data */
301
+ REG_ADDR_HIGH = 0x0050, /* MAC Address High */
302
+ REG_ADDR_LOW = 0x0054, /* MAC Address Low */
303
+ REG_TX_DMA_STA = 0x00B0, /* Transmit DMA Status */
304
+ REG_TX_CUR_DESC = 0x00B4, /* Transmit Current Descriptor */
305
+ REG_TX_CUR_BUF = 0x00B8, /* Transmit Current Buffer */
306
+ REG_RX_DMA_STA = 0x00C0, /* Receive DMA Status */
307
+ REG_RX_CUR_DESC = 0x00C4, /* Receive Current Descriptor */
308
+ REG_RX_CUR_BUF = 0x00C8, /* Receive Current Buffer */
309
+ REG_RGMII_STA = 0x00D0, /* RGMII Status */
310
+};
311
+
312
+/* EMAC register flags */
313
+enum {
314
+ BASIC_CTL0_100Mbps = (0b11 << 2),
315
+ BASIC_CTL0_FD = (1 << 0),
316
+ BASIC_CTL1_SOFTRST = (1 << 0),
317
+};
318
+
319
+enum {
320
+ INT_STA_RGMII_LINK = (1 << 16),
321
+ INT_STA_RX_EARLY = (1 << 13),
322
+ INT_STA_RX_OVERFLOW = (1 << 12),
323
+ INT_STA_RX_TIMEOUT = (1 << 11),
324
+ INT_STA_RX_DMA_STOP = (1 << 10),
325
+ INT_STA_RX_BUF_UA = (1 << 9),
326
+ INT_STA_RX = (1 << 8),
327
+ INT_STA_TX_EARLY = (1 << 5),
328
+ INT_STA_TX_UNDERFLOW = (1 << 4),
329
+ INT_STA_TX_TIMEOUT = (1 << 3),
330
+ INT_STA_TX_BUF_UA = (1 << 2),
331
+ INT_STA_TX_DMA_STOP = (1 << 1),
332
+ INT_STA_TX = (1 << 0),
333
+};
334
+
335
+enum {
336
+ INT_EN_RX_EARLY = (1 << 13),
337
+ INT_EN_RX_OVERFLOW = (1 << 12),
338
+ INT_EN_RX_TIMEOUT = (1 << 11),
339
+ INT_EN_RX_DMA_STOP = (1 << 10),
340
+ INT_EN_RX_BUF_UA = (1 << 9),
341
+ INT_EN_RX = (1 << 8),
342
+ INT_EN_TX_EARLY = (1 << 5),
343
+ INT_EN_TX_UNDERFLOW = (1 << 4),
344
+ INT_EN_TX_TIMEOUT = (1 << 3),
345
+ INT_EN_TX_BUF_UA = (1 << 2),
346
+ INT_EN_TX_DMA_STOP = (1 << 1),
347
+ INT_EN_TX = (1 << 0),
348
+};
349
+
350
+enum {
351
+ TX_CTL0_TX_EN = (1 << 31),
352
+ TX_CTL1_TX_DMA_START = (1 << 31),
353
+ TX_CTL1_TX_DMA_EN = (1 << 30),
354
+ TX_CTL1_TX_FLUSH = (1 << 0),
355
+};
356
+
357
+enum {
358
+ RX_CTL0_RX_EN = (1 << 31),
359
+ RX_CTL0_STRIP_FCS = (1 << 28),
360
+ RX_CTL0_CRC_IPV4 = (1 << 27),
361
+};
362
+
363
+enum {
364
+ RX_CTL1_RX_DMA_START = (1 << 31),
365
+ RX_CTL1_RX_DMA_EN = (1 << 30),
366
+ RX_CTL1_RX_MD = (1 << 1),
367
+};
368
+
369
+enum {
370
+ RX_FRM_FLT_DIS_ADDR = (1 << 31),
371
+};
372
+
373
+enum {
374
+ MII_CMD_PHY_ADDR_SHIFT = (12),
375
+ MII_CMD_PHY_ADDR_MASK = (0xf000),
376
+ MII_CMD_PHY_REG_SHIFT = (4),
377
+ MII_CMD_PHY_REG_MASK = (0xf0),
378
+ MII_CMD_PHY_RW = (1 << 1),
379
+ MII_CMD_PHY_BUSY = (1 << 0),
380
+};
381
+
382
+enum {
383
+ TX_DMA_STA_STOP = (0b000),
384
+ TX_DMA_STA_RUN_FETCH = (0b001),
385
+ TX_DMA_STA_WAIT_STA = (0b010),
386
+};
387
+
388
+enum {
389
+ RX_DMA_STA_STOP = (0b000),
390
+ RX_DMA_STA_RUN_FETCH = (0b001),
391
+ RX_DMA_STA_WAIT_FRM = (0b011),
392
+};
393
+
394
+/* EMAC register reset values */
395
+enum {
396
+ REG_BASIC_CTL_1_RST = 0x08000000,
397
+};
398
+
399
+/* EMAC constants */
400
+enum {
401
+ AW_SUN8I_EMAC_MIN_PKT_SZ = 64
402
+};
403
+
404
+/* Transmit/receive frame descriptor */
405
+typedef struct FrameDescriptor {
406
+ uint32_t status;
407
+ uint32_t status2;
408
+ uint32_t addr;
409
+ uint32_t next;
410
+} FrameDescriptor;
411
+
412
+/* Frame descriptor flags */
413
+enum {
414
+ DESC_STATUS_CTL = (1 << 31),
415
+ DESC_STATUS2_BUF_SIZE_MASK = (0x7ff),
416
+};
417
+
418
+/* Transmit frame descriptor flags */
419
+enum {
420
+ TX_DESC_STATUS_LENGTH_ERR = (1 << 14),
421
+ TX_DESC_STATUS2_FIRST_DESC = (1 << 29),
422
+ TX_DESC_STATUS2_LAST_DESC = (1 << 30),
423
+ TX_DESC_STATUS2_CHECKSUM_MASK = (0x3 << 27),
424
+};
425
+
426
+/* Receive frame descriptor flags */
427
+enum {
428
+ RX_DESC_STATUS_FIRST_DESC = (1 << 9),
429
+ RX_DESC_STATUS_LAST_DESC = (1 << 8),
430
+ RX_DESC_STATUS_FRM_LEN_MASK = (0x3fff0000),
431
+ RX_DESC_STATUS_FRM_LEN_SHIFT = (16),
432
+ RX_DESC_STATUS_NO_BUF = (1 << 14),
433
+ RX_DESC_STATUS_HEADER_ERR = (1 << 7),
434
+ RX_DESC_STATUS_LENGTH_ERR = (1 << 4),
435
+ RX_DESC_STATUS_CRC_ERR = (1 << 1),
436
+ RX_DESC_STATUS_PAYLOAD_ERR = (1 << 0),
437
+ RX_DESC_STATUS2_RX_INT_CTL = (1 << 31),
438
+};
439
+
440
+/* MII register offsets */
441
+enum {
442
+ MII_REG_CR = (0x0), /* Control */
443
+ MII_REG_ST = (0x1), /* Status */
444
+ MII_REG_ID_HIGH = (0x2), /* Identifier High */
445
+ MII_REG_ID_LOW = (0x3), /* Identifier Low */
446
+ MII_REG_ADV = (0x4), /* Advertised abilities */
447
+ MII_REG_LPA = (0x5), /* Link partner abilities */
448
+};
449
+
450
+/* MII register flags */
451
+enum {
452
+ MII_REG_CR_RESET = (1 << 15),
453
+ MII_REG_CR_POWERDOWN = (1 << 11),
454
+ MII_REG_CR_10Mbit = (0),
455
+ MII_REG_CR_100Mbit = (1 << 13),
456
+ MII_REG_CR_1000Mbit = (1 << 6),
457
+ MII_REG_CR_AUTO_NEG = (1 << 12),
458
+ MII_REG_CR_AUTO_NEG_RESTART = (1 << 9),
459
+ MII_REG_CR_FULLDUPLEX = (1 << 8),
460
+};
461
+
462
+enum {
463
+ MII_REG_ST_100BASE_T4 = (1 << 15),
464
+ MII_REG_ST_100BASE_X_FD = (1 << 14),
465
+ MII_REG_ST_100BASE_X_HD = (1 << 13),
466
+ MII_REG_ST_10_FD = (1 << 12),
467
+ MII_REG_ST_10_HD = (1 << 11),
468
+ MII_REG_ST_100BASE_T2_FD = (1 << 10),
469
+ MII_REG_ST_100BASE_T2_HD = (1 << 9),
470
+ MII_REG_ST_AUTONEG_COMPLETE = (1 << 5),
471
+ MII_REG_ST_AUTONEG_AVAIL = (1 << 3),
472
+ MII_REG_ST_LINK_UP = (1 << 2),
473
+};
474
+
475
+enum {
476
+ MII_REG_LPA_10_HD = (1 << 5),
477
+ MII_REG_LPA_10_FD = (1 << 6),
478
+ MII_REG_LPA_100_HD = (1 << 7),
479
+ MII_REG_LPA_100_FD = (1 << 8),
480
+ MII_REG_LPA_PAUSE = (1 << 10),
481
+ MII_REG_LPA_ASYMPAUSE = (1 << 11),
482
+};
483
+
484
+/* MII constants */
485
+enum {
486
+ MII_PHY_ID_HIGH = 0x0044,
487
+ MII_PHY_ID_LOW = 0x1400,
488
+};
489
+
490
+static void allwinner_sun8i_emac_mii_set_link(AwSun8iEmacState *s,
491
+ bool link_active)
492
+{
493
+ if (link_active) {
494
+ s->mii_st |= MII_REG_ST_LINK_UP;
495
+ } else {
496
+ s->mii_st &= ~MII_REG_ST_LINK_UP;
497
+ }
498
+}
499
+
500
+static void allwinner_sun8i_emac_mii_reset(AwSun8iEmacState *s,
501
+ bool link_active)
502
+{
503
+ s->mii_cr = MII_REG_CR_100Mbit | MII_REG_CR_AUTO_NEG |
504
+ MII_REG_CR_FULLDUPLEX;
505
+ s->mii_st = MII_REG_ST_100BASE_T4 | MII_REG_ST_100BASE_X_FD |
506
+ MII_REG_ST_100BASE_X_HD | MII_REG_ST_10_FD | MII_REG_ST_10_HD |
507
+ MII_REG_ST_100BASE_T2_FD | MII_REG_ST_100BASE_T2_HD |
508
+ MII_REG_ST_AUTONEG_COMPLETE | MII_REG_ST_AUTONEG_AVAIL;
509
+ s->mii_adv = 0;
510
+
511
+ allwinner_sun8i_emac_mii_set_link(s, link_active);
512
+}
513
+
514
+static void allwinner_sun8i_emac_mii_cmd(AwSun8iEmacState *s)
515
+{
516
+ uint8_t addr, reg;
517
+
518
+ addr = (s->mii_cmd & MII_CMD_PHY_ADDR_MASK) >> MII_CMD_PHY_ADDR_SHIFT;
519
+ reg = (s->mii_cmd & MII_CMD_PHY_REG_MASK) >> MII_CMD_PHY_REG_SHIFT;
520
+
521
+ if (addr != s->mii_phy_addr) {
522
+ return;
523
+ }
524
+
525
+ /* Read or write a PHY register? */
526
+ if (s->mii_cmd & MII_CMD_PHY_RW) {
527
+ trace_allwinner_sun8i_emac_mii_write_reg(reg, s->mii_data);
528
+
529
+ switch (reg) {
530
+ case MII_REG_CR:
531
+ if (s->mii_data & MII_REG_CR_RESET) {
532
+ allwinner_sun8i_emac_mii_reset(s, s->mii_st &
533
+ MII_REG_ST_LINK_UP);
534
+ } else {
535
+ s->mii_cr = s->mii_data & ~(MII_REG_CR_RESET |
536
+ MII_REG_CR_AUTO_NEG_RESTART);
537
+ }
538
+ break;
539
+ case MII_REG_ADV:
540
+ s->mii_adv = s->mii_data;
541
+ break;
542
+ case MII_REG_ID_HIGH:
543
+ case MII_REG_ID_LOW:
544
+ case MII_REG_LPA:
545
+ break;
546
+ default:
547
+ qemu_log_mask(LOG_UNIMP, "allwinner-h3-emac: write access to "
548
+ "unknown MII register 0x%x\n", reg);
549
+ break;
550
+ }
551
+ } else {
552
+ switch (reg) {
553
+ case MII_REG_CR:
554
+ s->mii_data = s->mii_cr;
555
+ break;
556
+ case MII_REG_ST:
557
+ s->mii_data = s->mii_st;
558
+ break;
559
+ case MII_REG_ID_HIGH:
560
+ s->mii_data = MII_PHY_ID_HIGH;
561
+ break;
562
+ case MII_REG_ID_LOW:
563
+ s->mii_data = MII_PHY_ID_LOW;
564
+ break;
565
+ case MII_REG_ADV:
566
+ s->mii_data = s->mii_adv;
567
+ break;
568
+ case MII_REG_LPA:
569
+ s->mii_data = MII_REG_LPA_10_HD | MII_REG_LPA_10_FD |
570
+ MII_REG_LPA_100_HD | MII_REG_LPA_100_FD |
571
+ MII_REG_LPA_PAUSE | MII_REG_LPA_ASYMPAUSE;
572
+ break;
573
+ default:
574
+ qemu_log_mask(LOG_UNIMP, "allwinner-h3-emac: read access to "
575
+ "unknown MII register 0x%x\n", reg);
576
+ s->mii_data = 0;
577
+ break;
578
+ }
579
+
580
+ trace_allwinner_sun8i_emac_mii_read_reg(reg, s->mii_data);
581
+ }
582
+}
583
+
584
+static void allwinner_sun8i_emac_update_irq(AwSun8iEmacState *s)
585
+{
586
+ qemu_set_irq(s->irq, (s->int_sta & s->int_en) != 0);
587
+}
588
+
589
+static uint32_t allwinner_sun8i_emac_next_desc(FrameDescriptor *desc,
590
+ size_t min_size)
591
+{
592
+ uint32_t paddr = desc->next;
593
+
594
+ cpu_physical_memory_read(paddr, desc, sizeof(*desc));
595
+
596
+ if ((desc->status & DESC_STATUS_CTL) &&
597
+ (desc->status2 & DESC_STATUS2_BUF_SIZE_MASK) >= min_size) {
598
+ return paddr;
599
+ } else {
600
+ return 0;
601
+ }
602
+}
603
+
604
+static uint32_t allwinner_sun8i_emac_get_desc(FrameDescriptor *desc,
605
+ uint32_t start_addr,
606
+ size_t min_size)
607
+{
608
+ uint32_t desc_addr = start_addr;
609
+
610
+ /* Note that the list is a cycle. Last entry points back to the head. */
611
+ while (desc_addr != 0) {
612
+ cpu_physical_memory_read(desc_addr, desc, sizeof(*desc));
613
+
614
+ if ((desc->status & DESC_STATUS_CTL) &&
615
+ (desc->status2 & DESC_STATUS2_BUF_SIZE_MASK) >= min_size) {
616
+ return desc_addr;
617
+ } else if (desc->next == start_addr) {
618
+ break;
619
+ } else {
620
+ desc_addr = desc->next;
621
+ }
622
+ }
623
+
624
+ return 0;
625
+}
626
+
627
+static uint32_t allwinner_sun8i_emac_rx_desc(AwSun8iEmacState *s,
628
+ FrameDescriptor *desc,
629
+ size_t min_size)
630
+{
631
+ return allwinner_sun8i_emac_get_desc(desc, s->rx_desc_curr, min_size);
632
+}
633
+
634
+static uint32_t allwinner_sun8i_emac_tx_desc(AwSun8iEmacState *s,
635
+ FrameDescriptor *desc,
636
+ size_t min_size)
637
+{
638
+ return allwinner_sun8i_emac_get_desc(desc, s->tx_desc_head, min_size);
639
+}
640
+
641
+static void allwinner_sun8i_emac_flush_desc(FrameDescriptor *desc,
642
+ uint32_t phys_addr)
643
+{
644
+ cpu_physical_memory_write(phys_addr, desc, sizeof(*desc));
645
+}
646
+
647
+static int allwinner_sun8i_emac_can_receive(NetClientState *nc)
648
+{
649
+ AwSun8iEmacState *s = qemu_get_nic_opaque(nc);
650
+ FrameDescriptor desc;
651
+
652
+ return (s->rx_ctl0 & RX_CTL0_RX_EN) &&
653
+ (allwinner_sun8i_emac_rx_desc(s, &desc, 0) != 0);
654
+}
655
+
656
+static ssize_t allwinner_sun8i_emac_receive(NetClientState *nc,
657
+ const uint8_t *buf,
658
+ size_t size)
659
+{
660
+ AwSun8iEmacState *s = qemu_get_nic_opaque(nc);
661
+ FrameDescriptor desc;
662
+ size_t bytes_left = size;
663
+ size_t desc_bytes = 0;
664
+ size_t pad_fcs_size = 4;
665
+ size_t padding = 0;
666
+
667
+ if (!(s->rx_ctl0 & RX_CTL0_RX_EN)) {
668
+ return -1;
669
+ }
670
+
671
+ s->rx_desc_curr = allwinner_sun8i_emac_rx_desc(s, &desc,
672
+ AW_SUN8I_EMAC_MIN_PKT_SZ);
673
+ if (!s->rx_desc_curr) {
674
+ s->int_sta |= INT_STA_RX_BUF_UA;
675
+ }
676
+
677
+ /* Keep filling RX descriptors until the whole frame is written */
678
+ while (s->rx_desc_curr && bytes_left > 0) {
679
+ desc.status &= ~DESC_STATUS_CTL;
680
+ desc.status &= ~RX_DESC_STATUS_FRM_LEN_MASK;
681
+
682
+ if (bytes_left == size) {
683
+ desc.status |= RX_DESC_STATUS_FIRST_DESC;
684
+ }
685
+
686
+ if ((desc.status2 & DESC_STATUS2_BUF_SIZE_MASK) <
687
+ (bytes_left + pad_fcs_size)) {
688
+ desc_bytes = desc.status2 & DESC_STATUS2_BUF_SIZE_MASK;
689
+ desc.status |= desc_bytes << RX_DESC_STATUS_FRM_LEN_SHIFT;
690
+ } else {
691
+ padding = pad_fcs_size;
692
+ if (bytes_left < AW_SUN8I_EMAC_MIN_PKT_SZ) {
693
+ padding += (AW_SUN8I_EMAC_MIN_PKT_SZ - bytes_left);
694
+ }
695
+
696
+ desc_bytes = (bytes_left);
697
+ desc.status |= RX_DESC_STATUS_LAST_DESC;
698
+ desc.status |= (bytes_left + padding)
699
+ << RX_DESC_STATUS_FRM_LEN_SHIFT;
700
+ }
701
+
702
+ cpu_physical_memory_write(desc.addr, buf, desc_bytes);
703
+ allwinner_sun8i_emac_flush_desc(&desc, s->rx_desc_curr);
704
+ trace_allwinner_sun8i_emac_receive(s->rx_desc_curr, desc.addr,
705
+ desc_bytes);
706
+
707
+ /* Check if frame needs to raise the receive interrupt */
708
+ if (!(desc.status2 & RX_DESC_STATUS2_RX_INT_CTL)) {
709
+ s->int_sta |= INT_STA_RX;
710
+ }
711
+
712
+ /* Increment variables */
713
+ buf += desc_bytes;
714
+ bytes_left -= desc_bytes;
715
+
716
+ /* Move to the next descriptor */
717
+ s->rx_desc_curr = allwinner_sun8i_emac_next_desc(&desc, 64);
718
+ if (!s->rx_desc_curr) {
719
+ /* Not enough buffer space available */
720
+ s->int_sta |= INT_STA_RX_BUF_UA;
721
+ s->rx_desc_curr = s->rx_desc_head;
722
+ break;
723
+ }
724
+ }
725
+
726
+ /* Report receive DMA is finished */
727
+ s->rx_ctl1 &= ~RX_CTL1_RX_DMA_START;
728
+ allwinner_sun8i_emac_update_irq(s);
729
+
730
+ return size;
731
+}
732
+
733
+static void allwinner_sun8i_emac_transmit(AwSun8iEmacState *s)
734
+{
735
+ NetClientState *nc = qemu_get_queue(s->nic);
736
+ FrameDescriptor desc;
737
+ size_t bytes = 0;
738
+ size_t packet_bytes = 0;
739
+ size_t transmitted = 0;
740
+ static uint8_t packet_buf[2048];
741
+
742
+ s->tx_desc_curr = allwinner_sun8i_emac_tx_desc(s, &desc, 0);
743
+
744
+ /* Read all transmit descriptors */
745
+ while (s->tx_desc_curr != 0) {
746
+
747
+ /* Read from physical memory into packet buffer */
748
+ bytes = desc.status2 & DESC_STATUS2_BUF_SIZE_MASK;
749
+ if (bytes + packet_bytes > sizeof(packet_buf)) {
750
+ desc.status |= TX_DESC_STATUS_LENGTH_ERR;
751
+ break;
752
+ }
753
+ cpu_physical_memory_read(desc.addr, packet_buf + packet_bytes, bytes);
754
+ packet_bytes += bytes;
755
+ desc.status &= ~DESC_STATUS_CTL;
756
+ allwinner_sun8i_emac_flush_desc(&desc, s->tx_desc_curr);
757
+
758
+ /* After the last descriptor, send the packet */
759
+ if (desc.status2 & TX_DESC_STATUS2_LAST_DESC) {
760
+ if (desc.status2 & TX_DESC_STATUS2_CHECKSUM_MASK) {
761
+ net_checksum_calculate(packet_buf, packet_bytes);
762
+ }
763
+
764
+ qemu_send_packet(nc, packet_buf, packet_bytes);
765
+ trace_allwinner_sun8i_emac_transmit(s->tx_desc_curr, desc.addr,
766
+ bytes);
767
+
768
+ packet_bytes = 0;
769
+ transmitted++;
770
+ }
771
+ s->tx_desc_curr = allwinner_sun8i_emac_next_desc(&desc, 0);
772
+ }
773
+
774
+ /* Raise transmit completed interrupt */
775
+ if (transmitted > 0) {
776
+ s->int_sta |= INT_STA_TX;
777
+ s->tx_ctl1 &= ~TX_CTL1_TX_DMA_START;
778
+ allwinner_sun8i_emac_update_irq(s);
779
+ }
780
+}
781
+
782
+static void allwinner_sun8i_emac_reset(DeviceState *dev)
783
+{
784
+ AwSun8iEmacState *s = AW_SUN8I_EMAC(dev);
785
+ NetClientState *nc = qemu_get_queue(s->nic);
786
+
787
+ trace_allwinner_sun8i_emac_reset();
788
+
789
+ s->mii_cmd = 0;
790
+ s->mii_data = 0;
791
+ s->basic_ctl0 = 0;
792
+ s->basic_ctl1 = REG_BASIC_CTL_1_RST;
793
+ s->int_en = 0;
794
+ s->int_sta = 0;
795
+ s->frm_flt = 0;
796
+ s->rx_ctl0 = 0;
797
+ s->rx_ctl1 = RX_CTL1_RX_MD;
798
+ s->rx_desc_head = 0;
799
+ s->rx_desc_curr = 0;
800
+ s->tx_ctl0 = 0;
801
+ s->tx_ctl1 = 0;
802
+ s->tx_desc_head = 0;
803
+ s->tx_desc_curr = 0;
804
+ s->tx_flowctl = 0;
805
+
806
+ allwinner_sun8i_emac_mii_reset(s, !nc->link_down);
807
+}
808
+
809
+static uint64_t allwinner_sun8i_emac_read(void *opaque, hwaddr offset,
810
+ unsigned size)
811
+{
812
+ AwSun8iEmacState *s = AW_SUN8I_EMAC(opaque);
813
+ uint64_t value = 0;
814
+ FrameDescriptor desc;
815
+
816
+ switch (offset) {
817
+ case REG_BASIC_CTL_0: /* Basic Control 0 */
818
+ value = s->basic_ctl0;
819
+ break;
820
+ case REG_BASIC_CTL_1: /* Basic Control 1 */
821
+ value = s->basic_ctl1;
822
+ break;
823
+ case REG_INT_STA: /* Interrupt Status */
824
+ value = s->int_sta;
825
+ break;
826
+ case REG_INT_EN: /* Interupt Enable */
827
+ value = s->int_en;
828
+ break;
829
+ case REG_TX_CTL_0: /* Transmit Control 0 */
830
+ value = s->tx_ctl0;
831
+ break;
832
+ case REG_TX_CTL_1: /* Transmit Control 1 */
833
+ value = s->tx_ctl1;
834
+ break;
835
+ case REG_TX_FLOW_CTL: /* Transmit Flow Control */
836
+ value = s->tx_flowctl;
837
+ break;
838
+ case REG_TX_DMA_DESC_LIST: /* Transmit Descriptor List Address */
839
+ value = s->tx_desc_head;
840
+ break;
841
+ case REG_RX_CTL_0: /* Receive Control 0 */
842
+ value = s->rx_ctl0;
843
+ break;
844
+ case REG_RX_CTL_1: /* Receive Control 1 */
845
+ value = s->rx_ctl1;
846
+ break;
847
+ case REG_RX_DMA_DESC_LIST: /* Receive Descriptor List Address */
848
+ value = s->rx_desc_head;
849
+ break;
850
+ case REG_FRM_FLT: /* Receive Frame Filter */
851
+ value = s->frm_flt;
852
+ break;
853
+ case REG_RX_HASH_0: /* Receive Hash Table 0 */
854
+ case REG_RX_HASH_1: /* Receive Hash Table 1 */
855
+ break;
856
+ case REG_MII_CMD: /* Management Interface Command */
857
+ value = s->mii_cmd;
858
+ break;
859
+ case REG_MII_DATA: /* Management Interface Data */
860
+ value = s->mii_data;
861
+ break;
862
+ case REG_ADDR_HIGH: /* MAC Address High */
863
+ value = *(((uint32_t *) (s->conf.macaddr.a)) + 1);
864
+ break;
865
+ case REG_ADDR_LOW: /* MAC Address Low */
866
+ value = *(uint32_t *) (s->conf.macaddr.a);
867
+ break;
868
+ case REG_TX_DMA_STA: /* Transmit DMA Status */
869
+ break;
870
+ case REG_TX_CUR_DESC: /* Transmit Current Descriptor */
871
+ value = s->tx_desc_curr;
872
+ break;
873
+ case REG_TX_CUR_BUF: /* Transmit Current Buffer */
874
+ if (s->tx_desc_curr != 0) {
875
+ cpu_physical_memory_read(s->tx_desc_curr, &desc, sizeof(desc));
876
+ value = desc.addr;
877
+ } else {
878
+ value = 0;
879
+ }
880
+ break;
881
+ case REG_RX_DMA_STA: /* Receive DMA Status */
882
+ break;
883
+ case REG_RX_CUR_DESC: /* Receive Current Descriptor */
884
+ value = s->rx_desc_curr;
885
+ break;
886
+ case REG_RX_CUR_BUF: /* Receive Current Buffer */
887
+ if (s->rx_desc_curr != 0) {
888
+ cpu_physical_memory_read(s->rx_desc_curr, &desc, sizeof(desc));
889
+ value = desc.addr;
890
+ } else {
891
+ value = 0;
892
+ }
893
+ break;
894
+ case REG_RGMII_STA: /* RGMII Status */
895
+ break;
896
+ default:
897
+ qemu_log_mask(LOG_UNIMP, "allwinner-h3-emac: read access to unknown "
898
+ "EMAC register 0x" TARGET_FMT_plx "\n",
899
+ offset);
900
+ }
901
+
902
+ trace_allwinner_sun8i_emac_read(offset, value);
903
+ return value;
904
+}
905
+
906
+static void allwinner_sun8i_emac_write(void *opaque, hwaddr offset,
907
+ uint64_t value, unsigned size)
908
+{
909
+ AwSun8iEmacState *s = AW_SUN8I_EMAC(opaque);
910
+ NetClientState *nc = qemu_get_queue(s->nic);
911
+
912
+ trace_allwinner_sun8i_emac_write(offset, value);
913
+
914
+ switch (offset) {
915
+ case REG_BASIC_CTL_0: /* Basic Control 0 */
916
+ s->basic_ctl0 = value;
917
+ break;
918
+ case REG_BASIC_CTL_1: /* Basic Control 1 */
919
+ if (value & BASIC_CTL1_SOFTRST) {
920
+ allwinner_sun8i_emac_reset(DEVICE(s));
921
+ value &= ~BASIC_CTL1_SOFTRST;
922
+ }
923
+ s->basic_ctl1 = value;
924
+ if (allwinner_sun8i_emac_can_receive(nc)) {
925
+ qemu_flush_queued_packets(nc);
926
+ }
927
+ break;
928
+ case REG_INT_STA: /* Interrupt Status */
929
+ s->int_sta &= ~value;
930
+ allwinner_sun8i_emac_update_irq(s);
931
+ break;
932
+ case REG_INT_EN: /* Interrupt Enable */
933
+ s->int_en = value;
934
+ allwinner_sun8i_emac_update_irq(s);
935
+ break;
936
+ case REG_TX_CTL_0: /* Transmit Control 0 */
937
+ s->tx_ctl0 = value;
938
+ break;
939
+ case REG_TX_CTL_1: /* Transmit Control 1 */
940
+ s->tx_ctl1 = value;
941
+ if (value & TX_CTL1_TX_DMA_EN) {
942
+ allwinner_sun8i_emac_transmit(s);
943
+ }
944
+ break;
945
+ case REG_TX_FLOW_CTL: /* Transmit Flow Control */
946
+ s->tx_flowctl = value;
947
+ break;
948
+ case REG_TX_DMA_DESC_LIST: /* Transmit Descriptor List Address */
949
+ s->tx_desc_head = value;
950
+ s->tx_desc_curr = value;
951
+ break;
952
+ case REG_RX_CTL_0: /* Receive Control 0 */
953
+ s->rx_ctl0 = value;
954
+ break;
955
+ case REG_RX_CTL_1: /* Receive Control 1 */
956
+ s->rx_ctl1 = value | RX_CTL1_RX_MD;
957
+ if ((value & RX_CTL1_RX_DMA_EN) &&
958
+ allwinner_sun8i_emac_can_receive(nc)) {
959
+ qemu_flush_queued_packets(nc);
960
+ }
961
+ break;
962
+ case REG_RX_DMA_DESC_LIST: /* Receive Descriptor List Address */
963
+ s->rx_desc_head = value;
964
+ s->rx_desc_curr = value;
965
+ break;
966
+ case REG_FRM_FLT: /* Receive Frame Filter */
967
+ s->frm_flt = value;
968
+ break;
969
+ case REG_RX_HASH_0: /* Receive Hash Table 0 */
970
+ case REG_RX_HASH_1: /* Receive Hash Table 1 */
971
+ break;
972
+ case REG_MII_CMD: /* Management Interface Command */
973
+ s->mii_cmd = value & ~MII_CMD_PHY_BUSY;
974
+ allwinner_sun8i_emac_mii_cmd(s);
975
+ break;
976
+ case REG_MII_DATA: /* Management Interface Data */
977
+ s->mii_data = value;
978
+ break;
979
+ case REG_ADDR_HIGH: /* MAC Address High */
980
+ s->conf.macaddr.a[4] = (value & 0xff);
981
+ s->conf.macaddr.a[5] = (value & 0xff00) >> 8;
982
+ break;
983
+ case REG_ADDR_LOW: /* MAC Address Low */
984
+ s->conf.macaddr.a[0] = (value & 0xff);
985
+ s->conf.macaddr.a[1] = (value & 0xff00) >> 8;
986
+ s->conf.macaddr.a[2] = (value & 0xff0000) >> 16;
987
+ s->conf.macaddr.a[3] = (value & 0xff000000) >> 24;
988
+ break;
989
+ case REG_TX_DMA_STA: /* Transmit DMA Status */
990
+ case REG_TX_CUR_DESC: /* Transmit Current Descriptor */
991
+ case REG_TX_CUR_BUF: /* Transmit Current Buffer */
992
+ case REG_RX_DMA_STA: /* Receive DMA Status */
993
+ case REG_RX_CUR_DESC: /* Receive Current Descriptor */
994
+ case REG_RX_CUR_BUF: /* Receive Current Buffer */
995
+ case REG_RGMII_STA: /* RGMII Status */
996
+ break;
997
+ default:
998
+ qemu_log_mask(LOG_UNIMP, "allwinner-h3-emac: write access to unknown "
999
+ "EMAC register 0x" TARGET_FMT_plx "\n",
1000
+ offset);
1001
+ }
1002
+}
1003
+
1004
+static void allwinner_sun8i_emac_set_link(NetClientState *nc)
1005
+{
1006
+ AwSun8iEmacState *s = qemu_get_nic_opaque(nc);
1007
+
1008
+ trace_allwinner_sun8i_emac_set_link(!nc->link_down);
1009
+ allwinner_sun8i_emac_mii_set_link(s, !nc->link_down);
1010
+}
1011
+
1012
+static const MemoryRegionOps allwinner_sun8i_emac_mem_ops = {
1013
+ .read = allwinner_sun8i_emac_read,
1014
+ .write = allwinner_sun8i_emac_write,
1015
+ .endianness = DEVICE_NATIVE_ENDIAN,
1016
+ .valid = {
1017
+ .min_access_size = 4,
1018
+ .max_access_size = 4,
1019
+ },
1020
+ .impl.min_access_size = 4,
1021
+};
1022
+
1023
+static NetClientInfo net_allwinner_sun8i_emac_info = {
1024
+ .type = NET_CLIENT_DRIVER_NIC,
1025
+ .size = sizeof(NICState),
1026
+ .can_receive = allwinner_sun8i_emac_can_receive,
1027
+ .receive = allwinner_sun8i_emac_receive,
1028
+ .link_status_changed = allwinner_sun8i_emac_set_link,
1029
+};
1030
+
1031
+static void allwinner_sun8i_emac_init(Object *obj)
1032
+{
1033
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1034
+ AwSun8iEmacState *s = AW_SUN8I_EMAC(obj);
1035
+
1036
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_sun8i_emac_mem_ops,
1037
+ s, TYPE_AW_SUN8I_EMAC, 64 * KiB);
1038
+ sysbus_init_mmio(sbd, &s->iomem);
1039
+ sysbus_init_irq(sbd, &s->irq);
1040
+}
1041
+
1042
+static void allwinner_sun8i_emac_realize(DeviceState *dev, Error **errp)
1043
+{
1044
+ AwSun8iEmacState *s = AW_SUN8I_EMAC(dev);
1045
+
1046
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
1047
+ s->nic = qemu_new_nic(&net_allwinner_sun8i_emac_info, &s->conf,
1048
+ object_get_typename(OBJECT(dev)), dev->id, s);
1049
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
1050
+}
1051
+
1052
+static Property allwinner_sun8i_emac_properties[] = {
1053
+ DEFINE_NIC_PROPERTIES(AwSun8iEmacState, conf),
1054
+ DEFINE_PROP_UINT8("phy-addr", AwSun8iEmacState, mii_phy_addr, 0),
1055
+ DEFINE_PROP_END_OF_LIST(),
1056
+};
1057
+
1058
+static int allwinner_sun8i_emac_post_load(void *opaque, int version_id)
1059
+{
1060
+ AwSun8iEmacState *s = opaque;
1061
+
1062
+ allwinner_sun8i_emac_set_link(qemu_get_queue(s->nic));
1063
+
1064
+ return 0;
1065
+}
1066
+
1067
+static const VMStateDescription vmstate_aw_emac = {
1068
+ .name = "allwinner-sun8i-emac",
1069
+ .version_id = 1,
1070
+ .minimum_version_id = 1,
1071
+ .post_load = allwinner_sun8i_emac_post_load,
1072
+ .fields = (VMStateField[]) {
1073
+ VMSTATE_UINT8(mii_phy_addr, AwSun8iEmacState),
1074
+ VMSTATE_UINT32(mii_cmd, AwSun8iEmacState),
1075
+ VMSTATE_UINT32(mii_data, AwSun8iEmacState),
1076
+ VMSTATE_UINT32(mii_cr, AwSun8iEmacState),
1077
+ VMSTATE_UINT32(mii_st, AwSun8iEmacState),
1078
+ VMSTATE_UINT32(mii_adv, AwSun8iEmacState),
1079
+ VMSTATE_UINT32(basic_ctl0, AwSun8iEmacState),
1080
+ VMSTATE_UINT32(basic_ctl1, AwSun8iEmacState),
1081
+ VMSTATE_UINT32(int_en, AwSun8iEmacState),
1082
+ VMSTATE_UINT32(int_sta, AwSun8iEmacState),
1083
+ VMSTATE_UINT32(frm_flt, AwSun8iEmacState),
1084
+ VMSTATE_UINT32(rx_ctl0, AwSun8iEmacState),
1085
+ VMSTATE_UINT32(rx_ctl1, AwSun8iEmacState),
1086
+ VMSTATE_UINT32(rx_desc_head, AwSun8iEmacState),
1087
+ VMSTATE_UINT32(rx_desc_curr, AwSun8iEmacState),
1088
+ VMSTATE_UINT32(tx_ctl0, AwSun8iEmacState),
1089
+ VMSTATE_UINT32(tx_ctl1, AwSun8iEmacState),
1090
+ VMSTATE_UINT32(tx_desc_head, AwSun8iEmacState),
1091
+ VMSTATE_UINT32(tx_desc_curr, AwSun8iEmacState),
1092
+ VMSTATE_UINT32(tx_flowctl, AwSun8iEmacState),
1093
+ VMSTATE_END_OF_LIST()
1094
+ }
1095
+};
1096
+
1097
+static void allwinner_sun8i_emac_class_init(ObjectClass *klass, void *data)
1098
+{
1099
+ DeviceClass *dc = DEVICE_CLASS(klass);
1100
+
1101
+ dc->realize = allwinner_sun8i_emac_realize;
1102
+ dc->reset = allwinner_sun8i_emac_reset;
1103
+ dc->vmsd = &vmstate_aw_emac;
1104
+ device_class_set_props(dc, allwinner_sun8i_emac_properties);
1105
+}
1106
+
1107
+static const TypeInfo allwinner_sun8i_emac_info = {
1108
+ .name = TYPE_AW_SUN8I_EMAC,
1109
+ .parent = TYPE_SYS_BUS_DEVICE,
1110
+ .instance_size = sizeof(AwSun8iEmacState),
1111
+ .instance_init = allwinner_sun8i_emac_init,
1112
+ .class_init = allwinner_sun8i_emac_class_init,
1113
+};
1114
+
1115
+static void allwinner_sun8i_emac_register_types(void)
1116
+{
1117
+ type_register_static(&allwinner_sun8i_emac_info);
1118
+}
1119
+
1120
+type_init(allwinner_sun8i_emac_register_types)
1121
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
1122
index XXXXXXX..XXXXXXX 100644
1123
--- a/hw/arm/Kconfig
1124
+++ b/hw/arm/Kconfig
1125
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10
1126
config ALLWINNER_H3
1127
bool
1128
select ALLWINNER_A10_PIT
1129
+ select ALLWINNER_SUN8I_EMAC
1130
select SERIAL
1131
select ARM_TIMER
1132
select ARM_GIC
1133
diff --git a/hw/net/Kconfig b/hw/net/Kconfig
1134
index XXXXXXX..XXXXXXX 100644
1135
--- a/hw/net/Kconfig
1136
+++ b/hw/net/Kconfig
1137
@@ -XXX,XX +XXX,XX @@ config MIPSNET
1138
config ALLWINNER_EMAC
1139
bool
1140
1141
+config ALLWINNER_SUN8I_EMAC
1142
+ bool
1143
+
1144
config IMX_FEC
1145
bool
1146
1147
diff --git a/hw/net/trace-events b/hw/net/trace-events
1148
index XXXXXXX..XXXXXXX 100644
1149
--- a/hw/net/trace-events
1150
+++ b/hw/net/trace-events
1151
@@ -XXX,XX +XXX,XX @@
1152
# See docs/devel/tracing.txt for syntax documentation.
1153
1154
+# allwinner-sun8i-emac.c
1155
+allwinner_sun8i_emac_mii_write_reg(uint32_t reg, uint32_t value) "MII write: reg=0x%" PRIx32 " value=0x%" PRIx32
1156
+allwinner_sun8i_emac_mii_read_reg(uint32_t reg, uint32_t value) "MII read: reg=0x%" PRIx32 " value=0x%" PRIx32
1157
+allwinner_sun8i_emac_receive(uint32_t desc, uint32_t paddr, uint32_t bytes) "RX packet: desc=0x%" PRIx32 " paddr=0x%" PRIx32 " bytes=%" PRIu32
1158
+allwinner_sun8i_emac_transmit(uint32_t desc, uint32_t paddr, uint32_t bytes) "TX packet: desc=0x%" PRIx32 " paddr=0x%" PRIx32 " bytes=%" PRIu32
1159
+allwinner_sun8i_emac_reset(void) "HW reset"
1160
+allwinner_sun8i_emac_set_link(bool active) "Set link: active=%u"
1161
+allwinner_sun8i_emac_read(uint64_t offset, uint64_t val) "MMIO read: offset=0x%" PRIx64 " value=0x%" PRIx64
1162
+allwinner_sun8i_emac_write(uint64_t offset, uint64_t val) "MMIO write: offset=0x%" PRIx64 " value=0x%" PRIx64
1163
+
1164
# etraxfs_eth.c
1165
mdio_phy_read(int regnum, uint16_t value) "read phy_reg:%d value:0x%04x"
1166
mdio_phy_write(int regnum, uint16_t value) "write phy_reg:%d value:0x%04x"
94
--
1167
--
95
2.20.1
1168
2.20.1
96
1169
97
1170
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
At the same time, add writefn to TTBR0_EL2 and TCR_EL2.
3
A real Allwinner H3 SoC contains a Boot ROM which is the
4
A later patch will update any ASID therein.
4
first code that runs right after the SoC is powered on.
5
The Boot ROM is responsible for loading user code (e.g. a bootloader)
6
from any of the supported external devices and writing the downloaded
7
code to internal SRAM. After loading the SoC begins executing the code
8
written to SRAM.
5
9
6
Tested-by: Alex Bennée <alex.bennee@linaro.org>
10
This commits adds emulation of the Boot ROM firmware setup functionality
11
by loading user code from SD card in the A1 SRAM. While the A1 SRAM is
12
64KiB, we limit the size to 32KiB because the real H3 Boot ROM also rejects
13
sizes larger than 32KiB. For reference, this behaviour is documented
14
by the Linux Sunxi project wiki at:
15
16
https://linux-sunxi.org/BROM#U-Boot_SPL_limitations
17
18
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
19
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
20
Message-id: 20200311221854.30370-11-nieklinnenbank@gmail.com
9
Message-id: 20200206105448.4726-5-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
22
---
12
target/arm/helper.c | 13 ++++++++++++-
23
include/hw/arm/allwinner-h3.h | 21 +++++++++++++++++++++
13
1 file changed, 12 insertions(+), 1 deletion(-)
24
hw/arm/allwinner-h3.c | 17 +++++++++++++++++
25
hw/arm/orangepi.c | 5 +++++
26
3 files changed, 43 insertions(+)
14
27
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
28
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
16
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
30
--- a/include/hw/arm/allwinner-h3.h
18
+++ b/target/arm/helper.c
31
+++ b/include/hw/arm/allwinner-h3.h
19
@@ -XXX,XX +XXX,XX @@ static void vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
32
@@ -XXX,XX +XXX,XX @@
20
raw_write(env, ri, value);
33
#include "hw/sd/allwinner-sdhost.h"
21
}
34
#include "hw/net/allwinner-sun8i-emac.h"
22
35
#include "target/arm/cpu.h"
23
+static void vmsa_tcr_ttbr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
36
+#include "sysemu/block-backend.h"
24
+ uint64_t value)
37
38
/**
39
* Allwinner H3 device list
40
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
41
MemoryRegion sram_c;
42
} AwH3State;
43
44
+/**
45
+ * Emulate Boot ROM firmware setup functionality.
46
+ *
47
+ * A real Allwinner H3 SoC contains a Boot ROM
48
+ * which is the first code that runs right after
49
+ * the SoC is powered on. The Boot ROM is responsible
50
+ * for loading user code (e.g. a bootloader) from any
51
+ * of the supported external devices and writing the
52
+ * downloaded code to internal SRAM. After loading the SoC
53
+ * begins executing the code written to SRAM.
54
+ *
55
+ * This function emulates the Boot ROM by copying 32 KiB
56
+ * of data from the given block device and writes it to
57
+ * the start of the first internal SRAM memory.
58
+ *
59
+ * @s: Allwinner H3 state object pointer
60
+ * @blk: Block backend device object pointer
61
+ */
62
+void allwinner_h3_bootrom_setup(AwH3State *s, BlockBackend *blk);
63
+
64
#endif /* HW_ARM_ALLWINNER_H3_H */
65
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/hw/arm/allwinner-h3.c
68
+++ b/hw/arm/allwinner-h3.c
69
@@ -XXX,XX +XXX,XX @@
70
#include "hw/char/serial.h"
71
#include "hw/misc/unimp.h"
72
#include "hw/usb/hcd-ehci.h"
73
+#include "hw/loader.h"
74
#include "sysemu/sysemu.h"
75
#include "hw/arm/allwinner-h3.h"
76
77
@@ -XXX,XX +XXX,XX @@ enum {
78
AW_H3_GIC_NUM_SPI = 128
79
};
80
81
+void allwinner_h3_bootrom_setup(AwH3State *s, BlockBackend *blk)
25
+{
82
+{
26
+ /* TODO: There are ASID fields in here with HCR_EL2.E2H */
83
+ const int64_t rom_size = 32 * KiB;
27
+ raw_write(env, ri, value);
84
+ g_autofree uint8_t *buffer = g_new0(uint8_t, rom_size);
85
+
86
+ if (blk_pread(blk, 8 * KiB, buffer, rom_size) < 0) {
87
+ error_setg(&error_fatal, "%s: failed to read BlockBackend data",
88
+ __func__);
89
+ return;
90
+ }
91
+
92
+ rom_add_blob("allwinner-h3.bootrom", buffer, rom_size,
93
+ rom_size, s->memmap[AW_H3_SRAM_A1],
94
+ NULL, NULL, NULL, NULL, false);
28
+}
95
+}
29
+
96
+
30
static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
97
static void allwinner_h3_init(Object *obj)
31
uint64_t value)
32
{
98
{
33
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
99
AwH3State *s = AW_H3(obj);
34
.fieldoffset = offsetof(CPUARMState, cp15.tpidr_el[2]) },
100
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
35
{ .name = "TTBR0_EL2", .state = ARM_CP_STATE_AA64,
101
index XXXXXXX..XXXXXXX 100644
36
.opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 0,
102
--- a/hw/arm/orangepi.c
37
- .access = PL2_RW, .resetvalue = 0,
103
+++ b/hw/arm/orangepi.c
38
+ .access = PL2_RW, .resetvalue = 0, .writefn = vmsa_tcr_ttbr_el2_write,
104
@@ -XXX,XX +XXX,XX @@ static void orangepi_init(MachineState *machine)
39
.fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el[2]) },
105
memory_region_add_subregion(get_system_memory(), h3->memmap[AW_H3_SDRAM],
40
{ .name = "HTTBR", .cp = 15, .opc1 = 4, .crm = 2,
106
machine->ram);
41
.access = PL2_RW, .type = ARM_CP_64BIT | ARM_CP_ALIAS,
107
42
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
108
+ /* Load target kernel or start using BootROM */
43
.opc0 = 3, .opc1 = 4, .crn = 13, .crm = 0, .opc2 = 1,
109
+ if (!machine->kernel_filename && blk_is_available(blk)) {
44
.access = PL2_RW,
110
+ /* Use Boot ROM to copy data from SD card to SRAM */
45
.fieldoffset = offsetof(CPUARMState, cp15.contextidr_el[2]) },
111
+ allwinner_h3_bootrom_setup(h3, blk);
46
+ { .name = "TTBR1_EL2", .state = ARM_CP_STATE_AA64,
112
+ }
47
+ .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 1,
113
orangepi_binfo.loader_start = h3->memmap[AW_H3_SDRAM];
48
+ .access = PL2_RW, .writefn = vmsa_tcr_ttbr_el2_write,
114
orangepi_binfo.ram_size = machine->ram_size;
49
+ .fieldoffset = offsetof(CPUARMState, cp15.ttbr1_el[2]) },
115
arm_load_kernel(ARM_CPU(first_cpu), machine, &orangepi_binfo);
50
REGINFO_SENTINEL
51
};
52
53
--
116
--
54
2.20.1
117
2.20.1
55
118
56
119
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
The fall through organization of this function meant that we
3
In the Allwinner H3 SoC the SDRAM controller is responsible
4
would raise an interrupt, then might overwrite that with another.
4
for interfacing with the external Synchronous Dynamic Random
5
Since interrupt prioritization is IMPLEMENTATION DEFINED, we
5
Access Memory (SDRAM). Types of memory that the SDRAM controller
6
can recognize these in any order we choose.
6
supports are DDR2/DDR3 and capacities of up to 2GiB. This commit
7
adds emulation support of the Allwinner H3 SDRAM controller.
7
8
8
Unify the code to raise the interrupt in a block at the end.
9
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
9
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
Tested-by: Alex Bennée <alex.bennee@linaro.org>
11
Message-id: 20200311221854.30370-12-nieklinnenbank@gmail.com
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20200206105448.4726-42-richard.henderson@linaro.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
13
---
16
target/arm/cpu.c | 30 ++++++++++++------------------
14
hw/misc/Makefile.objs | 1 +
17
1 file changed, 12 insertions(+), 18 deletions(-)
15
include/hw/arm/allwinner-h3.h | 5 +
16
include/hw/misc/allwinner-h3-dramc.h | 106 ++++++++
17
hw/arm/allwinner-h3.c | 19 +-
18
hw/arm/orangepi.c | 6 +
19
hw/misc/allwinner-h3-dramc.c | 358 +++++++++++++++++++++++++++
20
hw/misc/trace-events | 10 +
21
7 files changed, 502 insertions(+), 3 deletions(-)
22
create mode 100644 include/hw/misc/allwinner-h3-dramc.h
23
create mode 100644 hw/misc/allwinner-h3-dramc.c
18
24
19
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
25
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
20
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.c
27
--- a/hw/misc/Makefile.objs
22
+++ b/target/arm/cpu.c
28
+++ b/hw/misc/Makefile.objs
23
@@ -XXX,XX +XXX,XX @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
29
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_IVSHMEM_DEVICE) += ivshmem.o
24
uint64_t hcr_el2 = arm_hcr_el2_eff(env);
30
25
uint32_t target_el;
31
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-ccu.o
26
uint32_t excp_idx;
32
obj-$(CONFIG_ALLWINNER_H3) += allwinner-cpucfg.o
27
- bool ret = false;
33
+common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-dramc.o
28
+
34
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-sysctrl.o
29
+ /* The prioritization of interrupts is IMPLEMENTATION DEFINED. */
35
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-sid.o
30
36
common-obj-$(CONFIG_REALVIEW) += arm_sysctl.o
31
if (interrupt_request & CPU_INTERRUPT_FIQ) {
37
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
32
excp_idx = EXCP_FIQ;
38
index XXXXXXX..XXXXXXX 100644
33
target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure);
39
--- a/include/hw/arm/allwinner-h3.h
34
if (arm_excp_unmasked(cs, excp_idx, target_el,
40
+++ b/include/hw/arm/allwinner-h3.h
35
cur_el, secure, hcr_el2)) {
41
@@ -XXX,XX +XXX,XX @@
36
- cs->exception_index = excp_idx;
42
#include "hw/intc/arm_gic.h"
37
- env->exception.target_el = target_el;
43
#include "hw/misc/allwinner-h3-ccu.h"
38
- cc->do_interrupt(cs);
44
#include "hw/misc/allwinner-cpucfg.h"
39
- ret = true;
45
+#include "hw/misc/allwinner-h3-dramc.h"
40
+ goto found;
46
#include "hw/misc/allwinner-h3-sysctrl.h"
41
}
47
#include "hw/misc/allwinner-sid.h"
42
}
48
#include "hw/sd/allwinner-sdhost.h"
43
if (interrupt_request & CPU_INTERRUPT_HARD) {
49
@@ -XXX,XX +XXX,XX @@ enum {
44
@@ -XXX,XX +XXX,XX @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
50
AW_H3_UART2,
45
target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure);
51
AW_H3_UART3,
46
if (arm_excp_unmasked(cs, excp_idx, target_el,
52
AW_H3_EMAC,
47
cur_el, secure, hcr_el2)) {
53
+ AW_H3_DRAMCOM,
48
- cs->exception_index = excp_idx;
54
+ AW_H3_DRAMCTL,
49
- env->exception.target_el = target_el;
55
+ AW_H3_DRAMPHY,
50
- cc->do_interrupt(cs);
56
AW_H3_GIC_DIST,
51
- ret = true;
57
AW_H3_GIC_CPU,
52
+ goto found;
58
AW_H3_GIC_HYP,
53
}
59
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
54
}
60
AwA10PITState timer;
55
if (interrupt_request & CPU_INTERRUPT_VIRQ) {
61
AwH3ClockCtlState ccu;
56
@@ -XXX,XX +XXX,XX @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
62
AwCpuCfgState cpucfg;
57
target_el = 1;
63
+ AwH3DramCtlState dramc;
58
if (arm_excp_unmasked(cs, excp_idx, target_el,
64
AwH3SysCtrlState sysctrl;
59
cur_el, secure, hcr_el2)) {
65
AwSidState sid;
60
- cs->exception_index = excp_idx;
66
AwSdHostState mmc0;
61
- env->exception.target_el = target_el;
67
diff --git a/include/hw/misc/allwinner-h3-dramc.h b/include/hw/misc/allwinner-h3-dramc.h
62
- cc->do_interrupt(cs);
68
new file mode 100644
63
- ret = true;
69
index XXXXXXX..XXXXXXX
64
+ goto found;
70
--- /dev/null
65
}
71
+++ b/include/hw/misc/allwinner-h3-dramc.h
66
}
72
@@ -XXX,XX +XXX,XX @@
67
if (interrupt_request & CPU_INTERRUPT_VFIQ) {
73
+/*
68
@@ -XXX,XX +XXX,XX @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
74
+ * Allwinner H3 SDRAM Controller emulation
69
target_el = 1;
75
+ *
70
if (arm_excp_unmasked(cs, excp_idx, target_el,
76
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
71
cur_el, secure, hcr_el2)) {
77
+ *
72
- cs->exception_index = excp_idx;
78
+ * This program is free software: you can redistribute it and/or modify
73
- env->exception.target_el = target_el;
79
+ * it under the terms of the GNU General Public License as published by
74
- cc->do_interrupt(cs);
80
+ * the Free Software Foundation, either version 2 of the License, or
75
- ret = true;
81
+ * (at your option) any later version.
76
+ goto found;
82
+ *
77
}
83
+ * This program is distributed in the hope that it will be useful,
78
}
84
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
79
+ return false;
85
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
80
86
+ * GNU General Public License for more details.
81
- return ret;
87
+ *
82
+ found:
88
+ * You should have received a copy of the GNU General Public License
83
+ cs->exception_index = excp_idx;
89
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
84
+ env->exception.target_el = target_el;
90
+ */
85
+ cc->do_interrupt(cs);
91
+
86
+ return true;
92
+#ifndef HW_MISC_ALLWINNER_H3_DRAMC_H
93
+#define HW_MISC_ALLWINNER_H3_DRAMC_H
94
+
95
+#include "qom/object.h"
96
+#include "hw/sysbus.h"
97
+#include "exec/hwaddr.h"
98
+
99
+/**
100
+ * Constants
101
+ * @{
102
+ */
103
+
104
+/** Highest register address used by DRAMCOM module */
105
+#define AW_H3_DRAMCOM_REGS_MAXADDR (0x804)
106
+
107
+/** Total number of known DRAMCOM registers */
108
+#define AW_H3_DRAMCOM_REGS_NUM (AW_H3_DRAMCOM_REGS_MAXADDR / \
109
+ sizeof(uint32_t))
110
+
111
+/** Highest register address used by DRAMCTL module */
112
+#define AW_H3_DRAMCTL_REGS_MAXADDR (0x88c)
113
+
114
+/** Total number of known DRAMCTL registers */
115
+#define AW_H3_DRAMCTL_REGS_NUM (AW_H3_DRAMCTL_REGS_MAXADDR / \
116
+ sizeof(uint32_t))
117
+
118
+/** Highest register address used by DRAMPHY module */
119
+#define AW_H3_DRAMPHY_REGS_MAXADDR (0x4)
120
+
121
+/** Total number of known DRAMPHY registers */
122
+#define AW_H3_DRAMPHY_REGS_NUM (AW_H3_DRAMPHY_REGS_MAXADDR / \
123
+ sizeof(uint32_t))
124
+
125
+/** @} */
126
+
127
+/**
128
+ * Object model
129
+ * @{
130
+ */
131
+
132
+#define TYPE_AW_H3_DRAMC "allwinner-h3-dramc"
133
+#define AW_H3_DRAMC(obj) \
134
+ OBJECT_CHECK(AwH3DramCtlState, (obj), TYPE_AW_H3_DRAMC)
135
+
136
+/** @} */
137
+
138
+/**
139
+ * Allwinner H3 SDRAM Controller object instance state.
140
+ */
141
+typedef struct AwH3DramCtlState {
142
+ /*< private >*/
143
+ SysBusDevice parent_obj;
144
+ /*< public >*/
145
+
146
+ /** Physical base address for start of RAM */
147
+ hwaddr ram_addr;
148
+
149
+ /** Total RAM size in megabytes */
150
+ uint32_t ram_size;
151
+
152
+ /**
153
+ * @name Memory Regions
154
+ * @{
155
+ */
156
+
157
+ MemoryRegion row_mirror; /**< Simulates rows for RAM size detection */
158
+ MemoryRegion row_mirror_alias; /**< Alias of the row which is mirrored */
159
+ MemoryRegion dramcom_iomem; /**< DRAMCOM module I/O registers */
160
+ MemoryRegion dramctl_iomem; /**< DRAMCTL module I/O registers */
161
+ MemoryRegion dramphy_iomem; /**< DRAMPHY module I/O registers */
162
+
163
+ /** @} */
164
+
165
+ /**
166
+ * @name Hardware Registers
167
+ * @{
168
+ */
169
+
170
+ uint32_t dramcom[AW_H3_DRAMCOM_REGS_NUM]; /**< Array of DRAMCOM registers */
171
+ uint32_t dramctl[AW_H3_DRAMCTL_REGS_NUM]; /**< Array of DRAMCTL registers */
172
+ uint32_t dramphy[AW_H3_DRAMPHY_REGS_NUM] ;/**< Array of DRAMPHY registers */
173
+
174
+ /** @} */
175
+
176
+} AwH3DramCtlState;
177
+
178
+#endif /* HW_MISC_ALLWINNER_H3_DRAMC_H */
179
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
180
index XXXXXXX..XXXXXXX 100644
181
--- a/hw/arm/allwinner-h3.c
182
+++ b/hw/arm/allwinner-h3.c
183
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
184
[AW_H3_UART2] = 0x01c28800,
185
[AW_H3_UART3] = 0x01c28c00,
186
[AW_H3_EMAC] = 0x01c30000,
187
+ [AW_H3_DRAMCOM] = 0x01c62000,
188
+ [AW_H3_DRAMCTL] = 0x01c63000,
189
+ [AW_H3_DRAMPHY] = 0x01c65000,
190
[AW_H3_GIC_DIST] = 0x01c81000,
191
[AW_H3_GIC_CPU] = 0x01c82000,
192
[AW_H3_GIC_HYP] = 0x01c84000,
193
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
194
{ "scr", 0x01c2c400, 1 * KiB },
195
{ "gpu", 0x01c40000, 64 * KiB },
196
{ "hstmr", 0x01c60000, 4 * KiB },
197
- { "dramcom", 0x01c62000, 4 * KiB },
198
- { "dramctl0", 0x01c63000, 4 * KiB },
199
- { "dramphy0", 0x01c65000, 4 * KiB },
200
{ "spi0", 0x01c68000, 4 * KiB },
201
{ "spi1", 0x01c69000, 4 * KiB },
202
{ "csi", 0x01cb0000, 320 * KiB },
203
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
204
205
sysbus_init_child_obj(obj, "emac", &s->emac, sizeof(s->emac),
206
TYPE_AW_SUN8I_EMAC);
207
+
208
+ sysbus_init_child_obj(obj, "dramc", &s->dramc, sizeof(s->dramc),
209
+ TYPE_AW_H3_DRAMC);
210
+ object_property_add_alias(obj, "ram-addr", OBJECT(&s->dramc),
211
+ "ram-addr", &error_abort);
212
+ object_property_add_alias(obj, "ram-size", OBJECT(&s->dramc),
213
+ "ram-size", &error_abort);
87
}
214
}
88
215
89
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
216
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
217
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
218
qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART3),
219
115200, serial_hd(3), DEVICE_NATIVE_ENDIAN);
220
221
+ /* DRAMC */
222
+ qdev_init_nofail(DEVICE(&s->dramc));
223
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 0, s->memmap[AW_H3_DRAMCOM]);
224
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 1, s->memmap[AW_H3_DRAMCTL]);
225
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 2, s->memmap[AW_H3_DRAMPHY]);
226
+
227
/* Unimplemented devices */
228
for (i = 0; i < ARRAY_SIZE(unimplemented); i++) {
229
create_unimplemented_device(unimplemented[i].device_name,
230
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
231
index XXXXXXX..XXXXXXX 100644
232
--- a/hw/arm/orangepi.c
233
+++ b/hw/arm/orangepi.c
234
@@ -XXX,XX +XXX,XX @@ static void orangepi_init(MachineState *machine)
235
/* Setup EMAC properties */
236
object_property_set_int(OBJECT(&h3->emac), 1, "phy-addr", &error_abort);
237
238
+ /* DRAMC */
239
+ object_property_set_uint(OBJECT(h3), h3->memmap[AW_H3_SDRAM],
240
+ "ram-addr", &error_abort);
241
+ object_property_set_int(OBJECT(h3), machine->ram_size / MiB, "ram-size",
242
+ &error_abort);
243
+
244
/* Mark H3 object realized */
245
object_property_set_bool(OBJECT(h3), true, "realized", &error_abort);
246
247
diff --git a/hw/misc/allwinner-h3-dramc.c b/hw/misc/allwinner-h3-dramc.c
248
new file mode 100644
249
index XXXXXXX..XXXXXXX
250
--- /dev/null
251
+++ b/hw/misc/allwinner-h3-dramc.c
252
@@ -XXX,XX +XXX,XX @@
253
+/*
254
+ * Allwinner H3 SDRAM Controller emulation
255
+ *
256
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
257
+ *
258
+ * This program is free software: you can redistribute it and/or modify
259
+ * it under the terms of the GNU General Public License as published by
260
+ * the Free Software Foundation, either version 2 of the License, or
261
+ * (at your option) any later version.
262
+ *
263
+ * This program is distributed in the hope that it will be useful,
264
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
265
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
266
+ * GNU General Public License for more details.
267
+ *
268
+ * You should have received a copy of the GNU General Public License
269
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
270
+ */
271
+
272
+#include "qemu/osdep.h"
273
+#include "qemu/units.h"
274
+#include "qemu/error-report.h"
275
+#include "hw/sysbus.h"
276
+#include "migration/vmstate.h"
277
+#include "qemu/log.h"
278
+#include "qemu/module.h"
279
+#include "exec/address-spaces.h"
280
+#include "hw/qdev-properties.h"
281
+#include "qapi/error.h"
282
+#include "hw/misc/allwinner-h3-dramc.h"
283
+#include "trace.h"
284
+
285
+#define REG_INDEX(offset) (offset / sizeof(uint32_t))
286
+
287
+/* DRAMCOM register offsets */
288
+enum {
289
+ REG_DRAMCOM_CR = 0x0000, /* Control Register */
290
+};
291
+
292
+/* DRAMCTL register offsets */
293
+enum {
294
+ REG_DRAMCTL_PIR = 0x0000, /* PHY Initialization Register */
295
+ REG_DRAMCTL_PGSR = 0x0010, /* PHY General Status Register */
296
+ REG_DRAMCTL_STATR = 0x0018, /* Status Register */
297
+};
298
+
299
+/* DRAMCTL register flags */
300
+enum {
301
+ REG_DRAMCTL_PGSR_INITDONE = (1 << 0),
302
+};
303
+
304
+enum {
305
+ REG_DRAMCTL_STATR_ACTIVE = (1 << 0),
306
+};
307
+
308
+static void allwinner_h3_dramc_map_rows(AwH3DramCtlState *s, uint8_t row_bits,
309
+ uint8_t bank_bits, uint16_t page_size)
310
+{
311
+ /*
312
+ * This function simulates row addressing behavior when bootloader
313
+ * software attempts to detect the amount of available SDRAM. In U-Boot
314
+ * the controller is configured with the widest row addressing available.
315
+ * Then a pattern is written to RAM at an offset on the row boundary size.
316
+ * If the value read back equals the value read back from the
317
+ * start of RAM, the bootloader knows the amount of row bits.
318
+ *
319
+ * This function inserts a mirrored memory region when the configured row
320
+ * bits are not matching the actual emulated memory, to simulate the
321
+ * same behavior on hardware as expected by the bootloader.
322
+ */
323
+ uint8_t row_bits_actual = 0;
324
+
325
+ /* Calculate the actual row bits using the ram_size property */
326
+ for (uint8_t i = 8; i < 12; i++) {
327
+ if (1 << i == s->ram_size) {
328
+ row_bits_actual = i + 3;
329
+ break;
330
+ }
331
+ }
332
+
333
+ if (s->ram_size == (1 << (row_bits - 3))) {
334
+ /* When row bits is the expected value, remove the mirror */
335
+ memory_region_set_enabled(&s->row_mirror_alias, false);
336
+ trace_allwinner_h3_dramc_rowmirror_disable();
337
+
338
+ } else if (row_bits_actual) {
339
+ /* Row bits not matching ram_size, install the rows mirror */
340
+ hwaddr row_mirror = s->ram_addr + ((1 << (row_bits_actual +
341
+ bank_bits)) * page_size);
342
+
343
+ memory_region_set_enabled(&s->row_mirror_alias, true);
344
+ memory_region_set_address(&s->row_mirror_alias, row_mirror);
345
+
346
+ trace_allwinner_h3_dramc_rowmirror_enable(row_mirror);
347
+ }
348
+}
349
+
350
+static uint64_t allwinner_h3_dramcom_read(void *opaque, hwaddr offset,
351
+ unsigned size)
352
+{
353
+ const AwH3DramCtlState *s = AW_H3_DRAMC(opaque);
354
+ const uint32_t idx = REG_INDEX(offset);
355
+
356
+ if (idx >= AW_H3_DRAMCOM_REGS_NUM) {
357
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
358
+ __func__, (uint32_t)offset);
359
+ return 0;
360
+ }
361
+
362
+ trace_allwinner_h3_dramcom_read(offset, s->dramcom[idx], size);
363
+
364
+ return s->dramcom[idx];
365
+}
366
+
367
+static void allwinner_h3_dramcom_write(void *opaque, hwaddr offset,
368
+ uint64_t val, unsigned size)
369
+{
370
+ AwH3DramCtlState *s = AW_H3_DRAMC(opaque);
371
+ const uint32_t idx = REG_INDEX(offset);
372
+
373
+ trace_allwinner_h3_dramcom_write(offset, val, size);
374
+
375
+ if (idx >= AW_H3_DRAMCOM_REGS_NUM) {
376
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
377
+ __func__, (uint32_t)offset);
378
+ return;
379
+ }
380
+
381
+ switch (offset) {
382
+ case REG_DRAMCOM_CR: /* Control Register */
383
+ allwinner_h3_dramc_map_rows(s, ((val >> 4) & 0xf) + 1,
384
+ ((val >> 2) & 0x1) + 2,
385
+ 1 << (((val >> 8) & 0xf) + 3));
386
+ break;
387
+ default:
388
+ break;
389
+ };
390
+
391
+ s->dramcom[idx] = (uint32_t) val;
392
+}
393
+
394
+static uint64_t allwinner_h3_dramctl_read(void *opaque, hwaddr offset,
395
+ unsigned size)
396
+{
397
+ const AwH3DramCtlState *s = AW_H3_DRAMC(opaque);
398
+ const uint32_t idx = REG_INDEX(offset);
399
+
400
+ if (idx >= AW_H3_DRAMCTL_REGS_NUM) {
401
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
402
+ __func__, (uint32_t)offset);
403
+ return 0;
404
+ }
405
+
406
+ trace_allwinner_h3_dramctl_read(offset, s->dramctl[idx], size);
407
+
408
+ return s->dramctl[idx];
409
+}
410
+
411
+static void allwinner_h3_dramctl_write(void *opaque, hwaddr offset,
412
+ uint64_t val, unsigned size)
413
+{
414
+ AwH3DramCtlState *s = AW_H3_DRAMC(opaque);
415
+ const uint32_t idx = REG_INDEX(offset);
416
+
417
+ trace_allwinner_h3_dramctl_write(offset, val, size);
418
+
419
+ if (idx >= AW_H3_DRAMCTL_REGS_NUM) {
420
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
421
+ __func__, (uint32_t)offset);
422
+ return;
423
+ }
424
+
425
+ switch (offset) {
426
+ case REG_DRAMCTL_PIR: /* PHY Initialization Register */
427
+ s->dramctl[REG_INDEX(REG_DRAMCTL_PGSR)] |= REG_DRAMCTL_PGSR_INITDONE;
428
+ s->dramctl[REG_INDEX(REG_DRAMCTL_STATR)] |= REG_DRAMCTL_STATR_ACTIVE;
429
+ break;
430
+ default:
431
+ break;
432
+ }
433
+
434
+ s->dramctl[idx] = (uint32_t) val;
435
+}
436
+
437
+static uint64_t allwinner_h3_dramphy_read(void *opaque, hwaddr offset,
438
+ unsigned size)
439
+{
440
+ const AwH3DramCtlState *s = AW_H3_DRAMC(opaque);
441
+ const uint32_t idx = REG_INDEX(offset);
442
+
443
+ if (idx >= AW_H3_DRAMPHY_REGS_NUM) {
444
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
445
+ __func__, (uint32_t)offset);
446
+ return 0;
447
+ }
448
+
449
+ trace_allwinner_h3_dramphy_read(offset, s->dramphy[idx], size);
450
+
451
+ return s->dramphy[idx];
452
+}
453
+
454
+static void allwinner_h3_dramphy_write(void *opaque, hwaddr offset,
455
+ uint64_t val, unsigned size)
456
+{
457
+ AwH3DramCtlState *s = AW_H3_DRAMC(opaque);
458
+ const uint32_t idx = REG_INDEX(offset);
459
+
460
+ trace_allwinner_h3_dramphy_write(offset, val, size);
461
+
462
+ if (idx >= AW_H3_DRAMPHY_REGS_NUM) {
463
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
464
+ __func__, (uint32_t)offset);
465
+ return;
466
+ }
467
+
468
+ s->dramphy[idx] = (uint32_t) val;
469
+}
470
+
471
+static const MemoryRegionOps allwinner_h3_dramcom_ops = {
472
+ .read = allwinner_h3_dramcom_read,
473
+ .write = allwinner_h3_dramcom_write,
474
+ .endianness = DEVICE_NATIVE_ENDIAN,
475
+ .valid = {
476
+ .min_access_size = 4,
477
+ .max_access_size = 4,
478
+ },
479
+ .impl.min_access_size = 4,
480
+};
481
+
482
+static const MemoryRegionOps allwinner_h3_dramctl_ops = {
483
+ .read = allwinner_h3_dramctl_read,
484
+ .write = allwinner_h3_dramctl_write,
485
+ .endianness = DEVICE_NATIVE_ENDIAN,
486
+ .valid = {
487
+ .min_access_size = 4,
488
+ .max_access_size = 4,
489
+ },
490
+ .impl.min_access_size = 4,
491
+};
492
+
493
+static const MemoryRegionOps allwinner_h3_dramphy_ops = {
494
+ .read = allwinner_h3_dramphy_read,
495
+ .write = allwinner_h3_dramphy_write,
496
+ .endianness = DEVICE_NATIVE_ENDIAN,
497
+ .valid = {
498
+ .min_access_size = 4,
499
+ .max_access_size = 4,
500
+ },
501
+ .impl.min_access_size = 4,
502
+};
503
+
504
+static void allwinner_h3_dramc_reset(DeviceState *dev)
505
+{
506
+ AwH3DramCtlState *s = AW_H3_DRAMC(dev);
507
+
508
+ /* Set default values for registers */
509
+ memset(&s->dramcom, 0, sizeof(s->dramcom));
510
+ memset(&s->dramctl, 0, sizeof(s->dramctl));
511
+ memset(&s->dramphy, 0, sizeof(s->dramphy));
512
+}
513
+
514
+static void allwinner_h3_dramc_realize(DeviceState *dev, Error **errp)
515
+{
516
+ AwH3DramCtlState *s = AW_H3_DRAMC(dev);
517
+
518
+ /* Only power of 2 RAM sizes from 256MiB up to 2048MiB are supported */
519
+ for (uint8_t i = 8; i < 13; i++) {
520
+ if (1 << i == s->ram_size) {
521
+ break;
522
+ } else if (i == 12) {
523
+ error_report("%s: ram-size %u MiB is not supported",
524
+ __func__, s->ram_size);
525
+ exit(1);
526
+ }
527
+ }
528
+
529
+ /* Setup row mirror mappings */
530
+ memory_region_init_ram(&s->row_mirror, OBJECT(s),
531
+ "allwinner-h3-dramc.row-mirror",
532
+ 4 * KiB, &error_abort);
533
+ memory_region_add_subregion_overlap(get_system_memory(), s->ram_addr,
534
+ &s->row_mirror, 10);
535
+
536
+ memory_region_init_alias(&s->row_mirror_alias, OBJECT(s),
537
+ "allwinner-h3-dramc.row-mirror-alias",
538
+ &s->row_mirror, 0, 4 * KiB);
539
+ memory_region_add_subregion_overlap(get_system_memory(),
540
+ s->ram_addr + 1 * MiB,
541
+ &s->row_mirror_alias, 10);
542
+ memory_region_set_enabled(&s->row_mirror_alias, false);
543
+}
544
+
545
+static void allwinner_h3_dramc_init(Object *obj)
546
+{
547
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
548
+ AwH3DramCtlState *s = AW_H3_DRAMC(obj);
549
+
550
+ /* DRAMCOM registers */
551
+ memory_region_init_io(&s->dramcom_iomem, OBJECT(s),
552
+ &allwinner_h3_dramcom_ops, s,
553
+ TYPE_AW_H3_DRAMC, 4 * KiB);
554
+ sysbus_init_mmio(sbd, &s->dramcom_iomem);
555
+
556
+ /* DRAMCTL registers */
557
+ memory_region_init_io(&s->dramctl_iomem, OBJECT(s),
558
+ &allwinner_h3_dramctl_ops, s,
559
+ TYPE_AW_H3_DRAMC, 4 * KiB);
560
+ sysbus_init_mmio(sbd, &s->dramctl_iomem);
561
+
562
+ /* DRAMPHY registers */
563
+ memory_region_init_io(&s->dramphy_iomem, OBJECT(s),
564
+ &allwinner_h3_dramphy_ops, s,
565
+ TYPE_AW_H3_DRAMC, 4 * KiB);
566
+ sysbus_init_mmio(sbd, &s->dramphy_iomem);
567
+}
568
+
569
+static Property allwinner_h3_dramc_properties[] = {
570
+ DEFINE_PROP_UINT64("ram-addr", AwH3DramCtlState, ram_addr, 0x0),
571
+ DEFINE_PROP_UINT32("ram-size", AwH3DramCtlState, ram_size, 256 * MiB),
572
+ DEFINE_PROP_END_OF_LIST()
573
+};
574
+
575
+static const VMStateDescription allwinner_h3_dramc_vmstate = {
576
+ .name = "allwinner-h3-dramc",
577
+ .version_id = 1,
578
+ .minimum_version_id = 1,
579
+ .fields = (VMStateField[]) {
580
+ VMSTATE_UINT32_ARRAY(dramcom, AwH3DramCtlState, AW_H3_DRAMCOM_REGS_NUM),
581
+ VMSTATE_UINT32_ARRAY(dramctl, AwH3DramCtlState, AW_H3_DRAMCTL_REGS_NUM),
582
+ VMSTATE_UINT32_ARRAY(dramphy, AwH3DramCtlState, AW_H3_DRAMPHY_REGS_NUM),
583
+ VMSTATE_END_OF_LIST()
584
+ }
585
+};
586
+
587
+static void allwinner_h3_dramc_class_init(ObjectClass *klass, void *data)
588
+{
589
+ DeviceClass *dc = DEVICE_CLASS(klass);
590
+
591
+ dc->reset = allwinner_h3_dramc_reset;
592
+ dc->vmsd = &allwinner_h3_dramc_vmstate;
593
+ dc->realize = allwinner_h3_dramc_realize;
594
+ device_class_set_props(dc, allwinner_h3_dramc_properties);
595
+}
596
+
597
+static const TypeInfo allwinner_h3_dramc_info = {
598
+ .name = TYPE_AW_H3_DRAMC,
599
+ .parent = TYPE_SYS_BUS_DEVICE,
600
+ .instance_init = allwinner_h3_dramc_init,
601
+ .instance_size = sizeof(AwH3DramCtlState),
602
+ .class_init = allwinner_h3_dramc_class_init,
603
+};
604
+
605
+static void allwinner_h3_dramc_register(void)
606
+{
607
+ type_register_static(&allwinner_h3_dramc_info);
608
+}
609
+
610
+type_init(allwinner_h3_dramc_register)
611
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
612
index XXXXXXX..XXXXXXX 100644
613
--- a/hw/misc/trace-events
614
+++ b/hw/misc/trace-events
615
@@ -XXX,XX +XXX,XX @@ allwinner_cpucfg_cpu_reset(uint8_t cpu_id, uint32_t reset_addr) "id %u, reset_ad
616
allwinner_cpucfg_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
617
allwinner_cpucfg_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
618
619
+# allwinner-h3-dramc.c
620
+allwinner_h3_dramc_rowmirror_disable(void) "Disable row mirror"
621
+allwinner_h3_dramc_rowmirror_enable(uint64_t addr) "Enable row mirror: addr 0x%" PRIx64
622
+allwinner_h3_dramcom_read(uint64_t offset, uint64_t data, unsigned size) "Read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
623
+allwinner_h3_dramcom_write(uint64_t offset, uint64_t data, unsigned size) "Write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
624
+allwinner_h3_dramctl_read(uint64_t offset, uint64_t data, unsigned size) "Read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
625
+allwinner_h3_dramctl_write(uint64_t offset, uint64_t data, unsigned size) "Write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
626
+allwinner_h3_dramphy_read(uint64_t offset, uint64_t data, unsigned size) "Read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
627
+allwinner_h3_dramphy_write(uint64_t offset, uint64_t data, unsigned size) "write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
628
+
629
# allwinner-sid.c
630
allwinner_sid_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
631
allwinner_sid_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
90
--
632
--
91
2.20.1
633
2.20.1
92
634
93
635
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
Rather than call to a separate function and re-compute any
3
Allwinner System-on-Chips usually contain a Real Time Clock (RTC)
4
parameters for the flush, simply use the correct flush
4
for non-volatile system date and time keeping. This commit adds a generic
5
function directly.
5
Allwinner RTC device that supports the RTC devices found in Allwinner SoC
6
family sun4i (A10), sun7i (A20) and sun6i and newer (A31, H2+, H3, etc).
7
The following RTC functionality and features are implemented:
6
8
7
Tested-by: Alex Bennée <alex.bennee@linaro.org>
9
* Year-Month-Day read/write
10
* Hour-Minute-Second read/write
11
* General Purpose storage
12
13
The following boards are extended with the RTC device:
14
15
* Cubieboard (hw/arm/cubieboard.c)
16
* Orange Pi PC (hw/arm/orangepi.c)
17
18
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
19
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
20
Message-id: 20200311221854.30370-13-nieklinnenbank@gmail.com
10
Message-id: 20200206105448.4726-9-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
22
---
13
target/arm/helper.c | 52 +++++++++++++++++++++------------------------
23
hw/rtc/Makefile.objs | 1 +
14
1 file changed, 24 insertions(+), 28 deletions(-)
24
include/hw/arm/allwinner-a10.h | 2 +
25
include/hw/arm/allwinner-h3.h | 3 +
26
include/hw/rtc/allwinner-rtc.h | 134 +++++++++++
27
hw/arm/allwinner-a10.c | 8 +
28
hw/arm/allwinner-h3.c | 9 +-
29
hw/rtc/allwinner-rtc.c | 411 +++++++++++++++++++++++++++++++++
30
hw/rtc/trace-events | 4 +
31
8 files changed, 571 insertions(+), 1 deletion(-)
32
create mode 100644 include/hw/rtc/allwinner-rtc.h
33
create mode 100644 hw/rtc/allwinner-rtc.c
15
34
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
35
diff --git a/hw/rtc/Makefile.objs b/hw/rtc/Makefile.objs
17
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.c
37
--- a/hw/rtc/Makefile.objs
19
+++ b/target/arm/helper.c
38
+++ b/hw/rtc/Makefile.objs
20
@@ -XXX,XX +XXX,XX @@ static void tlbiall_write(CPUARMState *env, const ARMCPRegInfo *ri,
39
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MC146818RTC) += mc146818rtc.o
21
uint64_t value)
40
common-obj-$(CONFIG_SUN4V_RTC) += sun4v-rtc.o
41
common-obj-$(CONFIG_ASPEED_SOC) += aspeed_rtc.o
42
common-obj-$(CONFIG_GOLDFISH_RTC) += goldfish_rtc.o
43
+common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-rtc.o
44
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/hw/arm/allwinner-a10.h
47
+++ b/include/hw/arm/allwinner-a10.h
48
@@ -XXX,XX +XXX,XX @@
49
#include "hw/ide/ahci.h"
50
#include "hw/usb/hcd-ohci.h"
51
#include "hw/usb/hcd-ehci.h"
52
+#include "hw/rtc/allwinner-rtc.h"
53
54
#include "target/arm/cpu.h"
55
56
@@ -XXX,XX +XXX,XX @@ typedef struct AwA10State {
57
AwEmacState emac;
58
AllwinnerAHCIState sata;
59
AwSdHostState mmc0;
60
+ AwRtcState rtc;
61
MemoryRegion sram_a;
62
EHCISysBusState ehci[AW_A10_NUM_USB];
63
OHCISysBusState ohci[AW_A10_NUM_USB];
64
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
65
index XXXXXXX..XXXXXXX 100644
66
--- a/include/hw/arm/allwinner-h3.h
67
+++ b/include/hw/arm/allwinner-h3.h
68
@@ -XXX,XX +XXX,XX @@
69
#include "hw/misc/allwinner-sid.h"
70
#include "hw/sd/allwinner-sdhost.h"
71
#include "hw/net/allwinner-sun8i-emac.h"
72
+#include "hw/rtc/allwinner-rtc.h"
73
#include "target/arm/cpu.h"
74
#include "sysemu/block-backend.h"
75
76
@@ -XXX,XX +XXX,XX @@ enum {
77
AW_H3_GIC_CPU,
78
AW_H3_GIC_HYP,
79
AW_H3_GIC_VCPU,
80
+ AW_H3_RTC,
81
AW_H3_CPUCFG,
82
AW_H3_SDRAM
83
};
84
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
85
AwSidState sid;
86
AwSdHostState mmc0;
87
AwSun8iEmacState emac;
88
+ AwRtcState rtc;
89
GICState gic;
90
MemoryRegion sram_a1;
91
MemoryRegion sram_a2;
92
diff --git a/include/hw/rtc/allwinner-rtc.h b/include/hw/rtc/allwinner-rtc.h
93
new file mode 100644
94
index XXXXXXX..XXXXXXX
95
--- /dev/null
96
+++ b/include/hw/rtc/allwinner-rtc.h
97
@@ -XXX,XX +XXX,XX @@
98
+/*
99
+ * Allwinner Real Time Clock emulation
100
+ *
101
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
102
+ *
103
+ * This program is free software: you can redistribute it and/or modify
104
+ * it under the terms of the GNU General Public License as published by
105
+ * the Free Software Foundation, either version 2 of the License, or
106
+ * (at your option) any later version.
107
+ *
108
+ * This program is distributed in the hope that it will be useful,
109
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
110
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
111
+ * GNU General Public License for more details.
112
+ *
113
+ * You should have received a copy of the GNU General Public License
114
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
115
+ */
116
+
117
+#ifndef HW_MISC_ALLWINNER_RTC_H
118
+#define HW_MISC_ALLWINNER_RTC_H
119
+
120
+#include "qom/object.h"
121
+#include "hw/sysbus.h"
122
+
123
+/**
124
+ * Constants
125
+ * @{
126
+ */
127
+
128
+/** Highest register address used by RTC device */
129
+#define AW_RTC_REGS_MAXADDR (0x200)
130
+
131
+/** Total number of known registers */
132
+#define AW_RTC_REGS_NUM (AW_RTC_REGS_MAXADDR / sizeof(uint32_t))
133
+
134
+/** @} */
135
+
136
+/**
137
+ * Object model types
138
+ * @{
139
+ */
140
+
141
+/** Generic Allwinner RTC device (abstract) */
142
+#define TYPE_AW_RTC "allwinner-rtc"
143
+
144
+/** Allwinner RTC sun4i family (A10, A12) */
145
+#define TYPE_AW_RTC_SUN4I TYPE_AW_RTC "-sun4i"
146
+
147
+/** Allwinner RTC sun6i family and newer (A31, H2+, H3, etc) */
148
+#define TYPE_AW_RTC_SUN6I TYPE_AW_RTC "-sun6i"
149
+
150
+/** Allwinner RTC sun7i family (A20) */
151
+#define TYPE_AW_RTC_SUN7I TYPE_AW_RTC "-sun7i"
152
+
153
+/** @} */
154
+
155
+/**
156
+ * Object model macros
157
+ * @{
158
+ */
159
+
160
+#define AW_RTC(obj) \
161
+ OBJECT_CHECK(AwRtcState, (obj), TYPE_AW_RTC)
162
+#define AW_RTC_CLASS(klass) \
163
+ OBJECT_CLASS_CHECK(AwRtcClass, (klass), TYPE_AW_RTC)
164
+#define AW_RTC_GET_CLASS(obj) \
165
+ OBJECT_GET_CLASS(AwRtcClass, (obj), TYPE_AW_RTC)
166
+
167
+/** @} */
168
+
169
+/**
170
+ * Allwinner RTC per-object instance state.
171
+ */
172
+typedef struct AwRtcState {
173
+ /*< private >*/
174
+ SysBusDevice parent_obj;
175
+ /*< public >*/
176
+
177
+ /**
178
+ * Actual year represented by the device when year counter is zero
179
+ *
180
+ * Can be overridden by the user using the corresponding 'base-year'
181
+ * property. The base year used by the target OS driver can vary, for
182
+ * example the Linux driver for sun6i uses 1970 while NetBSD uses 2000.
183
+ */
184
+ int base_year;
185
+
186
+ /** Maps I/O registers in physical memory */
187
+ MemoryRegion iomem;
188
+
189
+ /** Array of hardware registers */
190
+ uint32_t regs[AW_RTC_REGS_NUM];
191
+
192
+} AwRtcState;
193
+
194
+/**
195
+ * Allwinner RTC class-level struct.
196
+ *
197
+ * This struct is filled by each sunxi device specific code
198
+ * such that the generic code can use this struct to support
199
+ * all devices.
200
+ */
201
+typedef struct AwRtcClass {
202
+ /*< private >*/
203
+ SysBusDeviceClass parent_class;
204
+ /*< public >*/
205
+
206
+ /** Defines device specific register map */
207
+ const uint8_t *regmap;
208
+
209
+ /** Size of the regmap in bytes */
210
+ size_t regmap_size;
211
+
212
+ /**
213
+ * Read device specific register
214
+ *
215
+ * @offset: register offset to read
216
+ * @return true if register read successful, false otherwise
217
+ */
218
+ bool (*read)(AwRtcState *s, uint32_t offset);
219
+
220
+ /**
221
+ * Write device specific register
222
+ *
223
+ * @offset: register offset to write
224
+ * @data: value to set in register
225
+ * @return true if register write successful, false otherwise
226
+ */
227
+ bool (*write)(AwRtcState *s, uint32_t offset, uint32_t data);
228
+
229
+} AwRtcClass;
230
+
231
+#endif /* HW_MISC_ALLWINNER_RTC_H */
232
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
233
index XXXXXXX..XXXXXXX 100644
234
--- a/hw/arm/allwinner-a10.c
235
+++ b/hw/arm/allwinner-a10.c
236
@@ -XXX,XX +XXX,XX @@
237
#define AW_A10_EHCI_BASE 0x01c14000
238
#define AW_A10_OHCI_BASE 0x01c14400
239
#define AW_A10_SATA_BASE 0x01c18000
240
+#define AW_A10_RTC_BASE 0x01c20d00
241
242
static void aw_a10_init(Object *obj)
22
{
243
{
23
/* Invalidate all (TLBIALL) */
244
@@ -XXX,XX +XXX,XX @@ static void aw_a10_init(Object *obj)
24
- ARMCPU *cpu = env_archcpu(env);
245
25
+ CPUState *cs = env_cpu(env);
246
sysbus_init_child_obj(obj, "mmc0", &s->mmc0, sizeof(s->mmc0),
26
247
TYPE_AW_SDHOST_SUN4I);
27
if (tlb_force_broadcast(env)) {
248
+
28
- tlbiall_is_write(env, NULL, value);
249
+ sysbus_init_child_obj(obj, "rtc", &s->rtc, sizeof(s->rtc),
29
- return;
250
+ TYPE_AW_RTC_SUN4I);
30
+ tlb_flush_all_cpus_synced(cs);
31
+ } else {
32
+ tlb_flush(cs);
33
}
34
-
35
- tlb_flush(CPU(cpu));
36
}
251
}
37
252
38
static void tlbimva_write(CPUARMState *env, const ARMCPRegInfo *ri,
253
static void aw_a10_realize(DeviceState *dev, Error **errp)
39
uint64_t value)
254
@@ -XXX,XX +XXX,XX @@ static void aw_a10_realize(DeviceState *dev, Error **errp)
40
{
255
sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc0), 0, qdev_get_gpio_in(dev, 32));
41
/* Invalidate single TLB entry by MVA and ASID (TLBIMVA) */
256
object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->mmc0),
42
- ARMCPU *cpu = env_archcpu(env);
257
"sd-bus", &error_abort);
43
+ CPUState *cs = env_cpu(env);
258
+
44
259
+ /* RTC */
45
+ value &= TARGET_PAGE_MASK;
260
+ qdev_init_nofail(DEVICE(&s->rtc));
46
if (tlb_force_broadcast(env)) {
261
+ sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->rtc), 0, AW_A10_RTC_BASE, 10);
47
- tlbimva_is_write(env, NULL, value);
48
- return;
49
+ tlb_flush_page_all_cpus_synced(cs, value);
50
+ } else {
51
+ tlb_flush_page(cs, value);
52
}
53
-
54
- tlb_flush_page(CPU(cpu), value & TARGET_PAGE_MASK);
55
}
262
}
56
263
57
static void tlbiasid_write(CPUARMState *env, const ARMCPRegInfo *ri,
264
static void aw_a10_class_init(ObjectClass *oc, void *data)
58
uint64_t value)
265
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
59
{
266
index XXXXXXX..XXXXXXX 100644
60
/* Invalidate by ASID (TLBIASID) */
267
--- a/hw/arm/allwinner-h3.c
61
- ARMCPU *cpu = env_archcpu(env);
268
+++ b/hw/arm/allwinner-h3.c
62
+ CPUState *cs = env_cpu(env);
269
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
63
270
[AW_H3_GIC_CPU] = 0x01c82000,
64
if (tlb_force_broadcast(env)) {
271
[AW_H3_GIC_HYP] = 0x01c84000,
65
- tlbiasid_is_write(env, NULL, value);
272
[AW_H3_GIC_VCPU] = 0x01c86000,
66
- return;
273
+ [AW_H3_RTC] = 0x01f00000,
67
+ tlb_flush_all_cpus_synced(cs);
274
[AW_H3_CPUCFG] = 0x01f01c00,
68
+ } else {
275
[AW_H3_SDRAM] = 0x40000000
69
+ tlb_flush(cs);
276
};
70
}
277
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
71
-
278
{ "csi", 0x01cb0000, 320 * KiB },
72
- tlb_flush(CPU(cpu));
279
{ "tve", 0x01e00000, 64 * KiB },
280
{ "hdmi", 0x01ee0000, 128 * KiB },
281
- { "rtc", 0x01f00000, 1 * KiB },
282
{ "r_timer", 0x01f00800, 1 * KiB },
283
{ "r_intc", 0x01f00c00, 1 * KiB },
284
{ "r_wdog", 0x01f01000, 1 * KiB },
285
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
286
"ram-addr", &error_abort);
287
object_property_add_alias(obj, "ram-size", OBJECT(&s->dramc),
288
"ram-size", &error_abort);
289
+
290
+ sysbus_init_child_obj(obj, "rtc", &s->rtc, sizeof(s->rtc),
291
+ TYPE_AW_RTC_SUN6I);
73
}
292
}
74
293
75
static void tlbimvaa_write(CPUARMState *env, const ARMCPRegInfo *ri,
294
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
76
uint64_t value)
295
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
77
{
296
sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 1, s->memmap[AW_H3_DRAMCTL]);
78
/* Invalidate single entry by MVA, all ASIDs (TLBIMVAA) */
297
sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 2, s->memmap[AW_H3_DRAMPHY]);
79
- ARMCPU *cpu = env_archcpu(env);
298
80
+ CPUState *cs = env_cpu(env);
299
+ /* RTC */
81
300
+ qdev_init_nofail(DEVICE(&s->rtc));
82
+ value &= TARGET_PAGE_MASK;
301
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, s->memmap[AW_H3_RTC]);
83
if (tlb_force_broadcast(env)) {
302
+
84
- tlbimvaa_is_write(env, NULL, value);
303
/* Unimplemented devices */
85
- return;
304
for (i = 0; i < ARRAY_SIZE(unimplemented); i++) {
86
+ tlb_flush_page_all_cpus_synced(cs, value);
305
create_unimplemented_device(unimplemented[i].device_name,
87
+ } else {
306
diff --git a/hw/rtc/allwinner-rtc.c b/hw/rtc/allwinner-rtc.c
88
+ tlb_flush_page(cs, value);
307
new file mode 100644
89
}
308
index XXXXXXX..XXXXXXX
90
-
309
--- /dev/null
91
- tlb_flush_page(CPU(cpu), value & TARGET_PAGE_MASK);
310
+++ b/hw/rtc/allwinner-rtc.c
92
}
311
@@ -XXX,XX +XXX,XX @@
93
312
+/*
94
static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri,
313
+ * Allwinner Real Time Clock emulation
95
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vmalle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
314
+ *
96
int mask = vae1_tlbmask(env);
315
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
97
316
+ *
98
if (tlb_force_broadcast(env)) {
317
+ * This program is free software: you can redistribute it and/or modify
99
- tlbi_aa64_vmalle1is_write(env, NULL, value);
318
+ * it under the terms of the GNU General Public License as published by
100
- return;
319
+ * the Free Software Foundation, either version 2 of the License, or
101
+ tlb_flush_by_mmuidx_all_cpus_synced(cs, mask);
320
+ * (at your option) any later version.
102
+ } else {
321
+ *
103
+ tlb_flush_by_mmuidx(cs, mask);
322
+ * This program is distributed in the hope that it will be useful,
104
}
323
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
105
-
324
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
106
- tlb_flush_by_mmuidx(cs, mask);
325
+ * GNU General Public License for more details.
107
}
326
+ *
108
327
+ * You should have received a copy of the GNU General Public License
109
static int alle1_tlbmask(CPUARMState *env)
328
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
110
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
329
+ */
111
uint64_t pageaddr = sextract64(value << 12, 0, 56);
330
+
112
331
+#include "qemu/osdep.h"
113
if (tlb_force_broadcast(env)) {
332
+#include "qemu/units.h"
114
- tlbi_aa64_vae1is_write(env, NULL, value);
333
+#include "hw/sysbus.h"
115
- return;
334
+#include "migration/vmstate.h"
116
+ tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
335
+#include "qemu/log.h"
117
+ } else {
336
+#include "qemu/module.h"
118
+ tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
337
+#include "qemu-common.h"
119
}
338
+#include "hw/qdev-properties.h"
120
-
339
+#include "hw/rtc/allwinner-rtc.h"
121
- tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
340
+#include "trace.h"
122
}
341
+
123
342
+/* RTC registers */
124
static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
343
+enum {
344
+ REG_LOSC = 1, /* Low Oscillator Control */
345
+ REG_YYMMDD, /* RTC Year-Month-Day */
346
+ REG_HHMMSS, /* RTC Hour-Minute-Second */
347
+ REG_ALARM1_WKHHMMSS, /* Alarm1 Week Hour-Minute-Second */
348
+ REG_ALARM1_EN, /* Alarm1 Enable */
349
+ REG_ALARM1_IRQ_EN, /* Alarm1 IRQ Enable */
350
+ REG_ALARM1_IRQ_STA, /* Alarm1 IRQ Status */
351
+ REG_GP0, /* General Purpose Register 0 */
352
+ REG_GP1, /* General Purpose Register 1 */
353
+ REG_GP2, /* General Purpose Register 2 */
354
+ REG_GP3, /* General Purpose Register 3 */
355
+
356
+ /* sun4i registers */
357
+ REG_ALARM1_DDHHMMSS, /* Alarm1 Day Hour-Minute-Second */
358
+ REG_CPUCFG, /* CPU Configuration Register */
359
+
360
+ /* sun6i registers */
361
+ REG_LOSC_AUTOSTA, /* LOSC Auto Switch Status */
362
+ REG_INT_OSC_PRE, /* Internal OSC Clock Prescaler */
363
+ REG_ALARM0_COUNTER, /* Alarm0 Counter */
364
+ REG_ALARM0_CUR_VLU, /* Alarm0 Counter Current Value */
365
+ REG_ALARM0_ENABLE, /* Alarm0 Enable */
366
+ REG_ALARM0_IRQ_EN, /* Alarm0 IRQ Enable */
367
+ REG_ALARM0_IRQ_STA, /* Alarm0 IRQ Status */
368
+ REG_ALARM_CONFIG, /* Alarm Config */
369
+ REG_LOSC_OUT_GATING, /* LOSC Output Gating Register */
370
+ REG_GP4, /* General Purpose Register 4 */
371
+ REG_GP5, /* General Purpose Register 5 */
372
+ REG_GP6, /* General Purpose Register 6 */
373
+ REG_GP7, /* General Purpose Register 7 */
374
+ REG_RTC_DBG, /* RTC Debug Register */
375
+ REG_GPL_HOLD_OUT, /* GPL Hold Output Register */
376
+ REG_VDD_RTC, /* VDD RTC Regulate Register */
377
+ REG_IC_CHARA, /* IC Characteristics Register */
378
+};
379
+
380
+/* RTC register flags */
381
+enum {
382
+ REG_LOSC_YMD = (1 << 7),
383
+ REG_LOSC_HMS = (1 << 8),
384
+};
385
+
386
+/* RTC sun4i register map (offset to name) */
387
+const uint8_t allwinner_rtc_sun4i_regmap[] = {
388
+ [0x0000] = REG_LOSC,
389
+ [0x0004] = REG_YYMMDD,
390
+ [0x0008] = REG_HHMMSS,
391
+ [0x000C] = REG_ALARM1_DDHHMMSS,
392
+ [0x0010] = REG_ALARM1_WKHHMMSS,
393
+ [0x0014] = REG_ALARM1_EN,
394
+ [0x0018] = REG_ALARM1_IRQ_EN,
395
+ [0x001C] = REG_ALARM1_IRQ_STA,
396
+ [0x0020] = REG_GP0,
397
+ [0x0024] = REG_GP1,
398
+ [0x0028] = REG_GP2,
399
+ [0x002C] = REG_GP3,
400
+ [0x003C] = REG_CPUCFG,
401
+};
402
+
403
+/* RTC sun6i register map (offset to name) */
404
+const uint8_t allwinner_rtc_sun6i_regmap[] = {
405
+ [0x0000] = REG_LOSC,
406
+ [0x0004] = REG_LOSC_AUTOSTA,
407
+ [0x0008] = REG_INT_OSC_PRE,
408
+ [0x0010] = REG_YYMMDD,
409
+ [0x0014] = REG_HHMMSS,
410
+ [0x0020] = REG_ALARM0_COUNTER,
411
+ [0x0024] = REG_ALARM0_CUR_VLU,
412
+ [0x0028] = REG_ALARM0_ENABLE,
413
+ [0x002C] = REG_ALARM0_IRQ_EN,
414
+ [0x0030] = REG_ALARM0_IRQ_STA,
415
+ [0x0040] = REG_ALARM1_WKHHMMSS,
416
+ [0x0044] = REG_ALARM1_EN,
417
+ [0x0048] = REG_ALARM1_IRQ_EN,
418
+ [0x004C] = REG_ALARM1_IRQ_STA,
419
+ [0x0050] = REG_ALARM_CONFIG,
420
+ [0x0060] = REG_LOSC_OUT_GATING,
421
+ [0x0100] = REG_GP0,
422
+ [0x0104] = REG_GP1,
423
+ [0x0108] = REG_GP2,
424
+ [0x010C] = REG_GP3,
425
+ [0x0110] = REG_GP4,
426
+ [0x0114] = REG_GP5,
427
+ [0x0118] = REG_GP6,
428
+ [0x011C] = REG_GP7,
429
+ [0x0170] = REG_RTC_DBG,
430
+ [0x0180] = REG_GPL_HOLD_OUT,
431
+ [0x0190] = REG_VDD_RTC,
432
+ [0x01F0] = REG_IC_CHARA,
433
+};
434
+
435
+static bool allwinner_rtc_sun4i_read(AwRtcState *s, uint32_t offset)
436
+{
437
+ /* no sun4i specific registers currently implemented */
438
+ return false;
439
+}
440
+
441
+static bool allwinner_rtc_sun4i_write(AwRtcState *s, uint32_t offset,
442
+ uint32_t data)
443
+{
444
+ /* no sun4i specific registers currently implemented */
445
+ return false;
446
+}
447
+
448
+static bool allwinner_rtc_sun6i_read(AwRtcState *s, uint32_t offset)
449
+{
450
+ const AwRtcClass *c = AW_RTC_GET_CLASS(s);
451
+
452
+ switch (c->regmap[offset]) {
453
+ case REG_GP4: /* General Purpose Register 4 */
454
+ case REG_GP5: /* General Purpose Register 5 */
455
+ case REG_GP6: /* General Purpose Register 6 */
456
+ case REG_GP7: /* General Purpose Register 7 */
457
+ return true;
458
+ default:
459
+ break;
460
+ }
461
+ return false;
462
+}
463
+
464
+static bool allwinner_rtc_sun6i_write(AwRtcState *s, uint32_t offset,
465
+ uint32_t data)
466
+{
467
+ const AwRtcClass *c = AW_RTC_GET_CLASS(s);
468
+
469
+ switch (c->regmap[offset]) {
470
+ case REG_GP4: /* General Purpose Register 4 */
471
+ case REG_GP5: /* General Purpose Register 5 */
472
+ case REG_GP6: /* General Purpose Register 6 */
473
+ case REG_GP7: /* General Purpose Register 7 */
474
+ return true;
475
+ default:
476
+ break;
477
+ }
478
+ return false;
479
+}
480
+
481
+static uint64_t allwinner_rtc_read(void *opaque, hwaddr offset,
482
+ unsigned size)
483
+{
484
+ AwRtcState *s = AW_RTC(opaque);
485
+ const AwRtcClass *c = AW_RTC_GET_CLASS(s);
486
+ uint64_t val = 0;
487
+
488
+ if (offset >= c->regmap_size) {
489
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
490
+ __func__, (uint32_t)offset);
491
+ return 0;
492
+ }
493
+
494
+ if (!c->regmap[offset]) {
495
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid register 0x%04x\n",
496
+ __func__, (uint32_t)offset);
497
+ return 0;
498
+ }
499
+
500
+ switch (c->regmap[offset]) {
501
+ case REG_LOSC: /* Low Oscillator Control */
502
+ val = s->regs[REG_LOSC];
503
+ s->regs[REG_LOSC] &= ~(REG_LOSC_YMD | REG_LOSC_HMS);
504
+ break;
505
+ case REG_YYMMDD: /* RTC Year-Month-Day */
506
+ case REG_HHMMSS: /* RTC Hour-Minute-Second */
507
+ case REG_GP0: /* General Purpose Register 0 */
508
+ case REG_GP1: /* General Purpose Register 1 */
509
+ case REG_GP2: /* General Purpose Register 2 */
510
+ case REG_GP3: /* General Purpose Register 3 */
511
+ val = s->regs[c->regmap[offset]];
512
+ break;
513
+ default:
514
+ if (!c->read(s, offset)) {
515
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented register 0x%04x\n",
516
+ __func__, (uint32_t)offset);
517
+ }
518
+ val = s->regs[c->regmap[offset]];
519
+ break;
520
+ }
521
+
522
+ trace_allwinner_rtc_read(offset, val);
523
+ return val;
524
+}
525
+
526
+static void allwinner_rtc_write(void *opaque, hwaddr offset,
527
+ uint64_t val, unsigned size)
528
+{
529
+ AwRtcState *s = AW_RTC(opaque);
530
+ const AwRtcClass *c = AW_RTC_GET_CLASS(s);
531
+
532
+ if (offset >= c->regmap_size) {
533
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
534
+ __func__, (uint32_t)offset);
535
+ return;
536
+ }
537
+
538
+ if (!c->regmap[offset]) {
539
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid register 0x%04x\n",
540
+ __func__, (uint32_t)offset);
541
+ return;
542
+ }
543
+
544
+ trace_allwinner_rtc_write(offset, val);
545
+
546
+ switch (c->regmap[offset]) {
547
+ case REG_YYMMDD: /* RTC Year-Month-Day */
548
+ s->regs[REG_YYMMDD] = val;
549
+ s->regs[REG_LOSC] |= REG_LOSC_YMD;
550
+ break;
551
+ case REG_HHMMSS: /* RTC Hour-Minute-Second */
552
+ s->regs[REG_HHMMSS] = val;
553
+ s->regs[REG_LOSC] |= REG_LOSC_HMS;
554
+ break;
555
+ case REG_GP0: /* General Purpose Register 0 */
556
+ case REG_GP1: /* General Purpose Register 1 */
557
+ case REG_GP2: /* General Purpose Register 2 */
558
+ case REG_GP3: /* General Purpose Register 3 */
559
+ s->regs[c->regmap[offset]] = val;
560
+ break;
561
+ default:
562
+ if (!c->write(s, offset, val)) {
563
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented register 0x%04x\n",
564
+ __func__, (uint32_t)offset);
565
+ }
566
+ break;
567
+ }
568
+}
569
+
570
+static const MemoryRegionOps allwinner_rtc_ops = {
571
+ .read = allwinner_rtc_read,
572
+ .write = allwinner_rtc_write,
573
+ .endianness = DEVICE_NATIVE_ENDIAN,
574
+ .valid = {
575
+ .min_access_size = 4,
576
+ .max_access_size = 4,
577
+ },
578
+ .impl.min_access_size = 4,
579
+};
580
+
581
+static void allwinner_rtc_reset(DeviceState *dev)
582
+{
583
+ AwRtcState *s = AW_RTC(dev);
584
+ struct tm now;
585
+
586
+ /* Clear registers */
587
+ memset(s->regs, 0, sizeof(s->regs));
588
+
589
+ /* Get current datetime */
590
+ qemu_get_timedate(&now, 0);
591
+
592
+ /* Set RTC with current datetime */
593
+ if (s->base_year > 1900) {
594
+ s->regs[REG_YYMMDD] = ((now.tm_year + 1900 - s->base_year) << 16) |
595
+ ((now.tm_mon + 1) << 8) |
596
+ now.tm_mday;
597
+ s->regs[REG_HHMMSS] = (((now.tm_wday + 6) % 7) << 29) |
598
+ (now.tm_hour << 16) |
599
+ (now.tm_min << 8) |
600
+ now.tm_sec;
601
+ }
602
+}
603
+
604
+static void allwinner_rtc_init(Object *obj)
605
+{
606
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
607
+ AwRtcState *s = AW_RTC(obj);
608
+
609
+ /* Memory mapping */
610
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_rtc_ops, s,
611
+ TYPE_AW_RTC, 1 * KiB);
612
+ sysbus_init_mmio(sbd, &s->iomem);
613
+}
614
+
615
+static const VMStateDescription allwinner_rtc_vmstate = {
616
+ .name = "allwinner-rtc",
617
+ .version_id = 1,
618
+ .minimum_version_id = 1,
619
+ .fields = (VMStateField[]) {
620
+ VMSTATE_UINT32_ARRAY(regs, AwRtcState, AW_RTC_REGS_NUM),
621
+ VMSTATE_END_OF_LIST()
622
+ }
623
+};
624
+
625
+static Property allwinner_rtc_properties[] = {
626
+ DEFINE_PROP_INT32("base-year", AwRtcState, base_year, 0),
627
+ DEFINE_PROP_END_OF_LIST(),
628
+};
629
+
630
+static void allwinner_rtc_class_init(ObjectClass *klass, void *data)
631
+{
632
+ DeviceClass *dc = DEVICE_CLASS(klass);
633
+
634
+ dc->reset = allwinner_rtc_reset;
635
+ dc->vmsd = &allwinner_rtc_vmstate;
636
+ device_class_set_props(dc, allwinner_rtc_properties);
637
+}
638
+
639
+static void allwinner_rtc_sun4i_init(Object *obj)
640
+{
641
+ AwRtcState *s = AW_RTC(obj);
642
+ s->base_year = 2010;
643
+}
644
+
645
+static void allwinner_rtc_sun4i_class_init(ObjectClass *klass, void *data)
646
+{
647
+ AwRtcClass *arc = AW_RTC_CLASS(klass);
648
+
649
+ arc->regmap = allwinner_rtc_sun4i_regmap;
650
+ arc->regmap_size = sizeof(allwinner_rtc_sun4i_regmap);
651
+ arc->read = allwinner_rtc_sun4i_read;
652
+ arc->write = allwinner_rtc_sun4i_write;
653
+}
654
+
655
+static void allwinner_rtc_sun6i_init(Object *obj)
656
+{
657
+ AwRtcState *s = AW_RTC(obj);
658
+ s->base_year = 1970;
659
+}
660
+
661
+static void allwinner_rtc_sun6i_class_init(ObjectClass *klass, void *data)
662
+{
663
+ AwRtcClass *arc = AW_RTC_CLASS(klass);
664
+
665
+ arc->regmap = allwinner_rtc_sun6i_regmap;
666
+ arc->regmap_size = sizeof(allwinner_rtc_sun6i_regmap);
667
+ arc->read = allwinner_rtc_sun6i_read;
668
+ arc->write = allwinner_rtc_sun6i_write;
669
+}
670
+
671
+static void allwinner_rtc_sun7i_init(Object *obj)
672
+{
673
+ AwRtcState *s = AW_RTC(obj);
674
+ s->base_year = 1970;
675
+}
676
+
677
+static void allwinner_rtc_sun7i_class_init(ObjectClass *klass, void *data)
678
+{
679
+ AwRtcClass *arc = AW_RTC_CLASS(klass);
680
+ allwinner_rtc_sun4i_class_init(klass, arc);
681
+}
682
+
683
+static const TypeInfo allwinner_rtc_info = {
684
+ .name = TYPE_AW_RTC,
685
+ .parent = TYPE_SYS_BUS_DEVICE,
686
+ .instance_init = allwinner_rtc_init,
687
+ .instance_size = sizeof(AwRtcState),
688
+ .class_init = allwinner_rtc_class_init,
689
+ .class_size = sizeof(AwRtcClass),
690
+ .abstract = true,
691
+};
692
+
693
+static const TypeInfo allwinner_rtc_sun4i_info = {
694
+ .name = TYPE_AW_RTC_SUN4I,
695
+ .parent = TYPE_AW_RTC,
696
+ .class_init = allwinner_rtc_sun4i_class_init,
697
+ .instance_init = allwinner_rtc_sun4i_init,
698
+};
699
+
700
+static const TypeInfo allwinner_rtc_sun6i_info = {
701
+ .name = TYPE_AW_RTC_SUN6I,
702
+ .parent = TYPE_AW_RTC,
703
+ .class_init = allwinner_rtc_sun6i_class_init,
704
+ .instance_init = allwinner_rtc_sun6i_init,
705
+};
706
+
707
+static const TypeInfo allwinner_rtc_sun7i_info = {
708
+ .name = TYPE_AW_RTC_SUN7I,
709
+ .parent = TYPE_AW_RTC,
710
+ .class_init = allwinner_rtc_sun7i_class_init,
711
+ .instance_init = allwinner_rtc_sun7i_init,
712
+};
713
+
714
+static void allwinner_rtc_register(void)
715
+{
716
+ type_register_static(&allwinner_rtc_info);
717
+ type_register_static(&allwinner_rtc_sun4i_info);
718
+ type_register_static(&allwinner_rtc_sun6i_info);
719
+ type_register_static(&allwinner_rtc_sun7i_info);
720
+}
721
+
722
+type_init(allwinner_rtc_register)
723
diff --git a/hw/rtc/trace-events b/hw/rtc/trace-events
724
index XXXXXXX..XXXXXXX 100644
725
--- a/hw/rtc/trace-events
726
+++ b/hw/rtc/trace-events
727
@@ -XXX,XX +XXX,XX @@
728
# See docs/devel/tracing.txt for syntax documentation.
729
730
+# allwinner-rtc.c
731
+allwinner_rtc_read(uint64_t addr, uint64_t value) "addr 0x%" PRIx64 " value 0x%" PRIx64
732
+allwinner_rtc_write(uint64_t addr, uint64_t value) "addr 0x%" PRIx64 " value 0x%" PRIx64
733
+
734
# sun4v-rtc.c
735
sun4v_rtc_read(uint64_t addr, uint64_t value) "read: addr 0x%" PRIx64 " value 0x%" PRIx64
736
sun4v_rtc_write(uint64_t addr, uint64_t value) "write: addr 0x%" PRIx64 " value 0x%" PRIx64
125
--
737
--
126
2.20.1
738
2.20.1
127
739
128
740
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
The bold text sounds like 'knock knock'. Only bolding the
3
This test boots a Linux kernel on a OrangePi PC board and verify
4
second 'not' makes it easier to read.
4
the serial output is working.
5
5
6
Fixes: dea101a1ae
6
The kernel image and DeviceTree blob are built by the Armbian
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
project (based on Debian):
8
Reviewed-by: Andrew Jones <drjones@redhat.com>
8
https://www.armbian.com/orange-pi-pc/
9
Message-id: 20200206225148.23923-1-philmd@redhat.com
9
10
If ARM is a target being built, "make check-acceptance" will
11
automatically include this test by the use of the "arch:arm" tags.
12
13
Alternatively, this test can be run using:
14
15
$ make check-venv
16
$ ./tests/venv/bin/avocado --show=console,app run -t machine:orangepi-pc tests/acceptance/boot_linux_console.py
17
JOB ID : 2e4d15eceb13c33672af406f08171e6e9de1414a
18
JOB LOG : ~/job-results/job-2019-12-17T05.46-2e4d15e/job.log
19
(1/1) tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_arm_orangepi:
20
console: Uncompressing Linux... done, booting the kernel.
21
console: Booting Linux on physical CPU 0x0
22
console: Linux version 4.20.7-sunxi (root@armbian.com) (gcc version 7.2.1 20171011 (Linaro GCC 7.2-2017.11)) #5.75 SMP Fri Feb 8 09:02:10 CET 2019
23
console: CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=50c5387d
24
console: CPU: div instructions available: patching division code
25
console: CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
26
console: OF: fdt: Machine model: Xunlong Orange Pi PC
27
console: Memory policy: Data cache writealloc
28
console: OF: reserved mem: failed to allocate memory for node 'cma@4a000000'
29
console: cma: Failed to reserve 128 MiB
30
console: psci: probing for conduit method from DT.
31
console: psci: PSCIv0.2 detected in firmware.
32
console: psci: Using standard PSCI v0.2 function IDs
33
console: psci: Trusted OS migration not required
34
console: random: get_random_bytes called from start_kernel+0x8d/0x3c2 with crng_init=0
35
console: percpu: Embedded 18 pages/cpu @(ptrval) s41228 r8192 d24308 u73728
36
console: Built 1 zonelists, mobility grouping on. Total pages: 32480
37
console: Kernel command line: printk.time=0 console=ttyS0,115200
38
PASS (8.59 s)
39
JOB TIME : 8.81 s
40
41
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
42
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
43
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
44
Tested-by: Alex Bennée <alex.bennee@linaro.org>
45
Message-id: 20200311221854.30370-14-nieklinnenbank@gmail.com
46
[NL: rename in commit message Raspbian to Armbian, remove vm.set_machine()]
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
47
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
48
---
12
docs/arm-cpu-features.rst | 2 +-
49
tests/acceptance/boot_linux_console.py | 25 +++++++++++++++++++++++++
13
1 file changed, 1 insertion(+), 1 deletion(-)
50
1 file changed, 25 insertions(+)
14
51
15
diff --git a/docs/arm-cpu-features.rst b/docs/arm-cpu-features.rst
52
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
16
index XXXXXXX..XXXXXXX 100644
53
index XXXXXXX..XXXXXXX 100644
17
--- a/docs/arm-cpu-features.rst
54
--- a/tests/acceptance/boot_linux_console.py
18
+++ b/docs/arm-cpu-features.rst
55
+++ b/tests/acceptance/boot_linux_console.py
19
@@ -XXX,XX +XXX,XX @@ the list of KVM VCPU features and their descriptions.
56
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(Test):
20
57
exec_command_and_wait_for_pattern(self, 'reboot',
21
kvm-no-adjvtime By default kvm-no-adjvtime is disabled. This
58
'reboot: Restarting system')
22
means that by default the virtual time
59
23
- adjustment is enabled (vtime is *not not*
60
+ def test_arm_orangepi(self):
24
+ adjustment is enabled (vtime is not *not*
61
+ """
25
adjusted).
62
+ :avocado: tags=arch:arm
26
63
+ :avocado: tags=machine:orangepi-pc
27
When virtual time adjustment is enabled each
64
+ """
65
+ deb_url = ('https://apt.armbian.com/pool/main/l/'
66
+ 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
67
+ deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
68
+ deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
69
+ kernel_path = self.extract_from_deb(deb_path,
70
+ '/boot/vmlinuz-4.20.7-sunxi')
71
+ dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb'
72
+ dtb_path = self.extract_from_deb(deb_path, dtb_path)
73
+
74
+ self.vm.set_console()
75
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
76
+ 'console=ttyS0,115200n8 '
77
+ 'earlycon=uart,mmio32,0x1c28000')
78
+ self.vm.add_args('-kernel', kernel_path,
79
+ '-dtb', dtb_path,
80
+ '-append', kernel_command_line)
81
+ self.vm.launch()
82
+ console_pattern = 'Kernel command line: %s' % kernel_command_line
83
+ self.wait_for_console_pattern(console_pattern)
84
+
85
def test_s390x_s390_ccw_virtio(self):
86
"""
87
:avocado: tags=arch:s390x
28
--
88
--
29
2.20.1
89
2.20.1
30
90
31
91
diff view generated by jsdifflib
1
From: Rene Stange <rsta2@o2online.de>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
TD (two dimensions) DMA mode did not work, because the xlen variable
3
This test boots a Linux kernel on a OrangePi PC board and verify
4
has not been re-initialized before each additional ylen run through
4
the serial output is working.
5
in bcm2835_dma_update(). Fix it.
6
5
7
Signed-off-by: Rene Stange <rsta2@o2online.de>
6
The kernel image and DeviceTree blob are built by the Armbian
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
project (based on Debian):
8
https://www.armbian.com/orange-pi-pc/
9
10
The cpio image used comes from the linux-build-test project:
11
https://github.com/groeck/linux-build-test
12
13
If ARM is a target being built, "make check-acceptance" will
14
automatically include this test by the use of the "arch:arm" tags.
15
16
Alternatively, this test can be run using:
17
18
$ avocado --show=console run -t machine:orangepi-pc tests/acceptance/boot_linux_console.py
19
console: Uncompressing Linux... done, booting the kernel.
20
console: Booting Linux on physical CPU 0x0
21
console: Linux version 4.20.7-sunxi (root@armbian.com) (gcc version 7.2.1 20171011 (Linaro GCC 7.2-2017.11)) #5.75 SMP Fri Feb 8 09:02:10 CET 2019
22
console: CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=50c5387d
23
console: CPU: div instructions available: patching division code
24
console: CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
25
console: OF: fdt: Machine model: Xunlong Orange Pi PC
26
[...]
27
console: Trying to unpack rootfs image as initramfs...
28
console: Freeing initrd memory: 3256K
29
console: Freeing unused kernel memory: 1024K
30
console: Run /init as init process
31
console: mount: mounting devtmpfs on /dev failed: Device or resource busy
32
console: Starting logging: OK
33
console: Initializing random number generator... random: dd: uninitialized urandom read (512 bytes read)
34
console: done.
35
console: Starting network: OK
36
console: Found console ttyS0
37
console: Linux version 4.20.7-sunxi (root@armbian.com) (gcc version 7.2.1 20171011 (Linaro GCC 7.2-2017.11)) #5.75 SMP Fri Feb 8 09:02:10 CET 2019
38
console: Boot successful.
39
console: cat /proc/cpuinfo
40
console: / # cat /proc/cpuinfo
41
console: processor : 0
42
console: model name : ARMv7 Processor rev 5 (v7l)
43
console: BogoMIPS : 125.00
44
console: Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm
45
console: CPU implementer : 0x41
46
console: CPU architecture: 7
47
console: CPU variant : 0x0
48
console: CPU part : 0xc07
49
console: CPU revision : 5
50
[...]
51
console: processor : 3
52
console: model name : ARMv7 Processor rev 5 (v7l)
53
console: BogoMIPS : 125.00
54
console: Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm
55
console: CPU implementer : 0x41
56
console: CPU architecture: 7
57
console: CPU variant : 0x0
58
console: CPU part : 0xc07
59
console: CPU revision : 5
60
console: Hardware : Allwinner sun8i Family
61
console: Revision : 0000
62
console: Serial : 0000000000000000
63
console: cat /proc/iomem
64
console: / # cat /proc/iomem
65
console: 01000000-010fffff : clock@1000000
66
console: 01c00000-01c00fff : system-control@1c00000
67
console: 01c02000-01c02fff : dma-controller@1c02000
68
[...]
69
console: reboot
70
console: / # reboot
71
console: / # Found console ttyS0
72
console: Stopping network: OK
73
console: hrtimer: interrupt took 21852064 ns
74
console: Saving random seed... random: dd: uninitialized urandom read (512 bytes read)
75
console: done.
76
console: Stopping logging: OK
77
console: umount: devtmpfs busy - remounted read-only
78
console: umount: can't unmount /: Invalid argument
79
console: The system is going down NOW!
80
console: Sent SIGTERM to all processes
81
console: Sent SIGKILL to all processes
82
console: Requesting system reboot
83
console: reboot: Restarting system
84
PASS (48.32 s)
85
JOB TIME : 49.16 s
86
87
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
88
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
89
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
90
Tested-by: Alex Bennée <alex.bennee@linaro.org>
91
Message-id: 20200311221854.30370-15-nieklinnenbank@gmail.com
92
[NL: rename in commit message Raspbian to Armbian, remove vm.set_machine()]
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
93
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
94
---
11
hw/dma/bcm2835_dma.c | 4 +++-
95
tests/acceptance/boot_linux_console.py | 40 ++++++++++++++++++++++++++
12
1 file changed, 3 insertions(+), 1 deletion(-)
96
1 file changed, 40 insertions(+)
13
97
14
diff --git a/hw/dma/bcm2835_dma.c b/hw/dma/bcm2835_dma.c
98
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
15
index XXXXXXX..XXXXXXX 100644
99
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/dma/bcm2835_dma.c
100
--- a/tests/acceptance/boot_linux_console.py
17
+++ b/hw/dma/bcm2835_dma.c
101
+++ b/tests/acceptance/boot_linux_console.py
18
@@ -XXX,XX +XXX,XX @@
102
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(Test):
19
static void bcm2835_dma_update(BCM2835DMAState *s, unsigned c)
103
console_pattern = 'Kernel command line: %s' % kernel_command_line
20
{
104
self.wait_for_console_pattern(console_pattern)
21
BCM2835DMAChan *ch = &s->chan[c];
105
22
- uint32_t data, xlen, ylen;
106
+ def test_arm_orangepi_initrd(self):
23
+ uint32_t data, xlen, xlen_td, ylen;
107
+ """
24
int16_t dst_stride, src_stride;
108
+ :avocado: tags=arch:arm
25
109
+ :avocado: tags=machine:orangepi-pc
26
if (!(s->enable & (1 << c))) {
110
+ """
27
@@ -XXX,XX +XXX,XX @@ static void bcm2835_dma_update(BCM2835DMAState *s, unsigned c)
111
+ deb_url = ('https://apt.armbian.com/pool/main/l/'
28
dst_stride = 0;
112
+ 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
29
src_stride = 0;
113
+ deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
30
}
114
+ deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
31
+ xlen_td = xlen;
115
+ kernel_path = self.extract_from_deb(deb_path,
32
116
+ '/boot/vmlinuz-4.20.7-sunxi')
33
while (ylen != 0) {
117
+ dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb'
34
/* Normal transfer mode */
118
+ dtb_path = self.extract_from_deb(deb_path, dtb_path)
35
@@ -XXX,XX +XXX,XX @@ static void bcm2835_dma_update(BCM2835DMAState *s, unsigned c)
119
+ initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
36
if (--ylen != 0) {
120
+ '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
37
ch->source_ad += src_stride;
121
+ 'arm/rootfs-armv7a.cpio.gz')
38
ch->dest_ad += dst_stride;
122
+ initrd_hash = '604b2e45cdf35045846b8bbfbf2129b1891bdc9c'
39
+ xlen = xlen_td;
123
+ initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
40
}
124
+ initrd_path = os.path.join(self.workdir, 'rootfs.cpio')
41
}
125
+ archive.gzip_uncompress(initrd_path_gz, initrd_path)
42
ch->cs |= BCM2708_DMA_END;
126
+
127
+ self.vm.set_console()
128
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
129
+ 'console=ttyS0,115200 '
130
+ 'panic=-1 noreboot')
131
+ self.vm.add_args('-kernel', kernel_path,
132
+ '-dtb', dtb_path,
133
+ '-initrd', initrd_path,
134
+ '-append', kernel_command_line,
135
+ '-no-reboot')
136
+ self.vm.launch()
137
+ self.wait_for_console_pattern('Boot successful.')
138
+
139
+ exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
140
+ 'Allwinner sun8i Family')
141
+ exec_command_and_wait_for_pattern(self, 'cat /proc/iomem',
142
+ 'system-control@1c00000')
143
+ exec_command_and_wait_for_pattern(self, 'reboot',
144
+ 'reboot: Restarting system')
145
+
146
def test_s390x_s390_ccw_virtio(self):
147
"""
148
:avocado: tags=arch:s390x
43
--
149
--
44
2.20.1
150
2.20.1
45
151
46
152
diff view generated by jsdifflib
1
From: Rene Stange <rsta2@o2online.de>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
In TD (two dimensions) DMA mode ylen has to be increased by one after
3
The kernel image and DeviceTree blob are built by the Armbian
4
reading it from the TXFR_LEN register, because a value of zero has to
4
project (based on Debian):
5
result in one run through of the ylen loop. This has been tested on a
5
https://www.armbian.com/orange-pi-pc/
6
real Raspberry Pi 3 Model B+. In the previous implementation the ylen
7
loop was not passed at all for a value of zero.
8
6
9
Signed-off-by: Rene Stange <rsta2@o2online.de>
7
The SD image is from the kernelci.org project:
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
https://kernelci.org/faq/#the-code
9
10
If ARM is a target being built, "make check-acceptance" will
11
automatically include this test by the use of the "arch:arm" tags.
12
13
Alternatively, this test can be run using:
14
15
$ avocado --show=console run -t machine:orangepi-pc tests/acceptance/boot_linux_console.py
16
console: Uncompressing Linux... done, booting the kernel.
17
console: Booting Linux on physical CPU 0x0
18
console: Linux version 4.20.7-sunxi (root@armbian.com) (gcc version 7.2.1 20171011 (Linaro GCC 7.2-2017.11)) #5.75 SMP Fri Feb 8 09:02:10 CET 2019
19
console: CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=50c5387d
20
[...]
21
console: sunxi-wdt 1c20ca0.watchdog: Watchdog enabled (timeout=16 sec, nowayout=0)
22
console: sunxi-mmc 1c0f000.mmc: Linked as a consumer to regulator.2
23
console: sunxi-mmc 1c0f000.mmc: Got CD GPIO
24
console: ledtrig-cpu: registered to indicate activity on CPUs
25
console: hidraw: raw HID events driver (C) Jiri Kosina
26
console: usbcore: registered new interface driver usbhid
27
console: usbhid: USB HID core driver
28
console: Initializing XFRM netlink socket
29
console: sunxi-mmc 1c0f000.mmc: initialized, max. request size: 16384 KB
30
console: NET: Registered protocol family 10
31
console: mmc0: host does not support reading read-only switch, assuming write-enable
32
console: mmc0: Problem switching card into high-speed mode!
33
console: mmc0: new SD card at address 4567
34
console: mmcblk0: mmc0:4567 QEMU! 60.0 MiB
35
[...]
36
console: EXT4-fs (mmcblk0): mounting ext2 file system using the ext4 subsystem
37
console: EXT4-fs (mmcblk0): mounted filesystem without journal. Opts: (null)
38
console: VFS: Mounted root (ext2 filesystem) on device 179:0.
39
console: Run /sbin/init as init process
40
console: EXT4-fs (mmcblk0): re-mounted. Opts: block_validity,barrier,user_xattr,acl
41
console: Starting syslogd: OK
42
console: Starting klogd: OK
43
console: Populating /dev using udev: udevd[203]: starting version 3.2.7
44
console: /bin/sh: can't access tty; job control turned off
45
console: cat /proc/partitions
46
console: / # cat /proc/partitions
47
console: major minor #blocks name
48
console: 1 0 4096 ram0
49
console: 1 1 4096 ram1
50
console: 1 2 4096 ram2
51
console: 1 3 4096 ram3
52
console: 179 0 61440 mmcblk0
53
console: reboot
54
console: / # reboot
55
console: umount: devtmpfs busy - remounted read-only
56
console: EXT4-fs (mmcblk0): re-mounted. Opts: (null)
57
console: The system is going down NOW!
58
console: Sent SIGTERM to all processes
59
console: Sent SIGKILL to all processes
60
console: Requesting system reboot
61
console: reboot: Restarting system
62
JOB TIME : 68.64 s
63
64
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
65
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
66
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
67
Tested-by: Alex Bennée <alex.bennee@linaro.org>
68
Message-id: 20200311221854.30370-16-nieklinnenbank@gmail.com
69
[NL: rename in commit message Raspbian to Armbian, remove vm.set_machine()]
70
[NL: extend test with ethernet device checks]
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
71
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
72
---
13
hw/dma/bcm2835_dma.c | 4 ++--
73
tests/acceptance/boot_linux_console.py | 47 ++++++++++++++++++++++++++
14
1 file changed, 2 insertions(+), 2 deletions(-)
74
1 file changed, 47 insertions(+)
15
75
16
diff --git a/hw/dma/bcm2835_dma.c b/hw/dma/bcm2835_dma.c
76
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
17
index XXXXXXX..XXXXXXX 100644
77
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/dma/bcm2835_dma.c
78
--- a/tests/acceptance/boot_linux_console.py
19
+++ b/hw/dma/bcm2835_dma.c
79
+++ b/tests/acceptance/boot_linux_console.py
20
@@ -XXX,XX +XXX,XX @@ static void bcm2835_dma_update(BCM2835DMAState *s, unsigned c)
80
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(Test):
21
ch->stride = ldl_le_phys(&s->dma_as, ch->conblk_ad + 16);
81
exec_command_and_wait_for_pattern(self, 'reboot',
22
ch->nextconbk = ldl_le_phys(&s->dma_as, ch->conblk_ad + 20);
82
'reboot: Restarting system')
23
83
24
+ ylen = 1;
84
+ def test_arm_orangepi_sd(self):
25
if (ch->ti & BCM2708_DMA_TDMODE) {
85
+ """
26
/* 2D transfer mode */
86
+ :avocado: tags=arch:arm
27
- ylen = (ch->txfr_len >> 16) & 0x3fff;
87
+ :avocado: tags=machine:orangepi-pc
28
+ ylen += (ch->txfr_len >> 16) & 0x3fff;
88
+ """
29
xlen = ch->txfr_len & 0xffff;
89
+ deb_url = ('https://apt.armbian.com/pool/main/l/'
30
dst_stride = ch->stride >> 16;
90
+ 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
31
src_stride = ch->stride & 0xffff;
91
+ deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
32
} else {
92
+ deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
33
- ylen = 1;
93
+ kernel_path = self.extract_from_deb(deb_path,
34
xlen = ch->txfr_len;
94
+ '/boot/vmlinuz-4.20.7-sunxi')
35
dst_stride = 0;
95
+ dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb'
36
src_stride = 0;
96
+ dtb_path = self.extract_from_deb(deb_path, dtb_path)
97
+ rootfs_url = ('http://storage.kernelci.org/images/rootfs/buildroot/'
98
+ 'kci-2019.02/armel/base/rootfs.ext2.xz')
99
+ rootfs_hash = '692510cb625efda31640d1de0a8d60e26040f061'
100
+ rootfs_path_xz = self.fetch_asset(rootfs_url, asset_hash=rootfs_hash)
101
+ rootfs_path = os.path.join(self.workdir, 'rootfs.cpio')
102
+ archive.lzma_uncompress(rootfs_path_xz, rootfs_path)
103
+
104
+ self.vm.set_console()
105
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
106
+ 'console=ttyS0,115200 '
107
+ 'root=/dev/mmcblk0 rootwait rw '
108
+ 'panic=-1 noreboot')
109
+ self.vm.add_args('-kernel', kernel_path,
110
+ '-dtb', dtb_path,
111
+ '-drive', 'file=' + rootfs_path + ',if=sd,format=raw',
112
+ '-append', kernel_command_line,
113
+ '-no-reboot')
114
+ self.vm.launch()
115
+ shell_ready = "/bin/sh: can't access tty; job control turned off"
116
+ self.wait_for_console_pattern(shell_ready)
117
+
118
+ exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
119
+ 'Allwinner sun8i Family')
120
+ exec_command_and_wait_for_pattern(self, 'cat /proc/partitions',
121
+ 'mmcblk0')
122
+ exec_command_and_wait_for_pattern(self, 'ifconfig eth0 up',
123
+ 'eth0: Link is Up')
124
+ exec_command_and_wait_for_pattern(self, 'udhcpc eth0',
125
+ 'udhcpc: lease of 10.0.2.15 obtained')
126
+ exec_command_and_wait_for_pattern(self, 'ping -c 3 10.0.2.2',
127
+ '3 packets transmitted, 3 packets received, 0% packet loss')
128
+ exec_command_and_wait_for_pattern(self, 'reboot',
129
+ 'reboot: Restarting system')
130
+
131
def test_s390x_s390_ccw_virtio(self):
132
"""
133
:avocado: tags=arch:s390x
37
--
134
--
38
2.20.1
135
2.20.1
39
136
40
137
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
This test boots Ubuntu Bionic on a OrangePi PC board.
4
5
As it requires 1GB of storage, and is slow, this test is disabled
6
on automatic CI testing.
7
8
It is useful for workstation testing. Currently Avocado timeouts too
9
quickly, so we can't run userland commands.
10
11
The kernel image and DeviceTree blob are built by the Armbian
12
project (based on Debian):
13
https://www.armbian.com/orange-pi-pc/
14
15
The Ubuntu image is downloaded from:
16
https://dl.armbian.com/orangepipc/Bionic_current
17
18
This test can be run using:
19
20
$ AVOCADO_ALLOW_LARGE_STORAGE=yes \
21
avocado --show=app,console run -t machine:orangepi-pc \
22
tests/acceptance/boot_linux_console.py
23
console: U-Boot SPL 2019.04-armbian (Nov 18 2019 - 23:08:35 +0100)
24
console: DRAM: 1024 MiB
25
console: Failed to set core voltage! Can't set CPU frequency
26
console: Trying to boot from MMC1
27
console: U-Boot 2019.04-armbian (Nov 18 2019 - 23:08:35 +0100) Allwinner Technology
28
console: CPU: Allwinner H3 (SUN8I 0000)
29
console: Model: Xunlong Orange Pi PC
30
console: DRAM: 1 GiB
31
console: MMC: mmc@1c0f000: 0
32
[...]
33
console: Uncompressing Linux... done, booting the kernel.
34
console: Booting Linux on physical CPU 0x0
35
console: Linux version 5.3.9-sunxi (root@builder) (gcc version 8.3.0 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36))) #19.11.3 SMP Mon Nov 18 18:49:43 CET 2019
36
console: CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=50c5387d
37
console: CPU: div instructions available: patching division code
38
console: CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
39
console: OF: fdt: Machine model: Xunlong Orange Pi PC
40
[...]
41
console: EXT4-fs (mmcblk0p1): mounted filesystem with writeback data mode. Opts: (null)
42
console: done.
43
console: Begin: Running /scripts/local-bottom ... done.
44
console: Begin: Running /scripts/init-bottom ... done.
45
console: systemd[1]: systemd 237 running in system mode. (...)
46
console: systemd[1]: Detected architecture arm.
47
console: Welcome to Ubuntu 18.04.3 LTS!
48
console: systemd[1]: Set hostname to <orangepipc>.
49
50
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
51
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
52
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Tested-by: Alex Bennée <alex.bennee@linaro.org>
53
Tested-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
54
Message-id: 20200311221854.30370-17-nieklinnenbank@gmail.com
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
55
[NL: rename in commit message Raspbian to Armbian, remove vm.set_machine()]
6
Message-id: 20200206105448.4726-38-richard.henderson@linaro.org
56
[NL: changed test to boot from SD card via BootROM, added check for 7z]
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
57
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
58
---
9
target/arm/cpu64.c | 1 +
59
tests/acceptance/boot_linux_console.py | 48 ++++++++++++++++++++++++++
10
1 file changed, 1 insertion(+)
60
1 file changed, 48 insertions(+)
11
61
12
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
62
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
13
index XXXXXXX..XXXXXXX 100644
63
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu64.c
64
--- a/tests/acceptance/boot_linux_console.py
15
+++ b/target/arm/cpu64.c
65
+++ b/tests/acceptance/boot_linux_console.py
16
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
66
@@ -XXX,XX +XXX,XX @@ from avocado_qemu import exec_command_and_wait_for_pattern
17
t = cpu->isar.id_aa64mmfr1;
67
from avocado_qemu import wait_for_console_pattern
18
t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* HPD */
68
from avocado.utils import process
19
t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1);
69
from avocado.utils import archive
20
+ t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1);
70
+from avocado.utils.path import find_command, CmdNotFoundError
21
cpu->isar.id_aa64mmfr1 = t;
71
22
72
+P7ZIP_AVAILABLE = True
23
/* Replicate the same data to the 32-bit id registers. */
73
+try:
74
+ find_command('7z')
75
+except CmdNotFoundError:
76
+ P7ZIP_AVAILABLE = False
77
78
class BootLinuxConsole(Test):
79
"""
80
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(Test):
81
exec_command_and_wait_for_pattern(self, 'reboot',
82
'reboot: Restarting system')
83
84
+ @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
85
+ @skipUnless(P7ZIP_AVAILABLE, '7z not installed')
86
+ def test_arm_orangepi_bionic(self):
87
+ """
88
+ :avocado: tags=arch:arm
89
+ :avocado: tags=machine:orangepi-pc
90
+ """
91
+
92
+ # This test download a 196MB compressed image and expand it to 932MB...
93
+ image_url = ('https://dl.armbian.com/orangepipc/archive/'
94
+ 'Armbian_19.11.3_Orangepipc_bionic_current_5.3.9.7z')
95
+ image_hash = '196a8ffb72b0123d92cea4a070894813d305c71e'
96
+ image_path_7z = self.fetch_asset(image_url, asset_hash=image_hash)
97
+ image_name = 'Armbian_19.11.3_Orangepipc_bionic_current_5.3.9.img'
98
+ image_path = os.path.join(self.workdir, image_name)
99
+ process.run("7z e -o%s %s" % (self.workdir, image_path_7z))
100
+
101
+ self.vm.set_console()
102
+ self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw',
103
+ '-nic', 'user',
104
+ '-no-reboot')
105
+ self.vm.launch()
106
+
107
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
108
+ 'console=ttyS0,115200 '
109
+ 'loglevel=7 '
110
+ 'nosmp '
111
+ 'systemd.default_timeout_start_sec=9000 '
112
+ 'systemd.mask=armbian-zram-config.service '
113
+ 'systemd.mask=armbian-ramlog.service')
114
+
115
+ self.wait_for_console_pattern('U-Boot SPL')
116
+ self.wait_for_console_pattern('Autoboot in ')
117
+ exec_command_and_wait_for_pattern(self, ' ', '=>')
118
+ exec_command_and_wait_for_pattern(self, "setenv extraargs '" +
119
+ kernel_command_line + "'", '=>')
120
+ exec_command_and_wait_for_pattern(self, 'boot', 'Starting kernel ...');
121
+
122
+ self.wait_for_console_pattern('systemd[1]: Set hostname ' +
123
+ 'to <orangepipc>')
124
+ self.wait_for_console_pattern('Starting Load Kernel Modules...')
125
+
126
def test_s390x_s390_ccw_virtio(self):
127
"""
128
:avocado: tags=arch:s390x
24
--
129
--
25
2.20.1
130
2.20.1
26
131
27
132
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
When VHE is enabled, the exception level below EL2 is not EL1,
3
This test boots U-Boot then NetBSD (stored on a SD card) on
4
but EL0, and so to identify the entry vector offset for exceptions
4
a OrangePi PC board.
5
targeting EL2 we need to look at the width of EL0, not of EL1.
6
5
6
As it requires ~1.3GB of storage, it is disabled by default.
7
8
U-Boot is built by the Debian project [1], and the SD card image
9
is provided by the NetBSD organization [2].
10
11
Once the compressed SD card image is downloaded (304MB) and
12
extracted, this test is fast:
13
14
$ AVOCADO_ALLOW_LARGE_STORAGE=yes \
15
avocado --show=app,console run -t machine:orangepi-pc \
16
tests/acceptance/boot_linux_console.py
17
console: U-Boot SPL 2020.01+dfsg-1 (Jan 08 2020 - 08:19:44 +0000)
18
console: DRAM: 1024 MiB
19
console: U-Boot 2020.01+dfsg-1 (Jan 08 2020 - 08:19:44 +0000) Allwinner Technology
20
console: CPU: Allwinner H3 (SUN8I 0000)
21
console: scanning bus usb@1c1b000 for devices... 1 USB Device(s) found
22
console: scanning bus usb@1c1d000 for devices... 1 USB Device(s) found
23
console: scanning usb for storage devices... 0 Storage Device(s) found
24
console: Hit any key to stop autoboot: 0
25
console: => setenv bootargs root=ld0a
26
console: => setenv kernel netbsd-GENERIC.ub
27
console: => setenv fdtfile dtb/sun8i-h3-orangepi-pc.dtb
28
console: => boot
29
console: ## Booting kernel from Legacy Image at 42000000 ...
30
console: Image Name: NetBSD/earmv7hf 9.0_RC1
31
console: Image Type: ARM Linux Kernel Image (no loading done) (uncompressed)
32
console: XIP Kernel Image (no loading done)
33
console: Loading Device Tree to 49ff6000, end 49fffe01 ... OK
34
console: Starting kernel ...
35
console: [ 1.0000000] NetBSD/evbarm (fdt) booting ...
36
console: [ 1.0000000] NetBSD 9.0 (GENERIC) #0: Fri Feb 14 00:06:28 UTC 2020
37
console: [ 1.0000000] mkrepro@mkrepro.NetBSD.org:/usr/src/sys/arch/evbarm/compile/GENERIC
38
console: [ 1.0000000] total memory = 1024 MB
39
console: [ 1.0000000] avail memory = 1003 MB
40
console: [ 1.0000000] armfdt0 (root)
41
console: [ 1.0000000] simplebus0 at armfdt0: Xunlong Orange Pi PC
42
console: [ 1.0000000] cpu0 at cpus0: Cortex-A7 r0p5 (Cortex V7A core)
43
console: [ 1.0000000] cpu0: DC enabled IC enabled WB enabled LABT branch prediction enabled
44
console: [ 1.0000000] cpu0: 32KB/64B 2-way L1 VIPT Instruction cache
45
console: [ 1.0000000] cpu0: 32KB/64B 2-way write-back-locking-C L1 PIPT Data cache
46
console: [ 1.0000000] cpu0: 2304KB/64B 16-way write-through L2 PIPT Unified cache
47
console: [ 1.0000000] vfp0 at cpu0: NEON MPE (VFP 3.0+), rounding, NaN propagation, denormals
48
...
49
console: [ 2.3812082] sdmmc0: SD card status: 4-bit, C0
50
console: [ 2.3812082] ld0 at sdmmc0: <0xaa:0x5859:QEMU!:0x01:0xdeadbeef:0x062>
51
console: [ 2.4012856] ld0: 1226 MB, 622 cyl, 64 head, 63 sec, 512 bytes/sect x 2511872 sectors
52
console: [ 2.5321222] ld0: 4-bit width, High-Speed/SDR25, 50.000 MHz
53
console: [ 3.1068718] WARNING: 4 errors while detecting hardware; check system log.
54
console: [ 3.1179868] boot device: ld0
55
console: [ 3.1470623] root on ld0a dumps on ld0b
56
console: [ 3.2464436] root file system type: ffs
57
console: [ 3.2897123] kern.module.path=/stand/evbarm/9.0/modules
58
console: Mon Feb 17 20:33:35 UTC 2020
59
console: Starting root file system check:
60
PASS (35.96 s)
61
RESULTS : PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0
62
JOB TIME : 36.09 s
63
64
Note, this test only took ~65 seconds to run on Travis-CI, see: [3].
65
66
This test is based on a description from Niek Linnenbank from [4].
67
68
[1] https://wiki.debian.org/InstallingDebianOn/Allwinner#Creating_a_bootable_SD_Card_with_u-boot
69
[2] https://wiki.netbsd.org/ports/evbarm/allwinner/
70
[3] https://travis-ci.org/philmd/qemu/jobs/638823612#L3778
71
[4] https://www.mail-archive.com/qemu-devel@nongnu.org/msg669347.html
72
73
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
74
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
75
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Tested-by: Alex Bennée <alex.bennee@linaro.org>
76
Tested-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
77
Message-id: 20200311221854.30370-18-nieklinnenbank@gmail.com
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
78
[NL: changed test to use NetBSD 9.0 final release and -global allwinner-rtc.base-year]
10
Message-id: 20200206105448.4726-37-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
79
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
80
---
13
target/arm/helper.c | 9 +++++++--
81
tests/acceptance/boot_linux_console.py | 70 ++++++++++++++++++++++++++
14
1 file changed, 7 insertions(+), 2 deletions(-)
82
1 file changed, 70 insertions(+)
15
83
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
84
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
17
index XXXXXXX..XXXXXXX 100644
85
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.c
86
--- a/tests/acceptance/boot_linux_console.py
19
+++ b/target/arm/helper.c
87
+++ b/tests/acceptance/boot_linux_console.py
20
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
88
@@ -XXX,XX +XXX,XX @@ import shutil
21
* immediately lower than the target level is using AArch32 or AArch64
89
from avocado import skipUnless
22
*/
90
from avocado_qemu import Test
23
bool is_aa64;
91
from avocado_qemu import exec_command_and_wait_for_pattern
24
+ uint64_t hcr;
92
+from avocado_qemu import interrupt_interactive_console_until_pattern
25
93
from avocado_qemu import wait_for_console_pattern
26
switch (new_el) {
94
from avocado.utils import process
27
case 3:
95
from avocado.utils import archive
28
is_aa64 = (env->cp15.scr_el3 & SCR_RW) != 0;
96
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(Test):
29
break;
97
'to <orangepipc>')
30
case 2:
98
self.wait_for_console_pattern('Starting Load Kernel Modules...')
31
- is_aa64 = (env->cp15.hcr_el2 & HCR_RW) != 0;
99
32
- break;
100
+ @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
33
+ hcr = arm_hcr_el2_eff(env);
101
+ def test_arm_orangepi_uboot_netbsd9(self):
34
+ if ((hcr & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
102
+ """
35
+ is_aa64 = (hcr & HCR_RW) != 0;
103
+ :avocado: tags=arch:arm
36
+ break;
104
+ :avocado: tags=machine:orangepi-pc
37
+ }
105
+ """
38
+ /* fall through */
106
+ # This test download a 304MB compressed image and expand it to 1.3GB...
39
case 1:
107
+ deb_url = ('http://snapshot.debian.org/archive/debian/'
40
is_aa64 = is_a64(env);
108
+ '20200108T145233Z/pool/main/u/u-boot/'
41
break;
109
+ 'u-boot-sunxi_2020.01%2Bdfsg-1_armhf.deb')
110
+ deb_hash = 'f67f404a80753ca3d1258f13e38f2b060e13db99'
111
+ deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
112
+ # We use the common OrangePi PC 'plus' build of U-Boot for our secondary
113
+ # program loader (SPL). We will then set the path to the more specific
114
+ # OrangePi "PC" device tree blob with 'setenv fdtfile' in U-Boot prompt,
115
+ # before to boot NetBSD.
116
+ uboot_path = '/usr/lib/u-boot/orangepi_plus/u-boot-sunxi-with-spl.bin'
117
+ uboot_path = self.extract_from_deb(deb_path, uboot_path)
118
+ image_url = ('https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.0/'
119
+ 'evbarm-earmv7hf/binary/gzimg/armv7.img.gz')
120
+ image_hash = '2babb29d36d8360adcb39c09e31060945259917a'
121
+ image_path_gz = self.fetch_asset(image_url, asset_hash=image_hash)
122
+ image_path = os.path.join(self.workdir, 'armv7.img')
123
+ image_drive_args = 'if=sd,format=raw,snapshot=on,file=' + image_path
124
+ archive.gzip_uncompress(image_path_gz, image_path)
125
+
126
+ # dd if=u-boot-sunxi-with-spl.bin of=armv7.img bs=1K seek=8 conv=notrunc
127
+ with open(uboot_path, 'rb') as f_in:
128
+ with open(image_path, 'r+b') as f_out:
129
+ f_out.seek(8 * 1024)
130
+ shutil.copyfileobj(f_in, f_out)
131
+
132
+ # Extend image, to avoid that NetBSD thinks the partition
133
+ # inside the image is larger than device size itself
134
+ f_out.seek(0, 2)
135
+ f_out.seek(64 * 1024 * 1024, 1)
136
+ f_out.write(bytearray([0x00]))
137
+
138
+ self.vm.set_console()
139
+ self.vm.add_args('-nic', 'user',
140
+ '-drive', image_drive_args,
141
+ '-global', 'allwinner-rtc.base-year=2000',
142
+ '-no-reboot')
143
+ self.vm.launch()
144
+ wait_for_console_pattern(self, 'U-Boot 2020.01+dfsg-1')
145
+ interrupt_interactive_console_until_pattern(self,
146
+ 'Hit any key to stop autoboot:',
147
+ 'switch to partitions #0, OK')
148
+
149
+ exec_command_and_wait_for_pattern(self, '', '=>')
150
+ cmd = 'setenv bootargs root=ld0a'
151
+ exec_command_and_wait_for_pattern(self, cmd, '=>')
152
+ cmd = 'setenv kernel netbsd-GENERIC.ub'
153
+ exec_command_and_wait_for_pattern(self, cmd, '=>')
154
+ cmd = 'setenv fdtfile dtb/sun8i-h3-orangepi-pc.dtb'
155
+ exec_command_and_wait_for_pattern(self, cmd, '=>')
156
+ cmd = ("setenv bootcmd 'fatload mmc 0:1 ${kernel_addr_r} ${kernel}; "
157
+ "fatload mmc 0:1 ${fdt_addr_r} ${fdtfile}; "
158
+ "fdt addr ${fdt_addr_r}; "
159
+ "bootm ${kernel_addr_r} - ${fdt_addr_r}'")
160
+ exec_command_and_wait_for_pattern(self, cmd, '=>')
161
+
162
+ exec_command_and_wait_for_pattern(self, 'boot',
163
+ 'Booting kernel from Legacy Image')
164
+ wait_for_console_pattern(self, 'Starting kernel ...')
165
+ wait_for_console_pattern(self, 'NetBSD 9.0 (GENERIC)')
166
+ # Wait for user-space
167
+ wait_for_console_pattern(self, 'Starting root file system check')
168
+
169
def test_s390x_s390_ccw_virtio(self):
170
"""
171
:avocado: tags=arch:s390x
42
--
172
--
43
2.20.1
173
2.20.1
44
174
45
175
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
According to ARM ARM we should only trap from the EL1&0 regime.
3
The Xunlong Orange Pi PC machine is a functional ARM machine
4
4
based on the Allwinner H3 System-on-Chip. It supports mainline
5
Tested-by: Alex Bennée <alex.bennee@linaro.org>
5
Linux, U-Boot, NetBSD and is covered by acceptance tests.
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
7
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
7
This commit adds a documentation text file with a description
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
of the machine and instructions for the user.
9
Message-id: 20200206105448.4726-35-richard.henderson@linaro.org
9
10
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Message-id: 20200311221854.30370-19-nieklinnenbank@gmail.com
13
[PMM: moved file into docs/system/arm to match the reorg
14
of the arm target part of the docs; tweaked heading to
15
match other boards]
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
17
---
12
target/arm/pauth_helper.c | 5 ++++-
18
MAINTAINERS | 1 +
13
1 file changed, 4 insertions(+), 1 deletion(-)
19
docs/system/arm/orangepi.rst | 253 +++++++++++++++++++++++++++++++++++
14
20
docs/system/target-arm.rst | 2 +
15
diff --git a/target/arm/pauth_helper.c b/target/arm/pauth_helper.c
21
3 files changed, 256 insertions(+)
22
create mode 100644 docs/system/arm/orangepi.rst
23
24
diff --git a/MAINTAINERS b/MAINTAINERS
16
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/pauth_helper.c
26
--- a/MAINTAINERS
18
+++ b/target/arm/pauth_helper.c
27
+++ b/MAINTAINERS
19
@@ -XXX,XX +XXX,XX @@ static void pauth_check_trap(CPUARMState *env, int el, uintptr_t ra)
28
@@ -XXX,XX +XXX,XX @@ S: Maintained
20
if (el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
29
F: hw/*/allwinner-h3*
21
uint64_t hcr = arm_hcr_el2_eff(env);
30
F: include/hw/*/allwinner-h3*
22
bool trap = !(hcr & HCR_API);
31
F: hw/arm/orangepi.c
23
- /* FIXME: ARMv8.1-VHE: trap only applies to EL1&0 regime. */
32
+F: docs/system/orangepi.rst
24
+ if (el == 0) {
33
25
+ /* Trap only applies to EL1&0 regime. */
34
ARM PrimeCell and CMSDK devices
26
+ trap &= (hcr & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE);
35
M: Peter Maydell <peter.maydell@linaro.org>
27
+ }
36
diff --git a/docs/system/arm/orangepi.rst b/docs/system/arm/orangepi.rst
28
/* FIXME: ARMv8.3-NV: HCR_NV trap takes precedence for ERETA[AB]. */
37
new file mode 100644
29
if (trap) {
38
index XXXXXXX..XXXXXXX
30
pauth_trap(env, 2, ra);
39
--- /dev/null
40
+++ b/docs/system/arm/orangepi.rst
41
@@ -XXX,XX +XXX,XX @@
42
+Orange Pi PC (``orangepi-pc``)
43
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
44
+
45
+The Xunlong Orange Pi PC is an Allwinner H3 System on Chip
46
+based embedded computer with mainline support in both U-Boot
47
+and Linux. The board comes with a Quad Core Cortex-A7 @ 1.3GHz,
48
+1GiB RAM, 100Mbit ethernet, USB, SD/MMC, USB, HDMI and
49
+various other I/O.
50
+
51
+Supported devices
52
+"""""""""""""""""
53
+
54
+The Orange Pi PC machine supports the following devices:
55
+
56
+ * SMP (Quad Core Cortex-A7)
57
+ * Generic Interrupt Controller configuration
58
+ * SRAM mappings
59
+ * SDRAM controller
60
+ * Real Time Clock
61
+ * Timer device (re-used from Allwinner A10)
62
+ * UART
63
+ * SD/MMC storage controller
64
+ * EMAC ethernet
65
+ * USB 2.0 interfaces
66
+ * Clock Control Unit
67
+ * System Control module
68
+ * Security Identifier device
69
+
70
+Limitations
71
+"""""""""""
72
+
73
+Currently, Orange Pi PC does *not* support the following features:
74
+
75
+- Graphical output via HDMI, GPU and/or the Display Engine
76
+- Audio output
77
+- Hardware Watchdog
78
+
79
+Also see the 'unimplemented' array in the Allwinner H3 SoC module
80
+for a complete list of unimplemented I/O devices: ``./hw/arm/allwinner-h3.c``
81
+
82
+Boot options
83
+""""""""""""
84
+
85
+The Orange Pi PC machine can start using the standard -kernel functionality
86
+for loading a Linux kernel or ELF executable. Additionally, the Orange Pi PC
87
+machine can also emulate the BootROM which is present on an actual Allwinner H3
88
+based SoC, which loads the bootloader from a SD card, specified via the -sd argument
89
+to qemu-system-arm.
90
+
91
+Machine-specific options
92
+""""""""""""""""""""""""
93
+
94
+The following machine-specific options are supported:
95
+
96
+- allwinner-rtc.base-year=YYYY
97
+
98
+ The Allwinner RTC device is automatically created by the Orange Pi PC machine
99
+ and uses a default base year value which can be overridden using the 'base-year' property.
100
+ The base year is the actual represented year when the RTC year value is zero.
101
+ This option can be used in case the target operating system driver uses a different
102
+ base year value. The minimum value for the base year is 1900.
103
+
104
+- allwinner-sid.identifier=abcd1122-a000-b000-c000-12345678ffff
105
+
106
+ The Security Identifier value can be read by the guest.
107
+ For example, U-Boot uses it to determine a unique MAC address.
108
+
109
+The above machine-specific options can be specified in qemu-system-arm
110
+via the '-global' argument, for example:
111
+
112
+.. code-block:: bash
113
+
114
+ $ qemu-system-arm -M orangepi-pc -sd mycard.img \
115
+ -global allwinner-rtc.base-year=2000
116
+
117
+Running mainline Linux
118
+""""""""""""""""""""""
119
+
120
+Mainline Linux kernels from 4.19 up to latest master are known to work.
121
+To build a Linux mainline kernel that can be booted by the Orange Pi PC machine,
122
+simply configure the kernel using the sunxi_defconfig configuration:
123
+
124
+.. code-block:: bash
125
+
126
+ $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make mrproper
127
+ $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make sunxi_defconfig
128
+
129
+To be able to use USB storage, you need to manually enable the corresponding
130
+configuration item. Start the kconfig configuration tool:
131
+
132
+.. code-block:: bash
133
+
134
+ $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make menuconfig
135
+
136
+Navigate to the following item, enable it and save your configuration:
137
+
138
+ Device Drivers > USB support > USB Mass Storage support
139
+
140
+Build the Linux kernel with:
141
+
142
+.. code-block:: bash
143
+
144
+ $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make
145
+
146
+To boot the newly build linux kernel in QEMU with the Orange Pi PC machine, use:
147
+
148
+.. code-block:: bash
149
+
150
+ $ qemu-system-arm -M orangepi-pc -nic user -nographic \
151
+ -kernel /path/to/linux/arch/arm/boot/zImage \
152
+ -append 'console=ttyS0,115200' \
153
+ -dtb /path/to/linux/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dtb
154
+
155
+Orange Pi PC images
156
+"""""""""""""""""""
157
+
158
+Note that the mainline kernel does not have a root filesystem. You may provide it
159
+with an official Orange Pi PC image from the official website:
160
+
161
+ http://www.orangepi.org/downloadresources/
162
+
163
+Another possibility is to run an Armbian image for Orange Pi PC which
164
+can be downloaded from:
165
+
166
+ https://www.armbian.com/orange-pi-pc/
167
+
168
+Alternatively, you can also choose to build you own image with buildroot
169
+using the orangepi_pc_defconfig. Also see https://buildroot.org for more information.
170
+
171
+You can choose to attach the selected image either as an SD card or as USB mass storage.
172
+For example, to boot using the Orange Pi PC Debian image on SD card, simply add the -sd
173
+argument and provide the proper root= kernel parameter:
174
+
175
+.. code-block:: bash
176
+
177
+ $ qemu-system-arm -M orangepi-pc -nic user -nographic \
178
+ -kernel /path/to/linux/arch/arm/boot/zImage \
179
+ -append 'console=ttyS0,115200 root=/dev/mmcblk0p2' \
180
+ -dtb /path/to/linux/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dtb \
181
+ -sd OrangePi_pc_debian_stretch_server_linux5.3.5_v1.0.img
182
+
183
+To attach the image as an USB mass storage device to the machine,
184
+simply append to the command:
185
+
186
+.. code-block:: bash
187
+
188
+ -drive if=none,id=stick,file=myimage.img \
189
+ -device usb-storage,bus=usb-bus.0,drive=stick
190
+
191
+Instead of providing a custom Linux kernel via the -kernel command you may also
192
+choose to let the Orange Pi PC machine load the bootloader from SD card, just like
193
+a real board would do using the BootROM. Simply pass the selected image via the -sd
194
+argument and remove the -kernel, -append, -dbt and -initrd arguments:
195
+
196
+.. code-block:: bash
197
+
198
+ $ qemu-system-arm -M orangepi-pc -nic user -nographic \
199
+ -sd Armbian_19.11.3_Orangepipc_buster_current_5.3.9.img
200
+
201
+Note that both the official Orange Pi PC images and Armbian images start
202
+a lot of userland programs via systemd. Depending on the host hardware and OS,
203
+they may be slow to emulate, especially due to emulating the 4 cores.
204
+To help reduce the performance slow down due to emulating the 4 cores, you can
205
+give the following kernel parameters via U-Boot (or via -append):
206
+
207
+.. code-block:: bash
208
+
209
+ => setenv extraargs 'systemd.default_timeout_start_sec=9000 loglevel=7 nosmp console=ttyS0,115200'
210
+
211
+Running U-Boot
212
+""""""""""""""
213
+
214
+U-Boot mainline can be build and configured using the orangepi_pc_defconfig
215
+using similar commands as describe above for Linux. Note that it is recommended
216
+for development/testing to select the following configuration setting in U-Boot:
217
+
218
+ Device Tree Control > Provider for DTB for DT Control > Embedded DTB
219
+
220
+To start U-Boot using the Orange Pi PC machine, provide the
221
+u-boot binary to the -kernel argument:
222
+
223
+.. code-block:: bash
224
+
225
+ $ qemu-system-arm -M orangepi-pc -nic user -nographic \
226
+ -kernel /path/to/uboot/u-boot -sd disk.img
227
+
228
+Use the following U-boot commands to load and boot a Linux kernel from SD card:
229
+
230
+.. code-block:: bash
231
+
232
+ => setenv bootargs console=ttyS0,115200
233
+ => ext2load mmc 0 0x42000000 zImage
234
+ => ext2load mmc 0 0x43000000 sun8i-h3-orangepi-pc.dtb
235
+ => bootz 0x42000000 - 0x43000000
236
+
237
+Running NetBSD
238
+""""""""""""""
239
+
240
+The NetBSD operating system also includes support for Allwinner H3 based boards,
241
+including the Orange Pi PC. NetBSD 9.0 is known to work best for the Orange Pi PC
242
+board and provides a fully working system with serial console, networking and storage.
243
+For the Orange Pi PC machine, get the 'evbarm-earmv7hf' based image from:
244
+
245
+ https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.0/evbarm-earmv7hf/binary/gzimg/armv7.img.gz
246
+
247
+The image requires manually installing U-Boot in the image. Build U-Boot with
248
+the orangepi_pc_defconfig configuration as described in the previous section.
249
+Next, unzip the NetBSD image and write the U-Boot binary including SPL using:
250
+
251
+.. code-block:: bash
252
+
253
+ $ gunzip armv7.img.gz
254
+ $ dd if=/path/to/u-boot-sunxi-with-spl.bin of=armv7.img bs=1024 seek=8 conv=notrunc
255
+
256
+Finally, before starting the machine the SD image must be extended such
257
+that the NetBSD kernel will not conclude the NetBSD partition is larger than
258
+the emulated SD card:
259
+
260
+.. code-block:: bash
261
+
262
+ $ dd if=/dev/zero bs=1M count=64 >> armv7.img
263
+
264
+Start the machine using the following command:
265
+
266
+.. code-block:: bash
267
+
268
+ $ qemu-system-arm -M orangepi-pc -nic user -nographic \
269
+ -sd armv7.img -global allwinner-rtc.base-year=2000
270
+
271
+At the U-Boot stage, interrupt the automatic boot process by pressing a key
272
+and set the following environment variables before booting:
273
+
274
+.. code-block:: bash
275
+
276
+ => setenv bootargs root=ld0a
277
+ => setenv kernel netbsd-GENERIC.ub
278
+ => setenv fdtfile dtb/sun8i-h3-orangepi-pc.dtb
279
+ => setenv bootcmd 'fatload mmc 0:1 ${kernel_addr_r} ${kernel}; fatload mmc 0:1 ${fdt_addr_r} ${fdtfile}; fdt addr ${fdt_addr_r}; bootm ${kernel_addr_r} - ${fdt_addr_r}'
280
+
281
+Optionally you may save the environment variables to SD card with 'saveenv'.
282
+To continue booting simply give the 'boot' command and NetBSD boots.
283
+
284
+Orange Pi PC acceptance tests
285
+"""""""""""""""""""""""""""""
286
+
287
+The Orange Pi PC machine has several acceptance tests included.
288
+To run the whole set of tests, build QEMU from source and simply
289
+provide the following command:
290
+
291
+.. code-block:: bash
292
+
293
+ $ AVOCADO_ALLOW_LARGE_STORAGE=yes avocado --show=app,console run \
294
+ -t machine:orangepi-pc tests/acceptance/boot_linux_console.py
295
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
296
index XXXXXXX..XXXXXXX 100644
297
--- a/docs/system/target-arm.rst
298
+++ b/docs/system/target-arm.rst
299
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
300
``qemu-system-aarch64 --machine help``.
301
302
.. toctree::
303
+ :maxdepth: 1
304
305
arm/integratorcp
306
arm/versatile
307
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
308
arm/stellaris
309
arm/musicpal
310
arm/sx1
311
+ arm/orangepi
312
313
Arm CPU features
314
================
31
--
315
--
32
2.20.1
316
2.20.1
33
317
34
318
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
The TGE bit routes all asynchronous exceptions to EL2.
3
Mention 'max' value in the gic-version property description.
4
4
5
Tested-by: Alex Bennée <alex.bennee@linaro.org>
5
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Andrew Jones <drjones@redhat.com>
8
Message-id: 20200206105448.4726-33-richard.henderson@linaro.org
8
Message-id: 20200311131618.7187-2-eric.auger@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
target/arm/helper.c | 6 ++++++
11
hw/arm/virt.c | 3 ++-
12
1 file changed, 6 insertions(+)
12
1 file changed, 2 insertions(+), 1 deletion(-)
13
13
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
16
--- a/hw/arm/virt.c
17
+++ b/target/arm/helper.c
17
+++ b/hw/arm/virt.c
18
@@ -XXX,XX +XXX,XX @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
18
@@ -XXX,XX +XXX,XX @@ static void virt_instance_init(Object *obj)
19
break;
19
virt_set_gic_version, NULL);
20
};
20
object_property_set_description(obj, "gic-version",
21
21
"Set GIC version. "
22
+ /*
22
- "Valid values are 2, 3 and host", NULL);
23
+ * For these purposes, TGE and AMO/IMO/FMO both force the
23
+ "Valid values are 2, 3, host and max",
24
+ * interrupt to EL2. Fold TGE into the bit extracted above.
24
+ NULL);
25
+ */
25
26
+ hcr |= (hcr_el2 & HCR_TGE) != 0;
26
vms->highmem_ecam = !vmc->no_highmem_ecam;
27
+
28
/* Perform a table-lookup for the target EL given the current state */
29
target_el = target_el_table[is64][scr][rw][hcr][secure][cur_el];
30
27
31
--
28
--
32
2.20.1
29
2.20.1
33
30
34
31
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
We had completely run out of TBFLAG bits.
3
We plan to introduce yet another value for the gic version (nosel).
4
Split A- and M-profile bits into two overlapping buckets.
4
As we already use exotic values such as 0 and -1, let's introduce
5
This results in 4 free bits.
5
a dedicated enum type and let vms->gic_version take this
6
type.
6
7
7
We used to initialize all of the a32 and m32 fields in DisasContext
8
Signed-off-by: Eric Auger <eric.auger@redhat.com>
8
by assignment, in arm_tr_init_disas_context. Now we only initialize
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
either the a32 or m32 by assignment, because the bits overlap in
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
tbflags. So zero the entire structure in gen_intermediate_code.
11
Reviewed-by: Andrew Jones <drjones@redhat.com>
11
12
Message-id: 20200311131618.7187-3-eric.auger@redhat.com
12
Tested-by: Alex Bennée <alex.bennee@linaro.org>
13
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20200206105448.4726-16-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
14
---
18
target/arm/cpu.h | 68 ++++++++++++++++++++++++++----------------
15
include/hw/arm/virt.h | 11 +++++++++--
19
target/arm/helper.c | 17 +++++------
16
hw/arm/virt.c | 30 +++++++++++++++---------------
20
target/arm/translate.c | 57 +++++++++++++++++++----------------
17
2 files changed, 24 insertions(+), 17 deletions(-)
21
3 files changed, 82 insertions(+), 60 deletions(-)
22
18
23
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
19
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
24
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/cpu.h
21
--- a/include/hw/arm/virt.h
26
+++ b/target/arm/cpu.h
22
+++ b/include/hw/arm/virt.h
27
@@ -XXX,XX +XXX,XX @@ typedef ARMCPU ArchCPU;
23
@@ -XXX,XX +XXX,XX @@ typedef enum VirtIOMMUType {
28
* We put flags which are shared between 32 and 64 bit mode at the top
24
VIRT_IOMMU_VIRTIO,
29
* of the word, and flags which apply to only one mode at the bottom.
25
} VirtIOMMUType;
30
*
26
31
+ * 31 21 18 14 9 0
27
+typedef enum VirtGICType {
32
+ * +--------------+-----+-----+----------+--------------+
28
+ VIRT_GIC_VERSION_MAX,
33
+ * | | | TBFLAG_A32 | |
29
+ VIRT_GIC_VERSION_HOST,
34
+ * | | +-----+----------+ TBFLAG_AM32 |
30
+ VIRT_GIC_VERSION_2,
35
+ * | TBFLAG_ANY | |TBFLAG_M32| |
31
+ VIRT_GIC_VERSION_3,
36
+ * | | +-------------------------|
32
+} VirtGICType;
37
+ * | | | TBFLAG_A64 |
38
+ * +--------------+-----------+-------------------------+
39
+ * 31 21 14 0
40
+ *
41
* Unless otherwise noted, these bits are cached in env->hflags.
42
*/
43
FIELD(TBFLAG_ANY, AARCH64_STATE, 31, 1)
44
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_ANY, PSTATE_SS, 26, 1) /* Not cached. */
45
/* Target EL if we take a floating-point-disabled exception */
46
FIELD(TBFLAG_ANY, FPEXC_EL, 24, 2)
47
FIELD(TBFLAG_ANY, BE_DATA, 23, 1)
48
-/*
49
- * For A-profile only, target EL for debug exceptions.
50
- * Note that this overlaps with the M-profile-only HANDLER and STACKCHECK bits.
51
- */
52
+/* For A-profile only, target EL for debug exceptions. */
53
FIELD(TBFLAG_ANY, DEBUG_TARGET_EL, 21, 2)
54
55
-/* Bit usage when in AArch32 state: */
56
-FIELD(TBFLAG_A32, THUMB, 0, 1) /* Not cached. */
57
-FIELD(TBFLAG_A32, VECLEN, 1, 3) /* Not cached. */
58
-FIELD(TBFLAG_A32, VECSTRIDE, 4, 2) /* Not cached. */
59
+/*
60
+ * Bit usage when in AArch32 state, both A- and M-profile.
61
+ */
62
+FIELD(TBFLAG_AM32, CONDEXEC, 0, 8) /* Not cached. */
63
+FIELD(TBFLAG_AM32, THUMB, 8, 1) /* Not cached. */
64
+
33
+
65
+/*
34
typedef struct MemMapEntry {
66
+ * Bit usage when in AArch32 state, for A-profile only.
35
hwaddr base;
67
+ */
36
hwaddr size;
68
+FIELD(TBFLAG_A32, VECLEN, 9, 3) /* Not cached. */
37
@@ -XXX,XX +XXX,XX @@ typedef struct {
69
+FIELD(TBFLAG_A32, VECSTRIDE, 12, 2) /* Not cached. */
38
bool highmem_ecam;
70
/*
39
bool its;
71
* We store the bottom two bits of the CPAR as TB flags and handle
40
bool virt;
72
* checks on the other bits at runtime. This shares the same bits as
41
- int32_t gic_version;
73
* VECSTRIDE, which is OK as no XScale CPU has VFP.
42
+ VirtGICType gic_version;
74
* Not cached, because VECLEN+VECSTRIDE are not cached.
43
VirtIOMMUType iommu;
75
*/
44
uint16_t virtio_iommu_bdf;
76
-FIELD(TBFLAG_A32, XSCALE_CPAR, 4, 2)
45
struct arm_boot_info bootinfo;
77
+FIELD(TBFLAG_A32, XSCALE_CPAR, 12, 2)
46
@@ -XXX,XX +XXX,XX @@ static inline int virt_gicv3_redist_region_count(VirtMachineState *vms)
78
+FIELD(TBFLAG_A32, VFPEN, 14, 1) /* Partially cached, minus FPEXC. */
47
uint32_t redist0_capacity =
79
+FIELD(TBFLAG_A32, SCTLR_B, 15, 1)
48
vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
80
+FIELD(TBFLAG_A32, HSTR_ACTIVE, 16, 1)
49
81
/*
50
- assert(vms->gic_version == 3);
82
* Indicates whether cp register reads and writes by guest code should access
51
+ assert(vms->gic_version == VIRT_GIC_VERSION_3);
83
* the secure or nonsecure bank of banked registers; note that this is not
52
84
* the same thing as the current security state of the processor!
53
return vms->smp_cpus > redist0_capacity ? 2 : 1;
85
*/
54
}
86
-FIELD(TBFLAG_A32, NS, 6, 1)
55
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
87
-FIELD(TBFLAG_A32, VFPEN, 7, 1) /* Partially cached, minus FPEXC. */
88
-FIELD(TBFLAG_A32, CONDEXEC, 8, 8) /* Not cached. */
89
-FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
90
-FIELD(TBFLAG_A32, HSTR_ACTIVE, 17, 1)
91
+FIELD(TBFLAG_A32, NS, 17, 1)
92
93
-/* For M profile only, set if FPCCR.LSPACT is set */
94
-FIELD(TBFLAG_A32, LSPACT, 18, 1) /* Not cached. */
95
-/* For M profile only, set if we must create a new FP context */
96
-FIELD(TBFLAG_A32, NEW_FP_CTXT_NEEDED, 19, 1) /* Not cached. */
97
-/* For M profile only, set if FPCCR.S does not match current security state */
98
-FIELD(TBFLAG_A32, FPCCR_S_WRONG, 20, 1) /* Not cached. */
99
-/* For M profile only, Handler (ie not Thread) mode */
100
-FIELD(TBFLAG_A32, HANDLER, 21, 1)
101
-/* For M profile only, whether we should generate stack-limit checks */
102
-FIELD(TBFLAG_A32, STACKCHECK, 22, 1)
103
+/*
104
+ * Bit usage when in AArch32 state, for M-profile only.
105
+ */
106
+/* Handler (ie not Thread) mode */
107
+FIELD(TBFLAG_M32, HANDLER, 9, 1)
108
+/* Whether we should generate stack-limit checks */
109
+FIELD(TBFLAG_M32, STACKCHECK, 10, 1)
110
+/* Set if FPCCR.LSPACT is set */
111
+FIELD(TBFLAG_M32, LSPACT, 11, 1) /* Not cached. */
112
+/* Set if we must create a new FP context */
113
+FIELD(TBFLAG_M32, NEW_FP_CTXT_NEEDED, 12, 1) /* Not cached. */
114
+/* Set if FPCCR.S does not match current security state */
115
+FIELD(TBFLAG_M32, FPCCR_S_WRONG, 13, 1) /* Not cached. */
116
117
-/* Bit usage when in AArch64 state */
118
+/*
119
+ * Bit usage when in AArch64 state
120
+ */
121
FIELD(TBFLAG_A64, TBII, 0, 2)
122
FIELD(TBFLAG_A64, SVEEXC_EL, 2, 2)
123
FIELD(TBFLAG_A64, ZCR_LEN, 4, 4)
124
diff --git a/target/arm/helper.c b/target/arm/helper.c
125
index XXXXXXX..XXXXXXX 100644
56
index XXXXXXX..XXXXXXX 100644
126
--- a/target/arm/helper.c
57
--- a/hw/arm/virt.c
127
+++ b/target/arm/helper.c
58
+++ b/hw/arm/virt.c
128
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_m32(CPUARMState *env, int fp_el,
59
@@ -XXX,XX +XXX,XX @@ static void fdt_add_timer_nodes(const VirtMachineState *vms)
129
{
60
irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI;
130
uint32_t flags = 0;
131
132
- /* v8M always enables the fpu. */
133
- flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
134
-
135
if (arm_v7m_is_handler_mode(env)) {
136
- flags = FIELD_DP32(flags, TBFLAG_A32, HANDLER, 1);
137
+ flags = FIELD_DP32(flags, TBFLAG_M32, HANDLER, 1);
138
}
61
}
139
62
140
/*
63
- if (vms->gic_version == 2) {
141
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_m32(CPUARMState *env, int fp_el,
64
+ if (vms->gic_version == VIRT_GIC_VERSION_2) {
142
if (arm_feature(env, ARM_FEATURE_V8) &&
65
irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
143
!((mmu_idx & ARM_MMU_IDX_M_NEGPRI) &&
66
GIC_FDT_IRQ_PPI_CPU_WIDTH,
144
(env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_STKOFHFNMIGN_MASK))) {
67
(1 << vms->smp_cpus) - 1);
145
- flags = FIELD_DP32(flags, TBFLAG_A32, STACKCHECK, 1);
68
@@ -XXX,XX +XXX,XX @@ static void fdt_add_gic_node(VirtMachineState *vms)
146
+ flags = FIELD_DP32(flags, TBFLAG_M32, STACKCHECK, 1);
69
qemu_fdt_setprop_cell(vms->fdt, nodename, "#address-cells", 0x2);
70
qemu_fdt_setprop_cell(vms->fdt, nodename, "#size-cells", 0x2);
71
qemu_fdt_setprop(vms->fdt, nodename, "ranges", NULL, 0);
72
- if (vms->gic_version == 3) {
73
+ if (vms->gic_version == VIRT_GIC_VERSION_3) {
74
int nb_redist_regions = virt_gicv3_redist_region_count(vms);
75
76
qemu_fdt_setprop_string(vms->fdt, nodename, "compatible",
77
@@ -XXX,XX +XXX,XX @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms)
78
}
147
}
79
}
148
80
149
return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
81
- if (vms->gic_version == 2) {
150
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
82
+ if (vms->gic_version == VIRT_GIC_VERSION_2) {
151
if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
83
irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
152
FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S)
84
GIC_FDT_IRQ_PPI_CPU_WIDTH,
153
!= env->v7m.secure) {
85
(1 << vms->smp_cpus) - 1);
154
- flags = FIELD_DP32(flags, TBFLAG_A32, FPCCR_S_WRONG, 1);
86
@@ -XXX,XX +XXX,XX @@ static uint64_t virt_cpu_mp_affinity(VirtMachineState *vms, int idx)
155
+ flags = FIELD_DP32(flags, TBFLAG_M32, FPCCR_S_WRONG, 1);
87
* purposes are to make TCG consistent (with 64-bit KVM hosts)
156
}
88
* and to improve SGI efficiency.
157
89
*/
158
if ((env->v7m.fpccr[env->v7m.secure] & R_V7M_FPCCR_ASPEN_MASK) &&
90
- if (vms->gic_version == 3) {
159
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
91
+ if (vms->gic_version == VIRT_GIC_VERSION_3) {
160
* active FP context; we must create a new FP context before
92
clustersz = GICV3_TARGETLIST_BITS;
161
* executing any FP insn.
93
} else {
162
*/
94
clustersz = GIC_TARGETLIST_BITS;
163
- flags = FIELD_DP32(flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED, 1);
95
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
164
+ flags = FIELD_DP32(flags, TBFLAG_M32, NEW_FP_CTXT_NEEDED, 1);
96
/* We can probe only here because during property set
165
}
97
* KVM is not available yet
166
98
*/
167
bool is_secure = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK;
99
- if (vms->gic_version <= 0) {
168
if (env->v7m.fpccr[is_secure] & R_V7M_FPCCR_LSPACT_MASK) {
100
- /* "host" or "max" */
169
- flags = FIELD_DP32(flags, TBFLAG_A32, LSPACT, 1);
101
+ if (vms->gic_version == VIRT_GIC_VERSION_HOST ||
170
+ flags = FIELD_DP32(flags, TBFLAG_M32, LSPACT, 1);
102
+ vms->gic_version == VIRT_GIC_VERSION_MAX) {
103
if (!kvm_enabled()) {
104
- if (vms->gic_version == 0) {
105
+ if (vms->gic_version == VIRT_GIC_VERSION_HOST) {
106
error_report("gic-version=host requires KVM");
107
exit(1);
108
} else {
109
/* "max": currently means 3 for TCG */
110
- vms->gic_version = 3;
111
+ vms->gic_version = VIRT_GIC_VERSION_3;
171
}
112
}
172
} else {
113
} else {
173
/*
114
vms->gic_version = kvm_arm_vgic_probe();
174
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
115
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
175
}
116
/* The maximum number of CPUs depends on the GIC version, or on how
176
}
117
* many redistributors we can fit into the memory map.
177
178
- flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb);
179
- flags = FIELD_DP32(flags, TBFLAG_A32, CONDEXEC, env->condexec_bits);
180
+ flags = FIELD_DP32(flags, TBFLAG_AM32, THUMB, env->thumb);
181
+ flags = FIELD_DP32(flags, TBFLAG_AM32, CONDEXEC, env->condexec_bits);
182
pstate_for_ss = env->uncached_cpsr;
183
}
184
185
diff --git a/target/arm/translate.c b/target/arm/translate.c
186
index XXXXXXX..XXXXXXX 100644
187
--- a/target/arm/translate.c
188
+++ b/target/arm/translate.c
189
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
190
*/
118
*/
191
dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
119
- if (vms->gic_version == 3) {
192
!arm_el_is_aa64(env, 3);
120
+ if (vms->gic_version == VIRT_GIC_VERSION_3) {
193
- dc->thumb = FIELD_EX32(tb_flags, TBFLAG_A32, THUMB);
121
virt_max_cpus =
194
- dc->sctlr_b = FIELD_EX32(tb_flags, TBFLAG_A32, SCTLR_B);
122
vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
195
- dc->hstr_active = FIELD_EX32(tb_flags, TBFLAG_A32, HSTR_ACTIVE);
123
virt_max_cpus +=
196
+ dc->thumb = FIELD_EX32(tb_flags, TBFLAG_AM32, THUMB);
124
@@ -XXX,XX +XXX,XX @@ static void virt_set_its(Object *obj, bool value, Error **errp)
197
dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
125
static char *virt_get_gic_version(Object *obj, Error **errp)
198
- condexec = FIELD_EX32(tb_flags, TBFLAG_A32, CONDEXEC);
126
{
199
+ condexec = FIELD_EX32(tb_flags, TBFLAG_AM32, CONDEXEC);
127
VirtMachineState *vms = VIRT_MACHINE(obj);
200
dc->condexec_mask = (condexec & 0xf) << 1;
128
- const char *val = vms->gic_version == 3 ? "3" : "2";
201
dc->condexec_cond = condexec >> 4;
129
+ const char *val = vms->gic_version == VIRT_GIC_VERSION_3 ? "3" : "2";
202
+
130
203
core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
131
return g_strdup(val);
204
dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
132
}
205
dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
133
@@ -XXX,XX +XXX,XX @@ static void virt_set_gic_version(Object *obj, const char *value, Error **errp)
206
#if !defined(CONFIG_USER_ONLY)
134
VirtMachineState *vms = VIRT_MACHINE(obj);
207
dc->user = (dc->current_el == 0);
135
208
#endif
136
if (!strcmp(value, "3")) {
209
- dc->ns = FIELD_EX32(tb_flags, TBFLAG_A32, NS);
137
- vms->gic_version = 3;
210
dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
138
+ vms->gic_version = VIRT_GIC_VERSION_3;
211
- dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
139
} else if (!strcmp(value, "2")) {
212
- dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
140
- vms->gic_version = 2;
213
- if (arm_feature(env, ARM_FEATURE_XSCALE)) {
141
+ vms->gic_version = VIRT_GIC_VERSION_2;
214
- dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
142
} else if (!strcmp(value, "host")) {
215
- dc->vec_stride = 0;
143
- vms->gic_version = 0; /* Will probe later */
216
+
144
+ vms->gic_version = VIRT_GIC_VERSION_HOST; /* Will probe later */
217
+ if (arm_feature(env, ARM_FEATURE_M)) {
145
} else if (!strcmp(value, "max")) {
218
+ dc->vfp_enabled = 1;
146
- vms->gic_version = -1; /* Will probe later */
219
+ dc->be_data = MO_TE;
147
+ vms->gic_version = VIRT_GIC_VERSION_MAX; /* Will probe later */
220
+ dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_M32, HANDLER);
221
+ dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
222
+ regime_is_secure(env, dc->mmu_idx);
223
+ dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_M32, STACKCHECK);
224
+ dc->v8m_fpccr_s_wrong =
225
+ FIELD_EX32(tb_flags, TBFLAG_M32, FPCCR_S_WRONG);
226
+ dc->v7m_new_fp_ctxt_needed =
227
+ FIELD_EX32(tb_flags, TBFLAG_M32, NEW_FP_CTXT_NEEDED);
228
+ dc->v7m_lspact = FIELD_EX32(tb_flags, TBFLAG_M32, LSPACT);
229
} else {
148
} else {
230
- dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
149
error_setg(errp, "Invalid gic-version value");
231
- dc->c15_cpar = 0;
150
error_append_hint(errp, "Valid values are 3, 2, host, max.\n");
232
+ dc->be_data =
151
@@ -XXX,XX +XXX,XX @@ static void virt_instance_init(Object *obj)
233
+ FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
152
"physical address space above 32 bits",
234
+ dc->debug_target_el =
153
NULL);
235
+ FIELD_EX32(tb_flags, TBFLAG_ANY, DEBUG_TARGET_EL);
154
/* Default GIC type is v2 */
236
+ dc->sctlr_b = FIELD_EX32(tb_flags, TBFLAG_A32, SCTLR_B);
155
- vms->gic_version = 2;
237
+ dc->hstr_active = FIELD_EX32(tb_flags, TBFLAG_A32, HSTR_ACTIVE);
156
+ vms->gic_version = VIRT_GIC_VERSION_2;
238
+ dc->ns = FIELD_EX32(tb_flags, TBFLAG_A32, NS);
157
object_property_add_str(obj, "gic-version", virt_get_gic_version,
239
+ dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
158
virt_set_gic_version, NULL);
240
+ if (arm_feature(env, ARM_FEATURE_XSCALE)) {
159
object_property_set_description(obj, "gic-version",
241
+ dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
242
+ } else {
243
+ dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
244
+ dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
245
+ }
246
}
247
- dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_A32, HANDLER);
248
- dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
249
- regime_is_secure(env, dc->mmu_idx);
250
- dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_A32, STACKCHECK);
251
- dc->v8m_fpccr_s_wrong = FIELD_EX32(tb_flags, TBFLAG_A32, FPCCR_S_WRONG);
252
- dc->v7m_new_fp_ctxt_needed =
253
- FIELD_EX32(tb_flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED);
254
- dc->v7m_lspact = FIELD_EX32(tb_flags, TBFLAG_A32, LSPACT);
255
dc->cp_regs = cpu->cp_regs;
256
dc->features = env->features;
257
258
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
259
dc->ss_active = FIELD_EX32(tb_flags, TBFLAG_ANY, SS_ACTIVE);
260
dc->pstate_ss = FIELD_EX32(tb_flags, TBFLAG_ANY, PSTATE_SS);
261
dc->is_ldex = false;
262
- if (!arm_feature(env, ARM_FEATURE_M)) {
263
- dc->debug_target_el = FIELD_EX32(tb_flags, TBFLAG_ANY, DEBUG_TARGET_EL);
264
- }
265
266
dc->page_start = dc->base.pc_first & TARGET_PAGE_MASK;
267
268
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps thumb_translator_ops = {
269
/* generate intermediate code for basic block 'tb'. */
270
void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
271
{
272
- DisasContext dc;
273
+ DisasContext dc = { };
274
const TranslatorOps *ops = &arm_translator_ops;
275
276
- if (FIELD_EX32(tb->flags, TBFLAG_A32, THUMB)) {
277
+ if (FIELD_EX32(tb->flags, TBFLAG_AM32, THUMB)) {
278
ops = &thumb_translator_ops;
279
}
280
#ifdef TARGET_AARCH64
281
--
160
--
282
2.20.1
161
2.20.1
283
162
284
163
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
Tested-by: Alex Bennée <alex.bennee@linaro.org>
3
Let's move the code which freezes which gic-version to
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
be applied in a dedicated function. We also now set by
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
default the VIRT_GIC_VERSION_NO_SET. This eventually
6
Message-id: 20200206105448.4726-32-richard.henderson@linaro.org
6
turns into the legacy v2 choice in the finalize() function.
7
8
Signed-off-by: Eric Auger <eric.auger@redhat.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Andrew Jones <drjones@redhat.com>
11
Message-id: 20200311131618.7187-4-eric.auger@redhat.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
13
---
9
target/arm/helper.c | 25 ++++++++++++++++++-------
14
include/hw/arm/virt.h | 1 +
10
1 file changed, 18 insertions(+), 7 deletions(-)
15
hw/arm/virt.c | 54 ++++++++++++++++++++++++++-----------------
16
2 files changed, 34 insertions(+), 21 deletions(-)
11
17
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
13
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/helper.c
20
--- a/include/hw/arm/virt.h
15
+++ b/target/arm/helper.c
21
+++ b/include/hw/arm/virt.h
16
@@ -XXX,XX +XXX,XX @@ static CPAccessResult aa64_cacheop_access(CPUARMState *env,
22
@@ -XXX,XX +XXX,XX @@ typedef enum VirtGICType {
17
23
VIRT_GIC_VERSION_HOST,
18
static int vae1_tlbmask(CPUARMState *env)
24
VIRT_GIC_VERSION_2,
19
{
25
VIRT_GIC_VERSION_3,
20
+ /* Since we exclude secure first, we may read HCR_EL2 directly. */
26
+ VIRT_GIC_VERSION_NOSEL,
21
if (arm_is_secure_below_el3(env)) {
27
} VirtGICType;
22
return ARMMMUIdxBit_SE10_1 | ARMMMUIdxBit_SE10_0;
28
23
+ } else if ((env->cp15.hcr_el2 & (HCR_E2H | HCR_TGE))
29
typedef struct MemMapEntry {
24
+ == (HCR_E2H | HCR_TGE)) {
30
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
25
+ return ARMMMUIdxBit_E20_2 | ARMMMUIdxBit_E20_0;
31
index XXXXXXX..XXXXXXX 100644
26
} else {
32
--- a/hw/arm/virt.c
27
return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0;
33
+++ b/hw/arm/virt.c
28
}
34
@@ -XXX,XX +XXX,XX @@ static void virt_set_memmap(VirtMachineState *vms)
29
@@ -XXX,XX +XXX,XX @@ static int alle1_tlbmask(CPUARMState *env)
30
}
35
}
31
}
36
}
32
37
33
+static int e2_tlbmask(CPUARMState *env)
38
+/*
39
+ * finalize_gic_version - Determines the final gic_version
40
+ * according to the gic-version property
41
+ *
42
+ * Default GIC type is v2
43
+ */
44
+static void finalize_gic_version(VirtMachineState *vms)
34
+{
45
+{
35
+ /* TODO: ARMv8.4-SecEL2 */
46
+ if (vms->gic_version == VIRT_GIC_VERSION_HOST ||
36
+ return ARMMMUIdxBit_E20_0 | ARMMMUIdxBit_E20_2 | ARMMMUIdxBit_E2;
47
+ vms->gic_version == VIRT_GIC_VERSION_MAX) {
48
+ if (!kvm_enabled()) {
49
+ if (vms->gic_version == VIRT_GIC_VERSION_HOST) {
50
+ error_report("gic-version=host requires KVM");
51
+ exit(1);
52
+ } else {
53
+ /* "max": currently means 3 for TCG */
54
+ vms->gic_version = VIRT_GIC_VERSION_3;
55
+ }
56
+ } else {
57
+ vms->gic_version = kvm_arm_vgic_probe();
58
+ if (!vms->gic_version) {
59
+ error_report(
60
+ "Unable to determine GIC version supported by host");
61
+ exit(1);
62
+ }
63
+ }
64
+ } else if (vms->gic_version == VIRT_GIC_VERSION_NOSEL) {
65
+ vms->gic_version = VIRT_GIC_VERSION_2;
66
+ }
37
+}
67
+}
38
+
68
+
39
static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
69
static void machvirt_init(MachineState *machine)
40
uint64_t value)
41
{
70
{
42
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
71
VirtMachineState *vms = VIRT_MACHINE(machine);
43
static void tlbi_aa64_alle2_write(CPUARMState *env, const ARMCPRegInfo *ri,
72
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
44
uint64_t value)
73
/* We can probe only here because during property set
45
{
74
* KVM is not available yet
46
- ARMCPU *cpu = env_archcpu(env);
47
- CPUState *cs = CPU(cpu);
48
+ CPUState *cs = env_cpu(env);
49
+ int mask = e2_tlbmask(env);
50
51
- tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E2);
52
+ tlb_flush_by_mmuidx(cs, mask);
53
}
54
55
static void tlbi_aa64_alle3_write(CPUARMState *env, const ARMCPRegInfo *ri,
56
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_alle2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
57
uint64_t value)
58
{
59
CPUState *cs = env_cpu(env);
60
+ int mask = e2_tlbmask(env);
61
62
- tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_E2);
63
+ tlb_flush_by_mmuidx_all_cpus_synced(cs, mask);
64
}
65
66
static void tlbi_aa64_alle3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
67
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae2_write(CPUARMState *env, const ARMCPRegInfo *ri,
68
* Currently handles both VAE2 and VALE2, since we don't support
69
* flush-last-level-only.
70
*/
75
*/
71
- ARMCPU *cpu = env_archcpu(env);
76
- if (vms->gic_version == VIRT_GIC_VERSION_HOST ||
72
- CPUState *cs = CPU(cpu);
77
- vms->gic_version == VIRT_GIC_VERSION_MAX) {
73
+ CPUState *cs = env_cpu(env);
78
- if (!kvm_enabled()) {
74
+ int mask = e2_tlbmask(env);
79
- if (vms->gic_version == VIRT_GIC_VERSION_HOST) {
75
uint64_t pageaddr = sextract64(value << 12, 0, 56);
80
- error_report("gic-version=host requires KVM");
76
81
- exit(1);
77
- tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E2);
82
- } else {
78
+ tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
83
- /* "max": currently means 3 for TCG */
79
}
84
- vms->gic_version = VIRT_GIC_VERSION_3;
80
85
- }
81
static void tlbi_aa64_vae3_write(CPUARMState *env, const ARMCPRegInfo *ri,
86
- } else {
87
- vms->gic_version = kvm_arm_vgic_probe();
88
- if (!vms->gic_version) {
89
- error_report(
90
- "Unable to determine GIC version supported by host");
91
- exit(1);
92
- }
93
- }
94
- }
95
+ finalize_gic_version(vms);
96
97
if (!cpu_type_valid(machine->cpu_type)) {
98
error_report("mach-virt: CPU type %s not supported", machine->cpu_type);
99
@@ -XXX,XX +XXX,XX @@ static void virt_instance_init(Object *obj)
100
"Set on/off to enable/disable using "
101
"physical address space above 32 bits",
102
NULL);
103
- /* Default GIC type is v2 */
104
- vms->gic_version = VIRT_GIC_VERSION_2;
105
+ vms->gic_version = VIRT_GIC_VERSION_NOSEL;
106
object_property_add_str(obj, "gic-version", virt_get_gic_version,
107
virt_set_gic_version, NULL);
108
object_property_set_description(obj, "gic-version",
82
--
109
--
83
2.20.1
110
2.20.1
84
111
85
112
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
The value computed is fully boolean; using int8_t is odd.
3
Convert kvm_arm_vgic_probe() so that it returns a
4
bitmap of supported in-kernel emulation VGIC versions instead
5
of the max version: at the moment values can be v2 and v3.
6
This allows to expose the case where the host GICv3 also
7
supports GICv2 emulation. This will be useful to choose the
8
default version in KVM accelerated mode.
4
9
5
Tested-by: Alex Bennée <alex.bennee@linaro.org>
10
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Reviewed-by: Andrew Jones <drjones@redhat.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200206105448.4726-41-richard.henderson@linaro.org
13
Message-id: 20200311131618.7187-5-eric.auger@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
15
---
11
target/arm/cpu.c | 6 +++---
16
target/arm/kvm_arm.h | 3 +++
12
1 file changed, 3 insertions(+), 3 deletions(-)
17
hw/arm/virt.c | 11 +++++++++--
18
target/arm/kvm.c | 14 ++++++++------
19
3 files changed, 20 insertions(+), 8 deletions(-)
13
20
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
21
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
15
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.c
23
--- a/target/arm/kvm_arm.h
17
+++ b/target/arm/cpu.c
24
+++ b/target/arm/kvm_arm.h
18
@@ -XXX,XX +XXX,XX @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
25
@@ -XXX,XX +XXX,XX @@
19
{
26
#include "exec/memory.h"
20
CPUARMState *env = cs->env_ptr;
27
#include "qemu/error-report.h"
21
bool pstate_unmasked;
28
22
- int8_t unmasked = 0;
29
+#define KVM_ARM_VGIC_V2 (1 << 0)
23
+ bool unmasked = false;
30
+#define KVM_ARM_VGIC_V3 (1 << 1)
24
31
+
25
/*
32
/**
26
* Don't take exceptions if they target a lower EL.
33
* kvm_arm_vcpu_init:
27
@@ -XXX,XX +XXX,XX @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
34
* @cs: CPUState
28
* don't affect the masking logic, only the interrupt routing.
35
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
29
*/
36
index XXXXXXX..XXXXXXX 100644
30
if (target_el == 3 || !secure) {
37
--- a/hw/arm/virt.c
31
- unmasked = 1;
38
+++ b/hw/arm/virt.c
32
+ unmasked = true;
39
@@ -XXX,XX +XXX,XX @@ static void finalize_gic_version(VirtMachineState *vms)
40
vms->gic_version = VIRT_GIC_VERSION_3;
33
}
41
}
34
} else {
42
} else {
35
/*
43
- vms->gic_version = kvm_arm_vgic_probe();
36
@@ -XXX,XX +XXX,XX @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
44
- if (!vms->gic_version) {
37
}
45
+ int probe_bitmap = kvm_arm_vgic_probe();
38
46
+
39
if ((scr || hcr) && !secure) {
47
+ if (!probe_bitmap) {
40
- unmasked = 1;
48
error_report(
41
+ unmasked = true;
49
"Unable to determine GIC version supported by host");
50
exit(1);
51
+ } else {
52
+ if (probe_bitmap & KVM_ARM_VGIC_V3) {
53
+ vms->gic_version = VIRT_GIC_VERSION_3;
54
+ } else {
55
+ vms->gic_version = VIRT_GIC_VERSION_2;
56
+ }
42
}
57
}
43
}
58
}
59
} else if (vms->gic_version == VIRT_GIC_VERSION_NOSEL) {
60
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/kvm.c
63
+++ b/target/arm/kvm.c
64
@@ -XXX,XX +XXX,XX @@ int kvm_arch_irqchip_create(KVMState *s)
65
66
int kvm_arm_vgic_probe(void)
67
{
68
+ int val = 0;
69
+
70
if (kvm_create_device(kvm_state,
71
KVM_DEV_TYPE_ARM_VGIC_V3, true) == 0) {
72
- return 3;
73
- } else if (kvm_create_device(kvm_state,
74
- KVM_DEV_TYPE_ARM_VGIC_V2, true) == 0) {
75
- return 2;
76
- } else {
77
- return 0;
78
+ val |= KVM_ARM_VGIC_V3;
44
}
79
}
80
+ if (kvm_create_device(kvm_state,
81
+ KVM_DEV_TYPE_ARM_VGIC_V2, true) == 0) {
82
+ val |= KVM_ARM_VGIC_V2;
83
+ }
84
+ return val;
85
}
86
87
int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level)
45
--
88
--
46
2.20.1
89
2.20.1
47
90
48
91
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
Several of the EL1/0 registers are redirected to the EL2 version when in
3
Restructure the finalize_gic_version with switch cases and
4
EL2 and HCR_EL2.E2H is set. Many of these registers have side effects.
4
clearly separate the following cases:
5
Link together the two ARMCPRegInfo structures after they have been
6
properly instantiated. Install common dispatch routines to all of the
7
relevant registers.
8
5
9
The same set of registers that are redirected also have additional
6
- KVM mode / in-kernel irqchip
10
EL12/EL02 aliases created to access the original register that was
7
- KVM mode / userspace irqchip
11
redirected.
8
- TCG mode
12
9
13
Omit the generic timer registers from redirection here, because we'll
10
In KVM mode / in-kernel irqchip , we explictly check whether
14
need multiple kinds of redirection from both EL0 and EL2.
11
the chosen version is supported by the host. If the end-user
12
explicitly sets v2/v3 and this is not supported by the host,
13
then the user gets an explicit error message. Note that for
14
old kernels where the CREATE_DEVICE ioctl doesn't exist then
15
we will now fail if the user specifically asked for gicv2,
16
where previously we (probably) would have succeeded.
15
17
16
Tested-by: Alex Bennée <alex.bennee@linaro.org>
18
In KVM mode / userspace irqchip we immediatly output an error
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
in case the end-user explicitly selected v3. Also we warn the
18
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
20
end-user about the unexpected usage of gic-version=host in
19
Message-id: 20200206105448.4726-29-richard.henderson@linaro.org
21
that case as only userspace GICv2 is supported.
22
23
Signed-off-by: Eric Auger <eric.auger@redhat.com>
24
Reviewed-by: Andrew Jones <drjones@redhat.com>
25
Message-id: 20200311131618.7187-6-eric.auger@redhat.com
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
27
---
22
target/arm/cpu.h | 13 ++++
28
hw/arm/virt.c | 88 +++++++++++++++++++++++++++++++++++++++------------
23
target/arm/helper.c | 162 ++++++++++++++++++++++++++++++++++++++++++++
29
1 file changed, 67 insertions(+), 21 deletions(-)
24
2 files changed, 175 insertions(+)
25
30
26
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
31
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
27
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu.h
33
--- a/hw/arm/virt.c
29
+++ b/target/arm/cpu.h
34
+++ b/hw/arm/virt.c
30
@@ -XXX,XX +XXX,XX @@ struct ARMCPRegInfo {
35
@@ -XXX,XX +XXX,XX @@ static void virt_set_memmap(VirtMachineState *vms)
31
* fieldoffset is 0 then no reset will be done.
36
*/
32
*/
37
static void finalize_gic_version(VirtMachineState *vms)
33
CPResetFn *resetfn;
38
{
39
- if (vms->gic_version == VIRT_GIC_VERSION_HOST ||
40
- vms->gic_version == VIRT_GIC_VERSION_MAX) {
41
- if (!kvm_enabled()) {
42
- if (vms->gic_version == VIRT_GIC_VERSION_HOST) {
43
- error_report("gic-version=host requires KVM");
44
- exit(1);
45
- } else {
46
- /* "max": currently means 3 for TCG */
47
- vms->gic_version = VIRT_GIC_VERSION_3;
48
- }
49
- } else {
50
- int probe_bitmap = kvm_arm_vgic_probe();
51
+ if (kvm_enabled()) {
52
+ int probe_bitmap;
53
54
- if (!probe_bitmap) {
55
+ if (!kvm_irqchip_in_kernel()) {
56
+ switch (vms->gic_version) {
57
+ case VIRT_GIC_VERSION_HOST:
58
+ warn_report(
59
+ "gic-version=host not relevant with kernel-irqchip=off "
60
+ "as only userspace GICv2 is supported. Using v2 ...");
61
+ return;
62
+ case VIRT_GIC_VERSION_MAX:
63
+ case VIRT_GIC_VERSION_NOSEL:
64
+ vms->gic_version = VIRT_GIC_VERSION_2;
65
+ return;
66
+ case VIRT_GIC_VERSION_2:
67
+ return;
68
+ case VIRT_GIC_VERSION_3:
69
error_report(
70
- "Unable to determine GIC version supported by host");
71
+ "gic-version=3 is not supported with kernel-irqchip=off");
72
exit(1);
73
- } else {
74
- if (probe_bitmap & KVM_ARM_VGIC_V3) {
75
- vms->gic_version = VIRT_GIC_VERSION_3;
76
- } else {
77
- vms->gic_version = VIRT_GIC_VERSION_2;
78
- }
79
}
80
}
81
- } else if (vms->gic_version == VIRT_GIC_VERSION_NOSEL) {
34
+
82
+
35
+ /*
83
+ probe_bitmap = kvm_arm_vgic_probe();
36
+ * "Original" writefn and readfn.
84
+ if (!probe_bitmap) {
37
+ * For ARMv8.1-VHE register aliases, we overwrite the read/write
85
+ error_report("Unable to determine GIC version supported by host");
38
+ * accessor functions of various EL1/EL0 to perform the runtime
86
+ exit(1);
39
+ * check for which sysreg should actually be modified, and then
40
+ * forwards the operation. Before overwriting the accessors,
41
+ * the original function is copied here, so that accesses that
42
+ * really do go to the EL1/EL0 version proceed normally.
43
+ * (The corresponding EL2 register is linked via opaque.)
44
+ */
45
+ CPReadFn *orig_readfn;
46
+ CPWriteFn *orig_writefn;
47
};
48
49
/* Macros which are lvalues for the field in CPUARMState for the
50
diff --git a/target/arm/helper.c b/target/arm/helper.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/helper.c
53
+++ b/target/arm/helper.c
54
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
55
REGINFO_SENTINEL
56
};
57
58
+#ifndef CONFIG_USER_ONLY
59
+/* Test if system register redirection is to occur in the current state. */
60
+static bool redirect_for_e2h(CPUARMState *env)
61
+{
62
+ return arm_current_el(env) == 2 && (arm_hcr_el2_eff(env) & HCR_E2H);
63
+}
64
+
65
+static uint64_t el2_e2h_read(CPUARMState *env, const ARMCPRegInfo *ri)
66
+{
67
+ CPReadFn *readfn;
68
+
69
+ if (redirect_for_e2h(env)) {
70
+ /* Switch to the saved EL2 version of the register. */
71
+ ri = ri->opaque;
72
+ readfn = ri->readfn;
73
+ } else {
74
+ readfn = ri->orig_readfn;
75
+ }
76
+ if (readfn == NULL) {
77
+ readfn = raw_read;
78
+ }
79
+ return readfn(env, ri);
80
+}
81
+
82
+static void el2_e2h_write(CPUARMState *env, const ARMCPRegInfo *ri,
83
+ uint64_t value)
84
+{
85
+ CPWriteFn *writefn;
86
+
87
+ if (redirect_for_e2h(env)) {
88
+ /* Switch to the saved EL2 version of the register. */
89
+ ri = ri->opaque;
90
+ writefn = ri->writefn;
91
+ } else {
92
+ writefn = ri->orig_writefn;
93
+ }
94
+ if (writefn == NULL) {
95
+ writefn = raw_write;
96
+ }
97
+ writefn(env, ri, value);
98
+}
99
+
100
+static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
101
+{
102
+ struct E2HAlias {
103
+ uint32_t src_key, dst_key, new_key;
104
+ const char *src_name, *dst_name, *new_name;
105
+ bool (*feature)(const ARMISARegisters *id);
106
+ };
107
+
108
+#define K(op0, op1, crn, crm, op2) \
109
+ ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP, crn, crm, op0, op1, op2)
110
+
111
+ static const struct E2HAlias aliases[] = {
112
+ { K(3, 0, 1, 0, 0), K(3, 4, 1, 0, 0), K(3, 5, 1, 0, 0),
113
+ "SCTLR", "SCTLR_EL2", "SCTLR_EL12" },
114
+ { K(3, 0, 1, 0, 2), K(3, 4, 1, 1, 2), K(3, 5, 1, 0, 2),
115
+ "CPACR", "CPTR_EL2", "CPACR_EL12" },
116
+ { K(3, 0, 2, 0, 0), K(3, 4, 2, 0, 0), K(3, 5, 2, 0, 0),
117
+ "TTBR0_EL1", "TTBR0_EL2", "TTBR0_EL12" },
118
+ { K(3, 0, 2, 0, 1), K(3, 4, 2, 0, 1), K(3, 5, 2, 0, 1),
119
+ "TTBR1_EL1", "TTBR1_EL2", "TTBR1_EL12" },
120
+ { K(3, 0, 2, 0, 2), K(3, 4, 2, 0, 2), K(3, 5, 2, 0, 2),
121
+ "TCR_EL1", "TCR_EL2", "TCR_EL12" },
122
+ { K(3, 0, 4, 0, 0), K(3, 4, 4, 0, 0), K(3, 5, 4, 0, 0),
123
+ "SPSR_EL1", "SPSR_EL2", "SPSR_EL12" },
124
+ { K(3, 0, 4, 0, 1), K(3, 4, 4, 0, 1), K(3, 5, 4, 0, 1),
125
+ "ELR_EL1", "ELR_EL2", "ELR_EL12" },
126
+ { K(3, 0, 5, 1, 0), K(3, 4, 5, 1, 0), K(3, 5, 5, 1, 0),
127
+ "AFSR0_EL1", "AFSR0_EL2", "AFSR0_EL12" },
128
+ { K(3, 0, 5, 1, 1), K(3, 4, 5, 1, 1), K(3, 5, 5, 1, 1),
129
+ "AFSR1_EL1", "AFSR1_EL2", "AFSR1_EL12" },
130
+ { K(3, 0, 5, 2, 0), K(3, 4, 5, 2, 0), K(3, 5, 5, 2, 0),
131
+ "ESR_EL1", "ESR_EL2", "ESR_EL12" },
132
+ { K(3, 0, 6, 0, 0), K(3, 4, 6, 0, 0), K(3, 5, 6, 0, 0),
133
+ "FAR_EL1", "FAR_EL2", "FAR_EL12" },
134
+ { K(3, 0, 10, 2, 0), K(3, 4, 10, 2, 0), K(3, 5, 10, 2, 0),
135
+ "MAIR_EL1", "MAIR_EL2", "MAIR_EL12" },
136
+ { K(3, 0, 10, 3, 0), K(3, 4, 10, 3, 0), K(3, 5, 10, 3, 0),
137
+ "AMAIR0", "AMAIR_EL2", "AMAIR_EL12" },
138
+ { K(3, 0, 12, 0, 0), K(3, 4, 12, 0, 0), K(3, 5, 12, 0, 0),
139
+ "VBAR", "VBAR_EL2", "VBAR_EL12" },
140
+ { K(3, 0, 13, 0, 1), K(3, 4, 13, 0, 1), K(3, 5, 13, 0, 1),
141
+ "CONTEXTIDR_EL1", "CONTEXTIDR_EL2", "CONTEXTIDR_EL12" },
142
+ { K(3, 0, 14, 1, 0), K(3, 4, 14, 1, 0), K(3, 5, 14, 1, 0),
143
+ "CNTKCTL", "CNTHCTL_EL2", "CNTKCTL_EL12" },
144
+
145
+ /*
146
+ * Note that redirection of ZCR is mentioned in the description
147
+ * of ZCR_EL2, and aliasing in the description of ZCR_EL1, but
148
+ * not in the summary table.
149
+ */
150
+ { K(3, 0, 1, 2, 0), K(3, 4, 1, 2, 0), K(3, 5, 1, 2, 0),
151
+ "ZCR_EL1", "ZCR_EL2", "ZCR_EL12", isar_feature_aa64_sve },
152
+
153
+ /* TODO: ARMv8.2-SPE -- PMSCR_EL2 */
154
+ /* TODO: ARMv8.4-Trace -- TRFCR_EL2 */
155
+ };
156
+#undef K
157
+
158
+ size_t i;
159
+
160
+ for (i = 0; i < ARRAY_SIZE(aliases); i++) {
161
+ const struct E2HAlias *a = &aliases[i];
162
+ ARMCPRegInfo *src_reg, *dst_reg;
163
+
164
+ if (a->feature && !a->feature(&cpu->isar)) {
165
+ continue;
166
+ }
87
+ }
167
+
88
+
168
+ src_reg = g_hash_table_lookup(cpu->cp_regs, &a->src_key);
89
+ switch (vms->gic_version) {
169
+ dst_reg = g_hash_table_lookup(cpu->cp_regs, &a->dst_key);
90
+ case VIRT_GIC_VERSION_HOST:
170
+ g_assert(src_reg != NULL);
91
+ case VIRT_GIC_VERSION_MAX:
171
+ g_assert(dst_reg != NULL);
92
+ if (probe_bitmap & KVM_ARM_VGIC_V3) {
172
+
93
+ vms->gic_version = VIRT_GIC_VERSION_3;
173
+ /* Cross-compare names to detect typos in the keys. */
94
+ } else {
174
+ g_assert(strcmp(src_reg->name, a->src_name) == 0);
95
+ vms->gic_version = VIRT_GIC_VERSION_2;
175
+ g_assert(strcmp(dst_reg->name, a->dst_name) == 0);
96
+ }
176
+
97
+ return;
177
+ /* None of the core system registers use opaque; we will. */
98
+ case VIRT_GIC_VERSION_NOSEL:
178
+ g_assert(src_reg->opaque == NULL);
99
+ vms->gic_version = VIRT_GIC_VERSION_2;
179
+
100
+ break;
180
+ /* Create alias before redirection so we dup the right data. */
101
+ case VIRT_GIC_VERSION_2:
181
+ if (a->new_key) {
102
+ case VIRT_GIC_VERSION_3:
182
+ ARMCPRegInfo *new_reg = g_memdup(src_reg, sizeof(ARMCPRegInfo));
103
+ break;
183
+ uint32_t *new_key = g_memdup(&a->new_key, sizeof(uint32_t));
184
+ bool ok;
185
+
186
+ new_reg->name = a->new_name;
187
+ new_reg->type |= ARM_CP_ALIAS;
188
+ /* Remove PL1/PL0 access, leaving PL2/PL3 R/W in place. */
189
+ new_reg->access &= PL2_RW | PL3_RW;
190
+
191
+ ok = g_hash_table_insert(cpu->cp_regs, new_key, new_reg);
192
+ g_assert(ok);
193
+ }
104
+ }
194
+
105
+
195
+ src_reg->opaque = dst_reg;
106
+ /* Check chosen version is effectively supported by the host */
196
+ src_reg->orig_readfn = src_reg->readfn ?: raw_read;
107
+ if (vms->gic_version == VIRT_GIC_VERSION_2 &&
197
+ src_reg->orig_writefn = src_reg->writefn ?: raw_write;
108
+ !(probe_bitmap & KVM_ARM_VGIC_V2)) {
198
+ if (!src_reg->raw_readfn) {
109
+ error_report("host does not support in-kernel GICv2 emulation");
199
+ src_reg->raw_readfn = raw_read;
110
+ exit(1);
111
+ } else if (vms->gic_version == VIRT_GIC_VERSION_3 &&
112
+ !(probe_bitmap & KVM_ARM_VGIC_V3)) {
113
+ error_report("host does not support in-kernel GICv3 emulation");
114
+ exit(1);
200
+ }
115
+ }
201
+ if (!src_reg->raw_writefn) {
116
+ return;
202
+ src_reg->raw_writefn = raw_write;
203
+ }
204
+ src_reg->readfn = el2_e2h_read;
205
+ src_reg->writefn = el2_e2h_write;
206
+ }
117
+ }
207
+}
208
+#endif
209
+
118
+
210
static CPAccessResult ctr_el0_access(CPUARMState *env, const ARMCPRegInfo *ri,
119
+ /* TCG mode */
211
bool isread)
120
+ switch (vms->gic_version) {
212
{
121
+ case VIRT_GIC_VERSION_NOSEL:
213
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
122
vms->gic_version = VIRT_GIC_VERSION_2;
214
: cpu_isar_feature(aa32_predinv, cpu)) {
123
+ break;
215
define_arm_cp_regs(cpu, predinv_reginfo);
124
+ case VIRT_GIC_VERSION_MAX:
125
+ vms->gic_version = VIRT_GIC_VERSION_3;
126
+ break;
127
+ case VIRT_GIC_VERSION_HOST:
128
+ error_report("gic-version=host requires KVM");
129
+ exit(1);
130
+ case VIRT_GIC_VERSION_2:
131
+ case VIRT_GIC_VERSION_3:
132
+ break;
216
}
133
}
217
+
218
+#ifndef CONFIG_USER_ONLY
219
+ /*
220
+ * Register redirections and aliases must be done last,
221
+ * after the registers from the other extensions have been defined.
222
+ */
223
+ if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
224
+ define_arm_vh_e2h_redirects_aliases(cpu);
225
+ }
226
+#endif
227
}
134
}
228
135
229
void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
230
--
136
--
231
2.20.1
137
2.20.1
232
138
233
139
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
When TGE+E2H are both set, CPACR_EL1 is ignored.
3
At the moment if the end-user does not specify the gic-version along
4
with KVM acceleration, v2 is set by default. However most of the
5
systems now have GICv3 and sometimes they do not support GICv2
6
compatibility.
4
7
5
Tested-by: Alex Bennée <alex.bennee@linaro.org>
8
This patch keeps the default v2 selection in all cases except
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
in the KVM accelerated mode when either
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
- the host does not support GICv2 in-kernel emulation or
8
Message-id: 20200206105448.4726-34-richard.henderson@linaro.org
11
- number of VCPUS exceeds 8.
12
13
Those cases did not work anyway so we do not break any compatibility.
14
Now we get v3 selected in such a case.
15
16
Signed-off-by: Eric Auger <eric.auger@redhat.com>
17
Reported-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
18
Reviewed-by: Andrew Jones <drjones@redhat.com>
19
Message-id: 20200311131618.7187-7-eric.auger@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
21
---
11
target/arm/helper.c | 53 ++++++++++++++++++++++++---------------------
22
hw/arm/virt.c | 17 ++++++++++++++++-
12
1 file changed, 28 insertions(+), 25 deletions(-)
23
1 file changed, 16 insertions(+), 1 deletion(-)
13
24
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
25
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
15
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
27
--- a/hw/arm/virt.c
17
+++ b/target/arm/helper.c
28
+++ b/hw/arm/virt.c
18
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
29
@@ -XXX,XX +XXX,XX @@ static void virt_set_memmap(VirtMachineState *vms)
19
int sve_exception_el(CPUARMState *env, int el)
30
*/
31
static void finalize_gic_version(VirtMachineState *vms)
20
{
32
{
21
#ifndef CONFIG_USER_ONLY
33
+ unsigned int max_cpus = MACHINE(vms)->smp.max_cpus;
22
- if (el <= 1) {
23
+ uint64_t hcr_el2 = arm_hcr_el2_eff(env);
24
+
34
+
25
+ if (el <= 1 && (hcr_el2 & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
35
if (kvm_enabled()) {
26
bool disabled = false;
36
int probe_bitmap;
27
37
28
/* The CPACR.ZEN controls traps to EL1:
38
@@ -XXX,XX +XXX,XX @@ static void finalize_gic_version(VirtMachineState *vms)
29
@@ -XXX,XX +XXX,XX @@ int sve_exception_el(CPUARMState *env, int el)
39
}
30
}
40
return;
31
if (disabled) {
41
case VIRT_GIC_VERSION_NOSEL:
32
/* route_to_el2 */
42
- vms->gic_version = VIRT_GIC_VERSION_2;
33
- return (arm_feature(env, ARM_FEATURE_EL2)
43
+ if ((probe_bitmap & KVM_ARM_VGIC_V2) && max_cpus <= GIC_NCPU) {
34
- && (arm_hcr_el2_eff(env) & HCR_TGE) ? 2 : 1);
44
+ vms->gic_version = VIRT_GIC_VERSION_2;
35
+ return hcr_el2 & HCR_TGE ? 2 : 1;
45
+ } else if (probe_bitmap & KVM_ARM_VGIC_V3) {
36
}
46
+ /*
37
47
+ * in case the host does not support v2 in-kernel emulation or
38
/* Check CPACR.FPEN. */
48
+ * the end-user requested more than 8 VCPUs we now default
39
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes)
49
+ * to v3. In any case defaulting to v2 would be broken.
40
int fp_exception_el(CPUARMState *env, int cur_el)
50
+ */
41
{
51
+ vms->gic_version = VIRT_GIC_VERSION_3;
42
#ifndef CONFIG_USER_ONLY
52
+ } else if (max_cpus > GIC_NCPU) {
43
- int fpen;
53
+ error_report("host only supports in-kernel GICv2 emulation "
44
-
54
+ "but more than 8 vcpus are requested");
45
/* CPACR and the CPTR registers don't exist before v6, so FP is
55
+ exit(1);
46
* always accessible
47
*/
48
@@ -XXX,XX +XXX,XX @@ int fp_exception_el(CPUARMState *env, int cur_el)
49
* 0, 2 : trap EL0 and EL1/PL1 accesses
50
* 1 : trap only EL0 accesses
51
* 3 : trap no accesses
52
+ * This register is ignored if E2H+TGE are both set.
53
*/
54
- fpen = extract32(env->cp15.cpacr_el1, 20, 2);
55
- switch (fpen) {
56
- case 0:
57
- case 2:
58
- if (cur_el == 0 || cur_el == 1) {
59
- /* Trap to PL1, which might be EL1 or EL3 */
60
- if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
61
+ if ((arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
62
+ int fpen = extract32(env->cp15.cpacr_el1, 20, 2);
63
+
64
+ switch (fpen) {
65
+ case 0:
66
+ case 2:
67
+ if (cur_el == 0 || cur_el == 1) {
68
+ /* Trap to PL1, which might be EL1 or EL3 */
69
+ if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
70
+ return 3;
71
+ }
72
+ return 1;
73
+ }
56
+ }
74
+ if (cur_el == 3 && !is_a64(env)) {
57
break;
75
+ /* Secure PL1 running at EL3 */
58
case VIRT_GIC_VERSION_2:
76
return 3;
59
case VIRT_GIC_VERSION_3:
77
}
78
- return 1;
79
+ break;
80
+ case 1:
81
+ if (cur_el == 0) {
82
+ return 1;
83
+ }
84
+ break;
85
+ case 3:
86
+ break;
87
}
88
- if (cur_el == 3 && !is_a64(env)) {
89
- /* Secure PL1 running at EL3 */
90
- return 3;
91
- }
92
- break;
93
- case 1:
94
- if (cur_el == 0) {
95
- return 1;
96
- }
97
- break;
98
- case 3:
99
- break;
100
}
101
102
/*
103
--
60
--
104
2.20.1
61
2.20.1
105
62
106
63
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Beata Michalska <beata.michalska@linaro.org>
2
2
3
Not all of the breakpoint types are supported, but those that
3
KVM_SET_VCPU_EVENTS might actually lead to vcpu registers being modified.
4
only examine contextidr are extended to support the new register.
4
As such this should be the last step of sync to avoid potential overwriting
5
of whatever changes KVM might have done.
5
6
6
Tested-by: Alex Bennée <alex.bennee@linaro.org>
7
Signed-off-by: Beata Michalska <beata.michalska@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Andrew Jones <drjones@redhat.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200312003401.29017-2-beata.michalska@linaro.org
9
Message-id: 20200206105448.4726-4-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
target/arm/debug_helper.c | 50 +++++++++++++++++++++++++++++----------
12
target/arm/kvm32.c | 15 ++++++++++-----
13
target/arm/helper.c | 12 ++++++++++
13
target/arm/kvm64.c | 15 ++++++++++-----
14
2 files changed, 50 insertions(+), 12 deletions(-)
14
2 files changed, 20 insertions(+), 10 deletions(-)
15
15
16
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
16
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/debug_helper.c
18
--- a/target/arm/kvm32.c
19
+++ b/target/arm/debug_helper.c
19
+++ b/target/arm/kvm32.c
20
@@ -XXX,XX +XXX,XX @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn)
20
@@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level)
21
int ctx_cmps = extract32(cpu->dbgdidr, 20, 4);
21
return ret;
22
int bt;
23
uint32_t contextidr;
24
+ uint64_t hcr_el2;
25
26
/*
27
* Links to unimplemented or non-context aware breakpoints are
28
@@ -XXX,XX +XXX,XX @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn)
29
}
22
}
30
23
31
bt = extract64(bcr, 20, 4);
24
- ret = kvm_put_vcpu_events(cpu);
25
- if (ret) {
26
- return ret;
27
- }
32
-
28
-
33
- /*
29
write_cpustate_to_list(cpu, true);
34
- * We match the whole register even if this is AArch32 using the
30
35
- * short descriptor format (in which case it holds both PROCID and ASID),
31
if (!write_list_to_kvmstate(cpu, level)) {
36
- * since we don't implement the optional v7 context ID masking.
32
return EINVAL;
37
- */
38
- contextidr = extract64(env->cp15.contextidr_el[1], 0, 32);
39
+ hcr_el2 = arm_hcr_el2_eff(env);
40
41
switch (bt) {
42
case 3: /* linked context ID match */
43
- if (arm_current_el(env) > 1) {
44
- /* Context matches never fire in EL2 or (AArch64) EL3 */
45
+ switch (arm_current_el(env)) {
46
+ default:
47
+ /* Context matches never fire in AArch64 EL3 */
48
return false;
49
+ case 2:
50
+ if (!(hcr_el2 & HCR_E2H)) {
51
+ /* Context matches never fire in EL2 without E2H enabled. */
52
+ return false;
53
+ }
54
+ contextidr = env->cp15.contextidr_el[2];
55
+ break;
56
+ case 1:
57
+ contextidr = env->cp15.contextidr_el[1];
58
+ break;
59
+ case 0:
60
+ if ((hcr_el2 & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
61
+ contextidr = env->cp15.contextidr_el[2];
62
+ } else {
63
+ contextidr = env->cp15.contextidr_el[1];
64
+ }
65
+ break;
66
}
67
- return (contextidr == extract64(env->cp15.dbgbvr[lbn], 0, 32));
68
- case 5: /* linked address mismatch (reserved in AArch64) */
69
+ break;
70
+
71
+ case 7: /* linked contextidr_el1 match */
72
+ contextidr = env->cp15.contextidr_el[1];
73
+ break;
74
+ case 13: /* linked contextidr_el2 match */
75
+ contextidr = env->cp15.contextidr_el[2];
76
+ break;
77
+
78
case 9: /* linked VMID match (reserved if no EL2) */
79
case 11: /* linked context ID and VMID match (reserved if no EL2) */
80
+ case 15: /* linked full context ID match */
81
default:
82
/*
83
* Links to Unlinked context breakpoints must generate no
84
@@ -XXX,XX +XXX,XX @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn)
85
return false;
86
}
33
}
87
34
88
- return false;
89
+ /*
35
+ /*
90
+ * We match the whole register even if this is AArch32 using the
36
+ * Setting VCPU events should be triggered after syncing the registers
91
+ * short descriptor format (in which case it holds both PROCID and ASID),
37
+ * to avoid overwriting potential changes made by KVM upon calling
92
+ * since we don't implement the optional v7 context ID masking.
38
+ * KVM_SET_VCPU_EVENTS ioctl
93
+ */
39
+ */
94
+ return contextidr == (uint32_t)env->cp15.dbgbvr[lbn];
40
+ ret = kvm_put_vcpu_events(cpu);
95
}
41
+ if (ret) {
96
42
+ return ret;
97
static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp)
98
diff --git a/target/arm/helper.c b/target/arm/helper.c
99
index XXXXXXX..XXXXXXX 100644
100
--- a/target/arm/helper.c
101
+++ b/target/arm/helper.c
102
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo jazelle_regs[] = {
103
REGINFO_SENTINEL
104
};
105
106
+static const ARMCPRegInfo vhe_reginfo[] = {
107
+ { .name = "CONTEXTIDR_EL2", .state = ARM_CP_STATE_AA64,
108
+ .opc0 = 3, .opc1 = 4, .crn = 13, .crm = 0, .opc2 = 1,
109
+ .access = PL2_RW,
110
+ .fieldoffset = offsetof(CPUARMState, cp15.contextidr_el[2]) },
111
+ REGINFO_SENTINEL
112
+};
113
+
114
void register_cp_regs_for_features(ARMCPU *cpu)
115
{
116
/* Register all the coprocessor registers based on feature bits */
117
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
118
define_arm_cp_regs(cpu, lor_reginfo);
119
}
120
121
+ if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
122
+ define_arm_cp_regs(cpu, vhe_reginfo);
123
+ }
43
+ }
124
+
44
+
125
if (cpu_isar_feature(aa64_sve, cpu)) {
45
kvm_arm_sync_mpstate_to_kvm(cpu);
126
define_one_arm_cp_reg(cpu, &zcr_el1_reginfo);
46
127
if (arm_feature(env, ARM_FEATURE_EL2)) {
47
return ret;
48
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/kvm64.c
51
+++ b/target/arm/kvm64.c
52
@@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level)
53
return ret;
54
}
55
56
- ret = kvm_put_vcpu_events(cpu);
57
- if (ret) {
58
- return ret;
59
- }
60
-
61
write_cpustate_to_list(cpu, true);
62
63
if (!write_list_to_kvmstate(cpu, level)) {
64
return -EINVAL;
65
}
66
67
+ /*
68
+ * Setting VCPU events should be triggered after syncing the registers
69
+ * to avoid overwriting potential changes made by KVM upon calling
70
+ * KVM_SET_VCPU_EVENTS ioctl
71
+ */
72
+ ret = kvm_put_vcpu_events(cpu);
73
+ if (ret) {
74
+ return ret;
75
+ }
76
+
77
kvm_arm_sync_mpstate_to_kvm(cpu);
78
79
return ret;
128
--
80
--
129
2.20.1
81
2.20.1
130
82
131
83
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
This is part of a reorganization to the set of mmu_idx.
4
The EL1&0 regime is the only one that uses 2-stage translation.
5
Spelling out Stage avoids confusion with Secure.
6
7
Tested-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20200206105448.4726-12-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
target/arm/cpu.h | 4 ++--
14
target/arm/internals.h | 6 +++---
15
target/arm/helper.c | 27 ++++++++++++++-------------
16
3 files changed, 19 insertions(+), 18 deletions(-)
17
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.h
21
+++ b/target/arm/cpu.h
22
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdx {
23
/* Indexes below here don't have TLBs and are used only for AT system
24
* instructions or for the first stage of an S12 page table walk.
25
*/
26
- ARMMMUIdx_S1NSE0 = 0 | ARM_MMU_IDX_NOTLB,
27
- ARMMMUIdx_S1NSE1 = 1 | ARM_MMU_IDX_NOTLB,
28
+ ARMMMUIdx_Stage1_E0 = 0 | ARM_MMU_IDX_NOTLB,
29
+ ARMMMUIdx_Stage1_E1 = 1 | ARM_MMU_IDX_NOTLB,
30
} ARMMMUIdx;
31
32
/* Bit macros for the core-mmu-index values for each index,
33
diff --git a/target/arm/internals.h b/target/arm/internals.h
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/internals.h
36
+++ b/target/arm/internals.h
37
@@ -XXX,XX +XXX,XX @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
38
switch (mmu_idx) {
39
case ARMMMUIdx_E10_0:
40
case ARMMMUIdx_E10_1:
41
- case ARMMMUIdx_S1NSE0:
42
- case ARMMMUIdx_S1NSE1:
43
+ case ARMMMUIdx_Stage1_E0:
44
+ case ARMMMUIdx_Stage1_E1:
45
case ARMMMUIdx_S1E2:
46
case ARMMMUIdx_Stage2:
47
case ARMMMUIdx_MPrivNegPri:
48
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_mmu_idx(CPUARMState *env);
49
#ifdef CONFIG_USER_ONLY
50
static inline ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env)
51
{
52
- return ARMMMUIdx_S1NSE0;
53
+ return ARMMMUIdx_Stage1_E0;
54
}
55
#else
56
ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env);
57
diff --git a/target/arm/helper.c b/target/arm/helper.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/target/arm/helper.c
60
+++ b/target/arm/helper.c
61
@@ -XXX,XX +XXX,XX @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
62
bool take_exc = false;
63
64
if (fi.s1ptw && current_el == 1 && !arm_is_secure(env)
65
- && (mmu_idx == ARMMMUIdx_S1NSE1 || mmu_idx == ARMMMUIdx_S1NSE0)) {
66
+ && (mmu_idx == ARMMMUIdx_Stage1_E1 ||
67
+ mmu_idx == ARMMMUIdx_Stage1_E0)) {
68
/*
69
* Synchronous stage 2 fault on an access made as part of the
70
* translation table walk for AT S1E0* or AT S1E1* insn
71
@@ -XXX,XX +XXX,XX @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
72
mmu_idx = ARMMMUIdx_S1E3;
73
break;
74
case 2:
75
- mmu_idx = ARMMMUIdx_S1NSE1;
76
+ mmu_idx = ARMMMUIdx_Stage1_E1;
77
break;
78
case 1:
79
- mmu_idx = secure ? ARMMMUIdx_S1SE1 : ARMMMUIdx_S1NSE1;
80
+ mmu_idx = secure ? ARMMMUIdx_S1SE1 : ARMMMUIdx_Stage1_E1;
81
break;
82
default:
83
g_assert_not_reached();
84
@@ -XXX,XX +XXX,XX @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
85
mmu_idx = ARMMMUIdx_S1SE0;
86
break;
87
case 2:
88
- mmu_idx = ARMMMUIdx_S1NSE0;
89
+ mmu_idx = ARMMMUIdx_Stage1_E0;
90
break;
91
case 1:
92
- mmu_idx = secure ? ARMMMUIdx_S1SE0 : ARMMMUIdx_S1NSE0;
93
+ mmu_idx = secure ? ARMMMUIdx_S1SE0 : ARMMMUIdx_Stage1_E0;
94
break;
95
default:
96
g_assert_not_reached();
97
@@ -XXX,XX +XXX,XX @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
98
case 0:
99
switch (ri->opc1) {
100
case 0: /* AT S1E1R, AT S1E1W */
101
- mmu_idx = secure ? ARMMMUIdx_S1SE1 : ARMMMUIdx_S1NSE1;
102
+ mmu_idx = secure ? ARMMMUIdx_S1SE1 : ARMMMUIdx_Stage1_E1;
103
break;
104
case 4: /* AT S1E2R, AT S1E2W */
105
mmu_idx = ARMMMUIdx_S1E2;
106
@@ -XXX,XX +XXX,XX @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
107
}
108
break;
109
case 2: /* AT S1E0R, AT S1E0W */
110
- mmu_idx = secure ? ARMMMUIdx_S1SE0 : ARMMMUIdx_S1NSE0;
111
+ mmu_idx = secure ? ARMMMUIdx_S1SE0 : ARMMMUIdx_Stage1_E0;
112
break;
113
case 4: /* AT S12E1R, AT S12E1W */
114
mmu_idx = secure ? ARMMMUIdx_S1SE1 : ARMMMUIdx_E10_1;
115
@@ -XXX,XX +XXX,XX @@ static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
116
case ARMMMUIdx_S1SE0:
117
return arm_el_is_aa64(env, 3) ? 1 : 3;
118
case ARMMMUIdx_S1SE1:
119
- case ARMMMUIdx_S1NSE0:
120
- case ARMMMUIdx_S1NSE1:
121
+ case ARMMMUIdx_Stage1_E0:
122
+ case ARMMMUIdx_Stage1_E1:
123
case ARMMMUIdx_MPrivNegPri:
124
case ARMMMUIdx_MUserNegPri:
125
case ARMMMUIdx_MPriv:
126
@@ -XXX,XX +XXX,XX @@ static inline bool regime_translation_disabled(CPUARMState *env,
127
}
128
129
if ((env->cp15.hcr_el2 & HCR_DC) &&
130
- (mmu_idx == ARMMMUIdx_S1NSE0 || mmu_idx == ARMMMUIdx_S1NSE1)) {
131
+ (mmu_idx == ARMMMUIdx_Stage1_E0 || mmu_idx == ARMMMUIdx_Stage1_E1)) {
132
/* HCR.DC means SCTLR_EL1.M behaves as 0 */
133
return true;
134
}
135
@@ -XXX,XX +XXX,XX @@ static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
136
static inline ARMMMUIdx stage_1_mmu_idx(ARMMMUIdx mmu_idx)
137
{
138
if (mmu_idx == ARMMMUIdx_E10_0 || mmu_idx == ARMMMUIdx_E10_1) {
139
- mmu_idx += (ARMMMUIdx_S1NSE0 - ARMMMUIdx_E10_0);
140
+ mmu_idx += (ARMMMUIdx_Stage1_E0 - ARMMMUIdx_E10_0);
141
}
142
return mmu_idx;
143
}
144
@@ -XXX,XX +XXX,XX @@ static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
145
{
146
switch (mmu_idx) {
147
case ARMMMUIdx_S1SE0:
148
- case ARMMMUIdx_S1NSE0:
149
+ case ARMMMUIdx_Stage1_E0:
150
case ARMMMUIdx_MUser:
151
case ARMMMUIdx_MSUser:
152
case ARMMMUIdx_MUserNegPri:
153
@@ -XXX,XX +XXX,XX @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
154
hwaddr addr, MemTxAttrs txattrs,
155
ARMMMUFaultInfo *fi)
156
{
157
- if ((mmu_idx == ARMMMUIdx_S1NSE0 || mmu_idx == ARMMMUIdx_S1NSE1) &&
158
+ if ((mmu_idx == ARMMMUIdx_Stage1_E0 || mmu_idx == ARMMMUIdx_Stage1_E1) &&
159
!regime_translation_disabled(env, ARMMMUIdx_Stage2)) {
160
target_ulong s2size;
161
hwaddr s2pa;
162
--
163
2.20.1
164
165
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
We are about to expand the number of mmuidx to 10, and so need 4 bits.
4
For the benefit of reading the number out of -d exec, align it to the
5
penultimate nibble.
6
7
Tested-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20200206105448.4726-17-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
target/arm/cpu.h | 16 ++++++++--------
14
1 file changed, 8 insertions(+), 8 deletions(-)
15
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ typedef ARMCPU ArchCPU;
21
* We put flags which are shared between 32 and 64 bit mode at the top
22
* of the word, and flags which apply to only one mode at the bottom.
23
*
24
- * 31 21 18 14 9 0
25
+ * 31 20 18 14 9 0
26
* +--------------+-----+-----+----------+--------------+
27
* | | | TBFLAG_A32 | |
28
* | | +-----+----------+ TBFLAG_AM32 |
29
@@ -XXX,XX +XXX,XX @@ typedef ARMCPU ArchCPU;
30
* | | +-------------------------|
31
* | | | TBFLAG_A64 |
32
* +--------------+-----------+-------------------------+
33
- * 31 21 14 0
34
+ * 31 20 14 0
35
*
36
* Unless otherwise noted, these bits are cached in env->hflags.
37
*/
38
FIELD(TBFLAG_ANY, AARCH64_STATE, 31, 1)
39
-FIELD(TBFLAG_ANY, MMUIDX, 28, 3)
40
-FIELD(TBFLAG_ANY, SS_ACTIVE, 27, 1)
41
-FIELD(TBFLAG_ANY, PSTATE_SS, 26, 1) /* Not cached. */
42
+FIELD(TBFLAG_ANY, SS_ACTIVE, 30, 1)
43
+FIELD(TBFLAG_ANY, PSTATE_SS, 29, 1) /* Not cached. */
44
+FIELD(TBFLAG_ANY, BE_DATA, 28, 1)
45
+FIELD(TBFLAG_ANY, MMUIDX, 24, 4)
46
/* Target EL if we take a floating-point-disabled exception */
47
-FIELD(TBFLAG_ANY, FPEXC_EL, 24, 2)
48
-FIELD(TBFLAG_ANY, BE_DATA, 23, 1)
49
+FIELD(TBFLAG_ANY, FPEXC_EL, 22, 2)
50
/* For A-profile only, target EL for debug exceptions. */
51
-FIELD(TBFLAG_ANY, DEBUG_TARGET_EL, 21, 2)
52
+FIELD(TBFLAG_ANY, DEBUG_TARGET_EL, 20, 2)
53
54
/*
55
* Bit usage when in AArch32 state, both A- and M-profile.
56
--
57
2.20.1
58
59
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Define via macro expansion, so that renumbering of the base ARMMMUIdx
4
symbols is automatically reflected in the bit definitions.
5
6
Tested-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20200206105448.4726-18-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
target/arm/cpu.h | 39 +++++++++++++++++++++++----------------
14
1 file changed, 23 insertions(+), 16 deletions(-)
15
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdx {
21
ARMMMUIdx_Stage1_E1 = 1 | ARM_MMU_IDX_NOTLB,
22
} ARMMMUIdx;
23
24
-/* Bit macros for the core-mmu-index values for each index,
25
+/*
26
+ * Bit macros for the core-mmu-index values for each index,
27
* for use when calling tlb_flush_by_mmuidx() and friends.
28
*/
29
+#define TO_CORE_BIT(NAME) \
30
+ ARMMMUIdxBit_##NAME = 1 << (ARMMMUIdx_##NAME & ARM_MMU_IDX_COREIDX_MASK)
31
+
32
typedef enum ARMMMUIdxBit {
33
- ARMMMUIdxBit_E10_0 = 1 << 0,
34
- ARMMMUIdxBit_E10_1 = 1 << 1,
35
- ARMMMUIdxBit_E2 = 1 << 2,
36
- ARMMMUIdxBit_SE3 = 1 << 3,
37
- ARMMMUIdxBit_SE10_0 = 1 << 4,
38
- ARMMMUIdxBit_SE10_1 = 1 << 5,
39
- ARMMMUIdxBit_Stage2 = 1 << 6,
40
- ARMMMUIdxBit_MUser = 1 << 0,
41
- ARMMMUIdxBit_MPriv = 1 << 1,
42
- ARMMMUIdxBit_MUserNegPri = 1 << 2,
43
- ARMMMUIdxBit_MPrivNegPri = 1 << 3,
44
- ARMMMUIdxBit_MSUser = 1 << 4,
45
- ARMMMUIdxBit_MSPriv = 1 << 5,
46
- ARMMMUIdxBit_MSUserNegPri = 1 << 6,
47
- ARMMMUIdxBit_MSPrivNegPri = 1 << 7,
48
+ TO_CORE_BIT(E10_0),
49
+ TO_CORE_BIT(E10_1),
50
+ TO_CORE_BIT(E2),
51
+ TO_CORE_BIT(SE10_0),
52
+ TO_CORE_BIT(SE10_1),
53
+ TO_CORE_BIT(SE3),
54
+ TO_CORE_BIT(Stage2),
55
+
56
+ TO_CORE_BIT(MUser),
57
+ TO_CORE_BIT(MPriv),
58
+ TO_CORE_BIT(MUserNegPri),
59
+ TO_CORE_BIT(MPrivNegPri),
60
+ TO_CORE_BIT(MSUser),
61
+ TO_CORE_BIT(MSPriv),
62
+ TO_CORE_BIT(MSUserNegPri),
63
+ TO_CORE_BIT(MSPrivNegPri),
64
} ARMMMUIdxBit;
65
66
+#undef TO_CORE_BIT
67
+
68
#define MMU_USER_IDX 0
69
70
static inline int arm_to_core_mmu_idx(ARMMMUIdx mmu_idx)
71
--
72
2.20.1
73
74
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Replace the magic numbers with the relevant ARM_MMU_IDX_M_* constants.
4
Keep the definitions short by referencing previous symbols.
5
6
Tested-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200206105448.4726-19-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/cpu.h | 16 ++++++++--------
13
1 file changed, 8 insertions(+), 8 deletions(-)
14
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdx {
20
ARMMMUIdx_SE10_0 = 4 | ARM_MMU_IDX_A,
21
ARMMMUIdx_SE10_1 = 5 | ARM_MMU_IDX_A,
22
ARMMMUIdx_Stage2 = 6 | ARM_MMU_IDX_A,
23
- ARMMMUIdx_MUser = 0 | ARM_MMU_IDX_M,
24
- ARMMMUIdx_MPriv = 1 | ARM_MMU_IDX_M,
25
- ARMMMUIdx_MUserNegPri = 2 | ARM_MMU_IDX_M,
26
- ARMMMUIdx_MPrivNegPri = 3 | ARM_MMU_IDX_M,
27
- ARMMMUIdx_MSUser = 4 | ARM_MMU_IDX_M,
28
- ARMMMUIdx_MSPriv = 5 | ARM_MMU_IDX_M,
29
- ARMMMUIdx_MSUserNegPri = 6 | ARM_MMU_IDX_M,
30
- ARMMMUIdx_MSPrivNegPri = 7 | ARM_MMU_IDX_M,
31
+ ARMMMUIdx_MUser = ARM_MMU_IDX_M,
32
+ ARMMMUIdx_MPriv = ARM_MMU_IDX_M | ARM_MMU_IDX_M_PRIV,
33
+ ARMMMUIdx_MUserNegPri = ARMMMUIdx_MUser | ARM_MMU_IDX_M_NEGPRI,
34
+ ARMMMUIdx_MPrivNegPri = ARMMMUIdx_MPriv | ARM_MMU_IDX_M_NEGPRI,
35
+ ARMMMUIdx_MSUser = ARMMMUIdx_MUser | ARM_MMU_IDX_M_S,
36
+ ARMMMUIdx_MSPriv = ARMMMUIdx_MPriv | ARM_MMU_IDX_M_S,
37
+ ARMMMUIdx_MSUserNegPri = ARMMMUIdx_MUserNegPri | ARM_MMU_IDX_M_S,
38
+ ARMMMUIdx_MSPrivNegPri = ARMMMUIdx_MPrivNegPri | ARM_MMU_IDX_M_S,
39
/* Indexes below here don't have TLBs and are used only for AT system
40
* instructions or for the first stage of an S12 page table walk.
41
*/
42
--
43
2.20.1
44
45
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Return the indexes for the EL2&0 regime when the appropriate bits
4
are set within HCR_EL2.
5
6
Tested-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200206105448.4726-22-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/helper.c | 11 +++++++++--
13
1 file changed, 9 insertions(+), 2 deletions(-)
14
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
18
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
20
return arm_v7m_mmu_idx_for_secstate(env, env->v7m.secure);
21
}
22
23
+ /* See ARM pseudo-function ELIsInHost. */
24
switch (el) {
25
case 0:
26
- /* TODO: ARMv8.1-VHE */
27
if (arm_is_secure_below_el3(env)) {
28
return ARMMMUIdx_SE10_0;
29
}
30
+ if ((env->cp15.hcr_el2 & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)
31
+ && arm_el_is_aa64(env, 2)) {
32
+ return ARMMMUIdx_E20_0;
33
+ }
34
return ARMMMUIdx_E10_0;
35
case 1:
36
if (arm_is_secure_below_el3(env)) {
37
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
38
}
39
return ARMMMUIdx_E10_1;
40
case 2:
41
- /* TODO: ARMv8.1-VHE */
42
/* TODO: ARMv8.4-SecEL2 */
43
+ /* Note that TGE does not apply at EL2. */
44
+ if ((env->cp15.hcr_el2 & HCR_E2H) && arm_el_is_aa64(env, 2)) {
45
+ return ARMMMUIdx_E20_2;
46
+ }
47
return ARMMMUIdx_E2;
48
case 3:
49
return ARMMMUIdx_SE3;
50
--
51
2.20.1
52
53
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Use the correct sctlr for EL2&0 regime. Due to header ordering,
4
and where arm_mmu_idx_el is declared, we need to move the function
5
out of line. Use the function in many more places in order to
6
select the correct control.
7
8
Tested-by: Alex Bennée <alex.bennee@linaro.org>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20200206105448.4726-23-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
target/arm/cpu.h | 10 +---------
15
target/arm/helper-a64.c | 2 +-
16
target/arm/helper.c | 20 +++++++++++++++-----
17
target/arm/pauth_helper.c | 9 +--------
18
4 files changed, 18 insertions(+), 23 deletions(-)
19
20
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.h
23
+++ b/target/arm/cpu.h
24
@@ -XXX,XX +XXX,XX @@ static inline bool arm_sctlr_b(CPUARMState *env)
25
(env->cp15.sctlr_el[1] & SCTLR_B) != 0;
26
}
27
28
-static inline uint64_t arm_sctlr(CPUARMState *env, int el)
29
-{
30
- if (el == 0) {
31
- /* FIXME: ARMv8.1-VHE S2 translation regime. */
32
- return env->cp15.sctlr_el[1];
33
- } else {
34
- return env->cp15.sctlr_el[el];
35
- }
36
-}
37
+uint64_t arm_sctlr(CPUARMState *env, int el);
38
39
static inline bool arm_cpu_data_is_big_endian_a32(CPUARMState *env,
40
bool sctlr_b)
41
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/target/arm/helper-a64.c
44
+++ b/target/arm/helper-a64.c
45
@@ -XXX,XX +XXX,XX @@ static void daif_check(CPUARMState *env, uint32_t op,
46
uint32_t imm, uintptr_t ra)
47
{
48
/* DAIF update to PSTATE. This is OK from EL0 only if UMA is set. */
49
- if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UMA)) {
50
+ if (arm_current_el(env) == 0 && !(arm_sctlr(env, 0) & SCTLR_UMA)) {
51
raise_exception_ra(env, EXCP_UDEF,
52
syn_aa64_sysregtrap(0, extract32(op, 0, 3),
53
extract32(op, 3, 3), 4,
54
diff --git a/target/arm/helper.c b/target/arm/helper.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/target/arm/helper.c
57
+++ b/target/arm/helper.c
58
@@ -XXX,XX +XXX,XX @@ static void aa64_fpsr_write(CPUARMState *env, const ARMCPRegInfo *ri,
59
static CPAccessResult aa64_daif_access(CPUARMState *env, const ARMCPRegInfo *ri,
60
bool isread)
61
{
62
- if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UMA)) {
63
+ if (arm_current_el(env) == 0 && !(arm_sctlr(env, 0) & SCTLR_UMA)) {
64
return CP_ACCESS_TRAP;
65
}
66
return CP_ACCESS_OK;
67
@@ -XXX,XX +XXX,XX @@ static CPAccessResult aa64_cacheop_access(CPUARMState *env,
68
/* Cache invalidate/clean: NOP, but EL0 must UNDEF unless
69
* SCTLR_EL1.UCI is set.
70
*/
71
- if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UCI)) {
72
+ if (arm_current_el(env) == 0 && !(arm_sctlr(env, 0) & SCTLR_UCI)) {
73
return CP_ACCESS_TRAP;
74
}
75
return CP_ACCESS_OK;
76
@@ -XXX,XX +XXX,XX @@ static uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
77
}
78
}
79
80
-#ifndef CONFIG_USER_ONLY
81
+uint64_t arm_sctlr(CPUARMState *env, int el)
82
+{
83
+ /* Only EL0 needs to be adjusted for EL1&0 or EL2&0. */
84
+ if (el == 0) {
85
+ ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, 0);
86
+ el = (mmu_idx == ARMMMUIdx_E20_0 ? 2 : 1);
87
+ }
88
+ return env->cp15.sctlr_el[el];
89
+}
90
91
/* Return the SCTLR value which controls this address translation regime */
92
-static inline uint32_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
93
+static inline uint64_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
94
{
95
return env->cp15.sctlr_el[regime_el(env, mmu_idx)];
96
}
97
98
+#ifndef CONFIG_USER_ONLY
99
+
100
/* Return true if the specified stage of address translation is disabled */
101
static inline bool regime_translation_disabled(CPUARMState *env,
102
ARMMMUIdx mmu_idx)
103
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
104
flags = FIELD_DP32(flags, TBFLAG_A64, ZCR_LEN, zcr_len);
105
}
106
107
- sctlr = arm_sctlr(env, el);
108
+ sctlr = regime_sctlr(env, stage1);
109
110
if (arm_cpu_data_is_big_endian_a64(el, sctlr)) {
111
flags = FIELD_DP32(flags, TBFLAG_ANY, BE_DATA, 1);
112
diff --git a/target/arm/pauth_helper.c b/target/arm/pauth_helper.c
113
index XXXXXXX..XXXXXXX 100644
114
--- a/target/arm/pauth_helper.c
115
+++ b/target/arm/pauth_helper.c
116
@@ -XXX,XX +XXX,XX @@ static void pauth_check_trap(CPUARMState *env, int el, uintptr_t ra)
117
118
static bool pauth_key_enabled(CPUARMState *env, int el, uint32_t bit)
119
{
120
- uint32_t sctlr;
121
- if (el == 0) {
122
- /* FIXME: ARMv8.1-VHE S2 translation regime. */
123
- sctlr = env->cp15.sctlr_el[1];
124
- } else {
125
- sctlr = env->cp15.sctlr_el[el];
126
- }
127
- return (sctlr & bit) != 0;
128
+ return (arm_sctlr(env, el) & bit) != 0;
129
}
130
131
uint64_t HELPER(pacia)(CPUARMState *env, uint64_t x, uint64_t y)
132
--
133
2.20.1
134
135
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
The comment that we don't support EL2 is somewhat out of date.
4
Update to include checks against HCR_EL2.TDZ.
5
6
Tested-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200206105448.4726-24-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/helper.c | 26 +++++++++++++++++++++-----
13
1 file changed, 21 insertions(+), 5 deletions(-)
14
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
18
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_ipas2e1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
20
static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri,
21
bool isread)
22
{
23
- /* We don't implement EL2, so the only control on DC ZVA is the
24
- * bit in the SCTLR which can prohibit access for EL0.
25
- */
26
- if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_DZE)) {
27
- return CP_ACCESS_TRAP;
28
+ int cur_el = arm_current_el(env);
29
+
30
+ if (cur_el < 2) {
31
+ uint64_t hcr = arm_hcr_el2_eff(env);
32
+
33
+ if (cur_el == 0) {
34
+ if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
35
+ if (!(env->cp15.sctlr_el[2] & SCTLR_DZE)) {
36
+ return CP_ACCESS_TRAP_EL2;
37
+ }
38
+ } else {
39
+ if (!(env->cp15.sctlr_el[1] & SCTLR_DZE)) {
40
+ return CP_ACCESS_TRAP;
41
+ }
42
+ if (hcr & HCR_TDZ) {
43
+ return CP_ACCESS_TRAP_EL2;
44
+ }
45
+ }
46
+ } else if (hcr & HCR_TDZ) {
47
+ return CP_ACCESS_TRAP_EL2;
48
+ }
49
}
50
return CP_ACCESS_OK;
51
}
52
--
53
2.20.1
54
55
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Update to include checks against HCR_EL2.TID2.
4
5
Tested-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200206105448.4726-25-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/helper.c | 26 +++++++++++++++++++++-----
12
1 file changed, 21 insertions(+), 5 deletions(-)
13
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
17
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
19
static CPAccessResult ctr_el0_access(CPUARMState *env, const ARMCPRegInfo *ri,
20
bool isread)
21
{
22
- /* Only accessible in EL0 if SCTLR.UCT is set (and only in AArch64,
23
- * but the AArch32 CTR has its own reginfo struct)
24
- */
25
- if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UCT)) {
26
- return CP_ACCESS_TRAP;
27
+ int cur_el = arm_current_el(env);
28
+
29
+ if (cur_el < 2) {
30
+ uint64_t hcr = arm_hcr_el2_eff(env);
31
+
32
+ if (cur_el == 0) {
33
+ if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
34
+ if (!(env->cp15.sctlr_el[2] & SCTLR_UCT)) {
35
+ return CP_ACCESS_TRAP_EL2;
36
+ }
37
+ } else {
38
+ if (!(env->cp15.sctlr_el[1] & SCTLR_UCT)) {
39
+ return CP_ACCESS_TRAP;
40
+ }
41
+ if (hcr & HCR_TID2) {
42
+ return CP_ACCESS_TRAP_EL2;
43
+ }
44
+ }
45
+ } else if (hcr & HCR_TID2) {
46
+ return CP_ACCESS_TRAP_EL2;
47
+ }
48
}
49
50
if (arm_current_el(env) < 2 && arm_hcr_el2_eff(env) & HCR_TID2) {
51
--
52
2.20.1
53
54
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
For ARMv8.1, op1 == 5 is reserved for EL2 aliases of
4
EL1 and EL0 registers.
5
6
Tested-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200206105448.4726-28-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/helper.c | 5 +----
13
1 file changed, 1 insertion(+), 4 deletions(-)
14
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
18
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
20
mask = PL0_RW;
21
break;
22
case 4:
23
+ case 5:
24
/* min_EL EL2 */
25
mask = PL2_RW;
26
break;
27
- case 5:
28
- /* unallocated encoding, so not possible */
29
- assert(false);
30
- break;
31
case 6:
32
/* min_EL EL3 */
33
mask = PL3_RW;
34
--
35
2.20.1
36
37
diff view generated by jsdifflib