Subversion Repositories Kolibri OS

Rev

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