1
The following changes since commit eae587e8e3694b1aceab23239493fb4c7e1a80f5:
1
The following changes since commit 8f6330a807f2642dc2a3cdf33347aa28a4c00a87:
2
2
3
Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2021-09-13' into staging (2021-09-13 11:00:30 +0100)
3
Merge tag 'pull-maintainer-updates-060324-1' of https://gitlab.com/stsquad/qemu into staging (2024-03-06 16:56:20 +0000)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210913
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20240308
8
8
9
for you to fetch changes up to 9a2b2ecf4d25a3943918c95d2db4508b304161b5:
9
for you to fetch changes up to bbf6c6dbead82292a20951eb1204442a6b838de9:
10
10
11
hw/arm/mps2.c: Mark internal-only I2C buses as 'full' (2021-09-13 17:09:28 +0100)
11
target/arm: Move v7m-related code from cpu32.c into a separate file (2024-03-08 14:45:03 +0000)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
target-arm queue:
14
target-arm queue:
15
* mark MPS2/MPS3 board-internal i2c buses as 'full' so that command
15
* Implement FEAT_ECV
16
line user-created devices are not plugged into them
16
* STM32L4x5: Implement GPIO device
17
* Take an exception if PSTATE.IL is set
17
* Fix 32-bit SMOPA
18
* Support an emulated ITS in the virt board
18
* Refactor v7m related code from cpu32.c into its own file
19
* Add support for kudo-bmc board
19
* hw/rtc/sun4v-rtc: Relicense to GPLv2-or-later
20
* Probe for KVM_CAP_ARM_VM_IPA_SIZE when creating scratch VM
21
* cadence_uart: Fix clock handling issues that prevented
22
u-boot from running
23
20
24
----------------------------------------------------------------
21
----------------------------------------------------------------
25
Bin Meng (6):
22
Inès Varhol (3):
26
hw/misc: zynq_slcr: Correctly compute output clocks in the reset exit phase
23
hw/gpio: Implement STM32L4x5 GPIO
27
hw/char: cadence_uart: Disable transmit when input clock is disabled
24
hw/arm: Connect STM32L4x5 GPIO to STM32L4x5 SoC
28
hw/char: cadence_uart: Move clock/reset check to uart_can_receive()
25
tests/qtest: Add STM32L4x5 GPIO QTest testcase
29
hw/char: cadence_uart: Convert to memop_with_attrs() ops
30
hw/char: cadence_uart: Ignore access when unclocked or in reset for uart_{read, write}()
31
hw/char: cadence_uart: Log a guest error when device is unclocked or in reset
32
26
33
Chris Rauer (1):
27
Peter Maydell (9):
34
hw/arm: Add support for kudo-bmc board.
28
target/arm: Move some register related defines to internals.h
35
29
target/arm: Timer _EL02 registers UNDEF for E2H == 0
36
Marc Zyngier (1):
30
target/arm: use FIELD macro for CNTHCTL bit definitions
37
hw/arm/virt: KVM: Probe for KVM_CAP_ARM_VM_IPA_SIZE when creating scratch VM
31
target/arm: Don't allow RES0 CNTHCTL_EL2 bits to be written
38
32
target/arm: Implement new FEAT_ECV trap bits
39
Peter Maydell (5):
33
target/arm: Define CNTPCTSS_EL0 and CNTVCTSS_EL0
40
target/arm: Take an exception if PSTATE.IL is set
34
target/arm: Implement FEAT_ECV CNTPOFF_EL2 handling
41
qdev: Support marking individual buses as 'full'
35
target/arm: Enable FEAT_ECV for 'max' CPU
42
hw/arm/mps2-tz.c: Add extra data parameter to MakeDevFn
36
hw/rtc/sun4v-rtc: Relicense to GPLv2-or-later
43
hw/arm/mps2-tz.c: Mark internal-only I2C buses as 'full'
44
hw/arm/mps2.c: Mark internal-only I2C buses as 'full'
45
37
46
Richard Henderson (1):
38
Richard Henderson (1):
47
target/arm: Merge disas_a64_insn into aarch64_tr_translate_insn
39
target/arm: Fix 32-bit SMOPA
48
40
49
Shashi Mallela (9):
41
Thomas Huth (1):
50
hw/intc: GICv3 ITS initial framework
42
target/arm: Move v7m-related code from cpu32.c into a separate file
51
hw/intc: GICv3 ITS register definitions added
52
hw/intc: GICv3 ITS command queue framework
53
hw/intc: GICv3 ITS Command processing
54
hw/intc: GICv3 ITS Feature enablement
55
hw/intc: GICv3 redistributor ITS processing
56
tests/data/acpi/virt: Add IORT files for ITS
57
hw/arm/virt: add ITS support in virt GIC
58
tests/data/acpi/virt: Update IORT files for ITS
59
43
60
docs/system/arm/nuvoton.rst | 1 +
44
MAINTAINERS | 1 +
61
hw/intc/gicv3_internal.h | 188 ++++-
45
docs/system/arm/b-l475e-iot01a.rst | 2 +-
62
include/hw/arm/virt.h | 2 +
46
docs/system/arm/emulation.rst | 1 +
63
include/hw/intc/arm_gicv3_common.h | 13 +
47
include/hw/arm/stm32l4x5_soc.h | 2 +
64
include/hw/intc/arm_gicv3_its_common.h | 32 +-
48
include/hw/gpio/stm32l4x5_gpio.h | 71 +++++
65
include/hw/qdev-core.h | 24 +
49
include/hw/misc/stm32l4x5_syscfg.h | 3 +-
66
target/arm/cpu.h | 1 +
50
include/hw/rtc/sun4v-rtc.h | 2 +-
67
target/arm/kvm_arm.h | 4 +-
51
target/arm/cpu-features.h | 10 +
68
target/arm/syndrome.h | 5 +
52
target/arm/cpu.h | 129 +--------
69
target/arm/translate.h | 2 +
53
target/arm/internals.h | 151 ++++++++++
70
hw/arm/mps2-tz.c | 92 ++-
54
hw/arm/stm32l4x5_soc.c | 71 ++++-
71
hw/arm/mps2.c | 12 +-
55
hw/gpio/stm32l4x5_gpio.c | 477 ++++++++++++++++++++++++++++++++
72
hw/arm/npcm7xx_boards.c | 34 +
56
hw/misc/stm32l4x5_syscfg.c | 1 +
73
hw/arm/virt.c | 29 +-
57
hw/rtc/sun4v-rtc.c | 2 +-
74
hw/char/cadence_uart.c | 61 +-
58
target/arm/helper.c | 189 ++++++++++++-
75
hw/intc/arm_gicv3.c | 14 +
59
target/arm/tcg/cpu-v7m.c | 290 +++++++++++++++++++
76
hw/intc/arm_gicv3_common.c | 13 +
60
target/arm/tcg/cpu32.c | 261 ------------------
77
hw/intc/arm_gicv3_cpuif.c | 7 +-
61
target/arm/tcg/cpu64.c | 1 +
78
hw/intc/arm_gicv3_dist.c | 5 +-
62
target/arm/tcg/sme_helper.c | 77 +++---
79
hw/intc/arm_gicv3_its.c | 1322 ++++++++++++++++++++++++++++++++
63
tests/qtest/stm32l4x5_gpio-test.c | 551 +++++++++++++++++++++++++++++++++++++
80
hw/intc/arm_gicv3_its_common.c | 7 +-
64
tests/tcg/aarch64/sme-smopa-1.c | 47 ++++
81
hw/intc/arm_gicv3_its_kvm.c | 2 +-
65
tests/tcg/aarch64/sme-smopa-2.c | 54 ++++
82
hw/intc/arm_gicv3_redist.c | 153 +++-
66
hw/arm/Kconfig | 3 +-
83
hw/misc/zynq_slcr.c | 31 +-
67
hw/gpio/Kconfig | 3 +
84
softmmu/qdev-monitor.c | 7 +-
68
hw/gpio/meson.build | 1 +
85
target/arm/helper-a64.c | 1 +
69
hw/gpio/trace-events | 6 +
86
target/arm/helper.c | 8 +
70
target/arm/meson.build | 3 +
87
target/arm/kvm.c | 7 +-
71
target/arm/tcg/meson.build | 3 +
88
target/arm/translate-a64.c | 255 +++---
72
target/arm/trace-events | 1 +
89
target/arm/translate.c | 21 +
73
tests/qtest/meson.build | 3 +-
90
hw/intc/meson.build | 1 +
74
tests/tcg/aarch64/Makefile.target | 2 +-
91
tests/data/acpi/virt/IORT | Bin 0 -> 124 bytes
75
31 files changed, 1962 insertions(+), 456 deletions(-)
92
tests/data/acpi/virt/IORT.memhp | Bin 0 -> 124 bytes
76
create mode 100644 include/hw/gpio/stm32l4x5_gpio.h
93
tests/data/acpi/virt/IORT.numamem | Bin 0 -> 124 bytes
77
create mode 100644 hw/gpio/stm32l4x5_gpio.c
94
tests/data/acpi/virt/IORT.pxb | Bin 0 -> 124 bytes
78
create mode 100644 target/arm/tcg/cpu-v7m.c
95
35 files changed, 2144 insertions(+), 210 deletions(-)
79
create mode 100644 tests/qtest/stm32l4x5_gpio-test.c
96
create mode 100644 hw/intc/arm_gicv3_its.c
80
create mode 100644 tests/tcg/aarch64/sme-smopa-1.c
97
create mode 100644 tests/data/acpi/virt/IORT
81
create mode 100644 tests/tcg/aarch64/sme-smopa-2.c
98
create mode 100644 tests/data/acpi/virt/IORT.memhp
99
create mode 100644 tests/data/acpi/virt/IORT.numamem
100
create mode 100644 tests/data/acpi/virt/IORT.pxb
101
82
diff view generated by jsdifflib
Deleted patch
1
From: Bin Meng <bmeng.cn@gmail.com>
2
1
3
As of today, when booting upstream U-Boot for Xilinx Zynq, the UART
4
does not receive anything. Debugging shows that the UART input clock
5
frequency is zero which prevents the UART from receiving anything as
6
per the logic in uart_receive().
7
8
From zynq_slcr_reset_exit() comment, it intends to compute output
9
clocks according to ps_clk and registers. zynq_slcr_compute_clocks()
10
is called to accomplish the task, inside which device_is_in_reset()
11
is called to actually make the attempt in vain.
12
13
Rework reset_hold() and reset_exit() so that in the reset exit phase,
14
the logic can really compute output clocks in reset_exit().
15
16
With this change, upstream U-Boot boots properly again with:
17
18
$ qemu-system-arm -M xilinx-zynq-a9 -m 1G -display none -serial null -serial stdio \
19
-device loader,file=u-boot-dtb.bin,addr=0x4000000,cpu-num=0
20
21
Fixes: 38867cb7ec90 ("hw/misc/zynq_slcr: add clock generation for uarts")
22
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
23
Acked-by: Alistair Francis <alistair.francis@wdc.com>
24
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
25
Message-id: 20210901124521.30599-2-bmeng.cn@gmail.com
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
---
28
hw/misc/zynq_slcr.c | 31 ++++++++++++++++++-------------
29
1 file changed, 18 insertions(+), 13 deletions(-)
30
31
diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/hw/misc/zynq_slcr.c
34
+++ b/hw/misc/zynq_slcr.c
35
@@ -XXX,XX +XXX,XX @@ static uint64_t zynq_slcr_compute_clock(const uint64_t periods[],
36
zynq_slcr_compute_clock((plls), (state)->regs[reg], \
37
reg ## _ ## enable_field ## _SHIFT)
38
39
+static void zynq_slcr_compute_clocks_internal(ZynqSLCRState *s, uint64_t ps_clk)
40
+{
41
+ uint64_t io_pll = zynq_slcr_compute_pll(ps_clk, s->regs[R_IO_PLL_CTRL]);
42
+ uint64_t arm_pll = zynq_slcr_compute_pll(ps_clk, s->regs[R_ARM_PLL_CTRL]);
43
+ uint64_t ddr_pll = zynq_slcr_compute_pll(ps_clk, s->regs[R_DDR_PLL_CTRL]);
44
+
45
+ uint64_t uart_mux[4] = {io_pll, io_pll, arm_pll, ddr_pll};
46
+
47
+ /* compute uartX reference clocks */
48
+ clock_set(s->uart0_ref_clk,
49
+ ZYNQ_COMPUTE_CLK(s, uart_mux, R_UART_CLK_CTRL, CLKACT0));
50
+ clock_set(s->uart1_ref_clk,
51
+ ZYNQ_COMPUTE_CLK(s, uart_mux, R_UART_CLK_CTRL, CLKACT1));
52
+}
53
+
54
/**
55
* Compute and set the ouputs clocks periods.
56
* But do not propagate them further. Connected clocks
57
@@ -XXX,XX +XXX,XX @@ static void zynq_slcr_compute_clocks(ZynqSLCRState *s)
58
ps_clk = 0;
59
}
60
61
- uint64_t io_pll = zynq_slcr_compute_pll(ps_clk, s->regs[R_IO_PLL_CTRL]);
62
- uint64_t arm_pll = zynq_slcr_compute_pll(ps_clk, s->regs[R_ARM_PLL_CTRL]);
63
- uint64_t ddr_pll = zynq_slcr_compute_pll(ps_clk, s->regs[R_DDR_PLL_CTRL]);
64
-
65
- uint64_t uart_mux[4] = {io_pll, io_pll, arm_pll, ddr_pll};
66
-
67
- /* compute uartX reference clocks */
68
- clock_set(s->uart0_ref_clk,
69
- ZYNQ_COMPUTE_CLK(s, uart_mux, R_UART_CLK_CTRL, CLKACT0));
70
- clock_set(s->uart1_ref_clk,
71
- ZYNQ_COMPUTE_CLK(s, uart_mux, R_UART_CLK_CTRL, CLKACT1));
72
+ zynq_slcr_compute_clocks_internal(s, ps_clk);
73
}
74
75
/**
76
@@ -XXX,XX +XXX,XX @@ static void zynq_slcr_reset_hold(Object *obj)
77
ZynqSLCRState *s = ZYNQ_SLCR(obj);
78
79
/* will disable all output clocks */
80
- zynq_slcr_compute_clocks(s);
81
+ zynq_slcr_compute_clocks_internal(s, 0);
82
zynq_slcr_propagate_clocks(s);
83
}
84
85
@@ -XXX,XX +XXX,XX @@ static void zynq_slcr_reset_exit(Object *obj)
86
ZynqSLCRState *s = ZYNQ_SLCR(obj);
87
88
/* will compute output clocks according to ps_clk and registers */
89
- zynq_slcr_compute_clocks(s);
90
+ zynq_slcr_compute_clocks_internal(s, clock_get(s->ps_clk));
91
zynq_slcr_propagate_clocks(s);
92
}
93
94
--
95
2.20.1
96
97
diff view generated by jsdifflib
Deleted patch
1
From: Bin Meng <bmeng.cn@gmail.com>
2
1
3
At present when input clock is disabled, any character transmitted
4
to tx fifo can still show on the serial line, which is wrong.
5
6
Fixes: b636db306e06 ("hw/char/cadence_uart: add clock support")
7
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
Message-id: 20210901124521.30599-3-bmeng.cn@gmail.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/char/cadence_uart.c | 5 +++++
14
1 file changed, 5 insertions(+)
15
16
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/char/cadence_uart.c
19
+++ b/hw/char/cadence_uart.c
20
@@ -XXX,XX +XXX,XX @@ static gboolean cadence_uart_xmit(void *do_not_use, GIOCondition cond,
21
static void uart_write_tx_fifo(CadenceUARTState *s, const uint8_t *buf,
22
int size)
23
{
24
+ /* ignore characters when unclocked or in reset */
25
+ if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) {
26
+ return;
27
+ }
28
+
29
if ((s->r[R_CR] & UART_CR_TX_DIS) || !(s->r[R_CR] & UART_CR_TX_EN)) {
30
return;
31
}
32
--
33
2.20.1
34
35
diff view generated by jsdifflib
Deleted patch
1
From: Bin Meng <bmeng.cn@gmail.com>
2
1
3
Currently the clock/reset check is done in uart_receive(), but we
4
can move the check to uart_can_receive() which is earlier.
5
6
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-id: 20210901124521.30599-4-bmeng.cn@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
hw/char/cadence_uart.c | 17 ++++++++++-------
13
1 file changed, 10 insertions(+), 7 deletions(-)
14
15
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/char/cadence_uart.c
18
+++ b/hw/char/cadence_uart.c
19
@@ -XXX,XX +XXX,XX @@ static void uart_parameters_setup(CadenceUARTState *s)
20
static int uart_can_receive(void *opaque)
21
{
22
CadenceUARTState *s = opaque;
23
- int ret = MAX(CADENCE_UART_RX_FIFO_SIZE, CADENCE_UART_TX_FIFO_SIZE);
24
- uint32_t ch_mode = s->r[R_MR] & UART_MR_CHMODE;
25
+ int ret;
26
+ uint32_t ch_mode;
27
+
28
+ /* ignore characters when unclocked or in reset */
29
+ if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) {
30
+ return 0;
31
+ }
32
+
33
+ ret = MAX(CADENCE_UART_RX_FIFO_SIZE, CADENCE_UART_TX_FIFO_SIZE);
34
+ ch_mode = s->r[R_MR] & UART_MR_CHMODE;
35
36
if (ch_mode == NORMAL_MODE || ch_mode == ECHO_MODE) {
37
ret = MIN(ret, CADENCE_UART_RX_FIFO_SIZE - s->rx_count);
38
@@ -XXX,XX +XXX,XX @@ static void uart_receive(void *opaque, const uint8_t *buf, int size)
39
CadenceUARTState *s = opaque;
40
uint32_t ch_mode = s->r[R_MR] & UART_MR_CHMODE;
41
42
- /* ignore characters when unclocked or in reset */
43
- if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) {
44
- return;
45
- }
46
-
47
if (ch_mode == NORMAL_MODE || ch_mode == ECHO_MODE) {
48
uart_write_rx_fifo(opaque, buf, size);
49
}
50
--
51
2.20.1
52
53
diff view generated by jsdifflib
1
In v8A, the PSTATE.IL bit is set for various kinds of illegal
1
cpu.h has a lot of #defines relating to CPU register fields.
2
exception return or mode-change attempts. We already set PSTATE.IL
2
Most of these aren't actually used outside target/arm code,
3
(or its AArch32 equivalent CPSR.IL) in all those cases, but we
3
so there's no point in cluttering up the cpu.h file with them.
4
weren't implementing the part of the behaviour where attempting to
4
Move some easy ones to internals.h.
5
execute an instruction with PSTATE.IL takes an immediate exception
6
with an appropriate syndrome value.
7
8
Add a new TB flags bit tracking PSTATE.IL/CPSR.IL, and generate code
9
to take an exception instead of whatever the instruction would have
10
been.
11
12
PSTATE.IL and CPSR.IL change only on exception entry, attempted
13
exception exit, and various AArch32 mode changes via cpsr_write().
14
These places generally already rebuild the hflags, so the only place
15
we need an extra rebuild_hflags call is in the illegal-return
16
codepath of the AArch64 exception_return helper.
17
5
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20210821195958.41312-2-richard.henderson@linaro.org
9
Message-id: 20240301183219.2424889-2-peter.maydell@linaro.org
22
Message-Id: <20210817162118.24319-1-peter.maydell@linaro.org>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
[rth: Added missing returns; set IL bit in syndrome]
25
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
26
---
10
---
27
target/arm/cpu.h | 1 +
11
target/arm/cpu.h | 128 -----------------------------------------
28
target/arm/syndrome.h | 5 +++++
12
target/arm/internals.h | 128 +++++++++++++++++++++++++++++++++++++++++
29
target/arm/translate.h | 2 ++
13
2 files changed, 128 insertions(+), 128 deletions(-)
30
target/arm/helper-a64.c | 1 +
31
target/arm/helper.c | 8 ++++++++
32
target/arm/translate-a64.c | 11 +++++++++++
33
target/arm/translate.c | 21 +++++++++++++++++++++
34
7 files changed, 49 insertions(+)
35
14
36
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
37
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/cpu.h
17
--- a/target/arm/cpu.h
39
+++ b/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
40
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_ANY, FPEXC_EL, 8, 2)
19
@@ -XXX,XX +XXX,XX @@ typedef struct ARMGenericTimer {
41
FIELD(TBFLAG_ANY, DEBUG_TARGET_EL, 10, 2)
20
uint64_t ctl; /* Timer Control register */
42
/* Memory operations require alignment: SCTLR_ELx.A or CCR.UNALIGN_TRP */
21
} ARMGenericTimer;
43
FIELD(TBFLAG_ANY, ALIGN_MEM, 12, 1)
22
44
+FIELD(TBFLAG_ANY, PSTATE__IL, 13, 1)
23
-#define VTCR_NSW (1u << 29)
45
24
-#define VTCR_NSA (1u << 30)
46
/*
25
-#define VSTCR_SW VTCR_NSW
47
* Bit usage when in AArch32 state, both A- and M-profile.
26
-#define VSTCR_SA VTCR_NSA
48
diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h
27
-
28
/* Define a maximum sized vector register.
29
* For 32-bit, this is a 128-bit NEON/AdvSIMD register.
30
* For 64-bit, this is a 2048-bit SVE register.
31
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
32
#define SCTLR_SPINTMASK (1ULL << 62) /* FEAT_NMI */
33
#define SCTLR_TIDCP (1ULL << 63) /* FEAT_TIDCP1 */
34
35
-/* Bit definitions for CPACR (AArch32 only) */
36
-FIELD(CPACR, CP10, 20, 2)
37
-FIELD(CPACR, CP11, 22, 2)
38
-FIELD(CPACR, TRCDIS, 28, 1) /* matches CPACR_EL1.TTA */
39
-FIELD(CPACR, D32DIS, 30, 1) /* up to v7; RAZ in v8 */
40
-FIELD(CPACR, ASEDIS, 31, 1)
41
-
42
-/* Bit definitions for CPACR_EL1 (AArch64 only) */
43
-FIELD(CPACR_EL1, ZEN, 16, 2)
44
-FIELD(CPACR_EL1, FPEN, 20, 2)
45
-FIELD(CPACR_EL1, SMEN, 24, 2)
46
-FIELD(CPACR_EL1, TTA, 28, 1) /* matches CPACR.TRCDIS */
47
-
48
-/* Bit definitions for HCPTR (AArch32 only) */
49
-FIELD(HCPTR, TCP10, 10, 1)
50
-FIELD(HCPTR, TCP11, 11, 1)
51
-FIELD(HCPTR, TASE, 15, 1)
52
-FIELD(HCPTR, TTA, 20, 1)
53
-FIELD(HCPTR, TAM, 30, 1) /* matches CPTR_EL2.TAM */
54
-FIELD(HCPTR, TCPAC, 31, 1) /* matches CPTR_EL2.TCPAC */
55
-
56
-/* Bit definitions for CPTR_EL2 (AArch64 only) */
57
-FIELD(CPTR_EL2, TZ, 8, 1) /* !E2H */
58
-FIELD(CPTR_EL2, TFP, 10, 1) /* !E2H, matches HCPTR.TCP10 */
59
-FIELD(CPTR_EL2, TSM, 12, 1) /* !E2H */
60
-FIELD(CPTR_EL2, ZEN, 16, 2) /* E2H */
61
-FIELD(CPTR_EL2, FPEN, 20, 2) /* E2H */
62
-FIELD(CPTR_EL2, SMEN, 24, 2) /* E2H */
63
-FIELD(CPTR_EL2, TTA, 28, 1)
64
-FIELD(CPTR_EL2, TAM, 30, 1) /* matches HCPTR.TAM */
65
-FIELD(CPTR_EL2, TCPAC, 31, 1) /* matches HCPTR.TCPAC */
66
-
67
-/* Bit definitions for CPTR_EL3 (AArch64 only) */
68
-FIELD(CPTR_EL3, EZ, 8, 1)
69
-FIELD(CPTR_EL3, TFP, 10, 1)
70
-FIELD(CPTR_EL3, ESM, 12, 1)
71
-FIELD(CPTR_EL3, TTA, 20, 1)
72
-FIELD(CPTR_EL3, TAM, 30, 1)
73
-FIELD(CPTR_EL3, TCPAC, 31, 1)
74
-
75
-#define MDCR_MTPME (1U << 28)
76
-#define MDCR_TDCC (1U << 27)
77
-#define MDCR_HLP (1U << 26) /* MDCR_EL2 */
78
-#define MDCR_SCCD (1U << 23) /* MDCR_EL3 */
79
-#define MDCR_HCCD (1U << 23) /* MDCR_EL2 */
80
-#define MDCR_EPMAD (1U << 21)
81
-#define MDCR_EDAD (1U << 20)
82
-#define MDCR_TTRF (1U << 19)
83
-#define MDCR_STE (1U << 18) /* MDCR_EL3 */
84
-#define MDCR_SPME (1U << 17) /* MDCR_EL3 */
85
-#define MDCR_HPMD (1U << 17) /* MDCR_EL2 */
86
-#define MDCR_SDD (1U << 16)
87
-#define MDCR_SPD (3U << 14)
88
-#define MDCR_TDRA (1U << 11)
89
-#define MDCR_TDOSA (1U << 10)
90
-#define MDCR_TDA (1U << 9)
91
-#define MDCR_TDE (1U << 8)
92
-#define MDCR_HPME (1U << 7)
93
-#define MDCR_TPM (1U << 6)
94
-#define MDCR_TPMCR (1U << 5)
95
-#define MDCR_HPMN (0x1fU)
96
-
97
-/* Not all of the MDCR_EL3 bits are present in the 32-bit SDCR */
98
-#define SDCR_VALID_MASK (MDCR_MTPME | MDCR_TDCC | MDCR_SCCD | \
99
- MDCR_EPMAD | MDCR_EDAD | MDCR_TTRF | \
100
- MDCR_STE | MDCR_SPME | MDCR_SPD)
101
-
102
#define CPSR_M (0x1fU)
103
#define CPSR_T (1U << 5)
104
#define CPSR_F (1U << 6)
105
@@ -XXX,XX +XXX,XX @@ FIELD(CPTR_EL3, TCPAC, 31, 1)
106
#define XPSR_NZCV CPSR_NZCV
107
#define XPSR_IT CPSR_IT
108
109
-#define TTBCR_N (7U << 0) /* TTBCR.EAE==0 */
110
-#define TTBCR_T0SZ (7U << 0) /* TTBCR.EAE==1 */
111
-#define TTBCR_PD0 (1U << 4)
112
-#define TTBCR_PD1 (1U << 5)
113
-#define TTBCR_EPD0 (1U << 7)
114
-#define TTBCR_IRGN0 (3U << 8)
115
-#define TTBCR_ORGN0 (3U << 10)
116
-#define TTBCR_SH0 (3U << 12)
117
-#define TTBCR_T1SZ (3U << 16)
118
-#define TTBCR_A1 (1U << 22)
119
-#define TTBCR_EPD1 (1U << 23)
120
-#define TTBCR_IRGN1 (3U << 24)
121
-#define TTBCR_ORGN1 (3U << 26)
122
-#define TTBCR_SH1 (1U << 28)
123
-#define TTBCR_EAE (1U << 31)
124
-
125
-FIELD(VTCR, T0SZ, 0, 6)
126
-FIELD(VTCR, SL0, 6, 2)
127
-FIELD(VTCR, IRGN0, 8, 2)
128
-FIELD(VTCR, ORGN0, 10, 2)
129
-FIELD(VTCR, SH0, 12, 2)
130
-FIELD(VTCR, TG0, 14, 2)
131
-FIELD(VTCR, PS, 16, 3)
132
-FIELD(VTCR, VS, 19, 1)
133
-FIELD(VTCR, HA, 21, 1)
134
-FIELD(VTCR, HD, 22, 1)
135
-FIELD(VTCR, HWU59, 25, 1)
136
-FIELD(VTCR, HWU60, 26, 1)
137
-FIELD(VTCR, HWU61, 27, 1)
138
-FIELD(VTCR, HWU62, 28, 1)
139
-FIELD(VTCR, NSW, 29, 1)
140
-FIELD(VTCR, NSA, 30, 1)
141
-FIELD(VTCR, DS, 32, 1)
142
-FIELD(VTCR, SL2, 33, 1)
143
-
144
/* Bit definitions for ARMv8 SPSR (PSTATE) format.
145
* Only these are valid when in AArch64 mode; in
146
* AArch32 mode SPSRs are basically CPSR-format.
147
@@ -XXX,XX +XXX,XX @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
148
#define HCR_TWEDEN (1ULL << 59)
149
#define HCR_TWEDEL MAKE_64BIT_MASK(60, 4)
150
151
-#define HCRX_ENAS0 (1ULL << 0)
152
-#define HCRX_ENALS (1ULL << 1)
153
-#define HCRX_ENASR (1ULL << 2)
154
-#define HCRX_FNXS (1ULL << 3)
155
-#define HCRX_FGTNXS (1ULL << 4)
156
-#define HCRX_SMPME (1ULL << 5)
157
-#define HCRX_TALLINT (1ULL << 6)
158
-#define HCRX_VINMI (1ULL << 7)
159
-#define HCRX_VFNMI (1ULL << 8)
160
-#define HCRX_CMOW (1ULL << 9)
161
-#define HCRX_MCE2 (1ULL << 10)
162
-#define HCRX_MSCEN (1ULL << 11)
163
-
164
-#define HPFAR_NS (1ULL << 63)
165
-
166
#define SCR_NS (1ULL << 0)
167
#define SCR_IRQ (1ULL << 1)
168
#define SCR_FIQ (1ULL << 2)
169
@@ -XXX,XX +XXX,XX @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
170
#define SCR_GPF (1ULL << 48)
171
#define SCR_NSE (1ULL << 62)
172
173
-#define HSTR_TTEE (1 << 16)
174
-#define HSTR_TJDBX (1 << 17)
175
-
176
-#define CNTHCTL_CNTVMASK (1 << 18)
177
-#define CNTHCTL_CNTPMASK (1 << 19)
178
-
179
/* Return the current FPSCR value. */
180
uint32_t vfp_get_fpscr(CPUARMState *env);
181
void vfp_set_fpscr(CPUARMState *env, uint32_t val);
182
diff --git a/target/arm/internals.h b/target/arm/internals.h
49
index XXXXXXX..XXXXXXX 100644
183
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/syndrome.h
184
--- a/target/arm/internals.h
51
+++ b/target/arm/syndrome.h
185
+++ b/target/arm/internals.h
52
@@ -XXX,XX +XXX,XX @@ static inline uint32_t syn_wfx(int cv, int cond, int ti, bool is_16bit)
186
@@ -XXX,XX +XXX,XX @@ FIELD(DBGWCR, WT, 20, 1)
53
(cv << 24) | (cond << 20) | ti;
187
FIELD(DBGWCR, MASK, 24, 5)
54
}
188
FIELD(DBGWCR, SSCE, 29, 1)
55
189
56
+static inline uint32_t syn_illegalstate(void)
190
+#define VTCR_NSW (1u << 29)
57
+{
191
+#define VTCR_NSA (1u << 30)
58
+ return (EC_ILLEGALSTATE << ARM_EL_EC_SHIFT) | ARM_EL_IL;
192
+#define VSTCR_SW VTCR_NSW
59
+}
193
+#define VSTCR_SA VTCR_NSA
60
+
194
+
61
#endif /* TARGET_ARM_SYNDROME_H */
195
+/* Bit definitions for CPACR (AArch32 only) */
62
diff --git a/target/arm/translate.h b/target/arm/translate.h
196
+FIELD(CPACR, CP10, 20, 2)
63
index XXXXXXX..XXXXXXX 100644
197
+FIELD(CPACR, CP11, 22, 2)
64
--- a/target/arm/translate.h
198
+FIELD(CPACR, TRCDIS, 28, 1) /* matches CPACR_EL1.TTA */
65
+++ b/target/arm/translate.h
199
+FIELD(CPACR, D32DIS, 30, 1) /* up to v7; RAZ in v8 */
66
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
200
+FIELD(CPACR, ASEDIS, 31, 1)
67
bool hstr_active;
201
+
68
/* True if memory operations require alignment */
202
+/* Bit definitions for CPACR_EL1 (AArch64 only) */
69
bool align_mem;
203
+FIELD(CPACR_EL1, ZEN, 16, 2)
70
+ /* True if PSTATE.IL is set */
204
+FIELD(CPACR_EL1, FPEN, 20, 2)
71
+ bool pstate_il;
205
+FIELD(CPACR_EL1, SMEN, 24, 2)
72
/*
206
+FIELD(CPACR_EL1, TTA, 28, 1) /* matches CPACR.TRCDIS */
73
* >= 0, a copy of PSTATE.BTYPE, which will be 0 without v8.5-BTI.
207
+
74
* < 0, set by the current instruction.
208
+/* Bit definitions for HCPTR (AArch32 only) */
75
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
209
+FIELD(HCPTR, TCP10, 10, 1)
76
index XXXXXXX..XXXXXXX 100644
210
+FIELD(HCPTR, TCP11, 11, 1)
77
--- a/target/arm/helper-a64.c
211
+FIELD(HCPTR, TASE, 15, 1)
78
+++ b/target/arm/helper-a64.c
212
+FIELD(HCPTR, TTA, 20, 1)
79
@@ -XXX,XX +XXX,XX @@ illegal_return:
213
+FIELD(HCPTR, TAM, 30, 1) /* matches CPTR_EL2.TAM */
80
if (!arm_singlestep_active(env)) {
214
+FIELD(HCPTR, TCPAC, 31, 1) /* matches CPTR_EL2.TCPAC */
81
env->pstate &= ~PSTATE_SS;
215
+
82
}
216
+/* Bit definitions for CPTR_EL2 (AArch64 only) */
83
+ helper_rebuild_hflags_a64(env, cur_el);
217
+FIELD(CPTR_EL2, TZ, 8, 1) /* !E2H */
84
qemu_log_mask(LOG_GUEST_ERROR, "Illegal exception return at EL%d: "
218
+FIELD(CPTR_EL2, TFP, 10, 1) /* !E2H, matches HCPTR.TCP10 */
85
"resuming execution at 0x%" PRIx64 "\n", cur_el, env->pc);
219
+FIELD(CPTR_EL2, TSM, 12, 1) /* !E2H */
86
}
220
+FIELD(CPTR_EL2, ZEN, 16, 2) /* E2H */
87
diff --git a/target/arm/helper.c b/target/arm/helper.c
221
+FIELD(CPTR_EL2, FPEN, 20, 2) /* E2H */
88
index XXXXXXX..XXXXXXX 100644
222
+FIELD(CPTR_EL2, SMEN, 24, 2) /* E2H */
89
--- a/target/arm/helper.c
223
+FIELD(CPTR_EL2, TTA, 28, 1)
90
+++ b/target/arm/helper.c
224
+FIELD(CPTR_EL2, TAM, 30, 1) /* matches HCPTR.TAM */
91
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el,
225
+FIELD(CPTR_EL2, TCPAC, 31, 1) /* matches HCPTR.TCPAC */
92
DP_TBFLAG_A32(flags, HSTR_ACTIVE, 1);
226
+
93
}
227
+/* Bit definitions for CPTR_EL3 (AArch64 only) */
94
228
+FIELD(CPTR_EL3, EZ, 8, 1)
95
+ if (env->uncached_cpsr & CPSR_IL) {
229
+FIELD(CPTR_EL3, TFP, 10, 1)
96
+ DP_TBFLAG_ANY(flags, PSTATE__IL, 1);
230
+FIELD(CPTR_EL3, ESM, 12, 1)
97
+ }
231
+FIELD(CPTR_EL3, TTA, 20, 1)
98
+
232
+FIELD(CPTR_EL3, TAM, 30, 1)
99
return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
233
+FIELD(CPTR_EL3, TCPAC, 31, 1)
100
}
234
+
101
235
+#define MDCR_MTPME (1U << 28)
102
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
236
+#define MDCR_TDCC (1U << 27)
103
}
237
+#define MDCR_HLP (1U << 26) /* MDCR_EL2 */
104
}
238
+#define MDCR_SCCD (1U << 23) /* MDCR_EL3 */
105
239
+#define MDCR_HCCD (1U << 23) /* MDCR_EL2 */
106
+ if (env->pstate & PSTATE_IL) {
240
+#define MDCR_EPMAD (1U << 21)
107
+ DP_TBFLAG_ANY(flags, PSTATE__IL, 1);
241
+#define MDCR_EDAD (1U << 20)
108
+ }
242
+#define MDCR_TTRF (1U << 19)
109
+
243
+#define MDCR_STE (1U << 18) /* MDCR_EL3 */
110
if (cpu_isar_feature(aa64_mte, env_archcpu(env))) {
244
+#define MDCR_SPME (1U << 17) /* MDCR_EL3 */
111
/*
245
+#define MDCR_HPMD (1U << 17) /* MDCR_EL2 */
112
* Set MTE_ACTIVE if any access may be Checked, and leave clear
246
+#define MDCR_SDD (1U << 16)
113
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
247
+#define MDCR_SPD (3U << 14)
114
index XXXXXXX..XXXXXXX 100644
248
+#define MDCR_TDRA (1U << 11)
115
--- a/target/arm/translate-a64.c
249
+#define MDCR_TDOSA (1U << 10)
116
+++ b/target/arm/translate-a64.c
250
+#define MDCR_TDA (1U << 9)
117
@@ -XXX,XX +XXX,XX @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
251
+#define MDCR_TDE (1U << 8)
118
s->fp_access_checked = false;
252
+#define MDCR_HPME (1U << 7)
119
s->sve_access_checked = false;
253
+#define MDCR_TPM (1U << 6)
120
254
+#define MDCR_TPMCR (1U << 5)
121
+ if (s->pstate_il) {
255
+#define MDCR_HPMN (0x1fU)
122
+ /*
256
+
123
+ * Illegal execution state. This has priority over BTI
257
+/* Not all of the MDCR_EL3 bits are present in the 32-bit SDCR */
124
+ * exceptions, but comes after instruction abort exceptions.
258
+#define SDCR_VALID_MASK (MDCR_MTPME | MDCR_TDCC | MDCR_SCCD | \
125
+ */
259
+ MDCR_EPMAD | MDCR_EDAD | MDCR_TTRF | \
126
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
260
+ MDCR_STE | MDCR_SPME | MDCR_SPD)
127
+ syn_illegalstate(), default_exception_el(s));
261
+
128
+ return;
262
+#define TTBCR_N (7U << 0) /* TTBCR.EAE==0 */
129
+ }
263
+#define TTBCR_T0SZ (7U << 0) /* TTBCR.EAE==1 */
130
+
264
+#define TTBCR_PD0 (1U << 4)
131
if (dc_isar_feature(aa64_bti, s)) {
265
+#define TTBCR_PD1 (1U << 5)
132
if (s->base.num_insns == 1) {
266
+#define TTBCR_EPD0 (1U << 7)
133
/*
267
+#define TTBCR_IRGN0 (3U << 8)
134
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
268
+#define TTBCR_ORGN0 (3U << 10)
135
#endif
269
+#define TTBCR_SH0 (3U << 12)
136
dc->fp_excp_el = EX_TBFLAG_ANY(tb_flags, FPEXC_EL);
270
+#define TTBCR_T1SZ (3U << 16)
137
dc->align_mem = EX_TBFLAG_ANY(tb_flags, ALIGN_MEM);
271
+#define TTBCR_A1 (1U << 22)
138
+ dc->pstate_il = EX_TBFLAG_ANY(tb_flags, PSTATE__IL);
272
+#define TTBCR_EPD1 (1U << 23)
139
dc->sve_excp_el = EX_TBFLAG_A64(tb_flags, SVEEXC_EL);
273
+#define TTBCR_IRGN1 (3U << 24)
140
dc->sve_len = (EX_TBFLAG_A64(tb_flags, ZCR_LEN) + 1) * 16;
274
+#define TTBCR_ORGN1 (3U << 26)
141
dc->pauth_active = EX_TBFLAG_A64(tb_flags, PAUTH_ACTIVE);
275
+#define TTBCR_SH1 (1U << 28)
142
diff --git a/target/arm/translate.c b/target/arm/translate.c
276
+#define TTBCR_EAE (1U << 31)
143
index XXXXXXX..XXXXXXX 100644
277
+
144
--- a/target/arm/translate.c
278
+FIELD(VTCR, T0SZ, 0, 6)
145
+++ b/target/arm/translate.c
279
+FIELD(VTCR, SL0, 6, 2)
146
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
280
+FIELD(VTCR, IRGN0, 8, 2)
147
return;
281
+FIELD(VTCR, ORGN0, 10, 2)
148
}
282
+FIELD(VTCR, SH0, 12, 2)
149
283
+FIELD(VTCR, TG0, 14, 2)
150
+ if (s->pstate_il) {
284
+FIELD(VTCR, PS, 16, 3)
151
+ /*
285
+FIELD(VTCR, VS, 19, 1)
152
+ * Illegal execution state. This has priority over BTI
286
+FIELD(VTCR, HA, 21, 1)
153
+ * exceptions, but comes after instruction abort exceptions.
287
+FIELD(VTCR, HD, 22, 1)
154
+ */
288
+FIELD(VTCR, HWU59, 25, 1)
155
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
289
+FIELD(VTCR, HWU60, 26, 1)
156
+ syn_illegalstate(), default_exception_el(s));
290
+FIELD(VTCR, HWU61, 27, 1)
157
+ return;
291
+FIELD(VTCR, HWU62, 28, 1)
158
+ }
292
+FIELD(VTCR, NSW, 29, 1)
159
+
293
+FIELD(VTCR, NSA, 30, 1)
160
if (cond == 0xf) {
294
+FIELD(VTCR, DS, 32, 1)
161
/* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
295
+FIELD(VTCR, SL2, 33, 1)
162
* choose to UNDEF. In ARMv5 and above the space is used
296
+
163
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
297
+#define HCRX_ENAS0 (1ULL << 0)
164
#endif
298
+#define HCRX_ENALS (1ULL << 1)
165
dc->fp_excp_el = EX_TBFLAG_ANY(tb_flags, FPEXC_EL);
299
+#define HCRX_ENASR (1ULL << 2)
166
dc->align_mem = EX_TBFLAG_ANY(tb_flags, ALIGN_MEM);
300
+#define HCRX_FNXS (1ULL << 3)
167
+ dc->pstate_il = EX_TBFLAG_ANY(tb_flags, PSTATE__IL);
301
+#define HCRX_FGTNXS (1ULL << 4)
168
302
+#define HCRX_SMPME (1ULL << 5)
169
if (arm_feature(env, ARM_FEATURE_M)) {
303
+#define HCRX_TALLINT (1ULL << 6)
170
dc->vfp_enabled = 1;
304
+#define HCRX_VINMI (1ULL << 7)
171
@@ -XXX,XX +XXX,XX @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
305
+#define HCRX_VFNMI (1ULL << 8)
172
}
306
+#define HCRX_CMOW (1ULL << 9)
173
dc->insn = insn;
307
+#define HCRX_MCE2 (1ULL << 10)
174
308
+#define HCRX_MSCEN (1ULL << 11)
175
+ if (dc->pstate_il) {
309
+
176
+ /*
310
+#define HPFAR_NS (1ULL << 63)
177
+ * Illegal execution state. This has priority over BTI
311
+
178
+ * exceptions, but comes after instruction abort exceptions.
312
+#define HSTR_TTEE (1 << 16)
179
+ */
313
+#define HSTR_TJDBX (1 << 17)
180
+ gen_exception_insn(dc, dc->pc_curr, EXCP_UDEF,
314
+
181
+ syn_illegalstate(), default_exception_el(dc));
315
+#define CNTHCTL_CNTVMASK (1 << 18)
182
+ return;
316
+#define CNTHCTL_CNTPMASK (1 << 19)
183
+ }
317
+
184
+
318
/* We use a few fake FSR values for internal purposes in M profile.
185
if (dc->eci) {
319
* M profile cores don't have A/R format FSRs, but currently our
186
/*
320
* get_phys_addr() code assumes A/R profile and reports failures via
187
* For M-profile continuable instructions, ECI/ICI handling
188
--
321
--
189
2.20.1
322
2.34.1
190
323
191
324
diff view generated by jsdifflib
1
The various MPS2 boards implemented in mps2.c have multiple I2C
1
The timer _EL02 registers should UNDEF for invalid accesses from EL2
2
buses: a bus dedicated to the audio configuration, one for the LCD
2
or EL3 when HCR_EL2.E2H == 0, not take a cp access trap. We were
3
touchscreen controller, and two which are connected to the external
3
delivering the exception to EL2 with the wrong syndrome.
4
Shield expansion connector. Mark the buses which are used only for
5
board-internal devices as 'full' so that if the user creates i2c
6
devices on the commandline without specifying a bus name then they
7
will be connected to the I2C controller used for the Shield
8
connector, where guest software will expect them.
9
4
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210903151435.22379-5-peter.maydell@linaro.org
7
Message-id: 20240301183219.2424889-3-peter.maydell@linaro.org
13
---
8
---
14
hw/arm/mps2.c | 12 +++++++++++-
9
target/arm/helper.c | 2 +-
15
1 file changed, 11 insertions(+), 1 deletion(-)
10
1 file changed, 1 insertion(+), 1 deletion(-)
16
11
17
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/mps2.c
14
--- a/target/arm/helper.c
20
+++ b/hw/arm/mps2.c
15
+++ b/target/arm/helper.c
21
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
16
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
22
0x40023000, /* Audio */
17
return CP_ACCESS_OK;
23
0x40029000, /* Shield0 */
24
0x4002a000}; /* Shield1 */
25
- sysbus_create_simple(TYPE_ARM_SBCON_I2C, i2cbase[i], NULL);
26
+ DeviceState *dev;
27
+
28
+ dev = sysbus_create_simple(TYPE_ARM_SBCON_I2C, i2cbase[i], NULL);
29
+ if (i < 2) {
30
+ /*
31
+ * internal-only bus: mark it full to avoid user-created
32
+ * i2c devices being plugged into it.
33
+ */
34
+ BusState *qbus = qdev_get_child_bus(dev, "i2c");
35
+ qbus_mark_full(qbus);
36
+ }
37
}
18
}
38
create_unimplemented_device("i2s", 0x40024000, 0x400);
19
if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
39
20
- return CP_ACCESS_TRAP;
21
+ return CP_ACCESS_TRAP_UNCATEGORIZED;
22
}
23
return CP_ACCESS_OK;
24
}
40
--
25
--
41
2.20.1
26
2.34.1
42
43
diff view generated by jsdifflib
1
The mps2-tz boards use a data-driven structure to create the devices
1
We prefer the FIELD macro over ad-hoc #defines for register bits;
2
that sit behind peripheral protection controllers. Currently the
2
switch CNTHCTL to that style before we add any more bits.
3
functions which create these devices are passed an 'opaque' pointer
4
which is always the address within the machine struct of the device
5
to create, and some "all devices need this" information like irqs and
6
addresses.
7
8
If a specific device needs more information than this, it is
9
currently not possible to pass that through from the PPCInfo
10
data structure. Add support for passing an extra data parameter,
11
so that we can more flexibly handle the needs of specific
12
device types. To provide some type-safety we make this extra
13
parameter a pointer to a union (which initially has no members).
14
15
In particular, we would like to be able to indicate which of the
16
i2c controllers are for on-board devices only and which are
17
connected to the external 'shield' expansion port; a subsequent
18
patch will use this mechanism for that purpose.
19
3
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
21
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
22
Message-id: 20210903151435.22379-3-peter.maydell@linaro.org
7
Message-id: 20240301183219.2424889-4-peter.maydell@linaro.org
23
---
8
---
24
hw/arm/mps2-tz.c | 35 ++++++++++++++++++++++-------------
9
target/arm/internals.h | 27 +++++++++++++++++++++++++--
25
1 file changed, 22 insertions(+), 13 deletions(-)
10
target/arm/helper.c | 9 ++++-----
11
2 files changed, 29 insertions(+), 7 deletions(-)
26
12
27
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
13
diff --git a/target/arm/internals.h b/target/arm/internals.h
28
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/arm/mps2-tz.c
15
--- a/target/arm/internals.h
30
+++ b/hw/arm/mps2-tz.c
16
+++ b/target/arm/internals.h
31
@@ -XXX,XX +XXX,XX @@ static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
17
@@ -XXX,XX +XXX,XX @@ FIELD(VTCR, SL2, 33, 1)
18
#define HSTR_TTEE (1 << 16)
19
#define HSTR_TJDBX (1 << 17)
20
21
-#define CNTHCTL_CNTVMASK (1 << 18)
22
-#define CNTHCTL_CNTPMASK (1 << 19)
23
+/*
24
+ * Depending on the value of HCR_EL2.E2H, bits 0 and 1
25
+ * have different bit definitions, and EL1PCTEN might be
26
+ * bit 0 or bit 10. We use _E2H1 and _E2H0 suffixes to
27
+ * disambiguate if necessary.
28
+ */
29
+FIELD(CNTHCTL, EL0PCTEN_E2H1, 0, 1)
30
+FIELD(CNTHCTL, EL0VCTEN_E2H1, 1, 1)
31
+FIELD(CNTHCTL, EL1PCTEN_E2H0, 0, 1)
32
+FIELD(CNTHCTL, EL1PCEN_E2H0, 1, 1)
33
+FIELD(CNTHCTL, EVNTEN, 2, 1)
34
+FIELD(CNTHCTL, EVNTDIR, 3, 1)
35
+FIELD(CNTHCTL, EVNTI, 4, 4)
36
+FIELD(CNTHCTL, EL0VTEN, 8, 1)
37
+FIELD(CNTHCTL, EL0PTEN, 9, 1)
38
+FIELD(CNTHCTL, EL1PCTEN_E2H1, 10, 1)
39
+FIELD(CNTHCTL, EL1PTEN, 11, 1)
40
+FIELD(CNTHCTL, ECV, 12, 1)
41
+FIELD(CNTHCTL, EL1TVT, 13, 1)
42
+FIELD(CNTHCTL, EL1TVCT, 14, 1)
43
+FIELD(CNTHCTL, EL1NVPCT, 15, 1)
44
+FIELD(CNTHCTL, EL1NVVCT, 16, 1)
45
+FIELD(CNTHCTL, EVNTIS, 17, 1)
46
+FIELD(CNTHCTL, CNTVMASK, 18, 1)
47
+FIELD(CNTHCTL, CNTPMASK, 19, 1)
48
49
/* We use a few fake FSR values for internal purposes in M profile.
50
* M profile cores don't have A/R format FSRs, but currently our
51
diff --git a/target/arm/helper.c b/target/arm/helper.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/helper.c
54
+++ b/target/arm/helper.c
55
@@ -XXX,XX +XXX,XX @@ static void gt_update_irq(ARMCPU *cpu, int timeridx)
56
* It is RES0 in Secure and NonSecure state.
57
*/
58
if ((ss == ARMSS_Root || ss == ARMSS_Realm) &&
59
- ((timeridx == GTIMER_VIRT && (cnthctl & CNTHCTL_CNTVMASK)) ||
60
- (timeridx == GTIMER_PHYS && (cnthctl & CNTHCTL_CNTPMASK)))) {
61
+ ((timeridx == GTIMER_VIRT && (cnthctl & R_CNTHCTL_CNTVMASK_MASK)) ||
62
+ (timeridx == GTIMER_PHYS && (cnthctl & R_CNTHCTL_CNTPMASK_MASK)))) {
63
irqstate = 0;
64
}
65
66
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
67
{
68
ARMCPU *cpu = env_archcpu(env);
69
uint32_t oldval = env->cp15.cnthctl_el2;
70
-
71
raw_write(env, ri, value);
72
73
- if ((oldval ^ value) & CNTHCTL_CNTVMASK) {
74
+ if ((oldval ^ value) & R_CNTHCTL_CNTVMASK_MASK) {
75
gt_update_irq(cpu, GTIMER_VIRT);
76
- } else if ((oldval ^ value) & CNTHCTL_CNTPMASK) {
77
+ } else if ((oldval ^ value) & R_CNTHCTL_CNTPMASK_MASK) {
78
gt_update_irq(cpu, GTIMER_PHYS);
32
}
79
}
33
}
80
}
34
35
+/* Union describing the device-specific extra data we pass to the devfn. */
36
+typedef union PPCExtraData {
37
+} PPCExtraData;
38
+
39
/* Most of the devices in the AN505 FPGA image sit behind
40
* Peripheral Protection Controllers. These data structures
41
* define the layout of which devices sit behind which PPCs.
42
@@ -XXX,XX +XXX,XX @@ static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
43
*/
44
typedef MemoryRegion *MakeDevFn(MPS2TZMachineState *mms, void *opaque,
45
const char *name, hwaddr size,
46
- const int *irqs);
47
+ const int *irqs,
48
+ const PPCExtraData *extradata);
49
50
typedef struct PPCPortInfo {
51
const char *name;
52
@@ -XXX,XX +XXX,XX @@ typedef struct PPCPortInfo {
53
hwaddr addr;
54
hwaddr size;
55
int irqs[3]; /* currently no device needs more IRQ lines than this */
56
+ PPCExtraData extradata; /* to pass device-specific info to the devfn */
57
} PPCPortInfo;
58
59
typedef struct PPCInfo {
60
@@ -XXX,XX +XXX,XX @@ typedef struct PPCInfo {
61
static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
62
void *opaque,
63
const char *name, hwaddr size,
64
- const int *irqs)
65
+ const int *irqs,
66
+ const PPCExtraData *extradata)
67
{
68
/* Initialize, configure and realize a TYPE_UNIMPLEMENTED_DEVICE,
69
* and return a pointer to its MemoryRegion.
70
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
71
72
static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
73
const char *name, hwaddr size,
74
- const int *irqs)
75
+ const int *irqs, const PPCExtraData *extradata)
76
{
77
/* The irq[] array is tx, rx, combined, in that order */
78
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
79
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
80
81
static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
82
const char *name, hwaddr size,
83
- const int *irqs)
84
+ const int *irqs, const PPCExtraData *extradata)
85
{
86
MPS2SCC *scc = opaque;
87
DeviceState *sccdev;
88
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
89
90
static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
91
const char *name, hwaddr size,
92
- const int *irqs)
93
+ const int *irqs, const PPCExtraData *extradata)
94
{
95
MPS2FPGAIO *fpgaio = opaque;
96
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
97
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
98
99
static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
100
const char *name, hwaddr size,
101
- const int *irqs)
102
+ const int *irqs,
103
+ const PPCExtraData *extradata)
104
{
105
SysBusDevice *s;
106
NICInfo *nd = &nd_table[0];
107
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
108
109
static MemoryRegion *make_eth_usb(MPS2TZMachineState *mms, void *opaque,
110
const char *name, hwaddr size,
111
- const int *irqs)
112
+ const int *irqs,
113
+ const PPCExtraData *extradata)
114
{
115
/*
116
* The AN524 makes the ethernet and USB share a PPC port.
117
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_usb(MPS2TZMachineState *mms, void *opaque,
118
119
static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
120
const char *name, hwaddr size,
121
- const int *irqs)
122
+ const int *irqs, const PPCExtraData *extradata)
123
{
124
TZMPC *mpc = opaque;
125
int i = mpc - &mms->mpc[0];
126
@@ -XXX,XX +XXX,XX @@ static void remap_irq_fn(void *opaque, int n, int level)
127
128
static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
129
const char *name, hwaddr size,
130
- const int *irqs)
131
+ const int *irqs, const PPCExtraData *extradata)
132
{
133
/* The irq[] array is DMACINTR, DMACINTERR, DMACINTTC, in that order */
134
PL080State *dma = opaque;
135
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
136
137
static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
138
const char *name, hwaddr size,
139
- const int *irqs)
140
+ const int *irqs, const PPCExtraData *extradata)
141
{
142
/*
143
* The AN505 has five PL022 SPI controllers.
144
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
145
146
static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
147
const char *name, hwaddr size,
148
- const int *irqs)
149
+ const int *irqs, const PPCExtraData *extradata)
150
{
151
ArmSbconI2CState *i2c = opaque;
152
SysBusDevice *s;
153
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
154
155
static MemoryRegion *make_rtc(MPS2TZMachineState *mms, void *opaque,
156
const char *name, hwaddr size,
157
- const int *irqs)
158
+ const int *irqs, const PPCExtraData *extradata)
159
{
160
PL031State *pl031 = opaque;
161
SysBusDevice *s;
162
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
163
}
164
165
mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size,
166
- pinfo->irqs);
167
+ pinfo->irqs, &pinfo->extradata);
168
portname = g_strdup_printf("port[%d]", port);
169
object_property_set_link(OBJECT(ppc), portname, OBJECT(mr),
170
&error_fatal);
171
--
81
--
172
2.20.1
82
2.34.1
173
83
174
84
diff view generated by jsdifflib
1
The various MPS2 boards have multiple I2C buses: typically a bus
1
Don't allow the guest to write CNTHCTL_EL2 bits which don't exist.
2
dedicated to the audio configuration, one for the LCD touchscreen
2
This is not strictly architecturally required, but it is how we've
3
controller, one for a DDR4 EEPROM, and two which are connected to the
3
tended to implement registers more recently.
4
external Shield expansion connector. Mark the buses which are used
4
5
only for board-internal devices as 'full' so that if the user creates
5
In particular, bits [19:18] are only present with FEAT_RME,
6
i2c devices on the commandline without specifying a bus name then
6
and bits [17:12] will only be present with FEAT_ECV.
7
they will be connected to the I2C controller used for the Shield
8
connector, where guest software will expect them.
9
7
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210903151435.22379-4-peter.maydell@linaro.org
10
Message-id: 20240301183219.2424889-5-peter.maydell@linaro.org
13
---
11
---
14
hw/arm/mps2-tz.c | 57 ++++++++++++++++++++++++++++++++++++------------
12
target/arm/helper.c | 18 ++++++++++++++++++
15
1 file changed, 43 insertions(+), 14 deletions(-)
13
1 file changed, 18 insertions(+)
16
14
17
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/mps2-tz.c
17
--- a/target/arm/helper.c
20
+++ b/hw/arm/mps2-tz.c
18
+++ b/target/arm/helper.c
21
@@ -XXX,XX +XXX,XX @@ static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
19
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
22
20
{
23
/* Union describing the device-specific extra data we pass to the devfn. */
21
ARMCPU *cpu = env_archcpu(env);
24
typedef union PPCExtraData {
22
uint32_t oldval = env->cp15.cnthctl_el2;
25
+ bool i2c_internal;
23
+ uint32_t valid_mask =
26
} PPCExtraData;
24
+ R_CNTHCTL_EL0PCTEN_E2H1_MASK |
27
25
+ R_CNTHCTL_EL0VCTEN_E2H1_MASK |
28
/* Most of the devices in the AN505 FPGA image sit behind
26
+ R_CNTHCTL_EVNTEN_MASK |
29
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
27
+ R_CNTHCTL_EVNTDIR_MASK |
30
object_initialize_child(OBJECT(mms), name, i2c, TYPE_ARM_SBCON_I2C);
28
+ R_CNTHCTL_EVNTI_MASK |
31
s = SYS_BUS_DEVICE(i2c);
29
+ R_CNTHCTL_EL0VTEN_MASK |
32
sysbus_realize(s, &error_fatal);
30
+ R_CNTHCTL_EL0PTEN_MASK |
31
+ R_CNTHCTL_EL1PCTEN_E2H1_MASK |
32
+ R_CNTHCTL_EL1PTEN_MASK;
33
+
33
+
34
+ /*
34
+ if (cpu_isar_feature(aa64_rme, cpu)) {
35
+ * If this is an internal-use-only i2c bus, mark it full
35
+ valid_mask |= R_CNTHCTL_CNTVMASK_MASK | R_CNTHCTL_CNTPMASK_MASK;
36
+ * so that user-created i2c devices are not plugged into it.
37
+ * If we implement models of any on-board i2c devices that
38
+ * plug in to one of the internal-use-only buses, then we will
39
+ * need to create and plugging those in here before we mark the
40
+ * bus as full.
41
+ */
42
+ if (extradata->i2c_internal) {
43
+ BusState *qbus = qdev_get_child_bus(DEVICE(i2c), "i2c");
44
+ qbus_mark_full(qbus);
45
+ }
36
+ }
46
+
37
+
47
return sysbus_mmio_get_region(s, 0);
38
+ /* Clear RES0 bits */
48
}
39
+ value &= valid_mask;
49
40
+
50
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
41
raw_write(env, ri, value);
51
{ "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000, { 36, 37, 44 } },
42
52
{ "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000, { 38, 39, 45 } },
43
if ((oldval ^ value) & R_CNTHCTL_CNTVMASK_MASK) {
53
{ "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000, { 40, 41, 46 } },
54
- { "i2c0", make_i2c, &mms->i2c[0], 0x40207000, 0x1000 },
55
- { "i2c1", make_i2c, &mms->i2c[1], 0x40208000, 0x1000 },
56
- { "i2c2", make_i2c, &mms->i2c[2], 0x4020c000, 0x1000 },
57
- { "i2c3", make_i2c, &mms->i2c[3], 0x4020d000, 0x1000 },
58
+ { "i2c0", make_i2c, &mms->i2c[0], 0x40207000, 0x1000, {},
59
+ { .i2c_internal = true /* touchscreen */ } },
60
+ { "i2c1", make_i2c, &mms->i2c[1], 0x40208000, 0x1000, {},
61
+ { .i2c_internal = true /* audio conf */ } },
62
+ { "i2c2", make_i2c, &mms->i2c[2], 0x4020c000, 0x1000, {},
63
+ { .i2c_internal = false /* shield 0 */ } },
64
+ { "i2c3", make_i2c, &mms->i2c[3], 0x4020d000, 0x1000, {},
65
+ { .i2c_internal = false /* shield 1 */ } },
66
},
67
}, {
68
.name = "apb_ppcexp2",
69
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
70
}, {
71
.name = "apb_ppcexp1",
72
.ports = {
73
- { "i2c0", make_i2c, &mms->i2c[0], 0x41200000, 0x1000 },
74
- { "i2c1", make_i2c, &mms->i2c[1], 0x41201000, 0x1000 },
75
+ { "i2c0", make_i2c, &mms->i2c[0], 0x41200000, 0x1000, {},
76
+ { .i2c_internal = true /* touchscreen */ } },
77
+ { "i2c1", make_i2c, &mms->i2c[1], 0x41201000, 0x1000, {},
78
+ { .i2c_internal = true /* audio conf */ } },
79
{ "spi0", make_spi, &mms->spi[0], 0x41202000, 0x1000, { 52 } },
80
{ "spi1", make_spi, &mms->spi[1], 0x41203000, 0x1000, { 53 } },
81
{ "spi2", make_spi, &mms->spi[2], 0x41204000, 0x1000, { 54 } },
82
- { "i2c2", make_i2c, &mms->i2c[2], 0x41205000, 0x1000 },
83
- { "i2c3", make_i2c, &mms->i2c[3], 0x41206000, 0x1000 },
84
+ { "i2c2", make_i2c, &mms->i2c[2], 0x41205000, 0x1000, {},
85
+ { .i2c_internal = false /* shield 0 */ } },
86
+ { "i2c3", make_i2c, &mms->i2c[3], 0x41206000, 0x1000, {},
87
+ { .i2c_internal = false /* shield 1 */ } },
88
{ /* port 7 reserved */ },
89
- { "i2c4", make_i2c, &mms->i2c[4], 0x41208000, 0x1000 },
90
+ { "i2c4", make_i2c, &mms->i2c[4], 0x41208000, 0x1000, {},
91
+ { .i2c_internal = true /* DDR4 EEPROM */ } },
92
},
93
}, {
94
.name = "apb_ppcexp2",
95
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
96
}, {
97
.name = "apb_ppcexp1",
98
.ports = {
99
- { "i2c0", make_i2c, &mms->i2c[0], 0x49200000, 0x1000 },
100
- { "i2c1", make_i2c, &mms->i2c[1], 0x49201000, 0x1000 },
101
+ { "i2c0", make_i2c, &mms->i2c[0], 0x49200000, 0x1000, {},
102
+ { .i2c_internal = true /* touchscreen */ } },
103
+ { "i2c1", make_i2c, &mms->i2c[1], 0x49201000, 0x1000, {},
104
+ { .i2c_internal = true /* audio conf */ } },
105
{ "spi0", make_spi, &mms->spi[0], 0x49202000, 0x1000, { 53 } },
106
{ "spi1", make_spi, &mms->spi[1], 0x49203000, 0x1000, { 54 } },
107
{ "spi2", make_spi, &mms->spi[2], 0x49204000, 0x1000, { 55 } },
108
- { "i2c2", make_i2c, &mms->i2c[2], 0x49205000, 0x1000 },
109
- { "i2c3", make_i2c, &mms->i2c[3], 0x49206000, 0x1000 },
110
+ { "i2c2", make_i2c, &mms->i2c[2], 0x49205000, 0x1000, {},
111
+ { .i2c_internal = false /* shield 0 */ } },
112
+ { "i2c3", make_i2c, &mms->i2c[3], 0x49206000, 0x1000, {},
113
+ { .i2c_internal = false /* shield 1 */ } },
114
{ /* port 7 reserved */ },
115
- { "i2c4", make_i2c, &mms->i2c[4], 0x49208000, 0x1000 },
116
+ { "i2c4", make_i2c, &mms->i2c[4], 0x49208000, 0x1000, {},
117
+ { .i2c_internal = true /* DDR4 EEPROM */ } },
118
},
119
}, {
120
.name = "apb_ppcexp2",
121
--
44
--
122
2.20.1
45
2.34.1
123
124
diff view generated by jsdifflib
1
From: Shashi Mallela <shashi.mallela@linaro.org>
1
The functionality defined by ID_AA64MMFR0_EL1.ECV == 1 is:
2
* four new trap bits for various counter and timer registers
3
* the CNTHCTL_EL2.EVNTIS and CNTKCTL_EL1.EVNTIS bits which control
4
scaling of the event stream. This is a no-op for us, because we don't
5
implement the event stream (our WFE is a NOP): all we need to do is
6
allow CNTHCTL_EL2.ENVTIS to be read and written.
7
* extensions to PMSCR_EL1.PCT, PMSCR_EL2.PCT, TRFCR_EL1.TS and
8
TRFCR_EL2.TS: these are all no-ops for us, because we don't implement
9
FEAT_SPE or FEAT_TRF.
10
* new registers CNTPCTSS_EL0 and NCTVCTSS_EL0 which are
11
"self-sychronizing" views of the CNTPCT_EL0 and CNTVCT_EL0, meaning
12
that no barriers are needed around their accesses. For us these
13
are just the same as the normal views, because all our sysregs are
14
inherently self-sychronizing.
2
15
3
Implemented lpi processing at redistributor to get lpi config info
16
In this commit we implement the trap handling and permit the new
4
from lpi configuration table,determine priority,set pending state in
17
CNTHCTL_EL2 bits to be written.
5
lpi pending table and forward the lpi to cpuif.Added logic to invoke
6
redistributor lpi processing with translated LPI which set/clear LPI
7
from ITS device as part of ITS INT,CLEAR,DISCARD command and
8
GITS_TRANSLATER processing.
9
18
10
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
11
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Message-id: 20210910143951.92242-7-shashi.mallela@linaro.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20240301183219.2424889-6-peter.maydell@linaro.org
15
---
22
---
16
hw/intc/gicv3_internal.h | 9 ++
23
target/arm/cpu-features.h | 5 ++++
17
include/hw/intc/arm_gicv3_common.h | 7 ++
24
target/arm/helper.c | 51 +++++++++++++++++++++++++++++++++++----
18
hw/intc/arm_gicv3.c | 14 +++
25
2 files changed, 51 insertions(+), 5 deletions(-)
19
hw/intc/arm_gicv3_common.c | 1 +
20
hw/intc/arm_gicv3_cpuif.c | 7 +-
21
hw/intc/arm_gicv3_its.c | 23 +++++
22
hw/intc/arm_gicv3_redist.c | 141 +++++++++++++++++++++++++++++
23
7 files changed, 200 insertions(+), 2 deletions(-)
24
26
25
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
27
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
26
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/intc/gicv3_internal.h
29
--- a/target/arm/cpu-features.h
28
+++ b/hw/intc/gicv3_internal.h
30
+++ b/target/arm/cpu-features.h
29
@@ -XXX,XX +XXX,XX @@ FIELD(GICR_PENDBASER, PHYADDR, 16, 36)
31
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_fgt(const ARMISARegisters *id)
30
FIELD(GICR_PENDBASER, OUTERCACHE, 56, 3)
32
return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, FGT) != 0;
31
FIELD(GICR_PENDBASER, PTZ, 62, 1)
33
}
32
34
33
+#define GICR_PROPBASER_IDBITS_THRESHOLD 0xd
35
+static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id)
36
+{
37
+ return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 0;
38
+}
34
+
39
+
35
#define ICC_CTLR_EL1_CBPR (1U << 0)
40
static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
36
#define ICC_CTLR_EL1_EOIMODE (1U << 1)
41
{
37
#define ICC_CTLR_EL1_PMHE (1U << 6)
42
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
38
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1)
43
diff --git a/target/arm/helper.c b/target/arm/helper.c
39
40
#define L1TABLE_ENTRY_SIZE 8
41
42
+#define LPI_CTE_ENABLED TABLE_ENTRY_VALID_MASK
43
+#define LPI_PRIORITY_MASK 0xfc
44
+
45
#define GITS_CMDQ_ENTRY_SIZE 32
46
#define NUM_BYTES_IN_DW 8
47
48
@@ -XXX,XX +XXX,XX @@ FIELD(MAPC, RDBASE, 16, 32)
49
* Valid = 1 bit,RDBase = 36 bits(considering max RDBASE)
50
*/
51
#define GITS_CTE_SIZE (0x8ULL)
52
+#define GITS_CTE_RDBASE_PROCNUM_MASK MAKE_64BIT_MASK(1, RDBASE_PROCNUM_LENGTH)
53
54
/* Special interrupt IDs */
55
#define INTID_SECURE 1020
56
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
57
unsigned size, MemTxAttrs attrs);
58
void gicv3_dist_set_irq(GICv3State *s, int irq, int level);
59
void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level);
60
+void gicv3_redist_process_lpi(GICv3CPUState *cs, int irq, int level);
61
+void gicv3_redist_lpi_pending(GICv3CPUState *cs, int irq, int level);
62
+void gicv3_redist_update_lpi(GICv3CPUState *cs);
63
void gicv3_redist_send_sgi(GICv3CPUState *cs, int grp, int irq, bool ns);
64
void gicv3_init_cpuif(GICv3State *s);
65
66
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
67
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
68
--- a/include/hw/intc/arm_gicv3_common.h
45
--- a/target/arm/helper.c
69
+++ b/include/hw/intc/arm_gicv3_common.h
46
+++ b/target/arm/helper.c
70
@@ -XXX,XX +XXX,XX @@ struct GICv3CPUState {
47
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_counter_access(CPUARMState *env, int timeridx,
71
* real state above; it doesn't need to be migrated.
48
: !extract32(env->cp15.cnthctl_el2, 0, 1))) {
72
*/
49
return CP_ACCESS_TRAP_EL2;
73
PendingIrq hppi;
50
}
74
+
51
+ if (has_el2 && timeridx == GTIMER_VIRT) {
75
+ /*
52
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1TVCT)) {
76
+ * Cached information recalculated from LPI tables
53
+ return CP_ACCESS_TRAP_EL2;
77
+ * in guest memory
54
+ }
78
+ */
55
+ }
79
+ PendingIrq hpplpi;
56
break;
80
+
81
/* This is temporary working state, to avoid a malloc in gicv3_update() */
82
bool seenbetter;
83
};
84
diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/hw/intc/arm_gicv3.c
87
+++ b/hw/intc/arm_gicv3.c
88
@@ -XXX,XX +XXX,XX @@ static void gicv3_redist_update_noirqset(GICv3CPUState *cs)
89
cs->hppi.grp = gicv3_irq_group(cs->gic, cs, cs->hppi.irq);
90
}
57
}
91
58
return CP_ACCESS_OK;
92
+ if ((cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) && cs->gic->lpi_enable &&
59
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_timer_access(CPUARMState *env, int timeridx,
93
+ (cs->hpplpi.prio != 0xff)) {
60
}
94
+ if (irqbetter(cs, cs->hpplpi.irq, cs->hpplpi.prio)) {
61
}
95
+ cs->hppi.irq = cs->hpplpi.irq;
62
}
96
+ cs->hppi.prio = cs->hpplpi.prio;
63
+ if (has_el2 && timeridx == GTIMER_VIRT) {
97
+ cs->hppi.grp = cs->hpplpi.grp;
64
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1TVT)) {
98
+ seenbetter = true;
65
+ return CP_ACCESS_TRAP_EL2;
66
+ }
67
+ }
68
break;
69
}
70
return CP_ACCESS_OK;
71
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
72
if (cpu_isar_feature(aa64_rme, cpu)) {
73
valid_mask |= R_CNTHCTL_CNTVMASK_MASK | R_CNTHCTL_CNTPMASK_MASK;
74
}
75
+ if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
76
+ valid_mask |=
77
+ R_CNTHCTL_EL1TVT_MASK |
78
+ R_CNTHCTL_EL1TVCT_MASK |
79
+ R_CNTHCTL_EL1NVPCT_MASK |
80
+ R_CNTHCTL_EL1NVVCT_MASK |
81
+ R_CNTHCTL_EVNTIS_MASK;
82
+ }
83
84
/* Clear RES0 bits */
85
value &= valid_mask;
86
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
87
{
88
if (arm_current_el(env) == 1) {
89
/* This must be a FEAT_NV access */
90
- /* TODO: FEAT_ECV will need to check CNTHCTL_EL2 here */
91
return CP_ACCESS_OK;
92
}
93
if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
94
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
95
return CP_ACCESS_OK;
96
}
97
98
+static CPAccessResult access_el1nvpct(CPUARMState *env, const ARMCPRegInfo *ri,
99
+ bool isread)
100
+{
101
+ if (arm_current_el(env) == 1) {
102
+ /* This must be a FEAT_NV access with NVx == 101 */
103
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1NVPCT)) {
104
+ return CP_ACCESS_TRAP_EL2;
99
+ }
105
+ }
100
+ }
106
+ }
101
+
107
+ return e2h_access(env, ri, isread);
102
/* If the best interrupt we just found would preempt whatever
103
* was the previous best interrupt before this update, then
104
* we know it's definitely the best one now.
105
@@ -XXX,XX +XXX,XX @@ static void gicv3_set_irq(void *opaque, int irq, int level)
106
107
static void arm_gicv3_post_load(GICv3State *s)
108
{
109
+ int i;
110
/* Recalculate our cached idea of the current highest priority
111
* pending interrupt, but don't set IRQ or FIQ lines.
112
*/
113
+ for (i = 0; i < s->num_cpu; i++) {
114
+ gicv3_redist_update_lpi(&s->cpu[i]);
115
+ }
116
gicv3_full_update_noirqset(s);
117
/* Repopulate the cache of GICv3CPUState pointers for target CPUs */
118
gicv3_cache_all_target_cpustates(s);
119
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
120
index XXXXXXX..XXXXXXX 100644
121
--- a/hw/intc/arm_gicv3_common.c
122
+++ b/hw/intc/arm_gicv3_common.c
123
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_reset(DeviceState *dev)
124
memset(cs->gicr_ipriorityr, 0, sizeof(cs->gicr_ipriorityr));
125
126
cs->hppi.prio = 0xff;
127
+ cs->hpplpi.prio = 0xff;
128
129
/* State in the CPU interface must *not* be reset here, because it
130
* is part of the CPU's reset domain, not the GIC device's.
131
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
132
index XXXXXXX..XXXXXXX 100644
133
--- a/hw/intc/arm_gicv3_cpuif.c
134
+++ b/hw/intc/arm_gicv3_cpuif.c
135
@@ -XXX,XX +XXX,XX @@ static void icc_activate_irq(GICv3CPUState *cs, int irq)
136
cs->gicr_iactiver0 = deposit32(cs->gicr_iactiver0, irq, 1, 1);
137
cs->gicr_ipendr0 = deposit32(cs->gicr_ipendr0, irq, 1, 0);
138
gicv3_redist_update(cs);
139
- } else {
140
+ } else if (irq < GICV3_LPI_INTID_START) {
141
gicv3_gicd_active_set(cs->gic, irq);
142
gicv3_gicd_pending_clear(cs->gic, irq);
143
gicv3_update(cs->gic, irq, 1);
144
+ } else {
145
+ gicv3_redist_lpi_pending(cs, irq, 0);
146
}
147
}
148
149
@@ -XXX,XX +XXX,XX @@ static void icc_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
150
trace_gicv3_icc_eoir_write(is_eoir0 ? 0 : 1,
151
gicv3_redist_affid(cs), value);
152
153
- if (irq >= cs->gic->num_irq) {
154
+ if ((irq >= cs->gic->num_irq) &&
155
+ !(cs->gic->lpi_enable && (irq >= GICV3_LPI_INTID_START))) {
156
/* This handles two cases:
157
* 1. If software writes the ID of a spurious interrupt [ie 1020-1023]
158
* to the GICC_EOIR, the GIC ignores that write.
159
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/hw/intc/arm_gicv3_its.c
162
+++ b/hw/intc/arm_gicv3_its.c
163
@@ -XXX,XX +XXX,XX @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
164
uint64_t cte = 0;
165
bool cte_valid = false;
166
bool result = false;
167
+ uint64_t rdbase;
168
169
if (cmd == NONE) {
170
devid = offset;
171
@@ -XXX,XX +XXX,XX @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
172
* Current implementation only supports rdbase == procnum
173
* Hence rdbase physical address is ignored
174
*/
175
+ rdbase = (cte & GITS_CTE_RDBASE_PROCNUM_MASK) >> 1U;
176
+
177
+ if (rdbase > s->gicv3->num_cpu) {
178
+ return result;
179
+ }
180
+
181
+ if ((cmd == CLEAR) || (cmd == DISCARD)) {
182
+ gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 0);
183
+ } else {
184
+ gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 1);
185
+ }
186
+
187
if (cmd == DISCARD) {
188
IteEntry ite = {};
189
/* remove mapping from interrupt translation table */
190
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
191
MemTxResult res = MEMTX_OK;
192
bool result = true;
193
uint8_t cmd;
194
+ int i;
195
196
if (!(s->ctlr & ITS_CTLR_ENABLED)) {
197
return;
198
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
199
break;
200
case GITS_CMD_INV:
201
case GITS_CMD_INVALL:
202
+ /*
203
+ * Current implementation doesn't cache any ITS tables,
204
+ * but the calculated lpi priority information. We only
205
+ * need to trigger lpi priority re-calculation to be in
206
+ * sync with LPI config table or pending table changes.
207
+ */
208
+ for (i = 0; i < s->gicv3->num_cpu; i++) {
209
+ gicv3_redist_update_lpi(&s->gicv3->cpu[i]);
210
+ }
211
break;
212
default:
213
break;
214
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
215
index XXXXXXX..XXXXXXX 100644
216
--- a/hw/intc/arm_gicv3_redist.c
217
+++ b/hw/intc/arm_gicv3_redist.c
218
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr offset,
219
if (cs->gicr_typer & GICR_TYPER_PLPIS) {
220
if (value & GICR_CTLR_ENABLE_LPIS) {
221
cs->gicr_ctlr |= GICR_CTLR_ENABLE_LPIS;
222
+ /* Check for any pending interr in pending table */
223
+ gicv3_redist_update_lpi(cs);
224
+ gicv3_redist_update(cs);
225
} else {
226
cs->gicr_ctlr &= ~GICR_CTLR_ENABLE_LPIS;
227
}
228
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
229
return r;
230
}
231
232
+static void gicv3_redist_check_lpi_priority(GICv3CPUState *cs, int irq)
233
+{
234
+ AddressSpace *as = &cs->gic->dma_as;
235
+ uint64_t lpict_baddr;
236
+ uint8_t lpite;
237
+ uint8_t prio;
238
+
239
+ lpict_baddr = cs->gicr_propbaser & R_GICR_PROPBASER_PHYADDR_MASK;
240
+
241
+ address_space_read(as, lpict_baddr + ((irq - GICV3_LPI_INTID_START) *
242
+ sizeof(lpite)), MEMTXATTRS_UNSPECIFIED, &lpite,
243
+ sizeof(lpite));
244
+
245
+ if (!(lpite & LPI_CTE_ENABLED)) {
246
+ return;
247
+ }
248
+
249
+ if (cs->gic->gicd_ctlr & GICD_CTLR_DS) {
250
+ prio = lpite & LPI_PRIORITY_MASK;
251
+ } else {
252
+ prio = ((lpite & LPI_PRIORITY_MASK) >> 1) | 0x80;
253
+ }
254
+
255
+ if ((prio < cs->hpplpi.prio) ||
256
+ ((prio == cs->hpplpi.prio) && (irq <= cs->hpplpi.irq))) {
257
+ cs->hpplpi.irq = irq;
258
+ cs->hpplpi.prio = prio;
259
+ /* LPIs are always non-secure Grp1 interrupts */
260
+ cs->hpplpi.grp = GICV3_G1NS;
261
+ }
262
+}
108
+}
263
+
109
+
264
+void gicv3_redist_update_lpi(GICv3CPUState *cs)
110
+static CPAccessResult access_el1nvvct(CPUARMState *env, const ARMCPRegInfo *ri,
111
+ bool isread)
265
+{
112
+{
266
+ /*
113
+ if (arm_current_el(env) == 1) {
267
+ * This function scans the LPI pending table and for each pending
114
+ /* This must be a FEAT_NV access with NVx == 101 */
268
+ * LPI, reads the corresponding entry from LPI configuration table
115
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1NVVCT)) {
269
+ * to extract the priority info and determine if the current LPI
116
+ return CP_ACCESS_TRAP_EL2;
270
+ * priority is lower than the last computed high priority lpi interrupt.
271
+ * If yes, replace current LPI as the new high priority lpi interrupt.
272
+ */
273
+ AddressSpace *as = &cs->gic->dma_as;
274
+ uint64_t lpipt_baddr;
275
+ uint32_t pendt_size = 0;
276
+ uint8_t pend;
277
+ int i, bit;
278
+ uint64_t idbits;
279
+
280
+ idbits = MIN(FIELD_EX64(cs->gicr_propbaser, GICR_PROPBASER, IDBITS),
281
+ GICD_TYPER_IDBITS);
282
+
283
+ if (!(cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) || !cs->gicr_propbaser ||
284
+ !cs->gicr_pendbaser) {
285
+ return;
286
+ }
287
+
288
+ cs->hpplpi.prio = 0xff;
289
+
290
+ lpipt_baddr = cs->gicr_pendbaser & R_GICR_PENDBASER_PHYADDR_MASK;
291
+
292
+ /* Determine the highest priority pending interrupt among LPIs */
293
+ pendt_size = (1ULL << (idbits + 1));
294
+
295
+ for (i = GICV3_LPI_INTID_START / 8; i < pendt_size / 8; i++) {
296
+ address_space_read(as, lpipt_baddr + i, MEMTXATTRS_UNSPECIFIED, &pend,
297
+ sizeof(pend));
298
+
299
+ while (pend) {
300
+ bit = ctz32(pend);
301
+ gicv3_redist_check_lpi_priority(cs, i * 8 + bit);
302
+ pend &= ~(1 << bit);
303
+ }
117
+ }
304
+ }
118
+ }
119
+ return e2h_access(env, ri, isread);
305
+}
120
+}
306
+
121
+
307
+void gicv3_redist_lpi_pending(GICv3CPUState *cs, int irq, int level)
122
/* Test if system register redirection is to occur in the current state. */
308
+{
123
static bool redirect_for_e2h(CPUARMState *env)
309
+ /*
310
+ * This function updates the pending bit in lpi pending table for
311
+ * the irq being activated or deactivated.
312
+ */
313
+ AddressSpace *as = &cs->gic->dma_as;
314
+ uint64_t lpipt_baddr;
315
+ bool ispend = false;
316
+ uint8_t pend;
317
+
318
+ /*
319
+ * get the bit value corresponding to this irq in the
320
+ * lpi pending table
321
+ */
322
+ lpipt_baddr = cs->gicr_pendbaser & R_GICR_PENDBASER_PHYADDR_MASK;
323
+
324
+ address_space_read(as, lpipt_baddr + ((irq / 8) * sizeof(pend)),
325
+ MEMTXATTRS_UNSPECIFIED, &pend, sizeof(pend));
326
+
327
+ ispend = extract32(pend, irq % 8, 1);
328
+
329
+ /* no change in the value of pending bit, return */
330
+ if (ispend == level) {
331
+ return;
332
+ }
333
+ pend = deposit32(pend, irq % 8, 1, level ? 1 : 0);
334
+
335
+ address_space_write(as, lpipt_baddr + ((irq / 8) * sizeof(pend)),
336
+ MEMTXATTRS_UNSPECIFIED, &pend, sizeof(pend));
337
+
338
+ /*
339
+ * check if this LPI is better than the current hpplpi, if yes
340
+ * just set hpplpi.prio and .irq without doing a full rescan
341
+ */
342
+ if (level) {
343
+ gicv3_redist_check_lpi_priority(cs, irq);
344
+ } else {
345
+ if (irq == cs->hpplpi.irq) {
346
+ gicv3_redist_update_lpi(cs);
347
+ }
348
+ }
349
+}
350
+
351
+void gicv3_redist_process_lpi(GICv3CPUState *cs, int irq, int level)
352
+{
353
+ uint64_t idbits;
354
+
355
+ idbits = MIN(FIELD_EX64(cs->gicr_propbaser, GICR_PROPBASER, IDBITS),
356
+ GICD_TYPER_IDBITS);
357
+
358
+ if (!(cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) || !cs->gicr_propbaser ||
359
+ !cs->gicr_pendbaser || (irq > (1ULL << (idbits + 1)) - 1) ||
360
+ irq < GICV3_LPI_INTID_START) {
361
+ return;
362
+ }
363
+
364
+ /* set/clear the pending bit for this irq */
365
+ gicv3_redist_lpi_pending(cs, irq, level);
366
+
367
+ gicv3_redist_update(cs);
368
+}
369
+
370
void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level)
371
{
124
{
372
/* Update redistributor state for a change in an external PPI input line */
125
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
126
{ .name = "CNTP_CTL_EL02", .state = ARM_CP_STATE_AA64,
127
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 2, .opc2 = 1,
128
.type = ARM_CP_IO | ARM_CP_ALIAS,
129
- .access = PL2_RW, .accessfn = e2h_access,
130
+ .access = PL2_RW, .accessfn = access_el1nvpct,
131
.nv2_redirect_offset = 0x180 | NV2_REDIR_NO_NV1,
132
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].ctl),
133
.writefn = gt_phys_ctl_write, .raw_writefn = raw_write },
134
{ .name = "CNTV_CTL_EL02", .state = ARM_CP_STATE_AA64,
135
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 1,
136
.type = ARM_CP_IO | ARM_CP_ALIAS,
137
- .access = PL2_RW, .accessfn = e2h_access,
138
+ .access = PL2_RW, .accessfn = access_el1nvvct,
139
.nv2_redirect_offset = 0x170 | NV2_REDIR_NO_NV1,
140
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].ctl),
141
.writefn = gt_virt_ctl_write, .raw_writefn = raw_write },
142
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
143
.type = ARM_CP_IO | ARM_CP_ALIAS,
144
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
145
.nv2_redirect_offset = 0x178 | NV2_REDIR_NO_NV1,
146
- .access = PL2_RW, .accessfn = e2h_access,
147
+ .access = PL2_RW, .accessfn = access_el1nvpct,
148
.writefn = gt_phys_cval_write, .raw_writefn = raw_write },
149
{ .name = "CNTV_CVAL_EL02", .state = ARM_CP_STATE_AA64,
150
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 2,
151
.type = ARM_CP_IO | ARM_CP_ALIAS,
152
.nv2_redirect_offset = 0x168 | NV2_REDIR_NO_NV1,
153
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
154
- .access = PL2_RW, .accessfn = e2h_access,
155
+ .access = PL2_RW, .accessfn = access_el1nvvct,
156
.writefn = gt_virt_cval_write, .raw_writefn = raw_write },
157
#endif
158
};
373
--
159
--
374
2.20.1
160
2.34.1
375
376
diff view generated by jsdifflib
1
From: Chris Rauer <crauer@google.com>
1
For FEAT_ECV, new registers CNTPCTSS_EL0 and CNTVCTSS_EL0 are
2
defined, which are "self-synchronized" views of the physical and
3
virtual counts as seen in the CNTPCT_EL0 and CNTVCT_EL0 registers
4
(meaning that no barriers are needed around accesses to them to
5
ensure that reads of them do not occur speculatively and out-of-order
6
with other instructions).
2
7
3
kudo-bmc is a board supported by OpenBMC.
8
For QEMU, all our system registers are self-synchronized, so we can
4
https://github.com/openbmc/openbmc/tree/master/meta-fii/meta-kudo
9
simply copy the existing implementation of CNTPCT_EL0 and CNTVCT_EL0
10
to the new register encodings.
5
11
6
Since v1:
12
This means we now implement all the functionality required for
7
- hyphenated Cortex-A9
13
ID_AA64MMFR0_EL1.ECV == 0b0001.
8
14
9
Tested: Booted kudo firmware.
10
Signed-off-by: Chris Rauer <crauer@google.com>
11
Reviewed-by: Patrick Venture <venture@google.com>
12
Message-id: 20210907223234.1165705-1-crauer@google.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20240301183219.2424889-7-peter.maydell@linaro.org
14
---
18
---
15
docs/system/arm/nuvoton.rst | 1 +
19
target/arm/helper.c | 43 +++++++++++++++++++++++++++++++++++++++++++
16
hw/arm/npcm7xx_boards.c | 34 ++++++++++++++++++++++++++++++++++
20
1 file changed, 43 insertions(+)
17
2 files changed, 35 insertions(+)
18
21
19
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
22
diff --git a/target/arm/helper.c b/target/arm/helper.c
20
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
21
--- a/docs/system/arm/nuvoton.rst
24
--- a/target/arm/helper.c
22
+++ b/docs/system/arm/nuvoton.rst
25
+++ b/target/arm/helper.c
23
@@ -XXX,XX +XXX,XX @@ Hyperscale applications. The following machines are based on this chip :
26
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
24
27
},
25
- ``quanta-gbs-bmc`` Quanta GBS server BMC
28
};
26
- ``quanta-gsj`` Quanta GSJ server BMC
29
27
+- ``kudo-bmc`` Fii USA Kudo server BMC
30
+/*
28
31
+ * FEAT_ECV adds extra views of CNTVCT_EL0 and CNTPCT_EL0 which
29
There are also two more SoCs, NPCM710 and NPCM705, which are single-core
32
+ * are "self-synchronizing". For QEMU all sysregs are self-synchronizing,
30
variants of NPCM750 and NPCM730, respectively. These are currently not
33
+ * so our implementations here are identical to the normal registers.
31
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
34
+ */
32
index XXXXXXX..XXXXXXX 100644
35
+static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
33
--- a/hw/arm/npcm7xx_boards.c
36
+ { .name = "CNTVCTSS", .cp = 15, .crm = 14, .opc1 = 9,
34
+++ b/hw/arm/npcm7xx_boards.c
37
+ .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
35
@@ -XXX,XX +XXX,XX @@
38
+ .accessfn = gt_vct_access,
36
#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
39
+ .readfn = gt_virt_cnt_read, .resetfn = arm_cp_reset_ignore,
37
#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
40
+ },
38
#define QUANTA_GBS_POWER_ON_STRAPS 0x000017ff
41
+ { .name = "CNTVCTSS_EL0", .state = ARM_CP_STATE_AA64,
39
+#define KUDO_BMC_POWER_ON_STRAPS 0x00001fff
42
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 6,
40
43
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
41
static const char npcm7xx_default_bootrom[] = "npcm7xx_bootrom.bin";
44
+ .accessfn = gt_vct_access, .readfn = gt_virt_cnt_read,
42
45
+ },
43
@@ -XXX,XX +XXX,XX @@ static void quanta_gbs_init(MachineState *machine)
46
+ { .name = "CNTPCTSS", .cp = 15, .crm = 14, .opc1 = 8,
44
npcm7xx_load_kernel(machine, soc);
47
+ .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
45
}
48
+ .accessfn = gt_pct_access,
46
49
+ .readfn = gt_cnt_read, .resetfn = arm_cp_reset_ignore,
47
+static void kudo_bmc_init(MachineState *machine)
50
+ },
48
+{
51
+ { .name = "CNTPCTSS_EL0", .state = ARM_CP_STATE_AA64,
49
+ NPCM7xxState *soc;
52
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 5,
50
+
53
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
51
+ soc = npcm7xx_create_soc(machine, KUDO_BMC_POWER_ON_STRAPS);
54
+ .accessfn = gt_pct_access, .readfn = gt_cnt_read,
52
+ npcm7xx_connect_dram(soc, machine->ram);
55
+ },
53
+ qdev_realize(DEVICE(soc), NULL, &error_fatal);
54
+
55
+ npcm7xx_load_bootrom(machine, soc);
56
+ npcm7xx_connect_flash(&soc->fiu[0], 0, "mx66u51235f",
57
+ drive_get(IF_MTD, 0, 0));
58
+ npcm7xx_connect_flash(&soc->fiu[1], 0, "mx66u51235f",
59
+ drive_get(IF_MTD, 3, 0));
60
+
61
+ npcm7xx_load_kernel(machine, soc);
62
+}
63
+
64
static void npcm7xx_set_soc_type(NPCM7xxMachineClass *nmc, const char *type)
65
{
66
NPCM7xxClass *sc = NPCM7XX_CLASS(object_class_by_name(type));
67
@@ -XXX,XX +XXX,XX @@ static void gbs_bmc_machine_class_init(ObjectClass *oc, void *data)
68
mc->default_ram_size = 1 * GiB;
69
}
70
71
+static void kudo_bmc_machine_class_init(ObjectClass *oc, void *data)
72
+{
73
+ NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_CLASS(oc);
74
+ MachineClass *mc = MACHINE_CLASS(oc);
75
+
76
+ npcm7xx_set_soc_type(nmc, TYPE_NPCM730);
77
+
78
+ mc->desc = "Kudo BMC (Cortex-A9)";
79
+ mc->init = kudo_bmc_init;
80
+ mc->default_ram_size = 1 * GiB;
81
+};
56
+};
82
+
57
+
83
static const TypeInfo npcm7xx_machine_types[] = {
58
#else
84
{
59
85
.name = TYPE_NPCM7XX_MACHINE,
60
/*
86
@@ -XXX,XX +XXX,XX @@ static const TypeInfo npcm7xx_machine_types[] = {
61
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
87
.name = MACHINE_TYPE_NAME("quanta-gbs-bmc"),
88
.parent = TYPE_NPCM7XX_MACHINE,
89
.class_init = gbs_bmc_machine_class_init,
90
+ }, {
91
+ .name = MACHINE_TYPE_NAME("kudo-bmc"),
92
+ .parent = TYPE_NPCM7XX_MACHINE,
93
+ .class_init = kudo_bmc_machine_class_init,
94
},
62
},
95
};
63
};
96
64
65
+/*
66
+ * CNTVCTSS_EL0 has the same trap conditions as CNTVCT_EL0, so it also
67
+ * is exposed to userspace by Linux.
68
+ */
69
+static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
70
+ { .name = "CNTVCTSS_EL0", .state = ARM_CP_STATE_AA64,
71
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 6,
72
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
73
+ .readfn = gt_virt_cnt_read,
74
+ },
75
+};
76
+
77
#endif
78
79
static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
80
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
81
if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
82
define_arm_cp_regs(cpu, generic_timer_cp_reginfo);
83
}
84
+ if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
85
+ define_arm_cp_regs(cpu, gen_timer_ecv_cp_reginfo);
86
+ }
87
if (arm_feature(env, ARM_FEATURE_VAPA)) {
88
ARMCPRegInfo vapa_cp_reginfo[] = {
89
{ .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
97
--
90
--
98
2.20.1
91
2.34.1
99
100
diff view generated by jsdifflib
1
From: Shashi Mallela <shashi.mallela@linaro.org>
1
When ID_AA64MMFR0_EL1.ECV is 0b0010, a new register CNTPOFF_EL2 is
2
implemented. This is similar to the existing CNTVOFF_EL2, except
3
that it controls a hypervisor-adjustable offset made to the physical
4
counter and timer.
2
5
3
Added functionality to trigger ITS command queue processing on
6
Implement the handling for this register, which includes control/trap
4
write to CWRITE register and process each command queue entry to
7
bits in SCR_EL3 and CNTHCTL_EL2.
5
identify the command type and handle commands like MAPD,MAPC,SYNC.
6
8
7
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Eric Auger <eric.auger@redhat.com>
10
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
11
Message-id: 20210910143951.92242-4-shashi.mallela@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20240301183219.2424889-8-peter.maydell@linaro.org
13
---
12
---
14
hw/intc/gicv3_internal.h | 40 +++++
13
target/arm/cpu-features.h | 5 +++
15
hw/intc/arm_gicv3_its.c | 319 +++++++++++++++++++++++++++++++++++++++
14
target/arm/cpu.h | 1 +
16
2 files changed, 359 insertions(+)
15
target/arm/helper.c | 68 +++++++++++++++++++++++++++++++++++++--
16
target/arm/trace-events | 1 +
17
4 files changed, 73 insertions(+), 2 deletions(-)
17
18
18
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
19
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
19
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/intc/gicv3_internal.h
21
--- a/target/arm/cpu-features.h
21
+++ b/hw/intc/gicv3_internal.h
22
+++ b/target/arm/cpu-features.h
22
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1)
23
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id)
23
#define L1TABLE_ENTRY_SIZE 8
24
return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 0;
24
25
#define GITS_CMDQ_ENTRY_SIZE 32
26
+#define NUM_BYTES_IN_DW 8
27
+
28
+#define CMD_MASK 0xff
29
+
30
+/* ITS Commands */
31
+#define GITS_CMD_CLEAR 0x04
32
+#define GITS_CMD_DISCARD 0x0F
33
+#define GITS_CMD_INT 0x03
34
+#define GITS_CMD_MAPC 0x09
35
+#define GITS_CMD_MAPD 0x08
36
+#define GITS_CMD_MAPI 0x0B
37
+#define GITS_CMD_MAPTI 0x0A
38
+#define GITS_CMD_INV 0x0C
39
+#define GITS_CMD_INVALL 0x0D
40
+#define GITS_CMD_SYNC 0x05
41
+
42
+/* MAPC command fields */
43
+#define ICID_LENGTH 16
44
+#define ICID_MASK ((1U << ICID_LENGTH) - 1)
45
+FIELD(MAPC, RDBASE, 16, 32)
46
+
47
+#define RDBASE_PROCNUM_LENGTH 16
48
+#define RDBASE_PROCNUM_MASK ((1ULL << RDBASE_PROCNUM_LENGTH) - 1)
49
+
50
+/* MAPD command fields */
51
+#define ITTADDR_LENGTH 44
52
+#define ITTADDR_SHIFT 8
53
+#define ITTADDR_MASK MAKE_64BIT_MASK(ITTADDR_SHIFT, ITTADDR_LENGTH)
54
+#define SIZE_MASK 0x1f
55
+
56
+#define DEVID_SHIFT 32
57
+#define DEVID_MASK MAKE_64BIT_MASK(32, 32)
58
+
59
+#define VALID_SHIFT 63
60
+#define CMD_FIELD_VALID_MASK (1ULL << VALID_SHIFT)
61
+#define L2_TABLE_VALID_MASK CMD_FIELD_VALID_MASK
62
+#define TABLE_ENTRY_VALID_MASK (1ULL << 0)
63
64
/**
65
* Default features advertised by this version of ITS
66
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1)
67
* Valid = 1 bit,ITTAddr = 44 bits,Size = 5 bits
68
*/
69
#define GITS_DTE_SIZE (0x8ULL)
70
+#define GITS_DTE_ITTADDR_SHIFT 6
71
+#define GITS_DTE_ITTADDR_MASK MAKE_64BIT_MASK(GITS_DTE_ITTADDR_SHIFT, \
72
+ ITTADDR_LENGTH)
73
74
/*
75
* 8 bytes Collection Table Entry size
76
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
77
index XXXXXXX..XXXXXXX 100644
78
--- a/hw/intc/arm_gicv3_its.c
79
+++ b/hw/intc/arm_gicv3_its.c
80
@@ -XXX,XX +XXX,XX @@ static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
81
return result;
82
}
25
}
83
26
84
+static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
27
+static inline bool isar_feature_aa64_ecv(const ARMISARegisters *id)
85
+ uint64_t rdbase)
86
+{
28
+{
87
+ AddressSpace *as = &s->gicv3->dma_as;
29
+ return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 1;
88
+ uint64_t value;
89
+ uint64_t l2t_addr;
90
+ bool valid_l2t;
91
+ uint32_t l2t_id;
92
+ uint32_t max_l2_entries;
93
+ uint64_t cte = 0;
94
+ MemTxResult res = MEMTX_OK;
95
+
96
+ if (!s->ct.valid) {
97
+ return true;
98
+ }
99
+
100
+ if (valid) {
101
+ /* add mapping entry to collection table */
102
+ cte = (valid & TABLE_ENTRY_VALID_MASK) | (rdbase << 1ULL);
103
+ }
104
+
105
+ /*
106
+ * The specification defines the format of level 1 entries of a
107
+ * 2-level table, but the format of level 2 entries and the format
108
+ * of flat-mapped tables is IMPDEF.
109
+ */
110
+ if (s->ct.indirect) {
111
+ l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE);
112
+
113
+ value = address_space_ldq_le(as,
114
+ s->ct.base_addr +
115
+ (l2t_id * L1TABLE_ENTRY_SIZE),
116
+ MEMTXATTRS_UNSPECIFIED, &res);
117
+
118
+ if (res != MEMTX_OK) {
119
+ return false;
120
+ }
121
+
122
+ valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
123
+
124
+ if (valid_l2t) {
125
+ max_l2_entries = s->ct.page_sz / s->ct.entry_sz;
126
+
127
+ l2t_addr = value & ((1ULL << 51) - 1);
128
+
129
+ address_space_stq_le(as, l2t_addr +
130
+ ((icid % max_l2_entries) * GITS_CTE_SIZE),
131
+ cte, MEMTXATTRS_UNSPECIFIED, &res);
132
+ }
133
+ } else {
134
+ /* Flat level table */
135
+ address_space_stq_le(as, s->ct.base_addr + (icid * GITS_CTE_SIZE),
136
+ cte, MEMTXATTRS_UNSPECIFIED, &res);
137
+ }
138
+ if (res != MEMTX_OK) {
139
+ return false;
140
+ } else {
141
+ return true;
142
+ }
143
+}
30
+}
144
+
31
+
145
+static bool process_mapc(GICv3ITSState *s, uint32_t offset)
32
static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
33
{
34
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
35
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/cpu.h
38
+++ b/target/arm/cpu.h
39
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
40
uint64_t c14_cntkctl; /* Timer Control register */
41
uint64_t cnthctl_el2; /* Counter/Timer Hyp Control register */
42
uint64_t cntvoff_el2; /* Counter Virtual Offset register */
43
+ uint64_t cntpoff_el2; /* Counter Physical Offset register */
44
ARMGenericTimer c14_timer[NUM_GTIMERS];
45
uint32_t c15_cpar; /* XScale Coprocessor Access Register */
46
uint32_t c15_ticonfig; /* TI925T configuration byte. */
47
diff --git a/target/arm/helper.c b/target/arm/helper.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/helper.c
50
+++ b/target/arm/helper.c
51
@@ -XXX,XX +XXX,XX @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
52
if (cpu_isar_feature(aa64_rme, cpu)) {
53
valid_mask |= SCR_NSE | SCR_GPF;
54
}
55
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
56
+ valid_mask |= SCR_ECVEN;
57
+ }
58
} else {
59
valid_mask &= ~(SCR_RW | SCR_ST);
60
if (cpu_isar_feature(aa32_ras, cpu)) {
61
@@ -XXX,XX +XXX,XX @@ void gt_rme_post_el_change(ARMCPU *cpu, void *ignored)
62
gt_update_irq(cpu, GTIMER_PHYS);
63
}
64
65
+static uint64_t gt_phys_raw_cnt_offset(CPUARMState *env)
146
+{
66
+{
147
+ AddressSpace *as = &s->gicv3->dma_as;
67
+ if ((env->cp15.scr_el3 & SCR_ECVEN) &&
148
+ uint16_t icid;
68
+ FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, ECV) &&
149
+ uint64_t rdbase;
69
+ arm_is_el2_enabled(env) &&
150
+ bool valid;
70
+ (arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
151
+ MemTxResult res = MEMTX_OK;
71
+ return env->cp15.cntpoff_el2;
152
+ bool result = false;
153
+ uint64_t value;
154
+
155
+ offset += NUM_BYTES_IN_DW;
156
+ offset += NUM_BYTES_IN_DW;
157
+
158
+ value = address_space_ldq_le(as, s->cq.base_addr + offset,
159
+ MEMTXATTRS_UNSPECIFIED, &res);
160
+
161
+ if (res != MEMTX_OK) {
162
+ return result;
163
+ }
72
+ }
164
+
73
+ return 0;
165
+ icid = value & ICID_MASK;
166
+
167
+ rdbase = (value & R_MAPC_RDBASE_MASK) >> R_MAPC_RDBASE_SHIFT;
168
+ rdbase &= RDBASE_PROCNUM_MASK;
169
+
170
+ valid = (value & CMD_FIELD_VALID_MASK);
171
+
172
+ if ((icid > s->ct.maxids.max_collids) || (rdbase > s->gicv3->num_cpu)) {
173
+ qemu_log_mask(LOG_GUEST_ERROR,
174
+ "ITS MAPC: invalid collection table attributes "
175
+ "icid %d rdbase %lu\n", icid, rdbase);
176
+ /*
177
+ * in this implementation, in case of error
178
+ * we ignore this command and move onto the next
179
+ * command in the queue
180
+ */
181
+ } else {
182
+ result = update_cte(s, icid, valid, rdbase);
183
+ }
184
+
185
+ return result;
186
+}
74
+}
187
+
75
+
188
+static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
76
+static uint64_t gt_phys_cnt_offset(CPUARMState *env)
189
+ uint8_t size, uint64_t itt_addr)
190
+{
77
+{
191
+ AddressSpace *as = &s->gicv3->dma_as;
78
+ if (arm_current_el(env) >= 2) {
192
+ uint64_t value;
79
+ return 0;
193
+ uint64_t l2t_addr;
194
+ bool valid_l2t;
195
+ uint32_t l2t_id;
196
+ uint32_t max_l2_entries;
197
+ uint64_t dte = 0;
198
+ MemTxResult res = MEMTX_OK;
199
+
200
+ if (s->dt.valid) {
201
+ if (valid) {
202
+ /* add mapping entry to device table */
203
+ dte = (valid & TABLE_ENTRY_VALID_MASK) |
204
+ ((size & SIZE_MASK) << 1U) |
205
+ (itt_addr << GITS_DTE_ITTADDR_SHIFT);
206
+ }
207
+ } else {
208
+ return true;
209
+ }
80
+ }
210
+
81
+ return gt_phys_raw_cnt_offset(env);
211
+ /*
212
+ * The specification defines the format of level 1 entries of a
213
+ * 2-level table, but the format of level 2 entries and the format
214
+ * of flat-mapped tables is IMPDEF.
215
+ */
216
+ if (s->dt.indirect) {
217
+ l2t_id = devid / (s->dt.page_sz / L1TABLE_ENTRY_SIZE);
218
+
219
+ value = address_space_ldq_le(as,
220
+ s->dt.base_addr +
221
+ (l2t_id * L1TABLE_ENTRY_SIZE),
222
+ MEMTXATTRS_UNSPECIFIED, &res);
223
+
224
+ if (res != MEMTX_OK) {
225
+ return false;
226
+ }
227
+
228
+ valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
229
+
230
+ if (valid_l2t) {
231
+ max_l2_entries = s->dt.page_sz / s->dt.entry_sz;
232
+
233
+ l2t_addr = value & ((1ULL << 51) - 1);
234
+
235
+ address_space_stq_le(as, l2t_addr +
236
+ ((devid % max_l2_entries) * GITS_DTE_SIZE),
237
+ dte, MEMTXATTRS_UNSPECIFIED, &res);
238
+ }
239
+ } else {
240
+ /* Flat level table */
241
+ address_space_stq_le(as, s->dt.base_addr + (devid * GITS_DTE_SIZE),
242
+ dte, MEMTXATTRS_UNSPECIFIED, &res);
243
+ }
244
+ if (res != MEMTX_OK) {
245
+ return false;
246
+ } else {
247
+ return true;
248
+ }
249
+}
82
+}
250
+
83
+
251
+static bool process_mapd(GICv3ITSState *s, uint64_t value, uint32_t offset)
84
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
85
{
86
ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
87
@@ -XXX,XX +XXX,XX @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
88
* reset timer to when ISTATUS next has to change
89
*/
90
uint64_t offset = timeridx == GTIMER_VIRT ?
91
- cpu->env.cp15.cntvoff_el2 : 0;
92
+ cpu->env.cp15.cntvoff_el2 : gt_phys_raw_cnt_offset(&cpu->env);
93
uint64_t count = gt_get_countervalue(&cpu->env);
94
/* Note that this must be unsigned 64 bit arithmetic: */
95
int istatus = count - offset >= gt->cval;
96
@@ -XXX,XX +XXX,XX @@ static void gt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri,
97
98
static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
99
{
100
- return gt_get_countervalue(env);
101
+ return gt_get_countervalue(env) - gt_phys_cnt_offset(env);
102
}
103
104
static uint64_t gt_virt_cnt_offset(CPUARMState *env)
105
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
106
case GTIMER_HYPVIRT:
107
offset = gt_virt_cnt_offset(env);
108
break;
109
+ case GTIMER_PHYS:
110
+ offset = gt_phys_cnt_offset(env);
111
+ break;
112
}
113
114
return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
115
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
116
case GTIMER_HYPVIRT:
117
offset = gt_virt_cnt_offset(env);
118
break;
119
+ case GTIMER_PHYS:
120
+ offset = gt_phys_cnt_offset(env);
121
+ break;
122
}
123
124
trace_arm_gt_tval_write(timeridx, value);
125
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
126
R_CNTHCTL_EL1NVVCT_MASK |
127
R_CNTHCTL_EVNTIS_MASK;
128
}
129
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
130
+ valid_mask |= R_CNTHCTL_ECV_MASK;
131
+ }
132
133
/* Clear RES0 bits */
134
value &= valid_mask;
135
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
136
},
137
};
138
139
+static CPAccessResult gt_cntpoff_access(CPUARMState *env,
140
+ const ARMCPRegInfo *ri,
141
+ bool isread)
252
+{
142
+{
253
+ AddressSpace *as = &s->gicv3->dma_as;
143
+ if (arm_current_el(env) == 2 && !(env->cp15.scr_el3 & SCR_ECVEN)) {
254
+ uint32_t devid;
144
+ return CP_ACCESS_TRAP_EL3;
255
+ uint8_t size;
256
+ uint64_t itt_addr;
257
+ bool valid;
258
+ MemTxResult res = MEMTX_OK;
259
+ bool result = false;
260
+
261
+ devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
262
+
263
+ offset += NUM_BYTES_IN_DW;
264
+ value = address_space_ldq_le(as, s->cq.base_addr + offset,
265
+ MEMTXATTRS_UNSPECIFIED, &res);
266
+
267
+ if (res != MEMTX_OK) {
268
+ return result;
269
+ }
145
+ }
270
+
146
+ return CP_ACCESS_OK;
271
+ size = (value & SIZE_MASK);
272
+
273
+ offset += NUM_BYTES_IN_DW;
274
+ value = address_space_ldq_le(as, s->cq.base_addr + offset,
275
+ MEMTXATTRS_UNSPECIFIED, &res);
276
+
277
+ if (res != MEMTX_OK) {
278
+ return result;
279
+ }
280
+
281
+ itt_addr = (value & ITTADDR_MASK) >> ITTADDR_SHIFT;
282
+
283
+ valid = (value & CMD_FIELD_VALID_MASK);
284
+
285
+ if ((devid > s->dt.maxids.max_devids) ||
286
+ (size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) {
287
+ qemu_log_mask(LOG_GUEST_ERROR,
288
+ "ITS MAPD: invalid device table attributes "
289
+ "devid %d or size %d\n", devid, size);
290
+ /*
291
+ * in this implementation, in case of error
292
+ * we ignore this command and move onto the next
293
+ * command in the queue
294
+ */
295
+ } else {
296
+ result = update_dte(s, devid, valid, size, itt_addr);
297
+ }
298
+
299
+ return result;
300
+}
147
+}
301
+
148
+
302
+/*
149
+static void gt_cntpoff_write(CPUARMState *env, const ARMCPRegInfo *ri,
303
+ * Current implementation blocks until all
150
+ uint64_t value)
304
+ * commands are processed
305
+ */
306
+static void process_cmdq(GICv3ITSState *s)
307
+{
151
+{
308
+ uint32_t wr_offset = 0;
152
+ ARMCPU *cpu = env_archcpu(env);
309
+ uint32_t rd_offset = 0;
310
+ uint32_t cq_offset = 0;
311
+ uint64_t data;
312
+ AddressSpace *as = &s->gicv3->dma_as;
313
+ MemTxResult res = MEMTX_OK;
314
+ bool result = true;
315
+ uint8_t cmd;
316
+
153
+
317
+ if (!(s->ctlr & ITS_CTLR_ENABLED)) {
154
+ trace_arm_gt_cntpoff_write(value);
318
+ return;
155
+ raw_write(env, ri, value);
319
+ }
156
+ gt_recalc_timer(cpu, GTIMER_PHYS);
320
+
321
+ wr_offset = FIELD_EX64(s->cwriter, GITS_CWRITER, OFFSET);
322
+
323
+ if (wr_offset > s->cq.max_entries) {
324
+ qemu_log_mask(LOG_GUEST_ERROR,
325
+ "%s: invalid write offset "
326
+ "%d\n", __func__, wr_offset);
327
+ return;
328
+ }
329
+
330
+ rd_offset = FIELD_EX64(s->creadr, GITS_CREADR, OFFSET);
331
+
332
+ if (rd_offset > s->cq.max_entries) {
333
+ qemu_log_mask(LOG_GUEST_ERROR,
334
+ "%s: invalid read offset "
335
+ "%d\n", __func__, rd_offset);
336
+ return;
337
+ }
338
+
339
+ while (wr_offset != rd_offset) {
340
+ cq_offset = (rd_offset * GITS_CMDQ_ENTRY_SIZE);
341
+ data = address_space_ldq_le(as, s->cq.base_addr + cq_offset,
342
+ MEMTXATTRS_UNSPECIFIED, &res);
343
+ if (res != MEMTX_OK) {
344
+ result = false;
345
+ }
346
+ cmd = (data & CMD_MASK);
347
+
348
+ switch (cmd) {
349
+ case GITS_CMD_INT:
350
+ break;
351
+ case GITS_CMD_CLEAR:
352
+ break;
353
+ case GITS_CMD_SYNC:
354
+ /*
355
+ * Current implementation makes a blocking synchronous call
356
+ * for every command issued earlier, hence the internal state
357
+ * is already consistent by the time SYNC command is executed.
358
+ * Hence no further processing is required for SYNC command.
359
+ */
360
+ break;
361
+ case GITS_CMD_MAPD:
362
+ result = process_mapd(s, data, cq_offset);
363
+ break;
364
+ case GITS_CMD_MAPC:
365
+ result = process_mapc(s, cq_offset);
366
+ break;
367
+ case GITS_CMD_MAPTI:
368
+ break;
369
+ case GITS_CMD_MAPI:
370
+ break;
371
+ case GITS_CMD_DISCARD:
372
+ break;
373
+ case GITS_CMD_INV:
374
+ case GITS_CMD_INVALL:
375
+ break;
376
+ default:
377
+ break;
378
+ }
379
+ if (result) {
380
+ rd_offset++;
381
+ rd_offset %= s->cq.max_entries;
382
+ s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, OFFSET, rd_offset);
383
+ } else {
384
+ /*
385
+ * in this implementation, in case of dma read/write error
386
+ * we stall the command processing
387
+ */
388
+ s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, STALLED, 1);
389
+ qemu_log_mask(LOG_GUEST_ERROR,
390
+ "%s: %x cmd processing failed\n", __func__, cmd);
391
+ break;
392
+ }
393
+ }
394
+}
157
+}
395
+
158
+
159
+static const ARMCPRegInfo gen_timer_cntpoff_reginfo = {
160
+ .name = "CNTPOFF_EL2", .state = ARM_CP_STATE_AA64,
161
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 0, .opc2 = 6,
162
+ .access = PL2_RW, .type = ARM_CP_IO, .resetvalue = 0,
163
+ .accessfn = gt_cntpoff_access, .writefn = gt_cntpoff_write,
164
+ .nv2_redirect_offset = 0x1a8,
165
+ .fieldoffset = offsetof(CPUARMState, cp15.cntpoff_el2),
166
+};
167
#else
168
396
/*
169
/*
397
* This function extracts the ITS Device and Collection table specific
170
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
398
* parameters (like base_addr, size etc) from GITS_BASER register.
171
if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
399
@@ -XXX,XX +XXX,XX @@ static bool its_writel(GICv3ITSState *s, hwaddr offset,
172
define_arm_cp_regs(cpu, gen_timer_ecv_cp_reginfo);
400
extract_table_params(s);
173
}
401
extract_cmdq_params(s);
174
+#ifndef CONFIG_USER_ONLY
402
s->creadr = 0;
175
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
403
+ process_cmdq(s);
176
+ define_one_arm_cp_reg(cpu, &gen_timer_cntpoff_reginfo);
404
}
177
+ }
405
break;
178
+#endif
406
case GITS_CBASER:
179
if (arm_feature(env, ARM_FEATURE_VAPA)) {
407
@@ -XXX,XX +XXX,XX @@ static bool its_writel(GICv3ITSState *s, hwaddr offset,
180
ARMCPRegInfo vapa_cp_reginfo[] = {
408
case GITS_CWRITER:
181
{ .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
409
s->cwriter = deposit64(s->cwriter, 0, 32,
182
diff --git a/target/arm/trace-events b/target/arm/trace-events
410
(value & ~R_GITS_CWRITER_RETRY_MASK));
183
index XXXXXXX..XXXXXXX 100644
411
+ if (s->cwriter != s->creadr) {
184
--- a/target/arm/trace-events
412
+ process_cmdq(s);
185
+++ b/target/arm/trace-events
413
+ }
186
@@ -XXX,XX +XXX,XX @@ arm_gt_tval_write(int timer, uint64_t value) "gt_tval_write: timer %d value 0x%"
414
break;
187
arm_gt_ctl_write(int timer, uint64_t value) "gt_ctl_write: timer %d value 0x%" PRIx64
415
case GITS_CWRITER + 4:
188
arm_gt_imask_toggle(int timer) "gt_ctl_write: timer %d IMASK toggle"
416
s->cwriter = deposit64(s->cwriter, 32, 32, value);
189
arm_gt_cntvoff_write(uint64_t value) "gt_cntvoff_write: value 0x%" PRIx64
417
@@ -XXX,XX +XXX,XX @@ static bool its_writell(GICv3ITSState *s, hwaddr offset,
190
+arm_gt_cntpoff_write(uint64_t value) "gt_cntpoff_write: value 0x%" PRIx64
418
break;
191
arm_gt_update_irq(int timer, int irqstate) "gt_update_irq: timer %d irqstate %d"
419
case GITS_CWRITER:
192
420
s->cwriter = value & ~R_GITS_CWRITER_RETRY_MASK;
193
# kvm.c
421
+ if (s->cwriter != s->creadr) {
422
+ process_cmdq(s);
423
+ }
424
break;
425
case GITS_CREADR:
426
if (s->gicv3->gicd_ctlr & GICD_CTLR_DS) {
427
--
194
--
428
2.20.1
195
2.34.1
429
430
diff view generated by jsdifflib
1
By default, QEMU will allow devices to be plugged into a bus up to
1
Enable all FEAT_ECV features on the 'max' CPU.
2
the bus class's device count limit. If the user creates a device on
3
the command line or via the monitor and doesn't explicitly specify
4
the bus to plug it in, QEMU will plug it into the first non-full bus
5
that it finds.
6
7
This is fine in most cases, but some machines have multiple buses of
8
a given type, some of which are dedicated to on-board devices and
9
some of which have an externally exposed connector for user-pluggable
10
devices. One example is I2C buses.
11
12
Provide a new function qbus_mark_full() so that a machine model can
13
mark this kind of "internal only" bus as 'full' after it has created
14
all the devices that should be plugged into that bus. The "find a
15
non-full bus" algorithm will then skip the internal-only bus when
16
looking for a place to plug in user-created devices.
17
2
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Message-id: 20210903151435.22379-2-peter.maydell@linaro.org
6
Message-id: 20240301183219.2424889-9-peter.maydell@linaro.org
21
---
7
---
22
include/hw/qdev-core.h | 24 ++++++++++++++++++++++++
8
docs/system/arm/emulation.rst | 1 +
23
softmmu/qdev-monitor.c | 7 ++++++-
9
target/arm/tcg/cpu64.c | 1 +
24
2 files changed, 30 insertions(+), 1 deletion(-)
10
2 files changed, 2 insertions(+)
25
11
26
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
12
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
27
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
28
--- a/include/hw/qdev-core.h
14
--- a/docs/system/arm/emulation.rst
29
+++ b/include/hw/qdev-core.h
15
+++ b/docs/system/arm/emulation.rst
30
@@ -XXX,XX +XXX,XX @@ struct BusState {
16
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
31
HotplugHandler *hotplug_handler;
17
- FEAT_DotProd (Advanced SIMD dot product instructions)
32
int max_index;
18
- FEAT_DoubleFault (Double Fault Extension)
33
bool realized;
19
- FEAT_E0PD (Preventing EL0 access to halves of address maps)
34
+ bool full;
20
+- FEAT_ECV (Enhanced Counter Virtualization)
35
int num_children;
21
- FEAT_EPAC (Enhanced pointer authentication)
36
22
- FEAT_ETS (Enhanced Translation Synchronization)
37
/*
23
- FEAT_EVT (Enhanced Virtualization Traps)
38
@@ -XXX,XX +XXX,XX @@ static inline bool qbus_is_hotpluggable(BusState *bus)
24
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
39
return bus->hotplug_handler;
40
}
41
42
+/**
43
+ * qbus_mark_full: Mark this bus as full, so no more devices can be attached
44
+ * @bus: Bus to mark as full
45
+ *
46
+ * By default, QEMU will allow devices to be plugged into a bus up
47
+ * to the bus class's device count limit. Calling this function
48
+ * marks a particular bus as full, so that no more devices can be
49
+ * plugged into it. In particular this means that the bus will not
50
+ * be considered as a candidate for plugging in devices created by
51
+ * the user on the commandline or via the monitor.
52
+ * If a machine has multiple buses of a given type, such as I2C,
53
+ * where some of those buses in the real hardware are used only for
54
+ * internal devices and some are exposed via expansion ports, you
55
+ * can use this function to mark the internal-only buses as full
56
+ * after you have created all their internal devices. Then user
57
+ * created devices will appear on the expansion-port bus where
58
+ * guest software expects them.
59
+ */
60
+static inline void qbus_mark_full(BusState *bus)
61
+{
62
+ bus->full = true;
63
+}
64
+
65
void device_listener_register(DeviceListener *listener);
66
void device_listener_unregister(DeviceListener *listener);
67
68
diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c
69
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
70
--- a/softmmu/qdev-monitor.c
26
--- a/target/arm/tcg/cpu64.c
71
+++ b/softmmu/qdev-monitor.c
27
+++ b/target/arm/tcg/cpu64.c
72
@@ -XXX,XX +XXX,XX @@ static DeviceState *qbus_find_dev(BusState *bus, char *elem)
28
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
73
29
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN64_2, 2); /* 64k stage2 supported */
74
static inline bool qbus_is_full(BusState *bus)
30
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 2); /* 4k stage2 supported */
75
{
31
t = FIELD_DP64(t, ID_AA64MMFR0, FGT, 1); /* FEAT_FGT */
76
- BusClass *bus_class = BUS_GET_CLASS(bus);
32
+ t = FIELD_DP64(t, ID_AA64MMFR0, ECV, 2); /* FEAT_ECV */
77
+ BusClass *bus_class;
33
cpu->isar.id_aa64mmfr0 = t;
78
+
34
79
+ if (bus->full) {
35
t = cpu->isar.id_aa64mmfr1;
80
+ return true;
81
+ }
82
+ bus_class = BUS_GET_CLASS(bus);
83
return bus_class->max_dev && bus->num_children >= bus_class->max_dev;
84
}
85
86
--
36
--
87
2.20.1
37
2.34.1
88
38
89
39
diff view generated by jsdifflib
1
From: Shashi Mallela <shashi.mallela@linaro.org>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
Added register definitions relevant to ITS,implemented overall
3
Features supported :
4
ITS device framework with stubs for ITS control and translater
4
- the 8 STM32L4x5 GPIOs are initialized with their reset values
5
regions read/write,extended ITS common to handle mmio init between
5
(except IDR, see below)
6
existing kvm device and newer qemu device.
6
- input mode : setting a pin in input mode "externally" (using input
7
irqs) results in an out irq (transmitted to SYSCFG)
8
- output mode : setting a bit in ODR sets the corresponding out irq
9
(if this line is configured in output mode)
10
- pull-up, pull-down
11
- push-pull, open-drain
7
12
8
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
13
Difference with the real GPIOs :
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
- Alternate Function and Analog mode aren't implemented :
10
Reviewed-by: Eric Auger <eric.auger@redhat.com>
15
pins in AF/Analog behave like pins in input mode
11
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
16
- floating pins stay at their last value
12
Message-id: 20210910143951.92242-2-shashi.mallela@linaro.org
17
- register IDR reset values differ from the real one :
18
values are coherent with the other registers reset values
19
and the fact that AF/Analog modes aren't implemented
20
- setting I/O output speed isn't supported
21
- locking port bits isn't supported
22
- ADC function isn't supported
23
- GPIOH has 16 pins instead of 2 pins
24
- writing to registers LCKR, AFRL, AFRH and ASCR is ineffective
25
26
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
27
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
28
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
29
Acked-by: Alistair Francis <alistair.francis@wdc.com>
30
Message-id: 20240305210444.310665-2-ines.varhol@telecom-paris.fr
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
32
---
15
hw/intc/gicv3_internal.h | 96 +++++++++-
33
MAINTAINERS | 1 +
16
include/hw/intc/arm_gicv3_its_common.h | 9 +-
34
docs/system/arm/b-l475e-iot01a.rst | 2 +-
17
hw/intc/arm_gicv3_its.c | 241 +++++++++++++++++++++++++
35
include/hw/gpio/stm32l4x5_gpio.h | 70 +++++
18
hw/intc/arm_gicv3_its_common.c | 7 +-
36
hw/gpio/stm32l4x5_gpio.c | 477 +++++++++++++++++++++++++++++
19
hw/intc/arm_gicv3_its_kvm.c | 2 +-
37
hw/gpio/Kconfig | 3 +
20
hw/intc/meson.build | 1 +
38
hw/gpio/meson.build | 1 +
21
6 files changed, 342 insertions(+), 14 deletions(-)
39
hw/gpio/trace-events | 6 +
22
create mode 100644 hw/intc/arm_gicv3_its.c
40
7 files changed, 559 insertions(+), 1 deletion(-)
41
create mode 100644 include/hw/gpio/stm32l4x5_gpio.h
42
create mode 100644 hw/gpio/stm32l4x5_gpio.c
23
43
24
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
44
diff --git a/MAINTAINERS b/MAINTAINERS
25
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/intc/gicv3_internal.h
46
--- a/MAINTAINERS
27
+++ b/hw/intc/gicv3_internal.h
47
+++ b/MAINTAINERS
28
@@ -XXX,XX +XXX,XX @@
48
@@ -XXX,XX +XXX,XX @@ F: hw/arm/stm32l4x5_soc.c
29
#ifndef QEMU_ARM_GICV3_INTERNAL_H
49
F: hw/misc/stm32l4x5_exti.c
30
#define QEMU_ARM_GICV3_INTERNAL_H
50
F: hw/misc/stm32l4x5_syscfg.c
31
51
F: hw/misc/stm32l4x5_rcc.c
32
+#include "hw/registerfields.h"
52
+F: hw/gpio/stm32l4x5_gpio.c
33
#include "hw/intc/arm_gicv3_common.h"
53
F: include/hw/*/stm32l4x5_*.h
34
54
35
/* Distributor registers, as offsets from the distributor base address */
55
B-L475E-IOT01A IoT Node
36
@@ -XXX,XX +XXX,XX @@
56
diff --git a/docs/system/arm/b-l475e-iot01a.rst b/docs/system/arm/b-l475e-iot01a.rst
37
#define GICD_CTLR_E1NWF (1U << 7)
38
#define GICD_CTLR_RWP (1U << 31)
39
40
+/* 16 bits EventId */
41
+#define GICD_TYPER_IDBITS 0xf
42
+
43
/*
44
* Redistributor frame offsets from RD_base
45
*/
46
@@ -XXX,XX +XXX,XX @@
47
#define GICR_WAKER_ProcessorSleep (1U << 1)
48
#define GICR_WAKER_ChildrenAsleep (1U << 2)
49
50
-#define GICR_PROPBASER_OUTER_CACHEABILITY_MASK (7ULL << 56)
51
-#define GICR_PROPBASER_ADDR_MASK (0xfffffffffULL << 12)
52
-#define GICR_PROPBASER_SHAREABILITY_MASK (3U << 10)
53
-#define GICR_PROPBASER_CACHEABILITY_MASK (7U << 7)
54
-#define GICR_PROPBASER_IDBITS_MASK (0x1f)
55
+FIELD(GICR_PROPBASER, IDBITS, 0, 5)
56
+FIELD(GICR_PROPBASER, INNERCACHE, 7, 3)
57
+FIELD(GICR_PROPBASER, SHAREABILITY, 10, 2)
58
+FIELD(GICR_PROPBASER, PHYADDR, 12, 40)
59
+FIELD(GICR_PROPBASER, OUTERCACHE, 56, 3)
60
61
-#define GICR_PENDBASER_PTZ (1ULL << 62)
62
-#define GICR_PENDBASER_OUTER_CACHEABILITY_MASK (7ULL << 56)
63
-#define GICR_PENDBASER_ADDR_MASK (0xffffffffULL << 16)
64
-#define GICR_PENDBASER_SHAREABILITY_MASK (3U << 10)
65
-#define GICR_PENDBASER_CACHEABILITY_MASK (7U << 7)
66
+FIELD(GICR_PENDBASER, INNERCACHE, 7, 3)
67
+FIELD(GICR_PENDBASER, SHAREABILITY, 10, 2)
68
+FIELD(GICR_PENDBASER, PHYADDR, 16, 36)
69
+FIELD(GICR_PENDBASER, OUTERCACHE, 56, 3)
70
+FIELD(GICR_PENDBASER, PTZ, 62, 1)
71
72
#define ICC_CTLR_EL1_CBPR (1U << 0)
73
#define ICC_CTLR_EL1_EOIMODE (1U << 1)
74
@@ -XXX,XX +XXX,XX @@
75
#define ICH_VTR_EL2_PREBITS_SHIFT 26
76
#define ICH_VTR_EL2_PRIBITS_SHIFT 29
77
78
+/* ITS Registers */
79
+
80
+FIELD(GITS_BASER, SIZE, 0, 8)
81
+FIELD(GITS_BASER, PAGESIZE, 8, 2)
82
+FIELD(GITS_BASER, SHAREABILITY, 10, 2)
83
+FIELD(GITS_BASER, PHYADDR, 12, 36)
84
+FIELD(GITS_BASER, PHYADDRL_64K, 16, 32)
85
+FIELD(GITS_BASER, PHYADDRH_64K, 12, 4)
86
+FIELD(GITS_BASER, ENTRYSIZE, 48, 5)
87
+FIELD(GITS_BASER, OUTERCACHE, 53, 3)
88
+FIELD(GITS_BASER, TYPE, 56, 3)
89
+FIELD(GITS_BASER, INNERCACHE, 59, 3)
90
+FIELD(GITS_BASER, INDIRECT, 62, 1)
91
+FIELD(GITS_BASER, VALID, 63, 1)
92
+
93
+FIELD(GITS_CTLR, QUIESCENT, 31, 1)
94
+
95
+FIELD(GITS_TYPER, PHYSICAL, 0, 1)
96
+FIELD(GITS_TYPER, ITT_ENTRY_SIZE, 4, 4)
97
+FIELD(GITS_TYPER, IDBITS, 8, 5)
98
+FIELD(GITS_TYPER, DEVBITS, 13, 5)
99
+FIELD(GITS_TYPER, SEIS, 18, 1)
100
+FIELD(GITS_TYPER, PTA, 19, 1)
101
+FIELD(GITS_TYPER, CIDBITS, 32, 4)
102
+FIELD(GITS_TYPER, CIL, 36, 1)
103
+
104
+#define GITS_BASER_PAGESIZE_4K 0
105
+#define GITS_BASER_PAGESIZE_16K 1
106
+#define GITS_BASER_PAGESIZE_64K 2
107
+
108
+#define GITS_BASER_TYPE_DEVICE 1ULL
109
+#define GITS_BASER_TYPE_COLLECTION 4ULL
110
+
111
+/**
112
+ * Default features advertised by this version of ITS
113
+ */
114
+/* Physical LPIs supported */
115
+#define GITS_TYPE_PHYSICAL (1U << 0)
116
+
117
+/*
118
+ * 12 bytes Interrupt translation Table Entry size
119
+ * as per Table 5.3 in GICv3 spec
120
+ * ITE Lower 8 Bytes
121
+ * Bits: | 49 ... 26 | 25 ... 2 | 1 | 0 |
122
+ * Values: | 1023 | IntNum | IntType | Valid |
123
+ * ITE Higher 4 Bytes
124
+ * Bits: | 31 ... 16 | 15 ...0 |
125
+ * Values: | vPEID | ICID |
126
+ */
127
+#define ITS_ITT_ENTRY_SIZE 0xC
128
+
129
+/* 16 bits EventId */
130
+#define ITS_IDBITS GICD_TYPER_IDBITS
131
+
132
+/* 16 bits DeviceId */
133
+#define ITS_DEVBITS 0xF
134
+
135
+/* 16 bits CollectionId */
136
+#define ITS_CIDBITS 0xF
137
+
138
+/*
139
+ * 8 bytes Device Table Entry size
140
+ * Valid = 1 bit,ITTAddr = 44 bits,Size = 5 bits
141
+ */
142
+#define GITS_DTE_SIZE (0x8ULL)
143
+
144
+/*
145
+ * 8 bytes Collection Table Entry size
146
+ * Valid = 1 bit,RDBase = 36 bits(considering max RDBASE)
147
+ */
148
+#define GITS_CTE_SIZE (0x8ULL)
149
+
150
/* Special interrupt IDs */
151
#define INTID_SECURE 1020
152
#define INTID_NONSECURE 1021
153
diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h
154
index XXXXXXX..XXXXXXX 100644
57
index XXXXXXX..XXXXXXX 100644
155
--- a/include/hw/intc/arm_gicv3_its_common.h
58
--- a/docs/system/arm/b-l475e-iot01a.rst
156
+++ b/include/hw/intc/arm_gicv3_its_common.h
59
+++ b/docs/system/arm/b-l475e-iot01a.rst
157
@@ -XXX,XX +XXX,XX @@
60
@@ -XXX,XX +XXX,XX @@ Currently B-L475E-IOT01A machine's only supports the following devices:
158
#include "hw/intc/arm_gicv3_common.h"
61
- STM32L4x5 EXTI (Extended interrupts and events controller)
159
#include "qom/object.h"
62
- STM32L4x5 SYSCFG (System configuration controller)
160
63
- STM32L4x5 RCC (Reset and clock control)
161
+#define TYPE_ARM_GICV3_ITS "arm-gicv3-its"
64
+- STM32L4x5 GPIOs (General-purpose I/Os)
162
+
65
163
#define ITS_CONTROL_SIZE 0x10000
66
Missing devices
164
#define ITS_TRANS_SIZE 0x10000
67
"""""""""""""""
165
#define ITS_SIZE (ITS_CONTROL_SIZE + ITS_TRANS_SIZE)
68
@@ -XXX,XX +XXX,XX @@ Missing devices
166
69
The B-L475E-IOT01A does *not* support the following devices:
167
#define GITS_CTLR 0x0
70
168
#define GITS_IIDR 0x4
71
- Serial ports (UART)
169
+#define GITS_TYPER 0x8
72
-- General-purpose I/Os (GPIO)
170
#define GITS_CBASER 0x80
73
- Analog to Digital Converter (ADC)
171
#define GITS_CWRITER 0x88
74
- SPI controller
172
#define GITS_CREADR 0x90
75
- Timer controller (TIMER)
173
#define GITS_BASER 0x100
76
diff --git a/include/hw/gpio/stm32l4x5_gpio.h b/include/hw/gpio/stm32l4x5_gpio.h
174
175
+#define GITS_TRANSLATER 0x0040
176
+
177
struct GICv3ITSState {
178
SysBusDevice parent_obj;
179
180
@@ -XXX,XX +XXX,XX @@ struct GICv3ITSState {
181
/* Registers */
182
uint32_t ctlr;
183
uint32_t iidr;
184
+ uint64_t typer;
185
uint64_t cbaser;
186
uint64_t cwriter;
187
uint64_t creadr;
188
@@ -XXX,XX +XXX,XX @@ struct GICv3ITSState {
189
190
typedef struct GICv3ITSState GICv3ITSState;
191
192
-void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops);
193
+void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops,
194
+ const MemoryRegionOps *tops);
195
196
#define TYPE_ARM_GICV3_ITS_COMMON "arm-gicv3-its-common"
197
typedef struct GICv3ITSCommonClass GICv3ITSCommonClass;
198
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
199
new file mode 100644
77
new file mode 100644
200
index XXXXXXX..XXXXXXX
78
index XXXXXXX..XXXXXXX
201
--- /dev/null
79
--- /dev/null
202
+++ b/hw/intc/arm_gicv3_its.c
80
+++ b/include/hw/gpio/stm32l4x5_gpio.h
203
@@ -XXX,XX +XXX,XX @@
81
@@ -XXX,XX +XXX,XX @@
204
+/*
82
+/*
205
+ * ITS emulation for a GICv3-based system
83
+ * STM32L4x5 GPIO (General Purpose Input/Ouput)
206
+ *
84
+ *
207
+ * Copyright Linaro.org 2021
85
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
86
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
208
+ *
87
+ *
209
+ * Authors:
88
+ * SPDX-License-Identifier: GPL-2.0-or-later
210
+ * Shashi Mallela <shashi.mallela@linaro.org>
211
+ *
89
+ *
212
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at your
90
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
213
+ * option) any later version. See the COPYING file in the top-level directory.
91
+ * See the COPYING file in the top-level directory.
92
+ */
93
+
94
+/*
95
+ * The reference used is the STMicroElectronics RM0351 Reference manual
96
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
97
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
98
+ */
99
+
100
+#ifndef HW_STM32L4X5_GPIO_H
101
+#define HW_STM32L4X5_GPIO_H
102
+
103
+#include "hw/sysbus.h"
104
+#include "qom/object.h"
105
+
106
+#define TYPE_STM32L4X5_GPIO "stm32l4x5-gpio"
107
+OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5GpioState, STM32L4X5_GPIO)
108
+
109
+#define GPIO_NUM_PINS 16
110
+
111
+struct Stm32l4x5GpioState {
112
+ SysBusDevice parent_obj;
113
+
114
+ MemoryRegion mmio;
115
+
116
+ /* GPIO registers */
117
+ uint32_t moder;
118
+ uint32_t otyper;
119
+ uint32_t ospeedr;
120
+ uint32_t pupdr;
121
+ uint32_t idr;
122
+ uint32_t odr;
123
+ uint32_t lckr;
124
+ uint32_t afrl;
125
+ uint32_t afrh;
126
+ uint32_t ascr;
127
+
128
+ /* GPIO registers reset values */
129
+ uint32_t moder_reset;
130
+ uint32_t ospeedr_reset;
131
+ uint32_t pupdr_reset;
132
+
133
+ /*
134
+ * External driving of pins.
135
+ * The pins can be set externally through the device
136
+ * anonymous input GPIOs lines under certain conditions.
137
+ * The pin must not be in push-pull output mode,
138
+ * and can't be set high in open-drain mode.
139
+ * Pins driven externally and configured to
140
+ * output mode will in general be "disconnected"
141
+ * (see `get_gpio_pinmask_to_disconnect()`)
142
+ */
143
+ uint16_t disconnected_pins;
144
+ uint16_t pins_connected_high;
145
+
146
+ char *name;
147
+ Clock *clk;
148
+ qemu_irq pin[GPIO_NUM_PINS];
149
+};
150
+
151
+#endif
152
diff --git a/hw/gpio/stm32l4x5_gpio.c b/hw/gpio/stm32l4x5_gpio.c
153
new file mode 100644
154
index XXXXXXX..XXXXXXX
155
--- /dev/null
156
+++ b/hw/gpio/stm32l4x5_gpio.c
157
@@ -XXX,XX +XXX,XX @@
158
+/*
159
+ * STM32L4x5 GPIO (General Purpose Input/Ouput)
214
+ *
160
+ *
161
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
162
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
163
+ *
164
+ * SPDX-License-Identifier: GPL-2.0-or-later
165
+ *
166
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
167
+ * See the COPYING file in the top-level directory.
168
+ */
169
+
170
+/*
171
+ * The reference used is the STMicroElectronics RM0351 Reference manual
172
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
173
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
215
+ */
174
+ */
216
+
175
+
217
+#include "qemu/osdep.h"
176
+#include "qemu/osdep.h"
218
+#include "qemu/log.h"
177
+#include "qemu/log.h"
178
+#include "hw/gpio/stm32l4x5_gpio.h"
179
+#include "hw/irq.h"
180
+#include "hw/qdev-clock.h"
219
+#include "hw/qdev-properties.h"
181
+#include "hw/qdev-properties.h"
220
+#include "hw/intc/arm_gicv3_its_common.h"
182
+#include "qapi/visitor.h"
221
+#include "gicv3_internal.h"
222
+#include "qom/object.h"
223
+#include "qapi/error.h"
183
+#include "qapi/error.h"
224
+
184
+#include "migration/vmstate.h"
225
+typedef struct GICv3ITSClass GICv3ITSClass;
185
+#include "trace.h"
226
+/* This is reusing the GICv3ITSState typedef from ARM_GICV3_ITS_COMMON */
186
+
227
+DECLARE_OBJ_CHECKERS(GICv3ITSState, GICv3ITSClass,
187
+#define GPIO_MODER 0x00
228
+ ARM_GICV3_ITS, TYPE_ARM_GICV3_ITS)
188
+#define GPIO_OTYPER 0x04
229
+
189
+#define GPIO_OSPEEDR 0x08
230
+struct GICv3ITSClass {
190
+#define GPIO_PUPDR 0x0C
231
+ GICv3ITSCommonClass parent_class;
191
+#define GPIO_IDR 0x10
232
+ void (*parent_reset)(DeviceState *dev);
192
+#define GPIO_ODR 0x14
193
+#define GPIO_BSRR 0x18
194
+#define GPIO_LCKR 0x1C
195
+#define GPIO_AFRL 0x20
196
+#define GPIO_AFRH 0x24
197
+#define GPIO_BRR 0x28
198
+#define GPIO_ASCR 0x2C
199
+
200
+/* 0b11111111_11111111_00000000_00000000 */
201
+#define RESERVED_BITS_MASK 0xFFFF0000
202
+
203
+static void update_gpio_idr(Stm32l4x5GpioState *s);
204
+
205
+static bool is_pull_up(Stm32l4x5GpioState *s, unsigned pin)
206
+{
207
+ return extract32(s->pupdr, 2 * pin, 2) == 1;
208
+}
209
+
210
+static bool is_pull_down(Stm32l4x5GpioState *s, unsigned pin)
211
+{
212
+ return extract32(s->pupdr, 2 * pin, 2) == 2;
213
+}
214
+
215
+static bool is_output(Stm32l4x5GpioState *s, unsigned pin)
216
+{
217
+ return extract32(s->moder, 2 * pin, 2) == 1;
218
+}
219
+
220
+static bool is_open_drain(Stm32l4x5GpioState *s, unsigned pin)
221
+{
222
+ return extract32(s->otyper, pin, 1) == 1;
223
+}
224
+
225
+static bool is_push_pull(Stm32l4x5GpioState *s, unsigned pin)
226
+{
227
+ return extract32(s->otyper, pin, 1) == 0;
228
+}
229
+
230
+static void stm32l4x5_gpio_reset_hold(Object *obj)
231
+{
232
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
233
+
234
+ s->moder = s->moder_reset;
235
+ s->otyper = 0x00000000;
236
+ s->ospeedr = s->ospeedr_reset;
237
+ s->pupdr = s->pupdr_reset;
238
+ s->idr = 0x00000000;
239
+ s->odr = 0x00000000;
240
+ s->lckr = 0x00000000;
241
+ s->afrl = 0x00000000;
242
+ s->afrh = 0x00000000;
243
+ s->ascr = 0x00000000;
244
+
245
+ s->disconnected_pins = 0xFFFF;
246
+ s->pins_connected_high = 0x0000;
247
+ update_gpio_idr(s);
248
+}
249
+
250
+static void stm32l4x5_gpio_set(void *opaque, int line, int level)
251
+{
252
+ Stm32l4x5GpioState *s = opaque;
253
+ /*
254
+ * The pin isn't set if line is configured in output mode
255
+ * except if level is 0 and the output is open-drain.
256
+ * This way there will be no short-circuit prone situations.
257
+ */
258
+ if (is_output(s, line) && !(is_open_drain(s, line) && (level == 0))) {
259
+ qemu_log_mask(LOG_GUEST_ERROR, "Line %d can't be driven externally\n",
260
+ line);
261
+ return;
262
+ }
263
+
264
+ s->disconnected_pins &= ~(1 << line);
265
+ if (level) {
266
+ s->pins_connected_high |= (1 << line);
267
+ } else {
268
+ s->pins_connected_high &= ~(1 << line);
269
+ }
270
+ trace_stm32l4x5_gpio_pins(s->name, s->disconnected_pins,
271
+ s->pins_connected_high);
272
+ update_gpio_idr(s);
273
+}
274
+
275
+
276
+static void update_gpio_idr(Stm32l4x5GpioState *s)
277
+{
278
+ uint32_t new_idr_mask = 0;
279
+ uint32_t new_idr = s->odr;
280
+ uint32_t old_idr = s->idr;
281
+ int new_pin_state, old_pin_state;
282
+
283
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
284
+ if (is_output(s, i)) {
285
+ if (is_push_pull(s, i)) {
286
+ new_idr_mask |= (1 << i);
287
+ } else if (!(s->odr & (1 << i))) {
288
+ /* open-drain ODR 0 */
289
+ new_idr_mask |= (1 << i);
290
+ /* open-drain ODR 1 */
291
+ } else if (!(s->disconnected_pins & (1 << i)) &&
292
+ !(s->pins_connected_high & (1 << i))) {
293
+ /* open-drain ODR 1 with pin connected low */
294
+ new_idr_mask |= (1 << i);
295
+ new_idr &= ~(1 << i);
296
+ /* open-drain ODR 1 with unactive pin */
297
+ } else if (is_pull_up(s, i)) {
298
+ new_idr_mask |= (1 << i);
299
+ } else if (is_pull_down(s, i)) {
300
+ new_idr_mask |= (1 << i);
301
+ new_idr &= ~(1 << i);
302
+ }
303
+ /*
304
+ * The only case left is for open-drain ODR 1
305
+ * with unactive pin without pull-up or pull-down :
306
+ * the value is floating.
307
+ */
308
+ /* input or analog mode with connected pin */
309
+ } else if (!(s->disconnected_pins & (1 << i))) {
310
+ if (s->pins_connected_high & (1 << i)) {
311
+ /* pin high */
312
+ new_idr_mask |= (1 << i);
313
+ new_idr |= (1 << i);
314
+ } else {
315
+ /* pin low */
316
+ new_idr_mask |= (1 << i);
317
+ new_idr &= ~(1 << i);
318
+ }
319
+ /* input or analog mode with disconnected pin */
320
+ } else {
321
+ if (is_pull_up(s, i)) {
322
+ /* pull-up */
323
+ new_idr_mask |= (1 << i);
324
+ new_idr |= (1 << i);
325
+ } else if (is_pull_down(s, i)) {
326
+ /* pull-down */
327
+ new_idr_mask |= (1 << i);
328
+ new_idr &= ~(1 << i);
329
+ }
330
+ /*
331
+ * The only case left is for a disconnected pin
332
+ * without pull-up or pull-down :
333
+ * the value is floating.
334
+ */
335
+ }
336
+ }
337
+
338
+ s->idr = (old_idr & ~new_idr_mask) | (new_idr & new_idr_mask);
339
+ trace_stm32l4x5_gpio_update_idr(s->name, old_idr, s->idr);
340
+
341
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
342
+ if (new_idr_mask & (1 << i)) {
343
+ new_pin_state = (new_idr & (1 << i)) > 0;
344
+ old_pin_state = (old_idr & (1 << i)) > 0;
345
+ if (new_pin_state > old_pin_state) {
346
+ qemu_irq_raise(s->pin[i]);
347
+ } else if (new_pin_state < old_pin_state) {
348
+ qemu_irq_lower(s->pin[i]);
349
+ }
350
+ }
351
+ }
352
+}
353
+
354
+/*
355
+ * Return mask of pins that are both configured in output
356
+ * mode and externally driven (except pins in open-drain
357
+ * mode externally set to 0).
358
+ */
359
+static uint32_t get_gpio_pinmask_to_disconnect(Stm32l4x5GpioState *s)
360
+{
361
+ uint32_t pins_to_disconnect = 0;
362
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
363
+ /* for each connected pin in output mode */
364
+ if (!(s->disconnected_pins & (1 << i)) && is_output(s, i)) {
365
+ /* if either push-pull or high level */
366
+ if (is_push_pull(s, i) || s->pins_connected_high & (1 << i)) {
367
+ pins_to_disconnect |= (1 << i);
368
+ qemu_log_mask(LOG_GUEST_ERROR,
369
+ "Line %d can't be driven externally\n",
370
+ i);
371
+ }
372
+ }
373
+ }
374
+ return pins_to_disconnect;
375
+}
376
+
377
+/*
378
+ * Set field `disconnected_pins` and call `update_gpio_idr()`
379
+ */
380
+static void disconnect_gpio_pins(Stm32l4x5GpioState *s, uint16_t lines)
381
+{
382
+ s->disconnected_pins |= lines;
383
+ trace_stm32l4x5_gpio_pins(s->name, s->disconnected_pins,
384
+ s->pins_connected_high);
385
+ update_gpio_idr(s);
386
+}
387
+
388
+static void disconnected_pins_set(Object *obj, Visitor *v,
389
+ const char *name, void *opaque, Error **errp)
390
+{
391
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
392
+ uint16_t value;
393
+ if (!visit_type_uint16(v, name, &value, errp)) {
394
+ return;
395
+ }
396
+ disconnect_gpio_pins(s, value);
397
+}
398
+
399
+static void disconnected_pins_get(Object *obj, Visitor *v,
400
+ const char *name, void *opaque, Error **errp)
401
+{
402
+ visit_type_uint16(v, name, (uint16_t *)opaque, errp);
403
+}
404
+
405
+static void clock_freq_get(Object *obj, Visitor *v,
406
+ const char *name, void *opaque, Error **errp)
407
+{
408
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
409
+ uint32_t clock_freq_hz = clock_get_hz(s->clk);
410
+ visit_type_uint32(v, name, &clock_freq_hz, errp);
411
+}
412
+
413
+static void stm32l4x5_gpio_write(void *opaque, hwaddr addr,
414
+ uint64_t val64, unsigned int size)
415
+{
416
+ Stm32l4x5GpioState *s = opaque;
417
+
418
+ uint32_t value = val64;
419
+ trace_stm32l4x5_gpio_write(s->name, addr, val64);
420
+
421
+ switch (addr) {
422
+ case GPIO_MODER:
423
+ s->moder = value;
424
+ disconnect_gpio_pins(s, get_gpio_pinmask_to_disconnect(s));
425
+ qemu_log_mask(LOG_UNIMP,
426
+ "%s: Analog and AF modes aren't supported\n\
427
+ Analog and AF mode behave like input mode\n",
428
+ __func__);
429
+ return;
430
+ case GPIO_OTYPER:
431
+ s->otyper = value & ~RESERVED_BITS_MASK;
432
+ disconnect_gpio_pins(s, get_gpio_pinmask_to_disconnect(s));
433
+ return;
434
+ case GPIO_OSPEEDR:
435
+ qemu_log_mask(LOG_UNIMP,
436
+ "%s: Changing I/O output speed isn't supported\n\
437
+ I/O speed is already maximal\n",
438
+ __func__);
439
+ s->ospeedr = value;
440
+ return;
441
+ case GPIO_PUPDR:
442
+ s->pupdr = value;
443
+ update_gpio_idr(s);
444
+ return;
445
+ case GPIO_IDR:
446
+ qemu_log_mask(LOG_UNIMP,
447
+ "%s: GPIO->IDR is read-only\n",
448
+ __func__);
449
+ return;
450
+ case GPIO_ODR:
451
+ s->odr = value & ~RESERVED_BITS_MASK;
452
+ update_gpio_idr(s);
453
+ return;
454
+ case GPIO_BSRR: {
455
+ uint32_t bits_to_reset = (value & RESERVED_BITS_MASK) >> GPIO_NUM_PINS;
456
+ uint32_t bits_to_set = value & ~RESERVED_BITS_MASK;
457
+ /* If both BSx and BRx are set, BSx has priority.*/
458
+ s->odr &= ~bits_to_reset;
459
+ s->odr |= bits_to_set;
460
+ update_gpio_idr(s);
461
+ return;
462
+ }
463
+ case GPIO_LCKR:
464
+ qemu_log_mask(LOG_UNIMP,
465
+ "%s: Locking port bits configuration isn't supported\n",
466
+ __func__);
467
+ s->lckr = value & ~RESERVED_BITS_MASK;
468
+ return;
469
+ case GPIO_AFRL:
470
+ qemu_log_mask(LOG_UNIMP,
471
+ "%s: Alternate functions aren't supported\n",
472
+ __func__);
473
+ s->afrl = value;
474
+ return;
475
+ case GPIO_AFRH:
476
+ qemu_log_mask(LOG_UNIMP,
477
+ "%s: Alternate functions aren't supported\n",
478
+ __func__);
479
+ s->afrh = value;
480
+ return;
481
+ case GPIO_BRR: {
482
+ uint32_t bits_to_reset = value & ~RESERVED_BITS_MASK;
483
+ s->odr &= ~bits_to_reset;
484
+ update_gpio_idr(s);
485
+ return;
486
+ }
487
+ case GPIO_ASCR:
488
+ qemu_log_mask(LOG_UNIMP,
489
+ "%s: ADC function isn't supported\n",
490
+ __func__);
491
+ s->ascr = value & ~RESERVED_BITS_MASK;
492
+ return;
493
+ default:
494
+ qemu_log_mask(LOG_GUEST_ERROR,
495
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
496
+ }
497
+}
498
+
499
+static uint64_t stm32l4x5_gpio_read(void *opaque, hwaddr addr,
500
+ unsigned int size)
501
+{
502
+ Stm32l4x5GpioState *s = opaque;
503
+
504
+ trace_stm32l4x5_gpio_read(s->name, addr);
505
+
506
+ switch (addr) {
507
+ case GPIO_MODER:
508
+ return s->moder;
509
+ case GPIO_OTYPER:
510
+ return s->otyper;
511
+ case GPIO_OSPEEDR:
512
+ return s->ospeedr;
513
+ case GPIO_PUPDR:
514
+ return s->pupdr;
515
+ case GPIO_IDR:
516
+ return s->idr;
517
+ case GPIO_ODR:
518
+ return s->odr;
519
+ case GPIO_BSRR:
520
+ return 0;
521
+ case GPIO_LCKR:
522
+ return s->lckr;
523
+ case GPIO_AFRL:
524
+ return s->afrl;
525
+ case GPIO_AFRH:
526
+ return s->afrh;
527
+ case GPIO_BRR:
528
+ return 0;
529
+ case GPIO_ASCR:
530
+ return s->ascr;
531
+ default:
532
+ qemu_log_mask(LOG_GUEST_ERROR,
533
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
534
+ return 0;
535
+ }
536
+}
537
+
538
+static const MemoryRegionOps stm32l4x5_gpio_ops = {
539
+ .read = stm32l4x5_gpio_read,
540
+ .write = stm32l4x5_gpio_write,
541
+ .endianness = DEVICE_NATIVE_ENDIAN,
542
+ .impl = {
543
+ .min_access_size = 4,
544
+ .max_access_size = 4,
545
+ .unaligned = false,
546
+ },
547
+ .valid = {
548
+ .min_access_size = 4,
549
+ .max_access_size = 4,
550
+ .unaligned = false,
551
+ },
233
+};
552
+};
234
+
553
+
235
+static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset,
554
+static void stm32l4x5_gpio_init(Object *obj)
236
+ uint64_t data, unsigned size,
555
+{
237
+ MemTxAttrs attrs)
556
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
238
+{
557
+
239
+ return MEMTX_OK;
558
+ memory_region_init_io(&s->mmio, obj, &stm32l4x5_gpio_ops, s,
240
+}
559
+ TYPE_STM32L4X5_GPIO, 0x400);
241
+
560
+
242
+static bool its_writel(GICv3ITSState *s, hwaddr offset,
561
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
243
+ uint64_t value, MemTxAttrs attrs)
562
+
244
+{
563
+ qdev_init_gpio_out(DEVICE(obj), s->pin, GPIO_NUM_PINS);
245
+ bool result = true;
564
+ qdev_init_gpio_in(DEVICE(obj), stm32l4x5_gpio_set, GPIO_NUM_PINS);
246
+
565
+
247
+ return result;
566
+ s->clk = qdev_init_clock_in(DEVICE(s), "clk", NULL, s, 0);
248
+}
567
+
249
+
568
+ object_property_add(obj, "disconnected-pins", "uint16",
250
+static bool its_readl(GICv3ITSState *s, hwaddr offset,
569
+ disconnected_pins_get, disconnected_pins_set,
251
+ uint64_t *data, MemTxAttrs attrs)
570
+ NULL, &s->disconnected_pins);
252
+{
571
+ object_property_add(obj, "clock-freq-hz", "uint32",
253
+ bool result = true;
572
+ clock_freq_get, NULL, NULL, NULL);
254
+
573
+}
255
+ return result;
574
+
256
+}
575
+static void stm32l4x5_gpio_realize(DeviceState *dev, Error **errp)
257
+
576
+{
258
+static bool its_writell(GICv3ITSState *s, hwaddr offset,
577
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(dev);
259
+ uint64_t value, MemTxAttrs attrs)
578
+ if (!clock_has_source(s->clk)) {
260
+{
579
+ error_setg(errp, "GPIO: clk input must be connected");
261
+ bool result = true;
580
+ return;
262
+
581
+ }
263
+ return result;
582
+}
264
+}
583
+
265
+
584
+static const VMStateDescription vmstate_stm32l4x5_gpio = {
266
+static bool its_readll(GICv3ITSState *s, hwaddr offset,
585
+ .name = TYPE_STM32L4X5_GPIO,
267
+ uint64_t *data, MemTxAttrs attrs)
586
+ .version_id = 1,
268
+{
587
+ .minimum_version_id = 1,
269
+ bool result = true;
588
+ .fields = (VMStateField[]){
270
+
589
+ VMSTATE_UINT32(moder, Stm32l4x5GpioState),
271
+ return result;
590
+ VMSTATE_UINT32(otyper, Stm32l4x5GpioState),
272
+}
591
+ VMSTATE_UINT32(ospeedr, Stm32l4x5GpioState),
273
+
592
+ VMSTATE_UINT32(pupdr, Stm32l4x5GpioState),
274
+static MemTxResult gicv3_its_read(void *opaque, hwaddr offset, uint64_t *data,
593
+ VMSTATE_UINT32(idr, Stm32l4x5GpioState),
275
+ unsigned size, MemTxAttrs attrs)
594
+ VMSTATE_UINT32(odr, Stm32l4x5GpioState),
276
+{
595
+ VMSTATE_UINT32(lckr, Stm32l4x5GpioState),
277
+ GICv3ITSState *s = (GICv3ITSState *)opaque;
596
+ VMSTATE_UINT32(afrl, Stm32l4x5GpioState),
278
+ bool result;
597
+ VMSTATE_UINT32(afrh, Stm32l4x5GpioState),
279
+
598
+ VMSTATE_UINT32(ascr, Stm32l4x5GpioState),
280
+ switch (size) {
599
+ VMSTATE_UINT16(disconnected_pins, Stm32l4x5GpioState),
281
+ case 4:
600
+ VMSTATE_UINT16(pins_connected_high, Stm32l4x5GpioState),
282
+ result = its_readl(s, offset, data, attrs);
601
+ VMSTATE_END_OF_LIST()
283
+ break;
602
+ }
284
+ case 8:
285
+ result = its_readll(s, offset, data, attrs);
286
+ break;
287
+ default:
288
+ result = false;
289
+ break;
290
+ }
291
+
292
+ if (!result) {
293
+ qemu_log_mask(LOG_GUEST_ERROR,
294
+ "%s: invalid guest read at offset " TARGET_FMT_plx
295
+ "size %u\n", __func__, offset, size);
296
+ /*
297
+ * The spec requires that reserved registers are RAZ/WI;
298
+ * so use false returns from leaf functions as a way to
299
+ * trigger the guest-error logging but don't return it to
300
+ * the caller, or we'll cause a spurious guest data abort.
301
+ */
302
+ *data = 0;
303
+ }
304
+ return MEMTX_OK;
305
+}
306
+
307
+static MemTxResult gicv3_its_write(void *opaque, hwaddr offset, uint64_t data,
308
+ unsigned size, MemTxAttrs attrs)
309
+{
310
+ GICv3ITSState *s = (GICv3ITSState *)opaque;
311
+ bool result;
312
+
313
+ switch (size) {
314
+ case 4:
315
+ result = its_writel(s, offset, data, attrs);
316
+ break;
317
+ case 8:
318
+ result = its_writell(s, offset, data, attrs);
319
+ break;
320
+ default:
321
+ result = false;
322
+ break;
323
+ }
324
+
325
+ if (!result) {
326
+ qemu_log_mask(LOG_GUEST_ERROR,
327
+ "%s: invalid guest write at offset " TARGET_FMT_plx
328
+ "size %u\n", __func__, offset, size);
329
+ /*
330
+ * The spec requires that reserved registers are RAZ/WI;
331
+ * so use false returns from leaf functions as a way to
332
+ * trigger the guest-error logging but don't return it to
333
+ * the caller, or we'll cause a spurious guest data abort.
334
+ */
335
+ }
336
+ return MEMTX_OK;
337
+}
338
+
339
+static const MemoryRegionOps gicv3_its_control_ops = {
340
+ .read_with_attrs = gicv3_its_read,
341
+ .write_with_attrs = gicv3_its_write,
342
+ .valid.min_access_size = 4,
343
+ .valid.max_access_size = 8,
344
+ .impl.min_access_size = 4,
345
+ .impl.max_access_size = 8,
346
+ .endianness = DEVICE_NATIVE_ENDIAN,
347
+};
603
+};
348
+
604
+
349
+static const MemoryRegionOps gicv3_its_translation_ops = {
605
+static Property stm32l4x5_gpio_properties[] = {
350
+ .write_with_attrs = gicv3_its_translation_write,
606
+ DEFINE_PROP_STRING("name", Stm32l4x5GpioState, name),
351
+ .valid.min_access_size = 2,
607
+ DEFINE_PROP_UINT32("mode-reset", Stm32l4x5GpioState, moder_reset, 0),
352
+ .valid.max_access_size = 4,
608
+ DEFINE_PROP_UINT32("ospeed-reset", Stm32l4x5GpioState, ospeedr_reset, 0),
353
+ .impl.min_access_size = 2,
609
+ DEFINE_PROP_UINT32("pupd-reset", Stm32l4x5GpioState, pupdr_reset, 0),
354
+ .impl.max_access_size = 4,
355
+ .endianness = DEVICE_NATIVE_ENDIAN,
356
+};
357
+
358
+static void gicv3_arm_its_realize(DeviceState *dev, Error **errp)
359
+{
360
+ GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
361
+ int i;
362
+
363
+ for (i = 0; i < s->gicv3->num_cpu; i++) {
364
+ if (!(s->gicv3->cpu[i].gicr_typer & GICR_TYPER_PLPIS)) {
365
+ error_setg(errp, "Physical LPI not supported by CPU %d", i);
366
+ return;
367
+ }
368
+ }
369
+
370
+ gicv3_its_init_mmio(s, &gicv3_its_control_ops, &gicv3_its_translation_ops);
371
+
372
+ /* set the ITS default features supported */
373
+ s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL,
374
+ GITS_TYPE_PHYSICAL);
375
+ s->typer = FIELD_DP64(s->typer, GITS_TYPER, ITT_ENTRY_SIZE,
376
+ ITS_ITT_ENTRY_SIZE - 1);
377
+ s->typer = FIELD_DP64(s->typer, GITS_TYPER, IDBITS, ITS_IDBITS);
378
+ s->typer = FIELD_DP64(s->typer, GITS_TYPER, DEVBITS, ITS_DEVBITS);
379
+ s->typer = FIELD_DP64(s->typer, GITS_TYPER, CIL, 1);
380
+ s->typer = FIELD_DP64(s->typer, GITS_TYPER, CIDBITS, ITS_CIDBITS);
381
+}
382
+
383
+static void gicv3_its_reset(DeviceState *dev)
384
+{
385
+ GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
386
+ GICv3ITSClass *c = ARM_GICV3_ITS_GET_CLASS(s);
387
+
388
+ c->parent_reset(dev);
389
+
390
+ /* Quiescent bit reset to 1 */
391
+ s->ctlr = FIELD_DP32(s->ctlr, GITS_CTLR, QUIESCENT, 1);
392
+
393
+ /*
394
+ * setting GITS_BASER0.Type = 0b001 (Device)
395
+ * GITS_BASER1.Type = 0b100 (Collection Table)
396
+ * GITS_BASER<n>.Type,where n = 3 to 7 are 0b00 (Unimplemented)
397
+ * GITS_BASER<0,1>.Page_Size = 64KB
398
+ * and default translation table entry size to 16 bytes
399
+ */
400
+ s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, TYPE,
401
+ GITS_BASER_TYPE_DEVICE);
402
+ s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, PAGESIZE,
403
+ GITS_BASER_PAGESIZE_64K);
404
+ s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, ENTRYSIZE,
405
+ GITS_DTE_SIZE - 1);
406
+
407
+ s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, TYPE,
408
+ GITS_BASER_TYPE_COLLECTION);
409
+ s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, PAGESIZE,
410
+ GITS_BASER_PAGESIZE_64K);
411
+ s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, ENTRYSIZE,
412
+ GITS_CTE_SIZE - 1);
413
+}
414
+
415
+static Property gicv3_its_props[] = {
416
+ DEFINE_PROP_LINK("parent-gicv3", GICv3ITSState, gicv3, "arm-gicv3",
417
+ GICv3State *),
418
+ DEFINE_PROP_END_OF_LIST(),
610
+ DEFINE_PROP_END_OF_LIST(),
419
+};
611
+};
420
+
612
+
421
+static void gicv3_its_class_init(ObjectClass *klass, void *data)
613
+static void stm32l4x5_gpio_class_init(ObjectClass *klass, void *data)
422
+{
614
+{
423
+ DeviceClass *dc = DEVICE_CLASS(klass);
615
+ DeviceClass *dc = DEVICE_CLASS(klass);
424
+ GICv3ITSClass *ic = ARM_GICV3_ITS_CLASS(klass);
616
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
425
+
617
+
426
+ dc->realize = gicv3_arm_its_realize;
618
+ device_class_set_props(dc, stm32l4x5_gpio_properties);
427
+ device_class_set_props(dc, gicv3_its_props);
619
+ dc->vmsd = &vmstate_stm32l4x5_gpio;
428
+ device_class_set_parent_reset(dc, gicv3_its_reset, &ic->parent_reset);
620
+ dc->realize = stm32l4x5_gpio_realize;
429
+}
621
+ rc->phases.hold = stm32l4x5_gpio_reset_hold;
430
+
622
+}
431
+static const TypeInfo gicv3_its_info = {
623
+
432
+ .name = TYPE_ARM_GICV3_ITS,
624
+static const TypeInfo stm32l4x5_gpio_types[] = {
433
+ .parent = TYPE_ARM_GICV3_ITS_COMMON,
625
+ {
434
+ .instance_size = sizeof(GICv3ITSState),
626
+ .name = TYPE_STM32L4X5_GPIO,
435
+ .class_init = gicv3_its_class_init,
627
+ .parent = TYPE_SYS_BUS_DEVICE,
436
+ .class_size = sizeof(GICv3ITSClass),
628
+ .instance_size = sizeof(Stm32l4x5GpioState),
629
+ .instance_init = stm32l4x5_gpio_init,
630
+ .class_init = stm32l4x5_gpio_class_init,
631
+ },
437
+};
632
+};
438
+
633
+
439
+static void gicv3_its_register_types(void)
634
+DEFINE_TYPES(stm32l4x5_gpio_types)
440
+{
635
diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
441
+ type_register_static(&gicv3_its_info);
442
+}
443
+
444
+type_init(gicv3_its_register_types)
445
diff --git a/hw/intc/arm_gicv3_its_common.c b/hw/intc/arm_gicv3_its_common.c
446
index XXXXXXX..XXXXXXX 100644
636
index XXXXXXX..XXXXXXX 100644
447
--- a/hw/intc/arm_gicv3_its_common.c
637
--- a/hw/gpio/Kconfig
448
+++ b/hw/intc/arm_gicv3_its_common.c
638
+++ b/hw/gpio/Kconfig
449
@@ -XXX,XX +XXX,XX @@ static int gicv3_its_post_load(void *opaque, int version_id)
639
@@ -XXX,XX +XXX,XX @@ config GPIO_PWR
450
640
451
static const VMStateDescription vmstate_its = {
641
config SIFIVE_GPIO
452
.name = "arm_gicv3_its",
642
bool
453
+ .version_id = 1,
643
+
454
+ .minimum_version_id = 1,
644
+config STM32L4X5_GPIO
455
.pre_save = gicv3_its_pre_save,
645
+ bool
456
.post_load = gicv3_its_post_load,
646
diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
457
.priority = MIG_PRI_GICV3_ITS,
458
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps gicv3_its_trans_ops = {
459
.endianness = DEVICE_NATIVE_ENDIAN,
460
};
461
462
-void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops)
463
+void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops,
464
+ const MemoryRegionOps *tops)
465
{
466
SysBusDevice *sbd = SYS_BUS_DEVICE(s);
467
468
memory_region_init_io(&s->iomem_its_cntrl, OBJECT(s), ops, s,
469
"control", ITS_CONTROL_SIZE);
470
memory_region_init_io(&s->iomem_its_translation, OBJECT(s),
471
- &gicv3_its_trans_ops, s,
472
+ tops ? tops : &gicv3_its_trans_ops, s,
473
"translation", ITS_TRANS_SIZE);
474
475
/* Our two regions are always adjacent, therefore we now combine them
476
diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c
477
index XXXXXXX..XXXXXXX 100644
647
index XXXXXXX..XXXXXXX 100644
478
--- a/hw/intc/arm_gicv3_its_kvm.c
648
--- a/hw/gpio/meson.build
479
+++ b/hw/intc/arm_gicv3_its_kvm.c
649
+++ b/hw/gpio/meson.build
480
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_its_realize(DeviceState *dev, Error **errp)
650
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_RASPI', if_true: files(
481
kvm_arm_register_device(&s->iomem_its_cntrl, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
651
'bcm2835_gpio.c',
482
KVM_VGIC_ITS_ADDR_TYPE, s->dev_fd, 0);
652
'bcm2838_gpio.c'
483
653
))
484
- gicv3_its_init_mmio(s, NULL);
654
+system_ss.add(when: 'CONFIG_STM32L4X5_SOC', if_true: files('stm32l4x5_gpio.c'))
485
+ gicv3_its_init_mmio(s, NULL, NULL);
655
system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_gpio.c'))
486
656
system_ss.add(when: 'CONFIG_SIFIVE_GPIO', if_true: files('sifive_gpio.c'))
487
if (!kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
657
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
488
GITS_CTLR)) {
489
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
490
index XXXXXXX..XXXXXXX 100644
658
index XXXXXXX..XXXXXXX 100644
491
--- a/hw/intc/meson.build
659
--- a/hw/gpio/trace-events
492
+++ b/hw/intc/meson.build
660
+++ b/hw/gpio/trace-events
493
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_ARM_GIC', if_true: files(
661
@@ -XXX,XX +XXX,XX @@ sifive_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " val
494
'arm_gicv3_dist.c',
662
# aspeed_gpio.c
495
'arm_gicv3_its_common.c',
663
aspeed_gpio_read(uint64_t offset, uint64_t value) "offset: 0x%" PRIx64 " value 0x%" PRIx64
496
'arm_gicv3_redist.c',
664
aspeed_gpio_write(uint64_t offset, uint64_t value) "offset: 0x%" PRIx64 " value 0x%" PRIx64
497
+ 'arm_gicv3_its.c',
665
+
498
))
666
+# stm32l4x5_gpio.c
499
softmmu_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_pic.c'))
667
+stm32l4x5_gpio_read(char *gpio, uint64_t addr) "GPIO%s addr: 0x%" PRIx64 " "
500
softmmu_ss.add(when: 'CONFIG_HEATHROW_PIC', if_true: files('heathrow_pic.c'))
668
+stm32l4x5_gpio_write(char *gpio, uint64_t addr, uint64_t data) "GPIO%s addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
669
+stm32l4x5_gpio_update_idr(char *gpio, uint32_t old_idr, uint32_t new_idr) "GPIO%s from: 0x%x to: 0x%x"
670
+stm32l4x5_gpio_pins(char *gpio, uint16_t disconnected, uint16_t high) "GPIO%s disconnected pins: 0x%x levels: 0x%x"
501
--
671
--
502
2.20.1
672
2.34.1
503
673
504
674
diff view generated by jsdifflib
1
From: Shashi Mallela <shashi.mallela@linaro.org>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
Added ITS command queue handling for MAPTI,MAPI commands,handled ITS
3
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
4
translation which triggers an LPI via INT command as well as write
4
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
5
to GITS_TRANSLATER register,defined enum to differentiate between ITS
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
command interrupt trigger and GITS_TRANSLATER based interrupt trigger.
6
Acked-by: Alistair Francis <alistair.francis@wdc.com>
7
Each of these commands make use of other functionalities implemented to
7
Message-id: 20240305210444.310665-3-ines.varhol@telecom-paris.fr
8
get device table entry,collection table entry or interrupt translation
9
table entry required for their processing.
10
11
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Message-id: 20210910143951.92242-5-shashi.mallela@linaro.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
9
---
16
hw/intc/gicv3_internal.h | 12 +
10
include/hw/arm/stm32l4x5_soc.h | 2 +
17
include/hw/intc/arm_gicv3_common.h | 2 +
11
include/hw/gpio/stm32l4x5_gpio.h | 1 +
18
hw/intc/arm_gicv3_its.c | 365 ++++++++++++++++++++++++++++-
12
include/hw/misc/stm32l4x5_syscfg.h | 3 +-
19
3 files changed, 378 insertions(+), 1 deletion(-)
13
hw/arm/stm32l4x5_soc.c | 71 +++++++++++++++++++++++-------
20
14
hw/misc/stm32l4x5_syscfg.c | 1 +
21
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
15
hw/arm/Kconfig | 3 +-
22
index XXXXXXX..XXXXXXX 100644
16
6 files changed, 63 insertions(+), 18 deletions(-)
23
--- a/hw/intc/gicv3_internal.h
17
24
+++ b/hw/intc/gicv3_internal.h
18
diff --git a/include/hw/arm/stm32l4x5_soc.h b/include/hw/arm/stm32l4x5_soc.h
25
@@ -XXX,XX +XXX,XX @@ FIELD(MAPC, RDBASE, 16, 32)
19
index XXXXXXX..XXXXXXX 100644
26
#define ITTADDR_MASK MAKE_64BIT_MASK(ITTADDR_SHIFT, ITTADDR_LENGTH)
20
--- a/include/hw/arm/stm32l4x5_soc.h
27
#define SIZE_MASK 0x1f
21
+++ b/include/hw/arm/stm32l4x5_soc.h
28
22
@@ -XXX,XX +XXX,XX @@
29
+/* MAPI command fields */
23
#include "hw/misc/stm32l4x5_syscfg.h"
30
+#define EVENTID_MASK ((1ULL << 32) - 1)
24
#include "hw/misc/stm32l4x5_exti.h"
31
+
25
#include "hw/misc/stm32l4x5_rcc.h"
32
+/* MAPTI command fields */
26
+#include "hw/gpio/stm32l4x5_gpio.h"
33
+#define pINTID_SHIFT 32
27
#include "qom/object.h"
34
+#define pINTID_MASK MAKE_64BIT_MASK(32, 32)
28
35
+
29
#define TYPE_STM32L4X5_SOC "stm32l4x5-soc"
36
#define DEVID_SHIFT 32
30
@@ -XXX,XX +XXX,XX @@ struct Stm32l4x5SocState {
37
#define DEVID_MASK MAKE_64BIT_MASK(32, 32)
31
OrIRQState exti_or_gates[NUM_EXTI_OR_GATES];
38
32
Stm32l4x5SyscfgState syscfg;
39
@@ -XXX,XX +XXX,XX @@ FIELD(MAPC, RDBASE, 16, 32)
33
Stm32l4x5RccState rcc;
40
* Values: | vPEID | ICID |
34
+ Stm32l4x5GpioState gpio[NUM_GPIOS];
41
*/
35
42
#define ITS_ITT_ENTRY_SIZE 0xC
36
MemoryRegion sram1;
43
+#define ITE_ENTRY_INTTYPE_SHIFT 1
37
MemoryRegion sram2;
44
+#define ITE_ENTRY_INTID_SHIFT 2
38
diff --git a/include/hw/gpio/stm32l4x5_gpio.h b/include/hw/gpio/stm32l4x5_gpio.h
45
+#define ITE_ENTRY_INTID_MASK MAKE_64BIT_MASK(2, 24)
39
index XXXXXXX..XXXXXXX 100644
46
+#define ITE_ENTRY_INTSP_SHIFT 26
40
--- a/include/hw/gpio/stm32l4x5_gpio.h
47
+#define ITE_ENTRY_ICID_MASK MAKE_64BIT_MASK(0, 16)
41
+++ b/include/hw/gpio/stm32l4x5_gpio.h
48
42
@@ -XXX,XX +XXX,XX @@
49
/* 16 bits EventId */
43
#define TYPE_STM32L4X5_GPIO "stm32l4x5-gpio"
50
#define ITS_IDBITS GICD_TYPER_IDBITS
44
OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5GpioState, STM32L4X5_GPIO)
51
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
45
52
index XXXXXXX..XXXXXXX 100644
46
+#define NUM_GPIOS 8
53
--- a/include/hw/intc/arm_gicv3_common.h
47
#define GPIO_NUM_PINS 16
54
+++ b/include/hw/intc/arm_gicv3_common.h
48
55
@@ -XXX,XX +XXX,XX @@
49
struct Stm32l4x5GpioState {
56
#define GICV3_MAXIRQ 1020
50
diff --git a/include/hw/misc/stm32l4x5_syscfg.h b/include/hw/misc/stm32l4x5_syscfg.h
57
#define GICV3_MAXSPI (GICV3_MAXIRQ - GIC_INTERNAL)
51
index XXXXXXX..XXXXXXX 100644
58
52
--- a/include/hw/misc/stm32l4x5_syscfg.h
59
+#define GICV3_LPI_INTID_START 8192
53
+++ b/include/hw/misc/stm32l4x5_syscfg.h
60
+
54
@@ -XXX,XX +XXX,XX @@
61
#define GICV3_REDIST_SIZE 0x20000
55
62
56
#include "hw/sysbus.h"
63
/* Number of SGI target-list bits */
57
#include "qom/object.h"
64
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
58
+#include "hw/gpio/stm32l4x5_gpio.h"
65
index XXXXXXX..XXXXXXX 100644
59
66
--- a/hw/intc/arm_gicv3_its.c
60
#define TYPE_STM32L4X5_SYSCFG "stm32l4x5-syscfg"
67
+++ b/hw/intc/arm_gicv3_its.c
61
OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5SyscfgState, STM32L4X5_SYSCFG)
68
@@ -XXX,XX +XXX,XX @@ struct GICv3ITSClass {
62
69
void (*parent_reset)(DeviceState *dev);
63
-#define NUM_GPIOS 8
64
-#define GPIO_NUM_PINS 16
65
#define SYSCFG_NUM_EXTICR 4
66
67
struct Stm32l4x5SyscfgState {
68
diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/hw/arm/stm32l4x5_soc.c
71
+++ b/hw/arm/stm32l4x5_soc.c
72
@@ -XXX,XX +XXX,XX @@
73
#include "sysemu/sysemu.h"
74
#include "hw/or-irq.h"
75
#include "hw/arm/stm32l4x5_soc.h"
76
+#include "hw/gpio/stm32l4x5_gpio.h"
77
#include "hw/qdev-clock.h"
78
#include "hw/misc/unimp.h"
79
80
@@ -XXX,XX +XXX,XX @@ static const int exti_or_gate1_lines_in[EXTI_OR_GATE1_NUM_LINES_IN] = {
81
16, 35, 36, 37, 38,
70
};
82
};
71
83
72
+/*
84
+static const struct {
73
+ * This is an internal enum used to distinguish between LPI triggered
85
+ uint32_t addr;
74
+ * via command queue and LPI triggered via gits_translater write.
86
+ uint32_t moder_reset;
75
+ */
87
+ uint32_t ospeedr_reset;
76
+typedef enum ItsCmdType {
88
+ uint32_t pupdr_reset;
77
+ NONE = 0, /* internal indication for GITS_TRANSLATER write */
89
+} stm32l4x5_gpio_cfg[NUM_GPIOS] = {
78
+ CLEAR = 1,
90
+ { 0x48000000, 0xABFFFFFF, 0x0C000000, 0x64000000 },
79
+ DISCARD = 2,
91
+ { 0x48000400, 0xFFFFFEBF, 0x00000000, 0x00000100 },
80
+ INT = 3,
92
+ { 0x48000800, 0xFFFFFFFF, 0x00000000, 0x00000000 },
81
+} ItsCmdType;
93
+ { 0x48000C00, 0xFFFFFFFF, 0x00000000, 0x00000000 },
82
+
94
+ { 0x48001000, 0xFFFFFFFF, 0x00000000, 0x00000000 },
83
+typedef struct {
95
+ { 0x48001400, 0xFFFFFFFF, 0x00000000, 0x00000000 },
84
+ uint32_t iteh;
96
+ { 0x48001800, 0xFFFFFFFF, 0x00000000, 0x00000000 },
85
+ uint64_t itel;
97
+ { 0x48001C00, 0x0000000F, 0x00000000, 0x00000000 },
86
+} IteEntry;
98
+};
87
+
99
+
88
static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
100
static void stm32l4x5_soc_initfn(Object *obj)
89
{
101
{
90
uint64_t result = 0;
102
Stm32l4x5SocState *s = STM32L4X5_SOC(obj);
91
@@ -XXX,XX +XXX,XX @@ static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
103
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_initfn(Object *obj)
92
return result;
104
}
105
object_initialize_child(obj, "syscfg", &s->syscfg, TYPE_STM32L4X5_SYSCFG);
106
object_initialize_child(obj, "rcc", &s->rcc, TYPE_STM32L4X5_RCC);
107
+
108
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
109
+ g_autofree char *name = g_strdup_printf("gpio%c", 'a' + i);
110
+ object_initialize_child(obj, name, &s->gpio[i], TYPE_STM32L4X5_GPIO);
111
+ }
93
}
112
}
94
113
95
+static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte,
114
static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
96
+ MemTxResult *res)
115
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
97
+{
116
Stm32l4x5SocState *s = STM32L4X5_SOC(dev_soc);
98
+ AddressSpace *as = &s->gicv3->dma_as;
117
const Stm32l4x5SocClass *sc = STM32L4X5_SOC_GET_CLASS(dev_soc);
99
+ uint64_t l2t_addr;
118
MemoryRegion *system_memory = get_system_memory();
100
+ uint64_t value;
119
- DeviceState *armv7m;
101
+ bool valid_l2t;
120
+ DeviceState *armv7m, *dev;
102
+ uint32_t l2t_id;
121
SysBusDevice *busdev;
103
+ uint32_t max_l2_entries;
122
+ uint32_t pin_index;
104
+
123
105
+ if (s->ct.indirect) {
124
if (!memory_region_init_rom(&s->flash, OBJECT(dev_soc), "flash",
106
+ l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE);
125
sc->flash_size, errp)) {
107
+
126
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
108
+ value = address_space_ldq_le(as,
127
return;
109
+ s->ct.base_addr +
128
}
110
+ (l2t_id * L1TABLE_ENTRY_SIZE),
129
111
+ MEMTXATTRS_UNSPECIFIED, res);
130
+ /* GPIOs */
112
+
131
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
113
+ if (*res == MEMTX_OK) {
132
+ g_autofree char *name = g_strdup_printf("%c", 'A' + i);
114
+ valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
133
+ dev = DEVICE(&s->gpio[i]);
115
+
134
+ qdev_prop_set_string(dev, "name", name);
116
+ if (valid_l2t) {
135
+ qdev_prop_set_uint32(dev, "mode-reset",
117
+ max_l2_entries = s->ct.page_sz / s->ct.entry_sz;
136
+ stm32l4x5_gpio_cfg[i].moder_reset);
118
+
137
+ qdev_prop_set_uint32(dev, "ospeed-reset",
119
+ l2t_addr = value & ((1ULL << 51) - 1);
138
+ stm32l4x5_gpio_cfg[i].ospeedr_reset);
120
+
139
+ qdev_prop_set_uint32(dev, "pupd-reset",
121
+ *cte = address_space_ldq_le(as, l2t_addr +
140
+ stm32l4x5_gpio_cfg[i].pupdr_reset);
122
+ ((icid % max_l2_entries) * GITS_CTE_SIZE),
141
+ busdev = SYS_BUS_DEVICE(&s->gpio[i]);
123
+ MEMTXATTRS_UNSPECIFIED, res);
142
+ g_free(name);
124
+ }
143
+ name = g_strdup_printf("gpio%c-out", 'a' + i);
125
+ }
144
+ qdev_connect_clock_in(DEVICE(&s->gpio[i]), "clk",
126
+ } else {
145
+ qdev_get_clock_out(DEVICE(&(s->rcc)), name));
127
+ /* Flat level table */
146
+ if (!sysbus_realize(busdev, errp)) {
128
+ *cte = address_space_ldq_le(as, s->ct.base_addr +
147
+ return;
129
+ (icid * GITS_CTE_SIZE),
148
+ }
130
+ MEMTXATTRS_UNSPECIFIED, res);
149
+ sysbus_mmio_map(busdev, 0, stm32l4x5_gpio_cfg[i].addr);
131
+ }
150
+ }
132
+
151
+
133
+ return (*cte & TABLE_ENTRY_VALID_MASK) != 0;
152
/* System configuration controller */
134
+}
153
busdev = SYS_BUS_DEVICE(&s->syscfg);
135
+
154
if (!sysbus_realize(busdev, errp)) {
136
+static bool update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
155
return;
137
+ IteEntry ite)
156
}
138
+{
157
sysbus_mmio_map(busdev, 0, SYSCFG_ADDR);
139
+ AddressSpace *as = &s->gicv3->dma_as;
158
- /*
140
+ uint64_t itt_addr;
159
- * TODO: when the GPIO device is implemented, connect it
141
+ MemTxResult res = MEMTX_OK;
160
- * to SYCFG using `qdev_connect_gpio_out`, NUM_GPIOS and
142
+
161
- * GPIO_NUM_PINS.
143
+ itt_addr = (dte & GITS_DTE_ITTADDR_MASK) >> GITS_DTE_ITTADDR_SHIFT;
162
- */
144
+ itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
163
+
145
+
164
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
146
+ address_space_stq_le(as, itt_addr + (eventid * (sizeof(uint64_t) +
165
+ for (unsigned j = 0; j < GPIO_NUM_PINS; j++) {
147
+ sizeof(uint32_t))), ite.itel, MEMTXATTRS_UNSPECIFIED,
166
+ pin_index = GPIO_NUM_PINS * i + j;
148
+ &res);
167
+ qdev_connect_gpio_out(DEVICE(&s->gpio[i]), j,
149
+
168
+ qdev_get_gpio_in(DEVICE(&s->syscfg),
150
+ if (res == MEMTX_OK) {
169
+ pin_index));
151
+ address_space_stl_le(as, itt_addr + (eventid * (sizeof(uint64_t) +
152
+ sizeof(uint32_t))) + sizeof(uint32_t), ite.iteh,
153
+ MEMTXATTRS_UNSPECIFIED, &res);
154
+ }
155
+ if (res != MEMTX_OK) {
156
+ return false;
157
+ } else {
158
+ return true;
159
+ }
160
+}
161
+
162
+static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
163
+ uint16_t *icid, uint32_t *pIntid, MemTxResult *res)
164
+{
165
+ AddressSpace *as = &s->gicv3->dma_as;
166
+ uint64_t itt_addr;
167
+ bool status = false;
168
+ IteEntry ite = {};
169
+
170
+ itt_addr = (dte & GITS_DTE_ITTADDR_MASK) >> GITS_DTE_ITTADDR_SHIFT;
171
+ itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
172
+
173
+ ite.itel = address_space_ldq_le(as, itt_addr +
174
+ (eventid * (sizeof(uint64_t) +
175
+ sizeof(uint32_t))), MEMTXATTRS_UNSPECIFIED,
176
+ res);
177
+
178
+ if (*res == MEMTX_OK) {
179
+ ite.iteh = address_space_ldl_le(as, itt_addr +
180
+ (eventid * (sizeof(uint64_t) +
181
+ sizeof(uint32_t))) + sizeof(uint32_t),
182
+ MEMTXATTRS_UNSPECIFIED, res);
183
+
184
+ if (*res == MEMTX_OK) {
185
+ if (ite.itel & TABLE_ENTRY_VALID_MASK) {
186
+ if ((ite.itel >> ITE_ENTRY_INTTYPE_SHIFT) &
187
+ GITS_TYPE_PHYSICAL) {
188
+ *pIntid = (ite.itel & ITE_ENTRY_INTID_MASK) >>
189
+ ITE_ENTRY_INTID_SHIFT;
190
+ *icid = ite.iteh & ITE_ENTRY_ICID_MASK;
191
+ status = true;
192
+ }
193
+ }
194
+ }
170
+ }
195
+ }
171
+ }
196
+ return status;
172
197
+}
173
/* EXTI device */
198
+
174
busdev = SYS_BUS_DEVICE(&s->exti);
199
+static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res)
175
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
200
+{
176
}
201
+ AddressSpace *as = &s->gicv3->dma_as;
177
}
202
+ uint64_t l2t_addr;
178
203
+ uint64_t value;
179
- for (unsigned i = 0; i < 16; i++) {
204
+ bool valid_l2t;
180
+ for (unsigned i = 0; i < GPIO_NUM_PINS; i++) {
205
+ uint32_t l2t_id;
181
qdev_connect_gpio_out(DEVICE(&s->syscfg), i,
206
+ uint32_t max_l2_entries;
182
qdev_get_gpio_in(DEVICE(&s->exti), i));
207
+
183
}
208
+ if (s->dt.indirect) {
184
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
209
+ l2t_id = devid / (s->dt.page_sz / L1TABLE_ENTRY_SIZE);
185
/* RESERVED: 0x40024400, 0x7FDBC00 */
210
+
186
211
+ value = address_space_ldq_le(as,
187
/* AHB2 BUS */
212
+ s->dt.base_addr +
188
- create_unimplemented_device("GPIOA", 0x48000000, 0x400);
213
+ (l2t_id * L1TABLE_ENTRY_SIZE),
189
- create_unimplemented_device("GPIOB", 0x48000400, 0x400);
214
+ MEMTXATTRS_UNSPECIFIED, res);
190
- create_unimplemented_device("GPIOC", 0x48000800, 0x400);
215
+
191
- create_unimplemented_device("GPIOD", 0x48000C00, 0x400);
216
+ if (*res == MEMTX_OK) {
192
- create_unimplemented_device("GPIOE", 0x48001000, 0x400);
217
+ valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
193
- create_unimplemented_device("GPIOF", 0x48001400, 0x400);
218
+
194
- create_unimplemented_device("GPIOG", 0x48001800, 0x400);
219
+ if (valid_l2t) {
195
- create_unimplemented_device("GPIOH", 0x48001C00, 0x400);
220
+ max_l2_entries = s->dt.page_sz / s->dt.entry_sz;
196
/* RESERVED: 0x48002000, 0x7FDBC00 */
221
+
197
create_unimplemented_device("OTG_FS", 0x50000000, 0x40000);
222
+ l2t_addr = value & ((1ULL << 51) - 1);
198
create_unimplemented_device("ADC", 0x50040000, 0x400);
223
+
199
diff --git a/hw/misc/stm32l4x5_syscfg.c b/hw/misc/stm32l4x5_syscfg.c
224
+ value = address_space_ldq_le(as, l2t_addr +
200
index XXXXXXX..XXXXXXX 100644
225
+ ((devid % max_l2_entries) * GITS_DTE_SIZE),
201
--- a/hw/misc/stm32l4x5_syscfg.c
226
+ MEMTXATTRS_UNSPECIFIED, res);
202
+++ b/hw/misc/stm32l4x5_syscfg.c
227
+ }
203
@@ -XXX,XX +XXX,XX @@
228
+ }
204
#include "hw/irq.h"
229
+ } else {
205
#include "migration/vmstate.h"
230
+ /* Flat level table */
206
#include "hw/misc/stm32l4x5_syscfg.h"
231
+ value = address_space_ldq_le(as, s->dt.base_addr +
207
+#include "hw/gpio/stm32l4x5_gpio.h"
232
+ (devid * GITS_DTE_SIZE),
208
233
+ MEMTXATTRS_UNSPECIFIED, res);
209
#define SYSCFG_MEMRMP 0x00
234
+ }
210
#define SYSCFG_CFGR1 0x04
235
+
211
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
236
+ return value;
212
index XXXXXXX..XXXXXXX 100644
237
+}
213
--- a/hw/arm/Kconfig
238
+
214
+++ b/hw/arm/Kconfig
239
+/*
215
@@ -XXX,XX +XXX,XX @@ config STM32L4X5_SOC
240
+ * This function handles the processing of following commands based on
216
bool
241
+ * the ItsCmdType parameter passed:-
217
select ARM_V7M
242
+ * 1. triggering of lpi interrupt translation via ITS INT command
218
select OR_IRQ
243
+ * 2. triggering of lpi interrupt translation via gits_translater register
219
- select STM32L4X5_SYSCFG
244
+ * 3. handling of ITS CLEAR command
220
select STM32L4X5_EXTI
245
+ * 4. handling of ITS DISCARD command
221
+ select STM32L4X5_SYSCFG
246
+ */
222
select STM32L4X5_RCC
247
+static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
223
+ select STM32L4X5_GPIO
248
+ ItsCmdType cmd)
224
249
+{
225
config XLNX_ZYNQMP_ARM
250
+ AddressSpace *as = &s->gicv3->dma_as;
226
bool
251
+ uint32_t devid, eventid;
252
+ MemTxResult res = MEMTX_OK;
253
+ bool dte_valid;
254
+ uint64_t dte = 0;
255
+ uint32_t max_eventid;
256
+ uint16_t icid = 0;
257
+ uint32_t pIntid = 0;
258
+ bool ite_valid = false;
259
+ uint64_t cte = 0;
260
+ bool cte_valid = false;
261
+ bool result = false;
262
+
263
+ if (cmd == NONE) {
264
+ devid = offset;
265
+ } else {
266
+ devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
267
+
268
+ offset += NUM_BYTES_IN_DW;
269
+ value = address_space_ldq_le(as, s->cq.base_addr + offset,
270
+ MEMTXATTRS_UNSPECIFIED, &res);
271
+ }
272
+
273
+ if (res != MEMTX_OK) {
274
+ return result;
275
+ }
276
+
277
+ eventid = (value & EVENTID_MASK);
278
+
279
+ dte = get_dte(s, devid, &res);
280
+
281
+ if (res != MEMTX_OK) {
282
+ return result;
283
+ }
284
+ dte_valid = dte & TABLE_ENTRY_VALID_MASK;
285
+
286
+ if (dte_valid) {
287
+ max_eventid = (1UL << (((dte >> 1U) & SIZE_MASK) + 1));
288
+
289
+ ite_valid = get_ite(s, eventid, dte, &icid, &pIntid, &res);
290
+
291
+ if (res != MEMTX_OK) {
292
+ return result;
293
+ }
294
+
295
+ if (ite_valid) {
296
+ cte_valid = get_cte(s, icid, &cte, &res);
297
+ }
298
+
299
+ if (res != MEMTX_OK) {
300
+ return result;
301
+ }
302
+ }
303
+
304
+ if ((devid > s->dt.maxids.max_devids) || !dte_valid || !ite_valid ||
305
+ !cte_valid || (eventid > max_eventid)) {
306
+ qemu_log_mask(LOG_GUEST_ERROR,
307
+ "%s: invalid command attributes "
308
+ "devid %d or eventid %d or invalid dte %d or"
309
+ "invalid cte %d or invalid ite %d\n",
310
+ __func__, devid, eventid, dte_valid, cte_valid,
311
+ ite_valid);
312
+ /*
313
+ * in this implementation, in case of error
314
+ * we ignore this command and move onto the next
315
+ * command in the queue
316
+ */
317
+ } else {
318
+ /*
319
+ * Current implementation only supports rdbase == procnum
320
+ * Hence rdbase physical address is ignored
321
+ */
322
+ if (cmd == DISCARD) {
323
+ IteEntry ite = {};
324
+ /* remove mapping from interrupt translation table */
325
+ result = update_ite(s, eventid, dte, ite);
326
+ }
327
+ }
328
+
329
+ return result;
330
+}
331
+
332
+static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
333
+ bool ignore_pInt)
334
+{
335
+ AddressSpace *as = &s->gicv3->dma_as;
336
+ uint32_t devid, eventid;
337
+ uint32_t pIntid = 0;
338
+ uint32_t max_eventid, max_Intid;
339
+ bool dte_valid;
340
+ MemTxResult res = MEMTX_OK;
341
+ uint16_t icid = 0;
342
+ uint64_t dte = 0;
343
+ IteEntry ite;
344
+ uint32_t int_spurious = INTID_SPURIOUS;
345
+ bool result = false;
346
+
347
+ devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
348
+ offset += NUM_BYTES_IN_DW;
349
+ value = address_space_ldq_le(as, s->cq.base_addr + offset,
350
+ MEMTXATTRS_UNSPECIFIED, &res);
351
+
352
+ if (res != MEMTX_OK) {
353
+ return result;
354
+ }
355
+
356
+ eventid = (value & EVENTID_MASK);
357
+
358
+ if (!ignore_pInt) {
359
+ pIntid = ((value & pINTID_MASK) >> pINTID_SHIFT);
360
+ }
361
+
362
+ offset += NUM_BYTES_IN_DW;
363
+ value = address_space_ldq_le(as, s->cq.base_addr + offset,
364
+ MEMTXATTRS_UNSPECIFIED, &res);
365
+
366
+ if (res != MEMTX_OK) {
367
+ return result;
368
+ }
369
+
370
+ icid = value & ICID_MASK;
371
+
372
+ dte = get_dte(s, devid, &res);
373
+
374
+ if (res != MEMTX_OK) {
375
+ return result;
376
+ }
377
+ dte_valid = dte & TABLE_ENTRY_VALID_MASK;
378
+
379
+ max_eventid = (1UL << (((dte >> 1U) & SIZE_MASK) + 1));
380
+
381
+ if (!ignore_pInt) {
382
+ max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1;
383
+ }
384
+
385
+ if ((devid > s->dt.maxids.max_devids) || (icid > s->ct.maxids.max_collids)
386
+ || !dte_valid || (eventid > max_eventid) ||
387
+ (!ignore_pInt && (((pIntid < GICV3_LPI_INTID_START) ||
388
+ (pIntid > max_Intid)) && (pIntid != INTID_SPURIOUS)))) {
389
+ qemu_log_mask(LOG_GUEST_ERROR,
390
+ "%s: invalid command attributes "
391
+ "devid %d or icid %d or eventid %d or pIntid %d or"
392
+ "unmapped dte %d\n", __func__, devid, icid, eventid,
393
+ pIntid, dte_valid);
394
+ /*
395
+ * in this implementation, in case of error
396
+ * we ignore this command and move onto the next
397
+ * command in the queue
398
+ */
399
+ } else {
400
+ /* add ite entry to interrupt translation table */
401
+ ite.itel = (dte_valid & TABLE_ENTRY_VALID_MASK) |
402
+ (GITS_TYPE_PHYSICAL << ITE_ENTRY_INTTYPE_SHIFT);
403
+
404
+ if (ignore_pInt) {
405
+ ite.itel |= (eventid << ITE_ENTRY_INTID_SHIFT);
406
+ } else {
407
+ ite.itel |= (pIntid << ITE_ENTRY_INTID_SHIFT);
408
+ }
409
+ ite.itel |= (int_spurious << ITE_ENTRY_INTSP_SHIFT);
410
+ ite.iteh = icid;
411
+
412
+ result = update_ite(s, eventid, dte, ite);
413
+ }
414
+
415
+ return result;
416
+}
417
+
418
static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
419
uint64_t rdbase)
420
{
421
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
422
423
switch (cmd) {
424
case GITS_CMD_INT:
425
+ res = process_its_cmd(s, data, cq_offset, INT);
426
break;
427
case GITS_CMD_CLEAR:
428
+ res = process_its_cmd(s, data, cq_offset, CLEAR);
429
break;
430
case GITS_CMD_SYNC:
431
/*
432
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
433
result = process_mapc(s, cq_offset);
434
break;
435
case GITS_CMD_MAPTI:
436
+ result = process_mapti(s, data, cq_offset, false);
437
break;
438
case GITS_CMD_MAPI:
439
+ result = process_mapti(s, data, cq_offset, true);
440
break;
441
case GITS_CMD_DISCARD:
442
+ result = process_its_cmd(s, data, cq_offset, DISCARD);
443
break;
444
case GITS_CMD_INV:
445
case GITS_CMD_INVALL:
446
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset,
447
uint64_t data, unsigned size,
448
MemTxAttrs attrs)
449
{
450
- return MEMTX_OK;
451
+ GICv3ITSState *s = (GICv3ITSState *)opaque;
452
+ bool result = true;
453
+ uint32_t devid = 0;
454
+
455
+ switch (offset) {
456
+ case GITS_TRANSLATER:
457
+ if (s->ctlr & ITS_CTLR_ENABLED) {
458
+ devid = attrs.requester_id;
459
+ result = process_its_cmd(s, data, devid, NONE);
460
+ }
461
+ break;
462
+ default:
463
+ break;
464
+ }
465
+
466
+ if (result) {
467
+ return MEMTX_OK;
468
+ } else {
469
+ return MEMTX_ERROR;
470
+ }
471
}
472
473
static bool its_writel(GICv3ITSState *s, hwaddr offset,
474
--
227
--
475
2.20.1
228
2.34.1
476
229
477
230
diff view generated by jsdifflib
1
From: Shashi Mallela <shashi.mallela@linaro.org>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
Added expected IORT files applicable with latest GICv3
3
The testcase contains :
4
ITS changes.Temporarily differences in these files are
4
- `test_idr_reset_value()` :
5
okay.
5
Checks the reset values of MODER, OTYPER, PUPDR, ODR and IDR.
6
- `test_gpio_output_mode()` :
7
Checks that writing a bit in register ODR results in the corresponding
8
pin rising or lowering, if this pin is configured in output mode.
9
- `test_gpio_input_mode()` :
10
Checks that a input pin set high or low externally results
11
in the pin rising and lowering.
12
- `test_pull_up_pull_down()` :
13
Checks that a floating pin in pull-up/down mode is actually high/down.
14
- `test_push_pull()` :
15
Checks that a pin set externally is disconnected when configured in
16
push-pull output mode, and can't be set externally while in this mode.
17
- `test_open_drain()` :
18
Checks that a pin set externally high is disconnected when configured
19
in open-drain output mode, and can't be set high while in this mode.
20
- `test_bsrr_brr()` :
21
Checks that writing to BSRR and BRR has the desired result in ODR.
22
- `test_clock_enable()` :
23
Checks that GPIO clock is at the right frequency after enabling it.
6
24
7
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
25
Acked-by: Thomas Huth <thuth@redhat.com>
8
Acked-by: Igor Mammedov <imammedo@redhat.com>
26
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
10
Message-id: 20210910143951.92242-8-shashi.mallela@linaro.org
28
Message-id: 20240305210444.310665-4-ines.varhol@telecom-paris.fr
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
30
---
13
tests/qtest/bios-tables-test-allowed-diff.h | 4 ++++
31
tests/qtest/stm32l4x5_gpio-test.c | 551 ++++++++++++++++++++++++++++++
14
tests/data/acpi/virt/IORT | 0
32
tests/qtest/meson.build | 3 +-
15
tests/data/acpi/virt/IORT.memhp | 0
33
2 files changed, 553 insertions(+), 1 deletion(-)
16
tests/data/acpi/virt/IORT.numamem | 0
34
create mode 100644 tests/qtest/stm32l4x5_gpio-test.c
17
tests/data/acpi/virt/IORT.pxb | 0
18
5 files changed, 4 insertions(+)
19
create mode 100644 tests/data/acpi/virt/IORT
20
create mode 100644 tests/data/acpi/virt/IORT.memhp
21
create mode 100644 tests/data/acpi/virt/IORT.numamem
22
create mode 100644 tests/data/acpi/virt/IORT.pxb
23
35
24
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
36
diff --git a/tests/qtest/stm32l4x5_gpio-test.c b/tests/qtest/stm32l4x5_gpio-test.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/tests/qtest/bios-tables-test-allowed-diff.h
27
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
28
@@ -1 +1,5 @@
29
/* List of comma-separated changed AML files to ignore */
30
+"tests/data/acpi/virt/IORT",
31
+"tests/data/acpi/virt/IORT.memhp",
32
+"tests/data/acpi/virt/IORT.numamem",
33
+"tests/data/acpi/virt/IORT.pxb",
34
diff --git a/tests/data/acpi/virt/IORT b/tests/data/acpi/virt/IORT
35
new file mode 100644
37
new file mode 100644
36
index XXXXXXX..XXXXXXX
38
index XXXXXXX..XXXXXXX
37
diff --git a/tests/data/acpi/virt/IORT.memhp b/tests/data/acpi/virt/IORT.memhp
39
--- /dev/null
38
new file mode 100644
40
+++ b/tests/qtest/stm32l4x5_gpio-test.c
39
index XXXXXXX..XXXXXXX
41
@@ -XXX,XX +XXX,XX @@
40
diff --git a/tests/data/acpi/virt/IORT.numamem b/tests/data/acpi/virt/IORT.numamem
42
+/*
41
new file mode 100644
43
+ * QTest testcase for STM32L4x5_GPIO
42
index XXXXXXX..XXXXXXX
44
+ *
43
diff --git a/tests/data/acpi/virt/IORT.pxb b/tests/data/acpi/virt/IORT.pxb
45
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
44
new file mode 100644
46
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
45
index XXXXXXX..XXXXXXX
47
+ *
48
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
49
+ * See the COPYING file in the top-level directory.
50
+ */
51
+
52
+#include "qemu/osdep.h"
53
+#include "libqtest-single.h"
54
+
55
+#define GPIO_BASE_ADDR 0x48000000
56
+#define GPIO_SIZE 0x400
57
+#define NUM_GPIOS 8
58
+#define NUM_GPIO_PINS 16
59
+
60
+#define GPIO_A 0x48000000
61
+#define GPIO_B 0x48000400
62
+#define GPIO_C 0x48000800
63
+#define GPIO_D 0x48000C00
64
+#define GPIO_E 0x48001000
65
+#define GPIO_F 0x48001400
66
+#define GPIO_G 0x48001800
67
+#define GPIO_H 0x48001C00
68
+
69
+#define MODER 0x00
70
+#define OTYPER 0x04
71
+#define PUPDR 0x0C
72
+#define IDR 0x10
73
+#define ODR 0x14
74
+#define BSRR 0x18
75
+#define BRR 0x28
76
+
77
+#define MODER_INPUT 0
78
+#define MODER_OUTPUT 1
79
+
80
+#define PUPDR_NONE 0
81
+#define PUPDR_PULLUP 1
82
+#define PUPDR_PULLDOWN 2
83
+
84
+#define OTYPER_PUSH_PULL 0
85
+#define OTYPER_OPEN_DRAIN 1
86
+
87
+const uint32_t moder_reset[NUM_GPIOS] = {
88
+ 0xABFFFFFF,
89
+ 0xFFFFFEBF,
90
+ 0xFFFFFFFF,
91
+ 0xFFFFFFFF,
92
+ 0xFFFFFFFF,
93
+ 0xFFFFFFFF,
94
+ 0xFFFFFFFF,
95
+ 0x0000000F
96
+};
97
+
98
+const uint32_t pupdr_reset[NUM_GPIOS] = {
99
+ 0x64000000,
100
+ 0x00000100,
101
+ 0x00000000,
102
+ 0x00000000,
103
+ 0x00000000,
104
+ 0x00000000,
105
+ 0x00000000,
106
+ 0x00000000
107
+};
108
+
109
+const uint32_t idr_reset[NUM_GPIOS] = {
110
+ 0x0000A000,
111
+ 0x00000010,
112
+ 0x00000000,
113
+ 0x00000000,
114
+ 0x00000000,
115
+ 0x00000000,
116
+ 0x00000000,
117
+ 0x00000000
118
+};
119
+
120
+static uint32_t gpio_readl(unsigned int gpio, unsigned int offset)
121
+{
122
+ return readl(gpio + offset);
123
+}
124
+
125
+static void gpio_writel(unsigned int gpio, unsigned int offset, uint32_t value)
126
+{
127
+ writel(gpio + offset, value);
128
+}
129
+
130
+static void gpio_set_bit(unsigned int gpio, unsigned int reg,
131
+ unsigned int pin, uint32_t value)
132
+{
133
+ uint32_t mask = 0xFFFFFFFF & ~(0x1 << pin);
134
+ gpio_writel(gpio, reg, (gpio_readl(gpio, reg) & mask) | value << pin);
135
+}
136
+
137
+static void gpio_set_2bits(unsigned int gpio, unsigned int reg,
138
+ unsigned int pin, uint32_t value)
139
+{
140
+ uint32_t offset = 2 * pin;
141
+ uint32_t mask = 0xFFFFFFFF & ~(0x3 << offset);
142
+ gpio_writel(gpio, reg, (gpio_readl(gpio, reg) & mask) | value << offset);
143
+}
144
+
145
+static unsigned int get_gpio_id(uint32_t gpio_addr)
146
+{
147
+ return (gpio_addr - GPIO_BASE_ADDR) / GPIO_SIZE;
148
+}
149
+
150
+static void gpio_set_irq(unsigned int gpio, int num, int level)
151
+{
152
+ g_autofree char *name = g_strdup_printf("/machine/soc/gpio%c",
153
+ get_gpio_id(gpio) + 'a');
154
+ qtest_set_irq_in(global_qtest, name, NULL, num, level);
155
+}
156
+
157
+static void disconnect_all_pins(unsigned int gpio)
158
+{
159
+ g_autofree char *path = g_strdup_printf("/machine/soc/gpio%c",
160
+ get_gpio_id(gpio) + 'a');
161
+ QDict *r;
162
+
163
+ r = qtest_qmp(global_qtest, "{ 'execute': 'qom-set', 'arguments': "
164
+ "{ 'path': %s, 'property': 'disconnected-pins', 'value': %d } }",
165
+ path, 0xFFFF);
166
+ g_assert_false(qdict_haskey(r, "error"));
167
+ qobject_unref(r);
168
+}
169
+
170
+static uint32_t get_disconnected_pins(unsigned int gpio)
171
+{
172
+ g_autofree char *path = g_strdup_printf("/machine/soc/gpio%c",
173
+ get_gpio_id(gpio) + 'a');
174
+ uint32_t disconnected_pins = 0;
175
+ QDict *r;
176
+
177
+ r = qtest_qmp(global_qtest, "{ 'execute': 'qom-get', 'arguments':"
178
+ " { 'path': %s, 'property': 'disconnected-pins'} }", path);
179
+ g_assert_false(qdict_haskey(r, "error"));
180
+ disconnected_pins = qdict_get_int(r, "return");
181
+ qobject_unref(r);
182
+ return disconnected_pins;
183
+}
184
+
185
+static uint32_t reset(uint32_t gpio, unsigned int offset)
186
+{
187
+ switch (offset) {
188
+ case MODER:
189
+ return moder_reset[get_gpio_id(gpio)];
190
+ case PUPDR:
191
+ return pupdr_reset[get_gpio_id(gpio)];
192
+ case IDR:
193
+ return idr_reset[get_gpio_id(gpio)];
194
+ }
195
+ return 0x0;
196
+}
197
+
198
+static void system_reset(void)
199
+{
200
+ QDict *r;
201
+ r = qtest_qmp(global_qtest, "{'execute': 'system_reset'}");
202
+ g_assert_false(qdict_haskey(r, "error"));
203
+ qobject_unref(r);
204
+}
205
+
206
+static void test_idr_reset_value(void)
207
+{
208
+ /*
209
+ * Checks that the values in MODER, OTYPER, PUPDR and ODR
210
+ * after reset are correct, and that the value in IDR is
211
+ * coherent.
212
+ * Since AF and analog modes aren't implemented, IDR reset
213
+ * values aren't the same as with a real board.
214
+ *
215
+ * Register IDR contains the actual values of all GPIO pins.
216
+ * Its value depends on the pins' configuration
217
+ * (intput/output/analog : register MODER, push-pull/open-drain :
218
+ * register OTYPER, pull-up/pull-down/none : register PUPDR)
219
+ * and on the values stored in register ODR
220
+ * (in case the pin is in output mode).
221
+ */
222
+
223
+ gpio_writel(GPIO_A, MODER, 0xDEADBEEF);
224
+ gpio_writel(GPIO_A, ODR, 0xDEADBEEF);
225
+ gpio_writel(GPIO_A, OTYPER, 0xDEADBEEF);
226
+ gpio_writel(GPIO_A, PUPDR, 0xDEADBEEF);
227
+
228
+ gpio_writel(GPIO_B, MODER, 0xDEADBEEF);
229
+ gpio_writel(GPIO_B, ODR, 0xDEADBEEF);
230
+ gpio_writel(GPIO_B, OTYPER, 0xDEADBEEF);
231
+ gpio_writel(GPIO_B, PUPDR, 0xDEADBEEF);
232
+
233
+ gpio_writel(GPIO_C, MODER, 0xDEADBEEF);
234
+ gpio_writel(GPIO_C, ODR, 0xDEADBEEF);
235
+ gpio_writel(GPIO_C, OTYPER, 0xDEADBEEF);
236
+ gpio_writel(GPIO_C, PUPDR, 0xDEADBEEF);
237
+
238
+ gpio_writel(GPIO_H, MODER, 0xDEADBEEF);
239
+ gpio_writel(GPIO_H, ODR, 0xDEADBEEF);
240
+ gpio_writel(GPIO_H, OTYPER, 0xDEADBEEF);
241
+ gpio_writel(GPIO_H, PUPDR, 0xDEADBEEF);
242
+
243
+ system_reset();
244
+
245
+ uint32_t moder = gpio_readl(GPIO_A, MODER);
246
+ uint32_t odr = gpio_readl(GPIO_A, ODR);
247
+ uint32_t otyper = gpio_readl(GPIO_A, OTYPER);
248
+ uint32_t pupdr = gpio_readl(GPIO_A, PUPDR);
249
+ uint32_t idr = gpio_readl(GPIO_A, IDR);
250
+ /* 15: AF, 14: AF, 13: AF, 12: Analog ... */
251
+ /* here AF is the same as Analog and Input mode */
252
+ g_assert_cmphex(moder, ==, reset(GPIO_A, MODER));
253
+ g_assert_cmphex(odr, ==, reset(GPIO_A, ODR));
254
+ g_assert_cmphex(otyper, ==, reset(GPIO_A, OTYPER));
255
+ /* 15: pull-up, 14: pull-down, 13: pull-up, 12: neither ... */
256
+ g_assert_cmphex(pupdr, ==, reset(GPIO_A, PUPDR));
257
+ /* 15 : 1, 14: 0, 13: 1, 12 : reset value ... */
258
+ g_assert_cmphex(idr, ==, reset(GPIO_A, IDR));
259
+
260
+ moder = gpio_readl(GPIO_B, MODER);
261
+ odr = gpio_readl(GPIO_B, ODR);
262
+ otyper = gpio_readl(GPIO_B, OTYPER);
263
+ pupdr = gpio_readl(GPIO_B, PUPDR);
264
+ idr = gpio_readl(GPIO_B, IDR);
265
+ /* ... 5: Analog, 4: AF, 3: AF, 2: Analog ... */
266
+ /* here AF is the same as Analog and Input mode */
267
+ g_assert_cmphex(moder, ==, reset(GPIO_B, MODER));
268
+ g_assert_cmphex(odr, ==, reset(GPIO_B, ODR));
269
+ g_assert_cmphex(otyper, ==, reset(GPIO_B, OTYPER));
270
+ /* ... 5: neither, 4: pull-up, 3: neither ... */
271
+ g_assert_cmphex(pupdr, ==, reset(GPIO_B, PUPDR));
272
+ /* ... 5 : reset value, 4 : 1, 3 : reset value ... */
273
+ g_assert_cmphex(idr, ==, reset(GPIO_B, IDR));
274
+
275
+ moder = gpio_readl(GPIO_C, MODER);
276
+ odr = gpio_readl(GPIO_C, ODR);
277
+ otyper = gpio_readl(GPIO_C, OTYPER);
278
+ pupdr = gpio_readl(GPIO_C, PUPDR);
279
+ idr = gpio_readl(GPIO_C, IDR);
280
+ /* Analog, same as Input mode*/
281
+ g_assert_cmphex(moder, ==, reset(GPIO_C, MODER));
282
+ g_assert_cmphex(odr, ==, reset(GPIO_C, ODR));
283
+ g_assert_cmphex(otyper, ==, reset(GPIO_C, OTYPER));
284
+ /* no pull-up or pull-down */
285
+ g_assert_cmphex(pupdr, ==, reset(GPIO_C, PUPDR));
286
+ /* reset value */
287
+ g_assert_cmphex(idr, ==, reset(GPIO_C, IDR));
288
+
289
+ moder = gpio_readl(GPIO_H, MODER);
290
+ odr = gpio_readl(GPIO_H, ODR);
291
+ otyper = gpio_readl(GPIO_H, OTYPER);
292
+ pupdr = gpio_readl(GPIO_H, PUPDR);
293
+ idr = gpio_readl(GPIO_H, IDR);
294
+ /* Analog, same as Input mode */
295
+ g_assert_cmphex(moder, ==, reset(GPIO_H, MODER));
296
+ g_assert_cmphex(odr, ==, reset(GPIO_H, ODR));
297
+ g_assert_cmphex(otyper, ==, reset(GPIO_H, OTYPER));
298
+ /* no pull-up or pull-down */
299
+ g_assert_cmphex(pupdr, ==, reset(GPIO_H, PUPDR));
300
+ /* reset value */
301
+ g_assert_cmphex(idr, ==, reset(GPIO_H, IDR));
302
+}
303
+
304
+static void test_gpio_output_mode(const void *data)
305
+{
306
+ /*
307
+ * Checks that setting a bit in ODR sets the corresponding
308
+ * GPIO line high : it should set the right bit in IDR
309
+ * and send an irq to syscfg.
310
+ * Additionally, it checks that values written to ODR
311
+ * when not in output mode are stored and not discarded.
312
+ */
313
+ unsigned int pin = ((uint64_t)data) & 0xF;
314
+ uint32_t gpio = ((uint64_t)data) >> 32;
315
+ unsigned int gpio_id = get_gpio_id(gpio);
316
+
317
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
318
+
319
+ /* Set a bit in ODR and check nothing happens */
320
+ gpio_set_bit(gpio, ODR, pin, 1);
321
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
322
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
323
+
324
+ /* Configure the relevant line as output and check the pin is high */
325
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
326
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
327
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
328
+
329
+ /* Reset the bit in ODR and check the pin is low */
330
+ gpio_set_bit(gpio, ODR, pin, 0);
331
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
332
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
333
+
334
+ /* Clean the test */
335
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
336
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
337
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
338
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
339
+}
340
+
341
+static void test_gpio_input_mode(const void *data)
342
+{
343
+ /*
344
+ * Test that setting a line high/low externally sets the
345
+ * corresponding GPIO line high/low : it should set the
346
+ * right bit in IDR and send an irq to syscfg.
347
+ */
348
+ unsigned int pin = ((uint64_t)data) & 0xF;
349
+ uint32_t gpio = ((uint64_t)data) >> 32;
350
+ unsigned int gpio_id = get_gpio_id(gpio);
351
+
352
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
353
+
354
+ /* Configure a line as input, raise it, and check that the pin is high */
355
+ gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
356
+ gpio_set_irq(gpio, pin, 1);
357
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
358
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
359
+
360
+ /* Lower the line and check that the pin is low */
361
+ gpio_set_irq(gpio, pin, 0);
362
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
363
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
364
+
365
+ /* Clean the test */
366
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
367
+ disconnect_all_pins(gpio);
368
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
369
+}
370
+
371
+static void test_pull_up_pull_down(const void *data)
372
+{
373
+ /*
374
+ * Test that a floating pin with pull-up sets the pin
375
+ * high and vice-versa.
376
+ */
377
+ unsigned int pin = ((uint64_t)data) & 0xF;
378
+ uint32_t gpio = ((uint64_t)data) >> 32;
379
+ unsigned int gpio_id = get_gpio_id(gpio);
380
+
381
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
382
+
383
+ /* Configure a line as input with pull-up, check the line is set high */
384
+ gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
385
+ gpio_set_2bits(gpio, PUPDR, pin, PUPDR_PULLUP);
386
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
387
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
388
+
389
+ /* Configure the line with pull-down, check the line is low */
390
+ gpio_set_2bits(gpio, PUPDR, pin, PUPDR_PULLDOWN);
391
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
392
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
393
+
394
+ /* Clean the test */
395
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
396
+ gpio_writel(gpio, PUPDR, reset(gpio, PUPDR));
397
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
398
+}
399
+
400
+static void test_push_pull(const void *data)
401
+{
402
+ /*
403
+ * Test that configuring a line in push-pull output mode
404
+ * disconnects the pin, that the pin can't be set or reset
405
+ * externally afterwards.
406
+ */
407
+ unsigned int pin = ((uint64_t)data) & 0xF;
408
+ uint32_t gpio = ((uint64_t)data) >> 32;
409
+ uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio);
410
+
411
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
412
+
413
+ /* Setting a line high externally, configuring it in push-pull output */
414
+ /* And checking the pin was disconnected */
415
+ gpio_set_irq(gpio, pin, 1);
416
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
417
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
418
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
419
+
420
+ /* Setting a line low externally, configuring it in push-pull output */
421
+ /* And checking the pin was disconnected */
422
+ gpio_set_irq(gpio2, pin, 0);
423
+ gpio_set_bit(gpio2, ODR, pin, 1);
424
+ gpio_set_2bits(gpio2, MODER, pin, MODER_OUTPUT);
425
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF);
426
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR) | (1 << pin));
427
+
428
+ /* Trying to set a push-pull output pin, checking it doesn't work */
429
+ gpio_set_irq(gpio, pin, 1);
430
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
431
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
432
+
433
+ /* Trying to reset a push-pull output pin, checking it doesn't work */
434
+ gpio_set_irq(gpio2, pin, 0);
435
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF);
436
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR) | (1 << pin));
437
+
438
+ /* Clean the test */
439
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
440
+ gpio_writel(gpio2, ODR, reset(gpio2, ODR));
441
+ gpio_writel(gpio2, MODER, reset(gpio2, MODER));
442
+}
443
+
444
+static void test_open_drain(const void *data)
445
+{
446
+ /*
447
+ * Test that configuring a line in open-drain output mode
448
+ * disconnects a pin set high externally and that the pin
449
+ * can't be set high externally while configured in open-drain.
450
+ *
451
+ * However a pin set low externally shouldn't be disconnected,
452
+ * and it can be set low externally when in open-drain mode.
453
+ */
454
+ unsigned int pin = ((uint64_t)data) & 0xF;
455
+ uint32_t gpio = ((uint64_t)data) >> 32;
456
+ uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio);
457
+
458
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
459
+
460
+ /* Setting a line high externally, configuring it in open-drain output */
461
+ /* And checking the pin was disconnected */
462
+ gpio_set_irq(gpio, pin, 1);
463
+ gpio_set_bit(gpio, OTYPER, pin, OTYPER_OPEN_DRAIN);
464
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
465
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
466
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
467
+
468
+ /* Setting a line low externally, configuring it in open-drain output */
469
+ /* And checking the pin wasn't disconnected */
470
+ gpio_set_irq(gpio2, pin, 0);
471
+ gpio_set_bit(gpio2, ODR, pin, 1);
472
+ gpio_set_bit(gpio2, OTYPER, pin, OTYPER_OPEN_DRAIN);
473
+ gpio_set_2bits(gpio2, MODER, pin, MODER_OUTPUT);
474
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF & ~(1 << pin));
475
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==,
476
+ reset(gpio2, IDR) & ~(1 << pin));
477
+
478
+ /* Trying to set a open-drain output pin, checking it doesn't work */
479
+ gpio_set_irq(gpio, pin, 1);
480
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
481
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
482
+
483
+ /* Trying to reset a open-drain output pin, checking it works */
484
+ gpio_set_bit(gpio, ODR, pin, 1);
485
+ gpio_set_irq(gpio, pin, 0);
486
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF & ~(1 << pin));
487
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==,
488
+ reset(gpio2, IDR) & ~(1 << pin));
489
+
490
+ /* Clean the test */
491
+ disconnect_all_pins(gpio2);
492
+ gpio_writel(gpio2, OTYPER, reset(gpio2, OTYPER));
493
+ gpio_writel(gpio2, ODR, reset(gpio2, ODR));
494
+ gpio_writel(gpio2, MODER, reset(gpio2, MODER));
495
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR));
496
+ disconnect_all_pins(gpio);
497
+ gpio_writel(gpio, OTYPER, reset(gpio, OTYPER));
498
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
499
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
500
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
501
+}
502
+
503
+static void test_bsrr_brr(const void *data)
504
+{
505
+ /*
506
+ * Test that writing a '1' in BSS and BSRR
507
+ * has the desired effect on ODR.
508
+ * In BSRR, BSx has priority over BRx.
509
+ */
510
+ unsigned int pin = ((uint64_t)data) & 0xF;
511
+ uint32_t gpio = ((uint64_t)data) >> 32;
512
+
513
+ gpio_writel(gpio, BSRR, (1 << pin));
514
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
515
+
516
+ gpio_writel(gpio, BSRR, (1 << (pin + NUM_GPIO_PINS)));
517
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
518
+
519
+ gpio_writel(gpio, BSRR, (1 << pin));
520
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
521
+
522
+ gpio_writel(gpio, BRR, (1 << pin));
523
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
524
+
525
+ /* BSx should have priority over BRx */
526
+ gpio_writel(gpio, BSRR, (1 << pin) | (1 << (pin + NUM_GPIO_PINS)));
527
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
528
+
529
+ gpio_writel(gpio, BRR, (1 << pin));
530
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
531
+
532
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
533
+}
534
+
535
+int main(int argc, char **argv)
536
+{
537
+ int ret;
538
+
539
+ g_test_init(&argc, &argv, NULL);
540
+ g_test_set_nonfatal_assertions();
541
+ qtest_add_func("stm32l4x5/gpio/test_idr_reset_value",
542
+ test_idr_reset_value);
543
+ /*
544
+ * The inputs for the tests (gpio and pin) can be changed,
545
+ * but the tests don't work for pins that are high at reset
546
+ * (GPIOA15, GPIO13 and GPIOB5).
547
+ * Specifically, rising the pin then checking `get_irq()`
548
+ * is problematic since the pin was already high.
549
+ */
550
+ qtest_add_data_func("stm32l4x5/gpio/test_gpioc5_output_mode",
551
+ (void *)((uint64_t)GPIO_C << 32 | 5),
552
+ test_gpio_output_mode);
553
+ qtest_add_data_func("stm32l4x5/gpio/test_gpioh3_output_mode",
554
+ (void *)((uint64_t)GPIO_H << 32 | 3),
555
+ test_gpio_output_mode);
556
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_input_mode1",
557
+ (void *)((uint64_t)GPIO_D << 32 | 6),
558
+ test_gpio_input_mode);
559
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_input_mode2",
560
+ (void *)((uint64_t)GPIO_C << 32 | 10),
561
+ test_gpio_input_mode);
562
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_pull_up_pull_down1",
563
+ (void *)((uint64_t)GPIO_B << 32 | 5),
564
+ test_pull_up_pull_down);
565
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_pull_up_pull_down2",
566
+ (void *)((uint64_t)GPIO_F << 32 | 1),
567
+ test_pull_up_pull_down);
568
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_push_pull1",
569
+ (void *)((uint64_t)GPIO_G << 32 | 6),
570
+ test_push_pull);
571
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_push_pull2",
572
+ (void *)((uint64_t)GPIO_H << 32 | 3),
573
+ test_push_pull);
574
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_open_drain1",
575
+ (void *)((uint64_t)GPIO_C << 32 | 4),
576
+ test_open_drain);
577
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_open_drain2",
578
+ (void *)((uint64_t)GPIO_E << 32 | 11),
579
+ test_open_drain);
580
+ qtest_add_data_func("stm32l4x5/gpio/test_bsrr_brr1",
581
+ (void *)((uint64_t)GPIO_A << 32 | 12),
582
+ test_bsrr_brr);
583
+ qtest_add_data_func("stm32l4x5/gpio/test_bsrr_brr2",
584
+ (void *)((uint64_t)GPIO_D << 32 | 0),
585
+ test_bsrr_brr);
586
+
587
+ qtest_start("-machine b-l475e-iot01a");
588
+ ret = g_test_run();
589
+ qtest_end();
590
+
591
+ return ret;
592
+}
593
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
594
index XXXXXXX..XXXXXXX 100644
595
--- a/tests/qtest/meson.build
596
+++ b/tests/qtest/meson.build
597
@@ -XXX,XX +XXX,XX @@ qtests_aspeed = \
598
qtests_stm32l4x5 = \
599
['stm32l4x5_exti-test',
600
'stm32l4x5_syscfg-test',
601
- 'stm32l4x5_rcc-test']
602
+ 'stm32l4x5_rcc-test',
603
+ 'stm32l4x5_gpio-test']
604
605
qtests_arm = \
606
(config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
46
--
607
--
47
2.20.1
608
2.34.1
48
609
49
610
diff view generated by jsdifflib
1
From: Bin Meng <bmeng.cn@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This converts uart_read() and uart_write() to memop_with_attrs() ops.
3
While the 8-bit input elements are sequential in the input vector,
4
4
the 32-bit output elements are not sequential in the output matrix.
5
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
5
Do not attempt to compute 2 32-bit outputs at the same time.
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
6
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Cc: qemu-stable@nongnu.org
8
Message-id: 20210901124521.30599-5-bmeng.cn@gmail.com
8
Fixes: 23a5e3859f5 ("target/arm: Implement SME integer outer product")
9
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2083
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Message-id: 20240305163931.242795-1-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
14
---
11
hw/char/cadence_uart.c | 26 +++++++++++++++-----------
15
target/arm/tcg/sme_helper.c | 77 ++++++++++++++++++-------------
12
1 file changed, 15 insertions(+), 11 deletions(-)
16
tests/tcg/aarch64/sme-smopa-1.c | 47 +++++++++++++++++++
13
17
tests/tcg/aarch64/sme-smopa-2.c | 54 ++++++++++++++++++++++
14
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
18
tests/tcg/aarch64/Makefile.target | 2 +-
19
4 files changed, 147 insertions(+), 33 deletions(-)
20
create mode 100644 tests/tcg/aarch64/sme-smopa-1.c
21
create mode 100644 tests/tcg/aarch64/sme-smopa-2.c
22
23
diff --git a/target/arm/tcg/sme_helper.c b/target/arm/tcg/sme_helper.c
15
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/char/cadence_uart.c
25
--- a/target/arm/tcg/sme_helper.c
17
+++ b/hw/char/cadence_uart.c
26
+++ b/target/arm/tcg/sme_helper.c
18
@@ -XXX,XX +XXX,XX @@ static void uart_read_rx_fifo(CadenceUARTState *s, uint32_t *c)
27
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn,
19
uart_update_status(s);
28
}
20
}
29
}
21
30
22
-static void uart_write(void *opaque, hwaddr offset,
31
-typedef uint64_t IMOPFn(uint64_t, uint64_t, uint64_t, uint8_t, bool);
23
- uint64_t value, unsigned size)
32
+typedef uint32_t IMOPFn32(uint32_t, uint32_t, uint32_t, uint8_t, bool);
24
+static MemTxResult uart_write(void *opaque, hwaddr offset,
33
+static inline void do_imopa_s(uint32_t *za, uint32_t *zn, uint32_t *zm,
25
+ uint64_t value, unsigned size, MemTxAttrs attrs)
34
+ uint8_t *pn, uint8_t *pm,
35
+ uint32_t desc, IMOPFn32 *fn)
36
+{
37
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 4;
38
+ bool neg = simd_data(desc);
39
40
-static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
41
- uint8_t *pn, uint8_t *pm,
42
- uint32_t desc, IMOPFn *fn)
43
+ for (row = 0; row < oprsz; ++row) {
44
+ uint8_t pa = (pn[H1(row >> 1)] >> ((row & 1) * 4)) & 0xf;
45
+ uint32_t *za_row = &za[tile_vslice_index(row)];
46
+ uint32_t n = zn[H4(row)];
47
+
48
+ for (col = 0; col < oprsz; ++col) {
49
+ uint8_t pb = pm[H1(col >> 1)] >> ((col & 1) * 4);
50
+ uint32_t *a = &za_row[H4(col)];
51
+
52
+ *a = fn(n, zm[H4(col)], *a, pa & pb, neg);
53
+ }
54
+ }
55
+}
56
+
57
+typedef uint64_t IMOPFn64(uint64_t, uint64_t, uint64_t, uint8_t, bool);
58
+static inline void do_imopa_d(uint64_t *za, uint64_t *zn, uint64_t *zm,
59
+ uint8_t *pn, uint8_t *pm,
60
+ uint32_t desc, IMOPFn64 *fn)
26
{
61
{
27
CadenceUARTState *s = opaque;
62
intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
28
63
bool neg = simd_data(desc);
29
DB_PRINT(" offset:%x data:%08x\n", (unsigned)offset, (unsigned)value);
64
@@ -XXX,XX +XXX,XX @@ static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
30
offset >>= 2;
31
if (offset >= CADENCE_UART_R_MAX) {
32
- return;
33
+ return MEMTX_DECODE_ERROR;
34
}
35
switch (offset) {
36
case R_IER: /* ier (wts imr) */
37
@@ -XXX,XX +XXX,XX @@ static void uart_write(void *opaque, hwaddr offset,
38
break;
39
}
40
uart_update_status(s);
41
+
42
+ return MEMTX_OK;
43
}
65
}
44
66
45
-static uint64_t uart_read(void *opaque, hwaddr offset,
67
#define DEF_IMOP_32(NAME, NTYPE, MTYPE) \
46
- unsigned size)
68
-static uint64_t NAME(uint64_t n, uint64_t m, uint64_t a, uint8_t p, bool neg) \
47
+static MemTxResult uart_read(void *opaque, hwaddr offset,
69
+static uint32_t NAME(uint32_t n, uint32_t m, uint32_t a, uint8_t p, bool neg) \
48
+ uint64_t *value, unsigned size, MemTxAttrs attrs)
70
{ \
49
{
71
- uint32_t sum0 = 0, sum1 = 0; \
50
CadenceUARTState *s = opaque;
72
+ uint32_t sum = 0; \
51
uint32_t c = 0;
73
/* Apply P to N as a mask, making the inactive elements 0. */ \
52
74
n &= expand_pred_b(p); \
53
offset >>= 2;
75
- sum0 += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
54
if (offset >= CADENCE_UART_R_MAX) {
76
- sum0 += (NTYPE)(n >> 8) * (MTYPE)(m >> 8); \
55
- c = 0;
77
- sum0 += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
56
- } else if (offset == R_TX_RX) {
78
- sum0 += (NTYPE)(n >> 24) * (MTYPE)(m >> 24); \
57
+ return MEMTX_DECODE_ERROR;
79
- sum1 += (NTYPE)(n >> 32) * (MTYPE)(m >> 32); \
58
+ }
80
- sum1 += (NTYPE)(n >> 40) * (MTYPE)(m >> 40); \
59
+ if (offset == R_TX_RX) {
81
- sum1 += (NTYPE)(n >> 48) * (MTYPE)(m >> 48); \
60
uart_read_rx_fifo(s, &c);
82
- sum1 += (NTYPE)(n >> 56) * (MTYPE)(m >> 56); \
61
} else {
83
- if (neg) { \
62
- c = s->r[offset];
84
- sum0 = (uint32_t)a - sum0, sum1 = (uint32_t)(a >> 32) - sum1; \
63
+ c = s->r[offset];
85
- } else { \
64
}
86
- sum0 = (uint32_t)a + sum0, sum1 = (uint32_t)(a >> 32) + sum1; \
65
87
- } \
66
DB_PRINT(" offset:%x data:%08x\n", (unsigned)(offset << 2), (unsigned)c);
88
- return ((uint64_t)sum1 << 32) | sum0; \
67
- return c;
89
+ sum += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
68
+ *value = c;
90
+ sum += (NTYPE)(n >> 8) * (MTYPE)(m >> 8); \
69
+ return MEMTX_OK;
91
+ sum += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
92
+ sum += (NTYPE)(n >> 24) * (MTYPE)(m >> 24); \
93
+ return neg ? a - sum : a + sum; \
70
}
94
}
71
95
72
static const MemoryRegionOps uart_ops = {
96
#define DEF_IMOP_64(NAME, NTYPE, MTYPE) \
73
- .read = uart_read,
97
@@ -XXX,XX +XXX,XX @@ DEF_IMOP_64(umopa_d, uint16_t, uint16_t)
74
- .write = uart_write,
98
DEF_IMOP_64(sumopa_d, int16_t, uint16_t)
75
+ .read_with_attrs = uart_read,
99
DEF_IMOP_64(usmopa_d, uint16_t, int16_t)
76
+ .write_with_attrs = uart_write,
100
77
.endianness = DEVICE_NATIVE_ENDIAN,
101
-#define DEF_IMOPH(NAME) \
78
};
102
- void HELPER(sme_##NAME)(void *vza, void *vzn, void *vzm, void *vpn, \
79
103
- void *vpm, uint32_t desc) \
104
- { do_imopa(vza, vzn, vzm, vpn, vpm, desc, NAME); }
105
+#define DEF_IMOPH(NAME, S) \
106
+ void HELPER(sme_##NAME##_##S)(void *vza, void *vzn, void *vzm, \
107
+ void *vpn, void *vpm, uint32_t desc) \
108
+ { do_imopa_##S(vza, vzn, vzm, vpn, vpm, desc, NAME##_##S); }
109
110
-DEF_IMOPH(smopa_s)
111
-DEF_IMOPH(umopa_s)
112
-DEF_IMOPH(sumopa_s)
113
-DEF_IMOPH(usmopa_s)
114
-DEF_IMOPH(smopa_d)
115
-DEF_IMOPH(umopa_d)
116
-DEF_IMOPH(sumopa_d)
117
-DEF_IMOPH(usmopa_d)
118
+DEF_IMOPH(smopa, s)
119
+DEF_IMOPH(umopa, s)
120
+DEF_IMOPH(sumopa, s)
121
+DEF_IMOPH(usmopa, s)
122
+
123
+DEF_IMOPH(smopa, d)
124
+DEF_IMOPH(umopa, d)
125
+DEF_IMOPH(sumopa, d)
126
+DEF_IMOPH(usmopa, d)
127
diff --git a/tests/tcg/aarch64/sme-smopa-1.c b/tests/tcg/aarch64/sme-smopa-1.c
128
new file mode 100644
129
index XXXXXXX..XXXXXXX
130
--- /dev/null
131
+++ b/tests/tcg/aarch64/sme-smopa-1.c
132
@@ -XXX,XX +XXX,XX @@
133
+#include <stdio.h>
134
+#include <string.h>
135
+
136
+int main()
137
+{
138
+ static const int cmp[4][4] = {
139
+ { 110, 134, 158, 182 },
140
+ { 390, 478, 566, 654 },
141
+ { 670, 822, 974, 1126 },
142
+ { 950, 1166, 1382, 1598 }
143
+ };
144
+ int dst[4][4];
145
+ int *tmp = &dst[0][0];
146
+
147
+ asm volatile(
148
+ ".arch armv8-r+sme\n\t"
149
+ "smstart\n\t"
150
+ "index z0.b, #0, #1\n\t"
151
+ "movprfx z1, z0\n\t"
152
+ "add z1.b, z1.b, #16\n\t"
153
+ "ptrue p0.b\n\t"
154
+ "smopa za0.s, p0/m, p0/m, z0.b, z1.b\n\t"
155
+ "ptrue p0.s, vl4\n\t"
156
+ "mov w12, #0\n\t"
157
+ "st1w { za0h.s[w12, #0] }, p0, [%0]\n\t"
158
+ "add %0, %0, #16\n\t"
159
+ "st1w { za0h.s[w12, #1] }, p0, [%0]\n\t"
160
+ "add %0, %0, #16\n\t"
161
+ "st1w { za0h.s[w12, #2] }, p0, [%0]\n\t"
162
+ "add %0, %0, #16\n\t"
163
+ "st1w { za0h.s[w12, #3] }, p0, [%0]\n\t"
164
+ "smstop"
165
+ : "+r"(tmp) : : "memory");
166
+
167
+ if (memcmp(cmp, dst, sizeof(dst)) == 0) {
168
+ return 0;
169
+ }
170
+
171
+ /* See above for correct results. */
172
+ for (int i = 0; i < 4; ++i) {
173
+ for (int j = 0; j < 4; ++j) {
174
+ printf("%6d", dst[i][j]);
175
+ }
176
+ printf("\n");
177
+ }
178
+ return 1;
179
+}
180
diff --git a/tests/tcg/aarch64/sme-smopa-2.c b/tests/tcg/aarch64/sme-smopa-2.c
181
new file mode 100644
182
index XXXXXXX..XXXXXXX
183
--- /dev/null
184
+++ b/tests/tcg/aarch64/sme-smopa-2.c
185
@@ -XXX,XX +XXX,XX @@
186
+#include <stdio.h>
187
+#include <string.h>
188
+
189
+int main()
190
+{
191
+ static const long cmp[4][4] = {
192
+ { 110, 134, 158, 182 },
193
+ { 390, 478, 566, 654 },
194
+ { 670, 822, 974, 1126 },
195
+ { 950, 1166, 1382, 1598 }
196
+ };
197
+ long dst[4][4];
198
+ long *tmp = &dst[0][0];
199
+ long svl;
200
+
201
+ /* Validate that we have a wide enough vector for 4 elements. */
202
+ asm(".arch armv8-r+sme-i64\n\trdsvl %0, #1" : "=r"(svl));
203
+ if (svl < 32) {
204
+ return 0;
205
+ }
206
+
207
+ asm volatile(
208
+ "smstart\n\t"
209
+ "index z0.h, #0, #1\n\t"
210
+ "movprfx z1, z0\n\t"
211
+ "add z1.h, z1.h, #16\n\t"
212
+ "ptrue p0.b\n\t"
213
+ "smopa za0.d, p0/m, p0/m, z0.h, z1.h\n\t"
214
+ "ptrue p0.d, vl4\n\t"
215
+ "mov w12, #0\n\t"
216
+ "st1d { za0h.d[w12, #0] }, p0, [%0]\n\t"
217
+ "add %0, %0, #32\n\t"
218
+ "st1d { za0h.d[w12, #1] }, p0, [%0]\n\t"
219
+ "mov w12, #2\n\t"
220
+ "add %0, %0, #32\n\t"
221
+ "st1d { za0h.d[w12, #0] }, p0, [%0]\n\t"
222
+ "add %0, %0, #32\n\t"
223
+ "st1d { za0h.d[w12, #1] }, p0, [%0]\n\t"
224
+ "smstop"
225
+ : "+r"(tmp) : : "memory");
226
+
227
+ if (memcmp(cmp, dst, sizeof(dst)) == 0) {
228
+ return 0;
229
+ }
230
+
231
+ /* See above for correct results. */
232
+ for (int i = 0; i < 4; ++i) {
233
+ for (int j = 0; j < 4; ++j) {
234
+ printf("%6ld", dst[i][j]);
235
+ }
236
+ printf("\n");
237
+ }
238
+ return 1;
239
+}
240
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
241
index XXXXXXX..XXXXXXX 100644
242
--- a/tests/tcg/aarch64/Makefile.target
243
+++ b/tests/tcg/aarch64/Makefile.target
244
@@ -XXX,XX +XXX,XX @@ endif
245
246
# SME Tests
247
ifneq ($(CROSS_AS_HAS_ARMV9_SME),)
248
-AARCH64_TESTS += sme-outprod1
249
+AARCH64_TESTS += sme-outprod1 sme-smopa-1 sme-smopa-2
250
endif
251
252
# System Registers Tests
80
--
253
--
81
2.20.1
254
2.34.1
82
255
83
256
diff view generated by jsdifflib
Deleted patch
1
From: Bin Meng <bmeng.cn@gmail.com>
2
1
3
Read or write to uart registers when unclocked or in reset should be
4
ignored. Add the check there, and as a result of this, the check in
5
uart_write_tx_fifo() is now unnecessary.
6
7
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-id: 20210901124521.30599-6-bmeng.cn@gmail.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/char/cadence_uart.c | 15 ++++++++++-----
14
1 file changed, 10 insertions(+), 5 deletions(-)
15
16
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/char/cadence_uart.c
19
+++ b/hw/char/cadence_uart.c
20
@@ -XXX,XX +XXX,XX @@ static gboolean cadence_uart_xmit(void *do_not_use, GIOCondition cond,
21
static void uart_write_tx_fifo(CadenceUARTState *s, const uint8_t *buf,
22
int size)
23
{
24
- /* ignore characters when unclocked or in reset */
25
- if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) {
26
- return;
27
- }
28
-
29
if ((s->r[R_CR] & UART_CR_TX_DIS) || !(s->r[R_CR] & UART_CR_TX_EN)) {
30
return;
31
}
32
@@ -XXX,XX +XXX,XX @@ static MemTxResult uart_write(void *opaque, hwaddr offset,
33
{
34
CadenceUARTState *s = opaque;
35
36
+ /* ignore access when unclocked or in reset */
37
+ if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) {
38
+ return MEMTX_ERROR;
39
+ }
40
+
41
DB_PRINT(" offset:%x data:%08x\n", (unsigned)offset, (unsigned)value);
42
offset >>= 2;
43
if (offset >= CADENCE_UART_R_MAX) {
44
@@ -XXX,XX +XXX,XX @@ static MemTxResult uart_read(void *opaque, hwaddr offset,
45
CadenceUARTState *s = opaque;
46
uint32_t c = 0;
47
48
+ /* ignore access when unclocked or in reset */
49
+ if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) {
50
+ return MEMTX_ERROR;
51
+ }
52
+
53
offset >>= 2;
54
if (offset >= CADENCE_UART_R_MAX) {
55
return MEMTX_DECODE_ERROR;
56
--
57
2.20.1
58
59
diff view generated by jsdifflib
Deleted patch
1
From: Bin Meng <bmeng.cn@gmail.com>
2
1
3
We've got SW that expects FSBL (Bootlooader) to setup clocks and
4
resets. It's quite common that users run that SW on QEMU without
5
FSBL (FSBL typically requires the Xilinx tools installed). That's
6
fine, since users can stil use -device loader to enable clocks etc.
7
8
To help folks understand what's going, a log (guest-error) message
9
would be helpful here. In particular with the serial port since
10
things will go very quiet if they get things wrong.
11
12
Suggested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
13
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
14
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
15
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
16
Message-id: 20210901124521.30599-7-bmeng.cn@gmail.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
hw/char/cadence_uart.c | 8 ++++++++
20
1 file changed, 8 insertions(+)
21
22
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/char/cadence_uart.c
25
+++ b/hw/char/cadence_uart.c
26
@@ -XXX,XX +XXX,XX @@ static int uart_can_receive(void *opaque)
27
28
/* ignore characters when unclocked or in reset */
29
if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) {
30
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: uart is unclocked or in reset\n",
31
+ __func__);
32
return 0;
33
}
34
35
@@ -XXX,XX +XXX,XX @@ static void uart_event(void *opaque, QEMUChrEvent event)
36
37
/* ignore characters when unclocked or in reset */
38
if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) {
39
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: uart is unclocked or in reset\n",
40
+ __func__);
41
return;
42
}
43
44
@@ -XXX,XX +XXX,XX @@ static MemTxResult uart_write(void *opaque, hwaddr offset,
45
46
/* ignore access when unclocked or in reset */
47
if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) {
48
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: uart is unclocked or in reset\n",
49
+ __func__);
50
return MEMTX_ERROR;
51
}
52
53
@@ -XXX,XX +XXX,XX @@ static MemTxResult uart_read(void *opaque, hwaddr offset,
54
55
/* ignore access when unclocked or in reset */
56
if (!clock_is_enabled(s->refclk) || device_is_in_reset(DEVICE(s))) {
57
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: uart is unclocked or in reset\n",
58
+ __func__);
59
return MEMTX_ERROR;
60
}
61
62
--
63
2.20.1
64
65
diff view generated by jsdifflib
Deleted patch
1
From: Marc Zyngier <maz@kernel.org>
2
1
3
Although we probe for the IPA limits imposed by KVM (and the hardware)
4
when computing the memory map, we still use the old style '0' when
5
creating a scratch VM in kvm_arm_create_scratch_host_vcpu().
6
7
On systems that are severely IPA challenged (such as the Apple M1),
8
this results in a failure as KVM cannot use the default 40bit that
9
'0' represents.
10
11
Instead, probe for the extension and use the reported IPA limit
12
if available.
13
14
Cc: Andrew Jones <drjones@redhat.com>
15
Cc: Eric Auger <eric.auger@redhat.com>
16
Cc: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Marc Zyngier <maz@kernel.org>
18
Reviewed-by: Andrew Jones <drjones@redhat.com>
19
Message-id: 20210822144441.1290891-2-maz@kernel.org
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
22
target/arm/kvm.c | 7 ++++++-
23
1 file changed, 6 insertions(+), 1 deletion(-)
24
25
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/kvm.c
28
+++ b/target/arm/kvm.c
29
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
30
struct kvm_vcpu_init *init)
31
{
32
int ret = 0, kvmfd = -1, vmfd = -1, cpufd = -1;
33
+ int max_vm_pa_size;
34
35
kvmfd = qemu_open_old("/dev/kvm", O_RDWR);
36
if (kvmfd < 0) {
37
goto err;
38
}
39
- vmfd = ioctl(kvmfd, KVM_CREATE_VM, 0);
40
+ max_vm_pa_size = ioctl(kvmfd, KVM_CHECK_EXTENSION, KVM_CAP_ARM_VM_IPA_SIZE);
41
+ if (max_vm_pa_size < 0) {
42
+ max_vm_pa_size = 0;
43
+ }
44
+ vmfd = ioctl(kvmfd, KVM_CREATE_VM, max_vm_pa_size);
45
if (vmfd < 0) {
46
goto err;
47
}
48
--
49
2.20.1
50
51
diff view generated by jsdifflib
Deleted patch
1
From: Shashi Mallela <shashi.mallela@linaro.org>
2
1
3
Defined descriptors for ITS device table,collection table and ITS
4
command queue entities.Implemented register read/write functions,
5
extract ITS table parameters and command queue parameters,extended
6
gicv3 common to capture qemu address space(which host the ITS table
7
platform memories required for subsequent ITS processing) and
8
initialize the same in ITS device.
9
10
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Eric Auger <eric.auger@redhat.com>
13
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
14
Message-id: 20210910143951.92242-3-shashi.mallela@linaro.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
hw/intc/gicv3_internal.h | 29 ++
18
include/hw/intc/arm_gicv3_common.h | 3 +
19
include/hw/intc/arm_gicv3_its_common.h | 23 ++
20
hw/intc/arm_gicv3_its.c | 376 +++++++++++++++++++++++++
21
4 files changed, 431 insertions(+)
22
23
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/intc/gicv3_internal.h
26
+++ b/hw/intc/gicv3_internal.h
27
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_BASER, INNERCACHE, 59, 3)
28
FIELD(GITS_BASER, INDIRECT, 62, 1)
29
FIELD(GITS_BASER, VALID, 63, 1)
30
31
+FIELD(GITS_CBASER, SIZE, 0, 8)
32
+FIELD(GITS_CBASER, SHAREABILITY, 10, 2)
33
+FIELD(GITS_CBASER, PHYADDR, 12, 40)
34
+FIELD(GITS_CBASER, OUTERCACHE, 53, 3)
35
+FIELD(GITS_CBASER, INNERCACHE, 59, 3)
36
+FIELD(GITS_CBASER, VALID, 63, 1)
37
+
38
+FIELD(GITS_CREADR, STALLED, 0, 1)
39
+FIELD(GITS_CREADR, OFFSET, 5, 15)
40
+
41
+FIELD(GITS_CWRITER, RETRY, 0, 1)
42
+FIELD(GITS_CWRITER, OFFSET, 5, 15)
43
+
44
+FIELD(GITS_CTLR, ENABLED, 0, 1)
45
FIELD(GITS_CTLR, QUIESCENT, 31, 1)
46
47
FIELD(GITS_TYPER, PHYSICAL, 0, 1)
48
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, PTA, 19, 1)
49
FIELD(GITS_TYPER, CIDBITS, 32, 4)
50
FIELD(GITS_TYPER, CIL, 36, 1)
51
52
+#define GITS_IDREGS 0xFFD0
53
+
54
+#define ITS_CTLR_ENABLED (1U) /* ITS Enabled */
55
+
56
+#define GITS_BASER_RO_MASK (R_GITS_BASER_ENTRYSIZE_MASK | \
57
+ R_GITS_BASER_TYPE_MASK)
58
+
59
#define GITS_BASER_PAGESIZE_4K 0
60
#define GITS_BASER_PAGESIZE_16K 1
61
#define GITS_BASER_PAGESIZE_64K 2
62
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1)
63
#define GITS_BASER_TYPE_DEVICE 1ULL
64
#define GITS_BASER_TYPE_COLLECTION 4ULL
65
66
+#define GITS_PAGE_SIZE_4K 0x1000
67
+#define GITS_PAGE_SIZE_16K 0x4000
68
+#define GITS_PAGE_SIZE_64K 0x10000
69
+
70
+#define L1TABLE_ENTRY_SIZE 8
71
+
72
+#define GITS_CMDQ_ENTRY_SIZE 32
73
+
74
/**
75
* Default features advertised by this version of ITS
76
*/
77
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
78
index XXXXXXX..XXXXXXX 100644
79
--- a/include/hw/intc/arm_gicv3_common.h
80
+++ b/include/hw/intc/arm_gicv3_common.h
81
@@ -XXX,XX +XXX,XX @@ struct GICv3State {
82
int dev_fd; /* kvm device fd if backed by kvm vgic support */
83
Error *migration_blocker;
84
85
+ MemoryRegion *dma;
86
+ AddressSpace dma_as;
87
+
88
/* Distributor */
89
90
/* for a GIC with the security extensions the NS banked version of this
91
diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h
92
index XXXXXXX..XXXXXXX 100644
93
--- a/include/hw/intc/arm_gicv3_its_common.h
94
+++ b/include/hw/intc/arm_gicv3_its_common.h
95
@@ -XXX,XX +XXX,XX @@
96
97
#define GITS_TRANSLATER 0x0040
98
99
+typedef struct {
100
+ bool valid;
101
+ bool indirect;
102
+ uint16_t entry_sz;
103
+ uint32_t page_sz;
104
+ uint32_t max_entries;
105
+ union {
106
+ uint32_t max_devids;
107
+ uint32_t max_collids;
108
+ } maxids;
109
+ uint64_t base_addr;
110
+} TableDesc;
111
+
112
+typedef struct {
113
+ bool valid;
114
+ uint32_t max_entries;
115
+ uint64_t base_addr;
116
+} CmdQDesc;
117
+
118
struct GICv3ITSState {
119
SysBusDevice parent_obj;
120
121
@@ -XXX,XX +XXX,XX @@ struct GICv3ITSState {
122
uint64_t creadr;
123
uint64_t baser[8];
124
125
+ TableDesc dt;
126
+ TableDesc ct;
127
+ CmdQDesc cq;
128
+
129
Error *migration_blocker;
130
};
131
132
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
133
index XXXXXXX..XXXXXXX 100644
134
--- a/hw/intc/arm_gicv3_its.c
135
+++ b/hw/intc/arm_gicv3_its.c
136
@@ -XXX,XX +XXX,XX @@ struct GICv3ITSClass {
137
void (*parent_reset)(DeviceState *dev);
138
};
139
140
+static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
141
+{
142
+ uint64_t result = 0;
143
+
144
+ switch (page_sz) {
145
+ case GITS_PAGE_SIZE_4K:
146
+ case GITS_PAGE_SIZE_16K:
147
+ result = FIELD_EX64(value, GITS_BASER, PHYADDR) << 12;
148
+ break;
149
+
150
+ case GITS_PAGE_SIZE_64K:
151
+ result = FIELD_EX64(value, GITS_BASER, PHYADDRL_64K) << 16;
152
+ result |= FIELD_EX64(value, GITS_BASER, PHYADDRH_64K) << 48;
153
+ break;
154
+
155
+ default:
156
+ break;
157
+ }
158
+ return result;
159
+}
160
+
161
+/*
162
+ * This function extracts the ITS Device and Collection table specific
163
+ * parameters (like base_addr, size etc) from GITS_BASER register.
164
+ * It is called during ITS enable and also during post_load migration
165
+ */
166
+static void extract_table_params(GICv3ITSState *s)
167
+{
168
+ uint16_t num_pages = 0;
169
+ uint8_t page_sz_type;
170
+ uint8_t type;
171
+ uint32_t page_sz = 0;
172
+ uint64_t value;
173
+
174
+ for (int i = 0; i < 8; i++) {
175
+ value = s->baser[i];
176
+
177
+ if (!value) {
178
+ continue;
179
+ }
180
+
181
+ page_sz_type = FIELD_EX64(value, GITS_BASER, PAGESIZE);
182
+
183
+ switch (page_sz_type) {
184
+ case 0:
185
+ page_sz = GITS_PAGE_SIZE_4K;
186
+ break;
187
+
188
+ case 1:
189
+ page_sz = GITS_PAGE_SIZE_16K;
190
+ break;
191
+
192
+ case 2:
193
+ case 3:
194
+ page_sz = GITS_PAGE_SIZE_64K;
195
+ break;
196
+
197
+ default:
198
+ g_assert_not_reached();
199
+ }
200
+
201
+ num_pages = FIELD_EX64(value, GITS_BASER, SIZE) + 1;
202
+
203
+ type = FIELD_EX64(value, GITS_BASER, TYPE);
204
+
205
+ switch (type) {
206
+
207
+ case GITS_BASER_TYPE_DEVICE:
208
+ memset(&s->dt, 0 , sizeof(s->dt));
209
+ s->dt.valid = FIELD_EX64(value, GITS_BASER, VALID);
210
+
211
+ if (!s->dt.valid) {
212
+ return;
213
+ }
214
+
215
+ s->dt.page_sz = page_sz;
216
+ s->dt.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
217
+ s->dt.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
218
+
219
+ if (!s->dt.indirect) {
220
+ s->dt.max_entries = (num_pages * page_sz) / s->dt.entry_sz;
221
+ } else {
222
+ s->dt.max_entries = (((num_pages * page_sz) /
223
+ L1TABLE_ENTRY_SIZE) *
224
+ (page_sz / s->dt.entry_sz));
225
+ }
226
+
227
+ s->dt.maxids.max_devids = (1UL << (FIELD_EX64(s->typer, GITS_TYPER,
228
+ DEVBITS) + 1));
229
+
230
+ s->dt.base_addr = baser_base_addr(value, page_sz);
231
+
232
+ break;
233
+
234
+ case GITS_BASER_TYPE_COLLECTION:
235
+ memset(&s->ct, 0 , sizeof(s->ct));
236
+ s->ct.valid = FIELD_EX64(value, GITS_BASER, VALID);
237
+
238
+ /*
239
+ * GITS_TYPER.HCC is 0 for this implementation
240
+ * hence writes are discarded if ct.valid is 0
241
+ */
242
+ if (!s->ct.valid) {
243
+ return;
244
+ }
245
+
246
+ s->ct.page_sz = page_sz;
247
+ s->ct.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
248
+ s->ct.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
249
+
250
+ if (!s->ct.indirect) {
251
+ s->ct.max_entries = (num_pages * page_sz) / s->ct.entry_sz;
252
+ } else {
253
+ s->ct.max_entries = (((num_pages * page_sz) /
254
+ L1TABLE_ENTRY_SIZE) *
255
+ (page_sz / s->ct.entry_sz));
256
+ }
257
+
258
+ if (FIELD_EX64(s->typer, GITS_TYPER, CIL)) {
259
+ s->ct.maxids.max_collids = (1UL << (FIELD_EX64(s->typer,
260
+ GITS_TYPER, CIDBITS) + 1));
261
+ } else {
262
+ /* 16-bit CollectionId supported when CIL == 0 */
263
+ s->ct.maxids.max_collids = (1UL << 16);
264
+ }
265
+
266
+ s->ct.base_addr = baser_base_addr(value, page_sz);
267
+
268
+ break;
269
+
270
+ default:
271
+ break;
272
+ }
273
+ }
274
+}
275
+
276
+static void extract_cmdq_params(GICv3ITSState *s)
277
+{
278
+ uint16_t num_pages = 0;
279
+ uint64_t value = s->cbaser;
280
+
281
+ num_pages = FIELD_EX64(value, GITS_CBASER, SIZE) + 1;
282
+
283
+ memset(&s->cq, 0 , sizeof(s->cq));
284
+ s->cq.valid = FIELD_EX64(value, GITS_CBASER, VALID);
285
+
286
+ if (s->cq.valid) {
287
+ s->cq.max_entries = (num_pages * GITS_PAGE_SIZE_4K) /
288
+ GITS_CMDQ_ENTRY_SIZE;
289
+ s->cq.base_addr = FIELD_EX64(value, GITS_CBASER, PHYADDR);
290
+ s->cq.base_addr <<= R_GITS_CBASER_PHYADDR_SHIFT;
291
+ }
292
+}
293
+
294
static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset,
295
uint64_t data, unsigned size,
296
MemTxAttrs attrs)
297
@@ -XXX,XX +XXX,XX @@ static bool its_writel(GICv3ITSState *s, hwaddr offset,
298
uint64_t value, MemTxAttrs attrs)
299
{
300
bool result = true;
301
+ int index;
302
303
+ switch (offset) {
304
+ case GITS_CTLR:
305
+ s->ctlr |= (value & ~(s->ctlr));
306
+
307
+ if (s->ctlr & ITS_CTLR_ENABLED) {
308
+ extract_table_params(s);
309
+ extract_cmdq_params(s);
310
+ s->creadr = 0;
311
+ }
312
+ break;
313
+ case GITS_CBASER:
314
+ /*
315
+ * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
316
+ * already enabled
317
+ */
318
+ if (!(s->ctlr & ITS_CTLR_ENABLED)) {
319
+ s->cbaser = deposit64(s->cbaser, 0, 32, value);
320
+ s->creadr = 0;
321
+ s->cwriter = s->creadr;
322
+ }
323
+ break;
324
+ case GITS_CBASER + 4:
325
+ /*
326
+ * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
327
+ * already enabled
328
+ */
329
+ if (!(s->ctlr & ITS_CTLR_ENABLED)) {
330
+ s->cbaser = deposit64(s->cbaser, 32, 32, value);
331
+ s->creadr = 0;
332
+ s->cwriter = s->creadr;
333
+ }
334
+ break;
335
+ case GITS_CWRITER:
336
+ s->cwriter = deposit64(s->cwriter, 0, 32,
337
+ (value & ~R_GITS_CWRITER_RETRY_MASK));
338
+ break;
339
+ case GITS_CWRITER + 4:
340
+ s->cwriter = deposit64(s->cwriter, 32, 32, value);
341
+ break;
342
+ case GITS_CREADR:
343
+ if (s->gicv3->gicd_ctlr & GICD_CTLR_DS) {
344
+ s->creadr = deposit64(s->creadr, 0, 32,
345
+ (value & ~R_GITS_CREADR_STALLED_MASK));
346
+ } else {
347
+ /* RO register, ignore the write */
348
+ qemu_log_mask(LOG_GUEST_ERROR,
349
+ "%s: invalid guest write to RO register at offset "
350
+ TARGET_FMT_plx "\n", __func__, offset);
351
+ }
352
+ break;
353
+ case GITS_CREADR + 4:
354
+ if (s->gicv3->gicd_ctlr & GICD_CTLR_DS) {
355
+ s->creadr = deposit64(s->creadr, 32, 32, value);
356
+ } else {
357
+ /* RO register, ignore the write */
358
+ qemu_log_mask(LOG_GUEST_ERROR,
359
+ "%s: invalid guest write to RO register at offset "
360
+ TARGET_FMT_plx "\n", __func__, offset);
361
+ }
362
+ break;
363
+ case GITS_BASER ... GITS_BASER + 0x3f:
364
+ /*
365
+ * IMPDEF choice:- GITS_BASERn register becomes RO if ITS is
366
+ * already enabled
367
+ */
368
+ if (!(s->ctlr & ITS_CTLR_ENABLED)) {
369
+ index = (offset - GITS_BASER) / 8;
370
+
371
+ if (offset & 7) {
372
+ value <<= 32;
373
+ value &= ~GITS_BASER_RO_MASK;
374
+ s->baser[index] &= GITS_BASER_RO_MASK | MAKE_64BIT_MASK(0, 32);
375
+ s->baser[index] |= value;
376
+ } else {
377
+ value &= ~GITS_BASER_RO_MASK;
378
+ s->baser[index] &= GITS_BASER_RO_MASK | MAKE_64BIT_MASK(32, 32);
379
+ s->baser[index] |= value;
380
+ }
381
+ }
382
+ break;
383
+ case GITS_IIDR:
384
+ case GITS_IDREGS ... GITS_IDREGS + 0x2f:
385
+ /* RO registers, ignore the write */
386
+ qemu_log_mask(LOG_GUEST_ERROR,
387
+ "%s: invalid guest write to RO register at offset "
388
+ TARGET_FMT_plx "\n", __func__, offset);
389
+ break;
390
+ default:
391
+ result = false;
392
+ break;
393
+ }
394
return result;
395
}
396
397
@@ -XXX,XX +XXX,XX @@ static bool its_readl(GICv3ITSState *s, hwaddr offset,
398
uint64_t *data, MemTxAttrs attrs)
399
{
400
bool result = true;
401
+ int index;
402
403
+ switch (offset) {
404
+ case GITS_CTLR:
405
+ *data = s->ctlr;
406
+ break;
407
+ case GITS_IIDR:
408
+ *data = gicv3_iidr();
409
+ break;
410
+ case GITS_IDREGS ... GITS_IDREGS + 0x2f:
411
+ /* ID registers */
412
+ *data = gicv3_idreg(offset - GITS_IDREGS);
413
+ break;
414
+ case GITS_TYPER:
415
+ *data = extract64(s->typer, 0, 32);
416
+ break;
417
+ case GITS_TYPER + 4:
418
+ *data = extract64(s->typer, 32, 32);
419
+ break;
420
+ case GITS_CBASER:
421
+ *data = extract64(s->cbaser, 0, 32);
422
+ break;
423
+ case GITS_CBASER + 4:
424
+ *data = extract64(s->cbaser, 32, 32);
425
+ break;
426
+ case GITS_CREADR:
427
+ *data = extract64(s->creadr, 0, 32);
428
+ break;
429
+ case GITS_CREADR + 4:
430
+ *data = extract64(s->creadr, 32, 32);
431
+ break;
432
+ case GITS_CWRITER:
433
+ *data = extract64(s->cwriter, 0, 32);
434
+ break;
435
+ case GITS_CWRITER + 4:
436
+ *data = extract64(s->cwriter, 32, 32);
437
+ break;
438
+ case GITS_BASER ... GITS_BASER + 0x3f:
439
+ index = (offset - GITS_BASER) / 8;
440
+ if (offset & 7) {
441
+ *data = extract64(s->baser[index], 32, 32);
442
+ } else {
443
+ *data = extract64(s->baser[index], 0, 32);
444
+ }
445
+ break;
446
+ default:
447
+ result = false;
448
+ break;
449
+ }
450
return result;
451
}
452
453
@@ -XXX,XX +XXX,XX @@ static bool its_writell(GICv3ITSState *s, hwaddr offset,
454
uint64_t value, MemTxAttrs attrs)
455
{
456
bool result = true;
457
+ int index;
458
459
+ switch (offset) {
460
+ case GITS_BASER ... GITS_BASER + 0x3f:
461
+ /*
462
+ * IMPDEF choice:- GITS_BASERn register becomes RO if ITS is
463
+ * already enabled
464
+ */
465
+ if (!(s->ctlr & ITS_CTLR_ENABLED)) {
466
+ index = (offset - GITS_BASER) / 8;
467
+ s->baser[index] &= GITS_BASER_RO_MASK;
468
+ s->baser[index] |= (value & ~GITS_BASER_RO_MASK);
469
+ }
470
+ break;
471
+ case GITS_CBASER:
472
+ /*
473
+ * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
474
+ * already enabled
475
+ */
476
+ if (!(s->ctlr & ITS_CTLR_ENABLED)) {
477
+ s->cbaser = value;
478
+ s->creadr = 0;
479
+ s->cwriter = s->creadr;
480
+ }
481
+ break;
482
+ case GITS_CWRITER:
483
+ s->cwriter = value & ~R_GITS_CWRITER_RETRY_MASK;
484
+ break;
485
+ case GITS_CREADR:
486
+ if (s->gicv3->gicd_ctlr & GICD_CTLR_DS) {
487
+ s->creadr = value & ~R_GITS_CREADR_STALLED_MASK;
488
+ } else {
489
+ /* RO register, ignore the write */
490
+ qemu_log_mask(LOG_GUEST_ERROR,
491
+ "%s: invalid guest write to RO register at offset "
492
+ TARGET_FMT_plx "\n", __func__, offset);
493
+ }
494
+ break;
495
+ case GITS_TYPER:
496
+ /* RO registers, ignore the write */
497
+ qemu_log_mask(LOG_GUEST_ERROR,
498
+ "%s: invalid guest write to RO register at offset "
499
+ TARGET_FMT_plx "\n", __func__, offset);
500
+ break;
501
+ default:
502
+ result = false;
503
+ break;
504
+ }
505
return result;
506
}
507
508
@@ -XXX,XX +XXX,XX @@ static bool its_readll(GICv3ITSState *s, hwaddr offset,
509
uint64_t *data, MemTxAttrs attrs)
510
{
511
bool result = true;
512
+ int index;
513
514
+ switch (offset) {
515
+ case GITS_TYPER:
516
+ *data = s->typer;
517
+ break;
518
+ case GITS_BASER ... GITS_BASER + 0x3f:
519
+ index = (offset - GITS_BASER) / 8;
520
+ *data = s->baser[index];
521
+ break;
522
+ case GITS_CBASER:
523
+ *data = s->cbaser;
524
+ break;
525
+ case GITS_CREADR:
526
+ *data = s->creadr;
527
+ break;
528
+ case GITS_CWRITER:
529
+ *data = s->cwriter;
530
+ break;
531
+ default:
532
+ result = false;
533
+ break;
534
+ }
535
return result;
536
}
537
538
@@ -XXX,XX +XXX,XX @@ static void gicv3_arm_its_realize(DeviceState *dev, Error **errp)
539
540
gicv3_its_init_mmio(s, &gicv3_its_control_ops, &gicv3_its_translation_ops);
541
542
+ address_space_init(&s->gicv3->dma_as, s->gicv3->dma,
543
+ "gicv3-its-sysmem");
544
+
545
/* set the ITS default features supported */
546
s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL,
547
GITS_TYPE_PHYSICAL);
548
@@ -XXX,XX +XXX,XX @@ static void gicv3_its_reset(DeviceState *dev)
549
GITS_CTE_SIZE - 1);
550
}
551
552
+static void gicv3_its_post_load(GICv3ITSState *s)
553
+{
554
+ if (s->ctlr & ITS_CTLR_ENABLED) {
555
+ extract_table_params(s);
556
+ extract_cmdq_params(s);
557
+ }
558
+}
559
+
560
static Property gicv3_its_props[] = {
561
DEFINE_PROP_LINK("parent-gicv3", GICv3ITSState, gicv3, "arm-gicv3",
562
GICv3State *),
563
@@ -XXX,XX +XXX,XX @@ static void gicv3_its_class_init(ObjectClass *klass, void *data)
564
{
565
DeviceClass *dc = DEVICE_CLASS(klass);
566
GICv3ITSClass *ic = ARM_GICV3_ITS_CLASS(klass);
567
+ GICv3ITSCommonClass *icc = ARM_GICV3_ITS_COMMON_CLASS(klass);
568
569
dc->realize = gicv3_arm_its_realize;
570
device_class_set_props(dc, gicv3_its_props);
571
device_class_set_parent_reset(dc, gicv3_its_reset, &ic->parent_reset);
572
+ icc->post_load = gicv3_its_post_load;
573
}
574
575
static const TypeInfo gicv3_its_info = {
576
--
577
2.20.1
578
579
diff view generated by jsdifflib
Deleted patch
1
From: Shashi Mallela <shashi.mallela@linaro.org>
2
1
3
Added properties to enable ITS feature and define qemu system
4
address space memory in gicv3 common,setup distributor and
5
redistributor registers to indicate LPI support.
6
7
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
10
Message-id: 20210910143951.92242-6-shashi.mallela@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/intc/gicv3_internal.h | 2 ++
14
include/hw/intc/arm_gicv3_common.h | 1 +
15
hw/intc/arm_gicv3_common.c | 12 ++++++++++++
16
hw/intc/arm_gicv3_dist.c | 5 ++++-
17
hw/intc/arm_gicv3_redist.c | 12 +++++++++---
18
5 files changed, 28 insertions(+), 4 deletions(-)
19
20
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/intc/gicv3_internal.h
23
+++ b/hw/intc/gicv3_internal.h
24
@@ -XXX,XX +XXX,XX @@
25
#define GICD_CTLR_E1NWF (1U << 7)
26
#define GICD_CTLR_RWP (1U << 31)
27
28
+#define GICD_TYPER_LPIS_SHIFT 17
29
+
30
/* 16 bits EventId */
31
#define GICD_TYPER_IDBITS 0xf
32
33
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
34
index XXXXXXX..XXXXXXX 100644
35
--- a/include/hw/intc/arm_gicv3_common.h
36
+++ b/include/hw/intc/arm_gicv3_common.h
37
@@ -XXX,XX +XXX,XX @@ struct GICv3State {
38
uint32_t num_cpu;
39
uint32_t num_irq;
40
uint32_t revision;
41
+ bool lpi_enable;
42
bool security_extn;
43
bool irq_reset_nonsecure;
44
bool gicd_no_migration_shift_bug;
45
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/hw/intc/arm_gicv3_common.c
48
+++ b/hw/intc/arm_gicv3_common.c
49
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
50
return;
51
}
52
53
+ if (s->lpi_enable && !s->dma) {
54
+ error_setg(errp, "Redist-ITS: Guest 'sysmem' reference link not set");
55
+ return;
56
+ }
57
+
58
s->cpu = g_new0(GICv3CPUState, s->num_cpu);
59
60
for (i = 0; i < s->num_cpu; i++) {
61
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
62
(1 << 24) |
63
(i << 8) |
64
(last << 4);
65
+
66
+ if (s->lpi_enable) {
67
+ s->cpu[i].gicr_typer |= GICR_TYPER_PLPIS;
68
+ }
69
}
70
}
71
72
@@ -XXX,XX +XXX,XX @@ static Property arm_gicv3_common_properties[] = {
73
DEFINE_PROP_UINT32("num-cpu", GICv3State, num_cpu, 1),
74
DEFINE_PROP_UINT32("num-irq", GICv3State, num_irq, 32),
75
DEFINE_PROP_UINT32("revision", GICv3State, revision, 3),
76
+ DEFINE_PROP_BOOL("has-lpi", GICv3State, lpi_enable, 0),
77
DEFINE_PROP_BOOL("has-security-extensions", GICv3State, security_extn, 0),
78
DEFINE_PROP_ARRAY("redist-region-count", GICv3State, nb_redist_regions,
79
redist_region_count, qdev_prop_uint32, uint32_t),
80
+ DEFINE_PROP_LINK("sysmem", GICv3State, dma, TYPE_MEMORY_REGION,
81
+ MemoryRegion *),
82
DEFINE_PROP_END_OF_LIST(),
83
};
84
85
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/hw/intc/arm_gicv3_dist.c
88
+++ b/hw/intc/arm_gicv3_dist.c
89
@@ -XXX,XX +XXX,XX @@ static bool gicd_readl(GICv3State *s, hwaddr offset,
90
* A3V == 1 (non-zero values of Affinity level 3 supported)
91
* IDbits == 0xf (we support 16-bit interrupt identifiers)
92
* DVIS == 0 (Direct virtual LPI injection not supported)
93
- * LPIS == 0 (LPIs not supported)
94
+ * LPIS == 1 (LPIs are supported if affinity routing is enabled)
95
+ * num_LPIs == 0b00000 (bits [15:11],Number of LPIs as indicated
96
+ * by GICD_TYPER.IDbits)
97
* MBIS == 0 (message-based SPIs not supported)
98
* SecurityExtn == 1 if security extns supported
99
* CPUNumber == 0 since for us ARE is always 1
100
@@ -XXX,XX +XXX,XX @@ static bool gicd_readl(GICv3State *s, hwaddr offset,
101
bool sec_extn = !(s->gicd_ctlr & GICD_CTLR_DS);
102
103
*data = (1 << 25) | (1 << 24) | (sec_extn << 10) |
104
+ (s->lpi_enable << GICD_TYPER_LPIS_SHIFT) |
105
(0xf << 19) | itlinesnumber;
106
return true;
107
}
108
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
109
index XXXXXXX..XXXXXXX 100644
110
--- a/hw/intc/arm_gicv3_redist.c
111
+++ b/hw/intc/arm_gicv3_redist.c
112
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr offset,
113
case GICR_CTLR:
114
/* For our implementation, GICR_TYPER.DPGS is 0 and so all
115
* the DPG bits are RAZ/WI. We don't do anything asynchronously,
116
- * so UWP and RWP are RAZ/WI. And GICR_TYPER.LPIS is 0 (we don't
117
- * implement LPIs) so Enable_LPIs is RES0. So there are no writable
118
- * bits for us.
119
+ * so UWP and RWP are RAZ/WI. GICR_TYPER.LPIS is 1 (we
120
+ * implement LPIs) so Enable_LPIs is programmable.
121
*/
122
+ if (cs->gicr_typer & GICR_TYPER_PLPIS) {
123
+ if (value & GICR_CTLR_ENABLE_LPIS) {
124
+ cs->gicr_ctlr |= GICR_CTLR_ENABLE_LPIS;
125
+ } else {
126
+ cs->gicr_ctlr &= ~GICR_CTLR_ENABLE_LPIS;
127
+ }
128
+ }
129
return MEMTX_OK;
130
case GICR_STATUSR:
131
/* RAZ/WI for our implementation */
132
--
133
2.20.1
134
135
diff view generated by jsdifflib
1
From: Shashi Mallela <shashi.mallela@linaro.org>
1
The sun4v RTC device model added under commit a0e893039cf2ce0 in 2016
2
was unfortunately added with a license of GPL-v3-or-later, which is
3
not compatible with other QEMU code which has a GPL-v2-only license.
2
4
3
Included creation of ITS as part of virt platform GIC
5
Relicense the code in the .c and the .h file to GPL-v2-or-later,
4
initialization. This Emulated ITS model now co-exists with kvm
6
to make it compatible with the rest of QEMU.
5
ITS and is enabled in absence of kvm irq kernel support in a
6
platform.
7
7
8
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
8
Cc: qemu-stable@nongnu.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20210910143951.92242-9-shashi.mallela@linaro.org
10
Signed-off-by: Paolo Bonzini (for Red Hat) <pbonzini@redhat.com>
11
Signed-off-by: Artyom Tarasenko <atar4qemu@gmail.com>
12
Signed-off-by: Markus Armbruster <armbru@redhat.com>
13
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
14
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
15
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
16
Acked-by: Alex Bennée <alex.bennee@linaro.org>
17
Message-id: 20240223161300.938542-1-peter.maydell@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
19
---
13
include/hw/arm/virt.h | 2 ++
20
include/hw/rtc/sun4v-rtc.h | 2 +-
14
target/arm/kvm_arm.h | 4 ++--
21
hw/rtc/sun4v-rtc.c | 2 +-
15
hw/arm/virt.c | 29 +++++++++++++++++++++++++++--
22
2 files changed, 2 insertions(+), 2 deletions(-)
16
3 files changed, 31 insertions(+), 4 deletions(-)
17
23
18
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
24
diff --git a/include/hw/rtc/sun4v-rtc.h b/include/hw/rtc/sun4v-rtc.h
19
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/arm/virt.h
26
--- a/include/hw/rtc/sun4v-rtc.h
21
+++ b/include/hw/arm/virt.h
27
+++ b/include/hw/rtc/sun4v-rtc.h
22
@@ -XXX,XX +XXX,XX @@ struct VirtMachineClass {
28
@@ -XXX,XX +XXX,XX @@
23
MachineClass parent;
29
*
24
bool disallow_affinity_adjustment;
30
* Copyright (c) 2016 Artyom Tarasenko
25
bool no_its;
31
*
26
+ bool no_tcg_its;
32
- * This code is licensed under the GNU GPL v3 or (at your option) any later
27
bool no_pmu;
33
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
28
bool claim_edge_triggered_timers;
34
* version.
29
bool smbios_old_sys_ver;
35
*/
30
@@ -XXX,XX +XXX,XX @@ struct VirtMachineState {
36
31
bool highmem;
37
diff --git a/hw/rtc/sun4v-rtc.c b/hw/rtc/sun4v-rtc.c
32
bool highmem_ecam;
33
bool its;
34
+ bool tcg_its;
35
bool virt;
36
bool ras;
37
bool mte;
38
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
39
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/kvm_arm.h
39
--- a/hw/rtc/sun4v-rtc.c
41
+++ b/target/arm/kvm_arm.h
40
+++ b/hw/rtc/sun4v-rtc.c
42
@@ -XXX,XX +XXX,XX @@ static inline const char *its_class_name(void)
41
@@ -XXX,XX +XXX,XX @@
43
/* KVM implementation requires this capability */
42
*
44
return kvm_direct_msi_enabled() ? "arm-its-kvm" : NULL;
43
* Copyright (c) 2016 Artyom Tarasenko
45
} else {
44
*
46
- /* Software emulation is not implemented yet */
45
- * This code is licensed under the GNU GPL v3 or (at your option) any later
47
- return NULL;
46
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
48
+ /* Software emulation based model */
47
* version.
49
+ return "arm-gicv3-its";
48
*/
50
}
51
}
52
53
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/hw/arm/virt.c
56
+++ b/hw/arm/virt.c
57
@@ -XXX,XX +XXX,XX @@ static void create_its(VirtMachineState *vms)
58
const char *itsclass = its_class_name();
59
DeviceState *dev;
60
61
+ if (!strcmp(itsclass, "arm-gicv3-its")) {
62
+ if (!vms->tcg_its) {
63
+ itsclass = NULL;
64
+ }
65
+ }
66
+
67
if (!itsclass) {
68
/* Do nothing if not supported */
69
return;
70
@@ -XXX,XX +XXX,XX @@ static void create_v2m(VirtMachineState *vms)
71
vms->msi_controller = VIRT_MSI_CTRL_GICV2M;
72
}
73
74
-static void create_gic(VirtMachineState *vms)
75
+static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
76
{
77
MachineState *ms = MACHINE(vms);
78
/* We create a standalone GIC */
79
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms)
80
nb_redist_regions);
81
qdev_prop_set_uint32(vms->gic, "redist-region-count[0]", redist0_count);
82
83
+ if (!kvm_irqchip_in_kernel()) {
84
+ if (vms->tcg_its) {
85
+ object_property_set_link(OBJECT(vms->gic), "sysmem",
86
+ OBJECT(mem), &error_fatal);
87
+ qdev_prop_set_bit(vms->gic, "has-lpi", true);
88
+ }
89
+ }
90
+
91
if (nb_redist_regions == 2) {
92
uint32_t redist1_capacity =
93
vms->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE;
94
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
95
96
virt_flash_fdt(vms, sysmem, secure_sysmem ?: sysmem);
97
98
- create_gic(vms);
99
+ create_gic(vms, sysmem);
100
101
virt_cpu_post_init(vms, sysmem);
102
103
@@ -XXX,XX +XXX,XX @@ static void virt_instance_init(Object *obj)
104
} else {
105
/* Default allows ITS instantiation */
106
vms->its = true;
107
+
108
+ if (vmc->no_tcg_its) {
109
+ vms->tcg_its = false;
110
+ } else {
111
+ vms->tcg_its = true;
112
+ }
113
}
114
115
/* Default disallows iommu instantiation */
116
@@ -XXX,XX +XXX,XX @@ DEFINE_VIRT_MACHINE_AS_LATEST(6, 2)
117
118
static void virt_machine_6_1_options(MachineClass *mc)
119
{
120
+ VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
121
+
122
virt_machine_6_2_options(mc);
123
compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
124
+
125
+ /* qemu ITS was introduced with 6.2 */
126
+ vmc->no_tcg_its = true;
127
}
128
DEFINE_VIRT_MACHINE(6, 1)
129
49
130
--
50
--
131
2.20.1
51
2.34.1
132
52
133
53
diff view generated by jsdifflib
Deleted patch
1
From: Shashi Mallela <shashi.mallela@linaro.org>
2
1
3
Updated expected IORT files applicable with latest GICv3
4
ITS changes.
5
6
Full diff of new file disassembly:
7
8
/*
9
* Intel ACPI Component Architecture
10
* AML/ASL+ Disassembler version 20180629 (64-bit version)
11
* Copyright (c) 2000 - 2018 Intel Corporation
12
*
13
* Disassembly of tests/data/acpi/virt/IORT.pxb, Tue Jun 29 17:35:38 2021
14
*
15
* ACPI Data Table [IORT]
16
*
17
* Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue
18
*/
19
20
[000h 0000 4] Signature : "IORT" [IO Remapping Table]
21
[004h 0004 4] Table Length : 0000007C
22
[008h 0008 1] Revision : 00
23
[009h 0009 1] Checksum : 07
24
[00Ah 0010 6] Oem ID : "BOCHS "
25
[010h 0016 8] Oem Table ID : "BXPC "
26
[018h 0024 4] Oem Revision : 00000001
27
[01Ch 0028 4] Asl Compiler ID : "BXPC"
28
[020h 0032 4] Asl Compiler Revision : 00000001
29
30
[024h 0036 4] Node Count : 00000002
31
[028h 0040 4] Node Offset : 00000030
32
[02Ch 0044 4] Reserved : 00000000
33
34
[030h 0048 1] Type : 00
35
[031h 0049 2] Length : 0018
36
[033h 0051 1] Revision : 00
37
[034h 0052 4] Reserved : 00000000
38
[038h 0056 4] Mapping Count : 00000000
39
[03Ch 0060 4] Mapping Offset : 00000000
40
41
[040h 0064 4] ItsCount : 00000001
42
[044h 0068 4] Identifiers : 00000000
43
44
[048h 0072 1] Type : 02
45
[049h 0073 2] Length : 0034
46
[04Bh 0075 1] Revision : 00
47
[04Ch 0076 4] Reserved : 00000000
48
[050h 0080 4] Mapping Count : 00000001
49
[054h 0084 4] Mapping Offset : 00000020
50
51
[058h 0088 8] Memory Properties : [IORT Memory Access Properties]
52
[058h 0088 4] Cache Coherency : 00000001
53
[05Ch 0092 1] Hints (decoded below) : 00
54
Transient : 0
55
Write Allocate : 0
56
Read Allocate : 0
57
Override : 0
58
[05Dh 0093 2] Reserved : 0000
59
[05Fh 0095 1] Memory Flags (decoded below) : 03
60
Coherency : 1
61
Device Attribute : 1
62
[060h 0096 4] ATS Attribute : 00000000
63
[064h 0100 4] PCI Segment Number : 00000000
64
[068h 0104 1] Memory Size Limit : 00
65
[069h 0105 3] Reserved : 000000
66
67
[068h 0104 4] Input base : 00000000
68
[06Ch 0108 4] ID Count : 0000FFFF
69
[070h 0112 4] Output Base : 00000000
70
[074h 0116 4] Output Reference : 00000030
71
[078h 0120 4] Flags (decoded below) : 00000000
72
Single Mapping : 0
73
74
Raw Table Data: Length 124 (0x7C)
75
76
0000: 49 4F 52 54 7C 00 00 00 00 07 42 4F 43 48 53 20 // IORT|.....BOCHS
77
0010: 42 58 50 43 20 20 20 20 01 00 00 00 42 58 50 43 // BXPC ....BXPC
78
0020: 01 00 00 00 02 00 00 00 30 00 00 00 00 00 00 00 // ........0.......
79
0030: 00 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................
80
0040: 01 00 00 00 00 00 00 00 02 34 00 00 00 00 00 00 // .........4......
81
0050: 01 00 00 00 20 00 00 00 01 00 00 00 00 00 00 03 // .... ...........
82
0060: 00 00 00 00 00 00 00 00 00 00 00 00 FF FF 00 00 // ................
83
0070: 00 00 00 00 30 00 00 00 00 00 00 00 // ....0.......
84
85
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
86
Acked-by: Igor Mammedov <imammedo@redhat.com>
87
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
88
Message-id: 20210910143951.92242-10-shashi.mallela@linaro.org
89
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
90
---
91
tests/qtest/bios-tables-test-allowed-diff.h | 4 ----
92
tests/data/acpi/virt/IORT | Bin 0 -> 124 bytes
93
tests/data/acpi/virt/IORT.memhp | Bin 0 -> 124 bytes
94
tests/data/acpi/virt/IORT.numamem | Bin 0 -> 124 bytes
95
tests/data/acpi/virt/IORT.pxb | Bin 0 -> 124 bytes
96
5 files changed, 4 deletions(-)
97
98
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
99
index XXXXXXX..XXXXXXX 100644
100
--- a/tests/qtest/bios-tables-test-allowed-diff.h
101
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
102
@@ -1,5 +1 @@
103
/* List of comma-separated changed AML files to ignore */
104
-"tests/data/acpi/virt/IORT",
105
-"tests/data/acpi/virt/IORT.memhp",
106
-"tests/data/acpi/virt/IORT.numamem",
107
-"tests/data/acpi/virt/IORT.pxb",
108
diff --git a/tests/data/acpi/virt/IORT b/tests/data/acpi/virt/IORT
109
index XXXXXXX..XXXXXXX 100644
110
GIT binary patch
111
literal 124
112
zcmebD4+^Pa00MR=e`k+i1*eDrX9XZ&1PX!JAesq?4S*O7Bw!2(4Uz`|CKCt^;wu0#
113
QRGb+i3L*dhhtM#y0PN=p0RR91
114
115
literal 0
116
HcmV?d00001
117
118
diff --git a/tests/data/acpi/virt/IORT.memhp b/tests/data/acpi/virt/IORT.memhp
119
index XXXXXXX..XXXXXXX 100644
120
GIT binary patch
121
literal 124
122
zcmebD4+^Pa00MR=e`k+i1*eDrX9XZ&1PX!JAesq?4S*O7Bw!2(4Uz`|CKCt^;wu0#
123
QRGb+i3L*dhhtM#y0PN=p0RR91
124
125
literal 0
126
HcmV?d00001
127
128
diff --git a/tests/data/acpi/virt/IORT.numamem b/tests/data/acpi/virt/IORT.numamem
129
index XXXXXXX..XXXXXXX 100644
130
GIT binary patch
131
literal 124
132
zcmebD4+^Pa00MR=e`k+i1*eDrX9XZ&1PX!JAesq?4S*O7Bw!2(4Uz`|CKCt^;wu0#
133
QRGb+i3L*dhhtM#y0PN=p0RR91
134
135
literal 0
136
HcmV?d00001
137
138
diff --git a/tests/data/acpi/virt/IORT.pxb b/tests/data/acpi/virt/IORT.pxb
139
index XXXXXXX..XXXXXXX 100644
140
GIT binary patch
141
literal 124
142
zcmebD4+^Pa00MR=e`k+i1*eDrX9XZ&1PX!JAesq?4S*O7Bw!2(4Uz`|CKCt^;wu0#
143
QRGb+i3L*dhhtM#y0PN=p0RR91
144
145
literal 0
146
HcmV?d00001
147
148
--
149
2.20.1
150
151
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
It is confusing to have different exits from translation
3
Move the code to a separate file so that we do not have to compile
4
for various conditions in separate functions.
4
it anymore if CONFIG_ARM_V7M is not set.
5
5
6
Merge disas_a64_insn into its only caller. Standardize
6
Signed-off-by: Thomas Huth <thuth@redhat.com>
7
on the "s" name for the DisasContext, as the code from
7
Message-id: 20240308141051.536599-2-thuth@redhat.com
8
disas_a64_insn had more instances.
9
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210821195958.41312-3-richard.henderson@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
10
---
15
target/arm/translate-a64.c | 224 ++++++++++++++++++-------------------
11
target/arm/tcg/cpu-v7m.c | 290 +++++++++++++++++++++++++++++++++++++
16
1 file changed, 109 insertions(+), 115 deletions(-)
12
target/arm/tcg/cpu32.c | 261 ---------------------------------
13
target/arm/meson.build | 3 +
14
target/arm/tcg/meson.build | 3 +
15
4 files changed, 296 insertions(+), 261 deletions(-)
16
create mode 100644 target/arm/tcg/cpu-v7m.c
17
17
18
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
18
diff --git a/target/arm/tcg/cpu-v7m.c b/target/arm/tcg/cpu-v7m.c
19
new file mode 100644
20
index XXXXXXX..XXXXXXX
21
--- /dev/null
22
+++ b/target/arm/tcg/cpu-v7m.c
23
@@ -XXX,XX +XXX,XX @@
24
+/*
25
+ * QEMU ARMv7-M TCG-only CPUs.
26
+ *
27
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
28
+ *
29
+ * This code is licensed under the GNU GPL v2 or later.
30
+ *
31
+ * SPDX-License-Identifier: GPL-2.0-or-later
32
+ */
33
+
34
+#include "qemu/osdep.h"
35
+#include "cpu.h"
36
+#include "hw/core/tcg-cpu-ops.h"
37
+#include "internals.h"
38
+
39
+#if !defined(CONFIG_USER_ONLY)
40
+
41
+#include "hw/intc/armv7m_nvic.h"
42
+
43
+static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
44
+{
45
+ CPUClass *cc = CPU_GET_CLASS(cs);
46
+ ARMCPU *cpu = ARM_CPU(cs);
47
+ CPUARMState *env = &cpu->env;
48
+ bool ret = false;
49
+
50
+ /*
51
+ * ARMv7-M interrupt masking works differently than -A or -R.
52
+ * There is no FIQ/IRQ distinction. Instead of I and F bits
53
+ * masking FIQ and IRQ interrupts, an exception is taken only
54
+ * if it is higher priority than the current execution priority
55
+ * (which depends on state like BASEPRI, FAULTMASK and the
56
+ * currently active exception).
57
+ */
58
+ if (interrupt_request & CPU_INTERRUPT_HARD
59
+ && (armv7m_nvic_can_take_pending_exception(env->nvic))) {
60
+ cs->exception_index = EXCP_IRQ;
61
+ cc->tcg_ops->do_interrupt(cs);
62
+ ret = true;
63
+ }
64
+ return ret;
65
+}
66
+
67
+#endif /* !CONFIG_USER_ONLY */
68
+
69
+static void cortex_m0_initfn(Object *obj)
70
+{
71
+ ARMCPU *cpu = ARM_CPU(obj);
72
+ set_feature(&cpu->env, ARM_FEATURE_V6);
73
+ set_feature(&cpu->env, ARM_FEATURE_M);
74
+
75
+ cpu->midr = 0x410cc200;
76
+
77
+ /*
78
+ * These ID register values are not guest visible, because
79
+ * we do not implement the Main Extension. They must be set
80
+ * to values corresponding to the Cortex-M0's implemented
81
+ * features, because QEMU generally controls its emulation
82
+ * by looking at ID register fields. We use the same values as
83
+ * for the M3.
84
+ */
85
+ cpu->isar.id_pfr0 = 0x00000030;
86
+ cpu->isar.id_pfr1 = 0x00000200;
87
+ cpu->isar.id_dfr0 = 0x00100000;
88
+ cpu->id_afr0 = 0x00000000;
89
+ cpu->isar.id_mmfr0 = 0x00000030;
90
+ cpu->isar.id_mmfr1 = 0x00000000;
91
+ cpu->isar.id_mmfr2 = 0x00000000;
92
+ cpu->isar.id_mmfr3 = 0x00000000;
93
+ cpu->isar.id_isar0 = 0x01141110;
94
+ cpu->isar.id_isar1 = 0x02111000;
95
+ cpu->isar.id_isar2 = 0x21112231;
96
+ cpu->isar.id_isar3 = 0x01111110;
97
+ cpu->isar.id_isar4 = 0x01310102;
98
+ cpu->isar.id_isar5 = 0x00000000;
99
+ cpu->isar.id_isar6 = 0x00000000;
100
+}
101
+
102
+static void cortex_m3_initfn(Object *obj)
103
+{
104
+ ARMCPU *cpu = ARM_CPU(obj);
105
+ set_feature(&cpu->env, ARM_FEATURE_V7);
106
+ set_feature(&cpu->env, ARM_FEATURE_M);
107
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
108
+ cpu->midr = 0x410fc231;
109
+ cpu->pmsav7_dregion = 8;
110
+ cpu->isar.id_pfr0 = 0x00000030;
111
+ cpu->isar.id_pfr1 = 0x00000200;
112
+ cpu->isar.id_dfr0 = 0x00100000;
113
+ cpu->id_afr0 = 0x00000000;
114
+ cpu->isar.id_mmfr0 = 0x00000030;
115
+ cpu->isar.id_mmfr1 = 0x00000000;
116
+ cpu->isar.id_mmfr2 = 0x00000000;
117
+ cpu->isar.id_mmfr3 = 0x00000000;
118
+ cpu->isar.id_isar0 = 0x01141110;
119
+ cpu->isar.id_isar1 = 0x02111000;
120
+ cpu->isar.id_isar2 = 0x21112231;
121
+ cpu->isar.id_isar3 = 0x01111110;
122
+ cpu->isar.id_isar4 = 0x01310102;
123
+ cpu->isar.id_isar5 = 0x00000000;
124
+ cpu->isar.id_isar6 = 0x00000000;
125
+}
126
+
127
+static void cortex_m4_initfn(Object *obj)
128
+{
129
+ ARMCPU *cpu = ARM_CPU(obj);
130
+
131
+ set_feature(&cpu->env, ARM_FEATURE_V7);
132
+ set_feature(&cpu->env, ARM_FEATURE_M);
133
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
134
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
135
+ cpu->midr = 0x410fc240; /* r0p0 */
136
+ cpu->pmsav7_dregion = 8;
137
+ cpu->isar.mvfr0 = 0x10110021;
138
+ cpu->isar.mvfr1 = 0x11000011;
139
+ cpu->isar.mvfr2 = 0x00000000;
140
+ cpu->isar.id_pfr0 = 0x00000030;
141
+ cpu->isar.id_pfr1 = 0x00000200;
142
+ cpu->isar.id_dfr0 = 0x00100000;
143
+ cpu->id_afr0 = 0x00000000;
144
+ cpu->isar.id_mmfr0 = 0x00000030;
145
+ cpu->isar.id_mmfr1 = 0x00000000;
146
+ cpu->isar.id_mmfr2 = 0x00000000;
147
+ cpu->isar.id_mmfr3 = 0x00000000;
148
+ cpu->isar.id_isar0 = 0x01141110;
149
+ cpu->isar.id_isar1 = 0x02111000;
150
+ cpu->isar.id_isar2 = 0x21112231;
151
+ cpu->isar.id_isar3 = 0x01111110;
152
+ cpu->isar.id_isar4 = 0x01310102;
153
+ cpu->isar.id_isar5 = 0x00000000;
154
+ cpu->isar.id_isar6 = 0x00000000;
155
+}
156
+
157
+static void cortex_m7_initfn(Object *obj)
158
+{
159
+ ARMCPU *cpu = ARM_CPU(obj);
160
+
161
+ set_feature(&cpu->env, ARM_FEATURE_V7);
162
+ set_feature(&cpu->env, ARM_FEATURE_M);
163
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
164
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
165
+ cpu->midr = 0x411fc272; /* r1p2 */
166
+ cpu->pmsav7_dregion = 8;
167
+ cpu->isar.mvfr0 = 0x10110221;
168
+ cpu->isar.mvfr1 = 0x12000011;
169
+ cpu->isar.mvfr2 = 0x00000040;
170
+ cpu->isar.id_pfr0 = 0x00000030;
171
+ cpu->isar.id_pfr1 = 0x00000200;
172
+ cpu->isar.id_dfr0 = 0x00100000;
173
+ cpu->id_afr0 = 0x00000000;
174
+ cpu->isar.id_mmfr0 = 0x00100030;
175
+ cpu->isar.id_mmfr1 = 0x00000000;
176
+ cpu->isar.id_mmfr2 = 0x01000000;
177
+ cpu->isar.id_mmfr3 = 0x00000000;
178
+ cpu->isar.id_isar0 = 0x01101110;
179
+ cpu->isar.id_isar1 = 0x02112000;
180
+ cpu->isar.id_isar2 = 0x20232231;
181
+ cpu->isar.id_isar3 = 0x01111131;
182
+ cpu->isar.id_isar4 = 0x01310132;
183
+ cpu->isar.id_isar5 = 0x00000000;
184
+ cpu->isar.id_isar6 = 0x00000000;
185
+}
186
+
187
+static void cortex_m33_initfn(Object *obj)
188
+{
189
+ ARMCPU *cpu = ARM_CPU(obj);
190
+
191
+ set_feature(&cpu->env, ARM_FEATURE_V8);
192
+ set_feature(&cpu->env, ARM_FEATURE_M);
193
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
194
+ set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
195
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
196
+ cpu->midr = 0x410fd213; /* r0p3 */
197
+ cpu->pmsav7_dregion = 16;
198
+ cpu->sau_sregion = 8;
199
+ cpu->isar.mvfr0 = 0x10110021;
200
+ cpu->isar.mvfr1 = 0x11000011;
201
+ cpu->isar.mvfr2 = 0x00000040;
202
+ cpu->isar.id_pfr0 = 0x00000030;
203
+ cpu->isar.id_pfr1 = 0x00000210;
204
+ cpu->isar.id_dfr0 = 0x00200000;
205
+ cpu->id_afr0 = 0x00000000;
206
+ cpu->isar.id_mmfr0 = 0x00101F40;
207
+ cpu->isar.id_mmfr1 = 0x00000000;
208
+ cpu->isar.id_mmfr2 = 0x01000000;
209
+ cpu->isar.id_mmfr3 = 0x00000000;
210
+ cpu->isar.id_isar0 = 0x01101110;
211
+ cpu->isar.id_isar1 = 0x02212000;
212
+ cpu->isar.id_isar2 = 0x20232232;
213
+ cpu->isar.id_isar3 = 0x01111131;
214
+ cpu->isar.id_isar4 = 0x01310132;
215
+ cpu->isar.id_isar5 = 0x00000000;
216
+ cpu->isar.id_isar6 = 0x00000000;
217
+ cpu->clidr = 0x00000000;
218
+ cpu->ctr = 0x8000c000;
219
+}
220
+
221
+static void cortex_m55_initfn(Object *obj)
222
+{
223
+ ARMCPU *cpu = ARM_CPU(obj);
224
+
225
+ set_feature(&cpu->env, ARM_FEATURE_V8);
226
+ set_feature(&cpu->env, ARM_FEATURE_V8_1M);
227
+ set_feature(&cpu->env, ARM_FEATURE_M);
228
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
229
+ set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
230
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
231
+ cpu->midr = 0x410fd221; /* r0p1 */
232
+ cpu->revidr = 0;
233
+ cpu->pmsav7_dregion = 16;
234
+ cpu->sau_sregion = 8;
235
+ /* These are the MVFR* values for the FPU + full MVE configuration */
236
+ cpu->isar.mvfr0 = 0x10110221;
237
+ cpu->isar.mvfr1 = 0x12100211;
238
+ cpu->isar.mvfr2 = 0x00000040;
239
+ cpu->isar.id_pfr0 = 0x20000030;
240
+ cpu->isar.id_pfr1 = 0x00000230;
241
+ cpu->isar.id_dfr0 = 0x10200000;
242
+ cpu->id_afr0 = 0x00000000;
243
+ cpu->isar.id_mmfr0 = 0x00111040;
244
+ cpu->isar.id_mmfr1 = 0x00000000;
245
+ cpu->isar.id_mmfr2 = 0x01000000;
246
+ cpu->isar.id_mmfr3 = 0x00000011;
247
+ cpu->isar.id_isar0 = 0x01103110;
248
+ cpu->isar.id_isar1 = 0x02212000;
249
+ cpu->isar.id_isar2 = 0x20232232;
250
+ cpu->isar.id_isar3 = 0x01111131;
251
+ cpu->isar.id_isar4 = 0x01310132;
252
+ cpu->isar.id_isar5 = 0x00000000;
253
+ cpu->isar.id_isar6 = 0x00000000;
254
+ cpu->clidr = 0x00000000; /* caches not implemented */
255
+ cpu->ctr = 0x8303c003;
256
+}
257
+
258
+static const TCGCPUOps arm_v7m_tcg_ops = {
259
+ .initialize = arm_translate_init,
260
+ .synchronize_from_tb = arm_cpu_synchronize_from_tb,
261
+ .debug_excp_handler = arm_debug_excp_handler,
262
+ .restore_state_to_opc = arm_restore_state_to_opc,
263
+
264
+#ifdef CONFIG_USER_ONLY
265
+ .record_sigsegv = arm_cpu_record_sigsegv,
266
+ .record_sigbus = arm_cpu_record_sigbus,
267
+#else
268
+ .tlb_fill = arm_cpu_tlb_fill,
269
+ .cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
270
+ .do_interrupt = arm_v7m_cpu_do_interrupt,
271
+ .do_transaction_failed = arm_cpu_do_transaction_failed,
272
+ .do_unaligned_access = arm_cpu_do_unaligned_access,
273
+ .adjust_watchpoint_address = arm_adjust_watchpoint_address,
274
+ .debug_check_watchpoint = arm_debug_check_watchpoint,
275
+ .debug_check_breakpoint = arm_debug_check_breakpoint,
276
+#endif /* !CONFIG_USER_ONLY */
277
+};
278
+
279
+static void arm_v7m_class_init(ObjectClass *oc, void *data)
280
+{
281
+ ARMCPUClass *acc = ARM_CPU_CLASS(oc);
282
+ CPUClass *cc = CPU_CLASS(oc);
283
+
284
+ acc->info = data;
285
+ cc->tcg_ops = &arm_v7m_tcg_ops;
286
+ cc->gdb_core_xml_file = "arm-m-profile.xml";
287
+}
288
+
289
+static const ARMCPUInfo arm_v7m_cpus[] = {
290
+ { .name = "cortex-m0", .initfn = cortex_m0_initfn,
291
+ .class_init = arm_v7m_class_init },
292
+ { .name = "cortex-m3", .initfn = cortex_m3_initfn,
293
+ .class_init = arm_v7m_class_init },
294
+ { .name = "cortex-m4", .initfn = cortex_m4_initfn,
295
+ .class_init = arm_v7m_class_init },
296
+ { .name = "cortex-m7", .initfn = cortex_m7_initfn,
297
+ .class_init = arm_v7m_class_init },
298
+ { .name = "cortex-m33", .initfn = cortex_m33_initfn,
299
+ .class_init = arm_v7m_class_init },
300
+ { .name = "cortex-m55", .initfn = cortex_m55_initfn,
301
+ .class_init = arm_v7m_class_init },
302
+};
303
+
304
+static void arm_v7m_cpu_register_types(void)
305
+{
306
+ size_t i;
307
+
308
+ for (i = 0; i < ARRAY_SIZE(arm_v7m_cpus); ++i) {
309
+ arm_cpu_register(&arm_v7m_cpus[i]);
310
+ }
311
+}
312
+
313
+type_init(arm_v7m_cpu_register_types)
314
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
19
index XXXXXXX..XXXXXXX 100644
315
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/translate-a64.c
316
--- a/target/arm/tcg/cpu32.c
21
+++ b/target/arm/translate-a64.c
317
+++ b/target/arm/tcg/cpu32.c
22
@@ -XXX,XX +XXX,XX @@ static bool btype_destination_ok(uint32_t insn, bool bt, int btype)
318
@@ -XXX,XX +XXX,XX @@
23
return false;
319
#include "hw/boards.h"
320
#endif
321
#include "cpregs.h"
322
-#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG)
323
-#include "hw/intc/armv7m_nvic.h"
324
-#endif
325
326
327
/* Share AArch32 -cpu max features with AArch64. */
328
@@ -XXX,XX +XXX,XX @@ void aa32_max_features(ARMCPU *cpu)
329
/* CPU models. These are not needed for the AArch64 linux-user build. */
330
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
331
332
-#if !defined(CONFIG_USER_ONLY)
333
-static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
334
-{
335
- CPUClass *cc = CPU_GET_CLASS(cs);
336
- ARMCPU *cpu = ARM_CPU(cs);
337
- CPUARMState *env = &cpu->env;
338
- bool ret = false;
339
-
340
- /*
341
- * ARMv7-M interrupt masking works differently than -A or -R.
342
- * There is no FIQ/IRQ distinction. Instead of I and F bits
343
- * masking FIQ and IRQ interrupts, an exception is taken only
344
- * if it is higher priority than the current execution priority
345
- * (which depends on state like BASEPRI, FAULTMASK and the
346
- * currently active exception).
347
- */
348
- if (interrupt_request & CPU_INTERRUPT_HARD
349
- && (armv7m_nvic_can_take_pending_exception(env->nvic))) {
350
- cs->exception_index = EXCP_IRQ;
351
- cc->tcg_ops->do_interrupt(cs);
352
- ret = true;
353
- }
354
- return ret;
355
-}
356
-#endif /* !CONFIG_USER_ONLY */
357
-
358
static void arm926_initfn(Object *obj)
359
{
360
ARMCPU *cpu = ARM_CPU(obj);
361
@@ -XXX,XX +XXX,XX @@ static void cortex_a15_initfn(Object *obj)
362
define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
24
}
363
}
25
364
26
-/* C3.1 A64 instruction index by encoding */
365
-static void cortex_m0_initfn(Object *obj)
27
-static void disas_a64_insn(CPUARMState *env, DisasContext *s)
366
-{
28
-{
367
- ARMCPU *cpu = ARM_CPU(obj);
29
- uint32_t insn;
368
- set_feature(&cpu->env, ARM_FEATURE_V6);
30
-
369
- set_feature(&cpu->env, ARM_FEATURE_M);
31
- s->pc_curr = s->base.pc_next;
370
-
32
- insn = arm_ldl_code(env, s->base.pc_next, s->sctlr_b);
371
- cpu->midr = 0x410cc200;
33
- s->insn = insn;
34
- s->base.pc_next += 4;
35
-
36
- s->fp_access_checked = false;
37
- s->sve_access_checked = false;
38
-
39
- if (s->pstate_il) {
40
- /*
41
- * Illegal execution state. This has priority over BTI
42
- * exceptions, but comes after instruction abort exceptions.
43
- */
44
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
45
- syn_illegalstate(), default_exception_el(s));
46
- return;
47
- }
48
-
49
- if (dc_isar_feature(aa64_bti, s)) {
50
- if (s->base.num_insns == 1) {
51
- /*
52
- * At the first insn of the TB, compute s->guarded_page.
53
- * We delayed computing this until successfully reading
54
- * the first insn of the TB, above. This (mostly) ensures
55
- * that the softmmu tlb entry has been populated, and the
56
- * page table GP bit is available.
57
- *
58
- * Note that we need to compute this even if btype == 0,
59
- * because this value is used for BR instructions later
60
- * where ENV is not available.
61
- */
62
- s->guarded_page = is_guarded_page(env, s);
63
-
64
- /* First insn can have btype set to non-zero. */
65
- tcg_debug_assert(s->btype >= 0);
66
-
67
- /*
68
- * Note that the Branch Target Exception has fairly high
69
- * priority -- below debugging exceptions but above most
70
- * everything else. This allows us to handle this now
71
- * instead of waiting until the insn is otherwise decoded.
72
- */
73
- if (s->btype != 0
74
- && s->guarded_page
75
- && !btype_destination_ok(insn, s->bt, s->btype)) {
76
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
77
- syn_btitrap(s->btype),
78
- default_exception_el(s));
79
- return;
80
- }
81
- } else {
82
- /* Not the first insn: btype must be 0. */
83
- tcg_debug_assert(s->btype == 0);
84
- }
85
- }
86
-
87
- switch (extract32(insn, 25, 4)) {
88
- case 0x0: case 0x1: case 0x3: /* UNALLOCATED */
89
- unallocated_encoding(s);
90
- break;
91
- case 0x2:
92
- if (!dc_isar_feature(aa64_sve, s) || !disas_sve(s, insn)) {
93
- unallocated_encoding(s);
94
- }
95
- break;
96
- case 0x8: case 0x9: /* Data processing - immediate */
97
- disas_data_proc_imm(s, insn);
98
- break;
99
- case 0xa: case 0xb: /* Branch, exception generation and system insns */
100
- disas_b_exc_sys(s, insn);
101
- break;
102
- case 0x4:
103
- case 0x6:
104
- case 0xc:
105
- case 0xe: /* Loads and stores */
106
- disas_ldst(s, insn);
107
- break;
108
- case 0x5:
109
- case 0xd: /* Data processing - register */
110
- disas_data_proc_reg(s, insn);
111
- break;
112
- case 0x7:
113
- case 0xf: /* Data processing - SIMD and floating point */
114
- disas_data_proc_simd_fp(s, insn);
115
- break;
116
- default:
117
- assert(FALSE); /* all 15 cases should be handled above */
118
- break;
119
- }
120
-
121
- /* if we allocated any temporaries, free them here */
122
- free_tmp_a64(s);
123
-
372
-
124
- /*
373
- /*
125
- * After execution of most insns, btype is reset to 0.
374
- * These ID register values are not guest visible, because
126
- * Note that we set btype == -1 when the insn sets btype.
375
- * we do not implement the Main Extension. They must be set
376
- * to values corresponding to the Cortex-M0's implemented
377
- * features, because QEMU generally controls its emulation
378
- * by looking at ID register fields. We use the same values as
379
- * for the M3.
127
- */
380
- */
128
- if (s->btype > 0 && s->base.is_jmp != DISAS_NORETURN) {
381
- cpu->isar.id_pfr0 = 0x00000030;
129
- reset_btype(s);
382
- cpu->isar.id_pfr1 = 0x00000200;
130
- }
383
- cpu->isar.id_dfr0 = 0x00100000;
131
-}
384
- cpu->id_afr0 = 0x00000000;
132
-
385
- cpu->isar.id_mmfr0 = 0x00000030;
133
static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
386
- cpu->isar.id_mmfr1 = 0x00000000;
134
CPUState *cpu)
387
- cpu->isar.id_mmfr2 = 0x00000000;
135
{
388
- cpu->isar.id_mmfr3 = 0x00000000;
136
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
389
- cpu->isar.id_isar0 = 0x01141110;
137
390
- cpu->isar.id_isar1 = 0x02111000;
138
static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
391
- cpu->isar.id_isar2 = 0x21112231;
139
{
392
- cpu->isar.id_isar3 = 0x01111110;
140
- DisasContext *dc = container_of(dcbase, DisasContext, base);
393
- cpu->isar.id_isar4 = 0x01310102;
141
+ DisasContext *s = container_of(dcbase, DisasContext, base);
394
- cpu->isar.id_isar5 = 0x00000000;
142
CPUARMState *env = cpu->env_ptr;
395
- cpu->isar.id_isar6 = 0x00000000;
143
+ uint32_t insn;
396
-}
144
397
-
145
- if (dc->ss_active && !dc->pstate_ss) {
398
-static void cortex_m3_initfn(Object *obj)
146
+ if (s->ss_active && !s->pstate_ss) {
399
-{
147
/* Singlestep state is Active-pending.
400
- ARMCPU *cpu = ARM_CPU(obj);
148
* If we're in this state at the start of a TB then either
401
- set_feature(&cpu->env, ARM_FEATURE_V7);
149
* a) we just took an exception to an EL which is being debugged
402
- set_feature(&cpu->env, ARM_FEATURE_M);
150
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
403
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
151
* "did not step an insn" case, and so the syndrome ISV and EX
404
- cpu->midr = 0x410fc231;
152
* bits should be zero.
405
- cpu->pmsav7_dregion = 8;
153
*/
406
- cpu->isar.id_pfr0 = 0x00000030;
154
- assert(dc->base.num_insns == 1);
407
- cpu->isar.id_pfr1 = 0x00000200;
155
- gen_swstep_exception(dc, 0, 0);
408
- cpu->isar.id_dfr0 = 0x00100000;
156
- dc->base.is_jmp = DISAS_NORETURN;
409
- cpu->id_afr0 = 0x00000000;
157
- } else {
410
- cpu->isar.id_mmfr0 = 0x00000030;
158
- disas_a64_insn(env, dc);
411
- cpu->isar.id_mmfr1 = 0x00000000;
159
+ assert(s->base.num_insns == 1);
412
- cpu->isar.id_mmfr2 = 0x00000000;
160
+ gen_swstep_exception(s, 0, 0);
413
- cpu->isar.id_mmfr3 = 0x00000000;
161
+ s->base.is_jmp = DISAS_NORETURN;
414
- cpu->isar.id_isar0 = 0x01141110;
162
+ return;
415
- cpu->isar.id_isar1 = 0x02111000;
163
}
416
- cpu->isar.id_isar2 = 0x21112231;
164
417
- cpu->isar.id_isar3 = 0x01111110;
165
- translator_loop_temp_check(&dc->base);
418
- cpu->isar.id_isar4 = 0x01310102;
166
+ s->pc_curr = s->base.pc_next;
419
- cpu->isar.id_isar5 = 0x00000000;
167
+ insn = arm_ldl_code(env, s->base.pc_next, s->sctlr_b);
420
- cpu->isar.id_isar6 = 0x00000000;
168
+ s->insn = insn;
421
-}
169
+ s->base.pc_next += 4;
422
-
170
+
423
-static void cortex_m4_initfn(Object *obj)
171
+ s->fp_access_checked = false;
424
-{
172
+ s->sve_access_checked = false;
425
- ARMCPU *cpu = ARM_CPU(obj);
173
+
426
-
174
+ if (s->pstate_il) {
427
- set_feature(&cpu->env, ARM_FEATURE_V7);
175
+ /*
428
- set_feature(&cpu->env, ARM_FEATURE_M);
176
+ * Illegal execution state. This has priority over BTI
429
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
177
+ * exceptions, but comes after instruction abort exceptions.
430
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
178
+ */
431
- cpu->midr = 0x410fc240; /* r0p0 */
179
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
432
- cpu->pmsav7_dregion = 8;
180
+ syn_illegalstate(), default_exception_el(s));
433
- cpu->isar.mvfr0 = 0x10110021;
181
+ return;
434
- cpu->isar.mvfr1 = 0x11000011;
182
+ }
435
- cpu->isar.mvfr2 = 0x00000000;
183
+
436
- cpu->isar.id_pfr0 = 0x00000030;
184
+ if (dc_isar_feature(aa64_bti, s)) {
437
- cpu->isar.id_pfr1 = 0x00000200;
185
+ if (s->base.num_insns == 1) {
438
- cpu->isar.id_dfr0 = 0x00100000;
186
+ /*
439
- cpu->id_afr0 = 0x00000000;
187
+ * At the first insn of the TB, compute s->guarded_page.
440
- cpu->isar.id_mmfr0 = 0x00000030;
188
+ * We delayed computing this until successfully reading
441
- cpu->isar.id_mmfr1 = 0x00000000;
189
+ * the first insn of the TB, above. This (mostly) ensures
442
- cpu->isar.id_mmfr2 = 0x00000000;
190
+ * that the softmmu tlb entry has been populated, and the
443
- cpu->isar.id_mmfr3 = 0x00000000;
191
+ * page table GP bit is available.
444
- cpu->isar.id_isar0 = 0x01141110;
192
+ *
445
- cpu->isar.id_isar1 = 0x02111000;
193
+ * Note that we need to compute this even if btype == 0,
446
- cpu->isar.id_isar2 = 0x21112231;
194
+ * because this value is used for BR instructions later
447
- cpu->isar.id_isar3 = 0x01111110;
195
+ * where ENV is not available.
448
- cpu->isar.id_isar4 = 0x01310102;
196
+ */
449
- cpu->isar.id_isar5 = 0x00000000;
197
+ s->guarded_page = is_guarded_page(env, s);
450
- cpu->isar.id_isar6 = 0x00000000;
198
+
451
-}
199
+ /* First insn can have btype set to non-zero. */
452
-
200
+ tcg_debug_assert(s->btype >= 0);
453
-static void cortex_m7_initfn(Object *obj)
201
+
454
-{
202
+ /*
455
- ARMCPU *cpu = ARM_CPU(obj);
203
+ * Note that the Branch Target Exception has fairly high
456
-
204
+ * priority -- below debugging exceptions but above most
457
- set_feature(&cpu->env, ARM_FEATURE_V7);
205
+ * everything else. This allows us to handle this now
458
- set_feature(&cpu->env, ARM_FEATURE_M);
206
+ * instead of waiting until the insn is otherwise decoded.
459
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
207
+ */
460
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
208
+ if (s->btype != 0
461
- cpu->midr = 0x411fc272; /* r1p2 */
209
+ && s->guarded_page
462
- cpu->pmsav7_dregion = 8;
210
+ && !btype_destination_ok(insn, s->bt, s->btype)) {
463
- cpu->isar.mvfr0 = 0x10110221;
211
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
464
- cpu->isar.mvfr1 = 0x12000011;
212
+ syn_btitrap(s->btype),
465
- cpu->isar.mvfr2 = 0x00000040;
213
+ default_exception_el(s));
466
- cpu->isar.id_pfr0 = 0x00000030;
214
+ return;
467
- cpu->isar.id_pfr1 = 0x00000200;
215
+ }
468
- cpu->isar.id_dfr0 = 0x00100000;
216
+ } else {
469
- cpu->id_afr0 = 0x00000000;
217
+ /* Not the first insn: btype must be 0. */
470
- cpu->isar.id_mmfr0 = 0x00100030;
218
+ tcg_debug_assert(s->btype == 0);
471
- cpu->isar.id_mmfr1 = 0x00000000;
219
+ }
472
- cpu->isar.id_mmfr2 = 0x01000000;
220
+ }
473
- cpu->isar.id_mmfr3 = 0x00000000;
221
+
474
- cpu->isar.id_isar0 = 0x01101110;
222
+ switch (extract32(insn, 25, 4)) {
475
- cpu->isar.id_isar1 = 0x02112000;
223
+ case 0x0: case 0x1: case 0x3: /* UNALLOCATED */
476
- cpu->isar.id_isar2 = 0x20232231;
224
+ unallocated_encoding(s);
477
- cpu->isar.id_isar3 = 0x01111131;
225
+ break;
478
- cpu->isar.id_isar4 = 0x01310132;
226
+ case 0x2:
479
- cpu->isar.id_isar5 = 0x00000000;
227
+ if (!dc_isar_feature(aa64_sve, s) || !disas_sve(s, insn)) {
480
- cpu->isar.id_isar6 = 0x00000000;
228
+ unallocated_encoding(s);
481
-}
229
+ }
482
-
230
+ break;
483
-static void cortex_m33_initfn(Object *obj)
231
+ case 0x8: case 0x9: /* Data processing - immediate */
484
-{
232
+ disas_data_proc_imm(s, insn);
485
- ARMCPU *cpu = ARM_CPU(obj);
233
+ break;
486
-
234
+ case 0xa: case 0xb: /* Branch, exception generation and system insns */
487
- set_feature(&cpu->env, ARM_FEATURE_V8);
235
+ disas_b_exc_sys(s, insn);
488
- set_feature(&cpu->env, ARM_FEATURE_M);
236
+ break;
489
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
237
+ case 0x4:
490
- set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
238
+ case 0x6:
491
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
239
+ case 0xc:
492
- cpu->midr = 0x410fd213; /* r0p3 */
240
+ case 0xe: /* Loads and stores */
493
- cpu->pmsav7_dregion = 16;
241
+ disas_ldst(s, insn);
494
- cpu->sau_sregion = 8;
242
+ break;
495
- cpu->isar.mvfr0 = 0x10110021;
243
+ case 0x5:
496
- cpu->isar.mvfr1 = 0x11000011;
244
+ case 0xd: /* Data processing - register */
497
- cpu->isar.mvfr2 = 0x00000040;
245
+ disas_data_proc_reg(s, insn);
498
- cpu->isar.id_pfr0 = 0x00000030;
246
+ break;
499
- cpu->isar.id_pfr1 = 0x00000210;
247
+ case 0x7:
500
- cpu->isar.id_dfr0 = 0x00200000;
248
+ case 0xf: /* Data processing - SIMD and floating point */
501
- cpu->id_afr0 = 0x00000000;
249
+ disas_data_proc_simd_fp(s, insn);
502
- cpu->isar.id_mmfr0 = 0x00101F40;
250
+ break;
503
- cpu->isar.id_mmfr1 = 0x00000000;
251
+ default:
504
- cpu->isar.id_mmfr2 = 0x01000000;
252
+ assert(FALSE); /* all 15 cases should be handled above */
505
- cpu->isar.id_mmfr3 = 0x00000000;
253
+ break;
506
- cpu->isar.id_isar0 = 0x01101110;
254
+ }
507
- cpu->isar.id_isar1 = 0x02212000;
255
+
508
- cpu->isar.id_isar2 = 0x20232232;
256
+ /* if we allocated any temporaries, free them here */
509
- cpu->isar.id_isar3 = 0x01111131;
257
+ free_tmp_a64(s);
510
- cpu->isar.id_isar4 = 0x01310132;
258
+
511
- cpu->isar.id_isar5 = 0x00000000;
259
+ /*
512
- cpu->isar.id_isar6 = 0x00000000;
260
+ * After execution of most insns, btype is reset to 0.
513
- cpu->clidr = 0x00000000;
261
+ * Note that we set btype == -1 when the insn sets btype.
514
- cpu->ctr = 0x8000c000;
262
+ */
515
-}
263
+ if (s->btype > 0 && s->base.is_jmp != DISAS_NORETURN) {
516
-
264
+ reset_btype(s);
517
-static void cortex_m55_initfn(Object *obj)
265
+ }
518
-{
266
+
519
- ARMCPU *cpu = ARM_CPU(obj);
267
+ translator_loop_temp_check(&s->base);
520
-
521
- set_feature(&cpu->env, ARM_FEATURE_V8);
522
- set_feature(&cpu->env, ARM_FEATURE_V8_1M);
523
- set_feature(&cpu->env, ARM_FEATURE_M);
524
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
525
- set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
526
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
527
- cpu->midr = 0x410fd221; /* r0p1 */
528
- cpu->revidr = 0;
529
- cpu->pmsav7_dregion = 16;
530
- cpu->sau_sregion = 8;
531
- /* These are the MVFR* values for the FPU + full MVE configuration */
532
- cpu->isar.mvfr0 = 0x10110221;
533
- cpu->isar.mvfr1 = 0x12100211;
534
- cpu->isar.mvfr2 = 0x00000040;
535
- cpu->isar.id_pfr0 = 0x20000030;
536
- cpu->isar.id_pfr1 = 0x00000230;
537
- cpu->isar.id_dfr0 = 0x10200000;
538
- cpu->id_afr0 = 0x00000000;
539
- cpu->isar.id_mmfr0 = 0x00111040;
540
- cpu->isar.id_mmfr1 = 0x00000000;
541
- cpu->isar.id_mmfr2 = 0x01000000;
542
- cpu->isar.id_mmfr3 = 0x00000011;
543
- cpu->isar.id_isar0 = 0x01103110;
544
- cpu->isar.id_isar1 = 0x02212000;
545
- cpu->isar.id_isar2 = 0x20232232;
546
- cpu->isar.id_isar3 = 0x01111131;
547
- cpu->isar.id_isar4 = 0x01310132;
548
- cpu->isar.id_isar5 = 0x00000000;
549
- cpu->isar.id_isar6 = 0x00000000;
550
- cpu->clidr = 0x00000000; /* caches not implemented */
551
- cpu->ctr = 0x8303c003;
552
-}
553
-
554
static const ARMCPRegInfo cortexr5_cp_reginfo[] = {
555
/* Dummy the TCM region regs for the moment */
556
{ .name = "ATCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 0,
557
@@ -XXX,XX +XXX,XX @@ static void pxa270c5_initfn(Object *obj)
558
cpu->reset_sctlr = 0x00000078;
268
}
559
}
269
560
270
static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
561
-static const TCGCPUOps arm_v7m_tcg_ops = {
562
- .initialize = arm_translate_init,
563
- .synchronize_from_tb = arm_cpu_synchronize_from_tb,
564
- .debug_excp_handler = arm_debug_excp_handler,
565
- .restore_state_to_opc = arm_restore_state_to_opc,
566
-
567
-#ifdef CONFIG_USER_ONLY
568
- .record_sigsegv = arm_cpu_record_sigsegv,
569
- .record_sigbus = arm_cpu_record_sigbus,
570
-#else
571
- .tlb_fill = arm_cpu_tlb_fill,
572
- .cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
573
- .do_interrupt = arm_v7m_cpu_do_interrupt,
574
- .do_transaction_failed = arm_cpu_do_transaction_failed,
575
- .do_unaligned_access = arm_cpu_do_unaligned_access,
576
- .adjust_watchpoint_address = arm_adjust_watchpoint_address,
577
- .debug_check_watchpoint = arm_debug_check_watchpoint,
578
- .debug_check_breakpoint = arm_debug_check_breakpoint,
579
-#endif /* !CONFIG_USER_ONLY */
580
-};
581
-
582
-static void arm_v7m_class_init(ObjectClass *oc, void *data)
583
-{
584
- ARMCPUClass *acc = ARM_CPU_CLASS(oc);
585
- CPUClass *cc = CPU_CLASS(oc);
586
-
587
- acc->info = data;
588
- cc->tcg_ops = &arm_v7m_tcg_ops;
589
- cc->gdb_core_xml_file = "arm-m-profile.xml";
590
-}
591
-
592
#ifndef TARGET_AARCH64
593
/*
594
* -cpu max: a CPU with as many features enabled as our emulation supports.
595
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_tcg_cpus[] = {
596
{ .name = "cortex-a8", .initfn = cortex_a8_initfn },
597
{ .name = "cortex-a9", .initfn = cortex_a9_initfn },
598
{ .name = "cortex-a15", .initfn = cortex_a15_initfn },
599
- { .name = "cortex-m0", .initfn = cortex_m0_initfn,
600
- .class_init = arm_v7m_class_init },
601
- { .name = "cortex-m3", .initfn = cortex_m3_initfn,
602
- .class_init = arm_v7m_class_init },
603
- { .name = "cortex-m4", .initfn = cortex_m4_initfn,
604
- .class_init = arm_v7m_class_init },
605
- { .name = "cortex-m7", .initfn = cortex_m7_initfn,
606
- .class_init = arm_v7m_class_init },
607
- { .name = "cortex-m33", .initfn = cortex_m33_initfn,
608
- .class_init = arm_v7m_class_init },
609
- { .name = "cortex-m55", .initfn = cortex_m55_initfn,
610
- .class_init = arm_v7m_class_init },
611
{ .name = "cortex-r5", .initfn = cortex_r5_initfn },
612
{ .name = "cortex-r5f", .initfn = cortex_r5f_initfn },
613
{ .name = "cortex-r52", .initfn = cortex_r52_initfn },
614
diff --git a/target/arm/meson.build b/target/arm/meson.build
615
index XXXXXXX..XXXXXXX 100644
616
--- a/target/arm/meson.build
617
+++ b/target/arm/meson.build
618
@@ -XXX,XX +XXX,XX @@ arm_system_ss.add(files(
619
'ptw.c',
620
))
621
622
+arm_user_ss = ss.source_set()
623
+
624
subdir('hvf')
625
626
if 'CONFIG_TCG' in config_all_accel
627
@@ -XXX,XX +XXX,XX @@ endif
628
629
target_arch += {'arm': arm_ss}
630
target_system_arch += {'arm': arm_system_ss}
631
+target_user_arch += {'arm': arm_user_ss}
632
diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build
633
index XXXXXXX..XXXXXXX 100644
634
--- a/target/arm/tcg/meson.build
635
+++ b/target/arm/tcg/meson.build
636
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
637
arm_system_ss.add(files(
638
'psci.c',
639
))
640
+
641
+arm_system_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('cpu-v7m.c'))
642
+arm_user_ss.add(when: 'TARGET_AARCH64', if_false: files('cpu-v7m.c'))
271
--
643
--
272
2.20.1
644
2.34.1
273
274
diff view generated by jsdifflib