Subversion Repositories Kolibri OS

Rev

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