mirror of
				https://github.com/taigrr/gopher-os
				synced 2025-01-18 04:43:13 -08:00 
			
		
		
		
	Reserve and initialize the BitmapAllocator frame pools
This commit is contained in:
		
							parent
							
								
									1c3bfcd58d
								
							
						
					
					
						commit
						bc44151c93
					
				
							
								
								
									
										164
									
								
								kernel/mem/pmm/allocator/bitmap_allocator.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								kernel/mem/pmm/allocator/bitmap_allocator.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,164 @@ | |||||||
|  | package allocator | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"reflect" | ||||||
|  | 	"unsafe" | ||||||
|  | 
 | ||||||
|  | 	"github.com/achilleasa/gopher-os/kernel" | ||||||
|  | 	"github.com/achilleasa/gopher-os/kernel/hal/multiboot" | ||||||
|  | 	"github.com/achilleasa/gopher-os/kernel/mem" | ||||||
|  | 	"github.com/achilleasa/gopher-os/kernel/mem/pmm" | ||||||
|  | 	"github.com/achilleasa/gopher-os/kernel/mem/vmm" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	// FrameAllocator is a BitmapAllocator instance that serves as the | ||||||
|  | 	// primary allocator for reserving pages. | ||||||
|  | 	FrameAllocator BitmapAllocator | ||||||
|  | 
 | ||||||
