mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Cc: ejo@pengutronix.de, Peter Maydell <peter.maydell@linaro.org>,
	Ahmad Fatoum <a.fatoum@pengutronix.de>
Subject: [PATCH 1/5] ARM64: io: implement I/O accessors in assembly
Date: Wed,  9 Oct 2024 08:05:07 +0200	[thread overview]
Message-ID: <20241009060511.4121157-2-a.fatoum@pengutronix.de> (raw)
In-Reply-To: <20241009060511.4121157-1-a.fatoum@pengutronix.de>

We currently implement the I/O accessors in C with volatile accesses.
With I/O memory being mapped strongly ordered, we are thus ensured that
actual memory access size and order is as specified in the C code.

This was sufficient so far, but triggers problems when barebox is run
under KVM: KVM expects that MMIO regions are only accessed via
instructions that set the ISV bit in the ESR_EL1 register.

An example for an instruction that doesn't set the ISV bit is the
pre-index and post-index form of ldr/str, e.g.:

	ldr     x0, =0x9000fe0
	ldr     w1, [x0], #4

This will fail when virtualized with KVM, because KVM would have to
decode the instruction on trap to handle the post-increment of x0,
which is currently unimplemented.

Let's fix this by implementing readl/writel and friends in assembly
unconditionally like Linux does.

This introduces some slight overhead, because the post-index variants
reduce code size when reading multiple registers sequentially, but this
ought to be negligible.

Suggested-by: Peter Maydell <peter.maydell@linaro.org>
Link: https://lore.kernel.org/all/CAFEAcA_Yv2a=XCKw80y9iyBRoC27UL6Sfzgy4KwFDkC1gbzK7w@mail.gmail.com/
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/arm/include/asm/io.h   |  5 +-
 arch/arm/include/asm/io64.h | 99 +++++++++++++++++++++++++++++++++++++
 2 files changed, 103 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/include/asm/io64.h

diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 9e9b13ad18c6..0b9bb9bfaf9a 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -5,7 +5,7 @@
 
 #include <linux/compiler.h>
 
