blob: 1151b8e48c5e21913730ad2874c091bd6fa20d44 [file] [log] [blame]
/*
*
* Blue Gene personality /proc interface with the control system
*
* Copyright 2003,2005 International Business Machines
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* User apps can mmap /proc/personality to directly access the binary
* personality in SRAM (see bglpersonality.h), or they can read
* /proc/personality.sh which expands to shell commands (so it can be sourced)
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/mm.h>
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/bluegene.h>
#include <asm/bgp_personality.h>
static struct proc_dir_entry *personality_proc_entry = NULL;
static struct proc_dir_entry *personality_sh_proc_entry = NULL;
static BGP_Personality_t bgpers;
/* Binary personality interface. Doesn't need to be fast. */
static int bgpersonality_read(char *page, char **start, off_t offset,
int count, int *eof, void *data)
{
bluegene_getPersonality(&bgpers, count);
memcpy(page, &bgpers, count);
*eof = 1;
return count;
}
static void* bgpers_sh_seq_start(struct seq_file* f,
loff_t* pos)
{
return *pos <= 32 ? (void*) pos : (void*) NULL;
}
static void* bgpers_sh_seq_next(struct seq_file* f,
void* v,
loff_t* pos)
{
return ++(*pos) <= 32 ? (void*) pos : (void*) NULL;
}
static void bgpers_sh_seq_stop(struct seq_file* f,
void* v)
{
return;
}
/* Produce a personality in a form parsable by a shell. */
static int bgpers_sh_seq_show(struct seq_file* f,
void* v)
{
loff_t offset = *((loff_t*) v);
BGP_UCI_ComputeCard_t* uci;
bluegene_getPersonality(&bgpers, sizeof(bgpers));
uci = (BGP_UCI_ComputeCard_t*) &bgpers.Kernel_Config.UniversalComponentIdentifier;
switch((unsigned long) offset) {
case 0:
seq_printf(f, "BG_UCI=%08x\n",
bgpers.Kernel_Config.UniversalComponentIdentifier);
break;
case 1:
seq_printf(f, "BG_LOCATION=R%1x%1x-M%c-N%02d-J%02d\n",
uci->RackRow, uci->RackColumn, (uci->Midplane ? '1' : '0'),
uci->NodeCard, uci->ComputeCard);
break;
case 2:
seq_printf(f, "BG_MAC=%02x:%02x:%02x:%02x:%02x:%02x\n",
bgpers.Ethernet_Config.EmacID[0],
bgpers.Ethernet_Config.EmacID[1],
bgpers.Ethernet_Config.EmacID[2],
bgpers.Ethernet_Config.EmacID[3],
bgpers.Ethernet_Config.EmacID[4],
bgpers.Ethernet_Config.EmacID[5]);
break;
case 3:
seq_printf(f, "BG_IP=%d.%d.%d.%d\n",
bgpers.Ethernet_Config.IPAddress.octet[12],
bgpers.Ethernet_Config.IPAddress.octet[13],
bgpers.Ethernet_Config.IPAddress.octet[14],
bgpers.Ethernet_Config.IPAddress.octet[15]);
break;
case 4:
seq_printf(f, "BG_NETMASK=%d.%d.%d.%d\n",
bgpers.Ethernet_Config.IPNetmask.octet[12],
bgpers.Ethernet_Config.IPNetmask.octet[13],
bgpers.Ethernet_Config.IPNetmask.octet[14],
bgpers.Ethernet_Config.IPNetmask.octet[15]);
break;
case 5:
seq_printf(f, "BG_BROADCAST=%d.%d.%d.%d\n",
bgpers.Ethernet_Config.IPBroadcast.octet[12],
bgpers.Ethernet_Config.IPBroadcast.octet[13],
bgpers.Ethernet_Config.IPBroadcast.octet[14],
bgpers.Ethernet_Config.IPBroadcast.octet[15]);
break;
case 6:
seq_printf(f, "BG_GATEWAY=%d.%d.%d.%d\n",
bgpers.Ethernet_Config.IPGateway.octet[12],
bgpers.Ethernet_Config.IPGateway.octet[13],
bgpers.Ethernet_Config.IPGateway.octet[14],
bgpers.Ethernet_Config.IPGateway.octet[15]);
break;
case 7:
seq_printf(f, "BG_MTU=%d\n", bgpers.Ethernet_Config.MTU);
break;
case 8:
seq_printf(f, "BG_FS=%d.%d.%d.%d\n",
bgpers.Ethernet_Config.NFSServer.octet[12],
bgpers.Ethernet_Config.NFSServer.octet[13],
bgpers.Ethernet_Config.NFSServer.octet[14],
bgpers.Ethernet_Config.NFSServer.octet[15]);
break;
case 9:
seq_printf(f, "BG_EXPORTDIR=\"%s\"\n", bgpers.Ethernet_Config.NFSExportDir);
break;
case 10:
seq_printf(f, "BG_SIMULATION=%d\n",
(bgpers.Kernel_Config.NodeConfig & BGP_PERS_ENABLE_Simulation ? 1 : 0));
break;
case 11:
seq_printf(f, "BG_PSETNUM=%d\n", bgpers.Network_Config.PSetNum);
break;
case 12:
seq_printf(f, "BG_NUMPSETS=%d\n", bgpers.Network_Config.IOnodes);
break;
case 13:
seq_printf(f, "BG_NODESINPSET=%d\n", bgpers.Network_Config.PSetSize);
break;
case 14:
seq_printf(f, "BG_XSIZE=%d\n", bgpers.Network_Config.Xnodes);
break;
case 15:
seq_printf(f, "BG_YSIZE=%d\n", bgpers.Network_Config.Ynodes);
break;
case 16:
seq_printf(f, "BG_ZSIZE=%d\n", bgpers.Network_Config.Znodes);
break;
case 17:
seq_printf(f, "BG_VERBOSE=%d\n", (bgpers.Kernel_Config.TraceConfig & BGP_TRACE_VERBOSE) ? 1 : 0);
break;
case 18:
switch (bgpers.Network_Config.PSetSize) {
case 16:
seq_printf(f, "BG_PSETSIZE=\"4 2 2\"\n");
break;
case 32:
seq_printf(f, "BG_PSETSIZE=\"4 4 2\"\n");
break;
case 64:
seq_printf(f, "BG_PSETSIZE=\"4 4 4\"\n");
break;
case 128:
seq_printf(f, "BG_PSETSIZE=\"4 4 8\"\n");
break;
case 256:
seq_printf(f, "BG_PSETSIZE=\"8 4 8\"\n");
break;
case 512:
seq_printf(f, "BG_PSETSIZE=\"8 8 8\"\n");
break;
default:
seq_printf(f, "BG_PSETSIZE=\"? ? ?\"\n");
}
break;
case 19:
/* if (bgpers.Network_Config.RankInPSet) */
/* // Not an IO node so display pset origin. */
seq_printf(f, "BG_PSETORG=\"%d %d %d\"\n",
bgpers.Network_Config.Xcoord,
bgpers.Network_Config.Ycoord,
bgpers.Network_Config.Zcoord);
break;
case 20:
seq_printf(f, "BG_CLOCKHZ=%d\n", bgpers.Kernel_Config.FreqMHz);
break;
case 21:
seq_printf(f, "BG_GLINTS=%d\n",
(bgpers.Kernel_Config.NodeConfig & BGP_PERS_ENABLE_GlobalInts) ? 1 : 0);
break;
case 22:
seq_printf(f, "BG_ISTORUS=\"%s%s%s\"\n",
(bgpers.Kernel_Config.NodeConfig & BGP_PERS_ENABLE_TorusMeshX) ? "X" : "",
(bgpers.Kernel_Config.NodeConfig & BGP_PERS_ENABLE_TorusMeshY) ? "Y" : "",
(bgpers.Kernel_Config.NodeConfig & BGP_PERS_ENABLE_TorusMeshZ) ? "Z" : "");
break;
case 23: {
char blockID[BGP_PERSONALITY_LEN_NFSDIR+1];
strncpy(blockID, bgpers.Ethernet_Config.NFSMountDir, sizeof(blockID));
blockID[sizeof(blockID)-1] = '\0';
seq_printf(f, "BG_BLOCKID=\"%s\"\n", blockID);
break;
}
case 24:
seq_printf(f, "BG_SN=%d.%d.%d.%d\n",
bgpers.Ethernet_Config.serviceNode.octet[12],
bgpers.Ethernet_Config.serviceNode.octet[13],
bgpers.Ethernet_Config.serviceNode.octet[14],
bgpers.Ethernet_Config.serviceNode.octet[15]);
break;
case 25:
seq_printf(f, "BG_IS_IO_NODE=%d\n", (bgpers.Network_Config.RankInPSet ? 0 : 1));
break;
case 26:
seq_printf(f, "BG_RANK_IN_PSET=%d\nBG_RANK=%d\n",
bgpers.Network_Config.RankInPSet,
bgpers.Network_Config.Rank);
break;
case 27:
seq_printf(f, "BG_IP_OVER_COL=%d\n", (bgpers.Block_Config & BGP_PERS_BLKCFG_IPOverCollective) ? 1 : 0);
break;
case 28:
seq_printf(f, "BG_IP_OVER_TOR=%d\n", (bgpers.Block_Config & BGP_PERS_BLKCFG_IPOverTorus) ? 1 : 0);
break;
case 29:
seq_printf(f, "BG_IP_OVER_COL_VC=%d\n", (bgpers.Block_Config & BGP_PERS_BLKCFG_IPOverCollectiveVC) ? 1 : 0);
break;
case 30:
if ((bgpers.Block_Config & BGP_PERS_BLKCFG_CIOModeSel(3)) == BGP_PERS_BLKCFG_CIOModeSel(BGP_PERS_BLKCFG_CIOMode_MuxOnly))
seq_printf(f, "BG_CIO_MODE=MUX_ONLY\n");
else if ((bgpers.Block_Config & BGP_PERS_BLKCFG_CIOModeSel(3)) == BGP_PERS_BLKCFG_CIOModeSel(BGP_PERS_BLKCFG_CIOMode_None))
seq_printf(f, "BG_CIO_MODE=NONE\n");
else if ((bgpers.Block_Config & BGP_PERS_BLKCFG_CIOModeSel(3)) == BGP_PERS_BLKCFG_CIOModeSel(BGP_PERS_BLKCFG_CIOMode_Full))
seq_printf(f, "BG_CIO_MODE=FULL\n");
else
seq_printf(f, "BG_CIO_MODE=UNKNOWN\n");
break;
case 31:
if ((bgpers.Block_Config & BGP_PERS_BLKCFG_bgsysFSSel(3)) == BGP_PERS_BLKCFG_bgsysFSSel(BGP_PERS_BLKCFG_bgsys_NFSv3))
seq_printf(f, "BG_BGSYS_FS_TYPE=NFSv3\n");
else if ((bgpers.Block_Config & BGP_PERS_BLKCFG_bgsysFSSel(3)) == BGP_PERS_BLKCFG_bgsysFSSel(BGP_PERS_BLKCFG_bgsys_NFSv4))
seq_printf(f, "BG_BGSYS_FS_TYPE=NFSv4\n");
else
seq_printf(f, "BG_BGSYS_FS_TYPE=UNKNOWN\n");
break;
case 32:
seq_printf(f, "BG_HTC_MODE=%d\n",
(bgpers.Kernel_Config.NodeConfig & BGP_PERS_ENABLE_HighThroughput) ? 1 : 0);
break;
default:
seq_printf(f, "Illegal offset %d\n", (unsigned int) offset);
}
return 0;
}
void bgpersonality_cleanup_module(void)
{
if (personality_proc_entry) {
remove_proc_entry(personality_proc_entry->name, NULL);
}
if (personality_sh_proc_entry) {
remove_proc_entry(personality_sh_proc_entry->name, NULL);
}
}
static struct seq_operations bgpers_sh_seq_ops = {
.start = bgpers_sh_seq_start,
.next = bgpers_sh_seq_next,
.stop = bgpers_sh_seq_stop,
.show = bgpers_sh_seq_show
};
static int bgpers_sh_proc_open(struct inode* inode,
struct file* f)
{
return seq_open(f, &bgpers_sh_seq_ops);
}
static struct file_operations bgpers_sh_fops = {
.owner = THIS_MODULE,
.open = bgpers_sh_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release
};
int bgpersonality_init_module(void)
{
personality_proc_entry = create_proc_read_entry("personality", 0644, NULL,
bgpersonality_read, (void *) 0);
if (!personality_proc_entry)
goto out;
personality_sh_proc_entry = create_proc_entry("personality.sh", 0, NULL);
if (!personality_sh_proc_entry)
goto out;
else
personality_sh_proc_entry->proc_fops = &bgpers_sh_fops;
return 0;
out:
bgpersonality_cleanup_module();
return -ENOMEM;
}
module_init(bgpersonality_init_module);
module_exit(bgpersonality_cleanup_module);