Beispiel #1
0
static void
ztpfDeriveUcontext( ucontext_t *uscPtr ) { 
   DIB * pDib = ecbp2()->ce2dib;
   DBFHDR * pJdb = (DBFHDR *)(pDib->dibjdb);
   DBFITEM * pDbi = NULL;
   void * lowcore = NULL;

   if( pJdb ) {					 /* If JDB contents are for this thread */
	  if( pJdb->ijavcnt ) {		 /*  and the JDB is unlocked			*/
		 pDbi = (DBFITEM *)(pJdb+1);		 /* Point at the JDB base	*/
		 lowcore = (pDbi->ijavsbuf);		/*  and its low core copy. */
	  }
	  else {					 /* Otherwise use what's in the DIB		*/
		 lowcore = pDib->dilow;  /* Use the low core pointer from DIB	*/
	  }
   }
	/*
     *	 Fill in the uc_mcontext, uc_flags and uc_sigmask fields. 
	 *	 Leave uc_link alone, it has no meaning in or for z/TPF.
     */
   uscPtr->uc_mcontext.psw.mask = pDib->dispw[0];  /* PSW lo half */
   uscPtr->uc_mcontext.psw.addr = pDib->dispw[1];  /* PSW hi half */
   memcpy( uscPtr->uc_mcontext.gregs,
		  pDib->direg, sizeof(pDib->direg) );		/*GPRs*/
	memcpy( uscPtr->uc_mcontext.fpregs.fprs, 
		  pDib->dfreg, sizeof(pDib->dfreg) );		/*FPRs*/
	uscPtr->uc_flags = ecbp2()->ce2thnum;			/* Put the TID in ucontext->uc_flags  */
	sigprocmask( SIG_SETMASK, NULL, &(uscPtr->uc_sigmask) ); /* Our mask is the old mask  */
	return;
}
Beispiel #2
0
void
ztpf_nonpreemptible_helper(void)
{
	safeStorage *s = allocateDurableStorage();
	uint8_t holdkey;
	sigset_t newmask;
	sigset_t oldmask;

	/*
	 *    Go translate the TPF-ish data available at interrupt time into UNIX-ish
	 *    formatted blocks in preparation to call the master synchronous signal
	 *    handler for the JVM's structured signal handling architecture. This
	 *    storage comes from a static storage segment in DJPR.
	 */
	s->pDIB = (DIB *) (ecbp2()->ce2dib);
	s->argv.dibPtr = s->pDIB;
	translateInterruptContexts(&(s->argv));

	/*
	 *    Only proceed if (1) the signal is currently NOT blocked, and (2)
	 *    if no other interrupt has queued itself. In the interim, if
	 *    applicable, sleep for 50 ms. IOW, serialize all synchronous
	 *    signals -- we have to, we only have one JDB.
	 */
	sigemptyset(&newmask); /* Ensure our 'constant' mask word is zeros    */
	sigaddset(&newmask, s->siginfo.si_signo); /* Build a constant signal mask word        */

	do {
		PROC_LOCK(&(s->pPROC->iproc_JVMLock), holdkey);
		if (s->pPROC->iproc_tdibptr) { /* Are we blocked because we're already    working    */
			PROC_UNLOCK(&(s->pPROC->iproc_JVMLock), holdkey); /* another signal? If so,unlock    */
			usleep(50000); /* and sleep for 50 ms.            */
		}
		pthread_sigmask(SIG_BLOCK, NULL, &oldmask); /* Test the signal mask again.    */
	} while ((newmask & oldmask) || (s->pPROC->iproc_tdibptr));
	/*
	 *    We are released to go process this signal. Do it. The lock we also hold
	 *    on our little subsection of the PROC block is also still in effect.
	 *    But first, stash the DIB pointer in the IPROC block, then unlock it.
	 */
	s->pPROC->iproc_tdibptr = (uint64_t) s->pDIB; /*    Stash the faulting DIB pointer            */
	PROC_UNLOCK(&(s->pPROC->iproc_JVMLock), holdkey);
	/*
	 * Call the master structured signal handler for synchronous signals.
	 * It's not possible that an async signal can get here. The signal handler will
	 * either hand off execution to the JIT, or will run the dump agents. Do not
	 * expect a return; else the normal SIG_DFL (bye, bye) rule applies.
	 */
	masterSynchSignalHandler(s->siginfo.si_signo, &(s->siginfo), &(s->ucontext),
			s->pDIB->dbrevn);
	/*
	 * If execution returns to this point, the signal handler returned
	 * here. This means that the thread accepts the consequences of a
	 * return from the SIG_DFL treatment of a fatal signal, which means
	 * an end to the process.
	 */
	exit(0);
	/* UNREACHABLE */
}
Beispiel #3
0
Datei: os.c Projekt: ATCP/mtcp
int os_check_server(char *server) {
#ifndef USE_TPF_DAEMON
    int rv;
    int *current_acn;
    if((rv = inetd_getServerStatus(server)) == INETD_SERVER_STATUS_INACTIVE)
        return 1;
    else {
        current_acn = (int *)cinfc_fast(CINFC_CMMACNUM);
        if(ecbp2()->ce2acn != *current_acn)
            return 1;
    }
#endif
    return 0;
}
Beispiel #4
0
void
ztpf_preemptible_helper(void)
{
	safeStorage *s = allocateDurableStorage();
	translateInterruptContexts(&(s->argv));

	s->argv.flags = J9TPF_NO_PORT_LIBRARY;
	s->pDIB = ecbp2()->ce2dib;
	s->argv.dibPtr = s->pDIB;
	masterSynchSignalHandler(s->siginfo.si_signo, &(s->siginfo), &(s->ucontext),
			s->pDIB->dbrevn);
	/*
	 * Like its "harder" cousin, below, if the signal handler returns here, it is
	 * acknowledging that it wants to exit. Otherwise, don't expect a return. In
	 * the normal case, the faulting thread gets returned to the J9 thread pool
	 * so there's no chance of an accidental return here.
	 */
	exit(0);
	/* UNREACHABLE */
}
Beispiel #5
0
/**
 * \internal
 *      
 * \details Build the data (in the user-passed <TT>buffer</TT> address)
 * block to which an Elf64_Phdr will point. Its role is to extract 
 * information passed to it in CE2DIB and IJAVDBF and put them in the
 * proper places. Sometimes these values require translation to put 
 * them into proper contextual meaning, for example, a hardware PIC code
 * can infer a signal value. As long as we get close enough, it's good.
 * The contents of the NOTE section are very poorly documented.
 *
 * \note The final sub-section, tagged <i><tt>NT_ZTPF_SERRC</tt></i>, is invented 
 * for this routine's purposes: its role is to express the SE number associated 
 * with the already-written traditional SERRC dump as requested during design. Its 
 * existence may require addition of a method to the Java class which processes 
 * ELF NOTEs in <b><tt>jdmpview</tt></b> - there is no ELF NOTE tag otherwise 
 * suited for this purpose. Otherwise, this information stays buried.
 *
 * This function returns the total size of the buffer as its Elf64_Phdr
 * must report it.
 *
 * \param[in]  buffer    Writeable memory large enough to house the NOTE
 *                        section (see \ref NOTE_TABLE_SIZE, above).
 * \param[in]  dibPtr    Address of the CPSE<->JVM Dump Interchange Block
 *                        belonging to the faulting or requesting Unit Of Work.
 * \returns
 *         Size, in bytes, of the NOTE table section as written.
 */
