1 /****^  ***********************************************************
  2         *                                                         *
  3         * Copyright, (C) Honeywell Bull Inc., 1987                *
  4         *                                                         *
  5         * Copyright, (C) Honeywell Information Systems Inc., 1983 *
  6         *                                                         *
  7         * Copyright (c) 1972 by Massachusetts Institute of        *
  8         * Technology and Honeywell Information Systems, Inc.      *
  9         *                                                         *
 10         *********************************************************** */
 11 
 12 /*
 13    Written April 1975 by R. Bratt
 14 
 15    Last modified by:
 16 
 17    R. Bratt October 1975 to initialize kstes as needed
 18    R. Bratt June 1975 to differentiate segno_in_use and invalidsegno conditions
 19    R. Bratt May 1976 to call garbage_collect_kst in an attempt to avoid kst overflow
 20    R. Bratt June 1976 to cause access to be recalculated when priv_init or allow_write are set
 21    M. Weaver March 1977 to add use_count parameter
 22    E. N. Kittlitz December 1980 to immediately activate directories.
 23    J. Bongiovanni, January 1983, to fix stack initiation bug
 24    E. N. Kittlitz, February 1983, for kst_util.
 25    E. N. Kittlitz, 831130, suspend vcpu during call to activate
 26    K. Loepere, October 1984, for control over directory activations (for
 27    performance; also has to do with centralizing references to
 28    validate_entryp).  Also deleted hdr and unused notion of object
 29    undetectability.
 30 */
 31 
 32 
 33 /****^  HISTORY COMMENTS:
 34   1) change(86-08-09,GDixon), approve(86-08-09,MCR7388),
 35      audit(86-09-02,Farley), install(86-09-08,MR12.0-1150):
 36      Copy makeknown_info.entryp into kstep.entryp in every call, rather just in
 37      those calls which create the kst entry.  In calls which activate the
 38      segment, seg_fault$makeknown_activate will use this kste.entryp to
 39      reference the directory entry for the segment.  Also, document the
 40      restrictions which callers of makeknown_ must adhere to.
 41                                                    END HISTORY COMMENTS */
 42 
 43 
 44 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
 45 /*                                                                           */
 46 /* Function: makeknown_ is responsible for obtaining a segment number for    */
 47 /* an object.  Whenever possible makeknown_ returns a segment number which   */
 48 /* was previously assigned to the object.                                    */
 49 /*                                                                           */
 50 /* WARNING: In order to call makeknown_:                                     */
 51 /*  a) the directory containing the entry pointed to by                      */
 52 /*     makeknown_info.entryp must be locked by the caller throughout the     */
 53 /*     call to makeknown_.                                                   */
 54 /*  b) after locking the directory and before calling makeknown_, the        */
 55 /*     caller must have validated makeknown_info.entryp to ensure that it    */
 56 /*     points to the dir entry whose uid equals makeknown_.info.uid.         */
 57 /* One way to perform both functions is to call sum$getbranch or             */
 58 /* sum$getbranch_root_my.                                                    */
 59 /*                                                                           */
 60 /* USAGE:  call makeknown_ (infop, segno, use_count, code);                  */
 61 /*                                                                           */
 62 /* infop                [ptr] --- pointer to the makeknown_info structure    */
 63 /*                                describing the object (input)              */
 64 /* segno     [fixed bin (17)] --- segment number (input/output)              */
 65 /* use_count [fixed bin (17)] --- updated usage count (output)               */
 66 /* code      [fixed bin (35)] --- status code (output)                       */
 67 /*                                                                           */
 68 /* *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
 69 
 70 /* format: style4 */
 71 makeknown_:
 72      procedure (a_makeknown_infop, a_segno, a_use_count, a_code);
 73 
 74 /* Parameters */
 75 
 76 dcl  a_code fixed bin (35);
 77 dcl  a_makeknown_infop ptr;
 78 dcl  a_segno fixed bin (17);
 79 dcl  a_use_count fixed bin (17);
 80 
 81 /* Variables */
 82 
 83 dcl  code fixed bin (35);
 84 dcl  hash_bucket fixed bin (17);
 85 dcl  pkstep ptr;
 86 dcl  ring fixed bin (3);
 87 dcl  1 sdwi aligned like sdw_info;
 88 dcl  segno fixed bin (17);
 89 dcl  valid bit (1) aligned;
 90 dcl  vcpu_suspend_1 fixed bin (71);
 91 dcl  vcpu_suspend_2 fixed bin (71);
 92 
 93 /* External */
 94 
 95 dcl  dseg$ (0:4095) fixed bin (71) external;
 96 dcl  error_table_$invalidsegno fixed bin (35) external static;
 97 dcl  error_table_$nrmkst fixed bin (35) ext static;
 98 dcl  error_table_$segknown fixed bin (35) external static;
 99 dcl  error_table_$segno_in_use fixed bin (35) external static;
