Compare commits

...

21 Commits

Author SHA1 Message Date
Bananymous 6d899aa6ce BuildSystem: using sysroot doesn't need root privileges anymore!
Sysroot is now created with fakeroot. This allows root access to be
only needed for disk image creation, since it uses loopback devices.
2023-11-04 17:50:43 +02:00
Bananymous 120f7329b1 BAN: Update ASSERT api
its now much harder to mix < with <= and > with >=
2023-11-02 00:01:12 +02:00
Bananymous 4f25c20c97 Kernel: Canonicalize vaddr before using it 2023-10-30 19:20:17 +02:00
Bananymous 5e396851f4 Kernel: Remove unused externs in kernel.cpp 2023-10-30 19:09:31 +02:00
Bananymous a44482639d Kernel: Temporarily force FileBackedRegion mappings writable
Now that write-protect bit is enabled this is neccessary.
2023-10-30 19:08:33 +02:00
Bananymous 3bac19e518 Kernel: Add fast page to page table
Add "fast page" to KERNEL_OFFSET. This is always present in page
tables and only requires changing the page table entry to map. This
requires no interrupts since it should only be for very operations
like memcpy.

I used to map all temporary mappings to vaddr 0, but this is much
better. C++ standard always says that nullptr access is undefined
and this gets rid of it.

Fixed some bugs I found along the way
2023-10-30 19:02:09 +02:00
Bananymous 4dbe15aa0e Kernel: Remove GeneralAllocator since it was not used 2023-10-30 18:13:17 +02:00
Bananymous 1c5985148c Kernel: Allow offsetof with packed fields
This is not standard C++ but should be fine with my toolchain.
2023-10-30 17:51:18 +02:00
Bananymous ce2461d0e8 Kernel: panic takes arguments as rvalue references 2023-10-30 16:22:02 +02:00
Bananymous 4e785a133c Kernel: Fix ext2 small link deallocation
Also fix deallocation bug
2023-10-30 16:22:02 +02:00
Bananymous 26c7aee327 Kernel: only map kernel from g_kernel_start onwards 2023-10-30 16:22:02 +02:00
Bananymous 0405461742 BAN: Implement better ASSERT macros
Implement macros for all basic binary ops. These macros print failed
values when the fail.
2023-10-30 16:22:02 +02:00
Bananymous 8a10853ba7 Kernel: Enable Write Protect. This seems to be good for security 2023-10-30 12:23:22 +02:00
Bananymous 5d34cebeca Kernel: Fix stack OOB detection
I now check both interrupt and normal stack to detect OOB. Processes
are killed if they encouner stack over/under flow.
2023-10-30 12:17:08 +02:00
Bananymous 3d899d2e44 Kernel/LibELF: Map pages always as RW so kernel can write to them
Kernel doesn't seem to require W permissions to a page without UEFI
so this had not been found earlier.
2023-10-30 12:14:12 +02:00
Bananymous f72fdeeb59 BAN: String now uses union for its sso storage
This allows String to shrink by 8 bytes since Variant's 8 index is
no longer stored in here.

This required me to make Strings max size one bit less, but that
should still be fine. There should never be strings with size of
over half of the computer's address space.
2023-10-30 11:13:16 +02:00
Bananymous 382f9d9bb3 Userspace: Add quick test for global ctors and dtors 2023-10-30 11:11:10 +02:00
Bananymous bc1d1bf919 LibC: implement and call __cxa_finalize() on exit()
This allows global destructors to be actually called
2023-10-30 11:10:08 +02:00
Bananymous f05b9a6877 Kernel/LibC: Add crt* files to LibC and remove crt0 from kernel
There was no reason for libc get crt0 from kernel.
2023-10-30 11:06:13 +02:00
Bananymous ea5ed3001e Toolchain: Clone GCC and Binutils from git
This feels much cleaner than just downloading tar balls from
pregiven urls. Also patching works much better like this!

I added --disable-initfini-array since global constructors were
not called.
2023-10-30 11:02:57 +02:00
Bananymous f312c3a4d7 Kernel: Fix ACPI DSDT address
Read x_dsdt address only if fadt's length contains it. Bochs seems
to have version 1 fadt without the x_* fields.
2023-10-29 21:35:11 +02:00
69 changed files with 712 additions and 153809 deletions

2
.gitignore vendored
View File

@ -2,4 +2,4 @@
.idea/
build/
base/
script/fakeroot-context

View File

