[PATCH v5 08/15] pc-bios/s390-ccw: Introduce CLP Architecture

jrossi@linux.ibm.com posted 15 patches 1 month ago
Maintainers: "Michael S. Tsirkin" <mst@redhat.com>, Marcel Apfelbaum <marcel.apfelbaum@gmail.com>, Christian Borntraeger <borntraeger@linux.ibm.com>, Thomas Huth <thuth@redhat.com>, Jared Rossi <jrossi@linux.ibm.com>, Zhuoying Cai <zycai@linux.ibm.com>, Richard Henderson <richard.henderson@linaro.org>, Ilya Leoshkevich <iii@linux.ibm.com>, David Hildenbrand <david@kernel.org>, Halil Pasic <pasic@linux.ibm.com>, Eric Farman <farman@linux.ibm.com>, Matthew Rosato <mjrosato@linux.ibm.com>, Farhan Ali <alifm@linux.ibm.com>, John Snow <jsnow@redhat.com>, Fabiano Rosas <farosas@suse.de>, Laurent Vivier <lvivier@redhat.com>, Paolo Bonzini <pbonzini@redhat.com>
[PATCH v5 08/15] pc-bios/s390-ccw: Introduce CLP Architecture
Posted by jrossi@linux.ibm.com 1 month ago
From: Jared Rossi <jrossi@linux.ibm.com>

Call Logical Processor (CLP) Architecture is used for managing PCI functions on
s390x. Define and include the structures and routines needed to interact with
PCI devices during IPL.

Acked-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Eric Farman <farman@linux.ibm.com>
Signed-off-by: Jared Rossi <jrossi@linux.ibm.com>
---
 pc-bios/s390-ccw/Makefile |  2 +-
 pc-bios/s390-ccw/clp.c    | 99 +++++++++++++++++++++++++++++++++++++++
 pc-bios/s390-ccw/clp.h    | 24 ++++++++++
 3 files changed, 124 insertions(+), 1 deletion(-)
 create mode 100644 pc-bios/s390-ccw/clp.c
 create mode 100644 pc-bios/s390-ccw/clp.h

diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
index 259cff09db..9c29548f84 100644
--- a/pc-bios/s390-ccw/Makefile
+++ b/pc-bios/s390-ccw/Makefile
@@ -35,7 +35,7 @@ QEMU_DGFLAGS = -MMD -MP -MT $@ -MF $(@D)/$(*F).d
 
 OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o netmain.o \
 	  virtio.o virtio-net.o virtio-scsi.o virtio-blkdev.o cio.o dasd-ipl.o \
-	  virtio-ccw.o
+	  virtio-ccw.o clp.o
 
 SLOF_DIR := $(SRC_PATH)/../../roms/SLOF
 
