Example #1
0
int verify_variable_length(void* start)
{
	if(start == NULL || start == 0 || start >= PHYS_BASE) {
		return false;
	}
	char* current_character;
	void* last_addr = pg_round_down(start);
	
	// Is first page OK?
	if(pagedir_get_page(thread_current()->pagedir, last_addr) == NULL){
		return false;
	}

	for(current_character = start; ; current_character++){

		// We have changed page, lets validate it. :-)
		if(last_addr != pg_round_down(current_character)){
			last_addr = pg_round_down(current_character);
			if(last_addr == NULL || last_addr == 0 || last_addr >= PHYS_BASE){
				return false;
			}
			if(pagedir_get_page(thread_current()->pagedir, last_addr) == NULL){
				return false;
			}
		}
		// If we have come this far, we know the current page is OK. 

		if(*current_character == '\0'){
			return true;
 		}

	}
	return false;

}
Example #2
0
/*
 * Maps the given user virtual address to the hash table's supplementary_page_table_entry.
 * i.e. Allocate the new supplementary_page_table_entry object and map it with
 * rounded down value of given virtual address
 */
struct supplementary_page_table_entry* allocate_supplementary_PTE (
    void * vir_addr,
    bool write_only)
{
  struct thread *current = thread_current ();
  struct supplementary_page_table_entry *page = malloc (sizeof ( *page ));
  if (page == NULL)
  {
    return page;
  }

  /* Initialize supplementary_page_table_entry with default values and given virtual address*/
  page->sup_thread = current;
  page->supplementary_frame_in_memory = NULL;
  page->file_offset = 0;
  page->vaddr = pg_round_down (vir_addr);
  page->is_readonly = !write_only;
  page->swap_write = write_only;
  page->area_swap = (block_sector_t) -1;
  page->rw_bytes = 0;
  page->sup_file = NULL;

  // Insert this supplementary page table entry into supplementary page table
  if (hash_insert (current->supplementary_page_table, &page->elem) != NULL)
  {
    // If failed - release the object and return NULL
    free (page);
    page = NULL;
  }
  return page;
}
Example #3
0
bool 
grow_stack (void *uaddr)
{
  void *upage = pg_round_down (uaddr);
  if((size_t)(PHYS_BASE - upage) > (1 << 23)) return false;

  struct spage_table_entry *spte = malloc (sizeof (struct spage_table_entry));
  if (!spte) return false;
  spte->upage = upage;
  spte->in_memory = true;
  spte->writable = true;
  spte->spage_type = SWAP;
  spte->inevictable = true;

  uint8_t *f = frame_alloc (PAL_USER, spte);
  if (!f)
    {
      free (spte);
      return false;
    }

  if (!install_page (spte->upage, f, spte->writable))
    {
      free (spte);
      frame_free (f);
      return false;
    }

  if (intr_context ()) spte->inevictable = false;

  return hash_insert (&thread_current ()->spage_table, &spte->elem) == NULL;
}
Example #4
0
/* Validates a user-provided pointer. Checks that it's in the required
 * range, and that it correpsonds to a page directory entry
 */
