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 
32 extern C void executeInterrupt(CPUState state)
33 {
34  Kernel::instance()->executeIntVector(state.vector, &state);
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  {
60  hookIntVector(i, exception, 0);
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
71  hookIntVector(i, interrupt, 0);
72  }
73 
74  // Only core0 uses PIC and PIT.
75  if (info->coreId == 0)
76  {
77  // Set PIT interrupt frequency to 250 hertz
78  m_pit.setFrequency(100);
79 
80  // Configure the master and slave PICs
81  m_pic.initialize();
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  {
99  m_apic.start(&m_pit);
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
116  enableIRQ(m_pit.getInterrupt(), true);
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;
125  gdt[KERNEL_TSS].privilege = 0;
126  gdt[KERNEL_TSS].present = 1;
127  gdt[KERNEL_TSS].limitHigh = 0;
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 
140 void 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 }
IntelKernel::enableIRQ
virtual void enableIRQ(u32 irq, bool enabled)
Enable or disable an hardware interrupt (IRQ).
Definition: IntelKernel.cpp:140
Segment::type
u32 type
Definition: IntelCore.h:178
Timer::getFrequency
Size getFrequency() const
Get timer frequency.
Definition: Timer.cpp:33
IntelPaging
Intel virtual memory implementation.
Definition: IntelPaging.h:43
IntelKernel::clocktick
static void clocktick(CPUState *state, ulong param, ulong vector)
i8253 system clock interrupt handler.
Definition: IntelKernel.cpp:192
executeInterrupt
C void executeInterrupt(CPUState state)
Definition: IntelKernel.cpp:32
IntController::clear
virtual Result clear(uint irq)=0
Clear hardware interrupt (IRQ).
Timer::Success
@ Success
Definition: Timer.h:54
SplitAllocator::allocate
virtual Result allocate(Range &args)
Allocate physical memory.
Definition: SplitAllocator.cpp:35
IntelAPIC::getCounter
uint getCounter() const
Get timer initial counter.
Definition: IntelAPIC.cpp:50
SplitAllocator.h
ProcessManager
Represents a process which may run on the host.
Definition: ProcessManager.h:44
Macros.h
Vector.h
API::invoke
Result invoke(Number number, ulong arg1, ulong arg2, ulong arg3, ulong arg4, ulong arg5)
Execute a generic API function.
Definition: API.cpp:35
ulong
unsigned long ulong
Unsigned long number.
Definition: Types.h:47
NOTICE
#define NOTICE(msg)
Output a notice message.
Definition: Log.h:75
Kernel::m_coreInfo
CoreInfo * m_coreInfo
CoreInfo object for this core.
Definition: Kernel.h:236
MemoryBlock::set
static void * set(void *dest, int ch, unsigned count)
Fill memory with a constant byte.
Definition: MemoryBlock.cpp:25
CPURegs::eax
u32 eax
Definition: IntelCore.h:202
IntelAPIC::clear
virtual IntController::Result clear(uint irq)
Clear hardware interrupt (IRQ).
Definition: IntelAPIC.cpp:189
Segment::limitHigh
u32 limitHigh
Definition: IntelCore.h:181
Kernel::m_timer
Timer * m_timer
Timer device.
Definition: Kernel.h:245
Process::getID
ProcessID getID() const
Retrieve our ID number.
Definition: Process.cpp:60
IntelKernel::IntelKernel
IntelKernel(CoreInfo *info)
Constructor function.
Definition: IntelKernel.cpp:37
PAGESIZE
#define PAGESIZE
ARM uses 4K pages.
Definition: ARMConstant.h:97
IntelAPIC::stop
virtual Timer::Result stop()
Stop the APIC timer.
Definition: IntelAPIC.cpp:156
ltr
#define ltr(sel)
Loads the Task State Register (LTR) with the given segment.
Definition: IntelCore.h:81
Address
unsigned long Address
A memory address.
Definition: Types.h:131
CoreInfo::memory
Memory::Range memory
Defines the physical memory available to the core.
Definition: CoreInfo.h:69
param
void param(Terminal *term, int key, int value)
Set terminal parameters.
Definition: Terminal.cpp:305
CPURegs::ebx
u32 ebx
Definition: IntelCore.h:202
MemoryBlock.h
API::Number
Number
Enumeration of supported generic kernel API functions.
Definition: API.h:49
IntelKernel::trap
static void trap(CPUState *state, ulong param, ulong vector)
Kernel trap handler (system calls).
Definition: IntelKernel.cpp:180
CPURegs::edi
u32 edi
Definition: IntelCore.h:202
TSS::ss0
u32 ss0
Definition: IntelCore.h:155
IntelCore::readCR3
volatile u32 readCR3() const
Read the CR3 register.
Definition: IntelCore.cpp:150
Kernel::getProcessManager
ProcessManager * getProcessManager()
Get process manager.
Definition: Kernel.cpp:143
IntelKernel::m_pit
IntelPIT m_pit
PIT timer instance.
Definition: IntelKernel.h:101
kernelTss
TSS kernelTss
Task State Segment.
CoreInfo::coreId
uint coreId
Core identifier.
Definition: CoreInfo.h:66
MegaByte
#define MegaByte(v)
Convert megabytes to bytes.
Definition: Macros.h:57
TSS
Intel's Task State Segment.
Definition: IntelCore.h:152
C
#define C
Used to define external C functions.
Definition: Macros.h:134
FATAL
#define FATAL(msg)
Output a critical message and terminate program immediatly.
Definition: Log.h:50
Kernel::m_intControl
IntController * m_intControl
Interrupt Controller.
Definition: Kernel.h:242
CPURegs::esi
u32 esi
Definition: IntelCore.h:202
BootImage.h
Memory::Range::phys
Address phys
Physical address.
Definition: Memory.h:58
IntelKernel.h
CPURegs::edx
u32 edx
Definition: IntelCore.h:202
Segment::baseLow
u32 baseLow
Definition: IntelCore.h:176
IntelAPIC::start
Timer::Result start(IntelPIT *pit)
Start the timer using PIT as reference timer.
Definition: IntelAPIC.cpp:55
Kernel::enableIRQ
virtual void enableIRQ(u32 irq, bool enabled)
Enable or disable an hardware interrupt (IRQ).
Definition: Kernel.cpp:168
Kernel::getAPI
API * getAPI()
Get API.
Definition: Kernel.cpp:148
IntelKernel::interrupt
static void interrupt(CPUState *state, ulong param, ulong vector)
Default interrupt handler.
Definition: IntelKernel.cpp:168
KERNEL_TSS
#define KERNEL_TSS
Kernel Task State Segment.
Definition: IntelConstant.h:64
IntelKernel
Implements an x86 compatible kernel.
Definition: IntelKernel.h:43
u32
unsigned int u32
Unsigned 32-bit number.
Definition: Types.h:53
IntelCore::logException
void logException(CPUState *state) const
Log a CPU exception.
Definition: IntelCore.cpp:26
Size
unsigned int Size
Any sane size indicator cannot go negative.
Definition: Types.h:128
WeakSingleton< Kernel >::instance
static Kernel * instance()
Retrieve the instance.
Definition: Singleton.h:86
Segment::present
u32 present
Definition: IntelCore.h:180
ProcessManager::schedule
Result schedule()
Schedule next process to run.
Definition: ProcessManager.cpp:155
KERNEL_TSS_SEL
#define KERNEL_TSS_SEL
Definition: IntelConstant.h:65
CPUState::regs
CPURegs regs
Definition: IntelCore.h:244
IntelPIC::initialize
Result initialize()
Initialize the PIC.
Definition: IntelPIC.cpp:28
Kernel
FreeNOS kernel implementation.
Definition: Kernel.h:92
IntelKernel::m_apic
IntelAPIC m_apic
APIC instance (used if available)
Definition: IntelKernel.h:104
CPUState
Contains all the CPU registers.
Definition: ARMCore.h:243
TSS::esp0
u32 esp0
Definition: IntelCore.h:155
CoreInfo
Per-Core information structure.
Definition: CoreInfo.h:60
coreInfo
CoreInfo coreInfo
Local CoreInfo instance.
IntelBoot.h
CoreInfo::timerCounter
uint timerCounter
Arch-specific timer counter.
Definition: CoreInfo.h:99
IntelKernel::m_pic
IntelPIC m_pic
PIC instance.
Definition: IntelKernel.h:107
ListIterator.h
Segment::limitLow
u32 limitLow
Definition: IntelCore.h:175
IntelPaging::initialize
virtual Result initialize()
Initialize the MemoryContext.
Definition: IntelPaging.cpp:47
assert
#define assert(exp)
Insert program diagnostics.
Definition: assert.h:60
IntelKernel::exception
static void exception(CPUState *state, ulong param, ulong vector)
Called when the CPU detects a fault.
Definition: IntelKernel.cpp:155
interruptRun
C void(* interruptRun)(CPUState state)
Process an interrupt.
Kernel::hookIntVector
virtual void hookIntVector(u32 vec, InterruptHandler h, ulong p)
Hooks a function to an hardware interrupt.
Definition: Kernel.cpp:194
ProcessManager::remove
void remove(Process *proc, const uint exitStatus=0)
Remove a Process.
Definition: ProcessManager.cpp:100
String.h
IntController::getBase
uint getBase() const
Get interrupt number base offset.
Definition: IntController.cpp:25
TSS::bitmap
u32 bitmap
Definition: IntelCore.h:166
gdt
Segment gdt[]
Global Descriptor Table.
IntelPIT::setFrequency
virtual Result setFrequency(Size hertz)
Set interrupt frequency.
Definition: IntelPIT.cpp:37
IntelPaging::activate
virtual Result activate(bool initializeMMU=false)
Activate the MemoryContext.
Definition: IntelPaging.cpp:95
CPURegs::ecx
u32 ecx
Definition: IntelCore.h:202
Timer::getInterrupt
Size getInterrupt() const
Get timer interrupt number.
Definition: Timer.cpp:28
CPUState::vector
u32 vector
Definition: IntelCore.h:247
IntelMap
Defines memory map for Intel systems.
Definition: IntelMap.h:37
Kernel::m_alloc
SplitAllocator * m_alloc
Physical memory allocator.
Definition: Kernel.h:227
TSS
struct TSS TSS
Intel's Task State Segment.
Segment::privilege
u32 privilege
Definition: IntelCore.h:179
ProcessManager::current
Process * current()
Current process running.
Definition: ProcessManager.cpp:203
IntelCore
Intel CPU Core.
Definition: IntelCore.h:257
IntelMap.h
ZERO
#define ZERO
Zero value.
Definition: Macros.h:43
Kernel::executeIntVector
virtual void executeIntVector(u32 vec, CPUState *state)
Execute an interrupt handler.
Definition: Kernel.cpp:210
Segment::baseMid
u32 baseMid
Definition: IntelCore.h:177
IntelAPIC::initialize
virtual Timer::Result initialize()
Initialize the APIC.
Definition: IntelAPIC.cpp:162
Segment::baseHigh
u32 baseHigh
Definition: IntelCore.h:183
Timer::tick
virtual Result tick()
Process timer tick.
Definition: Timer.cpp:74
Segment::granularity
u32 granularity
Definition: IntelCore.h:182
List.h
KERNEL_DS_SEL
#define KERNEL_DS_SEL
Definition: IntelConstant.h:53