More unfinished work on kernel API

This commit is contained in:
2020-12-18 14:12:00 -06:00
parent 512f81f515
commit f4395ab6b5
30 changed files with 1024 additions and 568 deletions

View File

@@ -1,5 +1,5 @@
noinst_PROGRAMS = quark-kernel
quark_kernel_SOURCES = kernelstate.cpp module.cpp systeminfo.cpp util.cpp memorymap.cpp pageallocator.cpp allocator.cpp scheduler.cpp
quark_kernel_SOURCES = module.cpp util.cpp memorymap.cpp memoryregion.cpp pageallocator.cpp allocator.cpp scheduler.cpp
quark_kernel_LDADD = -lgcc
quark_kernel_CPPFLAGS = -ffreestanding -mgeneral-regs-only -O0 -Wall -fno-exceptions -fno-rtti -ggdb
quark_kernel_LDFLAGS = -nostdlib
@@ -14,3 +14,4 @@ quark_kernel_SOURCES += x86/mmap.cpp \
quark_kernel_LDFLAGS += -T x86/linker.ld
quark_kernel_DEPENDENCIES = x86/linker.ld
endif

View File

@@ -4,7 +4,7 @@
#include "pageallocator.hpp"
#include "memorymanager.hpp"
#include "memorymap.hpp"
#include "memoryblock.hpp"
#include "sharedblock.hpp"
#include "process.hpp"
#include "systypes.hpp"
@@ -14,6 +14,10 @@ class Kernel
{
public:
void* malloc(size_t size);
void free(void* ptr);
/**
* @brief Maps a region of pages starting at virtual address 'page' with
* length 'length'. Allocates each mapped frame and any necessary page
@@ -64,9 +68,30 @@ public:
*/
void unmapRegion(void* page, size_t length);
/**
* @brief Create a Shared Block object
*
* @param length
* @param flags
* @returns The ID of the
*/
unsigned int createSharedBlock(size_t length, int flags);
const MemoryBlock& getSharedBlock(unsigned int id);
/**
* @brief Get the shared memory block referred to by 'id'
*
* @param id
* @returns a reference
*/
const SharedBlock& getSharedBlock(unsigned int id);
/**
* @brief Create a new process
*
* @param imageBlockID
* @return Process&
*/
Process& createProcess(unsigned int imageBlockID);
/**
* @brief Get the process object corresponsing to 'pid'
@@ -112,7 +137,7 @@ public:
* If it holds any shared blocks which are not held by any other process,
* those blocks will be freed.
*
* @param pid pid of the process to terminate
* @param pid id of the process to terminate
*/
void terminateProcess(unsigned int pid);

View File

@@ -1,9 +0,0 @@
#include "kernelstate.hpp"
using namespace kernelns;
BuddyAllocator State::pageAllocator;
Allocator State::allocator;
Interrupts State::interrupts;
ProcessQueue State::processQueue;
SystemInfo State::config;

View File

@@ -1,33 +0,0 @@
#ifndef KERNELSTATE_H
#define KERNELSTATE_H
#include "pageallocator.hpp"
#include "allocator.hpp"
#include "interrupts.hpp"
#include "scheduler.hpp"
#include "systeminfo.hpp"
namespace kernelns
{
class State
{
public:
static const unsigned int MAX_PROCESSES = 2048;
static BuddyAllocator pageAllocator;
static Allocator allocator;
static Interrupts interrupts;
static ProcessQueue processQueue;
static SystemInfo config;
};
}
#endif

View File

@@ -1,95 +0,0 @@
#ifndef MAP_H
#define MAP_H
template<class Key, class Value>
class Map
{
public:
Map();
bool contains(const Key& key) const
{
if(m_tree == nullptr)
return false;
else if(m_tree->search(key) == nullptr)
return false;
return true;
}
Value& get(const Key& key)
{
if(m_tree = nullptr)
return (Value&) *nullptr;
Node* node = m_tree->search(key);
if(node == nullptr)
return (Value&) *nullptr;
else
return node->m_value;
}
void insert(const Value& value);
void remove(const Key& key);
unsigned int size() const;
private:
class Node
{
public:
enum class Color
{
Black,
Red
}
Key m_key;
Value& m_value;
Node *left, *right, *parent;
Color color;
Node();
Node* uncle()
{
if(parent != nullptr && parent->parent != nullptr)
{
if(parent == parent->parent->left)
return parent->parent->right;
return parent->parent->left;
}
return nullptr;
}
Node* search(const Key& key)
{
if(key == m_key)
return this;
if(left != nullptr)
{
Node* lsearch = left->search(key);
if(lsearch != nullptr)
return lsearch;
}
if(right != nullptr)
{
Node* rsearch = right->search(key);
if(rsearch != nullptr)
return rsearch;
}
return nullptr;
}
};
Node *m_tree;
};
#endif

View File

@@ -1,34 +0,0 @@
#ifndef MEMORYBLOCK_H
#define MEMORYBLOCK_H
#include "systypes.hpp"
class MemoryBlock
{
public:
physaddr_t getLocation() const;
physaddr_t getEnd() const;
size_t getSize() const;
int getAttributes() const;
unsigned int getOwners() const;
void decrementOwners();
private:
physaddr_t m_location;
size_t m_size;
int m_attributes;
unsigned int m_owners;
};
#endif

View File

@@ -12,7 +12,7 @@ public:
*
* @return the size in bytes of a single page
*/
virtual unsigned int pageSize() const = 0;
virtual unsigned int getPageSize() const = 0;
/**
* Allocates space for a new top-level page table, and initializes it to

View File

@@ -2,129 +2,6 @@
using namespace kernelns;
MemoryMap::Region::Region()
{
m_location = 0;
m_size = 0;
m_type = (Type) 0;
}
MemoryMap::Region::Region(Region& copy)
{
m_location = copy.m_location;
m_size = copy.m_size;
m_type = copy.m_type;
}
MemoryMap::Region::Region(physaddr_t location, size_t size, Type type)
{
m_location = location;
m_size = size;
m_type = (size_t) type;
}
const MemoryMap::Region& MemoryMap::Region::operator=(const MemoryMap::Region& rhs)
{
m_location = rhs.m_location;
m_size = rhs.m_size;
m_type = rhs.m_type;
return rhs;
}
const bool MemoryMap::Region::operator==(const MemoryMap::Region& rhs) const
{
return (m_location == rhs.m_location) && (m_size == rhs.m_size);
}
const bool MemoryMap::Region::operator<(const MemoryMap::Region& rhs) const
{
return (m_location < rhs.m_location) || ((m_location == rhs.m_location) && (m_size < rhs.m_size));
}
const bool MemoryMap::Region::operator>(const MemoryMap::Region& rhs) const
{
return (m_location > rhs.m_location) || ((m_location == rhs.m_location) && (m_size > rhs.m_size));
}
const bool MemoryMap::Region::operator<=(const MemoryMap::Region& rhs) const
{
return (m_location < rhs.m_location) || ((m_location == rhs.m_location) && (m_size <= rhs.m_size));
}
const bool MemoryMap::Region::operator>=(const MemoryMap::Region& rhs) const
{
return (m_location > rhs.m_location) || ((m_location == rhs.m_location) && (m_size >= rhs.m_size));
}
physaddr_t MemoryMap::Region::getLocation() const
{
return m_location;
}
size_t MemoryMap::Region::getSize() const
{
return m_size;
}
MemoryMap::Type MemoryMap::Region::getType() const
{
return (Type) m_type;
}
physaddr_t MemoryMap::Region::getEnd() const
{
return m_location + m_size;
}
bool MemoryMap::Region::contains(const MemoryMap::Region& r) const
{
return contains(r.m_location, r.m_size);
}
bool MemoryMap::Region::contains(physaddr_t location, size_t size) const
{
return (location >= m_location) &&
(location + size <= m_location + m_size);
}
bool MemoryMap::Region::overlaps(const MemoryMap::Region& r) const
{
if(r.m_location < m_location)
{
return r.m_location + r.m_size < m_location;
}
else
{
return r.m_location >= m_location && r.m_location < m_location + m_size;
}
}
bool MemoryMap::Region::bordersLeft(const MemoryMap::Region& right) const
{
return m_location + m_size == right.m_location;
}
bool MemoryMap::Region::bordersRight(const MemoryMap::Region& left) const
{
return m_location == left.m_location + left.m_size;
}
bool MemoryMap::Region::borders(const MemoryMap::Region& r) const
{
return bordersLeft(r) || bordersRight(r);
}
void MemoryMap::Region::truncateLeft(physaddr_t left)
{
m_size = getEnd() - left;
m_location = left;
}
void MemoryMap::Region::truncateRight(physaddr_t right)
{
m_size = right - m_location;
}
MemoryMap::MemoryMap()
{
this->m_entries = 0;
@@ -137,7 +14,7 @@ MemoryMap::MemoryMap(MemoryMap& copy)
this->m_entries = copy.m_entries;
}
const MemoryMap::Region& MemoryMap::operator[](size_t index) const
const MemoryRegion& MemoryMap::operator[](size_t index) const
{
return m_map[index];
}
@@ -147,76 +24,58 @@ size_t MemoryMap::size() const
return m_entries;
}
void MemoryMap::insertEntry(physaddr_t location, size_t size, Type type)
size_t MemoryMap::totalMemory() const
{
Region newRegion(location, size, type);
unsigned int i = 0;
while(i < m_entries)
{
if(newRegion < m_map[i])
{
Region buffer = newRegion;
newRegion = m_map[i];
m_map[i] = buffer;
}
i++;
}
m_map[i] = newRegion;
m_entries++;
for(i = 0; i < (m_entries - 1); i++)
size_t sum = 0;
for(int i = 0; i < m_entries; i++)
{
if(m_map[i].overlaps(m_map[i+1]))
{
if(m_map[i].getType() == m_map[i+1].getType())
{
m_map[i] = Region(m_map[i].getLocation(),
(m_map[i+1].getEnd() > m_map[i].getEnd() ? m_map[i+1].getEnd() : m_map[i].getEnd()) - m_map[i].getLocation(),
m_map[i].getType());
remove(i + 1);
i--;
}
else if(m_map[i].getType() == AVAILABLE)
{
if(m_map[i+1].contains(m_map[i]))
{
remove(i);
i--;
}
else if(m_map[i].getEnd() <= m_map[i+1].getEnd())
{
m_map[i].truncateRight(m_map[i+1].getLocation());
}
else
{
unsigned int end = m_map[i].getEnd();
m_map[i].truncateRight(m_map[i+1].getLocation());
insertEntry(m_map[i+1].getEnd(), end - m_map[i+1].getEnd(), AVAILABLE);
}
}
else if(m_map[i+1].getType() == AVAILABLE)
{
if(m_map[i].contains(m_map[i + 1]))
{
remove(i + 1);
i--;
}
else
{
m_map[i+1].truncateLeft(m_map[i].getEnd());
}
}
else
{
// two overlapping unavailable regions
}
}
else if(m_map[i].bordersLeft(m_map[i+1]) && m_map[i].getType() == m_map[i+1].getType())
{
m_map[i] = Region(m_map[i].getLocation(), m_map[i+1].getEnd() - m_map[i].getLocation(), m_map[i].getType());
remove(i + 1);
i--;
}
sum += m_map[i].getSize();
}
return sum;
}
size_t MemoryMap::totalMemory(unsigned int type) const
{
size_t sum = 0;
for(int i = 0; i < m_entries; i++)
{
if(m_map[i].getType() == type)
sum += m_map[i].getSize();
}
return sum;
}
bool MemoryMap::overlaps(const MemoryRegion& region) const
{
for(int i = 0; i < m_entries; i++)
{
if(m_map[i].overlaps(region))
return true;
}
return false;
}
bool MemoryMap::contains(const MemoryRegion& region) const
{
for(int i = 0; i < m_entries; i++)
{
if(m_map[i].contains(region) && m_map[i].getType() == region.getType())
return true;
}
return false;
}
void MemoryMap::insertEntry(const MemoryRegion& region)
{
simpleInsert(region);
unsigned int i = 0;
while(i != invalidIndex)
i = trim(i);
}
void MemoryMap::insertEntry(physaddr_t location, size_t size, unsigned int type)
{
insertEntry(MemoryRegion(location, size, type));
}
void MemoryMap::remove(unsigned int index)
@@ -226,4 +85,88 @@ void MemoryMap::remove(unsigned int index)
m_map[i] = m_map[i+1];
}
m_entries--;
}
void MemoryMap::simpleInsert(const MemoryRegion& region)
{
MemoryRegion newRegion(region);
unsigned int i = 0;
while(i < m_entries)
{
if(newRegion < m_map[i])
{
MemoryRegion buffer = newRegion;
newRegion = m_map[i];
m_map[i] = buffer;
}
i++;
}
m_map[i] = newRegion;
m_entries++;
}
void MemoryMap::simpleInsert(physaddr_t location, size_t size, unsigned int type)
{
simpleInsert(MemoryRegion(location, size, type));
}
unsigned int MemoryMap::trim(unsigned int index)
{
if(index + 1 >= m_entries)
return invalidIndex;
MemoryRegion& left = m_map[index];
MemoryRegion& right = m_map[index+1];
if(left.overlaps(right))
{
if(left.getType() == right.getType())
{
left = MemoryRegion(left.getLocation(),
(right.getEnd() > left.getEnd() ? right.getEnd() : left.getEnd()) - left.getLocation(),
left.getType());
remove(index + 1);
return index;
}
else if(left.getType() < right.getType())
{
if(right.contains(left))
{
remove(index);
return index;
}
else if(left.getEnd() <= right.getEnd())
{
left.truncateRight(right.getLocation());
return index + 1;
}
else
{
MemoryRegion newRight(right.getEnd(), left.getEnd() - right.getEnd(), left.getType());
left.truncateRight(right.getLocation());
if(left.getSize() == 0)
remove(index);
simpleInsert(newRight);
return index + 2;
}
}
else
{
if(left.contains(right))
{
remove(index + 1);
return index;
}
else
{
right.truncateLeft(left.getEnd());
return index + 1;
}
}
}
else if(left.bordersLeft(right) && left.getType() == right.getType())
{
left = MemoryRegion(left.getLocation(), right.getEnd() - left.getLocation(), left.getType());
remove(index + 1);
return index;
}
return index + 1;
}

View File

@@ -2,6 +2,7 @@
#define MEMORYMAP_H
#include "systypes.hpp"
#include "memoryregion.hpp"
namespace kernelns
{
@@ -9,90 +10,138 @@ namespace kernelns
class MemoryMap
{
public:
enum Type
{
AVAILABLE = 1,
UNAVAILABLE = 2,
ACPI = 3,
DEFECTIVE = 5
};
class Region
{
public:
Region();
Region(Region& copy);
Region(physaddr_t location, size_t size, Type type);
const Region& operator=(const Region& rhs);
const bool operator==(const Region& rhs) const;
const bool operator<(const Region& rhs) const;
const bool operator>(const Region& rhs) const;
const bool operator<=(const Region& rhs) const;
const bool operator>=(const Region& rhs) const;
physaddr_t getLocation() const;
size_t getSize() const;
Type getType() const;
physaddr_t getEnd() const;
bool contains(const Region& r) const;
bool contains(physaddr_t location, size_t size) const;
bool overlaps(const Region& r) const;
bool bordersLeft(const Region& right) const;
bool bordersRight(const Region& left) const;
bool borders(const Region& r) const;
void truncateLeft(physaddr_t left);
void truncateRight(physaddr_t right);
private:
physaddr_t m_location;
size_t m_size;
size_t m_type;
};
MemoryMap();
MemoryMap(MemoryMap& copy);
const Region& operator[](size_t index) const;
const MemoryRegion& operator[](size_t index) const;
/**
* @return The number of memory regions described by this object
*/
size_t size() const;
/**
* @brief Get the total amount of memory described by this memory map.
* Since no two regions may overlap, this is equivalent to the sum of the
* size of each memory region stored in this object.
*
* @return The total amount of memory described by this memory map.
*/
size_t totalMemory() const;
void insertEntry(physaddr_t location, size_t size, Type type);
/**
* @brief Get the total amount of memory of a specified type described by
* this memory map. Since no two regions overlap, this is equivalent to the
* sum of the size of each memory region stored in this object whose type
* is equal to `type`.
*
* @param type The type of memory region to count
* @return The total amount of memory of the specified type
*/
size_t totalMemory(unsigned int type) const;
/**
* @brief Checks if `region` overlaps any memory region contained in this
* memory map.
*
* @param region
* @return true if, for any region `k` in this map, `k.overlaps(region)`.
* @return false if there is no region in this map where `k.overlaps(region)`.
*/
bool overlaps(const MemoryRegion& region) const;
/**
* @brief Checks if `region` is contained an any memory region in this map
* with the same type as `region`.
*
* @param region
* @return true if, for any region `k` in this map, `k.contains(region)
* && k.getType() == region.getType()`.
* @return false if the condition above is not true
*/
bool contains(const MemoryRegion& region) const;
/**
* @brief Adds `region` into the memory map. Adjusts the map as necessary
* so that no regions overlap. Regions of higher type take precedence over
* regions with lower types; therefore, the lower typed regions are trimmed
* or deleted where they overlap with higher typed regions. Adjacent or
* overlapping regions with identical types are merged.
*
* @param region The memory region to insert
*/
void insertEntry(const MemoryRegion& region);
/**
* @brief Overload of `insertEntry()`. @see insertRegion(const MemoryRegion&).
*
* @param location
* @param size
* @param type
*/
void insertEntry(physaddr_t location, size_t size, unsigned int type);
private:
/**
* @brief Removes the element at `index` in `m_map`. All objects located
* after that index are moved accordingly.
*
* @param index Locatation of the object to delete
*/
void remove(unsigned int index);
/**
* @brief Inserts a copy of `region` into `m_map`. The new element is
* inserted such that `m_map` is sorted in ascending order. Overlapping
* elements are not trimmed.
*
* @param region The memory region to insert
*/
void simpleInsert(const MemoryRegion& region);
/**
* @brief Overload of `simpleInsert(const MemoryRegion& region)`.
*
* @param location
* @param size
* @param type
*/
void simpleInsert(physaddr_t location, size_t size, unsigned int type);
/**
* @brief If `m_map[index].overlaps(m_map[index+1])`, the two elements are
* modified so that they no longer overlap. The following rules apply:
*
* 1. This memory map will describe the same set of locations before and
* after performing this operation.
*
* 2. Adjacent regions of the same type are merged into a single region.
*
* 3. Where two regions of differing types overlap, the higher type takes
* precedence. The region of the lower type is truncated, split, or deleted
* so as to not overlap the region of the higher type.
*
* 4. This operation is local: only `m_map[index]` and `m_map[index+1]` are
* modified (although if a region must be split, a new region will be
* inserted at the location `index+2`).
*
* This function has no effect if `index+1 >= m_entries`, or if
* `m_map[index]` does not overlap the `m_map[index+1]`.
*
* @param index The location of the region to trim.
*
* @return The index of the rightmost region affected.
*/
unsigned int trim(unsigned int index);
static const unsigned int maxEntries = 16;
Region m_map[maxEntries];
static const unsigned int invalidIndex = 0xFFFF;
MemoryRegion m_map[maxEntries];
size_t m_entries;

128
src/memoryregion.cpp Normal file
View File

@@ -0,0 +1,128 @@
#include "memoryregion.hpp"
MemoryRegion::MemoryRegion()
{
m_location = 0;
m_size = 0;
m_type = 0;
}
MemoryRegion::MemoryRegion(const MemoryRegion& copy)
{
m_location = copy.m_location;
m_size = copy.m_size;
m_type = copy.m_type;
}
MemoryRegion::MemoryRegion(physaddr_t location, size_t size, unsigned int type)
{
m_location = location;
m_size = size;
m_type = (size_t) type;
}
const MemoryRegion& MemoryRegion::operator=(const MemoryRegion& rhs)
{
m_location = rhs.m_location;
m_size = rhs.m_size;
m_type = rhs.m_type;
return rhs;
}
bool MemoryRegion::operator==(const MemoryRegion& rhs) const
{
return (m_location == rhs.m_location) && (m_size == rhs.m_size);
}
bool MemoryRegion::operator!=(const MemoryRegion& rhs) const
{
return (m_location != rhs.m_location) || (m_size != rhs.m_size);
}
bool MemoryRegion::operator<(const MemoryRegion& rhs) const
{
return (m_location < rhs.m_location) || ((m_location == rhs.m_location) && (m_size < rhs.m_size));
}
bool MemoryRegion::operator>(const MemoryRegion& rhs) const
{
return (m_location > rhs.m_location) || ((m_location == rhs.m_location) && (m_size > rhs.m_size));
}
bool MemoryRegion::operator<=(const MemoryRegion& rhs) const
{
return (m_location < rhs.m_location) || ((m_location == rhs.m_location) && (m_size <= rhs.m_size));
}
bool MemoryRegion::operator>=(const MemoryRegion& rhs) const
{
return (m_location > rhs.m_location) || ((m_location == rhs.m_location) && (m_size >= rhs.m_size));
}
physaddr_t MemoryRegion::getLocation() const
{
return m_location;
}
size_t MemoryRegion::getSize() const
{
return m_size;
}
unsigned int MemoryRegion::getType() const
{
return m_type;
}
physaddr_t MemoryRegion::getEnd() const
{
return m_location + m_size;
}
bool MemoryRegion::contains(const MemoryRegion& r) const
{
return contains(r.m_location, r.m_size);
}
bool MemoryRegion::contains(physaddr_t location, size_t size) const
{
return (location >= m_location) &&
(location + size <= m_location + m_size);
}
bool MemoryRegion::overlaps(const MemoryRegion& r) const
{
if(r.m_location < m_location)
return r.m_location + r.m_size > m_location;
else
return r.m_location < getEnd();
}
bool MemoryRegion::bordersLeft(const MemoryRegion& right) const
{
return getEnd() == right.m_location;
}
bool MemoryRegion::bordersRight(const MemoryRegion& left) const
{
return m_location == left.m_location + left.m_size;
}
bool MemoryRegion::borders(const MemoryRegion& r) const
{
return bordersLeft(r) || bordersRight(r);
}
void MemoryRegion::truncateLeft(physaddr_t left)
{
m_size = getEnd() - left;
m_location = left;
}
void MemoryRegion::truncateRight(physaddr_t right)
{
if(right > m_location)
m_size = right - m_location;
else
m_size = 0;
}

87
src/memoryregion.hpp Normal file
View File

@@ -0,0 +1,87 @@
#ifndef MEMORYBLOCK_H
#define MEMORYBLOCK_H
#include "systypes.hpp"
class MemoryRegion
{
public:
MemoryRegion();
MemoryRegion(const MemoryRegion& copy);
MemoryRegion(physaddr_t location, size_t size, unsigned int type);
const MemoryRegion& operator=(const MemoryRegion& rhs);
/**
* @brief Tests whether this object describes the same region of memory
* as rhs, irrespective of type.
*
* @param rhs The object to compare to
* @return true if and only if the location and size of the two regions are equal
* @return false if the two regions have differing locations or differing sizes
*/
bool operator==(const MemoryRegion& rhs) const;
/**
* @brief Tests whether this object describes a different region of memory
* than rhs, irrespective of type.
*
* @param rhs The object to compare to
* @return true if the two regions have differing locations or differing sizes
* @return false if and only if the location and size of the two regions are equal
*/
bool operator!=(const MemoryRegion& rhs) const;
/**
* @brief
*
* @param rhs
* @return true
* @return false
*/
bool operator<(const MemoryRegion& rhs) const;
bool operator>(const MemoryRegion& rhs) const;
bool operator<=(const MemoryRegion& rhs) const;
bool operator>=(const MemoryRegion& rhs) const;
physaddr_t getLocation() const;
size_t getSize() const;
unsigned int getType() const;
physaddr_t getEnd() const;
bool contains(const MemoryRegion& r) const;
bool contains(physaddr_t location, size_t size) const;
bool overlaps(const MemoryRegion& r) const;
bool bordersLeft(const MemoryRegion& right) const;
bool bordersRight(const MemoryRegion& left) const;
bool borders(const MemoryRegion& r) const;
void truncateLeft(physaddr_t left);
void truncateRight(physaddr_t right);
private:
physaddr_t m_location;
size_t m_size;
unsigned int m_type;
};
#endif

11
src/memorytype.hpp Normal file
View File

@@ -0,0 +1,11 @@
#ifndef MEMORYTYPE_H
#define MEMORYTYPE_H
enum class MemoryType
{
Available = 1,
Unavailable = 2,
Defective = 3
};
#endif

38
src/message.cpp Normal file
View File

@@ -0,0 +1,38 @@
#include "message.hpp"
Message::Message()
{
m_sender = 0;
m_type = 0;
m_args[0] = 0;
m_args[1] = 0;
m_args[2] = 0;
}
Message::Message(const Message& copy)
{
m_sender = copy.m_sender;
m_type = copy.m_type;
m_args[0] = copy.m_args[0];
m_args[1] = copy.m_args[1];
m_args[2] = copy.m_args[2];
}
Message::Message(unsigned int sender, unsigned int type,
unsigned long arg1, unsigned long arg2, unsigned long arg3)
{
m_sender = sender;
m_type = type;
m_args[0] = arg1;
m_args[1] = arg2;
m_args[2] = arg3;
}
Message& Message::operator=(const Message& rhs)
{
m_sender = rhs.m_sender;
m_type = rhs.m_type;
m_args[0] = rhs.m_args[0];
m_args[1] = rhs.m_args[1];
m_args[2] = rhs.m_args[2];
}

59
src/message.hpp Normal file
View File

@@ -0,0 +1,59 @@
#ifndef MESSAGE_H
#define MESSAGE_H
struct Message
{
/**
* @brief Default constructor. Initializes all members to 0.
*
*/
Message();
/**
* @brief Copy constructor.
*
* @param copy
*/
Message(const Message& copy);
/**
* @brief Construct a new Message object.
*
* @param sender
* @param type
* @param arg1
* @param arg2
* @param arg3
*/
Message(unsigned int sender, unsigned int type,
unsigned long arg1, unsigned long arg2, unsigned long arg3);
/**
* @brief Copy the contents of `rhs` to this object.
*
* @param rhs
* @return Message&
*/
Message& operator=(const Message& rhs);
/**
* @brief PID of the process that generated this message.
*/
unsigned int m_sender;
/**
* @brief Context-specific parameter which indicates to the receiver how
* the arguments are to be interpreted.
*/
unsigned int m_type;
/**
* @brief Arguments of this message. The meaning of these values depend on
* context, as well as the values of `m_sender` and `m_type`.
*/
unsigned long m_args[3];
};
#endif

View File

@@ -1,7 +0,0 @@
#ifndef MMGR_H
#define MMGR_H
#include "mmap.hpp"
#include "pageallocator.hpp"
#endif

View File

@@ -1,6 +1,7 @@
#include "pageallocator.hpp"
#include "systypes.hpp"
#include "memorymap.hpp"
#include "memorytype.hpp"
#define roundUp(n, m) ((n % m == 0) ? n : (n + m - (n % m)))
@@ -44,7 +45,7 @@ kernelns::BuddyAllocator::BuddyAllocator(const kernelns::MemoryMap& memmap,
physaddr_t location = 0x100000;
for(size_t i = 0; i < memmap.size() && memmap[i].getSize() > 0; i++)
{
if(memmap[i].getType() != kernelns::MemoryMap::AVAILABLE)
if(memmap[i].getType() != (unsigned int) MemoryType::Available)
continue;
if(memmap[i].getLocation() > location)
location = roundUp(memmap[i].getLocation(), 4096);

View File

@@ -2,7 +2,8 @@
#define PROCESS_H
#include <stddef.h>
#include "map.hpp"
#include "message.hpp"
namespace kernelns
{
@@ -17,16 +18,35 @@ public:
Process();
unsigned int getID() const;
bool map(void* location, size_t size);
/**
* @brief If the specified region is mapped and does not overlap a shared
* or private block, or the kernel, removes that region from the process's
* internal memory map. If the specified region overlaps an unmapped region,
* a shared or private block, or the kernel, the object goes unmodified.
* This method does not affect the page tables in any way, only the process's
* internal bookkeeping.
*
* @param location
* @param size
* @return true if the memory map was sucessfully updated
* @return false if the memory map was not modified
*/
bool unmap(void* location, size_t size);
bool hasSharedBlock(unsigned int blockID) const;
bool hasPhysicalBlock(unsigned int blockID) const;
void pushMessage(Message* message);
Message* popMessage();
private:
Map<unsigned int, MemoryBlock&> m_sharedBlocks;
Map<unsigned int, MemoryBlock&> m_physicalBlocks;
};
}

18
src/sharedblock.hpp Normal file
View File

@@ -0,0 +1,18 @@
#ifndef SHAREDBLOCK_H
#define SHAREDBLOCK_H
#include "memoryregion.hpp"
class SharedBlock : public MemoryRegion
{
public:
unsigned int getFlags() const;
private:
unsigned int m_flags;
};
#endif

View File

@@ -1,17 +1,28 @@
#include "syscalls.hpp"
#include "kernel.hpp"
#include "memorytype.hpp"
int mmap(void* location, size_t length, int flags)
{
// TODO: check that the requested region does not overlap something important
if(kernel.getActiveProcess().map(location, length))
{
if(kernel.allocateRegion(location, length, flags))
return 0;
else if(kernel.getActiveProcess().unmap(location, length))
return 1;
kernel.terminateActiveProcess();
}
return kernel.allocateRegion(location, length, flags);
}
int munmap(void* location, size_t length)
{
// TODO: check that the requested region does not overlap something important
kernel.freeRegion(location, length);
return 0;
if(kernel.getActiveProcess().unmap(location, length))
{
kernel.freeRegion(location, length);
return 0;
}
return 1;
}
unsigned int createSharedBlock(void* location, size_t length, int flags)
@@ -19,7 +30,7 @@ unsigned int createSharedBlock(void* location, size_t length, int flags)
unsigned int blockID = kernel.createSharedBlock(length, flags);
if(blockID > 0)
{
const MemoryBlock& block = kernel.getSharedBlock(blockID);
const SharedBlock& block = kernel.getSharedBlock(blockID);
kernel.mapRegion(location, block.getLocation(), length, flags);
// TODO: add block to current process
// TODO: perform safety checks
@@ -29,8 +40,8 @@ unsigned int createSharedBlock(void* location, size_t length, int flags)
int aquireSharedBlock(void* location, unsigned int id)
{
const MemoryBlock& block = kernel.getSharedBlock(id);
kernel.mapRegion(location, block.getLocation(), block.getSize(), block.getAttributes());
const SharedBlock& block = kernel.getSharedBlock(id);
kernel.mapRegion(location, block.getLocation(), block.getSize(), block.getFlags());
// TODO: (somehow) handle invalid ids -- possibly hard while using references
// TODO: add block to current process
// TODO: perform safety checks
@@ -59,4 +70,24 @@ int aquirePhysicalBlock(void* location, physaddr_t physicalAddress, size_t lengt
int releasePhysicalBlock(int id)
{
return 0;
}
int sendMessage(unsigned int recipient, const Message* message)
{
Message* copy = new Message(*message);
copy->m_sender = kernel.getActiveProcess().getID();
kernel.getProcess(recipient).pushMessage(copy);
return 0;
}
int receiveMessage(Message* buffer)
{
if(buffer == nullptr)
return 1;
Message* message = kernel.getActiveProcess().popMessage();
if(message == nullptr)
return 1;
*buffer = *message;
delete message;
return 0;
}

View File

@@ -3,6 +3,7 @@
#include <stddef.h>
#include "systypes.hpp"
#include "message.hpp"
int mmap(void* location, size_t length, int flags);
@@ -20,4 +21,8 @@ int aquirePhysicalBlock(void* location, physaddr_t physicalAddress, size_t lengt
int releasePhysicalBlock(int id);
int sendMessage(unsigned int recipient, const Message* message);
int receiveMessage(Message* buffer);
#endif

View File

@@ -1,25 +0,0 @@
#include "systeminfo.hpp"
#include "util.hpp"
using namespace kernelns;
SystemInfo::SystemInfo()
{
}
SystemInfo::SystemInfo(MemoryMap& memoryMap, const char* commandLine)
: m_memmap(memoryMap)
{
strcpy(this->commandLine, commandLine);
}
const MemoryMap& SystemInfo::getMemoryMap() const
{
return m_memmap;
}
const char* SystemInfo::getCommandLine() const
{
return commandLine;
}

View File

@@ -1,34 +0,0 @@
#ifndef SYSTEMINFO_H
#define SYSTEMINFO_H
#include <stddef.h>
#include "systypes.hpp"
#include "memorymap.hpp"
namespace kernelns
{
class SystemInfo
{
public:
SystemInfo();
SystemInfo(MemoryMap& memoryMap, const char* commandLine);
const MemoryMap& getMemoryMap() const;
const char* getCommandLine() const;
private:
MemoryMap m_memmap;
char commandLine[128];
};
}
#endif

View File

@@ -1,7 +1,7 @@
#include <stdint.h>
#include "util.hpp"
#include "kernelstate.hpp"
#include "kernel.hpp"
void* memcpy(void* destination, const void* source, size_t num)
{
@@ -112,25 +112,31 @@ char* strcpy(char* destination, const char* source)
void* malloc(size_t size)
{
return kernelns::State::allocator.allocate(size);
return kernel.malloc(size);
}
void* calloc(size_t count, size_t size)
{
return memset(malloc(count * size), 0, count * size);
void* ptr = malloc(count * size);
if(ptr != nullptr)
memset(malloc(count * size), 0, count * size);
return ptr;
}
void* realloc(void* ptr, size_t size)
{
void* n = kernelns::State::allocator.allocate(size);
memmove(n, ptr, size);
free(ptr);
void* n = kernel.malloc(size);
if(n != nullptr)
{
memmove(n, ptr, size);
free(ptr);
}
return n;
}
void free(void* p)
{
kernelns::State::allocator.free(p);
kernel.free(p);
}
void __cxa_pure_virtual()

View File

@@ -1,30 +1,14 @@
#include <stdint.h>
#include "multiboot2.hpp"
#include "tty.hpp"
#include "../kernelstate.hpp"
#include "../systeminfo.hpp"
#include "../mmap.hpp"
#include "../util.hpp"
#include "../memorytype.hpp"
using namespace kernelns;
extern int _kernelEnd;
enum BootInfoType
{
Terminate = 0,
CommandLine = 1,
BootLoader = 2,
Module = 3,
MemoryInfo = 4,
BootDevice = 5,
MMap = 6,
VBEInfo = 7,
FramebufferInfo = 8,
ELFSymbols = 9,
APMTable = 10
};
extern "C"
int startPaging(uint32_t* directory, uint32_t* table, uint32_t* identityTable)
{
@@ -57,12 +41,12 @@ int initialize(void* multibootInfo)
for(; heapSize > 1; log++)
heapSize >>= 1;
heapSize <<= log;
new(&State::allocator) Allocator((void*) (0xFFC00000 - heapSize), heapSize, 64);
//new(&State::allocator) Allocator((void*) (0xFFC00000 - heapSize), heapSize, 64);
Multiboot2Info bootInfo(multibootInfo);
if(!bootInfo.isValid())
return 1;
bootInfo.getMemoryMap().insertEntry(0, 4 * 1024 * 1024, MemoryMap::UNAVAILABLE);
new(&State::config) SystemInfo(bootInfo.getMemoryMap(), bootInfo.getCommandLine());
bootInfo.getMemoryMap().insertEntry(0, 4 * 1024 * 1024, (unsigned int) MemoryType::Unavailable);
//new(&State::config) SystemInfo(bootInfo.getMemoryMap(), bootInfo.getCommandLine());
TTY tty((char*) 0xFF8B8000);
tty << "Type\t\tLocation\t\tSize\n";
for(size_t i = 0; i < bootInfo.getMemoryMap().size() && bootInfo.getMemoryMap()[i].getSize() > 0; i++)

View File

@@ -0,0 +1,31 @@
#include "memorymanagerx86.hpp"
unsigned int MemoryManagerx86::getPageSize() const
{
return pageSize;
}
physaddr_t MemoryManagerx86::createAddressSpace()
{
if(((size_t) table & 0xFFF) != 0)
return -1;
PageTableEntry* newDirectory = (PageTableEntry*) table;
newDirectory[1022] = m_pageDirectory[1022];
newDirectory[1023] = m_pageDirectory[1023];
return 0;
}
void MemoryManagerx86::loadAddressSpace(physaddr_t table)
{
}
int MemoryManagerx86::mapPage(void *page, physaddr_t frame, int flags)
{
}
physaddr_t MemoryManagerx86::unmapPage(void *page)
{
}

View File

@@ -0,0 +1,29 @@
#ifndef MEMORYMANAGERX86_H
#define MEMORYMANAGERX86_H
#include "../memorymanager.hpp"
#include "pagetableentry.hpp"
class MemoryManagerx86 : public MemoryManager
{
public:
virtual unsigned int getPageSize() const;
virtual physaddr_t createAddressSpace();
virtual void loadAddressSpace(physaddr_t table);
virtual int mapPage(void* page, physaddr_t frame, int flags);
virtual physaddr_t unmapPage(void* page);
private:
static const unsigned int pageSize = 4096;
PageTableEntry *m_pageTables, *m_pageDirectory;
};
#endif

View File

@@ -1,4 +1,5 @@
#include "multiboot2.hpp"
#include "../memorytype.hpp"
using namespace kernelns;
@@ -11,31 +12,35 @@ Multiboot2Info::Multiboot2Info(void* tableLocation)
ptr += 2;
while(*ptr != 0)
{
if(*ptr == T_BootCommand)
if(*ptr == (uint32_t) Tag::BootCommand)
{
m_commandLine = &reinterpret_cast<TagString*>(ptr)->str;
}
else if(*ptr == T_Bootloader)
else if(*ptr == (uint32_t) Tag::Bootloader)
{
m_bootloader = &reinterpret_cast<TagString*>(ptr)->str;
}
else if(*ptr == T_MemoryMap)
else if(*ptr == (uint32_t) Tag::MemoryMap)
{
unsigned int tagSize = reinterpret_cast<TagMemoryMap*>(ptr)->size - 16;
unsigned int entrySize = reinterpret_cast<TagMemoryMap*>(ptr)->entrySize;
MemoryMapEntry* entry = &reinterpret_cast<TagMemoryMap*>(ptr)->entries;
while(tagSize > 0)
{
m_memmap.insertEntry(entry->base, entry->length, (MemoryMap::Type) entry->type);
unsigned int regionType =
(entry->type == (unsigned int) Multiboot2MemoryType::Available) ? (unsigned int) MemoryType::Available
: ((entry->type == (unsigned int) Multiboot2MemoryType::Defective) ? (unsigned int) MemoryType::Defective
: (unsigned int) MemoryType::Unavailable);
m_memmap.insertEntry(entry->base, entry->length, entry->type);
entry = (MemoryMapEntry*) (reinterpret_cast<char*>(entry) + entrySize);
tagSize -= entrySize;
}
}
else if(*ptr == T_Module)
else if(*ptr == (uint32_t) Tag::Module)
{
TagModule* moduleTag = reinterpret_cast<TagModule*>(ptr);
m_modules[m_moduleCount] = Module(moduleTag->start, moduleTag->end, &moduleTag->str);
m_memmap.insertEntry(moduleTag->start, moduleTag->end - moduleTag->start, MemoryMap::UNAVAILABLE);
m_memmap.insertEntry(moduleTag->start, moduleTag->end - moduleTag->start, (unsigned int) MemoryType::Unavailable);
}
unsigned int size = (ptr[1] + 7) - ((ptr[1] + 7) % 8);
ptr += size / sizeof(uint32_t);

View File

@@ -11,29 +11,36 @@ class Multiboot2Info
{
public:
enum TagType
enum class Tag
{
T_BootCommand = 1,
T_Bootloader = 2,
T_Module = 3,
T_MemoryInfo = 4,
T_BIOSBootDevice = 5,
T_MemoryMap = 6,
T_VBE = 7,
T_Framebuffer = 8,
T_ELFSymbols = 9,
T_APM = 10,
T_EFI32SystemTable = 11,
T_EFI64SystemTable = 12,
T_SMBIOS = 13,
T_ACPI10RSDP = 14,
T_ACPT20RSDP = 15,
T_Network = 16,
T_EFIMemoryMap = 17,
T_EFIBootServices = 18,
T_EFI32Image = 19,
T_EFI64Image = 20,
T_LoadAddress = 21
BootCommand = 1,
Bootloader = 2,
Module = 3,
MemoryInfo = 4,
BIOSBootDevice = 5,
MemoryMap = 6,
VBE = 7,
Framebuffer = 8,
ELFSymbols = 9,
APM = 10,
EFI32SystemTable = 11,
EFI64SystemTable = 12,
SMBIOS = 13,
ACPI10RSDP = 14,
ACPT20RSDP = 15,
Network = 16,
EFIMemoryMap = 17,
EFIBootServices = 18,
EFI32Image = 19,
EFI64Image = 20,
LoadAddress = 21
};
enum class Multiboot2MemoryType
{
Available = 1,
ACPI = 3,
Defective = 5
};
struct TagString

132
src/x86/pagetableentry.cpp Normal file
View File

@@ -0,0 +1,132 @@
#include "pagetableentry.hpp"
PageTableEntry::PageTableEntry()
{
this->present = 0;
this->rw = 0;
this->usermode = 0;
this->writeThrough = 0;
this->cacheDisable = 0;
this->accessed = 0;
this->dirty = 0;
this->pat = 0;
this->global = 0;
this->shared = 0;
this->ignored = 0;
this->physicalAddress = 0;
}
bool PageTableEntry::getAccessed() const
{
return accessed == 1;
}
bool PageTableEntry::getCacheDisable() const
{
return cacheDisable == 1;
}
void PageTableEntry::setCacheDisable(bool cacheDisable)
{
this->cacheDisable = cacheDisable ? 1 : 0;
}
bool PageTableEntry::getDirty() const
{
return dirty == 1;
}
bool PageTableEntry::getGlobal() const
{
return global == 1;
}
void PageTableEntry::setGlobal(bool global)
{
this->global = global ? 1 : 0;
}
bool PageTableEntry::getPat() const
{
return pat == 1;
}
void PageTableEntry::setPat(bool pat)
{
this->pat = pat ? 1 : 0;
}
physaddr_t PageTableEntry::getPhysicalAddress() const
{
physaddr_t physicalAddress = this->physicalAddress;
return physicalAddress << 12;
}
physaddr_t PageTableEntry::setPhysicalAddress(physaddr_t physicalAddress)
{
this->physicalAddress = physicalAddress >> 12;
return this->physicalAddress << 12;
}
bool PageTableEntry::getPresent() const
{
return present == 1;
}
void PageTableEntry::setPresent(bool present)
{
this->present = present ? 1 : 0;
}
bool PageTableEntry::getRw() const
{
return rw == 1;
}
void PageTableEntry::setRw(bool rw)
{
this->rw = rw ? 1 : 0;
}
bool PageTableEntry::getShared() const
{
return shared == 1;
}
void PageTableEntry::setShared(bool shared)
{
this->shared = shared ? 1 : 0;
}
bool PageTableEntry::getUsermode() const
{
return usermode == 1;
}
void PageTableEntry::setUsermode(bool usermode)
{
this->usermode = usermode ? 1 : 0;
}
bool PageTableEntry::getWriteThrough() const
{
return writeThrough == 1;
}
void PageTableEntry::setWriteThrough(bool writeThrough)
{
this->writeThrough = writeThrough ? 1 : 0;
}
physaddr_t PageTableEntry::operator=(physaddr_t rhs)
{
return setPhysicalAddress(rhs);
}
PageTableEntry PageTableEntry::operator=(PageTableEntry rhs)
{
uint32_t *iThis = (uint32_t *)this;
uint32_t *iThat = (uint32_t *)&rhs;
*iThis = *iThat;
return rhs;
}

View File

@@ -0,0 +1,83 @@
#ifndef PAGETABLEENTRY_H
#define PAGETABLEENTRY_H
#include "../systypes.hpp"
class PageTableEntry {
public:
PageTableEntry();
bool getAccessed() const;
bool getCacheDisable() const;
void setCacheDisable(bool cacheDisable);
bool getDirty() const;
bool getGlobal() const;
void setGlobal(bool global);
bool getPat() const;
void setPat(bool pat);
physaddr_t getPhysicalAddress() const;
physaddr_t setPhysicalAddress(physaddr_t physicalAddress);
bool getPresent() const;
void setPresent(bool present);
bool getRw() const;
void setRw(bool rw);
bool getShared() const;
void setShared(bool shared);
bool getUsermode() const;
void setUsermode(bool usermode);
bool getWriteThrough() const;
void setWriteThrough(bool writeThrough);
physaddr_t operator=(physaddr_t rhs);
PageTableEntry operator=(PageTableEntry rhs);
private:
uint32_t present : 1;
uint32_t rw : 1;
uint32_t usermode : 1;
uint32_t writeThrough : 1;
uint32_t cacheDisable : 1;
uint32_t accessed : 1;
uint32_t dirty : 1;
uint32_t pat : 1;
uint32_t global : 1;
uint32_t shared : 1;
uint32_t ignored : 2;
uint32_t physicalAddress : 20;
};
#endif