Subversion Repositories Kolibri OS

Rev

Rev 789 | Rev 891 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
709 diamond 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2007-2008. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
750 victor 8
$Revision: 820 $
9
 
709 diamond 10
; Virtual-8086 mode manager
11
; diamond, 2007, 2008
12
 
13
DEBUG_SHOW_IO = 0
14
 
15
struc V86_machine
16
{
17
; page directory
18
        .pagedir dd     ?
19
; translation table: V86 address -> flat linear address
20
        .pages  dd      ?
21
; mutex to protect all data from writing by multiple threads at one time
22
        .mutex  dd      ?
23
; i/o permission map
24
        .iopm   dd      ?
25
.size = $
26
}
27
virtual at 0
28
V86_machine V86_machine
29
end virtual
30
 
31
; Create V86 machine
32
; in: nothing
33
; out: eax = handle (pointer to struc V86_machine)
34
;      eax = NULL => failure
35
; destroys: ebx, ecx, edx (due to malloc)
36
v86_create:
37
; allocate V86_machine structure
38
        mov     eax, V86_machine.size
39
        call    malloc
40
        test    eax, eax
41
        jz      .fail
42
; initialize mutex
43
        and     dword [eax+V86_machine.mutex], 0
44
; allocate tables
45
        mov     ebx, eax
46
; We allocate 4 pages.
47
; First is main page directory for V86 mode.
48
; Second page:
49
; first half (0x800 bytes) is page table for addresses 0 - 0x100000,
50
; second half is for V86-to-linear translation.
51
; Third and fourth are for I/O permission map.
724 diamond 52
        push    8000h           ; blocks less than 8 pages are discontinuous
709 diamond 53
        call    kernel_alloc
54
        test    eax, eax
55
        jz      .fail2
56
        mov     [ebx+V86_machine.pagedir], eax
57
        push    edi eax
58
        mov     edi, eax
59
        add     eax, 1800h
60
        mov     [ebx+V86_machine.pages], eax
61
; initialize tables
62
        mov     ecx, 2000h/4
63
        xor     eax, eax
64
        rep     stosd
65
        mov     [ebx+V86_machine.iopm], edi
66
        dec     eax
67
        mov     ecx, 2000h/4
68
        rep     stosd
69
        pop     eax
70
; page directory: first entry is page table...
71
        mov     edi, eax
72
        add     eax, 1000h
73
        push    eax
74
        call    get_pg_addr
75
        or      al, PG_UW
76
        stosd
77
; ...and also copy system page tables
78
; thx to Serge, system is located at high addresses
79
        add     edi, (OS_BASE shr 20) - 4
80
        push    esi
81
        mov     esi, (OS_BASE shr 20) + sys_pgdir
82
        mov     ecx, 0x80000000 shr 22
83
        rep     movsd
712 serge 84
 
85
        mov     eax, [ebx+V86_machine.pagedir]   ;root dir also is
86
        call    get_pg_addr                      ;used as page table
87
        or      al, PG_SW
88
        mov [edi-4096+(page_tabs shr 20)], eax
89
 
709 diamond 90
        pop     esi
91
; now V86 specific: initialize known addresses in first Mb
820 diamond 92
        pop     eax
709 diamond 93
; first page - BIOS data (shared between all machines!)
94
; physical address = 0x2f0000
95
; linear address = BOOT_VAR = OS_BASE + 0x2f0000
96
        mov     dword [eax], (BOOT_VAR - OS_BASE) or 111b
97
        mov     dword [eax+800h], BOOT_VAR
98
; page before 0xA0000 - Extended BIOS Data Area (shared between all machines!)
820 diamond 99
; physical address = 0x9C000
100
; linear address = 0x8009C000
101
; (I have seen one computer with EBDA segment = 0x9D80,
102
; all other computers use less memory)
103
        mov     ecx, 4
104
        mov     edx, 0x9C000
105
        push    eax
106
        lea     edi, [eax+0x9C*4]
107
@@:
108
        lea     eax, [edx + OS_BASE]
109
        mov     [edi+800h], eax
110
        lea     eax, [edx + 111b]
111
        stosd
112
        loop    @b
113
        pop     eax
114
        pop     edi
709 diamond 115
; addresses 0xC0000 - 0xFFFFF - BIOS code (shared between all machines!)
116
; physical address = 0xC0000
117
; linear address = 0x800C0000
118
        mov     ecx, 0xC0
119
@@:
120
        mov     edx, ecx
121
        shl     edx, 12
