[UNSW] COMP3231/9201/3891/9283 Operating Systems 2019/T1

ASST0: Getting warmed up

Contents

  1. Due Dates and Mark Distribution
  2. Introduction
  3. Getting Started
  4. Reading Component
  5. Working with the Kernel
  6. Your Task
  7. Submitting

1. Due Time & Date and Mark Distribution

Due Time & Date: 8am (08:00), Fri March 1st (Week 2)

Marks: Worth 10 marks (contributing to the 100 potential class marks available in the course)

This warmup is done as an individual.

No bonuses apply for this warmup exercise.


2. Introduction

The aim of the warmup exercise is to have you familiarise yourself with the environment that you will be using for the more substantial assignments. The exercise consists of two parts: an assessed exercise for marks, and a non-assessable component. The non-assessable component consists of a set of directed questions to give you practice navigating and reading the code base. The answers to this code reading Q & A component of the exercise are available on the wiki (improvable by you the students). The assessable exercise consists of you: learning how to build and run OS/161, making a very minor change to the existing OS to fix a bug, and learning the submission process. The change is conceptually trivial, so you can view this exercise as us giving away marks as an incentive for you to get the assignment environment up and running early in the trimester in preparation for the assignments.

Note that this exercise is not indicative of the level of difficulty of the actual assignments. The assignments are much more challenging.

The OS/161 Environment

This assignment will introduce you to the components of the environment you will use during the semester:

  • OS/161, the educational operating system you will modify to implement the assignments.
  • System/161, the MIPS machine simulator that OS/161 runs on.
  • GDB, a debugger that will make your life much easier.

The introduction to the OS/161 system explains how the components of the OS/161 system fit together, and contains important information about using the tools. You should take the time to read it now.

git

git is a source code management system used to track changes to a piece of software. We make use of git in this course to allow you to manage the large code base, and recover from potential problems. git keeps a copy of each committed change to your OS/161 files. It allows you to track the changes you have made, and more importantly, rollback to a known state if things get out of hand.

git also enables you and your partner to work on the same code repository in a coordinated way. You can even work on versions of your code stored at home and at CSE.

git is a large system of which you need to know only a small subset. We will give you directions for the parts you need to know, but feel free to expand your knowledge as git is a common tool worth knowing, and is used widely in industry.


3. Getting Started

Setting up your development environment

See the Wiki for details of how to set up your development environment. Working at CSE requires the least effort to set up and is supported, but is also the least efficient to work with. Working on your own equipment is the most efficient, but requires a little time to set up - time that you have at the start of the trimester.

If you are here, we assume you have the following set up:

  • the cross compilations tools are accessible on the commandline,
  • SSH is set up,
  • and your public SSH key is loaded in `gitlab.cse.unsw.edu.au`.
  • .

Obtaining the distribution with git

The following steps obtains a copy of the assignment sources.

  • Create a sub-directory off your home directory to contain your cs3231 work.
    % cd ~
    % mkdir cs3231
    
  • Clone the source repository from gitlab.cse.unsw.edu.au. Note: You should change the student number to match your own, and course code (comp3231) is correct even though you might be enroled in another course code.
    % cd ~/cs3231
    % git clone gitlab@gitlab.cse.unsw.EDU.AU:z8990549/19t1-comp3231-asst0.git asst0-src
    

You should now have an asst0-src directory to work on.


4. Reading component

Now that you have an OS/161 source tree, read the code walkthrough.

This component of this warmup aims to guide you through the code base to help you begin to comprehend its contents, identify what functionality is implemented where.

Note that while the code reading component is not assessable, we view it as the ideal opportunity to get to know your way around the code, including practicing with whatever code browsing tool or editor you plan to use. You will benefit in the assignments by practicing navigating around and developing a rudimentary understanding of the code base. The code reading component is here to give you some of that practice.


5. Working with the Kernel

Building a Kernel

Now to the business end of this exercise. You will now build and install a kernel.
  • You first have to configure your source tree. This step sets up some information for later compilation, such as the location of various directories, the compiler to use, and compilation flags to supply.
    % cd ~/cs3231/asst0-src
    % ./configure
    
  • Now we build the application binaries that OS/161 will be able to execute in future assignments. Run the following commands in the current directory. They copy the binaries to a UNIX-like filesystem layout in ~/cs3231/root.
    % bmake
    % bmake install
    
  • Now you must configure the kernel itself. This step prepares for a compilation of the specific set of files that make up the warmup kernel.
    % cd ~/cs3231/asst0-src/kern/conf
    % ./config ASST0
    
  • The next task is to build the kernel. Note the bmake depend step. This step works out which include files are required by which source files so the source files can be recompiled if the include files change. Remember to "bmake depend" when you have added or removed files or change #include statements.
    % cd ../compile/ASST0
    % bmake depend
    % bmake
    
  • Now install the kernel.
    % bmake install
    

Running your Kernel

