hv: debug: add the hypervisor NPK log
The npk_log is a log destination for the hypervisor, similar to the console_log and the mem_log. It can be enabled/disabled/configured by the SOS kernel via the hypercall HC_SETUP_HV_NPK_LOG. The configuration includes: 1. Set the MMIO base address of the reserved NPK master. 2. Set the log level of the hypervisor NPK log. After that, the npk_log can be enabled to write the hypervisor logs to the MMIO address of the reserved NPK master with a simple header. Signed-off-by: Zhi Jin <zhi.jin@intel.com> Signed-off-by: Liu, Xiaojing <xiaojing.liu@intel.com> Reviewed-by: CHEN Gang <gang.c.chen@intel.com> Acked-by: Anthony Xu <anthony.xu@intel.com>
This commit is contained in:
parent
3c6df9b70c
commit
6367650a70
|
@ -50,7 +50,7 @@ config LOG_BUF_SIZE
|
|||
|
||||
config LOG_DESTINATION
|
||||
int "Bitmap of consoles where logs are printed"
|
||||
default 3
|
||||
default 7
|
||||
|
||||
config CPU_UP_TIMEOUT
|
||||
int "Timeout in ms when bringing up secondary CPUs"
|
||||
|
@ -99,6 +99,10 @@ config MEM_LOGLEVEL_DEFAULT
|
|||
int "Default loglevel in memory"
|
||||
default 5
|
||||
|
||||
config NPK_LOGLEVEL_DEFAULT
|
||||
int "Default loglevel for the hypervisor NPK log"
|
||||
default 5
|
||||
|
||||
config LOW_RAM_SIZE
|
||||
hex "Size of the low RAM region"
|
||||
default 0x00010000
|
||||
|
|
|
@ -89,14 +89,17 @@ void do_logmsg(uint32_t severity, const char *fmt, ...)
|
|||
uint16_t pcpu_id;
|
||||
bool do_console_log;
|
||||
bool do_mem_log;
|
||||
bool do_npk_log;
|
||||
char *buffer;
|
||||
|
||||
do_console_log = (((logmsg.flags & LOG_FLAG_STDOUT) != 0U) &&
|
||||
(severity <= console_loglevel));
|
||||
do_mem_log = (((logmsg.flags & LOG_FLAG_MEMORY) != 0U) &&
|
||||
(severity <= mem_loglevel));
|
||||
do_npk_log = ((logmsg.flags & LOG_FLAG_NPK) != 0U &&
|
||||
(severity <= npk_loglevel));
|
||||
|
||||
if (!do_console_log && !do_mem_log) {
|
||||
if (!do_console_log && !do_mem_log && !do_npk_log) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -124,6 +127,10 @@ void do_logmsg(uint32_t severity, const char *fmt, ...)
|
|||
- strnlen_s(buffer, LOG_MESSAGE_MAX_SIZE), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
/* Check if flags specify to output to NPK */
|
||||
if (do_npk_log)
|
||||
npk_log_write(buffer, strnlen_s(buffer, LOG_MESSAGE_MAX_SIZE));
|
||||
|
||||
/* Check if flags specify to output to stdout */
|
||||
if (do_console_log) {
|
||||
spinlock_irqsave_obtain(&(logmsg.lock), &rflags);
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright (C) 2018 Intel Corporation.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <hypervisor.h>
|
||||
|
||||
static int npk_log_enabled, npk_log_setup_ref;
|
||||
static uint64_t base;
|
||||
|
||||
static inline int npk_write(const char *value, void *addr, size_t sz)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
if (sz >= 8U) {
|
||||
mmio_write64(*(uint64_t *)value, addr);
|
||||
ret = 8;
|
||||
} else if (sz >= 4U) {
|
||||
mmio_write32(*(uint32_t *)value, addr);
|
||||
ret = 4;
|
||||
} else if (sz >= 2U) {
|
||||
mmio_write16(*(uint16_t *)value, addr);
|
||||
ret = 2;
|
||||
} else if (sz >= 1U) {
|
||||
mmio_write8(*(uint8_t *)value, addr);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void npk_log_setup(struct hv_npk_log_param *param)
|
||||
{
|
||||
int i;
|
||||
|
||||
pr_info("HV_NPK_LOG: cmd %d param 0x%llx\n", param->cmd,
|
||||
param->mmio_addr);
|
||||
|
||||
param->res = HV_NPK_LOG_RES_KO;
|
||||
if (atomic_inc_return(&npk_log_setup_ref) > 1)
|
||||
goto out;
|
||||
|
||||
switch (param->cmd) {
|
||||
case HV_NPK_LOG_CMD_CONF:
|
||||
if (param->mmio_addr || param->loglevel != 0xffffU)
|
||||
param->res = HV_NPK_LOG_RES_OK;
|
||||
case HV_NPK_LOG_CMD_ENABLE:
|
||||
if (param->mmio_addr)
|
||||
base = param->mmio_addr;
|
||||
if (param->loglevel != 0xffffU)
|
||||
npk_loglevel = param->loglevel;
|
||||
if (base && param->cmd == HV_NPK_LOG_CMD_ENABLE) {
|
||||
if (!npk_log_enabled)
|
||||
for (i = 0; i < phys_cpu_num; i++)
|
||||
per_cpu(npk_log_ref, i) = 0;
|
||||
param->res = HV_NPK_LOG_RES_OK;
|
||||
npk_log_enabled = 1;
|
||||
}
|
||||
break;
|
||||
case HV_NPK_LOG_CMD_DISABLE:
|
||||
npk_log_enabled = 0;
|
||||
param->res = HV_NPK_LOG_RES_OK;
|
||||
break;
|
||||
case HV_NPK_LOG_CMD_QUERY:
|
||||
param->res = npk_log_enabled ? HV_NPK_LOG_RES_ENABLED :
|
||||
HV_NPK_LOG_RES_DISABLED;
|
||||
param->loglevel = npk_loglevel;
|
||||
param->mmio_addr = base;
|
||||
break;
|
||||
default:
|
||||
pr_err("HV_NPK_LOG: unknown cmd (%d)\n", param->cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
pr_info("HV_NPK_LOG: result %d\n", param->res);
|
||||
atomic_dec32((uint32_t *)&npk_log_setup_ref);
|
||||
}
|
||||
|
||||
void npk_log_write(const char *buf, size_t buf_len)
|
||||
{
|
||||
uint32_t cpu_id = get_cpu_id();
|
||||
struct npk_chan *channel = (struct npk_chan *)base;
|
||||
const char *p = buf;
|
||||
int sz;
|
||||
uint32_t ref;
|
||||
size_t len;
|
||||
|
||||
if (!npk_log_enabled || !channel)
|
||||
return;
|
||||
|
||||
/* calculate the channel offset based on cpu_id and npk_log_ref */
|
||||
ref = (atomic_inc_return((int *)&per_cpu(npk_log_ref, cpu_id)) - 1)
|
||||
& HV_NPK_LOG_REF_MASK;
|
||||
channel += (cpu_id << HV_NPK_LOG_REF_SHIFT) + ref;
|
||||
len = min(buf_len, HV_NPK_LOG_MAX);
|
||||
mmio_write32(HV_NPK_LOG_HDR, &(channel->DnTS));
|
||||
mmio_write16(len, &(channel->Dn));
|
||||
|
||||
for (sz = 0; sz >= 0; p += sz)
|
||||
sz = npk_write(p, &(channel->Dn), buf + len - p);
|
||||
|
||||
mmio_write8(0U, &(channel->FLAG));
|
||||
|
||||
atomic_dec32(&per_cpu(npk_log_ref, cpu_id));
|
||||
}
|
|
@ -128,6 +128,7 @@ static struct shell_cmd shell_cmds[] = {
|
|||
/* The initial log level*/
|
||||
uint32_t console_loglevel = CONFIG_CONSOLE_LOGLEVEL_DEFAULT;
|
||||
uint32_t mem_loglevel = CONFIG_MEM_LOGLEVEL_DEFAULT;
|
||||
uint32_t npk_loglevel = CONFIG_NPK_LOGLEVEL_DEFAULT;
|
||||
|
||||
static struct shell hv_shell;
|
||||
static struct shell *p_shell = &hv_shell;
|
||||
|
@ -872,17 +873,21 @@ static int shell_loglevel(int argc, char **argv)
|
|||
{
|
||||
char str[MAX_STR_SIZE] = {0};
|
||||
|
||||
if (argc == 1) {
|
||||
snprintf(str, MAX_STR_SIZE,
|
||||
"console_loglevel: %u, mem_loglevel: %u\r\n",
|
||||
console_loglevel, mem_loglevel);
|
||||
shell_puts(str);
|
||||
} else if (argc == 2) {
|
||||
console_loglevel = atoi(argv[1]);
|
||||
} else if (argc == 3) {
|
||||
console_loglevel = atoi(argv[1]);
|
||||
switch (argc) {
|
||||
case 4:
|
||||
npk_loglevel = atoi(argv[3]);
|
||||
case 3:
|
||||
mem_loglevel = atoi(argv[2]);
|
||||
} else {
|
||||
case 2:
|
||||
console_loglevel = atoi(argv[1]);
|
||||
break;
|
||||
case 1:
|
||||
snprintf(str, MAX_STR_SIZE, "console_loglevel: %u, "
|
||||
"mem_loglevel: %u, npk_loglevel: %u\r\n",
|
||||
console_loglevel, mem_loglevel, npk_loglevel);
|
||||
shell_puts(str);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -90,7 +90,8 @@ struct shell {
|
|||
#define SHELL_CMD_LOGDUMP_HELP "log buffer dump"
|
||||
|
||||
#define SHELL_CMD_LOG_LVL "loglevel"
|
||||
#define SHELL_CMD_LOG_LVL_PARAM "[console_loglevel] [mem_loglevel]"
|
||||
#define SHELL_CMD_LOG_LVL_PARAM "[<console_loglevel> [<mem_loglevel> " \
|
||||
"[npk_loglevel]]]"
|
||||
#define SHELL_CMD_LOG_LVL_HELP "get(para is NULL), or set loglevel [0-6]"
|
||||
|
||||
#define SHELL_CMD_CPUID "cpuid"
|
||||
|
|
|
@ -23,6 +23,7 @@ struct per_cpu_region {
|
|||
uint64_t *sbuf[ACRN_SBUF_ID_MAX];
|
||||
uint64_t vmexit_cnt[64];
|
||||
uint64_t vmexit_time[64];
|
||||
uint32_t npk_log_ref;
|
||||
#endif
|
||||
uint64_t irq_count[NR_IRQS];
|
||||
uint64_t softirq_pending;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
/* Logging flags */
|
||||
#define LOG_FLAG_STDOUT 0x00000001U
|
||||
#define LOG_FLAG_MEMORY 0x00000002U
|
||||
#define LOG_FLAG_NPK 0x00000004U
|
||||
#define LOG_ENTRY_SIZE 80
|
||||
/* Size of buffer used to store a message being logged,
|
||||
* should align to LOG_ENTRY_SIZE.
|
||||
|
@ -29,6 +30,7 @@
|
|||
|
||||
extern uint32_t console_loglevel;
|
||||
extern uint32_t mem_loglevel;
|
||||
extern uint32_t npk_loglevel;
|
||||
void init_logmsg(__unused uint32_t mem_size, uint32_t flags);
|
||||
void print_logmsg_buffer(uint16_t pcpu_id);
|
||||
void do_logmsg(uint32_t severity, const char *fmt, ...);
|
||||
|
|
|
@ -6,7 +6,51 @@
|
|||
#ifndef NPK_LOG_H
|
||||
#define NPK_LOG_H
|
||||
|
||||
#define HV_NPK_LOG_REF_SHIFT 2U
|
||||
#define HV_NPK_LOG_REF_MASK ((1U << HV_NPK_LOG_REF_SHIFT) - 1U)
|
||||
|
||||
#define HV_NPK_LOG_MAX 1024U
|
||||
#define HV_NPK_LOG_HDR 0x01000242U
|
||||
|
||||
enum {
|
||||
HV_NPK_LOG_CMD_INVALID,
|
||||
HV_NPK_LOG_CMD_CONF,
|
||||
HV_NPK_LOG_CMD_ENABLE,
|
||||
HV_NPK_LOG_CMD_DISABLE,
|
||||
HV_NPK_LOG_CMD_QUERY,
|
||||
};
|
||||
|
||||
enum {
|
||||
HV_NPK_LOG_RES_INVALID,
|
||||
HV_NPK_LOG_RES_OK,
|
||||
HV_NPK_LOG_RES_KO,
|
||||
HV_NPK_LOG_RES_ENABLED,
|
||||
HV_NPK_LOG_RES_DISABLED,
|
||||
};
|
||||
|
||||
struct hv_npk_log_param;
|
||||
|
||||
struct npk_chan {
|
||||
uint64_t Dn;
|
||||
uint64_t DnM;
|
||||
uint64_t DnTS;
|
||||
uint64_t DnMTS;
|
||||
uint64_t USER;
|
||||
uint64_t USER_TS;
|
||||
uint32_t FLAG;
|
||||
uint32_t FLAG_TS;
|
||||
uint32_t MERR;
|
||||
uint32_t unused;
|
||||
} __packed;
|
||||
|
||||
#ifdef HV_DEBUG
|
||||
void npk_log_setup(struct hv_npk_log_param *param);
|
||||
void npk_log_write(const char *buf, size_t len);
|
||||
#else
|
||||
static inline void npk_log_setup(__unused struct hv_npk_log_param *param)
|
||||
{}
|
||||
static inline void npk_log_write(__unused const char *buf, __unused size_t len)
|
||||
{}
|
||||
#endif /* HV_DEBUG */
|
||||
|
||||
#endif /* NPK_LOG_H */
|
||||
|
|
Loading…
Reference in New Issue