Subversion Repositories Kolibri OS

Rev

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