xref: /openbmc/qemu/util/s390x_pci_mmio.c (revision 6b18f6e34246ae62aefcaaa56585f14cd1a15295)
1*b17d69a1SFarhan Ali /*
2*b17d69a1SFarhan Ali  * s390x PCI MMIO definitions
3*b17d69a1SFarhan Ali  *
4*b17d69a1SFarhan Ali  * Copyright 2025 IBM Corp.
5*b17d69a1SFarhan Ali  * Author(s): Farhan Ali <alifm@linux.ibm.com>
6*b17d69a1SFarhan Ali  *
7*b17d69a1SFarhan Ali  * SPDX-License-Identifier: GPL-2.0-or-later
8*b17d69a1SFarhan Ali  */
9*b17d69a1SFarhan Ali 
10*b17d69a1SFarhan Ali #include "qemu/osdep.h"
11*b17d69a1SFarhan Ali #include <sys/syscall.h>
12*b17d69a1SFarhan Ali #include "qemu/s390x_pci_mmio.h"
13*b17d69a1SFarhan Ali #include "elf.h"
14*b17d69a1SFarhan Ali 
15*b17d69a1SFarhan Ali union register_pair {
16*b17d69a1SFarhan Ali     unsigned __int128 pair;
17*b17d69a1SFarhan Ali     struct {
18*b17d69a1SFarhan Ali         uint64_t even;
19*b17d69a1SFarhan Ali         uint64_t odd;
20*b17d69a1SFarhan Ali     };
21*b17d69a1SFarhan Ali };
22*b17d69a1SFarhan Ali 
23*b17d69a1SFarhan Ali static bool is_mio_supported;
24*b17d69a1SFarhan Ali 
check_is_mio_supported(void)25*b17d69a1SFarhan Ali static __attribute__((constructor)) void check_is_mio_supported(void)
26*b17d69a1SFarhan Ali {
27*b17d69a1SFarhan Ali     is_mio_supported = !!(qemu_getauxval(AT_HWCAP) & HWCAP_S390_PCI_MIO);
28*b17d69a1SFarhan Ali }
29*b17d69a1SFarhan Ali 
s390x_pcilgi(const void * ioaddr,size_t len)30*b17d69a1SFarhan Ali static uint64_t s390x_pcilgi(const void *ioaddr, size_t len)
31*b17d69a1SFarhan Ali {
32*b17d69a1SFarhan Ali     union register_pair ioaddr_len = { .even = (uint64_t)ioaddr,
33*b17d69a1SFarhan Ali                                        .odd = len };
34*b17d69a1SFarhan Ali     uint64_t val;
35*b17d69a1SFarhan Ali     int cc;
36*b17d69a1SFarhan Ali 
37*b17d69a1SFarhan Ali     asm volatile(
38*b17d69a1SFarhan Ali         /* pcilgi */
39*b17d69a1SFarhan Ali         ".insn   rre,0xb9d60000,%[val],%[ioaddr_len]\n"
40*b17d69a1SFarhan Ali         "ipm     %[cc]\n"
41*b17d69a1SFarhan Ali         "srl     %[cc],28\n"
42*b17d69a1SFarhan Ali         : [cc] "=d"(cc), [val] "=d"(val),
43*b17d69a1SFarhan Ali         [ioaddr_len] "+d"(ioaddr_len.pair) :: "cc");
44*b17d69a1SFarhan Ali 
45*b17d69a1SFarhan Ali     if (cc) {
46*b17d69a1SFarhan Ali         val = -1ULL;
47*b17d69a1SFarhan Ali     }
48*b17d69a1SFarhan Ali 
49*b17d69a1SFarhan Ali     return val;
50*b17d69a1SFarhan Ali }
51*b17d69a1SFarhan Ali 
s390x_pcistgi(void * ioaddr,uint64_t val,size_t len)52*b17d69a1SFarhan Ali static void s390x_pcistgi(void *ioaddr, uint64_t val, size_t len)
53*b17d69a1SFarhan Ali {
54*b17d69a1SFarhan Ali     union register_pair ioaddr_len = {.even = (uint64_t)ioaddr, .odd = len};
55*b17d69a1SFarhan Ali 
56*b17d69a1SFarhan Ali     asm volatile (
57*b17d69a1SFarhan Ali         /* pcistgi */
58*b17d69a1SFarhan Ali         ".insn   rre,0xb9d40000,%[val],%[ioaddr_len]\n"
59*b17d69a1SFarhan Ali         : [ioaddr_len] "+d" (ioaddr_len.pair)
60*b17d69a1SFarhan Ali         : [val] "d" (val)
61*b17d69a1SFarhan Ali         : "cc", "memory");
62*b17d69a1SFarhan Ali }
63*b17d69a1SFarhan Ali 
s390x_pci_mmio_read_8(const void * ioaddr)64*b17d69a1SFarhan Ali uint8_t s390x_pci_mmio_read_8(const void *ioaddr)
65*b17d69a1SFarhan Ali {
66*b17d69a1SFarhan Ali     uint8_t val = 0;
67*b17d69a1SFarhan Ali 
68*b17d69a1SFarhan Ali     if (is_mio_supported) {
69*b17d69a1SFarhan Ali         val = s390x_pcilgi(ioaddr, sizeof(val));
70*b17d69a1SFarhan Ali     } else {
71*b17d69a1SFarhan Ali         syscall(__NR_s390_pci_mmio_read, ioaddr, &val, sizeof(val));
72*b17d69a1SFarhan Ali     }
73*b17d69a1SFarhan Ali     return val;
74*b17d69a1SFarhan Ali }
75*b17d69a1SFarhan Ali 
s390x_pci_mmio_read_16(const void * ioaddr)76*b17d69a1SFarhan Ali uint16_t s390x_pci_mmio_read_16(const void *ioaddr)
77*b17d69a1SFarhan Ali {
78*b17d69a1SFarhan Ali     uint16_t val = 0;
79*b17d69a1SFarhan Ali 
80*b17d69a1SFarhan Ali     if (is_mio_supported) {
81*b17d69a1SFarhan Ali         val = s390x_pcilgi(ioaddr, sizeof(val));
82*b17d69a1SFarhan Ali     } else {
83*b17d69a1SFarhan Ali         syscall(__NR_s390_pci_mmio_read, ioaddr, &val, sizeof(val));
84*b17d69a1SFarhan Ali     }
85*b17d69a1SFarhan Ali     return val;
86*b17d69a1SFarhan Ali }
87*b17d69a1SFarhan Ali 
s390x_pci_mmio_read_32(const void * ioaddr)88*b17d69a1SFarhan Ali uint32_t s390x_pci_mmio_read_32(const void *ioaddr)
89*b17d69a1SFarhan Ali {
90*b17d69a1SFarhan Ali     uint32_t val = 0;
91*b17d69a1SFarhan Ali 
92*b17d69a1SFarhan Ali     if (is_mio_supported) {
93*b17d69a1SFarhan Ali         val = s390x_pcilgi(ioaddr, sizeof(val));
94*b17d69a1SFarhan Ali     } else {
95*b17d69a1SFarhan Ali         syscall(__NR_s390_pci_mmio_read, ioaddr, &val, sizeof(val));
96*b17d69a1SFarhan Ali     }
97*b17d69a1SFarhan Ali     return val;
98*b17d69a1SFarhan Ali }
99*b17d69a1SFarhan Ali 
s390x_pci_mmio_read_64(const void * ioaddr)100*b17d69a1SFarhan Ali uint64_t s390x_pci_mmio_read_64(const void *ioaddr)
101*b17d69a1SFarhan Ali {
102*b17d69a1SFarhan Ali     uint64_t val = 0;
103*b17d69a1SFarhan Ali 
104*b17d69a1SFarhan Ali     if (is_mio_supported) {
105*b17d69a1SFarhan Ali         val = s390x_pcilgi(ioaddr, sizeof(val));
106*b17d69a1SFarhan Ali     } else {
107*b17d69a1SFarhan Ali         syscall(__NR_s390_pci_mmio_read, ioaddr, &val, sizeof(val));
108*b17d69a1SFarhan Ali     }
109*b17d69a1SFarhan Ali     return val;
110*b17d69a1SFarhan Ali }
111*b17d69a1SFarhan Ali 
s390x_pci_mmio_write_8(void * ioaddr,uint8_t val)112*b17d69a1SFarhan Ali void s390x_pci_mmio_write_8(void *ioaddr, uint8_t val)
113*b17d69a1SFarhan Ali {
114*b17d69a1SFarhan Ali     if (is_mio_supported) {
115*b17d69a1SFarhan Ali         s390x_pcistgi(ioaddr, val, sizeof(val));
116*b17d69a1SFarhan Ali     } else {
117*b17d69a1SFarhan Ali         syscall(__NR_s390_pci_mmio_write, ioaddr, &val, sizeof(val));
118*b17d69a1SFarhan Ali     }
119*b17d69a1SFarhan Ali }
120*b17d69a1SFarhan Ali 
s390x_pci_mmio_write_16(void * ioaddr,uint16_t val)121*b17d69a1SFarhan Ali void s390x_pci_mmio_write_16(void *ioaddr, uint16_t val)
122*b17d69a1SFarhan Ali {
123*b17d69a1SFarhan Ali     if (is_mio_supported) {
124*b17d69a1SFarhan Ali         s390x_pcistgi(ioaddr, val, sizeof(val));
125*b17d69a1SFarhan Ali     } else {
126*b17d69a1SFarhan Ali         syscall(__NR_s390_pci_mmio_write, ioaddr, &val, sizeof(val));
127*b17d69a1SFarhan Ali     }
128*b17d69a1SFarhan Ali }
129*b17d69a1SFarhan Ali 
s390x_pci_mmio_write_32(void * ioaddr,uint32_t val)130*b17d69a1SFarhan Ali void s390x_pci_mmio_write_32(void *ioaddr, uint32_t val)
131*b17d69a1SFarhan Ali {
132*b17d69a1SFarhan Ali     if (is_mio_supported) {
133*b17d69a1SFarhan Ali         s390x_pcistgi(ioaddr, val, sizeof(val));
134*b17d69a1SFarhan Ali     } else {
135*b17d69a1SFarhan Ali         syscall(__NR_s390_pci_mmio_write, ioaddr, &val, sizeof(val));
136*b17d69a1SFarhan Ali     }
137*b17d69a1SFarhan Ali }
138*b17d69a1SFarhan Ali 
s390x_pci_mmio_write_64(void * ioaddr,uint64_t val)139*b17d69a1SFarhan Ali void s390x_pci_mmio_write_64(void *ioaddr, uint64_t val)
140*b17d69a1SFarhan Ali {
141*b17d69a1SFarhan Ali     if (is_mio_supported) {
142*b17d69a1SFarhan Ali         s390x_pcistgi(ioaddr, val, sizeof(val));
143*b17d69a1SFarhan Ali     } else {
144*b17d69a1SFarhan Ali         syscall(__NR_s390_pci_mmio_write, ioaddr, &val, sizeof(val));
145*b17d69a1SFarhan Ali     }
146*b17d69a1SFarhan Ali }
147