Compare commits
2 Commits
main
...
c50dba900d
| Author | SHA1 | Date | |
|---|---|---|---|
| c50dba900d | |||
| 502bb4f84a |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,4 +3,3 @@
|
|||||||
build/
|
build/
|
||||||
base/
|
base/
|
||||||
script/fakeroot-context
|
script/fakeroot-context
|
||||||
tools/update-image-perms
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ namespace BAN
|
|||||||
constexpr T& front();
|
constexpr 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;
|
||||||
|
|
||||||
|
|||||||
@@ -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,"\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\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\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;
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#define _ban_count_args_impl(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, ...) _9
|
|
||||||
#define _ban_count_args(...) _ban_count_args_impl(__VA_ARGS__ __VA_OPT__(,) 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
|
||||||
|
|
||||||
#define _ban_concat_impl(a, b) a##b
|
|
||||||
#define _ban_concat(a, b) _ban_concat_impl(a, b)
|
|
||||||
|
|
||||||
#define _ban_stringify_impl(x) #x
|
|
||||||
#define _ban_stringify(x) _ban_stringify_impl(x)
|
|
||||||
|
|
||||||
#define _ban_fe_0(f)
|
|
||||||
#define _ban_fe_1(f, _0) f(0, _0)
|
|
||||||
#define _ban_fe_2(f, _0, _1) f(0, _0) f(1, _1)
|
|
||||||
#define _ban_fe_3(f, _0, _1, _2) f(0, _0) f(1, _1) f(2, _2)
|
|
||||||
#define _ban_fe_4(f, _0, _1, _2, _3) f(0, _0) f(1, _1) f(2, _2) f(3, _3)
|
|
||||||
#define _ban_fe_5(f, _0, _1, _2, _3, _4) f(0, _0) f(1, _1) f(2, _2) f(3, _3) f(4, _4)
|
|
||||||
#define _ban_fe_6(f, _0, _1, _2, _3, _4, _5) f(0, _0) f(1, _1) f(2, _2) f(3, _3) f(4, _4) f(5, _5)
|
|
||||||
#define _ban_fe_7(f, _0, _1, _2, _3, _4, _5, _6) f(0, _0) f(1, _1) f(2, _2) f(3, _3) f(4, _4) f(5, _5) f(6, _6)
|
|
||||||
#define _ban_fe_8(f, _0, _1, _2, _3, _4, _5, _6, _7) f(0, _0) f(1, _1) f(2, _2) f(3, _3) f(4, _4) f(5, _5) f(6, _6) f(7, _7)
|
|
||||||
#define _ban_fe_9(f, _0, _1, _2, _3, _4, _5, _6, _7, _8) f(0, _0) f(1, _1) f(2, _2) f(3, _3) f(4, _4) f(5, _5) f(6, _6) f(7, _7) f(8, _8)
|
|
||||||
#define _ban_for_each(f, ...) _ban_concat(_ban_fe_, _ban_count_args(__VA_ARGS__))(f __VA_OPT__(,) __VA_ARGS__)
|
|
||||||
|
|
||||||
#define _ban_fe_comma_0(f)
|
|
||||||
#define _ban_fe_comma_1(f, _0) f(0, _0)
|
|
||||||
#define _ban_fe_comma_2(f, _0, _1) f(0, _0), f(1, _1)
|
|
||||||
#define _ban_fe_comma_3(f, _0, _1, _2) f(0, _0), f(1, _1), f(2, _2)
|
|
||||||
#define _ban_fe_comma_4(f, _0, _1, _2, _3) f(0, _0), f(1, _1), f(2, _2), f(3, _3)
|
|
||||||
#define _ban_fe_comma_5(f, _0, _1, _2, _3, _4) f(0, _0), f(1, _1), f(2, _2), f(3, _3), f(4, _4)
|
|
||||||
#define _ban_fe_comma_6(f, _0, _1, _2, _3, _4, _5) f(0, _0), f(1, _1), f(2, _2), f(3, _3), f(4, _4), f(5, _5)
|
|
||||||
#define _ban_fe_comma_7(f, _0, _1, _2, _3, _4, _5, _6) f(0, _0), f(1, _1), f(2, _2), f(3, _3), f(4, _4), f(5, _5), f(6, _6)
|
|
||||||
#define _ban_fe_comma_8(f, _0, _1, _2, _3, _4, _5, _6, _7) f(0, _0), f(1, _1), f(2, _2), f(3, _3), f(4, _4), f(5, _5), f(6, _6), f(7, _7)
|
|
||||||
#define _ban_fe_comma_9(f, _0, _1, _2, _3, _4, _5, _6, _7, _8) f(0, _0), f(1, _1), f(2, _2), f(3, _3), f(4, _4), f(5, _5), f(6, _6), f(7, _7), f(8, _8)
|
|
||||||
#define _ban_for_each_comma(f, ...) _ban_concat(_ban_fe_comma_, _ban_count_args(__VA_ARGS__))(f __VA_OPT__(,) __VA_ARGS__)
|
|
||||||
|
|
||||||
#define _ban_get_0(a0, ...) a0
|
|
||||||
#define _ban_get_1(a0, a1, ...) a1
|
|
||||||
#define _ban_get_2(a0, a1, a2, ...) a2
|
|
||||||
#define _ban_get_3(a0, a1, a2, a3, ...) a3
|
|
||||||
#define _ban_get_4(a0, a1, a2, a3, a4, ...) a4
|
|
||||||
#define _ban_get_5(a0, a1, a2, a3, a4, a5, ...) a5
|
|
||||||
#define _ban_get_6(a0, a1, a2, a3, a4, a5, a6, ...) a6
|
|
||||||
#define _ban_get_7(a0, a1, a2, a3, a4, a5, a6, a7, ...) a7
|
|
||||||
#define _ban_get_8(a0, a1, a2, a3, a4, a5, a6, a7, a8, ...) a8
|
|
||||||
#define _ban_get_9(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, ...) a9
|
|
||||||
#define _ban_get(n, ...) _ban_concat(_ban_get_, n)(__VA_ARGS__)
|
|
||||||
@@ -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>
|
||||||
@@ -324,28 +309,17 @@ 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>)
|
|
||||||
{
|
|
||||||
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));
|
asm("fsqrt" : "+t"(x));
|
||||||
return 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:
|
||||||
@@ -247,12 +246,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; } };
|
||||||
|
|||||||
@@ -126,7 +126,6 @@ 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();
|
||||||
}
|
}
|
||||||
@@ -134,7 +133,6 @@ namespace BAN
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,12 +157,11 @@ 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;
|
||||||
}
|
}
|
||||||
@@ -174,12 +171,11 @@ 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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,35 +381,10 @@ 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 constexpr (BAN::is_trivially_copyable_v<T>)
|
|
||||||
{
|
|
||||||
if constexpr (BAN::reallocator)
|
|
||||||
{
|
|
||||||
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
|
|
||||||
{
|
|
||||||
auto* new_data = static_cast<T*>(BAN::allocator(new_cap * sizeof(T)));
|
|
||||||
if (new_data == nullptr)
|
if (new_data == nullptr)
|
||||||
return Error::from_errno(ENOMEM);
|
return Error::from_errno(ENOMEM);
|
||||||
for (size_type i = 0; i < m_size; i++)
|
for (size_type i = 0; i < m_size; i++)
|
||||||
@@ -419,8 +394,6 @@ namespace BAN
|
|||||||
}
|
}
|
||||||
BAN::deallocator(m_data);
|
BAN::deallocator(m_data);
|
||||||
m_data = new_data;
|
m_data = new_data;
|
||||||
}
|
|
||||||
|
|
||||||
m_capacity = new_cap;
|
m_capacity = new_cap;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -5,12 +5,9 @@ set(KERNEL_SOURCES
|
|||||||
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/BatterySystem.cpp
|
||||||
kernel/ACPI/EmbeddedController.cpp
|
|
||||||
kernel/APIC.cpp
|
kernel/APIC.cpp
|
||||||
kernel/Audio/AC97/Controller.cpp
|
kernel/Audio/AC97/Controller.cpp
|
||||||
kernel/Audio/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
|
||||||
@@ -25,7 +22,6 @@ set(KERNEL_SOURCES
|
|||||||
kernel/Epoll.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
|
||||||
@@ -51,7 +47,6 @@ set(KERNEL_SOURCES
|
|||||||
kernel/InterruptController.cpp
|
kernel/InterruptController.cpp
|
||||||
kernel/kernel.cpp
|
kernel/kernel.cpp
|
||||||
kernel/Lock/SpinLock.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
|
||||||
@@ -112,7 +107,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 +133,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 +143,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}")
|
||||||
@@ -168,13 +158,10 @@ set(BAN_SOURCES
|
|||||||
set(KLIBC_SOURCES
|
set(KLIBC_SOURCES
|
||||||
klibc/ctype.cpp
|
klibc/ctype.cpp
|
||||||
klibc/string.cpp
|
klibc/string.cpp
|
||||||
klibc/arch/${BANAN_ARCH}/string.S
|
|
||||||
)
|
|
||||||
|
|
||||||
set(LIBDEFLATE_SOURCE
|
# Ehhh don't do this but for now libc uses the same stuff kernel can use
|
||||||
../userspace/libraries/LibDEFLATE/Compressor.cpp
|
# This won't work after libc starts using sse implemetations tho
|
||||||
../userspace/libraries/LibDEFLATE/Decompressor.cpp
|
../userspace/libraries/LibC/arch/${BANAN_ARCH}/string.S
|
||||||
../userspace/libraries/LibDEFLATE/HuffmanTree.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LIBFONT_SOURCES
|
set(LIBFONT_SOURCES
|
||||||
@@ -187,25 +174,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
|
||||||
@@ -259,11 +239,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)
|
||||||
|
|||||||
@@ -21,11 +21,6 @@ namespace Kernel
|
|||||||
|
|
||||||
SpinLock PageTable::s_fast_page_lock;
|
SpinLock PageTable::s_fast_page_lock;
|
||||||
|
|
||||||
constexpr uint64_t s_page_flag_mask = 0x8000000000000FFF;
|
|
||||||
constexpr uint64_t s_page_addr_mask = ~s_page_flag_mask;
|
|
||||||
|
|
||||||
static bool s_is_post_heap_done = false;
|
|
||||||
|
|
||||||
static PageTable* s_kernel = nullptr;
|
static PageTable* s_kernel = nullptr;
|
||||||
static bool s_has_nxe = false;
|
static bool s_has_nxe = false;
|
||||||
static bool s_has_pge = false;
|
static bool s_has_pge = false;
|
||||||
@@ -72,7 +67,7 @@ namespace Kernel
|
|||||||
|
|
||||||
void PageTable::initialize_post_heap()
|
void PageTable::initialize_post_heap()
|
||||||
{
|
{
|
||||||
s_is_post_heap_done = true;
|
// NOTE: this is no-op as our 32 bit target does not use hhdm
|
||||||
}
|
}
|
||||||
|
|
||||||
void PageTable::initial_load()
|
void PageTable::initial_load()
|
||||||
@@ -146,9 +141,9 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static uint64_t* P2V(const T paddr)
|
static vaddr_t P2V(const T paddr)
|
||||||
{
|
{
|
||||||
return reinterpret_cast<uint64_t*>(reinterpret_cast<paddr_t>(paddr) - g_boot_info.kernel_paddr + KERNEL_OFFSET);
|
return (paddr_t)paddr - g_boot_info.kernel_paddr + KERNEL_OFFSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PageTable::initialize_kernel()
|
void PageTable::initialize_kernel()
|
||||||
@@ -198,18 +193,13 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
constexpr uint64_t pdpte = (fast_page() >> 30) & 0x1FF;
|
constexpr uint64_t pdpte = (fast_page() >> 30) & 0x1FF;
|
||||||
constexpr uint64_t pde = (fast_page() >> 21) & 0x1FF;
|
constexpr uint64_t pde = (fast_page() >> 21) & 0x1FF;
|
||||||
constexpr uint64_t pte = (fast_page() >> 12) & 0x1FF;
|
|
||||||
|
|
||||||
const uint64_t* pdpt = P2V(m_highest_paging_struct);
|
uint64_t* pdpt = reinterpret_cast<uint64_t*>(P2V(m_highest_paging_struct));
|
||||||
ASSERT(pdpt[pdpte] & Flags::Present);
|
ASSERT(pdpt[pdpte] & Flags::Present);
|
||||||
|
|
||||||
uint64_t* pd = P2V(pdpt[pdpte] & s_page_addr_mask);
|
uint64_t* pd = reinterpret_cast<uint64_t*>(P2V(pdpt[pdpte]) & PAGE_ADDR_MASK);
|
||||||
ASSERT(!(pd[pde] & Flags::Present));
|
ASSERT(!(pd[pde] & Flags::Present));
|
||||||
pd[pde] = V2P(allocate_zeroed_page_aligned_page()) | Flags::ReadWrite | Flags::Present;
|
pd[pde] = V2P(allocate_zeroed_page_aligned_page()) | Flags::ReadWrite | Flags::Present;
|
||||||
|
|
||||||
uint64_t* pt = P2V(pd[pde] & s_page_addr_mask);
|
|
||||||
ASSERT(pt[pte] == 0);
|
|
||||||
pt[pte] = Flags::Reserved;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PageTable::map_fast_page(paddr_t paddr)
|
void PageTable::map_fast_page(paddr_t paddr)
|
||||||
@@ -224,14 +214,14 @@ namespace Kernel
|
|||||||
constexpr uint64_t pde = (fast_page() >> 21) & 0x1FF;
|
constexpr uint64_t pde = (fast_page() >> 21) & 0x1FF;
|
||||||
constexpr uint64_t pte = (fast_page() >> 12) & 0x1FF;
|
constexpr uint64_t pte = (fast_page() >> 12) & 0x1FF;
|
||||||
|
|
||||||
uint64_t* pdpt = P2V(s_kernel->m_highest_paging_struct);
|
uint64_t* pdpt = reinterpret_cast<uint64_t*>(P2V(s_kernel->m_highest_paging_struct));
|
||||||
uint64_t* pd = P2V(pdpt[pdpte] & s_page_addr_mask);
|
uint64_t* pd = reinterpret_cast<uint64_t*>(P2V(pdpt[pdpte] & PAGE_ADDR_MASK));
|
||||||
uint64_t* pt = P2V(pd[pde] & s_page_addr_mask);
|
uint64_t* pt = reinterpret_cast<uint64_t*>(P2V(pd[pde] & PAGE_ADDR_MASK));
|
||||||
|
|
||||||
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()
|
||||||
@@ -244,14 +234,14 @@ namespace Kernel
|
|||||||
constexpr uint64_t pde = (fast_page() >> 21) & 0x1FF;
|
constexpr uint64_t pde = (fast_page() >> 21) & 0x1FF;
|
||||||
constexpr uint64_t pte = (fast_page() >> 12) & 0x1FF;
|
constexpr uint64_t pte = (fast_page() >> 12) & 0x1FF;
|
||||||
|
|
||||||
uint64_t* pdpt = P2V(s_kernel->m_highest_paging_struct);
|
uint64_t* pdpt = reinterpret_cast<uint64_t*>(P2V(s_kernel->m_highest_paging_struct));
|
||||||
uint64_t* pd = P2V(pdpt[pdpte] & s_page_addr_mask);
|
uint64_t* pd = reinterpret_cast<uint64_t*>(P2V(pdpt[pdpte] & PAGE_ADDR_MASK));
|
||||||
uint64_t* pt = P2V(pd[pde] & s_page_addr_mask);
|
uint64_t* pt = reinterpret_cast<uint64_t*>(P2V(pd[pde] & PAGE_ADDR_MASK));
|
||||||
|
|
||||||
ASSERT(pt[pte] & Flags::Present);
|
ASSERT(pt[pte] & Flags::Present);
|
||||||
pt[pte] = Flags::Reserved;
|
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()
|
||||||
@@ -273,7 +263,7 @@ namespace Kernel
|
|||||||
m_highest_paging_struct = V2P(kmalloc(32, 32, true));
|
m_highest_paging_struct = V2P(kmalloc(32, 32, true));
|
||||||
ASSERT(m_highest_paging_struct);
|
ASSERT(m_highest_paging_struct);
|
||||||
|
|
||||||
uint64_t* pdpt = P2V(m_highest_paging_struct);
|
uint64_t* pdpt = reinterpret_cast<uint64_t*>(P2V(m_highest_paging_struct));
|
||||||
pdpt[0] = 0;
|
pdpt[0] = 0;
|
||||||
pdpt[1] = 0;
|
pdpt[1] = 0;
|
||||||
pdpt[2] = 0;
|
pdpt[2] = 0;
|
||||||
@@ -286,17 +276,18 @@ namespace Kernel
|
|||||||
if (m_highest_paging_struct == 0)
|
if (m_highest_paging_struct == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint64_t* pdpt = P2V(m_highest_paging_struct);
|
uint64_t* pdpt = reinterpret_cast<uint64_t*>(P2V(m_highest_paging_struct));
|
||||||
|
|
||||||
for (uint32_t pdpte = 0; pdpte < 3; pdpte++)
|
for (uint32_t pdpte = 0; pdpte < 3; pdpte++)
|
||||||
{
|
{
|
||||||
if (!(pdpt[pdpte] & Flags::Present))
|
if (!(pdpt[pdpte] & Flags::Present))
|
||||||
continue;
|
continue;
|
||||||
uint64_t* pd = P2V(pdpt[pdpte] & s_page_addr_mask);
|
uint64_t* pd = reinterpret_cast<uint64_t*>(P2V(pdpt[pdpte] & PAGE_ADDR_MASK));
|
||||||
for (uint32_t pde = 0; pde < 512; pde++)
|
for (uint32_t pde = 0; pde < 512; pde++)
|
||||||
{
|
{
|
||||||
if (!(pd[pde] & Flags::Present))
|
if (!(pd[pde] & Flags::Present))
|
||||||
continue;
|
continue;
|
||||||
kfree(P2V(pd[pde] & s_page_addr_mask));
|
kfree(reinterpret_cast<uint64_t*>(P2V(pd[pde] & PAGE_ADDR_MASK)));
|
||||||
}
|
}
|
||||||
kfree(pd);
|
kfree(pd);
|
||||||
}
|
}
|
||||||
@@ -307,43 +298,15 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
SpinLockGuard _(m_lock);
|
SpinLockGuard _(m_lock);
|
||||||
ASSERT(m_highest_paging_struct < 0x100000000);
|
ASSERT(m_highest_paging_struct < 0x100000000);
|
||||||
asm volatile("movl %0, %%cr3" :: "r"(static_cast<uint32_t>(m_highest_paging_struct)));
|
const uint32_t pdpt_lo = m_highest_paging_struct;
|
||||||
|
asm volatile("movl %0, %%cr3" :: "r"(pdpt_lo));
|
||||||
Processor::set_current_page_table(this);
|
Processor::set_current_page_table(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PageTable::invalidate_range(vaddr_t vaddr, size_t pages, bool send_smp_message)
|
void PageTable::invalidate(vaddr_t vaddr, bool send_smp_message)
|
||||||
{
|
{
|
||||||
ASSERT(vaddr % PAGE_SIZE == 0);
|
ASSERT(vaddr % PAGE_SIZE == 0);
|
||||||
|
asm volatile("invlpg (%0)" :: "r"(vaddr) : "memory");
|
||||||
const bool is_userspace = (vaddr < KERNEL_OFFSET);
|
|
||||||
if (is_userspace && this != &PageTable::current())
|
|
||||||
;
|
|
||||||
else if (pages <= 32 || !s_is_post_heap_done)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < pages; i++, vaddr += PAGE_SIZE)
|
|
||||||
asm volatile("invlpg (%0)" :: "r"(vaddr));
|
|
||||||
}
|
|
||||||
else if (is_userspace || !s_has_pge)
|
|
||||||
{
|
|
||||||
asm volatile("movl %0, %%cr3" :: "r"(static_cast<uint32_t>(m_highest_paging_struct)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
asm volatile(
|
|
||||||
"movl %%cr4, %%eax;"
|
|
||||||
|
|
||||||
"andl $~0x80, %%eax;"
|
|
||||||
"movl %%eax, %%cr4;"
|
|
||||||
|
|
||||||
"movl %0, %%cr3;"
|
|
||||||
|
|
||||||
"orl $0x80, %%eax;"
|
|
||||||
"movl %%eax, %%cr4;"
|
|
||||||
:
|
|
||||||
: "r"(static_cast<uint32_t>(m_highest_paging_struct))
|
|
||||||
: "eax"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (send_smp_message)
|
if (send_smp_message)
|
||||||
{
|
{
|
||||||
@@ -351,14 +314,13 @@ namespace Kernel
|
|||||||
.type = Processor::SMPMessage::Type::FlushTLB,
|
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||||
.flush_tlb = {
|
.flush_tlb = {
|
||||||
.vaddr = vaddr,
|
.vaddr = vaddr,
|
||||||
.page_count = pages,
|
.page_count = 1
|
||||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PageTable::unmap_page(vaddr_t vaddr, bool invalidate)
|
void PageTable::unmap_page(vaddr_t vaddr, bool send_smp_message)
|
||||||
{
|
{
|
||||||
ASSERT(vaddr);
|
ASSERT(vaddr);
|
||||||
ASSERT(vaddr % PAGE_SIZE == 0);
|
ASSERT(vaddr % PAGE_SIZE == 0);
|
||||||
@@ -377,16 +339,12 @@ namespace Kernel
|
|||||||
if (is_page_free(vaddr))
|
if (is_page_free(vaddr))
|
||||||
Kernel::panic("trying to unmap unmapped page 0x{H}", vaddr);
|
Kernel::panic("trying to unmap unmapped page 0x{H}", vaddr);
|
||||||
|
|
||||||
uint64_t* pdpt = P2V(m_highest_paging_struct);
|
uint64_t* pdpt = reinterpret_cast<uint64_t*>(P2V(m_highest_paging_struct));
|
||||||
uint64_t* pd = P2V(pdpt[pdpte] & s_page_addr_mask);
|
uint64_t* pd = reinterpret_cast<uint64_t*>(P2V(pdpt[pdpte] & PAGE_ADDR_MASK));
|
||||||
uint64_t* pt = P2V(pd[pde] & s_page_addr_mask);
|
uint64_t* pt = reinterpret_cast<uint64_t*>(P2V(pd[pde] & PAGE_ADDR_MASK));
|
||||||
|
|
||||||
const paddr_t old_paddr = pt[pte] & s_page_addr_mask;
|
|
||||||
|
|
||||||
pt[pte] = 0;
|
pt[pte] = 0;
|
||||||
|
invalidate(vaddr, send_smp_message);
|
||||||
if (invalidate && old_paddr != 0)
|
|
||||||
invalidate_page(vaddr, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PageTable::unmap_range(vaddr_t vaddr, size_t size)
|
void PageTable::unmap_range(vaddr_t vaddr, size_t size)
|
||||||
@@ -398,10 +356,17 @@ namespace Kernel
|
|||||||
SpinLockGuard _(m_lock);
|
SpinLockGuard _(m_lock);
|
||||||
for (vaddr_t page = 0; page < page_count; page++)
|
for (vaddr_t page = 0; page < page_count; page++)
|
||||||
unmap_page(vaddr + page * PAGE_SIZE, false);
|
unmap_page(vaddr + page * PAGE_SIZE, false);
|
||||||
invalidate_range(vaddr, page_count, true);
|
|
||||||
|
Processor::broadcast_smp_message({
|
||||||
|
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||||
|
.flush_tlb = {
|
||||||
|
.vaddr = vaddr,
|
||||||
|
.page_count = page_count
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void PageTable::map_page_at(paddr_t paddr, vaddr_t vaddr, flags_t flags, MemoryType memory_type, bool invalidate)
|
void PageTable::map_page_at(paddr_t paddr, vaddr_t vaddr, flags_t flags, MemoryType memory_type, bool send_smp_message)
|
||||||
{
|
{
|
||||||
ASSERT(vaddr);
|
ASSERT(vaddr);
|
||||||
ASSERT(vaddr != fast_page());
|
ASSERT(vaddr != fast_page());
|
||||||
@@ -436,11 +401,11 @@ namespace Kernel
|
|||||||
|
|
||||||
SpinLockGuard _(m_lock);
|
SpinLockGuard _(m_lock);
|
||||||
|
|
||||||
uint64_t* pdpt = P2V(m_highest_paging_struct);
|
uint64_t* pdpt = reinterpret_cast<uint64_t*>(P2V(m_highest_paging_struct));
|
||||||
if (!(pdpt[pdpte] & Flags::Present))
|
if (!(pdpt[pdpte] & Flags::Present))
|
||||||
pdpt[pdpte] = V2P(allocate_zeroed_page_aligned_page()) | Flags::Present;
|
pdpt[pdpte] = V2P(allocate_zeroed_page_aligned_page()) | Flags::Present;
|
||||||
|
|
||||||
uint64_t* pd = P2V(pdpt[pdpte] & s_page_addr_mask);
|
uint64_t* pd = reinterpret_cast<uint64_t*>(P2V(pdpt[pdpte] & PAGE_ADDR_MASK));
|
||||||
if ((pd[pde] & uwr_flags) != uwr_flags)
|
if ((pd[pde] & uwr_flags) != uwr_flags)
|
||||||
{
|
{
|
||||||
if (!(pd[pde] & Flags::Present))
|
if (!(pd[pde] & Flags::Present))
|
||||||
@@ -451,14 +416,10 @@ namespace Kernel
|
|||||||
if (!(flags & Flags::Present))
|
if (!(flags & Flags::Present))
|
||||||
uwr_flags &= ~Flags::Present;
|
uwr_flags &= ~Flags::Present;
|
||||||
|
|
||||||
uint64_t* pt = P2V(pd[pde] & s_page_addr_mask);
|
uint64_t* pt = reinterpret_cast<uint64_t*>(P2V(pd[pde] & PAGE_ADDR_MASK));
|
||||||
|
|
||||||
const paddr_t old_paddr = pt[pte] & s_page_addr_mask;
|
|
||||||
|
|
||||||
pt[pte] = paddr | uwr_flags | extra_flags;
|
pt[pte] = paddr | uwr_flags | extra_flags;
|
||||||
|
|
||||||
if (invalidate && old_paddr != 0)
|
invalidate(vaddr, send_smp_message);
|
||||||
invalidate_page(vaddr, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
@@ -472,49 +433,14 @@ namespace Kernel
|
|||||||
SpinLockGuard _(m_lock);
|
SpinLockGuard _(m_lock);
|
||||||
for (size_t page = 0; page < page_count; page++)
|
for (size_t page = 0; page < page_count; page++)
|
||||||
map_page_at(paddr + page * PAGE_SIZE, vaddr + page * PAGE_SIZE, flags, memory_type, false);
|
map_page_at(paddr + page * PAGE_SIZE, vaddr + page * PAGE_SIZE, flags, memory_type, false);
|
||||||
invalidate_range(vaddr, page_count, true);
|
|
||||||
|
Processor::broadcast_smp_message({
|
||||||
|
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||||
|
.flush_tlb = {
|
||||||
|
.vaddr = vaddr,
|
||||||
|
.page_count = page_count
|
||||||
}
|
}
|
||||||
|
});
|
||||||
void PageTable::remove_writable_from_range(vaddr_t vaddr, size_t size)
|
|
||||||
{
|
|
||||||
ASSERT(vaddr);
|
|
||||||
ASSERT(vaddr % PAGE_SIZE == 0);
|
|
||||||
|
|
||||||
uint32_t pdpte = (vaddr >> 30) & 0x1FF;
|
|
||||||
uint32_t pde = (vaddr >> 21) & 0x1FF;
|
|
||||||
uint32_t pte = (vaddr >> 12) & 0x1FF;
|
|
||||||
|
|
||||||
const uint32_t e_pdpte = ((vaddr + size - 1) >> 30) & 0x1FF;
|
|
||||||
const uint32_t e_pde = ((vaddr + size - 1) >> 21) & 0x1FF;
|
|
||||||
const uint32_t e_pte = ((vaddr + size - 1) >> 12) & 0x1FF;
|
|
||||||
|
|
||||||
SpinLockGuard _(m_lock);
|
|
||||||
|
|
||||||
const uint64_t* pdpt = P2V(m_highest_paging_struct);
|
|
||||||
for (; pdpte <= e_pdpte; pdpte++)
|
|
||||||
{
|
|
||||||
if (!(pdpt[pdpte] & Flags::Present))
|
|
||||||
continue;
|
|
||||||
const uint64_t* pd = P2V(pdpt[pdpte] & s_page_addr_mask);
|
|
||||||
for (; pde < 512; pde++)
|
|
||||||
{
|
|
||||||
if (pdpte == e_pdpte && pde > e_pde)
|
|
||||||
break;
|
|
||||||
if (!(pd[pde] & Flags::ReadWrite))
|
|
||||||
continue;
|
|
||||||
uint64_t* pt = P2V(pd[pde] & s_page_addr_mask);
|
|
||||||
for (; pte < 512; pte++)
|
|
||||||
{
|
|
||||||
if (pdpte == e_pdpte && pde == e_pde && pte > e_pte)
|
|
||||||
break;
|
|
||||||
pt[pte] &= ~static_cast<uint64_t>(Flags::ReadWrite);
|
|
||||||
}
|
|
||||||
pte = 0;
|
|
||||||
}
|
|
||||||
pde = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
invalidate_range(vaddr, size / PAGE_SIZE, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t PageTable::get_page_data(vaddr_t vaddr) const
|
uint64_t PageTable::get_page_data(vaddr_t vaddr) const
|
||||||
@@ -527,15 +453,15 @@ namespace Kernel
|
|||||||
|
|
||||||
SpinLockGuard _(m_lock);
|
SpinLockGuard _(m_lock);
|
||||||
|
|
||||||
const uint64_t* pdpt = P2V(m_highest_paging_struct);
|
uint64_t* pdpt = (uint64_t*)P2V(m_highest_paging_struct);
|
||||||
if (!(pdpt[pdpte] & Flags::Present))
|
if (!(pdpt[pdpte] & Flags::Present))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const uint64_t* pd = P2V(pdpt[pdpte] & s_page_addr_mask);
|
uint64_t* pd = (uint64_t*)P2V(pdpt[pdpte] & PAGE_ADDR_MASK);
|
||||||
if (!(pd[pde] & Flags::Present))
|
if (!(pd[pde] & Flags::Present))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const uint64_t* pt = P2V(pd[pde] & s_page_addr_mask);
|
uint64_t* pt = (uint64_t*)P2V(pd[pde] & PAGE_ADDR_MASK);
|
||||||
if (!(pt[pte] & Flags::Used))
|
if (!(pt[pte] & Flags::Used))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -549,7 +475,8 @@ namespace Kernel
|
|||||||
|
|
||||||
paddr_t PageTable::physical_address_of(vaddr_t vaddr) const
|
paddr_t PageTable::physical_address_of(vaddr_t vaddr) const
|
||||||
{
|
{
|
||||||
return get_page_data(vaddr) & s_page_addr_mask;
|
uint64_t page_data = get_page_data(vaddr);
|
||||||
|
return (page_data & PAGE_ADDR_MASK) & ~(1ull << 63);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PageTable::is_page_free(vaddr_t vaddr) const
|
bool PageTable::is_page_free(vaddr_t vaddr) const
|
||||||
@@ -570,13 +497,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -590,9 +517,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);
|
||||||
invalidate_range(vaddr, bytes / PAGE_SIZE, true);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -605,37 +530,39 @@ namespace Kernel
|
|||||||
if (size_t rem = last_address % PAGE_SIZE)
|
if (size_t rem = last_address % PAGE_SIZE)
|
||||||
last_address -= rem;
|
last_address -= rem;
|
||||||
|
|
||||||
uint32_t pdpte = (first_address >> 30) & 0x1FF;
|
const uint32_t s_pdpte = (first_address >> 30) & 0x1FF;
|
||||||
uint32_t pde = (first_address >> 21) & 0x1FF;
|
const uint32_t s_pde = (first_address >> 21) & 0x1FF;
|
||||||
uint32_t pte = (first_address >> 12) & 0x1FF;
|
const uint32_t s_pte = (first_address >> 12) & 0x1FF;
|
||||||
|
|
||||||
const uint32_t e_pdpte = ((last_address - 1) >> 30) & 0x1FF;
|
const uint32_t e_pdpte = (last_address >> 30) & 0x1FF;
|
||||||
const uint32_t e_pde = ((last_address - 1) >> 21) & 0x1FF;
|
const uint32_t e_pde = (last_address >> 21) & 0x1FF;
|
||||||
const uint32_t e_pte = ((last_address - 1) >> 12) & 0x1FF;
|
const uint32_t e_pte = (last_address >> 12) & 0x1FF;
|
||||||
|
|
||||||
SpinLockGuard _(m_lock);
|
SpinLockGuard _(m_lock);
|
||||||
|
|
||||||
// Try to find free page that can be mapped without
|
// Try to find free page that can be mapped without
|
||||||
// allocations (page table with unused entries)
|
// allocations (page table with unused entries)
|
||||||
const uint64_t* pdpt = P2V(m_highest_paging_struct);
|
uint64_t* pdpt = reinterpret_cast<uint64_t*>(P2V(m_highest_paging_struct));
|
||||||
for (; pdpte <= e_pdpte; pdpte++)
|
for (uint32_t pdpte = s_pdpte; pdpte < 4; pdpte++)
|
||||||
{
|
{
|
||||||
|
if (pdpte > e_pdpte)
|
||||||
|
break;
|
||||||
if (!(pdpt[pdpte] & Flags::Present))
|
if (!(pdpt[pdpte] & Flags::Present))
|
||||||
continue;
|
continue;
|
||||||
const uint64_t* pd = P2V(pdpt[pdpte] & s_page_addr_mask);
|
uint64_t* pd = reinterpret_cast<uint64_t*>(P2V(pdpt[pdpte] & PAGE_ADDR_MASK));
|
||||||
for (; pde < 512; pde++)
|
for (uint32_t pde = s_pde; pde < 512; pde++)
|
||||||
{
|
{
|
||||||
if (pdpte == e_pdpte && pde > e_pde)
|
if (pdpte == e_pdpte && pde > e_pde)
|
||||||
break;
|
break;
|
||||||
if (!(pd[pde] & Flags::Present))
|
if (!(pd[pde] & Flags::Present))
|
||||||
continue;
|
continue;
|
||||||
const uint64_t* pt = P2V(pd[pde] & s_page_addr_mask);
|
uint64_t* pt = (uint64_t*)P2V(pd[pde] & PAGE_ADDR_MASK);
|
||||||
for (; pte < 512; pte++)
|
for (uint32_t pte = s_pte; pte < 512; pte++)
|
||||||
{
|
{
|
||||||
if (pdpte == e_pdpte && pde == e_pde && pte > e_pte)
|
if (pdpte == e_pdpte && pde == e_pde && pte >= e_pte)
|
||||||
break;
|
break;
|
||||||
if (pt[pte] & Flags::Used)
|
if (!(pt[pte] & Flags::Used))
|
||||||
continue;
|
{
|
||||||
vaddr_t vaddr = 0;
|
vaddr_t vaddr = 0;
|
||||||
vaddr |= (vaddr_t)pdpte << 30;
|
vaddr |= (vaddr_t)pdpte << 30;
|
||||||
vaddr |= (vaddr_t)pde << 21;
|
vaddr |= (vaddr_t)pde << 21;
|
||||||
@@ -643,9 +570,8 @@ namespace Kernel
|
|||||||
ASSERT(reserve_page(vaddr));
|
ASSERT(reserve_page(vaddr));
|
||||||
return vaddr;
|
return vaddr;
|
||||||
}
|
}
|
||||||
pte = 0;
|
|
||||||
}
|
}
|
||||||
pde = 0;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find any free page
|
// Find any free page
|
||||||
@@ -658,7 +584,7 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
vaddr_t PageTable::reserve_free_contiguous_pages(size_t page_count, vaddr_t first_address, vaddr_t last_address)
|
vaddr_t PageTable::reserve_free_contiguous_pages(size_t page_count, vaddr_t first_address, vaddr_t last_address)
|
||||||
@@ -691,7 +617,7 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_range(vaddr_t start, vaddr_t end, PageTable::flags_t flags)
|
static void dump_range(vaddr_t start, vaddr_t end, PageTable::flags_t flags)
|
||||||
@@ -714,7 +640,7 @@ namespace Kernel
|
|||||||
flags_t flags = 0;
|
flags_t flags = 0;
|
||||||
vaddr_t start = 0;
|
vaddr_t start = 0;
|
||||||
|
|
||||||
const uint64_t* pdpt = P2V(m_highest_paging_struct);
|
uint64_t* pdpt = reinterpret_cast<uint64_t*>(P2V(m_highest_paging_struct));
|
||||||
for (uint32_t pdpte = 0; pdpte < 4; pdpte++)
|
for (uint32_t pdpte = 0; pdpte < 4; pdpte++)
|
||||||
{
|
{
|
||||||
if (!(pdpt[pdpte] & Flags::Present))
|
if (!(pdpt[pdpte] & Flags::Present))
|
||||||
@@ -723,7 +649,7 @@ namespace Kernel
|
|||||||
start = 0;
|
start = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const uint64_t* pd = P2V(pdpt[pdpte] & s_page_addr_mask);
|
uint64_t* pd = (uint64_t*)P2V(pdpt[pdpte] & PAGE_ADDR_MASK);
|
||||||
for (uint64_t pde = 0; pde < 512; pde++)
|
for (uint64_t pde = 0; pde < 512; pde++)
|
||||||
{
|
{
|
||||||
if (!(pd[pde] & Flags::Present))
|
if (!(pd[pde] & Flags::Present))
|
||||||
@@ -732,7 +658,7 @@ namespace Kernel
|
|||||||
start = 0;
|
start = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const uint64_t* pt = P2V(pd[pde] & s_page_addr_mask);
|
uint64_t* pt = (uint64_t*)P2V(pd[pde] & PAGE_ADDR_MASK);
|
||||||
for (uint64_t pte = 0; pte < 512; pte++)
|
for (uint64_t pte = 0; pte < 512; pte++)
|
||||||
{
|
{
|
||||||
if (parse_flags(pt[pte]) != flags)
|
if (parse_flags(pt[pte]) != flags)
|
||||||
|
|||||||
@@ -1,41 +1,16 @@
|
|||||||
.section .userspace, "ax"
|
.section .userspace, "ax"
|
||||||
|
|
||||||
// stack contains
|
// stack contains
|
||||||
// (4 bytes) return address (on return stack)
|
// return address
|
||||||
// (4 bytes) return stack
|
// signal number
|
||||||
// (4 bytes) return rflags
|
// signal handler
|
||||||
// (8 bytes) restore sigmask
|
|
||||||
// (36 bytes) siginfo_t
|
|
||||||
// (4 bytes) signal number
|
|
||||||
// (4 bytes) signal handler
|
|
||||||
|
|
||||||
.global signal_trampoline
|
.global signal_trampoline
|
||||||
signal_trampoline:
|
signal_trampoline:
|
||||||
pushl %esi // gregs
|
pusha
|
||||||
pushl %edi
|
|
||||||
pushl %edx
|
|
||||||
pushl %ecx
|
|
||||||
pushl %ebx
|
|
||||||
pushl %eax
|
|
||||||
pushl %ebp
|
|
||||||
|
|
||||||
movl 80(%esp), %eax
|
movl 40(%esp), %edi
|
||||||
pushl %eax; addl $4, (%esp)
|
movl 36(%esp), %eax
|
||||||
pushl (%eax)
|
|
||||||
|
|
||||||
// FIXME: populate these
|
|
||||||
xorl %eax, %eax
|
|
||||||
pushl %eax // stack
|
|
||||||
pushl %eax
|
|
||||||
pushl %eax
|
|
||||||
pushl %eax // sigset
|
|
||||||
pushl %eax
|
|
||||||
pushl %eax // link
|
|
||||||
|
|
||||||
movl %esp, %edx // ucontext
|
|
||||||
leal 68(%esp), %esi // siginfo
|
|
||||||
movl 64(%esp), %edi // signal number
|
|
||||||
movl 60(%esp), %eax // handlers
|
|
||||||
|
|
||||||
// align stack to 16 bytes
|
// align stack to 16 bytes
|
||||||
movl %esp, %ebp
|
movl %esp, %ebp
|
||||||
@@ -44,9 +19,7 @@ signal_trampoline:
|
|||||||
subl $512, %esp
|
subl $512, %esp
|
||||||
fxsave (%esp)
|
fxsave (%esp)
|
||||||
|
|
||||||
subl $4, %esp
|
subl $12, %esp
|
||||||
pushl %edx
|
|
||||||
pushl %esi
|
|
||||||
pushl %edi
|
pushl %edi
|
||||||
call *%eax
|
call *%eax
|
||||||
addl $16, %esp
|
addl $16, %esp
|
||||||
@@ -56,31 +29,9 @@ signal_trampoline:
|
|||||||
|
|
||||||
// restore stack
|
// restore stack
|
||||||
movl %ebp, %esp
|
movl %ebp, %esp
|
||||||
addl $24, %esp
|
popa
|
||||||
|
|
||||||
// restore sigmask
|
|
||||||
movl $83, %eax // SYS_SIGPROCMASK
|
|
||||||
movl $3, %ebx // SIG_SETMASK
|
|
||||||
leal 72(%esp), %ecx // set
|
|
||||||
xorl %edx, %edx // oset
|
|
||||||
int $0xF0
|
|
||||||
|
|
||||||
// restore registers
|
|
||||||
addl $8, %esp
|
addl $8, %esp
|
||||||
popl %ebp
|
|
||||||
popl %eax
|
|
||||||
popl %ebx
|
|
||||||
popl %ecx
|
|
||||||
popl %edx
|
|
||||||
popl %edi
|
|
||||||
popl %esi
|
|
||||||
|
|
||||||
// skip handler, number, siginfo_t, sigmask
|
|
||||||
addl $52, %esp
|
|
||||||
|
|
||||||
// restore flags
|
|
||||||
popf
|
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
|
||||||
@@ -63,7 +69,7 @@ sys_fork_trampoline:
|
|||||||
|
|
||||||
call read_ip
|
call read_ip
|
||||||
testl %eax, %eax
|
testl %eax, %eax
|
||||||
jz .done
|
jz .reload_stack
|
||||||
|
|
||||||
movl %esp, %ebx
|
movl %esp, %ebx
|
||||||
|
|
||||||
@@ -79,3 +85,9 @@ sys_fork_trampoline:
|
|||||||
popl %ebx
|
popl %ebx
|
||||||
popl %ebp
|
popl %ebp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
.reload_stack:
|
||||||
|
call get_thread_start_sp
|
||||||
|
movl %eax, %esp
|
||||||
|
xorl %eax, %eax
|
||||||
|
jmp .done
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ read_ip:
|
|||||||
# void start_kernel_thread()
|
# void start_kernel_thread()
|
||||||
.global start_kernel_thread
|
.global start_kernel_thread
|
||||||
start_kernel_thread:
|
start_kernel_thread:
|
||||||
|
call get_thread_start_sp
|
||||||
|
movl %eax, %esp
|
||||||
|
|
||||||
# STACK LAYOUT
|
# STACK LAYOUT
|
||||||
# on_exit arg
|
# on_exit arg
|
||||||
# on_exit func
|
# on_exit func
|
||||||
@@ -28,15 +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
|
||||||
|
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
|
|
||||||
@@ -11,28 +11,9 @@
|
|||||||
|
|
||||||
.code32
|
.code32
|
||||||
|
|
||||||
// video mode info, page align modules
|
# multiboot2 header
|
||||||
.set multiboot_flags, (1 << 2) | (1 << 0)
|
|
||||||
|
|
||||||
.section .multiboot, "aw"
|
.section .multiboot, "aw"
|
||||||
multiboot_start:
|
.align 8
|
||||||
.long 0x1BADB002
|
|
||||||
.long multiboot_flags
|
|
||||||
.long -(0x1BADB002 + multiboot_flags)
|
|
||||||
|
|
||||||
.long 0
|
|
||||||
.long 0
|
|
||||||
.long 0
|
|
||||||
.long 0
|
|
||||||
.long 0
|
|
||||||
|
|
||||||
.long 0
|
|
||||||
.long FB_WIDTH
|
|
||||||
.long FB_HEIGHT
|
|
||||||
.long FB_BPP
|
|
||||||
multiboot_end:
|
|
||||||
|
|
||||||
.section .multiboot2, "aw"
|
|
||||||
multiboot2_start:
|
multiboot2_start:
|
||||||
.long 0xE85250D6
|
.long 0xE85250D6
|
||||||
.long 0
|
.long 0
|
||||||
@@ -68,6 +49,7 @@ multiboot2_start:
|
|||||||
multiboot2_end:
|
multiboot2_end:
|
||||||
|
|
||||||
.section .bananboot, "aw"
|
.section .bananboot, "aw"
|
||||||
|
.align 8
|
||||||
bananboot_start:
|
bananboot_start:
|
||||||
.long 0xBABAB007
|
.long 0xBABAB007
|
||||||
.long -(0xBABAB007 + FB_WIDTH + FB_HEIGHT + FB_BPP)
|
.long -(0xBABAB007 + FB_WIDTH + FB_HEIGHT + FB_BPP)
|
||||||
@@ -185,13 +167,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
|
||||||
@@ -234,7 +209,6 @@ 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
|
||||||
@@ -311,7 +285,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,67 +1,66 @@
|
|||||||
.macro intr_header, n
|
.macro push_userspace
|
||||||
|
pushw %gs
|
||||||
|
pushw %fs
|
||||||
|
pushw %es
|
||||||
|
pushw %ds
|
||||||
pushal
|
pushal
|
||||||
testb $3, \n+8*4(%esp)
|
.endm
|
||||||
jz 1f
|
|
||||||
|
.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: cld
|
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro intr_footer, n
|
.macro pop_userspace
|
||||||
testb $3, \n+8*4(%esp)
|
popal
|
||||||
jz 1f
|
popw %ds
|
||||||
call cpp_check_signal
|
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: popal
|
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
isr_stub:
|
isr_stub:
|
||||||
intr_header 12
|
push_userspace
|
||||||
|
load_kernel_segments
|
||||||
|
cld
|
||||||
|
|
||||||
movl %cr0, %eax; pushl %eax
|
movl %cr0, %eax; pushl %eax
|
||||||
movl %cr2, %eax; pushl %eax
|
movl %cr2, %eax; pushl %eax
|
||||||
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
|
||||||
|
|
||||||
intr_footer 12
|
pop_userspace
|
||||||
addl $8, %esp
|
addl $8, %esp
|
||||||
iret
|
iret
|
||||||
|
|
||||||
irq_stub:
|
irq_stub:
|
||||||
intr_header 12
|
push_userspace
|
||||||
|
load_kernel_segments
|
||||||
|
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
|
||||||
@@ -72,13 +71,37 @@ irq_stub:
|
|||||||
|
|
||||||
movl %ebp, %esp
|
movl %ebp, %esp
|
||||||
|
|
||||||
intr_footer 12
|
pop_userspace
|
||||||
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:
|
||||||
intr_header 4
|
push_userspace
|
||||||
|
load_kernel_segments
|
||||||
|
cld
|
||||||
|
|
||||||
movl %esp, %ebp
|
movl %esp, %ebp
|
||||||
andl $-16, %esp
|
andl $-16, %esp
|
||||||
@@ -87,12 +110,14 @@ asm_ipi_handler:
|
|||||||
|
|
||||||
movl %ebp, %esp
|
movl %ebp, %esp
|
||||||
|
|
||||||
intr_footer 4
|
pop_userspace
|
||||||
iret
|
iret
|
||||||
|
|
||||||
.global asm_timer_handler
|
.global asm_timer_handler
|
||||||
asm_timer_handler:
|
asm_timer_handler:
|
||||||
intr_header 4
|
push_userspace
|
||||||
|
load_kernel_segments
|
||||||
|
cld
|
||||||
|
|
||||||
movl %esp, %ebp
|
movl %esp, %ebp
|
||||||
andl $-16, %esp
|
andl $-16, %esp
|
||||||
@@ -101,7 +126,7 @@ asm_timer_handler:
|
|||||||
|
|
||||||
movl %ebp, %esp
|
movl %ebp, %esp
|
||||||
|
|
||||||
intr_footer 4
|
pop_userspace
|
||||||
iret
|
iret
|
||||||
|
|
||||||
.macro isr n
|
.macro isr n
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ SECTIONS
|
|||||||
{
|
{
|
||||||
g_kernel_execute_start = .;
|
g_kernel_execute_start = .;
|
||||||
*(.multiboot)
|
*(.multiboot)
|
||||||
*(.multiboot2)
|
|
||||||
*(.bananboot)
|
*(.bananboot)
|
||||||
*(.text.*)
|
*(.text.*)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace Kernel
|
|||||||
SpinLock PageTable::s_fast_page_lock;
|
SpinLock PageTable::s_fast_page_lock;
|
||||||
|
|
||||||
static constexpr vaddr_t s_hhdm_offset = 0xFFFF800000000000;
|
static constexpr vaddr_t s_hhdm_offset = 0xFFFF800000000000;
|
||||||
static bool s_is_post_heap_done = false;
|
static bool s_is_hddm_initialized = false;
|
||||||
|
|
||||||
constexpr uint64_t s_page_flag_mask = 0x8000000000000FFF;
|
constexpr uint64_t s_page_flag_mask = 0x8000000000000FFF;
|
||||||
constexpr uint64_t s_page_addr_mask = ~s_page_flag_mask;
|
constexpr uint64_t s_page_addr_mask = ~s_page_flag_mask;
|
||||||
@@ -376,7 +376,7 @@ namespace Kernel
|
|||||||
V2P = &FuncsHHDM::V2P;
|
V2P = &FuncsHHDM::V2P;
|
||||||
P2V = &FuncsHHDM::P2V;
|
P2V = &FuncsHHDM::P2V;
|
||||||
|
|
||||||
s_is_post_heap_done = true;
|
s_is_hddm_initialized = true;
|
||||||
|
|
||||||
// This is a hack to unmap fast page. fast page pt is copied
|
// This is a hack to unmap fast page. fast page pt is copied
|
||||||
// while it is mapped, so we need to manually unmap it
|
// while it is mapped, so we need to manually unmap it
|
||||||
@@ -485,7 +485,6 @@ namespace Kernel
|
|||||||
constexpr uint64_t pml4e = (uc_vaddr >> 39) & 0x1FF;
|
constexpr uint64_t pml4e = (uc_vaddr >> 39) & 0x1FF;
|
||||||
constexpr uint64_t pdpte = (uc_vaddr >> 30) & 0x1FF;
|
constexpr uint64_t pdpte = (uc_vaddr >> 30) & 0x1FF;
|
||||||
constexpr uint64_t pde = (uc_vaddr >> 21) & 0x1FF;
|
constexpr uint64_t pde = (uc_vaddr >> 21) & 0x1FF;
|
||||||
constexpr uint64_t pte = (uc_vaddr >> 12) & 0x1FF;
|
|
||||||
|
|
||||||
uint64_t* pml4 = P2V(m_highest_paging_struct);
|
uint64_t* pml4 = P2V(m_highest_paging_struct);
|
||||||
ASSERT(!(pml4[pml4e] & Flags::Present));
|
ASSERT(!(pml4[pml4e] & Flags::Present));
|
||||||
@@ -498,10 +497,6 @@ namespace Kernel
|
|||||||
uint64_t* pd = P2V(pdpt[pdpte] & s_page_addr_mask);
|
uint64_t* pd = P2V(pdpt[pdpte] & s_page_addr_mask);
|
||||||
ASSERT(!(pd[pde] & Flags::Present));
|
ASSERT(!(pd[pde] & Flags::Present));
|
||||||
pd[pde] = allocate_zeroed_page_aligned_page() | Flags::ReadWrite | Flags::Present;
|
pd[pde] = allocate_zeroed_page_aligned_page() | Flags::ReadWrite | Flags::Present;
|
||||||
|
|
||||||
uint64_t* pt = P2V(pd[pde] & s_page_addr_mask);
|
|
||||||
ASSERT(pt[pte] == 0);
|
|
||||||
pt[pte] = Flags::Reserved;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PageTable::map_fast_page(paddr_t paddr)
|
void PageTable::map_fast_page(paddr_t paddr)
|
||||||
@@ -526,7 +521,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()
|
||||||
@@ -547,9 +542,9 @@ namespace Kernel
|
|||||||
uint64_t* pt = P2V(pd[pde] & s_page_addr_mask);
|
uint64_t* pt = P2V(pd[pde] & s_page_addr_mask);
|
||||||
|
|
||||||
ASSERT(pt[pte] & Flags::Present);
|
ASSERT(pt[pte] & Flags::Present);
|
||||||
pt[pte] = Flags::Reserved;
|
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()
|
||||||
@@ -617,39 +612,10 @@ namespace Kernel
|
|||||||
Processor::set_current_page_table(this);
|
Processor::set_current_page_table(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PageTable::invalidate_range(vaddr_t vaddr, size_t pages, bool send_smp_message)
|
void PageTable::invalidate(vaddr_t vaddr, bool send_smp_message)
|
||||||
{
|
{
|
||||||
ASSERT(vaddr % PAGE_SIZE == 0);
|
ASSERT(vaddr % PAGE_SIZE == 0);
|
||||||
|
asm volatile("invlpg (%0)" :: "r"(vaddr) : "memory");
|
||||||
const bool is_userspace = (vaddr < KERNEL_OFFSET);
|
|
||||||
if (is_userspace && this != &PageTable::current())
|
|
||||||
;
|
|
||||||
else if (pages <= 32 || !s_is_post_heap_done)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < pages; i++, vaddr += PAGE_SIZE)
|
|
||||||
asm volatile("invlpg (%0)" :: "r"(vaddr));
|
|
||||||
}
|
|
||||||
else if (is_userspace || !s_has_pge)
|
|
||||||
{
|
|
||||||
asm volatile("movq %0, %%cr3" :: "r"(m_highest_paging_struct));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
asm volatile(
|
|
||||||
"movq %%cr4, %%rax;"
|
|
||||||
|
|
||||||
"andq $~0x80, %%rax;"
|
|
||||||
"movq %%rax, %%cr4;"
|
|
||||||
|
|
||||||
"movq %0, %%cr3;"
|
|
||||||
|
|
||||||
"orq $0x80, %%rax;"
|
|
||||||
"movq %%rax, %%cr4;"
|
|
||||||
:
|
|
||||||
: "r"(m_highest_paging_struct)
|
|
||||||
: "rax"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (send_smp_message)
|
if (send_smp_message)
|
||||||
{
|
{
|
||||||
@@ -657,14 +623,13 @@ namespace Kernel
|
|||||||
.type = Processor::SMPMessage::Type::FlushTLB,
|
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||||
.flush_tlb = {
|
.flush_tlb = {
|
||||||
.vaddr = vaddr,
|
.vaddr = vaddr,
|
||||||
.page_count = pages,
|
.page_count = 1
|
||||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PageTable::unmap_page(vaddr_t vaddr, bool invalidate)
|
void PageTable::unmap_page(vaddr_t vaddr, bool send_smp_message)
|
||||||
{
|
{
|
||||||
ASSERT(vaddr);
|
ASSERT(vaddr);
|
||||||
ASSERT(vaddr != fast_page());
|
ASSERT(vaddr != fast_page());
|
||||||
@@ -693,27 +658,30 @@ 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 (invalidate && old_paddr != 0)
|
|
||||||
invalidate_page(vaddr, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PageTable::unmap_range(vaddr_t vaddr, size_t size)
|
void PageTable::unmap_range(vaddr_t vaddr, size_t size)
|
||||||
{
|
{
|
||||||
ASSERT(vaddr % PAGE_SIZE == 0);
|
ASSERT(vaddr % PAGE_SIZE == 0);
|
||||||
|
|
||||||
const size_t page_count = range_page_count(vaddr, size);
|
size_t page_count = range_page_count(vaddr, size);
|
||||||
|
|
||||||
SpinLockGuard _(m_lock);
|
SpinLockGuard _(m_lock);
|
||||||
for (vaddr_t page = 0; page < page_count; page++)
|
for (vaddr_t page = 0; page < page_count; page++)
|
||||||
unmap_page(vaddr + page * PAGE_SIZE, false);
|
unmap_page(vaddr + page * PAGE_SIZE, false);
|
||||||
invalidate_range(vaddr, page_count, true);
|
|
||||||
|
Processor::broadcast_smp_message({
|
||||||
|
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||||
|
.flush_tlb = {
|
||||||
|
.vaddr = vaddr,
|
||||||
|
.page_count = page_count
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void PageTable::map_page_at(paddr_t paddr, vaddr_t vaddr, flags_t flags, MemoryType memory_type, bool invalidate)
|
void PageTable::map_page_at(paddr_t paddr, vaddr_t vaddr, flags_t flags, MemoryType memory_type, bool send_smp_message)
|
||||||
{
|
{
|
||||||
ASSERT(vaddr);
|
ASSERT(vaddr);
|
||||||
ASSERT(vaddr != fast_page());
|
ASSERT(vaddr != fast_page());
|
||||||
@@ -774,12 +742,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 (invalidate && old_paddr != 0)
|
invalidate(vaddr, send_smp_message);
|
||||||
invalidate_page(vaddr, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
@@ -795,66 +760,14 @@ namespace Kernel
|
|||||||
SpinLockGuard _(m_lock);
|
SpinLockGuard _(m_lock);
|
||||||
for (size_t page = 0; page < page_count; page++)
|
for (size_t page = 0; page < page_count; page++)
|
||||||
map_page_at(paddr + page * PAGE_SIZE, vaddr + page * PAGE_SIZE, flags, memory_type, false);
|
map_page_at(paddr + page * PAGE_SIZE, vaddr + page * PAGE_SIZE, flags, memory_type, false);
|
||||||
invalidate_range(vaddr, page_count, true);
|
|
||||||
|
Processor::broadcast_smp_message({
|
||||||
|
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||||
|
.flush_tlb = {
|
||||||
|
.vaddr = vaddr,
|
||||||
|
.page_count = page_count
|
||||||
}
|
}
|
||||||
|
});
|
||||||
void PageTable::remove_writable_from_range(vaddr_t vaddr, size_t size)
|
|
||||||
{
|
|
||||||
ASSERT(vaddr);
|
|
||||||
ASSERT(vaddr % PAGE_SIZE == 0);
|
|
||||||
|
|
||||||
ASSERT(is_canonical(vaddr));
|
|
||||||
ASSERT(is_canonical(vaddr + size - 1));
|
|
||||||
|
|
||||||
const vaddr_t uc_vaddr_start = uncanonicalize(vaddr);
|
|
||||||
const vaddr_t uc_vaddr_end = uncanonicalize(vaddr + size - 1);
|
|
||||||
|
|
||||||
uint16_t pml4e = (uc_vaddr_start >> 39) & 0x1FF;
|
|
||||||
uint16_t pdpte = (uc_vaddr_start >> 30) & 0x1FF;
|
|
||||||
uint16_t pde = (uc_vaddr_start >> 21) & 0x1FF;
|
|
||||||
uint16_t pte = (uc_vaddr_start >> 12) & 0x1FF;
|
|
||||||
|
|
||||||
const uint16_t e_pml4e = (uc_vaddr_end >> 39) & 0x1FF;
|
|
||||||
const uint16_t e_pdpte = (uc_vaddr_end >> 30) & 0x1FF;
|
|
||||||
const uint16_t e_pde = (uc_vaddr_end >> 21) & 0x1FF;
|
|
||||||
const uint16_t e_pte = (uc_vaddr_end >> 12) & 0x1FF;
|
|
||||||
|
|
||||||
SpinLockGuard _(m_lock);
|
|
||||||
|
|
||||||
const uint64_t* pml4 = P2V(m_highest_paging_struct);
|
|
||||||
for (; pml4e <= e_pml4e; pml4e++)
|
|
||||||
{
|
|
||||||
if (!(pml4[pml4e] & Flags::ReadWrite))
|
|
||||||
continue;
|
|
||||||
const uint64_t* pdpt = P2V(pml4[pml4e] & s_page_addr_mask);
|
|
||||||
for (; pdpte < 512; pdpte++)
|
|
||||||
{
|
|
||||||
if (pml4e == e_pml4e && pdpte > e_pdpte)
|
|
||||||
break;
|
|
||||||
if (!(pdpt[pdpte] & Flags::ReadWrite))
|
|
||||||
continue;
|
|
||||||
const uint64_t* pd = P2V(pdpt[pdpte] & s_page_addr_mask);
|
|
||||||
for (; pde < 512; pde++)
|
|
||||||
{
|
|
||||||
if (pml4e == e_pml4e && pdpte == e_pdpte && pde > e_pde)
|
|
||||||
break;
|
|
||||||
if (!(pd[pde] & Flags::ReadWrite))
|
|
||||||
continue;
|
|
||||||
uint64_t* pt = P2V(pd[pde] & s_page_addr_mask);
|
|
||||||
for (; pte < 512; pte++)
|
|
||||||
{
|
|
||||||
if (pml4e == e_pml4e && pdpte == e_pdpte && pde == e_pde && pte > e_pte)
|
|
||||||
break;
|
|
||||||
pt[pte] &= ~static_cast<uint64_t>(Flags::ReadWrite);
|
|
||||||
}
|
|
||||||
pte = 0;
|
|
||||||
}
|
|
||||||
pde = 0;
|
|
||||||
}
|
|
||||||
pdpte = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
invalidate_range(vaddr, size / PAGE_SIZE, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t PageTable::get_page_data(vaddr_t vaddr) const
|
uint64_t PageTable::get_page_data(vaddr_t vaddr) const
|
||||||
@@ -901,13 +814,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 invalidate)
|
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, invalidate);
|
map_page_at(0, vaddr, Flags::Reserved);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -921,8 +834,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);
|
||||||
invalidate_range(vaddr, bytes / PAGE_SIZE, true);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -936,9 +848,9 @@ 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 - 1);
|
const vaddr_t uc_vaddr_end = uncanonicalize(last_address);
|
||||||
|
|
||||||
uint16_t pml4e = (uc_vaddr_start >> 39) & 0x1FF;
|
uint16_t pml4e = (uc_vaddr_start >> 39) & 0x1FF;
|
||||||
uint16_t pdpte = (uc_vaddr_start >> 30) & 0x1FF;
|
uint16_t pdpte = (uc_vaddr_start >> 30) & 0x1FF;
|
||||||
@@ -955,8 +867,10 @@ namespace Kernel
|
|||||||
// Try to find free page that can be mapped without
|
// Try to find free page that can be mapped without
|
||||||
// allocations (page table with unused entries)
|
// allocations (page table with unused entries)
|
||||||
const uint64_t* pml4 = P2V(m_highest_paging_struct);
|
const uint64_t* pml4 = P2V(m_highest_paging_struct);
|
||||||
for (; pml4e <= e_pml4e; pml4e++)
|
for (; pml4e < 512; pml4e++)
|
||||||
{
|
{
|
||||||
|
if (pml4e > e_pml4e)
|
||||||
|
break;
|
||||||
if (!(pml4[pml4e] & Flags::Present))
|
if (!(pml4[pml4e] & Flags::Present))
|
||||||
continue;
|
continue;
|
||||||
const uint64_t* pdpt = P2V(pml4[pml4e] & s_page_addr_mask);
|
const uint64_t* pdpt = P2V(pml4[pml4e] & s_page_addr_mask);
|
||||||
@@ -976,10 +890,10 @@ namespace Kernel
|
|||||||
const uint64_t* pt = P2V(pd[pde] & s_page_addr_mask);
|
const uint64_t* pt = P2V(pd[pde] & s_page_addr_mask);
|
||||||
for (; pte < 512; pte++)
|
for (; pte < 512; pte++)
|
||||||
{
|
{
|
||||||
if (pml4e == e_pml4e && pdpte == e_pdpte && pde == e_pde && pte > e_pte)
|
if (pml4e == e_pml4e && pdpte == e_pdpte && pde == e_pde && pte >= e_pte)
|
||||||
break;
|
break;
|
||||||
if (pt[pte] & Flags::Used)
|
if (!(pt[pte] & Flags::Used))
|
||||||
continue;
|
{
|
||||||
vaddr_t vaddr = 0;
|
vaddr_t vaddr = 0;
|
||||||
vaddr |= static_cast<uint64_t>(pml4e) << 39;
|
vaddr |= static_cast<uint64_t>(pml4e) << 39;
|
||||||
vaddr |= static_cast<uint64_t>(pdpte) << 30;
|
vaddr |= static_cast<uint64_t>(pdpte) << 30;
|
||||||
@@ -989,11 +903,9 @@ namespace Kernel
|
|||||||
ASSERT(reserve_page(vaddr));
|
ASSERT(reserve_page(vaddr));
|
||||||
return vaddr;
|
return vaddr;
|
||||||
}
|
}
|
||||||
pte = 0;
|
|
||||||
}
|
}
|
||||||
pde = 0;
|
|
||||||
}
|
}
|
||||||
pdpte = 0;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (vaddr_t uc_vaddr = uc_vaddr_start; uc_vaddr < uc_vaddr_end; uc_vaddr += PAGE_SIZE)
|
for (vaddr_t uc_vaddr = uc_vaddr_start; uc_vaddr < uc_vaddr_end; uc_vaddr += PAGE_SIZE)
|
||||||
@@ -1005,7 +917,7 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
vaddr_t PageTable::reserve_free_contiguous_pages(size_t page_count, vaddr_t first_address, vaddr_t last_address)
|
vaddr_t PageTable::reserve_free_contiguous_pages(size_t page_count, vaddr_t first_address, vaddr_t last_address)
|
||||||
@@ -1018,7 +930,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);
|
||||||
|
|
||||||
@@ -1047,7 +959,7 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PageTable::is_page_free(vaddr_t page) const
|
bool PageTable::is_page_free(vaddr_t page) const
|
||||||
|
|||||||
@@ -1,48 +1,30 @@
|
|||||||
.section .userspace, "ax"
|
.section .userspace, "ax"
|
||||||
|
|
||||||
// stack contains
|
// stack contains
|
||||||
// (8 bytes) return address (on return stack)
|
// return address
|
||||||
// (8 bytes) return stack
|
// signal number
|
||||||
// (8 bytes) return rflags
|
// signal handler
|
||||||
// (8 bytes) restore sigmask
|
|
||||||
// (56 bytes) siginfo_t
|
|
||||||
// (8 bytes) signal number
|
|
||||||
// (8 bytes) 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
|
||||||
|
|
||||||
movq 208(%rsp), %rax
|
movq 128(%rsp), %rdi
|
||||||
pushq %rax; addq $(128 + 8), (%rsp)
|
movq 120(%rsp), %rax
|
||||||
pushq (%rax)
|
|
||||||
|
|
||||||
// FIXME: populate these
|
|
||||||
xorq %rax, %rax
|
|
||||||
pushq %rax // stack
|
|
||||||
pushq %rax
|
|
||||||
pushq %rax
|
|
||||||
pushq %rax // sigset
|
|
||||||
pushq %rax // link
|
|
||||||
|
|
||||||
movq %rsp, %rdx // ucontext
|
|
||||||
leaq 192(%rsp), %rsi // siginfo
|
|
||||||
movq 184(%rsp), %rdi // signal number
|
|
||||||
movq 176(%rsp), %rax // handler
|
|
||||||
|
|
||||||
// align stack to 16 bytes
|
// align stack to 16 bytes
|
||||||
movq %rsp, %rbp
|
movq %rsp, %rbp
|
||||||
@@ -58,40 +40,24 @@ signal_trampoline:
|
|||||||
|
|
||||||
// restore stack
|
// restore stack
|
||||||
movq %rbp, %rsp
|
movq %rbp, %rsp
|
||||||
addq $40, %rsp
|
|
||||||
|
|
||||||
// restore sigmask
|
|
||||||
movq $83, %rdi // SYS_SIGPROCMASK
|
|
||||||
movq $3, %rsi // SIG_SETMASK
|
|
||||||
leaq 192(%rsp), %rdx // set
|
|
||||||
xorq %r10, %r10 // oset
|
|
||||||
syscall
|
|
||||||
|
|
||||||
// restore registers
|
|
||||||
addq $16, %rsp
|
|
||||||
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, sigmask
|
addq $16, %rsp
|
||||||
addq $80, %rsp
|
|
||||||
|
|
||||||
// restore flags
|
|
||||||
popfq
|
popfq
|
||||||
|
|
||||||
movq (%rsp), %rsp
|
|
||||||
|
|
||||||
// return over red-zone
|
// return over red-zone
|
||||||
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
|
||||||
jz .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
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ read_ip:
|
|||||||
# void start_kernel_thread()
|
# void start_kernel_thread()
|
||||||
.global start_kernel_thread
|
.global start_kernel_thread
|
||||||
start_kernel_thread:
|
start_kernel_thread:
|
||||||
|
call get_thread_start_sp
|
||||||
|
movq %rax, %rsp
|
||||||
|
|
||||||
# STACK LAYOUT
|
# STACK LAYOUT
|
||||||
# on_exit arg
|
# on_exit arg
|
||||||
# on_exit func
|
# on_exit func
|
||||||
@@ -24,5 +27,9 @@ start_kernel_thread:
|
|||||||
|
|
||||||
.global start_userspace_thread
|
.global start_userspace_thread
|
||||||
start_userspace_thread:
|
start_userspace_thread:
|
||||||
swapgs
|
call load_thread_sse
|
||||||
|
|
||||||
|
call get_thread_start_sp
|
||||||
|
movq %rax, %rsp
|
||||||
|
|
||||||
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
|
|
||||||
@@ -11,28 +11,9 @@
|
|||||||
|
|
||||||
.code32
|
.code32
|
||||||
|
|
||||||
// custom addresses, video mode info, page align modules
|
# multiboot2 header
|
||||||
.set multiboot_flags, (1 << 16) | (1 << 2) | (1 << 0)
|
|
||||||
|
|
||||||
.section .multiboot, "aw"
|
.section .multiboot, "aw"
|
||||||
multiboot_start:
|
.align 8
|
||||||
.long 0x1BADB002
|
|
||||||
.long multiboot_flags
|
|
||||||
.long -(0x1BADB002 + multiboot_flags)
|
|
||||||
|
|
||||||
.long V2P(multiboot_start)
|
|
||||||
.long V2P(g_kernel_start)
|
|
||||||
.long V2P(g_kernel_bss_start)
|
|
||||||
.long V2P(g_kernel_end)
|
|
||||||
.long V2P(_start)
|
|
||||||
|
|
||||||
.long 0
|
|
||||||
.long FB_WIDTH
|
|
||||||
.long FB_HEIGHT
|
|
||||||
.long FB_BPP
|
|
||||||
multiboot_end:
|
|
||||||
|
|
||||||
.section .multiboot2, "aw"
|
|
||||||
multiboot2_start:
|
multiboot2_start:
|
||||||
.long 0xE85250D6
|
.long 0xE85250D6
|
||||||
.long 0
|
.long 0
|
||||||
@@ -68,6 +49,7 @@ multiboot2_start:
|
|||||||
multiboot2_end:
|
multiboot2_end:
|
||||||
|
|
||||||
.section .bananboot, "aw"
|
.section .bananboot, "aw"
|
||||||
|
.align 8
|
||||||
bananboot_start:
|
bananboot_start:
|
||||||
.long 0xBABAB007
|
.long 0xBABAB007
|
||||||
.long -(0xBABAB007 + FB_WIDTH + FB_HEIGHT + FB_BPP)
|
.long -(0xBABAB007 + FB_WIDTH + FB_HEIGHT + FB_BPP)
|
||||||
@@ -180,13 +162,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
|
||||||
@@ -223,7 +198,6 @@ _start:
|
|||||||
|
|
||||||
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
|
||||||
@@ -310,7 +284,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,4 +1,4 @@
|
|||||||
.macro intr_header, n
|
.macro pushaq
|
||||||
pushq %rax
|
pushq %rax
|
||||||
pushq %rcx
|
pushq %rcx
|
||||||
pushq %rdx
|
pushq %rdx
|
||||||
@@ -14,18 +14,10 @@
|
|||||||
pushq %r13
|
pushq %r13
|
||||||
pushq %r14
|
pushq %r14
|
||||||
pushq %r15
|
pushq %r15
|
||||||
testb $3, \n+15*8(%rsp)
|
|
||||||
jz 1f
|
|
||||||
swapgs
|
|
||||||
1: cld
|
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro intr_footer, n
|
.macro popaq
|
||||||
testb $3, \n+15*8(%rsp)
|
popq %r15
|
||||||
jz 1f
|
|
||||||
call cpp_check_signal
|
|
||||||
swapgs
|
|
||||||
1: popq %r15
|
|
||||||
popq %r14
|
popq %r14
|
||||||
popq %r13
|
popq %r13
|
||||||
popq %r12
|
popq %r12
|
||||||
@@ -43,7 +35,8 @@
|
|||||||
.endm
|
.endm
|
||||||
|
|
||||||
isr_stub:
|
isr_stub:
|
||||||
intr_header 24
|
pushaq
|
||||||
|
cld
|
||||||
movq %cr0, %rax; pushq %rax
|
movq %cr0, %rax; pushq %rax
|
||||||
movq %cr2, %rax; pushq %rax
|
movq %cr2, %rax; pushq %rax
|
||||||
movq %cr3, %rax; pushq %rax
|
movq %cr3, %rax; pushq %rax
|
||||||
@@ -56,33 +49,43 @@ isr_stub:
|
|||||||
call cpp_isr_handler
|
call cpp_isr_handler
|
||||||
addq $32, %rsp
|
addq $32, %rsp
|
||||||
|
|
||||||
intr_footer 24
|
popaq
|
||||||
addq $16, %rsp
|
addq $16, %rsp
|
||||||
iretq
|
iretq
|
||||||
|
|
||||||
irq_stub:
|
irq_stub:
|
||||||
intr_header 24
|
pushaq
|
||||||
xorq %rbp, %rbp
|
cld
|
||||||
movq 120(%rsp), %rdi # irq number
|
movq 120(%rsp), %rdi # irq number
|
||||||
call cpp_irq_handler
|
call cpp_irq_handler
|
||||||
intr_footer 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:
|
||||||
intr_header 8
|
pushaq
|
||||||
xorq %rbp, %rbp
|
cld
|
||||||
call cpp_ipi_handler
|
call cpp_ipi_handler
|
||||||
intr_footer 8
|
popaq
|
||||||
iretq
|
iretq
|
||||||
|
|
||||||
.global asm_timer_handler
|
.global asm_timer_handler
|
||||||
asm_timer_handler:
|
asm_timer_handler:
|
||||||
intr_header 8
|
pushaq
|
||||||
xorq %rbp, %rbp
|
cld
|
||||||
call cpp_timer_handler
|
call cpp_timer_handler
|
||||||
intr_footer 8
|
popaq
|
||||||
iretq
|
iretq
|
||||||
|
|
||||||
.macro isr n
|
.macro isr n
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ SECTIONS
|
|||||||
{
|
{
|
||||||
g_kernel_execute_start = .;
|
g_kernel_execute_start = .;
|
||||||
*(.multiboot)
|
*(.multiboot)
|
||||||
*(.multiboot2)
|
|
||||||
*(.bananboot)
|
*(.bananboot)
|
||||||
*(.text.*)
|
*(.text.*)
|
||||||
}
|
}
|
||||||
@@ -44,7 +43,6 @@ SECTIONS
|
|||||||
}
|
}
|
||||||
.bss ALIGN(4K) : AT(ADDR(.bss) - KERNEL_OFFSET)
|
.bss ALIGN(4K) : AT(ADDR(.bss) - KERNEL_OFFSET)
|
||||||
{
|
{
|
||||||
g_kernel_bss_start = .;
|
|
||||||
*(COMMON)
|
*(COMMON)
|
||||||
*(.bss)
|
*(.bss)
|
||||||
g_kernel_writable_end = .;
|
g_kernel_writable_end = .;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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,34 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <BAN/MacroUtils.h>
|
|
||||||
|
|
||||||
#if defined(__x86_64__)
|
|
||||||
#define _kas_instruction "syscall"
|
|
||||||
#define _kas_result rax
|
|
||||||
#define _kas_arguments rdi, rsi, rdx, r10, r8, r9
|
|
||||||
#define _kas_globbers rcx, rdx, rdi, rsi, r8, r9, r10, r11
|
|
||||||
#elif defined(__i686__)
|
|
||||||
#define _kas_instruction "int $0xF0"
|
|
||||||
#define _kas_result eax
|
|
||||||
#define _kas_arguments eax, ebx, ecx, edx, esi, edi
|
|
||||||
#define _kas_globbers
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define _kas_argument_var(index, value) register long _kas_a##index asm(_ban_stringify(_ban_get(index, _kas_arguments))) = (long)value;
|
|
||||||
#define _kas_dummy_var(index, value) register long _kas_d##index asm(#value);
|
|
||||||
#define _kas_input(index, _) "r"(_kas_a##index)
|
|
||||||
#define _kas_output(index, _) , "=r"(_kas_d##index)
|
|
||||||
#define _kas_globber(_, value) #value
|
|
||||||
|
|
||||||
#define _kas_syscall(...) ({ \
|
|
||||||
register long _kas_ret asm(_ban_stringify(_kas_result)); \
|
|
||||||
_ban_for_each(_kas_argument_var, __VA_ARGS__) \
|
|
||||||
_ban_for_each(_kas_dummy_var, _kas_globbers) \
|
|
||||||
asm volatile( \
|
|
||||||
_kas_instruction \
|
|
||||||
: "=r"(_kas_ret) _ban_for_each(_kas_output, _kas_globbers) \
|
|
||||||
: _ban_for_each_comma(_kas_input, __VA_ARGS__) \
|
|
||||||
: "cc", "memory"); \
|
|
||||||
(void)_kas_a0; /* require 1 argument */ \
|
|
||||||
_kas_ret; \
|
|
||||||
})
|
|
||||||
@@ -6,10 +6,10 @@
|
|||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
class AC97AudioController final : public AudioController, public Interruptable
|
class AC97AudioController : public AudioController, public Interruptable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<void> create(PCI::Device& pci_device);
|
static BAN::ErrorOr<BAN::RefPtr<AC97AudioController>> create(PCI::Device& pci_device);
|
||||||
|
|
||||||
void handle_irq() override;
|
void handle_irq() override;
|
||||||
|
|
||||||
@@ -19,24 +19,16 @@ namespace Kernel
|
|||||||
uint32_t get_channels() const override { return 2; }
|
uint32_t get_channels() const override { return 2; }
|
||||||
uint32_t get_sample_rate() const override { return 48000; }
|
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:
|
private:
|
||||||
AC97AudioController(PCI::Device& pci_device)
|
AC97AudioController(PCI::Device& pci_device)
|
||||||
: m_pci_device(pci_device)
|
: m_pci_device(pci_device)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
uint32_t get_volume_data() const;
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> initialize();
|
BAN::ErrorOr<void> initialize();
|
||||||
BAN::ErrorOr<void> initialize_bld();
|
BAN::ErrorOr<void> initialize_bld();
|
||||||
BAN::ErrorOr<void> initialize_interrupts();
|
BAN::ErrorOr<void> initialize_interrupts();
|
||||||
|
|
||||||
bool queue_samples_to_bld();
|
void queue_samples_to_bld();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr size_t m_bdl_entries = 32;
|
static constexpr size_t m_bdl_entries = 32;
|
||||||
|
|||||||
@@ -1,39 +1,29 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <kernel/Device/Device.h>
|
#include <kernel/Device/Device.h>
|
||||||
#include <kernel/Memory/ByteRingBuffer.h>
|
|
||||||
#include <kernel/PCI.h>
|
#include <kernel/PCI.h>
|
||||||
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
class AudioController : public CharacterDevice
|
class AudioController : public CharacterDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<void> create(PCI::Device& pci_device);
|
static BAN::ErrorOr<BAN::RefPtr<AudioController>> create(PCI::Device& pci_device);
|
||||||
|
|
||||||
dev_t rdev() const override { return m_rdev; }
|
dev_t rdev() const override { return m_rdev; }
|
||||||
BAN::StringView name() const override { return m_name; }
|
BAN::StringView name() const override { return m_name; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
AudioController();
|
AudioController();
|
||||||
BAN::ErrorOr<void> initialize();
|
|
||||||
|
|
||||||
virtual void handle_new_data() = 0;
|
virtual void handle_new_data() = 0;
|
||||||
|
|
||||||
virtual uint32_t get_channels() const = 0;
|
virtual uint32_t get_channels() const = 0;
|
||||||
virtual uint32_t get_sample_rate() 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_read_impl() const override { return false; }
|
||||||
bool can_write_impl() const override { SpinLockGuard _(m_spinlock); return !m_sample_data->full(); }
|
bool can_write_impl() const override { SpinLockGuard _(m_spinlock); return m_sample_data_size < m_sample_data_capacity; }
|
||||||
bool has_error_impl() const override { return false; }
|
bool has_error_impl() const override { return false; }
|
||||||
bool has_hungup_impl() const override { return false; }
|
bool has_hungup_impl() const override { return false; }
|
||||||
|
|
||||||
@@ -46,9 +36,9 @@ namespace Kernel
|
|||||||
mutable SpinLock m_spinlock;
|
mutable SpinLock m_spinlock;
|
||||||
|
|
||||||
static constexpr size_t m_sample_data_capacity = 1 << 20;
|
static constexpr size_t m_sample_data_capacity = 1 << 20;
|
||||||
BAN::UniqPtr<ByteRingBuffer> m_sample_data;
|
uint8_t m_sample_data[m_sample_data_capacity];
|
||||||
|
size_t m_sample_data_head { 0 };
|
||||||
snd_volume_info m_volume_info {};
|
size_t m_sample_data_size { 0 };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const dev_t m_rdev;
|
const dev_t m_rdev;
|
||||||
|
|||||||
@@ -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,
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -44,7 +44,7 @@ namespace Kernel
|
|||||||
struct BootModule
|
struct BootModule
|
||||||
{
|
{
|
||||||
paddr_t start;
|
paddr_t start;
|
||||||
uint64_t size;
|
size_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BootInfo
|
struct BootInfo
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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,7 +16,6 @@ namespace Kernel
|
|||||||
Debug,
|
Debug,
|
||||||
Keyboard,
|
Keyboard,
|
||||||
Mouse,
|
Mouse,
|
||||||
Joystick,
|
|
||||||
SCSI,
|
SCSI,
|
||||||
NVMeController,
|
NVMeController,
|
||||||
NVMeNamespace,
|
NVMeNamespace,
|
||||||
|
|||||||
@@ -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; }
|
||||||
@@ -28,7 +27,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(); }
|
||||||
@@ -37,8 +36,6 @@ 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;
|
||||||
|
|
||||||
BAN::ErrorOr<long> ioctl_impl(int cmd, void* arg) 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; }
|
||||||
|
|||||||
@@ -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&);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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:
|
||||||
@@ -94,7 +79,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 +102,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 +113,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;
|
||||||
@@ -61,18 +60,18 @@ namespace Kernel
|
|||||||
// 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 +84,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;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace Kernel
|
|||||||
|
|
||||||
class FileBackedRegion;
|
class FileBackedRegion;
|
||||||
class FileSystem;
|
class FileSystem;
|
||||||
struct SharedFileData;
|
class SharedFileData;
|
||||||
|
|
||||||
class Inode : public BAN::RefCounted<Inode>
|
class Inode : public BAN::RefCounted<Inode>
|
||||||
{
|
{
|
||||||
@@ -97,7 +97,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 +108,10 @@ 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> 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);
|
||||||
@@ -147,7 +144,6 @@ namespace Kernel
|
|||||||
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
|
||||||
@@ -159,12 +155,10 @@ 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> 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); }
|
||||||
@@ -193,7 +187,7 @@ namespace Kernel
|
|||||||
friend class Epoll;
|
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
|
||||||
@@ -39,7 +38,7 @@ 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 m_reading_count == 0; }
|
||||||
virtual bool has_hungup_impl() const override { return m_writing_count == 0; }
|
virtual bool has_hungup_impl() const override { return m_writing_count == 0; }
|
||||||
@@ -55,7 +54,9 @@ 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 };
|
BAN::Atomic<uint32_t> m_reading_count { 1 };
|
||||||
|
|||||||
@@ -57,31 +57,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:
|
||||||
@@ -107,57 +82,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
|
||||||
|
|||||||
@@ -156,8 +156,6 @@ 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; }
|
||||||
@@ -169,8 +167,6 @@ namespace Kernel
|
|||||||
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,11 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <kernel/BootInfo.h>
|
#include <kernel/BootInfo.h>
|
||||||
#include <kernel/FS/Inode.h>
|
#include <kernel/FS/FileSystem.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
BAN::ErrorOr<bool> unpack_boot_module_into_directory(BAN::RefPtr<Inode>, const BootModule&);
|
bool is_ustar_boot_module(const BootModule&);
|
||||||
|
BAN::ErrorOr<void> unpack_boot_module_into_filesystem(BAN::RefPtr<FileSystem>, const BootModule&);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,13 +71,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;
|
constexpr uint8_t IRQ_SYSCALL = 0xF0;
|
||||||
#if ARCH(i686)
|
constexpr uint8_t IRQ_YIELD = 0xF1;
|
||||||
constexpr uint8_t IRQ_SYSCALL = 0xF0; // hard coded in kernel/API/Syscall.h
|
constexpr uint8_t IRQ_IPI = 0xF2;
|
||||||
#endif
|
constexpr uint8_t IRQ_TIMER = 0xF3;
|
||||||
constexpr uint8_t IRQ_IPI = 0xF1;
|
|
||||||
constexpr uint8_t IRQ_TIMER = 0xF2;
|
|
||||||
|
|
||||||
#if ARCH(x86_64)
|
#if ARCH(x86_64)
|
||||||
struct GateDescriptor
|
struct GateDescriptor
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
Mouse,
|
Mouse,
|
||||||
Keyboard,
|
Keyboard,
|
||||||
Joystick,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -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,12 +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> identify_device(uint8_t, uint8_t scancode_set);
|
||||||
|
|
||||||
void device_initialize_task(void*);
|
void device_initialize_task(void*);
|
||||||
|
|
||||||
@@ -72,9 +61,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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ namespace Kernel
|
|||||||
static void initialize();
|
static void initialize();
|
||||||
static Heap& get();
|
static Heap& get();
|
||||||
|
|
||||||
void release_boot_modules();
|
|
||||||
|
|
||||||
paddr_t take_free_page();
|
paddr_t take_free_page();
|
||||||
void release_page(paddr_t);
|
void release_page(paddr_t);
|
||||||
|
|
||||||
|
|||||||
@@ -11,37 +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);
|
||||||
|
|
||||||
private:
|
|
||||||
struct PhysicalPage
|
|
||||||
{
|
|
||||||
PhysicalPage(paddr_t paddr)
|
|
||||||
: paddr(paddr)
|
|
||||||
{ }
|
|
||||||
~PhysicalPage();
|
|
||||||
|
|
||||||
BAN::Atomic<uint32_t> ref_count { 1 };
|
|
||||||
const paddr_t paddr;
|
|
||||||
};
|
|
||||||
BAN::Vector<PhysicalPage*> m_physical_pages;
|
|
||||||
Mutex m_mutex;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,17 +33,12 @@ 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; }
|
||||||
|
|
||||||
@@ -51,7 +46,6 @@ namespace Kernel
|
|||||||
void unpin();
|
void unpin();
|
||||||
void wait_not_pinned();
|
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,20 +54,18 @@ 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 };
|
||||||
|
|
||||||
|
|||||||
@@ -100,21 +100,19 @@ namespace Kernel
|
|||||||
static BAN::ErrorOr<PageTable*> create_userspace();
|
static BAN::ErrorOr<PageTable*> create_userspace();
|
||||||
~PageTable();
|
~PageTable();
|
||||||
|
|
||||||
void unmap_page(vaddr_t, bool invalidate = true);
|
void unmap_page(vaddr_t, bool send_smp_message = true);
|
||||||
void unmap_range(vaddr_t, size_t bytes);
|
void unmap_range(vaddr_t, size_t bytes);
|
||||||
|
|
||||||
void map_page_at(paddr_t, vaddr_t, flags_t, MemoryType = MemoryType::Normal, bool invalidate = true);
|
void map_page_at(paddr_t, vaddr_t, flags_t, MemoryType = MemoryType::Normal, bool send_smp_message = true);
|
||||||
void map_range_at(paddr_t, vaddr_t, size_t bytes, flags_t, MemoryType = MemoryType::Normal);
|
void map_range_at(paddr_t, vaddr_t, size_t bytes, flags_t, MemoryType = MemoryType::Normal);
|
||||||
|
|
||||||
void remove_writable_from_range(vaddr_t, size_t);
|
|
||||||
|
|
||||||
paddr_t physical_address_of(vaddr_t) const;
|
paddr_t physical_address_of(vaddr_t) const;
|
||||||
flags_t get_page_flags(vaddr_t) const;
|
flags_t get_page_flags(vaddr_t) const;
|
||||||
|
|
||||||
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 invalidate = 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);
|
||||||
@@ -123,9 +121,6 @@ namespace Kernel
|
|||||||
void load();
|
void load();
|
||||||
void initial_load();
|
void initial_load();
|
||||||
|
|
||||||
void invalidate_page(vaddr_t addr, bool send_smp_message) { invalidate_range(addr, 1, send_smp_message); }
|
|
||||||
void invalidate_range(vaddr_t addr, size_t pages, bool send_smp_message);
|
|
||||||
|
|
||||||
InterruptState lock() const { return m_lock.lock(); }
|
InterruptState lock() const { return m_lock.lock(); }
|
||||||
void unlock(InterruptState state) const { m_lock.unlock(state); }
|
void unlock(InterruptState state) const { m_lock.unlock(state); }
|
||||||
|
|
||||||
@@ -138,6 +133,8 @@ namespace Kernel
|
|||||||
void map_kernel_memory();
|
void map_kernel_memory();
|
||||||
void prepare_fast_page();
|
void prepare_fast_page();
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace Kernel
|
|||||||
class PhysicalRange
|
class PhysicalRange
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PhysicalRange(paddr_t, uint64_t);
|
PhysicalRange(paddr_t, size_t);
|
||||||
|
|
||||||
paddr_t reserve_page();
|
paddr_t reserve_page();
|
||||||
void release_page(paddr_t);
|
void release_page(paddr_t);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ namespace Kernel
|
|||||||
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, bool add_guard_pages);
|
||||||
~VirtualRange();
|
~VirtualRange();
|
||||||
|
|
||||||
|
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 + (m_has_guard_pages ? PAGE_SIZE : 0); }
|
||||||
size_t size() const { return m_size - (m_has_guard_pages ? 2 * PAGE_SIZE : 0); }
|
size_t size() const { return m_size - (m_has_guard_pages ? 2 * PAGE_SIZE : 0); }
|
||||||
PageTable::flags_t flags() const { return m_flags; }
|
PageTable::flags_t flags() const { return m_flags; }
|
||||||
@@ -36,7 +38,7 @@ 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, bool has_guard_pages, vaddr_t, size_t, PageTable::flags_t);
|
||||||
|
|||||||
@@ -31,18 +31,35 @@ namespace Kernel
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<ARPTable>> create();
|
static BAN::ErrorOr<BAN::UniqPtr<ARPTable>> create();
|
||||||
|
~ARPTable();
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::MACAddress> get_mac_from_ipv4(NetworkInterface&, BAN::IPv4Address);
|
BAN::ErrorOr<BAN::MACAddress> get_mac_from_ipv4(NetworkInterface&, BAN::IPv4Address);
|
||||||
|
|
||||||
BAN::ErrorOr<void> handle_arp_packet(NetworkInterface&, BAN::ConstByteSpan);
|
void add_arp_packet(NetworkInterface&, BAN::ConstByteSpan);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ARPTable() = default;
|
ARPTable();
|
||||||
|
|
||||||
|
void packet_handle_task();
|
||||||
|
BAN::ErrorOr<void> handle_arp_packet(NetworkInterface&, const ARPPacket&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SpinLock m_arp_table_lock;
|
struct PendingArpPacket
|
||||||
|
{
|
||||||
|
NetworkInterface& interface;
|
||||||
|
ARPPacket packet;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
SpinLock m_table_lock;
|
||||||
|
SpinLock m_pending_lock;
|
||||||
|
|
||||||
BAN::HashMap<BAN::IPv4Address, BAN::MACAddress> m_arp_table;
|
BAN::HashMap<BAN::IPv4Address, BAN::MACAddress> m_arp_table;
|
||||||
|
|
||||||
|
Thread* m_thread { nullptr };
|
||||||
|
BAN::CircularQueue<PendingArpPacket, 128> m_pending_packets;
|
||||||
|
ThreadBlocker m_pending_thread_blocker;
|
||||||
|
|
||||||
friend class BAN::UniqPtr<ARPTable>;
|
friend class BAN::UniqPtr<ARPTable>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -23,14 +23,14 @@ namespace Kernel
|
|||||||
static BAN::ErrorOr<BAN::RefPtr<E1000>> create(PCI::Device&);
|
static BAN::ErrorOr<BAN::RefPtr<E1000>> create(PCI::Device&);
|
||||||
~E1000();
|
~E1000();
|
||||||
|
|
||||||
BAN::MACAddress get_mac_address() const override { return m_mac_address; }
|
virtual BAN::MACAddress get_mac_address() const override { return m_mac_address; }
|
||||||
|
|
||||||
bool link_up() override { return m_link_up; }
|
virtual bool link_up() override { return m_link_up; }
|
||||||
int link_speed() override;
|
virtual int link_speed() override;
|
||||||
|
|
||||||
size_t payload_mtu() const override { return E1000_RX_BUFFER_SIZE - sizeof(EthernetHeader); }
|
virtual size_t payload_mtu() const override { return E1000_RX_BUFFER_SIZE - sizeof(EthernetHeader); }
|
||||||
|
|
||||||
void handle_irq() final override;
|
virtual void handle_irq() final override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
E1000(PCI::Device& pci_device)
|
E1000(PCI::Device& pci_device)
|
||||||
@@ -45,12 +45,12 @@ namespace Kernel
|
|||||||
uint32_t read32(uint16_t reg);
|
uint32_t read32(uint16_t reg);
|
||||||
void write32(uint16_t reg, uint32_t value);
|
void write32(uint16_t reg, uint32_t value);
|
||||||
|
|
||||||
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) override;
|
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan) override;
|
||||||
|
|
||||||
bool can_read_impl() const override { return false; }
|
virtual bool can_read_impl() const override { return false; }
|
||||||
bool can_write_impl() const override { return false; }
|
virtual bool can_write_impl() const override { return false; }
|
||||||
bool has_error_impl() const override { return false; }
|
virtual bool has_error_impl() const override { return false; }
|
||||||
bool has_hungup_impl() const override { return false; }
|
virtual bool has_hungup_impl() const override { return false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BAN::ErrorOr<void> read_mac_address();
|
BAN::ErrorOr<void> read_mac_address();
|
||||||
@@ -61,7 +61,7 @@ namespace Kernel
|
|||||||
void enable_link();
|
void enable_link();
|
||||||
BAN::ErrorOr<void> enable_interrupt();
|
BAN::ErrorOr<void> enable_interrupt();
|
||||||
|
|
||||||
void receive_thread();
|
void handle_receive();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PCI::Device& m_pci_device;
|
PCI::Device& m_pci_device;
|
||||||
@@ -75,10 +75,6 @@ namespace Kernel
|
|||||||
BAN::UniqPtr<DMARegion> m_tx_descriptor_region;
|
BAN::UniqPtr<DMARegion> m_tx_descriptor_region;
|
||||||
SpinLock m_lock;
|
SpinLock m_lock;
|
||||||
|
|
||||||
bool m_thread_should_die { false };
|
|
||||||
BAN::Atomic<bool> m_thread_is_dead { true };
|
|
||||||
ThreadBlocker m_thread_blocker;
|
|
||||||
|
|
||||||
BAN::MACAddress m_mac_address {};
|
BAN::MACAddress m_mac_address {};
|
||||||
bool m_link_up { false };
|
bool m_link_up { false };
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ namespace Kernel
|
|||||||
static BAN::ErrorOr<BAN::RefPtr<E1000E>> create(PCI::Device&);
|
static BAN::ErrorOr<BAN::RefPtr<E1000E>> create(PCI::Device&);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void detect_eeprom() override;
|
virtual void detect_eeprom() override;
|
||||||
uint32_t eeprom_read(uint8_t addr) override;
|
virtual uint32_t eeprom_read(uint8_t addr) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
E1000E(PCI::Device& pci_device)
|
E1000E(PCI::Device& pci_device)
|
||||||
|
|||||||
@@ -38,13 +38,14 @@ namespace Kernel
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<IPv4Layer>> create();
|
static BAN::ErrorOr<BAN::UniqPtr<IPv4Layer>> create();
|
||||||
|
~IPv4Layer();
|
||||||
|
|
||||||
ARPTable& arp_table() { return *m_arp_table; }
|
ARPTable& arp_table() { return *m_arp_table; }
|
||||||
|
|
||||||
BAN::ErrorOr<void> handle_ipv4_packet(NetworkInterface&, BAN::ConstByteSpan);
|
void add_ipv4_packet(NetworkInterface&, BAN::ConstByteSpan);
|
||||||
|
|
||||||
virtual void unbind_socket(uint16_t port) override;
|
virtual void unbind_socket(uint16_t port) override;
|
||||||
virtual BAN::ErrorOr<void> bind_socket_with_target(BAN::RefPtr<NetworkSocket>, const sockaddr* target_address, socklen_t target_address_len) override;
|
virtual BAN::ErrorOr<void> bind_socket_to_unused(BAN::RefPtr<NetworkSocket>, const sockaddr* send_address, socklen_t send_address_len) override;
|
||||||
virtual BAN::ErrorOr<void> bind_socket_to_address(BAN::RefPtr<NetworkSocket>, const sockaddr* address, socklen_t address_len) override;
|
virtual BAN::ErrorOr<void> bind_socket_to_address(BAN::RefPtr<NetworkSocket>, const sockaddr* address, socklen_t address_len) override;
|
||||||
virtual BAN::ErrorOr<void> get_socket_address(BAN::RefPtr<NetworkSocket>, sockaddr* address, socklen_t* address_len) override;
|
virtual BAN::ErrorOr<void> get_socket_address(BAN::RefPtr<NetworkSocket>, sockaddr* address, socklen_t* address_len) override;
|
||||||
|
|
||||||
@@ -54,14 +55,32 @@ namespace Kernel
|
|||||||
virtual size_t header_size() const override { return sizeof(IPv4Header); }
|
virtual size_t header_size() const override { return sizeof(IPv4Header); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IPv4Layer() = default;
|
IPv4Layer();
|
||||||
|
|
||||||
BAN::ErrorOr<in_port_t> find_free_port();
|
void add_ipv4_header(BAN::ByteSpan packet, BAN::IPv4Address src_ipv4, BAN::IPv4Address dst_ipv4, uint8_t protocol) const;
|
||||||
|
|
||||||
|
void packet_handle_task();
|
||||||
|
BAN::ErrorOr<void> handle_ipv4_packet(NetworkInterface&, BAN::ByteSpan);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BAN::UniqPtr<ARPTable> m_arp_table;
|
struct PendingIPv4Packet
|
||||||
|
{
|
||||||
|
NetworkInterface& interface;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
RecursiveSpinLock m_bound_socket_lock;
|
RecursiveSpinLock m_bound_socket_lock;
|
||||||
|
|
||||||
|
BAN::UniqPtr<ARPTable> m_arp_table;
|
||||||
|
Thread* m_thread { nullptr };
|
||||||
|
|
||||||
|
static constexpr size_t pending_packet_buffer_size = 128 * PAGE_SIZE;
|
||||||
|
BAN::UniqPtr<VirtualRange> m_pending_packet_buffer;
|
||||||
|
BAN::CircularQueue<PendingIPv4Packet, 128> m_pending_packets;
|
||||||
|
ThreadBlocker m_pending_thread_blocker;
|
||||||
|
SpinLock m_pending_lock;
|
||||||
|
size_t m_pending_total_size { 0 };
|
||||||
|
|
||||||
BAN::HashMap<int, BAN::WeakPtr<NetworkSocket>> m_bound_sockets;
|
BAN::HashMap<int, BAN::WeakPtr<NetworkSocket>> m_bound_sockets;
|
||||||
|
|
||||||
friend class BAN::UniqPtr<IPv4Layer>;
|
friend class BAN::UniqPtr<IPv4Layer>;
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr size_t buffer_size = BAN::numeric_limits<uint16_t>::max() + 1;
|
static constexpr size_t buffer_size = BAN::numeric_limits<uint16_t>::max() + 1;
|
||||||
static constexpr size_t buffer_count = 32;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::RefPtr<LoopbackInterface>> create();
|
static BAN::ErrorOr<BAN::RefPtr<LoopbackInterface>> create();
|
||||||
@@ -25,9 +24,8 @@ namespace Kernel
|
|||||||
LoopbackInterface()
|
LoopbackInterface()
|
||||||
: NetworkInterface(Type::Loopback)
|
: NetworkInterface(Type::Loopback)
|
||||||
{}
|
{}
|
||||||
~LoopbackInterface();
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) override;
|
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan) override;
|
||||||
|
|
||||||
bool can_read_impl() const override { return false; }
|
bool can_read_impl() const override { return false; }
|
||||||
bool can_write_impl() const override { return false; }
|
bool can_write_impl() const override { return false; }
|
||||||
@@ -35,27 +33,8 @@ namespace Kernel
|
|||||||
bool has_hungup_impl() const override { return false; }
|
bool has_hungup_impl() const override { return false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void receive_thread();
|
SpinLock m_buffer_lock;
|
||||||
|
|
||||||
private:
|
|
||||||
struct Descriptor
|
|
||||||
{
|
|
||||||
uint8_t* addr;
|
|
||||||
uint32_t size;
|
|
||||||
uint8_t state;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
Mutex m_buffer_lock;
|
|
||||||
BAN::UniqPtr<VirtualRange> m_buffer;
|
BAN::UniqPtr<VirtualRange> m_buffer;
|
||||||
|
|
||||||
uint32_t m_buffer_tail { 0 };
|
|
||||||
uint32_t m_buffer_head { 0 };
|
|
||||||
Descriptor m_descriptors[buffer_count] {};
|
|
||||||
|
|
||||||
bool m_thread_should_die { false };
|
|
||||||
BAN::Atomic<bool> m_thread_is_dead { true };
|
|
||||||
ThreadBlocker m_thread_blocker;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,11 +60,7 @@ namespace Kernel
|
|||||||
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; }
|
virtual BAN::StringView name() const override { return m_name; }
|
||||||
|
|
||||||
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan payload)
|
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan) = 0;
|
||||||
{
|
|
||||||
return send_bytes(destination, protocol, { &payload, 1 });
|
|
||||||
}
|
|
||||||
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) = 0;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Type m_type;
|
const Type m_type;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace Kernel
|
|||||||
BAN::IPv4Address src_ipv4 { 0 };
|
BAN::IPv4Address src_ipv4 { 0 };
|
||||||
BAN::IPv4Address dst_ipv4 { 0 };
|
BAN::IPv4Address dst_ipv4 { 0 };
|
||||||
BAN::NetworkEndian<uint16_t> protocol { 0 };
|
BAN::NetworkEndian<uint16_t> protocol { 0 };
|
||||||
BAN::NetworkEndian<uint16_t> length { 0 };
|
BAN::NetworkEndian<uint16_t> extra { 0 };
|
||||||
};
|
};
|
||||||
static_assert(sizeof(PseudoHeader) == 12);
|
static_assert(sizeof(PseudoHeader) == 12);
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ namespace Kernel
|
|||||||
virtual ~NetworkLayer() {}
|
virtual ~NetworkLayer() {}
|
||||||
|
|
||||||
virtual void unbind_socket(uint16_t port) = 0;
|
virtual void unbind_socket(uint16_t port) = 0;
|
||||||
virtual BAN::ErrorOr<void> bind_socket_with_target(BAN::RefPtr<NetworkSocket>, const sockaddr* target_address, socklen_t target_address_len) = 0;
|
virtual BAN::ErrorOr<void> bind_socket_to_unused(BAN::RefPtr<NetworkSocket>, const sockaddr* send_address, socklen_t send_address_len) = 0;
|
||||||
virtual BAN::ErrorOr<void> bind_socket_to_address(BAN::RefPtr<NetworkSocket>, const sockaddr* address, socklen_t address_len) = 0;
|
virtual BAN::ErrorOr<void> bind_socket_to_address(BAN::RefPtr<NetworkSocket>, const sockaddr* address, socklen_t address_len) = 0;
|
||||||
virtual BAN::ErrorOr<void> get_socket_address(BAN::RefPtr<NetworkSocket>, sockaddr* address, socklen_t* address_len) = 0;
|
virtual BAN::ErrorOr<void> get_socket_address(BAN::RefPtr<NetworkSocket>, sockaddr* address, socklen_t* address_len) = 0;
|
||||||
|
|
||||||
@@ -36,7 +36,6 @@ namespace Kernel
|
|||||||
NetworkLayer() = default;
|
NetworkLayer() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint16_t calculate_internet_checksum(BAN::ConstByteSpan buffer);
|
uint16_t calculate_internet_checksum(BAN::ConstByteSpan packet, const PseudoHeader& pseudo_header);
|
||||||
uint16_t calculate_internet_checksum(BAN::Span<const BAN::ConstByteSpan> buffers);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
#include <kernel/Networking/NetworkInterface.h>
|
#include <kernel/Networking/NetworkInterface.h>
|
||||||
#include <kernel/Networking/NetworkLayer.h>
|
#include <kernel/Networking/NetworkLayer.h>
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -26,30 +24,18 @@ namespace Kernel
|
|||||||
static constexpr uint16_t PORT_NONE = 0;
|
static constexpr uint16_t PORT_NONE = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void bind_address_and_port(const sockaddr*, socklen_t);
|
void bind_interface_and_port(NetworkInterface*, uint16_t port);
|
||||||
~NetworkSocket();
|
~NetworkSocket();
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::RefPtr<NetworkInterface>> interface(const sockaddr* target, socklen_t target_len);
|
NetworkInterface& interface() { ASSERT(m_interface); return *m_interface; }
|
||||||
|
|
||||||
virtual size_t protocol_header_size() const = 0;
|
virtual size_t protocol_header_size() const = 0;
|
||||||
virtual void get_protocol_header(BAN::ByteSpan header, BAN::ConstByteSpan payload, uint16_t dst_port, PseudoHeader) = 0;
|
virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader) = 0;
|
||||||
virtual NetworkProtocol protocol() const = 0;
|
virtual NetworkProtocol protocol() const = 0;
|
||||||
|
|
||||||
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) = 0;
|
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) = 0;
|
||||||
|
|
||||||
bool is_bound() const { return m_address_len >= static_cast<socklen_t>(sizeof(sa_family_t)) && m_address.ss_family != AF_UNSPEC; }
|
bool is_bound() const { return m_interface != nullptr; }
|
||||||
in_port_t bound_port() const
|
|
||||||
{
|
|
||||||
ASSERT(is_bound());
|
|
||||||
ASSERT(m_address.ss_family == AF_INET && m_address_len >= static_cast<socklen_t>(sizeof(sockaddr_in)));
|
|
||||||
return BAN::network_endian_to_host(reinterpret_cast<const sockaddr_in*>(&m_address)->sin_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
const sockaddr* address() const { return reinterpret_cast<const sockaddr*>(&m_address); }
|
|
||||||
socklen_t address_len() const { return m_address_len; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool can_interface_send_to(const NetworkInterface&, const sockaddr*, socklen_t) const;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NetworkSocket(NetworkLayer&, const Socket::Info&);
|
NetworkSocket(NetworkLayer&, const Socket::Info&);
|
||||||
@@ -60,8 +46,8 @@ namespace Kernel
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
NetworkLayer& m_network_layer;
|
NetworkLayer& m_network_layer;
|
||||||
sockaddr_storage m_address { .ss_family = AF_UNSPEC, .ss_storage = {} };
|
NetworkInterface* m_interface = nullptr;
|
||||||
socklen_t m_address_len { 0 };
|
uint16_t m_port { PORT_NONE };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,11 +29,9 @@ namespace Kernel
|
|||||||
: NetworkInterface(Type::Ethernet)
|
: NetworkInterface(Type::Ethernet)
|
||||||
, m_pci_device(pci_device)
|
, m_pci_device(pci_device)
|
||||||
{ }
|
{ }
|
||||||
~RTL8169();
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> initialize();
|
BAN::ErrorOr<void> initialize();
|
||||||
|
|
||||||
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan>) override;
|
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan) 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; }
|
||||||
@@ -49,7 +47,7 @@ namespace Kernel
|
|||||||
void enable_link();
|
void enable_link();
|
||||||
BAN::ErrorOr<void> enable_interrupt();
|
BAN::ErrorOr<void> enable_interrupt();
|
||||||
|
|
||||||
void receive_thread();
|
void handle_receive();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PCI::Device& m_pci_device;
|
PCI::Device& m_pci_device;
|
||||||
@@ -65,9 +63,6 @@ namespace Kernel
|
|||||||
BAN::UniqPtr<DMARegion> m_tx_descriptor_region;
|
BAN::UniqPtr<DMARegion> m_tx_descriptor_region;
|
||||||
|
|
||||||
SpinLock m_lock;
|
SpinLock m_lock;
|
||||||
|
|
||||||
bool m_thread_should_die { false };
|
|
||||||
BAN::Atomic<bool> m_thread_is_dead { true };
|
|
||||||
ThreadBlocker m_thread_blocker;
|
ThreadBlocker m_thread_blocker;
|
||||||
|
|
||||||
uint32_t m_rx_current { 0 };
|
uint32_t m_rx_current { 0 };
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <BAN/HashMap.h>
|
|
||||||
#include <BAN/Endianness.h>
|
#include <BAN/Endianness.h>
|
||||||
#include <BAN/Queue.h>
|
#include <BAN/Queue.h>
|
||||||
#include <kernel/Lock/Mutex.h>
|
#include <kernel/Lock/Mutex.h>
|
||||||
#include <kernel/Memory/ByteRingBuffer.h>
|
#include <kernel/Memory/VirtualRange.h>
|
||||||
#include <kernel/Networking/NetworkInterface.h>
|
#include <kernel/Networking/NetworkInterface.h>
|
||||||
#include <kernel/Networking/NetworkSocket.h>
|
#include <kernel/Networking/NetworkSocket.h>
|
||||||
#include <kernel/Thread.h>
|
#include <kernel/Thread.h>
|
||||||
@@ -50,30 +49,26 @@ namespace Kernel
|
|||||||
static BAN::ErrorOr<BAN::RefPtr<TCPSocket>> create(NetworkLayer&, const Info&);
|
static BAN::ErrorOr<BAN::RefPtr<TCPSocket>> create(NetworkLayer&, const Info&);
|
||||||
~TCPSocket();
|
~TCPSocket();
|
||||||
|
|
||||||
NetworkProtocol protocol() const override { return NetworkProtocol::TCP; }
|
virtual NetworkProtocol protocol() const override { return NetworkProtocol::TCP; }
|
||||||
|
|
||||||
size_t protocol_header_size() const override { return sizeof(TCPHeader) + m_tcp_options_bytes; }
|
virtual size_t protocol_header_size() const override { return sizeof(TCPHeader) + m_tcp_options_bytes; }
|
||||||
void get_protocol_header(BAN::ByteSpan header, BAN::ConstByteSpan payload, uint16_t dst_port, PseudoHeader) override;
|
virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BAN::ErrorOr<long> accept_impl(sockaddr*, socklen_t*, int) override;
|
virtual BAN::ErrorOr<long> accept_impl(sockaddr*, socklen_t*, int) override;
|
||||||
BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override;
|
virtual BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override;
|
||||||
BAN::ErrorOr<void> listen_impl(int) override;
|
virtual BAN::ErrorOr<void> listen_impl(int) override;
|
||||||
BAN::ErrorOr<void> bind_impl(const sockaddr*, socklen_t) override;
|
virtual BAN::ErrorOr<void> bind_impl(const sockaddr*, socklen_t) override;
|
||||||
BAN::ErrorOr<size_t> recvmsg_impl(msghdr& message, int flags) override;
|
virtual BAN::ErrorOr<size_t> sendto_impl(BAN::ConstByteSpan, const sockaddr*, socklen_t) override;
|
||||||
BAN::ErrorOr<size_t> sendmsg_impl(const msghdr& message, int flags) override;
|
virtual BAN::ErrorOr<size_t> recvfrom_impl(BAN::ByteSpan, sockaddr*, socklen_t*) override;
|
||||||
BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override;
|
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override;
|
||||||
BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
|
|
||||||
BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) override;
|
|
||||||
|
|
||||||
BAN::ErrorOr<long> ioctl_impl(int, void*) override;
|
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) override;
|
||||||
|
|
||||||
void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) override;
|
virtual bool can_read_impl() const override;
|
||||||
|
virtual bool can_write_impl() const override;
|
||||||
bool can_read_impl() const override;
|
virtual bool has_error_impl() const override { return false; }
|
||||||
bool can_write_impl() const override;
|
virtual bool has_hungup_impl() const override;
|
||||||
bool has_error_impl() const override { return false; }
|
|
||||||
bool has_hungup_impl() const override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class State
|
enum class State
|
||||||
@@ -97,8 +92,9 @@ namespace Kernel
|
|||||||
|
|
||||||
bool has_ghost_byte { false };
|
bool has_ghost_byte { false };
|
||||||
|
|
||||||
|
uint32_t data_size { 0 }; // number of bytes in this buffer
|
||||||
uint8_t scale_shift { 0 }; // window scale
|
uint8_t scale_shift { 0 }; // window scale
|
||||||
BAN::UniqPtr<ByteRingBuffer> buffer;
|
BAN::UniqPtr<VirtualRange> buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SendWindowInfo
|
struct SendWindowInfo
|
||||||
@@ -115,10 +111,10 @@ namespace Kernel
|
|||||||
uint64_t last_send_ms { 0 }; // last send time, used for retransmission timeout
|
uint64_t last_send_ms { 0 }; // last send time, used for retransmission timeout
|
||||||
|
|
||||||
bool has_ghost_byte { false };
|
bool has_ghost_byte { false };
|
||||||
bool had_zero_window { false };
|
|
||||||
|
|
||||||
|
uint32_t data_size { 0 }; // number of bytes in this buffer
|
||||||
uint32_t sent_size { 0 }; // number of bytes in this buffer that have been sent
|
uint32_t sent_size { 0 }; // number of bytes in this buffer that have been sent
|
||||||
BAN::UniqPtr<ByteRingBuffer> buffer;
|
BAN::UniqPtr<VirtualRange> buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ConnectionInfo
|
struct ConnectionInfo
|
||||||
@@ -132,8 +128,6 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
ConnectionInfo target;
|
ConnectionInfo target;
|
||||||
uint32_t target_start_seq;
|
uint32_t target_start_seq;
|
||||||
uint16_t maximum_seqment_size;
|
|
||||||
uint8_t window_scale;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ListenKey
|
struct ListenKey
|
||||||
@@ -168,17 +162,8 @@ namespace Kernel
|
|||||||
State m_next_state { State::Closed };
|
State m_next_state { State::Closed };
|
||||||
uint8_t m_next_flags { 0 };
|
uint8_t m_next_flags { 0 };
|
||||||
|
|
||||||
size_t m_last_sent_window_size { 0 };
|
|
||||||
|
|
||||||
Thread* m_thread { nullptr };
|
Thread* m_thread { nullptr };
|
||||||
|
|
||||||
// TODO: actually support these
|
|
||||||
bool m_keep_alive { false };
|
|
||||||
bool m_no_delay { false };
|
|
||||||
|
|
||||||
bool m_should_send_zero_window { false };
|
|
||||||
bool m_should_send_window_update { false };
|
|
||||||
|
|
||||||
uint64_t m_time_wait_start_ms { 0 };
|
uint64_t m_time_wait_start_ms { 0 };
|
||||||
|
|
||||||
ThreadBlocker m_thread_blocker;
|
ThreadBlocker m_thread_blocker;
|
||||||
|
|||||||
@@ -25,28 +25,23 @@ namespace Kernel
|
|||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::RefPtr<UDPSocket>> create(NetworkLayer&, const Socket::Info&);
|
static BAN::ErrorOr<BAN::RefPtr<UDPSocket>> create(NetworkLayer&, const Socket::Info&);
|
||||||
|
|
||||||
NetworkProtocol protocol() const override { return NetworkProtocol::UDP; }
|
virtual NetworkProtocol protocol() const override { return NetworkProtocol::UDP; }
|
||||||
|
|
||||||
size_t protocol_header_size() const override { return sizeof(UDPHeader); }
|
virtual size_t protocol_header_size() const override { return sizeof(UDPHeader); }
|
||||||
void get_protocol_header(BAN::ByteSpan header, BAN::ConstByteSpan payload, uint16_t dst_port, PseudoHeader) override;
|
virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) override;
|
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) override;
|
||||||
|
|
||||||
BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override;
|
virtual BAN::ErrorOr<void> bind_impl(const sockaddr* address, socklen_t address_len) override;
|
||||||
BAN::ErrorOr<void> bind_impl(const sockaddr* address, socklen_t address_len) override;
|
virtual BAN::ErrorOr<size_t> sendto_impl(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len) override;
|
||||||
BAN::ErrorOr<size_t> recvmsg_impl(msghdr& message, int flags) override;
|
virtual BAN::ErrorOr<size_t> recvfrom_impl(BAN::ByteSpan buffer, sockaddr* address, socklen_t* address_len) override;
|
||||||
BAN::ErrorOr<size_t> sendmsg_impl(const msghdr& message, int flags) override;
|
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override { return BAN::Error::from_errno(ENOTCONN); }
|
||||||
BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override { return BAN::Error::from_errno(ENOTCONN); }
|
|
||||||
BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
|
|
||||||
BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) override;
|
|
||||||
|
|
||||||
BAN::ErrorOr<long> ioctl_impl(int, void*) override;
|
virtual bool can_read_impl() const override { return !m_packets.empty(); }
|
||||||
|
virtual bool can_write_impl() const override { return true; }
|
||||||
bool can_read_impl() const override { return !m_packets.empty(); }
|
virtual bool has_error_impl() const override { return false; }
|
||||||
bool can_write_impl() const override { return true; }
|
virtual bool has_hungup_impl() const override { return false; }
|
||||||
bool has_error_impl() const override { return false; }
|
|
||||||
bool has_hungup_impl() const override { return false; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UDPSocket(NetworkLayer&, const Socket::Info&);
|
UDPSocket(NetworkLayer&, const Socket::Info&);
|
||||||
@@ -66,9 +61,6 @@ namespace Kernel
|
|||||||
SpinLock m_packet_lock;
|
SpinLock m_packet_lock;
|
||||||
ThreadBlocker m_packet_thread_blocker;
|
ThreadBlocker m_packet_thread_blocker;
|
||||||
|
|
||||||
sockaddr_storage m_peer_address {};
|
|
||||||
socklen_t m_peer_address_len { 0 };
|
|
||||||
|
|
||||||
friend class BAN::RefPtr<UDPSocket>;
|
friend class BAN::RefPtr<UDPSocket>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,7 @@
|
|||||||
#include <BAN/WeakPtr.h>
|
#include <BAN/WeakPtr.h>
|
||||||
#include <kernel/FS/Socket.h>
|
#include <kernel/FS/Socket.h>
|
||||||
#include <kernel/FS/TmpFS/Inode.h>
|
#include <kernel/FS/TmpFS/Inode.h>
|
||||||
#include <kernel/FS/VirtualFileSystem.h>
|
#include <kernel/Lock/SpinLock.h>
|
||||||
#include <kernel/OpenFileDescriptorSet.h>
|
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
@@ -16,9 +15,6 @@ namespace Kernel
|
|||||||
BAN_NON_COPYABLE(UnixDomainSocket);
|
BAN_NON_COPYABLE(UnixDomainSocket);
|
||||||
BAN_NON_MOVABLE(UnixDomainSocket);
|
BAN_NON_MOVABLE(UnixDomainSocket);
|
||||||
|
|
||||||
public:
|
|
||||||
using FDWrapper = OpenFileDescriptorSet::FDWrapper;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::RefPtr<UnixDomainSocket>> create(Socket::Type, const Socket::Info&);
|
static BAN::ErrorOr<BAN::RefPtr<UnixDomainSocket>> create(Socket::Type, const Socket::Info&);
|
||||||
BAN::ErrorOr<void> make_socket_pair(UnixDomainSocket&);
|
BAN::ErrorOr<void> make_socket_pair(UnixDomainSocket&);
|
||||||
@@ -28,11 +24,9 @@ namespace Kernel
|
|||||||
virtual BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override;
|
virtual BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override;
|
||||||
virtual BAN::ErrorOr<void> listen_impl(int) override;
|
virtual BAN::ErrorOr<void> listen_impl(int) override;
|
||||||
virtual BAN::ErrorOr<void> bind_impl(const sockaddr*, socklen_t) override;
|
virtual BAN::ErrorOr<void> bind_impl(const sockaddr*, socklen_t) override;
|
||||||
virtual BAN::ErrorOr<size_t> recvmsg_impl(msghdr& message, int flags) override;
|
virtual BAN::ErrorOr<size_t> sendto_impl(BAN::ConstByteSpan, const sockaddr*, socklen_t) override;
|
||||||
virtual BAN::ErrorOr<size_t> sendmsg_impl(const msghdr& message, int flags) override;
|
virtual BAN::ErrorOr<size_t> recvfrom_impl(BAN::ByteSpan, sockaddr*, socklen_t*) override;
|
||||||
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override;
|
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override;
|
||||||
virtual BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
|
|
||||||
virtual BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) override;
|
|
||||||
|
|
||||||
virtual bool can_read_impl() const override;
|
virtual bool can_read_impl() const override;
|
||||||
virtual bool can_write_impl() const override;
|
virtual bool can_write_impl() const override;
|
||||||
@@ -43,8 +37,10 @@ namespace Kernel
|
|||||||
UnixDomainSocket(Socket::Type, const Socket::Info&);
|
UnixDomainSocket(Socket::Type, const Socket::Info&);
|
||||||
~UnixDomainSocket();
|
~UnixDomainSocket();
|
||||||
|
|
||||||
bool is_bound() const { return !m_bound_file.canonical_path.empty(); }
|
BAN::ErrorOr<void> add_packet(BAN::ConstByteSpan);
|
||||||
bool is_bound_to_unused() const { return !m_bound_file.inode; }
|
|
||||||
|
bool is_bound() const { return !m_bound_path.empty(); }
|
||||||
|
bool is_bound_to_unused() const { return m_bound_path == "X"_sv; }
|
||||||
|
|
||||||
bool is_streaming() const;
|
bool is_streaming() const;
|
||||||
|
|
||||||
@@ -57,7 +53,7 @@ namespace Kernel
|
|||||||
BAN::WeakPtr<UnixDomainSocket> connection;
|
BAN::WeakPtr<UnixDomainSocket> connection;
|
||||||
BAN::Queue<BAN::RefPtr<UnixDomainSocket>> pending_connections;
|
BAN::Queue<BAN::RefPtr<UnixDomainSocket>> pending_connections;
|
||||||
ThreadBlocker pending_thread_blocker;
|
ThreadBlocker pending_thread_blocker;
|
||||||
Mutex pending_lock;
|
SpinLock pending_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ConnectionlessInfo
|
struct ConnectionlessInfo
|
||||||
@@ -65,32 +61,18 @@ namespace Kernel
|
|||||||
BAN::String peer_address;
|
BAN::String peer_address;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PacketInfo
|
|
||||||
{
|
|
||||||
size_t size;
|
|
||||||
BAN::Vector<FDWrapper> fds;
|
|
||||||
BAN::Optional<struct ucred> ucred;
|
|
||||||
BAN::WeakPtr<UnixDomainSocket> sender;
|
|
||||||
};
|
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> add_packet(const msghdr&, PacketInfo&&, bool dont_block);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Socket::Type m_socket_type;
|
const Socket::Type m_socket_type;
|
||||||
VirtualFileSystem::File m_bound_file;
|
BAN::String m_bound_path;
|
||||||
|
|
||||||
BAN::Variant<ConnectionInfo, ConnectionlessInfo> m_info;
|
BAN::Variant<ConnectionInfo, ConnectionlessInfo> m_info;
|
||||||
|
|
||||||
BAN::CircularQueue<PacketInfo, 512> m_packet_infos;
|
BAN::CircularQueue<size_t, 128> m_packet_sizes;
|
||||||
size_t m_packet_size_total { 0 };
|
size_t m_packet_size_total { 0 };
|
||||||
size_t m_packet_buffer_tail { 0 };
|
|
||||||
BAN::UniqPtr<VirtualRange> m_packet_buffer;
|
BAN::UniqPtr<VirtualRange> m_packet_buffer;
|
||||||
mutable Mutex m_packet_lock;
|
SpinLock m_packet_lock;
|
||||||
ThreadBlocker m_packet_thread_blocker;
|
ThreadBlocker m_packet_thread_blocker;
|
||||||
|
|
||||||
BAN::Atomic<size_t> m_sndbuf { 0 };
|
|
||||||
BAN::Atomic<size_t> m_bytes_sent { 0 };
|
|
||||||
|
|
||||||
friend class BAN::RefPtr<UnixDomainSocket>;
|
friend class BAN::RefPtr<UnixDomainSocket>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<int> dup2(int, int);
|
BAN::ErrorOr<int> dup2(int, int);
|
||||||
|
|
||||||
BAN::ErrorOr<int> fcntl(int fd, int cmd, uintptr_t extra);
|
BAN::ErrorOr<int> fcntl(int fd, int cmd, int extra);
|
||||||
|
|
||||||
BAN::ErrorOr<off_t> seek(int fd, off_t offset, int whence);
|
BAN::ErrorOr<off_t> seek(int fd, off_t offset, int whence);
|
||||||
BAN::ErrorOr<off_t> tell(int) const;
|
BAN::ErrorOr<off_t> tell(int) const;
|
||||||
@@ -44,10 +44,6 @@ namespace Kernel
|
|||||||
void close_all();
|
void close_all();
|
||||||
void close_cloexec();
|
void close_cloexec();
|
||||||
|
|
||||||
bool is_cloexec(int fd);
|
|
||||||
void add_cloexec(int fd);
|
|
||||||
void remove_cloexec(int fd);
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> flock(int fd, int op);
|
BAN::ErrorOr<void> flock(int fd, int op);
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> read(int fd, BAN::ByteSpan);
|
BAN::ErrorOr<size_t> read(int fd, BAN::ByteSpan);
|
||||||
@@ -55,8 +51,8 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<size_t> read_dir_entries(int fd, struct dirent* list, size_t list_len);
|
BAN::ErrorOr<size_t> read_dir_entries(int fd, struct dirent* list, size_t list_len);
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> recvmsg(int socket, msghdr& message, int flags);
|
BAN::ErrorOr<size_t> recvfrom(int fd, BAN::ByteSpan buffer, sockaddr* address, socklen_t* address_len);
|
||||||
BAN::ErrorOr<size_t> sendmsg(int socket, const msghdr& message, int flags);
|
BAN::ErrorOr<size_t> sendto(int fd, BAN::ConstByteSpan buffer, const sockaddr* address, socklen_t address_len);
|
||||||
|
|
||||||
BAN::ErrorOr<VirtualFileSystem::File> file_of(int) const;
|
BAN::ErrorOr<VirtualFileSystem::File> file_of(int) const;
|
||||||
BAN::ErrorOr<BAN::String> path_of(int) const;
|
BAN::ErrorOr<BAN::String> path_of(int) const;
|
||||||
@@ -78,8 +74,8 @@ namespace Kernel
|
|||||||
|
|
||||||
struct flock_t
|
struct flock_t
|
||||||
{
|
{
|
||||||
bool locked { false };
|
bool locked;
|
||||||
bool shared { false };
|
bool shared;
|
||||||
ThreadBlocker thread_blocker;
|
ThreadBlocker thread_blocker;
|
||||||
BAN::HashSet<pid_t> lockers;
|
BAN::HashSet<pid_t> lockers;
|
||||||
};
|
};
|
||||||
@@ -88,42 +84,36 @@ namespace Kernel
|
|||||||
friend class BAN::RefPtr<OpenFileDescription>;
|
friend class BAN::RefPtr<OpenFileDescription>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct OpenFile
|
||||||
|
{
|
||||||
|
OpenFile() = default;
|
||||||
|
OpenFile(BAN::RefPtr<OpenFileDescription> description, int descriptor_flags)
|
||||||
|
: description(BAN::move(description))
|
||||||
|
, descriptor_flags(descriptor_flags)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
BAN::RefPtr<Inode> inode() const { ASSERT(description); return description->file.inode; }
|
||||||
|
BAN::StringView path() const { ASSERT(description); return description->file.canonical_path.sv(); }
|
||||||
|
|
||||||
|
int& status_flags() { ASSERT(description); return description->status_flags; }
|
||||||
|
const int& status_flags() const { ASSERT(description); return description->status_flags; }
|
||||||
|
|
||||||
|
off_t& offset() { ASSERT(description); return description->offset; }
|
||||||
|
const off_t& offset() const { ASSERT(description); return description->offset; }
|
||||||
|
|
||||||
|
BAN::RefPtr<OpenFileDescription> description;
|
||||||
|
int descriptor_flags { 0 };
|
||||||
|
};
|
||||||
|
|
||||||
BAN::ErrorOr<void> validate_fd(int) const;
|
BAN::ErrorOr<void> validate_fd(int) const;
|
||||||
BAN::ErrorOr<int> get_free_fd() const;
|
BAN::ErrorOr<int> get_free_fd() const;
|
||||||
BAN::ErrorOr<void> get_free_fd_pair(int fds[2]) const;
|
BAN::ErrorOr<void> get_free_fd_pair(int fds[2]) const;
|
||||||
|
|
||||||
public:
|
|
||||||
class FDWrapper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FDWrapper(BAN::RefPtr<OpenFileDescription>);
|
|
||||||
FDWrapper(const FDWrapper& other) { *this = other; }
|
|
||||||
FDWrapper(FDWrapper&& other) { *this = BAN::move(other); }
|
|
||||||
~FDWrapper();
|
|
||||||
|
|
||||||
FDWrapper& operator=(const FDWrapper&);
|
|
||||||
FDWrapper& operator=(FDWrapper&&);
|
|
||||||
|
|
||||||
int fd() const { return m_fd; }
|
|
||||||
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
private:
|
|
||||||
BAN::RefPtr<OpenFileDescription> m_description;
|
|
||||||
int m_fd { -1 };
|
|
||||||
|
|
||||||
friend class OpenFileDescriptorSet;
|
|
||||||
};
|
|
||||||
|
|
||||||
BAN::ErrorOr<FDWrapper> get_fd_wrapper(int fd);
|
|
||||||
size_t open_all_fd_wrappers(BAN::Span<FDWrapper> fd_wrappers);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Credentials& m_credentials;
|
const Credentials& m_credentials;
|
||||||
mutable Mutex m_mutex;
|
mutable Mutex m_mutex;
|
||||||
|
|
||||||
BAN::Array<BAN::RefPtr<OpenFileDescription>, OPEN_MAX> m_open_files;
|
BAN::Array<OpenFile, OPEN_MAX> m_open_files;
|
||||||
BAN::Array<uint32_t, (OPEN_MAX + 31) / 32> m_cloexec_files {};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ namespace Kernel::PCI
|
|||||||
void initialize_impl();
|
void initialize_impl();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr uint8_t m_msi_count = IRQ_MSI_END - IRQ_MSI_BASE;
|
static constexpr uint8_t m_msi_count = IRQ_SYSCALL - IRQ_MSI_BASE;
|
||||||
using PCIBus = BAN::Array<BAN::Array<Device, 8>, 32>;
|
using PCIBus = BAN::Array<BAN::Array<Device, 8>, 32>;
|
||||||
BAN::Array<PCIBus, 256> m_buses;
|
BAN::Array<PCIBus, 256> m_buses;
|
||||||
BAN::Array<paddr_t, 256> m_bus_pcie_paddr;
|
BAN::Array<paddr_t, 256> m_bus_pcie_paddr;
|
||||||
|
|||||||
@@ -19,26 +19,15 @@ namespace Kernel
|
|||||||
asm volatile("cli");
|
asm volatile("cli");
|
||||||
|
|
||||||
const bool had_debug_lock = Debug::s_debug_lock.current_processor_has_lock();
|
const bool had_debug_lock = Debug::s_debug_lock.current_processor_has_lock();
|
||||||
|
|
||||||
bool first_panic = false;
|
|
||||||
|
|
||||||
{
|
|
||||||
SpinLockGuard _(Debug::s_debug_lock);
|
|
||||||
derrorln("Kernel panic at {}", location);
|
derrorln("Kernel panic at {}", location);
|
||||||
if (had_debug_lock)
|
if (had_debug_lock)
|
||||||
derrorln(" while having debug lock...");
|
derrorln(" while having debug lock...");
|
||||||
derrorln(message, BAN::forward<Args>(args)...);
|
derrorln(message, BAN::forward<Args>(args)...);
|
||||||
if (!g_paniced)
|
if (!g_paniced)
|
||||||
{
|
{
|
||||||
Debug::dump_stack_trace();
|
|
||||||
g_paniced = true;
|
g_paniced = true;
|
||||||
first_panic = true;
|
Debug::dump_stack_trace();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (first_panic)
|
|
||||||
Debug::dump_qr_code();
|
|
||||||
|
|
||||||
asm volatile("ud2");
|
asm volatile("ud2");
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
#include <kernel/ELF.h>
|
#include <kernel/ELF.h>
|
||||||
#include <kernel/FS/Inode.h>
|
#include <kernel/FS/Inode.h>
|
||||||
#include <kernel/Lock/Mutex.h>
|
#include <kernel/Lock/Mutex.h>
|
||||||
#include <kernel/Lock/RWLock.h>
|
|
||||||
#include <kernel/Memory/Heap.h>
|
#include <kernel/Memory/Heap.h>
|
||||||
#include <kernel/Memory/MemoryRegion.h>
|
#include <kernel/Memory/MemoryRegion.h>
|
||||||
#include <kernel/Memory/SharedMemoryObject.h>
|
#include <kernel/Memory/SharedMemoryObject.h>
|
||||||
@@ -77,7 +76,6 @@ namespace Kernel
|
|||||||
BAN::ErrorOr<long> sys_getcwd(char* buffer, size_t size);
|
BAN::ErrorOr<long> sys_getcwd(char* buffer, size_t size);
|
||||||
BAN::ErrorOr<long> sys_chdir(const char* path);
|
BAN::ErrorOr<long> sys_chdir(const char* path);
|
||||||
BAN::ErrorOr<long> sys_fchdir(int fildes);
|
BAN::ErrorOr<long> sys_fchdir(int fildes);
|
||||||
BAN::ErrorOr<long> sys_chroot(const char* path);
|
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_setuid(uid_t);
|
BAN::ErrorOr<long> sys_setuid(uid_t);
|
||||||
BAN::ErrorOr<long> sys_setgid(gid_t);
|
BAN::ErrorOr<long> sys_setgid(gid_t);
|
||||||
@@ -97,9 +95,6 @@ namespace Kernel
|
|||||||
BAN::ErrorOr<long> sys_getppid() const { return m_parent; }
|
BAN::ErrorOr<long> sys_getppid() const { return m_parent; }
|
||||||
BAN::ErrorOr<long> sys_getpid() const { return pid(); }
|
BAN::ErrorOr<long> sys_getpid() const { return pid(); }
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_getgroups(gid_t groups[], size_t count);
|
|
||||||
BAN::ErrorOr<long> sys_setgroups(const gid_t groups[], size_t count);
|
|
||||||
|
|
||||||
BAN::ErrorOr<long> open_inode(VirtualFileSystem::File&&, int flags);
|
BAN::ErrorOr<long> open_inode(VirtualFileSystem::File&&, int flags);
|
||||||
|
|
||||||
BAN::ErrorOr<void> create_file_or_dir(int fd, const char* path, mode_t mode) const;
|
BAN::ErrorOr<void> create_file_or_dir(int fd, const char* path, mode_t mode) const;
|
||||||
@@ -110,9 +105,9 @@ namespace Kernel
|
|||||||
BAN::ErrorOr<long> sys_access(const char* path, int amode);
|
BAN::ErrorOr<long> sys_access(const char* path, int amode);
|
||||||
BAN::ErrorOr<long> sys_create_dir(const char*, mode_t);
|
BAN::ErrorOr<long> sys_create_dir(const char*, mode_t);
|
||||||
BAN::ErrorOr<long> sys_hardlinkat(int fd1, const char* path1, int fd2, const char* path2, int flag);
|
BAN::ErrorOr<long> sys_hardlinkat(int fd1, const char* path1, int fd2, const char* path2, int flag);
|
||||||
BAN::ErrorOr<long> sys_renameat(int oldfd, const char* old, int newfd, const char* _new);
|
|
||||||
BAN::ErrorOr<long> sys_unlinkat(int fd, const char* path, int flag);
|
BAN::ErrorOr<long> sys_unlinkat(int fd, const char* path, int flag);
|
||||||
BAN::ErrorOr<long> sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize);
|
BAN::ErrorOr<long> sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_symlinkat(const char* path1, int fd, const char* path2);
|
BAN::ErrorOr<long> sys_symlinkat(const char* path1, int fd, const char* path2);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_flock(int fd, int op);
|
BAN::ErrorOr<long> sys_flock(int fd, int op);
|
||||||
@@ -135,8 +130,8 @@ namespace Kernel
|
|||||||
BAN::ErrorOr<long> sys_bind(int socket, const sockaddr* address, socklen_t address_len);
|
BAN::ErrorOr<long> sys_bind(int socket, const sockaddr* address, socklen_t address_len);
|
||||||
BAN::ErrorOr<long> sys_connect(int socket, const sockaddr* address, socklen_t address_len);
|
BAN::ErrorOr<long> sys_connect(int socket, const sockaddr* address, socklen_t address_len);
|
||||||
BAN::ErrorOr<long> sys_listen(int socket, int backlog);
|
BAN::ErrorOr<long> sys_listen(int socket, int backlog);
|
||||||
BAN::ErrorOr<long> sys_recvmsg(int socket, msghdr* message, int flags);
|
BAN::ErrorOr<long> sys_sendto(const sys_sendto_t*);
|
||||||
BAN::ErrorOr<long> sys_sendmsg(int socket, const msghdr* message, int flags);
|
BAN::ErrorOr<long> sys_recvfrom(sys_recvfrom_t*);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_ioctl(int fildes, int request, void* arg);
|
BAN::ErrorOr<long> sys_ioctl(int fildes, int request, void* arg);
|
||||||
|
|
||||||
@@ -147,12 +142,10 @@ namespace Kernel
|
|||||||
BAN::ErrorOr<long> sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event* event);
|
BAN::ErrorOr<long> sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event* event);
|
||||||
BAN::ErrorOr<long> sys_epoll_pwait2(int epfd, struct epoll_event* events, int maxevents, const struct timespec* timeout, const sigset_t* sigmask);
|
BAN::ErrorOr<long> sys_epoll_pwait2(int epfd, struct epoll_event* events, int maxevents, const struct timespec* timeout, const sigset_t* sigmask);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_eventfd(unsigned int initval_hi, int flags);
|
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_pipe(int fildes[2]);
|
BAN::ErrorOr<long> sys_pipe(int fildes[2]);
|
||||||
BAN::ErrorOr<long> sys_dup2(int fildes, int fildes2);
|
BAN::ErrorOr<long> sys_dup2(int fildes, int fildes2);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_fcntl(int fildes, int cmd, uintptr_t extra);
|
BAN::ErrorOr<long> sys_fcntl(int fildes, int cmd, int extra);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_seek(int fd, off_t offset, int whence);
|
BAN::ErrorOr<long> sys_seek(int fd, off_t offset, int whence);
|
||||||
BAN::ErrorOr<long> sys_tell(int fd);
|
BAN::ErrorOr<long> sys_tell(int fd);
|
||||||
@@ -168,50 +161,35 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<long> sys_sync(bool should_block);
|
BAN::ErrorOr<long> sys_sync(bool should_block);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_get_nprocessor();
|
|
||||||
|
|
||||||
static BAN::ErrorOr<long> clean_poweroff(int command);
|
static BAN::ErrorOr<long> clean_poweroff(int command);
|
||||||
BAN::ErrorOr<long> sys_poweroff(int command);
|
BAN::ErrorOr<long> sys_poweroff(int command);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_readdir(int fd, struct dirent* list, size_t list_len);
|
BAN::ErrorOr<long> sys_readdir(int fd, struct dirent* list, size_t list_len);
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::Vector<BAN::UniqPtr<MemoryRegion>>> split_memory_region(BAN::UniqPtr<MemoryRegion>&& region, vaddr_t base, size_t length);
|
|
||||||
BAN::ErrorOr<long> sys_mmap(const sys_mmap_t*);
|
BAN::ErrorOr<long> sys_mmap(const sys_mmap_t*);
|
||||||
BAN::ErrorOr<long> sys_munmap(void* addr, size_t len);
|
BAN::ErrorOr<long> sys_munmap(void* addr, size_t len);
|
||||||
BAN::ErrorOr<long> sys_mprotect(void* addr, size_t len, int prot);
|
|
||||||
BAN::ErrorOr<long> sys_msync(void* addr, size_t len, int flags);
|
BAN::ErrorOr<long> sys_msync(void* addr, size_t len, int flags);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_smo_create(size_t len, int prot);
|
BAN::ErrorOr<long> sys_smo_create(size_t len, int prot);
|
||||||
BAN::ErrorOr<long> sys_smo_delete(SharedMemoryObjectManager::Key);
|
BAN::ErrorOr<long> sys_smo_delete(SharedMemoryObjectManager::Key);
|
||||||
BAN::ErrorOr<long> sys_smo_map(SharedMemoryObjectManager::Key);
|
BAN::ErrorOr<long> sys_smo_map(SharedMemoryObjectManager::Key);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_ttyname(int fildes, char* name, size_t namesize);
|
BAN::ErrorOr<long> sys_ttyname(int fildes, char* storage);
|
||||||
BAN::ErrorOr<long> sys_isatty(int fildes);
|
BAN::ErrorOr<long> sys_isatty(int fildes);
|
||||||
BAN::ErrorOr<long> sys_posix_openpt(int flags);
|
BAN::ErrorOr<long> sys_posix_openpt(int flags);
|
||||||
BAN::ErrorOr<long> sys_ptsname(int fildes, char* buffer, size_t buffer_len);
|
BAN::ErrorOr<long> sys_ptsname(int fildes, char* buffer, size_t buffer_len);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_tty_ctrl(int fildes, int command, int flags);
|
BAN::ErrorOr<long> sys_tty_ctrl(int fildes, int command, int flags);
|
||||||
|
|
||||||
void set_stopped(bool stopped, int signal);
|
static BAN::ErrorOr<void> kill(pid_t pid, int signal);
|
||||||
void wait_while_stopped();
|
|
||||||
|
|
||||||
static BAN::ErrorOr<void> kill(pid_t pid, int signal, const siginfo_t& = {});
|
|
||||||
BAN::ErrorOr<long> sys_kill(pid_t pid, int signal);
|
BAN::ErrorOr<long> sys_kill(pid_t pid, int signal);
|
||||||
BAN::ErrorOr<long> sys_sigaction(int signal, const struct sigaction* act, struct sigaction* oact);
|
BAN::ErrorOr<long> sys_sigaction(int signal, const struct sigaction* act, struct sigaction* oact);
|
||||||
BAN::ErrorOr<long> sys_sigpending(sigset_t* set);
|
BAN::ErrorOr<long> sys_sigpending(sigset_t* set);
|
||||||
BAN::ErrorOr<long> sys_sigprocmask(int how, const sigset_t* set, sigset_t* oset);
|
BAN::ErrorOr<long> sys_sigprocmask(int how, const sigset_t* set, sigset_t* oset);
|
||||||
BAN::ErrorOr<long> sys_sigsuspend(const sigset_t* set);
|
|
||||||
BAN::ErrorOr<long> sys_sigwait(const sigset_t* set, int* sig);
|
|
||||||
BAN::ErrorOr<long> sys_sigaltstack(const stack_t* ss, stack_t* oss);
|
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_futex(int op, const uint32_t* addr, uint32_t val, const timespec* abstime);
|
|
||||||
BAN::ErrorOr<long> sys_yield();
|
BAN::ErrorOr<long> sys_yield();
|
||||||
|
BAN::ErrorOr<long> sys_set_tls(void*);
|
||||||
BAN::ErrorOr<long> sys_set_fsbase(void*);
|
BAN::ErrorOr<long> sys_get_tls();
|
||||||
BAN::ErrorOr<long> sys_get_fsbase();
|
|
||||||
BAN::ErrorOr<long> sys_set_gsbase(void*);
|
|
||||||
BAN::ErrorOr<long> sys_get_gsbase();
|
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_pthread_create(const pthread_attr_t* attr, void (*entry)(void*), void* arg);
|
BAN::ErrorOr<long> sys_pthread_create(const pthread_attr_t* attr, void (*entry)(void*), void* arg);
|
||||||
BAN::ErrorOr<long> sys_pthread_exit(void* value);
|
BAN::ErrorOr<long> sys_pthread_exit(void* value);
|
||||||
BAN::ErrorOr<long> sys_pthread_join(pthread_t thread, void** value);
|
BAN::ErrorOr<long> sys_pthread_join(pthread_t thread, void** value);
|
||||||
@@ -221,6 +199,8 @@ namespace Kernel
|
|||||||
BAN::ErrorOr<long> sys_tcgetpgrp(int fd);
|
BAN::ErrorOr<long> sys_tcgetpgrp(int fd);
|
||||||
BAN::ErrorOr<long> sys_tcsetpgrp(int fd, pid_t pgid);
|
BAN::ErrorOr<long> sys_tcsetpgrp(int fd, pid_t pgid);
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> sys_termid(char*);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_clock_gettime(clockid_t, timespec*);
|
BAN::ErrorOr<long> sys_clock_gettime(clockid_t, timespec*);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_load_keymap(const char* path);
|
BAN::ErrorOr<long> sys_load_keymap(const char* path);
|
||||||
@@ -229,33 +209,24 @@ namespace Kernel
|
|||||||
|
|
||||||
static Process& current() { return Thread::current().process(); }
|
static Process& current() { return Thread::current().process(); }
|
||||||
|
|
||||||
vaddr_t shared_page_vaddr() const { return m_shared_page_vaddr; }
|
|
||||||
|
|
||||||
PageTable& page_table() { return m_page_table ? *m_page_table : PageTable::kernel(); }
|
PageTable& page_table() { return m_page_table ? *m_page_table : PageTable::kernel(); }
|
||||||
|
|
||||||
size_t proc_meminfo(off_t offset, BAN::ByteSpan) const;
|
size_t proc_meminfo(off_t offset, BAN::ByteSpan) const;
|
||||||
size_t proc_cmdline(off_t offset, BAN::ByteSpan) const;
|
size_t proc_cmdline(off_t offset, BAN::ByteSpan) const;
|
||||||
size_t proc_environ(off_t offset, BAN::ByteSpan) const;
|
size_t proc_environ(off_t offset, BAN::ByteSpan) const;
|
||||||
BAN::ErrorOr<BAN::String> proc_cwd() const;
|
|
||||||
BAN::ErrorOr<BAN::String> proc_exe() const;
|
|
||||||
|
|
||||||
BAN::StringView executable() const { return m_executable; }
|
|
||||||
|
|
||||||
// Returns error if page could not be allocated
|
// Returns error if page could not be allocated
|
||||||
// Returns true if the page was allocated successfully
|
// Returns true if the page was allocated successfully
|
||||||
// Return false if access was page violation (segfault)
|
// Return false if access was page violation (segfault)
|
||||||
BAN::ErrorOr<bool> allocate_page_for_demand_paging(vaddr_t addr, bool wants_write, bool wants_exec);
|
BAN::ErrorOr<bool> allocate_page_for_demand_paging(vaddr_t addr, bool wants_write);
|
||||||
|
|
||||||
// FIXME: remove this API
|
// FIXME: remove this API
|
||||||
BAN::ErrorOr<BAN::String> absolute_path_of(BAN::StringView) const;
|
BAN::ErrorOr<BAN::String> absolute_path_of(BAN::StringView) const;
|
||||||
|
|
||||||
OpenFileDescriptorSet& open_file_descriptor_set() { return m_open_file_descriptors; }
|
|
||||||
|
|
||||||
// ONLY CALLED BY TIMER INTERRUPT
|
// ONLY CALLED BY TIMER INTERRUPT
|
||||||
static void update_alarm_queue();
|
static void update_alarm_queue();
|
||||||
|
|
||||||
const VirtualFileSystem::File& working_directory() const { return m_working_directory; }
|
const VirtualFileSystem::File& working_directory() const { return m_working_directory; }
|
||||||
const VirtualFileSystem::File& root_file() const { return m_root_file; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Process(const Credentials&, pid_t pid, pid_t parent, pid_t sid, pid_t pgrp);
|
Process(const Credentials&, pid_t pid, pid_t parent, pid_t sid, pid_t pgrp);
|
||||||
@@ -274,21 +245,13 @@ namespace Kernel
|
|||||||
BAN::StringView file_name;
|
BAN::StringView file_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Adds new region to the sorted array of mapped regions
|
|
||||||
// You must hold writer end of m_mapped_region_lock when calling this.
|
|
||||||
BAN::ErrorOr<void> add_mapped_region(BAN::UniqPtr<MemoryRegion>&&);
|
|
||||||
// If address is contained by a region, returns the index of that.
|
|
||||||
// Otherwise returns the address of the first region after this address.
|
|
||||||
// You must hold reader end of m_mapped_region_lock when calling this.
|
|
||||||
size_t find_mapped_region(vaddr_t) const;
|
|
||||||
|
|
||||||
BAN::ErrorOr<VirtualFileSystem::File> find_file(int fd, const char* path, int flags) const;
|
BAN::ErrorOr<VirtualFileSystem::File> find_file(int fd, const char* path, int flags) const;
|
||||||
BAN::ErrorOr<FileParent> find_parent_file(int fd, const char* path, int flags) const;
|
BAN::ErrorOr<FileParent> find_parent_file(int fd, const char* path, int flags) const;
|
||||||
BAN::ErrorOr<VirtualFileSystem::File> find_relative_parent(int fd, const char* path) const;
|
BAN::ErrorOr<VirtualFileSystem::File> find_relative_parent(int fd, const char* path) const;
|
||||||
|
|
||||||
BAN::ErrorOr<void> read_from_user(const void* user_addr, void* out, size_t size);
|
BAN::ErrorOr<void> validate_string_access(const char*);
|
||||||
BAN::ErrorOr<void> read_string_from_user(const char* user_addr, char* out, size_t max_size);
|
BAN::ErrorOr<void> validate_pointer_access_check(const void*, size_t, bool needs_write);
|
||||||
BAN::ErrorOr<void> write_to_user(void* user_addr, const void* in, size_t size);
|
BAN::ErrorOr<void> validate_pointer_access(const void*, size_t, bool needs_write);
|
||||||
BAN::ErrorOr<MemoryRegion*> validate_and_pin_pointer_access(const void*, size_t, bool needs_write);
|
BAN::ErrorOr<MemoryRegion*> validate_and_pin_pointer_access(const void*, size_t, bool needs_write);
|
||||||
|
|
||||||
uint64_t signal_pending_mask() const
|
uint64_t signal_pending_mask() const
|
||||||
@@ -297,7 +260,7 @@ namespace Kernel
|
|||||||
return m_signal_pending_mask;
|
return m_signal_pending_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_pending_signal(uint8_t signal, const siginfo_t& info)
|
void add_pending_signal(uint8_t signal)
|
||||||
{
|
{
|
||||||
ASSERT(signal >= _SIGMIN);
|
ASSERT(signal >= _SIGMIN);
|
||||||
ASSERT(signal <= _SIGMAX);
|
ASSERT(signal <= _SIGMAX);
|
||||||
@@ -309,7 +272,6 @@ namespace Kernel
|
|||||||
if (handler == SIG_DFL && (signal == SIGCHLD || signal == SIGURG))
|
if (handler == SIG_DFL && (signal == SIGCHLD || signal == SIGURG))
|
||||||
return;
|
return;
|
||||||
m_signal_pending_mask |= 1ull << signal;
|
m_signal_pending_mask |= 1ull << signal;
|
||||||
m_signal_infos[signal] = info;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove_pending_signal(uint8_t signal)
|
void remove_pending_signal(uint8_t signal)
|
||||||
@@ -322,18 +284,18 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ChildWaitStatus
|
struct ChildExitStatus
|
||||||
{
|
{
|
||||||
pid_t pid { 0 };
|
pid_t pid { 0 };
|
||||||
pid_t pgrp { 0 };
|
pid_t pgrp { 0 };
|
||||||
BAN::Optional<int> status;
|
int exit_code { 0 };
|
||||||
|
bool exited { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
Credentials m_credentials;
|
Credentials m_credentials;
|
||||||
|
|
||||||
OpenFileDescriptorSet m_open_file_descriptors;
|
OpenFileDescriptorSet m_open_file_descriptors;
|
||||||
|
|
||||||
mutable RWLock m_memory_region_lock;
|
|
||||||
BAN::Vector<BAN::UniqPtr<MemoryRegion>> m_mapped_regions;
|
BAN::Vector<BAN::UniqPtr<MemoryRegion>> m_mapped_regions;
|
||||||
|
|
||||||
pid_t m_sid;
|
pid_t m_sid;
|
||||||
@@ -343,27 +305,7 @@ namespace Kernel
|
|||||||
|
|
||||||
mutable Mutex m_process_lock;
|
mutable Mutex m_process_lock;
|
||||||
|
|
||||||
BAN::Atomic<bool> m_stopped { false };
|
|
||||||
ThreadBlocker m_stop_blocker;
|
|
||||||
|
|
||||||
VirtualFileSystem::File m_working_directory;
|
VirtualFileSystem::File m_working_directory;
|
||||||
VirtualFileSystem::File m_root_file;
|
|
||||||
|
|
||||||
vaddr_t m_shared_page_vaddr { 0 };
|
|
||||||
|
|
||||||
struct futex_t
|
|
||||||
{
|
|
||||||
Mutex mutex;
|
|
||||||
ThreadBlocker blocker;
|
|
||||||
uint32_t waiters { 0 };
|
|
||||||
uint32_t to_wakeup { 0 };
|
|
||||||
};
|
|
||||||
|
|
||||||
static BAN::HashMap<paddr_t, BAN::UniqPtr<futex_t>> s_futexes;
|
|
||||||
static Mutex s_futex_lock;
|
|
||||||
|
|
||||||
BAN::HashMap<paddr_t, BAN::UniqPtr<futex_t>> m_futexes;
|
|
||||||
Mutex m_futex_lock;
|
|
||||||
|
|
||||||
BAN::Vector<Thread*> m_threads;
|
BAN::Vector<Thread*> m_threads;
|
||||||
|
|
||||||
@@ -379,26 +321,20 @@ namespace Kernel
|
|||||||
uint64_t m_alarm_wake_time_ns { 0 };
|
uint64_t m_alarm_wake_time_ns { 0 };
|
||||||
|
|
||||||
mutable SpinLock m_signal_lock;
|
mutable SpinLock m_signal_lock;
|
||||||
siginfo_t m_signal_infos[_SIGMAX + 1] { };
|
|
||||||
struct sigaction m_signal_handlers[_SIGMAX + 1] { };
|
struct sigaction m_signal_handlers[_SIGMAX + 1] { };
|
||||||
uint64_t m_signal_pending_mask { 0 };
|
uint64_t m_signal_pending_mask { 0 };
|
||||||
|
|
||||||
BAN::Vector<BAN::String> m_cmdline;
|
BAN::Vector<BAN::String> m_cmdline;
|
||||||
BAN::Vector<BAN::String> m_environ;
|
BAN::Vector<BAN::String> m_environ;
|
||||||
BAN::String m_executable;
|
|
||||||
|
|
||||||
BAN::Vector<ChildWaitStatus> m_child_wait_statuses;
|
BAN::Vector<ChildExitStatus> m_child_exit_statuses;
|
||||||
SpinLock m_child_wait_lock;
|
ThreadBlocker m_child_exit_blocker;
|
||||||
ThreadBlocker m_child_wait_blocker;
|
|
||||||
|
|
||||||
BAN::Atomic<bool> m_is_exiting { false };
|
|
||||||
|
|
||||||
bool m_has_called_exec { false };
|
bool m_has_called_exec { false };
|
||||||
|
|
||||||
BAN::UniqPtr<PageTable> m_page_table;
|
BAN::UniqPtr<PageTable> m_page_table;
|
||||||
BAN::RefPtr<TTY> m_controlling_terminal;
|
BAN::RefPtr<TTY> m_controlling_terminal;
|
||||||
|
|
||||||
friend class OpenFileDescriptorSet;
|
|
||||||
friend class Thread;
|
friend class Thread;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user