122
        push    edx
123
        or      edx, 101b
124
        mov     [eax+ecx*4], edx
125
        pop     edx
126
        add     edx, OS_BASE
127
        mov     [eax+ecx*4+0x800], edx
128
        inc     cl
129
        jnz     @b
130
        mov     eax, ebx
131
        ret
132
.fail2:
133
        mov     eax, ebx
134
        call    free
135
.fail:
136
        xor     eax, eax
137
        ret
138
 
139
; Destroy V86 machine
140
; in: eax = handle
141
; out: nothing
142
; destroys: eax, ebx, ecx, edx (due to free)
143
v86_destroy:
144
        push    eax
145
        stdcall kernel_free, [eax+V86_machine.pagedir]
146
        pop     eax
147
        jmp     free
148
 
149
; Translate V86-address to linear address
150
; in: eax=V86 address
151
;     esi=handle
152
; out: eax=linear address
153
; destroys: nothing
154
v86_get_lin_addr:
155
        push    ecx edx
156
        mov     ecx, eax
157
        mov     edx, [esi+V86_machine.pages]
158
        shr     ecx, 12
159
        and     eax, 0xFFF
160
        add     eax, [edx+ecx*4]        ; atomic operation, no mutex needed
161
        pop     edx ecx
162
        ret
163
 
164
; Sets linear address for V86-page
165
; in: eax=linear address (must be page-aligned)
166
;     ecx=V86 page (NOT address!)
167
;     esi=handle
168
; out: nothing
169
; destroys: nothing
170
v86_set_page:
171
        push    eax ebx
172
        mov     ebx, [esi+V86_machine.pagedir]
173
        mov     [ebx+ecx*4+0x1800], eax
174
        call    get_pg_addr
175
        or      al, 111b
176
        mov     [ebx+ecx*4+0x1000], eax
177
        pop     ebx eax
178
        ret
179
 
180
; Allocate memory in V86 machine
181
; in: eax=size (in bytes)
182
;     esi=handle
183
; out: eax=V86 address, para-aligned (0x10 multiple)
184
; destroys: nothing
724 diamond 185
; недописана!!!
709 diamond 186
;v86_alloc:
187
;        push    ebx ecx edx edi
188
;        lea     ebx, [esi+V86_machine.mutex]
189
;        call    wait_mutex
190
;        add     eax, 0x1F
191
;        shr     eax, 4
192
;        mov     ebx, 0x1000  ; start with address 0x1000 (second page)
193
;        mov     edi, [esi+V86_machine.tables]
194
;.l:
195
;        mov     ecx, ebx
196
;        shr     ecx, 12
197
;        mov     edx, [edi+0x1000+ecx*4] ; get linear address
198
;        test    edx, edx                ; page allocated?
199
;        jz      .unalloc
200
;        mov     ecx, ebx
201
;        and     ecx, 0xFFF
202
;        add     edx, ecx
203
;        cmp     dword [edx], 0          ; free block?
204
;        jnz     .n
724 diamond 205
;        cmp     dword [edx+4],
709 diamond 206
;        and     [esi+V86_machine.mutex], 0
207
;        pop     edi edx ecx ebx
208
;        ret
209
 
210
uglobal
211
sys_v86_machine dd      ?
212
endg
213
 
214
; Called from kernel.asm at first stages of loading
215
; Initialize system V86 machine (used to simulate BIOS int 13h)
216
init_sys_v86:
217
        call    v86_create
218
        mov     [sys_v86_machine], eax
219
        test    eax, eax
220
        jz      .ret
221
        mov     byte [BOOT_VAR + 0x500], 0xCD
222
        mov     byte [BOOT_VAR + 0x501], 0x13
223
        mov     byte [BOOT_VAR + 0x502], 0xF4
224
        mov     byte [BOOT_VAR + 0x503], 0xCD
225
        mov     byte [BOOT_VAR + 0x504], 0x10
226
        mov     byte [BOOT_VAR + 0x505], 0xF4
227
        mov     esi, eax
228
        mov     ebx, [eax+V86_machine.pagedir]
820 diamond 229
; one page for stack, two pages for results (0x2000 bytes = 16 sectors)
230
        mov     dword [ebx+0x99*4+0x1000], 0x99000 or 111b
231
        mov     dword [ebx+0x99*4+0x1800], OS_BASE + 0x99000
232
        mov     dword [ebx+0x9A*4+0x1000], 0x9A000 or 111b
