FreeNOS
IntelKernel.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015 Niek Linnenbank
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <FreeNOS/ProcessManager.h>
19#include <FreeNOS/System.h>
20#include <Macros.h>
21#include <List.h>
22#include <ListIterator.h>
23#include <SplitAllocator.h>
24#include <Vector.h>
25#include <MemoryBlock.h>
26#include <String.h>
27#include <BootImage.h>
28#include <intel/IntelMap.h>
29#include <intel/IntelBoot.h>
30#include "IntelKernel.h"
31
32extern C void executeInterrupt(CPUState state)
33{
35}
36
38 : Kernel(info)
39{
40 IntelMap map;
41 IntelCore core;
42
43 // First megabyte should not be used on Intel (I/O devices and tables)
44 for (Size i = 0; i < MegaByte(1); i += PAGESIZE)
45 {
46 m_alloc->allocate(info->memory.phys + i);
47 }
48
49 // Refresh MemoryContext::current()
50 IntelPaging memContext(&map, core.readCR3(), m_alloc);
51 memContext.initialize();
52 memContext.activate();
53
54 // Install interruptRun() callback
56
57 // Setup exception handlers
58 for (int i = 0; i < 17; i++)
59 {
61 }
62 // Setup IRQ handlers
63 for (int i = 17; i < 256; i++)
64 {
65 // Trap gate
66 if (i == 0x90)
67 hookIntVector(0x90, trap, 0);
68
69 // Hardware Interrupt
70 else
72 }
73
74 // Only core0 uses PIC and PIT.
75 if (info->coreId == 0)
76 {
77 // Set PIT interrupt frequency to 250 hertz
79
80 // Configure the master and slave PICs
83 }
84 else
86
87 // Try to configure the APIC.
89 {
90 NOTICE("Using APIC timer");
91
92 // Enable APIC timer interrupt
94
95 m_timer = &m_apic;
96
97 if (m_coreInfo->timerCounter == 0)
98 {
101 }
102 else
104 }
105 // Use PIT as system timer.
106 else
107 {
108 NOTICE("Using PIT timer");
109 m_timer = &m_pit;
110
111 // Install PIT interrupt vector handler
114
115 // Enable PIT interrupt
117 }
118
119 // Initialize TSS Segment
120 Address tssAddr = (Address) &kernelTss;
121 gdt[KERNEL_TSS].limitLow = sizeof(TSS);
122 gdt[KERNEL_TSS].baseLow = (tssAddr) & 0xffff;
123 gdt[KERNEL_TSS].baseMid = (tssAddr >> 16) & 0xff;
124 gdt[KERNEL_TSS].type = 9;
129 gdt[KERNEL_TSS].baseHigh = (tssAddr >> 24) & 0xff;
130
131 // Fill the Task State Segment (TSS).
132 MemoryBlock::set(&kernelTss, 0, sizeof(TSS));
134 kernelTss.esp0 = 0;
135 kernelTss.bitmap = sizeof(TSS);
137
138}
139
140void IntelKernel::enableIRQ(u32 irq, bool enabled)
141{
142 if (irq == m_apic.getInterrupt())
143 {
144 if (enabled)
145 m_apic.start();
146 else
147 m_apic.stop();
148
149 return;
150 }
151
152 Kernel::enableIRQ(irq, enabled);
153}
154
156{
157 IntelCore core;
159
160 core.logException(state);
161 FATAL("core" << coreInfo.coreId << ": Exception in Process: " << procs->current()->getID());
162
163 assert(procs->current() != ZERO);
164 procs->remove(procs->current());
165 procs->schedule();
166}
167
169{
171
172 if (kern->m_intControl)
173 {
174 kern->m_intControl->clear(
175 state->vector - kern->m_intControl->getBase()
176 );
177 }
178}
179
181{
182 state->regs.eax = Kernel::instance()->getAPI()->invoke(
183 (API::Number) state->regs.eax,
184 state->regs.ecx,
185 state->regs.ebx,
186 state->regs.edx,
187 state->regs.esi,
188 state->regs.edi
189 );
190}
191
193{
195 Size irq = kern->m_timer->getInterrupt();
196
197 kern->enableIRQ(irq, true);
198
199 // Ensure the APIC timer gets end-of-interrupt
200 if (irq == kern->m_apic.getInterrupt())
201 kern->m_apic.clear(irq);
202
203 kern->m_timer->tick();
204 kern->getProcessManager()->schedule();
205}
C void executeInterrupt(CPUState state)
Result invoke(Number number, ulong arg1, ulong arg2, ulong arg3, ulong arg4, ulong arg5)
Execute a generic API function.
Definition API.cpp:35
Number
Enumeration of supported generic kernel API functions.
Definition API.h:50
uint getBase() const
Get interrupt number base offset.
virtual Result clear(uint irq)=0
Clear hardware interrupt (IRQ).
virtual Timer::Result initialize()
Initialize the APIC.
virtual Timer::Result stop()
Stop the APIC timer.
Timer::Result start(IntelPIT *pit)
Start the timer using PIT as reference timer.
Definition IntelAPIC.cpp:55
virtual IntController::Result clear(uint irq)
Clear hardware interrupt (IRQ).
uint getCounter() const
Get timer initial counter.
Definition IntelAPIC.cpp:50
Intel CPU Core.
Definition IntelCore.h:258
volatile u32 readCR3() const
Read the CR3 register.
void logException(CPUState *state) const
Log a CPU exception.
Definition IntelCore.cpp:26
Implements an x86 compatible kernel.
Definition IntelKernel.h:44
IntelAPIC m_apic
APIC instance (used if available)
static void clocktick(CPUState *state, ulong param, ulong vector)
i8253 system clock interrupt handler.
static void exception(CPUState *state, ulong param, ulong vector)
Called when the CPU detects a fault.
static void interrupt(CPUState *state, ulong param, ulong vector)
Default interrupt handler.
IntelPIT m_pit
PIT timer instance.
IntelKernel(CoreInfo *info)
Constructor function.
static void trap(CPUState *state, ulong param, ulong vector)
Kernel trap handler (system calls).
IntelPIC m_pic
PIC instance.
virtual void enableIRQ(u32 irq, bool enabled)
Enable or disable an hardware interrupt (IRQ).
Defines memory map for Intel systems.
Definition IntelMap.h:38
Result initialize()
Initialize the PIC.
Definition IntelPIC.cpp:28
virtual Result setFrequency(Size hertz)
Set interrupt frequency.
Definition IntelPIT.cpp:37
Intel virtual memory implementation.
Definition IntelPaging.h:44
virtual Result initialize()
Initialize the MemoryContext.
virtual Result activate(bool initializeMMU=false)
Activate the MemoryContext.
FreeNOS kernel implementation.
Definition Kernel.h:93
CoreInfo * m_coreInfo
CoreInfo object for this core.
Definition Kernel.h:236
SplitAllocator * m_alloc
Physical memory allocator.
Definition Kernel.h:227
API * getAPI()
Get API.
Definition Kernel.cpp:148
virtual void hookIntVector(u32 vec, InterruptHandler h, ulong p)
Hooks a function to an hardware interrupt.
Definition Kernel.cpp:194
virtual void executeIntVector(u32 vec, CPUState *state)
Execute an interrupt handler.
Definition Kernel.cpp:210
IntController * m_intControl
Interrupt Controller.
Definition Kernel.h:242
virtual void enableIRQ(u32 irq, bool enabled)
Enable or disable an hardware interrupt (IRQ).
Definition Kernel.cpp:168
Timer * m_timer
Timer device.
Definition Kernel.h:245
ProcessManager * getProcessManager()
Get process manager.
Definition Kernel.cpp:143
static void * set(void *dest, int ch, unsigned count)
Fill memory with a constant byte.
Represents a process which may run on the host.
void remove(Process *proc, const uint exitStatus=0)
Remove a Process.
Result schedule()
Schedule next process to run.
Process * current()
Current process running.
ProcessID getID() const
Retrieve our ID number.
Definition Process.cpp:60
virtual Result allocate(Range &args)
Allocate physical memory.
Size getFrequency() const
Get timer frequency.
Definition Timer.cpp:33
virtual Result tick()
Process timer tick.
Definition Timer.cpp:74
@ Success
Definition Timer.h:54
Size getInterrupt() const
Get timer interrupt number.
Definition Timer.cpp:28
static Kernel * instance()
Retrieve the instance.
Definition Singleton.h:86
#define PAGESIZE
ARM uses 4K pages.
Definition ARMConstant.h:97
#define KERNEL_DS_SEL
#define ltr(sel)
Loads the Task State Register (LTR) with the given segment.
Definition IntelCore.h:81
TSS kernelTss
Task State Segment.
C void(* interruptRun)(CPUState state)
Process an interrupt.
#define KERNEL_TSS_SEL
#define KERNEL_TSS
Kernel Task State Segment.
Segment gdt[]
Global Descriptor Table.
CoreInfo coreInfo
Local CoreInfo instance.
#define assert(exp)
Insert program diagnostics.
Definition assert.h:60
unsigned int u32
Unsigned 32-bit number.
Definition Types.h:53
unsigned long Address
A memory address.
Definition Types.h:131
#define MegaByte(v)
Convert megabytes to bytes.
Definition Macros.h:57
#define NOTICE(msg)
Output a notice message.
Definition Log.h:75
unsigned long ulong
Unsigned long number.
Definition Types.h:47
#define FATAL(msg)
Output a critical message and terminate program immediatly.
Definition Log.h:50
unsigned int Size
Any sane size indicator cannot go negative.
Definition Types.h:128
#define ZERO
Zero value.
Definition Macros.h:43
#define C
Used to define external C functions.
Definition Macros.h:134
void param(Terminal *term, int key, int value)
Set terminal parameters.
Definition Terminal.cpp:305
u32 eax
Definition IntelCore.h:202
u32 esi
Definition IntelCore.h:202
u32 edi
Definition IntelCore.h:202
u32 edx
Definition IntelCore.h:202
u32 ebx
Definition IntelCore.h:202
u32 ecx
Definition IntelCore.h:202
Contains all the CPU registers.
Definition ARMCore.h:244
u32 vector
Definition IntelCore.h:247
CPURegs regs
Definition IntelCore.h:244
Per-Core information structure.
Definition CoreInfo.h:61
uint timerCounter
Arch-specific timer counter.
Definition CoreInfo.h:99
uint coreId
Core identifier.
Definition CoreInfo.h:66
Memory::Range memory
Defines the physical memory available to the core.
Definition CoreInfo.h:69
Address phys
Physical address.
Definition Memory.h:58
u32 privilege
Definition IntelCore.h:179
u32 baseMid
Definition IntelCore.h:177
u32 limitHigh
Definition IntelCore.h:181
u32 limitLow
Definition IntelCore.h:175
u32 baseLow
Definition IntelCore.h:176
u32 present
Definition IntelCore.h:180
u32 baseHigh
Definition IntelCore.h:183
u32 type
Definition IntelCore.h:178
u32 granularity
Definition IntelCore.h:182
Intel's Task State Segment.
Definition IntelCore.h:153
u32 esp0
Definition IntelCore.h:155
u32 ss0
Definition IntelCore.h:155
u32 bitmap
Definition IntelCore.h:166