3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ke/i386/ldt.c
6 * PURPOSE: LDT managment
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
11 /* INCLUDES *****************************************************************/
15 #include <internal/debug.h>
17 /* GLOBALS *******************************************************************/
19 static KSPIN_LOCK LdtLock
;
21 /* FUNCTIONS *****************************************************************/
23 BOOL
PspIsDescriptorValid(PLDT_ENTRY ldt_entry
)
27 Allow invalid descriptors.
29 if(!ldt_entry
->HighWord
.Bits
.Type
&&
30 !ldt_entry
->HighWord
.Bits
.Dpl
)
33 /* eliminate system descriptors and code segments other than
34 execute and execute/read and DPL<3 descriptors */
35 if(!(ldt_entry
->HighWord
.Bits
.Type
& 0x10) ||
36 (ldt_entry
->HighWord
.Bits
.Type
& 0x8 &&
37 ldt_entry
->HighWord
.Bits
.Type
& 0x4) ||
38 ldt_entry
->HighWord
.Bits
.Dpl
!= 3 ||
39 ldt_entry
->HighWord
.Bits
.Reserved_0
) return FALSE
;
41 if(!ldt_entry
->HighWord
.Bits
.Pres
) return TRUE
;
43 Base
=ldt_entry
->BaseLow
| (ldt_entry
->HighWord
.Bytes
.BaseMid
<< 16) |
44 (ldt_entry
->HighWord
.Bytes
.BaseHi
<< 24);
46 SegLimit
=ldt_entry
->LimitLow
|
47 (ldt_entry
->HighWord
.Bits
.LimitHi
<< 16);
49 if(ldt_entry
->HighWord
.Bits
.Type
& 0x4)
51 SegLimit
=(ldt_entry
->HighWord
.Bits
.Default_Big
) ? -1 : (USHORT
)-1;
53 } else if(ldt_entry
->HighWord
.Bits
.Granularity
)
55 SegLimit
=(SegLimit
<< 12) | 0xfff;
58 return ((Base
+ SegLimit
> (ULONG
) MmHighestUserAddress
) ||
59 (Base
> Base
+SegLimit
) ? FALSE
: TRUE
);
63 NtSetLdtEntries (ULONG Selector1
,
69 ULONG NewLdtSize
= sizeof(LDT_ENTRY
);
70 PUSHORT LdtDescriptor
;
74 if((Selector1
& ~0xffff) || (Selector2
& ~0xffff)) return STATUS_INVALID_LDT_DESCRIPTOR
;
79 if((Selector1
&& !PspIsDescriptorValid(&LdtEntry1
)) ||
80 (Selector2
&& !PspIsDescriptorValid(&LdtEntry2
))) return STATUS_INVALID_LDT_DESCRIPTOR
;
81 if(!(Selector1
|| Selector2
)) return STATUS_SUCCESS
;
83 NewLdtSize
+= (Selector1
>= Selector2
) ? Selector1
: Selector2
;
85 KeAcquireSpinLock(&LdtLock
, &oldIrql
);
87 LdtDescriptor
= (PUSHORT
) &KeGetCurrentProcess()->LdtDescriptor
[0];
88 LdtBase
= LdtDescriptor
[1] |
89 ((LdtDescriptor
[2] & 0xff) << 16) |
90 ((LdtDescriptor
[3] & ~0xff) << 16);
91 LdtLimit
= LdtDescriptor
[0] |
92 ((LdtDescriptor
[3] & 0xf) << 16);
94 if(LdtLimit
< (NewLdtSize
- 1))
96 /* allocate new ldt, copy old one there, set gdt ldt entry to new
97 values and load ldtr register and free old ldt */
99 ULONG NewLdtBase
= (ULONG
) ExAllocatePool(NonPagedPool
,
104 KeReleaseSpinLock(&LdtLock
, oldIrql
);
105 return STATUS_INSUFFICIENT_RESOURCES
;
110 memcpy((PVOID
) NewLdtBase
, (PVOID
) LdtBase
, LdtLimit
+1);
113 LdtDescriptor
[0] = (USHORT
)((--NewLdtSize
) & 0xffff);
114 LdtDescriptor
[1] = (USHORT
)(NewLdtBase
& 0xffff);
115 LdtDescriptor
[2] = (USHORT
)(((NewLdtBase
& 0xff0000) >> 16) | 0x8200);
116 LdtDescriptor
[3] = (USHORT
)(((NewLdtSize
& 0xf0000) >> 16) |
117 ((NewLdtBase
& 0xff000000) >> 16));
119 KeSetGdtSelector(LDT_SELECTOR
,
120 ((PULONG
) LdtDescriptor
)[0],
121 ((PULONG
) LdtDescriptor
)[1]);
123 #if defined(__GNUC__)
126 : "a" (LDT_SELECTOR
));
127 #elif defined(_MSC_VER)
128 __asm mov ax
, LDT_SELECTOR
131 #error Unknown compiler for inline assembler
136 ExFreePool((PVOID
) LdtBase
);
139 LdtBase
= NewLdtBase
;
144 memcpy((char*)LdtBase
+ Selector1
,
151 memcpy((char*)LdtBase
+ Selector2
,
156 KeReleaseSpinLock(&LdtLock
, oldIrql
);
157 return STATUS_SUCCESS
;
161 Ki386InitializeLdt(VOID
)
163 PUSHORT Gdt
= KeGetCurrentKPCR()->GDT
;
164 unsigned int base
, length
;
167 * Set up an a descriptor for the LDT
171 Gdt
[(LDT_SELECTOR
/ 2) + 0] = (length
& 0xFFFF);
172 Gdt
[(LDT_SELECTOR
/ 2) + 1] = (base
& 0xFFFF);
173 Gdt
[(LDT_SELECTOR
/ 2) + 2] = ((base
& 0xFF0000) >> 16) | 0x8200;
174 Gdt
[(LDT_SELECTOR
/ 2) + 3] = ((length
& 0xF0000) >> 16) |
175 ((base
& 0xFF000000) >> 16);