Exemplo n.º 1
0
static
int
load_each_segment(struct vnode *v, off_t offset, vaddr_t vaddr, paddr_t paddr, 
                  size_t memsize, size_t filesize,
                  int is_executable, int first_read)
{
	struct uio u;
	int result;
	size_t fillamt;
    int spl;
    
	if (filesize > memsize) {
		kprintf("ELF: warning: segment filesize > segment memsize\n");
		filesize = memsize;
	}
    
	DEBUG(DB_EXEC, "ELF: Loading %lu bytes to 0x%lx\n", 
	      (unsigned long) filesize, (unsigned long) vaddr);
    
    if(first_read == 0){
        
        u.uio_iovec.iov_ubase = (userptr_t)vaddr;
        u.uio_iovec.iov_len = memsize;   // length of the memory space
        u.uio_resid = filesize;          // amount to actually read
        u.uio_offset = offset;
        u.uio_segflg = is_executable ? UIO_USERISPACE : UIO_USERSPACE;
        u.uio_rw = UIO_READ;
        u.uio_space = curthread->t_vmspace;
        
    }else{
        
        return 0;
    }
	
    result = VOP_READ(v, &u);
    
	if (result) {
        
		return result;
	}
	if (u.uio_resid != 0) {
		/* short read; problem with executable? */
		kprintf("ELF: short read on segment - file truncated?\n");
		return ENOEXEC;
	}
    
    /* Fill the rest of the memory space (if any) with zeros */
	fillamt = memsize - filesize;
	if (fillamt > 0) {
		DEBUG(DB_EXEC, "ELF: Zero-filling %lu more bytes\n", 
		      (unsigned long) fillamt);
		u.uio_resid += fillamt;
		result = uiomovezeros(fillamt, &u);
	}
	return result;
}
Exemplo n.º 2
0
/*
 * Load a segment at virtual address VADDR. The segment in memory
 * extends from VADDR up to (but not including) VADDR+MEMSIZE. The
 * segment on disk is located at file offset OFFSET and has length
 * FILESIZE.
 *
 * FILESIZE may be less than MEMSIZE; if so the remaining portion of
 * the in-memory segment should be zero-filled.
 *
 * Note that uiomove will catch it if someone tries to load an
 * executable whose load address is in kernel space. If you should
 * change this code to not use uiomove, be sure to check for this case
 * explicitly.
 */
int
load_segment(struct vnode *v, off_t offset, vaddr_t vaddr, 
	     size_t memsize, size_t filesize,
	     int is_executable)
{

	struct uio u; // Memory block
	int result;
	size_t fillamt;


	// The virtual memory has to be bigger then the file that we are loading into it
	if (filesize > memsize) {
		kprintf("ELF: warning: segment filesize > segment memsize\n");
		filesize = memsize;
	}

	DEBUG(DB_EXEC, "ELF: Loading %lu bytes to 0x%lx\n", 
	      (unsigned long) filesize, (unsigned long) vaddr);

	//u.uio_iovec.iov_ubase = (userptr_t)PADDR_TO_KVADDR(vaddr);
	u.uio_iovec.iov_ubase = (userptr_t)vaddr;
	u.uio_iovec.iov_len = memsize;   // length of the memory space
	u.uio_resid = filesize;          // amount to actually read
	u.uio_offset = offset;
	//u.uio_segflg = is_executable ? UIO_USERISPACE : UIO_USERSPACE;
	u.uio_segflg = UIO_SYSSPACE;
	u.uio_rw = UIO_READ;
	//u.uio_space = curthread->t_vmspace;
	u.uio_space = NULL;

	result = VOP_READ(v, &u);
	if (result) {
		return result;
	}

	DEBUG(1,"after read\n");

	if (u.uio_resid != 0) {
		/* short read; problem with executable? */
		kprintf("ELF: short read on segment - file truncated?\n");
		return ENOEXEC;
	}

	/* Fill the rest of the memory space (if any) with zeros */
	fillamt = memsize - filesize;
	if (fillamt > 0) {
		DEBUG(DB_EXEC, "ELF: Zero-filling %lu more bytes\n", 
		      (unsigned long) fillamt);
		u.uio_resid += fillamt;
		result = uiomovezeros(fillamt, &u);
	}
	
	return result;
}
Exemplo n.º 3
0
/*
 * Do I/O (either read or write) of a single whole block.
 */
