Page MenuHomeFreeBSD

D9612.id25216.diff
No OneTemporary

D9612.id25216.diff

Index: sys/x86/include/apicreg.h
===================================================================
--- sys/x86/include/apicreg.h
+++ sys/x86/include/apicreg.h
@@ -241,6 +241,18 @@
LAPIC_CCR_TIMER = 0x39,
LAPIC_DCR_TIMER = 0x3e,
LAPIC_SELF_IPI = 0x3f, /* Only in x2APIC */
+ LAPIC_EXT_FEATURES = 0x40, /* AMD */
+ LAPIC_EXT_CTRL = 0x41, /* AMD */
+ LAPIC_EXT_SEOI = 0x42, /* AMD */
+ LAPIC_EXT_IER0 = 0x48, /* AMD */
+ LAPIC_EXT_IER1 = 0x49, /* AMD */
+ LAPIC_EXT_IER2 = 0x4a, /* AMD */
+ LAPIC_EXT_IER3 = 0x4b, /* AMD */
+ LAPIC_EXT_IER4 = 0x4c, /* AMD */
+ LAPIC_EXT_IER5 = 0x4d, /* AMD */
+ LAPIC_EXT_IER6 = 0x4e, /* AMD */
+ LAPIC_EXT_IER7 = 0x4f, /* AMD */
+ LAPIC_EXT_LVT = 0x50, /* AMD */
};
/*
@@ -295,6 +307,7 @@
#define APIC_VER_MAXLVT 0x00ff0000
#define MAXLVTSHIFT 16
#define APIC_VER_EOI_SUPPRESSION 0x01000000
+#define APIC_VER_AMD_EXT_SPACE 0x80000000
/* fields in LDR */
#define APIC_LDR_RESERVED 0x00ffffff
@@ -418,6 +431,13 @@
#define APIC_TDCR_128 0x0a
#define APIC_TDCR_1 0x0b
+/* Constants related to AMD Extended APIC Features Register */
+#define APIC_EXTF_ELVT_MASK 0x00ff0000
+#define APIC_EXTF_ELVT_SHIFT 16
+#define APIC_EXTF_EXTID_CAP 0x00000004
+#define APIC_EXTF_SEIO_CAP 0x00000002
+#define APIC_EXTF_IER_CAP 0x00000001
+
/* LVT table indices */
#define APIC_LVT_LINT0 0
#define APIC_LVT_LINT1 1
@@ -428,6 +448,13 @@
#define APIC_LVT_CMCI 6
#define APIC_LVT_MAX APIC_LVT_CMCI
+/* Extended LVT constants, seem to be assigned by fiat */
+#define APIC_ELVT_IBS 0 /* Instruction based sampling */
+#define APIC_ELVT_MCA 1 /* MCE thresholding */
+#define APIC_ELVT_DEI 2 /* Deferred error interrupt */
+#define APIC_ELVT_3 3 /* Free */
+#define APIC_ELVT_MAX APIC_ELVT_3
+
/******************************************************************************
* I/O APIC defines
*/
Index: sys/x86/include/apicvar.h
===================================================================
--- sys/x86/include/apicvar.h
+++ sys/x86/include/apicvar.h
@@ -232,6 +232,9 @@
/* CMC */
void (*enable_cmc)(void);
+ /* AMD ELVT */
+ int (*enable_mca_elvt)(void);
+
/* IPI */
void (*ipi_raw)(register_t, u_int);
void (*ipi_vectored)(u_int, int);
@@ -396,6 +399,13 @@
apic_ops.enable_cmc();
}
+static inline int
+lapic_enable_mca_elvt(void)
+{
+
+ return (apic_ops.enable_mca_elvt());
+}
+
static inline void
lapic_ipi_raw(register_t icrlo, u_int dest)
{
Index: sys/x86/x86/local_apic.c
===================================================================
--- sys/x86/x86/local_apic.c
+++ sys/x86/x86/local_apic.c
@@ -319,6 +319,7 @@
static void native_lapic_disable_pmc(void);
static void native_lapic_reenable_pmc(void);
static void native_lapic_enable_cmc(void);
+static int native_lapic_enable_mca_elvt(void);
static int native_lapic_set_lvt_mask(u_int apic_id, u_int lvt,
u_char masked);
static int native_lapic_set_lvt_mode(u_int apic_id, u_int lvt,
@@ -357,6 +358,7 @@
.disable_pmc = native_lapic_disable_pmc,
.reenable_pmc = native_lapic_reenable_pmc,
.enable_cmc = native_lapic_enable_cmc,
+ .enable_mca_elvt = native_lapic_enable_mca_elvt,
#ifdef SMP
.ipi_raw = native_lapic_ipi_raw,
.ipi_vectored = native_lapic_ipi_vectored,
@@ -608,12 +610,14 @@
static void
native_lapic_dump(const char* str)
{
+ uint32_t version;
uint32_t maxlvt;
- maxlvt = (lapic_read32(LAPIC_VERSION) & APIC_VER_MAXLVT) >> MAXLVTSHIFT;
+ version = lapic_read32(LAPIC_VERSION);
+ maxlvt = (version & APIC_VER_MAXLVT) >> MAXLVTSHIFT;
printf("cpu%d %s:\n", PCPU_GET(cpuid), str);
printf(" ID: 0x%08x VER: 0x%08x LDR: 0x%08x DFR: 0x%08x",
- lapic_read32(LAPIC_ID), lapic_read32(LAPIC_VERSION),
+ lapic_read32(LAPIC_ID), version,
lapic_read32(LAPIC_LDR), x2apic_mode ? 0 : lapic_read32(LAPIC_DFR));
if ((cpu_feature2 & CPUID2_X2APIC) != 0)
printf(" x2APIC: %d", x2apic_mode);
@@ -628,6 +632,20 @@
printf("\n");
if (maxlvt >= APIC_LVT_CMCI)
printf(" cmci: 0x%08x\n", lapic_read32(LAPIC_LVT_CMCI));
+ if (cpu_vendor_id == CPU_VENDOR_AMD &&
+ (version & APIC_VER_AMD_EXT_SPACE) != 0) {
+ uint32_t extf;
+ int elvt;
+ int i;
+
+ extf = lapic_read32(LAPIC_EXT_FEATURES);
+ printf(" AMD ext features: 0x%08x\n", extf);
+ elvt = (extf & APIC_EXTF_ELVT_MASK) >> APIC_EXTF_ELVT_SHIFT;
+ for (i = 0; i < elvt; i++) {
+ printf(" AMD elvt%d: 0x%08x\n", i,
+ lapic_read32(LAPIC_EXT_LVT + i));
+ }
+ }
}
static void
@@ -1311,6 +1329,38 @@
printf("lapic%u: CMCI unmasked\n", apic_id);
}
+static int
+native_lapic_enable_mca_elvt(void)
+{
+ uint32_t elvt;
+ uint32_t value;
+
+#ifdef DEV_ATPIC
+ if (!x2apic_mode && lapic_map == NULL)
+ return (-1);
+#endif
+
+ if (cpu_vendor_id != CPU_VENDOR_AMD ||
+ (lapic_read32(LAPIC_VERSION) & APIC_VER_AMD_EXT_SPACE) == 0) {
+ return (-1);
+ }
+ elvt = (lapic_read32(LAPIC_EXT_FEATURES) & APIC_EXTF_ELVT_MASK) >>
+ APIC_EXTF_ELVT_SHIFT;
+ if (elvt <= APIC_ELVT_MCA)
+ return (-1);
+
+ value = lapic_read32(LAPIC_EXT_LVT + APIC_ELVT_MCA);
+ if ((value & APIC_LVT_M) == 0) {
+ printf("AMD Extended LVT0 is already active\n");
+ return (-1);
+ }
+ value &= ~(APIC_LVT_M | APIC_LVT_DM | APIC_LVT_VECTOR);
+ value |= APIC_LVT_DM_FIXED;
+ value |= APIC_CMC_INT;
+ lapic_write32(LAPIC_EXT_LVT + APIC_ELVT_MCA, value);
+ return (APIC_ELVT_MCA);
+}
+
void
lapic_handle_error(void)
{

File Metadata

Mime Type
text/plain
Expires
Tue, Apr 7, 11:42 AM (9 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31028480
Default Alt Text
D9612.id25216.diff (5 KB)

Event Timeline