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

dmub_reg.c (3570B)


      1/*
      2 * Copyright 2019 Advanced Micro Devices, Inc.
      3 *
      4 * Permission is hereby granted, free of charge, to any person obtaining a
      5 * copy of this software and associated documentation files (the "Software"),
      6 * to deal in the Software without restriction, including without limitation
      7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 * and/or sell copies of the Software, and to permit persons to whom the
      9 * Software is furnished to do so, subject to the following conditions:
     10 *
     11 * The above copyright notice and this permission notice shall be included in
     12 * all copies or substantial portions of the Software.
     13 *
     14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20 * OTHER DEALINGS IN THE SOFTWARE.
     21 *
     22 * Authors: AMD
     23 *
     24 */
     25
     26#include "dmub_reg.h"
     27#include "../dmub_srv.h"
     28
     29struct dmub_reg_value_masks {
     30	uint32_t value;
     31	uint32_t mask;
     32};
     33
     34static inline void
     35set_reg_field_value_masks(struct dmub_reg_value_masks *field_value_mask,
     36			  uint32_t value, uint32_t mask, uint8_t shift)
     37{
     38	field_value_mask->value =
     39		(field_value_mask->value & ~mask) | (mask & (value << shift));
     40	field_value_mask->mask = field_value_mask->mask | mask;
     41}
     42
     43static void set_reg_field_values(struct dmub_reg_value_masks *field_value_mask,
     44				 uint32_t addr, int n, uint8_t shift1,
     45				 uint32_t mask1, uint32_t field_value1,
     46				 va_list ap)
     47{
     48	uint32_t shift, mask, field_value;
     49	int i = 1;
     50
     51	/* gather all bits value/mask getting updated in this register */
     52	set_reg_field_value_masks(field_value_mask, field_value1, mask1,
     53				  shift1);
     54
     55	while (i < n) {
     56		shift = va_arg(ap, uint32_t);
     57		mask = va_arg(ap, uint32_t);
     58		field_value = va_arg(ap, uint32_t);
     59
     60		set_reg_field_value_masks(field_value_mask, field_value, mask,
     61					  shift);
     62		i++;
     63	}
     64}
     65
     66static inline uint32_t get_reg_field_value_ex(uint32_t reg_value, uint32_t mask,
     67					      uint8_t shift)
     68{
     69	return (mask & reg_value) >> shift;
     70}
     71
     72void dmub_reg_update(struct dmub_srv *srv, uint32_t addr, int n, uint8_t shift1,
     73		     uint32_t mask1, uint32_t field_value1, ...)
     74{
     75	struct dmub_reg_value_masks field_value_mask = { 0 };
     76	uint32_t reg_val;
     77	va_list ap;
     78
     79	va_start(ap, field_value1);
     80	set_reg_field_values(&field_value_mask, addr, n, shift1, mask1,
     81			     field_value1, ap);
     82	va_end(ap);
     83
     84	reg_val = srv->funcs.reg_read(srv->user_ctx, addr);
     85	reg_val = (reg_val & ~field_value_mask.mask) | field_value_mask.value;
     86	srv->funcs.reg_write(srv->user_ctx, addr, reg_val);
     87}
     88
     89void dmub_reg_set(struct dmub_srv *srv, uint32_t addr, uint32_t reg_val, int n,
     90		  uint8_t shift1, uint32_t mask1, uint32_t field_value1, ...)
     91{
     92	struct dmub_reg_value_masks field_value_mask = { 0 };
     93	va_list ap;
     94
     95	va_start(ap, field_value1);
     96	set_reg_field_values(&field_value_mask, addr, n, shift1, mask1,
     97			     field_value1, ap);
     98	va_end(ap);
     99
    100	reg_val = (reg_val & ~field_value_mask.mask) | field_value_mask.value;
    101	srv->funcs.reg_write(srv->user_ctx, addr, reg_val);
    102}
    103
    104void dmub_reg_get(struct dmub_srv *srv, uint32_t addr, uint8_t shift,
    105		  uint32_t mask, uint32_t *field_value)
    106{
    107	uint32_t reg_val = srv->funcs.reg_read(srv->user_ctx, addr);
    108	*field_value = get_reg_field_value_ex(reg_val, mask, shift);
    109}