source: vendor/emx/current/src/dos/segments.asm

Last change on this file was 18, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 16.8 KB
Line 
1;
2; SEGMENTS.ASM -- Manage segments
3;
4; Copyright (c) 1991-1999 by Eberhard Mattes
5;
6; This file is part of emx.
7;
8; emx is free software; you can redistribute it and/or modify it
9; under the terms of the GNU General Public License as published by
10; the Free Software Foundation; either version 2, or (at your option)
11; any later version.
12;
13; emx is distributed in the hope that it will be useful,
14; but WITHOUT ANY WARRANTY; without even the implied warranty of
15; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16; GNU General Public License for more details.
17;
18; You should have received a copy of the GNU General Public License
19; along with emx; see the file COPYING. If not, write to
20; the Free Software Foundation, 59 Temple Place - Suite 330,
21; Boston, MA 02111-1307, USA.
22;
23; See emx.asm for a special exception.
24;
25
26__SEGMENTS = 1
27
28 INCLUDE EMX.INC
29 INCLUDE TABLES.INC
30 INCLUDE MISC.INC
31 INCLUDE PAGING.INC
32 INCLUDE SEGMENTS.INC
33 INCLUDE SIGNAL.INC ; Required by PROCESS.INC
34 INCLUDE PROCESS.INC
35
36 PUBLIC NEW_TSS, G_PHYS_BASE
37 PUBLIC CREATE_SEG, SEG_SIZE, SEG_BASE, SEG_ATTR, GET_BASE
38 PUBLIC NULL_SEG, GET_LIN, GET_DESC, SV_SEGMENT, ADD_PAGES
39 PUBLIC ACCESS_LOWMEM, MAP_PHYS
40 PUBLIC INIT_DESC, RM_SEG_BASE, RM_SEG_SIZE, INIT_TSS
41
42SV_DATA SEGMENT
43
44;
45; Base address of G_PHYS_SEL (see also G_PHYS_DESC)
46;
47G_PHYS_BASE DD 0
48;
49; New TSS (with I/O bitmap) active
50;
51NEW_TSS DB FALSE ; Initially not active
52
53SV_DATA ENDS
54
55
56SV_CODE SEGMENT
57
58 ASSUME CS:SV_CODE, DS:NOTHING
59
60
61;
62; Create a segment (make GDT/LDT entry)
63;
64; In: SI Pointer to GDT/LDT entry
65; AX Segment attributes (A_CODE32, A_DATA32, DPL_0, ..., DPL_3)
66; EBX Base address of segment
67; ECX Size of segment (limit+1)
68;
69 ASSUME DS:NOTHING
70
71CREATE_SEG PROC NEAR
72 CALL SEG_ATTR
73 CALL SEG_BASE
74 CALL SEG_SIZE
75 RET
76CREATE_SEG ENDP
77
78
79;
80; Set the type/attributes of a segment
81;
82; In: DS:SI Pointer to descriptor
83; AX Type / attributes (A_CODE32, A_DATA32, DPL_0, ..., DPL_3)
84;
85SEG_ATTR PROC NEAR
86 AND WORD PTR [SI+5], 0CF00H ; Clear all but G, B|D, limit
87 OR [SI+5], AX ; Set segment type/attributes
88 RET
89SEG_ATTR ENDP
90
91
92;
93; Set the base address of a segment
94;
95; In: DS:SI Pointer to GDT entry
96; EBX Base address of segment
97;
98 ASSUME SI:PTR DESCRIPTOR
99SEG_BASE PROC NEAR
100 PUSH EBX
101 MOV [SI].BASE_0_15, BX ; Base 0..15
102 SHR EBX, 16
103 MOV [SI].BASE_16_23, BL ; Base 16..23
104 MOV [SI].BASE_24_31, BH ; Base 24..31
105 POP EBX
106 RET
107 ASSUME SI:NOTHING
108SEG_BASE ENDP
109
110
111;
112; Set the size of a segment
113;
114; In: DS:SI Pointer to GDT entry (already contains access & other info)
115; ECX Size of segment (limit+1)
116;
117 ASSUME SI:PTR DESCRIPTOR
118SEG_SIZE PROC NEAR
119 PUSH ECX
120 AND [SI].GRAN, 70H ; Keep B|0|AVL, clear G|limit
121 CMP ECX, 1 SHL 20 ; Byte granular?
122 JA SHORT SS_BIG ; No -> page granular
123 DEC ECX ; ECX := limit (byte granular)
124 MOV [SI].LIMIT_0_15, CX ; Limit 0..15
125 SHR ECX, 16
126 OR [SI].GRAN, CL ; Limit 16..19
127 JMP SHORT SS_RET
128
129SS_BIG: ADD ECX, 0FFFH ; Round up
130 SHR ECX, 12 ; Convert to number of pages
131 DEC ECX ; ECX := limit (page granular)
132 MOV [SI].LIMIT_0_15, CX ; Limit 0..15
133 SHR ECX, 16
134 OR CL, 80H ; Set G
135 OR [SI].GRAN, CL ; Limit 16..19
136SS_RET: POP ECX
137 RET
138 ASSUME SI:NOTHING
139SEG_SIZE ENDP
140
141
142;
143; Get the base address of a segment
144;
145; In: DS:SI Pointer to GDT entry
146;
147; Out: EBX Base address of segment
148;
149 ASSUME SI:PTR DESCRIPTOR
150GET_BASE PROC NEAR
151 MOV BL, [SI].BASE_16_23 ; Base 16..23
152 MOV BH, [SI].BASE_24_31 ; Base 24..31
153 SHL EBX, 16
154 MOV BX, [SI].BASE_0_15 ; Base 0..15
155 RET
156 ASSUME SI:NOTHING
157GET_BASE ENDP
158
159;
160; Convert virtual address to linear address
161;
162; In: AX Selector
163; EBX Offset
164; LDTR Local descriptor table
165;
166; Out: EBX Linear address
167; CY Error
168;
169 ASSUME DS:SV_DATA
170GET_LIN PROC NEAR
171 PUSH EAX
172 PUSH ESI
173 .386P
174 SLDT SI
175 .386
176 CALL GET_DESC
177 MOV EAX, EBX
178 CALL GET_BASE
179 ADD EBX, EAX
180 CLC
181 POP ESI
182 POP EAX
183 RET
184GET_LIN ENDP
185
186;
187; Get LDT/GDT entry
188;
189; In: AX Selector
190; SI Local descriptor table (selector)
191;
192; Out: SI Pointer to table entry
193;
194 ASSUME DS:SV_DATA
195GET_DESC PROC NEAR
196 PUSH AX
197 TEST AX, 04H ; GDT?
198 JZ SHORT GDES_1 ; Yes ->
199 AND SI, NOT 07H
200 SUB SI, G_LDT_SEL
201 IMUL SI, LDT_ENTRIES
202 LEA SI, LDTS[SI]
203 JMP SHORT GDES_2
204GDES_1: LEA SI, GDT
205GDES_2: AND AX, NOT 07H
206 ADD SI, AX
207 POP AX
208 RET
209GET_DESC ENDP
210
211;
212; Create a null segment (make GDT/LDT entry)
213;
214; In: DS:SI Pointer to GDT/LDT entry
215;
216 ASSUME DS:NOTHING
217NULL_SEG PROC NEAR
218 MOV DWORD PTR [SI+0], 0
219 MOV DWORD PTR [SI+4], 0
220 RET
221NULL_SEG ENDP
222
223
224;
225; Create supervisor data segment (not swappable)
226;
227; In: ECX Size (bytes)
228; DS:SI Pointer to GDT entry
229;
230; Out: CY Out of memory
231;
232; Note: No physical memory is allocated for the pages, so the pages must
233; be present if accessed from within the page fault handler (to avoid
234; recursion)
235;
236 ASSUME DS:SV_DATA
237SV_SEGMENT PROC NEAR
238 PUSH EAX
239 PUSH EBX
240 PUSH ECX
241 MOV AL, PIDX_SV
242 CALL ALLOC_PAGES ; Get linear addresses
243 CALL INIT_PAGES ; Create page tables
244 JC SHORT SVS_RET ; Out of memory -> return
245 MOV EBX, PAGE_LOCKED ; Create locked pages
246 MOV EDX, PIDX_SV OR SRC_ZERO
247 CALL SET_PAGES
248 MOV EBX, EAX ; Linear address to EBX
249 POP ECX ; Number of bytes
250 PUSH ECX
251 MOV AX, A_DATA32 OR DPL_0 ; Supervisor data segment
252 CALL CREATE_SEG ; Create segment descriptor
253SVS_RET: POP ECX
254 POP EBX
255 POP EAX
256 RET
257SV_SEGMENT ENDP
258
259;
260; Allocate, initialize and switch to new TSS.
261;
262; If there isn't enough memory, NEW_TSS stays FALSE.
263;
264 ASSUME DS:SV_DATA
265INIT_TSS PROC NEAR
266;
267; Allocate memory
268;
269 MOV ECX, SIZE TSS_STRUC + 2001H
270 LEA SI, G_TMP1_DESC ; Use temporary descriptor
271 CALL SV_SEGMENT ; Create supervisor segment
272 JC SHORT IT_RET ; Out of memory -> done
273;
274; Copy initial TSS to new segment
275;
276 PUSH DS ; Save DS
277 MOV AX, G_TSS_MEM_SEL
278 MOV DS, AX
279 MOV AX, G_TMP1_SEL
280 MOV ES, AX
281 XOR SI, SI
282 XOR DI, DI
283 MOV CX, SIZE TSS_STRUC
284 REP MOVSB
285;
286; Initialize I/O bitmap (all 64K ports disabled)
287;
288 MOV AX, 0FFH
289 MOV CX, 2001H
290 REP STOSB
291 POP DS ; Restore DS
292;
293; Copy to G_TSS_MEM_SEL descriptor
294;
295 MOV_ES_DS ; ES := DS
296 LEA SI, G_TMP1_DESC
297 LEA DI, G_TSS_MEM_DESC
298 MOVSD
299 MOVSD
300;
301; Copy to G_TSS_SEL descriptor
302;
303 CLI ; Disable interrupts
304 LEA SI, G_TMP1_DESC
305 LEA DI, G_TSS_DESC
306 MOVSD
307 MOVSD
308 LEA SI, G_TSS_DESC
309 MOV AX, A_TSS ; Turn it into a TSS desciptor
310 CALL SEG_ATTR
311;
312; Switch to new TSS
313;
314 AND TSS_BUSY, NOT 2
315 MOV AX, G_TSS_SEL
316 .386P
317 LTR AX
318 .386
319 STI ; Enable interrupts
320 MOV NEW_TSS, NOT FALSE ; New TSS active
321IT_RET: RET
322INIT_TSS ENDP
323
324;
325; Add some pages of memory to a process. The pages will be added at the
326; end of the data segment, above the stack.
327;
328; In: DI Pointer to process table entry
329; ECX Number of pages
330;
331; Out: EAX Address in process space of the memory (or 0 on failure)
332;
333 ASSUME DS:SV_DATA
334ADD_PAGES PROC NEAR
335 ASSUME DI:PTR PROCESS
336 PUSH SI
337 MOV EAX, [DI].P_DSEG_SIZE
338 ADD EAX, 1000H ; One empty page
339 PUSH EAX ; Save the return value
340 SHL ECX, 12 ; Compute number of bytes
341 ADD EAX, ECX ; Adjust end address
342 JC SHORT AP_FAIL ; Overflow -> fail
343 CMP EAX, [DI].P_LIN_SIZE ; Beyond end of address space?
344 JA SHORT AP_FAIL ; Yes -> fail
345 MOV EDX, EAX ; New data segment size
346 POP EAX ; Address of new pages
347 PUSH EAX
348 PUSH EDX
349 ADD EAX, [DI].P_LINEAR ; Compute linear address
350 SHR ECX, 12 ; Number of pages
351 MOV EBX, PAGE_WRITE OR PAGE_USER
352 MOV EDX, SRC_NONE
353 TEST [DI].P_FLAGS, PF_DONT_ZERO
354 JNZ SHORT AP_1
355 MOV EDX, SRC_ZERO
356AP_1: MOV DL, [DI].P_PIDX
357 CALL SET_COMMIT ; Set PAGE_ALLOC bit
358 CALL SET_PAGES
359 POP EAX ; New data segment size
360 JC SHORT AP_FAIL
361 MOV [DI].P_DSEG_SIZE, EAX ; Update data segment size
362 MOV ECX, [DI].P_DSEG_SIZE
363 MOV SI, [DI].P_LDT_PTR
364 ADD SI, L_DATA_SEL AND NOT 07H
365 CALL SEG_SIZE
366 POP EAX
367 POP SI
368 RET
369
370AP_FAIL: POP EAX
371 POP SI
372 XOR EAX, EAX ; Return 0
373 RET
374 ASSUME DI:NOTHING
375ADD_PAGES ENDP
376
377
378;
379; Map pages into the address space of a process
380;
381; In: DI Pointer to process table entry
382; EBX Physical address
383; ECX Number of pages
384;
385; Out: EAX Adress in process space (0 if no space)
386;
387 ASSUME DS:SV_DATA
388 ASSUME DI:PTR PROCESS
389MAP_PHYS PROC NEAR
390 MOV EAX, [DI].P_DSEG_SIZE
391 ADD EAX, 1000H
392 PUSH EAX
393 MOV EDX, ECX
394 SHL EDX, 12
395 ADD EAX, EDX
396 JC SHORT MP_FAIL
397 CMP EAX, [DI].P_LIN_SIZE
398 JA SHORT MP_FAIL
399 MOV [DI].P_DSEG_SIZE, EAX
400 SUB EAX, EDX
401 ADD EAX, [DI].P_LINEAR
402 MOV DL, [DI].P_PIDX
403 TEST EBX, NOT 0FFFH ; Is the address = 0?
404 JNZ SHORT MP_MORE ; No -> continue
405 PUSH ECX
406 MOV ECX, 1 ; Set one page table entry
407 CALL SET_PAGES ; This is required because
408 POP ECX ; SET_PAGES doesn't increment
409 DEC ECX ; the address if it is 0
410 JZ SHORT MP_DONE
411 ADD EAX, 1000H
412 ADD EBX, 1000H
413MP_MORE: CALL SET_PAGES
414MP_DONE: MOV ECX, [DI].P_DSEG_SIZE
415 MOV SI, [DI].P_LDT_PTR
416 ADD SI, L_DATA_SEL AND NOT 07H
417 CALL SEG_SIZE
418 POP EAX
419 RET
420
421MP_FAIL: POP EAX
422 XOR EAX, EAX
423 RET
424 ASSUME DI:NOTHING
425MAP_PHYS ENDP
426
427
428;
429; Convert real-mode pointer to protected-mode pointer
430;
431; In: EAX Real-mode Segment:Offset
432;
433; Out: EBX Offset into G_LOWMEM_SEL segment
434; EAX Modified
435;
436ACCESS_LOWMEM PROC NEAR
437 ROL EAX, 16 ; EAX = offset:segment
438 MOVZX EBX, AX ; EBX = segment
439 SHL EBX, 4 ; EBX = base address of segment
440 SHR EAX, 16 ; EAX = offset
441 ADD EBX, EAX
442 RET
443ACCESS_LOWMEM ENDP
444
445SV_CODE ENDS
446
447
448
449INIT_CODE SEGMENT
450
451 ASSUME CS:INIT_CODE, DS:NOTHING
452
453;
454; Convert the base field of a GDT entry. It already contains the
455; offset into the real-mode segment given in AX.
456;
457; In: AX Real-mode segment
458; DI Pointer to descriptor table entry (SV_DATA)
459;
460 ASSUME DS:SV_DATA
461 ASSUME DI:PTR DESCRIPTOR
462INIT_DESC PROC NEAR
463 PUSH EAX
464 PUSH EDX
465 MOVZX EAX, AX
466 SHL EAX, 4
467 MOVZX EDX, [DI].BASE_0_15 ; Get real-mode offset
468 ADD EAX, EDX
469 CALL RM_SEG_BASE ; Set base address
470 POP EDX
471 POP EAX
472 RET
473 ASSUME DI:NOTHING
474INIT_DESC ENDP
475
476
477
478;
479; Set the base address of a segment (real-mode version)
480;
481; In: DS:DI Pointer to GDT entry
482; EAX Base address of segment
483;
484 ASSUME DS:SV_DATA
485 ASSUME DI:PTR DESCRIPTOR
486RM_SEG_BASE PROC NEAR
487 PUSH EAX
488 MOV [DI].BASE_0_15, AX ; Base 0..15
489 SHR EAX, 16
490 MOV [DI].BASE_16_23, AL ; Base 16..23
491 MOV [DI].BASE_24_31, AH ; Base 24..31
492 POP EAX
493 RET
494 ASSUME DI:NOTHING
495RM_SEG_BASE ENDP
496
497
498;
499; Set the size of a segment (real-mode version)
500;
501; In: DS:DI Pointer to GDT entry
502; ECX Size of segment (limit+1)
503;
504 ASSUME DS:SV_DATA
505 ASSUME DI:PTR DESCRIPTOR
506RM_SEG_SIZE PROC NEAR
507 PUSH ECX
508 AND [DI].GRAN, 70H ; Keep B|0|AVL, clear G|limit
509 CMP ECX, 1 SHL 20 ; Byte granular?
510 JA SHORT RSS_BIG ; No -> page granular
511 DEC ECX ; ECX := limit (byte granular)
512 MOV [DI].LIMIT_0_15, CX ; Limit 0..15
513 SHR ECX, 16
514 OR [DI].GRAN, CL ; Limit 16..19
515 JMP SHORT RSS_RET
516
517RSS_BIG: ADD ECX, 0FFFH ; Round up
518 SHR ECX, 12 ; Convert to number of pages
519 DEC ECX ; ECX := limit (page granular)
520 MOV [DI].LIMIT_0_15, CX ; Limit 0..15
521 SHR ECX, 16
522 OR CL, 80H ; Set G
523 OR [DI].GRAN, CL ; Limit 16..19
524RSS_RET: POP ECX
525 RET
526 ASSUME DI:NOTHING
527RM_SEG_SIZE ENDP
528
529
530INIT_CODE ENDS
531
532 END
Note: See TracBrowser for help on using the repository browser.