bool fillSpaceBeforeStagingArea(int &tempChunks, void *stagingArea, void **chunkPool, bool addressesGrowDown) { // Make sure there are no available chunks before the staging area. tempChunks = 0; chunkPool[tempChunks++] = mapMemory(2 * Chunk); while (tempChunks < MaxTempChunks && chunkPool[tempChunks - 1] && (chunkPool[tempChunks - 1] < stagingArea) ^ addressesGrowDown) { chunkPool[tempChunks++] = mapMemory(2 * Chunk); if (!chunkPool[tempChunks - 1]) break; // We already have our staging area, so OOM here is okay. if ((chunkPool[tempChunks - 1] < chunkPool[tempChunks - 2]) ^ addressesGrowDown) break; // The address growth direction is inconsistent! } // OOM also means success in this case. if (!chunkPool[tempChunks - 1]) { --tempChunks; return true; } // Bail if we can't guarantee the right address space layout. if ((chunkPool[tempChunks - 1] < stagingArea) ^ addressesGrowDown || (tempChunks > 1 && (chunkPool[tempChunks - 1] < chunkPool[tempChunks - 2]) ^ addressesGrowDown)) { while (--tempChunks >= 0) unmapPages(chunkPool[tempChunks], 2 * Chunk); unmapPages(stagingArea, StagingSize); return false; } return true; }
bool addressesGrowUp() { void *p1 = mapMemory(2 * Chunk); void *p2 = mapMemory(2 * Chunk); unmapPages(p1, 2 * Chunk); unmapPages(p2, 2 * Chunk); return p1 < p2; }
int main(int argc, char *argv[]) { char* filename; s32 ret; mipsCpu* cpu; printf("greenLeaf 0.1\n"); printf("mips emulator by The Lemon Man and SquidMan\n"); if(argc < 2) { /* No arguments passed. */ filename = calloc(5, 1); sprintf(filename, "test/mmon"); }else{ filename = calloc(strlen(argv[1]) + 1, 1); sprintf(filename, argv[1]); } #ifdef DEBUG printf("Debug mode enabled\n"); #endif printf("Initializing the CPU core...\n"); cpu = initializeCPU(ENDIANNESS_LE, 0x80000000); printf("Mapping the ram...\n"); printf("Main memory %d\n", mapMemory(cpu, 0x80000000, 0x40000, FLAG_RAM)); printf("Reset vector %d\n", mapMemory(cpu, 0xBFC00000, 0x40000, FLAG_RAM)); printf("Additional mem %d\n", mapMemory(cpu, 0xA0000010, 0x2000, FLAG_RAM)); // ret = openRaw(cpu, filename, 0xBFC00000); ret = openElf32(cpu, filename); printf("Entry %#x\n", (u32)ret); printf("Uart %i\n", setupUart(cpu, 0xB40003f8)); setPC(cpu, ret); printf("Press enter to run a tick and print the registers...\n"); printf("Press enter to continue.\n"); for(;;) { #ifdef TICK_AT_A_TIME fgetc(stdin); #endif runProcessor(cpu, 1); /* Run a single cycle at a time */ //~ printRegisters(cpu); } printf("Execution finished... unmapping the ram\n"); unmapMemory(cpu); free(filename); return 1; }
uint32_t mapMemory(void *hostAddress) { while (mToVirtual.find(mUniqueAddress) != mToVirtual.end()) { mUniqueAddress++; } mapMemory(mUniqueAddress, hostAddress); return mUniqueAddress; }
staging_buffer::staging_buffer(renderer& renderer, size_t size) : _renderer(renderer) { auto device = _renderer.device(); _buffer = device.createBuffer(vk::BufferCreateInfo{ {}, size, vk::BufferUsageFlagBits::eTransferSrc, vk::SharingMode::eExclusive,0,nullptr }); auto mem_reqs = device.getBufferMemoryRequirements(_buffer); _memory = device.allocateMemory(vk::MemoryAllocateInfo{ mem_reqs.size(), _renderer.find_adequate_memory(mem_reqs, vk::MemoryPropertyFlagBits::eHostVisible) }); device.bindBufferMemory(_buffer, _memory, 0); _size = mem_reqs.size(); _mapped_memory = device.mapMemory(_memory, 0, mem_reqs.size(), {}); }
VkResult DeviceMemory::upload(const VkDeviceSize offset, const VkDeviceSize size, const VkMemoryMapFlags flags, const void* uploadData, const size_t uploadDataSize) { auto result = mapMemory(offset, size, flags); if (result != VK_SUCCESS) { return result; } memcpy(data, uploadData, uploadDataSize); unmapMemory(); return result; }
int setupUart(mipsCpu* cpu, u32 baseAddr) { if(mapMemory(cpu, baseAddr, 0xF, FLAG_RAM) < 0) { #ifdef DEBUG printf("Cannot allocate space for UART buffer\n"); #endif return -1; } _uartAddress = baseAddr; /* Set up parameters. */ cpu->writeByte(cpu, _uartAddress + UART_REG_LCR, 0xE0); return 1; }
bool testGCAllocatorDown(const size_t PageSize) { const size_t UnalignedSize = StagingSize + Alignment - PageSize; void *chunkPool[MaxTempChunks]; // Allocate a contiguous chunk that we can partition for testing. void *stagingArea = mapMemory(UnalignedSize); if (!stagingArea) return false; // Ensure that the staging area is aligned. unmapPages(stagingArea, UnalignedSize); if (offsetFromAligned(stagingArea)) { void *stagingEnd = (void *)(uintptr_t(stagingArea) + UnalignedSize); const size_t Offset = offsetFromAligned(stagingEnd); // Place the area at the highest aligned address. stagingArea = (void *)(uintptr_t(stagingEnd) - Offset - StagingSize); } mapMemoryAt(stagingArea, StagingSize); // Make sure there are no available chunks above the staging area. int tempChunks; if (!fillSpaceBeforeStagingArea(tempChunks, stagingArea, chunkPool, true)) return false; // Unmap the staging area so we can set it up for testing. unmapPages(stagingArea, StagingSize); // Check that the first chunk is used if it is aligned. CHECK(positionIsCorrect("---------xxxooxx", stagingArea, chunkPool, tempChunks)); // Check that the first chunk is used if it can be aligned. CHECK(positionIsCorrect("---------xxxoo-x", stagingArea, chunkPool, tempChunks)); // Check that an aligned chunk after a single unalignable chunk is used. CHECK(positionIsCorrect("-------xxxoox--x", stagingArea, chunkPool, tempChunks)); // Check that we fall back to the slow path after two unalignable chunks. CHECK(positionIsCorrect("-xxx--oox--xx--x", stagingArea, chunkPool, tempChunks)); // Check that we also fall back after an unalignable and an alignable chunk. CHECK(positionIsCorrect("-x--oo-x---xx--x", stagingArea, chunkPool, tempChunks)); // Check that the last ditch allocator works as expected. CHECK(positionIsCorrect("---xoo-xx--xx--x", stagingArea, chunkPool, tempChunks, UseLastDitchAllocator)); // Clean up. while (--tempChunks >= 0) unmapPages(chunkPool[tempChunks], 2 * Chunk); return true; }
VkResult DeviceMemory::upload(const VkDeviceSize offset, const VkMemoryMapFlags flags, const void* uploadData, const size_t uploadDataSize) { auto result = mapMemory(offset, uploadDataSize, flags); if (result != VK_SUCCESS) { return result; } memcpy(data, uploadData, uploadDataSize); if (!(memoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) { result = flushMappedMemoryRanges(offset, uploadDataSize); } unmapMemory(); return result; }
bool addressesGrowUp(bool* resultOut) { /* * Try to detect whether the OS allocates memory in increasing or decreasing * address order by making several allocations and comparing the addresses. */ static const unsigned ChunksToTest = 20; static const int ThresholdCount = 15; void* chunks[ChunksToTest]; for (unsigned i = 0; i < ChunksToTest; i++) { chunks[i] = mapMemory(2 * Chunk); CHECK(chunks[i]); } int upCount = 0; int downCount = 0; for (unsigned i = 0; i < ChunksToTest - 1; i++) { if (chunks[i] < chunks[i + 1]) upCount++; else downCount++; } for (unsigned i = 0; i < ChunksToTest; i++) unmapPages(chunks[i], 2 * Chunk); /* Check results were mostly consistent. */ CHECK(abs(upCount - downCount) >= ThresholdCount); *resultOut = upCount > downCount; return true; }