xref: /openbmc/linux/arch/x86/lib/msr-smp.c (revision 8be98d2f2a0a262f8bf8a0bc1fdf522b3c7aab17)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2e683014cSPaul Gortmaker #include <linux/export.h>
36ede31e0SBorislav Petkov #include <linux/preempt.h>
46ede31e0SBorislav Petkov #include <linux/smp.h>
507cde313SEric Dumazet #include <linux/completion.h>
66ede31e0SBorislav Petkov #include <asm/msr.h>
76ede31e0SBorislav Petkov 
__rdmsr_on_cpu(void * info)86ede31e0SBorislav Petkov static void __rdmsr_on_cpu(void *info)
96ede31e0SBorislav Petkov {
106ede31e0SBorislav Petkov 	struct msr_info *rv = info;
116ede31e0SBorislav Petkov 	struct msr *reg;
126ede31e0SBorislav Petkov 	int this_cpu = raw_smp_processor_id();
136ede31e0SBorislav Petkov 
146ede31e0SBorislav Petkov 	if (rv->msrs)
156ede31e0SBorislav Petkov 		reg = per_cpu_ptr(rv->msrs, this_cpu);
166ede31e0SBorislav Petkov 	else
176ede31e0SBorislav Petkov 		reg = &rv->reg;
186ede31e0SBorislav Petkov 
196ede31e0SBorislav Petkov 	rdmsr(rv->msr_no, reg->l, reg->h);
206ede31e0SBorislav Petkov }
216ede31e0SBorislav Petkov 
__wrmsr_on_cpu(void * info)226ede31e0SBorislav Petkov static void __wrmsr_on_cpu(void *info)
236ede31e0SBorislav Petkov {
246ede31e0SBorislav Petkov 	struct msr_info *rv = info;
256ede31e0SBorislav Petkov 	struct msr *reg;
266ede31e0SBorislav Petkov 	int this_cpu = raw_smp_processor_id();
276ede31e0SBorislav Petkov 
286ede31e0SBorislav Petkov 	if (rv->msrs)
296ede31e0SBorislav Petkov 		reg = per_cpu_ptr(rv->msrs, this_cpu);
306ede31e0SBorislav Petkov 	else
316ede31e0SBorislav Petkov 		reg = &rv->reg;
326ede31e0SBorislav Petkov 
336ede31e0SBorislav Petkov 	wrmsr(rv->msr_no, reg->l, reg->h);
346ede31e0SBorislav Petkov }
356ede31e0SBorislav Petkov 
rdmsr_on_cpu(unsigned int cpu,u32 msr_no,u32 * l,u32 * h)366ede31e0SBorislav Petkov int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
376ede31e0SBorislav Petkov {
386ede31e0SBorislav Petkov 	int err;
396ede31e0SBorislav Petkov 	struct msr_info rv;
406ede31e0SBorislav Petkov 
416ede31e0SBorislav Petkov 	memset(&rv, 0, sizeof(rv));
426ede31e0SBorislav Petkov 
436ede31e0SBorislav Petkov 	rv.msr_no = msr_no;
446ede31e0SBorislav Petkov 	err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1);
456ede31e0SBorislav Petkov 	*l = rv.reg.l;
466ede31e0SBorislav Petkov 	*h = rv.reg.h;
476ede31e0SBorislav Petkov 
486ede31e0SBorislav Petkov 	return err;
496ede31e0SBorislav Petkov }
506ede31e0SBorislav Petkov EXPORT_SYMBOL(rdmsr_on_cpu);
516ede31e0SBorislav Petkov 
rdmsrl_on_cpu(unsigned int cpu,u32 msr_no,u64 * q)521a6b991aSJacob Pan int rdmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 *q)
531a6b991aSJacob Pan {
541a6b991aSJacob Pan 	int err;
551a6b991aSJacob Pan 	struct msr_info rv;
561a6b991aSJacob Pan 
571a6b991aSJacob Pan 	memset(&rv, 0, sizeof(rv));
581a6b991aSJacob Pan 
591a6b991aSJacob Pan 	rv.msr_no = msr_no;
601a6b991aSJacob Pan 	err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1);
611a6b991aSJacob Pan 	*q = rv.reg.q;
621a6b991aSJacob Pan 
631a6b991aSJacob Pan 	return err;
641a6b991aSJacob Pan }
651a6b991aSJacob Pan EXPORT_SYMBOL(rdmsrl_on_cpu);
661a6b991aSJacob Pan 
wrmsr_on_cpu(unsigned int cpu,u32 msr_no,u32 l,u32 h)676ede31e0SBorislav Petkov int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
686ede31e0SBorislav Petkov {
696ede31e0SBorislav Petkov 	int err;
706ede31e0SBorislav Petkov 	struct msr_info rv;
716ede31e0SBorislav Petkov 
726ede31e0SBorislav Petkov 	memset(&rv, 0, sizeof(rv));
736ede31e0SBorislav Petkov 
746ede31e0SBorislav Petkov 	rv.msr_no = msr_no;
756ede31e0SBorislav Petkov 	rv.reg.l = l;
766ede31e0SBorislav Petkov 	rv.reg.h = h;
776ede31e0SBorislav Petkov 	err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1);
786ede31e0SBorislav Petkov 
796ede31e0SBorislav Petkov 	return err;
806ede31e0SBorislav Petkov }
816ede31e0SBorislav Petkov EXPORT_SYMBOL(wrmsr_on_cpu);
826ede31e0SBorislav Petkov 
wrmsrl_on_cpu(unsigned int cpu,u32 msr_no,u64 q)831a6b991aSJacob Pan int wrmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 q)
841a6b991aSJacob Pan {
851a6b991aSJacob Pan 	int err;
861a6b991aSJacob Pan 	struct msr_info rv;
871a6b991aSJacob Pan 
881a6b991aSJacob Pan 	memset(&rv, 0, sizeof(rv));
891a6b991aSJacob Pan 
901a6b991aSJacob Pan 	rv.msr_no = msr_no;
911a6b991aSJacob Pan 	rv.reg.q = q;
921a6b991aSJacob Pan 
931a6b991aSJacob Pan 	err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1);
941a6b991aSJacob Pan 
951a6b991aSJacob Pan 	return err;
961a6b991aSJacob Pan }
971a6b991aSJacob Pan EXPORT_SYMBOL(wrmsrl_on_cpu);
981a6b991aSJacob Pan 
__rwmsr_on_cpus(const struct cpumask * mask,u32 msr_no,struct msr * msrs,void (* msr_func)(void * info))996ede31e0SBorislav Petkov static void __rwmsr_on_cpus(const struct cpumask *mask, u32 msr_no,
1006ede31e0SBorislav Petkov 			    struct msr *msrs,
1016ede31e0SBorislav Petkov 			    void (*msr_func) (void *info))
1026ede31e0SBorislav Petkov {
1036ede31e0SBorislav Petkov 	struct msr_info rv;
1046ede31e0SBorislav Petkov 	int this_cpu;
1056ede31e0SBorislav Petkov 
1066ede31e0SBorislav Petkov 	memset(&rv, 0, sizeof(rv));
1076ede31e0SBorislav Petkov 
1086ede31e0SBorislav Petkov 	rv.msrs	  = msrs;
1096ede31e0SBorislav Petkov 	rv.msr_no = msr_no;
1106ede31e0SBorislav Petkov 
1116ede31e0SBorislav Petkov 	this_cpu = get_cpu();
1126ede31e0SBorislav Petkov 
1136ede31e0SBorislav Petkov 	if (cpumask_test_cpu(this_cpu, mask))
1146ede31e0SBorislav Petkov 		msr_func(&rv);
1156ede31e0SBorislav Petkov 
1166ede31e0SBorislav Petkov 	smp_call_function_many(mask, msr_func, &rv, 1);
1176ede31e0SBorislav Petkov 	put_cpu();
1186ede31e0SBorislav Petkov }
1196ede31e0SBorislav Petkov 
1206ede31e0SBorislav Petkov /* rdmsr on a bunch of CPUs
1216ede31e0SBorislav Petkov  *
1226ede31e0SBorislav Petkov  * @mask:       which CPUs
1236ede31e0SBorislav Petkov  * @msr_no:     which MSR
1246ede31e0SBorislav Petkov  * @msrs:       array of MSR values
1256ede31e0SBorislav Petkov  *
1266ede31e0SBorislav Petkov  */
rdmsr_on_cpus(const struct cpumask * mask,u32 msr_no,struct msr * msrs)1276ede31e0SBorislav Petkov void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs)
1286ede31e0SBorislav Petkov {
1296ede31e0SBorislav Petkov 	__rwmsr_on_cpus(mask, msr_no, msrs, __rdmsr_on_cpu);
1306ede31e0SBorislav Petkov }
1316ede31e0SBorislav Petkov EXPORT_SYMBOL(rdmsr_on_cpus);
1326ede31e0SBorislav Petkov 
1336ede31e0SBorislav Petkov /*
1346ede31e0SBorislav Petkov  * wrmsr on a bunch of CPUs
1356ede31e0SBorislav Petkov  *
1366ede31e0SBorislav Petkov  * @mask:       which CPUs
1376ede31e0SBorislav Petkov  * @msr_no:     which MSR
1386ede31e0SBorislav Petkov  * @msrs:       array of MSR values
1396ede31e0SBorislav Petkov  *
1406ede31e0SBorislav Petkov  */
wrmsr_on_cpus(const struct cpumask * mask,u32 msr_no,struct msr * msrs)1416ede31e0SBorislav Petkov void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs)
1426ede31e0SBorislav Petkov {
1436ede31e0SBorislav Petkov 	__rwmsr_on_cpus(mask, msr_no, msrs, __wrmsr_on_cpu);
1446ede31e0SBorislav Petkov }
1456ede31e0SBorislav Petkov EXPORT_SYMBOL(wrmsr_on_cpus);
1466ede31e0SBorislav Petkov 
14707cde313SEric Dumazet struct msr_info_completion {
14807cde313SEric Dumazet 	struct msr_info		msr;
14907cde313SEric Dumazet 	struct completion	done;
15007cde313SEric Dumazet };
15107cde313SEric Dumazet 
1526ede31e0SBorislav Petkov /* These "safe" variants are slower and should be used when the target MSR
1536ede31e0SBorislav Petkov    may not actually exist. */
__rdmsr_safe_on_cpu(void * info)1546ede31e0SBorislav Petkov static void __rdmsr_safe_on_cpu(void *info)
1556ede31e0SBorislav Petkov {
15607cde313SEric Dumazet 	struct msr_info_completion *rv = info;
1576ede31e0SBorislav Petkov 
15807cde313SEric Dumazet 	rv->msr.err = rdmsr_safe(rv->msr.msr_no, &rv->msr.reg.l, &rv->msr.reg.h);
15907cde313SEric Dumazet 	complete(&rv->done);
1606ede31e0SBorislav Petkov }
1616ede31e0SBorislav Petkov 
__wrmsr_safe_on_cpu(void * info)1626ede31e0SBorislav Petkov static void __wrmsr_safe_on_cpu(void *info)
1636ede31e0SBorislav Petkov {
1646ede31e0SBorislav Petkov 	struct msr_info *rv = info;
1656ede31e0SBorislav Petkov 
1666ede31e0SBorislav Petkov 	rv->err = wrmsr_safe(rv->msr_no, rv->reg.l, rv->reg.h);
1676ede31e0SBorislav Petkov }
1686ede31e0SBorislav Petkov 
rdmsr_safe_on_cpu(unsigned int cpu,u32 msr_no,u32 * l,u32 * h)1696ede31e0SBorislav Petkov int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
1706ede31e0SBorislav Petkov {
17107cde313SEric Dumazet 	struct msr_info_completion rv;
172545b8c8dSPeter Zijlstra 	call_single_data_t csd;
1736ede31e0SBorislav Petkov 	int err;
1746ede31e0SBorislav Petkov 
175545b8c8dSPeter Zijlstra 	INIT_CSD(&csd, __rdmsr_safe_on_cpu, &rv);
176545b8c8dSPeter Zijlstra 
1776ede31e0SBorislav Petkov 	memset(&rv, 0, sizeof(rv));
17807cde313SEric Dumazet 	init_completion(&rv.done);
17907cde313SEric Dumazet 	rv.msr.msr_no = msr_no;
1806ede31e0SBorislav Petkov 
18107cde313SEric Dumazet 	err = smp_call_function_single_async(cpu, &csd);
18207cde313SEric Dumazet 	if (!err) {
18307cde313SEric Dumazet 		wait_for_completion(&rv.done);
18407cde313SEric Dumazet 		err = rv.msr.err;
18507cde313SEric Dumazet 	}
18607cde313SEric Dumazet 	*l = rv.msr.reg.l;
18707cde313SEric Dumazet 	*h = rv.msr.reg.h;
1886ede31e0SBorislav Petkov 
18907cde313SEric Dumazet 	return err;
1906ede31e0SBorislav Petkov }
1916ede31e0SBorislav Petkov EXPORT_SYMBOL(rdmsr_safe_on_cpu);
1926ede31e0SBorislav Petkov 
wrmsr_safe_on_cpu(unsigned int cpu,u32 msr_no,u32 l,u32 h)1936ede31e0SBorislav Petkov int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
1946ede31e0SBorislav Petkov {
1956ede31e0SBorislav Petkov 	int err;
1966ede31e0SBorislav Petkov 	struct msr_info rv;
1976ede31e0SBorislav Petkov 
1986ede31e0SBorislav Petkov 	memset(&rv, 0, sizeof(rv));
1996ede31e0SBorislav Petkov 
2006ede31e0SBorislav Petkov 	rv.msr_no = msr_no;
2016ede31e0SBorislav Petkov 	rv.reg.l = l;
2026ede31e0SBorislav Petkov 	rv.reg.h = h;
2036ede31e0SBorislav Petkov 	err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1);
2046ede31e0SBorislav Petkov 
2056ede31e0SBorislav Petkov 	return err ? err : rv.err;
2066ede31e0SBorislav Petkov }
2076ede31e0SBorislav Petkov EXPORT_SYMBOL(wrmsr_safe_on_cpu);
2086ede31e0SBorislav Petkov 
wrmsrl_safe_on_cpu(unsigned int cpu,u32 msr_no,u64 q)2091a6b991aSJacob Pan int wrmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 q)
2101a6b991aSJacob Pan {
2111a6b991aSJacob Pan 	int err;
2121a6b991aSJacob Pan 	struct msr_info rv;
2131a6b991aSJacob Pan 
2141a6b991aSJacob Pan 	memset(&rv, 0, sizeof(rv));
2151a6b991aSJacob Pan 
2161a6b991aSJacob Pan 	rv.msr_no = msr_no;
2171a6b991aSJacob Pan 	rv.reg.q = q;
2181a6b991aSJacob Pan 
2191a6b991aSJacob Pan 	err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1);
2201a6b991aSJacob Pan 
2211a6b991aSJacob Pan 	return err ? err : rv.err;
2221a6b991aSJacob Pan }
2231a6b991aSJacob Pan EXPORT_SYMBOL(wrmsrl_safe_on_cpu);
2241a6b991aSJacob Pan 
rdmsrl_safe_on_cpu(unsigned int cpu,u32 msr_no,u64 * q)2251a6b991aSJacob Pan int rdmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 *q)
2261a6b991aSJacob Pan {
2279b9a5135SEric Dumazet 	u32 low, high;
2281a6b991aSJacob Pan 	int err;
2291a6b991aSJacob Pan 
2309b9a5135SEric Dumazet 	err = rdmsr_safe_on_cpu(cpu, msr_no, &low, &high);
2319b9a5135SEric Dumazet 	*q = (u64)high << 32 | low;
2321a6b991aSJacob Pan 
2339b9a5135SEric Dumazet 	return err;
2341a6b991aSJacob Pan }
2351a6b991aSJacob Pan EXPORT_SYMBOL(rdmsrl_safe_on_cpu);
2361a6b991aSJacob Pan 
2376ede31e0SBorislav Petkov /*
2386ede31e0SBorislav Petkov  * These variants are significantly slower, but allows control over
2396ede31e0SBorislav Petkov  * the entire 32-bit GPR set.
2406ede31e0SBorislav Petkov  */
__rdmsr_safe_regs_on_cpu(void * info)2416ede31e0SBorislav Petkov static void __rdmsr_safe_regs_on_cpu(void *info)
2426ede31e0SBorislav Petkov {
2436ede31e0SBorislav Petkov 	struct msr_regs_info *rv = info;
2446ede31e0SBorislav Petkov 
2456ede31e0SBorislav Petkov 	rv->err = rdmsr_safe_regs(rv->regs);
2466ede31e0SBorislav Petkov }
2476ede31e0SBorislav Petkov 
__wrmsr_safe_regs_on_cpu(void * info)2486ede31e0SBorislav Petkov static void __wrmsr_safe_regs_on_cpu(void *info)
2496ede31e0SBorislav Petkov {
2506ede31e0SBorislav Petkov 	struct msr_regs_info *rv = info;
2516ede31e0SBorislav Petkov 
2526ede31e0SBorislav Petkov 	rv->err = wrmsr_safe_regs(rv->regs);
2536ede31e0SBorislav Petkov }
2546ede31e0SBorislav Petkov 
rdmsr_safe_regs_on_cpu(unsigned int cpu,u32 regs[8])255*396a66aaSArnd Bergmann int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8])
2566ede31e0SBorislav Petkov {
2576ede31e0SBorislav Petkov 	int err;
2586ede31e0SBorislav Petkov 	struct msr_regs_info rv;
2596ede31e0SBorislav Petkov 
2606ede31e0SBorislav Petkov 	rv.regs   = regs;
2616ede31e0SBorislav Petkov 	rv.err    = -EIO;
2626ede31e0SBorislav Petkov 	err = smp_call_function_single(cpu, __rdmsr_safe_regs_on_cpu, &rv, 1);
2636ede31e0SBorislav Petkov 
2646ede31e0SBorislav Petkov 	return err ? err : rv.err;
2656ede31e0SBorislav Petkov }
2666ede31e0SBorislav Petkov EXPORT_SYMBOL(rdmsr_safe_regs_on_cpu);
2676ede31e0SBorislav Petkov 
wrmsr_safe_regs_on_cpu(unsigned int cpu,u32 regs[8])268*396a66aaSArnd Bergmann int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8])
2696ede31e0SBorislav Petkov {
2706ede31e0SBorislav Petkov 	int err;
2716ede31e0SBorislav Petkov 	struct msr_regs_info rv;
2726ede31e0SBorislav Petkov 
2736ede31e0SBorislav Petkov 	rv.regs = regs;
2746ede31e0SBorislav Petkov 	rv.err  = -EIO;
2756ede31e0SBorislav Petkov 	err = smp_call_function_single(cpu, __wrmsr_safe_regs_on_cpu, &rv, 1);
2766ede31e0SBorislav Petkov 
2776ede31e0SBorislav Petkov 	return err ? err : rv.err;
2786ede31e0SBorislav Petkov }
2796ede31e0SBorislav Petkov EXPORT_SYMBOL(wrmsr_safe_regs_on_cpu);
280