233
        mov     dword [ebx+0x9A*4+0x1800], OS_BASE + 0x9A000
770 diamond 234
        mov     dword [ebx+0x9B*4+0x1000], 0x9B000 or 111b
235
        mov     dword [ebx+0x9B*4+0x1800], OS_BASE + 0x9B000
709 diamond 236
if ~DEBUG_SHOW_IO
237
; allow access to all ports
238
        mov     ecx, [esi+V86_machine.iopm]
239
        xor     eax, eax
240
        mov     edi, ecx
241
        mov     ecx, 10000h/8/4
242
        rep     stosd
243
end if
244
.ret:
245
        ret
246
 
247
struc v86_regs
248
{
249
; don't change the order, it is important
250
        .edi    dd      ?
251
        .esi    dd      ?
252
        .ebp    dd      ?
253
                dd      ?       ; ignored
254
        .ebx    dd      ?
255
        .edx    dd      ?
256
        .ecx    dd      ?
257
        .eax    dd      ?
258
        .eip    dd      ?
259
        .cs     dd      ?
260
        .eflags dd      ?       ; VM flag must be set!
261
        .esp    dd      ?
262
        .ss     dd      ?
263
        .es     dd      ?
264
        .ds     dd      ?
265
        .fs     dd      ?
266
        .gs     dd      ?
267
.size = $
268
}
269
virtual at 0
270
v86_regs v86_regs
271
end virtual
272
 
273
; Run V86 machine
274
; in: ebx -> registers for V86 (two structures: in and out)
275
;     esi = handle
276
;     ecx = expected end address (CS:IP)
277
;     edx = IRQ to hook or -1 if not required
278
; out: structure pointed to by ebx is filled with new values
279
;     eax = 1 - exception has occured, cl contains code
280
;     eax = 2 - access to disabled i/o port, ecx contains port address
281
;     eax = 3 - IRQ is already hooked by another VM
282
; destroys: nothing
283
v86_start:
284
        pushad
285
 
286
        cli
287
 
288
        mov     ecx, [CURRENT_TASK]
289
        shl     ecx, 8
290
        add     ecx, SLOT_BASE
291
 
292
        mov     eax, [esi+V86_machine.iopm]
293
        call    get_pg_addr
294
        inc     eax
295
        push    dword [ecx+APPDATA.io_map]
296
        push    dword [ecx+APPDATA.io_map+4]
297
        mov     dword [ecx+APPDATA.io_map], eax
298
        mov     dword [page_tabs + (tss._io_map_0 shr 10)], eax
299
        add     eax, 0x1000
300
        mov     dword [ecx+APPDATA.io_map+4], eax
301
        mov     dword [page_tabs + (tss._io_map_1 shr 10)], eax
302
 
303
        push    [ecx+APPDATA.dir_table]
304
        push    [ecx+APPDATA.saved_esp0]
305
        mov     [ecx+APPDATA.saved_esp0], esp
306
        mov     [tss._esp0], esp
307
 
308
        mov     eax, [esi+V86_machine.pagedir]
309
        call    get_pg_addr
310
        mov     [ecx+APPDATA.dir_table], eax
311
        mov     cr3, eax
312
 
313
;        mov     [irq_tab+5*4], my05
314
 
315
; We do not enable interrupts, because V86 IRQ redirector assumes that
316
; machine is running
317
; They will be enabled by IRET.
318
;        sti
319
 
320
        mov     eax, esi
321
        sub     esp, v86_regs.size
322
        mov     esi, ebx
323
        mov     edi, esp
324
        mov     ecx, v86_regs.size/4
325
        rep     movsd
326
 
327
        cmp     edx, -1
328
        jz      .noirqhook
329
uglobal
330
v86_irqhooks    rd      16*2
331
endg
332
        cmp     [v86_irqhooks+edx*8], 0
333
        jz      @f
334
        cmp     [v86_irqhooks+edx*8], eax
335
        jz      @f
336
        mov     esi, v86_irqerr
337
        call    sys_msg_board_str
338
        inc     [v86_irqhooks+edx*8+4]
339
        mov     eax, 3
340
        jmp     v86_exc_c.exit
341
@@:
342
        mov     [v86_irqhooks+edx*8], eax
343
        inc     [v86_irqhooks+edx*8+4]
344
.noirqhook:
345
 
346
        popad
347
        iretd
348
 
349
; It is only possible to leave virtual-8086 mode by faulting to
350
; a protected-mode interrupt handler (typically the general-protection
351
; exception handler, which in turn calls the virtual 8086-mode monitor).
352
 