100 dcl  1 pds$transparent external aligned,
101        2 tms bit (1) unaligned,
102        2 tus bit (1) unaligned,
103        2 tpd bit (1) unaligned;
104 
105 /* Entries */
106 
107 dcl  fim_util$fim_v_time_calc_ext entry (fixed bin (71), fixed bin (71));
108 dcl  fim_util$fim_v_time_init_ext entry (fixed bin (71), fixed bin (71));
109 dcl  kst_util$garbage_collect entry (fixed bin (35));
110 dcl  kst_util$initialize_region entry (fixed bin);
111 dcl  kst_util$unthread_kste entry (ptr);
112 dcl  kstsrch entry (bit (36) aligned, fixed bin (17), ptr);
113 dcl  level$get entry () returns (fixed bin (3));
114 dcl  makeunknown_ entry (fixed bin, bit (36) aligned, bit (1) aligned, fixed bin (35));
115 dcl  sdw_util_$construct entry (ptr, ptr);
116 dcl  sdw_util_$dissect entry (ptr, ptr);
117 dcl  sdw_util_$get_valid entry (ptr, bit (1) aligned);
118 dcl  seg_fault$makeknown_activate entry (ptr, fixed bin (35));
119 dcl  setfaults$disconnect entry (fixed bin (17));
120 
121 /* Misc */
122 
123 dcl  (addr, baseno, fixed, null, ptr, rel, string, unspec) builtin;
124 %page;
125           makeknown_infop = a_makeknown_infop;
126           segno = a_segno;
127           a_use_count = 0;
128           a_code = 0;
129           kstp = pds$kstp;
130           ring = level$get ();
131           call kstsrch (makeknown_info.uid, hash_bucket, kstep);
132           if kstep ^= null () then do;                      /* got kste */
133                a_code = error_table_$segknown;
134                a_segno = kste.segno;
135                if (^kste.priv_init & makeknown_info.priv_init) | (^kste.allow_write & makeknown_info.allow_write) then do;
136                                                             /* access may increase -- could do this better */
137                     call setfaults$disconnect ((kste.segno));
138                     kste.dtbm = (36)"1"b;                   /* force access recomputation at next seg_fault */
139                end;
140           end;
141           else do;                                          /* get kste */
142                if makeknown_info.rsw then do;               /* reserved segment switch */
143                     if segno - kst.lowseg < ring |          /* lower ring stack or hardcore */
144                          segno > kst.highseg then call abort (error_table_$invalidsegno);
145                     if segno > kst.highest_used_segno then call kst_util$initialize_region (segno);
146                     kstep = addr (kst.kst_entry (segno));
147                     if unspec (kste.entryp) ^= "0"b then call abort (error_table_$segno_in_use);
148                     if kste.fp ^= (18)"1"b then call kst_util$unthread_kste (kstep);
149                end;
150                else do;
151                     if kst.free_list = "0"b                 /* the cupboard was bare */
152                     then if kst.highest_used_segno < kst.highseg
153                          then call kst_util$initialize_region (kst.highest_used_segno + 1);
154                          else do;
155                               call kst_util$garbage_collect (code);
156                               if code ^= 0 then call abort (code);
157                          end;
158                     if kst.free_list = ""b
159                     then                                    /* can't happen */
160                          call abort (error_table_$nrmkst);
161                     kstep = ptr (kstp, kst.free_list);      /* set kst entry pointer to first free entry */
162                     kst.free_list = kste.fp;                /* remove from free list */
163                     a_segno = kste.segno;                   /* return segment number */
164                end;                                         /* thread into hash class */
165                kste.fp = kst.uid_hash_bucket (hash_bucket);
166                kst.uid_hash_bucket (hash_bucket) = rel (kstep);
167                                                             /* if this is not the root increment parent infcount */
168                if makeknown_info.entryp ^= null () then do;
169                     pkstep = addr (kst.kst_entry (fixed (baseno (makeknown_info.entryp), 17)));
170                     pkstep -> kste.infcount = pkstep -> kste.infcount + 1;
171                end;                                         /* set up new kste */
172                kste.dirsw = makeknown_info.dirsw;
173                kste.uid = makeknown_info.uid;
174                kste.dtbm = (36)"1"b;                        /* force access computation at first seg_fault */
175 
176 /* force no access in sdw */
177 
178                call sdw_util_$dissect (addr (dseg$ (kste.segno)), addr (sdwi)); /* Take it apart to set access */
179 
180                sdwi.r1, sdwi.r2, sdwi.r3 = "0"b;
181                string (sdwi.access) = "0"b;
182 
183                call sdw_util_$construct (addr (dseg$ (kste.segno)), addr (sdwi)); /* Put it back together */
184           end;
185           kste.tus = pds$transparent.tus;
186           kste.tms = pds$transparent.tms | kste.dirsw;      /* THIS IS CRUCIAL to proper maintenance of dtcm for dirs */
187           kste.tpd = pds$transparent.tpd;
188           kste.allow_write = kste.allow_write | makeknown_info.allow_write;
189           kste.priv_init = kste.priv_init | makeknown_info.priv_init;
190           kste.entryp = makeknown_info.entryp;
191           kste.audit = makeknown_info.audit;
192           if kste.usage_count (ring) ^< 0                   /* mark kste as known in proper ring */
193           then kste.usage_count (ring) = kste.usage_count (ring) + 1;
194           a_use_count = kste.usage_count (ring);
195 
196           if makeknown_info.activate then do;
197                call sdw_util_$get_valid (addr (dseg$ (kste.segno)), valid);
198                if ^valid then do;
199                     call fim_util$fim_v_time_init_ext (vcpu_suspend_1, vcpu_suspend_2);
200                     call seg_fault$makeknown_activate (kstep, code);
201                                                             /* seg_fault/connect as required */
202                     if code = 0 then                        /* make activate vcpu free  */
203                          call fim_util$fim_v_time_calc_ext (vcpu_suspend_1, vcpu_suspend_2);
204                     else do;                                /* something really awful? */
205                          a_code = code;                     /* override any other error code */
206                          call makeunknown_ ((kste.segno), "01"b, ("0"b), code);
207                                                             /* force terminate */
208                     end;
209                end;
210           end;
211 
212           return;
213 
214 
215 abort:
216      proc (code);
217 dcl  code fixed bin (35);
218           a_code = code;
219           go to non_local_return;
220      end abort;
221 
222 non_local_return:
223           return;
224 %page;
225 %include kst;
226 %page;
227 %include makeknown_info;
228 %page;
229 %include sdw_info;
230 %page;
231 %include stack_header;
232      end makeknown_;