Skip to content

Commit 51a76a9

Browse files
lyan3jren1
authored andcommitted
hv: save early hv logmsg before sos booted
Add percpu earlylog sbuf within hypervisor memory space to accommodate log before sos booting, and copy the earlylog to SOS allocated sbuf at the first do_logmsg after SOS sets the sbuf during booting. With the patch, earlylog of hypervisor could be captured with acrnlog service if SOS booted. And it may help debugging hv issue if SOS failed to boot, with "logdump" command. Signed-off-by: Yan, Like <like.yan@intel.com> Reviewed-by: Zhao Yakui <yakui.zhao@intel.com> Acked-by: Anthony Xu <anthony.xu@intel.com>
1 parent c61559a commit 51a76a9

File tree

1 file changed

+105
-21
lines changed

1 file changed

+105
-21
lines changed

hypervisor/debug/logmsg.c

Lines changed: 105 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,14 @@
4141
*/
4242
#define LOG_MESSAGE_MAX_SIZE (4 * LOG_ENTRY_SIZE)
4343

44+
/* buf size should be identical to the size in hvlog option, which is
45+
* transfered to SOS:
46+
* bsp/uefi/clearlinux/acrn.conf: hvlog=2M@0x1FE00000
47+
*/
48+
#define HVLOG_BUF_SIZE (2*1024*1024)
49+
4450
DEFINE_CPU_DATA(char [LOG_MESSAGE_MAX_SIZE], logbuf);
51+
DEFINE_CPU_DATA(struct shared_buf *, earlylog_sbuf);
4552

