Merge branch 'upstream'
This commit is contained in:
		| @@ -135,12 +135,6 @@ coremap_used_bytes() { | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| 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) | ||||||
| { | { | ||||||
|   | |||||||
| @@ -75,24 +75,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. | ||||||
|  * |  * | ||||||
|   | |||||||
| @@ -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. | ||||||
|   | |||||||
| @@ -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); | ||||||
|  |  | ||||||
| /* | /* | ||||||
|   | |||||||
| @@ -63,7 +63,6 @@ void free_kpages(vaddr_t addr); | |||||||
| unsigned int coremap_used_bytes(void); | unsigned int coremap_used_bytes(void); | ||||||
|  |  | ||||||
| /* 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 *); | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -478,7 +478,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. | ||||||
| @@ -1139,6 +1139,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) | ||||||
| { | { | ||||||
| @@ -1153,16 +1156,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; | ||||||
| @@ -1175,11 +1190,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; | ||||||
| @@ -1207,14 +1225,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; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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();*/ | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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). | ||||||
|   | |||||||
| @@ -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" | ||||||
|   | |||||||
| @@ -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 */ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user