353
v86_debug_exc:
354
        pushad
355
        xor     eax, eax
356
        mov     dr6, eax
357
        mov     bl, 1
358
        jmp     v86_exc_c
359
 
360
v86_page_fault:
361
        add     esp, 4
362
        pushad
363
        mov     bl, 14
364
        jmp     v86_exc_c
365
 
366
v86_except_16:
367
        pushad
368
        mov     bl, 16
369
        jmp     v86_exc_c
370
v86_except_19:
371
        pushad
372
        mov     bl, 19
373
 
374
iglobal
375
v86_exc_str1    db      'V86 : unexpected exception ',0
376
v86_exc_str2    db      ' at ',0
377
v86_exc_str3    db      ':',0
378
v86_exc_str4    db      13,10,'V86 : faulted code:',0
379
v86_exc_str5    db      ' (unavailable)',0
380
v86_newline     db      13,10,0
381
v86_io_str1     db      'V86 : access to disabled i/o port ',0
382
v86_io_byte     db      ' (byte)',13,10,0
383
v86_io_word     db      ' (word)',13,10,0
384
v86_io_dword    db      ' (dword)',13,10,0
385
v86_irqerr      db      'V86 : IRQ already hooked',13,10,0
386
endg
387
 
388
v86_exc_c:
389
        mov     ax, app_data
390
        mov     ds, ax
391
        mov     es, ax
392
; Did we all that we have wanted to do?
393
        mov     eax, [esp+v86_regs.size+10h+18h]
394
        cmp     word [esp+v86_regs.eip], ax
395
        jnz     @f
396
        shr     eax, 16
397
        cmp     word [esp+v86_regs.cs], ax
398
        jz      .done
399
@@:
400
; Various system events, which must be handled, result in #GP
401
        cmp     bl, 13
402
        jnz     .nogp
403
; If faulted EIP exceeds 0xFFFF, we have #GP and it is an error
404
        cmp     word [esp+v86_regs.eip+2], 0
405
        jnz     .nogp
