Subversion Repositories Kolibri OS

Rev

Rev 712 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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