Merge in 2.0.2.

This commit is contained in:
Geoffrey Challen 2017-01-09 22:58:21 -05:00
parent cafa9f5690
commit 08a300d1a6
12 changed files with 2010 additions and 688 deletions

2497
CHANGES

File diff suppressed because it is too large Load Diff

View File

@ -126,12 +126,6 @@ free_kpages(vaddr_t addr)
(void)addr; (void)addr;
} }
void
vm_tlbshootdown_all(void)
{
panic("dumbvm tried to do tlb shootdown?!\n");
}
void void
vm_tlbshootdown(const struct tlbshootdown *ts) vm_tlbshootdown(const struct tlbshootdown *ts)
{ {

View File

@ -74,24 +74,21 @@ struct cpu {
* Accessed by other cpus. * Accessed by other cpus.
* Protected by the IPI lock. * Protected by the IPI lock.
* *
* If c_numshootdown is -1 (TLBSHOOTDOWN_ALL), all mappings * TLB shootdown requests made to this CPU are queued in
* should be invalidated. This is used if more than * c_shootdown[], with c_numshootdown holding the number of
* TLBSHOOTDOWN_MAX mappings are going to be invalidated at * requests. TLBSHOOTDOWN_MAX is the maximum number that can
* once. TLBSHOOTDOWN_MAX is MD and chosen based on when it * be queued at once, which is machine-dependent.
* becomes more efficient just to flush the whole TLB.
* *
* struct tlbshootdown is machine-dependent and might * The contents of struct tlbshootdown are also machine-
* reasonably be either an address space and vaddr pair, or a * dependent and might reasonably be either an address space
* paddr, or something else. * and vaddr pair, or a paddr, or something else.
*/ */
uint32_t c_ipi_pending; /* One bit for each IPI number */ uint32_t c_ipi_pending; /* One bit for each IPI number */
struct tlbshootdown c_shootdown[TLBSHOOTDOWN_MAX]; struct tlbshootdown c_shootdown[TLBSHOOTDOWN_MAX];
int c_numshootdown; unsigned c_numshootdown;
struct spinlock c_ipi_lock; struct spinlock c_ipi_lock;
}; };
#define TLBSHOOTDOWN_ALL (-1)
/* /*
* Initialization functions. * Initialization functions.
* *

View File

@ -34,7 +34,7 @@
* Leave this alone, so we can tell what version of the OS/161 base * Leave this alone, so we can tell what version of the OS/161 base
* code we gave you. * code we gave you.
*/ */
#define BASE_VERSION "2.0.1" #define BASE_VERSION "2.0.2"
/* /*
* Change this as you see fit in the course of hacking the system. * Change this as you see fit in the course of hacking the system.

View File

@ -156,6 +156,13 @@ int vfs_getcwd(struct uio *buf);
* vfs_unmount - Unmount the filesystem presently mounted on the * vfs_unmount - Unmount the filesystem presently mounted on the
* specified device. * specified device.
* *
* vfs_swapon - Look up DEVNAME and mark it as a swap device,
* returning a vnode. Similar to vfs_mount.
*
* vfs_swapoff - Unmark DEVNAME as a swap device. The vnode
* previously returned by vfs_swapon should be
* decref'd first. Similar to vfs_unmount.
*
* vfs_unmountall - Unmount all mounted filesystems. * vfs_unmountall - Unmount all mounted filesystems.
*/ */
@ -172,6 +179,8 @@ int vfs_mount(const char *devname, void *data,
struct device *dev, struct device *dev,
struct fs **result)); struct fs **result));
int vfs_unmount(const char *devname); int vfs_unmount(const char *devname);
int vfs_swapon(const char *devname, struct vnode **result);
int vfs_swapoff(const char *devname);
int vfs_unmountall(void); int vfs_unmountall(void);
/* /*

View File

@ -56,7 +56,6 @@ vaddr_t alloc_kpages(unsigned npages);
void free_kpages(vaddr_t addr); void free_kpages(vaddr_t addr);
/* TLB shootdown handling called from interprocessor_interrupt */ /* TLB shootdown handling called from interprocessor_interrupt */
void vm_tlbshootdown_all(void);
void vm_tlbshootdown(const struct tlbshootdown *); void vm_tlbshootdown(const struct tlbshootdown *);

