From 0d470b3327db0c88ea9ba3b567706ff905ff9460 Mon Sep 17 00:00:00 2001 From: Douglas Thain Date: Fri, 15 Dec 2023 16:21:08 -0500 Subject: [PATCH] Set up local fix for es segment register. --- user/sysstat.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/user/sysstat.c b/user/sysstat.c index 385da0d9..059fe438 100644 --- a/user/sysstat.c +++ b/user/sysstat.c @@ -8,22 +8,29 @@ See the file LICENSE for details. #include "library/string.h" #include "library/stdio.h" -struct system_stats s = {0}; int main(int argc, char *argv[]) { - printf("a"); - flush(); + /* + This demonstrates (and fixes) a kernel bug. + GCC implements the initialization of the structure on the stack like this: + rep stos %eax,%es:(%edi) + However, basekernel does not automatically set up (or save) the es segment register, + and so the operation crashes. The es register should be set up correctly in kernelcore, + saved and restored when processing interrupts/system calls, and also initialized correctly + using process_kstack_init. + */ + + /* The workaround here is to explicitly set up the es register prior to using it.*/ - printf("b"); - flush(); + asm("movl %ds, %ax"); + asm("movl %ax, %es"); + + struct system_stats s = {0}; if (syscall_system_stats(&s)) { return 1; } - printf("c"); - flush(); - printf("System uptime: %u:%u:%u\n", s.time / (3600), (s.time % 3600) / 60, s.time % 60); printf("Disk 0: %d blocks read, %d blocks written\n", s.blocks_read[0], s.blocks_written[0]);