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

ipa_resource.c (5346B)


      1// SPDX-License-Identifier: GPL-2.0
      2
      3/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
      4 * Copyright (C) 2018-2021 Linaro Ltd.
      5 */
      6
      7#include <linux/types.h>
      8#include <linux/kernel.h>
      9
     10#include "ipa.h"
     11#include "ipa_data.h"
     12#include "ipa_reg.h"
     13#include "ipa_resource.h"
     14
     15/**
     16 * DOC: IPA Resources
     17 *
     18 * The IPA manages a set of resources internally for various purposes.
     19 * A given IPA version has a fixed number of resource types, and a fixed
     20 * total number of resources of each type.  "Source" resource types
     21 * are separate from "destination" resource types.
     22 *
     23 * Each version of IPA also has some number of resource groups.  Each
     24 * endpoint is assigned to a resource group, and all endpoints in the
     25 * same group share pools of each type of resource.  A subset of the
     26 * total resources of each type is assigned for use by each group.
     27 */
     28
     29static bool ipa_resource_limits_valid(struct ipa *ipa,
     30				      const struct ipa_resource_data *data)
     31{
     32	u32 group_count;
     33	u32 i;
     34	u32 j;
     35
     36	/* We program at most 8 source or destination resource group limits */
     37	BUILD_BUG_ON(IPA_RESOURCE_GROUP_MAX > 8);
     38
     39	group_count = data->rsrc_group_src_count;
     40	if (!group_count || group_count > IPA_RESOURCE_GROUP_MAX)
     41		return false;
     42
     43	/* Return an error if a non-zero resource limit is specified
     44	 * for a resource group not supported by hardware.
     45	 */
     46	for (i = 0; i < data->resource_src_count; i++) {
     47		const struct ipa_resource *resource;
     48
     49		resource = &data->resource_src[i];
     50		for (j = group_count; j < IPA_RESOURCE_GROUP_MAX; j++)
     51			if (resource->limits[j].min || resource->limits[j].max)
     52				return false;
     53	}
     54
     55	group_count = data->rsrc_group_dst_count;
     56	if (!group_count || group_count > IPA_RESOURCE_GROUP_MAX)
     57		return false;
     58
     59	for (i = 0; i < data->resource_dst_count; i++) {
     60		const struct ipa_resource *resource;
     61
     62		resource = &data->resource_dst[i];
     63		for (j = group_count; j < IPA_RESOURCE_GROUP_MAX; j++)
     64			if (resource->limits[j].min || resource->limits[j].max)
     65				return false;
     66	}
     67
     68	return true;
     69}
     70
     71static void
     72ipa_resource_config_common(struct ipa *ipa, u32 offset,
     73			   const struct ipa_resource_limits *xlimits,
     74			   const struct ipa_resource_limits *ylimits)
     75{
     76	u32 val;
     77
     78	val = u32_encode_bits(xlimits->min, X_MIN_LIM_FMASK);
     79	val |= u32_encode_bits(xlimits->max, X_MAX_LIM_FMASK);
     80	if (ylimits) {
     81		val |= u32_encode_bits(ylimits->min, Y_MIN_LIM_FMASK);
     82		val |= u32_encode_bits(ylimits->max, Y_MAX_LIM_FMASK);
     83	}
     84
     85	iowrite32(val, ipa->reg_virt + offset);
     86}
     87
     88static void ipa_resource_config_src(struct ipa *ipa, u32 resource_type,
     89				    const struct ipa_resource_data *data)
     90{
     91	u32 group_count = data->rsrc_group_src_count;
     92	const struct ipa_resource_limits *ylimits;
     93	const struct ipa_resource *resource;
     94	u32 offset;
     95
     96	resource = &data->resource_src[resource_type];
     97
     98	offset = IPA_REG_SRC_RSRC_GRP_01_RSRC_TYPE_N_OFFSET(resource_type);
     99	ylimits = group_count == 1 ? NULL : &resource->limits[1];
    100	ipa_resource_config_common(ipa, offset, &resource->limits[0], ylimits);
    101
    102	if (group_count < 3)
    103		return;
    104
    105	offset = IPA_REG_SRC_RSRC_GRP_23_RSRC_TYPE_N_OFFSET(resource_type);
    106	ylimits = group_count == 3 ? NULL : &resource->limits[3];
    107	ipa_resource_config_common(ipa, offset, &resource->limits[2], ylimits);
    108
    109	if (group_count < 5)
    110		return;
    111
    112	offset = IPA_REG_SRC_RSRC_GRP_45_RSRC_TYPE_N_OFFSET(resource_type);
    113	ylimits = group_count == 5 ? NULL : &resource->limits[5];
    114	ipa_resource_config_common(ipa, offset, &resource->limits[4], ylimits);
    115
    116	if (group_count < 7)
    117		return;
    118
    119	offset = IPA_REG_SRC_RSRC_GRP_67_RSRC_TYPE_N_OFFSET(resource_type);
    120	ylimits = group_count == 7 ? NULL : &resource->limits[7];
    121	ipa_resource_config_common(ipa, offset, &resource->limits[6], ylimits);
    122}
    123
    124static void ipa_resource_config_dst(struct ipa *ipa, u32 resource_type,
    125				    const struct ipa_resource_data *data)
    126{
    127	u32 group_count = data->rsrc_group_dst_count;
    128	const struct ipa_resource_limits *ylimits;
    129	const struct ipa_resource *resource;
    130	u32 offset;
    131
    132	resource = &data->resource_dst[resource_type];
    133
    134	offset = IPA_REG_DST_RSRC_GRP_01_RSRC_TYPE_N_OFFSET(resource_type);
    135	ylimits = group_count == 1 ? NULL : &resource->limits[1];
    136	ipa_resource_config_common(ipa, offset, &resource->limits[0], ylimits);
    137
    138	if (group_count < 3)
    139		return;
    140
    141	offset = IPA_REG_DST_RSRC_GRP_23_RSRC_TYPE_N_OFFSET(resource_type);
    142	ylimits = group_count == 3 ? NULL : &resource->limits[3];
    143	ipa_resource_config_common(ipa, offset, &resource->limits[2], ylimits);
    144
    145	if (group_count < 5)
    146		return;
    147
    148	offset = IPA_REG_DST_RSRC_GRP_45_RSRC_TYPE_N_OFFSET(resource_type);
    149	ylimits = group_count == 5 ? NULL : &resource->limits[5];
    150	ipa_resource_config_common(ipa, offset, &resource->limits[4], ylimits);
    151
    152	if (group_count < 7)
    153		return;
    154
    155	offset = IPA_REG_DST_RSRC_GRP_67_RSRC_TYPE_N_OFFSET(resource_type);
    156	ylimits = group_count == 7 ? NULL : &resource->limits[7];
    157	ipa_resource_config_common(ipa, offset, &resource->limits[6], ylimits);
    158}
    159
    160/* Configure resources; there is no ipa_resource_deconfig() */
    161int ipa_resource_config(struct ipa *ipa, const struct ipa_resource_data *data)
    162{
    163	u32 i;
    164
    165	if (!ipa_resource_limits_valid(ipa, data))
    166		return -EINVAL;
    167
    168	for (i = 0; i < data->resource_src_count; i++)
    169		ipa_resource_config_src(ipa, i, data);
    170
    171	for (i = 0; i < data->resource_dst_count; i++)
    172		ipa_resource_config_dst(ipa, i, data);
    173
    174	return 0;
    175}