bool valid_user_pointer(const void *ptr) {
    uint32_t *pd, *pde;
    struct list_elem *e;
    struct vm_area_struct *iter;
    struct thread *t = thread_current();
    void *esp = t->esp;

    /* Check if page in supplemental page table */
    if (spt_present(t, pg_round_down(ptr))) {
        return true;
    }

    /* Special case for esp, must be in pagedir */
    pd = active_pd();
    pde = pd + pd_no(esp);

    /* If we have messed up esp */
    if (*pde == 0) {
        return false;
    }


    /* If the pointer is above esp (but in user_vaddr), it may correspond to
     * a part of the stack that would be later loaded lazily on a pagefault.
     * So this should be considered a good pointer.
     */
    if (is_user_vaddr(ptr) && ptr >= esp) {
        return true;
    }

    /* If we're here, this isn't a valid address */
    return false;
}
Example #5
0
void stack_growth(void *vaddr){
  uint32_t *paddr,*lru_page;
  
  if ((paddr = palloc_get_page(PAL_ZERO)) != NULL) {
		fte_create(paddr, false);
		install_page_ext (pg_round_down(vaddr), paddr, true);
		set_page_valid(pg_round_down(vaddr), paddr);
	}
  else
  {
    lru_page = lru_get_page();

    swap_out(lru_page);
		set_page_valid(pg_round_down(vaddr), lru_page);
  }

}
Example #6
0
struct spage_table_entry * 
spage_table_find (void *uaddr)
{
  struct spage_table_entry spte;
  spte.upage = pg_round_down (uaddr);

  struct hash_elem *e = hash_find (&thread_current()->spage_table, &spte.elem);
  if (!e) return NULL;
  return hash_entry (e, struct spage_table_entry, elem);
}
Example #7
0
/*
 * Converts a pointer to any address into a number from
 * 0 to USER_PAGES-1 (the amount of pages in the userpool)
 * This can be used to as an index to access the frames
 * within the frame table.
 */
static uint32_t
page_to_pagenum(void *page) {
    // pages are consecutive and nothing can be before the base
    ASSERT(page >= frametable.base_addr);

    // remove offset within frame
    page = pg_round_down(page);
    // address shift relative to base addr
    page -= (uintptr_t) frametable.base_addr;
    return pg_no(page);
}
Example #8
0
/* Reads 'size' bytes from file open as fd into buffer. Returns number of
   bytes actually read - 0 at end of file, or -1 if file could not be read.
   fd = 0 reads from the keyboard. */
static int
sys_read(int fd, void *buffer, unsigned size, struct intr_frame *f) 
{
  /* Cannot read from stdout. */
  if (fd == STDOUT_FILENO)
    sys_exit(ERROR);
  int bytes;
  void *buf_iter = pg_round_down(buffer);

  check_fd(fd);
  check_buffer(buffer, size);

  lock_acquire(&secure_file);

  for (; buf_iter <= buffer + size; buf_iter += PGSIZE) {
    struct spt_entry *entry = get_spt_entry(&thread_current()->supp_pt, buf_iter);
    if (entry == NULL && should_stack_grow(buf_iter, f->esp)) {
      grow_stack(buf_iter);
    } 
  }

  /* fd = 0 corresponds to reading from stdin. */
  if (fd == STDIN_FILENO) 
  {
    unsigned i;
    uint8_t keys[size];
    /* Make an array of keys pressed. */
    for (i = 0; i < size; i++) 
    {
      keys[i] = input_getc();
    }
    /* Put these keys pressed into the buffer. */
    memcpy(buffer, (const void *) keys, size);
    /* Must have successfully read all bytes we were told to. */
    bytes = size;
  } else {

    struct file *f = get_file(fd);
    if (!f) 
    {
      lock_release(&secure_file);
      return ERROR;
    }
    bytes = file_read(f, buffer, size);
  }

  lock_release(&secure_file);
  return bytes;
}
Example #9
0
// Find the vm_entry object that got vaddr.
struct vm_entry *find_vme (void *vaddr)
{
	struct vm_entry vm;
	struct hash_elem *h;
	struct thread *cur = thread_current();
	
	vm.vaddr = pg_round_down(vaddr);

	h = hash_find(&cur->vm, &vm.elem);

	if (h == NULL)
	{
		return h;
	}

