Mercurial > illumos > illumos-gate
changeset 10942:eaa343de0d06
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
line wrap: on
line diff
--- a/usr/src/cmd/fm/eversholt/files/i386/i86pc/intel.esc Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/cmd/fm/eversholt/files/i386/i86pc/intel.esc Tue Nov 03 21:14:05 2009 -0500 @@ -434,12 +434,12 @@ */ #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 @@ 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 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 @@ { 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 @@ 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 @@ 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("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 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 @@ /* 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_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_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_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_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("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_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_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 @@ 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 @@ 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]) &&
--- a/usr/src/cmd/mdb/intel/modules/generic_cpu/gcpu.c Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/cmd/mdb/intel/modules/generic_cpu/gcpu.c Tue Nov 03 21:14:05 2009 -0500 @@ -45,6 +45,9 @@ 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 {
--- a/usr/src/cmd/smbios/smbios.c Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/cmd/smbios/smbios.c Tue Nov 03 21:14:05 2009 -0500 @@ -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 @@ 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 @@ 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 @@ 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 @@ } 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 @@ 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++; }
--- a/usr/src/common/smbios/smb_info.c Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/common/smbios/smb_info.c Tue Nov 03 21:14:05 2009 -0500 @@ -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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 0, 0, offsetof(smb_cache_t, smbca_socket), + 0, + 0, + 0, 0 }, { SMB_TYPE_PORT, 0, @@ -121,6 +140,9 @@ 0, 0, offsetof(smb_port_t, smbpo_iref), + 0, + 0, + 0, 0 }, { SMB_TYPE_SLOT, 0, @@ -129,6 +151,9 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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); +}
--- a/usr/src/common/smbios/smb_open.c Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/common/smbios/smb_open.c Tue Nov 03 21:14:05 2009 -0500 @@ -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 @@ } 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;
--- a/usr/src/lib/fm/topo/libtopo/common/mapfile-vers Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/lib/fm/topo/libtopo/common/mapfile-vers Tue Nov 03 21:14:05 2009 -0500 @@ -121,6 +121,7 @@ topo_mod_unregister; topo_mod_walk_init; topo_mod_zalloc; + topo_mod_smbios; topo_node_asru; topo_node_asru_set; topo_node_bind;
--- a/usr/src/lib/fm/topo/libtopo/common/topo_mod.map Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/lib/fm/topo/libtopo/common/topo_mod.map Tue Nov 03 21:14:05 2009 -0500 @@ -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;
--- a/usr/src/lib/fm/topo/maps/i86pc/Makefile Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/lib/fm/topo/maps/i86pc/Makefile Tue Nov 03 21:14:05 2009 -0500 @@ -27,7 +27,7 @@ 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
--- a/usr/src/lib/fm/topo/maps/i86pc/i86pc-hc-topology.xml Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/lib/fm/topo/maps/i86pc/i86pc-hc-topology.xml Tue Nov 03 21:14:05 2009 -0500 @@ -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'>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/fm/topo/maps/i86pc/i86pc-legacy-hc-topology.xml Tue Nov 03 21:14:05 2009 -0500 @@ -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>
--- a/usr/src/lib/fm/topo/modules/common/pcibus/did_props.c Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/lib/fm/topo/modules/common/pcibus/did_props.c Tue Nov 03 21:14:05 2009 -0500 @@ -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 @@ { 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 @@ { 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);
--- a/usr/src/lib/fm/topo/modules/i86pc/Makefile Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/lib/fm/topo/modules/i86pc/Makefile Tue Nov 03 21:14:05 2009 -0500 @@ -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)
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/Makefile Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/lib/fm/topo/modules/i86pc/chip/Makefile Tue Nov 03 21:14:05 2009 -0500 @@ -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 @@ 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
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip.c Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip.c Tue Nov 03 21:14:05 2009 -0500 @@ -143,7 +143,7 @@ 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ } } - 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 @@ 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 @@ 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 @@ 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_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 @@ /*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 @@ } } + /* + * 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();
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip.h Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip.h Tue Nov 03 21:14:05 2009 -0500 @@ -37,6 +37,21 @@ #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 @@ /* * 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
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip_amd.c Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip_amd.c Tue Nov 03 21:14:05 2009 -0500 @@ -98,6 +98,19 @@ { 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 @@ */ /*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 @@ (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 @@ * 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); - 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 @@ 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 @@ } 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 @@ } 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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ * (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 @@ 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"); /*
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip_intel.c Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip_intel.c Tue Nov 03 21:14:05 2009 -0500 @@ -145,6 +145,9 @@ (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 @@ } 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 @@ 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 @@ } } 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 @@ 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 @@ 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 @@ } 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 @@ (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_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 @@ 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 @@ 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 @@ } 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 @@ 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)); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip_smbios.c Tue Nov 03 21:14:05 2009 -0500 @@ -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); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/Makefile Tue Nov 03 21:14:05 2009 -0500 @@ -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 $<
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi.c Tue Nov 03 21:14:05 2009 -0500 @@ -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); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_bboard.c Tue Nov 03 21:14:05 2009 -0500 @@ -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); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_chassis.c Tue Nov 03 21:14:05 2009 -0500 @@ -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); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_generic.c Tue Nov 03 21:14:05 2009 -0500 @@ -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); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_hostbridge.c Tue Nov 03 21:14:05 2009 -0500 @@ -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)); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_impl.h Tue Nov 03 21:14:05 2009 -0500 @@ -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 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi_subr.c Tue Nov 03 21:14:05 2009 -0500 @@ -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); +}
--- a/usr/src/lib/libsmbios/common/mapfile-vers Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/lib/libsmbios/common/mapfile-vers Tue Nov 03 21:14:05 2009 -0500 @@ -81,26 +81,32 @@ 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;
--- a/usr/src/pkgdefs/SUNWfmd/prototype_i386 Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/pkgdefs/SUNWfmd/prototype_i386 Tue Nov 03 21:14:05 2009 -0500 @@ -82,11 +82,13 @@ 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
--- a/usr/src/uts/common/io/devfm.c Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/uts/common/io/devfm.c Tue Nov 03 21:14:05 2009 -0500 @@ -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 @@ #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 @@ { 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 @@ 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 }, };
--- a/usr/src/uts/common/os/fm.c Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/uts/common/os/fm.c Tue Nov 03 21:14:05 2009 -0500 @@ -1269,3 +1269,102 @@ 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; + } + } +}
--- a/usr/src/uts/common/sys/devfm.h Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/uts/common/sys/devfm.h Tue Nov 03 21:14:05 2009 -0500 @@ -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 @@ #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 @@ #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 @@ #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 @@ #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"
--- a/usr/src/uts/common/sys/fm/protocol.h Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/uts/common/sys/fm/protocol.h Tue Nov 03 21:14:05 2009 -0500 @@ -323,6 +323,8 @@ 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);
--- a/usr/src/uts/common/sys/smbios.h Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/uts/common/sys/smbios.h Tue Nov 03 21:14:05 2009 -0500 @@ -126,6 +126,10 @@ #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 @@ 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 @@ 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 @@ /* * 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 @@ 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 @@ #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 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 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 *);
--- a/usr/src/uts/common/sys/smbios_impl.h Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/uts/common/sys/smbios_impl.h Tue Nov 03 21:14:05 2009 -0500 @@ -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 @@ 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 {
--- a/usr/src/uts/i86pc/cpu/amd_opteron/ao_mca.c Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/uts/i86pc/cpu/amd_opteron/ao_mca.c Tue Nov 03 21:14:05 2009 -0500 @@ -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 @@ } 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 @@ (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 @@ } 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 @@ 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 @@ 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); } }
--- a/usr/src/uts/i86pc/cpu/authenticamd/authamd_main.c Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/uts/i86pc/cpu/authenticamd/authamd_main.c Tue Nov 03 21:14:05 2009 -0500 @@ -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 @@ nvlist_t *nvl; int nelems = 0; int i, chan, cs; + nvlist_t *board_list = NULL; if ((msl = mslogout) == NULL) return; @@ -997,12 +1002,25 @@ 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); + } } }
--- a/usr/src/uts/i86pc/cpu/generic_cpu/gcpu_mca.c Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/uts/i86pc/cpu/generic_cpu/gcpu_mca.c Tue Nov 03 21:14:05 2009 -0500 @@ -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 @@ 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); }
--- a/usr/src/uts/i86pc/cpu/genuineintel/gintel_main.c Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/uts/i86pc/cpu/genuineintel/gintel_main.c Tue Nov 03 21:14:05 2009 -0500 @@ -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 @@ } } +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 @@ { 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 @@ } 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 @@ 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);
--- a/usr/src/uts/i86pc/os/cmi.c Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/uts/i86pc/os/cmi.c Tue Nov 03 21:14:05 2009 -0500 @@ -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_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 @@ cms_init(hdl); + cmi_read_smbios(hdl); + mutex_exit(&cmi_load_lock); return (hdl);
--- a/usr/src/uts/i86pc/os/cmi_hw.c Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/uts/i86pc/os/cmi_hw.c Tue Nov 03 21:14:05 2009 -0500 @@ -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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } 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(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 @@ 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 @@ 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 @@ 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 @@ 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 };
--- a/usr/src/uts/i86pc/os/startup.c Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/uts/i86pc/os/startup.c Tue Nov 03 21:14:05 2009 -0500 @@ -1545,6 +1545,18 @@ */ 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 @@ 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
--- a/usr/src/uts/i86xpv/os/xen_machdep.c Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/uts/i86xpv/os/xen_machdep.c Tue Nov 03 21:14:05 2009 -0500 @@ -1275,6 +1275,12 @@ } 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);
--- a/usr/src/uts/intel/Makefile.files Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/uts/intel/Makefile.files Tue Nov 03 21:14:05 2009 -0500 @@ -45,6 +45,7 @@ desctbls_asm.o \ exception.o \ float.o \ + fmsmb.o \ fpu.o \ i86_subr.o \ lock_prim.o \
--- a/usr/src/uts/intel/io/devfm_machdep.c Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/uts/intel/io/devfm_machdep.c Tue Nov 03 21:14:05 2009 -0500 @@ -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 @@ 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 @@ 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 @@ 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 @@ 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); +}
--- a/usr/src/uts/intel/io/mc-amd/mcamd.h Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/uts/intel/io/mc-amd/mcamd.h Tue Nov 03 21:14:05 2009 -0500 @@ -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 @@ 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 {
--- a/usr/src/uts/intel/io/mc-amd/mcamd_drv.c Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/uts/intel/io/mc-amd/mcamd_drv.c Tue Nov 03 21:14:05 2009 -0500 @@ -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 @@ 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 @@ } 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->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 @@ /* Integrate this memory controller device into existing set */ if (mc == NULL) { - mc = mc_create(chipid); + mc = mc_create(chipid, dip); if (mc == NULL) { /*
--- a/usr/src/uts/intel/io/mc-amd/mcamd_subr.c Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/uts/intel/io/mc-amd/mcamd_subr.c Tue Nov 03 21:14:05 2009 -0500 @@ -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 @@ } 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 @@ 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 @@ * 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 @@ } 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 @@ { 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 @@ 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);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/intel/os/fmsmb.c Tue Nov 03 21:14:05 2009 -0500 @@ -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); +}
--- a/usr/src/uts/intel/sys/cpu_module.h Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/uts/intel/sys/cpu_module.h Tue Nov 03 21:14:05 2009 -0500 @@ -153,12 +153,16 @@ 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 *);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/intel/sys/fm/smb/fmsmb.h Tue Nov 03 21:14:05 2009 -0500 @@ -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 */
--- a/usr/src/uts/intel/sys/hypervisor.h Tue Nov 03 17:06:24 2009 -0800 +++ b/usr/src/uts/intel/sys/hypervisor.h Tue Nov 03 21:14:05 2009 -0500 @@ -132,6 +132,7 @@ 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);