| git.druid.rocks | index | druid520 | kaboom | src/ | kernel/ | klog.nsc |
src/kernel/klog.nsc
/*
* klog: a dmesg-style kernel log. append-only, not a true ring buffer
* yet -- once the 8kib buffer fills, later messages are silently
* dropped rather than wrapping over the oldest ones. a real ring
* buffer is a known, real follow-up; not needed for a kernel whose
* entire boot log so far is a couple dozen short lines.
*/
u8
ptr_byte_at(ptr base, u64 index)
{
ptr p;
u64 word;
p = base + index;
word = (u64)*p;
return (u8)(word & (u64)0xff);
}
global i8 klog_buf[8192];
global u64 klog_pos;
global void
klog_init(void)
{
u64 i;
i = 0;
while(i < (u64)8192)
{
klog_buf[i] = 0;
i = i + (u64)1;
}
klog_pos = 0;
}
global void
klog_write(ptr msg)
{
u64 i;
u8 ch;
i = 0;
while(1)
{
ch = ptr_byte_at(msg, i);
if(ch == (u8)0)
{
return;
}
if(klog_pos >= (u64)8192)
{
return; /* log full -- drop the rest of this message */
}
klog_buf[klog_pos] = (i8)ch;
klog_pos = klog_pos + (u64)1;
i = i + (u64)1;
}
}
/* copies up to maxlen bytes of the log so far into buf (a bare ptr,
* not a real array -- byte-at-a-time fill is a read-modify-write of
* the containing 8-byte word, same technique as every other
* byte-through-ptr write in this kernel). returns the number of bytes
* copied. */
global u64
klog_read(ptr buf, u64 maxlen)
{
u64 n;
u64 i;
u64 word;
u64 wordoff;
u64 byteoff;
ptr dst;
n = klog_pos;
if(n > maxlen)
{
n = maxlen;
}
dst = buf;
i = 0;
while(i < n)
{
wordoff = i & ~(u64)7;
byteoff = i & (u64)7;
word = (u64)*(dst + wordoff);
word = word & ~((u64)0xff << (byteoff * (u64)8));
word = word | ((u64)(u8)klog_buf[i] << (byteoff * (u64)8));
*(dst + wordoff) = (i64)word;
i = i + (u64)1;
}
return n;
}