static
int
sfs_blockio(struct sfs_vnode *sv, struct uio *uio)
{
	struct sfs_fs *sfs = sv->sv_v.vn_fs->fs_data;
	u_int32_t diskblock;
	u_int32_t fileblock;
	int result;
	int doalloc = (uio->uio_rw==UIO_WRITE);
	off_t saveoff;
	off_t diskoff;
	off_t saveres;
	off_t diskres;

	/* Get the block number within the file */
	fileblock = uio->uio_offset / SFS_BLOCKSIZE;

	/* Look up the disk block number */
	result = sfs_bmap(sv, fileblock, doalloc, &diskblock);
	if (result) {
		return result;
	}

	if (diskblock == 0) {
		/*
		 * No block - fill with zeros.
		 *
		 * We must be reading, or sfs_bmap would have
		 * allocated a block for us.
		 */
		assert(uio->uio_rw == UIO_READ);
		return uiomovezeros(SFS_BLOCKSIZE, uio);
	}

	/*
	 * Do the I/O directly to the uio region. Save the uio_offset,
	 * and substitute one that makes sense to the device.
	 */
	saveoff = uio->uio_offset;
	diskoff = diskblock * SFS_BLOCKSIZE;
	uio->uio_offset = diskoff;

	/*
	 * Temporarily set the residue to be one block size.
	 */
	assert(uio->uio_resid >= SFS_BLOCKSIZE);
	saveres = uio->uio_resid;
	diskres = SFS_BLOCKSIZE;
	uio->uio_resid = diskres;
	
	result = sfs_rwblock(sfs, uio);

	/*
	 * Now, restore the original uio_offset and uio_resid and update 
	 * them by the amount of I/O done.
	 */
	uio->uio_offset = (uio->uio_offset - diskoff) + saveoff;
	uio->uio_resid = (uio->uio_resid - diskres) + saveres;

	return result;
}
Exemplo n.º 4
0
/*
 * Load a segment at virtual address VADDR. The segment in memory
 * extends from VADDR up to (but not including) VADDR+MEMSIZE. The
 * segment on disk is located at file offset OFFSET and has length
 * FILESIZE.
 *
 * FILESIZE may be less than MEMSIZE; if so the remaining portion of
 * the in-memory segment should be zero-filled.
 *
 * Note that uiomove will catch it if someone tries to load an
 * executable whose load address is in kernel space. If you should
 * change this code to not use uiomove, be sure to check for this case
 * explicitly.
 */
