如果要使用MCA,首先要初始化芯片来激活 machine-check exception和 error-reporting机制
下面给出的伪代码中展示了如何完成MCA的初始化动作。本代码首先检测MCA和exception是否被芯片支持;然后使能 machine-check exception和 error-reporting的bank寄存器。
在主板上电以后, IA32_MCi_STATUS寄存器中的数据并不保证是正确的直到软件将它初始化为全0
伪代码如下:
/*获得CPUID, 并检查芯片是否支持MCA和MCE*/
if(CPUID[14]){
支持MCA;
}
if(CPUID[7]){
支持MCE;
}
if(CPU支持MCE){
if(CPU支持MCA){
if(1 == IA32_MCG_CAP.MCG_CTL_P) /*芯片上有IA32_MCG_CTL寄存器*/{
IA32_MCG_CTL = FFFFFFFFFFFFFFFFH; /*使能所有的MCA特性*/
}
if(1 == IA32_MCG_CAP.MCG_LMCE_P
&& 1 == IA32_FEATURE_CONTROL.LOCK
&& 1 == IA32_FEATURE_CONTROL.LMCE_ON){ /*芯片中有IA32_MCG_EXT_CTL寄存器,且平台支持LMCE特性*/
IA32_MCG_EXT_CTL = IA32_MCG_EXT_CTL | 01H; /*使能LMCE特性,以便精准单播MCE到被影响的CPU*/
}
/*确定支持的error-reporting banks数量*/
COUNT = IA32_MCG_CAP.Count;
MAX_BANK_NUMBER = COUNT - 1;
if(P6处理器家族, 且 EXTMODEL:MODEL <= 1AH){
/*除了第0个bank,使能所有的bank来记录错误*/
for(i=1; i <= MAX_BANK_NUMBER; i++){ /*从1到MAX_BANK_NUMBER*/
IA32_MCi_CTL = 0FFFFFFFFFFFFFFFFH;
}
}else {
/*使能所有的bank来记录错误*/
for(i=0; i <= MAX_BANK_NUMBER; i++){ /*从0到MAX_BANK_NUMBER*/
IA32_MCi_CTL = 0FFFFFFFFFFFFFFFFH;
}
}
/*在power reset的时候,BIOS清除所有的错误状态记录*/
if(BIOS发现在power reset){
for(i=0; i <= MAX_BANK_NUMBER; i++){ /*从0到MAX_BANK_NUMBER*/
IA32_MCi_STATUS = 0x0;
}
}else{
for(i=0; i <= MAX_BANK_NUMBER; i++){ /*从0到MAX_BANK_NUMBER*/
记录STATUS中已有的错误; /*既可BIOS做,也可以由OS做*/
IA32_MCi_STATUS = 0x0; /*只能OS做*/
}
}
}
在IDT的18号向量中,设定 Machine Check Exception (#MC) 的处理函数
CR4.MCE = 1; /*设定CR4的16bit, 使能Machine-Check Exceptions*/
}
相关文章 Intel MCE UCR ERRORS(三) UCR的错误分类