/* * Function: freeSecureMemory() * * Description: * Free a single page of secure memory. * * Inputs: * p - The first virtual address of the secure memory to free. * size - The amount of secure memory to allocate measured in bytes. * */ void freeSecureMemory (void) { /* * Get the current interrupt context; the arguments will be in it. */ sva_icontext_t * icp = getCPUState()->newCurrentIC; /* * Get the pointer address and size out of the interrupt context. */ unsigned char * p = (unsigned char *)(icp->rdi); uintptr_t size = icp->rsi; /* * Verify that the memory is within the secure memory portion of the * address space. */ uintptr_t pint = (uintptr_t) p; if ((SECMEMSTART <= pint) && (pint < SECMEMEND) && (SECMEMSTART <= (pint + size)) && ((pint + size) < SECMEMEND)) { /* * Zero out the memory. */ memset (p, 0, size); /* * Get the physical address before unmapping the page. We do this because * unmapping the page may remove page table pages that are no longer * needed for mapping secure pages. */ uintptr_t paddr = getPhysicalAddr (p); /* * Unmap the memory from the secure memory virtual address space. */ unmapSecurePage (get_pagetable(), p); /* * Release the memory to the operating system. Note that we must first * get the physical address of the data page as that is what the OS is * expecting. */ releaseSVAMemory (paddr, size); } return; }
/* * Function: ghostFree() * * Description: * Free the physical frames backing ghost memory at the specified virtual * address. This function frees entire frames and returns the physical memory * to the operating system kernel. * * Note that this function may be called upon to unmap ghost memory from a * thread *other* than the one currently running on the CPU. * * Inputs: * threadp - A pointer to the SVA Thread for which we should release the frame * of secure memory. * p - A pointer to the virtual address of the ghost memory to free. * size - The amount of ghost memory in bytes to free. * */ void ghostFree (struct SVAThread * threadp, unsigned char * p, intptr_t size) { /* Per-CPU data structure maintained by SVA */ struct CPUState * cpup; /* Pointer to thread currently executing on the CPU */ struct SVAThread * currentThread; /* * If the amount of memory to free is zero, do nothing. */ if (size == 0) { return; } /* * Get a pointer to the thread currently running on the CPU. */ cpup = getCPUState(); currentThread = cpup->currentThread; /* * Get the PML4E entry for the Ghost Memory for the thread. */ pml4e_t * secmemPML4Ep = &(threadp->secmemPML4e); /* * Verify that the memory is within the secure memory portion of the * address space. */ uintptr_t pint = (uintptr_t) p; if ((SECMEMSTART <= pint) && (pint < SECMEMEND) && (SECMEMSTART <= (pint + size)) && ((pint + size) < SECMEMEND)) { /* * Loop through each page of the ghost memory until all of the frames * have been returned to the operating system kernel. */ for (unsigned char * ptr = p; ptr < (p + size); ptr += X86_PAGE_SIZE) { /* * Get the physical address before unmapping the page. We do this * because unmapping the page may remove page table pages that are no * longer needed for mapping secure pages. */ uintptr_t paddr; if (getPhysicalAddrFromPML4E (ptr, secmemPML4Ep, &paddr)) { /* * Unmap the memory from the secure memory virtual address space. */ unmapSecurePage (threadp, ptr); /* * Release the memory to the operating system. Note that we must first * get the physical address of the data page as that is what the OS is * expecting. * * TODO: * This code works around a limitation in the releaseSVAMemory() * implementation in which it only releases one page at a time to the * OS. */ if(getPageDescPtr(paddr)->count == 0) { /* * Zero out the contents of the ghost memory if it has been mapped * in the current address space. */ if(threadp == currentThread){ unsigned char * dmapAddr = getVirtualSVADMAP (paddr); memset (dmapAddr, 0, X86_PAGE_SIZE); } free_frame(paddr); } } } } return; }