drivers/xen/mcelog.c

Source file repositories/reference/linux-study-clean/drivers/xen/mcelog.c

File Facts

System
Linux kernel
Corpus path
drivers/xen/mcelog.c
Extension
.c
Size
10412 bytes
Lines
424
Domain
Driver Families
Bucket
drivers/xen
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct file_operations xen_mce_chrdev_ops = {
	.open			= xen_mce_chrdev_open,
	.release		= xen_mce_chrdev_release,
	.read			= xen_mce_chrdev_read,
	.poll			= xen_mce_chrdev_poll,
	.unlocked_ioctl		= xen_mce_chrdev_ioctl,
};

static struct miscdevice xen_mce_chrdev_device __ro_after_init = {
	MISC_MCELOG_MINOR,
	"mcelog",
	&xen_mce_chrdev_ops,
};

/*
 * Caller should hold the mcelog_lock
 */
static void xen_mce_log(struct xen_mce *mce)
{
	unsigned entry;

	entry = xen_mcelog.next;

	/*
	 * When the buffer fills up discard new entries.
	 * Assume that the earlier errors are the more
	 * interesting ones:
	 */
	if (entry >= XEN_MCE_LOG_LEN) {
		set_bit(XEN_MCE_OVERFLOW,
			(unsigned long *)&xen_mcelog.flags);
		return;
	}

	memcpy(xen_mcelog.entry + entry, mce, sizeof(struct xen_mce));

	xen_mcelog.next++;
}

static int convert_log(struct mc_info *mi)
{
	struct mcinfo_common *mic;
	struct mcinfo_global *mc_global;
	struct mcinfo_bank *mc_bank;
	struct xen_mce m;
	unsigned int i, j;

	mic = NULL;
	x86_mcinfo_lookup(&mic, mi, MC_TYPE_GLOBAL);
	if (unlikely(!mic)) {
		pr_warn("Failed to find global error info\n");
		return -ENODEV;
	}

	memset(&m, 0, sizeof(struct xen_mce));

	mc_global = (struct mcinfo_global *)mic;
	m.mcgstatus = mc_global->mc_gstatus;
	m.apicid = mc_global->mc_apicid;

	for (i = 0; i < ncpus; i++)
		if (g_physinfo[i].mc_apicid == m.apicid)
			break;
	if (unlikely(i == ncpus)) {
		pr_warn("Failed to match cpu with apicid %d\n", m.apicid);
		return -ENODEV;
	}

	m.socketid = g_physinfo[i].mc_chipid;
	m.cpu = m.extcpu = g_physinfo[i].mc_cpunr;
	m.cpuvendor = (__u8)g_physinfo[i].mc_vendor;
	for (j = 0; j < g_physinfo[i].mc_nmsrvals; ++j)
		switch (g_physinfo[i].mc_msrvalues[j].reg) {
		case MSR_IA32_MCG_CAP:
			m.mcgcap = g_physinfo[i].mc_msrvalues[j].value;
			break;

		case MSR_PPIN:
		case MSR_AMD_PPIN:
			m.ppin = g_physinfo[i].mc_msrvalues[j].value;
			break;
		}

	mic = NULL;
	x86_mcinfo_lookup(&mic, mi, MC_TYPE_BANK);
	if (unlikely(!mic)) {
		pr_warn("Fail to find bank error info\n");
		return -ENODEV;
	}

Annotation

Implementation Notes