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

crdump.c (2516B)


      1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
      2/* Copyright (c) 2019 Mellanox Technologies */
      3
      4#include <linux/mlx5/driver.h>
      5#include "mlx5_core.h"
      6#include "lib/pci_vsc.h"
      7#include "lib/mlx5.h"
      8
      9#define BAD_ACCESS			0xBADACCE5
     10#define MLX5_PROTECTED_CR_SCAN_CRSPACE	0x7
     11
     12static bool mlx5_crdump_enabled(struct mlx5_core_dev *dev)
     13{
     14	return !!dev->priv.health.crdump_size;
     15}
     16
     17static int mlx5_crdump_fill(struct mlx5_core_dev *dev, u32 *cr_data)
     18{
     19	u32 crdump_size = dev->priv.health.crdump_size;
     20	int i, ret;
     21
     22	for (i = 0; i < (crdump_size / 4); i++)
     23		cr_data[i] = BAD_ACCESS;
     24
     25	ret = mlx5_vsc_gw_read_block_fast(dev, cr_data, crdump_size);
     26	if (ret <= 0) {
     27		if (ret == 0)
     28			return -EIO;
     29		return ret;
     30	}
     31
     32	if (crdump_size != ret) {
     33		mlx5_core_warn(dev, "failed to read full dump, read %d out of %u\n",
     34			       ret, crdump_size);
     35		return -EINVAL;
     36	}
     37
     38	return 0;
     39}
     40
     41int mlx5_crdump_collect(struct mlx5_core_dev *dev, u32 *cr_data)
     42{
     43	int ret;
     44
     45	if (!mlx5_crdump_enabled(dev))
     46		return -ENODEV;
     47
     48	ret = mlx5_vsc_gw_lock(dev);
     49	if (ret) {
     50		mlx5_core_warn(dev, "crdump: failed to lock vsc gw err %d\n",
     51			       ret);
     52		return ret;
     53	}
     54	/* Verify no other PF is running cr-dump or sw reset */
     55	ret = mlx5_vsc_sem_set_space(dev, MLX5_SEMAPHORE_SW_RESET,
     56				     MLX5_VSC_LOCK);
     57	if (ret) {
     58		mlx5_core_warn(dev, "Failed to lock SW reset semaphore\n");
     59		goto unlock_gw;
     60	}
     61
     62	ret = mlx5_vsc_gw_set_space(dev, MLX5_VSC_SPACE_SCAN_CRSPACE, NULL);
     63	if (ret)
     64		goto unlock_sem;
     65
     66	ret = mlx5_crdump_fill(dev, cr_data);
     67
     68unlock_sem:
     69	mlx5_vsc_sem_set_space(dev, MLX5_SEMAPHORE_SW_RESET, MLX5_VSC_UNLOCK);
     70unlock_gw:
     71	mlx5_vsc_gw_unlock(dev);
     72	return ret;
     73}
     74
     75int mlx5_crdump_enable(struct mlx5_core_dev *dev)
     76{
     77	struct mlx5_priv *priv = &dev->priv;
     78	u32 space_size;
     79	int ret;
     80
     81	if (!mlx5_core_is_pf(dev) || !mlx5_vsc_accessible(dev) ||
     82	    mlx5_crdump_enabled(dev))
     83		return 0;
     84
     85	ret = mlx5_vsc_gw_lock(dev);
     86	if (ret)
     87		return ret;
     88
     89	/* Check if space is supported and get space size */
     90	ret = mlx5_vsc_gw_set_space(dev, MLX5_VSC_SPACE_SCAN_CRSPACE,
     91				    &space_size);
     92	if (ret) {
     93		/* Unlock and mask error since space is not supported */
     94		mlx5_vsc_gw_unlock(dev);
     95		return 0;
     96	}
     97
     98	if (!space_size) {
     99		mlx5_core_warn(dev, "Invalid Crspace size, zero\n");
    100		mlx5_vsc_gw_unlock(dev);
    101		return -EINVAL;
    102	}
    103
    104	ret = mlx5_vsc_gw_unlock(dev);
    105	if (ret)
    106		return ret;
    107
    108	priv->health.crdump_size = space_size;
    109	return 0;
    110}
    111
    112void mlx5_crdump_disable(struct mlx5_core_dev *dev)
    113{
    114	dev->priv.health.crdump_size = 0;
    115}