arch/x86/lib/msr-smp.c

Source file repositories/reference/linux-study-clean/arch/x86/lib/msr-smp.c

File Facts

System
Linux kernel
Corpus path
arch/x86/lib/msr-smp.c
Extension
.c
Size
4260 bytes
Lines
217
Domain
Architecture Layer
Bucket
arch/x86
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

struct msr_info_completion {
	struct msr_info		msr;
	struct completion	done;
};

/* 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)
{
	struct msr_info_completion *rv = info;

	rv->msr.err = rdmsr_safe(rv->msr.msr_no, &rv->msr.reg.l, &rv->msr.reg.h);
	complete(&rv->done);
}

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

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

int wrmsrq_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 q)
{
	int err;
	struct msr_info rv;

	memset(&rv, 0, sizeof(rv));

	rv.msr_no = msr_no;
	rv.reg.q = q;

	err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1);

	return err ? err : rv.err;
}
EXPORT_SYMBOL(wrmsrq_safe_on_cpu);

int rdmsrq_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 *q)
{
	struct msr_info_completion rv;
	call_single_data_t csd;
	int err;

	INIT_CSD(&csd, __rdmsr_safe_on_cpu, &rv);

	memset(&rv, 0, sizeof(rv));
	init_completion(&rv.done);
	rv.msr.msr_no = msr_no;

	err = smp_call_function_single_async(cpu, &csd);
	if (!err) {
		wait_for_completion(&rv.done);
		err = rv.msr.err;
	}
	*q = rv.msr.reg.q;

	return err;
}
EXPORT_SYMBOL(rdmsrq_safe_on_cpu);

/*
 * These variants are significantly slower, but allows control over
 * the entire 32-bit GPR set.
 */
static void __rdmsr_safe_regs_on_cpu(void *info)
{
	struct msr_regs_info *rv = info;

	rv->err = rdmsr_safe_regs(rv->regs);
}

static void __wrmsr_safe_regs_on_cpu(void *info)
{
	struct msr_regs_info *rv = info;

	rv->err = wrmsr_safe_regs(rv->regs);
}

int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8])
{
	int err;
	struct msr_regs_info rv;

	rv.regs   = regs;
	rv.err    = -EIO;
	err = smp_call_function_single(cpu, __rdmsr_safe_regs_on_cpu, &rv, 1);

	return err ? err : rv.err;
}

Annotation

Implementation Notes