Files
Arquivotheca.AIX-4.1.3/bos/kernel/proc/POWER/fp_trapstate_ker.c
seta75D d6fe8fe829 Init
2021-10-11 22:19:34 -03:00

238 lines
5.1 KiB
C

static char sccsid[] = "@(#)29 1.5 src/bos/kernel/proc/POWER/fp_trapstate_ker.c, sysproc, bos411, 9428A410j 4/13/94 14:31:24";
/*
* COMPONENT_NAME: SYSPROC
*
* FUNCTIONS: _fp_trapstate_ker
*
*
* ORIGINS: 27,83
*
* IBM CONFIDENTIAL -- (IBM Confidential Restricted when
* combined with the aggregated modules for this product)
* SOURCE MATERIALS
*
* (C) COPYRIGHT International Business Machines Corp. 1994
* All Rights Reserved
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*/
#include <sys/user.h>
#include <sys/machine.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/fp_cpusync.h>
#include <sys/systemcfg.h>
#include <fptrap.h>
#include <sys/systm.h>
#include <sys/mstsave.h>
#include <sys/syspest.h>/* to define the assert and ASSERT macros */
extern void disown_fp();
/*
* NAME: _fp_trapstate_ker()
*
* FUNCTION:
* _fp_trapstate_ker() system call; sets or queries a process's state
* as regards the MSR(FE and/or IE) bits.
*
* EXECUTION ENVIRONMENT:
* Preemptable, Interrupts enabled on input.
* Runs on Pinned Kernel Stack for SVCs.
* An AIX Signal will not be delivered until this code is through
* running. This serializes `u.u_save.fpinfo' updates.
* This code is pageable.
*
* NOTES:
*
* INPUT:
*
* OUTPUT:
*/
int
_fp_trapstate_ker( int flag )
{
int rc; /* return value */
int work; /* working copy of fpinfo */
/* First, figure out what the current state is,
* in terms of the contents of fpinfo and what
* platform is running.
*/
work = u.u_save.fpinfo & (FP_IMP_INT | FP_SYNC_TASK);
/* for PowerPC, all combinations of the
* fpinfo bits 0x8 and 0x1 are valid.
*/
if (__power_pc())
{
switch (work)
{
case PPC_OFF:
rc = FP_TRAPSTATE_OFF;
break;
case PPC_IMP:
rc = FP_TRAPSTATE_IMP;
break;
case PPC_IMP_REC:
rc = FP_TRAPSTATE_IMP_REC;
break;
case PPC_PRECISE:
rc = FP_TRAPSTATE_PRECISE;
break;
default:
return FP_TRAPSTATE_ERROR;
}
}
else
/* Rios, RSC or Rios-2 */
{
switch (_system_configuration.implementation)
{
/* For Rios-1 and RSC, if the SYNC_TASK bit is
* on the process is in precise trap mode, else
* no traps can be generated.
*/
case POWER_RS1:
case POWER_RSC:
if (work & FP_SYNC_TASK)
rc = FP_TRAPSTATE_PRECISE;
else
rc = FP_TRAPSTATE_OFF;
break;
/* For Rios-2 there is a hierarchy for the
* bits. If FP_SYNC_TASK is on, the process
* is is precise trap mode. Otherwise,
* if the FP_IMP_INT bit is on the process is
* in imprecise mode, otherwise in no traps mode.
*/
case POWER_RS2:
if (work & FP_SYNC_TASK)
rc = FP_TRAPSTATE_PRECISE;
else
if (work & FP_IMP_INT)
rc = FP_TRAPSTATE_IMP;
else
rc = FP_TRAPSTATE_OFF;
break;
default:
return FP_TRAPSTATE_ERROR;
}
}
/* take care of query case first; it doesn't
* have to disown the FP unit
*/
if (flag == FP_TRAPSTATE_QUERY)
{
return rc;
}
/*
* Make sure this process does not own the fp unit.
* This will force the SVC handler back-end to
* reset the FE, IE and FP bits for the task.
*/
disown_fp( curthread->t_tid );
if (flag != FP_TRAPSTATE_FASTMODE)
{
switch(flag)
{
case FP_TRAPSTATE_PRECISE:
if (__power_pc())
{
u.u_save.fpinfo |= PPC_PRECISE;
}
else
{
u.u_save.fpinfo &= ~FP_IMP_INT;
u.u_save.fpinfo |= FP_SYNC_TASK;
}
return rc;
case FP_TRAPSTATE_IMP:
if (__power_pc())
{
u.u_save.fpinfo &= ~PPC_PRECISE;
u.u_save.fpinfo |= PPC_IMP;
}
else
{
if (__power_rs2())
{
u.u_save.fpinfo &= ~FP_SYNC_TASK;
u.u_save.fpinfo |= FP_IMP_INT;
}
else
{
return FP_TRAPSTATE_UNIMPL;
}
}
return rc;
case FP_TRAPSTATE_IMP_REC:
if (__power_pc())
{
u.u_save.fpinfo &= ~PPC_PRECISE;
u.u_save.fpinfo |= PPC_IMP_REC;
}
else
return FP_TRAPSTATE_UNIMPL;
return rc;
case FP_TRAPSTATE_OFF:
u.u_save.fpinfo &= ~PPC_PRECISE;
return rc;
default:
return FP_TRAPSTATE_ERROR;
}
}
else
{
/* FASTMODE */
switch (_system_configuration.implementation)
{
/* Note: future implementations should have
* appropriate case clauses added.
*/
case POWER_601:
u.u_save.fpinfo |= PPC_PRECISE;
return FP_TRAPSTATE_PRECISE;
case POWER_RS1:
case POWER_RSC:
u.u_save.fpinfo &= ~FP_IMP_INT;
u.u_save.fpinfo |= FP_SYNC_TASK;
return FP_TRAPSTATE_PRECISE;
case POWER_RS2:
u.u_save.fpinfo &= ~FP_SYNC_TASK;
u.u_save.fpinfo |= FP_IMP_INT;
return FP_TRAPSTATE_IMP;
default:
/* A PowerPC platform we don't know about.
* The default is precise mode.
*/
u.u_save.fpinfo |= PPC_PRECISE;
return FP_TRAPSTATE_PRECISE;
}
}
}