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-smp.c (5466B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include <linux/export.h>
      3#include <linux/preempt.h>
      4#include <linux/smp.h>
      5#include <linux/completion.h>
      6#include <asm/msr.h>
      7
      8static void __rdmsr_on_cpu(void *info)
      9{
     10	struct msr_info *rv = info;
     11	struct msr *reg;
     12	int this_cpu = raw_smp_processor_id();
     13
     14	if (rv->msrs)
     15		reg = per_cpu_ptr(rv->msrs, this_cpu);
     16	else
     17		reg = &rv->reg;
     18
     19	rdmsr(rv->msr_no, reg->l, reg->h);
     20}
     21
     22static void __wrmsr_on_cpu(void *info)
     23{
     24	struct msr_info *rv = info;
     25	struct msr *reg;
     26	int this_cpu = raw_smp_processor_id();
     27
     28	if (rv->msrs)
     29		reg = per_cpu_ptr(rv->msrs, this_cpu);
     30	else
     31		reg = &rv->reg;
     32
     33	wrmsr(rv->msr_no, reg->l, reg->h);
     34}
     35
     36int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
     37{
     38	int err;
     39	struct msr_info rv;
     40
     41	memset(&rv, 0, sizeof(rv));
     42
     43	rv.msr_no = msr_no;
     44	err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1);
     45	*l = rv.reg.l;
     46	*h = rv.reg.h;
     47
     48	return err;
     49}
     50EXPORT_SYMBOL(rdmsr_on_cpu);
     51
     52int rdmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 *q)
     53{
     54	int err;
     55	struct msr_info rv;
     56
     57	memset(&rv, 0, sizeof(rv));
     58
     59	rv.msr_no = msr_no;
     60	err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1);
     61	*q = rv.reg.q;
     62
     63	return err;
     64}
     65EXPORT_SYMBOL(rdmsrl_on_cpu);
     66
     67int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
     68{
     69	int err;
     70	struct msr_info rv;
     71
     72	memset(&rv, 0, sizeof(rv));
     73
     74	rv.msr_no = msr_no;
     75	rv.reg.l = l;
     76	rv.reg.h = h;
     77	err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1);
     78
     79	return err;
     80}
     81EXPORT_SYMBOL(wrmsr_on_cpu);
     82
     83int wrmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 q)
     84{
     85	int err;
     86	struct msr_info rv;
     87
     88	memset(&rv, 0, sizeof(rv));
     89
     90	rv.msr_no = msr_no;
     91	rv.reg.q = q;
     92
     93	err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1);
     94
     95	return err;
     96}
     97EXPORT_SYMBOL(wrmsrl_on_cpu);
     98
     99static void __rwmsr_on_cpus(const struct cpumask *mask, u32 msr_no,
    100			    struct msr *msrs,
    101			    void (*msr_func) (void *info))
    102{
    103	struct msr_info rv;
    104	int this_cpu;
    105
    106	memset(&rv, 0, sizeof(rv));
    107
    108	rv.msrs	  = msrs;
    109	rv.msr_no = msr_no;
    110
    111	this_cpu = get_cpu();
    112
    113	if (cpumask_test_cpu(this_cpu, mask))
    114		msr_func(&rv);
    115
    116	smp_call_function_many(mask, msr_func, &rv, 1);
    117	put_cpu();
    118}
    119
    120/* rdmsr on a bunch of CPUs
    121 *
    122 * @mask:       which CPUs
    123 * @msr_no:     which MSR
    124 * @msrs:       array of MSR values
    125 *
    126 */
    127void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs)
    128{
    129	__rwmsr_on_cpus(mask, msr_no, msrs, __rdmsr_on_cpu);
    130}
    131EXPORT_SYMBOL(rdmsr_on_cpus);
    132
    133/*
    134 * wrmsr on a bunch of CPUs
    135 *
    136 * @mask:       which CPUs
    137 * @msr_no:     which MSR
    138 * @msrs:       array of MSR values
    139 *
    140 */
    141void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs)
    142{
    143	__rwmsr_on_cpus(mask, msr_no, msrs, __wrmsr_on_cpu);
    144}
    145EXPORT_SYMBOL(wrmsr_on_cpus);
    146
    147struct msr_info_completion {
    148	struct msr_info		msr;
    149	struct completion	done;
    150};
    151
    152/* These "safe" variants are slower and should be used when the target MSR
    153   may not actually exist. */
    154static void __rdmsr_safe_on_cpu(void *info)
    155{
    156	struct msr_info_completion *rv = info;
    157
    158	rv->msr.err = rdmsr_safe(rv->msr.msr_no, &rv->msr.reg.l, &rv->msr.reg.h);
    159	complete(&rv->done);
    160}
    161
    162static void __wrmsr_safe_on_cpu(void *info)
    163{
    164	struct msr_info *rv = info;
    165
    166	rv->err = wrmsr_safe(rv->msr_no, rv->reg.l, rv->reg.h);
    167}
    168
    169int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
    170{
    171	struct msr_info_completion rv;
    172	call_single_data_t csd;
    173	int err;
    174
    175	INIT_CSD(&csd, __rdmsr_safe_on_cpu, &rv);
    176
    177	memset(&rv, 0, sizeof(rv));
    178	init_completion(&rv.done);
    179	rv.msr.msr_no = msr_no;
    180
    181	err = smp_call_function_single_async(cpu, &csd);
    182	if (!err) {
    183		wait_for_completion(&rv.done);
    184		err = rv.msr.err;
    185	}
    186	*l = rv.msr.reg.l;
    187	*h = rv.msr.reg.h;
    188
    189	return err;
    190}
    191EXPORT_SYMBOL(rdmsr_safe_on_cpu);
    192
    193int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
    194{
    195	int err;
    196	struct msr_info rv;
    197
    198	memset(&rv, 0, sizeof(rv));
    199
    200	rv.msr_no = msr_no;
    201	rv.reg.l = l;
    202	rv.reg.h = h;
    203	err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1);
    204
    205	return err ? err : rv.err;
    206}
    207EXPORT_SYMBOL(wrmsr_safe_on_cpu);
    208
    209int wrmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 q)
    210{
    211	int err;
    212	struct msr_info rv;
    213
    214	memset(&rv, 0, sizeof(rv));
    215
    216	rv.msr_no = msr_no;
    217	rv.reg.q = q;
    218
    219	err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1);
    220
    221	return err ? err : rv.err;
    222}
    223EXPORT_SYMBOL(wrmsrl_safe_on_cpu);
    224
    225int rdmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 *q)
    226{
    227	u32 low, high;
    228	int err;
    229
    230	err = rdmsr_safe_on_cpu(cpu, msr_no, &low, &high);
    231	*q = (u64)high << 32 | low;
    232
    233	return err;
    234}
    235EXPORT_SYMBOL(rdmsrl_safe_on_cpu);
    236
    237/*
    238 * These variants are significantly slower, but allows control over
    239 * the entire 32-bit GPR set.
    240 */
    241static void __rdmsr_safe_regs_on_cpu(void *info)
    242{
    243	struct msr_regs_info *rv = info;
    244
    245	rv->err = rdmsr_safe_regs(rv->regs);
    246}
    247
    248static void __wrmsr_safe_regs_on_cpu(void *info)
    249{
    250	struct msr_regs_info *rv = info;
    251
    252	rv->err = wrmsr_safe_regs(rv->regs);
    253}
    254
    255int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8])
    256{
    257	int err;
    258	struct msr_regs_info rv;
    259
    260	rv.regs   = regs;
    261	rv.err    = -EIO;
    262	err = smp_call_function_single(cpu, __rdmsr_safe_regs_on_cpu, &rv, 1);
    263
    264	return err ? err : rv.err;
    265}
    266EXPORT_SYMBOL(rdmsr_safe_regs_on_cpu);
    267
    268int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8])
    269{
    270	int err;
    271	struct msr_regs_info rv;
    272
    273	rv.regs = regs;
    274	rv.err  = -EIO;
    275	err = smp_call_function_single(cpu, __wrmsr_safe_regs_on_cpu, &rv, 1);
    276
    277	return err ? err : rv.err;
    278}
    279EXPORT_SYMBOL(wrmsr_safe_regs_on_cpu);