home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1998 November / VPR9811A.BIN / BENCH / CWSDPMI2 / CWSDPMI2.LZH / SRC.LZH / TABLES.ASM < prev    next >
Assembly Source File  |  1996-07-31  |  11KB  |  453 lines

  1. ; Copyright (C) 1995,1996 CW Sandmann (sandmann@clio.rice.edu) 1206 Braelinn, Sugarland, TX 77479
  2. ; Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  3. ;
  4. ; This file is distributed under the terms listed in the document
  5. ; "copying.cws", available from CW Sandmann at the address above.
  6. ; A copy of "copying.cws" should accompany this file; if not, a copy
  7. ; should be available from where this file was obtained.  This file
  8. ; may not be distributed without a verbatim copy of "copying.cws".
  9. ;
  10. ; This file is distributed WITHOUT ANY WARRANTY; without even the implied
  11. ; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12.  
  13.     title    tables
  14.     include segdefs.inc
  15.     include tss.inc
  16.     include gdt.inc
  17.  
  18. ;------------------------------------------------------------------------
  19.  
  20.     start_data16
  21.  
  22.     extrn    _tss_ptr:word
  23.     extrn    _was_exception:byte
  24.     extrn    _hard_master_lo:byte
  25.     extrn    _npx:byte
  26.     extrn    _DPMIsp:word
  27.  
  28. has_error    db    1,0,1,1,1,1,1,0
  29.  
  30.     end_data16
  31.  
  32. ;------------------------------------------------------------------------
  33.  
  34.     start_bss
  35.  
  36.     public    _i_tss
  37. _i_tss    label    tss_s
  38.     db    type tss_s dup (?)
  39.  
  40. ivec_number    dw    ?
  41.  
  42.     extrn    _locked_stack:dword
  43.     extrn    _locked_count:byte
  44.     extrn    _user_interrupt_handler:fword
  45.     extrn    _dpmisim_regs:dword
  46.     end_bss
  47.  
  48. ;------------------------------------------------------------------------
  49.  
  50.     start_code16
  51.     extrn    _user_interrupt_return:near
  52.  
  53. ; Code size reduction (improved) by Morten Welinder
  54.  
  55.     public    _ivec0, _ivec1
  56. ;    align    4        ; fix segdefs
  57. _ivec0:
  58.     push    ds        ; 1 byte
  59.     call    ivec_common    ; 3 bytes
  60. _ivec1:
  61. rept 255
  62.     push    ds        ; 1 byte
  63.     call    ivec_common    ; 3 bytes
  64. endm
  65.  
  66. ivec_common:
  67.     push    g_pdata
  68.     pop    ds
  69.     pop    ivec_number
  70.     sub    ivec_number, offset _ivec1    ; pushes address *after* call
  71.     shr    ivec_number, 2
  72.     pop    ds
  73.     jmpt    g_itss            ; macro for jump to task segment itss
  74.  
  75. ; Task set up with ds = g_rdata, interrupts disabled
  76.     public    _interrupt_common
  77. _interrupt_common:
  78.     mov    bx,_tss_ptr
  79.     mov    ax,ivec_number
  80.     mov    [bx].tss_irqn,al
  81.     mov    esi,[bx].tss_esp
  82.     mov    fs,[bx].tss_ss        ; fs:esi -> stack
  83.     cmp    al,15
  84.     ja    short has_no_error
  85.     sub    al,8
  86.     jb    short has_no_error
  87.     mov    di,ax            ; DI has the IRQ value now
  88.     cmp    has_error[di],0
  89.     je    short check_SW_int
  90.     mov    ax,fs:[esi+8]
  91.     and    ah,30h            ; Flags IOPL if SW int, CS if exception
  92.     cmp    ah,30h
  93.     je    check_SW_int        ; We don't have selectors this large !
  94.     mov    eax,fs:[esi]
  95.     mov    [bx].tss_error,eax
  96.     add    esi,4
  97.     mov    eax,cr2            ; For page faults
  98.     mov    [bx].tss_cr2,eax
  99.     jmp    short has_no_error
  100. check_SW_int:
  101.     lgs    edi,fs:[esi]        ; CS:EIP -> GS:EDI
  102.     mov    ax,gs:[edi-2]        ; Get two bytes before; Int 0x??
  103.     cmp    al,0cdh            
  104.     jne    short has_no_error
  105.     cmp    [bx].tss_irqn,ah
  106.     jne    short has_no_error    ; Not a SW interrupt
  107.     mov    cx,di
  108.     add    cl,_hard_master_lo    ; SW int in range 8-15 redirected
  109.     mov    [bx].tss_irqn,cl    
  110. has_no_error:
  111.     mov    eax,fs:[esi]        ; eip
  112.     mov    [bx].tss_eip,eax
  113.     mov    eax,fs:[esi+8]
  114.     mov    [bx].tss_eflags,eax
  115.     mov    ax,fs:[esi+4]
  116.     mov    cx,[bx].tss_cs
  117.     mov    [bx].tss_cs,ax
  118.     add    esi,12
  119.     xor    ax,cx            ; Are low 3 bits equal?
  120.     test    al,3            ; Our CPL = 0; is their CS RPL ?
  121.     jz    short same_privilege
  122.     mov    ax,fs:[esi+4]        ; saved SS
  123.     mov    [bx].tss_ss,ax
  124.     mov    esi,fs:[esi]        ; saved SP
  125. same_privilege:
  126.     mov    [bx].tss_esp,esi    ; store corrected stack pointer
  127.     mov    _was_exception,1
  128.     xor    eax,eax
  129.     mov    fs,ax            ; just in case it becomes invalid!
  130.     mov    gs,ax            ; just in case it becomes invalid!
  131.     mov    cr2,eax            ; so we can tell INT 0E from page fault
  132.     jmpt    g_ctss            ; pass control back to real mode
  133.     jmp    _interrupt_common    ; it's a task
  134.  
  135. IF run_ring EQ 0
  136. ; Task set up with ds = g_rdata, interrupts disabled
  137.     public    _double_fault
  138. _double_fault:
  139.     mov    bx,_tss_ptr
  140.     mov    [bx].tss_irqn,8        ; double fault
  141.     pop    [bx].tss_error        ; dword
  142.     mov    _was_exception,1
  143.     jmpt    g_ctss
  144.     jmp    short _double_fault
  145. ENDIF
  146.  
  147. ;------------------------------------------------------------------------
  148. ;    This code takes HW interrupts which must be handled at Ring 0 to
  149. ;    make sure the stack is valid and converts them to Ring 3 user 
  150. ;    interrupt handlers on the locked stack.  This code assumes a 
  151. ;    ring transition (since we run with interrrupts disabled at our 
  152. ;    ring 0 code) but probably should be fixed to jump to the ivec
  153. ;    handler in that case.
  154.  
  155.     public    _irq0, _irq1
  156. ;    align    4        ; fix segdefs
  157.  
  158. irq    macro    n
  159.     push    n            ; 2 bytes
  160.     jmp    short irq_common    ; 2 bytes
  161.     endm
  162. _irq0:
  163.     irq    0
  164. _irq1:
  165.     x=6
  166.     rept 15
  167.      irq    x
  168.      x=x+6
  169.     endm
  170.  
  171. irq_common:
  172. IF run_ring EQ 0
  173. ; Interrupts are disabled; the 32-bit IRET 3 dwords (and irq#) on the stack.
  174. ; Copy it to the locked stack adding the 2 stack dwords or move it down.
  175. ; user_interrupt_return emulates an IRET changing stacks on the same ring.
  176.     push    ds
  177.     push    g_pdata
  178.     pop    ds
  179.  
  180.     cmp    _locked_count,0        ; If on locked stack, OK
  181.     jne    short already_locked
  182.     mov    dword ptr _locked_stack+4064,edi    ;Save edi
  183.     lea    edi,_locked_stack+4064    ; Locked stack - 20 - 12
  184.     mov    [edi+4],eax        ; saved eax
  185.     mov    eax,[esp]        ; ds/irq
  186.     mov    [edi+8],eax
  187.     mov    eax,[esp+4]        ; offset
  188.     mov    [edi+12],eax
  189.     mov    eax,[esp+8]        ; selector
  190.     mov    [edi+16],eax
  191.     mov    eax,[esp+12]        ; flags
  192.     mov    [edi+20],eax
  193.     lea    eax,[esp+16]
  194.     mov    [edi+24],eax
  195.     mov    [edi+28],ss
  196.     mov    ax,ds
  197.     mov    ss,ax
  198.     mov    esp,edi            ; Now on locked stack
  199.     pop    edi
  200.     jmp    short @f1
  201. already_locked:
  202.     sub    esp,8            ; Room for ESP:SS
  203.     push    eax
  204.     mov    eax,[esp+12]
  205.     mov    [esp+4],eax        ; ds/irq
  206.     mov    eax,[esp+16]
  207.     mov    [esp+8],eax        ; offset
  208.     mov    eax,[esp+20]
  209.     mov    [esp+12],eax        ; selector
  210.     mov    eax,[esp+24]
  211.     mov    [esp+16],eax        ; flags
  212.     lea    eax,[esp+28]
  213.     mov    [esp+20],eax
  214.     mov    [esp+24],ss
  215. @f1:
  216.     inc    _locked_count
  217. ;    At this point we have two dwords on new stack
  218.     sub    esp,24
  219.     mov    eax,[esp+24]
  220.     mov    [esp],eax        ; saved eax
  221.     mov    eax,[esp+28]
  222.     mov    [esp+4],eax        ; saved ds/irq
  223.  
  224.     mov    dword ptr [esp+20],offset _TEXT:_user_interrupt_return
  225.     mov    word ptr [esp+24],g_pcode
  226.     mov    dword ptr [esp+28],3002h
  227.  
  228.     xchg    bx,[esp+6]        ; IRQ # times size in BX
  229.     mov    eax,dword ptr _user_interrupt_handler[bx]
  230.     mov    dword ptr [esp+8],eax
  231.     mov    ax,word ptr _user_interrupt_handler[bx+4]
  232.     mov    word ptr [esp+12],ax
  233.     mov    dword ptr [esp+16],3002h
  234.  
  235.     pop    eax
  236.     pop    ds
  237.     pop    bx
  238.     iretd
  239. ELSE
  240. ; Our stack will be ring 0 at end of TSS after ring change; interrupts are 
  241. ; disabled.  We have the 32-bit ring change IRET structure on the stack.
  242. ; Copy it to the ring 3 stack; user_interrupt_return emulates an IRET 
  243. ; changing stacks on the same ring.
  244.     push    bp
  245.     mov    bp,sp
  246.     push    ds
  247.     push    es
  248.  
  249.     push    esi
  250.     push    edi
  251.     push    ecx
  252.  
  253.     push    g_pdata
  254.     pop    ds
  255.  
  256.     cmp    _locked_count,0        ; If on locked stack, OK
  257.     jne    short already_locked
  258.     lea    edi,_locked_stack+4076    ; Locked stack - 20
  259.     push    g_pdata
  260.     pop    es
  261.     jmp    short @f1
  262. already_locked:
  263.     mov    edi,[bp+16]        ; Saved ESP
  264.     mov    es,[bp+20]        ; Saved SS
  265.     sub    edi,20            ; Make room on current locked stack
  266. @f1:
  267.     inc    _locked_count
  268.     mov    ecx,5            ; 20 bytes
  269.     movzx    esi,bp
  270.     add    si,4            ; SS:ESI (adjust for local pushes)
  271.     cld
  272.     rep    movs dword ptr es:[edi],dword ptr ss:[esi]    ;ecx count
  273.     sub    edi,32            ; 20 bytes + 12 more for iret frame
  274.     mov    dword ptr es:[edi+8],3002h
  275.     mov    word ptr es:[edi+4],g_pcode
  276.     mov    dword ptr es:[edi],offset _TEXT:_user_interrupt_return
  277.     
  278.     xchg    bx,[bp+2]        ; IRQ # times size in BX
  279.     mov    ecx,dword ptr _user_interrupt_handler[bx]
  280.     mov    dword ptr [bp+4],ecx
  281.     mov    cx,word ptr _user_interrupt_handler[bx+4]
  282.     mov    word ptr [bp+8],cx
  283.     mov    word ptr [bp+12],3002h
  284.     mov    dword ptr [bp+16],edi    ; The new ESP
  285.     mov    word ptr [bp+20],es    ; The new SS
  286.  
  287.     pop    ecx
  288.     pop    edi
  289.     pop    esi
  290.     pop    es
  291.     pop    ds
  292.     pop    bp
  293.     pop    bx
  294.     iretd
  295. ENDIF
  296.  
  297. IFDEF I31PROT
  298. extrn _i_31prot:near
  299.  
  300. ; Note for later: since we may be changing descriptors we should make sure that
  301. ; all segment registers are reloaded.  Ones that are no longer valid are zeroed.
  302.  
  303.     public    _ivec31
  304. _ivec31:
  305.     cmp    ah,3
  306.     jne    _ivec0 + 31h * (_ivec1 - _ivec0)
  307.     cmp    al,2
  308.     jg    _ivec0 + 31h * (_ivec1 - _ivec0)
  309. ; Real mode call - ES:EDI points to structure
  310. ; Set up DS:ESI to point to their copy, ES:EDI to ours
  311.     push    ds es esi edi ecx
  312.     push    es
  313.     pop    ds
  314.     mov    esi,edi
  315.     mov    cx,g_pdata
  316.     mov    es,cx
  317.     mov    edi,offset DGROUP:_dpmisim_regs
  318.     mov    ecx,25
  319.     cld
  320.     rep    movs word ptr es:[edi],word ptr ds:[esi]
  321.     pop    ecx edi esi es ds
  322.     jmp    _ivec0 + 31h * (_ivec1 - _ivec0)
  323.  
  324. ; This is where we return to restore the register structure
  325. ; Because of a bug in GO32 V1.10 & V1.11, we can't touch the user stack!
  326.     public    _ivec31x
  327.     public    _i30x_jump
  328.     public    _i30x_stack
  329.     public    _i30x_sti
  330. _ivec31x:
  331. ; Real mode return - ES:EDI points to structure
  332. ; Set up DS:ESI to point to to our copy
  333.     pushf
  334.     push    ds esi edi ecx
  335.     mov    cx,g_pdata
  336.     mov    ds,cx
  337.     mov    esi,offset DGROUP:_dpmisim_regs
  338.     mov    ecx,21            ; don't update CS:IP or SS:SP
  339.     cld
  340.     rep    movs word ptr es:[edi],word ptr ds:[esi]
  341.     pop    ecx edi esi ds
  342.     popf
  343.     lss    esp,fword ptr cs:_i30x_stack
  344. _i30x_sti    db    ?
  345.     db    66h, 0eah                ; far jmp to 32 bit
  346. _i30x_jump    dd    ?
  347.     dw    ?
  348. _i30x_stack    dd    ?
  349.     dw    ?
  350.     
  351. ENDIF
  352.  
  353.     public    _ivec7
  354. _ivec7:
  355.     clts
  356. ;    push    eax
  357. ;    mov    eax,cr0
  358. ;    and    al,0F3h            ; Clear EM & TS bits
  359. ;    mov    cr0,eax
  360. ;    pop    eax
  361.     iretd
  362.  
  363.     public    _real_i8
  364. _real_i8:
  365.     int    08h
  366.     iret
  367.     int    09h
  368.     iret
  369.     int    0ah
  370.     iret
  371.     int    0bh
  372.     iret
  373.     int    0ch
  374.     iret
  375.     int    0dh
  376.     iret
  377.     int    0eh
  378.     iret
  379.     int    0fh
  380.     iret
  381.  
  382. ; Improved code by Morten Welinder.  CWS note: We must save bp si di here, 
  383. ; (since called by TC).
  384.  
  385.     public    _generic_handler
  386. _generic_handler:
  387.     push    bp si di
  388.     push    _DPMIsp        ; Needed for RMCB's to be recursive
  389.     mov    _DPMIsp,sp
  390.     sub    _DPMIsp,spare_stack    ; space + extra for HW interrupt
  391.     push    ds
  392.     mov    bx,_tss_ptr
  393.     mov    ax,word ptr [bx].tss_eflags
  394.     and    ax,0011111011010101b        ; user flags
  395.     push    ax
  396.     push    cs
  397.     call    generic1            ; ax, cs, "call" makes iret
  398.     pushf
  399.     cli
  400.     push    ebx
  401.     mov    bx,_tss_ptr
  402.     mov    [bx].tss_eax,eax
  403.     mov    [bx].tss_ecx,ecx
  404.     mov    [bx].tss_edx,edx
  405.     mov    [bx].tss_esi,esi
  406.     mov    [bx].tss_edi,edi
  407.     mov    [bx].tss_ebp,ebp
  408.     pop    dword ptr [bx].tss_ebx
  409.     pop    ax
  410.     mov    dx,0000111011010101b        ; user flags
  411.     mov    cx,word ptr [bx].tss_eflags
  412.     and    ax,dx
  413.     not    dx
  414.     and    cx,dx
  415.     or    ax,cx
  416.     mov    word ptr [bx].tss_eflags,ax
  417.  
  418.     pop    ds
  419.     pop    _DPMIsp
  420.     pop    di si bp
  421.     xor    ax,ax
  422.     retn
  423.  
  424. ; Simulate interrupt call setup (bigger/slower than self modifying code,
  425. ; but I may need it with hw interrupt callbacks)
  426. generic1:
  427.     and    ah,not 2
  428.     push    ax                ; Flags with IF=0
  429.     xor    cx,cx
  430.     mov    es,cx    
  431.     mov    cl,[bx].tss_irqn
  432.     shl    cx,2
  433.     mov    di,cx
  434.     push    dword ptr es:[di]        ; CS:IP of int handler
  435.  
  436. ; DS & ES are undefined -- could use segment translation but don't bother
  437.  
  438.     mov    eax,[bx].tss_eax
  439.     mov    ecx,[bx].tss_ecx
  440.     mov    edx,[bx].tss_edx
  441.     mov    esi,[bx].tss_esi
  442.     mov    edi,[bx].tss_edi
  443.     mov    ebp,[bx].tss_ebp
  444.     mov    ebx,[bx].tss_ebx
  445.  
  446.     iret                    ; Actually an "int tss_irqn"
  447.  
  448.     end_code16
  449.  
  450. ;------------------------------------------------------------------------
  451.  
  452.     end
  453.