59 lines
1.5 KiB
Diff
59 lines
1.5 KiB
Diff
diff --git a/nvme-print.c b/nvme-print.c
|
|
index 2327674..cc27dc9 100644
|
|
--- a/nvme-print.c
|
|
+++ b/nvme-print.c
|
|
@@ -2452,23 +2452,45 @@ static void nvme_show_registers_pmrmscu(uint32_t pmrmscu)
|
|
pmrmscu);
|
|
}
|
|
|
|
-static inline uint32_t mmio_read32(void *addr)
|
|
+/*
|
|
+ * VMs on arm64 can only use a subset of instructions for MMIO that provide
|
|
+ * the hypervisor with a complete instruction decode. Provide assembly MMIO
|
|
+ * accessors to prevent the compiler from using a possibly unsupported
|
|
+ * instruction.
|
|
+ *
|
|
+ * See kernel commit c726200dd106 ("KVM: arm/arm64: Allow reporting non-ISV
|
|
+ * data aborts to userspace") for more details.
|
|
+ */
|
|
+#if defined(__aarch64__)
|
|
+static inline uint32_t __raw_readl(const volatile uint32_t *addr)
|
|
+{
|
|
+ uint32_t val;
|
|
+
|
|
+ asm volatile("ldr %w0, %1" : "=r" (val) : "Qo" (*addr));
|
|
+
|
|
+ return val;
|
|
+}
|
|
+#else
|
|
+static inline uint32_t __raw_readl(volatile uint32_t *addr)
|
|
{
|
|
- __le32 *p = addr;
|
|
+ return *addr;
|
|
+}
|
|
+#endif
|
|
|
|
- return le32_to_cpu(*p);
|
|
+static inline uint32_t mmio_read32(void *addr)
|
|
+{
|
|
+ return le32_to_cpu(__raw_readl(addr));
|
|
}
|
|
|
|
/* Access 64-bit registers as 2 32-bit; Some devices fail 64-bit MMIO. */
|
|
static inline __u64 mmio_read64(void *addr)
|
|
{
|
|
- const volatile __u32 *p = addr;
|
|
- __u32 low, high;
|
|
+ uint32_t low, high;
|
|
|
|
- low = le32_to_cpu(*p);
|
|
- high = le32_to_cpu(*(p + 1));
|
|
+ low = le32_to_cpu(__raw_readl(addr));
|
|
+ high = le32_to_cpu(__raw_readl(addr + sizeof(uint32_t)));
|
|
|
|
- return ((__u64) high << 32) | low;
|
|
+ return ((uint64_t)high << 32) | low;
|
|
}
|
|
|
|
static void json_ctrl_registers(void *bar)
|