static
int
load_segment(struct addrspace *as, struct vnode *v,
	     off_t offset, vaddr_t vaddr, 
	     size_t memsize, size_t filesize,
	     int is_executable)
{
	struct iovec iov;
	struct uio u;
	int result;

	if (filesize > memsize) {
		kprintf("ELF: warning: segment filesize > segment memsize\n");
		filesize = memsize;
	}

	DEBUG(DB_EXEC, "ELF: Loading %lu bytes to 0x%lx\n", 
	      (unsigned long) filesize, (unsigned long) vaddr);

	iov.iov_ubase = (userptr_t)vaddr;
	iov.iov_len = memsize;		 // length of the memory space
	u.uio_iov = &iov;
	u.uio_iovcnt = 1;
	u.uio_resid = filesize;          // amount to read from the file
	u.uio_offset = offset;
	u.uio_segflg = is_executable ? UIO_USERISPACE : UIO_USERSPACE;
	u.uio_rw = UIO_READ;
	u.uio_space = as;

	result = VOP_READ(v, &u);
	if (result) {
		return result;
	}

	if (u.uio_resid != 0) {
		/* short read; problem with executable? */
		kprintf("ELF: short read on segment - file truncated?\n");
		return ENOEXEC;
	}

	/*
	 * If memsize > filesize, the remaining space should be
	 * zero-filled. There is no need to do this explicitly,
	 * because the VM system should provide pages that do not
	 * contain other processes' data, i.e., are already zeroed.
	 *
	 * During development of your VM system, it may have bugs that
	 * cause it to (maybe only sometimes) not provide zero-filled
	 * pages, which can cause user programs to fail in strange
	 * ways. Explicitly zeroing program BSS may help identify such
	 * bugs, so the following disabled code is provided as a
	 * diagnostic tool. Note that it must be disabled again before
	 * you submit your code for grading.
	 */
#if 0
	{
		size_t fillamt;

		fillamt = memsize - filesize;
		if (fillamt > 0) {
			DEBUG(DB_EXEC, "ELF: Zero-filling %lu more bytes\n", 
			      (unsigned long) fillamt);
			u.uio_resid += fillamt;
			result = uiomovezeros(fillamt, &u);
		}
	}
#endif
	
	return result;
}
Exemplo n.º 5
0
int
swap_pagein( u_int32_t paddr, int rw, u_int32_t mem, u_int32_t file, u_int32_t offset, int swap, int swap_index)
{
	int result;
	int fillamt;
	struct uio u;
	struct addrspace *as;
//	struct vnode *swap_vnode;

	as = curthread->t_vmspace;

	if(swap == 1)
	{
		result = vfs_open(SWAP_DEVICE, O_RDWR, &swap_vnode);
		mk_kuio(&u, paddr, PAGE_SIZE, swap_index * PAGE_SIZE, UIO_READ);
		result = VOP_READ(swap_vnode, &u);

		if (result) {
			return result;
		}

		vfs_close(swap_vnode);
	}
	else 
	{
		/* Open the file. */
		struct vnode *v;
		result = vfs_open(as->as_progname, O_RDONLY, &v);
		if (result) {
			return result;
		}

		mk_kuio_pd(&u, paddr, mem, file, offset, rw);
		if(rw == UIO_READ)
		{
			result = VOP_READ(v, &u)	;
		}
		else
		{
			result = VOP_WRITE(v, &u);
		}

		if (u.uio_resid != 0) {
			/* short read; problem with executable? */
			kprintf("ELF: short read on segment - file truncated?\n");
			return ENOEXEC;
		}

		/* Fill the rest of the memory space (if any) with zeros */
		fillamt = mem - file;
		if (fillamt > 0) {

			u.uio_resid += fillamt;
			u.uio_rw = UIO_READ;
			result = uiomovezeros(fillamt, &u);
		}
				
		if (result==EIO) {
			panic("swap: EIO on swapfile (offset %ld)\n",
			      (long)as->as_offset1);
		}
		else if (result==EINVAL) {
			panic("swap: EINVAL from swapfile (offset %ld)\n",
			      (long)as->as_offset1);
		}
		else if (result) {
			panic("swap: Error %d from swapfile (offset %ld)\n",
			      result, (long)as->as_offset1);
		}

		/* Done with the file now. */
		vfs_close(v);

		return 0;
	
	}




}
Exemplo n.º 6
0
/*
 * Do I/O (either read or write) of a single whole block.
 *
 * Locking: must hold vnode lock. May get/release sfs_freemaplock.
 *
 * Requires up to 2 buffers.
 */