If you have made it this far, your have built and installed the entire OS in ~/cs3231/root. Now it is time to run it.
  • Download the sample sys161-asst0.conf and copy it to ~/cs3231/root/sys161.conf.
  • Change to the root directory of your OS.
    % cd ~/cs3231/root
    
  • Now run system/161 (the machine simulator) on your kernel.
    % sys161 kernel
    
  • You will observe OS/161 begin its boot sequence and then encounter an error, panic, and wait for a debugger.
    sys161: System/161 release 2.0.8, compiled Feb 19 2017 14:31:53
    
    OS/161 base system version 2.0.3
    (with locks&CVs solution)
    Copyright (c) 2000, 2001-2005, 2008-2011, 2013, 2014
       President and Fellows of Harvard College.  All rights reserved.
    
    Put-your-group-name-here's system version 0 (ASST0 #9)
    
    352k physical memory available
    Device probe...
    lamebus0 (system main bus)
    emu0 at lamebus0
    ltrace0 at lamebus0
    ltimer0 at lamebus0
    beep0 at ltimer0
    rtclock0 at ltimer0
    lrandom0 at lamebus0
    random0 at lrandom0
    lser0 at lamebus0
    con0 at lser0
    
    cpu0: MIPS/161 (System/161 2.x) features 0x0
    panic: Fatal exception 3 (TLB miss on store) in kernel mode
    panic: EPC 0x8000b504, exception vaddr 0x0
    panic: I can't handle this... I think I'll just die now...
    sys161: trace: software-requested debugger stop
    sys161: Waiting for debugger connection...
    

Summarising, you have configured and installed in ~/cs3231/root the userland applications that will eventually run on OS/161 and the OS/161 kernel itself. Going forward, you would normally only be modifying the kernel (the files in ~/cs3231/asst0-src/kern). To rebuild the kernel after changes, only the following commands are required in ~/cs3231/asst0-src/kern/compile/ASST0.

% bmake && bmake install

Using GDB

GDB is a tool in the toolbox that can help you understand what went wrong with your code. It has the advantage over kprintf() style debugging in that it does not change the behaviour of the code, and it can be used when something unexpected happens and not require you to change the code and reproduce the problem in order to debug it. This is very useful for intermittant bugs.

The Wiki has a setup guide for os161-gdb. Now is a good time to set it up. You'll need it to follow the example below. There is also a short tutorial here on using GDB with OS/161


6. Your Task

The task for this assignment is to find the bug that is causing OS/161 to crash and fix it. You can then commit your changes with git and push the changes back to gitlab.cse.unsw.edu.au.

Firstly, lets examine the output above where OS/161 crashes. Skip the initialisation status messages until you reach the point where the panic begins. Let's examine each line at a high level (as the semester progresses you'll get a deeper understanding of what is going on).

  • A fatal exception has occured, i.e. something OS/161 can't recover from, so it has paniced. The exception is related to storing to memory while in kernel mode.
  • The EPC (Exception Program Counter) address is the address in memory of the intruction that caused the problem. The vaddr is the address it was attempting to store to. You might guess at this point that the code might be attempting to store to a NULL pointer.
  • Yes, we are panicing, kernels should not reference NULL pointers.
  • sys161 is nice enough to stop and wait for you to connect os161-gdb to find the problem.

Finding the bug

Now we will look at two methods to find the offending code. The first using mostly just GDB, then second method will take advantage of the fact with know the address of the faulting instruction already.

Using just GDB

Open a second terminal window on the same machine and run GDB as follows, then use the connect and where commands. Note: login.cse.unsw.edu.au is actually and alias for several separate machines.

