Compare commits
2 Commits
main
...
40649c8b46
| Author | SHA1 | Date | |
|---|---|---|---|
| 40649c8b46 | |||
| 996c5ebe74 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,4 +3,3 @@
|
|||||||
build/
|
build/
|
||||||
base/
|
base/
|
||||||
script/fakeroot-context
|
script/fakeroot-context
|
||||||
tools/update-image-perms
|
|
||||||
|
|||||||
@@ -18,78 +18,78 @@ namespace BAN
|
|||||||
using const_iterator = ConstIteratorSimple<T, Array>;
|
using const_iterator = ConstIteratorSimple<T, Array>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr Array() = default;
|
Array() = default;
|
||||||
constexpr Array(const T&);
|
Array(const T&);
|
||||||
|
|
||||||
iterator begin() { return iterator(m_data); }
|
iterator begin() { return iterator(m_data); }
|
||||||
iterator end() { return iterator(m_data + size()); }
|
iterator end() { return iterator(m_data + size()); }
|
||||||
const_iterator begin() const { return const_iterator(m_data); }
|
const_iterator begin() const { return const_iterator(m_data); }
|
||||||
const_iterator end() const { return const_iterator(m_data + size()); }
|
const_iterator end() const { return const_iterator(m_data + size()); }
|
||||||
|
|
||||||
constexpr const T& operator[](size_type) const;
|
const T& operator[](size_type) const;
|
||||||
constexpr T& operator[](size_type);
|
T& operator[](size_type);
|
||||||
|
|
||||||
constexpr const T& back() const;
|
const T& back() const;
|
||||||
constexpr T& back();
|
T& back();
|
||||||
constexpr const T& front() const;
|
const T& front() const;
|
||||||
constexpr T& front();
|
T& front();
|
||||||
|
|
||||||
Span<T> span() { return Span(m_data, size()); }
|
Span<T> span() { return Span(m_data, size()); }
|
||||||
Span<const T> span() const { return Span(m_data, size()); }
|
const Span<T> span() const { return Span(m_data, size()); }
|
||||||
|
|
||||||
constexpr size_type size() const;
|
constexpr size_type size() const;
|
||||||
|
|
||||||
constexpr const T* data() const { return m_data; }
|
const T* data() const { return m_data; }
|
||||||
constexpr T* data() { return m_data; }
|
T* data() { return m_data; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T m_data[S] {};
|
T m_data[S] {};
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T, size_t S>
|
template<typename T, size_t S>
|
||||||
constexpr Array<T, S>::Array(const T& value)
|
Array<T, S>::Array(const T& value)
|
||||||
{
|
{
|
||||||
for (size_type i = 0; i < S; i++)
|
for (size_type i = 0; i < S; i++)
|
||||||
m_data[i] = value;
|
m_data[i] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, size_t S>
|
template<typename T, size_t S>
|
||||||
constexpr const T& Array<T, S>::operator[](size_type index) const
|
const T& Array<T, S>::operator[](size_type index) const
|
||||||
{
|
{
|
||||||
ASSERT(index < S);
|
ASSERT(index < S);
|
||||||
return m_data[index];
|
return m_data[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, size_t S>
|
template<typename T, size_t S>
|
||||||
constexpr T& Array<T, S>::operator[](size_type index)
|
T& Array<T, S>::operator[](size_type index)
|
||||||
{
|
{
|
||||||
ASSERT(index < S);
|
ASSERT(index < S);
|
||||||
return m_data[index];
|
return m_data[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, size_t S>
|
template<typename T, size_t S>
|
||||||
constexpr const T& Array<T, S>::back() const
|
const T& Array<T, S>::back() const
|
||||||
{
|
{
|
||||||
ASSERT(S != 0);
|
ASSERT(S != 0);
|
||||||
return m_data[S - 1];
|
return m_data[S - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, size_t S>
|
template<typename T, size_t S>
|
||||||
constexpr T& Array<T, S>::back()
|
T& Array<T, S>::back()
|
||||||
{
|
{
|
||||||
ASSERT(S != 0);
|
ASSERT(S != 0);
|
||||||
return m_data[S - 1];
|
return m_data[S - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, size_t S>
|
template<typename T, size_t S>
|
||||||
constexpr const T& Array<T, S>::front() const
|
const T& Array<T, S>::front() const
|
||||||
{
|
{
|
||||||
ASSERT(S != 0);
|
ASSERT(S != 0);
|
||||||
return m_data[0];
|
return m_data[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, size_t S>
|
template<typename T, size_t S>
|
||||||
constexpr T& Array<T, S>::front()
|
T& Array<T, S>::front()
|
||||||
{
|
{
|
||||||
ASSERT(S != 0);
|
ASSERT(S != 0);
|
||||||
return m_data[0];
|
return m_data[0];
|
||||||
|
|||||||
@@ -34,11 +34,6 @@ namespace BAN
|
|||||||
const T& back() const;
|
const T& back() const;
|
||||||
T& back();
|
T& back();
|
||||||
|
|
||||||
const T& operator[](size_t index) const;
|
|
||||||
T& operator[](size_t index);
|
|
||||||
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
size_type size() const { return m_size; }
|
size_type size() const { return m_size; }
|
||||||
bool empty() const { return size() == 0; }
|
bool empty() const { return size() == 0; }
|
||||||
bool full() const { return size() == capacity(); }
|
bool full() const { return size() == capacity(); }
|
||||||
@@ -58,7 +53,8 @@ namespace BAN
|
|||||||
template<typename T, size_t S>
|
template<typename T, size_t S>
|
||||||
CircularQueue<T, S>::~CircularQueue()
|
CircularQueue<T, S>::~CircularQueue()
|
||||||
{
|
{
|
||||||
clear();
|
for (size_type i = 0; i < m_size; i++)
|
||||||
|
element_at((m_first + i) % capacity())->~T();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, size_t S>
|
template<typename T, size_t S>
|
||||||
@@ -119,28 +115,6 @@ namespace BAN
|
|||||||
return *element_at((m_first + m_size - 1) % capacity());
|
return *element_at((m_first + m_size - 1) % capacity());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, size_t S>
|
|
||||||
const T& CircularQueue<T, S>::operator[](size_t index) const
|
|
||||||
{
|
|
||||||
ASSERT(index < m_size);
|
|
||||||
return *element_at((m_first + index) % capacity());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, size_t S>
|
|
||||||
T& CircularQueue<T, S>::operator[](size_t index)
|
|
||||||
{
|
|
||||||
ASSERT(index < m_size);
|
|
||||||
return *element_at((m_first + index) % capacity());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, size_t S>
|
|
||||||
void CircularQueue<T, S>::clear()
|
|
||||||
{
|
|
||||||
for (size_type i = 0; i < m_size; i++)
|
|
||||||
element_at((m_first + i) % capacity())->~T();
|
|
||||||
m_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, size_t S>
|
template<typename T, size_t S>
|
||||||
const T* CircularQueue<T, S>::element_at(size_type index) const
|
const T* CircularQueue<T, S>::element_at(size_type index) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,35 +9,29 @@
|
|||||||
#include <BAN/Formatter.h>
|
#include <BAN/Formatter.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#define __debug_putchar [](int c) { putc_unlocked(c, stddbg); }
|
#define __debug_putchar [](int c) { putc(c, stddbg); }
|
||||||
|
|
||||||
#define dprintln(...) \
|
#define dprintln(...) \
|
||||||
do { \
|
do { \
|
||||||
flockfile(stddbg); \
|
|
||||||
BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \
|
BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \
|
||||||
BAN::Formatter::print(__debug_putchar,"\n"); \
|
BAN::Formatter::print(__debug_putchar,"\r\n"); \
|
||||||
fflush(stddbg); \
|
fflush(stddbg); \
|
||||||
funlockfile(stddbg); \
|
|
||||||
} while (false)
|
} while (false)
|
||||||
|
|
||||||
#define dwarnln(...) \
|
#define dwarnln(...) \
|
||||||
do { \
|
do { \
|
||||||
flockfile(stddbg); \
|
|
||||||
BAN::Formatter::print(__debug_putchar, "\e[33m"); \
|
BAN::Formatter::print(__debug_putchar, "\e[33m"); \
|
||||||
BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \
|
BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \
|
||||||
BAN::Formatter::print(__debug_putchar, "\e[m\n"); \
|
BAN::Formatter::print(__debug_putchar, "\e[m\r\n"); \
|
||||||
fflush(stddbg); \
|
fflush(stddbg); \
|
||||||
funlockfile(stddbg); \
|
|
||||||
} while(false)
|
} while(false)
|
||||||
|
|
||||||
#define derrorln(...) \
|
#define derrorln(...) \
|
||||||
do { \
|
do { \
|
||||||
flockfile(stddbg); \
|
|
||||||
BAN::Formatter::print(__debug_putchar, "\e[31m"); \
|
BAN::Formatter::print(__debug_putchar, "\e[31m"); \
|
||||||
BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \
|
BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \
|
||||||
BAN::Formatter::print(__debug_putchar, "\e[m\n"); \
|
BAN::Formatter::print(__debug_putchar, "\e[m\r\n"); \
|
||||||
fflush(stddbg); \
|
fflush(stddbg); \
|
||||||
funlockfile(stddbg); \
|
|
||||||
} while(false)
|
} while(false)
|
||||||
|
|
||||||
#define dprintln_if(cond, ...) \
|
#define dprintln_if(cond, ...) \
|
||||||
|
|||||||
@@ -1,89 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <BAN/Iterators.h>
|
|
||||||
#include <BAN/Swap.h>
|
|
||||||
#include <BAN/Traits.h>
|
|
||||||
|
|
||||||
namespace BAN
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
|
|
||||||
template<typename It, typename Comp>
|
|
||||||
void heapify_up(It begin, size_t index, Comp comp)
|
|
||||||
{
|
|
||||||
size_t parent = (index - 1) / 2;
|
|
||||||
while (parent < index)
|
|
||||||
{
|
|
||||||
if (comp(*(begin + index), *(begin + parent)))
|
|
||||||
break;
|
|
||||||
swap(*(begin + parent), *(begin + index));
|
|
||||||
index = parent;
|
|
||||||
parent = (index - 1) / 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename It, typename Comp>
|
|
||||||
void heapify_down(It begin, size_t index, size_t len, Comp comp)
|
|
||||||
{
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
const size_t lchild = 2 * index + 1;
|
|
||||||
const size_t rchild = 2 * index + 2;
|
|
||||||
|
|
||||||
size_t child = 0;
|
|
||||||
if (lchild < len && !comp(*(begin + lchild), *(begin + index)))
|
|
||||||
{
|
|
||||||
if (rchild < len && !comp(*(begin + rchild), *(begin + lchild)))
|
|
||||||
child = rchild;
|
|
||||||
else
|
|
||||||
child = lchild;
|
|
||||||
}
|
|
||||||
else if (rchild < len && !comp(*(begin + rchild), *(begin + index)))
|
|
||||||
child = rchild;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
|
|
||||||
swap(*(begin + child), *(begin + index));
|
|
||||||
index = child;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
|
||||||
void make_heap(It begin, It end, Comp comp = {})
|
|
||||||
{
|
|
||||||
const size_t len = distance(begin, end);
|
|
||||||
if (len <= 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
size_t index = (len - 2) / 2;
|
|
||||||
while (index < len)
|
|
||||||
detail::heapify_down(begin, index--, len, comp);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
|
||||||
void push_heap(It begin, It end, Comp comp = {})
|
|
||||||
{
|
|
||||||
const size_t len = distance(begin, end);
|
|
||||||
detail::heapify_up(begin, len - 1, comp);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
|
||||||
void pop_heap(It begin, It end, Comp comp = {})
|
|
||||||
{
|
|
||||||
const size_t len = distance(begin, end);
|
|
||||||
swap(*begin, *(begin + len - 1));
|
|
||||||
detail::heapify_down(begin, 0, len - 1, comp);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
|
||||||
void sort_heap(It begin, It end, Comp comp = {})
|
|
||||||
{
|
|
||||||
while (begin != end)
|
|
||||||
pop_heap(begin, end--, comp);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -9,10 +9,6 @@ namespace BAN
|
|||||||
|
|
||||||
struct IPv4Address
|
struct IPv4Address
|
||||||
{
|
{
|
||||||
constexpr IPv4Address()
|
|
||||||
: IPv4Address(0)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
constexpr IPv4Address(uint32_t u32_address)
|
constexpr IPv4Address(uint32_t u32_address)
|
||||||
{
|
{
|
||||||
raw = u32_address;
|
raw = u32_address;
|
||||||
|
|||||||
@@ -36,11 +36,12 @@ namespace BAN::Math
|
|||||||
template<integral T>
|
template<integral T>
|
||||||
inline constexpr T gcd(T a, T b)
|
inline constexpr T gcd(T a, T b)
|
||||||
{
|
{
|
||||||
|
T t;
|
||||||
while (b)
|
while (b)
|
||||||
{
|
{
|
||||||
T temp = b;
|
t = b;
|
||||||
b = a % b;
|
b = a % b;
|
||||||
a = temp;
|
a = t;
|
||||||
}
|
}
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
@@ -65,20 +66,25 @@ namespace BAN::Math
|
|||||||
return (x & (x - 1)) == 0;
|
return (x & (x - 1)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<integral T>
|
template<BAN::integral T>
|
||||||
__attribute__((always_inline))
|
static constexpr bool will_multiplication_overflow(T a, T b)
|
||||||
inline constexpr bool will_multiplication_overflow(T a, T b)
|
|
||||||
{
|
{
|
||||||
T dummy;
|
if (a == 0 || b == 0)
|
||||||
return __builtin_mul_overflow(a, b, &dummy);
|
return false;
|
||||||
|
if ((a > 0) == (b > 0))
|
||||||
|
return a > BAN::numeric_limits<T>::max() / b;
|
||||||
|
else
|
||||||
|
return a < BAN::numeric_limits<T>::min() / b;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<integral T>
|
template<BAN::integral T>
|
||||||
__attribute__((always_inline))
|
static constexpr bool will_addition_overflow(T a, T b)
|
||||||
inline constexpr bool will_addition_overflow(T a, T b)
|
|
||||||
{
|
{
|
||||||
T dummy;
|
if (a > 0 && b > 0)
|
||||||
return __builtin_add_overflow(a, b, &dummy);
|
return a > BAN::numeric_limits<T>::max() - b;
|
||||||
|
if (a < 0 && b < 0)
|
||||||
|
return a < BAN::numeric_limits<T>::min() - b;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -92,19 +98,6 @@ namespace BAN::Math
|
|||||||
return sizeof(T) * 8 - __builtin_clzll(x) - 1;
|
return sizeof(T) * 8 - __builtin_clzll(x) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is ugly but my clangd does not like including
|
|
||||||
// intrinsic headers at all
|
|
||||||
#if !defined(__SSE__) || !defined(__SSE2__)
|
|
||||||
#pragma GCC push_options
|
|
||||||
#ifndef __SSE__
|
|
||||||
#pragma GCC target("sse")
|
|
||||||
#endif
|
|
||||||
#ifndef __SSE2__
|
|
||||||
#pragma GCC target("sse2")
|
|
||||||
#endif
|
|
||||||
#define BAN_MATH_POP_OPTIONS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template<floating_point T>
|
template<floating_point T>
|
||||||
inline constexpr T floor(T x)
|
inline constexpr T floor(T x)
|
||||||
{
|
{
|
||||||
@@ -166,23 +159,7 @@ namespace BAN::Math
|
|||||||
"jne 1b;"
|
"jne 1b;"
|
||||||
: "+t"(a)
|
: "+t"(a)
|
||||||
: "u"(b)
|
: "u"(b)
|
||||||
: "ax", "cc"
|
: "ax"
|
||||||
);
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<floating_point T>
|
|
||||||
inline constexpr T remainder(T a, T b)
|
|
||||||
{
|
|
||||||
asm(
|
|
||||||
"1:"
|
|
||||||
"fprem1;"
|
|
||||||
"fnstsw %%ax;"
|
|
||||||
"testb $4, %%ah;"
|
|
||||||
"jne 1b;"
|
|
||||||
: "+t"(a)
|
|
||||||
: "u"(b)
|
|
||||||
: "ax", "cc"
|
|
||||||
);
|
);
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
@@ -190,7 +167,7 @@ namespace BAN::Math
|
|||||||
template<floating_point T>
|
template<floating_point T>
|
||||||
static T modf(T x, T* iptr)
|
static T modf(T x, T* iptr)
|
||||||
{
|
{
|
||||||
const T frac = BAN::Math::fmod<T>(x, (T)1.0);
|
const T frac = BAN::Math::fmod<T>(x, 1);
|
||||||
*iptr = x - frac;
|
*iptr = x - frac;
|
||||||
return frac;
|
return frac;
|
||||||
}
|
}
|
||||||
@@ -198,15 +175,15 @@ namespace BAN::Math
|
|||||||
template<floating_point T>
|
template<floating_point T>
|
||||||
inline constexpr T frexp(T num, int* exp)
|
inline constexpr T frexp(T num, int* exp)
|
||||||
{
|
{
|
||||||
if (num == (T)0.0)
|
if (num == 0.0)
|
||||||
{
|
{
|
||||||
*exp = 0;
|
*exp = 0;
|
||||||
return (T)0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
T e;
|
T _exp;
|
||||||
asm("fxtract" : "+t"(num), "=u"(e));
|
asm("fxtract" : "+t"(num), "=u"(_exp));
|
||||||
*exp = (int)e + 1;
|
*exp = (int)_exp + 1;
|
||||||
return num / (T)2.0;
|
return num / (T)2.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,7 +251,6 @@ namespace BAN::Math
|
|||||||
"fstp %%st(1);"
|
"fstp %%st(1);"
|
||||||
: "+t"(x)
|
: "+t"(x)
|
||||||
);
|
);
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,9 +263,18 @@ namespace BAN::Math
|
|||||||
template<floating_point T>
|
template<floating_point T>
|
||||||
inline constexpr T pow(T x, T y)
|
inline constexpr T pow(T x, T y)
|
||||||
{
|
{
|
||||||
if (x == (T)0.0)
|
asm(
|
||||||
return (T)0.0;
|
"fyl2x;"
|
||||||
return exp2<T>(y * log2<T>(x));
|
"fld1;"
|
||||||
|
"fld %%st(1);"
|
||||||
|
"fprem;"
|
||||||
|
"f2xm1;"
|
||||||
|
"faddp;"
|
||||||
|
"fscale;"
|
||||||
|
: "+t"(x), "+u"(y)
|
||||||
|
);
|
||||||
|
|
||||||
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<floating_point T>
|
template<floating_point T>
|
||||||
@@ -325,27 +310,16 @@ namespace BAN::Math
|
|||||||
template<floating_point T>
|
template<floating_point T>
|
||||||
inline constexpr T sqrt(T x)
|
inline constexpr T sqrt(T x)
|
||||||
{
|
{
|
||||||
if constexpr(BAN::is_same_v<T, float>)
|
asm("fsqrt" : "+t"(x));
|
||||||
{
|
return x;
|
||||||
using v4sf = float __attribute__((vector_size(16)));
|
|
||||||
return __builtin_ia32_sqrtss((v4sf) { x, 0.0f, 0.0f, 0.0f })[0];
|
|
||||||
}
|
|
||||||
else if constexpr(BAN::is_same_v<T, double>)
|
|
||||||
{
|
|
||||||
using v2df = double __attribute__((vector_size(16)));
|
|
||||||
return __builtin_ia32_sqrtsd((v2df) { x, 0.0 })[0];
|
|
||||||
}
|
|
||||||
else if constexpr(BAN::is_same_v<T, long double>)
|
|
||||||
{
|
|
||||||
asm("fsqrt" : "+t"(x));
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<floating_point T>
|
template<floating_point T>
|
||||||
inline constexpr T cbrt(T value)
|
inline constexpr T cbrt(T value)
|
||||||
{
|
{
|
||||||
return pow<T>(value, (T)1.0 / (T)3.0);
|
if (value == 0.0)
|
||||||
|
return 0.0;
|
||||||
|
return pow<T>(value, 1.0 / 3.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<floating_point T>
|
template<floating_point T>
|
||||||
@@ -372,21 +346,30 @@ namespace BAN::Math
|
|||||||
inline constexpr T tan(T x)
|
inline constexpr T tan(T x)
|
||||||
{
|
{
|
||||||
T one, ret;
|
T one, ret;
|
||||||
asm("fptan" : "=t"(one), "=u"(ret) : "0"(x));
|
asm(
|
||||||
|
"fptan"
|
||||||
|
: "=t"(one), "=u"(ret)
|
||||||
|
: "0"(x)
|
||||||
|
);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<floating_point T>
|
template<floating_point T>
|
||||||
inline constexpr T atan2(T y, T x)
|
inline constexpr T atan2(T y, T x)
|
||||||
{
|
{
|
||||||
asm("fpatan" : "+t"(x) : "u"(y) : "st(1)");
|
asm(
|
||||||
|
"fpatan"
|
||||||
|
: "+t"(x)
|
||||||
|
: "u"(y)
|
||||||
|
: "st(1)"
|
||||||
|
);
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<floating_point T>
|
template<floating_point T>
|
||||||
inline constexpr T atan(T x)
|
inline constexpr T atan(T x)
|
||||||
{
|
{
|
||||||
return atan2<T>(x, (T)1.0);
|
return atan2<T>(x, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<floating_point T>
|
template<floating_point T>
|
||||||
@@ -395,10 +378,10 @@ namespace BAN::Math
|
|||||||
if (x == (T)0.0)
|
if (x == (T)0.0)
|
||||||
return (T)0.0;
|
return (T)0.0;
|
||||||
if (x == (T)1.0)
|
if (x == (T)1.0)
|
||||||
return +numbers::pi_v<T> / (T)2.0;
|
return numbers::pi_v<T> / (T)2.0;
|
||||||
if (x == (T)-1.0)
|
if (x == (T)-1.0)
|
||||||
return -numbers::pi_v<T> / (T)2.0;
|
return -numbers::pi_v<T> / (T)2.0;
|
||||||
return (T)2.0 * atan<T>(x / ((T)1.0 + sqrt<T>((T)1.0 - x * x)));
|
return (T)2.0 * atan<T>(x / (T(1.0) + sqrt<T>((T)1.0 - x * x)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<floating_point T>
|
template<floating_point T>
|
||||||
@@ -428,7 +411,7 @@ namespace BAN::Math
|
|||||||
template<floating_point T>
|
template<floating_point T>
|
||||||
inline constexpr T tanh(T x)
|
inline constexpr T tanh(T x)
|
||||||
{
|
{
|
||||||
const T exp_px = exp<T>(+x);
|
const T exp_px = exp<T>(x);
|
||||||
const T exp_nx = exp<T>(-x);
|
const T exp_nx = exp<T>(-x);
|
||||||
return (exp_px - exp_nx) / (exp_px + exp_nx);
|
return (exp_px - exp_nx) / (exp_px + exp_nx);
|
||||||
}
|
}
|
||||||
@@ -457,9 +440,4 @@ namespace BAN::Math
|
|||||||
return sqrt<T>(x * x + y * y);
|
return sqrt<T>(x * x + y * y);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BAN_MATH_POP_OPTIONS
|
|
||||||
#undef BAN_MATH_POP_OPTIONS
|
|
||||||
#pragma GCC pop_options
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,12 +9,10 @@
|
|||||||
namespace BAN
|
namespace BAN
|
||||||
{
|
{
|
||||||
#if defined(__is_kernel)
|
#if defined(__is_kernel)
|
||||||
static constexpr void*(*allocator)(size_t) = kmalloc;
|
static constexpr void*(&allocator)(size_t) = kmalloc;
|
||||||
static constexpr void*(*reallocator)(void*, size_t) = nullptr;
|
static constexpr void(&deallocator)(void*) = kfree;
|
||||||
static constexpr void(*deallocator)(void*) = kfree;
|
|
||||||
#else
|
#else
|
||||||
static constexpr void*(*allocator)(size_t) = malloc;
|
static constexpr void*(&allocator)(size_t) = malloc;
|
||||||
static constexpr void*(*reallocator)(void*, size_t) = realloc;
|
static constexpr void(&deallocator)(void*) = free;
|
||||||
static constexpr void(*deallocator)(void*) = free;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "BAN/Errors.h"
|
|
||||||
#include <BAN/Vector.h>
|
|
||||||
#include <BAN/Heap.h>
|
|
||||||
|
|
||||||
namespace BAN
|
|
||||||
{
|
|
||||||
|
|
||||||
template<typename T, typename Comp = less<T>>
|
|
||||||
class PriorityQueue
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PriorityQueue() = default;
|
|
||||||
PriorityQueue(Comp comp)
|
|
||||||
: m_comp(comp)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
ErrorOr<void> push(const T& value)
|
|
||||||
{
|
|
||||||
TRY(m_data.push_back(value));
|
|
||||||
push_heap(m_data.begin(), m_data.end());
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
ErrorOr<void> push(T&& value)
|
|
||||||
{
|
|
||||||
TRY(m_data.push_back(move(value)));
|
|
||||||
push_heap(m_data.begin(), m_data.end());
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
ErrorOr<void> emplace(Args&&... args) requires is_constructible_v<T, Args...>
|
|
||||||
{
|
|
||||||
TRY(m_data.emplace_back(forward<Args>(args)...));
|
|
||||||
push_heap(m_data.begin(), m_data.end());
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
void pop()
|
|
||||||
{
|
|
||||||
pop_heap(m_data.begin(), m_data.end());
|
|
||||||
m_data.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> reserve(Vector<T>::size_type size)
|
|
||||||
{
|
|
||||||
return m_data.reserve(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
T& top() { return m_data.front(); }
|
|
||||||
const T& top() const { return m_data.front(); }
|
|
||||||
|
|
||||||
bool empty() const { return m_data.empty(); }
|
|
||||||
Vector<T>::size_type size() const { return m_data.size(); }
|
|
||||||
Vector<T>::size_type capacity() const { return m_data.capacity(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
Comp m_comp;
|
|
||||||
Vector<T> m_data;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <BAN/Heap.h>
|
|
||||||
#include <BAN/Math.h>
|
#include <BAN/Math.h>
|
||||||
#include <BAN/Swap.h>
|
#include <BAN/Swap.h>
|
||||||
#include <BAN/Traits.h>
|
#include <BAN/Traits.h>
|
||||||
@@ -9,7 +8,7 @@
|
|||||||
namespace BAN::sort
|
namespace BAN::sort
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
template<typename It, typename Comp = less<typename It::value_type>>
|
||||||
void exchange_sort(It begin, It end, Comp comp = {})
|
void exchange_sort(It begin, It end, Comp comp = {})
|
||||||
{
|
{
|
||||||
for (It lhs = begin; lhs != end; ++lhs)
|
for (It lhs = begin; lhs != end; ++lhs)
|
||||||
@@ -43,7 +42,7 @@ namespace BAN::sort
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
template<typename It, typename Comp = less<typename It::value_type>>
|
||||||
void quick_sort(It begin, It end, Comp comp = {})
|
void quick_sort(It begin, It end, Comp comp = {})
|
||||||
{
|
{
|
||||||
if (distance(begin, end) <= 1)
|
if (distance(begin, end) <= 1)
|
||||||
@@ -53,14 +52,14 @@ namespace BAN::sort
|
|||||||
quick_sort(++mid, end, comp);
|
quick_sort(++mid, end, comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
template<typename It, typename Comp = less<typename It::value_type>>
|
||||||
void insertion_sort(It begin, It end, Comp comp = {})
|
void insertion_sort(It begin, It end, Comp comp = {})
|
||||||
{
|
{
|
||||||
if (distance(begin, end) <= 1)
|
if (distance(begin, end) <= 1)
|
||||||
return;
|
return;
|
||||||
for (It it1 = next(begin, 1); it1 != end; ++it1)
|
for (It it1 = next(begin, 1); it1 != end; ++it1)
|
||||||
{
|
{
|
||||||
auto x = move(*it1);
|
typename It::value_type x = move(*it1);
|
||||||
It it2 = it1;
|
It it2 = it1;
|
||||||
for (; it2 != begin && comp(x, *prev(it2, 1)); --it2)
|
for (; it2 != begin && comp(x, *prev(it2, 1)); --it2)
|
||||||
*it2 = move(*prev(it2, 1));
|
*it2 = move(*prev(it2, 1));
|
||||||
@@ -68,7 +67,83 @@ namespace BAN::sort
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename It, typename Comp>
|
||||||
|
void push_heap(It begin, size_t hole_index, size_t top_index, typename It::value_type value, Comp comp)
|
||||||
|
{
|
||||||
|
size_t parent = (hole_index - 1) / 2;
|
||||||
|
while (hole_index > top_index && comp(*next(begin, parent), value))
|
||||||
|
{
|
||||||
|
*next(begin, hole_index) = move(*next(begin, parent));
|
||||||
|
hole_index = parent;
|
||||||
|
parent = (hole_index - 1) / 2;
|
||||||
|
}
|
||||||
|
*next(begin, hole_index) = move(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename It, typename Comp>
|
||||||
|
void adjust_heap(It begin, size_t hole_index, size_t len, typename It::value_type value, Comp comp)
|
||||||
|
{
|
||||||
|
const size_t top_index = hole_index;
|
||||||
|
size_t child = hole_index;
|
||||||
|
while (child < (len - 1) / 2)
|
||||||
|
{
|
||||||
|
child = 2 * (child + 1);
|
||||||
|
if (comp(*next(begin, child), *next(begin, child - 1)))
|
||||||
|
child--;
|
||||||
|
*next(begin, hole_index) = move(*next(begin, child));
|
||||||
|
hole_index = child;
|
||||||
|
}
|
||||||
|
if (len % 2 == 0 && child == (len - 2) / 2)
|
||||||
|
{
|
||||||
|
child = 2 * (child + 1);
|
||||||
|
*next(begin, hole_index) = move(*next(begin, child - 1));
|
||||||
|
hole_index = child - 1;
|
||||||
|
}
|
||||||
|
push_heap(begin, hole_index, top_index, move(value), comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename It, typename Comp = less<typename It::value_type>>
|
||||||
|
void make_heap(It begin, It end, Comp comp = {})
|
||||||
|
{
|
||||||
|
const size_t len = distance(begin, end);
|
||||||
|
if (len <= 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
size_t parent = (len - 2) / 2;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
detail::adjust_heap(begin, parent, len, move(*next(begin, parent)), comp);
|
||||||
|
|
||||||
|
if (parent == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
parent--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename It, typename Comp = less<typename It::value_type>>
|
||||||
|
void sort_heap(It begin, It end, Comp comp = {})
|
||||||
|
{
|
||||||
|
const size_t len = distance(begin, end);
|
||||||
|
if (len <= 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
size_t last = len;
|
||||||
|
while (last > 1)
|
||||||
|
{
|
||||||
|
last--;
|
||||||
|
typename It::value_type x = move(*next(begin, last));
|
||||||
|
*next(begin, last) = move(*begin);
|
||||||
|
detail::adjust_heap(begin, 0, last, move(x), comp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename It, typename Comp = less<typename It::value_type>>
|
||||||
void heap_sort(It begin, It end, Comp comp = {})
|
void heap_sort(It begin, It end, Comp comp = {})
|
||||||
{
|
{
|
||||||
make_heap(begin, end, comp);
|
make_heap(begin, end, comp);
|
||||||
@@ -92,7 +167,7 @@ namespace BAN::sort
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
template<typename It, typename Comp = less<typename It::value_type>>
|
||||||
void intro_sort(It begin, It end, Comp comp = {})
|
void intro_sort(It begin, It end, Comp comp = {})
|
||||||
{
|
{
|
||||||
const size_t len = distance(begin, end);
|
const size_t len = distance(begin, end);
|
||||||
@@ -115,10 +190,10 @@ namespace BAN::sort
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename It, size_t radix = 256>
|
template<typename It, size_t radix = 256>
|
||||||
requires is_unsigned_v<it_value_type_t<It>> && (radix > 0 && (radix & (radix - 1)) == 0)
|
requires is_unsigned_v<typename It::value_type> && (radix > 0 && (radix & (radix - 1)) == 0)
|
||||||
BAN::ErrorOr<void> radix_sort(It begin, It end)
|
BAN::ErrorOr<void> radix_sort(It begin, It end)
|
||||||
{
|
{
|
||||||
using value_type = it_value_type_t<It>;
|
using value_type = typename It::value_type;
|
||||||
|
|
||||||
const size_t len = distance(begin, end);
|
const size_t len = distance(begin, end);
|
||||||
if (len <= 1)
|
if (len <= 1)
|
||||||
@@ -156,7 +231,7 @@ namespace BAN::sort
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
template<typename It, typename Comp = less<typename It::value_type>>
|
||||||
void sort(It begin, It end, Comp comp = {})
|
void sort(It begin, It end, Comp comp = {})
|
||||||
{
|
{
|
||||||
return intro_sort(begin, end, comp);
|
return intro_sort(begin, end, comp);
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ namespace BAN
|
|||||||
|
|
||||||
value_type* data() const
|
value_type* data() const
|
||||||
{
|
{
|
||||||
|
ASSERT(m_data);
|
||||||
return m_data;
|
return m_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,6 +84,7 @@ namespace BAN
|
|||||||
|
|
||||||
Span slice(size_type start, size_type length = ~size_type(0)) const
|
Span slice(size_type start, size_type length = ~size_type(0)) const
|
||||||
{
|
{
|
||||||
|
ASSERT(m_data);
|
||||||
ASSERT(start <= m_size);
|
ASSERT(start <= m_size);
|
||||||
if (length == ~size_type(0))
|
if (length == ~size_type(0))
|
||||||
length = m_size - start;
|
length = m_size - start;
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ namespace BAN
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using size_type = size_t;
|
using size_type = size_t;
|
||||||
using value_type = char;
|
|
||||||
using iterator = IteratorSimple<char, String>;
|
using iterator = IteratorSimple<char, String>;
|
||||||
using const_iterator = ConstIteratorSimple<char, String>;
|
using const_iterator = ConstIteratorSimple<char, String>;
|
||||||
static constexpr size_type sso_capacity = 15;
|
static constexpr size_type sso_capacity = 15;
|
||||||
@@ -353,9 +352,10 @@ namespace BAN::Formatter
|
|||||||
{
|
{
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
void print_argument(F putc, const String& string, const ValueFormat& format)
|
void print_argument(F putc, const String& string, const ValueFormat&)
|
||||||
{
|
{
|
||||||
print_argument(putc, string.sv(), format);
|
for (String::size_type i = 0; i < string.size(); i++)
|
||||||
|
putc(string[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ namespace BAN
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using size_type = size_t;
|
using size_type = size_t;
|
||||||
using value_type = char;
|
|
||||||
using const_iterator = ConstIteratorSimple<char, StringView>;
|
using const_iterator = ConstIteratorSimple<char, StringView>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -22,8 +21,7 @@ namespace BAN
|
|||||||
constexpr StringView(const char* string, size_type len = -1)
|
constexpr StringView(const char* string, size_type len = -1)
|
||||||
{
|
{
|
||||||
if (len == size_type(-1))
|
if (len == size_type(-1))
|
||||||
for (len = 0; string[len];)
|
len = strlen(string);
|
||||||
len++;
|
|
||||||
m_data = string;
|
m_data = string;
|
||||||
m_size = len;
|
m_size = len;
|
||||||
}
|
}
|
||||||
@@ -247,12 +245,10 @@ namespace BAN::Formatter
|
|||||||
{
|
{
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
void print_argument(F putc, const StringView& sv, const ValueFormat& format)
|
void print_argument(F putc, const StringView& sv, const ValueFormat&)
|
||||||
{
|
{
|
||||||
for (StringView::size_type i = 0; i < sv.size(); i++)
|
for (StringView::size_type i = 0; i < sv.size(); i++)
|
||||||
putc(sv[i]);
|
putc(sv[i]);
|
||||||
for (int i = sv.size(); i < format.fill; i++)
|
|
||||||
putc(' ');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,9 +61,6 @@ namespace BAN
|
|||||||
template<typename T> struct is_move_constructible { static constexpr bool value = is_constructible_v<T, T&&>; };
|
template<typename T> struct is_move_constructible { static constexpr bool value = is_constructible_v<T, T&&>; };
|
||||||
template<typename T> inline constexpr bool is_move_constructible_v = is_move_constructible<T>::value;
|
template<typename T> inline constexpr bool is_move_constructible_v = is_move_constructible<T>::value;
|
||||||
|
|
||||||
template<typename T> struct is_trivially_copyable { static constexpr bool value = __is_trivially_copyable(T); };
|
|
||||||
template<typename T> inline constexpr bool is_trivially_copyable_v = is_trivially_copyable<T>::value;
|
|
||||||
|
|
||||||
template<typename T> struct is_integral { static constexpr bool value = requires (T t, T* p, void (*f)(T)) { reinterpret_cast<T>(t); f(0); p + t; }; };
|
template<typename T> struct is_integral { static constexpr bool value = requires (T t, T* p, void (*f)(T)) { reinterpret_cast<T>(t); f(0); p + t; }; };
|
||||||
template<typename T> inline constexpr bool is_integral_v = is_integral<T>::value;
|
template<typename T> inline constexpr bool is_integral_v = is_integral<T>::value;
|
||||||
template<typename T> concept integral = is_integral_v<T>;
|
template<typename T> concept integral = is_integral_v<T>;
|
||||||
@@ -142,10 +139,6 @@ namespace BAN
|
|||||||
template<typename T> using make_signed_t = typename make_signed<T>::type;
|
template<typename T> using make_signed_t = typename make_signed<T>::type;
|
||||||
#undef __BAN_TRAITS_MAKE_SIGNED_CV
|
#undef __BAN_TRAITS_MAKE_SIGNED_CV
|
||||||
|
|
||||||
template<typename T> struct it_value_type { using value_type = T::value_type; };
|
|
||||||
template<typename T> struct it_value_type<T*> { using value_type = T; };
|
|
||||||
template<typename T> using it_value_type_t = typename it_value_type<T>::value_type;
|
|
||||||
|
|
||||||
template<typename T> struct less { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs < rhs; } };
|
template<typename T> struct less { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs < rhs; } };
|
||||||
template<typename T> struct equal { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs == rhs; } };
|
template<typename T> struct equal { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs == rhs; } };
|
||||||
template<typename T> struct greater { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs > rhs; } };
|
template<typename T> struct greater { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs > rhs; } };
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace BAN::UTF8
|
|||||||
return 3;
|
return 3;
|
||||||
if ((first_byte & 0xF8) == 0xF0)
|
if ((first_byte & 0xF8) == 0xF0)
|
||||||
return 4;
|
return 4;
|
||||||
return UTF8::invalid;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> requires (sizeof(T) == 1)
|
template<typename T> requires (sizeof(T) == 1)
|
||||||
|
|||||||
@@ -126,16 +126,14 @@ namespace BAN
|
|||||||
Variant(Variant&& other)
|
Variant(Variant&& other)
|
||||||
: m_index(other.m_index)
|
: m_index(other.m_index)
|
||||||
{
|
{
|
||||||
if (other.has_value())
|
detail::move_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
||||||
detail::move_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
|
||||||
other.clear();
|
other.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant(const Variant& other)
|
Variant(const Variant& other)
|
||||||
: m_index(other.m_index)
|
: m_index(other.m_index)
|
||||||
{
|
{
|
||||||
if (other.has_value())
|
detail::copy_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
||||||
detail::copy_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -159,13 +157,12 @@ namespace BAN
|
|||||||
|
|
||||||
Variant& operator=(Variant&& other)
|
Variant& operator=(Variant&& other)
|
||||||
{
|
{
|
||||||
if (m_index == other.m_index && m_index != invalid_index())
|
if (m_index == other.m_index)
|
||||||
detail::move_assign<Ts...>(m_index, other.m_storage, m_storage);
|
detail::move_assign<Ts...>(m_index, other.m_storage, m_storage);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
if (other.has_value())
|
detail::move_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
||||||
detail::move_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
|
||||||
m_index = other.m_index;
|
m_index = other.m_index;
|
||||||
}
|
}
|
||||||
other.clear();
|
other.clear();
|
||||||
@@ -174,13 +171,12 @@ namespace BAN
|
|||||||
|
|
||||||
Variant& operator=(const Variant& other)
|
Variant& operator=(const Variant& other)
|
||||||
{
|
{
|
||||||
if (m_index == other.m_index && m_index != invalid_index())
|
if (m_index == other.m_index)
|
||||||
detail::copy_assign<Ts...>(m_index, other.m_storage, m_storage);
|
detail::copy_assign<Ts...>(m_index, other.m_storage, m_storage);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
if (other.has_value())
|
detail::copy_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
||||||
detail::copy_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
|
||||||
m_index = other.m_index;
|
m_index = other.m_index;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ namespace BAN
|
|||||||
bool contains(const T&) const;
|
bool contains(const T&) const;
|
||||||
|
|
||||||
Span<T> span() { return Span(m_data, m_size); }
|
Span<T> span() { return Span(m_data, m_size); }
|
||||||
Span<const T> span() const { return Span(m_data, m_size); }
|
const Span<T> span() const { return Span(m_data, m_size); }
|
||||||
|
|
||||||
const T& operator[](size_type) const;
|
const T& operator[](size_type) const;
|
||||||
T& operator[](size_type);
|
T& operator[](size_type);
|
||||||
@@ -381,46 +381,19 @@ namespace BAN
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
ErrorOr<void> Vector<T>::ensure_capacity(size_type size)
|
ErrorOr<void> Vector<T>::ensure_capacity(size_type size)
|
||||||
{
|
{
|
||||||
static_assert(alignof(T) <= alignof(max_align_t), "over aligned types not supported");
|
|
||||||
|
|
||||||
if (m_capacity >= size)
|
if (m_capacity >= size)
|
||||||
return {};
|
return {};
|
||||||
|
size_type new_cap = BAN::Math::max<size_type>(size, m_capacity * 2);
|
||||||
const size_type new_cap = BAN::Math::max<size_type>(size, m_capacity * 2);
|
T* new_data = (T*)BAN::allocator(new_cap * sizeof(T));
|
||||||
|
if (new_data == nullptr)
|
||||||
if constexpr (BAN::is_trivially_copyable_v<T>)
|
return Error::from_errno(ENOMEM);
|
||||||
|
for (size_type i = 0; i < m_size; i++)
|
||||||
{
|
{
|
||||||
if constexpr (BAN::reallocator)
|
new (new_data + i) T(move(m_data[i]));
|
||||||
{
|
m_data[i].~T();
|
||||||
auto* new_data = static_cast<T*>(BAN::reallocator(m_data, new_cap * sizeof(T)));
|
|
||||||
if (new_data == nullptr)
|
|
||||||
return Error::from_errno(ENOMEM);
|
|
||||||
m_data = new_data;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto* new_data = static_cast<T*>(BAN::allocator(new_cap * sizeof(T)));
|
|
||||||
if (new_data == nullptr)
|
|
||||||
return Error::from_errno(ENOMEM);
|
|
||||||
memcpy(new_data, m_data, m_size * sizeof(T));
|
|
||||||
BAN::deallocator(m_data);
|
|
||||||
m_data = new_data;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
BAN::deallocator(m_data);
|
||||||
{
|
m_data = new_data;
|
||||||
auto* new_data = static_cast<T*>(BAN::allocator(new_cap * sizeof(T)));
|
|
||||||
if (new_data == nullptr)
|
|
||||||
return Error::from_errno(ENOMEM);
|
|
||||||
for (size_type i = 0; i < m_size; i++)
|
|
||||||
{
|
|
||||||
new (new_data + i) T(move(m_data[i]));
|
|
||||||
m_data[i].~T();
|
|
||||||
}
|
|
||||||
BAN::deallocator(m_data);
|
|
||||||
m_data = new_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_capacity = new_cap;
|
m_capacity = new_cap;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace BAN
|
|||||||
class WeakLink : public RefCounted<WeakLink<T>>
|
class WeakLink : public RefCounted<WeakLink<T>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RefPtr<T> try_lock() const
|
RefPtr<T> try_lock()
|
||||||
{
|
{
|
||||||
#if __is_kernel
|
#if __is_kernel
|
||||||
Kernel::SpinLockGuard _(m_weak_lock);
|
Kernel::SpinLockGuard _(m_weak_lock);
|
||||||
@@ -44,7 +44,7 @@ namespace BAN
|
|||||||
private:
|
private:
|
||||||
T* m_ptr;
|
T* m_ptr;
|
||||||
#if __is_kernel
|
#if __is_kernel
|
||||||
mutable Kernel::SpinLock m_weak_lock;
|
Kernel::SpinLock m_weak_lock;
|
||||||
#endif
|
#endif
|
||||||
friend class RefPtr<WeakLink<T>>;
|
friend class RefPtr<WeakLink<T>>;
|
||||||
};
|
};
|
||||||
@@ -99,7 +99,7 @@ namespace BAN
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<T> lock() const
|
RefPtr<T> lock()
|
||||||
{
|
{
|
||||||
if (m_link)
|
if (m_link)
|
||||||
return m_link->try_lock();
|
return m_link->try_lock();
|
||||||
|
|||||||
@@ -29,12 +29,12 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|||||||
|
|
||||||
# include headers of ${library} to ${target}
|
# include headers of ${library} to ${target}
|
||||||
function(banan_include_headers target library)
|
function(banan_include_headers target library)
|
||||||
target_include_directories(${target} PUBLIC $<TARGET_PROPERTY:${library},SOURCE_DIR>/include)
|
target_include_directories(${target} PRIVATE $<TARGET_PROPERTY:${library},SOURCE_DIR>/include)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
# include headers and link ${library} to ${target}
|
# include headers and link ${library} to ${target}
|
||||||
function(banan_link_library target library)
|
function(banan_link_library target library)
|
||||||
target_link_libraries(${target} PUBLIC ${library})
|
target_link_libraries(${target} PRIVATE ${library})
|
||||||
banan_include_headers(${target} ${library})
|
banan_include_headers(${target} ${library})
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ If you want to try out DOOM, you should first enter the GUI environment using th
|
|||||||
- [x] Basic graphical environment
|
- [x] Basic graphical environment
|
||||||
- [x] Terminal emulator
|
- [x] Terminal emulator
|
||||||
- [x] Status bar
|
- [x] Status bar
|
||||||
- [x] Program launcher
|
- [ ] Program launcher
|
||||||
- [ ] Some nice apps
|
- [ ] Some nice apps
|
||||||
- [x] ELF dynamic linking
|
- [x] ELF dynamic linking
|
||||||
- [x] copy-on-write memory
|
- [x] copy-on-write memory
|
||||||
@@ -118,8 +118,6 @@ To change the bootloader you can set environment variable BANAN\_BOOTLOADER; sup
|
|||||||
|
|
||||||
To run with UEFI set environment variable BANAN\_UEFI\_BOOT=1. You will also have to set OVMF\_PATH to the correct OVMF (default */usr/share/ovmf/x64/OVMF.fd*).
|
To run with UEFI set environment variable BANAN\_UEFI\_BOOT=1. You will also have to set OVMF\_PATH to the correct OVMF (default */usr/share/ovmf/x64/OVMF.fd*).
|
||||||
|
|
||||||
To build an image with no physical root filesystem, but an initrd set environment variable BANAN\_INITRD=1. This can be used when testing on hardware with unsupported USB controller.
|
|
||||||
|
|
||||||
If you have corrupted your disk image or want to create new one, you can either manually delete *build/banan-os.img* and build system will automatically create you a new one or you can run the following command.
|
If you have corrupted your disk image or want to create new one, you can either manually delete *build/banan-os.img* and build system will automatically create you a new one or you can run the following command.
|
||||||
```sh
|
```sh
|
||||||
./bos image-full
|
./bos image-full
|
||||||
|
|||||||
Binary file not shown.
@@ -1,16 +1,11 @@
|
|||||||
set(KERNEL_SOURCES
|
set(KERNEL_SOURCES
|
||||||
font/prefs.psf.o
|
font/prefs.psf.o
|
||||||
kernel/ACPI/ACPI.cpp
|
kernel/ACPI/ACPI.cpp
|
||||||
|
kernel/ACPI/BatterySystem.cpp
|
||||||
kernel/ACPI/AML/Namespace.cpp
|
kernel/ACPI/AML/Namespace.cpp
|
||||||
kernel/ACPI/AML/Node.cpp
|
kernel/ACPI/AML/Node.cpp
|
||||||
kernel/ACPI/AML/OpRegion.cpp
|
kernel/ACPI/AML/OpRegion.cpp
|
||||||
kernel/ACPI/BatterySystem.cpp
|
|
||||||
kernel/ACPI/EmbeddedController.cpp
|
|
||||||
kernel/APIC.cpp
|
kernel/APIC.cpp
|
||||||
kernel/Audio/AC97/Controller.cpp
|
|
||||||
kernel/Audio/Controller.cpp
|
|
||||||
kernel/Audio/HDAudio/AudioFunctionGroup.cpp
|
|
||||||
kernel/Audio/HDAudio/Controller.cpp
|
|
||||||
kernel/BootInfo.cpp
|
kernel/BootInfo.cpp
|
||||||
kernel/CPUID.cpp
|
kernel/CPUID.cpp
|
||||||
kernel/Credentials.cpp
|
kernel/Credentials.cpp
|
||||||
@@ -22,10 +17,8 @@ set(KERNEL_SOURCES
|
|||||||
kernel/Device/RandomDevice.cpp
|
kernel/Device/RandomDevice.cpp
|
||||||
kernel/Device/ZeroDevice.cpp
|
kernel/Device/ZeroDevice.cpp
|
||||||
kernel/ELF.cpp
|
kernel/ELF.cpp
|
||||||
kernel/Epoll.cpp
|
|
||||||
kernel/Errors.cpp
|
kernel/Errors.cpp
|
||||||
kernel/FS/DevFS/FileSystem.cpp
|
kernel/FS/DevFS/FileSystem.cpp
|
||||||
kernel/FS/EventFD.cpp
|
|
||||||
kernel/FS/Ext2/FileSystem.cpp
|
kernel/FS/Ext2/FileSystem.cpp
|
||||||
kernel/FS/Ext2/Inode.cpp
|
kernel/FS/Ext2/Inode.cpp
|
||||||
kernel/FS/FAT/FileSystem.cpp
|
kernel/FS/FAT/FileSystem.cpp
|
||||||
@@ -37,7 +30,6 @@ set(KERNEL_SOURCES
|
|||||||
kernel/FS/ProcFS/Inode.cpp
|
kernel/FS/ProcFS/Inode.cpp
|
||||||
kernel/FS/TmpFS/FileSystem.cpp
|
kernel/FS/TmpFS/FileSystem.cpp
|
||||||
kernel/FS/TmpFS/Inode.cpp
|
kernel/FS/TmpFS/Inode.cpp
|
||||||
kernel/FS/USTARModule.cpp
|
|
||||||
kernel/FS/VirtualFileSystem.cpp
|
kernel/FS/VirtualFileSystem.cpp
|
||||||
kernel/GDT.cpp
|
kernel/GDT.cpp
|
||||||
kernel/IDT.cpp
|
kernel/IDT.cpp
|
||||||
@@ -50,8 +42,6 @@ set(KERNEL_SOURCES
|
|||||||
kernel/Interruptable.cpp
|
kernel/Interruptable.cpp
|
||||||
kernel/InterruptController.cpp
|
kernel/InterruptController.cpp
|
||||||
kernel/kernel.cpp
|
kernel/kernel.cpp
|
||||||
kernel/Lock/SpinLock.cpp
|
|
||||||
kernel/Memory/ByteRingBuffer.cpp
|
|
||||||
kernel/Memory/DMARegion.cpp
|
kernel/Memory/DMARegion.cpp
|
||||||
kernel/Memory/FileBackedRegion.cpp
|
kernel/Memory/FileBackedRegion.cpp
|
||||||
kernel/Memory/Heap.cpp
|
kernel/Memory/Heap.cpp
|
||||||
@@ -65,7 +55,6 @@ set(KERNEL_SOURCES
|
|||||||
kernel/Networking/E1000/E1000.cpp
|
kernel/Networking/E1000/E1000.cpp
|
||||||
kernel/Networking/E1000/E1000E.cpp
|
kernel/Networking/E1000/E1000E.cpp
|
||||||
kernel/Networking/IPv4Layer.cpp
|
kernel/Networking/IPv4Layer.cpp
|
||||||
kernel/Networking/Loopback.cpp
|
|
||||||
kernel/Networking/NetworkInterface.cpp
|
kernel/Networking/NetworkInterface.cpp
|
||||||
kernel/Networking/NetworkLayer.cpp
|
kernel/Networking/NetworkLayer.cpp
|
||||||
kernel/Networking/NetworkManager.cpp
|
kernel/Networking/NetworkManager.cpp
|
||||||
@@ -82,6 +71,7 @@ set(KERNEL_SOURCES
|
|||||||
kernel/Processor.cpp
|
kernel/Processor.cpp
|
||||||
kernel/Random.cpp
|
kernel/Random.cpp
|
||||||
kernel/Scheduler.cpp
|
kernel/Scheduler.cpp
|
||||||
|
kernel/ThreadBlocker.cpp
|
||||||
kernel/SSP.cpp
|
kernel/SSP.cpp
|
||||||
kernel/Storage/ATA/AHCI/Controller.cpp
|
kernel/Storage/ATA/AHCI/Controller.cpp
|
||||||
kernel/Storage/ATA/AHCI/Device.cpp
|
kernel/Storage/ATA/AHCI/Device.cpp
|
||||||
@@ -104,7 +94,6 @@ set(KERNEL_SOURCES
|
|||||||
kernel/Terminal/TTY.cpp
|
kernel/Terminal/TTY.cpp
|
||||||
kernel/Terminal/VirtualTTY.cpp
|
kernel/Terminal/VirtualTTY.cpp
|
||||||
kernel/Thread.cpp
|
kernel/Thread.cpp
|
||||||
kernel/ThreadBlocker.cpp
|
|
||||||
kernel/Timer/HPET.cpp
|
kernel/Timer/HPET.cpp
|
||||||
kernel/Timer/PIT.cpp
|
kernel/Timer/PIT.cpp
|
||||||
kernel/Timer/RTC.cpp
|
kernel/Timer/RTC.cpp
|
||||||
@@ -112,7 +101,6 @@ set(KERNEL_SOURCES
|
|||||||
kernel/USB/Controller.cpp
|
kernel/USB/Controller.cpp
|
||||||
kernel/USB/Device.cpp
|
kernel/USB/Device.cpp
|
||||||
kernel/USB/HID/HIDDriver.cpp
|
kernel/USB/HID/HIDDriver.cpp
|
||||||
kernel/USB/HID/Joystick.cpp
|
|
||||||
kernel/USB/HID/Keyboard.cpp
|
kernel/USB/HID/Keyboard.cpp
|
||||||
kernel/USB/HID/Mouse.cpp
|
kernel/USB/HID/Mouse.cpp
|
||||||
kernel/USB/Hub/HubDriver.cpp
|
kernel/USB/Hub/HubDriver.cpp
|
||||||
@@ -139,8 +127,6 @@ if("${BANAN_ARCH}" STREQUAL "x86_64")
|
|||||||
arch/x86_64/Signal.S
|
arch/x86_64/Signal.S
|
||||||
arch/x86_64/Syscall.S
|
arch/x86_64/Syscall.S
|
||||||
arch/x86_64/Thread.S
|
arch/x86_64/Thread.S
|
||||||
arch/x86_64/User.S
|
|
||||||
arch/x86_64/Yield.S
|
|
||||||
)
|
)
|
||||||
elseif("${BANAN_ARCH}" STREQUAL "i686")
|
elseif("${BANAN_ARCH}" STREQUAL "i686")
|
||||||
set(KERNEL_SOURCES
|
set(KERNEL_SOURCES
|
||||||
@@ -151,8 +137,6 @@ elseif("${BANAN_ARCH}" STREQUAL "i686")
|
|||||||
arch/i686/Signal.S
|
arch/i686/Signal.S
|
||||||
arch/i686/Syscall.S
|
arch/i686/Syscall.S
|
||||||
arch/i686/Thread.S
|
arch/i686/Thread.S
|
||||||
arch/i686/User.S
|
|
||||||
arch/i686/Yield.S
|
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "unsupported architecure ${BANAN_ARCH}")
|
message(FATAL_ERROR "unsupported architecure ${BANAN_ARCH}")
|
||||||
@@ -174,12 +158,6 @@ set(KLIBC_SOURCES
|
|||||||
../userspace/libraries/LibC/arch/${BANAN_ARCH}/string.S
|
../userspace/libraries/LibC/arch/${BANAN_ARCH}/string.S
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LIBDEFLATE_SOURCE
|
|
||||||
../userspace/libraries/LibDEFLATE/Compressor.cpp
|
|
||||||
../userspace/libraries/LibDEFLATE/Decompressor.cpp
|
|
||||||
../userspace/libraries/LibDEFLATE/HuffmanTree.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
set(LIBFONT_SOURCES
|
set(LIBFONT_SOURCES
|
||||||
../userspace/libraries/LibFont/Font.cpp
|
../userspace/libraries/LibFont/Font.cpp
|
||||||
../userspace/libraries/LibFont/PSF.cpp
|
../userspace/libraries/LibFont/PSF.cpp
|
||||||
@@ -190,25 +168,18 @@ set(LIBINPUT_SOURCE
|
|||||||
../userspace/libraries/LibInput/KeyEvent.cpp
|
../userspace/libraries/LibInput/KeyEvent.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LIBQR_SOURCE
|
|
||||||
../userspace/libraries/LibQR/QRCode.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
set(KERNEL_SOURCES
|
set(KERNEL_SOURCES
|
||||||
${KERNEL_SOURCES}
|
${KERNEL_SOURCES}
|
||||||
${BAN_SOURCES}
|
${BAN_SOURCES}
|
||||||
${KLIBC_SOURCES}
|
${KLIBC_SOURCES}
|
||||||
${LIBDEFLATE_SOURCE}
|
|
||||||
${LIBFONT_SOURCES}
|
${LIBFONT_SOURCES}
|
||||||
${LIBINPUT_SOURCE}
|
${LIBINPUT_SOURCE}
|
||||||
${LIBQR_SOURCE}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(kernel ${KERNEL_SOURCES})
|
add_executable(kernel ${KERNEL_SOURCES})
|
||||||
|
|
||||||
target_compile_definitions(kernel PRIVATE __is_kernel)
|
target_compile_definitions(kernel PRIVATE __is_kernel)
|
||||||
target_compile_definitions(kernel PRIVATE __arch=${BANAN_ARCH})
|
target_compile_definitions(kernel PRIVATE __arch=${BANAN_ARCH})
|
||||||
target_compile_definitions(kernel PRIVATE LIBDEFLATE_AVOID_STACK=1)
|
|
||||||
|
|
||||||
target_compile_options(kernel PRIVATE
|
target_compile_options(kernel PRIVATE
|
||||||
-O2 -g
|
-O2 -g
|
||||||
@@ -262,11 +233,9 @@ add_custom_command(
|
|||||||
|
|
||||||
banan_include_headers(kernel ban)
|
banan_include_headers(kernel ban)
|
||||||
banan_include_headers(kernel libc)
|
banan_include_headers(kernel libc)
|
||||||
banan_include_headers(kernel libdeflate)
|
|
||||||
banan_include_headers(kernel libelf)
|
|
||||||
banan_include_headers(kernel libfont)
|
banan_include_headers(kernel libfont)
|
||||||
|
banan_include_headers(kernel libelf)
|
||||||
banan_include_headers(kernel libinput)
|
banan_include_headers(kernel libinput)
|
||||||
banan_include_headers(kernel libqr)
|
|
||||||
|
|
||||||
banan_install_headers(kernel)
|
banan_install_headers(kernel)
|
||||||
set_target_properties(kernel PROPERTIES OUTPUT_NAME banan-os.kernel)
|
set_target_properties(kernel PROPERTIES OUTPUT_NAME banan-os.kernel)
|
||||||
|
|||||||
@@ -206,7 +206,6 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
ASSERT(s_kernel);
|
ASSERT(s_kernel);
|
||||||
ASSERT(paddr);
|
ASSERT(paddr);
|
||||||
ASSERT(paddr % PAGE_SIZE == 0);
|
|
||||||
|
|
||||||
ASSERT(s_fast_page_lock.current_processor_has_lock());
|
ASSERT(s_fast_page_lock.current_processor_has_lock());
|
||||||
|
|
||||||
@@ -221,7 +220,7 @@ namespace Kernel
|
|||||||
ASSERT(!(pt[pte] & Flags::Present));
|
ASSERT(!(pt[pte] & Flags::Present));
|
||||||
pt[pte] = paddr | Flags::ReadWrite | Flags::Present;
|
pt[pte] = paddr | Flags::ReadWrite | Flags::Present;
|
||||||
|
|
||||||
asm volatile("invlpg (%0)" :: "r"(fast_page()) : "memory");
|
invalidate(fast_page(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PageTable::unmap_fast_page()
|
void PageTable::unmap_fast_page()
|
||||||
@@ -241,7 +240,7 @@ namespace Kernel
|
|||||||
ASSERT(pt[pte] & Flags::Present);
|
ASSERT(pt[pte] & Flags::Present);
|
||||||
pt[pte] = 0;
|
pt[pte] = 0;
|
||||||
|
|
||||||
asm volatile("invlpg (%0)" :: "r"(fast_page()) : "memory");
|
invalidate(fast_page(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<PageTable*> PageTable::create_userspace()
|
BAN::ErrorOr<PageTable*> PageTable::create_userspace()
|
||||||
@@ -314,8 +313,7 @@ namespace Kernel
|
|||||||
.type = Processor::SMPMessage::Type::FlushTLB,
|
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||||
.flush_tlb = {
|
.flush_tlb = {
|
||||||
.vaddr = vaddr,
|
.vaddr = vaddr,
|
||||||
.page_count = 1,
|
.page_count = 1
|
||||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -344,12 +342,8 @@ namespace Kernel
|
|||||||
uint64_t* pd = reinterpret_cast<uint64_t*>(P2V(pdpt[pdpte] & PAGE_ADDR_MASK));
|
uint64_t* pd = reinterpret_cast<uint64_t*>(P2V(pdpt[pdpte] & PAGE_ADDR_MASK));
|
||||||
uint64_t* pt = reinterpret_cast<uint64_t*>(P2V(pd[pde] & PAGE_ADDR_MASK));
|
uint64_t* pt = reinterpret_cast<uint64_t*>(P2V(pd[pde] & PAGE_ADDR_MASK));
|
||||||
|
|
||||||
const paddr_t old_paddr = pt[pte] & PAGE_ADDR_MASK;
|
|
||||||
|
|
||||||
pt[pte] = 0;
|
pt[pte] = 0;
|
||||||
|
invalidate(vaddr, send_smp_message);
|
||||||
if (old_paddr != 0)
|
|
||||||
invalidate(vaddr, send_smp_message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PageTable::unmap_range(vaddr_t vaddr, size_t size)
|
void PageTable::unmap_range(vaddr_t vaddr, size_t size)
|
||||||
@@ -366,8 +360,7 @@ namespace Kernel
|
|||||||
.type = Processor::SMPMessage::Type::FlushTLB,
|
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||||
.flush_tlb = {
|
.flush_tlb = {
|
||||||
.vaddr = vaddr,
|
.vaddr = vaddr,
|
||||||
.page_count = page_count,
|
.page_count = page_count
|
||||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -423,13 +416,9 @@ namespace Kernel
|
|||||||
uwr_flags &= ~Flags::Present;
|
uwr_flags &= ~Flags::Present;
|
||||||
|
|
||||||
uint64_t* pt = reinterpret_cast<uint64_t*>(P2V(pd[pde] & PAGE_ADDR_MASK));
|
uint64_t* pt = reinterpret_cast<uint64_t*>(P2V(pd[pde] & PAGE_ADDR_MASK));
|
||||||
|
|
||||||
const paddr_t old_paddr = pt[pte] & PAGE_ADDR_MASK;
|
|
||||||
|
|
||||||
pt[pte] = paddr | uwr_flags | extra_flags;
|
pt[pte] = paddr | uwr_flags | extra_flags;
|
||||||
|
|
||||||
if (old_paddr != 0)
|
invalidate(vaddr, send_smp_message);
|
||||||
invalidate(vaddr, send_smp_message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PageTable::map_range_at(paddr_t paddr, vaddr_t vaddr, size_t size, flags_t flags, MemoryType memory_type)
|
void PageTable::map_range_at(paddr_t paddr, vaddr_t vaddr, size_t size, flags_t flags, MemoryType memory_type)
|
||||||
@@ -448,8 +437,7 @@ namespace Kernel
|
|||||||
.type = Processor::SMPMessage::Type::FlushTLB,
|
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||||
.flush_tlb = {
|
.flush_tlb = {
|
||||||
.vaddr = vaddr,
|
.vaddr = vaddr,
|
||||||
.page_count = page_count,
|
.page_count = page_count
|
||||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -508,13 +496,13 @@ namespace Kernel
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PageTable::reserve_page(vaddr_t vaddr, bool only_free, bool send_smp_message)
|
bool PageTable::reserve_page(vaddr_t vaddr, bool only_free)
|
||||||
{
|
{
|
||||||
SpinLockGuard _(m_lock);
|
SpinLockGuard _(m_lock);
|
||||||
ASSERT(vaddr % PAGE_SIZE == 0);
|
ASSERT(vaddr % PAGE_SIZE == 0);
|
||||||
if (only_free && !is_page_free(vaddr))
|
if (only_free && !is_page_free(vaddr))
|
||||||
return false;
|
return false;
|
||||||
map_page_at(0, vaddr, Flags::Reserved, MemoryType::Normal, send_smp_message);
|
map_page_at(0, vaddr, Flags::Reserved);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -528,15 +516,7 @@ namespace Kernel
|
|||||||
if (only_free && !is_range_free(vaddr, bytes))
|
if (only_free && !is_range_free(vaddr, bytes))
|
||||||
return false;
|
return false;
|
||||||
for (size_t offset = 0; offset < bytes; offset += PAGE_SIZE)
|
for (size_t offset = 0; offset < bytes; offset += PAGE_SIZE)
|
||||||
reserve_page(vaddr + offset, true, false);
|
reserve_page(vaddr + offset);
|
||||||
Processor::broadcast_smp_message({
|
|
||||||
.type = Processor::SMPMessage::Type::FlushTLB,
|
|
||||||
.flush_tlb = {
|
|
||||||
.vaddr = vaddr,
|
|
||||||
.page_count = bytes / PAGE_SIZE,
|
|
||||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,72 +2,33 @@
|
|||||||
|
|
||||||
// stack contains
|
// stack contains
|
||||||
// return address
|
// return address
|
||||||
// return stack
|
|
||||||
// return rflags
|
|
||||||
// siginfo_t
|
|
||||||
// signal number
|
// signal number
|
||||||
// signal handler
|
// signal handler
|
||||||
|
|
||||||
.global signal_trampoline
|
.global signal_trampoline
|
||||||
signal_trampoline:
|
signal_trampoline:
|
||||||
pushl %esi // gregs
|
|
||||||
pushl %edi
|
|
||||||
pushl %edx
|
|
||||||
pushl %ecx
|
|
||||||
pushl %ebx
|
|
||||||
pushl %eax
|
|
||||||
pushl %ebp
|
pushl %ebp
|
||||||
|
movl %esp, %ebp
|
||||||
|
|
||||||
// FIXME: populate these
|
pusha
|
||||||
xorl %eax, %eax
|
|
||||||
pushl %eax // stack
|
|
||||||
pushl %eax
|
|
||||||
pushl %eax
|
|
||||||
pushl %eax // sigset
|
|
||||||
pushl %eax
|
|
||||||
pushl %eax // link
|
|
||||||
|
|
||||||
movl %esp, %edx // ucontext
|
movl 40(%esp), %edi
|
||||||
leal 60(%esp), %esi // siginfo
|
movl 36(%esp), %eax
|
||||||
movl 56(%esp), %edi // signal number
|
|
||||||
movl 52(%esp), %eax // handlers
|
|
||||||
|
|
||||||
// align stack to 16 bytes
|
// align stack to 16 bytes
|
||||||
movl %esp, %ebp
|
movl %esp, %ebp
|
||||||
andl $-16, %esp
|
andl $-16, %esp
|
||||||
|
|
||||||
subl $512, %esp
|
subl $12, %esp
|
||||||
fxsave (%esp)
|
|
||||||
|
|
||||||
subl $4, %esp
|
|
||||||
pushl %edx
|
|
||||||
pushl %esi
|
|
||||||
pushl %edi
|
pushl %edi
|
||||||
call *%eax
|
call *%eax
|
||||||
addl $16, %esp
|
addl $16, %esp
|
||||||
|
|
||||||
fxrstor (%esp)
|
|
||||||
addl $512, %esp
|
|
||||||
|
|
||||||
// restore stack
|
// restore stack
|
||||||
movl %ebp, %esp
|
movl %ebp, %esp
|
||||||
addl $24, %esp
|
popa
|
||||||
|
|
||||||
// restore registers
|
leave
|
||||||
popl %ebp
|
addl $8, %esp
|
||||||
popl %eax
|
|
||||||
popl %ebx
|
|
||||||
popl %ecx
|
|
||||||
popl %edx
|
|
||||||
popl %edi
|
|
||||||
popl %esi
|
|
||||||
|
|
||||||
// skip handler, number, siginfo_t
|
|
||||||
addl $44, %esp
|
|
||||||
|
|
||||||
// restore flags
|
|
||||||
popf
|
|
||||||
|
|
||||||
movl (%esp), %esp
|
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
// arguments in EAX, EBX, ECX, EDX, ESI, EDI
|
// arguments in EAX, EBX, ECX, EDX, ESI, EDI
|
||||||
.global asm_syscall_handler
|
.global asm_syscall_handler
|
||||||
asm_syscall_handler:
|
asm_syscall_handler:
|
||||||
|
# save segment registers
|
||||||
|
pushw %ds
|
||||||
|
pushw %es
|
||||||
|
pushw %fs
|
||||||
|
pushw %gs
|
||||||
|
|
||||||
# save general purpose registers
|
# save general purpose registers
|
||||||
pushl %ebx
|
pushl %ebx
|
||||||
pushl %ecx
|
pushl %ecx
|
||||||
@@ -12,10 +18,13 @@ asm_syscall_handler:
|
|||||||
|
|
||||||
# align stack
|
# align stack
|
||||||
movl %esp, %ebp
|
movl %esp, %ebp
|
||||||
andl $-16, %esp
|
subl $15, %esp
|
||||||
|
andl $0xFFFFFFF0, %esp
|
||||||
|
|
||||||
# push arguments
|
# push arguments
|
||||||
subl $8, %esp
|
subl $4, %esp
|
||||||
|
pushl %ebp
|
||||||
|
addl $32, (%esp)
|
||||||
pushl %edi
|
pushl %edi
|
||||||
pushl %esi
|
pushl %esi
|
||||||
pushl %edx
|
pushl %edx
|
||||||
@@ -35,15 +44,6 @@ asm_syscall_handler:
|
|||||||
|
|
||||||
movl %ebp, %esp
|
movl %ebp, %esp
|
||||||
|
|
||||||
# restore userspace segments
|
|
||||||
movw $(0x20 | 3), %bx
|
|
||||||
movw %bx, %ds
|
|
||||||
movw %bx, %es
|
|
||||||
movw $(0x30 | 3), %bx
|
|
||||||
movw %bx, %fs
|
|
||||||
movw $(0x38 | 3), %bx
|
|
||||||
movw %bx, %gs
|
|
||||||
|
|
||||||
# restore general purpose registers
|
# restore general purpose registers
|
||||||
popl %ebp
|
popl %ebp
|
||||||
popl %esi
|
popl %esi
|
||||||
@@ -52,6 +52,12 @@ asm_syscall_handler:
|
|||||||
popl %ecx
|
popl %ecx
|
||||||
popl %ebx
|
popl %ebx
|
||||||
|
|
||||||
|
# restore segment registers
|
||||||
|
popw %gs
|
||||||
|
popw %fs
|
||||||
|
popw %es
|
||||||
|
popw %ds
|
||||||
|
|
||||||
iret
|
iret
|
||||||
|
|
||||||
.global sys_fork_trampoline
|
.global sys_fork_trampoline
|
||||||
|
|||||||
@@ -31,18 +31,25 @@ start_kernel_thread:
|
|||||||
subl $12, %esp
|
subl $12, %esp
|
||||||
pushl %edi
|
pushl %edi
|
||||||
call *%esi
|
call *%esi
|
||||||
|
addl $16, %esp
|
||||||
|
|
||||||
|
|
||||||
.global start_userspace_thread
|
.global start_userspace_thread
|
||||||
start_userspace_thread:
|
start_userspace_thread:
|
||||||
|
call load_thread_sse
|
||||||
|
|
||||||
call get_thread_start_sp
|
call get_thread_start_sp
|
||||||
movl %eax, %esp
|
movl %eax, %esp
|
||||||
|
|
||||||
|
# ds, es = user data
|
||||||
movw $(0x20 | 3), %bx
|
movw $(0x20 | 3), %bx
|
||||||
movw %bx, %ds
|
movw %bx, %ds
|
||||||
movw %bx, %es
|
movw %bx, %es
|
||||||
|
# gs = thread local
|
||||||
movw $(0x30 | 3), %bx
|
movw $(0x30 | 3), %bx
|
||||||
movw %bx, %fs
|
|
||||||
movw $(0x38 | 3), %bx
|
|
||||||
movw %bx, %gs
|
movw %bx, %gs
|
||||||
|
# fs = 0
|
||||||
|
xorw %bx, %bx
|
||||||
|
movw %bx, %fs
|
||||||
|
|
||||||
iret
|
iret
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
# bool safe_user_memcpy(void*, const void*, size_t)
|
|
||||||
.global safe_user_memcpy
|
|
||||||
.global safe_user_memcpy_end
|
|
||||||
.global safe_user_memcpy_fault
|
|
||||||
safe_user_memcpy:
|
|
||||||
xorl %eax, %eax
|
|
||||||
xchgl 4(%esp), %edi
|
|
||||||
xchgl 8(%esp), %esi
|
|
||||||
movl 12(%esp), %ecx
|
|
||||||
movl %edi, %edx
|
|
||||||
rep movsb
|
|
||||||
movl 4(%esp), %edi
|
|
||||||
movl 8(%esp), %esi
|
|
||||||
incl %eax
|
|
||||||
safe_user_memcpy_fault:
|
|
||||||
ret
|
|
||||||
safe_user_memcpy_end:
|
|
||||||
|
|
||||||
# bool safe_user_strncpy(void*, const void*, size_t)
|
|
||||||
.global safe_user_strncpy
|
|
||||||
.global safe_user_strncpy_end
|
|
||||||
.global safe_user_strncpy_fault
|
|
||||||
safe_user_strncpy:
|
|
||||||
xchgl 4(%esp), %edi
|
|
||||||
xchgl 8(%esp), %esi
|
|
||||||
movl 12(%esp), %ecx
|
|
||||||
|
|
||||||
testl %ecx, %ecx
|
|
||||||
jz safe_user_strncpy_fault
|
|
||||||
|
|
||||||
.safe_user_strncpy_loop:
|
|
||||||
movb (%esi), %al
|
|
||||||
movb %al, (%edi)
|
|
||||||
testb %al, %al
|
|
||||||
jz .safe_user_strncpy_done
|
|
||||||
|
|
||||||
incl %edi
|
|
||||||
incl %esi
|
|
||||||
decl %ecx
|
|
||||||
jnz .safe_user_strncpy_loop
|
|
||||||
|
|
||||||
safe_user_strncpy_fault:
|
|
||||||
xorl %eax, %eax
|
|
||||||
jmp .safe_user_strncpy_return
|
|
||||||
|
|
||||||
.safe_user_strncpy_done:
|
|
||||||
movl $1, %eax
|
|
||||||
|
|
||||||
.safe_user_strncpy_return:
|
|
||||||
movl 4(%esp), %edi
|
|
||||||
movl 8(%esp), %esi
|
|
||||||
ret
|
|
||||||
|
|
||||||
safe_user_strncpy_end:
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
.global asm_yield_trampoline
|
|
||||||
asm_yield_trampoline:
|
|
||||||
leal 4(%esp), %ecx
|
|
||||||
movl 4(%esp), %esp
|
|
||||||
|
|
||||||
pushl -4(%ecx)
|
|
||||||
pushl %ecx
|
|
||||||
pushl %eax
|
|
||||||
pushl %ebx
|
|
||||||
pushl %esi
|
|
||||||
pushl %edi
|
|
||||||
pushl %ebp
|
|
||||||
|
|
||||||
pushl %esp
|
|
||||||
call scheduler_on_yield
|
|
||||||
addl $4, %esp
|
|
||||||
|
|
||||||
popl %ebp
|
|
||||||
popl %edi
|
|
||||||
popl %esi
|
|
||||||
popl %ebx
|
|
||||||
popl %eax
|
|
||||||
movl 4(%esp), %ecx
|
|
||||||
movl 0(%esp), %esp
|
|
||||||
jmp *%ecx
|
|
||||||
@@ -14,23 +14,6 @@
|
|||||||
# multiboot2 header
|
# multiboot2 header
|
||||||
.section .multiboot, "aw"
|
.section .multiboot, "aw"
|
||||||
.align 8
|
.align 8
|
||||||
multiboot_start:
|
|
||||||
.long 0x1BADB002
|
|
||||||
.long (1 << 2) # page align modules
|
|
||||||
.long -(0x1BADB002 + (1 << 2))
|
|
||||||
|
|
||||||
.long 0
|
|
||||||
.long 0
|
|
||||||
.long 0
|
|
||||||
.long 0
|
|
||||||
.long 0
|
|
||||||
|
|
||||||
.long 0
|
|
||||||
.long FB_WIDTH
|
|
||||||
.long FB_HEIGHT
|
|
||||||
.long FB_BPP
|
|
||||||
multiboot_end:
|
|
||||||
.align 8
|
|
||||||
multiboot2_start:
|
multiboot2_start:
|
||||||
.long 0xE85250D6
|
.long 0xE85250D6
|
||||||
.long 0
|
.long 0
|
||||||
@@ -53,12 +36,6 @@ multiboot2_start:
|
|||||||
.long 12
|
.long 12
|
||||||
.long V2P(_start)
|
.long V2P(_start)
|
||||||
|
|
||||||
# page align modules
|
|
||||||
.align 8
|
|
||||||
.short 6
|
|
||||||
.short 0
|
|
||||||
.long 8
|
|
||||||
|
|
||||||
.align 8
|
.align 8
|
||||||
.short 0
|
.short 0
|
||||||
.short 0
|
.short 0
|
||||||
@@ -76,10 +53,10 @@ bananboot_start:
|
|||||||
bananboot_end:
|
bananboot_end:
|
||||||
|
|
||||||
.section .bss, "aw", @nobits
|
.section .bss, "aw", @nobits
|
||||||
.global g_boot_stack_top
|
.align 4096
|
||||||
g_boot_stack_bottom:
|
boot_stack_bottom:
|
||||||
.skip 4096 * 4
|
.skip 4096 * 4
|
||||||
g_boot_stack_top:
|
boot_stack_top:
|
||||||
|
|
||||||
.global g_kernel_cmdline
|
.global g_kernel_cmdline
|
||||||
g_kernel_cmdline:
|
g_kernel_cmdline:
|
||||||
@@ -184,13 +161,6 @@ enable_sse:
|
|||||||
movl %eax, %cr4
|
movl %eax, %cr4
|
||||||
ret
|
ret
|
||||||
|
|
||||||
enable_tsc:
|
|
||||||
# allow userspace to use RDTSC
|
|
||||||
movl %cr4, %ecx
|
|
||||||
andl $0xFFFFFFFB, %ecx
|
|
||||||
movl %ecx, %cr4
|
|
||||||
ret
|
|
||||||
|
|
||||||
initialize_paging:
|
initialize_paging:
|
||||||
# enable PAE
|
# enable PAE
|
||||||
movl %cr4, %ecx
|
movl %cr4, %ecx
|
||||||
@@ -218,7 +188,7 @@ _start:
|
|||||||
movl %ebx, V2P(bootloader_info)
|
movl %ebx, V2P(bootloader_info)
|
||||||
|
|
||||||
# load boot stack
|
# load boot stack
|
||||||
movl $V2P(g_boot_stack_top), %esp
|
movl $V2P(boot_stack_top), %esp
|
||||||
|
|
||||||
# load boot GDT
|
# load boot GDT
|
||||||
lgdt V2P(boot_gdtr)
|
lgdt V2P(boot_gdtr)
|
||||||
@@ -233,11 +203,10 @@ gdt_flush:
|
|||||||
# do processor initialization
|
# do processor initialization
|
||||||
call check_requirements
|
call check_requirements
|
||||||
call enable_sse
|
call enable_sse
|
||||||
call enable_tsc
|
|
||||||
call initialize_paging
|
call initialize_paging
|
||||||
|
|
||||||
# load higher half stack pointer
|
# load higher half stack pointer
|
||||||
movl $g_boot_stack_top, %esp
|
movl $boot_stack_top, %esp
|
||||||
|
|
||||||
# jump to higher half
|
# jump to higher half
|
||||||
leal higher_half, %ecx
|
leal higher_half, %ecx
|
||||||
@@ -310,7 +279,6 @@ ap_protected_mode:
|
|||||||
movb $1, AP_V2P(ap_stack_loaded)
|
movb $1, AP_V2P(ap_stack_loaded)
|
||||||
|
|
||||||
leal V2P(enable_sse), %ecx; call *%ecx
|
leal V2P(enable_sse), %ecx; call *%ecx
|
||||||
leal V2P(enable_tsc), %ecx; call *%ecx
|
|
||||||
leal V2P(initialize_paging), %ecx; call *%ecx
|
leal V2P(initialize_paging), %ecx; call *%ecx
|
||||||
|
|
||||||
# load boot gdt and enter long mode
|
# load boot gdt and enter long mode
|
||||||
|
|||||||
@@ -1,33 +1,32 @@
|
|||||||
.macro maybe_load_kernel_segments, n
|
.macro push_userspace
|
||||||
testb $3, \n(%esp)
|
pushw %gs
|
||||||
jz 1f; jnp 1f
|
pushw %fs
|
||||||
|
pushw %es
|
||||||
|
pushw %ds
|
||||||
|
pushal
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro load_kernel_segments
|
||||||
movw $0x10, %ax
|
movw $0x10, %ax
|
||||||
movw %ax, %ds
|
movw %ax, %ds
|
||||||
movw %ax, %es
|
movw %ax, %es
|
||||||
movw %ax, %fs
|
movw %ax, %fs
|
||||||
|
|
||||||
movw $0x28, %ax
|
movw $0x28, %ax
|
||||||
movw %ax, %gs
|
movw %ax, %gs
|
||||||
1:
|
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro maybe_load_userspace_segments, n
|
.macro pop_userspace
|
||||||
testb $3, \n(%esp)
|
popal
|
||||||
jz 1f; jnp 1f
|
popw %ds
|
||||||
|
popw %es
|
||||||
movw $(0x20 | 3), %bx
|
popw %fs
|
||||||
movw %bx, %ds
|
popw %gs
|
||||||
movw %bx, %es
|
|
||||||
movw $(0x30 | 3), %bx
|
|
||||||
movw %bx, %fs
|
|
||||||
movw $(0x38 | 3), %bx
|
|
||||||
movw %bx, %gs
|
|
||||||
1:
|
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
isr_stub:
|
isr_stub:
|
||||||
pushal
|
push_userspace
|
||||||
maybe_load_kernel_segments 44
|
load_kernel_segments
|
||||||
cld
|
cld
|
||||||
|
|
||||||
movl %cr0, %eax; pushl %eax
|
movl %cr0, %eax; pushl %eax
|
||||||
@@ -35,39 +34,33 @@ isr_stub:
|
|||||||
movl %cr3, %eax; pushl %eax
|
movl %cr3, %eax; pushl %eax
|
||||||
movl %cr4, %eax; pushl %eax
|
movl %cr4, %eax; pushl %eax
|
||||||
|
|
||||||
movl 48(%esp), %edi // isr number
|
movl %esp, %eax // register ptr
|
||||||
movl 52(%esp), %esi // error code
|
leal 64(%esp), %ebx // interrupt stack ptr
|
||||||
leal 56(%esp), %edx // interrupt stack ptr
|
movl 60(%esp), %ecx // error code
|
||||||
movl %esp, %ecx // register ptr
|
movl 56(%esp), %edx // isr number
|
||||||
|
|
||||||
# stack frame for stack trace
|
|
||||||
leal 56(%esp), %eax
|
|
||||||
pushl (%eax)
|
|
||||||
pushl %ebp
|
|
||||||
|
|
||||||
movl %esp, %ebp
|
movl %esp, %ebp
|
||||||
andl $-16, %esp
|
andl $-16, %esp
|
||||||
|
|
||||||
|
pushl %eax
|
||||||
|
pushl %ebx
|
||||||
pushl %ecx
|
pushl %ecx
|
||||||
pushl %edx
|
pushl %edx
|
||||||
pushl %esi
|
|
||||||
pushl %edi
|
|
||||||
call cpp_isr_handler
|
call cpp_isr_handler
|
||||||
|
|
||||||
movl %ebp, %esp
|
movl %ebp, %esp
|
||||||
addl $24, %esp
|
addl $16, %esp
|
||||||
|
|
||||||
maybe_load_userspace_segments 44
|
pop_userspace
|
||||||
popal
|
|
||||||
addl $8, %esp
|
addl $8, %esp
|
||||||
iret
|
iret
|
||||||
|
|
||||||
irq_stub:
|
irq_stub:
|
||||||
pushal
|
push_userspace
|
||||||
maybe_load_kernel_segments 44
|
load_kernel_segments
|
||||||
cld
|
cld
|
||||||
|
|
||||||
movl 32(%esp), %edi # interrupt number
|
movl 40(%esp), %edi # interrupt number
|
||||||
|
|
||||||
movl %esp, %ebp
|
movl %esp, %ebp
|
||||||
andl $-16, %esp
|
andl $-16, %esp
|
||||||
@@ -78,15 +71,36 @@ irq_stub:
|
|||||||
|
|
||||||
movl %ebp, %esp
|
movl %ebp, %esp
|
||||||
|
|
||||||
maybe_load_userspace_segments 44
|
pop_userspace
|
||||||
popal
|
|
||||||
addl $8, %esp
|
addl $8, %esp
|
||||||
iret
|
iret
|
||||||
|
|
||||||
|
.global asm_yield_handler
|
||||||
|
asm_yield_handler:
|
||||||
|
# This can only be called from kernel, so no segment saving is needed
|
||||||
|
pushal
|
||||||
|
cld
|
||||||
|
|
||||||
|
leal 32(%esp), %edi # interrupt stack ptr
|
||||||
|
movl %esp, %esi # interrupt registers ptr
|
||||||
|
|
||||||
|
movl %esp, %ebp
|
||||||
|
andl $-16, %esp
|
||||||
|
|
||||||
|
subl $8, %esp
|
||||||
|
pushl %esi
|
||||||
|
pushl %edi
|
||||||
|
call cpp_yield_handler
|
||||||
|
|
||||||
|
movl %ebp, %esp
|
||||||
|
|
||||||
|
popal
|
||||||
|
iret
|
||||||
|
|
||||||
.global asm_ipi_handler
|
.global asm_ipi_handler
|
||||||
asm_ipi_handler:
|
asm_ipi_handler:
|
||||||
pushal
|
push_userspace
|
||||||
maybe_load_kernel_segments 36
|
load_kernel_segments
|
||||||
cld
|
cld
|
||||||
|
|
||||||
movl %esp, %ebp
|
movl %esp, %ebp
|
||||||
@@ -96,14 +110,13 @@ asm_ipi_handler:
|
|||||||
|
|
||||||
movl %ebp, %esp
|
movl %ebp, %esp
|
||||||
|
|
||||||
maybe_load_userspace_segments 36
|
pop_userspace
|
||||||
popal
|
|
||||||
iret
|
iret
|
||||||
|
|
||||||
.global asm_timer_handler
|
.global asm_timer_handler
|
||||||
asm_timer_handler:
|
asm_timer_handler:
|
||||||
pushal
|
push_userspace
|
||||||
maybe_load_kernel_segments 36
|
load_kernel_segments
|
||||||
cld
|
cld
|
||||||
|
|
||||||
movl %esp, %ebp
|
movl %esp, %ebp
|
||||||
@@ -113,8 +126,7 @@ asm_timer_handler:
|
|||||||
|
|
||||||
movl %ebp, %esp
|
movl %ebp, %esp
|
||||||
|
|
||||||
maybe_load_userspace_segments 36
|
pop_userspace
|
||||||
popal
|
|
||||||
iret
|
iret
|
||||||
|
|
||||||
.macro isr n
|
.macro isr n
|
||||||
|
|||||||
@@ -503,7 +503,6 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
ASSERT(s_kernel);
|
ASSERT(s_kernel);
|
||||||
ASSERT(paddr);
|
ASSERT(paddr);
|
||||||
ASSERT(paddr % PAGE_SIZE == 0);
|
|
||||||
|
|
||||||
ASSERT(s_fast_page_lock.current_processor_has_lock());
|
ASSERT(s_fast_page_lock.current_processor_has_lock());
|
||||||
|
|
||||||
@@ -521,7 +520,7 @@ namespace Kernel
|
|||||||
ASSERT(!(pt[pte] & Flags::Present));
|
ASSERT(!(pt[pte] & Flags::Present));
|
||||||
pt[pte] = paddr | Flags::ReadWrite | Flags::Present;
|
pt[pte] = paddr | Flags::ReadWrite | Flags::Present;
|
||||||
|
|
||||||
asm volatile("invlpg (%0)" :: "r"(fast_page()) : "memory");
|
invalidate(fast_page(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PageTable::unmap_fast_page()
|
void PageTable::unmap_fast_page()
|
||||||
@@ -544,7 +543,7 @@ namespace Kernel
|
|||||||
ASSERT(pt[pte] & Flags::Present);
|
ASSERT(pt[pte] & Flags::Present);
|
||||||
pt[pte] = 0;
|
pt[pte] = 0;
|
||||||
|
|
||||||
asm volatile("invlpg (%0)" :: "r"(fast_page()) : "memory");
|
invalidate(fast_page(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<PageTable*> PageTable::create_userspace()
|
BAN::ErrorOr<PageTable*> PageTable::create_userspace()
|
||||||
@@ -623,8 +622,7 @@ namespace Kernel
|
|||||||
.type = Processor::SMPMessage::Type::FlushTLB,
|
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||||
.flush_tlb = {
|
.flush_tlb = {
|
||||||
.vaddr = vaddr,
|
.vaddr = vaddr,
|
||||||
.page_count = 1,
|
.page_count = 1
|
||||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -659,12 +657,8 @@ namespace Kernel
|
|||||||
uint64_t* pd = P2V(pdpt[pdpte] & s_page_addr_mask);
|
uint64_t* pd = P2V(pdpt[pdpte] & s_page_addr_mask);
|
||||||
uint64_t* pt = P2V(pd[pde] & s_page_addr_mask);
|
uint64_t* pt = P2V(pd[pde] & s_page_addr_mask);
|
||||||
|
|
||||||
const paddr_t old_paddr = pt[pte] & PAGE_ADDR_MASK;
|
|
||||||
|
|
||||||
pt[pte] = 0;
|
pt[pte] = 0;
|
||||||
|
invalidate(vaddr, send_smp_message);
|
||||||
if (old_paddr != 0)
|
|
||||||
invalidate(vaddr, send_smp_message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PageTable::unmap_range(vaddr_t vaddr, size_t size)
|
void PageTable::unmap_range(vaddr_t vaddr, size_t size)
|
||||||
@@ -681,8 +675,7 @@ namespace Kernel
|
|||||||
.type = Processor::SMPMessage::Type::FlushTLB,
|
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||||
.flush_tlb = {
|
.flush_tlb = {
|
||||||
.vaddr = vaddr,
|
.vaddr = vaddr,
|
||||||
.page_count = page_count,
|
.page_count = page_count
|
||||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -748,12 +741,9 @@ namespace Kernel
|
|||||||
if (!(flags & Flags::Present))
|
if (!(flags & Flags::Present))
|
||||||
uwr_flags &= ~Flags::Present;
|
uwr_flags &= ~Flags::Present;
|
||||||
|
|
||||||
const paddr_t old_paddr = pt[pte] & PAGE_ADDR_MASK;
|
|
||||||
|
|
||||||
pt[pte] = paddr | uwr_flags | extra_flags;
|
pt[pte] = paddr | uwr_flags | extra_flags;
|
||||||
|
|
||||||
if (old_paddr != 0)
|
invalidate(vaddr, send_smp_message);
|
||||||
invalidate(vaddr, send_smp_message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PageTable::map_range_at(paddr_t paddr, vaddr_t vaddr, size_t size, flags_t flags, MemoryType memory_type)
|
void PageTable::map_range_at(paddr_t paddr, vaddr_t vaddr, size_t size, flags_t flags, MemoryType memory_type)
|
||||||
@@ -774,8 +764,7 @@ namespace Kernel
|
|||||||
.type = Processor::SMPMessage::Type::FlushTLB,
|
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||||
.flush_tlb = {
|
.flush_tlb = {
|
||||||
.vaddr = vaddr,
|
.vaddr = vaddr,
|
||||||
.page_count = page_count,
|
.page_count = page_count
|
||||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -824,13 +813,13 @@ namespace Kernel
|
|||||||
return page_data & s_page_addr_mask;
|
return page_data & s_page_addr_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PageTable::reserve_page(vaddr_t vaddr, bool only_free, bool send_smp_message)
|
bool PageTable::reserve_page(vaddr_t vaddr, bool only_free)
|
||||||
{
|
{
|
||||||
SpinLockGuard _(m_lock);
|
SpinLockGuard _(m_lock);
|
||||||
ASSERT(vaddr % PAGE_SIZE == 0);
|
ASSERT(vaddr % PAGE_SIZE == 0);
|
||||||
if (only_free && !is_page_free(vaddr))
|
if (only_free && !is_page_free(vaddr))
|
||||||
return false;
|
return false;
|
||||||
map_page_at(0, vaddr, Flags::Reserved, MemoryType::Normal, send_smp_message);
|
map_page_at(0, vaddr, Flags::Reserved);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -844,15 +833,7 @@ namespace Kernel
|
|||||||
if (only_free && !is_range_free(vaddr, bytes))
|
if (only_free && !is_range_free(vaddr, bytes))
|
||||||
return false;
|
return false;
|
||||||
for (size_t offset = 0; offset < bytes; offset += PAGE_SIZE)
|
for (size_t offset = 0; offset < bytes; offset += PAGE_SIZE)
|
||||||
reserve_page(vaddr + offset, true, false);
|
reserve_page(vaddr + offset);
|
||||||
Processor::broadcast_smp_message({
|
|
||||||
.type = Processor::SMPMessage::Type::FlushTLB,
|
|
||||||
.flush_tlb = {
|
|
||||||
.vaddr = vaddr,
|
|
||||||
.page_count = bytes / PAGE_SIZE,
|
|
||||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -866,7 +847,7 @@ namespace Kernel
|
|||||||
last_address -= rem;
|
last_address -= rem;
|
||||||
|
|
||||||
ASSERT(is_canonical(first_address));
|
ASSERT(is_canonical(first_address));
|
||||||
ASSERT(is_canonical(last_address - 1));
|
ASSERT(is_canonical(last_address));
|
||||||
const vaddr_t uc_vaddr_start = uncanonicalize(first_address);
|
const vaddr_t uc_vaddr_start = uncanonicalize(first_address);
|
||||||
const vaddr_t uc_vaddr_end = uncanonicalize(last_address);
|
const vaddr_t uc_vaddr_end = uncanonicalize(last_address);
|
||||||
|
|
||||||
@@ -948,7 +929,7 @@ namespace Kernel
|
|||||||
last_address -= rem;
|
last_address -= rem;
|
||||||
|
|
||||||
ASSERT(is_canonical(first_address));
|
ASSERT(is_canonical(first_address));
|
||||||
ASSERT(is_canonical(last_address - 1));
|
ASSERT(is_canonical(last_address));
|
||||||
|
|
||||||
SpinLockGuard _(m_lock);
|
SpinLockGuard _(m_lock);
|
||||||
|
|
||||||
|
|||||||
@@ -2,83 +2,55 @@
|
|||||||
|
|
||||||
// stack contains
|
// stack contains
|
||||||
// return address
|
// return address
|
||||||
// return stack
|
|
||||||
// return rflags
|
|
||||||
// siginfo_t
|
|
||||||
// signal number
|
// signal number
|
||||||
// signal handler
|
// signal handler
|
||||||
|
|
||||||
.global signal_trampoline
|
.global signal_trampoline
|
||||||
signal_trampoline:
|
signal_trampoline:
|
||||||
pushq %r15 // gregs
|
pushq %rax
|
||||||
pushq %r14
|
|
||||||
pushq %r13
|
|
||||||
pushq %r12
|
|
||||||
pushq %r11
|
|
||||||
pushq %r10
|
|
||||||
pushq %r9
|
|
||||||
pushq %r8
|
|
||||||
pushq %rsi
|
|
||||||
pushq %rdi
|
|
||||||
pushq %rdx
|
|
||||||
pushq %rcx
|
|
||||||
pushq %rbx
|
pushq %rbx
|
||||||
pushq %rax
|
pushq %rcx
|
||||||
|
pushq %rdx
|
||||||
pushq %rbp
|
pushq %rbp
|
||||||
|
pushq %rdi
|
||||||
|
pushq %rsi
|
||||||
|
pushq %r8
|
||||||
|
pushq %r9
|
||||||
|
pushq %r10
|
||||||
|
pushq %r11
|
||||||
|
pushq %r12
|
||||||
|
pushq %r13
|
||||||
|
pushq %r14
|
||||||
|
pushq %r15
|
||||||
|
|
||||||
// FIXME: populate these
|
movq 128(%rsp), %rdi
|
||||||
xorq %rax, %rax
|
movq 120(%rsp), %rax
|
||||||
pushq %rax // stack
|
|
||||||
pushq %rax
|
|
||||||
pushq %rax
|
|
||||||
pushq %rax // sigset
|
|
||||||
pushq %rax // link
|
|
||||||
|
|
||||||
movq %rsp, %rdx // ucontext
|
|
||||||
leaq 176(%rsp), %rsi // siginfo
|
|
||||||
movq 168(%rsp), %rdi // signal number
|
|
||||||
movq 160(%rsp), %rax // handler
|
|
||||||
|
|
||||||
// align stack to 16 bytes
|
// align stack to 16 bytes
|
||||||
movq %rsp, %rbp
|
movq %rsp, %rbp
|
||||||
andq $-16, %rsp
|
andq $-16, %rsp
|
||||||
|
|
||||||
subq $512, %rsp
|
|
||||||
fxsave64 (%rsp)
|
|
||||||
|
|
||||||
call *%rax
|
call *%rax
|
||||||
|
|
||||||
fxrstor64 (%rsp)
|
|
||||||
addq $512, %rsp
|
|
||||||
|
|
||||||
// restore stack
|
// restore stack
|
||||||
movq %rbp, %rsp
|
movq %rbp, %rsp
|
||||||
addq $40, %rsp
|
|
||||||
|
|
||||||
// restore registers
|
|
||||||
popq %rbp
|
|
||||||
popq %rax
|
|
||||||
popq %rbx
|
|
||||||
popq %rcx
|
|
||||||
popq %rdx
|
|
||||||
popq %rdi
|
|
||||||
popq %rsi
|
|
||||||
popq %r8
|
|
||||||
popq %r9
|
|
||||||
popq %r10
|
|
||||||
popq %r11
|
|
||||||
popq %r12
|
|
||||||
popq %r13
|
|
||||||
popq %r14
|
|
||||||
popq %r15
|
popq %r15
|
||||||
|
popq %r14
|
||||||
|
popq %r13
|
||||||
|
popq %r12
|
||||||
|
popq %r11
|
||||||
|
popq %r10
|
||||||
|
popq %r9
|
||||||
|
popq %r8
|
||||||
|
popq %rsi
|
||||||
|
popq %rdi
|
||||||
|
popq %rbp
|
||||||
|
popq %rdx
|
||||||
|
popq %rcx
|
||||||
|
popq %rbx
|
||||||
|
popq %rax
|
||||||
|
|
||||||
// skip handler, number, siginfo_t
|
addq $16, %rsp
|
||||||
addq $72, %rsp
|
|
||||||
|
|
||||||
// restore flags
|
// return over red-zone
|
||||||
popfq
|
|
||||||
|
|
||||||
movq (%rsp), %rsp
|
|
||||||
|
|
||||||
// return over red-zone and siginfo_t
|
|
||||||
ret $128
|
ret $128
|
||||||
|
|||||||
@@ -1,26 +1,49 @@
|
|||||||
|
// arguments in RAX, RBX, RCX, RDX, RSI, RDI
|
||||||
|
// System V ABI: RDI, RSI, RDX, RCX, R8, R9
|
||||||
.global asm_syscall_handler
|
.global asm_syscall_handler
|
||||||
asm_syscall_handler:
|
asm_syscall_handler:
|
||||||
swapgs
|
pushq %rbx
|
||||||
|
|
||||||
movq %rsp, %rax
|
|
||||||
movq %gs:8, %rsp
|
|
||||||
|
|
||||||
pushq $(0x20 | 3)
|
|
||||||
pushq %rax
|
|
||||||
pushq %r11
|
|
||||||
pushq $(0x28 | 3)
|
|
||||||
pushq %rcx
|
pushq %rcx
|
||||||
subq $8, %rsp
|
pushq %rdx
|
||||||
|
pushq %rdi
|
||||||
|
pushq %rsi
|
||||||
|
pushq %rbp
|
||||||
|
pushq %r8
|
||||||
|
pushq %r9
|
||||||
|
pushq %r10
|
||||||
|
pushq %r11
|
||||||
|
pushq %r12
|
||||||
|
pushq %r13
|
||||||
|
pushq %r14
|
||||||
|
pushq %r15
|
||||||
|
cld
|
||||||
|
|
||||||
movq %r10, %rcx
|
movq %rsi, %r8
|
||||||
|
movq %rdi, %r9
|
||||||
|
movq %rax, %rdi
|
||||||
|
movq %rbx, %rsi
|
||||||
|
xchgq %rcx, %rdx
|
||||||
|
leaq 112(%rsp), %rbx
|
||||||
|
pushq %rbx
|
||||||
call cpp_syscall_handler
|
call cpp_syscall_handler
|
||||||
|
addq $8, %rsp
|
||||||
|
|
||||||
movq 8(%rsp), %rcx
|
popq %r15
|
||||||
movq 24(%rsp), %r11
|
popq %r14
|
||||||
movq 32(%rsp), %rsp
|
popq %r13
|
||||||
|
popq %r12
|
||||||
|
popq %r11
|
||||||
|
popq %r10
|
||||||
|
popq %r9
|
||||||
|
popq %r8
|
||||||
|
popq %rbp
|
||||||
|
popq %rsi
|
||||||
|
popq %rdi
|
||||||
|
popq %rdx
|
||||||
|
popq %rcx
|
||||||
|
popq %rbx
|
||||||
|
iretq
|
||||||
|
|
||||||
swapgs
|
|
||||||
sysretq
|
|
||||||
|
|
||||||
.global sys_fork_trampoline
|
.global sys_fork_trampoline
|
||||||
sys_fork_trampoline:
|
sys_fork_trampoline:
|
||||||
@@ -33,7 +56,7 @@ sys_fork_trampoline:
|
|||||||
|
|
||||||
call read_ip
|
call read_ip
|
||||||
testq %rax, %rax
|
testq %rax, %rax
|
||||||
je .done
|
je .reload_stack
|
||||||
|
|
||||||
movq %rax, %rsi
|
movq %rax, %rsi
|
||||||
movq %rsp, %rdi
|
movq %rsp, %rdi
|
||||||
@@ -47,3 +70,9 @@ sys_fork_trampoline:
|
|||||||
popq %rbp
|
popq %rbp
|
||||||
popq %rbx
|
popq %rbx
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
.reload_stack:
|
||||||
|
call get_thread_start_sp
|
||||||
|
movq %rax, %rsp
|
||||||
|
xorq %rax, %rax
|
||||||
|
jmp .done
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ start_kernel_thread:
|
|||||||
|
|
||||||
.global start_userspace_thread
|
.global start_userspace_thread
|
||||||
start_userspace_thread:
|
start_userspace_thread:
|
||||||
|
call load_thread_sse
|
||||||
|
|
||||||
call get_thread_start_sp
|
call get_thread_start_sp
|
||||||
movq %rax, %rsp
|
movq %rax, %rsp
|
||||||
|
|
||||||
swapgs
|
|
||||||
|
|
||||||
iretq
|
iretq
|
||||||
|
|||||||
@@ -1,87 +0,0 @@
|
|||||||
# bool safe_user_memcpy(void*, const void*, size_t)
|
|
||||||
.global safe_user_memcpy
|
|
||||||
.global safe_user_memcpy_end
|
|
||||||
.global safe_user_memcpy_fault
|
|
||||||
safe_user_memcpy:
|
|
||||||
xorq %rax, %rax
|
|
||||||
movq %rdx, %rcx
|
|
||||||
rep movsb
|
|
||||||
incq %rax
|
|
||||||
safe_user_memcpy_fault:
|
|
||||||
ret
|
|
||||||
safe_user_memcpy_end:
|
|
||||||
|
|
||||||
# bool safe_user_strncpy(void*, const void*, size_t)
|
|
||||||
.global safe_user_strncpy
|
|
||||||
.global safe_user_strncpy_end
|
|
||||||
.global safe_user_strncpy_fault
|
|
||||||
safe_user_strncpy:
|
|
||||||
movq %rdx, %rcx
|
|
||||||
testq %rcx, %rcx
|
|
||||||
jz safe_user_strncpy_fault
|
|
||||||
|
|
||||||
.safe_user_strncpy_align_loop:
|
|
||||||
testb $0x7, %sil
|
|
||||||
jz .safe_user_strncpy_align_done
|
|
||||||
|
|
||||||
movb (%rsi), %al
|
|
||||||
movb %al, (%rdi)
|
|
||||||
testb %al, %al
|
|
||||||
jz .safe_user_strncpy_done
|
|
||||||
|
|
||||||
incq %rdi
|
|
||||||
incq %rsi
|
|
||||||
decq %rcx
|
|
||||||
jnz .safe_user_strncpy_align_loop
|
|
||||||
jmp safe_user_strncpy_fault
|
|
||||||
|
|
||||||
.safe_user_strncpy_align_done:
|
|
||||||
movq $0x0101010101010101, %r8
|
|
||||||
movq $0x8080808080808080, %r9
|
|
||||||
|
|
||||||
.safe_user_strncpy_qword_loop:
|
|
||||||
cmpq $8, %rcx
|
|
||||||
jb .safe_user_strncpy_qword_done
|
|
||||||
|
|
||||||
movq (%rsi), %rax
|
|
||||||
movq %rax, %r10
|
|
||||||
movq %rax, %r11
|
|
||||||
|
|
||||||
# https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
|
|
||||||
subq %r8, %r10
|
|
||||||
notq %r11
|
|
||||||
andq %r11, %r10
|
|
||||||
andq %r9, %r10
|
|
||||||
jnz .safe_user_strncpy_byte_loop
|
|
||||||
|
|
||||||
movq %rax, (%rdi)
|
|
||||||
|
|
||||||
addq $8, %rdi
|
|
||||||
addq $8, %rsi
|
|
||||||
subq $8, %rcx
|
|
||||||
jnz .safe_user_strncpy_qword_loop
|
|
||||||
jmp safe_user_strncpy_fault
|
|
||||||
|
|
||||||
.safe_user_strncpy_qword_done:
|
|
||||||
testq %rcx, %rcx
|
|
||||||
jz safe_user_strncpy_fault
|
|
||||||
|
|
||||||
.safe_user_strncpy_byte_loop:
|
|
||||||
movb (%rsi), %al
|
|
||||||
movb %al, (%rdi)
|
|
||||||
testb %al, %al
|
|
||||||
jz .safe_user_strncpy_done
|
|
||||||
|
|
||||||
incq %rdi
|
|
||||||
incq %rsi
|
|
||||||
decq %rcx
|
|
||||||
jnz .safe_user_strncpy_byte_loop
|
|
||||||
|
|
||||||
safe_user_strncpy_fault:
|
|
||||||
xorq %rax, %rax
|
|
||||||
ret
|
|
||||||
|
|
||||||
.safe_user_strncpy_done:
|
|
||||||
movb $1, %al
|
|
||||||
ret
|
|
||||||
safe_user_strncpy_end:
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
.global asm_yield_trampoline
|
|
||||||
asm_yield_trampoline:
|
|
||||||
leaq 8(%rsp), %rcx
|
|
||||||
movq %rdi, %rsp
|
|
||||||
|
|
||||||
subq $8, %rsp
|
|
||||||
pushq -8(%rcx)
|
|
||||||
pushq %rcx
|
|
||||||
pushq %rax
|
|
||||||
pushq %rbx
|
|
||||||
pushq %rbp
|
|
||||||
pushq %r12
|
|
||||||
pushq %r13
|
|
||||||
pushq %r14
|
|
||||||
pushq %r15
|
|
||||||
|
|
||||||
movq %rsp, %rdi
|
|
||||||
call scheduler_on_yield
|
|
||||||
|
|
||||||
popq %r15
|
|
||||||
popq %r14
|
|
||||||
popq %r13
|
|
||||||
popq %r12
|
|
||||||
popq %rbp
|
|
||||||
popq %rbx
|
|
||||||
popq %rax
|
|
||||||
movq 8(%rsp), %rcx
|
|
||||||
movq 0(%rsp), %rsp
|
|
||||||
jmp *%rcx
|
|
||||||
@@ -14,23 +14,6 @@
|
|||||||
# multiboot2 header
|
# multiboot2 header
|
||||||
.section .multiboot, "aw"
|
.section .multiboot, "aw"
|
||||||
.align 8
|
.align 8
|
||||||
multiboot_start:
|
|
||||||
.long 0x1BADB002
|
|
||||||
.long (1 << 2) # page align modules
|
|
||||||
.long -(0x1BADB002 + (1 << 2))
|
|
||||||
|
|
||||||
.long 0
|
|
||||||
.long 0
|
|
||||||
.long 0
|
|
||||||
.long 0
|
|
||||||
.long 0
|
|
||||||
|
|
||||||
.long 0
|
|
||||||
.long FB_WIDTH
|
|
||||||
.long FB_HEIGHT
|
|
||||||
.long FB_BPP
|
|
||||||
multiboot_end:
|
|
||||||
.align 8
|
|
||||||
multiboot2_start:
|
multiboot2_start:
|
||||||
.long 0xE85250D6
|
.long 0xE85250D6
|
||||||
.long 0
|
.long 0
|
||||||
@@ -53,12 +36,6 @@ multiboot2_start:
|
|||||||
.long 12
|
.long 12
|
||||||
.long V2P(_start)
|
.long V2P(_start)
|
||||||
|
|
||||||
# page align modules
|
|
||||||
.align 8
|
|
||||||
.short 6
|
|
||||||
.short 0
|
|
||||||
.long 8
|
|
||||||
|
|
||||||
.align 8
|
.align 8
|
||||||
.short 0
|
.short 0
|
||||||
.short 0
|
.short 0
|
||||||
@@ -76,10 +53,9 @@ bananboot_start:
|
|||||||
bananboot_end:
|
bananboot_end:
|
||||||
|
|
||||||
.section .bss, "aw", @nobits
|
.section .bss, "aw", @nobits
|
||||||
.global g_boot_stack_top
|
boot_stack_bottom:
|
||||||
g_boot_stack_bottom:
|
.skip 4096 * 64
|
||||||
.skip 4096 * 4
|
boot_stack_top:
|
||||||
g_boot_stack_top:
|
|
||||||
|
|
||||||
.global g_kernel_cmdline
|
.global g_kernel_cmdline
|
||||||
g_kernel_cmdline:
|
g_kernel_cmdline:
|
||||||
@@ -179,13 +155,6 @@ enable_sse:
|
|||||||
movl %eax, %cr4
|
movl %eax, %cr4
|
||||||
ret
|
ret
|
||||||
|
|
||||||
enable_tsc:
|
|
||||||
# allow userspace to use RDTSC
|
|
||||||
movl %cr4, %ecx
|
|
||||||
andl $0xFFFFFFFB, %ecx
|
|
||||||
movl %ecx, %cr4
|
|
||||||
ret
|
|
||||||
|
|
||||||
initialize_paging:
|
initialize_paging:
|
||||||
# enable PAE
|
# enable PAE
|
||||||
movl %cr4, %ecx
|
movl %cr4, %ecx
|
||||||
@@ -218,11 +187,10 @@ _start:
|
|||||||
movl %eax, V2P(bootloader_magic)
|
movl %eax, V2P(bootloader_magic)
|
||||||
movl %ebx, V2P(bootloader_info)
|
movl %ebx, V2P(bootloader_info)
|
||||||
|
|
||||||
movl $V2P(g_boot_stack_top), %esp
|
movl $V2P(boot_stack_top), %esp
|
||||||
|
|
||||||
call check_requirements
|
call check_requirements
|
||||||
call enable_sse
|
call enable_sse
|
||||||
call enable_tsc
|
|
||||||
call initialize_paging
|
call initialize_paging
|
||||||
|
|
||||||
# flush gdt and jump to 64 bit
|
# flush gdt and jump to 64 bit
|
||||||
@@ -309,7 +277,6 @@ ap_protected_mode:
|
|||||||
movb $1, AP_V2P(ap_stack_loaded)
|
movb $1, AP_V2P(ap_stack_loaded)
|
||||||
|
|
||||||
leal V2P(enable_sse), %ecx; call *%ecx
|
leal V2P(enable_sse), %ecx; call *%ecx
|
||||||
leal V2P(enable_tsc), %ecx; call *%ecx
|
|
||||||
leal V2P(initialize_paging), %ecx; call *%ecx
|
leal V2P(initialize_paging), %ecx; call *%ecx
|
||||||
|
|
||||||
# load boot gdt and enter long mode
|
# load boot gdt and enter long mode
|
||||||
|
|||||||
@@ -1,12 +1,4 @@
|
|||||||
.macro swapgs_if_necessary, n
|
.macro pushaq
|
||||||
testb $3, \n(%rsp)
|
|
||||||
jz 1f; jnp 1f
|
|
||||||
swapgs
|
|
||||||
1:
|
|
||||||
.endm
|
|
||||||
|
|
||||||
.macro pushaq, n
|
|
||||||
swapgs_if_necessary \n
|
|
||||||
pushq %rax
|
pushq %rax
|
||||||
pushq %rcx
|
pushq %rcx
|
||||||
pushq %rdx
|
pushq %rdx
|
||||||
@@ -24,7 +16,7 @@
|
|||||||
pushq %r15
|
pushq %r15
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro popaq, n
|
.macro popaq
|
||||||
popq %r15
|
popq %r15
|
||||||
popq %r14
|
popq %r14
|
||||||
popq %r13
|
popq %r13
|
||||||
@@ -40,11 +32,10 @@
|
|||||||
popq %rdx
|
popq %rdx
|
||||||
popq %rcx
|
popq %rcx
|
||||||
popq %rax
|
popq %rax
|
||||||
swapgs_if_necessary \n
|
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
isr_stub:
|
isr_stub:
|
||||||
pushaq 24
|
pushaq
|
||||||
cld
|
cld
|
||||||
movq %cr0, %rax; pushq %rax
|
movq %cr0, %rax; pushq %rax
|
||||||
movq %cr2, %rax; pushq %rax
|
movq %cr2, %rax; pushq %rax
|
||||||
@@ -58,33 +49,43 @@ isr_stub:
|
|||||||
call cpp_isr_handler
|
call cpp_isr_handler
|
||||||
addq $32, %rsp
|
addq $32, %rsp
|
||||||
|
|
||||||
popaq 24
|
popaq
|
||||||
addq $16, %rsp
|
addq $16, %rsp
|
||||||
iretq
|
iretq
|
||||||
|
|
||||||
irq_stub:
|
irq_stub:
|
||||||
pushaq 24
|
pushaq
|
||||||
cld
|
cld
|
||||||
movq 120(%rsp), %rdi # irq number
|
movq 120(%rsp), %rdi # irq number
|
||||||
call cpp_irq_handler
|
call cpp_irq_handler
|
||||||
popaq 24
|
popaq
|
||||||
addq $16, %rsp
|
addq $16, %rsp
|
||||||
iretq
|
iretq
|
||||||
|
|
||||||
|
.global asm_yield_handler
|
||||||
|
asm_yield_handler:
|
||||||
|
pushaq
|
||||||
|
cld
|
||||||
|
leaq 120(%rsp), %rdi # interrupt stack ptr
|
||||||
|
movq %rsp, %rsi # interrupt register ptr
|
||||||
|
call cpp_yield_handler
|
||||||
|
popaq
|
||||||
|
iretq
|
||||||
|
|
||||||
.global asm_ipi_handler
|
.global asm_ipi_handler
|
||||||
asm_ipi_handler:
|
asm_ipi_handler:
|
||||||
pushaq 8
|
pushaq
|
||||||
cld
|
cld
|
||||||
call cpp_ipi_handler
|
call cpp_ipi_handler
|
||||||
popaq 8
|
popaq
|
||||||
iretq
|
iretq
|
||||||
|
|
||||||
.global asm_timer_handler
|
.global asm_timer_handler
|
||||||
asm_timer_handler:
|
asm_timer_handler:
|
||||||
pushaq 8
|
pushaq
|
||||||
cld
|
cld
|
||||||
call cpp_timer_handler
|
call cpp_timer_handler
|
||||||
popaq 8
|
popaq
|
||||||
iretq
|
iretq
|
||||||
|
|
||||||
.macro isr n
|
.macro isr n
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include <BAN/Vector.h>
|
#include <BAN/Vector.h>
|
||||||
#include <kernel/ACPI/AML/Namespace.h>
|
#include <kernel/ACPI/AML/Namespace.h>
|
||||||
#include <kernel/ACPI/EmbeddedController.h>
|
|
||||||
#include <kernel/ACPI/Headers.h>
|
#include <kernel/ACPI/Headers.h>
|
||||||
#include <kernel/Memory/Types.h>
|
#include <kernel/Memory/Types.h>
|
||||||
#include <kernel/ThreadBlocker.h>
|
#include <kernel/ThreadBlocker.h>
|
||||||
@@ -36,12 +35,8 @@ namespace Kernel::ACPI
|
|||||||
BAN::ErrorOr<void> poweroff();
|
BAN::ErrorOr<void> poweroff();
|
||||||
BAN::ErrorOr<void> reset();
|
BAN::ErrorOr<void> reset();
|
||||||
|
|
||||||
BAN::ErrorOr<void> register_gpe_handler(uint8_t gpe, void (*callback)(void*), void* argument);
|
|
||||||
|
|
||||||
void handle_irq() override;
|
void handle_irq() override;
|
||||||
|
|
||||||
BAN::Span<BAN::UniqPtr<EmbeddedController>> embedded_controllers() { return m_embedded_controllers.span(); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ACPI() = default;
|
ACPI() = default;
|
||||||
BAN::ErrorOr<void> initialize_impl();
|
BAN::ErrorOr<void> initialize_impl();
|
||||||
@@ -55,12 +50,6 @@ namespace Kernel::ACPI
|
|||||||
|
|
||||||
BAN::ErrorOr<void> route_interrupt_link_device(const AML::Scope& device, uint64_t& routed_irq_mask);
|
BAN::ErrorOr<void> route_interrupt_link_device(const AML::Scope& device, uint64_t& routed_irq_mask);
|
||||||
|
|
||||||
BAN::ErrorOr<void> initialize_embedded_controller(const AML::Scope& embedded_controller);
|
|
||||||
BAN::ErrorOr<void> initialize_embedded_controllers();
|
|
||||||
|
|
||||||
BAN::Optional<GAS> find_gpe_block(size_t index);
|
|
||||||
bool enable_gpe(uint8_t gpe);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
paddr_t m_header_table_paddr = 0;
|
paddr_t m_header_table_paddr = 0;
|
||||||
vaddr_t m_header_table_vaddr = 0;
|
vaddr_t m_header_table_vaddr = 0;
|
||||||
@@ -79,23 +68,8 @@ namespace Kernel::ACPI
|
|||||||
|
|
||||||
ThreadBlocker m_event_thread_blocker;
|
ThreadBlocker m_event_thread_blocker;
|
||||||
|
|
||||||
BAN::Vector<BAN::UniqPtr<EmbeddedController>> m_embedded_controllers;
|
|
||||||
|
|
||||||
struct GPEHandler
|
|
||||||
{
|
|
||||||
bool has_callback { false };
|
|
||||||
union {
|
|
||||||
AML::Reference* method;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
void (*callback)(void*);
|
|
||||||
void* argument;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
bool m_has_any_gpes { false };
|
|
||||||
AML::Scope m_gpe_scope;
|
AML::Scope m_gpe_scope;
|
||||||
BAN::Array<GPEHandler, 0xFF> m_gpe_methods;
|
BAN::Array<AML::Reference*, 0xFF> m_gpe_methods { nullptr };
|
||||||
|
|
||||||
bool m_hardware_reduced { false };
|
bool m_hardware_reduced { false };
|
||||||
AML::Namespace* m_namespace { nullptr };
|
AML::Namespace* m_namespace { nullptr };
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ namespace Kernel::ACPI::AML
|
|||||||
BAN::ErrorOr<void> for_each_child(const Scope&, const BAN::Function<BAN::Iteration(const Scope&, Reference*)>&);
|
BAN::ErrorOr<void> for_each_child(const Scope&, const BAN::Function<BAN::Iteration(const Scope&, Reference*)>&);
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::Vector<Scope>> find_device_with_eisa_id(BAN::StringView eisa_id);
|
BAN::ErrorOr<BAN::Vector<Scope>> find_device_with_eisa_id(BAN::StringView eisa_id);
|
||||||
BAN::ErrorOr<BAN::Vector<Scope>> find_device_with_eisa_id(BAN::Span<BAN::StringView> eisa_ids);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BAN::ErrorOr<Scope> resolve_path(const Scope& scope, const NameString& name_string);
|
BAN::ErrorOr<Scope> resolve_path(const Scope& scope, const NameString& name_string);
|
||||||
|
|||||||
@@ -89,9 +89,6 @@ namespace Kernel::ACPI::AML
|
|||||||
GAS::AddressSpaceID address_space;
|
GAS::AddressSpaceID address_space;
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
uint64_t length;
|
uint64_t length;
|
||||||
alignas(Scope) uint8_t scope_storage[sizeof(Scope)];
|
|
||||||
Scope& scope() { return *reinterpret_cast<Scope*>(scope_storage); }
|
|
||||||
const Scope& scope() const { return *reinterpret_cast<const Scope*>(scope_storage); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FieldUnit
|
struct FieldUnit
|
||||||
|
|||||||
@@ -1,69 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <BAN/Atomic.h>
|
|
||||||
#include <BAN/UniqPtr.h>
|
|
||||||
|
|
||||||
#include <kernel/ACPI/AML/Scope.h>
|
|
||||||
#include <kernel/Lock/Mutex.h>
|
|
||||||
#include <kernel/Thread.h>
|
|
||||||
|
|
||||||
namespace Kernel::ACPI
|
|
||||||
{
|
|
||||||
|
|
||||||
class EmbeddedController
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<EmbeddedController>> create(AML::Scope&& scope, uint16_t command_port, uint16_t data_port, BAN::Optional<uint8_t> gpe);
|
|
||||||
~EmbeddedController();
|
|
||||||
|
|
||||||
BAN::ErrorOr<uint8_t> read_byte(uint8_t offset);
|
|
||||||
BAN::ErrorOr<void> write_byte(uint8_t offset, uint8_t value);
|
|
||||||
|
|
||||||
const AML::Scope& scope() const { return m_scope; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
EmbeddedController(AML::Scope&& scope, uint16_t command_port, uint16_t data_port, bool has_gpe)
|
|
||||||
: m_scope(BAN::move(scope))
|
|
||||||
, m_command_port(command_port)
|
|
||||||
, m_data_port(data_port)
|
|
||||||
, m_has_gpe(has_gpe)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
private:
|
|
||||||
void wait_status_bit(uint8_t bit, uint8_t value);
|
|
||||||
|
|
||||||
uint8_t read_one(uint16_t port);
|
|
||||||
void write_one(uint16_t port, uint8_t value);
|
|
||||||
|
|
||||||
static void handle_gpe_wrapper(void*);
|
|
||||||
void handle_gpe();
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> call_query_method(uint8_t notification);
|
|
||||||
|
|
||||||
void thread_task();
|
|
||||||
|
|
||||||
struct Command
|
|
||||||
{
|
|
||||||
uint8_t command;
|
|
||||||
BAN::Optional<uint8_t> data1;
|
|
||||||
BAN::Optional<uint8_t> data2;
|
|
||||||
uint8_t* response;
|
|
||||||
BAN::Atomic<bool> done;
|
|
||||||
};
|
|
||||||
BAN::ErrorOr<void> send_command(Command& command);
|
|
||||||
|
|
||||||
private:
|
|
||||||
const AML::Scope m_scope;
|
|
||||||
const uint16_t m_command_port;
|
|
||||||
const uint16_t m_data_port;
|
|
||||||
const bool m_has_gpe;
|
|
||||||
|
|
||||||
Mutex m_mutex;
|
|
||||||
ThreadBlocker m_thread_blocker;
|
|
||||||
|
|
||||||
BAN::Optional<Command*> m_queued_command;
|
|
||||||
|
|
||||||
Thread* m_thread { nullptr };
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,179 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <BAN/ByteSpan.h>
|
|
||||||
#include <BAN/Debug.h>
|
|
||||||
#include <BAN/Optional.h>
|
|
||||||
|
|
||||||
namespace Kernel::ACPI
|
|
||||||
{
|
|
||||||
|
|
||||||
struct ResourceData
|
|
||||||
{
|
|
||||||
enum class Type
|
|
||||||
{
|
|
||||||
IRQ,
|
|
||||||
DMA,
|
|
||||||
IOPort,
|
|
||||||
FixedIOPort,
|
|
||||||
FixedDMA,
|
|
||||||
|
|
||||||
// TODO: large stuff the stuff :)
|
|
||||||
};
|
|
||||||
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
uint16_t irq_mask;
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
uint8_t edge_triggered : 1;
|
|
||||||
uint8_t : 2;
|
|
||||||
uint8_t active_low : 1;
|
|
||||||
uint8_t shared : 1;
|
|
||||||
uint8_t wake_capable : 1;
|
|
||||||
uint8_t : 2;
|
|
||||||
};
|
|
||||||
uint8_t raw;
|
|
||||||
};
|
|
||||||
} irq;
|
|
||||||
struct {
|
|
||||||
uint8_t channel_mask;
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
uint8_t type : 2; // 0: 8 bit, 1: 8 and 16 bit, 2: 16 bit only
|
|
||||||
uint8_t bus_master : 1;
|
|
||||||
uint8_t : 2;
|
|
||||||
uint8_t channel_speed : 2; // 0: compatibility, 1: type A, 2: type B, 3: type F
|
|
||||||
uint8_t : 1;
|
|
||||||
};
|
|
||||||
uint8_t raw;
|
|
||||||
};
|
|
||||||
} dma;
|
|
||||||
struct {
|
|
||||||
uint16_t range_min_base;
|
|
||||||
uint16_t range_max_base;
|
|
||||||
uint8_t base_alignment;
|
|
||||||
uint8_t range_length;
|
|
||||||
} io_port;
|
|
||||||
struct {
|
|
||||||
uint16_t range_base;
|
|
||||||
uint8_t range_length;
|
|
||||||
} fixed_io_port;
|
|
||||||
struct {
|
|
||||||
uint16_t request_line;
|
|
||||||
uint16_t channel;
|
|
||||||
uint8_t transfer_width; // 0: 8 bit, 1: 16 bit, 2: 32 bit, 3: 64 bit, 4: 128 bit
|
|
||||||
} fixed_dma;
|
|
||||||
} as;
|
|
||||||
Type type;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ResourceParser
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ResourceParser(BAN::ConstByteSpan buffer)
|
|
||||||
: m_buffer(buffer)
|
|
||||||
{}
|
|
||||||
|
|
||||||
BAN::Optional<ResourceData> get_next()
|
|
||||||
{
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (m_buffer.empty())
|
|
||||||
return {};
|
|
||||||
|
|
||||||
if (m_buffer[0] & 0x80)
|
|
||||||
{
|
|
||||||
dprintln("Skipping large resource 0x{2H}", m_buffer[0] & 0x7F);
|
|
||||||
const uint16_t length = (m_buffer[2] << 8) | m_buffer[1];
|
|
||||||
if (m_buffer.size() < static_cast<size_t>(3 + length))
|
|
||||||
return {};
|
|
||||||
m_buffer = m_buffer.slice(3 + length);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint8_t length = m_buffer[0] & 0x07;
|
|
||||||
if (m_buffer.size() < static_cast<size_t>(1 + length))
|
|
||||||
return {};
|
|
||||||
|
|
||||||
BAN::Optional<ResourceData> result;
|
|
||||||
switch ((m_buffer[0] >> 3) & 0x0F)
|
|
||||||
{
|
|
||||||
case 0x04:
|
|
||||||
if (length < 2)
|
|
||||||
break;
|
|
||||||
result = ResourceData {
|
|
||||||
.as = { .irq = {
|
|
||||||
.irq_mask = static_cast<uint16_t>((m_buffer[2] << 8) | m_buffer[1]),
|
|
||||||
.raw = (length >= 3) ? m_buffer[3] : static_cast<uint8_t>(1),
|
|
||||||
}},
|
|
||||||
.type = ResourceData::Type::IRQ,
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case 0x05:
|
|
||||||
if (length < 2)
|
|
||||||
break;
|
|
||||||
result = ResourceData {
|
|
||||||
.as = { .dma = {
|
|
||||||
.channel_mask = m_buffer[1],
|
|
||||||
.raw = m_buffer[2],
|
|
||||||
}},
|
|
||||||
.type = ResourceData::Type::DMA,
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case 0x08:
|
|
||||||
if (length < 7)
|
|
||||||
break;
|
|
||||||
result = ResourceData {
|
|
||||||
.as = { .io_port = {
|
|
||||||
.range_min_base = static_cast<uint16_t>(((m_buffer[3] << 8) | m_buffer[2]) & ((m_buffer[1] & 1) ? 0xFFFF : 0x03FF)),
|
|
||||||
.range_max_base = static_cast<uint16_t>(((m_buffer[5] << 8) | m_buffer[4]) & ((m_buffer[1] & 1) ? 0xFFFF : 0x03FF)),
|
|
||||||
.base_alignment = m_buffer[6],
|
|
||||||
.range_length = m_buffer[7],
|
|
||||||
}},
|
|
||||||
.type = ResourceData::Type::IOPort,
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case 0x09:
|
|
||||||
if (length < 3)
|
|
||||||
break;
|
|
||||||
result = ResourceData {
|
|
||||||
.as = { .fixed_io_port = {
|
|
||||||
.range_base = static_cast<uint16_t>(((m_buffer[2] << 8) | m_buffer[1]) & 0x03FF),
|
|
||||||
.range_length = m_buffer[3],
|
|
||||||
}},
|
|
||||||
.type = ResourceData::Type::FixedIOPort,
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case 0x0A:
|
|
||||||
if (length < 5)
|
|
||||||
break;
|
|
||||||
result = ResourceData {
|
|
||||||
.as = { .fixed_dma = {
|
|
||||||
.request_line = static_cast<uint16_t>((m_buffer[2] << 8) | m_buffer[1]),
|
|
||||||
.channel = static_cast<uint16_t>((m_buffer[4] << 8) | m_buffer[3]),
|
|
||||||
.transfer_width = m_buffer[5],
|
|
||||||
}},
|
|
||||||
.type = ResourceData::Type::FixedDMA,
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case 0x0F:
|
|
||||||
// End tag
|
|
||||||
return {};
|
|
||||||
case 0x06:
|
|
||||||
case 0x07:
|
|
||||||
case 0x0E:
|
|
||||||
dprintln("Skipping short resource 0x{2H}", (m_buffer[0] >> 3) & 0x0F);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_buffer = m_buffer.slice(1 + length);
|
|
||||||
if (result.has_value())
|
|
||||||
return result.release_value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
BAN::ConstByteSpan m_buffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
namespace Kernel::API
|
|
||||||
{
|
|
||||||
|
|
||||||
enum SharedPageFeature : uint32_t
|
|
||||||
{
|
|
||||||
SPF_GETTIME = 1 << 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SharedPage
|
|
||||||
{
|
|
||||||
uint8_t __sequence[0x100];
|
|
||||||
|
|
||||||
uint32_t features;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint8_t shift;
|
|
||||||
uint64_t mult;
|
|
||||||
uint64_t realtime_seconds;
|
|
||||||
} gettime_shared;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint32_t seq;
|
|
||||||
uint64_t last_ns;
|
|
||||||
uint64_t last_tsc;
|
|
||||||
} gettime_local;
|
|
||||||
} cpus[];
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <kernel/Attributes.h>
|
|
||||||
#include <kernel/IDT.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <sys/syscall.h>
|
|
||||||
|
|
||||||
namespace Kernel
|
|
||||||
{
|
|
||||||
|
|
||||||
ALWAYS_INLINE long syscall(int syscall, uintptr_t arg1 = 0, uintptr_t arg2 = 0, uintptr_t arg3 = 0, uintptr_t arg4 = 0, uintptr_t arg5 = 0)
|
|
||||||
{
|
|
||||||
long ret;
|
|
||||||
#if ARCH(x86_64)
|
|
||||||
register uintptr_t r10 asm("r10") = arg3;
|
|
||||||
register uintptr_t r8 asm( "r8") = arg4;
|
|
||||||
register uintptr_t r9 asm( "r9") = arg5;
|
|
||||||
asm volatile(
|
|
||||||
"syscall"
|
|
||||||
: "=a"(ret)
|
|
||||||
, "+D"(syscall)
|
|
||||||
, "+S"(arg1)
|
|
||||||
, "+d"(arg2)
|
|
||||||
, "+r"(r10)
|
|
||||||
, "+r"(r8)
|
|
||||||
, "+r"(r9)
|
|
||||||
:: "rcx", "r11", "memory");
|
|
||||||
#elif ARCH(i686)
|
|
||||||
asm volatile(
|
|
||||||
"int %[irq]"
|
|
||||||
: "=a"(ret)
|
|
||||||
: [irq]"i"(static_cast<int>(IRQ_SYSCALL)) // WTF GCC 15
|
|
||||||
, "a"(syscall)
|
|
||||||
, "b"(arg1)
|
|
||||||
, "c"(arg2)
|
|
||||||
, "d"(arg3)
|
|
||||||
, "S"(arg4)
|
|
||||||
, "D"(arg5)
|
|
||||||
: "memory");
|
|
||||||
#endif
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <kernel/Audio/Controller.h>
|
|
||||||
#include <kernel/Memory/DMARegion.h>
|
|
||||||
|
|
||||||
namespace Kernel
|
|
||||||
{
|
|
||||||
|
|
||||||
class AC97AudioController final : public AudioController, public Interruptable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static BAN::ErrorOr<void> create(PCI::Device& pci_device);
|
|
||||||
|
|
||||||
void handle_irq() override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void handle_new_data() override;
|
|
||||||
|
|
||||||
uint32_t get_channels() const override { return 2; }
|
|
||||||
uint32_t get_sample_rate() const override { return 48000; }
|
|
||||||
|
|
||||||
uint32_t get_total_pins() const override { return 1; }
|
|
||||||
uint32_t get_current_pin() const override { return 0; }
|
|
||||||
BAN::ErrorOr<void> set_current_pin(uint32_t pin) override { if (pin != 0) return BAN::Error::from_errno(EINVAL); return {}; }
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> set_volume_mdB(int32_t) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
AC97AudioController(PCI::Device& pci_device)
|
|
||||||
: m_pci_device(pci_device)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
uint32_t get_volume_data() const;
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> initialize();
|
|
||||||
BAN::ErrorOr<void> initialize_bld();
|
|
||||||
BAN::ErrorOr<void> initialize_interrupts();
|
|
||||||
|
|
||||||
bool queue_samples_to_bld();
|
|
||||||
|
|
||||||
private:
|
|
||||||
static constexpr size_t m_bdl_entries = 32;
|
|
||||||
static constexpr size_t m_samples_per_entry = 0x1000;
|
|
||||||
|
|
||||||
// We only store samples in 2 BDL entries at a time to reduce the amount of samples queued.
|
|
||||||
// This is to reduce latency as you cannot remove data already passed to the BDLs
|
|
||||||
static constexpr size_t m_used_bdl_entries = 2;
|
|
||||||
|
|
||||||
PCI::Device& m_pci_device;
|
|
||||||
BAN::UniqPtr<PCI::BarRegion> m_mixer;
|
|
||||||
BAN::UniqPtr<PCI::BarRegion> m_bus_master;
|
|
||||||
|
|
||||||
BAN::UniqPtr<DMARegion> m_bdl_region;
|
|
||||||
|
|
||||||
uint32_t m_bdl_tail { 0 };
|
|
||||||
uint32_t m_bdl_head { 0 };
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
namespace Kernel::AC97
|
|
||||||
{
|
|
||||||
|
|
||||||
struct BufferDescriptorListEntry
|
|
||||||
{
|
|
||||||
uint32_t address;
|
|
||||||
uint16_t samples;
|
|
||||||
uint16_t flags; // bit 14: last entry, bit 15: IOC
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <kernel/Device/Device.h>
|
|
||||||
#include <kernel/Memory/ByteRingBuffer.h>
|
|
||||||
#include <kernel/PCI.h>
|
|
||||||
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
|
|
||||||
namespace Kernel
|
|
||||||
{
|
|
||||||
|
|
||||||
class AudioController : public CharacterDevice
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static BAN::ErrorOr<void> create(PCI::Device& pci_device);
|
|
||||||
|
|
||||||
dev_t rdev() const override { return m_rdev; }
|
|
||||||
BAN::StringView name() const override { return m_name; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
AudioController();
|
|
||||||
BAN::ErrorOr<void> initialize();
|
|
||||||
|
|
||||||
virtual void handle_new_data() = 0;
|
|
||||||
|
|
||||||
virtual uint32_t get_channels() const = 0;
|
|
||||||
virtual uint32_t get_sample_rate() const = 0;
|
|
||||||
|
|
||||||
virtual uint32_t get_total_pins() const = 0;
|
|
||||||
virtual uint32_t get_current_pin() const = 0;
|
|
||||||
virtual BAN::ErrorOr<void> set_current_pin(uint32_t) = 0;
|
|
||||||
|
|
||||||
virtual BAN::ErrorOr<void> set_volume_mdB(int32_t) = 0;
|
|
||||||
|
|
||||||
bool can_read_impl() const override { return false; }
|
|
||||||
bool can_write_impl() const override { SpinLockGuard _(m_spinlock); return !m_sample_data->full(); }
|
|
||||||
bool has_error_impl() const override { return false; }
|
|
||||||
bool has_hungup_impl() const override { return false; }
|
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
|
||||||
|
|
||||||
BAN::ErrorOr<long> ioctl_impl(int cmd, void* arg) override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
ThreadBlocker m_sample_data_blocker;
|
|
||||||
mutable SpinLock m_spinlock;
|
|
||||||
|
|
||||||
static constexpr size_t m_sample_data_capacity = 1 << 20;
|
|
||||||
BAN::UniqPtr<ByteRingBuffer> m_sample_data;
|
|
||||||
|
|
||||||
snd_volume_info m_volume_info {};
|
|
||||||
|
|
||||||
private:
|
|
||||||
const dev_t m_rdev;
|
|
||||||
char m_name[10] {};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <kernel/Audio/Controller.h>
|
|
||||||
#include <kernel/Audio/HDAudio/Controller.h>
|
|
||||||
|
|
||||||
namespace Kernel
|
|
||||||
{
|
|
||||||
|
|
||||||
class HDAudioController;
|
|
||||||
|
|
||||||
class HDAudioFunctionGroup final : public AudioController
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static BAN::ErrorOr<BAN::RefPtr<HDAudioFunctionGroup>> create(BAN::RefPtr<HDAudioController>, uint8_t cid, HDAudio::AFGNode&&);
|
|
||||||
|
|
||||||
void on_stream_interrupt(uint8_t stream_index);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// FIXME: allow setting these :D
|
|
||||||
uint32_t get_channels() const override { return 2; }
|
|
||||||
uint32_t get_sample_rate() const override { return 48000; }
|
|
||||||
|
|
||||||
uint32_t get_total_pins() const override;
|
|
||||||
uint32_t get_current_pin() const override;
|
|
||||||
BAN::ErrorOr<void> set_current_pin(uint32_t) override;
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> set_volume_mdB(int32_t) override;
|
|
||||||
|
|
||||||
void handle_new_data() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
HDAudioFunctionGroup(BAN::RefPtr<HDAudioController> controller, uint8_t cid, HDAudio::AFGNode&& afg_node)
|
|
||||||
: m_controller(controller)
|
|
||||||
, m_afg_node(BAN::move(afg_node))
|
|
||||||
, m_cid(cid)
|
|
||||||
{ }
|
|
||||||
~HDAudioFunctionGroup();
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> initialize();
|
|
||||||
BAN::ErrorOr<void> initialize_stream();
|
|
||||||
BAN::ErrorOr<void> initialize_output();
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> enable_output_path(uint8_t index);
|
|
||||||
BAN::ErrorOr<void> disable_output_path(uint8_t index);
|
|
||||||
|
|
||||||
void reset_stream();
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> recurse_output_paths(const HDAudio::AFGWidget& widget, BAN::Vector<const HDAudio::AFGWidget*>& path);
|
|
||||||
|
|
||||||
uint16_t get_format_data() const;
|
|
||||||
|
|
||||||
size_t bdl_offset() const;
|
|
||||||
|
|
||||||
void queue_bdl_data();
|
|
||||||
|
|
||||||
private:
|
|
||||||
// use 6 512 sample BDL entries
|
|
||||||
// each entry is ~10.7 ms at 48 kHz
|
|
||||||
// -> total buffered audio is 64 ms
|
|
||||||
static constexpr size_t m_bdl_entry_sample_frames = 512;
|
|
||||||
static constexpr size_t m_bdl_entry_count = 6;
|
|
||||||
|
|
||||||
BAN::RefPtr<HDAudioController> m_controller;
|
|
||||||
const HDAudio::AFGNode m_afg_node;
|
|
||||||
const uint8_t m_cid;
|
|
||||||
|
|
||||||
BAN::Vector<BAN::Vector<const HDAudio::AFGWidget*>> m_output_paths;
|
|
||||||
BAN::Vector<const HDAudio::AFGWidget*> m_output_pins;
|
|
||||||
size_t m_output_path_index { SIZE_MAX };
|
|
||||||
|
|
||||||
uint8_t m_stream_id { 0xFF };
|
|
||||||
uint8_t m_stream_index { 0xFF };
|
|
||||||
BAN::UniqPtr<DMARegion> m_bdl_region;
|
|
||||||
|
|
||||||
size_t m_bdl_head { 0 };
|
|
||||||
size_t m_bdl_tail { 0 };
|
|
||||||
bool m_stream_running { false };
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <kernel/Audio/Controller.h>
|
|
||||||
#include <kernel/Audio/HDAudio/Definitions.h>
|
|
||||||
#include <kernel/Memory/DMARegion.h>
|
|
||||||
|
|
||||||
namespace Kernel
|
|
||||||
{
|
|
||||||
|
|
||||||
class HDAudioController : public Interruptable, public BAN::RefCounted<HDAudioController>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static BAN::ErrorOr<void> create(PCI::Device& pci_device);
|
|
||||||
|
|
||||||
BAN::ErrorOr<uint32_t> send_command(HDAudio::CORBEntry);
|
|
||||||
|
|
||||||
uint8_t get_stream_index(HDAudio::StreamType type, uint8_t index) const;
|
|
||||||
|
|
||||||
BAN::ErrorOr<uint8_t> allocate_stream_id();
|
|
||||||
void deallocate_stream_id(uint8_t id);
|
|
||||||
|
|
||||||
BAN::ErrorOr<uint8_t> allocate_stream(HDAudio::StreamType type, void* afg);
|
|
||||||
void deallocate_stream(uint8_t index);
|
|
||||||
|
|
||||||
PCI::BarRegion& bar0() { return *m_bar0; }
|
|
||||||
|
|
||||||
bool is_64bit() const { return m_is64bit; }
|
|
||||||
|
|
||||||
void handle_irq() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
HDAudioController(PCI::Device& pci_device)
|
|
||||||
: m_pci_device(pci_device)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> initialize();
|
|
||||||
BAN::ErrorOr<void> initialize_ring_buffers();
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> reset_controller();
|
|
||||||
|
|
||||||
BAN::ErrorOr<HDAudio::Codec> initialize_codec(uint8_t codec);
|
|
||||||
BAN::ErrorOr<HDAudio::AFGNode> initialize_node(uint8_t codec, uint8_t node);
|
|
||||||
BAN::ErrorOr<HDAudio::AFGWidget> initialize_widget(uint8_t codec, uint8_t node);
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct RingBuffer
|
|
||||||
{
|
|
||||||
vaddr_t vaddr;
|
|
||||||
uint32_t index;
|
|
||||||
uint32_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
PCI::Device& m_pci_device;
|
|
||||||
BAN::UniqPtr<PCI::BarRegion> m_bar0;
|
|
||||||
bool m_is64bit { false };
|
|
||||||
|
|
||||||
bool m_use_immediate_command { false };
|
|
||||||
|
|
||||||
uint8_t m_output_streams { 0 };
|
|
||||||
uint8_t m_input_streams { 0 };
|
|
||||||
uint8_t m_bidir_streams { 0 };
|
|
||||||
void* m_allocated_streams[30] {};
|
|
||||||
|
|
||||||
// NOTE: stream ids are from 1 to 15
|
|
||||||
uint16_t m_allocated_stream_ids { 0 };
|
|
||||||
|
|
||||||
Mutex m_command_mutex;
|
|
||||||
SpinLock m_rb_lock;
|
|
||||||
ThreadBlocker m_rb_blocker;
|
|
||||||
|
|
||||||
RingBuffer m_corb;
|
|
||||||
RingBuffer m_rirb;
|
|
||||||
BAN::UniqPtr<DMARegion> m_ring_buffer_region;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <BAN/Vector.h>
|
|
||||||
|
|
||||||
namespace Kernel::HDAudio
|
|
||||||
{
|
|
||||||
|
|
||||||
struct CORBEntry
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
uint32_t data : 8;
|
|
||||||
uint32_t command : 12;
|
|
||||||
uint32_t node_index : 8;
|
|
||||||
uint32_t codec_address : 4;
|
|
||||||
};
|
|
||||||
uint32_t raw;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
static_assert(sizeof(CORBEntry) == sizeof(uint32_t));
|
|
||||||
|
|
||||||
struct BDLEntry
|
|
||||||
{
|
|
||||||
paddr_t address;
|
|
||||||
uint32_t length;
|
|
||||||
uint32_t ioc;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(BDLEntry) == 16);
|
|
||||||
|
|
||||||
struct AFGWidget
|
|
||||||
{
|
|
||||||
enum class Type
|
|
||||||
{
|
|
||||||
OutputConverter,
|
|
||||||
InputConverter,
|
|
||||||
Mixer,
|
|
||||||
Selector,
|
|
||||||
PinComplex,
|
|
||||||
Power,
|
|
||||||
VolumeKnob,
|
|
||||||
BeepGenerator,
|
|
||||||
};
|
|
||||||
|
|
||||||
Type type;
|
|
||||||
uint8_t id;
|
|
||||||
|
|
||||||
union
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
bool input;
|
|
||||||
bool output;
|
|
||||||
bool display; // HDMI or DP
|
|
||||||
uint32_t config;
|
|
||||||
} pin_complex;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Amplifier
|
|
||||||
{
|
|
||||||
uint8_t offset;
|
|
||||||
uint8_t num_steps;
|
|
||||||
uint8_t step_size;
|
|
||||||
bool mute;
|
|
||||||
};
|
|
||||||
|
|
||||||
BAN::Optional<Amplifier> output_amplifier;
|
|
||||||
|
|
||||||
BAN::Vector<uint16_t> connections;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AFGNode
|
|
||||||
{
|
|
||||||
uint8_t id;
|
|
||||||
BAN::Vector<AFGWidget> widgets;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Codec
|
|
||||||
{
|
|
||||||
uint8_t id;
|
|
||||||
BAN::Vector<AFGNode> nodes;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class StreamType
|
|
||||||
{
|
|
||||||
Input,
|
|
||||||
Output,
|
|
||||||
Bidirectional,
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
namespace Kernel::HDAudio
|
|
||||||
{
|
|
||||||
|
|
||||||
enum Regs : uint8_t
|
|
||||||
{
|
|
||||||
GCAP = 0x00,
|
|
||||||
VMIN = 0x02,
|
|
||||||
VMAJ = 0x03,
|
|
||||||
GCTL = 0x08,
|
|
||||||
STATESTS = 0x0E,
|
|
||||||
|
|
||||||
INTCTL = 0x20,
|
|
||||||
INTSTS = 0x24,
|
|
||||||
|
|
||||||
CORBLBASE = 0x40,
|
|
||||||
CORBUBASE = 0x44,
|
|
||||||
CORBWP = 0x48,
|
|
||||||
CORBRP = 0x4A,
|
|
||||||
CORBCTL = 0x4C,
|
|
||||||
CORBSTS = 0x4D,
|
|
||||||
CORBSIZE = 0x4E,
|
|
||||||
|
|
||||||
RIRBLBASE = 0x50,
|
|
||||||
RIRBUBASE = 0x54,
|
|
||||||
RIRBWP = 0x58,
|
|
||||||
RINTCNT = 0x5A,
|
|
||||||
RIRBCTL = 0x5C,
|
|
||||||
RIRBSTS = 0x5D,
|
|
||||||
RIRBSIZE = 0x5E,
|
|
||||||
|
|
||||||
ICOI = 0x60,
|
|
||||||
ICII = 0x64,
|
|
||||||
ICIS = 0x68,
|
|
||||||
|
|
||||||
SDCTL = 0x00,
|
|
||||||
SDSTS = 0x03,
|
|
||||||
SDLPIB = 0x04,
|
|
||||||
SDCBL = 0x08,
|
|
||||||
SDLVI = 0x0C,
|
|
||||||
SDFIFOD = 0x10,
|
|
||||||
SDFMT = 0x12,
|
|
||||||
SDBDPL = 0x18,
|
|
||||||
SDBDPU = 0x1C,
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -41,12 +41,6 @@ namespace Kernel
|
|||||||
Type type;
|
Type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BootModule
|
|
||||||
{
|
|
||||||
paddr_t start;
|
|
||||||
size_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BootInfo
|
struct BootInfo
|
||||||
{
|
{
|
||||||
BAN::String command_line;
|
BAN::String command_line;
|
||||||
@@ -54,7 +48,6 @@ namespace Kernel
|
|||||||
RSDP rsdp {};
|
RSDP rsdp {};
|
||||||
paddr_t kernel_paddr {};
|
paddr_t kernel_paddr {};
|
||||||
|
|
||||||
BAN::Vector<BootModule> modules;
|
|
||||||
BAN::Vector<MemoryMapEntry> memory_map_entries;
|
BAN::Vector<MemoryMapEntry> memory_map_entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -81,6 +81,5 @@ namespace CPUID
|
|||||||
bool has_pge();
|
bool has_pge();
|
||||||
bool has_pat();
|
bool has_pat();
|
||||||
bool has_1gib_pages();
|
bool has_1gib_pages();
|
||||||
bool has_invariant_tsc();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,8 +35,10 @@ namespace Kernel
|
|||||||
|
|
||||||
bool has_egid(gid_t) const;
|
bool has_egid(gid_t) const;
|
||||||
|
|
||||||
BAN::Span<const gid_t> groups() const { return m_supplementary.span(); }
|
BAN::ErrorOr<void> initialize_supplementary_groups();
|
||||||
BAN::ErrorOr<void> set_groups(BAN::Span<const gid_t> groups);
|
|
||||||
|
private:
|
||||||
|
BAN::ErrorOr<BAN::String> find_username() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uid_t m_ruid, m_euid, m_suid;
|
uid_t m_ruid, m_euid, m_suid;
|
||||||
|
|||||||
@@ -70,15 +70,10 @@
|
|||||||
#define DEBUG_USB_MOUSE 0
|
#define DEBUG_USB_MOUSE 0
|
||||||
#define DEBUG_USB_MASS_STORAGE 0
|
#define DEBUG_USB_MASS_STORAGE 0
|
||||||
|
|
||||||
#define DEBUG_HDAUDIO 0
|
|
||||||
|
|
||||||
|
|
||||||
namespace Debug
|
namespace Debug
|
||||||
{
|
{
|
||||||
void dump_stack_trace();
|
void dump_stack_trace();
|
||||||
void dump_stack_trace(uintptr_t ip, uintptr_t bp);
|
|
||||||
void dump_qr_code();
|
|
||||||
|
|
||||||
void putchar(char);
|
void putchar(char);
|
||||||
void print_prefix(const char*, int);
|
void print_prefix(const char*, int);
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
class DebugDevice final : public CharacterDevice
|
class DebugDevice : public CharacterDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::RefPtr<DebugDevice>> create(mode_t, uid_t, gid_t);
|
static BAN::ErrorOr<BAN::RefPtr<DebugDevice>> create(mode_t, uid_t, gid_t);
|
||||||
@@ -24,7 +24,6 @@ namespace Kernel
|
|||||||
virtual bool can_read_impl() const override { return false; }
|
virtual bool can_read_impl() const override { return false; }
|
||||||
virtual bool can_write_impl() const override { return true; }
|
virtual bool can_write_impl() const override { return true; }
|
||||||
virtual bool has_error_impl() const override { return false; }
|
virtual bool has_error_impl() const override { return false; }
|
||||||
virtual bool has_hungup_impl() const override { return false; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const dev_t m_rdev;
|
const dev_t m_rdev;
|
||||||
|
|||||||
@@ -16,11 +16,7 @@ namespace Kernel
|
|||||||
virtual bool is_partition() const { return false; }
|
virtual bool is_partition() const { return false; }
|
||||||
virtual bool is_storage_device() const { return false; }
|
virtual bool is_storage_device() const { return false; }
|
||||||
|
|
||||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> mmap_region(PageTable&, off_t offset, size_t len, AddressRange, MemoryRegion::Type, PageTable::flags_t, int status_flags)
|
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> mmap_region(PageTable&, off_t offset, size_t len, AddressRange, MemoryRegion::Type, PageTable::flags_t) { (void)offset; (void)len; return BAN::Error::from_errno(EINVAL); }
|
||||||
{
|
|
||||||
(void)offset; (void)len; (void)status_flags;
|
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual dev_t rdev() const override = 0;
|
virtual dev_t rdev() const override = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -16,14 +16,11 @@ namespace Kernel
|
|||||||
Debug,
|
Debug,
|
||||||
Keyboard,
|
Keyboard,
|
||||||
Mouse,
|
Mouse,
|
||||||
Joystick,
|
|
||||||
SCSI,
|
SCSI,
|
||||||
NVMeController,
|
NVMeController,
|
||||||
NVMeNamespace,
|
NVMeNamespace,
|
||||||
Ethernet,
|
Ethernet,
|
||||||
Loopback,
|
|
||||||
TmpFS,
|
TmpFS,
|
||||||
AudioController,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> create_from_boot_framebuffer();
|
static BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> create_from_boot_framebuffer();
|
||||||
static BAN::RefPtr<FramebufferDevice> boot_framebuffer();
|
|
||||||
~FramebufferDevice();
|
~FramebufferDevice();
|
||||||
|
|
||||||
uint32_t width() const { return m_width; }
|
uint32_t width() const { return m_width; }
|
||||||
@@ -18,7 +17,6 @@ namespace Kernel
|
|||||||
|
|
||||||
uint32_t get_pixel(uint32_t x, uint32_t y) const;
|
uint32_t get_pixel(uint32_t x, uint32_t y) const;
|
||||||
void set_pixel(uint32_t x, uint32_t y, uint32_t rgb);
|
void set_pixel(uint32_t x, uint32_t y, uint32_t rgb);
|
||||||
void fill(uint32_t rgb);
|
|
||||||
|
|
||||||
// positive rows -> empty pixels on bottom
|
// positive rows -> empty pixels on bottom
|
||||||
// negative rows -> empty pixels on top
|
// negative rows -> empty pixels on top
|
||||||
@@ -28,7 +26,7 @@ namespace Kernel
|
|||||||
void sync_pixels_linear(uint32_t first_pixel, uint32_t pixel_count);
|
void sync_pixels_linear(uint32_t first_pixel, uint32_t pixel_count);
|
||||||
void sync_pixels_rectangle(uint32_t top_right_x, uint32_t top_right_y, uint32_t width, uint32_t height);
|
void sync_pixels_rectangle(uint32_t top_right_x, uint32_t top_right_y, uint32_t width, uint32_t height);
|
||||||
|
|
||||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> mmap_region(PageTable&, off_t offset, size_t len, AddressRange, MemoryRegion::Type, PageTable::flags_t, int status_flags) override;
|
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> mmap_region(PageTable&, off_t offset, size_t len, AddressRange, MemoryRegion::Type, PageTable::flags_t) override;
|
||||||
|
|
||||||
virtual dev_t rdev() const override { return m_rdev; }
|
virtual dev_t rdev() const override { return m_rdev; }
|
||||||
virtual BAN::StringView name() const override { return m_name.sv(); }
|
virtual BAN::StringView name() const override { return m_name.sv(); }
|
||||||
@@ -40,7 +38,6 @@ namespace Kernel
|
|||||||
virtual bool can_read_impl() const override { return true; }
|
virtual bool can_read_impl() const override { return true; }
|
||||||
virtual bool can_write_impl() const override { return true; }
|
virtual bool can_write_impl() const override { return true; }
|
||||||
virtual bool has_error_impl() const override { return false; }
|
virtual bool has_error_impl() const override { return false; }
|
||||||
virtual bool has_hungup_impl() const override { return false; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FramebufferDevice(mode_t mode, uid_t uid, gid_t gid, dev_t rdev, paddr_t paddr, uint32_t width, uint32_t height, uint32_t pitch, uint8_t bpp);
|
FramebufferDevice(mode_t mode, uid_t uid, gid_t gid, dev_t rdev, paddr_t paddr, uint32_t width, uint32_t height, uint32_t pitch, uint8_t bpp);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
class NullDevice final : public CharacterDevice
|
class NullDevice : public CharacterDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::RefPtr<NullDevice>> create(mode_t, uid_t, gid_t);
|
static BAN::ErrorOr<BAN::RefPtr<NullDevice>> create(mode_t, uid_t, gid_t);
|
||||||
@@ -26,7 +26,6 @@ namespace Kernel
|
|||||||
virtual bool can_read_impl() const override { return false; }
|
virtual bool can_read_impl() const override { return false; }
|
||||||
virtual bool can_write_impl() const override { return true; }
|
virtual bool can_write_impl() const override { return true; }
|
||||||
virtual bool has_error_impl() const override { return false; }
|
virtual bool has_error_impl() const override { return false; }
|
||||||
virtual bool has_hungup_impl() const override { return false; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const dev_t m_rdev;
|
const dev_t m_rdev;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
class RandomDevice final : public CharacterDevice
|
class RandomDevice : public CharacterDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::RefPtr<RandomDevice>> create(mode_t, uid_t, gid_t);
|
static BAN::ErrorOr<BAN::RefPtr<RandomDevice>> create(mode_t, uid_t, gid_t);
|
||||||
@@ -24,7 +24,6 @@ namespace Kernel
|
|||||||
virtual bool can_read_impl() const override { return true; }
|
virtual bool can_read_impl() const override { return true; }
|
||||||
virtual bool can_write_impl() const override { return false; }
|
virtual bool can_write_impl() const override { return false; }
|
||||||
virtual bool has_error_impl() const override { return false; }
|
virtual bool has_error_impl() const override { return false; }
|
||||||
virtual bool has_hungup_impl() const override { return false; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const dev_t m_rdev;
|
const dev_t m_rdev;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
class ZeroDevice final : public CharacterDevice
|
class ZeroDevice : public CharacterDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::RefPtr<ZeroDevice>> create(mode_t, uid_t, gid_t);
|
static BAN::ErrorOr<BAN::RefPtr<ZeroDevice>> create(mode_t, uid_t, gid_t);
|
||||||
@@ -24,7 +24,6 @@ namespace Kernel
|
|||||||
virtual bool can_read_impl() const override { return true; }
|
virtual bool can_read_impl() const override { return true; }
|
||||||
virtual bool can_write_impl() const override { return false; }
|
virtual bool can_write_impl() const override { return false; }
|
||||||
virtual bool has_error_impl() const override { return false; }
|
virtual bool has_error_impl() const override { return false; }
|
||||||
virtual bool has_hungup_impl() const override { return false; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const dev_t m_rdev;
|
const dev_t m_rdev;
|
||||||
|
|||||||
@@ -20,6 +20,6 @@ namespace Kernel::ELF
|
|||||||
BAN::Vector<BAN::UniqPtr<MemoryRegion>> regions;
|
BAN::Vector<BAN::UniqPtr<MemoryRegion>> regions;
|
||||||
};
|
};
|
||||||
|
|
||||||
BAN::ErrorOr<LoadResult> load_from_inode(BAN::RefPtr<Inode> root, BAN::RefPtr<Inode> inode, const Credentials&, PageTable&);
|
BAN::ErrorOr<LoadResult> load_from_inode(BAN::RefPtr<Inode>, const Credentials&, PageTable&);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,109 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <BAN/Array.h>
|
|
||||||
#include <BAN/CircularQueue.h>
|
|
||||||
#include <BAN/HashMap.h>
|
|
||||||
#include <BAN/HashSet.h>
|
|
||||||
#include <kernel/FS/Inode.h>
|
|
||||||
|
|
||||||
#include <limits.h>
|
|
||||||
#include <sys/epoll.h>
|
|
||||||
|
|
||||||
namespace Kernel
|
|
||||||
{
|
|
||||||
|
|
||||||
class Epoll final : public Inode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static BAN::ErrorOr<BAN::RefPtr<Epoll>> create();
|
|
||||||
~Epoll();
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> ctl(int op, int fd, BAN::RefPtr<Inode> inode, epoll_event event);
|
|
||||||
BAN::ErrorOr<size_t> wait(BAN::Span<epoll_event> events, uint64_t waketime_ns);
|
|
||||||
|
|
||||||
void notify(BAN::RefPtr<Inode> inode, uint32_t event);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Epoll() = default;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ino_t ino() const override { return 0; }
|
|
||||||
Mode mode() const override { return { Mode::IRUSR | Mode::IWUSR }; }
|
|
||||||
nlink_t nlink() const override { return 0; }
|
|
||||||
uid_t uid() const override { return 0; }
|
|
||||||
gid_t gid() const override { return 0; }
|
|
||||||
off_t size() const override { return 0; }
|
|
||||||
timespec atime() const override { return {}; }
|
|
||||||
timespec mtime() const override { return {}; }
|
|
||||||
timespec ctime() const override { return {}; }
|
|
||||||
blksize_t blksize() const override { return PAGE_SIZE; }
|
|
||||||
blkcnt_t blocks() const override { return 0; }
|
|
||||||
dev_t dev() const override { return 0; }
|
|
||||||
dev_t rdev() const override { return 0; }
|
|
||||||
|
|
||||||
bool is_epoll() const override { return true; }
|
|
||||||
|
|
||||||
const FileSystem* filesystem() const override { return nullptr; }
|
|
||||||
|
|
||||||
bool can_read_impl() const override { return false; }
|
|
||||||
bool can_write_impl() const override { return false; }
|
|
||||||
bool has_error_impl() const override { return false; }
|
|
||||||
bool has_hungup_impl() const override { return false; }
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> fsync_impl() override { return {}; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct InodeRefPtrHash
|
|
||||||
{
|
|
||||||
BAN::hash_t operator()(const BAN::RefPtr<Inode>& inode)
|
|
||||||
{
|
|
||||||
return BAN::hash<const Inode*>()(inode.ptr());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ListenEventList
|
|
||||||
{
|
|
||||||
BAN::Array<epoll_event, OPEN_MAX> events;
|
|
||||||
uint32_t bitmap[(OPEN_MAX + 31) / 32] {};
|
|
||||||
|
|
||||||
bool has_fd(int fd) const
|
|
||||||
{
|
|
||||||
// For some reason having (fd < 0 || ...) makes GCC 15.1.0
|
|
||||||
// think bitmap access can be out of bounds...
|
|
||||||
if (static_cast<size_t>(fd) >= events.size())
|
|
||||||
return false;
|
|
||||||
return bitmap[fd / 32] & (1u << (fd % 32));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool empty() const
|
|
||||||
{
|
|
||||||
for (auto val : bitmap)
|
|
||||||
if (val != 0)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_fd(int fd, epoll_event event)
|
|
||||||
{
|
|
||||||
ASSERT(!has_fd(fd));
|
|
||||||
bitmap[fd / 32] |= (1u << (fd % 32));
|
|
||||||
events[fd] = event;
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove_fd(int fd)
|
|
||||||
{
|
|
||||||
ASSERT(has_fd(fd));
|
|
||||||
bitmap[fd / 32] &= ~(1u << (fd % 32));
|
|
||||||
events[fd] = {};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
ThreadBlocker m_thread_blocker;
|
|
||||||
SpinLock m_ready_lock;
|
|
||||||
BAN::HashMap<BAN::RefPtr<Inode>, uint32_t, InodeRefPtrHash> m_ready_events;
|
|
||||||
BAN::HashMap<BAN::RefPtr<Inode>, uint32_t, InodeRefPtrHash> m_processing_events;
|
|
||||||
BAN::HashMap<BAN::RefPtr<Inode>, ListenEventList, InodeRefPtrHash> m_listening_events;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -22,7 +22,6 @@ namespace Kernel
|
|||||||
|
|
||||||
void add_inode(BAN::StringView path, BAN::RefPtr<TmpInode>);
|
void add_inode(BAN::StringView path, BAN::RefPtr<TmpInode>);
|
||||||
|
|
||||||
void initiate_disk_cache_drop();
|
|
||||||
void initiate_sync(bool should_block);
|
void initiate_sync(bool should_block);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -38,10 +37,6 @@ namespace Kernel
|
|||||||
ThreadBlocker m_sync_done;
|
ThreadBlocker m_sync_done;
|
||||||
ThreadBlocker m_sync_thread_blocker;
|
ThreadBlocker m_sync_thread_blocker;
|
||||||
volatile bool m_should_sync { false };
|
volatile bool m_should_sync { false };
|
||||||
|
|
||||||
SpinLock m_disk_cache_lock;
|
|
||||||
ThreadBlocker m_disk_cache_thread_blocker;
|
|
||||||
BAN::Atomic<bool> m_should_drop_disk_cache { false };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <kernel/FS/Inode.h>
|
|
||||||
|
|
||||||
namespace Kernel
|
|
||||||
{
|
|
||||||
|
|
||||||
class EventFD final : public Inode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static BAN::ErrorOr<BAN::RefPtr<Inode>> create(uint64_t initval, bool semaphore);
|
|
||||||
|
|
||||||
ino_t ino() const override { return 0; }
|
|
||||||
Mode mode() const override { return { Mode::IFCHR | Mode::IRUSR | Mode::IWUSR }; }
|
|
||||||
nlink_t nlink() const override { return ref_count(); }
|
|
||||||
uid_t uid() const override { return 0; }
|
|
||||||
gid_t gid() const override { return 0; }
|
|
||||||
off_t size() const override { return 0; }
|
|
||||||
timespec atime() const override { return {}; }
|
|
||||||
timespec mtime() const override { return {}; }
|
|
||||||
timespec ctime() const override { return {}; }
|
|
||||||
blksize_t blksize() const override { return 8; }
|
|
||||||
blkcnt_t blocks() const override { return 0; }
|
|
||||||
dev_t dev() const override { return 0; }
|
|
||||||
dev_t rdev() const override { return 0; }
|
|
||||||
|
|
||||||
const FileSystem* filesystem() const override { return nullptr; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
|
||||||
BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
|
||||||
BAN::ErrorOr<void> fsync_impl() final override { return {}; }
|
|
||||||
|
|
||||||
bool can_read_impl() const override { return m_value > 0; }
|
|
||||||
bool can_write_impl() const override { return m_value < UINT64_MAX - 1; }
|
|
||||||
bool has_error_impl() const override { return false; }
|
|
||||||
bool has_hungup_impl() const override { return false; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
EventFD(uint64_t initval, bool is_semaphore)
|
|
||||||
: m_is_semaphore(is_semaphore)
|
|
||||||
, m_value(initval)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
private:
|
|
||||||
const bool m_is_semaphore;
|
|
||||||
uint64_t m_value;
|
|
||||||
|
|
||||||
ThreadBlocker m_thread_blocker;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -26,32 +26,18 @@ namespace Kernel
|
|||||||
class BlockBufferWrapper
|
class BlockBufferWrapper
|
||||||
{
|
{
|
||||||
BAN_NON_COPYABLE(BlockBufferWrapper);
|
BAN_NON_COPYABLE(BlockBufferWrapper);
|
||||||
|
BAN_NON_MOVABLE(BlockBufferWrapper);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BlockBufferWrapper(BAN::Span<uint8_t> buffer, void (*callback)(void*, const uint8_t*), void* argument)
|
BlockBufferWrapper(BAN::Span<uint8_t> buffer, bool& used)
|
||||||
: m_buffer(buffer)
|
: m_buffer(buffer)
|
||||||
, m_callback(callback)
|
, m_used(used)
|
||||||
, m_argument(argument)
|
{
|
||||||
{ }
|
ASSERT(m_used);
|
||||||
BlockBufferWrapper(BlockBufferWrapper&& other) { *this = BAN::move(other); }
|
}
|
||||||
~BlockBufferWrapper()
|
~BlockBufferWrapper()
|
||||||
{
|
{
|
||||||
if (m_callback == nullptr)
|
m_used = false;
|
||||||
return;
|
|
||||||
m_callback(m_argument, m_buffer.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockBufferWrapper& operator=(BlockBufferWrapper&& other)
|
|
||||||
{
|
|
||||||
this->m_buffer = other.m_buffer;
|
|
||||||
this->m_callback = other.m_callback;
|
|
||||||
this->m_argument = other.m_argument;
|
|
||||||
|
|
||||||
other.m_buffer = {};
|
|
||||||
other.m_callback = nullptr;
|
|
||||||
other.m_argument = nullptr;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const { return m_buffer.size(); }
|
size_t size() const { return m_buffer.size(); }
|
||||||
@@ -67,8 +53,7 @@ namespace Kernel
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
BAN::Span<uint8_t> m_buffer;
|
BAN::Span<uint8_t> m_buffer;
|
||||||
void (*m_callback)(void*, const uint8_t*);
|
bool& m_used;
|
||||||
void* m_argument;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -77,6 +62,8 @@ namespace Kernel
|
|||||||
|
|
||||||
virtual BAN::RefPtr<Inode> root_inode() override { return m_root_inode; }
|
virtual BAN::RefPtr<Inode> root_inode() override { return m_root_inode; }
|
||||||
|
|
||||||
|
virtual dev_t dev() const override { return m_block_device->rdev(); };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ext2FS(BAN::RefPtr<BlockDevice> block_device)
|
Ext2FS(BAN::RefPtr<BlockDevice> block_device)
|
||||||
: m_block_device(block_device)
|
: m_block_device(block_device)
|
||||||
@@ -94,7 +81,7 @@ namespace Kernel
|
|||||||
BAN::ErrorOr<void> sync_superblock();
|
BAN::ErrorOr<void> sync_superblock();
|
||||||
BAN::ErrorOr<void> sync_block(uint32_t block);
|
BAN::ErrorOr<void> sync_block(uint32_t block);
|
||||||
|
|
||||||
BAN::ErrorOr<BlockBufferWrapper> get_block_buffer();
|
BlockBufferWrapper get_block_buffer();
|
||||||
|
|
||||||
BAN::ErrorOr<uint32_t> reserve_free_block(uint32_t primary_bgd);
|
BAN::ErrorOr<uint32_t> reserve_free_block(uint32_t primary_bgd);
|
||||||
BAN::ErrorOr<void> release_block(uint32_t block);
|
BAN::ErrorOr<void> release_block(uint32_t block);
|
||||||
@@ -117,13 +104,10 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BlockBufferManager() = default;
|
BlockBufferManager() = default;
|
||||||
BAN::ErrorOr<BlockBufferWrapper> get_buffer();
|
BlockBufferWrapper get_buffer();
|
||||||
|
|
||||||
BAN::ErrorOr<void> initialize(size_t block_size);
|
BAN::ErrorOr<void> initialize(size_t block_size);
|
||||||
|
|
||||||
private:
|
|
||||||
void destroy_callback(const uint8_t* buffer_ptr);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct BlockBuffer
|
struct BlockBuffer
|
||||||
{
|
{
|
||||||
@@ -131,20 +115,8 @@ namespace Kernel
|
|||||||
bool used { false };
|
bool used { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ThreadInfo
|
|
||||||
{
|
|
||||||
pid_t tid { 0 };
|
|
||||||
size_t buffers { 0 };
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr size_t max_threads = 8;
|
BAN::Array<BlockBuffer, 10> m_buffers;
|
||||||
static constexpr size_t max_buffers_per_thread = 6;
|
|
||||||
|
|
||||||
Mutex m_buffer_mutex;
|
|
||||||
ThreadBlocker m_buffer_blocker;
|
|
||||||
BAN::Array<BlockBuffer, max_threads * max_buffers_per_thread> m_buffers;
|
|
||||||
BAN::Array<ThreadInfo, max_threads> m_thread_infos;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ namespace Kernel
|
|||||||
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
|
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
|
||||||
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
|
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
|
||||||
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) override;
|
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) override;
|
||||||
virtual BAN::ErrorOr<void> rename_inode_impl(BAN::RefPtr<Inode>, BAN::StringView, BAN::StringView) override;
|
|
||||||
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) override;
|
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) override;
|
||||||
|
|
||||||
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
|
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
|
||||||
@@ -47,32 +46,29 @@ namespace Kernel
|
|||||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||||
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
||||||
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
||||||
virtual BAN::ErrorOr<void> chown_impl(uid_t, gid_t) override;
|
|
||||||
virtual BAN::ErrorOr<void> utimens_impl(const timespec[2]) override;
|
|
||||||
virtual BAN::ErrorOr<void> fsync_impl() override;
|
virtual BAN::ErrorOr<void> fsync_impl() override;
|
||||||
|
|
||||||
virtual bool can_read_impl() const override { return true; }
|
virtual bool can_read_impl() const override { return true; }
|
||||||
virtual bool can_write_impl() const override { return true; }
|
virtual bool can_write_impl() const override { return true; }
|
||||||
virtual bool has_error_impl() const override { return false; }
|
virtual bool has_error_impl() const override { return false; }
|
||||||
virtual bool has_hungup_impl() const override { return false; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Returns maximum number of data blocks in use
|
// Returns maximum number of data blocks in use
|
||||||
// NOTE: the inode might have more blocks than what this suggests if it has been shrinked
|
// NOTE: the inode might have more blocks than what this suggests if it has been shrinked
|
||||||
uint32_t max_used_data_block_count() const { return size() / blksize(); }
|
uint32_t max_used_data_block_count() const { return size() / blksize(); }
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::Optional<uint32_t>> block_from_indirect_block(uint32_t& block, uint32_t index, uint32_t depth, bool allocate);
|
BAN::ErrorOr<BAN::Optional<uint32_t>> block_from_indirect_block(uint32_t block, uint32_t index, uint32_t depth);
|
||||||
BAN::ErrorOr<BAN::Optional<uint32_t>> fs_block_of_data_block_index(uint32_t data_block_index, bool allocate);
|
BAN::ErrorOr<BAN::Optional<uint32_t>> fs_block_of_data_block_index(uint32_t data_block_index);
|
||||||
|
|
||||||
BAN::ErrorOr<void> link_inode_to_directory(Ext2Inode&, BAN::StringView name);
|
BAN::ErrorOr<void> link_inode_to_directory(Ext2Inode&, BAN::StringView name);
|
||||||
BAN::ErrorOr<void> remove_inode_from_directory(BAN::StringView name, bool cleanup_directory);
|
|
||||||
BAN::ErrorOr<bool> is_directory_empty();
|
BAN::ErrorOr<bool> is_directory_empty();
|
||||||
|
|
||||||
BAN::ErrorOr<void> cleanup_indirect_block(uint32_t block, uint32_t depth);
|
BAN::ErrorOr<void> cleanup_indirect_block(uint32_t block, uint32_t depth);
|
||||||
BAN::ErrorOr<void> cleanup_default_links();
|
BAN::ErrorOr<void> cleanup_default_links();
|
||||||
BAN::ErrorOr<void> cleanup_data_blocks();
|
|
||||||
BAN::ErrorOr<void> cleanup_from_fs();
|
BAN::ErrorOr<void> cleanup_from_fs();
|
||||||
|
|
||||||
|
BAN::ErrorOr<uint32_t> allocate_new_block_to_indirect_block(uint32_t& block, uint32_t index, uint32_t depth);
|
||||||
|
BAN::ErrorOr<uint32_t> allocate_new_block(uint32_t data_block_index);
|
||||||
BAN::ErrorOr<void> sync();
|
BAN::ErrorOr<void> sync();
|
||||||
|
|
||||||
uint32_t block_group() const;
|
uint32_t block_group() const;
|
||||||
@@ -85,26 +81,6 @@ namespace Kernel
|
|||||||
{}
|
{}
|
||||||
static BAN::ErrorOr<BAN::RefPtr<Ext2Inode>> create(Ext2FS&, uint32_t);
|
static BAN::ErrorOr<BAN::RefPtr<Ext2Inode>> create(Ext2FS&, uint32_t);
|
||||||
|
|
||||||
private:
|
|
||||||
struct ScopedSync
|
|
||||||
{
|
|
||||||
ScopedSync(Ext2Inode& inode)
|
|
||||||
: inode(inode)
|
|
||||||
, inode_info(inode.m_inode)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
~ScopedSync()
|
|
||||||
{
|
|
||||||
if (memcmp(&inode.m_inode, &inode_info, sizeof(Ext2::Inode)) == 0)
|
|
||||||
return;
|
|
||||||
if (auto ret = inode.sync(); ret.is_error())
|
|
||||||
dwarnln("failed to sync inode: {}", ret.error());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ext2Inode& inode;
|
|
||||||
Ext2::Inode inode_info;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ext2FS& m_fs;
|
Ext2FS& m_fs;
|
||||||
Ext2::Inode m_inode;
|
Ext2::Inode m_inode;
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ namespace Kernel
|
|||||||
|
|
||||||
virtual BAN::RefPtr<Inode> root_inode() override { return m_root_inode; }
|
virtual BAN::RefPtr<Inode> root_inode() override { return m_root_inode; }
|
||||||
|
|
||||||
|
virtual dev_t dev() const override { return m_block_device->rdev(); };
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::RefPtr<FATInode>> open_inode(BAN::RefPtr<FATInode> parent, const FAT::DirectoryEntry& entry, uint32_t cluster_index, uint32_t entry_index);
|
BAN::ErrorOr<BAN::RefPtr<FATInode>> open_inode(BAN::RefPtr<FATInode> parent, const FAT::DirectoryEntry& entry, uint32_t cluster_index, uint32_t entry_index);
|
||||||
BAN::ErrorOr<void> inode_read_cluster(BAN::RefPtr<FATInode>, size_t index, BAN::ByteSpan buffer);
|
BAN::ErrorOr<void> inode_read_cluster(BAN::RefPtr<FATInode>, size_t index, BAN::ByteSpan buffer);
|
||||||
blksize_t inode_block_size(BAN::RefPtr<const FATInode>) const;
|
blksize_t inode_block_size(BAN::RefPtr<const FATInode>) const;
|
||||||
|
|||||||
@@ -44,13 +44,11 @@ namespace Kernel
|
|||||||
//virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
//virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||||
//virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
//virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
||||||
//virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
//virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
||||||
//virtual BAN::ErrorOr<void> utimens_impl(const timespec[2]) override;
|
|
||||||
virtual BAN::ErrorOr<void> fsync_impl() override { return {}; }
|
virtual BAN::ErrorOr<void> fsync_impl() override { return {}; }
|
||||||
|
|
||||||
virtual bool can_read_impl() const override { return true; }
|
virtual bool can_read_impl() const override { return true; }
|
||||||
virtual bool can_write_impl() const override { return true; }
|
virtual bool can_write_impl() const override { return true; }
|
||||||
virtual bool has_error_impl() const override { return false; }
|
virtual bool has_error_impl() const override { return false; }
|
||||||
virtual bool has_hungup_impl() const override { return false; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FATInode(FATFS& fs, const FAT::DirectoryEntry& entry, ino_t ino, uint32_t block_count)
|
FATInode(FATFS& fs, const FAT::DirectoryEntry& entry, ino_t ino, uint32_t block_count)
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ namespace Kernel
|
|||||||
static BAN::ErrorOr<BAN::RefPtr<FileSystem>> from_block_device(BAN::RefPtr<BlockDevice>);
|
static BAN::ErrorOr<BAN::RefPtr<FileSystem>> from_block_device(BAN::RefPtr<BlockDevice>);
|
||||||
|
|
||||||
virtual BAN::RefPtr<Inode> root_inode() = 0;
|
virtual BAN::RefPtr<Inode> root_inode() = 0;
|
||||||
|
|
||||||
|
virtual dev_t dev() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <BAN/ByteSpan.h>
|
#include <BAN/ByteSpan.h>
|
||||||
#include <BAN/LinkedList.h>
|
|
||||||
#include <BAN/RefPtr.h>
|
#include <BAN/RefPtr.h>
|
||||||
#include <BAN/String.h>
|
#include <BAN/String.h>
|
||||||
#include <BAN/StringView.h>
|
#include <BAN/StringView.h>
|
||||||
@@ -20,9 +19,10 @@
|
|||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
class FileBackedRegion;
|
|
||||||
class FileSystem;
|
class FileSystem;
|
||||||
struct SharedFileData;
|
|
||||||
|
class FileBackedRegion;
|
||||||
|
class SharedFileData;
|
||||||
|
|
||||||
class Inode : public BAN::RefCounted<Inode>
|
class Inode : public BAN::RefCounted<Inode>
|
||||||
{
|
{
|
||||||
@@ -85,7 +85,6 @@ namespace Kernel
|
|||||||
virtual dev_t rdev() const = 0;
|
virtual dev_t rdev() const = 0;
|
||||||
|
|
||||||
virtual bool is_device() const { return false; }
|
virtual bool is_device() const { return false; }
|
||||||
virtual bool is_epoll() const { return false; }
|
|
||||||
virtual bool is_pipe() const { return false; }
|
virtual bool is_pipe() const { return false; }
|
||||||
virtual bool is_tty() const { return false; }
|
virtual bool is_tty() const { return false; }
|
||||||
|
|
||||||
@@ -97,7 +96,6 @@ namespace Kernel
|
|||||||
BAN::ErrorOr<void> create_file(BAN::StringView, mode_t, uid_t, gid_t);
|
BAN::ErrorOr<void> create_file(BAN::StringView, mode_t, uid_t, gid_t);
|
||||||
BAN::ErrorOr<void> create_directory(BAN::StringView, mode_t, uid_t, gid_t);
|
BAN::ErrorOr<void> create_directory(BAN::StringView, mode_t, uid_t, gid_t);
|
||||||
BAN::ErrorOr<void> link_inode(BAN::StringView, BAN::RefPtr<Inode>);
|
BAN::ErrorOr<void> link_inode(BAN::StringView, BAN::RefPtr<Inode>);
|
||||||
BAN::ErrorOr<void> rename_inode(BAN::RefPtr<Inode>, BAN::StringView, BAN::StringView);
|
|
||||||
BAN::ErrorOr<void> unlink(BAN::StringView);
|
BAN::ErrorOr<void> unlink(BAN::StringView);
|
||||||
|
|
||||||
// Link API
|
// Link API
|
||||||
@@ -109,12 +107,9 @@ namespace Kernel
|
|||||||
BAN::ErrorOr<void> bind(const sockaddr* address, socklen_t address_len);
|
BAN::ErrorOr<void> bind(const sockaddr* address, socklen_t address_len);
|
||||||
BAN::ErrorOr<void> connect(const sockaddr* address, socklen_t address_len);
|
BAN::ErrorOr<void> connect(const sockaddr* address, socklen_t address_len);
|
||||||
BAN::ErrorOr<void> listen(int backlog);
|
BAN::ErrorOr<void> listen(int backlog);
|
||||||
BAN::ErrorOr<size_t> sendmsg(const msghdr& message, int flags);
|
BAN::ErrorOr<size_t> sendto(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len);
|
||||||
BAN::ErrorOr<size_t> recvmsg(msghdr& message, int flags);
|
BAN::ErrorOr<size_t> recvfrom(BAN::ByteSpan buffer, sockaddr* address, socklen_t* address_len);
|
||||||
BAN::ErrorOr<void> getsockname(sockaddr* address, socklen_t* address_len);
|
BAN::ErrorOr<void> getsockname(sockaddr* address, socklen_t* address_len);
|
||||||
BAN::ErrorOr<void> getpeername(sockaddr* address, socklen_t* address_len);
|
|
||||||
BAN::ErrorOr<void> getsockopt(int level, int option, void* value, socklen_t* value_len);
|
|
||||||
BAN::ErrorOr<void> setsockopt(int level, int option, const void* value, socklen_t value_len);
|
|
||||||
|
|
||||||
// General API
|
// General API
|
||||||
BAN::ErrorOr<size_t> read(off_t, BAN::ByteSpan buffer);
|
BAN::ErrorOr<size_t> read(off_t, BAN::ByteSpan buffer);
|
||||||
@@ -122,33 +117,23 @@ namespace Kernel
|
|||||||
BAN::ErrorOr<void> truncate(size_t);
|
BAN::ErrorOr<void> truncate(size_t);
|
||||||
BAN::ErrorOr<void> chmod(mode_t);
|
BAN::ErrorOr<void> chmod(mode_t);
|
||||||
BAN::ErrorOr<void> chown(uid_t, gid_t);
|
BAN::ErrorOr<void> chown(uid_t, gid_t);
|
||||||
BAN::ErrorOr<void> utimens(const timespec[2]);
|
|
||||||
BAN::ErrorOr<void> fsync();
|
BAN::ErrorOr<void> fsync();
|
||||||
|
|
||||||
// Select/Non blocking API
|
// Select/Non blocking API
|
||||||
bool can_read() const;
|
bool can_read() const;
|
||||||
bool can_write() const;
|
bool can_write() const;
|
||||||
bool has_error() const;
|
bool has_error() const;
|
||||||
bool has_hungup() const;
|
|
||||||
|
|
||||||
BAN::ErrorOr<long> ioctl(int request, void* arg);
|
BAN::ErrorOr<long> ioctl(int request, void* arg);
|
||||||
|
|
||||||
BAN::ErrorOr<void> add_epoll(class Epoll*);
|
|
||||||
void del_epoll(class Epoll*);
|
|
||||||
void epoll_notify(uint32_t event);
|
|
||||||
|
|
||||||
virtual void on_close(int status_flags) { (void)status_flags; }
|
|
||||||
virtual void on_clone(int status_flags) { (void)status_flags; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Directory API
|
// Directory API
|
||||||
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
virtual BAN::ErrorOr<void> rename_inode_impl(BAN::RefPtr<Inode>, BAN::StringView, BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
|
|
||||||
|
|
||||||
// Link API
|
// Link API
|
||||||
virtual BAN::ErrorOr<BAN::String> link_target_impl() { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<BAN::String> link_target_impl() { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
@@ -159,12 +144,9 @@ namespace Kernel
|
|||||||
virtual BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
virtual BAN::ErrorOr<void> listen_impl(int) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<void> listen_impl(int) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
virtual BAN::ErrorOr<void> bind_impl(const sockaddr*, socklen_t) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<void> bind_impl(const sockaddr*, socklen_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
virtual BAN::ErrorOr<size_t> recvmsg_impl(msghdr&, int) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<size_t> sendto_impl(BAN::ConstByteSpan, const sockaddr*, socklen_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
virtual BAN::ErrorOr<size_t> sendmsg_impl(const msghdr&, int) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<size_t> recvfrom_impl(BAN::ByteSpan, sockaddr*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
virtual BAN::ErrorOr<void> getsockname_impl(sockaddr*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<void> getsockname_impl(sockaddr*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); }
|
|
||||||
virtual BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); }
|
|
||||||
virtual BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) { return BAN::Error::from_errno(ENOTSUP); }
|
|
||||||
|
|
||||||
// General API
|
// General API
|
||||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
@@ -172,14 +154,12 @@ namespace Kernel
|
|||||||
virtual BAN::ErrorOr<void> truncate_impl(size_t) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<void> truncate_impl(size_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
virtual BAN::ErrorOr<void> chmod_impl(mode_t) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<void> chmod_impl(mode_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
virtual BAN::ErrorOr<void> chown_impl(uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<void> chown_impl(uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
virtual BAN::ErrorOr<void> utimens_impl(const timespec[2]) { return BAN::Error::from_errno(ENOTSUP); }
|
|
||||||
virtual BAN::ErrorOr<void> fsync_impl() = 0;
|
virtual BAN::ErrorOr<void> fsync_impl() = 0;
|
||||||
|
|
||||||
// Select/Non blocking API
|
// Select/Non blocking API
|
||||||
virtual bool can_read_impl() const = 0;
|
virtual bool can_read_impl() const = 0;
|
||||||
virtual bool can_write_impl() const = 0;
|
virtual bool can_write_impl() const = 0;
|
||||||
virtual bool has_error_impl() const = 0;
|
virtual bool has_error_impl() const = 0;
|
||||||
virtual bool has_hungup_impl() const = 0;
|
|
||||||
|
|
||||||
virtual BAN::ErrorOr<long> ioctl_impl(int, void*) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<long> ioctl_impl(int, void*) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
|
|
||||||
@@ -188,12 +168,9 @@ namespace Kernel
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
BAN::WeakPtr<SharedFileData> m_shared_region;
|
BAN::WeakPtr<SharedFileData> m_shared_region;
|
||||||
SpinLock m_epoll_lock;
|
|
||||||
BAN::LinkedList<class Epoll*> m_epolls;
|
|
||||||
friend class Epoll;
|
|
||||||
friend class FileBackedRegion;
|
friend class FileBackedRegion;
|
||||||
friend class OpenFileDescriptorSet;
|
friend class OpenFileDescriptorSet;
|
||||||
friend struct SharedFileData;
|
friend class SharedFileData;
|
||||||
friend class TTY;
|
friend class TTY;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include <BAN/Array.h>
|
#include <BAN/Array.h>
|
||||||
#include <kernel/FS/Inode.h>
|
#include <kernel/FS/Inode.h>
|
||||||
#include <kernel/Memory/ByteRingBuffer.h>
|
|
||||||
#include <kernel/ThreadBlocker.h>
|
#include <kernel/ThreadBlocker.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
@@ -14,9 +13,8 @@ namespace Kernel
|
|||||||
static BAN::ErrorOr<BAN::RefPtr<Inode>> create(const Credentials&);
|
static BAN::ErrorOr<BAN::RefPtr<Inode>> create(const Credentials&);
|
||||||
|
|
||||||
virtual bool is_pipe() const override { return true; }
|
virtual bool is_pipe() const override { return true; }
|
||||||
|
void clone_writing();
|
||||||
void on_close(int status_flags) override;
|
void close_writing();
|
||||||
void on_clone(int status_flags) override;
|
|
||||||
|
|
||||||
virtual ino_t ino() const override { return 0; } // FIXME
|
virtual ino_t ino() const override { return 0; } // FIXME
|
||||||
virtual Mode mode() const override { return { Mode::IFIFO | Mode::IRUSR | Mode::IWUSR }; }
|
virtual Mode mode() const override { return { Mode::IFIFO | Mode::IRUSR | Mode::IWUSR }; }
|
||||||
@@ -39,10 +37,9 @@ namespace Kernel
|
|||||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||||
virtual BAN::ErrorOr<void> fsync_impl() final override { return {}; }
|
virtual BAN::ErrorOr<void> fsync_impl() final override { return {}; }
|
||||||
|
|
||||||
virtual bool can_read_impl() const override { return !m_buffer->empty(); }
|
virtual bool can_read_impl() const override { return m_buffer_size > 0; }
|
||||||
virtual bool can_write_impl() const override { return true; }
|
virtual bool can_write_impl() const override { return true; }
|
||||||
virtual bool has_error_impl() const override { return m_reading_count == 0; }
|
virtual bool has_error_impl() const override { return false; }
|
||||||
virtual bool has_hungup_impl() const override { return m_writing_count == 0; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Pipe(const Credentials&);
|
Pipe(const Credentials&);
|
||||||
@@ -55,10 +52,11 @@ namespace Kernel
|
|||||||
timespec m_ctime {};
|
timespec m_ctime {};
|
||||||
ThreadBlocker m_thread_blocker;
|
ThreadBlocker m_thread_blocker;
|
||||||
|
|
||||||
BAN::UniqPtr<ByteRingBuffer> m_buffer;
|
BAN::Array<uint8_t, PAGE_SIZE> m_buffer;
|
||||||
|
BAN::Atomic<size_t> m_buffer_size { 0 };
|
||||||
|
size_t m_buffer_tail { 0 };
|
||||||
|
|
||||||
BAN::Atomic<uint32_t> m_writing_count { 1 };
|
BAN::Atomic<uint32_t> m_writing_count { 1 };
|
||||||
BAN::Atomic<uint32_t> m_reading_count { 1 };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ namespace Kernel
|
|||||||
virtual bool can_read_impl() const override { return true; }
|
virtual bool can_read_impl() const override { return true; }
|
||||||
virtual bool can_write_impl() const override { return false; }
|
virtual bool can_write_impl() const override { return false; }
|
||||||
virtual bool has_error_impl() const override { return false; }
|
virtual bool has_error_impl() const override { return false; }
|
||||||
virtual bool has_hungup_impl() const override { return false; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ProcROProcessInode(Process&, size_t (Process::*)(off_t, BAN::ByteSpan) const, TmpFileSystem&, const TmpInodeInfo&);
|
ProcROProcessInode(Process&, size_t (Process::*)(off_t, BAN::ByteSpan) const, TmpFileSystem&, const TmpInodeInfo&);
|
||||||
@@ -57,31 +56,6 @@ namespace Kernel
|
|||||||
size_t (Process::*m_callback)(off_t, BAN::ByteSpan) const;
|
size_t (Process::*m_callback)(off_t, BAN::ByteSpan) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ProcSymlinkProcessInode final : public TmpInode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static BAN::ErrorOr<BAN::RefPtr<ProcSymlinkProcessInode>> create_new(Process& process, BAN::ErrorOr<BAN::String> (Process::*callback)() const, TmpFileSystem&, mode_t);
|
|
||||||
~ProcSymlinkProcessInode() = default;
|
|
||||||
|
|
||||||
virtual uid_t uid() const override { return m_process.credentials().ruid(); }
|
|
||||||
virtual gid_t gid() const override { return m_process.credentials().rgid(); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
|
|
||||||
|
|
||||||
virtual bool can_read_impl() const override { return false; }
|
|
||||||
virtual bool can_write_impl() const override { return false; }
|
|
||||||
virtual bool has_error_impl() const override { return false; }
|
|
||||||
virtual bool has_hungup_impl() const override { return false; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
ProcSymlinkProcessInode(Process& process, BAN::ErrorOr<BAN::String> (Process::*)() const, TmpFileSystem&, const TmpInodeInfo&);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Process& m_process;
|
|
||||||
BAN::ErrorOr<BAN::String> (Process::*m_callback)() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ProcROInode final : public TmpInode
|
class ProcROInode final : public TmpInode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -98,7 +72,6 @@ namespace Kernel
|
|||||||
virtual bool can_read_impl() const override { return true; }
|
virtual bool can_read_impl() const override { return true; }
|
||||||
virtual bool can_write_impl() const override { return false; }
|
virtual bool can_write_impl() const override { return false; }
|
||||||
virtual bool has_error_impl() const override { return false; }
|
virtual bool has_error_impl() const override { return false; }
|
||||||
virtual bool has_hungup_impl() const override { return false; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ProcROInode(size_t (*callback)(off_t, BAN::ByteSpan), TmpFileSystem&, const TmpInodeInfo&);
|
ProcROInode(size_t (*callback)(off_t, BAN::ByteSpan), TmpFileSystem&, const TmpInodeInfo&);
|
||||||
@@ -107,57 +80,4 @@ namespace Kernel
|
|||||||
size_t (*m_callback)(off_t, BAN::ByteSpan);
|
size_t (*m_callback)(off_t, BAN::ByteSpan);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ProcSymlinkInode final : public TmpInode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static BAN::ErrorOr<BAN::RefPtr<ProcSymlinkInode>> create_new(BAN::ErrorOr<BAN::String> (*)(void*), void (*)(void*), void* data, TmpFileSystem&, mode_t, uid_t, gid_t);
|
|
||||||
~ProcSymlinkInode();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
|
|
||||||
|
|
||||||
virtual bool can_read_impl() const override { return false; }
|
|
||||||
virtual bool can_write_impl() const override { return false; }
|
|
||||||
virtual bool has_error_impl() const override { return false; }
|
|
||||||
virtual bool has_hungup_impl() const override { return false; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
ProcSymlinkInode(BAN::ErrorOr<BAN::String> (*callback)(void*), void (*destructor)(void*), void* data, TmpFileSystem&, const TmpInodeInfo&);
|
|
||||||
|
|
||||||
private:
|
|
||||||
BAN::ErrorOr<BAN::String> (*m_callback)(void*);
|
|
||||||
void (*m_destructor)(void*);
|
|
||||||
void* m_data;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ProcFDDirectoryInode final : public TmpInode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static BAN::ErrorOr<BAN::RefPtr<ProcFDDirectoryInode>> create_new(Process&, TmpFileSystem&, mode_t);
|
|
||||||
~ProcFDDirectoryInode() = default;
|
|
||||||
|
|
||||||
virtual uid_t uid() const override { return m_process.credentials().ruid(); }
|
|
||||||
virtual gid_t gid() const override { return m_process.credentials().rgid(); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) override;
|
|
||||||
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) override;
|
|
||||||
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override { return BAN::Error::from_errno(EPERM); }
|
|
||||||
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) override { return BAN::Error::from_errno(EPERM); }
|
|
||||||
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) override { return BAN::Error::from_errno(EPERM); }
|
|
||||||
virtual BAN::ErrorOr<void> rename_inode_impl(BAN::RefPtr<Inode>, BAN::StringView, BAN::StringView) override { return BAN::Error::from_errno(EPERM); }
|
|
||||||
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) override { return BAN::Error::from_errno(EPERM); }
|
|
||||||
|
|
||||||
virtual bool can_read_impl() const override { return false; }
|
|
||||||
virtual bool can_write_impl() const override { return false; }
|
|
||||||
virtual bool has_error_impl() const override { return false; }
|
|
||||||
virtual bool has_hungup_impl() const override { return false; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
ProcFDDirectoryInode(Process&, TmpFileSystem&, const TmpInodeInfo&);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Process& m_process;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ namespace Kernel
|
|||||||
: m_info(info)
|
: m_info(info)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan buffer) override { return recvfrom_impl(buffer, nullptr, nullptr); }
|
||||||
|
BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan buffer) override { return sendto_impl(buffer, nullptr, 0); }
|
||||||
BAN::ErrorOr<void> fsync_impl() final override { return {}; }
|
BAN::ErrorOr<void> fsync_impl() final override { return {}; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace Kernel
|
|||||||
// 1x singly indirect
|
// 1x singly indirect
|
||||||
// 1x doubly indirect
|
// 1x doubly indirect
|
||||||
// 1x triply indirect
|
// 1x triply indirect
|
||||||
BAN::Array<size_t, 5> block;
|
BAN::Array<paddr_t, 5> block;
|
||||||
static constexpr size_t direct_block_count = 2;
|
static constexpr size_t direct_block_count = 2;
|
||||||
#elif ARCH(i686)
|
#elif ARCH(i686)
|
||||||
uint32_t __padding;
|
uint32_t __padding;
|
||||||
@@ -36,8 +36,8 @@ namespace Kernel
|
|||||||
// 1x singly indirect
|
// 1x singly indirect
|
||||||
// 1x doubly indirect
|
// 1x doubly indirect
|
||||||
// 1x triply indirect
|
// 1x triply indirect
|
||||||
BAN::Array<size_t, 16> block;
|
BAN::Array<paddr_t, 8> block;
|
||||||
static constexpr size_t direct_block_count = 13;
|
static constexpr size_t direct_block_count = 5;
|
||||||
#else
|
#else
|
||||||
#error
|
#error
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ namespace Kernel
|
|||||||
|
|
||||||
virtual BAN::RefPtr<Inode> root_inode() override { return m_root_inode; }
|
virtual BAN::RefPtr<Inode> root_inode() override { return m_root_inode; }
|
||||||
|
|
||||||
dev_t rdev() const { return m_rdev; }
|
virtual dev_t dev() const override { return m_rdev; }
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::RefPtr<TmpInode>> open_inode(ino_t ino);
|
BAN::ErrorOr<BAN::RefPtr<TmpInode>> open_inode(ino_t ino);
|
||||||
|
|
||||||
@@ -118,8 +118,16 @@ namespace Kernel
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
InodeLocation find_inode(ino_t ino);
|
InodeLocation find_inode(ino_t ino);
|
||||||
|
|
||||||
paddr_t find_block(size_t index);
|
paddr_t find_block(size_t index);
|
||||||
|
|
||||||
|
template<TmpFuncs::for_each_indirect_paddr_allocating_callback F>
|
||||||
|
BAN::ErrorOr<void> for_each_indirect_paddr_allocating(PageInfo page_info, F callback, size_t depth);
|
||||||
|
template<TmpFuncs::for_each_indirect_paddr_allocating_callback F>
|
||||||
|
BAN::ErrorOr<BAN::Iteration> for_each_indirect_paddr_allocating_internal(PageInfo page_info, F callback, size_t depth);
|
||||||
|
|
||||||
|
paddr_t find_indirect(PageInfo root, size_t index, size_t depth);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const dev_t m_rdev;
|
const dev_t m_rdev;
|
||||||
|
|
||||||
@@ -138,14 +146,14 @@ namespace Kernel
|
|||||||
static constexpr size_t max_data_pages =
|
static constexpr size_t max_data_pages =
|
||||||
(PAGE_SIZE / sizeof(PageInfo)) *
|
(PAGE_SIZE / sizeof(PageInfo)) *
|
||||||
(PAGE_SIZE / sizeof(PageInfo)) *
|
(PAGE_SIZE / sizeof(PageInfo)) *
|
||||||
(PAGE_SIZE / sizeof(PageInfo) - 1);
|
(PAGE_SIZE / sizeof(PageInfo));
|
||||||
|
|
||||||
// We store inodes in pages with double indirection.
|
// We store inodes in pages with double indirection.
|
||||||
// With 64-bit pointers we can store 512^2 pages of inodes
|
// With 64-bit pointers we can store 512^2 pages of inodes
|
||||||
// which should be enough for now.
|
// which should be enough for now.
|
||||||
// In future this should be dynamically calculated based on maximum
|
// In future this should be dynamically calculated based on maximum
|
||||||
// number of pages for this file system.
|
// number of pages for this file system.
|
||||||
PageInfo m_inode_pages {};
|
PageInfo m_inode_pages;
|
||||||
static constexpr size_t first_inode = 1;
|
static constexpr size_t first_inode = 1;
|
||||||
static constexpr size_t max_inodes =
|
static constexpr size_t max_inodes =
|
||||||
(PAGE_SIZE / sizeof(PageInfo)) *
|
(PAGE_SIZE / sizeof(PageInfo)) *
|
||||||
|
|||||||
@@ -47,22 +47,14 @@ namespace Kernel
|
|||||||
protected:
|
protected:
|
||||||
TmpInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
TmpInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
||||||
|
|
||||||
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
|
||||||
virtual BAN::ErrorOr<void> chown_impl(uid_t, gid_t) override;
|
|
||||||
virtual BAN::ErrorOr<void> utimens_impl(const timespec[2]) override;
|
|
||||||
virtual BAN::ErrorOr<void> fsync_impl() override { return {}; }
|
virtual BAN::ErrorOr<void> fsync_impl() override { return {}; }
|
||||||
|
|
||||||
void sync();
|
void sync();
|
||||||
|
void free_all_blocks();
|
||||||
virtual BAN::ErrorOr<void> prepare_unlink() { return {}; };
|
virtual BAN::ErrorOr<void> prepare_unlink() { return {}; };
|
||||||
|
|
||||||
void free_all_blocks();
|
|
||||||
void free_indirect_blocks(size_t block, uint32_t depth);
|
|
||||||
|
|
||||||
BAN::Optional<size_t> block_index(size_t data_block_index);
|
BAN::Optional<size_t> block_index(size_t data_block_index);
|
||||||
BAN::Optional<size_t> block_index_from_indirect(size_t block, size_t index, uint32_t depth);
|
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> block_index_with_allocation(size_t data_block_index);
|
BAN::ErrorOr<size_t> block_index_with_allocation(size_t data_block_index);
|
||||||
BAN::ErrorOr<size_t> block_index_from_indirect_with_allocation(size_t& block, size_t index, uint32_t depth);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TmpFileSystem& m_fs;
|
TmpFileSystem& m_fs;
|
||||||
@@ -83,11 +75,11 @@ namespace Kernel
|
|||||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||||
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
||||||
|
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
||||||
|
|
||||||
virtual bool can_read_impl() const override { return true; }
|
virtual bool can_read_impl() const override { return true; }
|
||||||
virtual bool can_write_impl() const override { return true; }
|
virtual bool can_write_impl() const override { return true; }
|
||||||
virtual bool has_error_impl() const override { return false; }
|
virtual bool has_error_impl() const override { return false; }
|
||||||
virtual bool has_hungup_impl() const override { return false; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TmpFileInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
TmpFileInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
||||||
@@ -105,11 +97,11 @@ namespace Kernel
|
|||||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override { return BAN::Error::from_errno(ENODEV); }
|
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override { return BAN::Error::from_errno(ENODEV); }
|
||||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override { return BAN::Error::from_errno(ENODEV); }
|
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override { return BAN::Error::from_errno(ENODEV); }
|
||||||
virtual BAN::ErrorOr<void> truncate_impl(size_t) override { return BAN::Error::from_errno(ENODEV); }
|
virtual BAN::ErrorOr<void> truncate_impl(size_t) override { return BAN::Error::from_errno(ENODEV); }
|
||||||
|
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
||||||
|
|
||||||
virtual bool can_read_impl() const override { return false; }
|
virtual bool can_read_impl() const override { return false; }
|
||||||
virtual bool can_write_impl() const override { return false; }
|
virtual bool can_write_impl() const override { return false; }
|
||||||
virtual bool has_error_impl() const override { return false; }
|
virtual bool has_error_impl() const override { return false; }
|
||||||
virtual bool has_hungup_impl() const override { return false; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TmpSocketInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
TmpSocketInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
||||||
@@ -123,14 +115,14 @@ namespace Kernel
|
|||||||
static BAN::ErrorOr<BAN::RefPtr<TmpSymlinkInode>> create_new(TmpFileSystem&, mode_t, uid_t, gid_t, BAN::StringView target);
|
static BAN::ErrorOr<BAN::RefPtr<TmpSymlinkInode>> create_new(TmpFileSystem&, mode_t, uid_t, gid_t, BAN::StringView target);
|
||||||
~TmpSymlinkInode();
|
~TmpSymlinkInode();
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> set_link_target(BAN::StringView);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BAN::ErrorOr<BAN::String> link_target_impl() override;
|
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
|
||||||
BAN::ErrorOr<void> set_link_target_impl(BAN::StringView) override;
|
|
||||||
|
|
||||||
virtual bool can_read_impl() const override { return false; }
|
virtual bool can_read_impl() const override { return false; }
|
||||||
virtual bool can_write_impl() const override { return false; }
|
virtual bool can_write_impl() const override { return false; }
|
||||||
virtual bool has_error_impl() const override { return false; }
|
virtual bool has_error_impl() const override { return false; }
|
||||||
virtual bool has_hungup_impl() const override { return false; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TmpSymlinkInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
TmpSymlinkInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
||||||
@@ -156,21 +148,16 @@ namespace Kernel
|
|||||||
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) override final;
|
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) override final;
|
||||||
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override final;
|
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override final;
|
||||||
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) override final;
|
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) override final;
|
||||||
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) override final;
|
|
||||||
virtual BAN::ErrorOr<void> rename_inode_impl(BAN::RefPtr<Inode>, BAN::StringView, BAN::StringView) override final;
|
|
||||||
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) override;
|
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) override;
|
||||||
|
|
||||||
virtual bool can_read_impl() const override { return false; }
|
virtual bool can_read_impl() const override { return false; }
|
||||||
virtual bool can_write_impl() const override { return false; }
|
virtual bool can_write_impl() const override { return false; }
|
||||||
virtual bool has_error_impl() const override { return false; }
|
virtual bool has_error_impl() const override { return false; }
|
||||||
virtual bool has_hungup_impl() const override { return false; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<TmpFuncs::for_each_valid_entry_callback F>
|
template<TmpFuncs::for_each_valid_entry_callback F>
|
||||||
void for_each_valid_entry(F callback);
|
void for_each_valid_entry(F callback);
|
||||||
|
|
||||||
BAN::ErrorOr<void> unlink_inode(BAN::StringView, bool cleanup);
|
|
||||||
|
|
||||||
friend class TmpInode;
|
friend class TmpInode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <kernel/BootInfo.h>
|
|
||||||
#include <kernel/FS/FileSystem.h>
|
|
||||||
|
|
||||||
namespace Kernel
|
|
||||||
{
|
|
||||||
|
|
||||||
bool is_ustar_boot_module(const BootModule&);
|
|
||||||
BAN::ErrorOr<void> unpack_boot_module_into_filesystem(BAN::RefPtr<FileSystem>, const BootModule&);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -29,6 +29,9 @@ namespace Kernel
|
|||||||
|
|
||||||
virtual BAN::RefPtr<Inode> root_inode() override { return m_root_fs->root_inode(); }
|
virtual BAN::RefPtr<Inode> root_inode() override { return m_root_fs->root_inode(); }
|
||||||
|
|
||||||
|
// FIXME:
|
||||||
|
virtual dev_t dev() const override { return 0; }
|
||||||
|
|
||||||
BAN::ErrorOr<void> mount(const Credentials&, BAN::StringView, BAN::StringView);
|
BAN::ErrorOr<void> mount(const Credentials&, BAN::StringView, BAN::StringView);
|
||||||
BAN::ErrorOr<void> mount(const Credentials&, BAN::RefPtr<FileSystem>, BAN::StringView);
|
BAN::ErrorOr<void> mount(const Credentials&, BAN::RefPtr<FileSystem>, BAN::StringView);
|
||||||
|
|
||||||
@@ -71,13 +74,13 @@ namespace Kernel
|
|||||||
|
|
||||||
File root_file()
|
File root_file()
|
||||||
{
|
{
|
||||||
return File { root_inode(), "/"_sv };
|
return File(root_inode(), "/"_sv);
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<File> file_from_relative_path(BAN::RefPtr<Inode> root_inode, const File& parent, const Credentials&, BAN::StringView, int);
|
BAN::ErrorOr<File> file_from_relative_path(const File& parent, const Credentials&, BAN::StringView, int);
|
||||||
BAN::ErrorOr<File> file_from_absolute_path(BAN::RefPtr<Inode> root_inode, const Credentials& credentials, BAN::StringView path, int flags)
|
BAN::ErrorOr<File> file_from_absolute_path(const Credentials& credentials, BAN::StringView path, int flags)
|
||||||
{
|
{
|
||||||
return file_from_relative_path(root_inode, File { root_inode, "/"_sv }, credentials, path, flags);
|
return file_from_relative_path(root_file(), credentials, path, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -129,8 +129,7 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if ARCH(i686)
|
#if ARCH(i686)
|
||||||
void set_fsbase(uintptr_t addr);
|
void set_tls(uintptr_t addr);
|
||||||
void set_gsbase(uintptr_t addr);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -151,11 +150,11 @@ namespace Kernel
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
#if ARCH(x86_64)
|
#if ARCH(x86_64)
|
||||||
BAN::Array<SegmentDescriptor, 8> m_gdt; // null, kernel code, kernel data, user code (32 bit), user data, user code (64 bit), tss low, tss high
|
BAN::Array<SegmentDescriptor, 7> m_gdt; // null, kernel code, kernel data, user code, user data, tss low, tss high
|
||||||
static constexpr uint16_t m_tss_offset = 0x30;
|
static constexpr uint16_t m_tss_offset = 0x28;
|
||||||
#elif ARCH(i686)
|
#elif ARCH(i686)
|
||||||
BAN::Array<SegmentDescriptor, 9> m_gdt; // null, kernel code, kernel data, user code, user data, processor data, fsbase, gsbase, tss
|
BAN::Array<SegmentDescriptor, 8> m_gdt; // null, kernel code, kernel data, user code, user data, processor data, tls, tss
|
||||||
static constexpr uint16_t m_tss_offset = 0x40;
|
static constexpr uint16_t m_tss_offset = 0x38;
|
||||||
#endif
|
#endif
|
||||||
TaskStateSegment m_tss;
|
TaskStateSegment m_tss;
|
||||||
const GDTR m_gdtr {
|
const GDTR m_gdtr {
|
||||||
|
|||||||
@@ -18,12 +18,10 @@ namespace Kernel
|
|||||||
|
|
||||||
constexpr uint8_t IRQ_VECTOR_BASE = 0x20;
|
constexpr uint8_t IRQ_VECTOR_BASE = 0x20;
|
||||||
constexpr uint8_t IRQ_MSI_BASE = 0x80;
|
constexpr uint8_t IRQ_MSI_BASE = 0x80;
|
||||||
constexpr uint8_t IRQ_MSI_END = 0xF0;
|
|
||||||
#if ARCH(i686)
|
|
||||||
constexpr uint8_t IRQ_SYSCALL = 0xF0;
|
constexpr uint8_t IRQ_SYSCALL = 0xF0;
|
||||||
#endif
|
constexpr uint8_t IRQ_YIELD = 0xF1;
|
||||||
constexpr uint8_t IRQ_IPI = 0xF1;
|
constexpr uint8_t IRQ_IPI = 0xF2;
|
||||||
constexpr uint8_t IRQ_TIMER = 0xF2;
|
constexpr uint8_t IRQ_TIMER = 0xF3;
|
||||||
|
|
||||||
#if ARCH(x86_64)
|
#if ARCH(x86_64)
|
||||||
struct GateDescriptor
|
struct GateDescriptor
|
||||||
@@ -77,7 +75,7 @@ namespace Kernel
|
|||||||
private:
|
private:
|
||||||
IDT() = default;
|
IDT() = default;
|
||||||
|
|
||||||
void register_interrupt_handler(uint8_t index, void (*handler)(), uint8_t ist = 0);
|
void register_interrupt_handler(uint8_t index, void (*handler)());
|
||||||
void register_syscall_handler(uint8_t index, void (*handler)());
|
void register_syscall_handler(uint8_t index, void (*handler)());
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
Mouse,
|
Mouse,
|
||||||
Keyboard,
|
Keyboard,
|
||||||
Joystick,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -32,7 +31,7 @@ namespace Kernel
|
|||||||
bool can_read_impl() const override { SpinLockGuard _(m_event_lock); return m_event_count > 0; }
|
bool can_read_impl() const override { SpinLockGuard _(m_event_lock); return m_event_count > 0; }
|
||||||
bool can_write_impl() const override { return false; }
|
bool can_write_impl() const override { return false; }
|
||||||
bool has_error_impl() const override { return false; }
|
bool has_error_impl() const override { return false; }
|
||||||
bool has_hungup_impl() const override { return false; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BAN::ErrorOr<size_t> read_non_block(BAN::ByteSpan);
|
BAN::ErrorOr<size_t> read_non_block(BAN::ByteSpan);
|
||||||
@@ -65,7 +64,7 @@ namespace Kernel
|
|||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::RefPtr<KeyboardDevice>> create(mode_t mode, uid_t uid, gid_t gid);
|
static BAN::ErrorOr<BAN::RefPtr<KeyboardDevice>> create(mode_t mode, uid_t uid, gid_t gid);
|
||||||
|
|
||||||
void notify();
|
void notify() { m_thread_blocker.unblock(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
KeyboardDevice(mode_t mode, uid_t uid, gid_t gid);
|
KeyboardDevice(mode_t mode, uid_t uid, gid_t gid);
|
||||||
@@ -74,7 +73,6 @@ namespace Kernel
|
|||||||
bool can_read_impl() const override;
|
bool can_read_impl() const override;
|
||||||
bool can_write_impl() const override { return false; }
|
bool can_write_impl() const override { return false; }
|
||||||
bool has_error_impl() const override { return false; }
|
bool has_error_impl() const override { return false; }
|
||||||
bool has_hungup_impl() const override { return false; }
|
|
||||||
|
|
||||||
BAN::StringView name() const final override { return m_name; }
|
BAN::StringView name() const final override { return m_name; }
|
||||||
dev_t rdev() const final override { return m_rdev; }
|
dev_t rdev() const final override { return m_rdev; }
|
||||||
@@ -92,7 +90,7 @@ namespace Kernel
|
|||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::RefPtr<MouseDevice>> create(mode_t mode, uid_t uid, gid_t gid);
|
static BAN::ErrorOr<BAN::RefPtr<MouseDevice>> create(mode_t mode, uid_t uid, gid_t gid);
|
||||||
|
|
||||||
void notify();
|
void notify() { m_thread_blocker.unblock(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MouseDevice(mode_t mode, uid_t uid, gid_t gid);
|
MouseDevice(mode_t mode, uid_t uid, gid_t gid);
|
||||||
@@ -101,7 +99,6 @@ namespace Kernel
|
|||||||
bool can_read_impl() const override;
|
bool can_read_impl() const override;
|
||||||
bool can_write_impl() const override { return false; }
|
bool can_write_impl() const override { return false; }
|
||||||
bool has_error_impl() const override { return false; }
|
bool has_error_impl() const override { return false; }
|
||||||
bool has_hungup_impl() const override { return false; }
|
|
||||||
|
|
||||||
BAN::StringView name() const final override { return m_name; }
|
BAN::StringView name() const final override { return m_name; }
|
||||||
dev_t rdev() const final override { return m_rdev; }
|
dev_t rdev() const final override { return m_rdev; }
|
||||||
|
|||||||
@@ -14,15 +14,6 @@ namespace Kernel::Input
|
|||||||
|
|
||||||
class PS2Controller
|
class PS2Controller
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
enum class DeviceType
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
Unknown,
|
|
||||||
Keyboard,
|
|
||||||
Mouse,
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<void> initialize(uint8_t scancode_set);
|
static BAN::ErrorOr<void> initialize(uint8_t scancode_set);
|
||||||
static PS2Controller& get();
|
static PS2Controller& get();
|
||||||
@@ -33,14 +24,10 @@ namespace Kernel::Input
|
|||||||
// Returns true, if byte is used as command, if returns false, byte is meant to device
|
// Returns true, if byte is used as command, if returns false, byte is meant to device
|
||||||
bool handle_command_byte(PS2Device*, uint8_t);
|
bool handle_command_byte(PS2Device*, uint8_t);
|
||||||
|
|
||||||
uint8_t data_port() const { return m_data_port; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PS2Controller() = default;
|
PS2Controller() = default;
|
||||||
BAN::ErrorOr<void> initialize_impl(uint8_t scancode_set);
|
BAN::ErrorOr<void> initialize_impl(uint8_t scancode_set);
|
||||||
BAN::ErrorOr<DeviceType> identify_device(uint8_t);
|
BAN::ErrorOr<void> initialize_device(uint8_t, uint8_t scancode_set);
|
||||||
|
|
||||||
void device_initialize_task(void*);
|
|
||||||
|
|
||||||
BAN::ErrorOr<uint8_t> read_byte();
|
BAN::ErrorOr<uint8_t> read_byte();
|
||||||
BAN::ErrorOr<void> send_byte(uint16_t port, uint8_t byte);
|
BAN::ErrorOr<void> send_byte(uint16_t port, uint8_t byte);
|
||||||
@@ -72,9 +59,6 @@ namespace Kernel::Input
|
|||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint16_t m_command_port { PS2::IOPort::COMMAND };
|
|
||||||
uint16_t m_data_port { PS2::IOPort::DATA };
|
|
||||||
|
|
||||||
BAN::RefPtr<PS2Device> m_devices[2];
|
BAN::RefPtr<PS2Device> m_devices[2];
|
||||||
|
|
||||||
Mutex m_mutex;
|
Mutex m_mutex;
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ namespace Kernel::Input
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
PS2Device(PS2Controller&, InputDevice::Type type);
|
PS2Device(PS2Controller&, InputDevice::Type type);
|
||||||
virtual ~PS2Device();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PS2Controller& m_controller;
|
PS2Controller& m_controller;
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ namespace Kernel
|
|||||||
uintptr_t r10;
|
uintptr_t r10;
|
||||||
uintptr_t r9;
|
uintptr_t r9;
|
||||||
uintptr_t r8;
|
uintptr_t r8;
|
||||||
|
|
||||||
uintptr_t rdi;
|
uintptr_t rdi;
|
||||||
uintptr_t rsi;
|
uintptr_t rsi;
|
||||||
uintptr_t rbp;
|
uintptr_t rbp;
|
||||||
@@ -35,18 +36,6 @@ namespace Kernel
|
|||||||
uintptr_t rcx;
|
uintptr_t rcx;
|
||||||
uintptr_t rax;
|
uintptr_t rax;
|
||||||
};
|
};
|
||||||
struct YieldRegisters
|
|
||||||
{
|
|
||||||
uintptr_t r15;
|
|
||||||
uintptr_t r14;
|
|
||||||
uintptr_t r13;
|
|
||||||
uintptr_t r12;
|
|
||||||
uintptr_t rbp;
|
|
||||||
uintptr_t rbx;
|
|
||||||
uintptr_t ret;
|
|
||||||
uintptr_t sp;
|
|
||||||
uintptr_t ip;
|
|
||||||
};
|
|
||||||
#elif ARCH(i686)
|
#elif ARCH(i686)
|
||||||
struct InterruptRegisters
|
struct InterruptRegisters
|
||||||
{
|
{
|
||||||
@@ -59,16 +48,6 @@ namespace Kernel
|
|||||||
uintptr_t ecx;
|
uintptr_t ecx;
|
||||||
uintptr_t eax;
|
uintptr_t eax;
|
||||||
};
|
};
|
||||||
struct YieldRegisters
|
|
||||||
{
|
|
||||||
uintptr_t ebp;
|
|
||||||
uintptr_t edi;
|
|
||||||
uintptr_t esi;
|
|
||||||
uintptr_t ebx;
|
|
||||||
uintptr_t ret;
|
|
||||||
uintptr_t sp;
|
|
||||||
uintptr_t ip;
|
|
||||||
};
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,4 +29,30 @@ namespace Kernel
|
|||||||
Lock& m_lock;
|
Lock& m_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename Lock>
|
||||||
|
class LockFreeGuard
|
||||||
|
{
|
||||||
|
BAN_NON_COPYABLE(LockFreeGuard);
|
||||||
|
BAN_NON_MOVABLE(LockFreeGuard);
|
||||||
|
|
||||||
|
public:
|
||||||
|
LockFreeGuard(Lock& lock)
|
||||||
|
: m_lock(lock)
|
||||||
|
, m_depth(lock.lock_depth())
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < m_depth; i++)
|
||||||
|
m_lock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
~LockFreeGuard()
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < m_depth; i++)
|
||||||
|
m_lock.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Lock& m_lock;
|
||||||
|
const uint32_t m_depth;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,19 +9,7 @@
|
|||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
class BaseMutex
|
class Mutex
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual void lock() = 0;
|
|
||||||
virtual bool try_lock() = 0;
|
|
||||||
virtual void unlock() = 0;
|
|
||||||
|
|
||||||
virtual pid_t locker() const = 0;
|
|
||||||
virtual bool is_locked() const = 0;
|
|
||||||
virtual uint32_t lock_depth() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Mutex : public BaseMutex
|
|
||||||
{
|
{
|
||||||
BAN_NON_COPYABLE(Mutex);
|
BAN_NON_COPYABLE(Mutex);
|
||||||
BAN_NON_MOVABLE(Mutex);
|
BAN_NON_MOVABLE(Mutex);
|
||||||
@@ -29,14 +17,13 @@ namespace Kernel
|
|||||||
public:
|
public:
|
||||||
Mutex() = default;
|
Mutex() = default;
|
||||||
|
|
||||||
void lock() override
|
void lock()
|
||||||
{
|
{
|
||||||
const auto tid = Thread::current_tid();
|
const auto tid = Thread::current_tid();
|
||||||
if (tid == m_locker)
|
if (tid == m_locker)
|
||||||
ASSERT(m_lock_depth > 0);
|
ASSERT(m_lock_depth > 0);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ASSERT(!tid || !Thread::current().has_spinlock());
|
|
||||||
pid_t expected = -1;
|
pid_t expected = -1;
|
||||||
while (!m_locker.compare_exchange(expected, tid))
|
while (!m_locker.compare_exchange(expected, tid))
|
||||||
{
|
{
|
||||||
@@ -50,7 +37,7 @@ namespace Kernel
|
|||||||
m_lock_depth++;
|
m_lock_depth++;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool try_lock() override
|
bool try_lock()
|
||||||
{
|
{
|
||||||
const auto tid = Thread::current_tid();
|
const auto tid = Thread::current_tid();
|
||||||
if (tid == m_locker)
|
if (tid == m_locker)
|
||||||
@@ -68,7 +55,7 @@ namespace Kernel
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unlock() override
|
void unlock()
|
||||||
{
|
{
|
||||||
const auto tid = Thread::current_tid();
|
const auto tid = Thread::current_tid();
|
||||||
ASSERT(m_locker == tid);
|
ASSERT(m_locker == tid);
|
||||||
@@ -81,16 +68,16 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t locker() const override { return m_locker; }
|
pid_t locker() const { return m_locker; }
|
||||||
bool is_locked() const override { return m_locker != -1; }
|
bool is_locked() const { return m_locker != -1; }
|
||||||
uint32_t lock_depth() const override { return m_lock_depth; }
|
uint32_t lock_depth() const { return m_lock_depth; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BAN::Atomic<pid_t> m_locker { -1 };
|
BAN::Atomic<pid_t> m_locker { -1 };
|
||||||
uint32_t m_lock_depth { 0 };
|
uint32_t m_lock_depth { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
class PriorityMutex : public BaseMutex
|
class PriorityMutex
|
||||||
{
|
{
|
||||||
BAN_NON_COPYABLE(PriorityMutex);
|
BAN_NON_COPYABLE(PriorityMutex);
|
||||||
BAN_NON_MOVABLE(PriorityMutex);
|
BAN_NON_MOVABLE(PriorityMutex);
|
||||||
@@ -98,15 +85,13 @@ namespace Kernel
|
|||||||
public:
|
public:
|
||||||
PriorityMutex() = default;
|
PriorityMutex() = default;
|
||||||
|
|
||||||
void lock() override
|
void lock()
|
||||||
{
|
{
|
||||||
const auto tid = Thread::current_tid();
|
const auto tid = Thread::current_tid();
|
||||||
|
|
||||||
if (tid == m_locker)
|
if (tid == m_locker)
|
||||||
ASSERT(m_lock_depth > 0);
|
ASSERT(m_lock_depth > 0);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ASSERT(!tid || !Thread::current().has_spinlock());
|
|
||||||
bool has_priority = tid ? !Thread::current().is_userspace() : true;
|
bool has_priority = tid ? !Thread::current().is_userspace() : true;
|
||||||
if (has_priority)
|
if (has_priority)
|
||||||
m_queue_length++;
|
m_queue_length++;
|
||||||
@@ -123,10 +108,9 @@ namespace Kernel
|
|||||||
m_lock_depth++;
|
m_lock_depth++;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool try_lock() override
|
bool try_lock()
|
||||||
{
|
{
|
||||||
const auto tid = Thread::current_tid();
|
const auto tid = Thread::current_tid();
|
||||||
|
|
||||||
if (tid == m_locker)
|
if (tid == m_locker)
|
||||||
ASSERT(m_lock_depth > 0);
|
ASSERT(m_lock_depth > 0);
|
||||||
else
|
else
|
||||||
@@ -145,7 +129,7 @@ namespace Kernel
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unlock() override
|
void unlock()
|
||||||
{
|
{
|
||||||
const auto tid = Thread::current_tid();
|
const auto tid = Thread::current_tid();
|
||||||
ASSERT(m_locker == tid);
|
ASSERT(m_locker == tid);
|
||||||
@@ -161,9 +145,9 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t locker() const override { return m_locker; }
|
pid_t locker() const { return m_locker; }
|
||||||
bool is_locked() const override { return m_locker != -1; }
|
bool is_locked() const { return m_locker != -1; }
|
||||||
uint32_t lock_depth() const override { return m_lock_depth; }
|
uint32_t lock_depth() const { return m_lock_depth; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BAN::Atomic<pid_t> m_locker { -1 };
|
BAN::Atomic<pid_t> m_locker { -1 };
|
||||||
|
|||||||
@@ -1,97 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <kernel/Lock/Mutex.h>
|
|
||||||
#include <kernel/Lock/LockGuard.h>
|
|
||||||
|
|
||||||
namespace Kernel
|
|
||||||
{
|
|
||||||
|
|
||||||
class RWLock
|
|
||||||
{
|
|
||||||
BAN_NON_COPYABLE(RWLock);
|
|
||||||
BAN_NON_MOVABLE(RWLock);
|
|
||||||
public:
|
|
||||||
RWLock() = default;
|
|
||||||
|
|
||||||
void rd_lock()
|
|
||||||
{
|
|
||||||
LockGuard _(m_mutex);
|
|
||||||
while (m_writers_waiting > 0 || m_writer_active)
|
|
||||||
m_thread_blocker.block_indefinite(&m_mutex);
|
|
||||||
m_readers_active++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void rd_unlock()
|
|
||||||
{
|
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (--m_readers_active == 0)
|
|
||||||
m_thread_blocker.unblock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void wr_lock()
|
|
||||||
{
|
|
||||||
LockGuard _(m_mutex);
|
|
||||||
m_writers_waiting++;
|
|
||||||
while (m_readers_active > 0 || m_writer_active)
|
|
||||||
m_thread_blocker.block_indefinite(&m_mutex);
|
|
||||||
m_writers_waiting--;
|
|
||||||
m_writer_active = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void wr_unlock()
|
|
||||||
{
|
|
||||||
LockGuard _(m_mutex);
|
|
||||||
m_writer_active = false;
|
|
||||||
m_thread_blocker.unblock();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Mutex m_mutex;
|
|
||||||
ThreadBlocker m_thread_blocker;
|
|
||||||
uint32_t m_readers_active { 0 };
|
|
||||||
uint32_t m_writers_waiting { 0 };
|
|
||||||
bool m_writer_active { false };
|
|
||||||
};
|
|
||||||
|
|
||||||
class RWLockRDGuard
|
|
||||||
{
|
|
||||||
BAN_NON_COPYABLE(RWLockRDGuard);
|
|
||||||
BAN_NON_MOVABLE(RWLockRDGuard);
|
|
||||||
public:
|
|
||||||
RWLockRDGuard(RWLock& lock)
|
|
||||||
: m_lock(lock)
|
|
||||||
{
|
|
||||||
m_lock.rd_lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
~RWLockRDGuard()
|
|
||||||
{
|
|
||||||
m_lock.rd_unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
RWLock& m_lock;
|
|
||||||
};
|
|
||||||
|
|
||||||
class RWLockWRGuard
|
|
||||||
{
|
|
||||||
BAN_NON_COPYABLE(RWLockWRGuard);
|
|
||||||
BAN_NON_MOVABLE(RWLockWRGuard);
|
|
||||||
public:
|
|
||||||
RWLockWRGuard(RWLock& lock)
|
|
||||||
: m_lock(lock)
|
|
||||||
{
|
|
||||||
m_lock.wr_lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
~RWLockWRGuard()
|
|
||||||
{
|
|
||||||
m_lock.wr_unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
RWLock& m_lock;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -18,13 +18,42 @@ namespace Kernel
|
|||||||
public:
|
public:
|
||||||
SpinLock() = default;
|
SpinLock() = default;
|
||||||
|
|
||||||
InterruptState lock();
|
InterruptState lock()
|
||||||
|
{
|
||||||
|
auto state = Processor::get_interrupt_state();
|
||||||
|
Processor::set_interrupt_state(InterruptState::Disabled);
|
||||||
|
|
||||||
bool try_lock_interrupts_disabled();
|
auto id = Processor::current_id().as_u32();
|
||||||
|
ASSERT(m_locker.load(BAN::MemoryOrder::memory_order_relaxed) != id);
|
||||||
|
|
||||||
void unlock(InterruptState state);
|
auto expected = PROCESSOR_NONE.as_u32();
|
||||||
|
while (!m_locker.compare_exchange(expected, id, BAN::MemoryOrder::memory_order_acquire))
|
||||||
|
{
|
||||||
|
Processor::pause();
|
||||||
|
expected = PROCESSOR_NONE.as_u32();
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t lock_depth() const { return current_processor_has_lock(); }
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool try_lock_interrupts_disabled()
|
||||||
|
{
|
||||||
|
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
|
||||||
|
|
||||||
|
auto id = Processor::current_id().as_u32();
|
||||||
|
ASSERT(m_locker.load(BAN::MemoryOrder::memory_order_relaxed) != id);
|
||||||
|
|
||||||
|
auto expected = PROCESSOR_NONE.as_u32();
|
||||||
|
return m_locker.compare_exchange(expected, id, BAN::MemoryOrder::memory_order_acquire);
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlock(InterruptState state)
|
||||||
|
{
|
||||||
|
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
|
||||||
|
ASSERT(current_processor_has_lock());
|
||||||
|
m_locker.store(PROCESSOR_NONE.as_u32(), BAN::MemoryOrder::memory_order_release);
|
||||||
|
Processor::set_interrupt_state(state);
|
||||||
|
}
|
||||||
|
|
||||||
bool current_processor_has_lock() const
|
bool current_processor_has_lock() const
|
||||||
{
|
{
|
||||||
@@ -43,13 +72,36 @@ namespace Kernel
|
|||||||
public:
|
public:
|
||||||
RecursiveSpinLock() = default;
|
RecursiveSpinLock() = default;
|
||||||
|
|
||||||
InterruptState lock();
|
InterruptState lock()
|
||||||
|
{
|
||||||
|
auto state = Processor::get_interrupt_state();
|
||||||
|
Processor::set_interrupt_state(InterruptState::Disabled);
|
||||||
|
|
||||||
bool try_lock_interrupts_disabled();
|
auto id = Processor::current_id().as_u32();
|
||||||
|
|
||||||
void unlock(InterruptState state);
|
ProcessorID::value_type expected = PROCESSOR_NONE.as_u32();
|
||||||
|
while (!m_locker.compare_exchange(expected, id, BAN::MemoryOrder::memory_order_acq_rel))
|
||||||
|
{
|
||||||
|
if (expected == id)
|
||||||
|
break;
|
||||||
|
Processor::pause();
|
||||||
|
expected = PROCESSOR_NONE.as_u32();
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t lock_depth() const { return m_lock_depth; }
|
m_lock_depth++;
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlock(InterruptState state)
|
||||||
|
{
|
||||||
|
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
|
||||||
|
ASSERT(current_processor_has_lock());
|
||||||
|
ASSERT(m_lock_depth > 0);
|
||||||
|
if (--m_lock_depth == 0)
|
||||||
|
m_locker.store(PROCESSOR_NONE.as_u32(), BAN::MemoryOrder::memory_order_release);
|
||||||
|
Processor::set_interrupt_state(state);
|
||||||
|
}
|
||||||
|
|
||||||
bool current_processor_has_lock() const
|
bool current_processor_has_lock() const
|
||||||
{
|
{
|
||||||
@@ -61,9 +113,6 @@ namespace Kernel
|
|||||||
uint32_t m_lock_depth { 0 };
|
uint32_t m_lock_depth { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Lock>
|
|
||||||
class SpinLockGuardAsMutex;
|
|
||||||
|
|
||||||
template<typename Lock>
|
template<typename Lock>
|
||||||
class SpinLockGuard
|
class SpinLockGuard
|
||||||
{
|
{
|
||||||
@@ -85,7 +134,6 @@ namespace Kernel
|
|||||||
private:
|
private:
|
||||||
Lock& m_lock;
|
Lock& m_lock;
|
||||||
InterruptState m_state;
|
InterruptState m_state;
|
||||||
friend class SpinLockGuardAsMutex<Lock>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <kernel/Lock/SpinLock.h>
|
|
||||||
#include <kernel/Lock/Mutex.h>
|
|
||||||
|
|
||||||
namespace Kernel
|
|
||||||
{
|
|
||||||
|
|
||||||
// FIXME: These classes are HACKS to allow passing spinlock
|
|
||||||
// to unblock functions. Write a better API that either
|
|
||||||
// allows passing spinlocks or do something cleaner that
|
|
||||||
// whatever shit this is
|
|
||||||
|
|
||||||
template<typename Lock>
|
|
||||||
class SpinLockAsMutex : public BaseMutex
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SpinLockAsMutex(Lock& lock, InterruptState state)
|
|
||||||
: m_lock(lock)
|
|
||||||
, m_lock_depth(lock.lock_depth())
|
|
||||||
, m_state(state)
|
|
||||||
, m_locker(Thread::current_tid())
|
|
||||||
{
|
|
||||||
ASSERT(m_lock.current_processor_has_lock());
|
|
||||||
}
|
|
||||||
|
|
||||||
void lock() override
|
|
||||||
{
|
|
||||||
m_lock.lock();
|
|
||||||
m_lock_depth++;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool try_lock() override
|
|
||||||
{
|
|
||||||
lock();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void unlock() override
|
|
||||||
{
|
|
||||||
m_lock.unlock(--m_lock_depth ? InterruptState::Disabled : m_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
pid_t locker() const override { return is_locked() ? m_locker : -1; }
|
|
||||||
bool is_locked() const override { return m_lock_depth; }
|
|
||||||
uint32_t lock_depth() const override { return m_lock_depth; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
SpinLock& m_lock;
|
|
||||||
uint32_t m_lock_depth { 0 };
|
|
||||||
InterruptState m_state;
|
|
||||||
const pid_t m_locker;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Lock>
|
|
||||||
class SpinLockGuardAsMutex : public SpinLockAsMutex<Lock>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SpinLockGuardAsMutex(SpinLockGuard<Lock>& guard)
|
|
||||||
: SpinLockAsMutex<Lock>(guard.m_lock, guard.m_state)
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <BAN/ByteSpan.h>
|
|
||||||
#include <BAN/UniqPtr.h>
|
|
||||||
#include <BAN/Vector.h>
|
|
||||||
|
|
||||||
#include <kernel/Memory/Types.h>
|
|
||||||
|
|
||||||
namespace Kernel
|
|
||||||
{
|
|
||||||
|
|
||||||
class ByteRingBuffer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<ByteRingBuffer>> create(size_t size);
|
|
||||||
~ByteRingBuffer();
|
|
||||||
|
|
||||||
void push(BAN::ConstByteSpan data)
|
|
||||||
{
|
|
||||||
ASSERT(data.size() + m_size <= m_capacity);
|
|
||||||
uint8_t* buffer_head = reinterpret_cast<uint8_t*>(m_vaddr) + (m_tail + m_size) % m_capacity;
|
|
||||||
memcpy(buffer_head, data.data(), data.size());
|
|
||||||
m_size += data.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pop(size_t size)
|
|
||||||
{
|
|
||||||
ASSERT(size <= m_size);
|
|
||||||
m_tail = (m_tail + size) % m_capacity;
|
|
||||||
m_size -= size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pop_back(size_t size)
|
|
||||||
{
|
|
||||||
ASSERT(size <= m_size);
|
|
||||||
m_size -= size;
|
|
||||||
}
|
|
||||||
|
|
||||||
BAN::ConstByteSpan get_data() const
|
|
||||||
{
|
|
||||||
const uint8_t* base = reinterpret_cast<const uint8_t*>(m_vaddr);
|
|
||||||
return { base + m_tail, m_size };
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t front() const
|
|
||||||
{
|
|
||||||
ASSERT(!empty());
|
|
||||||
return reinterpret_cast<const uint8_t*>(m_vaddr)[m_tail];
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t back() const
|
|
||||||
{
|
|
||||||
ASSERT(!empty());
|
|
||||||
return reinterpret_cast<const uint8_t*>(m_vaddr)[m_tail + m_size];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool empty() const { return m_size == 0; }
|
|
||||||
bool full() const { return m_size == m_capacity; }
|
|
||||||
size_t free() const { return m_capacity - m_size; }
|
|
||||||
size_t size() const { return m_size; }
|
|
||||||
size_t capacity() const { return m_capacity; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
ByteRingBuffer(size_t capacity)
|
|
||||||
: m_capacity(capacity)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
private:
|
|
||||||
size_t m_size { 0 };
|
|
||||||
size_t m_tail { 0 };
|
|
||||||
const size_t m_capacity;
|
|
||||||
|
|
||||||
vaddr_t m_vaddr { 0 };
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -27,19 +27,18 @@ namespace Kernel
|
|||||||
BAN_NON_MOVABLE(FileBackedRegion);
|
BAN_NON_MOVABLE(FileBackedRegion);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<FileBackedRegion>> create(BAN::RefPtr<Inode>, PageTable&, off_t offset, size_t size, AddressRange address_range, Type, PageTable::flags_t, int status_flags);
|
static BAN::ErrorOr<BAN::UniqPtr<FileBackedRegion>> create(BAN::RefPtr<Inode>, PageTable&, off_t offset, size_t size, AddressRange address_range, Type, PageTable::flags_t);
|
||||||
~FileBackedRegion();
|
~FileBackedRegion();
|
||||||
|
|
||||||
BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override;
|
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override;
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> split(size_t offset) override;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FileBackedRegion(BAN::RefPtr<Inode>, PageTable&, off_t offset, ssize_t size, Type type, PageTable::flags_t flags, int status_flags);
|
FileBackedRegion(BAN::RefPtr<Inode>, PageTable&, off_t offset, ssize_t size, Type flags, PageTable::flags_t page_flags);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BAN::RefPtr<Inode> m_inode;
|
BAN::RefPtr<Inode> m_inode;
|
||||||
|
|||||||
@@ -11,23 +11,22 @@ namespace Kernel
|
|||||||
BAN_NON_MOVABLE(MemoryBackedRegion);
|
BAN_NON_MOVABLE(MemoryBackedRegion);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<MemoryBackedRegion>> create(PageTable&, size_t size, AddressRange, Type, PageTable::flags_t, int status_flags);
|
static BAN::ErrorOr<BAN::UniqPtr<MemoryBackedRegion>> create(PageTable&, size_t size, AddressRange, Type, PageTable::flags_t);
|
||||||
~MemoryBackedRegion();
|
~MemoryBackedRegion();
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> split(size_t offset) override;
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
|
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
|
||||||
|
|
||||||
// Copy data from buffer into this region
|
// Copy data from buffer into this region
|
||||||
// This can fail if no memory is mapped and no free memory was available
|
// This can fail if no memory is mapped and no free memory was available
|
||||||
BAN::ErrorOr<void> copy_data_to_region(size_t offset_into_region, const uint8_t* buffer, size_t buffer_size);
|
BAN::ErrorOr<void> copy_data_to_region(size_t offset_into_region, const uint8_t* buffer, size_t buffer_size);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MemoryBackedRegion(PageTable&, size_t size, Type, PageTable::flags_t, int status_flags);
|
MemoryBackedRegion(PageTable&, size_t size, Type, PageTable::flags_t);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <BAN/UniqPtr.h>
|
#include <BAN/UniqPtr.h>
|
||||||
#include <kernel/Lock/Mutex.h>
|
|
||||||
#include <kernel/Memory/PageTable.h>
|
#include <kernel/Memory/PageTable.h>
|
||||||
#include <kernel/Memory/Types.h>
|
#include <kernel/Memory/Types.h>
|
||||||
#include <kernel/ThreadBlocker.h>
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
@@ -33,25 +33,15 @@ namespace Kernel
|
|||||||
bool contains(vaddr_t address) const;
|
bool contains(vaddr_t address) const;
|
||||||
bool contains_fully(vaddr_t address, size_t size) const;
|
bool contains_fully(vaddr_t address, size_t size) const;
|
||||||
bool overlaps(vaddr_t address, size_t size) const;
|
bool overlaps(vaddr_t address, size_t size) const;
|
||||||
bool is_contained_by(vaddr_t address, size_t size) const;
|
|
||||||
|
|
||||||
bool writable() const { return m_flags & PageTable::Flags::ReadWrite; }
|
bool writable() const { return m_flags & PageTable::Flags::ReadWrite; }
|
||||||
|
|
||||||
size_t size() const { return m_size; }
|
size_t size() const { return m_size; }
|
||||||
vaddr_t vaddr() const { return m_vaddr; }
|
vaddr_t vaddr() const { return m_vaddr; }
|
||||||
|
|
||||||
int status_flags() const { return m_status_flags; }
|
|
||||||
Type type() const { return m_type; }
|
|
||||||
PageTable::flags_t flags() const { return m_flags; }
|
|
||||||
|
|
||||||
size_t virtual_page_count() const { return BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE); }
|
size_t virtual_page_count() const { return BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE); }
|
||||||
size_t physical_page_count() const { return m_physical_page_count; }
|
size_t physical_page_count() const { return m_physical_page_count; }
|
||||||
|
|
||||||
void pin();
|
|
||||||
void unpin();
|
|
||||||
void wait_not_pinned();
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> mprotect(PageTable::flags_t);
|
|
||||||
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) = 0;
|
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) = 0;
|
||||||
|
|
||||||
// Returns error if no memory was available
|
// Returns error if no memory was available
|
||||||
@@ -60,26 +50,20 @@ namespace Kernel
|
|||||||
BAN::ErrorOr<bool> allocate_page_containing(vaddr_t address, bool wants_write);
|
BAN::ErrorOr<bool> allocate_page_containing(vaddr_t address, bool wants_write);
|
||||||
|
|
||||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) = 0;
|
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) = 0;
|
||||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> split(size_t offset) = 0;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MemoryRegion(PageTable&, size_t size, Type type, PageTable::flags_t flags, int status_flags);
|
MemoryRegion(PageTable&, size_t size, Type type, PageTable::flags_t flags);
|
||||||
BAN::ErrorOr<void> initialize(AddressRange);
|
BAN::ErrorOr<void> initialize(AddressRange);
|
||||||
|
|
||||||
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t address, bool wants_write) = 0;
|
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t address, bool wants_write) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PageTable& m_page_table;
|
PageTable& m_page_table;
|
||||||
size_t m_size { 0 };
|
const size_t m_size;
|
||||||
const Type m_type;
|
const Type m_type;
|
||||||
PageTable::flags_t m_flags;
|
const PageTable::flags_t m_flags;
|
||||||
const int m_status_flags;
|
|
||||||
vaddr_t m_vaddr { 0 };
|
vaddr_t m_vaddr { 0 };
|
||||||
size_t m_physical_page_count { 0 };
|
size_t m_physical_page_count { 0 };
|
||||||
|
|
||||||
Mutex m_pinned_mutex;
|
|
||||||
BAN::Atomic<size_t> m_pinned_count { 0 };
|
|
||||||
ThreadBlocker m_pinned_blocker;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ namespace Kernel
|
|||||||
bool is_page_free(vaddr_t) const;
|
bool is_page_free(vaddr_t) const;
|
||||||
bool is_range_free(vaddr_t, size_t bytes) const;
|
bool is_range_free(vaddr_t, size_t bytes) const;
|
||||||
|
|
||||||
bool reserve_page(vaddr_t, bool only_free = true, bool send_smp_message = true);
|
bool reserve_page(vaddr_t, bool only_free = true);
|
||||||
bool reserve_range(vaddr_t, size_t bytes, bool only_free = true);
|
bool reserve_range(vaddr_t, size_t bytes, bool only_free = true);
|
||||||
|
|
||||||
vaddr_t reserve_free_page(vaddr_t first_address, vaddr_t last_address = UINTPTR_MAX);
|
vaddr_t reserve_free_page(vaddr_t first_address, vaddr_t last_address = UINTPTR_MAX);
|
||||||
@@ -133,7 +133,7 @@ namespace Kernel
|
|||||||
void map_kernel_memory();
|
void map_kernel_memory();
|
||||||
void prepare_fast_page();
|
void prepare_fast_page();
|
||||||
|
|
||||||
void invalidate(vaddr_t, bool send_smp_message);
|
static void invalidate(vaddr_t, bool send_smp_message);
|
||||||
|
|
||||||
static void map_fast_page(paddr_t);
|
static void map_fast_page(paddr_t);
|
||||||
static void unmap_fast_page();
|
static void unmap_fast_page();
|
||||||
|
|||||||
@@ -6,8 +6,6 @@
|
|||||||
#include <kernel/Lock/SpinLock.h>
|
#include <kernel/Lock/SpinLock.h>
|
||||||
#include <kernel/Memory/MemoryRegion.h>
|
#include <kernel/Memory/MemoryRegion.h>
|
||||||
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -57,17 +55,15 @@ namespace Kernel
|
|||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<SharedMemoryObject>> create(BAN::RefPtr<SharedMemoryObjectManager::Object>, PageTable&, AddressRange);
|
static BAN::ErrorOr<BAN::UniqPtr<SharedMemoryObject>> create(BAN::RefPtr<SharedMemoryObjectManager::Object>, PageTable&, AddressRange);
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> split(size_t offset) override;
|
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
|
||||||
|
|
||||||
BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SharedMemoryObject(BAN::RefPtr<SharedMemoryObjectManager::Object> object, PageTable& page_table)
|
SharedMemoryObject(BAN::RefPtr<SharedMemoryObjectManager::Object> object, PageTable& page_table)
|
||||||
: MemoryRegion(page_table, object->size, MemoryRegion::Type::SHARED, object->flags, O_EXEC | O_RDWR)
|
: MemoryRegion(page_table, object->size, MemoryRegion::Type::SHARED, object->flags)
|
||||||
, m_object(object)
|
, m_object(object)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#if ARCH(x86_64)
|
#if ARCH(x86_64)
|
||||||
#define KERNEL_OFFSET 0xFFFFFFFF80000000
|
#define KERNEL_OFFSET 0xFFFFFFFF80000000
|
||||||
#define USERSPACE_END 0x800000000000
|
#define USERSPACE_END 0xFFFF800000000000
|
||||||
#elif ARCH(i686)
|
#elif ARCH(i686)
|
||||||
#define KERNEL_OFFSET 0xC0000000
|
#define KERNEL_OFFSET 0xC0000000
|
||||||
#define USERSPACE_END 0xC0000000
|
#define USERSPACE_END 0xC0000000
|
||||||
@@ -12,7 +12,6 @@
|
|||||||
#error
|
#error
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#undef PAGE_SIZE
|
|
||||||
#define PAGE_SIZE ((uintptr_t)4096)
|
#define PAGE_SIZE ((uintptr_t)4096)
|
||||||
#define PAGE_SIZE_SHIFT 12
|
#define PAGE_SIZE_SHIFT 12
|
||||||
#define PAGE_ADDR_MASK (~(uintptr_t)0xFFF)
|
#define PAGE_ADDR_MASK (~(uintptr_t)0xFFF)
|
||||||
|
|||||||
@@ -15,21 +15,21 @@ namespace Kernel
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// Create virtual range to fixed virtual address
|
// Create virtual range to fixed virtual address
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<VirtualRange>> create_to_vaddr(PageTable&, vaddr_t, size_t, PageTable::flags_t flags, bool preallocate_pages, bool add_guard_pages);
|
static BAN::ErrorOr<BAN::UniqPtr<VirtualRange>> create_to_vaddr(PageTable&, vaddr_t, size_t, PageTable::flags_t flags, bool preallocate_pages);
|
||||||
// Create virtual range to virtual address range
|
// Create virtual range to virtual address range
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<VirtualRange>> create_to_vaddr_range(PageTable&, vaddr_t vaddr_start, vaddr_t vaddr_end, size_t, PageTable::flags_t flags, bool preallocate_pages, bool add_guard_pages);
|
static BAN::ErrorOr<BAN::UniqPtr<VirtualRange>> create_to_vaddr_range(PageTable&, vaddr_t vaddr_start, vaddr_t vaddr_end, size_t, PageTable::flags_t flags, bool preallocate_pages);
|
||||||
~VirtualRange();
|
~VirtualRange();
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::UniqPtr<VirtualRange>> clone(PageTable&);
|
BAN::ErrorOr<BAN::UniqPtr<VirtualRange>> clone(PageTable&);
|
||||||
|
|
||||||
vaddr_t vaddr() const { return m_vaddr + (m_has_guard_pages ? PAGE_SIZE : 0); }
|
vaddr_t vaddr() const { return m_vaddr; }
|
||||||
size_t size() const { return m_size - (m_has_guard_pages ? 2 * PAGE_SIZE : 0); }
|
size_t size() const { return m_size; }
|
||||||
PageTable::flags_t flags() const { return m_flags; }
|
PageTable::flags_t flags() const { return m_flags; }
|
||||||
|
|
||||||
paddr_t paddr_of(vaddr_t vaddr) const
|
paddr_t paddr_of(vaddr_t vaddr) const
|
||||||
{
|
{
|
||||||
ASSERT(vaddr % PAGE_SIZE == 0);
|
ASSERT(vaddr % PAGE_SIZE == 0);
|
||||||
const size_t index = (vaddr - this->vaddr()) / PAGE_SIZE;
|
const size_t index = (vaddr - m_vaddr) / PAGE_SIZE;
|
||||||
ASSERT(index < m_paddrs.size());
|
ASSERT(index < m_paddrs.size());
|
||||||
const paddr_t paddr = m_paddrs[index];
|
const paddr_t paddr = m_paddrs[index];
|
||||||
ASSERT(paddr);
|
ASSERT(paddr);
|
||||||
@@ -38,16 +38,15 @@ namespace Kernel
|
|||||||
|
|
||||||
bool contains(vaddr_t address) const { return vaddr() <= address && address < vaddr() + size(); }
|
bool contains(vaddr_t address) const { return vaddr() <= address && address < vaddr() + size(); }
|
||||||
|
|
||||||
BAN::ErrorOr<bool> allocate_page_for_demand_paging(vaddr_t address);
|
BAN::ErrorOr<void> allocate_page_for_demand_paging(vaddr_t address);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VirtualRange(PageTable&, bool preallocated, bool has_guard_pages, vaddr_t, size_t, PageTable::flags_t);
|
VirtualRange(PageTable&, bool preallocated, vaddr_t, size_t, PageTable::flags_t);
|
||||||
BAN::ErrorOr<void> initialize();
|
BAN::ErrorOr<void> initialize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PageTable& m_page_table;
|
PageTable& m_page_table;
|
||||||
const bool m_preallocated;
|
const bool m_preallocated;
|
||||||
const bool m_has_guard_pages;
|
|
||||||
const vaddr_t m_vaddr;
|
const vaddr_t m_vaddr;
|
||||||
const size_t m_size;
|
const size_t m_size;
|
||||||
const PageTable::flags_t m_flags;
|
const PageTable::flags_t m_flags;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user