summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Pothier <Tom.Pothier@Sun.COM>2009-11-03 21:14:05 -0500
committerTom Pothier <Tom.Pothier@Sun.COM>2009-11-03 21:14:05 -0500
commit074bb90d80fdbeb2d04a8450a55ecbc96de28785 (patch)
tree8a51c05e37f62db5e4c24f3e134755322fa6c78a
parent36d41b68ce4ecc38f01ced5fe21dddf05a5f9289 (diff)
downloadillumos-joyent-074bb90d80fdbeb2d04a8450a55ecbc96de28785.tar.gz
PSARC/2009/490 x86 Generic FMA Topology Enumerator
6785310 Implement SMBIOS contained elements/handles 6841286 Need x86 generic FMA topo enumerator 6853537 x86gentopo needs OEM-Specific SMBIOS structures 6865771 Topology relationships should be derived from contained handles & elements of SMBIOS 6865814 Chip enumerator should derive serials & labels using libsmbios, if SMBIOS is FM aware 6865845 /dev/fm should export the Initial APICID, SMBIOS based ID/instance to the chip enumerator 6866456 Generic Topology FMRI ereport
-rw-r--r--usr/src/cmd/fm/eversholt/files/i386/i86pc/intel.esc364
-rw-r--r--usr/src/cmd/mdb/intel/modules/generic_cpu/gcpu.c3
-rw-r--r--usr/src/cmd/smbios/smbios.c181
-rw-r--r--usr/src/common/smbios/smb_info.c189
-rw-r--r--usr/src/common/smbios/smb_open.c23
-rw-r--r--usr/src/lib/fm/topo/libtopo/common/mapfile-vers1
-rw-r--r--usr/src/lib/fm/topo/libtopo/common/topo_mod.map2
-rw-r--r--usr/src/lib/fm/topo/maps/i86pc/Makefile2
-rw-r--r--usr/src/lib/fm/topo/maps/i86pc/i86pc-hc-topology.xml125
-rw-r--r--usr/src/lib/fm/topo/maps/i86pc/i86pc-legacy-hc-topology.xml166
-rw-r--r--usr/src/lib/fm/topo/modules/common/pcibus/did_props.c26
-rw-r--r--usr/src/lib/fm/topo/modules/i86pc/Makefile5
-rw-r--r--usr/src/lib/fm/topo/modules/i86pc/chip/Makefile6
-rw-r--r--usr/src/lib/fm/topo/modules/i86pc/chip/chip.c370
-rw-r--r--usr/src/lib/fm/topo/modules/i86pc/chip/chip.h36
-rw-r--r--usr/src/lib/fm/topo/modules/i86pc/chip/chip_amd.c197
-rw-r--r--usr/src/lib/fm/topo/modules/i86pc/chip/chip_intel.c95
-rw-r--r--usr/src/lib/fm/topo/modules/i86pc/chip/chip_smbios.c590
-rw-r--r--usr/src/lib/fm/topo/modules/i86pc/x86pi/Makefile52
-rw-r--r--usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi.c462
-rw-r--r--usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_bboard.c370
-rw-r--r--usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_chassis.c116
-rw-r--r--usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_generic.c211
-rw-r--r--usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_hostbridge.c290
-rw-r--r--usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_impl.h206
-rw-r--r--usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_subr.c653
-rw-r--r--usr/src/lib/libsmbios/common/mapfile-vers6
-rw-r--r--usr/src/pkgdefs/SUNWfmd/prototype_i3862
-rw-r--r--usr/src/uts/common/io/devfm.c6
-rw-r--r--usr/src/uts/common/os/fm.c99
-rw-r--r--usr/src/uts/common/sys/devfm.h17
-rw-r--r--usr/src/uts/common/sys/fm/protocol.h2
-rw-r--r--usr/src/uts/common/sys/smbios.h60
-rw-r--r--usr/src/uts/common/sys/smbios_impl.h38
-rw-r--r--usr/src/uts/i86pc/cpu/amd_opteron/ao_mca.c47
-rw-r--r--usr/src/uts/i86pc/cpu/authenticamd/authamd_main.c30
-rw-r--r--usr/src/uts/i86pc/cpu/generic_cpu/gcpu_mca.c27
-rw-r--r--usr/src/uts/i86pc/cpu/genuineintel/gintel_main.c105
-rw-r--r--usr/src/uts/i86pc/os/cmi.c5
-rw-r--r--usr/src/uts/i86pc/os/cmi_hw.c128
-rw-r--r--usr/src/uts/i86pc/os/startup.c18
-rw-r--r--usr/src/uts/i86xpv/os/xen_machdep.c6
-rw-r--r--usr/src/uts/intel/Makefile.files1
-rw-r--r--usr/src/uts/intel/io/devfm_machdep.c62
-rw-r--r--usr/src/uts/intel/io/mc-amd/mcamd.h4
-rw-r--r--usr/src/uts/intel/io/mc-amd/mcamd_drv.c46
-rw-r--r--usr/src/uts/intel/io/mc-amd/mcamd_subr.c82
-rw-r--r--usr/src/uts/intel/os/fmsmb.c1129
-rw-r--r--usr/src/uts/intel/sys/cpu_module.h4
-rw-r--r--usr/src/uts/intel/sys/fm/smb/fmsmb.h52
-rw-r--r--usr/src/uts/intel/sys/hypervisor.h1
51 files changed, 6213 insertions, 505 deletions
diff --git a/usr/src/cmd/fm/eversholt/files/i386/i86pc/intel.esc b/usr/src/cmd/fm/eversholt/files/i386/i86pc/intel.esc
index f4e5c3a18e..b7a03bcfaf 100644
--- a/usr/src/cmd/fm/eversholt/files/i386/i86pc/intel.esc
+++ b/usr/src/cmd/fm/eversholt/files/i386/i86pc/intel.esc
@@ -434,12 +434,12 @@ prop upset.discard@rank (0)-> EREPORT_BUS_ERROR;
*/
#define CONTAINS_RANK (payloadprop_contains("resource", \
- asru(motherboard/chip/memory-controller/dram-channel/dimm/rank)) || \
+ asru(chip/memory-controller/dram-channel/dimm/rank)) || \
payloadprop_contains("resource", \
- asru(motherboard/chip/memory-controller/dram-channel/dimm)))
+ asru(chip/memory-controller/dram-channel/dimm)))
#define STAT_CPU_MEM_CE_PGFLTS \
- stat.ce_pgflt@motherboard/chip/memory-controller/dram-channel/dimm
+ stat.ce_pgflt@chip/memory-controller/dram-channel/dimm
#define SET_RES_OFFSET \
(!payloadprop_defined("resource[0].hc-specific.offset") || \
@@ -448,21 +448,21 @@ prop upset.discard@rank (0)-> EREPORT_BUS_ERROR;
engine STAT_CPU_MEM_CE_PGFLTS;
-event ereport.cpu.intel.quickpath.mem_ue@motherboard/chip/memory-controller
+event ereport.cpu.intel.quickpath.mem_ue@chip/memory-controller
{within(12s)};
event fault.memory.intel.page_ue@
- motherboard/chip/memory-controller/dram-channel/dimm/rank,
+ chip/memory-controller/dram-channel/dimm/rank,
message=0, response=0; /* do not message individual pageflts */
prop fault.memory.intel.page_ue@
- motherboard/chip/memory-controller/dram-channel/dimm/rank
+ chip/memory-controller/dram-channel/dimm/rank
{ CONTAINS_RANK && (payloadprop_defined("physaddr") ||
payloadprop_defined("resource[0].hc-specific.offset")) &&
SET_ADDR && SET_RES_OFFSET } (0)->
- ereport.cpu.intel.quickpath.mem_ue@motherboard/chip/memory-controller;
+ ereport.cpu.intel.quickpath.mem_ue@chip/memory-controller;
-#define CHIPDIMM motherboard/chip/memory-controller/dram-channel/dimm
+#define CHIPDIMM chip/memory-controller/dram-channel/dimm
event fault.memory.intel.dimm_ue@CHIPDIMM/rank;
@@ -475,12 +475,12 @@ prop fault.memory.intel.dimm_ue@CHIPDIMM/rank (1)->
prop error.memory.intel.dimm_ue_ep@CHIPDIMM/rank
{ CONTAINS_RANK } (1)->
- ereport.cpu.intel.quickpath.mem_ue@motherboard/chip/memory-controller;
+ ereport.cpu.intel.quickpath.mem_ue@chip/memory-controller;
prop fault.memory.intel.dimm_ue@CHIPDIMM/rank (0)-> EREPORT_BUS_ERROR;
event ereport.cpu.intel.quickpath.mem_ce@
- motherboard/chip/memory-controller{within(12s)};
+ chip/memory-controller{within(12s)};
engine serd.memory.intel.page_ce@CHIPDIMM/rank, N=PAGE_CE_COUNT, T=PAGE_CE_TIME;
event fault.memory.intel.page_ce@CHIPDIMM/rank, message=0, response=0,
@@ -490,7 +490,7 @@ prop fault.memory.intel.page_ce@CHIPDIMM/rank
{ CONTAINS_RANK && (payloadprop_defined("physaddr") ||
payloadprop_defined("resource[0].hc-specific.offset")) &&
SET_ADDR && SET_RES_OFFSET } (0)->
- ereport.cpu.intel.quickpath.mem_ce@motherboard/chip/memory-controller;
+ ereport.cpu.intel.quickpath.mem_ce@chip/memory-controller;
engine serd.memory.intel.dimm_ce@CHIPDIMM, N=PAGE_CE_COUNT, T=PAGE_CE_TIME;
event fault.memory.intel.dimm_ce@CHIPDIMM,
@@ -498,7 +498,7 @@ event fault.memory.intel.dimm_ce@CHIPDIMM,
prop fault.memory.intel.dimm_ce@CHIPDIMM
{ !confprop_defined(CHIPDIMM, "dimm-size") &&
count(STAT_CPU_MEM_CE_PGFLTS) > 512 } (0)->
- ereport.cpu.intel.quickpath.mem_ce@motherboard/chip/memory-controller;
+ ereport.cpu.intel.quickpath.mem_ce@chip/memory-controller;
#define CPU_MEM_DIMM_CE(dimm_size, n, t, fault_rate) \
prop fault.memory.intel.dimm_ce@CHIPDIMM { \
@@ -506,7 +506,7 @@ prop fault.memory.intel.dimm_ce@CHIPDIMM
count(STAT_CPU_MEM_CE_PGFLTS) > fault_rate && \
setserdn(n) & setserdt(t) } (0)-> \
ereport.cpu.intel.quickpath.mem_ce@ \
- motherboard/chip/memory-controller;
+ chip/memory-controller;
CPU_MEM_DIMM_CE("16G", 16, 1week, 2000)
CPU_MEM_DIMM_CE("8G", 8, 1week, 2000)
@@ -515,69 +515,69 @@ CPU_MEM_DIMM_CE("2G", 4, 2week, 1000)
CPU_MEM_DIMM_CE("1G", 4, 4week, 500)
CPU_MEM_DIMM_CE("512M", 4, 8week, 250)
-event ereport.cpu.intel.quickpath.mem_unknown@motherboard/chip/memory-controller {within(12s)};
-event ereport.cpu.intel.quickpath.mem_unknown@motherboard/chip/memory-controller/dram-channel
+event ereport.cpu.intel.quickpath.mem_unknown@chip/memory-controller {within(12s)};
+event ereport.cpu.intel.quickpath.mem_unknown@chip/memory-controller/dram-channel
{within(12s)};
event ereport.cpu.intel.quickpath.mem_unknown@
- motherboard/chip/memory-controller/dram-channel/dimm/rank{within(12s)};
-event upset.discard@motherboard/chip/memory-controller;
-event upset.discard@motherboard/chip/memory-controller/dram-channel/dimm/rank;
+ chip/memory-controller/dram-channel/dimm/rank{within(12s)};
+event upset.discard@chip/memory-controller;
+event upset.discard@chip/memory-controller/dram-channel/dimm/rank;
-prop upset.discard@motherboard/chip/memory-controller (0)->
- ereport.cpu.intel.quickpath.mem_unknown@motherboard/chip/memory-controller,
+prop upset.discard@chip/memory-controller (0)->
+ ereport.cpu.intel.quickpath.mem_unknown@chip/memory-controller,
ereport.cpu.intel.quickpath.mem_unknown@
- motherboard/chip/memory-controller/dram-channel;
+ chip/memory-controller/dram-channel;
prop upset.discard@
- motherboard/chip/memory-controller/dram-channel/dimm/rank (1)->
+ chip/memory-controller/dram-channel/dimm/rank (1)->
ereport.cpu.intel.quickpath.mem_unknown@
- motherboard/chip/memory-controller/dram-channel/dimm/rank;
+ chip/memory-controller/dram-channel/dimm/rank;
-event ereport.cpu.intel.quickpath.mem_parity@motherboard/chip/memory-controller {within(1s)};
-event fault.cpu.intel.quickpath.mem_parity@motherboard/chip/memory-controller;
+event ereport.cpu.intel.quickpath.mem_parity@chip/memory-controller {within(1s)};
+event fault.cpu.intel.quickpath.mem_parity@chip/memory-controller;
-prop fault.cpu.intel.quickpath.mem_parity@motherboard/chip/memory-controller (1)->
- ereport.cpu.intel.quickpath.mem_parity@motherboard/chip/memory-controller;
+prop fault.cpu.intel.quickpath.mem_parity@chip/memory-controller (1)->
+ ereport.cpu.intel.quickpath.mem_parity@chip/memory-controller;
-event ereport.cpu.intel.quickpath.mem_addr_parity@motherboard/chip/memory-controller {within(1s)};
+event ereport.cpu.intel.quickpath.mem_addr_parity@chip/memory-controller {within(1s)};
event fault.cpu.intel.quickpath.mem_addr_parity@
- motherboard/chip/memory-controller;
+ chip/memory-controller;
event fault.cpu.intel.quickpath.mem_addr_parity@CHIPDIMM;
event fault.cpu.intel.quickpath.mem_addr_parity@CHIPDIMM/rank;
prop fault.cpu.intel.quickpath.mem_addr_parity@
- motherboard/chip/memory-controller (1)->
- ereport.cpu.intel.quickpath.mem_addr_parity@motherboard/chip/memory-controller;
+ chip/memory-controller (1)->
+ ereport.cpu.intel.quickpath.mem_addr_parity@chip/memory-controller;
prop fault.cpu.intel.quickpath.mem_addr_parity@CHIPDIMM
{ payloadprop_contains("resource", asru(CHIPDIMM)) } (1)->
- ereport.cpu.intel.quickpath.mem_addr_parity@motherboard/chip/memory-controller;
+ ereport.cpu.intel.quickpath.mem_addr_parity@chip/memory-controller;
prop fault.cpu.intel.quickpath.mem_addr_parity@CHIPDIMM/rank
{ payloadprop_contains("resource", asru(CHIPDIMM/rank)) } (1)->
- ereport.cpu.intel.quickpath.mem_addr_parity@motherboard/chip/memory-controller;
+ ereport.cpu.intel.quickpath.mem_addr_parity@chip/memory-controller;
-event ereport.cpu.intel.quickpath.mem_bad_addr@motherboard/chip/memory-controller {within(1s)};
-event fault.cpu.intel.quickpath.mem_bad_addr@motherboard/chip/memory-controller;
+event ereport.cpu.intel.quickpath.mem_bad_addr@chip/memory-controller {within(1s)};
+event fault.cpu.intel.quickpath.mem_bad_addr@chip/memory-controller;
-prop fault.cpu.intel.quickpath.mem_bad_addr@motherboard/chip/memory-controller (1)->
- ereport.cpu.intel.quickpath.mem_bad_addr@motherboard/chip/memory-controller;
+prop fault.cpu.intel.quickpath.mem_bad_addr@chip/memory-controller (1)->
+ ereport.cpu.intel.quickpath.mem_bad_addr@chip/memory-controller;
-event ereport.cpu.intel.quickpath.mem_spare@motherboard/chip/memory-controller {within(1s)};
+event ereport.cpu.intel.quickpath.mem_spare@chip/memory-controller {within(1s)};
event fault.cpu.intel.quickpath.mem_spare@
- motherboard/chip/memory-controller/dram-channel/dimm;
+ chip/memory-controller/dram-channel/dimm;
prop fault.cpu.intel.quickpath.mem_spare@
- motherboard/chip/memory-controller/dram-channel/dimm (1)->
- ereport.cpu.intel.quickpath.mem_spare@motherboard/chip/memory-controller;
+ chip/memory-controller/dram-channel/dimm (1)->
+ ereport.cpu.intel.quickpath.mem_spare@chip/memory-controller;
-event ereport.cpu.intel.quickpath.mem_bad_id@motherboard/chip/memory-controller {within(1s)};
-event fault.cpu.intel.quickpath.mem_bad_id@motherboard/chip/memory-controller;
+event ereport.cpu.intel.quickpath.mem_bad_id@chip/memory-controller {within(1s)};
+event fault.cpu.intel.quickpath.mem_bad_id@chip/memory-controller;
-prop fault.cpu.intel.quickpath.mem_bad_id@motherboard/chip/memory-controller (1)->
- ereport.cpu.intel.quickpath.mem_bad_id@motherboard/chip/memory-controller;
+prop fault.cpu.intel.quickpath.mem_bad_id@chip/memory-controller (1)->
+ ereport.cpu.intel.quickpath.mem_bad_id@chip/memory-controller;
-event ereport.cpu.intel.quickpath.mem_redundant@motherboard/chip/memory-controller {within(1s)};
+event ereport.cpu.intel.quickpath.mem_redundant@chip/memory-controller {within(1s)};
engine serd.cpu.intel.quickpath.mem_redundant@CHIPDIMM, N=2, T=72h;
event fault.cpu.intel.quickpath.mem_redundant@CHIPDIMM,
engine=serd.cpu.intel.quickpath.mem_redundant@CHIPDIMM;
@@ -590,26 +590,26 @@ prop fault.cpu.intel.quickpath.mem_redundant@CHIPDIMM (1)->
prop error.cpu.intel.quickpath.mem_redundant@CHIPDIMM/rank
{ CONTAINS_RANK } (1)->
ereport.cpu.intel.quickpath.mem_redundant@
- motherboard/chip/memory-controller;
+ chip/memory-controller;
#define STATUS_UC (payloadprop("error_uncorrected") == 1)
-event ereport.cpu.intel.quickpath.interconnect@motherboard/chip
+event ereport.cpu.intel.quickpath.interconnect@chip
{within(1s)};
-event upset.cpu.intel.quickpath.interconnect@motherboard/chip;
+event upset.cpu.intel.quickpath.interconnect@chip;
/* Diagnose corrected events to upsets */
-prop upset.cpu.intel.quickpath.interconnect@motherboard/chip
+prop upset.cpu.intel.quickpath.interconnect@chip
{ !STATUS_UC } (1)->
- ereport.cpu.intel.quickpath.interconnect@motherboard/chip;
+ ereport.cpu.intel.quickpath.interconnect@chip;
-engine serd.cpu.intel.quickpath.interconnect@motherboard/chip,
+engine serd.cpu.intel.quickpath.interconnect@chip,
N=3, T=72h;
-event fault.cpu.intel.quickpath.interconnect@motherboard/chip,
- engine=serd.cpu.intel.quickpath.interconnect@motherboard/chip;
+event fault.cpu.intel.quickpath.interconnect@chip,
+ engine=serd.cpu.intel.quickpath.interconnect@chip;
/* Diagnose uncorrected events to faults */
-prop fault.cpu.intel.quickpath.interconnect@motherboard/chip
+prop fault.cpu.intel.quickpath.interconnect@chip
{ STATUS_UC } (0)->
- ereport.cpu.intel.quickpath.interconnect@motherboard/chip;
+ ereport.cpu.intel.quickpath.interconnect@chip;
/*
@@ -618,7 +618,7 @@ prop fault.cpu.intel.quickpath.interconnect@motherboard/chip
/* MBox errors */
#define EX_MEM_EVENT(leafclass, t) \
event ereport.cpu.intel.quickpath.leafclass@ \
- motherboard/chip/memory-controller { within(t) }
+ chip/memory-controller { within(t) }
EX_MEM_EVENT(mem_lnktrns, 1s);
EX_MEM_EVENT(mem_lnkpers, 1s);
@@ -626,18 +626,18 @@ EX_MEM_EVENT(mem_sbfbdlinkerr, 1s);
EX_MEM_EVENT(mem_nbfbdlnkerr, 1s);
EX_MEM_EVENT(mem_lnkcrcvld, 1s);
-engine serd.cpu.intel.quickpath.mem_link_ce@motherboard/chip/memory-controller,
+engine serd.cpu.intel.quickpath.mem_link_ce@chip/memory-controller,
N=500, T=1week;
-event fault.cpu.intel.quickpath.mem_link_ce@motherboard/chip/memory-controller,
- engine=serd.cpu.intel.quickpath.mem_link_ce@motherboard/chip/memory-controller,
+event fault.cpu.intel.quickpath.mem_link_ce@chip/memory-controller,
+ engine=serd.cpu.intel.quickpath.mem_link_ce@chip/memory-controller,
retire=0, response=0;
-prop fault.cpu.intel.quickpath.mem_link_ce@motherboard/chip/memory-controller ->
- ereport.cpu.intel.quickpath.mem_lnktrns@motherboard/chip/memory-controller,
- ereport.cpu.intel.quickpath.mem_lnkpers@motherboard/chip/memory-controller,
- ereport.cpu.intel.quickpath.mem_sbfbdlinkerr@motherboard/chip/memory-controller,
- ereport.cpu.intel.quickpath.mem_nbfbdlnkerr@motherboard/chip/memory-controller,
- ereport.cpu.intel.quickpath.mem_lnkcrcvld@motherboard/chip/memory-controller;
+prop fault.cpu.intel.quickpath.mem_link_ce@chip/memory-controller ->
+ ereport.cpu.intel.quickpath.mem_lnktrns@chip/memory-controller,
+ ereport.cpu.intel.quickpath.mem_lnkpers@chip/memory-controller,
+ ereport.cpu.intel.quickpath.mem_sbfbdlinkerr@chip/memory-controller,
+ ereport.cpu.intel.quickpath.mem_nbfbdlnkerr@chip/memory-controller,
+ ereport.cpu.intel.quickpath.mem_lnkcrcvld@chip/memory-controller;
EX_MEM_EVENT(mem_lnkuncorr_uc, 1s);
EX_MEM_EVENT(mem_lnkpers_uc, 1s);
@@ -645,30 +645,30 @@ EX_MEM_EVENT(mem_sbfbdlinkerr_uc, 1s);
EX_MEM_EVENT(mem_nbfbdlnkerr_uc, 1s);
EX_MEM_EVENT(mem_lnkcrcvld_uc, 1s);
-event fault.cpu.intel.quickpath.mem_link_ue@motherboard/chip/memory-controller,
+event fault.cpu.intel.quickpath.mem_link_ue@chip/memory-controller,
retire=0;
-prop fault.cpu.intel.quickpath.mem_link_ue@motherboard/chip/memory-controller ->
- ereport.cpu.intel.quickpath.mem_lnkuncorr_uc@motherboard/chip/memory-controller,
- ereport.cpu.intel.quickpath.mem_lnkpers_uc@motherboard/chip/memory-controller,
- ereport.cpu.intel.quickpath.mem_sbfbdlinkerr_uc@motherboard/chip/memory-controller,
- ereport.cpu.intel.quickpath.mem_nbfbdlnkerr_uc@motherboard/chip/memory-controller,
- ereport.cpu.intel.quickpath.mem_lnkcrcvld_uc@motherboard/chip/memory-controller;
+prop fault.cpu.intel.quickpath.mem_link_ue@chip/memory-controller ->
+ ereport.cpu.intel.quickpath.mem_lnkuncorr_uc@chip/memory-controller,
+ ereport.cpu.intel.quickpath.mem_lnkpers_uc@chip/memory-controller,
+ ereport.cpu.intel.quickpath.mem_sbfbdlinkerr_uc@chip/memory-controller,
+ ereport.cpu.intel.quickpath.mem_nbfbdlnkerr_uc@chip/memory-controller,
+ ereport.cpu.intel.quickpath.mem_lnkcrcvld_uc@chip/memory-controller;
EX_MEM_EVENT(mem_ptrl_fsm_err, 1s);
EX_MEM_EVENT(mem_errflw_fsm_fail, 1s);
EX_MEM_EVENT(mem_vberr, 1s);
-engine serd.cpu.intel.quickpath.mem_controller_ce@motherboard/chip/memory-controller,
+engine serd.cpu.intel.quickpath.mem_controller_ce@chip/memory-controller,
N=500, T=1week;
-event fault.cpu.intel.quickpath.mem_controller_ce@motherboard/chip/memory-controller,
- engine=serd.cpu.intel.quickpath.mem_controller_ce@motherboard/chip/memory-controller,
+event fault.cpu.intel.quickpath.mem_controller_ce@chip/memory-controller,
+ engine=serd.cpu.intel.quickpath.mem_controller_ce@chip/memory-controller,
retire=0, response=0;
-prop fault.cpu.intel.quickpath.mem_controller_ce@motherboard/chip/memory-controller ->
- ereport.cpu.intel.quickpath.mem_ptrl_fsm_err@motherboard/chip/memory-controller,
- ereport.cpu.intel.quickpath.mem_errflw_fsm_fail@motherboard/chip/memory-controller,
- ereport.cpu.intel.quickpath.mem_vberr@motherboard/chip/memory-controller;
+prop fault.cpu.intel.quickpath.mem_controller_ce@chip/memory-controller ->
+ ereport.cpu.intel.quickpath.mem_ptrl_fsm_err@chip/memory-controller,
+ ereport.cpu.intel.quickpath.mem_errflw_fsm_fail@chip/memory-controller,
+ ereport.cpu.intel.quickpath.mem_vberr@chip/memory-controller;
EX_MEM_EVENT(mem_ptrl_fsm_err_uc, 1s);
EX_MEM_EVENT(mem_errflw_fsm_fail_uc, 1s);
@@ -676,27 +676,27 @@ EX_MEM_EVENT(mem_mcpar_fsmerr_uc, 1s);
EX_MEM_EVENT(mem_vberr_uc, 1s);
EX_MEM_EVENT(mem_fberr_uc, 1s);
-event fault.cpu.intel.quickpath.mem_controller_ue@motherboard/chip/memory-controller,
+event fault.cpu.intel.quickpath.mem_controller_ue@chip/memory-controller,
retire=0;
-prop fault.cpu.intel.quickpath.mem_controller_ue@motherboard/chip/memory-controller ->
- ereport.cpu.intel.quickpath.mem_ptrl_fsm_err_uc@motherboard/chip/memory-controller,
- ereport.cpu.intel.quickpath.mem_errflw_fsm_fail_uc@motherboard/chip/memory-controller,
- ereport.cpu.intel.quickpath.mem_mcpar_fsmerr_uc@motherboard/chip/memory-controller,
- ereport.cpu.intel.quickpath.mem_vberr_uc@motherboard/chip/memory-controller,
- ereport.cpu.intel.quickpath.mem_fberr_uc@motherboard/chip/memory-controller;
+prop fault.cpu.intel.quickpath.mem_controller_ue@chip/memory-controller ->
+ ereport.cpu.intel.quickpath.mem_ptrl_fsm_err_uc@chip/memory-controller,
+ ereport.cpu.intel.quickpath.mem_errflw_fsm_fail_uc@chip/memory-controller,
+ ereport.cpu.intel.quickpath.mem_mcpar_fsmerr_uc@chip/memory-controller,
+ ereport.cpu.intel.quickpath.mem_vberr_uc@chip/memory-controller,
+ ereport.cpu.intel.quickpath.mem_fberr_uc@chip/memory-controller;
EX_MEM_EVENT(mem_scrubbing_uc, 1s);
event fault.cpu.intel.quickpath.mem_scrubbing@
- motherboard/chip/memory-controller/dram-channel/dimm/rank,
+ chip/memory-controller/dram-channel/dimm/rank,
response=0;
prop fault.cpu.intel.quickpath.mem_scrubbing@
- motherboard/chip/memory-controller/dram-channel/dimm/rank[rank_num]
+ chip/memory-controller/dram-channel/dimm/rank[rank_num]
{ payloadprop_defined("rank") && rank_num == payloadprop("rank") &&
(payloadprop_defined("physaddr") || payloadprop_defined("offset")) &&
SET_ADDR && SET_OFFSET } (1)->
- ereport.cpu.intel.quickpath.mem_scrubbing_uc@motherboard/chip/memory-controller;
+ ereport.cpu.intel.quickpath.mem_scrubbing_uc@chip/memory-controller;
EX_MEM_EVENT(mem_ecc_uc, 12s);
EX_MEM_EVENT(mem_even_parity_uc, 1s);
@@ -705,61 +705,61 @@ EX_MEM_EVENT(mem_ecc, 12s);
EX_MEM_EVENT(mem_even_parity, 1s);
event error.memory.intel.ex_dimm_ce@
- motherboard/chip/memory-controller/dram-channel/dimm/rank;
+ chip/memory-controller/dram-channel/dimm/rank;
prop fault.memory.intel.page_ue@
- motherboard/chip/memory-controller/dram-channel/dimm/rank[rank_num]
+ chip/memory-controller/dram-channel/dimm/rank[rank_num]
{ payloadprop_defined("rank") && rank_num == payloadprop("rank") &&
(payloadprop_defined("physaddr") || payloadprop_defined("offset")) &&
SET_ADDR && SET_OFFSET } (0)->
- ereport.cpu.intel.quickpath.mem_ecc_uc@motherboard/chip/memory-controller,
- ereport.cpu.intel.quickpath.mem_even_parity_uc@motherboard/chip/memory-controller;
+ ereport.cpu.intel.quickpath.mem_ecc_uc@chip/memory-controller,
+ ereport.cpu.intel.quickpath.mem_even_parity_uc@chip/memory-controller;
prop fault.memory.intel.page_ce@
- motherboard/chip/memory-controller/dram-channel/dimm/rank[rank_num]
+ chip/memory-controller/dram-channel/dimm/rank[rank_num]
{ payloadprop_defined("rank") && rank_num == payloadprop("rank") &&
(payloadprop_defined("physaddr") || payloadprop_defined("offset")) &&
SET_ADDR && SET_OFFSET } (0)->
- ereport.cpu.intel.quickpath.mem_ecc@motherboard/chip/memory-controller,
- ereport.cpu.intel.quickpath.mem_even_parity@motherboard/chip/memory-controller;
+ ereport.cpu.intel.quickpath.mem_ecc@chip/memory-controller,
+ ereport.cpu.intel.quickpath.mem_even_parity@chip/memory-controller;
prop error.memory.intel.dimm_ue_ex@
- motherboard/chip/memory-controller/dram-channel/dimm/rank[rank_num]
+ chip/memory-controller/dram-channel/dimm/rank[rank_num]
{ payloadprop_defined("rank") && rank_num == payloadprop("rank") } (1)->
- ereport.cpu.intel.quickpath.mem_ecc_uc@motherboard/chip/memory-controller,
- ereport.cpu.intel.quickpath.mem_even_parity_uc@motherboard/chip/memory-controller;
+ ereport.cpu.intel.quickpath.mem_ecc_uc@chip/memory-controller,
+ ereport.cpu.intel.quickpath.mem_even_parity_uc@chip/memory-controller;
prop fault.memory.intel.dimm_ce@
- motherboard/chip/memory-controller/dram-channel/dimm
- { !confprop_defined(motherboard/chip/memory-controller/dram-channel/dimm,
+ chip/memory-controller/dram-channel/dimm
+ { !confprop_defined(chip/memory-controller/dram-channel/dimm,
"dimm-size") && setserdn(10) & setserdt(1week) } (0)->
error.memory.intel.ex_dimm_ce@
- motherboard/chip/memory-controller/dram-channel/dimm/rank;
+ chip/memory-controller/dram-channel/dimm/rank;
prop error.memory.intel.ex_dimm_ce@
- motherboard/chip/memory-controller/dram-channel/dimm/rank[rank_num]
+ chip/memory-controller/dram-channel/dimm/rank[rank_num]
{ payloadprop_defined("rank") && rank_num == payloadprop("rank") &&
- !confprop_defined(motherboard/chip/memory-controller/dram-channel/dimm,
+ !confprop_defined(chip/memory-controller/dram-channel/dimm,
"dimm-size") &&
count(STAT_CPU_MEM_CE_PGFLTS) > 512 } (1)->
- ereport.cpu.intel.quickpath.mem_ecc@motherboard/chip/memory-controller,
- ereport.cpu.intel.quickpath.mem_even_parity@motherboard/chip/memory-controller;
+ ereport.cpu.intel.quickpath.mem_ecc@chip/memory-controller,
+ ereport.cpu.intel.quickpath.mem_even_parity@chip/memory-controller;
#define EX_CPU_MEM_DIMM_CE(dimm_size, n, t, fault_rate) \
prop fault.memory.intel.dimm_ce@ \
- motherboard/chip/memory-controller/dram-channel/dimm { \
- confprop(motherboard/chip/memory-controller/dram-channel/dimm, \
+ chip/memory-controller/dram-channel/dimm { \
+ confprop(chip/memory-controller/dram-channel/dimm, \
"dimm-size") == dimm_size && \
setserdn(n) & setserdt(t) } (0)-> \
error.memory.intel.ex_dimm_ce@ \
- motherboard/chip/memory-controller/dram-channel/dimm/rank; \
+ chip/memory-controller/dram-channel/dimm/rank; \
prop error.memory.intel.ex_dimm_ce@ \
- motherboard/chip/memory-controller/dram-channel/dimm/rank[rank_num] { \
+ chip/memory-controller/dram-channel/dimm/rank[rank_num] { \
payloadprop_defined("rank") && rank_num == payloadprop("rank") && \
- confprop(motherboard/chip/memory-controller/dram-channel/dimm, \
+ confprop(chip/memory-controller/dram-channel/dimm, \
"dimm-size") == dimm_size && \
count(STAT_CPU_MEM_CE_PGFLTS) > fault_rate } (1)-> \
- ereport.cpu.intel.quickpath.mem_ecc@motherboard/chip/memory-controller, \
- ereport.cpu.intel.quickpath.mem_even_parity@motherboard/chip/memory-controller;
+ ereport.cpu.intel.quickpath.mem_ecc@chip/memory-controller, \
+ ereport.cpu.intel.quickpath.mem_even_parity@chip/memory-controller;
EX_CPU_MEM_DIMM_CE("16G", 16, 1week, 2000)
EX_CPU_MEM_DIMM_CE("8G", 8, 1week, 2000)
@@ -767,56 +767,56 @@ EX_CPU_MEM_DIMM_CE("4G", 4, 1week, 1500)
EX_CPU_MEM_DIMM_CE("2G", 4, 2week, 1000)
EX_CPU_MEM_DIMM_CE("1G", 4, 4week, 500)
-event upset.memory.intel.discard@motherboard/chip/memory-controller{within(1s)};
+event upset.memory.intel.discard@chip/memory-controller{within(1s)};
-prop upset.memory.intel.discard@motherboard/chip/memory-controller (0)->
- ereport.cpu.intel.quickpath.mem_scrubbing_uc@motherboard/chip/memory-controller,
- ereport.cpu.intel.quickpath.mem_ecc_uc@motherboard/chip/memory-controller,
- ereport.cpu.intel.quickpath.mem_even_parity_uc@motherboard/chip/memory-controller,
- ereport.cpu.intel.quickpath.mem_ecc@motherboard/chip/memory-controller,
- ereport.cpu.intel.quickpath.mem_even_parity@motherboard/chip/memory-controller;
+prop upset.memory.intel.discard@chip/memory-controller (0)->
+ ereport.cpu.intel.quickpath.mem_scrubbing_uc@chip/memory-controller,
+ ereport.cpu.intel.quickpath.mem_ecc_uc@chip/memory-controller,
+ ereport.cpu.intel.quickpath.mem_even_parity_uc@chip/memory-controller,
+ ereport.cpu.intel.quickpath.mem_ecc@chip/memory-controller,
+ ereport.cpu.intel.quickpath.mem_even_parity@chip/memory-controller;
EX_MEM_EVENT(mem_failover_mir, 1s);
-event fault.cpu.intel.quickpath.mem_failover_mir@motherboard/chip/memory-controller,
+event fault.cpu.intel.quickpath.mem_failover_mir@chip/memory-controller,
retire=0;
-prop fault.cpu.intel.quickpath.mem_failover_mir@motherboard/chip/memory-controller ->
- ereport.cpu.intel.quickpath.mem_failover_mir@motherboard/chip/memory-controller;
+prop fault.cpu.intel.quickpath.mem_failover_mir@chip/memory-controller ->
+ ereport.cpu.intel.quickpath.mem_failover_mir@chip/memory-controller;
/*
* RBox errors
*/
#define EX_EVENT(leafclass, t) \
- event ereport.cpu.intel.quickpath.leafclass@motherboard/chip { within(t) }
+ event ereport.cpu.intel.quickpath.leafclass@chip { within(t) }
-engine serd.cpu.intel.quickpath.bus_interconnect@motherboard/chip,
+engine serd.cpu.intel.quickpath.bus_interconnect@chip,
N=3, T=72h;
-event fault.cpu.intel.quickpath.bus_interconnect@motherboard/chip,
- engine=serd.cpu.intel.quickpath.bus_interconnect@motherboard/chip,
+event fault.cpu.intel.quickpath.bus_interconnect@chip,
+ engine=serd.cpu.intel.quickpath.bus_interconnect@chip,
retire=0;
EX_EVENT(bus_retry_abort, 1s);
EX_EVENT(bus_link_init_ce, 1s);
-event upset.cpu.intel.quickpath.discard@motherboard/chip;
+event upset.cpu.intel.quickpath.discard@chip;
-prop upset.cpu.intel.quickpath.discard@motherboard/chip (0)->
- ereport.cpu.intel.quickpath.bus_retry_abort@motherboard/chip,
- ereport.cpu.intel.quickpath.bus_link_init_ce@motherboard/chip;
+prop upset.cpu.intel.quickpath.discard@chip (0)->
+ ereport.cpu.intel.quickpath.bus_retry_abort@chip,
+ ereport.cpu.intel.quickpath.bus_link_init_ce@chip;
EX_EVENT(bus_unknown, 1s);
EX_EVENT(bus_single_ecc, 1s);
EX_EVENT(bus_crc_flit, 1s);
-prop fault.cpu.intel.quickpath.bus_interconnect@motherboard/chip (0)->
- ereport.cpu.intel.quickpath.bus_unknown@motherboard/chip,
- ereport.cpu.intel.quickpath.bus_single_ecc@motherboard/chip,
- ereport.cpu.intel.quickpath.bus_crc_flit@motherboard/chip;
+prop fault.cpu.intel.quickpath.bus_interconnect@chip (0)->
+ ereport.cpu.intel.quickpath.bus_unknown@chip,
+ ereport.cpu.intel.quickpath.bus_single_ecc@chip,
+ ereport.cpu.intel.quickpath.bus_crc_flit@chip;
EX_EVENT(bus_unknown_external, 1s);
EX_EVENT(bus_crc_flit_external, 1s);
-prop upset.cpu.intel.quickpath.discard@motherboard/chip (0)->
- ereport.cpu.intel.quickpath.bus_unknown_external@motherboard/chip,
- ereport.cpu.intel.quickpath.bus_crc_flit_external@motherboard/chip;
+prop upset.cpu.intel.quickpath.discard@chip (0)->
+ ereport.cpu.intel.quickpath.bus_unknown_external@chip,
+ ereport.cpu.intel.quickpath.bus_crc_flit_external@chip;
EX_EVENT(bus_unknown_uc, 1s);
EX_EVENT(bus_opr_poison_err, 1s);
@@ -828,17 +828,17 @@ EX_EVENT(bus_bad_vn_credit, 1s);
EX_EVENT(bus_hdr_double_ecc, 1s);
EX_EVENT(bus_link_retry_err, 1s);
-prop fault.cpu.intel.quickpath.bus_interconnect@motherboard/chip
+prop fault.cpu.intel.quickpath.bus_interconnect@chip
{ setserdincrement(4) } (0)->
- ereport.cpu.intel.quickpath.bus_unknown_uc@motherboard/chip,
- ereport.cpu.intel.quickpath.bus_opr_poison_err@motherboard/chip,
- ereport.cpu.intel.quickpath.bus_eot_parity@motherboard/chip,
- ereport.cpu.intel.quickpath.bus_rta_parity@motherboard/chip,
- ereport.cpu.intel.quickpath.bus_bad_sbu_route@motherboard/chip,
- ereport.cpu.intel.quickpath.bus_bad_msg@motherboard/chip,
- ereport.cpu.intel.quickpath.bus_bad_vn_credit@motherboard/chip,
- ereport.cpu.intel.quickpath.bus_hdr_double_ecc@motherboard/chip,
- ereport.cpu.intel.quickpath.bus_link_retry_err@motherboard/chip;
+ ereport.cpu.intel.quickpath.bus_unknown_uc@chip,
+ ereport.cpu.intel.quickpath.bus_opr_poison_err@chip,
+ ereport.cpu.intel.quickpath.bus_eot_parity@chip,
+ ereport.cpu.intel.quickpath.bus_rta_parity@chip,
+ ereport.cpu.intel.quickpath.bus_bad_sbu_route@chip,
+ ereport.cpu.intel.quickpath.bus_bad_msg@chip,
+ ereport.cpu.intel.quickpath.bus_bad_vn_credit@chip,
+ ereport.cpu.intel.quickpath.bus_hdr_double_ecc@chip,
+ ereport.cpu.intel.quickpath.bus_link_retry_err@chip;
EX_EVENT(bus_unknown_uc_external, 1s);
EX_EVENT(bus_opr_poison_err_external, 1s);
@@ -850,49 +850,49 @@ EX_EVENT(bus_bad_vn_credit_external, 1s);
EX_EVENT(bus_hdr_double_ecc_external, 1s);
EX_EVENT(bus_link_retry_err_external, 1s);
-prop upset.cpu.intel.quickpath.discard@motherboard/chip (0)->
- ereport.cpu.intel.quickpath.bus_unknown_uc_external@motherboard/chip,
- ereport.cpu.intel.quickpath.bus_opr_poison_err_external@motherboard/chip,
- ereport.cpu.intel.quickpath.bus_eot_parity_external@motherboard/chip,
- ereport.cpu.intel.quickpath.bus_rta_parity_external@motherboard/chip,
- ereport.cpu.intel.quickpath.bus_bad_sbu_route_external@motherboard/chip,
- ereport.cpu.intel.quickpath.bus_bad_msg_external@motherboard/chip,
- ereport.cpu.intel.quickpath.bus_bad_vn_credit_external@motherboard/chip,
- ereport.cpu.intel.quickpath.bus_hdr_double_ecc_external@motherboard/chip,
- ereport.cpu.intel.quickpath.bus_link_retry_err_external@motherboard/chip;
+prop upset.cpu.intel.quickpath.discard@chip (0)->
+ ereport.cpu.intel.quickpath.bus_unknown_uc_external@chip,
+ ereport.cpu.intel.quickpath.bus_opr_poison_err_external@chip,
+ ereport.cpu.intel.quickpath.bus_eot_parity_external@chip,
+ ereport.cpu.intel.quickpath.bus_rta_parity_external@chip,
+ ereport.cpu.intel.quickpath.bus_bad_sbu_route_external@chip,
+ ereport.cpu.intel.quickpath.bus_bad_msg_external@chip,
+ ereport.cpu.intel.quickpath.bus_bad_vn_credit_external@chip,
+ ereport.cpu.intel.quickpath.bus_hdr_double_ecc_external@chip,
+ ereport.cpu.intel.quickpath.bus_link_retry_err_external@chip;
/*
* CBox errors
*/
EX_EVENT(llc_ewb_uc, 1s);
-event fault.cpu.intel.quickpath.llc_ewb@motherboard/chip,
+event fault.cpu.intel.quickpath.llc_ewb@chip,
retire=0, response=0;
-prop fault.cpu.intel.quickpath.llc_ewb@motherboard/chip
+prop fault.cpu.intel.quickpath.llc_ewb@chip
{ (payloadprop_defined("physaddr") || payloadprop_defined("offset")) &&
SET_ADDR && SET_OFFSET } (1)->
- ereport.cpu.intel.quickpath.llc_ewb_uc@motherboard/chip;
+ ereport.cpu.intel.quickpath.llc_ewb_uc@chip;
-prop upset.cpu.intel.quickpath.discard@motherboard/chip (0)->
- ereport.cpu.intel.quickpath.llc_ewb_uc@motherboard/chip;
+prop upset.cpu.intel.quickpath.discard@chip (0)->
+ ereport.cpu.intel.quickpath.llc_ewb_uc@chip;
/*
* SBox errors
*/
EX_EVENT(system_cache_uc, 1s);
-event fault.cpu.intel.quickpath.system_cache@motherboard/chip,
+event fault.cpu.intel.quickpath.system_cache@chip,
retire=0, response=0;
-prop fault.cpu.intel.quickpath.system_cache@motherboard/chip ->
- ereport.cpu.intel.quickpath.system_cache_uc@motherboard/chip;
+prop fault.cpu.intel.quickpath.system_cache@chip ->
+ ereport.cpu.intel.quickpath.system_cache_uc@chip;
/*
* BBox errors
*/
EX_EVENT(home_agent_uc, 1s);
-event fault.cpu.intel.quickpath.home_agent@motherboard/chip,
+event fault.cpu.intel.quickpath.home_agent@chip,
retire=0, response=0;
-prop fault.cpu.intel.quickpath.home_agent@motherboard/chip ->
- ereport.cpu.intel.quickpath.home_agent_uc@motherboard/chip;
+prop fault.cpu.intel.quickpath.home_agent@chip ->
+ ereport.cpu.intel.quickpath.home_agent_uc@chip;
/*
* UBox errors
@@ -900,18 +900,18 @@ prop fault.cpu.intel.quickpath.home_agent@motherboard/chip ->
EX_EVENT(sys_cfg_cfa_ecc, 1s);
EX_EVENT(sys_cfg_uc, 1s);
-engine serd.cpu.intel.quickpath.sys_cfg@motherboard/chip,
+engine serd.cpu.intel.quickpath.sys_cfg@chip,
N=2, T=72h;
-event fault.cpu.intel.quickpath.sys_cfg@motherboard/chip,
- engine=serd.cpu.intel.quickpath.sys_cfg@motherboard/chip,
+event fault.cpu.intel.quickpath.sys_cfg@chip,
+ engine=serd.cpu.intel.quickpath.sys_cfg@chip,
retire=0, response=0;
-prop fault.cpu.intel.quickpath.sys_cfg@motherboard/chip (0)->
- ereport.cpu.intel.quickpath.sys_cfg_cfa_ecc@motherboard/chip;
+prop fault.cpu.intel.quickpath.sys_cfg@chip (0)->
+ ereport.cpu.intel.quickpath.sys_cfg_cfa_ecc@chip;
-prop fault.cpu.intel.quickpath.sys_cfg@motherboard/chip
+prop fault.cpu.intel.quickpath.sys_cfg@chip
{ setserdincrement(3) } (0)->
- ereport.cpu.intel.quickpath.sys_cfg_uc@motherboard/chip;
+ ereport.cpu.intel.quickpath.sys_cfg_uc@chip;
/*
* Handling poison errors
@@ -927,11 +927,11 @@ event fault.cpu.intel.discard_fatal@motherboard,
prop fault.cpu.intel.has_poison@motherboard
{ payloadprop_defined("poison") && 1 == payloadprop("poison") } (1)->
- ereport.cpu.intel.quickpath.mem_scrubbing_uc@motherboard/chip<>/memory-controller<>,
- ereport.cpu.intel.quickpath.llc_ewb_uc@motherboard/chip<>,
- ereport.cpu.intel.quickpath.system_cache_uc@motherboard/chip<>,
- ereport.cpu.intel.quickpath.bus_opr_poison_err@motherboard/chip<>,
- ereport.cpu.intel.quickpath.bus_opr_poison_err_external@motherboard/chip<>;
+ ereport.cpu.intel.quickpath.mem_scrubbing_uc@chip<>/memory-controller<>,
+ ereport.cpu.intel.quickpath.llc_ewb_uc@chip<>,
+ ereport.cpu.intel.quickpath.system_cache_uc@chip<>,
+ ereport.cpu.intel.quickpath.bus_opr_poison_err@chip<>,
+ ereport.cpu.intel.quickpath.bus_opr_poison_err_external@chip<>;
prop fault.cpu.intel.discard_fatal@motherboard
{ count(stat.has_poison@motherboard[0]) > count(stat.discard_fatal@motherboard[0]) &&
diff --git a/usr/src/cmd/mdb/intel/modules/generic_cpu/gcpu.c b/usr/src/cmd/mdb/intel/modules/generic_cpu/gcpu.c
index 99b7742b96..3fe17e8afc 100644
--- a/usr/src/cmd/mdb/intel/modules/generic_cpu/gcpu.c
+++ b/usr/src/cmd/mdb/intel/modules/generic_cpu/gcpu.c
@@ -45,6 +45,9 @@ typedef struct cmi_hdl_impl {
const struct cmi_mc_ops *cmih_mcops; /* Memory-controller ops */
void *cmih_mcdata; /* Memory-controller data */
uint64_t cmih_flags;
+ uint16_t cmih_smbiosid; /* SMBIOS Type 4 struct ID */
+ uint_t cmih_smb_chipid; /* smbios chipid */
+ nvlist_t *cmih_smb_bboard; /* smbios bboard */
} cmi_hdl_impl_t;
typedef struct cmi_hdl_ent {
diff --git a/usr/src/cmd/smbios/smbios.c b/usr/src/cmd/smbios/smbios.c
index 09373dc1be..6ecde1ef11 100644
--- a/usr/src/cmd/smbios/smbios.c
+++ b/usr/src/cmd/smbios/smbios.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -21,12 +20,10 @@
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/sysmacros.h>
#include <sys/param.h>
@@ -266,6 +263,7 @@ static void
print_bboard(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_bboard_t b;
+ int chdl_cnt;
(void) smbios_info_bboard(shp, id, &b);
@@ -276,12 +274,32 @@ print_bboard(smbios_hdl_t *shp, id_t id, FILE *fp)
desc_printf(smbios_bboard_type_desc(b.smbb_type),
fp, " Board Type: 0x%x", b.smbb_type);
+
+ chdl_cnt = b.smbb_contn;
+ if (chdl_cnt != 0) {
+ id_t *chdl;
+ uint16_t hdl;
+ int i, n, cnt;
+
+ chdl = alloca(chdl_cnt * sizeof (id_t));
+ cnt = smbios_info_contains(shp, id, chdl_cnt, chdl);
+ if (cnt > SMB_CONT_MAX)
+ return;
+ n = MIN(chdl_cnt, cnt);
+
+ oprintf(fp, "\n");
+ for (i = 0; i < n; i++) {
+ hdl = (uint16_t)chdl[i];
+ oprintf(fp, " Contained Handle: %u\n", hdl);
+ }
+ }
}
static void
print_chassis(smbios_hdl_t *shp, id_t id, FILE *fp)
{
smbios_chassis_t c;
+ int elem_cnt;
(void) smbios_info_chassis(shp, id, &c);
@@ -302,7 +320,37 @@ print_chassis(smbios_hdl_t *shp, id_t id, FILE *fp)
oprintf(fp, " Chassis Height: %uu\n", c.smbc_uheight);
oprintf(fp, " Power Cords: %u\n", c.smbc_cords);
- oprintf(fp, " Element Records: %u\n", c.smbc_elems);
+
+ elem_cnt = c.smbc_elems;
+ oprintf(fp, " Element Records: %u\n", elem_cnt);
+
+ if (elem_cnt > 0) {
+ id_t *elems;
+ uint8_t type;
+ int i, n, cnt;
+
+ elems = alloca(c.smbc_elems * sizeof (id_t));
+ cnt = smbios_info_contains(shp, id, elem_cnt, elems);
+ if (cnt > SMB_CONT_MAX)
+ return;
+ n = MIN(elem_cnt, cnt);
+
+ oprintf(fp, "\n");
+ for (i = 0; i < n; i++) {
+ type = (uint8_t)elems[i];
+ if (type & 0x80) {
+ /* SMBIOS structrure Type */
+ desc_printf(smbios_type_name(type & 0x7f), fp,
+ " Contained SMBIOS structure Type: %u",
+ type & 0x80);
+ } else {
+ /* SMBIOS Base Board Type */
+ desc_printf(smbios_bboard_type_desc(type), fp,
+ " Contained SMBIOS Base Board Type: 0x%x",
+ type);
+ }
+ }
+ }
}
static void
@@ -767,6 +815,109 @@ print_ipmi(smbios_hdl_t *shp, FILE *fp)
}
static int
+check_oem(smbios_hdl_t *shp)
+{
+ int i;
+ int cnt;
+ int rv;
+ id_t oem_id;
+ smbios_struct_t s;
+ const char **oem_str;
+
+ rv = smbios_lookup_type(shp, SMB_TYPE_OEMSTR, &s);
+ if (rv != 0) {
+ return (-1);
+ }
+
+ oem_id = s.smbstr_id;
+
+ cnt = smbios_info_strtab(shp, oem_id, 0, NULL);
+ if (cnt > 0) {
+ oem_str = alloca(sizeof (char *) * cnt);
+ (void) smbios_info_strtab(shp, oem_id, cnt, oem_str);
+
+ for (i = 0; i < cnt; i++) {
+ if (strncmp(oem_str[i], SMB_PRMS1,
+ strlen(SMB_PRMS1) + 1) == 0) {
+ return (0);
+ }
+ }
+ }
+
+ return (-1);
+}
+
+static void
+print_extprocessor(smbios_hdl_t *shp, id_t id, FILE *fp)
+{
+ int i;
+ smbios_processor_ext_t ep;
+
+ if (check_oem(shp) != 0)
+ return;
+
+ (void) smbios_info_extprocessor(shp, id, &ep);
+
+ oprintf(fp, " Processor: %u\n", ep.smbpe_processor);
+ oprintf(fp, " FRU: %u\n", ep.smbpe_fru);
+ oprintf(fp, " Initial APIC ID count: %u\n\n", ep.smbpe_n);
+
+ for (i = 0; i < ep.smbpe_n; i++) {
+ oprintf(fp, " Logical Strand %u: Initial APIC ID: %u\n", i,
+ ep.smbpe_apicid[i]);
+ }
+}
+
+static void
+print_pciexrc(smbios_hdl_t *shp, id_t id, FILE *fp)
+{
+ smbios_pciexrc_t pcie;
+
+ if (check_oem(shp) != 0)
+ return;
+
+ (void) smbios_info_pciexrc(shp, id, &pcie);
+
+ oprintf(fp, " Component ID: %u\n", pcie.smbpcie_bb);
+ oprintf(fp, " BDF: 0x%x\n", pcie.smbpcie_bdf);
+}
+
+static void
+print_extmemarray(smbios_hdl_t *shp, id_t id, FILE *fp)
+{
+ smbios_memarray_ext_t em;
+
+ if (check_oem(shp) != 0)
+ return;
+
+ (void) smbios_info_extmemarray(shp, id, &em);
+
+ oprintf(fp, " Physical Memory Array Handle: %u\n", em.smbmae_ma);
+ oprintf(fp, " Component Parent Handle: %u\n", em.smbmae_comp);
+ oprintf(fp, " BDF: 0x%x\n", em.smbmae_bdf);
+}
+
+static void
+print_extmemdevice(smbios_hdl_t *shp, id_t id, FILE *fp)
+{
+ int i;
+ smbios_memdevice_ext_t emd;
+
+ if (check_oem(shp) != 0)
+ return;
+
+ (void) smbios_info_extmemdevice(shp, id, &emd);
+
+ oprintf(fp, " Memory Device Handle: %u\n", emd.smbmdeve_md);
+ oprintf(fp, " DRAM Channel: %u\n", emd.smbmdeve_drch);
+ oprintf(fp, " Number of Chip Selects: %u\n", emd.smbmdeve_ncs);
+
+ for (i = 0; i < emd.smbmdeve_ncs; i++) {
+ oprintf(fp, " Chip Select: %u\n", emd.smbmdeve_cs[i]);
+ }
+}
+
+static int
print_struct(smbios_hdl_t *shp, const smbios_struct_t *sp, void *fp)
{
smbios_info_t info;
@@ -886,6 +1037,22 @@ print_struct(smbios_hdl_t *shp, const smbios_struct_t *sp, void *fp)
oprintf(fp, "\n");
print_ipmi(shp, fp);
break;
+ case SUN_OEM_EXT_PROCESSOR:
+ oprintf(fp, "\n");
+ print_extprocessor(shp, sp->smbstr_id, fp);
+ break;
+ case SUN_OEM_PCIEXRC:
+ oprintf(fp, "\n");
+ print_pciexrc(shp, sp->smbstr_id, fp);
+ break;
+ case SUN_OEM_EXT_MEMARRAY:
+ oprintf(fp, "\n");
+ print_extmemarray(shp, sp->smbstr_id, fp);
+ break;
+ case SUN_OEM_EXT_MEMDEVICE:
+ oprintf(fp, "\n");
+ print_extmemdevice(shp, sp->smbstr_id, fp);
+ break;
default:
hex++;
}
diff --git a/usr/src/common/smbios/smb_info.c b/usr/src/common/smbios/smb_info.c
index c374101a3b..b1882c74ca 100644
--- a/usr/src/common/smbios/smb_info.c
+++ b/usr/src/common/smbios/smb_info.c
@@ -63,6 +63,7 @@
* To simplify life for our clients, we factor these common things out into
* smbios_info_t, which can be retrieved for any structure. The following
* table describes the mapping from a given structure to the smbios_info_t.
+ * Multiple SMBIOS stuctures' contained objects are also handled here.
*/
static const struct smb_infospec {
uint8_t is_type; /* structure type */
@@ -73,6 +74,9 @@ static const struct smb_infospec {
uint8_t is_asset; /* asset tag offset */
uint8_t is_location; /* location string offset */
uint8_t is_part; /* part number offset */
+ uint8_t is_contc; /* contained count */
+ uint8_t is_contsz; /* contained size */
+ uint8_t is_contv; /* contained objects */
} _smb_infospecs[] = {
{ SMB_TYPE_SYSTEM,
offsetof(smb_system_t, smbsi_manufacturer),
@@ -81,6 +85,9 @@ static const struct smb_infospec {
offsetof(smb_system_t, smbsi_serial),
0,
0,
+ 0,
+ 0,
+ 0,
0 },
{ SMB_TYPE_BASEBOARD,
offsetof(smb_bboard_t, smbbb_manufacturer),
@@ -89,7 +96,10 @@ static const struct smb_infospec {
offsetof(smb_bboard_t, smbbb_serial),
offsetof(smb_bboard_t, smbbb_asset),
offsetof(smb_bboard_t, smbbb_location),
- 0 },
+ 0,
+ offsetof(smb_bboard_t, smbbb_cn),
+ SMB_CONT_WORD,
+ offsetof(smb_bboard_t, smbbb_cv) },
{ SMB_TYPE_CHASSIS,
offsetof(smb_chassis_t, smbch_manufacturer),
0,
@@ -97,7 +107,10 @@ static const struct smb_infospec {
offsetof(smb_chassis_t, smbch_serial),
offsetof(smb_chassis_t, smbch_asset),
0,
- 0 },
+ 0,
+ offsetof(smb_chassis_t, smbch_cn),
+ SMB_CONT_BYTE,
+ offsetof(smb_chassis_t, smbch_cv) },
{ SMB_TYPE_PROCESSOR,
offsetof(smb_processor_t, smbpr_manufacturer),
0,
@@ -105,7 +118,10 @@ static const struct smb_infospec {
offsetof(smb_processor_t, smbpr_serial),
offsetof(smb_processor_t, smbpr_asset),
offsetof(smb_processor_t, smbpr_socket),
- offsetof(smb_processor_t, smbpr_part) },
+ offsetof(smb_processor_t, smbpr_part),
+ 0,
+ 0,
+ 0 },
{ SMB_TYPE_CACHE,
0,
0,
@@ -113,6 +129,9 @@ static const struct smb_infospec {
0,
0,
offsetof(smb_cache_t, smbca_socket),
+ 0,
+ 0,
+ 0,
0 },
{ SMB_TYPE_PORT,
0,
@@ -121,6 +140,9 @@ static const struct smb_infospec {
0,
0,
offsetof(smb_port_t, smbpo_iref),
+ 0,
+ 0,
+ 0,
0 },
{ SMB_TYPE_SLOT,
0,
@@ -129,6 +151,9 @@ static const struct smb_infospec {
0,
0,
offsetof(smb_slot_t, smbsl_name),
+ 0,
+ 0,
+ 0,
0 },
{ SMB_TYPE_MEMDEVICE,
offsetof(smb_memdevice_t, smbmdev_manufacturer),
@@ -137,7 +162,10 @@ static const struct smb_infospec {
offsetof(smb_memdevice_t, smbmdev_serial),
offsetof(smb_memdevice_t, smbmdev_asset),
offsetof(smb_memdevice_t, smbmdev_dloc),
- offsetof(smb_memdevice_t, smbmdev_part) },
+ offsetof(smb_memdevice_t, smbmdev_part),
+ 0,
+ 0,
+ 0 },
{ SMB_TYPE_POWERSUP,
offsetof(smb_powersup_t, smbpsup_manufacturer),
offsetof(smb_powersup_t, smbpsup_devname),
@@ -145,7 +173,10 @@ static const struct smb_infospec {
offsetof(smb_powersup_t, smbpsup_serial),
offsetof(smb_powersup_t, smbpsup_asset),
offsetof(smb_powersup_t, smbpsup_loc),
- offsetof(smb_powersup_t, smbpsup_part) },
+ offsetof(smb_powersup_t, smbpsup_part),
+ 0,
+ 0,
+ 0 },
{ SMB_TYPE_EOT }
};
@@ -240,6 +271,50 @@ smbios_info_common(smbios_hdl_t *shp, id_t id, smbios_info_t *ip)
return (n ? 0 : smb_set_errno(shp, ESMB_NOINFO));
}
+/*
+ * Returns the actual number of contained objects.
+ *
+ * idc - number of contained objects
+ * idv - returned array of contained objects
+ */
+int
+smbios_info_contains(smbios_hdl_t *shp, id_t id, uint_t idc, id_t *idv)
+{
+ const smb_struct_t *stp = smb_lookup_id(shp, id);
+ const struct smb_infospec *isp;
+ id_t *cp;
+ uint_t size;
+ uint8_t cnt;
+ int i, n;
+
+ if (stp == NULL) {
+ return (-1); /* errno is set for us */
+ }
+
+ for (isp = _smb_infospecs; isp->is_type != SMB_TYPE_EOT; isp++) {
+ if (isp->is_type == stp->smbst_hdr->smbh_type)
+ break;
+ }
+ if (isp->is_type == SMB_TYPE_EOT)
+ return (smb_set_errno(shp, ESMB_TYPE));
+
+ size = isp->is_contsz;
+ cnt = *((uint8_t *)(uintptr_t)stp->smbst_hdr + isp->is_contc);
+ cp = (id_t *)((uintptr_t)stp->smbst_hdr + isp->is_contv);
+
+ n = MIN(cnt, idc);
+ for (i = 0; i < n; i++) {
+ if (size == SMB_CONT_WORD)
+ idv[i] = *((uint8_t *)(uintptr_t)cp + (i * 2));
+ else if (size == SMB_CONT_BYTE)
+ idv[i] = *((uint8_t *)(uintptr_t)cp + (i * 3));
+ else
+ return (smb_set_errno(shp, ESMB_INVAL));
+ }
+
+ return (cnt);
+}
+
id_t
smbios_info_bios(smbios_hdl_t *shp, smbios_bios_t *bp)
{
@@ -324,14 +399,10 @@ smbios_info_bboard(smbios_hdl_t *shp, id_t id, smbios_bboard_t *bbp)
smb_info_bcopy(stp->smbst_hdr, &bb, sizeof (bb));
bzero(bbp, sizeof (smbios_bboard_t));
- /*
- * At present, we do not provide support for the contained object
- * handles portion of the Base Board structure, as none of the 2.3+
- * BIOSes commonly in use appear to implement it at present.
- */
bbp->smbb_chassis = bb.smbbb_chassis;
bbp->smbb_flags = bb.smbbb_flags;
bbp->smbb_type = bb.smbbb_type;
+ bbp->smbb_contn = bb.smbbb_cn;
return (0);
}
@@ -351,11 +422,6 @@ smbios_info_chassis(smbios_hdl_t *shp, id_t id, smbios_chassis_t *chp)
smb_info_bcopy(stp->smbst_hdr, &ch, sizeof (ch));
bzero(chp, sizeof (smbios_chassis_t));
- /*
- * At present, we do not provide support for the contained object
- * handles portion of the Chassis structure, as none of the 2.3+
- * BIOSes commonly in use appear to implement it at present.
- */
chp->smbc_oemdata = ch.smbch_oemdata;
chp->smbc_lock = (ch.smbch_type & SMB_CHT_LOCK) != 0;
chp->smbc_type = ch.smbch_type & ~SMB_CHT_LOCK;
@@ -366,6 +432,7 @@ smbios_info_chassis(smbios_hdl_t *shp, id_t id, smbios_chassis_t *chp)
chp->smbc_uheight = ch.smbch_uheight;
chp->smbc_cords = ch.smbch_cords;
chp->smbc_elems = ch.smbch_cn;
+ chp->smbc_elemlen = ch.smbch_cm;
return (0);
}
@@ -912,3 +979,95 @@ smbios_csn(smbios_hdl_t *shp)
return (smb_get_sn(shp, &psn, &csn) == SMB_ERR ? NULL : csn);
}
+
+int
+smbios_info_extprocessor(smbios_hdl_t *shp, id_t id,
+ smbios_processor_ext_t *epp)
+{
+ const smb_struct_t *stp = smb_lookup_id(shp, id);
+ smb_processor_ext_t *exp;
+
+ if (stp == NULL)
+ return (-1); /* errno is set for us */
+
+ if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_PROCESSOR)
+ return (smb_set_errno(shp, ESMB_TYPE));
+
+ exp = (smb_processor_ext_t *)(uintptr_t)stp->smbst_hdr;
+ bzero(epp, sizeof (smbios_processor_ext_t));
+
+ epp->smbpe_processor = exp->smbpre_processor;
+ epp->smbpe_fru = exp->smbpre_fru;
+ epp->smbpe_n = exp->smbpre_n;
+ epp->smbpe_apicid = exp->smbpre_apicid;
+
+ return (0);
+}
+
+int
+smbios_info_pciexrc(smbios_hdl_t *shp, id_t id,
+ smbios_pciexrc_t *rcp)
+{
+ const smb_struct_t *stp = smb_lookup_id(shp, id);
+ smb_pciexrc_t rc;
+
+ if (stp == NULL)
+ return (-1); /* errno is set for us */
+
+ if (stp->smbst_hdr->smbh_type != SUN_OEM_PCIEXRC)
+ return (smb_set_errno(shp, ESMB_TYPE));
+
+ smb_info_bcopy(stp->smbst_hdr, &rc, sizeof (rc));
+ bzero(rcp, sizeof (smbios_pciexrc_t));
+
+ rcp->smbpcie_bb = rc.smbpciexrc_bboard;
+ rcp->smbpcie_bdf = rc.smbpciexrc_bdf;
+
+ return (0);
+}
+
+int
+smbios_info_extmemarray(smbios_hdl_t *shp, id_t id, smbios_memarray_ext_t *emap)
+{
+ const smb_struct_t *stp = smb_lookup_id(shp, id);
+ smb_memarray_ext_t exma;
+
+ if (stp == NULL)
+ return (-1); /* errno is set for us */
+
+ if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_MEMARRAY)
+ return (smb_set_errno(shp, ESMB_TYPE));
+
+ smb_info_bcopy(stp->smbst_hdr, &exma, sizeof (exma));
+ bzero(emap, sizeof (smbios_memarray_ext_t));
+
+ emap->smbmae_ma = exma.smbmarre_ma;
+ emap->smbmae_comp = exma.smbmarre_component;
+ emap->smbmae_bdf = exma.smbmarre_bdf;
+
+ return (0);
+}
+
+int
+smbios_info_extmemdevice(smbios_hdl_t *shp, id_t id,
+ smbios_memdevice_ext_t *emdp)
+{
+ const smb_struct_t *stp = smb_lookup_id(shp, id);
+ smb_memdevice_ext_t exmd;
+
+ if (stp == NULL)
+ return (-1); /* errno is set for us */
+
+ if (stp->smbst_hdr->smbh_type != SUN_OEM_EXT_MEMDEVICE)
+ return (smb_set_errno(shp, ESMB_TYPE));
+
+ smb_info_bcopy(stp->smbst_hdr, &exmd, sizeof (exmd));
+ bzero(emdp, sizeof (smbios_memdevice_ext_t));
+
+ emdp->smbmdeve_md = exmd.smbmdeve_mdev;
+ emdp->smbmdeve_drch = exmd.smbmdeve_dchan;
+ emdp->smbmdeve_ncs = exmd.smbmdeve_ncs;
+ emdp->smbmdeve_cs = exmd.smbmdeve_cs;
+
+ return (0);
+}
diff --git a/usr/src/common/smbios/smb_open.c b/usr/src/common/smbios/smb_open.c
index b56fa4748c..a2967e4565 100644
--- a/usr/src/common/smbios/smb_open.c
+++ b/usr/src/common/smbios/smb_open.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -21,12 +20,10 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/smbios_impl.h>
static const uint_t _smb_hashlen = 64; /* hash length (must be Pof2) */
@@ -306,6 +303,20 @@ smbios_lookup_id(smbios_hdl_t *shp, id_t id, smbios_struct_t *sp)
}
int
+smbios_lookup_type(smbios_hdl_t *shp, uint_t type, smbios_struct_t *sp)
+{
+ const smb_struct_t *stp = smb_lookup_type(shp, type);
+
+ if (stp == NULL)
+ return (-1); /* errno is set for us */
+
+ if (sp != NULL)
+ (void) smb_export(stp, sp);
+
+ return (0);
+}
+
+int
smbios_iter(smbios_hdl_t *shp, smbios_struct_f *func, void *data)
{
const smb_struct_t *sp = shp->sh_structs;
diff --git a/usr/src/lib/fm/topo/libtopo/common/mapfile-vers b/usr/src/lib/fm/topo/libtopo/common/mapfile-vers
index f142d7be95..edcee2ae3b 100644
--- a/usr/src/lib/fm/topo/libtopo/common/mapfile-vers
+++ b/usr/src/lib/fm/topo/libtopo/common/mapfile-vers
@@ -121,6 +121,7 @@ SUNWprivate {
topo_mod_unregister;
topo_mod_walk_init;
topo_mod_zalloc;
+ topo_mod_smbios;
topo_node_asru;
topo_node_asru_set;
topo_node_bind;
diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_mod.map b/usr/src/lib/fm/topo/libtopo/common/topo_mod.map
index 44f8d2aaf0..160d9f461f 100644
--- a/usr/src/lib/fm/topo/libtopo/common/topo_mod.map
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_mod.map
@@ -66,6 +66,8 @@
topo_mod_walk_init = FUNCTION extern;
+ topo_mod_smbios = FUNCTION extern;
+
topo_method_register = FUNCTION extern;
topo_method_unregister = FUNCTION extern;
topo_method_unregister_all = FUNCTION extern;
diff --git a/usr/src/lib/fm/topo/maps/i86pc/Makefile b/usr/src/lib/fm/topo/maps/i86pc/Makefile
index a0dfd3b827..4e9475b546 100644
--- a/usr/src/lib/fm/topo/maps/i86pc/Makefile
+++ b/usr/src/lib/fm/topo/maps/i86pc/Makefile
@@ -27,7 +27,7 @@ ARCH = i86pc
CLASS = arch
DTDFILE = topology.dtd.1
TOPOFILE = i86pc-hc-topology.xml chip-hc-topology.xml psu-hc-topology.xml \
-fan-hc-topology.xml chassis-hc-topology.xml
+fan-hc-topology.xml i86pc-legacy-hc-topology.xml chassis-hc-topology.xml
SRCDIR = ../i86pc
diff --git a/usr/src/lib/fm/topo/maps/i86pc/i86pc-hc-topology.xml b/usr/src/lib/fm/topo/maps/i86pc/i86pc-hc-topology.xml
index 053fe0565b..5002e13068 100644
--- a/usr/src/lib/fm/topo/maps/i86pc/i86pc-hc-topology.xml
+++ b/usr/src/lib/fm/topo/maps/i86pc/i86pc-hc-topology.xml
@@ -27,131 +27,8 @@
<topology name='i86pc' scheme='hc'>
- <range name='motherboard' min='0' max='0'>
- <node instance='0'>
- <set type='product' setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4100-M2|Sun-Fire-X4200-M2|Sun-Fire-X4140|Sun-Fire-X4240|Sun-Fire-X4440|Sun-Fire-X4500|Sun-Fire-X4540|Sun-Fire-X4600-M2'>
- <fac-enum provider='fac_prov_ipmi' />
- <propgroup name='protocol' version='1'
- name-stability='Private' data-stability='Private' >
- <propval name='label' type='string' value='MB' />
- </propgroup>
- <propgroup name='ipmi' version='1'
- name-stability='Private' data-stability='Private' >
- <propval name='entity_ref' type='string_array' >
- <propitem value='MB' />
- <propitem value='mb.fru' />
- </propval>
- </propgroup>
-
- </set>
- <set type='product' setlist='SUN-FIRE-X4150|SUN-FIRE-X4250|SUN-FIRE-X4450'>
- <fac-enum provider='fac_prov_ipmi' />
- <propgroup name='protocol' version='1'
- name-stability='Private' data-stability='Private' >
- <propval name='label' type='string' value='MB' />
- </propgroup>
- <propgroup name='ipmi' version='1'
- name-stability='Private' data-stability='Private' >
- <propval name='entity_ref' type='string' value='MB' />
- </propgroup>
-
- </set>
- <set type='product' setlist='default'>
- <propgroup name='protocol' version='1'
- name-stability='Private' data-stability='Private' >
- <propval name='label' type='string' value='MB' />
- </propgroup>
- </set>
- </node>
-
- <dependents grouping='children'>
- <range name='chip' min='0' max='100'>
- <enum-method name='chip' version='1' />
- <propmap name='chip' />
- </range>
- <range name='hostbridge' min='0' max='254'>
- <enum-method name='hostbridge' version='1' />
- </range>
- </dependents>
-
- </range>
-
<range name='chassis' min='0' max='0'>
- <propmap name='chassis' />
-
- <dependents grouping='children'>
-
- <set type='product' setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4100-M2|Sun-Fire-X4200-M2|Sun-Fire-X4140|Sun-Fire-X4240|Sun-Fire-X4440'>
- <range name='psu' min='0' max='100'>
- <enum-method name='ipmi' version='1' />
- <propmap name='psu' />
- </range>
- <range name='fanmodule' min='0' max='100'>
- <propmap name='fan' />
- </range>
- <set type='product' setlist='Sun-Fire-X4200-M2'>
- <range name='bay' min='0' max='3'>
- <propmap name='Sun-Fire-X4200-M2-disk' />
- </range>
- </set>
- <set type='product' setlist='Sun-Fire-X4200-Server'>
- <range name='bay' min='0' max='3'>
- <propmap name='Sun-Fire-X4200-Server-disk' />
- </range>
- </set>
- <set type='product' setlist='default'>
- <range name='bay' min='0' max='1024'>
- <enum-method name='ses' version='1' />
- </range>
- </set>
- </set>
-
- <set type='product' setlist='Sun-Fire-X4500|Sun-Fire-X4540|SUN-FIRE-X4150|SUN-FIRE-X4250|SUN-FIRE-X4450'>
- <range name='psu' min='0' max='100'>
- <propmap name='psu' />
- </range>
- <range name='fanmodule' min='0' max='100'>
- <propmap name='fan' />
- </range>
- <set type='product' setlist='Sun-Fire-X4500'>
- <range name='bay' min='0' max='47'>
- <propmap name='Sun-Fire-X4500-disk' />
- </range>
- </set>
- <set type='product' setlist='Sun-Fire-X4540'>
- <range name='bay' min='0' max='47'>
- <propmap name='Sun-Fire-X4540-disk' />
- </range>
- </set>
- </set>
-
- <set type='product' setlist='Sun-Fire-X4600|Sun-Fire-X4600-M2'>
- <range name='psu' min='0' max='100'>
- <enum-method name='ipmi' version='1' />
- <propmap name='psu' />
- </range>
- <range name='fan' min='0' max='3'>
- <propmap name='fan' />
- </range>
- <range name='bay' min='0' max='3'>
- <propmap name='Sun-Fire-X4600-M2-disk' />
- </range>
- </set>
-
- <set type='product' setlist='default'>
- <range name='psu' min='0' max='100'>
- <enum-method name='ipmi' version='1' />
- </range>
- <range name='fan' min='0' max='100'>
- <enum-method name='ipmi' version='1' />
- </range>
- <range name='bay' min='0' max='1024'>
- <enum-method name='ses' version='1' />
- </range>
- </set>
-
- </dependents>
-
+ <enum-method name='x86pi' version='1' />
</range>
<range name='ses-enclosure' min='0' max='1024'>
diff --git a/usr/src/lib/fm/topo/maps/i86pc/i86pc-legacy-hc-topology.xml b/usr/src/lib/fm/topo/maps/i86pc/i86pc-legacy-hc-topology.xml
new file mode 100644
index 0000000000..d6ef9b2e07
--- /dev/null
+++ b/usr/src/lib/fm/topo/maps/i86pc/i86pc-legacy-hc-topology.xml
@@ -0,0 +1,166 @@
+<?xml version="1.0"?>
+<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1">
+<!--
+ Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ Use is subject to license terms.
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+-->
+
+<!--
+ This map file is loaded by the generic enumerator (x86pi.so) when
+ an FMA-compliant SMBIOS can't be found.
+-->
+
+<topology name='i86pc' scheme='hc'>
+
+ <range name='motherboard' min='0' max='0'>
+ <node instance='0'>
+ <set type='product' setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4100-M2|Sun-Fire-X4200-M2|Sun-Fire-X4140|Sun-Fire-X4240|Sun-Fire-X4440|Sun-Fire-X4500|Sun-Fire-X4540|Sun-Fire-X4600-M2'>
+ <fac-enum provider='fac_prov_ipmi' />
+ <propgroup name='protocol' version='1'
+ name-stability='Private' data-stability='Private' >
+ <propval name='label' type='string' value='MB' />
+ </propgroup>
+ <propgroup name='ipmi' version='1'
+ name-stability='Private' data-stability='Private' >
+ <propval name='entity_ref' type='string_array' >
+ <propitem value='MB' />
+ <propitem value='mb.fru' />
+ </propval>
+ </propgroup>
+
+ </set>
+ <set type='product' setlist='SUN-FIRE-X4150|SUN-FIRE-X4250|SUN-FIRE-X4450'>
+ <fac-enum provider='fac_prov_ipmi' />
+ <propgroup name='protocol' version='1'
+ name-stability='Private' data-stability='Private' >
+ <propval name='label' type='string' value='MB' />
+ </propgroup>
+ <propgroup name='ipmi' version='1'
+ name-stability='Private' data-stability='Private' >
+ <propval name='entity_ref' type='string' value='MB' />
+ </propgroup>
+
+ </set>
+ <set type='product' setlist='default'>
+ <propgroup name='protocol' version='1'
+ name-stability='Private' data-stability='Private' >
+ <propval name='label' type='string' value='MB' />
+ </propgroup>
+ </set>
+ </node>
+
+ <dependents grouping='children'>
+ <range name='chip' min='0' max='100'>
+ <enum-method name='chip' version='1' />
+ <propmap name='chip' />
+ </range>
+ <range name='hostbridge' min='0' max='254'>
+ <enum-method name='hostbridge' version='1' />
+ </range>
+ </dependents>
+
+ </range>
+
+ <range name='chassis' min='0' max='0'>
+ <propmap name='chassis' />
+
+ <dependents grouping='children'>
+
+ <set type='product' setlist='Sun-Fire-X4100-Server|Sun-Fire-X4200-Server|Sun-Fire-X4100-M2|Sun-Fire-X4200-M2|Sun-Fire-X4140|Sun-Fire-X4240|Sun-Fire-X4440'>
+ <range name='psu' min='0' max='100'>
+ <enum-method name='ipmi' version='1' />
+ <propmap name='psu' />
+ </range>
+ <range name='fanmodule' min='0' max='100'>
+ <propmap name='fan' />
+ </range>
+ <set type='product' setlist='Sun-Fire-X4200-M2'>
+ <range name='bay' min='0' max='3'>
+ <propmap name='Sun-Fire-X4200-M2-disk' />
+ </range>
+ </set>
+ <set type='product' setlist='Sun-Fire-X4200-Server'>
+ <range name='bay' min='0' max='3'>
+ <propmap name='Sun-Fire-X4200-Server-disk' />
+ </range>
+ </set>
+ <set type='product' setlist='default'>
+ <range name='bay' min='0' max='1024'>
+ <enum-method name='ses' version='1' />
+ </range>
+ </set>
+ </set>
+
+ <set type='product' setlist='Sun-Fire-X4500|Sun-Fire-X4540|SUN-FIRE-X4150|SUN-FIRE-X4250|SUN-FIRE-X4450'>
+ <range name='psu' min='0' max='100'>
+ <propmap name='psu' />
+ </range>
+ <range name='fanmodule' min='0' max='100'>
+ <propmap name='fan' />
+ </range>
+ <set type='product' setlist='Sun-Fire-X4500'>
+ <range name='bay' min='0' max='47'>
+ <propmap name='Sun-Fire-X4500-disk' />
+ </range>
+ </set>
+ <set type='product' setlist='Sun-Fire-X4540'>
+ <range name='bay' min='0' max='47'>
+ <propmap name='Sun-Fire-X4540-disk' />
+ </range>
+ </set>
+ </set>
+
+ <set type='product' setlist='Sun-Fire-X4600|Sun-Fire-X4600-M2'>
+ <range name='psu' min='0' max='100'>
+ <enum-method name='ipmi' version='1' />
+ <propmap name='psu' />
+ </range>
+ <range name='fan' min='0' max='3'>
+ <propmap name='fan' />
+ </range>
+ <range name='bay' min='0' max='3'>
+ <propmap name='Sun-Fire-X4600-M2-disk' />
+ </range>
+ </set>
+
+ <set type='product' setlist='default'>
+ <range name='psu' min='0' max='100'>
+ <enum-method name='ipmi' version='1' />
+ </range>
+ <range name='fan' min='0' max='100'>
+ <enum-method name='ipmi' version='1' />
+ </range>
+ <range name='bay' min='0' max='1024'>
+ <enum-method name='ses' version='1' />
+ </range>
+ </set>
+
+ </dependents>
+
+ </range>
+
+ <range name='ses-enclosure' min='0' max='1024'>
+ <enum-method name='ses' version='1' />
+ </range>
+
+</topology>
diff --git a/usr/src/lib/fm/topo/modules/common/pcibus/did_props.c b/usr/src/lib/fm/topo/modules/common/pcibus/did_props.c
index 3724e78c5a..cc0ededcdc 100644
--- a/usr/src/lib/fm/topo/modules/common/pcibus/did_props.c
+++ b/usr/src/lib/fm/topo/modules/common/pcibus/did_props.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -129,15 +129,23 @@ txprop_t RC_common_props[] = {
{ NULL, &io_pgroup, TOPO_IO_MODULE, MODULEprop_set },
{ NULL, &pci_pgroup, TOPO_PCI_EXCAP, EXCAP_set },
{ NULL, &pci_pgroup, TOPO_PCI_BDF, BDF_set },
+ { NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set },
+ /*
+ * These props need to be put at the end of table. x86pi has its
+ * own way to set them.
+ */
{ NULL, &protocol_pgroup, TOPO_PROP_LABEL, label_set },
- { NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set },
- { NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set }
+ { NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set }
};
txprop_t ExHB_common_props[] = {
+ { NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set },
+ /*
+ * These props need to be put at the end of table. x86pi has its
+ * own way to set them.
+ */
{ NULL, &protocol_pgroup, TOPO_PROP_LABEL, label_set },
- { NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set },
- { NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set }
+ { NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set }
};
txprop_t IOB_common_props[] = {
@@ -150,9 +158,13 @@ txprop_t HB_common_props[] = {
{ NULL, &io_pgroup, TOPO_IO_DEV, DEVprop_set },
{ NULL, &io_pgroup, TOPO_IO_DRIVER, DRIVERprop_set },
{ NULL, &io_pgroup, TOPO_IO_MODULE, MODULEprop_set },
+ { NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set },
+ /*
+ * These props need to be put at the end of table. x86pi has its
+ * own way to set them.
+ */
{ NULL, &protocol_pgroup, TOPO_PROP_LABEL, label_set },
- { NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set },
- { NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set }
+ { NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set }
};
int Bus_propcnt = sizeof (Bus_common_props) / sizeof (txprop_t);
diff --git a/usr/src/lib/fm/topo/modules/i86pc/Makefile b/usr/src/lib/fm/topo/modules/i86pc/Makefile
index baef73bd75..f42af0a306 100644
--- a/usr/src/lib/fm/topo/modules/i86pc/Makefile
+++ b/usr/src/lib/fm/topo/modules/i86pc/Makefile
@@ -20,12 +20,11 @@
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-SUBDIRS = chip hostbridge pcibus
+SUBDIRS = chip hostbridge pcibus x86pi
.PARALLEL: $(SUBDIRS)
diff --git a/usr/src/lib/fm/topo/modules/i86pc/chip/Makefile b/usr/src/lib/fm/topo/modules/i86pc/chip/Makefile
index 1af838ab64..ff2d070398 100644
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/Makefile
+++ b/usr/src/lib/fm/topo/modules/i86pc/chip/Makefile
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -27,7 +27,7 @@ MODULE = chip
ARCH = i86pc
CLASS = arch
MODULESRCS = chip.c chip_label.c chip_subr.c chip_amd.c chip_intel.c\
-chip_serial.c
+chip_serial.c chip_smbios.c
include ../../Makefile.plugin
-LDLIBS += -lipmi -lfmd_agent -lumem
+LDLIBS += -lipmi -lfmd_agent -lumem -lsmbios
diff --git a/usr/src/lib/fm/topo/modules/i86pc/chip/chip.c b/usr/src/lib/fm/topo/modules/i86pc/chip/chip.c
index 347c70e9c0..e6b75fa8e7 100644
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip.c
+++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip.c
@@ -143,7 +143,7 @@ is_xpv(void)
static tnode_t *
create_node(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth, char *name,
- topo_instance_t inst)
+ topo_instance_t inst, uint16_t smbios_id)
{
nvlist_t *fmri;
tnode_t *cnode;
@@ -152,22 +152,57 @@ create_node(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth, char *name,
whinge(mod, NULL, "create_node: mkrsrc failed\n");
return (NULL);
}
+
+ if (FM_AWARE_SMBIOS(mod)) {
+ id_t phys_cpu_smbid;
+ int perr = 0;
+ const char *serial = NULL;
+ const char *part = NULL;
+ const char *rev = NULL;
+
+ phys_cpu_smbid = smbios_id;
+ serial = chip_serial_smbios_get(mod, phys_cpu_smbid);
+ part = chip_part_smbios_get(mod, phys_cpu_smbid);
+ rev = chip_rev_smbios_get(mod, phys_cpu_smbid);
+
+ perr += nvlist_add_string(fmri, FM_FMRI_HC_SERIAL_ID,
+ serial);
+ perr += nvlist_add_string(fmri, FM_FMRI_HC_PART,
+ part);
+ perr += nvlist_add_string(fmri, FM_FMRI_HC_REVISION,
+ rev);
+
+ if (perr != 0)
+ whinge(mod, NULL,
+ "create_node: nvlist_add_string failed\n");
+
+ topo_mod_strfree(mod, (char *)serial);
+ topo_mod_strfree(mod, (char *)part);
+ topo_mod_strfree(mod, (char *)rev);
+ }
+
cnode = topo_node_bind(mod, pnode, name, inst, fmri);
+
nvlist_free(fmri);
- if (cnode == NULL)
- whinge(mod, NULL, "create_node: node bind failed for %s %d\n",
- name, (int)inst);
+ if (cnode == NULL) {
+ whinge(mod, NULL, "create_node: node bind failed"
+ " for %s %d\n", name, (int)inst);
+ }
return (cnode);
}
static int
-create_strand(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu, nvlist_t *auth)
+create_strand(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu,
+ nvlist_t *auth, uint16_t chip_smbiosid)
{
tnode_t *strand;
int32_t strandid, cpuid;
- int err, nerr = 0;
+ int err, perr, nerr = 0;
nvlist_t *fmri;
+ char *serial = NULL;
+ char *part = NULL;
+ char *rev = NULL;
if ((err = nvlist_lookup_int32(cpu, FM_PHYSCPU_INFO_STRAND_ID,
&strandid)) != 0) {
@@ -183,19 +218,40 @@ create_strand(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu, nvlist_t *auth)
}
if ((strand = create_node(mod, pnode, auth, STRAND_NODE_NAME,
- strandid)) == NULL)
+ strandid, chip_smbiosid)) == NULL)
return (-1);
/*
* Inherit FRU from core node, in native use cpu scheme ASRU,
* in xpv, use hc scheme ASRU.
*/
- (void) topo_node_fru_set(strand, NULL, 0, &err);
+ (void) topo_node_fru_set(strand, NULL, 0, &perr);
+ /*
+ * From the inherited FRU, extract the Serial
+ * number(if SMBIOS donates) and set it in the ASRU
+ */
+ if (FM_AWARE_SMBIOS(mod)) {
+ char *val = NULL;
+
+ if (topo_prop_get_fmri(strand, TOPO_PGROUP_PROTOCOL,
+ TOPO_PROP_RESOURCE, &fmri, &err) != 0)
+ whinge(mod, NULL,
+ "create_strand: topo_prop_get_fmri failed\n");
+ if (nvlist_lookup_string(fmri, FM_FMRI_HC_SERIAL_ID, &val) != 0)
+ whinge(mod, NULL,
+ "create_strand: nvlist_lookup_string failed: \n");
+ else
+ serial = topo_mod_strdup(mod, val);
+ nvlist_free(fmri);
+ }
if (is_xpv()) {
if (topo_node_resource(strand, &fmri, &err) == -1) {
whinge(mod, &nerr, "create_strand: "
"topo_node_resource failed\n");
} else {
+ if (FM_AWARE_SMBIOS(mod))
+ (void) nvlist_add_string(fmri,
+ FM_FMRI_HC_SERIAL_ID, serial);
(void) topo_node_asru_set(strand, fmri, 0, &err);
nvlist_free(fmri);
}
@@ -204,7 +260,7 @@ create_strand(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu, nvlist_t *auth)
whinge(mod, &nerr, "create_strand: lookup cpuid "
"failed\n");
} else {
- if ((fmri = cpu_fmri_create(mod, cpuid, NULL, 0))
+ if ((fmri = cpu_fmri_create(mod, cpuid, serial, 0))
!= NULL) {
(void) topo_node_asru_set(strand, fmri,
0, &err);
@@ -224,16 +280,55 @@ create_strand(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu, nvlist_t *auth)
nerr -= add_nvlist_longprops(mod, strand, cpu, PGNAME(STRAND), NULL,
STRAND_CHIP_ID, STRAND_CORE_ID, STRAND_CPU_ID, NULL);
+ if (FM_AWARE_SMBIOS(mod)) {
+ (void) topo_node_label_set(strand, NULL, &perr);
+
+ if (topo_node_resource(strand, &fmri, &perr) != 0) {
+ whinge(mod, &nerr, "create_strand: "
+ "topo_node_resource failed\n");
+ perr = 0;
+ }
+
+ perr += nvlist_lookup_string(fmri,
+ FM_FMRI_HC_PART, &part);
+ perr += nvlist_lookup_string(fmri,
+ FM_FMRI_HC_REVISION, &rev);
+
+ if (perr != 0) {
+ whinge(mod, NULL,
+ "create_strand: nvlist_lookup_string failed\n");
+ perr = 0;
+ }
+
+ perr += topo_prop_set_string(strand, PGNAME(STRAND),
+ FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE, serial, &perr);
+ perr += topo_prop_set_string(strand, PGNAME(STRAND),
+ FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE, part, &perr);
+ perr += topo_prop_set_string(strand, PGNAME(STRAND),
+ FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE, rev, &perr);
+
+ if (perr != 0)
+ whinge(mod, NULL, "create_strand: topo_prop_set_string"
+ "failed\n");
+
+ nvlist_free(fmri);
+ topo_mod_strfree(mod, serial);
+ }
+
return (err == 0 && nerr == 0 ? 0 : -1);
}
static int
-create_core(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu, nvlist_t *auth)
+create_core(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu,
+ nvlist_t *auth, uint16_t chip_smbiosid)
{
tnode_t *core;
int32_t coreid, cpuid;
- int err, nerr = 0;
+ int err, perr, nerr = 0;
nvlist_t *fmri;
+ char *serial = NULL;
+ char *part = NULL;
+ char *rev = NULL;
if ((err = nvlist_lookup_int32(cpu, FM_PHYSCPU_INFO_CORE_ID, &coreid))
!= 0) {
@@ -243,19 +338,40 @@ create_core(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu, nvlist_t *auth)
}
if ((core = topo_node_lookup(pnode, CORE_NODE_NAME, coreid)) == NULL) {
if ((core = create_node(mod, pnode, auth, CORE_NODE_NAME,
- coreid)) == NULL)
+ coreid, chip_smbiosid)) == NULL)
return (-1);
/*
* Inherit FRU from the chip node, for native, we use hc
* scheme ASRU for the core node.
*/
- (void) topo_node_fru_set(core, NULL, 0, &err);
+ (void) topo_node_fru_set(core, NULL, 0, &perr);
+ /*
+ * From the inherited FRU, extract the Serial
+ * number if SMBIOS donates and set it in the ASRU
+ */
+ if (FM_AWARE_SMBIOS(mod)) {
+ char *val = NULL;
+
+ if (topo_node_resource(core, &fmri, &err) != 0)
+ whinge(mod, NULL,
+ "create_core: topo_prop_get_fmri failed\n");
+ if (nvlist_lookup_string(fmri, FM_FMRI_HC_SERIAL_ID,
+ &val) != 0)
+ whinge(mod, NULL, "create_core:"
+ "nvlist_lookup_string failed\n");
+ else
+ serial = topo_mod_strdup(mod, val);
+ nvlist_free(fmri);
+ }
if (is_xpv()) {
if (topo_node_resource(core, &fmri, &err) == -1) {
whinge(mod, &nerr, "create_core: "
"topo_node_resource failed\n");
} else {
+ if (FM_AWARE_SMBIOS(mod))
+ (void) nvlist_add_string(fmri,
+ FM_FMRI_HC_SERIAL_ID, serial);
(void) topo_node_asru_set(core, fmri, 0, &err);
nvlist_free(fmri);
}
@@ -273,7 +389,7 @@ create_core(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu, nvlist_t *auth)
return (-1);
}
- if (! is_xpv()) {
+ if (!is_xpv()) {
/*
* In native mode, we're in favor of cpu scheme ASRU for
* printing reason. More work needs to be done to support
@@ -283,7 +399,7 @@ create_core(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu, nvlist_t *auth)
whinge(mod, &nerr, "create_core: lookup cpuid "
"failed\n");
} else {
- if ((fmri = cpu_fmri_create(mod, cpuid, NULL, 0))
+ if ((fmri = cpu_fmri_create(mod, cpuid, serial, 0))
!= NULL) {
(void) topo_node_asru_set(core, fmri, 0, &err);
nvlist_free(fmri);
@@ -294,7 +410,42 @@ create_core(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu, nvlist_t *auth)
}
}
- err = create_strand(mod, core, cpu, auth);
+ if (FM_AWARE_SMBIOS(mod)) {
+ (void) topo_node_label_set(core, NULL, &perr);
+
+ if (topo_node_resource(core, &fmri, &perr) != 0) {
+ whinge(mod, &nerr, "create_core: "
+ "topo_node_resource failed\n");
+ perr = 0;
+ }
+
+ perr += nvlist_lookup_string(fmri,
+ FM_FMRI_HC_PART, &part);
+ perr += nvlist_lookup_string(fmri,
+ FM_FMRI_HC_REVISION, &rev);
+
+ if (perr != 0) {
+ whinge(mod, NULL,
+ "create_core: nvlist_lookup_string failed\n");
+ perr = 0;
+ }
+
+ perr += topo_prop_set_string(core, PGNAME(CORE),
+ FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE, serial, &perr);
+ perr += topo_prop_set_string(core, PGNAME(CORE),
+ FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE, part, &perr);
+ perr += topo_prop_set_string(core, PGNAME(CORE),
+ FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE, rev, &perr);
+
+ if (perr != 0)
+ whinge(mod, NULL, "create_core: topo_prop_set_string"
+ "failed\n");
+
+ nvlist_free(fmri);
+ topo_mod_strfree(mod, serial);
+ }
+
+ err = create_strand(mod, core, cpu, auth, chip_smbiosid);
return (err == 0 && nerr == 0 ? 0 : -1);
}
@@ -307,14 +458,19 @@ create_chip(topo_mod_t *mod, tnode_t *pnode, topo_instance_t min,
tnode_t *chip;
int32_t chipid;
nvlist_t *fmri = NULL;
- int err, nerr = 0;
+ int err, perr, nerr = 0;
int32_t fms[3];
const char *vendor;
boolean_t create_mc = B_FALSE;
+ uint16_t smbios_id;
+ /*
+ * /dev/fm will export the chipid based on SMBIOS' ordering
+ * of Type-4 structures, if SMBIOS meets FMA needs
+ */
if ((err = nvlist_lookup_int32(cpu, FM_PHYSCPU_INFO_CHIP_ID, &chipid))
!= 0) {
- whinge(mod, NULL, "create_chip: lookup chip_id failed: %s\n",
+ whinge(mod, &nerr, "create_chip: lookup chip_id failed: %s\n",
strerror(err));
return (-1);
}
@@ -322,21 +478,37 @@ create_chip(topo_mod_t *mod, tnode_t *pnode, topo_instance_t min,
if (chipid < min || chipid > max)
return (-1);
+ if (FM_AWARE_SMBIOS(mod)) {
+ if ((err = nvlist_lookup_uint16(cpu,
+ FM_PHYSCPU_INFO_SMBIOS_ID, &smbios_id)) != 0) {
+ whinge(mod, NULL,
+ "create_chip: lookup smbios_id failed"
+ ": enumerating x86pi & chip topology, but"
+ " no Chip properties from SMBIOS"
+ " - err msg : %s\n", strerror(err));
+ /*
+ * Lets reset the module specific
+ * data to NULL, overriding any
+ * SMBIOS capability encoded earlier.
+ * This will fail all subsequent
+ * FM_AWARE_SMBIOS checks.
+ */
+ topo_mod_setspecific(mod, NULL);
+ }
+ }
+
if ((chip = topo_node_lookup(pnode, CHIP_NODE_NAME, chipid)) == NULL) {
if ((chip = create_node(mod, pnode, auth, CHIP_NODE_NAME,
- chipid)) == NULL)
+ chipid, smbios_id)) == NULL)
return (-1);
-
- if (topo_method_register(mod, chip, chip_methods) < 0)
- whinge(mod, &nerr, "create_chip: "
- "topo_method_register failed\n");
-
- if (topo_node_resource(chip, &fmri, &err) == -1) {
- whinge(mod, &nerr, "create_chip: "
- "topo_node_resource failed\n");
- } else {
- (void) topo_node_fru_set(chip, fmri, 0, &err);
- nvlist_free(fmri);
+ /*
+ * Do not register XML map methods if SMBIOS can provide
+ * serial, part, revision & label
+ */
+ if (!FM_AWARE_SMBIOS(mod)) {
+ if (topo_method_register(mod, chip, chip_methods) < 0)
+ whinge(mod, &nerr, "create_chip: "
+ "topo_method_register failed\n");
}
(void) topo_pgroup_create(chip, &chip_pgroup, &err);
@@ -345,6 +517,83 @@ create_chip(topo_mod_t *mod, tnode_t *pnode, topo_instance_t min,
nerr -= add_nvlist_longprops(mod, chip, cpu, PGNAME(CHIP),
fms, CHIP_FAMILY, CHIP_MODEL, CHIP_STEPPING, NULL);
+ if (FM_AWARE_SMBIOS(mod)) {
+ int fru = 0;
+ char *serial = NULL;
+ char *part = NULL;
+ char *rev = NULL;
+ char *label;
+
+ fru = chip_fru_smbios_get(mod, smbios_id);
+ /*
+ * Chip is not a FRU, set the FRU fmri of parent node
+ */
+ if (topo_node_resource(chip, &fmri, &perr) != 0)
+ whinge(mod, &nerr, "create_chip: "
+ "topo_node_resource failed\n");
+ if (!fru) {
+ (void) topo_node_fru_set(chip, NULL, 0, &perr);
+ label = NULL;
+ } else {
+ label = (char *)chip_label_smbios_get(mod,
+ pnode, smbios_id, NULL);
+
+ if (topo_node_fru_set(chip, fmri, 0, &perr)
+ != 0) {
+ whinge(mod, NULL, "create_chip: "
+ "topo_node_fru_set failed\n");
+ perr = 0;
+ }
+ }
+
+ perr += nvlist_lookup_string(fmri,
+ FM_FMRI_HC_SERIAL_ID, &serial);
+ perr += nvlist_lookup_string(fmri,
+ FM_FMRI_HC_PART, &part);
+ perr += nvlist_lookup_string(fmri,
+ FM_FMRI_HC_REVISION, &rev);
+
+ if (perr != 0) {
+ whinge(mod, NULL,
+ "create_chip: nvlist_lookup_string"
+ "failed\n");
+ perr = 0;
+ }
+
+ perr += topo_prop_set_string(chip, PGNAME(CHIP),
+ FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE,
+ serial, &perr);
+ perr += topo_prop_set_string(chip, PGNAME(CHIP),
+ FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE,
+ part, &perr);
+ perr += topo_prop_set_string(chip, PGNAME(CHIP),
+ FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE,
+ rev, &perr);
+
+ if (perr != 0)
+ whinge(mod, NULL,
+ "create_chip: topo_prop_set_string"
+ "failed\n");
+
+ nvlist_free(fmri);
+
+ if (topo_node_label_set(chip, label, &perr)
+ == -1) {
+ whinge(mod, NULL, "create_chip: "
+ "topo_node_label_set failed\n");
+ }
+ topo_mod_strfree(mod, label);
+
+ } else {
+ if (topo_node_resource(chip, &fmri, &err) == -1) {
+ whinge(mod, &nerr, "create_chip: "
+ "topo_node_resource failed\n");
+ } else {
+ (void) topo_node_fru_set(chip, fmri, 0, &perr);
+ nvlist_free(fmri);
+ }
+ }
+
if (topo_method_register(mod, chip, strands_retire_methods) < 0)
whinge(mod, &nerr, "create_chip: "
"topo_method_register failed\n");
@@ -356,18 +605,46 @@ create_chip(topo_mod_t *mod, tnode_t *pnode, topo_instance_t min,
create_mc = B_TRUE;
}
- err = create_core(mod, chip, cpu, auth);
+ if (FM_AWARE_SMBIOS(mod)) {
+ int status = 0;
+ /*
+ * STATUS
+ * CPU Socket Populated
+ * CPU Socket Unpopulated
+ * Populated : Enabled
+ * Populated : Disabled by BIOS (Setup)
+ * Populated : Disabled by BIOS (Error)
+ * Populated : Idle
+ *
+ * Enumerate core & strand only for Populated : Enabled
+ * Enumerate Off-Chip Memory Controller only for
+ * Populated : Enabled
+ */
+
+ status = chip_status_smbios_get(mod, (id_t)smbios_id);
+ if (!status) {
+ whinge(mod, NULL, "create_chip: "
+ "CPU Socket is not populated or is disabled\n");
+ return (0);
+ }
+ }
+
+ err = create_core(mod, chip, cpu, auth, smbios_id);
/*
* Create memory-controller node under a chip for architectures
* that may have on-chip memory-controller(s).
+ * If SMBIOS meets FMA needs, when Multi-Chip-Module is
+ * addressed, mc instances should be derived from SMBIOS
*/
if (create_mc) {
if (strcmp(vendor, "AuthenticAMD") == 0)
- amd_mc_create(mod, chip, MCT_NODE_NAME, auth,
+ amd_mc_create(mod, smbios_id, chip, MCT_NODE_NAME, auth,
fms[0], fms[1], fms[2], &nerr);
- else if (!mc_offchip)
- onchip_mc_create(mod, chip, MCT_NODE_NAME, auth);
+ else if (!mc_offchip) {
+ onchip_mc_create(mod, smbios_id, chip,
+ MCT_NODE_NAME, auth);
+ }
}
return (err == 0 && nerr == 0 ? 0 : -1);
@@ -415,7 +692,7 @@ create_chips(topo_mod_t *mod, tnode_t *pnode, const char *name,
/*ARGSUSED*/
static int
chip_enum(topo_mod_t *mod, tnode_t *pnode, const char *name,
- topo_instance_t min, topo_instance_t max, void *arg, void *notused)
+ topo_instance_t min, topo_instance_t max, void *arg, void *smbios_enabled)
{
int rv = 0;
nvlist_t *auth = NULL;
@@ -446,6 +723,29 @@ chip_enum(topo_mod_t *mod, tnode_t *pnode, const char *name,
}
}
+ /*
+ * Set Chip Enumerator Module's private data with the value passed by
+ * x86pi Enumerator, defining SMBIOS capabilities
+ */
+ topo_mod_setspecific(mod, smbios_enabled);
+
+ if (FM_AWARE_SMBIOS(mod))
+ if (init_chip_smbios(mod) != 0) {
+ whinge(mod, NULL,
+ "init_chip_smbios() failed, "
+ " enumerating x86pi & chip topology, but no"
+ " CPU & Memory properties will be"
+ " derived from SMBIOS\n");
+ /*
+ * Lets reset the module specific
+ * data to NULL, overriding any
+ * SMBIOS capability encoded earlier.
+ * This will fail all subsequent
+ * FM_AWARE_SMBIOS checks.
+ */
+ topo_mod_setspecific(mod, NULL);
+ }
+
auth = topo_mod_auth(mod, pnode);
offchip_mc = mc_offchip_open();
diff --git a/usr/src/lib/fm/topo/modules/i86pc/chip/chip.h b/usr/src/lib/fm/topo/modules/i86pc/chip/chip.h
index 980769e879..740b59415b 100644
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip.h
+++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip.h
@@ -37,6 +37,21 @@ extern "C" {
#define CHIP_VERSION TOPO_VERSION
+/* Below should match the definitions in x86pi_impl.h */
+#define X86PI_FULL 1
+#define X86PI_NONE 2
+
+/*
+ * FM_AWARE_SMBIOS means SMBIOS meets FMA needs
+ * X86PI_FULL is defined as 1 in x86pi.so
+ * And passed from x86pi.so to chip.so as module
+ * private data
+ */
+#define FM_AWARE_SMBIOS(mod) \
+ (topo_mod_getspecific(mod) != NULL && \
+ (*(int *)topo_mod_getspecific(mod) == X86PI_FULL))
+#define IGNORE_ID 0xFFFF
+
#define CHIP_NODE_NAME "chip"
#define CORE_NODE_NAME "core"
#define STRAND_NODE_NAME "strand"
@@ -161,19 +176,34 @@ extern int mem_asru_create(topo_mod_t *, nvlist_t *, nvlist_t **);
/*
* Prototypes for chip_amd.c
*/
-extern void amd_mc_create(topo_mod_t *, tnode_t *, const char *, nvlist_t *,
- int, int, int, int *);
+extern void amd_mc_create(topo_mod_t *, uint16_t, tnode_t *,
+ const char *, nvlist_t *, int, int, int, int *);
/*
* Prototypes for chip_intel.c
*/
extern int mc_offchip_open(void);
extern int mc_offchip_create(topo_mod_t *, tnode_t *, const char *, nvlist_t *);
-extern void onchip_mc_create(topo_mod_t *, tnode_t *, const char *, nvlist_t *);
+extern void onchip_mc_create(topo_mod_t *, uint16_t, tnode_t *,
+ const char *, nvlist_t *);
extern char *get_fmtstr(topo_mod_t *, nvlist_t *);
extern int store_prop_val(topo_mod_t *, char *, char *, nvlist_t **out);
+/*
+ * Prototypes for chip_smbios.c
+ */
+
+extern int init_chip_smbios(topo_mod_t *);
+extern int chip_status_smbios_get(topo_mod_t *, id_t);
+extern int chip_fru_smbios_get(topo_mod_t *, id_t);
+extern const char *chip_label_smbios_get(topo_mod_t *, tnode_t *, id_t, char *);
+extern const char *chip_serial_smbios_get(topo_mod_t *, id_t);
+extern const char *chip_part_smbios_get(topo_mod_t *, id_t);
+extern const char *chip_rev_smbios_get(topo_mod_t *, id_t);
+extern id_t memnode_to_smbiosid(uint16_t, const char *, uint64_t, void *);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/fm/topo/modules/i86pc/chip/chip_amd.c b/usr/src/lib/fm/topo/modules/i86pc/chip/chip_amd.c
index a97d18db85..deb0913bce 100644
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip_amd.c
+++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip_amd.c
@@ -98,6 +98,19 @@ const topo_method_t ntv_page_retire_methods[] = {
{ NULL }
};
+/*
+ * Serials, Labels are obtained from SMBIOS, so
+ * we leave out the related methods, any other
+ * methods that will be added to gen_cs_methods
+ * should be added to x86pi_gen_cs_methods too
+ */
+static const topo_method_t x86pi_gen_cs_methods[] = {
+ { TOPO_METH_ASRU_COMPUTE, TOPO_METH_ASRU_COMPUTE_DESC,
+ TOPO_METH_ASRU_COMPUTE_VERSION, TOPO_STABILITY_INTERNAL,
+ mem_asru_compute },
+ { NULL }
+};
+
static const topo_method_t gen_cs_methods[] = {
{ TOPO_METH_ASRU_COMPUTE, TOPO_METH_ASRU_COMPUTE_DESC,
TOPO_METH_ASRU_COMPUTE_VERSION, TOPO_STABILITY_INTERNAL,
@@ -127,8 +140,8 @@ static nvlist_t *cs_fmri[MC_CHIP_NCS];
*/
/*ARGSUSED*/
static int
-amd_generic_mc_create(topo_mod_t *mod, tnode_t *cnode, tnode_t *mcnode,
- int family, int model, int stepping, nvlist_t *auth)
+amd_generic_mc_create(topo_mod_t *mod, uint16_t smbid, tnode_t *cnode,
+ tnode_t *mcnode, int family, int model, int stepping, nvlist_t *auth)
{
int chan, cs;
@@ -176,6 +189,15 @@ amd_generic_mc_create(topo_mod_t *mod, tnode_t *cnode, tnode_t *mcnode,
(void) topo_prop_set_string(chnode, PGNAME(CHAN), "channel",
TOPO_PROP_IMMUTABLE, chan == 0 ? "A" : "B", &err);
+ if (FM_AWARE_SMBIOS(mod)) {
+ if (topo_node_label_set(chnode, NULL, &err) == -1)
+ whinge(mod, NULL, "amd_generic_mc_create: "
+ "topo_node_label_set\n");
+ if (topo_node_fru_set(chnode, NULL, 0, &err) != 0)
+ whinge(mod, NULL, "amd_generic_mc_create: "
+ "topo_node_fru_set failed\n");
+ }
+
if (topo_node_range_create(mod, chnode, CS_NODE_NAME,
0, MAX_CSNUM) < 0) {
whinge(mod, NULL, "amd_generic_mc_create: "
@@ -206,16 +228,76 @@ amd_generic_mc_create(topo_mod_t *mod, tnode_t *cnode, tnode_t *mcnode,
* The topology does not represent pages (there are
* too many) so when a page is faulted we generate
* an ASRU to represent the individual page.
+ * If SMBIOS meets FMA needs, derive labels & serials
+ * for DIMMS and apply to chip-select nodes.
+ * If deriving from SMBIOS, skip IPMI
*/
- if (topo_method_register(mod, csnode,
- gen_cs_methods) < 0)
- whinge(mod, NULL, "amd_generic_mc_create: "
- "method registration failed\n");
+ if (FM_AWARE_SMBIOS(mod)) {
+ if (topo_method_register(mod, csnode,
+ x86pi_gen_cs_methods) < 0)
+ whinge(mod, NULL,
+ "amd_generic_mc_create: "
+ "method registration failed\n");
+ } else {
+ if (topo_method_register(mod, csnode,
+ gen_cs_methods) < 0)
+ whinge(mod, NULL,
+ "amd_generic_mc_create: method"
+ "registration failed\n");
+ }
(void) topo_node_asru_set(csnode, fmri,
TOPO_ASRU_COMPUTE, &err);
-
nvlist_free(fmri);
+
+ /*
+ * If SMBIOS meets FMA needs, set DIMM as the FRU for
+ * the chip-select node. Use the channel & chip-select
+ * numbers to get the DIMM instance.
+ * Send via inst : dram channel number
+ * Receive via inst : dimm instance
+ */
+ if (FM_AWARE_SMBIOS(mod)) {
+ int inst;
+ id_t dimm_smbid;
+ const char *serial;
+ const char *part;
+ const char *rev;
+ char *label;
+
+ (void) topo_pgroup_create(csnode,
+ &cs_pgroup, &err);
+ inst = chan;
+ dimm_smbid = memnode_to_smbiosid(smbid,
+ CS_NODE_NAME, cs, &inst);
+ serial = chip_serial_smbios_get(mod,
+ dimm_smbid);
+ part = chip_part_smbios_get(mod,
+ dimm_smbid);
+ rev = chip_rev_smbios_get(mod, dimm_smbid);
+ label = (char *)chip_label_smbios_get(mod,
+ chnode, dimm_smbid, NULL);
+
+ (void) topo_prop_set_string(csnode, PGNAME(CS),
+ FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE,
+ serial, &err);
+ (void) topo_prop_set_string(csnode, PGNAME(CS),
+ FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE,
+ part, &err);
+ (void) topo_prop_set_string(csnode, PGNAME(CS),
+ FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE,
+ rev, &err);
+
+ /*
+ * We apply DIMM labels to chip-select nodes,
+ * FRU for chip-selects should be DIMMs, and
+ * we do not derive dimm nodes for Family 0x10
+ * so FRU fmri is NULL, but FRU Labels are set,
+ * the FRU labels point to the DIMM.
+ */
+ (void) topo_node_label_set(csnode, label, &err);
+ topo_mod_strfree(mod, label);
+ }
}
}
@@ -267,7 +349,6 @@ amd_lookup_by_mcid(topo_mod_t *mod, topo_instance_t id)
err = nvlist_unpack(buf, mcs.mcs_size, &nvl, 0);
topo_mod_free(mod, buf, mcs.mcs_size);
-
if (nvlist_lookup_uint8(nvl, MC_NVLIST_VERSTR, &ver) != 0) {
whinge(mod, NULL, "mc nvlist is not versioned\n");
nvlist_free(nvl);
@@ -339,8 +420,10 @@ amd_rank_create(topo_mod_t *mod, tnode_t *pnode, nvlist_t *dimmnvl,
}
nvlist_free(fmri);
-
- (void) topo_node_fru_set(ranknode, pfmri, 0, &err);
+ if (FM_AWARE_SMBIOS(mod))
+ (void) topo_node_fru_set(ranknode, NULL, 0, &err);
+ else
+ (void) topo_node_fru_set(ranknode, pfmri, 0, &err);
/*
* If a rank is faulted the asru is the associated
@@ -378,15 +461,20 @@ amd_rank_create(topo_mod_t *mod, tnode_t *pnode, nvlist_t *dimmnvl,
}
static int
-amd_dimm_create(topo_mod_t *mod, tnode_t *pnode, const char *name,
- nvlist_t *mc, nvlist_t *auth)
+amd_dimm_create(topo_mod_t *mod, uint16_t chip_smbid, tnode_t *pnode,
+ const char *name, nvlist_t *mc, nvlist_t *auth)
{
int i, err, nerr = 0;
+ int perr = 0;
nvpair_t *nvp;
tnode_t *dimmnode;
nvlist_t *fmri, **dimmarr = NULL;
uint64_t num;
uint_t ndimm;
+ id_t smbid;
+ const char *serial;
+ const char *part;
+ const char *rev;
if (nvlist_lookup_nvlist_array(mc, "dimmlist", &dimmarr, &ndimm) != 0) {
whinge(mod, NULL, "amd_dimm_create: dimmlist lookup failed\n");
@@ -412,6 +500,23 @@ amd_dimm_create(topo_mod_t *mod, tnode_t *pnode, const char *name,
whinge(mod, &nerr, "amd_dimm_create: mkrsrc failed\n");
continue;
}
+ if (FM_AWARE_SMBIOS(mod)) {
+ smbid = memnode_to_smbiosid(chip_smbid, DIMM_NODE_NAME,
+ i, NULL);
+ serial = chip_serial_smbios_get(mod, smbid);
+ part = chip_part_smbios_get(mod, smbid);
+ rev = chip_rev_smbios_get(mod, smbid);
+ perr += nvlist_add_string(fmri, FM_FMRI_HC_SERIAL_ID,
+ serial);
+ perr += nvlist_add_string(fmri, FM_FMRI_HC_PART,
+ part);
+ perr += nvlist_add_string(fmri, FM_FMRI_HC_REVISION,
+ rev);
+
+ if (perr != 0)
+ whinge(mod, NULL, "amd_dimm_create:"
+ "nvlist_add_string failed\n");
+ }
if ((dimmnode = topo_node_bind(mod, pnode, name, num, fmri))
== NULL) {
@@ -421,17 +526,44 @@ amd_dimm_create(topo_mod_t *mod, tnode_t *pnode, const char *name,
continue;
}
- if (topo_method_register(mod, dimmnode, dimm_methods) < 0)
- whinge(mod, &nerr, "amd_dimm_create: "
- "topo_method_register failed");
+ if (!FM_AWARE_SMBIOS(mod))
+ if (topo_method_register(mod,
+ dimmnode, dimm_methods) < 0)
+ whinge(mod, &nerr, "amd_dimm_create: "
+ "topo_method_register failed");
+
+ (void) topo_pgroup_create(dimmnode, &dimm_pgroup, &err);
+
+ if (FM_AWARE_SMBIOS(mod)) {
+ char *label;
+
+ nvlist_free(fmri);
+ (void) topo_node_resource(dimmnode,
+ &fmri, &err);
+
+ label = (char *)chip_label_smbios_get(mod,
+ pnode, smbid, NULL);
+ if (topo_node_label_set(dimmnode, label,
+ &perr) == -1)
+ topo_mod_dprintf(mod, "Failed"
+ "to set label\n");
+ topo_mod_strfree(mod, label);
+
+ (void) topo_prop_set_string(dimmnode, PGNAME(DIMM),
+ FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE,
+ serial, &err);
+ (void) topo_prop_set_string(dimmnode, PGNAME(DIMM),
+ FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE,
+ part, &err);
+ (void) topo_prop_set_string(dimmnode, PGNAME(DIMM),
+ FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE,
+ rev, &err);
+ }
(void) topo_node_asru_set(dimmnode, fmri, 0, &err);
(void) topo_node_fru_set(dimmnode, fmri, 0, &err);
-
nvlist_free(fmri);
- (void) topo_pgroup_create(dimmnode, &dimm_pgroup, &err);
-
for (nvp = nvlist_next_nvpair(dimmarr[i], NULL); nvp != NULL;
nvp = nvlist_next_nvpair(dimmarr[i], nvp)) {
if (nvpair_type(nvp) == DATA_TYPE_UINT64_ARRAY &&
@@ -587,14 +719,17 @@ amd_htconfig(topo_mod_t *mod, tnode_t *cnode, nvlist_t *htnvl)
}
void
-amd_mc_create(topo_mod_t *mod, tnode_t *pnode, const char *name, nvlist_t *auth,
- int family, int model, int stepping, int *nerrp)
+amd_mc_create(topo_mod_t *mod, uint16_t smbid, tnode_t *pnode, const char *name,
+ nvlist_t *auth, int family, int model, int stepping, int *nerrp)
{
tnode_t *mcnode;
nvlist_t *fmri;
nvpair_t *nvp;
nvlist_t *mc = NULL;
int i, err;
+ char *serial = NULL;
+ char *part = NULL;
+ char *rev = NULL;
/*
* Return with no error for anything before AMD family 0xf - we
@@ -604,6 +739,13 @@ amd_mc_create(topo_mod_t *mod, tnode_t *pnode, const char *name, nvlist_t *auth,
if (family < 0xf)
return;
+ if (FM_AWARE_SMBIOS(mod)) {
+ (void) topo_node_resource(pnode, &fmri, &err);
+ (void) nvlist_lookup_string(fmri, "serial", &serial);
+ (void) nvlist_lookup_string(fmri, "part", &part);
+ (void) nvlist_lookup_string(fmri, "revision", &rev);
+ }
+
if (mkrsrc(mod, pnode, name, 0, auth, &fmri) != 0) {
whinge(mod, nerrp, "mc_create: mkrsrc failed\n");
return;
@@ -615,6 +757,12 @@ amd_mc_create(topo_mod_t *mod, tnode_t *pnode, const char *name, nvlist_t *auth,
return;
}
+ if (FM_AWARE_SMBIOS(mod)) {
+ (void) nvlist_add_string(fmri, "serial", serial);
+ (void) nvlist_add_string(fmri, "part", part);
+ (void) nvlist_add_string(fmri, "revision", rev);
+ }
+
if ((mcnode = topo_node_bind(mod, pnode, name, 0,
fmri)) == NULL) {
nvlist_free(mc);
@@ -626,6 +774,11 @@ amd_mc_create(topo_mod_t *mod, tnode_t *pnode, const char *name, nvlist_t *auth,
if (topo_node_fru_set(mcnode, NULL, 0, &err) < 0)
whinge(mod, nerrp, "mc_create: topo_node_fru_set failed\n");
+ if (FM_AWARE_SMBIOS(mod)) {
+ if (topo_node_label_set(mcnode, NULL, &err) == -1)
+ topo_mod_dprintf(mod, "Failed to set label\n");
+ }
+
nvlist_free(fmri);
if ((mc = amd_lookup_by_mcid(mod, topo_node_instance(pnode))) == NULL) {
@@ -636,7 +789,7 @@ amd_mc_create(topo_mod_t *mod, tnode_t *pnode, const char *name, nvlist_t *auth,
* (presumably newly-released) cpu model. We fallback to
* creating a generic maximal topology.
*/
- if (amd_generic_mc_create(mod, pnode, mcnode,
+ if (amd_generic_mc_create(mod, smbid, pnode, mcnode,
family, model, stepping, auth) != 0)
whinge(mod, nerrp,
"mc_create: amd_generic_mc_create failed\n");
@@ -678,7 +831,7 @@ amd_mc_create(topo_mod_t *mod, tnode_t *pnode, const char *name, nvlist_t *auth,
if (amd_dramchan_create(mod, mcnode, CHAN_NODE_NAME, auth) != 0 ||
amd_cs_create(mod, mcnode, CS_NODE_NAME, mc, auth) != 0 ||
- amd_dimm_create(mod, mcnode, DIMM_NODE_NAME, mc, auth) != 0)
+ amd_dimm_create(mod, smbid, mcnode, DIMM_NODE_NAME, mc, auth) != 0)
whinge(mod, nerrp, "mc_create: create children failed\n");
/*
diff --git a/usr/src/lib/fm/topo/modules/i86pc/chip/chip_intel.c b/usr/src/lib/fm/topo/modules/i86pc/chip/chip_intel.c
index 09f895dfa8..ffa698fe79 100644
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip_intel.c
+++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip_intel.c
@@ -145,6 +145,9 @@ mc_add_ranks(topo_mod_t *mod, tnode_t *dnode, nvlist_t *auth, int dimm,
(void) topo_node_asru_set(rnode, fmri, TOPO_ASRU_COMPUTE, &err);
+ if (FM_AWARE_SMBIOS(mod))
+ topo_node_label_set(rnode, NULL, &err);
+
nvlist_free(fmri);
(void) topo_pgroup_create(rnode, &rank_pgroup, &err);
@@ -157,8 +160,8 @@ mc_add_ranks(topo_mod_t *mod, tnode_t *dnode, nvlist_t *auth, int dimm,
}
static void
-mc_add_dimms(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth,
- nvlist_t **nvl, uint_t ndimms, int maxdimms, int maxranks)
+mc_add_dimms(topo_mod_t *mod, uint16_t chip_smbid, tnode_t *pnode,
+ nvlist_t *auth, nvlist_t **nvl, uint_t ndimms, int maxdimms, int maxranks)
{
int i;
nvlist_t *fmri;
@@ -174,6 +177,7 @@ mc_add_dimms(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth,
char *rev = NULL;
char *label = NULL;
char *name;
+ id_t smbid;
if (topo_node_range_create(mod, pnode, DIMM, 0,
maxdimms ? maxdimms-1 : ndimms-1) < 0) {
@@ -204,6 +208,24 @@ mc_add_dimms(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth,
}
}
fmri = NULL;
+
+ if (FM_AWARE_SMBIOS(mod)) {
+ int channum;
+
+ channum = topo_node_instance(pnode);
+ smbid = memnode_to_smbiosid(chip_smbid, DIMM_NODE_NAME,
+ i, &channum);
+ if (serial == NULL)
+ serial = (char *)chip_serial_smbios_get(mod,
+ smbid);
+ if (part == NULL)
+ part = (char *)chip_part_smbios_get(mod,
+ smbid);
+ if (rev == NULL)
+ rev = (char *)chip_rev_smbios_get(mod,
+ smbid);
+ }
+
fmri = topo_mod_hcfmri(mod, pnode, FM_HC_SCHEME_VERSION,
DIMM, dimm_number, NULL, auth, part, rev, serial);
if (fmri == NULL) {
@@ -219,12 +241,11 @@ mc_add_dimms(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth,
return;
}
- if (topo_method_register(mod, dnode, dimm_methods) < 0)
- whinge(mod, NULL, "mc_add_dimms: "
- "topo_method_register failed");
+ if (!FM_AWARE_SMBIOS(mod))
+ if (topo_method_register(mod, dnode, dimm_methods) < 0)
+ whinge(mod, NULL, "mc_add_dimms: "
+ "topo_method_register failed");
- (void) topo_node_fru_set(dnode, fmri, 0, &err);
- nvlist_free(fmri);
(void) topo_pgroup_create(dnode, &dimm_pgroup, &err);
for (nvp = nvlist_next_nvpair(nvl[i], NULL); nvp != NULL;
@@ -237,8 +258,25 @@ mc_add_dimms(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth,
dnode);
}
}
- if (label)
- (void) topo_node_label_set(dnode, label, &err);
+
+ if (FM_AWARE_SMBIOS(mod)) {
+ nvlist_free(fmri);
+ (void) topo_node_resource(dnode, &fmri, &err);
+ /*
+ * We will use a full absolute parent/child label
+ */
+ label = (char *)chip_label_smbios_get(mod,
+ pnode, smbid, label);
+ }
+
+ (void) topo_node_label_set(dnode, label, &err);
+
+ if (FM_AWARE_SMBIOS(mod))
+ topo_mod_strfree(mod, label);
+
+ (void) topo_node_fru_set(dnode, fmri, 0, &err);
+ (void) topo_node_asru_set(dnode, fmri, 0, &err);
+ nvlist_free(fmri);
if (nranks) {
mc_add_ranks(mod, dnode, auth, dimm_number, ranks_nvp,
@@ -248,8 +286,8 @@ mc_add_dimms(topo_mod_t *mod, tnode_t *pnode, nvlist_t *auth,
}
static int
-mc_add_channel(topo_mod_t *mod, tnode_t *pnode, int channel, nvlist_t *auth,
- nvlist_t *nvl, int maxdimms, int maxranks)
+mc_add_channel(topo_mod_t *mod, uint16_t chip_smbid, tnode_t *pnode,
+ int channel, nvlist_t *auth, nvlist_t *nvl, int maxdimms, int maxranks)
{
tnode_t *mc_channel;
nvlist_t *fmri;
@@ -273,10 +311,14 @@ mc_add_channel(topo_mod_t *mod, tnode_t *pnode, int channel, nvlist_t *auth,
(void) topo_node_fru_set(mc_channel, NULL, 0, &err);
nvlist_free(fmri);
(void) topo_pgroup_create(mc_channel, &dimm_channel_pgroup, &err);
+
+ if (FM_AWARE_SMBIOS(mod))
+ (void) topo_node_label_set(mc_channel, NULL, &err);
+
if (nvlist_lookup_nvlist_array(nvl, MCINTEL_NVLIST_DIMMS, &dimm_nvl,
&ndimms) == 0) {
- mc_add_dimms(mod, mc_channel, auth, dimm_nvl, ndimms, maxdimms,
- maxranks);
+ mc_add_dimms(mod, chip_smbid, mc_channel, auth, dimm_nvl,
+ ndimms, maxdimms, maxranks);
}
for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL;
nvp = nvlist_next_nvpair(nvl, nvp)) {
@@ -286,12 +328,13 @@ mc_add_channel(topo_mod_t *mod, tnode_t *pnode, int channel, nvlist_t *auth,
mc_channel);
}
}
+
return (0);
}
static int
-mc_nb_create(topo_mod_t *mod, tnode_t *pnode, const char *name, nvlist_t *auth,
- nvlist_t *nvl)
+mc_nb_create(topo_mod_t *mod, uint16_t chip_smbid, tnode_t *pnode,
+ const char *name, nvlist_t *auth, nvlist_t *nvl)
{
int err;
int i, j;
@@ -355,6 +398,9 @@ mc_nb_create(topo_mod_t *mod, tnode_t *pnode, const char *name, nvlist_t *auth,
nvlist_free(fmri);
(void) topo_pgroup_create(mcnode, &mc_pgroup, &err);
+ if (FM_AWARE_SMBIOS(mod))
+ (void) topo_node_label_set(mcnode, NULL, &err);
+
if (topo_node_range_create(mod, mcnode, DRAMCHANNEL, channel,
channel + nchannels - 1) < 0) {
whinge(mod, NULL,
@@ -362,8 +408,9 @@ mc_nb_create(topo_mod_t *mod, tnode_t *pnode, const char *name, nvlist_t *auth,
return (-1);
}
for (j = 0; j < nchannels; j++) {
- if (mc_add_channel(mod, mcnode, channel, auth,
- channel_nvl[channel], maxdimms, maxranks) < 0) {
+ if (mc_add_channel(mod, chip_smbid, mcnode, channel,
+ auth, channel_nvl[channel], maxdimms,
+ maxranks) < 0) {
return (-1);
}
channel++;
@@ -387,8 +434,8 @@ mc_nb_create(topo_mod_t *mod, tnode_t *pnode, const char *name, nvlist_t *auth,
}
int
-mc_node_create(topo_mod_t *mod, tnode_t *pnode, const char *name,
- nvlist_t *auth)
+mc_node_create(topo_mod_t *mod, uint16_t chip_smbid, tnode_t *pnode,
+ const char *name, nvlist_t *auth)
{
mc_snapshot_info_t mcs;
void *buf = NULL;
@@ -421,23 +468,23 @@ mc_node_create(topo_mod_t *mod, tnode_t *pnode, const char *name,
return (NULL);
}
- rc = mc_nb_create(mod, pnode, name, auth, nvl);
+ rc = mc_nb_create(mod, chip_smbid, pnode, name, auth, nvl);
nvlist_free(nvl);
return (rc);
}
void
-onchip_mc_create(topo_mod_t *mod, tnode_t *pnode, const char *name,
- nvlist_t *auth)
+onchip_mc_create(topo_mod_t *mod, uint16_t chip_smbid, tnode_t *pnode,
+ const char *name, nvlist_t *auth)
{
if (mc_onchip(topo_node_instance(pnode)))
- (void) mc_node_create(mod, pnode, name, auth);
+ (void) mc_node_create(mod, chip_smbid, pnode, name, auth);
}
int
mc_offchip_create(topo_mod_t *mod, tnode_t *pnode, const char *name,
nvlist_t *auth)
{
- return (mc_node_create(mod, pnode, name, auth));
+ return (mc_node_create(mod, IGNORE_ID, pnode, name, auth));
}
diff --git a/usr/src/lib/fm/topo/modules/i86pc/chip/chip_smbios.c b/usr/src/lib/fm/topo/modules/i86pc/chip/chip_smbios.c
new file mode 100644
index 0000000000..a4e0b1505c
--- /dev/null
+++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip_smbios.c
@@ -0,0 +1,590 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <unistd.h>
+#include <ctype.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <sys/devfm.h>
+#include <libnvpair.h>
+#include <sys/smbios.h>
+#include <fm/topo_mod.h>
+#include <sys/fm/protocol.h>
+#include <sys/smbios_impl.h>
+
+#include "chip.h"
+
+#define CPU_SLOTS 64
+#define DIMM_SLOTS 512
+#define MC_INSTANCES 128
+
+#define MAXNAMELEN 256
+#define LABEL 1
+
+#define SKIP_CS 9999
+
+
+typedef struct cpu_smbios {
+ id_t cpu_id;
+ uint8_t status;
+ uint8_t fru;
+}csmb_t;
+
+typedef struct dimm_smbios {
+ id_t dimm_id;
+ id_t extdimm_id;
+ const char *bankloc;
+}dsmb_t;
+
+typedef struct mct_smbios {
+ id_t extmct_id;
+ id_t mct_id;
+ id_t p_id;
+}msmb_t;
+
+csmb_t cpusmb[CPU_SLOTS];
+dsmb_t dimmsmb[DIMM_SLOTS];
+msmb_t mctsmb[MC_INSTANCES];
+
+static int ncpu_ids = 0;
+static int bb_count = 0;
+static int ndimm_ids, nmct_ids = 0;
+
+static smbios_hdl_t *shp = NULL;
+static int fill_chip_smbios = 0;
+typedef int smbios_rec_f(topo_mod_t *, const smbios_struct_t *);
+
+static smbios_struct_t *
+smb_export(const smb_struct_t *stp, smbios_struct_t *sp)
+{
+ const smb_header_t *hdr;
+
+ if (stp == NULL)
+ return (NULL);
+
+ hdr = stp->smbst_hdr;
+ sp->smbstr_id = hdr->smbh_hdl;
+ sp->smbstr_type = hdr->smbh_type;
+ sp->smbstr_data = hdr;
+ sp->smbstr_size = (size_t)(stp->smbst_end - (uchar_t *)hdr);
+
+ return (sp);
+}
+
+static int
+extdimmslot_to_dimmslot(id_t chip_smbid, int channum, int csnum)
+{
+ smbios_memdevice_ext_t emd;
+ smbios_memdevice_t md;
+ int i, j, k;
+ int match = 0;
+
+ if (chip_smbid == IGNORE_ID && bb_count <= 1 && nmct_ids <= 1) {
+ for (i = 0; i < ndimm_ids; i++) {
+ (void) smbios_info_extmemdevice(shp,
+ dimmsmb[i].extdimm_id, &emd);
+ if (emd.smbmdeve_drch == channum) {
+ if (csnum == SKIP_CS)
+ return (emd.smbmdeve_md);
+ for (k = 0; k < emd.smbmdeve_ncs; k++)
+ if (emd.smbmdeve_cs[k] == csnum)
+ return (emd.smbmdeve_md);
+ }
+ }
+ }
+
+ for (j = 0; j < nmct_ids; j++) {
+ if (mctsmb[j].p_id == chip_smbid) {
+ for (i = 0; i < ndimm_ids; i++) {
+ (void) smbios_info_extmemdevice(shp,
+ dimmsmb[i].extdimm_id, &emd);
+ (void) smbios_info_memdevice(shp,
+ emd.smbmdeve_md, &md);
+ if (md.smbmd_array == mctsmb[j].mct_id &&
+ emd.smbmdeve_drch == channum) {
+ match = 1;
+ break;
+ }
+ }
+ if (match) {
+ if (csnum == SKIP_CS)
+ return (emd.smbmdeve_md);
+ for (k = 0; k < emd.smbmdeve_ncs; k++)
+ if (emd.smbmdeve_cs[k] == csnum)
+ return (emd.smbmdeve_md);
+ }
+ }
+ }
+
+ return (-1);
+}
+
+id_t
+memnode_to_smbiosid(uint16_t chip_smbid, const char *name, uint64_t nodeid,
+ void *data)
+{
+
+ if (strcmp(name, CS_NODE_NAME) == 0) {
+ int channum, csnum;
+ id_t dimmslot = -1;
+
+ if (data == NULL)
+ return (-1);
+ channum = *(int *)data;
+ csnum = nodeid;
+ /*
+ * Set the DIMM Slot label to the Chip Select Node
+ * Set the "data" to carry the DIMM instance
+ */
+ dimmslot = extdimmslot_to_dimmslot(chip_smbid, channum, csnum);
+ if (dimmslot != -1 && dimmsmb[0].dimm_id != 0)
+ *((id_t *)data) = dimmslot % (dimmsmb[0].dimm_id);
+ else
+ *((id_t *)data) = -1;
+
+ return (dimmslot);
+
+ } else if (strcmp(name, DIMM_NODE_NAME) == 0) {
+ static int dimmnum = 0;
+
+ /*
+ * On certain Intel Chips, topology does not have
+ * chip-select nodes, it has the below layout
+ * chip/memory-controller/dram-channel/dimm
+ * so we check if channel instance is passed
+ * and get the SMBIOS ID based on the channel
+ */
+ if (data != NULL) {
+ int channum;
+ id_t dimmslot = -1;
+
+ channum = *(int *)data;
+ dimmslot = extdimmslot_to_dimmslot(chip_smbid,
+ channum, SKIP_CS);
+
+ return (dimmslot);
+ }
+ dimmnum = nodeid;
+ return (dimmsmb[dimmnum].dimm_id);
+ }
+
+ return (-1);
+}
+
+
+int
+chip_get_smbstruct(topo_mod_t *mod, const smbios_struct_t *sp)
+{
+ smbios_processor_t p;
+ smbios_memdevice_t md;
+ smbios_processor_ext_t extp;
+ smbios_memarray_ext_t extma;
+
+ /*
+ * We expect that the first SUN_OEM_EXT_XXX
+ * that comes after a SMB_TYPE_XXX correspond
+ * to each other in the SMBIOS ordering of the
+ * records. And SUN_OEM_EXT_XXX always comes
+ * after its SMB_TYPE_XXX record.
+ */
+ switch (sp->smbstr_type) {
+ case SMB_TYPE_BASEBOARD:
+ bb_count++;
+ break;
+ case SMB_TYPE_MEMARRAY:
+ mctsmb[nmct_ids].mct_id = sp->smbstr_id;
+ break;
+ case SUN_OEM_EXT_MEMARRAY:
+ mctsmb[nmct_ids].extmct_id = sp->smbstr_id;
+ if (shp != NULL) {
+ if (smbios_info_extmemarray(shp,
+ sp->smbstr_id, &extma) != 0) {
+ topo_mod_dprintf(mod, "chip_get_smbstruct : "
+ "smbios_info_extmemarray()"
+ "failed\n");
+ return (-1);
+ }
+ } else
+ return (-1);
+ if (extma.smbmae_ma == mctsmb[nmct_ids].mct_id)
+ mctsmb[nmct_ids].p_id = extma.smbmae_comp;
+ else
+ return (-1);
+
+ nmct_ids++;
+ break;
+ case SMB_TYPE_MEMDEVICE:
+ dimmsmb[ndimm_ids].dimm_id = sp->smbstr_id;
+ if (shp != NULL) {
+ if (smbios_info_memdevice(shp,
+ sp->smbstr_id, &md) != 0)
+ return (-1);
+ } else
+ return (-1);
+ dimmsmb[ndimm_ids].bankloc = md.smbmd_bloc;
+ break;
+ /*
+ * Every SMB_TYPE_MEMDEVICE SHOULD have a
+ * corresponding SUN_OEM_EXT_MEMDEVICE
+ */
+ case SUN_OEM_EXT_MEMDEVICE:
+ dimmsmb[ndimm_ids++].extdimm_id = sp->smbstr_id;
+ break;
+ case SMB_TYPE_PROCESSOR:
+ cpusmb[ncpu_ids].cpu_id = sp->smbstr_id;
+ if (shp != NULL) {
+ if (smbios_info_processor(shp,
+ sp->smbstr_id, &p) != 0) {
+ topo_mod_dprintf(mod, "chip_get_smbstruct : "
+ "smbios_info_processor()"
+ "failed\n");
+ return (-1);
+ }
+ }
+ cpusmb[ncpu_ids].status = p.smbp_status;
+ break;
+ /*
+ * Every SMB_TYPE_PROCESSOR SHOULD have a
+ * corresponding SUN_OEM_EXT_PROCESSOR
+ */
+ case SUN_OEM_EXT_PROCESSOR:
+ if (smbios_info_extprocessor(shp,
+ sp->smbstr_id, &extp) != 0) {
+ topo_mod_dprintf(mod, "chip_get_smbstruct : "
+ "smbios_info_extprocessor()"
+ "failed\n");
+ return (-1);
+ }
+ cpusmb[ncpu_ids].fru = extp.smbpe_fru;
+ ncpu_ids++;
+ break;
+ }
+ return (0);
+}
+
+static int
+chip_smbios_iterate(topo_mod_t *mod, smbios_rec_f *func_iter)
+{
+ const smb_struct_t *sp = shp->sh_structs;
+ smbios_struct_t s;
+ int i, rv = 0;
+
+ for (i = 0; i < shp->sh_nstructs; i++, sp++) {
+ if (sp->smbst_hdr->smbh_type != SMB_TYPE_INACTIVE &&
+ (rv = func_iter(mod, smb_export(sp, &s))) != 0)
+ break;
+ }
+ return (rv);
+}
+
+int
+init_chip_smbios(topo_mod_t *mod)
+{
+ if (shp == NULL) {
+ if ((shp = topo_mod_smbios(mod)) == NULL) {
+ whinge(mod, NULL, "init_chip_smbios: smbios "
+ "handle get failed\n");
+ return (-1);
+ }
+ }
+
+ if (!fill_chip_smbios) {
+ if (chip_smbios_iterate(mod, chip_get_smbstruct) == -1)
+ return (-1);
+ fill_chip_smbios = 1;
+ }
+
+ return (0);
+}
+
+int
+chip_status_smbios_get(topo_mod_t *mod, id_t smb_id)
+{
+ /*
+ * Type-4 Socket Status bit definitions per SMBIOS Version 2.6
+ *
+ * STATUS
+ * CPU Socket Populated
+ * CPU Socket Unpopulated
+ * Populated : Enabled
+ * Populated : Disabled by BIOS (Setup)
+ * Populated : Disabled by BIOS (Error)
+ * Populated : Idle
+ */
+ uint8_t enabled = 0x01;
+ uint8_t populated = 0x40;
+
+ for (int i = 0; i < ncpu_ids; i++) {
+ if (smb_id == cpusmb[i].cpu_id) {
+ if (cpusmb[i].status == (enabled | populated))
+ return (1);
+ else
+ return (0);
+ }
+ }
+
+ topo_mod_dprintf(mod, "topo_status_smbios_get() failed"
+ " considering that Type 4 ID : %d is disabled", smb_id);
+ return (0);
+}
+
+int
+chip_fru_smbios_get(topo_mod_t *mod, id_t smb_id)
+{
+ /*
+ * smbios_processor_ext_t->smbpe_fru : if set to 1
+ * processor is a FRU
+ */
+ uint8_t fru = 1;
+
+ for (int i = 0; i < ncpu_ids; i++) {
+ if (smb_id == cpusmb[i].cpu_id) {
+ if (cpusmb[i].fru == fru)
+ return (1);
+ else
+ return (0);
+ }
+ }
+
+ topo_mod_dprintf(mod, "topo_fru_smbios_get() failed"
+ " considering that Type 4 ID : %d is not a FRU", smb_id);
+ return (0);
+}
+
+/*
+ * This could be defined as topo_mod_strlen()
+ */
+size_t
+chip_strlen(const char *str)
+{
+ int len = 0;
+
+ if (str != NULL)
+ len = strlen(str);
+
+ return (len);
+}
+
+/*
+ * We clean Serials, Revisions, Part No. strings, to
+ * avoid getting lost when fmd synthesizes these
+ * strings. :, =, /, ' ' characters are replaced
+ * with character '-' any non-printable characters
+ * as seen with !isprint() is also replaced with '-'
+ * Labels are checked only for non-printable characters.
+ */
+static const char *
+chip_cleanup_smbios_str(topo_mod_t *mod, const char *begin, int str_type)
+{
+ char buf[MAXNAMELEN];
+ const char *end, *cp;
+ char *pp;
+ char c;
+ int i;
+
+ end = begin + strlen(begin);
+
+ while (begin < end && isspace(*begin))
+ begin++;
+ while (begin < end && isspace(*(end - 1)))
+ end--;
+
+ if (begin >= end)
+ return (NULL);
+
+ cp = begin;
+ for (i = 0; i < MAXNAMELEN - 1; i++) {
+ if (cp >= end)
+ break;
+ c = *cp;
+ if (str_type == LABEL) {
+ if (!isprint(c))
+ buf[i] = '-';
+ else
+ buf[i] = c;
+ } else {
+ if (c == ':' || c == '=' || c == '/' ||
+ isspace(c) || !isprint(c))
+ buf[i] = '-';
+ else
+ buf[i] = c;
+ }
+ cp++;
+ }
+ buf[i] = 0;
+
+ pp = topo_mod_strdup(mod, buf);
+
+ if (str_type == LABEL)
+ topo_mod_strfree(mod, (char *)begin);
+
+ return (pp);
+}
+
+const char *
+chip_label_smbios_get(topo_mod_t *mod, tnode_t *pnode, id_t smb_id,
+ char *ksmbios_label)
+{
+ smbios_info_t c;
+ char *label = NULL;
+ char *buf = NULL;
+ const char *lsmbios_label = NULL;
+ int bufsz = 0;
+ char *delim = NULL, *blank = " ";
+ const char *dimm_bank = NULL;
+ const char *clean_label = NULL;
+ int err;
+
+ if (shp != NULL) {
+ /*
+ * Get Parent FRU's label
+ */
+ if (topo_prop_get_string(pnode, TOPO_PGROUP_PROTOCOL,
+ TOPO_PROP_LABEL, &label, &err) == -1)
+ topo_mod_dprintf(mod, "Failed to get"
+ " Label of Parent Node error : %d\n", err);
+
+ if (label != NULL)
+ label = (char *)chip_cleanup_smbios_str(mod,
+ label, LABEL);
+
+ /*
+ * On Intel the driver gets the label from ksmbios
+ * so we check if we already have it, if not we
+ * get it from libsmbios
+ */
+ if (ksmbios_label == NULL && smb_id != -1) {
+ if (smbios_info_common(shp, smb_id, &c) != SMB_ERR) {
+ for (int i = 0; i < ndimm_ids; i++) {
+ if (smb_id == dimmsmb[i].dimm_id) {
+ dimm_bank = dimmsmb[i].bankloc;
+ break;
+ }
+ }
+ if (dimm_bank != NULL) {
+ bufsz += chip_strlen(blank) +
+ chip_strlen(dimm_bank);
+ }
+ lsmbios_label = c.smbi_location;
+ }
+ } else
+ lsmbios_label = ksmbios_label;
+
+ if (label != NULL && lsmbios_label != NULL)
+ delim = "/";
+
+ bufsz += chip_strlen(label) + chip_strlen(delim) +
+ chip_strlen(lsmbios_label) + 1;
+
+ buf = topo_mod_alloc(mod, bufsz);
+
+ if (buf != NULL) {
+ if (label != NULL) {
+ (void) strlcpy(buf, label, bufsz);
+ if (lsmbios_label != NULL) {
+ (void) strlcat(buf, delim, bufsz);
+ /*
+ * If we are working on a DIMM
+ * and we are deriving from libsmbios
+ * smbi_location has the Device Locator.
+ * add the Device Locator
+ * add Bank Locator latter
+ */
+ (void) strlcat(buf, lsmbios_label,
+ bufsz);
+ }
+ } else if (lsmbios_label != NULL)
+ (void) strlcpy(buf, lsmbios_label,
+ bufsz);
+
+ if (dimm_bank != NULL) {
+ (void) strlcat(buf, blank, bufsz);
+ (void) strlcat(buf, dimm_bank, bufsz);
+ }
+ }
+
+ clean_label = chip_cleanup_smbios_str(mod, buf, LABEL);
+ topo_mod_strfree(mod, label);
+
+ return (clean_label);
+ }
+
+ topo_mod_dprintf(mod, "Failed to get Label\n");
+ return (NULL);
+}
+
+
+const char *
+chip_serial_smbios_get(topo_mod_t *mod, id_t smb_id)
+{
+ smbios_info_t c;
+ const char *clean_serial = NULL;
+
+ if (shp != NULL && smb_id != -1)
+ if (smbios_info_common(shp, smb_id, &c) != SMB_ERR) {
+ clean_serial = chip_cleanup_smbios_str(mod,
+ c.smbi_serial, 0);
+ return (clean_serial);
+ }
+
+ topo_mod_dprintf(mod, "Failed to get Serial \n");
+ return (NULL);
+}
+
+
+const char *
+chip_part_smbios_get(topo_mod_t *mod, id_t smb_id)
+{
+ smbios_info_t c;
+ const char *clean_part = NULL;
+
+ if (shp != NULL && smb_id != -1)
+ if (smbios_info_common(shp, smb_id, &c) != SMB_ERR) {
+ clean_part = chip_cleanup_smbios_str(mod,
+ c.smbi_part, 0);
+ return (clean_part);
+ }
+
+ topo_mod_dprintf(mod, "Failed to get Part\n");
+ return (NULL);
+}
+
+const char *
+chip_rev_smbios_get(topo_mod_t *mod, id_t smb_id)
+{
+ smbios_info_t c;
+ const char *clean_rev = NULL;
+
+ if (shp != NULL && smb_id != -1)
+ if (smbios_info_common(shp, smb_id, &c) != SMB_ERR) {
+ clean_rev = chip_cleanup_smbios_str(mod,
+ c.smbi_version, 0);
+ return (clean_rev);
+ }
+
+ topo_mod_dprintf(mod, "Failed to get Revision\n");
+ return (NULL);
+}
diff --git a/usr/src/lib/fm/topo/modules/i86pc/x86pi/Makefile b/usr/src/lib/fm/topo/modules/i86pc/x86pi/Makefile
new file mode 100644
index 0000000000..1f6b0985e5
--- /dev/null
+++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/Makefile
@@ -0,0 +1,52 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+MODULE = x86pi
+ARCH = i86pc
+CLASS = arch
+
+TOPODIR = ../../../libtopo/common
+
+UTILDIR = ../../common/pcibus
+BRDIR = ../../common/hostbridge
+UTILSRCS = did.c did_hash.c did_props.c
+X86PISRCS = x86pi.c x86pi_bboard.c x86pi_chassis.c \
+ x86pi_generic.c x86pi_hostbridge.c x86pi_subr.c
+MODULESRCS = $(X86PISRCS) $(UTILSRCS)
+
+include ../../Makefile.plugin
+
+LDLIBS += -lsmbios -ldevinfo -luutil
+
+CPPFLAGS += -I. -I$(ROOT)/usr/platform/i86pc/include -I$(TOPODIR)
+CPPFLAGS += -I$(UTILDIR) -I$(BRDIR)
+
+%.o: $(UTILDIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(CTFCONVERT_O)
+
+%.ln: $(UTILDIR)/%.c
+ $(LINT.c) -c $<
diff --git a/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi.c b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi.c
new file mode 100644
index 0000000000..bc2e483064
--- /dev/null
+++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi.c
@@ -0,0 +1,462 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * x86 Generic FMA Topology Enumerator
+ */
+
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <strings.h>
+#include <sys/fcntl.h>
+#include <fm/topo_mod.h>
+#include <fm/topo_hc.h>
+#include <sys/systeminfo.h>
+#include <sys/smbios.h>
+#include <sys/smbios_impl.h>
+#include <sys/fm/protocol.h>
+#include <x86pi_impl.h>
+
+
+static int x86pi_enum_start(topo_mod_t *, x86pi_enum_t *);
+static int x86pi_enum_gentopo(topo_mod_t *, tnode_t *, smbios_hdl_t *);
+
+/*
+ * Entry point called by libtopo when enumeration is required
+ */
+static topo_enum_f x86pi_enum; /* libtopo enumeration entry point */
+
+/*
+ * Declare the operations vector and information structure used during
+ * module registration
+ */
+static topo_modops_t x86pi_ops =
+ { x86pi_enum, NULL };
+
+static topo_modinfo_t x86pi_modinfo =
+ { X86PI_DESC, X86PI_SCHEME, X86PI_VERSION, &x86pi_ops };
+
+/*
+ * Used to pass SMBIOS' FM compatibility to the
+ * chip enumerator
+ */
+int x86pi_smbios = 0;
+
+/*
+ * Called by libtopo when the topo module is loaded.
+ */
+int
+_topo_init(topo_mod_t *mod, topo_version_t version)
+{
+ int result;
+ char isa[MAXNAMELEN];
+
+ if (getenv("TOPOX86PIDBG") != NULL) {
+ /* Debugging is requested for this module */
+ topo_mod_setdebug(mod);
+ }
+ topo_mod_dprintf(mod, "module initializing.\n");
+
+ if (version != TOPO_VERSION) {
+ topo_mod_seterrno(mod, EMOD_VER_NEW);
+ topo_mod_dprintf(mod, "incompatible topo version %d\n",
+ version);
+ return (-1);
+ }
+
+ /* Verify that this is a i86pc architecture machine */
+ (void) sysinfo(SI_MACHINE, isa, MAXNAMELEN);
+ if (strncmp(isa, "i86pc", MAXNAMELEN) != 0) {
+ topo_mod_dprintf(mod, "not i86pc architecture: %s\n", isa);
+ return (-1);
+ }
+
+ result = topo_mod_register(mod, &x86pi_modinfo, TOPO_VERSION);
+ if (result < 0) {
+ topo_mod_dprintf(mod, "registration failed: %s\n",
+ topo_mod_errmsg(mod));
+ /* module errno already set */
+ return (-1);
+ }
+ topo_mod_dprintf(mod, "module ready.\n");
+ return (0);
+}
+
+
+/*
+ * Clean up any data used by the module before it is unloaded.
+ */
+void
+_topo_fini(topo_mod_t *mod)
+{
+ topo_mod_dprintf(mod, "module finishing.\n");
+
+ x86pi_hbr_enum_fini(mod);
+
+ /* Unregister from libtopo */
+ topo_mod_unregister(mod);
+}
+
+
+/*
+ * Enumeration entry point for the x86 Generic topology enumerator
+ */
+/* ARGSUSED */
+static int
+x86pi_enum(topo_mod_t *mod, tnode_t *t_parent, const char *name,
+ topo_instance_t min, topo_instance_t max, void *pi_private, void *data)
+{
+ int result;
+ hrtime_t starttime;
+ x86pi_enum_t x86pi;
+
+ /* Begin enumeration */
+ starttime = gethrtime();
+ topo_mod_dprintf(mod, "enumeration starting.\n");
+
+ /*
+ * Let's do some enumeration.
+ */
+ bzero(&x86pi, sizeof (x86pi_enum_t));
+ x86pi.t_parent = t_parent;
+ result = x86pi_enum_start(mod, &x86pi);
+ if (result != 0) {
+ topo_mod_dprintf(mod, "Enumeration failed.\n");
+ return (-1);
+ }
+
+ /* Complete enumeration */
+ topo_mod_dprintf(mod, "enumeration complete in %lld ms.\n",
+ ((gethrtime() - starttime)/MICROSEC));
+
+ /* All done */
+ return (result);
+}
+
+static int
+x86pi_enum_start(topo_mod_t *mod, x86pi_enum_t *x86pi)
+{
+ int rv;
+ int complvl = 0;
+ smbios_hdl_t *shp;
+ char *f = "x86pi_enum_start";
+
+ /*
+ * Verify BIOS compliance.
+ */
+ shp = x86pi_smb_open(mod);
+ if (shp == NULL) {
+ topo_mod_dprintf(mod, "%s: failed to open SMBIOS\n", f);
+ complvl = X86PI_NONE;
+ } else {
+ complvl = x86pi_check_comp(mod, shp);
+ }
+
+ topo_mod_dprintf(mod, "%s: SMBIOS x86pi compliance: %s\n", f,
+ complvl == X86PI_FULL ? "FULL" : "NONE");
+
+ if (complvl == X86PI_NONE) {
+ /* fall back to legacy enumeration */
+ topo_mod_dprintf(mod,
+ "%s: Calling legacy enumeration\n", f);
+
+ return (topo_mod_enummap(mod, x86pi->t_parent,
+ "i86pc-legacy", FM_FMRI_SCHEME_HC));
+ }
+
+ x86pi->priv = (void *)shp;
+ x86pi_smbios = complvl;
+
+ if (x86pi_hbr_enum_init(mod) < 0) {
+ topo_mod_dprintf(mod, "%s: x86pi_hbr_enum_init() failed.\n", f);
+ return (-1);
+ }
+
+ /*
+ * Create the topology.
+ */
+ fac_done = 0;
+ rv = x86pi_enum_gentopo(mod, x86pi->t_parent, shp);
+ if (rv != 0) {
+ return (-1);
+ }
+ x86pi->mod = mod;
+
+ if (fac_done == 0) {
+ (void) topo_mod_enummap(mod, x86pi->t_parent, "chassis",
+ FM_FMRI_SCHEME_HC);
+ (void) topo_mod_enummap(mod, x86pi->t_parent, "fan",
+ FM_FMRI_SCHEME_HC);
+ (void) topo_mod_enummap(mod, x86pi->t_parent, "psu",
+ FM_FMRI_SCHEME_HC);
+ }
+
+ /* All done */
+ topo_mod_dprintf(mod, "%s: done.\n", f);
+ return (rv);
+}
+
+/*
+ * Create the i86pc topology
+ *
+ * If either Type 2 or Type 3 structures have contained elements/handles,
+ * walk them creating the topo.
+ *
+ * If there are no contained elements/handles, build this topo:
+ *
+ * Main Chassis
+ * Motherboard
+ * CMP Chip/Core/Strands
+ * Memory Controllers/Memory Devices (DIMMs)
+ * PCIE HostBrige
+ * PCIE Root Complex
+ *
+ */
+static int
+x86pi_enum_gentopo(topo_mod_t *mod, tnode_t *t_parent, smbios_hdl_t *shp)
+{
+ int rv;
+ int nch, nbb, ncmp, i;
+ int ch_smbid, bb_smbid;
+ tnode_t *chassis_node = NULL;
+ tnode_t *basebd_node = NULL;
+ smbs_cnt_t *smbc;
+ tnode_t *motherchassis_node = NULL;
+ tnode_t *pnode = NULL;
+ id_t psmbid;
+ int notvisited;
+ int bb_count, ch_count;
+ int min, max;
+ int ch_inst = 0;
+ topo_instance_t hbri = 0, rci = 0;
+ smbios_pciexrc_t hbr;
+ char *f = "x86pi_enum_gentopo";
+
+ if (t_parent == NULL) {
+ topo_mod_dprintf(mod, "%s: NULL parent\n", f);
+ return (-1);
+ }
+
+ /*
+ * "Chassis'"
+ */
+ /* Type 3 structs */
+ stypes[SMB_TYPE_CHASSIS].type = SMB_TYPE_CHASSIS;
+ x86pi_smb_strcnt(shp, &stypes[SMB_TYPE_CHASSIS]);
+
+ ch_count = stypes[SMB_TYPE_CHASSIS].count;
+
+ for (nch = 0; nch < ch_count; nch++) {
+ topo_mod_dprintf(mod, "%s: found %d chassis\n", f,
+ stypes[SMB_TYPE_CHASSIS].count);
+
+ ch_smbid = stypes[SMB_TYPE_CHASSIS].ids[nch].id;
+
+ /*
+ * Expect SMBIOS to set the first Chassis Structure to be the
+ * parent/mother of all chassis
+ */
+ if (nch == 0)
+ motherchassis_node = chassis_node =
+ x86pi_gen_chassis(mod, t_parent, shp,
+ ch_smbid, ch_inst++);
+ else {
+ if (motherchassis_node != NULL)
+ chassis_node = x86pi_gen_chassis(mod,
+ motherchassis_node, shp,
+ ch_smbid, ch_inst++);
+ else
+ chassis_node = x86pi_gen_chassis(mod,
+ t_parent, shp, ch_smbid, ch_inst++);
+ }
+
+ if (chassis_node == NULL) {
+ topo_mod_dprintf(mod,
+ "%s: Failed to create chassis %d\n", f, nch);
+ continue;
+ }
+ stypes[SMB_TYPE_CHASSIS].ids[nch].node = chassis_node;
+ }
+
+ /*
+ * "Base Board"
+ */
+ /* Type 2 structs */
+ stypes[SMB_TYPE_BASEBOARD].type = SMB_TYPE_BASEBOARD;
+ x86pi_smb_strcnt(shp, &stypes[SMB_TYPE_BASEBOARD]);
+ bb_count = notvisited = stypes[SMB_TYPE_BASEBOARD].count;
+
+ for (nbb = 0; nbb < bb_count; nbb++) {
+ stypes[SMB_TYPE_BASEBOARD].ids[nbb].visited = 0;
+ stypes[SMB_TYPE_BASEBOARD].ids[nbb].con_by_id = 0;
+ stypes[SMB_TYPE_BASEBOARD].ids[nbb].node = NULL;
+ }
+ (void) x86pi_bb_contains(mod, shp);
+
+ min = 0;
+ nbb = 0;
+ do {
+ /*
+ * We have reached end of the array due to the
+ * parent-child relationship, without visiting all
+ * baseboards! so re-iterate..
+ * (or)
+ * All baseboards are visited and their contained
+ * processors are enumerated
+ * (and/or)
+ * More baseboards pending a visit
+ */
+ if (nbb > bb_count && notvisited)
+ nbb = 0;
+ else if (nbb > bb_count && !notvisited)
+ break;
+ if (stypes[SMB_TYPE_BASEBOARD].ids[nbb].visited ==
+ X86PI_VISITED) {
+ nbb++;
+ continue;
+ }
+
+ /*
+ * Get the Top-most Parent Baseboard, irrespective
+ * of its index in the array of Type-2s
+ * If this Baseboard has no Baseboard parents
+ * place it under the chassis that contains it
+ */
+ bb_smbid = x86pi_bb_topparent(shp, nbb, &pnode, &psmbid);
+ if (bb_smbid == -1 || pnode == NULL) {
+ topo_mod_dprintf(mod,
+ "Failed to get BaseBoard node (%d): parent\n",
+ nbb);
+ return (-1);
+ }
+
+ if (stypes[SMB_TYPE_BASEBOARD].ids[nbb].id != bb_smbid) {
+ for (int i = 0; i < bb_count; i++) {
+ if (bb_smbid ==
+ stypes[SMB_TYPE_BASEBOARD].ids[i].id) {
+ stypes[SMB_TYPE_BASEBOARD].ids[i].\
+ visited = 1;
+ notvisited--;
+ break;
+ }
+ }
+ } else {
+ stypes[SMB_TYPE_BASEBOARD].ids[nbb].visited = 1;
+ notvisited--;
+ }
+
+ basebd_node = x86pi_gen_bboard(mod, pnode, shp,
+ bb_smbid, nbb, psmbid);
+ if (basebd_node == NULL) {
+ topo_mod_dprintf(mod,
+ "Failed to create BaseBoard node (%d)\n", nbb);
+ nbb++;
+ continue;
+ }
+
+ stypes[SMB_TYPE_BASEBOARD].ids[nbb].node = basebd_node;
+ /*
+ * Look for contained handles here and if there are
+ * make sure the chip handle below is part of it.
+ */
+ ncmp = x86pi_bb_getchips(mod, shp, nbb, bb_count);
+ if (ncmp > 0) {
+ max = min + ncmp - 1;
+ /* make sure the chip enum is loaded */
+ topo_mod_dprintf(mod, "%s: loading chip enum\n", f);
+
+ if (topo_mod_load(mod, CHIP, TOPO_VERSION) == NULL) {
+ topo_mod_dprintf(mod,
+ "%s: Failed to load %s module: %s\n", f,
+ CHIP, topo_strerror(topo_mod_errno(mod)));
+ } else {
+ /* create node range */
+ topo_mod_dprintf(mod,
+ "%s: chip range %d to %d\n",
+ f, min, max);
+ rv = topo_node_range_create(mod, basebd_node,
+ CHIP, min, max);
+ if (rv != 0) {
+ topo_mod_dprintf(mod,
+ "%s: Failed to create node range: "
+ "%s\n", f,
+ topo_strerror(topo_mod_errno(mod)));
+ } else {
+ /* call the chip enumerator */
+ topo_mod_dprintf(mod, "%s: calling"
+ " chip enum\n", f);
+ rv =
+ topo_mod_enumerate(mod, basebd_node,
+ CHIP, CHIP, min, max,
+ &x86pi_smbios);
+ min = max + 1;
+ if (rv != 0)
+ topo_mod_dprintf(mod, "%s:%s"
+ "enumeration failed: \n",
+ f, CHIP);
+ }
+ }
+ }
+
+ /* enumerate the hostbridge node */
+ rv = topo_node_range_create(mod, basebd_node, HOSTBRIDGE,
+ 0, 255);
+ if (rv != 0) {
+ topo_mod_dprintf(mod,
+ "%s: Failed to create %s range: %s\n",
+ f, HOSTBRIDGE, topo_mod_errmsg(mod));
+ continue;
+ }
+
+ smbc = &stypes[SUN_OEM_PCIEXRC];
+ smbc->type = SUN_OEM_PCIEXRC;
+ x86pi_smb_strcnt(shp, smbc);
+ for (i = 0; i < smbc->count; i++) {
+ if (smbios_info_pciexrc(shp, smbc->ids[i].id,
+ &hbr) != 0) {
+ topo_mod_dprintf(mod,
+ "smbios_info_pciexrc failed: "
+ "id = %d\n", (int)smbc->ids[i].id);
+ continue;
+ }
+
+ if (hbr.smbpcie_bb != bb_smbid)
+ continue;
+ rv = x86pi_gen_hbr(mod, basebd_node, shp,
+ smbc->ids[i].id, hbri, &rci);
+ if (rv != 0)
+ topo_mod_dprintf(mod,
+ "couldn't create hostbridge=%d\n", hbri);
+ hbri++;
+ }
+ nbb++;
+
+ } while (notvisited);
+
+ return (0);
+}
diff --git a/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_bboard.c b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_bboard.c
new file mode 100644
index 0000000000..25157baeda
--- /dev/null
+++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_bboard.c
@@ -0,0 +1,370 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Create Base Board (MB) topology node from SMBIOS Type 2 structure
+ */
+
+#include <sys/types.h>
+#include <strings.h>
+#include <fm/topo_mod.h>
+#include <fm/topo_hc.h>
+#include <sys/systeminfo.h>
+#include <sys/smbios_impl.h>
+#include <sys/smbios.h>
+#include <x86pi_impl.h>
+
+/* base baoed type values to hc-canonical-name */
+static const struct x86pi_bb_name {
+ int type;
+ const char *name;
+} x86pi_bb_names[] = {
+ { SMB_BBT_SBLADE, "systemboard" },
+ { SMB_BBT_PROC, "cpuboard" },
+ { SMB_BBT_IO, "ioboard" },
+ { SMB_BBT_MEM, "memboard" },
+ { SMB_BBT_DAUGHTER, "systemboard" },
+ { SMB_BBT_MOTHER, "motherboard" },
+ { SMB_BBT_PROCMEM, "systemboard" },
+ { SMB_BBT_PROCIO, "systemboard" },
+ { SMB_BBT_INTER, "systemboard" },
+ { 0x00 }
+};
+
+tnode_t *
+x86pi_gen_bboard(topo_mod_t *mod, tnode_t *t_parent, smbios_hdl_t *shp,
+ int smb_id, int instance, int psmb_id)
+{
+ int rv;
+ smbios_info_t ip;
+ smbios_bboard_t bb;
+ smbios_struct_t sp;
+ x86pi_hcfmri_t bb_hcfmri;
+ tnode_t *bb_node;
+ const struct x86pi_bb_name *bbnp;
+ static int cpuboard = 0;
+ static int memboard = 0;
+ static int ioboard = 0;
+ static int systemboard = 0;
+ static int motherboard = 0;
+ char *f = "x86pi_gen_bboard";
+
+ topo_mod_dprintf(mod, "%s\n", f);
+
+ /* SMBIOS Base Board struct */
+ rv = smbios_info_bboard(shp, smb_id, &bb);
+ if (rv != 0) {
+ topo_mod_dprintf(mod, "%s: smbios_info_bboard() failed\n", f);
+ return (NULL);
+ }
+ (void) smbios_lookup_id(shp, psmb_id, &sp);
+ if (sp.smbstr_type == SMB_TYPE_CHASSIS &&
+ bb.smbb_chassis != psmb_id) {
+ topo_mod_dprintf(mod, "%s: base board (%d) does not belong to "
+ "chassis (%d)\n", f, smb_id, psmb_id);
+ return (NULL);
+ }
+
+ /* SMBIOS Base Board strings */
+ rv = smbios_info_common(shp, smb_id, &ip);
+ if (rv != 0) {
+ return (NULL);
+ }
+
+ /*
+ * populate string entries
+ *
+ * We don't set "product" because it may contain characters
+ * unacceptable by fmri. topo_mod_auth() will set the product-id
+ * for us and call topo_cleanup_auth_str() when necessary.
+ */
+ bb_hcfmri.serial_number = x86pi_cleanup_smbios_str(mod,
+ ip.smbi_serial, 0);
+ bb_hcfmri.version = x86pi_cleanup_smbios_str(mod, ip.smbi_version, 0);
+ /* asset tag string contains the part number */
+ bb_hcfmri.part_number = x86pi_cleanup_smbios_str(mod,
+ ip.smbi_asset, 0);
+ bb_hcfmri.location = x86pi_cleanup_smbios_str(mod, ip.smbi_location, 0);
+
+ /* determine the hc-name */
+ for (bbnp = x86pi_bb_names; bbnp->type != 0x00; bbnp++) {
+ if (bbnp->type == bb.smbb_type) {
+ switch (bbnp->type) {
+ case SMB_BBT_PROC :
+ instance = cpuboard++;
+ break;
+ case SMB_BBT_IO :
+ instance = ioboard++;
+ break;
+ case SMB_BBT_MEM :
+ instance = memboard++;
+ break;
+ case SMB_BBT_MOTHER :
+ instance = motherboard++;
+ break;
+ default :
+ /*
+ * Enumerate any other baseboard type
+ * as systemboard.
+ *
+ * SMB_BBT_UNKNOWN
+ * SMB_BBT_OTHER
+ * SMB_BBT_SBLADE
+ * SMB_BBT_CSWITCH
+ * SMB_BBT_SMM
+ * SMB_BBT_DAUGHTER
+ * SMB_BBT_PROCMEM
+ * SMB_BBT_PROCIO
+ * SMB_BBT_INTER
+ */
+ instance = systemboard++;
+ break;
+ }
+ break;
+ }
+ }
+
+ bb_hcfmri.instance = instance;
+ if (bbnp->type != 0x00)
+ bb_hcfmri.hc_name = topo_mod_strdup(mod, bbnp->name);
+ else
+ bb_hcfmri.hc_name = topo_mod_strdup(mod, "NULL");
+
+ topo_mod_dprintf(mod, "%s: S/N (%s)\n", f, bb_hcfmri.serial_number);
+ topo_mod_dprintf(mod, "%s: version/N (%s)\n", f, bb_hcfmri.version);
+ topo_mod_dprintf(mod, "%s: Part/N (%s)\n", f, bb_hcfmri.part_number);
+ topo_mod_dprintf(mod, "%s: location (%s)\n", f, bb_hcfmri.location);
+ topo_mod_dprintf(mod, "%s: instance (%d)\n", f, bb_hcfmri.instance);
+ topo_mod_dprintf(mod, "%s: hc_name (%s)\n", f, bb_hcfmri.hc_name);
+
+ rv = x86pi_enum_generic(mod, &bb_hcfmri, t_parent, t_parent, &bb_node,
+ X86PI_ENUM_FRU);
+ if (rv != 0) {
+ topo_mod_dprintf(mod, "%s: failed to create tnode %d\n", f,
+ instance);
+ bb_node = NULL;
+ }
+
+ /* free up strings */
+ if (bb_hcfmri.hc_name != NULL) {
+ topo_mod_strfree(mod, (char *)bb_hcfmri.hc_name);
+ }
+ if (bb_hcfmri.part_number != NULL) {
+ topo_mod_strfree(mod, (char *)bb_hcfmri.part_number);
+ }
+ if (bb_hcfmri.serial_number != NULL) {
+ topo_mod_strfree(mod, (char *)bb_hcfmri.serial_number);
+ }
+ if (bb_hcfmri.version != NULL) {
+ topo_mod_strfree(mod, (char *)bb_hcfmri.version);
+ }
+ if (bb_hcfmri.location != NULL) {
+ topo_mod_strfree(mod, (char *)bb_hcfmri.location);
+ }
+
+ return (bb_node);
+}
+
+
+int
+x86pi_bb_getchips(topo_mod_t *mod, smbios_hdl_t *shp, int index, int nboards)
+{
+ id_t *cid;
+ int count;
+ int ncmp = 0;
+ smbios_struct_t sp;
+ smbs_cnt_t *smbc = NULL;
+
+ cid = stypes[SMB_TYPE_BASEBOARD].ids[index].con_ids;
+ count = stypes[SMB_TYPE_BASEBOARD].ids[index].con_cnt;
+
+ for (int i = 0; i < count; i++) {
+ (void) smbios_lookup_id(shp, cid[i], &sp);
+ if (sp.smbstr_type == SMB_TYPE_PROCESSOR) {
+ ncmp++;
+ }
+ }
+
+ /*
+ * If there are missing SMB_TYPE_PROCESSOR structures
+ * contained within SMB_TYPE_BASEBOARD, and if the
+ * system has only one baseboard we enumerate
+ * all processors under it.
+ */
+ smbc = &stypes[SMB_TYPE_PROCESSOR];
+ smbc->type = SMB_TYPE_PROCESSOR;
+ x86pi_smb_strcnt(shp, smbc);
+
+ if (nboards == 1) {
+ if (ncmp != stypes[SMB_TYPE_PROCESSOR].count)
+ ncmp = stypes[SMB_TYPE_PROCESSOR].count;
+ } else {
+ if (ncmp == 0) {
+ topo_mod_dprintf(mod, "failed to get processors"
+ " (or) no processors are contained"
+ " within baseboard instance %d, unable to"
+ " enumerate chips\n", index);
+ }
+ }
+
+ return (ncmp);
+}
+
+
+id_t
+x86pi_bb_topparent(smbios_hdl_t *shp, int index, tnode_t **pnode, id_t *psmbid)
+{
+
+ id_t top_bb_smbid = -1;
+ id_t smb_id;
+ int bb_count, ch_count;
+ smbios_struct_t sp;
+
+ smb_id = stypes[SMB_TYPE_BASEBOARD].ids[index].con_by_id;
+ (void) smbios_lookup_id(shp, smb_id, &sp);
+
+ if (sp.smbstr_type == SMB_TYPE_CHASSIS) {
+ top_bb_smbid = stypes[SMB_TYPE_BASEBOARD].ids[index].id;
+ *psmbid = smb_id;
+ ch_count = stypes[SMB_TYPE_CHASSIS].count;
+ for (int i = 0; i < ch_count; i++)
+ if (stypes[SMB_TYPE_CHASSIS].ids[i].id == *psmbid)
+ *pnode = stypes[SMB_TYPE_CHASSIS].ids[i].node;
+
+ return (top_bb_smbid);
+
+ } else if (sp.smbstr_type == SMB_TYPE_BASEBOARD) {
+ bb_count = stypes[SMB_TYPE_BASEBOARD].count;
+ for (int i = 0; i < bb_count; i++) {
+ if (stypes[SMB_TYPE_BASEBOARD].ids[i].id == smb_id) {
+ if (stypes[SMB_TYPE_BASEBOARD].ids[i].visited
+ == X86PI_VISITED) {
+ top_bb_smbid =
+ stypes[SMB_TYPE_BASEBOARD].\
+ ids[index].id;
+ *pnode =
+ stypes[SMB_TYPE_BASEBOARD].ids[i].\
+ node;
+ *psmbid =
+ stypes[SMB_TYPE_BASEBOARD].ids[i].\
+ id;
+ break;
+ }
+ top_bb_smbid = x86pi_bb_topparent(shp,
+ i, pnode, psmbid);
+ break;
+ }
+ }
+ }
+
+ return (top_bb_smbid);
+}
+
+
+id_t
+x86pi_bb_chassis(smbios_hdl_t *shp, id_t bb_smbid)
+{
+ smbios_bboard_t bb;
+ int rv;
+
+ rv = smbios_info_bboard(shp, bb_smbid, &bb);
+ if (rv != 0)
+ return (-1);
+
+ return (bb.smbb_chassis);
+}
+
+
+int
+x86pi_bb_contains(topo_mod_t *mod, smbios_hdl_t *shp)
+{
+ int rv;
+ id_t smb_id;
+ smbios_bboard_t bb;
+ int bb_count = 0;
+ uint_t cont_cnt = 0;
+ smbios_struct_t sp;
+
+ bb_count = stypes[SMB_TYPE_BASEBOARD].count;
+ for (int i = 0; i < bb_count; i++) {
+ smb_id = stypes[SMB_TYPE_BASEBOARD].ids[i].id;
+ /* SMBIOS Base Board struct */
+ rv = smbios_info_bboard(shp, smb_id, &bb);
+ if (rv != 0)
+ return (-1);
+ /* Set Baseboard - Chassis Relationship */
+ if (stypes[SMB_TYPE_BASEBOARD].ids[i].con_by_id == 0) {
+ stypes[SMB_TYPE_BASEBOARD].ids[i].con_by_id =
+ rv = x86pi_bb_chassis(shp, smb_id);
+ if (rv == -1) {
+ topo_mod_dprintf(mod, " failed to get"
+ " the chassis handle\n");
+ return (rv);
+ }
+ }
+
+ /* SMBIOS contained object handles */
+ cont_cnt = bb.smbb_contn;
+ if (cont_cnt > 0) {
+ id_t *cont_hdl;
+ uint16_t hdl;
+
+ /* allocate space for and get contained handles */
+ cont_hdl = topo_mod_alloc(mod, cont_cnt *
+ sizeof (id_t));
+ rv = smbios_info_contains(shp, smb_id, cont_cnt,
+ cont_hdl);
+ if (rv > SMB_CONT_MAX) {
+ topo_mod_free(mod, cont_hdl, cont_cnt *
+ sizeof (id_t));
+ return (-1);
+ }
+ cont_cnt = MIN(rv, cont_cnt);
+
+ /* attach contained handles */
+ stypes[SMB_TYPE_BASEBOARD].ids[i].con_cnt = cont_cnt;
+ for (int j = 0; j < cont_cnt; j++) {
+ hdl = (uint16_t)cont_hdl[j];
+ topo_mod_dprintf(mod, "id %d contained handle"
+ " %d: %d\n", i, j, hdl);
+ stypes[SMB_TYPE_BASEBOARD].ids[i].\
+ con_ids[j] = hdl;
+ (void) smbios_lookup_id(shp, hdl, &sp);
+ if (sp.smbstr_type == SMB_TYPE_BASEBOARD) {
+ for (int k = 0; k < bb_count; k++)
+ if (stypes[SMB_TYPE_BASEBOARD].\
+ ids[k].id == hdl)
+ stypes[\
+ SMB_TYPE_BASEBOARD\
+ ].ids[k].con_by_id =
+ smb_id;
+ }
+ }
+ topo_mod_free(mod, cont_hdl, cont_cnt * sizeof (id_t));
+ }
+ }
+ return (0);
+}
diff --git a/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_chassis.c b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_chassis.c
new file mode 100644
index 0000000000..b17e075605
--- /dev/null
+++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_chassis.c
@@ -0,0 +1,116 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Create chassis topology node from SMBIOS Type 3 structure
+ */
+
+#include <sys/types.h>
+#include <strings.h>
+#include <fm/topo_mod.h>
+#include <fm/topo_hc.h>
+#include <sys/systeminfo.h>
+#include <sys/smbios_impl.h>
+#include <x86pi_impl.h>
+
+
+tnode_t *
+x86pi_gen_chassis(topo_mod_t *mod, tnode_t *t_parent, smbios_hdl_t *shp,
+ int smb_id, int instance)
+{
+ int rv;
+ smbios_info_t ip;
+ smbios_chassis_t ch;
+ x86pi_hcfmri_t ch_hcfmri;
+ tnode_t *ch_node;
+ char *f = "x86pi_gen_chassis";
+
+
+ /* init fmri struct */
+ bzero(&ch_hcfmri, sizeof (x86pi_hcfmri_t));
+
+ /* grab SMBIOS strings */
+ rv = smbios_info_common(shp, smb_id, &ip);
+ if (rv != 0) {
+ return (NULL);
+ }
+
+ /* grab SMBIOS type 3 struct */
+ rv = smbios_info_chassis(shp, smb_id, &ch);
+ if (rv != 0) {
+ return (NULL);
+ }
+
+ /* populate string entries */
+ ch_hcfmri.serial_number = x86pi_cleanup_smbios_str(mod,
+ ip.smbi_serial, 0);
+ ch_hcfmri.version = x86pi_cleanup_smbios_str(mod, ip.smbi_version, 0);
+ ch_hcfmri.manufacturer = x86pi_cleanup_smbios_str(mod,
+ ip.smbi_manufacturer, 0);
+
+ /* set hc_name and instance */
+ ch_hcfmri.hc_name = topo_mod_strdup(mod, "chassis");
+ ch_hcfmri.instance = instance;
+
+ topo_mod_dprintf(mod, "%s: instance (%d)\n", f, ch_hcfmri.instance);
+ topo_mod_dprintf(mod, "%s: hc name (%s)\n", f, ch_hcfmri.hc_name);
+ topo_mod_dprintf(mod, "%s: Serial Number (%s)\n",
+ f, ch_hcfmri.serial_number);
+ topo_mod_dprintf(mod, "%s: Version (%s)\n", f, ch_hcfmri.version);
+ topo_mod_dprintf(mod, "%s: Manufacturer (%s)\n",
+ f, ch_hcfmri.manufacturer);
+
+ /* create topo node */
+ if (!instance) {
+ /* First Chassis SMBIOS Record is Chassis topo instance 0 */
+ rv = x86pi_enum_generic(mod, &ch_hcfmri, t_parent, NULL,
+ &ch_node, 0);
+ } else {
+ rv = x86pi_enum_generic(mod, &ch_hcfmri, t_parent, t_parent,
+ &ch_node, 0);
+ }
+ if (rv != 0) {
+ topo_mod_dprintf(mod, "%s: failed to create %d tnode\n", f,
+ instance);
+ return (NULL);
+ }
+
+ /* free up strings */
+ if (ch_hcfmri.serial_number != NULL) {
+ topo_mod_strfree(mod, (char *)ch_hcfmri.serial_number);
+ }
+ if (ch_hcfmri.version != NULL) {
+ topo_mod_strfree(mod, (char *)ch_hcfmri.version);
+ }
+ if (ch_hcfmri.manufacturer != NULL) {
+ topo_mod_strfree(mod, (char *)ch_hcfmri.manufacturer);
+ }
+ if (ch_hcfmri.hc_name != NULL) {
+ topo_mod_strfree(mod, (char *)ch_hcfmri.hc_name);
+ }
+
+ return (ch_node);
+}
diff --git a/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_generic.c b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_generic.c
new file mode 100644
index 0000000000..6e19ef059d
--- /dev/null
+++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_generic.c
@@ -0,0 +1,211 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Create a generic topology node.
+ */
+#include <sys/types.h>
+#include <strings.h>
+#include <sys/fm/protocol.h>
+#include <fm/topo_mod.h>
+#include <fm/topo_hc.h>
+#include <x86pi_impl.h>
+
+#define _ENUM_NAME "enum_generic"
+#define _FAC_PROV "fac_prov_ipmi"
+
+/*
+ * Create a generic topo node based on the hcfmri strcuture passed in.
+ */
+int
+x86pi_enum_generic(topo_mod_t *mod, x86pi_hcfmri_t *hcfmri,
+ tnode_t *t_bindparent, tnode_t *t_fmriparent, tnode_t **t_node, int flag)
+{
+ int rv;
+ int err;
+ nvlist_t *out;
+ nvlist_t *fmri;
+ nvlist_t *auth;
+
+ topo_mod_dprintf(mod, "%s adding entry for type (%s)\n",
+ _ENUM_NAME, hcfmri->hc_name);
+
+ if (t_bindparent == NULL) {
+ topo_mod_dprintf(mod,
+ "%s called with NULL parent for type %s\n",
+ _ENUM_NAME, hcfmri->hc_name);
+ return (-1);
+ }
+
+ /* Create the FMRI for this node */
+ auth = topo_mod_auth(mod, t_bindparent);
+ fmri = topo_mod_hcfmri(mod, t_fmriparent, FM_HC_SCHEME_VERSION,
+ hcfmri->hc_name, hcfmri->instance, NULL, auth,
+ hcfmri->part_number, hcfmri->version, hcfmri->serial_number);
+
+ nvlist_free(auth);
+
+ if (fmri == NULL) {
+ topo_mod_dprintf(mod,
+ "%s failed to create %s fmri : %s\n", _ENUM_NAME,
+ hcfmri->hc_name, topo_strerror(topo_mod_errno(mod)));
+ return (-1);
+ }
+
+ rv = topo_node_range_create(mod, t_bindparent, hcfmri->hc_name, 0, 4);
+ if (rv != 0 && topo_mod_errno(mod) != EMOD_NODE_DUP) {
+ topo_mod_dprintf(mod, "%s range create failed for node %s\n",
+ _ENUM_NAME, hcfmri->hc_name);
+ }
+
+ /* Bind this node to the parent */
+ *t_node = x86pi_node_bind(mod, t_bindparent, hcfmri, fmri, flag);
+ nvlist_free(fmri);
+ if (*t_node == NULL) {
+ topo_mod_dprintf(mod,
+ "%s failed to bind %s node instance %d: %s\n",
+ _ENUM_NAME, hcfmri->hc_name, hcfmri->instance,
+ topo_strerror(topo_mod_errno(mod)));
+ return (-1);
+ }
+
+ /* call IPMI facility provider to register fac methods */
+ if (topo_mod_load(mod, _FAC_PROV, TOPO_VERSION) == NULL) {
+ topo_mod_dprintf(mod,
+ "%s: Failed to load %s module: %s\n", _ENUM_NAME, _FAC_PROV,
+ topo_mod_errmsg(mod));
+ return (-1);
+ }
+
+ rv = topo_mod_enumerate(mod, *t_node, _FAC_PROV, _FAC_PROV, 0, 0, NULL);
+ if (rv != 0) {
+ topo_mod_dprintf(mod,
+ "%s: %s failed: %s\n", _ENUM_NAME, _FAC_PROV,
+ topo_mod_errmsg(mod));
+ return (-1);
+ }
+
+ /* invoke fac_prov_ipmi_enum method */
+ if (topo_method_supported(*t_node, TOPO_METH_FAC_ENUM, 0)) {
+ if (topo_method_invoke(*t_node, TOPO_METH_FAC_ENUM, 0, NULL,
+ &out, &err) != 0) {
+ /* log the error and drive on */
+ topo_mod_dprintf(mod,
+ "%s: TOPO_METH_FAC_ENUM failed\n", _ENUM_NAME);
+ } else {
+ fac_done = 1;
+ }
+ }
+
+ topo_mod_dprintf(mod, "%s added (%s) node\n", _ENUM_NAME,
+ topo_node_name(*t_node));
+
+ return (0);
+}
+
+
+tnode_t *
+x86pi_node_bind(topo_mod_t *mod, tnode_t *t_parent, x86pi_hcfmri_t *hcfmri,
+ nvlist_t *fmri, int flag)
+{
+ int result;
+ tnode_t *t_node;
+ char *f = "x86pi_node_bind";
+
+ if (t_parent == NULL) {
+ topo_mod_dprintf(mod,
+ "%s: NULL parent for %s node instance %d\n",
+ f, hcfmri->hc_name, hcfmri->instance);
+ return (NULL);
+ }
+
+ /* Bind this node to the parent */
+ t_node = topo_node_bind(mod, t_parent, hcfmri->hc_name,
+ hcfmri->instance, fmri);
+ if (t_node == NULL) {
+ topo_mod_dprintf(mod,
+ "%s: failed to bind %s node instance %d: %s\n",
+ f, hcfmri->hc_name, (uint32_t)hcfmri->instance,
+ topo_strerror(topo_mod_errno(mod)));
+ return (NULL);
+ }
+ topo_mod_dprintf(mod, "%s: bound %s node instance %d type %s\n",
+ f, hcfmri->hc_name, hcfmri->instance, hcfmri->hc_name);
+
+ /*
+ * We have bound the node. Now decorate it with an appropriate
+ * FRU and label (which may be inherited from the parent).
+ */
+ result = x86pi_set_frufmri(mod, hcfmri, t_parent, t_node, flag);
+ if (result != 0) {
+ /*
+ * Though we have failed to set the FRU FMRI we still continue.
+ * The module errno is set by the called routine, so we report
+ * the problem and move on.
+ */
+ topo_mod_dprintf(mod,
+ "%s: failed to set FRU FMRI for %s node\n",
+ f, hcfmri->hc_name);
+ }
+
+ result = x86pi_set_label(mod, hcfmri->location, hcfmri->hc_name,
+ t_node);
+ if (result != 0) {
+ /*
+ * Though we have failed to set the label, we still continue.
+ * The module errno is set by the called routine, so we report
+ * the problem and move on.
+ */
+ topo_mod_dprintf(mod, "%s: no label for %s node\n",
+ f, hcfmri->hc_name);
+ }
+
+ result = x86pi_set_auth(mod, hcfmri, t_parent, t_node);
+ if (result != 0) {
+ /*
+ * Though we have failed to set the authority, we still
+ * continue. The module errno is set by the called routine, so
+ * we report the problem and move on.
+ */
+ topo_mod_dprintf(mod,
+ "%s: no authority information for %s node\n",
+ f, hcfmri->hc_name);
+ }
+
+ result = x86pi_set_system(mod, t_node);
+ if (result != 0) {
+ /*
+ * Though we have failed to set the system group, we still
+ * continue. The module errno is set by the called routine, so
+ * we report the problem and move on.
+ */
+ topo_mod_dprintf(mod,
+ "%s: no system information for %s node\n",
+ f, hcfmri->hc_name);
+ }
+
+ return (t_node);
+}
diff --git a/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_hostbridge.c b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_hostbridge.c
new file mode 100644
index 0000000000..c3b5857634
--- /dev/null
+++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_hostbridge.c
@@ -0,0 +1,290 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * i86pc Generic hostbridge/pciex/pci enumerator
+ *
+ * hostbridge/pciexrc/pcibus topo nodes are created per SMBIOS type 138
+ * (SUN_OEM_PCIEXRC) records. Each type 138 record can either represent
+ * a hostbridge or a pciexrc/pcibus determined by whether it points to
+ * a baseboard record or another type 138 record.
+ *
+ * x86pi_gen_hbr() is called when a new hostbridge node needs to be created..
+ * It then searches all the type 138 records that connected to it. For each
+ * of the records, bdf is compared to find a matching di_node. If the
+ * di_node is a pciex root port, a pciexrc (bad name!) node will be created.
+ * When pciexrc creation is done, or the di_node is a pcibus, in either
+ * case the pcibus module will loaded to enumerate pciexbus/pcibus etc.
+ *
+ * The enumeration uses did routines heavily, which requires a did hash
+ * pointer stored in x86pi's module-specific area.
+ */
+
+#include <sys/types.h>
+#include <strings.h>
+#include <fm/topo_mod.h>
+#include <fm/topo_hc.h>
+#include <sys/systeminfo.h>
+#include <sys/smbios_impl.h>
+#include <sys/fm/protocol.h>
+#include <x86pi_impl.h>
+#include <did.h>
+#include <did_impl.h>
+#include <did_props.h>
+#include <hostbridge.h>
+
+#define PCI_ENUM "pcibus"
+#define PCI_ENUMR_VERS 1
+#define MAX_HB_BUSES 255
+
+extern txprop_t RC_common_props[], HB_common_props[], ExHB_common_props[];
+extern int RC_propcnt, HB_propcnt, ExHB_propcnt;
+
+static topo_mod_t *pcimp = NULL;
+
+int
+x86pi_hbr_enum_init(topo_mod_t *mod)
+{
+ did_hash_t *tab = (did_hash_t *)topo_mod_getspecific(mod);
+ const char *f = "x86pi_hbr_enum_init";
+
+ if (tab == NULL && did_hash_init(mod) < 0) {
+ topo_mod_dprintf(mod, "%s: did_hash_init() failed.\n", f);
+ return (-1);
+ }
+
+ if (pcimp == NULL &&
+ (pcimp = topo_mod_load(mod, PCI_ENUM, PCI_ENUMR_VERS))
+ == NULL) {
+ topo_mod_dprintf(mod,
+ "%s: %s enumerator could not load %s.\n",
+ f, HOSTBRIDGE, PCI_ENUM);
+ did_hash_fini(mod);
+ return (-1);
+ }
+
+ return (0);
+}
+
+void
+x86pi_hbr_enum_fini(topo_mod_t *mod)
+{
+ did_hash_fini(mod);
+ if (pcimp != NULL) {
+ topo_mod_unload(pcimp);
+ pcimp = NULL;
+ }
+}
+
+static uint16_t
+x86pi_bdf(topo_mod_t *mod, di_node_t node)
+{
+ int *val;
+
+ if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "reg", &val) < 0) {
+ topo_mod_dprintf(mod, "couldn't get \"reg\" prop: %s.\n",
+ strerror(errno));
+ return ((uint16_t)-1);
+ }
+
+ return (uint16_t)((*val & PCI_REG_BDFR_M) >> PCI_REG_FUNC_SHIFT);
+}
+
+static int
+pciex_process(topo_mod_t *mod, tnode_t *tn_hbr, di_node_t rcn,
+ topo_instance_t rci)
+{
+ did_t *did;
+ int rv;
+ tnode_t *tn_rc;
+ x86pi_hcfmri_t hcfmri = {0};
+ tnode_t *tn_bb = topo_node_parent(tn_hbr);
+ const char *f = "pciexrc_process";
+
+ if ((did = did_create(mod, rcn, topo_node_instance(tn_bb),
+ topo_node_instance(tn_hbr), rci, TRUST_BDF)) == NULL)
+ return (NULL);
+
+ did_markrc(did);
+
+ /*
+ * Let did set the hostbridge properties excluding FRU and label.
+ */
+ (void) did_props_set(tn_hbr, did, ExHB_common_props, ExHB_propcnt - 2);
+
+ if (topo_node_range_create(mod, tn_hbr, PCIEX_ROOT, 0,
+ MAX_HB_BUSES) != 0 && topo_mod_errno(mod) != EMOD_NODE_DUP) {
+ topo_mod_dprintf(mod,
+ "%s: create child range for %s failed: %s\n",
+ f, PCIEX_ROOT, topo_mod_errmsg(mod));
+ return (-1);
+ }
+
+ hcfmri.hc_name = PCIEX_ROOT;
+ hcfmri.instance = rci;
+ rv = x86pi_enum_generic(mod, &hcfmri, tn_hbr, tn_hbr, &tn_rc, 0);
+ if (rv != 0) {
+ topo_mod_dprintf(mod, "%s: failed to create %s = %d\n",
+ f, PCIEX_ROOT, rci);
+ return (-1);
+ }
+
+ /*
+ * pcibus enumerator requires di_node_t be set in node specific
+ */
+ topo_node_setspecific(tn_rc, rcn);
+
+ /*
+ * Let did set the RC properties excluding FRU, and label.
+ */
+ if (did_props_set(tn_rc, did, RC_common_props, RC_propcnt - 2) < 0) {
+ topo_mod_dprintf(mod, "%s: did_props_set failed for %s = %d\n",
+ f, PCIEX_ROOT, rci);
+ topo_node_unbind(tn_rc);
+ return (-1);
+ }
+
+ if (topo_node_range_create(mod, tn_rc, PCIEX_BUS, 0,
+ MAX_HB_BUSES) != 0 && topo_mod_errno(mod) != EMOD_NODE_DUP) {
+ topo_mod_dprintf(mod,
+ "%s: create child range for %s failed: %s\n",
+ f, PCIEX_BUS, topo_mod_errmsg(mod));
+ return (-1);
+ }
+
+ return (topo_mod_enumerate(mod, tn_rc, PCI_BUS, PCIEX_BUS,
+ 0, MAX_HB_BUSES, did));
+}
+
+static int
+pci_process(topo_mod_t *mod, tnode_t *tn_hbr, di_node_t bn)
+{
+ did_t *did;
+ tnode_t *tn_bb = topo_node_parent(tn_hbr);
+
+ if ((did = did_create(mod, bn, topo_node_instance(tn_bb),
+ topo_node_instance(tn_hbr), NO_RC, TRUST_BDF)) == NULL)
+ return (-1);
+
+ /*
+ * Let did set the hostbridge properties excluding FRU and label.
+ */
+ (void) did_props_set(tn_hbr, did, HB_common_props, HB_propcnt - 2);
+
+ if (topo_node_range_create(mod, tn_hbr, PCI_BUS, 0,
+ MAX_HB_BUSES) != 0 && topo_mod_errno(mod) != EMOD_NODE_DUP) {
+ topo_mod_dprintf(mod, "create child range for %s failed: %s\n",
+ PCI_BUS, topo_mod_errmsg(mod));
+ return (-1);
+ }
+
+ return (topo_mod_enumerate(mod, tn_hbr, PCI_BUS, PCI_BUS,
+ 0, MAX_HB_BUSES, did));
+}
+
+static int
+x86pi_gen_pci_pciexrc(topo_mod_t *mod, tnode_t *tn_hbr, uint16_t bdf,
+ topo_instance_t *rcip)
+{
+ di_node_t devtree, pnode, cnode;
+
+ topo_mod_dprintf(mod, "creating pci/pciexrc node bdf = %#x\n",
+ (int)bdf);
+
+ devtree = topo_mod_devinfo(mod);
+ if (devtree == DI_NODE_NIL) {
+ topo_mod_dprintf(mod, "devinfo init failed.\n");
+ return (-1);
+ }
+
+ for (pnode = di_drv_first_node(PCI, devtree);
+ pnode != DI_NODE_NIL; pnode = di_drv_next_node(pnode))
+ if (x86pi_bdf(mod, pnode) == bdf)
+ return (pci_process(mod, tn_hbr, pnode));
+
+ pnode = di_drv_first_node(NPE, devtree);
+ while (pnode != DI_NODE_NIL) {
+ for (cnode = di_child_node(pnode); cnode != DI_NODE_NIL;
+ cnode = di_sibling_node(cnode)) {
+ if (di_driver_name(cnode) == NULL ||
+ x86pi_bdf(mod, cnode) != bdf)
+ continue;
+
+ if (strcmp(di_driver_name(cnode), PCI_PCI) == 0)
+ return (pci_process(mod, tn_hbr, cnode));
+
+ if (strcmp(di_driver_name(cnode), PCIEB) == 0)
+ return (pciex_process(mod, tn_hbr,
+ cnode, (*rcip)++));
+
+ topo_mod_dprintf(mod, "no matching driver found: "
+ "bdf = %#x\n", (int)bdf);
+ }
+ pnode = di_drv_next_node(pnode);
+ }
+
+ topo_mod_dprintf(mod, "no matching bdf found: bdf = %#x\n", (int)bdf);
+
+ return (0);
+}
+
+int
+x86pi_gen_hbr(topo_mod_t *mod, tnode_t *tn_bb, smbios_hdl_t *shp,
+ int hbr_smbid, topo_instance_t hbri, topo_instance_t *rcip)
+{
+ x86pi_hcfmri_t hcfmri = {0};
+ tnode_t *tn_hbr;
+ smbs_cnt_t *smbc = &stypes[SUN_OEM_PCIEXRC];
+ smbios_pciexrc_t smb_rc;
+ int i, rv, err = 0;
+ const char *f = "x86pi_gen_hbr";
+
+ hcfmri.hc_name = HOSTBRIDGE;
+ hcfmri.instance = hbri;
+
+ /* create and bind the "hostbridge" node */
+ rv = x86pi_enum_generic(mod, &hcfmri, tn_bb, tn_bb, &tn_hbr, 0);
+ if (rv != 0) {
+ topo_mod_dprintf(mod, "%s: failed to create %s = %d\n",
+ f, HOSTBRIDGE, hbri);
+ return (topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM));
+ }
+
+ /*
+ * Walk the smbios records and create the pci/pciexrc nodes
+ */
+ for (i = 0; i < smbc->count; i++) {
+ if (smbios_info_pciexrc(shp, smbc->ids[i].id, &smb_rc) != 0)
+ topo_mod_dprintf(mod,
+ "%s: failed: id = %d\n", f, (int)smbc->ids[i].id);
+ else if (smb_rc.smbpcie_bb == hbr_smbid &&
+ x86pi_gen_pci_pciexrc(mod, tn_hbr, smb_rc.smbpcie_bdf,
+ rcip) != 0)
+ err++;
+ }
+
+ return (err == 0 ? 0 : topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM));
+}
diff --git a/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_impl.h b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_impl.h
new file mode 100644
index 0000000000..fa0cbf674f
--- /dev/null
+++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_impl.h
@@ -0,0 +1,206 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _X86PI_IMPL_H
+#define _X86PI_IMPL_H
+
+/*
+ * i86pc Generic Enumerator private interfaces
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <smbios.h>
+#include <ctype.h>
+
+
+/*
+ * Table showing the relationship between hc-canonical names and the
+ * SMBIOS tables/values.
+ *
+ * **************************************************************************
+ * | hc-name | SMB Table | Offset - Name | Value |
+ * --------------------------------------------------------------------------
+ * --------------------------------------------------------------------------
+ * | "motherboard" | Type 2 | 0x0D - Board Type | 0x0A |
+ * --------------------------------------------------------------------------
+ * | "cpuboard" | Type 2 | 0x0D - Board Type | 0x06 |
+ * --------------------------------------------------------------------------
+ * | "memboard" | Type 2 | 0x0D - Board Type | 0x08 |
+ * --------------------------------------------------------------------------
+ * | "ioboard" | Type 2 | 0x0D - Board Type | 0x07 |
+ * --------------------------------------------------------------------------
+ * | "systemboard" | Type 2 | 0x0D - Board Type | 0x03,0x09,|
+ * | | | | 0x0B,0x0C |
+ * --------------------------------------------------------------------------
+ * | "hostbridge" | Type 138 | |
+ * --------------------------------------------------------------------------
+ * | "pciexrc" | Type 138 | |
+ * **************************************************************************
+ */
+
+
+/* Definitions used when registering the enumerator with libtopo */
+#define X86PI_DESC "i86pc Generic Topology Enumerator"
+#define X86PI_SCHEME "hc"
+#define X86PI_VERSION TOPO_VERSION
+
+/*
+ * Solaris FMA Compliance level for SMBIOS.
+ * The same X86PI_* definitions are used in chip.h
+ * please keep them in sync
+ */
+#define X86PI_FULL 1
+#define X86PI_NONE 2
+
+/* used in traversing contained bboards */
+#define X86PI_VISITED 1
+
+#define LABEL 1
+
+/* Flags used by x86pi_enum_generic */
+#define X86PI_ENUM_FRU 0x0001 /* Indicates a FRU */
+
+/* max allowed contained count */
+#define SMB_MAX_ID 0x40
+
+/* indication of successful fac node creation */
+int fac_done;
+
+/*
+ * Count and smbios struct id(s) for each smbios struct type.
+ */
+typedef struct smbs_con_ids {
+ id_t id; /* smbios struct id */
+ id_t con_cnt; /* containee count */
+ id_t con_ids[SMB_MAX_ID]; /* containee ids */
+ id_t con_by_id; /* container id */
+ int visited; /* visit flag */
+ tnode_t *node;
+} smbs_con_ids_t;
+
+typedef struct smbs_cnt {
+ int type; /* SMBIOS stucture type */
+ int count; /* number of table entries */
+ smbs_con_ids_t ids[SMB_MAX_ID]; /* SMBIOS table entry id(s) */
+} smbs_cnt_t;
+
+smbs_cnt_t stypes[SMB_TYPE_OEM_HI]; /* one for each struct */
+
+/*
+ * The enumerator needs to pass some state in to the function that walks
+ * the PRI graph. This structure contains the necessary information.
+ */
+struct x86pi_enum_s {
+ topo_mod_t *mod; /* Topo module handle */
+ tnode_t *t_parent; /* "Chassis" parent */
+ uint32_t force; /* force legacy */
+ void *priv; /* Private data */
+};
+typedef struct x86pi_enum_s x86pi_enum_t;
+
+/*
+ * x86gentopo hcfmri info structure.
+ *
+ * Available unformed SMBIOS strings:
+ * smbi_manufacturer
+ * smbi_product
+ * smbi_version
+ * smbi_serial
+ * smbi_asset
+ * smbi_location
+ * smbi_part
+ *
+ */
+struct x86pi_hcfmri_info_s {
+ int instance;
+ int rev;
+
+ const char *hc_name;
+ const char *manufacturer;
+ const char *product;
+ const char *version;
+ const char *serial_number;
+ const char *asset_tag;
+ const char *location;
+ const char *part_number;
+};
+typedef struct x86pi_hcfmri_info_s x86pi_hcfmri_t;
+
+/*
+ * Prototypes
+ */
+
+/* SMBIOS */
+smbios_hdl_t *x86pi_smb_open(topo_mod_t *);
+void x86pi_smb_strcnt(smbios_hdl_t *, smbs_cnt_t *);
+int x86pi_check_comp(topo_mod_t *, smbios_hdl_t *);
+
+/* Node generation */
+tnode_t *x86pi_gen_chassis(topo_mod_t *, tnode_t *, smbios_hdl_t *, int, int);
+tnode_t *x86pi_gen_bboard(topo_mod_t *, tnode_t *, smbios_hdl_t *, int, int,
+ int);
+int x86pi_gen_cmp(topo_mod_t *, tnode_t *, smbios_hdl_t *, int, int, int);
+int x86pi_gen_core(topo_mod_t *, tnode_t *, int, int, int);
+int x86pi_gen_strand(topo_mod_t *, tnode_t *, int, int, int);
+int x86pi_gen_memarray(topo_mod_t *, tnode_t *, smbios_hdl_t *, int, int);
+void x86pi_gen_memdev(topo_mod_t *, tnode_t *, smbios_hdl_t *, int, int, int);
+int x86pi_gen_hbr(topo_mod_t *, tnode_t *, smbios_hdl_t *, int,
+ topo_instance_t, topo_instance_t *);
+
+/* support routines */
+int x86pi_enum_generic(topo_mod_t *, x86pi_hcfmri_t *, tnode_t *, tnode_t *,
+ tnode_t **, int);
+tnode_t *x86pi_node_bind(topo_mod_t *, tnode_t *, x86pi_hcfmri_t *, nvlist_t *,
+ int);
+void x86pi_hcfmri_info_fini(topo_mod_t *, x86pi_hcfmri_t *);
+
+/* get/set info */
+char *x86pi_get_serverid(topo_mod_t *);
+int x86pi_set_frufmri(topo_mod_t *, x86pi_hcfmri_t *, tnode_t *, tnode_t *,
+ int);
+int x86pi_set_label(topo_mod_t *, const char *, const char *, tnode_t *);
+int x86pi_set_auth(topo_mod_t *, x86pi_hcfmri_t *, tnode_t *, tnode_t *);
+int x86pi_set_system(topo_mod_t *, tnode_t *);
+
+/* hostbridge */
+int x86pi_hbr_enum_init(topo_mod_t *);
+void x86pi_hbr_enum_fini(topo_mod_t *);
+
+/* base board */
+id_t x86pi_bb_topparent(smbios_hdl_t *, int, tnode_t **, id_t *);
+int x86pi_bb_contains(topo_mod_t *, smbios_hdl_t *);
+int x86pi_bb_getchips(topo_mod_t *, smbios_hdl_t *, int, int);
+
+const char *x86pi_cleanup_smbios_str(topo_mod_t *, const char *, int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _X86PI_IMPL_H */
diff --git a/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_subr.c b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_subr.c
new file mode 100644
index 0000000000..474064e278
--- /dev/null
+++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_subr.c
@@ -0,0 +1,653 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Subroutines used by the i86pc Generic Topology Enumerator
+ */
+
+#include <sys/types.h>
+#include <strings.h>
+#include <deflt.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <fm/topo_mod.h>
+#include <fm/topo_hc.h>
+#include <sys/devfm.h>
+#include <sys/systeminfo.h>
+#include <sys/fm/protocol.h>
+#include <sys/utsname.h>
+#include <sys/smbios.h>
+#include <sys/smbios_impl.h>
+#include <x86pi_impl.h>
+
+
+static const topo_pgroup_info_t sys_pgroup = {
+ TOPO_PGROUP_SYSTEM,
+ TOPO_STABILITY_PRIVATE,
+ TOPO_STABILITY_PRIVATE,
+ 1
+};
+
+static const topo_pgroup_info_t auth_pgroup = {
+ FM_FMRI_AUTHORITY,
+ TOPO_STABILITY_PRIVATE,
+ TOPO_STABILITY_PRIVATE,
+ 1
+};
+
+
+/*
+ * Free hcfmri strings.
+ */
+void
+x86pi_hcfmri_info_fini(topo_mod_t *mod, x86pi_hcfmri_t *hc)
+{
+ if (hc->hc_name != NULL)
+ topo_mod_strfree(mod, (char *)hc->hc_name);
+ if (hc->manufacturer != NULL)
+ topo_mod_strfree(mod, (char *)hc->manufacturer);
+ if (hc->product != NULL)
+ topo_mod_strfree(mod, (char *)hc->product);
+ if (hc->version != NULL)
+ topo_mod_strfree(mod, (char *)hc->version);
+ if (hc->serial_number != NULL)
+ topo_mod_strfree(mod, (char *)hc->serial_number);
+ if (hc->asset_tag != NULL)
+ topo_mod_strfree(mod, (char *)hc->asset_tag);
+ if (hc->location != NULL)
+ topo_mod_strfree(mod, (char *)hc->location);
+ if (hc->part_number != NULL)
+ topo_mod_strfree(mod, (char *)hc->part_number);
+}
+
+
+/*
+ * Get the server hostname (the ID as far as the topo authority is
+ * concerned) from sysinfo and return a copy to the caller.
+ *
+ * The string must be freed with topo_mod_strfree()
+ */
+char *
+x86pi_get_serverid(topo_mod_t *mod)
+{
+ int result;
+ char hostname[MAXNAMELEN];
+
+ topo_mod_dprintf(mod, "x86pi_get_serverid\n");
+
+ result = sysinfo(SI_HOSTNAME, hostname, sizeof (hostname));
+ /* Everything is freed up and it's time to return the platform-id */
+ if (result == -1) {
+ return (NULL);
+ }
+ topo_mod_dprintf(mod, "x86pi_get_serverid: hostname = %s\n", hostname);
+
+ return (topo_mod_strdup(mod, hostname));
+}
+
+
+/*
+ * Get copy of SMBIOS.
+ */
+smbios_hdl_t *
+x86pi_smb_open(topo_mod_t *mod)
+{
+ smbios_hdl_t *smb_hdl;
+ char *f = "x86pi_smb_open";
+
+ topo_mod_dprintf(mod, "%s\n", f);
+
+ smb_hdl = topo_mod_smbios(mod);
+ if (smb_hdl == NULL) {
+ topo_mod_dprintf(mod, "%s: failed to load SMBIOS\n", f);
+ return (NULL);
+ }
+
+ return (smb_hdl);
+}
+
+
+/*
+ * Go through the smbios structures looking for a type. Fill in
+ * the structure count as well as the id(s) of the struct types.
+ */
+void
+x86pi_smb_strcnt(smbios_hdl_t *shp, smbs_cnt_t *stype)
+{
+ const smb_struct_t *sp = shp->sh_structs;
+ int nstructs = shp->sh_nstructs;
+ int i, cnt;
+
+ for (i = 0, cnt = 0; i < nstructs; i++, sp++) {
+ if (sp->smbst_hdr->smbh_type == stype->type) {
+ stype->ids[cnt].node = NULL;
+ stype->ids[cnt].id = sp->smbst_hdr->smbh_hdl;
+ cnt++;
+ }
+ }
+
+ stype->count = cnt;
+}
+
+
+/*
+ * Calculate the authority information for a node. Inherit the data if
+ * possible, but always create an appropriate property group.
+ */
+int
+x86pi_set_auth(topo_mod_t *mod, x86pi_hcfmri_t *hcfmri, tnode_t *t_parent,
+ tnode_t *t_node)
+{
+ int result;
+ int err;
+ int is_chassis = 0;
+ int chassis_instance = 0;
+ nvlist_t *auth;
+ char *val = NULL;
+ char *prod = NULL;
+ char *psn = NULL;
+ char *csn = NULL;
+ char *server = NULL;
+ char *f = "x86pi_set_auth";
+
+ if (mod == NULL || t_parent == NULL || t_node == NULL) {
+ return (-1);
+ }
+
+ result = topo_pgroup_create(t_node, &auth_pgroup, &err);
+ if (result != 0 && err != ETOPO_PROP_DEFD) {
+ /*
+ * We failed to create the property group and it was not
+ * already defined. Set the err code and return failure.
+ */
+ topo_mod_seterrno(mod, err);
+ return (-1);
+ }
+
+ /* Get the authority information already available from the parent */
+ auth = topo_mod_auth(mod, t_parent);
+
+ /* Determnine if this is a chassis node and set it's instance */
+ if ((strlen(hcfmri->hc_name) == strlen(CHASSIS)) &&
+ strncmp(hcfmri->hc_name, CHASSIS, strlen(CHASSIS)) == 0) {
+ is_chassis = 1;
+ chassis_instance = hcfmri->instance;
+ }
+
+ /*
+ * Set the authority data, inheriting it if possible, but creating it
+ * if necessary.
+ */
+
+ /* product-id */
+ result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
+ FM_FMRI_AUTH_PRODUCT, &err);
+ if (result != 0 && err != ETOPO_PROP_DEFD) {
+ result = nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT,
+ &prod);
+ if (result != 0 || prod == NULL) {
+ /*
+ * No product information in the parent node or auth
+ * list. Use the product information in the hcfrmi
+ * struct.
+ */
+ prod = (char *)hcfmri->product;
+ if (prod == NULL) {
+ topo_mod_dprintf(mod, "%s: product name not "
+ "found for %s node\n", f, hcfmri->hc_name);
+ }
+ }
+
+ /*
+ * We continue even if the product information is not available
+ * to enumerate as much as possible.
+ */
+ if (prod != NULL) {
+ result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY,
+ FM_FMRI_AUTH_PRODUCT, TOPO_PROP_IMMUTABLE, prod,
+ &err);
+ if (result != 0) {
+ /* Preserve the error and continue */
+ topo_mod_seterrno(mod, err);
+ topo_mod_dprintf(mod, "%s: failed to set "
+ "property %s (%d) : %s\n", f,
+ FM_FMRI_AUTH_PRODUCT, err,
+ topo_strerror(err));
+ }
+ }
+ }
+
+ /* product-sn */
+ result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
+ FM_FMRI_AUTH_PRODUCT_SN, &err);
+ if (result != 0 && err != ETOPO_PROP_DEFD) {
+ result = nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT_SN,
+ &psn);
+ if (result != 0 || psn == NULL) {
+ /*
+ * No product-sn information in the parent node or auth
+ * list.
+ */
+ topo_mod_dprintf(mod, "%s: psn not found\n", f);
+ } else {
+ /*
+ * We continue even if the product-sn information is
+ * not available to enumerate as much as possible.
+ */
+ result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY,
+ FM_FMRI_AUTH_PRODUCT_SN, TOPO_PROP_IMMUTABLE, psn,
+ &err);
+ if (result != 0) {
+ /* Preserve the error and continue */
+ topo_mod_seterrno(mod, err);
+ topo_mod_dprintf(mod, "%s: failed to "
+ "set property %s (%d) : %s\n", f,
+ FM_FMRI_AUTH_PRODUCT_SN, err,
+ topo_strerror(err));
+ }
+ }
+ }
+
+ /* chassis-id */
+ if (is_chassis == 0 || (is_chassis == 1 && chassis_instance == 0)) {
+ /* either not a chassis node, or chassis #0 */
+ result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
+ FM_FMRI_AUTH_CHASSIS, &err);
+ } else {
+ /* chassis 'n' in a >1 chassis system */
+ result = err = -1;
+ }
+ if (result != 0 && err != ETOPO_PROP_DEFD) {
+ if (is_chassis == 0) {
+ result = nvlist_lookup_string(auth,
+ FM_FMRI_AUTH_CHASSIS, &csn);
+ if (result != 0 || csn == NULL) {
+ /*
+ * No chassis information in the parent
+ * node or auth list.
+ */
+ topo_mod_dprintf(mod,
+ "%s: csn name not found\n", f);
+ }
+ } else {
+ /*
+ * So as not to blindly set the chassis-id to
+ * chassis #0's serial number.
+ */
+ csn = val = topo_mod_strdup(mod, hcfmri->serial_number);
+ }
+
+ /*
+ * We continue even if the chassis information is not available
+ * to enumerate as much as possible.
+ */
+ if (csn != NULL) {
+ if (is_chassis == 1)
+ result = topo_prop_set_string(t_node,
+ FM_FMRI_AUTHORITY, FM_FMRI_AUTH_CHASSIS,
+ TOPO_PROP_MUTABLE, csn, &err);
+ else
+ result = topo_prop_set_string(t_node,
+ FM_FMRI_AUTHORITY, FM_FMRI_AUTH_CHASSIS,
+ TOPO_PROP_IMMUTABLE, csn, &err);
+
+ if (result != 0) {
+ /* Preserve the error and continue */
+ topo_mod_seterrno(mod, err);
+ topo_mod_dprintf(mod, "%s: failed to "
+ "set property %s (%d) : %s\n", f,
+ FM_FMRI_AUTH_CHASSIS, err,
+ topo_strerror(err));
+ }
+ }
+
+ if (val != NULL) {
+ topo_mod_strfree(mod, val);
+ val = NULL;
+ }
+ }
+
+ /* server-id */
+ result = topo_prop_inherit(t_node, FM_FMRI_AUTHORITY,
+ FM_FMRI_AUTH_SERVER, &err);
+ if (result != 0 && err != ETOPO_PROP_DEFD) {
+ result = nvlist_lookup_string(auth, FM_FMRI_AUTH_SERVER,
+ &server);
+ if (result != 0 || server == NULL) {
+ /*
+ * No server information in the parent node or auth
+ * list. Find the server information in hostname.
+ */
+ server = val = x86pi_get_serverid(mod);
+ if (server == NULL) {
+ topo_mod_dprintf(mod, "%s: server "
+ "name not found for %s node\n", f,
+ hcfmri->hc_name);
+ }
+ }
+
+ /*
+ * We continue even if the server information is not available
+ * to enumerate as much as possible.
+ */
+ if (server != NULL) {
+ result = topo_prop_set_string(t_node, FM_FMRI_AUTHORITY,
+ FM_FMRI_AUTH_SERVER, TOPO_PROP_IMMUTABLE, server,
+ &err);
+ if (result != 0) {
+ /* Preserve the error and continue */
+ topo_mod_seterrno(mod, err);
+ topo_mod_dprintf(mod, "%s: failed to "
+ "set property %s (%d) : %s\n", f,
+ FM_FMRI_AUTH_SERVER, err,
+ topo_strerror(err));
+ }
+ }
+
+ if (val != NULL)
+ topo_mod_strfree(mod, val);
+ }
+
+ nvlist_free(auth);
+
+ return (0);
+}
+
+
+/*
+ * Calculate a generic FRU for the given node. If the node is not a FRU,
+ * then inherit the FRU data from the nodes parent.
+ */
+int
+x86pi_set_frufmri(topo_mod_t *mod, x86pi_hcfmri_t *hcfmri, tnode_t *t_parent,
+ tnode_t *t_node, int flag)
+{
+ int result;
+ int err;
+
+ nvlist_t *auth = NULL;
+ nvlist_t *frufmri = NULL;
+
+ if (t_node == NULL || mod == NULL) {
+ return (-1);
+ }
+
+ /*
+ * Determine if this node is a FRU
+ */
+ if (!(flag & X86PI_ENUM_FRU)) {
+ /* This node is not a FRU. Inherit from parent and return */
+ topo_node_fru_set(t_node, NULL, 0, &result);
+ return (0);
+ }
+
+ /*
+ * This node is a FRU. Create an FMRI.
+ */
+ auth = topo_mod_auth(mod, t_parent);
+ frufmri = topo_mod_hcfmri(mod, t_parent, FM_HC_SCHEME_VERSION,
+ hcfmri->hc_name, hcfmri->instance, NULL, auth,
+ hcfmri->part_number, hcfmri->version, hcfmri->serial_number);
+ if (frufmri == NULL) {
+ topo_mod_dprintf(mod, "failed to create FRU: %s\n",
+ topo_strerror(topo_mod_errno(mod)));
+ }
+ nvlist_free(auth);
+
+ /* Set the FRU, whether NULL or not */
+ result = topo_node_fru_set(t_node, frufmri, 0, &err);
+ if (result != 0) {
+ topo_mod_seterrno(mod, err);
+ }
+ nvlist_free(frufmri);
+
+ return (result);
+}
+
+
+/*
+ * Set the label for a topo node.
+ */
+int
+x86pi_set_label(topo_mod_t *mod, const char *label, const char *name,
+ tnode_t *t_node)
+{
+ int result;
+ int err;
+
+ if (mod == NULL) {
+ return (-1);
+ }
+
+ /*
+ * Set the label for this topology node.
+ * Note that a NULL label will inherit the label from topology
+ * node's parent.
+ */
+ result = topo_node_label_set(t_node, (char *)label, &err);
+ if (result != 0) {
+ topo_mod_seterrno(mod, err);
+ topo_mod_dprintf(mod, "x86pi_set_label: failed with label %s "
+ "on %s node: %s\n", (label == NULL ? "NULL" : label),
+ name, topo_strerror(err));
+ }
+
+ return (result);
+}
+
+
+/*
+ * Calculate the system information for a node. Inherit the data if
+ * possible, but always create an appropriate property group.
+ */
+int
+x86pi_set_system(topo_mod_t *mod, tnode_t *t_node)
+{
+ int result;
+ int err;
+ struct utsname uts;
+ char isa[MAXNAMELEN];
+
+ if (mod == NULL || t_node == NULL) {
+ return (-1);
+ }
+
+ result = topo_pgroup_create(t_node, &sys_pgroup, &err);
+ if (result != 0 && err != ETOPO_PROP_DEFD) {
+ /*
+ * We failed to create the property group and it was not
+ * already defined. Set the err code and return failure.
+ */
+ topo_mod_seterrno(mod, err);
+ return (-1);
+ }
+
+ result = topo_prop_inherit(t_node, TOPO_PGROUP_SYSTEM, TOPO_PROP_ISA,
+ &err);
+ if (result != 0 && err != ETOPO_PROP_DEFD) {
+ isa[0] = '\0';
+ result = sysinfo(SI_ARCHITECTURE, isa, sizeof (isa));
+ if (result == -1) {
+ /* Preserve the error and continue */
+ topo_mod_dprintf(mod, "x86pi_set_system: failed to "
+ "read SI_ARCHITECTURE: %d\n", errno);
+ }
+ if (strnlen(isa, MAXNAMELEN) > 0) {
+ result = topo_prop_set_string(t_node,
+ TOPO_PGROUP_SYSTEM, TOPO_PROP_ISA,
+ TOPO_PROP_IMMUTABLE, isa, &err);
+ if (result != 0) {
+ /* Preserve the error and continue */
+ topo_mod_seterrno(mod, err);
+ topo_mod_dprintf(mod,
+ "x86pi_set_auth: failed to "
+ "set property %s (%d) : %s\n",
+ TOPO_PROP_ISA, err, topo_strerror(err));
+ }
+ }
+ }
+
+ result = topo_prop_inherit(t_node, TOPO_PGROUP_SYSTEM,
+ TOPO_PROP_MACHINE, &err);
+ if (result != 0 && err != ETOPO_PROP_DEFD) {
+ result = uname(&uts);
+ if (result == -1) {
+ /* Preserve the error and continue */
+ topo_mod_seterrno(mod, errno);
+ topo_mod_dprintf(mod, "x86pi_set_system: failed to "
+ "read uname: %d\n", errno);
+ }
+ if (strnlen(uts.machine, sizeof (uts.machine)) > 0) {
+ result = topo_prop_set_string(t_node,
+ TOPO_PGROUP_SYSTEM, TOPO_PROP_MACHINE,
+ TOPO_PROP_IMMUTABLE, uts.machine, &err);
+ if (result != 0) {
+ /* Preserve the error and continue */
+ topo_mod_seterrno(mod, err);
+ topo_mod_dprintf(mod,
+ "x86pi_set_auth: failed to "
+ "set property %s (%d) : %s\n",
+ TOPO_PROP_MACHINE, err, topo_strerror(err));
+ }
+ }
+ }
+
+ return (0);
+}
+
+/*
+ * All the checks for compatibility are done within the kernel where the
+ * ereport generators are. They'll determine first if there's a problem
+ * and the topo enum will follow suit. The /dev/fm ioclt returns the value
+ * of the x86gentopo_legacy kernel variable which determines if this platform
+ * will provide an x86 generic topo or legacy topo enumeration.
+ */
+/* ARGSUSED */
+int
+x86pi_check_comp(topo_mod_t *mod, smbios_hdl_t *shp)
+{
+ int rv;
+ int fd;
+ int32_t legacy;
+ nvlist_t *nvl = NULL;
+ fm_ioc_data_t fid;
+ char *ibuf = NULL, *obuf = NULL;
+ size_t insz = 0, outsz = 0;
+ char *f = "x86pi_check_comp";
+
+ /* open /dev/fm */
+ fd = open("/dev/fm", O_RDONLY);
+ if (fd < 0) {
+ topo_mod_dprintf(mod, "%s: failed to open /dev/fm.\n", f);
+ return (X86PI_NONE);
+ }
+
+ /* set up buffers and ioctl data structure */
+ outsz = FM_IOC_MAXBUFSZ;
+ obuf = topo_mod_alloc(mod, outsz);
+ if (obuf == NULL) {
+ perror("umem_alloc");
+ return (X86PI_NONE);
+ }
+
+ fid.fid_version = 1;
+ fid.fid_insz = insz;
+ fid.fid_inbuf = ibuf;
+ fid.fid_outsz = outsz;
+ fid.fid_outbuf = obuf;
+
+ /* send the ioctl to /dev/fm to retrieve legacy variable */
+ rv = ioctl(fd, FM_IOC_GENTOPO_LEGACY, &fid);
+ if (rv < 0) {
+ topo_mod_dprintf(mod, "%s: ioctl to /dev/fm failed", f);
+ perror("fm_ioctl");
+ (void) close(fd);
+ return (X86PI_NONE);
+ }
+ (void) close(fd);
+
+ (void) nvlist_unpack(fid.fid_outbuf, fid.fid_outsz, &nvl, 0);
+ (void) nvlist_lookup_int32(nvl, FM_GENTOPO_LEGACY, &legacy);
+
+ nvlist_free(nvl);
+ topo_mod_free(mod, obuf, outsz);
+
+ if (legacy == 1) {
+ /* legacy kernel variable set; will do the same */
+ return (X86PI_NONE);
+ }
+
+ /* legacy kernel variable not set; generic topo enum */
+ return (X86PI_FULL);
+}
+
+const char *
+x86pi_cleanup_smbios_str(topo_mod_t *mod, const char *begin, int str_type)
+{
+ char buf[MAXNAMELEN];
+ const char *end, *cp;
+ char *pp;
+ char c;
+ int i;
+
+ end = begin + strlen(begin);
+
+ while (begin < end && isspace(*begin))
+ begin++;
+ while (begin < end && isspace(*(end - 1)))
+ end--;
+
+ if (begin >= end)
+ return (NULL);
+
+ cp = begin;
+ for (i = 0; i < MAXNAMELEN - 1; i++) {
+ if (cp >= end)
+ break;
+ c = *cp;
+ if (str_type == LABEL) {
+ if (!isprint(c))
+ buf[i] = '-';
+ else
+ buf[i] = c;
+ } else {
+ if (c == ':' || c == '=' || c == '/' ||
+ isspace(c) || !isprint(c))
+ buf[i] = '-';
+ else
+ buf[i] = c;
+ }
+ cp++;
+ }
+ buf[i] = 0;
+
+ pp = topo_mod_strdup(mod, buf);
+
+ if (str_type == LABEL)
+ topo_mod_strfree(mod, (char *)begin);
+
+ return (pp);
+}
diff --git a/usr/src/lib/libsmbios/common/mapfile-vers b/usr/src/lib/libsmbios/common/mapfile-vers
index a784236eb1..0fc59e6210 100644
--- a/usr/src/lib/libsmbios/common/mapfile-vers
+++ b/usr/src/lib/libsmbios/common/mapfile-vers
@@ -81,26 +81,32 @@ SUNWprivate_1.1 {
smbios_info_cache;
smbios_info_chassis;
smbios_info_common;
+ smbios_info_contains;
smbios_info_eventlog;
smbios_info_hwsec;
smbios_info_ipmi;
smbios_info_lang;
smbios_info_memarray;
+ smbios_info_extmemarray;
smbios_info_memarrmap;
smbios_info_memdevice;
+ smbios_info_extmemdevice;
smbios_info_memdevmap;
smbios_info_obdevs;
smbios_info_port;
smbios_info_processor;
+ smbios_info_extprocessor;
smbios_info_slot;
smbios_info_smbios;
smbios_info_strtab;
smbios_info_system;
+ smbios_info_pciexrc;
smbios_ipmi_flag_desc;
smbios_ipmi_flag_name;
smbios_ipmi_type_desc;
smbios_iter;
smbios_lookup_id;
+ smbios_lookup_type;
smbios_memarray_ecc_desc;
smbios_memarray_loc_desc;
smbios_memarray_use_desc;
diff --git a/usr/src/pkgdefs/SUNWfmd/prototype_i386 b/usr/src/pkgdefs/SUNWfmd/prototype_i386
index c77b21552d..764a92f156 100644
--- a/usr/src/pkgdefs/SUNWfmd/prototype_i386
+++ b/usr/src/pkgdefs/SUNWfmd/prototype_i386
@@ -82,11 +82,13 @@ d none usr/platform/i86pc/lib/fm/topo/plugins 755 root bin
f none usr/platform/i86pc/lib/fm/topo/plugins/chip.so 555 root bin
f none usr/platform/i86pc/lib/fm/topo/plugins/hostbridge.so 555 root bin
f none usr/platform/i86pc/lib/fm/topo/plugins/pcibus.so 555 root bin
+f none usr/platform/i86pc/lib/fm/topo/plugins/x86pi.so 555 root bin
d none usr/platform/i86pc/lib/fm/topo/maps 755 root bin
f none usr/platform/i86pc/lib/fm/topo/maps/chassis-hc-topology.xml 444 root bin
f none usr/platform/i86pc/lib/fm/topo/maps/chip-hc-topology.xml 444 root bin
f none usr/platform/i86pc/lib/fm/topo/maps/fan-hc-topology.xml 444 root bin
f none usr/platform/i86pc/lib/fm/topo/maps/i86pc-hc-topology.xml 444 root bin
+f none usr/platform/i86pc/lib/fm/topo/maps/i86pc-legacy-hc-topology.xml 444 root bin
f none usr/platform/i86pc/lib/fm/topo/maps/psu-hc-topology.xml 444 root bin
f none usr/platform/i86pc/lib/fm/topo/maps/Sun-Fire-X4200-M2-disk-hc-topology.xml 444 root bin
f none usr/platform/i86pc/lib/fm/topo/maps/Sun-Fire-X4200-Server-disk-hc-topology.xml 444 root bin
diff --git a/usr/src/uts/common/io/devfm.c b/usr/src/uts/common/io/devfm.c
index 7b72a5ed07..09115d7d35 100644
--- a/usr/src/uts/common/io/devfm.c
+++ b/usr/src/uts/common/io/devfm.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -44,6 +44,7 @@ extern int fm_get_paddr(nvlist_t *, uint64_t *);
#if defined(__x86)
extern int fm_ioctl_physcpu_info(int, nvlist_t *, nvlist_t **);
extern int fm_ioctl_cpu_retire(int, nvlist_t *, nvlist_t **);
+extern int fm_ioctl_gentopo_legacy(int, nvlist_t *, nvlist_t **);
#endif /* __x86 */
static int fm_ioctl_versions(int, nvlist_t *, nvlist_t **);
@@ -73,6 +74,7 @@ static const fm_vers_t fm_versions[] = {
{ FM_PAGE_OP_VERSION, 1 },
{ FM_CPU_OP_VERSION, 1 },
{ FM_CPU_INFO_VERSION, 1 },
+ { FM_TOPO_LEGACY_VERSION, 1 },
{ NULL, 0 }
};
@@ -93,6 +95,8 @@ static const fm_subr_t fm_subrs[] = {
fm_ioctl_cpu_retire },
{ FM_IOC_CPU_UNRETIRE, B_TRUE, FM_CPU_OP_VERSION,
fm_ioctl_cpu_retire },
+ { FM_IOC_GENTOPO_LEGACY, B_FALSE, FM_TOPO_LEGACY_VERSION,
+ fm_ioctl_gentopo_legacy },
#endif /* __x86 */
{ -1, B_FALSE, NULL, NULL },
};
diff --git a/usr/src/uts/common/os/fm.c b/usr/src/uts/common/os/fm.c
index c78c731d2c..c5ad2c3991 100644
--- a/usr/src/uts/common/os/fm.c
+++ b/usr/src/uts/common/os/fm.c
@@ -1269,3 +1269,102 @@ print_msg_hwerr(ctid_t ct_id, proc_t *p)
uprintf("Killed process %d (%s) in contract id %d "
"due to hardware error\n", p->p_pid, p->p_user.u_comm, ct_id);
}
+
+void
+fm_fmri_hc_create(nvlist_t *fmri, int version, const nvlist_t *auth,
+ nvlist_t *snvl, nvlist_t *bboard, int npairs, ...)
+{
+ nv_alloc_t *nva = nvlist_lookup_nv_alloc(fmri);
+ nvlist_t *pairs[HC_MAXPAIRS];
+ nvlist_t **hcl;
+ uint_t n;
+ int i, j;
+ va_list ap;
+ char *hcname, *hcid;
+
+ if (!fm_fmri_hc_set_common(fmri, version, auth))
+ return;
+
+ /*
+ * copy the bboard nvpairs to the pairs array
+ */
+ if (nvlist_lookup_nvlist_array(bboard, FM_FMRI_HC_LIST, &hcl, &n)
+ != 0) {
+ atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
+ return;
+ }
+
+ for (i = 0; i < n; i++) {
+ if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME,
+ &hcname) != 0) {
+ atomic_add_64(
+ &erpt_kstat_data.fmri_set_failed.value.ui64, 1);
+ return;
+ }
+ if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &hcid) != 0) {
+ atomic_add_64(
+ &erpt_kstat_data.fmri_set_failed.value.ui64, 1);
+ return;
+ }
+
+ pairs[i] = fm_nvlist_create(nva);
+ if (nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, hcname) != 0 ||
+ nvlist_add_string(pairs[i], FM_FMRI_HC_ID, hcid) != 0) {
+ for (j = 0; j <= i; j++) {
+ if (pairs[j] != NULL)
+ fm_nvlist_destroy(pairs[j],
+ FM_NVA_RETAIN);
+ }
+ atomic_add_64(
+ &erpt_kstat_data.fmri_set_failed.value.ui64, 1);
+ return;
+ }
+ }
+
+ /*
+ * create the pairs from passed in pairs
+ */
+ npairs = MIN(npairs, HC_MAXPAIRS);
+
+ va_start(ap, npairs);
+ for (i = n; i < npairs + n; i++) {
+ const char *name = va_arg(ap, const char *);
+ uint32_t id = va_arg(ap, uint32_t);
+ char idstr[11];
+ (void) snprintf(idstr, sizeof (idstr), "%u", id);
+ pairs[i] = fm_nvlist_create(nva);
+ if (nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, name) != 0 ||
+ nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr) != 0) {
+ for (j = 0; j <= i; j++) {
+ if (pairs[j] != NULL)
+ fm_nvlist_destroy(pairs[j],
+ FM_NVA_RETAIN);
+ }
+ atomic_add_64(
+ &erpt_kstat_data.fmri_set_failed.value.ui64, 1);
+ return;
+ }
+ }
+ va_end(ap);
+
+ /*
+ * Create the fmri hc list
+ */
+ if (nvlist_add_nvlist_array(fmri, FM_FMRI_HC_LIST, pairs,
+ npairs + n) != 0) {
+ atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
+ return;
+ }
+
+ for (i = 0; i < npairs + n; i++) {
+ fm_nvlist_destroy(pairs[i], FM_NVA_RETAIN);
+ }
+
+ if (snvl != NULL) {
+ if (nvlist_add_nvlist(fmri, FM_FMRI_HC_SPECIFIC, snvl) != 0) {
+ atomic_add_64(
+ &erpt_kstat_data.fmri_set_failed.value.ui64, 1);
+ return;
+ }
+ }
+}
diff --git a/usr/src/uts/common/sys/devfm.h b/usr/src/uts/common/sys/devfm.h
index e9ad95b39f..e42e259cba 100644
--- a/usr/src/uts/common/sys/devfm.h
+++ b/usr/src/uts/common/sys/devfm.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -40,6 +40,7 @@ extern "C" {
#define FM_PAGE_OP_VERSION "page-operation-version"
#define FM_CPU_OP_VERSION "cpu-operation-version"
#define FM_CPU_INFO_VERSION "cpu-info-version"
+#define FM_TOPO_LEGACY_VERSION "topo-legacy-version"
/*
* FMA driver ioctl interfaces
@@ -55,6 +56,7 @@ extern "C" {
#define FM_IOC_CPU_RETIRE (FM_IOC | 6)
#define FM_IOC_CPU_STATUS (FM_IOC | 7)
#define FM_IOC_CPU_UNRETIRE (FM_IOC | 8)
+#define FM_IOC_GENTOPO_LEGACY (FM_IOC | 9)
#endif /* __x86 */
/*
@@ -87,6 +89,7 @@ typedef struct fm_ioc_data32 {
#define FM_CPU_RETIRE_CORE_ID "core_id"
#define FM_CPU_RETIRE_STRAND_ID "strand_id"
#define FM_CPU_RETIRE_OLDSTATUS "oldstatus"
+#define FM_GENTOPO_LEGACY "gentopolegacy"
/*
* Properties set by FM_PHYSCPU_INFO
@@ -95,9 +98,21 @@ typedef struct fm_ioc_data32 {
#define FM_PHYSCPU_INFO_FAMILY "family"
#define FM_PHYSCPU_INFO_MODEL "model"
#define FM_PHYSCPU_INFO_STEPPING "stepping"
+
+/*
+ * When Multi-Chip-Module(MCM) support is added
+ * chip_id should map to the processor package
+ * and not the die in the processor package.
+ * This is for FMA; kernel's perception of
+ * chip_id could differ for MCM.
+ */
#define FM_PHYSCPU_INFO_CHIP_ID "chip_id"
+
#define FM_PHYSCPU_INFO_CORE_ID "core_id"
#define FM_PHYSCPU_INFO_STRAND_ID "strand_id"
+#define FM_PHYSCPU_INFO_STRAND_APICID "strand_initial_apicid"
+#define FM_PHYSCPU_INFO_SMBIOS_ID "smbios_id"
+#define FM_PHYSCPU_INFO_CHIP_ROOTS "chip_roots"
#define FM_PHYSCPU_INFO_CHIP_REV "chip_rev"
#define FM_PHYSCPU_INFO_SOCKET_TYPE "socket_type"
#define FM_PHYSCPU_INFO_CPU_ID "cpuid"
diff --git a/usr/src/uts/common/sys/fm/protocol.h b/usr/src/uts/common/sys/fm/protocol.h
index 4c19a47318..37f7e92db2 100644
--- a/usr/src/uts/common/sys/fm/protocol.h
+++ b/usr/src/uts/common/sys/fm/protocol.h
@@ -323,6 +323,8 @@ extern void fm_fmri_mem_set(nvlist_t *, int, const nvlist_t *, const char *,
extern void fm_authority_set(nvlist_t *, int, const char *, const char *,
const char *, const char *);
extern void fm_fmri_zfs_set(nvlist_t *, int, uint64_t, uint64_t);
+extern void fm_fmri_hc_create(nvlist_t *, int, const nvlist_t *, nvlist_t *,
+ nvlist_t *, int, ...);
extern uint64_t fm_ena_increment(uint64_t);
extern uint64_t fm_ena_generate(uint64_t, uchar_t);
diff --git a/usr/src/uts/common/sys/smbios.h b/usr/src/uts/common/sys/smbios.h
index 187ec2c63f..a21dceb5e3 100644
--- a/usr/src/uts/common/sys/smbios.h
+++ b/usr/src/uts/common/sys/smbios.h
@@ -126,6 +126,10 @@ typedef struct smbios_entry {
#define SMB_TYPE_EOT 127 /* end of table */
#define SMB_TYPE_OEM_LO 128 /* start of OEM-specific type range */
+#define SUN_OEM_EXT_PROCESSOR 132 /* processor extended info */
+#define SUN_OEM_PCIEXRC 138 /* PCIE RootComplex/RootPort info */
+#define SUN_OEM_EXT_MEMARRAY 144 /* phys memory array extended info */
+#define SUN_OEM_EXT_MEMDEVICE 145 /* memory device extended info */
#define SMB_TYPE_OEM_HI 256 /* end of OEM-specific type range */
/*
@@ -160,6 +164,10 @@ typedef struct smbios_version {
uint8_t smbv_minor; /* version minor number */
} smbios_version_t;
+#define SMB_CONT_BYTE 1 /* contained elements are byte size */
+#define SMB_CONT_WORD 2 /* contained elements are word size */
+#define SMB_CONT_MAX 255 /* maximum contained objects */
+
/*
* SMBIOS Bios Information. See DSP0134 Section 3.3.1 for more information.
* smbb_romsize is converted from the implementation format into bytes.
@@ -261,6 +269,7 @@ typedef struct smbios_bboard {
id_t smbb_chassis; /* chassis containing this board */
uint8_t smbb_flags; /* flags (see below) */
uint8_t smbb_type; /* board type (see below) */
+ uint8_t smbb_contn; /* number of contained object hdls */
} smbios_bboard_t;
#define SMB_BBFL_MOTHERBOARD 0x01 /* board is a motherboard */
@@ -286,8 +295,6 @@ typedef struct smbios_bboard {
/*
* SMBIOS Chassis description. See DSP0134 Section 3.3.4 for more information.
* We move the lock bit of the type field into smbc_lock for easier processing.
- * NOTE: We do not currently export the contained element data for each chassis
- * as this seems useless: see DSP0134 3.3.4.4. It can be added if necessary.
*/
typedef struct smbios_chassis {
uint32_t smbc_oemdata; /* OEM-specific data */
@@ -299,7 +306,8 @@ typedef struct smbios_chassis {
uint8_t smbc_security; /* security status */
uint8_t smbc_uheight; /* enclosure height in U's */
uint8_t smbc_cords; /* number of power cords */
- uint8_t smbc_elems; /* number of element records */
+ uint8_t smbc_elems; /* number of element records (n) */
+ uint8_t smbc_elemlen; /* length of contained element (m) */
} smbios_chassis_t;
#define SMB_CHT_OTHER 0x01 /* other */
@@ -1071,6 +1079,43 @@ typedef struct smbios_ipmi {
#define SMB_IPMI_F_INTREDGE 0x08 /* intr is edge triggered (else lvl) */
/*
+ * SMBIOS OEM-specific (Type 132) Processor Extended Information.
+ */
+typedef struct smbios_processor_ext {
+ uint16_t smbpe_processor; /* extending processor handle */
+ uint8_t smbpe_fru; /* FRU indicaor */
+ uint8_t smbpe_n; /* number of APIC IDs */
+ uint16_t *smbpe_apicid; /* strand Inital APIC IDs */
+} smbios_processor_ext_t;
+
+/*
+ * SMBIOS OEM-specific (Type 138) PCI-Express RC/RP Information.
+ */
+typedef struct smbios_pciexrc {
+ uint16_t smbpcie_bb; /* base board handle */
+ uint16_t smbpcie_bdf; /* Bus/Dev/Funct (PCI) */
+} smbios_pciexrc_t;
+
+/*
+ * SMBIOS OEM-specific (Type 144) Memory Array Extended Information.
+ */
+typedef struct smbios_memarray_ext {
+ uint16_t smbmae_ma; /* memory array handle */
+ uint16_t smbmae_comp; /* component parent handle */
+ uint16_t smbmae_bdf; /* Bus/Dev/Funct (PCI) */
+} smbios_memarray_ext_t;
+
+/*
+ * SMBIOS OEM-specific (Type 145) Memory Device Extended Information.
+ */
+typedef struct smbios_memdevice_ext {
+ uint16_t smbmdeve_md; /* memory device handle */
+ uint8_t smbmdeve_drch; /* DRAM channel */
+ uint8_t smbmdeve_ncs; /* number of chip selects */
+ uint8_t *smbmdeve_cs; /* array of chip select numbers */
+} smbios_memdevice_ext_t;
+
+/*
* SMBIOS Interfaces. An SMBIOS image can be opened by either providing a file
* pathname, device pathname, file descriptor, or raw memory buffer. Once an
* image is opened the functions below can be used to iterate over the various
@@ -1123,15 +1168,19 @@ extern int smbios_errno(smbios_hdl_t *);
extern const char *smbios_errmsg(int);
extern int smbios_lookup_id(smbios_hdl_t *, id_t, smbios_struct_t *);
+extern int smbios_lookup_type(smbios_hdl_t *, uint_t, smbios_struct_t *);
extern int smbios_iter(smbios_hdl_t *, smbios_struct_f *, void *);
extern void smbios_info_smbios(smbios_hdl_t *, smbios_entry_t *);
extern int smbios_info_common(smbios_hdl_t *, id_t, smbios_info_t *);
+extern int smbios_info_contains(smbios_hdl_t *, id_t, uint_t, id_t *);
extern id_t smbios_info_bios(smbios_hdl_t *, smbios_bios_t *);
extern id_t smbios_info_system(smbios_hdl_t *, smbios_system_t *);
extern int smbios_info_bboard(smbios_hdl_t *, id_t, smbios_bboard_t *);
extern int smbios_info_chassis(smbios_hdl_t *, id_t, smbios_chassis_t *);
extern int smbios_info_processor(smbios_hdl_t *, id_t, smbios_processor_t *);
+extern int smbios_info_extprocessor(smbios_hdl_t *, id_t,
+ smbios_processor_ext_t *);
extern int smbios_info_cache(smbios_hdl_t *, id_t, smbios_cache_t *);
extern int smbios_info_port(smbios_hdl_t *, id_t, smbios_port_t *);
extern int smbios_info_slot(smbios_hdl_t *, id_t, smbios_slot_t *);
@@ -1140,12 +1189,17 @@ extern int smbios_info_strtab(smbios_hdl_t *, id_t, int, const char *[]);
extern id_t smbios_info_lang(smbios_hdl_t *, smbios_lang_t *);
extern id_t smbios_info_eventlog(smbios_hdl_t *, smbios_evlog_t *);
extern int smbios_info_memarray(smbios_hdl_t *, id_t, smbios_memarray_t *);
+extern int smbios_info_extmemarray(smbios_hdl_t *, id_t,
+ smbios_memarray_ext_t *);
extern int smbios_info_memarrmap(smbios_hdl_t *, id_t, smbios_memarrmap_t *);
extern int smbios_info_memdevice(smbios_hdl_t *, id_t, smbios_memdevice_t *);
+extern int smbios_info_extmemdevice(smbios_hdl_t *, id_t,
+ smbios_memdevice_ext_t *);
extern int smbios_info_memdevmap(smbios_hdl_t *, id_t, smbios_memdevmap_t *);
extern id_t smbios_info_hwsec(smbios_hdl_t *, smbios_hwsec_t *);
extern id_t smbios_info_boot(smbios_hdl_t *, smbios_boot_t *);
extern id_t smbios_info_ipmi(smbios_hdl_t *, smbios_ipmi_t *);
+extern int smbios_info_pciexrc(smbios_hdl_t *, id_t, smbios_pciexrc_t *);
extern const char *smbios_psn(smbios_hdl_t *);
extern const char *smbios_csn(smbios_hdl_t *);
diff --git a/usr/src/uts/common/sys/smbios_impl.h b/usr/src/uts/common/sys/smbios_impl.h
index 3b87012f74..b1ac86b1b5 100644
--- a/usr/src/uts/common/sys/smbios_impl.h
+++ b/usr/src/uts/common/sys/smbios_impl.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -36,8 +35,6 @@
#ifndef _SYS_SMBIOS_IMPL_H
#define _SYS_SMBIOS_IMPL_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/smbios.h>
#include <sys/sysmacros.h>
@@ -360,6 +357,35 @@ typedef struct smb_powersup {
uint16_t smbpsup_iprobe; /* current probe handle */
} smb_powersup_t;
+typedef struct smb_processor_ext {
+ smb_header_t smbpre_hdr; /* structure header */
+ uint16_t smbpre_processor; /* processor handle */
+ uint8_t smbpre_fru; /* FRU indicator */
+ uint8_t smbpre_n; /* number of APIC IDs */
+ uint16_t smbpre_apicid[1]; /* strand initial apic id */
+} smb_processor_ext_t;
+
+typedef struct smb_pciexrc {
+ smb_header_t smbpciexrc_hdr; /* structure header */
+ uint16_t smbpciexrc_bboard; /* base board handle */
+ uint16_t smbpciexrc_bdf; /* PCI Bus/Dev/Func */
+} smb_pciexrc_t;
+
+typedef struct smb_memarray_ext {
+ smb_header_t smbmarre_hdr; /* structure header */
+ uint16_t smbmarre_ma; /* memory array handle */
+ uint16_t smbmarre_component; /* component parent handle */
+ uint16_t smbmarre_bdf; /* PCI bus/dev/funct */
+} smb_memarray_ext_t;
+
+typedef struct smb_memdevice_ext {
+ smb_header_t smbmdeve_hdr; /* structure header */
+ uint16_t smbmdeve_mdev; /* memory device handle */
+ uint8_t smbmdeve_dchan; /* DRAM channel */
+ uint8_t smbmdeve_ncs; /* number of chip select */
+ uint8_t smbmdeve_cs[1]; /* chip selects */
+} smb_memdevice_ext_t;
+
#pragma pack()
typedef struct smb_struct {
diff --git a/usr/src/uts/i86pc/cpu/amd_opteron/ao_mca.c b/usr/src/uts/i86pc/cpu/amd_opteron/ao_mca.c
index ae5e5bcff4..52e578af8f 100644
--- a/usr/src/uts/i86pc/cpu/amd_opteron/ao_mca.c
+++ b/usr/src/uts/i86pc/cpu/amd_opteron/ao_mca.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -48,6 +48,7 @@
#include <sys/fm/util.h>
#include <sys/fm/protocol.h>
#include <sys/fm/cpu/AMD.h>
+#include <sys/fm/smb/fmsmb.h>
#include <sys/acpi/acpi.h>
#include <sys/acpi/acpi_pci.h>
#include <sys/acpica.h>
@@ -60,6 +61,8 @@
int ao_mca_smi_disable = 1; /* attempt to disable SMI polling */
+extern int x86gentopo_legacy; /* x86 generic topology support */
+
struct ao_ctl_init {
uint32_t ctl_revmask; /* rev(s) to which this applies */
uint64_t ctl_bits; /* mca ctl reg bitmask to set */
@@ -617,9 +620,11 @@ ao_ereport_synd(ao_ms_data_t *ao, uint64_t status, uint_t *typep,
}
static nvlist_t *
-ao_ereport_create_resource_elem(nv_alloc_t *nva, mc_unum_t *unump, int dimmnum)
+ao_ereport_create_resource_elem(cmi_hdl_t hdl, nv_alloc_t *nva,
+ mc_unum_t *unump, int dimmnum)
{
nvlist_t *nvl, *snvl;
+ nvlist_t *board_list = NULL;
if ((nvl = fm_nvlist_create(nva)) == NULL) /* freed by caller */
return (NULL);
@@ -632,12 +637,31 @@ ao_ereport_create_resource_elem(nv_alloc_t *nva, mc_unum_t *unump, int dimmnum)
(void) nvlist_add_uint64(snvl, FM_FMRI_HC_SPECIFIC_OFFSET,
unump->unum_offset);
- fm_fmri_hc_set(nvl, FM_HC_SCHEME_VERSION, NULL, snvl, 5,
- "motherboard", unump->unum_board,
- "chip", unump->unum_chip,
- "memory-controller", unump->unum_mc,
- "dimm", unump->unum_dimms[dimmnum],
- "rank", unump->unum_rank);
+ if (!x86gentopo_legacy) {
+ board_list = cmi_hdl_smb_bboard(hdl);
+
+ if (board_list == NULL) {
+ fm_nvlist_destroy(nvl,
+ nva ? FM_NVA_RETAIN : FM_NVA_FREE);
+ fm_nvlist_destroy(snvl,
+ nva ? FM_NVA_RETAIN : FM_NVA_FREE);
+ return (NULL);
+ }
+
+ fm_fmri_hc_create(nvl, FM_HC_SCHEME_VERSION, NULL, snvl,
+ board_list, 4,
+ "chip", cmi_hdl_smb_chipid(hdl),
+ "memory-controller", unump->unum_mc,
+ "dimm", unump->unum_dimms[dimmnum],
+ "rank", unump->unum_rank);
+ } else {
+ fm_fmri_hc_set(nvl, FM_HC_SCHEME_VERSION, NULL, snvl, 5,
+ "motherboard", unump->unum_board,
+ "chip", unump->unum_chip,
+ "memory-controller", unump->unum_mc,
+ "dimm", unump->unum_dimms[dimmnum],
+ "rank", unump->unum_rank);
+ }
fm_nvlist_destroy(snvl, nva ? FM_NVA_RETAIN : FM_NVA_FREE);
@@ -645,7 +669,8 @@ ao_ereport_create_resource_elem(nv_alloc_t *nva, mc_unum_t *unump, int dimmnum)
}
static void
-ao_ereport_add_resource(nvlist_t *payload, nv_alloc_t *nva, mc_unum_t *unump)
+ao_ereport_add_resource(cmi_hdl_t hdl, nvlist_t *payload, nv_alloc_t *nva,
+ mc_unum_t *unump)
{
nvlist_t *elems[MC_UNUM_NDIMM];
@@ -656,7 +681,7 @@ ao_ereport_add_resource(nvlist_t *payload, nv_alloc_t *nva, mc_unum_t *unump)
if (unump->unum_dimms[i] == MC_INVALNUM)
break;
- if ((elems[nelems] = ao_ereport_create_resource_elem(nva,
+ if ((elems[nelems] = ao_ereport_create_resource_elem(hdl, nva,
unump, i)) == NULL)
break;
@@ -711,7 +736,7 @@ ao_ms_ereport_add_logout(cmi_hdl_t hdl, nvlist_t *ereport,
cmi_mc_patounum(addr, aed->aed_addrvalid_hi,
aed->aed_addrvalid_lo, synd, syndtype, &unum) ==
CMI_SUCCESS)
- ao_ereport_add_resource(ereport, nva, &unum);
+ ao_ereport_add_resource(hdl, ereport, nva, &unum);
}
}
diff --git a/usr/src/uts/i86pc/cpu/authenticamd/authamd_main.c b/usr/src/uts/i86pc/cpu/authenticamd/authamd_main.c
index ebcf63ab40..73ccd6d8e1 100644
--- a/usr/src/uts/i86pc/cpu/authenticamd/authamd_main.c
+++ b/usr/src/uts/i86pc/cpu/authenticamd/authamd_main.c
@@ -44,6 +44,8 @@
#include <sys/mc_amd.h>
#include <sys/fm/protocol.h>
#include <sys/fm/cpu/GENAMD.h>
+#include <sys/fm/smb/fmsmb.h>
+#include <sys/fm/util.h>
#include <sys/nvpair.h>
#include <sys/controlregs.h>
#include <sys/pghw.h>
@@ -53,6 +55,8 @@
#include "authamd.h"
+extern int x86gentopo_legacy; /* x86 generic topo support */
+
int authamd_ms_support_disable = 0;
#define AUTHAMD_F_REVS_BCDE \
@@ -982,6 +986,7 @@ authamd_ereport_add_resource(cmi_hdl_t hdl, authamd_data_t *authamd,
nvlist_t *nvl;
int nelems = 0;
int i, chan, cs;
+ nvlist_t *board_list = NULL;
if ((msl = mslogout) == NULL)
return;
@@ -997,12 +1002,25 @@ authamd_ereport_add_resource(cmi_hdl_t hdl, authamd_data_t *authamd,
elems[nelems] = nvl;
counts[nelems++] = msl->aal_eccerrcnt[chan][cs];
- fm_fmri_hc_set(nvl, FM_HC_SCHEME_VERSION, NULL, NULL, 5,
- "motherboard", 0,
- "chip", authamd->amd_shared->acs_chipid,
- "memory-controller", 0,
- "dram-channel", chan,
- "chip-select", cs);
+ if (!x86gentopo_legacy) {
+ board_list = cmi_hdl_smb_bboard(hdl);
+ if (board_list == NULL)
+ continue;
+ fm_fmri_hc_create(nvl, FM_HC_SCHEME_VERSION,
+ NULL, NULL, board_list, 4,
+ "chip", cmi_hdl_smb_chipid(hdl),
+ "memory-controller", 0,
+ "dram-channel", chan,
+ "chip-select", cs);
+ } else {
+ fm_fmri_hc_set(nvl, FM_HC_SCHEME_VERSION,
+ NULL, NULL, 5,
+ "motherboard", 0,
+ "chip", authamd->amd_shared->acs_chipid,
+ "memory-controller", 0,
+ "dram-channel", chan,
+ "chip-select", cs);
+ }
}
}
diff --git a/usr/src/uts/i86pc/cpu/generic_cpu/gcpu_mca.c b/usr/src/uts/i86pc/cpu/generic_cpu/gcpu_mca.c
index 2e206d47a4..b6c55d8123 100644
--- a/usr/src/uts/i86pc/cpu/generic_cpu/gcpu_mca.c
+++ b/usr/src/uts/i86pc/cpu/generic_cpu/gcpu_mca.c
@@ -43,11 +43,14 @@
#include <sys/errorq.h>
#include <sys/mca_x86.h>
#include <sys/fm/cpu/GMCA.h>
+#include <sys/fm/smb/fmsmb.h>
#include <sys/sysevent.h>
#include <sys/ontrap.h>
#include "gcpu.h"
+extern int x86gentopo_legacy; /* x86 generic topology support */
+
/*
* Clear to log telemetry found at initialization. While processor docs
* say you should process this telemetry on all but Intel family 0x6
@@ -501,16 +504,28 @@ gcpu_erpt_clsfmt(const char *fmt, char *buf, size_t buflen, uint64_t status,
static nvlist_t *
gcpu_fmri_create(cmi_hdl_t hdl, nv_alloc_t *nva)
{
- nvlist_t *nvl;
+ nvlist_t *nvl, *fmri;
if ((nvl = fm_nvlist_create(nva)) == NULL)
return (NULL);
- fm_fmri_hc_set(nvl, FM_HC_SCHEME_VERSION, NULL, NULL, 4,
- "motherboard", 0,
- "chip", cmi_hdl_chipid(hdl),
- "core", cmi_hdl_coreid(hdl),
- "strand", cmi_hdl_strandid(hdl));
+ if (!x86gentopo_legacy) {
+ fmri = cmi_hdl_smb_bboard(hdl);
+ if (fmri == NULL)
+ return (NULL);
+
+ fm_fmri_hc_create(nvl, FM_HC_SCHEME_VERSION,
+ NULL, NULL, fmri, 3,
+ "chip", cmi_hdl_smb_chipid(hdl),
+ "core", cmi_hdl_coreid(hdl),
+ "strand", cmi_hdl_strandid(hdl));
+ } else {
+ fm_fmri_hc_set(nvl, FM_HC_SCHEME_VERSION, NULL, NULL, 4,
+ "motherboard", 0,
+ "chip", cmi_hdl_chipid(hdl),
+ "core", cmi_hdl_coreid(hdl),
+ "strand", cmi_hdl_strandid(hdl));
+ }
return (nvl);
}
diff --git a/usr/src/uts/i86pc/cpu/genuineintel/gintel_main.c b/usr/src/uts/i86pc/cpu/genuineintel/gintel_main.c
index bb70237eb6..44ed9e6d5d 100644
--- a/usr/src/uts/i86pc/cpu/genuineintel/gintel_main.c
+++ b/usr/src/uts/i86pc/cpu/genuineintel/gintel_main.c
@@ -38,6 +38,10 @@
#include <sys/mc_intel.h>
#include <sys/pci_cfgspace.h>
#include <sys/fm/protocol.h>
+#include <sys/fm/util.h>
+#include <sys/fm/smb/fmsmb.h>
+
+extern int x86gentopo_legacy;
int gintel_ms_support_disable = 0;
int gintel_error_action_return = 0;
@@ -249,6 +253,36 @@ gintel_ereport_class(cmi_hdl_t hdl, cms_cookie_t mscookie,
}
}
+static nvlist_t *
+gintel_gentopo_ereport_detector(cmi_hdl_t hdl, cms_cookie_t mscookie,
+ nv_alloc_t *nva)
+{
+ nvlist_t *nvl = (nvlist_t *)NULL;
+ nvlist_t *board_list = (nvlist_t *)NULL;
+
+ if (mscookie) {
+ board_list = cmi_hdl_smb_bboard(hdl);
+
+ if (board_list == NULL)
+ return (NULL);
+
+ if ((nvl = fm_nvlist_create(nva)) == NULL)
+ return (NULL);
+
+ if ((uintptr_t)mscookie & GINTEL_ERROR_QUICKPATH) {
+ fm_fmri_hc_create(nvl, FM_HC_SCHEME_VERSION,
+ NULL, NULL, board_list, 1,
+ "chip", cmi_hdl_smb_chipid(hdl));
+ } else {
+ fm_fmri_hc_create(nvl, FM_HC_SCHEME_VERSION,
+ NULL, NULL, board_list, 2,
+ "chip", cmi_hdl_smb_chipid(hdl),
+ "memory-controller", 0);
+ }
+ }
+ return (nvl);
+}
+
/*ARGSUSED*/
nvlist_t *
gintel_ereport_detector(cmi_hdl_t hdl, int bankno, cms_cookie_t mscookie,
@@ -256,6 +290,11 @@ gintel_ereport_detector(cmi_hdl_t hdl, int bankno, cms_cookie_t mscookie,
{
nvlist_t *nvl = (nvlist_t *)NULL;
+ if (!x86gentopo_legacy) {
+ nvl = gintel_gentopo_ereport_detector(hdl, mscookie, nva);
+ return (nvl);
+ }
+
if (mscookie) {
if ((nvl = fm_nvlist_create(nva)) == NULL)
return (NULL);
@@ -274,6 +313,62 @@ gintel_ereport_detector(cmi_hdl_t hdl, int bankno, cms_cookie_t mscookie,
}
static nvlist_t *
+gintel_gentopo_ereport_create_resource_elem(cmi_hdl_t hdl, nv_alloc_t *nva,
+ mc_unum_t *unump)
+{
+ nvlist_t *nvl, *snvl;
+ nvlist_t *board_list = NULL;
+
+ board_list = cmi_hdl_smb_bboard(hdl);
+ if (board_list == NULL) {
+ return (NULL);
+ }
+
+ if ((nvl = fm_nvlist_create(nva)) == NULL) /* freed by caller */
+ return (NULL);
+
+ if ((snvl = fm_nvlist_create(nva)) == NULL) {
+ fm_nvlist_destroy(nvl, nva ? FM_NVA_RETAIN : FM_NVA_FREE);
+ return (NULL);
+ }
+
+ (void) nvlist_add_uint64(snvl, FM_FMRI_HC_SPECIFIC_OFFSET,
+ unump->unum_offset);
+
+ if (unump->unum_chan == -1) {
+ fm_fmri_hc_create(nvl, FM_HC_SCHEME_VERSION, NULL, snvl,
+ board_list, 2,
+ "chip", cmi_hdl_smb_chipid(hdl),
+ "memory-controller", unump->unum_mc);
+ } else if (unump->unum_cs == -1) {
+ fm_fmri_hc_create(nvl, FM_HC_SCHEME_VERSION, NULL, snvl,
+ board_list, 3,
+ "chip", cmi_hdl_smb_chipid(hdl),
+ "memory-controller", unump->unum_mc,
+ "dram-channel", unump->unum_chan);
+ } else if (unump->unum_rank == -1) {
+ fm_fmri_hc_create(nvl, FM_HC_SCHEME_VERSION, NULL, snvl,
+ board_list, 4,
+ "chip", cmi_hdl_smb_chipid(hdl),
+ "memory-controller", unump->unum_mc,
+ "dram-channel", unump->unum_chan,
+ "dimm", unump->unum_cs);
+ } else {
+ fm_fmri_hc_create(nvl, FM_HC_SCHEME_VERSION, NULL, snvl,
+ board_list, 5,
+ "chip", cmi_hdl_smb_chipid(hdl),
+ "memory-controller", unump->unum_mc,
+ "dram-channel", unump->unum_chan,
+ "dimm", unump->unum_cs,
+ "rank", unump->unum_rank);
+ }
+
+ fm_nvlist_destroy(snvl, nva ? FM_NVA_RETAIN : FM_NVA_FREE);
+
+ return (nvl);
+}
+
+static nvlist_t *
gintel_ereport_create_resource_elem(nv_alloc_t *nva, mc_unum_t *unump)
{
nvlist_t *nvl, *snvl;
@@ -400,7 +495,15 @@ gintel_ereport_add_logout(cmi_hdl_t hdl, nvlist_t *ereport,
TCODE_OFFSET_RAS(unum.unum_offset), NULL);
}
}
- resource = gintel_ereport_create_resource_elem(nva, &unum);
+
+ if (!x86gentopo_legacy) {
+ resource = gintel_gentopo_ereport_create_resource_elem(
+ hdl, nva, &unum);
+ } else {
+ resource = gintel_ereport_create_resource_elem(nva,
+ &unum);
+ }
+
fm_payload_set(ereport, FM_EREPORT_PAYLOAD_NAME_RESOURCE,
DATA_TYPE_NVLIST_ARRAY, 1, &resource, NULL);
fm_nvlist_destroy(resource, nva ? FM_NVA_RETAIN:FM_NVA_FREE);
diff --git a/usr/src/uts/i86pc/os/cmi.c b/usr/src/uts/i86pc/os/cmi.c
index 31fd4ff73a..f9d722f031 100644
--- a/usr/src/uts/i86pc/os/cmi.c
+++ b/usr/src/uts/i86pc/os/cmi.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -112,6 +112,7 @@ extern void *cmi_hdl_getcmi(cmi_hdl_t);
extern void cmi_hdl_setmc(cmi_hdl_t, const struct cmi_mc_ops *, void *);
extern void cmi_hdl_inj_begin(cmi_hdl_t);
extern void cmi_hdl_inj_end(cmi_hdl_t);
+extern void cmi_read_smbios(cmi_hdl_t);
#define HDL2CMI(hdl) cmi_hdl_getcmi(hdl)
@@ -475,6 +476,8 @@ cmi_init(enum cmi_hdl_class class, uint_t chipid, uint_t coreid,
cms_init(hdl);
+ cmi_read_smbios(hdl);
+
mutex_exit(&cmi_load_lock);
return (hdl);
diff --git a/usr/src/uts/i86pc/os/cmi_hw.c b/usr/src/uts/i86pc/os/cmi_hw.c
index 9517ade74d..e6d6fdeabf 100644
--- a/usr/src/uts/i86pc/os/cmi_hw.c
+++ b/usr/src/uts/i86pc/os/cmi_hw.c
@@ -48,6 +48,18 @@
#include <sys/trap.h>
#include <sys/mca_x86.h>
#include <sys/processor.h>
+#include <sys/cmn_err.h>
+#include <sys/nvpair.h>
+#include <sys/fm/util.h>
+#include <sys/fm/protocol.h>
+#include <sys/fm/smb/fmsmb.h>
+#include <sys/cpu_module_impl.h>
+
+/*
+ * Variable which determines if the SMBIOS supports x86 generic topology; or
+ * if legacy topolgy enumeration will occur.
+ */
+extern int x86gentopo_legacy;
/*
* Outside of this file consumers use the opaque cmi_hdl_t. This
@@ -70,6 +82,9 @@ typedef struct cmi_hdl_impl {
const struct cmi_mc_ops *cmih_mcops; /* Memory-controller ops */
void *cmih_mcdata; /* Memory-controller data */
uint64_t cmih_flags; /* See CMIH_F_* below */
+ uint16_t cmih_smbiosid; /* SMBIOS Type 4 struct ID */
+ uint_t cmih_smb_chipid; /* SMBIOS factored chipid */
+ nvlist_t *cmih_smb_bboard; /* SMBIOS bboard nvlist */
} cmi_hdl_impl_t;
#define IMPLHDL(ophdl) ((cmi_hdl_impl_t *)ophdl)
@@ -92,6 +107,7 @@ struct cmi_hdl_ops {
uint_t (*cmio_chipid)(cmi_hdl_impl_t *);
uint_t (*cmio_coreid)(cmi_hdl_impl_t *);
uint_t (*cmio_strandid)(cmi_hdl_impl_t *);
+ uint_t (*cmio_strand_apicid)(cmi_hdl_impl_t *);
uint32_t (*cmio_chiprev)(cmi_hdl_impl_t *);
const char *(*cmio_chiprevstr)(cmi_hdl_impl_t *);
uint32_t (*cmio_getsockettype)(cmi_hdl_impl_t *);
@@ -108,6 +124,9 @@ struct cmi_hdl_ops {
cmi_errno_t (*cmio_msrinterpose)(cmi_hdl_impl_t *, uint_t, uint64_t);
void (*cmio_int)(cmi_hdl_impl_t *, int);
int (*cmio_online)(cmi_hdl_impl_t *, int, int *);
+ uint16_t (*cmio_smbiosid) (cmi_hdl_impl_t *);
+ uint_t (*cmio_smb_chipid)(cmi_hdl_impl_t *);
+ nvlist_t *(*cmio_smb_bboard)(cmi_hdl_impl_t *);
};
static const struct cmi_hdl_ops cmi_hdl_ops;
@@ -602,6 +621,30 @@ ntv_strandid(cmi_hdl_impl_t *hdl)
return (hdl->cmih_strandid);
}
+static uint_t
+ntv_strand_apicid(cmi_hdl_impl_t *hdl)
+{
+ return (cpuid_get_apicid(HDLPRIV(hdl)));
+}
+
+static uint16_t
+ntv_smbiosid(cmi_hdl_impl_t *hdl)
+{
+ return (hdl->cmih_smbiosid);
+}
+
+static uint_t
+ntv_smb_chipid(cmi_hdl_impl_t *hdl)
+{
+ return (hdl->cmih_smb_chipid);
+}
+
+static nvlist_t *
+ntv_smb_bboard(cmi_hdl_impl_t *hdl)
+{
+ return (hdl->cmih_smb_bboard);
+}
+
static uint32_t
ntv_chiprev(cmi_hdl_impl_t *hdl)
{
@@ -858,6 +901,30 @@ xpv_strandid(cmi_hdl_impl_t *hdl)
return (hdl->cmih_strandid);
}
+static uint_t
+xpv_strand_apicid(cmi_hdl_impl_t *hdl)
+{
+ return (xen_physcpu_initial_apicid(HDLPRIV(hdl)));
+}
+
+static uint16_t
+xpv_smbiosid(cmi_hdl_impl_t *hdl)
+{
+ return (hdl->cmih_smbiosid);
+}
+
+static uint_t
+xpv_smb_chipid(cmi_hdl_impl_t *hdl)
+{
+ return (hdl->cmih_smb_chipid);
+}
+
+static nvlist_t *
+xpv_smb_bboard(cmi_hdl_impl_t *hdl)
+{
+ return (hdl->cmih_smb_bboard);
+}
+
extern uint32_t _cpuid_chiprev(uint_t, uint_t, uint_t, uint_t);
static uint32_t
@@ -1186,6 +1253,51 @@ cmi_hdl_create(enum cmi_hdl_class class, uint_t chipid, uint_t coreid,
}
void
+cmi_read_smbios(cmi_hdl_t ophdl)
+{
+
+ uint_t strand_apicid;
+ uint_t chip_inst;
+ uint16_t smb_id;
+ int rc = 0;
+
+ cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
+
+ /* set x86gentopo compatibility */
+ fm_smb_fmacompat();
+
+#ifndef __xpv
+ strand_apicid = ntv_strand_apicid(hdl);
+#else
+ strand_apicid = xpv_strand_apicid(hdl);
+#endif
+
+ if (!x86gentopo_legacy) {
+ /*
+ * If fm_smb_chipinst() or fm_smb_bboard() fails,
+ * topo reverts to legacy mode
+ */
+ rc = fm_smb_chipinst(strand_apicid, &chip_inst, &smb_id);
+ if (rc == 0) {
+ hdl->cmih_smb_chipid = chip_inst;
+ hdl->cmih_smbiosid = smb_id;
+ } else {
+#ifdef DEBUG
+ cmn_err(CE_NOTE, "cmi reads smbios chip info failed");
+#endif /* DEBUG */
+ return;
+ }
+
+ hdl->cmih_smb_bboard = fm_smb_bboard(strand_apicid);
+#ifdef DEBUG
+ if (hdl->cmih_smb_bboard == NULL)
+ cmn_err(CE_NOTE,
+ "cmi reads smbios base boards info failed");
+#endif /* DEBUG */
+ }
+}
+
+void
cmi_hdl_hold(cmi_hdl_t ophdl)
{
cmi_hdl_impl_t *hdl = IMPLHDL(ophdl);
@@ -1398,11 +1510,15 @@ CMI_HDL_OPFUNC(stepping, uint_t)
CMI_HDL_OPFUNC(chipid, uint_t)
CMI_HDL_OPFUNC(coreid, uint_t)
CMI_HDL_OPFUNC(strandid, uint_t)
+CMI_HDL_OPFUNC(strand_apicid, uint_t)
CMI_HDL_OPFUNC(chiprev, uint32_t)
CMI_HDL_OPFUNC(chiprevstr, const char *)
CMI_HDL_OPFUNC(getsockettype, uint32_t)
CMI_HDL_OPFUNC(getsocketstr, const char *)
CMI_HDL_OPFUNC(logical_id, id_t)
+CMI_HDL_OPFUNC(smbiosid, uint16_t)
+CMI_HDL_OPFUNC(smb_chipid, uint_t)
+CMI_HDL_OPFUNC(smb_bboard, nvlist_t *)
boolean_t
cmi_hdl_is_cmt(cmi_hdl_t ophdl)
@@ -1730,6 +1846,7 @@ static const struct cmi_hdl_ops cmi_hdl_ops = {
xpv_chipid, /* cmio_chipid */
xpv_coreid, /* cmio_coreid */
xpv_strandid, /* cmio_strandid */
+ xpv_strand_apicid, /* cmio_strand_apicid */
xpv_chiprev, /* cmio_chiprev */
xpv_chiprevstr, /* cmio_chiprevstr */
xpv_getsockettype, /* cmio_getsockettype */
@@ -1741,7 +1858,10 @@ static const struct cmi_hdl_ops cmi_hdl_ops = {
xpv_wrmsr, /* cmio_wrmsr */
xpv_msrinterpose, /* cmio_msrinterpose */
xpv_int, /* cmio_int */
- xpv_online /* cmio_online */
+ xpv_online, /* cmio_online */
+ xpv_smbiosid, /* cmio_smbiosid */
+ xpv_smb_chipid, /* cmio_smb_chipid */
+ xpv_smb_bboard /* cmio_smb_bboard */
#else /* __xpv */
@@ -1756,6 +1876,7 @@ static const struct cmi_hdl_ops cmi_hdl_ops = {
ntv_chipid, /* cmio_chipid */
ntv_coreid, /* cmio_coreid */
ntv_strandid, /* cmio_strandid */
+ ntv_strand_apicid, /* cmio_strandid */
ntv_chiprev, /* cmio_chiprev */
ntv_chiprevstr, /* cmio_chiprevstr */
ntv_getsockettype, /* cmio_getsockettype */
@@ -1767,6 +1888,9 @@ static const struct cmi_hdl_ops cmi_hdl_ops = {
ntv_wrmsr, /* cmio_wrmsr */
ntv_msrinterpose, /* cmio_msrinterpose */
ntv_int, /* cmio_int */
- ntv_online /* cmio_online */
+ ntv_online, /* cmio_online */
+ ntv_smbiosid, /* cmio_smbiosid */
+ ntv_smb_chipid, /* cmio_smb_chipid */
+ ntv_smb_bboard /* cmio_smb_bboard */
#endif
};
diff --git a/usr/src/uts/i86pc/os/startup.c b/usr/src/uts/i86pc/os/startup.c
index 56f7aa1ce5..0b2c94ff66 100644
--- a/usr/src/uts/i86pc/os/startup.c
+++ b/usr/src/uts/i86pc/os/startup.c
@@ -1545,6 +1545,18 @@ startup_modules(void)
*/
setup_ddi();
+#ifdef __xpv
+ if (DOMAIN_IS_INITDOMAIN(xen_info))
+#endif
+ {
+ /*
+ * Load the System Management BIOS into the global ksmbios
+ * handle, if an SMBIOS is present on this system.
+ */
+ ksmbios = smbios_open(NULL, SMB_VERSION, ksmbios_flags, NULL);
+ }
+
+
/*
* Set up the CPU module subsystem for the boot cpu in the native
* case, and all physical cpu resource in the xpv dom0 case.
@@ -2186,12 +2198,6 @@ post_startup(void)
if (DOMAIN_IS_INITDOMAIN(xen_info))
#endif
{
- /*
- * Load the System Management BIOS into the global ksmbios
- * handle, if an SMBIOS is present on this system.
- */
- ksmbios = smbios_open(NULL, SMB_VERSION, ksmbios_flags, NULL);
-
#if defined(__xpv)
xpv_panic_init();
#else
diff --git a/usr/src/uts/i86xpv/os/xen_machdep.c b/usr/src/uts/i86xpv/os/xen_machdep.c
index 252d362989..58b534b74e 100644
--- a/usr/src/uts/i86xpv/os/xen_machdep.c
+++ b/usr/src/uts/i86xpv/os/xen_machdep.c
@@ -1275,6 +1275,12 @@ xen_physcpu_strandid(xen_mc_lcpu_cookie_t cookie)
}
id_t
+xen_physcpu_initial_apicid(xen_mc_lcpu_cookie_t cookie)
+{
+ return (COOKIE2XCP(cookie)->mc_clusterid);
+}
+
+id_t
xen_physcpu_logical_id(xen_mc_lcpu_cookie_t cookie)
{
return (COOKIE2XCP(cookie)->mc_cpunr);
diff --git a/usr/src/uts/intel/Makefile.files b/usr/src/uts/intel/Makefile.files
index 6adea5979f..5c42a4fd5d 100644
--- a/usr/src/uts/intel/Makefile.files
+++ b/usr/src/uts/intel/Makefile.files
@@ -45,6 +45,7 @@ CORE_OBJS += \
desctbls_asm.o \
exception.o \
float.o \
+ fmsmb.o \
fpu.o \
i86_subr.o \
lock_prim.o \
diff --git a/usr/src/uts/intel/io/devfm_machdep.c b/usr/src/uts/intel/io/devfm_machdep.c
index 7d2edc884d..58c9f0ae7b 100644
--- a/usr/src/uts/intel/io/devfm_machdep.c
+++ b/usr/src/uts/intel/io/devfm_machdep.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -28,6 +28,7 @@
#include <sys/time.h>
#include <sys/fm/protocol.h>
+#include <sys/fm/smb/fmsmb.h>
#include <sys/devfm.h>
#include <sys/cpu_module.h>
@@ -52,6 +53,8 @@ typedef struct fm_cmi_walk_t
int nhdl; /* handles saved */
} fm_cmi_walk_t;
+extern int x86gentopo_legacy;
+
int
fm_get_paddr(nvlist_t *nvl, uint64_t *paddr)
{
@@ -145,7 +148,33 @@ select_cmi_hdl(cmi_hdl_t hdl, void *arg1, void *arg2, void *arg3)
static void
populate_cpu(nvlist_t **nvlp, cmi_hdl_t hdl)
{
+ uint_t fm_chipid;
+ uint16_t smbios_id;
+
(void) nvlist_alloc(nvlp, NV_UNIQUE_NAME, KM_SLEEP);
+
+ /*
+ * If SMBIOS satisfies FMA Topology needs, gather
+ * more information on the chip's physical roots
+ * like /chassis=x/motherboard=y/cpuboard=z and
+ * set the chip_id to match the SMBIOS' Type 4
+ * ordering & this has to match the ereport's chip
+ * resource instance derived off of SMBIOS.
+ * Multi-Chip-Module support should set the chipid
+ * in terms of the processor package rather than
+ * the die/node in the processor package, for FM.
+ */
+
+ if (!x86gentopo_legacy) {
+ smbios_id = cmi_hdl_smbiosid(hdl);
+ fm_chipid = cmi_hdl_smb_chipid(hdl);
+ (void) nvlist_add_nvlist(*nvlp, FM_PHYSCPU_INFO_CHIP_ROOTS,
+ cmi_hdl_smb_bboard(hdl));
+ (void) nvlist_add_uint16(*nvlp, FM_PHYSCPU_INFO_SMBIOS_ID,
+ (uint16_t)smbios_id);
+ } else
+ fm_chipid = cmi_hdl_chipid(hdl);
+
fm_payload_set(*nvlp,
FM_PHYSCPU_INFO_VENDOR_ID, DATA_TYPE_STRING,
cmi_hdl_vendorstr(hdl),
@@ -156,11 +185,13 @@ populate_cpu(nvlist_t **nvlp, cmi_hdl_t hdl)
FM_PHYSCPU_INFO_STEPPING, DATA_TYPE_INT32,
(int32_t)cmi_hdl_stepping(hdl),
FM_PHYSCPU_INFO_CHIP_ID, DATA_TYPE_INT32,
- (int32_t)cmi_hdl_chipid(hdl),
+ (int32_t)fm_chipid,
FM_PHYSCPU_INFO_CORE_ID, DATA_TYPE_INT32,
(int32_t)cmi_hdl_coreid(hdl),
FM_PHYSCPU_INFO_STRAND_ID, DATA_TYPE_INT32,
(int32_t)cmi_hdl_strandid(hdl),
+ FM_PHYSCPU_INFO_STRAND_APICID, DATA_TYPE_INT32,
+ (int32_t)cmi_hdl_strand_apicid(hdl),
FM_PHYSCPU_INFO_CHIP_REV, DATA_TYPE_STRING,
cmi_hdl_chiprevstr(hdl),
FM_PHYSCPU_INFO_SOCKET_TYPE, DATA_TYPE_UINT32,
@@ -257,3 +288,30 @@ fm_ioctl_cpu_retire(int cmd, nvlist_t *invl, nvlist_t **onvlp)
return (rc);
}
+
+/*
+ * Retrun the value of x86gentopo_legacy variable as an nvpair.
+ *
+ * The caller is responsible for freeing the nvlist.
+ */
+/* ARGSUSED */
+int
+fm_ioctl_gentopo_legacy(int cmd, nvlist_t *invl, nvlist_t **onvlp)
+{
+ nvlist_t *nvl;
+
+ if (cmd != FM_IOC_GENTOPO_LEGACY) {
+ return (ENOTTY);
+ }
+
+ /*
+ * Inform the caller of the intentions of the ereport generators to
+ * generate either a "generic" or "legacy" x86 topology.
+ */
+
+ (void) nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP);
+ (void) nvlist_add_int32(nvl, FM_GENTOPO_LEGACY, x86gentopo_legacy);
+ *onvlp = nvl;
+
+ return (0);
+}
diff --git a/usr/src/uts/intel/io/mc-amd/mcamd.h b/usr/src/uts/intel/io/mc-amd/mcamd.h
index f6bba1f1a4..ec9fcb5077 100644
--- a/usr/src/uts/intel/io/mc-amd/mcamd.h
+++ b/usr/src/uts/intel/io/mc-amd/mcamd.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -209,6 +209,8 @@ struct mc {
size_t mc_snapshotsz; /* packed nvlist buffer size */
uint_t mc_snapshotgen; /* snapshot generation number */
int mc_csdiscontig; /* chip-selects discontiguous */
+ uint_t smb_chipid; /* smbios chip instance */
+ nvlist_t *smb_bboard; /* smbios chip's parent */
};
typedef struct mcamd_hdl {
diff --git a/usr/src/uts/intel/io/mc-amd/mcamd_drv.c b/usr/src/uts/intel/io/mc-amd/mcamd_drv.c
index 9123851315..bbabeca5dc 100644
--- a/usr/src/uts/intel/io/mc-amd/mcamd_drv.c
+++ b/usr/src/uts/intel/io/mc-amd/mcamd_drv.c
@@ -47,11 +47,16 @@
#include <sys/pci_cfgspace.h>
#include <sys/mc.h>
#include <sys/mc_amd.h>
+#include <sys/smbios.h>
+#include <sys/pci.h>
#include <mcamd.h>
#include <mcamd_dimmcfg.h>
#include <mcamd_pcicfg.h>
#include <mcamd_api.h>
#include <sys/fm/cpu/AMD.h>
+#include <sys/fm/smb/fmsmb.h>
+#include <sys/fm/protocol.h>
+#include <sys/fm/util.h>
/*
* Set to prevent mc-amd from attaching.
@@ -1270,6 +1275,41 @@ mc_fm_init(dev_info_t *dip)
ddi_fm_handler_register(dip, mc_fm_handle, NULL);
}
+static void
+mc_read_smbios(mc_t *mc, dev_info_t *dip)
+{
+
+ uint16_t bdf;
+ pci_regspec_t *pci_rp;
+ uint32_t phys_hi;
+ int m;
+ uint_t chip_inst;
+ int rc = 0;
+
+ if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg",
+ (caddr_t)&pci_rp, &m) == DDI_SUCCESS) {
+ phys_hi = pci_rp->pci_phys_hi;
+ bdf = (uint16_t)(PCI_REG_BDFR_G(phys_hi) >>
+ PCI_REG_FUNC_SHIFT);
+
+ rc = fm_smb_mc_chipinst(bdf, &chip_inst);
+ if (rc == 0) {
+ mc->smb_chipid = chip_inst;
+ } else {
+#ifdef DEBUG
+ cmn_err(CE_NOTE, "mc reads smbios chip info failed");
+#endif /* DEBUG */
+ return;
+ }
+ mc->smb_bboard = fm_smb_mc_bboards(bdf);
+#ifdef DEBUG
+ if (mc->smb_bboard == NULL)
+ cmn_err(CE_NOTE,
+ "mc reads smbios base boards info failed");
+#endif /* DEBUG */
+ }
+}
+
/*ARGSUSED*/
static int
mc_create_cb(cmi_hdl_t whdl, void *arg1, void *arg2, void *arg3)
@@ -1287,7 +1327,7 @@ mc_create_cb(cmi_hdl_t whdl, void *arg1, void *arg2, void *arg3)
}
static mc_t *
-mc_create(chipid_t chipid)
+mc_create(chipid_t chipid, dev_info_t *dip)
{
mc_t *mc;
cmi_hdl_t hdl = NULL;
@@ -1315,6 +1355,8 @@ mc_create(chipid_t chipid)
mc->mc_revname = cmi_hdl_chiprevstr(hdl);
mc->mc_socket = cmi_hdl_getsockettype(hdl);
+ mc_read_smbios(mc, dip);
+
if (mc_list == NULL)
mc_list = mc;
if (mc_last != NULL)
@@ -1552,7 +1594,7 @@ mc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
/* Integrate this memory controller device into existing set */
if (mc == NULL) {
- mc = mc_create(chipid);
+ mc = mc_create(chipid, dip);
if (mc == NULL) {
/*
diff --git a/usr/src/uts/intel/io/mc-amd/mcamd_subr.c b/usr/src/uts/intel/io/mc-amd/mcamd_subr.c
index 7c418e3255..04cc5e5460 100644
--- a/usr/src/uts/intel/io/mc-amd/mcamd_subr.c
+++ b/usr/src/uts/intel/io/mc-amd/mcamd_subr.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -35,14 +35,19 @@
#include <sys/varargs.h>
#include <sys/fm/util.h>
#include <sys/fm/cpu/AMD.h>
+#include <sys/fm/smb/fmsmb.h>
#include <sys/fm/protocol.h>
#include <sys/mc.h>
+#include <sys/smbios.h>
+#include <sys/smbios_impl.h>
#include <mcamd.h>
#include <mcamd_off.h>
int mcamd_debug = 0; /* see mcamd_api.h for MCAMD_DBG_* values */
+extern int x86gentopo_legacy;
+
struct mc_offmap {
int mcom_code;
uint_t mcom_offset;
@@ -557,7 +562,8 @@ mcamd_unumtopa_wrap(void *arg, mc_unum_t *unump, nvlist_t *nvl, uint64_t *pap)
}
static void
-mc_ereport_dimm_resource(mc_unum_t *unump, nvlist_t *elems[], int *nump)
+mc_ereport_dimm_resource(mc_unum_t *unump, nvlist_t *elems[], int *nump,
+ mc_t *mc)
{
int i;
@@ -566,24 +572,44 @@ mc_ereport_dimm_resource(mc_unum_t *unump, nvlist_t *elems[], int *nump)
break;
elems[(*nump)++] = fm_nvlist_create(NULL);
- fm_fmri_hc_set(elems[i], FM_HC_SCHEME_VERSION, NULL, NULL, 5,
- "motherboard", unump->unum_board,
- "chip", unump->unum_chip,
- "memory-controller", unump->unum_mc,
- "dimm", unump->unum_dimms[i],
- "rank", unump->unum_rank);
+
+ if (!x86gentopo_legacy && mc->smb_bboard != NULL) {
+ fm_fmri_hc_create(elems[i], FM_HC_SCHEME_VERSION,
+ NULL, NULL, mc->smb_bboard, 4,
+ "chip", mc->smb_chipid,
+ "memory-controller", unump->unum_mc,
+ "dimm", unump->unum_dimms[i],
+ "rank", unump->unum_rank);
+ } else {
+ fm_fmri_hc_set(elems[i], FM_HC_SCHEME_VERSION,
+ NULL, NULL, 5,
+ "motherboard", unump->unum_board,
+ "chip", unump->unum_chip,
+ "memory-controller", unump->unum_mc,
+ "dimm", unump->unum_dimms[i],
+ "rank", unump->unum_rank);
+ }
}
}
static void
-mc_ereport_cs_resource(mc_unum_t *unump, nvlist_t *elems[], int *nump)
+mc_ereport_cs_resource(mc_unum_t *unump, nvlist_t *elems[], int *nump, mc_t *mc)
{
elems[0] = fm_nvlist_create(NULL);
- fm_fmri_hc_set(elems[0], FM_HC_SCHEME_VERSION, NULL, NULL, 4,
- "motherboard", unump->unum_board,
- "chip", unump->unum_chip,
- "memory-controller", unump->unum_mc,
- "chip-select", unump->unum_cs);
+
+ if (!x86gentopo_legacy && mc->smb_bboard != NULL) {
+ fm_fmri_hc_create(elems[0], FM_HC_SCHEME_VERSION, NULL, NULL,
+ mc->smb_bboard, 3,
+ "chip", mc->smb_chipid,
+ "memory-controller", unump->unum_mc,
+ "chip-select", unump->unum_cs);
+ } else {
+ fm_fmri_hc_set(elems[0], FM_HC_SCHEME_VERSION, NULL, NULL, 4,
+ "motherboard", unump->unum_board,
+ "chip", unump->unum_chip,
+ "memory-controller", unump->unum_mc,
+ "chip-select", unump->unum_cs);
+ }
*nump = 1;
}
@@ -595,16 +621,16 @@ mc_ereport_cs_resource(mc_unum_t *unump, nvlist_t *elems[], int *nump)
* topology node.
*/
static void
-mc_ereport_add_resource(nvlist_t *payload, mc_unum_t *unump)
+mc_ereport_add_resource(nvlist_t *payload, mc_unum_t *unump, mc_t *mc)
{
nvlist_t *elems[MC_UNUM_NDIMM];
int nelems = 0;
int i;
if (unump->unum_dimms[0] != MC_INVALNUM)
- mc_ereport_dimm_resource(unump, elems, &nelems);
+ mc_ereport_dimm_resource(unump, elems, &nelems, mc);
else if (unump->unum_cs != MC_INVALNUM)
- mc_ereport_cs_resource(unump, elems, &nelems);
+ mc_ereport_cs_resource(unump, elems, &nelems, mc);
if (nelems > 0) {
fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RESOURCE,
@@ -616,11 +642,12 @@ mc_ereport_add_resource(nvlist_t *payload, mc_unum_t *unump)
}
static void
-mc_ereport_add_payload(nvlist_t *ereport, uint64_t members, mc_unum_t *unump)
+mc_ereport_add_payload(nvlist_t *ereport, uint64_t members, mc_unum_t *unump,
+ mc_t *mc)
{
if (members & FM_EREPORT_PAYLOAD_FLAG_RESOURCE &&
unump != NULL)
- mc_ereport_add_resource(ereport, unump);
+ mc_ereport_add_resource(ereport, unump, mc);
}
static nvlist_t *
@@ -628,10 +655,17 @@ mc_fmri_create(mc_t *mc)
{
nvlist_t *nvl = fm_nvlist_create(NULL);
- fm_fmri_hc_set(nvl, FM_HC_SCHEME_VERSION, NULL, NULL, 3,
- "motherboard", 0,
- "chip", mc->mc_props.mcp_num,
- "memory-controller", 0);
+ if (!x86gentopo_legacy && mc->smb_bboard != NULL) {
+ fm_fmri_hc_create(nvl, FM_HC_SCHEME_VERSION, NULL, NULL,
+ mc->smb_bboard, 2,
+ "chip", mc->smb_chipid,
+ "memory-controller", 0);
+ } else {
+ fm_fmri_hc_set(nvl, FM_HC_SCHEME_VERSION, NULL, NULL, 3,
+ "motherboard", 0,
+ "chip", mc->mc_props.mcp_num,
+ "memory-controller", 0);
+ }
return (nvl);
}
@@ -668,7 +702,7 @@ mcamd_ereport_post(mc_t *mc, const char *class_sfx, mc_unum_t *unump,
fm_ena_generate(gethrtime(), FM_ENA_FMT1), detector, NULL);
fm_nvlist_destroy(detector, FM_NVA_FREE);
- mc_ereport_add_payload(ereport, payload, unump);
+ mc_ereport_add_payload(ereport, payload, unump, mc);
(void) fm_ereport_post(ereport, EVCH_TRYHARD);
fm_nvlist_destroy(ereport, FM_NVA_FREE);
diff --git a/usr/src/uts/intel/os/fmsmb.c b/usr/src/uts/intel/os/fmsmb.c
new file mode 100644
index 0000000000..627a0fb9c5
--- /dev/null
+++ b/usr/src/uts/intel/os/fmsmb.c
@@ -0,0 +1,1129 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/nvpair.h>
+#include <sys/cmn_err.h>
+#include <sys/fm/util.h>
+#include <sys/fm/protocol.h>
+#include <sys/smbios.h>
+#include <sys/smbios_impl.h>
+
+/*
+ * Variable used to determine if the x86 generic topology enumerator will
+ * revert to legacy enumeration. I.E. Big Kill Switch... tunable via
+ * /etc/system
+ */
+int x86gentopo_legacy = 0;
+
+#define MC 0
+#define PROC 1
+#define MAX_PAIRS 20
+#define MAX_CONT 40
+
+typedef struct bbindex {
+ int count;
+ uint16_t index[MAX_PAIRS];
+} bbindex_t;
+
+/*
+ * the enum values come from DMTF
+ */
+typedef enum baseb {
+ BB_BAD = 0, /* There is no bb value 0 */
+ BB_UNKNOWN, /* Unknown */
+ BB_OTHER, /* Other */
+ BB_BLADE, /* Server Blade */
+ BB_CONNSW, /* Connectivity Switch */
+ BB_SMM, /* System Management Module */
+ BB_PROCMOD, /* Processor Module */
+ BB_IOMOD, /* I/O Module */
+ BB_MEMMOD, /* Memory Module */
+ BB_DBOARD, /* Daughter Board */
+ BB_MBOARD, /* Motherboard */
+ BB_PROCMMOD, /* Processor/Memory Module */
+ BB_PROCIOMOD, /* Processor/IO Module */
+ BB_ICONNBD /* Interconnect Board */
+} bbd_t;
+
+static struct bboard_type {
+ bbd_t baseb;
+ const char *name;
+} bbd_type[] = {
+ {BB_BAD, NULL},
+ {BB_UNKNOWN, "unknown"},
+ {BB_OTHER, "other"},
+ {BB_BLADE, "systemboard"},
+ {BB_CONNSW, "connswitch"},
+ {BB_SMM, "smmodule"},
+ {BB_PROCMOD, "cpuboard"},
+ {BB_IOMOD, "ioboard"},
+ {BB_MEMMOD, "memboard"},
+ {BB_DBOARD, "systemboard"},
+ {BB_MBOARD, "motherboard"},
+ {BB_PROCMMOD, "systemboard"},
+ {BB_PROCIOMOD, "systemboard"},
+ {BB_ICONNBD, "systemboard"}
+};
+
+typedef struct smbs_con_ids {
+ int id;
+ int inst;
+ int cont_count;
+ uint16_t **cont_ids;
+ int cont_by_id;
+ int visited;
+} smbs_con_ids_t;
+
+typedef struct smbs_cnt {
+ int type; /* SMBIOS stucture type */
+ int count; /* number of table entries */
+ smbs_con_ids_t **ids; /* SMBIOS table entry id(s) */
+} smbs_cnt_t;
+
+/*
+ * dynamically allocate the storage for the smbs_cnt_t
+ */
+static smbs_cnt_t *
+smb_create_strcnt(int count)
+{
+ smbs_cnt_t *types = NULL;
+ int i, j;
+
+ types = kmem_zalloc(sizeof (smbs_cnt_t), KM_SLEEP);
+
+ types->ids = (smbs_con_ids_t **)kmem_zalloc(
+ count * sizeof (smbs_con_ids_t *), KM_SLEEP);
+
+ for (i = 0; i < count; i++) {
+ types->ids[i] = (smbs_con_ids_t *)kmem_zalloc(
+ sizeof (smbs_con_ids_t), KM_SLEEP);
+ }
+
+ for (i = 0; i < count; i++) {
+ types->ids[i]->cont_ids = (uint16_t **)kmem_zalloc(
+ MAX_CONT * sizeof (uint16_t *), KM_SLEEP);
+ }
+
+ for (i = 0; i < count; i++) {
+ for (j = 0; j < MAX_CONT; j++) {
+ types->ids[i]->cont_ids[j] = (uint16_t *)kmem_zalloc(
+ sizeof (uint16_t), KM_SLEEP);
+ }
+ }
+ return (types);
+}
+
+/*
+ * free the smbs_cnt_t memory
+ */
+static void
+smb_free_strcnt(smbs_cnt_t *types, int count)
+{
+ int i, j;
+
+ if (types == NULL)
+ return;
+
+ for (i = 0; i < count; i++) {
+ for (j = 0; j < MAX_CONT; j++) {
+ if (types->ids[i]->cont_ids[j] != NULL)
+ kmem_free(types->ids[i]->cont_ids[j],
+ sizeof (uint16_t));
+ }
+ }
+
+ for (i = 0; i < count; i++) {
+ if (types->ids[i]->cont_ids != NULL)
+ kmem_free(types->ids[i]->cont_ids,
+ MAX_CONT * sizeof (uint16_t *));
+ }
+
+ for (i = 0; i < count; i++) {
+ if (types->ids[i] != NULL)
+ kmem_free(types->ids[i], sizeof (smbs_con_ids_t));
+ }
+
+ if (types->ids != NULL)
+ kmem_free(types->ids, count * sizeof (smbs_con_ids_t *));
+
+ if (types != NULL)
+ kmem_free(types, sizeof (smbs_cnt_t));
+
+}
+
+/*
+ * count number of the structure type in the ksmbios
+ */
+static int
+smb_cnttypes(smbios_hdl_t *shp, int type)
+{
+ const smb_struct_t *sp = shp->sh_structs;
+ int nstructs = shp->sh_nstructs;
+ int i;
+ int cnt = 0;
+
+ for (i = 0, cnt = 0; i < nstructs; i++, sp++) {
+ if (sp->smbst_hdr->smbh_type == type)
+ cnt++;
+ }
+ return (cnt);
+}
+
+static void
+smb_strcnt(smbios_hdl_t *shp, smbs_cnt_t *stype)
+{
+ const smb_struct_t *sp = shp->sh_structs;
+ int nstructs = shp->sh_nstructs;
+ smbios_bboard_t bb;
+ int i, cnt;
+ int mb_cnt = 0;
+ int cpub_cnt = 0;
+ int sysb_cnt = 0;
+ int memb_cnt = 0;
+ int iob_cnt = 0;
+ int inst = 0;
+ int rc = 0;
+
+ for (i = 0, cnt = 0; i < nstructs; i++, sp++) {
+ if (sp->smbst_hdr->smbh_type == stype->type) {
+ stype->ids[cnt]->id = sp->smbst_hdr->smbh_hdl;
+ stype->ids[cnt]->inst = cnt;
+ stype->ids[cnt]->visited = 0;
+ stype->ids[cnt]->cont_by_id = -1;
+ if (stype->type == SMB_TYPE_BASEBOARD) {
+ rc = smbios_info_bboard(shp,
+ stype->ids[cnt]->id, &bb);
+ if (rc == 0) {
+ switch (bb.smbb_type) {
+ case SMB_BBT_PROC :
+ inst = cpub_cnt++;
+ break;
+ case SMB_BBT_IO :
+ inst = iob_cnt++;
+ break;
+ case SMB_BBT_MEM :
+ inst = memb_cnt++;
+ break;
+ case SMB_BBT_MOTHER :
+ inst = mb_cnt++;
+ break;
+ default:
+ /*
+ * SMB_BBT_UNKNOWN
+ * SMB_BBT_OTHER
+ * SMB_BBT_SBLADE
+ * SMB_BBT_CSWITCH
+ * SMB_BBT_SMM
+ * SMB_BBT_DAUGHTER
+ * SMB_BBT_PROCMEM
+ * SMB_BBT_PROCIO
+ * SMB_BBT_INTER
+ */
+ inst = sysb_cnt++;
+ break;
+ }
+ stype->ids[cnt]->inst = inst;
+ }
+ }
+ cnt++;
+ }
+ }
+ stype->count = cnt;
+}
+
+/*
+ * Go through the smbios structures looking for type 2. Fill in
+ * the cont_id and cont_by_id for each type 2
+ *
+ */
+static void
+smb_bb_contains(smbios_hdl_t *shp, smbs_cnt_t *stype)
+{
+ int i, j, cnt, c;
+ uint_t cont_count;
+ const smb_struct_t *spt;
+ smbios_bboard_t smb_bb;
+ uint16_t bb_id, cont_id;
+ uint_t cont_len;
+ id_t *cont_hdl = NULL;
+ int rc;
+
+ for (cnt = 0; cnt < stype->count; cnt++) {
+ bb_id = stype->ids[cnt]->id;
+ (void) smbios_info_bboard(shp, stype->ids[cnt]->id, &smb_bb);
+ cont_count = (uint_t)smb_bb.smbb_contn;
+ if (cont_count == 0) {
+ continue;
+ }
+
+ cont_len = sizeof (id_t);
+ cont_hdl = kmem_zalloc(cont_count * cont_len, KM_SLEEP);
+ if (cont_hdl == NULL)
+ continue;
+
+ rc = smbios_info_contains(shp, stype->ids[cnt]->id,
+ cont_count, cont_hdl);
+ if (rc > SMB_CONT_MAX) {
+ kmem_free(cont_hdl, cont_count * cont_len);
+ continue;
+ }
+ cont_count = MIN(rc, cont_count);
+
+ /*
+ * fill in the type 2 and type 4 ids which are
+ * contained in this type 2
+ */
+ c = 0;
+ for (j = 0; j < cont_count; j++) {
+ cont_id = (uint16_t)cont_hdl[j];
+ spt = smb_lookup_id(shp, cont_id);
+ if (spt->smbst_hdr->smbh_type == SMB_TYPE_BASEBOARD ||
+ spt->smbst_hdr->smbh_type == SMB_TYPE_PROCESSOR) {
+ *stype->ids[cnt]->cont_ids[c] = cont_id;
+ c++;
+ }
+
+ if (spt->smbst_hdr->smbh_type == SMB_TYPE_BASEBOARD) {
+ for (i = 0; i < stype->count; i++) {
+ if (stype->ids[i]->id == cont_id) {
+ stype->ids[i]->cont_by_id =
+ bb_id;
+ }
+ }
+ }
+
+ }
+ stype->ids[cnt]->cont_count = c;
+ if (cont_hdl != NULL)
+ kmem_free(cont_hdl, cont_count * cont_len);
+ }
+}
+
+/*
+ * Verify SMBIOS structures for x86 generic topology.
+ *
+ * Return (0) on success.
+ */
+static int
+fm_smb_check(smbios_hdl_t *shp)
+{
+ int i;
+ int bb_cnt = 0;
+ int pr_cnt = 0;
+ int expr_cnt = 0;
+ int ma_cnt = 0;
+ int exma_cnt = 0;
+ int mdev_cnt = 0;
+ int exmdev_cnt = 0;
+ uint16_t bb_id;
+ uint16_t pr_id, expr_id;
+ uint16_t ma_id, exma_id;
+ uint16_t mdev_id, exmdev_id;
+ smbios_bboard_t bb;
+ smbios_processor_ext_t exproc;
+ smbios_memarray_ext_t exma;
+ smbios_memdevice_ext_t exmdev;
+ smbs_cnt_t *bb_stype;
+ smbs_cnt_t *pr_stype, *expr_stype;
+ smbs_cnt_t *ma_stype, *exma_stype;
+ smbs_cnt_t *mdev_stype, *exmdev_stype;
+
+ /*
+ * Verify the existance of the requuired extended OEM-Specific
+ * structures and they coincide with the structures they extend
+ * (e.g. the number of extended processor structures equal the
+ * number of processor structures).
+ */
+ pr_cnt = smb_cnttypes(shp, SMB_TYPE_PROCESSOR);
+ expr_cnt = smb_cnttypes(shp, SUN_OEM_EXT_PROCESSOR);
+ ma_cnt = smb_cnttypes(shp, SMB_TYPE_MEMARRAY);
+ exma_cnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMARRAY);
+ mdev_cnt = smb_cnttypes(shp, SMB_TYPE_MEMDEVICE);
+ exmdev_cnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMDEVICE);
+ if (expr_cnt == 0 || exma_cnt == 0 || exmdev_cnt == 0 ||
+ expr_cnt != pr_cnt || exma_cnt != ma_cnt ||
+ exmdev_cnt != mdev_cnt) {
+#ifdef DEBUG
+ cmn_err(CE_NOTE, "Structure mismatch: ext_proc (%d) "
+ "proc (%d) ext_ma (%d) ma (%d) ext_mdev (%d) mdev (%d)\n",
+ expr_cnt, pr_cnt, exma_cnt, ma_cnt, exmdev_cnt,
+ mdev_cnt);
+#endif /* DEBUG */
+ return (-1);
+ }
+
+ /*
+ * Verify the OEM-Specific structrures are correctly
+ * linked to the SMBIOS structure types they extend.
+ */
+
+ /* allocate processor stypes */
+ pr_stype = smb_create_strcnt(pr_cnt);
+ expr_stype = smb_create_strcnt(expr_cnt);
+
+ /* fill in stypes */
+ pr_stype->type = SMB_TYPE_PROCESSOR;
+ smb_strcnt(shp, pr_stype);
+ expr_stype->type = SUN_OEM_EXT_PROCESSOR;
+ smb_strcnt(shp, expr_stype);
+
+ /* verify the ext proc struct belong to the proc struct */
+ for (i = 0; i < pr_cnt; i++) {
+ pr_id = pr_stype->ids[i]->id;
+ expr_id = expr_stype->ids[i]->id;
+ (void) smbios_info_extprocessor(shp, expr_id, &exproc);
+ if (exproc.smbpe_processor != pr_id) {
+#ifdef DEBUG
+ cmn_err(CE_NOTE, "Processor struct linkage (%d)", i);
+#endif /* DEBUG */
+ smb_free_strcnt(pr_stype, pr_cnt);
+ smb_free_strcnt(expr_stype, expr_cnt);
+ return (-1);
+ }
+ }
+
+ /* free stypes */
+ smb_free_strcnt(pr_stype, pr_cnt);
+ smb_free_strcnt(expr_stype, expr_cnt);
+
+ /* allocate memory array stypes */
+ ma_stype = smb_create_strcnt(ma_cnt);
+ exma_stype = smb_create_strcnt(exma_cnt);
+
+ /* fill in stypes */
+ ma_stype->type = SMB_TYPE_MEMARRAY;
+ smb_strcnt(shp, ma_stype);
+ exma_stype->type = SUN_OEM_EXT_MEMARRAY;
+ smb_strcnt(shp, exma_stype);
+
+ /* verify linkage from ext memarray struct to memarray struct */
+ for (i = 0; i < ma_cnt; i++) {
+ ma_id = ma_stype->ids[i]->id;
+ exma_id = exma_stype->ids[i]->id;
+ (void) smbios_info_extmemarray(shp, exma_id, &exma);
+ if (exma.smbmae_ma != ma_id) {
+#ifdef DEBUG
+ cmn_err(CE_NOTE, "Memory Array struct linkage (%d)", i);
+#endif /* DEBUG */
+ smb_free_strcnt(ma_stype, ma_cnt);
+ smb_free_strcnt(exma_stype, exma_cnt);
+ return (-1);
+ }
+ }
+
+ /* free stypes */
+ smb_free_strcnt(ma_stype, ma_cnt);
+ smb_free_strcnt(exma_stype, exma_cnt);
+
+ /* allocate memory device stypes */
+ mdev_stype = smb_create_strcnt(mdev_cnt);
+ exmdev_stype = smb_create_strcnt(exmdev_cnt);
+
+ /* fill in stypes */
+ mdev_stype->type = SMB_TYPE_MEMDEVICE;
+ smb_strcnt(shp, mdev_stype);
+ exmdev_stype->type = SUN_OEM_EXT_MEMDEVICE;
+ smb_strcnt(shp, exmdev_stype);
+
+ /* verify linkage */
+ for (i = 0; i < mdev_cnt; i++) {
+ mdev_id = mdev_stype->ids[i]->id;
+ exmdev_id = exmdev_stype->ids[i]->id;
+ (void) smbios_info_extmemdevice(shp, exmdev_id, &exmdev);
+ if (exmdev.smbmdeve_md != mdev_id) {
+#ifdef DEBUG
+ cmn_err(CE_NOTE, "Memory Device struct linkage (%d)",
+ i);
+#endif /* DEBUG */
+ smb_free_strcnt(mdev_stype, mdev_cnt);
+ smb_free_strcnt(exmdev_stype, exmdev_cnt);
+ return (-1);
+ }
+ }
+
+ /* free stypes */
+ smb_free_strcnt(mdev_stype, mdev_cnt);
+ smb_free_strcnt(exmdev_stype, exmdev_cnt);
+
+ /*
+ * Verify the presece of contained handles if there are more
+ * than one Type-2 (Base Board) structures.
+ */
+ bb_cnt = smb_cnttypes(shp, SMB_TYPE_BASEBOARD);
+ if (bb_cnt > 1) {
+ /* allocate base board stypes */
+ bb_stype = smb_create_strcnt(bb_cnt);
+
+ /* fill in stypes */
+ bb_stype->type = SMB_TYPE_BASEBOARD;
+ smb_strcnt(shp, bb_stype);
+
+ /* verify contained handles */
+ for (i = 0; i < bb_cnt; i++) {
+ bb_id = bb_stype->ids[i]->id;
+ (void) smbios_info_bboard(shp, bb_id, &bb);
+ if (bb.smbb_contn == 0) {
+#ifdef DEBUG
+ cmn_err(CE_NOTE, "No contained hanldes (%d)",
+ i);
+#endif /* DEBUG */
+ smb_free_strcnt(bb_stype, bb_cnt);
+ return (-1);
+ }
+ }
+
+ /* free stypes */
+ smb_free_strcnt(bb_stype, bb_cnt);
+ }
+
+ return (0);
+}
+
+void
+fm_smb_fmacompat()
+{
+ int i, j;
+ int id;
+ int cnt;
+ const char **oem_strings = NULL;
+ smbs_cnt_t *oemstypes;
+ smbios_hdl_t *shp;
+ int strcnt;
+ int compat = 0;
+
+ /* check for BKS */
+ if (x86gentopo_legacy == 1) {
+#ifdef DEBUG
+ cmn_err(CE_NOTE, "forced legacy x86 topology enumeration");
+#endif /* DEBUG */
+ return;
+ }
+
+ shp = ksmbios;
+ if (shp == NULL) {
+ goto bad;
+ }
+
+ /* OEM strings (Type 11) */
+ strcnt = smb_cnttypes(shp, SMB_TYPE_OEMSTR);
+ if (strcnt == 0)
+ goto bad;
+
+ oemstypes = smb_create_strcnt(strcnt);
+ if (oemstypes == NULL)
+ goto bad;
+
+ oemstypes->type = SMB_TYPE_OEMSTR;
+ smb_strcnt(shp, oemstypes);
+
+ for (i = 0; i < oemstypes->count; i++) {
+ id = oemstypes->ids[i]->id;
+ cnt = smbios_info_strtab(shp, id, 0, NULL);
+ if (cnt > 0) {
+ oem_strings = kmem_zalloc(sizeof (char *) * cnt,
+ KM_SLEEP);
+ (void) smbios_info_strtab(shp, id, cnt, oem_strings);
+
+ for (j = 0; j < cnt; j++) {
+ if (strncmp(oem_strings[j], SMB_PRMS1,
+ strlen(SMB_PRMS1) + 1) == 0) {
+ kmem_free(oem_strings,
+ sizeof (char *) * cnt);
+ smb_free_strcnt(oemstypes, strcnt);
+ compat = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ if (compat == 0) {
+ /* didn't find x86pi magic cookie */
+ if (oem_strings != NULL)
+ kmem_free(oem_strings, sizeof (char *) * cnt);
+ smb_free_strcnt(oemstypes, strcnt);
+ goto bad;
+ }
+
+ /* sanity check SMBIOS structures */
+ if (fm_smb_check(shp) == 0)
+ return;
+
+bad:
+ /* not compatible with x86gentopo; revert to legacy enumeration */
+#ifdef DEBUG
+ cmn_err(CE_NOTE, "SMBIOS is not compatible with x86 generic topology.");
+ cmn_err(CE_NOTE, "Invoking legacy x86 topology enumeration.");
+#endif /* DEBUG */
+ x86gentopo_legacy = 1;
+}
+
+static int
+find_matching_apic(smbios_hdl_t *shp, uint16_t proc_id, uint_t strand_apicid)
+{
+ uint16_t ext_id;
+ int i, j;
+ smbios_processor_ext_t ep;
+ smbs_cnt_t *pstypes;
+ int strcnt;
+
+ strcnt = smb_cnttypes(shp, SUN_OEM_EXT_PROCESSOR);
+ if (strcnt == 0)
+ return (0);
+
+ pstypes = smb_create_strcnt(strcnt);
+ if (pstypes == NULL)
+ return (0);
+
+ pstypes->type = SUN_OEM_EXT_PROCESSOR;
+ smb_strcnt(shp, pstypes);
+ for (i = 0; i < pstypes->count; i++) {
+ ext_id = pstypes->ids[i]->id;
+ (void) smbios_info_extprocessor(shp, ext_id, &ep);
+ if (ep.smbpe_processor == proc_id) {
+ for (j = 0; j < ep.smbpe_n; j++) {
+ if (ep.smbpe_apicid[j] == strand_apicid) {
+ smb_free_strcnt(pstypes, strcnt);
+ return (1);
+ }
+ }
+ }
+ }
+ smb_free_strcnt(pstypes, strcnt);
+ return (0);
+}
+
+/*
+ * go throught the type 2 structure contained_ids looking for
+ * the type 4 which has strand_apicid == this strand_apicid
+ */
+static int
+find_matching_proc(smbios_hdl_t *shp, uint_t strand_apicid,
+ uint16_t bb_id, uint16_t proc_hdl, int is_proc)
+{
+ int n;
+ const smb_struct_t *sp;
+ smbios_bboard_t bb;
+ uint_t cont_count, cont_len;
+ uint16_t cont_id;
+ id_t *cont_hdl = NULL;
+ int rc;
+
+
+ (void) smbios_info_bboard(shp, bb_id, &bb);
+ cont_count = (uint_t)bb.smbb_contn;
+ if (cont_count == 0)
+ return (0);
+
+ cont_len = sizeof (id_t);
+ cont_hdl = kmem_zalloc(cont_count * cont_len, KM_SLEEP);
+ if (cont_hdl == NULL)
+ return (0);
+
+ rc = smbios_info_contains(shp, bb_id, cont_count, cont_hdl);
+ if (rc > SMB_CONT_MAX) {
+ kmem_free(cont_hdl, cont_count * cont_len);
+ return (0);
+ }
+ cont_count = MIN(rc, cont_count);
+
+ for (n = 0; n < cont_count; n++) {
+ cont_id = (uint16_t)cont_hdl[n];
+ sp = smb_lookup_id(shp, cont_id);
+ if (sp->smbst_hdr->smbh_type == SMB_TYPE_PROCESSOR) {
+ if (is_proc) {
+ if (find_matching_apic(shp, cont_id,
+ strand_apicid)) {
+ kmem_free(cont_hdl,
+ cont_count * cont_len);
+ return (1);
+ }
+ } else {
+ if (cont_id == proc_hdl) {
+ kmem_free(cont_hdl,
+ cont_count * cont_len);
+ return (1);
+ }
+ }
+ }
+ }
+ if (cont_hdl != NULL)
+ kmem_free(cont_hdl, cont_count * cont_len);
+
+ return (0);
+}
+
+void
+get_bboard_index(smbs_cnt_t *bbstypes, uint_t bb_id, bbindex_t *bb_idx)
+{
+ int curr_id, tmp_id;
+ int i, j, nb;
+ bbindex_t tmp_idx;
+
+ for (i = 0; i < MAX_PAIRS; i++)
+ tmp_idx.index[i] = 0;
+
+ tmp_idx.count = 0;
+
+ curr_id = bb_id;
+ for (nb = bbstypes->count-1, i = 0; nb >= 0; nb--) {
+ tmp_id = bbstypes->ids[nb]->id;
+ if (tmp_id == curr_id) {
+ tmp_idx.index[i] = nb;
+ tmp_idx.count++;
+ curr_id = bbstypes->ids[nb]->cont_by_id;
+ if (curr_id == -1)
+ break;
+ i++;
+ }
+ }
+
+ for (i = tmp_idx.count - 1, j = 0; i >= 0; i--) {
+ bb_idx->index[j] = tmp_idx.index[i];
+ j++;
+ }
+
+ bb_idx->count = tmp_idx.count;
+}
+
+int
+get_chassis_inst(smbios_hdl_t *shp, uint16_t *chassis_inst,
+ uint16_t bb_id, int *chcnt)
+{
+ int ch_strcnt;
+ smbs_cnt_t *chstypes;
+ uint16_t chassis_id, tmp_id;
+ smbios_bboard_t bb;
+ int rc = 0;
+ int i;
+
+ rc = smbios_info_bboard(shp, bb_id, &bb);
+ if (rc != 0) {
+ return (-1);
+ }
+
+ chassis_id = bb.smbb_chassis;
+
+ ch_strcnt = smb_cnttypes(shp, SMB_TYPE_CHASSIS);
+
+ if (ch_strcnt == 0)
+ return (-1);
+
+ chstypes = smb_create_strcnt(ch_strcnt);
+ if (chstypes == NULL)
+ return (-1);
+
+ chstypes->type = SMB_TYPE_CHASSIS;
+ smb_strcnt(shp, chstypes);
+
+ for (i = 0; i < chstypes->count; i++) {
+ tmp_id = chstypes->ids[i]->id;
+ if (tmp_id == chassis_id) {
+ *chassis_inst = chstypes->ids[i]->inst;
+ if (chstypes->ids[i]->inst != 0)
+ *chcnt = 2;
+ else
+ *chcnt = 1;
+ smb_free_strcnt(chstypes, ch_strcnt);
+ return (0);
+ }
+ }
+
+ smb_free_strcnt(chstypes, ch_strcnt);
+ return (-1);
+}
+
+int
+smb_get_bb_fmri(smbios_hdl_t *shp, nvlist_t *fmri, uint_t parent,
+ smbs_cnt_t *bbstypes)
+{
+ int rc = 0;
+ int i, j, n, cnt;
+ int id, index;
+ nvlist_t *pairs[MAX_PAIRS];
+ smbios_bboard_t bb;
+ uint16_t chassis_inst, mch_inst;
+ char name[40];
+ char idstr[11];
+ bbindex_t bb_idx;
+ uint16_t bbid;
+ int chcnt = 0;
+
+ for (n = 0; n < MAX_PAIRS; n++) {
+ bb_idx.index[n] = 0;
+ pairs[n] = NULL;
+ }
+ bb_idx.count = 0;
+
+ get_bboard_index(bbstypes, parent, &bb_idx);
+
+ index = bb_idx.index[0];
+ bbid = bbstypes->ids[index]->id;
+
+ rc = get_chassis_inst(shp, &chassis_inst, bbid, &chcnt);
+
+ if (rc != 0) {
+ return (rc);
+ }
+
+ if ((bb_idx.count + chcnt) > MAX_PAIRS) {
+ return (-1);
+ }
+
+ i = 0;
+ if (chcnt > 1) {
+ /*
+ * create main chassis pair
+ */
+ pairs[i] = fm_nvlist_create(NULL);
+ if (pairs[i] == NULL) {
+ return (-1);
+ }
+ mch_inst = 0;
+ (void) snprintf(idstr, sizeof (idstr), "%u", mch_inst);
+ if ((nvlist_add_string(pairs[i], FM_FMRI_HC_NAME,
+ "chassis") != 0) ||
+ (nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr)) != 0) {
+ fm_nvlist_destroy(pairs[i], FM_NVA_FREE);
+ return (-1);
+ }
+ i++;
+ }
+
+ /*
+ * create chassis pair
+ */
+ pairs[i] = fm_nvlist_create(NULL);
+ if (pairs[i] == NULL) {
+ for (n = 0; n < MAX_PAIRS; n++) {
+ if (pairs[n] != NULL)
+ fm_nvlist_destroy(pairs[n], FM_NVA_FREE);
+ }
+ return (-1);
+ }
+ (void) snprintf(idstr, sizeof (idstr), "%u", chassis_inst);
+ if ((nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, "chassis") != 0) ||
+ (nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr) != 0)) {
+ for (n = 0; n < MAX_PAIRS; n++) {
+ if (pairs[n] != NULL)
+ fm_nvlist_destroy(pairs[n], FM_NVA_FREE);
+ }
+ return (-1);
+ }
+
+ for (j = 0, i = chcnt, cnt = chcnt; j < bb_idx.count; j++) {
+ index = bb_idx.index[j];
+ bbid = bbstypes->ids[index]->id;
+ rc = smbios_info_bboard(shp, bbid, &bb);
+ if (rc != 0) {
+ rc = -1;
+ break;
+ }
+
+ pairs[i] = fm_nvlist_create(NULL);
+ if (pairs[i] == NULL) {
+ rc = -1;
+ break;
+ }
+
+ id = bbstypes->ids[index]->inst;
+ (void) snprintf(idstr, sizeof (idstr), "%u", id);
+ (void) strncpy(name, bbd_type[bb.smbb_type].name,
+ sizeof (name));
+ cnt++;
+
+ if (nvlist_add_string(pairs[i], FM_FMRI_HC_NAME, name) != 0 ||
+ nvlist_add_string(pairs[i], FM_FMRI_HC_ID, idstr)
+ != 0) {
+ rc = -1;
+ break;
+ }
+ i++;
+ }
+
+ if (rc != -1) {
+ if (nvlist_add_nvlist_array(fmri, FM_FMRI_HC_LIST,
+ pairs, cnt) != 0) {
+ rc = -1;
+ }
+ }
+
+ for (n = 0; n < cnt; n++) {
+ if (pairs[n] != NULL)
+ fm_nvlist_destroy(pairs[n], FM_NVA_FREE);
+ }
+
+ return (rc);
+}
+
+/*
+ * pass in strand_apic id
+ * return chip's bboards list which has strand_apicid == passed
+ * in strand_apic id
+ */
+static nvlist_t *
+smb_bboard(uint_t strand_apicid, uint16_t proc_hdl, int is_proc)
+{
+ smbios_hdl_t *shp;
+ smbs_cnt_t *bbstypes;
+ int nb;
+ int bb_smbid;
+ nvlist_t *fmri = NULL;
+ int rc = 0;
+ int bb_strcnt;
+
+ if (x86gentopo_legacy)
+ return (NULL);
+
+ shp = ksmbios;
+ if (shp == NULL) {
+ goto bad;
+ }
+
+ /*
+ * Type 2 structs : "base board"
+ */
+ bb_strcnt = smb_cnttypes(shp, SMB_TYPE_BASEBOARD);
+ if (bb_strcnt == 0) {
+ goto bad;
+ }
+
+ bbstypes = smb_create_strcnt(bb_strcnt);
+ if (bbstypes == NULL) {
+ goto bad;
+ }
+
+ bbstypes->type = SMB_TYPE_BASEBOARD;
+ smb_strcnt(shp, bbstypes);
+ smb_bb_contains(shp, bbstypes);
+
+ for (nb = 0; nb < bbstypes->count; nb++) {
+ if (bbstypes->ids[nb]->visited) {
+ continue;
+ }
+
+ bbstypes->ids[nb]->visited = 1;
+ bb_smbid = bbstypes->ids[nb]->id;
+
+ /*
+ * check if there is a matching processor under
+ * this board. If found, find base board(s) of this proc
+ * If proc is not in contained handle of a base board and
+ * there is only one base board in the system, treat that base
+ * board as the parent of the proc
+ */
+ if (find_matching_proc(shp, strand_apicid,
+ bb_smbid, proc_hdl, is_proc) || (bbstypes->count == 1)) {
+ fmri = fm_nvlist_create(NULL);
+ if (fmri == NULL) {
+ smb_free_strcnt(bbstypes, bb_strcnt);
+ goto bad;
+ }
+ /*
+ * find parent by walking the cont_by_id
+ */
+ rc = smb_get_bb_fmri(shp, fmri, bb_smbid, bbstypes);
+ smb_free_strcnt(bbstypes, bb_strcnt);
+ if (rc == 0) {
+ return (fmri);
+ } else
+ goto bad;
+ }
+
+ }
+
+ smb_free_strcnt(bbstypes, bb_strcnt);
+bad:
+ /* revert to legacy enumeration */
+ x86gentopo_legacy = 1;
+
+ return (NULL);
+}
+
+nvlist_t *
+fm_smb_bboard(uint_t strand_apicid)
+{
+ return (smb_bboard(strand_apicid, 0, PROC));
+}
+
+int
+fm_smb_chipinst(uint_t strand_apicid, uint_t *chip_inst, uint16_t *smbiosid)
+{
+ int n;
+ smbios_hdl_t *shp;
+ uint16_t proc_id;
+ smbs_cnt_t *pstypes;
+ int strcnt;
+
+ if (x86gentopo_legacy)
+ return (-1);
+
+ shp = ksmbios;
+ if (shp == NULL) {
+ goto bad;
+ }
+
+ strcnt = smb_cnttypes(shp, SMB_TYPE_PROCESSOR);
+ if (strcnt == 0)
+ goto bad;
+
+ pstypes = smb_create_strcnt(strcnt);
+ if (pstypes == NULL)
+ goto bad;
+
+ pstypes->type = SMB_TYPE_PROCESSOR;
+ smb_strcnt(shp, pstypes);
+ for (n = 0; n < pstypes->count; n++) {
+ proc_id = pstypes->ids[n]->id;
+ if (find_matching_apic(shp, proc_id, strand_apicid)) {
+ *chip_inst = pstypes->ids[n]->inst;
+ *smbiosid = pstypes->ids[n]->id;
+ smb_free_strcnt(pstypes, strcnt);
+ return (0);
+ }
+ }
+ smb_free_strcnt(pstypes, strcnt);
+bad:
+ /* revert to legacy enumerarion */
+ x86gentopo_legacy = 1;
+
+ return (-1);
+}
+
+nvlist_t *
+fm_smb_mc_bboards(uint_t bdf)
+{
+
+ int i;
+ smbios_hdl_t *shp;
+ uint16_t ext_id;
+ smbios_memarray_ext_t em;
+ nvlist_t *fmri = NULL;
+ smbs_cnt_t *mastypes;
+ int strcnt;
+
+ if (x86gentopo_legacy)
+ return (NULL);
+
+ shp = ksmbios;
+ if (shp == NULL) {
+ goto bad;
+ }
+
+ strcnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMARRAY);
+ if (strcnt == 0)
+ goto bad;
+
+ mastypes = smb_create_strcnt(strcnt);
+ if (mastypes == NULL)
+ goto bad;
+
+ mastypes->type = SUN_OEM_EXT_MEMARRAY;
+ smb_strcnt(shp, mastypes);
+ for (i = 0; i < mastypes->count; i++) {
+ ext_id = mastypes->ids[i]->id;
+ (void) smbios_info_extmemarray(shp, ext_id, &em);
+ if (em.smbmae_bdf == bdf) {
+ fmri = smb_bboard(0, em.smbmae_comp, MC);
+ smb_free_strcnt(mastypes, strcnt);
+ return (fmri);
+ }
+ }
+ smb_free_strcnt(mastypes, strcnt);
+bad:
+ /* revert to legacy enumerarion */
+ x86gentopo_legacy = 1;
+
+ return (NULL);
+}
+
+int
+fm_smb_mc_chipinst(uint_t bdf, uint_t *chip_inst) {
+
+ int i, j;
+ smbios_hdl_t *shp;
+ smbios_memarray_ext_t em;
+ uint16_t ext_id, proc_id;
+ smbs_cnt_t *mastypes;
+ smbs_cnt_t *pstypes;
+ int ma_strcnt, p_strcnt;
+
+ if (x86gentopo_legacy)
+ return (-1);
+
+ shp = ksmbios;
+ if (shp == NULL) {
+ goto bad;
+ }
+
+ ma_strcnt = smb_cnttypes(shp, SUN_OEM_EXT_MEMARRAY);
+ if (ma_strcnt == 0)
+ goto bad;
+
+ mastypes = smb_create_strcnt(ma_strcnt);
+ if (mastypes == NULL)
+ goto bad;
+
+ mastypes->type = SUN_OEM_EXT_MEMARRAY;
+ smb_strcnt(shp, mastypes);
+ for (i = 0; i < mastypes->count; i++) {
+ ext_id = mastypes->ids[i]->id;
+ (void) smbios_info_extmemarray(shp, ext_id, &em);
+ if (em.smbmae_bdf == bdf) {
+ p_strcnt = smb_cnttypes(shp, SMB_TYPE_PROCESSOR);
+ if (p_strcnt == 0) {
+ smb_free_strcnt(mastypes, ma_strcnt);
+ goto bad;
+ }
+
+ pstypes = smb_create_strcnt(p_strcnt);
+ if (pstypes == NULL) {
+ smb_free_strcnt(mastypes, ma_strcnt);
+ goto bad;
+ }
+
+ pstypes->type = SMB_TYPE_PROCESSOR;
+ smb_strcnt(shp, pstypes);
+ for (j = 0; j < pstypes->count; j++) {
+ proc_id = pstypes->ids[j]->id;
+ if (proc_id == em.smbmae_comp) {
+ *chip_inst = pstypes->ids[j]->inst;
+ smb_free_strcnt(mastypes, ma_strcnt);
+ smb_free_strcnt(pstypes, p_strcnt);
+ return (0);
+ }
+ }
+ }
+ }
+ smb_free_strcnt(mastypes, ma_strcnt);
+ smb_free_strcnt(pstypes, p_strcnt);
+bad:
+ /* revert to legacy enumeration */
+ x86gentopo_legacy = 1;
+
+ return (-1);
+}
diff --git a/usr/src/uts/intel/sys/cpu_module.h b/usr/src/uts/intel/sys/cpu_module.h
index 4f7d3fc605..7326602405 100644
--- a/usr/src/uts/intel/sys/cpu_module.h
+++ b/usr/src/uts/intel/sys/cpu_module.h
@@ -153,12 +153,16 @@ extern uint_t cmi_hdl_chipid(cmi_hdl_t);
extern uint_t cmi_hdl_dieid(cmi_hdl_t);
extern uint_t cmi_hdl_coreid(cmi_hdl_t);
extern uint_t cmi_hdl_strandid(cmi_hdl_t);
+extern uint_t cmi_hdl_strand_apicid(cmi_hdl_t);
extern boolean_t cmi_hdl_is_cmt(cmi_hdl_t);
extern uint32_t cmi_hdl_chiprev(cmi_hdl_t);
extern const char *cmi_hdl_chiprevstr(cmi_hdl_t);
extern uint32_t cmi_hdl_getsockettype(cmi_hdl_t);
extern const char *cmi_hdl_getsocketstr(cmi_hdl_t);
extern id_t cmi_hdl_logical_id(cmi_hdl_t);
+extern uint16_t cmi_hdl_smbiosid(cmi_hdl_t);
+extern uint_t cmi_hdl_smb_chipid(cmi_hdl_t);
+extern nvlist_t *cmi_hdl_smb_bboard(cmi_hdl_t);
extern int cmi_hdl_online(cmi_hdl_t, int, int *);
diff --git a/usr/src/uts/intel/sys/fm/smb/fmsmb.h b/usr/src/uts/intel/sys/fm/smb/fmsmb.h
new file mode 100644
index 0000000000..ae6dd61b30
--- /dev/null
+++ b/usr/src/uts/intel/sys/fm/smb/fmsmb.h
@@ -0,0 +1,52 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_FM_SMB_FMSMB_H
+#define _SYS_FM_SMB_FMSMB_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/nvpair.h>
+
+#ifdef _KERNEL
+#include <sys/systm.h>
+
+extern nvlist_t *fm_smb_bboard(uint_t);
+extern nvlist_t *fm_smb_mc_bboards(uint_t);
+extern int fm_smb_chipinst(uint_t, uint_t *, uint16_t *);
+extern int fm_smb_mc_chipinst(uint_t, uint_t *);
+extern void fm_smb_fmacompat();
+
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_FM_SMB_FMSMB_H */
diff --git a/usr/src/uts/intel/sys/hypervisor.h b/usr/src/uts/intel/sys/hypervisor.h
index 8219346731..7f2901c39e 100644
--- a/usr/src/uts/intel/sys/hypervisor.h
+++ b/usr/src/uts/intel/sys/hypervisor.h
@@ -132,6 +132,7 @@ extern int xen_physcpu_stepping(xen_mc_lcpu_cookie_t);
extern id_t xen_physcpu_chipid(xen_mc_lcpu_cookie_t);
extern id_t xen_physcpu_coreid(xen_mc_lcpu_cookie_t);
extern id_t xen_physcpu_strandid(xen_mc_lcpu_cookie_t);
+extern id_t xen_physcpu_initial_apicid(xen_mc_lcpu_cookie_t);
extern boolean_t xen_physcpu_is_cmt(xen_mc_lcpu_cookie_t);
extern id_t xen_physcpu_logical_id(xen_mc_lcpu_cookie_t);
extern uint64_t xen_physcpu_mcg_cap(xen_mc_lcpu_cookie_t);