diff mbox series

[v1,1/2] util: Add functions for s390x mmio read/write

Message ID 20250326181007.1099-2-alifm@linux.ibm.com (mailing list archive)
State New
Headers show
Series Enable QEMU NVMe userspace driver on s390x | expand

Commit Message

Farhan Ali March 26, 2025, 6:10 p.m. UTC
Starting with z15 (or newer) we can execute mmio
instructions from userspace. On older platforms
where we don't have these instructions available
we can fallback to using system calls to access
the PCI mapped resources.

This patch adds helper functions for mmio reads
and writes for s390x.

Signed-off-by: Farhan Ali <alifm@linux.ibm.com>
---
 include/qemu/s390x_pci_mmio.h |  17 ++++++
 util/meson.build              |   2 +
 util/s390x_pci_mmio.c         | 105 ++++++++++++++++++++++++++++++++++
 3 files changed, 124 insertions(+)
 create mode 100644 include/qemu/s390x_pci_mmio.h
 create mode 100644 util/s390x_pci_mmio.c

Comments

Stefan Hajnoczi March 27, 2025, 7:20 p.m. UTC | #1
On Wed, Mar 26, 2025 at 11:10:06AM -0700, Farhan Ali wrote:
> Starting with z15 (or newer) we can execute mmio
> instructions from userspace. On older platforms
> where we don't have these instructions available
> we can fallback to using system calls to access
> the PCI mapped resources.
> 
> This patch adds helper functions for mmio reads
> and writes for s390x.
> 
> Signed-off-by: Farhan Ali <alifm@linux.ibm.com>
> ---
>  include/qemu/s390x_pci_mmio.h |  17 ++++++
>  util/meson.build              |   2 +
>  util/s390x_pci_mmio.c         | 105 ++++++++++++++++++++++++++++++++++
>  3 files changed, 124 insertions(+)
>  create mode 100644 include/qemu/s390x_pci_mmio.h
>  create mode 100644 util/s390x_pci_mmio.c
> 
> diff --git a/include/qemu/s390x_pci_mmio.h b/include/qemu/s390x_pci_mmio.h
> new file mode 100644
> index 0000000000..be61b5ae29
> --- /dev/null
> +++ b/include/qemu/s390x_pci_mmio.h
> @@ -0,0 +1,17 @@
> +/*
> + * s390x PCI MMIO definitions
> + *
> + * Copyright 2025 IBM Corp.
> + * Author(s): Farhan Ali <alifm@linux.ibm.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +#ifndef S390X_PCI_MMIO_H
> +#define S390X_PCI_MMIO_H
> +
> +uint64_t s390x_pci_mmio_read_64(const void *ioaddr);
> +uint32_t s390x_pci_mmio_read_32(const void *ioaddr);
> +void s390x_pci_mmio_write_64(void *ioaddr, uint64_t val);
> +void s390x_pci_mmio_write_32(void *ioaddr, uint32_t val);
> +
> +#endif
> diff --git a/util/meson.build b/util/meson.build
> index 780b5977a8..acb21592f9 100644
> --- a/util/meson.build
> +++ b/util/meson.build
> @@ -131,4 +131,6 @@ elif cpu in ['ppc', 'ppc64']
>    util_ss.add(files('cpuinfo-ppc.c'))
>  elif cpu in ['riscv32', 'riscv64']
>    util_ss.add(files('cpuinfo-riscv.c'))
> +elif cpu == 's390x'
> +  util_ss.add(files('s390x_pci_mmio.c'))
>  endif
> diff --git a/util/s390x_pci_mmio.c b/util/s390x_pci_mmio.c
> new file mode 100644
> index 0000000000..2e0825d617
> --- /dev/null
> +++ b/util/s390x_pci_mmio.c
> @@ -0,0 +1,105 @@
> +/*
> + * s390x PCI MMIO definitions
> + *
> + * Copyright 2025 IBM Corp.
> + * Author(s): Farhan Ali <alifm@linux.ibm.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include <unistd.h>
> +#include <sys/syscall.h>
> +#include "qemu/osdep.h"

This should be the first #include in the file. From
docs/devel/style.rst:

  Include directives
  ------------------
  
  Order include directives as follows:
  
  .. code-block:: c
  
      #include "qemu/osdep.h"  /* Always first... */
      #include <...>           /* then system headers... */
      #include "..."           /* and finally QEMU headers. */

