Exemplo n.º 1
0
void
vm_tlbshootdown(const struct tlbshootdown *ts)
{
	vm_tlbflush(ts->target);
    V(ts->sem);
}
Exemplo n.º 2
0
int
as_copy(struct addrspace *old, struct addrspace **ret)
{
	struct addrspace *newas;
	int i,j, errno, retval, offset, region_len;
	struct region *old_region, *new_region;
	void *buffer;
	struct pt_entry *old_entry, *new_entry;

	newas = as_create();
	if (newas==NULL) {
		return ENOMEM;
	}

	buffer = kmalloc(PAGE_SIZE);

	newas->heap_start = old->heap_start;
	newas->heap_end = old->heap_end;

	// Copy regions
	region_len = array_num(old->as_regions);
	for (i = 0; i < region_len; i++) {
		old_region = array_get(old->as_regions, i);
		new_region = kmalloc(sizeof(struct region));
		if (old_region == NULL || new_region == NULL) {
			goto err0;
		}

		new_region->base = old_region->base;
		new_region->size = old_region->size;
		new_region->permission = old_region->permission;

		errno = array_add(newas->as_regions, new_region, NULL);
		if (errno) {
			goto err0;
		}
	}

	// Copy page table
	for (i = 0; i < PT_LEVEL_SIZE; i++){
		if (old->pagetable[i] != NULL){
			newas->pagetable[i] = kmalloc(PT_LEVEL_SIZE * sizeof(struct pt_entry));
			memset(newas->pagetable[i], 0, PT_LEVEL_SIZE * sizeof(struct pt_entry));
			// For each page table entry
			// Lock the entire L2 pagetable
			lock_acquire(old->pt_locks[i]);
			for (j = 0; j < PT_LEVEL_SIZE; j++){
				// We're about to copy this page. Make sure it can't be written to
				vm_tlbflush((i << 22) & (j << 12));

				old_entry = &old->pagetable[i][j];
				new_entry = &newas->pagetable[i][j];

				// For every valid pagetable entry...
				if (old_entry->allocated){
					offset = bs_alloc_index();
					if (old_entry->in_memory){
						// Write it to disk if it's in memory
						retval = bs_write_page((void *) PADDR_TO_KVADDR(old_entry->p_addr), offset);
						KASSERT(retval == 0);
					} else {
						// Or copy it to the new disk spot if not
						retval = bs_read_page(buffer, old_entry->store_index);
						KASSERT(retval == 0);

						retval = bs_write_page(buffer, offset);
						KASSERT(retval == 0);
					}
					// Update entry
					// TODO: this will be caught by coremap
					new_entry->p_addr = 0;
					new_entry->store_index = offset;
					new_entry->in_memory = false;
					new_entry->allocated = true;
				}
			}
			lock_release(old->pt_locks[i]);
		}
	}
	kfree(buffer);

	*ret = newas;

	return 0;

	err0:
	for (i=0; i < (int)region_len; i++){
		new_region = (struct region *)array_get(newas->as_regions,i);
		if (new_region != NULL)
			kfree(new_region);
	}
	return ENOMEM;
}