Subversion Repositories Kolibri OS

Rev

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