Commit cd297828 authored by Huajingjing's avatar Huajingjing Committed by Zheng Zengkai
Browse files

Huawei BMA: Adding Huawei BMA driver: host_kbox_drv

driver inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I920YY
CVE: NA

-----------------------------------------

The BMA software is a system management software offered by Huawei. It supports
the status monitoring, performance monitoring, and event monitoring of various
components, including server CPUs, memory, hard disks, NICs, IB cards, PCIe
cards, RAID controller cards, and optical modules.

The host_kbox_drv driver serves the function of a black box. When a panic or mce
event happen to the system, it will record the event time, system's status and
system logs and send them to BMC before the OS shutdown. This driver depends on
the host_edma_drv driver.

Link: https://lkml.org/lkml/2020/6/22/752



Signed-off-by: default avatarHuajingjing <huajingjing1@huawei.com>
parent 0cafdd73
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -5,3 +5,4 @@
obj-$(CONFIG_BMA) += edma_drv/
obj-$(CONFIG_BMA) += cdev_drv/
obj-$(CONFIG_BMA) += veth_drv/
obj-$(CONFIG_BMA) += kbox_drv/
+5 −0
Original line number Diff line number Diff line
obj-$(CONFIG_BMA) += host_kbox_drv.o
host_kbox_drv-y := kbox_main.o kbox_ram_drive.o kbox_ram_image.o kbox_ram_op.o kbox_printk.o kbox_dump.o kbox_hook.o kbox_panic.o
ifdef CONFIG_X86
host_kbox_drv-y += kbox_mce.o
endif
 No newline at end of file
+121 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/* Huawei iBMA driver.
 * Copyright (c) 2017, Huawei Technologies Co., Ltd.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/spinlock.h>
#include <linux/utsname.h>		/* system_utsname */
#include <linux/rtc.h>		/* struct rtc_time */
#include "kbox_include.h"
#include "kbox_main.h"
#include "kbox_printk.h"
#include "kbox_ram_image.h"
#include "kbox_ram_op.h"
#include "kbox_dump.h"
#include "kbox_panic.h"

#ifdef CONFIG_X86
#include "kbox_mce.h"
#endif

#define THREAD_TMP_BUF_SIZE 256

static DEFINE_SPINLOCK(g_dump_lock);

static const char g_day_in_month[] = {
	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};

#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
#define LEAP_YEAR(year) \
	((!((year) % 4) && ((year) % 100)) || !((year) % 400))
#define MONTH_DAYS(month, year) \
	(g_day_in_month[(month)] + (int)(LEAP_YEAR(year) && (month == 1)))

static void kbox_show_kernel_version(void)
{
	(void)kbox_dump_painc_info
		("\nOS : %s,\nRelease : %s,\nVersion : %s,\n",
		 init_uts_ns.name.sysname,
		 init_uts_ns.name.release,
		 init_uts_ns.name.version);
	(void)kbox_dump_painc_info
		("Machine : %s,\nNodename : %s\n",
		 init_uts_ns.name.machine,
		 init_uts_ns.name.nodename);
}

static void kbox_show_version(void)
{
	(void)kbox_dump_painc_info("\nKBOX_VERSION         : %s\n",
				   KBOX_VERSION);
}

static void kbox_show_time_stamps(void)
{
	struct rtc_time rtc_time_val = { };
	struct timespec64 uptime;

	ktime_get_coarse_real_ts64(&uptime);
	rtc_time64_to_tm(uptime.tv_sec, &rtc_time_val);

	(void)kbox_dump_painc_info
		("Current time         : %04d-%02d-%02d %02d:%02d:%02d\n",
		 rtc_time_val.tm_year + 1900, rtc_time_val.tm_mon + 1,
		 rtc_time_val.tm_mday, rtc_time_val.tm_hour,
		 rtc_time_val.tm_min, rtc_time_val.tm_sec);
}