% cd ~/cs3231/root
% os161-gdb kernel
GNU gdb (GDB) 7.8
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-unknown-linux-gnu --target=mips-harvard-os161".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from kernel...done.
(gdb) connect
membar_any_any () at includelinks/machine/membar.h:47
47              __asm volatile(
Breakpoint 1 at 0x8000ac8c: file ../../lib/kprintf.c, line 135.
(gdb) where
#0  membar_any_any () at includelinks/machine/membar.h:47
#1  membar_store_store () at includelinks/machine/membar.h:58
#2  lamebus_write_register (bus=<optimised out>, slot=<optimised out>, offset=offset@entry=16, val=val@entry=0)
    at ../../arch/sys161/dev/lamebus_machdep.c:184
#3  0x800052ec in ltrace_stop (code=code@entry=0) at ../../dev/lamebus/ltrace.c:87
#4  0x8000ad58 in panic (fmt=fmt@entry=0x80023bd8 "I can't handle this... I think I'll just die now...\n")
    at ../../lib/kprintf.c:184
#5  0x8001b2a8 in mips_trap (tf=0x80027f28) at ../../arch/mips/locore/trap.c:315
#6  <signal handler called>
#7  0x8000b504 in boot () at ../../main/main.c:140
#8  0x8000b5d4 in kmain (arguments=0x80026020 "") at ../../main/main.c:218
#9  0x8001d1ac in __start () at ../../arch/sys161/main/start.S:216
(gdb)

The where command shows the current nesting of function calls as represented by stack frames on the current kernel stack. Here are some observations.

  • Frames 9-7 show the kernel starting, entering kmain, and then boot.
  • Frame 6 indicates some kind of exception occured.
  • Frames 5 - 0 show the kernel catching the exception, calling panic and stopping.

Let's investigate by switching to frame 7 so we can inspect it's local variables.

(gdb) frame 7
#7  0x8000b504 in boot () at ../../main/main.c:140
140                     * foo = 'x';            /* attempt to access it */
(gdb) print foo
$1 = 0x0
(gdb)

The exception occurs while storing the character 'x' to the pointer foo, which has a value of zero, i.e. NULL. Lets use list to see more context.

(gdb) list
135             kheap_nextgeneration();
136
137             {
138                     /* remove this section of code to fix ASST0 */
139                     char *foo = NULL;       /* create a NULL pointer */
140                     * foo = 'x';            /* attempt to access it */
141             }
142
143             /*
144              * Make sure various things aren't screwed up.
(gdb)

It should be clear now how to fix the bug

Using EPC and GDB

Let's use our knowledge of EPC to go directly to the problem using the address of the offending instruction.

(gdb) list *0x8000b504                                                       
0x8000b504 is in boot (../../main/main.c:140).                               
135             kheap_nextgeneration();                                      
136                                                                          
137             {                                                            
138                     /* remove this section of code to fix ASST0 */       
139                     char *foo = NULL;       /* create a NULL pointer */  
140                     * foo = 'x';            /* attempt to access it */   
141             }                                                            
142                                                                          
143             /*                                                           
144              * Make sure various things aren't screwed up.               
(gdb)                                                                        

Here we have been taken directly to the offending statement in the code base. Note that while we can identify the line of code this way, we can't print out local variables unless we are in the correct stack frame, as illustrated below.

(gdb) print foo
No symbol "foo" in current context.
(gdb) frame 7
#7  0x8000b504 in boot () at ../../main/main.c:140
140                     * foo = 'x';            /* attempt to access it */
(gdb) print foo
$2 = 0x0
(gdb)

Fixing the bug

Remove the offending code and rebuild the kernel only, and rerun OS/161.

In asst0-src/kern/compile/ASST0.

% bmake && bmake install

The should get the following when you run sys161 on your new kernel where it runs until you get a boot prompt. You can enter 'q' to exit at this point.

% sys161 kernel
sys161: System/161 release 2.0.8, compiled Feb 19 2017 14:31:53

OS/161 base system version 2.0.3
(with locks&CVs solution)
Copyright (c) 2000, 2001-2005, 2008-2011, 2013, 2014
   President and Fellows of Harvard College.  All rights reserved.

Put-your-group-name-here's system version 0 (ASST0 #10)

352k physical memory available
Device probe...
lamebus0 (system main bus)
emu0 at lamebus0
ltrace0 at lamebus0
ltimer0 at lamebus0
beep0 at ltimer0
rtclock0 at ltimer0
lrandom0 at lamebus0
random0 at lrandom0
lser0 at lamebus0
con0 at lser0

OS/161 kernel [? for menu]: q
Shutting down.
The system is halted.
sys161: 5411375122 cycles (39129232 run, 5372245890 global-idle)
sys161:   cpu0: 3339292 kern, 0 user, 0 idle; 7328 ll, 7328/0 sc, 66160 sync
sys161: 783 irqs 0 exns 0r/0w disk 2r/592w console 0r/0w/1m emufs 0r/0w net
sys161: Elapsed real time: 213.657611 seconds (25.3273 mhz)
sys161: Elapsed virtual time: 215.027700909 seconds (25 mhz)
%

Note: The following sample output will vary slightly depending on the year it was originally generated.

You can also test OS/161 works with the menu choice supplied on the command line as follows.

% sys161 kernel q

This is generally the way we test your submission, so make sure that you have tested using the above method, even if you have also tested interactively.

Summarising thus far, you should now have a working code base.

Committing your changes with git

First check what your local status is to avoid anything unexpected.

% git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add ..." to update what will be committed)
  (use "git checkout -- ..." to discard changes in working directory)

        modified:   kern/main/main.c

no changes added to commit (use "git add" and/or "git commit -a")
%

All looks as expected, so lets commit the changes and push them back to gitlab. The -m is to add a descriptive commit message on the command line.

% git commit -a -m "foo pointer fix"
% git push

You now have a completed assigment on gitlab that you can submit. Feel free to log into gitlab.cse.unsw.edu.au via the web and explore your assigment.


7. Submitting

The submission instructions are available on the Wiki. To overview submission, you will be submitting the git repository via CSE's give system. For ASST0, the submission system will automark it immediately and tell you if you received the 10 marks. You can submit as many times as you like up until the deadline until you get the marks.

Warning! Don't ignore the submission system! If your submission fails the submission process, you will fail to receive any marks.

You're now done.


Page last modified: 2:54pm on Wednesday, 29th of September, 2021

Print Version

CRICOS Provider Number: 00098G