Subversion Repositories Kolibri OS

Rev

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