Subversion Repositories Kolibri OS

Rev

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