mirror of https://gitlab.com/qemu-project/qemu
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
147 lines
3.3 KiB
C
147 lines
3.3 KiB
C
/*
|
|
* s390x PCI MMIO definitions
|
|
*
|
|
* Copyright 2025 IBM Corp.
|
|
* Author(s): Farhan Ali <alifm@linux.ibm.com>
|
|
*
|
|
* 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));
|
|
}
|
|
}
|