The CHAOS Project - The CS152 Hardware Architecture Operating System Project
   


About
An OS for the processor designs from the UC Berkeley CS152 course.

Hansel Chung
hachu@ocf

Navigation
Work Log
Design Document

Distribution
CHAOS Kernel (20060318)

       

Fri, 28 Apr 2006

Web Site Changes
The web site will remain pretty simple as it was primarily a work log. Links to downloads will be added eventually, but password protected until I feel like declaring a license. The contact email address is partial to prevent spambots from picking it up. But considering this project is tied to the CS152 course at UC Berkeley, it should be obvious to anybody who's been to Berkeley, what the rest of my email address is. By the way, I've put in a log entry for every day that I spent working on the design and implementation of the project. Whether it was a 5 minute test run or several hours of thinking, there's a log entry. So if you total it up, I've worked on this project for 24 days (probably really like 50 hours total) and got myself my own malloc and multiprocessing implementations. Not too bad.

/chaos/worklog | permanent link

Sat, 18 Mar 2006

Finally, newproc is done

Added another -1 and a comment based on yesterday's note. It's fixed and it took less than 5 minutes.

Wrote deleteproc(int pid). This removes a process from the process list and calls the free on the process space of that process. While we're doing cooperative multitasking, it should be okay to call deleteproc() and then contextswitch() at the end of a program to free its own memory space and then have the final context switch save to a freed area and never return. However, when we move to preemptive multitasking, this probably isn't going to work if any of the stuff gets preempted.

From test runs, it appears deleteproc/contextswitch as it is works. Not bad for 2 hours total today.

/chaos/worklog | permanent link

Fri, 17 Mar 2006

Newproc doesn't like itself?

addu , $0, added to end of schedulerentry()
break 1 removed from contextswitchsupport.s

Program1 starts, Program2 starts, Program3 starts, and the yielding switches between each task nicely.

Next tasks/known bugs:
1) When a program ends, there's no proper cleanup. Gotta implement that.
2) Creating newproc without jumpstarting them seems to corrupt the previous PCB. Need to investigate. In the meantime, calling contextswitch after a newproc seems to work.

Evening update: while telling my friend Eric about this project's progress, it occurred to me that the newproc without jumpstarting bug is just because of an off-by-one bug regarding where to stick the jumpstart funcptr.

Originally, I did:
newProcSpace->stackptr = (unsigned int*)newProcSpace + sizeInWords - 1;
*((unsigned int*)newProcSpace->stackptr + 1) = funcptr;

I put in the -1 so that I would have an extra space at the end of my process space to put the function pointer. I was actually supposed to subtract 2 because newProcSpace[sizeInWords] is actually off the boundary by one since arrays are zero-indexed. Because I was writing off the end of the process space, on creation of a new process, my function pointer would get overwritten by malloc's tracking data. Calling contextswitch avoids this because my math kinda wastes a few words of space at the end of the process space and also uses the function pointer before it gets corrupted by the next newproc call.

/chaos/worklog | permanent link

Thu, 16 Mar 2006

Even more fun with newproc - out of memory

I totally didn't see that one coming. It appears initializing a simple program in 256 bytes of program space wasn't enough. Considering that some of the print calls take 24 bytes, the PCB takes like 36, the program takes 40 to begin with, and, the context switch takes 168..... yeah... 256 wasn't enough.

I, all of a sudden, come to this conclusion after reading the assembly to find how contextswitching could possibly have failed and trying to learn how to use the tracing ability of vmips to no avail.

Telling it to make program1's space a gigantic 2048 fixed that crashing issue. The problem is, on the switch out of program1, it actually just switched back to program1 instead of the kernel loop. Great.

At least, I think I can put process space at 1024 bytes with no harm.

At the end of the night, just as the batteries were running out on my computer, I realized that gcc's cleanup of the scheduler function was causing the stack pointer I wanted to get overwritten by the old stack pointer. This effectively made all the process tracking look correct but jump into the originating process instead of the intended destination. On the following context switch, the process tracking would end up saving information from the wrong process, permanently messing up all the process tracking. Tomorrow, I'll add an addu , $0, to the end of context switch and see if it solves everything.

/chaos/worklog | permanent link

Wed, 15 Mar 2006

Even more fun with newproc

By printing out the value at the address of procNext, we're finding that something's causing the procNext to be changed at the beginning of schedulerentry to 0xa200000c, which happens to be the value used to print stuff out. Now why did printstr/printint break something this time? Coincidence? Probably not...

/chaos/worklog | permanent link

Tue, 14 Mar 2006

More fun with newproc

First thing I discovered after a few hours looking at the traces is that context switch was crashing because it couldn't figure out where the globals were. Kinda strange considering I didn't do anything funky with the (it'll need to be handled when we start loading files though). Turns out, my overzealous attempts at making a normal-looking stack wasn't too good for the program because I tried to copy over / with the stack pointer when in reality, gcc uses as a temporary register for handling accesses to globals. My bad. Taking the line out got me the ability to run contextswitch from the newly spawned program.

The bad part is, it seems to be trying to restore to the wrong process control block now.

After putting in some printfs, I'm getting that while getting the procList from the beginning seems to be no problem at all, procNext has the wrong value. (We're doing round robin. We wern't having problems when we reached the end of the linked list of PCBs, but we're having problems with the linking itself.)

/chaos/worklog | permanent link

Sun, 12 Mar 2006

New Process Jumpstart

I implemented the jumpstart procedure instead of trying to replicate a stack.
What it does is set the stackptr to one word behind the bound, and then store the function pointer for the program entry point at the location where the stack pointer is supposed to point to.
This avoids having the function pointer getting corrupted when other function calls such as printf are used in the context switch function. I then also set the pcb state to 1. (0 == normally running, 1 == jumpstart is required)

During the context switch, the function pointer is pulled into the return address, and the stackptr is incremented to go back to where it belongs.
The state is set to zero before jumping into the function.

Problem is, the thing doesn't seem to work. It just freezes there.
I guess I'll have to use gdb or something cuz this just isn't working.

(after taking an hour break)

Oh, that makes sense, my own call to printStr/printInt is probably clobbering it.
After modifying the state==1 part of contextswitch so that is retrieved just before using it, Program1 started. However the contextswitch call from within seems to be failing.

Well, at least new procs start. Time to call it a night.

/chaos/worklog | permanent link

Wed, 04 Jan 2006

Launching Processes
Yesterday, I decided to take some time and implement some basic test programs that count numbers and then context switch. This is to test the context switch ability on actual programs.
The problem is, I hadn't finished the code to do the context switch itself. Also, initial tests of the functionality turned up the problem that I need to create a stack with return addresses for the functions to clean up with if I try to just insert a new process onto the queue.
So, the easiest solution is to mark the new processes and jump start them the easy way by simply setting the stackptr and jumping to the start of the function after the previous process has been safely cleaned up.
I'll do this later.

/chaos/worklog | permanent link

Sat, 10 Dec 2005

Web Site Opened!
Using the power of a canned solution, I installed Blosxom as a way of hosting the worklog for CHAOS (CS152 Hardware Architecture - Operating System). I'll post all of the work log entries up until now shortly.

This project is basically my personal work on creating additional functionality for the processor designed in CS152 in the form of an operating system and support hardware.

/chaos/worklog | permanent link

Fri, 02 Dec 2005

Board
Whoo hoo! I got a Xilinx Spartan 3 starter board! They're $99 on Xilinx.com along with a CPLD board since they're clearing everything out for the new Spartan 3E boards.

/chaos/worklog | permanent link

Sun, 09 Oct 2005

Break broken?
Productive morning. In 10 minutes of reading the vmips docs, I found something interesting. Using the break instruction doesn't immediately halt vmips as it is. It does something with a exception handler but as far as I know, the handlers just have a break instruction as well, so that might not be it either. But that might explain why the stuff didn't look exactly alike yesterday despite seeming to work. Perhaps this means to halt the machine, I need to write to a halt device. I wonder if there's an immediate halt on break feature?

/chaos/worklog | permanent link

Sat, 08 Oct 2005

To do: Undo gcc function init.
I just noticed that the contextswitch() function, which is supposed to be pretty much all assembly, doesn't completely undo the gcc stuff before starting to execute. Yesterday, I had just the increment. I just added the //$30 stuff in too. Unity context switch seems to work now but the results from before and after the context switch don't look perfectly alike. This took about 2 hour's worth of time today.

/chaos/worklog | permanent link

Fri, 07 Oct 2005

Declaring kernel register usage
Well, finally got some coding time in. About an hour and a half actually. Been so long.
Here's the scoop. will now be used to store the return address for after the restore. This means that you can enter from an interrupt handler or a yield call, copy EPC or to and then call register save/restore. Register save/restore will save everything but (incase we wanted something there for this stuff) call the scheduler, switch the , and then do the restore and jump to . I learned today that .globl is needed to make assembly functions link to C files.
I also learned today that accidentally switching and in copying to is a bad bad thing.
And finally, I also realized that while GetStackPtr() is good for just checking up a little, using it in the middle of a context switch is bad. Why? Because it's a function. And if you get the stack pointer in a function but don't restore to it, you'll restore into the wrong stack pointer. This doesn't fix unity context switch though.

/chaos/worklog | permanent link

Mon, 26 Sep 2005

Oh I forgot about those...
I was trying to figure out how to return from a interrupt handler and had completely forgotten that and are reserved for the kernel and interrupt handlers. So this makes it so that I can do all the context switch stuff using these registers for scratch space and then probably just have a function that calls the same area depending on whether it's a yield or a preempt. Refer to page A-35 in Patterson's book for an example exception handler.

/chaos/worklog | permanent link

Sat, 09 Jul 2005

Unimplemented instructions
Wow, I didn't touch this project for a half year...

While in Japan, so I wouldn't get bored on the plane trip back, I printed out a disassembly of the kernel and the C source. Later when I read it, I noticed a bunch of instructions (swc0, lwc1, etc.) I've never encountered before as well as a calling convention that didn't make all that much sense to me. Turns out they're for more modern MIPS processors. I modified the build script to use the gcc flag -mips2 and now the disassembly looks more like what I'm expecting.
After the fairly long break from the project, I need to figure out how to access the global variables and stuff from assembly to put together a proper contextswitch function.

/chaos/worklog | permanent link

Sun, 16 Jan 2005

Using the stack
A flash of enlightenment occurred! So originally I was going to use the process control block to store the registers when a thread is context switched out. Why? Because I think that's what we did in Nachos in class. Why? Because it's nice and easy to store stuff in a data structure since Nachos is in Java. Now, when I was implementing context switch, I just thought that I'd follow the usage of data structures like before and everything should be okay. And so that's what was written.
But when it came time to actually think through what was going on when I executed it, it occurred to me that registers will be clobbered when I do "currentProc->reg[1] = " so saving it like that was kinda stupid because I'd just get it in the middle of the context switch and it'd end up in the stack. This lead me to the other realization. Why not just push it all to the stack of the process space? Duh.
So now I'll need to rewrite it to push to stack, which should also take less memory since each process control block will now be 30 registers smaller. I'll just have to store the stack pointer instead of the entire register set.
By the way, the actual reason that my code failed was that I was doing the inline assembly incorrectly. I'll need to read up on that to see what I was supposed to do since "sw $1, 0(%1), currentProc->reg[1]" doesn't seem to work. (it puts currentProc's address not the address of the reg[1])

/chaos/worklog | permanent link

Fri, 14 Jan 2005

Fighting gcc
Context switching causes a TLB exception. It's because the register saving isn't working right since I apparently don't seem to understand how to do inline asm correctly. Example: "sw $1, 0(v0)" should be "sw $1, 40(v0)". But since I specify an offset of 0 originally, it has a 0 offset. I don't know how to make the compiler fill in the correct offset. I guess I need to do some more research.

/chaos/worklog | permanent link

Thu, 13 Jan 2005

Bytes and words
Fixed kmalloc bug which takes size and assumes words instead of bytes. kmalloc now accepts size as bytes. kfree implemented. Did some testing for kmalloc and kfree for various sizes. Also fixed kmalloc/kfree bug where when incrementing and decrementing from struct mallocBlock*, it needs to be cast into an unsigned int* first to make sure you're moving up and down the struct by a pointer length. The side effect from the bug was that the kmalloc returned value would be far beyond where the start of the allocated space. It now returns the proper address. Note however that the stack/heap collision check still hasn't been tested yet since the memory map isn't totally defined yet. Tests just assumed no collision.

/chaos/worklog | permanent link

Tue, 28 Dec 2004

Memory mapped CPU identification for multiple processors
Haven't been working on the project for the past couple of weeks because of my sister's graduation and visiting friends who have come back for winter break. Earlier this month, I thought about how a process can figure out which core it's running on if a system is multiprocessor. It dawned on me that the easiest way would be to have a register pre-configured to be read only and hold a value representing the CPU number. Today, as I was reading about the iPod Linux project, I found out that the CPU id for a 4G iPod is stored at 0x6000000. This makes me feel more confident that things really do work in a way similar to what I thought up in established OSs.

/chaos/worklog | permanent link

Tue, 14 Dec 2004

Malloc
I decided to try a little more to get the original kernel malloc plan working and had some progress. I dealt with some of the stuff I thought I had overlooked and began testing. There are issues with the memory map. Right now the vmips romfile generation places the kernel at a different location than expected, so I have to disable the heap/stack collision checks when testing. So far, I was able to call kmalloc(8) twice and get two pointers to regions of 8.... words. I need to correct that to bytes and also implement free().

/chaos/worklog | permanent link