/**************************************************************************** * * SciTech OS Portability Manager Library * * ======================================================================== * * The contents of this file are subject to the SciTech MGL Public * License Version 1.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.scitechsoft.com/mgl-license.txt * * Software distributed under the License is distributed on an * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc. * * The Initial Developer of the Original Code is SciTech Software, Inc. * All Rights Reserved. * * ======================================================================== * * Language: ANSI C * Environment: QNX * * Description: MTRR helper functions module. To make it easier to implement * the MTRR support under QNX, we simply put our ring 0 helper * functions into stubs that run them at ring 0 using whatever * mechanism is available. * ****************************************************************************/ #include "pmapi.h" #include #include #include #ifdef __QNXNTO__ #include #include #else #include #include #endif /*--------------------------- Global variables ----------------------------*/ #define R0_FLUSH_TLB 0 #define R0_SAVE_CR4 1 #define R0_RESTORE_CR4 2 #define R0_READ_MSR 3 #define R0_WRITE_MSR 4 typedef struct { int service; int reg; ulong eax; ulong edx; } R0_data; extern volatile R0_data _PM_R0; /*----------------------------- Implementation ----------------------------*/ #ifdef __QNXNTO__ const struct sigevent * _ASMAPI _PM_ring0_isr(void *arg, int id); #else pid_t far _ASMAPI _PM_ring0_isr(); #endif /**************************************************************************** REMARKS: Return true if ring 0 (or if we can call the helpers functions at ring 0) ****************************************************************************/ ibool _ASMAPI _MTRR_isRing0(void) { #ifdef __QNXNTO__ return false; // Not implemented yet! #else return true; #endif } /**************************************************************************** REMARKS: Function to execute a service at ring 0. This is done using the clock interrupt handler since the code we attach to it will always run at ring 0. ****************************************************************************/ static void CallRing0(void) { #ifdef __QNXNTO__ uint clock_intno = SYSPAGE_ENTRY(qtime)->intr; #else uint clock_intno = 0; /* clock irq */ #endif int intrid; #ifdef __QNXNTO__ mlock((void*)&_PM_R0, sizeof(_PM_R0)); ThreadCtl(_NTO_TCTL_IO, 0); #endif #ifdef __QNXNTO__ if ((intrid = InterruptAttach(_NTO_INTR_CLASS_EXTERNAL | clock_intno, _PM_ring0_isr, (void*)&_PM_R0, sizeof(_PM_R0), _NTO_INTR_FLAGS_END)) == -1) { #else if ((intrid = qnx_hint_attach(clock_intno, _PM_ring0_isr, FP_SEG(&_PM_R0))) == -1) { #endif perror("Attach"); exit(-1); } while (_PM_R0.service != -1) ; #ifdef __QNXNTO__ InterruptDetachId(intrid); #else qnx_hint_detach(intrid); #endif } /**************************************************************************** REMARKS: Flush the translation lookaside buffer. ****************************************************************************/ void PMAPI PM_flushTLB(void) { _PM_R0.service = R0_FLUSH_TLB; CallRing0(); } /**************************************************************************** REMARKS: Read and return the value of the CR4 register ****************************************************************************/ ulong _ASMAPI _MTRR_saveCR4(void) { _PM_R0.service = R0_SAVE_CR4; CallRing0(); return _PM_R0.reg; } /**************************************************************************** REMARKS: Restore the value of the CR4 register ****************************************************************************/ void _ASMAPI _MTRR_restoreCR4(ulong cr4Val) { _PM_R0.service = R0_RESTORE_CR4; _PM_R0.reg = cr4Val; CallRing0(); } /**************************************************************************** REMARKS: Read a machine status register for the CPU. ****************************************************************************/ void _ASMAPI _MTRR_readMSR( int reg, ulong *eax, ulong *edx) { _PM_R0.service = R0_READ_MSR; _PM_R0.reg = reg; CallRing0(); *eax = _PM_R0.eax; *edx = _PM_R0.edx; } /**************************************************************************** REMARKS: Write a machine status register for the CPU. ****************************************************************************/ void _ASMAPI _MTRR_writeMSR( int reg, ulong eax, ulong edx) { _PM_R0.service = R0_WRITE_MSR; _PM_R0.reg = reg; _PM_R0.eax = eax; _PM_R0.edx = edx; CallRing0(); }