public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Daniel Palmer <daniel@thingy.jp>
To: visitorckw@gmail.com, angelo@kernel-space.org, bmeng.cn@gmail.com
Cc: laurent@vivier.eu, u-boot@lists.denx.de, Daniel Palmer <daniel@0x0f.com>
Subject: [RFC PATCH 2/3] virtio: mmio: endian *fixes* *HACK*
Date: Tue, 10 Mar 2026 22:59:39 +0900	[thread overview]
Message-ID: <20260310135940.1756141-3-daniel@thingy.jp> (raw)
In-Reply-To: <20260310135940.1756141-1-daniel@thingy.jp>

From: Daniel Palmer <daniel@0x0f.com>

This is an attempt to *fix* virtio mmio on the QEMU m68k virt machine.
As far as I can tell all of the registers in the virtio mmio regions
should be little endian so after reading them they need to be converted
to big endian for the code to work on them? other parts of the code
are also doing endian conversion so I'm not sure.

Or QEMU is incorrectly giving big endian register values?
---
 drivers/virtio/virtio_mmio.c | 114 +++++++++++++++++++++--------------
 1 file changed, 68 insertions(+), 46 deletions(-)

diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index 28b46ab66238..2cf85fdab4ed 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -19,6 +19,27 @@
 #include <linux/io.h>
 #include "virtio_mmio.h"
 
+static inline u32 virtio_mmio_readl(void *addr)
+{
+	return in_le32(addr);
+}
+
+static inline u16 virtio_mmio_readw(void *addr)
+{
+	return in_le16(addr);
+}
+
+static inline void virtio_mmio_writel(u32 val, void *addr)
+{
+	out_le32(addr, val);
+}
+
+static inline void virtio_mmio_writew(u32 val, void *addr)
+{
+	out_le16(addr, val);
+}
+
+
 static int virtio_mmio_get_config(struct udevice *udev, unsigned int offset,
 				  void *buf, unsigned int len)
 {
@@ -44,17 +65,17 @@ static int virtio_mmio_get_config(struct udevice *udev, unsigned int offset,
 		memcpy(buf, &b, sizeof(b));
 		break;
 	case 2:
-		w = cpu_to_le16(readw(base + offset));
+		w = cpu_to_le16(virtio_mmio_readw(base + offset));
 		memcpy(buf, &w, sizeof(w));
 		break;
 	case 4:
-		l = cpu_to_le32(readl(base + offset));
+		l = cpu_to_le32(virtio_mmio_readl(base + offset));
 		memcpy(buf, &l, sizeof(l));
 		break;
 	case 8:
-		l = cpu_to_le32(readl(base + offset));
+		l = cpu_to_le32(virtio_mmio_readl(base + offset));
 		memcpy(buf, &l, sizeof(l));
-		l = cpu_to_le32(readl(base + offset + sizeof(l)));
+		l = cpu_to_le32(virtio_mmio_readl(base + offset + sizeof(l)));
 		memcpy(buf + sizeof(l), &l, sizeof(l));
 		break;
 	default:
@@ -90,17 +111,17 @@ static int virtio_mmio_set_config(struct udevice *udev, unsigned int offset,
 		break;
 	case 2:
 		memcpy(&w, buf, sizeof(w));
-		writew(le16_to_cpu(w), base + offset);
+		virtio_mmio_writew(le16_to_cpu(w), base + offset);
 		break;
 	case 4:
 		memcpy(&l, buf, sizeof(l));
-		writel(le32_to_cpu(l), base + offset);
+		virtio_mmio_writel(le32_to_cpu(l), base + offset);
 		break;
 	case 8:
 		memcpy(&l, buf, sizeof(l));
-		writel(le32_to_cpu(l), base + offset);
+		virtio_mmio_writel(le32_to_cpu(l), base + offset);
 		memcpy(&l, buf + sizeof(l), sizeof(l));
-		writel(le32_to_cpu(l), base + offset + sizeof(l));
+		virtio_mmio_writel(le32_to_cpu(l), base + offset + sizeof(l));
 		break;
 	default:
 		WARN_ON(true);
@@ -116,7 +137,7 @@ static int virtio_mmio_generation(struct udevice *udev, u32 *counter)
 	if (priv->version == 1)
 		*counter = 0;
 	else
-		*counter = readl(priv->base + VIRTIO_MMIO_CONFIG_GENERATION);
+		*counter = virtio_mmio_readl(priv->base + VIRTIO_MMIO_CONFIG_GENERATION);
 
 	return 0;
 }
@@ -125,7 +146,7 @@ static int virtio_mmio_get_status(struct udevice *udev, u8 *status)
 {
 	struct virtio_mmio_priv *priv = dev_get_priv(udev);
 
-	*status = readl(priv->base + VIRTIO_MMIO_STATUS) & 0xff;
+	*status = virtio_mmio_readl(priv->base + VIRTIO_MMIO_STATUS) & 0xff;
 
 	return 0;
 }
@@ -137,7 +158,7 @@ static int virtio_mmio_set_status(struct udevice *udev, u8 status)
 	/* We should never be setting status to 0 */
 	WARN_ON(status == 0);
 
-	writel(status, priv->base + VIRTIO_MMIO_STATUS);
+	virtio_mmio_writel(status, priv->base + VIRTIO_MMIO_STATUS);
 
 	return 0;
 }
@@ -147,7 +168,7 @@ static int virtio_mmio_reset(struct udevice *udev)
 	struct virtio_mmio_priv *priv = dev_get_priv(udev);
 
 	/* 0 status means a reset */
-	writel(0, priv->base + VIRTIO_MMIO_STATUS);
+	virtio_mmio_writel(0, priv->base + VIRTIO_MMIO_STATUS);
 
 	return 0;
 }
