Subversion Repositories Kolibri OS

Rev

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