1
A surprisingly short target-arm queue, but no point in holding
1
Some arm patches before softfreeze. These are all bug fixes.
2
onto these waiting for more code to arrive :-)
3
2
4
thanks
5
-- PMM
3
-- PMM
6
4
7
The following changes since commit 3d0bf8dfdfebd7f2ae41b6f220444b8047d6b1ee:
5
The following changes since commit 0ebf76aae58324b8f7bf6af798696687f5f4c2a9:
8
6
9
Merge remote-tracking branch 'remotes/dgilbert/tags/pull-migration-20170710a' into staging (2017-07-10 18:13:03 +0100)
7
Merge tag 'nvme-next-pull-request' of git://git.infradead.org/qemu-nvme into staging (2022-07-15 15:38:13 +0100)
10
8
11
are available in the git repository at:
9
are available in the Git repository at:
12
10
13
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20170711
11
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220718
14
12
15
for you to fetch changes up to 792dac309c8660306557ba058b8b5a6a75ab3c1f:
13
for you to fetch changes up to 004c8a8bc569c8b18fca6fc90ffe3223daaf17b7:
16
14
17
target-arm: v7M: ignore writes to CONTROL.SPSEL from Thread mode (2017-07-11 11:21:26 +0100)
15
Align Raspberry Pi DMA interrupts with Linux DTS (2022-07-18 13:25:13 +0100)
18
16
19
----------------------------------------------------------------
17
----------------------------------------------------------------
20
target-arm queue:
18
target-arm queue:
21
* v7M: ignore writes to CONTROL.SPSEL from Thread mode
19
* hw/intc/armv7m_nvic: ICPRn must not unpend an IRQ that is being held high
22
* KVM: Enable in-kernel timers with user space gic
20
* target/arm: Fill in VL for tbflags when SME enabled and SVE disabled
23
* aspeed: Register all watchdogs
21
* target/arm: Fix aarch64_sve_change_el for SME
24
* hw/misc: Add Exynos4210 Pseudo Random Number Generator
22
* linux-user/aarch64: Do not clear PROT_MTE on mprotect
23
* target/arm: Honour VTCR_EL2 bits in Secure EL2
24
* hw/adc: Fix CONV bit in NPCM7XX ADC CON register
25
* hw/adc: Make adci[*] R/W in NPCM7XX ADC
26
* target/arm: Don't set syndrome ISS for loads and stores with writeback
27
* Align Raspberry Pi DMA interrupts with Linux DTS
25
28
26
----------------------------------------------------------------
29
----------------------------------------------------------------
27
Alexander Graf (1):
30
Andrey Makarov (1):
28
ARM: KVM: Enable in-kernel timers with user space gic
31
Align Raspberry Pi DMA interrupts with Linux DTS
29
32
30
Joel Stanley (1):
33
Hao Wu (2):
31
aspeed: Register all watchdogs
34
hw/adc: Fix CONV bit in NPCM7XX ADC CON register
35
hw/adc: Make adci[*] R/W in NPCM7XX ADC
32
36
33
Krzysztof Kozlowski (1):
37
Peter Maydell (9):
34
hw/misc: Add Exynos4210 Pseudo Random Number Generator
38
hw/intc/armv7m_nvic: ICPRn must not unpend an IRQ that is being held high
39
target/arm: Define and use new regime_tcr_value() function
40
target/arm: Calculate mask/base_mask in get_level1_table_address()
41
target/arm: Fold regime_tcr() and regime_tcr_value() together
42
target/arm: Fix big-endian host handling of VTCR
43
target/arm: Store VTCR_EL2, VSTCR_EL2 registers as uint64_t
44
target/arm: Store TCR_EL* registers as uint64_t
45
target/arm: Honour VTCR_EL2 bits in Secure EL2
46
target/arm: Don't set syndrome ISS for loads and stores with writeback
35
47
36
Peter Maydell (1):
48
Richard Henderson (3):
37
target-arm: v7M: ignore writes to CONTROL.SPSEL from Thread mode
49
target/arm: Fill in VL for tbflags when SME enabled and SVE disabled
50
target/arm: Fix aarch64_sve_change_el for SME
51
linux-user/aarch64: Do not clear PROT_MTE on mprotect
38
52
39
hw/misc/Makefile.objs | 2 +-
53
include/hw/arm/bcm2835_peripherals.h | 2 +
40
include/hw/arm/aspeed_soc.h | 4 +-
54
target/arm/cpu.h | 38 ++++++++---
41
include/sysemu/kvm.h | 11 ++
55
target/arm/internals.h | 34 +++++++---
42
target/arm/cpu.h | 3 +
56
accel/tcg/translate-all.c | 13 +++-
43
accel/kvm/kvm-all.c | 5 +
57
hw/adc/npcm7xx_adc.c | 4 +-
44
accel/stubs/kvm-stub.c | 5 +
58
hw/arm/bcm2835_peripherals.c | 26 ++++++-
45
hw/arm/aspeed_soc.c | 25 ++--
59
hw/intc/armv7m_nvic.c | 9 ++-
46
hw/arm/exynos4210.c | 4 +
60
target/arm/cpu.c | 2 +-
47
hw/intc/arm_gic.c | 7 ++
61
target/arm/debug_helper.c | 2 +-
48
hw/misc/exynos4210_rng.c | 277 ++++++++++++++++++++++++++++++++++++++++++++
62
target/arm/helper.c | 128 ++++++++++++++++-------------------
49
target/arm/helper.c | 13 ++-
63
target/arm/ptw.c | 38 ++++++-----
50
target/arm/kvm.c | 51 ++++++++
64
target/arm/tlb_helper.c | 2 +-
51
12 files changed, 394 insertions(+), 13 deletions(-)
65
target/arm/translate-a64.c | 4 +-
52
create mode 100644 hw/misc/exynos4210_rng.c
66
tests/qtest/bcm2835-dma-test.c | 118 ++++++++++++++++++++++++++++++++
53
67
tests/qtest/npcm7xx_adc-test.c | 2 +-
68
tests/qtest/meson.build | 3 +-
69
16 files changed, 306 insertions(+), 119 deletions(-)
70
create mode 100644 tests/qtest/bcm2835-dma-test.c
diff view generated by jsdifflib
New patch
1
In the M-profile Arm ARM, rule R_CVJS defines when an interrupt should
2
be set to the Pending state:
3
A) when the input line is high and the interrupt is not Active
4
B) when the input line transitions from low to high and the interrupt
5
is Active
6
(Note that the first of these is an ongoing condition, and the
7
second is a point-in-time event.)
1
8
9
This can be rephrased as:
10
1 when the line goes from low to high, set Pending
11
2 when Active goes from 1 to 0, if line is high then set Pending
12
3 ignore attempts to clear Pending when the line is high
13
and Active is 0
14
15
where 1 covers both B and one of the "transition into condition A"
16
cases, 2 deals with the other "transition into condition A"
17
possibility, and 3 is "don't drop Pending if we're already in
18
condition A". Transitions out of condition A don't affect Pending
19
state.
20
21
We handle case 1 in set_irq_level(). For an interrupt (as opposed
22
to other kinds of exception) the only place where we clear Active
23
is in armv7m_nvic_complete_irq(), where we handle case 2 by
24
checking for whether we need to re-pend the exception. For case 3,
25
the only places where we clear Pending state on an interrupt are in
26
armv7m_nvic_acknowledge_irq() (where we are setting Active so it
27
doesn't count) and for writes to NVIC_ICPRn.
28
29
It is the "write to NVIC_ICPRn" case that we missed: we must ignore
30
this if the input line is high and the interrupt is not Active.
31
(This required behaviour is differently and perhaps more clearly
32
stated in the v7M Arm ARM, which has pseudocode in section B3.4.1
33
that implies it.)
34
35
Reported-by: Igor Kotrasiński <i.kotrasinsk@samsung.com>
36
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
37
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
38
Message-id: 20220628154724.3297442-1-peter.maydell@linaro.org
39
---
40
hw/intc/armv7m_nvic.c | 9 ++++++++-
41
1 file changed, 8 insertions(+), 1 deletion(-)
42
43
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/intc/armv7m_nvic.c
46
+++ b/hw/intc/armv7m_nvic.c
47
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
48
startvec = 8 * (offset - 0x280) + NVIC_FIRST_IRQ; /* vector # */
49
50
for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
51
+ /*
52
+ * Note that if the input line is still held high and the interrupt
53
+ * is not active then rule R_CVJS requires that the Pending state
54
+ * remains set; in that case we mustn't let it be cleared.
55
+ */
56
if (value & (1 << i) &&
57
- (attrs.secure || s->itns[startvec + i])) {
58
+ (attrs.secure || s->itns[startvec + i]) &&
59
+ !(setval == 0 && s->vectors[startvec + i].level &&
60
+ !s->vectors[startvec + i].active)) {
61
s->vectors[startvec + i].pending = setval;
62
}
63
}
64
--
65
2.25.1
66
67
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
When PSTATE.SM, VL = SVL even if SVE is disabled.
4
This is visible in kselftest ssve-test.
5
6
Reported-by: Mark Brown <broonie@kernel.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220713045848.217364-2-richard.henderson@linaro.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/helper.c | 10 ++++++++--
13
1 file changed, 8 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 @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
20
}
21
if (cpu_isar_feature(aa64_sme, env_archcpu(env))) {
22
int sme_el = sme_exception_el(env, el);
23
+ bool sm = FIELD_EX64(env->svcr, SVCR, SM);
24
25
DP_TBFLAG_A64(flags, SMEEXC_EL, sme_el);
26
if (sme_el == 0) {
27
/* Similarly, do not compute SVL if SME is disabled. */
28
- DP_TBFLAG_A64(flags, SVL, sve_vqm1_for_el_sm(env, el, true));
29
+ int svl = sve_vqm1_for_el_sm(env, el, true);
30
+ DP_TBFLAG_A64(flags, SVL, svl);
31
+ if (sm) {
32
+ /* If SVE is disabled, we will not have set VL above. */
33
+ DP_TBFLAG_A64(flags, VL, svl);
34
+ }
35
}
36
- if (FIELD_EX64(env->svcr, SVCR, SM)) {
37
+ if (sm) {
38
DP_TBFLAG_A64(flags, PSTATE_SM, 1);
39
DP_TBFLAG_A64(flags, SME_TRAP_NONSTREAMING, !sme_fa64(env, el));
40
}
41
--
42
2.25.1
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
We were only checking for SVE disabled and not taking into
4
account PSTATE.SM to check SME disabled, which resulted in
5
vectors being incorrectly truncated.
6
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220713045848.217364-3-richard.henderson@linaro.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/helper.c | 31 +++++++++++++++++++++++++------
13
1 file changed, 25 insertions(+), 6 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 aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq)
20
}
21
}
22
23
+static uint32_t sve_vqm1_for_el_sm_ena(CPUARMState *env, int el, bool sm)
24
+{
25
+ int exc_el;
26
+
27
+ if (sm) {
28
+ exc_el = sme_exception_el(env, el);
29
+ } else {
30
+ exc_el = sve_exception_el(env, el);
31
+ }
32
+ if (exc_el) {
33
+ return 0; /* disabled */
34
+ }
35
+ return sve_vqm1_for_el_sm(env, el, sm);
36
+}
37
+
38
/*
39
* Notice a change in SVE vector size when changing EL.
40
*/
41
@@ -XXX,XX +XXX,XX @@ void aarch64_sve_change_el(CPUARMState *env, int old_el,
42
{
43
ARMCPU *cpu = env_archcpu(env);
44
int old_len, new_len;
45
- bool old_a64, new_a64;
46
+ bool old_a64, new_a64, sm;
47
48
/* Nothing to do if no SVE. */
49
if (!cpu_isar_feature(aa64_sve, cpu)) {
50
@@ -XXX,XX +XXX,XX @@ void aarch64_sve_change_el(CPUARMState *env, int old_el,
51
* invoke ResetSVEState when taking an exception from, or
52
* returning to, AArch32 state when PSTATE.SM is enabled.
53
*/
54
- if (old_a64 != new_a64 && FIELD_EX64(env->svcr, SVCR, SM)) {
55
+ sm = FIELD_EX64(env->svcr, SVCR, SM);
56
+ if (old_a64 != new_a64 && sm) {
57
arm_reset_sve_state(env);
58
return;
59
}
60
@@ -XXX,XX +XXX,XX @@ void aarch64_sve_change_el(CPUARMState *env, int old_el,
61
* we already have the correct register contents when encountering the
62
* vq0->vq0 transition between EL0->EL1.
63
*/
64
- old_len = (old_a64 && !sve_exception_el(env, old_el)
65
- ? sve_vqm1_for_el(env, old_el) : 0);
66
- new_len = (new_a64 && !sve_exception_el(env, new_el)
67
- ? sve_vqm1_for_el(env, new_el) : 0);
68
+ old_len = new_len = 0;
69
+ if (old_a64) {
70
+ old_len = sve_vqm1_for_el_sm_ena(env, old_el, sm);
71
+ }
72
+ if (new_a64) {
73
+ new_len = sve_vqm1_for_el_sm_ena(env, new_el, sm);
74
+ }
75
76
/* When changing vector length, clear inaccessible state. */
77
if (new_len < old_len) {
78
--
79
2.25.1
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
The documentation for PROT_MTE says that it cannot be cleared
4
by mprotect. Further, the implementation of the VM_ARCH_CLEAR bit,
5
contains PROT_BTI confiming that bit should be cleared.
6
7
Introduce PAGE_TARGET_STICKY to allow target/arch/cpu.h to control
8
which bits may be reset during page_set_flags. This is sort of the
9
opposite of VM_ARCH_CLEAR, but works better with qemu's PAGE_* bits
10
that are separate from PROT_* bits.
11
12
Reported-by: Vitaly Buka <vitalybuka@google.com>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20220711031420.17820-1-richard.henderson@linaro.org
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
target/arm/cpu.h | 7 +++++--
19
accel/tcg/translate-all.c | 13 +++++++++++--
20
2 files changed, 16 insertions(+), 4 deletions(-)
21
22
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/cpu.h
25
+++ b/target/arm/cpu.h
26
@@ -XXX,XX +XXX,XX @@ static inline MemTxAttrs *typecheck_memtxattrs(MemTxAttrs *x)
27
28
/*
29
* AArch64 usage of the PAGE_TARGET_* bits for linux-user.
30
+ * Note that with the Linux kernel, PROT_MTE may not be cleared by mprotect
31
+ * mprotect but PROT_BTI may be cleared. C.f. the kernel's VM_ARCH_CLEAR.
32
*/
33
-#define PAGE_BTI PAGE_TARGET_1
34
-#define PAGE_MTE PAGE_TARGET_2
35
+#define PAGE_BTI PAGE_TARGET_1
36
+#define PAGE_MTE PAGE_TARGET_2
37
+#define PAGE_TARGET_STICKY PAGE_MTE
38
39
#ifdef TARGET_TAGGED_ADDRESSES
40
/**
41
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/accel/tcg/translate-all.c
44
+++ b/accel/tcg/translate-all.c
45
@@ -XXX,XX +XXX,XX @@ int page_get_flags(target_ulong address)
46
return p->flags;
47
}
48
49
+/*
50
+ * Allow the target to decide if PAGE_TARGET_[12] may be reset.
51
+ * By default, they are not kept.
52
+ */
53
+#ifndef PAGE_TARGET_STICKY
54
+#define PAGE_TARGET_STICKY 0
55
+#endif
56
+#define PAGE_STICKY (PAGE_ANON | PAGE_TARGET_STICKY)
57
+
58
/* Modify the flags of a page and invalidate the code if necessary.
59
The flag PAGE_WRITE_ORG is positioned automatically depending
60
on PAGE_WRITE. The mmap_lock should already be held. */
61
@@ -XXX,XX +XXX,XX @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
62
p->target_data = NULL;
63
p->flags = flags;
64
} else {
65
- /* Using mprotect on a page does not change MAP_ANON. */
66
- p->flags = (p->flags & PAGE_ANON) | flags;
67
+ /* Using mprotect on a page does not change sticky bits. */
68
+ p->flags = (p->flags & PAGE_STICKY) | flags;
69
}
70
}
71
}
72
--
73
2.25.1
diff view generated by jsdifflib
New patch
1
The regime_tcr() function returns a pointer to a struct TCR
2
corresponding to the TCR controlling a translation regime. The
3
struct TCR has the raw value of the register, plus two fields mask
4
and base_mask which are used as a small optimization in the case of
5
32-bit short-descriptor lookups. Almost all callers of regime_tcr()
6
only want the raw register value. Define and use a new
7
regime_tcr_value() function which returns only the raw 64-bit
8
register value.
1
9
10
This is a preliminary to removing the 32-bit short descriptor
11
optimization -- it only saves a handful of bit operations, which is
12
tiny compared to the overhead of doing a page table walk at all, and
13
the TCR struct is awkward and makes fixing
14
https://gitlab.com/qemu-project/qemu/-/issues/1103 unnecessarily
15
difficult.
16
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Message-id: 20220714132303.1287193-2-peter.maydell@linaro.org
20
---
21
target/arm/internals.h | 6 ++++++
22
target/arm/helper.c | 6 +++---
23
target/arm/ptw.c | 8 ++++----
24
target/arm/tlb_helper.c | 2 +-
25
4 files changed, 14 insertions(+), 8 deletions(-)
26
27
diff --git a/target/arm/internals.h b/target/arm/internals.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/internals.h
30
+++ b/target/arm/internals.h
31
@@ -XXX,XX +XXX,XX @@ static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
32
return &env->cp15.tcr_el[regime_el(env, mmu_idx)];
33
}
34
35
+/* Return the raw value of the TCR controlling this translation regime */
36
+static inline uint64_t regime_tcr_value(CPUARMState *env, ARMMMUIdx mmu_idx)
37
+{
38
+ return regime_tcr(env, mmu_idx)->raw_tcr;
39
+}
40
+
41
/**
42
* arm_num_brps: Return number of implemented breakpoints.
43
* Note that the ID register BRPS field is "number of bps - 1",
44
diff --git a/target/arm/helper.c b/target/arm/helper.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/arm/helper.c
47
+++ b/target/arm/helper.c
48
@@ -XXX,XX +XXX,XX @@ static int vae1_tlbmask(CPUARMState *env)
49
static int tlbbits_for_regime(CPUARMState *env, ARMMMUIdx mmu_idx,
50
uint64_t addr)
51
{
52
- uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
53
+ uint64_t tcr = regime_tcr_value(env, mmu_idx);
54
int tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
55
int select = extract64(addr, 55, 1);
56
57
@@ -XXX,XX +XXX,XX @@ static int aa64_va_parameter_tcma(uint64_t tcr, ARMMMUIdx mmu_idx)
58
ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
59
ARMMMUIdx mmu_idx, bool data)
60
{
61
- uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
62
+ uint64_t tcr = regime_tcr_value(env, mmu_idx);
63
bool epd, hpd, using16k, using64k, tsz_oob, ds;
64
int select, tsz, tbi, max_tsz, min_tsz, ps, sh;
65
ARMCPU *cpu = env_archcpu(env);
66
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
67
{
68
CPUARMTBFlags flags = {};
69
ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx);
70
- uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
71
+ uint64_t tcr = regime_tcr_value(env, mmu_idx);
72
uint64_t sctlr;
73
int tbii, tbid;
74
75
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/ptw.c
78
+++ b/target/arm/ptw.c
79
@@ -XXX,XX +XXX,XX @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
80
static ARMVAParameters aa32_va_parameters(CPUARMState *env, uint32_t va,
81
ARMMMUIdx mmu_idx)
82
{
83
- uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
84
+ uint64_t tcr = regime_tcr_value(env, mmu_idx);
85
uint32_t el = regime_el(env, mmu_idx);
86
int select, tsz;
87
bool epd, hpd;
88
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
89
uint32_t attrs;
90
int32_t stride;
91
int addrsize, inputsize, outputsize;
92
- TCR *tcr = regime_tcr(env, mmu_idx);
93
+ uint64_t tcr = regime_tcr_value(env, mmu_idx);
94
int ap, ns, xn, pxn;
95
uint32_t el = regime_el(env, mmu_idx);
96
uint64_t descaddrmask;
97
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
98
* For stage 2 translations the starting level is specified by the
99
* VTCR_EL2.SL0 field (whose interpretation depends on the page size)
100
*/
101
- uint32_t sl0 = extract32(tcr->raw_tcr, 6, 2);
102
- uint32_t sl2 = extract64(tcr->raw_tcr, 33, 1);
103
+ uint32_t sl0 = extract32(tcr, 6, 2);
104
+ uint32_t sl2 = extract64(tcr, 33, 1);
105
uint32_t startlevel;
106
bool ok;
107
108
diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
109
index XXXXXXX..XXXXXXX 100644
110
--- a/target/arm/tlb_helper.c
111
+++ b/target/arm/tlb_helper.c
112
@@ -XXX,XX +XXX,XX @@ bool regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx)
113
return true;
114
}
115
if (arm_feature(env, ARM_FEATURE_LPAE)
116
- && (regime_tcr(env, mmu_idx)->raw_tcr & TTBCR_EAE)) {
117
+ && (regime_tcr_value(env, mmu_idx) & TTBCR_EAE)) {
118
return true;
119
}
120
return false;
121
--
122
2.25.1
diff view generated by jsdifflib
New patch
1
In get_level1_table_address(), instead of using precalculated values
2
of mask and base_mask from the TCR struct, calculate them directly
3
(in the same way we currently do in vmsa_ttbcr_raw_write() to
4
populate the TCR struct fields).
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220714132303.1287193-3-peter.maydell@linaro.org
9
---
10
target/arm/ptw.c | 14 +++++++++-----
11
1 file changed, 9 insertions(+), 5 deletions(-)
12
13
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/ptw.c
16
+++ b/target/arm/ptw.c
17
@@ -XXX,XX +XXX,XX @@ static bool get_level1_table_address(CPUARMState *env, ARMMMUIdx mmu_idx,
18
uint32_t *table, uint32_t address)
19
{
20
/* Note that we can only get here for an AArch32 PL0/PL1 lookup */
21
- TCR *tcr = regime_tcr(env, mmu_idx);
22
+ uint64_t tcr = regime_tcr_value(env, mmu_idx);
23
+ int maskshift = extract32(tcr, 0, 3);
24
+ uint32_t mask = ~(((uint32_t)0xffffffffu) >> maskshift);
25
+ uint32_t base_mask;
26
27
- if (address & tcr->mask) {
28
- if (tcr->raw_tcr & TTBCR_PD1) {
29
+ if (address & mask) {
30
+ if (tcr & TTBCR_PD1) {
31
/* Translation table walk disabled for TTBR1 */
32
return false;
33
}
34
*table = regime_ttbr(env, mmu_idx, 1) & 0xffffc000;
35
} else {
36
- if (tcr->raw_tcr & TTBCR_PD0) {
37
+ if (tcr & TTBCR_PD0) {
38
/* Translation table walk disabled for TTBR0 */
39
return false;
40
}
41
- *table = regime_ttbr(env, mmu_idx, 0) & tcr->base_mask;
42
+ base_mask = ~((uint32_t)0x3fffu >> maskshift);
43
+ *table = regime_ttbr(env, mmu_idx, 0) & base_mask;
44
}
45
*table |= (address >> 18) & 0x3ffc;
46
return true;
47
--
48
2.25.1
diff view generated by jsdifflib
New patch
1
The only caller of regime_tcr() is now regime_tcr_value(); fold the
2
two together, and use the shorter and more natural 'regime_tcr'
3
name for the new function.
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220714132303.1287193-4-peter.maydell@linaro.org
8
---
9
target/arm/internals.h | 16 +++++-----------
10
target/arm/helper.c | 6 +++---
11
target/arm/ptw.c | 6 +++---
12
target/arm/tlb_helper.c | 2 +-
13
4 files changed, 12 insertions(+), 18 deletions(-)
14
15
diff --git a/target/arm/internals.h b/target/arm/internals.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/internals.h
18
+++ b/target/arm/internals.h
19
@@ -XXX,XX +XXX,XX @@ static inline uint64_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
20
return env->cp15.sctlr_el[regime_el(env, mmu_idx)];
21
}
22
23
-/* Return the TCR controlling this translation regime */
24
-static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
25
+/* Return the value of the TCR controlling this translation regime */
26
+static inline uint64_t regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
27
{
28
if (mmu_idx == ARMMMUIdx_Stage2) {
29
- return &env->cp15.vtcr_el2;
30
+ return env->cp15.vtcr_el2.raw_tcr;
31
}
32
if (mmu_idx == ARMMMUIdx_Stage2_S) {
33
/*
34
* Note: Secure stage 2 nominally shares fields from VTCR_EL2, but
35
* those are not currently used by QEMU, so just return VSTCR_EL2.
36
*/
37
- return &env->cp15.vstcr_el2;
38
+ return env->cp15.vstcr_el2.raw_tcr;
39
}
40
- return &env->cp15.tcr_el[regime_el(env, mmu_idx)];
41
-}
42
-
43
-/* Return the raw value of the TCR controlling this translation regime */
44
-static inline uint64_t regime_tcr_value(CPUARMState *env, ARMMMUIdx mmu_idx)
45
-{
46
- return regime_tcr(env, mmu_idx)->raw_tcr;
47
+ return env->cp15.tcr_el[regime_el(env, mmu_idx)].raw_tcr;
48
}
49
50
/**
51
diff --git a/target/arm/helper.c b/target/arm/helper.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/helper.c
54
+++ b/target/arm/helper.c
55
@@ -XXX,XX +XXX,XX @@ static int vae1_tlbmask(CPUARMState *env)
56
static int tlbbits_for_regime(CPUARMState *env, ARMMMUIdx mmu_idx,
57
uint64_t addr)
58
{
59
- uint64_t tcr = regime_tcr_value(env, mmu_idx);
60
+ uint64_t tcr = regime_tcr(env, mmu_idx);
61
int tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
62
int select = extract64(addr, 55, 1);
63
64
@@ -XXX,XX +XXX,XX @@ static int aa64_va_parameter_tcma(uint64_t tcr, ARMMMUIdx mmu_idx)
65
ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
66
ARMMMUIdx mmu_idx, bool data)
67
{
68
- uint64_t tcr = regime_tcr_value(env, mmu_idx);
69
+ uint64_t tcr = regime_tcr(env, mmu_idx);
70
bool epd, hpd, using16k, using64k, tsz_oob, ds;
71
int select, tsz, tbi, max_tsz, min_tsz, ps, sh;
72
ARMCPU *cpu = env_archcpu(env);
73
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
74
{
75
CPUARMTBFlags flags = {};
76
ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx);
77
- uint64_t tcr = regime_tcr_value(env, mmu_idx);
78
+ uint64_t tcr = regime_tcr(env, mmu_idx);
79
uint64_t sctlr;
80
int tbii, tbid;
81
82
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
83
index XXXXXXX..XXXXXXX 100644
84
--- a/target/arm/ptw.c
85
+++ b/target/arm/ptw.c
86
@@ -XXX,XX +XXX,XX @@ static bool get_level1_table_address(CPUARMState *env, ARMMMUIdx mmu_idx,
87
uint32_t *table, uint32_t address)
88
{
89
/* Note that we can only get here for an AArch32 PL0/PL1 lookup */
90
- uint64_t tcr = regime_tcr_value(env, mmu_idx);
91
+ uint64_t tcr = regime_tcr(env, mmu_idx);
92
int maskshift = extract32(tcr, 0, 3);
93
uint32_t mask = ~(((uint32_t)0xffffffffu) >> maskshift);
94
uint32_t base_mask;
95
@@ -XXX,XX +XXX,XX @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
96
static ARMVAParameters aa32_va_parameters(CPUARMState *env, uint32_t va,
97
ARMMMUIdx mmu_idx)
98
{
99
- uint64_t tcr = regime_tcr_value(env, mmu_idx);
100
+ uint64_t tcr = regime_tcr(env, mmu_idx);
101
uint32_t el = regime_el(env, mmu_idx);
102
int select, tsz;
103
bool epd, hpd;
104
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
105
uint32_t attrs;
106
int32_t stride;
107
int addrsize, inputsize, outputsize;
108
- uint64_t tcr = regime_tcr_value(env, mmu_idx);
109
+ uint64_t tcr = regime_tcr(env, mmu_idx);
110
int ap, ns, xn, pxn;
111
uint32_t el = regime_el(env, mmu_idx);
112
uint64_t descaddrmask;
113
diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
114
index XXXXXXX..XXXXXXX 100644
115
--- a/target/arm/tlb_helper.c
116
+++ b/target/arm/tlb_helper.c
117
@@ -XXX,XX +XXX,XX @@ bool regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx)
118
return true;
119
}
120
if (arm_feature(env, ARM_FEATURE_LPAE)
121
- && (regime_tcr_value(env, mmu_idx) & TTBCR_EAE)) {
122
+ && (regime_tcr(env, mmu_idx) & TTBCR_EAE)) {
123
return true;
124
}
125
return false;
126
--
127
2.25.1
diff view generated by jsdifflib
1
For v7M, writes to the CONTROL register are only permitted for
1
We have a bug in our handling of accesses to the AArch32 VTCR
2
privileged code. However even if the code is privileged, the
2
register on big-endian hosts: we were not adjusting the part of the
3
write must not affect the SPSEL bit in the CONTROL register
3
uint64_t field within TCR that the generated code would access. That
4
if the CPU is in Thread mode (as documented in the pseudocode
4
can be done with offsetoflow32(), by using an ARM_CP_STATE_BOTH cpreg
5
for the MSR instruction). Implement this, instead of permitting
5
struct, or by defining a full set of read/write/reset functions --
6
SPSEL to be written in all cases.
6
the various other TCR cpreg structs used one or another of those
7
strategies, but for VTCR we did not, so on a big-endian host VTCR
8
accesses would touch the wrong half of the register.
7
9
8
This was causing mbed applications not to run, because the
10
Use offsetoflow32() in the VTCR register struct. This works even
9
RTX RTOS they use relies on this behaviour.
11
though the field in the CPU struct is currently a struct TCR, because
12
the first field in that struct is the uint64_t raw_tcr.
13
14
None of the other TCR registers have this bug -- either they are
15
AArch64 only, or else they define resetfn, writefn, etc, and
16
expect to be passed the full struct pointer.
10
17
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 1498820791-8130-1-git-send-email-peter.maydell@linaro.org
20
Message-id: 20220714132303.1287193-5-peter.maydell@linaro.org
14
---
21
---
15
target/arm/helper.c | 13 ++++++++++---
22
target/arm/helper.c | 2 +-
16
1 file changed, 10 insertions(+), 3 deletions(-)
23
1 file changed, 1 insertion(+), 1 deletion(-)
17
24
18
diff --git a/target/arm/helper.c b/target/arm/helper.c
25
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper.c
27
--- a/target/arm/helper.c
21
+++ b/target/arm/helper.c
28
+++ b/target/arm/helper.c
22
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
29
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
23
}
30
.cp = 15, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 2,
24
break;
31
.type = ARM_CP_ALIAS,
25
case 20: /* CONTROL */
32
.access = PL2_RW, .accessfn = access_el3_aa32ns,
26
- switch_v7m_sp(env, (val & R_V7M_CONTROL_SPSEL_MASK) != 0);
33
- .fieldoffset = offsetof(CPUARMState, cp15.vtcr_el2) },
27
- env->v7m.control = val & (R_V7M_CONTROL_SPSEL_MASK |
34
+ .fieldoffset = offsetoflow32(CPUARMState, cp15.vtcr_el2) },
28
- R_V7M_CONTROL_NPRIV_MASK);
35
{ .name = "VTCR_EL2", .state = ARM_CP_STATE_AA64,
29
+ /* Writing to the SPSEL bit only has an effect if we are in
36
.opc0 = 3, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 2,
30
+ * thread mode; other bits can be updated by any privileged code.
37
.access = PL2_RW,
31
+ * switch_v7m_sp() deals with updating the SPSEL bit in
32
+ * env->v7m.control, so we only need update the others.
33
+ */
34
+ if (env->v7m.exception == 0) {
35
+ switch_v7m_sp(env, (val & R_V7M_CONTROL_SPSEL_MASK) != 0);
36
+ }
37
+ env->v7m.control &= ~R_V7M_CONTROL_NPRIV_MASK;
38
+ env->v7m.control |= val & R_V7M_CONTROL_NPRIV_MASK;
39
break;
40
default:
41
qemu_log_mask(LOG_GUEST_ERROR, "Attempt to write unknown special"
42
--
38
--
43
2.7.4
39
2.25.1
44
45
diff view generated by jsdifflib
New patch
1
Change the representation of the VSTCR_EL2 and VTCR_EL2 registers in
2
the CPU state struct from struct TCR to uint64_t.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20220714132303.1287193-6-peter.maydell@linaro.org
7
---
8
target/arm/cpu.h | 4 ++--
9
target/arm/internals.h | 4 ++--
10
target/arm/helper.c | 4 +---
11
target/arm/ptw.c | 14 +++++++-------
12
4 files changed, 12 insertions(+), 14 deletions(-)
13
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
19
uint64_t vsttbr_el2; /* Secure Virtualization Translation Table. */
20
/* MMU translation table base control. */
21
TCR tcr_el[4];
22
- TCR vtcr_el2; /* Virtualization Translation Control. */
23
- TCR vstcr_el2; /* Secure Virtualization Translation Control. */
24
+ uint64_t vtcr_el2; /* Virtualization Translation Control. */
25
+ uint64_t vstcr_el2; /* Secure Virtualization Translation Control. */
26
uint32_t c2_data; /* MPU data cacheable bits. */
27
uint32_t c2_insn; /* MPU instruction cacheable bits. */
28
union { /* MMU domain access control register
29
diff --git a/target/arm/internals.h b/target/arm/internals.h
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/internals.h
32
+++ b/target/arm/internals.h
33
@@ -XXX,XX +XXX,XX @@ static inline uint64_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
34
static inline uint64_t regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
35
{
36
if (mmu_idx == ARMMMUIdx_Stage2) {
37
- return env->cp15.vtcr_el2.raw_tcr;
38
+ return env->cp15.vtcr_el2;
39
}
40
if (mmu_idx == ARMMMUIdx_Stage2_S) {
41
/*
42
* Note: Secure stage 2 nominally shares fields from VTCR_EL2, but
43
* those are not currently used by QEMU, so just return VSTCR_EL2.
44
*/
45
- return env->cp15.vstcr_el2.raw_tcr;
46
+ return env->cp15.vstcr_el2;
47
}
48
return env->cp15.tcr_el[regime_el(env, mmu_idx)].raw_tcr;
49
}
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 el2_cp_reginfo[] = {
55
{ .name = "VTCR_EL2", .state = ARM_CP_STATE_AA64,
56
.opc0 = 3, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 2,
57
.access = PL2_RW,
58
- /* no .writefn needed as this can't cause an ASID change;
59
- * no .raw_writefn or .resetfn needed as we never use mask/base_mask
60
- */
61
+ /* no .writefn needed as this can't cause an ASID change */
62
.fieldoffset = offsetof(CPUARMState, cp15.vtcr_el2) },
63
{ .name = "VTTBR", .state = ARM_CP_STATE_AA32,
64
.cp = 15, .opc1 = 6, .crm = 2,
65
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/target/arm/ptw.c
68
+++ b/target/arm/ptw.c
69
@@ -XXX,XX +XXX,XX @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
70
if (arm_is_secure_below_el3(env)) {
71
/* Check if page table walk is to secure or non-secure PA space. */
72
if (*is_secure) {
73
- *is_secure = !(env->cp15.vstcr_el2.raw_tcr & VSTCR_SW);
74
+ *is_secure = !(env->cp15.vstcr_el2 & VSTCR_SW);
75
} else {
76
- *is_secure = !(env->cp15.vtcr_el2.raw_tcr & VTCR_NSW);
77
+ *is_secure = !(env->cp15.vtcr_el2 & VTCR_NSW);
78
}
79
} else {
80
assert(!*is_secure);
81
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
82
ipa_secure = attrs->secure;
83
if (arm_is_secure_below_el3(env)) {
84
if (ipa_secure) {
85
- attrs->secure = !(env->cp15.vstcr_el2.raw_tcr & VSTCR_SW);
86
+ attrs->secure = !(env->cp15.vstcr_el2 & VSTCR_SW);
87
} else {
88
- attrs->secure = !(env->cp15.vtcr_el2.raw_tcr & VTCR_NSW);
89
+ attrs->secure = !(env->cp15.vtcr_el2 & VTCR_NSW);
90
}
91
} else {
92
assert(!ipa_secure);
93
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
94
if (arm_is_secure_below_el3(env)) {
95
if (ipa_secure) {
96
attrs->secure =
97
- !(env->cp15.vstcr_el2.raw_tcr & (VSTCR_SA | VSTCR_SW));
98
+ !(env->cp15.vstcr_el2 & (VSTCR_SA | VSTCR_SW));
99
} else {
100
attrs->secure =
101
- !((env->cp15.vtcr_el2.raw_tcr & (VTCR_NSA | VTCR_NSW))
102
- || (env->cp15.vstcr_el2.raw_tcr & (VSTCR_SA | VSTCR_SW)));
103
+ !((env->cp15.vtcr_el2 & (VTCR_NSA | VTCR_NSW))
104
+ || (env->cp15.vstcr_el2 & (VSTCR_SA | VSTCR_SW)));
105
}
106
}
107
return 0;
108
--
109
2.25.1
diff view generated by jsdifflib
1
From: Joel Stanley <joel@jms.id.au>
1
Change the representation of the TCR_EL* registers in the CPU state
2
struct from struct TCR to uint64_t. This allows us to drop the
3
custom vmsa_ttbcr_raw_write() function, moving the "enforce RES0"
4
checks to their more usual location in the writefn
5
vmsa_ttbcr_write(). We also don't need the resetfn any more.
2
6
3
The ast2400 contains two and the ast2500 contains three watchdogs.
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Add this information to the AspeedSoCInfo and realise the correct number
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
of watchdogs for that each SoC type.
9
Message-id: 20220714132303.1287193-7-peter.maydell@linaro.org
10
---
11
target/arm/cpu.h | 8 +----
12
target/arm/internals.h | 6 ++--
13
target/arm/cpu.c | 2 +-
14
target/arm/debug_helper.c | 2 +-
15
target/arm/helper.c | 75 +++++++++++----------------------------
16
target/arm/ptw.c | 2 +-
17
6 files changed, 27 insertions(+), 68 deletions(-)
6
18
7
Signed-off-by: Joel Stanley <joel@jms.id.au>
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
8
Reviewed-by: Cédric Le Goater <clg@kaod.org>
20
index XXXXXXX..XXXXXXX 100644
9
Tested-by: Cédric Le Goater <clg@kaod.org>
21
--- a/target/arm/cpu.h
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
+++ b/target/arm/cpu.h
11
---
23
@@ -XXX,XX +XXX,XX @@ typedef struct ARMGenericTimer {
12
include/hw/arm/aspeed_soc.h | 4 +++-
24
#define GTIMER_HYPVIRT 4
13
hw/arm/aspeed_soc.c | 25 +++++++++++++++++--------
25
#define NUM_GTIMERS 5
14
2 files changed, 20 insertions(+), 9 deletions(-)
26
15
27
-typedef struct {
16
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
28
- uint64_t raw_tcr;
17
index XXXXXXX..XXXXXXX 100644
29
- uint32_t mask;
18
--- a/include/hw/arm/aspeed_soc.h
30
- uint32_t base_mask;
19
+++ b/include/hw/arm/aspeed_soc.h
31
-} TCR;
20
@@ -XXX,XX +XXX,XX @@
32
-
21
#include "hw/net/ftgmac100.h"
33
#define VTCR_NSW (1u << 29)
22
34
#define VTCR_NSA (1u << 30)
23
#define ASPEED_SPIS_NUM 2
35
#define VSTCR_SW VTCR_NSW
24
+#define ASPEED_WDTS_NUM 3
36
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
25
37
uint64_t vttbr_el2; /* Virtualization Translation Table Base. */
26
typedef struct AspeedSoCState {
38
uint64_t vsttbr_el2; /* Secure Virtualization Translation Table. */
27
/*< private >*/
39
/* MMU translation table base control. */
28
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSoCState {
40
- TCR tcr_el[4];
29
AspeedSMCState fmc;
41
+ uint64_t tcr_el[4];
30
AspeedSMCState spi[ASPEED_SPIS_NUM];
42
uint64_t vtcr_el2; /* Virtualization Translation Control. */
31
AspeedSDMCState sdmc;
43
uint64_t vstcr_el2; /* Secure Virtualization Translation Control. */
32
- AspeedWDTState wdt;
44
uint32_t c2_data; /* MPU data cacheable bits. */
33
+ AspeedWDTState wdt[ASPEED_WDTS_NUM];
45
diff --git a/target/arm/internals.h b/target/arm/internals.h
34
FTGMAC100State ftgmac100;
46
index XXXXXXX..XXXXXXX 100644
35
} AspeedSoCState;
47
--- a/target/arm/internals.h
36
48
+++ b/target/arm/internals.h
37
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSoCInfo {
49
@@ -XXX,XX +XXX,XX @@ unsigned int arm_pamax(ARMCPU *cpu);
38
const hwaddr *spi_bases;
50
*/
39
const char *fmc_typename;
51
static inline bool extended_addresses_enabled(CPUARMState *env)
40
const char **spi_typename;
52
{
41
+ int wdts_num;
53
- TCR *tcr = &env->cp15.tcr_el[arm_is_secure(env) ? 3 : 1];
42
} AspeedSoCInfo;
54
+ uint64_t tcr = env->cp15.tcr_el[arm_is_secure(env) ? 3 : 1];
43
55
return arm_el_is_aa64(env, 1) ||
44
typedef struct AspeedSoCClass {
56
- (arm_feature(env, ARM_FEATURE_LPAE) && (tcr->raw_tcr & TTBCR_EAE));
45
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
57
+ (arm_feature(env, ARM_FEATURE_LPAE) && (tcr & TTBCR_EAE));
46
index XXXXXXX..XXXXXXX 100644
58
}
47
--- a/hw/arm/aspeed_soc.c
59
48
+++ b/hw/arm/aspeed_soc.c
60
/* Update a QEMU watchpoint based on the information the guest has set in the
49
@@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = {
61
@@ -XXX,XX +XXX,XX @@ static inline uint64_t regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
50
.spi_bases = aspeed_soc_ast2400_spi_bases,
62
*/
51
.fmc_typename = "aspeed.smc.fmc",
63
return env->cp15.vstcr_el2;
52
.spi_typename = aspeed_soc_ast2400_typenames,
64
}
53
+ .wdts_num = 2,
65
- return env->cp15.tcr_el[regime_el(env, mmu_idx)].raw_tcr;
54
}, {
66
+ return env->cp15.tcr_el[regime_el(env, mmu_idx)];
55
.name = "ast2400-a1",
67
}
56
.cpu_model = "arm926",
68
57
@@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = {
69
/**
58
.spi_bases = aspeed_soc_ast2400_spi_bases,
70
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
59
.fmc_typename = "aspeed.smc.fmc",
71
index XXXXXXX..XXXXXXX 100644
60
.spi_typename = aspeed_soc_ast2400_typenames,
72
--- a/target/arm/cpu.c
61
+ .wdts_num = 2,
73
+++ b/target/arm/cpu.c
62
}, {
74
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
63
.name = "ast2400",
75
* Enable TBI0 but not TBI1.
64
.cpu_model = "arm926",
76
* Note that this must match useronly_clean_ptr.
65
@@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = {
77
*/
66
.spi_bases = aspeed_soc_ast2400_spi_bases,
78
- env->cp15.tcr_el[1].raw_tcr = 5 | (1ULL << 37);
67
.fmc_typename = "aspeed.smc.fmc",
79
+ env->cp15.tcr_el[1] = 5 | (1ULL << 37);
68
.spi_typename = aspeed_soc_ast2400_typenames,
80
69
+ .wdts_num = 2,
81
/* Enable MTE */
70
}, {
82
if (cpu_isar_feature(aa64_mte, cpu)) {
71
.name = "ast2500-a1",
83
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
72
.cpu_model = "arm1176",
84
index XXXXXXX..XXXXXXX 100644
73
@@ -XXX,XX +XXX,XX @@ static const AspeedSoCInfo aspeed_socs[] = {
85
--- a/target/arm/debug_helper.c
74
.spi_bases = aspeed_soc_ast2500_spi_bases,
86
+++ b/target/arm/debug_helper.c
75
.fmc_typename = "aspeed.smc.ast2500-fmc",
87
@@ -XXX,XX +XXX,XX @@ static uint32_t arm_debug_exception_fsr(CPUARMState *env)
76
.spi_typename = aspeed_soc_ast2500_typenames,
88
using_lpae = true;
77
+ .wdts_num = 3,
89
} else {
90
if (arm_feature(env, ARM_FEATURE_LPAE) &&
91
- (env->cp15.tcr_el[target_el].raw_tcr & TTBCR_EAE)) {
92
+ (env->cp15.tcr_el[target_el] & TTBCR_EAE)) {
93
using_lpae = true;
94
}
95
}
96
diff --git a/target/arm/helper.c b/target/arm/helper.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/target/arm/helper.c
99
+++ b/target/arm/helper.c
100
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pmsav5_cp_reginfo[] = {
101
.fieldoffset = offsetof(CPUARMState, cp15.c6_region[7]) },
102
};
103
104
-static void vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
105
- uint64_t value)
106
+static void vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
107
+ uint64_t value)
108
{
109
- TCR *tcr = raw_ptr(env, ri);
110
- int maskshift = extract32(value, 0, 3);
111
+ ARMCPU *cpu = env_archcpu(env);
112
113
if (!arm_feature(env, ARM_FEATURE_V8)) {
114
if (arm_feature(env, ARM_FEATURE_LPAE) && (value & TTBCR_EAE)) {
115
- /* Pre ARMv8 bits [21:19], [15:14] and [6:3] are UNK/SBZP when
116
- * using Long-desciptor translation table format */
117
+ /*
118
+ * Pre ARMv8 bits [21:19], [15:14] and [6:3] are UNK/SBZP when
119
+ * using Long-descriptor translation table format
120
+ */
121
value &= ~((7 << 19) | (3 << 14) | (0xf << 3));
122
} else if (arm_feature(env, ARM_FEATURE_EL3)) {
123
- /* In an implementation that includes the Security Extensions
124
+ /*
125
+ * In an implementation that includes the Security Extensions
126
* TTBCR has additional fields PD0 [4] and PD1 [5] for
127
* Short-descriptor translation table format.
128
*/
129
@@ -XXX,XX +XXX,XX @@ static void vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
130
}
131
}
132
133
- /* Update the masks corresponding to the TCR bank being written
134
- * Note that we always calculate mask and base_mask, but
135
- * they are only used for short-descriptor tables (ie if EAE is 0);
136
- * for long-descriptor tables the TCR fields are used differently
137
- * and the mask and base_mask values are meaningless.
138
- */
139
- tcr->raw_tcr = value;
140
- tcr->mask = ~(((uint32_t)0xffffffffu) >> maskshift);
141
- tcr->base_mask = ~((uint32_t)0x3fffu >> maskshift);
142
-}
143
-
144
-static void vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
145
- uint64_t value)
146
-{
147
- ARMCPU *cpu = env_archcpu(env);
148
- TCR *tcr = raw_ptr(env, ri);
149
-
150
if (arm_feature(env, ARM_FEATURE_LPAE)) {
151
/* With LPAE the TTBCR could result in a change of ASID
152
* via the TTBCR.A1 bit, so do a TLB flush.
153
*/
154
tlb_flush(CPU(cpu));
155
}
156
- /* Preserve the high half of TCR_EL1, set via TTBCR2. */
157
- value = deposit64(tcr->raw_tcr, 0, 32, value);
158
- vmsa_ttbcr_raw_write(env, ri, value);
159
-}
160
-
161
-static void vmsa_ttbcr_reset(CPUARMState *env, const ARMCPRegInfo *ri)
162
-{
163
- TCR *tcr = raw_ptr(env, ri);
164
-
165
- /* Reset both the TCR as well as the masks corresponding to the bank of
166
- * the TCR being reset.
167
- */
168
- tcr->raw_tcr = 0;
169
- tcr->mask = 0;
170
- tcr->base_mask = 0xffffc000u;
171
+ raw_write(env, ri, value);
172
}
173
174
static void vmsa_tcr_el12_write(CPUARMState *env, const ARMCPRegInfo *ri,
175
uint64_t value)
176
{
177
ARMCPU *cpu = env_archcpu(env);
178
- TCR *tcr = raw_ptr(env, ri);
179
180
/* For AArch64 the A1 bit could result in a change of ASID, so TLB flush. */
181
tlb_flush(CPU(cpu));
182
- tcr->raw_tcr = value;
183
+ raw_write(env, ri, value);
184
}
185
186
static void vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
187
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = {
188
.opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2,
189
.access = PL1_RW, .accessfn = access_tvm_trvm,
190
.writefn = vmsa_tcr_el12_write,
191
- .resetfn = vmsa_ttbcr_reset, .raw_writefn = raw_write,
192
+ .raw_writefn = raw_write,
193
+ .resetvalue = 0,
194
.fieldoffset = offsetof(CPUARMState, cp15.tcr_el[1]) },
195
{ .name = "TTBCR", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2,
196
.access = PL1_RW, .accessfn = access_tvm_trvm,
197
.type = ARM_CP_ALIAS, .writefn = vmsa_ttbcr_write,
198
- .raw_writefn = vmsa_ttbcr_raw_write,
199
- /* No offsetoflow32 -- pass the entire TCR to writefn/raw_writefn. */
200
- .bank_fieldoffsets = { offsetof(CPUARMState, cp15.tcr_el[3]),
201
- offsetof(CPUARMState, cp15.tcr_el[1])} },
202
+ .raw_writefn = raw_write,
203
+ .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.tcr_el[3]),
204
+ offsetoflow32(CPUARMState, cp15.tcr_el[1])} },
205
};
206
207
/* Note that unlike TTBCR, writing to TTBCR2 does not require flushing
208
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo ttbcr2_reginfo = {
209
.access = PL1_RW, .accessfn = access_tvm_trvm,
210
.type = ARM_CP_ALIAS,
211
.bank_fieldoffsets = {
212
- offsetofhigh32(CPUARMState, cp15.tcr_el[3].raw_tcr),
213
- offsetofhigh32(CPUARMState, cp15.tcr_el[1].raw_tcr),
214
+ offsetofhigh32(CPUARMState, cp15.tcr_el[3]),
215
+ offsetofhigh32(CPUARMState, cp15.tcr_el[1]),
78
},
216
},
79
};
217
};
80
218
81
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
219
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
82
object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc),
220
{ .name = "TCR_EL2", .state = ARM_CP_STATE_BOTH,
83
"ram-size", &error_abort);
221
.opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 2,
84
222
.access = PL2_RW, .writefn = vmsa_tcr_el12_write,
85
- object_initialize(&s->wdt, sizeof(s->wdt), TYPE_ASPEED_WDT);
223
- /* no .raw_writefn or .resetfn needed as we never use mask/base_mask */
86
- object_property_add_child(obj, "wdt", OBJECT(&s->wdt), NULL);
224
.fieldoffset = offsetof(CPUARMState, cp15.tcr_el[2]) },
87
- qdev_set_parent_bus(DEVICE(&s->wdt), sysbus_get_default());
225
{ .name = "VTCR", .state = ARM_CP_STATE_AA32,
88
+ for (i = 0; i < sc->info->wdts_num; i++) {
226
.cp = 15, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 2,
89
+ object_initialize(&s->wdt[i], sizeof(s->wdt[i]), TYPE_ASPEED_WDT);
227
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
90
+ object_property_add_child(obj, "wdt[*]", OBJECT(&s->wdt[i]), NULL);
228
{ .name = "TCR_EL3", .state = ARM_CP_STATE_AA64,
91
+ qdev_set_parent_bus(DEVICE(&s->wdt[i]), sysbus_get_default());
229
.opc0 = 3, .opc1 = 6, .crn = 2, .crm = 0, .opc2 = 2,
92
+ }
230
.access = PL3_RW,
93
231
- /* no .writefn needed as this can't cause an ASID change;
94
object_initialize(&s->ftgmac100, sizeof(s->ftgmac100), TYPE_FTGMAC100);
232
- * we must provide a .raw_writefn and .resetfn because we handle
95
object_property_add_child(obj, "ftgmac100", OBJECT(&s->ftgmac100), NULL);
233
- * reset and migration for the AArch32 TTBCR(S), which might be
96
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
234
- * using mask and base_mask.
97
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdmc), 0, ASPEED_SOC_SDMC_BASE);
235
- */
98
236
- .resetfn = vmsa_ttbcr_reset, .raw_writefn = vmsa_ttbcr_raw_write,
99
/* Watch dog */
237
+ /* no .writefn needed as this can't cause an ASID change */
100
- object_property_set_bool(OBJECT(&s->wdt), true, "realized", &err);
238
+ .resetvalue = 0,
101
- if (err) {
239
.fieldoffset = offsetof(CPUARMState, cp15.tcr_el[3]) },
102
- error_propagate(errp, err);
240
{ .name = "ELR_EL3", .state = ARM_CP_STATE_AA64,
103
- return;
241
.type = ARM_CP_ALIAS,
104
+ for (i = 0; i < sc->info->wdts_num; i++) {
242
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
105
+ object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized", &err);
243
index XXXXXXX..XXXXXXX 100644
106
+ if (err) {
244
--- a/target/arm/ptw.c
107
+ error_propagate(errp, err);
245
+++ b/target/arm/ptw.c
108
+ return;
246
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
109
+ }
247
int r_el = regime_el(env, mmu_idx);
110
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0,
248
if (arm_el_is_aa64(env, r_el)) {
111
+ ASPEED_SOC_WDT_BASE + i * 0x20);
249
int pamax = arm_pamax(env_archcpu(env));
112
}
250
- uint64_t tcr = env->cp15.tcr_el[r_el].raw_tcr;
113
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt), 0, ASPEED_SOC_WDT_BASE);
251
+ uint64_t tcr = env->cp15.tcr_el[r_el];
114
252
int addrtop, tbi;
115
/* Net */
253
116
qdev_set_nic_properties(DEVICE(&s->ftgmac100), &nd_table[0]);
254
tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
117
--
255
--
118
2.7.4
256
2.25.1
119
120
diff view generated by jsdifflib
1
From: Alexander Graf <agraf@suse.de>
1
In regime_tcr() we return the appropriate TCR register for the
2
translation regime. For Secure EL2, we return the VSTCR_EL2 value,
3
but in this translation regime some fields that control behaviour are
4
in VTCR_EL2. When this code was originally written (as the comment
5
notes), QEMU didn't care about any of those fields, but we have since
6
added support for features such as LPA2 which do need the values from
7
those fields.
2
8
3
When running with KVM enabled, you can choose between emulating the
9
Synthesize a TCR value by merging in the relevant VTCR_EL2 fields to
4
gic in kernel or user space. If the kernel supports in-kernel virtualization
10
the VSTCR_EL2 value.
5
of the interrupt controller, it will default to that. If not, if will
6
default to user space emulation.
7
11
8
Unfortunately when running in user mode gic emulation, we miss out on
12
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1103
9
interrupt events which are only available from kernel space, such as the timer.
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
This patch leverages the new kernel/user space pending line synchronization for
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
timer events. It does not handle PMU events yet.
15
Message-id: 20220714132303.1287193-8-peter.maydell@linaro.org
16
---
17
target/arm/cpu.h | 19 +++++++++++++++++++
18
target/arm/internals.h | 22 +++++++++++++++++++---
19
2 files changed, 38 insertions(+), 3 deletions(-)
12
20
13
Signed-off-by: Alexander Graf <agraf@suse.de>
14
Reviewed-by: Andrew Jones <drjones@redhat.com>
15
Message-id: 1498577737-130264-1-git-send-email-agraf@suse.de
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
include/sysemu/kvm.h | 11 +++++++++++
19
target/arm/cpu.h | 3 +++
20
accel/kvm/kvm-all.c | 5 +++++
21
accel/stubs/kvm-stub.c | 5 +++++
22
hw/intc/arm_gic.c | 7 +++++++
23
target/arm/kvm.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++
24
6 files changed, 82 insertions(+)
25
26
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/include/sysemu/kvm.h
29
+++ b/include/sysemu/kvm.h
30
@@ -XXX,XX +XXX,XX @@ int kvm_init_vcpu(CPUState *cpu);
31
int kvm_cpu_exec(CPUState *cpu);
32
int kvm_destroy_vcpu(CPUState *cpu);
33
34
+/**
35
+ * kvm_arm_supports_user_irq
36
+ *
37
+ * Not all KVM implementations support notifications for kernel generated
38
+ * interrupt events to user space. This function indicates whether the current
39
+ * KVM implementation does support them.
40
+ *
41
+ * Returns: true if KVM supports using kernel generated IRQs from user space
42
+ */
43
+bool kvm_arm_supports_user_irq(void);
44
+
45
#ifdef NEED_CPU_H
46
#include "cpu.h"
47
48
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
21
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
49
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/cpu.h
23
--- a/target/arm/cpu.h
51
+++ b/target/arm/cpu.h
24
+++ b/target/arm/cpu.h
52
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
25
@@ -XXX,XX +XXX,XX @@ FIELD(CPTR_EL3, TCPAC, 31, 1)
53
void *el_change_hook_opaque;
26
#define TTBCR_SH1 (1U << 28)
54
27
#define TTBCR_EAE (1U << 31)
55
int32_t node_id; /* NUMA node this CPU belongs to */
28
29
+FIELD(VTCR, T0SZ, 0, 6)
30
+FIELD(VTCR, SL0, 6, 2)
31
+FIELD(VTCR, IRGN0, 8, 2)
32
+FIELD(VTCR, ORGN0, 10, 2)
33
+FIELD(VTCR, SH0, 12, 2)
34
+FIELD(VTCR, TG0, 14, 2)
35
+FIELD(VTCR, PS, 16, 3)
36
+FIELD(VTCR, VS, 19, 1)
37
+FIELD(VTCR, HA, 21, 1)
38
+FIELD(VTCR, HD, 22, 1)
39
+FIELD(VTCR, HWU59, 25, 1)
40
+FIELD(VTCR, HWU60, 26, 1)
41
+FIELD(VTCR, HWU61, 27, 1)
42
+FIELD(VTCR, HWU62, 28, 1)
43
+FIELD(VTCR, NSW, 29, 1)
44
+FIELD(VTCR, NSA, 30, 1)
45
+FIELD(VTCR, DS, 32, 1)
46
+FIELD(VTCR, SL2, 33, 1)
56
+
47
+
57
+ /* Used to synchronize KVM and QEMU in-kernel device levels */
48
/* Bit definitions for ARMv8 SPSR (PSTATE) format.
58
+ uint8_t device_irq_level;
49
* Only these are valid when in AArch64 mode; in
59
};
50
* AArch32 mode SPSRs are basically CPSR-format.
60
51
diff --git a/target/arm/internals.h b/target/arm/internals.h
61
static inline ARMCPU *arm_env_get_cpu(CPUARMState *env)
62
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
63
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
64
--- a/accel/kvm/kvm-all.c
53
--- a/target/arm/internals.h
65
+++ b/accel/kvm/kvm-all.c
54
+++ b/target/arm/internals.h
66
@@ -XXX,XX +XXX,XX @@ int kvm_has_intx_set_mask(void)
55
@@ -XXX,XX +XXX,XX @@ static inline uint64_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
67
return kvm_state->intx_set_mask;
56
return env->cp15.sctlr_el[regime_el(env, mmu_idx)];
68
}
57
}
69
58
70
+bool kvm_arm_supports_user_irq(void)
59
+/*
71
+{
60
+ * These are the fields in VTCR_EL2 which affect both the Secure stage 2
72
+ return kvm_check_extension(kvm_state, KVM_CAP_ARM_USER_IRQ);
61
+ * and the Non-Secure stage 2 translation regimes (and hence which are
73
+}
62
+ * not present in VSTCR_EL2).
63
+ */
64
+#define VTCR_SHARED_FIELD_MASK \
65
+ (R_VTCR_IRGN0_MASK | R_VTCR_ORGN0_MASK | R_VTCR_SH0_MASK | \
66
+ R_VTCR_PS_MASK | R_VTCR_VS_MASK | R_VTCR_HA_MASK | R_VTCR_HD_MASK | \
67
+ R_VTCR_DS_MASK)
74
+
68
+
75
#ifdef KVM_CAP_SET_GUEST_DEBUG
69
/* Return the value of the TCR controlling this translation regime */
76
struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *cpu,
70
static inline uint64_t regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
77
target_ulong pc)
78
diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c
79
index XXXXXXX..XXXXXXX 100644
80
--- a/accel/stubs/kvm-stub.c
81
+++ b/accel/stubs/kvm-stub.c
82
@@ -XXX,XX +XXX,XX @@ void kvm_init_cpu_signals(CPUState *cpu)
83
{
71
{
84
abort();
72
@@ -XXX,XX +XXX,XX @@ static inline uint64_t regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
73
}
74
if (mmu_idx == ARMMMUIdx_Stage2_S) {
75
/*
76
- * Note: Secure stage 2 nominally shares fields from VTCR_EL2, but
77
- * those are not currently used by QEMU, so just return VSTCR_EL2.
78
+ * Secure stage 2 shares fields from VTCR_EL2. We merge those
79
+ * in with the VSTCR_EL2 value to synthesize a single VTCR_EL2 format
80
+ * value so the callers don't need to special case this.
81
+ *
82
+ * If a future architecture change defines bits in VSTCR_EL2 that
83
+ * overlap with these VTCR_EL2 fields we may need to revisit this.
84
*/
85
- return env->cp15.vstcr_el2;
86
+ uint64_t v = env->cp15.vstcr_el2 & ~VTCR_SHARED_FIELD_MASK;
87
+ v |= env->cp15.vtcr_el2 & VTCR_SHARED_FIELD_MASK;
88
+ return v;
89
}
90
return env->cp15.tcr_el[regime_el(env, mmu_idx)];
85
}
91
}
86
+
87
+bool kvm_arm_supports_user_irq(void)
88
+{
89
+ return false;
90
+}
91
#endif
92
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
93
index XXXXXXX..XXXXXXX 100644
94
--- a/hw/intc/arm_gic.c
95
+++ b/hw/intc/arm_gic.c
96
@@ -XXX,XX +XXX,XX @@
97
#include "qom/cpu.h"
98
#include "qemu/log.h"
99
#include "trace.h"
100
+#include "sysemu/kvm.h"
101
102
/* #define DEBUG_GIC */
103
104
@@ -XXX,XX +XXX,XX @@ static void arm_gic_realize(DeviceState *dev, Error **errp)
105
return;
106
}
107
108
+ if (kvm_enabled() && !kvm_arm_supports_user_irq()) {
109
+ error_setg(errp, "KVM with user space irqchip only works when the "
110
+ "host kernel supports KVM_CAP_ARM_USER_IRQ");
111
+ return;
112
+ }
113
+
114
/* This creates distributor and main CPU interface (s->cpuiomem[0]) */
115
gic_init_irqs_and_mmio(s, gic_set_irq, gic_ops);
116
117
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/target/arm/kvm.c
120
+++ b/target/arm/kvm.c
121
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init(MachineState *ms, KVMState *s)
122
*/
123
kvm_async_interrupts_allowed = true;
124
125
+ /*
126
+ * PSCI wakes up secondary cores, so we always need to
127
+ * have vCPUs waiting in kernel space
128
+ */
129
+ kvm_halt_in_kernel_allowed = true;
130
+
131
cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
132
133
type_register_static(&host_arm_cpu_type_info);
134
@@ -XXX,XX +XXX,XX @@ void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
135
136
MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
137
{
138
+ ARMCPU *cpu;
139
+ uint32_t switched_level;
140
+
141
+ if (kvm_irqchip_in_kernel()) {
142
+ /*
143
+ * We only need to sync timer states with user-space interrupt
144
+ * controllers, so return early and save cycles if we don't.
145
+ */
146
+ return MEMTXATTRS_UNSPECIFIED;
147
+ }
148
+
149
+ cpu = ARM_CPU(cs);
150
+
151
+ /* Synchronize our shadowed in-kernel device irq lines with the kvm ones */
152
+ if (run->s.regs.device_irq_level != cpu->device_irq_level) {
153
+ switched_level = cpu->device_irq_level ^ run->s.regs.device_irq_level;
154
+
155
+ qemu_mutex_lock_iothread();
156
+
157
+ if (switched_level & KVM_ARM_DEV_EL1_VTIMER) {
158
+ qemu_set_irq(cpu->gt_timer_outputs[GTIMER_VIRT],
159
+ !!(run->s.regs.device_irq_level &
160
+ KVM_ARM_DEV_EL1_VTIMER));
161
+ switched_level &= ~KVM_ARM_DEV_EL1_VTIMER;
162
+ }
163
+
164
+ if (switched_level & KVM_ARM_DEV_EL1_PTIMER) {
165
+ qemu_set_irq(cpu->gt_timer_outputs[GTIMER_PHYS],
166
+ !!(run->s.regs.device_irq_level &
167
+ KVM_ARM_DEV_EL1_PTIMER));
168
+ switched_level &= ~KVM_ARM_DEV_EL1_PTIMER;
169
+ }
170
+
171
+ /* XXX PMU IRQ is missing */
172
+
173
+ if (switched_level) {
174
+ qemu_log_mask(LOG_UNIMP, "%s: unhandled in-kernel device IRQ %x\n",
175
+ __func__, switched_level);
176
+ }
177
+
178
+ /* We also mark unknown levels as processed to not waste cycles */
179
+ cpu->device_irq_level = run->s.regs.device_irq_level;
180
+ qemu_mutex_unlock_iothread();
181
+ }
182
+
183
return MEMTXATTRS_UNSPECIFIED;
184
}
185
186
--
92
--
187
2.7.4
93
2.25.1
188
189
diff view generated by jsdifflib
New patch
1
From: Hao Wu <wuhaotsh@google.com>
1
2
3
The correct bit for the CONV bit in NPCM7XX ADC is bit 13. This patch
4
fixes that in the module, and also lower the IRQ when the guest
5
is done handling an interrupt event from the ADC module.
6
7
Signed-off-by: Hao Wu <wuhaotsh@google.com>
8
Reviewed-by: Patrick Venture<venture@google.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20220714182836.89602-4-wuhaotsh@google.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/adc/npcm7xx_adc.c | 2 +-
14
tests/qtest/npcm7xx_adc-test.c | 2 +-
15
2 files changed, 2 insertions(+), 2 deletions(-)
16
17
diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/adc/npcm7xx_adc.c
20
+++ b/hw/adc/npcm7xx_adc.c
21
@@ -XXX,XX +XXX,XX @@ REG32(NPCM7XX_ADC_DATA, 0x4)
22
#define NPCM7XX_ADC_CON_INT BIT(18)
23
#define NPCM7XX_ADC_CON_EN BIT(17)
24
#define NPCM7XX_ADC_CON_RST BIT(16)
25
-#define NPCM7XX_ADC_CON_CONV BIT(14)
26
+#define NPCM7XX_ADC_CON_CONV BIT(13)
27
#define NPCM7XX_ADC_CON_DIV(rv) extract32(rv, 1, 8)
28
29
#define NPCM7XX_ADC_MAX_RESULT 1023
30
diff --git a/tests/qtest/npcm7xx_adc-test.c b/tests/qtest/npcm7xx_adc-test.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/tests/qtest/npcm7xx_adc-test.c
33
+++ b/tests/qtest/npcm7xx_adc-test.c
34
@@ -XXX,XX +XXX,XX @@
35
#define CON_INT BIT(18)
36
#define CON_EN BIT(17)
37
#define CON_RST BIT(16)
38
-#define CON_CONV BIT(14)
39
+#define CON_CONV BIT(13)
40
#define CON_DIV(rv) extract32(rv, 1, 8)
41
42
#define FST_RDST BIT(1)
43
--
44
2.25.1
diff view generated by jsdifflib
New patch
1
From: Hao Wu <wuhaotsh@google.com>
1
2
3
Our sensor test requires both reading and writing from a sensor's
4
QOM property. So we need to make the input of ADC module R/W instead
5
of write only for that to work.
6
7
Signed-off-by: Hao Wu <wuhaotsh@google.com>
8
Reviewed-by: Titus Rwantare <titusr@google.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20220714182836.89602-5-wuhaotsh@google.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/adc/npcm7xx_adc.c | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/adc/npcm7xx_adc.c
19
+++ b/hw/adc/npcm7xx_adc.c
20
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_adc_init(Object *obj)
21
22
for (i = 0; i < NPCM7XX_ADC_NUM_INPUTS; ++i) {
23
object_property_add_uint32_ptr(obj, "adci[*]",
24
- &s->adci[i], OBJ_PROP_FLAG_WRITE);
25
+ &s->adci[i], OBJ_PROP_FLAG_READWRITE);
26
}
27
object_property_add_uint32_ptr(obj, "vref",
28
&s->vref, OBJ_PROP_FLAG_WRITE);
29
--
30
2.25.1
diff view generated by jsdifflib
New patch
1
The architecture requires that for faults on loads and stores which
2
do writeback, the syndrome information does not have the ISS
3
instruction syndrome information (i.e. ISV is 0). We got this wrong
4
for the load and store instructions covered by disas_ldst_reg_imm9().
5
Calculate iss_valid correctly so that if the insn is a writeback one
6
it is false.
1
7
8
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1057
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220715123323.1550983-1-peter.maydell@linaro.org
12
---
13
target/arm/translate-a64.c | 4 +++-
14
1 file changed, 3 insertions(+), 1 deletion(-)
15
16
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate-a64.c
19
+++ b/target/arm/translate-a64.c
20
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
21
bool is_store = false;
22
bool is_extended = false;
23
bool is_unpriv = (idx == 2);
24
- bool iss_valid = !is_vector;
25
+ bool iss_valid;
26
bool post_index;
27
bool writeback;
28
int memidx;
29
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
30
g_assert_not_reached();
31
}
32
33
+ iss_valid = !is_vector && !writeback;
34
+
35
if (rn == 31) {
36
gen_check_sp_alignment(s);
37
}
38
--
39
2.25.1
diff view generated by jsdifflib
1
From: Krzysztof Kozlowski <krzk@kernel.org>
1
From: Andrey Makarov <ph.makarov@gmail.com>
2
2
3
Add emulation for Exynos4210 Pseudo Random Number Generator which could
3
There is nothing in the specs on DMA engine interrupt lines: it should have
4
work on fixed seeds or with seeds provided by True Random Number
4
been in the "BCM2835 ARM Peripherals" datasheet but the appropriate
5
Generator block inside the SoC.
5
"ARM peripherals interrupt table" (p.113) is nearly empty.
6
6
7
Implement only the fixed seeds part of it in polling mode (no
7
All Raspberry Pi models 1-3 (based on bcm2835) have
8
interrupts).
8
Linux device tree (arch/arm/boot/dts/bcm2835-common.dtsi +25):
9
9
10
Emulation tested with two independent Linux kernel exynos-rng drivers:
10
/* dma channel 11-14 share one irq */
11
1. New kcapi-rng interface (targeting Linux v4.12),
11
12
2. Old hwrng inteface
12
This information is repeated in the driver code
13
# echo "exynos" > /sys/class/misc/hw_random/rng_current
13
(drivers/dma/bcm2835-dma.c +1344):
14
# dd if=/dev/hwrng of=/dev/null bs=1 count=16
14
15
15
/*
16
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
16
* in case of channel >= 11
17
Message-id: 20170425180609.11004-1-krzk@kernel.org
17
* use the 11th interrupt and that is shared
18
*/
19
20
In this patch channels 0--10 and 11--14 are handled separately.
21
22
Signed-off-by: Andrey Makarov <andrey.makarov@auriga.com>
23
Message-id: 20220716113210.349153-1-andrey.makarov@auriga.com
24
[PMM: fixed checkpatch nits]
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
25
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
[PMM: wrapped a few overlong lines; more efficient implementation
20
of exynos4210_rng_seed_ready()]
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
27
---
23
hw/misc/Makefile.objs | 2 +-
28
include/hw/arm/bcm2835_peripherals.h | 2 +
24
hw/arm/exynos4210.c | 4 +
29
hw/arm/bcm2835_peripherals.c | 26 +++++-
25
hw/misc/exynos4210_rng.c | 277 +++++++++++++++++++++++++++++++++++++++++++++++
30
tests/qtest/bcm2835-dma-test.c | 118 +++++++++++++++++++++++++++
26
3 files changed, 282 insertions(+), 1 deletion(-)
31
tests/qtest/meson.build | 3 +-
27
create mode 100644 hw/misc/exynos4210_rng.c
32
4 files changed, 147 insertions(+), 2 deletions(-)
28
33
create mode 100644 tests/qtest/bcm2835-dma-test.c
29
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
34
35
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
30
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/misc/Makefile.objs
37
--- a/include/hw/arm/bcm2835_peripherals.h
32
+++ b/hw/misc/Makefile.objs
38
+++ b/include/hw/arm/bcm2835_peripherals.h
33
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_IVSHMEM) += ivshmem.o
39
@@ -XXX,XX +XXX,XX @@
34
obj-$(CONFIG_REALVIEW) += arm_sysctl.o
40
#include "hw/char/bcm2835_aux.h"
35
obj-$(CONFIG_NSERIES) += cbus.o
41
#include "hw/display/bcm2835_fb.h"
36
obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
42
#include "hw/dma/bcm2835_dma.h"
37
-obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o exynos4210_clk.o
43
+#include "hw/or-irq.h"
38
+obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o exynos4210_clk.o exynos4210_rng.o
44
#include "hw/intc/bcm2835_ic.h"
39
obj-$(CONFIG_IMX) += imx_ccm.o
45
#include "hw/misc/bcm2835_property.h"
40
obj-$(CONFIG_IMX) += imx31_ccm.o
46
#include "hw/misc/bcm2835_rng.h"
41
obj-$(CONFIG_IMX) += imx25_ccm.o
47
@@ -XXX,XX +XXX,XX @@ struct BCM2835PeripheralState {
42
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
48
BCM2835AuxState aux;
49
BCM2835FBState fb;
50
BCM2835DMAState dma;
51
+ qemu_or_irq orgated_dma_irq;
52
BCM2835ICState ic;
53
BCM2835PropertyState property;
54
BCM2835RngState rng;
55
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
43
index XXXXXXX..XXXXXXX 100644
56
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/arm/exynos4210.c
57
--- a/hw/arm/bcm2835_peripherals.c
45
+++ b/hw/arm/exynos4210.c
58
+++ b/hw/arm/bcm2835_peripherals.c
46
@@ -XXX,XX +XXX,XX @@
59
@@ -XXX,XX +XXX,XX @@
47
/* Clock controller SFR base address */
60
/* Capabilities for SD controller: no DMA, high-speed, default clocks etc. */
48
#define EXYNOS4210_CLK_BASE_ADDR 0x10030000
61
#define BCM2835_SDHC_CAPAREG 0x52134b4
49
62
50
+/* PRNG/HASH SFR base address */
63
+/*
51
+#define EXYNOS4210_RNG_BASE_ADDR 0x10830400
64
+ * According to Linux driver & DTS, dma channels 0--10 have separate IRQ,
52
+
65
+ * while channels 11--14 share one IRQ:
53
/* Display controllers (FIMD) */
66
+ */
54
#define EXYNOS4210_FIMD0_BASE_ADDR 0x11C00000
67
+#define SEPARATE_DMA_IRQ_MAX 10
55
68
+#define ORGATED_DMA_IRQ_COUNT 4
56
@@ -XXX,XX +XXX,XX @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem)
69
+
57
sysbus_create_simple("exynos4210.pmu", EXYNOS4210_PMU_BASE_ADDR, NULL);
70
static void create_unimp(BCM2835PeripheralState *ps,
58
71
UnimplementedDeviceState *uds,
59
sysbus_create_simple("exynos4210.clk", EXYNOS4210_CLK_BASE_ADDR, NULL);
72
const char *name, hwaddr ofs, hwaddr size)
60
+ sysbus_create_simple("exynos4210.rng", EXYNOS4210_RNG_BASE_ADDR, NULL);
73
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
61
74
/* DMA Channels */
62
/* PWM */
75
object_initialize_child(obj, "dma", &s->dma, TYPE_BCM2835_DMA);
63
sysbus_create_varargs("exynos4210.pwm", EXYNOS4210_PWM_BASE_ADDR,
76
64
diff --git a/hw/misc/exynos4210_rng.c b/hw/misc/exynos4210_rng.c
77
+ object_initialize_child(obj, "orgated-dma-irq",
78
+ &s->orgated_dma_irq, TYPE_OR_IRQ);
79
+ object_property_set_int(OBJECT(&s->orgated_dma_irq), "num-lines",
80
+ ORGATED_DMA_IRQ_COUNT, &error_abort);
81
+
82
object_property_add_const_link(OBJECT(&s->dma), "dma-mr",
83
OBJECT(&s->gpu_bus_mr));
84
85
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
86
memory_region_add_subregion(&s->peri_mr, DMA15_OFFSET,
87
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dma), 1));
88
89
- for (n = 0; n <= 12; n++) {
90
+ for (n = 0; n <= SEPARATE_DMA_IRQ_MAX; n++) {
91
sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), n,
92
qdev_get_gpio_in_named(DEVICE(&s->ic),
93
BCM2835_IC_GPU_IRQ,
94
INTERRUPT_DMA0 + n));
95
}
96
+ if (!qdev_realize(DEVICE(&s->orgated_dma_irq), NULL, errp)) {
97
+ return;
98
+ }
99
+ for (n = 0; n < ORGATED_DMA_IRQ_COUNT; n++) {
100
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma),
101
+ SEPARATE_DMA_IRQ_MAX + 1 + n,
102
+ qdev_get_gpio_in(DEVICE(&s->orgated_dma_irq), n));
103
+ }
104
+ qdev_connect_gpio_out(DEVICE(&s->orgated_dma_irq), 0,
105
+ qdev_get_gpio_in_named(DEVICE(&s->ic),
106
+ BCM2835_IC_GPU_IRQ,
107
+ INTERRUPT_DMA0 + SEPARATE_DMA_IRQ_MAX + 1));
108
109
/* THERMAL */
110
if (!sysbus_realize(SYS_BUS_DEVICE(&s->thermal), errp)) {
111
diff --git a/tests/qtest/bcm2835-dma-test.c b/tests/qtest/bcm2835-dma-test.c
65
new file mode 100644
112
new file mode 100644
66
index XXXXXXX..XXXXXXX
113
index XXXXXXX..XXXXXXX
67
--- /dev/null
114
--- /dev/null
68
+++ b/hw/misc/exynos4210_rng.c
115
+++ b/tests/qtest/bcm2835-dma-test.c
69
@@ -XXX,XX +XXX,XX @@
116
@@ -XXX,XX +XXX,XX @@
70
+/*
117
+/*
71
+ * Exynos4210 Pseudo Random Nubmer Generator Emulation
118
+ * QTest testcase for BCM283x DMA engine (on Raspberry Pi 3)
119
+ * and its interrupts coming to Interrupt Controller.
72
+ *
120
+ *
73
+ * Copyright (c) 2017 Krzysztof Kozlowski <krzk@kernel.org>
121
+ * Copyright (c) 2022 Auriga LLC
74
+ *
122
+ *
75
+ * This program is free software; you can redistribute it and/or modify it
123
+ * SPDX-License-Identifier: GPL-2.0-or-later
76
+ * under the terms of the GNU General Public License as published by the
77
+ * 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, but WITHOUT
81
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
82
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
83
+ * for more details.
84
+ *
85
+ * You should have received a copy of the GNU General Public License along
86
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
87
+ */
124
+ */
88
+
125
+
89
+#include "qemu/osdep.h"
126
+#include "qemu/osdep.h"
90
+#include "crypto/random.h"
127
+#include "libqtest-single.h"
91
+#include "hw/sysbus.h"
128
+
92
+#include "qemu/log.h"
129
+/* Offsets in raspi3b platform: */
93
+
130
+#define RASPI3_DMA_BASE 0x3f007000
94
+#define DEBUG_EXYNOS_RNG 0
131
+#define RASPI3_IC_BASE 0x3f00b200
95
+
132
+
96
+#define DPRINTF(fmt, ...) \
133
+/* Used register/fields definitions */
97
+ do { \
134
+
98
+ if (DEBUG_EXYNOS_RNG) { \
135
+/* DMA engine registers: */
99
+ printf("exynos4210_rng: " fmt, ## __VA_ARGS__); \
136
+#define BCM2708_DMA_CS 0
100
+ } \
137
+#define BCM2708_DMA_ACTIVE (1 << 0)
101
+ } while (0)
138
+#define BCM2708_DMA_INT (1 << 2)
102
+
139
+
103
+#define TYPE_EXYNOS4210_RNG "exynos4210.rng"
140
+#define BCM2708_DMA_ADDR 0x04
104
+#define EXYNOS4210_RNG(obj) \
141
+
105
+ OBJECT_CHECK(Exynos4210RngState, (obj), TYPE_EXYNOS4210_RNG)
142
+#define BCM2708_DMA_INT_STATUS 0xfe0
106
+
143
+
107
+/*
144
+/* DMA Trasfer Info fields: */
108
+ * Exynos4220, PRNG, only polling mode is supported.
145
+#define BCM2708_DMA_INT_EN (1 << 0)
109
+ */
146
+#define BCM2708_DMA_D_INC (1 << 4)
110
+
147
+#define BCM2708_DMA_S_INC (1 << 8)
111
+/* RNG_CONTROL_1 register bitfields, reset value: 0x0 */
148
+
112
+#define EXYNOS4210_RNG_CONTROL_1_PRNG 0x8
149
+/* Interrupt controller registers: */
113
+#define EXYNOS4210_RNG_CONTROL_1_START_INIT BIT(4)
150
+#define IRQ_PENDING_BASIC 0x00
114
+/* RNG_STATUS register bitfields, reset value: 0x1 */
151
+#define IRQ_GPU_PENDING1_AGGR (1 << 8)
115
+#define EXYNOS4210_RNG_STATUS_PRNG_ERROR BIT(7)
152
+#define IRQ_PENDING_1 0x04
116
+#define EXYNOS4210_RNG_STATUS_PRNG_DONE BIT(5)
153
+#define IRQ_ENABLE_1 0x10
117
+#define EXYNOS4210_RNG_STATUS_MSG_DONE BIT(4)
154
+
118
+#define EXYNOS4210_RNG_STATUS_PARTIAL_DONE BIT(3)
155
+/* Data for the test: */
119
+#define EXYNOS4210_RNG_STATUS_PRNG_BUSY BIT(2)
156
+#define SCB_ADDR 256
120
+#define EXYNOS4210_RNG_STATUS_SEED_SETTING_DONE BIT(1)
157
+#define S_ADDR 32
121
+#define EXYNOS4210_RNG_STATUS_BUFFER_READY BIT(0)
158
+#define D_ADDR 64
122
+#define EXYNOS4210_RNG_STATUS_WRITE_MASK (EXYNOS4210_RNG_STATUS_PRNG_DONE \
159
+#define TXFR_LEN 32
123
+ | EXYNOS4210_RNG_STATUS_MSG_DONE \
160
+const uint32_t check_data = 0x12345678;
124
+ | EXYNOS4210_RNG_STATUS_PARTIAL_DONE)
161
+
125
+
162
+static void bcm2835_dma_test_interrupt(int dma_c, int irq_line)
126
+#define EXYNOS4210_RNG_CONTROL_1 0x0
127
+#define EXYNOS4210_RNG_STATUS 0x10
128
+#define EXYNOS4210_RNG_SEED_IN 0x140
129
+#define EXYNOS4210_RNG_SEED_IN_OFFSET(n) (EXYNOS4210_RNG_SEED_IN + (n * 0x4))
130
+#define EXYNOS4210_RNG_PRNG 0x160
131
+#define EXYNOS4210_RNG_PRNG_OFFSET(n) (EXYNOS4210_RNG_PRNG + (n * 0x4))
132
+
133
+#define EXYNOS4210_RNG_PRNG_NUM 5
134
+
135
+#define EXYNOS4210_RNG_REGS_MEM_SIZE 0x200
136
+
137
+typedef struct Exynos4210RngState {
138
+ SysBusDevice parent_obj;
139
+ MemoryRegion iomem;
140
+
141
+ int32_t randr_value[EXYNOS4210_RNG_PRNG_NUM];
142
+ /* bits from 0 to EXYNOS4210_RNG_PRNG_NUM if given seed register was set */
143
+ uint32_t seed_set;
144
+
145
+ /* Register values */
146
+ uint32_t reg_control;
147
+ uint32_t reg_status;
148
+} Exynos4210RngState;
149
+
150
+static bool exynos4210_rng_seed_ready(const Exynos4210RngState *s)
151
+{
163
+{
152
+ uint32_t mask = MAKE_64BIT_MASK(0, EXYNOS4210_RNG_PRNG_NUM);
164
+ uint64_t dma_base = RASPI3_DMA_BASE + dma_c * 0x100;
153
+
165
+ int gpu_irq_line = 16 + irq_line;
154
+ /* Return true if all the seed-set bits are set. */
166
+
155
+ return (s->seed_set & mask) == mask;
167
+ /* Check that interrupts are silent by default: */
168
+ writel(RASPI3_IC_BASE + IRQ_ENABLE_1, 1 << gpu_irq_line);
169
+ int isr = readl(dma_base + BCM2708_DMA_INT_STATUS);
170
+ g_assert_cmpint(isr, ==, 0);
171
+ uint32_t reg0 = readl(dma_base + BCM2708_DMA_CS);
172
+ g_assert_cmpint(reg0, ==, 0);
173
+ uint32_t ic_pending = readl(RASPI3_IC_BASE + IRQ_PENDING_BASIC);
174
+ g_assert_cmpint(ic_pending, ==, 0);
175
+ uint32_t gpu_pending1 = readl(RASPI3_IC_BASE + IRQ_PENDING_1);
176
+ g_assert_cmpint(gpu_pending1, ==, 0);
177
+
178
+ /* Prepare Control Block: */
179
+ writel(SCB_ADDR + 0, BCM2708_DMA_S_INC | BCM2708_DMA_D_INC |
180
+ BCM2708_DMA_INT_EN); /* transfer info */
181
+ writel(SCB_ADDR + 4, S_ADDR); /* source address */
182
+ writel(SCB_ADDR + 8, D_ADDR); /* destination address */
183
+ writel(SCB_ADDR + 12, TXFR_LEN); /* transfer length */
184
+ writel(dma_base + BCM2708_DMA_ADDR, SCB_ADDR);
185
+
186
+ writel(S_ADDR, check_data);
187
+ for (int word = S_ADDR + 4; word < S_ADDR + TXFR_LEN; word += 4) {
188
+ writel(word, ~check_data);
189
+ }
190
+ /* Perform the transfer: */
191
+ writel(dma_base + BCM2708_DMA_CS, BCM2708_DMA_ACTIVE);
192
+
193
+ /* Check that destination == source: */
194
+ uint32_t data = readl(D_ADDR);
195
+ g_assert_cmpint(data, ==, check_data);
196
+ for (int word = D_ADDR + 4; word < D_ADDR + TXFR_LEN; word += 4) {
197
+ data = readl(word);
198
+ g_assert_cmpint(data, ==, ~check_data);
199
+ }
200
+
201
+ /* Check that interrupt status is set both in DMA and IC controllers: */
202
+ isr = readl(RASPI3_DMA_BASE + BCM2708_DMA_INT_STATUS);
203
+ g_assert_cmpint(isr, ==, 1 << dma_c);
204
+
205
+ ic_pending = readl(RASPI3_IC_BASE + IRQ_PENDING_BASIC);
206
+ g_assert_cmpint(ic_pending, ==, IRQ_GPU_PENDING1_AGGR);
207
+
208
+ gpu_pending1 = readl(RASPI3_IC_BASE + IRQ_PENDING_1);
209
+ g_assert_cmpint(gpu_pending1, ==, 1 << gpu_irq_line);
210
+
211
+ /* Clean up, clear interrupt: */
212
+ writel(dma_base + BCM2708_DMA_CS, BCM2708_DMA_INT);
156
+}
213
+}
157
+
214
+
158
+static void exynos4210_rng_set_seed(Exynos4210RngState *s, unsigned int i,
215
+static void bcm2835_dma_test_interrupts(void)
159
+ uint64_t val)
160
+{
216
+{
161
+ /*
217
+ /* DMA engines 0--10 have separate IRQ lines, 11--14 - only one: */
162
+ * We actually ignore the seed and always generate true random numbers.
218
+ bcm2835_dma_test_interrupt(0, 0);
163
+ * Theoretically this should not match the device as Exynos has
219
+ bcm2835_dma_test_interrupt(10, 10);
164
+ * a Pseudo Random Number Generator but testing shown that it always
220
+ bcm2835_dma_test_interrupt(11, 11);
165
+ * generates random numbers regardless of the seed value.
221
+ bcm2835_dma_test_interrupt(14, 11);
166
+ */
167
+ s->seed_set |= BIT(i);
168
+
169
+ /* If all seeds were written, update the status to reflect it */
170
+ if (exynos4210_rng_seed_ready(s)) {
171
+ s->reg_status |= EXYNOS4210_RNG_STATUS_SEED_SETTING_DONE;
172
+ } else {
173
+ s->reg_status &= ~EXYNOS4210_RNG_STATUS_SEED_SETTING_DONE;
174
+ }
175
+}
222
+}
176
+
223
+
177
+static void exynos4210_rng_run_engine(Exynos4210RngState *s)
224
+int main(int argc, char **argv)
178
+{
225
+{
179
+ Error *err = NULL;
180
+ int ret;
226
+ int ret;
181
+
227
+ g_test_init(&argc, &argv, NULL);
182
+ /* Seed set? */
228
+ qtest_add_func("/bcm2835/dma/test_interrupts",
183
+ if ((s->reg_status & EXYNOS4210_RNG_STATUS_SEED_SETTING_DONE) == 0) {
229
+ bcm2835_dma_test_interrupts);
184
+ goto out;
230
+ qtest_start("-machine raspi3b");
185
+ }
231
+ ret = g_test_run();
186
+
232
+ qtest_end();
187
+ /* PRNG engine chosen? */
233
+ return ret;
188
+ if ((s->reg_control & EXYNOS4210_RNG_CONTROL_1_PRNG) == 0) {
189
+ goto out;
190
+ }
191
+
192
+ /* PRNG engine started? */
193
+ if ((s->reg_control & EXYNOS4210_RNG_CONTROL_1_START_INIT) == 0) {
194
+ goto out;
195
+ }
196
+
197
+ /* Get randoms */
198
+ ret = qcrypto_random_bytes((uint8_t *)s->randr_value,
199
+ sizeof(s->randr_value), &err);
200
+ if (!ret) {
201
+ /* Notify that PRNG is ready */
202
+ s->reg_status |= EXYNOS4210_RNG_STATUS_PRNG_DONE;
203
+ } else {
204
+ error_report_err(err);
205
+ }
206
+
207
+out:
208
+ /* Always clear start engine bit */
209
+ s->reg_control &= ~EXYNOS4210_RNG_CONTROL_1_START_INIT;
210
+}
234
+}
211
+
235
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
212
+static uint64_t exynos4210_rng_read(void *opaque, hwaddr offset,
236
index XXXXXXX..XXXXXXX 100644
213
+ unsigned size)
237
--- a/tests/qtest/meson.build
214
+{
238
+++ b/tests/qtest/meson.build
215
+ Exynos4210RngState *s = (Exynos4210RngState *)opaque;
239
@@ -XXX,XX +XXX,XX @@ qtests_aarch64 = \
216
+ uint32_t val = 0;
240
['arm-cpu-features',
217
+
241
'numa-test',
218
+ assert(size == 4);
242
'boot-serial-test',
219
+
243
- 'migration-test']
220
+ switch (offset) {
244
+ 'migration-test',
221
+ case EXYNOS4210_RNG_CONTROL_1:
245
+ 'bcm2835-dma-test']
222
+ val = s->reg_control;
246
223
+ break;
247
qtests_s390x = \
224
+
248
(slirp.found() ? ['pxe-test', 'test-netfilter'] : []) + \
225
+ case EXYNOS4210_RNG_STATUS:
226
+ val = s->reg_status;
227
+ break;
228
+
229
+ case EXYNOS4210_RNG_PRNG_OFFSET(0):
230
+ case EXYNOS4210_RNG_PRNG_OFFSET(1):
231
+ case EXYNOS4210_RNG_PRNG_OFFSET(2):
232
+ case EXYNOS4210_RNG_PRNG_OFFSET(3):
233
+ case EXYNOS4210_RNG_PRNG_OFFSET(4):
234
+ val = s->randr_value[(offset - EXYNOS4210_RNG_PRNG_OFFSET(0)) / 4];
235
+ DPRINTF("returning random @0x%" HWADDR_PRIx ": 0x%" PRIx32 "\n",
236
+ offset, val);
237
+ break;
238
+
239
+ default:
240
+ qemu_log_mask(LOG_GUEST_ERROR,
241
+ "%s: bad read offset 0x%" HWADDR_PRIx "\n",
242
+ __func__, offset);
243
+ }
244
+
245
+ return val;
246
+}
247
+
248
+static void exynos4210_rng_write(void *opaque, hwaddr offset,
249
+ uint64_t val, unsigned size)
250
+{
251
+ Exynos4210RngState *s = (Exynos4210RngState *)opaque;
252
+
253
+ assert(size == 4);
254
+
255
+ switch (offset) {
256
+ case EXYNOS4210_RNG_CONTROL_1:
257
+ DPRINTF("RNG_CONTROL_1 = 0x%" PRIx64 "\n", val);
258
+ s->reg_control = val;
259
+ exynos4210_rng_run_engine(s);
260
+ break;
261
+
262
+ case EXYNOS4210_RNG_STATUS:
263
+ /* For clearing status fields */
264
+ s->reg_status &= ~EXYNOS4210_RNG_STATUS_WRITE_MASK;
265
+ s->reg_status |= val & EXYNOS4210_RNG_STATUS_WRITE_MASK;
266
+ break;
267
+
268
+ case EXYNOS4210_RNG_SEED_IN_OFFSET(0):
269
+ case EXYNOS4210_RNG_SEED_IN_OFFSET(1):
270
+ case EXYNOS4210_RNG_SEED_IN_OFFSET(2):
271
+ case EXYNOS4210_RNG_SEED_IN_OFFSET(3):
272
+ case EXYNOS4210_RNG_SEED_IN_OFFSET(4):
273
+ exynos4210_rng_set_seed(s,
274
+ (offset - EXYNOS4210_RNG_SEED_IN_OFFSET(0)) / 4,
275
+ val);
276
+ break;
277
+
278
+ default:
279
+ qemu_log_mask(LOG_GUEST_ERROR,
280
+ "%s: bad write offset 0x%" HWADDR_PRIx "\n",
281
+ __func__, offset);
282
+ }
283
+}
284
+
285
+static const MemoryRegionOps exynos4210_rng_ops = {
286
+ .read = exynos4210_rng_read,
287
+ .write = exynos4210_rng_write,
288
+ .endianness = DEVICE_NATIVE_ENDIAN,
289
+};
290
+
291
+static void exynos4210_rng_reset(DeviceState *dev)
292
+{
293
+ Exynos4210RngState *s = EXYNOS4210_RNG(dev);
294
+
295
+ s->reg_control = 0;
296
+ s->reg_status = EXYNOS4210_RNG_STATUS_BUFFER_READY;
297
+ memset(s->randr_value, 0, sizeof(s->randr_value));
298
+ s->seed_set = 0;
299
+}
300
+
301
+static void exynos4210_rng_init(Object *obj)
302
+{
303
+ Exynos4210RngState *s = EXYNOS4210_RNG(obj);
304
+ SysBusDevice *dev = SYS_BUS_DEVICE(obj);
305
+
306
+ memory_region_init_io(&s->iomem, obj, &exynos4210_rng_ops, s,
307
+ TYPE_EXYNOS4210_RNG, EXYNOS4210_RNG_REGS_MEM_SIZE);
308
+ sysbus_init_mmio(dev, &s->iomem);
309
+}
310
+
311
+static const VMStateDescription exynos4210_rng_vmstate = {
312
+ .name = TYPE_EXYNOS4210_RNG,
313
+ .version_id = 1,
314
+ .minimum_version_id = 1,
315
+ .fields = (VMStateField[]) {
316
+ VMSTATE_INT32_ARRAY(randr_value, Exynos4210RngState,
317
+ EXYNOS4210_RNG_PRNG_NUM),
318
+ VMSTATE_UINT32(seed_set, Exynos4210RngState),
319
+ VMSTATE_UINT32(reg_status, Exynos4210RngState),
320
+ VMSTATE_UINT32(reg_control, Exynos4210RngState),
321
+ VMSTATE_END_OF_LIST()
322
+ }
323
+};
324
+
325
+static void exynos4210_rng_class_init(ObjectClass *klass, void *data)
326
+{
327
+ DeviceClass *dc = DEVICE_CLASS(klass);
328
+
329
+ dc->reset = exynos4210_rng_reset;
330
+ dc->vmsd = &exynos4210_rng_vmstate;
331
+}
332
+
333
+static const TypeInfo exynos4210_rng_info = {
334
+ .name = TYPE_EXYNOS4210_RNG,
335
+ .parent = TYPE_SYS_BUS_DEVICE,
336
+ .instance_size = sizeof(Exynos4210RngState),
337
+ .instance_init = exynos4210_rng_init,
338
+ .class_init = exynos4210_rng_class_init,
339
+};
340
+
341
+static void exynos4210_rng_register(void)
342
+{
343
+ type_register_static(&exynos4210_rng_info);
344
+}
345
+
346
+type_init(exynos4210_rng_register)
347
--
249
--
348
2.7.4
250
2.25.1
349
350
diff view generated by jsdifflib