Initial commit
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
bin/qkernel
|
||||||
|
bin/*.o
|
||||||
|
bin/*~
|
||||||
16
src/Makefile
Normal file
16
src/Makefile
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
objs = math.o cstring.o error.o pagetableentry.o physicalmemoryallocator.o multiboot2header.o entry.o quarkkernel.o
|
||||||
|
link_script = linker.ld
|
||||||
|
quark_bin = qkernel
|
||||||
|
|
||||||
|
CXX = i686-elf-g++
|
||||||
|
CC = i686-elf-gcc
|
||||||
|
|
||||||
|
CPPFLAGS += -ffreestanding -O2 -Wall -Wextra -fno-exceptions -fno-rtti
|
||||||
|
|
||||||
|
all: $(objs)
|
||||||
|
echo $(PATH)
|
||||||
|
i686-elf-g++ -o $(quark_bin) -T $(link_script) -ffreestanding -nostdlib -O2 $(objs) -lgcc
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm *.o
|
||||||
|
rm -f $(quark_bin)
|
||||||
609
src/bitmap.h
Normal file
609
src/bitmap.h
Normal file
@@ -0,0 +1,609 @@
|
|||||||
|
/*
|
||||||
|
* Bitmap.h
|
||||||
|
*
|
||||||
|
* Created on: Jun 1, 2019
|
||||||
|
* Author: nathan
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRC_BITMAP_H_
|
||||||
|
#define SRC_BITMAP_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
namespace qkernel {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a fixed array of N bits. Somewhat analogous to std::bitset. Can
|
||||||
|
* be manipulated using standard arithmetic operators (&, |, ^, ~).
|
||||||
|
*/
|
||||||
|
template <size_t N>
|
||||||
|
class Bitmap {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A proxy object used to reference an individual bit contained in a Bitmap object.
|
||||||
|
*/
|
||||||
|
class Reference
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a reference to a bit contained in a Bitmap object.
|
||||||
|
*
|
||||||
|
* @param data A reference to the byte in which the referenced bit is
|
||||||
|
* contained
|
||||||
|
* @param position The position of the referenced bit inside 'data.' 0
|
||||||
|
* denotes the least significant bit; 7 denoted the most significant
|
||||||
|
* bit.
|
||||||
|
*/
|
||||||
|
Reference(uint8_t& data, size_t position);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the bit referenced by this object to 'b'
|
||||||
|
*
|
||||||
|
* @returns a reference to this object
|
||||||
|
*/
|
||||||
|
Reference& operator=(const bool b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the bit referenced by this object to the value of the bit
|
||||||
|
* referenced by 'r.'
|
||||||
|
*
|
||||||
|
* @returns a reference to this object
|
||||||
|
*/
|
||||||
|
Reference& operator=(const Reference& r);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns the inverse of the value of the bit referenced by this
|
||||||
|
* object.
|
||||||
|
*/
|
||||||
|
bool operator~() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the bit referenced by this object to a boolean, whose value
|
||||||
|
* is 'true' if the bit referenced it set, and false if it is clear.
|
||||||
|
*/
|
||||||
|
operator bool() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
uint8_t& data;
|
||||||
|
|
||||||
|
size_t position;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a bitmap containing 'N' bits, containing uninitialized
|
||||||
|
* data.
|
||||||
|
*/
|
||||||
|
Bitmap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a bitmap containing 'N' bits, copying data from 'bitmap' into
|
||||||
|
* the new object.
|
||||||
|
*/
|
||||||
|
Bitmap(const Bitmap<N>& bitmap);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a bitmap containing 'N' bits, initializing each bit to 'v.'
|
||||||
|
*/
|
||||||
|
Bitmap(const bool value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a bitmap containing 'N' bits, initializing the first 32 bits
|
||||||
|
* to the bits contained in 'value.' If the bitmap contains more than 32
|
||||||
|
* bits, the rest are initialized to 0.
|
||||||
|
*/
|
||||||
|
Bitmap(const uint8_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a bitmap containing 'N' bits, initializing the first 32 bits
|
||||||
|
* to the bits contained in 'value.' If the bitmap contains more than 32
|
||||||
|
* bits, the rest are initialized to 0.
|
||||||
|
*/
|
||||||
|
Bitmap(const uint16_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a bitmap containing 'N' bits, initializing the first 32 bits
|
||||||
|
* to the bits contained in 'value.' If the bitmap contains more than 32
|
||||||
|
* bits, the rest are initialized to 0.
|
||||||
|
*/
|
||||||
|
Bitmap(const uint32_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns the number of bits stored in this bitmap
|
||||||
|
*/
|
||||||
|
size_t size();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns the number of bits that are set
|
||||||
|
*/
|
||||||
|
size_t count();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns true if all bits are set; otherwise false.
|
||||||
|
*/
|
||||||
|
bool all();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns true if at least one bit is set; otherwise false.
|
||||||
|
*/
|
||||||
|
bool any();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns true if all bits are cleared; otherwise false.
|
||||||
|
*/
|
||||||
|
bool none();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets all bits in this bitmap.
|
||||||
|
*
|
||||||
|
* @returns a reference to this bitmap
|
||||||
|
*/
|
||||||
|
Bitmap<N>& set();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears all bits in this bitmap.
|
||||||
|
*
|
||||||
|
* @returns a reference to this bitmap
|
||||||
|
*/
|
||||||
|
Bitmap<N>& clear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares the contents of 'bitmap' and this bitmap.
|
||||||
|
*
|
||||||
|
* @param bitmap The bitmap to compare this object to.
|
||||||
|
*
|
||||||
|
* @returns true only if each bit in 'other' is equal to each bit in this
|
||||||
|
* bitmap; otherwise false.
|
||||||
|
*/
|
||||||
|
bool operator==(const Bitmap<N>& other) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares the contents of 'bitmap' and this bitmap.
|
||||||
|
*
|
||||||
|
* @param bitmap The bitmap to compare this object to.
|
||||||
|
*
|
||||||
|
* @returns false only if each bit in 'other' is equal to each bit in this
|
||||||
|
* bitmap; otherwise true.
|
||||||
|
*/
|
||||||
|
bool operator!=(const Bitmap<N>& other) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accesses the bit at 'index.' Does not perform bounds checking;
|
||||||
|
* out-of-bounds access will result in problems.
|
||||||
|
*
|
||||||
|
* @param index The position in the bitmap to access
|
||||||
|
*
|
||||||
|
* @returns a reference to the bit at 'index'
|
||||||
|
*/
|
||||||
|
Reference operator[](const size_t index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accesses the bit at 'index.' Does not perform bounds checking;
|
||||||
|
* out-of-bounds access will result in problems.
|
||||||
|
*
|
||||||
|
* @param index The position in the bitmap to access
|
||||||
|
*
|
||||||
|
* @returns the value of the bit at position 'index'
|
||||||
|
*/
|
||||||
|
bool operator[](const size_t index) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns a bitmap containing the bitwise AND of this bitmap and 'other.'
|
||||||
|
*/
|
||||||
|
Bitmap<N> operator&(const Bitmap<N>& other) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value of this bitmap to the bitwise AND of this bitmap and
|
||||||
|
* 'other.'
|
||||||
|
*
|
||||||
|
* @returns a reference to this bitmap
|
||||||
|
*/
|
||||||
|
Bitmap<N>& operator&=(const Bitmap<N>& other);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns a bitmap containing the bitwise OR of this bitmap and 'other.'
|
||||||
|
*/
|
||||||
|
Bitmap<N> operator|(const Bitmap<N>& other) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value of this bitmap to the bitwise OR of this bitmap and
|
||||||
|
* 'other.'
|
||||||
|
*
|
||||||
|
* @returns a reference to this bitmap
|
||||||
|
*/
|
||||||
|
Bitmap<N>& operator|=(const Bitmap<N>& other);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns a bitmap containing the bitwise XOR of this bitmap and 'other.'
|
||||||
|
*/
|
||||||
|
Bitmap<N> operator^(const Bitmap<N>& other) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value of this bitmap to the bitwise OR of this bitmap and
|
||||||
|
* 'other.'
|
||||||
|
*
|
||||||
|
* @returns a reference to this bitmap
|
||||||
|
*/
|
||||||
|
Bitmap<N>& operator^=(const Bitmap<N>& other);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shifts this bitmap 'n' bits left.
|
||||||
|
*
|
||||||
|
* @returns a new Bitmap containing the result
|
||||||
|
*/
|
||||||
|
Bitmap<N> operator<<(const size_t n) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shifts this bitmap 'n' bits left.
|
||||||
|
*
|
||||||
|
* @returns a reference to this bitmap
|
||||||
|
*/
|
||||||
|
Bitmap<N>& operator<<=(const size_t n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shifts this bitmap 'n' bits right.
|
||||||
|
*
|
||||||
|
* @returns a new Bitmap containing the result
|
||||||
|
*/
|
||||||
|
Bitmap<N> operator>>(const size_t n) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shifts the bitmap 'n' bits right.
|
||||||
|
*
|
||||||
|
* @returns a reference to this bitmap
|
||||||
|
*/
|
||||||
|
Bitmap<N>& operator>>=(const size_t n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the bitwise NOT of this bitmap
|
||||||
|
*
|
||||||
|
* @returns a new bitmap containing the result
|
||||||
|
*/
|
||||||
|
Bitmap<N> operator~() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
uint8_t data[(N / 8) + 1];
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace qkernel */
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline qkernel::Bitmap<N>::Reference::Reference(uint8_t& data, size_t position)
|
||||||
|
: data(data)
|
||||||
|
{
|
||||||
|
this->position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline typename qkernel::Bitmap<N>::Reference& qkernel::Bitmap<N>::Reference::operator =(const bool b) {
|
||||||
|
if(b)
|
||||||
|
{
|
||||||
|
data |= 1 << position;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data &= ~(1 << position);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline typename qkernel::Bitmap<N>::Reference& qkernel::Bitmap<N>::Reference::operator =(const Reference& r) {
|
||||||
|
if((bool) r)
|
||||||
|
{
|
||||||
|
data |= 1 << position;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data &= ~(1 << position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline bool qkernel::Bitmap<N>::Reference::operator ~() const {
|
||||||
|
return !((bool) (*this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline qkernel::Bitmap<N>::Reference::operator bool() const {
|
||||||
|
uint8_t value = data & (1 << position);
|
||||||
|
if((data & (1 << position)) != 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline qkernel::Bitmap<N>::Bitmap() {
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline qkernel::Bitmap<N>::Bitmap(const Bitmap<N>& bitmap) {
|
||||||
|
for(size_t i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
(*this)[i] = bitmap[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline qkernel::Bitmap<N>::Bitmap(const bool value) {
|
||||||
|
for(size_t i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
(*this)[i] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline qkernel::Bitmap<N>::Bitmap(uint8_t value) {
|
||||||
|
size_t max = N >= 8 ? 8 : N;
|
||||||
|
for(size_t i = 0; i < max; i++)
|
||||||
|
{
|
||||||
|
(*this)[i] = value & 1;
|
||||||
|
value >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline qkernel::Bitmap<N>::Bitmap(uint16_t value) {
|
||||||
|
size_t max = N >= 16 ? 16 : N;
|
||||||
|
for(size_t i = 0; i < max; i++)
|
||||||
|
{
|
||||||
|
(*this)[i] = value & 1;
|
||||||
|
value >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline qkernel::Bitmap<N>::Bitmap(uint32_t value) {
|
||||||
|
size_t max = N >= 32 ? 32 : N;
|
||||||
|
for(size_t i = 0; i < max; i++)
|
||||||
|
{
|
||||||
|
(*this)[i] = value & 1;
|
||||||
|
value >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline size_t qkernel::Bitmap<N>::size() {
|
||||||
|
return N;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline size_t qkernel::Bitmap<N>::count() {
|
||||||
|
size_t count = 0;
|
||||||
|
for(size_t i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
if((*this)[i] == true)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline bool qkernel::Bitmap<N>::all() {
|
||||||
|
for(size_t i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
if((*this)[i] == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline bool qkernel::Bitmap<N>::any() {
|
||||||
|
for(size_t i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
if((*this)[i] == true)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline bool qkernel::Bitmap<N>::none() {
|
||||||
|
for(size_t i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
if((*this)[i] == true)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline qkernel::Bitmap<N>& qkernel::Bitmap<N>::set() {
|
||||||
|
for(size_t i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
(*this)[i] = true;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline qkernel::Bitmap<N>& qkernel::Bitmap<N>::clear() {
|
||||||
|
for(size_t i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
(*this)[i] = false;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline bool qkernel::Bitmap<N>::operator ==(const Bitmap<N>& other) const {
|
||||||
|
for(size_t i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
if((*this)[i] != other[i])
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline bool qkernel::Bitmap<N>::operator !=(const Bitmap<N>& other) const {
|
||||||
|
return !((*this) == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline typename qkernel::Bitmap<N>::Reference qkernel::Bitmap<N>::operator [](const size_t index) {
|
||||||
|
return Reference(data[index / 8], index % 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline bool qkernel::Bitmap<N>::operator [](const size_t index) const {
|
||||||
|
return (data[index/8] & (1 << (index % 8))) == 0 ? false : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline qkernel::Bitmap<N> qkernel::Bitmap<N>::operator &(const Bitmap<N>& other) const {
|
||||||
|
Bitmap<N> result;
|
||||||
|
for(size_t i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
result[i] = (*this)[i] && other[i];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline qkernel::Bitmap<N>& qkernel::Bitmap<N>::operator &=(const Bitmap<N>& other) {
|
||||||
|
for(size_t i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
(*this)[i] = (*this)[i] && other[i];
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline qkernel::Bitmap<N> qkernel::Bitmap<N>::operator |(const Bitmap<N>& other) const {
|
||||||
|
Bitmap<N> result;
|
||||||
|
for(size_t i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
result[i] = (*this)[i] || other[i];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline qkernel::Bitmap<N>& qkernel::Bitmap<N>::operator |=(const Bitmap<N>& other) {
|
||||||
|
for(size_t i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
(*this)[i] = (*this)[i] || other[i];
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline qkernel::Bitmap<N> qkernel::Bitmap<N>::operator ^(const Bitmap<N>& other) const {
|
||||||
|
Bitmap<N> result;
|
||||||
|
for(size_t i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
result[i] = (*this)[i] ^ other[i];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline qkernel::Bitmap<N>& qkernel::Bitmap<N>::operator ^=(const Bitmap<N>& other) {
|
||||||
|
for(size_t i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
(*this)[i] = (*this)[i] ^ other[i];
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline qkernel::Bitmap<N> qkernel::Bitmap<N>::operator <<(const size_t n) const {
|
||||||
|
Bitmap<N> result;
|
||||||
|
for(size_t i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
if(i < n)
|
||||||
|
{
|
||||||
|
result[i] = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result[i] = (*this)[i-n];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline qkernel::Bitmap<N>& qkernel::Bitmap<N>::operator <<=(const size_t n) {
|
||||||
|
for(size_t i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
if(i == 0)
|
||||||
|
{
|
||||||
|
(*this)[i] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(*this)[i] = (*this)[i-1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline qkernel::Bitmap<N> qkernel::Bitmap<N>::operator >>(const size_t n) const {
|
||||||
|
Bitmap<N> result;
|
||||||
|
for(size_t i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
if(i > N - n)
|
||||||
|
{
|
||||||
|
result[i] = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result[i] = (*this)[i+n];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline qkernel::Bitmap<N>& qkernel::Bitmap<N>::operator >>=(const size_t n) {
|
||||||
|
for(size_t i = N - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if(i == N - 1)
|
||||||
|
{
|
||||||
|
(*this)[i] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(*this)[i] = (*this)[i+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline qkernel::Bitmap<N> qkernel::Bitmap<N>::operator ~() const {
|
||||||
|
Bitmap<N> result;
|
||||||
|
for(size_t i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
result[i] = !(*this)[i];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SRC_BITMAP_H_ */
|
||||||
85
src/cstring.cpp
Normal file
85
src/cstring.cpp
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* cstring.cpp
|
||||||
|
*
|
||||||
|
* Created on: Jun 13, 2019
|
||||||
|
* Author: nathan
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "cstring.h"
|
||||||
|
|
||||||
|
void* memcpy(void* destination, const void* source, size_t num)
|
||||||
|
{
|
||||||
|
if(num > 0)
|
||||||
|
{
|
||||||
|
const uint8_t* src = (const uint8_t*) source;
|
||||||
|
uint8_t* dest = (uint8_t*) destination;
|
||||||
|
for(size_t i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
dest[i] = src[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There are four distinct cases here:
|
||||||
|
* 1. destination and source blocks do not overlap
|
||||||
|
* 2. destination and source are the same
|
||||||
|
* 3. destination and source do overlap; destination starts before source
|
||||||
|
* 4. destination and source do overlap; destination starts after source
|
||||||
|
*
|
||||||
|
* Memcpy results in expected behavior in all cases except for case 4. In that
|
||||||
|
* case, copying must be done backwards to avoid reading from bytes that have
|
||||||
|
* already been overwritten.
|
||||||
|
*/
|
||||||
|
void* memmove(void* destination, const void* source, size_t num)
|
||||||
|
{
|
||||||
|
if(num > 0)
|
||||||
|
{
|
||||||
|
if(((size_t) destination) < ((size_t) source) || ((size_t) destination) >= (((size_t) source)) + num)
|
||||||
|
{
|
||||||
|
return memcpy(destination, source, num);
|
||||||
|
}
|
||||||
|
else if(destination != source)
|
||||||
|
{
|
||||||
|
size_t i = num - 1;
|
||||||
|
const uint8_t* src = (const uint8_t*) source;
|
||||||
|
uint8_t* dest = (uint8_t*) destination;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
dest[i] = src[i];
|
||||||
|
i--;
|
||||||
|
} while(i != 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
int memcmp(const void* ptr1, const void* ptr2, size_t num)
|
||||||
|
{
|
||||||
|
const uint8_t* a = (const uint8_t*) ptr1;
|
||||||
|
const uint8_t* b = (const uint8_t*) ptr2;
|
||||||
|
for(size_t i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
if(a[i] < b[i])
|
||||||
|
return -1;
|
||||||
|
else if(a[i] > b[i])
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* memset (void* ptr, int value, size_t num)
|
||||||
|
{
|
||||||
|
uint8_t* dest = (uint8_t*) ptr;
|
||||||
|
uint8_t v = (uint8_t) value;
|
||||||
|
for(size_t i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
dest[i] = v;
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
26
src/cstring.h
Normal file
26
src/cstring.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* cstring.h
|
||||||
|
*
|
||||||
|
* Created on: Jun 13, 2019
|
||||||
|
* Author: nathan
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRC_CSTRING_H_
|
||||||
|
#define SRC_CSTRING_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
|
||||||
|
void* memcpy(void* destination, const void* source, size_t num);
|
||||||
|
|
||||||
|
void* memmove(void* destination, const void* source, size_t num);
|
||||||
|
|
||||||
|
int memcmp(const void* ptr1, const void* ptr2, size_t num);
|
||||||
|
|
||||||
|
void* memset (void* ptr, int value, size_t num);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SRC_CSTRING_H_ */
|
||||||
71
src/entry.S
Normal file
71
src/entry.S
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
.section .multiboot
|
||||||
|
.include "multiboot2header.S"
|
||||||
|
|
||||||
|
.section .bss
|
||||||
|
|
||||||
|
.align 16
|
||||||
|
stackBottom:
|
||||||
|
.skip 16384
|
||||||
|
stackTop:
|
||||||
|
|
||||||
|
.align 4096
|
||||||
|
_tempPgDir:
|
||||||
|
.skip 4096
|
||||||
|
_tempIdentityMap:
|
||||||
|
.skip 4096
|
||||||
|
_tempPgTable:
|
||||||
|
.skip 4096
|
||||||
|
|
||||||
|
.section .text
|
||||||
|
.global _start
|
||||||
|
.type _start, @function
|
||||||
|
_start:
|
||||||
|
cmp $0x36d76289, %eax
|
||||||
|
jne _err
|
||||||
|
|
||||||
|
movb $64, 0xB8000
|
||||||
|
|
||||||
|
mov $0, %ecx
|
||||||
|
1: mov %ecx, %eax
|
||||||
|
mov $4096, %edx
|
||||||
|
mul %edx
|
||||||
|
add $PHYSICAL_BASE, %eax
|
||||||
|
or $3, %eax
|
||||||
|
mov $_tempPgTable, %edi
|
||||||
|
mov %eax, (%edi, %ecx, 4)
|
||||||
|
mov $_tempIdentityMap, %edi
|
||||||
|
mov %eax, 1024(%edi, %ecx, 4)
|
||||||
|
inc %ecx
|
||||||
|
cmp $IMAGE_SIZE, %ecx
|
||||||
|
jne 1b
|
||||||
|
|
||||||
|
mov $_tempIdentityMap, %eax
|
||||||
|
or $3, %eax
|
||||||
|
mov %eax, (_tempPgDir)
|
||||||
|
|
||||||
|
mov $_tempPgTable, %eax
|
||||||
|
or $3, %eax
|
||||||
|
mov %eax, (_tempPgDir + 3072)
|
||||||
|
|
||||||
|
mov $_tempPgDir, %eax
|
||||||
|
mov %eax, %cr3
|
||||||
|
|
||||||
|
mov %cr0, %eax
|
||||||
|
or $0x80010000, %eax
|
||||||
|
mov %eax, %cr0
|
||||||
|
lea 2f, %eax
|
||||||
|
jmp *%eax
|
||||||
|
2: movl $0, (_tempIdentityMap)
|
||||||
|
mov %cr3, %eax
|
||||||
|
mov %eax, %cr3
|
||||||
|
|
||||||
|
mov $stackTop, %esp
|
||||||
|
|
||||||
|
call main
|
||||||
|
|
||||||
|
_err:
|
||||||
|
cli
|
||||||
|
3: hlt
|
||||||
|
jmp 3b
|
||||||
|
|
||||||
|
.size _start, . - _start
|
||||||
33
src/error.cpp
Normal file
33
src/error.cpp
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Error.cpp
|
||||||
|
*
|
||||||
|
* Created on: May 23, 2019
|
||||||
|
* Author: nathan
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
|
namespace qkernel {
|
||||||
|
|
||||||
|
Error lastError;
|
||||||
|
|
||||||
|
Error::Error()
|
||||||
|
: errorType(ErrorType::none), message("") {}
|
||||||
|
|
||||||
|
Error::Error(ErrorType errorType)
|
||||||
|
: errorType(errorType), message("") {}
|
||||||
|
|
||||||
|
Error::Error(ErrorType errorType, const char* message)
|
||||||
|
: errorType(errorType), message(message) {}
|
||||||
|
|
||||||
|
ErrorType Error::getType()
|
||||||
|
{
|
||||||
|
return errorType;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* Error::getMessage()
|
||||||
|
{
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace qkernel */
|
||||||
40
src/error.h
Normal file
40
src/error.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Error.h
|
||||||
|
*
|
||||||
|
* Created on: May 23, 2019
|
||||||
|
* Author: nathan
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRC_ERROR_H_
|
||||||
|
#define SRC_ERROR_H_
|
||||||
|
|
||||||
|
#include "errortype.h"
|
||||||
|
|
||||||
|
namespace qkernel {
|
||||||
|
|
||||||
|
class Error {
|
||||||
|
public:
|
||||||
|
|
||||||
|
Error();
|
||||||
|
|
||||||
|
Error(ErrorType errorType);
|
||||||
|
|
||||||
|
Error(ErrorType errorType, const char* message);
|
||||||
|
|
||||||
|
ErrorType getType();
|
||||||
|
|
||||||
|
const char* getMessage();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
ErrorType errorType;
|
||||||
|
|
||||||
|
const char* message;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
extern Error lastError;
|
||||||
|
|
||||||
|
} /* namespace qkernel */
|
||||||
|
|
||||||
|
#endif /* SRC_ERROR_H_ */
|
||||||
22
src/errortype.h
Normal file
22
src/errortype.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* ErrorType.h
|
||||||
|
*
|
||||||
|
* Created on: May 23, 2019
|
||||||
|
* Author: nathan
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRC_ERRORTYPE_H_
|
||||||
|
#define SRC_ERRORTYPE_H_
|
||||||
|
|
||||||
|
|
||||||
|
enum class ErrorType
|
||||||
|
{
|
||||||
|
none,
|
||||||
|
outOfBounds,
|
||||||
|
illegalState,
|
||||||
|
outOfMemory,
|
||||||
|
invalidArgument
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* SRC_ERRORTYPE_H_ */
|
||||||
27
src/math.cpp
Normal file
27
src/math.cpp
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* math.cpp
|
||||||
|
*
|
||||||
|
* Created on: May 23, 2019
|
||||||
|
* Author: nathan
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "math.h"
|
||||||
|
|
||||||
|
uint32_t ilog2(uint32_t n, bool roundUp)
|
||||||
|
{
|
||||||
|
uint32_t m = n;
|
||||||
|
uint32_t count = 0;
|
||||||
|
bool isPowerOfTwo = true;
|
||||||
|
while(m)
|
||||||
|
{
|
||||||
|
if((m & 1) == 1 && m > 1)
|
||||||
|
{
|
||||||
|
isPowerOfTwo = false;
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
m >>= 1;
|
||||||
|
}
|
||||||
|
return count - (isPowerOfTwo ? 1 : (roundUp ? 0 : 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
22
src/math.h
Normal file
22
src/math.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* math.h
|
||||||
|
*
|
||||||
|
* Created on: May 23, 2019
|
||||||
|
* Author: nathan
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRC_MATH_H_
|
||||||
|
#define SRC_MATH_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the logarithm in base 2 of a given integer, returning an integer as
|
||||||
|
* the result. For n = -1, returns unsigned -1.
|
||||||
|
*
|
||||||
|
* @returns floor(log2(n)), where n > 0. Else unsigned -1.
|
||||||
|
*/
|
||||||
|
uint32_t ilog2(uint32_t n, bool roundUp = false);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* SRC_MATH_H_ */
|
||||||
94
src/multiboot2header.S
Normal file
94
src/multiboot2header.S
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* Define constants for the multiboot header. See Multuboot 2 Specifications for details.
|
||||||
|
*/
|
||||||
|
.set align, 1<<0
|
||||||
|
.set meminfo, 1<<1
|
||||||
|
.set magic, 0xE85250D6
|
||||||
|
.set arch, 0
|
||||||
|
.set headerLength, _multibootHeaderEnd - _multibootHeaderStart
|
||||||
|
.set checksum, -(magic + arch + headerLength)
|
||||||
|
|
||||||
|
.set tagNotOptional, 0
|
||||||
|
|
||||||
|
.set tagInfoRequestType, 1
|
||||||
|
.set tagInfoRequestSize, _multibootInfoTagEnd - _multibootInfoTagStart
|
||||||
|
.set requestBootCommand, 1
|
||||||
|
.set requestBootLoaderName, 2
|
||||||
|
.set requestBootModules, 3
|
||||||
|
.set requestMemoryInfo, 4
|
||||||
|
.set requestBootDevice, 5
|
||||||
|
.set requestMemoryMap, 6
|
||||||
|
|
||||||
|
.set tagAddressType, 2
|
||||||
|
.set tagAddressSize, 24
|
||||||
|
.set tagAddressHeaderLocation, LOAD_START
|
||||||
|
.set tagAddressLoadStart, LOAD_START
|
||||||
|
.set tagAddressLoadEnd, LOAD_END
|
||||||
|
.set tagAddressBSSEnd, BSS_END
|
||||||
|
|
||||||
|
.set tagEntryType, 3
|
||||||
|
.set tagEntrySize, 12
|
||||||
|
.set tagEntryAddress, _start - (0xC0000000 - 0x100000)
|
||||||
|
|
||||||
|
.set tagModuleAlignType, 6
|
||||||
|
.set tagModuleAlignSize, 8
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Each multiboot tag must be 8-byte aligned, or GRUB will not be able to read the header.
|
||||||
|
*/
|
||||||
|
.align 8
|
||||||
|
_multibootHeaderStart:
|
||||||
|
|
||||||
|
.long magic
|
||||||
|
.long arch
|
||||||
|
.long headerLength
|
||||||
|
.long checksum
|
||||||
|
|
||||||
|
.align 8
|
||||||
|
|
||||||
|
_multibootInfoTagStart:
|
||||||
|
.short tagInfoRequestType
|
||||||
|
.short tagNotOptional
|
||||||
|
.long tagInfoRequestSize
|
||||||
|
.long requestBootCommand
|
||||||
|
.long requestBootLoaderName
|
||||||
|
.long requestBootModules
|
||||||
|
.long requestMemoryInfo
|
||||||
|
.long requestBootDevice
|
||||||
|
.long requestMemoryMap
|
||||||
|
_multibootInfoTagEnd:
|
||||||
|
|
||||||
|
.align 8
|
||||||
|
|
||||||
|
.short tagAddressType
|
||||||
|
.short tagNotOptional
|
||||||
|
.long tagAddressSize
|
||||||
|
.long tagAddressHeaderLocation
|
||||||
|
.long tagAddressLoadStart
|
||||||
|
.long tagAddressLoadEnd
|
||||||
|
.long tagAddressBSSEnd
|
||||||
|
|
||||||
|
.align 8
|
||||||
|
|
||||||
|
.short tagEntryType
|
||||||
|
.short tagNotOptional
|
||||||
|
.long tagEntrySize
|
||||||
|
.long tagEntryAddress
|
||||||
|
|
||||||
|
.align 8
|
||||||
|
|
||||||
|
.short tagModuleAlignType
|
||||||
|
.short tagNotOptional
|
||||||
|
.long tagModuleAlignSize
|
||||||
|
|
||||||
|
.align 8
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Terminate list of multiboot header tags.
|
||||||
|
* Ending tag has type = 0, flags = 0, size = 8
|
||||||
|
*/
|
||||||
|
.long 0
|
||||||
|
.long 8
|
||||||
|
|
||||||
|
_multibootHeaderEnd:
|
||||||
|
|
||||||
127
src/pagetableentry.cpp
Normal file
127
src/pagetableentry.cpp
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* PageTableEntry.cpp
|
||||||
|
*
|
||||||
|
* Created on: May 22, 2019
|
||||||
|
* Author: nathan
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "pagetableentry.h"
|
||||||
|
|
||||||
|
namespace qkernel {
|
||||||
|
|
||||||
|
static_assert(sizeof(PageTableEntry) == 4, "PTE structure is the wrong size!");
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PageTableEntry::getAccessed() const {
|
||||||
|
return accessed;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PageTableEntry::getCacheDisable() const {
|
||||||
|
return cacheDisable;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PageTableEntry::setCacheDisable(uint32_t cacheDisable)
|
||||||
|
{
|
||||||
|
this->cacheDisable = cacheDisable;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PageTableEntry::getDirty() const {
|
||||||
|
return dirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PageTableEntry::getGlobal() const {
|
||||||
|
return global;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PageTableEntry::setGlobal(uint32_t global)
|
||||||
|
{
|
||||||
|
this->global = global;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PageTableEntry::getPat() const {
|
||||||
|
return pat;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PageTableEntry::setPat(uint32_t pat)
|
||||||
|
{
|
||||||
|
this->pat = pat;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PageTableEntry::getPhysicalAddress() const {
|
||||||
|
uint32_t physicalAddress = this->physicalAddress;
|
||||||
|
return physicalAddress << 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PageTableEntry::setPhysicalAddress(uint32_t physicalAddress)
|
||||||
|
{
|
||||||
|
if(physicalAddress % 4096 == 0)
|
||||||
|
{
|
||||||
|
this->physicalAddress = physicalAddress >> 12;
|
||||||
|
return this->physicalAddress;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->physicalAddress = !physicalAddress;
|
||||||
|
return this->physicalAddress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PageTableEntry::getPresent() const {
|
||||||
|
return present;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PageTableEntry::setPresent(uint32_t present)
|
||||||
|
{
|
||||||
|
this->present = present;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PageTableEntry::getRw() const {
|
||||||
|
return rw;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PageTableEntry::setRw(uint32_t rw)
|
||||||
|
{
|
||||||
|
this->rw = rw;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PageTableEntry::getUsermode() const {
|
||||||
|
return usermode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PageTableEntry::setUsermode(uint32_t usermode)
|
||||||
|
{
|
||||||
|
this->usermode = usermode;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PageTableEntry::getWriteThrough() const {
|
||||||
|
return writeThrough;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PageTableEntry::getShared() const {
|
||||||
|
return shared;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PageTableEntry::setShared(uint32_t shared) {
|
||||||
|
this->shared = shared;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PageTableEntry::setWriteThrough(uint32_t writeThrough)
|
||||||
|
{
|
||||||
|
this->writeThrough = writeThrough;
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace qkernel */
|
||||||
56
src/pagetableentry.h
Normal file
56
src/pagetableentry.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* PageTableEntry.h
|
||||||
|
*
|
||||||
|
* Created on: May 22, 2019
|
||||||
|
* Author: nathan
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRC_PAGETABLEENTRY_H_
|
||||||
|
#define SRC_PAGETABLEENTRY_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace qkernel {
|
||||||
|
|
||||||
|
class PageTableEntry {
|
||||||
|
public:
|
||||||
|
PageTableEntry();
|
||||||
|
uint32_t getAccessed() const;
|
||||||
|
uint32_t getCacheDisable() const;
|
||||||
|
void setCacheDisable(uint32_t cacheDisable);
|
||||||
|
uint32_t getDirty() const;
|
||||||
|
uint32_t getGlobal() const;
|
||||||
|
void setGlobal(uint32_t global);
|
||||||
|
uint32_t getPat() const;
|
||||||
|
void setPat(uint32_t pat);
|
||||||
|
uint32_t getPhysicalAddress() const;
|
||||||
|
uint32_t setPhysicalAddress(uint32_t physicalAddress);
|
||||||
|
uint32_t getPresent() const;
|
||||||
|
void setPresent(uint32_t present);
|
||||||
|
uint32_t getRw() const;
|
||||||
|
void setRw(uint32_t rw);
|
||||||
|
uint32_t getShared() const;
|
||||||
|
void setShared(uint32_t shared);
|
||||||
|
uint32_t getUsermode() const;
|
||||||
|
void setUsermode(uint32_t usermode);
|
||||||
|
uint32_t getWriteThrough() const;
|
||||||
|
void setWriteThrough(uint32_t writeThrough);
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace qkernel */
|
||||||
|
|
||||||
|
#endif /* SRC_PAGETABLEENTRY_H_ */
|
||||||
202
src/physicalmemoryallocator.cpp
Normal file
202
src/physicalmemoryallocator.cpp
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
/*
|
||||||
|
* PhysicalMemoryAllocator.cpp
|
||||||
|
*
|
||||||
|
* Created on: May 23, 2019
|
||||||
|
* Author: nathan
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "physicalmemoryallocator.h"
|
||||||
|
#include "math.h"
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
|
namespace qkernel {
|
||||||
|
|
||||||
|
void* const PhysicalMemoryAllocator::nullPtr = (void*) -1;
|
||||||
|
|
||||||
|
PhysicalMemoryAllocator::PhysicalMemoryAllocator()
|
||||||
|
{
|
||||||
|
for(size_t i = 0; i <= treeHeight; i++)
|
||||||
|
{
|
||||||
|
memoryMaps[i] = Bitmap<treeLeaves>(!available);
|
||||||
|
}
|
||||||
|
memoryMaps[treeHeight][0] = available;
|
||||||
|
}
|
||||||
|
|
||||||
|
PhysicalMemoryAllocator::~PhysicalMemoryAllocator()
|
||||||
|
{
|
||||||
|
// TODO Auto-generated destructor stub
|
||||||
|
}
|
||||||
|
|
||||||
|
void* PhysicalMemoryAllocator::allocate(uint32_t pages)
|
||||||
|
{
|
||||||
|
uint32_t height = ilog2(pages, true);
|
||||||
|
if(height >= treeHeight) // We can't allocate the whole address space at once!
|
||||||
|
{
|
||||||
|
return (void*) nullPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t index = findFreeBlock(height);
|
||||||
|
if(index != nullIndex)
|
||||||
|
{
|
||||||
|
memoryMaps[height][index] = !available;
|
||||||
|
return nodeToAddress(height, index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return nullPtr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhysicalMemoryAllocator::free(void* location, uint32_t pages)
|
||||||
|
{
|
||||||
|
uint32_t height = ilog2(pages, true);
|
||||||
|
if(height >= treeHeight || reinterpret_cast<uint32_t>(location) % (4096 * pages) != 0) // We can't free the whole address space at once!
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t index = addressToNode(height, location);
|
||||||
|
memoryMaps[height][index] = available;
|
||||||
|
|
||||||
|
if(memoryMaps[height][getBuddy(index)] == available)
|
||||||
|
{
|
||||||
|
merge(height, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PhysicalMemoryAllocator::totalFreePages()
|
||||||
|
{
|
||||||
|
uint32_t count = 0;
|
||||||
|
for(size_t i = 0; i <= treeHeight; i++)
|
||||||
|
{
|
||||||
|
count += (1 << i) * memoryMaps[i].count();
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PhysicalMemoryAllocator::largestFreeBlock()
|
||||||
|
{
|
||||||
|
for(size_t i = treeHeight; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if(memoryMaps[i].any())
|
||||||
|
{
|
||||||
|
return 1 << i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PhysicalMemoryAllocator::findFreeBlock(uint32_t height)
|
||||||
|
{
|
||||||
|
if(memoryMaps[height].none())
|
||||||
|
{
|
||||||
|
if(height == treeHeight)
|
||||||
|
{
|
||||||
|
lastError = Error(ErrorType::outOfMemory, "Out of memory");
|
||||||
|
return nullIndex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint32_t parentIndex = findFreeBlock(height + 1);
|
||||||
|
if(parentIndex == (uint32_t) -1)
|
||||||
|
{
|
||||||
|
lastError = Error(ErrorType::outOfMemory, "Out of memory");
|
||||||
|
return nullIndex;
|
||||||
|
}
|
||||||
|
split(height + 1, parentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
for(size_t index = 0; index < nodesAtHeight(height); index++)
|
||||||
|
{
|
||||||
|
if(memoryMaps[height][index] == available)
|
||||||
|
{
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastError = Error(ErrorType::illegalState, "There were still no free blocks after splitting larger ones!");
|
||||||
|
return nullIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PhysicalMemoryAllocator::merge(uint32_t height, uint32_t index)
|
||||||
|
{
|
||||||
|
if(height == treeHeight)
|
||||||
|
{
|
||||||
|
lastError = Error(ErrorType::outOfBounds, "Attempted to merge root node");
|
||||||
|
return nullIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(memoryMaps[height][index] == 0 && memoryMaps[height][getBuddy(index)] == 0)
|
||||||
|
{
|
||||||
|
memoryMaps[height][index] = !available;
|
||||||
|
memoryMaps[height][getBuddy(index)] = !available;
|
||||||
|
memoryMaps[height + 1][getParent(index)] = available;
|
||||||
|
if(height + 1 < 20)
|
||||||
|
{
|
||||||
|
if(memoryMaps[height + 1][getBuddy(getParent(index))] == available)
|
||||||
|
{
|
||||||
|
return merge(height + 1, getParent(index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return getParent(index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lastError = Error(ErrorType::invalidArgument, "Attempted to merge a node that is in use");
|
||||||
|
return nullIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PhysicalMemoryAllocator::split(uint32_t height, uint32_t index)
|
||||||
|
{
|
||||||
|
if(height == 0)
|
||||||
|
{
|
||||||
|
lastError = Error(ErrorType::outOfBounds, "Attempted to split leaf node");
|
||||||
|
return nullIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(memoryMaps[height][index] == available)
|
||||||
|
{
|
||||||
|
memoryMaps[height][index] = !available;
|
||||||
|
memoryMaps[height - 1][getChild(index)] = available;
|
||||||
|
memoryMaps[height - 1][getBuddy(getChild(index))] = available;
|
||||||
|
return getChild(index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lastError = Error(ErrorType::invalidArgument, "Attempted to split node currently in use");
|
||||||
|
return nullIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PhysicalMemoryAllocator::getBuddy(uint32_t index)
|
||||||
|
{
|
||||||
|
return index ^ 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PhysicalMemoryAllocator::getParent(uint32_t index)
|
||||||
|
{
|
||||||
|
return (index - index % 2) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PhysicalMemoryAllocator::getChild(uint32_t index)
|
||||||
|
{
|
||||||
|
return index * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* PhysicalMemoryAllocator::nodeToAddress(uint32_t height, uint32_t index)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<void*>(index * 4096 * (1 << height));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PhysicalMemoryAllocator::nodesAtHeight(uint32_t height)
|
||||||
|
{
|
||||||
|
return treeLeaves / (1 << height);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PhysicalMemoryAllocator::addressToNode(uint32_t height,
|
||||||
|
void* address)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<uint32_t>(address) / (4096 * (1 << height));
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace qkernel */
|
||||||
90
src/physicalmemoryallocator.h
Normal file
90
src/physicalmemoryallocator.h
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* PhysicalMemoryAllocator.h
|
||||||
|
*
|
||||||
|
* Created on: May 23, 2019
|
||||||
|
* Author: nathan
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PHYSICALMEMORYALLOCATOR_H_
|
||||||
|
#define PHYSICALMEMORYALLOCATOR_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "bitmap.h"
|
||||||
|
|
||||||
|
namespace qkernel {
|
||||||
|
|
||||||
|
class PhysicalMemoryAllocator {
|
||||||
|
public:
|
||||||
|
|
||||||
|
static void* const nullPtr;
|
||||||
|
|
||||||
|
PhysicalMemoryAllocator();
|
||||||
|
|
||||||
|
~PhysicalMemoryAllocator();
|
||||||
|
|
||||||
|
void* allocate(uint32_t pages);
|
||||||
|
|
||||||
|
void free(void* location, uint32_t pages);
|
||||||
|
|
||||||
|
uint32_t totalFreePages();
|
||||||
|
|
||||||
|
uint32_t largestFreeBlock();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static const uint32_t nullIndex = (uint32_t) -1;
|
||||||
|
|
||||||
|
static const bool available = true;
|
||||||
|
|
||||||
|
static const size_t treeHeight = 20;
|
||||||
|
|
||||||
|
static const size_t treeLeaves = 1024 * 1024;
|
||||||
|
|
||||||
|
Bitmap<treeLeaves> memoryMaps[treeHeight + 1];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches nodes of the given height for an available block. If none is
|
||||||
|
* present, recursively splits higher nodes until one is.
|
||||||
|
*
|
||||||
|
* @param height The height of the desired node.
|
||||||
|
* @returns the index of the located node
|
||||||
|
*/
|
||||||
|
uint32_t findFreeBlock(uint32_t height);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merges a pair of buddies that have both become available. Recurses if
|
||||||
|
* the buddy of the new block is available.
|
||||||
|
*
|
||||||
|
* @param height The height of the blocks to merge.
|
||||||
|
* @param index The index of one of the buddies to be merged.
|
||||||
|
*/
|
||||||
|
uint32_t merge(uint32_t height, uint32_t index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits a block into a pair of buddies, making the original unavailable.
|
||||||
|
*
|
||||||
|
* @param height The height of the block to split.
|
||||||
|
* @param index The index of the block to split.
|
||||||
|
*
|
||||||
|
* @returns the index of the first of the pair of new blocks.
|
||||||
|
*/
|
||||||
|
uint32_t split(uint32_t height, uint32_t index);
|
||||||
|
|
||||||
|
uint32_t getBuddy(uint32_t index);
|
||||||
|
|
||||||
|
uint32_t getParent(uint32_t index);
|
||||||
|
|
||||||
|
uint32_t getChild(uint32_t index);
|
||||||
|
|
||||||
|
uint32_t nodesAtHeight(uint32_t height);
|
||||||
|
|
||||||
|
void* nodeToAddress(uint32_t height, uint32_t index);
|
||||||
|
|
||||||
|
uint32_t addressToNode(uint32_t height, void* address);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace qkernel */
|
||||||
|
|
||||||
|
#endif /* PHYSICALMEMORYALLOCATOR_H_ */
|
||||||
13
src/quarkkernel.cpp
Normal file
13
src/quarkkernel.cpp
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#if __STDC_HOSTED__ == 1 || __i686__ != 1
|
||||||
|
#error "ERROR: This program must be compiled for a freestanding environment, and currently only supports the i686 target."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
int x = 2;
|
||||||
|
x -= 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user