mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-04-28 11:43:56 +00:00
sbuf_put copies sbuf->ele_size of data, and puts into ring. Currently this function assumes that data size from caller is no less than sbuf->ele_size. But as sbuf->ele_size is usually setup by some sources outside of the HV (e.g., the service VM), it is not meant to be trusted. So caller should provide the max length of the data for safety reason. sbuf_put() will return UINT32_MAX if max_len of data is less than element size. Additionally, a helper function sbuf_put_many() is added for putting multiple entries. Tracked-On: #8547 Signed-off-by: Wu Zhou <wu.zhou@intel.com> Reviewed-by: Junjie Mao <junjie.mao@intel.com>
105 lines
2.5 KiB
C
105 lines
2.5 KiB
C
/*
|
|
* Copyright (C) 2018-2022 Intel Corporation.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <types.h>
|
|
#include <asm/lib/atomic.h>
|
|
#include <sprintf.h>
|
|
#include <asm/lib/spinlock.h>
|
|
#include <asm/per_cpu.h>
|
|
#include <npk_log.h>
|
|
#include <logmsg.h>
|
|
#include <ticks.h>
|
|
|
|
/* buf size should be identical to the size in hvlog option, which is
|
|
* transfered to Service VM:
|
|
* bsp/uefi/clearlinux/acrn.conf: hvlog=2M@0x1FE00000
|
|
*/
|
|
|
|
struct acrn_logmsg_ctl {
|
|
int32_t seq;
|
|
spinlock_t lock;
|
|
};
|
|
|
|
static struct acrn_logmsg_ctl logmsg_ctl;
|
|
|
|
void init_logmsg()
|
|
{
|
|
logmsg_ctl.seq = 0;
|
|
|
|
spinlock_init(&(logmsg_ctl.lock));
|
|
}
|
|
|
|
void do_logmsg(uint32_t severity, const char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
uint64_t timestamp, rflags;
|
|
uint16_t pcpu_id;
|
|
bool do_console_log;
|
|
bool do_mem_log;
|
|
bool do_npk_log;
|
|
char *buffer;
|
|
struct thread_object *current;
|
|
|
|
do_console_log = (severity <= console_loglevel);
|
|
do_mem_log = (severity <= mem_loglevel);
|
|
do_npk_log = (severity <= npk_loglevel);
|
|
|
|
if (!do_console_log && !do_mem_log && !do_npk_log) {
|
|
return;
|
|
}
|
|
|
|
/* Get time-stamp value */
|
|
timestamp = cpu_ticks();
|
|
|
|
/* Scale time-stamp appropriately */
|
|
timestamp = ticks_to_us(timestamp);
|
|
|
|
/* Get CPU ID */
|
|
pcpu_id = get_pcpu_id();
|
|
buffer = per_cpu(logbuf, pcpu_id);
|
|
current = sched_get_current(pcpu_id);
|
|
|
|
(void)memset(buffer, 0U, LOG_MESSAGE_MAX_SIZE);
|
|
/* Put time-stamp, CPU ID and severity into buffer */
|
|
snprintf(buffer, LOG_MESSAGE_MAX_SIZE, "[%luus][cpu=%hu][%s][sev=%u][seq=%u]:",
|
|
timestamp, pcpu_id, current->name, severity, atomic_inc_return(&logmsg_ctl.seq));
|
|
|
|
/* Put message into remaining portion of local buffer */
|
|
va_start(args, fmt);
|
|
vsnprintf(buffer + strnlen_s(buffer, LOG_MESSAGE_MAX_SIZE),
|
|
LOG_MESSAGE_MAX_SIZE
|
|
- strnlen_s(buffer, LOG_MESSAGE_MAX_SIZE), fmt, args);
|
|
va_end(args);
|
|
|
|
/* Check whether output to NPK */
|
|
if (do_npk_log) {
|
|
npk_log_write(buffer, strnlen_s(buffer, LOG_MESSAGE_MAX_SIZE));
|
|
}
|
|
|
|
/* Check whether output to stdout */
|
|
if (do_console_log) {
|
|
spinlock_irqsave_obtain(&(logmsg_ctl.lock), &rflags);
|
|
|
|
/* Send buffer to stdout */
|
|
printf("%s\n\r", buffer);
|
|
|
|
spinlock_irqrestore_release(&(logmsg_ctl.lock), rflags);
|
|
}
|
|
|
|
/* Check whether output to memory */
|
|
if (do_mem_log) {
|
|
uint32_t msg_len;
|
|
struct shared_buf *sbuf = per_cpu(sbuf, pcpu_id)[ACRN_HVLOG];
|
|
|
|
/* If sbuf is not ready, we just drop the massage */
|
|
if (sbuf != NULL) {
|
|
msg_len = strnlen_s(buffer, LOG_MESSAGE_MAX_SIZE);
|
|
(void)sbuf_put_many(sbuf, LOG_ENTRY_SIZE, (uint8_t *)buffer,
|
|
LOG_ENTRY_SIZE * (((msg_len - 1U) / LOG_ENTRY_SIZE) + 1));
|
|
}
|
|
}
|
|
}
|