Update of /project/movitz/cvsroot/movitz/losp/x86-pc In directory common-lisp.net:/tmp/cvs-serv737
Modified Files: interrupt.lisp Log Message: Moved much stuff from :x86-pc/interrupt to :muerte/interrupt, because it's really a required part of Muerte.
Date: Tue Apr 6 20:12:28 2004 Author: ffjeld
Index: movitz/losp/x86-pc/interrupt.lisp diff -u movitz/losp/x86-pc/interrupt.lisp:1.8 movitz/losp/x86-pc/interrupt.lisp:1.9 --- movitz/losp/x86-pc/interrupt.lisp:1.8 Tue Apr 6 10:42:11 2004 +++ movitz/losp/x86-pc/interrupt.lisp Tue Apr 6 20:12:28 2004 @@ -10,12 +10,11 @@ ;;;; Author: Frode Vatvedt Fjeld frodef@acm.org ;;;; Created at: Fri May 4 18:08:50 2001 ;;;; -;;;; $Id: interrupt.lisp,v 1.8 2004/04/06 14:42:11 ffjeld Exp $ +;;;; $Id: interrupt.lisp,v 1.9 2004/04/07 00:12:28 ffjeld Exp $ ;;;; ;;;;------------------------------------------------------------------
(require :x86-pc/pic8259) -(require :x86-pc/debugger) (provide :x86-pc/interrupt)
(in-package muerte.x86-pc) @@ -25,250 +24,6 @@ (:movb #x20 :al) (:outb :al #x20)))
-(defmacro stack-word (offset) - `(with-inline-assembly (:returns :eax) - (:movl (:esp ,(* 4 offset)) :eax))) - -(define-compiler-macro int-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 - '(:eip :eflags nil :error-code :exception :ebp nil - :ecx :eax :edx :ebx :esi :edi) - #+ignore '(:edi :esi :ebp :esp :ebx :edx :ecx :eax - :exception :error-code - :eip :cs :eflags)))))) - -(defun int-frame-index (name) - (- 5 (position name - '(:eip :eflags nil :error-code :exception :ebp nil - :ecx :eax :edx :ebx :esi :edi)))) - -(define-compiler-macro int-frame-ref (&whole form frame reg type &optional (offset 0) &environment env) - `(memref ,frame (+ (* 4 (int-frame-index ,reg)) ,offset) 0 ,type)) - -(defun int-frame-ref (frame reg type &optional (offset 0)) - (int-frame-ref frame reg type offset)) - -(defun (setf int-frame-ref) (x frame reg type) - (setf (memref frame (* 4 (int-frame-index reg)) 0 type) x)) - -(define-primitive-function muerte::default-interrupt-trampoline () - "Default first-stage interrupt handler." - #.(cl:list* 'with-inline-assembly '(:returns :nothing) - (cl:loop :for i :from 0 :to movitz::+idt-size+ - :append (cl:if (cl: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))))) - (with-inline-assembly (:returns :multiple-values) - ok - ;; Stack: - ;; 20: Interruptee EFLAGS (later EIP) - ;; 16: Interruptee CS (later EFLAGS) - ;; 12: Interruptee EIP - ;; 8: Error code - ;; 4: Exception number - ;; 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 :edi) ; -28 - - ;; rearrange stack for return - (:movl (:ebp 12) :eax) ; load return address - (:movl (:ebp 20) :ebx) ; load EFLAGS - (:movl :ebx (:ebp 16)) ; EFLAGS at next-to-bottom of stack - (:movl :eax (:ebp 20)) ; return address at bottom of stack - - (:xorl :eax :eax) ; Ensure safe value - (:xorl :edx :edx) ; Ensure safe value - - (:movl ':nil-value :edi) ; We want NIL! - - (:pushl (:ebp 16)) ; EFLAGS - (:pushl :cs) ; push CS - (:call (:pc+ 0)) ; push EIP. - ;; Now add a few bytes to the on-stack EIP so the iret goes to - ;; *DEST* below. - ((4) :addl 5 (:esp)) ; 4 bytes - ((1) :iretd) ; 1 byte - - ;; *DEST* iret branches to here. - ;; we're now in the context of the interruptee. - -;;; (:pushl :eax) ; fake stack-frame return address -;;; (:pushl :ebp) ; set up fake stack-frame -;;; (:movl :esp :ebp) ; (GIVES EBP OFFSET 8 RELATIVE TO NUMBERS ABOVE!!) -;;; (:pushl :edi) ; A fake "funobj" for the fake stack-frame.. -;;; ; ..the int-frame will be put here shortly. - - ;; 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) - push-values-loop - (:locally (:pushl (:eax))) - (:addl 4 :eax) - (:subl 1 :ecx) - (:jnz 'push-values-loop) - push-values-done - (:locally (:pushl (:edi (:edi-offset num-values)))) - - ;; call handler - (:movl (:ebp 4) :ebx) ; interrupt number into EBX - (:locally (:movl (:edi (:edi-offset interrupt-handlers)) :eax)) - (:movl (:eax 2 (:ebx 4)) :eax) ; symbol at (aref EBX interrupt-handlers) into :esi - (:leal (:eax -7) :ecx) - (:testb 7 :cl) - (:jnz 'skip-interrupt-handler) ; if it's not a symbol, never mind. - (:movl (:eax #.(movitz::slot-offset 'movitz::movitz-symbol 'movitz::function-value)) - :esi) ; load new funobj from symbol into ESI - (:movl :ebp :ebx) ; pass INT-frame as arg1 - ;; (:movl :ebx (:ebp -4)) ; put INT-frame as our fake stack-frame's funobj. - (:movl (:ebp 4) :eax) ; pass interrupt number as arg 0. - (:shll #.movitz::+movitz-fixnum-shift+ :eax) - (:call (:esi #.(movitz::slot-offset 'movitz::movitz-funobj 'movitz::code-vector%2op))) - - skip-interrupt-handler - ;; Restore thread-local values - (:popl :ecx) - (:locally (:movl :ecx (:edi (:edi-offset num-values)))) - (:jecxz 'pop-values-done) - pop-values-loop - ;; ((:fs-override) :popl (:edi #.(movitz::global-constant-offset 'values) (:ecx 4) -4)) - (:locally (:popl (:edi (:edi-offset values) (:ecx 4) -4))) - (:subl 1 :ecx) - (:jnz 'pop-values-loop) - pop-values-done - - (:movl (:ebp -28) :edi) - (:movl (:ebp -24) :esi) - (:movl (:ebp -20) :ebx) - (:movl (:ebp -16) :edx) - (:movl (:ebp -12) :eax) - (:movl (:ebp -8) :ecx) - - (:leave) - (:addl 12 :esp) - -;;; (:leal (:ebp 8) :esp) -;;; (:popal) ; pop interruptee's registers -;;; (:addl 12 :esp) ; skip stack-hole - (:popfl) ; pop EFLAGS - (:ret))) ; pop EIP - -(defvar *last-interrupt-frame* nil) - -(defun muerte::interrupt-default-handler (number int-frame) - (declare (muerte::without-check-stack-limit)) - (macrolet ((@ (fixnum-address &optional (type :lisp)) - "Dereference the fixnum-address." - `(memref ,fixnum-address 0 0 ,type))) - (let (($eip (+ int-frame (int-frame-index :eip))) - ($eax (+ int-frame (int-frame-index :eax))) - ($ebx (+ int-frame (int-frame-index :ebx))) - ($ecx (+ int-frame (int-frame-index :ecx))) - ($edx (+ int-frame (int-frame-index :edx))) - ($esi (+ int-frame (int-frame-index :esi))) - (*last-interrupt-frame* int-frame)) - (block nil - (case number - (0 (error "Division by zero.")) - (3 (break "Break instruction at ~@Z." $eip)) - (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 - (int-frame-ref int-frame :error-code :unsigned-byte32) - $eax $ebx $ecx)) - (68 (warn "EIP: ~@Z EAX: ~@Z EBX: ~@Z ECX: ~@Z EDX: ~@Z" - $eip $eax $ebx $ecx $edx) - (dotimes (i 100000) - (with-inline-assembly (:returns :nothing) (:nop)))) - (67 (muerte.debug:backtrace :fresh-lines nil :length 6) - (dotimes (i 100000) - (with-inline-assembly (:returns :nothing) (:nop)))) - (66 (error "Unspecified type error at ~@Z in ~S with EAX=~@Z, ECX=~@Z." - $eip (@ (+ int-frame (int-frame-index :esi))) - $eax $ecx)) - (62 (error "Trying to save too many values: ~@Z." $ecx)) - ((5 55) - (let* ((stack (muerte::%run-time-context-slot 'movitz::stack-vector)) - (old-bottom (muerte::stack-bottom)) - (real-bottom (- (object-location stack) 2)) - (stack-left (- old-bottom real-bottom)) - (new-bottom (cond - ((< stack-left 10) - (princ "Halting CPU due to stack exhaustion.") - (muerte::halt-cpu)) - ((<= stack-left 256) - (format *debug-io* - "~&This is your LAST chance to pop off stack.~%") - real-bottom) - (t (+ real-bottom (truncate stack-left 2)))))) ; Cushion the fall.. - (unwind-protect - (progn - (setf (muerte::stack-bottom) new-bottom) - (format *debug-io* "~&Stack-warning: Bumped stack-bottom by ~D to #x~X.~%" - (- old-bottom new-bottom) - new-bottom) - (break "Stack overload exception ~D at ESP=~@Z with bottom #x~X." - number - (+ int-frame (int-frame-index :ebp)) - old-bottom)) - (format *debug-io* "~&Stack-warning: Resetting stack-bottom to #x~X.~%" - old-bottom) - (setf (muerte::stack-bottom) old-bottom)))) - (69 - (error "Not a function: ~S" (@ $edx))) - (70 - (error "[EIP=~@Z] Index ~@Z out of bounds ~@Z for ~S." $eip $ecx $ebx (@ $eax))) - (98 - (let ((name (@ $ecx))) - (when (symbolp name) - (error 'undefined-function :name name)))) - (99 - (let ((name (@ $edx))) - (when (symbolp name) - (error 'unbound-variable :name name)))) - ((100);; 101 102 103 104 105) - (let ((funobj (@ (+ int-frame (int-frame-index :esi)))) - (code (int-frame-ref int-frame :ecx :unsigned-byte8))) - (error 'muerte:wrong-argument-count - :function funobj - :argument-count (if (logbitp 7 code) - (ash (int-frame-ref int-frame :ecx :unsigned-byte32) - -24) - code)))) - (108 - (error 'throw-error :tag (@ $eax))) - (110 - ;; (print-dynamic-context); what's this? - (throw :debugger nil)) - (112 - (setf (%run-time-context-slot 'nursery-space) - (memref (%run-time-context-slot 'nursery-space) -6 3 :lisp)) - (error "Out of memory. Please take out the garbage.")) - (t (funcall (if (< 16 number 50) #'warn #'error) - "Exception occurred: ~D, EIP: ~@Z, EAX: ~@Z, ECX: ~@Z, ESI: ~@Z" - number $eip $eax $ecx $esi))) - nil)))) - - -;;; (with-inline-assembly (:returns :nothing) (:movb #x47 (#xb8045)) -;;; (:addb #x01 (#xb8044)))) - - (defun idt-init () (init-pic8259 32 40) (setf (pic8259-irq-mask) #xffff) @@ -284,24 +39,6 @@ (setf (pic8259-irq-mask) #xfffe) (with-inline-assembly (:returns :nothing) (:sti)))
-(defun cli () - (with-inline-assembly (:returns :nothing) - (:cli))) - -(defun sti () - (with-inline-assembly (:returns :nothing) - (:sti))) - -(defun interrupt-handler (n) - (let ((vector (load-global-constant interrupt-handlers))) - (svref vector n))) - -(defun (setf interrupt-handler) (handler n) - (check-type handler symbol) - (assert (fboundp handler)) - (let ((vector (load-global-constant interrupt-handlers))) - (setf (svref vector n) handler))) - (defparameter *timer-counter* 0)
(defun timer-handler (number int-frame) @@ -312,31 +49,3 @@ (pic8259-end-of-interrupt 0))
-(define-primitive-function primitive-software-interrupt () - "A primitive code-vector that generates software interrupts." - (macrolet ((make-software-interrupt-code () - (cons 'progn - (loop for vector from 0 to 255 - collect `(with-inline-assembly (:returns :nothing) - ;; Each code-entry is 2+1+1=4 bytes. - ((2) :int ,vector) - ((1) :ret) - ((1) :nop)))))) - (make-software-interrupt-code))) - -(defun software-interrupt (interrupt-vector &optional (eax 0) (ebx 0)) - "Generate software-interrupt number <interrupt-vector>." - ;; The problem now is that the x86 INT instruction only takes an - ;; immediate argument. - ;; Hence the primitive-function primitive-software-interrupt. - (check-type interrupt-vector (unsigned-byte 8)) - (let ((code-vector (symbol-value 'primitive-software-interrupt))) - (check-type code-vector vector) - (with-inline-assembly-case () - (do-case (t :nothing) - (:compile-two-forms (:ecx :edx) interrupt-vector code-vector) - (:leal (:edx :ecx 2) :ecx) - (:compile-two-forms (:eax :ebx) eax ebx) - (:shrl 2 :eax) - (:shrl 2 :ebx) - (:call :ecx)))))