Subversion Repositories Kolibri OS

Rev

Rev 4993 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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