Esempio n. 1
0
void
sva_ghost_fault (uintptr_t vaddr) {
  uint64_t tsc_tmp;
  if(tsc_read_enable_sva)
     tsc_tmp = sva_read_tsc();

  kernel_to_usersva_pcid();
  /* Old interrupt flags */
  uintptr_t rflags;

  /*
   * Disable interrupts.
   */
  rflags = sva_enter_critical();

  /* Physical address of allocated secure memory pointer */
  uintptr_t sp;

  /* The address of the PML4e page table */
  pml4e_t pml4e;

  /*
   * Get the current interrupt context; the arguments will be in it.
   */
  struct CPUState * cpup = getCPUState();
  struct SVAThread * threadp = cpup->currentThread;

  /*
   * Determine if this is the first secure memory allocation.
   */
  unsigned char firstSecAlloc = (threadp->secmemSize == 0);

  /*
   * Get a page of memory from the operating system.  Note that the OS provides
   * the physical address of the allocated memory.
   */
  if ((sp = provideSVAMemory (X86_PAGE_SIZE)) != 0) {
    /* Physical address of the allocated page */
    uintptr_t paddr = (uintptr_t) sp;

    /*
     * Map the memory into a part of the address space reserved for secure
     * memory.
     */
    pml4e = mapSecurePage (vaddr, paddr);

    /*
     * If this is the first piece of secure memory that we've allocated,
     * record the address of the top-level page table that maps in the secure
     * memory region.  The context switching intrinsics will want to know
     * where this entry is so that it can quickly enable and disable it on
     * context switches.
     */
    if (firstSecAlloc) {
      threadp->secmemPML4e = pml4e;
    }
  } else {
    panic ("SVA: Kernel secure memory allocation failed!\n");
  }

  /*
   * Zero out the ghost memory contents.
   */
  memset (vaddr, 0, X86_PAGE_SIZE);

  /* Re-enable interrupts if necessary */
  sva_exit_critical (rflags);
  usersva_to_kernel_pcid();
  record_tsc(sva_ghost_fault_api, ((uint64_t) sva_read_tsc() - tsc_tmp));
  return;
}
Esempio n. 2
0
/*
 * Function: ghostMalloc()
 *
 * Description:
 *  Allocate ghost memory.
 */
unsigned char *
ghostMalloc (intptr_t size) {
  /* Physical address of allocated secure memory pointer */
  uintptr_t sp;

  /* Virtual address assigned to secure memory by SVA */
  unsigned char * vaddrStart = 0;

  /* The address of the PML4e page table */
  pml4e_t pml4e = 0;

  /*
   * Get the current interrupt context; the arguments will be in it.
   */
  struct CPUState * cpup = getCPUState();
  struct SVAThread * threadp = cpup->currentThread;

  /*
   * Determine if this is the first secure memory allocation.
   */
  unsigned char firstSecAlloc = (threadp->secmemSize == 0);

  /*
   * Determine where this ghost memory will be allocated and update the size
   * of the ghost memory.
   */
  unsigned char * vaddr = vaddrStart = getNextSecureAddress (threadp, size);

  /*
   * Get a page of memory from the operating system.  Note that the OS provides
   * the physical address of the allocated memory.
   */
  for (intptr_t remaining = size; remaining > 0; remaining -= X86_PAGE_SIZE) {
    if ((sp = provideSVAMemory (X86_PAGE_SIZE)) != 0) {
      /* Physical address of the allocated page */
      uintptr_t paddr = sp;

      /*
       * Map the memory into a part of the address space reserved for secure
       * memory.
       */
      pml4e = mapSecurePage (vaddr, paddr);

      /*
       * If this is the first piece of secure memory that we've allocated,
       * record the address of the top-level page table that maps in the secure
       * memory region.  The context switching intrinsics will want to know
       * where this entry is so that it can quickly enable and disable it on
       * context switches.
       */
      if (firstSecAlloc) {
        threadp->secmemPML4e = pml4e;
      }

      /*
       * Move to the next virtual address.
       */
      vaddr += X86_PAGE_SIZE;
    } else {
      panic ("SVA: Kernel secure memory allocation failed!\n");
    }
  }

  /* Return a pointer to the allocated ghost memory */
  return vaddrStart;
}
Esempio n. 3
0
/*
 * Function: sva_ghost_fault()
 *
 * Description:
 *  Handle page faults of ghost memory pages.
 *
 * Inputs:
 *  vaddr - The virtual address of the faulting ghost memory page.
 *  code  - The page fault code.
 *
 */