static uintptr_t
buildELFNoteArea(Elf64_Nhdr *buffer, DIB *dibPtr)
{
	uintptr_t tableSize = NOTE_TABLE_SIZE; /* Return value                    */

	/* Pointers to the different required NOTE subsections, in sequential
	 * order of appearance: PRSTATUS, PRPSINFO, AUXV, FPREGSET, and
	 * S390_LAST_BREAK. The NOTE subsections are a little bizarre: each has a
	 * header of 0x0c bytes in length, followed by a displayable label of
	 * what it is. In general, these headers end up being 0x14 bytes in length
	 * because their data needs to be fullword-aligned. So, in general, the ptr
	 * prefixed with "nsh_" is the lower of the two addresses, being the
	 * Elf64_Nhdr pointer, and the un-prefixed pointer is where the data goes.
	 * Kinda screwy, but so is the NOTE section itself when there are a number
	 * of subsections in sequence.
	 */
	Elf64_Nhdr *nsh_prstat; /* NT_PRSTATUS NOTE header        */
	prstatus_t *prstat; /* PRSTATUS NOTE data ptr        */
	Elf64_Nhdr *nsh_prpsin; /* NT_PRPSINFO NOTE header        */
	prpsinfo_t *prinfo; /* PRPSINFO NOTE data ptr        */
	Elf64_Nhdr *nsh_auxvxx; /* NT_AUXV NOTE header            */
	AUXV *auxv; /* NT_AUXV NOTE data ptr        */
	Elf64_Nhdr *nsh_fpregs; /* NT_FPREGSET NOTE header        */
	fpregset_t *fpregs; /* NT_FPREGSET data ptr            */
	Elf64_Nhdr *nsh_lastbr; /* NT_S390_LAST_BREAK NOTE hdr    */
	uint16_t signalNumber;
	siginfo_t wSiginfo;

	DIB *holdDibPtr;
	DBFHDR *dbfPtr = dibPtr->dibjdb;
	/*
	 *    The ERI sits as the first JDB index item. We have to bump its pointer
	 *    past the DBFHDR, which just so happens to be the same length as a DBFITEM
	 *    itself.
	 */
	DBFITEM *eriRef = (DBFITEM *) dbfPtr + 1;
	struct cderi *eriPtr = (struct cderi *) (eriRef->ijavsbuf);
	/*
	 * z/TPF keeps its process information in a unique IPROC block, address it.
	 */
	struct iproc *pIPROC = iproc_process; /* Ptr to this PID's IPROC block */
	struct iproc *pPIPROC; /* Ptr to mom's PID IPROC block    */
	/*
	 *     The datatypes inside each NOTE section and subsection are so diverse
	 *     as to make the commonly-used typecasting approach cumbersome and difficult
	 *     to understand. Often working pointer fields which have a length of 1 for
	 *     address arithmetic uses are the easiest or best way to do this yet still
	 *     have legible code. We use all three of the following data objects in that
	 *     vein.
	 */
	uint8_t *wSrc; /* General uint8_t address pointer    */
	uint8_t *wDest; /* General uint8_t address pointer    */
	uint8_t *wPtr; /* General uint8_t address pointer    */

	/*
	 *     Build the NT_PRSTATUS subsection first
	 */
	KEY0();
	memset(buffer, 0, tableSize); /* Clear the entire buffer        */
	nsh_prstat = buffer; /* Start the data sec hdr ptr.    */
	prstat = (prstatus_t *) NOTE_DATA_OFFSET(nsh_prstat); /* Point at its data*/
	nsh_prstat->n_namesz = 5; /* Size of "CORE" = 5            */
	nsh_prstat->n_descsz = sizeof(prstatus_t);
	nsh_prstat->n_type = NT_PRSTATUS; /* Type = 1                        */
	memcpy(nsh_prstat + 1, "CORE", 5); /* Label this one "CORE".        */
	/*
	 *    The "current signal" value is inferred from the h/w PIC value lookup.
	 *    Unfortunately, ztpfDeriveSiginfo() is coded to use the DIB hung off
	 *    page 2 of the ECB, not the passed DIB. So hold on to the real
	 *    DIB address for this ECB in a safe place, and stuff the passed dibPtr
	 *    into page 2 of the ECB before the call, then replace it after the
	 *    call.
	 */
	holdDibPtr = ecbp2()->ce2dib; /* Substitute the passed DIB    */
	ecbp2()->ce2dib = dibPtr; /*  for the real one, then ...    */
	UNKEY(); /*  reset the SPK to prob state */
	ztpfDeriveSiginfo(&wSiginfo); /* While we go build a long        */
	KEY0(); /*  siginfo_t from which to        */
	prstat->info.si_signo = wSiginfo.si_signo; /*  feed the short one. After    */
	prstat->info.si_code = wSiginfo.si_code; /*  we've returned, get back    */
	prstat->info.si_errno = wSiginfo.si_errno; /*  into supv state prot key.    */
	prstat->cursig = wSiginfo.si_errno;
	ecbp2()->ce2dib = holdDibPtr; /* Replace the real DIB pointer    */
	/*
	 *    The relative PID values come from the process block .... Just read
	 *  them dirty; don't bother with a lock at first, see if it works before
	 *  we take a chance on losing ctl with a lock
	 */
	prstat->pid = pIPROC->iproc_pid; /* My PID                    */
	prstat->pgid = pIPROC->iproc_pgid; /* My PGID                    */
	prstat->ppid = pIPROC->iproc_pptr->iproc_pid; /* Mom's PID                */
	/* No concept of a session ID    */
	/*
	 * The System z TOD clock ticks once every 244 picoseconds. To get to accurate
	 * nanoseconds, we'd need to divide its value by 4.09836. Since we can't
	 * divide by a fractional quantity without going to floating point (and
	 * thereby introducing approximation error & burning more cycles), we
	 * usually trade precision for speed by shifting right 2 bits (dividing by 4)
	 * to yield nanoseconds from a little less than a quarter of a ns. That's
	 * considered close enough. But now that we need _micro_second (ns * 1000)
	 * precision, we'd be amplifying the error. And since we have to divide by 1000
	 * anyway, we might as well divide by 4098 (would shifting right 12 bits, for
	 * 4096, be close enough? No. That would cause us to lose a full millisecond in
	 * precision error!) to be accurate. So that's what we're doing below, since
	 * we have to eat the cycles in the division operation anyway -- might as well
	 * use the right divisor. Never mind rounding up with the remainder; we're
	 * already generating a larger result than reality because we can't go
	 * fractional. Does it really matter? Nah. But if you're gonna do it, you might
	 * as well do it right ....
	 */
	prstat->stime.tv_usec = ecbptr()->ce1istim / 4098; /* Used CPU time    */
	wDest = (char *) &(prstat->reg); /* Point at offset +0 of reg fld    */
	/*
	 *     The PGM/O PSW is followed by a 16-wide array of ULONGs which
	 *     represent the values of all 16 general registers, 0 through 15,
	 *     as they were at the time the PGM/N PSW fired. Prepare to copy
	 *     them into the NT_PRSTATUS section, lth=128+16 (144).
	 */
	wSrc = (char *) (dibPtr->dispw); /* Point @ PSW & general regs        */
	memcpy(wDest, wSrc, 144); /* Preserve all that data.            */
	prstat->fpvalid = TRUE; /* Yes, we have floating point        */
	/*
	 * NT_PRPSINFO is next
	 */
	nsh_prpsin = (Elf64_Nhdr *) (prstat + 1); /* Point to next NOTE hdr    */
	prinfo = (prpsinfo_t *) NOTE_DATA_OFFSET(nsh_prpsin);
	nsh_prpsin->n_namesz = 5; /* Size of "CORE" = 5        */
	nsh_prpsin->n_descsz = sizeof(prpsinfo_t);
	nsh_prpsin->n_type = NT_PRPSINFO; /* Type = 3                    */
	memcpy(nsh_prpsin + 1, "CORE", 5); /* Set "CORE" name ...        */
	prinfo->char_state = 'R'; /* We were 'R'unning.        */
	prinfo->flag = 0x00400440L; /* Flags are constant        */
	prinfo->uid = pIPROC->iproc_uid; /* User id &                */
	prinfo->gid = pIPROC->iproc_gid; /*  group id.                */
	memcpy(&prinfo->pid, &prstat->pid, 16); /* Process ID set again        */
	strcpy(prinfo->fname, "main"); /* Just like Linux does it    */
	wSrc = getenv("IBM_JAVA_COMMAND_LINE");
	if (wSrc) {
		strncpy(prinfo->psargs, wSrc, PRARGSZ);
		prinfo->psargs[PRARGSZ - 1] = '\0';
	}
	/*
	 * NT_AUXV after that ... we fake it (we have no ELF protocols involved
	 * in task switching and thus have no AUXV structure or meaning).
	 */
	nsh_auxvxx = (Elf64_Nhdr *) (prinfo + 1); /* Next NOTE header            */
	auxv = (AUXV *) NOTE_DATA_OFFSET(nsh_auxvxx); /* and data region ptr.    */
	nsh_auxvxx->n_namesz = 5; /* Size of "CORE" = 5        */
	nsh_auxvxx->n_descsz = sizeof(AUXV);
	nsh_auxvxx->n_type = NT_AUXV; /* Type = 6                    */
	memcpy(nsh_auxvxx + 1, "CORE", 5); /* Set "CORE" name ...        */
	memset(auxv, 0, sizeof(AUXV)); /* Fill it out.                */
	/*
	 * ... then NT_FPREGSET
	 */
	nsh_fpregs = (Elf64_Nhdr *) (auxv + 1); /* Next NOTE header            */
	fpregs = (fpregset_t *) NOTE_DATA_OFFSET(nsh_fpregs); /* and data ptr    */
	nsh_fpregs->n_namesz = 5; /* Size of "CORE" = 5        */
	nsh_fpregs->n_descsz = sizeof(fpregset_t);
	nsh_fpregs->n_type = NT_FPREGSET; /* Type = 2                    */
	memcpy(nsh_fpregs + 1, "CORE", 5); /* Set "CORE" name ...        */
	/*
	 * We don't care what the real FPCR contained. We're setting the mask
	 * only to state that 16 fprs exist. The real FPCR is too hard to get,
	 * anyway.
	 */
	fpregs->fpcr = 0x00800000;
	wSrc = (uint8_t *) &(dibPtr->dfreg); /* Get the adrs of the fp    */
	wDest = (uint8_t *) &(fpregs->fpreg); /*  regs, then copy them    */
	memcpy(wDest, wSrc, sizeof(fpregs->fpreg)); /*  into the note area.    */
	/*
	 * ... then NT_S390_LAST_BREAK
	 */
	nsh_lastbr = (Elf64_Nhdr *) (fpregs + 1);
	nsh_lastbr->n_namesz = 6; /* Size of "LINUX" = 6        */
	nsh_lastbr->n_descsz = 8; /* Always 0x008 bytes.        */
	nsh_lastbr->n_type = 0x306; /* Type = NT_S390_LAST_BR    */
	wDest = (uint8_t *) NOTE_DATA_OFFSET(nsh_lastbr);
	memcpy(nsh_lastbr + 1, "LINUX", 6); /* Set "LINUX" name            */
	wSrc = (char *) (dibPtr->dbrevn); /* Get NOTE data source ptr */
	memcpy(wDest, wSrc, 8); /*  and move it in.            */
	UNKEY();
	return tableSize; /* We're done.                */
	/*
	 * ... and finally, NT_ZTPF_SERRC (made up; we'll need to add the Java
	 * class code to display this)
	 */
	wPtr += 8;
	nsh_lastbr = (Elf64_Nhdr *) (wDest + 8);
	nsh_lastbr->n_namesz = 5; /* Size of "ZTPF" = 5        */
	nsh_lastbr->n_descsz = 68; /* Always 0x044 bytes.        */
	nsh_lastbr->n_type = 0x500; /* Type = 500                */
	memcpy(nsh_lastbr + 1, "ZTPF", 5); /* Set "ZTPF" name ...        */
	wDest += 0x14; /*  and point at data        */
	sprintf(wDest, "SE-%4.4d OPR-%c%6.6X PGM-%4.4s %5.5c %8.8s", eriPtr->eriseq,
			eriPtr->eridpfx, eriPtr->eridnum, eriPtr->eridate, eriPtr->eritime);
	UNKEY();
	return tableSize; /* We're done.                */
}
Beispiel #6
0
void
ztpfDeriveSiginfo( siginfo_t *build ) {
   uint16_t	pic;
   uint16_t	ilc;
   uint8_t dxc;
   sigvpair_t *translated = NULL;
   void *lowcore = NULL;
   DIB *pDib = ecbp2()->ce2dib;
   DBFHDR *pDbf = (DBFHDR *)(pDib->dibjdb);
   DBFITEM *pDbi;
   struct cderi *pEri = NULL;
   struct iproc *procPtr = iproc_process;

   /*
	*	 If we have a java dump buffer (ijavdbf) which belongs to this
	*	 thread AND that buffer is not locked, then use it. We prefer
	*	 the low core image in the java dump buffer to the copy in the
	*	 DIB; but use the DIB's copy if there's no buffer.
	*/
   if( pDbf && pDbf->ijavcnt ) {	/* We have the full Error Recording Info, use it.	*/
	  pDbi = (DBFITEM *)pDbf+1;					/* We have a bunch of void ptrs			*/
	  pEri = (struct cderi *)(pDbi->ijavsbuf);	/*	to cast through ... ugh...			*/
	  lowcore = pEri;							/* And struct cderi is incomplete ...	*/
	  lowcore += (unsigned long int)0x310;		/*	ai yi yi Lucy.						*/
   }
   else {							/* All we have is the DIB, so use it instead.		*/
	  lowcore = pDib->dilow;					/* Fixup low core pointer				*/
	  pEri = NULL;								/* And indicate there's no full ERI.	*/
   }
   pic = s390FetchPIC( lowcore );		/* Translate the PIC into si_signo & si_code	*/
   translated = (sigvpair_t *)&pic2pair[pic];
   build->si_signo = translated->si_signo;
   build->si_code = translated->si_code;
   /*
	* This could just as well have been an "if-then-else" construct, but
	* it was felt wise to leave it in case testing revealed something else
	* that requires analysis.
	*/
   switch( build->si_signo ) { 
   case SIGFPE:
	  if( 0 == build->si_code ) {		   /* If we need to interpret DXC bits,   */
		 /*
		 * Returning a good si_code value means we have to interrogate the
		 * DXC value, so go get a normalized version of it.
		 */
		 dxc = s390FetchDXC( lowcore );
		 /*
		  * "Sluice" through the acceptable values of the DXC for known si_code
		  * values. If we don't find one, call it SI_KERNEL for lack of any 
		  * better idea.
		  */
		 if( 0x09 == dxc )
			build->si_code = FPE_INTDIV;
		 else if( 0x08 == dxc )
			build->si_code = FPE_INTOVF;
		 else if( 0x40 == dxc )
			build->si_code = FPE_FLTDIV;
		 else if( 0x20 == dxc )
			build->si_code = FPE_FLTOVF;
		 else if( 0x10 == dxc )
			build->si_code = FPE_FLTUND;
		 else if( 0x08 == dxc )
			build->si_code = FPE_FLTRES;
		 else if( 0x80 == dxc )
			build->si_code = FPE_FLTINV;
		 else
			build->si_code = SI_KERNEL;    /* Unknown synchronous signal	  */
	  }
	  break;
	/*
	 * SIGSEGV signals need si_addr set to the addr that failed translation
	 * It's in the ERI, but not in the DIB. So if we have an ERI, use it.
	 */
   case SIGSEGV:
	  if( build->si_code == SEGV_MAPERR && pEri ) { 
		 uint64_t *address;
		 lowcore = pEri;			/* The failing vaddr is at ISVTRXAD */
		 address = lowcore+(unsigned long int)0x1b8;	/*	at offset 0x1B8 into the ERI*/
		 build->si_addr = (void *)*address; /* Move the failed address.		*/
	  }									/* Otherwise leave it zero.			*/
	  break;
   case SIGILL:
	  build->si_addr = (char *)pDib->dispw[1];	/*	Failing PSW $IP			*/
	  break;
   default:
	  break;
   }										
   build->si_pid = procPtr->iproc_pid;	/* All of them need PID and			 */
   build->si_uid = procPtr->iproc_uid;	/*	UID values, with TID & errno	 */
   build->si_ztpf_tid = ecbp2()->ce2thnum; /* values, too.					 */
   build->si_errno = errno;
   return;
}