X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=doc%2Fuserprog.texi;h=8ed52b1e6aca46b28c40c9d4a962ee95ee28f7d5;hb=ad463f508ae96156401eaadf92e5801ba393e63d;hp=a9a84b2dcd854609cbd40bd82648cf96b1a9773c;hpb=f415a37905c57f61b444806bf84f5405184452aa;p=pintos-anon diff --git a/doc/userprog.texi b/doc/userprog.texi index a9a84b2..8ed52b1 100644 --- a/doc/userprog.texi +++ b/doc/userprog.texi @@ -20,10 +20,9 @@ assignment. The ``alarm clock'' functionality may be useful in projects 3 and 4, but it is not strictly required. You might find it useful to go back and reread how to run the tests -(@pxref{Testing}). In particular, the tests for project 2 and later -projects will probably run faster if you use the qemu emulator, e.g.@: -via @code{make check PINTOSOPTS='--qemu'}. The qemu emulator is -available only on the Linux machines. +(@pxref{Testing}). In particular, the tests for project 2 (and later +projects) will probably run faster if you use the qemu emulator, e.g.@: +via @code{make check PINTOSOPTS='--qemu'}. @menu * Project 2 Background:: @@ -430,29 +429,37 @@ Therefore, for those who want to try the latter technique, we'll provide a little bit of helpful code: @verbatim -/* Tries to copy a byte from user address USRC to kernel address KDST. - Returns true if successful, false if USRC is invalid. */ -static inline bool get_user (uint8_t *kdst, const uint8_t *usrc) { - int eax; - asm ("movl $1f, %%eax; movb %2, %%al; movb %%al, %0; 1:" - : "=m" (*kdst), "=&a" (eax) : "m" (*usrc)); - return eax != 0; +/* Reads a byte at user virtual address UADDR. + UADDR must be below PHYS_BASE. + Returns the byte value if successful, -1 if a segfault + occurred. */ +static int +get_user (const uint8_t *uaddr) +{ + int result; + asm ("movl $1f, %0; movzbl %1, %0; 1:" + : "=&a" (result) : "m" (*uaddr)); + return result; } - -/* Tries to 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; + +/* Writes BYTE to user address UDST. + UDST must be below PHYS_BASE. + Returns true if successful, false if a segfault occurred. */ +static bool +put_user (uint8_t *udst, uint8_t byte) +{ + int error_code; + asm ("movl $1f, %0; movb %b2, %1; 1:" + : "=&a" (error_code), "=m" (*udst) : "r" (byte)); + return error_code != -1; } @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 -modified @func{page_fault} so that a page fault in the kernel merely sets -@code{eax} to 0 and copies its former value into @code{eip}. +modified @func{page_fault} so that a page fault in the kernel merely +sets @code{eax} to @t{0xffffffff} and copies its former value +into @code{eip}. @node Project 2 Suggested Order of Implementation @section Suggested Order of Implementation