Otherwise:

Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Farhan Ali March 27, 2025, 7:53 p.m. UTC | #2
On 3/27/2025 12:20 PM, Stefan Hajnoczi wrote:
> On Wed, Mar 26, 2025 at 11:10:06AM -0700, Farhan Ali wrote:
>> Starting with z15 (or newer) we can execute mmio
>> instructions from userspace. On older platforms
>> where we don't have these instructions available
>> we can fallback to using system calls to access
>> the PCI mapped resources.
>>
>> This patch adds helper functions for mmio reads
>> and writes for s390x.
>>
>> Signed-off-by: Farhan Ali <alifm@linux.ibm.com>
>> ---
>>   include/qemu/s390x_pci_mmio.h |  17 ++++++
>>   util/meson.build              |   2 +
>>   util/s390x_pci_mmio.c         | 105 ++++++++++++++++++++++++++++++++++
>>   3 files changed, 124 insertions(+)
>>   create mode 100644 include/qemu/s390x_pci_mmio.h
>>   create mode 100644 util/s390x_pci_mmio.c
>>
>> diff --git a/include/qemu/s390x_pci_mmio.h b/include/qemu/s390x_pci_mmio.h
>> new file mode 100644
>> index 0000000000..be61b5ae29
>> --- /dev/null
>> +++ b/include/qemu/s390x_pci_mmio.h
>> @@ -0,0 +1,17 @@
>> +/*
>> + * s390x PCI MMIO definitions
>> + *
>> + * Copyright 2025 IBM Corp.
>> + * Author(s): Farhan Ali <alifm@linux.ibm.com>
>> + *
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + */
>> +#ifndef S390X_PCI_MMIO_H
>> +#define S390X_PCI_MMIO_H
>> +
>> +uint64_t s390x_pci_mmio_read_64(const void *ioaddr);
>> +uint32_t s390x_pci_mmio_read_32(const void *ioaddr);
>> +void s390x_pci_mmio_write_64(void *ioaddr, uint64_t val);
>> +void s390x_pci_mmio_write_32(void *ioaddr, uint32_t val);
>> +
>> +#endif
>> diff --git a/util/meson.build b/util/meson.build
>> index 780b5977a8..acb21592f9 100644
>> --- a/util/meson.build
>> +++ b/util/meson.build
>> @@ -131,4 +131,6 @@ elif cpu in ['ppc', 'ppc64']
>>     util_ss.add(files('cpuinfo-ppc.c'))
>>   elif cpu in ['riscv32', 'riscv64']
>>     util_ss.add(files('cpuinfo-riscv.c'))
>> +elif cpu == 's390x'
>> +  util_ss.add(files('s390x_pci_mmio.c'))
>>   endif
>> diff --git a/util/s390x_pci_mmio.c b/util/s390x_pci_mmio.c
>> new file mode 100644
>> index 0000000000..2e0825d617
>> --- /dev/null
>> +++ b/util/s390x_pci_mmio.c
>> @@ -0,0 +1,105 @@
>> +/*
>> + * s390x PCI MMIO definitions
>> + *
>> + * Copyright 2025 IBM Corp.
>> + * Author(s): Farhan Ali <alifm@linux.ibm.com>
>> + *
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + */
>> +
>> +#include <unistd.h>
>> +#include <sys/syscall.h>
>> +#include "qemu/osdep.h"
> This should be the first #include in the file. From
> docs/devel/style.rst:
>
>    Include directives
>    ------------------
>    
>    Order include directives as follows:
>    
>    .. code-block:: c
>    
>        #include "qemu/osdep.h"  /* Always first... */
>        #include <...>           /* then system headers... */
>        #include "..."           /* and finally QEMU headers. */
>
> Otherwise:
>
> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>

Will fix in next revision. Thanks!
diff mbox series

Patch

