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

msr.c (2364B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include <linux/export.h>
      3#include <linux/percpu.h>
      4#include <linux/preempt.h>
      5#include <asm/msr.h>
      6#define CREATE_TRACE_POINTS
      7#include <asm/msr-trace.h>
      8
      9struct msr *msrs_alloc(void)
     10{
     11	struct msr *msrs = NULL;
     12
     13	msrs = alloc_percpu(struct msr);
     14	if (!msrs) {
     15		pr_warn("%s: error allocating msrs\n", __func__);
     16		return NULL;
     17	}
     18
     19	return msrs;
     20}
     21EXPORT_SYMBOL(msrs_alloc);
     22
     23void msrs_free(struct msr *msrs)
     24{
     25	free_percpu(msrs);
     26}
     27EXPORT_SYMBOL(msrs_free);
     28
     29/**
     30 * Read an MSR with error handling
     31 *
     32 * @msr: MSR to read
     33 * @m: value to read into
     34 *
     35 * It returns read data only on success, otherwise it doesn't change the output
     36 * argument @m.
     37 *
     38 */
     39static int msr_read(u32 msr, struct msr *m)
     40{
     41	int err;
     42	u64 val;
     43
     44	err = rdmsrl_safe(msr, &val);
     45	if (!err)
     46		m->q = val;
     47
     48	return err;
     49}
     50
     51/**
     52 * Write an MSR with error handling
     53 *
     54 * @msr: MSR to write
     55 * @m: value to write
     56 */
     57static int msr_write(u32 msr, struct msr *m)
     58{
     59	return wrmsrl_safe(msr, m->q);
     60}
     61
     62static inline int __flip_bit(u32 msr, u8 bit, bool set)
     63{
     64	struct msr m, m1;
     65	int err = -EINVAL;
     66
     67	if (bit > 63)
     68		return err;
     69
     70	err = msr_read(msr, &m);
     71	if (err)
     72		return err;
     73
     74	m1 = m;
     75	if (set)
     76		m1.q |=  BIT_64(bit);
     77	else
     78		m1.q &= ~BIT_64(bit);
     79
     80	if (m1.q == m.q)
     81		return 0;
     82
     83	err = msr_write(msr, &m1);
     84	if (err)
     85		return err;
     86
     87	return 1;
     88}
     89
     90/**
     91 * Set @bit in a MSR @msr.
     92 *
     93 * Retval:
     94 * < 0: An error was encountered.
     95 * = 0: Bit was already set.
     96 * > 0: Hardware accepted the MSR write.
     97 */
     98int msr_set_bit(u32 msr, u8 bit)
     99{
    100	return __flip_bit(msr, bit, true);
    101}
    102
    103/**
    104 * Clear @bit in a MSR @msr.
    105 *
    106 * Retval:
    107 * < 0: An error was encountered.
    108 * = 0: Bit was already cleared.
    109 * > 0: Hardware accepted the MSR write.
    110 */
    111int msr_clear_bit(u32 msr, u8 bit)
    112{
    113	return __flip_bit(msr, bit, false);
    114}
    115
    116#ifdef CONFIG_TRACEPOINTS
    117void do_trace_write_msr(unsigned int msr, u64 val, int failed)
    118{
    119	trace_write_msr(msr, val, failed);
    120}
    121EXPORT_SYMBOL(do_trace_write_msr);
    122EXPORT_TRACEPOINT_SYMBOL(write_msr);
    123
    124void do_trace_read_msr(unsigned int msr, u64 val, int failed)
    125{
    126	trace_read_msr(msr, val, failed);
    127}
    128EXPORT_SYMBOL(do_trace_read_msr);
    129EXPORT_TRACEPOINT_SYMBOL(read_msr);
    130
    131void do_trace_rdpmc(unsigned counter, u64 val, int failed)
    132{
    133	trace_rdpmc(counter, val, failed);
    134}
    135EXPORT_SYMBOL(do_trace_rdpmc);
    136EXPORT_TRACEPOINT_SYMBOL(rdpmc);
    137
    138#endif