很多企业的核心业务大都运行在服务器系上,一旦系统出现非预料的宕机,很可能造成数据出错甚至丢失,这种情况如果发生在金融和银行系统上,将会造成不可估量的损失。为此,有必要实时检测服务器的健康状态,包括风扇转速、CPU和主板的温度、核心电压、电源模块的状态等,进而及时预报各种可能出现的错误。系统管理软件(system managemnet software)就是为了实现这一功能的,它依赖于各个厂家的主板和模块的实现方式。为了统一不同厂家的实现方法,1998年Intel、Dell、HP、NEC共同提出了IPMI 规范,用来监控温度、电压、风扇转速和实现远程控制。到2004年IPMI 规范已经发展到了2.0颁布,并且广泛应用在各种服务器上,不同的厂家为了实现额外的功能,大都都扩展了一些OEM的IPMI命令给用户。这就极大地方便了系统管理软件的设计和实现。
一个典型的IPMI的总的架构如下图所示:
通过上面的图可以看到 ,一个系统上可能有多个BMC,BMC上可以连接一些非智能的卡或者sensor,这些器件和 BMC以及BMC之间通过IPMB连接。和BMC通信的接口的包括Smbus、PCIE、USB和LPC。I2C在早期的系统上用得比较普遍 ,PCIE常用作KVM,而USB多用于固件升级,LPC接口最常见。BMC和 主机之间的接口叫作system management interface(简称system interface或si)。传统的BMC的system interface包括:
KCS:最常用的接口 ,物理层基于LPC协议,实现了 8742 KCS interface,后文的System interface默认就是LPC接口
SMIC (system management interface chip):用在没有内建的KCS/LPC控制器的BMC上,有三个IO Port,可基于ASIC/FPGA实现。
BT接口: 速度和性能最好的接口,需要握手,同样可基于ASIC/FPGA实现3个IO port,可用于定制化的BMC上。
2.System Interface接口
LPC的全称是Low Pin Count interface,它通过CLK信号LFRAM和复用的AD信号来实现类似PCI协议的多种操作,包括IO Read/Write,Memory Read/Write, Sync,TAR,按照下面的时序执行各种操作,进而实现上层的KCS (keyboard control style)接口。
Host和BMC之间通过LPC引脚直接连接。Host端的原理图如下图所示,其中最右侧的一列信号来自于主机的LPC控制器。
3. 驱动的实现
内核中IPMI驱动是分层实现的,最底层分别实现了基于Smbus、LPC的自动检测、事物处理、结果读取和清除的操作,并用这些函数初始化了抽象的system interface的对应的函数,从而屏蔽了底层硬件接口的区别。更上层的设备抽象和协议实现都是直接和抽象的system interface直接交互的。具体的说明可以参考内核中的Documentation/IPMI.txt文档,简要的归纳如下:
ipmi_smbus.ko: 实现对 IPMI management controller基于Smbus直接访问的接口驱动;
ipmi_ssif.ko: 在更早的内核版本里对应的名字就是 ipmi_smbus.ko,支持通过Smbus接口发送、接受信息;
ipmi_si.ko: 屏蔽了不同系统接口的驱动,支持KCS/SMIC/BT,除非host 和BMC之间使用Smbus或者其他定制化的接口,否则都需要这一标准驱动;定义了probe BMC的三种方法:ACPI/SMBIOS(DMI)/PCI (class type);
ipmi_msghandler.ko: 内核用它来实现IPMI协议规范 ,它注册了 IPMI驱动;
ipmi_devintf.ko: provides a userland IOCTL interface for the IPMI driver,每一个打开的文件都都对应到一个消息处理句柄。定义了 /dev/ipmi0对应的ioctl/open/release/fasync/poll/llseek的操作,给应用层程序提供了fs接口。其中ioctl的操作类型包括:
IPMICTL_SEND_COMMAND,IPMICTL_SEND_COMMAND,IPMICTL_RECEIVE_MSG和 IPMICTL_RECEIVE_MSG_TRUNC。应用程序就是通过打开/dev/ipmi0或者/dev/ipmi0并调用各种IOCTL来实现和BMC的通信的;
ipmi_watchdog.ko:向上层用户提供一个标准的linux 看门狗计时器;
ipmi_poweroff.ko: 支持通过ipmi命令开关机的内核驱动。