Subversion Repositories Kolibri OS

Rev

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

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