/* CPUID -- Display CPU information from REXX */ /* article in TSO TIMES, Fall 1993, by John Andrisan */ /* of IBM ISSC subdivision in Long Beach California */ /*********************************************************************/ /* A TSO REXX Exec to get information aobut CPUs from the MVS */ /* control blocks: DVT, SMCA, CSD, PCCAVT, and PCCA; then show CPU */ /* number, id serial number, type, SMF id letter, and anything else */ /* that looks interesting. */ /* */ /* The control block chain that I want to follow: */ /* location 10x --> CVT */ /* CVT+C4x --> SMCA */ /* SMCA+16 contains the SMF id */ /* CVT+294x --> CSD */ /* CSD+4, +8 and + 10 contain */ /* some interesting cpu counts */ /* CVT+2FCx --> PCCAVT */ /* PCCAVT+0 --> PCCA for CPU 0 */ /* PCCAVT+4 --> PCCA for CPU 1 */ /* ... etc. */ /* PCCAVT+60 --> PCCA for CPU 15 */ /* PCCA+4 contains the cpu id, serial#, type */ /* PCCA+24 --> virtual PSA */ /* PCCA+28 --> real PSA */ /*********************************************************************/ /* ---------begin available "The REXX Macros Toolbox" only portion*/ "CLS" /* clear screen*/ say '----- information obtained via WHICH CPU ------' "WHICH CPU" say ' ' say '----- information from CPUID -- Display CPU information' /* ------------ end available "The REXX Macros Toolbox" only portion*/ arg what . if what='?' then do /* offer the user some help */ say ' use: COMMAND ===> CPUID' say ' No parms are required' say ' You will be shown the SMF id letter defining this system,' say ' the CPU id, serial number, and CPU type of each CPU,' say ' This exec (CPUID) only works on TSO.' end if address() /='TSO' then do say 'This exec only works in MVS/TSO.' exit 4 end call init /* set up some constants */ CVT=storage('10',4) CVT=bitand(CVT,'7FFFFFFF'x) /* zero high bit */ SMCA=storage(d2x(c2d(CVT)+x2d('C4')),4) /* get to SMCA */ SMCA=bitand(SMCA,'7FFFFFFF'x) SMCASID=storage(d2x(c2d(SMCA)+16),4) say 'SMF id=' SMCASID CSD=storage(d2x(c2d(CVT)+x2d('294')),4) /* get to CSD */ CSD=bitand(CSD,'7FFFFFFF'x) /* zero high bit */ /* the counts shown next may change whil you run*/ nr_cpus=c2d(storage(d2x(c2d(CSD)+10),2)) /* get nr cur alive */ say 'nr cpus currently alive:' nr_cpus /* whatever that is */ job_avail_cpus=x2b(c2x(storage(d2x(c2d(csd)+4),2))) say count_bits(job_avail_cpus) 'available for jobs' srb_avail_cpus=x2b(c2x(storage(d2x(c2d(csd)+8),2))) say count_bits(srb_avail_cpus) 'available for srbs' cur_alive_cpus=x2b(c2x(storage(d2x(c2d(CSD)+10),2))) say count_bits(cur_alive_cpus) 'currently alive' say ' ' PCCAAVT=storage(d2x(c2d(CVt)+x2d('2FC')),4) /* get to PCCAVT */ PCCAAVT=bitand(PCCAAVT,'7FFFFFFF'x) /* zero high bit*/ say '-----CPU-------------- PSA PSA ' say '# ver id serial type vaddr raddr status:' do i=0 to 60 by 4 PCCA=storage(d2x(c2d(PCCAAVT)+i),4) /* get the i-th PCCA */ PCCA=bitand(PCCA,'7FFFFFFF'x) /* zero high bit */ if PCCA=='00000000'x then iterate i /* avoid empty entry */ info=storage(c2x(PCCA),32) if substr(job_avail_cpus,i%4+1,1)='1' then jobs='jobs' else jobs='no-jobs' if substr(srb_avail_cpus,i%4+1,1)='1' then srbs='srbs' else jobs='no-srbs' if substr(cur_alive_cpus,i%4+1,1)='1' then alive='alive' else alive='no-alive' /* as run "The REXX Macros Toolbox" 1993/12/16 SMF id= H901 nr cpus currently alive: 5 5 available for jobs 5 available for srbs 2 currently alive -----CPU-------------- PSA PSA # ver id serial type vaddr raddr status: 00 52 0 12495 3090 8000F6F0 00157240 jobs srbs no-alive 01 52 1 12495 3090 7800F9F0 00134030 jobs srbs no-alive 02 52 2 12495 3090 0000F980 0002F040 jobs srbs no-alive 03 52 3 12495 3090 0000F960 00068040 jobs srbs no-alive 04 52 4 12495 3090 1000F7F0 000A2040 jobs srbs no-alive 05 a: 9 & 00070C30 0080007B no-srbs srbs no-alive */ say , /*cpu number:*/ right(i%4,2,'0')' ', /*cpu ver : */ substr(info,5,2)' ', /*cpuid: */ substr(info,7,1), /*cpu serial:*/ substr(info,8,5)' ', /*cpu type: */ substr(info,13,4)' ', /*PSA vaddr:*/ c2x(substr(info,24,4))' ', /*PSA raddr:*/ c2x(substr(info,28,4))' ', /* the status shown next may change while you run*/, /*status:*/ jobs srbs alive end exit 0 /* ------------------- subroutines ---------------------- */ count_bits: arg bit_string . bit_sum = 0 do bit=1 to length(bit_string) if substr(bit_string,bit,1)='1' then bit_sum=bit_sum + 1 end return(bit_sum) X2B: /* X2B is a function for hex to binary string conversion*/ arg arg . bitout='' do i=1 to length(arg) t=substr(arg,i,1) bitout=bitout||hex.t end return bitout init: /* constants needed in x2b */ hex.0='0000'; hex.1='0001'; hex.2='0010'; hex.3='0011'; hex.4='0100'; hex.5='0101'; hex.6='0110'; hex.7='0111'; hex.8='1000'; hex.9='1001'; hex.A='1010'; hex.B='1011'; hex.C='1100'; hex.D='1101'; hex.E='1110'; hex.F='1111'; return