* [PULL 1/5] hw/sd: Fix sun4i allwinner-sdhost for U-Boot
2022-11-21 13:02 [PULL 0/5] target-arm queue Peter Maydell
@ 2022-11-21 13:02 ` Peter Maydell
2022-11-21 13:02 ` [PULL 2/5] hw/intc: clean-up access to GIC multi-byte registers Peter Maydell
` (4 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Peter Maydell @ 2022-11-21 13:02 UTC (permalink / raw)
To: qemu-devel
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
Trying to run U-Boot for Cubieboard (Allwinner A10) fails because it cannot
access SD card. The problem is that FIFO register in current
allwinner-sdhost implementation is at the address corresponding to
Allwinner H3, but not A10.
Linux kernel is not affected since Linux driver uses DMA access and does
not use FIFO register for reading/writing.
This patch adds new class parameter `is_sun4i` and based on that
parameter uses register at offset 0x100 either as FIFO register (if
sun4i) or as threshold register (if not sun4i; in this case register at
0x200 is FIFO register).
Tested with U-Boot and Linux kernel image built for Cubieboard and
OrangePi PC.
Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20221112214900.24152-1-strahinja.p.jankovic@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
include/hw/sd/allwinner-sdhost.h | 1 +
hw/sd/allwinner-sdhost.c | 67 ++++++++++++++++++++++----------
2 files changed, 47 insertions(+), 21 deletions(-)
diff --git a/include/hw/sd/allwinner-sdhost.h b/include/hw/sd/allwinner-sdhost.h
index bfe08ff4ef2..30c1e604041 100644
--- a/include/hw/sd/allwinner-sdhost.h
+++ b/include/hw/sd/allwinner-sdhost.h
@@ -130,6 +130,7 @@ struct AwSdHostClass {
/** Maximum buffer size in bytes per DMA descriptor */
size_t max_desc_size;
+ bool is_sun4i;
};
diff --git a/hw/sd/allwinner-sdhost.c b/hw/sd/allwinner-sdhost.c
index 455d6eabf64..51e5e908307 100644
--- a/hw/sd/allwinner-sdhost.c
+++ b/hw/sd/allwinner-sdhost.c
@@ -65,7 +65,7 @@ enum {
REG_SD_DLBA = 0x84, /* Descriptor List Base Address */
REG_SD_IDST = 0x88, /* Internal DMA Controller Status */
REG_SD_IDIE = 0x8C, /* Internal DMA Controller IRQ Enable */
- REG_SD_THLDC = 0x100, /* Card Threshold Control */
+ REG_SD_THLDC = 0x100, /* Card Threshold Control / FIFO (sun4i only)*/
REG_SD_DSBD = 0x10C, /* eMMC DDR Start Bit Detection Control */
REG_SD_RES_CRC = 0x110, /* Response CRC from card/eMMC */
REG_SD_DATA7_CRC = 0x114, /* CRC Data 7 from card/eMMC */
@@ -415,10 +415,29 @@ static void allwinner_sdhost_dma(AwSdHostState *s)
}
}
+static uint32_t allwinner_sdhost_fifo_read(AwSdHostState *s)
+{
+ uint32_t res = 0;
+
+ if (sdbus_data_ready(&s->sdbus)) {
+ sdbus_read_data(&s->sdbus, &res, sizeof(uint32_t));
+ le32_to_cpus(&res);
+ allwinner_sdhost_update_transfer_cnt(s, sizeof(uint32_t));
+ allwinner_sdhost_auto_stop(s);
+ allwinner_sdhost_update_irq(s);
+ } else {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: no data ready on SD bus\n",
+ __func__);
+ }
+
+ return res;
+}
+
static uint64_t allwinner_sdhost_read(void *opaque, hwaddr offset,
unsigned size)
{
AwSdHostState *s = AW_SDHOST(opaque);
+ AwSdHostClass *sc = AW_SDHOST_GET_CLASS(s);
uint32_t res = 0;
switch (offset) {
@@ -508,8 +527,12 @@ static uint64_t allwinner_sdhost_read(void *opaque, hwaddr offset,
case REG_SD_IDIE: /* Internal DMA Controller Interrupt Enable */
res = s->dmac_irq;
break;
- case REG_SD_THLDC: /* Card Threshold Control */
- res = s->card_threshold;
+ case REG_SD_THLDC: /* Card Threshold Control or FIFO register (sun4i) */
+ if (sc->is_sun4i) {
+ res = allwinner_sdhost_fifo_read(s);
+ } else {
+ res = s->card_threshold;
+ }
break;
case REG_SD_DSBD: /* eMMC DDR Start Bit Detection Control */
res = s->startbit_detect;
@@ -531,16 +554,7 @@ static uint64_t allwinner_sdhost_read(void *opaque, hwaddr offset,
res = s->status_crc;
break;
case REG_SD_FIFO: /* Read/Write FIFO */
- if (sdbus_data_ready(&s->sdbus)) {
- sdbus_read_data(&s->sdbus, &res, sizeof(uint32_t));
- le32_to_cpus(&res);
- allwinner_sdhost_update_transfer_cnt(s, sizeof(uint32_t));
- allwinner_sdhost_auto_stop(s);
- allwinner_sdhost_update_irq(s);
- } else {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: no data ready on SD bus\n",
- __func__);
- }
+ res = allwinner_sdhost_fifo_read(s);
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset %"
@@ -553,11 +567,20 @@ static uint64_t allwinner_sdhost_read(void *opaque, hwaddr offset,
return res;
}
+static void allwinner_sdhost_fifo_write(AwSdHostState *s, uint64_t value)
+{
+ uint32_t u32 = cpu_to_le32(value);
+ sdbus_write_data(&s->sdbus, &u32, sizeof(u32));
+ allwinner_sdhost_update_transfer_cnt(s, sizeof(u32));
+ allwinner_sdhost_auto_stop(s);
+ allwinner_sdhost_update_irq(s);
+}
+
static void allwinner_sdhost_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
AwSdHostState *s = AW_SDHOST(opaque);
- uint32_t u32;
+ AwSdHostClass *sc = AW_SDHOST_GET_CLASS(s);
trace_allwinner_sdhost_write(offset, value, size);
@@ -657,18 +680,18 @@ static void allwinner_sdhost_write(void *opaque, hwaddr offset,
s->dmac_irq = value;
allwinner_sdhost_update_irq(s);
break;
- case REG_SD_THLDC: /* Card Threshold Control */
- s->card_threshold = value;
+ case REG_SD_THLDC: /* Card Threshold Control or FIFO (sun4i) */
+ if (sc->is_sun4i) {
+ allwinner_sdhost_fifo_write(s, value);
+ } else {
+ s->card_threshold = value;
+ }
break;
case REG_SD_DSBD: /* eMMC DDR Start Bit Detection Control */
s->startbit_detect = value;
break;
case REG_SD_FIFO: /* Read/Write FIFO */
- u32 = cpu_to_le32(value);
- sdbus_write_data(&s->sdbus, &u32, sizeof(u32));
- allwinner_sdhost_update_transfer_cnt(s, sizeof(u32));
- allwinner_sdhost_auto_stop(s);
- allwinner_sdhost_update_irq(s);
+ allwinner_sdhost_fifo_write(s, value);
break;
case REG_SD_RES_CRC: /* Response CRC from card/eMMC */
case REG_SD_DATA7_CRC: /* CRC Data 7 from card/eMMC */
@@ -834,12 +857,14 @@ static void allwinner_sdhost_sun4i_class_init(ObjectClass *klass, void *data)
{
AwSdHostClass *sc = AW_SDHOST_CLASS(klass);
sc->max_desc_size = 8 * KiB;
+ sc->is_sun4i = true;
}
static void allwinner_sdhost_sun5i_class_init(ObjectClass *klass, void *data)
{
AwSdHostClass *sc = AW_SDHOST_CLASS(klass);
sc->max_desc_size = 64 * KiB;
+ sc->is_sun4i = false;
}
static const TypeInfo allwinner_sdhost_info = {
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PULL 2/5] hw/intc: clean-up access to GIC multi-byte registers
2022-11-21 13:02 [PULL 0/5] target-arm queue Peter Maydell
2022-11-21 13:02 ` [PULL 1/5] hw/sd: Fix sun4i allwinner-sdhost for U-Boot Peter Maydell
@ 2022-11-21 13:02 ` Peter Maydell
2022-11-21 13:02 ` [PULL 3/5] hw/intc: add implementation of GICD_IIDR to Arm GIC Peter Maydell
` (3 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Peter Maydell @ 2022-11-21 13:02 UTC (permalink / raw)
To: qemu-devel
From: Alex Bennée <alex.bennee@linaro.org>
gic_dist_readb was returning a word value which just happened to work
as a result of the way we OR the data together. Lets fix it so only
the explicit byte is returned for each part of GICD_TYPER. I've
changed the return type to uint8_t although the overflow is only
detected with an explicit -Wconversion.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
hw/intc/arm_gic.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index 492b2421ab4..1a04144c38b 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -941,7 +941,7 @@ static void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
gic_update(s);
}
-static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
+static uint8_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
{
GICState *s = (GICState *)opaque;
uint32_t res;
@@ -955,6 +955,7 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
cm = 1 << cpu;
if (offset < 0x100) {
if (offset == 0) { /* GICD_CTLR */
+ /* We rely here on the only non-zero bits being in byte 0 */
if (s->security_extn && !attrs.secure) {
/* The NS bank of this register is just an alias of the
* EnableGrp1 bit in the S bank version.
@@ -964,11 +965,14 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
return s->ctlr;
}
}
- if (offset == 4)
- /* Interrupt Controller Type Register */
- return ((s->num_irq / 32) - 1)
- | ((s->num_cpu - 1) << 5)
- | (s->security_extn << 10);
+ if (offset == 4) {
+ /* GICD_TYPER byte 0 */
+ return ((s->num_irq / 32) - 1) | ((s->num_cpu - 1) << 5);
+ }
+ if (offset == 5) {
+ /* GICD_TYPER byte 1 */
+ return (s->security_extn << 2);
+ }
if (offset < 0x08)
return 0;
if (offset >= 0x80) {
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PULL 5/5] target/arm: Limit LPA2 effective output address when TCR.DS == 0
2022-11-21 13:02 [PULL 0/5] target-arm queue Peter Maydell
` (3 preceding siblings ...)
2022-11-21 13:02 ` [PULL 4/5] tests/avocado/boot_linux.py: Bump aarch64 virt test timeout to 720s Peter Maydell
@ 2022-11-21 13:02 ` Peter Maydell
2022-11-21 15:54 ` [PULL 0/5] target-arm queue Stefan Hajnoczi
5 siblings, 0 replies; 9+ messages in thread
From: Peter Maydell @ 2022-11-21 13:02 UTC (permalink / raw)
To: qemu-devel
From: Ard Biesheuvel <ardb@kernel.org>
With LPA2, the effective output address size is at most 48 bits when
TCR.DS == 0. This case is currently unhandled in the page table walker,
where we happily assume LVA/64k granule when outputsize > 48 and
param.ds == 0, resulting in the wrong conversion to be used from a
page table descriptor to a physical address.
if (outputsize > 48) {
if (param.ds) {
descaddr |= extract64(descriptor, 8, 2) << 50;
} else {
descaddr |= extract64(descriptor, 12, 4) << 48;
}
So cap the outputsize to 48 when TCR.DS is cleared, as per the
architecture.
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
Cc: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20221116170316.259695-1-ardb@kernel.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target/arm/ptw.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 3745ac97234..9a6277d862f 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -1222,6 +1222,14 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
ps = MIN(ps, param.ps);
assert(ps < ARRAY_SIZE(pamax_map));
outputsize = pamax_map[ps];
+
+ /*
+ * With LPA2, the effective output address (OA) size is at most 48 bits
+ * unless TCR.DS == 1
+ */
+ if (!param.ds && param.gran != Gran64K) {
+ outputsize = MIN(outputsize, 48);
+ }
} else {
param = aa32_va_parameters(env, address, mmu_idx);
level = 1;
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread