static Res VMChunkInit(Chunk chunk, BootBlock boot) { VMChunk vmChunk; Addr overheadLimit; void *p; Res res; BT saMapped, saPages; /* chunk is supposed to be uninitialized, so don't check it. */ vmChunk = Chunk2VMChunk(chunk); AVERT(BootBlock, boot); res = BootAlloc(&p, boot, BTSize(chunk->pages), MPS_PF_ALIGN); if (res != ResOK) goto failSaMapped; saMapped = p; res = BootAlloc(&p, boot, BTSize(chunk->pageTablePages), MPS_PF_ALIGN); if (res != ResOK) goto failSaPages; saPages = p; overheadLimit = AddrAdd(chunk->base, (Size)BootAllocated(boot)); /* Put the page table as late as possible, as in VM systems we don't want */ /* to map it. */ res = BootAlloc(&p, boot, chunk->pageTablePages << chunk->pageShift, chunk->pageSize); if (res != ResOK) goto failAllocPageTable; chunk->pageTable = p; /* Map memory for the bit tables. */ if (vmChunk->overheadMappedLimit < overheadLimit) { overheadLimit = AddrAlignUp(overheadLimit, ChunkPageSize(chunk)); res = vmArenaMap(VMChunkVMArena(vmChunk), vmChunk->vm, vmChunk->overheadMappedLimit, overheadLimit); if (res != ResOK) goto failTableMap; vmChunk->overheadMappedLimit = overheadLimit; } SparseArrayInit(&vmChunk->pages, chunk->pageTable, sizeof(PageUnion), chunk->pages, saMapped, saPages, vmChunk->vm); return ResOK; /* .no-clean: No clean-ups needed for boot, as we will discard the chunk. */ failTableMap: failSaPages: failAllocPageTable: failSaMapped: return res; }
/* VMChunkCreate -- create a chunk * * chunkReturn, return parameter for the created chunk. * vmArena, the parent VMArena. * size, approximate amount of virtual address that the chunk should reserve. */ static Res VMChunkCreate(Chunk *chunkReturn, VMArena vmArena, Size size) { Res res; Addr base, limit, chunkStructLimit; Align pageSize; VM vm; BootBlockStruct bootStruct; BootBlock boot = &bootStruct; VMChunk vmChunk; void *p; AVER(chunkReturn != NULL); AVERT(VMArena, vmArena); AVER(size > 0); res = VMCreate(&vm, size, vmArena->vmParams); if (res != ResOK) goto failVMCreate; pageSize = VMAlign(vm); /* The VM will have aligned the userSize; pick up the actual size. */ base = VMBase(vm); limit = VMLimit(vm); res = BootBlockInit(boot, (void *)base, (void *)limit); if (res != ResOK) goto failBootInit; /* Allocate and map the descriptor. */ /* See <design/arena/>.@@@@ */ res = BootAlloc(&p, boot, sizeof(VMChunkStruct), MPS_PF_ALIGN); if (res != ResOK) goto failChunkAlloc; vmChunk = p; /* Calculate the limit of the page where the chunkStruct resides. */ chunkStructLimit = AddrAlignUp((Addr)(vmChunk + 1), pageSize); res = vmArenaMap(vmArena, vm, base, chunkStructLimit); if (res != ResOK) goto failChunkMap; vmChunk->overheadMappedLimit = chunkStructLimit; vmChunk->vm = vm; res = ChunkInit(VMChunk2Chunk(vmChunk), VMArena2Arena(vmArena), base, limit, pageSize, boot); if (res != ResOK) goto failChunkInit; BootBlockFinish(boot); vmChunk->sig = VMChunkSig; AVERT(VMChunk, vmChunk); *chunkReturn = VMChunk2Chunk(vmChunk); return ResOK; failChunkInit: /* No need to unmap, as we're destroying the VM. */ failChunkMap: failChunkAlloc: failBootInit: VMDestroy(vm); failVMCreate: return res; }
/* VMChunkCreate -- create a chunk * * chunkReturn, return parameter for the created chunk. * vmArena, the parent VMArena. * size, approximate amount of virtual address that the chunk should reserve. */ static Res VMChunkCreate(Chunk *chunkReturn, VMArena vmArena, Size size) { Arena arena; Res res; Addr base, limit, chunkStructLimit; VMStruct vmStruct; VM vm = &vmStruct; BootBlockStruct bootStruct; BootBlock boot = &bootStruct; VMChunk vmChunk; void *p; AVER(chunkReturn != NULL); AVERT(VMArena, vmArena); arena = VMArena2Arena(vmArena); AVER(size > 0); res = VMInit(vm, size, ArenaGrainSize(arena), vmArena->vmParams); if (res != ResOK) goto failVMInit; base = VMBase(vm); limit = VMLimit(vm); res = BootBlockInit(boot, (void *)base, (void *)limit); if (res != ResOK) goto failBootInit; /* Allocate and map the descriptor. */ /* See <design/arena/>.@@@@ */ res = BootAlloc(&p, boot, sizeof(VMChunkStruct), MPS_PF_ALIGN); if (res != ResOK) goto failChunkAlloc; vmChunk = p; /* Calculate the limit of the grain where the chunkStruct resides. */ chunkStructLimit = AddrAlignUp((Addr)(vmChunk + 1), ArenaGrainSize(arena)); res = vmArenaMap(vmArena, vm, base, chunkStructLimit); if (res != ResOK) goto failChunkMap; vmChunk->overheadMappedLimit = chunkStructLimit; /* Copy VM descriptor into its place in the chunk. */ VMCopy(VMChunkVM(vmChunk), vm); res = ChunkInit(VMChunk2Chunk(vmChunk), arena, base, limit, VMReserved(VMChunkVM(vmChunk)), boot); if (res != ResOK) goto failChunkInit; BootBlockFinish(boot); vmChunk->sig = VMChunkSig; AVERT(VMChunk, vmChunk); *chunkReturn = VMChunk2Chunk(vmChunk); return ResOK; failChunkInit: VMUnmap(vm, VMBase(vm), chunkStructLimit); failChunkMap: failChunkAlloc: failBootInit: VMFinish(vm); failVMInit: return res; }