📄 multicpu.cpp
字号:
/*******************************************************************
* Functions for MP Systems *
******************************************************************/
/*--
Module Name:
multicpu.cpp
Abstract: Functions to suspend/resume all secondary processors.
Revision History:
Sten 11/05/2003
Initial release
--*/
extern "C" {
#pragma warning ( push, 3 )
#include <ntddk.h>
extern void __declspec(dllimport) HalInitializeProcessor(int, int);
#pragma warning ( pop )
}
#pragma warning ( disable: 4514 ) // unreferenced inline function has been removed
#include "multicpu.h"
///////////////////////////////////////////////////////////////////
// PUBLIC DEFINITIONS
///////////////////////////////////////////////////////////////////
DWORD mp_OldHandler = 0;
WORD mp_OldSelector = 0;
BYTE mp_OldFlag = 0;
DWORD mp_NumOfCPUs = 1; // default value is 1 processor
DWORD mp_PCR_VA = 0xFFDFF000;
DWORD *mp_PCR_VA_array = &mp_PCR_VA;
///////////////////////////////////////////////////////////////////
// STATIC DEFINITIONS
///////////////////////////////////////////////////////////////////
static DWORD mp_spinlock = 0;
static DWORD mp_IPI_Delivered_Flag = 0;
static DWORD mp_LocalAPIC_ID = 0xFFFFFFFF;
static WORD mp_SavedDS = 0x23;
static DWORD mp_APIC_Regs_VA = 0xFFFE0000;
static DWORD mp_OldNMIHandler = 0;
static WORD mp_OldNMISelector = 0;
static BYTE mp_OldNMIFlag = 0;
///////////////////////////////////////////////////////////////////
// mp_Init()
//
// Initialize multicpu module
//
///////////////////////////////////////////////////////////////////
void __declspec(naked) mp_Init()
{
__asm
{
pushad
mov ax, ds ; save data selector
mov mp_SavedDS, ax
call mp_AnalyzeHalInitProcessor
/*
mov eax, 2 ; hook NMI interrupt on all CPUs
mov dl, 8Eh
mov edi, offset mp_NMIHook
mov bx, cs
call mp_HookInterrupt
mov eax, mp_OldHandler
mov mp_OldNMIHandler, eax
mov bx, mp_OldSelector
mov mp_OldNMISelector, bx
mov al, mp_OldFlag
mov mp_OldNMIFlag, al
*/
popad
retn
}
}
///////////////////////////////////////////////////////////////////
// mp_Done()
//
// Unhook all hooks installed by multicpu module
//
///////////////////////////////////////////////////////////////////
void __declspec(naked) mp_Done()
{
__asm
{
cmp mp_OldNMIHandler, 0
jz exit_done
pushad
mov eax, 2 ; restore old NMI handler on all CPUs
mov dl, mp_OldNMIFlag ; TO DO: restore whole IDT Entry
mov edi, mp_OldNMIHandler
mov bx, mp_OldNMISelector
call mp_HookInterrupt
popad
exit_done:
retn
}
}
///////////////////////////////////////////////////////////////////
// mp_NMIHook()
//
// My own NMI handler
//
///////////////////////////////////////////////////////////////////
void __declspec(naked) mp_NMIHook()
{
__asm
{
// call mp_INT02_IOAPIC
push word ptr cs:[mp_OldNMISelector]
push dword ptr cs:[mp_OldNMIHandler]
retf
}
}
///////////////////////////////////////////////////////////////////
// mp_AnalyzeHalInitProcessor()
//
// Returns number of active CPUs in the system.
// - Sets mp_NumOfCPUs to the number of active processors in the
// system.
// - Sets mp_PCR_VA_array to the value extracted from the HAL
// code.
//
///////////////////////////////////////////////////////////////////
DWORD __declspec(naked) mp_AnalyzeHalInitProcessor()
{
__asm
{
pushad
mov ecx, 128
mov edi, offset HalInitializeProcessor
mov edi, [edi]
cld
search_some_bytes:
mov al, 89h
repne scasb
jnz short return_default
mov ax, [edi]
cmp ax, 850Ch
jnz short search_some_bytes
mov eax, [edi+2]
or eax, eax
jns short return_default
add edi, 80000h
cmp eax, edi
ja short return_default
mov mp_PCR_VA_array, eax
mov edi, eax
xor ecx, ecx
count_CPUs:
mov eax, [edi]
or eax, eax
jz short count_end
add edi, 4
inc ecx
jmp short count_CPUs
; ---------------------------------------------------------------------------
count_end:
jecxz short return_default
mov mp_NumOfCPUs, ecx
return_default:
popad
mov eax, mp_NumOfCPUs
retn
}
}
///////////////////////////////////////////////////////////////////
// mp_GetLocalAPIC_ID()
//
// Return local APIC ID for current processor.
//
///////////////////////////////////////////////////////////////////
DWORD __declspec(naked) mp_GetLocalAPIC_ID()
{
__asm
{
mov eax, mp_APIC_Regs_VA
mov eax, [eax+20h] ; Read Local APIC ID
shr eax, 24 ; extract ID
mov mp_LocalAPIC_ID, eax
retn
}
}
///////////////////////////////////////////////////////////////////
// mp_ResumeSecondCPUs()
//
// Resume all secondary processors.
//
///////////////////////////////////////////////////////////////////
DWORD __declspec(naked) mp_ResumeSecondCPUs()
{
__asm
{
push eax
mov eax, ss:mp_spinlock
or eax, eax
jz short resume_CPUs_exit
cmp ax, 1
jbe short resume_CPUs_exit
dec eax
or ax, ax
jz short clear_flags
mov mp_spinlock, eax
jmp short resume_CPUs_exit
; ---------------------------------------------------------------------------
clear_flags:
mov mp_LocalAPIC_ID, 0FFFFFFFFh
mov mp_spinlock, 0
resume_CPUs_exit:
pop eax
retn
}
}
///////////////////////////////////////////////////////////////////
// mp_StopSecondCPUs()
//
// Stop all secondary processors.
//
///////////////////////////////////////////////////////////////////
DWORD __declspec(naked) mp_StopSecondCPUs()
{
__asm
{
cmp cs:mp_NumOfCPUs, 1
ja short do_stop_second_cpus
retn
; ---------------------------------------------------------------------------
do_stop_second_cpus:
pushad
mov ebp, esp
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -