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 *****************************************************************/
24 extern VOID
KeSetGdtSelector(ULONG Entry
, ULONG Value1
, ULONG Value2
);
26 BOOL
PspIsDescriptorValid(PLDT_ENTRY ldt_entry
)
30 Allow invalid descriptors.
32 if(!ldt_entry
->HighWord
.Bits
.Type
&&
33 !ldt_entry
->HighWord
.Bits
.Dpl
)
36 /* eliminate system descriptors and code segments other than
37 execute and execute/read and DPL<3 descriptors */
38 if(!(ldt_entry
->HighWord
.Bits
.Type
& 0x10) ||
39 (ldt_entry
->HighWord
.Bits
.Type
& 0x8 &&
40 ldt_entry
->HighWord
.Bits
.Type
& 0x4) ||
41 ldt_entry
->HighWord
.Bits
.Dpl
!= 3 ||
42 ldt_entry
->HighWord
.Bits
.Reserved_0
) return FALSE
;
44 if(!ldt_entry
->HighWord
.Bits
.Pres
) return TRUE
;
46 Base
=ldt_entry
->BaseLow
| (ldt_entry
->HighWord
.Bytes
.BaseMid
<< 16) |
47 (ldt_entry
->HighWord
.Bytes
.BaseHi
<< 24);
49 SegLimit
=ldt_entry
->LimitLow
|
50 (ldt_entry
->HighWord
.Bits
.LimitHi
<< 16);
52 if(ldt_entry
->HighWord
.Bits
.Type
& 0x4)
54 SegLimit
=(ldt_entry
->HighWord
.Bits
.Default_Big
) ? -1 : (USHORT
)-1;
56 } else if(ldt_entry
->HighWord
.Bits
.Granularity
)
58 SegLimit
=(SegLimit
<< 12) | 0xfff;
61 return ((Base
+ SegLimit
> (ULONG
) MmHighestUserAddress
) ||
62 (Base
> Base
+SegLimit
) ? FALSE
: TRUE
);
66 NtSetLdtEntries (ULONG Selector1
,
72 ULONG NewLdtSize
= sizeof(LDT_ENTRY
);
73 PUSHORT LdtDescriptor
;
77 if((Selector1
& ~0xffff) || (Selector2
& ~0xffff)) return STATUS_INVALID_LDT_DESCRIPTOR
;
82 if((Selector1
&& !PspIsDescriptorValid(&LdtEntry1
)) ||
83 (Selector2
&& !PspIsDescriptorValid(&LdtEntry2
))) return STATUS_INVALID_LDT_DESCRIPTOR
;
84 if(!(Selector1
|| Selector2
)) return STATUS_SUCCESS
;
86 NewLdtSize
+= (Selector1
>= Selector2
) ? Selector1
: Selector2
;
88 KeAcquireSpinLock(&LdtLock
, &oldIrql
);
90 LdtDescriptor
= (PUSHORT
) &KeGetCurrentProcess()->LdtDescriptor
;
91 LdtBase
= LdtDescriptor
[1] |
92 ((LdtDescriptor
[2] & 0xff) << 16) |
93 ((LdtDescriptor
[3] & ~0xff) << 16);
94 LdtLimit
= LdtDescriptor
[0] |
95 ((LdtDescriptor
[3] & 0xf) << 16);
97 if(LdtLimit
< (NewLdtSize
- 1))
99 /* allocate new ldt, copy old one there, set gdt ldt entry to new
100 values and load ldtr register and free old ldt */
102 ULONG NewLdtBase
= (ULONG
) ExAllocatePool(NonPagedPool
,
107 KeReleaseSpinLock(&LdtLock
, oldIrql
);
108 return STATUS_INSUFFICIENT_RESOURCES
;
113 memcpy((PVOID
) NewLdtBase
, (PVOID
) LdtBase
, LdtLimit
+1);
116 LdtDescriptor
[0] = (USHORT
)((--NewLdtSize
) & 0xffff);
117 LdtDescriptor
[1] = (USHORT
)(NewLdtBase
& 0xffff);
118 LdtDescriptor
[2] = (USHORT
)(((NewLdtBase
& 0xff0000) >> 16) | 0x8200);
119 LdtDescriptor
[3] = (USHORT
)(((NewLdtSize
& 0xf0000) >> 16) |
120 ((NewLdtBase
& 0xff000000) >> 16));
122 KeSetGdtSelector(KGDT_LDT
,
123 ((PULONG
) LdtDescriptor
)[0],
124 ((PULONG
) LdtDescriptor
)[1]);
126 #if defined(__GNUC__)
130 #elif defined(_MSC_VER)
131 __asm mov ax
, KGDT_LDT
134 #error Unknown compiler for inline assembler
139 ExFreePool((PVOID
) LdtBase
);
142 LdtBase
= NewLdtBase
;
147 memcpy((char*)LdtBase
+ Selector1
,
154 memcpy((char*)LdtBase
+ Selector2
,
159 KeReleaseSpinLock(&LdtLock
, oldIrql
);
160 return STATUS_SUCCESS
;
164 Ki386InitializeLdt(VOID
)
166 PUSHORT Gdt
= KeGetCurrentKPCR()->GDT
;
167 unsigned int base
, length
;
170 * Set up an a descriptor for the LDT
174 Gdt
[(KGDT_LDT
/ 2) + 0] = (length
& 0xFFFF);
175 Gdt
[(KGDT_LDT
/ 2) + 1] = (base
& 0xFFFF);
176 Gdt
[(KGDT_LDT
/ 2) + 2] = ((base
& 0xFF0000) >> 16) | 0x8200;
177 Gdt
[(KGDT_LDT
/ 2) + 3] = ((length
& 0xF0000) >> 16) |
178 ((base
& 0xFF000000) >> 16);