406
; Otherwise we can safely access byte at CS:IP
407
; (because it is #GP, not #PF handler)
724 diamond 408
; Если бы мы могли схлопотать исключение только из-за чтения байтов кода,
409
; мы бы его уже схлопотали и это было бы не #GP
709 diamond 410
        movzx   esi, word [esp+v86_regs.cs]
411
        shl     esi, 4
412
        add     esi, [esp+v86_regs.eip]
413
        lodsb
414
        cmp     al, 0xCD        ; int xx command = CD xx
415
        jz      .handle_int
416
        cmp     al, 0xCF
417
        jz      .handle_iret
418
        cmp     al, 0xF3
419
        jz      .handle_rep
420
        cmp     al, 0xEC
421
        jz      .handle_in
422
        cmp     al, 0xED
423
        jz      .handle_in_word
424
        cmp     al, 0xEE
425
        jz      .handle_out
426
        cmp     al, 0xEF
427
        jz      .handle_out_word
428
        cmp     al, 0xE4
429
        jz      .handle_in_imm
430
        cmp     al, 0xE6
431
        jz      .handle_out_imm
432
        cmp     al, 0x9C
433
        jz      .handle_pushf
434
        cmp     al, 0x9D
435
        jz      .handle_popf
436
        cmp     al, 0xFA
437
        jz      .handle_cli
438
        cmp     al, 0xFB
439
        jz      .handle_sti
440
        cmp     al, 0x66
441
        jz      .handle_66
442
        jmp     .nogp
443
.handle_int:
444
        cmp     word [esp+v86_regs.eip], 0xFFFF
445
        jae     .nogp
446
        xor     eax, eax
447
        lodsb
448
;        call    sys_msg_board_byte
449
; simulate INT command
450
; N.B. It is possible that some checks need to be corrected,
451
;      but at least in case of normal execution the code works.
452
.simulate_int:
453
        cmp     word [esp+v86_regs.esp], 6
454
        jae     @f
455
        mov     bl, 12          ; #SS exception
456
        jmp     .nogp
457
@@:
458
        movzx   edx, word [esp+v86_regs.ss]
459
        shl     edx, 4
460
        push    eax
461
        movzx   eax, word [esp+4+v86_regs.esp]
462
        sub     eax, 6
463
        add     edx, eax
464
        mov     eax, edx
465
        mov     esi, [esp+4+v86_regs.size+10h+4]
466
        call    v86_get_lin_addr
467
        cmp     eax, 0x1000
468
        jae     @f
469
        mov     bl, 14          ; #PF exception
470
        jmp     .nogp
471
@@:
472
        lea     eax, [edx+5]
473
        call    v86_get_lin_addr
474
        cmp     eax, 0x1000
475
        jae     @f
476
        mov     bl, 14          ; #PF exception
477
        jmp     .nogp
478
@@:
479
        sub     word [esp+4+v86_regs.esp], 6
480
        mov     eax, [esp+4+v86_regs.eip]
481
        inc     eax
482
        inc     eax
483
        mov     word [edx], ax
484
        mov     eax, [esp+4+v86_regs.cs]
485
        mov     word [edx+2], ax
486
        mov     eax, [esp+4+v86_regs.eflags]
487
        mov     word [edx+4], ax
488
        pop     eax
489
        mov     cx, [eax*4]
490
        mov     word [esp+v86_regs.eip], cx
491
        mov     cx, [eax*4+2]
492
        mov     word [esp+v86_regs.cs], cx
493
; note that interrupts will be disabled globally at IRET
494
        and     byte [esp+v86_regs.eflags+1], not 3 ; clear IF and TF flags
495
; continue V86 execution
496
        popad
497
        iretd
498
.handle_iret:
499
        cmp     word [esp+v86_regs.esp], 0x10000 - 6
500
        jbe     @f
501
        mov     bl, 12
502
        jmp     .nogp
503
@@:
504
        movzx   edx, word [esp+v86_regs.ss]
505
        shl     edx, 4
506
        movzx   eax, word [esp+v86_regs.esp]
507
        add     edx, eax
508
        mov     eax, edx
509
        mov     esi, [esp+v86_regs.size+10h+4]
510
        call    v86_get_lin_addr
511
        cmp     eax, 0x1000
512
        jae     @f
513
        mov     bl, 14
514
        jmp     .nogp
515
@@:
516
        lea     eax, [edx+5]
517
        call    v86_get_lin_addr
518
        cmp     eax, 0x1000
519
        jae     @f
520
        mov     bl, 14
521
        jmp     .nogp
522
@@:
523
        mov     ax, [edx]
524
        mov     word [esp+v86_regs.eip], ax
525
        mov     ax, [edx+2]
526
        mov     word [esp+v86_regs.cs], ax
527
        mov     ax, [edx+4]
528
        mov     word [esp+v86_regs.eflags], ax
529
        add     word [esp+v86_regs.esp], 6
530
        popad
531
        iretd
532
.handle_pushf:
533
        cmp     word [esp+v86_regs.esp], 1
534
        jnz     @f
535
        mov     bl, 12
536
        jmp     .nogp
537
@@:
538
        movzx   edx, word [esp+v86_regs.ss]
539
        shl     edx, 4
540
        mov     eax, [esp+v86_regs.esp]
541
        sub     eax, 2
542
        movzx   eax, ax
543
        add     edx, eax
544
        mov     eax, edx
545
        mov     esi, [esp+v86_regs.size+10h+4]
546
        call    v86_get_lin_addr
547
        cmp     eax, 0x1000
548
        jae     @f
549
        mov     bl, 14          ; #PF exception
550
        jmp     .nogp
551
@@:
552
        lea     eax, [edx+1]
553
        call    v86_get_lin_addr
554
        cmp     eax, 0x1000
555
        jae     @f
556
        mov     bl, 14
557
        jmp     .nogp
558
@@:
559
        sub     word [esp+v86_regs.esp], 2
560
        mov     eax, [esp+v86_regs.eflags]
561
        mov     [edx], ax
562
        inc     word [esp+v86_regs.eip]
563
        popad
564
        iretd
770 diamond 565
.handle_pushfd:
566
        cmp     word [esp+v86_regs.esp], 4
567
        jae     @f
568
        mov     bl, 12          ; #SS exception
569
        jmp     .nogp
570
@@:
571
        movzx   edx, word [esp+v86_regs.ss]
572
        shl     edx, 4
573
        movzx   eax, word [esp+v86_regs.esp]
574
        sub     eax, 4
575
        add     edx, eax
576
        mov     eax, edx
577
        mov     esi, [esp+v86_regs.size+10h+4]
578
        call    v86_get_lin_addr
579
        cmp     eax, 0x1000
580
        jae     @f
581
        mov     bl, 14          ; #PF exception
582
        jmp     .nogp
583
@@:
584
        lea     eax, [edx+3]
585
        call    v86_get_lin_addr
586
        cmp     eax, 0x1000
587
        jae     @f
588
        mov     bl, 14          ; #PF exception
589
        jmp     .nogp
590
@@:
591
        sub     word [esp+v86_regs.esp], 4
592
        movzx   eax, word [esp+v86_regs.eflags]
593
        mov     [edx], eax
594
        add     word [esp+v86_regs.eip], 2
595
        popad
596
        iretd
709 diamond 597
.handle_popf:
598
        cmp     word [esp+v86_regs.esp], 0xFFFF
599
        jnz     @f
600
        mov     bl, 12
601
        jmp     .nogp
602
@@:
603
        movzx   edx, word [esp+v86_regs.ss]
604
        shl     edx, 4
605
        movzx   eax, word [esp+v86_regs.esp]
606
        add     edx, eax
607
        mov     eax, edx
608
        mov     esi, [esp+v86_regs.size+10h+4]
609
        call    v86_get_lin_addr
610
        cmp     eax, 0x1000
611
        jae     @f
612
        mov     bl, 14          ; #PF exception
613
        jmp     .nogp
614
@@:
615
        lea     eax, [edx+1]
616
        call    v86_get_lin_addr
617
        cmp     eax, 0x1000
618
        jae     @f
619
        mov     bl, 14
620
        jmp     .nogp
621
@@:
622
        mov     ax, [edx]
623
        mov     word [esp+v86_regs.eflags], ax
624
        add     word [esp+v86_regs.esp], 2
625
        inc     word [esp+v86_regs.eip]
626
        popad
627
        iretd
770 diamond 628
.handle_popfd:
629
        cmp     word [esp+v86_regs.esp], 0x10000 - 4
630
        jbe     @f
631
        mov     bl, 12
632
        jmp     .nogp
633
@@:
634
        movzx   edx, word [esp+v86_regs.ss]
635
        shl     edx, 4
636
        movzx   eax, word [esp+v86_regs.esp]
637
        add     edx, eax
638
        mov     eax, edx
639
        mov     esi, [esp+v86_regs.size+10h+4]
640
        call    v86_get_lin_addr
641
        cmp     eax, 0x1000
642
        jae     @f
643
        mov     bl, 14
644
        jmp     .nogp
645
@@:
646
        lea     eax, [edx+3]
647
        call    v86_get_lin_addr
648
        cmp     eax, 0x1000
649
        jae     @f
650
        mov     bl, 14
651
        jmp     .nogp
652
@@:
653
        mov     eax, [edx]
654
        mov     word [esp+v86_regs.eflags], ax
655
        add     word [esp+v86_regs.esp], 4
656
        add     word [esp+v86_regs.eip], 2
657
        popad
658
        iretd
709 diamond 659
.handle_cli:
660
        and     byte [esp+v86_regs.eflags+1], not 2
661
        inc     word [esp+v86_regs.eip]
662
        popad
663
        iretd
664
.handle_sti:
665
        or      byte [esp+v86_regs.eflags+1], 2
666
        inc     word [esp+v86_regs.eip]
667
        popad
668
        iretd
669
.handle_rep:
670
        cmp     word [esp+v86_regs.eip], 0xFFFF
671
        jae     .nogp
672
        lodsb
673
        cmp     al, 6Eh
674
        jz      .handle_rep_outsb
675
        jmp     .nogp
676
.handle_rep_outsb:
677
.handle_in:
678
.handle_out:
679
.invalid_io_byte:
680
        movzx   ebx, word [esp+v86_regs.edx]
681
        mov     ecx, 1
682
        jmp     .invalid_io
683
.handle_in_imm:
684
.handle_out_imm:
685
        cmp     word [esp+v86_regs.eip], 0xFFFF
686
        jae     .nogp
687
        lodsb
688
        movzx   ebx, al
689
        mov     ecx, 1
690
        jmp     .invalid_io
691
.handle_66:
692
        cmp     word [esp+v86_regs.eip], 0xFFFF
693
        jae     .nogp
694
        lodsb
770 diamond 695
        cmp     al, 0x9C
696
        jz      .handle_pushfd
697
        cmp     al, 0x9D
698
        jz      .handle_popfd
709 diamond 699
        cmp     al, 0xEF
700
        jz      .handle_out_dword
701
        cmp     al, 0xED
702
        jz      .handle_in_dword
703
        jmp     .nogp
704
.handle_in_word:
705
.handle_out_word:
706
        movzx   ebx, word [esp+v86_regs.edx]
707
        mov     ecx, 2
708
        jmp     .invalid_io
709
.handle_in_dword:
710
.handle_out_dword:
711
.invalid_io_dword:
712
        movzx   ebx, word [esp+v86_regs.edx]
713
        mov     ecx, 4
714
.invalid_io:
715
        mov     esi, v86_io_str1
716
        call    sys_msg_board_str
717
        mov     eax, ebx
718
        call    sys_msg_board_dword
719
        mov     esi, v86_io_byte
720
        cmp     ecx, 1
721
        jz      @f
722
        mov     esi, v86_io_word
723
        cmp     ecx, 2
724
        jz      @f
725
        mov     esi, v86_io_dword
726
@@:
727
        call    sys_msg_board_str
728
if DEBUG_SHOW_IO
729
        mov     edx, ebx
730
        mov     ebx, 200
731
        call    delay_hs
732
        mov     esi, [esp+v86_regs.size+10h+4]
733
        mov     eax, [esi+V86_machine.iopm]
734
@@:
735
        btr     [eax], edx
736
        inc     edx
737
        loop    @b
738
        popad
739
        iretd
740
else
741
        mov     eax, 2
742
        jmp     .exit
743
end if
744
.nogp:
745
 
746
        mov     esi, v86_exc_str1
747
        call    sys_msg_board_str
748
        mov     al, bl
749
        call    sys_msg_board_byte
750
        mov     esi, v86_exc_str2
751
        call    sys_msg_board_str
752
        mov     ax, [esp+32+4]
753
        call    sys_msg_board_word
754
        mov     esi, v86_exc_str3
755
        call    sys_msg_board_str
756
        mov     ax, [esp+32]
757
        call    sys_msg_board_word
758
        mov     esi, v86_exc_str4
759
        call    sys_msg_board_str
760
        mov     ecx, 8
761
        movzx   edx, word [esp+32+4]
762
        shl     edx, 4
763
        add     edx, [esp+32]
764
@@:
765
        mov     esi, [esp+v86_regs.size+10h+4]
766
        mov     eax, edx
767
        call    v86_get_lin_addr
768
        cmp     eax, 0x1000
769
        jb      .nopage
770
        mov     esi, v86_exc_str3-2
771
        call    sys_msg_board_str
772
        mov     al, [edx]
773
        call    sys_msg_board_byte
774
        inc     edx
775
        loop    @b
776
        jmp     @f
777
.nopage:
778
        mov     esi, v86_exc_str5
779
        call    sys_msg_board_str
780
@@:
781
        mov     esi, v86_newline
782
        call    sys_msg_board_str
783
        mov     eax, 1
784
        jmp     .exit
785
 
786
.done:
787
        xor     eax, eax
788
 
789
.exit:
790
        mov     [esp+v86_regs.size+10h+1Ch], eax
791
        mov     [esp+v86_regs.size+10h+18h], ebx
792
 
793
        mov     edx, [esp+v86_regs.size+10h+14h]
794
        cmp     edx, -1
795
        jz      @f
796
        dec     [v86_irqhooks+edx*8+4]
797
        jnz     @f
798
        and     [v86_irqhooks+edx*8], 0
799
@@:
800
 
801
        mov     esi, esp
802
        mov     edi, [esi+v86_regs.size+10h+10h]
803
        add     edi, v86_regs.size
804
        mov     ecx, v86_regs.size/4
805
        rep     movsd
806
        mov     esp, esi
807
 
808
        cli
809
        mov     ecx, [CURRENT_TASK]
810
        shl     ecx, 8
811
        pop     eax
812
        mov     [SLOT_BASE+ecx+APPDATA.saved_esp0], eax
813
        mov     [tss._esp0], eax
814
        pop     eax
815
        mov     [SLOT_BASE+ecx+APPDATA.dir_table], eax
816
        pop     ebx
817
        mov     dword [SLOT_BASE+ecx+APPDATA.io_map+4], ebx
818
        mov     dword [page_tabs + (tss._io_map_1 shr 10)], ebx
819
        pop     ebx
820
        mov     dword [SLOT_BASE+ecx+APPDATA.io_map], ebx
821
        mov     dword [page_tabs + (tss._io_map_0 shr 10)], ebx
822
        mov     cr3, eax
823
;        mov     [irq_tab+5*4], 0
824
        sti
825
 
826
        popad
827
        ret
828
 
829
;my05:
830
;        mov     dx, 30C2h
831
;        mov     cx, 4
832
;.0:
833
;        in      al, dx
834
;        cmp     al, 0FFh
835
;        jz      @f
836
;        test    al, 4
837
;        jnz     .1
838
;@@:
839
;        add     dx, 8
840
;        in      al, dx
841
;        cmp     al, 0FFh
842
;        jz      @f
843
;        test    al, 4
844
;        jnz     .1
845
;@@:
846
;        loop    .0
847
;        ret
848
;.1:
849
;        or      al, 84h
850
;        out     dx, al
851
;.2:
852
;        mov     dx, 30F7h
853
;        in      al, dx
854
;        mov     byte [BOOT_VAR + 48Eh], 0FFh
855
;        ret
856
 
857
v86_irq:
785 diamond 858
; push irq/pushad/jmp v86_irq
709 diamond 859
; eax = irq
789 diamond 860
        lea     esi, [esp+1Ch]
709 diamond 861
        lea     edi, [esi+4]
785 diamond 862
        mov     ecx, 8
709 diamond 863
        std
864
        rep     movsd
865
        cld
788 diamond 866
        mov     edi, eax
709 diamond 867
        pop     eax
868
        mov     esi, [v86_irqhooks+edi*8]       ; get VM handle
869
        mov     eax, [esi+V86_machine.pagedir]
870
        call    get_pg_addr
871
        mov     ecx, [CURRENT_TASK]
872
        shl     ecx, 8
873
        cmp     [SLOT_BASE+ecx+APPDATA.dir_table], eax
874
        jnz     .notcurrent
875
        lea     eax, [edi+8]
876
        cmp     al, 10h
877
        jb      @f
724 diamond 878
        add     al, 60h
709 diamond 879
@@:
880
        jmp     v86_exc_c.simulate_int
881
.notcurrent:
882
        mov     ebx, SLOT_BASE + 0x100
883
        mov     ecx, [TASK_COUNT]
884
.scan:
885
        cmp     [ebx+APPDATA.dir_table], eax
886
        jnz     .cont
887
        push    ecx
888
        mov     ecx, [ebx+APPDATA.saved_esp0]
889
        cmp     word [ecx-v86_regs.size+v86_regs.esp], 6
890
        jb      .cont2
891
        movzx   edx, word [ecx-v86_regs.size+v86_regs.ss]
892
        shl     edx, 4
893
        push    eax
894
        movzx   eax, word [ecx-v86_regs.size+v86_regs.esp]
895
        sub     eax, 6
896
        add     edx, eax
897
        mov     eax, edx
898
        call    v86_get_lin_addr
899
        cmp     eax, 0x1000
900
        jb      .cont3
901
        lea     eax, [edx+5]
902
        call    v86_get_lin_addr
903
        cmp     eax, 0x1000
904
        jb      .cont3
905
        pop     eax
906
        pop     ecx
907
        jmp     .found
908
.cont3:
909
        pop     eax
910
.cont2:
911
        pop     ecx
912
.cont:
913
        loop    .scan
914
        mov     al, 20h
915
        out     20h, al
916
        cmp     edi, 8
917
        jb      @f
918
        out     0A0h, al
919
@@:
920
        popad
921
        iretd
922
.found:
923
        mov     cr3, eax
924
        sub     word [esi-v86_regs.size+v86_regs.esp], 6
925
        mov     ecx, [esi-v86_regs.size+v86_regs.eip]
926
        mov     word [edx], cx
927
        mov     ecx, [esi-v86_regs.size+v86_regs.cs]
928
        mov     word [edx+2], cx
929
        mov     ecx, [esi-v86_regs.size+v86_regs.eflags]
930
        mov     word [edx+4], cx
931
        lea     eax, [edi+8]
932
        cmp     al, 10h
933
        jb      @f
724 diamond 934
        add     al, 60h
709 diamond 935
@@:
936
        mov     cx, [eax*4]
937
        mov     word [esi-v86_regs.size+v86_regs.eip], cx
938
        mov     cx, [eax*4+2]
939
        mov     word [esi-v86_regs.size+v86_regs.cs], cx
940
        and     byte [esi-v86_regs.size+v86_regs.eflags+1], not 3
941
        push    ebx
942
        call    update_counters
943
        pop     ebx
944
        sub     ebx, SLOT_BASE
945
        shr     ebx, 8
946
        mov     esi, [CURRENT_TASK]
947
        call    do_change_task
948
        popad
949
        iretd