Subversion Repositories Kolibri OS

Rev

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