KLCONFIG on SGI Origin 350

Linuxソースコードを読んでいくと、どうもCPU構成の情報はKLCONFIGという所から読み込んでやればいいらしい事が分かる。

arch/mips/sgi-ip27/ip27-smp.cというファイルを覗くとこんな関数がある:

static int do_cpumask(cnodeid_t cnode, nasid_t nasid, int highest)
{
	static int tot_cpus_found = 0;
	lboard_t *brd;
	klcpu_t *acpu;
	int cpus_found = 0;
	cpuid_t cpuid;

	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27);

	do {
		acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU);
		while (acpu) {
			cpuid = acpu->cpu_info.virtid;
			/* cnode is not valid for completely disabled brds */
			if (get_actual_nasid(brd) == brd->brd_nasid)
				cpuid_to_compact_node[cpuid] = cnode;
			if (cpuid > highest)
				highest = cpuid;
			/* Only let it join in if it's marked enabled */
			if ((acpu->cpu_info.flags & KLINFO_ENABLE) &&
			    (tot_cpus_found != NR_CPUS)) {
				cpu_set(cpuid, cpu_possible_map);
				alloc_cpupda(cpuid, tot_cpus_found);
				cpus_found++;
				tot_cpus_found++;
			}
			acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu,
								KLSTRUCT_CPU);
		}
		brd = KLCF_NEXT(brd);
		if (!brd)
			break;

		brd = find_lboard(brd, KLTYPE_IP27);
	} while (brd);

	return highest;
}

見たところ、board情報を取り出す→board情報からcpu情報を取り出す→プロセッサ数カウントアップ、となっている。
ここで出て来るKLCONFIGってなんだろなーと見ていくと、
arch/mips/include/asm/sn/klconfig.hという所に色々な定義が入っていて、そこに興味深いコメントが書いてある。

ローカルボードとリモートボードのリンクドリストがあって、それぞれのエントリからCPU情報が取れるよ、と言っているようだ。

/*
 * The KLCONFIG area is organized as a LINKED LIST of BOARDs. A BOARD
 * can be either 'LOCAL' or 'REMOTE'. LOCAL means it is attached to
 * the LOCAL/current NODE. REMOTE means it is attached to a different
 * node.(TBD - Need a way to treat ROUTER boards.)
 *
 * There are 2 different structures to represent these boards -
 * lboard - Local board, rboard - remote board. These 2 structures
 * can be arbitrarily mixed in the LINKED LIST of BOARDs. (Refer
 * Figure below). The first byte of the rboard or lboard structure
 * is used to find out its type - no unions are used.
 * If it is a lboard, then the config info of this board will be found
 * on the local node. (LOCAL NODE BASE + offset value gives pointer to
 * the structure.
 * If it is a rboard, the local structure contains the node number
 * and the offset of the beginning of the LINKED LIST on the remote node.
 * The details of the hardware on a remote node can be built locally,
 * if required, by reading the LINKED LIST on the remote node and
 * ignoring all the rboards on that node.
 *
 * The local node uses the REMOTE NODE NUMBER + OFFSET to point to the
 * First board info on the remote node. The remote node list is
 * traversed as the local list, using the REMOTE BASE ADDRESS and not
 * the local base address and ignoring all rboard values.
 *
 *
 KLCONFIG

 +------------+      +------------+      +------------+      +------------+
 |  lboard    |  +-->|   lboard   |  +-->|   rboard   |  +-->|   lboard   |
 +------------+  |   +------------+  |   +------------+  |   +------------+
 | board info |  |   | board info |  |   |errinfo,bptr|  |   | board info |
 +------------+  |   +------------+  |   +------------+  |   +------------+
 | offset     |--+   |  offset    |--+   |  offset    |--+   |offset=NULL |
 +------------+      +------------+      +------------+      +------------+


 +------------+
 | board info |
 +------------+       +--------------------------------+
 | compt 1    |------>| type, rev, diaginfo, size ...  |  (CPU)
 +------------+       +--------------------------------+
 | compt 2    |--+
 +------------+  |    +--------------------------------+
 |  ...       |  +--->| type, rev, diaginfo, size ...  |  (MEM_BANK)
 +------------+       +--------------------------------+
 | errinfo    |--+
 +------------+  |    +--------------------------------+
                 +--->|r/l brd errinfo,compt err flags |
                      +--------------------------------+

 *
 * Each BOARD consists of COMPONENTs and the BOARD structure has
 * pointers (offsets) to its COMPONENT structure.
 * The COMPONENT structure has version info, size and speed info, revision,
 * error info and the NIC info. This structure can accommodate any
 * BOARD with arbitrary COMPONENT composition.
 *
 * The ERRORINFO part of each BOARD has error information
 * that describes errors about the BOARD itself. It also has flags to
 * indicate the COMPONENT(s) on the board that have errors. The error
 * information specific to the COMPONENT is present in the respective
 * COMPONENT structure.
 *
 * The ERRORINFO structure is also treated like a COMPONENT, ie. the
 * BOARD has pointers(offset) to the ERRORINFO structure. The rboard
 * structure also has a pointer to the ERRORINFO structure. This is
 * the place to store ERRORINFO about a REMOTE NODE, if the HUB on
 * that NODE is not working or if the REMOTE MEMORY is BAD. In cases where
 * only the CPU of the REMOTE NODE is disabled, the ERRORINFO pointer can
 * be a NODE NUMBER, REMOTE OFFSET combination, pointing to error info
 * which is present on the REMOTE NODE.(TBD)
 * REMOTE ERRINFO can be stored on any of the nearest nodes
 * or on all the nearest nodes.(TBD)
 * Like BOARD structures, REMOTE ERRINFO structures can be built locally
 * using the rboard errinfo pointer.
 *
 * In order to get useful information from this Data organization, a set of
 * interface routines are provided (TBD). The important thing to remember while
 * manipulating the structures, is that, the NODE number information should
 * be used. If the NODE is non-zero (remote) then each offset should
 * be added to the REMOTE BASE ADDR else it should be added to the LOCAL BASE ADDR.
 * This includes offsets for BOARDS, COMPONENTS and ERRORINFO.
 *
 * Note that these structures do not provide much info about connectivity.
 * That info will be part of HWGRAPH, which is an extension of the cfg_t
 * data structure. (ref IP27prom/cfg.h) It has to be extended to include
 * the IO part of the Network(TBD).
 *
 * The data structures below define the above concepts.
 */

