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

trap.c (7840B)


      1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
      2/* Copyright (c) 2020 Mellanox Technologies */
      3
      4#include <net/page_pool.h>
      5#include "en/txrx.h"
      6#include "en/params.h"
      7#include "en/trap.h"
      8
      9static int mlx5e_trap_napi_poll(struct napi_struct *napi, int budget)
     10{
     11	struct mlx5e_trap *trap_ctx = container_of(napi, struct mlx5e_trap, napi);
     12	struct mlx5e_ch_stats *ch_stats = trap_ctx->stats;
     13	struct mlx5e_rq *rq = &trap_ctx->rq;
     14	bool busy = false;
     15	int work_done = 0;
     16
     17	rcu_read_lock();
     18
     19	ch_stats->poll++;
     20
     21	work_done = mlx5e_poll_rx_cq(&rq->cq, budget);
     22	busy |= work_done == budget;
     23	busy |= rq->post_wqes(rq);
     24
     25	if (busy) {
     26		work_done = budget;
     27		goto out;
     28	}
     29
     30	if (unlikely(!napi_complete_done(napi, work_done)))
     31		goto out;
     32
     33	mlx5e_cq_arm(&rq->cq);
     34
     35out:
     36	rcu_read_unlock();
     37	return work_done;
     38}
     39
     40static void mlx5e_init_trap_rq(struct mlx5e_trap *t, struct mlx5e_params *params,
     41			       struct mlx5e_rq *rq)
     42{
     43	struct mlx5_core_dev *mdev = t->mdev;
     44	struct mlx5e_priv *priv = t->priv;
     45
     46	rq->wq_type      = params->rq_wq_type;
     47	rq->pdev         = t->pdev;
     48	rq->netdev       = priv->netdev;
     49	rq->priv         = priv;
     50	rq->clock        = &mdev->clock;
     51	rq->tstamp       = &priv->tstamp;
     52	rq->mdev         = mdev;
     53	rq->hw_mtu       = MLX5E_SW2HW_MTU(params, params->sw_mtu);
     54	rq->stats        = &priv->trap_stats.rq;
     55	rq->ptp_cyc2time = mlx5_rq_ts_translator(mdev);
     56	xdp_rxq_info_unused(&rq->xdp_rxq);
     57	mlx5e_rq_set_trap_handlers(rq, params);
     58}
     59
     60static int mlx5e_open_trap_rq(struct mlx5e_priv *priv, struct mlx5e_trap *t)
     61{
     62	struct mlx5e_rq_param *rq_param = &t->rq_param;
     63	struct mlx5_core_dev *mdev = priv->mdev;
     64	struct mlx5e_create_cq_param ccp = {};
     65	struct dim_cq_moder trap_moder = {};
     66	struct mlx5e_rq *rq = &t->rq;
     67	int node;
     68	int err;
     69
     70	node = dev_to_node(mdev->device);
     71
     72	ccp.node     = node;
     73	ccp.ch_stats = t->stats;
     74	ccp.napi     = &t->napi;
     75	ccp.ix       = 0;
     76	err = mlx5e_open_cq(priv, trap_moder, &rq_param->cqp, &ccp, &rq->cq);
     77	if (err)
     78		return err;
     79
     80	mlx5e_init_trap_rq(t, &t->params, rq);
     81	err = mlx5e_open_rq(&t->params, rq_param, NULL, node, rq);
     82	if (err)
     83		goto err_destroy_cq;
     84
     85	return 0;
     86
     87err_destroy_cq:
     88	mlx5e_close_cq(&rq->cq);
     89
     90	return err;
     91}
     92
     93static void mlx5e_close_trap_rq(struct mlx5e_rq *rq)
     94{
     95	mlx5e_close_rq(rq);
     96	mlx5e_close_cq(&rq->cq);
     97}
     98
     99static int mlx5e_create_trap_direct_rq_tir(struct mlx5_core_dev *mdev, struct mlx5e_tir *tir,
    100					   u32 rqn)
    101{
    102	struct mlx5e_tir_builder *builder;
    103	int err;
    104
    105	builder = mlx5e_tir_builder_alloc(false);
    106	if (!builder)
    107		return -ENOMEM;
    108
    109	mlx5e_tir_builder_build_inline(builder, mdev->mlx5e_res.hw_objs.td.tdn, rqn);
    110	err = mlx5e_tir_init(tir, builder, mdev, true);
    111
    112	mlx5e_tir_builder_free(builder);
    113
    114	return err;
    115}
    116
    117static void mlx5e_build_trap_params(struct mlx5_core_dev *mdev,
    118				    int max_mtu, u16 q_counter,
    119				    struct mlx5e_trap *t)
    120{
    121	struct mlx5e_params *params = &t->params;
    122
    123	params->rq_wq_type = MLX5_WQ_TYPE_CYCLIC;
    124	mlx5e_init_rq_type_params(mdev, params);
    125	params->sw_mtu = max_mtu;
    126	mlx5e_build_rq_param(mdev, params, NULL, q_counter, &t->rq_param);
    127}
    128
    129static struct mlx5e_trap *mlx5e_open_trap(struct mlx5e_priv *priv)
    130{
    131	int cpu = cpumask_first(mlx5_comp_irq_get_affinity_mask(priv->mdev, 0));
    132	struct net_device *netdev = priv->netdev;
    133	struct mlx5e_trap *t;
    134	int err;
    135
    136	t = kvzalloc_node(sizeof(*t), GFP_KERNEL, cpu_to_node(cpu));
    137	if (!t)
    138		return ERR_PTR(-ENOMEM);
    139
    140	mlx5e_build_trap_params(priv->mdev, netdev->max_mtu, priv->q_counter, t);
    141
    142	t->priv     = priv;
    143	t->mdev     = priv->mdev;
    144	t->tstamp   = &priv->tstamp;
    145	t->pdev     = mlx5_core_dma_dev(priv->mdev);
    146	t->netdev   = priv->netdev;
    147	t->mkey_be  = cpu_to_be32(priv->mdev->mlx5e_res.hw_objs.mkey);
    148	t->stats    = &priv->trap_stats.ch;
    149
    150	netif_napi_add(netdev, &t->napi, mlx5e_trap_napi_poll, 64);
    151
    152	err = mlx5e_open_trap_rq(priv, t);
    153	if (unlikely(err))
    154		goto err_napi_del;
    155
    156	err = mlx5e_create_trap_direct_rq_tir(t->mdev, &t->tir, t->rq.rqn);
    157	if (err)
    158		goto err_close_trap_rq;
    159
    160	return t;
    161
    162err_close_trap_rq:
    163	mlx5e_close_trap_rq(&t->rq);
    164err_napi_del:
    165	netif_napi_del(&t->napi);
    166	kvfree(t);
    167	return ERR_PTR(err);
    168}
    169
    170void mlx5e_close_trap(struct mlx5e_trap *trap)
    171{
    172	mlx5e_tir_destroy(&trap->tir);
    173	mlx5e_close_trap_rq(&trap->rq);
    174	netif_napi_del(&trap->napi);
    175	kvfree(trap);
    176}
    177
    178static void mlx5e_activate_trap(struct mlx5e_trap *trap)
    179{
    180	napi_enable(&trap->napi);
    181	mlx5e_activate_rq(&trap->rq);
    182	mlx5e_trigger_napi_sched(&trap->napi);
    183}
    184
    185void mlx5e_deactivate_trap(struct mlx5e_priv *priv)
    186{
    187	struct mlx5e_trap *trap = priv->en_trap;
    188
    189	mlx5e_deactivate_rq(&trap->rq);
    190	napi_disable(&trap->napi);
    191}
    192
    193static struct mlx5e_trap *mlx5e_add_trap_queue(struct mlx5e_priv *priv)
    194{
    195	struct mlx5e_trap *trap;
    196
    197	trap = mlx5e_open_trap(priv);
    198	if (IS_ERR(trap))
    199		goto out;
    200
    201	mlx5e_activate_trap(trap);
    202out:
    203	return trap;
    204}
    205
    206static void mlx5e_del_trap_queue(struct mlx5e_priv *priv)
    207{
    208	mlx5e_deactivate_trap(priv);
    209	mlx5e_close_trap(priv->en_trap);
    210	priv->en_trap = NULL;
    211}
    212
    213static int mlx5e_trap_get_tirn(struct mlx5e_trap *en_trap)
    214{
    215	return en_trap->tir.tirn;
    216}
    217
    218static int mlx5e_handle_action_trap(struct mlx5e_priv *priv, int trap_id)
    219{
    220	bool open_queue = !priv->en_trap;
    221	struct mlx5e_trap *trap;
    222	int err;
    223
    224	if (open_queue) {
    225		trap = mlx5e_add_trap_queue(priv);
    226		if (IS_ERR(trap))
    227			return PTR_ERR(trap);
    228		priv->en_trap = trap;
    229	}
    230
    231	switch (trap_id) {
    232	case DEVLINK_TRAP_GENERIC_ID_INGRESS_VLAN_FILTER:
    233		err = mlx5e_add_vlan_trap(priv, trap_id, mlx5e_trap_get_tirn(priv->en_trap));
    234		if (err)
    235			goto err_out;
    236		break;
    237	case DEVLINK_TRAP_GENERIC_ID_DMAC_FILTER:
    238		err = mlx5e_add_mac_trap(priv, trap_id, mlx5e_trap_get_tirn(priv->en_trap));
    239		if (err)
    240			goto err_out;
    241		break;
    242	default:
    243		netdev_warn(priv->netdev, "%s: Unknown trap id %d\n", __func__, trap_id);
    244		err = -EINVAL;
    245		goto err_out;
    246	}
    247	return 0;
    248
    249err_out:
    250	if (open_queue)
    251		mlx5e_del_trap_queue(priv);
    252	return err;
    253}
    254
    255static int mlx5e_handle_action_drop(struct mlx5e_priv *priv, int trap_id)
    256{
    257	switch (trap_id) {
    258	case DEVLINK_TRAP_GENERIC_ID_INGRESS_VLAN_FILTER:
    259		mlx5e_remove_vlan_trap(priv);
    260		break;
    261	case DEVLINK_TRAP_GENERIC_ID_DMAC_FILTER:
    262		mlx5e_remove_mac_trap(priv);
    263		break;
    264	default:
    265		netdev_warn(priv->netdev, "%s: Unknown trap id %d\n", __func__, trap_id);
    266		return -EINVAL;
    267	}
    268	if (priv->en_trap && !mlx5_devlink_trap_get_num_active(priv->mdev))
    269		mlx5e_del_trap_queue(priv);
    270
    271	return 0;
    272}
    273
    274int mlx5e_handle_trap_event(struct mlx5e_priv *priv, struct mlx5_trap_ctx *trap_ctx)
    275{
    276	int err = 0;
    277
    278	/* Traps are unarmed when interface is down, no need to update
    279	 * them. The configuration is saved in the core driver,
    280	 * queried and applied upon interface up operation in
    281	 * mlx5e_open_locked().
    282	 */
    283	if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
    284		return 0;
    285
    286	switch (trap_ctx->action) {
    287	case DEVLINK_TRAP_ACTION_TRAP:
    288		err = mlx5e_handle_action_trap(priv, trap_ctx->id);
    289		break;
    290	case DEVLINK_TRAP_ACTION_DROP:
    291		err = mlx5e_handle_action_drop(priv, trap_ctx->id);
    292		break;
    293	default:
    294		netdev_warn(priv->netdev, "%s: Unsupported action %d\n", __func__,
    295			    trap_ctx->action);
    296		err = -EINVAL;
    297	}
    298	return err;
    299}
    300
    301static int mlx5e_apply_trap(struct mlx5e_priv *priv, int trap_id, bool enable)
    302{
    303	enum devlink_trap_action action;
    304	int err;
    305
    306	err = mlx5_devlink_traps_get_action(priv->mdev, trap_id, &action);
    307	if (err)
    308		return err;
    309	if (action == DEVLINK_TRAP_ACTION_TRAP)
    310		err = enable ? mlx5e_handle_action_trap(priv, trap_id) :
    311			       mlx5e_handle_action_drop(priv, trap_id);
    312	return err;
    313}
    314
    315static const int mlx5e_traps_arr[] = {
    316	DEVLINK_TRAP_GENERIC_ID_INGRESS_VLAN_FILTER,
    317	DEVLINK_TRAP_GENERIC_ID_DMAC_FILTER,
    318};
    319
    320int mlx5e_apply_traps(struct mlx5e_priv *priv, bool enable)
    321{
    322	int err;
    323	int i;
    324
    325	for (i = 0; i < ARRAY_SIZE(mlx5e_traps_arr); i++) {
    326		err = mlx5e_apply_trap(priv, mlx5e_traps_arr[i], enable);
    327		if (err)
    328			return err;
    329	}
    330	return 0;
    331}