-#ifndef CONFIG_CPU_64
+#ifdef CONFIG_ARM32
 /*
  * Generic IO read/write.  These perform native-endian accesses.  Note
  * that some architectures will want to re-define __raw_{read,write}w.
@@ -25,6 +25,9 @@ void __raw_readsl(const volatile void __iomem *addr, void *data, int longlen);
 #define writesb(p,d,l)		__raw_writesb(p,d,l)
 #define writesw(p,d,l)		__raw_writesw(p,d,l)
 #define writesl(p,d,l)		__raw_writesl(p,d,l)
+
+#elif defined(CONFIG_ARM64)
+#include <asm/io64.h>
 #endif
 
 #define	IO_SPACE_LIMIT	0
diff --git a/arch/arm/include/asm/io64.h b/arch/arm/include/asm/io64.h
new file mode 100644
index 000000000000..6e3cba97f7ca
--- /dev/null
+++ b/arch/arm/include/asm/io64.h
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Based on arch/arm/include/asm/io.h
+ *
+ * Copyright (C) 1996-2000 Russell King
+ * Copyright (C) 2012 ARM Ltd.
+ */
+#ifndef __ASM_IO64_H
+#define __ASM_IO64_H
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+#include <asm/byteorder.h>
+
+/*
+ * Generic IO read/write.  These perform native-endian accesses.
+ */
+static __always_inline void ___raw_writeb(u8 val, volatile void __iomem *addr)
+{
+	volatile u8 __iomem *ptr = addr;
+	asm volatile("strb %w0, %1" : : "rZ" (val), "Qo" (*ptr));
+}
+
+static __always_inline void ___raw_writew(u16 val, volatile void __iomem *addr)
+{
+	volatile u16 __iomem *ptr = addr;
+	asm volatile("strh %w0, %1" : : "rZ" (val), "Qo" (*ptr));
+}
+
+static __always_inline void ___raw_writel(u32 val, volatile void __iomem *addr)
+{
+	volatile u32 __iomem *ptr = addr;
+	asm volatile("str %w0, %1" : : "rZ" (val), "Qo" (*ptr));
+}
+
+static __always_inline void ___raw_writeq(u64 val, volatile void __iomem *addr)
+{
+	volatile u64 __iomem *ptr = addr;
+	asm volatile("str %x0, %1" : : "rZ" (val), "Qo" (*ptr));
+}
+
+static __always_inline u8 ___raw_readb(const volatile void __iomem *addr)
+{
+	u8 val;
+	asm volatile("ldrb %w0, [%1]" : "=r" (val) : "r" (addr));
+	return val;
+}
+
+static __always_inline u16 ___raw_readw(const volatile void __iomem *addr)
+{
+	u16 val;
+
+	asm volatile("ldrh %w0, [%1]" : "=r" (val) : "r" (addr));
+	return val;
+}
+
+static __always_inline u32 ___raw_readl(const volatile void __iomem *addr)
+{
+	u32 val;
+	asm volatile("ldr %w0, [%1]" : "=r" (val) : "r" (addr));
+	return val;
+}
+
+static __always_inline u64 ___raw_readq(const volatile void __iomem *addr)
+{
+	u64 val;
+	asm volatile("ldr %0, [%1]" : "=r" (val) : "r" (addr));
+	return val;
+}
+
+
+#ifdef __LINUX_IO_STRICT_PROTOTYPES__
+#define __IOMEM(a)	(a)
+#else
+#define __IOMEM(a)	((void __force __iomem *)(a))
+#endif
+
+#define __raw_writeb(v, a) ___raw_writeb(v, __IOMEM(a))
+#define __raw_writew(v, a) ___raw_writew(v, __IOMEM(a))
+#define __raw_writel(v, a) ___raw_writel(v, __IOMEM(a))
+#define __raw_writeq(v, a) ___raw_writeq(v, __IOMEM(a))
+
+#define __raw_readb(a) ___raw_readb(__IOMEM(a))
+#define __raw_readw(a) ___raw_readw(__IOMEM(a))
+#define __raw_readl(a) ___raw_readl(__IOMEM(a))
+#define __raw_readq(a) ___raw_readq(__IOMEM(a))
+
+/*
+ * io{read,write}{16,32,64}be() macros
+ */
+#define ioread16be(p)		({ __u16 __v = be16_to_cpu((__force __be16)__raw_readw(p)); __v; })
+#define ioread32be(p)		({ __u32 __v = be32_to_cpu((__force __be32)__raw_readl(p)); __v; })
+#define ioread64be(p)		({ __u64 __v = be64_to_cpu((__force __be64)__raw_readq(p)); __v; })
+
+#define iowrite16be(v,p)	({ __raw_writew((__force __u16)cpu_to_be16(v), p); })
+#define iowrite32be(v,p)	({ __raw_writel((__force __u32)cpu_to_be32(v), p); })
+#define iowrite64be(v,p)	({ __raw_writeq((__force __u64)cpu_to_be64(v), p); })
+
+#endif	/* __ASM_IO64_H */
-- 
2.39.5




  reply	other threads:[~2024-10-09  6:08 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-09  6:05 [PATCH 0/5] ARM64: make barebox compatible with KVM Ahmad Fatoum
2024-10-09  6:05 ` Ahmad Fatoum [this message]
2024-10-09  6:05 ` [PATCH 2/5] ARM64: board-dt-2nd: grow stack down from start of binary Ahmad Fatoum
2024-10-09  6:05 ` [PATCH 3/5] mtd: cfi-flash: use I/O accessors for reads/writes of MMIO regions Ahmad Fatoum
2024-10-09  6:05 ` [PATCH 4/5] ARM64: mmu: flush cacheable regions prior to remapping Ahmad Fatoum
2024-10-09  6:05 ` [PATCH 5/5] virtio: don't use DMA API unless required Ahmad Fatoum
2024-10-14 12:48   ` Sascha Hauer
2024-10-14 13:05     ` Ahmad Fatoum
2024-10-14 13:06   ` [PATCH] fixup! " Ahmad Fatoum
2024-10-15  6:54 ` [PATCH 0/5] ARM64: make barebox compatible with KVM Sascha Hauer

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=20241009060511.4121157-2-a.fatoum@pengutronix.de \
    --to=a.fatoum@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    --cc=ejo@pengutronix.de \
    --cc=peter.maydell@linaro.org \
    /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