void kbox_dump_event(enum kbox_error_type_e type, unsigned long event,
		     const char *msg)
{
	if (!spin_trylock(&g_dump_lock))
		return;

	(void)kbox_dump_painc_info("\n====kbox begin dumping...====\n");

	switch (type) {
#ifdef CONFIG_X86
	case KBOX_MCE_EVENT:

		kbox_handle_mce_dump(msg);

		break;
#endif

	case KBOX_OPPS_EVENT:

		break;
	case KBOX_PANIC_EVENT:
		if (kbox_handle_panic_dump(msg) == KBOX_FALSE)
			goto end;

		break;
	default:
		break;
	}

	kbox_show_kernel_version();

	kbox_show_version();

	kbox_show_time_stamps();

	(void)kbox_dump_painc_info("\n====kbox end dump====\n");

	kbox_output_syslog_info();
	kbox_output_printk_info();

end:
	spin_unlock(&g_dump_lock);
}
+33 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/* Huawei iBMA driver.
 * Copyright (c) 2017, Huawei Technologies Co., Ltd.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#ifndef _KBOX_DUMP_H_
#define _KBOX_DUMP_H_

#define DUMPSTATE_MCE_RESET 1
#define DUMPSTATE_OPPS_RESET 2
#define DUMPSTATE_PANIC_RESET 3

enum kbox_error_type_e {
	KBOX_MCE_EVENT = 1,
	KBOX_OPPS_EVENT,
	KBOX_PANIC_EVENT
};

int kbox_dump_thread_info(const char *fmt, ...);
void kbox_dump_event(enum kbox_error_type_e type, unsigned long event,
		     const char *msg);

#endif
+102 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/* Huawei iBMA driver.
 * Copyright (c) 2017, Huawei Technologies Co., Ltd.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/notifier.h>
#include <linux/panic_notifier.h>
#include "kbox_include.h"
#include "kbox_dump.h"
#include "kbox_hook.h"

int panic_notify(struct notifier_block *this,
		 unsigned long event, void *msg);

static int die_notify(struct notifier_block *self,
		      unsigned long val, void *data);

static struct notifier_block g_panic_nb = {
	.notifier_call = panic_notify,
	.priority = 100,
};

static struct notifier_block g_die_nb = {
	.notifier_call = die_notify,
};

int panic_notify(struct notifier_block *pthis, unsigned long event, void *msg)
{
	UNUSED(pthis);
	UNUSED(event);

	kbox_dump_event(KBOX_PANIC_EVENT, DUMPSTATE_PANIC_RESET,
			(const char *)msg);

	return NOTIFY_OK;
}

int die_notify(struct notifier_block *self, unsigned long val, void *data)
{
	struct kbox_die_args *args = (struct kbox_die_args *)data;

	if (!args)
		return NOTIFY_OK;

	switch (val) {
	case 1:
		break;
	case 5:
		if (strcmp(args->str, "nmi") == 0)
			return NOTIFY_OK;
#ifdef CONFIG_X86
		kbox_dump_event(KBOX_MCE_EVENT, DUMPSTATE_MCE_RESET, args->str);
#endif
		break;

	default:
		break;
	}

	return NOTIFY_OK;
}

int kbox_register_hook(void)
{
	int ret = 0;

	ret = atomic_notifier_chain_register(&panic_notifier_list, &g_panic_nb);
	if (ret)
		KBOX_MSG("atomic_notifier_chain_register g_panic_nb failed!\n");

	ret = register_die_notifier(&g_die_nb);
	if (ret)
		KBOX_MSG("register_die_notifier g_die_nb failed!\n");

	return ret;
}

void kbox_unregister_hook(void)
{
	int ret = 0;

	ret =
	    atomic_notifier_chain_unregister(&panic_notifier_list, &g_panic_nb);
	if (ret < 0) {
		KBOX_MSG
		    ("atomic_notifier_chain_unregister g_panic_nb failed!\n");
	}

	ret = unregister_die_notifier(&g_die_nb);
	if (ret < 0)
		KBOX_MSG("unregister_die_notifier g_die_nb failed!\n");
}
Loading