From 8ec873b7d8a4a52f01e1e301f1af0996ff222638 Mon Sep 17 00:00:00 2001 From: Frans Kaashoek Date: Fri, 26 Jul 2019 10:35:21 -0400 Subject: [PATCH] Checkpoint: split alarmtest exercise in two exercises --- labs/syscall.html | 172 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 144 insertions(+), 28 deletions(-) diff --git a/labs/syscall.html b/labs/syscall.html index a167885..dad86fe 100644 --- a/labs/syscall.html +++ b/labs/syscall.html @@ -10,7 +10,9 @@ This lab makes you familiar with the implementation of system calls. In particular, you will implement a new system call: alarm. - +Note: before this lab, it would be good to have recitation section + on gdb +

Warmup: system call tracing

In this exercise you will modify the xv6 kernel to print out a line @@ -46,6 +48,56 @@ print its output.)

Optional: print the system call arguments. +

RISC-V assembly

+ +

For the alarm system call it will be important to understand RISC-V +assembly. Since in later labs you will also read and write assembly, +it is important that you familiarize yourself with RISC_V assembly. + +

Add a file user/call.c with the following content, modify the + Makefile to add the program to the user programs, and compile (make + fs.img). The Makefile also produces a binary and a readable + assembly a version of the program in the file user/call.asm. +

+#include "kernel/param.h"
+#include "kernel/types.h"
+#include "kernel/stat.h"
+#include "user/user.h"
+
+int g(int x) {
+  return x+3;
+}
+
+int f(int x) {
+  return g(x);
+}
+
+void main(void) {
+  printf(1, "%d %d\n", f(8)+1, 13);
+  exit();
+}
+
+ +

Since you will be reading and writing RISC-V assembly code for xv6, + you should read through call.asm and understand it. The instruction + manual for RISC-V is in the doc directory (doc/riscv-spec-v2.2.pdf). + Here are some questions that you should answer for yourself: + +

+ +

alarm

@@ -70,25 +122,37 @@ interrupts.

You should put the following example program in user/alarmtest.c: +XXX Insert the final program here

 #include "kernel/param.h"
 #include "kernel/types.h"
 #include "kernel/stat.h"
+#include "kernel/riscv.h"
 #include "user/user.h"
 
+void test0();
+void test1();
 void periodic();
 
 int
 main(int argc, char *argv[])
+{
+  test0();
+  test1();
+  exit();
+}
+
+void test0()
 {
   int i;
-  printf(1, "alarmtest starting\n");
-  alarm(10, periodic);
-  for(i = 0; i < 25*500000; i++){
+  printf(1, "test0 start\n");
+  alarm(2, periodic);
+  for(i = 0; i < 1000*500000; i++){
     if((i % 250000) == 0)
       write(2, ".", 1);
   }
-  exit();
+  alarm(0, 0);
+  printf(1, "test0 done\n");
 }
 
 void
@@ -96,13 +160,37 @@ periodic()
 {
   printf(1, "alarm!\n");
 }
+
+void __attribute__ ((noinline)) foo(int i, int *j) {
+  if((i % 2500000) == 0) {
+    write(2, ".", 1);
+  }
+  *j += 1;
+}
+
+void test1() {
+  int i;
+  int j;
+
+  printf(1, "test1 start\n");
+  j = 0;
+  alarm(2, periodic);
+  for(i = 0; i < 1000*500000; i++){
+    foo(i, &j);
+  }
+  if(i != j) {
+    printf(2, "i %d should = j %d\n", i, j);
+    exit();
+  }
+  printf(1, "test1 done\n");
+}
 
-The program calls alarm(10, periodic) to ask the kernel to +The program calls alarm(2, periodic1) in test0 to ask the kernel to force a call to periodic() every 10 ticks, and then spins for a while. After you have implemented the alarm() system call in the kernel, -alarmtest should produce output like this: +alarmtest should produce output like this for test0:
 $ alarmtest
@@ -125,7 +213,26 @@ alarmtest starting
 (If you only see one "alarm!", try increasing the number of iterations in
 alarmtest.c by 10x.)
 
-Here are some hints:
+

The main challenge will be to arrange that the handler is invoked + when the process's alarm interval expires. In your usertrap, when a + process's alarm interval expires, you'll want to cause it to execute + its handler. How can you do that? You will need to understand in + details how system calls work (i.e., the code in kernel/trampoline.S + and kernel/trap.c). Which register contains the address where + systems calls return to? + +

Your solution will be few lines of code, but it will be tricky to + write the right lines of code. Common failure scenarios are: the + user program crashes or doesn't terminate. You can see the assembly + code for the alarmtest program in alarmtest.asm, which will be handy + for debugging. + +

Test0

+ +

To get started, the best strategy is to first pass test0, which + will force you to handle the main challenge above. Here are some + hints how to pass test0: +

-
  • -It's OK if your solution doesn't save the caller-saved user registers -when calling the handler. + -