1
target-arm queue for rc1 -- these are all bug fixes.
1
The following changes since commit eae587e8e3694b1aceab23239493fb4c7e1a80f5:
2
2
3
thanks
3
Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2021-09-13' into staging (2021-09-13 11:00:30 +0100)
4
-- PMM
5
6
The following changes since commit b9404bf592e7ba74180e1a54ed7a266ec6ee67f2:
7
8
Merge remote-tracking branch 'remotes/dgilbert/tags/pull-hmp-20190715' into staging (2019-07-15 12:22:07 +0100)
9
4
10
are available in the Git repository at:
5
are available in the Git repository at:
11
6
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190715
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210913
13
8
14
for you to fetch changes up to 51c9122e92b776a3f16af0b9282f1dc5012e2a19:
9
for you to fetch changes up to 9a2b2ecf4d25a3943918c95d2db4508b304161b5:
15
10
16
target/arm: NS BusFault on vector table fetch escalates to NS HardFault (2019-07-15 14:17:04 +0100)
11
hw/arm/mps2.c: Mark internal-only I2C buses as 'full' (2021-09-13 17:09:28 +0100)
17
12
18
----------------------------------------------------------------
13
----------------------------------------------------------------
19
target-arm queue:
14
target-arm queue:
20
* report ARMv8-A FP support for AArch32 -cpu max
15
* mark MPS2/MPS3 board-internal i2c buses as 'full' so that command
21
* hw/ssi/xilinx_spips: Avoid AXI writes to the LQSPI linear memory
16
line user-created devices are not plugged into them
22
* hw/ssi/xilinx_spips: Avoid out-of-bound access to lqspi_buf[]
17
* Take an exception if PSTATE.IL is set
23
* hw/ssi/mss-spi: Avoid crash when reading empty RX FIFO
18
* Support an emulated ITS in the virt board
24
* hw/display/xlnx_dp: Avoid crash when reading empty RX FIFO
19
* Add support for kudo-bmc board
25
* hw/arm/virt: Fix non-secure flash mode
20
* Probe for KVM_CAP_ARM_VM_IPA_SIZE when creating scratch VM
26
* pl031: Correctly migrate state when using -rtc clock=host
21
* cadence_uart: Fix clock handling issues that prevented
27
* fix regression that meant arm926 and arm1026 lost VFP
22
u-boot from running
28
double-precision support
29
* v8M: NS BusFault on vector table fetch escalates to NS HardFault
30
23
31
----------------------------------------------------------------
24
----------------------------------------------------------------
32
Alex Bennée (1):
25
Bin Meng (6):
33
target/arm: report ARMv8-A FP support for AArch32 -cpu max
26
hw/misc: zynq_slcr: Correctly compute output clocks in the reset exit phase
27
hw/char: cadence_uart: Disable transmit when input clock is disabled
28
hw/char: cadence_uart: Move clock/reset check to uart_can_receive()
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
34
32
35
David Engraf (1):
33
Chris Rauer (1):
36
hw/arm/virt: Fix non-secure flash mode
34
hw/arm: Add support for kudo-bmc board.
37
35
38
Peter Maydell (3):
36
Marc Zyngier (1):
39
pl031: Correctly migrate state when using -rtc clock=host
37
hw/arm/virt: KVM: Probe for KVM_CAP_ARM_VM_IPA_SIZE when creating scratch VM
40
target/arm: Set VFP-related MVFR0 fields for arm926 and arm1026
41
target/arm: NS BusFault on vector table fetch escalates to NS HardFault
42
38
43
Philippe Mathieu-Daudé (5):
39
Peter Maydell (5):
44
hw/ssi/xilinx_spips: Convert lqspi_read() to read_with_attrs
40
target/arm: Take an exception if PSTATE.IL is set
45
hw/ssi/xilinx_spips: Avoid AXI writes to the LQSPI linear memory
41
qdev: Support marking individual buses as 'full'
46
hw/ssi/xilinx_spips: Avoid out-of-bound access to lqspi_buf[]
42
hw/arm/mps2-tz.c: Add extra data parameter to MakeDevFn
47
hw/ssi/mss-spi: Avoid crash when reading empty RX FIFO
43
hw/arm/mps2-tz.c: Mark internal-only I2C buses as 'full'
48
hw/display/xlnx_dp: Avoid crash when reading empty RX FIFO
44
hw/arm/mps2.c: Mark internal-only I2C buses as 'full'
49
45
50
include/hw/timer/pl031.h | 2 ++
46
Richard Henderson (1):
51
hw/arm/virt.c | 2 +-
47
target/arm: Merge disas_a64_insn into aarch64_tr_translate_insn
52
hw/core/machine.c | 1 +
53
hw/display/xlnx_dp.c | 15 +++++---
54
hw/ssi/mss-spi.c | 8 ++++-
55
hw/ssi/xilinx_spips.c | 43 +++++++++++++++-------
56
hw/timer/pl031.c | 92 +++++++++++++++++++++++++++++++++++++++++++++---
57
target/arm/cpu.c | 16 +++++++++
58
target/arm/m_helper.c | 21 ++++++++---
59
9 files changed, 174 insertions(+), 26 deletions(-)
60
48
49
Shashi Mallela (9):
50
hw/intc: GICv3 ITS initial framework
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
60
docs/system/arm/nuvoton.rst | 1 +
61
hw/intc/gicv3_internal.h | 188 ++++-
62
include/hw/arm/virt.h | 2 +
63
include/hw/intc/arm_gicv3_common.h | 13 +
64
include/hw/intc/arm_gicv3_its_common.h | 32 +-
65
include/hw/qdev-core.h | 24 +
66
target/arm/cpu.h | 1 +
67
target/arm/kvm_arm.h | 4 +-
68
target/arm/syndrome.h | 5 +
69
target/arm/translate.h | 2 +
70
hw/arm/mps2-tz.c | 92 ++-
71
hw/arm/mps2.c | 12 +-
72
hw/arm/npcm7xx_boards.c | 34 +
73
hw/arm/virt.c | 29 +-
74
hw/char/cadence_uart.c | 61 +-
75
hw/intc/arm_gicv3.c | 14 +
76
hw/intc/arm_gicv3_common.c | 13 +
77
hw/intc/arm_gicv3_cpuif.c | 7 +-
78
hw/intc/arm_gicv3_dist.c | 5 +-
79
hw/intc/arm_gicv3_its.c | 1322 ++++++++++++++++++++++++++++++++
80
hw/intc/arm_gicv3_its_common.c | 7 +-
81
hw/intc/arm_gicv3_its_kvm.c | 2 +-
82
hw/intc/arm_gicv3_redist.c | 153 +++-
83
hw/misc/zynq_slcr.c | 31 +-
84
softmmu/qdev-monitor.c | 7 +-
85
target/arm/helper-a64.c | 1 +
86
target/arm/helper.c | 8 +
87
target/arm/kvm.c | 7 +-
88
target/arm/translate-a64.c | 255 +++---
89
target/arm/translate.c | 21 +
90
hw/intc/meson.build | 1 +
91
tests/data/acpi/virt/IORT | Bin 0 -> 124 bytes
92
tests/data/acpi/virt/IORT.memhp | Bin 0 -> 124 bytes
93
tests/data/acpi/virt/IORT.numamem | Bin 0 -> 124 bytes
94
tests/data/acpi/virt/IORT.pxb | Bin 0 -> 124 bytes
95
35 files changed, 2144 insertions(+), 210 deletions(-)
96
create mode 100644 hw/intc/arm_gicv3_its.c
97
create mode 100644 tests/data/acpi/virt/IORT
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
diff view generated by jsdifflib
New patch
1
From: Bin Meng <bmeng.cn@gmail.com>
1
2
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
New patch
1
From: Bin Meng <bmeng.cn@gmail.com>
1
2
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
New patch
1
From: Bin Meng <bmeng.cn@gmail.com>
1
2
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
New patch
1
From: Bin Meng <bmeng.cn@gmail.com>
1
2
3
This converts uart_read() and uart_write() to memop_with_attrs() ops.
4
5
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 20210901124521.30599-5-bmeng.cn@gmail.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/char/cadence_uart.c | 26 +++++++++++++++-----------
12
1 file changed, 15 insertions(+), 11 deletions(-)
13
14
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/char/cadence_uart.c
17
+++ b/hw/char/cadence_uart.c
18
@@ -XXX,XX +XXX,XX @@ static void uart_read_rx_fifo(CadenceUARTState *s, uint32_t *c)
19
uart_update_status(s);
20
}
21
22
-static void uart_write(void *opaque, hwaddr offset,
23
- uint64_t value, unsigned size)
24
+static MemTxResult uart_write(void *opaque, hwaddr offset,
25
+ uint64_t value, unsigned size, MemTxAttrs attrs)
26
{
27
CadenceUARTState *s = opaque;
28
29
DB_PRINT(" offset:%x data:%08x\n", (unsigned)offset, (unsigned)value);
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
}
44
45
-static uint64_t uart_read(void *opaque, hwaddr offset,
46
- unsigned size)
47
+static MemTxResult uart_read(void *opaque, hwaddr offset,
48
+ uint64_t *value, unsigned size, MemTxAttrs attrs)
49
{
50
CadenceUARTState *s = opaque;
51
uint32_t c = 0;
52
53
offset >>= 2;
54
if (offset >= CADENCE_UART_R_MAX) {
55
- c = 0;
56
- } else if (offset == R_TX_RX) {
57
+ return MEMTX_DECODE_ERROR;
58
+ }
59
+ if (offset == R_TX_RX) {
60
uart_read_rx_fifo(s, &c);
61
} else {
62
- c = s->r[offset];
63
+ c = s->r[offset];
64
}
65
66
DB_PRINT(" offset:%x data:%08x\n", (unsigned)(offset << 2), (unsigned)c);
67
- return c;
68
+ *value = c;
69
+ return MEMTX_OK;
70
}
71
72
static const MemoryRegionOps uart_ops = {
73
- .read = uart_read,
74
- .write = uart_write,
75
+ .read_with_attrs = uart_read,
76
+ .write_with_attrs = uart_write,
77
.endianness = DEVICE_NATIVE_ENDIAN,
78
};
79
80
--
81
2.20.1
82
83
diff view generated by jsdifflib
New patch
1
From: Bin Meng <bmeng.cn@gmail.com>
1
2
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
New patch
1
From: Bin Meng <bmeng.cn@gmail.com>
1
2
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
New patch
1
From: Marc Zyngier <maz@kernel.org>
1
2
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
New patch
1
From: Chris Rauer <crauer@google.com>
1
2
3
kudo-bmc is a board supported by OpenBMC.
4
https://github.com/openbmc/openbmc/tree/master/meta-fii/meta-kudo
5
6
Since v1:
7
- hyphenated Cortex-A9
8
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>
14
---
15
docs/system/arm/nuvoton.rst | 1 +
16
hw/arm/npcm7xx_boards.c | 34 ++++++++++++++++++++++++++++++++++
17
2 files changed, 35 insertions(+)
18
19
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
20
index XXXXXXX..XXXXXXX 100644
21
--- a/docs/system/arm/nuvoton.rst
22
+++ b/docs/system/arm/nuvoton.rst
23
@@ -XXX,XX +XXX,XX @@ Hyperscale applications. The following machines are based on this chip :
24
25
- ``quanta-gbs-bmc`` Quanta GBS server BMC
26
- ``quanta-gsj`` Quanta GSJ server BMC
27
+- ``kudo-bmc`` Fii USA Kudo server BMC
28
29
There are also two more SoCs, NPCM710 and NPCM705, which are single-core
30
variants of NPCM750 and NPCM730, respectively. These are currently not
31
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/hw/arm/npcm7xx_boards.c
34
+++ b/hw/arm/npcm7xx_boards.c
35
@@ -XXX,XX +XXX,XX @@
36
#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
37
#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
38
#define QUANTA_GBS_POWER_ON_STRAPS 0x000017ff
39
+#define KUDO_BMC_POWER_ON_STRAPS 0x00001fff
40
41
static const char npcm7xx_default_bootrom[] = "npcm7xx_bootrom.bin";
42
43
@@ -XXX,XX +XXX,XX @@ static void quanta_gbs_init(MachineState *machine)
44
npcm7xx_load_kernel(machine, soc);
45
}
46
47
+static void kudo_bmc_init(MachineState *machine)
48
+{
49
+ NPCM7xxState *soc;
50
+
51
+ soc = npcm7xx_create_soc(machine, KUDO_BMC_POWER_ON_STRAPS);
52
+ npcm7xx_connect_dram(soc, machine->ram);
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
+};
82
+
83
static const TypeInfo npcm7xx_machine_types[] = {
84
{
85
.name = TYPE_NPCM7XX_MACHINE,
86
@@ -XXX,XX +XXX,XX @@ static const TypeInfo npcm7xx_machine_types[] = {
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
},
95
};
96
97
--
98
2.20.1
99
100
diff view generated by jsdifflib
New patch
1
From: Shashi Mallela <shashi.mallela@linaro.org>
1
2
3
Added register definitions relevant to ITS,implemented overall
4
ITS device framework with stubs for ITS control and translater
5
regions read/write,extended ITS common to handle mmio init between
6
existing kvm device and newer qemu device.
7
8
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Eric Auger <eric.auger@redhat.com>
11
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
12
Message-id: 20210910143951.92242-2-shashi.mallela@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
hw/intc/gicv3_internal.h | 96 +++++++++-
16
include/hw/intc/arm_gicv3_its_common.h | 9 +-
17
hw/intc/arm_gicv3_its.c | 241 +++++++++++++++++++++++++
18
hw/intc/arm_gicv3_its_common.c | 7 +-
19
hw/intc/arm_gicv3_its_kvm.c | 2 +-
20
hw/intc/meson.build | 1 +
21
6 files changed, 342 insertions(+), 14 deletions(-)
22
create mode 100644 hw/intc/arm_gicv3_its.c
23
24
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/intc/gicv3_internal.h
27
+++ b/hw/intc/gicv3_internal.h
28
@@ -XXX,XX +XXX,XX @@
29
#ifndef QEMU_ARM_GICV3_INTERNAL_H
30
#define QEMU_ARM_GICV3_INTERNAL_H
31
32
+#include "hw/registerfields.h"
33
#include "hw/intc/arm_gicv3_common.h"
34
35
/* Distributor registers, as offsets from the distributor base address */
36
@@ -XXX,XX +XXX,XX @@
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
155
--- a/include/hw/intc/arm_gicv3_its_common.h
156
+++ b/include/hw/intc/arm_gicv3_its_common.h
157
@@ -XXX,XX +XXX,XX @@
158
#include "hw/intc/arm_gicv3_common.h"
159
#include "qom/object.h"
160
161
+#define TYPE_ARM_GICV3_ITS "arm-gicv3-its"
162
+
163
#define ITS_CONTROL_SIZE 0x10000
164
#define ITS_TRANS_SIZE 0x10000
165
#define ITS_SIZE (ITS_CONTROL_SIZE + ITS_TRANS_SIZE)
166
167
#define GITS_CTLR 0x0
168
#define GITS_IIDR 0x4
169
+#define GITS_TYPER 0x8
170
#define GITS_CBASER 0x80
171
#define GITS_CWRITER 0x88
172
#define GITS_CREADR 0x90
173
#define GITS_BASER 0x100
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
200
index XXXXXXX..XXXXXXX
201
--- /dev/null
202
+++ b/hw/intc/arm_gicv3_its.c
203
@@ -XXX,XX +XXX,XX @@
204
+/*
205
+ * ITS emulation for a GICv3-based system
206
+ *
207
+ * Copyright Linaro.org 2021
208
+ *
209
+ * Authors:
210
+ * Shashi Mallela <shashi.mallela@linaro.org>
211
+ *
212
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at your
213
+ * option) any later version. See the COPYING file in the top-level directory.
214
+ *
215
+ */
216
+
217
+#include "qemu/osdep.h"
218
+#include "qemu/log.h"
219
+#include "hw/qdev-properties.h"
220
+#include "hw/intc/arm_gicv3_its_common.h"
221
+#include "gicv3_internal.h"
222
+#include "qom/object.h"
223
+#include "qapi/error.h"
224
+
225
+typedef struct GICv3ITSClass GICv3ITSClass;
226
+/* This is reusing the GICv3ITSState typedef from ARM_GICV3_ITS_COMMON */
227
+DECLARE_OBJ_CHECKERS(GICv3ITSState, GICv3ITSClass,
228
+ ARM_GICV3_ITS, TYPE_ARM_GICV3_ITS)
229
+
230
+struct GICv3ITSClass {
231
+ GICv3ITSCommonClass parent_class;
232
+ void (*parent_reset)(DeviceState *dev);
233
+};
234
+
235
+static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset,
236
+ uint64_t data, unsigned size,
237
+ MemTxAttrs attrs)
238
+{
239
+ return MEMTX_OK;
240
+}
241
+
242
+static bool its_writel(GICv3ITSState *s, hwaddr offset,
243
+ uint64_t value, MemTxAttrs attrs)
244
+{
245
+ bool result = true;
246
+
247
+ return result;
248
+}
249
+
250
+static bool its_readl(GICv3ITSState *s, hwaddr offset,
251
+ uint64_t *data, MemTxAttrs attrs)
252
+{
253
+ bool result = true;
254
+
255
+ return result;
256
+}
257
+
258
+static bool its_writell(GICv3ITSState *s, hwaddr offset,
259
+ uint64_t value, MemTxAttrs attrs)
260
+{
261
+ bool result = true;
262
+
263
+ return result;
264
+}
265
+
266
+static bool its_readll(GICv3ITSState *s, hwaddr offset,
267
+ uint64_t *data, MemTxAttrs attrs)
268
+{
269
+ bool result = true;
270
+
271
+ return result;
272
+}
273
+
274
+static MemTxResult gicv3_its_read(void *opaque, hwaddr offset, uint64_t *data,
275
+ unsigned size, MemTxAttrs attrs)
276
+{
277
+ GICv3ITSState *s = (GICv3ITSState *)opaque;
278
+ bool result;
279
+
280
+ switch (size) {
281
+ case 4:
282
+ result = its_readl(s, offset, data, attrs);
283
+ break;
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
+};
348
+
349
+static const MemoryRegionOps gicv3_its_translation_ops = {
350
+ .write_with_attrs = gicv3_its_translation_write,
351
+ .valid.min_access_size = 2,
352
+ .valid.max_access_size = 4,
353
+ .impl.min_access_size = 2,
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(),
419
+};
420
+
421
+static void gicv3_its_class_init(ObjectClass *klass, void *data)
422
+{
423
+ DeviceClass *dc = DEVICE_CLASS(klass);
424
+ GICv3ITSClass *ic = ARM_GICV3_ITS_CLASS(klass);
425
+
426
+ dc->realize = gicv3_arm_its_realize;
427
+ device_class_set_props(dc, gicv3_its_props);
428
+ device_class_set_parent_reset(dc, gicv3_its_reset, &ic->parent_reset);
429
+}
430
+
431
+static const TypeInfo gicv3_its_info = {
432
+ .name = TYPE_ARM_GICV3_ITS,
433
+ .parent = TYPE_ARM_GICV3_ITS_COMMON,
434
+ .instance_size = sizeof(GICv3ITSState),
435
+ .class_init = gicv3_its_class_init,
436
+ .class_size = sizeof(GICv3ITSClass),
437
+};
438
+
439
+static void gicv3_its_register_types(void)
440
+{
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
447
--- a/hw/intc/arm_gicv3_its_common.c
448
+++ b/hw/intc/arm_gicv3_its_common.c
449
@@ -XXX,XX +XXX,XX @@ static int gicv3_its_post_load(void *opaque, int version_id)
450
451
static const VMStateDescription vmstate_its = {
452
.name = "arm_gicv3_its",
453
+ .version_id = 1,
454
+ .minimum_version_id = 1,
455
.pre_save = gicv3_its_pre_save,
456
.post_load = gicv3_its_post_load,
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
478
--- a/hw/intc/arm_gicv3_its_kvm.c
479
+++ b/hw/intc/arm_gicv3_its_kvm.c
480
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_its_realize(DeviceState *dev, Error **errp)
481
kvm_arm_register_device(&s->iomem_its_cntrl, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
482
KVM_VGIC_ITS_ADDR_TYPE, s->dev_fd, 0);
483
484
- gicv3_its_init_mmio(s, NULL);
485
+ gicv3_its_init_mmio(s, NULL, NULL);
486
487
if (!kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
488
GITS_CTLR)) {
489
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
490
index XXXXXXX..XXXXXXX 100644
491
--- a/hw/intc/meson.build
492
+++ b/hw/intc/meson.build
493
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_ARM_GIC', if_true: files(
494
'arm_gicv3_dist.c',
495
'arm_gicv3_its_common.c',
496
'arm_gicv3_redist.c',
497
+ 'arm_gicv3_its.c',
498
))
499
softmmu_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_pic.c'))
500
softmmu_ss.add(when: 'CONFIG_HEATHROW_PIC', if_true: files('heathrow_pic.c'))
501
--
502
2.20.1
503
504
diff view generated by jsdifflib
1
The PL031 RTC tracks the difference between the guest RTC
1
From: Shashi Mallela <shashi.mallela@linaro.org>
2
and the host RTC using a tick_offset field. For migration,
3
however, we currently always migrate the offset between
4
the guest and the vm_clock, even if the RTC clock is not
5
the same as the vm_clock; this was an attempt to retain
6
migration backwards compatibility.
7
2
8
Unfortunately this results in the RTC behaving oddly across
3
Defined descriptors for ITS device table,collection table and ITS
9
a VM state save and restore -- since the VM clock stands still
4
command queue entities.Implemented register read/write functions,
10
across save-then-restore, regardless of how much real world
5
extract ITS table parameters and command queue parameters,extended
11
time has elapsed, the guest RTC ends up out of sync with the
6
gicv3 common to capture qemu address space(which host the ITS table
12
host RTC in the restored VM.
7
platform memories required for subsequent ITS processing) and
8
initialize the same in ITS device.
13
9
14
Fix this by migrating the raw tick_offset. To retain migration
10
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
15
compatibility as far as possible, we have a new property
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
migrate-tick-offset; by default this is 'true' and we will
12
Reviewed-by: Eric Auger <eric.auger@redhat.com>
17
migrate the true tick offset in a new subsection; if the
13
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
18
incoming data has no subsection we fall back to the old
14
Message-id: 20210910143951.92242-3-shashi.mallela@linaro.org
19
vm_clock-based offset information, so old->new migration
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
compatibility is preserved. For complete new->old migration
16
---
21
compatibility, the property is set to 'false' for 4.0 and
17
hw/intc/gicv3_internal.h | 29 ++
22
earlier machine types (this will only affect 'virt-4.0'
18
include/hw/intc/arm_gicv3_common.h | 3 +
23
and below, as none of the other pl031-using machines are
19
include/hw/intc/arm_gicv3_its_common.h | 23 ++
24
versioned).
20
hw/intc/arm_gicv3_its.c | 376 +++++++++++++++++++++++++
21
4 files changed, 431 insertions(+)
25
22
26
Reported-by: Russell King <rmk@armlinux.org.uk>
23
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
29
Message-id: 20190709143912.28905-1-peter.maydell@linaro.org
30
---
31
include/hw/timer/pl031.h | 2 +
32
hw/core/machine.c | 1 +
33
hw/timer/pl031.c | 92 ++++++++++++++++++++++++++++++++++++++--
34
3 files changed, 91 insertions(+), 4 deletions(-)
35
36
diff --git a/include/hw/timer/pl031.h b/include/hw/timer/pl031.h
37
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
38
--- a/include/hw/timer/pl031.h
25
--- a/hw/intc/gicv3_internal.h
39
+++ b/include/hw/timer/pl031.h
26
+++ b/hw/intc/gicv3_internal.h
40
@@ -XXX,XX +XXX,XX @@ typedef struct PL031State {
27
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_BASER, INNERCACHE, 59, 3)
41
*/
28
FIELD(GITS_BASER, INDIRECT, 62, 1)
42
uint32_t tick_offset_vmstate;
29
FIELD(GITS_BASER, VALID, 63, 1)
43
uint32_t tick_offset;
30
44
+ bool tick_offset_migrated;
31
+FIELD(GITS_CBASER, SIZE, 0, 8)
45
+ bool migrate_tick_offset;
32
+FIELD(GITS_CBASER, SHAREABILITY, 10, 2)
46
33
+FIELD(GITS_CBASER, PHYADDR, 12, 40)
47
uint32_t mr;
34
+FIELD(GITS_CBASER, OUTERCACHE, 53, 3)
48
uint32_t lr;
35
+FIELD(GITS_CBASER, INNERCACHE, 59, 3)
49
diff --git a/hw/core/machine.c b/hw/core/machine.c
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
50
index XXXXXXX..XXXXXXX 100644
78
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/core/machine.c
79
--- a/include/hw/intc/arm_gicv3_common.h
52
+++ b/hw/core/machine.c
80
+++ b/include/hw/intc/arm_gicv3_common.h
53
@@ -XXX,XX +XXX,XX @@ GlobalProperty hw_compat_4_0[] = {
81
@@ -XXX,XX +XXX,XX @@ struct GICv3State {
54
{ "virtio-gpu-pci", "edid", "false" },
82
int dev_fd; /* kvm device fd if backed by kvm vgic support */
55
{ "virtio-device", "use-started", "false" },
83
Error *migration_blocker;
56
{ "virtio-balloon-device", "qemu-4-0-config-size", "true" },
84
57
+ { "pl031", "migrate-tick-offset", "false" },
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;
58
};
130
};
59
const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0);
131
60
132
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
61
diff --git a/hw/timer/pl031.c b/hw/timer/pl031.c
62
index XXXXXXX..XXXXXXX 100644
133
index XXXXXXX..XXXXXXX 100644
63
--- a/hw/timer/pl031.c
134
--- a/hw/intc/arm_gicv3_its.c
64
+++ b/hw/timer/pl031.c
135
+++ b/hw/intc/arm_gicv3_its.c
65
@@ -XXX,XX +XXX,XX @@ static int pl031_pre_save(void *opaque)
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)
66
{
299
{
67
PL031State *s = opaque;
300
bool result = true;
68
301
+ int index;
69
- /* tick_offset is base_time - rtc_clock base time. Instead, we want to
302
70
- * store the base time relative to the QEMU_CLOCK_VIRTUAL for backwards-compatibility. */
303
+ switch (offset) {
71
+ /*
304
+ case GITS_CTLR:
72
+ * The PL031 device model code uses the tick_offset field, which is
305
+ s->ctlr |= (value & ~(s->ctlr));
73
+ * the offset between what the guest RTC should read and what the
306
+
74
+ * QEMU rtc_clock reads:
307
+ if (s->ctlr & ITS_CTLR_ENABLED) {
75
+ * guest_rtc = rtc_clock + tick_offset
308
+ extract_table_params(s);
76
+ * and so
309
+ extract_cmdq_params(s);
77
+ * tick_offset = guest_rtc - rtc_clock
310
+ s->creadr = 0;
78
+ *
311
+ }
79
+ * We want to migrate this offset, which sounds straightforward.
312
+ break;
80
+ * Unfortunately older versions of QEMU migrated a conversion of this
313
+ case GITS_CBASER:
81
+ * offset into an offset from the vm_clock. (This was in turn an
314
+ /*
82
+ * attempt to be compatible with even older QEMU versions, but it
315
+ * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
83
+ * has incorrect behaviour if the rtc_clock is not the same as the
316
+ * already enabled
84
+ * vm_clock.) So we put the actual tick_offset into a migration
317
+ */
85
+ * subsection, and the backwards-compatible time-relative-to-vm_clock
318
+ if (!(s->ctlr & ITS_CTLR_ENABLED)) {
86
+ * in the main migration state.
319
+ s->cbaser = deposit64(s->cbaser, 0, 32, value);
87
+ *
320
+ s->creadr = 0;
88
+ * Calculate base time relative to QEMU_CLOCK_VIRTUAL:
321
+ s->cwriter = s->creadr;
89
+ */
322
+ }
90
int64_t delta = qemu_clock_get_ns(rtc_clock) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
323
+ break;
91
s->tick_offset_vmstate = s->tick_offset + delta / NANOSECONDS_PER_SECOND;
324
+ case GITS_CBASER + 4:
92
325
+ /*
93
return 0;
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;
94
}
395
}
95
396
96
+static int pl031_pre_load(void *opaque)
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)
97
+{
553
+{
98
+ PL031State *s = opaque;
554
+ if (s->ctlr & ITS_CTLR_ENABLED) {
99
+
555
+ extract_table_params(s);
100
+ s->tick_offset_migrated = false;
556
+ extract_cmdq_params(s);
101
+ return 0;
557
+ }
102
+}
558
+}
103
+
559
+
104
static int pl031_post_load(void *opaque, int version_id)
560
static Property gicv3_its_props[] = {
105
{
561
DEFINE_PROP_LINK("parent-gicv3", GICv3ITSState, gicv3, "arm-gicv3",
106
PL031State *s = opaque;
562
GICv3State *),
107
563
@@ -XXX,XX +XXX,XX @@ static void gicv3_its_class_init(ObjectClass *klass, void *data)
108
- int64_t delta = qemu_clock_get_ns(rtc_clock) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
109
- s->tick_offset = s->tick_offset_vmstate - delta / NANOSECONDS_PER_SECOND;
110
+ /*
111
+ * If we got the tick_offset subsection, then we can just use
112
+ * the value in that. Otherwise the source is an older QEMU and
113
+ * has given us the offset from the vm_clock; convert it back to
114
+ * an offset from the rtc_clock. This will cause time to incorrectly
115
+ * go backwards compared to the host RTC, but this is unavoidable.
116
+ */
117
+
118
+ if (!s->tick_offset_migrated) {
119
+ int64_t delta = qemu_clock_get_ns(rtc_clock) -
120
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
121
+ s->tick_offset = s->tick_offset_vmstate -
122
+ delta / NANOSECONDS_PER_SECOND;
123
+ }
124
pl031_set_alarm(s);
125
return 0;
126
}
127
128
+static int pl031_tick_offset_post_load(void *opaque, int version_id)
129
+{
130
+ PL031State *s = opaque;
131
+
132
+ s->tick_offset_migrated = true;
133
+ return 0;
134
+}
135
+
136
+static bool pl031_tick_offset_needed(void *opaque)
137
+{
138
+ PL031State *s = opaque;
139
+
140
+ return s->migrate_tick_offset;
141
+}
142
+
143
+static const VMStateDescription vmstate_pl031_tick_offset = {
144
+ .name = "pl031/tick-offset",
145
+ .version_id = 1,
146
+ .minimum_version_id = 1,
147
+ .needed = pl031_tick_offset_needed,
148
+ .post_load = pl031_tick_offset_post_load,
149
+ .fields = (VMStateField[]) {
150
+ VMSTATE_UINT32(tick_offset, PL031State),
151
+ VMSTATE_END_OF_LIST()
152
+ }
153
+};
154
+
155
static const VMStateDescription vmstate_pl031 = {
156
.name = "pl031",
157
.version_id = 1,
158
.minimum_version_id = 1,
159
.pre_save = pl031_pre_save,
160
+ .pre_load = pl031_pre_load,
161
.post_load = pl031_post_load,
162
.fields = (VMStateField[]) {
163
VMSTATE_UINT32(tick_offset_vmstate, PL031State),
164
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_pl031 = {
165
VMSTATE_UINT32(im, PL031State),
166
VMSTATE_UINT32(is, PL031State),
167
VMSTATE_END_OF_LIST()
168
+ },
169
+ .subsections = (const VMStateDescription*[]) {
170
+ &vmstate_pl031_tick_offset,
171
+ NULL
172
}
173
};
174
175
+static Property pl031_properties[] = {
176
+ /*
177
+ * True to correctly migrate the tick offset of the RTC. False to
178
+ * obtain backward migration compatibility with older QEMU versions,
179
+ * at the expense of the guest RTC going backwards compared with the
180
+ * host RTC when the VM is saved/restored if using -rtc host.
181
+ * (Even if set to 'true' older QEMU can migrate forward to newer QEMU;
182
+ * 'false' also permits newer QEMU to migrate to older QEMU.)
183
+ */
184
+ DEFINE_PROP_BOOL("migrate-tick-offset",
185
+ PL031State, migrate_tick_offset, true),
186
+ DEFINE_PROP_END_OF_LIST()
187
+};
188
+
189
static void pl031_class_init(ObjectClass *klass, void *data)
190
{
564
{
191
DeviceClass *dc = DEVICE_CLASS(klass);
565
DeviceClass *dc = DEVICE_CLASS(klass);
192
566
GICv3ITSClass *ic = ARM_GICV3_ITS_CLASS(klass);
193
dc->vmsd = &vmstate_pl031;
567
+ GICv3ITSCommonClass *icc = ARM_GICV3_ITS_COMMON_CLASS(klass);
194
+ dc->props = pl031_properties;
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;
195
}
573
}
196
574
197
static const TypeInfo pl031_info = {
575
static const TypeInfo gicv3_its_info = {
198
--
576
--
199
2.20.1
577
2.20.1
200
578
201
579
diff view generated by jsdifflib
New patch
1
From: Shashi Mallela <shashi.mallela@linaro.org>
1
2
3
Added functionality to trigger ITS command queue processing on
4
write to CWRITE register and process each command queue entry to
5
identify the command type and handle commands like MAPD,MAPC,SYNC.
6
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>
13
---
14
hw/intc/gicv3_internal.h | 40 +++++
15
hw/intc/arm_gicv3_its.c | 319 +++++++++++++++++++++++++++++++++++++++
16
2 files changed, 359 insertions(+)
17
18
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/intc/gicv3_internal.h
21
+++ b/hw/intc/gicv3_internal.h
22
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1)
23
#define L1TABLE_ENTRY_SIZE 8
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
}
83
84
+static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
85
+ uint64_t rdbase)
86
+{
87
+ AddressSpace *as = &s->gicv3->dma_as;
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
+}
144
+
145
+static bool process_mapc(GICv3ITSState *s, uint32_t offset)
146
+{
147
+ AddressSpace *as = &s->gicv3->dma_as;
148
+ uint16_t icid;
149
+ uint64_t rdbase;
150
+ bool valid;
151
+ MemTxResult res = MEMTX_OK;
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
+ }
164
+
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
+}
187
+
188
+static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
189
+ uint8_t size, uint64_t itt_addr)
190
+{
191
+ AddressSpace *as = &s->gicv3->dma_as;
192
+ uint64_t value;
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
+ }
210
+
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
+}
250
+
251
+static bool process_mapd(GICv3ITSState *s, uint64_t value, uint32_t offset)
252
+{
253
+ AddressSpace *as = &s->gicv3->dma_as;
254
+ uint32_t devid;
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
+ }
270
+
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
+}
301
+
302
+/*
303
+ * Current implementation blocks until all
304
+ * commands are processed
305
+ */
306
+static void process_cmdq(GICv3ITSState *s)
307
+{
308
+ uint32_t wr_offset = 0;
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
+
317
+ if (!(s->ctlr & ITS_CTLR_ENABLED)) {
318
+ return;
319
+ }
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
+}
395
+
396
/*
397
* This function extracts the ITS Device and Collection table specific
398
* parameters (like base_addr, size etc) from GITS_BASER register.
399
@@ -XXX,XX +XXX,XX @@ static bool its_writel(GICv3ITSState *s, hwaddr offset,
400
extract_table_params(s);
401
extract_cmdq_params(s);
402
s->creadr = 0;
403
+ process_cmdq(s);
404
}
405
break;
406
case GITS_CBASER:
407
@@ -XXX,XX +XXX,XX @@ static bool its_writel(GICv3ITSState *s, hwaddr offset,
408
case GITS_CWRITER:
409
s->cwriter = deposit64(s->cwriter, 0, 32,
410
(value & ~R_GITS_CWRITER_RETRY_MASK));
411
+ if (s->cwriter != s->creadr) {
412
+ process_cmdq(s);
413
+ }
414
break;
415
case GITS_CWRITER + 4:
416
s->cwriter = deposit64(s->cwriter, 32, 32, value);
417
@@ -XXX,XX +XXX,XX @@ static bool its_writell(GICv3ITSState *s, hwaddr offset,
418
break;
419
case GITS_CWRITER:
420
s->cwriter = value & ~R_GITS_CWRITER_RETRY_MASK;
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
--
428
2.20.1
429
430
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Shashi Mallela <shashi.mallela@linaro.org>
2
2
3
Reading the RX_DATA register when the RX_FIFO is empty triggers
3
Added ITS command queue handling for MAPTI,MAPI commands,handled ITS
4
an abort. This can be easily reproduced:
4
translation which triggers an LPI via INT command as well as write
5
to GITS_TRANSLATER register,defined enum to differentiate between ITS
6
command interrupt trigger and GITS_TRANSLATER based interrupt trigger.
7
Each of these commands make use of other functionalities implemented to
8
get device table entry,collection table entry or interrupt translation
9
table entry required for their processing.
5
10
6
$ qemu-system-arm -M emcraft-sf2 -monitor stdio -S
11
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
7
QEMU 4.0.50 monitor - type 'help' for more information
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
(qemu) x 0x40001010
13
Message-id: 20210910143951.92242-5-shashi.mallela@linaro.org
9
Aborted (core dumped)
10
11
(gdb) bt
12
#1 0x00007f035874f895 in abort () at /lib64/libc.so.6
13
#2 0x00005628686591ff in fifo8_pop (fifo=0x56286a9a4c68) at util/fifo8.c:66
14
#3 0x00005628683e0b8e in fifo32_pop (fifo=0x56286a9a4c68) at include/qemu/fifo32.h:137
15
#4 0x00005628683e0efb in spi_read (opaque=0x56286a9a4850, addr=4, size=4) at hw/ssi/mss-spi.c:168
16
#5 0x0000562867f96801 in memory_region_read_accessor (mr=0x56286a9a4b60, addr=16, value=0x7ffeecb0c5c8, size=4, shift=0, mask=4294967295, attrs=...) at memory.c:439
17
#6 0x0000562867f96cdb in access_with_adjusted_size (addr=16, value=0x7ffeecb0c5c8, size=4, access_size_min=1, access_size_max=4, access_fn=0x562867f967c3 <memory_region_read_accessor>, mr=0x56286a9a4b60, attrs=...) at memory.c:569
18
#7 0x0000562867f99940 in memory_region_dispatch_read1 (mr=0x56286a9a4b60, addr=16, pval=0x7ffeecb0c5c8, size=4, attrs=...) at memory.c:1420
19
#8 0x0000562867f99a08 in memory_region_dispatch_read (mr=0x56286a9a4b60, addr=16, pval=0x7ffeecb0c5c8, size=4, attrs=...) at memory.c:1447
20
#9 0x0000562867f38721 in flatview_read_continue (fv=0x56286aec6360, addr=1073745936, attrs=..., buf=0x7ffeecb0c7c0 "\340ǰ\354\376\177", len=4, addr1=16, l=4, mr=0x56286a9a4b60) at exec.c:3385
21
#10 0x0000562867f38874 in flatview_read (fv=0x56286aec6360, addr=1073745936, attrs=..., buf=0x7ffeecb0c7c0 "\340ǰ\354\376\177", len=4) at exec.c:3423
22
#11 0x0000562867f388ea in address_space_read_full (as=0x56286aa3e890, addr=1073745936, attrs=..., buf=0x7ffeecb0c7c0 "\340ǰ\354\376\177", len=4) at exec.c:3436
23
#12 0x0000562867f389c5 in address_space_rw (as=0x56286aa3e890, addr=1073745936, attrs=..., buf=0x7ffeecb0c7c0 "\340ǰ\354\376\177", len=4, is_write=false) at exec.c:3466
24
#13 0x0000562867f3bdd7 in cpu_memory_rw_debug (cpu=0x56286aa19d00, addr=1073745936, buf=0x7ffeecb0c7c0 "\340ǰ\354\376\177", len=4, is_write=0) at exec.c:3976
25
#14 0x000056286811ed51 in memory_dump (mon=0x56286a8c32d0, count=1, format=120, wsize=4, addr=1073745936, is_physical=0) at monitor/misc.c:730
26
#15 0x000056286811eff1 in hmp_memory_dump (mon=0x56286a8c32d0, qdict=0x56286b15c400) at monitor/misc.c:785
27
#16 0x00005628684740ee in handle_hmp_command (mon=0x56286a8c32d0, cmdline=0x56286a8caeb2 "0x40001010") at monitor/hmp.c:1082
28
29
From the datasheet "Actel SmartFusion Microcontroller Subsystem
30
User's Guide" Rev.1, Table 13-3 "SPI Register Summary", this
31
register has a reset value of 0.
32
33
Check the FIFO is not empty before accessing it, else log an
34
error message.
35
36
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
37
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
38
Message-id: 20190709113715.7761-3-philmd@redhat.com
39
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
40
---
15
---
41
hw/ssi/mss-spi.c | 8 +++++++-
16
hw/intc/gicv3_internal.h | 12 +
42
1 file changed, 7 insertions(+), 1 deletion(-)
17
include/hw/intc/arm_gicv3_common.h | 2 +
18
hw/intc/arm_gicv3_its.c | 365 ++++++++++++++++++++++++++++-
19
3 files changed, 378 insertions(+), 1 deletion(-)
43
20
44
diff --git a/hw/ssi/mss-spi.c b/hw/ssi/mss-spi.c
21
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
45
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/ssi/mss-spi.c
23
--- a/hw/intc/gicv3_internal.h
47
+++ b/hw/ssi/mss-spi.c
24
+++ b/hw/intc/gicv3_internal.h
48
@@ -XXX,XX +XXX,XX @@ spi_read(void *opaque, hwaddr addr, unsigned int size)
25
@@ -XXX,XX +XXX,XX @@ FIELD(MAPC, RDBASE, 16, 32)
49
case R_SPI_RX:
26
#define ITTADDR_MASK MAKE_64BIT_MASK(ITTADDR_SHIFT, ITTADDR_LENGTH)
50
s->regs[R_SPI_STATUS] &= ~S_RXFIFOFUL;
27
#define SIZE_MASK 0x1f
51
s->regs[R_SPI_STATUS] &= ~S_RXCHOVRF;
28
52
- ret = fifo32_pop(&s->rx_fifo);
29
+/* MAPI command fields */
53
+ if (fifo32_is_empty(&s->rx_fifo)) {
30
+#define EVENTID_MASK ((1ULL << 32) - 1)
54
+ qemu_log_mask(LOG_GUEST_ERROR,
31
+
55
+ "%s: Reading empty RX_FIFO\n",
32
+/* MAPTI command fields */
56
+ __func__);
33
+#define pINTID_SHIFT 32
34
+#define pINTID_MASK MAKE_64BIT_MASK(32, 32)
35
+
36
#define DEVID_SHIFT 32
37
#define DEVID_MASK MAKE_64BIT_MASK(32, 32)
38
39
@@ -XXX,XX +XXX,XX @@ FIELD(MAPC, RDBASE, 16, 32)
40
* Values: | vPEID | ICID |
41
*/
42
#define ITS_ITT_ENTRY_SIZE 0xC
43
+#define ITE_ENTRY_INTTYPE_SHIFT 1
44
+#define ITE_ENTRY_INTID_SHIFT 2
45
+#define ITE_ENTRY_INTID_MASK MAKE_64BIT_MASK(2, 24)
46
+#define ITE_ENTRY_INTSP_SHIFT 26
47
+#define ITE_ENTRY_ICID_MASK MAKE_64BIT_MASK(0, 16)
48
49
/* 16 bits EventId */
50
#define ITS_IDBITS GICD_TYPER_IDBITS
51
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
52
index XXXXXXX..XXXXXXX 100644
53
--- a/include/hw/intc/arm_gicv3_common.h
54
+++ b/include/hw/intc/arm_gicv3_common.h
55
@@ -XXX,XX +XXX,XX @@
56
#define GICV3_MAXIRQ 1020
57
#define GICV3_MAXSPI (GICV3_MAXIRQ - GIC_INTERNAL)
58
59
+#define GICV3_LPI_INTID_START 8192
60
+
61
#define GICV3_REDIST_SIZE 0x20000
62
63
/* Number of SGI target-list bits */
64
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/hw/intc/arm_gicv3_its.c
67
+++ b/hw/intc/arm_gicv3_its.c
68
@@ -XXX,XX +XXX,XX @@ struct GICv3ITSClass {
69
void (*parent_reset)(DeviceState *dev);
70
};
71
72
+/*
73
+ * This is an internal enum used to distinguish between LPI triggered
74
+ * via command queue and LPI triggered via gits_translater write.
75
+ */
76
+typedef enum ItsCmdType {
77
+ NONE = 0, /* internal indication for GITS_TRANSLATER write */
78
+ CLEAR = 1,
79
+ DISCARD = 2,
80
+ INT = 3,
81
+} ItsCmdType;
82
+
83
+typedef struct {
84
+ uint32_t iteh;
85
+ uint64_t itel;
86
+} IteEntry;
87
+
88
static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
89
{
90
uint64_t result = 0;
91
@@ -XXX,XX +XXX,XX @@ static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
92
return result;
93
}
94
95
+static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte,
96
+ MemTxResult *res)
97
+{
98
+ AddressSpace *as = &s->gicv3->dma_as;
99
+ uint64_t l2t_addr;
100
+ uint64_t value;
101
+ bool valid_l2t;
102
+ uint32_t l2t_id;
103
+ uint32_t max_l2_entries;
104
+
105
+ if (s->ct.indirect) {
106
+ l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE);
107
+
108
+ value = address_space_ldq_le(as,
109
+ s->ct.base_addr +
110
+ (l2t_id * L1TABLE_ENTRY_SIZE),
111
+ MEMTXATTRS_UNSPECIFIED, res);
112
+
113
+ if (*res == MEMTX_OK) {
114
+ valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
115
+
116
+ if (valid_l2t) {
117
+ max_l2_entries = s->ct.page_sz / s->ct.entry_sz;
118
+
119
+ l2t_addr = value & ((1ULL << 51) - 1);
120
+
121
+ *cte = address_space_ldq_le(as, l2t_addr +
122
+ ((icid % max_l2_entries) * GITS_CTE_SIZE),
123
+ MEMTXATTRS_UNSPECIFIED, res);
124
+ }
125
+ }
126
+ } else {
127
+ /* Flat level table */
128
+ *cte = address_space_ldq_le(as, s->ct.base_addr +
129
+ (icid * GITS_CTE_SIZE),
130
+ MEMTXATTRS_UNSPECIFIED, res);
131
+ }
132
+
133
+ return (*cte & TABLE_ENTRY_VALID_MASK) != 0;
134
+}
135
+
136
+static bool update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
137
+ IteEntry ite)
138
+{
139
+ AddressSpace *as = &s->gicv3->dma_as;
140
+ uint64_t itt_addr;
141
+ MemTxResult res = MEMTX_OK;
142
+
143
+ itt_addr = (dte & GITS_DTE_ITTADDR_MASK) >> GITS_DTE_ITTADDR_SHIFT;
144
+ itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
145
+
146
+ address_space_stq_le(as, itt_addr + (eventid * (sizeof(uint64_t) +
147
+ sizeof(uint32_t))), ite.itel, MEMTXATTRS_UNSPECIFIED,
148
+ &res);
149
+
150
+ if (res == MEMTX_OK) {
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
+ }
195
+ }
196
+ return status;
197
+}
198
+
199
+static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res)
200
+{
201
+ AddressSpace *as = &s->gicv3->dma_as;
202
+ uint64_t l2t_addr;
203
+ uint64_t value;
204
+ bool valid_l2t;
205
+ uint32_t l2t_id;
206
+ uint32_t max_l2_entries;
207
+
208
+ if (s->dt.indirect) {
209
+ l2t_id = devid / (s->dt.page_sz / L1TABLE_ENTRY_SIZE);
210
+
211
+ value = address_space_ldq_le(as,
212
+ s->dt.base_addr +
213
+ (l2t_id * L1TABLE_ENTRY_SIZE),
214
+ MEMTXATTRS_UNSPECIFIED, res);
215
+
216
+ if (*res == MEMTX_OK) {
217
+ valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
218
+
219
+ if (valid_l2t) {
220
+ max_l2_entries = s->dt.page_sz / s->dt.entry_sz;
221
+
222
+ l2t_addr = value & ((1ULL << 51) - 1);
223
+
224
+ value = address_space_ldq_le(as, l2t_addr +
225
+ ((devid % max_l2_entries) * GITS_DTE_SIZE),
226
+ MEMTXATTRS_UNSPECIFIED, res);
227
+ }
228
+ }
229
+ } else {
230
+ /* Flat level table */
231
+ value = address_space_ldq_le(as, s->dt.base_addr +
232
+ (devid * GITS_DTE_SIZE),
233
+ MEMTXATTRS_UNSPECIFIED, res);
234
+ }
235
+
236
+ return value;
237
+}
238
+
239
+/*
240
+ * This function handles the processing of following commands based on
241
+ * the ItsCmdType parameter passed:-
242
+ * 1. triggering of lpi interrupt translation via ITS INT command
243
+ * 2. triggering of lpi interrupt translation via gits_translater register
244
+ * 3. handling of ITS CLEAR command
245
+ * 4. handling of ITS DISCARD command
246
+ */
247
+static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
248
+ ItsCmdType cmd)
249
+{
250
+ AddressSpace *as = &s->gicv3->dma_as;
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);
57
+ } else {
406
+ } else {
58
+ ret = fifo32_pop(&s->rx_fifo);
407
+ ite.itel |= (pIntid << ITE_ENTRY_INTID_SHIFT);
59
+ }
408
+ }
60
if (fifo32_is_empty(&s->rx_fifo)) {
409
+ ite.itel |= (int_spurious << ITE_ENTRY_INTSP_SHIFT);
61
s->regs[R_SPI_STATUS] |= S_RXFIFOEMP;
410
+ ite.iteh = icid;
62
}
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,
63
--
474
--
64
2.20.1
475
2.20.1
65
476
66
477
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Shashi Mallela <shashi.mallela@linaro.org>
2
2
3
In the next commit we will implement the write_with_attrs()
3
Added properties to enable ITS feature and define qemu system
4
handler. To avoid using different APIs, convert the read()
4
address space memory in gicv3 common,setup distributor and
5
handler first.
5
redistributor registers to indicate LPI support.
6
6
7
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
7
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
8
Tested-by: Francisco Iglesias <frasse.iglesias@gmail.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
10
Message-id: 20210910143951.92242-6-shashi.mallela@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
hw/ssi/xilinx_spips.c | 23 +++++++++++------------
13
hw/intc/gicv3_internal.h | 2 ++
13
1 file changed, 11 insertions(+), 12 deletions(-)
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(-)
14
19
15
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
20
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
16
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/ssi/xilinx_spips.c
22
--- a/hw/intc/gicv3_internal.h
18
+++ b/hw/ssi/xilinx_spips.c
23
+++ b/hw/intc/gicv3_internal.h
19
@@ -XXX,XX +XXX,XX @@ static void lqspi_load_cache(void *opaque, hwaddr addr)
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
+ }
20
}
69
}
21
}
70
}
22
71
23
-static uint64_t
72
@@ -XXX,XX +XXX,XX @@ static Property arm_gicv3_common_properties[] = {
24
-lqspi_read(void *opaque, hwaddr addr, unsigned int size)
73
DEFINE_PROP_UINT32("num-cpu", GICv3State, num_cpu, 1),
25
+static MemTxResult lqspi_read(void *opaque, hwaddr addr, uint64_t *value,
74
DEFINE_PROP_UINT32("num-irq", GICv3State, num_irq, 32),
26
+ unsigned size, MemTxAttrs attrs)
75
DEFINE_PROP_UINT32("revision", GICv3State, revision, 3),
27
{
76
+ DEFINE_PROP_BOOL("has-lpi", GICv3State, lpi_enable, 0),
28
- XilinxQSPIPS *q = opaque;
77
DEFINE_PROP_BOOL("has-security-extensions", GICv3State, security_extn, 0),
29
- uint32_t ret;
78
DEFINE_PROP_ARRAY("redist-region-count", GICv3State, nb_redist_regions,
30
+ XilinxQSPIPS *q = XILINX_QSPIPS(opaque);
79
redist_region_count, qdev_prop_uint32, uint32_t),
31
80
+ DEFINE_PROP_LINK("sysmem", GICv3State, dma, TYPE_MEMORY_REGION,
32
if (addr >= q->lqspi_cached_addr &&
81
+ MemoryRegion *),
33
addr <= q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
82
DEFINE_PROP_END_OF_LIST(),
34
uint8_t *retp = &q->lqspi_buf[addr - q->lqspi_cached_addr];
83
};
35
- ret = cpu_to_le32(*(uint32_t *)retp);
84
36
- DB_PRINT_L(1, "addr: %08x, data: %08x\n", (unsigned)addr,
85
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
37
- (unsigned)ret);
86
index XXXXXXX..XXXXXXX 100644
38
- return ret;
87
--- a/hw/intc/arm_gicv3_dist.c
39
- } else {
88
+++ b/hw/intc/arm_gicv3_dist.c
40
- lqspi_load_cache(opaque, addr);
89
@@ -XXX,XX +XXX,XX @@ static bool gicd_readl(GICv3State *s, hwaddr offset,
41
- return lqspi_read(opaque, addr, size);
90
* A3V == 1 (non-zero values of Affinity level 3 supported)
42
+ *value = cpu_to_le32(*(uint32_t *)retp);
91
* IDbits == 0xf (we support 16-bit interrupt identifiers)
43
+ DB_PRINT_L(1, "addr: %08" HWADDR_PRIx ", data: %08" PRIx64 "\n",
92
* DVIS == 0 (Direct virtual LPI injection not supported)
44
+ addr, *value);
93
- * LPIS == 0 (LPIs not supported)
45
+ return MEMTX_OK;
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;
46
}
107
}
47
+
108
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
48
+ lqspi_load_cache(opaque, addr);
109
index XXXXXXX..XXXXXXX 100644
49
+ return lqspi_read(opaque, addr, value, size, attrs);
110
--- a/hw/intc/arm_gicv3_redist.c
50
}
111
+++ b/hw/intc/arm_gicv3_redist.c
51
112
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr offset,
52
static const MemoryRegionOps lqspi_ops = {
113
case GICR_CTLR:
53
- .read = lqspi_read,
114
/* For our implementation, GICR_TYPER.DPGS is 0 and so all
54
+ .read_with_attrs = lqspi_read,
115
* the DPG bits are RAZ/WI. We don't do anything asynchronously,
55
.endianness = DEVICE_NATIVE_ENDIAN,
116
- * so UWP and RWP are RAZ/WI. And GICR_TYPER.LPIS is 0 (we don't
56
.valid = {
117
- * implement LPIs) so Enable_LPIs is RES0. So there are no writable
57
.min_access_size = 1,
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 */
58
--
132
--
59
2.20.1
133
2.20.1
60
134
61
135
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Shashi Mallela <shashi.mallela@linaro.org>
2
2
3
Lei Sun found while auditing the code that a CPU write would
3
Implemented lpi processing at redistributor to get lpi config info
4
trigger a NULL pointer dereference.
4
from lpi configuration table,determine priority,set pending state in
5
5
lpi pending table and forward the lpi to cpuif.Added logic to invoke
6
>From UG1085 datasheet [*] AXI writes in this region are ignored
6
redistributor lpi processing with translated LPI which set/clear LPI
7
and generates an AXI Slave Error (SLVERR).
7
from ITS device as part of ITS INT,CLEAR,DISCARD command and
8
8
GITS_TRANSLATER processing.
9
Fix by implementing the write_with_attrs() handler.
9
10
Return MEMTX_ERROR when the region is accessed (this error maps
10
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
11
to an AXI slave error).
11
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
12
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
[*] https://www.xilinx.com/support/documentation/user_guides/ug1085-zynq-ultrascale-trm.pdf
13
Message-id: 20210910143951.92242-7-shashi.mallela@linaro.org
14
15
Reported-by: Lei Sun <slei.casper@gmail.com>
16
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
17
Tested-by: Francisco Iglesias <frasse.iglesias@gmail.com>
18
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
15
---
21
hw/ssi/xilinx_spips.c | 16 ++++++++++++++++
16
hw/intc/gicv3_internal.h | 9 ++
22
1 file changed, 16 insertions(+)
17
include/hw/intc/arm_gicv3_common.h | 7 ++
23
18
hw/intc/arm_gicv3.c | 14 +++
24
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
19
hw/intc/arm_gicv3_common.c | 1 +
25
index XXXXXXX..XXXXXXX 100644
20
hw/intc/arm_gicv3_cpuif.c | 7 +-
26
--- a/hw/ssi/xilinx_spips.c
21
hw/intc/arm_gicv3_its.c | 23 +++++
27
+++ b/hw/ssi/xilinx_spips.c
22
hw/intc/arm_gicv3_redist.c | 141 +++++++++++++++++++++++++++++
28
@@ -XXX,XX +XXX,XX @@ static MemTxResult lqspi_read(void *opaque, hwaddr addr, uint64_t *value,
23
7 files changed, 200 insertions(+), 2 deletions(-)
29
return lqspi_read(opaque, addr, value, size, attrs);
24
25
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/intc/gicv3_internal.h
28
+++ b/hw/intc/gicv3_internal.h
29
@@ -XXX,XX +XXX,XX @@ FIELD(GICR_PENDBASER, PHYADDR, 16, 36)
30
FIELD(GICR_PENDBASER, OUTERCACHE, 56, 3)
31
FIELD(GICR_PENDBASER, PTZ, 62, 1)
32
33
+#define GICR_PROPBASER_IDBITS_THRESHOLD 0xd
34
+
35
#define ICC_CTLR_EL1_CBPR (1U << 0)
36
#define ICC_CTLR_EL1_EOIMODE (1U << 1)
37
#define ICC_CTLR_EL1_PMHE (1U << 6)
38
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1)
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
68
--- a/include/hw/intc/arm_gicv3_common.h
69
+++ b/include/hw/intc/arm_gicv3_common.h
70
@@ -XXX,XX +XXX,XX @@ struct GICv3CPUState {
71
* real state above; it doesn't need to be migrated.
72
*/
73
PendingIrq hppi;
74
+
75
+ /*
76
+ * Cached information recalculated from LPI tables
77
+ * in guest memory
78
+ */
79
+ PendingIrq hpplpi;
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
}
91
92
+ if ((cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) && cs->gic->lpi_enable &&
93
+ (cs->hpplpi.prio != 0xff)) {
94
+ if (irqbetter(cs, cs->hpplpi.irq, cs->hpplpi.prio)) {
95
+ cs->hppi.irq = cs->hpplpi.irq;
96
+ cs->hppi.prio = cs->hpplpi.prio;
97
+ cs->hppi.grp = cs->hpplpi.grp;
98
+ seenbetter = true;
99
+ }
100
+ }
101
+
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
}
30
}
147
}
31
148
32
+static MemTxResult lqspi_write(void *opaque, hwaddr offset, uint64_t value,
149
@@ -XXX,XX +XXX,XX @@ static void icc_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
33
+ unsigned size, MemTxAttrs attrs)
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)
34
+{
233
+{
35
+ /*
234
+ AddressSpace *as = &cs->gic->dma_as;
36
+ * From UG1085, Chapter 24 (Quad-SPI controllers):
235
+ uint64_t lpict_baddr;
37
+ * - Writes are ignored
236
+ uint8_t lpite;
38
+ * - AXI writes generate an external AXI slave error (SLVERR)
237
+ uint8_t prio;
39
+ */
238
+
40
+ qemu_log_mask(LOG_GUEST_ERROR, "%s Unexpected %u-bit access to 0x%" PRIx64
239
+ lpict_baddr = cs->gicr_propbaser & R_GICR_PROPBASER_PHYADDR_MASK;
41
+ " (value: 0x%" PRIx64 "\n",
240
+
42
+ __func__, size << 3, offset, value);
241
+ address_space_read(as, lpict_baddr + ((irq - GICV3_LPI_INTID_START) *
43
+
242
+ sizeof(lpite)), MEMTXATTRS_UNSPECIFIED, &lpite,
44
+ return MEMTX_ERROR;
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
+ }
45
+}
262
+}
46
+
263
+
47
static const MemoryRegionOps lqspi_ops = {
264
+void gicv3_redist_update_lpi(GICv3CPUState *cs)
48
.read_with_attrs = lqspi_read,
265
+{
49
+ .write_with_attrs = lqspi_write,
266
+ /*
50
.endianness = DEVICE_NATIVE_ENDIAN,
267
+ * This function scans the LPI pending table and for each pending
51
.valid = {
268
+ * LPI, reads the corresponding entry from LPI configuration table
52
.min_access_size = 1,
269
+ * to extract the priority info and determine if the current LPI
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
+ }
304
+ }
305
+}
306
+
307
+void gicv3_redist_lpi_pending(GICv3CPUState *cs, int irq, int level)
308
+{
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
{
372
/* Update redistributor state for a change in an external PPI input line */
53
--
373
--
54
2.20.1
374
2.20.1
55
375
56
376
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Shashi Mallela <shashi.mallela@linaro.org>
2
2
3
Both lqspi_read() and lqspi_load_cache() expect a 32-bit
3
Added expected IORT files applicable with latest GICv3
4
aligned address.
4
ITS changes.Temporarily differences in these files are
5
okay.
5
6
6
>From UG1085 datasheet [*] chapter on 'Quad-SPI Controller':
7
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
7
8
Acked-by: Igor Mammedov <imammedo@redhat.com>
8
Transfer Size Limitations
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
10
Message-id: 20210910143951.92242-8-shashi.mallela@linaro.org
10
Because of the 32-bit wide TX, RX, and generic FIFO, all
11
APB/AXI transfers must be an integer multiple of 4-bytes.
12
Shorter transfers are not possible.
13
14
Set MemoryRegionOps.impl values to force 32-bit accesses,
15
this way we are sure we do not access the lqspi_buf[] array
16
out of bound.
17
18
[*] https://www.xilinx.com/support/documentation/user_guides/ug1085-zynq-ultrascale-trm.pdf
19
20
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
21
Tested-by: Francisco Iglesias <frasse.iglesias@gmail.com>
22
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
---
12
---
25
hw/ssi/xilinx_spips.c | 4 ++++
13
tests/qtest/bios-tables-test-allowed-diff.h | 4 ++++
26
1 file changed, 4 insertions(+)
14
tests/data/acpi/virt/IORT | 0
15
tests/data/acpi/virt/IORT.memhp | 0
16
tests/data/acpi/virt/IORT.numamem | 0
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
27
23
28
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
24
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
29
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/ssi/xilinx_spips.c
26
--- a/tests/qtest/bios-tables-test-allowed-diff.h
31
+++ b/hw/ssi/xilinx_spips.c
27
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
32
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps lqspi_ops = {
28
@@ -1 +1,5 @@
33
.read_with_attrs = lqspi_read,
29
/* List of comma-separated changed AML files to ignore */
34
.write_with_attrs = lqspi_write,
30
+"tests/data/acpi/virt/IORT",
35
.endianness = DEVICE_NATIVE_ENDIAN,
31
+"tests/data/acpi/virt/IORT.memhp",
36
+ .impl = {
32
+"tests/data/acpi/virt/IORT.numamem",
37
+ .min_access_size = 4,
33
+"tests/data/acpi/virt/IORT.pxb",
38
+ .max_access_size = 4,
34
diff --git a/tests/data/acpi/virt/IORT b/tests/data/acpi/virt/IORT
39
+ },
35
new file mode 100644
40
.valid = {
36
index XXXXXXX..XXXXXXX
41
.min_access_size = 1,
37
diff --git a/tests/data/acpi/virt/IORT.memhp b/tests/data/acpi/virt/IORT.memhp
42
.max_access_size = 4
38
new file mode 100644
39
index XXXXXXX..XXXXXXX
40
diff --git a/tests/data/acpi/virt/IORT.numamem b/tests/data/acpi/virt/IORT.numamem
41
new file mode 100644
42
index XXXXXXX..XXXXXXX
43
diff --git a/tests/data/acpi/virt/IORT.pxb b/tests/data/acpi/virt/IORT.pxb
44
new file mode 100644
45
index XXXXXXX..XXXXXXX
43
--
46
--
44
2.20.1
47
2.20.1
45
48
46
49
diff view generated by jsdifflib
1
From: David Engraf <david.engraf@sysgo.com>
1
From: Shashi Mallela <shashi.mallela@linaro.org>
2
2
3
Using the whole 128 MiB flash in non-secure mode is not working because
3
Included creation of ITS as part of virt platform GIC
4
virt_flash_fdt() expects the same address for secure_sysmem and sysmem.
4
initialization. This Emulated ITS model now co-exists with kvm
5
This is not correctly handled by caller because it forwards NULL for
5
ITS and is enabled in absence of kvm irq kernel support in a
6
secure_sysmem in non-secure flash mode.
6
platform.
7
7
8
Fixed by using sysmem when secure_sysmem is NULL.
8
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
9
10
Signed-off-by: David Engraf <david.engraf@sysgo.com>
11
Message-id: 20190712075002.14326-1-david.engraf@sysgo.com
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20210910143951.92242-9-shashi.mallela@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
12
---
15
hw/arm/virt.c | 2 +-
13
include/hw/arm/virt.h | 2 ++
16
1 file changed, 1 insertion(+), 1 deletion(-)
14
target/arm/kvm_arm.h | 4 ++--
15
hw/arm/virt.c | 29 +++++++++++++++++++++++++++--
16
3 files changed, 31 insertions(+), 4 deletions(-)
17
17
18
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/arm/virt.h
21
+++ b/include/hw/arm/virt.h
22
@@ -XXX,XX +XXX,XX @@ struct VirtMachineClass {
23
MachineClass parent;
24
bool disallow_affinity_adjustment;
25
bool no_its;
26
+ bool no_tcg_its;
27
bool no_pmu;
28
bool claim_edge_triggered_timers;
29
bool smbios_old_sys_ver;
30
@@ -XXX,XX +XXX,XX @@ struct VirtMachineState {
31
bool highmem;
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
40
--- a/target/arm/kvm_arm.h
41
+++ b/target/arm/kvm_arm.h
42
@@ -XXX,XX +XXX,XX @@ static inline const char *its_class_name(void)
43
/* KVM implementation requires this capability */
44
return kvm_direct_msi_enabled() ? "arm-its-kvm" : NULL;
45
} else {
46
- /* Software emulation is not implemented yet */
47
- return NULL;
48
+ /* Software emulation based model */
49
+ return "arm-gicv3-its";
50
}
51
}
52
18
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
53
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
19
index XXXXXXX..XXXXXXX 100644
54
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/virt.c
55
--- a/hw/arm/virt.c
21
+++ b/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;
22
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
94
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
23
&machine->device_memory->mr);
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
+ }
24
}
113
}
25
114
26
- virt_flash_fdt(vms, sysmem, secure_sysmem);
115
/* Default disallows iommu instantiation */
27
+ virt_flash_fdt(vms, sysmem, secure_sysmem ?: sysmem);
116
@@ -XXX,XX +XXX,XX @@ DEFINE_VIRT_MACHINE_AS_LATEST(6, 2)
28
117
29
create_gic(vms, pic);
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)
30
129
31
--
130
--
32
2.20.1
131
2.20.1
33
132
34
133
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
From: Shashi Mallela <shashi.mallela@linaro.org>
2
2
3
When we converted to using feature bits in 602f6e42cfbf we missed out
3
Updated expected IORT files applicable with latest GICv3
4
the fact (dp && arm_dc_feature(s, ARM_FEATURE_V8)) was supported for
4
ITS changes.
5
-cpu max configurations. This caused a regression in the GCC test
6
suite. Fix this by setting the appropriate bits in mvfr1.FPHP to
7
report ARMv8-A with FP support (but not ARMv8.2-FP16).
8
5
9
Fixes: https://bugs.launchpad.net/qemu/+bug/1836078
6
Full diff of new file disassembly:
10
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
7
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
/*
12
Message-id: 20190711103737.10017-1-alex.bennee@linaro.org
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
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
89
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
90
---
15
target/arm/cpu.c | 4 ++++
91
tests/qtest/bios-tables-test-allowed-diff.h | 4 ----
16
1 file changed, 4 insertions(+)
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(-)
17
97
18
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
98
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
19
index XXXXXXX..XXXXXXX 100644
99
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.c
100
--- a/tests/qtest/bios-tables-test-allowed-diff.h
21
+++ b/target/arm/cpu.c
101
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
22
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
102
@@ -1,5 +1 @@
23
t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
103
/* List of comma-separated changed AML files to ignore */
24
cpu->isar.id_isar6 = t;
104
-"tests/data/acpi/virt/IORT",
25
105
-"tests/data/acpi/virt/IORT.memhp",
26
+ t = cpu->isar.mvfr1;
106
-"tests/data/acpi/virt/IORT.numamem",
27
+ t = FIELD_DP32(t, MVFR1, FPHP, 2); /* v8.0 FP support */
107
-"tests/data/acpi/virt/IORT.pxb",
28
+ cpu->isar.mvfr1 = t;
108
diff --git a/tests/data/acpi/virt/IORT b/tests/data/acpi/virt/IORT
29
+
109
index XXXXXXX..XXXXXXX 100644
30
t = cpu->isar.mvfr2;
110
GIT binary patch
31
t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
111
literal 124
32
t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
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
33
--
148
--
34
2.20.1
149
2.20.1
35
150
36
151
diff view generated by jsdifflib
1
In the M-profile architecture, when we do a vector table fetch and it
1
In v8A, the PSTATE.IL bit is set for various kinds of illegal
2
fails, we need to report a HardFault. Whether this is a Secure HF or
2
exception return or mode-change attempts. We already set PSTATE.IL
3
a NonSecure HF depends on several things. If AIRCR.BFHFNMINS is 0
3
(or its AArch32 equivalent CPSR.IL) in all those cases, but we
4
then HF is always Secure, because there is no NonSecure HardFault.
4
weren't implementing the part of the behaviour where attempting to
5
Otherwise, the answer depends on whether the 'underlying exception'
5
execute an instruction with PSTATE.IL takes an immediate exception
6
(MemManage, BusFault, SecureFault) targets Secure or NonSecure. (In
6
with an appropriate syndrome value.
7
the pseudocode, this is handled in the Vector() function: the final
8
exc.isSecure is calculated by looking at the exc.isSecure from the
9
exception returned from the memory access, not the isSecure input
10
argument.)
11
7
12
We weren't doing this correctly, because we were looking at
8
Add a new TB flags bit tracking PSTATE.IL/CPSR.IL, and generate code
13
the target security domain of the exception we were trying to
9
to take an exception instead of whatever the instruction would have
14
load the vector table entry for. This produces errors of two kinds:
10
been.
15
* a load from the NS vector table which hits the "NS access
16
to S memory" SecureFault should end up as a Secure HardFault,
17
but we were raising an NS HardFault
18
* a load from the S vector table which causes a BusFault
19
should raise an NS HardFault if BFHFNMINS == 1 (because
20
in that case all BusFaults are NonSecure), but we were raising
21
a Secure HardFault
22
11
23
Correct the logic.
12
PSTATE.IL and CPSR.IL change only on exception entry, attempted
24
13
exception exit, and various AArch32 mode changes via cpsr_write().
25
We also fix a comment error where we claimed that we might
14
These places generally already rebuild the hflags, so the only place
26
be escalating MemManage to HardFault, and forgot about SecureFault.
15
we need an extra rebuild_hflags call is in the illegal-return
27
(Vector loads can never hit MPU access faults, because they're
16
codepath of the AArch64 exception_return helper.
28
always aligned and always use the default address map.)
29
17
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
Message-id: 20190705094823.28905-1-peter.maydell@linaro.org
19
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20210821195958.41312-2-richard.henderson@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>
32
---
26
---
33
target/arm/m_helper.c | 21 +++++++++++++++++----
27
target/arm/cpu.h | 1 +
34
1 file changed, 17 insertions(+), 4 deletions(-)
28
target/arm/syndrome.h | 5 +++++
29
target/arm/translate.h | 2 ++
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
35
36
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
36
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
37
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/m_helper.c
38
--- a/target/arm/cpu.h
39
+++ b/target/arm/m_helper.c
39
+++ b/target/arm/cpu.h
40
@@ -XXX,XX +XXX,XX @@ static bool arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure,
40
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_ANY, FPEXC_EL, 8, 2)
41
if (sattrs.ns) {
41
FIELD(TBFLAG_ANY, DEBUG_TARGET_EL, 10, 2)
42
attrs.secure = false;
42
/* Memory operations require alignment: SCTLR_ELx.A or CCR.UNALIGN_TRP */
43
} else if (!targets_secure) {
43
FIELD(TBFLAG_ANY, ALIGN_MEM, 12, 1)
44
- /* NS access to S memory */
44
+FIELD(TBFLAG_ANY, PSTATE__IL, 13, 1)
45
+ /*
45
46
+ * NS access to S memory: the underlying exception which we escalate
46
/*
47
+ * to HardFault is SecureFault, which always targets Secure.
47
* Bit usage when in AArch32 state, both A- and M-profile.
48
+ */
48
diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h
49
+ exc_secure = true;
49
index XXXXXXX..XXXXXXX 100644
50
goto load_fail;
50
--- a/target/arm/syndrome.h
51
+++ b/target/arm/syndrome.h
52
@@ -XXX,XX +XXX,XX @@ static inline uint32_t syn_wfx(int cv, int cond, int ti, bool is_16bit)
53
(cv << 24) | (cond << 20) | ti;
54
}
55
56
+static inline uint32_t syn_illegalstate(void)
57
+{
58
+ return (EC_ILLEGALSTATE << ARM_EL_EC_SHIFT) | ARM_EL_IL;
59
+}
60
+
61
#endif /* TARGET_ARM_SYNDROME_H */
62
diff --git a/target/arm/translate.h b/target/arm/translate.h
63
index XXXXXXX..XXXXXXX 100644
64
--- a/target/arm/translate.h
65
+++ b/target/arm/translate.h
66
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
67
bool hstr_active;
68
/* True if memory operations require alignment */
69
bool align_mem;
70
+ /* True if PSTATE.IL is set */
71
+ bool pstate_il;
72
/*
73
* >= 0, a copy of PSTATE.BTYPE, which will be 0 without v8.5-BTI.
74
* < 0, set by the current instruction.
75
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/helper-a64.c
78
+++ b/target/arm/helper-a64.c
79
@@ -XXX,XX +XXX,XX @@ illegal_return:
80
if (!arm_singlestep_active(env)) {
81
env->pstate &= ~PSTATE_SS;
82
}
83
+ helper_rebuild_hflags_a64(env, cur_el);
84
qemu_log_mask(LOG_GUEST_ERROR, "Illegal exception return at EL%d: "
85
"resuming execution at 0x%" PRIx64 "\n", cur_el, env->pc);
86
}
87
diff --git a/target/arm/helper.c b/target/arm/helper.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/target/arm/helper.c
90
+++ b/target/arm/helper.c
91
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el,
92
DP_TBFLAG_A32(flags, HSTR_ACTIVE, 1);
93
}
94
95
+ if (env->uncached_cpsr & CPSR_IL) {
96
+ DP_TBFLAG_ANY(flags, PSTATE__IL, 1);
97
+ }
98
+
99
return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
100
}
101
102
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
51
}
103
}
52
}
104
}
53
@@ -XXX,XX +XXX,XX @@ static bool arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure,
105
54
vector_entry = address_space_ldl(arm_addressspace(cs, attrs), addr,
106
+ if (env->pstate & PSTATE_IL) {
55
attrs, &result);
107
+ DP_TBFLAG_ANY(flags, PSTATE__IL, 1);
56
if (result != MEMTX_OK) {
108
+ }
109
+
110
if (cpu_isar_feature(aa64_mte, env_archcpu(env))) {
111
/*
112
* Set MTE_ACTIVE if any access may be Checked, and leave clear
113
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
114
index XXXXXXX..XXXXXXX 100644
115
--- a/target/arm/translate-a64.c
116
+++ b/target/arm/translate-a64.c
117
@@ -XXX,XX +XXX,XX @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
118
s->fp_access_checked = false;
119
s->sve_access_checked = false;
120
121
+ if (s->pstate_il) {
57
+ /*
122
+ /*
58
+ * Underlying exception is BusFault: its target security state
123
+ * Illegal execution state. This has priority over BTI
59
+ * depends on BFHFNMINS.
124
+ * exceptions, but comes after instruction abort exceptions.
60
+ */
125
+ */
61
+ exc_secure = !(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK);
126
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
62
goto load_fail;
127
+ syn_illegalstate(), default_exception_el(s));
128
+ return;
129
+ }
130
+
131
if (dc_isar_feature(aa64_bti, s)) {
132
if (s->base.num_insns == 1) {
133
/*
134
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
135
#endif
136
dc->fp_excp_el = EX_TBFLAG_ANY(tb_flags, FPEXC_EL);
137
dc->align_mem = EX_TBFLAG_ANY(tb_flags, ALIGN_MEM);
138
+ dc->pstate_il = EX_TBFLAG_ANY(tb_flags, PSTATE__IL);
139
dc->sve_excp_el = EX_TBFLAG_A64(tb_flags, SVEEXC_EL);
140
dc->sve_len = (EX_TBFLAG_A64(tb_flags, ZCR_LEN) + 1) * 16;
141
dc->pauth_active = EX_TBFLAG_A64(tb_flags, PAUTH_ACTIVE);
142
diff --git a/target/arm/translate.c b/target/arm/translate.c
143
index XXXXXXX..XXXXXXX 100644
144
--- a/target/arm/translate.c
145
+++ b/target/arm/translate.c
146
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
147
return;
63
}
148
}
64
*pvec = vector_entry;
149
65
@@ -XXX,XX +XXX,XX @@ load_fail:
150
+ if (s->pstate_il) {
66
/*
151
+ /*
67
* All vector table fetch fails are reported as HardFault, with
152
+ * Illegal execution state. This has priority over BTI
68
* HFSR.VECTTBL and .FORCED set. (FORCED is set because
153
+ * exceptions, but comes after instruction abort exceptions.
69
- * technically the underlying exception is a MemManage or BusFault
154
+ */
70
+ * technically the underlying exception is a SecureFault or BusFault
155
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
71
* that is escalated to HardFault.) This is a terminal exception,
156
+ syn_illegalstate(), default_exception_el(s));
72
* so we will either take the HardFault immediately or else enter
157
+ return;
73
* lockup (the latter case is handled in armv7m_nvic_set_pending_derived()).
74
+ * The HardFault is Secure if BFHFNMINS is 0 (meaning that all HFs are
75
+ * secure); otherwise it targets the same security state as the
76
+ * underlying exception.
77
*/
78
- exc_secure = targets_secure ||
79
- !(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK);
80
+ if (!(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
81
+ exc_secure = true;
82
+ }
158
+ }
83
env->v7m.hfsr |= R_V7M_HFSR_VECTTBL_MASK | R_V7M_HFSR_FORCED_MASK;
159
+
84
armv7m_nvic_set_pending_derived(env->nvic, ARMV7M_EXCP_HARD, exc_secure);
160
if (cond == 0xf) {
85
return false;
161
/* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
162
* choose to UNDEF. In ARMv5 and above the space is used
163
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
164
#endif
165
dc->fp_excp_el = EX_TBFLAG_ANY(tb_flags, FPEXC_EL);
166
dc->align_mem = EX_TBFLAG_ANY(tb_flags, ALIGN_MEM);
167
+ dc->pstate_il = EX_TBFLAG_ANY(tb_flags, PSTATE__IL);
168
169
if (arm_feature(env, ARM_FEATURE_M)) {
170
dc->vfp_enabled = 1;
171
@@ -XXX,XX +XXX,XX @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
172
}
173
dc->insn = insn;
174
175
+ if (dc->pstate_il) {
176
+ /*
177
+ * Illegal execution state. This has priority over BTI
178
+ * exceptions, but comes after instruction abort exceptions.
179
+ */
180
+ gen_exception_insn(dc, dc->pc_curr, EXCP_UDEF,
181
+ syn_illegalstate(), default_exception_el(dc));
182
+ return;
183
+ }
184
+
185
if (dc->eci) {
186
/*
187
* For M-profile continuable instructions, ECI/ICI handling
86
--
188
--
87
2.20.1
189
2.20.1
88
190
89
191
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
In the previous commit we fixed a crash when the guest read a
3
It is confusing to have different exits from translation
4
register that pop from an empty FIFO.
4
for various conditions in separate functions.
5
By auditing the repository, we found another similar use with
5
6
an easy way to reproduce:
6
Merge disas_a64_insn into its only caller. Standardize
7
7
on the "s" name for the DisasContext, as the code from
8
$ qemu-system-aarch64 -M xlnx-zcu102 -monitor stdio -S
8
disas_a64_insn had more instances.
9
QEMU 4.0.50 monitor - type 'help' for more information
9
10
(qemu) xp/b 0xfd4a0134
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Aborted (core dumped)
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
12
Message-id: 20210821195958.41312-3-richard.henderson@linaro.org
13
(gdb) bt
14
#0 0x00007f6936dea57f in raise () at /lib64/libc.so.6
15
#1 0x00007f6936dd4895 in abort () at /lib64/libc.so.6
16
#2 0x0000561ad32975ec in xlnx_dp_aux_pop_rx_fifo (s=0x7f692babee70) at hw/display/xlnx_dp.c:431
17
#3 0x0000561ad3297dc0 in xlnx_dp_read (opaque=0x7f692babee70, offset=77, size=4) at hw/display/xlnx_dp.c:667
18
#4 0x0000561ad321b896 in memory_region_read_accessor (mr=0x7f692babf620, addr=308, value=0x7ffe05c1db88, size=4, shift=0, mask=4294967295, attrs=...) at memory.c:439
19
#5 0x0000561ad321bd70 in access_with_adjusted_size (addr=308, value=0x7ffe05c1db88, size=1, access_size_min=4, access_size_max=4, access_fn=0x561ad321b858 <memory_region_read_accessor>, mr=0x7f692babf620, attrs=...) at memory.c:569
20
#6 0x0000561ad321e9d5 in memory_region_dispatch_read1 (mr=0x7f692babf620, addr=308, pval=0x7ffe05c1db88, size=1, attrs=...) at memory.c:1420
21
#7 0x0000561ad321ea9d in memory_region_dispatch_read (mr=0x7f692babf620, addr=308, pval=0x7ffe05c1db88, size=1, attrs=...) at memory.c:1447
22
#8 0x0000561ad31bd742 in flatview_read_continue (fv=0x561ad69c04f0, addr=4249485620, attrs=..., buf=0x7ffe05c1dcf0 "\020\335\301\005\376\177", len=1, addr1=308, l=1, mr=0x7f692babf620) at exec.c:3385
23
#9 0x0000561ad31bd895 in flatview_read (fv=0x561ad69c04f0, addr=4249485620, attrs=..., buf=0x7ffe05c1dcf0 "\020\335\301\005\376\177", len=1) at exec.c:3423
24
#10 0x0000561ad31bd90b in address_space_read_full (as=0x561ad5bb3020, addr=4249485620, attrs=..., buf=0x7ffe05c1dcf0 "\020\335\301\005\376\177", len=1) at exec.c:3436
25
#11 0x0000561ad33b1c42 in address_space_read (len=1, buf=0x7ffe05c1dcf0 "\020\335\301\005\376\177", attrs=..., addr=4249485620, as=0x561ad5bb3020) at include/exec/memory.h:2131
26
#12 0x0000561ad33b1c42 in memory_dump (mon=0x561ad59c4530, count=1, format=120, wsize=1, addr=4249485620, is_physical=1) at monitor/misc.c:723
27
#13 0x0000561ad33b1fc1 in hmp_physical_memory_dump (mon=0x561ad59c4530, qdict=0x561ad6c6fd00) at monitor/misc.c:795
28
#14 0x0000561ad37b4a9f in handle_hmp_command (mon=0x561ad59c4530, cmdline=0x561ad59d0f22 "/b 0x00000000fd4a0134") at monitor/hmp.c:1082
29
30
Fix by checking the FIFO is not empty before popping from it.
31
32
The datasheet is not clear about the reset value of this register,
33
we choose to return '0'.
34
35
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
36
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
37
Message-id: 20190709113715.7761-4-philmd@redhat.com
38
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
39
---
14
---
40
hw/display/xlnx_dp.c | 15 +++++++++++----
15
target/arm/translate-a64.c | 224 ++++++++++++++++++-------------------
41
1 file changed, 11 insertions(+), 4 deletions(-)
16
1 file changed, 109 insertions(+), 115 deletions(-)
42
17
43
diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c
18
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
44
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/display/xlnx_dp.c
20
--- a/target/arm/translate-a64.c
46
+++ b/hw/display/xlnx_dp.c
21
+++ b/target/arm/translate-a64.c
47
@@ -XXX,XX +XXX,XX @@ static uint8_t xlnx_dp_aux_pop_rx_fifo(XlnxDPState *s)
22
@@ -XXX,XX +XXX,XX @@ static bool btype_destination_ok(uint32_t insn, bool bt, int btype)
48
uint8_t ret;
23
return false;
49
24
}
50
if (fifo8_is_empty(&s->rx_fifo)) {
25
51
- DPRINTF("rx_fifo underflow..\n");
26
-/* C3.1 A64 instruction index by encoding */
52
- abort();
27
-static void disas_a64_insn(CPUARMState *env, DisasContext *s)
53
+ qemu_log_mask(LOG_GUEST_ERROR,
28
-{
54
+ "%s: Reading empty RX_FIFO\n",
29
- uint32_t insn;
55
+ __func__);
30
-
31
- s->pc_curr = s->base.pc_next;
32
- insn = arm_ldl_code(env, s->base.pc_next, s->sctlr_b);
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
-
124
- /*
125
- * After execution of most insns, btype is reset to 0.
126
- * Note that we set btype == -1 when the insn sets btype.
127
- */
128
- if (s->btype > 0 && s->base.is_jmp != DISAS_NORETURN) {
129
- reset_btype(s);
130
- }
131
-}
132
-
133
static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
134
CPUState *cpu)
135
{
136
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
137
138
static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
139
{
140
- DisasContext *dc = container_of(dcbase, DisasContext, base);
141
+ DisasContext *s = container_of(dcbase, DisasContext, base);
142
CPUARMState *env = cpu->env_ptr;
143
+ uint32_t insn;
144
145
- if (dc->ss_active && !dc->pstate_ss) {
146
+ if (s->ss_active && !s->pstate_ss) {
147
/* Singlestep state is Active-pending.
148
* If we're in this state at the start of a TB then either
149
* a) we just took an exception to an EL which is being debugged
150
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
151
* "did not step an insn" case, and so the syndrome ISV and EX
152
* bits should be zero.
153
*/
154
- assert(dc->base.num_insns == 1);
155
- gen_swstep_exception(dc, 0, 0);
156
- dc->base.is_jmp = DISAS_NORETURN;
157
- } else {
158
- disas_a64_insn(env, dc);
159
+ assert(s->base.num_insns == 1);
160
+ gen_swstep_exception(s, 0, 0);
161
+ s->base.is_jmp = DISAS_NORETURN;
162
+ return;
163
}
164
165
- translator_loop_temp_check(&dc->base);
166
+ s->pc_curr = s->base.pc_next;
167
+ insn = arm_ldl_code(env, s->base.pc_next, s->sctlr_b);
168
+ s->insn = insn;
169
+ s->base.pc_next += 4;
170
+
171
+ s->fp_access_checked = false;
172
+ s->sve_access_checked = false;
173
+
174
+ if (s->pstate_il) {
56
+ /*
175
+ /*
57
+ * The datasheet is not clear about the reset value, it seems
176
+ * Illegal execution state. This has priority over BTI
58
+ * to be unspecified. We choose to return '0'.
177
+ * exceptions, but comes after instruction abort exceptions.
59
+ */
178
+ */
60
+ ret = 0;
179
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
61
+ } else {
180
+ syn_illegalstate(), default_exception_el(s));
62
+ ret = fifo8_pop(&s->rx_fifo);
181
+ return;
63
+ DPRINTF("pop 0x%" PRIX8 " from rx_fifo.\n", ret);
182
+ }
64
}
183
+
65
- ret = fifo8_pop(&s->rx_fifo);
184
+ if (dc_isar_feature(aa64_bti, s)) {
66
- DPRINTF("pop 0x%" PRIX8 " from rx_fifo.\n", ret);
185
+ if (s->base.num_insns == 1) {
67
return ret;
186
+ /*
187
+ * At the first insn of the TB, compute s->guarded_page.
188
+ * We delayed computing this until successfully reading
189
+ * the first insn of the TB, above. This (mostly) ensures
190
+ * that the softmmu tlb entry has been populated, and the
191
+ * page table GP bit is available.
192
+ *
193
+ * Note that we need to compute this even if btype == 0,
194
+ * because this value is used for BR instructions later
195
+ * where ENV is not available.
196
+ */
197
+ s->guarded_page = is_guarded_page(env, s);
198
+
199
+ /* First insn can have btype set to non-zero. */
200
+ tcg_debug_assert(s->btype >= 0);
201
+
202
+ /*
203
+ * Note that the Branch Target Exception has fairly high
204
+ * priority -- below debugging exceptions but above most
205
+ * everything else. This allows us to handle this now
206
+ * instead of waiting until the insn is otherwise decoded.
207
+ */
208
+ if (s->btype != 0
209
+ && s->guarded_page
210
+ && !btype_destination_ok(insn, s->bt, s->btype)) {
211
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
212
+ syn_btitrap(s->btype),
213
+ default_exception_el(s));
214
+ return;
215
+ }
216
+ } else {
217
+ /* Not the first insn: btype must be 0. */
218
+ tcg_debug_assert(s->btype == 0);
219
+ }
220
+ }
221
+
222
+ switch (extract32(insn, 25, 4)) {
223
+ case 0x0: case 0x1: case 0x3: /* UNALLOCATED */
224
+ unallocated_encoding(s);
225
+ break;
226
+ case 0x2:
227
+ if (!dc_isar_feature(aa64_sve, s) || !disas_sve(s, insn)) {
228
+ unallocated_encoding(s);
229
+ }
230
+ break;
231
+ case 0x8: case 0x9: /* Data processing - immediate */
232
+ disas_data_proc_imm(s, insn);
233
+ break;
234
+ case 0xa: case 0xb: /* Branch, exception generation and system insns */
235
+ disas_b_exc_sys(s, insn);
236
+ break;
237
+ case 0x4:
238
+ case 0x6:
239
+ case 0xc:
240
+ case 0xe: /* Loads and stores */
241
+ disas_ldst(s, insn);
242
+ break;
243
+ case 0x5:
244
+ case 0xd: /* Data processing - register */
245
+ disas_data_proc_reg(s, insn);
246
+ break;
247
+ case 0x7:
248
+ case 0xf: /* Data processing - SIMD and floating point */
249
+ disas_data_proc_simd_fp(s, insn);
250
+ break;
251
+ default:
252
+ assert(FALSE); /* all 15 cases should be handled above */
253
+ break;
254
+ }
255
+
256
+ /* if we allocated any temporaries, free them here */
257
+ free_tmp_a64(s);
258
+
259
+ /*
260
+ * After execution of most insns, btype is reset to 0.
261
+ * Note that we set btype == -1 when the insn sets btype.
262
+ */
263
+ if (s->btype > 0 && s->base.is_jmp != DISAS_NORETURN) {
264
+ reset_btype(s);
265
+ }
266
+
267
+ translator_loop_temp_check(&s->base);
68
}
268
}
69
269
270
static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
70
--
271
--
71
2.20.1
272
2.20.1
72
273
73
274
diff view generated by jsdifflib
New patch
1
By default, QEMU will allow devices to be plugged into a bus up to
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.
1
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
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Message-id: 20210903151435.22379-2-peter.maydell@linaro.org
21
---
22
include/hw/qdev-core.h | 24 ++++++++++++++++++++++++
23
softmmu/qdev-monitor.c | 7 ++++++-
24
2 files changed, 30 insertions(+), 1 deletion(-)
25
26
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/include/hw/qdev-core.h
29
+++ b/include/hw/qdev-core.h
30
@@ -XXX,XX +XXX,XX @@ struct BusState {
31
HotplugHandler *hotplug_handler;
32
int max_index;
33
bool realized;
34
+ bool full;
35
int num_children;
36
37
/*
38
@@ -XXX,XX +XXX,XX @@ static inline bool qbus_is_hotpluggable(BusState *bus)
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
70
--- a/softmmu/qdev-monitor.c
71
+++ b/softmmu/qdev-monitor.c
72
@@ -XXX,XX +XXX,XX @@ static DeviceState *qbus_find_dev(BusState *bus, char *elem)
73
74
static inline bool qbus_is_full(BusState *bus)
75
{
76
- BusClass *bus_class = BUS_GET_CLASS(bus);
77
+ BusClass *bus_class;
78
+
79
+ if (bus->full) {
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
--
87
2.20.1
88
89
diff view generated by jsdifflib
New patch
1
The mps2-tz boards use a data-driven structure to create the devices
2
that sit behind peripheral protection controllers. Currently the
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.
1
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
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
22
Message-id: 20210903151435.22379-3-peter.maydell@linaro.org
23
---
24
hw/arm/mps2-tz.c | 35 ++++++++++++++++++++++-------------
25
1 file changed, 22 insertions(+), 13 deletions(-)
26
27
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/arm/mps2-tz.c
30
+++ b/hw/arm/mps2-tz.c
31
@@ -XXX,XX +XXX,XX @@ static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
32
}
33
}
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
--
172
2.20.1
173
174
diff view generated by jsdifflib
1
The ARMv5 architecture didn't specify detailed per-feature ID
1
The various MPS2 boards have multiple I2C buses: typically a bus
2
registers. Now that we're using the MVFR0 register fields to
2
dedicated to the audio configuration, one for the LCD touchscreen
3
gate the existence of VFP instructions, we need to set up
3
controller, one for a DDR4 EEPROM, and two which are connected to the
4
the correct values in the cpu->isar structure so that we still
4
external Shield expansion connector. Mark the buses which are used
5
provide an FPU to the guest.
5
only for board-internal devices as 'full' so that if the user creates
6
i2c devices on the commandline without specifying a bus name then
7
they will be connected to the I2C controller used for the Shield
8
connector, where guest software will expect them.
6
9
7
This fixes a regression in the arm926 and arm1026 CPUs, which
8
are the only ones that both have VFP and are ARMv5 or earlier.
9
This regression was introduced by the VFP refactoring, and more
10
specifically by commits 1120827fa182f0e76 and 266bd25c485597c,
11
which accidentally disabled VFP short-vector support and
12
double-precision support on these CPUs.
13
14
Fixes: 1120827fa182f0e
15
Fixes: 266bd25c485597c
16
Fixes: https://bugs.launchpad.net/qemu/+bug/1836192
17
Reported-by: Christophe Lyon <christophe.lyon@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Message-id: 20210903151435.22379-4-peter.maydell@linaro.org
21
Tested-by: Christophe Lyon <christophe.lyon@linaro.org>
22
Message-id: 20190711131241.22231-1-peter.maydell@linaro.org
23
---
13
---
24
target/arm/cpu.c | 12 ++++++++++++
14
hw/arm/mps2-tz.c | 57 ++++++++++++++++++++++++++++++++++++------------
25
1 file changed, 12 insertions(+)
15
1 file changed, 43 insertions(+), 14 deletions(-)
26
16
27
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
17
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
28
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/cpu.c
19
--- a/hw/arm/mps2-tz.c
30
+++ b/target/arm/cpu.c
20
+++ b/hw/arm/mps2-tz.c
31
@@ -XXX,XX +XXX,XX @@ static void arm926_initfn(Object *obj)
21
@@ -XXX,XX +XXX,XX @@ static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
32
* set the field to indicate Jazelle support within QEMU.
22
33
*/
23
/* Union describing the device-specific extra data we pass to the devfn. */
34
cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1);
24
typedef union PPCExtraData {
25
+ bool i2c_internal;
26
} PPCExtraData;
27
28
/* Most of the devices in the AN505 FPGA image sit behind
29
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
30
object_initialize_child(OBJECT(mms), name, i2c, TYPE_ARM_SBCON_I2C);
31
s = SYS_BUS_DEVICE(i2c);
32
sysbus_realize(s, &error_fatal);
33
+
35
+ /*
34
+ /*
36
+ * Similarly, we need to set MVFR0 fields to enable double precision
35
+ * If this is an internal-use-only i2c bus, mark it full
37
+ * and short vector support even though ARMv5 doesn't have this register.
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.
38
+ */
41
+ */
39
+ cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
42
+ if (extradata->i2c_internal) {
40
+ cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1);
43
+ BusState *qbus = qdev_get_child_bus(DEVICE(i2c), "i2c");
44
+ qbus_mark_full(qbus);
45
+ }
46
+
47
return sysbus_mmio_get_region(s, 0);
41
}
48
}
42
49
43
static void arm946_initfn(Object *obj)
50
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
44
@@ -XXX,XX +XXX,XX @@ static void arm1026_initfn(Object *obj)
51
{ "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000, { 36, 37, 44 } },
45
* set the field to indicate Jazelle support within QEMU.
52
{ "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000, { 38, 39, 45 } },
46
*/
53
{ "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000, { 40, 41, 46 } },
47
cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1);
54
- { "i2c0", make_i2c, &mms->i2c[0], 0x40207000, 0x1000 },
48
+ /*
55
- { "i2c1", make_i2c, &mms->i2c[1], 0x40208000, 0x1000 },
49
+ * Similarly, we need to set MVFR0 fields to enable double precision
56
- { "i2c2", make_i2c, &mms->i2c[2], 0x4020c000, 0x1000 },
50
+ * and short vector support even though ARMv5 doesn't have this register.
57
- { "i2c3", make_i2c, &mms->i2c[3], 0x4020d000, 0x1000 },
51
+ */
58
+ { "i2c0", make_i2c, &mms->i2c[0], 0x40207000, 0x1000, {},
52
+ cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
59
+ { .i2c_internal = true /* touchscreen */ } },
53
+ cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1);
60
+ { "i2c1", make_i2c, &mms->i2c[1], 0x40208000, 0x1000, {},
54
61
+ { .i2c_internal = true /* audio conf */ } },
55
{
62
+ { "i2c2", make_i2c, &mms->i2c[2], 0x4020c000, 0x1000, {},
56
/* The 1026 had an IFAR at c6,c0,0,1 rather than the ARMv6 c6,c0,0,2 */
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",
57
--
121
--
58
2.20.1
122
2.20.1
59
123
60
124
diff view generated by jsdifflib
New patch
1
The various MPS2 boards implemented in mps2.c have multiple I2C
2
buses: a bus dedicated to the audio configuration, one for the LCD
3
touchscreen controller, and two which are connected to the external
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.
1
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210903151435.22379-5-peter.maydell@linaro.org
13
---
14
hw/arm/mps2.c | 12 +++++++++++-
15
1 file changed, 11 insertions(+), 1 deletion(-)
16
17
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/mps2.c
20
+++ b/hw/arm/mps2.c
21
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
22
0x40023000, /* Audio */
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
}
38
create_unimplemented_device("i2s", 0x40024000, 0x400);
39
40
--
41
2.20.1
42
43
diff view generated by jsdifflib