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

mmio.c (4878B)


      1// SPDX-License-Identifier: GPL-2.0+
      2// Copyright 2019 IBM Corp.
      3#include <linux/sched/mm.h>
      4#include "trace.h"
      5#include "ocxl_internal.h"
      6
      7int ocxl_global_mmio_read32(struct ocxl_afu *afu, size_t offset,
      8				enum ocxl_endian endian, u32 *val)
      9{
     10	if (offset > afu->config.global_mmio_size - 4)
     11		return -EINVAL;
     12
     13#ifdef __BIG_ENDIAN__
     14	if (endian == OCXL_HOST_ENDIAN)
     15		endian = OCXL_BIG_ENDIAN;
     16#endif
     17
     18	switch (endian) {
     19	case OCXL_BIG_ENDIAN:
     20		*val = readl_be((char *)afu->global_mmio_ptr + offset);
     21		break;
     22
     23	default:
     24		*val = readl((char *)afu->global_mmio_ptr + offset);
     25		break;
     26	}
     27
     28	return 0;
     29}
     30EXPORT_SYMBOL_GPL(ocxl_global_mmio_read32);
     31
     32int ocxl_global_mmio_read64(struct ocxl_afu *afu, size_t offset,
     33				enum ocxl_endian endian, u64 *val)
     34{
     35	if (offset > afu->config.global_mmio_size - 8)
     36		return -EINVAL;
     37
     38#ifdef __BIG_ENDIAN__
     39	if (endian == OCXL_HOST_ENDIAN)
     40		endian = OCXL_BIG_ENDIAN;
     41#endif
     42
     43	switch (endian) {
     44	case OCXL_BIG_ENDIAN:
     45		*val = readq_be((char *)afu->global_mmio_ptr + offset);
     46		break;
     47
     48	default:
     49		*val = readq((char *)afu->global_mmio_ptr + offset);
     50		break;
     51	}
     52
     53	return 0;
     54}
     55EXPORT_SYMBOL_GPL(ocxl_global_mmio_read64);
     56
     57int ocxl_global_mmio_write32(struct ocxl_afu *afu, size_t offset,
     58				enum ocxl_endian endian, u32 val)
     59{
     60	if (offset > afu->config.global_mmio_size - 4)
     61		return -EINVAL;
     62
     63#ifdef __BIG_ENDIAN__
     64	if (endian == OCXL_HOST_ENDIAN)
     65		endian = OCXL_BIG_ENDIAN;
     66#endif
     67
     68	switch (endian) {
     69	case OCXL_BIG_ENDIAN:
     70		writel_be(val, (char *)afu->global_mmio_ptr + offset);
     71		break;
     72
     73	default:
     74		writel(val, (char *)afu->global_mmio_ptr + offset);
     75		break;
     76	}
     77
     78
     79	return 0;
     80}
     81EXPORT_SYMBOL_GPL(ocxl_global_mmio_write32);
     82
     83int ocxl_global_mmio_write64(struct ocxl_afu *afu, size_t offset,
     84				enum ocxl_endian endian, u64 val)
     85{
     86	if (offset > afu->config.global_mmio_size - 8)
     87		return -EINVAL;
     88
     89#ifdef __BIG_ENDIAN__
     90	if (endian == OCXL_HOST_ENDIAN)
     91		endian = OCXL_BIG_ENDIAN;
     92#endif
     93
     94	switch (endian) {
     95	case OCXL_BIG_ENDIAN:
     96		writeq_be(val, (char *)afu->global_mmio_ptr + offset);
     97		break;
     98
     99	default:
    100		writeq(val, (char *)afu->global_mmio_ptr + offset);
    101		break;
    102	}
    103
    104
    105	return 0;
    106}
    107EXPORT_SYMBOL_GPL(ocxl_global_mmio_write64);
    108
    109int ocxl_global_mmio_set32(struct ocxl_afu *afu, size_t offset,
    110				enum ocxl_endian endian, u32 mask)
    111{
    112	u32 tmp;
    113
    114	if (offset > afu->config.global_mmio_size - 4)
    115		return -EINVAL;
    116
    117#ifdef __BIG_ENDIAN__
    118	if (endian == OCXL_HOST_ENDIAN)
    119		endian = OCXL_BIG_ENDIAN;
    120#endif
    121
    122	switch (endian) {
    123	case OCXL_BIG_ENDIAN:
    124		tmp = readl_be((char *)afu->global_mmio_ptr + offset);
    125		tmp |= mask;
    126		writel_be(tmp, (char *)afu->global_mmio_ptr + offset);
    127		break;
    128
    129	default:
    130		tmp = readl((char *)afu->global_mmio_ptr + offset);
    131		tmp |= mask;
    132		writel(tmp, (char *)afu->global_mmio_ptr + offset);
    133		break;
    134	}
    135
    136	return 0;
    137}
    138EXPORT_SYMBOL_GPL(ocxl_global_mmio_set32);
    139
    140int ocxl_global_mmio_set64(struct ocxl_afu *afu, size_t offset,
    141				enum ocxl_endian endian, u64 mask)
    142{
    143	u64 tmp;
    144
    145	if (offset > afu->config.global_mmio_size - 8)
    146		return -EINVAL;
    147
    148#ifdef __BIG_ENDIAN__
    149	if (endian == OCXL_HOST_ENDIAN)
    150		endian = OCXL_BIG_ENDIAN;
    151#endif
    152
    153	switch (endian) {
    154	case OCXL_BIG_ENDIAN:
    155		tmp = readq_be((char *)afu->global_mmio_ptr + offset);
    156		tmp |= mask;
    157		writeq_be(tmp, (char *)afu->global_mmio_ptr + offset);
    158		break;
    159
    160	default:
    161		tmp = readq((char *)afu->global_mmio_ptr + offset);
    162		tmp |= mask;
    163		writeq(tmp, (char *)afu->global_mmio_ptr + offset);
    164		break;
    165	}
    166
    167	return 0;
    168}
    169EXPORT_SYMBOL_GPL(ocxl_global_mmio_set64);
    170
    171int ocxl_global_mmio_clear32(struct ocxl_afu *afu, size_t offset,
    172				enum ocxl_endian endian, u32 mask)
    173{
    174	u32 tmp;
    175
    176	if (offset > afu->config.global_mmio_size - 4)
    177		return -EINVAL;
    178
    179#ifdef __BIG_ENDIAN__
    180	if (endian == OCXL_HOST_ENDIAN)
    181		endian = OCXL_BIG_ENDIAN;
    182#endif
    183
    184	switch (endian) {
    185	case OCXL_BIG_ENDIAN:
    186		tmp = readl_be((char *)afu->global_mmio_ptr + offset);
    187		tmp &= ~mask;
    188		writel_be(tmp, (char *)afu->global_mmio_ptr + offset);
    189		break;
    190
    191	default:
    192		tmp = readl((char *)afu->global_mmio_ptr + offset);
    193		tmp &= ~mask;
    194		writel(tmp, (char *)afu->global_mmio_ptr + offset);
    195		break;
    196	}
    197
    198
    199	return 0;
    200}
    201EXPORT_SYMBOL_GPL(ocxl_global_mmio_clear32);
    202
    203int ocxl_global_mmio_clear64(struct ocxl_afu *afu, size_t offset,
    204				enum ocxl_endian endian, u64 mask)
    205{
    206	u64 tmp;
    207
    208	if (offset > afu->config.global_mmio_size - 8)
    209		return -EINVAL;
    210
    211#ifdef __BIG_ENDIAN__
    212	if (endian == OCXL_HOST_ENDIAN)
    213		endian = OCXL_BIG_ENDIAN;
    214#endif
    215
    216	switch (endian) {
    217	case OCXL_BIG_ENDIAN:
    218		tmp = readq_be((char *)afu->global_mmio_ptr + offset);
    219		tmp &= ~mask;
    220		writeq_be(tmp, (char *)afu->global_mmio_ptr + offset);
    221		break;
    222
    223	default:
    224		tmp = readq((char *)afu->global_mmio_ptr + offset);
    225		tmp &= ~mask;
    226		writeq(tmp, (char *)afu->global_mmio_ptr + offset);
    227		break;
    228	}
    229
    230	writeq(tmp, (char *)afu->global_mmio_ptr + offset);
    231
    232	return 0;
    233}
    234EXPORT_SYMBOL_GPL(ocxl_global_mmio_clear64);