Files
Yaya48 cf256aa081 Import QEMU upstream snapshot d2e570c
Upstream: https://gitlab.com/qemu-project/qemu.git

Upstream-Commit: d2e570cc0f97b936902a5b1b86b73c0f5998b475
2026-08-31 02:15:30 +02:00

147 lines
3.3 KiB
C

/*
* s390x PCI MMIO definitions
*
* Copyright 2025 IBM Corp.
* Author(s): Farhan Ali <[email protected]>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "qemu/osdep.h"
#include <sys/syscall.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");
}
uint8_t s390x_pci_mmio_read_8(const void *ioaddr)
{
uint8_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;
}
uint16_t s390x_pci_mmio_read_16(const void *ioaddr)
{
uint16_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;
}
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_8(void *ioaddr, uint8_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_16(void *ioaddr, uint16_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));
}
}
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));
}
}