Subversion Repositories Kolibri OS

Rev

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