Compare commits
21 Commits
1af3ca19ab
...
6d899aa6ce
Author | SHA1 | Date |
---|---|---|
Bananymous | 6d899aa6ce | |
Bananymous | 120f7329b1 | |
Bananymous | 4f25c20c97 | |
Bananymous | 5e396851f4 | |
Bananymous | a44482639d | |
Bananymous | 3bac19e518 | |
Bananymous | 4dbe15aa0e | |
Bananymous | 1c5985148c | |
Bananymous | ce2461d0e8 | |
Bananymous | 4e785a133c | |
Bananymous | 26c7aee327 | |
Bananymous | 0405461742 | |
Bananymous | 8a10853ba7 | |
Bananymous | 5d34cebeca | |
Bananymous | 3d899d2e44 | |
Bananymous | f72fdeeb59 | |
Bananymous | 382f9d9bb3 | |
Bananymous | bc1d1bf919 | |
Bananymous | f05b9a6877 | |
Bananymous | ea5ed3001e | |
Bananymous | f312c3a4d7 |
|
@ -2,4 +2,4 @@
|
|||
.idea/
|
||||
build/
|
||||
base/
|
||||
|
||||
script/fakeroot-context
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include <BAN/String.h>
|
||||
#include <BAN/New.h>
|
||||
#include <BAN/Variant.h>
|
||||
|
||||
namespace BAN
|
||||
{
|
||||
|
@ -32,7 +31,6 @@ namespace BAN
|
|||
String& String::operator=(const String& other)
|
||||
{
|
||||
clear();
|
||||
if (!other.fits_in_sso())
|
||||
MUST(ensure_capacity(other.size()));
|
||||
memcpy(data(), other.data(), other.size() + 1);
|
||||
m_size = other.size();
|
||||
|
@ -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,7 +60,6 @@ namespace BAN
|
|||
String& String::operator=(StringView other)
|
||||
{
|
||||
clear();
|
||||
if (!fits_in_sso(other.size()))
|
||||
MUST(ensure_capacity(other.size()));
|
||||
memcpy(data(), other.data(), other.size());
|
||||
m_size = other.size();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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_.
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
|
@ -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 };
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
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++;
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
buffer += PAGE_SIZE - page_offset;
|
||||
bytes -= PAGE_SIZE - page_offset;
|
||||
page_offset = 0;
|
||||
page_index++;
|
||||
}
|
||||
page_table.unmap_page(0);
|
||||
}
|
||||
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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*);
|
||||
|
|
|
@ -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 "")
|
||||
|
|
|
@ -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
|
|
@ -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. */
|
|
@ -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
|
|
@ -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 (*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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
fi
|
||||
|
||||
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-full.sh
|
||||
exit 0
|
||||
$BANAN_SCRIPT_DIR/image-create.sh
|
||||
fi
|
||||
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
|
||||
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
131814
toolchain/gcc-12.2.0.patch
131814
toolchain/gcc-12.2.0.patch
File diff suppressed because it is too large
Load Diff
|
@ -23,6 +23,7 @@ set(USERSPACE_PROJECTS
|
|||
sync
|
||||
tee
|
||||
test
|
||||
test-globals
|
||||
touch
|
||||
u8sum
|
||||
whoami
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
|
@ -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()
|
||||
{
|
||||
|
||||
}
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue