wok-6.x view linld/stuff/src/VCPI.ASM @ rev 25035
Up libqcow (20210419)
author | Pascal Bellard <pascal.bellard@slitaz.org> |
---|---|
date | Fri May 20 18:11:13 2022 +0000 (2022-05-20) |
parents | e4805f18eb64 |
children |
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 255
28 %crefref
29 %noincl
30 %nomacs
32 include "common.inc"
34 ifdef VCPI
35 p386
37 ;****** Stuff for declaring descriptors
38 struc descr
39 limit dw ?
40 base0 dw ?
41 base16 db ?
42 type db ?
43 limit16 db ?
44 base24 db ?
45 ends descr
46 macro descriptor name,typ,plevel,present,limit,gran,base
47 ;;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)>
48 name descr <limit and 0ffffh,base ,0 ,typ or plevel or present,(limit shr 16) or gran,0 >
49 endm
50 ; decriptor types (bit0..4 of descr.type )
51 tss386_avail = 09h
52 data_seg = 00010000b ; data segment
53 expand_down = 00000100b ; =1 limit counts down from base
54 writable = 00000010b ; =1 if write access allowed to data segment
55 code_seg = 00011000b ; code segment
56 conforming = 00000100b ; =1 code can be accesses and executed at any PL
57 readable = 00000010b ; =1 if code also can be read (cannot be ovwritten)
58 ; privilege levels (bit5..6 of descr.type )
59 priv0 = 00000000b
60 priv1 = 00100000b
61 priv2 = 01000000b
62 priv3 = 01100000b
63 ; segment present bit (bit7 of descr.type )
64 is_present = 10000000b
65 not_present = 00000000b
66 ;definition of granularity ( bits6..7 in descr.limit16 )
67 gran_byte = 00000000b
68 gran_page = 10000000b ; 4k granularity
69 use_16 = 00000000b
70 use_32 = 01000000b
72 ;****** rm32,imm16 helper
73 macro movzx_e rm,i
74 db 66h
75 mov rm,i
76 dw 0
77 endm
79 macro pushd sreg
80 db 66h
81 push sreg
82 endm
84 group DGROUP _TEXT
85 assume cs:DGROUP,ds:DGROUP
87 segment _TEXT byte public use16 'CODE'
89 ;***************************************************************
90 ;int get_vcpi_interface();
91 ;****** Return: Z - page mapping for low 640k is 1:1
92 ;****** NZ - otherwise (it's bad)
93 ;****** Uses: Flags
94 ;***************************************************************
95 ;global _get_vcpi_interface:near
96 proc _get_vcpi_interface near
98 ;push si di
100 ; Get and save VCPI pm interface
101 ;mov si,offset gdt_vcpi ;DS:DI => 3 GDT entries for VCPI
102 ;mov di,[si+page0_ofs-gdt_vcpi] ;ES:DI => page0
103 ;push ds
104 ;pop es
105 ;push di
106 ;mov ax,0DE01h ;get vcpi pm interface
107 int 67h
108 xchg [si+vcpi_pm_entry-gdt_vcpi],ebx ; bx=((640*1024) shr 12)
110 ; Check that mapping for low 640k is 1:1
111 pop si ; [page0_ofs]
112 ;cld
113 mov cx,bx
114 @@map_chk:
115 lodsd
116 shr eax,12
117 add ax,cx
118 ;cmp eax,ebx ; ((640*1024) shr 12)
119 cmp ax,bx ; ((640*1024) shr 12)
120 loope @@map_chk
121 ;pop di si
122 ret
124 endp _get_vcpi_interface
127 ;***************************************************************
128 ;char* prepare_vcpi(void *pagebuf);
129 ;****** Return: AX=>first unused byte in pagebuf
130 ;****** Uses: Flags
131 ;***************************************************************
132 global prepare_vcpi:near
133 proc prepare_vcpi near
135 ;Calculate pagedir/page0 addrs, initialize cr3 and pagedir[0]
136 ; heap_top = prepare_vcpi(malloc_or_die(8*1024+4));
138 ;mov edx,cs
139 ;shl edx,4 ;edx = linear addr of CS
140 mov si,offset gdt_vcpi
141 ; Fix up base of some gdt descriptors
142 ; Note: 'add [dword xx.base0],edx' actually updates 24 bit quantity!
143 ; Do NOT replace with mov!
144 mov bx,10000h-28h
145 add [dword si+sw2pm_addr-gdt_vcpi],edx
146 add [dword si+sw2pm_idtr_ptr-gdt_vcpi],edx
147 @@fixup:
148 add [dword bx+si+(gdt_code.base0)-gdt_vcpi+28h],edx
149 add bx,8
150 js @@fixup
151 mov bh,10h
152 extrn _heap_top:word
153 ;movzx eax,[_heap_top]
154 mov ax,[_heap_top]
155 add ax,bx ; assume _heap_top < 0f000h
156 add eax,edx
157 and ax,0f000h ;eax = 4k aligned linear addr of pagebuf
158 add [si+sw2pm_cr3-gdt_vcpi],eax ;eax=page0 linear addr
159 mov edi,eax
160 sub edi,edx
161 mov al,3 ;add present+writable bits
162 mov [bx+di],eax ;stuff it into pagedir[0]
163 ;push ds
164 ;pop es ;es:di->page0,es:di+1000h->pagedir
165 ;page directory will use only one entry (4 bytes):
166 ;cr3 => pagedir => page0 => ########
167 ; (1 entry) (1024 => # 4M #
168 ; entries)=> # page #
169 ; => ########
170 ; Return
171 lea ax,[bx+di+4]
172 mov [_heap_top],ax
173 ;ret
174 push di
175 mov ax,0DE01h ;get vcpi pm interface
176 jmp _get_vcpi_interface
178 endp prepare_vcpi
180 org $-40
181 tss dd ?,? ;enough, we'll never use it anyway
182 label gdt byte
183 gdt_null descr <?> ;0000
184 gdt_vcpi descr <?> ;0008
185 gdt_vcpi2 descr <?> ;0010
186 gdt_vcpi3 descr <?> ;0018
187 org $-8
188 global gdt_memcpy:descr
189 gdt_memcpy descr <?> ;null + gdt_abs
190 descriptor gdt_abs ,(data_seg+writable),priv0,is_present,0fffffh,(gran_page+use_32),0
191 ;Note: code/data segs must be flagged use16 (i.e. use ip/sp, not eip/esp)
192 ;Note: base addrs will be fixed up in prepare_vcpi()
193 descriptor gdt_code,(code_seg+readable),priv0,is_present,0fffffh,(gran_page+use_16),0
194 global gdt_data:descr
195 descriptor gdt_data,(data_seg+writable),priv0,is_present,0fffffh,(gran_page+use_16),0
196 descriptor gdt_tss ,tss386_avail ,priv0,is_present,0ffh ,gran_byte ,<offset tss>
197 SEL_VCPI = (gdt_vcpi - gdt_null)
198 SEL_TSS = (gdt_tss - gdt_null)
199 SEL_ABS = (gdt_abs - gdt_null)
200 SEL_CODE = (gdt_code - gdt_null)
201 SEL_DATA = (gdt_data - gdt_null)
203 label gdtr pword
204 gdt_lim dw 0ffffh
205 gdt_base dw offset gdt,0
207 ;Note: layout dictated by vcpi api, don't rearrange!
208 label sw2pm_params byte
209 ;Note: base addrs will be fixed up in prepare_vcpi()
210 label pagedir_laddr dword
211 sw2pm_cr3 dd 1000h
212 sw2pm_gdtr_ptr dw offset gdtr,0
213 sw2pm_idtr_ptr dw offset idtr,0
214 sw2pm_ldtr dw 0 ;we don't need it
215 sw2pm_tr dw SEL_TSS ;vcpi thinks we need it... can't set to 0
216 sw2pm_jumpaddr dw offset pmode,0
217 dw SEL_CODE
219 vcpi_pm_entry dd ((640*1024) shr 12)
220 dw SEL_VCPI
222 label idtr pword
223 idt_lim dw 03ffh ;we won't enable ints,
224 idt_base dd 0 ; so let's leave it the same as for rm
227 ;***************************************************************
228 ;void memcpy_vcpi(u32 dstofs,u16 srcseg,u32 srcofs);
229 ;***************************************************************
230 ;****** Copies PAGE_SIZE bytes
231 ;****** Uses: Flags
232 ;***************************************************************
233 global vcpi_pm_copy_routine:near
234 proc vcpi_pm_copy_routine near
236 struc pm_regs
237 $$retaddr dw ?
238 $$edi dd ?
239 $$esi dd ?
240 $$ebp dd ?
241 $$esp dd ?
242 $$ebx dd ?
243 $$edx dd ?
244 $$ecx dd ?
245 $$eax dd ?
246 ends
248 ;***************************************************************
249 ;****** Helper: goes into 16bit pm and calls routine (addr on stk)
250 ;***************************************************************
251 mov bp,sp ; ss:bp => struct pm_regs
253 mov bx,5 ; IRET stack for return to vm
254 @@push_sreg:
255 pushd ss ; fake pushd gs fs ds es ss
256 dec bx
257 jnz @@push_sreg ; (9 dwords)
258 push ebp ; esp
259 pushfd ; eflags: IF saved here
260 pushd cs ;
261 push bx ;\eip
262 push offset vcpi_ret ;/
264 mov edx,esi
265 switch_to_pm:
266 movzx_e si,<offset sw2pm_params>
267 org $-4
268 sw2pm_addr dd ?
269 mov ax,0DE0Ch ; vcpi: switch to pm
270 cli ; load GDTR LDTR TR need 16 bytes in SS:ESP
271 int 67h ; EAX, ESI, DS, ES, FS, GS destroyed
272 pmode:
273 assume nothing
274 assume cs:DGROUP
276 ; Now we are in 16-bit protected mode
277 push SEL_DATA
278 pop ss
279 test bx,bx
280 jnz vm2rm_end
282 lea sp,[bp-8-9*4]
284 ; Call the routine (bp points to params on stack if any)
285 call do_memcpy_vcpi ; set ds=all_addrspace
287 ; Ok, let's return to vm
288 mov ax,0DE0Ch ; maybe we need whole eax?
289 cli ; to be safe
290 clts ;
291 ; Go to vm86 mode. Sregs, esp, eflags (IF) restored from IRET stack
292 jmp [pword cs:vcpi_pm_entry]
294 ;***************************************************************
296 ;***************************************************************
297 ;****** Helper: This is where real copy is done
298 ;***************************************************************
299 label do_memcpy_vcpi near
301 push SEL_ABS
302 pop ds
303 push ds
304 pop es
305 assume nothing
306 assume cs:DGROUP
308 ; Set up target addr:
309 ; replace page mapping for page at 0 so
310 ; that it points to dstofs
311 xchg eax,edi
312 mov al,03h ; writeable, present
313 call @@set_mapping
314 xor edi,edi ;es:edi => remapped page
316 ; Set up source addr
317 mov esi,edx
319 ; Do copying
320 db 67h ;address width override for esi/edi
321 rep movsb
323 @@set_mapping:
324 mov esi,[cs:sw2pm_cr3]
325 xchg [esi-1000h],eax ; restore page0[0]
326 mov esi,cr3 ; reload TLB cache
327 mov cr3,esi ;
328 ; Return
329 vcpi_ret:
330 ret
332 endp vcpi_pm_copy_routine
335 ;***************************************************************
336 ;void _vm2rm();
337 ;***************************************************************
338 ;****** Uses: Flags
339 ;***************************************************************
340 global _vm2rm:far
341 proc _vm2rm far
343 assume cs:DGROUP,ds:DGROUP
344 push ds
345 extrn sssp:dword
346 mov bx,offset sssp
347 mov [bx],sp
348 ;mov [bx+2],ss
349 ifdef QUICK_BOOT
350 CMDNUMOFS = 24
351 ifdef MINRAM
352 CMDNUMOFS = CMDNUMOFS+4
353 endif
354 ifdef CPUTYPE
355 CMDNUMOFS = CMDNUMOFS+4
356 endif
357 extrn _cmdnum:dword
358 v86boot = (byte _cmdnum+CMDNUMOFS)
359 test [v86boot],bh
360 jnz @vm2rm_ret
361 endif
362 ifdef NO386
363 extrn _vcpi:byte
364 test [_vcpi],bh
365 else
366 smsw ax ;SMSW cannot be trapped! :-)
367 and al,1 ;MSW_PE
368 endif
369 jz @vm2rm_ret
370 jmp switch_to_pm ; EAX, ESI, DS, ES, FS, GS destroyed
371 vm2rm_end:
372 assume nothing
373 assume cs:DGROUP
375 ;push ss
376 ;pop ds
378 ; Now we are in 16-bit protected mode
379 ; Black magic here
380 mov eax,cr0
381 and eax,7ffffffeh ; clear PG,P bits
382 mov cr0,eax ; look mommy, we're in rm now!
383 mov cr3,eax ; flush TLB cache
385 ; Now we are in rm, but not yet: have to restore sregs:
386 lss sp,[cs:bx] ; SS
387 @vm2rm_ret:
388 pop ds ; DS
389 retf ; CS
391 endp _vm2rm
393 ends _TEXT
394 else
396 group DGROUP _TEXT
397 assume cs:DGROUP,ds:DGROUP
399 segment _TEXT byte public use16 'CODE'
400 global gdt_data:near
401 gdt_data:
402 ends _TEXT
404 endif
406 end
408 ;###### END OF FILE ############################################