mirror of
https://github.com/taigrr/gopher-os
synced 2025-01-18 04:43:13 -08:00
79 lines
2.3 KiB
Go
79 lines
2.3 KiB
Go
package vmm
|
|
|
|
import (
|
|
"github.com/achilleasa/gopher-os/kernel"
|
|
"github.com/achilleasa/gopher-os/kernel/cpu"
|
|
"github.com/achilleasa/gopher-os/kernel/irq"
|
|
"github.com/achilleasa/gopher-os/kernel/kfmt/early"
|
|
"github.com/achilleasa/gopher-os/kernel/mem/pmm"
|
|
)
|
|
|
|
var (
|
|
// frameAllocator points to a frame allocator function registered using
|
|
// SetFrameAllocator.
|
|
frameAllocator FrameAllocatorFn
|
|
|
|
// the following functions are mocked by tests and are automatically
|
|
// inlined by the compiler.
|
|
panicFn = kernel.Panic
|
|
handleExceptionWithCodeFn = irq.HandleExceptionWithCode
|
|
readCR2Fn = cpu.ReadCR2
|
|
)
|
|
|
|
// FrameAllocatorFn is a function that can allocate physical frames.
|
|
type FrameAllocatorFn func() (pmm.Frame, *kernel.Error)
|
|
|
|
// SetFrameAllocator registers a frame allocator function that will be used by
|
|
// the vmm code when new physical frames need to be allocated.
|
|
func SetFrameAllocator(allocFn FrameAllocatorFn) {
|
|
frameAllocator = allocFn
|
|
}
|
|
|
|
func pageFaultHandler(errorCode uint64, frame *irq.Frame, regs *irq.Regs) {
|
|
early.Printf("\nPage fault while accessing address: 0x%16x\nReason: ", readCR2Fn())
|
|
switch {
|
|
case errorCode == 0:
|
|
early.Printf("read from non-present page")
|
|
case errorCode == 1:
|
|
early.Printf("page protection violation (read)")
|
|
case errorCode == 2:
|
|
early.Printf("write to non-present page")
|
|
case errorCode == 3:
|
|
early.Printf("page protection violation (write)")
|
|
case errorCode == 4:
|
|
early.Printf("page-fault in user-mode")
|
|
case errorCode == 8:
|
|
early.Printf("page table has reserved bit set")
|
|
case errorCode == 16:
|
|
early.Printf("instruction fetch")
|
|
default:
|
|
early.Printf("unknown")
|
|
}
|
|
|
|
early.Printf("\n\nRegisters:\n")
|
|
regs.Print()
|
|
frame.Print()
|
|
|
|
// TODO: Revisit this when user-mode tasks are implemented
|
|
panicFn(nil)
|
|
}
|
|
|
|
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")
|
|
regs.Print()
|
|
frame.Print()
|
|
|
|
// TODO: Revisit this when user-mode tasks are implemented
|
|
panicFn(nil)
|
|
}
|
|
|
|
// Init initializes the vmm system and installs paging-related exception
|
|
// handlers.
|
|
func Init() *kernel.Error {
|
|
handleExceptionWithCodeFn(irq.PageFaultException, pageFaultHandler)
|
|
handleExceptionWithCodeFn(irq.GPFException, generalProtectionFaultHandler)
|
|
|
|
return nil
|
|
}
|