Subversion Repositories Kolibri OS

Rev

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