Subversion Repositories Kolibri OS

Rev

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