pc-bios/s390-ccw: Introduce PCI device
Define selected s390x PCI instructions. Signed-off-by: Jared Rossi <jrossi@linux.ibm.com> Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com> Acked-by: Thomas Huth <thuth@redhat.com> Message-ID: <20260309003601.242634-11-jrossi@linux.ibm.com> Reviewed-by: Farhan Ali <alifm@linux.ibm.com> [thuth: Remove unused defines as suggested by Farhan] Signed-off-by: Thomas Huth <thuth@redhat.com>
Jared Rossi committed
Mar 8, 2026 at 20:35 UTC
5ed17bb32abc5aa78dc321ae672a1520f4730873
3 files changed
+155
-1
pc-bios/s390-ccw/Makefile
+1
-1
@@ -35,7 +35,7 @@ QEMU_DGFLAGS = -MMD -MP -MT $@ -MF $(@D)/$(*F).d
35
36
OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o netmain.o \
37
virtio.o virtio-net.o virtio-scsi.o virtio-blkdev.o cio.o dasd-ipl.o \
38
- virtio-ccw.o clp.o
38
+ virtio-ccw.o clp.o pci.o
39
40
SLOF_DIR := $(SRC_PATH)/../../roms/SLOF
41
pc-bios/s390-ccw/pci.c
new
+118
@@ -0,0 +1,118 @@
1
+/*
2
+ * s390x PCI functionality
3
+ *
4
+ * Copyright 2025 IBM Corp.
5
+ * Author(s): Jared Rossi <jrossi@linux.ibm.com>
6
+ *
7
+ * SPDX-License-Identifier: GPL-2.0-or-later
8
+ */
9
+
10
+#include "clp.h"
11
+#include "pci.h"
12
+#include "bswap.h"
13
+#include <stdio.h>
14
+#include <stdbool.h>
15
+
16
+/* PCI load */
17
+static inline int pcilg(uint64_t *data, uint64_t req, uint64_t offset,
18
+ uint8_t *status)
19
+{
20
+ union register_pair req_off = {.even = req, .odd = offset};
21
+ int cc = -1;
22
+ uint64_t __data;
23
+
24
+ asm volatile (
25
+ " .insn rre,0xb9d20000,%[data],%[req_off]\n"
26
+ " ipm %[cc]\n"
27
+ " srl %[cc],28\n"
28
+ : [cc] "+d" (cc), [data] "=d" (__data),
29
+ [req_off] "+d" (req_off.pair) :: "cc");
30
+ *status = req_off.even >> 24 & 0xff;
31
+ *data = __data;
32
+ return cc;
33
+}
34
+
35
+/* PCI store */
36
+static inline int pcistg(uint64_t data, uint64_t req, uint64_t offset,
37
+ uint8_t *status)
38
+{
39
+ union register_pair req_off = {.even = req, .odd = offset};
40
+ int cc = -1;
41
+
42
+ asm volatile (
43
+ " .insn rre,0xb9d00000,%[data],%[req_off]\n"
44
+ " ipm %[cc]\n"
45
+ " srl %[cc],28\n"
46
+ : [cc] "+d" (cc), [req_off] "+d" (req_off.pair)
47
+ : [data] "d" (data)
48
+ : "cc");
49
+ *status = req_off.even >> 24 & 0xff;
50
+ return cc;
51
+}
52
+
53
+int pci_write(uint32_t fhandle, uint64_t offset, uint8_t pcias, uint64_t data,
54
+ uint8_t len)
55
+{
56
+
57
+ uint64_t req = ZPCI_CREATE_REQ(fhandle, pcias, len);
58
+ uint8_t status;
59
+ int rc;
60
+
61
+ /* len must be non-zero power of 2 with a maximum of 8 bytes per write */
62
+ switch (len) {
63
+ case 1:
64
+ case 2:
65
+ case 4:
66
+ case 8:
67
+ rc = pcistg(data, req, offset, &status);
68
+ break;
69
+ default:
70
+ return -1;
71
+ }
72
+
73
+ /* Error condition detected */
74
+ if (rc != 0) {
75
+ printf("PCI store failed with status condition %d, return code %d\n",
76
+ status, rc);
77
+ return -1;
78
+ }
79
+
80
+ return 0;
81
+}
82
+
83
+int pci_read(uint32_t fhandle, uint64_t offset, uint8_t pcias, void *buf,
84
+ uint8_t len)
85
+{
86
+ uint64_t req, data;
87
+ uint8_t status;
88
+ int rc;
89
+
90
+ req = ZPCI_CREATE_REQ(fhandle, pcias, len);
91
+ rc = pcilg(&data, req, offset, &status);
92
+
93
+ /* Error condition detected */
94
+ if (rc != 0) {
95
+ printf("PCI load failed with status condition %d, return code %d\n",
96
+ status, rc);
97
+ return -1;
98
+ }
99
+
100
+ switch (len) {
101
+ case 1:
102
+ *(uint8_t *)buf = data;
103
+ break;
104
+ case 2:
105
+ *(uint16_t *)buf = data;
106
+ break;
107
+ case 4:
108
+ *(uint32_t *)buf = data;
109
+ break;
110
+ case 8:
111
+ *(uint64_t *)buf = data;
112
+ break;
113
+ default:
114
+ return -1;
115
+ }
116
+
117
+ return 0;
118
+}
pc-bios/s390-ccw/pci.h
new
+36
@@ -0,0 +1,36 @@
1
+/*
2
+ * s390x PCI definitions
3
+ *
4
+ * Copyright 2025 IBM Corp.
5
+ * Author(s): Jared Rossi <jrossi@linux.ibm.com>
6
+ *
7
+ * SPDX-License-Identifier: GPL-2.0-or-later
8
+ */
9
+
10
+#ifndef PCI_H
11
+#define PCI_H
12
+
13
+#include <stdint.h>
14
+#include <stdbool.h>
15
+#include "clp.h"
16
+
17
+#define ZPCI_CREATE_REQ(handle, space, len) \
18
+ ((uint64_t) handle << 32 | space << 16 | len)
19
+
20
+union register_pair {
21
+ unsigned __int128 pair;
22
+ struct {
23
+ unsigned long even;
24
+ unsigned long odd;
25
+ };
26
+};
27
+
28
+#define PCI_CFGBAR 0xF /* Base Address Register for config space */
29
+#define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */
30
+
31
+int pci_write(uint32_t fhandle, uint64_t offset, uint8_t pcias, uint64_t data,
32
+ uint8_t len);
33
+int pci_read(uint32_t fhandle, uint64_t offset, uint8_t pcias, void *buf,
34
+ uint8_t len);
35
+
36
+#endif