Update docs.
[pintos-anon] / doc / userprog.texi
index 8ac03dacfdda7ddd3831437460b833d925319465..5c0ee7224830eb5ae8df2179dcb414e1b1e0ae15 100644 (file)
@@ -15,7 +15,9 @@ other part of the code for this assignment. We will describe the
 relevant parts below. If you are confident in your HW1 code, you can
 build on top of it.  However, if you wish you can start with a fresh
 copy of the code and re-implement @code{thread_join()}, which is the
-only part of project #1 required for this assignment.
+only part of project #1 required for this assignment.  Your submission
+should define @code{THREAD_JOIN_IMPLEMENTED} in @file{constants.h}
+(@pxref{Conditional Compilation}).
 
 Up to now, all of the code you have written for Pintos has been part
 of the operating system kernel.  This means, for example, that all the
@@ -39,6 +41,7 @@ in place.  This will stop the tests from being run.
 * Project 2 Code::              
 * Using the File System::       
 * How User Programs Work::      
+* Virtual Memory Layout::       
 * Global Requirements::         
 * Problem 2-1 Argument Passing::  
 * Problem 2-2 System Calls::    
@@ -56,15 +59,9 @@ doing is to simply go over each part you'll be working with.  In
 where the bulk of your work will be:
 
 @table @file
-@item addrspace.c
-@itemx addrspace.h
-An address space keeps track of all the data necessary to execute a
-user program.  Address space data is stored in @code{struct thread},
-but manipulated only by @file{addrspace.c}.  Address spaces need to
-keep track of things like paging information for the process (so that
-it knows which memory the process is using).  Address spaces also
-handle loading the program into memory and starting up the process's
-execution.
+@item process.c
+@itemx process.h
+Loads ELF binaries and starts processes.
 
 @item pagedir.c
 @itemx pagedir.h
@@ -172,16 +169,16 @@ we require you to support.)  The only other limitation is that Pintos
 can't run programs using floating point operations, since it doesn't
 include the necessary kernel functionality to save and restore the
 processor's floating-point unit when switching threads.  You can look
-in @file{test} directory for some examples.
+in @file{tests/userprog} directory for some examples.
 
 Pintos loads ELF executables, where ELF is an executable format used
 by Linux, Solaris, and many other Unix and Unix-like systems.
 Therefore, you can use any compiler and linker that produce
 80@var{x}86 ELF executables to produce programs for Pintos.  We
-recommend using the tools we provide in the @file{tests} directory.  By
-default, the @file{Makefile} in this directory will compile the test
-programs we provide.  You can edit the @file{Makefile} to compile your
-own test programs as well.
+recommend using the tools we provide in the @file{tests/userprog}
+directory.  By default, the @file{Makefile} in this directory will
+compile the test programs we provide.  You can edit the
+@file{Makefile} to compile your own test programs as well.
 
 One thing you should realize immediately is that, until you use the
 above operation to copy a test program to the emulated disk, Pintos
@@ -222,9 +219,9 @@ access kernel virtual memory will cause a page fault, handled by
 @code{page_fault()} in @file{userprog/exception.c}, and the process
 will be terminated.  Kernel threads can access both kernel virtual
 memory and, if a user process is running, the user virtual memory of
-the running process.  However, an attempt to access memory at a user
-virtual address that doesn't have a page mapped into it will also
-cause a page fault.
+the running process.  However, even in the kernel, an attempt to
+access memory at a user virtual address that doesn't have a page
+mapped into it will cause a page fault.
 
 @node Global Requirements
 @section Global Requirements
@@ -246,13 +243,13 @@ first process.
 @node Problem 2-1 Argument Passing
 @section Problem 2-1: Argument Passing
 
-Currently, @code{thread_execute()} does not support passing arguments
+Currently, @code{process_execute()} does not support passing arguments
 to new processes.  UNIX and other operating systems do allow passing
 command line arguments to a program, which accesses them via the argc,
 argv arguments to main.  You must implement this functionality by
-extending @code{thread_execute()} so that instead of simply taking a
+extending @code{process_execute()} so that instead of simply taking a
 program file name, it can take a program name with arguments as a
-single string.  That is, @code{thread_execute("grep foo *.c")} should
+single string.  That is, @code{process_execute("grep foo *.c")} should
 be a legal call.  @xref{80x86 Calling Convention}, for information on
 exactly how this works.
 
@@ -374,7 +371,7 @@ is not safe to call into the filesystem code provided in the
 recommend adding a single lock that controls access to the filesystem
 code.  You should acquire this lock before calling any functions in
 the @file{filesys} directory, and release it afterward.  Don't forget