で、これ、全部自分で読みに行かないと駄目?と途方にくれていたら、もうちゃんと実装されていた。
きちんとエントリをイテレートして画面表示するデバッグプリントも仕込まれてて、有効にするとこんなのが表示される:

lboard type 11 slot 0 nasid 0 nic 0x5627f3ad ncomp 5
	hub, widget 0 physid 0x00 virtid 0 prt 0 bus 0
	  port -1 flag 0 speed 200MHz
	memory, widget 0 physid 0xff virtid -1 prt 0 bus 0
	  2048MB, select 0 flags 3
		bank 1 1024MB
		bank 2 1024MB
IP35 memory from 0x0 to 0x40000000 (1024 MB)
memrange_register: memory from 0x4000000 to 0x40000000
IP35 memory from 0x40000000 to 0x80000000 (1024 MB)
memrange_register: memory from 0x40000000 to 0x80000000
	hub uart, widget 0 physid 0x00 virtid 0 prt 0 bus 0
	[ARCBios component: class 6 type 18 flags 78 key 0x6 SN1 TTY]
	cpu, widget 0 physid 0x00 virtid 0 prt 0 bus 0
	  type f50/e4ab 1000MHz cache 16MB speed 333MHz
	cpu, widget 0 physid 0x02 virtid 1 prt 0 bus 0
	  type f50/e4ab 1000MHz cache 16MB speed 333MHz
lboard type 42 slot 0 nasid 0 nic 0xffffffffffffffff ncomp 1
	xbow, widget 0 physid 0xff virtid 0 prt 0 bus 0
	 hub master link 11
		widget 11 nasid 0 flg 6
		widget 15 nasid 0 flg 5
lboard type 77 slot f nasid 0 nic 0x5627f3ad ncomp 5
	bridge, widget f physid 0x0f virtid 15 prt 0 bus 0
	ioc4, widget f physid 0x01 virtid 0 prt 0 bus 0
	[ARCBios component: class 0 type 32 flags 00 key 0x0 (no name)]
	ioc4 ATA, widget f physid 0x01 virtid -1 prt 0 bus 0
	[ARCBios component: class 0 type 0 flags 00 key 0x0 (no name)]
	dual scsi, widget f physid 0x03 virtid -1 prt 0 bus 0
		bus 0, physid 0x03 virtid 0, specific 0, numdevs 2
		bus 1, physid 0x03 virtid 1, specific 0, numdevs 0
	[ARCBios component: class 0 type 0 flags 00 key 0x0 (no name)]
	gigabit Ethernet, widget f physid 0x04 virtid 1 prt 0 bus 0
	[ARCBios component: class 6 type 36 flags 60 key 0xf240b000000 (no name)]
lboard type 77 slot f nasid 0 nic 0x5627f3ad ncomp 5
	bridge, widget f physid 0x1f virtid 31 prt 0 bus 1
	unknown component, widget f physid 0x01 virtid 0 prt 0 bus 1 pcifn 0
	unknown component, widget f physid 0x01 virtid 0 prt 0 bus 1 pcifn 1
	unknown component, widget f physid 0x02 virtid 0 prt 0 bus 1 pcifn 0
	unknown component, widget f physid 0x02 virtid 0 prt 0 bus 1 pcifn 1

まぁなにやら色々とハードが羅列されてるが、CPUは2個見えているのでプロセッサ検出の所ではこの情報が使えるに違いないし、既にコードも存在しているのでここは殆ど手を入れる必要なさそう。