/* * Function: fill_in_frames() * * Description: * Allocate some number of frames and put them into the frame cache * queue. */ static inline void fill_in_frames(void) { int i, max_nframe, nframe; uintptr_t paddr; /* * Generate a suitable number not so big that triggers * release_frames() when calling frame_enqueue(). */ max_nframe = FRAME_CACHE_SIZE - 1 - frame_cache_used(); if (vg_random) { /* A random number between 1 and current capacity of frame cache queue */ nframe = random() % max_nframe + 1; } else { /* Minimum of a constant and current capacity of frame cache queue */ nframe = max_nframe < MAX_FRAMES_PER_OP ? max_nframe : MAX_FRAMES_PER_OP; } for (i = 0; i < nframe; ++i) { paddr = provideSVAMemory(X86_PAGE_SIZE); frame_enqueue(paddr); } }
/* * 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; }
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; }