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

pasid.c (2150B)


      1// SPDX-License-Identifier: GPL-2.0+
      2// Copyright 2017 IBM Corp.
      3#include "ocxl_internal.h"
      4
      5
      6struct id_range {
      7	struct list_head list;
      8	u32 start;
      9	u32 end;
     10};
     11
     12#ifdef DEBUG
     13static void dump_list(struct list_head *head, char *type_str)
     14{
     15	struct id_range *cur;
     16
     17	pr_debug("%s ranges allocated:\n", type_str);
     18	list_for_each_entry(cur, head, list) {
     19		pr_debug("Range %d->%d\n", cur->start, cur->end);
     20	}
     21}
     22#endif
     23
     24static int range_alloc(struct list_head *head, u32 size, int max_id,
     25		char *type_str)
     26{
     27	struct list_head *pos;
     28	struct id_range *cur, *new;
     29	int rc, last_end;
     30
     31	new = kmalloc(sizeof(struct id_range), GFP_KERNEL);
     32	if (!new)
     33		return -ENOMEM;
     34
     35	pos = head;
     36	last_end = -1;
     37	list_for_each_entry(cur, head, list) {
     38		if ((cur->start - last_end) > size)
     39			break;
     40		last_end = cur->end;
     41		pos = &cur->list;
     42	}
     43
     44	new->start = last_end + 1;
     45	new->end = new->start + size - 1;
     46
     47	if (new->end > max_id) {
     48		kfree(new);
     49		rc = -ENOSPC;
     50	} else {
     51		list_add(&new->list, pos);
     52		rc = new->start;
     53	}
     54
     55#ifdef DEBUG
     56	dump_list(head, type_str);
     57#endif
     58	return rc;
     59}
     60
     61static void range_free(struct list_head *head, u32 start, u32 size,
     62		char *type_str)
     63{
     64	bool found = false;
     65	struct id_range *cur, *tmp;
     66
     67	list_for_each_entry_safe(cur, tmp, head, list) {
     68		if (cur->start == start && cur->end == (start + size - 1)) {
     69			found = true;
     70			list_del(&cur->list);
     71			kfree(cur);
     72			break;
     73		}
     74	}
     75	WARN_ON(!found);
     76#ifdef DEBUG
     77	dump_list(head, type_str);
     78#endif
     79}
     80
     81int ocxl_pasid_afu_alloc(struct ocxl_fn *fn, u32 size)
     82{
     83	int max_pasid;
     84
     85	if (fn->config.max_pasid_log < 0)
     86		return -ENOSPC;
     87	max_pasid = 1 << fn->config.max_pasid_log;
     88	return range_alloc(&fn->pasid_list, size, max_pasid, "afu pasid");
     89}
     90
     91void ocxl_pasid_afu_free(struct ocxl_fn *fn, u32 start, u32 size)
     92{
     93	return range_free(&fn->pasid_list, start, size, "afu pasid");
     94}
     95
     96int ocxl_actag_afu_alloc(struct ocxl_fn *fn, u32 size)
     97{
     98	int max_actag;
     99
    100	max_actag = fn->actag_enabled;
    101	return range_alloc(&fn->actag_list, size, max_actag, "afu actag");
    102}
    103
    104void ocxl_actag_afu_free(struct ocxl_fn *fn, u32 start, u32 size)
    105{
    106	return range_free(&fn->actag_list, start, size, "afu actag");
    107}