static
int
sfs_blockio(struct sfs_vnode *sv, struct uio *uio)
{
	struct sfs_fs *sfs = sv->sv_absvn.vn_fs->fs_data;
	struct buf *iobuf;
	void *ioptr;
	daddr_t diskblock;
	uint32_t fileblock;
	int result;
	bool doalloc = (uio->uio_rw==UIO_WRITE);
	unsigned new_checksum = 0;

	KASSERT(lock_do_i_hold(sv->sv_lock));

	/* Get the block number within the file */
	fileblock = uio->uio_offset / SFS_BLOCKSIZE;

	/* Look up the disk block number */
	result = sfs_bmap(sv, fileblock, doalloc, &diskblock);
	if (result) {
		return result;
	}

	if (diskblock == 0) {
		/*
		 * No block - fill with zeros.
		 *
		 * We must be reading, or sfs_bmap would have
		 * allocated a block for us.
		 */
		KASSERT(uio->uio_rw == UIO_READ);
		return uiomovezeros(SFS_BLOCKSIZE, uio);
	}

	if (uio->uio_rw == UIO_READ) {
		result = buffer_read(&sfs->sfs_absfs, diskblock, SFS_BLOCKSIZE,
				     &iobuf);
	}
	else {
		result = buffer_get(&sfs->sfs_absfs, diskblock, SFS_BLOCKSIZE,
				    &iobuf);
	}
	if (result) {
		return result;
	}

	/*
	 * Do the I/O into the buffer.
	 */
	ioptr = buffer_map(iobuf);
	result = uiomove(ioptr, SFS_BLOCKSIZE, uio);
	if (result) {
		buffer_release(iobuf);
		return result;
	}

	if (uio->uio_rw == UIO_WRITE) {
		new_checksum = checksum(ioptr);
		sfs_jphys_write_wrapper(sfs, NULL, 
			jentry_block_write(diskblock, new_checksum, false));
		buffer_mark_valid(iobuf);
		buffer_mark_dirty(iobuf);	// Journalled
	}

	buffer_release(iobuf);
	return 0;
}
Exemplo n.º 7
0
/*
 * Do I/O to a block of a file that doesn't cover the whole block.  We
 * need to read in the original block first, even if we're writing, so
 * we don't clobber the portion of the block we're not intending to
 * write over.
 *
 * SKIPSTART is the number of bytes to skip past at the beginning of
 * the sector; LEN is the number of bytes to actually read or write.
 * UIO is the area to do the I/O into.
 *
 * Requires up to 2 buffers.
 */
static
int
sfs_partialio(struct sfs_vnode *sv, struct uio *uio,
	      uint32_t skipstart, uint32_t len)
{
	struct sfs_fs *sfs = sv->sv_absvn.vn_fs->fs_data;
	struct buf *iobuffer;
	unsigned char *ioptr;
	daddr_t diskblock;
	uint32_t fileblock;
	int result;
	unsigned new_checksum = 0;

	/* Allocate missing blocks if and only if we're writing */
	bool doalloc = (uio->uio_rw==UIO_WRITE);

	KASSERT(lock_do_i_hold(sv->sv_lock));
	KASSERT(skipstart + len <= SFS_BLOCKSIZE);

	/* Compute the block offset of this block in the file */
	fileblock = uio->uio_offset / SFS_BLOCKSIZE;

	/* Get the disk block number */
	result = sfs_bmap(sv, fileblock, doalloc, &diskblock);
	if (result) {
		return result;
	}

	if (diskblock == 0) {
		/*
		 * There was no block mapped at this point in the file.
		 *
		 * We must be reading, or sfs_bmap would have
		 * allocated a block for us.
		 */
		KASSERT(uio->uio_rw == UIO_READ);
		return uiomovezeros(len, uio);
	}
	else {
		/*
		 * Read the block.
		 */
		result = buffer_read(&sfs->sfs_absfs, diskblock, SFS_BLOCKSIZE,
				     &iobuffer);
		if (result) {
			return result;
		}
	}

	/*
	 * Now perform the requested operation into/out of the buffer.
	 */
	ioptr = buffer_map(iobuffer);
	result = uiomove(ioptr+skipstart, len, uio);
	if (result) {
		buffer_release(iobuffer);
		return result;
	}

	/*
	 * If it was a write, mark the modified block dirty and journal
	 */
	if (uio->uio_rw == UIO_WRITE) {
		// Compute checksum and journal
		new_checksum = checksum(ioptr);
		sfs_jphys_write_wrapper(sfs, NULL, 
			jentry_block_write(diskblock, new_checksum, false));

		buffer_mark_dirty(iobuffer);	// Journalled
	}

	buffer_release(iobuffer);
	return 0;
}