mirror of
https://github.com/SDL-Hercules-390/hyperion.git
synced 2026-07-26 02:29:51 +02:00
496ebf3d67
1. Acquire use of the signaling and response facility prior to system_reset Hackaround to #806: "ARCHLVL cpu reset leading to interrupt handling race" 2. refactor: thread safe utility functions Updates a few utility functions designated/considred MT-Safe by POSIX or most modern implementations (e.g., glibc).
311 lines
11 KiB
C
311 lines
11 KiB
C
/* ARCHLVL.C (C) Copyright Jan Jaeger, 2010-2012 */
|
|
/* (C) Copyright "Fish" (David B. Trout), 2018-2019 */
|
|
/* Architecture Level functions */
|
|
/* */
|
|
/* Released under "The Q Public License Version 1" */
|
|
/* (http://www.hercules-390.org/herclic.html) as modifications to */
|
|
/* Hercules. */
|
|
|
|
#include "hstdinc.h"
|
|
|
|
#define _ARCHLVL_C_
|
|
#define _HENGINE_DLL_
|
|
|
|
#include "hercules.h"
|
|
#include "opcode.h" // Need DEF_INST
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* (delineates ARCH_DEP from non-arch_dep) */
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
#if !defined( _GEN_ARCH )
|
|
|
|
// _ARCH_NUM_0 has been built.
|
|
// Now build the other architectures...
|
|
|
|
#if defined( _ARCH_NUM_1 )
|
|
#define _GEN_ARCH _ARCH_NUM_1
|
|
#include "archlvl.c"
|
|
#endif
|
|
|
|
#if defined( _ARCH_NUM_2 )
|
|
#undef _GEN_ARCH
|
|
#define _GEN_ARCH _ARCH_NUM_2
|
|
#include "archlvl.c"
|
|
#endif
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* (delineates ARCH_DEP from non-arch_dep) */
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* ACTUAL Architecture bit-masks */
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
#undef NONE
|
|
#undef S370
|
|
#undef E390
|
|
#undef Z900
|
|
#undef Z390
|
|
#undef MALL
|
|
|
|
#define NONE 0x00 /* NO architectures or disabled */
|
|
#define S370 0x80 /* S/370 architecture */
|
|
#define E390 0x40 /* ESA/390 architecture */
|
|
#define Z900 0x20 /* z/Arch architecture */
|
|
|
|
#define Z390 (E390|Z900) /* BOTH ESA/390 and z/Arch */
|
|
#define MALL (S370|Z390) /* All architectures */
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Architecture Level Table */
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
static ARCHTAB archtab[] =
|
|
{
|
|
//---------------------------------------------------------
|
|
//
|
|
// The "_ARCH_nnn_NAME" entries MUST come first. The
|
|
// 'get_archtab_by_arch' function expects it.
|
|
//
|
|
// The FIRST entry is our DEFAULT initial startup archi-
|
|
// tecture set by the 'init_default_archmode' function.
|
|
//
|
|
//---------------------------------------------------------
|
|
|
|
#if defined( _900 )
|
|
AT( _ARCH_900_NAME, ARCH_900_IDX, Z900 ) // "z/Arch" feat900.h
|
|
#endif
|
|
#if defined( _390 )
|
|
AT( _ARCH_390_NAME, ARCH_390_IDX, E390 ) // "ESA/390" feat390.h
|
|
#endif
|
|
#if defined( _370 )
|
|
AT( _ARCH_370_NAME, ARCH_370_IDX, S370 ) // "S/370" feat370.h
|
|
#endif
|
|
|
|
// Other supported names come afterwards, in any order.
|
|
|
|
#if defined( _370 )
|
|
AT( "S370", ARCH_370_IDX, S370 )
|
|
AT( "370", ARCH_370_IDX, S370 )
|
|
#endif
|
|
#if defined( _390 )
|
|
AT( "ESA390", ARCH_390_IDX, E390 )
|
|
AT( "E390", ARCH_390_IDX, E390 )
|
|
AT( "E/390", ARCH_390_IDX, E390 )
|
|
AT( "ESA", ARCH_390_IDX, E390 )
|
|
AT( "S/390", ARCH_390_IDX, E390 )
|
|
AT( "OS/390", ARCH_390_IDX, E390 )
|
|
AT( "S390", ARCH_390_IDX, E390 )
|
|
AT( "OS390", ARCH_390_IDX, E390 )
|
|
AT( "390", ARCH_390_IDX, E390 )
|
|
#endif
|
|
#if defined( _900 )
|
|
AT( "zArch", ARCH_900_IDX, Z900 )
|
|
AT( "z", ARCH_900_IDX, Z900 )
|
|
AT( "900", ARCH_900_IDX, Z900 )
|
|
AT( "Z900", ARCH_900_IDX, Z900 )
|
|
AT( "z/900", ARCH_900_IDX, Z900 )
|
|
AT( "ESAME", ARCH_900_IDX, Z900 )
|
|
AT( "ESA/ME", ARCH_900_IDX, Z900 )
|
|
#endif
|
|
};
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* init_default_archmode (public) */
|
|
/*-------------------------------------------------------------------*/
|
|
void init_default_archmode()
|
|
{
|
|
// Called ONCE by bldcfg.c 'build_config' during system startup.
|
|
|
|
sysblk.arch_mode = archtab[0].num; // (always the first entry)
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* get_archtab_by_arch */
|
|
/*-------------------------------------------------------------------*/
|
|
const ARCHTAB* get_archtab_by_arch( int archnum )
|
|
{
|
|
// An "Architecture mode" (archmode, arch_mode) is the same
|
|
// thing as an "Architecture number" (archnum, arch_num),
|
|
// which is simply an index value determined at build time
|
|
// depending on which architectures that Hercules was built
|
|
// with support for (ARCH_nnn_IDX #defined by featchk.h) and
|
|
// is used to index into architecture dependent tables such as
|
|
// the sysblk.facility_list and the opcode tables in opcode.c
|
|
|
|
size_t i;
|
|
for (i=0; i < _countof( archtab ); i++)
|
|
if (archtab[i].num == archnum)
|
|
return &archtab[i];
|
|
return NULL;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* get_archtab_by_name */
|
|
/*-------------------------------------------------------------------*/
|
|
const ARCHTAB* get_archtab_by_name( const char* name )
|
|
{
|
|
size_t i;
|
|
for (i=0; i < _countof( archtab ); i++)
|
|
if (strcasecmp( archtab[i].name, name ) == 0)
|
|
return &archtab[i];
|
|
return NULL;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* get_arch_name_by_arch */
|
|
/*-------------------------------------------------------------------*/
|
|
const char* get_arch_name_by_arch( int archnum )
|
|
{
|
|
const ARCHTAB* at = get_archtab_by_arch( archnum );
|
|
return at ? at->name : NULL;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* get_arch_name (public) */
|
|
/*-------------------------------------------------------------------*/
|
|
const char* get_arch_name( REGS* regs )
|
|
{
|
|
int archnum = regs ? regs->arch_mode : sysblk.arch_mode;
|
|
return get_arch_name_by_arch( archnum );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* get_archmode_by_name */
|
|
/*-------------------------------------------------------------------*/
|
|
static int get_archmode_by_name( const char* archname )
|
|
{
|
|
const ARCHTAB* at = get_archtab_by_name( archname );
|
|
return at ? at->num : -1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* archlvl_cmd (public) */
|
|
/*-------------------------------------------------------------------*/
|
|
/* */
|
|
/* ARCHLVL S/370 | ESA/390 | z/ARCH */
|
|
/* */
|
|
/*-------------------------------------------------------------------*/
|
|
int archlvl_cmd( int argc, char* argv[], char* cmdline )
|
|
{
|
|
U64 old_mainsize = sysblk.mainsize;
|
|
U64 new_mainsize = sysblk.mainsize;
|
|
int old_arch_mode = sysblk.arch_mode;
|
|
int new_arch_mode = sysblk.arch_mode;
|
|
|
|
UNREFERENCED( cmdline );
|
|
|
|
UPPER_ARGV_0( argv );
|
|
|
|
/*-----------------------------------------------------*/
|
|
/* Display Architecture Mode? */
|
|
/*-----------------------------------------------------*/
|
|
|
|
if (argc < 2)
|
|
{
|
|
// "%-14s: %s"
|
|
WRMSG( HHC02203, "I", "ARCHLVL", get_arch_name( NULL ));
|
|
return 0;
|
|
}
|
|
|
|
/* Too many arguments? */
|
|
if (argc > 2)
|
|
{
|
|
// "Invalid command usage. Type 'help %s' for assistance."
|
|
WRMSG( HHC02299, "E", argv[0] );
|
|
return -1;
|
|
}
|
|
|
|
/*-----------------------------------------------------*/
|
|
/* Set Architecture */
|
|
/*-----------------------------------------------------*/
|
|
|
|
/* Make sure all CPUs are deconfigured or stopped */
|
|
if (!are_all_cpus_stopped())
|
|
{
|
|
// "All CPU's must be stopped %s"
|
|
WRMSG( HHC02253, "E", "to switch architectures" );
|
|
return HERRCPUONL;
|
|
}
|
|
|
|
/* Determine new architecture mode */
|
|
if ((new_arch_mode = get_archmode_by_name( argv[1] )) < 0)
|
|
{
|
|
// "ARCHLVL '%s' is invalid"
|
|
WRMSG( HHC00895, "E", argv[1] );
|
|
return -1;
|
|
}
|
|
|
|
obtain_lock( &sysblk.sigplock );
|
|
{
|
|
OBTAIN_INTLOCK( NULL );
|
|
|
|
/* Nothing for us to do unless the architecture changed */
|
|
if (new_arch_mode != old_arch_mode )
|
|
{
|
|
/* Re-configure storage if MAINSIZE needs to be adjusted */
|
|
if ((new_mainsize = adjust_mainsize( new_arch_mode, sysblk.mainsize )) != old_mainsize)
|
|
configure_storage( new_mainsize >> SHIFT_4K );
|
|
|
|
/* Perform system reset to switch architecture mode */
|
|
{
|
|
static const bool clear = false, ipl = false;
|
|
system_reset( new_arch_mode, clear, ipl, sysblk.pcpu );
|
|
}
|
|
|
|
/* (ensure dummyregs matches new architecture) */
|
|
sysblk.dummyregs.arch_mode = sysblk.arch_mode;
|
|
}
|
|
|
|
/* ALWAYS do an "initial_cpu_reset()" for all processors */
|
|
initial_cpu_reset_all();
|
|
|
|
RELEASE_INTLOCK( NULL );
|
|
}
|
|
release_lock( &sysblk.sigplock );
|
|
|
|
/* Display results */
|
|
if (argc > 1 && MLVL( VERBOSE ))
|
|
{
|
|
// "%-14s set to %s"
|
|
WRMSG( HHC02204, "I", "ARCHLVL", get_arch_name_by_arch( sysblk.arch_mode ));
|
|
|
|
if (new_mainsize != old_mainsize)
|
|
{
|
|
char memsize[64];
|
|
bool increased = (new_mainsize > old_mainsize);
|
|
fmt_memsize_KB( sysblk.mainsize >> SHIFT_KIBIBYTE, memsize, sizeof( memsize ));
|
|
|
|
// "MAINSIZE %screased to %s architectural %simum"
|
|
WRMSG( HHC17006, "W", increased ? "in" : "de", memsize,
|
|
increased ? "min" : "max" );
|
|
}
|
|
}
|
|
|
|
/* If S/370 archmode was just set, force LPARNUM to BASIC.
|
|
Else if LPARNUM is BASIC, change it back to LPARNUM 1
|
|
if archmode is z/Arch. Else (ARCH_390_IDX) leave it alone.
|
|
The user can override this automatic LPARNUM switching
|
|
via their own subsequent LPARNUM stmt/cmd if such auto-
|
|
matic behavior is not desired.
|
|
*/
|
|
if (1
|
|
&& ARCH_370_IDX == sysblk.arch_mode
|
|
&& om_basic != sysblk.operation_mode
|
|
)
|
|
panel_command( "LPARNUM BASIC" );
|
|
else if (1
|
|
&& ARCH_900_IDX == sysblk.arch_mode
|
|
&& om_basic == sysblk.operation_mode
|
|
)
|
|
{
|
|
panel_command( "LPARNUM 1" );
|
|
panel_command( "CPUIDFMT 0" );
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif /* !defined( _GEN_ARCH ) */
|