Subversion Repositories Kolibri OS

Rev

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

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