Subversion Repositories Kolibri OS

Rev

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

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