@ -1,6 +1,5 @@
#include <BAN/String.h>
#include <BAN/New.h>
#include <BAN/Variant.h>
namespace BAN
{
@ -32,8 +31,7 @@ namespace BAN
String& String::operator=(const String& other)
{
clear();
if (!other.fits_in_sso())
MUST(ensure_capacity(other.size()));
MUST(ensure_capacity(other.size()));
memcpy(data(), other.data(), other.size() + 1);
m_size = other.size();
return *this;
@ -43,14 +41,18 @@ namespace BAN
{
clear();
if (other.fits_in_sso())
if (other.has_sso())
memcpy(data(), other.data(), other.size() + 1);
else
m_storage = other.m_storage.get<GeneralStorage>();
{
m_storage.general_storage = other.m_storage.general_storage;
m_has_sso = false;
}
m_size = other.m_size;
other.m_size = 0;
other.m_storage = SSOStorage();
other.m_storage.sso_storage = SSOStorage();
other.m_has_sso = true;
return *this;
}
@ -58,8 +60,7 @@ namespace BAN
String& String::operator=(StringView other)
{
clear();
if (!fits_in_sso(other.size()))
MUST(ensure_capacity(other.size()));
MUST(ensure_capacity(other.size()));
memcpy(data(), other.data(), other.size());
m_size = other.size();
data()[m_size] = '\0';
@ -125,8 +126,9 @@ namespace BAN
{
if (!has_sso())
{
deallocator(m_storage.get<GeneralStorage>().data);
m_storage = SSOStorage();
deallocator(m_storage.general_storage.data);
m_storage.sso_storage = SSOStorage();
m_has_sso = true;
}
m_size = 0;
data()[m_size] = '\0';
@ -167,15 +169,6 @@ namespace BAN
return {};
}
// shrink general -> sso
if (!has_sso() && fits_in_sso(new_size))
{
char* data = m_storage.get<GeneralStorage>().data;
m_storage = SSOStorage();
memcpy(m_storage.get<SSOStorage>().storage, data, new_size);
deallocator(data);
}
m_size = new_size;
data()[m_size] = '\0';
return {};
@ -194,20 +187,21 @@ namespace BAN
if (fits_in_sso())
{
char* data = m_storage.get<GeneralStorage>().data;
m_storage = SSOStorage();
memcpy(m_storage.get<SSOStorage>().storage, data, m_size + 1);
char* data = m_storage.general_storage.data;
m_storage.sso_storage = SSOStorage();
m_has_sso = true;
memcpy(this->data(), data, m_size + 1);
deallocator(data);
return {};
}
GeneralStorage& storage = m_storage.get<GeneralStorage>();
GeneralStorage& storage = m_storage.general_storage;
if (storage.capacity == m_size)
return {};
char* new_data = (char*)allocator(m_size + 1);
if (new_data == nullptr)
return BAN::Error::from_errno(ENOMEM);
return Error::from_errno(ENOMEM);
memcpy(new_data, storage.data, m_size);
deallocator(storage.data);
@ -222,40 +216,45 @@ namespace BAN
{
if (has_sso())
return sso_capacity;
return m_storage.get<GeneralStorage>().capacity;
return m_storage.general_storage.capacity;
}
char* String::data()
{
if (has_sso())
return m_storage.get<SSOStorage>().storage;
return m_storage.get<GeneralStorage>().data;
return m_storage.sso_storage.data;
return m_storage.general_storage.data;
}
const char* String::data() const
{
if (has_sso())
return m_storage.get<SSOStorage>().storage;
return m_storage.get<GeneralStorage>().data;
return m_storage.sso_storage.data;
return m_storage.general_storage.data;
}
ErrorOr<void> String::ensure_capacity(size_type new_size)
{
if (m_size >= new_size || fits_in_sso(new_size))
if (m_size >= new_size)
return {};
if (has_sso() && fits_in_sso(new_size))
return {};
char* new_data = (char*)allocator(new_size + 1);
if (new_data == nullptr)
return BAN::Error::from_errno(ENOMEM);
return Error::from_errno(ENOMEM);
memcpy(new_data, data(), m_size + 1);
if (has_sso())
m_storage = GeneralStorage();
{
m_storage.general_storage = GeneralStorage();
m_has_sso = false;
}
else
deallocator(m_storage.get<GeneralStorage>().data);
deallocator(m_storage.general_storage.data);
auto& storage = m_storage.get<GeneralStorage>();
auto& storage = m_storage.general_storage;
storage.capacity = new_size;
storage.data = new_data;
@ -264,7 +263,7 @@ namespace BAN
bool String::has_sso() const
{
return m_storage.has<SSOStorage>();
return m_has_sso;
}
}

View File

@ -10,17 +10,15 @@ set(BAN_SOURCES
)
add_custom_target(ban-headers
COMMAND sudo rsync -a ${CMAKE_CURRENT_SOURCE_DIR}/include/ ${BANAN_INCLUDE}/
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_CURRENT_SOURCE_DIR}/include/ ${BANAN_INCLUDE}/
DEPENDS sysroot
USES_TERMINAL
)
add_library(ban ${BAN_SOURCES})
add_dependencies(ban headers libc-install)
add_custom_target(ban-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/libban.a ${BANAN_LIB}/
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/libban.a ${BANAN_LIB}/
DEPENDS ban
BYPRODUCTS ${BANAN_LIB}/libban.a
USES_TERMINAL
)

View File

@ -1,8 +1,30 @@
#pragma once
#include <BAN/Traits.h>
#if defined(__is_kernel)
#include <kernel/Panic.h>
#define ASSERT(cond) do { if (!(cond)) Kernel::panic("ASSERT("#cond") failed"); } while (false)
#define ASSERT(cond) \
do { \
if (!(cond)) \
Kernel::panic("ASSERT(" #cond ") failed"); \
} while (false)
#define __ASSERT_BIN_OP(lhs, rhs, name, op) \
do { \
auto&& _lhs = lhs; \
auto&& _rhs = rhs; \
if (!(_lhs op _rhs)) \
Kernel::panic(name "(" #lhs ", " #rhs ") ({} " #op " {}) failed", _lhs, _rhs); \
} while (false)
#define ASSERT_LT(lhs, rhs) __ASSERT_BIN_OP(lhs, rhs, "ASSERT_LT", <)
#define ASSERT_LTE(lhs, rhs) __ASSERT_BIN_OP(lhs, rhs, "ASSERT_LTE", <=)
#define ASSERT_GT(lhs, rhs) __ASSERT_BIN_OP(lhs, rhs, "ASSERT_GT", >)
#define ASSERT_GTE(lhs, rhs) __ASSERT_BIN_OP(lhs, rhs, "ASSERT_GTE", >=)
#define ASSERT_EQ(lhs, rhs) __ASSERT_BIN_OP(lhs, rhs, "ASSERT_EQ", ==)
#define ASSERT_NEQ(lhs, rhs) __ASSERT_BIN_OP(lhs, rhs, "ASSERT_NEQ", !=)
#define ASSERT_NOT_REACHED() Kernel::panic("ASSERT_NOT_REACHED() failed")
#else
#include <assert.h>

View File

@ -82,17 +82,21 @@ namespace BAN
private:
struct SSOStorage
{
char storage[sso_capacity + 1] {};
char data[sso_capacity + 1] {};
};
struct GeneralStorage
{
size_type capacity { 0 };
char* data;
size_type capacity { 0 };
char* data { nullptr };
};
private:
Variant<SSOStorage, GeneralStorage> m_storage { SSOStorage() };
size_type m_size { 0 };
union {
SSOStorage sso_storage;
GeneralStorage general_storage;
} m_storage { .sso_storage = SSOStorage() };
size_type m_size : sizeof(size_type) * 8 - 1 { 0 };
size_type m_has_sso : 1 { true };
};
template<typename... Args>

View File

@ -10,7 +10,6 @@ add_compile_definitions(__enable_sse=0)
project(banan-os CXX C ASM)
set(BANAN_BASE_SYSROOT ${CMAKE_SOURCE_DIR}/base-sysroot.tar.gz)
set(BANAN_SYSROOT ${CMAKE_BINARY_DIR}/sysroot)
set(BANAN_INCLUDE ${BANAN_SYSROOT}/usr/include)
set(BANAN_LIB ${BANAN_SYSROOT}/usr/lib)
set(BANAN_BIN ${BANAN_SYSROOT}/usr/bin)
@ -24,8 +23,7 @@ add_subdirectory(userspace)
add_custom_target(sysroot
COMMAND ${CMAKE_COMMAND} -E make_directory ${BANAN_SYSROOT}
COMMAND cd ${BANAN_SYSROOT} && sudo tar xf ${BANAN_BASE_SYSROOT}
USES_TERMINAL
COMMAND cd ${BANAN_SYSROOT} && tar xf ${BANAN_BASE_SYSROOT}
)
add_custom_target(headers
@ -36,6 +34,7 @@ add_custom_target(headers
)
add_custom_target(install-sysroot
COMMAND cd ${BANAN_SYSROOT} && tar cf ${BANAN_SYSROOT_TAR} *
DEPENDS kernel-install
DEPENDS ban-install
DEPENDS libc-install

View File

@ -3,9 +3,8 @@ cmake_minimum_required(VERSION 3.26)
project(LibELF CXX)
add_custom_target(libelf-headers
COMMAND sudo rsync -a ${CMAKE_CURRENT_SOURCE_DIR}/include/ ${BANAN_INCLUDE}/
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_CURRENT_SOURCE_DIR}/include/ ${BANAN_INCLUDE}/
DEPENDS sysroot
USES_TERMINAL
)
add_custom_target(libelf-install

View File

@ -1,4 +1,5 @@
#include <BAN/ScopeGuard.h>
#include <kernel/CriticalScope.h>
#include <kernel/Memory/Heap.h>
#include <kernel/LockGuard.h>
#include <LibELF/LoadableELF.h>
@ -226,7 +227,8 @@ namespace LibELF
if (paddr == 0)
return BAN::Error::from_errno(ENOMEM);
m_page_table.map_page_at(paddr, vaddr, flags);
// Temporarily map page as RW so kernel can write to it
m_page_table.map_page_at(paddr, vaddr, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
m_physical_page_count++;
memset((void*)vaddr, 0x00, PAGE_SIZE);
@ -245,6 +247,9 @@ namespace LibELF
TRY(m_inode->read(program_header.p_offset + file_offset, { (uint8_t*)vaddr + vaddr_offset, bytes }));
}
// Map page with the correct flags
m_page_table.map_page_at(paddr, vaddr, flags);
return {};
}
default:
@ -302,9 +307,12 @@ namespace LibELF
if (paddr == 0)
return BAN::Error::from_errno(ENOMEM);
m_page_table.map_page_at(paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
memcpy((void*)0, (void*)(start + i * PAGE_SIZE), PAGE_SIZE);
m_page_table.unmap_page(0);
{
CriticalScope _;
PageTable::map_fast_page(paddr);
memcpy(PageTable::fast_page_as_ptr(), (void*)(start + i * PAGE_SIZE), PAGE_SIZE);
PageTable::unmap_fast_page();
}
new_page_table.map_page_at(paddr, start + i * PAGE_SIZE, flags);
elf->m_physical_page_count++;

View File

@ -2,7 +2,7 @@
# banan-os
This is my hobby operating system written in C++. Currently supports only x86_64 architecture. We have a ext2 filesystem, basic ramfs, IDE disk drivers in ATA PIO mode, ATA AHCI drivers, userspace processes, executable loading from ELF format, linear VBE graphics and multithreaded processing on single core.
This is my hobby operating system written in C++. Currently supports only x86\_64 architecture. We have a ext2 filesystem, basic ramfs, IDE disk drivers in ATA PIO mode, ATA AHCI drivers, userspace processes, executable loading from ELF format, linear VBE graphics and multithreaded processing on single core.
![screenshot from qemu running banan-os](assets/banan-os.png)
@ -20,7 +20,7 @@ To build the toolchain for this os. You can run the following command.
./script/build.sh toolchain
```
To build the os itself you can run one of the following commands. You will need root access since the sysroot has "proper" permissions.
To build the os itself you can run one of the following commands. You will need root access for disk image creation/modification.
```sh
./script/build.sh qemu
./script/build.sh qemu-nographic
@ -39,8 +39,6 @@ If you have corrupted your disk image or want to create new one, you can either
./script/build.sh image-full
```
> ***NOTE*** ```ninja clean``` has to be ran with root permissions, since it deletes from the banan-so sysroot.
If you feel like ```./script/build.sh``` is too verbose, there exists a symlink _bos_ in this projects root directory. All build commands can be used with ```./bos args...``` instead.
I have also created shell completion script for zsh. You can either copy the file in _script/shell-completion/zsh/\_bos_ to _/usr/share/zsh/site-functions/_ or add the _script/shell-completion/zsh_ to your fpath in _.zshrc_.

View File

@ -36,7 +36,6 @@ set(KERNEL_SOURCES
kernel/kernel.cpp
kernel/Memory/DMARegion.cpp
kernel/Memory/FileBackedRegion.cpp
kernel/Memory/GeneralAllocator.cpp
kernel/Memory/Heap.cpp
kernel/Memory/kmalloc.cpp
kernel/Memory/MemoryBackedRegion.cpp
@ -148,6 +147,9 @@ target_compile_options(kernel PUBLIC $<$<COMPILE_LANGUAGE:CXX>:-Wno-literal-suff
target_compile_options(kernel PUBLIC -fmacro-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}=.)
target_compile_options(kernel PUBLIC -fstack-protector -ffreestanding -Wall -Werror=return-type -Wstack-usage=1024 -fno-omit-frame-pointer -mgeneral-regs-only)
# This might not work with other toolchains
target_compile_options(kernel PUBLIC $<$<COMPILE_LANGUAGE:CXX>:-Wno-invalid-offsetof>)
if(ENABLE_KERNEL_UBSAN)
target_compile_options(kernel PUBLIC -fsanitize=undefined)
endif()
@ -162,28 +164,15 @@ endif()
target_link_options(kernel PUBLIC -ffreestanding -nostdlib)
add_custom_target(crt0
COMMAND ${CMAKE_CXX_COMPILER} -c ${CMAKE_CURRENT_SOURCE_DIR}/arch/${BANAN_ARCH}/crt0.S -o ${CMAKE_CURRENT_BINARY_DIR}/crt0.o
DEPENDS headers
)
add_custom_command(
TARGET crt0
POST_BUILD
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/crt0.o ${BANAN_LIB}/
)
add_custom_target(kernel-headers
COMMAND sudo rsync -a ${CMAKE_CURRENT_SOURCE_DIR}/include/ ${BANAN_INCLUDE}/
COMMAND sudo rsync -a ${CMAKE_CURRENT_SOURCE_DIR}/lai/include/ ${BANAN_INCLUDE}/
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_CURRENT_SOURCE_DIR}/include/ ${BANAN_INCLUDE}/
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_CURRENT_SOURCE_DIR}/lai/include/ ${BANAN_INCLUDE}/
DEPENDS sysroot
USES_TERMINAL
)
add_custom_target(kernel-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/kernel ${BANAN_BOOT}/banan-os.kernel
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/kernel ${BANAN_BOOT}/banan-os.kernel
DEPENDS kernel
USES_TERMINAL
)
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -print-file-name=crtbegin.o OUTPUT_VARIABLE CRTBEGIN OUTPUT_STRIP_TRAILING_WHITESPACE)
@ -193,8 +182,8 @@ add_custom_command(
TARGET kernel PRE_LINK
COMMAND ${CMAKE_CXX_COMPILER} -MD -c ${CMAKE_CURRENT_SOURCE_DIR}/arch/${BANAN_ARCH}/crti.S ${COMPILE_OPTIONS}
COMMAND ${CMAKE_CXX_COMPILER} -MD -c ${CMAKE_CURRENT_SOURCE_DIR}/arch/${BANAN_ARCH}/crtn.S ${COMPILE_OPTIONS}
COMMAND cp ${CRTBEGIN} .
COMMAND cp ${CRTEND} .
COMMAND ${CMAKE_COMMAND} -E copy ${CRTBEGIN} .
COMMAND ${CMAKE_COMMAND} -E copy ${CRTEND} .
)
#add_custom_command(

View File

@ -181,14 +181,20 @@ namespace Kernel::IDT
{
// Check if stack is OOB
auto& stack = Thread::current().stack();
if (interrupt_stack.rsp < stack.vaddr())
auto& istack = Thread::current().interrupt_stack();
if (stack.vaddr() < interrupt_stack.rsp && interrupt_stack.rsp <= stack.vaddr() + stack.size())
; // using normal stack
else if (istack.vaddr() < interrupt_stack.rsp && interrupt_stack.rsp <= istack.vaddr() + istack.size())
; // using interrupt stack
else
{
derrorln("Stack overflow");
goto done;
}
if (interrupt_stack.rsp >= stack.vaddr() + stack.size())
{
derrorln("Stack underflow");
derrorln("Stack pointer out of bounds!");
derrorln("rsp {H}, stack {H}->{H}, istack {H}->{H}",
interrupt_stack.rsp,
stack.vaddr(), stack.vaddr() + stack.size(),
istack.vaddr(), istack.vaddr() + istack.size()
);
Thread::current().handle_signal(SIGKILL);
goto done;
}
@ -207,7 +213,7 @@ namespace Kernel::IDT
if (result.is_error())
{
dwarnln("Demand paging: {}", result.error());
Thread::current().handle_signal(SIGTERM);
Thread::current().handle_signal(SIGKILL);
goto done;
}
}

View File

@ -1,6 +1,6 @@
#include <BAN/Errors.h>
#include <kernel/Arch.h>
#include <kernel/CPUID.h>
#include <kernel/InterruptController.h>
#include <kernel/LockGuard.h>
#include <kernel/Memory/kmalloc.h>
#include <kernel/Memory/PageTable.h>
@ -92,6 +92,13 @@ namespace Kernel
s_has_pge = true;
}
// enable write protect to kernel
asm volatile(
"movq %cr0, %rax;"
"orq $0x10000, %rax;"
"movq %rax, %cr0;"
);
ASSERT(s_kernel == nullptr);
s_kernel = new PageTable();
ASSERT(s_kernel);
@ -136,8 +143,16 @@ namespace Kernel
uint64_t* pml4 = (uint64_t*)P2V(m_highest_paging_struct);
pml4[511] = s_global_pml4e;
// Map (0 -> phys_kernel_end) to (KERNEL_OFFSET -> virt_kernel_end)
map_range_at(0, KERNEL_OFFSET, (uintptr_t)g_kernel_end - KERNEL_OFFSET, Flags::ReadWrite | Flags::Present);
prepare_fast_page();
// Map (phys_kernel_start -> phys_kernel_end) to (virt_kernel_start -> virt_kernel_end)
ASSERT((vaddr_t)g_kernel_start % PAGE_SIZE == 0);
map_range_at(
V2P(g_kernel_start),
(vaddr_t)g_kernel_start,
g_kernel_end - g_kernel_start,
Flags::ReadWrite | Flags::Present
);
// Map executable kernel memory as executable
map_range_at(
@ -172,6 +187,76 @@ namespace Kernel
g_multiboot2_info = (multiboot2_info_t*)(multiboot2_vaddr + ((vaddr_t)g_multiboot2_info % PAGE_SIZE));
}
void PageTable::prepare_fast_page()
{
constexpr vaddr_t uc_vaddr = uncanonicalize(fast_page());
constexpr uint64_t pml4e = (uc_vaddr >> 39) & 0x1FF;
constexpr uint64_t pdpte = (uc_vaddr >> 30) & 0x1FF;
constexpr uint64_t pde = (uc_vaddr >> 21) & 0x1FF;
constexpr uint64_t pte = (uc_vaddr >> 12) & 0x1FF;
uint64_t* pml4 = (uint64_t*)P2V(m_highest_paging_struct);
ASSERT(!(pml4[pml4e] & Flags::Present));
pml4[pml4e] = V2P(allocate_zeroed_page_aligned_page()) | Flags::ReadWrite | Flags::Present;
uint64_t* pdpt = (uint64_t*)P2V(pml4[pml4e] & PAGE_ADDR_MASK);
ASSERT(!(pdpt[pdpte] & Flags::Present));
pdpt[pdpte] = V2P(allocate_zeroed_page_aligned_page()) | Flags::ReadWrite | Flags::Present;
uint64_t* pd = (uint64_t*)P2V(pdpt[pdpte] & PAGE_ADDR_MASK);
ASSERT(!(pd[pde] & Flags::Present));
pd[pde] = V2P(allocate_zeroed_page_aligned_page()) | Flags::ReadWrite | Flags::Present;
uint64_t* pt = (uint64_t*)P2V(pd[pde] & PAGE_ADDR_MASK);
ASSERT(!(pt[pte] & Flags::Present));
pt[pte] = V2P(allocate_zeroed_page_aligned_page());
}
void PageTable::map_fast_page(paddr_t paddr)
{
ASSERT(s_kernel);
ASSERT_NEQ(paddr, 0);
ASSERT(!interrupts_enabled());
constexpr vaddr_t uc_vaddr = uncanonicalize(fast_page());
constexpr uint64_t pml4e = (uc_vaddr >> 39) & 0x1FF;
constexpr uint64_t pdpte = (uc_vaddr >> 30) & 0x1FF;
constexpr uint64_t pde = (uc_vaddr >> 21) & 0x1FF;
constexpr uint64_t pte = (uc_vaddr >> 12) & 0x1FF;
uint64_t* pml4 = (uint64_t*)P2V(s_kernel->m_highest_paging_struct);
uint64_t* pdpt = (uint64_t*)P2V(pml4[pml4e] & PAGE_ADDR_MASK);
uint64_t* pd = (uint64_t*)P2V(pdpt[pdpte] & PAGE_ADDR_MASK);
uint64_t* pt = (uint64_t*)P2V(pd[pde] & PAGE_ADDR_MASK);
ASSERT(!(pt[pte] & Flags::Present));
pt[pte] = paddr | Flags::ReadWrite | Flags::Present;
invalidate(fast_page());
}
void PageTable::unmap_fast_page()
{
ASSERT(s_kernel);
ASSERT(!interrupts_enabled());
constexpr vaddr_t uc_vaddr = uncanonicalize(fast_page());
constexpr uint64_t pml4e = (uc_vaddr >> 39) & 0x1FF;
constexpr uint64_t pdpte = (uc_vaddr >> 30) & 0x1FF;
constexpr uint64_t pde = (uc_vaddr >> 21) & 0x1FF;
constexpr uint64_t pte = (uc_vaddr >> 12) & 0x1FF;
uint64_t* pml4 = (uint64_t*)P2V(s_kernel->m_highest_paging_struct);
uint64_t* pdpt = (uint64_t*)P2V(pml4[pml4e] & PAGE_ADDR_MASK);
uint64_t* pd = (uint64_t*)P2V(pdpt[pdpte] & PAGE_ADDR_MASK);
uint64_t* pt = (uint64_t*)P2V(pd[pde] & PAGE_ADDR_MASK);
ASSERT(pt[pte] & Flags::Present);
pt[pte] = 0;
invalidate(fast_page());
}
BAN::ErrorOr<PageTable*> PageTable::create_userspace()
{
LockGuard _(s_kernel->m_lock);
@ -233,13 +318,16 @@ namespace Kernel
void PageTable::invalidate(vaddr_t vaddr)
{
ASSERT(vaddr % PAGE_SIZE == 0);
if (this == s_current)
asm volatile("invlpg (%0)" :: "r"(vaddr) : "memory");
asm volatile("invlpg (%0)" :: "r"(vaddr) : "memory");
}
void PageTable::unmap_page(vaddr_t vaddr)
{
if (vaddr && (vaddr >= KERNEL_OFFSET) != (this == s_kernel))
ASSERT(vaddr);
ASSERT(vaddr != fast_page());
if (vaddr >= KERNEL_OFFSET)
ASSERT_GTE(vaddr, (vaddr_t)g_kernel_start);
if ((vaddr >= KERNEL_OFFSET) != (this == s_kernel))
Kernel::panic("unmapping {8H}, kernel: {}", vaddr, this == s_kernel);
ASSERT(is_canonical(vaddr));
@ -281,7 +369,11 @@ namespace Kernel
void PageTable::map_page_at(paddr_t paddr, vaddr_t vaddr, flags_t flags)
{
if (vaddr && (vaddr >= KERNEL_OFFSET) != (this == s_kernel))
ASSERT(vaddr);
ASSERT(vaddr != fast_page());
if (vaddr >= KERNEL_OFFSET)
ASSERT_GTE(vaddr, (vaddr_t)g_kernel_start);
if ((vaddr >= KERNEL_OFFSET) != (this == s_kernel))
Kernel::panic("mapping {8H} to {8H}, kernel: {}", paddr, vaddr, this == s_kernel);
ASSERT(is_canonical(vaddr));
@ -348,12 +440,11 @@ namespace Kernel
{
ASSERT(is_canonical(vaddr));
ASSERT(vaddr);
ASSERT(paddr % PAGE_SIZE == 0);
ASSERT(vaddr % PAGE_SIZE == 0);
size_t first_page = vaddr / PAGE_SIZE;
size_t last_page = (vaddr + size - 1) / PAGE_SIZE;
size_t page_count = last_page - first_page + 1;
size_t page_count = range_page_count(vaddr, size);
LockGuard _(m_lock);
for (size_t page = 0; page < page_count; page++)
@ -430,6 +521,8 @@ namespace Kernel
vaddr_t PageTable::reserve_free_page(vaddr_t first_address, vaddr_t last_address)
{
if (first_address >= KERNEL_OFFSET && first_address < (vaddr_t)g_kernel_end)
first_address = (vaddr_t)g_kernel_end;
if (size_t rem = first_address % PAGE_SIZE)
first_address += PAGE_SIZE - rem;
if (size_t rem = last_address % PAGE_SIZE)
@ -487,8 +580,9 @@ namespace Kernel
vaddr |= (uint64_t)pdpte << 30;
vaddr |= (uint64_t)pde << 21;
vaddr |= (uint64_t)pte << 12;
vaddr = canonicalize(vaddr);
ASSERT(reserve_page(vaddr));
return canonicalize(vaddr);
return vaddr;
}
}
}
@ -512,6 +606,8 @@ namespace Kernel
vaddr_t PageTable::reserve_free_contiguous_pages(size_t page_count, vaddr_t first_address, vaddr_t last_address)
{
if (first_address >= KERNEL_OFFSET && first_address < (vaddr_t)g_kernel_start)
first_address = (vaddr_t)g_kernel_start;
if (size_t rem = first_address % PAGE_SIZE)
first_address += PAGE_SIZE - rem;
if (size_t rem = last_address % PAGE_SIZE)

View File

@ -38,6 +38,7 @@ namespace Kernel
BAN::RefPtr<Inode> m_inode;
const off_t m_offset;
// FIXME: is this even synchronized?
BAN::RefPtr<SharedFileData> m_shared_data;
};

View File

@ -1,46 +0,0 @@
#pragma once
#include <BAN/LinkedList.h>
#include <BAN/Optional.h>
#include <BAN/UniqPtr.h>
#include <kernel/Memory/Heap.h>
#include <kernel/Memory/PageTable.h>
namespace Kernel
{
class GeneralAllocator
{
BAN_NON_COPYABLE(GeneralAllocator);
BAN_NON_MOVABLE(GeneralAllocator);
public:
static BAN::ErrorOr<BAN::UniqPtr<GeneralAllocator>> create(PageTable&, vaddr_t first_vaddr);
~GeneralAllocator();
BAN::ErrorOr<BAN::UniqPtr<GeneralAllocator>> clone(PageTable&);
BAN::Optional<paddr_t> paddr_of(vaddr_t);
vaddr_t allocate(size_t);
bool deallocate(vaddr_t);
private:
GeneralAllocator(PageTable&, vaddr_t first_vaddr);
private:
struct Allocation
{
vaddr_t address { 0 };
BAN::Vector<paddr_t> pages;
bool contains(vaddr_t);
};
private:
PageTable& m_page_table;
BAN::LinkedList<Allocation> m_allocations;
const vaddr_t m_first_vaddr;
};
}

View File

@ -29,6 +29,24 @@ namespace Kernel
static PageTable& kernel();
static PageTable& current();
static void map_fast_page(paddr_t);
static void unmap_fast_page();
static constexpr vaddr_t fast_page() { return KERNEL_OFFSET; }
// FIXME: implement sized checks, return span, etc
static void* fast_page_as_ptr(size_t offset = 0)
{
ASSERT(offset <= PAGE_SIZE);
return reinterpret_cast<void*>(fast_page() + offset);
}
template<typename T>
static T& fast_page_as(size_t offset = 0)
{
ASSERT(offset + sizeof(T) <= PAGE_SIZE);
return *reinterpret_cast<T*>(fast_page() + offset);
}
static bool is_valid_pointer(uintptr_t);
static BAN::ErrorOr<PageTable*> create_userspace();
@ -64,7 +82,8 @@ namespace Kernel
uint64_t get_page_data(vaddr_t) const;
void initialize_kernel();
void map_kernel_memory();
void invalidate(vaddr_t);
void prepare_fast_page();
static void invalidate(vaddr_t);
private:
paddr_t m_highest_paging_struct { 0 };

View File

@ -11,11 +11,11 @@ namespace Kernel::detail
template<typename... Args>
__attribute__((__noreturn__))
static void panic_impl(const char* file, int line, const char* message, Args... args)
static void panic_impl(const char* file, int line, const char* message, Args&&... args)
{
asm volatile("cli");
derrorln("Kernel panic at {}:{}", file, line);
derrorln(message, args...);
derrorln(message, BAN::forward<Args>(args)...);
if (!g_paniced)
{
g_paniced = true;

View File

@ -71,6 +71,7 @@ namespace Kernel
vaddr_t stack_base() const { return m_stack->vaddr(); }
size_t stack_size() const { return m_stack->size(); }
VirtualRange& stack() { return *m_stack; }
VirtualRange& interrupt_stack() { return *m_interrupt_stack; }
vaddr_t interrupt_stack_base() const { return m_interrupt_stack ? m_interrupt_stack->vaddr() : 0; }
size_t interrupt_stack_size() const { return m_interrupt_stack ? m_interrupt_stack->size() : 0; }

View File

@ -117,33 +117,33 @@ namespace Kernel
if (rsdp->revision >= 2)
{
PageTable::kernel().map_page_at(rsdp->xsdt_address & PAGE_ADDR_MASK, 0, PageTable::Flags::Present);
const XSDT* xsdt = (const XSDT*)(rsdp->xsdt_address % PAGE_SIZE);
BAN::ScopeGuard _([xsdt] { PageTable::kernel().unmap_page(0); });
PageTable::map_fast_page(rsdp->xsdt_address & PAGE_ADDR_MASK);
auto& xsdt = PageTable::fast_page_as<const XSDT>(rsdp->xsdt_address % PAGE_SIZE);
BAN::ScopeGuard _([] { PageTable::unmap_fast_page(); });
if (memcmp(xsdt->signature, "XSDT", 4) != 0)
if (memcmp(xsdt.signature, "XSDT", 4) != 0)
return BAN::Error::from_error_code(ErrorCode::ACPI_RootInvalid);
if (!is_valid_std_header(xsdt))
if (!is_valid_std_header(&xsdt))
return BAN::Error::from_error_code(ErrorCode::ACPI_RootInvalid);
m_header_table_paddr = (paddr_t)xsdt->entries + (rsdp->rsdt_address & PAGE_ADDR_MASK);
m_header_table_paddr = rsdp->xsdt_address + offsetof(XSDT, entries);
m_entry_size = 8;
root_entry_count = (xsdt->length - sizeof(SDTHeader)) / 8;
root_entry_count = (xsdt.length - sizeof(SDTHeader)) / 8;
}
else
{
PageTable::kernel().map_page_at(rsdp->rsdt_address & PAGE_ADDR_MASK, 0, PageTable::Flags::Present);
const RSDT* rsdt = (const RSDT*)((vaddr_t)rsdp->rsdt_address % PAGE_SIZE);
BAN::ScopeGuard _([rsdt] { PageTable::kernel().unmap_page(0); });
PageTable::map_fast_page(rsdp->rsdt_address & PAGE_ADDR_MASK);
auto& rsdt = PageTable::fast_page_as<const RSDT>(rsdp->rsdt_address % PAGE_SIZE);
BAN::ScopeGuard _([] { PageTable::unmap_fast_page(); });
if (memcmp(rsdt->signature, "RSDT", 4) != 0)
if (memcmp(rsdt.signature, "RSDT", 4) != 0)
return BAN::Error::from_error_code(ErrorCode::ACPI_RootInvalid);
if (!is_valid_std_header(rsdt))
if (!is_valid_std_header(&rsdt))
return BAN::Error::from_error_code(ErrorCode::ACPI_RootInvalid);
m_header_table_paddr = (paddr_t)rsdt->entries + (rsdp->rsdt_address & PAGE_ADDR_MASK);
m_header_table_paddr = rsdp->rsdt_address + offsetof(RSDT, entries);
m_entry_size = 4;
root_entry_count = (rsdt->length - sizeof(SDTHeader)) / 4;
root_entry_count = (rsdt.length - sizeof(SDTHeader)) / 4;
}
size_t needed_pages = range_page_count(m_header_table_paddr, root_entry_count * m_entry_size);
@ -162,9 +162,9 @@ namespace Kernel
auto map_header =
[](paddr_t header_paddr) -> vaddr_t
{
PageTable::kernel().map_page_at(header_paddr & PAGE_ADDR_MASK, 0, PageTable::Flags::Present);
size_t header_length = ((SDTHeader*)(header_paddr % PAGE_SIZE))->length;
PageTable::kernel().unmap_page(0);
PageTable::map_fast_page(header_paddr & PAGE_ADDR_MASK);
size_t header_length = PageTable::fast_page_as<SDTHeader>(header_paddr % PAGE_SIZE).length;
PageTable::unmap_fast_page();
size_t needed_pages = range_page_count(header_paddr, header_length);
vaddr_t page_vaddr = PageTable::kernel().reserve_free_contiguous_pages(needed_pages, KERNEL_OFFSET);
@ -211,7 +211,10 @@ namespace Kernel
if (memcmp(header->signature, "FACP", 4) == 0)
{
auto* fadt = (FADT*)header;
paddr_t dsdt_paddr = fadt->x_dsdt;
paddr_t dsdt_paddr = 0;
if (fadt->length > offsetof(FADT, x_dsdt))
dsdt_paddr = fadt->x_dsdt;
if (dsdt_paddr == 0 || !PageTable::is_valid_pointer(dsdt_paddr))
dsdt_paddr = fadt->dsdt;

View File

@ -274,6 +274,9 @@ namespace Kernel
{
ASSERT(m_inode.links_count == 0);
if (mode().iflnk() && (size_t)size() < sizeof(m_inode.block))
goto done;
// cleanup direct blocks
for (uint32_t i = 0; i < 12; i++)
if (m_inode.block[i])
@ -287,6 +290,7 @@ namespace Kernel
if (m_inode.block[14])
cleanup_indirect_block(m_inode.block[14], 3);
done:
// mark blocks as deleted
memset(m_inode.block, 0x00, sizeof(m_inode.block));
@ -759,7 +763,7 @@ needs_new_block:
if (data_block_index < indices_per_fs_block * indices_per_fs_block)
return TRY(allocate_new_block_to_indirect_block(m_inode.block[13], data_block_index, 2));
data_block_index -= indices_per_fs_block;
data_block_index -= indices_per_fs_block * indices_per_fs_block;
if (data_block_index < indices_per_fs_block * indices_per_fs_block * indices_per_fs_block)
return TRY(allocate_new_block_to_indirect_block(m_inode.block[14], data_block_index, 3));

View File

@ -1,3 +1,4 @@
#include <kernel/CriticalScope.h>
#include <kernel/LockGuard.h>
#include <kernel/Memory/FileBackedRegion.h>
#include <kernel/Memory/Heap.h>
@ -71,13 +72,10 @@ namespace Kernel
continue;
{
auto& page_table = PageTable::current();
LockGuard _(page_table);
ASSERT(page_table.is_page_free(0));
page_table.map_page_at(pages[i], 0, PageTable::Flags::Present);
memcpy(page_buffer, (void*)0, PAGE_SIZE);
page_table.unmap_page(0);
CriticalScope _;
PageTable::map_fast_page(pages[i]);
memcpy(page_buffer, PageTable::fast_page_as_ptr(), PAGE_SIZE);
PageTable::unmap_fast_page();
}
if (auto ret = inode->write(i * PAGE_SIZE, BAN::ConstByteSpan::from(page_buffer)); ret.is_error())
@ -100,28 +98,15 @@ namespace Kernel
paddr_t paddr = Heap::get().take_free_page();
if (paddr == 0)
return BAN::Error::from_errno(ENOMEM);
m_page_table.map_page_at(paddr, vaddr, m_flags);
// Temporarily force mapping to be writable so kernel can write to it
m_page_table.map_page_at(paddr, vaddr, m_flags | PageTable::Flags::ReadWrite);
size_t file_offset = m_offset + (vaddr - m_vaddr);
size_t bytes = BAN::Math::min<size_t>(m_size - file_offset, PAGE_SIZE);
BAN::ErrorOr<size_t> read_ret = 0;
// Zero out the new page
if (&PageTable::current() == &m_page_table)
read_ret = m_inode->read(file_offset, BAN::ByteSpan((uint8_t*)vaddr, bytes));
else
{
auto& page_table = PageTable::current();
LockGuard _(page_table);
ASSERT(page_table.is_page_free(0));
page_table.map_page_at(paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
read_ret = m_inode->read(file_offset, BAN::ByteSpan((uint8_t*)0, bytes));
memset((void*)0, 0x00, PAGE_SIZE);
page_table.unmap_page(0);
}
ASSERT_EQ(&PageTable::current(), &m_page_table);
auto read_ret = m_inode->read(file_offset, BAN::ByteSpan((uint8_t*)vaddr, bytes));
if (read_ret.is_error())
{
@ -137,6 +122,10 @@ namespace Kernel
m_page_table.unmap_page(vaddr);
return BAN::Error::from_errno(EIO);
}
// Disable writable if not wanted
if (!(m_flags & PageTable::Flags::ReadWrite))
m_page_table.map_page_at(paddr, vaddr, m_flags);
}
else if (m_type == Type::SHARED)
{
@ -158,15 +147,10 @@ namespace Kernel
TRY(m_inode->read(offset, BAN::ByteSpan(m_shared_data->page_buffer, bytes)));
auto& page_table = PageTable::current();
// TODO: check if this can cause deadlock?
LockGuard page_table_lock(page_table);
ASSERT(page_table.is_page_free(0));
page_table.map_page_at(pages[page_index], 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
memcpy((void*)0, m_shared_data->page_buffer, PAGE_SIZE);
page_table.unmap_page(0);
CriticalScope _;
PageTable::map_fast_page(pages[page_index]);
memcpy(PageTable::fast_page_as_ptr(), m_shared_data->page_buffer, PAGE_SIZE);
PageTable::unmap_fast_page();
}
paddr_t paddr = pages[page_index];

View File

@ -1,145 +0,0 @@
#include <kernel/Memory/GeneralAllocator.h>
namespace Kernel
{
BAN::ErrorOr<BAN::UniqPtr<GeneralAllocator>> GeneralAllocator::create(PageTable& page_table, vaddr_t first_vaddr)
{
auto* allocator = new GeneralAllocator(page_table, first_vaddr);
if (allocator == nullptr)
return BAN::Error::from_errno(ENOMEM);
return BAN::UniqPtr<GeneralAllocator>::adopt(allocator);
}
GeneralAllocator::GeneralAllocator(PageTable& page_table, vaddr_t first_vaddr)
: m_page_table(page_table)
, m_first_vaddr(first_vaddr)
{ }
GeneralAllocator::~GeneralAllocator()
{
while (!m_allocations.empty())
deallocate(m_allocations.front().address);
}
vaddr_t GeneralAllocator::allocate(size_t bytes)
{
size_t needed_pages = BAN::Math::div_round_up<size_t>(bytes, PAGE_SIZE);
Allocation allocation;
if (allocation.pages.resize(needed_pages, 0).is_error())
return 0;
for (size_t i = 0; i < needed_pages; i++)
{
paddr_t paddr = Heap::get().take_free_page();
if (paddr == 0)
{
for (size_t j = 0; j < i; j++)
Heap::get().release_page(allocation.pages[j]);
return 0;
}
allocation.pages[i] = paddr;
}
m_page_table.lock();
allocation.address = m_page_table.reserve_free_contiguous_pages(needed_pages, m_first_vaddr);
ASSERT(allocation.address);
for (size_t i = 0; i < needed_pages; i++)
{
vaddr_t vaddr = allocation.address + i * PAGE_SIZE;
m_page_table.map_page_at(allocation.pages[i], vaddr, PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present);
}
if (&m_page_table == &PageTable::current())
m_page_table.load();
m_page_table.unlock();
MUST(m_allocations.push_back(BAN::move(allocation)));
return allocation.address;
}
bool GeneralAllocator::deallocate(vaddr_t address)
{
for (auto it = m_allocations.begin(); it != m_allocations.end(); it++)
{
if (it->address != address)
continue;
m_page_table.unmap_range(it->address, it->pages.size() * PAGE_SIZE);
for (auto paddr : it->pages)
Heap::get().release_page(paddr);
m_allocations.remove(it);
return true;
}
return false;
}
BAN::ErrorOr<BAN::UniqPtr<GeneralAllocator>> GeneralAllocator::clone(PageTable& new_page_table)
{
auto allocator = TRY(GeneralAllocator::create(new_page_table, m_first_vaddr));
m_page_table.lock();
ASSERT(m_page_table.is_page_free(0));
for (auto& allocation : m_allocations)
{
Allocation new_allocation;
ASSERT(new_page_table.is_range_free(allocation.address, allocation.pages.size() * PAGE_SIZE));
new_allocation.address = allocation.address;
MUST(new_allocation.pages.reserve(allocation.pages.size()));
PageTable::flags_t flags = m_page_table.get_page_flags(allocation.address);
for (size_t i = 0; i < allocation.pages.size(); i++)
{
paddr_t paddr = Heap::get().take_free_page();
ASSERT(paddr);
vaddr_t vaddr = allocation.address + i * PAGE_SIZE;
MUST(new_allocation.pages.push_back(paddr));
new_page_table.map_page_at(paddr, vaddr, flags);
m_page_table.map_page_at(paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
memcpy((void*)0, (void*)vaddr, PAGE_SIZE);
}
MUST(allocator->m_allocations.push_back(BAN::move(new_allocation)));
}
m_page_table.unmap_page(0);
m_page_table.unlock();
return allocator;
}
BAN::Optional<paddr_t> GeneralAllocator::paddr_of(vaddr_t vaddr)
{
for (auto& allocation : m_allocations)
{
if (!allocation.contains(vaddr))
continue;
size_t offset = vaddr - allocation.address;
size_t page_index = offset / PAGE_SIZE;
size_t page_offset = offset % PAGE_SIZE;
return allocation.pages[page_index] + page_offset;
}
return {};
}
bool GeneralAllocator::Allocation::contains(vaddr_t vaddr)
{
return this->address <= vaddr && vaddr < this->address + this->pages.size() * PAGE_SIZE;
}
}

View File

@ -1,3 +1,4 @@
#include <kernel/CriticalScope.h>
#include <kernel/LockGuard.h>
#include <kernel/Memory/Heap.h>
#include <kernel/Memory/MemoryBackedRegion.h>
@ -60,12 +61,10 @@ namespace Kernel
memset((void*)vaddr, 0x00, PAGE_SIZE);
else
{
LockGuard _(PageTable::current());
ASSERT(PageTable::current().is_page_free(0));
PageTable::current().map_page_at(paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
memset((void*)0, 0x00, PAGE_SIZE);
PageTable::current().unmap_page(0);
CriticalScope _;
PageTable::map_fast_page(paddr);
memset(PageTable::fast_page_as_ptr(), 0x00, PAGE_SIZE);
PageTable::unmap_fast_page();
}
return true;
@ -105,15 +104,10 @@ namespace Kernel
memcpy((void*)write_vaddr, (void*)(buffer + written), bytes);
else
{
paddr_t paddr = m_page_table.physical_address_of(write_vaddr & PAGE_ADDR_MASK);
ASSERT(paddr);
LockGuard _(PageTable::current());
ASSERT(PageTable::current().is_page_free(0));
PageTable::current().map_page_at(paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
memcpy((void*)page_offset, (void*)(buffer + written), bytes);
PageTable::current().unmap_page(0);
CriticalScope _;
PageTable::map_fast_page(m_page_table.physical_address_of(write_vaddr & PAGE_ADDR_MASK));
memcpy(PageTable::fast_page_as_ptr(page_offset), (void*)(buffer + written), bytes);
PageTable::unmap_fast_page();
}
written += bytes;

View File

@ -1,3 +1,4 @@
#include <kernel/CriticalScope.h>
#include <kernel/LockGuard.h>
#include <kernel/Memory/Heap.h>
#include <kernel/Memory/VirtualRange.h>
@ -124,7 +125,6 @@ namespace Kernel
auto result = TRY(create_to_vaddr(page_table, vaddr(), size(), flags(), m_preallocated));
LockGuard _(m_page_table);
ASSERT(m_page_table.is_page_free(0));
for (size_t offset = 0; offset < size(); offset += PAGE_SIZE)
{
if (!m_preallocated && m_page_table.physical_address_of(vaddr() + offset))
@ -134,10 +134,12 @@ namespace Kernel
return BAN::Error::from_errno(ENOMEM);
result->m_page_table.map_page_at(paddr, vaddr() + offset, m_flags);
}
m_page_table.map_page_at(result->m_page_table.physical_address_of(vaddr() + offset), 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
memcpy((void*)0, (void*)(vaddr() + offset), PAGE_SIZE);
CriticalScope _;
PageTable::map_fast_page(result->m_page_table.physical_address_of(vaddr() + offset));
memcpy(PageTable::fast_page_as_ptr(), (void*)(vaddr() + offset), PAGE_SIZE);
PageTable::unmap_fast_page();
}
m_page_table.unmap_page(0);
return result;
}
@ -172,14 +174,13 @@ namespace Kernel
return;
}
LockGuard _(page_table);
ASSERT(page_table.is_page_free(0));
for (size_t offset = 0; offset < size(); offset += PAGE_SIZE)
{
page_table.map_page_at(m_page_table.physical_address_of(vaddr() + offset), 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
memset((void*)0, 0, PAGE_SIZE);
CriticalScope _;
PageTable::map_fast_page(m_page_table.physical_address_of(vaddr() + offset));
memset(PageTable::fast_page_as_ptr(), 0x00, PAGE_SIZE);
PageTable::unmap_fast_page();
}
page_table.unmap_page(0);
}
void VirtualRange::copy_from(size_t offset, const uint8_t* buffer, size_t bytes)
@ -187,47 +188,34 @@ namespace Kernel
if (bytes == 0)
return;
// NOTE: Handling overflow
ASSERT(offset <= size());
ASSERT(bytes <= size());
ASSERT(offset + bytes <= size());
// Verify no overflow
ASSERT_LTE(bytes, size());
ASSERT_LTE(offset, size());
ASSERT_LTE(offset, size() - bytes);
PageTable& page_table = PageTable::current();
if (m_kmalloc || &page_table == &m_page_table)
if (m_kmalloc || &PageTable::current() == &m_page_table)
{
memcpy((void*)(vaddr() + offset), buffer, bytes);
return;
}
LockGuard _(page_table);
ASSERT(page_table.is_page_free(0));
size_t off = offset % PAGE_SIZE;
size_t i = offset / PAGE_SIZE;
// NOTE: we map the first page separately since it needs extra calculations
page_table.map_page_at(m_page_table.physical_address_of(vaddr() + i * PAGE_SIZE), 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
memcpy((void*)off, buffer, PAGE_SIZE - off);
buffer += PAGE_SIZE - off;
bytes -= PAGE_SIZE - off;
i++;
size_t page_offset = offset % PAGE_SIZE;
size_t page_index = offset / PAGE_SIZE;
while (bytes > 0)
{
size_t len = BAN::Math::min<size_t>(PAGE_SIZE, bytes);
{
CriticalScope _;
PageTable::map_fast_page(m_page_table.physical_address_of(vaddr() + page_index * PAGE_SIZE));
memcpy(PageTable::fast_page_as_ptr(page_offset), buffer, PAGE_SIZE - page_offset);
PageTable::unmap_fast_page();
}
page_table.map_page_at(m_page_table.physical_address_of(vaddr() + i * PAGE_SIZE), 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
memcpy((void*)0, buffer, len);
buffer += len;
bytes -= len;
i++;
buffer += PAGE_SIZE - page_offset;
bytes -= PAGE_SIZE - page_offset;
page_offset = 0;
page_index++;
}
page_table.unmap_page(0);
}
}

View File

@ -1,7 +1,6 @@
#include <BAN/Errors.h>
#include <kernel/CriticalScope.h>
#include <kernel/kprint.h>
#include <kernel/Memory/GeneralAllocator.h>
#include <kernel/Memory/kmalloc.h>
#include <kernel/Thread.h>

View File

@ -47,9 +47,9 @@ namespace Kernel
continue;
CriticalScope _;
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::Present);
memcpy(buffer.data(), (void*)(page_cache_offset * m_sector_size), m_sector_size);
page_table.unmap_page(0);
PageTable::map_fast_page(cache.paddr);
memcpy(buffer.data(), PageTable::fast_page_as_ptr(page_cache_offset * m_sector_size), m_sector_size);
PageTable::unmap_fast_page();
return true;
}
@ -82,9 +82,9 @@ namespace Kernel
{
CriticalScope _;
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
memcpy((void*)(page_cache_offset * m_sector_size), buffer.data(), m_sector_size);
page_table.unmap_page(0);
PageTable::map_fast_page(cache.paddr);
memcpy(PageTable::fast_page_as_ptr(page_cache_offset * m_sector_size), buffer.data(), m_sector_size);
PageTable::unmap_fast_page();
}
cache.sector_mask |= 1 << page_cache_offset;
@ -113,9 +113,9 @@ namespace Kernel
{
CriticalScope _;
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
memcpy((void*)(page_cache_offset * m_sector_size), buffer.data(), m_sector_size);
page_table.unmap_page(0);
PageTable::map_fast_page(cache.paddr);
memcpy(PageTable::fast_page_as_ptr(page_cache_offset * m_sector_size), buffer.data(), m_sector_size);
PageTable::unmap_fast_page();
}
return {};
@ -123,21 +123,16 @@ namespace Kernel
BAN::ErrorOr<void> DiskCache::sync()
{
ASSERT(&PageTable::current() == &PageTable::kernel());
auto& page_table = PageTable::kernel();
for (auto& cache : m_cache)
{
if (cache.dirty_mask == 0)
continue;
{
LockGuard _(page_table);
ASSERT(page_table.is_page_free(0));
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::Present);
memcpy(m_sync_cache.data(), (void*)0, PAGE_SIZE);
page_table.unmap_page(0);
CriticalScope _;
PageTable::map_fast_page(cache.paddr);
memcpy(m_sync_cache.data(), PageTable::fast_page_as_ptr(), PAGE_SIZE);
PageTable::unmap_fast_page();
}
uint8_t sector_start = 0;

View File

@ -79,9 +79,6 @@ static void parse_command_line()
}
}
extern "C" uint8_t g_userspace_start[];
extern "C" uint8_t g_userspace_end[];
TerminalDriver* g_terminal_driver = nullptr;
static void init2(void*);

View File

@ -26,21 +26,32 @@ set(LIBC_SOURCES
)
add_custom_target(libc-headers
COMMAND sudo rsync -a ${CMAKE_CURRENT_SOURCE_DIR}/include/ ${BANAN_INCLUDE}/
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_CURRENT_SOURCE_DIR}/include/ ${BANAN_INCLUDE}/
DEPENDS sysroot
USES_TERMINAL
)
add_custom_target(crtx
COMMAND ${CMAKE_C_COMPILER} -c ${CMAKE_CURRENT_SOURCE_DIR}/arch/${BANAN_ARCH}/crt0.S -o crt0.o
COMMAND ${CMAKE_C_COMPILER} -c ${CMAKE_CURRENT_SOURCE_DIR}/arch/${BANAN_ARCH}/crti.S -o crti.o
COMMAND ${CMAKE_C_COMPILER} -c ${CMAKE_CURRENT_SOURCE_DIR}/arch/${BANAN_ARCH}/crtn.S -o crtn.o
)
add_custom_target(crtx-install
COMMAND ${CMAKE_COMMAND} -E copy crt0.o ${BANAN_LIB}/
COMMAND ${CMAKE_COMMAND} -E copy crti.o ${BANAN_LIB}/
COMMAND ${CMAKE_COMMAND} -E copy crtn.o ${BANAN_LIB}/
DEPENDS crtx
)
add_library(libc ${LIBC_SOURCES})
add_dependencies(libc headers crt0)
add_dependencies(libc headers crtx-install)
target_compile_options(libc PRIVATE -g -Wstack-usage=512)
add_custom_target(libc-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/libc.a ${BANAN_LIB}/
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/libc.a ${BANAN_LIB}/
DEPENDS libc
BYPRODUCTS ${BANAN_LIB}/libc.a
USES_TERMINAL
)
set(CMAKE_STATIC_LIBRARY_PREFIX "")

View File

@ -8,19 +8,19 @@ _start:
pushq %rbp # rbp=0
movq %rsp, %rbp
# We need those in a moment when we call main.
# Save argc, argv, environ
pushq %rdx
pushq %rsi
pushq %rdi
# Prepare signals, memory allocation, stdio and such.
# Prepare malloc, environment
movq %rdx, %rdi
call _init_libc
# Run the global constructors.
# Call global constructos
call _init
# Restore argc and argv.
# Restore argc, argv, environ
popq %rdi
popq %rsi
popq %rdx
@ -28,7 +28,8 @@ _start:
# Run main
call main
# Terminate the process with the exit code.
# Cleanly exit the process
movl %eax, %edi
call exit
.size _start, . - _start

16
libc/arch/x86_64/crti.S Normal file
View File

@ -0,0 +1,16 @@
/* x86-64 crti.s */
.section .init
.global _init
.type _init, @function
_init:
pushq %rbp
movq %rsp, %rbp
/* gcc will nicely put the contents of crtbegin.o's .init section here. */
.section .fini
.global _fini
.type _fini, @function
_fini:
pushq %rbp
movq %rsp, %rbp
/* gcc will nicely put the contents of crtbegin.o's .fini section here. */

10
libc/arch/x86_64/crtn.S Normal file
View File

@ -0,0 +1,10 @@
/* x86-64 crtn.s */
.section .init
/* gcc will nicely put the contents of crtend.o's .init section here. */
popq %rbp
ret
.section .fini
/* gcc will nicely put the contents of crtend.o's .fini section here. */
popq %rbp
ret

View File

@ -1,35 +1,37 @@
#include <icxxabi.h>
#define ATEXIT_MAX_FUNCS 128
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned uarch_t;
struct atexit_func_entry_t
{
/*
* Each member is at least 4 bytes large. Such that each entry is 12bytes.
* 128 * 12 = 1.5KB exact.
**/
void (*destructor_func)(void *);
void *obj_ptr;
void *dso_handle;
void (*destructor)(void*);
void* data;
void* dso_handle;
};
atexit_func_entry_t __atexit_funcs[ATEXIT_MAX_FUNCS];
uarch_t __atexit_func_count = 0;
static atexit_func_entry_t __atexit_funcs[ATEXIT_MAX_FUNCS];
static int __atexit_func_count = 0;
int __cxa_atexit(void (*f)(void *), void *objptr, void *dso)
int __cxa_atexit(void (*func)(void*), void* data, void* dso_handle)
{
if (__atexit_func_count >= ATEXIT_MAX_FUNCS) {return -1;};
__atexit_funcs[__atexit_func_count].destructor_func = f;
__atexit_funcs[__atexit_func_count].obj_ptr = objptr;
__atexit_funcs[__atexit_func_count].dso_handle = dso;
if (__atexit_func_count >= ATEXIT_MAX_FUNCS)
return -1;;
__atexit_funcs[__atexit_func_count].destructor = func;
__atexit_funcs[__atexit_func_count].data = data;
__atexit_funcs[__atexit_func_count].dso_handle = dso_handle;
__atexit_func_count++;
return 0; /*I would prefer if functions returned 1 on success, but the ABI says...*/
return 0;
};
#ifdef __cplusplus
};
#endif
void __cxa_finalize(void* func)
{
for (int i = __atexit_func_count - 1; i >= 0; i--)
{
if (func && func != __atexit_funcs[i].destructor)
continue;
if (__atexit_funcs[i].destructor == nullptr)
continue;
__atexit_funcs[i].destructor(__atexit_funcs[i].data);
__atexit_funcs[i].destructor = nullptr;
}
}

10
libc/include/icxxabi.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include <sys/cdefs.h>
__BEGIN_DECLS
int __cxa_atexit(void (*func)(void*), void* data, void* dso_handle);
void __cxa_finalize(void* func);
__END_DECLS

View File

@ -7,6 +7,8 @@
#include <sys/syscall.h>
#include <unistd.h>
#include <icxxabi.h>
extern "C" char** environ;
extern "C" void _fini();
@ -21,6 +23,7 @@ void abort(void)
void exit(int status)
{
fflush(nullptr);
__cxa_finalize(nullptr);
_fini();
_exit(status);
ASSERT_NOT_REACHED();

View File

@ -4,6 +4,12 @@ set -e
export BANAN_SCRIPT_DIR=$(dirname $(realpath $0))
source $BANAN_SCRIPT_DIR/config.sh
FAKEROOT_FILE="$BANAN_BUILD_DIR/fakeroot-context"
run_fakeroot() {
fakeroot -i $FAKEROOT_FILE -s $FAKEROOT_FILE -- /bin/bash -c '$@' bash $@
}
make_build_dir () {
mkdir -p $BANAN_BUILD_DIR
cd $BANAN_BUILD_DIR
@ -19,7 +25,7 @@ build_target () {
exit 1
fi
cd $BANAN_BUILD_DIR
ninja $1
run_fakeroot ninja $1
}
build_toolchain () {
@ -39,11 +45,7 @@ build_toolchain () {
create_image () {
build_target install-sysroot
if [[ "$1" == "full" ]]; then
$BANAN_SCRIPT_DIR/image-full.sh
else
$BANAN_SCRIPT_DIR/image.sh
fi
$BANAN_SCRIPT_DIR/image.sh "$1"
}
run_qemu () {
@ -56,7 +58,7 @@ run_bochs () {
$BANAN_SCRIPT_DIR/bochs.sh $@
}
if [[ "$(uname)" == "Linux" ]]; then
if [[ -c /dev/kvm ]]; then
QEMU_ACCEL="-accel kvm"
fi

View File

@ -18,6 +18,7 @@ export BANAN_TOOLCHAIN_TRIPLE_PREFIX=$BANAN_ARCH-banan_os
export BANAN_BUILD_DIR=$BANAN_ROOT_DIR/build
export BANAN_SYSROOT=$BANAN_BUILD_DIR/sysroot
export BANAN_SYSROOT_TAR=$BANAN_SYSROOT.tar
export BANAN_DISK_IMAGE_PATH=$BANAN_BUILD_DIR/banan-os.img

View File

@ -72,7 +72,7 @@ sudo partprobe $LOOP_DEV
PARTITION1=${LOOP_DEV}p1
PARTITION2=${LOOP_DEV}p2
sudo mkfs.ext2 -d $BANAN_SYSROOT -b 1024 -q $PARTITION2
sudo mkfs.ext2 -b 1024 -q $PARTITION2
if [[ "$BANAN_UEFI_BOOT" == "1" ]]; then
sudo mkfs.fat $PARTITION1 > /dev/null

View File

@ -1,44 +1,38 @@
#!/bin/bash
if [[ -z $BANAN_ROOT_DIR ]]; then
echo "You must set the BANAN_ROOT_DIR environment variable" >&2
exit 1
fi
if [[ -z $BANAN_DISK_IMAGE_PATH ]]; then
echo "You must set the BANAN_DISK_IMAGE_PATH environment variable" >&2
exit 1
fi
if [[ -z $BANAN_SYSROOT ]]; then
echo "You must set the BANAN_SYSROOT environment variable" >&2
if [[ -z $BANAN_SYSROOT_TAR ]]; then
echo "You must set the BANAN_SYSROOT_TAR environment variable" >&2
exit 1
fi
if [[ ! -f $BANAN_DISK_IMAGE_PATH ]]; then
$BANAN_SCRIPT_DIR/image-full.sh
exit 0
if [[ "$1" == "full" ]] || [[ ! -f $BANAN_DISK_IMAGE_PATH ]]; then
$BANAN_SCRIPT_DIR/image-create.sh
else
fdisk -l $BANAN_DISK_IMAGE_PATH | grep -q 'EFI System'; IMAGE_IS_UEFI=$?
[[ $BANAN_UEFI_BOOT == 1 ]]; CREATE_IS_UEFI=$?
if [[ $IMAGE_IS_UEFI -ne $CREATE_IS_UEFI ]]; then
echo Converting disk image to/from UEFI
$BANAN_SCRIPT_DIR/image-create.sh
fi
fi
fdisk -l $BANAN_DISK_IMAGE_PATH | grep -q 'EFI System'; IMAGE_IS_UEFI=$?
[[ $BANAN_UEFI_BOOT == 1 ]]; CREATE_IS_UEFI=$?
if [[ $IMAGE_IS_UEFI -ne $CREATE_IS_UEFI ]]; then
echo Converting disk image to/from UEFI
$BANAN_SCRIPT_DIR/image-full.sh
exit 0
fi
MOUNT_DIR=/mnt
LOOP_DEV=$(sudo losetup -f --show $BANAN_DISK_IMAGE_PATH)
LOOP_DEV=$(sudo losetup --show -f "$BANAN_DISK_IMAGE_PATH")
sudo partprobe $LOOP_DEV
ROOT_PARTITON=${LOOP_DEV}p2
ROOT_PARTITION=${LOOP_DEV}p2
MOUNT_DIR=/mnt
sudo mount $ROOT_PARTITON $MOUNT_DIR
sudo mount $ROOT_PARTITION $MOUNT_DIR
sudo rsync -a ${BANAN_SYSROOT}/* ${MOUNT_DIR}/
cd $MOUNT_DIR
sudo tar xf $BANAN_SYSROOT_TAR
cd
sudo umount $MOUNT_DIR

View File

@ -1,9 +1,19 @@
if (NOT DEFINED ENV{BANAN_ARCH})
message(FATAL_ERROR "environment variable BANAN_ARCH not defined")
endif ()
set(BANAN_ARCH $ENV{BANAN_ARCH})
if (NOT DEFINED ENV{BANAN_SYSROOT})
message(FATAL_ERROR "environment variable BANAN_SYSROOT not defined")
endif ()
set(BANAN_SYSROOT $ENV{BANAN_SYSROOT})
if (NOT DEFINED ENV{BANAN_SYSROOT_TAR})
message(FATAL_ERROR "environment variable BANAN_SYSROOT_TAR not defined")
endif ()
set(BANAN_SYSROOT_TAR $ENV{BANAN_SYSROOT_TAR})
set(TOOLCHAIN_PREFIX ${CMAKE_SOURCE_DIR}/toolchain/local)
set(CMAKE_SYSTEM_NAME banan-os)

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,13 @@
set -e
BINUTILS_VERSION="binutils-2.39"
BINUTILS_GIT="https://sourceware.org/git/binutils-gdb.git"
BINUTILS_BRANCH="binutils-2_39"
GCC_VERSION="gcc-12.2.0"
GCC_GIT="https://gcc.gnu.org/git/gcc.git"
GCC_BRANCH="releases/$GCC_VERSION"
GRUB_VERSION="grub-2.06"
if [[ -z $BANAN_SYSROOT ]]; then
@ -51,22 +57,20 @@ build_binutils () {
cd $BANAN_BUILD_DIR/toolchain
if [ ! -f ${BINUTILS_VERSION}.tar.xz ]; then
wget https://ftp.gnu.org/gnu/binutils/${BINUTILS_VERSION}.tar.xz
fi
if [ ! -d $BINUTILS_VERSION ]; then
tar xvf ${BINUTILS_VERSION}.tar.xz
patch -s -p0 < $BANAN_TOOLCHAIN_DIR/${BINUTILS_VERSION}.patch
git clone --single-branch --branch $BINUTILS_BRANCH $BINUTILS_GIT $BINUTILS_VERSION
cd $BINUTILS_VERSION
git am $BANAN_TOOLCHAIN_DIR/$BINUTILS_VERSION.patch
fi
cd $BINUTILS_VERSION
cd $BANAN_BUILD_DIR/toolchain/$BINUTILS_VERSION
enter_clean_build
../configure \
--target="$BANAN_TOOLCHAIN_TRIPLE_PREFIX" \
--prefix="$BANAN_TOOLCHAIN_PREFIX" \
--with-sysroot="$BANAN_SYSROOT" \
--disable-initfini-array \
--disable-nls \
--disable-werror
@ -79,22 +83,20 @@ build_gcc () {
cd $BANAN_BUILD_DIR/toolchain
if [ ! -f ${GCC_VERSION}.tar.xz ]; then
wget https://ftp.gnu.org/gnu/gcc/${GCC_VERSION}/${GCC_VERSION}.tar.xz
fi
if [ ! -d $GCC_VERSION ]; then
tar xvf ${GCC_VERSION}.tar.xz
patch -s -p0 < $BANAN_TOOLCHAIN_DIR/${GCC_VERSION}.patch
git clone --single-branch --branch $GCC_BRANCH $GCC_GIT $GCC_VERSION
cd $GCC_VERSION
git am $BANAN_TOOLCHAIN_DIR/$GCC_VERSION.patch
fi
cd ${GCC_VERSION}
cd $BANAN_BUILD_DIR/toolchain/$GCC_VERSION
enter_clean_build
../configure \
--target="$BANAN_TOOLCHAIN_TRIPLE_PREFIX" \
--prefix="$BANAN_TOOLCHAIN_PREFIX" \
--with-sysroot="$BANAN_SYSROOT" \
--disable-initfini-array \
--disable-nls \
--enable-languages=c,c++
@ -159,6 +161,9 @@ sudo rsync -a $BANAN_ROOT_DIR/libc/include/ $BANAN_SYSROOT/usr/include/
mkdir -p $BANAN_BUILD_DIR/toolchain
# Cleanup all old files from toolchain prefix
rm -rf $BANAN_TOOLCHAIN_PREFIX
build_binutils
build_gcc
build_grub

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,7 @@ set(USERSPACE_PROJECTS
sync
tee
test
test-globals
touch
u8sum
whoami

View File

@ -11,7 +11,6 @@ target_compile_options(Shell PUBLIC -O2 -g)
target_link_libraries(Shell PUBLIC libc ban)
add_custom_target(Shell-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/Shell ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/Shell ${BANAN_BIN}/
DEPENDS Shell
USES_TERMINAL
)

View File

@ -11,7 +11,6 @@ target_compile_options(cat-mmap PUBLIC -O2 -g)
target_link_libraries(cat-mmap PUBLIC libc)
add_custom_target(cat-mmap-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/cat-mmap ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/cat-mmap ${BANAN_BIN}/
DEPENDS cat-mmap
USES_TERMINAL
)

View File

@ -11,7 +11,6 @@ target_compile_options(cat PUBLIC -O2 -g)
target_link_libraries(cat PUBLIC libc)
add_custom_target(cat-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/cat ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/cat ${BANAN_BIN}/
DEPENDS cat
USES_TERMINAL
)

View File

@ -11,7 +11,6 @@ target_compile_options(chmod PUBLIC -O2 -g)
target_link_libraries(chmod PUBLIC libc)
add_custom_target(chmod-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/chmod ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/chmod ${BANAN_BIN}/
DEPENDS chmod
USES_TERMINAL
)

View File

@ -11,7 +11,6 @@ target_compile_options(cp PUBLIC -O2 -g)
target_link_libraries(cp PUBLIC libc ban)
add_custom_target(cp-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/cp ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/cp ${BANAN_BIN}/
DEPENDS cp
USES_TERMINAL
)

View File

@ -20,9 +20,8 @@ target_compile_options($PROGRAM_NAME PUBLIC -O2 -g)
target_link_libraries($PROGRAM_NAME PUBLIC libc)
add_custom_target($PROGRAM_NAME-install
COMMAND sudo cp \${CMAKE_CURRENT_BINARY_DIR}/$PROGRAM_NAME \${BANAN_BIN}/
COMMAND \${CMAKE_COMMAND} -E copy \${CMAKE_CURRENT_BINARY_DIR}/$PROGRAM_NAME \${BANAN_BIN}/
DEPENDS $PROGRAM_NAME
USES_TERMINAL
)
EOF

View File

@ -11,7 +11,6 @@ target_compile_options(dd PUBLIC -O2 -g)
target_link_libraries(dd PUBLIC libc)
add_custom_target(dd-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/dd ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/dd ${BANAN_BIN}/
DEPENDS dd
USES_TERMINAL
)

View File

@ -11,7 +11,6 @@ target_compile_options(echo PUBLIC -O2 -g)
target_link_libraries(echo PUBLIC libc)
add_custom_target(echo-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/echo ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/echo ${BANAN_BIN}/
DEPENDS echo
USES_TERMINAL
)

View File

@ -11,7 +11,6 @@ target_compile_options(id PUBLIC -O2 -g)
target_link_libraries(id PUBLIC libc ban)
add_custom_target(id-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/id ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/id ${BANAN_BIN}/
DEPENDS id
USES_TERMINAL
)

View File

@ -11,7 +11,6 @@ target_compile_options(init PUBLIC -O2 -g)
target_link_libraries(init PUBLIC libc ban)
add_custom_target(init-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/init ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/init ${BANAN_BIN}/
DEPENDS init
USES_TERMINAL
)

View File

@ -11,7 +11,6 @@ target_compile_options(ls PUBLIC -O2 -g)
target_link_libraries(ls PUBLIC libc)
add_custom_target(ls-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/ls ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/ls ${BANAN_BIN}/
DEPENDS ls
USES_TERMINAL
)

View File

@ -11,7 +11,6 @@ target_compile_options(meminfo PUBLIC -O2 -g)
target_link_libraries(meminfo PUBLIC libc)
add_custom_target(meminfo-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/meminfo ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/meminfo ${BANAN_BIN}/
DEPENDS meminfo
USES_TERMINAL
)

View File

@ -11,7 +11,6 @@ target_compile_options(mkdir PUBLIC -O2 -g)
target_link_libraries(mkdir PUBLIC libc)
add_custom_target(mkdir-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/mkdir ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/mkdir ${BANAN_BIN}/
DEPENDS mkdir
USES_TERMINAL
)

View File

@ -11,7 +11,6 @@ target_compile_options(mmap-shared-test PUBLIC -O2 -g)
target_link_libraries(mmap-shared-test PUBLIC libc)
add_custom_target(mmap-shared-test-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/mmap-shared-test ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/mmap-shared-test ${BANAN_BIN}/
DEPENDS mmap-shared-test
USES_TERMINAL
)

View File

@ -11,7 +11,6 @@ target_compile_options(poweroff PUBLIC -O2 -g)
target_link_libraries(poweroff PUBLIC libc)
add_custom_target(poweroff-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/poweroff ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/poweroff ${BANAN_BIN}/
DEPENDS poweroff
USES_TERMINAL
)

View File

@ -11,7 +11,6 @@ target_compile_options(rm PUBLIC -O2 -g)
target_link_libraries(rm PUBLIC libc ban)
add_custom_target(rm-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/rm ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/rm ${BANAN_BIN}/
DEPENDS rm
USES_TERMINAL
)

View File

@ -11,7 +11,6 @@ target_compile_options(snake PUBLIC -O2 -g)
target_link_libraries(snake PUBLIC libc)
add_custom_target(snake-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/snake ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/snake ${BANAN_BIN}/
DEPENDS snake
USES_TERMINAL
)

View File

@ -11,7 +11,6 @@ target_compile_options(stat PUBLIC -O2 -g)
target_link_libraries(stat PUBLIC libc ban)
add_custom_target(stat-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/stat ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/stat ${BANAN_BIN}/
DEPENDS stat
USES_TERMINAL
)

View File

@ -11,7 +11,6 @@ target_compile_options(sync PUBLIC -O2 -g)
target_link_libraries(sync PUBLIC libc)
add_custom_target(sync-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/sync ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/sync ${BANAN_BIN}/
DEPENDS sync
USES_TERMINAL
)

View File

@ -11,7 +11,6 @@ target_compile_options(tee PUBLIC -O2 -g)
target_link_libraries(tee PUBLIC libc)
add_custom_target(tee-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/tee ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/tee ${BANAN_BIN}/
DEPENDS tee
USES_TERMINAL
)

View File

@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 3.26)
project(test-globals CXX)
set(SOURCES
main.cpp
)
add_executable(test-globals ${SOURCES})
target_compile_options(test-globals PUBLIC -O2 -g)
target_link_libraries(test-globals PUBLIC libc)
add_custom_target(test-globals-install
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/test-globals ${BANAN_BIN}/
DEPENDS test-globals
)

View File

@ -0,0 +1,14 @@
#include <stdio.h>
struct foo_t
{
foo_t() { printf("global constructor works\n"); }
~foo_t() { printf("global destructor works\n"); }
};
foo_t foo;
int main()
{
}

View File

@ -11,7 +11,6 @@ target_compile_options(test PUBLIC -O2 -g)
target_link_libraries(test PUBLIC libc)
add_custom_target(test-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/test ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/test ${BANAN_BIN}/
DEPENDS test
USES_TERMINAL
)

View File

@ -11,7 +11,6 @@ target_compile_options(touch PUBLIC -O2 -g)
target_link_libraries(touch PUBLIC libc)
add_custom_target(touch-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/touch ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/touch ${BANAN_BIN}/
DEPENDS touch
USES_TERMINAL
)

View File

@ -11,7 +11,6 @@ target_compile_options(u8sum PUBLIC -O2 -g)
target_link_libraries(u8sum PUBLIC libc)
add_custom_target(u8sum-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/u8sum ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/u8sum ${BANAN_BIN}/
DEPENDS u8sum
USES_TERMINAL
)

View File

@ -11,7 +11,6 @@ target_compile_options(whoami PUBLIC -O2 -g)
target_link_libraries(whoami PUBLIC libc ban)
add_custom_target(whoami-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/whoami ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/whoami ${BANAN_BIN}/
DEPENDS whoami
USES_TERMINAL
)

View File

@ -11,7 +11,6 @@ target_compile_options(yes PUBLIC -O2 -g)
target_link_libraries(yes PUBLIC libc)
add_custom_target(yes-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/yes ${BANAN_BIN}/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/yes ${BANAN_BIN}/
DEPENDS yes
USES_TERMINAL
)