in main.c and don't make it disk specific; the icache is shared. This
doesn't matter since we have only one disk, but conceptually cleaner
and maybe helpful to students for mount lab.
Use refcnt to pin blocks into the cache
Replace flags/B_VALID with a boolean field valid
Use info[id].status to signal completion of disk interrupt
Pass a read/write flag to virtio_disk_rw
procinit() and map them high up (below TRAMPOLNE) with an empty
mapping below each stack. Never free a kernel stack.
Another way would be to allocate and map them dynamically, but then we
need to reload page table when switching processes in scheduler()
and/or have a kernel pagetable per proc (if we want k->stack to be the
same virtual address in each process).
One gotcha: kernel addresses are not equal to physical addresses for
stack addresses. A stack address must be translated if we need its
physical address (e.g., virtio passes a stack address to the disk).