linux mce的一些相关内容和用户态监控的设计方法

之所以想起写一点关于mce的东西,倒不是因为遇到mce的异常了,之前遇到过很多mce的异常,内存居多,但没有好好记录下来,写这个是因为参加2018 clk南京会议的一点想法。

 
  1. void __init trap_init(void)
  2. {
  3. 。。。
  4. #ifdef CONFIG_X86_MCE
  5. set_intr_gate_ist(X86_TRAP_MC, &machine_check, MCE_STACK);
  6. #endif
  7. 。。。
  8. }

其中mce的初始化流程为:

Start_kernel-->check_bugs-->identify_boot_cpu-->identify_cpu-->mcheck_cpu_init

 
  1. /*
  2. * Called for each booted CPU to set up machine checks.
  3. * Must be called with preempt off:
  4. */
  5. void mcheck_cpu_init(struct cpuinfo_x86 *c)
  6. {
  7. ...
  8. machine_check_vector = do_machine_check;----------这个函数,主要工作函数
  9. __mcheck_cpu_init_generic();
  10. __mcheck_cpu_init_vendor(c);
  11. __mcheck_cpu_init_clear_banks();
  12. __mcheck_cpu_init_timer();
  13. ....
  14. }

如果为了调试mce功能,模拟硬件真的出问题,那么可以使用 mce-inject 用户态工具来实现,对应内核的函数为:

 
  1. void mce_inject_log(struct mce *m)
  2. {
  3. mutex_lock(&mce_chrdev_read_mutex);
  4. mce_log(m);
  5. mutex_unlock(&mce_chrdev_read_mutex);
  6. }

当然调试的时候,一般需要修改tolerant 值,不然有可能引起复位:

 
  1. cat /sys/devices/system/machinecheck/machinecheck15/tolerant
  2. [root@centos7 ~]#
  3. [root@centos7 ~]# ls -alrt /sys/devices/system/machinecheck/machinecheck15/tolerant
  4. -rw-r--r--. root root 10月 : /sys/devices/system/machinecheck/machinecheck15/tolerant
  5. [root@centos7 ~]# echo > /sys/devices/system/machinecheck/machinecheck15/tolerant
  6. [root@centos7 ~]# cat /sys/devices/system/machinecheck/machinecheck15/tolerant
  7. /*
  8. * Tolerant levels:
  9. * 0: always panic on uncorrected errors, log corrected errors
  10. * 1: panic or SIGBUS on uncorrected errors, log corrected errors
  11. * 2: SIGBUS or log uncorrected errors (if possible), log corr. errors
  12. * 3: never panic or SIGBUS, log all errors (for testing only)
  13. */

下面描述的是引发思考的过程,即mce的通知机制,为什么突然想写mce的机制,是因为其实它应用的模式可以解签,

我们把内核维护mce数据的方式视为mce数据的生产者,而用户态取该数据视为消费者的话,生产消费模型非常明显,针对这种模型,一般由两种方式来处理:

1.轮询,

2.中断通知

其中中断通知又可以细分为有守护进程,即daemon 方式,还有一种是无守护进程,直接回调一个trigger的方式。

 
  1. [root@centos7 ~]# ps -ef |grep -i mce
  2. root 10月13 ? :: /usr/sbin/mcelog --ignorenodev --daemon --syslog
  3. root : pts/ :: grep --color=auto -i mce
  4. [root@centos7 ~]# cat /proc//stack
  5. [<ffffffff81212b95>] poll_schedule_timeout+0x55/0xb0
  6. [<ffffffff8121411d>] do_sys_poll+0x4cd/0x580
  7. [<ffffffff8121443e>] SyS_ppoll+0xce/0x1d0
  8. [<ffffffff816965c9>] system_call_fastpath+0x16/0x1b
  9. [<ffffffffffffffff>] 0xffffffffffffffff

上面这个例子就是daemon方式,等待在poll中,等内核事件通知。

等待的文件名是/dev/mcelog:

 
  1. [root@centos7 ~]# lsof -p
  2. COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
  3. mcelog root cwd DIR , /
  4. mcelog root rtd DIR , /
  5. mcelog root txt REG , /usr/sbin/mcelog
  6. mcelog root mem REG , /usr/lib64/libnss_files-2.17.so
  7. mcelog root mem REG , /usr/lib64/libc-2.17.so
  8. mcelog root mem REG , /usr/lib64/ld-2.17.so
  9. mcelog root 0u CHR , 0t0 /dev/null
  10. mcelog root 1u CHR , 0t0 /dev/null
  11. mcelog root 2u CHR , 0t0 /dev/null
  12. mcelog root 3r CHR , 0t0 /dev/mcelog------------------这个设备
  13. mcelog root 4u unix 0xffff880035de8000 0t0 /var/run/mcelog-client

那么,既然是sys文件系统,肯定有对应的read和write来提供给用户使用,read显而易见,是读取mce日志,write是干啥的?其实这里的write主要就是为了给别人注册用的,mce本身不是

调用write来写数据,它直接维护一个数据区,等别人来读,另外daemon是使用poll方法来等待的,所以自然还得实现poll方法:

 
  1. static const struct file_operations mce_chrdev_ops = {
  2. .open = mce_chrdev_open,
  3. .release = mce_chrdev_release,
  4. .read = mce_chrdev_read,
  5. .write = mce_chrdev_write,
  6. .poll = mce_chrdev_poll,
  7. .unlocked_ioctl = mce_chrdev_ioctl,
  8. .llseek = no_llseek,
  9. };

poll方法的最终实现:

 
  1. static unsigned int mce_chrdev_poll(struct file *file, poll_table *wait)
  2. {
  3. poll_wait(file, &mce_chrdev_wait, wait);----------一般阻塞在这,mce_chrdev_wait是一个等待队列
  4. if (READ_ONCE(mcelog.next))
  5. return POLLIN | POLLRDNORM;
  6. if (!mce_apei_read_done && apei_check_mce())
  7. return POLLIN | POLLRDNORM;
  8. return ;
  9. }

既然有等待队列,自然而然就会想,我什么时候唤醒:

 
  1. int mce_notify_irq(void)
  2. {
  3. /* Not more than two messages every minute */
  4. static DEFINE_RATELIMIT_STATE(ratelimit, *HZ, );
  5. if (test_and_clear_bit(, &mce_need_notify)) {
  6. /* wake processes polling /dev/mcelog */
  7. wake_up_interruptible(&mce_chrdev_wait);
  8. if (mce_helper[])
  9. schedule_work(&mce_trigger_work);
  10. if (__ratelimit(&ratelimit))
  11. pr_info(HW_ERR "Machine check events logged\n");
  12. return ;
  13. }
  14. return ;
  15. }

既然mce的来源有用户调试,以及真实检测,所以很自然唤醒也有多个来源。比如inject来唤醒和mce真实中断唤醒。

用户进程被poll唤醒之后,一般是poll_in,自然需要去读取数据,直接调用read方法就行。也就是一个简单的read和poll,就解决了监控用户态侧的大部分功能。

其他信息就不一一列了,昨天参加clk南京的会议,其中富士通一个兄弟说他们实现了NVDIMM 的一个监控,原因在于他们认为NVDIMM 是很难replace,所有有必要监控它。

它列出了一个模型,就是用户态daemon,然后设置filter到内核,内核将其监控到的event发给等待的用户进程,使用的方法正是triggers a poll event ,和目前的mce有异曲同工之妙。

假设让你设计这种监控类的东西,你会怎么设计呢?

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值