Mailing List Archive

[xen-unstable] x86 mce: Re-arrange mce_intel.c, to make it more clean
# HG changeset patch
# User Keir Fraser <keir.fraser@citrix.com>
# Date 1276154210 -3600
# Node ID 104da3a219fa0e3c22c77abb1db35357d1e2c344
# Parent 65b27a094ec826a5a7db2d53e77988c3d76cef63
x86 mce: Re-arrange mce_intel.c, to make it more clean

Seperate logic for MCE handling, Intel MCA, MCE, CMCI handler, to make
it more clean. No logic changes in this patch.

Signed-off-by: Jiang, Yunhong <yunhong.jiang@intel.com>
---
xen/arch/x86/cpu/mcheck/mce_intel.c | 303 ++++++++++++++++++------------------
1 files changed, 156 insertions(+), 147 deletions(-)

diff -r 65b27a094ec8 -r 104da3a219fa xen/arch/x86/cpu/mcheck/mce_intel.c
--- a/xen/arch/x86/cpu/mcheck/mce_intel.c Wed Jun 09 14:38:30 2010 +0100
+++ b/xen/arch/x86/cpu/mcheck/mce_intel.c Thu Jun 10 08:16:50 2010 +0100
@@ -26,30 +26,7 @@ boolean_param("mce_fb", mce_force_broadc

static int nr_intel_ext_msrs = 0;

-/* Below are for MCE handling */
-struct mce_softirq_barrier {
- atomic_t val;
- atomic_t ingen;
- atomic_t outgen;
-};
-
-static struct mce_softirq_barrier mce_inside_bar, mce_severity_bar;
-static struct mce_softirq_barrier mce_trap_bar;
-
-/*
- * mce_logout_lock should only be used in the trap handler,
- * while MCIP has not been cleared yet in the global status
- * register. Other use is not safe, since an MCE trap can
- * happen at any moment, which would cause lock recursion.
- */
-static DEFINE_SPINLOCK(mce_logout_lock);
-
-static atomic_t severity_cpu = ATOMIC_INIT(-1);
-static atomic_t found_error = ATOMIC_INIT(0);
-
-static void mce_barrier_enter(struct mce_softirq_barrier *);
-static void mce_barrier_exit(struct mce_softirq_barrier *);
-
+/* Thermal Hanlding */
#ifdef CONFIG_X86_MCE_THERMAL
static void unexpected_thermal_interrupt(struct cpu_user_regs *regs)
{
@@ -153,133 +130,34 @@ static void intel_init_thermal(struct cp
}
#endif /* CONFIG_X86_MCE_THERMAL */

-static inline void intel_get_extended_msr(struct mcinfo_extended *ext, u32 msr)
-{
- if ( ext->mc_msrs < ARRAY_SIZE(ext->mc_msr)
- && msr < MSR_IA32_MCG_EAX + nr_intel_ext_msrs ) {
- ext->mc_msr[ext->mc_msrs].reg = msr;
- rdmsrl(msr, ext->mc_msr[ext->mc_msrs].value);
- ++ext->mc_msrs;
- }
-}
-
-
-struct mcinfo_extended *
-intel_get_extended_msrs(struct mcinfo_global *mig, struct mc_info *mi)
-{
- struct mcinfo_extended *mc_ext;
- int i;
-
- /*
- * According to spec, processor _support_ 64 bit will always
- * have MSR beyond IA32_MCG_MISC
- */
- if (!mi|| !mig || nr_intel_ext_msrs == 0 ||
- !(mig->mc_gstatus & MCG_STATUS_EIPV))
- return NULL;
-
- mc_ext = x86_mcinfo_reserve(mi, sizeof(struct mcinfo_extended));
- if (!mc_ext)
- {
- mi->flags |= MCINFO_FLAGS_UNCOMPLETE;
- return NULL;
- }
-
- /* this function will called when CAP(9).MCG_EXT_P = 1 */
- memset(&mc_ext, 0, sizeof(struct mcinfo_extended));
- mc_ext->common.type = MC_TYPE_EXTENDED;
- mc_ext->common.size = sizeof(struct mcinfo_extended);
-
- for (i = MSR_IA32_MCG_EAX; i <= MSR_IA32_MCG_MISC; i++)
- intel_get_extended_msr(mc_ext, i);
-
-#ifdef __x86_64__
- for (i = MSR_IA32_MCG_R8; i <= MSR_IA32_MCG_R15; i++)
- intel_get_extended_msr(mc_ext, i);
-#endif
-
- return mc_ext;
-}
+/* MCE handling */
+struct mce_softirq_barrier {
+ atomic_t val;
+ atomic_t ingen;
+ atomic_t outgen;
+};
+
+static struct mce_softirq_barrier mce_inside_bar, mce_severity_bar;
+static struct mce_softirq_barrier mce_trap_bar;
+
+/*
+ * mce_logout_lock should only be used in the trap handler,
+ * while MCIP has not been cleared yet in the global status
+ * register. Other use is not safe, since an MCE trap can
+ * happen at any moment, which would cause lock recursion.
+ */
+static DEFINE_SPINLOCK(mce_logout_lock);
+
+static atomic_t severity_cpu = ATOMIC_INIT(-1);
+static atomic_t found_error = ATOMIC_INIT(0);
+
+static void mce_barrier_enter(struct mce_softirq_barrier *);
+static void mce_barrier_exit(struct mce_softirq_barrier *);

static void intel_UCR_handler(struct mcinfo_bank *bank,
struct mcinfo_global *global,
struct mcinfo_extended *extension,
- struct mca_handle_result *result)
-{
- struct domain *d;
- unsigned long mfn, gfn;
- uint32_t status;
-
- mce_printk(MCE_VERBOSE, "MCE: Enter UCR recovery action\n");
- result->result = MCA_NEED_RESET;
- if (bank->mc_addr != 0) {
- mfn = bank->mc_addr >> PAGE_SHIFT;
- if (!offline_page(mfn, 1, &status)) {
- /* This is free page */
- if (status & PG_OFFLINE_OFFLINED)
- result->result = MCA_RECOVERED;
- else if (status & PG_OFFLINE_PENDING) {
- /* This page has owner */
- if (status & PG_OFFLINE_OWNED) {
- result->result |= MCA_OWNER;
- result->owner = status >> PG_OFFLINE_OWNER_SHIFT;
- mce_printk(MCE_QUIET, "MCE: This error page is ownded"
- " by DOM %d\n", result->owner);
- /* Fill vMCE# injection and vMCE# MSR virtualization "
- * "related data */
- bank->mc_domid = result->owner;
- /* XXX: Cannot handle shared pages yet
- * (this should identify all domains and gfn mapping to
- * the mfn in question) */
- BUG_ON( result->owner == DOMID_COW );
- if ( result->owner != DOMID_XEN ) {
-
- d = get_domain_by_id(result->owner);
- if ( mca_ctl_conflict(bank, d) )
- {
- /* Guest has different MCE ctl with hypervisor */
- if ( d )
- put_domain(d);
- return;
- }
-
- ASSERT(d);
- gfn =
- get_gpfn_from_mfn((bank->mc_addr) >> PAGE_SHIFT);
- bank->mc_addr = gfn << PAGE_SHIFT |
- (bank->mc_addr & (PAGE_SIZE -1 ));
- if ( fill_vmsr_data(bank, d,
- global->mc_gstatus) == -1 )
- {
- mce_printk(MCE_QUIET, "Fill vMCE# data for DOM%d "
- "failed\n", result->owner);
- put_domain(d);
- domain_crash(d);
- return;
- }
- /* We will inject vMCE to DOMU*/
- if ( inject_vmce(d) < 0 )
- {
- mce_printk(MCE_QUIET, "inject vMCE to DOM%d"
- " failed\n", d->domain_id);
- put_domain(d);
- domain_crash(d);
- return;
- }
- /* Impacted domain go on with domain's recovery job
- * if the domain has its own MCA handler.
- * For xen, it has contained the error and finished
- * its own recovery job.
- */
- result->result = MCA_RECOVERED;
- put_domain(d);
- }
- }
- }
- }
- }
-}
-
+ struct mca_handle_result *result);
#define INTEL_MAX_RECOVERY 2
struct mca_error_handler intel_recovery_handler[INTEL_MAX_RECOVERY] =
{{0x017A, intel_UCR_handler}, {0x00C0, intel_UCR_handler}};
@@ -526,6 +404,134 @@ static void mce_barrier(struct mce_softi
}
#endif

+/* Intel MCE handler */
+static inline void intel_get_extended_msr(struct mcinfo_extended *ext, u32 msr)
+{
+ if ( ext->mc_msrs < ARRAY_SIZE(ext->mc_msr)
+ && msr < MSR_IA32_MCG_EAX + nr_intel_ext_msrs ) {
+ ext->mc_msr[ext->mc_msrs].reg = msr;
+ rdmsrl(msr, ext->mc_msr[ext->mc_msrs].value);
+ ++ext->mc_msrs;
+ }
+}
+
+
+struct mcinfo_extended *
+intel_get_extended_msrs(struct mcinfo_global *mig, struct mc_info *mi)
+{
+ struct mcinfo_extended *mc_ext;
+ int i;
+
+ /*
+ * According to spec, processor _support_ 64 bit will always
+ * have MSR beyond IA32_MCG_MISC
+ */
+ if (!mi|| !mig || nr_intel_ext_msrs == 0 ||
+ !(mig->mc_gstatus & MCG_STATUS_EIPV))
+ return NULL;
+
+ mc_ext = x86_mcinfo_reserve(mi, sizeof(struct mcinfo_extended));
+ if (!mc_ext)
+ {
+ mi->flags |= MCINFO_FLAGS_UNCOMPLETE;
+ return NULL;
+ }
+
+ /* this function will called when CAP(9).MCG_EXT_P = 1 */
+ memset(&mc_ext, 0, sizeof(struct mcinfo_extended));
+ mc_ext->common.type = MC_TYPE_EXTENDED;
+ mc_ext->common.size = sizeof(struct mcinfo_extended);
+
+ for (i = MSR_IA32_MCG_EAX; i <= MSR_IA32_MCG_MISC; i++)
+ intel_get_extended_msr(mc_ext, i);
+
+#ifdef __x86_64__
+ for (i = MSR_IA32_MCG_R8; i <= MSR_IA32_MCG_R15; i++)
+ intel_get_extended_msr(mc_ext, i);
+#endif
+
+ return mc_ext;
+}
+
+static void intel_UCR_handler(struct mcinfo_bank *bank,
+ struct mcinfo_global *global,
+ struct mcinfo_extended *extension,
+ struct mca_handle_result *result)
+{
+ struct domain *d;
+ unsigned long mfn, gfn;
+ uint32_t status;
+
+ mce_printk(MCE_VERBOSE, "MCE: Enter UCR recovery action\n");
+ result->result = MCA_NEED_RESET;
+ if (bank->mc_addr != 0) {
+ mfn = bank->mc_addr >> PAGE_SHIFT;
+ if (!offline_page(mfn, 1, &status)) {
+ /* This is free page */
+ if (status & PG_OFFLINE_OFFLINED)
+ result->result = MCA_RECOVERED;
+ else if (status & PG_OFFLINE_PENDING) {
+ /* This page has owner */
+ if (status & PG_OFFLINE_OWNED) {
+ result->result |= MCA_OWNER;
+ result->owner = status >> PG_OFFLINE_OWNER_SHIFT;
+ mce_printk(MCE_QUIET, "MCE: This error page is ownded"
+ " by DOM %d\n", result->owner);
+ /* Fill vMCE# injection and vMCE# MSR virtualization "
+ * "related data */
+ bank->mc_domid = result->owner;
+ /* XXX: Cannot handle shared pages yet
+ * (this should identify all domains and gfn mapping to
+ * the mfn in question) */
+ BUG_ON( result->owner == DOMID_COW );
+ if ( result->owner != DOMID_XEN ) {
+
+ d = get_domain_by_id(result->owner);
+ if ( mca_ctl_conflict(bank, d) )
+ {
+ /* Guest has different MCE ctl with hypervisor */
+ if ( d )
+ put_domain(d);
+ return;
+ }
+
+ ASSERT(d);
+ gfn =
+ get_gpfn_from_mfn((bank->mc_addr) >> PAGE_SHIFT);
+ bank->mc_addr = gfn << PAGE_SHIFT |
+ (bank->mc_addr & (PAGE_SIZE -1 ));
+ if ( fill_vmsr_data(bank, d,
+ global->mc_gstatus) == -1 )
+ {
+ mce_printk(MCE_QUIET, "Fill vMCE# data for DOM%d "
+ "failed\n", result->owner);
+ put_domain(d);
+ domain_crash(d);
+ return;
+ }
+ /* We will inject vMCE to DOMU*/
+ if ( inject_vmce(d) < 0 )
+ {
+ mce_printk(MCE_QUIET, "inject vMCE to DOM%d"
+ " failed\n", d->domain_id);
+ put_domain(d);
+ domain_crash(d);
+ return;
+ }
+ /* Impacted domain go on with domain's recovery job
+ * if the domain has its own MCA handler.
+ * For xen, it has contained the error and finished
+ * its own recovery job.
+ */
+ result->result = MCA_RECOVERED;
+ put_domain(d);
+ }
+ }
+ }
+ }
+ }
+}
+
static void intel_machine_check(struct cpu_user_regs * regs, long error_code)
{
uint64_t gstatus;
@@ -691,6 +697,7 @@ static int intel_recoverable_scan(u64 st
return 0;
}

+/* CMCI */
static DEFINE_SPINLOCK(cmci_discover_lock);

/*
@@ -881,6 +888,7 @@ fastcall void smp_cmci_interrupt(struct
set_irq_regs(old_regs);
}

+/* MCA */
void mce_intel_feature_init(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_X86_MCE_THERMAL
@@ -1021,6 +1029,7 @@ enum mcheck_type intel_mcheck_init(struc
return mcheck_intel;
}

+/* intel specific MCA MSR */
int intel_mce_wrmsr(uint32_t msr, uint64_t val)
{
int ret = 0;

_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog