Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

661 lines
16 KiB

  1. include kernel.inc
  2. include protect.inc
  3. .list
  4. .386p
  5. DataBegin
  6. externB WinFlags
  7. externW hGlobalHeap
  8. externW pGlobalHeap
  9. externW ArenaSel
  10. externD hBmDPMI
  11. externD FreeArenaList
  12. externD FreeArenaCount
  13. externD SelTableStart
  14. externW SelTableLen
  15. externW InitialPages
  16. DataEnd
  17. sBegin INITCODE
  18. assumes CS,CODE
  19. externNP get_physical_address
  20. externNP set_physical_address
  21. externNP set_selector_address32
  22. externNP set_selector_limit32
  23. externNP alloc_arena_header
  24. externNP AssociateSelector32
  25. externNP alloc_data_sel
  26. externNP alloc_data_sel32
  27. externNP GrowHeap
  28. externNP DPMIProc
  29. externFP greserve
  30. GA_ALIGN_BYTES = (((GA_ALIGN+1) SHL 4) - 1)
  31. GA_MASK_BYTES = NOT GA_ALIGN_BYTES
  32. ;-----------------------------------------------------------------------;
  33. ; get_selector_address32 ;
  34. ; ;
  35. ; Function to translate return of get_physical_address (DX:AX) into EAX ;
  36. ; ;
  37. ;-----------------------------------------------------------------------;
  38. cProc get_selector_address32,<PUBLIC,NEAR>
  39. parmW selector
  40. cBegin
  41. push dx
  42. cCall get_physical_address,<selector>
  43. shl eax, 16
  44. mov ax, dx
  45. ror eax, 16
  46. pop dx
  47. cEnd
  48. ;-----------------------------------------------------------------------;
  49. ; GlobalInit ;
  50. ; ;
  51. ; Procedure to initialize the global heap. Called with the starting ;
  52. ; and ending paragraph addresses. ;
  53. ; ;
  54. ; Arguments: ;
  55. ; parmW hdelta = size (.25k) of master object ;
  56. ; parmW palloc = block to mark allocated ;
  57. ; = (ROM) Size of DS == allocated block ;
  58. ; parmW pstart = first available address ;
  59. ; parmW pend = last available address ;
  60. ; ;
  61. ; Returns: ;
  62. ; AX = handle for allocated block ;
  63. ; ;
  64. ; Error Returns: ;
  65. ; ;
  66. ; Alters: ;
  67. ; ES ;
  68. ; Calls: ;
  69. ; ginit ;
  70. ; hthread ;
  71. ; ghalloc ;
  72. ; History: ;
  73. ; ;
  74. ; Sat Jun 20, 1987 05:55:35p -by- David N. Weise [davidw] ;
  75. ; Making real EMS work with the fast boot version. ;
  76. ; ;
  77. ; Sun Mar 15, 1987 06:38:04p -by- David N. Weise [davidw] ;
  78. ; Added support for the linked free list long ago. ;
  79. ; ;
  80. ; Wed Feb 18, 1987 08:09:18p -by- David N. Weise [davidw] ;
  81. ; Added the initialization of the gi_alt entries. ;
  82. ; ;
  83. ; Mon Sep 08, 1986 07:53:41p -by- David N. Weise [davidw ;
  84. ; Changed the return values so that this can be called from other than ;
  85. ; initialization code. ;
  86. ;-----------------------------------------------------------------------;
  87. cProc GlobalInit,<PUBLIC,NEAR>,<ds,si,di>
  88. parmW hdelta
  89. parmW palloc
  90. parmW pstart
  91. parmW pend
  92. localW emspalloc
  93. localW hInitMem
  94. localD allocated_arena
  95. localW next_block
  96. localW free_hi
  97. localW free_lo
  98. cBegin
  99. mov ax,palloc ; AX = block to mark allocated
  100. mov bx,pstart ; BX = first available address
  101. mov cx,hdelta ; CX = size (.25k) of master object
  102. mov dx,pend ; DX = last available address
  103. call ginit
  104. jc FailGlobalInit
  105. SetKernelDS es
  106. mov allocated_arena,eax
  107. xor edi,edi ; Initialize master object
  108. mov [di].phi_first,ebx ; Fill in pointers to first and
  109. mov [di].phi_last,edx ; last blocks
  110. mov [di].hi_count,4 ; 4 arena entries
  111. or eax,eax
  112. jnz short allocated_block
  113. mov [di].hi_count,3 ; 3 arena entries
  114. allocated_block:
  115. mov [di].gi_lruchain,edi ; Nothing in LRU list so far
  116. mov [di].gi_lrucount,di
  117. mov [di].gi_lrulock,di ; ...and not locked
  118. mov [di].gi_reserve,edi ; No discardable code reserve area yet
  119. push eax
  120. mov eax, ds:[edx.pga_address]
  121. mov word ptr [di].gi_disfence,ax ; gi_disfence = hi_last
  122. shr eax, 16
  123. mov word ptr [di].gi_disfence_hi,ax
  124. pop eax
  125. mov [di].gi_alt_first,-1 ; Fill in pointers to first and
  126. mov [di].gi_alt_last,-1 ; last blocks, the -1 is necessary!!
  127. mov [di].gi_alt_count,di ; # of arena entries
  128. mov [di].gi_alt_lruchain,di
  129. mov [di].gi_alt_lrucount,di ; MUST be 0!
  130. mov [di].gi_alt_free_count,di
  131. mov [di].gi_alt_reserve,di
  132. mov [di].gi_alt_disfence,di
  133. mov [di].gi_alt_pPhantom,-1 ; MUST be -1!
  134. mov ax, ds:[esi.pga_handle] ; Pick up master objects selector
  135. mov hGlobalHeap,ax
  136. mov ds:[esi].pga_count,0
  137. mov ds:[esi].pga_selcount,1
  138. if ROM
  139. mov esi,ds:[ebx].pga_next ; in ROM, alloced == first.next
  140. else
  141. mov esi,ds:[edx].pga_prev ; Point to allocated object before
  142. endif
  143. mov bx,ds:[esi.pga_handle]
  144. StoH bx ; It is moveable
  145. mov ds:[esi].pga_handle,bx
  146. mov hInitMem,bx
  147. if ROM
  148. mov ds:[esi].pga_count,1 ; LOCKED in ROM
  149. else
  150. mov ds:[esi].pga_count,0
  151. endif
  152. no_allocated_object:
  153. ; initialize free list
  154. mov [di].gi_free_count,1
  155. mov eax,[di].phi_first
  156. mov ecx,[di].phi_last
  157. if ROM
  158. mov ebx,ds:[ecx].pga_prev
  159. else
  160. mov ebx,ds:[eax].pga_next
  161. endif
  162. mov ds:[eax].pga_freeprev,-1 ; Fill in first sentinal
  163. mov ds:[eax].pga_freenext,ebx
  164. mov ds:[ecx].pga_freeprev,ebx ; Fill in last sentinal
  165. mov ds:[ecx].pga_freenext,-1
  166. mov ds:[ebx].pga_freeprev,eax ; Link in free block
  167. mov ds:[ebx].pga_freenext,ecx
  168. pushad
  169. SetKernelDS fs
  170. mov edx, 030000h ; Insist on enough for fence
  171. call GrowHeap
  172. jc short Failed_GrowHeap ;garage sale machine,tough luck!
  173. ; 192k (3 segs) fixed greserve
  174. mov ax, 1000h ; fence it all off. (in paras)
  175. push fs
  176. call greserve ; greserve will triple the no.
  177. pop fs
  178. or ax, ax
  179. stc ; assume failure
  180. jz short Failed_GrowHeap
  181. ifdef WOW
  182. clc
  183. ; WOW isn't greedy and doesn't have gcommit_block
  184. else
  185. mov esi, ds:[edi].phi_last ; sentinel
  186. mov esi, ds:[esi].pga_prev ; not_there
  187. mov esi, ds:[esi].pga_prev ; free blk
  188. call gcommit_block ; commit it all
  189. jc short Failed_GrowHeap ; to guarantee stable system
  190. ; Let's start with 20MB reserve and allocate more as reqd.
  191. mov edx, 20*1024*1024 ; Let's get greedy
  192. call GrowHeap
  193. clc ; we don't care about this fail
  194. endif
  195. Failed_GrowHeap:
  196. UnSetKernelDS fs
  197. popad
  198. jc short FailGlobalInit
  199. mov ax,hInitMem
  200. clc
  201. FailGlobalInit:
  202. cEnd
  203. ;-----------------------------------------------------------------------;
  204. ; ginit ;
  205. ; ;
  206. ; Procedure to initialize the global heap. ;
  207. ; ;
  208. ; The global heap looks as follows after this procedure returns: ;
  209. ; ;
  210. ; BX - first object in arena, alway busy, zero length. ;
  211. ; - free object ;
  212. ; AX - allocated object ;
  213. ; DS - master object ;
  214. ; DX - last object in arena, alway busy, zero length. ;
  215. ; ;
  216. ; ;
  217. ; Arguments: ;
  218. ; AX = address of block to mark allocated. May be zero. ;
  219. ; = (ROM) length of allocated block (which is DS) ;
  220. ; BX = address of first paragraph in arena ;
  221. ; DX = address of last paragraph in arena ;
  222. ; CX = initial size of master object, in bytes ;
  223. ; ;
  224. ; Returns: ;
  225. ; AX = aligned address of block marked allocated. ;
  226. ; BX = aligned address of first object in arena ;
  227. ; CX = size of master object, in bytes ;
  228. ; DX = aligned address of last object in arena ;
  229. ; DS = aligned address of master object ;
  230. ; ;
  231. ; Registers Preserved: ;
  232. ; ;
  233. ; Registers Destroyed: ;
  234. ; DI,SI,ES ;
  235. ; Calls: ;
  236. ; nothing ;
  237. ; History: ;
  238. ; ;
  239. ; Thu Sep 11, 1986 04:22:02p -by- David N. Weise [davidw] ;
  240. ; Commented it, made it handle the case of no allocated block correctly.;
  241. ;-----------------------------------------------------------------------;
  242. assumes ds, nothing
  243. assumes es, nothing
  244. cProc ginit,<PUBLIC,NEAR>
  245. localD size_free
  246. localD size_allocated
  247. localD size_master
  248. localD allocated_arena
  249. localW allocated_sel
  250. localD BurgerMaster_arena
  251. localW BurgerMaster_sel
  252. localD new_last_arena
  253. cBegin
  254. ; ESI = the first block address (sentinel, always busy)
  255. SetKernelDS es
  256. push ax
  257. cCall get_selector_address32,<bx> ; Start of our memory
  258. add eax, GA_ALIGN_BYTES ; Align our start
  259. and al, GA_MASK_BYTES
  260. push eax ; Save the start address
  261. cCall set_selector_address32,<bx,eax> ; This will be our arena list
  262. mov ArenaSel, bx
  263. mov BurgerMaster_sel, bx
  264. mov si, bx
  265. push bx
  266. push di
  267. xor bx, bx ; # physical pages available
  268. sub sp, 30h
  269. mov di, sp
  270. push es
  271. smov es, ss
  272. DPMICALL 0500h
  273. pop es
  274. mov eax, 16*1024 ; Size of selector table
  275. jc short default_sel_table
  276. mov bx, word ptr ss:[di][10h]
  277. cmp bx, 256
  278. jb short default_sel_table
  279. ;;;mov eax, 31*1024
  280. mov eax, 32*1024
  281. default_sel_table:
  282. mov [InitialPages], bx
  283. ; For WOW we assume 386 Kernel is running on paging System
  284. ; So always set WF1_PAGING
  285. ifndef WOW
  286. mov ecx, ss:[di][20h] ; Paging file size
  287. inc ecx
  288. cmp ecx, 1 ; 0 or -1?
  289. jbe short @F
  290. endif
  291. or byte ptr WinFlags[1], WF1_PAGING
  292. @@:
  293. mov ecx, ss:[di][0]
  294. shr ecx, 7 ; Bytes reserved for arenas
  295. add sp, 30h
  296. pop di
  297. pop bx
  298. add ecx, GA_ALIGN_BYTES ; Align length of arena table
  299. and cl, GA_MASK_BYTES
  300. add eax, GA_ALIGN_BYTES ; Align length of selector table
  301. and al, GA_MASK_BYTES
  302. mov SelTableLen, ax
  303. cmp ecx, DEFAULT_ARENA_SIZE ; Number of bytes of arenas
  304. jae short @F
  305. mov ecx, DEFAULT_ARENA_SIZE
  306. @@:
  307. mov ebx, Size GlobalInfo+GA_ALIGN_BYTES
  308. and bl, GA_MASK_BYTES ; EBX start of arenas
  309. mov size_master, ebx
  310. add ecx, ebx
  311. mov SelTableStart, ecx
  312. add eax, ecx ; EAX total length of segment
  313. push ecx
  314. push ebx
  315. push eax
  316. push si
  317. mov cx, ax ; Make BX:CX required
  318. mov ebx, eax ; length of Burgermaster
  319. shr ebx, 16
  320. push bx ; Save length
  321. push cx
  322. DPMICALL 0501h
  323. mov hBmDPMI[0], di ; Save DPMI handle
  324. mov hBmDPMI[2], si
  325. pop di ; SI:DI now length
  326. pop si
  327. jc Failginit
  328. if 0
  329. mov di, 4096 ; Lock first page
  330. xor si, si
  331. DPMICALL 0600h ; Now page lock it
  332. push bx
  333. push cx
  334. add cx, word ptr SelTableStart
  335. adc bx, 0
  336. and cx, not 4095
  337. DPMICALL 0600h
  338. pop cx
  339. pop bx
  340. endif
  341. shl ebx, 16
  342. mov bx, cx ; Address in EBX
  343. pop si
  344. pop eax
  345. cCall set_selector_address32,<si,ebx>
  346. mov edi, ebx
  347. ;;; cCall set_selector_limit32, <si,eax>
  348. push eax
  349. push dx
  350. dec eax
  351. mov ecx, eax ; Limit in CX:DX
  352. shr ecx, 16
  353. mov dx, ax
  354. test cx,0fff0h ; bits 20-31 set?
  355. jz @F ; No.
  356. or dx,0fffh ; Yes, page align limit.
  357. @@:
  358. mov bx, si ; Selector in BX
  359. DPMICALL 8
  360. pop dx
  361. pop eax
  362. pop ebx
  363. pop ecx
  364. jc Failginit
  365. mov ds, si
  366. sub ecx, ebx ; Subtract out BurgerMaster
  367. cCall InitialiseArenas,<ebx,ecx>
  368. mov ecx, eax
  369. pop esi ; Sentinel address
  370. cCall alloc_arena_header,<esi> ; Sentinel
  371. mov esi, eax
  372. cCall alloc_arena_header,<edi> ; BurgerMaster
  373. mov BurgerMaster_arena, eax
  374. mov ds:[eax].pga_handle, ds ; Save selector in handle field
  375. mov ds:[eax].pga_size, ecx
  376. push edi
  377. push ecx
  378. movzx ecx, SelTableLen
  379. mov edi, SelTableStart
  380. push es
  381. smov es, ds ; Zero this area
  382. UnSetKernelDS es
  383. shr ecx, 2
  384. xor eax, eax
  385. rep stos dword ptr es:[edi]
  386. pop es
  387. ReSetKernelDS es
  388. pop ecx
  389. pop edi
  390. cCall AssociateSelector32,<ds,BurgerMaster_Arena> ; Set back link
  391. ; EDI = the Free block address (initial free block)
  392. ife ROM
  393. mov eax, ds:[esi].pga_address
  394. ;;; add eax, ecx
  395. cCall alloc_arena_header,<eax>
  396. mov edi, eax ; Free block arena in EDI
  397. movzx eax, dx ; Get linear address
  398. shl eax, 4
  399. else
  400. cCall get_selector_address32, <dx>
  401. endif
  402. ; EDX = the last block address (sentinel, always busy)
  403. and al, GA_MASK_BYTES
  404. push eax
  405. cCall alloc_arena_header,<eax>
  406. mov new_last_arena, eax ; Save it away
  407. pop ebx
  408. if ROM
  409. ; in ROM, the alloced segment is the data segment, and we are
  410. ; passed the length, not the address
  411. ;
  412. ; the length (a word) is on the stack from that very first push way
  413. ; up there, and we want the base in eax and the length in ebx
  414. ;
  415. CheckKernelDS ES
  416. cCall get_selector_address32, <es>
  417. and al, GA_MASK_BYTES
  418. xor ebx, ebx ; clear hi word of length
  419. pop bx
  420. add ebx, GA_ALIGN_BYTES
  421. and bl, GA_MASK_BYTES
  422. cCall set_selector_limit32, <es, ebx>
  423. else
  424. pop ax ; Allocated Block
  425. cCall get_selector_address32, <ax>
  426. and al, GA_MASK_BYTES ; "Align" it
  427. sub ebx, eax ; Length in bytes
  428. endif
  429. ife ROM
  430. push eax
  431. endif
  432. push eax
  433. cCall alloc_arena_header, <eax>
  434. mov ds:[eax].pga_size, ebx ; Record size
  435. mov allocated_arena, eax
  436. mov ebx, eax
  437. pop eax
  438. if ROM
  439. CheckKernelDS ES
  440. mov allocated_sel, es
  441. mov ds:[ebx.pga_handle], es
  442. cCall AssociateSelector32,<es, ebx>
  443. else
  444. cCall alloc_data_sel32, <eax, ds:[ebx].pga_size>
  445. mov allocated_sel, ax
  446. mov ds:[ebx.pga_handle], ax ; Save selector
  447. cCall AssociateSelector32,<ax,ebx> ; Set back link
  448. endif
  449. if ROM
  450. ; now deal with the free one
  451. mov eax, ds:[ebx].pga_address
  452. add eax, ds:[ebx].pga_size
  453. add eax, GA_ALIGN_BYTES
  454. and al, GA_MASK_BYTES
  455. cCall alloc_arena_header, <eax>
  456. mov edi, eax
  457. cCall get_selector_address32, <dx>
  458. mov ebx, eax
  459. else
  460. pop ebx
  461. endif
  462. sub ebx, ds:[edi].pga_address ; Length in bytes
  463. mov ds:[edi].pga_size, ebx
  464. mov eax, allocated_arena
  465. mov ecx, BurgerMaster_arena
  466. mov edx, new_last_arena
  467. ; Fill in first block
  468. xor ebx, ebx
  469. mov ds:[esi].pga_sig,GA_SIGNATURE
  470. mov ds:[esi].pga_size,ebx
  471. mov ds:[esi].pga_owner,-1
  472. mov ds:[esi].pga_flags,bx
  473. mov ds:[esi].pga_prev,esi ; first.prev = self
  474. if ROM
  475. mov ds:[esi].pga_next,eax ; first.next = alloced (ds)
  476. else
  477. mov ds:[esi].pga_next,edi ; first.next = free
  478. endif
  479. mov ds:[esi].pga_handle,bx
  480. mov ds:[esi].pga_lrunext,ebx
  481. mov ds:[esi].pga_lruprev,ebx
  482. ; Fill in the last block (sentinel block)
  483. mov ds:[edx].pga_sig,GA_ENDSIG
  484. mov ds:[edx].pga_size,ebx
  485. mov ds:[edx].pga_owner,-1 ; Always allocated
  486. mov ds:[edx].pga_next,edx ; last.next = self
  487. if ROM
  488. mov ds:[edx].pga_prev,edi ; last.prev = free
  489. else
  490. mov ds:[edx].pga_prev,eax ; last.prev = alloced
  491. endif
  492. mov ds:[edx].pga_flags,bx
  493. mov ds:[edx].pga_handle, bx
  494. mov ds:[edx].pga_lrunext,ebx
  495. mov ds:[edx].pga_lruprev,ebx
  496. ; Fill in the master object
  497. mov ds:[ecx].pga_next,ecx
  498. mov ds:[ecx].pga_prev,ecx
  499. mov ds:[ecx].pga_sig,GA_SIGNATURE
  500. mov ds:[ecx].pga_owner,-3
  501. mov ds:[ecx].pga_flags,bx
  502. mov ds:[ecx].pga_lruprev,ebx
  503. mov ds:[ecx].pga_lrunext,ebx
  504. ; Fill in the allocated block
  505. if ROM
  506. mov ds:[eax].pga_next,edi ; next = free
  507. mov ds:[eax].pga_prev,esi ; prev = first
  508. else
  509. mov ds:[eax].pga_next,edx ; next object is Sentinel
  510. mov ds:[eax].pga_prev,edi ; Previous object is second block
  511. endif
  512. mov ds:[eax].pga_sig,GA_SIGNATURE
  513. mov ds:[eax].pga_owner,-1
  514. mov ds:[eax].pga_flags,bx
  515. mov ds:[eax].pga_lruprev,ebx
  516. mov ds:[eax].pga_lrunext,ebx
  517. ; Fill in free block
  518. mov ds:[edi].pga_sig,GA_SIGNATURE
  519. mov ds:[edi].pga_owner,bx ; This is a free block
  520. mov ds:[edi].pga_flags,bx
  521. if ROM
  522. mov ds:[edi].pga_next,edx ; next = last
  523. mov ds:[edi].pga_prev,eax ; prev = alloced
  524. else
  525. mov ds:[edi].pga_next,eax ; Next obj allocated block
  526. mov ds:[edi].pga_prev,esi
  527. endif
  528. mov ds:[edi].pga_handle,bx
  529. mov ds:[edi].pga_lruprev,ebx
  530. mov ds:[edi].pga_lrunext,ebx
  531. ; Initialize master object
  532. mov ecx, size_master
  533. mov dx,BurgerMaster_sel
  534. shr ecx, 1
  535. push ecx ; save size in words
  536. mov pGlobalHeap,dx
  537. mov es,dx
  538. UnSetKernelDS es
  539. xor eax,eax
  540. xor di,di ; Init master object to zero
  541. shr ecx, 1
  542. rep stosd
  543. mov ds,dx ; Switch to master object as our DS
  544. pop ecx
  545. shl ecx,1 ; ECX = size of master object in bytes
  546. mov eax, allocated_arena ; EAX = address of allocated block
  547. mov edx, new_last_arena ; EDX = address of last block
  548. mov ebx, esi ; EBX = address of first block
  549. mov esi, BurgerMaster_arena ; ESI = arena of BurgerMaster
  550. clc
  551. Failginit:
  552. cEnd
  553. assumes ds, nothing
  554. assumes es, nothing
  555. cProc InitialiseArenas,<PUBLIC,NEAR>
  556. parmD StartOffset
  557. parmD BytesAllocated
  558. cBegin
  559. push ecx
  560. push esi
  561. push edi
  562. CheckKernelDS es
  563. ReSetKernelDS es
  564. mov esi, StartOffset
  565. mov ecx, BytesAllocated
  566. add ecx, esi
  567. mov FreeArenaList, esi ; Point to list
  568. lea edi, [esi+size GlobalArena32]
  569. IA_loop:
  570. cmp edi, ecx
  571. jae short IA_done
  572. mov [esi.pga_next], edi
  573. add esi, size GlobalArena32
  574. add edi, size GlobalArena32
  575. inc FreeArenaCount
  576. jmps IA_loop
  577. IA_done:
  578. mov ds:[esi.pga_next], -1 ; Terminate list
  579. UnSetKernelDS es
  580. pop edi
  581. pop esi
  582. pop ecx
  583. cEnd
  584. sEnd INITCODE
  585. end