aboutsummaryrefslogtreecommitdiff
path: root/board/MAI/bios_emulator/scitech/src/pm/qnx/mtrrqnx.c
blob: de749e38349f1ed5594026c52f2e196027c9a437 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/****************************************************************************
*
*                   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();
}