1
ARM queu; includes all the NVIC rewrite patches.
1
Hi; this mostly contains the first slice of A64 decodetree
2
The QOMify-armv7m patchset hasn't got enough review just
2
patches, plus some other minor pieces. It also has the
3
yet but I may be able to sneak it in before freeze
3
enablement of MTE for KVM guests.
4
tomorrow if it gets review. Didn't want to hold this lot
5
up waiting, anyway.
6
4
7
thanks
5
thanks
8
-- PMM
6
-- PMM
9
7
8
The following changes since commit d27e7c359330ba7020bdbed7ed2316cb4cf6ffc1:
10
9
11
The following changes since commit 8f2d7c341184a95d05476ea3c45dbae2b9ddbe51:
10
qapi/parser: Drop two bad type hints for now (2023-05-17 10:18:33 -0700)
12
11
13
Merge remote-tracking branch 'remotes/berrange/tags/pull-qcrypto-2017-02-27-1' into staging (2017-02-27 15:33:21 +0000)
12
are available in the Git repository at:
14
13
15
are available in the git repository at:
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20230518
16
15
17
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20170227
16
for you to fetch changes up to 91608e2a44f36e79cb83f863b8a7bb57d2c98061:
18
17
19
for you to fetch changes up to 94d5bcf5a7f3799660b62098a5183f161aad0601:
18
docs: Convert u2f.txt to rST (2023-05-18 11:40:32 +0100)
20
21
hw/arm/exynos: Fix proper mapping of CPUs by providing real cluster ID (2017-02-27 17:23:16 +0000)
22
19
23
----------------------------------------------------------------
20
----------------------------------------------------------------
24
target-arm queue:
21
target-arm queue:
25
* raspi2: implement RNG module, GPIO and new SD card controller
22
* Fix vd == vm overlap in sve_ldff1_z
26
(sufficient to boot new raspbian kernels)
23
* Add support for MTE with KVM guests
27
* sdhci: bugfixes for block transfers
24
* Add RAZ/WI handling for DBGDTR[TX|RX]
28
* virt: fix cpu object reference leak
25
* Start of conversion of A64 decoder to decodetree
29
* Add missing fp_access_check() to aarch64 crypto instructions
26
* Saturate L2CTLR_EL1 core count field rather than overflowing
30
* cputlb: Don't assume do_unassigned_access() never returns
27
* vexpress: Avoid trivial memory leak of 'flashalias'
31
* virt: Add a user option to disallow ITS instantiation
28
* sbsa-ref: switch default cpu core to Neoverse-N1
32
* i.MX timers: fix reset handling
29
* sbsa-ref: use Bochs graphics card instead of VGA
33
* ARMv7M NVIC: rewrite to fix broken priority handling and masking
30
* MAINTAINERS: Add Marcin Juszkiewicz to sbsa-ref reviewer list
34
* exynos: Fix proper mapping of CPUs by providing real cluster ID
31
* docs: Convert u2f.txt to rST
35
* exynos: Fix Linux kernel division by zero for PLLs
36
32
37
----------------------------------------------------------------
33
----------------------------------------------------------------
38
Clement Deschamps (4):
34
Alex Bennée (1):
39
bcm2835_sdhost: add bcm2835 sdhost controller
35
target/arm: add RAZ/WI handling for DBGDTR[TX|RX]
40
hw/sd: add card-reparenting function
41
bcm2835_gpio: add bcm2835 gpio controller
42
bcm2835: add sdhost and gpio controllers
43
36
44
Eric Auger (1):
37
Cornelia Huck (1):
45
hw/arm/virt: Add a user option to disallow ITS instantiation
38
arm/kvm: add support for MTE
46
39
47
Igor Mammedov (1):
40
Marcin Juszkiewicz (3):
48
hw/arm/virt: fix cpu object reference leak
41
sbsa-ref: switch default cpu core to Neoverse-N1
42
Maintainers: add myself as reviewer for sbsa-ref
43
sbsa-ref: use Bochs graphics card instead of VGA
49
44
50
Krzysztof Kozlowski (2):
45
Peter Maydell (14):
51
hw/arm/exynos: Fix Linux kernel division by zero for PLLs
46
target/arm: Create decodetree skeleton for A64
52
hw/arm/exynos: Fix proper mapping of CPUs by providing real cluster ID
47
target/arm: Pull calls to disas_sve() and disas_sme() out of legacy decoder
48
target/arm: Convert Extract instructions to decodetree
49
target/arm: Convert unconditional branch immediate to decodetree
50
target/arm: Convert CBZ, CBNZ to decodetree
51
target/arm: Convert TBZ, TBNZ to decodetree
52
target/arm: Convert conditional branch insns to decodetree
53
target/arm: Convert BR, BLR, RET to decodetree
54
target/arm: Convert BRA[AB]Z, BLR[AB]Z, RETA[AB] to decodetree
55
target/arm: Convert BRAA, BRAB, BLRAA, BLRAB to decodetree
56
target/arm: Convert ERET, ERETAA, ERETAB to decodetree
57
target/arm: Saturate L2CTLR_EL1 core count field rather than overflowing
58
hw/arm/vexpress: Avoid trivial memory leak of 'flashalias'
59
docs: Convert u2f.txt to rST
53
60
54
Kurban Mallachiev (1):
61
Richard Henderson (10):
55
ARM i.MX timers: fix reset handling
62
target/arm: Fix vd == vm overlap in sve_ldff1_z
63
target/arm: Split out disas_a64_legacy
64
target/arm: Convert PC-rel addressing to decodetree
65
target/arm: Split gen_add_CC and gen_sub_CC
66
target/arm: Convert Add/subtract (immediate) to decodetree
67
target/arm: Convert Add/subtract (immediate with tags) to decodetree
68
target/arm: Replace bitmask64 with MAKE_64BIT_MASK
69
target/arm: Convert Logical (immediate) to decodetree
70
target/arm: Convert Move wide (immediate) to decodetree
71
target/arm: Convert Bitfield to decodetree
56
72
57
Marcin Chojnacki (1):
73
MAINTAINERS | 1 +
58
target-arm: Implement BCM2835 hardware RNG
74
docs/system/device-emulation.rst | 1 +
75
docs/system/devices/usb-u2f.rst | 93 +++
76
docs/system/devices/usb.rst | 2 +-
77
docs/u2f.txt | 110 ----
78
target/arm/cpu.h | 4 +
79
target/arm/kvm_arm.h | 19 +
80
target/arm/tcg/translate.h | 5 +
81
target/arm/tcg/a64.decode | 152 +++++
82
hw/arm/sbsa-ref.c | 4 +-
83
hw/arm/vexpress.c | 40 +-
84
hw/arm/virt.c | 73 ++-
85
target/arm/cortex-regs.c | 11 +-
86
target/arm/cpu.c | 9 +-
87
target/arm/debug_helper.c | 11 +-
88
target/arm/kvm.c | 35 +
89
target/arm/kvm64.c | 5 +
90
target/arm/tcg/sve_helper.c | 6 +
91
target/arm/tcg/translate-a64.c | 1321 ++++++++++++++++----------------------
92
target/arm/tcg/meson.build | 1 +
93
20 files changed, 979 insertions(+), 924 deletions(-)
94
create mode 100644 docs/system/devices/usb-u2f.rst
95
delete mode 100644 docs/u2f.txt
96
create mode 100644 target/arm/tcg/a64.decode
59
97
60
Michael Davidsaver (5):
61
armv7m: Rewrite NVIC to not use any GIC code
62
arm: gic: Remove references to NVIC
63
armv7m: Escalate exceptions to HardFault if necessary
64
armv7m: Simpler and faster exception start
65
armv7m: VECTCLRACTIVE and VECTRESET are UNPREDICTABLE
66
67
Nick Reilly (1):
68
Add missing fp_access_check() to aarch64 crypto instructions
69
70
Peter Maydell (10):
71
bcm2835_rng: Use qcrypto_random_bytes() rather than rand()
72
cputlb: Don't assume do_unassigned_access() never returns
73
armv7m: Rename nvic_state to NVICState
74
armv7m: Implement reading and writing of PRIGROUP
75
armv7m: Fix condition check for taking exceptions
76
armv7m: Remove unused armv7m_nvic_acknowledge_irq() return value
77
armv7m: Extract "exception taken" code into functions
78
armv7m: Check exception return consistency
79
armv7m: Raise correct kind of UsageFault for attempts to execute ARM code
80
armv7m: Allow SHCSR writes to change pending and active bits
81
82
Prasad J Pandit (4):
83
sd: sdhci: mask transfer mode register value
84
sd: sdhci: check transfer mode register in multi block transfer
85
sd: sdhci: conditionally invoke multi block transfer
86
sd: sdhci: Remove block count enable check in single block transfers
87
88
hw/gpio/Makefile.objs | 1 +
89
hw/misc/Makefile.objs | 3 +-
90
hw/sd/Makefile.objs | 1 +
91
hw/intc/gic_internal.h | 7 +-
92
include/hw/arm/bcm2835_peripherals.h | 6 +
93
include/hw/arm/virt.h | 1 +
94
include/hw/gpio/bcm2835_gpio.h | 39 ++
95
include/hw/misc/bcm2835_rng.h | 27 ++
96
include/hw/sd/bcm2835_sdhost.h | 48 ++
97
include/hw/sd/sd.h | 11 +
98
target/arm/cpu.h | 23 +-
99
cputlb.c | 15 +-
100
hw/arm/bcm2835_peripherals.c | 58 ++-
101
hw/arm/exynos4210.c | 18 +
102
hw/arm/virt.c | 32 +-
103
hw/gpio/bcm2835_gpio.c | 353 ++++++++++++++
104
hw/intc/arm_gic.c | 31 +-
105
hw/intc/arm_gic_common.c | 23 +-
106
hw/intc/armv7m_nvic.c | 885 ++++++++++++++++++++++++++++-------
107
hw/misc/bcm2835_rng.c | 149 ++++++
108
hw/misc/exynos4210_clk.c | 164 +++++++
109
hw/sd/bcm2835_sdhost.c | 429 +++++++++++++++++
110
hw/sd/core.c | 30 ++
111
hw/sd/sdhci.c | 25 +-
112
hw/timer/imx_gpt.c | 33 +-
113
linux-user/main.c | 1 +
114
target/arm/cpu.c | 16 +-
115
target/arm/helper.c | 245 +++++++---
116
target/arm/translate-a64.c | 12 +
117
target/arm/translate.c | 8 +-
118
hw/intc/trace-events | 15 +
119
31 files changed, 2376 insertions(+), 333 deletions(-)
120
create mode 100644 include/hw/gpio/bcm2835_gpio.h
121
create mode 100644 include/hw/misc/bcm2835_rng.h
122
create mode 100644 include/hw/sd/bcm2835_sdhost.h
123
create mode 100644 hw/gpio/bcm2835_gpio.c
124
create mode 100644 hw/misc/bcm2835_rng.c
125
create mode 100644 hw/misc/exynos4210_clk.c
126
create mode 100644 hw/sd/bcm2835_sdhost.c
127
diff view generated by jsdifflib
1
From: Prasad J Pandit <pjp@fedoraproject.org>
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
2
2
3
In sdhci_write invoke multi block transfer if it is enabled
3
The world outside moves to newer and newer cpu cores. Let move SBSA
4
in the transfer mode register 's->trnmod'.
4
Reference Platform to something newer as well.
5
5
6
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
6
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
7
Message-id: 20170214185225.7994-4-ppandit@redhat.com
7
Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
8
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
8
Message-id: 20230506183417.1360427-1-marcin.juszkiewicz@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
hw/sd/sdhci.c | 6 +++++-
11
hw/arm/sbsa-ref.c | 2 +-
12
1 file changed, 5 insertions(+), 1 deletion(-)
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
13
14
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
14
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/sd/sdhci.c
16
--- a/hw/arm/sbsa-ref.c
17
+++ b/hw/sd/sdhci.c
17
+++ b/hw/arm/sbsa-ref.c
18
@@ -XXX,XX +XXX,XX @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
18
@@ -XXX,XX +XXX,XX @@ static void sbsa_ref_class_init(ObjectClass *oc, void *data)
19
/* Writing to last byte of sdmasysad might trigger transfer */
19
20
if (!(mask & 0xFF000000) && TRANSFERRING_DATA(s->prnsts) && s->blkcnt &&
20
mc->init = sbsa_ref_init;
21
s->blksize && SDHC_DMA_TYPE(s->hostctl) == SDHC_CTRL_SDMA) {
21
mc->desc = "QEMU 'SBSA Reference' ARM Virtual Machine";
22
- sdhci_sdma_transfer_multi_blocks(s);
22
- mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a57");
23
+ if (s->trnmod & SDHC_TRNS_MULTI) {
23
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("neoverse-n1");
24
+ sdhci_sdma_transfer_multi_blocks(s);
24
mc->max_cpus = 512;
25
+ } else {
25
mc->pci_allow_0_address = true;
26
+ sdhci_sdma_transfer_single_block(s);
26
mc->minimum_page_bits = 12;
27
+ }
28
}
29
break;
30
case SDHC_BLKSIZE:
31
--
27
--
32
2.7.4
28
2.34.1
33
34
diff view generated by jsdifflib
1
From: Nick Reilly <nreilly@blackberry.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The aarch64 crypto instructions for AES and SHA are missing the
3
If vd == vm, copy vm to scratch, so that we can pre-zero
4
check for if the FPU is enabled.
4
the output and still access the gather indicies.
5
5
6
Signed-off-by: Nick Reilly <nreilly@blackberry.com>
6
Cc: qemu-stable@nongnu.org
7
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1612
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230504104232.1877774-1-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
12
---
10
target/arm/translate-a64.c | 12 ++++++++++++
13
target/arm/tcg/sve_helper.c | 6 ++++++
11
1 file changed, 12 insertions(+)
14
1 file changed, 6 insertions(+)
12
15
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
16
diff --git a/target/arm/tcg/sve_helper.c b/target/arm/tcg/sve_helper.c
14
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-a64.c
18
--- a/target/arm/tcg/sve_helper.c
16
+++ b/target/arm/translate-a64.c
19
+++ b/target/arm/tcg/sve_helper.c
17
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_aes(DisasContext *s, uint32_t insn)
20
@@ -XXX,XX +XXX,XX @@ void sve_ldff1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm,
21
intptr_t reg_off;
22
SVEHostPage info;
23
target_ulong addr, in_page;
24
+ ARMVectorReg scratch;
25
26
/* Skip to the first true predicate. */
27
reg_off = find_next_active(vg, 0, reg_max, esz);
28
@@ -XXX,XX +XXX,XX @@ void sve_ldff1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm,
18
return;
29
return;
19
}
30
}
20
31
21
+ if (!fp_access_check(s)) {
32
+ /* Protect against overlap between vd and vm. */
22
+ return;
33
+ if (unlikely(vd == vm)) {
34
+ vm = memcpy(&scratch, vm, reg_max);
23
+ }
35
+ }
24
+
36
+
25
/* Note that we convert the Vx register indexes into the
37
/*
26
* index within the vfp.regs[] array, so we can share the
38
* Probe the first element, allowing faults.
27
* helper with the AArch32 instructions.
39
*/
28
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
29
return;
30
}
31
32
+ if (!fp_access_check(s)) {
33
+ return;
34
+ }
35
+
36
tcg_rd_regno = tcg_const_i32(rd << 1);
37
tcg_rn_regno = tcg_const_i32(rn << 1);
38
tcg_rm_regno = tcg_const_i32(rm << 1);
39
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
40
return;
41
}
42
43
+ if (!fp_access_check(s)) {
44
+ return;
45
+ }
46
+
47
tcg_rd_regno = tcg_const_i32(rd << 1);
48
tcg_rn_regno = tcg_const_i32(rn << 1);
49
50
--
40
--
51
2.7.4
41
2.34.1
52
53
diff view generated by jsdifflib
1
From: Prasad J Pandit <pjp@fedoraproject.org>
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
2
2
3
In SDHCI protocol, the transfer mode register is defined
3
At Linaro I work on sbsa-ref, know direction it goes.
4
to be of 6 bits. Mask its value with '0x0037' so that an
5
invalid value could not be assigned.
6
4
7
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
5
May not get code details each time.
8
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
6
9
Message-id: 20170214185225.7994-2-ppandit@redhat.com
7
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Message-id: 20230515143753.365591-1-marcin.juszkiewicz@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
hw/sd/sdhci.c | 3 ++-
12
MAINTAINERS | 1 +
13
1 file changed, 2 insertions(+), 1 deletion(-)
13
1 file changed, 1 insertion(+)
14
14
15
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
15
diff --git a/MAINTAINERS b/MAINTAINERS
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/sd/sdhci.c
17
--- a/MAINTAINERS
18
+++ b/hw/sd/sdhci.c
18
+++ b/MAINTAINERS
19
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ SBSA-REF
20
(SDHC_CAPAB_BASECLKFREQ << 8) | (SDHC_CAPAB_TOUNIT << 7) | \
20
M: Radoslaw Biernacki <rad@semihalf.com>
21
(SDHC_CAPAB_TOCLKFREQ))
21
M: Peter Maydell <peter.maydell@linaro.org>
22
22
R: Leif Lindholm <quic_llindhol@quicinc.com>
23
+#define MASK_TRNMOD 0x0037
23
+R: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
24
#define MASKED_WRITE(reg, mask, val) (reg = (reg & (mask)) | (val))
24
L: qemu-arm@nongnu.org
25
25
S: Maintained
26
static uint8_t sdhci_slotint(SDHCIState *s)
26
F: hw/arm/sbsa-ref.c
27
@@ -XXX,XX +XXX,XX @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
28
if (!(s->capareg & SDHC_CAN_DO_DMA)) {
29
value &= ~SDHC_TRNS_DMA;
30
}
31
- MASKED_WRITE(s->trnmod, mask, value);
32
+ MASKED_WRITE(s->trnmod, mask, value & MASK_TRNMOD);
33
MASKED_WRITE(s->cmdreg, mask >> 16, value >> 16);
34
35
/* Writing to the upper byte of CMDREG triggers SD command generation */
36
--
27
--
37
2.7.4
28
2.34.1
38
29
39
30
diff view generated by jsdifflib
1
The M profile condition for when we can take a pending exception or
1
From: Cornelia Huck <cohuck@redhat.com>
2
interrupt is not the same as that for A/R profile. The code
2
3
originally copied from the A/R profile version of the
3
Extend the 'mte' property for the virt machine to cover KVM as
4
cpu_exec_interrupt function only worked by chance for the
4
well. For KVM, we don't allocate tag memory, but instead enable the
5
very simple case of exceptions being masked by PRIMASK.
5
capability.
6
Replace it with a call to a function in the NVIC code that
6
7
correctly compares the priority of the pending exception
7
If MTE has been enabled, we need to disable migration, as we do not
8
against the current execution priority of the CPU.
8
yet have a way to migrate the tags as well. Therefore, MTE will stay
9
9
off with KVM unless requested explicitly.
10
[Michael Davidsaver's patchset had a patch to do something
10
11
similar but the implementation ended up being a rewrite.]
11
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
12
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20230428095533.21747-2-cohuck@redhat.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
15
---
16
---
16
target/arm/cpu.h | 8 ++++++++
17
target/arm/cpu.h | 4 +++
17
hw/intc/armv7m_nvic.c | 7 +++++++
18
target/arm/kvm_arm.h | 19 ++++++++++++
18
target/arm/cpu.c | 16 ++++++++--------
19
hw/arm/virt.c | 73 +++++++++++++++++++++++++-------------------
19
3 files changed, 23 insertions(+), 8 deletions(-)
20
target/arm/cpu.c | 9 +++---
21
target/arm/kvm.c | 35 +++++++++++++++++++++
22
target/arm/kvm64.c | 5 +++
23
6 files changed, 109 insertions(+), 36 deletions(-)
20
24
21
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
25
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
22
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/cpu.h
27
--- a/target/arm/cpu.h
24
+++ b/target/arm/cpu.h
28
+++ b/target/arm/cpu.h
25
@@ -XXX,XX +XXX,XX @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
29
@@ -XXX,XX +XXX,XX @@ struct ArchCPU {
26
uint32_t cur_el, bool secure);
30
*/
27
31
uint32_t psci_conduit;
28
/* Interface between CPU and Interrupt controller. */
32
29
+#ifndef CONFIG_USER_ONLY
33
+ /* CPU has Memory Tag Extension */
30
+bool armv7m_nvic_can_take_pending_exception(void *opaque);
34
+ bool has_mte;
31
+#else
35
+
32
+static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
36
/* For v8M, initial value of the Secure VTOR */
33
+{
37
uint32_t init_svtor;
34
+ return true;
38
/* For v8M, initial value of the Non-secure VTOR */
35
+}
39
@@ -XXX,XX +XXX,XX @@ struct ArchCPU {
36
+#endif
40
bool prop_pauth;
37
void armv7m_nvic_set_pending(void *opaque, int irq);
41
bool prop_pauth_impdef;
38
int armv7m_nvic_acknowledge_irq(void *opaque);
42
bool prop_lpa2;
39
void armv7m_nvic_complete_irq(void *opaque, int irq);
43
+ OnOffAuto prop_mte;
40
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
44
41
index XXXXXXX..XXXXXXX 100644
45
/* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */
42
--- a/hw/intc/armv7m_nvic.c
46
uint32_t dcz_blocksize;
43
+++ b/hw/intc/armv7m_nvic.c
47
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
44
@@ -XXX,XX +XXX,XX @@ static inline int nvic_exec_prio(NVICState *s)
48
index XXXXXXX..XXXXXXX 100644
45
return MIN(running, s->exception_prio);
49
--- a/target/arm/kvm_arm.h
46
}
50
+++ b/target/arm/kvm_arm.h
47
51
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_pmu_supported(void);
48
+bool armv7m_nvic_can_take_pending_exception(void *opaque)
52
*/
49
+{
53
bool kvm_arm_sve_supported(void);
50
+ NVICState *s = opaque;
54
51
+
55
+/**
52
+ return nvic_exec_prio(s) > nvic_pending_prio(s);
56
+ * kvm_arm_mte_supported:
53
+}
57
+ *
54
+
58
+ * Returns: true if KVM can enable MTE, and false otherwise.
55
/* caller must call nvic_irq_update() after this */
59
+ */
56
static void set_prio(NVICState *s, unsigned irq, uint8_t prio)
60
+bool kvm_arm_mte_supported(void);
57
{
61
+
62
/**
63
* kvm_arm_get_max_vm_ipa_size:
64
* @ms: Machine state handle
65
@@ -XXX,XX +XXX,XX @@ void kvm_arm_pvtime_init(CPUState *cs, uint64_t ipa);
66
67
int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level);
68
69
+void kvm_arm_enable_mte(Object *cpuobj, Error **errp);
70
+
71
#else
72
73
/*
74
@@ -XXX,XX +XXX,XX @@ static inline bool kvm_arm_steal_time_supported(void)
75
return false;
76
}
77
78
+static inline bool kvm_arm_mte_supported(void)
79
+{
80
+ return false;
81
+}
82
+
83
/*
84
* These functions should never actually be called without KVM support.
85
*/
86
@@ -XXX,XX +XXX,XX @@ static inline uint32_t kvm_arm_sve_get_vls(CPUState *cs)
87
g_assert_not_reached();
88
}
89
90
+static inline void kvm_arm_enable_mte(Object *cpuobj, Error **errp)
91
+{
92
+ g_assert_not_reached();
93
+}
94
+
95
#endif
96
97
static inline const char *gic_class_name(void)
98
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
99
index XXXXXXX..XXXXXXX 100644
100
--- a/hw/arm/virt.c
101
+++ b/hw/arm/virt.c
102
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
103
exit(1);
104
}
105
106
- if (vms->mte && (kvm_enabled() || hvf_enabled())) {
107
+ if (vms->mte && hvf_enabled()) {
108
error_report("mach-virt: %s does not support providing "
109
"MTE to the guest CPU",
110
current_accel_name());
111
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
112
}
113
114
if (vms->mte) {
115
- /* Create the memory region only once, but link to all cpus. */
116
- if (!tag_sysmem) {
117
- /*
118
- * The property exists only if MemTag is supported.
119
- * If it is, we must allocate the ram to back that up.
120
- */
121
- if (!object_property_find(cpuobj, "tag-memory")) {
122
- error_report("MTE requested, but not supported "
123
- "by the guest CPU");
124
+ if (tcg_enabled()) {
125
+ /* Create the memory region only once, but link to all cpus. */
126
+ if (!tag_sysmem) {
127
+ /*
128
+ * The property exists only if MemTag is supported.
129
+ * If it is, we must allocate the ram to back that up.
130
+ */
131
+ if (!object_property_find(cpuobj, "tag-memory")) {
132
+ error_report("MTE requested, but not supported "
133
+ "by the guest CPU");
134
+ exit(1);
135
+ }
136
+
137
+ tag_sysmem = g_new(MemoryRegion, 1);
138
+ memory_region_init(tag_sysmem, OBJECT(machine),
139
+ "tag-memory", UINT64_MAX / 32);
140
+
141
+ if (vms->secure) {
142
+ secure_tag_sysmem = g_new(MemoryRegion, 1);
143
+ memory_region_init(secure_tag_sysmem, OBJECT(machine),
144
+ "secure-tag-memory",
145
+ UINT64_MAX / 32);
146
+
147
+ /* As with ram, secure-tag takes precedence over tag. */
148
+ memory_region_add_subregion_overlap(secure_tag_sysmem,
149
+ 0, tag_sysmem, -1);
150
+ }
151
+ }
152
+
153
+ object_property_set_link(cpuobj, "tag-memory",
154
+ OBJECT(tag_sysmem), &error_abort);
155
+ if (vms->secure) {
156
+ object_property_set_link(cpuobj, "secure-tag-memory",
157
+ OBJECT(secure_tag_sysmem),
158
+ &error_abort);
159
+ }
160
+ } else if (kvm_enabled()) {
161
+ if (!kvm_arm_mte_supported()) {
162
+ error_report("MTE requested, but not supported by KVM");
163
exit(1);
164
}
165
-
166
- tag_sysmem = g_new(MemoryRegion, 1);
167
- memory_region_init(tag_sysmem, OBJECT(machine),
168
- "tag-memory", UINT64_MAX / 32);
169
-
170
- if (vms->secure) {
171
- secure_tag_sysmem = g_new(MemoryRegion, 1);
172
- memory_region_init(secure_tag_sysmem, OBJECT(machine),
173
- "secure-tag-memory", UINT64_MAX / 32);
174
-
175
- /* As with ram, secure-tag takes precedence over tag. */
176
- memory_region_add_subregion_overlap(secure_tag_sysmem, 0,
177
- tag_sysmem, -1);
178
- }
179
- }
180
-
181
- object_property_set_link(cpuobj, "tag-memory", OBJECT(tag_sysmem),
182
- &error_abort);
183
- if (vms->secure) {
184
- object_property_set_link(cpuobj, "secure-tag-memory",
185
- OBJECT(secure_tag_sysmem),
186
- &error_abort);
187
+ kvm_arm_enable_mte(cpuobj, &error_abort);
188
}
189
}
190
58
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
191
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
59
index XXXXXXX..XXXXXXX 100644
192
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/cpu.c
193
--- a/target/arm/cpu.c
61
+++ b/target/arm/cpu.c
194
+++ b/target/arm/cpu.c
62
@@ -XXX,XX +XXX,XX @@ static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
195
@@ -XXX,XX +XXX,XX @@ void arm_cpu_post_init(Object *obj)
63
CPUARMState *env = &cpu->env;
196
qdev_prop_allow_set_link_before_realize,
64
bool ret = false;
197
OBJ_PROP_LINK_STRONG);
65
198
}
66
-
199
+ cpu->has_mte = true;
67
- if (interrupt_request & CPU_INTERRUPT_FIQ
200
}
68
- && !(env->daif & PSTATE_F)) {
201
#endif
69
- cs->exception_index = EXCP_FIQ;
202
}
70
- cc->do_interrupt(cs);
203
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
71
- ret = true;
204
}
72
- }
205
if (cpu->tag_memory) {
73
/* ARMv7-M interrupt return works by loading a magic value
206
error_setg(errp,
74
* into the PC. On real hardware the load causes the
207
- "Cannot enable %s when guest CPUs has MTE enabled",
75
* return to occur. The qemu implementation performs the
208
+ "Cannot enable %s when guest CPUs has tag memory enabled",
76
@@ -XXX,XX +XXX,XX @@ static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
209
current_accel_name());
77
* the stack if an interrupt occurred at the wrong time.
210
return;
78
* We avoid this by disabling interrupts when
211
}
79
* pc contains a magic address.
212
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
80
+ *
213
}
81
+ * ARMv7-M interrupt masking works differently than -A or -R.
214
82
+ * There is no FIQ/IRQ distinction. Instead of I and F bits
215
#ifndef CONFIG_USER_ONLY
83
+ * masking FIQ and IRQ interrupts, an exception is taken only
216
- if (cpu->tag_memory == NULL && cpu_isar_feature(aa64_mte, cpu)) {
84
+ * if it is higher priority than the current execution priority
217
+ if (!cpu->has_mte && cpu_isar_feature(aa64_mte, cpu)) {
85
+ * (which depends on state like BASEPRI, FAULTMASK and the
218
/*
86
+ * currently active exception).
219
- * Disable the MTE feature bits if we do not have tag-memory
87
*/
220
- * provided by the machine.
88
if (interrupt_request & CPU_INTERRUPT_HARD
221
+ * Disable the MTE feature bits if we do not have the feature
89
- && !(env->daif & PSTATE_I)
222
+ * setup by the machine.
90
+ && (armv7m_nvic_can_take_pending_exception(env->nvic))
223
*/
91
&& (env->regs[15] < 0xfffffff0)) {
224
cpu->isar.id_aa64pfr1 =
92
cs->exception_index = EXCP_IRQ;
225
FIELD_DP64(cpu->isar.id_aa64pfr1, ID_AA64PFR1, MTE, 0);
93
cc->do_interrupt(cs);
226
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
227
index XXXXXXX..XXXXXXX 100644
228
--- a/target/arm/kvm.c
229
+++ b/target/arm/kvm.c
230
@@ -XXX,XX +XXX,XX @@
231
#include "hw/boards.h"
232
#include "hw/irq.h"
233
#include "qemu/log.h"
234
+#include "migration/blocker.h"
235
236
const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
237
KVM_CAP_LAST_INFO
238
@@ -XXX,XX +XXX,XX @@ bool kvm_arch_cpu_check_are_resettable(void)
239
void kvm_arch_accel_class_init(ObjectClass *oc)
240
{
241
}
242
+
243
+void kvm_arm_enable_mte(Object *cpuobj, Error **errp)
244
+{
245
+ static bool tried_to_enable;
246
+ static bool succeeded_to_enable;
247
+ Error *mte_migration_blocker = NULL;
248
+ int ret;
249
+
250
+ if (!tried_to_enable) {
251
+ /*
252
+ * MTE on KVM is enabled on a per-VM basis (and retrying doesn't make
253
+ * sense), and we only want a single migration blocker as well.
254
+ */
255
+ tried_to_enable = true;
256
+
257
+ ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_ARM_MTE, 0);
258
+ if (ret) {
259
+ error_setg_errno(errp, -ret, "Failed to enable KVM_CAP_ARM_MTE");
260
+ return;
261
+ }
262
+
263
+ /* TODO: add proper migration support with MTE enabled */
264
+ error_setg(&mte_migration_blocker,
265
+ "Live migration disabled due to MTE enabled");
266
+ if (migrate_add_blocker(mte_migration_blocker, errp)) {
267
+ error_free(mte_migration_blocker);
268
+ return;
269
+ }
270
+ succeeded_to_enable = true;
271
+ }
272
+ if (succeeded_to_enable) {
273
+ object_property_set_bool(cpuobj, "has_mte", true, NULL);
274
+ }
275
+}
276
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
277
index XXXXXXX..XXXXXXX 100644
278
--- a/target/arm/kvm64.c
279
+++ b/target/arm/kvm64.c
280
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_steal_time_supported(void)
281
return kvm_check_extension(kvm_state, KVM_CAP_STEAL_TIME);
282
}
283
284
+bool kvm_arm_mte_supported(void)
285
+{
286
+ return kvm_check_extension(kvm_state, KVM_CAP_ARM_MTE);
287
+}
288
+
289
QEMU_BUILD_BUG_ON(KVM_ARM64_SVE_VQ_MIN != 1);
290
291
uint32_t kvm_arm_sve_get_vls(CPUState *cs)
94
--
292
--
95
2.7.4
293
2.34.1
96
97
diff view generated by jsdifflib
1
From: Prasad J Pandit <pjp@fedoraproject.org>
1
From: Alex Bennée <alex.bennee@linaro.org>
2
2
3
In the SDHCI protocol, the transfer mode register value
3
The commit b3aa2f2128 (target/arm: provide stubs for more external
4
is used during multi block transfer to check if block count
4
debug registers) was added to handle HyperV's unconditional usage of
5
register is enabled and should be updated. Transfer mode
5
Debug Communications Channel. It turns out that Linux will similarly
6
register could be set such that, block count register would
6
break if you enable CONFIG_HVC_DCC "ARM JTAG DCC console".
7
not be updated, thus leading to an infinite loop. Add check
8
to avoid it.
9
7
10
Reported-by: Wjjzhang <wjjzhang@tencent.com>
8
Extend the registers we RAZ/WI set to avoid this.
11
Reported-by: Jiang Xin <jiangxin1@huawei.com>
9
12
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
10
Cc: Anders Roxell <anders.roxell@linaro.org>
13
Message-id: 20170214185225.7994-3-ppandit@redhat.com
11
Cc: Evgeny Iakovlev <eiakovlev@linux.microsoft.com>
14
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
12
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20230516104420.407912-1-alex.bennee@linaro.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
16
---
17
hw/sd/sdhci.c | 10 +++++-----
17
target/arm/debug_helper.c | 11 +++++++++--
18
1 file changed, 5 insertions(+), 5 deletions(-)
18
1 file changed, 9 insertions(+), 2 deletions(-)
19
19
20
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
20
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
21
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/sd/sdhci.c
22
--- a/target/arm/debug_helper.c
23
+++ b/hw/sd/sdhci.c
23
+++ b/target/arm/debug_helper.c
24
@@ -XXX,XX +XXX,XX @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
24
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
25
uint32_t boundary_chk = 1 << (((s->blksize & 0xf000) >> 12) + 12);
25
.access = PL0_R, .accessfn = access_tdcc,
26
uint32_t boundary_count = boundary_chk - (s->sdmasysad % boundary_chk);
26
.type = ARM_CP_CONST, .resetvalue = 0 },
27
27
/*
28
+ if (!(s->trnmod & SDHC_TRNS_BLK_CNT_EN) || !s->blkcnt) {
28
- * OSDTRRX_EL1/OSDTRTX_EL1 are used for save and restore of DBGDTRRX_EL0.
29
+ qemu_log_mask(LOG_UNIMP, "infinite transfer is not supported\n");
29
- * It is a component of the Debug Communications Channel, which is not implemented.
30
+ return;
30
+ * These registers belong to the Debug Communications Channel,
31
+ }
31
+ * which is not implemented. However we implement RAZ/WI behaviour
32
+
32
+ * with trapping to prevent spurious SIGILLs if the guest OS does
33
/* XXX: Some sd/mmc drivers (for example, u-boot-slp) do not account for
33
+ * access them as the support cannot be probed for.
34
* possible stop at page boundary if initial address is not page aligned,
34
*/
35
* allow them to work properly */
35
{ .name = "OSDTRRX_EL1", .state = ARM_CP_STATE_BOTH, .cp = 14,
36
@@ -XXX,XX +XXX,XX @@ static void sdhci_data_transfer(void *opaque)
36
.opc0 = 2, .opc1 = 0, .crn = 0, .crm = 0, .opc2 = 2,
37
if (s->trnmod & SDHC_TRNS_DMA) {
37
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
38
switch (SDHC_DMA_TYPE(s->hostctl)) {
38
.opc0 = 2, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 2,
39
case SDHC_CTRL_SDMA:
39
.access = PL1_RW, .accessfn = access_tdcc,
40
- if ((s->trnmod & SDHC_TRNS_MULTI) &&
40
.type = ARM_CP_CONST, .resetvalue = 0 },
41
- (!(s->trnmod & SDHC_TRNS_BLK_CNT_EN) || s->blkcnt == 0)) {
41
+ /* DBGDTRTX_EL0/DBGDTRRX_EL0 depend on direction */
42
- break;
42
+ { .name = "DBGDTR_EL0", .state = ARM_CP_STATE_BOTH, .cp = 14,
43
- }
43
+ .opc0 = 2, .opc1 = 3, .crn = 0, .crm = 5, .opc2 = 0,
44
-
44
+ .access = PL0_RW, .accessfn = access_tdcc,
45
if ((s->blkcnt == 1) || !(s->trnmod & SDHC_TRNS_MULTI)) {
45
+ .type = ARM_CP_CONST, .resetvalue = 0 },
46
sdhci_sdma_transfer_single_block(s);
46
/*
47
} else {
47
* OSECCR_EL1 provides a mechanism for an operating system
48
* to access the contents of EDECCR. EDECCR is not implemented though,
48
--
49
--
49
2.7.4
50
2.34.1
50
51
51
52
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
2
2
3
All the places in armv7m_cpu_do_interrupt() which pend an
3
Bochs card is normal PCI Express card so it fits better in system with
4
exception in the NVIC are doing so for synchronous
4
PCI Express bus. VGA is simple legacy PCI card.
5
exceptions. We know that we will always take some
6
exception in this case, so we can just acknowledge it
7
immediately, rather than returning and then immediately
8
being called again because the NVIC has raised its outbound
9
IRQ line.
10
5
11
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
6
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
12
[PMM: tweaked commit message; added DEBUG to the set of
7
Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
13
exceptions we handle immediately, since it is synchronous
8
Message-id: 20230505120936.1097060-1-marcin.juszkiewicz@linaro.org
14
when it results from the BKPT instruction]
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
17
---
10
---
18
target/arm/helper.c | 15 +++++++++------
11
hw/arm/sbsa-ref.c | 2 +-
19
1 file changed, 9 insertions(+), 6 deletions(-)
12
1 file changed, 1 insertion(+), 1 deletion(-)
20
13
21
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
22
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/helper.c
16
--- a/hw/arm/sbsa-ref.c
24
+++ b/target/arm/helper.c
17
+++ b/hw/arm/sbsa-ref.c
25
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
18
@@ -XXX,XX +XXX,XX @@ static void create_pcie(SBSAMachineState *sms)
26
case EXCP_UDEF:
27
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
28
env->v7m.cfsr |= R_V7M_CFSR_UNDEFINSTR_MASK;
29
- return;
30
+ break;
31
case EXCP_NOCP:
32
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
33
env->v7m.cfsr |= R_V7M_CFSR_NOCP_MASK;
34
- return;
35
+ break;
36
case EXCP_SWI:
37
/* The PC already points to the next instruction. */
38
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC);
39
- return;
40
+ break;
41
case EXCP_PREFETCH_ABORT:
42
case EXCP_DATA_ABORT:
43
/* TODO: if we implemented the MPU registers, this is where we
44
* should set the MMFAR, etc from exception.fsr and exception.vaddress.
45
*/
46
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM);
47
- return;
48
+ break;
49
case EXCP_BKPT:
50
if (semihosting_enabled()) {
51
int nr;
52
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
53
}
54
}
19
}
55
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG);
56
- return;
57
+ break;
58
case EXCP_IRQ:
59
- armv7m_nvic_acknowledge_irq(env->nvic);
60
break;
61
case EXCP_EXCEPTION_EXIT:
62
do_v7m_exception_exit(env);
63
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
64
return; /* Never happens. Keep compiler happy. */
65
}
20
}
66
21
67
+ armv7m_nvic_acknowledge_irq(env->nvic);
22
- pci_create_simple(pci->bus, -1, "VGA");
68
+
23
+ pci_create_simple(pci->bus, -1, "bochs-display");
69
+ qemu_log_mask(CPU_LOG_INT, "... as %d\n", env->v7m.exception);
24
70
+
25
create_smmu(sms, pci->bus);
71
/* Align stack pointer if the guest wants that */
26
}
72
if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) {
73
env->regs[13] -= 4;
74
--
27
--
75
2.7.4
28
2.34.1
76
77
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This adds the BCM2835 SDHost controller from Arasan.
3
Split out all of the decode stuff from aarch64_tr_translate_insn.
4
Call it disas_a64_legacy to indicate it will be replaced.
4
5
5
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20170224164021.9066-2-clement.deschamps@antfield.fr
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20230512144106.3608981-2-peter.maydell@linaro.org
10
[PMM: Rebased]
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
13
---
10
hw/sd/Makefile.objs | 1 +
14
target/arm/tcg/translate-a64.c | 82 ++++++++++++++++++----------------
11
include/hw/sd/bcm2835_sdhost.h | 48 +++++
15
1 file changed, 44 insertions(+), 38 deletions(-)
12
hw/sd/bcm2835_sdhost.c | 429 +++++++++++++++++++++++++++++++++++++++++
13
3 files changed, 478 insertions(+)
14
create mode 100644 include/hw/sd/bcm2835_sdhost.h
15
create mode 100644 hw/sd/bcm2835_sdhost.c
16
16
17
diff --git a/hw/sd/Makefile.objs b/hw/sd/Makefile.objs
17
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
18
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/sd/Makefile.objs
19
--- a/target/arm/tcg/translate-a64.c
20
+++ b/hw/sd/Makefile.objs
20
+++ b/target/arm/tcg/translate-a64.c
21
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_SDHCI) += sdhci.o
21
@@ -XXX,XX +XXX,XX @@ static bool btype_destination_ok(uint32_t insn, bool bt, int btype)
22
obj-$(CONFIG_MILKYMIST) += milkymist-memcard.o
22
return false;
23
obj-$(CONFIG_OMAP) += omap_mmc.o
23
}
24
obj-$(CONFIG_PXA2XX) += pxa2xx_mmci.o
24
25
+obj-$(CONFIG_RASPI) += bcm2835_sdhost.o
25
+/* C3.1 A64 instruction index by encoding */
26
diff --git a/include/hw/sd/bcm2835_sdhost.h b/include/hw/sd/bcm2835_sdhost.h
26
+static void disas_a64_legacy(DisasContext *s, uint32_t insn)
27
new file mode 100644
28
index XXXXXXX..XXXXXXX
29
--- /dev/null
30
+++ b/include/hw/sd/bcm2835_sdhost.h
31
@@ -XXX,XX +XXX,XX @@
32
+/*
33
+ * Raspberry Pi (BCM2835) SD Host Controller
34
+ *
35
+ * Copyright (c) 2017 Antfield SAS
36
+ *
37
+ * Authors:
38
+ * Clement Deschamps <clement.deschamps@antfield.fr>
39
+ * Luc Michel <luc.michel@antfield.fr>
40
+ *
41
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
42
+ * See the COPYING file in the top-level directory.
43
+ */
44
+
45
+#ifndef BCM2835_SDHOST_H
46
+#define BCM2835_SDHOST_H
47
+
48
+#include "hw/sysbus.h"
49
+#include "hw/sd/sd.h"
50
+
51
+#define TYPE_BCM2835_SDHOST "bcm2835-sdhost"
52
+#define BCM2835_SDHOST(obj) \
53
+ OBJECT_CHECK(BCM2835SDHostState, (obj), TYPE_BCM2835_SDHOST)
54
+
55
+#define BCM2835_SDHOST_FIFO_LEN 16
56
+
57
+typedef struct {
58
+ SysBusDevice busdev;
59
+ SDBus sdbus;
60
+ MemoryRegion iomem;
61
+
62
+ uint32_t cmd;
63
+ uint32_t cmdarg;
64
+ uint32_t status;
65
+ uint32_t rsp[4];
66
+ uint32_t config;
67
+ uint32_t edm;
68
+ uint32_t vdd;
69
+ uint32_t hbct;
70
+ uint32_t hblc;
71
+ int32_t fifo_pos;
72
+ int32_t fifo_len;
73
+ uint32_t fifo[BCM2835_SDHOST_FIFO_LEN];
74
+ uint32_t datacnt;
75
+
76
+ qemu_irq irq;
77
+} BCM2835SDHostState;
78
+
79
+#endif
80
diff --git a/hw/sd/bcm2835_sdhost.c b/hw/sd/bcm2835_sdhost.c
81
new file mode 100644
82
index XXXXXXX..XXXXXXX
83
--- /dev/null
84
+++ b/hw/sd/bcm2835_sdhost.c
85
@@ -XXX,XX +XXX,XX @@
86
+/*
87
+ * Raspberry Pi (BCM2835) SD Host Controller
88
+ *
89
+ * Copyright (c) 2017 Antfield SAS
90
+ *
91
+ * Authors:
92
+ * Clement Deschamps <clement.deschamps@antfield.fr>
93
+ * Luc Michel <luc.michel@antfield.fr>
94
+ *
95
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
96
+ * See the COPYING file in the top-level directory.
97
+ */
98
+
99
+#include "qemu/osdep.h"
100
+#include "qemu/log.h"
101
+#include "sysemu/blockdev.h"
102
+#include "hw/sd/bcm2835_sdhost.h"
103
+
104
+#define TYPE_BCM2835_SDHOST_BUS "bcm2835-sdhost-bus"
105
+#define BCM2835_SDHOST_BUS(obj) \
106
+ OBJECT_CHECK(SDBus, (obj), TYPE_BCM2835_SDHOST_BUS)
107
+
108
+#define SDCMD 0x00 /* Command to SD card - 16 R/W */
109
+#define SDARG 0x04 /* Argument to SD card - 32 R/W */
110
+#define SDTOUT 0x08 /* Start value for timeout counter - 32 R/W */
111
+#define SDCDIV 0x0c /* Start value for clock divider - 11 R/W */
112
+#define SDRSP0 0x10 /* SD card rsp (31:0) - 32 R */
113
+#define SDRSP1 0x14 /* SD card rsp (63:32) - 32 R */
114
+#define SDRSP2 0x18 /* SD card rsp (95:64) - 32 R */
115
+#define SDRSP3 0x1c /* SD card rsp (127:96) - 32 R */
116
+#define SDHSTS 0x20 /* SD host status - 11 R */
117
+#define SDVDD 0x30 /* SD card power control - 1 R/W */
118
+#define SDEDM 0x34 /* Emergency Debug Mode - 13 R/W */
119
+#define SDHCFG 0x38 /* Host configuration - 2 R/W */
120
+#define SDHBCT 0x3c /* Host byte count (debug) - 32 R/W */
121
+#define SDDATA 0x40 /* Data to/from SD card - 32 R/W */
122
+#define SDHBLC 0x50 /* Host block count (SDIO/SDHC) - 9 R/W */
123
+
124
+#define SDCMD_NEW_FLAG 0x8000
125
+#define SDCMD_FAIL_FLAG 0x4000
126
+#define SDCMD_BUSYWAIT 0x800
127
+#define SDCMD_NO_RESPONSE 0x400
128
+#define SDCMD_LONG_RESPONSE 0x200
129
+#define SDCMD_WRITE_CMD 0x80
130
+#define SDCMD_READ_CMD 0x40
131
+#define SDCMD_CMD_MASK 0x3f
132
+
133
+#define SDCDIV_MAX_CDIV 0x7ff
134
+
135
+#define SDHSTS_BUSY_IRPT 0x400
136
+#define SDHSTS_BLOCK_IRPT 0x200
137
+#define SDHSTS_SDIO_IRPT 0x100
138
+#define SDHSTS_REW_TIME_OUT 0x80
139
+#define SDHSTS_CMD_TIME_OUT 0x40
140
+#define SDHSTS_CRC16_ERROR 0x20
141
+#define SDHSTS_CRC7_ERROR 0x10
142
+#define SDHSTS_FIFO_ERROR 0x08
143
+/* Reserved */
144
+/* Reserved */
145
+#define SDHSTS_DATA_FLAG 0x01
146
+
147
+#define SDHCFG_BUSY_IRPT_EN (1 << 10)
148
+#define SDHCFG_BLOCK_IRPT_EN (1 << 8)
149
+#define SDHCFG_SDIO_IRPT_EN (1 << 5)
150
+#define SDHCFG_DATA_IRPT_EN (1 << 4)
151
+#define SDHCFG_SLOW_CARD (1 << 3)
152
+#define SDHCFG_WIDE_EXT_BUS (1 << 2)
153
+#define SDHCFG_WIDE_INT_BUS (1 << 1)
154
+#define SDHCFG_REL_CMD_LINE (1 << 0)
155
+
156
+#define SDEDM_FORCE_DATA_MODE (1 << 19)
157
+#define SDEDM_CLOCK_PULSE (1 << 20)
158
+#define SDEDM_BYPASS (1 << 21)
159
+
160
+#define SDEDM_WRITE_THRESHOLD_SHIFT 9
161
+#define SDEDM_READ_THRESHOLD_SHIFT 14
162
+#define SDEDM_THRESHOLD_MASK 0x1f
163
+
164
+#define SDEDM_FSM_MASK 0xf
165
+#define SDEDM_FSM_IDENTMODE 0x0
166
+#define SDEDM_FSM_DATAMODE 0x1
167
+#define SDEDM_FSM_READDATA 0x2
168
+#define SDEDM_FSM_WRITEDATA 0x3
169
+#define SDEDM_FSM_READWAIT 0x4
170
+#define SDEDM_FSM_READCRC 0x5
171
+#define SDEDM_FSM_WRITECRC 0x6
172
+#define SDEDM_FSM_WRITEWAIT1 0x7
173
+#define SDEDM_FSM_POWERDOWN 0x8
174
+#define SDEDM_FSM_POWERUP 0x9
175
+#define SDEDM_FSM_WRITESTART1 0xa
176
+#define SDEDM_FSM_WRITESTART2 0xb
177
+#define SDEDM_FSM_GENPULSES 0xc
178
+#define SDEDM_FSM_WRITEWAIT2 0xd
179
+#define SDEDM_FSM_STARTPOWDOWN 0xf
180
+
181
+#define SDDATA_FIFO_WORDS 16
182
+
183
+static void bcm2835_sdhost_update_irq(BCM2835SDHostState *s)
184
+{
27
+{
185
+ uint32_t irq = s->status &
28
+ switch (extract32(insn, 25, 4)) {
186
+ (SDHSTS_BUSY_IRPT | SDHSTS_BLOCK_IRPT | SDHSTS_SDIO_IRPT);
29
+ case 0x0:
187
+ qemu_set_irq(s->irq, !!irq);
30
+ if (!extract32(insn, 31, 1) || !disas_sme(s, insn)) {
188
+}
31
+ unallocated_encoding(s);
189
+
190
+static void bcm2835_sdhost_send_command(BCM2835SDHostState *s)
191
+{
192
+ SDRequest request;
193
+ uint8_t rsp[16];
194
+ int rlen;
195
+
196
+ request.cmd = s->cmd & SDCMD_CMD_MASK;
197
+ request.arg = s->cmdarg;
198
+
199
+ rlen = sdbus_do_command(&s->sdbus, &request, rsp);
200
+ if (rlen < 0) {
201
+ goto error;
202
+ }
203
+ if (!(s->cmd & SDCMD_NO_RESPONSE)) {
204
+#define RWORD(n) (((uint32_t)rsp[n] << 24) | (rsp[n + 1] << 16) \
205
+ | (rsp[n + 2] << 8) | rsp[n + 3])
206
+ if (rlen == 0 || (rlen == 4 && (s->cmd & SDCMD_LONG_RESPONSE))) {
207
+ goto error;
208
+ }
209
+ if (rlen != 4 && rlen != 16) {
210
+ goto error;
211
+ }
212
+ if (rlen == 4) {
213
+ s->rsp[0] = RWORD(0);
214
+ s->rsp[1] = s->rsp[2] = s->rsp[3] = 0;
215
+ } else {
216
+ s->rsp[0] = RWORD(12);
217
+ s->rsp[1] = RWORD(8);
218
+ s->rsp[2] = RWORD(4);
219
+ s->rsp[3] = RWORD(0);
220
+ }
221
+#undef RWORD
222
+ }
223
+ return;
224
+
225
+error:
226
+ s->cmd |= SDCMD_FAIL_FLAG;
227
+ s->status |= SDHSTS_CMD_TIME_OUT;
228
+}
229
+
230
+static void bcm2835_sdhost_fifo_push(BCM2835SDHostState *s, uint32_t value)
231
+{
232
+ int n;
233
+
234
+ if (s->fifo_len == BCM2835_SDHOST_FIFO_LEN) {
235
+ /* FIFO overflow */
236
+ return;
237
+ }
238
+ n = (s->fifo_pos + s->fifo_len) & (BCM2835_SDHOST_FIFO_LEN - 1);
239
+ s->fifo_len++;
240
+ s->fifo[n] = value;
241
+}
242
+
243
+static uint32_t bcm2835_sdhost_fifo_pop(BCM2835SDHostState *s)
244
+{
245
+ uint32_t value;
246
+
247
+ if (s->fifo_len == 0) {
248
+ /* FIFO underflow */
249
+ return 0;
250
+ }
251
+ value = s->fifo[s->fifo_pos];
252
+ s->fifo_len--;
253
+ s->fifo_pos = (s->fifo_pos + 1) & (BCM2835_SDHOST_FIFO_LEN - 1);
254
+ return value;
255
+}
256
+
257
+static void bcm2835_sdhost_fifo_run(BCM2835SDHostState *s)
258
+{
259
+ uint32_t value = 0;
260
+ int n;
261
+ int is_read;
262
+
263
+ is_read = (s->cmd & SDCMD_READ_CMD) != 0;
264
+ if (s->datacnt != 0 && (!is_read || sdbus_data_ready(&s->sdbus))) {
265
+ if (is_read) {
266
+ n = 0;
267
+ while (s->datacnt && s->fifo_len < BCM2835_SDHOST_FIFO_LEN) {
268
+ value |= (uint32_t)sdbus_read_data(&s->sdbus) << (n * 8);
269
+ s->datacnt--;
270
+ n++;
271
+ if (n == 4) {
272
+ bcm2835_sdhost_fifo_push(s, value);
273
+ n = 0;
274
+ value = 0;
275
+ }
276
+ }
277
+ if (n != 0) {
278
+ bcm2835_sdhost_fifo_push(s, value);
279
+ }
280
+ } else { /* write */
281
+ n = 0;
282
+ while (s->datacnt > 0 && (s->fifo_len > 0 || n > 0)) {
283
+ if (n == 0) {
284
+ value = bcm2835_sdhost_fifo_pop(s);
285
+ n = 4;
286
+ }
287
+ n--;
288
+ s->datacnt--;
289
+ sdbus_write_data(&s->sdbus, value & 0xff);
290
+ value >>= 8;
291
+ }
292
+ }
293
+ }
294
+ if (s->datacnt == 0) {
295
+ s->status |= SDHSTS_DATA_FLAG;
296
+
297
+ s->edm &= ~0xf;
298
+ s->edm |= SDEDM_FSM_DATAMODE;
299
+
300
+ if (s->config & SDHCFG_DATA_IRPT_EN) {
301
+ s->status |= SDHSTS_SDIO_IRPT;
302
+ }
303
+
304
+ if ((s->cmd & SDCMD_BUSYWAIT) && (s->config & SDHCFG_BUSY_IRPT_EN)) {
305
+ s->status |= SDHSTS_BUSY_IRPT;
306
+ }
307
+
308
+ if ((s->cmd & SDCMD_WRITE_CMD) && (s->config & SDHCFG_BLOCK_IRPT_EN)) {
309
+ s->status |= SDHSTS_BLOCK_IRPT;
310
+ }
311
+
312
+ bcm2835_sdhost_update_irq(s);
313
+ }
314
+
315
+ s->edm &= ~(0x1f << 4);
316
+ s->edm |= ((s->fifo_len & 0x1f) << 4);
317
+}
318
+
319
+static uint64_t bcm2835_sdhost_read(void *opaque, hwaddr offset,
320
+ unsigned size)
321
+{
322
+ BCM2835SDHostState *s = (BCM2835SDHostState *)opaque;
323
+ uint32_t res = 0;
324
+
325
+ switch (offset) {
326
+ case SDCMD:
327
+ res = s->cmd;
328
+ break;
329
+ case SDHSTS:
330
+ res = s->status;
331
+ break;
332
+ case SDRSP0:
333
+ res = s->rsp[0];
334
+ break;
335
+ case SDRSP1:
336
+ res = s->rsp[1];
337
+ break;
338
+ case SDRSP2:
339
+ res = s->rsp[2];
340
+ break;
341
+ case SDRSP3:
342
+ res = s->rsp[3];
343
+ break;
344
+ case SDEDM:
345
+ res = s->edm;
346
+ break;
347
+ case SDVDD:
348
+ res = s->vdd;
349
+ break;
350
+ case SDDATA:
351
+ res = bcm2835_sdhost_fifo_pop(s);
352
+ bcm2835_sdhost_fifo_run(s);
353
+ break;
354
+ case SDHBCT:
355
+ res = s->hbct;
356
+ break;
357
+ case SDHBLC:
358
+ res = s->hblc;
359
+ break;
360
+
361
+ default:
362
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
363
+ __func__, offset);
364
+ res = 0;
365
+ break;
366
+ }
367
+
368
+ return res;
369
+}
370
+
371
+static void bcm2835_sdhost_write(void *opaque, hwaddr offset,
372
+ uint64_t value, unsigned size)
373
+{
374
+ BCM2835SDHostState *s = (BCM2835SDHostState *)opaque;
375
+
376
+ switch (offset) {
377
+ case SDCMD:
378
+ s->cmd = value;
379
+ if (value & SDCMD_NEW_FLAG) {
380
+ bcm2835_sdhost_send_command(s);
381
+ bcm2835_sdhost_fifo_run(s);
382
+ s->cmd &= ~SDCMD_NEW_FLAG;
383
+ }
32
+ }
384
+ break;
33
+ break;
385
+ case SDTOUT:
34
+ case 0x1: case 0x3: /* UNALLOCATED */
35
+ unallocated_encoding(s);
386
+ break;
36
+ break;
387
+ case SDCDIV:
37
+ case 0x2:
38
+ if (!disas_sve(s, insn)) {
39
+ unallocated_encoding(s);
40
+ }
388
+ break;
41
+ break;
389
+ case SDHSTS:
42
+ case 0x8: case 0x9: /* Data processing - immediate */
390
+ s->status &= ~value;
43
+ disas_data_proc_imm(s, insn);
391
+ bcm2835_sdhost_update_irq(s);
392
+ break;
44
+ break;
393
+ case SDARG:
45
+ case 0xa: case 0xb: /* Branch, exception generation and system insns */
394
+ s->cmdarg = value;
46
+ disas_b_exc_sys(s, insn);
395
+ break;
47
+ break;
396
+ case SDEDM:
48
+ case 0x4:
397
+ if ((value & 0xf) == 0xf) {
49
+ case 0x6:
398
+ /* power down */
50
+ case 0xc:
399
+ value &= ~0xf;
51
+ case 0xe: /* Loads and stores */
400
+ }
52
+ disas_ldst(s, insn);
401
+ s->edm = value;
402
+ break;
53
+ break;
403
+ case SDHCFG:
54
+ case 0x5:
404
+ s->config = value;
55
+ case 0xd: /* Data processing - register */
405
+ bcm2835_sdhost_fifo_run(s);
56
+ disas_data_proc_reg(s, insn);
406
+ break;
57
+ break;
407
+ case SDVDD:
58
+ case 0x7:
408
+ s->vdd = value;
59
+ case 0xf: /* Data processing - SIMD and floating point */
60
+ disas_data_proc_simd_fp(s, insn);
409
+ break;
61
+ break;
410
+ case SDDATA:
411
+ bcm2835_sdhost_fifo_push(s, value);
412
+ bcm2835_sdhost_fifo_run(s);
413
+ break;
414
+ case SDHBCT:
415
+ s->hbct = value;
416
+ break;
417
+ case SDHBLC:
418
+ s->hblc = value;
419
+ s->datacnt = s->hblc * s->hbct;
420
+ bcm2835_sdhost_fifo_run(s);
421
+ break;
422
+
423
+ default:
62
+ default:
424
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
63
+ assert(FALSE); /* all 15 cases should be handled above */
425
+ __func__, offset);
426
+ break;
64
+ break;
427
+ }
65
+ }
428
+}
66
+}
429
+
67
+
430
+static const MemoryRegionOps bcm2835_sdhost_ops = {
68
static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
431
+ .read = bcm2835_sdhost_read,
69
CPUState *cpu)
432
+ .write = bcm2835_sdhost_write,
70
{
433
+ .endianness = DEVICE_NATIVE_ENDIAN,
71
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
434
+};
72
disas_sme_fa64(s, insn);
435
+
73
}
436
+static const VMStateDescription vmstate_bcm2835_sdhost = {
74
437
+ .name = TYPE_BCM2835_SDHOST,
75
- switch (extract32(insn, 25, 4)) {
438
+ .version_id = 1,
76
- case 0x0:
439
+ .minimum_version_id = 1,
77
- if (!extract32(insn, 31, 1) || !disas_sme(s, insn)) {
440
+ .fields = (VMStateField[]) {
78
- unallocated_encoding(s);
441
+ VMSTATE_UINT32(cmd, BCM2835SDHostState),
79
- }
442
+ VMSTATE_UINT32(cmdarg, BCM2835SDHostState),
80
- break;
443
+ VMSTATE_UINT32(status, BCM2835SDHostState),
81
- case 0x1: case 0x3: /* UNALLOCATED */
444
+ VMSTATE_UINT32_ARRAY(rsp, BCM2835SDHostState, 4),
82
- unallocated_encoding(s);
445
+ VMSTATE_UINT32(config, BCM2835SDHostState),
83
- break;
446
+ VMSTATE_UINT32(edm, BCM2835SDHostState),
84
- case 0x2:
447
+ VMSTATE_UINT32(vdd, BCM2835SDHostState),
85
- if (!disas_sve(s, insn)) {
448
+ VMSTATE_UINT32(hbct, BCM2835SDHostState),
86
- unallocated_encoding(s);
449
+ VMSTATE_UINT32(hblc, BCM2835SDHostState),
87
- }
450
+ VMSTATE_INT32(fifo_pos, BCM2835SDHostState),
88
- break;
451
+ VMSTATE_INT32(fifo_len, BCM2835SDHostState),
89
- case 0x8: case 0x9: /* Data processing - immediate */
452
+ VMSTATE_UINT32_ARRAY(fifo, BCM2835SDHostState, BCM2835_SDHOST_FIFO_LEN),
90
- disas_data_proc_imm(s, insn);
453
+ VMSTATE_UINT32(datacnt, BCM2835SDHostState),
91
- break;
454
+ VMSTATE_END_OF_LIST()
92
- case 0xa: case 0xb: /* Branch, exception generation and system insns */
455
+ }
93
- disas_b_exc_sys(s, insn);
456
+};
94
- break;
457
+
95
- case 0x4:
458
+static void bcm2835_sdhost_init(Object *obj)
96
- case 0x6:
459
+{
97
- case 0xc:
460
+ BCM2835SDHostState *s = BCM2835_SDHOST(obj);
98
- case 0xe: /* Loads and stores */
461
+
99
- disas_ldst(s, insn);
462
+ qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
100
- break;
463
+ TYPE_BCM2835_SDHOST_BUS, DEVICE(s), "sd-bus");
101
- case 0x5:
464
+
102
- case 0xd: /* Data processing - register */
465
+ memory_region_init_io(&s->iomem, obj, &bcm2835_sdhost_ops, s,
103
- disas_data_proc_reg(s, insn);
466
+ TYPE_BCM2835_SDHOST, 0x1000);
104
- break;
467
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
105
- case 0x7:
468
+ sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
106
- case 0xf: /* Data processing - SIMD and floating point */
469
+}
107
- disas_data_proc_simd_fp(s, insn);
470
+
108
- break;
471
+static void bcm2835_sdhost_reset(DeviceState *dev)
109
- default:
472
+{
110
- assert(FALSE); /* all 15 cases should be handled above */
473
+ BCM2835SDHostState *s = BCM2835_SDHOST(dev);
111
- break;
474
+
112
- }
475
+ s->cmd = 0;
113
+ disas_a64_legacy(s, insn);
476
+ s->cmdarg = 0;
114
477
+ s->edm = 0x0000c60f;
115
/*
478
+ s->config = 0;
116
* After execution of most insns, btype is reset to 0.
479
+ s->hbct = 0;
480
+ s->hblc = 0;
481
+ s->datacnt = 0;
482
+ s->fifo_pos = 0;
483
+ s->fifo_len = 0;
484
+}
485
+
486
+static void bcm2835_sdhost_class_init(ObjectClass *klass, void *data)
487
+{
488
+ DeviceClass *dc = DEVICE_CLASS(klass);
489
+
490
+ dc->reset = bcm2835_sdhost_reset;
491
+ dc->vmsd = &vmstate_bcm2835_sdhost;
492
+}
493
+
494
+static TypeInfo bcm2835_sdhost_info = {
495
+ .name = TYPE_BCM2835_SDHOST,
496
+ .parent = TYPE_SYS_BUS_DEVICE,
497
+ .instance_size = sizeof(BCM2835SDHostState),
498
+ .class_init = bcm2835_sdhost_class_init,
499
+ .instance_init = bcm2835_sdhost_init,
500
+};
501
+
502
+static const TypeInfo bcm2835_sdhost_bus_info = {
503
+ .name = TYPE_BCM2835_SDHOST_BUS,
504
+ .parent = TYPE_SD_BUS,
505
+ .instance_size = sizeof(SDBus),
506
+};
507
+
508
+static void bcm2835_sdhost_register_types(void)
509
+{
510
+ type_register_static(&bcm2835_sdhost_info);
511
+ type_register_static(&bcm2835_sdhost_bus_info);
512
+}
513
+
514
+type_init(bcm2835_sdhost_register_types)
515
--
117
--
516
2.7.4
118
2.34.1
517
518
diff view generated by jsdifflib
1
From: Krzysztof Kozlowski <krzk@kernel.org>
1
The A64 translator uses a hand-written decoder for everything except
2
SVE or SME. It's fairly well structured, but it's becoming obvious
3
that it's still more painful to add instructions to than the A32
4
translator, because putting a new instruction into the right place in
5
a hand-written decoder is much harder than adding new instruction
6
patterns to a decodetree file.
2
7
3
Without any clock controller, the Linux kernel was hitting division by
8
As the first step in conversion to decodetree, create the skeleton of
4
zero during boot or with clk_summary:
9
the decodetree decoder; where it does not handle instructions we will
5
[ 0.000000] [<c031054c>] (unwind_backtrace) from [<c030ba6c>] (show_stack+0x10/0x14)
10
fall back to the legacy decoder (which will be for everything at the
6
[ 0.000000] [<c030ba6c>] (show_stack) from [<c05b2660>] (dump_stack+0x88/0x9c)
11
moment, since there are no patterns in a64.decode).
7
[ 0.000000] [<c05b2660>] (dump_stack) from [<c05b11a4>] (Ldiv0+0x8/0x10)
8
[ 0.000000] [<c05b11a4>] (Ldiv0) from [<c06ad1e0>] (samsung_pll45xx_recalc_rate+0x58/0x74)
9
[ 0.000000] [<c06ad1e0>] (samsung_pll45xx_recalc_rate) from [<c0692ec0>] (clk_register+0x39c/0x63c)
10
[ 0.000000] [<c0692ec0>] (clk_register) from [<c125d360>] (samsung_clk_register_pll+0x2e0/0x3d4)
11
[ 0.000000] [<c125d360>] (samsung_clk_register_pll) from [<c125d7e8>] (exynos4_clk_init+0x1b0/0x5e4)
12
[ 0.000000] [<c125d7e8>] (exynos4_clk_init) from [<c12335f4>] (of_clk_init+0x17c/0x210)
13
[ 0.000000] [<c12335f4>] (of_clk_init) from [<c1204700>] (time_init+0x24/0x2c)
14
[ 0.000000] [<c1204700>] (time_init) from [<c1200b2c>] (start_kernel+0x24c/0x38c)
15
[ 0.000000] [<c1200b2c>] (start_kernel) from [<4020807c>] (0x4020807c)
16
12
17
Provide stub for clock controller returning reset values for PLLs.
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20230512144106.3608981-3-peter.maydell@linaro.org
16
---
17
target/arm/tcg/a64.decode | 20 ++++++++++++++++++++
18
target/arm/tcg/translate-a64.c | 18 +++++++++++-------
19
target/arm/tcg/meson.build | 1 +
20
3 files changed, 32 insertions(+), 7 deletions(-)
21
create mode 100644 target/arm/tcg/a64.decode
18
22
19
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
23
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
20
Message-id: 20170226200142.31169-1-krzk@kernel.org
21
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
24
hw/misc/Makefile.objs | 2 +-
25
hw/arm/exynos4210.c | 6 ++
26
hw/misc/exynos4210_clk.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++
27
3 files changed, 171 insertions(+), 1 deletion(-)
28
create mode 100644 hw/misc/exynos4210_clk.c
29
30
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/misc/Makefile.objs
33
+++ b/hw/misc/Makefile.objs
34
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_IVSHMEM) += ivshmem.o
35
obj-$(CONFIG_REALVIEW) += arm_sysctl.o
36
obj-$(CONFIG_NSERIES) += cbus.o
37
obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
38
-obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o
39
+obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o exynos4210_clk.o
40
obj-$(CONFIG_IMX) += imx_ccm.o
41
obj-$(CONFIG_IMX) += imx31_ccm.o
42
obj-$(CONFIG_IMX) += imx25_ccm.o
43
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/arm/exynos4210.c
46
+++ b/hw/arm/exynos4210.c
47
@@ -XXX,XX +XXX,XX @@
48
#include "qemu/osdep.h"
49
#include "qapi/error.h"
50
#include "qemu-common.h"
51
+#include "qemu/log.h"
52
#include "cpu.h"
53
#include "hw/boards.h"
54
#include "sysemu/sysemu.h"
55
@@ -XXX,XX +XXX,XX @@
56
/* PMU SFR base address */
57
#define EXYNOS4210_PMU_BASE_ADDR 0x10020000
58
59
+/* Clock controller SFR base address */
60
+#define EXYNOS4210_CLK_BASE_ADDR 0x10030000
61
+
62
/* Display controllers (FIMD) */
63
#define EXYNOS4210_FIMD0_BASE_ADDR 0x11C00000
64
65
@@ -XXX,XX +XXX,XX @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
66
*/
67
sysbus_create_simple("exynos4210.pmu", EXYNOS4210_PMU_BASE_ADDR, NULL);
68
69
+ sysbus_create_simple("exynos4210.clk", EXYNOS4210_CLK_BASE_ADDR, NULL);
70
+
71
/* PWM */
72
sysbus_create_varargs("exynos4210.pwm", EXYNOS4210_PWM_BASE_ADDR,
73
s->irq_table[exynos4210_get_irq(22, 0)],
74
diff --git a/hw/misc/exynos4210_clk.c b/hw/misc/exynos4210_clk.c
75
new file mode 100644
24
new file mode 100644
76
index XXXXXXX..XXXXXXX
25
index XXXXXXX..XXXXXXX
77
--- /dev/null
26
--- /dev/null
78
+++ b/hw/misc/exynos4210_clk.c
27
+++ b/target/arm/tcg/a64.decode
79
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@
29
+# AArch64 A64 allowed instruction decoding
30
+#
31
+# Copyright (c) 2023 Linaro, Ltd
32
+#
33
+# This library is free software; you can redistribute it and/or
34
+# modify it under the terms of the GNU Lesser General Public
35
+# License as published by the Free Software Foundation; either
36
+# version 2.1 of the License, or (at your option) any later version.
37
+#
38
+# This library is distributed in the hope that it will be useful,
39
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
40
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41
+# Lesser General Public License for more details.
42
+#
43
+# You should have received a copy of the GNU Lesser General Public
44
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
45
+
46
+#
47
+# This file is processed by scripts/decodetree.py
48
+#
49
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/tcg/translate-a64.c
52
+++ b/target/arm/tcg/translate-a64.c
53
@@ -XXX,XX +XXX,XX @@ enum a64_shift_type {
54
A64_SHIFT_TYPE_ROR = 3
55
};
56
80
+/*
57
+/*
81
+ * Exynos4210 Clock Controller Emulation
58
+ * Include the generated decoders.
82
+ *
83
+ * Copyright (c) 2017 Krzysztof Kozlowski <krzk@kernel.org>
84
+ *
85
+ * This program is free software; you can redistribute it and/or modify it
86
+ * under the terms of the GNU General Public License as published by the
87
+ * Free Software Foundation; either version 2 of the License, or
88
+ * (at your option) any later version.
89
+ *
90
+ * This program is distributed in the hope that it will be useful, but WITHOUT
91
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
92
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
93
+ * for more details.
94
+ *
95
+ * You should have received a copy of the GNU General Public License along
96
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
97
+ */
59
+ */
98
+
60
+
99
+#include "qemu/osdep.h"
61
+#include "decode-sme-fa64.c.inc"
100
+#include "hw/sysbus.h"
62
+#include "decode-a64.c.inc"
101
+#include "qemu/log.h"
102
+
63
+
103
+#define TYPE_EXYNOS4210_CLK "exynos4210.clk"
64
/* Table based decoder typedefs - used when the relevant bits for decode
104
+#define EXYNOS4210_CLK(obj) \
65
* are too awkwardly scattered across the instruction (eg SIMD).
105
+ OBJECT_CHECK(Exynos4210ClkState, (obj), TYPE_EXYNOS4210_CLK)
66
*/
67
@@ -XXX,XX +XXX,XX @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
68
}
69
}
70
71
-/*
72
- * Include the generated SME FA64 decoder.
73
- */
74
-
75
-#include "decode-sme-fa64.c.inc"
76
-
77
static bool trans_OK(DisasContext *s, arg_OK *a)
78
{
79
return true;
80
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
81
disas_sme_fa64(s, insn);
82
}
83
84
- disas_a64_legacy(s, insn);
106
+
85
+
107
+#define CLK_PLL_LOCKED BIT(29)
86
+ if (!disas_a64(s, insn)) {
108
+
87
+ disas_a64_legacy(s, insn);
109
+#define EXYNOS4210_CLK_REGS_MEM_SIZE 0x15104
110
+
111
+typedef struct Exynos4210Reg {
112
+ const char *name; /* for debug only */
113
+ uint32_t offset;
114
+ uint32_t reset_value;
115
+} Exynos4210Reg;
116
+
117
+/* Clock controller register base: 0x10030000 */
118
+static const Exynos4210Reg exynos4210_clk_regs[] = {
119
+ {"EPLL_LOCK", 0xc010, 0x00000fff},
120
+ {"VPLL_LOCK", 0xc020, 0x00000fff},
121
+ {"EPLL_CON0", 0xc110, 0x00300301 | CLK_PLL_LOCKED},
122
+ {"EPLL_CON1", 0xc114, 0x00000000},
123
+ {"VPLL_CON0", 0xc120, 0x00240201 | CLK_PLL_LOCKED},
124
+ {"VPLL_CON1", 0xc124, 0x66010464},
125
+ {"APLL_LOCK", 0x14000, 0x00000fff},
126
+ {"MPLL_LOCK", 0x14004, 0x00000fff},
127
+ {"APLL_CON0", 0x14100, 0x00c80601 | CLK_PLL_LOCKED},
128
+ {"APLL_CON1", 0x14104, 0x0000001c},
129
+ {"MPLL_CON0", 0x14108, 0x00c80601 | CLK_PLL_LOCKED},
130
+ {"MPLL_CON1", 0x1410c, 0x0000001c},
131
+};
132
+
133
+#define EXYNOS4210_REGS_NUM ARRAY_SIZE(exynos4210_clk_regs)
134
+
135
+typedef struct Exynos4210ClkState {
136
+ SysBusDevice parent_obj;
137
+
138
+ MemoryRegion iomem;
139
+ uint32_t reg[EXYNOS4210_REGS_NUM];
140
+} Exynos4210ClkState;
141
+
142
+static uint64_t exynos4210_clk_read(void *opaque, hwaddr offset,
143
+ unsigned size)
144
+{
145
+ const Exynos4210ClkState *s = (Exynos4210ClkState *)opaque;
146
+ const Exynos4210Reg *regs = exynos4210_clk_regs;
147
+ unsigned int i;
148
+
149
+ for (i = 0; i < EXYNOS4210_REGS_NUM; i++) {
150
+ if (regs->offset == offset) {
151
+ return s->reg[i];
152
+ }
153
+ regs++;
154
+ }
88
+ }
155
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad read offset 0x%04x\n",
89
156
+ __func__, (uint32_t)offset);
90
/*
157
+ return 0;
91
* After execution of most insns, btype is reset to 0.
158
+}
92
diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build
159
+
93
index XXXXXXX..XXXXXXX 100644
160
+static void exynos4210_clk_write(void *opaque, hwaddr offset,
94
--- a/target/arm/tcg/meson.build
161
+ uint64_t val, unsigned size)
95
+++ b/target/arm/tcg/meson.build
162
+{
96
@@ -XXX,XX +XXX,XX @@ gen = [
163
+ Exynos4210ClkState *s = (Exynos4210ClkState *)opaque;
97
decodetree.process('a32-uncond.decode', extra_args: '--static-decode=disas_a32_uncond'),
164
+ const Exynos4210Reg *regs = exynos4210_clk_regs;
98
decodetree.process('t32.decode', extra_args: '--static-decode=disas_t32'),
165
+ unsigned int i;
99
decodetree.process('t16.decode', extra_args: ['-w', '16', '--static-decode=disas_t16']),
166
+
100
+ decodetree.process('a64.decode', extra_args: ['--static-decode=disas_a64']),
167
+ for (i = 0; i < EXYNOS4210_REGS_NUM; i++) {
101
]
168
+ if (regs->offset == offset) {
102
169
+ s->reg[i] = val;
103
arm_ss.add(gen)
170
+ return;
171
+ }
172
+ regs++;
173
+ }
174
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write offset 0x%04x\n",
175
+ __func__, (uint32_t)offset);
176
+}
177
+
178
+static const MemoryRegionOps exynos4210_clk_ops = {
179
+ .read = exynos4210_clk_read,
180
+ .write = exynos4210_clk_write,
181
+ .endianness = DEVICE_NATIVE_ENDIAN,
182
+ .valid = {
183
+ .min_access_size = 4,
184
+ .max_access_size = 4,
185
+ .unaligned = false
186
+ }
187
+};
188
+
189
+static void exynos4210_clk_reset(DeviceState *dev)
190
+{
191
+ Exynos4210ClkState *s = EXYNOS4210_CLK(dev);
192
+ unsigned int i;
193
+
194
+ /* Set default values for registers */
195
+ for (i = 0; i < EXYNOS4210_REGS_NUM; i++) {
196
+ s->reg[i] = exynos4210_clk_regs[i].reset_value;
197
+ }
198
+}
199
+
200
+static void exynos4210_clk_init(Object *obj)
201
+{
202
+ Exynos4210ClkState *s = EXYNOS4210_CLK(obj);
203
+ SysBusDevice *dev = SYS_BUS_DEVICE(obj);
204
+
205
+ /* memory mapping */
206
+ memory_region_init_io(&s->iomem, obj, &exynos4210_clk_ops, s,
207
+ TYPE_EXYNOS4210_CLK, EXYNOS4210_CLK_REGS_MEM_SIZE);
208
+ sysbus_init_mmio(dev, &s->iomem);
209
+}
210
+
211
+static const VMStateDescription exynos4210_clk_vmstate = {
212
+ .name = TYPE_EXYNOS4210_CLK,
213
+ .version_id = 1,
214
+ .minimum_version_id = 1,
215
+ .fields = (VMStateField[]) {
216
+ VMSTATE_UINT32_ARRAY(reg, Exynos4210ClkState, EXYNOS4210_REGS_NUM),
217
+ VMSTATE_END_OF_LIST()
218
+ }
219
+};
220
+
221
+static void exynos4210_clk_class_init(ObjectClass *klass, void *data)
222
+{
223
+ DeviceClass *dc = DEVICE_CLASS(klass);
224
+
225
+ dc->reset = exynos4210_clk_reset;
226
+ dc->vmsd = &exynos4210_clk_vmstate;
227
+}
228
+
229
+static const TypeInfo exynos4210_clk_info = {
230
+ .name = TYPE_EXYNOS4210_CLK,
231
+ .parent = TYPE_SYS_BUS_DEVICE,
232
+ .instance_size = sizeof(Exynos4210ClkState),
233
+ .instance_init = exynos4210_clk_init,
234
+ .class_init = exynos4210_clk_class_init,
235
+};
236
+
237
+static void exynos4210_clk_register(void)
238
+{
239
+ qemu_log_mask(LOG_GUEST_ERROR, "Clock init\n");
240
+ type_register_static(&exynos4210_clk_info);
241
+}
242
+
243
+type_init(exynos4210_clk_register)
244
--
104
--
245
2.7.4
105
2.34.1
246
247
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
The SVE and SME decode is already done by decodetree. Pull the calls
2
to these decoders out of the legacy decoder. This doesn't change
3
behaviour because all the patterns in sve.decode and sme.decode
4
already require the bits that the legacy decoder is decoding to have
5
the correct values.
2
6
3
The VECTCLRACTIVE and VECTRESET bits in the AIRCR are both
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
documented as UNPREDICTABLE if you write a 1 to them when
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
the processor is not halted in Debug state (ie stopped
9
Message-id: 20230512144106.3608981-4-peter.maydell@linaro.org
6
and under the control of an external JTAG debugger).
10
---
7
Since we don't implement Debug state or emulated JTAG
11
target/arm/tcg/translate-a64.c | 20 ++++----------------
8
these bits are always UNPREDICTABLE for us. Instead of
12
1 file changed, 4 insertions(+), 16 deletions(-)
9
logging them as unimplemented we can simply log writes
10
as guest errors and ignore them.
11
13
12
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
14
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
13
[PMM: change extracted from another patch; commit message
14
constructed from scratch]
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
18
---
19
hw/intc/armv7m_nvic.c | 8 ++++++--
20
1 file changed, 6 insertions(+), 2 deletions(-)
21
22
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
23
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/intc/armv7m_nvic.c
16
--- a/target/arm/tcg/translate-a64.c
25
+++ b/hw/intc/armv7m_nvic.c
17
+++ b/target/arm/tcg/translate-a64.c
26
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
18
@@ -XXX,XX +XXX,XX @@ static bool btype_destination_ok(uint32_t insn, bool bt, int btype)
27
qemu_irq_pulse(s->sysresetreq);
19
static void disas_a64_legacy(DisasContext *s, uint32_t insn)
28
}
20
{
29
if (value & 2) {
21
switch (extract32(insn, 25, 4)) {
30
- qemu_log_mask(LOG_UNIMP, "VECTCLRACTIVE unimplemented\n");
22
- case 0x0:
31
+ qemu_log_mask(LOG_GUEST_ERROR,
23
- if (!extract32(insn, 31, 1) || !disas_sme(s, insn)) {
32
+ "Setting VECTCLRACTIVE when not in DEBUG mode "
24
- unallocated_encoding(s);
33
+ "is UNPREDICTABLE\n");
25
- }
34
}
26
- break;
35
if (value & 1) {
27
- case 0x1: case 0x3: /* UNALLOCATED */
36
- qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n");
28
- unallocated_encoding(s);
37
+ qemu_log_mask(LOG_GUEST_ERROR,
29
- break;
38
+ "Setting VECTRESET when not in DEBUG mode "
30
- case 0x2:
39
+ "is UNPREDICTABLE\n");
31
- if (!disas_sve(s, insn)) {
40
}
32
- unallocated_encoding(s);
41
s->prigroup = extract32(value, 8, 3);
33
- }
42
nvic_irq_update(s);
34
- break;
35
case 0x8: case 0x9: /* Data processing - immediate */
36
disas_data_proc_imm(s, insn);
37
break;
38
@@ -XXX,XX +XXX,XX @@ static void disas_a64_legacy(DisasContext *s, uint32_t insn)
39
disas_data_proc_simd_fp(s, insn);
40
break;
41
default:
42
- assert(FALSE); /* all 15 cases should be handled above */
43
+ unallocated_encoding(s);
44
break;
45
}
46
}
47
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
48
disas_sme_fa64(s, insn);
49
}
50
51
-
52
- if (!disas_a64(s, insn)) {
53
+ if (!disas_a64(s, insn) &&
54
+ !disas_sme(s, insn) &&
55
+ !disas_sve(s, insn)) {
56
disas_a64_legacy(s, insn);
57
}
58
43
--
59
--
44
2.7.4
60
2.34.1
45
46
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Provide a new function sdbus_reparent_card() in sd core for reparenting
3
Convert the ADR and ADRP instructions.
4
a card from a SDBus to another one.
5
4
6
This function is required by the raspi platform, where the two SD
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
controllers can be dynamically switched.
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
9
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
10
Message-id: 20170224164021.9066-3-clement.deschamps@antfield.fr
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
[PMM: added a doc comment to the header file]
8
Message-id: 20230512144106.3608981-5-peter.maydell@linaro.org
9
[PMM: Rebased]
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
12
---
15
include/hw/sd/sd.h | 11 +++++++++++
13
target/arm/tcg/a64.decode | 13 ++++++++++++
16
hw/sd/core.c | 30 ++++++++++++++++++++++++++++++
14
target/arm/tcg/translate-a64.c | 38 +++++++++++++---------------------
17
2 files changed, 41 insertions(+)
15
2 files changed, 27 insertions(+), 24 deletions(-)
18
16
19
diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
17
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
20
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/sd/sd.h
19
--- a/target/arm/tcg/a64.decode
22
+++ b/include/hw/sd/sd.h
20
+++ b/target/arm/tcg/a64.decode
23
@@ -XXX,XX +XXX,XX @@ uint8_t sdbus_read_data(SDBus *sd);
21
@@ -XXX,XX +XXX,XX @@
24
bool sdbus_data_ready(SDBus *sd);
22
#
25
bool sdbus_get_inserted(SDBus *sd);
23
# This file is processed by scripts/decodetree.py
26
bool sdbus_get_readonly(SDBus *sd);
24
#
27
+/**
25
+
28
+ * sdbus_reparent_card: Reparent an SD card from one controller to another
26
+&ri rd imm
29
+ * @from: controller bus to remove card from
27
+
30
+ * @to: controller bus to move card to
28
+
31
+ *
29
+### Data Processing - Immediate
32
+ * Reparent an SD card, effectively unplugging it from one controller
30
+
33
+ * and inserting it into another. This is useful for SoCs like the
31
+# PC-rel addressing
34
+ * bcm2835 which have two SD controllers and connect a single SD card
32
+
35
+ * to them, selected by the guest reprogramming GPIO line routing.
33
+%imm_pcrel 5:s19 29:2
36
+ */
34
+@pcrel . .. ..... ................... rd:5 &ri imm=%imm_pcrel
37
+void sdbus_reparent_card(SDBus *from, SDBus *to);
35
+
38
36
+ADR 0 .. 10000 ................... ..... @pcrel
39
/* Functions to be used by SD devices to report back to qdevified controllers */
37
+ADRP 1 .. 10000 ................... ..... @pcrel
40
void sdbus_set_inserted(SDBus *sd, bool inserted);
38
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
41
diff --git a/hw/sd/core.c b/hw/sd/core.c
42
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/sd/core.c
40
--- a/target/arm/tcg/translate-a64.c
44
+++ b/hw/sd/core.c
41
+++ b/target/arm/tcg/translate-a64.c
45
@@ -XXX,XX +XXX,XX @@ void sdbus_set_readonly(SDBus *sdbus, bool readonly)
42
@@ -XXX,XX +XXX,XX @@ static void disas_ldst(DisasContext *s, uint32_t insn)
46
}
43
}
47
}
44
}
48
45
49
+void sdbus_reparent_card(SDBus *from, SDBus *to)
46
-/* PC-rel. addressing
47
- * 31 30 29 28 24 23 5 4 0
48
- * +----+-------+-----------+-------------------+------+
49
- * | op | immlo | 1 0 0 0 0 | immhi | Rd |
50
- * +----+-------+-----------+-------------------+------+
51
+/*
52
+ * PC-rel. addressing
53
*/
54
-static void disas_pc_rel_adr(DisasContext *s, uint32_t insn)
55
+
56
+static bool trans_ADR(DisasContext *s, arg_ri *a)
57
{
58
- unsigned int page, rd;
59
- int64_t offset;
60
+ gen_pc_plus_diff(s, cpu_reg(s, a->rd), a->imm);
61
+ return true;
62
+}
63
64
- page = extract32(insn, 31, 1);
65
- /* SignExtend(immhi:immlo) -> offset */
66
- offset = sextract64(insn, 5, 19);
67
- offset = offset << 2 | extract32(insn, 29, 2);
68
- rd = extract32(insn, 0, 5);
69
+static bool trans_ADRP(DisasContext *s, arg_ri *a)
50
+{
70
+{
51
+ BusChild *kid = QTAILQ_FIRST(&from->qbus.children);
71
+ int64_t offset = (int64_t)a->imm << 12;
52
+ SDState *card;
72
53
+ SDCardClass *sc;
73
- if (page) {
54
+ bool readonly;
74
- /* ADRP (page based) */
55
+
75
- offset <<= 12;
56
+ /* We directly reparent the card object rather than implementing this
76
- /* The page offset is ok for CF_PCREL. */
57
+ * as a hotpluggable connection because we don't want to expose SD cards
77
- offset -= s->pc_curr & 0xfff;
58
+ * to users as being hotpluggable, and we can get away with it in this
78
- }
59
+ * limited use case. This could perhaps be implemented more cleanly in
79
-
60
+ * future by adding support to the hotplug infrastructure for "device
80
- gen_pc_plus_diff(s, cpu_reg(s, rd), offset);
61
+ * can be hotplugged only via code, not by user".
81
+ /* The page offset is ok for CF_PCREL. */
62
+ */
82
+ offset -= s->pc_curr & 0xfff;
63
+
83
+ gen_pc_plus_diff(s, cpu_reg(s, a->rd), offset);
64
+ if (!kid) {
84
+ return true;
65
+ return;
85
}
66
+ }
86
67
+
87
/*
68
+ card = SD_CARD(kid->child);
88
@@ -XXX,XX +XXX,XX @@ static void disas_extract(DisasContext *s, uint32_t insn)
69
+ sc = SD_CARD_GET_CLASS(card);
89
static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
70
+ readonly = sc->get_readonly(card);
90
{
71
+
91
switch (extract32(insn, 23, 6)) {
72
+ sdbus_set_inserted(from, false);
92
- case 0x20: case 0x21: /* PC-rel. addressing */
73
+ object_unparent(OBJECT(kid));
93
- disas_pc_rel_adr(s, insn);
74
+ qdev_set_parent_bus(DEVICE(card), &to->qbus);
94
- break;
75
+ sdbus_set_inserted(to, true);
95
case 0x22: /* Add/subtract (immediate) */
76
+ sdbus_set_readonly(to, readonly);
96
disas_add_sub_imm(s, insn);
77
+}
97
break;
78
+
79
static const TypeInfo sd_bus_info = {
80
.name = TYPE_SD_BUS,
81
.parent = TYPE_BUS,
82
--
98
--
83
2.7.4
99
2.34.1
84
85
diff view generated by jsdifflib
1
From: Kurban Mallachiev <mallachiev@ispras.ru>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The i.MX timer device can be reset by writing to the SWR bit
3
Split out specific 32-bit and 64-bit functions.
4
of the CR register. This has to behave differently from hard
4
These carry the same signature as tcg_gen_add_i64,
5
(power-on) reset because it does not reset all of the bits
5
and so will be easier to pass as callbacks.
6
in the CR register.
7
6
8
We were incorrectly implementing soft reset and hard reset
7
Retain gen_add_CC and gen_sub_CC during conversion.
9
the same way, and in addition had a logic error which meant
10
that we were clearing the bits that soft-reset is supposed
11
to preserve and not touching the bits that soft-reset clears.
12
This was not correct behaviour for either kind of reset.
13
8
14
Separate out the soft reset and hard reset code paths, and
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
correct the handling of reset of the CR register so that it
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
is correct in both cases.
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
12
Message-id: 20230512144106.3608981-6-peter.maydell@linaro.org
18
Signed-off-by: Kurban Mallachiev <mallachiev@ispras.ru>
13
[PMM: rebased]
19
[PMM: rephrased commit message, spacing on operators;
20
use bool rather than int for is_soft_reset]
21
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
16
---
24
hw/timer/imx_gpt.c | 33 +++++++++++++++++++++++++--------
17
target/arm/tcg/translate-a64.c | 149 +++++++++++++++++++--------------
25
1 file changed, 25 insertions(+), 8 deletions(-)
18
1 file changed, 84 insertions(+), 65 deletions(-)
26
19
27
diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
20
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
28
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/timer/imx_gpt.c
22
--- a/target/arm/tcg/translate-a64.c
30
+++ b/hw/timer/imx_gpt.c
23
+++ b/target/arm/tcg/translate-a64.c
31
@@ -XXX,XX +XXX,XX @@ static uint64_t imx_gpt_read(void *opaque, hwaddr offset, unsigned size)
24
@@ -XXX,XX +XXX,XX @@ static inline void gen_logic_CC(int sf, TCGv_i64 result)
32
return reg_value;
33
}
25
}
34
26
35
-static void imx_gpt_reset(DeviceState *dev)
27
/* dest = T0 + T1; compute C, N, V and Z flags */
36
-{
28
+static void gen_add64_CC(TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
37
- IMXGPTState *s = IMX_GPT(dev);
38
39
+static void imx_gpt_reset_common(IMXGPTState *s, bool is_soft_reset)
40
+{
29
+{
41
/* stop timer */
30
+ TCGv_i64 result, flag, tmp;
42
ptimer_stop(s->timer);
31
+ result = tcg_temp_new_i64();
43
32
+ flag = tcg_temp_new_i64();
44
- /*
33
+ tmp = tcg_temp_new_i64();
45
- * Soft reset doesn't touch some bits; hard reset clears them
34
+
46
+ /* Soft reset and hard reset differ only in their handling of the CR
35
+ tcg_gen_movi_i64(tmp, 0);
47
+ * register -- soft reset preserves the values of some bits there.
36
+ tcg_gen_add2_i64(result, flag, t0, tmp, t1, tmp);
48
*/
37
+
49
- s->cr &= ~(GPT_CR_EN|GPT_CR_ENMOD|GPT_CR_STOPEN|GPT_CR_DOZEN|
38
+ tcg_gen_extrl_i64_i32(cpu_CF, flag);
50
- GPT_CR_WAITEN|GPT_CR_DBGEN);
39
+
51
+ if (is_soft_reset) {
40
+ gen_set_NZ64(result);
52
+ /* Clear all CR bits except those that are preserved by soft reset. */
41
+
53
+ s->cr &= GPT_CR_EN | GPT_CR_ENMOD | GPT_CR_STOPEN | GPT_CR_DOZEN |
42
+ tcg_gen_xor_i64(flag, result, t0);
54
+ GPT_CR_WAITEN | GPT_CR_DBGEN |
43
+ tcg_gen_xor_i64(tmp, t0, t1);
55
+ (GPT_CR_CLKSRC_MASK << GPT_CR_CLKSRC_SHIFT);
44
+ tcg_gen_andc_i64(flag, flag, tmp);
56
+ } else {
45
+ tcg_gen_extrh_i64_i32(cpu_VF, flag);
57
+ s->cr = 0;
46
+
58
+ }
47
+ tcg_gen_mov_i64(dest, result);
59
s->sr = 0;
48
+}
60
s->pr = 0;
49
+
61
s->ir = 0;
50
+static void gen_add32_CC(TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
62
@@ -XXX,XX +XXX,XX @@ static void imx_gpt_reset(DeviceState *dev)
51
+{
52
+ TCGv_i32 t0_32 = tcg_temp_new_i32();
53
+ TCGv_i32 t1_32 = tcg_temp_new_i32();
54
+ TCGv_i32 tmp = tcg_temp_new_i32();
55
+
56
+ tcg_gen_movi_i32(tmp, 0);
57
+ tcg_gen_extrl_i64_i32(t0_32, t0);
58
+ tcg_gen_extrl_i64_i32(t1_32, t1);
59
+ tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, t1_32, tmp);
60
+ tcg_gen_mov_i32(cpu_ZF, cpu_NF);
61
+ tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
62
+ tcg_gen_xor_i32(tmp, t0_32, t1_32);
63
+ tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
64
+ tcg_gen_extu_i32_i64(dest, cpu_NF);
65
+}
66
+
67
static void gen_add_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
68
{
69
if (sf) {
70
- TCGv_i64 result, flag, tmp;
71
- result = tcg_temp_new_i64();
72
- flag = tcg_temp_new_i64();
73
- tmp = tcg_temp_new_i64();
74
-
75
- tcg_gen_movi_i64(tmp, 0);
76
- tcg_gen_add2_i64(result, flag, t0, tmp, t1, tmp);
77
-
78
- tcg_gen_extrl_i64_i32(cpu_CF, flag);
79
-
80
- gen_set_NZ64(result);
81
-
82
- tcg_gen_xor_i64(flag, result, t0);
83
- tcg_gen_xor_i64(tmp, t0, t1);
84
- tcg_gen_andc_i64(flag, flag, tmp);
85
- tcg_gen_extrh_i64_i32(cpu_VF, flag);
86
-
87
- tcg_gen_mov_i64(dest, result);
88
+ gen_add64_CC(dest, t0, t1);
89
} else {
90
- /* 32 bit arithmetic */
91
- TCGv_i32 t0_32 = tcg_temp_new_i32();
92
- TCGv_i32 t1_32 = tcg_temp_new_i32();
93
- TCGv_i32 tmp = tcg_temp_new_i32();
94
-
95
- tcg_gen_movi_i32(tmp, 0);
96
- tcg_gen_extrl_i64_i32(t0_32, t0);
97
- tcg_gen_extrl_i64_i32(t1_32, t1);
98
- tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, t1_32, tmp);
99
- tcg_gen_mov_i32(cpu_ZF, cpu_NF);
100
- tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
101
- tcg_gen_xor_i32(tmp, t0_32, t1_32);
102
- tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
103
- tcg_gen_extu_i32_i64(dest, cpu_NF);
104
+ gen_add32_CC(dest, t0, t1);
63
}
105
}
64
}
106
}
65
107
66
+static void imx_gpt_soft_reset(DeviceState *dev)
108
/* dest = T0 - T1; compute C, N, V and Z flags */
109
+static void gen_sub64_CC(TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
67
+{
110
+{
68
+ IMXGPTState *s = IMX_GPT(dev);
111
+ /* 64 bit arithmetic */
69
+ imx_gpt_reset_common(s, true);
112
+ TCGv_i64 result, flag, tmp;
113
+
114
+ result = tcg_temp_new_i64();
115
+ flag = tcg_temp_new_i64();
116
+ tcg_gen_sub_i64(result, t0, t1);
117
+
118
+ gen_set_NZ64(result);
119
+
120
+ tcg_gen_setcond_i64(TCG_COND_GEU, flag, t0, t1);
121
+ tcg_gen_extrl_i64_i32(cpu_CF, flag);
122
+
123
+ tcg_gen_xor_i64(flag, result, t0);
124
+ tmp = tcg_temp_new_i64();
125
+ tcg_gen_xor_i64(tmp, t0, t1);
126
+ tcg_gen_and_i64(flag, flag, tmp);
127
+ tcg_gen_extrh_i64_i32(cpu_VF, flag);
128
+ tcg_gen_mov_i64(dest, result);
70
+}
129
+}
71
+
130
+
72
+static void imx_gpt_reset(DeviceState *dev)
131
+static void gen_sub32_CC(TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
73
+{
132
+{
74
+ IMXGPTState *s = IMX_GPT(dev);
133
+ /* 32 bit arithmetic */
75
+ imx_gpt_reset_common(s, false);
134
+ TCGv_i32 t0_32 = tcg_temp_new_i32();
135
+ TCGv_i32 t1_32 = tcg_temp_new_i32();
136
+ TCGv_i32 tmp;
137
+
138
+ tcg_gen_extrl_i64_i32(t0_32, t0);
139
+ tcg_gen_extrl_i64_i32(t1_32, t1);
140
+ tcg_gen_sub_i32(cpu_NF, t0_32, t1_32);
141
+ tcg_gen_mov_i32(cpu_ZF, cpu_NF);
142
+ tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0_32, t1_32);
143
+ tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
144
+ tmp = tcg_temp_new_i32();
145
+ tcg_gen_xor_i32(tmp, t0_32, t1_32);
146
+ tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
147
+ tcg_gen_extu_i32_i64(dest, cpu_NF);
76
+}
148
+}
77
+
149
+
78
static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
150
static void gen_sub_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
79
unsigned size)
80
{
151
{
81
@@ -XXX,XX +XXX,XX @@ static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
152
if (sf) {
82
s->cr = value & ~0x7c14;
153
- /* 64 bit arithmetic */
83
if (s->cr & GPT_CR_SWR) { /* force reset */
154
- TCGv_i64 result, flag, tmp;
84
/* handle the reset */
155
-
85
- imx_gpt_reset(DEVICE(s));
156
- result = tcg_temp_new_i64();
86
+ imx_gpt_soft_reset(DEVICE(s));
157
- flag = tcg_temp_new_i64();
87
} else {
158
- tcg_gen_sub_i64(result, t0, t1);
88
/* set our freq, as the source might have changed */
159
-
89
imx_gpt_set_freq(s);
160
- gen_set_NZ64(result);
161
-
162
- tcg_gen_setcond_i64(TCG_COND_GEU, flag, t0, t1);
163
- tcg_gen_extrl_i64_i32(cpu_CF, flag);
164
-
165
- tcg_gen_xor_i64(flag, result, t0);
166
- tmp = tcg_temp_new_i64();
167
- tcg_gen_xor_i64(tmp, t0, t1);
168
- tcg_gen_and_i64(flag, flag, tmp);
169
- tcg_gen_extrh_i64_i32(cpu_VF, flag);
170
- tcg_gen_mov_i64(dest, result);
171
+ gen_sub64_CC(dest, t0, t1);
172
} else {
173
- /* 32 bit arithmetic */
174
- TCGv_i32 t0_32 = tcg_temp_new_i32();
175
- TCGv_i32 t1_32 = tcg_temp_new_i32();
176
- TCGv_i32 tmp;
177
-
178
- tcg_gen_extrl_i64_i32(t0_32, t0);
179
- tcg_gen_extrl_i64_i32(t1_32, t1);
180
- tcg_gen_sub_i32(cpu_NF, t0_32, t1_32);
181
- tcg_gen_mov_i32(cpu_ZF, cpu_NF);
182
- tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0_32, t1_32);
183
- tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
184
- tmp = tcg_temp_new_i32();
185
- tcg_gen_xor_i32(tmp, t0_32, t1_32);
186
- tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
187
- tcg_gen_extu_i32_i64(dest, cpu_NF);
188
+ gen_sub32_CC(dest, t0, t1);
189
}
190
}
191
90
--
192
--
91
2.7.4
193
2.34.1
92
93
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
In 2.9 ITS will block save/restore and migration use cases. As such,
3
Convert the ADD and SUB (immediate) instructions.
4
let's introduce a user option that allows to turn its instantiation
5
off, along with GICv3. With the "its" option turned false, migration
6
will be possible, obviously at the expense of MSI support (with GICv3).
7
4
8
Signed-off-by: Eric Auger <eric.auger@redhat.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 1487681108-14452-1-git-send-email-eric.auger@redhat.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20230512144106.3608981-7-peter.maydell@linaro.org
9
[PMM: Rebased; adjusted to use translate.h's TRANS macro]
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@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
include/hw/arm/virt.h | 1 +
13
target/arm/tcg/translate.h | 5 +++
14
hw/arm/virt.c | 31 +++++++++++++++++++++++++++++--
14
target/arm/tcg/a64.decode | 17 ++++++++
15
2 files changed, 30 insertions(+), 2 deletions(-)
15
target/arm/tcg/translate-a64.c | 73 ++++++++++------------------------
16
3 files changed, 42 insertions(+), 53 deletions(-)
16
17
17
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
18
diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h
18
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/virt.h
20
--- a/target/arm/tcg/translate.h
20
+++ b/include/hw/arm/virt.h
21
+++ b/target/arm/tcg/translate.h
21
@@ -XXX,XX +XXX,XX @@ typedef struct {
22
@@ -XXX,XX +XXX,XX @@ static inline int rsub_8(DisasContext *s, int x)
22
FWCfgState *fw_cfg;
23
return 8 - x;
23
bool secure;
24
bool highmem;
25
+ bool its;
26
bool virt;
27
int32_t gic_version;
28
struct arm_boot_info bootinfo;
29
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/virt.c
32
+++ b/hw/arm/virt.c
33
@@ -XXX,XX +XXX,XX @@ static void create_v2m(VirtMachineState *vms, qemu_irq *pic)
34
static void create_gic(VirtMachineState *vms, qemu_irq *pic)
35
{
36
/* We create a standalone GIC */
37
- VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
38
DeviceState *gicdev;
39
SysBusDevice *gicbusdev;
40
const char *gictype;
41
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
42
43
fdt_add_gic_node(vms);
44
45
- if (type == 3 && !vmc->no_its) {
46
+ if (type == 3 && vms->its) {
47
create_its(vms, gicdev);
48
} else if (type == 2) {
49
create_v2m(vms, pic);
50
@@ -XXX,XX +XXX,XX @@ static void virt_set_highmem(Object *obj, bool value, Error **errp)
51
vms->highmem = value;
52
}
24
}
53
25
54
+static bool virt_get_its(Object *obj, Error **errp)
26
+static inline int shl_12(DisasContext *s, int x)
55
+{
27
+{
56
+ VirtMachineState *vms = VIRT_MACHINE(obj);
28
+ return x << 12;
57
+
58
+ return vms->its;
59
+}
29
+}
60
+
30
+
61
+static void virt_set_its(Object *obj, bool value, Error **errp)
31
static inline int neon_3same_fp_size(DisasContext *s, int x)
32
{
33
/* Convert 0==fp32, 1==fp16 into a MO_* value */
34
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/tcg/a64.decode
37
+++ b/target/arm/tcg/a64.decode
38
@@ -XXX,XX +XXX,XX @@
39
#
40
41
&ri rd imm
42
+&rri_sf rd rn imm sf
43
44
45
### Data Processing - Immediate
46
@@ -XXX,XX +XXX,XX @@
47
48
ADR 0 .. 10000 ................... ..... @pcrel
49
ADRP 1 .. 10000 ................... ..... @pcrel
50
+
51
+# Add/subtract (immediate)
52
+
53
+%imm12_sh12 10:12 !function=shl_12
54
+@addsub_imm sf:1 .. ...... . imm:12 rn:5 rd:5
55
+@addsub_imm12 sf:1 .. ...... . ............ rn:5 rd:5 imm=%imm12_sh12
56
+
57
+ADD_i . 00 100010 0 ............ ..... ..... @addsub_imm
58
+ADD_i . 00 100010 1 ............ ..... ..... @addsub_imm12
59
+ADDS_i . 01 100010 0 ............ ..... ..... @addsub_imm
60
+ADDS_i . 01 100010 1 ............ ..... ..... @addsub_imm12
61
+
62
+SUB_i . 10 100010 0 ............ ..... ..... @addsub_imm
63
+SUB_i . 10 100010 1 ............ ..... ..... @addsub_imm12
64
+SUBS_i . 11 100010 0 ............ ..... ..... @addsub_imm
65
+SUBS_i . 11 100010 1 ............ ..... ..... @addsub_imm12
66
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/tcg/translate-a64.c
69
+++ b/target/arm/tcg/translate-a64.c
70
@@ -XXX,XX +XXX,XX @@ static void disas_ldst(DisasContext *s, uint32_t insn)
71
}
72
}
73
74
+typedef void ArithTwoOp(TCGv_i64, TCGv_i64, TCGv_i64);
75
+
76
+static bool gen_rri(DisasContext *s, arg_rri_sf *a,
77
+ bool rd_sp, bool rn_sp, ArithTwoOp *fn)
62
+{
78
+{
63
+ VirtMachineState *vms = VIRT_MACHINE(obj);
79
+ TCGv_i64 tcg_rn = rn_sp ? cpu_reg_sp(s, a->rn) : cpu_reg(s, a->rn);
80
+ TCGv_i64 tcg_rd = rd_sp ? cpu_reg_sp(s, a->rd) : cpu_reg(s, a->rd);
81
+ TCGv_i64 tcg_imm = tcg_constant_i64(a->imm);
64
+
82
+
65
+ vms->its = value;
83
+ fn(tcg_rd, tcg_rn, tcg_imm);
84
+ if (!a->sf) {
85
+ tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
86
+ }
87
+ return true;
66
+}
88
+}
67
+
89
+
68
static char *virt_get_gic_version(Object *obj, Error **errp)
90
/*
91
* PC-rel. addressing
92
*/
93
@@ -XXX,XX +XXX,XX @@ static bool trans_ADRP(DisasContext *s, arg_ri *a)
94
95
/*
96
* Add/subtract (immediate)
97
- *
98
- * 31 30 29 28 23 22 21 10 9 5 4 0
99
- * +--+--+--+-------------+--+-------------+-----+-----+
100
- * |sf|op| S| 1 0 0 0 1 0 |sh| imm12 | Rn | Rd |
101
- * +--+--+--+-------------+--+-------------+-----+-----+
102
- *
103
- * sf: 0 -> 32bit, 1 -> 64bit
104
- * op: 0 -> add , 1 -> sub
105
- * S: 1 -> set flags
106
- * sh: 1 -> LSL imm by 12
107
*/
108
-static void disas_add_sub_imm(DisasContext *s, uint32_t insn)
109
-{
110
- int rd = extract32(insn, 0, 5);
111
- int rn = extract32(insn, 5, 5);
112
- uint64_t imm = extract32(insn, 10, 12);
113
- bool shift = extract32(insn, 22, 1);
114
- bool setflags = extract32(insn, 29, 1);
115
- bool sub_op = extract32(insn, 30, 1);
116
- bool is_64bit = extract32(insn, 31, 1);
117
-
118
- TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
119
- TCGv_i64 tcg_rd = setflags ? cpu_reg(s, rd) : cpu_reg_sp(s, rd);
120
- TCGv_i64 tcg_result;
121
-
122
- if (shift) {
123
- imm <<= 12;
124
- }
125
-
126
- tcg_result = tcg_temp_new_i64();
127
- if (!setflags) {
128
- if (sub_op) {
129
- tcg_gen_subi_i64(tcg_result, tcg_rn, imm);
130
- } else {
131
- tcg_gen_addi_i64(tcg_result, tcg_rn, imm);
132
- }
133
- } else {
134
- TCGv_i64 tcg_imm = tcg_constant_i64(imm);
135
- if (sub_op) {
136
- gen_sub_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
137
- } else {
138
- gen_add_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
139
- }
140
- }
141
-
142
- if (is_64bit) {
143
- tcg_gen_mov_i64(tcg_rd, tcg_result);
144
- } else {
145
- tcg_gen_ext32u_i64(tcg_rd, tcg_result);
146
- }
147
-}
148
+TRANS(ADD_i, gen_rri, a, 1, 1, tcg_gen_add_i64)
149
+TRANS(SUB_i, gen_rri, a, 1, 1, tcg_gen_sub_i64)
150
+TRANS(ADDS_i, gen_rri, a, 0, 1, a->sf ? gen_add64_CC : gen_add32_CC)
151
+TRANS(SUBS_i, gen_rri, a, 0, 1, a->sf ? gen_sub64_CC : gen_sub32_CC)
152
153
/*
154
* Add/subtract (immediate, with tags)
155
@@ -XXX,XX +XXX,XX @@ static void disas_extract(DisasContext *s, uint32_t insn)
156
static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
69
{
157
{
70
VirtMachineState *vms = VIRT_MACHINE(obj);
158
switch (extract32(insn, 23, 6)) {
71
@@ -XXX,XX +XXX,XX @@ type_init(machvirt_machine_init);
159
- case 0x22: /* Add/subtract (immediate) */
72
static void virt_2_9_instance_init(Object *obj)
160
- disas_add_sub_imm(s, insn);
73
{
161
- break;
74
VirtMachineState *vms = VIRT_MACHINE(obj);
162
case 0x23: /* Add/subtract (immediate, with tags) */
75
+ VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
163
disas_add_sub_imm_with_tags(s, insn);
76
164
break;
77
/* EL3 is disabled by default on virt: this makes us consistent
78
* between KVM and TCG for this board, and it also allows us to
79
@@ -XXX,XX +XXX,XX @@ static void virt_2_9_instance_init(Object *obj)
80
"Set GIC version. "
81
"Valid values are 2, 3 and host", NULL);
82
83
+ if (vmc->no_its) {
84
+ vms->its = false;
85
+ } else {
86
+ /* Default allows ITS instantiation */
87
+ vms->its = true;
88
+ object_property_add_bool(obj, "its", virt_get_its,
89
+ virt_set_its, NULL);
90
+ object_property_set_description(obj, "its",
91
+ "Set on/off to enable/disable "
92
+ "ITS instantiation",
93
+ NULL);
94
+ }
95
+
96
vms->memmap = a15memmap;
97
vms->irqmap = a15irqmap;
98
}
99
--
165
--
100
2.7.4
166
2.34.1
101
102
diff view generated by jsdifflib
1
From: Krzysztof Kozlowski <krzk@kernel.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The Exynos4210 has cluster ID 0x9 in its MPIDR register (raw value
3
Convert the ADDG and SUBG (immediate) instructions.
4
0x8000090x). If this cluster ID is not provided, then Linux kernel
5
cannot map DeviceTree nodes to MPIDR values resulting in kernel
6
warning and lack of any secondary CPUs:
7
4
8
DT missing boot CPU MPIDR[23:0], fall back to default cpu_logical_map
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
...
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
smp: Bringing up secondary CPUs ...
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
smp: Brought up 1 node, 1 CPU
8
Message-id: 20230512144106.3608981-8-peter.maydell@linaro.org
12
SMP: Total of 1 processors activated (24.00 BogoMIPS).
9
[PMM: Rebased; use TRANS_FEAT()]
13
14
Provide a cluster ID so Linux will see proper MPIDR and will try to
15
bring the secondary CPU online.
16
17
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
18
Message-id: 20170226200142.31169-2-krzk@kernel.org
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
12
---
22
hw/arm/exynos4210.c | 12 ++++++++++++
13
target/arm/tcg/a64.decode | 8 +++++++
23
1 file changed, 12 insertions(+)
14
target/arm/tcg/translate-a64.c | 38 ++++++++++------------------------
15
2 files changed, 19 insertions(+), 27 deletions(-)
24
16
25
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
17
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
26
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/exynos4210.c
19
--- a/target/arm/tcg/a64.decode
28
+++ b/hw/arm/exynos4210.c
20
+++ b/target/arm/tcg/a64.decode
29
@@ -XXX,XX +XXX,XX @@ void exynos4210_write_secondary(ARMCPU *cpu,
21
@@ -XXX,XX +XXX,XX @@ SUB_i . 10 100010 0 ............ ..... ..... @addsub_imm
30
info->smp_loader_start);
22
SUB_i . 10 100010 1 ............ ..... ..... @addsub_imm12
23
SUBS_i . 11 100010 0 ............ ..... ..... @addsub_imm
24
SUBS_i . 11 100010 1 ............ ..... ..... @addsub_imm12
25
+
26
+# Add/subtract (immediate with tags)
27
+
28
+&rri_tag rd rn uimm6 uimm4
29
+@addsub_imm_tag . .. ...... . uimm6:6 .. uimm4:4 rn:5 rd:5 &rri_tag
30
+
31
+ADDG_i 1 00 100011 0 ...... 00 .... ..... ..... @addsub_imm_tag
32
+SUBG_i 1 10 100011 0 ...... 00 .... ..... ..... @addsub_imm_tag
33
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/tcg/translate-a64.c
36
+++ b/target/arm/tcg/translate-a64.c
37
@@ -XXX,XX +XXX,XX @@ TRANS(SUBS_i, gen_rri, a, 0, 1, a->sf ? gen_sub64_CC : gen_sub32_CC)
38
39
/*
40
* Add/subtract (immediate, with tags)
41
- *
42
- * 31 30 29 28 23 22 21 16 14 10 9 5 4 0
43
- * +--+--+--+-------------+--+---------+--+-------+-----+-----+
44
- * |sf|op| S| 1 0 0 0 1 1 |o2| uimm6 |o3| uimm4 | Rn | Rd |
45
- * +--+--+--+-------------+--+---------+--+-------+-----+-----+
46
- *
47
- * op: 0 -> add, 1 -> sub
48
*/
49
-static void disas_add_sub_imm_with_tags(DisasContext *s, uint32_t insn)
50
+
51
+static bool gen_add_sub_imm_with_tags(DisasContext *s, arg_rri_tag *a,
52
+ bool sub_op)
53
{
54
- int rd = extract32(insn, 0, 5);
55
- int rn = extract32(insn, 5, 5);
56
- int uimm4 = extract32(insn, 10, 4);
57
- int uimm6 = extract32(insn, 16, 6);
58
- bool sub_op = extract32(insn, 30, 1);
59
TCGv_i64 tcg_rn, tcg_rd;
60
int imm;
61
62
- /* Test all of sf=1, S=0, o2=0, o3=0. */
63
- if ((insn & 0xa040c000u) != 0x80000000u ||
64
- !dc_isar_feature(aa64_mte_insn_reg, s)) {
65
- unallocated_encoding(s);
66
- return;
67
- }
68
-
69
- imm = uimm6 << LOG2_TAG_GRANULE;
70
+ imm = a->uimm6 << LOG2_TAG_GRANULE;
71
if (sub_op) {
72
imm = -imm;
73
}
74
75
- tcg_rn = cpu_reg_sp(s, rn);
76
- tcg_rd = cpu_reg_sp(s, rd);
77
+ tcg_rn = cpu_reg_sp(s, a->rn);
78
+ tcg_rd = cpu_reg_sp(s, a->rd);
79
80
if (s->ata) {
81
gen_helper_addsubg(tcg_rd, cpu_env, tcg_rn,
82
tcg_constant_i32(imm),
83
- tcg_constant_i32(uimm4));
84
+ tcg_constant_i32(a->uimm4));
85
} else {
86
tcg_gen_addi_i64(tcg_rd, tcg_rn, imm);
87
gen_address_with_allocation_tag0(tcg_rd, tcg_rd);
88
}
89
+ return true;
31
}
90
}
32
91
33
+static uint64_t exynos4210_calc_affinity(int cpu)
92
+TRANS_FEAT(ADDG_i, aa64_mte_insn_reg, gen_add_sub_imm_with_tags, a, false)
34
+{
93
+TRANS_FEAT(SUBG_i, aa64_mte_insn_reg, gen_add_sub_imm_with_tags, a, true)
35
+ uint64_t mp_affinity;
36
+
94
+
37
+ /* Exynos4210 has 0x9 as cluster ID */
95
/* The input should be a value in the bottom e bits (with higher
38
+ mp_affinity = (0x9 << ARM_AFF1_SHIFT) | cpu;
96
* bits zero); returns that value replicated into every element
39
+
97
* of size e in a 64 bit integer.
40
+ return mp_affinity;
98
@@ -XXX,XX +XXX,XX @@ static void disas_extract(DisasContext *s, uint32_t insn)
41
+}
99
static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
42
+
43
Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
44
unsigned long ram_size)
45
{
100
{
46
@@ -XXX,XX +XXX,XX @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
101
switch (extract32(insn, 23, 6)) {
47
}
102
- case 0x23: /* Add/subtract (immediate, with tags) */
48
103
- disas_add_sub_imm_with_tags(s, insn);
49
s->cpu[n] = ARM_CPU(cpuobj);
104
- break;
50
+ object_property_set_int(cpuobj, exynos4210_calc_affinity(n),
105
case 0x24: /* Logical (immediate) */
51
+ "mp-affinity", &error_abort);
106
disas_logic_imm(s, insn);
52
object_property_set_int(cpuobj, EXYNOS4210_SMP_PRIVATE_BASE_ADDR,
107
break;
53
"reset-cbar", &error_abort);
54
object_property_set_bool(cpuobj, true, "realized", &error_fatal);
55
--
108
--
56
2.7.4
109
2.34.1
57
58
diff view generated by jsdifflib
1
From: Igor Mammedov <imammedo@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
object_new(FOO) returns an object with ref_cnt == 1
3
Use the bitops.h macro rather than rolling our own here.
4
and following
5
object_property_set_bool(cpuobj, true, "realized", NULL)
6
set parent of cpuobj to '/machine/unattached' which makes
7
ref_cnt == 2.
8
4
9
Since machvirt_init() doesn't take ownership of cpuobj
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
returned by object_new() it should explicitly drop
11
reference to cpuobj when dangling pointer is about to
12
go out of scope like it's done pc_new_cpu() to avoid
13
object leak.
14
15
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
16
Message-id: 1487253461-269218-1-git-send-email-imammedo@redhat.com
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20230512144106.3608981-9-peter.maydell@linaro.org
19
---
9
---
20
hw/arm/virt.c | 1 +
10
target/arm/tcg/translate-a64.c | 11 ++---------
21
1 file changed, 1 insertion(+)
11
1 file changed, 2 insertions(+), 9 deletions(-)
22
12
23
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
13
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
24
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/arm/virt.c
15
--- a/target/arm/tcg/translate-a64.c
26
+++ b/hw/arm/virt.c
16
+++ b/target/arm/tcg/translate-a64.c
27
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
17
@@ -XXX,XX +XXX,XX @@ static uint64_t bitfield_replicate(uint64_t mask, unsigned int e)
28
}
18
return mask;
29
19
}
30
object_property_set_bool(cpuobj, true, "realized", NULL);
20
31
+ object_unref(cpuobj);
21
-/* Return a value with the bottom len bits set (where 0 < len <= 64) */
22
-static inline uint64_t bitmask64(unsigned int length)
23
-{
24
- assert(length > 0 && length <= 64);
25
- return ~0ULL >> (64 - length);
26
-}
27
-
28
/* Simplified variant of pseudocode DecodeBitMasks() for the case where we
29
* only require the wmask. Returns false if the imms/immr/immn are a reserved
30
* value (ie should cause a guest UNDEF exception), and true if they are
31
@@ -XXX,XX +XXX,XX @@ bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
32
/* Create the value of one element: s+1 set bits rotated
33
* by r within the element (which is e bits wide)...
34
*/
35
- mask = bitmask64(s + 1);
36
+ mask = MAKE_64BIT_MASK(0, s + 1);
37
if (r) {
38
mask = (mask >> r) | (mask << (e - r));
39
- mask &= bitmask64(e);
40
+ mask &= MAKE_64BIT_MASK(0, e);
32
}
41
}
33
fdt_add_timer_nodes(vms);
42
/* ...then replicate the element over the whole 64 bit value */
34
fdt_add_cpu_nodes(vms);
43
mask = bitfield_replicate(mask, e);
35
--
44
--
36
2.7.4
45
2.34.1
37
38
diff view generated by jsdifflib
1
From: Prasad J Pandit <pjp@fedoraproject.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
In SDHCI protocol, the 'Block count enable' bit of the Transfer
3
Convert the ADD, ORR, EOR, ANDS (immediate) instructions.
4
Mode register is relevant only in multi block transfers. We need
5
not check it in single block transfers.
6
4
7
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20170214185225.7994-5-ppandit@redhat.com
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20230512144106.3608981-10-peter.maydell@linaro.org
9
[PMM: rebased]
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
hw/sd/sdhci.c | 6 +-----
12
target/arm/tcg/a64.decode | 15 ++++++
13
1 file changed, 1 insertion(+), 5 deletions(-)
13
target/arm/tcg/translate-a64.c | 94 +++++++++++-----------------------
14
2 files changed, 44 insertions(+), 65 deletions(-)
14
15
15
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
16
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/sd/sdhci.c
18
--- a/target/arm/tcg/a64.decode
18
+++ b/hw/sd/sdhci.c
19
+++ b/target/arm/tcg/a64.decode
19
@@ -XXX,XX +XXX,XX @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
20
@@ -XXX,XX +XXX,XX @@ SUBS_i . 11 100010 1 ............ ..... ..... @addsub_imm12
21
22
ADDG_i 1 00 100011 0 ...... 00 .... ..... ..... @addsub_imm_tag
23
SUBG_i 1 10 100011 0 ...... 00 .... ..... ..... @addsub_imm_tag
24
+
25
+# Logical (immediate)
26
+
27
+&rri_log rd rn sf dbm
28
+@logic_imm_64 1 .. ...... dbm:13 rn:5 rd:5 &rri_log sf=1
29
+@logic_imm_32 0 .. ...... 0 dbm:12 rn:5 rd:5 &rri_log sf=0
30
+
31
+AND_i . 00 100100 . ...... ...... ..... ..... @logic_imm_64
32
+AND_i . 00 100100 . ...... ...... ..... ..... @logic_imm_32
33
+ORR_i . 01 100100 . ...... ...... ..... ..... @logic_imm_64
34
+ORR_i . 01 100100 . ...... ...... ..... ..... @logic_imm_32
35
+EOR_i . 10 100100 . ...... ...... ..... ..... @logic_imm_64
36
+EOR_i . 10 100100 . ...... ...... ..... ..... @logic_imm_32
37
+ANDS_i . 11 100100 . ...... ...... ..... ..... @logic_imm_64
38
+ANDS_i . 11 100100 . ...... ...... ..... ..... @logic_imm_32
39
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/tcg/translate-a64.c
42
+++ b/target/arm/tcg/translate-a64.c
43
@@ -XXX,XX +XXX,XX @@ static uint64_t bitfield_replicate(uint64_t mask, unsigned int e)
44
return mask;
20
}
45
}
21
46
22
/* single block SDMA transfer */
47
-/* Simplified variant of pseudocode DecodeBitMasks() for the case where we
48
+/*
49
+ * Logical (immediate)
50
+ */
51
+
52
+/*
53
+ * Simplified variant of pseudocode DecodeBitMasks() for the case where we
54
* only require the wmask. Returns false if the imms/immr/immn are a reserved
55
* value (ie should cause a guest UNDEF exception), and true if they are
56
* valid, in which case the decoded bit pattern is written to result.
57
@@ -XXX,XX +XXX,XX @@ bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
58
return true;
59
}
60
61
-/* Logical (immediate)
62
- * 31 30 29 28 23 22 21 16 15 10 9 5 4 0
63
- * +----+-----+-------------+---+------+------+------+------+
64
- * | sf | opc | 1 0 0 1 0 0 | N | immr | imms | Rn | Rd |
65
- * +----+-----+-------------+---+------+------+------+------+
66
- */
67
-static void disas_logic_imm(DisasContext *s, uint32_t insn)
68
+static bool gen_rri_log(DisasContext *s, arg_rri_log *a, bool set_cc,
69
+ void (*fn)(TCGv_i64, TCGv_i64, int64_t))
70
{
71
- unsigned int sf, opc, is_n, immr, imms, rn, rd;
72
TCGv_i64 tcg_rd, tcg_rn;
73
- uint64_t wmask;
74
- bool is_and = false;
75
+ uint64_t imm;
76
77
- sf = extract32(insn, 31, 1);
78
- opc = extract32(insn, 29, 2);
79
- is_n = extract32(insn, 22, 1);
80
- immr = extract32(insn, 16, 6);
81
- imms = extract32(insn, 10, 6);
82
- rn = extract32(insn, 5, 5);
83
- rd = extract32(insn, 0, 5);
23
-
84
-
24
static void sdhci_sdma_transfer_single_block(SDHCIState *s)
85
- if (!sf && is_n) {
25
{
86
- unallocated_encoding(s);
26
int n;
87
- return;
27
@@ -XXX,XX +XXX,XX @@ static void sdhci_sdma_transfer_single_block(SDHCIState *s)
88
+ /* Some immediate field values are reserved. */
28
sdbus_write_data(&s->sdbus, s->fifo_buffer[n]);
89
+ if (!logic_imm_decode_wmask(&imm, extract32(a->dbm, 12, 1),
29
}
90
+ extract32(a->dbm, 0, 6),
91
+ extract32(a->dbm, 6, 6))) {
92
+ return false;
93
+ }
94
+ if (!a->sf) {
95
+ imm &= 0xffffffffull;
96
}
97
98
- if (opc == 0x3) { /* ANDS */
99
- tcg_rd = cpu_reg(s, rd);
100
- } else {
101
- tcg_rd = cpu_reg_sp(s, rd);
102
- }
103
- tcg_rn = cpu_reg(s, rn);
104
+ tcg_rd = set_cc ? cpu_reg(s, a->rd) : cpu_reg_sp(s, a->rd);
105
+ tcg_rn = cpu_reg(s, a->rn);
106
107
- if (!logic_imm_decode_wmask(&wmask, is_n, imms, immr)) {
108
- /* some immediate field values are reserved */
109
- unallocated_encoding(s);
110
- return;
111
+ fn(tcg_rd, tcg_rn, imm);
112
+ if (set_cc) {
113
+ gen_logic_CC(a->sf, tcg_rd);
30
}
114
}
31
-
115
-
32
- if (s->trnmod & SDHC_TRNS_BLK_CNT_EN) {
116
- if (!sf) {
33
- s->blkcnt--;
117
- wmask &= 0xffffffff;
34
- }
118
- }
35
+ s->blkcnt--;
119
-
36
120
- switch (opc) {
37
sdhci_end_transfer(s);
121
- case 0x3: /* ANDS */
122
- case 0x0: /* AND */
123
- tcg_gen_andi_i64(tcg_rd, tcg_rn, wmask);
124
- is_and = true;
125
- break;
126
- case 0x1: /* ORR */
127
- tcg_gen_ori_i64(tcg_rd, tcg_rn, wmask);
128
- break;
129
- case 0x2: /* EOR */
130
- tcg_gen_xori_i64(tcg_rd, tcg_rn, wmask);
131
- break;
132
- default:
133
- assert(FALSE); /* must handle all above */
134
- break;
135
- }
136
-
137
- if (!sf && !is_and) {
138
- /* zero extend final result; we know we can skip this for AND
139
- * since the immediate had the high 32 bits clear.
140
- */
141
+ if (!a->sf) {
142
tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
143
}
144
-
145
- if (opc == 3) { /* ANDS */
146
- gen_logic_CC(sf, tcg_rd);
147
- }
148
+ return true;
38
}
149
}
150
151
+TRANS(AND_i, gen_rri_log, a, false, tcg_gen_andi_i64)
152
+TRANS(ORR_i, gen_rri_log, a, false, tcg_gen_ori_i64)
153
+TRANS(EOR_i, gen_rri_log, a, false, tcg_gen_xori_i64)
154
+TRANS(ANDS_i, gen_rri_log, a, true, tcg_gen_andi_i64)
155
+
156
/*
157
* Move wide (immediate)
158
*
159
@@ -XXX,XX +XXX,XX @@ static void disas_extract(DisasContext *s, uint32_t insn)
160
static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
161
{
162
switch (extract32(insn, 23, 6)) {
163
- case 0x24: /* Logical (immediate) */
164
- disas_logic_imm(s, insn);
165
- break;
166
case 0x25: /* Move wide (immediate) */
167
disas_movw_imm(s, insn);
168
break;
39
--
169
--
40
2.7.4
170
2.34.1
41
42
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This adds the BCM2835 GPIO controller.
3
Convert the MON, MOVZ, MOVK instructions.
4
4
5
It currently implements:
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
- The 54 GPIOs as outputs (qemu_irq)
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
- The SD controller selection via alternate function of GPIOs 48-53
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
8
Message-id: 20230512144106.3608981-11-peter.maydell@linaro.org
9
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
9
[PMM: Rebased]
10
Message-id: 20170224164021.9066-4-clement.deschamps@antfield.fr
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
12
---
14
hw/gpio/Makefile.objs | 1 +
13
target/arm/tcg/a64.decode | 13 ++++++
15
include/hw/gpio/bcm2835_gpio.h | 39 +++++
14
target/arm/tcg/translate-a64.c | 73 ++++++++++++++--------------------
16
hw/gpio/bcm2835_gpio.c | 353 +++++++++++++++++++++++++++++++++++++++++
15
2 files changed, 42 insertions(+), 44 deletions(-)
17
3 files changed, 393 insertions(+)
18
create mode 100644 include/hw/gpio/bcm2835_gpio.h
19
create mode 100644 hw/gpio/bcm2835_gpio.c
20
16
21
diff --git a/hw/gpio/Makefile.objs b/hw/gpio/Makefile.objs
17
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
22
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/gpio/Makefile.objs
19
--- a/target/arm/tcg/a64.decode
24
+++ b/hw/gpio/Makefile.objs
20
+++ b/target/arm/tcg/a64.decode
25
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_GPIO_KEY) += gpio_key.o
21
@@ -XXX,XX +XXX,XX @@ EOR_i . 10 100100 . ...... ...... ..... ..... @logic_imm_64
26
22
EOR_i . 10 100100 . ...... ...... ..... ..... @logic_imm_32
27
obj-$(CONFIG_OMAP) += omap_gpio.o
23
ANDS_i . 11 100100 . ...... ...... ..... ..... @logic_imm_64
28
obj-$(CONFIG_IMX) += imx_gpio.o
24
ANDS_i . 11 100100 . ...... ...... ..... ..... @logic_imm_32
29
+obj-$(CONFIG_RASPI) += bcm2835_gpio.o
30
diff --git a/include/hw/gpio/bcm2835_gpio.h b/include/hw/gpio/bcm2835_gpio.h
31
new file mode 100644
32
index XXXXXXX..XXXXXXX
33
--- /dev/null
34
+++ b/include/hw/gpio/bcm2835_gpio.h
35
@@ -XXX,XX +XXX,XX @@
36
+/*
37
+ * Raspberry Pi (BCM2835) GPIO Controller
38
+ *
39
+ * Copyright (c) 2017 Antfield SAS
40
+ *
41
+ * Authors:
42
+ * Clement Deschamps <clement.deschamps@antfield.fr>
43
+ * Luc Michel <luc.michel@antfield.fr>
44
+ *
45
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
46
+ * See the COPYING file in the top-level directory.
47
+ */
48
+
25
+
49
+#ifndef BCM2835_GPIO_H
26
+# Move wide (immediate)
50
+#define BCM2835_GPIO_H
51
+
27
+
52
+#include "hw/sd/sd.h"
28
+&movw rd sf imm hw
29
+@movw_64 1 .. ...... hw:2 imm:16 rd:5 &movw sf=1
30
+@movw_32 0 .. ...... 0 hw:1 imm:16 rd:5 &movw sf=0
53
+
31
+
54
+typedef struct BCM2835GpioState {
32
+MOVN . 00 100101 .. ................ ..... @movw_64
55
+ SysBusDevice parent_obj;
33
+MOVN . 00 100101 .. ................ ..... @movw_32
34
+MOVZ . 10 100101 .. ................ ..... @movw_64
35
+MOVZ . 10 100101 .. ................ ..... @movw_32
36
+MOVK . 11 100101 .. ................ ..... @movw_64
37
+MOVK . 11 100101 .. ................ ..... @movw_32
38
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/tcg/translate-a64.c
41
+++ b/target/arm/tcg/translate-a64.c
42
@@ -XXX,XX +XXX,XX @@ TRANS(ANDS_i, gen_rri_log, a, true, tcg_gen_andi_i64)
43
44
/*
45
* Move wide (immediate)
46
- *
47
- * 31 30 29 28 23 22 21 20 5 4 0
48
- * +--+-----+-------------+-----+----------------+------+
49
- * |sf| opc | 1 0 0 1 0 1 | hw | imm16 | Rd |
50
- * +--+-----+-------------+-----+----------------+------+
51
- *
52
- * sf: 0 -> 32 bit, 1 -> 64 bit
53
- * opc: 00 -> N, 10 -> Z, 11 -> K
54
- * hw: shift/16 (0,16, and sf only 32, 48)
55
*/
56
-static void disas_movw_imm(DisasContext *s, uint32_t insn)
56
+
57
+
57
+ MemoryRegion iomem;
58
+static bool trans_MOVZ(DisasContext *s, arg_movw *a)
58
+
59
{
59
+ /* SDBus selector */
60
- int rd = extract32(insn, 0, 5);
60
+ SDBus sdbus;
61
- uint64_t imm = extract32(insn, 5, 16);
61
+ SDBus *sdbus_sdhci;
62
- int sf = extract32(insn, 31, 1);
62
+ SDBus *sdbus_sdhost;
63
- int opc = extract32(insn, 29, 2);
63
+
64
- int pos = extract32(insn, 21, 2) << 4;
64
+ uint8_t fsel[54];
65
- TCGv_i64 tcg_rd = cpu_reg(s, rd);
65
+ uint32_t lev0, lev1;
66
+ int pos = a->hw << 4;
66
+ uint8_t sd_fsel;
67
+ tcg_gen_movi_i64(cpu_reg(s, a->rd), (uint64_t)a->imm << pos);
67
+ qemu_irq out[54];
68
+ return true;
68
+} BCM2835GpioState;
69
+}
69
+
70
70
+#define TYPE_BCM2835_GPIO "bcm2835_gpio"
71
- if (!sf && (pos >= 32)) {
71
+#define BCM2835_GPIO(obj) \
72
- unallocated_encoding(s);
72
+ OBJECT_CHECK(BCM2835GpioState, (obj), TYPE_BCM2835_GPIO)
73
- return;
73
+
74
- }
74
+#endif
75
+static bool trans_MOVN(DisasContext *s, arg_movw *a)
75
diff --git a/hw/gpio/bcm2835_gpio.c b/hw/gpio/bcm2835_gpio.c
76
new file mode 100644
77
index XXXXXXX..XXXXXXX
78
--- /dev/null
79
+++ b/hw/gpio/bcm2835_gpio.c
80
@@ -XXX,XX +XXX,XX @@
81
+/*
82
+ * Raspberry Pi (BCM2835) GPIO Controller
83
+ *
84
+ * Copyright (c) 2017 Antfield SAS
85
+ *
86
+ * Authors:
87
+ * Clement Deschamps <clement.deschamps@antfield.fr>
88
+ * Luc Michel <luc.michel@antfield.fr>
89
+ *
90
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
91
+ * See the COPYING file in the top-level directory.
92
+ */
93
+
94
+#include "qemu/osdep.h"
95
+#include "qemu/log.h"
96
+#include "qemu/timer.h"
97
+#include "qapi/error.h"
98
+#include "hw/sysbus.h"
99
+#include "hw/sd/sd.h"
100
+#include "hw/gpio/bcm2835_gpio.h"
101
+
102
+#define GPFSEL0 0x00
103
+#define GPFSEL1 0x04
104
+#define GPFSEL2 0x08
105
+#define GPFSEL3 0x0C
106
+#define GPFSEL4 0x10
107
+#define GPFSEL5 0x14
108
+#define GPSET0 0x1C
109
+#define GPSET1 0x20
110
+#define GPCLR0 0x28
111
+#define GPCLR1 0x2C
112
+#define GPLEV0 0x34
113
+#define GPLEV1 0x38
114
+#define GPEDS0 0x40
115
+#define GPEDS1 0x44
116
+#define GPREN0 0x4C
117
+#define GPREN1 0x50
118
+#define GPFEN0 0x58
119
+#define GPFEN1 0x5C
120
+#define GPHEN0 0x64
121
+#define GPHEN1 0x68
122
+#define GPLEN0 0x70
123
+#define GPLEN1 0x74
124
+#define GPAREN0 0x7C
125
+#define GPAREN1 0x80
126
+#define GPAFEN0 0x88
127
+#define GPAFEN1 0x8C
128
+#define GPPUD 0x94
129
+#define GPPUDCLK0 0x98
130
+#define GPPUDCLK1 0x9C
131
+
132
+static uint32_t gpfsel_get(BCM2835GpioState *s, uint8_t reg)
133
+{
76
+{
134
+ int i;
77
+ int pos = a->hw << 4;
135
+ uint32_t value = 0;
78
+ uint64_t imm = a->imm;
136
+ for (i = 0; i < 10; i++) {
79
137
+ uint32_t index = 10 * reg + i;
80
- switch (opc) {
138
+ if (index < sizeof(s->fsel)) {
81
- case 0: /* MOVN */
139
+ value |= (s->fsel[index] & 0x7) << (3 * i);
82
- case 2: /* MOVZ */
140
+ }
83
- imm <<= pos;
141
+ }
84
- if (opc == 0) {
142
+ return value;
85
- imm = ~imm;
86
- }
87
- if (!sf) {
88
- imm &= 0xffffffffu;
89
- }
90
- tcg_gen_movi_i64(tcg_rd, imm);
91
- break;
92
- case 3: /* MOVK */
93
- tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_constant_i64(imm), pos, 16);
94
- if (!sf) {
95
- tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
96
- }
97
- break;
98
- default:
99
- unallocated_encoding(s);
100
- break;
101
+ imm = ~(imm << pos);
102
+ if (!a->sf) {
103
+ imm = (uint32_t)imm;
104
}
105
+ tcg_gen_movi_i64(cpu_reg(s, a->rd), imm);
106
+ return true;
143
+}
107
+}
144
+
108
+
145
+static void gpfsel_set(BCM2835GpioState *s, uint8_t reg, uint32_t value)
109
+static bool trans_MOVK(DisasContext *s, arg_movw *a)
146
+{
110
+{
147
+ int i;
111
+ int pos = a->hw << 4;
148
+ for (i = 0; i < 10; i++) {
112
+ TCGv_i64 tcg_rd, tcg_im;
149
+ uint32_t index = 10 * reg + i;
113
+
150
+ if (index < sizeof(s->fsel)) {
114
+ tcg_rd = cpu_reg(s, a->rd);
151
+ int fsel = (value >> (3 * i)) & 0x7;
115
+ tcg_im = tcg_constant_i64(a->imm);
152
+ s->fsel[index] = fsel;
116
+ tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_im, pos, 16);
153
+ }
117
+ if (!a->sf) {
118
+ tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
154
+ }
119
+ }
155
+
120
+ return true;
156
+ /* SD controller selection (48-53) */
121
}
157
+ if (s->sd_fsel != 0
122
158
+ && (s->fsel[48] == 0) /* SD_CLK_R */
123
/* Bitfield
159
+ && (s->fsel[49] == 0) /* SD_CMD_R */
124
@@ -XXX,XX +XXX,XX @@ static void disas_extract(DisasContext *s, uint32_t insn)
160
+ && (s->fsel[50] == 0) /* SD_DATA0_R */
125
static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
161
+ && (s->fsel[51] == 0) /* SD_DATA1_R */
126
{
162
+ && (s->fsel[52] == 0) /* SD_DATA2_R */
127
switch (extract32(insn, 23, 6)) {
163
+ && (s->fsel[53] == 0) /* SD_DATA3_R */
128
- case 0x25: /* Move wide (immediate) */
164
+ ) {
129
- disas_movw_imm(s, insn);
165
+ /* SDHCI controller selected */
130
- break;
166
+ sdbus_reparent_card(s->sdbus_sdhost, s->sdbus_sdhci);
131
case 0x26: /* Bitfield */
167
+ s->sd_fsel = 0;
132
disas_bitfield(s, insn);
168
+ } else if (s->sd_fsel != 4
133
break;
169
+ && (s->fsel[48] == 4) /* SD_CLK_R */
170
+ && (s->fsel[49] == 4) /* SD_CMD_R */
171
+ && (s->fsel[50] == 4) /* SD_DATA0_R */
172
+ && (s->fsel[51] == 4) /* SD_DATA1_R */
173
+ && (s->fsel[52] == 4) /* SD_DATA2_R */
174
+ && (s->fsel[53] == 4) /* SD_DATA3_R */
175
+ ) {
176
+ /* SDHost controller selected */
177
+ sdbus_reparent_card(s->sdbus_sdhci, s->sdbus_sdhost);
178
+ s->sd_fsel = 4;
179
+ }
180
+}
181
+
182
+static int gpfsel_is_out(BCM2835GpioState *s, int index)
183
+{
184
+ if (index >= 0 && index < 54) {
185
+ return s->fsel[index] == 1;
186
+ }
187
+ return 0;
188
+}
189
+
190
+static void gpset(BCM2835GpioState *s,
191
+ uint32_t val, uint8_t start, uint8_t count, uint32_t *lev)
192
+{
193
+ uint32_t changes = val & ~*lev;
194
+ uint32_t cur = 1;
195
+
196
+ int i;
197
+ for (i = 0; i < count; i++) {
198
+ if ((changes & cur) && (gpfsel_is_out(s, start + i))) {
199
+ qemu_set_irq(s->out[start + i], 1);
200
+ }
201
+ cur <<= 1;
202
+ }
203
+
204
+ *lev |= val;
205
+}
206
+
207
+static void gpclr(BCM2835GpioState *s,
208
+ uint32_t val, uint8_t start, uint8_t count, uint32_t *lev)
209
+{
210
+ uint32_t changes = val & *lev;
211
+ uint32_t cur = 1;
212
+
213
+ int i;
214
+ for (i = 0; i < count; i++) {
215
+ if ((changes & cur) && (gpfsel_is_out(s, start + i))) {
216
+ qemu_set_irq(s->out[start + i], 0);
217
+ }
218
+ cur <<= 1;
219
+ }
220
+
221
+ *lev &= ~val;
222
+}
223
+
224
+static uint64_t bcm2835_gpio_read(void *opaque, hwaddr offset,
225
+ unsigned size)
226
+{
227
+ BCM2835GpioState *s = (BCM2835GpioState *)opaque;
228
+
229
+ switch (offset) {
230
+ case GPFSEL0:
231
+ case GPFSEL1:
232
+ case GPFSEL2:
233
+ case GPFSEL3:
234
+ case GPFSEL4:
235
+ case GPFSEL5:
236
+ return gpfsel_get(s, offset / 4);
237
+ case GPSET0:
238
+ case GPSET1:
239
+ /* Write Only */
240
+ return 0;
241
+ case GPCLR0:
242
+ case GPCLR1:
243
+ /* Write Only */
244
+ return 0;
245
+ case GPLEV0:
246
+ return s->lev0;
247
+ case GPLEV1:
248
+ return s->lev1;
249
+ case GPEDS0:
250
+ case GPEDS1:
251
+ case GPREN0:
252
+ case GPREN1:
253
+ case GPFEN0:
254
+ case GPFEN1:
255
+ case GPHEN0:
256
+ case GPHEN1:
257
+ case GPLEN0:
258
+ case GPLEN1:
259
+ case GPAREN0:
260
+ case GPAREN1:
261
+ case GPAFEN0:
262
+ case GPAFEN1:
263
+ case GPPUD:
264
+ case GPPUDCLK0:
265
+ case GPPUDCLK1:
266
+ /* Not implemented */
267
+ return 0;
268
+ default:
269
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
270
+ __func__, offset);
271
+ break;
272
+ }
273
+
274
+ return 0;
275
+}
276
+
277
+static void bcm2835_gpio_write(void *opaque, hwaddr offset,
278
+ uint64_t value, unsigned size)
279
+{
280
+ BCM2835GpioState *s = (BCM2835GpioState *)opaque;
281
+
282
+ switch (offset) {
283
+ case GPFSEL0:
284
+ case GPFSEL1:
285
+ case GPFSEL2:
286
+ case GPFSEL3:
287
+ case GPFSEL4:
288
+ case GPFSEL5:
289
+ gpfsel_set(s, offset / 4, value);
290
+ break;
291
+ case GPSET0:
292
+ gpset(s, value, 0, 32, &s->lev0);
293
+ break;
294
+ case GPSET1:
295
+ gpset(s, value, 32, 22, &s->lev1);
296
+ break;
297
+ case GPCLR0:
298
+ gpclr(s, value, 0, 32, &s->lev0);
299
+ break;
300
+ case GPCLR1:
301
+ gpclr(s, value, 32, 22, &s->lev1);
302
+ break;
303
+ case GPLEV0:
304
+ case GPLEV1:
305
+ /* Read Only */
306
+ break;
307
+ case GPEDS0:
308
+ case GPEDS1:
309
+ case GPREN0:
310
+ case GPREN1:
311
+ case GPFEN0:
312
+ case GPFEN1:
313
+ case GPHEN0:
314
+ case GPHEN1:
315
+ case GPLEN0:
316
+ case GPLEN1:
317
+ case GPAREN0:
318
+ case GPAREN1:
319
+ case GPAFEN0:
320
+ case GPAFEN1:
321
+ case GPPUD:
322
+ case GPPUDCLK0:
323
+ case GPPUDCLK1:
324
+ /* Not implemented */
325
+ break;
326
+ default:
327
+ goto err_out;
328
+ }
329
+ return;
330
+
331
+err_out:
332
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
333
+ __func__, offset);
334
+}
335
+
336
+static void bcm2835_gpio_reset(DeviceState *dev)
337
+{
338
+ BCM2835GpioState *s = BCM2835_GPIO(dev);
339
+
340
+ int i;
341
+ for (i = 0; i < 6; i++) {
342
+ gpfsel_set(s, i, 0);
343
+ }
344
+
345
+ s->sd_fsel = 0;
346
+
347
+ /* SDHCI is selected by default */
348
+ sdbus_reparent_card(&s->sdbus, s->sdbus_sdhci);
349
+
350
+ s->lev0 = 0;
351
+ s->lev1 = 0;
352
+}
353
+
354
+static const MemoryRegionOps bcm2835_gpio_ops = {
355
+ .read = bcm2835_gpio_read,
356
+ .write = bcm2835_gpio_write,
357
+ .endianness = DEVICE_NATIVE_ENDIAN,
358
+};
359
+
360
+static const VMStateDescription vmstate_bcm2835_gpio = {
361
+ .name = "bcm2835_gpio",
362
+ .version_id = 1,
363
+ .minimum_version_id = 1,
364
+ .fields = (VMStateField[]) {
365
+ VMSTATE_UINT8_ARRAY(fsel, BCM2835GpioState, 54),
366
+ VMSTATE_UINT32(lev0, BCM2835GpioState),
367
+ VMSTATE_UINT32(lev1, BCM2835GpioState),
368
+ VMSTATE_UINT8(sd_fsel, BCM2835GpioState),
369
+ VMSTATE_END_OF_LIST()
370
+ }
371
+};
372
+
373
+static void bcm2835_gpio_init(Object *obj)
374
+{
375
+ BCM2835GpioState *s = BCM2835_GPIO(obj);
376
+ DeviceState *dev = DEVICE(obj);
377
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
378
+
379
+ qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
380
+ TYPE_SD_BUS, DEVICE(s), "sd-bus");
381
+
382
+ memory_region_init_io(&s->iomem, obj,
383
+ &bcm2835_gpio_ops, s, "bcm2835_gpio", 0x1000);
384
+ sysbus_init_mmio(sbd, &s->iomem);
385
+ qdev_init_gpio_out(dev, s->out, 54);
386
+}
387
+
388
+static void bcm2835_gpio_realize(DeviceState *dev, Error **errp)
389
+{
390
+ BCM2835GpioState *s = BCM2835_GPIO(dev);
391
+ Object *obj;
392
+ Error *err = NULL;
393
+
394
+ obj = object_property_get_link(OBJECT(dev), "sdbus-sdhci", &err);
395
+ if (obj == NULL) {
396
+ error_setg(errp, "%s: required sdhci link not found: %s",
397
+ __func__, error_get_pretty(err));
398
+ return;
399
+ }
400
+ s->sdbus_sdhci = SD_BUS(obj);
401
+
402
+ obj = object_property_get_link(OBJECT(dev), "sdbus-sdhost", &err);
403
+ if (obj == NULL) {
404
+ error_setg(errp, "%s: required sdhost link not found: %s",
405
+ __func__, error_get_pretty(err));
406
+ return;
407
+ }
408
+ s->sdbus_sdhost = SD_BUS(obj);
409
+}
410
+
411
+static void bcm2835_gpio_class_init(ObjectClass *klass, void *data)
412
+{
413
+ DeviceClass *dc = DEVICE_CLASS(klass);
414
+
415
+ dc->vmsd = &vmstate_bcm2835_gpio;
416
+ dc->realize = &bcm2835_gpio_realize;
417
+ dc->reset = &bcm2835_gpio_reset;
418
+}
419
+
420
+static const TypeInfo bcm2835_gpio_info = {
421
+ .name = TYPE_BCM2835_GPIO,
422
+ .parent = TYPE_SYS_BUS_DEVICE,
423
+ .instance_size = sizeof(BCM2835GpioState),
424
+ .instance_init = bcm2835_gpio_init,
425
+ .class_init = bcm2835_gpio_class_init,
426
+};
427
+
428
+static void bcm2835_gpio_register_types(void)
429
+{
430
+ type_register_static(&bcm2835_gpio_info);
431
+}
432
+
433
+type_init(bcm2835_gpio_register_types)
434
--
134
--
435
2.7.4
135
2.34.1
436
437
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This adds the bcm2835_sdhost and bcm2835_gpio to the BCM2835 platform.
3
Convert the BFM, SBFM, UBFM instructions.
4
4
5
For supporting the SD controller selection (alternate function of GPIOs
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
48-53), the bcm2835_gpio now exposes an sdbus.
7
It also has a link to both the sdbus of sdhci and sdhost controllers,
8
and the card is reparented from one bus to another when the alternate
9
function of GPIOs 48-53 is modified.
10
11
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
12
Message-id: 20170224164021.9066-5-clement.deschamps@antfield.fr
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20230512144106.3608981-12-peter.maydell@linaro.org
9
[PMM: Rebased]
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
11
---
16
include/hw/arm/bcm2835_peripherals.h | 4 ++++
12
target/arm/tcg/a64.decode | 13 +++
17
hw/arm/bcm2835_peripherals.c | 43 ++++++++++++++++++++++++++++++++++--
13
target/arm/tcg/translate-a64.c | 144 ++++++++++++++++++---------------
18
2 files changed, 45 insertions(+), 2 deletions(-)
14
2 files changed, 94 insertions(+), 63 deletions(-)
19
15
20
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
16
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
21
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/arm/bcm2835_peripherals.h
18
--- a/target/arm/tcg/a64.decode
23
+++ b/include/hw/arm/bcm2835_peripherals.h
19
+++ b/target/arm/tcg/a64.decode
24
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ MOVZ . 10 100101 .. ................ ..... @movw_64
25
#include "hw/misc/bcm2835_rng.h"
21
MOVZ . 10 100101 .. ................ ..... @movw_32
26
#include "hw/misc/bcm2835_mbox.h"
22
MOVK . 11 100101 .. ................ ..... @movw_64
27
#include "hw/sd/sdhci.h"
23
MOVK . 11 100101 .. ................ ..... @movw_32
28
+#include "hw/sd/bcm2835_sdhost.h"
24
+
29
+#include "hw/gpio/bcm2835_gpio.h"
25
+# Bitfield
30
26
+
31
#define TYPE_BCM2835_PERIPHERALS "bcm2835-peripherals"
27
+&bitfield rd rn sf immr imms
32
#define BCM2835_PERIPHERALS(obj) \
28
+@bitfield_64 1 .. ...... 1 immr:6 imms:6 rn:5 rd:5 &bitfield sf=1
33
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2835PeripheralState {
29
+@bitfield_32 0 .. ...... 0 0 immr:5 0 imms:5 rn:5 rd:5 &bitfield sf=0
34
BCM2835RngState rng;
30
+
35
BCM2835MboxState mboxes;
31
+SBFM . 00 100110 . ...... ...... ..... ..... @bitfield_64
36
SDHCIState sdhci;
32
+SBFM . 00 100110 . ...... ...... ..... ..... @bitfield_32
37
+ BCM2835SDHostState sdhost;
33
+BFM . 01 100110 . ...... ...... ..... ..... @bitfield_64
38
+ BCM2835GpioState gpio;
34
+BFM . 01 100110 . ...... ...... ..... ..... @bitfield_32
39
} BCM2835PeripheralState;
35
+UBFM . 10 100110 . ...... ...... ..... ..... @bitfield_64
40
36
+UBFM . 10 100110 . ...... ...... ..... ..... @bitfield_32
41
#endif /* BCM2835_PERIPHERALS_H */
37
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
42
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
43
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/arm/bcm2835_peripherals.c
39
--- a/target/arm/tcg/translate-a64.c
45
+++ b/hw/arm/bcm2835_peripherals.c
40
+++ b/target/arm/tcg/translate-a64.c
46
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
41
@@ -XXX,XX +XXX,XX @@ static bool trans_MOVK(DisasContext *s, arg_movw *a)
47
object_property_add_child(obj, "sdhci", OBJECT(&s->sdhci), NULL);
42
return true;
48
qdev_set_parent_bus(DEVICE(&s->sdhci), sysbus_get_default());
49
50
+ /* SDHOST */
51
+ object_initialize(&s->sdhost, sizeof(s->sdhost), TYPE_BCM2835_SDHOST);
52
+ object_property_add_child(obj, "sdhost", OBJECT(&s->sdhost), NULL);
53
+ qdev_set_parent_bus(DEVICE(&s->sdhost), sysbus_get_default());
54
+
55
/* DMA Channels */
56
object_initialize(&s->dma, sizeof(s->dma), TYPE_BCM2835_DMA);
57
object_property_add_child(obj, "dma", OBJECT(&s->dma), NULL);
58
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
59
60
object_property_add_const_link(OBJECT(&s->dma), "dma-mr",
61
OBJECT(&s->gpu_bus_mr), &error_abort);
62
+
63
+ /* GPIO */
64
+ object_initialize(&s->gpio, sizeof(s->gpio), TYPE_BCM2835_GPIO);
65
+ object_property_add_child(obj, "gpio", OBJECT(&s->gpio), NULL);
66
+ qdev_set_parent_bus(DEVICE(&s->gpio), sysbus_get_default());
67
+
68
+ object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhci",
69
+ OBJECT(&s->sdhci.sdbus), &error_abort);
70
+ object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhost",
71
+ OBJECT(&s->sdhost.sdbus), &error_abort);
72
}
43
}
73
44
74
static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
45
-/* Bitfield
75
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
46
- * 31 30 29 28 23 22 21 16 15 10 9 5 4 0
76
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0,
47
- * +----+-----+-------------+---+------+------+------+------+
77
qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
48
- * | sf | opc | 1 0 0 1 1 0 | N | immr | imms | Rn | Rd |
78
INTERRUPT_ARASANSDIO));
49
- * +----+-----+-------------+---+------+------+------+------+
79
- object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->sdhci), "sd-bus",
50
+/*
80
- &err);
51
+ * Bitfield
81
+
52
*/
82
+ /* SDHOST */
53
-static void disas_bitfield(DisasContext *s, uint32_t insn)
83
+ object_property_set_bool(OBJECT(&s->sdhost), true, "realized", &err);
54
+
84
if (err) {
55
+static bool trans_SBFM(DisasContext *s, arg_SBFM *a)
85
error_propagate(errp, err);
56
{
86
return;
57
- unsigned int sf, n, opc, ri, si, rn, rd, bitsize, pos, len;
58
- TCGv_i64 tcg_rd, tcg_tmp;
59
+ TCGv_i64 tcg_rd = cpu_reg(s, a->rd);
60
+ TCGv_i64 tcg_tmp = read_cpu_reg(s, a->rn, 1);
61
+ unsigned int bitsize = a->sf ? 64 : 32;
62
+ unsigned int ri = a->immr;
63
+ unsigned int si = a->imms;
64
+ unsigned int pos, len;
65
66
- sf = extract32(insn, 31, 1);
67
- opc = extract32(insn, 29, 2);
68
- n = extract32(insn, 22, 1);
69
- ri = extract32(insn, 16, 6);
70
- si = extract32(insn, 10, 6);
71
- rn = extract32(insn, 5, 5);
72
- rd = extract32(insn, 0, 5);
73
- bitsize = sf ? 64 : 32;
74
-
75
- if (sf != n || ri >= bitsize || si >= bitsize || opc > 2) {
76
- unallocated_encoding(s);
77
- return;
78
- }
79
-
80
- tcg_rd = cpu_reg(s, rd);
81
-
82
- /* Suppress the zero-extend for !sf. Since RI and SI are constrained
83
- to be smaller than bitsize, we'll never reference data outside the
84
- low 32-bits anyway. */
85
- tcg_tmp = read_cpu_reg(s, rn, 1);
86
-
87
- /* Recognize simple(r) extractions. */
88
if (si >= ri) {
89
/* Wd<s-r:0> = Wn<s:r> */
90
len = (si - ri) + 1;
91
- if (opc == 0) { /* SBFM: ASR, SBFX, SXTB, SXTH, SXTW */
92
- tcg_gen_sextract_i64(tcg_rd, tcg_tmp, ri, len);
93
- goto done;
94
- } else if (opc == 2) { /* UBFM: UBFX, LSR, UXTB, UXTH */
95
- tcg_gen_extract_i64(tcg_rd, tcg_tmp, ri, len);
96
- return;
97
+ tcg_gen_sextract_i64(tcg_rd, tcg_tmp, ri, len);
98
+ if (!a->sf) {
99
+ tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
100
}
101
- /* opc == 1, BFXIL fall through to deposit */
102
+ } else {
103
+ /* Wd<32+s-r,32-r> = Wn<s:0> */
104
+ len = si + 1;
105
+ pos = (bitsize - ri) & (bitsize - 1);
106
+
107
+ if (len < ri) {
108
+ /*
109
+ * Sign extend the destination field from len to fill the
110
+ * balance of the word. Let the deposit below insert all
111
+ * of those sign bits.
112
+ */
113
+ tcg_gen_sextract_i64(tcg_tmp, tcg_tmp, 0, len);
114
+ len = ri;
115
+ }
116
+
117
+ /*
118
+ * We start with zero, and we haven't modified any bits outside
119
+ * bitsize, therefore no final zero-extension is unneeded for !sf.
120
+ */
121
+ tcg_gen_deposit_z_i64(tcg_rd, tcg_tmp, pos, len);
122
+ }
123
+ return true;
124
+}
125
+
126
+static bool trans_UBFM(DisasContext *s, arg_UBFM *a)
127
+{
128
+ TCGv_i64 tcg_rd = cpu_reg(s, a->rd);
129
+ TCGv_i64 tcg_tmp = read_cpu_reg(s, a->rn, 1);
130
+ unsigned int bitsize = a->sf ? 64 : 32;
131
+ unsigned int ri = a->immr;
132
+ unsigned int si = a->imms;
133
+ unsigned int pos, len;
134
+
135
+ tcg_rd = cpu_reg(s, a->rd);
136
+ tcg_tmp = read_cpu_reg(s, a->rn, 1);
137
+
138
+ if (si >= ri) {
139
+ /* Wd<s-r:0> = Wn<s:r> */
140
+ len = (si - ri) + 1;
141
+ tcg_gen_extract_i64(tcg_rd, tcg_tmp, ri, len);
142
+ } else {
143
+ /* Wd<32+s-r,32-r> = Wn<s:0> */
144
+ len = si + 1;
145
+ pos = (bitsize - ri) & (bitsize - 1);
146
+ tcg_gen_deposit_z_i64(tcg_rd, tcg_tmp, pos, len);
147
+ }
148
+ return true;
149
+}
150
+
151
+static bool trans_BFM(DisasContext *s, arg_BFM *a)
152
+{
153
+ TCGv_i64 tcg_rd = cpu_reg(s, a->rd);
154
+ TCGv_i64 tcg_tmp = read_cpu_reg(s, a->rn, 1);
155
+ unsigned int bitsize = a->sf ? 64 : 32;
156
+ unsigned int ri = a->immr;
157
+ unsigned int si = a->imms;
158
+ unsigned int pos, len;
159
+
160
+ tcg_rd = cpu_reg(s, a->rd);
161
+ tcg_tmp = read_cpu_reg(s, a->rn, 1);
162
+
163
+ if (si >= ri) {
164
+ /* Wd<s-r:0> = Wn<s:r> */
165
tcg_gen_shri_i64(tcg_tmp, tcg_tmp, ri);
166
+ len = (si - ri) + 1;
167
pos = 0;
168
} else {
169
- /* Handle the ri > si case with a deposit
170
- * Wd<32+s-r,32-r> = Wn<s:0>
171
- */
172
+ /* Wd<32+s-r,32-r> = Wn<s:0> */
173
len = si + 1;
174
pos = (bitsize - ri) & (bitsize - 1);
87
}
175
}
88
176
89
+ memory_region_add_subregion(&s->peri_mr, MMCI0_OFFSET,
177
- if (opc == 0 && len < ri) {
90
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sdhost), 0));
178
- /* SBFM: sign extend the destination field from len to fill
91
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhost), 0,
179
- the balance of the word. Let the deposit below insert all
92
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
180
- of those sign bits. */
93
+ INTERRUPT_SDIO));
181
- tcg_gen_sextract_i64(tcg_tmp, tcg_tmp, 0, len);
94
+
182
- len = ri;
95
/* DMA Channels */
183
- }
96
object_property_set_bool(OBJECT(&s->dma), true, "realized", &err);
184
-
97
if (err) {
185
- if (opc == 1) { /* BFM, BFXIL */
98
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
186
- tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, pos, len);
99
BCM2835_IC_GPU_IRQ,
187
- } else {
100
INTERRUPT_DMA0 + n));
188
- /* SBFM or UBFM: We start with zero, and we haven't modified
189
- any bits outside bitsize, therefore the zero-extension
190
- below is unneeded. */
191
- tcg_gen_deposit_z_i64(tcg_rd, tcg_tmp, pos, len);
192
- return;
193
- }
194
-
195
- done:
196
- if (!sf) { /* zero extend final result */
197
+ tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, pos, len);
198
+ if (!a->sf) {
199
tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
101
}
200
}
102
+
201
+ return true;
103
+ /* GPIO */
104
+ object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err);
105
+ if (err) {
106
+ error_propagate(errp, err);
107
+ return;
108
+ }
109
+
110
+ memory_region_add_subregion(&s->peri_mr, GPIO_OFFSET,
111
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0));
112
+
113
+ object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->gpio), "sd-bus",
114
+ &err);
115
+ if (err) {
116
+ error_propagate(errp, err);
117
+ return;
118
+ }
119
}
202
}
120
203
121
static void bcm2835_peripherals_class_init(ObjectClass *oc, void *data)
204
/* Extract
205
@@ -XXX,XX +XXX,XX @@ static void disas_extract(DisasContext *s, uint32_t insn)
206
static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
207
{
208
switch (extract32(insn, 23, 6)) {
209
- case 0x26: /* Bitfield */
210
- disas_bitfield(s, insn);
211
- break;
212
case 0x27: /* Extract */
213
disas_extract(s, insn);
214
break;
122
--
215
--
123
2.7.4
216
2.34.1
124
125
diff view generated by jsdifflib
1
Implement the NVIC SHCSR write behaviour which allows pending and
1
Convert the EXTR instruction to decodetree (this is the
2
active status of some exceptions to be changed.
2
only one in the 'Extract" class). This is the last of
3
the dp-immediate insns in the legacy decoder, so we
4
can now remove disas_data_proc_imm().
3
5
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230512144106.3608981-13-peter.maydell@linaro.org
6
---
9
---
7
hw/intc/armv7m_nvic.c | 13 +++++++++++--
10
target/arm/tcg/a64.decode | 7 +++
8
1 file changed, 11 insertions(+), 2 deletions(-)
11
target/arm/tcg/translate-a64.c | 94 +++++++++++-----------------------
12
2 files changed, 36 insertions(+), 65 deletions(-)
9
13
10
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
14
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
11
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
12
--- a/hw/intc/armv7m_nvic.c
16
--- a/target/arm/tcg/a64.decode
13
+++ b/hw/intc/armv7m_nvic.c
17
+++ b/target/arm/tcg/a64.decode
14
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
18
@@ -XXX,XX +XXX,XX @@ BFM . 01 100110 . ...... ...... ..... ..... @bitfield_64
15
cpu->env.v7m.ccr = value;
19
BFM . 01 100110 . ...... ...... ..... ..... @bitfield_32
20
UBFM . 10 100110 . ...... ...... ..... ..... @bitfield_64
21
UBFM . 10 100110 . ...... ...... ..... ..... @bitfield_32
22
+
23
+# Extract
24
+
25
+&extract rd rn rm imm sf
26
+
27
+EXTR 1 00 100111 1 0 rm:5 imm:6 rn:5 rd:5 &extract sf=1
28
+EXTR 0 00 100111 0 0 rm:5 0 imm:5 rn:5 rd:5 &extract sf=0
29
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/tcg/translate-a64.c
32
+++ b/target/arm/tcg/translate-a64.c
33
@@ -XXX,XX +XXX,XX @@ static bool trans_BFM(DisasContext *s, arg_BFM *a)
34
return true;
35
}
36
37
-/* Extract
38
- * 31 30 29 28 23 22 21 20 16 15 10 9 5 4 0
39
- * +----+------+-------------+---+----+------+--------+------+------+
40
- * | sf | op21 | 1 0 0 1 1 1 | N | o0 | Rm | imms | Rn | Rd |
41
- * +----+------+-------------+---+----+------+--------+------+------+
42
- */
43
-static void disas_extract(DisasContext *s, uint32_t insn)
44
+static bool trans_EXTR(DisasContext *s, arg_extract *a)
45
{
46
- unsigned int sf, n, rm, imm, rn, rd, bitsize, op21, op0;
47
+ TCGv_i64 tcg_rd, tcg_rm, tcg_rn;
48
49
- sf = extract32(insn, 31, 1);
50
- n = extract32(insn, 22, 1);
51
- rm = extract32(insn, 16, 5);
52
- imm = extract32(insn, 10, 6);
53
- rn = extract32(insn, 5, 5);
54
- rd = extract32(insn, 0, 5);
55
- op21 = extract32(insn, 29, 2);
56
- op0 = extract32(insn, 21, 1);
57
- bitsize = sf ? 64 : 32;
58
+ tcg_rd = cpu_reg(s, a->rd);
59
60
- if (sf != n || op21 || op0 || imm >= bitsize) {
61
- unallocated_encoding(s);
62
- } else {
63
- TCGv_i64 tcg_rd, tcg_rm, tcg_rn;
64
-
65
- tcg_rd = cpu_reg(s, rd);
66
-
67
- if (unlikely(imm == 0)) {
68
- /* tcg shl_i32/shl_i64 is undefined for 32/64 bit shifts,
69
- * so an extract from bit 0 is a special case.
70
- */
71
- if (sf) {
72
- tcg_gen_mov_i64(tcg_rd, cpu_reg(s, rm));
73
- } else {
74
- tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rm));
75
- }
76
+ if (unlikely(a->imm == 0)) {
77
+ /*
78
+ * tcg shl_i32/shl_i64 is undefined for 32/64 bit shifts,
79
+ * so an extract from bit 0 is a special case.
80
+ */
81
+ if (a->sf) {
82
+ tcg_gen_mov_i64(tcg_rd, cpu_reg(s, a->rm));
83
} else {
84
- tcg_rm = cpu_reg(s, rm);
85
- tcg_rn = cpu_reg(s, rn);
86
+ tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, a->rm));
87
+ }
88
+ } else {
89
+ tcg_rm = cpu_reg(s, a->rm);
90
+ tcg_rn = cpu_reg(s, a->rn);
91
92
- if (sf) {
93
- /* Specialization to ROR happens in EXTRACT2. */
94
- tcg_gen_extract2_i64(tcg_rd, tcg_rm, tcg_rn, imm);
95
+ if (a->sf) {
96
+ /* Specialization to ROR happens in EXTRACT2. */
97
+ tcg_gen_extract2_i64(tcg_rd, tcg_rm, tcg_rn, a->imm);
98
+ } else {
99
+ TCGv_i32 t0 = tcg_temp_new_i32();
100
+
101
+ tcg_gen_extrl_i64_i32(t0, tcg_rm);
102
+ if (a->rm == a->rn) {
103
+ tcg_gen_rotri_i32(t0, t0, a->imm);
104
} else {
105
- TCGv_i32 t0 = tcg_temp_new_i32();
106
-
107
- tcg_gen_extrl_i64_i32(t0, tcg_rm);
108
- if (rm == rn) {
109
- tcg_gen_rotri_i32(t0, t0, imm);
110
- } else {
111
- TCGv_i32 t1 = tcg_temp_new_i32();
112
- tcg_gen_extrl_i64_i32(t1, tcg_rn);
113
- tcg_gen_extract2_i32(t0, t0, t1, imm);
114
- }
115
- tcg_gen_extu_i32_i64(tcg_rd, t0);
116
+ TCGv_i32 t1 = tcg_temp_new_i32();
117
+ tcg_gen_extrl_i64_i32(t1, tcg_rn);
118
+ tcg_gen_extract2_i32(t0, t0, t1, a->imm);
119
}
120
+ tcg_gen_extu_i32_i64(tcg_rd, t0);
121
}
122
}
123
-}
124
-
125
-/* Data processing - immediate */
126
-static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
127
-{
128
- switch (extract32(insn, 23, 6)) {
129
- case 0x27: /* Extract */
130
- disas_extract(s, insn);
131
- break;
132
- default:
133
- unallocated_encoding(s);
134
- break;
135
- }
136
+ return true;
137
}
138
139
/* Shift a TCGv src by TCGv shift_amount, put result in dst.
140
@@ -XXX,XX +XXX,XX @@ static bool btype_destination_ok(uint32_t insn, bool bt, int btype)
141
static void disas_a64_legacy(DisasContext *s, uint32_t insn)
142
{
143
switch (extract32(insn, 25, 4)) {
144
- case 0x8: case 0x9: /* Data processing - immediate */
145
- disas_data_proc_imm(s, insn);
146
- break;
147
case 0xa: case 0xb: /* Branch, exception generation and system insns */
148
disas_b_exc_sys(s, insn);
16
break;
149
break;
17
case 0xd24: /* System Handler Control. */
18
- /* TODO: Real hardware allows you to set/clear the active bits
19
- under some circumstances. We don't implement this. */
20
+ s->vectors[ARMV7M_EXCP_MEM].active = (value & (1 << 0)) != 0;
21
+ s->vectors[ARMV7M_EXCP_BUS].active = (value & (1 << 1)) != 0;
22
+ s->vectors[ARMV7M_EXCP_USAGE].active = (value & (1 << 3)) != 0;
23
+ s->vectors[ARMV7M_EXCP_SVC].active = (value & (1 << 7)) != 0;
24
+ s->vectors[ARMV7M_EXCP_DEBUG].active = (value & (1 << 8)) != 0;
25
+ s->vectors[ARMV7M_EXCP_PENDSV].active = (value & (1 << 10)) != 0;
26
+ s->vectors[ARMV7M_EXCP_SYSTICK].active = (value & (1 << 11)) != 0;
27
+ s->vectors[ARMV7M_EXCP_USAGE].pending = (value & (1 << 12)) != 0;
28
+ s->vectors[ARMV7M_EXCP_MEM].pending = (value & (1 << 13)) != 0;
29
+ s->vectors[ARMV7M_EXCP_BUS].pending = (value & (1 << 14)) != 0;
30
+ s->vectors[ARMV7M_EXCP_SVC].pending = (value & (1 << 15)) != 0;
31
s->vectors[ARMV7M_EXCP_MEM].enabled = (value & (1 << 16)) != 0;
32
s->vectors[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0;
33
s->vectors[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0;
34
--
150
--
35
2.7.4
151
2.34.1
36
37
diff view generated by jsdifflib
1
Switch to using qcrypto_random_bytes() rather than rand() as
1
Convert the unconditional branch immediate insns B and BL to
2
our source of randomness for the BCM2835 RNG.
2
decodetree.
3
4
If qcrypto_random_bytes() fails, we don't want to return the guest a
5
non-random value in case they're really using it for cryptographic
6
purposes, so the best we can do is a fatal error. This shouldn't
7
happen unless something's broken, though.
8
9
In theory we could implement this device's full FIFO and interrupt
10
semantics and then just stop filling the FIFO. That's a lot of work,
11
though, and doesn't really give a very nice diagnostic to the user
12
since the guest will just seem to hang.
13
3
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230512144106.3608981-14-peter.maydell@linaro.org
16
---
7
---
17
hw/misc/bcm2835_rng.c | 27 ++++++++++++++++++++++++++-
8
target/arm/tcg/a64.decode | 9 +++++++++
18
1 file changed, 26 insertions(+), 1 deletion(-)
9
target/arm/tcg/translate-a64.c | 31 +++++++++++--------------------
10
2 files changed, 20 insertions(+), 20 deletions(-)
19
11
20
diff --git a/hw/misc/bcm2835_rng.c b/hw/misc/bcm2835_rng.c
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
21
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/bcm2835_rng.c
14
--- a/target/arm/tcg/a64.decode
23
+++ b/hw/misc/bcm2835_rng.c
15
+++ b/target/arm/tcg/a64.decode
24
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@
25
17
26
#include "qemu/osdep.h"
18
&ri rd imm
27
#include "qemu/log.h"
19
&rri_sf rd rn imm sf
28
+#include "qapi/error.h"
20
+&i imm
29
+#include "crypto/random.h"
21
30
#include "hw/misc/bcm2835_rng.h"
22
31
23
### Data Processing - Immediate
32
+static uint32_t get_random_bytes(void)
24
@@ -XXX,XX +XXX,XX @@ UBFM . 10 100110 . ...... ...... ..... ..... @bitfield_32
33
+{
25
34
+ uint32_t res;
26
EXTR 1 00 100111 1 0 rm:5 imm:6 rn:5 rd:5 &extract sf=1
35
+ Error *err = NULL;
27
EXTR 0 00 100111 0 0 rm:5 0 imm:5 rn:5 rd:5 &extract sf=0
36
+
28
+
37
+ if (qcrypto_random_bytes((uint8_t *)&res, sizeof(res), &err) < 0) {
29
+# Branches
38
+ /* On failure we don't want to return the guest a non-random
30
+
39
+ * value in case they're really using it for cryptographic
31
+%imm26 0:s26 !function=times_4
40
+ * purposes, so the best we can do is die here.
32
+@branch . ..... .......................... &i imm=%imm26
41
+ * This shouldn't happen unless something's broken.
33
+
42
+ * In theory we could implement this device's full FIFO
34
+B 0 00101 .......................... @branch
43
+ * and interrupt semantics and then just stop filling the
35
+BL 1 00101 .......................... @branch
44
+ * FIFO. That's a lot of work, though, so we assume any
36
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
45
+ * errors are systematic problems and trust that if we didn't
37
index XXXXXXX..XXXXXXX 100644
46
+ * fail as the guest inited then we won't fail later on
38
--- a/target/arm/tcg/translate-a64.c
47
+ * mid-run.
39
+++ b/target/arm/tcg/translate-a64.c
48
+ */
40
@@ -XXX,XX +XXX,XX @@ static inline AArch64DecodeFn *lookup_disas_fn(const AArch64DecodeTable *table,
49
+ error_report_err(err);
41
* match up with those in the manual.
50
+ exit(1);
42
*/
51
+ }
43
52
+ return res;
44
-/* Unconditional branch (immediate)
45
- * 31 30 26 25 0
46
- * +----+-----------+-------------------------------------+
47
- * | op | 0 0 1 0 1 | imm26 |
48
- * +----+-----------+-------------------------------------+
49
- */
50
-static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
51
+static bool trans_B(DisasContext *s, arg_i *a)
52
{
53
- int64_t diff = sextract32(insn, 0, 26) * 4;
54
-
55
- if (insn & (1U << 31)) {
56
- /* BL Branch with link */
57
- gen_pc_plus_diff(s, cpu_reg(s, 30), curr_insn_len(s));
58
- }
59
-
60
- /* B Branch / BL Branch with link */
61
reset_btype(s);
62
- gen_goto_tb(s, 0, diff);
63
+ gen_goto_tb(s, 0, a->imm);
64
+ return true;
53
+}
65
+}
54
+
66
+
55
static uint64_t bcm2835_rng_read(void *opaque, hwaddr offset,
67
+static bool trans_BL(DisasContext *s, arg_i *a)
56
unsigned size)
68
+{
69
+ gen_pc_plus_diff(s, cpu_reg(s, 30), curr_insn_len(s));
70
+ reset_btype(s);
71
+ gen_goto_tb(s, 0, a->imm);
72
+ return true;
73
}
74
75
/* Compare and branch (immediate)
76
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
77
static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
57
{
78
{
58
@@ -XXX,XX +XXX,XX @@ static uint64_t bcm2835_rng_read(void *opaque, hwaddr offset,
79
switch (extract32(insn, 25, 7)) {
59
res = s->rng_status | (1 << 24);
80
- case 0x0a: case 0x0b:
81
- case 0x4a: case 0x4b: /* Unconditional branch (immediate) */
82
- disas_uncond_b_imm(s, insn);
83
- break;
84
case 0x1a: case 0x5a: /* Compare & branch (immediate) */
85
disas_comp_b_imm(s, insn);
60
break;
86
break;
61
case 0x8: /* rng_data */
62
- res = rand();
63
+ res = get_random_bytes();
64
break;
65
66
default:
67
--
87
--
68
2.7.4
88
2.34.1
69
70
diff view generated by jsdifflib
1
M profile doesn't implement ARM, and the architecturally required
1
Convert the compare-and-branch-immediate insns CBZ and CBNZ
2
behaviour for attempts to execute with the Thumb bit clear is to
2
to decodetree.
3
generate a UsageFault with the CFSR INVSTATE bit set. We were
4
incorrectly implementing this as generating an UNDEFINSTR UsageFault;
5
fix this.
6
3
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230512144106.3608981-15-peter.maydell@linaro.org
9
---
7
---
10
target/arm/cpu.h | 1 +
8
target/arm/tcg/a64.decode | 5 +++++
11
linux-user/main.c | 1 +
9
target/arm/tcg/translate-a64.c | 26 ++++++--------------------
12
target/arm/helper.c | 4 ++++
10
2 files changed, 11 insertions(+), 20 deletions(-)
13
target/arm/translate.c | 8 ++++++--
14
4 files changed, 12 insertions(+), 2 deletions(-)
15
11
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
14
--- a/target/arm/tcg/a64.decode
19
+++ b/target/arm/cpu.h
15
+++ b/target/arm/tcg/a64.decode
20
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ EXTR 0 00 100111 0 0 rm:5 0 imm:5 rn:5 rd:5 &extract sf=0
21
#define EXCP_VFIQ 15
17
22
#define EXCP_SEMIHOST 16 /* semihosting call */
18
B 0 00101 .......................... @branch
23
#define EXCP_NOCP 17 /* v7M NOCP UsageFault */
19
BL 1 00101 .......................... @branch
24
+#define EXCP_INVSTATE 18 /* v7M INVSTATE UsageFault */
20
+
25
21
+%imm19 5:s19 !function=times_4
26
#define ARMV7M_EXCP_RESET 1
22
+&cbz rt imm sf nz
27
#define ARMV7M_EXCP_NMI 2
23
+
28
diff --git a/linux-user/main.c b/linux-user/main.c
24
+CBZ sf:1 011010 nz:1 ................... rt:5 &cbz imm=%imm19
25
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
29
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
30
--- a/linux-user/main.c
27
--- a/target/arm/tcg/translate-a64.c
31
+++ b/linux-user/main.c
28
+++ b/target/arm/tcg/translate-a64.c
32
@@ -XXX,XX +XXX,XX @@ void cpu_loop(CPUARMState *env)
29
@@ -XXX,XX +XXX,XX @@ static bool trans_BL(DisasContext *s, arg_i *a)
33
switch(trapnr) {
30
return true;
34
case EXCP_UDEF:
31
}
35
case EXCP_NOCP:
32
36
+ case EXCP_INVSTATE:
33
-/* Compare and branch (immediate)
37
{
34
- * 31 30 25 24 23 5 4 0
38
TaskState *ts = cs->opaque;
35
- * +----+-------------+----+---------------------+--------+
39
uint32_t opcode;
36
- * | sf | 0 1 1 0 1 0 | op | imm19 | Rt |
40
diff --git a/target/arm/helper.c b/target/arm/helper.c
37
- * +----+-------------+----+---------------------+--------+
41
index XXXXXXX..XXXXXXX 100644
38
- */
42
--- a/target/arm/helper.c
39
-static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
43
+++ b/target/arm/helper.c
40
+
44
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
41
+static bool trans_CBZ(DisasContext *s, arg_cbz *a)
45
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
42
{
46
env->v7m.cfsr |= R_V7M_CFSR_NOCP_MASK;
43
- unsigned int sf, op, rt;
44
- int64_t diff;
45
DisasLabel match;
46
TCGv_i64 tcg_cmp;
47
48
- sf = extract32(insn, 31, 1);
49
- op = extract32(insn, 24, 1); /* 0: CBZ; 1: CBNZ */
50
- rt = extract32(insn, 0, 5);
51
- diff = sextract32(insn, 5, 19) * 4;
52
-
53
- tcg_cmp = read_cpu_reg(s, rt, sf);
54
+ tcg_cmp = read_cpu_reg(s, a->rt, a->sf);
55
reset_btype(s);
56
57
match = gen_disas_label(s);
58
- tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
59
+ tcg_gen_brcondi_i64(a->nz ? TCG_COND_NE : TCG_COND_EQ,
60
tcg_cmp, 0, match.label);
61
gen_goto_tb(s, 0, 4);
62
set_disas_label(s, match);
63
- gen_goto_tb(s, 1, diff);
64
+ gen_goto_tb(s, 1, a->imm);
65
+ return true;
66
}
67
68
/* Test and branch (immediate)
69
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
70
static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
71
{
72
switch (extract32(insn, 25, 7)) {
73
- case 0x1a: case 0x5a: /* Compare & branch (immediate) */
74
- disas_comp_b_imm(s, insn);
75
- break;
76
case 0x1b: case 0x5b: /* Test & branch (immediate) */
77
disas_test_b_imm(s, insn);
47
break;
78
break;
48
+ case EXCP_INVSTATE:
49
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
50
+ env->v7m.cfsr |= R_V7M_CFSR_INVSTATE_MASK;
51
+ break;
52
case EXCP_SWI:
53
/* The PC already points to the next instruction. */
54
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC);
55
diff --git a/target/arm/translate.c b/target/arm/translate.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/translate.c
58
+++ b/target/arm/translate.c
59
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
60
TCGv_i32 addr;
61
TCGv_i64 tmp64;
62
63
- /* M variants do not implement ARM mode. */
64
+ /* M variants do not implement ARM mode; this must raise the INVSTATE
65
+ * UsageFault exception.
66
+ */
67
if (arm_dc_feature(s, ARM_FEATURE_M)) {
68
- goto illegal_op;
69
+ gen_exception_insn(s, 4, EXCP_INVSTATE, syn_uncategorized(),
70
+ default_exception_el(s));
71
+ return;
72
}
73
cond = insn >> 28;
74
if (cond == 0xf){
75
--
79
--
76
2.7.4
80
2.34.1
77
78
diff view generated by jsdifflib
1
Having armv7m_nvic_acknowledge_irq() return the new value of
1
Convert the test-and-branch-immediate insns TBZ and TBNZ
2
env->v7m.exception and its one caller assign the return value
2
to decodetree.
3
back to env->v7m.exception is pointless. Just make the return
4
type void instead.
5
3
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230512144106.3608981-16-peter.maydell@linaro.org
8
---
7
---
9
target/arm/cpu.h | 2 +-
8
target/arm/tcg/a64.decode | 6 ++++++
10
hw/intc/armv7m_nvic.c | 4 +---
9
target/arm/tcg/translate-a64.c | 25 +++++--------------------
11
target/arm/helper.c | 2 +-
10
2 files changed, 11 insertions(+), 20 deletions(-)
12
3 files changed, 3 insertions(+), 5 deletions(-)
13
11
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
15
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
14
--- a/target/arm/tcg/a64.decode
17
+++ b/target/arm/cpu.h
15
+++ b/target/arm/tcg/a64.decode
18
@@ -XXX,XX +XXX,XX @@ static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
16
@@ -XXX,XX +XXX,XX @@ BL 1 00101 .......................... @branch
17
&cbz rt imm sf nz
18
19
CBZ sf:1 011010 nz:1 ................... rt:5 &cbz imm=%imm19
20
+
21
+%imm14 5:s14 !function=times_4
22
+%imm31_19 31:1 19:5
23
+&tbz rt imm nz bitpos
24
+
25
+TBZ . 011011 nz:1 ..... .............. rt:5 &tbz imm=%imm14 bitpos=%imm31_19
26
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/tcg/translate-a64.c
29
+++ b/target/arm/tcg/translate-a64.c
30
@@ -XXX,XX +XXX,XX @@ static bool trans_CBZ(DisasContext *s, arg_cbz *a)
31
return true;
19
}
32
}
20
#endif
33
21
void armv7m_nvic_set_pending(void *opaque, int irq);
34
-/* Test and branch (immediate)
22
-int armv7m_nvic_acknowledge_irq(void *opaque);
35
- * 31 30 25 24 23 19 18 5 4 0
23
+void armv7m_nvic_acknowledge_irq(void *opaque);
36
- * +----+-------------+----+-------+-------------+------+
24
void armv7m_nvic_complete_irq(void *opaque, int irq);
37
- * | b5 | 0 1 1 0 1 1 | op | b40 | imm14 | Rt |
25
38
- * +----+-------------+----+-------+-------------+------+
26
/* Interface for defining coprocessor registers.
39
- */
27
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
40
-static void disas_test_b_imm(DisasContext *s, uint32_t insn)
28
index XXXXXXX..XXXXXXX 100644
41
+static bool trans_TBZ(DisasContext *s, arg_tbz *a)
29
--- a/hw/intc/armv7m_nvic.c
42
{
30
+++ b/hw/intc/armv7m_nvic.c
43
- unsigned int bit_pos, op, rt;
31
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq)
44
- int64_t diff;
45
DisasLabel match;
46
TCGv_i64 tcg_cmp;
47
48
- bit_pos = (extract32(insn, 31, 1) << 5) | extract32(insn, 19, 5);
49
- op = extract32(insn, 24, 1); /* 0: TBZ; 1: TBNZ */
50
- diff = sextract32(insn, 5, 14) * 4;
51
- rt = extract32(insn, 0, 5);
52
-
53
tcg_cmp = tcg_temp_new_i64();
54
- tcg_gen_andi_i64(tcg_cmp, cpu_reg(s, rt), (1ULL << bit_pos));
55
+ tcg_gen_andi_i64(tcg_cmp, cpu_reg(s, a->rt), 1ULL << a->bitpos);
56
57
reset_btype(s);
58
59
match = gen_disas_label(s);
60
- tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
61
+ tcg_gen_brcondi_i64(a->nz ? TCG_COND_NE : TCG_COND_EQ,
62
tcg_cmp, 0, match.label);
63
gen_goto_tb(s, 0, 4);
64
set_disas_label(s, match);
65
- gen_goto_tb(s, 1, diff);
66
+ gen_goto_tb(s, 1, a->imm);
67
+ return true;
32
}
68
}
33
69
34
/* Make pending IRQ active. */
70
/* Conditional branch (immediate)
35
-int armv7m_nvic_acknowledge_irq(void *opaque)
71
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
36
+void armv7m_nvic_acknowledge_irq(void *opaque)
72
static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
37
{
73
{
38
NVICState *s = (NVICState *)opaque;
74
switch (extract32(insn, 25, 7)) {
39
CPUARMState *env = &s->cpu->env;
75
- case 0x1b: case 0x5b: /* Test & branch (immediate) */
40
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_acknowledge_irq(void *opaque)
76
- disas_test_b_imm(s, insn);
41
env->v7m.exception = s->vectpending;
77
- break;
42
78
case 0x2a: /* Conditional branch (immediate) */
43
nvic_irq_update(s);
79
disas_cond_b_imm(s, insn);
44
-
45
- return env->v7m.exception;
46
}
47
48
void armv7m_nvic_complete_irq(void *opaque, int irq)
49
diff --git a/target/arm/helper.c b/target/arm/helper.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/helper.c
52
+++ b/target/arm/helper.c
53
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
54
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG);
55
return;
56
case EXCP_IRQ:
57
- env->v7m.exception = armv7m_nvic_acknowledge_irq(env->nvic);
58
+ armv7m_nvic_acknowledge_irq(env->nvic);
59
break;
80
break;
60
case EXCP_EXCEPTION_EXIT:
61
do_v7m_exception_exit(env);
62
--
81
--
63
2.7.4
82
2.34.1
64
65
diff view generated by jsdifflib
1
Implement the exception return consistency checks
1
Convert the immediate conditional branch insn B.cond to
2
described in the v7M pseudocode ExceptionReturn().
2
decodetree.
3
4
Inspired by a patch from Michael Davidsaver's series, but
5
this is a reimplementation from scratch based on the
6
ARM ARM pseudocode.
7
3
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230512144106.3608981-17-peter.maydell@linaro.org
10
---
7
---
11
target/arm/cpu.h | 12 +++++-
8
target/arm/tcg/a64.decode | 2 ++
12
hw/intc/armv7m_nvic.c | 12 +++++-
9
target/arm/tcg/translate-a64.c | 30 ++++++------------------------
13
target/arm/helper.c | 112 +++++++++++++++++++++++++++++++++++++++++++++-----
10
2 files changed, 8 insertions(+), 24 deletions(-)
14
3 files changed, 123 insertions(+), 13 deletions(-)
15
11
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
14
--- a/target/arm/tcg/a64.decode
19
+++ b/target/arm/cpu.h
15
+++ b/target/arm/tcg/a64.decode
20
@@ -XXX,XX +XXX,XX @@ static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
16
@@ -XXX,XX +XXX,XX @@ CBZ sf:1 011010 nz:1 ................... rt:5 &cbz imm=%imm19
21
#endif
17
&tbz rt imm nz bitpos
22
void armv7m_nvic_set_pending(void *opaque, int irq);
18
23
void armv7m_nvic_acknowledge_irq(void *opaque);
19
TBZ . 011011 nz:1 ..... .............. rt:5 &tbz imm=%imm14 bitpos=%imm31_19
24
-void armv7m_nvic_complete_irq(void *opaque, int irq);
20
+
25
+/**
21
+B_cond 0101010 0 ................... 0 cond:4 imm=%imm19
26
+ * armv7m_nvic_complete_irq: complete specified interrupt or exception
22
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
27
+ * @opaque: the NVIC
28
+ * @irq: the exception number to complete
29
+ *
30
+ * Returns: -1 if the irq was not active
31
+ * 1 if completing this irq brought us back to base (no active irqs)
32
+ * 0 if there is still an irq active after this one was completed
33
+ * (Ignoring -1, this is the same as the RETTOBASE value before completion.)
34
+ */
35
+int armv7m_nvic_complete_irq(void *opaque, int irq);
36
37
/* Interface for defining coprocessor registers.
38
* Registers are defined in tables of arm_cp_reginfo structs
39
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
40
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/intc/armv7m_nvic.c
24
--- a/target/arm/tcg/translate-a64.c
42
+++ b/hw/intc/armv7m_nvic.c
25
+++ b/target/arm/tcg/translate-a64.c
43
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_acknowledge_irq(void *opaque)
26
@@ -XXX,XX +XXX,XX @@ static bool trans_TBZ(DisasContext *s, arg_tbz *a)
44
nvic_irq_update(s);
27
return true;
45
}
28
}
46
29
47
-void armv7m_nvic_complete_irq(void *opaque, int irq)
30
-/* Conditional branch (immediate)
48
+int armv7m_nvic_complete_irq(void *opaque, int irq)
31
- * 31 25 24 23 5 4 3 0
32
- * +---------------+----+---------------------+----+------+
33
- * | 0 1 0 1 0 1 0 | o1 | imm19 | o0 | cond |
34
- * +---------------+----+---------------------+----+------+
35
- */
36
-static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
37
+static bool trans_B_cond(DisasContext *s, arg_B_cond *a)
49
{
38
{
50
NVICState *s = (NVICState *)opaque;
39
- unsigned int cond;
51
VecInfo *vec;
40
- int64_t diff;
52
+ int ret;
41
-
53
42
- if ((insn & (1 << 4)) || (insn & (1 << 24))) {
54
assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
43
- unallocated_encoding(s);
55
44
- return;
56
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_complete_irq(void *opaque, int irq)
45
- }
57
46
- diff = sextract32(insn, 5, 19) * 4;
58
trace_nvic_complete_irq(irq);
47
- cond = extract32(insn, 0, 4);
59
48
-
60
+ if (!vec->active) {
49
reset_btype(s);
61
+ /* Tell the caller this was an illegal exception return */
50
- if (cond < 0x0e) {
62
+ return -1;
51
+ if (a->cond < 0x0e) {
63
+ }
52
/* genuinely conditional branches */
64
+
53
DisasLabel match = gen_disas_label(s);
65
+ ret = nvic_rettobase(s);
54
- arm_gen_test_cc(cond, match.label);
66
+
55
+ arm_gen_test_cc(a->cond, match.label);
67
vec->active = 0;
56
gen_goto_tb(s, 0, 4);
68
if (vec->level) {
57
set_disas_label(s, match);
69
/* Re-pend the exception if it's still held high; only
58
- gen_goto_tb(s, 1, diff);
70
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_complete_irq(void *opaque, int irq)
59
+ gen_goto_tb(s, 1, a->imm);
60
} else {
61
/* 0xe and 0xf are both "always" conditions */
62
- gen_goto_tb(s, 0, diff);
63
+ gen_goto_tb(s, 0, a->imm);
71
}
64
}
72
65
+ return true;
73
nvic_irq_update(s);
74
+
75
+ return ret;
76
}
66
}
77
67
78
/* callback when external interrupt line is changed */
68
/* HINT instruction group, including various allocated HINTs */
79
diff --git a/target/arm/helper.c b/target/arm/helper.c
69
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
80
index XXXXXXX..XXXXXXX 100644
70
static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
81
--- a/target/arm/helper.c
82
+++ b/target/arm/helper.c
83
@@ -XXX,XX +XXX,XX @@ static void v7m_push_stack(ARMCPU *cpu)
84
v7m_push(env, env->regs[0]);
85
}
86
87
-static void do_v7m_exception_exit(CPUARMState *env)
88
+static void do_v7m_exception_exit(ARMCPU *cpu)
89
{
71
{
90
+ CPUARMState *env = &cpu->env;
72
switch (extract32(insn, 25, 7)) {
91
uint32_t type;
73
- case 0x2a: /* Conditional branch (immediate) */
92
uint32_t xpsr;
74
- disas_cond_b_imm(s, insn);
93
-
75
- break;
94
+ bool ufault = false;
76
case 0x6a: /* Exception generation / System */
95
+ bool return_to_sp_process = false;
77
if (insn & (1 << 24)) {
96
+ bool return_to_handler = false;
78
if (extract32(insn, 22, 2) == 0) {
97
+ bool rettobase = false;
98
+
99
+ /* We can only get here from an EXCP_EXCEPTION_EXIT, and
100
+ * arm_v7m_do_unassigned_access() enforces the architectural rule
101
+ * that jumps to magic addresses don't have magic behaviour unless
102
+ * we're in Handler mode (compare pseudocode BXWritePC()).
103
+ */
104
+ assert(env->v7m.exception != 0);
105
+
106
+ /* In the spec pseudocode ExceptionReturn() is called directly
107
+ * from BXWritePC() and gets the full target PC value including
108
+ * bit zero. In QEMU's implementation we treat it as a normal
109
+ * jump-to-register (which is then caught later on), and so split
110
+ * the target value up between env->regs[15] and env->thumb in
111
+ * gen_bx(). Reconstitute it.
112
+ */
113
type = env->regs[15];
114
+ if (env->thumb) {
115
+ type |= 1;
116
+ }
117
+
118
+ qemu_log_mask(CPU_LOG_INT, "Exception return: magic PC %" PRIx32
119
+ " previous exception %d\n",
120
+ type, env->v7m.exception);
121
+
122
+ if (extract32(type, 5, 23) != extract32(-1, 5, 23)) {
123
+ qemu_log_mask(LOG_GUEST_ERROR, "M profile: zero high bits in exception "
124
+ "exit PC value 0x%" PRIx32 " are UNPREDICTABLE\n", type);
125
+ }
126
+
127
if (env->v7m.exception != ARMV7M_EXCP_NMI) {
128
/* Auto-clear FAULTMASK on return from other than NMI */
129
env->daif &= ~PSTATE_F;
130
}
131
- if (env->v7m.exception != 0) {
132
- armv7m_nvic_complete_irq(env->nvic, env->v7m.exception);
133
+
134
+ switch (armv7m_nvic_complete_irq(env->nvic, env->v7m.exception)) {
135
+ case -1:
136
+ /* attempt to exit an exception that isn't active */
137
+ ufault = true;
138
+ break;
139
+ case 0:
140
+ /* still an irq active now */
141
+ break;
142
+ case 1:
143
+ /* we returned to base exception level, no nesting.
144
+ * (In the pseudocode this is written using "NestedActivation != 1"
145
+ * where we have 'rettobase == false'.)
146
+ */
147
+ rettobase = true;
148
+ break;
149
+ default:
150
+ g_assert_not_reached();
151
+ }
152
+
153
+ switch (type & 0xf) {
154
+ case 1: /* Return to Handler */
155
+ return_to_handler = true;
156
+ break;
157
+ case 13: /* Return to Thread using Process stack */
158
+ return_to_sp_process = true;
159
+ /* fall through */
160
+ case 9: /* Return to Thread using Main stack */
161
+ if (!rettobase &&
162
+ !(env->v7m.ccr & R_V7M_CCR_NONBASETHRDENA_MASK)) {
163
+ ufault = true;
164
+ }
165
+ break;
166
+ default:
167
+ ufault = true;
168
+ }
169
+
170
+ if (ufault) {
171
+ /* Bad exception return: instead of popping the exception
172
+ * stack, directly take a usage fault on the current stack.
173
+ */
174
+ env->v7m.cfsr |= R_V7M_CFSR_INVPC_MASK;
175
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
176
+ v7m_exception_taken(cpu, type | 0xf0000000);
177
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
178
+ "stackframe: failed exception return integrity check\n");
179
+ return;
180
}
181
182
/* Switch to the target stack. */
183
- switch_v7m_sp(env, (type & 4) != 0);
184
+ switch_v7m_sp(env, return_to_sp_process);
185
/* Pop registers. */
186
env->regs[0] = v7m_pop(env);
187
env->regs[1] = v7m_pop(env);
188
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(CPUARMState *env)
189
/* Undo stack alignment. */
190
if (xpsr & 0x200)
191
env->regs[13] |= 4;
192
- /* ??? The exception return type specifies Thread/Handler mode. However
193
- this is also implied by the xPSR value. Not sure what to do
194
- if there is a mismatch. */
195
- /* ??? Likewise for mismatches between the CONTROL register and the stack
196
- pointer. */
197
+
198
+ /* The restored xPSR exception field will be zero if we're
199
+ * resuming in Thread mode. If that doesn't match what the
200
+ * exception return type specified then this is a UsageFault.
201
+ */
202
+ if (return_to_handler == (env->v7m.exception == 0)) {
203
+ /* Take an INVPC UsageFault by pushing the stack again. */
204
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
205
+ env->v7m.cfsr |= R_V7M_CFSR_INVPC_MASK;
206
+ v7m_push_stack(cpu);
207
+ v7m_exception_taken(cpu, type | 0xf0000000);
208
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on new stackframe: "
209
+ "failed exception return integrity check\n");
210
+ return;
211
+ }
212
+
213
+ /* Otherwise, we have a successful exception exit. */
214
+ qemu_log_mask(CPU_LOG_INT, "...successful exception return\n");
215
}
216
217
static void arm_log_exception(int idx)
218
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
219
case EXCP_IRQ:
220
break;
221
case EXCP_EXCEPTION_EXIT:
222
- do_v7m_exception_exit(env);
223
+ do_v7m_exception_exit(cpu);
224
return;
225
default:
226
cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
227
--
79
--
228
2.7.4
80
2.34.1
229
230
diff view generated by jsdifflib
1
From: Marcin Chojnacki <marcinch7@gmail.com>
1
Convert the simple (non-pointer-auth) BR, BLR and RET insns
2
to decodetree.
2
3
3
Recent vanilla Raspberry Pi kernels started to make use of
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
the hardware random number generator in BCM2835 SoC. As a
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
result, those kernels wouldn't work anymore under QEMU
6
Message-id: 20230512144106.3608981-18-peter.maydell@linaro.org
6
but rather just freeze during the boot process.
7
---
8
target/arm/tcg/a64.decode | 5 ++++
9
target/arm/tcg/translate-a64.c | 55 ++++++++++++++++++++++++++++++----
10
2 files changed, 54 insertions(+), 6 deletions(-)
7
11
8
This patch implements a trivial BCM2835 compatible RNG,
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
9
and adds it as a peripheral to BCM2835 platform, which
10
allows to boot a vanilla Raspberry Pi kernel under Qemu.
11
12
Changes since v1:
13
* Prevented guest from writing [31..20] bits in rng_status
14
* Removed redundant minimum_version_id_old
15
* Added field entries for the state
16
* Changed realize function to reset
17
18
Signed-off-by: Marcin Chojnacki <marcinch7@gmail.com>
19
Message-id: 20170210210857.47893-1-marcinch7@gmail.com
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
23
hw/misc/Makefile.objs | 1 +
24
include/hw/arm/bcm2835_peripherals.h | 2 +
25
include/hw/misc/bcm2835_rng.h | 27 ++++++++
26
hw/arm/bcm2835_peripherals.c | 15 +++++
27
hw/misc/bcm2835_rng.c | 124 +++++++++++++++++++++++++++++++++++
28
5 files changed, 169 insertions(+)
29
create mode 100644 include/hw/misc/bcm2835_rng.h
30
create mode 100644 hw/misc/bcm2835_rng.c
31
32
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
33
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/misc/Makefile.objs
14
--- a/target/arm/tcg/a64.decode
35
+++ b/hw/misc/Makefile.objs
15
+++ b/target/arm/tcg/a64.decode
36
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_OMAP) += omap_sdrc.o
16
@@ -XXX,XX +XXX,XX @@
37
obj-$(CONFIG_OMAP) += omap_tap.o
17
# This file is processed by scripts/decodetree.py
38
obj-$(CONFIG_RASPI) += bcm2835_mbox.o
18
#
39
obj-$(CONFIG_RASPI) += bcm2835_property.o
19
40
+obj-$(CONFIG_RASPI) += bcm2835_rng.o
20
+&r rn
41
obj-$(CONFIG_SLAVIO) += slavio_misc.o
21
&ri rd imm
42
obj-$(CONFIG_ZYNQ) += zynq_slcr.o
22
&rri_sf rd rn imm sf
43
obj-$(CONFIG_ZYNQ) += zynq-xadc.o
23
&i imm
44
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
24
@@ -XXX,XX +XXX,XX @@ CBZ sf:1 011010 nz:1 ................... rt:5 &cbz imm=%imm19
25
TBZ . 011011 nz:1 ..... .............. rt:5 &tbz imm=%imm14 bitpos=%imm31_19
26
27
B_cond 0101010 0 ................... 0 cond:4 imm=%imm19
28
+
29
+BR 1101011 0000 11111 000000 rn:5 00000 &r
30
+BLR 1101011 0001 11111 000000 rn:5 00000 &r
31
+RET 1101011 0010 11111 000000 rn:5 00000 &r
32
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
45
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
46
--- a/include/hw/arm/bcm2835_peripherals.h
34
--- a/target/arm/tcg/translate-a64.c
47
+++ b/include/hw/arm/bcm2835_peripherals.h
35
+++ b/target/arm/tcg/translate-a64.c
48
@@ -XXX,XX +XXX,XX @@
36
@@ -XXX,XX +XXX,XX @@ static bool trans_B_cond(DisasContext *s, arg_B_cond *a)
49
#include "hw/dma/bcm2835_dma.h"
37
return true;
50
#include "hw/intc/bcm2835_ic.h"
38
}
51
#include "hw/misc/bcm2835_property.h"
39
52
+#include "hw/misc/bcm2835_rng.h"
40
+static void set_btype_for_br(DisasContext *s, int rn)
53
#include "hw/misc/bcm2835_mbox.h"
54
#include "hw/sd/sdhci.h"
55
56
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2835PeripheralState {
57
BCM2835DMAState dma;
58
BCM2835ICState ic;
59
BCM2835PropertyState property;
60
+ BCM2835RngState rng;
61
BCM2835MboxState mboxes;
62
SDHCIState sdhci;
63
} BCM2835PeripheralState;
64
diff --git a/include/hw/misc/bcm2835_rng.h b/include/hw/misc/bcm2835_rng.h
65
new file mode 100644
66
index XXXXXXX..XXXXXXX
67
--- /dev/null
68
+++ b/include/hw/misc/bcm2835_rng.h
69
@@ -XXX,XX +XXX,XX @@
70
+/*
71
+ * BCM2835 Random Number Generator emulation
72
+ *
73
+ * Copyright (C) 2017 Marcin Chojnacki <marcinch7@gmail.com>
74
+ *
75
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
76
+ * See the COPYING file in the top-level directory.
77
+ */
78
+
79
+#ifndef BCM2835_RNG_H
80
+#define BCM2835_RNG_H
81
+
82
+#include "hw/sysbus.h"
83
+
84
+#define TYPE_BCM2835_RNG "bcm2835-rng"
85
+#define BCM2835_RNG(obj) \
86
+ OBJECT_CHECK(BCM2835RngState, (obj), TYPE_BCM2835_RNG)
87
+
88
+typedef struct {
89
+ SysBusDevice busdev;
90
+ MemoryRegion iomem;
91
+
92
+ uint32_t rng_ctrl;
93
+ uint32_t rng_status;
94
+} BCM2835RngState;
95
+
96
+#endif
97
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
98
index XXXXXXX..XXXXXXX 100644
99
--- a/hw/arm/bcm2835_peripherals.c
100
+++ b/hw/arm/bcm2835_peripherals.c
101
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
102
object_property_add_const_link(OBJECT(&s->property), "dma-mr",
103
OBJECT(&s->gpu_bus_mr), &error_abort);
104
105
+ /* Random Number Generator */
106
+ object_initialize(&s->rng, sizeof(s->rng), TYPE_BCM2835_RNG);
107
+ object_property_add_child(obj, "rng", OBJECT(&s->rng), NULL);
108
+ qdev_set_parent_bus(DEVICE(&s->rng), sysbus_get_default());
109
+
110
/* Extended Mass Media Controller */
111
object_initialize(&s->sdhci, sizeof(s->sdhci), TYPE_SYSBUS_SDHCI);
112
object_property_add_child(obj, "sdhci", OBJECT(&s->sdhci), NULL);
113
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
114
sysbus_connect_irq(SYS_BUS_DEVICE(&s->property), 0,
115
qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_PROPERTY));
116
117
+ /* Random Number Generator */
118
+ object_property_set_bool(OBJECT(&s->rng), true, "realized", &err);
119
+ if (err) {
120
+ error_propagate(errp, err);
121
+ return;
122
+ }
123
+
124
+ memory_region_add_subregion(&s->peri_mr, RNG_OFFSET,
125
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->rng), 0));
126
+
127
/* Extended Mass Media Controller */
128
object_property_set_int(OBJECT(&s->sdhci), BCM2835_SDHC_CAPAREG, "capareg",
129
&err);
130
diff --git a/hw/misc/bcm2835_rng.c b/hw/misc/bcm2835_rng.c
131
new file mode 100644
132
index XXXXXXX..XXXXXXX
133
--- /dev/null
134
+++ b/hw/misc/bcm2835_rng.c
135
@@ -XXX,XX +XXX,XX @@
136
+/*
137
+ * BCM2835 Random Number Generator emulation
138
+ *
139
+ * Copyright (C) 2017 Marcin Chojnacki <marcinch7@gmail.com>
140
+ *
141
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
142
+ * See the COPYING file in the top-level directory.
143
+ */
144
+
145
+#include "qemu/osdep.h"
146
+#include "qemu/log.h"
147
+#include "hw/misc/bcm2835_rng.h"
148
+
149
+static uint64_t bcm2835_rng_read(void *opaque, hwaddr offset,
150
+ unsigned size)
151
+{
41
+{
152
+ BCM2835RngState *s = (BCM2835RngState *)opaque;
42
+ if (dc_isar_feature(aa64_bti, s)) {
153
+ uint32_t res = 0;
43
+ /* BR to {x16,x17} or !guard -> 1, else 3. */
154
+
44
+ set_btype(s, rn == 16 || rn == 17 || !s->guarded_page ? 1 : 3);
155
+ assert(size == 4);
156
+
157
+ switch (offset) {
158
+ case 0x0: /* rng_ctrl */
159
+ res = s->rng_ctrl;
160
+ break;
161
+ case 0x4: /* rng_status */
162
+ res = s->rng_status | (1 << 24);
163
+ break;
164
+ case 0x8: /* rng_data */
165
+ res = rand();
166
+ break;
167
+
168
+ default:
169
+ qemu_log_mask(LOG_GUEST_ERROR,
170
+ "bcm2835_rng_read: Bad offset %x\n",
171
+ (int)offset);
172
+ res = 0;
173
+ break;
174
+ }
175
+
176
+ return res;
177
+}
178
+
179
+static void bcm2835_rng_write(void *opaque, hwaddr offset,
180
+ uint64_t value, unsigned size)
181
+{
182
+ BCM2835RngState *s = (BCM2835RngState *)opaque;
183
+
184
+ assert(size == 4);
185
+
186
+ switch (offset) {
187
+ case 0x0: /* rng_ctrl */
188
+ s->rng_ctrl = value;
189
+ break;
190
+ case 0x4: /* rng_status */
191
+ /* we shouldn't let the guest write to bits [31..20] */
192
+ s->rng_status &= ~0xFFFFF; /* clear 20 lower bits */
193
+ s->rng_status |= value & 0xFFFFF; /* set them to new value */
194
+ break;
195
+
196
+ default:
197
+ qemu_log_mask(LOG_GUEST_ERROR,
198
+ "bcm2835_rng_write: Bad offset %x\n",
199
+ (int)offset);
200
+ break;
201
+ }
45
+ }
202
+}
46
+}
203
+
47
+
204
+static const MemoryRegionOps bcm2835_rng_ops = {
48
+static void set_btype_for_blr(DisasContext *s)
205
+ .read = bcm2835_rng_read,
49
+{
206
+ .write = bcm2835_rng_write,
50
+ if (dc_isar_feature(aa64_bti, s)) {
207
+ .endianness = DEVICE_NATIVE_ENDIAN,
51
+ /* BLR sets BTYPE to 2, regardless of source guarded page. */
208
+};
52
+ set_btype(s, 2);
209
+
210
+static const VMStateDescription vmstate_bcm2835_rng = {
211
+ .name = TYPE_BCM2835_RNG,
212
+ .version_id = 1,
213
+ .minimum_version_id = 1,
214
+ .fields = (VMStateField[]) {
215
+ VMSTATE_UINT32(rng_ctrl, BCM2835RngState),
216
+ VMSTATE_UINT32(rng_status, BCM2835RngState),
217
+ VMSTATE_END_OF_LIST()
218
+ }
53
+ }
219
+};
220
+
221
+static void bcm2835_rng_init(Object *obj)
222
+{
223
+ BCM2835RngState *s = BCM2835_RNG(obj);
224
+
225
+ memory_region_init_io(&s->iomem, obj, &bcm2835_rng_ops, s,
226
+ TYPE_BCM2835_RNG, 0x10);
227
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
228
+}
54
+}
229
+
55
+
230
+static void bcm2835_rng_reset(DeviceState *dev)
56
+static bool trans_BR(DisasContext *s, arg_r *a)
231
+{
57
+{
232
+ BCM2835RngState *s = BCM2835_RNG(dev);
58
+ gen_a64_set_pc(s, cpu_reg(s, a->rn));
233
+
59
+ set_btype_for_br(s, a->rn);
234
+ s->rng_ctrl = 0;
60
+ s->base.is_jmp = DISAS_JUMP;
235
+ s->rng_status = 0;
61
+ return true;
236
+}
62
+}
237
+
63
+
238
+static void bcm2835_rng_class_init(ObjectClass *klass, void *data)
64
+static bool trans_BLR(DisasContext *s, arg_r *a)
239
+{
65
+{
240
+ DeviceClass *dc = DEVICE_CLASS(klass);
66
+ TCGv_i64 dst = cpu_reg(s, a->rn);
241
+
67
+ TCGv_i64 lr = cpu_reg(s, 30);
242
+ dc->reset = bcm2835_rng_reset;
68
+ if (dst == lr) {
243
+ dc->vmsd = &vmstate_bcm2835_rng;
69
+ TCGv_i64 tmp = tcg_temp_new_i64();
70
+ tcg_gen_mov_i64(tmp, dst);
71
+ dst = tmp;
72
+ }
73
+ gen_pc_plus_diff(s, lr, curr_insn_len(s));
74
+ gen_a64_set_pc(s, dst);
75
+ set_btype_for_blr(s);
76
+ s->base.is_jmp = DISAS_JUMP;
77
+ return true;
244
+}
78
+}
245
+
79
+
246
+static TypeInfo bcm2835_rng_info = {
80
+static bool trans_RET(DisasContext *s, arg_r *a)
247
+ .name = TYPE_BCM2835_RNG,
248
+ .parent = TYPE_SYS_BUS_DEVICE,
249
+ .instance_size = sizeof(BCM2835RngState),
250
+ .class_init = bcm2835_rng_class_init,
251
+ .instance_init = bcm2835_rng_init,
252
+};
253
+
254
+static void bcm2835_rng_register_types(void)
255
+{
81
+{
256
+ type_register_static(&bcm2835_rng_info);
82
+ gen_a64_set_pc(s, cpu_reg(s, a->rn));
83
+ s->base.is_jmp = DISAS_JUMP;
84
+ return true;
257
+}
85
+}
258
+
86
+
259
+type_init(bcm2835_rng_register_types)
87
/* HINT instruction group, including various allocated HINTs */
88
static void handle_hint(DisasContext *s, uint32_t insn,
89
unsigned int op1, unsigned int op2, unsigned int crm)
90
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
91
btype_mod = opc;
92
switch (op3) {
93
case 0:
94
- /* BR, BLR, RET */
95
- if (op4 != 0) {
96
- goto do_unallocated;
97
- }
98
- dst = cpu_reg(s, rn);
99
- break;
100
+ /* BR, BLR, RET : handled in decodetree */
101
+ goto do_unallocated;
102
103
case 2:
104
case 3:
260
--
105
--
261
2.7.4
106
2.34.1
262
263
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
Convert the single-register pointer-authentication variants of BR,
2
BLR, RET to decodetree. (BRAA/BLRAA are in a different branch of
3
the legacy decoder and will be dealt with in the next commit.)
2
4
3
Despite some superficial similarities of register layout, the
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
M-profile NVIC is really very different from the A-profile GIC.
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Our current attempt to reuse the GIC code means that we have
7
Message-id: 20230512144106.3608981-19-peter.maydell@linaro.org
6
significant bugs in our NVIC.
8
---
9
target/arm/tcg/a64.decode | 7 ++
10
target/arm/tcg/translate-a64.c | 132 +++++++++++++++++++--------------
11
2 files changed, 84 insertions(+), 55 deletions(-)
7
12
8
Implement the NVIC as an entirely separate device, to give
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
9
us somewhere we can get the behaviour correct.
10
11
This initial commit does not attempt to implement exception
12
priority escalation, since the GIC-based code didn't either.
13
It does fix a few bugs in passing:
14
* ICSR.RETTOBASE polarity was wrong and didn't account for
15
internal exceptions
16
* ICSR.VECTPENDING was 16 too high if the pending exception
17
was for an external interrupt
18
* UsageFault, BusFault and MemFault were not disabled on reset
19
as they are supposed to be
20
21
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
22
[PMM: reworked, various bugs and stylistic cleanups]
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
25
---
26
hw/intc/armv7m_nvic.c | 738 ++++++++++++++++++++++++++++++++++++++++----------
27
hw/intc/trace-events | 15 +
28
2 files changed, 609 insertions(+), 144 deletions(-)
29
30
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
31
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/intc/armv7m_nvic.c
15
--- a/target/arm/tcg/a64.decode
33
+++ b/hw/intc/armv7m_nvic.c
16
+++ b/target/arm/tcg/a64.decode
34
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ B_cond 0101010 0 ................... 0 cond:4 imm=%imm19
35
#include "hw/sysbus.h"
18
BR 1101011 0000 11111 000000 rn:5 00000 &r
36
#include "qemu/timer.h"
19
BLR 1101011 0001 11111 000000 rn:5 00000 &r
37
#include "hw/arm/arm.h"
20
RET 1101011 0010 11111 000000 rn:5 00000 &r
38
+#include "target/arm/cpu.h"
39
#include "exec/address-spaces.h"
40
-#include "gic_internal.h"
41
#include "qemu/log.h"
42
+#include "trace.h"
43
+
21
+
44
+/* IRQ number counting:
22
+&braz rn m
45
+ *
23
+BRAZ 1101011 0000 11111 00001 m:1 rn:5 11111 &braz # BRAAZ, BRABZ
46
+ * the num-irq property counts the number of external IRQ lines
24
+BLRAZ 1101011 0001 11111 00001 m:1 rn:5 11111 &braz # BLRAAZ, BLRABZ
47
+ *
48
+ * NVICState::num_irq counts the total number of exceptions
49
+ * (external IRQs, the 15 internal exceptions including reset,
50
+ * and one for the unused exception number 0).
51
+ *
52
+ * NVIC_MAX_IRQ is the highest permitted number of external IRQ lines.
53
+ *
54
+ * NVIC_MAX_VECTORS is the highest permitted number of exceptions.
55
+ *
56
+ * Iterating through all exceptions should typically be done with
57
+ * for (i = 1; i < s->num_irq; i++) to avoid the unused slot 0.
58
+ *
59
+ * The external qemu_irq lines are the NVIC's external IRQ lines,
60
+ * so line 0 is exception 16.
61
+ *
62
+ * In the terminology of the architecture manual, "interrupts" are
63
+ * a subcategory of exception referring to the external interrupts
64
+ * (which are exception numbers NVIC_FIRST_IRQ and upward).
65
+ * For historical reasons QEMU tends to use "interrupt" and
66
+ * "exception" more or less interchangeably.
67
+ */
68
+#define NVIC_FIRST_IRQ 16
69
+#define NVIC_MAX_VECTORS 512
70
+#define NVIC_MAX_IRQ (NVIC_MAX_VECTORS - NVIC_FIRST_IRQ)
71
+
25
+
72
+/* Effective running priority of the CPU when no exception is active
26
+&reta m
73
+ * (higher than the highest possible priority value)
27
+RETA 1101011 0010 11111 00001 m:1 11111 11111 &reta # RETAA, RETAB
74
+ */
28
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
75
+#define NVIC_NOEXC_PRIO 0x100
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/tcg/translate-a64.c
31
+++ b/target/arm/tcg/translate-a64.c
32
@@ -XXX,XX +XXX,XX @@ static bool trans_RET(DisasContext *s, arg_r *a)
33
return true;
34
}
35
36
+static TCGv_i64 auth_branch_target(DisasContext *s, TCGv_i64 dst,
37
+ TCGv_i64 modifier, bool use_key_a)
38
+{
39
+ TCGv_i64 truedst;
40
+ /*
41
+ * Return the branch target for a BRAA/RETA/etc, which is either
42
+ * just the destination dst, or that value with the pauth check
43
+ * done and the code removed from the high bits.
44
+ */
45
+ if (!s->pauth_active) {
46
+ return dst;
47
+ }
76
+
48
+
77
+typedef struct VecInfo {
49
+ truedst = tcg_temp_new_i64();
78
+ /* Exception priorities can range from -3 to 255; only the unmodifiable
50
+ if (use_key_a) {
79
+ * priority values for RESET, NMI and HardFault can be negative.
51
+ gen_helper_autia(truedst, cpu_env, dst, modifier);
80
+ */
52
+ } else {
81
+ int16_t prio;
53
+ gen_helper_autib(truedst, cpu_env, dst, modifier);
82
+ uint8_t enabled;
54
+ }
83
+ uint8_t pending;
55
+ return truedst;
84
+ uint8_t active;
85
+ uint8_t level; /* exceptions <=15 never set level */
86
+} VecInfo;
87
88
typedef struct NVICState {
89
- GICState gic;
90
+ /*< private >*/
91
+ SysBusDevice parent_obj;
92
+ /*< public >*/
93
+
94
ARMCPU *cpu;
95
96
+ VecInfo vectors[NVIC_MAX_VECTORS];
97
uint32_t prigroup;
98
99
+ /* vectpending and exception_prio are both cached state that can
100
+ * be recalculated from the vectors[] array and the prigroup field.
101
+ */
102
+ unsigned int vectpending; /* highest prio pending enabled exception */
103
+ int exception_prio; /* group prio of the highest prio active exception */
104
+
105
struct {
106
uint32_t control;
107
uint32_t reload;
108
int64_t tick;
109
QEMUTimer *timer;
110
} systick;
111
+
112
MemoryRegion sysregmem;
113
- MemoryRegion gic_iomem_alias;
114
MemoryRegion container;
115
+
116
uint32_t num_irq;
117
+ qemu_irq excpout;
118
qemu_irq sysresetreq;
119
} NVICState;
120
121
#define TYPE_NVIC "armv7m_nvic"
122
-/**
123
- * NVICClass:
124
- * @parent_reset: the parent class' reset handler.
125
- *
126
- * A model of the v7M NVIC and System Controller
127
- */
128
-typedef struct NVICClass {
129
- /*< private >*/
130
- ARMGICClass parent_class;
131
- /*< public >*/
132
- DeviceRealize parent_realize;
133
- void (*parent_reset)(DeviceState *dev);
134
-} NVICClass;
135
-
136
-#define NVIC_CLASS(klass) \
137
- OBJECT_CLASS_CHECK(NVICClass, (klass), TYPE_NVIC)
138
-#define NVIC_GET_CLASS(obj) \
139
- OBJECT_GET_CLASS(NVICClass, (obj), TYPE_NVIC)
140
+
141
#define NVIC(obj) \
142
OBJECT_CHECK(NVICState, (obj), TYPE_NVIC)
143
144
@@ -XXX,XX +XXX,XX @@ static void systick_reset(NVICState *s)
145
timer_del(s->systick.timer);
146
}
147
148
-/* The external routines use the hardware vector numbering, ie. the first
149
- IRQ is #16. The internal GIC routines use #32 as the first IRQ. */
150
+static int nvic_pending_prio(NVICState *s)
151
+{
152
+ /* return the priority of the current pending interrupt,
153
+ * or NVIC_NOEXC_PRIO if no interrupt is pending
154
+ */
155
+ return s->vectpending ? s->vectors[s->vectpending].prio : NVIC_NOEXC_PRIO;
156
+}
56
+}
157
+
57
+
158
+/* Return the value of the ISCR RETTOBASE bit:
58
+static bool trans_BRAZ(DisasContext *s, arg_braz *a)
159
+ * 1 if there is exactly one active exception
160
+ * 0 if there is more than one active exception
161
+ * UNKNOWN if there are no active exceptions (we choose 1,
162
+ * which matches the choice Cortex-M3 is documented as making).
163
+ *
164
+ * NB: some versions of the documentation talk about this
165
+ * counting "active exceptions other than the one shown by IPSR";
166
+ * this is only different in the obscure corner case where guest
167
+ * code has manually deactivated an exception and is about
168
+ * to fail an exception-return integrity check. The definition
169
+ * above is the one from the v8M ARM ARM and is also in line
170
+ * with the behaviour documented for the Cortex-M3.
171
+ */
172
+static bool nvic_rettobase(NVICState *s)
173
+{
59
+{
174
+ int irq, nhand = 0;
60
+ TCGv_i64 dst;
175
+
61
+
176
+ for (irq = ARMV7M_EXCP_RESET; irq < s->num_irq; irq++) {
62
+ if (!dc_isar_feature(aa64_pauth, s)) {
177
+ if (s->vectors[irq].active) {
178
+ nhand++;
179
+ if (nhand == 2) {
180
+ return 0;
181
+ }
182
+ }
183
+ }
184
+
185
+ return 1;
186
+}
187
+
188
+/* Return the value of the ISCR ISRPENDING bit:
189
+ * 1 if an external interrupt is pending
190
+ * 0 if no external interrupt is pending
191
+ */
192
+static bool nvic_isrpending(NVICState *s)
193
+{
194
+ int irq;
195
+
196
+ /* We can shortcut if the highest priority pending interrupt
197
+ * happens to be external or if there is nothing pending.
198
+ */
199
+ if (s->vectpending > NVIC_FIRST_IRQ) {
200
+ return true;
201
+ }
202
+ if (s->vectpending == 0) {
203
+ return false;
63
+ return false;
204
+ }
64
+ }
205
+
65
+
206
+ for (irq = NVIC_FIRST_IRQ; irq < s->num_irq; irq++) {
66
+ dst = auth_branch_target(s, cpu_reg(s, a->rn), tcg_constant_i64(0), !a->m);
207
+ if (s->vectors[irq].pending) {
67
+ gen_a64_set_pc(s, dst);
208
+ return true;
68
+ set_btype_for_br(s, a->rn);
209
+ }
69
+ s->base.is_jmp = DISAS_JUMP;
210
+ }
70
+ return true;
211
+ return false;
212
+}
71
+}
213
+
72
+
214
+/* Return a mask word which clears the subpriority bits from
73
+static bool trans_BLRAZ(DisasContext *s, arg_braz *a)
215
+ * a priority value for an M-profile exception, leaving only
216
+ * the group priority.
217
+ */
218
+static inline uint32_t nvic_gprio_mask(NVICState *s)
219
+{
74
+{
220
+ return ~0U << (s->prigroup + 1);
75
+ TCGv_i64 dst, lr;
76
+
77
+ if (!dc_isar_feature(aa64_pauth, s)) {
78
+ return false;
79
+ }
80
+
81
+ dst = auth_branch_target(s, cpu_reg(s, a->rn), tcg_constant_i64(0), !a->m);
82
+ lr = cpu_reg(s, 30);
83
+ if (dst == lr) {
84
+ TCGv_i64 tmp = tcg_temp_new_i64();
85
+ tcg_gen_mov_i64(tmp, dst);
86
+ dst = tmp;
87
+ }
88
+ gen_pc_plus_diff(s, lr, curr_insn_len(s));
89
+ gen_a64_set_pc(s, dst);
90
+ set_btype_for_blr(s);
91
+ s->base.is_jmp = DISAS_JUMP;
92
+ return true;
221
+}
93
+}
222
+
94
+
223
+/* Recompute vectpending and exception_prio */
95
+static bool trans_RETA(DisasContext *s, arg_reta *a)
224
+static void nvic_recompute_state(NVICState *s)
225
+{
96
+{
226
+ int i;
97
+ TCGv_i64 dst;
227
+ int pend_prio = NVIC_NOEXC_PRIO;
228
+ int active_prio = NVIC_NOEXC_PRIO;
229
+ int pend_irq = 0;
230
+
98
+
231
+ for (i = 1; i < s->num_irq; i++) {
99
+ dst = auth_branch_target(s, cpu_reg(s, 30), cpu_X[31], !a->m);
232
+ VecInfo *vec = &s->vectors[i];
100
+ gen_a64_set_pc(s, dst);
233
+
101
+ s->base.is_jmp = DISAS_JUMP;
234
+ if (vec->enabled && vec->pending && vec->prio < pend_prio) {
102
+ return true;
235
+ pend_prio = vec->prio;
236
+ pend_irq = i;
237
+ }
238
+ if (vec->active && vec->prio < active_prio) {
239
+ active_prio = vec->prio;
240
+ }
241
+ }
242
+
243
+ s->vectpending = pend_irq;
244
+ s->exception_prio = active_prio & nvic_gprio_mask(s);
245
+
246
+ trace_nvic_recompute_state(s->vectpending, s->exception_prio);
247
+}
103
+}
248
+
104
+
249
+/* Return the current execution priority of the CPU
105
/* HINT instruction group, including various allocated HINTs */
250
+ * (equivalent to the pseudocode ExecutionPriority function).
106
static void handle_hint(DisasContext *s, uint32_t insn,
251
+ * This is a value between -2 (NMI priority) and NVIC_NOEXC_PRIO.
107
unsigned int op1, unsigned int op2, unsigned int crm)
252
+ */
108
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
253
+static inline int nvic_exec_prio(NVICState *s)
109
}
254
+{
110
255
+ CPUARMState *env = &s->cpu->env;
111
switch (opc) {
256
+ int running;
112
- case 0: /* BR */
257
+
113
- case 1: /* BLR */
258
+ if (env->daif & PSTATE_F) { /* FAULTMASK */
114
- case 2: /* RET */
259
+ running = -1;
115
- btype_mod = opc;
260
+ } else if (env->daif & PSTATE_I) { /* PRIMASK */
116
- switch (op3) {
261
+ running = 0;
117
- case 0:
262
+ } else if (env->v7m.basepri > 0) {
118
- /* BR, BLR, RET : handled in decodetree */
263
+ running = env->v7m.basepri & nvic_gprio_mask(s);
119
- goto do_unallocated;
264
+ } else {
265
+ running = NVIC_NOEXC_PRIO; /* lower than any possible priority */
266
+ }
267
+ /* consider priority of active handler */
268
+ return MIN(running, s->exception_prio);
269
+}
270
+
271
+/* caller must call nvic_irq_update() after this */
272
+static void set_prio(NVICState *s, unsigned irq, uint8_t prio)
273
+{
274
+ assert(irq > ARMV7M_EXCP_NMI); /* only use for configurable prios */
275
+ assert(irq < s->num_irq);
276
+
277
+ s->vectors[irq].prio = prio;
278
+
279
+ trace_nvic_set_prio(irq, prio);
280
+}
281
+
282
+/* Recompute state and assert irq line accordingly.
283
+ * Must be called after changes to:
284
+ * vec->active, vec->enabled, vec->pending or vec->prio for any vector
285
+ * prigroup
286
+ */
287
+static void nvic_irq_update(NVICState *s)
288
+{
289
+ int lvl;
290
+ int pend_prio;
291
+
292
+ nvic_recompute_state(s);
293
+ pend_prio = nvic_pending_prio(s);
294
+
295
+ /* Raise NVIC output if this IRQ would be taken, except that we
296
+ * ignore the effects of the BASEPRI, FAULTMASK and PRIMASK (which
297
+ * will be checked for in arm_v7m_cpu_exec_interrupt()); changes
298
+ * to those CPU registers don't cause us to recalculate the NVIC
299
+ * pending info.
300
+ */
301
+ lvl = (pend_prio < s->exception_prio);
302
+ trace_nvic_irq_update(s->vectpending, pend_prio, s->exception_prio, lvl);
303
+ qemu_set_irq(s->excpout, lvl);
304
+}
305
+
306
+static void armv7m_nvic_clear_pending(void *opaque, int irq)
307
+{
308
+ NVICState *s = (NVICState *)opaque;
309
+ VecInfo *vec;
310
+
311
+ assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
312
+
313
+ vec = &s->vectors[irq];
314
+ trace_nvic_clear_pending(irq, vec->enabled, vec->prio);
315
+ if (vec->pending) {
316
+ vec->pending = 0;
317
+ nvic_irq_update(s);
318
+ }
319
+}
320
+
321
void armv7m_nvic_set_pending(void *opaque, int irq)
322
{
323
NVICState *s = (NVICState *)opaque;
324
- if (irq >= 16)
325
- irq += 16;
326
- gic_set_pending_private(&s->gic, 0, irq);
327
+ VecInfo *vec;
328
+
329
+ assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
330
+
331
+ vec = &s->vectors[irq];
332
+ trace_nvic_set_pending(irq, vec->enabled, vec->prio);
333
+ if (!vec->pending) {
334
+ vec->pending = 1;
335
+ nvic_irq_update(s);
336
+ }
337
}
338
339
/* Make pending IRQ active. */
340
int armv7m_nvic_acknowledge_irq(void *opaque)
341
{
342
NVICState *s = (NVICState *)opaque;
343
- uint32_t irq;
344
-
120
-
345
- irq = gic_acknowledge_irq(&s->gic, 0, MEMTXATTRS_UNSPECIFIED);
121
- case 2:
346
- if (irq == 1023)
122
- case 3:
347
- hw_error("Interrupt but no vector\n");
123
- if (!dc_isar_feature(aa64_pauth, s)) {
348
- if (irq >= 32)
124
- goto do_unallocated;
349
- irq -= 16;
125
- }
350
- return irq;
126
- if (opc == 2) {
351
+ CPUARMState *env = &s->cpu->env;
127
- /* RETAA, RETAB */
352
+ const int pending = s->vectpending;
128
- if (rn != 0x1f || op4 != 0x1f) {
353
+ const int running = nvic_exec_prio(s);
129
- goto do_unallocated;
354
+ int pendgroupprio;
130
- }
355
+ VecInfo *vec;
131
- rn = 30;
356
+
132
- modifier = cpu_X[31];
357
+ assert(pending > ARMV7M_EXCP_RESET && pending < s->num_irq);
133
- } else {
358
+
134
- /* BRAAZ, BRABZ, BLRAAZ, BLRABZ */
359
+ vec = &s->vectors[pending];
135
- if (op4 != 0x1f) {
360
+
136
- goto do_unallocated;
361
+ assert(vec->enabled);
137
- }
362
+ assert(vec->pending);
138
- modifier = tcg_constant_i64(0);
363
+
139
- }
364
+ pendgroupprio = vec->prio & nvic_gprio_mask(s);
140
- if (s->pauth_active) {
365
+ assert(pendgroupprio < running);
141
- dst = tcg_temp_new_i64();
366
+
142
- if (op3 == 2) {
367
+ trace_nvic_acknowledge_irq(pending, vec->prio);
143
- gen_helper_autia(dst, cpu_env, cpu_reg(s, rn), modifier);
368
+
144
- } else {
369
+ vec->active = 1;
145
- gen_helper_autib(dst, cpu_env, cpu_reg(s, rn), modifier);
370
+ vec->pending = 0;
146
- }
371
+
147
- } else {
372
+ env->v7m.exception = s->vectpending;
148
- dst = cpu_reg(s, rn);
373
+
149
- }
374
+ nvic_irq_update(s);
150
- break;
375
+
151
-
376
+ return env->v7m.exception;
152
- default:
377
}
153
- goto do_unallocated;
378
154
- }
379
void armv7m_nvic_complete_irq(void *opaque, int irq)
155
- /* BLR also needs to load return address */
380
{
156
- if (opc == 1) {
381
NVICState *s = (NVICState *)opaque;
157
- TCGv_i64 lr = cpu_reg(s, 30);
382
- if (irq >= 16)
158
- if (dst == lr) {
383
- irq += 16;
159
- TCGv_i64 tmp = tcg_temp_new_i64();
384
- gic_complete_irq(&s->gic, 0, irq, MEMTXATTRS_UNSPECIFIED);
160
- tcg_gen_mov_i64(tmp, dst);
385
+ VecInfo *vec;
161
- dst = tmp;
386
+
162
- }
387
+ assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
163
- gen_pc_plus_diff(s, lr, curr_insn_len(s));
388
+
164
- }
389
+ vec = &s->vectors[irq];
165
- gen_a64_set_pc(s, dst);
390
+
166
- break;
391
+ trace_nvic_complete_irq(irq);
167
+ case 0:
392
+
168
+ case 1:
393
+ vec->active = 0;
169
+ case 2:
394
+ if (vec->level) {
170
+ /*
395
+ /* Re-pend the exception if it's still held high; only
171
+ * BR, BLR, RET, RETAA, RETAB, BRAAZ, BRABZ, BLRAAZ, BLRABZ:
396
+ * happens for extenal IRQs
172
+ * handled in decodetree
397
+ */
173
+ */
398
+ assert(irq >= NVIC_FIRST_IRQ);
174
+ goto do_unallocated;
399
+ vec->pending = 1;
175
400
+ }
176
case 8: /* BRAA */
401
+
177
case 9: /* BLRAA */
402
+ nvic_irq_update(s);
403
+}
404
+
405
+/* callback when external interrupt line is changed */
406
+static void set_irq_level(void *opaque, int n, int level)
407
+{
408
+ NVICState *s = opaque;
409
+ VecInfo *vec;
410
+
411
+ n += NVIC_FIRST_IRQ;
412
+
413
+ assert(n >= NVIC_FIRST_IRQ && n < s->num_irq);
414
+
415
+ trace_nvic_set_irq_level(n, level);
416
+
417
+ /* The pending status of an external interrupt is
418
+ * latched on rising edge and exception handler return.
419
+ *
420
+ * Pulsing the IRQ will always run the handler
421
+ * once, and the handler will re-run until the
422
+ * level is low when the handler completes.
423
+ */
424
+ vec = &s->vectors[n];
425
+ if (level != vec->level) {
426
+ vec->level = level;
427
+ if (level) {
428
+ armv7m_nvic_set_pending(s, n);
429
+ }
430
+ }
431
}
432
433
static uint32_t nvic_readl(NVICState *s, uint32_t offset)
434
{
435
ARMCPU *cpu = s->cpu;
436
uint32_t val;
437
- int irq;
438
439
switch (offset) {
440
case 4: /* Interrupt Control Type. */
441
- return (s->num_irq / 32) - 1;
442
+ return ((s->num_irq - NVIC_FIRST_IRQ) / 32) - 1;
443
case 0x10: /* SysTick Control and Status. */
444
val = s->systick.control;
445
s->systick.control &= ~SYSTICK_COUNTFLAG;
446
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset)
447
case 0xd04: /* Interrupt Control State. */
448
/* VECTACTIVE */
449
val = cpu->env.v7m.exception;
450
- if (val == 1023) {
451
- val = 0;
452
- } else if (val >= 32) {
453
- val -= 16;
454
- }
455
/* VECTPENDING */
456
- if (s->gic.current_pending[0] != 1023)
457
- val |= (s->gic.current_pending[0] << 12);
458
- /* ISRPENDING and RETTOBASE */
459
- for (irq = 32; irq < s->num_irq; irq++) {
460
- if (s->gic.irq_state[irq].pending) {
461
- val |= (1 << 22);
462
- break;
463
- }
464
- if (irq != cpu->env.v7m.exception && s->gic.irq_state[irq].active) {
465
- val |= (1 << 11);
466
- }
467
+ val |= (s->vectpending & 0xff) << 12;
468
+ /* ISRPENDING - set if any external IRQ is pending */
469
+ if (nvic_isrpending(s)) {
470
+ val |= (1 << 22);
471
+ }
472
+ /* RETTOBASE - set if only one handler is active */
473
+ if (nvic_rettobase(s)) {
474
+ val |= (1 << 11);
475
}
476
/* PENDSTSET */
477
- if (s->gic.irq_state[ARMV7M_EXCP_SYSTICK].pending)
478
+ if (s->vectors[ARMV7M_EXCP_SYSTICK].pending) {
479
val |= (1 << 26);
480
+ }
481
/* PENDSVSET */
482
- if (s->gic.irq_state[ARMV7M_EXCP_PENDSV].pending)
483
+ if (s->vectors[ARMV7M_EXCP_PENDSV].pending) {
484
val |= (1 << 28);
485
+ }
486
/* NMIPENDSET */
487
- if (s->gic.irq_state[ARMV7M_EXCP_NMI].pending)
488
+ if (s->vectors[ARMV7M_EXCP_NMI].pending) {
489
val |= (1 << 31);
490
+ }
491
+ /* ISRPREEMPT not implemented */
492
return val;
493
case 0xd08: /* Vector Table Offset. */
494
return cpu->env.v7m.vecbase;
495
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset)
496
return cpu->env.v7m.ccr;
497
case 0xd24: /* System Handler Status. */
498
val = 0;
499
- if (s->gic.irq_state[ARMV7M_EXCP_MEM].active) val |= (1 << 0);
500
- if (s->gic.irq_state[ARMV7M_EXCP_BUS].active) val |= (1 << 1);
501
- if (s->gic.irq_state[ARMV7M_EXCP_USAGE].active) val |= (1 << 3);
502
- if (s->gic.irq_state[ARMV7M_EXCP_SVC].active) val |= (1 << 7);
503
- if (s->gic.irq_state[ARMV7M_EXCP_DEBUG].active) val |= (1 << 8);
504
- if (s->gic.irq_state[ARMV7M_EXCP_PENDSV].active) val |= (1 << 10);
505
- if (s->gic.irq_state[ARMV7M_EXCP_SYSTICK].active) val |= (1 << 11);
506
- if (s->gic.irq_state[ARMV7M_EXCP_USAGE].pending) val |= (1 << 12);
507
- if (s->gic.irq_state[ARMV7M_EXCP_MEM].pending) val |= (1 << 13);
508
- if (s->gic.irq_state[ARMV7M_EXCP_BUS].pending) val |= (1 << 14);
509
- if (s->gic.irq_state[ARMV7M_EXCP_SVC].pending) val |= (1 << 15);
510
- if (s->gic.irq_state[ARMV7M_EXCP_MEM].enabled) val |= (1 << 16);
511
- if (s->gic.irq_state[ARMV7M_EXCP_BUS].enabled) val |= (1 << 17);
512
- if (s->gic.irq_state[ARMV7M_EXCP_USAGE].enabled) val |= (1 << 18);
513
+ if (s->vectors[ARMV7M_EXCP_MEM].active) {
514
+ val |= (1 << 0);
515
+ }
516
+ if (s->vectors[ARMV7M_EXCP_BUS].active) {
517
+ val |= (1 << 1);
518
+ }
519
+ if (s->vectors[ARMV7M_EXCP_USAGE].active) {
520
+ val |= (1 << 3);
521
+ }
522
+ if (s->vectors[ARMV7M_EXCP_SVC].active) {
523
+ val |= (1 << 7);
524
+ }
525
+ if (s->vectors[ARMV7M_EXCP_DEBUG].active) {
526
+ val |= (1 << 8);
527
+ }
528
+ if (s->vectors[ARMV7M_EXCP_PENDSV].active) {
529
+ val |= (1 << 10);
530
+ }
531
+ if (s->vectors[ARMV7M_EXCP_SYSTICK].active) {
532
+ val |= (1 << 11);
533
+ }
534
+ if (s->vectors[ARMV7M_EXCP_USAGE].pending) {
535
+ val |= (1 << 12);
536
+ }
537
+ if (s->vectors[ARMV7M_EXCP_MEM].pending) {
538
+ val |= (1 << 13);
539
+ }
540
+ if (s->vectors[ARMV7M_EXCP_BUS].pending) {
541
+ val |= (1 << 14);
542
+ }
543
+ if (s->vectors[ARMV7M_EXCP_SVC].pending) {
544
+ val |= (1 << 15);
545
+ }
546
+ if (s->vectors[ARMV7M_EXCP_MEM].enabled) {
547
+ val |= (1 << 16);
548
+ }
549
+ if (s->vectors[ARMV7M_EXCP_BUS].enabled) {
550
+ val |= (1 << 17);
551
+ }
552
+ if (s->vectors[ARMV7M_EXCP_USAGE].enabled) {
553
+ val |= (1 << 18);
554
+ }
555
return val;
556
case 0xd28: /* Configurable Fault Status. */
557
return cpu->env.v7m.cfsr;
558
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
559
if (value & (1 << 28)) {
560
armv7m_nvic_set_pending(s, ARMV7M_EXCP_PENDSV);
561
} else if (value & (1 << 27)) {
562
- s->gic.irq_state[ARMV7M_EXCP_PENDSV].pending = 0;
563
- gic_update(&s->gic);
564
+ armv7m_nvic_clear_pending(s, ARMV7M_EXCP_PENDSV);
565
}
566
if (value & (1 << 26)) {
567
armv7m_nvic_set_pending(s, ARMV7M_EXCP_SYSTICK);
568
} else if (value & (1 << 25)) {
569
- s->gic.irq_state[ARMV7M_EXCP_SYSTICK].pending = 0;
570
- gic_update(&s->gic);
571
+ armv7m_nvic_clear_pending(s, ARMV7M_EXCP_SYSTICK);
572
}
573
break;
574
case 0xd08: /* Vector Table Offset. */
575
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
576
qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n");
577
}
578
s->prigroup = extract32(value, 8, 3);
579
+ nvic_irq_update(s);
580
}
581
break;
582
case 0xd10: /* System Control. */
583
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
584
case 0xd24: /* System Handler Control. */
585
/* TODO: Real hardware allows you to set/clear the active bits
586
under some circumstances. We don't implement this. */
587
- s->gic.irq_state[ARMV7M_EXCP_MEM].enabled = (value & (1 << 16)) != 0;
588
- s->gic.irq_state[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0;
589
- s->gic.irq_state[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0;
590
+ s->vectors[ARMV7M_EXCP_MEM].enabled = (value & (1 << 16)) != 0;
591
+ s->vectors[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0;
592
+ s->vectors[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0;
593
+ nvic_irq_update(s);
594
break;
595
case 0xd28: /* Configurable Fault Status. */
596
cpu->env.v7m.cfsr &= ~value; /* W1C */
597
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
598
"NVIC: Aux fault status registers unimplemented\n");
599
break;
600
case 0xf00: /* Software Triggered Interrupt Register */
601
+ {
602
/* user mode can only write to STIR if CCR.USERSETMPEND permits it */
603
- if ((value & 0x1ff) < s->num_irq &&
604
+ int excnum = (value & 0x1ff) + NVIC_FIRST_IRQ;
605
+ if (excnum < s->num_irq &&
606
(arm_current_el(&cpu->env) ||
607
(cpu->env.v7m.ccr & R_V7M_CCR_USERSETMPEND_MASK))) {
608
- gic_set_pending_private(&s->gic, 0, value & 0x1ff);
609
+ armv7m_nvic_set_pending(s, excnum);
610
}
611
break;
612
+ }
613
default:
614
qemu_log_mask(LOG_GUEST_ERROR,
615
"NVIC: Bad write offset 0x%x\n", offset);
616
@@ -XXX,XX +XXX,XX @@ static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
617
{
618
NVICState *s = (NVICState *)opaque;
619
uint32_t offset = addr;
620
- int i;
621
+ unsigned i, startvec, end;
622
uint32_t val;
623
624
switch (offset) {
625
+ /* reads of set and clear both return the status */
626
+ case 0x100 ... 0x13f: /* NVIC Set enable */
627
+ offset += 0x80;
628
+ /* fall through */
629
+ case 0x180 ... 0x1bf: /* NVIC Clear enable */
630
+ val = 0;
631
+ startvec = offset - 0x180 + NVIC_FIRST_IRQ; /* vector # */
632
+
633
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
634
+ if (s->vectors[startvec + i].enabled) {
635
+ val |= (1 << i);
636
+ }
637
+ }
638
+ break;
639
+ case 0x200 ... 0x23f: /* NVIC Set pend */
640
+ offset += 0x80;
641
+ /* fall through */
642
+ case 0x280 ... 0x2bf: /* NVIC Clear pend */
643
+ val = 0;
644
+ startvec = offset - 0x280 + NVIC_FIRST_IRQ; /* vector # */
645
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
646
+ if (s->vectors[startvec + i].pending) {
647
+ val |= (1 << i);
648
+ }
649
+ }
650
+ break;
651
+ case 0x300 ... 0x33f: /* NVIC Active */
652
+ val = 0;
653
+ startvec = offset - 0x300 + NVIC_FIRST_IRQ; /* vector # */
654
+
655
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
656
+ if (s->vectors[startvec + i].active) {
657
+ val |= (1 << i);
658
+ }
659
+ }
660
+ break;
661
+ case 0x400 ... 0x5ef: /* NVIC Priority */
662
+ val = 0;
663
+ startvec = offset - 0x400 + NVIC_FIRST_IRQ; /* vector # */
664
+
665
+ for (i = 0; i < size && startvec + i < s->num_irq; i++) {
666
+ val |= s->vectors[startvec + i].prio << (8 * i);
667
+ }
668
+ break;
669
case 0xd18 ... 0xd23: /* System Handler Priority. */
670
val = 0;
671
for (i = 0; i < size; i++) {
672
- val |= s->gic.priority1[(offset - 0xd14) + i][0] << (i * 8);
673
+ val |= s->vectors[(offset - 0xd14) + i].prio << (i * 8);
674
}
675
- return val;
676
+ break;
677
case 0xfe0 ... 0xfff: /* ID. */
678
if (offset & 3) {
679
- return 0;
680
+ val = 0;
681
+ } else {
682
+ val = nvic_id[(offset - 0xfe0) >> 2];
683
+ }
684
+ break;
685
+ default:
686
+ if (size == 4) {
687
+ val = nvic_readl(s, offset);
688
+ } else {
689
+ qemu_log_mask(LOG_GUEST_ERROR,
690
+ "NVIC: Bad read of size %d at offset 0x%x\n",
691
+ size, offset);
692
+ val = 0;
693
}
694
- return nvic_id[(offset - 0xfe0) >> 2];
695
- }
696
- if (size == 4) {
697
- return nvic_readl(s, offset);
698
}
699
- qemu_log_mask(LOG_GUEST_ERROR,
700
- "NVIC: Bad read of size %d at offset 0x%x\n", size, offset);
701
- return 0;
702
+
703
+ trace_nvic_sysreg_read(addr, val, size);
704
+ return val;
705
}
706
707
static void nvic_sysreg_write(void *opaque, hwaddr addr,
708
@@ -XXX,XX +XXX,XX @@ static void nvic_sysreg_write(void *opaque, hwaddr addr,
709
{
710
NVICState *s = (NVICState *)opaque;
711
uint32_t offset = addr;
712
- int i;
713
+ unsigned i, startvec, end;
714
+ unsigned setval = 0;
715
+
716
+ trace_nvic_sysreg_write(addr, value, size);
717
718
switch (offset) {
719
+ case 0x100 ... 0x13f: /* NVIC Set enable */
720
+ offset += 0x80;
721
+ setval = 1;
722
+ /* fall through */
723
+ case 0x180 ... 0x1bf: /* NVIC Clear enable */
724
+ startvec = 8 * (offset - 0x180) + NVIC_FIRST_IRQ;
725
+
726
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
727
+ if (value & (1 << i)) {
728
+ s->vectors[startvec + i].enabled = setval;
729
+ }
730
+ }
731
+ nvic_irq_update(s);
732
+ return;
733
+ case 0x200 ... 0x23f: /* NVIC Set pend */
734
+ /* the special logic in armv7m_nvic_set_pending()
735
+ * is not needed since IRQs are never escalated
736
+ */
737
+ offset += 0x80;
738
+ setval = 1;
739
+ /* fall through */
740
+ case 0x280 ... 0x2bf: /* NVIC Clear pend */
741
+ startvec = 8 * (offset - 0x280) + NVIC_FIRST_IRQ; /* vector # */
742
+
743
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
744
+ if (value & (1 << i)) {
745
+ s->vectors[startvec + i].pending = setval;
746
+ }
747
+ }
748
+ nvic_irq_update(s);
749
+ return;
750
+ case 0x300 ... 0x33f: /* NVIC Active */
751
+ return; /* R/O */
752
+ case 0x400 ... 0x5ef: /* NVIC Priority */
753
+ startvec = 8 * (offset - 0x400) + NVIC_FIRST_IRQ; /* vector # */
754
+
755
+ for (i = 0; i < size && startvec + i < s->num_irq; i++) {
756
+ set_prio(s, startvec + i, (value >> (i * 8)) & 0xff);
757
+ }
758
+ nvic_irq_update(s);
759
+ return;
760
case 0xd18 ... 0xd23: /* System Handler Priority. */
761
for (i = 0; i < size; i++) {
762
- s->gic.priority1[(offset - 0xd14) + i][0] =
763
- (value >> (i * 8)) & 0xff;
764
+ unsigned hdlidx = (offset - 0xd14) + i;
765
+ set_prio(s, hdlidx, (value >> (i * 8)) & 0xff);
766
}
767
- gic_update(&s->gic);
768
+ nvic_irq_update(s);
769
return;
770
}
771
if (size == 4) {
772
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_sysreg_ops = {
773
.endianness = DEVICE_NATIVE_ENDIAN,
774
};
775
776
+static int nvic_post_load(void *opaque, int version_id)
777
+{
778
+ NVICState *s = opaque;
779
+ unsigned i;
780
+
781
+ /* Check for out of range priority settings */
782
+ if (s->vectors[ARMV7M_EXCP_RESET].prio != -3 ||
783
+ s->vectors[ARMV7M_EXCP_NMI].prio != -2 ||
784
+ s->vectors[ARMV7M_EXCP_HARD].prio != -1) {
785
+ return 1;
786
+ }
787
+ for (i = ARMV7M_EXCP_MEM; i < s->num_irq; i++) {
788
+ if (s->vectors[i].prio & ~0xff) {
789
+ return 1;
790
+ }
791
+ }
792
+
793
+ nvic_recompute_state(s);
794
+
795
+ return 0;
796
+}
797
+
798
+static const VMStateDescription vmstate_VecInfo = {
799
+ .name = "armv7m_nvic_info",
800
+ .version_id = 1,
801
+ .minimum_version_id = 1,
802
+ .fields = (VMStateField[]) {
803
+ VMSTATE_INT16(prio, VecInfo),
804
+ VMSTATE_UINT8(enabled, VecInfo),
805
+ VMSTATE_UINT8(pending, VecInfo),
806
+ VMSTATE_UINT8(active, VecInfo),
807
+ VMSTATE_UINT8(level, VecInfo),
808
+ VMSTATE_END_OF_LIST()
809
+ }
810
+};
811
+
812
static const VMStateDescription vmstate_nvic = {
813
.name = "armv7m_nvic",
814
- .version_id = 2,
815
- .minimum_version_id = 2,
816
+ .version_id = 3,
817
+ .minimum_version_id = 3,
818
+ .post_load = &nvic_post_load,
819
.fields = (VMStateField[]) {
820
+ VMSTATE_STRUCT_ARRAY(vectors, NVICState, NVIC_MAX_VECTORS, 1,
821
+ vmstate_VecInfo, VecInfo),
822
VMSTATE_UINT32(systick.control, NVICState),
823
VMSTATE_UINT32(systick.reload, NVICState),
824
VMSTATE_INT64(systick.tick, NVICState),
825
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_nvic = {
826
}
827
};
828
829
+static Property props_nvic[] = {
830
+ /* Number of external IRQ lines (so excluding the 16 internal exceptions) */
831
+ DEFINE_PROP_UINT32("num-irq", NVICState, num_irq, 64),
832
+ DEFINE_PROP_END_OF_LIST()
833
+};
834
+
835
static void armv7m_nvic_reset(DeviceState *dev)
836
{
837
NVICState *s = NVIC(dev);
838
- NVICClass *nc = NVIC_GET_CLASS(s);
839
- nc->parent_reset(dev);
840
- /* Common GIC reset resets to disabled; the NVIC doesn't have
841
- * per-CPU interfaces so mark our non-existent CPU interface
842
- * as enabled by default, and with a priority mask which allows
843
- * all interrupts through.
844
+
845
+ s->vectors[ARMV7M_EXCP_NMI].enabled = 1;
846
+ s->vectors[ARMV7M_EXCP_HARD].enabled = 1;
847
+ /* MEM, BUS, and USAGE are enabled through
848
+ * the System Handler Control register
849
*/
850
- s->gic.cpu_ctlr[0] = GICC_CTLR_EN_GRP0;
851
- s->gic.priority_mask[0] = 0x100;
852
- /* The NVIC as a whole is always enabled. */
853
- s->gic.ctlr = 1;
854
+ s->vectors[ARMV7M_EXCP_SVC].enabled = 1;
855
+ s->vectors[ARMV7M_EXCP_DEBUG].enabled = 1;
856
+ s->vectors[ARMV7M_EXCP_PENDSV].enabled = 1;
857
+ s->vectors[ARMV7M_EXCP_SYSTICK].enabled = 1;
858
+
859
+ s->vectors[ARMV7M_EXCP_RESET].prio = -3;
860
+ s->vectors[ARMV7M_EXCP_NMI].prio = -2;
861
+ s->vectors[ARMV7M_EXCP_HARD].prio = -1;
862
+
863
+ /* Strictly speaking the reset handler should be enabled.
864
+ * However, we don't simulate soft resets through the NVIC,
865
+ * and the reset vector should never be pended.
866
+ * So we leave it disabled to catch logic errors.
867
+ */
868
+
869
+ s->exception_prio = NVIC_NOEXC_PRIO;
870
+ s->vectpending = 0;
871
+
872
systick_reset(s);
873
}
874
875
static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
876
{
877
NVICState *s = NVIC(dev);
878
- NVICClass *nc = NVIC_GET_CLASS(s);
879
- Error *local_err = NULL;
880
881
s->cpu = ARM_CPU(qemu_get_cpu(0));
882
assert(s->cpu);
883
- /* The NVIC always has only one CPU */
884
- s->gic.num_cpu = 1;
885
- /* Tell the common code we're an NVIC */
886
- s->gic.revision = 0xffffffff;
887
- s->num_irq = s->gic.num_irq;
888
- nc->parent_realize(dev, &local_err);
889
- if (local_err) {
890
- error_propagate(errp, local_err);
891
+
892
+ if (s->num_irq > NVIC_MAX_IRQ) {
893
+ error_setg(errp, "num-irq %d exceeds NVIC maximum", s->num_irq);
894
return;
895
}
896
- gic_init_irqs_and_distributor(&s->gic);
897
- /* The NVIC and system controller register area looks like this:
898
- * 0..0xff : system control registers, including systick
899
- * 0x100..0xcff : GIC-like registers
900
- * 0xd00..0xfff : system control registers
901
- * We use overlaying to put the GIC like registers
902
- * over the top of the system control register region.
903
+
904
+ qdev_init_gpio_in(dev, set_irq_level, s->num_irq);
905
+
906
+ /* include space for internal exception vectors */
907
+ s->num_irq += NVIC_FIRST_IRQ;
908
+
909
+ /* The NVIC and System Control Space (SCS) starts at 0xe000e000
910
+ * and looks like this:
911
+ * 0x004 - ICTR
912
+ * 0x010 - 0x1c - systick
913
+ * 0x100..0x7ec - NVIC
914
+ * 0x7f0..0xcff - Reserved
915
+ * 0xd00..0xd3c - SCS registers
916
+ * 0xd40..0xeff - Reserved or Not implemented
917
+ * 0xf00 - STIR
918
+ *
919
+ * At the moment there is only one thing in the container region,
920
+ * but we leave it in place to allow us to pull systick out into
921
+ * its own device object later.
922
*/
923
memory_region_init(&s->container, OBJECT(s), "nvic", 0x1000);
924
/* The system register region goes at the bottom of the priority
925
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
926
memory_region_init_io(&s->sysregmem, OBJECT(s), &nvic_sysreg_ops, s,
927
"nvic_sysregs", 0x1000);
928
memory_region_add_subregion(&s->container, 0, &s->sysregmem);
929
- /* Alias the GIC region so we can get only the section of it
930
- * we need, and layer it on top of the system register region.
931
- */
932
- memory_region_init_alias(&s->gic_iomem_alias, OBJECT(s),
933
- "nvic-gic", &s->gic.iomem,
934
- 0x100, 0xc00);
935
- memory_region_add_subregion_overlap(&s->container, 0x100,
936
- &s->gic_iomem_alias, 1);
937
+
938
/* Map the whole thing into system memory at the location required
939
* by the v7M architecture.
940
*/
941
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_instance_init(Object *obj)
942
* any user-specified property setting, so just modify the
943
* value in the GICState struct.
944
*/
945
- GICState *s = ARM_GIC_COMMON(obj);
946
DeviceState *dev = DEVICE(obj);
947
NVICState *nvic = NVIC(obj);
948
- /* The ARM v7m may have anything from 0 to 496 external interrupt
949
- * IRQ lines. We default to 64. Other boards may differ and should
950
- * set the num-irq property appropriately.
951
- */
952
- s->num_irq = 64;
953
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
954
+
955
+ sysbus_init_irq(sbd, &nvic->excpout);
956
qdev_init_gpio_out_named(dev, &nvic->sysresetreq, "SYSRESETREQ", 1);
957
}
958
959
static void armv7m_nvic_class_init(ObjectClass *klass, void *data)
960
{
961
- NVICClass *nc = NVIC_CLASS(klass);
962
DeviceClass *dc = DEVICE_CLASS(klass);
963
964
- nc->parent_reset = dc->reset;
965
- nc->parent_realize = dc->realize;
966
dc->vmsd = &vmstate_nvic;
967
+ dc->props = props_nvic;
968
dc->reset = armv7m_nvic_reset;
969
dc->realize = armv7m_nvic_realize;
970
}
971
972
static const TypeInfo armv7m_nvic_info = {
973
.name = TYPE_NVIC,
974
- .parent = TYPE_ARM_GIC_COMMON,
975
+ .parent = TYPE_SYS_BUS_DEVICE,
976
.instance_init = armv7m_nvic_instance_init,
977
.instance_size = sizeof(NVICState),
978
.class_init = armv7m_nvic_class_init,
979
- .class_size = sizeof(NVICClass),
980
+ .class_size = sizeof(SysBusDeviceClass),
981
};
982
983
static void armv7m_nvic_register_types(void)
984
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
985
index XXXXXXX..XXXXXXX 100644
986
--- a/hw/intc/trace-events
987
+++ b/hw/intc/trace-events
988
@@ -XXX,XX +XXX,XX @@ gicv3_redist_write(uint32_t cpu, uint64_t offset, uint64_t data, unsigned size,
989
gicv3_redist_badwrite(uint32_t cpu, uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 redistributor %x write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d: error"
990
gicv3_redist_set_irq(uint32_t cpu, int irq, int level) "GICv3 redistributor %x interrupt %d level changed to %d"
991
gicv3_redist_send_sgi(uint32_t cpu, int irq) "GICv3 redistributor %x pending SGI %d"
992
+
993
+# hw/intc/armv7m_nvic.c
994
+nvic_recompute_state(int vectpending, int exception_prio) "NVIC state recomputed: vectpending %d exception_prio %d"
995
+nvic_set_prio(int irq, uint8_t prio) "NVIC set irq %d priority %d"
996
+nvic_irq_update(int vectpending, int pendprio, int exception_prio, int level) "NVIC vectpending %d pending prio %d exception_prio %d: setting irq line to %d"
997
+nvic_escalate_prio(int irq, int irqprio, int runprio) "NVIC escalating irq %d to HardFault: insufficient priority %d >= %d"
998
+nvic_escalate_disabled(int irq) "NVIC escalating irq %d to HardFault: disabled"
999
+nvic_set_pending(int irq, int en, int prio) "NVIC set pending irq %d (enabled: %d priority %d)"
1000
+nvic_clear_pending(int irq, int en, int prio) "NVIC clear pending irq %d (enabled: %d priority %d)"
1001
+nvic_set_pending_level(int irq) "NVIC set pending: irq %d higher prio than vectpending: setting irq line to 1"
1002
+nvic_acknowledge_irq(int irq, int prio) "NVIC acknowledge IRQ: %d now active (prio %d)"
1003
+nvic_complete_irq(int irq) "NVIC complete IRQ %d"
1004
+nvic_set_irq_level(int irq, int level) "NVIC external irq %d level set to %d"
1005
+nvic_sysreg_read(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
1006
+nvic_sysreg_write(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
1007
--
178
--
1008
2.7.4
179
2.34.1
1009
1010
diff view generated by jsdifflib
1
Extract the code from the tail end of arm_v7m_do_interrupt() which
1
Convert the last four BR-with-pointer-auth insns to decodetree.
2
enters the exception handler into a pair of utility functions
2
The remaining cases in the outer switch in disas_uncond_b_reg()
3
v7m_exception_taken() and v7m_push_stack(), which correspond roughly
3
all return early rather than leaving the case statement, so we
4
to the pseudocode PushStack() and ExceptionTaken().
4
can delete the now-unused code at the end of that function.
5
6
This also requires us to move the arm_v7m_load_vector() utility
7
routine up so we can call it.
8
9
Handling illegal exception returns has some cases where we want to
10
take a UsageFault either on an existing stack frame or with a new
11
stack frame but with a specific LR value, so we want to be able to
12
call these without having to go via arm_v7m_cpu_do_interrupt().
13
5
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230512144106.3608981-20-peter.maydell@linaro.org
16
---
9
---
17
target/arm/helper.c | 118 ++++++++++++++++++++++++++++++----------------------
10
target/arm/tcg/a64.decode | 4 ++
18
1 file changed, 68 insertions(+), 50 deletions(-)
11
target/arm/tcg/translate-a64.c | 97 ++++++++++++++--------------------
12
2 files changed, 43 insertions(+), 58 deletions(-)
19
13
20
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
21
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/helper.c
16
--- a/target/arm/tcg/a64.decode
23
+++ b/target/arm/helper.c
17
+++ b/target/arm/tcg/a64.decode
24
@@ -XXX,XX +XXX,XX @@ static void switch_v7m_sp(CPUARMState *env, bool new_spsel)
18
@@ -XXX,XX +XXX,XX @@ BLRAZ 1101011 0001 11111 00001 m:1 rn:5 11111 &braz # BLRAAZ, BLRABZ
25
}
19
20
&reta m
21
RETA 1101011 0010 11111 00001 m:1 11111 11111 &reta # RETAA, RETAB
22
+
23
+&bra rn rm m
24
+BRA 1101011 1000 11111 00001 m:1 rn:5 rm:5 &bra # BRAA, BRAB
25
+BLRA 1101011 1001 11111 00001 m:1 rn:5 rm:5 &bra # BLRAA, BLRAB
26
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/tcg/translate-a64.c
29
+++ b/target/arm/tcg/translate-a64.c
30
@@ -XXX,XX +XXX,XX @@ static bool trans_RETA(DisasContext *s, arg_reta *a)
31
return true;
26
}
32
}
27
33
28
+static uint32_t arm_v7m_load_vector(ARMCPU *cpu)
34
+static bool trans_BRA(DisasContext *s, arg_bra *a)
29
+{
35
+{
30
+ CPUState *cs = CPU(cpu);
36
+ TCGv_i64 dst;
31
+ CPUARMState *env = &cpu->env;
32
+ MemTxResult result;
33
+ hwaddr vec = env->v7m.vecbase + env->v7m.exception * 4;
34
+ uint32_t addr;
35
+
37
+
36
+ addr = address_space_ldl(cs->as, vec,
38
+ if (!dc_isar_feature(aa64_pauth, s)) {
37
+ MEMTXATTRS_UNSPECIFIED, &result);
39
+ return false;
38
+ if (result != MEMTX_OK) {
39
+ /* Architecturally this should cause a HardFault setting HSFR.VECTTBL,
40
+ * which would then be immediately followed by our failing to load
41
+ * the entry vector for that HardFault, which is a Lockup case.
42
+ * Since we don't model Lockup, we just report this guest error
43
+ * via cpu_abort().
44
+ */
45
+ cpu_abort(cs, "Failed to read from exception vector table "
46
+ "entry %08x\n", (unsigned)vec);
47
+ }
40
+ }
48
+ return addr;
41
+ dst = auth_branch_target(s, cpu_reg(s,a->rn), cpu_reg_sp(s, a->rm), !a->m);
42
+ gen_a64_set_pc(s, dst);
43
+ set_btype_for_br(s, a->rn);
44
+ s->base.is_jmp = DISAS_JUMP;
45
+ return true;
49
+}
46
+}
50
+
47
+
51
+static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr)
48
+static bool trans_BLRA(DisasContext *s, arg_bra *a)
52
+{
49
+{
53
+ /* Do the "take the exception" parts of exception entry,
50
+ TCGv_i64 dst, lr;
54
+ * but not the pushing of state to the stack. This is
55
+ * similar to the pseudocode ExceptionTaken() function.
56
+ */
57
+ CPUARMState *env = &cpu->env;
58
+ uint32_t addr;
59
+
51
+
60
+ armv7m_nvic_acknowledge_irq(env->nvic);
52
+ if (!dc_isar_feature(aa64_pauth, s)) {
61
+ switch_v7m_sp(env, 0);
53
+ return false;
62
+ /* Clear IT bits */
54
+ }
63
+ env->condexec_bits = 0;
55
+ dst = auth_branch_target(s, cpu_reg(s, a->rn), cpu_reg_sp(s, a->rm), !a->m);
64
+ env->regs[14] = lr;
56
+ lr = cpu_reg(s, 30);
65
+ addr = arm_v7m_load_vector(cpu);
57
+ if (dst == lr) {
66
+ env->regs[15] = addr & 0xfffffffe;
58
+ TCGv_i64 tmp = tcg_temp_new_i64();
67
+ env->thumb = addr & 1;
59
+ tcg_gen_mov_i64(tmp, dst);
60
+ dst = tmp;
61
+ }
62
+ gen_pc_plus_diff(s, lr, curr_insn_len(s));
63
+ gen_a64_set_pc(s, dst);
64
+ set_btype_for_blr(s);
65
+ s->base.is_jmp = DISAS_JUMP;
66
+ return true;
68
+}
67
+}
69
+
68
+
70
+static void v7m_push_stack(ARMCPU *cpu)
69
/* HINT instruction group, including various allocated HINTs */
71
+{
70
static void handle_hint(DisasContext *s, uint32_t insn,
72
+ /* Do the "set up stack frame" part of exception entry,
71
unsigned int op1, unsigned int op2, unsigned int crm)
73
+ * similar to pseudocode PushStack().
72
@@ -XXX,XX +XXX,XX @@ static void disas_exc(DisasContext *s, uint32_t insn)
74
+ */
73
static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
75
+ CPUARMState *env = &cpu->env;
76
+ uint32_t xpsr = xpsr_read(env);
77
+
78
+ /* Align stack pointer if the guest wants that */
79
+ if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) {
80
+ env->regs[13] -= 4;
81
+ xpsr |= 0x200;
82
+ }
83
+ /* Switch to the handler mode. */
84
+ v7m_push(env, xpsr);
85
+ v7m_push(env, env->regs[15]);
86
+ v7m_push(env, env->regs[14]);
87
+ v7m_push(env, env->regs[12]);
88
+ v7m_push(env, env->regs[3]);
89
+ v7m_push(env, env->regs[2]);
90
+ v7m_push(env, env->regs[1]);
91
+ v7m_push(env, env->regs[0]);
92
+}
93
+
94
static void do_v7m_exception_exit(CPUARMState *env)
95
{
74
{
96
uint32_t type;
75
unsigned int opc, op2, op3, rn, op4;
97
@@ -XXX,XX +XXX,XX @@ static void arm_log_exception(int idx)
76
- unsigned btype_mod = 2; /* 0: BR, 1: BLR, 2: other */
77
TCGv_i64 dst;
78
TCGv_i64 modifier;
79
80
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
81
case 0:
82
case 1:
83
case 2:
84
+ case 8:
85
+ case 9:
86
/*
87
- * BR, BLR, RET, RETAA, RETAB, BRAAZ, BRABZ, BLRAAZ, BLRABZ:
88
- * handled in decodetree
89
+ * BR, BLR, RET, RETAA, RETAB, BRAAZ, BRABZ, BLRAAZ, BLRABZ,
90
+ * BRAA, BLRAA: handled in decodetree
91
*/
92
goto do_unallocated;
93
94
- case 8: /* BRAA */
95
- case 9: /* BLRAA */
96
- if (!dc_isar_feature(aa64_pauth, s)) {
97
- goto do_unallocated;
98
- }
99
- if ((op3 & ~1) != 2) {
100
- goto do_unallocated;
101
- }
102
- btype_mod = opc & 1;
103
- if (s->pauth_active) {
104
- dst = tcg_temp_new_i64();
105
- modifier = cpu_reg_sp(s, op4);
106
- if (op3 == 2) {
107
- gen_helper_autia(dst, cpu_env, cpu_reg(s, rn), modifier);
108
- } else {
109
- gen_helper_autib(dst, cpu_env, cpu_reg(s, rn), modifier);
110
- }
111
- } else {
112
- dst = cpu_reg(s, rn);
113
- }
114
- /* BLRAA also needs to load return address */
115
- if (opc == 9) {
116
- TCGv_i64 lr = cpu_reg(s, 30);
117
- if (dst == lr) {
118
- TCGv_i64 tmp = tcg_temp_new_i64();
119
- tcg_gen_mov_i64(tmp, dst);
120
- dst = tmp;
121
- }
122
- gen_pc_plus_diff(s, lr, curr_insn_len(s));
123
- }
124
- gen_a64_set_pc(s, dst);
125
- break;
126
-
127
case 4: /* ERET */
128
if (s->current_el == 0) {
129
goto do_unallocated;
130
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
131
unallocated_encoding(s);
132
return;
98
}
133
}
134
-
135
- switch (btype_mod) {
136
- case 0: /* BR */
137
- if (dc_isar_feature(aa64_bti, s)) {
138
- /* BR to {x16,x17} or !guard -> 1, else 3. */
139
- set_btype(s, rn == 16 || rn == 17 || !s->guarded_page ? 1 : 3);
140
- }
141
- break;
142
-
143
- case 1: /* BLR */
144
- if (dc_isar_feature(aa64_bti, s)) {
145
- /* BLR sets BTYPE to 2, regardless of source guarded page. */
146
- set_btype(s, 2);
147
- }
148
- break;
149
-
150
- default: /* RET or none of the above. */
151
- /* BTYPE will be set to 0 by normal end-of-insn processing. */
152
- break;
153
- }
154
-
155
- s->base.is_jmp = DISAS_JUMP;
99
}
156
}
100
157
101
-static uint32_t arm_v7m_load_vector(ARMCPU *cpu)
158
/* Branches, exception generating and system instructions */
102
-
103
-{
104
- CPUState *cs = CPU(cpu);
105
- CPUARMState *env = &cpu->env;
106
- MemTxResult result;
107
- hwaddr vec = env->v7m.vecbase + env->v7m.exception * 4;
108
- uint32_t addr;
109
-
110
- addr = address_space_ldl(cs->as, vec,
111
- MEMTXATTRS_UNSPECIFIED, &result);
112
- if (result != MEMTX_OK) {
113
- /* Architecturally this should cause a HardFault setting HSFR.VECTTBL,
114
- * which would then be immediately followed by our failing to load
115
- * the entry vector for that HardFault, which is a Lockup case.
116
- * Since we don't model Lockup, we just report this guest error
117
- * via cpu_abort().
118
- */
119
- cpu_abort(cs, "Failed to read from exception vector table "
120
- "entry %08x\n", (unsigned)vec);
121
- }
122
- return addr;
123
-}
124
-
125
void arm_v7m_cpu_do_interrupt(CPUState *cs)
126
{
127
ARMCPU *cpu = ARM_CPU(cs);
128
CPUARMState *env = &cpu->env;
129
- uint32_t xpsr = xpsr_read(env);
130
uint32_t lr;
131
- uint32_t addr;
132
133
arm_log_exception(cs->exception_index);
134
135
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
136
return; /* Never happens. Keep compiler happy. */
137
}
138
139
- armv7m_nvic_acknowledge_irq(env->nvic);
140
-
141
+ v7m_push_stack(cpu);
142
+ v7m_exception_taken(cpu, lr);
143
qemu_log_mask(CPU_LOG_INT, "... as %d\n", env->v7m.exception);
144
-
145
- /* Align stack pointer if the guest wants that */
146
- if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) {
147
- env->regs[13] -= 4;
148
- xpsr |= 0x200;
149
- }
150
- /* Switch to the handler mode. */
151
- v7m_push(env, xpsr);
152
- v7m_push(env, env->regs[15]);
153
- v7m_push(env, env->regs[14]);
154
- v7m_push(env, env->regs[12]);
155
- v7m_push(env, env->regs[3]);
156
- v7m_push(env, env->regs[2]);
157
- v7m_push(env, env->regs[1]);
158
- v7m_push(env, env->regs[0]);
159
- switch_v7m_sp(env, 0);
160
- /* Clear IT bits */
161
- env->condexec_bits = 0;
162
- env->regs[14] = lr;
163
- addr = arm_v7m_load_vector(cpu);
164
- env->regs[15] = addr & 0xfffffffe;
165
- env->thumb = addr & 1;
166
}
167
168
/* Function used to synchronize QEMU's AArch64 register set with AArch32
169
--
159
--
170
2.7.4
160
2.34.1
171
172
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
Convert the exception-return insns ERET, ERETA and ERETB to
2
decodetree. These were the last insns left in the legacy
3
decoder function disas_uncond_reg_b(), which allows us to
4
remove it.
2
5
3
Now that the NVIC is its own separate implementation, we can
6
The old decoder explicitly decoded the DRPS instruction,
4
clean up the GIC code by removing REV_NVIC and conditionals
7
only in order to call unallocated_encoding() on it, exactly
5
which use it.
8
as would have happened if it hadn't decoded it. This is
9
because this insn always UNDEFs unless the CPU is in
10
halting-debug state, which we don't emulate. So we list
11
the pattern in a comment in a64.decode, but don't actively
12
decode it.
6
13
7
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20230512144106.3608981-21-peter.maydell@linaro.org
10
---
17
---
11
hw/intc/gic_internal.h | 7 ++-----
18
target/arm/tcg/a64.decode | 8 ++
12
hw/intc/arm_gic.c | 31 +++++--------------------------
19
target/arm/tcg/translate-a64.c | 163 +++++++++++----------------------
13
hw/intc/arm_gic_common.c | 23 ++++++++---------------
20
2 files changed, 63 insertions(+), 108 deletions(-)
14
3 files changed, 15 insertions(+), 46 deletions(-)
15
21
16
diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h
22
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
17
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/intc/gic_internal.h
24
--- a/target/arm/tcg/a64.decode
19
+++ b/hw/intc/gic_internal.h
25
+++ b/target/arm/tcg/a64.decode
20
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@ RETA 1101011 0010 11111 00001 m:1 11111 11111 &reta # RETAA, RETAB
21
27
&bra rn rm m
22
#define ALL_CPU_MASK ((unsigned)(((1 << GIC_NCPU) - 1)))
28
BRA 1101011 1000 11111 00001 m:1 rn:5 rm:5 &bra # BRAA, BRAB
23
29
BLRA 1101011 1001 11111 00001 m:1 rn:5 rm:5 &bra # BLRAA, BLRAB
24
-/* The NVIC has 16 internal vectors. However these are not exposed
30
+
25
- through the normal GIC interface. */
31
+ERET 1101011 0100 11111 000000 11111 00000
26
-#define GIC_BASE_IRQ ((s->revision == REV_NVIC) ? 32 : 0)
32
+ERETA 1101011 0100 11111 00001 m:1 11111 11111 &reta # ERETAA, ERETAB
27
+#define GIC_BASE_IRQ 0
33
+
28
34
+# We don't need to decode DRPS because it always UNDEFs except when
29
#define GIC_SET_ENABLED(irq, cm) s->irq_state[irq].enabled |= (cm)
35
+# the processor is in halting debug state (which we don't implement).
30
#define GIC_CLEAR_ENABLED(irq, cm) s->irq_state[irq].enabled &= ~(cm)
36
+# The pattern is listed here as documentation.
31
@@ -XXX,XX +XXX,XX @@
37
+# DRPS 1101011 0101 11111 000000 11111 00000
32
38
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
33
/* The special cases for the revision property: */
34
#define REV_11MPCORE 0
35
-#define REV_NVIC 0xffffffff
36
37
void gic_set_pending_private(GICState *s, int cpu, int irq);
38
uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs);
39
@@ -XXX,XX +XXX,XX @@ void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val,
40
41
static inline bool gic_test_pending(GICState *s, int irq, int cm)
42
{
43
- if (s->revision == REV_NVIC || s->revision == REV_11MPCORE) {
44
+ if (s->revision == REV_11MPCORE) {
45
return s->irq_state[irq].pending & cm;
46
} else {
47
/* Edge-triggered interrupts are marked pending on a rising edge, but
48
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
49
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/intc/arm_gic.c
40
--- a/target/arm/tcg/translate-a64.c
51
+++ b/hw/intc/arm_gic.c
41
+++ b/target/arm/tcg/translate-a64.c
52
@@ -XXX,XX +XXX,XX @@ static void gic_set_irq_11mpcore(GICState *s, int irq, int level,
42
@@ -XXX,XX +XXX,XX @@ static bool trans_BLRA(DisasContext *s, arg_bra *a)
43
return true;
44
}
45
46
+static bool trans_ERET(DisasContext *s, arg_ERET *a)
47
+{
48
+ TCGv_i64 dst;
49
+
50
+ if (s->current_el == 0) {
51
+ return false;
52
+ }
53
+ if (s->fgt_eret) {
54
+ gen_exception_insn_el(s, 0, EXCP_UDEF, 0, 2);
55
+ return true;
56
+ }
57
+ dst = tcg_temp_new_i64();
58
+ tcg_gen_ld_i64(dst, cpu_env,
59
+ offsetof(CPUARMState, elr_el[s->current_el]));
60
+
61
+ if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
62
+ gen_io_start();
63
+ }
64
+
65
+ gen_helper_exception_return(cpu_env, dst);
66
+ /* Must exit loop to check un-masked IRQs */
67
+ s->base.is_jmp = DISAS_EXIT;
68
+ return true;
69
+}
70
+
71
+static bool trans_ERETA(DisasContext *s, arg_reta *a)
72
+{
73
+ TCGv_i64 dst;
74
+
75
+ if (!dc_isar_feature(aa64_pauth, s)) {
76
+ return false;
77
+ }
78
+ if (s->current_el == 0) {
79
+ return false;
80
+ }
81
+ /* The FGT trap takes precedence over an auth trap. */
82
+ if (s->fgt_eret) {
83
+ gen_exception_insn_el(s, 0, EXCP_UDEF, a->m ? 3 : 2, 2);
84
+ return true;
85
+ }
86
+ dst = tcg_temp_new_i64();
87
+ tcg_gen_ld_i64(dst, cpu_env,
88
+ offsetof(CPUARMState, elr_el[s->current_el]));
89
+
90
+ dst = auth_branch_target(s, dst, cpu_X[31], !a->m);
91
+ if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
92
+ gen_io_start();
93
+ }
94
+
95
+ gen_helper_exception_return(cpu_env, dst);
96
+ /* Must exit loop to check un-masked IRQs */
97
+ s->base.is_jmp = DISAS_EXIT;
98
+ return true;
99
+}
100
+
101
/* HINT instruction group, including various allocated HINTs */
102
static void handle_hint(DisasContext *s, uint32_t insn,
103
unsigned int op1, unsigned int op2, unsigned int crm)
104
@@ -XXX,XX +XXX,XX @@ static void disas_exc(DisasContext *s, uint32_t insn)
53
}
105
}
54
}
106
}
55
107
56
-static void gic_set_irq_nvic(GICState *s, int irq, int level,
108
-/* Unconditional branch (register)
57
- int cm, int target)
109
- * 31 25 24 21 20 16 15 10 9 5 4 0
110
- * +---------------+-------+-------+-------+------+-------+
111
- * | 1 1 0 1 0 1 1 | opc | op2 | op3 | Rn | op4 |
112
- * +---------------+-------+-------+-------+------+-------+
113
- */
114
-static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
58
-{
115
-{
59
- if (level) {
116
- unsigned int opc, op2, op3, rn, op4;
60
- GIC_SET_LEVEL(irq, cm);
117
- TCGv_i64 dst;
61
- GIC_SET_PENDING(irq, target);
118
- TCGv_i64 modifier;
62
- } else {
119
-
63
- GIC_CLEAR_LEVEL(irq, cm);
120
- opc = extract32(insn, 21, 4);
121
- op2 = extract32(insn, 16, 5);
122
- op3 = extract32(insn, 10, 6);
123
- rn = extract32(insn, 5, 5);
124
- op4 = extract32(insn, 0, 5);
125
-
126
- if (op2 != 0x1f) {
127
- goto do_unallocated;
128
- }
129
-
130
- switch (opc) {
131
- case 0:
132
- case 1:
133
- case 2:
134
- case 8:
135
- case 9:
136
- /*
137
- * BR, BLR, RET, RETAA, RETAB, BRAAZ, BRABZ, BLRAAZ, BLRABZ,
138
- * BRAA, BLRAA: handled in decodetree
139
- */
140
- goto do_unallocated;
141
-
142
- case 4: /* ERET */
143
- if (s->current_el == 0) {
144
- goto do_unallocated;
145
- }
146
- switch (op3) {
147
- case 0: /* ERET */
148
- if (op4 != 0) {
149
- goto do_unallocated;
150
- }
151
- if (s->fgt_eret) {
152
- gen_exception_insn_el(s, 0, EXCP_UDEF, syn_erettrap(op3), 2);
153
- return;
154
- }
155
- dst = tcg_temp_new_i64();
156
- tcg_gen_ld_i64(dst, cpu_env,
157
- offsetof(CPUARMState, elr_el[s->current_el]));
158
- break;
159
-
160
- case 2: /* ERETAA */
161
- case 3: /* ERETAB */
162
- if (!dc_isar_feature(aa64_pauth, s)) {
163
- goto do_unallocated;
164
- }
165
- if (rn != 0x1f || op4 != 0x1f) {
166
- goto do_unallocated;
167
- }
168
- /* The FGT trap takes precedence over an auth trap. */
169
- if (s->fgt_eret) {
170
- gen_exception_insn_el(s, 0, EXCP_UDEF, syn_erettrap(op3), 2);
171
- return;
172
- }
173
- dst = tcg_temp_new_i64();
174
- tcg_gen_ld_i64(dst, cpu_env,
175
- offsetof(CPUARMState, elr_el[s->current_el]));
176
- if (s->pauth_active) {
177
- modifier = cpu_X[31];
178
- if (op3 == 2) {
179
- gen_helper_autia(dst, cpu_env, dst, modifier);
180
- } else {
181
- gen_helper_autib(dst, cpu_env, dst, modifier);
182
- }
183
- }
184
- break;
185
-
186
- default:
187
- goto do_unallocated;
188
- }
189
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
190
- gen_io_start();
191
- }
192
-
193
- gen_helper_exception_return(cpu_env, dst);
194
- /* Must exit loop to check un-masked IRQs */
195
- s->base.is_jmp = DISAS_EXIT;
196
- return;
197
-
198
- case 5: /* DRPS */
199
- if (op3 != 0 || op4 != 0 || rn != 0x1f) {
200
- goto do_unallocated;
201
- } else {
202
- unallocated_encoding(s);
203
- }
204
- return;
205
-
206
- default:
207
- do_unallocated:
208
- unallocated_encoding(s);
209
- return;
64
- }
210
- }
65
-}
211
-}
66
-
212
-
67
static void gic_set_irq_generic(GICState *s, int irq, int level,
213
/* Branches, exception generating and system instructions */
68
int cm, int target)
214
static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
69
{
215
{
70
@@ -XXX,XX +XXX,XX @@ static void gic_set_irq(void *opaque, int irq, int level)
216
@@ -XXX,XX +XXX,XX @@ static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
71
217
disas_exc(s, insn);
72
if (s->revision == REV_11MPCORE) {
73
gic_set_irq_11mpcore(s, irq, level, cm, target);
74
- } else if (s->revision == REV_NVIC) {
75
- gic_set_irq_nvic(s, irq, level, cm, target);
76
} else {
77
gic_set_irq_generic(s, irq, level, cm, target);
78
}
79
@@ -XXX,XX +XXX,XX @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs)
80
return 1023;
81
}
82
83
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
84
+ if (s->revision == REV_11MPCORE) {
85
/* Clear pending flags for both level and edge triggered interrupts.
86
* Level triggered IRQs will be reasserted once they become inactive.
87
*/
88
@@ -XXX,XX +XXX,XX @@ void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
89
DPRINTF("Set %d pending mask %x\n", irq, cm);
90
GIC_SET_PENDING(irq, cm);
91
}
218
}
92
- } else if (s->revision == REV_NVIC) {
219
break;
93
- if (GIC_TEST_LEVEL(irq, cm)) {
220
- case 0x6b: /* Unconditional branch (register) */
94
- DPRINTF("Set nvic %d pending mask %x\n", irq, cm);
221
- disas_uncond_b_reg(s, insn);
95
- GIC_SET_PENDING(irq, cm);
222
- break;
96
- }
223
default:
97
}
224
unallocated_encoding(s);
98
225
break;
99
group = gic_has_groups(s) && GIC_TEST_GROUP(irq, cm);
100
@@ -XXX,XX +XXX,XX @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
101
} else if (offset < 0xf10) {
102
goto bad_reg;
103
} else if (offset < 0xf30) {
104
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
105
+ if (s->revision == REV_11MPCORE) {
106
goto bad_reg;
107
}
108
109
@@ -XXX,XX +XXX,XX @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
110
case 2:
111
res = gic_id_gicv2[(offset - 0xfd0) >> 2];
112
break;
113
- case REV_NVIC:
114
- /* Shouldn't be able to get here */
115
- abort();
116
default:
117
res = 0;
118
}
119
@@ -XXX,XX +XXX,XX @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
120
continue; /* Ignore Non-secure access of Group0 IRQ */
121
}
122
123
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
124
+ if (s->revision == REV_11MPCORE) {
125
if (value & (1 << (i * 2))) {
126
GIC_SET_MODEL(irq + i);
127
} else {
128
@@ -XXX,XX +XXX,XX @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
129
goto bad_reg;
130
} else if (offset < 0xf20) {
131
/* GICD_CPENDSGIRn */
132
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
133
+ if (s->revision == REV_11MPCORE) {
134
goto bad_reg;
135
}
136
irq = (offset - 0xf10);
137
@@ -XXX,XX +XXX,XX @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
138
}
139
} else if (offset < 0xf30) {
140
/* GICD_SPENDSGIRn */
141
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
142
+ if (s->revision == REV_11MPCORE) {
143
goto bad_reg;
144
}
145
irq = (offset - 0xf20);
146
diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/hw/intc/arm_gic_common.c
149
+++ b/hw/intc/arm_gic_common.c
150
@@ -XXX,XX +XXX,XX @@ void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
151
* [N+32..N+63] PPIs for CPU 1
152
* ...
153
*/
154
- if (s->revision != REV_NVIC) {
155
- i += (GIC_INTERNAL * s->num_cpu);
156
- }
157
+ i += (GIC_INTERNAL * s->num_cpu);
158
qdev_init_gpio_in(DEVICE(s), handler, i);
159
160
for (i = 0; i < s->num_cpu; i++) {
161
@@ -XXX,XX +XXX,XX @@ void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
162
memory_region_init_io(&s->iomem, OBJECT(s), ops, s, "gic_dist", 0x1000);
163
sysbus_init_mmio(sbd, &s->iomem);
164
165
- if (s->revision != REV_NVIC) {
166
- /* This is the main CPU interface "for this core". It is always
167
- * present because it is required by both software emulation and KVM.
168
- * NVIC is not handled here because its CPU interface is different,
169
- * neither it can use KVM.
170
- */
171
- memory_region_init_io(&s->cpuiomem[0], OBJECT(s), ops ? &ops[1] : NULL,
172
- s, "gic_cpu", s->revision == 2 ? 0x2000 : 0x100);
173
- sysbus_init_mmio(sbd, &s->cpuiomem[0]);
174
- }
175
+ /* This is the main CPU interface "for this core". It is always
176
+ * present because it is required by both software emulation and KVM.
177
+ */
178
+ memory_region_init_io(&s->cpuiomem[0], OBJECT(s), ops ? &ops[1] : NULL,
179
+ s, "gic_cpu", s->revision == 2 ? 0x2000 : 0x100);
180
+ sysbus_init_mmio(sbd, &s->cpuiomem[0]);
181
}
182
183
static void arm_gic_common_realize(DeviceState *dev, Error **errp)
184
@@ -XXX,XX +XXX,XX @@ static void arm_gic_common_realize(DeviceState *dev, Error **errp)
185
}
186
187
if (s->security_extn &&
188
- (s->revision == REV_11MPCORE || s->revision == REV_NVIC)) {
189
+ (s->revision == REV_11MPCORE)) {
190
error_setg(errp, "this GIC revision does not implement "
191
"the security extensions");
192
return;
193
@@ -XXX,XX +XXX,XX @@ static Property arm_gic_common_properties[] = {
194
DEFINE_PROP_UINT32("num-irq", GICState, num_irq, 32),
195
/* Revision can be 1 or 2 for GIC architecture specification
196
* versions 1 or 2, or 0 to indicate the legacy 11MPCore GIC.
197
- * (Internally, 0xffffffff also indicates "not a GIC but an NVIC".)
198
*/
199
DEFINE_PROP_UINT32("revision", GICState, revision, 1),
200
/* True if the GIC should implement the security extensions */
201
--
226
--
202
2.7.4
227
2.34.1
203
204
diff view generated by jsdifflib
1
Add a state field for the v7M PRIGROUP register and implent
1
The IMPDEF sysreg L2CTLR_EL1 found on the Cortex-A35, A53, A57, A72
2
reading and writing it. The current NVIC doesn't honour
2
and which we (arguably dubiously) also provide in '-cpu max' has a
3
the values written, but the new version will.
3
2 bit field for the number of processors in the cluster. On real
4
hardware this must be sufficient because it can only be configured
5
with up to 4 CPUs in the cluster. However on QEMU if the board code
6
does not explicitly configure the code into clusters with the right
7
CPU count we default to "give the value assuming that all CPUs in
8
the system are in a single cluster", which might be too big to fit
9
in the field.
10
11
Instead of just overflowing this 2-bit field, saturate to 3 (meaning
12
"4 CPUs", so at least we don't overwrite other fields in the register.
13
It's unlikely that any guest code really cares about the value in
14
this field; at least, if it does it probably also wants the system
15
to be more closely matching real hardware, i.e. not to have more
16
than 4 CPUs.
17
18
This issue has been present since the L2CTLR was first added in
19
commit 377a44ec8f2fac5b back in 2014. It was only noticed because
20
Coverity complains (CID 1509227) that the shift might overflow 32 bits
21
and inadvertently sign extend into the top half of the 64 bit value.
4
22
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
25
Message-id: 20230512170223.3801643-2-peter.maydell@linaro.org
8
---
26
---
9
hw/intc/armv7m_nvic.c | 14 ++++++++------
27
target/arm/cortex-regs.c | 11 +++++++++--
10
1 file changed, 8 insertions(+), 6 deletions(-)
28
1 file changed, 9 insertions(+), 2 deletions(-)
11
29
12
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
30
diff --git a/target/arm/cortex-regs.c b/target/arm/cortex-regs.c
13
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/intc/armv7m_nvic.c
32
--- a/target/arm/cortex-regs.c
15
+++ b/hw/intc/armv7m_nvic.c
33
+++ b/target/arm/cortex-regs.c
16
@@ -XXX,XX +XXX,XX @@
34
@@ -XXX,XX +XXX,XX @@ static uint64_t l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
17
typedef struct NVICState {
35
{
18
GICState gic;
36
ARMCPU *cpu = env_archcpu(env);
19
ARMCPU *cpu;
37
20
+
38
- /* Number of cores is in [25:24]; otherwise we RAZ */
21
+ uint32_t prigroup;
39
- return (cpu->core_count - 1) << 24;
22
+
40
+ /*
23
struct {
41
+ * Number of cores is in [25:24]; otherwise we RAZ.
24
uint32_t control;
42
+ * If the board didn't configure the CPUs into clusters,
25
uint32_t reload;
43
+ * we default to "all CPUs in one cluster", which might be
26
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset)
44
+ * more than the 4 that the hardware permits and which is
27
case 0xd08: /* Vector Table Offset. */
45
+ * all you can report in this two-bit field. Saturate to
28
return cpu->env.v7m.vecbase;
46
+ * 0b11 (== 4 CPUs) rather than overflowing the field.
29
case 0xd0c: /* Application Interrupt/Reset Control. */
47
+ */
30
- return 0xfa050000;
48
+ return MIN(cpu->core_count - 1, 3) << 24;
31
+ return 0xfa050000 | (s->prigroup << 8);
49
}
32
case 0xd10: /* System Control. */
50
33
/* TODO: Implement SLEEPONEXIT. */
51
static const ARMCPRegInfo cortex_a72_a57_a53_cp_reginfo[] = {
34
return 0;
35
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
36
if (value & 1) {
37
qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n");
38
}
39
- if (value & 0x700) {
40
- qemu_log_mask(LOG_UNIMP, "PRIGROUP unimplemented\n");
41
- }
42
+ s->prigroup = extract32(value, 8, 3);
43
}
44
break;
45
case 0xd10: /* System Control. */
46
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_sysreg_ops = {
47
48
static const VMStateDescription vmstate_nvic = {
49
.name = "armv7m_nvic",
50
- .version_id = 1,
51
- .minimum_version_id = 1,
52
+ .version_id = 2,
53
+ .minimum_version_id = 2,
54
.fields = (VMStateField[]) {
55
VMSTATE_UINT32(systick.control, NVICState),
56
VMSTATE_UINT32(systick.reload, NVICState),
57
VMSTATE_INT64(systick.tick, NVICState),
58
VMSTATE_TIMER_PTR(systick.timer, NVICState),
59
+ VMSTATE_UINT32(prigroup, NVICState),
60
VMSTATE_END_OF_LIST()
61
}
62
};
63
--
52
--
64
2.7.4
53
2.34.1
65
66
diff view generated by jsdifflib
1
Rename the nvic_state struct to NVICState, to match
1
In the vexpress board code, we allocate a new MemoryRegion at the top
2
our naming conventions.
2
of vexpress_common_init() but only set it up and use it inside the
3
"if (map[VE_NORFLASHALIAS] != -1)" conditional, so we leak it if not.
4
This isn't a very interesting leak as it's a tiny amount of memory
5
once at startup, but it's easy to fix.
6
7
We could silence Coverity simply by moving the g_new() into the
8
if() block, but this use of g_new(MemoryRegion, 1) is a legacy from
9
when this board model was originally written; we wouldn't do that
10
if we wrote it today. The MemoryRegions are conceptually a part of
11
the board and must not go away until the whole board is done with
12
(at the end of the simulation), so they belong in its state struct.
13
14
This machine already has a VexpressMachineState struct that extends
15
MachineState, so statically put the MemoryRegions in there instead of
16
dynamically allocating them separately at runtime.
17
18
Spotted by Coverity (CID 1509083).
3
19
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
21
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
22
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
23
Message-id: 20230512170223.3801643-3-peter.maydell@linaro.org
7
---
24
---
8
hw/intc/armv7m_nvic.c | 44 ++++++++++++++++++++++----------------------
25
hw/arm/vexpress.c | 40 ++++++++++++++++++++--------------------
9
1 file changed, 22 insertions(+), 22 deletions(-)
26
1 file changed, 20 insertions(+), 20 deletions(-)
10
27
11
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
28
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
12
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/intc/armv7m_nvic.c
30
--- a/hw/arm/vexpress.c
14
+++ b/hw/intc/armv7m_nvic.c
31
+++ b/hw/arm/vexpress.c
15
@@ -XXX,XX +XXX,XX @@
32
@@ -XXX,XX +XXX,XX @@ struct VexpressMachineClass {
16
#include "gic_internal.h"
33
17
#include "qemu/log.h"
34
struct VexpressMachineState {
18
35
MachineState parent;
19
-typedef struct {
36
+ MemoryRegion vram;
20
+typedef struct NVICState {
37
+ MemoryRegion sram;
21
GICState gic;
38
+ MemoryRegion flashalias;
22
ARMCPU *cpu;
39
+ MemoryRegion lowram;
23
struct {
40
+ MemoryRegion a15sram;
24
@@ -XXX,XX +XXX,XX @@ typedef struct {
41
bool secure;
25
MemoryRegion container;
42
bool virt;
26
uint32_t num_irq;
43
};
27
qemu_irq sysresetreq;
44
@@ -XXX,XX +XXX,XX @@ struct VexpressMachineState {
28
-} nvic_state;
45
#define TYPE_VEXPRESS_A15_MACHINE MACHINE_TYPE_NAME("vexpress-a15")
29
+} NVICState;
46
OBJECT_DECLARE_TYPE(VexpressMachineState, VexpressMachineClass, VEXPRESS_MACHINE)
30
47
31
#define TYPE_NVIC "armv7m_nvic"
48
-typedef void DBoardInitFn(const VexpressMachineState *machine,
32
/**
49
+typedef void DBoardInitFn(VexpressMachineState *machine,
33
@@ -XXX,XX +XXX,XX @@ typedef struct NVICClass {
50
ram_addr_t ram_size,
34
#define NVIC_GET_CLASS(obj) \
51
const char *cpu_type,
35
OBJECT_GET_CLASS(NVICClass, (obj), TYPE_NVIC)
52
qemu_irq *pic);
36
#define NVIC(obj) \
53
@@ -XXX,XX +XXX,XX @@ static void init_cpus(MachineState *ms, const char *cpu_type,
37
- OBJECT_CHECK(nvic_state, (obj), TYPE_NVIC)
38
+ OBJECT_CHECK(NVICState, (obj), TYPE_NVIC)
39
40
static const uint8_t nvic_id[] = {
41
0x00, 0xb0, 0x1b, 0x00, 0x0d, 0xe0, 0x05, 0xb1
42
@@ -XXX,XX +XXX,XX @@ static const uint8_t nvic_id[] = {
43
int system_clock_scale;
44
45
/* Conversion factor from qemu timer to SysTick frequencies. */
46
-static inline int64_t systick_scale(nvic_state *s)
47
+static inline int64_t systick_scale(NVICState *s)
48
{
49
if (s->systick.control & SYSTICK_CLKSOURCE)
50
return system_clock_scale;
51
@@ -XXX,XX +XXX,XX @@ static inline int64_t systick_scale(nvic_state *s)
52
return 1000;
53
}
54
55
-static void systick_reload(nvic_state *s, int reset)
56
+static void systick_reload(NVICState *s, int reset)
57
{
58
/* The Cortex-M3 Devices Generic User Guide says that "When the
59
* ENABLE bit is set to 1, the counter loads the RELOAD value from the
60
@@ -XXX,XX +XXX,XX @@ static void systick_reload(nvic_state *s, int reset)
61
62
static void systick_timer_tick(void * opaque)
63
{
64
- nvic_state *s = (nvic_state *)opaque;
65
+ NVICState *s = (NVICState *)opaque;
66
s->systick.control |= SYSTICK_COUNTFLAG;
67
if (s->systick.control & SYSTICK_TICKINT) {
68
/* Trigger the interrupt. */
69
@@ -XXX,XX +XXX,XX @@ static void systick_timer_tick(void * opaque)
70
}
54
}
71
}
55
}
72
56
73
-static void systick_reset(nvic_state *s)
57
-static void a9_daughterboard_init(const VexpressMachineState *vms,
74
+static void systick_reset(NVICState *s)
58
+static void a9_daughterboard_init(VexpressMachineState *vms,
59
ram_addr_t ram_size,
60
const char *cpu_type,
61
qemu_irq *pic)
75
{
62
{
76
s->systick.control = 0;
63
MachineState *machine = MACHINE(vms);
77
s->systick.reload = 0;
64
MemoryRegion *sysmem = get_system_memory();
78
@@ -XXX,XX +XXX,XX @@ static void systick_reset(nvic_state *s)
65
- MemoryRegion *lowram = g_new(MemoryRegion, 1);
79
IRQ is #16. The internal GIC routines use #32 as the first IRQ. */
66
ram_addr_t low_ram_size;
80
void armv7m_nvic_set_pending(void *opaque, int irq)
67
68
if (ram_size > 0x40000000) {
69
@@ -XXX,XX +XXX,XX @@ static void a9_daughterboard_init(const VexpressMachineState *vms,
70
* address space should in theory be remappable to various
71
* things including ROM or RAM; we always map the RAM there.
72
*/
73
- memory_region_init_alias(lowram, NULL, "vexpress.lowmem", machine->ram,
74
- 0, low_ram_size);
75
- memory_region_add_subregion(sysmem, 0x0, lowram);
76
+ memory_region_init_alias(&vms->lowram, NULL, "vexpress.lowmem",
77
+ machine->ram, 0, low_ram_size);
78
+ memory_region_add_subregion(sysmem, 0x0, &vms->lowram);
79
memory_region_add_subregion(sysmem, 0x60000000, machine->ram);
80
81
/* 0x1e000000 A9MPCore (SCU) private memory region */
82
@@ -XXX,XX +XXX,XX @@ static VEDBoardInfo a9_daughterboard = {
83
.init = a9_daughterboard_init,
84
};
85
86
-static void a15_daughterboard_init(const VexpressMachineState *vms,
87
+static void a15_daughterboard_init(VexpressMachineState *vms,
88
ram_addr_t ram_size,
89
const char *cpu_type,
90
qemu_irq *pic)
81
{
91
{
82
- nvic_state *s = (nvic_state *)opaque;
92
MachineState *machine = MACHINE(vms);
83
+ NVICState *s = (NVICState *)opaque;
93
MemoryRegion *sysmem = get_system_memory();
84
if (irq >= 16)
94
- MemoryRegion *sram = g_new(MemoryRegion, 1);
85
irq += 16;
95
86
gic_set_pending_private(&s->gic, 0, irq);
96
{
87
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq)
97
/* We have to use a separate 64 bit variable here to avoid the gcc
88
/* Make pending IRQ active. */
98
@@ -XXX,XX +XXX,XX @@ static void a15_daughterboard_init(const VexpressMachineState *vms,
89
int armv7m_nvic_acknowledge_irq(void *opaque)
99
/* 0x2b060000: SP805 watchdog: not modelled */
90
{
100
/* 0x2b0a0000: PL341 dynamic memory controller: not modelled */
91
- nvic_state *s = (nvic_state *)opaque;
101
/* 0x2e000000: system SRAM */
92
+ NVICState *s = (NVICState *)opaque;
102
- memory_region_init_ram(sram, NULL, "vexpress.a15sram", 0x10000,
93
uint32_t irq;
103
+ memory_region_init_ram(&vms->a15sram, NULL, "vexpress.a15sram", 0x10000,
94
104
&error_fatal);
95
irq = gic_acknowledge_irq(&s->gic, 0, MEMTXATTRS_UNSPECIFIED);
105
- memory_region_add_subregion(sysmem, 0x2e000000, sram);
96
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_acknowledge_irq(void *opaque)
106
+ memory_region_add_subregion(sysmem, 0x2e000000, &vms->a15sram);
97
107
98
void armv7m_nvic_complete_irq(void *opaque, int irq)
108
/* 0x7ffb0000: DMA330 DMA controller: not modelled */
99
{
109
/* 0x7ffd0000: PL354 static memory controller: not modelled */
100
- nvic_state *s = (nvic_state *)opaque;
110
@@ -XXX,XX +XXX,XX @@ static void vexpress_common_init(MachineState *machine)
101
+ NVICState *s = (NVICState *)opaque;
111
I2CBus *i2c;
102
if (irq >= 16)
112
ram_addr_t vram_size, sram_size;
103
irq += 16;
113
MemoryRegion *sysmem = get_system_memory();
104
gic_complete_irq(&s->gic, 0, irq, MEMTXATTRS_UNSPECIFIED);
114
- MemoryRegion *vram = g_new(MemoryRegion, 1);
105
}
115
- MemoryRegion *sram = g_new(MemoryRegion, 1);
106
116
- MemoryRegion *flashalias = g_new(MemoryRegion, 1);
107
-static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
117
- MemoryRegion *flash0mem;
108
+static uint32_t nvic_readl(NVICState *s, uint32_t offset)
118
const hwaddr *map = daughterboard->motherboard_map;
109
{
119
int i;
110
ARMCPU *cpu = s->cpu;
120
111
uint32_t val;
121
@@ -XXX,XX +XXX,XX @@ static void vexpress_common_init(MachineState *machine)
112
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
122
123
if (map[VE_NORFLASHALIAS] != -1) {
124
/* Map flash 0 as an alias into low memory */
125
+ MemoryRegion *flash0mem;
126
flash0mem = sysbus_mmio_get_region(SYS_BUS_DEVICE(pflash0), 0);
127
- memory_region_init_alias(flashalias, NULL, "vexpress.flashalias",
128
+ memory_region_init_alias(&vms->flashalias, NULL, "vexpress.flashalias",
129
flash0mem, 0, VEXPRESS_FLASH_SIZE);
130
- memory_region_add_subregion(sysmem, map[VE_NORFLASHALIAS], flashalias);
131
+ memory_region_add_subregion(sysmem, map[VE_NORFLASHALIAS], &vms->flashalias);
113
}
132
}
114
}
133
115
134
dinfo = drive_get(IF_PFLASH, 0, 1);
116
-static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
135
ve_pflash_cfi01_register(map[VE_NORFLASH1], "vexpress.flash1", dinfo);
117
+static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
136
118
{
137
sram_size = 0x2000000;
119
ARMCPU *cpu = s->cpu;
138
- memory_region_init_ram(sram, NULL, "vexpress.sram", sram_size,
120
uint32_t oldval;
139
+ memory_region_init_ram(&vms->sram, NULL, "vexpress.sram", sram_size,
121
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
140
&error_fatal);
122
static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
141
- memory_region_add_subregion(sysmem, map[VE_SRAM], sram);
123
unsigned size)
142
+ memory_region_add_subregion(sysmem, map[VE_SRAM], &vms->sram);
124
{
143
125
- nvic_state *s = (nvic_state *)opaque;
144
vram_size = 0x800000;
126
+ NVICState *s = (NVICState *)opaque;
145
- memory_region_init_ram(vram, NULL, "vexpress.vram", vram_size,
127
uint32_t offset = addr;
146
+ memory_region_init_ram(&vms->vram, NULL, "vexpress.vram", vram_size,
128
int i;
147
&error_fatal);
129
uint32_t val;
148
- memory_region_add_subregion(sysmem, map[VE_VIDEORAM], vram);
130
@@ -XXX,XX +XXX,XX @@ static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
149
+ memory_region_add_subregion(sysmem, map[VE_VIDEORAM], &vms->vram);
131
static void nvic_sysreg_write(void *opaque, hwaddr addr,
150
132
uint64_t value, unsigned size)
151
/* 0x4e000000 LAN9118 Ethernet */
133
{
152
if (nd_table[0].used) {
134
- nvic_state *s = (nvic_state *)opaque;
135
+ NVICState *s = (NVICState *)opaque;
136
uint32_t offset = addr;
137
int i;
138
139
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_nvic = {
140
.version_id = 1,
141
.minimum_version_id = 1,
142
.fields = (VMStateField[]) {
143
- VMSTATE_UINT32(systick.control, nvic_state),
144
- VMSTATE_UINT32(systick.reload, nvic_state),
145
- VMSTATE_INT64(systick.tick, nvic_state),
146
- VMSTATE_TIMER_PTR(systick.timer, nvic_state),
147
+ VMSTATE_UINT32(systick.control, NVICState),
148
+ VMSTATE_UINT32(systick.reload, NVICState),
149
+ VMSTATE_INT64(systick.tick, NVICState),
150
+ VMSTATE_TIMER_PTR(systick.timer, NVICState),
151
VMSTATE_END_OF_LIST()
152
}
153
};
154
155
static void armv7m_nvic_reset(DeviceState *dev)
156
{
157
- nvic_state *s = NVIC(dev);
158
+ NVICState *s = NVIC(dev);
159
NVICClass *nc = NVIC_GET_CLASS(s);
160
nc->parent_reset(dev);
161
/* Common GIC reset resets to disabled; the NVIC doesn't have
162
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_reset(DeviceState *dev)
163
164
static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
165
{
166
- nvic_state *s = NVIC(dev);
167
+ NVICState *s = NVIC(dev);
168
NVICClass *nc = NVIC_GET_CLASS(s);
169
Error *local_err = NULL;
170
171
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_instance_init(Object *obj)
172
*/
173
GICState *s = ARM_GIC_COMMON(obj);
174
DeviceState *dev = DEVICE(obj);
175
- nvic_state *nvic = NVIC(obj);
176
+ NVICState *nvic = NVIC(obj);
177
/* The ARM v7m may have anything from 0 to 496 external interrupt
178
* IRQ lines. We default to 64. Other boards may differ and should
179
* set the num-irq property appropriately.
180
@@ -XXX,XX +XXX,XX @@ static const TypeInfo armv7m_nvic_info = {
181
.name = TYPE_NVIC,
182
.parent = TYPE_ARM_GIC_COMMON,
183
.instance_init = armv7m_nvic_instance_init,
184
- .instance_size = sizeof(nvic_state),
185
+ .instance_size = sizeof(NVICState),
186
.class_init = armv7m_nvic_class_init,
187
.class_size = sizeof(NVICClass),
188
};
189
--
153
--
190
2.7.4
154
2.34.1
191
155
192
156
diff view generated by jsdifflib
1
In get_page_addr_code(), if the guest PC doesn't correspond to RAM
1
Convert the u2f.txt file to rST, and place it in the right place
2
then we currently run the CPU's do_unassigned_access() hook if it has
2
in our manual layout. The old text didn't fit very well into our
3
one, and otherwise we give up and exit QEMU with a more-or-less
3
manual style, so the new version ends up looking like a rewrite,
4
useful message. This code assumes that the do_unassigned_access hook
4
although some of the original text is preserved:
5
will never return, because if it does then we'll plough on attempting
5
6
to use a non-RAM TLB entry to get a RAM address and will abort() in
6
* the 'building' section of the old file is removed, since we
7
qemu_ram_addr_from_host_nofail(). Unfortunately some CPU
7
generally assume that users have already built QEMU
8
implementations of this hook do return: Microblaze, SPARC and the ARM
8
* some rather verbose text has been cut back
9
v7M.
9
* document the passthrough device first, on the assumption
10
10
that's most likely to be of interest to users
11
Change the code to call report_bad_exec() if the hook returns, as
11
* cut back on the duplication of text between sections
12
well as if it didn't have one. This means we can tidy it up to use
12
* format example command lines etc with rST
13
the cpu_unassigned_access() function which wraps the "get the CPU
13
14
class and call the hook if it has one" work, since we aren't trying
14
As it's a short document it seemed simplest to do this all
15
to distinguish "no hook" from "hook existed and returned" any more.
15
in one go rather than try to do a minimal syntactic conversion
16
16
and then clean up the wording and layout.
17
This brings the handling of this hook into line with the handling
18
used for data accesses, where "hook returned" is treated the
19
same as "no hook existed" and gets you the default behaviour.
20
17
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <rth@twiddle.net>
19
Reviewed-by: Thomas Huth <thuth@redhat.com>
20
Message-id: 20230421163734.1152076-1-peter.maydell@linaro.org
23
---
21
---
24
cputlb.c | 15 +++++++--------
22
docs/system/device-emulation.rst | 1 +
25
1 file changed, 7 insertions(+), 8 deletions(-)
23
docs/system/devices/usb-u2f.rst | 93 ++++++++++++++++++++++++++
26
24
docs/system/devices/usb.rst | 2 +-
27
diff --git a/cputlb.c b/cputlb.c
25
docs/u2f.txt | 110 -------------------------------
26
4 files changed, 95 insertions(+), 111 deletions(-)
27
create mode 100644 docs/system/devices/usb-u2f.rst
28
delete mode 100644 docs/u2f.txt
29
30
diff --git a/docs/system/device-emulation.rst b/docs/system/device-emulation.rst
28
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
29
--- a/cputlb.c
32
--- a/docs/system/device-emulation.rst
30
+++ b/cputlb.c
33
+++ b/docs/system/device-emulation.rst
31
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
34
@@ -XXX,XX +XXX,XX @@ Emulated Devices
32
pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
35
devices/virtio-pmem.rst
33
mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
36
devices/vhost-user-rng.rst
34
if (memory_region_is_unassigned(mr)) {
37
devices/canokey.rst
35
- CPUClass *cc = CPU_GET_CLASS(cpu);
38
+ devices/usb-u2f.rst
36
-
39
devices/igb.rst
37
- if (cc->do_unassigned_access) {
40
diff --git a/docs/system/devices/usb-u2f.rst b/docs/system/devices/usb-u2f.rst
38
- cc->do_unassigned_access(cpu, addr, false, true, 0, 4);
41
new file mode 100644
39
- } else {
42
index XXXXXXX..XXXXXXX
40
- report_bad_exec(cpu, addr);
43
--- /dev/null
41
- exit(1);
44
+++ b/docs/system/devices/usb-u2f.rst
42
- }
45
@@ -XXX,XX +XXX,XX @@
43
+ cpu_unassigned_access(cpu, addr, false, true, 0, 4);
46
+Universal Second Factor (U2F) USB Key Device
44
+ /* The CPU's unassigned access hook might have longjumped out
47
+============================================
45
+ * with an exception. If it didn't (or there was no hook) then
48
+
46
+ * we can't proceed further.
49
+U2F is an open authentication standard that enables relying parties
47
+ */
50
+exposed to the internet to offer a strong second factor option for end
48
+ report_bad_exec(cpu, addr);
51
+user authentication.
49
+ exit(1);
52
+
50
}
53
+The second factor is provided by a device implementing the U2F
51
p = (void *)((uintptr_t)addr + env1->tlb_table[mmu_idx][page_index].addend);
54
+protocol. In case of a USB U2F security key, it is a USB HID device
52
return qemu_ram_addr_from_host_nofail(p);
55
+that implements the U2F protocol.
56
+
57
+QEMU supports both pass-through of a host U2F key device to a VM,
58
+and software emulation of a U2F key.
59
+
60
+``u2f-passthru``
61
+----------------
62
+
63
+The ``u2f-passthru`` device allows you to connect a real hardware
64
+U2F key on your host to a guest VM. All requests made from the guest
65
+are passed through to the physical security key connected to the
66
+host machine and vice versa.
67
+
68
+In addition, the dedicated pass-through allows you to share a single
69
+U2F security key with several guest VMs, which is not possible with a
70
+simple host device assignment pass-through.
71
+
72
+You can specify the host U2F key to use with the ``hidraw``
73
+option, which takes the host path to a Linux ``/dev/hidrawN`` device:
74
+
75
+.. parsed-literal::
76
+ |qemu_system| -usb -device u2f-passthru,hidraw=/dev/hidraw0
77
+
78
+If you don't specify the device, the ``u2f-passthru`` device will
79
+autoscan to take the first U2F device it finds on the host (this
80
+requires a working libudev):
81
+
82
+.. parsed-literal::
83
+ |qemu_system| -usb -device u2f-passthru
84
+
85
+``u2f-emulated``
86
+----------------
87
+
88
+``u2f-emulated`` is a completely software emulated U2F device.
89
+It uses `libu2f-emu <https://github.com/MattGorko/libu2f-emu>`__
90
+for the U2F key emulation. libu2f-emu
91
+provides a complete implementation of the U2F protocol device part for
92
+all specified transports given by the FIDO Alliance.
93
+
94
+To work, an emulated U2F device must have four elements:
95
+
96
+ * ec x509 certificate
97
+ * ec private key
98
+ * counter (four bytes value)
99
+ * 48 bytes of entropy (random bits)
100
+
101
+To use this type of device, these have to be configured, and these
102
+four elements must be passed one way or another.
103
+
104
+Assuming that you have a working libu2f-emu installed on the host,
105
+there are three possible ways to configure the ``u2f-emulated`` device:
106
+
107
+ * ephemeral
108
+ * setup directory
109
+ * manual
110
+
111
+Ephemeral is the simplest way to configure; it lets the device generate
112
+all the elements it needs for a single use of the lifetime of the device.
113
+It is the default if you do not pass any other options to the device.
114
+
115
+.. parsed-literal::
116
+ |qemu_system| -usb -device u2f-emulated
117
+
118
+You can pass the device the path of a setup directory on the host
119
+using the ``dir`` option; the directory must contain these four files:
120
+
121
+ * ``certificate.pem``: ec x509 certificate
122
+ * ``private-key.pem``: ec private key
123
+ * ``counter``: counter value
124
+ * ``entropy``: 48 bytes of entropy
125
+
126
+.. parsed-literal::
127
+ |qemu_system| -usb -device u2f-emulated,dir=$dir
128
+
129
+You can also manually pass the device the paths to each of these files,
130
+if you don't want them all to be in the same directory, using the options
131
+
132
+ * ``cert``
133
+ * ``priv``
134
+ * ``counter``
135
+ * ``entropy``
136
+
137
+.. parsed-literal::
138
+ |qemu_system| -usb -device u2f-emulated,cert=$DIR1/$FILE1,priv=$DIR2/$FILE2,counter=$DIR3/$FILE3,entropy=$DIR4/$FILE4
139
diff --git a/docs/system/devices/usb.rst b/docs/system/devices/usb.rst
140
index XXXXXXX..XXXXXXX 100644
141
--- a/docs/system/devices/usb.rst
142
+++ b/docs/system/devices/usb.rst
143
@@ -XXX,XX +XXX,XX @@ option or the ``device_add`` monitor command. Available devices are:
144
USB audio device
145
146
``u2f-{emulated,passthru}``
147
- Universal Second Factor device
148
+ :doc:`usb-u2f`
149
150
``canokey``
151
An Open-source Secure Key implementing FIDO2, OpenPGP, PIV and more.
152
diff --git a/docs/u2f.txt b/docs/u2f.txt
153
deleted file mode 100644
154
index XXXXXXX..XXXXXXX
155
--- a/docs/u2f.txt
156
+++ /dev/null
157
@@ -XXX,XX +XXX,XX @@
158
-QEMU U2F Key Device Documentation.
159
-
160
-Contents
161
-1. USB U2F key device
162
-2. Building
163
-3. Using u2f-emulated
164
-4. Using u2f-passthru
165
-5. Libu2f-emu
166
-
167
-1. USB U2F key device
168
-
169
-U2F is an open authentication standard that enables relying parties
170
-exposed to the internet to offer a strong second factor option for end
171
-user authentication.
172
-
173
-The standard brings many advantages to both parties, client and server,
174
-allowing to reduce over-reliance on passwords, it increases authentication
175
-security and simplifies passwords.
176
-
177
-The second factor is materialized by a device implementing the U2F
178
-protocol. In case of a USB U2F security key, it is a USB HID device
179
-that implements the U2F protocol.
180
-
181
-In QEMU, the USB U2F key device offers a dedicated support of U2F, allowing
182
-guest USB FIDO/U2F security keys operating in two possible modes:
183
-pass-through and emulated.
184
-
185
-The pass-through mode consists of passing all requests made from the guest
186
-to the physical security key connected to the host machine and vice versa.
187
-In addition, the dedicated pass-through allows to have a U2F security key
188
-shared on several guests which is not possible with a simple host device
189
-assignment pass-through.
190
-
191
-The emulated mode consists of completely emulating the behavior of an
192
-U2F device through software part. Libu2f-emu is used for that.
193
-
194
-
195
-2. Building
196
-
197
-To ensure the build of the u2f-emulated device variant which depends
198
-on libu2f-emu: configuring and building:
199
-
200
- ./configure --enable-u2f && make
201
-
202
-The pass-through mode is built by default on Linux. To take advantage
203
-of the autoscan option it provides, make sure you have a working libudev
204
-installed on the host.
205
-
206
-
207
-3. Using u2f-emulated
208
-
209
-To work, an emulated U2F device must have four elements:
210
- * ec x509 certificate
211
- * ec private key
212
- * counter (four bytes value)
213
- * 48 bytes of entropy (random bits)
214
-
215
-To use this type of device, this one has to be configured, and these
216
-four elements must be passed one way or another.
217
-
218
-Assuming that you have a working libu2f-emu installed on the host.
219
-There are three possible ways of configurations:
220
- * ephemeral
221
- * setup directory
222
- * manual
223
-
224
-Ephemeral is the simplest way to configure, it lets the device generate
225
-all the elements it needs for a single use of the lifetime of the device.
226
-
227
- qemu -usb -device u2f-emulated
228
-
229
-Setup directory allows to configure the device from a directory containing
230
-four files:
231
- * certificate.pem: ec x509 certificate
232
- * private-key.pem: ec private key
233
- * counter: counter value
234
- * entropy: 48 bytes of entropy
235
-
236
- qemu -usb -device u2f-emulated,dir=$dir
237
-
238
-Manual allows to configure the device more finely by specifying each
239
-of the elements necessary for the device:
240
- * cert
241
- * priv
242
- * counter
243
- * entropy
244
-
245
- qemu -usb -device u2f-emulated,cert=$DIR1/$FILE1,priv=$DIR2/$FILE2,counter=$DIR3/$FILE3,entropy=$DIR4/$FILE4
246
-
247
-
248
-4. Using u2f-passthru
249
-
250
-On the host specify the u2f-passthru device with a suitable hidraw:
251
-
252
- qemu -usb -device u2f-passthru,hidraw=/dev/hidraw0
253
-
254
-Alternately, the u2f-passthru device can autoscan to take the first
255
-U2F device it finds on the host (this requires a working libudev):
256
-
257
- qemu -usb -device u2f-passthru
258
-
259
-
260
-5. Libu2f-emu
261
-
262
-The u2f-emulated device uses libu2f-emu for the U2F key emulation. Libu2f-emu
263
-implements completely the U2F protocol device part for all specified
264
-transport given by the FIDO Alliance.
265
-
266
-For more information about libu2f-emu see this page:
267
-https://github.com/MattGorko/libu2f-emu.
53
--
268
--
54
2.7.4
269
2.34.1
55
56
diff view generated by jsdifflib
Deleted patch
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
2
1
3
The v7M exception architecture requires that if a synchronous
4
exception cannot be taken immediately (because it is disabled
5
or at too low a priority) then it should be escalated to
6
HardFault (and the HardFault exception is then taken).
7
Implement this escalation logic.
8
9
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
10
[PMM: extracted from another patch]
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
---
14
hw/intc/armv7m_nvic.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++
15
target/arm/helper.c | 2 --
16
2 files changed, 53 insertions(+), 2 deletions(-)
17
18
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/intc/armv7m_nvic.c
21
+++ b/hw/intc/armv7m_nvic.c
22
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq)
23
24
vec = &s->vectors[irq];
25
trace_nvic_set_pending(irq, vec->enabled, vec->prio);
26
+
27
+
28
+ if (irq >= ARMV7M_EXCP_HARD && irq < ARMV7M_EXCP_PENDSV) {
29
+ /* If a synchronous exception is pending then it may be
30
+ * escalated to HardFault if:
31
+ * * it is equal or lower priority to current execution
32
+ * * it is disabled
33
+ * (ie we need to take it immediately but we can't do so).
34
+ * Asynchronous exceptions (and interrupts) simply remain pending.
35
+ *
36
+ * For QEMU, we don't have any imprecise (asynchronous) faults,
37
+ * so we can assume that PREFETCH_ABORT and DATA_ABORT are always
38
+ * synchronous.
39
+ * Debug exceptions are awkward because only Debug exceptions
40
+ * resulting from the BKPT instruction should be escalated,
41
+ * but we don't currently implement any Debug exceptions other
42
+ * than those that result from BKPT, so we treat all debug exceptions
43
+ * as needing escalation.
44
+ *
45
+ * This all means we can identify whether to escalate based only on
46
+ * the exception number and don't (yet) need the caller to explicitly
47
+ * tell us whether this exception is synchronous or not.
48
+ */
49
+ int running = nvic_exec_prio(s);
50
+ bool escalate = false;
51
+
52
+ if (vec->prio >= running) {
53
+ trace_nvic_escalate_prio(irq, vec->prio, running);
54
+ escalate = true;
55
+ } else if (!vec->enabled) {
56
+ trace_nvic_escalate_disabled(irq);
57
+ escalate = true;
58
+ }
59
+
60
+ if (escalate) {
61
+ if (running < 0) {
62
+ /* We want to escalate to HardFault but we can't take a
63
+ * synchronous HardFault at this point either. This is a
64
+ * Lockup condition due to a guest bug. We don't model
65
+ * Lockup, so report via cpu_abort() instead.
66
+ */
67
+ cpu_abort(&s->cpu->parent_obj,
68
+ "Lockup: can't escalate %d to HardFault "
69
+ "(current priority %d)\n", irq, running);
70
+ }
71
+
72
+ /* We can do the escalation, so we take HardFault instead */
73
+ irq = ARMV7M_EXCP_HARD;
74
+ vec = &s->vectors[irq];
75
+ s->cpu->env.v7m.hfsr |= R_V7M_HFSR_FORCED_MASK;
76
+ }
77
+ }
78
+
79
if (!vec->pending) {
80
vec->pending = 1;
81
nvic_irq_update(s);
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 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
87
88
/* For exceptions we just mark as pending on the NVIC, and let that
89
handle it. */
90
- /* TODO: Need to escalate if the current priority is higher than the
91
- one we're raising. */
92
switch (cs->exception_index) {
93
case EXCP_UDEF:
94
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
95
--
96
2.7.4
97
98
diff view generated by jsdifflib