Reserve signal 0 for "null signal"

POSIX requires that signal 0 may be used in kill() and sigqueue() in
order to determine if a pid is valid (this functionality is also added
to sys_kill() in this commit).
Add sigqueue system call/library wrapper

This is of limited value since Telos doesn't implement queued signals
(not yet, anyways), but it could be useful if duplicate signals are rare
or a process only cares about the most recent signal.
Add SYS_SIGQUEUE and SI_* codes to syntax file

Also some other flags/codes that I forgot to add before.
U_CONTEXT_SIZE bugfix

Use U_CONTEXT_SIZE instead of pointer arithmetic to place interrupt
frame pointer in sig_restore.
Return negative error codes in signal functions

All syscalls should return negative error codes.
Add inline sig*set() functions to signal.h
Use 'device_operations' struct

Drivers provide a 'device_operations' struct which lists the
device-specific routines to be called for open(), close() etc..  This
means that device drivers no longer need to expose the names of their
routines, and entries in the device table are less cumbersome to
initialize.

Also, instead of using a dummy routine which returns an error for
unsupported operations, members of the 'device_operations' struct may be
set to NULL.  The device-independent routines will check for this and
return an error if no routine is provided for a device.
Allocate separate page directories for processes

Each process now has its own private page directory.  Currently this is
a shallow copy of the kernel's page directory.  The next logical step
would be to erase all unnecessary entries and map the stack somewhere.

paging_init() does some of the work already, by creating a 'dummy'
directory which maps the kernel and marks all other pages non-present.
pgdir_create() can memcpy() this directory and add mappings for stack
pages and whatnot.

Also, the pte_t type is defined through a typedef.  This type should be
used for referring to paging structure entries (PTEs and PDEs).
Add pte_t type to syntax file
Load kernel page directory after context switch

The kernel's page directory is loaded on every context switch into the
kernel.

Note: I had to hard-code the value of KERNEL_PAGE_OFFSET into the asm
constraint because of some stupidity with gcc (even though it agrees
that &_kernel_pgd and &KERNEL_PAGE_OFFSET are valid in an immediate
constraint, it complains that the difference of these values constitutes
an "impossible constraint").  I may have to replace KERNEL_PAGE_OFFSET
with a #define'd constant in the future.
Convert user pointers to physical addresses

Pointers from user address spaces are converted into physical addresses
for use in the kernel.

Also, the pmap_t type is defined for use with page directories.  This
name is shamelessly stolen from Mach, though pmap_t's in Mach contain
information in addition to the address of a page directory.
Separate functions for user/kernel process create

create_process() is split into functions create_kernel_process() and
create_user_process().  The helper function pcb_init() is defined in
order to capture some of the commonality between the two functions.

This will become more and more useful as differences between user and
kernel processes are implemented.  It was probably a bad idea to use a
general-purpose function to begin with.
Use 0-4MB for kernel heap, rest for pages

The kernel heap (i.e. memory managed by kmalloc(), kfree()) is
restricted to 0-4MB (mapped at 0xC0000000).  Everything else is managed
by the page frame allocator.
Copy Multiboot info structure to kernel memory
"Fix" stack after page fault

Some code is added to the page fault handler to patch up the stack so
that it looks like no error code was pushed.  I have no idea how the
page fault handler was working before.  This bug only became apparent
after unmapping the lower parts of memory (resulting in infinite page
faults).
Print faulting address for all page faults

Page-not-present page faults now print the offending address to the
console.
New copy_*_userspace() functions

The copy_*_userspace() functions are rewritten to use temporary page
mappings instead of assuming the region is identity-mapped in the
kernel.

In order to accomplish this, a page table is set up in paging_init() for
use with temporary mappings, and the functions kmap_page() and
kunmap_page() are defined to perform the actual mappings.  kunmap_page()
doesn't actually map the requested address, but rather returns the new
virtual address at which the requested location can be accessed.  This
makes copy_through_userspace() much simpler, since we don't have to
worry about address conflicts.
"Range" mapping of user memory

The functions kmap_tmp_range() and kunmap_range() are added to map
regions of memory in user-space which may cross page boundaries.  This
is now used in all copy_*_userspace() functions.

The helper function get_tmp_ptes() is pretty inefficient as it is now
implemented (linear scan through the temp page table).  This could be
improved somewhat by using a bitmap to map allocations within the temp
page table.  Then get_tmp_ptes() would have to scan at most 128 bytes to
find a mapping, as opposed to 4096.
Copy syscall arguments into kernel-space