4653
struct logmsg {
4754
uint32_t flags;
@@ -51,10 +58,63 @@ struct logmsg {
5158

5259
static struct logmsg logmsg;
5360

61+
static inline void alloc_earlylog_sbuf(uint32_t cpu_id)
62+
{
63+
uint32_t ele_size = LOG_ENTRY_SIZE;
64+
uint32_t ele_num = ((HVLOG_BUF_SIZE >> 1) / phy_cpu_num
65+
- SBUF_HEAD_SIZE) / ele_size;
66+
67+
per_cpu(earlylog_sbuf, cpu_id) = sbuf_allocate(ele_num, ele_size);
68+
if (!per_cpu(earlylog_sbuf,cpu_id))
69+
printf("failed to allcate sbuf for hvlog - %d\n", cpu_id);
70+
}
71+
72+
static inline void free_earlylog_sbuf(uint32_t cpu_id)
73+
{
74+
if (!per_cpu(earlylog_sbuf, cpu_id))
75+
return;
76+
77+
free(per_cpu(earlylog_sbuf, cpu_id));
78+
per_cpu(earlylog_sbuf, cpu_id) = NULL;
79+
}
80+
81+
static int do_copy_earlylog(struct shared_buf *dst_sbuf,
82+
struct shared_buf *src_sbuf)
83+
{
84+
uint32_t buf_size, valid_size;
85+
uint32_t cur_tail;
86+
spinlock_rflags;
87+
88+
if (src_sbuf->ele_size != dst_sbuf->ele_size
89+
&& src_sbuf->ele_num != dst_sbuf->ele_num) {
90+
spinlock_irqsave_obtain(&(logmsg.lock));
91+
printf("Error to copy early hvlog: size mismatch\n");
92+
spinlock_irqrestore_release(&(logmsg.lock));
93+
return -EINVAL;
94+
}
95+
96+
cur_tail = src_sbuf->tail;
97+
buf_size = SBUF_HEAD_SIZE + dst_sbuf->size;
98+
valid_size = SBUF_HEAD_SIZE + cur_tail;
99+
100+
memcpy_s((void *)dst_sbuf, buf_size, (void *)src_sbuf, valid_size);
101+
if (dst_sbuf->tail != cur_tail)
102+
/* there is chance to lose new log from certain pcpu */
103+
dst_sbuf->tail = cur_tail;
104+
105+
return 0;
106+
}
107+
54108
void init_logmsg(__unused uint32_t mem_size, uint32_t flags)
55109
{
110+
int32_t idx;
111+
56112
logmsg.flags = flags;
57113
logmsg.seq = 0;
114+
115+
/* allocate sbuf for log before sos booting */
116+
for (idx = 0; idx < phy_cpu_num; idx++)
117+
alloc_earlylog_sbuf(idx);
58118
}
59119

60120
void do_logmsg(uint32_t severity, const char *fmt, ...)
@@ -114,6 +174,18 @@ void do_logmsg(uint32_t severity, const char *fmt, ...)
114174
int i, msg_len;
115175
struct shared_buf *sbuf = (struct shared_buf *)
116176
per_cpu(sbuf, cpu_id)[ACRN_HVLOG];
177+
struct shared_buf *early_sbuf = per_cpu(earlylog_sbuf, cpu_id);
178+
179+
if (early_sbuf) {
180+
if (sbuf) {
181+
/* switch to sbuf from sos */
182+
do_copy_earlylog(sbuf, early_sbuf);
183+
free_earlylog_sbuf(cpu_id);
184+
} else
185+
/* use earlylog sbuf if no sbuf from sos */
186+
sbuf = early_sbuf;
187+
}
188+
117189
if (sbuf != NULL) {
118190
msg_len = strnlen_s(buffer, LOG_MESSAGE_MAX_SIZE);
119191

@@ -131,31 +203,43 @@ void print_logmsg_buffer(uint32_t cpu_id)
131203
spinlock_rflags;
132204
char buffer[LOG_ENTRY_SIZE + 1];
133205
int read_cnt;
134-
struct shared_buf *sbuf;
206+
struct shared_buf **sbuf;
207+
int is_earlylog = 0;
135208

136209
if (cpu_id >= (uint32_t)phy_cpu_num)
137210
return;
138211

139-
sbuf = (struct shared_buf *)per_cpu(sbuf, cpu_id)[ACRN_HVLOG];
140-
if (sbuf != NULL) {
212+
if (per_cpu(earlylog_sbuf, cpu_id)) {
213+
sbuf = &per_cpu(earlylog_sbuf, cpu_id);
214+
is_earlylog = 1;
215+
} else
216+
sbuf = (struct shared_buf **)
217+
&per_cpu(sbuf, cpu_id)[ACRN_HVLOG];
218+
219+
spinlock_irqsave_obtain(&(logmsg.lock));
220+
if (*sbuf)
221+
printf("CPU%d: head: 0x%x, tail: 0x%x %s\n\r",
222+
cpu_id, (*sbuf)->head, (*sbuf)->tail,
223+
is_earlylog ? "[earlylog]" : "");
224+
spinlock_irqrestore_release(&(logmsg.lock));
225+
226+
do {
227+
uint32_t idx;
228+
memset(buffer, 0, LOG_ENTRY_SIZE + 1);
229+
230+
if (*sbuf == NULL)
231+
return;
232+
233+
read_cnt = sbuf_get(*sbuf, (uint8_t *)buffer);
234+
235+
if (read_cnt <= 0)
236+
return;
237+
238+
idx = (read_cnt < LOG_ENTRY_SIZE) ? read_cnt : LOG_ENTRY_SIZE;
239+
buffer[idx] = '\0';
240+
141241
spinlock_irqsave_obtain(&(logmsg.lock));
142-
printf("CPU%d: head: 0x%x, tail: 0x%x\n\r",
143-
cpu_id, sbuf->head, sbuf->tail);
242+
printf("%s\n\r", buffer);
144243
spinlock_irqrestore_release(&(logmsg.lock));
145-
do {
146-
memset(buffer, 0, LOG_ENTRY_SIZE + 1);
147-
read_cnt = sbuf_get(sbuf, (uint8_t *)buffer);
148-
if (read_cnt > 0) {
149-
uint32_t idx;
150-
151-
idx = (read_cnt < LOG_ENTRY_SIZE) ?
152-
read_cnt : LOG_ENTRY_SIZE;
153-
buffer[idx] = '\0';
154-
155-
spinlock_irqsave_obtain(&(logmsg.lock));
156-
printf("%s\n\r", buffer);
157-
spinlock_irqrestore_release(&(logmsg.lock));
158-
}
159-
} while (read_cnt > 0);
160-
}
244+
} while (read_cnt > 0);
161245
}

0 commit comments

Comments
 (0)