|  | 	// The followning functions are used by tests to mock calls to the vmm package | ||||||
|  | 	// and are automatically inlined by the compiler. | ||||||
|  | 	reserveRegionFn = vmm.EarlyReserveRegion | ||||||
|  | 	mapFn           = vmm.Map | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type framePool struct { | ||||||
|  | 	// startFrame is the frame number for the first page in this pool. | ||||||
|  | 	// each free bitmap entry i corresponds to frame (startFrame + i). | ||||||
|  | 	startFrame pmm.Frame | ||||||
|  | 
 | ||||||
|  | 	// endFrame tracks the last frame in the pool. The total number of | ||||||
|  | 	// frames is given by: (endFrame - startFrame) - 1 | ||||||
|  | 	endFrame pmm.Frame | ||||||
|  | 
 | ||||||
|  | 	// freeCount tracks the available pages in this pool. The allocator | ||||||
|  | 	// can use this field to skip fully allocated pools without the need | ||||||
|  | 	// to scan the free bitmap. | ||||||
|  | 	freeCount uint32 | ||||||
|  | 
 | ||||||
|  | 	// freeBitmap tracks used/free pages in the pool. | ||||||
|  | 	freeBitmap    []uint64 | ||||||
|  | 	freeBitmapHdr reflect.SliceHeader | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // BitmapAllocator implements a physical frame allocator that tracks frame | ||||||
|  | // reservations across the available memory pools using bitmaps. | ||||||
|  | type BitmapAllocator struct { | ||||||
|  | 	// totalPages tracks the total number of pages across all pools. | ||||||
|  | 	totalPages uint32 | ||||||
|  | 
 | ||||||
|  | 	// reservedPages tracks the number of reserved pages across all pools. | ||||||
|  | 	reservedPages uint32 | ||||||
|  | 
 | ||||||
|  | 	pools    []framePool | ||||||
|  | 	poolsHdr reflect.SliceHeader | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // init allocates space for the allocator structures using the early bootmem | ||||||
|  | // allocator and flags any allocated pages as reserved. | ||||||
|  | func (alloc *BitmapAllocator) init() *kernel.Error { | ||||||
|  | 	return alloc.setupPoolBitmaps() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // setupPoolBitmaps uses the early allocator and vmm region reservation helper | ||||||
|  | // to initialize the list of available pools and their free bitmap slices. | ||||||
|  | func (alloc *BitmapAllocator) setupPoolBitmaps() *kernel.Error { | ||||||
|  | 	var ( | ||||||
|  | 		err                 *kernel.Error | ||||||
|  | 		sizeofPool          = unsafe.Sizeof(framePool{}) | ||||||
|  | 		pageSizeMinus1      = uint64(mem.PageSize - 1) | ||||||
|  | 		requiredBitmapBytes mem.Size | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	// Detect available memory regions and calculate their pool bitmap | ||||||
|  | 	// requirements. | ||||||
|  | 	multiboot.VisitMemRegions(func(region *multiboot.MemoryMapEntry) bool { | ||||||
|  | 		if region.Type != multiboot.MemAvailable { | ||||||
|  | 			return true | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		alloc.poolsHdr.Len++ | ||||||
|  | 		alloc.poolsHdr.Cap++ | ||||||
|  | 
 | ||||||
|  | 		// Reported addresses may not be page-aligned; round up to get | ||||||
|  | 		// the start frame and round down to get the end frame | ||||||
|  | 		regionStartFrame := pmm.Frame(((region.PhysAddress + pageSizeMinus1) & ^pageSizeMinus1) >> mem.PageShift) | ||||||
|  | 		regionEndFrame := pmm.Frame(((region.PhysAddress+region.Length) & ^pageSizeMinus1)>>mem.PageShift) - 1 | ||||||
|  | 		pageCount := uint32(regionEndFrame - regionStartFrame) | ||||||
|  | 		alloc.totalPages += pageCount | ||||||
|  | 
 | ||||||
|  | 		// To represent the free page bitmap we need pageCount bits. Since our | ||||||
|  | 		// slice uses uint64 for storing the bitmap we need to round up the | ||||||
|  | 		// required bits so they are a multiple of 64 bits | ||||||
|  | 		requiredBitmapBytes += mem.Size(((pageCount + 63) &^ 63) >> 3) | ||||||
|  | 		return true | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	// Reserve enough pages to hold the allocator state | ||||||
|  | 	requiredBytes := mem.Size(((uint64(uintptr(alloc.poolsHdr.Len)*sizeofPool) + uint64(requiredBitmapBytes)) + pageSizeMinus1) & ^pageSizeMinus1) | ||||||
|  | 	requiredPages := requiredBytes >> mem.PageShift | ||||||
|  | 	alloc.poolsHdr.Data, err = reserveRegionFn(requiredBytes) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for page, index := vmm.PageFromAddress(alloc.poolsHdr.Data), mem.Size(0); index < requiredPages; page, index = page+1, index+1 { | ||||||
|  | 		nextFrame, err := earlyAllocFrame() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if err = mapFn(page, nextFrame, vmm.FlagPresent|vmm.FlagRW|vmm.FlagNoExecute); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		mem.Memset(page.Address(), 0, mem.PageSize) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	alloc.pools = *(*[]framePool)(unsafe.Pointer(&alloc.poolsHdr)) | ||||||
|  | 
 | ||||||
|  | 	// Run a second pass to initialize the free bitmap slices for all pools | ||||||
|  | 	bitmapStartAddr := alloc.poolsHdr.Data + uintptr(alloc.poolsHdr.Len)*sizeofPool | ||||||
|  | 	poolIndex := 0 | ||||||
|  | 	multiboot.VisitMemRegions(func(region *multiboot.MemoryMapEntry) bool { | ||||||
|  | 		if region.Type != multiboot.MemAvailable { | ||||||
|  | 			return true | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		regionStartFrame := pmm.Frame(((region.PhysAddress + pageSizeMinus1) & ^pageSizeMinus1) >> mem.PageShift) | ||||||
|  | 		regionEndFrame := pmm.Frame(((region.PhysAddress+region.Length) & ^pageSizeMinus1)>>mem.PageShift) - 1 | ||||||
|  | 		bitmapBytes := uintptr((((regionEndFrame - regionStartFrame) + 63) &^ 63) >> 3) | ||||||
|  | 
 | ||||||
|  | 		alloc.pools[poolIndex].startFrame = regionStartFrame | ||||||
|  | 		alloc.pools[poolIndex].endFrame = regionEndFrame | ||||||
|  | 		alloc.pools[poolIndex].freeCount = uint32(regionEndFrame - regionStartFrame + 1) | ||||||
|  | 		alloc.pools[poolIndex].freeBitmapHdr.Len = int(bitmapBytes >> 3) | ||||||
|  | 		alloc.pools[poolIndex].freeBitmapHdr.Cap = alloc.pools[poolIndex].freeBitmapHdr.Len | ||||||
|  | 		alloc.pools[poolIndex].freeBitmapHdr.Data = bitmapStartAddr | ||||||
|  | 		alloc.pools[poolIndex].freeBitmap = *(*[]uint64)(unsafe.Pointer(&alloc.pools[poolIndex].freeBitmapHdr)) | ||||||
|  | 
 | ||||||
|  | 		bitmapStartAddr += bitmapBytes | ||||||
|  | 		poolIndex++ | ||||||
|  | 		return true | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // earlyAllocFrame is a helper that delegates a frame allocation request to the | ||||||
|  | // early allocator instance. This function is passed as an argument to | ||||||
|  | // vmm.SetFrameAllocator instead of earlyAllocator.AllocFrame. The latter | ||||||
|  | // confuses the compiler's escape analysis into thinking that | ||||||
|  | // earlyAllocator.Frame escapes to heap. | ||||||
|  | func earlyAllocFrame() (pmm.Frame, *kernel.Error) { | ||||||
|  | 	return earlyAllocator.AllocFrame() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Init sets up the kernel physical memory allocation sub-system. | ||||||
|  | func Init(kernelStart, kernelEnd uintptr) *kernel.Error { | ||||||
|  | 	earlyAllocator.init(kernelStart, kernelEnd) | ||||||
|  | 	earlyAllocator.printMemoryMap() | ||||||
|  | 
 | ||||||
|  | 	vmm.SetFrameAllocator(earlyAllocFrame) | ||||||
|  | 	return FrameAllocator.init() | ||||||
|  | } | ||||||
							
								
								
									
										183
									
								
								kernel/mem/pmm/allocator/bitmap_allocator_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								kernel/mem/pmm/allocator/bitmap_allocator_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,183 @@ | |||||||
|  | package allocator | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"math" | ||||||
|  | 	"testing" | ||||||
|  | 	"unsafe" | ||||||
|  | 
 | ||||||
|  | 	"github.com/achilleasa/gopher-os/kernel" | ||||||
|  | 	"github.com/achilleasa/gopher-os/kernel/hal/multiboot" | ||||||
|  | 	"github.com/achilleasa/gopher-os/kernel/mem" | ||||||
|  | 	"github.com/achilleasa/gopher-os/kernel/mem/pmm" | ||||||
|  | 	"github.com/achilleasa/gopher-os/kernel/mem/vmm" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func TestSetupPoolBitmaps(t *testing.T) { | ||||||
|  | 	defer func() { | ||||||
|  | 		mapFn = vmm.Map | ||||||
|  | 		reserveRegionFn = vmm.EarlyReserveRegion | ||||||
|  | 	}() | ||||||
|  | 
 | ||||||
|  | 	multiboot.SetInfoPtr(uintptr(unsafe.Pointer(&multibootMemoryMap[0]))) | ||||||
|  | 
 | ||||||
|  | 	// The captured multiboot data corresponds to qemu running with 128M RAM. | ||||||
|  | 	// The allocator will need to reserve 2 pages to store the bitmap data. | ||||||
|  | 	var ( | ||||||
|  | 		alloc   BitmapAllocator | ||||||
|  | 		physMem = make([]byte, 2*mem.PageSize) | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	// Init phys mem with junk | ||||||
|  | 	for i := 0; i < len(physMem); i++ { | ||||||
|  | 		physMem[i] = 0xf0 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	mapCallCount := 0 | ||||||
|  | 	mapFn = func(page vmm.Page, frame pmm.Frame, flags vmm.PageTableEntryFlag) *kernel.Error { | ||||||
|  | 		mapCallCount++ | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	reserveCallCount := 0 | ||||||
|  | 	reserveRegionFn = func(_ mem.Size) (uintptr, *kernel.Error) { | ||||||
|  | 		reserveCallCount++ | ||||||
|  | 		return uintptr(unsafe.Pointer(&physMem[0])), nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if err := alloc.setupPoolBitmaps(); err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if exp := 2; mapCallCount != exp { | ||||||
|  | 		t.Fatalf("expected allocator to call vmm.Map %d times; called %d", exp, mapCallCount) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if exp := 1; reserveCallCount != exp { | ||||||
|  | 		t.Fatalf("expected allocator to call vmm.EarlyReserveRegion %d times; called %d", exp, reserveCallCount) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if exp, got := 2, len(alloc.pools); got != exp { | ||||||
|  | 		t.Fatalf("expected allocator to initialize %d pools; got %d", exp, got) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for poolIndex, pool := range alloc.pools { | ||||||
|  | 		if expFreeCount := uint32(pool.endFrame - pool.startFrame + 1); pool.freeCount != expFreeCount { | ||||||
|  | 			t.Errorf("[pool %d] expected free count to be %d; got %d", poolIndex, expFreeCount, pool.freeCount) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if exp, got := int(math.Ceil(float64(pool.freeCount)/64.0)), len(pool.freeBitmap); got != exp { | ||||||
|  | 			t.Errorf("[pool %d] expected bitmap len to be %d; got %d", poolIndex, exp, got) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		for blockIndex, block := range pool.freeBitmap { | ||||||
|  | 			if block != 0 { | ||||||
|  | 				t.Errorf("[pool %d] expected bitmap block %d to be cleared; got %d", poolIndex, blockIndex, block) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestSetupPoolBitmapsErrors(t *testing.T) { | ||||||
|  | 	defer func() { | ||||||
|  | 		mapFn = vmm.Map | ||||||
|  | 		reserveRegionFn = vmm.EarlyReserveRegion | ||||||
|  | 	}() | ||||||
|  | 
 | ||||||
|  | 	multiboot.SetInfoPtr(uintptr(unsafe.Pointer(&multibootMemoryMap[0]))) | ||||||
|  | 	var alloc BitmapAllocator | ||||||
|  | 
 | ||||||
|  | 	t.Run("vmm.EarlyReserveRegion returns an error", func(t *testing.T) { | ||||||
|  | 		expErr := &kernel.Error{Module: "test", Message: "something went wrong"} | ||||||
|  | 
 | ||||||
|  | 		reserveRegionFn = func(_ mem.Size) (uintptr, *kernel.Error) { | ||||||
|  | 			return 0, expErr | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if err := alloc.setupPoolBitmaps(); err != expErr { | ||||||
|  | 			t.Fatalf("expected to get error: %v; got %v", expErr, err) | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  | 	t.Run("vmm.Map returns an error", func(t *testing.T) { | ||||||
|  | 		expErr := &kernel.Error{Module: "test", Message: "something went wrong"} | ||||||
|  | 
 | ||||||
|  | 		reserveRegionFn = func(_ mem.Size) (uintptr, *kernel.Error) { | ||||||
|  | 			return 0, nil | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		mapFn = func(page vmm.Page, frame pmm.Frame, flags vmm.PageTableEntryFlag) *kernel.Error { | ||||||
|  | 			return expErr | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if err := alloc.setupPoolBitmaps(); err != expErr { | ||||||
|  | 			t.Fatalf("expected to get error: %v; got %v", expErr, err) | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	t.Run("earlyAllocator returns an error", func(t *testing.T) { | ||||||
|  | 		emptyInfoData := []byte{ | ||||||
|  | 			0, 0, 0, 0, // size | ||||||
|  | 			0, 0, 0, 0, // reserved | ||||||
|  | 			0, 0, 0, 0, // tag with type zero and length zero | ||||||
|  | 			0, 0, 0, 0, | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		multiboot.SetInfoPtr(uintptr(unsafe.Pointer(&emptyInfoData[0]))) | ||||||
|  | 
 | ||||||
|  | 		if err := alloc.setupPoolBitmaps(); err != errBootAllocOutOfMemory { | ||||||
|  | 			t.Fatalf("expected to get error: %v; got %v", errBootAllocOutOfMemory, err) | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestAllocatorPackageInit(t *testing.T) { | ||||||
|  | 	defer func() { | ||||||
|  | 		mapFn = vmm.Map | ||||||
|  | 		reserveRegionFn = vmm.EarlyReserveRegion | ||||||
|  | 	}() | ||||||
|  | 
 | ||||||
|  | 	var ( | ||||||
|  | 		physMem = make([]byte, 2*mem.PageSize) | ||||||
|  | 		fb      = mockTTY() | ||||||
|  | 		buf     bytes.Buffer | ||||||
|  | 	) | ||||||
|  | 	multiboot.SetInfoPtr(uintptr(unsafe.Pointer(&multibootMemoryMap[0]))) | ||||||
|  | 
 | ||||||
|  | 	t.Run("success", func(t *testing.T) { | ||||||
|  | 		mapFn = func(page vmm.Page, frame pmm.Frame, flags vmm.PageTableEntryFlag) *kernel.Error { | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		reserveRegionFn = func(_ mem.Size) (uintptr, *kernel.Error) { | ||||||
|  | 			return uintptr(unsafe.Pointer(&physMem[0])), nil | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if err := Init(0x100000, 0x1fa7c8); err != nil { | ||||||
|  | 			t.Fatal(err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		for i := 0; i < len(fb); i += 2 { | ||||||
|  | 			if fb[i] == 0x0 { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 			buf.WriteByte(fb[i]) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		exp := "[boot_mem_alloc] system memory map:    [0x0000000000 - 0x000009fc00], size:     654336, type: available    [0x000009fc00 - 0x00000a0000], size:       1024, type: reserved    [0x00000f0000 - 0x0000100000], size:      65536, type: reserved    [0x0000100000 - 0x0007fe0000], size:  133038080, type: available    [0x0007fe0000 - 0x0008000000], size:     131072, type: reserved    [0x00fffc0000 - 0x0100000000], size:     262144, type: reserved[boot_mem_alloc] available memory: 130559Kb[boot_mem_alloc] kernel loaded at 0x100000 - 0x1fa7c8[boot_mem_alloc] size: 1025992 bytes, reserved pages: 251" | ||||||
|  | 		if got := buf.String(); got != exp { | ||||||
|  | 			t.Fatalf("expected printMemoryMap to generate the following output:\n%q\ngot:\n%q", exp, got) | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	t.Run("error", func(t *testing.T) { | ||||||
|  | 		expErr := &kernel.Error{Module: "test", Message: "something went wrong"} | ||||||
|  | 
 | ||||||
|  | 		mapFn = func(page vmm.Page, frame pmm.Frame, flags vmm.PageTableEntryFlag) *kernel.Error { | ||||||
|  | 			return expErr | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if err := Init(0x100000, 0x1fa7c8); err != expErr { | ||||||
|  | 			t.Fatalf("expected to get error: %v; got %v", expErr, err) | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  | } | ||||||
| @ -134,10 +134,3 @@ func (alloc *bootMemAllocator) printMemoryMap() { | |||||||
| 		uint64(alloc.kernelEndFrame-alloc.kernelStartFrame+1), | 		uint64(alloc.kernelEndFrame-alloc.kernelStartFrame+1), | ||||||
| 	) | 	) | ||||||
| } | } | ||||||
| 
 |  | ||||||
| // Init sets up the kernel physical memory allocation sub-system. |  | ||||||
| func Init(kernelStart, kernelEnd uintptr) *kernel.Error { |  | ||||||
| 	earlyAllocator.init(kernelStart, kernelEnd) |  | ||||||
| 	earlyAllocator.printMemoryMap() |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -1,7 +1,6 @@ | |||||||
| package allocator | package allocator | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"bytes" |  | ||||||
| 	"testing" | 	"testing" | ||||||
| 	"unsafe" | 	"unsafe" | ||||||
| 
 | 
 | ||||||
| @ -94,26 +93,6 @@ func TestBootMemoryAllocator(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestAllocatorPackageInit(t *testing.T) { |  | ||||||
| 	fb := mockTTY() |  | ||||||
| 	multiboot.SetInfoPtr(uintptr(unsafe.Pointer(&multibootMemoryMap[0]))) |  | ||||||
| 
 |  | ||||||
| 	Init(0x100000, 0x1fa7c8) |  | ||||||
| 
 |  | ||||||
| 	var buf bytes.Buffer |  | ||||||
| 	for i := 0; i < len(fb); i += 2 { |  | ||||||
| 		if fb[i] == 0x0 { |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 		buf.WriteByte(fb[i]) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	exp := "[boot_mem_alloc] system memory map:    [0x0000000000 - 0x000009fc00], size:     654336, type: available    [0x000009fc00 - 0x00000a0000], size:       1024, type: reserved    [0x00000f0000 - 0x0000100000], size:      65536, type: reserved    [0x0000100000 - 0x0007fe0000], size:  133038080, type: available    [0x0007fe0000 - 0x0008000000], size:     131072, type: reserved    [0x00fffc0000 - 0x0100000000], size:     262144, type: reserved[boot_mem_alloc] available memory: 130559Kb[boot_mem_alloc] kernel loaded at 0x100000 - 0x1fa7c8[boot_mem_alloc] size: 1025992 bytes, reserved pages: 251" |  | ||||||
| 	if got := buf.String(); got != exp { |  | ||||||
| 		t.Fatalf("expected printMemoryMap to generate the following output:\n%q\ngot:\n%q", exp, got) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| var ( | var ( | ||||||
| 	// A dump of multiboot data when running under qemu containing only the | 	// A dump of multiboot data when running under qemu containing only the | ||||||
| 	// memory region tag.  The dump encodes the following available memory | 	// memory region tag.  The dump encodes the following available memory | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user