Subversion Repositories Kolibri OS

Rev

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

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