void
sva_ghost_fault (uintptr_t vaddr, unsigned long code) {
  /* Old interrupt flags */
  uintptr_t rflags;

  /*
   * Disable interrupts.
   */
  rflags = sva_enter_critical();

  /* Physical address of allocated secure memory pointer */
  uintptr_t sp;

  /* The address of the PML4e page table */
  pml4e_t pml4e;

  /*
   * Get the current interrupt context; the arguments will be in it.
   */
  struct CPUState * cpup = getCPUState();
  struct SVAThread * threadp = cpup->currentThread;

  /* copy-on-write page fault */
  if((code & PGEX_P) && (code & PGEX_W)){
     pml4e_t * pml4e_ptr = get_pml4eVaddr (get_pagetable(), vaddr);
     if(!isPresent (pml4e_ptr)) 
        panic("sva_ghost_fault: cow pgfault pml4e %p does not exist\n", pml4e);
     pdpte_t * pdpte = get_pdpteVaddr (pml4e_ptr, vaddr);
     if(!isPresent (pdpte)) 
        panic("sva_ghost_fault: cow pgfault pdpte %p does not exist\n", pdpte);
     pde_t * pde = get_pdeVaddr (pdpte, vaddr);
     if(!isPresent (pde)) 
        panic("sva_ghost_fault: cow pgfault pde %p does not exist\n", pde);
     pte_t * pte = get_pteVaddr (pde, vaddr);
     uintptr_t paddr = *pte & PG_FRAME;
     page_desc_t * pgDesc = getPageDescPtr (paddr);

     if(pgDesc->type != PG_GHOST)
	panic("SVA: sva_ghost_fault: vaddr = 0x%lx paddr = 0x%lx is not a ghost memory page!\n", vaddr, paddr); 
     /* If only one process maps this page, directly grant this process write permission */

     if(pgDesc->count == 1)
     {
        * pte = (* pte) | PTE_CANWRITE;
     }
     /* Otherwise copy-on-write */
     else
     {
        uintptr_t vaddr_old = (uintptr_t) getVirtualSVADMAP(paddr);
        uintptr_t paddr_new = alloc_frame();
        page_desc_t * pgDesc_new = getPageDescPtr (paddr_new);
        if (pgRefCount (pgDesc_new) > 1) {
                panic ("SVA: Ghost page still in use somewhere else!\n");
        }
        if (isPTP(pgDesc_new) || isCodePG (pgDesc_new)) {
                panic ("SVA: Ghost page has wrong type!\n");
        }


     	memcpy(getVirtualSVADMAP(paddr_new), (void *) vaddr_old, X86_PAGE_SIZE);   
        *pte = (paddr_new & addrmask) | PTE_CANWRITE | PTE_CANUSER | PTE_PRESENT;
        invlpg(vaddr);	
	
	getPageDescPtr (paddr_new)->type = PG_GHOST;
        getPageDescPtr (paddr_new)->count = 1;
        pgDesc->count --;
     }
     
     return; 
   }

  /*
   * Determine if this is the first secure memory allocation.
   */
  unsigned char firstSecAlloc = (threadp->secmemSize == 0);

  /*
   * Get a page of memory from the operating system.  Note that the OS provides
   * the physical address of the allocated memory.
   */
  if ((sp = alloc_frame()) != 0) {
    /* Physical address of the allocated page */
    uintptr_t paddr = (uintptr_t) sp;

    /*
     * Map the memory into a part of the address space reserved for secure
     * memory.
     */
    pml4e = mapSecurePage ((uintptr_t)vaddr, paddr);

    /*
     * If this is the first piece of secure memory that we've allocated,
     * record the address of the top-level page table that maps in the secure
     * memory region.  The context switching intrinsics will want to know
     * where this entry is so that it can quickly enable and disable it on
     * context switches.
     */
    if (firstSecAlloc) {
      threadp->secmemPML4e = pml4e;
    }
  } else {
    panic ("SVA: Kernel secure memory allocation failed!\n");
  }

  /*
   * Zero out the ghost memory contents.
   */
  memset ((void *)vaddr, 0, X86_PAGE_SIZE);

  /* Re-enable interrupts if necessary */
  sva_exit_critical (rflags);
  return;
}