blob: f960c75714db39ebe068a7c6ea9cdd49543738d3 [file] [log] [blame]
/****************************************************************************
*
* 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 <stdio.h>
#include <sys/mman.h>
#include <time.h>
#ifdef __QNXNTO__
#include <sys/neutrino.h>
#include <sys/syspage.h>
#else
#include <i86.h>
#include <sys/irqinfo.h>
#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();
}