b3f7545ebc045972964cbe4a0dcb4b6dd9758a01
[tpg/acess2.git] / Kernel / arch / x86 / include / arch.h
1 /*
2  * Acess2
3  * - x86 Architecture
4  * arch/i386/include/arch.h
5  */
6 #ifndef _ARCH_H_
7 #define _ARCH_H_
8
9 // - Base Defintions
10 #define KERNEL_BASE     0xC0000000
11 #define BITS    32
12
13 // Allow nested spinlocks?
14 #define STACKED_LOCKS   1
15
16 // - Processor/Machine Specific Features
17 #if ARCH != i386 && ARCH != i486 && ARCH != i586
18 # error "Unknown architecture '" #ARCH "'"
19 #endif
20
21 #if USE_MP
22 # define        MAX_CPUS        8
23 #else
24 # define        MAX_CPUS        1
25 #endif
26
27 #if USE_PAE
28 # define        PHYS_BITS       48
29 #else
30 # define        PHYS_BITS       32
31 #endif
32
33 #define __ASM__ __asm__ __volatile__
34
35 // === Spinlocks ===
36 /**
37  * \brief Short Spinlock structure
38  */
39 struct sShortSpinlock {
40         volatile int    Lock;   //!< Lock value
41          int    IF;     //!< Interrupt state on call to SHORTLOCK
42         #if STACKED_LOCKS
43          int    Depth;
44         #endif
45 };
46 /**
47  * \brief Determine if a short spinlock is locked
48  * \param Lock  Lock pointer
49  */
50 static inline int IS_LOCKED(struct sShortSpinlock *Lock) {
51         return !!Lock->Lock;
52 }
53 /**
54  * \brief Acquire a Short Spinlock
55  * \param Lock  Lock pointer
56  * 
57  * This type of mutex should only be used for very short sections of code,
58  * or in places where a Mutex_* would be overkill, such as appending
59  * an element to linked list (usually two assignement lines in C)
60  * 
61  * \note This type of lock halts interrupts, so ensure that no timing
62  * functions are called while it is held. As a matter of fact, spend as
63  * little time as possible with this lock held
64  */
65 static inline void SHORTLOCK(struct sShortSpinlock *Lock) {
66          int    v = 1;
67          int    IF;
68         #if STACKED_LOCKS
69         extern int      GetCPUNum(void);
70          int    cpu = GetCPUNum() + 1;
71         #endif
72         
73         // Save interrupt state and clear interrupts
74         __ASM__ ("pushf;\n\tpop %%eax\n\tcli" : "=a"(IF));
75         IF &= 0x200;    // AND out all but the interrupt flag
76         
77         #if STACKED_LOCKS
78         if( Lock->Lock == cpu ) {
79                 Lock->Depth ++;
80                 return ;
81         }
82         #endif
83         
84         // Wait for another CPU to release
85         while(v) {
86                 #if STACKED_LOCKS
87                 // CMPXCHG:
88                 //  If r/m32 == EAX, set ZF and set r/m32 = r32
89                 //  Else, clear ZF and set EAX = r/m32
90                 __ASM__("lock cmpxchgl %%ecx, (%%edi)"
91                         : "=a"(v)
92                         : "a"(0), "c"(cpu), "D"(&Lock->Lock)
93                         );
94                 #else
95                 __ASM__("xchgl %%eax, (%%edi)":"=a"(v):"a"(1),"D"(&Lock->Lock));
96                 #endif
97         }
98         
99         Lock->IF = IF;
100 }
101 /**
102  * \brief Release a short lock
103  * \param Lock  Lock pointer
104  */
105 static inline void SHORTREL(struct sShortSpinlock *Lock) {
106         #if STACKED_LOCKS
107         if( Lock->Depth ) {
108                 Lock->Depth --;
109                 return ;
110         }
111         #endif
112         // Lock->IF can change anytime once Lock->Lock is zeroed
113         if(Lock->IF) {
114                 Lock->Lock = 0;
115                 __ASM__ ("sti");
116         }
117         else {
118                 Lock->Lock = 0;
119         }
120 }
121
122 // === MACROS ===
123 /**
124  * \brief Halt the CPU
125  */
126 #define HALT()  __asm__ __volatile__ ("hlt")
127 /**
128  * \brief Fire a magic breakpoint (bochs)
129  */
130 #define MAGIC_BREAK()   __asm__ __volatile__ ("xchg %bx, %bx")
131
132 // === TYPES ===
133 typedef unsigned int    Uint;   // Unsigned machine native integer
134 typedef unsigned char   Uint8;
135 typedef unsigned short  Uint16;
136 typedef unsigned long   Uint32;
137 typedef unsigned long long      Uint64;
138 typedef signed int              Sint;   // Signed Machine Native integer
139 typedef signed char             Sint8;
140 typedef signed short    Sint16;
141 typedef signed long             Sint32;
142 typedef signed long long        Sint64;
143 typedef Uint    size_t;
144
145 typedef Uint64  tPAddr;
146 typedef Uint32  tVAddr;
147
148 typedef struct {
149     Uint        gs, fs, es, ds;
150     Uint        edi, esi, ebp, kesp;
151         Uint    ebx, edx, ecx, eax;
152     Uint        int_num, err_code;
153     Uint        eip, cs;
154         Uint    eflags, esp, ss;
155 } tRegs;
156
157 typedef struct {
158         Uint    Resvd1[4];      // GS, FS, ES, DS
159         Uint    Arg4, Arg5;     // EDI, ESI
160         Uint    Arg6;   // EBP
161         Uint    Resvd2[1];      // Kernel ESP
162         union {
163                 Uint    Arg1;
164                 Uint    Error;
165         };      // EBX
166         union {
167                 Uint    Arg3;
168                 Uint    RetHi;  // High 32 bits of ret
169         };      // EDX
170         Uint    Arg2;   // ECX
171         union {
172                 Uint    Num;
173                 Uint    Return;
174         };      // EAX
175         Uint    Resvd3[5];      // Int, Err, Eip, CS, ...
176         Uint    StackPointer;   // ESP
177         Uint    Resvd4[1];      // SS
178 } tSyscallRegs;
179
180 typedef struct {
181         #if USE_PAE
182         Uint    PDPT[4];
183         #else
184         Uint    CR3;
185         #endif
186 } tMemoryState;
187
188 typedef struct {
189         Uint    EIP, ESP, EBP;
190 } tTaskState;
191
192 #endif  // !defined(_ARCH_H_)

UCC git Repository :: git.ucc.asn.au