📄 smp.c
字号:
/****************************************************************************** * * Copyright (c) 2003 Gerhard W. Gruber * * PROJECT: pICE * $Source: /cvsroot/pice/pice/module/smp.c,v $ * $Revision: 1.3 $ * $Date: 2004/02/17 23:07:37 $ * $Author: lightweave $ * $Name: $ * * $Log: smp.c,v $ * Revision 1.3 2004/02/17 23:07:37 lightweave * * Improved the DEBUG facillity and replaced the configuration handler with a * new code which now can read MS Windows INI style files. See CHANGES.txt for * more details. * Also added a macro which prevents compiling for kernels before 2.4.19. * * Revision 1.2 2003/06/18 22:00:22 lightweave * DEBUG and DEBUG_SERIAL added * * *****************************************************************************/static char *ident = "$Header: /cvsroot/pice/pice/module/smp.c,v 1.3 2004/02/17 23:07:37 lightweave Exp $";/*++Copyright (c) 1998-2001 Klaus P. GerlicherModule Name: smp.cAbstract: symmetric multi processor stuffEnvironment: LINUX 2.2.X Kernel mode onlyAuthor: Klaus P. GerlicherRevision History: 22-Oct-2001: createdCopyright notice: This file may be distributed under the terms of the GNU Public License.--*/////////////////////////////////////////////////////// INCLUDES////#include "remods.h"#include <asm/io.h>#include <asm/smp.h>#include "precomp.h"#ifdef CONFIG_SMPstatic volatile ULONG ulWait[PICE_MAX_CPUS] = {0,};// something we want a CPU to do while idleingstatic volatile ULONG ulCmdForThisCPU[PICE_MAX_CPUS] = {0,};struct task_struct *current_for_cpu[PICE_MAX_CPUS] = {0,};EXCEPTION_FRAME *frame_for_cpu[PICE_MAX_CPUS];CPUID_S cpuid_for_cpu[PICE_MAX_CPUS];// this only shows that CPUs are spinning volatile ULONG ulSpinCount[PICE_MAX_CPUS] = {0,};PUCHAR pLocalApic = NULL;void GetCpuId(void);#endif // CONFIG_SMP#if LINUX_VERSION_CODE < 0x020400 // kernels below 2.4.0 don't export thisstatic int (*pice_smp_call_function)(void (*function)(void*),void* info,int retry,int wait);#endif // LINUX_VERSION_CODE < 0x020400 //************************************************************************* // ProcessorsIdleLoop() // //************************************************************************* void ProcessorsIdleLoop(EXCEPTION_FRAME* pFrame){#ifdef CONFIG_SMP ULONG ulLocalFlags; ULONG this = current->processor; ENTER_FUNC(); save_flags(ulLocalFlags); cli(); ulSpinCount[this] = 0; // loop until ulWait goes high // we could let the other processor do any work we want here, maybe implement that someday while(!ulWait[this]) { //DPRINT(PICE_DEBUG, DBT_SMP, DBL_INFO, "LoopProcessorsLoop(): spinning...\n"); // increment spin counter, we can see this incrementing in shell with "CPU" command ulSpinCount[this]++; switch(ulCmdForThisCPU[this]) { case SMP_CPU_GET_CPU_INFO: DPRINT(PICE_DEBUG, DBT_SMP, DBL_INFO, "SMP_CPU_GET_CPU_INFO on CPU #%u\n",this); current_for_cpu[this] = current; frame_for_cpu[this] = pFrame; GetCpuId(); ulCmdForThisCPU[this] = SMP_CPU_DONE; DPRINT(PICE_DEBUG, DBT_SMP, DBL_INFO, "after SMP_CPU_GET_CPU_INFO on CPU #%u\n",this); break; case SMP_CPU_DONE: default: break; } } // well, who knows what for FlushCacheAndTLB(); restore_flags(ulLocalFlags); LEAVE_FUNC();#endif}//************************************************************************* // CallOtherCPU() // //************************************************************************* void CallOtherCPU(ULONG ulCmd){#ifdef CONFIG_SMP ULONG i; ENTER_FUNC(); DPRINT(PICE_DEBUG, DBT_SMP, DBL_INFO, "sending other processors cmd %x\n", ulCmd); // tell other CPUs to provide stuff for(i = 0; i < smp_num_cpus; i++) { if(i != current->processor) { ulCmdForThisCPU[i] = ulCmd; } } DPRINT(PICE_DEBUG, DBT_SMP, DBL_INFO, "waiting for other processors\n"); // wait for data for(i = 0; i < smp_num_cpus; i++) { if(i != current->processor) { while(ulCmdForThisCPU[i] != SMP_CPU_DONE) __asm__ __volatile__("nop"); } } LEAVE_FUNC();#endif // CONFIG_SMP}//************************************************************************* // LoopProcessorLoop() // //************************************************************************* #ifdef CONFIG_SMPstatic void LoopProcessorLoop(void* info){ void Debugger2ndProcessor(void); Debugger2ndProcessor();}#endif // CONFIG_SMP//************************************************************************* // LoopProcessors() // //************************************************************************* void LoopProcessors(void){#ifdef CONFIG_SMP ULONG i; ENTER_FUNC(); // tell others to loop for(i = 0; i < smp_num_cpus; i++) { // loop variable ulWait[i] = 0; } // call other CPUs, retry until ready and don't wait to finish // as all others will spin until return conditions are met#if LINUX_VERSION_CODE < 0x020400 DPRINT(PICE_DEBUG, DBT_SMP, DBL_INFO, "pice_smp_call_function = %.8X\n",pice_smp_call_function); if(pice_smp_call_function) (*pice_smp_call_function)(LoopProcessorLoop, NULL, 1, 0);#else // LINUX_VERSION_CODE < 0x020400 smp_call_function(LoopProcessorLoop, NULL, 1, 0);#endif // LINUX_VERSION_CODE < 0x020400 LEAVE_FUNC();#endif // CONFIG_SMP}//************************************************************************* // UnloopProcessors() // //************************************************************************* void UnloopProcessors(void){#ifdef CONFIG_SMP ULONG i; // tell others to unloop for(i=0;i<smp_num_cpus;i++) ulWait[i] = 1;#endif // CONFIG_SMP}//************************************************************************* // GetProcessor() // //************************************************************************* ULONG GetProcessor(void){ return smp_processor_id();}//************************************************************************* // FlushCacheAndTLBAllCpus() // //************************************************************************* #ifdef CONFIG_SMPstatic void CallFlushCacheAndTLB(void* info){ FlushCacheAndTLB();}#endif // CONFIG_SMP//************************************************************************* // FlushCacheAndTLBAllCpus() // //************************************************************************* void FlushCacheAndTLBAllCpus(void){ ENTER_FUNC(); // call other CPUs, retry until ready and wait#if LINUX_VERSION_CODE < 0x020400 DPRINT(PICE_DEBUG, DBT_SMP, DBL_INFO, "pice_smp_call_function = %.8X\n",pice_smp_call_function); if(pice_smp_call_function) (*pice_smp_call_function)(CallFlushCacheAndTLB, NULL, 1, 0);#else // LINUX_VERSION_CODE < 0x020400 smp_call_function(CallFlushCacheAndTLB, NULL, 1, 0);#endif // LINUX_VERSION_CODE < 0x020400 FlushCacheAndTLB(); LEAVE_FUNC();}//************************************************************************* // CallDisableHWBreakpoints() // //************************************************************************* static void CallDisableHWBreakpoints(void* info){ // disable HW breakpoints __asm__ __volatile__( "xorl %%eax,%%eax\n" "mov %%eax,%%dr6\n" "mov %%eax,%%dr7\n" "mov %%dr0,%%eax\n" "mov %%dr1,%%eax\n" "mov %%dr2,%%eax\n" "mov %%dr3,%%eax\n" :::"eax" ); }//************************************************************************* // DisableHWBreakpointsAllCpus() // //************************************************************************* void DisableHWBreakpointsAllCpus(void){ ENTER_FUNC(); // call other CPUs, retry until ready and wait#if LINUX_VERSION_CODE < 0x020400 DPRINT(PICE_DEBUG, DBT_SMP, DBL_INFO, "pice_smp_call_function = %.8X\n",pice_smp_call_function); if(pice_smp_call_function) (*pice_smp_call_function)(CallDisableHWBreakpoints, NULL, 1, 0);#else // LINUX_VERSION_CODE < 0x020400 smp_call_function(CallDisableHWBreakpoints, NULL, 1, 0);#endif // LINUX_VERSION_CODE < 0x020400 CallDisableHWBreakpoints(NULL); LEAVE_FUNC();}//************************************************************************* // GetCpuId() // //************************************************************************* void GetCpuId(void){#ifdef CONFIG_SMP PULONG p; ULONG junk; p = (PULONG)&cpuid_for_cpu[current->processor].vendor; memset(cpuid_for_cpu[current->processor].vendor,0,12); cpuid_for_cpu[current->processor].vendor[12] = 0; cpuid(0x00000000,&cpuid_for_cpu[current->processor].max_cpuid,&p[0],&p[2],&p[1]); cpuid(0x00000001,(PULONG)&cpuid_for_cpu[current->processor].signature,&junk,&junk,&junk); p = (PULONG)&cpuid_for_cpu[current->processor].cpu_name; memset(cpuid_for_cpu[current->processor].cpu_name,0,48); cpuid_for_cpu[current->processor].cpu_name[48] = 0; if(cpuid_for_cpu[current->processor].max_cpuid < 0x80000004) return; cpuid(0x80000002,&p[0],&p[1],&p[2],&p[3]); cpuid(0x80000003,&p[4],&p[5],&p[6],&p[7]); cpuid(0x80000004,&p[8],&p[9],&p[10],&p[11]);#endif // CONFIG_SMP}//************************************************************************* // InitSmp() // //************************************************************************* void InitSmp(void){ ENTER_FUNC();#ifdef CONFIG_SMP#if LINUX_VERSION_CODE < 0x020400 // try to find SMP smp_call_function ScanSystemMap("smp_call_function",(PULONG)&pice_smp_call_function); DPRINT(PICE_DEBUG, DBT_SMP, DBL_INFO, "smp_call_function @ %.8X\n",pice_smp_call_function);#endif // LINUX_VERSION_CODE < 0x020400 pLocalApic = ioremap(0xFFE00000,PAGE_SIZE);#endif // CONFIG_SMP LEAVE_FUNC();}//************************************************************************* // ExitSmp() // //************************************************************************* void ExitSmp(void){#ifdef CONFIG_SMP if(pLocalApic) iounmap(pLocalApic);#endif // CONFIG_SMP}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -