arch/x86/kernel/cpu/mce/inject.c

Source file repositories/reference/linux-study-clean/arch/x86/kernel/cpu/mce/inject.c

File Facts

System
Linux kernel
Corpus path
arch/x86/kernel/cpu/mce/inject.c
Extension
.c
Size
19388 bytes
Lines
807
Domain
Architecture Layer
Bucket
arch/x86
Inferred role
Architecture Layer: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations flags_fops = {
	.read           = flags_read,
	.write          = flags_write,
	.llseek         = generic_file_llseek,
};

/*
 * On which CPU to inject?
 */
MCE_INJECT_GET(extcpu);

static int inj_extcpu_set(void *data, u64 val)
{
	struct mce *m = (struct mce *)data;

	if (val >= nr_cpu_ids || !cpu_online(val)) {
		pr_err("%s: Invalid CPU: %llu\n", __func__, val);
		return -EINVAL;
	}
	m->extcpu = val;
	return 0;
}

DEFINE_SIMPLE_ATTRIBUTE(extcpu_fops, inj_extcpu_get, inj_extcpu_set, "%llu\n");

static void trigger_mce(void *info)
{
	asm volatile("int $18");
}

static void trigger_dfr_int(void *info)
{
	asm volatile("int %0" :: "i" (DEFERRED_ERROR_VECTOR));
}

static void trigger_thr_int(void *info)
{
	asm volatile("int %0" :: "i" (THRESHOLD_APIC_VECTOR));
}

static u32 get_nbc_for_node(int node_id)
{
	u32 cores_per_node;

	cores_per_node = topology_num_threads_per_package() / topology_amd_nodes_per_pkg();
	return cores_per_node * node_id;
}

static void toggle_nb_mca_mst_cpu(u16 nid)
{
	struct amd_northbridge *nb;
	struct pci_dev *F3;
	u32 val;
	int err;

	nb = node_to_amd_nb(nid);
	if (!nb)
		return;

	F3 = nb->misc;
	if (!F3)
		return;

	err = pci_read_config_dword(F3, NBCFG, &val);
	if (err) {
		pr_err("%s: Error reading F%dx%03x.\n",
		       __func__, PCI_FUNC(F3->devfn), NBCFG);
		return;
	}

	if (val & BIT(27))
		return;

	pr_err("%s: Set D18F3x44[NbMcaToMstCpuEn] which BIOS hasn't done.\n",
	       __func__);

	val |= BIT(27);
	err = pci_write_config_dword(F3, NBCFG, val);
	if (err)
		pr_err("%s: Error writing F%dx%03x.\n",
		       __func__, PCI_FUNC(F3->devfn), NBCFG);
}

static void prepare_msrs(void *info)
{
	struct mce m = *(struct mce *)info;
	u8 b = m.bank;

	wrmsrq(MSR_IA32_MCG_STATUS, m.mcgstatus);

Annotation

Implementation Notes