;;;-*- Mode:LISP; Package:K2; Base:10; Readtable:CL -*- ;;;; Save the world ;;; A saved image looks like this: ;;; ;;; Physical memory load: ;;; 00 Clusters 0-3 ;;; 04 Quantum Map ;;; 08 Region Bits ;;; 0C Initial PCD Data ;;; 0D GC RAM ;;; 11 Region Data ;;; 21 Area Data ;;; ?? add global vars ;;; 31 Initial Code ;;; ;;; Virtual memory load: ;;; Regions ;;; ;;; This is the boot sequence: ;;; ;;; 1. Load the physical memory load ;;; into physical memory. ;;; 2. Map in cluster 0 ;;; 3. Map in Initial code (pointed to by boot vector) ;;; 4. ?? Load virtual memory data (regions) into virtual memory ;;; (fast boot leave on boot device) ;;; 5. something sometime must put swaped-out in maps... ;;; 6. Size memory, put that in boot vector. ;;; 7. Put prom version in boot vector ;;; 8. Jump to code start ;;; (defparameter saved-image-initial-gc-ram-data-physical-location (ash #xD 10.)) (defparameter saved-image-region-data-physical-location (ash #x11 10.)) (defparameter saved-image-area-data-physical-location (ash #x21 10.)) (defun initial-data-size () (+ (vinc:cluster->address 4) ; clusters 0-3 vinc:*number-of-quanta* ; quantum map memory-management:*number-of-regions* ; region bits (vinc:cluster->address 5) ; PCD data, GC RAM vinc:*qs-in-quantum* ; Region Data 1 quantum (* 4 region-bits:*number-of-regions*) vinc:*qs-in-quantum* ; Area Data 1 quantum (why so big?) ; (vinc:cluster->address 1) ; global vars )) (defun save-it () (save-physical) (loop)) (defun save-physical () (let ((initial-code-size (initial-code-size)) (initial-data-size (initial-data-size))) (setup-boot-vector initial-data-size initial-code-size) ; ;; save physical memory load size ; (save-word (+ initial-data-size ; initial-code-size)) (save-cluster 0) ;; we want to leave space in memory ;; for the special clusters ;; (i think we only need to reserve cluster 2 in physical memory ;; but we need to be in sync with KOLD-LOADER which has the quantum map ;; in cluster 4) (skip-cluster) ;cluster 1 temporary map entry (skip-cluster) ;cluster 2 kbug communication area (skip-cluster) ;cluster 3 *k-io-regs-cluster* nubus mapped ;; NUBUS-INTERRUPTS says cluster 4 is *bus-access-cluster* ;; reserved for external bus access routines (save-quantum-map) (save-region-bits) (save-initial-pcd-data) (save-gc-ram) (save-region-data) (save-area-data) ; (save-global-vars) (save-initial-code) ;this marks the end (save-block 0 0))) ;;; Save all the regions ;;; except: ;;; region area ;;; 0 0 cluster 0 etc ;;; 1 1 PCD, Quantum Map, Region Bits ;;; 2 2 Region Data ;;; 3 3 Area Data ;;; 2048 4 Initial Code ;;; (defun save-virtual () (dotimes (region region-bits:*number-of-regions*) ;; don't save regions in physical memory load (when (and (not (<= region 3)) (not (= region (region-bits:region-number (vinc:cluster->address hw:*first-instruction-cluster*))))) (let ((region-space-type (region-bits:region-space-type (region-bits:read-region-bits region)))) ;; don't save invalid or free regions (unless (or (= region-space-type region-bits:$$region-space-invalid) (= region-space-type region-bits:$$region-space-free)) (save-region region))))) (save-block 0 0)) (defun write-boot-vector (element data) (hw:write-md-unboxed data) (hw:vma-start-write-no-gc-trap-unboxed (hw:24+ boot:**boot-vector-origin** element)) (hw:memory-wait)) (defun setup-boot-vector (initial-code-offset initial-code-size) (write-boot-vector boot::**initial-code-physical-location-bv-offset** initial-code-offset) (write-boot-vector boot::**initial-code-size-in-clusters-bv-offset** (1+ (vinc:cluster-number initial-code-size))) (write-boot-vector boot::**initial-code-entry-point-bv-offset** (initial-function-entry-point)) ;; these are in same place as cold load (write-boot-vector boot::*initial-gc-ram-data-physical-location* saved-image-initial-gc-ram-data-physical-location) ; (write-boot-vector boot::*initial-transporter-ram-data-physical-location* ; (cluster->address *initial-transporter-ram-data-physical-location*)) (write-boot-vector boot::*cold-load-flag* nil)) (defun skip-cluster () (skip-words vinc:*qs-in-cluster*)) (defun skip-words (n) ;; save in 256. word chunks (dotimes (i (hw:ldb n (byte (- (byte-size vinc:%%fixnum-field) 8.) 8.) 0)) (dotimes (i #x100) (kbug-set-data i NIL)) (save-block kbug-data-transfer-area-addr #x100)) (let ((rem (hw:ldb n (byte 8. 0.) 0.))) (unless (zerop rem) (dotimes (i rem) (kbug-set-data i NIL)) (save-block kbug-data-transfer-area-addr rem)))) ;(defun save-cluster (cluster) ; (do ((count 0 (1+ count)) ; (addr (cons:make-pointer vinc:$$dtp-unboxed-locative ; (vinc:cluster->address cluster)) ; (hw:24+ 1 addr))) ; ((>= count vinc:*qs-in-cluster*)) ; (hw:vma-start-read-no-transport-vma-unboxed-md-unboxed addr) ; (save-word (hw:read-md)))) (defun save-cluster (cluster) (save-block (vinc:cluster->address cluster) vinc:*qs-in-cluster*)) ;(defun save-quantum-map () ; (dotimes (i vinc:*number-of-quanta*) ; (save-word (quantum-map:read-quantum-map i)))) (defun save-quantum-map () (save-block gr:*quantum-map* vinc:*number-of-quanta*)) ;(defun save-region-bits () ; (dotimes (i region-bits:*number-of-regions*) ; (save-word (region-bits:read-region-bits i)))) (defun save-region-bits () (save-block gr:*region-bits* region-bits:*number-of-regions*)) ;(defun save-region-data () ; (dotimes (i region-bits:*number-of-regions*) ; (save-word (region-data:region-free-pointer i))) ; (dotimes (i region-bits:*number-of-regions*) ; (save-word (region-data:region-end-pointer i))) ; (dotimes (i region-bits:*number-of-regions*) ; (save-word (region-data:region-gc-pointer i)))) (defun save-region-data () ;; (region-data:region-origin 2.) ;; 4096 regions, 4 tables = 16 clusters = 1 quantum (save-block gr:*region-free-pointer* vinc:*qs-in-quantum*)) (defun save-area-data () ;; (region-data:region-origin 3.) (save-block gr:*region-list-thread* vinc:*qs-in-quantum*)) (defun store-frame (frame) (trap:without-traps #'(lambda () (hw:nop) (hw:nop) (let ((oar (hw:read-open-active-return)) (boxbits 0)) (hw:write-open-active-return (hw:dpb frame (byte 8. 16.) oar)) (hw:nop) (hw:nop) (hw:nop) (hw:nop) (hw:nop) (hw:nop) (kbug-set-data 0. (hw:o0)) (kbug-set-data 1. (hw:o1)) (kbug-set-data 2. (hw:o2)) (kbug-set-data 3. (hw:o3)) (kbug-set-data 4. (hw:o4)) (kbug-set-data 5. (hw:o5)) (kbug-set-data 6. (hw:o6)) (kbug-set-data 7. (hw:o7)) (kbug-set-data 8. (hw:o8)) (kbug-set-data 9. (hw:o9)) (kbug-set-data 10. (hw:o10)) (kbug-set-data 11. (hw:o11)) (kbug-set-data 12. (hw:o12)) (kbug-set-data 13. (hw:o13)) (kbug-set-data 14. (hw:o14)) (kbug-set-data 15. (hw:o15)) (setq boxbits (hw:accumulate-box-bits boxbits (hw:o15))) (setq boxbits (hw:accumulate-box-bits boxbits (hw:o14))) (setq boxbits (hw:accumulate-box-bits boxbits (hw:o13))) (setq boxbits (hw:accumulate-box-bits boxbits (hw:o12))) (setq boxbits (hw:accumulate-box-bits boxbits (hw:o11))) (setq boxbits (hw:accumulate-box-bits boxbits (hw:o10))) (setq boxbits (hw:accumulate-box-bits boxbits (hw:o9))) (setq boxbits (hw:accumulate-box-bits boxbits (hw:o8))) (setq boxbits (hw:accumulate-box-bits boxbits (hw:o7))) (setq boxbits (hw:accumulate-box-bits boxbits (hw:o6))) (setq boxbits (hw:accumulate-box-bits boxbits (hw:o5))) (setq boxbits (hw:accumulate-box-bits boxbits (hw:o4))) (setq boxbits (hw:accumulate-box-bits boxbits (hw:o3))) (setq boxbits (hw:accumulate-box-bits boxbits (hw:o2))) (setq boxbits (hw:accumulate-box-bits boxbits (hw:o1))) (setq boxbits (hw:accumulate-box-bits boxbits (hw:o0))) (kbug-set-data 16. boxbits) (hw:write-open-active-return oar)))) (hw:nop) (hw:nop) (hw:nop) (hw:nop) (hw:nop) (hw:nop)) (defun save-frame (frame) (store-frame frame) (save-block kbug-data-transfer-area-addr (1+ hw:frame-size))) (defun save-global-vars () (dotimes (i hw:number-of-global-frames) (save-frame i))) ;;; $$init-map-physical-cluster ;;; $$init-map-virtual-cluster ;;; $$init-map-initial-status ;;; $$init-map-cluster-count (defun save-initial-pcd-data () (let ((i -1)) (macrolet ((set-data (value) `(kbug-set-data (incf i) ,value))) ;; Initial instructions (set-data (vinc:cluster-number (initial-data-size))) (set-data hw:*first-instruction-cluster*) (set-data pcd::$$init-map-wired-read-only) (set-data (vinc:cluster-number (initial-code-size))) ;; Quantum Map (set-data boot:*quantum-map-physical-location*) (set-data (vinc:cluster-number boot:*quantum-map-virtual-location*)) (set-data pcd::$$init-map-wired) (set-data boot:*quantum-map-clusters*) ;; Region Bits (set-data boot:*region-bits-physical-location*) (set-data (vinc:cluster-number boot:*region-bits-virtual-location*)) (set-data pcd::$$init-map-wired) (set-data boot:*region-bits-clusters*) ;; Region Data (set-data (vinc:cluster-number saved-image-region-data-physical-location)) (set-data (vinc:cluster-number gr:*region-free-pointer*)) (set-data pcd::$$init-map-wired) ;??? (set-data 16.) ; 4096 regions, 4 tables = 16 clusters = 1 quantum ;; Area Data (set-data (vinc:cluster-number saved-image-area-data-physical-location)) (set-data (vinc:cluster-number gr:*region-list-thread*)) (set-data pcd::$$init-map-wired) ;??? (set-data 16.) ; 1 quantum ;; Shared memory cluster (set-data 2.) (set-data 2.) (set-data pcd::$$init-map-wired) (set-data 1.) ;; This must be last. It maps NIL. (set-data 0.) (set-data 0.) (set-data pcd::$$init-map-wired) (set-data 1.) ;; fill out 256 (do ((i (1+ i) (1+ i))) ((>= i #x100)) (kbug-set-data i NIL)) (save-block kbug-data-transfer-area-addr #x100) ;; fill out cluster (skip-words (- vinc:*qs-in-cluster* #x100))))) ;;; boot gc ram data was 1 cluster, but gc-ram is 4k long??? ;(defun save-gc-ram () ; (dotimes (i gc-ram:*number-of-gc-ram-entries*) ; (save-word (gc-ram:read-gc-ram i)))) (defun save-gc-ram () (do ((i1 0 (+ i1 #x100))) ((>= i1 gc-ram:*number-of-gc-ram-entries*)) (dotimes (i2 #x100) (kbug-set-data i2 (gc-ram:read-gc-ram (+ i1 i2)))) (save-block kbug-data-transfer-area-addr #x100))) ;(defun save-region (region) ; (let ((start-cluster (vinc:cluster-number (region-data:region-origin region))) ; (end-cluster (vinc:cluster-number (region-data:region-free-pointer region)))) ; (do ((cluster start-cluster (1+ cluster))) ; ((> cluster end-cluster)) ; (save-cluster cluster)))) (defun save-region (region) (save-block (region-data:region-origin region) (region-size region))) (defun region-size (region) (cons:make-pointer vinc:$$dtp-fixnum (hw:32- (region-data:region-end region) ;; some magic needs to be done to do this ;; (region-data:region-free-pointer region) (region-data:region-origin region)))) ;-------------------------------------------------------------------------------- ;;;; Initial Code ;;; how do we know this? (defconstant initial-code-area 4.) (defun initial-code-region () (area-data:area-data-region-thread (area-data:area-region-data initial-code-area))) (defun initial-code-size () ;; assuming only one region (region-size (initial-code-region))) (defun initial-function-entry-point () (hw:24- (%compiled-function-code (symbol:symbol-function 'boot:cold-boot-function)) (region-bits:region-origin (initial-code-region)))) (defun save-initial-code () ;; assume only one region? (save-region (initial-code-region))) ;-------------------------------------------------------------------------------- ;;; IO stuff (defun write-word (data) ;; DATA can be unboxed (kbug-stream-write-byte KBUG-K-OUTPUT-STREAM (hw:ldb data (byte 8 0.) 0)) (kbug-stream-write-byte KBUG-K-OUTPUT-STREAM (hw:ldb data (byte 8 8.) 0)) (kbug-stream-write-byte KBUG-K-OUTPUT-STREAM (hw:ldb data (byte 8 16.) 0)) (kbug-stream-write-byte KBUG-K-OUTPUT-STREAM (hw:ldb data (byte 8 24.) 0))) (defun get-physical-address (virtual-address) (let ((virtual-cluster (vinc:cluster-number virtual-address))) (let ((map-bits (map:read-map virtual-cluster))) ;; make sure its swapped in ;; this is broken becauset there can be more than one cluster here (when (= (map:extract-map-status map-bits) map:$$map-status-swapped-out) (map-fault:swap-in virtual-cluster) (setq map-bits (map:read-map virtual-cluster))) (dpb-multiple-unboxed 0. vinc:%%data-type (map:map-on-board-address map-bits) hw:%%mapped-vma-byte virtual-address)))) (defun save-block (start count) (write-word (get-physical-address start)) (write-word (hw:dpb-unboxed 0 vinc:%%data-type count)) ;; wait for ack (kbug-set-command #xFE) (do () ((not (= (kbug-read-command) #xFE)))))