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

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