Xyris  0.5
Arch.i686.cpp
Go to the documentation of this file.
1 /**
2  * @file Arch.i686.cpp
3  * @author Keeton Feavel ([email protected])
4  * @brief i686 architecture implementation of Arch.hpp
5  * @version 0.1
6  * @date 2021-08-24
7  *
8  * @copyright Copyright the Xyris Contributors (c) 2021
9  *
10  */
11 // Architecture (i686) specific header
12 #include <Arch/i686/Arch.i686.hpp>
13 #include <Arch/i686/regs.hpp>
14 #include <Arch/i686/gdt.hpp>
15 #include <Arch/i686/idt.hpp>
16 #include <Arch/i686/isr.hpp>
17 #include <Arch/i686/ports.hpp>
18 #include <Arch/i686/timer.hpp>
19 #include <cpuid.h>
20 #include <stddef.h>
21 #include <stdint.h>
22 // Architecture agnostic header
23 #include <Arch/Arch.hpp>
24 #include <Arch/Memory.hpp>
25 #include <cpuid.h>
26 // Helper functions
27 #include <Library/stdio.hpp>
29 #include <Devices/Serial/rs232.hpp>
30 
31 const char exceptionStrings[33][32] = {
32  "Divide-By-Zero", "Debugging", "Non-Maskable Interrupt", "Breakpoint",
33  "Overflow", "Bound Range Exceeded", "Invalid Opcode", "Device Not Available",
34  "Double Fault", "Coprocessor Overrun", "Invalid TSS", "Segment Not Present",
35  "Segmentation Fault", "Protection Fault", "Page Fault", "RESERVED",
36  "Floating Point Exception", "Alignment Check", "Machine Check", "SIMD Floating Point Exception",
37  "Virtualization Exception", "RESERVED", "RESERVED", "RESERVED",
38  "RESERVED", "RESERVED", "RESERVED", "RESERVED",
39  "RESERVED", "Security Exception", "RESERVED", "Triple Fault", "FPU Error",
40 };
41 
42 /*
43  * _ _ ___ _ __
44  * /_\ _ _ __| |_ |_ _|_ _| |_ ___ _ _ / _|__ _ __ ___
45  * / _ \| '_/ _| ' \ | || ' \ _/ -_) '_| _/ _` / _/ -_)
46  * /_/ \_\_| \__|_||_| |___|_||_\__\___|_| |_| \__,_\__\___|
47  */
48 
49 namespace Arch {
50 
51 void registersToString(char* buf, struct registers* regs)
52 {
53  ksprintf(
54  buf,
55  "\033[31m DS:\033[0m 0x%08X\n"
56  "\033[31mEDI:\033[0m 0x%08X \033[31mESI:\033[0m 0x%08X \033[31mEBP:\033[0m 0x%08X \033[31mESP:\033[0m 0x%08X\n"
57  "\033[31mEAX:\033[0m 0x%08X \033[31mEBX:\033[0m 0x%08X \033[31mECX:\033[0m 0x%08X \033[31mEDX:\033[0m 0x%08X\n"
58  "\033[31mERR:\033[0m 0x%08X \033[31mEIP:\033[0m 0x%08X \033[31m CS:\033[0m 0x%08X\n"
59  "\033[31mFLG:\033[0m 0x%08X \033[31m SS:\033[0m 0x%08X\n\n",
60  regs->ds,
61  regs->edi, regs->esi, regs->ebp, regs->esp,
62  regs->eax, regs->ebx, regs->ecx, regs->edx,
63  regs->err_code, regs->eip, regs->cs, regs->eflags,
64  regs->ss);
65 }
66 
68 {
69  log_all("Exception: %lu (%s)\n\n", regs->int_num, exceptionStrings[regs->int_num]);
70  if (regs->err_code) {
71  log_all("Error code: %lu", regs->err_code);
72  }
73 
75  Registers::CR2 cr2 = Registers::readCR2();
76  int missing = regs->err_code & 0x1; // Page not present
77  int rw = regs->err_code & 0x2; // Write operation?
78  int us = regs->err_code & 0x4; // Processor was in user-mode?
79  int reserved = regs->err_code & 0x8; // Overwritten CPU-reserved bits of page entry?
80  int id = regs->err_code & 0x10; // Caused by an instruction fetch?
81 
82  const char* real = (missing ? "missing" : "present");
83  const char* rws = (rw ? "reading" : "writing");
84  const char* uss = (us ? "user-mode" : "kernel");
85  const char* avail = (reserved ? "reserved" : "available");
86  log_all("Page fault at 0x%08lX [ %s %s %s %s ] (id -> %i)\n", cr2.pageFaultAddr, real, rws, uss, avail, id);
87  }
88 }
89 
90 } // !namespace Arch
91 
92 namespace Arch::Memory {
93 
94 void pagingEnable() {
95  struct Registers::CR0 cr0 = Registers::readCR0();
96  cr0.pagingEnable = 1;
97  Registers::writeCR0(cr0);
98 }
99 
101  struct Registers::CR0 cr0 = Registers::readCR0();
102  cr0.pagingEnable = 0;
103  Registers::writeCR0(cr0);
104 }
105 
106 } // !namespace Arch::Memory
107 
108 namespace Arch::CPU {
109 
110 void init()
111 {
112  criticalRegion([]() {
113  GDT::init(); // Initialize the Global Descriptor Table
114  Interrupts::init(); // Initialize Interrupt Service Requests
115  timer_init(1000); // Programmable Interrupt Timer (1ms)
116  });
117 }
118 
120  asm volatile("cli");
121 }
122 
124  asm volatile("sti");
125 }
126 
127 const char* vendor()
128 {
129  static int vendor[4];
130  __cpuid(0, vendor[0], vendor[1], vendor[2], vendor[3]);
131  return (char*)vendor;
132 }
133 
134 const char* model()
135 {
136  static int model[12];
137  __cpuid(0x80000002, model[0], model[1], model[2], model[3]);
138  __cpuid(0x80000003, model[4], model[5], model[6], model[7]);
139  __cpuid(0x80000004, model[8], model[9], model[10], model[11]);
140  return (char*)model;
141 }
142 
143 } // !namespace Arch::CPU
registers::ecx
uint32_t ecx
Definition: regs.hpp:21
stdio.hpp
Arch::Memory::pagingEnable
void pagingEnable()
Enable hardware paging.
Definition: Arch.i686.cpp:94
Interrupts::init
void init()
Definition: isr.cpp:70
registers::eflags
uint32_t eflags
Definition: regs.hpp:23
Arch::CPU::init
void init()
Definition: Arch.i686.cpp:110
Arch::CPU::criticalRegion
void criticalRegion(Function critWork)
Definition: Arch.hpp:82
ksprintf
int ksprintf(char *buf, const char *fmt,...)
Sends formatted output to a string.
Definition: printf.cpp:342
ports.hpp
Ports header file. Provides inline functions for getting and setting values at different ports....
Arch::Memory
Definition: Arch.i686.cpp:92
Arch::CPU::vendor
const char * vendor()
Definition: Arch.i686.cpp:127
console.hpp
Framebuffer console.
registers::esp
uint32_t esp
Definition: regs.hpp:23
Interrupts::EXCEPTION_PAGE_FAULT
@ EXCEPTION_PAGE_FAULT
Definition: isr.hpp:40
registers::ds
uint32_t ds
Definition: regs.hpp:20
registers::eax
uint32_t eax
Definition: regs.hpp:21
Arch::CPU::interruptsEnable
void interruptsEnable()
Definition: Arch.i686.cpp:123
Arch::Memory::pagingDisable
void pagingDisable()
Disable hardware paging.
Definition: Arch.i686.cpp:100
registers::ebp
uint32_t ebp
Definition: regs.hpp:21
Arch::registersToString
void registersToString(char *buf, struct registers *regs)
Write all register names and values as a string to a buffer. Provided buffer size must also take esca...
Definition: Arch.i686.cpp:51
timer.hpp
registers::ss
uint32_t ss
Definition: regs.hpp:23
timer_init
void timer_init(uint32_t freq)
Initialize the CPU timer with the given frequency.
Definition: timer.cpp:31
Arch::CPU::interruptsDisable
void interruptsDisable()
Definition: Arch.i686.cpp:119
registers::edi
uint32_t edi
Definition: regs.hpp:21
Arch.i686.hpp
i686 architecture implementation of Arch.hpp
registers
A structure definining values for all x86 registers. Cannot be namespaced due to C linkage and ASM in...
Definition: regs.hpp:19
regs.hpp
i686 control register definitions. C & C++ compatible header.
registers::eip
uint32_t eip
Definition: regs.hpp:23
log_all
#define log_all(fmt,...)
Prints a statement to serial debugger and the kernel framebuffer. Max message size is 1024 (including...
Definition: stdio.hpp:59
registers::err_code
uint32_t err_code
Definition: regs.hpp:22
rs232.hpp
A simple, write-only driver for the RS232 serial device standard. Code mostly ported from Panix-Archi...
Arch.hpp
Architecture control and initialization.
registers::edx
uint32_t edx
Definition: regs.hpp:21
Arch::registersPrintInformation
void registersPrintInformation(struct registers *regs)
Print register information to all kernel terminals (serial, framebuffer, etc.). Used for panic and de...
Definition: Arch.i686.cpp:67
exceptionStrings
const char exceptionStrings[33][32]
Definition: Arch.i686.cpp:31
Arch::CPU::model
const char * model()
Definition: Arch.i686.cpp:134
registers::esi
uint32_t esi
Definition: regs.hpp:21
registers::ebx
uint32_t ebx
Definition: regs.hpp:21
Arch::CPU
Definition: Arch.hpp:70
Arch
Definition: Arch.hpp:33
idt.hpp
Interrupt Descriptor Table header.
Memory.hpp
Architecture memory management & paging API.
registers::cs
uint32_t cs
Definition: regs.hpp:23
registers::int_num
uint32_t int_num
Definition: regs.hpp:22
gdt.hpp
The Global Descriptor Table (GDT) is specific to the IA32 architecture. It contains entries telling t...
isr.hpp
Interrupt Service Routine header.
GDT::init
void init()
Setup and install the GDT onto the system.
Definition: gdt.cpp:22