mirror of
https://github.com/taigrr/gopher-os
synced 2025-01-18 04:43:13 -08:00
Use go:redirect-from directive to map panic to kernel.Panic
All calls (but one) to kernel.Panic have been replaced by calls to panic. A call to kernel.Panic is still required to prevent the compiler from treating kernel.Panic as dead code and eliminating it.
This commit is contained in:
@@ -16,9 +16,10 @@ var (
|
||||
|
||||
// the following functions are mocked by tests and are automatically
|
||||
// inlined by the compiler.
|
||||
panicFn = kernel.Panic
|
||||
handleExceptionWithCodeFn = irq.HandleExceptionWithCode
|
||||
readCR2Fn = cpu.ReadCR2
|
||||
|
||||
errUnrecoverableFault = &kernel.Error{Module: "vmm", Message: "page/gpf fault"}
|
||||
)
|
||||
|
||||
// FrameAllocatorFn is a function that can allocate physical frames.
|
||||
@@ -78,7 +79,7 @@ func pageFaultHandler(errorCode uint64, frame *irq.Frame, regs *irq.Regs) {
|
||||
}
|
||||
}
|
||||
|
||||
nonRecoverablePageFault(faultAddress, errorCode, frame, regs, nil)
|
||||
nonRecoverablePageFault(faultAddress, errorCode, frame, regs, errUnrecoverableFault)
|
||||
}
|
||||
|
||||
func nonRecoverablePageFault(faultAddress uintptr, errorCode uint64, frame *irq.Frame, regs *irq.Regs, err *kernel.Error) {
|
||||
@@ -107,7 +108,7 @@ func nonRecoverablePageFault(faultAddress uintptr, errorCode uint64, frame *irq.
|
||||
frame.Print()
|
||||
|
||||
// TODO: Revisit this when user-mode tasks are implemented
|
||||
panicFn(err)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
func generalProtectionFaultHandler(_ uint64, frame *irq.Frame, regs *irq.Regs) {
|
||||
@@ -117,7 +118,7 @@ func generalProtectionFaultHandler(_ uint64, frame *irq.Frame, regs *irq.Regs) {
|
||||
frame.Print()
|
||||
|
||||
// TODO: Revisit this when user-mode tasks are implemented
|
||||
panicFn(nil)
|
||||
panic(errUnrecoverableFault)
|
||||
}
|
||||
|
||||
// reserveZeroedFrame reserves a physical frame to be used together with
|
||||
|
||||
@@ -2,6 +2,7 @@ package vmm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
"unsafe"
|
||||
@@ -17,18 +18,16 @@ import (
|
||||
|
||||
func TestRecoverablePageFault(t *testing.T) {
|
||||
var (
|
||||
frame irq.Frame
|
||||
regs irq.Regs
|
||||
panicCalled bool
|
||||
pageEntry pageTableEntry
|
||||
origPage = make([]byte, mem.PageSize)
|
||||
clonedPage = make([]byte, mem.PageSize)
|
||||
err = &kernel.Error{Module: "test", Message: "something went wrong"}
|
||||
frame irq.Frame
|
||||
regs irq.Regs
|
||||
pageEntry pageTableEntry
|
||||
origPage = make([]byte, mem.PageSize)
|
||||
clonedPage = make([]byte, mem.PageSize)
|
||||
err = &kernel.Error{Module: "test", Message: "something went wrong"}
|
||||
)
|
||||
|
||||
defer func(origPtePtr func(uintptr) unsafe.Pointer) {
|
||||
ptePtrFn = origPtePtr
|
||||
panicFn = kernel.Panic
|
||||
readCR2Fn = cpu.ReadCR2
|
||||
frameAllocator = nil
|
||||
mapTemporaryFn = MapTemporary
|
||||
@@ -58,97 +57,87 @@ func TestRecoverablePageFault(t *testing.T) {
|
||||
|
||||
mockTTY()
|
||||
|
||||
panicFn = func(_ *kernel.Error) {
|
||||
panicCalled = true
|
||||
}
|
||||
|
||||
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 }
|
||||
flushTLBEntryFn = func(_ uintptr) {}
|
||||
|
||||
for specIndex, spec := range specs {
|
||||
mapTemporaryFn = func(f pmm.Frame) (Page, *kernel.Error) { return Page(f), spec.mapError }
|
||||
SetFrameAllocator(func() (pmm.Frame, *kernel.Error) {
|
||||
addr := uintptr(unsafe.Pointer(&clonedPage[0]))
|
||||
return pmm.Frame(addr >> mem.PageShift), spec.allocError
|
||||
})
|
||||
t.Run(fmt.Sprint(specIndex), func(t *testing.T) {
|
||||
defer func() {
|
||||
err := recover()
|
||||
if spec.expPanic && err == nil {
|
||||
t.Error("expected a panic")
|
||||
} else if !spec.expPanic {
|
||||
if err != nil {
|
||||
t.Error("unexpected panic")
|
||||
return
|
||||
}
|
||||
|
||||
for i := 0; i < len(origPage); i++ {
|
||||
origPage[i] = byte(i % 256)
|
||||
clonedPage[i] = 0
|
||||
}
|
||||
|
||||
panicCalled = false
|
||||
pageEntry = 0
|
||||
pageEntry.SetFlags(spec.pteFlags)
|
||||
|
||||
pageFaultHandler(2, &frame, ®s)
|
||||
|
||||
if spec.expPanic != panicCalled {
|
||||
t.Errorf("[spec %d] expected panic %t; got %t", specIndex, spec.expPanic, panicCalled)
|
||||
}
|
||||
|
||||
if !spec.expPanic {
|
||||
for i := 0; i < len(origPage); i++ {
|
||||
if origPage[i] != clonedPage[i] {
|
||||
t.Errorf("[spec %d] expected clone page to be a copy of the original page; mismatch at index %d", specIndex, i)
|
||||
for i := 0; i < len(origPage); i++ {
|
||||
if origPage[i] != clonedPage[i] {
|
||||
t.Errorf("expected clone page to be a copy of the original page; mismatch at index %d", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
mapTemporaryFn = func(f pmm.Frame) (Page, *kernel.Error) { return Page(f), spec.mapError }
|
||||
SetFrameAllocator(func() (pmm.Frame, *kernel.Error) {
|
||||
addr := uintptr(unsafe.Pointer(&clonedPage[0]))
|
||||
return pmm.Frame(addr >> mem.PageShift), spec.allocError
|
||||
})
|
||||
|
||||
for i := 0; i < len(origPage); i++ {
|
||||
origPage[i] = byte(i % 256)
|
||||
clonedPage[i] = 0
|
||||
}
|
||||
}
|
||||
|
||||
pageEntry = 0
|
||||
pageEntry.SetFlags(spec.pteFlags)
|
||||
|
||||
pageFaultHandler(2, &frame, ®s)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestNonRecoverablePageFault(t *testing.T) {
|
||||
defer func() {
|
||||
panicFn = kernel.Panic
|
||||
}()
|
||||
|
||||
specs := []struct {
|
||||
errCode uint64
|
||||
expReason string
|
||||
expPanic bool
|
||||
}{
|
||||
{
|
||||
0,
|
||||
"read from non-present page",
|
||||
true,
|
||||
},
|
||||
{
|
||||
1,
|
||||
"page protection violation (read)",
|
||||
true,
|
||||
},
|
||||
{
|
||||
2,
|
||||
"write to non-present page",
|
||||
true,
|
||||
},
|
||||
{
|
||||
3,
|
||||
"page protection violation (write)",
|
||||
true,
|
||||
},
|
||||
{
|
||||
4,
|
||||
"page-fault in user-mode",
|
||||
true,
|
||||
},
|
||||
{
|
||||
8,
|
||||
"page table has reserved bit set",
|
||||
true,
|
||||
},
|
||||
{
|
||||
16,
|
||||
"instruction fetch",
|
||||
true,
|
||||
},
|
||||
{
|
||||
0xf00,
|
||||
"unknown",
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -157,58 +146,45 @@ func TestNonRecoverablePageFault(t *testing.T) {
|
||||
frame irq.Frame
|
||||
)
|
||||
|
||||
panicCalled := false
|
||||
panicFn = func(_ *kernel.Error) {
|
||||
panicCalled = true
|
||||
}
|
||||
|
||||
for specIndex, spec := range specs {
|
||||
fb := mockTTY()
|
||||
panicCalled = false
|
||||
t.Run(fmt.Sprint(specIndex), func(t *testing.T) {
|
||||
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, nil)
|
||||
if got := readTTY(fb); !strings.Contains(got, spec.expReason) {
|
||||
t.Errorf("[spec %d] expected reason %q; got output:\n%q", specIndex, spec.expReason, got)
|
||||
continue
|
||||
}
|
||||
|
||||
if spec.expPanic != panicCalled {
|
||||
t.Errorf("[spec %d] expected panic %t; got %t", specIndex, spec.expPanic, panicCalled)
|
||||
}
|
||||
nonRecoverablePageFault(0xbadf00d000, spec.errCode, &frame, ®s, errUnrecoverableFault)
|
||||
if got := readTTY(fb); !strings.Contains(got, spec.expReason) {
|
||||
t.Errorf("expected reason %q; got output:\n%q", spec.expReason, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGPtHandler(t *testing.T) {
|
||||
defer func() {
|
||||
panicFn = kernel.Panic
|
||||
readCR2Fn = cpu.ReadCR2
|
||||
}()
|
||||
|
||||
var (
|
||||
regs irq.Regs
|
||||
frame irq.Frame
|
||||
fb = mockTTY()
|
||||
)
|
||||
|
||||
readCR2Fn = func() uint64 {
|
||||
return 0xbadf00d000
|
||||
}
|
||||
|
||||
panicCalled := false
|
||||
panicFn = func(_ *kernel.Error) {
|
||||
panicCalled = true
|
||||
}
|
||||
defer func() {
|
||||
if err := recover(); err != errUnrecoverableFault {
|
||||
t.Errorf("expected a panic with errUnrecoverableFault; got %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
mockTTY()
|
||||
generalProtectionFaultHandler(0, &frame, ®s)
|
||||
|
||||
exp := "\nGeneral protection fault while accessing address: 0xbadf00d000\nRegisters:\nRAX = 0000000000000000 RBX = 0000000000000000\nRCX = 0000000000000000 RDX = 0000000000000000\nRSI = 0000000000000000 RDI = 0000000000000000\nRBP = 0000000000000000\nR8 = 0000000000000000 R9 = 0000000000000000\nR10 = 0000000000000000 R11 = 0000000000000000\nR12 = 0000000000000000 R13 = 0000000000000000\nR14 = 0000000000000000 R15 = 0000000000000000\nRIP = 0000000000000000 CS = 0000000000000000\nRSP = 0000000000000000 SS = 0000000000000000\nRFL = 0000000000000000"
|
||||
if got := readTTY(fb); got != exp {
|
||||
t.Errorf("expected output:\n%q\ngot:\n%q", exp, got)
|
||||
}
|
||||
|
||||
if !panicCalled {
|
||||
t.Error("expected kernel.Panic to be called")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInit(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user