diff --git a/include/qemu/s390x_pci_mmio.h b/include/qemu/s390x_pci_mmio.h
new file mode 100644
index 0000000000..be61b5ae29
--- /dev/null
+++ b/include/qemu/s390x_pci_mmio.h
@@ -0,0 +1,17 @@ 
+/*
+ * s390x PCI MMIO definitions
+ *
+ * Copyright 2025 IBM Corp.
+ * Author(s): Farhan Ali <alifm@linux.ibm.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef S390X_PCI_MMIO_H
+#define S390X_PCI_MMIO_H
+
+uint64_t s390x_pci_mmio_read_64(const void *ioaddr);
+uint32_t s390x_pci_mmio_read_32(const void *ioaddr);
+void s390x_pci_mmio_write_64(void *ioaddr, uint64_t val);
+void s390x_pci_mmio_write_32(void *ioaddr, uint32_t val);
+
+#endif
diff --git a/util/meson.build b/util/meson.build
index 780b5977a8..acb21592f9 100644
--- a/util/meson.build
+++ b/util/meson.build
@@ -131,4 +131,6 @@  elif cpu in ['ppc', 'ppc64']
   util_ss.add(files('cpuinfo-ppc.c'))
 elif cpu in ['riscv32', 'riscv64']
   util_ss.add(files('cpuinfo-riscv.c'))
+elif cpu == 's390x'
+  util_ss.add(files('s390x_pci_mmio.c'))
 endif
diff --git a/util/s390x_pci_mmio.c b/util/s390x_pci_mmio.c
new file mode 100644
index 0000000000..2e0825d617
--- /dev/null
+++ b/util/s390x_pci_mmio.c
@@ -0,0 +1,105 @@ 
+/*
+ * s390x PCI MMIO definitions
+ *
+ * Copyright 2025 IBM Corp.
+ * Author(s): Farhan Ali <alifm@linux.ibm.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <unistd.h>
+#include <sys/syscall.h>
+#include "qemu/osdep.h"
+#include "qemu/s390x_pci_mmio.h"
+#include "elf.h"
+
+union register_pair {
+    unsigned __int128 pair;
+    struct {
+        uint64_t even;
+        uint64_t odd;
+    };
+};
+
+static bool is_mio_supported;
+
+static __attribute__((constructor)) void check_is_mio_supported(void)
+{
+    is_mio_supported = !!(qemu_getauxval(AT_HWCAP) & HWCAP_S390_PCI_MIO);
+}
+
+static uint64_t s390x_pcilgi(const void *ioaddr, size_t len)
+{
+    union register_pair ioaddr_len = { .even = (uint64_t)ioaddr,
+                                       .odd = len };
+    uint64_t val;
+    int cc;
+
+    asm volatile(
+        /* pcilgi */
+        ".insn   rre,0xb9d60000,%[val],%[ioaddr_len]\n"
+        "ipm     %[cc]\n"
+        "srl     %[cc],28\n"
+        : [cc] "=d"(cc), [val] "=d"(val),
+        [ioaddr_len] "+&d"(ioaddr_len.pair) :: "cc");
+
+    if (cc) {
+        val = -1ULL;
+    }
+
+    return val;
+}
+
+static void s390x_pcistgi(void *ioaddr, uint64_t val, size_t len)
+{
+    union register_pair ioaddr_len = {.even = (uint64_t)ioaddr, .odd = len};
+
+    asm volatile (
+        /* pcistgi */
+        ".insn   rre,0xb9d40000,%[val],%[ioaddr_len]\n"
+        : [ioaddr_len] "+&d" (ioaddr_len.pair)
+        : [val] "d" (val)
+        : "cc", "memory");
+}
+
+uint32_t s390x_pci_mmio_read_32(const void *ioaddr)
+{
+    uint32_t val = 0;
+
+    if (is_mio_supported) {
+        val = s390x_pcilgi(ioaddr, sizeof(val));
+    } else {
+        syscall(__NR_s390_pci_mmio_read, ioaddr, &val, sizeof(val));
+    }
+    return val;
+}
+
+uint64_t s390x_pci_mmio_read_64(const void *ioaddr)
+{
+    uint64_t val = 0;
+
+    if (is_mio_supported) {
+        val = s390x_pcilgi(ioaddr, sizeof(val));
+    } else {
+        syscall(__NR_s390_pci_mmio_read, ioaddr, &val, sizeof(val));
+    }
+    return val;
+}
+
+void s390x_pci_mmio_write_64(void *ioaddr, uint64_t val)
+{
+    if (is_mio_supported) {
+        s390x_pcistgi(ioaddr, val, sizeof(val));
+    } else {
+        syscall(__NR_s390_pci_mmio_write, ioaddr, &val, sizeof(val));
+    }
+}
+
+void s390x_pci_mmio_write_32(void *ioaddr, uint32_t val)
+{
+    if (is_mio_supported) {
+        s390x_pcistgi(ioaddr, val, sizeof(val));
+    } else {
+        syscall(__NR_s390_pci_mmio_write, ioaddr, &val, sizeof(val));
+    }
+}