msr.c 1.8 KB
Newer Older
A
Alexey Dobriyan 已提交
1 2 3 4 5 6 7
#include <linux/module.h>
#include <linux/preempt.h>
#include <linux/smp.h>
#include <asm/msr.h>

struct msr_info {
	u32 msr_no;
8
	struct msr reg;
9
	int err;
A
Alexey Dobriyan 已提交
10 11 12 13 14 15
};

static void __rdmsr_on_cpu(void *info)
{
	struct msr_info *rv = info;

16
	rdmsr(rv->msr_no, rv->reg.l, rv->reg.h);
A
Alexey Dobriyan 已提交
17 18
}

19
static void __wrmsr_on_cpu(void *info)
A
Alexey Dobriyan 已提交
20
{
21 22
	struct msr_info *rv = info;

23
	wrmsr(rv->msr_no, rv->reg.l, rv->reg.h);
24 25
}

26
int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
27
{
28
	int err;
29 30 31
	struct msr_info rv;

	rv.msr_no = msr_no;
32
	err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1);
33 34
	*l = rv.reg.l;
	*h = rv.reg.h;
35

36
	return err;
A
Alexey Dobriyan 已提交
37 38
}

39 40 41 42 43 44
int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
{
	int err;
	struct msr_info rv;

	rv.msr_no = msr_no;
45 46
	rv.reg.l = l;
	rv.reg.h = h;
47 48 49 50 51 52 53 54
	err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1);

	return err;
}

/* These "safe" variants are slower and should be used when the target MSR
   may not actually exist. */
static void __rdmsr_safe_on_cpu(void *info)
A
Alexey Dobriyan 已提交
55 56 57
{
	struct msr_info *rv = info;

58
	rv->err = rdmsr_safe(rv->msr_no, &rv->reg.l, &rv->reg.h);
A
Alexey Dobriyan 已提交
59 60
}

61
static void __wrmsr_safe_on_cpu(void *info)
A
Alexey Dobriyan 已提交
62
{
63 64
	struct msr_info *rv = info;

65
	rv->err = wrmsr_safe(rv->msr_no, rv->reg.l, rv->reg.h);
66 67
}

68
int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
69
{
70
	int err;
71 72 73
	struct msr_info rv;

	rv.msr_no = msr_no;
74
	err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1);
75 76
	*l = rv.reg.l;
	*h = rv.reg.h;
77

78
	return err ? err : rv.err;
79 80 81 82
}

int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
{
83 84
	int err;
	struct msr_info rv;
85

86
	rv.msr_no = msr_no;
87 88
	rv.reg.l = l;
	rv.reg.h = h;
89 90 91
	err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1);

	return err ? err : rv.err;
A
Alexey Dobriyan 已提交
92 93 94 95
}

EXPORT_SYMBOL(rdmsr_on_cpu);
EXPORT_SYMBOL(wrmsr_on_cpu);
96 97
EXPORT_SYMBOL(rdmsr_safe_on_cpu);
EXPORT_SYMBOL(wrmsr_safe_on_cpu);