Subversion Repositories Kolibri OS

Rev

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