[movitz-cvs] CVS update: movitz/losp/muerte/interrupt.lisp

Frode Vatvedt Fjeld ffjeld at common-lisp.net
Thu Aug 12 16:57:16 UTC 2004


Update of /project/movitz/cvsroot/movitz/losp/muerte
In directory common-lisp.net:/tmp/cvs-serv28233

Modified Files:
	interrupt.lisp 
Log Message:
Rename interrupt-frame- to dit-frame
("default-interrupt-trampoline-frame-"). Also, reworked the
default-interrupt-trampoline a bit, re-arranged the frame layout etc.

Date: Thu Aug 12 09:57:15 2004
Author: ffjeld

Index: movitz/losp/muerte/interrupt.lisp
diff -u movitz/losp/muerte/interrupt.lisp:1.19 movitz/losp/muerte/interrupt.lisp:1.20
--- movitz/losp/muerte/interrupt.lisp:1.19	Tue Jul 27 06:50:08 2004
+++ movitz/losp/muerte/interrupt.lisp	Thu Aug 12 09:57:15 2004
@@ -10,59 +10,77 @@
 ;;;; Author:        Frode Vatvedt Fjeld <frodef at acm.org>
 ;;;; Created at:    Wed Apr  7 01:50:03 2004
 ;;;;                
-;;;; $Id: interrupt.lisp,v 1.19 2004/07/27 13:50:08 ffjeld Exp $
+;;;; $Id: interrupt.lisp,v 1.20 2004/08/12 16:57:15 ffjeld Exp $
 ;;;;                
 ;;;;------------------------------------------------------------------
 