View File

@ -465,7 +465,7 @@ thread_make_runnable(struct thread *target, bool already_have_lock)
target->t_state = S_READY; target->t_state = S_READY;
threadlist_addtail(&targetcpu->c_runqueue, target); threadlist_addtail(&targetcpu->c_runqueue, target);
if (targetcpu->c_isidle) { if (targetcpu->c_isidle && targetcpu != curcpu->c_self) {
/* /*
* Other processor is idle; send interrupt to make * Other processor is idle; send interrupt to make
* sure it unidles. * sure it unidles.
@ -1106,6 +1106,9 @@ ipi_send(struct cpu *target, int code)
spinlock_release(&target->c_ipi_lock); spinlock_release(&target->c_ipi_lock);
} }
/*
* Send an IPI to all CPUs.
*/
void void
ipi_broadcast(int code) ipi_broadcast(int code)
{ {
@ -1120,16 +1123,28 @@ ipi_broadcast(int code)
} }
} }
/*
* Send a TLB shootdown IPI to the specified CPU.
*/
void void
ipi_tlbshootdown(struct cpu *target, const struct tlbshootdown *mapping) ipi_tlbshootdown(struct cpu *target, const struct tlbshootdown *mapping)
{ {
int n; unsigned n;
spinlock_acquire(&target->c_ipi_lock); spinlock_acquire(&target->c_ipi_lock);
n = target->c_numshootdown; n = target->c_numshootdown;
if (n == TLBSHOOTDOWN_MAX) { if (n == TLBSHOOTDOWN_MAX) {
target->c_numshootdown = TLBSHOOTDOWN_ALL; /*
* If you have problems with this panic going off,
* consider: (1) increasing the maximum, (2) putting
* logic here to sleep until space appears (may
* interact awkwardly with VM system locking), (3)
* putting logic here to coalesce requests together,
* and/or (4) improving VM system state tracking to
* reduce the number of unnecessary shootdowns.
*/
panic("ipi_tlbshootdown: Too many shootdowns queued\n");
} }
else { else {
target->c_shootdown[n] = *mapping; target->c_shootdown[n] = *mapping;
@ -1142,11 +1157,14 @@ ipi_tlbshootdown(struct cpu *target, const struct tlbshootdown *mapping)
spinlock_release(&target->c_ipi_lock); spinlock_release(&target->c_ipi_lock);
} }
/*
* Handle an incoming interprocessor interrupt.
*/
void void
interprocessor_interrupt(void) interprocessor_interrupt(void)
{ {
uint32_t bits; uint32_t bits;
int i; unsigned i;
spinlock_acquire(&curcpu->c_ipi_lock); spinlock_acquire(&curcpu->c_ipi_lock);
bits = curcpu->c_ipi_pending; bits = curcpu->c_ipi_pending;
@ -1175,14 +1193,14 @@ interprocessor_interrupt(void)
*/ */
} }
if (bits & (1U << IPI_TLBSHOOTDOWN)) { if (bits & (1U << IPI_TLBSHOOTDOWN)) {
if (curcpu->c_numshootdown == TLBSHOOTDOWN_ALL) { /*
vm_tlbshootdown_all(); * Note: depending on your VM system locking you might
} * need to release the ipi lock while calling
else { * vm_tlbshootdown.
*/
for (i=0; i<curcpu->c_numshootdown; i++) { for (i=0; i<curcpu->c_numshootdown; i++) {
vm_tlbshootdown(&curcpu->c_shootdown[i]); vm_tlbshootdown(&curcpu->c_shootdown[i]);
} }
}
curcpu->c_numshootdown = 0; curcpu->c_numshootdown = 0;
} }

View File

@ -82,6 +82,9 @@ struct knowndev {
struct fs *kd_fs; struct fs *kd_fs;
}; };
/* A placeholder for kd_fs for devices used as swap */
#define SWAP_FS ((struct fs *)-1)
DECLARRAY(knowndev, static __UNUSED inline); DECLARRAY(knowndev, static __UNUSED inline);
DEFARRAY(knowndev, static __UNUSED inline); DEFARRAY(knowndev, static __UNUSED inline);
@ -160,7 +163,7 @@ vfs_sync(void)
num = knowndevarray_num(knowndevs); num = knowndevarray_num(knowndevs);
for (i=0; i<num; i++) { for (i=0; i<num; i++) {
dev = knowndevarray_get(knowndevs, i); dev = knowndevarray_get(knowndevs, i);
if (dev->kd_fs != NULL) { if (dev->kd_fs != NULL && dev->kd_fs != SWAP_FS) {
/*result =*/ FSOP_SYNC(dev->kd_fs); /*result =*/ FSOP_SYNC(dev->kd_fs);
} }
} }
@ -195,7 +198,7 @@ vfs_getroot(const char *devname, struct vnode **ret)
* and DEVNAME names the device, return ENXIO. * and DEVNAME names the device, return ENXIO.
*/ */
if (kd->kd_fs!=NULL) { if (kd->kd_fs != NULL && kd->kd_fs != SWAP_FS) {
const char *volname; const char *volname;
volname = FSOP_GETVOLNAME(kd->kd_fs); volname = FSOP_GETVOLNAME(kd->kd_fs);
@ -344,7 +347,7 @@ badnames(const char *n1, const char *n2, const char *n3)
for (i=0; i<num; i++) { for (i=0; i<num; i++) {
kd = knowndevarray_get(knowndevs, i); kd = knowndevarray_get(knowndevs, i);
if (kd->kd_fs) { if (kd->kd_fs != NULL && kd->kd_fs != SWAP_FS) {
volname = FSOP_GETVOLNAME(kd->kd_fs); volname = FSOP_GETVOLNAME(kd->kd_fs);
if (samestring3(volname, n1, n2, n3)) { if (samestring3(volname, n1, n2, n3)) {
return 1; return 1;
@ -542,6 +545,7 @@ vfs_mount(const char *devname, void *data,
} }
KASSERT(fs != NULL); KASSERT(fs != NULL);
KASSERT(fs != SWAP_FS);
kd->kd_fs = fs; kd->kd_fs = fs;
@ -553,6 +557,59 @@ vfs_mount(const char *devname, void *data,
return 0; return 0;
} }
/*
* Like mount, but for attaching swap. Hands back the raw device
* vnode. Unlike mount tolerates a trailing colon on the device name,
* to avoid student-facing confusion.
*/
int
vfs_swapon(const char *devname, struct vnode **ret)
{
char *myname = NULL;
size_t len;
struct knowndev *kd;
int result;
len = strlen(devname);
if (len > 0 && devname[len - 1] == ':') {
/* tolerate trailing :, e.g. lhd0: rather than lhd0 */
myname = kstrdup(devname);
if (myname == NULL) {
return ENOMEM;
}
myname[len - 1] = 0;
devname = myname;
}
vfs_biglock_acquire();
result = findmount(devname, &kd);
if (result) {
goto out;
}
if (kd->kd_fs != NULL) {
result = EBUSY;
goto out;
}
KASSERT(kd->kd_rawname != NULL);
KASSERT(kd->kd_device != NULL);
kprintf("vfs: Swap attached to %s\n", kd->kd_name);
kd->kd_fs = SWAP_FS;
VOP_INCREF(kd->kd_vnode);
*ret = kd->kd_vnode;
out:
vfs_biglock_release();
if (myname != NULL) {
kfree(myname);
}
return result;
}
/* /*
* Unmount a filesystem/device by name. * Unmount a filesystem/device by name.
* First calls FSOP_SYNC on the filesystem; then calls FSOP_UNMOUNT. * First calls FSOP_SYNC on the filesystem; then calls FSOP_UNMOUNT.
@ -570,7 +627,7 @@ vfs_unmount(const char *devname)
goto fail; goto fail;
} }
if (kd->kd_fs == NULL) { if (kd->kd_fs == NULL || kd->kd_fs == SWAP_FS) {
result = EINVAL; result = EINVAL;
goto fail; goto fail;
} }
@ -600,6 +657,43 @@ vfs_unmount(const char *devname)
return result; return result;
} }
/*
* Detach swap. Like unmount.
*
* (Provided for completeness; there is no real need to remove swap
* explicitly prior to shutting down, except perhaps when swapping to
* things that themselves want a clean shutdown, like RAIDs.)
*/
int
vfs_swapoff(const char *devname)
{
struct knowndev *kd;
int result;
vfs_biglock_acquire();
result = findmount(devname, &kd);
if (result) {
goto fail;
}
if (kd->kd_fs != SWAP_FS) {
result = EINVAL;
goto fail;
}
kprintf("vfs: Swap detached from %s:\n", kd->kd_name);
/* drop it */
kd->kd_fs = NULL;
KASSERT(result==0);
fail:
vfs_biglock_release();
return result;
}
/* /*
* Global unmount function. * Global unmount function.
*/ */
@ -623,6 +717,11 @@ vfs_unmountall(void)
/* not mounted */ /* not mounted */
continue; continue;
} }
if (dev->kd_fs == SWAP_FS) {
/* just drop it */
dev->kd_fs = NULL;
continue;
}
kprintf("vfs: Unmounting %s:\n", dev->kd_name); kprintf("vfs: Unmounting %s:\n", dev->kd_name);

View File

@ -129,7 +129,8 @@ vnode_decref(struct vnode *vn)
void void
vnode_check(struct vnode *v, const char *opstr) vnode_check(struct vnode *v, const char *opstr)
{ {
vfs_biglock_acquire(); /* not safe, and not really needed to check constant fields */
/*vfs_biglock_acquire();*/
if (v == NULL) { if (v == NULL) {
panic("vnode_check: vop_%s: null vnode\n", opstr); panic("vnode_check: vop_%s: null vnode\n", opstr);
@ -173,5 +174,5 @@ vnode_check(struct vnode *v, const char *opstr)
} }
spinlock_release(&v->vn_countlock); spinlock_release(&v->vn_countlock);
vfs_biglock_release(); /*vfs_biglock_release();*/
} }

View File

@ -96,7 +96,7 @@
# the build. Default is $(WORKDIR)/tooldir. # the build. Default is $(WORKDIR)/tooldir.
# #
# INSTALLTOP Staging directory for installation. # INSTALLTOP Staging directory for installation.
# Default is $(WORKDIR)/install # Default is $(WORKDIR)/install.
# #
# Probably the only reason to change these would be if you're short on # Probably the only reason to change these would be if you're short on
# diskspace in $(WORKDIR). # diskspace in $(WORKDIR).

View File

@ -55,10 +55,13 @@ installmanpages:
cp $(_F_) $(OSTREE)$(MANDIR)/$(_F_) cp $(_F_) $(OSTREE)$(MANDIR)/$(_F_)
.endfor .endfor
# clean: remove build products (nothing to do)
clean-local: ;
# Mark targets that don't represent files PHONY, to prevent various # Mark targets that don't represent files PHONY, to prevent various
# lossage if files by those names appear. # lossage if files by those names appear.
.PHONY: all all-local install-staging-local install-local installmanpages .PHONY: all all-local install-staging-local install-local installmanpages
.PHONY: clean-local
# Finally, get the shared definitions for the most basic rules. # Finally, get the shared definitions for the most basic rules.
.include "$(TOP)/mk/os161.baserules.mk" .include "$(TOP)/mk/os161.baserules.mk"

View File

@ -174,8 +174,11 @@ spawn(int njobs)
for (i=0; i<njobs; i++) { for (i=0; i<njobs; i++) {
pids[i] = fork(); pids[i] = fork();
if (pids[i] == -1) { if (pids[i] == -1) {
/* abandon the other procs; no way to kill them */ /* continue with the procs we have; cannot kill them */
err(1, "fork"); warn("fork");
warnx("*** Only started %u processes ***", i);
njobs = i;
break;
} }
if (pids[i] == 0) { if (pids[i] == 0) {
/* child */ /* child */