Subversion Repositories Kolibri OS

Rev

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