	return hash_entry(h, struct vm_entry, elem);
}
Example #10
0
/*! Read from file */
int read(uint32_t fd, void *buffer, unsigned size) {
    uint8_t* addr_e;
    struct supp_table* st;
    
    /* Check the validity of given pointer */
    if ((!checkva(buffer)) || (!checkva(buffer + size))){
        exit(-1);
    }
    
    for (addr_e = (uint8_t*) pg_round_down(buffer); 
         addr_e < (uint8_t*) buffer + size; addr_e += PGSIZE){
        st = find_supp_table(addr_e);
        if (st && !st->writable)
            exit(-1);
    }
    
    int read_size = 0;
    if (fd == STDIN_FILENO) {
        /* If std-in, then read using input_getc() */
        unsigned i;
        for (i = 0; i < size; i++){
            *((uint8_t*) buffer) = input_getc();
            ++ read_size;
            ++ buffer;
        }
    } else {
        /* Otherwise, first find the file of this fd. */
        struct f_info* f = findfile(fd);
        
        /* We should read a dir like a file. */
        if (f->isdir)
            exit(-1);
        
        struct file* fin = f->f;
        off_t pos = f->pos;
        
        /* Read from the file at f->pos */
        //lock_acquire(&filesys_lock);
        read_size = (int) file_read_at(fin, buffer, (off_t) size, pos);
        f->pos += (off_t) read_size;
        //lock_release(&filesys_lock);
        
    }
    return read_size;

}
Example #11
0
/**
 * Get supplementary_page_table_entry for given virtual address ->
 * First finds it into the supplementary_page_table, if found returns
 * supplementary_page_table_entry object.
 * Else if its a new page for stack auto growth then try to allocate the new page,
 * Else if its not a stack-page just return NULL.
 */
