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 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 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 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 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 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 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 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 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 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 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 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