diff --git a/pc-bios/s390-ccw/clp.c b/pc-bios/s390-ccw/clp.c
new file mode 100644
index 0000000000..8c04738bbf
--- /dev/null
+++ b/pc-bios/s390-ccw/clp.c
@@ -0,0 +1,99 @@
+/*
+ * Call Logical Processor (CLP) architecture
+ *
+ * Copyright 2025 IBM Corp.
+ * Author(s): Jared Rossi <jrossi@linux.ibm.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "clp.h"
+#include <stdio.h>
+#include <string.h>
+
+int clp_pci(void *data)
+{
+    struct { uint8_t _[CLP_BLK_SIZE]; } *req = data;
+    int cc = 3;
+
+    asm volatile (
+        "     .insn   rrf,0xb9a00000,0,%[req],0,2\n"
+        "     ipm     %[cc]\n"
+        "     srl     %[cc],28\n"
+        : [cc] "+d" (cc), "+m" (*req)
+        : [req] "a" (req)
+        : "cc");
+    if (cc) {
+        printf("CLP returned with non-zero condition code %d\n", cc);
+    }
+    return cc;
+}
+
+/*
+ * Get the PCI function entry for a given function ID
+ * Return 0 on success, 1 if the FID is not found, or a negative RC on error
+ */
+int find_pci_function(uint32_t fid, ClpFhListEntry *entry)
+{
+    int count = 0;
+    int limit = PCI_MAX_FUNCTIONS;
+    ClpReqRspListPci rrb;
+
+    rrb.request.hdr.len = sizeof(ClpReqListPci);
+    rrb.request.hdr.cmd = 0x02;
+    rrb.request.resume_token = 0;
+    rrb.response.hdr.len = sizeof(ClpRspListPci);
+
+    do {
+        if (clp_pci(&rrb) || rrb.response.hdr.rsp != 0x0010) {
+            puts("Failed to list PCI functions");
+            return -1;
+        }
+
+        /* Resume token set when max enteries are returned */
+        if (rrb.response.resume_token) {
+            count = CLP_FH_LIST_NR_ENTRIES;
+            rrb.request.resume_token = rrb.response.resume_token;
+        } else {
+            count = (rrb.response.hdr.len - 32) / sizeof(ClpFhListEntry);
+        }
+
+        limit -= count;
+
+        for (int i = 0; i < count; i++) {
+            if (rrb.response.fh_list[i].fid == fid) {
+                memcpy(entry, &rrb.response.fh_list[i], sizeof(ClpFhListEntry));
+                return 0;
+            }
+        }
+
+    } while (rrb.request.resume_token && limit > 0);
+
+    puts("No function entry found for FID!");
+
+    return 1;
+}
+
+/*
+ * Enable the PCI function associated with a given handle
+ * Return 0 on success or a negative RC on error
+ */
+int enable_pci_function(uint32_t *fhandle)
+{
+    ClpReqRspSetPci rrb;
+
+    rrb.request.hdr.len = sizeof(ClpReqSetPci);
+    rrb.request.hdr.cmd = 0x05;
+    rrb.request.fh = *fhandle;
+    rrb.request.oc = 0;
+    rrb.request.ndas = 1;
+    rrb.response.hdr.len = sizeof(ClpRspSetPci);
+
+    if (clp_pci(&rrb) || rrb.response.hdr.rsp != 0x0010) {
+        puts("Failed to enable PCI function");
+        return -1;
+    }
+
+    *fhandle = rrb.response.fh;
+    return 0;
+}
diff --git a/pc-bios/s390-ccw/clp.h b/pc-bios/s390-ccw/clp.h
new file mode 100644
index 0000000000..1ac2f8c177
--- /dev/null
+++ b/pc-bios/s390-ccw/clp.h
@@ -0,0 +1,24 @@
+/*
+ * Call Logical Processor (CLP) architecture definitions
+ *
+ * Copyright 2025 IBM Corp.
+ * Author(s): Jared Rossi <jrossi@linux.ibm.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef CLP_H
+#define CLP_H
+
+#ifndef QEMU_PACKED
+#define QEMU_PACKED __attribute__((packed))
+#endif
+
+#include <stdint.h>
+#include <s390-pci-clp.h>
+
+int clp_pci(void *data);
+int find_pci_function(uint32_t fid, ClpFhListEntry *entry);
+int enable_pci_function(uint32_t *fhandle);
+
+#endif
-- 
2.52.0
Re: [PATCH v5 08/15] pc-bios/s390-ccw: Introduce CLP Architecture
Posted by Farhan Ali 1 month ago
On 3/8/2026 5:35 PM, jrossi@linux.ibm.com wrote:
> From: Jared Rossi<jrossi@linux.ibm.com>
>
> Call Logical Processor (CLP) Architecture is used for managing PCI functions on
> s390x. Define and include the structures and routines needed to interact with
> PCI devices during IPL.
>
> Acked-by: Thomas Huth<thuth@redhat.com>
> Reviewed-by: Eric Farman<farman@linux.ibm.com>
> Signed-off-by: Jared Rossi<jrossi@linux.ibm.com>
> ---
>   pc-bios/s390-ccw/Makefile |  2 +-
>   pc-bios/s390-ccw/clp.c    | 99 +++++++++++++++++++++++++++++++++++++++
>   pc-bios/s390-ccw/clp.h    | 24 ++++++++++
>   3 files changed, 124 insertions(+), 1 deletion(-)
>   create mode 100644 pc-bios/s390-ccw/clp.c
>   create mode 100644 pc-bios/s390-ccw/clp.h

Reviewed-by: Farhan Ali<alifm@linux.ibm.com>
Re: [PATCH v5 08/15] pc-bios/s390-ccw: Introduce CLP Architecture
Posted by Matthew Rosato 1 month ago
On 3/8/26 8:35 PM, jrossi@linux.ibm.com wrote:
> From: Jared Rossi <jrossi@linux.ibm.com>
> 
> Call Logical Processor (CLP) Architecture is used for managing PCI functions on
> s390x. Define and include the structures and routines needed to interact with
> PCI devices during IPL.
> 
> Acked-by: Thomas Huth <thuth@redhat.com>
> Reviewed-by: Eric Farman <farman@linux.ibm.com>
> Signed-off-by: Jared Rossi <jrossi@linux.ibm.com>

Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com>

> ---
>  pc-bios/s390-ccw/Makefile |  2 +-
>  pc-bios/s390-ccw/clp.c    | 99 +++++++++++++++++++++++++++++++++++++++
>  pc-bios/s390-ccw/clp.h    | 24 ++++++++++
>  3 files changed, 124 insertions(+), 1 deletion(-)
>  create mode 100644 pc-bios/s390-ccw/clp.c
>  create mode 100644 pc-bios/s390-ccw/clp.h
> 
> diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
> index 259cff09db..9c29548f84 100644
> --- a/pc-bios/s390-ccw/Makefile
> +++ b/pc-bios/s390-ccw/Makefile
> @@ -35,7 +35,7 @@ QEMU_DGFLAGS = -MMD -MP -MT $@ -MF $(@D)/$(*F).d
>  
>  OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o netmain.o \
>  	  virtio.o virtio-net.o virtio-scsi.o virtio-blkdev.o cio.o dasd-ipl.o \
> -	  virtio-ccw.o
> +	  virtio-ccw.o clp.o
>  
>  SLOF_DIR := $(SRC_PATH)/../../roms/SLOF
>  
> diff --git a/pc-bios/s390-ccw/clp.c b/pc-bios/s390-ccw/clp.c
> new file mode 100644
> index 0000000000..8c04738bbf
> --- /dev/null
> +++ b/pc-bios/s390-ccw/clp.c
> @@ -0,0 +1,99 @@
> +/*
> + * Call Logical Processor (CLP) architecture
> + *
> + * Copyright 2025 IBM Corp.
> + * Author(s): Jared Rossi <jrossi@linux.ibm.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include "clp.h"
> +#include <stdio.h>
> +#include <string.h>
> +
> +int clp_pci(void *data)
> +{
> +    struct { uint8_t _[CLP_BLK_SIZE]; } *req = data;
> +    int cc = 3;
> +
> +    asm volatile (
> +        "     .insn   rrf,0xb9a00000,0,%[req],0,2\n"
> +        "     ipm     %[cc]\n"
> +        "     srl     %[cc],28\n"
> +        : [cc] "+d" (cc), "+m" (*req)
> +        : [req] "a" (req)
> +        : "cc");
> +    if (cc) {
> +        printf("CLP returned with non-zero condition code %d\n", cc);
> +    }
> +    return cc;
> +}
> +
> +/*
> + * Get the PCI function entry for a given function ID
> + * Return 0 on success, 1 if the FID is not found, or a negative RC on error
> + */
> +int find_pci_function(uint32_t fid, ClpFhListEntry *entry)
> +{
> +    int count = 0;
> +    int limit = PCI_MAX_FUNCTIONS;
> +    ClpReqRspListPci rrb;
> +
> +    rrb.request.hdr.len = sizeof(ClpReqListPci);
> +    rrb.request.hdr.cmd = 0x02;
> +    rrb.request.resume_token = 0;
> +    rrb.response.hdr.len = sizeof(ClpRspListPci);
> +
> +    do {
> +        if (clp_pci(&rrb) || rrb.response.hdr.rsp != 0x0010) {
> +            puts("Failed to list PCI functions");
> +            return -1;
> +        }
> +
> +        /* Resume token set when max enteries are returned */
> +        if (rrb.response.resume_token) {
> +            count = CLP_FH_LIST_NR_ENTRIES;
> +            rrb.request.resume_token = rrb.response.resume_token;
> +        } else {
> +            count = (rrb.response.hdr.len - 32) / sizeof(ClpFhListEntry);
> +        }
> +
> +        limit -= count;
> +
> +        for (int i = 0; i < count; i++) {
> +            if (rrb.response.fh_list[i].fid == fid) {
> +                memcpy(entry, &rrb.response.fh_list[i], sizeof(ClpFhListEntry));
> +                return 0;
> +            }
> +        }
> +
> +    } while (rrb.request.resume_token && limit > 0);
> +
> +    puts("No function entry found for FID!");
> +
> +    return 1;
> +}
> +
> +/*
> + * Enable the PCI function associated with a given handle
> + * Return 0 on success or a negative RC on error
> + */
> +int enable_pci_function(uint32_t *fhandle)
> +{
> +    ClpReqRspSetPci rrb;
> +
> +    rrb.request.hdr.len = sizeof(ClpReqSetPci);
> +    rrb.request.hdr.cmd = 0x05;
> +    rrb.request.fh = *fhandle;
> +    rrb.request.oc = 0;
> +    rrb.request.ndas = 1;
> +    rrb.response.hdr.len = sizeof(ClpRspSetPci);
> +
> +    if (clp_pci(&rrb) || rrb.response.hdr.rsp != 0x0010) {
> +        puts("Failed to enable PCI function");
> +        return -1;
> +    }
> +
> +    *fhandle = rrb.response.fh;
> +    return 0;
> +}
> diff --git a/pc-bios/s390-ccw/clp.h b/pc-bios/s390-ccw/clp.h
> new file mode 100644
> index 0000000000..1ac2f8c177
> --- /dev/null
> +++ b/pc-bios/s390-ccw/clp.h
> @@ -0,0 +1,24 @@
> +/*
> + * Call Logical Processor (CLP) architecture definitions
> + *
> + * Copyright 2025 IBM Corp.
> + * Author(s): Jared Rossi <jrossi@linux.ibm.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#ifndef CLP_H
> +#define CLP_H
> +
> +#ifndef QEMU_PACKED
> +#define QEMU_PACKED __attribute__((packed))
> +#endif
> +
> +#include <stdint.h>
> +#include <s390-pci-clp.h>
> +
> +int clp_pci(void *data);
> +int find_pci_function(uint32_t fid, ClpFhListEntry *entry);
> +int enable_pci_function(uint32_t *fhandle);
> +
> +#endif