-(in-package #:muerte)
+(in-package muerte)
 
 (provide :muerte/interrupt)
 
-(defvar *last-interrupt-frame* nil)
+(defvar *last-dit-frame* nil)
 
-(defmacro stack-word (offset)
-  `(with-inline-assembly (:returns :eax)
-     (:movl (:esp ,(* 4 offset)) :eax)))
+(defun dit-frame-esp (dit-frame)
+  (+ dit-frame 6))
 
-(define-compiler-macro interrupt-frame-index (&whole form name &environment env)
+(defconstant +dit-frame-map+
+    '(nil :eflags :eip :error-code :exception-vector :ebp :funobj
+      :edi
+      :atomically-status
+      :atomically-esp
+      :scratch0      
+      :ecx :eax :edx :ebx :esi))
+
+(define-compiler-macro dit-frame-index (&whole form name &environment env)
   (let ((name (and (movitz:movitz-constantp name env)
 		   (movitz:movitz-eval name env))))
     (if (not name)
 	form
-      (- 5 (position name
-		     '(nil :eflags :eip :error-code :exception :ebp nil
-		       :ecx :eax :edx :ebx :esi :edi :atomically-status))))))
-
-(defun interrupt-frame-index (name)
-  (- 5 (position name
-		 '(nil :eflags :eip :error-code :exception :ebp nil
-		   :ecx :eax :edx :ebx :esi :edi :atomically-status))))
+      (- 5 (position name +dit-frame-map+)))))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defun dit-frame-index (name)
+    (- 5 (position name +dit-frame-map+)))
+  (defun dit-frame-offset (name)
+    (* 4 (dit-frame-index name))))
 
-(define-compiler-macro interrupt-frame-ref (&whole form reg type
+(define-compiler-macro dit-frame-ref (&whole form reg type
 					    &optional (offset 0)
-						      (frame '*last-interrupt-frame*)
+						      (frame '*last-dit-frame*)
 					    &environment env)
-  `(memref ,frame (+ (* 4 (interrupt-frame-index ,reg)) ,offset) 0 ,type))
+  `(memref ,frame (+ (dit-frame-offset ,reg) ,offset) 0 ,type))
 
-(defun interrupt-frame-ref (reg type &optional (offset 0) (frame *last-interrupt-frame*))
-  (interrupt-frame-ref reg type offset frame))
+(defun dit-frame-ref (reg type &optional (offset 0) (frame *last-dit-frame*))
+  (dit-frame-ref reg type offset frame))
 
-(defun (setf interrupt-frame-ref) (x reg type &optional (frame *last-interrupt-frame*))
-  (setf (memref frame (* 4 (interrupt-frame-index reg)) 0 type) x))
+(defun (setf dit-frame-ref) (x reg type &optional (frame *last-dit-frame*))
+  (setf (memref frame (dit-frame-offset reg) 0 type) x))
 
-(define-primitive-function default-interrupt-trampoline ()
-  "Default first-stage interrupt handler."
+(defun dit-frame-casf (dit-frame)
+  "Compute the `currently active stack-frame' when the interrupt occurred."
+  (let ((ebp (dit-frame-ref :ebp :lisp 0 dit-frame))
+	(esp (dit-frame-esp dit-frame)))
+    (if (< esp ebp)
+	ebp
+      (let ((next-ebp (memref ebp 0 0 :lisp)))
+	(check-type next-ebp fixnum)
+	(assert (< esp next-ebp))
+	next-ebp))))
+
+(define-primitive-function (default-interrupt-trampoline :symtab-property t) ()
+  "Default first-stage/trampoline interrupt handler. Assumes the IF flag in EFLAGS
+is off, e.g. because this interrupt/exception is routed through an interrupt gate."
   (macrolet
       ((do-it ()
 	 `(with-inline-assembly (:returns :multiple-values)
-	    ,@(loop for i from 0 to movitz::+idt-size+
+	    ,@(loop for i from 0 to 255
+		  append (list i)
 		  append (if (member i '(8 10 11 12 13 14 17))
-			     `(((5) :pushl ,i)
-			       ((5) :jmp 'ok))
-			   `(((2) :pushl 0) ; replace Error Code
-			     ((2) :pushl ,i)
-			     ((1) :nop)
-			     ((5) :jmp 'ok))))
+			     `((:pushl ,i)
+			       (:jmp 'ok))
+			   `((:pushl 0) ; replace Error Code
+			     (:pushl ,i)
+			     (:jmp 'ok))))
 	   ok
 	    ;; Stack:
 	    ;; 20: Interruptee EFLAGS (later EIP)
@@ -73,16 +91,16 @@
 	    ;;  0: EBP
 	    (:pushl :ebp)
 	    (:movl :esp :ebp)
-	    (:pushl 0)			; 0 means default-interrupt-trampoline frame
-	    (:pushl :ecx)		; -8
-	    (:pushl :eax)		; -12
-	    (:pushl :edx)		; -16
-	    (:pushl :ebx)		; -20
-	    (:pushl :esi)		; -24
+	    (:pushl 0)			; 0 'funobj' means default-interrupt-trampoline frame
 	    (:pushl :edi)		; -28
 	    (:movl ':nil-value :edi)	; We want NIL!
-	    (:locally (:pushl (:edi (:edi-offset atomically-status)))) ; -32
-	    (:locally (:pushl (:edi (:edi-offset atomically-esp)))) ; -36
+	    (:locally (:pushl (:edi (:edi-offset atomically-status))))
+	    (:locally (:pushl (:edi (:edi-offset atomically-esp))))
+	    (:locally (:pushl (:edi (:edi-offset scratch0))))
+	    ,@(loop for reg in (sort (copy-list '(:eax :ebx :ecx :edx :esi))
+				     #'>
+				     :key #'dit-frame-index)
+		  collect `(:pushl ,reg))
 
 	    (:locally (:movl 0 (:edi (:edi-offset atomically-status))))
 
@@ -110,7 +128,7 @@
 	    ;; Save/push thread-local values
 	    (:locally (:movl (:edi (:edi-offset num-values)) :ecx))
 	    (:jecxz 'push-values-done)
-	    (:leal (:edi #.(movitz::global-constant-offset 'values)) :eax)
+	    (:leal (:edi (:offset movitz-run-time-context values)) :eax)
 	   push-values-loop
 	    (:locally (:pushl (:eax)))
 	    (:addl 4 :eax)
@@ -120,12 +138,11 @@
 	    (:locally (:pushl (:edi (:edi-offset num-values))))
     
 	    ;; call handler
-	    (:movl (:ebp 4) :ecx)	; interrupt number into ECX
-	    (:locally (:movl (:edi (:edi-offset interrupt-handlers)) :eax))
-	    (:movl (:eax 2 (:ecx 4)) :esi) ; funobj at (aref EBX interrupt-handlers) into :esi
-	    (:movl :ebp :ebx)		; pass interrupt-frame as arg1
-	    (:movl (:ebp 4) :ecx)	; pass interrupt number as arg 0.
-	    (:leal ((:ecx ,movitz:+movitz-fixnum-factor+)) :eax)
+	    (:movl (:ebp ,(dit-frame-offset :exception-vector)) :ecx)
+	    (:locally (:movl (:edi (:edi-offset exception-handlers)) :eax))
+	    (:movl (:eax 2 (:ecx 4)) :esi) ; funobj at (aref ECX exception-handlers) into :esi
+	    (:movl :ebp :ebx)		; pass dit-frame as arg1
+	    (:leal ((:ecx ,movitz:+movitz-fixnum-factor+)) :eax) ; pass interrupt number as arg 0.
 	    (:call (:esi ,(bt:slot-offset 'movitz::movitz-funobj 'movitz::code-vector%2op)))
 
 	   skip-interrupt-handler
@@ -140,40 +157,43 @@
 	    (:jnz 'pop-values-loop)
 	   pop-values-done
 
-	    (:movl (:ebp -32) :ecx)	; Check interruptee's atomically status
+	    (:movl (:ebp ,(dit-frame-offset :atomically-status)) :ecx)
 	    (:testb :cl :cl)
 	    (:jnz 'restart-atomical-block)
 
 	    ;; Interrupted code was non-atomical, the normal case.
 	   normal-return		; With atomically-status-to-restore in ECX
 	    (:locally (:movl :ecx (:edi (:edi-offset atomically-status))))
-	    (:movl (:ebp -36) :ecx)	; Load interruptee's atomically-esp..
-	    (:locally (:movl :ecx (:edi (:edi-offset atomically-esp)))) ; ..and restore it.
-	    (:movl (:ebp -28) :edi)
-	    (:movl (:ebp -24) :esi)
-	    (:movl (:ebp -20) :ebx)
-	    (:movl (:ebp -16) :edx)
-	    (:movl (:ebp -12) :eax)
-	    (:movl (:ebp -8)  :ecx)
-	    ;; Make stack safe before we exit interrupt-frame..
+	    (:movl (:ebp ,(dit-frame-offset :atomically-esp)) :ecx)
+	    (:locally (:movl :ecx (:edi (:edi-offset atomically-esp))))
+	    (:movl (:ebp ,(dit-frame-offset :scratch0)) :ecx)
+	    (:locally (:movl :ecx (:edi (:edi-offset scratch0))))
+	    (:movl (:ebp ,(dit-frame-offset :edi)) :edi)
+	    (:movl (:ebp ,(dit-frame-offset :esi)) :esi)
+	    (:movl (:ebp ,(dit-frame-offset :ebx)) :ebx)
+	    (:movl (:ebp ,(dit-frame-offset :edx)) :edx)
+	    (:movl (:ebp ,(dit-frame-offset :eax)) :eax)
+	    (:movl (:ebp ,(dit-frame-offset :ecx)) :ecx)
+	    ;; Make stack safe before we exit dit-frame..
 	    (:movl :edi (:ebp 4))
 	    (:movl :edi (:ebp 8))
 	    (:movl :edi (:ebp 12))
+	    (:cli)			; Clear IF in EFLAGS before leaving dit-frame.
 	    (:leave)
 	    (:addl 12 :esp)
-	    (:popfl)			; pop EFLAGS
+	    (:popfl)			; pop EFLAGS (also resets IF)
 	    (:ret)			; pop EIP
     
 	   restart-atomical-block
 	    (:cmpb ,(bt:enum-value 'movitz::atomically-status :restart-primitive-function) :cl)
 	    (:jne 'not-simple-atomical-pf-restart)
-	    (:testl #xff00 :ecx)	; map of registers to restore
+	    (:testl #xfe00 :ecx)	; map of registers to restore
 	    (:jnz 'not-simple-atomical-pf-restart)
 	    (:sarl 16 :ecx)		; move atomically-status data into ECX
 	    (:movl (:edi (:ecx 4) ,(- (movitz:tag :null)))
 		   :ecx)		; This is the EIP to restart
 	    (:movl :ecx (:ebp 20))
-	    (:movl (:ebp -32) :ecx)
+	    (:movl (:ebp ,(dit-frame-offset :atomically-status)) :ecx)
 	    (:testl ,(bt:enum-value 'movitz::atomically-status :reset-status-p)
 		    :ecx)		; Should we reset status to zero?
 	    (:jnz 'normal-return)
@@ -187,9 +207,9 @@
 	    (:jnz 'atomically-esp-ok)
 	    ;; Generate the correct ESP for interruptee's atomically-esp
 	    (:leal (:ebp 24) :ecx)
-	    (:movl :ecx (:ebp -36))
+	    (:movl :ecx (:ebp ,(dit-frame-offset :atomically-esp)))
 	   atomically-esp-ok
-	    (:movl (:ebp -32) :ecx)
+	    (:movl (:ebp ,(dit-frame-offset :atomically-status)) :ecx)
 	    (:testl ,(bt:enum-value 'movitz::atomically-status :reset-status-p)
 		    :ecx)		; Should we reset status to zero?
 	    (:jnz 'atomically-jumper-return)
@@ -197,22 +217,22 @@
 	    
 	   atomically-jumper-return
 	    (:locally (:movl :ecx (:edi (:edi-offset atomically-status))))
-	    (:movl (:ebp -36) :ecx)	; Load interruptee's atomically-esp..
+	    (:movl (:ebp ,(dit-frame-offset :atomically-esp)) :ecx) ; Load interruptee's atomically-esp..
 	    (:locally (:movl :ecx (:edi (:edi-offset atomically-esp)))) ; ..and restore it.
 
 	    (:testl #x40 (:ebp 16))	; Test EFLAGS bit DF
 	    (:jnz 'atomically-jumper-return-dirty-registers)
 
-	    (:movl (:ebp -28) :edi)
-	    (:movl (:ebp -24) :esi)
-	    (:movl (:ebp -16) :edx)
-	    (:movl (:ebp -12) :eax)
-	    (:movl (:ebp -8)  :ecx)
+	    (:movl (:ebp ,(dit-frame-offset :edi)) :edi)
+	    (:movl (:ebp ,(dit-frame-offset :esi)) :esi)
+	    (:movl (:ebp ,(dit-frame-offset :edx)) :edx)
+	    (:movl (:ebp ,(dit-frame-offset :eax)) :eax)
+	    (:movl (:ebp ,(dit-frame-offset :ecx)) :ecx)
 
-	    (:movl (:ebp -32) :ebx)	; atomically-status..
+	    (:movl (:ebp ,(dit-frame-offset :atomically-status)) :ebx) ; atomically-status..
 	    (:shrl ,(- 16 movitz:+movitz-fixnum-shift+) :ebx)
 
-	    ;; Make stack safe before we exit interrupt-frame..
+	    ;; Make stack safe before we exit dit-frame..
 	    (:movl :edi (:ebp 4))
 	    (:movl :edi (:ebp 8))
 	    (:movl :edi (:ebp 12))
@@ -220,6 +240,7 @@
 	    (:movl :edi (:ebp 20))
 	    (:movl (:ebp 0) :ebp)	; pop stack-frame
 	    (:locally (:movl (:edi (:edi-offset atomically-esp)) :esp)) ; restore ESP
+	    ;; XXXX this state isn't covered in the stack discipline!?!
 	    (:jmp (:esi :ebx ,(bt:slot-offset 'movitz:movitz-funobj 'movitz::constant0)))
 
 	   atomically-jumper-return-dirty-registers
@@ -228,20 +249,21 @@
 	    ;; DF will be cleared.
 	    (:movl :edi :edx)
 	    (:movl :edi :eax)
-	    (:movl :edi  :ecx)
+	    (:movl :edi :ecx)
 
-	    (:movl (:ebp -32) :ebx)	; atomically-status..
+	    (:movl (:ebp ,(dit-frame-offset :atomically-status)) :ebx)
 	    (:shrl ,(- 16 movitz:+movitz-fixnum-shift+) :ebx)
 
-	    ;; Make stack safe before we exit interrupt-frame..
+	    ;; Make stack safe before we exit dit-frame..
 	    (:movl :edi (:ebp 4))
 	    (:movl :edi (:ebp 8))
 	    (:movl :edi (:ebp 12))
 	    (:movl :edi (:ebp 16))
 	    (:movl :edi (:ebp 20))
-	    (:movl (:ebp 0) :ebp)	; pop interrupt-frame
+	    (:movl (:ebp 0) :ebp)	; pop dit-frame
 	    (:movl (:ebp -4) :esi)
 	    (:locally (:movl (:edi (:edi-offset atomically-esp)) :esp)) ; restore ESP
+	    ;; XXXX this state isn't covered in the stack discipline!?!
 	    (:jmp (:esi :ebx ,(bt:slot-offset 'movitz:movitz-funobj 'movitz::constant0)))
 
 	   not-simple-restart-jumper
@@ -252,27 +274,28 @@
 	    )))
     (do-it)))
 
-(defun interrupt-default-handler (number interrupt-frame)
+(defun interrupt-default-handler (vector dit-frame)
   (declare (without-check-stack-limit))
+  (cli)
   (macrolet ((dereference (fixnum-address &optional (type :lisp))
 	       "Dereference the fixnum-address."
 	       `(memref ,fixnum-address 0 0 ,type)))
-    (let (($eip (+ interrupt-frame (interrupt-frame-index :eip)))
-	  ($eax (+ interrupt-frame (interrupt-frame-index :eax)))
-	  ($ebx (+ interrupt-frame (interrupt-frame-index :ebx)))
-	  ($ecx (+ interrupt-frame (interrupt-frame-index :ecx)))
-	  ($edx (+ interrupt-frame (interrupt-frame-index :edx)))
-	  ($esi (+ interrupt-frame (interrupt-frame-index :esi)))
-	  (*last-interrupt-frame* interrupt-frame))
+    (let (($eip (+ dit-frame (dit-frame-index :eip)))
+	  ($eax (+ dit-frame (dit-frame-index :eax)))
+	  ($ebx (+ dit-frame (dit-frame-index :ebx)))
+	  ($ecx (+ dit-frame (dit-frame-index :ecx)))
+	  ($edx (+ dit-frame (dit-frame-index :edx)))
+	  ($esi (+ dit-frame (dit-frame-index :esi)))
+	  (*last-dit-frame* dit-frame))
       (block nil
-	(case number
+	(case vector
 	  (0 (error 'division-by-zero))
 	  (3 (break "Break instruction at ~@Z." $eip))
 	  (4 (error "Primitive overflow assertion failed."))
 	  (6 (error "Illegal instruction at ~@Z." $eip))
 	  (13 (error "General protection error. EIP=~@Z, error-code: #x~X, EAX: ~@Z, EBX: ~@Z, ECX: ~@Z"
 		     $eip
-		     (interrupt-frame-ref :error-code :unsigned-byte32 0 interrupt-frame)
+		     (dit-frame-ref :error-code :unsigned-byte32 0 dit-frame)
 		     $eax $ebx $ecx))
 	  ((60)
 	   ;; EAX failed type in EDX. May be restarted by returning with a new value in EAX.
@@ -286,7 +309,7 @@
 	  (64 (error 'type-error :datum (dereference $eax) :expected-type 'integer))
 	  (65 (error 'index-out-of-range :index (dereference $ebx) (dereference $ecx)))
 	  (66 (error "Unspecified type error at ~@Z in ~S with EAX=~@Z, ECX=~@Z."
-		     $eip (dereference (+ interrupt-frame (interrupt-frame-index :esi)))
+		     $eip (dereference (+ dit-frame (dit-frame-index :esi)))
 		     $eax $ecx))
 	  (67 (backtrace :fresh-lines nil :length 6)
 	      (dotimes (i 100000)
@@ -295,6 +318,7 @@
 		    $eip $eax $ebx $ecx $edx)
 	      (dotimes (i 100000)
 		(with-inline-assembly (:returns :nothing) (:nop))))
+	  (70 (error "Unaligned memref access."))
 	  ((5 55)
 	   (let* ((old-bottom (prog1 (stack-bottom)
 				(setf (stack-bottom) 0)))
@@ -317,8 +341,8 @@
 			   (- old-bottom new-bottom)
 			   new-bottom)
 		   (break "Stack overload exception ~D at EIP=~@Z, ESI=~@Z, ESP=~@Z, bottom=#x~X."
-			  number $eip $esi
-			  (+ interrupt-frame (interrupt-frame-index :ebp))
+			  vector $eip $esi
+			  (+ dit-frame (dit-frame-index :ebp))
 			  old-bottom))
 	       (format *debug-io* "~&Stack-warning: Resetting stack-bottom to #x~X.~%"
 		       old-bottom)
@@ -336,13 +360,13 @@
 	     (when (symbolp name)
 	       (error 'unbound-variable :name name))))
 	  ((100);; 101 102 103 104 105)
-	   (let ((funobj (dereference (+ interrupt-frame (interrupt-frame-index :esi))))
-		 (code (interrupt-frame-ref :ecx :unsigned-byte8 0 interrupt-frame)))
+	   (let ((funobj (dereference (+ dit-frame (dit-frame-index :esi))))
+		 (code (dit-frame-ref :ecx :unsigned-byte8 0 dit-frame)))
 	     (error 'wrong-argument-count
 		    :function funobj
 		    :argument-count (if (logbitp 7 code)
-					(ash (interrupt-frame-ref :ecx :unsigned-byte32
-								  0 interrupt-frame)
+					(ash (dit-frame-ref :ecx :unsigned-byte32
+								  0 dit-frame)
 					     -24)
 				      code))))
 	  (108
@@ -353,20 +377,20 @@
 	  (112
 	   (let ((*error-no-condition-for-debugger* t)) ; no space..
 	     (error "Out of memory. Please take out the garbage.")))
-	  (t (funcall (if (< 16 number 50) #'warn #'error)
+	  (t (funcall (if (< 16 vector 50) #'warn #'error)
 		      "Exception occurred: ~D, EIP: ~@Z, EAX: ~@Z, ECX: ~@Z, ESI: ~@Z"
-		      number $eip $eax $ecx $esi)))
+		      vector $eip $eax $ecx $esi)))
 	nil))))
 
 
-(defun exception-handler (n)
-  (let ((vector (load-global-constant interrupt-handlers)))
-    (svref vector n)))
+(defun exception-handler (vector)
+  (let ((handlers (load-global-constant exception-handlers)))
+    (svref handlers vector)))
 
-(defun (setf exception-handler) (handler n)
+(defun (setf exception-handler) (handler vector)
   (check-type handler function)
-  (let ((vector (load-global-constant interrupt-handlers)))
-    (setf (svref vector n) handler)))
+  (let ((handlers (load-global-constant exception-handlers)))
+    (setf (svref handlers vector) handler)))
 
 (defun cli ()
   (with-inline-assembly (:returns :nothing)
@@ -376,17 +400,17 @@
   (with-inline-assembly (:returns :nothing)
     (:sti)))
 
-(defun raise-exception (exception &optional (eax 0) (ebx 0))
+(defun raise-exception (vector &optional (eax 0) (ebx 0))
   "Generate a CPU exception, with those values in EAX and EBX."
   ;; The problem now is that the x86 INT instruction only takes an
   ;; immediate argument.
-  (check-type exception (unsigned-byte 8))
+  (check-type vector (unsigned-byte 8))
   (macrolet
       ((do-it ()
 	 `(with-inline-assembly (:returns :eax)
 	    (:load-lexical (:lexical-binding eax) :eax)
 	    (:load-lexical (:lexical-binding ebx) :ebx)
-	    (:load-lexical (:lexical-binding exception) :ecx)
+	    (:load-lexical (:lexical-binding vector) :ecx)
 	    (:shrl ,movitz:+movitz-fixnum-shift+ :ecx)
 	    (:jnz 'not-0)
 	    (:int 0)





More information about the Movitz-cvs mailing list