diff --git a/src/gopheros/kernel/irq/interrupt_amd64.go b/src/gopheros/kernel/irq/interrupt_amd64.go index 6525d3e..ef92ab1 100644 --- a/src/gopheros/kernel/irq/interrupt_amd64.go +++ b/src/gopheros/kernel/irq/interrupt_amd64.go @@ -1,6 +1,6 @@ package irq -import "gopheros/kernel/kfmt/early" +import "gopheros/kernel/kfmt" // Regs contains a snapshot of the register values when an interrupt occurred. type Regs struct { @@ -23,14 +23,14 @@ type Regs struct { // Print outputs a dump of the register values to the active console. func (r *Regs) Print() { - early.Printf("RAX = %16x RBX = %16x\n", r.RAX, r.RBX) - early.Printf("RCX = %16x RDX = %16x\n", r.RCX, r.RDX) - early.Printf("RSI = %16x RDI = %16x\n", r.RSI, r.RDI) - early.Printf("RBP = %16x\n", r.RBP) - early.Printf("R8 = %16x R9 = %16x\n", r.R8, r.R9) - early.Printf("R10 = %16x R11 = %16x\n", r.R10, r.R11) - early.Printf("R12 = %16x R13 = %16x\n", r.R12, r.R13) - early.Printf("R14 = %16x R15 = %16x\n", r.R14, r.R15) + kfmt.Printf("RAX = %16x RBX = %16x\n", r.RAX, r.RBX) + kfmt.Printf("RCX = %16x RDX = %16x\n", r.RCX, r.RDX) + kfmt.Printf("RSI = %16x RDI = %16x\n", r.RSI, r.RDI) + kfmt.Printf("RBP = %16x\n", r.RBP) + kfmt.Printf("R8 = %16x R9 = %16x\n", r.R8, r.R9) + kfmt.Printf("R10 = %16x R11 = %16x\n", r.R10, r.R11) + kfmt.Printf("R12 = %16x R13 = %16x\n", r.R12, r.R13) + kfmt.Printf("R14 = %16x R15 = %16x\n", r.R14, r.R15) } // Frame describes an exception frame that is automatically pushed by the CPU @@ -45,7 +45,7 @@ type Frame struct { // Print outputs a dump of the exception frame to the active console. func (f *Frame) Print() { - early.Printf("RIP = %16x CS = %16x\n", f.RIP, f.CS) - early.Printf("RSP = %16x SS = %16x\n", f.RSP, f.SS) - early.Printf("RFL = %16x\n", f.RFlags) + kfmt.Printf("RIP = %16x CS = %16x\n", f.RIP, f.CS) + kfmt.Printf("RSP = %16x SS = %16x\n", f.RSP, f.SS) + kfmt.Printf("RFL = %16x\n", f.RFlags) } diff --git a/src/gopheros/kernel/irq/interrupt_amd64_test.go b/src/gopheros/kernel/irq/interrupt_amd64_test.go index 750482b..79bb5a2 100644 --- a/src/gopheros/kernel/irq/interrupt_amd64_test.go +++ b/src/gopheros/kernel/irq/interrupt_amd64_test.go @@ -2,14 +2,16 @@ package irq import ( "bytes" - "gopheros/kernel/driver/video/console" - "gopheros/kernel/hal" + "gopheros/kernel/kfmt" "testing" - "unsafe" ) func TestRegsPrint(t *testing.T) { - fb := mockTTY() + defer func() { + kfmt.SetOutputSink(nil) + }() + var buf bytes.Buffer + regs := Regs{ RAX: 1, RBX: 2, @@ -29,15 +31,20 @@ func TestRegsPrint(t *testing.T) { } regs.Print() - exp := "RAX = 0000000000000001 RBX = 0000000000000002\nRCX = 0000000000000003 RDX = 0000000000000004\nRSI = 0000000000000005 RDI = 0000000000000006\nRBP = 0000000000000007\nR8 = 0000000000000008 R9 = 0000000000000009\nR10 = 000000000000000a R11 = 000000000000000b\nR12 = 000000000000000c R13 = 000000000000000d\nR14 = 000000000000000e R15 = 000000000000000f" + exp := "RAX = 0000000000000001 RBX = 0000000000000002\nRCX = 0000000000000003 RDX = 0000000000000004\nRSI = 0000000000000005 RDI = 0000000000000006\nRBP = 0000000000000007\nR8 = 0000000000000008 R9 = 0000000000000009\nR10 = 000000000000000a R11 = 000000000000000b\nR12 = 000000000000000c R13 = 000000000000000d\nR14 = 000000000000000e R15 = 000000000000000f\n" - if got := readTTY(fb); got != exp { + kfmt.SetOutputSink(&buf) + if got := buf.String(); got != exp { t.Fatalf("expected to get:\n%q\ngot:\n%q", exp, got) } } func TestFramePrint(t *testing.T) { - fb := mockTTY() + defer func() { + kfmt.SetOutputSink(nil) + }() + var buf bytes.Buffer + frame := Frame{ RIP: 1, CS: 2, @@ -47,37 +54,11 @@ func TestFramePrint(t *testing.T) { } frame.Print() - exp := "RIP = 0000000000000001 CS = 0000000000000002\nRSP = 0000000000000004 SS = 0000000000000005\nRFL = 0000000000000003" + exp := "RIP = 0000000000000001 CS = 0000000000000002\nRSP = 0000000000000004 SS = 0000000000000005\nRFL = 0000000000000003\n" - if got := readTTY(fb); got != exp { + kfmt.SetOutputSink(&buf) + if got := buf.String(); got != exp { t.Fatalf("expected to get:\n%q\ngot:\n%q", exp, got) } } - -func readTTY(fb []byte) string { - var buf bytes.Buffer - for i := 0; i < len(fb); i += 2 { - ch := fb[i] - if ch == 0 { - if i+2 < len(fb) && fb[i+2] != 0 { - buf.WriteByte('\n') - } - continue - } - - buf.WriteByte(ch) - } - - return buf.String() -} - -func mockTTY() []byte { - // Mock a tty to handle early.Printf output - mockConsoleFb := make([]byte, 160*25) - mockConsole := &console.Ega{} - mockConsole.Init(80, 25, uintptr(unsafe.Pointer(&mockConsoleFb[0]))) - hal.ActiveTerminal.AttachTo(mockConsole) - - return mockConsoleFb -} diff --git a/src/gopheros/kernel/kfmt/fmt_test.go b/src/gopheros/kernel/kfmt/fmt_test.go index 0a660fd..90d9bf0 100644 --- a/src/gopheros/kernel/kfmt/fmt_test.go +++ b/src/gopheros/kernel/kfmt/fmt_test.go @@ -168,10 +168,10 @@ func TestPrintfToRingBuffer(t *testing.T) { }() exp := "hello world" - Fprintf(&buf, exp) + Printf(exp) var buf bytes.Buffer - SetOutputSink(buf) + SetOutputSink(&buf) if got := buf.String(); got != exp { t.Fatalf("expected to get:\n%q\ngot:\n%q", exp, got) diff --git a/src/gopheros/kernel/kfmt/panic.go b/src/gopheros/kernel/kfmt/panic.go index 5ff9cb5..73b320b 100644 --- a/src/gopheros/kernel/kfmt/panic.go +++ b/src/gopheros/kernel/kfmt/panic.go @@ -3,7 +3,6 @@ package kfmt import ( "gopheros/kernel" "gopheros/kernel/cpu" - "gopheros/kernel/kfmt/early" ) var ( @@ -31,12 +30,12 @@ func Panic(e interface{}) { err = errRuntimePanic } - early.Printf("\n-----------------------------------\n") + Printf("\n-----------------------------------\n") if err != nil { - early.Printf("[%s] unrecoverable error: %s\n", err.Module, err.Message) + Printf("[%s] unrecoverable error: %s\n", err.Module, err.Message) } - early.Printf("*** kernel panic: system halted ***") - early.Printf("\n-----------------------------------\n") + Printf("*** kernel panic: system halted ***") + Printf("\n-----------------------------------\n") cpuHaltFn() } diff --git a/src/gopheros/kernel/kfmt/panic_test.go b/src/gopheros/kernel/kfmt/panic_test.go index e8ceacf..0888ddb 100644 --- a/src/gopheros/kernel/kfmt/panic_test.go +++ b/src/gopheros/kernel/kfmt/panic_test.go @@ -5,17 +5,18 @@ import ( "errors" "gopheros/kernel" "gopheros/kernel/cpu" - "gopheros/kernel/driver/video/console" - "gopheros/kernel/hal" "testing" - "unsafe" ) func TestPanic(t *testing.T) { defer func() { cpuHaltFn = cpu.Halt + SetOutputSink(nil) }() + var buf bytes.Buffer + SetOutputSink(&buf) + var cpuHaltCalled bool cpuHaltFn = func() { cpuHaltCalled = true @@ -23,14 +24,14 @@ func TestPanic(t *testing.T) { t.Run("with *kernel.Error", func(t *testing.T) { cpuHaltCalled = false - fb := mockTTY() + buf.Reset() err := &kernel.Error{Module: "test", Message: "panic test"} Panic(err) - exp := "\n-----------------------------------\n[test] unrecoverable error: panic test\n*** kernel panic: system halted ***\n-----------------------------------" + exp := "\n-----------------------------------\n[test] unrecoverable error: panic test\n*** kernel panic: system halted ***\n-----------------------------------\n" - if got := readTTY(fb); got != exp { + if got := buf.String(); got != exp { t.Fatalf("expected to get:\n%q\ngot:\n%q", exp, got) } @@ -41,14 +42,14 @@ func TestPanic(t *testing.T) { t.Run("with error", func(t *testing.T) { cpuHaltCalled = false - fb := mockTTY() + buf.Reset() err := errors.New("go error") Panic(err) - exp := "\n-----------------------------------\n[rt] unrecoverable error: go error\n*** kernel panic: system halted ***\n-----------------------------------" + exp := "\n-----------------------------------\n[rt] unrecoverable error: go error\n*** kernel panic: system halted ***\n-----------------------------------\n" - if got := readTTY(fb); got != exp { + if got := buf.String(); got != exp { t.Fatalf("expected to get:\n%q\ngot:\n%q", exp, got) } @@ -59,14 +60,14 @@ func TestPanic(t *testing.T) { t.Run("with string", func(t *testing.T) { cpuHaltCalled = false - fb := mockTTY() + buf.Reset() err := "string error" Panic(err) - exp := "\n-----------------------------------\n[rt] unrecoverable error: string error\n*** kernel panic: system halted ***\n-----------------------------------" + exp := "\n-----------------------------------\n[rt] unrecoverable error: string error\n*** kernel panic: system halted ***\n-----------------------------------\n" - if got := readTTY(fb); got != exp { + if got := buf.String(); got != exp { t.Fatalf("expected to get:\n%q\ngot:\n%q", exp, got) } @@ -77,13 +78,13 @@ func TestPanic(t *testing.T) { t.Run("without error", func(t *testing.T) { cpuHaltCalled = false - fb := mockTTY() + buf.Reset() Panic(nil) - exp := "\n-----------------------------------\n*** kernel panic: system halted ***\n-----------------------------------" + exp := "\n-----------------------------------\n*** kernel panic: system halted ***\n-----------------------------------\n" - if got := readTTY(fb); got != exp { + if got := buf.String(); got != exp { t.Fatalf("expected to get:\n%q\ngot:\n%q", exp, got) } @@ -92,30 +93,3 @@ func TestPanic(t *testing.T) { } }) } - -func readTTY(fb []byte) string { - var buf bytes.Buffer - for i := 0; i < len(fb); i += 2 { - ch := fb[i] - if ch == 0 { - if i+2 < len(fb) && fb[i+2] != 0 { - buf.WriteByte('\n') - } - continue - } - - buf.WriteByte(ch) - } - - return buf.String() -} - -func mockTTY() []byte { - // Mock a tty to handle early.Printf output - mockConsoleFb := make([]byte, 160*25) - mockConsole := &console.Ega{} - mockConsole.Init(80, 25, uintptr(unsafe.Pointer(&mockConsoleFb[0]))) - hal.ActiveTerminal.AttachTo(mockConsole) - - return mockConsoleFb -} diff --git a/src/gopheros/kernel/mem/pmm/allocator/bitmap_allocator.go b/src/gopheros/kernel/mem/pmm/allocator/bitmap_allocator.go index 1030b47..4afc144 100644 --- a/src/gopheros/kernel/mem/pmm/allocator/bitmap_allocator.go +++ b/src/gopheros/kernel/mem/pmm/allocator/bitmap_allocator.go @@ -3,7 +3,7 @@ package allocator import ( "gopheros/kernel" "gopheros/kernel/hal/multiboot" - "gopheros/kernel/kfmt/early" + "gopheros/kernel/kfmt" "gopheros/kernel/mem" "gopheros/kernel/mem/pmm" "gopheros/kernel/mem/vmm" @@ -234,7 +234,7 @@ func (alloc *BitmapAllocator) reserveEarlyAllocatorFrames() { } func (alloc *BitmapAllocator) printStats() { - early.Printf( + kfmt.Printf( "[bitmap_alloc] page stats: free: %d/%d (%d reserved)\n", alloc.totalPages-alloc.reservedPages, alloc.totalPages, diff --git a/src/gopheros/kernel/mem/pmm/allocator/bitmap_allocator_test.go b/src/gopheros/kernel/mem/pmm/allocator/bitmap_allocator_test.go index a36c80d..b3c0896 100644 --- a/src/gopheros/kernel/mem/pmm/allocator/bitmap_allocator_test.go +++ b/src/gopheros/kernel/mem/pmm/allocator/bitmap_allocator_test.go @@ -406,7 +406,6 @@ func TestAllocatorPackageInit(t *testing.T) { return uintptr(unsafe.Pointer(&physMem[0])), nil } - mockTTY() if err := Init(0x100000, 0x1fa7c8); err != nil { t.Fatal(err) } diff --git a/src/gopheros/kernel/mem/pmm/allocator/bootmem.go b/src/gopheros/kernel/mem/pmm/allocator/bootmem.go index 4970348..3d7ab1f 100644 --- a/src/gopheros/kernel/mem/pmm/allocator/bootmem.go +++ b/src/gopheros/kernel/mem/pmm/allocator/bootmem.go @@ -3,7 +3,7 @@ package allocator import ( "gopheros/kernel" "gopheros/kernel/hal/multiboot" - "gopheros/kernel/kfmt/early" + "gopheros/kernel/kfmt" "gopheros/kernel/mem" "gopheros/kernel/mem/pmm" ) @@ -117,19 +117,19 @@ func (alloc *bootMemAllocator) AllocFrame() (pmm.Frame, *kernel.Error) { // printMemoryMap scans the memory region information provided by the // bootloader and prints out the system's memory map. func (alloc *bootMemAllocator) printMemoryMap() { - early.Printf("[boot_mem_alloc] system memory map:\n") + kfmt.Printf("[boot_mem_alloc] system memory map:\n") var totalFree mem.Size multiboot.VisitMemRegions(func(region *multiboot.MemoryMapEntry) bool { - early.Printf("\t[0x%10x - 0x%10x], size: %10d, type: %s\n", region.PhysAddress, region.PhysAddress+region.Length, region.Length, region.Type.String()) + kfmt.Printf("\t[0x%10x - 0x%10x], size: %10d, type: %s\n", region.PhysAddress, region.PhysAddress+region.Length, region.Length, region.Type.String()) if region.Type == multiboot.MemAvailable { totalFree += mem.Size(region.Length) } return true }) - early.Printf("[boot_mem_alloc] available memory: %dKb\n", uint64(totalFree/mem.Kb)) - early.Printf("[boot_mem_alloc] kernel loaded at 0x%x - 0x%x\n", alloc.kernelStartAddr, alloc.kernelEndAddr) - early.Printf("[boot_mem_alloc] size: %d bytes, reserved pages: %d\n", + kfmt.Printf("[boot_mem_alloc] available memory: %dKb\n", uint64(totalFree/mem.Kb)) + kfmt.Printf("[boot_mem_alloc] kernel loaded at 0x%x - 0x%x\n", alloc.kernelStartAddr, alloc.kernelEndAddr) + kfmt.Printf("[boot_mem_alloc] size: %d bytes, reserved pages: %d\n", uint64(alloc.kernelEndAddr-alloc.kernelStartAddr), uint64(alloc.kernelEndFrame-alloc.kernelStartFrame+1), ) diff --git a/src/gopheros/kernel/mem/pmm/allocator/bootmem_test.go b/src/gopheros/kernel/mem/pmm/allocator/bootmem_test.go index 0494d5a..8a0d937 100644 --- a/src/gopheros/kernel/mem/pmm/allocator/bootmem_test.go +++ b/src/gopheros/kernel/mem/pmm/allocator/bootmem_test.go @@ -1,8 +1,6 @@ package allocator import ( - "gopheros/kernel/driver/video/console" - "gopheros/kernel/hal" "gopheros/kernel/hal/multiboot" "testing" "unsafe" @@ -118,13 +116,3 @@ var ( 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } ) - -func mockTTY() []byte { - // Mock a tty to handle early.Printf output - mockConsoleFb := make([]byte, 160*25) - mockConsole := &console.Ega{} - mockConsole.Init(80, 25, uintptr(unsafe.Pointer(&mockConsoleFb[0]))) - hal.ActiveTerminal.AttachTo(mockConsole) - - return mockConsoleFb -} diff --git a/src/gopheros/kernel/mem/vmm/translate_test.go b/src/gopheros/kernel/mem/vmm/translate_test.go index 6d7cca5..35dd1db 100644 --- a/src/gopheros/kernel/mem/vmm/translate_test.go +++ b/src/gopheros/kernel/mem/vmm/translate_test.go @@ -61,12 +61,3 @@ func TestTranslateAmd64(t *testing.T) { } } } - -/* - phys, err := vmm.Translate(uintptr(100 * mem.Mb)) - if err != nil { - early.Printf("err: %s\n", err.Error()) - } else { - early.Printf("phys: 0x%x\n", phys) - } -*/ diff --git a/src/gopheros/kernel/mem/vmm/vmm.go b/src/gopheros/kernel/mem/vmm/vmm.go index 3814347..b63b1f9 100644 --- a/src/gopheros/kernel/mem/vmm/vmm.go +++ b/src/gopheros/kernel/mem/vmm/vmm.go @@ -4,7 +4,7 @@ import ( "gopheros/kernel" "gopheros/kernel/cpu" "gopheros/kernel/irq" - "gopheros/kernel/kfmt/early" + "gopheros/kernel/kfmt" "gopheros/kernel/mem" "gopheros/kernel/mem/pmm" ) @@ -83,27 +83,27 @@ func pageFaultHandler(errorCode uint64, frame *irq.Frame, regs *irq.Regs) { } func nonRecoverablePageFault(faultAddress uintptr, errorCode uint64, frame *irq.Frame, regs *irq.Regs, err *kernel.Error) { - early.Printf("\nPage fault while accessing address: 0x%16x\nReason: ", faultAddress) + kfmt.Printf("\nPage fault while accessing address: 0x%16x\nReason: ", faultAddress) switch { case errorCode == 0: - early.Printf("read from non-present page") + kfmt.Printf("read from non-present page") case errorCode == 1: - early.Printf("page protection violation (read)") + kfmt.Printf("page protection violation (read)") case errorCode == 2: - early.Printf("write to non-present page") + kfmt.Printf("write to non-present page") case errorCode == 3: - early.Printf("page protection violation (write)") + kfmt.Printf("page protection violation (write)") case errorCode == 4: - early.Printf("page-fault in user-mode") + kfmt.Printf("page-fault in user-mode") case errorCode == 8: - early.Printf("page table has reserved bit set") + kfmt.Printf("page table has reserved bit set") case errorCode == 16: - early.Printf("instruction fetch") + kfmt.Printf("instruction fetch") default: - early.Printf("unknown") + kfmt.Printf("unknown") } - early.Printf("\n\nRegisters:\n") + kfmt.Printf("\n\nRegisters:\n") regs.Print() frame.Print() @@ -112,8 +112,8 @@ func nonRecoverablePageFault(faultAddress uintptr, errorCode uint64, frame *irq. } func generalProtectionFaultHandler(_ uint64, frame *irq.Frame, regs *irq.Regs) { - early.Printf("\nGeneral protection fault while accessing address: 0x%x\n", readCR2Fn()) - early.Printf("Registers:\n") + kfmt.Printf("\nGeneral protection fault while accessing address: 0x%x\n", readCR2Fn()) + kfmt.Printf("Registers:\n") regs.Print() frame.Print() diff --git a/src/gopheros/kernel/mem/vmm/vmm_test.go b/src/gopheros/kernel/mem/vmm/vmm_test.go index bec50d4..c41bd79 100644 --- a/src/gopheros/kernel/mem/vmm/vmm_test.go +++ b/src/gopheros/kernel/mem/vmm/vmm_test.go @@ -5,9 +5,8 @@ import ( "fmt" "gopheros/kernel" "gopheros/kernel/cpu" - "gopheros/kernel/driver/video/console" - "gopheros/kernel/hal" "gopheros/kernel/irq" + "gopheros/kernel/kfmt" "gopheros/kernel/mem" "gopheros/kernel/mem/pmm" "strings" @@ -54,8 +53,6 @@ func TestRecoverablePageFault(t *testing.T) { {FlagPresent | FlagCopyOnWrite, nil, nil, false}, } - mockTTY() - ptePtrFn = func(entry uintptr) unsafe.Pointer { return unsafe.Pointer(&pageEntry) } readCR2Fn = func() uint64 { return uint64(uintptr(unsafe.Pointer(&origPage[0]))) } unmapFn = func(_ Page) *kernel.Error { return nil } @@ -102,6 +99,10 @@ func TestRecoverablePageFault(t *testing.T) { } func TestNonRecoverablePageFault(t *testing.T) { + defer func() { + kfmt.SetOutputSink(nil) + }() + specs := []struct { errCode uint64 expReason string @@ -143,19 +144,21 @@ func TestNonRecoverablePageFault(t *testing.T) { var ( regs irq.Regs frame irq.Frame + buf bytes.Buffer ) + kfmt.SetOutputSink(&buf) for specIndex, spec := range specs { t.Run(fmt.Sprint(specIndex), func(t *testing.T) { + buf.Reset() defer func() { if err := recover(); err != errUnrecoverableFault { t.Errorf("expected a panic with errUnrecoverableFault; got %v", err) } }() - fb := mockTTY() nonRecoverablePageFault(0xbadf00d000, spec.errCode, &frame, ®s, errUnrecoverableFault) - if got := readTTY(fb); !strings.Contains(got, spec.expReason) { + if got := buf.String(); !strings.Contains(got, spec.expReason) { t.Errorf("expected reason %q; got output:\n%q", spec.expReason, got) } }) @@ -182,7 +185,6 @@ func TestGPtHandler(t *testing.T) { } }() - mockTTY() generalProtectionFaultHandler(0, &frame, ®s) } @@ -252,30 +254,3 @@ func TestInit(t *testing.T) { } }) } - -func readTTY(fb []byte) string { - var buf bytes.Buffer - for i := 0; i < len(fb); i += 2 { - ch := fb[i] - if ch == 0 { - if i+2 < len(fb) && fb[i+2] != 0 { - buf.WriteByte('\n') - } - continue - } - - buf.WriteByte(ch) - } - - return buf.String() -} - -func mockTTY() []byte { - // Mock a tty to handle early.Printf output - mockConsoleFb := make([]byte, 160*25) - mockConsole := &console.Ega{} - mockConsole.Init(80, 25, uintptr(unsafe.Pointer(&mockConsoleFb[0]))) - hal.ActiveTerminal.AttachTo(mockConsole) - - return mockConsoleFb -}