Subversion Repositories Kolibri OS

Rev

Rev 5363 | Rev 6333 | Go to most recent revision | 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: 6016 $
  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, 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
  48.         call    kernel_alloc
  49.         test    eax, eax
  50.         jz      .fail2
  51.  
  52.         mov     [ebx+V86_machine.iopm], eax
  53.  
  54.  
  55. ; initialize tables
  56.         push    edi
  57.         mov     edi, eax
  58.         mov     eax, -1
  59.         mov     ecx, 2000h/4
  60.         rep stosd
  61.  
  62.         mov     eax, [ebx+V86_machine.process]
  63.         mov     eax, [eax+PROC.pdt_0_phys]
  64.  
  65.         pushfd
  66.         cli
  67.         mov     cr3, eax
  68.  
  69.  
  70. ; now V86 specific: initialize known addresses in first Mb
  71.  
  72. ; first page - BIOS data (shared between all machines!)
  73. ; physical address = 0
  74. ; linear address = OS_BASE
  75. ; page before 0xA0000 - Extended BIOS Data Area (shared between all machines!)
  76. ; physical address = 0x9C000
  77. ; linear address = 0x8009C000
  78. ; (I have seen one computer with EBDA segment = 0x9D80,
  79. ; all other computers use less memory)
  80.  
  81.         mov     eax, PG_UWR
  82.         mov     [page_tabs], eax
  83.         invlpg  [eax]
  84.  
  85.         mov     byte [0x500], 0xCD
  86.         mov     byte [0x501], 0x13
  87.         mov     byte [0x502], 0xF4
  88.         mov     byte [0x503], 0xCD
  89.         mov     byte [0x504], 0x10
  90.         mov     byte [0x505], 0xF4
  91.  
  92.         mov     eax, 0x98000+PG_UWR
  93.         mov     edi, page_tabs+0x98*4
  94.         mov     edx, 0x1000
  95.         mov     ecx, 8
  96. @@:
  97.         stosd
  98.         add     eax, edx
  99.         loop    @b
  100.  
  101. ; addresses 0xC0000 - 0xFFFFF - BIOS code (shared between all machines!)
  102. ; physical address = 0xC0000
  103.  
  104.         mov     eax, 0xC0000+PG_UWR
  105.         mov     edi, page_tabs+0xC0*4
  106.         mov     ecx, 64
  107. @@:
  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.  
  120.         mov     eax, ebx
  121.         ret
  122. .fail2:
  123.         mov     eax, ebx
  124.         call    free
  125. .fail:
  126.         xor     eax, eax
  127.         ret
  128.  
  129. ;not used
  130. ; Destroy V86 machine
  131. ; in: eax = handle
  132. ; out: nothing
  133. ; destroys: eax, ebx, ecx, edx (due to free)
  134. ;v86_destroy:
  135. ;        push    eax
  136. ;        stdcall kernel_free, [eax+V86_machine.pagedir]
  137. ;        pop     eax
  138. ;        jmp     free
  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
  149.         mov     edx, [page_tabs+ecx*4]
  150.         and     eax, 0xFFF
  151.         and     edx, 0xFFFFF000
  152.         or      eax, edx
  153.         pop     edx ecx
  154.         ret
  155.  
  156. ;not used
  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
  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
  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
  178. ; недописана!!!
  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
  198. ;        cmp     dword [edx+4],
  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
  221.         rep stosd
  222. end if
  223. .ret:
  224.         ret
  225.  
  226. struct  v86_regs
  227. ; don't change the order, it is important
  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
  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:
  258.  
  259.         pushad
  260.  
  261.         cli
  262.  
  263.         mov     ecx, [current_slot]
  264.  
  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.  
  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
  277.  
  278.         mov     eax, [esi+V86_machine.iopm]
  279.         add     eax, 0x1000
  280.         call    get_pg_addr
  281.         inc     eax
  282.         mov     dword [ecx+APPDATA.io_map+4], eax
  283.         mov     dword [page_tabs + (tss._io_map_1 shr 10)], eax
  284.  
  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]
  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
  297.         sub     esp, sizeof.v86_regs
  298.         mov     esi, ebx
  299.         mov     edi, esp
  300.         mov     ecx, sizeof.v86_regs/4
  301.         rep movsd
  302.  
  303.         cmp     edx, -1
  304.         jz      .noirqhook
  305. uglobal
  306. v86_irqhooks    rd      IRQ_RESERVED * 2
  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
  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
  341. endg
  342.  
  343. v86_exc_c:
  344. ; Did we all that we have wanted to do?
  345.         cmp     bl, 1
  346.         jne     @f
  347.         xor     eax, eax
  348.         mov     dr6, eax
  349.   @@:
  350.         mov     eax, [esp+sizeof.v86_regs+10h+18h]
  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)
  365. ; Если бы мы могли схлопотать исключение только из-за чтения байтов кода,
  366. ; мы бы его уже схлопотали и это было бы не #GP
  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
  422.         mov     esi, [esp+4+sizeof.v86_regs+10h+4]
  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]
  438.         cmp     byte [esp+1], 0
  439.         jnz     @f
  440.         inc     eax
  441.         inc     eax
  442. @@:
  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
  449.         mov     ah, 0
  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
  470.         mov     esi, [esp+sizeof.v86_regs+10h+4]
  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
  506.         mov     esi, [esp+sizeof.v86_regs+10h+4]
  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
  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
  538.         mov     esi, [esp+sizeof.v86_regs+10h+4]
  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
  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
  569.         mov     esi, [esp+sizeof.v86_regs+10h+4]
  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
  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
  600.         mov     esi, [esp+sizeof.v86_regs+10h+4]
  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
  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
  656.         cmp     al, 0x9C
  657.         jz      .handle_pushfd
  658.         cmp     al, 0x9D
  659.         jz      .handle_popfd
  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. @@:
  726.         mov     esi, [esp+sizeof.v86_regs+10h+4]
  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:
  751.         mov     [esp+sizeof.v86_regs+10h+1Ch], eax
  752.         mov     [esp+sizeof.v86_regs+10h+18h], ebx
  753.  
  754.         mov     edx, [esp+sizeof.v86_regs+10h+14h]
  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
  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
  767.         mov     esp, esi
  768.  
  769.         cli
  770.         mov     ecx, [current_slot]
  771.         pop     eax
  772.  
  773.         mov     [ecx+APPDATA.saved_esp0], eax
  774.         mov     [tss._esp0], eax
  775.         pop     eax
  776.         mov     [ecx+APPDATA.process], eax
  777.         mov     [current_process], eax
  778.         pop     ebx
  779.         mov     dword [ecx+APPDATA.io_map+4], ebx
  780.         mov     dword [page_tabs + (tss._io_map_1 shr 10)], ebx
  781.         pop     ebx
  782.         mov     dword [ecx+APPDATA.io_map], ebx
  783.         mov     dword [page_tabs + (tss._io_map_0 shr 10)], ebx
  784.         mov     eax, [eax+PROC.pdt_0_phys]
  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.  
  819. align 4
  820. v86_irq:
  821. ; push irq/pushad/jmp v86_irq
  822. ; ebp = irq
  823.         lea     esi, [esp+1Ch]
  824.         lea     edi, [esi+4]
  825.         mov     ecx, 8
  826.         std
  827.         rep movsd
  828.         cld
  829.         mov     edi, ebp
  830.         pop     eax
  831. v86_irq2:
  832.         mov     esi, [v86_irqhooks+edi*8]       ; get VM handle
  833.         mov     eax, [esi+V86_machine.process]
  834.         mov     ecx, [CURRENT_TASK]
  835.         shl     ecx, 8
  836.         cmp     [SLOT_BASE+ecx+APPDATA.process], eax
  837.         jnz     .notcurrent
  838.         lea     eax, [edi+8]
  839.         cmp     al, 10h
  840.         mov     ah, 1
  841.         jb      @f
  842.         add     al, 60h
  843. @@:
  844.         jmp     v86_exc_c.simulate_int
  845. .notcurrent:
  846.         mov     ebx, SLOT_BASE + 0x100
  847.         mov     ecx, [TASK_COUNT]
  848. .scan:
  849.         cmp     [ebx+APPDATA.process], eax
  850.         jnz     .cont
  851.         push    ecx
  852.         mov     ecx, [ebx+APPDATA.saved_esp0]
  853.         cmp     word [ecx-sizeof.v86_regs+v86_regs.esp], 6
  854.         jb      .cont2
  855.         movzx   edx, word [ecx-sizeof.v86_regs+v86_regs.ss]
  856.         shl     edx, 4
  857.         push    eax
  858.         movzx   eax, word [ecx-sizeof.v86_regs+v86_regs.esp]
  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:
  877.         add     ebx, 0x100
  878.         loop    .scan
  879.         mov     ecx, edi
  880.         call    irq_eoi
  881.         popad
  882.         iretd
  883. .found:
  884.         mov     eax, [eax+PROC.pdt_0_phys]
  885.         mov     cr3, eax
  886.         mov     esi, [ebx+APPDATA.saved_esp0]
  887.         sub     word [esi-sizeof.v86_regs+v86_regs.esp], 6
  888.         mov     ecx, [esi-sizeof.v86_regs+v86_regs.eip]
  889.         mov     word [edx], cx
  890.         mov     ecx, [esi-sizeof.v86_regs+v86_regs.cs]
  891.         mov     word [edx+2], cx
  892.         mov     ecx, [esi-sizeof.v86_regs+v86_regs.eflags]
  893.         mov     word [edx+4], cx
  894.         lea     eax, [edi+8]
  895.         cmp     al, 10h
  896.         jb      @f
  897.         add     al, 60h
  898. @@:
  899.         mov     cx, [eax*4]
  900.         mov     word [esi-sizeof.v86_regs+v86_regs.eip], cx
  901.         mov     cx, [eax*4+2]
  902.         mov     word [esi-sizeof.v86_regs+v86_regs.cs], cx
  903.         and     byte [esi-sizeof.v86_regs+v86_regs.eflags+1], not 3
  904.         call    update_counters
  905.         lea     edi, [ebx + 0x100000000 - SLOT_BASE]
  906.         shr     edi, 3
  907.         add     edi, CURRENT_TASK
  908.         call    find_next_task.found
  909.         call    do_change_task
  910.         popad
  911.         iretd
  912.