d13010e7979d679a55fe672c82d308d378af4853
[reactos.git] / reactos / ntoskrnl / hal / x86 / usercall.c
1 #include <windows.h>
2 #include <internal/ntoskrnl.h>
3 #include <internal/ke.h>
4 #include <internal/symbol.h>
5 #include <internal/i386/segment.h>
6 #include <internal/mmhal.h>
7
8 #define NDEBUG
9 #include <internal/debug.h>
10 #include <internal/service.h>
11
12 /* The service dispatcher will take the service number passed in
13 * by the user mode process, logical and it with ServiceNumberMask
14 * and compare the resulting value with ServiceNumberValue. If the
15 * value matches, The passed service number will be and'ed with the
16 * inverse of ServiceNumberMask to obtain the index into the ServiceTable
17 * for the service to call
18 */
19 typedef struct _HAL_DISPATCH_TABLE_ENTRY
20 {
21 DWORD ServiceNumberMask;
22 DWORD ServiceNumberValue;
23 PSERVICE_TABLE ServiceTable;
24 DWORD TableCount;
25 } HAL_DISPATCH_TABLE_ENTRY, *PHAL_DISPATCH_TABLE_ENTRY;
26
27 static KSPIN_LOCK DispatchTableLock = {0,};
28 static DWORD DispatchTableCount = 0;
29 static HAL_DISPATCH_TABLE_ENTRY DispatchTables[16];
30
31 NTSTATUS HalRegisterServiceTable(DWORD Mask,
32 DWORD Value,
33 PSERVICE_TABLE Table,
34 DWORD Count)
35 {
36 NTSTATUS Status;
37 KIRQL OldLvl;
38
39 KeAcquireSpinLock(&DispatchTableLock, &OldLvl);
40
41 Status = STATUS_SUCCESS;
42
43 /* FIXME: should check for invalid/overlapping service tables */
44 DispatchTables[DispatchTableCount].ServiceNumberMask = Mask;
45 DispatchTables[DispatchTableCount].ServiceNumberValue = Value;
46 DispatchTables[DispatchTableCount].ServiceTable = Table;
47 DispatchTables[DispatchTableCount].TableCount = Count;
48 DispatchTableCount++;
49
50 KeReleaseSpinLock(&DispatchTableLock, OldLvl);
51
52 return Status;
53 }
54
55 #define _STR(x) #x
56 #define STR(x) _STR(x)
57
58 void PsBeginThreadWithContextInternal(void);
59 __asm__(
60 "\n\t.global _PsBeginThreadWithContextInternal\n\t"
61 "_PsBeginThreadWithContextInternal:\n\t"
62 "pushl $0\n\t"
63 "call _KeLowerIrql\n\t"
64 "popl %eax\n\t"
65 "popl %eax\n\t"
66 "popl %eax\n\t"
67 "popl %eax\n\t"
68 "popl %eax\n\t"
69 "popl %eax\n\t"
70 "popl %eax\n\t"
71 "popl %eax\n\t"
72 "addl $112,%esp\n\t"
73 "popl %gs\n\t"
74 "popl %fs\n\t"
75 "popl %es\n\t"
76 "popl %ds\n\t"
77 "popl %edi\n\t"
78 "popl %esi\n\t"
79 "popl %ebx\n\t"
80 "popl %edx\n\t"
81 "popl %ecx\n\t"
82 "popl %eax\n\t"
83 "popl %ebp\n\t"
84 "iret\n\t");
85
86 void interrupt_handler2e(void);
87 __asm__("\n\t.global _interrupt_handler2e\n\t"
88 "_interrupt_handler2e:\n\t"
89
90 /* Save the users context */
91 "pushl %ds\n\t"
92 "pushl %es\n\t"
93 "pushl %esi\n\t"
94 "pushl %edi\n\t"
95 "pushl %ebp\n\t"
96 "pushl %ebx\n\t"
97
98 /* Set ES to kernel segment */
99 "movw $"STR(KERNEL_DS)",%bx\n\t"
100 "movw %bx,%es\n\t"
101
102 /* Allocate new Kernel stack frame */
103 "movl %esp,%ebp\n\t"
104
105 /* Users's current stack frame pointer is source */
106 "movl %edx,%esi\n\t"
107
108 /* FIXME: determine system service table to use */
109 /* FIXME: chech to see if SS is valid/inrange */
110
111 /* Allocate room for argument list from kernel stack */
112 "movl %es:__SystemServiceTable(,%eax,8),%ecx\n\t"
113 "subl %ecx,%esp\n\t"
114
115 /* Copy the arguments from the user stack to the kernel stack */
116 "movl %esp,%edi\n\t"
117 "rep\n\tmovsb\n\t"
118
119 /* DS is now also kernel segment */
120 "movw %bx,%ds\n\t"
121
122 /* Make the system service call */
123 "movl %ds:__SystemServiceTable+4(,%eax,8),%eax\n\t"
124 "call *%eax\n\t"
125
126 /* Deallocate the kernel stack frame */
127 "movl %ebp,%esp\n\t"
128
129 /* Restore the user context */
130 "popl %ebx\n\t"
131 "popl %ebp\n\t"
132 "popl %edi\n\t"
133 "popl %esi\n\t"
134 "popl %es\n\t"
135 "popl %ds\n\t"
136 "iret\n\t");
137
138