Subversion Repositories Kolibri OS

Rev

Rev 6319 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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