FreeNOS
IntelProcess.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/System.h>
19 #include <MemoryBlock.h>
20 #include <Memory.h>
21 #include <SplitAllocator.h>
22 #include <intel/IntelPaging.h>
23 #include "IntelProcess.h"
24 
25 IntelProcess::IntelProcess(ProcessID id, Address entry, bool privileged, const MemoryMap &map)
26  : Process(id, entry, privileged, map)
27 {
28 }
29 
31 {
32  Memory::Range range;
33  Allocator::Range allocPhys, allocVirt;
34 
35  // Create MMU context
36  m_memoryContext = new IntelPaging(&m_map, Kernel::instance()->getAllocator());
37  if (!m_memoryContext)
38  {
39  ERROR("failed to create memory context");
40  return OutOfMemory;
41  }
42 
43  // Initialize MMU context
45  if (memResult != MemoryContext::Success)
46  {
47  ERROR("failed to initialize MemoryContext: result = " << (int) memResult);
48  return OutOfMemory;
49  }
50 
51  // Allocate User stack
54  allocPhys.address = 0;
55  allocPhys.size = range.size;
56  allocPhys.alignment = PAGESIZE;
57 
58  if (Kernel::instance()->getAllocator()->allocate(allocPhys) != Allocator::Success)
59  {
60  ERROR("failed to allocate user stack");
61  return OutOfMemory;
62  }
63  range.phys = allocPhys.address;
64 
65  // Map User stack
67  {
68  ERROR("failed to map user stack");
69  return MemoryMapError;
70  }
71 
72  // Allocate Kernel stack
73  allocPhys.address = 0;
74  allocPhys.size = KernelStackSize;
75  allocPhys.alignment = PAGESIZE;
76 
77  if (Kernel::instance()->getAllocator()->allocate(allocPhys, allocVirt) != Allocator::Success)
78  {
79  ERROR("failed to allocate kernel stack");
80  return OutOfMemory;
81  }
82  m_kernelStackBase = allocVirt.address;
84 
85  // Initialize registers
86  reset(m_entry);
87 
88  // Finalize with generic initialization
89  return Process::initialize();
90 }
91 
93 {
94  // Release the kernel stack memory page
97 }
98 
100 {
102  const Address userStack = range.virt + range.size - MEMALIGN;
103  const u16 dataSel = m_privileged ? KERNEL_DS_SEL : USER_DS_SEL;
104  const u16 codeSel = m_privileged ? KERNEL_CS_SEL : USER_CS_SEL;
105 
106  // Reset saved kernel stack pointer
108  - sizeof(IRQRegs0)
109  - sizeof(CPURegs);
110 
111  // Fill kernel stack with initial (user)registers to restore
112  // loadCoreState: struct CPUState
113  CPUState *regs = (CPUState *) m_kernelStackBase - 1;
114  MemoryBlock::set(regs, 0, sizeof(CPUState));
115  regs->seg.ss0 = KERNEL_DS_SEL;
116  regs->seg.fs = dataSel;
117  regs->seg.gs = dataSel;
118  regs->seg.es = dataSel;
119  regs->seg.ds = dataSel;
120  regs->regs.ebp = userStack;
121  regs->regs.esp0 = m_kernelStack;
122  regs->irq.eip = m_entry;
123  regs->irq.cs = codeSel;
125  INTEL_EFLAGS_IRQ | (0x3 << 12);
126  regs->irq.esp3 = userStack;
127  regs->irq.ss3 = dataSel;
128 
129  // restoreState: iret
130  IRQRegs0 *irq = (IRQRegs0 *) regs - 1;
131  irq->eip = (Address) loadCoreState;
132  irq->cs = KERNEL_CS_SEL;
134 
135  // restoreState: popa
136  CPURegs *pusha = (CPURegs *) irq - 1;
137  MemoryBlock::set(pusha, 0, sizeof(CPURegs));
138  pusha->ebp = m_kernelStackBase - sizeof(CPURegs);
139  pusha->esp0 = pusha->ebp;
140 }
141 
143 {
144  IntelProcess *p = (IntelProcess *) previous;
145 
146  // Reload Task State Register (with kernel stack for interrupts)
148 
149  // Activate the memory context of this process
151 
152  // Switch kernel stack (includes saved userspace registers)
154  m_kernelStack );
155 }
IRQRegs3::esp3
u32 esp3
Definition: IntelCore.h:231
MemoryContext::initialize
virtual Result initialize()=0
Initialize the MemoryContext.
Process::m_memoryContext
MemoryContext * m_memoryContext
MMU memory context.
Definition: Process.h:271
SegRegs::gs
u32 gs
Definition: IntelCore.h:193
IntelPaging
Intel virtual memory implementation.
Definition: IntelPaging.h:43
IntelProcess.h
switchCoreState
C void switchCoreState(Address *currentStack, Address stack)
Switch Core Stack.
CPURegs::esp0
u32 esp0
Definition: IntelCore.h:202
Memory::Range
Memory range.
Definition: Memory.h:55
CPURegs::ebp
u32 ebp
Definition: IntelCore.h:202
SplitAllocator.h
Process::MemoryMapError
@ MemoryMapError
Definition: Process.h:58
KERNEL_CS_SEL
#define KERNEL_CS_SEL
Definition: IntelConstant.h:49
Process
Represents a process which may run on the host.
Definition: Process.h:44
MemoryBlock::set
static void * set(void *dest, int ch, unsigned count)
Fill memory with a constant byte.
Definition: MemoryBlock.cpp:25
INTEL_EFLAGS_IRQ
#define INTEL_EFLAGS_IRQ
Definition: IntelCore.h:138
SegRegs::es
u32 es
Definition: IntelCore.h:193
MemoryMap::UserStack
@ UserStack
< User stack
Definition: MemoryMap.h:58
Memory::Writable
@ Writable
Definition: Memory.h:42
Memory::User
@ User
Definition: Memory.h:44
IntelProcess::IntelProcess
IntelProcess(ProcessID id, Address entry, bool privileged, const MemoryMap &map)
Constructor function.
Definition: IntelProcess.cpp:25
CPURegs
struct CPURegs CPURegs
Structure represents the pusha/popa format.
PAGESIZE
#define PAGESIZE
ARM uses 4K pages.
Definition: ARMConstant.h:97
USER_DS_SEL
#define USER_DS_SEL
Definition: IntelConstant.h:61
Process::m_map
MemoryMap m_map
Virtual memory layout.
Definition: Process.h:268
MEMALIGN
#define MEMALIGN
Memory address alignment.
Definition: ARMConstant.h:127
SegRegs::fs
u32 fs
Definition: IntelCore.h:193
IRQRegs0::eflags
u32 eflags
Definition: IntelCore.h:214
ProcessID
u32 ProcessID
Process Identification Number.
Definition: Types.h:140
Address
unsigned long Address
A memory address.
Definition: Types.h:131
Allocator::Range::address
Address address
Starting address of the memory range.
Definition: Allocator.h:67
MemoryBlock.h
Kernel::getAllocator
SplitAllocator * getAllocator()
Get physical memory allocator.
Definition: Kernel.cpp:138
IRQRegs3::cs
u32 cs
Definition: IntelCore.h:231
IntelPaging.h
Allocator::Range::alignment
Size alignment
Alignment in bytes or ZERO for default alignment.
Definition: Allocator.h:69
Memory::Readable
@ Readable
Definition: Memory.h:41
IntelProcess::reset
virtual void reset(const Address entry)
Restart execution at the given entry point.
Definition: IntelProcess.cpp:99
IntelProcess::initialize
virtual Result initialize()
Initialize the Process.
Definition: IntelProcess.cpp:30
Allocator::Range::size
Size size
Amount of memory in bytes.
Definition: Allocator.h:68
kernelTss
TSS kernelTss
Task State Segment.
SplitAllocator
Allocator which separates kernel mapped memory at virtual and physical addresses.
Definition: SplitAllocator.h:37
CPUState::irq
IRQRegs3 irq
Definition: IntelCore.h:250
IRQRegs0::eip
u32 eip
Definition: IntelCore.h:214
CPUState::seg
SegRegs seg
Definition: IntelCore.h:241
Process::Result
Result
Result codes.
Definition: Process.h:54
MemoryContext::activate
virtual Result activate(bool initializeMMU=false)=0
Activate the MemoryContext.
Process::OutOfMemory
@ OutOfMemory
Definition: Process.h:59
Allocator::Success
@ Success
Definition: Allocator.h:55
Memory::Range::phys
Address phys
Physical address.
Definition: Memory.h:58
CPURegs
Structure represents the pusha/popa format.
Definition: IntelCore.h:200
MemoryContext::Result
Result
Result codes.
Definition: MemoryContext.h:49
IntelProcess::~IntelProcess
virtual ~IntelProcess()
Destructor function.
Definition: IntelProcess.cpp:92
IntelProcess
Process which may execute on an Intel CPU.
Definition: IntelProcess.h:38
MemoryMap::range
Memory::Range range(Region region) const
Get memory range for the given region.
Definition: MemoryMap.cpp:36
u16
unsigned short u16
Unsigned 16-bit number.
Definition: Types.h:56
IntelProcess::execute
virtual void execute(Process *previous)
Execute the process.
Definition: IntelProcess.cpp:142
MemoryContext::Success
@ Success
Definition: MemoryContext.h:51
MemoryMap
Describes virtual memory map layout.
Definition: MemoryMap.h:38
WeakSingleton< Kernel >::instance
static Kernel * instance()
Retrieve the instance.
Definition: Singleton.h:86
Process::m_entry
Address m_entry
Entry point of the program.
Definition: Process.h:265
IntelProcess::m_kernelStackBase
Address m_kernelStackBase
Base kernel stack (fixed)
Definition: IntelProcess.h:92
CPUState::regs
CPURegs regs
Definition: IntelCore.h:244
SegRegs::ds
u32 ds
Definition: IntelCore.h:193
CPUState
Contains all the CPU registers.
Definition: ARMCore.h:243
TSS::esp0
u32 esp0
Definition: IntelCore.h:155
Memory.h
loadCoreState
C void loadCoreState()
Load Core State.
Allocator::Range
Describes a range of memory.
Definition: Allocator.h:65
IRQRegs0
Privileged Interrupt Registers (ring 0)
Definition: IntelCore.h:212
Process::initialize
virtual Result initialize()
Initialize the Process.
Definition: Process.cpp:172
ERROR
#define ERROR(msg)
Output an error message.
Definition: Log.h:61
entry
u32 entry[]
Definition: IntelACPI.h:64
SplitAllocator::release
virtual Result release(const Address addr)
Release memory page.
Definition: SplitAllocator.cpp:89
IntelProcess::m_kernelStack
Address m_kernelStack
Current kernel stack address (changes during execution).
Definition: IntelProcess.h:89
SegRegs::ss0
u32 ss0
Definition: IntelCore.h:193
IRQRegs3::eflags
u32 eflags
Definition: IntelCore.h:231
CPUState
struct CPUState CPUState
Contains all the CPU registers.
INTEL_EFLAGS_DEFAULT
#define INTEL_EFLAGS_DEFAULT
Definition: IntelCore.h:137
SplitAllocator::toPhysical
Address toPhysical(const Address virt) const
Convert Address to physical pointer.
Definition: SplitAllocator.cpp:100
USER_CS_SEL
#define USER_CS_SEL
Definition: IntelConstant.h:57
Memory::Range::virt
Address virt
Virtual address.
Definition: Memory.h:57
Memory::Range::size
Size size
Size in number of bytes.
Definition: Memory.h:59
IntelProcess::KernelStackSize
static const Size KernelStackSize
Size of the kernel stack.
Definition: IntelProcess.h:43
Memory::Range::access
Access access
Page access flags.
Definition: Memory.h:60
ZERO
#define ZERO
Zero value.
Definition: Macros.h:43
IRQRegs3::ss3
u32 ss3
Definition: IntelCore.h:231
MemoryContext::mapRangeContiguous
virtual Result mapRangeContiguous(Memory::Range *range)
Map a range of contiguous physical pages to virtual addresses.
Definition: MemoryContext.cpp:46
IRQRegs0::cs
u32 cs
Definition: IntelCore.h:214
Process::m_privileged
bool m_privileged
Privilege level.
Definition: Process.h:262
IRQRegs3::eip
u32 eip
Definition: IntelCore.h:231
KERNEL_DS_SEL
#define KERNEL_DS_SEL
Definition: IntelConstant.h:53