cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pci_io.h (4267B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2#ifndef _ASM_S390_PCI_IO_H
      3#define _ASM_S390_PCI_IO_H
      4
      5#ifdef CONFIG_PCI
      6
      7#include <linux/kernel.h>
      8#include <linux/slab.h>
      9#include <asm/pci_insn.h>
     10
     11/* I/O size constraints */
     12#define ZPCI_MAX_READ_SIZE	8
     13#define ZPCI_MAX_WRITE_SIZE	128
     14
     15/* I/O Map */
     16#define ZPCI_IOMAP_SHIFT		48
     17#define ZPCI_IOMAP_ADDR_SHIFT		62
     18#define ZPCI_IOMAP_ADDR_BASE		(1UL << ZPCI_IOMAP_ADDR_SHIFT)
     19#define ZPCI_IOMAP_ADDR_OFF_MASK	((1UL << ZPCI_IOMAP_SHIFT) - 1)
     20#define ZPCI_IOMAP_MAX_ENTRIES							\
     21	(1UL << (ZPCI_IOMAP_ADDR_SHIFT - ZPCI_IOMAP_SHIFT))
     22#define ZPCI_IOMAP_ADDR_IDX_MASK						\
     23	((ZPCI_IOMAP_ADDR_BASE - 1) & ~ZPCI_IOMAP_ADDR_OFF_MASK)
     24
     25struct zpci_iomap_entry {
     26	u32 fh;
     27	u8 bar;
     28	u16 count;
     29};
     30
     31extern struct zpci_iomap_entry *zpci_iomap_start;
     32
     33#define ZPCI_ADDR(idx) (ZPCI_IOMAP_ADDR_BASE | ((u64) idx << ZPCI_IOMAP_SHIFT))
     34#define ZPCI_IDX(addr)								\
     35	(((__force u64) addr & ZPCI_IOMAP_ADDR_IDX_MASK) >> ZPCI_IOMAP_SHIFT)
     36#define ZPCI_OFFSET(addr)							\
     37	((__force u64) addr & ZPCI_IOMAP_ADDR_OFF_MASK)
     38
     39#define ZPCI_CREATE_REQ(handle, space, len)					\
     40	((u64) handle << 32 | space << 16 | len)
     41
     42#define zpci_read(LENGTH, RETTYPE)						\
     43static inline RETTYPE zpci_read_##RETTYPE(const volatile void __iomem *addr)	\
     44{										\
     45	u64 data;								\
     46	int rc;									\
     47										\
     48	rc = zpci_load(&data, addr, LENGTH);					\
     49	if (rc)									\
     50		data = -1ULL;							\
     51	return (RETTYPE) data;							\
     52}
     53
     54#define zpci_write(LENGTH, VALTYPE)						\
     55static inline void zpci_write_##VALTYPE(VALTYPE val,				\
     56					const volatile void __iomem *addr)	\
     57{										\
     58	u64 data = (VALTYPE) val;						\
     59										\
     60	zpci_store(addr, data, LENGTH);						\
     61}
     62
     63zpci_read(8, u64)
     64zpci_read(4, u32)
     65zpci_read(2, u16)
     66zpci_read(1, u8)
     67zpci_write(8, u64)
     68zpci_write(4, u32)
     69zpci_write(2, u16)
     70zpci_write(1, u8)
     71
     72static inline int zpci_write_single(volatile void __iomem *dst, const void *src,
     73				    unsigned long len)
     74{
     75	u64 val;
     76
     77	switch (len) {
     78	case 1:
     79		val = (u64) *((u8 *) src);
     80		break;
     81	case 2:
     82		val = (u64) *((u16 *) src);
     83		break;
     84	case 4:
     85		val = (u64) *((u32 *) src);
     86		break;
     87	case 8:
     88		val = (u64) *((u64 *) src);
     89		break;
     90	default:
     91		val = 0;		/* let FW report error */
     92		break;
     93	}
     94	return zpci_store(dst, val, len);
     95}
     96
     97static inline int zpci_read_single(void *dst, const volatile void __iomem *src,
     98				   unsigned long len)
     99{
    100	u64 data;
    101	int cc;
    102
    103	cc = zpci_load(&data, src, len);
    104	if (cc)
    105		goto out;
    106
    107	switch (len) {
    108	case 1:
    109		*((u8 *) dst) = (u8) data;
    110		break;
    111	case 2:
    112		*((u16 *) dst) = (u16) data;
    113		break;
    114	case 4:
    115		*((u32 *) dst) = (u32) data;
    116		break;
    117	case 8:
    118		*((u64 *) dst) = (u64) data;
    119		break;
    120	}
    121out:
    122	return cc;
    123}
    124
    125int zpci_write_block(volatile void __iomem *dst, const void *src,
    126		     unsigned long len);
    127
    128static inline u8 zpci_get_max_write_size(u64 src, u64 dst, int len, int max)
    129{
    130	int count = len > max ? max : len, size = 1;
    131
    132	while (!(src & 0x1) && !(dst & 0x1) && ((size << 1) <= count)) {
    133		dst = dst >> 1;
    134		src = src >> 1;
    135		size = size << 1;
    136	}
    137	return size;
    138}
    139
    140static inline int zpci_memcpy_fromio(void *dst,
    141				     const volatile void __iomem *src,
    142				     unsigned long n)
    143{
    144	int size, rc = 0;
    145
    146	while (n > 0) {
    147		size = zpci_get_max_write_size((u64 __force) src,
    148					       (u64) dst, n,
    149					       ZPCI_MAX_READ_SIZE);
    150		rc = zpci_read_single(dst, src, size);
    151		if (rc)
    152			break;
    153		src += size;
    154		dst += size;
    155		n -= size;
    156	}
    157	return rc;
    158}
    159
    160static inline int zpci_memcpy_toio(volatile void __iomem *dst,
    161				   const void *src, unsigned long n)
    162{
    163	int size, rc = 0;
    164
    165	if (!src)
    166		return -EINVAL;
    167
    168	while (n > 0) {
    169		size = zpci_get_max_write_size((u64 __force) dst,
    170					       (u64) src, n,
    171					       ZPCI_MAX_WRITE_SIZE);
    172		if (size > 8) /* main path */
    173			rc = zpci_write_block(dst, src, size);
    174		else
    175			rc = zpci_write_single(dst, src, size);
    176		if (rc)
    177			break;
    178		src += size;
    179		dst += size;
    180		n -= size;
    181	}
    182	return rc;
    183}
    184
    185static inline int zpci_memset_io(volatile void __iomem *dst,
    186				 unsigned char val, size_t count)
    187{
    188	u8 *src = kmalloc(count, GFP_KERNEL);
    189	int rc;
    190
    191	if (src == NULL)
    192		return -ENOMEM;
    193	memset(src, val, count);
    194
    195	rc = zpci_memcpy_toio(dst, src, count);
    196	kfree(src);
    197	return rc;
    198}
    199
    200#endif /* CONFIG_PCI */
    201
    202#endif /* _ASM_S390_PCI_IO_H */