wok view linld/stuff/src/VCPI.ASM @ rev 22176

linld: spare up to 30k more for zImage
author Pascal Bellard <pascal.bellard@slitaz.org>
date Fri Nov 08 20:55:40 2019 +0100 (2019-11-08)
parents fcb1de9af8f7
children a946c1651082
line source
1 ;***************************************************************
2 ;****** This file is distributed under GPL
3 ;***************************************************************
4 ;VDPI init:
5 ;Call char* prepare_vcpi(void *pagebuf) first to
6 ;initialize paging tables needed for vm86.
7 ;pagebuf needs to be 8k+4 bytes. Returns ptr to 1st unused byte.
8 ;Then call int get_vcpi_interface(). Returns 1 if ok, 0 if bad.
9 ;
10 ;VCPI use:
11 ;u32* malloc_vcpi(u32 size) - source in HIMEM.CPP
12 ; Returns ptr to mallocated zero-terminated list of 4k page addrs
13 ; Addresses are sorted in ascending order
14 ; Never fails (will die if not enough mem)
15 ;void read2vcpi(int fd, u32* vp, u32 size,
16 ;void* xfer_buf, u16 xfer_size) - source in HIMEM.CPP
17 ; Reads opened fd data into malloc_vcpi'ed memory
18 ; Dies if file isn't exactly 'size' bytes long
19 ; Needs intermediate buffer of exactly Nx4k bytes
20 ;void memcpy_vcpi(u32 dstofs,u16 srcseg,u32 srcofs)
21 ; copies 4k from conventional memory to VCPI
22 ;void _vm2rm()
23 ; switches you from vm86 to plain real mode
26 ideal
27 %PAGESIZE 1000
28 %crefref
29 %noincl
30 %nomacs
31 p386
33 ;****** Stuff for declaring descriptors
34 struc descr
35 limit dw ?
36 base0 dw ?
37 base16 db ?
38 type db ?
39 limit16 db ?
40 base24 db ?
41 ends descr
42 macro descriptor name,typ,plevel,present,limit,gran,base
43 ;;name descr <limit and 0ffffh,base and 0ffffh,low (base shr 16),typ or plevel or present,(limit shr 16) or gran,high (base shr 16)>
44 name descr <limit and 0ffffh,base ,0 ,typ or plevel or present,(limit shr 16) or gran,0 >
45 endm
46 ; decriptor types (bit0..4 of descr.type )
47 tss386_avail = 09h
48 data_seg = 00010000b ; data segment
49 expand_down = 00000100b ; =1 limit counts down from base
50 writable = 00000010b ; =1 if write access allowed to data segment
51 code_seg = 00011000b ; code segment
52 conforming = 00000100b ; =1 code can be accesses and executed at any PL
53 readable = 00000010b ; =1 if code also can be read (cannot be ovwritten)
54 ; privilege levels (bit5..6 of descr.type )
55 priv0 = 00000000b
56 priv1 = 00100000b
57 priv2 = 01000000b
58 priv3 = 01100000b
59 ; segment present bit (bit7 of descr.type )
60 is_present = 10000000b
61 not_present = 00000000b
62 ;definition of granularity ( bits6..7 in descr.limit16 )
63 gran_byte = 00000000b
64 gran_page = 10000000b ; 4k granularity
65 use_16 = 00000000b
66 use_32 = 01000000b
68 ;****** rm32,imm16 helpers
69 macro addzx_e rm,i
70 db 66h
71 add rm,i
72 dw 0
73 endm
76 group DGROUP _TEXT,_BSS
77 assume cs:DGROUP,ds:DGROUP
79 segment _BSS byte public use16 'BSS'
81 tss dd ?,? ;enough, we'll never use it anyway
83 ends _BSS
85 segment _TEXT byte public use16 'CODE'
87 label gdt byte
88 gdt_null descr <?> ;0000
89 gdt_vcpi descr <?> ;0008
90 gdt_vcpi2 descr <?> ;0010
91 gdt_vcpi3 descr <?> ;0018
92 descriptor gdt_abs ,(data_seg+writable),priv0,is_present,0fffffh,(gran_page+use_32),0
93 ;Note: code/data segs must be flagged use16 (i.e. use ip/sp, not eip/esp)
94 ;Note: base addrs will be fixed up in prepare_vcpi()
95 descriptor gdt_code,(code_seg+readable),priv0,is_present,0fffffh,(gran_page+use_16),0
96 global gdt_data:descr
97 descriptor gdt_data,(data_seg+writable),priv0,is_present,0fffffh,(gran_page+use_16),0
98 descriptor gdt_tss ,tss386_avail ,priv0,is_present,0ffh ,gran_byte ,<offset tss>
99 SEL_VCPI = (gdt_vcpi - gdt_null)
100 SEL_TSS = (gdt_tss - gdt_null)
101 SEL_ABS = (gdt_abs - gdt_null)
102 SEL_CODE = (gdt_code - gdt_null)
103 SEL_DATA = (gdt_data - gdt_null)
105 label gdtr pword
106 gdt_lim dw 0ffffh
107 gdt_base dw offset gdt,0
109 ;Note: layout dictated by vcpi api, don't rearrange!
110 label sw2pm_params byte
111 ;Note: base addrs will be fixed up in prepare_vcpi()
112 label pagedir_laddr dword
113 sw2pm_cr3 dd 1000h
114 sw2pm_gdtr_ptr dw offset gdtr,0
115 sw2pm_idtr_ptr dw offset idtr,0
116 sw2pm_ldtr dw 0 ;we don't need it
117 sw2pm_tr dw SEL_TSS ;vcpi thinks we need it... can't set to 0
118 sw2pm_jumpaddr dd 0
119 dw SEL_CODE
121 vcpi_pm_entry dd 0
122 dw SEL_VCPI
124 label idtr pword
125 idt_lim dw 03ffh ;we won't enable ints,
126 idt_base dd 0 ; so let's leave it the same as for rm
129 ;***************************************************************
130 ;char* prepare_vcpi(void *pagebuf);
131 ;****** Return: AX=>first unused byte in pagebuf
132 ;****** Uses: Flags
133 ;***************************************************************
134 global prepare_vcpi:near
135 proc prepare_vcpi near
137 ;pop ax
138 ;pop bx ;pgbuf
139 ;push bx
140 ;push ax
142 ;Calculate pagedir/page0 addrs, initialize cr3 and pagedir[0]
143 ; heap_top = prepare_vcpi(malloc_or_die(8*1024+4));
145 mov edx,cs
146 shl edx,4 ;edx = linear addr of CS
147 mov si,offset gdt_vcpi
148 ; Fix up base of some gdt descriptors
149 ; Note: 'add [dword xx.base0],edx' actually updates 24 bit quantity!
150 ; Do NOT replace with mov!
151 mov ebx,10000h-28h
152 add [dword bx+si+sw2pm_idtr_ptr-gdt_vcpi+28h],edx
153 @@fixup:
154 add [dword bx+si+(gdt_code.base0)-gdt_vcpi+28h],edx
155 add bx,8
156 js @@fixup
157 mov bh,10h
158 extrn _heap_top:word
159 movzx eax,[_heap_top]
160 add eax,edx
161 and ax,0f000h ;eax = 4k aligned linear addr of pagebuf
162 add eax,ebx ;eax=page0 linear addr
163 add [si+sw2pm_cr3-gdt_vcpi],eax
164 mov edi,eax
165 sub edi,edx
166 mov al,3 ;add present+writable bits
167 mov [bx+di],eax ;stuff it into pagedir[0]
168 push ds
169 pop es ;es:di->page0,es:di+1000h->pagedir
170 ;page directory will use only one entry (4 bytes):
171 ;cr3 => pagedir => page0 => ########
172 ; (1 entry) (1024 => # 4M #
173 ; entries)=> # page #
174 ; => ########
175 ; Return
176 lea ax,[bx+di+4]
177 mov [_heap_top],ax
178 ;ret
180 endp prepare_vcpi
183 ;***************************************************************
184 ;int get_vcpi_interface();
185 ;****** Return: Z - page mapping for low 640k is 1:1
186 ;****** NZ - otherwise (it's bad)
187 ;****** Uses: Flags
188 ;***************************************************************
189 ;global _get_vcpi_interface:near
190 proc _get_vcpi_interface near
192 ;push si di
194 ; Get and save VCPI pm interface
195 ;mov si,offset gdt_vcpi ;DS:DI => 3 GDT entries for VCPI
196 ;mov di,[si+page0_ofs-gdt_vcpi] ;ES:DI => page0
197 ;push ds
198 ;pop es
199 push di
200 mov ax,0DE01h ;get vcpi pm interface
201 int 67h
202 xchg [vcpi_pm_entry],ebx ;clear ebx
203 ;xor bx,bx
205 ; Check that mapping for low 640k is 1:1
206 pop si ; [page0_ofs]
207 ;cld
208 @@map_chk:
209 lodsd
210 shr eax,12
211 cmp ax,bx
212 jne @@bad
213 inc bx
214 cmp al,((640*1024) shr 12)-1
215 jne @@map_chk
216 ; Return
217 @@bad:
218 ret
219 endp _get_vcpi_interface
222 ;***************************************************************
223 ;void memcpy_vcpi(u32 dstofs,u16 srcseg,u32 srcofs);
224 ;***************************************************************
225 ;****** Copies PAGE_SIZE bytes
226 ;****** Uses: Flags
227 ;***************************************************************
228 global vcpi_pm_copy_routine:near
229 proc vcpi_pm_copy_routine near
231 arg dstofs :dword, \
232 srcseg :word, \
233 srcofs :dword = PARAM_SIZE
235 struc pm_regs
236 $$retaddr dw ?
237 $$edi dd ?
238 $$esi dd ?
239 $$ebp dd ?
240 $$esp dd ?
241 $$ebx dd ?
242 $$edx dd ?
243 $$ecx dd ?
244 $$eax dd ?
245 ends
247 ;***************************************************************
248 ;****** Helper: goes into 16bit pm and calls routine (addr on stk)
249 ;***************************************************************
250 mov bp,sp ; ss:bp => struct pm_regs
252 xor ax,ax ; IRET stack for return to vm
253 push ax gs ; (9 dwords)
254 push ax fs ;
255 push ax ds ;
256 push ax es ;
257 push ax ss ;
258 push ebp ; esp
259 pushfd ; eflags: IF saved here
260 push ax cs ;
261 push ax ;\eip
262 push offset @@vm_ret ;/
264 ;;mov [saved_xx],xx ;use if your vcpi trashes bp/etc
266 call switch_to_pm
268 ; Now we are in 16-bit protected mode
269 mov ax,SEL_DATA
270 mov ss,ax
271 ;;mov ds,ax
272 ;;mov es,ax
273 ;;mov fs,ax
274 ;;mov gs,ax
275 assume nothing
276 assume cs:DGROUP
278 ;;mov xx,[saved_xx] ;use if your vcpi trashes bp/etc
279 lea sp,[bp-9*4] ;else we can do this trick with bp
281 ; Call the routine (bp points to params on stack if any)
282 mov bp,[word (pm_regs bp).$$ebp] ;ss:bp => params
283 call do_memcpy_vcpi
285 ; Ok, let's return to vm
286 mov ax,0DE0Ch ; maybe we need whole eax?
287 cli ; to be safe
288 clts ;
289 ;;push SEL_ABS ; vcpi wants ds=all_addrspace
290 ;;pop ds ;
291 call [pword cs:vcpi_pm_entry]
292 @@vm_ret:
293 ; Now we are in vm86 mode. Sregs, esp, eflags (IF) restored from IRET stack
294 ret
296 ;***************************************************************
297 switch_to_pm:
298 assume cs:DGROUP,ds:DGROUP
299 pop [word sw2pm_jumpaddr]
300 ;mov [word sw2pm_jumpaddr+2],0
301 ;mov [word sw2pm_jumpaddr+4],SEL_CODE
302 mov esi,cs
303 shl esi,4
304 addzx_e si,<offset sw2pm_params>
305 mov ax,0DE0Ch ; vcpi: switch to pm
306 cli
307 int 67h
309 ;***************************************************************
310 ;****** Helper: This is where real copy is done
311 ;***************************************************************
312 label do_memcpy_vcpi near
314 ; Note: ss:bp => params
315 ; Move data
316 mov al,SEL_ABS
317 mov ds,ax
318 mov es,ax
319 assume nothing
320 assume cs:DGROUP
322 ; Set up target addr:
323 ; replace page mapping for page at 0 so
324 ; that it points to dstofs
325 mov eax,[dstofs]
326 mov al,03h ; writeable, present
327 call @@set_mapping
328 ;push eax ;X we'll need to restore mapping...
329 xor edi,edi ;es:edi => remapped page
331 ; Set up source addr
332 mov esi,[srcofs]
334 ; Do copying
335 xor ecx,ecx
336 mov ch,4096/256
337 ;cld
338 ;; cmp esi,edi
339 ;; jae @@do_copy
340 ;; add esi,ecx ;src<dst: we must do
341 ;; dec esi ; copy backwards to avoid
342 ;; add edi,ecx ; overwrite bug
343 ;; dec edi ;
344 ;; std ;
345 ;;@@do_copy:
346 db 67h ;address width override for esi/edi
347 rep movsb
348 ;; cld
350 ; Restore page mapping for page at 0
351 ;pop eax ;X
352 @@set_mapping:
353 mov esi,[cs:sw2pm_cr3]
354 xchg [esi-1000h],eax ; restore page0[0]
355 mov ecx,cr3 ; reload TLB cache
356 mov cr3,ecx ;
357 ; Return
358 vcpi_ret:
359 ret
361 endp vcpi_pm_copy_routine
362 assume cs:DGROUP,ds:DGROUP
365 ;***************************************************************
366 ;void _vm2rm();
367 ;***************************************************************
368 ;****** Uses: Flags
369 ;***************************************************************
370 global _vm2rm:near
371 proc _vm2rm near
373 ifdef NO386
374 p8086
375 extrn _vcpi:byte
376 test [_vcpi],-1
377 else
378 p386
379 smsw ax ;SMSW cannot be trapped! :-)
380 and al,1 ;MSW_PE
381 endif
382 jz vcpi_ret
383 p386
384 pop ax
385 push cs ;*
386 push ax
387 push si
388 push ds
389 extrn sssp:word
390 mov [sssp],sp
391 ;mov [sssp+2],ss
393 call switch_to_pm
395 ; Now we are in 16-bit protected mode
396 mov ax,SEL_DATA ; load data sregs with limit >=64k
397 mov ss,ax ; or you may get limit violations
398 mov ds,ax ; later in rm
399 ;mov es,ax ; (actually I prefer 4gig limits :-)
400 ;mov fs,ax ;
401 ;mov gs,ax ;
403 ; Black magic here
404 mov eax,cr0
405 and eax,7ffffffeh ; clear PG,P bits
406 mov cr0,eax ; look mommy, we're in rm now!
407 mov cr3,eax ; flush TLB cache
409 ; Now we are in rm, but not yet: have to restore sregs:
410 lss sp,[dword sssp]; SS
411 pop ds ; DS
412 pop si
413 retf ; CS
415 endp _vm2rm
417 ends _TEXT
419 end
421 ;###### END OF FILE ############################################