-that @file{addrspace_load()} also accesses files.  @strong{For now, we
+that @file{process_execute()} also accesses files.  @strong{For now, we
 recommend against modifying code in the @file{filesys} directory.}
 
 We have provided you a function for each system call in
@@ -393,9 +390,6 @@ exception is a call to the @code{halt} system call.
 @node User Programs FAQ
 @section FAQ
 
-@enumerate 1
-@item General FAQs
-
 @enumerate 1
 @item
 @b{Do we need a working project 1 to implement project 2?}
@@ -433,7 +427,7 @@ You need to modify @file{tests/Makefile}.
 @b{What's the difference between @code{tid_t} and @code{pid_t}?}
 
 A @code{tid_t} identifies a kernel thread, which may have a user
-process running in it (if created with @code{thread_execute()}) or not
+process running in it (if created with @code{process_execute()}) or not
 (if created with @code{thread_create()}).  It is a data type used only
 in the kernel.
 
@@ -450,19 +444,64 @@ same process, or you can use a more complex mapping.  It's up to you.
 @b{I can't seem to figure out how to read from and write to user
 memory. What should I do?}
 
-The kernel must treat user memory delicately.  The user can pass a
-null pointer or an invalid pointer (one that doesn't point to any
-memory at all), or a kernel pointer (above @code{PHYS_BASE}).  All of
-these must be rejected without harm to the kernel or other running
-processes.
+The kernel must treat user memory delicately.  As part of a system
+call, the user can pass to the kernel a null pointer, a pointer to
+unmapped virtual memory, or a pointer to kernel virtual address space
+(above @code{PHYS_BASE}).  All of these types of invalid pointers must
+be rejected without harm to the kernel or other running processes.  At
+your option, the kernel may handle invalid pointers by terminating the
+process or returning from the system call with an error.
+
+There are at least two reasonable ways to do this correctly.  The
+first method is to ``verify then access'':@footnote{These terms are
+made up for this document.  They are not standard terminology.} verify
+the validity of a user-provided pointer, then dereference it.  If you
+choose this route, you'll want to look at the functions in
+@file{userprog/pagedir.c} and in @file{threads/mmu.h}.  This is the
+simplest way to handle user memory access.
+
+The second method is to ``assume and react'': directly dereference
+user pointers, after checking that they point below @code{PHYS_BASE}.
+Invalid user pointers will then cause a ``page fault'' that you can
+handle by modifying the code for @code{page_fault()} in
+@file{userprog/exception.cc}.  This technique is normally faster
+because it takes advantage of the processor's MMU, so it tends to be
+used in real kernels (including Linux).
+
+In either case, you need to make sure not to ``leak'' resources.  For
+example, suppose that your system call has acquired a lock or
+allocated a page of memory.  If you encounter an invalid user pointer
+afterward, you must still be sure to release the lock or free the page
+of memory.  If you choose to ``verify then access,'' then this should
+be straightforward, but for ``assume and react'' it's more difficult,
+because there's no way to return an error code from a memory access.
+Therefore, for those who want to try the latter technique, we'll
+provide a little bit of helpful code:
+
+@example
+/* 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) @{
+  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) @{
+  int eax;
+  asm ("movl $1f, %%eax; movb %b2, %0; 1:"
+       : "=m" (*udst), "=&a" (eax) : "r" (byte));
+  return eax != 0;
+@}
+@end example
 
-There are at least two reasonable ways to access user memory.  First,
-you can translate user addresses (below @code{PHYS_BASE}) into kernel
-addresses (above @code{PHYS_BASE}) using the functions in
-@file{pagedir.c}, and then access kernel memory.  Second, you can
-dereference user pointers directly and handle page faults by
-terminating the process.  In either case, you'll need to reject kernel
-pointers as a special case.
+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
+modified @code{page_fault()} so that a page fault in the kernel causes
+@code{eax} to be set to 0 and its former value copied into @code{eip}.
 
 @item
 @b{I'm also confused about reading from and writing to the stack. Can
@@ -485,9 +524,21 @@ the location.
 @item
 Each character is 1 byte.
 @end itemize
+
+@item
+@b{Why doesn't keyboard input work with @option{-v}?}
+
+Serial input isn't implemented.  Don't use @option{-v} if you want to
+use the shell or otherwise type at the keyboard.
 @end enumerate
 
-@item Argument Passing FAQs
+@menu
+* Problem 2-1 Argument Passing FAQ::  
+* Problem 2-2 System Calls FAQ::  
+@end menu
+
+@node Problem 2-1 Argument Passing FAQ
+@subsection Problem 2-1: Argument Passing FAQ
 
 @enumerate 1
 @item
@@ -530,7 +581,8 @@ any multiple of @t{0x10000000} from @t{0x80000000} to @t{0xc0000000},
 simply via recompilation.
 @end enumerate
 
-@item System Calls FAQs
+@node Problem 2-2 System Calls FAQ
+@subsection Problem 2-2: System Calls FAQ
 
 @enumerate 1
 @item
@@ -558,6 +610,7 @@ maximum.  That said, if your design calls for it, you may impose a
 limit of 128 open files per process (as the Solaris machines here do).
 
 @item
+@anchor{Removing an Open File}
 @b{What happens when two (or more) processes have a file open and one of
 them removes it?}
 
@@ -591,7 +644,6 @@ You should print the complete thread name (as specified in the
 @code{SYS_exec} call) followed by the exit status code,
 e.g.@: @samp{example 1 2 3 4: 0}.
 @end enumerate
-@end enumerate
 
 @node 80x86 Calling Convention
 @section 80@var{x}86 Calling Convention
@@ -602,7 +654,7 @@ calling convention.  Some of the basics should be familiar from CS
 have seen even more of it.  I've omitted some of the complexity, since
 this isn't a class in how function calls work, so don't expect this to
 be exactly correct in full, gory detail.  If you do want all the
-details, you can refer to @cite{[SysV-i386]}.
+details, you can refer to @bibref{SysV-i386}.
 
 Whenever a function call happens, you need to put the arguments on the
 call stack for that function, before the code for that function