@@ -156,12 +177,12 @@ static int virtio_mmio_get_features(struct udevice *udev, u64 *features)
 {
 	struct virtio_mmio_priv *priv = dev_get_priv(udev);
 
-	writel(1, priv->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL);
-	*features = readl(priv->base + VIRTIO_MMIO_DEVICE_FEATURES);
+	virtio_mmio_writel(1, priv->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL);
+	*features = virtio_mmio_readl(priv->base + VIRTIO_MMIO_DEVICE_FEATURES);
 	*features <<= 32;
 
-	writel(0, priv->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL);
-	*features |= readl(priv->base + VIRTIO_MMIO_DEVICE_FEATURES);
+	virtio_mmio_writel(0, priv->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL);
+	*features |= virtio_mmio_readl(priv->base + VIRTIO_MMIO_DEVICE_FEATURES);
 
 	return 0;
 }
@@ -177,12 +198,12 @@ static int virtio_mmio_set_features(struct udevice *udev)
 		return -EINVAL;
 	}
 
-	writel(1, priv->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL);
-	writel((u32)(uc_priv->features >> 32),
+	virtio_mmio_writel(1, priv->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL);
+	virtio_mmio_writel((u32)(uc_priv->features >> 32),
 	       priv->base + VIRTIO_MMIO_DRIVER_FEATURES);
 
-	writel(0, priv->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL);
-	writel((u32)uc_priv->features,
+	virtio_mmio_writel(0, priv->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL);
+	virtio_mmio_writel((u32)uc_priv->features,
 	       priv->base + VIRTIO_MMIO_DRIVER_FEATURES);
 
 	return 0;
@@ -197,16 +218,16 @@ static struct virtqueue *virtio_mmio_setup_vq(struct udevice *udev,
 	int err;
 
 	/* Select the queue we're interested in */
-	writel(index, priv->base + VIRTIO_MMIO_QUEUE_SEL);
+	virtio_mmio_writel(index, priv->base + VIRTIO_MMIO_QUEUE_SEL);
 
 	/* Queue shouldn't already be set up */
-	if (readl(priv->base + (priv->version == 1 ?
+	if (virtio_mmio_readl(priv->base + (priv->version == 1 ?
 	    VIRTIO_MMIO_QUEUE_PFN : VIRTIO_MMIO_QUEUE_READY))) {
 		err = -ENOENT;
 		goto error_available;
 	}
 
-	num = readl(priv->base + VIRTIO_MMIO_QUEUE_NUM_MAX);
+	num = virtio_mmio_readl(priv->base + VIRTIO_MMIO_QUEUE_NUM_MAX);
 	if (num == 0) {
 		err = -ENOENT;
 		goto error_new_virtqueue;
@@ -220,7 +241,7 @@ static struct virtqueue *virtio_mmio_setup_vq(struct udevice *udev,
 	}
 
 	/* Activate the queue */
-	writel(virtqueue_get_vring_size(vq),
+	virtio_mmio_writel(virtqueue_get_vring_size(vq),
 	       priv->base + VIRTIO_MMIO_QUEUE_NUM);
 	if (priv->version == 1) {
 		u64 q_pfn = virtqueue_get_desc_addr(vq) >> PAGE_SHIFT;
@@ -237,27 +258,27 @@ static struct virtqueue *virtio_mmio_setup_vq(struct udevice *udev,
 			goto error_bad_pfn;
 		}
 
-		writel(PAGE_SIZE, priv->base + VIRTIO_MMIO_QUEUE_ALIGN);
-		writel(q_pfn, priv->base + VIRTIO_MMIO_QUEUE_PFN);
+		virtio_mmio_writel(PAGE_SIZE, priv->base + VIRTIO_MMIO_QUEUE_ALIGN);
+		virtio_mmio_writel(q_pfn, priv->base + VIRTIO_MMIO_QUEUE_PFN);
 	} else {
 		u64 addr;
 
 		addr = virtqueue_get_desc_addr(vq);
-		writel((u32)addr, priv->base + VIRTIO_MMIO_QUEUE_DESC_LOW);
-		writel((u32)(addr >> 32),
+		virtio_mmio_writel((u32)addr, priv->base + VIRTIO_MMIO_QUEUE_DESC_LOW);
+		virtio_mmio_writel((u32)(addr >> 32),
 		       priv->base + VIRTIO_MMIO_QUEUE_DESC_HIGH);
 
 		addr = virtqueue_get_avail_addr(vq);
-		writel((u32)addr, priv->base + VIRTIO_MMIO_QUEUE_AVAIL_LOW);
-		writel((u32)(addr >> 32),
+		virtio_mmio_writel((u32)addr, priv->base + VIRTIO_MMIO_QUEUE_AVAIL_LOW);
+		virtio_mmio_writel((u32)(addr >> 32),
 		       priv->base + VIRTIO_MMIO_QUEUE_AVAIL_HIGH);
 
 		addr = virtqueue_get_used_addr(vq);
-		writel((u32)addr, priv->base + VIRTIO_MMIO_QUEUE_USED_LOW);
-		writel((u32)(addr >> 32),
+		virtio_mmio_writel((u32)addr, priv->base + VIRTIO_MMIO_QUEUE_USED_LOW);
+		virtio_mmio_writel((u32)(addr >> 32),
 		       priv->base + VIRTIO_MMIO_QUEUE_USED_HIGH);
 
-		writel(1, priv->base + VIRTIO_MMIO_QUEUE_READY);
+		virtio_mmio_writel(1, priv->base + VIRTIO_MMIO_QUEUE_READY);
 	}
 
 	return vq;
@@ -267,10 +288,10 @@ error_bad_pfn:
 
 error_new_virtqueue:
 	if (priv->version == 1) {
-		writel(0, priv->base + VIRTIO_MMIO_QUEUE_PFN);
+		virtio_mmio_writel(0, priv->base + VIRTIO_MMIO_QUEUE_PFN);
 	} else {
-		writel(0, priv->base + VIRTIO_MMIO_QUEUE_READY);
-		WARN_ON(readl(priv->base + VIRTIO_MMIO_QUEUE_READY));
+		virtio_mmio_writel(0, priv->base + VIRTIO_MMIO_QUEUE_READY);
+		WARN_ON(virtio_mmio_readl(priv->base + VIRTIO_MMIO_QUEUE_READY));
 	}
 
 error_available:
@@ -283,12 +304,12 @@ static void virtio_mmio_del_vq(struct virtqueue *vq)
 	unsigned int index = vq->index;
 
 	/* Select and deactivate the queue */
-	writel(index, priv->base + VIRTIO_MMIO_QUEUE_SEL);
+	virtio_mmio_writel(index, priv->base + VIRTIO_MMIO_QUEUE_SEL);
 	if (priv->version == 1) {
-		writel(0, priv->base + VIRTIO_MMIO_QUEUE_PFN);
+		virtio_mmio_writel(0, priv->base + VIRTIO_MMIO_QUEUE_PFN);
 	} else {
-		writel(0, priv->base + VIRTIO_MMIO_QUEUE_READY);
-		WARN_ON(readl(priv->base + VIRTIO_MMIO_QUEUE_READY));
+		virtio_mmio_writel(0, priv->base + VIRTIO_MMIO_QUEUE_READY);
+		WARN_ON(virtio_mmio_readl(priv->base + VIRTIO_MMIO_QUEUE_READY));
 	}
 
 	vring_del_virtqueue(vq);
@@ -329,7 +350,7 @@ static int virtio_mmio_notify(struct udevice *udev, struct virtqueue *vq)
 	 * We write the queue's selector into the notification register
 	 * to signal the other end
 	 */
-	writel(vq->index, priv->base + VIRTIO_MMIO_QUEUE_NOTIFY);
+	virtio_mmio_writel(vq->index, priv->base + VIRTIO_MMIO_QUEUE_NOTIFY);
 
 	return 0;
 }
@@ -359,14 +380,14 @@ static int virtio_mmio_probe(struct udevice *udev)
 	priv->base = (void __iomem *)plat->base;
 
 	/* Check magic value */
-	magic = readl(priv->base + VIRTIO_MMIO_MAGIC_VALUE);
+	magic = virtio_mmio_readl(priv->base + VIRTIO_MMIO_MAGIC_VALUE);
 	if (magic != ('v' | 'i' << 8 | 'r' << 16 | 't' << 24)) {
 		debug("(%s): wrong magic value 0x%08x!\n", udev->name, magic);
 		return 0;
 	}
 
 	/* Check device version */
-	priv->version = readl(priv->base + VIRTIO_MMIO_VERSION);
+	priv->version = virtio_mmio_readl(priv->base + VIRTIO_MMIO_VERSION);
 	if (priv->version < 1 || priv->version > 2) {
 		debug("(%s): version %d not supported!\n",
 		      udev->name, priv->version);
@@ -374,7 +395,7 @@ static int virtio_mmio_probe(struct udevice *udev)
 	}
 
 	/* Check device ID */
-	uc_priv->device = readl(priv->base + VIRTIO_MMIO_DEVICE_ID);
+	uc_priv->device = virtio_mmio_readl(priv->base + VIRTIO_MMIO_DEVICE_ID);
 	if (uc_priv->device == 0) {
 		/*
 		 * virtio-mmio device with an ID 0 is a (dummy) placeholder
@@ -382,10 +403,11 @@ static int virtio_mmio_probe(struct udevice *udev)
 		 */
 		return 0;
 	}
-	uc_priv->vendor = readl(priv->base + VIRTIO_MMIO_VENDOR_ID);
+	/* This is actually used as little endian locally? noice */
+	uc_priv->vendor = cpu_to_le32(virtio_mmio_readl(priv->base + VIRTIO_MMIO_VENDOR_ID));
 
 	if (priv->version == 1)
-		writel(PAGE_SIZE, priv->base + VIRTIO_MMIO_GUEST_PAGE_SIZE);
+		virtio_mmio_writel(PAGE_SIZE, priv->base + VIRTIO_MMIO_GUEST_PAGE_SIZE);
 
 	debug("(%s): device (%d) vendor (%08x) version (%d)\n", udev->name,
 	      uc_priv->device, uc_priv->vendor, priv->version);
-- 
2.51.0


  parent reply	other threads:[~2026-03-10 14:01 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-10 13:59 [RFC PATCH 0/3] Add virtio-mmio support to m68k virt machine Daniel Palmer
2026-03-10 13:59 ` [RFC PATCH 1/3] virtio: mmio: Allow instantiation via platform data Daniel Palmer
2026-03-10 13:59 ` Daniel Palmer [this message]
2026-03-14  8:53   ` [RFC PATCH 2/3] virtio: mmio: endian *fixes* *HACK* Daniel Palmer
2026-04-02 19:43     ` Kuan-Wei Chiu
2026-04-04  1:49       ` Daniel Palmer
2026-03-10 13:59 ` [RFC PATCH 3/3] board: qemu: m68k: Create virtio mmio instances Daniel Palmer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260310135940.1756141-3-daniel@thingy.jp \
    --to=daniel@thingy.jp \
    --cc=angelo@kernel-space.org \
    --cc=bmeng.cn@gmail.com \
    --cc=daniel@0x0f.com \
    --cc=laurent@vivier.eu \
    --cc=u-boot@lists.denx.de \
    --cc=visitorckw@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox