Before we delve into the details of the new code that you'll be
working with, you should probably undo the test cases from project 1.
-All you need to do is make sure the original @file{threads/test.c} is
-in place. This will stop the tests from being run.
@menu
* Project 2 Code::
task switching. Pintos uses the TSS only for switching stacks when a
user process enters an interrupt handler, as does Linux. @strong{You
should not need to modify these files for any of the projects.}
-However, you can read the code if you're interested in how the GDT
+However, you can read the code if you're interested in how the TSS
works.
@end table
You need to be able to create and format simulated disks. The
@command{pintos} program provides this functionality with its
-@option{make-disk} command. From the @file{filesys/build} directory,
+@option{make-disk} command. From the @file{userprog/build} directory,
execute @code{pintos make-disk fs.dsk 2}. This command creates a 2 MB
simulated disk named @file{fs.dsk}. (It does not actually start
Pintos.) Then format the disk by passing the @option{-f} option to
implementing the join syscall, but besides that, you can use
the original code provided for project 1.
+@item
+@b{All my user programs die with page faults.}
+
+This will generally happen if you haven't implemented problem 2-1
+yet. The reason is that the basic C library for user programs tries
+to read @var{argc} and @var{argv} off the stack. Because the stack
+isn't properly set up yet, this causes a page fault.
+
@item
@b{Is there a way I can disassemble user programs?}
free.
@item
-@b{How do I compile new user programs? How do I make 'echo' compile?}
+@b{How do I compile new user programs?}
You need to modify @file{tests/Makefile}.
Therefore, for those who want to try the latter technique, we'll
provide a little bit of helpful code:
-@example
+@verbatim
/* Tries to copy a byte from user address USRC to kernel address DST.
Returns true if successful, false if USRC is invalid. */
-static inline bool get_user (uint8_t *dst, const uint8_t *usrc) @{
+static inline bool get_user (uint8_t *dst, const uint8_t *usrc) {
int eax;
asm ("movl $1f, %%eax; movb %2, %%al; movb %%al, %0; 1:"
: "=m" (*dst), "=&a" (eax) : "m" (*usrc));
return eax != 0;
-@}
+}
/* Tries write BYTE to user address UDST.
Returns true if successful, false if UDST is invalid. */
-static inline bool put_user (uint8_t *udst, uint8_t byte) @{
+static inline bool put_user (uint8_t *udst, uint8_t byte) {
int eax;
asm ("movl $1f, %%eax; movb %b2, %0; 1:"
: "=m" (*udst), "=&a" (eax) : "r" (byte));
return eax != 0;
-@}
-@end example
+}
+@end verbatim
Each of these functions assumes that the user address has already been
verified to be below @code{PHYS_BASE}. They also assume that you've
thread's parent when @func{join} is called.
@item
-@b{Can I just cast a pointer to a @code{struct file} object to get a
+@b{Can I just cast a pointer to a @struct{file} object to get a
unique file descriptor? Can I just cast a @code{struct thread *} to a
@code{pid_t}? It's so much simpler that way!}
@end menu
@node Argument Passing to main
-@subsection Argument Passing to @func{main}
+@subsection Argument Passing to @code{main()}
In @func{main}'s case, there is no caller to prepare the stack
before it runs. Therefore, the kernel needs to do it. Fortunately,
@item @t{0xbfffffe0} @tab @code{argv[2]} @tab @t{0xbffffff8}
@item @t{0xbfffffdc} @tab @code{argv[1]} @tab @t{0xbffffff5}
@item @t{0xbfffffd8} @tab @code{argv[0]} @tab @t{0xbfffffed}
-@item @t{0xbfffffd4} @tab @code{argv} @tab @t{0xbffffffd8}
+@item @t{0xbfffffd4} @tab @code{argv} @tab @t{0xbfffffd8}
@item @t{0xbfffffd0} @tab @code{argc} @tab 4
@item @t{0xbfffffcc} @tab ``return address'' @tab 0
@end multitable
Here's what it would show in the above example, given that
@code{PHYS_BASE} is @t{0xc0000000}:
-@example
+@verbatim
bfffffc0 00 00 00 00 | ....|
bfffffd0 04 00 00 00 d8 ff ff bf-ed ff ff bf f5 ff ff bf |................|
bfffffe0 f8 ff ff bf fc ff ff bf-00 00 00 00 00 2f 62 69 |............./bi|
bffffff0 6e 2f 6c 73 00 2d 6c 00-2a 2e 68 00 2a 2e 63 00 |n/ls.-l.*.h.*.c.|
-@end example
+@end verbatim
@node System Calls
@section System Calls
@html
<CENTER>
@end html
-@multitable {Address} {Value}
+@multitable {@t{0xbffffe7c}} {Value}
@item Address @tab Value
@item @t{0xbffffe7c} @tab 3
@item @t{0xbffffe78} @tab 2
The 80@var{x}86 convention for function return values is to place them
in the @samp{EAX} register. System calls that return a value can do
-so by modifying the @samp{eax} member of @code{struct intr_frame}.
+so by modifying the @samp{eax} member of @struct{intr_frame}.