static struct supplementary_page_table_entry *get_page_table_entry (const void *vaddr)
{
  if (vaddr >= PHYS_BASE)
  {
    return NULL;
  }
  struct thread *current = thread_current ();
  struct supplementary_page_table_entry page1;
  struct hash_elem *elem;
  page1.vaddr = (void *) pg_round_down (vaddr);
  elem = hash_find (current->supplementary_page_table, &page1.elem);
  /* If page is present return the hash entry. */
  if (elem != NULL)
  {
    return hash_entry(elem, struct supplementary_page_table_entry, elem);
  } else
  {
    // Check the virtual address of stack page within 1MB - maximum stack limit
    if ( ( vaddr >= ( PHYS_BASE - STACK_SIZE_LIMIT ) )
Example #12
0
/* Given a virtual address (page) find a frame to put the page in and return 
   the physical address of the frame */
void*
frame_obtain (enum palloc_flags flags, void* uaddr)
{
  struct frame_table_entry* fte;
  /* Try and obtain frame in user memory */
  void *kaddr = palloc_get_page (flags);

  
  /* Successfully obtained frame */
  if (kaddr != NULL)
    {
      /* Create new frame table entry mapping the given page to the 
         allocated frame */
      fte = (struct frame_table_entry *) malloc 
                (sizeof (struct frame_table_entry));

      fte->owner = thread_current ();
      fte->kaddr = kaddr;
      fte->uaddr = pg_round_down (uaddr);

      lock_acquire (&frame_table_lock);
      list_push_front (&frame_table, &fte->elem);
      lock_release (&frame_table_lock);

      return fte->kaddr;
    }

  /* Failed to obtain frame */
  else
    {
      /* Perform eviction to release a frame and try allocation again */
      if (PAGE_EVICTION)
      {
        return frame_evict (uaddr);
      }
      else
      {
        PANIC ("Failed to allocate frame - eviction disabled.");
      }
    }

}
Example #13
0
/* Kontrollera alla adresser från och med start till och inte med
 * (start+length). */
int verify_fix_length(void* start, int length)
{
	if(start == NULL  || start == 0 || start >= PHYS_BASE){
		return false;
	}
	void* page_ptr = pg_round_down(start);
	
 	while(page_ptr < start + length){
		if(page_ptr == NULL  || page_ptr == 0 || page_ptr >= PHYS_BASE ){
			return false;
		}

		void* success = pagedir_get_page(thread_current()->pagedir, page_ptr);
		if(success == NULL){
			return false;
		}
		page_ptr += PGSIZE;		
	}
	return true;
}
Example #14
0
/* Creates a copy of user string US in kernel memory
   and returns it as a page that must be freed with
   palloc_free_page().
   Truncates the string at PGSIZE bytes in size.
   Call thread_exit() if any of the user accesses are invalid. */
static char *
copy_in_string (const char *us) 
{
  char *ks;
  char *upage;
  size_t length;
 
  ks = palloc_get_page (0);
  if (ks == NULL) 
    thread_exit ();

  length = 0;
  for (;;) 
    {
      upage = pg_round_down (us);
      if (!page_lock (upage, false))
        goto lock_error;

      for (; us < upage + PGSIZE; us++) 
        {
          ks[length++] = *us;
          if (*us == '\0') 
            {
              page_unlock (upage);
              return ks; 
            }
          else if (length >= PGSIZE) 
            goto too_long_error;
        }

      page_unlock (upage);
    }

 too_long_error:
  page_unlock (upage);
 lock_error:
  palloc_free_page (ks);
  thread_exit ();
}
Example #15
0
void write (struct intr_frame *f) {

	int fd = *value_stack_int(f->esp,4);
	const void * buffer = *(void **)value_stack(f->esp,8);
	unsigned size = *value_stack_int(f->esp,12);

	if (fd == 1) {
		//break up the string in multilpe outputs if it is bigger than 256
		int split = 256;
		int i = size / split;
		for (;i>0;i--) { 
			putbuf(buffer,split);
			buffer += split;
		}
		putbuf(buffer,size % split);
	}	
	else {
		unsigned fl_length = 0;

		if (fd == 0 || fd < 0 ) {
			f->eax = 0 ;
			return ;
		}

		struct filed * filed = find_file(fd);
		if (filed == NULL) { 
			f->eax = 0 ;
			return ;
		}	

		struct file * writeto = find_file(fd)->file;

		//check if it is a directory
		if ( file_direct(writeto) ) {
			f->eax = -1;
			return;
		}
		
		fl_length = file_length (writeto);
		//check if the actual file length is smaller than size
		//if(fl_length < size) size = fl_length;

		void * npage = pg_round_down (buffer);
		unsigned readsize = (unsigned) (npage + PGSIZE - buffer);
			
		bool read = true;
		unsigned bytes_read_total=0,bytes_read=0;
		
		//the new pagewise writing
		while(read){
			struct page * p = page_lookup(buffer,thread_current());
			//if the page is not her, we have to swap it in
			if (pagedir_get_page(thread_current()->pagedir,p->vaddr) == NULL) {
				page_swap_out(p->vaddr);
			}

			frame_lockdown(p->paddr);

			//everything fits in with one read
			if(size <= readsize){
				bytes_read = file_write (writeto, buffer, size);
				read = false;
			} else {
			//now we have tos plit it up
				bytes_read= file_write (writeto, buffer, readsize);
				//couldn't read all the bytes
				if(bytes_read != readsize) read = false;
				size -= bytes_read;
				
				if(size == 0) read = false;
				else {
					buffer += bytes_read;
					if (size >= PGSIZE) readsize = PGSIZE;
					else readsize = size;
				}
			}	
			//unlock the frame again
			frame_unlock(p->paddr);
			bytes_read_total+=bytes_read;
		}
		size = bytes_read_total;	
	}

	//set eax to return value
	f->eax = size;
}
Example #16
0
void*
frame_evict (void* uaddr)
{

  /* 1. Choose a frame to evict, using your page replacement algorithm.
        The "accessed" and "dirty" bits in the page table, described below, 
        will come in handy. */
  struct frame_table_entry *fte = NULL;
  switch (PAGE_EVICTION_ALGORITHM)
  {
    /* First in first out */
    case PAGE_EVICTION_FIFO:
      fte = frame_evict_choose_fifo ();
      break;

    /* Second chance */
    case PAGE_EVICTION_SECONDCHANCE:
      fte = frame_evict_choose_secondchance ();
      break;

    default:
      PANIC ("Invalid eviction algorithm choice.");
  }
  ASSERT (fte != NULL);


  /* 2. Remove references to the frame from any page table that refers to it.
        Unless you have implemented sharing, only a single page should refer to
        a frame at any given time. */
  pagedir_clear_page (fte->owner->pagedir, pg_round_down (fte->uaddr));


  /* 3. If necessary, write the page to the file system or to swap.
        The evicted frame may then be used to store a different page. */
  struct page *p_evict = 
      page_lookup (fte->owner->pages, pg_round_down (fte->uaddr));
  if (p_evict == NULL)
        PANIC ("Failed to get supp page for existing page.");

  /* Page to be evicted is in swap */
  if (p_evict->page_location_option == FILESYS)
    {
      if (p_evict->writable)
        {
          file_write_at (p_evict->file, fte->kaddr, p_evict->page_read_bytes,
              p_evict->ofs);
        }
    }
  else if (p_evict->page_location_option == ALLZERO)
    {
      // All zero, so can just be overwritten
    }
  else
    {
      // From stack
      int index = swap_to_disk (pg_round_down (fte->uaddr));
      
      /* Creates a supp page and insert it into pages. */
      struct page *p = page_create ();

      if (p == NULL)
        PANIC ("Failed to get supp page for swap slot.");

      p->addr = fte->uaddr;
      p->page_location_option = SWAPSLOT;
      p->swap_index = index;
      page_insert (fte->owner->pages, &p->hash_elem);
    }

  /* Replace virtual address with new virtual address */
  fte->owner = thread_current ();
  fte->uaddr = uaddr;

  /* Reinsert the frame table entry into the frame table */
  lock_acquire (&frame_table_lock);
  list_remove (&fte->elem);
  list_push_front (&frame_table, &fte->elem);
  lock_release (&frame_table_lock);

  return fte->kaddr;
}
Example #17
0
void read (struct intr_frame *f) {

	int fd = *value_stack_int(f->esp,4);
	void * buffer = *(void **)value_stack(f->esp,8);
	unsigned size = *value_stack_int(f->esp,12);
	int ret_val = 1;

	if (fd == 0) {
		//read from stdin
		ret_val = input_getc();	
	}	
	else {
		if (fd == 1 || fd < 0) {
			f->eax = 0;
			return ;
		}
		
		struct filed * filed = find_file(fd);
  	  	
		if (filed == NULL) ret_val = 0;
		else { 
			struct file * readfrom = find_file(fd)->file;

			void * npage = pg_round_down (buffer);
			unsigned readsize = (unsigned) (npage + PGSIZE - buffer);

			bool read = true;
			unsigned bytes_read_total=0,bytes_read=0;
			//the new pagewise reading
			while(read){
				struct page * p = page_lookup(buffer,thread_current());
				//if the page is not her, we have to swap it in
				if (pagedir_get_page(thread_current()->pagedir,p->vaddr) == NULL) {
					page_swap_out(p->vaddr);
				}

				if(!p->writable) exit_mythread(-1);

				frame_lockdown(p->paddr);

				//everything fits in with one read
				if(size <= readsize){
					bytes_read = file_read(readfrom, buffer, size);
					read = false;
				} else {
					//now we have tos plit it up
					bytes_read= file_read(readfrom, buffer, readsize);

					//couldn't read all the bytes
					if(bytes_read != readsize) read = false;
					size -= bytes_read;
				
					if(size == 0) read = false;
					else {
						buffer += bytes_read;
						if (size >= PGSIZE) readsize = PGSIZE;
						else readsize = size;
					}
				}		
				//unlock the frame again
				frame_unlock(p->paddr);
				bytes_read_total+=bytes_read;
			}
			ret_val = bytes_read_total;
		 }
	}

	//set eax to return value
	f->eax = ret_val;
}