;;; -*- Mode:LISP; Package:GC-FAULT; Base:10; Readtable:CL -*- ;;; This file handles volatility traps and box errors. ;;; This code runs without interrupts because saving the state, etc ;;; would just take too long. ;;; We expect the VMA and the MD to have the appropriate fault data in ;;; them. We are expected to not modify either. ;;; Extra hair is introduced here because we may be taking a volatility trap on the ;;; temporary map entry. In this case, we fake up the VMA to what it should be and ;;; process the trap. (defun gc-fault-handler () (let* ((real-vma (hw:read-vma)) (vma-boxed (hw:ldb-not (hw:read-memory-status) hw:%%memory-status-vma-not-boxed-bit 0.))) (when (= (cluster-number real-vma) vmem::*temporary-map-entry*) (let ((deduced-vma (hw:dpb gr::*temporary-map-entry-virtual-cluster* vinc:%%cluster-number real-vma))) (vmem:write-vma-generic deduced-vma vma-boxed) (dispatch hw:%%memory-control-transporter-mode (hw:read-memory-control) (vinc:$$transporter-mode-normal (handle-normal-gc-fault)) (t (trap::illop "GC fault with weird transporter mode."))))) (vmem:write-vma-generic real-vma vma-boxed) (dispatch hw:%%memory-control-transporter-mode (hw:read-memory-control) (vinc:$$transporter-mode-normal (handle-normal-gc-fault)) (t (trap::illop "GC fault with weird transporter mode."))))) (defun handle-normal-gc-fault () (let ((gc-ram-bits (hw:read-gc-ram))) (if (= hw:$$box-error (hw:ldb gc-ram-bits hw:%%transporter-ram-box-error 0.)) (trap::illop "Box error.") ;; It is a volatility trap. (let ((region-volatility (hw:ldb gc-ram-bits hw:%%gc-ram-quantum-volatility 0.)) (map-bits (hw:read-map))) (let ((map-status (extract-map-status map-bits))) (unless (or (= map-status $$map-status-normal) (and (= map-status $$map-status-read-only) gr:*allow-write-in-read-only*)) (trap::illop "GC fault on non-NORMAL cluster."))) (hw:write-map (hw:dpb region-volatility hw:%%map-volatility map-bits)) ; (trap::illop "Exiting GC fault.") (hw:nop)))))