diff --git a/.gitignore b/.gitignore
index 02e2a916..b4dcf36d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,9 +8,9 @@
/dependencies/uACPI
/dependencies/uHDA
/dependencies/flanterm/
-/dependencies/freebsd-e1000/
-/dependencies/include/
/dependencies/freebsd-e1000
+/dependencies/limine
+/dependencies/include/
/dependencies/needs_download.cmake
/qemu_log.txt
/tar
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a52ad865..478be4ea 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -19,6 +19,7 @@ option (OBOS_LAZY_IRQL "Enables lazy IRQL. Recommended if the main target of the
option (OBOS_USE_OBOS_GCC "Uses arch-obos-gcc instead of obos-elf-gcc. Ignored if OBOS_USE_CLANG is true.")
option (OBOS_COMPILE_USER_UTILS "Compiles user examples" ${OBOS_USE_OBOS_GCC})
option (OBOS_ONLY_COMPILE_USER_UTILS "Only compile user utilities" OFF)
+option (OBOS_USE_LIMINE "Use Limine instead of Hyper on supported architectures" OFF)
option (OBOS_ENABLE_UHDA "Whether to include uHDA" ON)
set (OBOS_LAZY_IRQL OFF)
@@ -87,6 +88,10 @@ if (OBOS_REFRESH_DEPENDENCIES)
message("Fetching Hyper.")
include("dependencies/hyper.cmake")
endif()
+ if (OBOS_USE_LIMINE)
+ message("Fetching Limine.")
+ include("dependencies/limine.cmake")
+ endif()
message("Fetching uACPI.")
include ("dependencies/uacpi.cmake")
message("Fetching flanterm.")
@@ -105,6 +110,9 @@ else()
if (NOT EXISTS hyper_install AND OBOS_ARCHITECTURE STREQUAL "x86_64")
include("dependencies/hyper.cmake")
endif()
+ if (OBOS_USE_LIMINE AND NOT EXISTS limine_exe)
+ include("dependencies/limine.cmake")
+ endif()
if (NOT EXISTS uacpi_cmake_file)
include("dependencies/uacpi.cmake")
endif()
@@ -129,7 +137,14 @@ if (OBOS_LAZY_IRQL)
else()
set (OBOS_LAZY_IRQL "0")
endif()
+
add_compile_definitions(OBOS_LAZY_IRQL=${OBOS_LAZY_IRQL})
+if (OBOS_USE_LIMINE)
+ set (OBOS_USE_LIMINE "1")
+else()
+ set (OBOS_USE_LIMINE "0")
+endif()
+add_compile_definitions(OBOS_USE_LIMINE=${OBOS_USE_LIMINE})
if (OBOS_ENABLE_LOCK_PROFILING)
set (OBOS_ENABLE_LOCK_PROFILING "1")
diff --git a/README.md b/README.md
index e7c12566..0a6c9d60 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,7 @@
# OBOS
OBOS uses ***✨ state of the art technology ✨*** to do ***✨ almost nothing ✨***
## Downloads
-- ISO Downloads can currently be found at http://obos-dev.ddns.net/images/
-- An XBPS binary package repository exists at http://obos-dev.ddns.net/current for x86_64-obos **only**.
+- The obos file server can be found at http://obos-dev.ddns.net/
## Building
### Prerequisites
- (For an x86-64 build) NASM
@@ -63,9 +62,6 @@ call launch_qemu.bat
- x86_64-obos: Working, not all ported programs work
- m68k-obos: Userspace is unstable, but the port works otherwise
- For information on ported programs, go to the obos-pkgs repository
-## Credits
-- My friend [@LemurLord16](https://github.com/LemurLord16) (@sigsbeedrive on discord) for listening to me yap about new features.
-- My cousin Ali because why not.
## License Notice
Most code in this repository is licensed under the MIT license.
Any code from other projects that require a license notice will be put below.
diff --git a/config/hyper.cfg b/config/hyper.cfg
index 86eda3ec..5bbf11b7 100644
--- a/config/hyper.cfg
+++ b/config/hyper.cfg
@@ -28,3 +28,7 @@ module:
type="memory"
name="FLANTERM_BUFF"
size=16777216
+module:
+ type="memory"
+ name="BUMP_REGION"
+ size=16777216
diff --git a/config/limine.conf b/config/limine.conf
new file mode 100644
index 00000000..2282dd43
--- /dev/null
+++ b/config/limine.conf
@@ -0,0 +1,32 @@
+timeout: 5
+
+/OBOS
+ protocol: limine
+ comment: OBOS
+
+ paging_mode: 4level
+ module_path: boot():/obos/initrd.tar
+ module_string: initrd
+ module_path: boot():/obos/initrd
+ module_string: initrd_driver
+ module_path: boot():/obos/flanterm_buff
+ module_string: FLANTERM_BUFF
+ module_path: boot():/obos/flanterm_buff
+ module_string: BUMP_REGION
+ path: boot():/obos/oboskrnl
+ cmdline: initrd-module=initrd initrd-driver-module=initrd_driver root-fs-partid initrd load-modules=/libps2,/extfs initial-swap-size=67108864 log-level=1 init-args /usr/bin/bash --login
+/OBOS (Login)
+ protocol: limine
+ comment: OBOS (Login Prompt)
+
+ paging_mode: 4level
+ module_path: boot():/obos/initrd.tar
+ module_string: initrd
+ module_path: boot():/obos/initrd
+ module_string: initrd_driver
+ module_path: boot():/obos/flanterm_buff
+ module_string: FLANTERM_BUFF
+ module_path: boot():/obos/flanterm_buff
+ module_string: BUMP_REGION
+ path: boot():/obos/oboskrnl
+ cmdline: initrd-module=initrd initrd-driver-module=initrd_driver root-fs-partid initrd load-modules=/libps2,/extfs initial-swap-size=67108864 log-level=1 init-args /usr/bin/bash --login -c login
\ No newline at end of file
diff --git a/dependencies/limine.cmake b/dependencies/limine.cmake
new file mode 100644
index 00000000..7efdd0a6
--- /dev/null
+++ b/dependencies/limine.cmake
@@ -0,0 +1,26 @@
+# dependencies/limine.cmake
+
+# Copyright (c) 2025 Omar Berrow
+
+include(FetchContent)
+
+if (OBOS_REFRESH_DEPENDENCIES)
+ FetchContent_Declare(Limine
+ GIT_REPOSITORY https://github.com/limine-bootloader/limine.git
+ GIT_TAG v10.3.0-binary
+ SOURCE_DIR ${CMAKE_SOURCE_DIR}/dependencies/limine
+ )
+ FetchContent_MakeAvailable(Limine)
+ file (COPY_FILE "${CMAKE_SOURCE_DIR}/dependencies/limine/limine.h" "${CMAKE_SOURCE_DIR}/dependencies/include/limine.h")
+endif()
+if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
+ execute_process(
+ COMMAND "make"
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/dependencies/limine
+ )
+ set (limine_exe ${CMAKE_SOURCE_DIR}/dependencies/limine/limine CACHE INTERNAL "x")
+ # elseif (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows" OR CMAKE_HOST_SYSTEM_NAME STREQUAL "MSYS")
+ # set (limine_exe ${CMAKE_SOURCE_DIR}/dependencies/limine/limine.exe CACHE INTERNAL "x")
+else()
+ message(FATAL_ERROR "You must be on to compile OBOS with Limine.")
+endif()
diff --git a/dependencies/uacpi.cmake b/dependencies/uacpi.cmake
index 7a026d32..88627c79 100644
--- a/dependencies/uacpi.cmake
+++ b/dependencies/uacpi.cmake
@@ -9,7 +9,7 @@ if (OBOS_REFRESH_DEPENDENCIES)
# In honor of the old uACPI link
#GIT_REPOSITORY https://github.com/UltraOS/uACPI.git
GIT_REPOSITORY https://github.com/uACPI/uACPI.git
- GIT_TAG 3.0.0
+ GIT_TAG 3.2.0
SOURCE_DIR ${CMAKE_SOURCE_DIR}/dependencies/uACPI
)
FetchContent_MakeAvailable(uACPI)
diff --git a/screenshots/20251202_0930.png b/screenshots/20251202_0930.png
new file mode 100644
index 00000000..fa9682cd
Binary files /dev/null and b/screenshots/20251202_0930.png differ
diff --git a/scripts/launch_qemu.sh b/scripts/launch_qemu.sh
index b178d690..bfe11054 100755
--- a/scripts/launch_qemu.sh
+++ b/scripts/launch_qemu.sh
@@ -13,7 +13,6 @@ qemu-system-x86_64 \
-debugcon file:/dev/stdout \
-monitor stdio \
-serial tcp:0.0.0.0:1534,server,nowait \
--smp cores=1,threads=1,sockets=1 \
-d int \
-D qemu_log.txt "$@"
diff --git a/scripts/launch_qemu.tcg.sh b/scripts/launch_qemu.tcg.sh
new file mode 100755
index 00000000..2635452c
--- /dev/null
+++ b/scripts/launch_qemu.tcg.sh
@@ -0,0 +1,26 @@
+cd ../
+
+rm qemu_log.txt
+
+echo $@
+qemu-system-x86_64 \
+-drive format=raw,file=out/obos.iso,media=disk,index=0 \
+-m 2G \
+-gdb tcp:0.0.0.0:1234 -S \
+-M q35 \
+-cpu Haswell \
+-accel tcg \
+-debugcon file:/dev/stdout \
+-monitor stdio \
+-serial tcp:0.0.0.0:1534,server,nowait \
+-d int \
+-D qemu_log.txt "$@"
+
+# -nographic
+# -enable-kvm \
+# -M smm=off \
+# -no-reboot
+# -enable-kvm \
+# -no-shutdown
+
+cd scripts
diff --git a/src/drivers/generic/ahci/command.c b/src/drivers/generic/ahci/command.c
index 8796aaef..e5e0bd04 100644
--- a/src/drivers/generic/ahci/command.c
+++ b/src/drivers/generic/ahci/command.c
@@ -14,7 +14,8 @@
#include
-#include "locks/wait.h"
+#include
+
#include "structs.h"
#include "command.h"
@@ -159,6 +160,9 @@ void WaitForTranscations()
Port* port = Ports + i;
for (size_t j = 0; j < 32; j++)
if (port->CommandBitmask & BIT(j) && port->PendingCommands[j])
- Core_WaitOnObject(WAITABLE_OBJECT(port->PendingCommands[j]->completionEvent));
+ {
+ obos_status status = Core_WaitOnObject(WAITABLE_OBJECT(port->PendingCommands[j]->completionEvent));
+ OBOS_UNUSED(status);
+ }
}
}
diff --git a/src/drivers/generic/ahci/interface.c b/src/drivers/generic/ahci/interface.c
index 08c6996c..a1352513 100644
--- a/src/drivers/generic/ahci/interface.c
+++ b/src/drivers/generic/ahci/interface.c
@@ -13,6 +13,7 @@
#include
#include
#include
+#include
#include
#include
@@ -63,7 +64,7 @@ static obos_status populate_physical_regions(uintptr_t base, size_t size, struct
base &= ~1;
const size_t MAX_PRDT_COUNT = sizeof(((HBA_CMD_TBL*)nullptr))->prdt_entry/sizeof(HBA_PRDT_ENTRY);
/*
- data->phys_regions = Mm_Allocator->Reallocate(Mm_Allocator, data->phys_regions, ++data->physRegionCount*sizeof(struct ahci_phys_region), nullptr);
+ data->phys_regions = Reallocate(Mm_Allocator, data->phys_regions, ++data->physRegionCount*sizeof(struct ahci_phys_region), nullptr);
struct ahci_phys_region* reg = &data->phys_regions[data->physRegionCount - 1];
*/
long bytesLeft = size;
@@ -83,17 +84,25 @@ static obos_status populate_physical_regions(uintptr_t base, size_t size, struct
{
if (data->physRegionCount >= MAX_PRDT_COUNT)
return OBOS_STATUS_INTERNAL_ERROR;
+
+ Mm_HandlePageFault(ctx, addr, (data->direction == COMMAND_DIRECTION_WRITE ? 0 : PF_EC_RW) | (ctx == &Mm_KernelContext ? 0 : PF_EC_UM));
+
page_info info = {};
MmS_QueryPageInfo(ctx->pt, addr, &info, nullptr);
+
page key = {.phys=info.phys};
page* pg = RB_FIND(phys_page_tree, &Mm_PhysicalPages, &key);
+ OBOS_ENSURE(pg != Mm_AnonPage);
+ OBOS_ENSURE(pg != Mm_UserAnonPage);
+
MmH_RefPage(pg);
+
if ((lastPhys + pgSize) != info.phys)
{
if (addr != base)
{
size_t old_sz = data->physRegionCount*sizeof(struct ahci_phys_region);
- data->phys_regions = Mm_Allocator->Reallocate(Mm_Allocator, data->phys_regions, ++data->physRegionCount*sizeof(struct ahci_phys_region), old_sz, nullptr);
+ data->phys_regions = Reallocate(Mm_Allocator, data->phys_regions, ++data->physRegionCount*sizeof(struct ahci_phys_region), old_sz, nullptr);
struct ahci_phys_region* reg = &data->phys_regions[data->physRegionCount - 1];
*reg = curr;
wroteback = true;
@@ -116,7 +125,7 @@ static obos_status populate_physical_regions(uintptr_t base, size_t size, struct
if (!wroteback && curr.phys)
{
size_t old_sz = data->physRegionCount*sizeof(struct ahci_phys_region);
- data->phys_regions = Mm_Allocator->Reallocate(Mm_Allocator, data->phys_regions, ++data->physRegionCount*sizeof(struct ahci_phys_region), old_sz, nullptr);
+ data->phys_regions = Reallocate(Mm_Allocator, data->phys_regions, ++data->physRegionCount*sizeof(struct ahci_phys_region), old_sz, nullptr);
struct ahci_phys_region* reg = &data->phys_regions[data->physRegionCount - 1];
*reg = curr;
}
@@ -145,7 +154,7 @@ static obos_status unpopulate_physical_regions(uintptr_t base, size_t size, stru
MmH_DerefPage(pg);
pgSize = info.prot.huge_page ? OBOS_HUGE_PAGE_SIZE : OBOS_PAGE_SIZE;
}
- Mm_Allocator->Free(Mm_Allocator, data->phys_regions, data->physRegionCount*sizeof(struct ahci_phys_region));
+ Free(Mm_Allocator, data->phys_regions, data->physRegionCount*sizeof(struct ahci_phys_region));
return OBOS_STATUS_SUCCESS;
}
// #pragma GCC pop_options
@@ -215,7 +224,12 @@ obos_status read_sync(dev_desc desc, void* buf, size_t blkCount, size_t blkOffse
// irql oldIrql = Core_RaiseIrql(IRQL_AHCI);
SendCommand(port, &data, blkOffset, 0x40, blkCount == 0x10000 ? 0 : blkCount);
// Core_LowerIrql(oldIrql);
- Core_WaitOnObject(WAITABLE_OBJECT(data.completionEvent));
+ if (obos_is_error(status = Core_WaitOnObject(WAITABLE_OBJECT(data.completionEvent))))
+ {
+ Core_SemaphoreRelease(&port->lock);
+ unpopulate_physical_regions((uintptr_t)buf, blkCount*port->sectorSize, &data);
+ break;
+ }
Core_EventClear(&data.completionEvent);
if (!port->works)
{
@@ -275,7 +289,12 @@ obos_status write_sync(dev_desc desc, const void* buf, size_t blkCount, size_t b
{
SendCommand(port, &data, blkOffset, 0x40, blkCount == 0x10000 ? 0 : blkCount);
HBA->ghc |= BIT(1) /* GhcIE */;
- Core_WaitOnObject(WAITABLE_OBJECT(data.completionEvent));
+ if (obos_is_error(status = Core_WaitOnObject(WAITABLE_OBJECT(data.completionEvent))))
+ {
+ Core_SemaphoreRelease(&port->lock);
+ unpopulate_physical_regions((uintptr_t)buf, blkCount*port->sectorSize, &data);
+ break;
+ }
Core_EventClear(&data.completionEvent);
if (!port->works)
{
diff --git a/src/drivers/generic/ahci/main.c b/src/drivers/generic/ahci/main.c
index 61f635b2..515b9fea 100644
--- a/src/drivers/generic/ahci/main.c
+++ b/src/drivers/generic/ahci/main.c
@@ -158,6 +158,7 @@ static void* map_registers(uintptr_t phys, size_t size, bool uc)
page.phys = phys+offset;
MmS_SetPageMapping(Mm_KernelContext.pt, &page, phys + offset, false);
}
+ Drv_TLBShootdown(Mm_KernelContext.pt, (uintptr_t)virt, size);
return virt+phys_page_offset;
}
diff --git a/src/drivers/generic/extfs/helper.c b/src/drivers/generic/extfs/helper.c
index caa19c38..aa6da2ab 100644
--- a/src/drivers/generic/extfs/helper.c
+++ b/src/drivers/generic/extfs/helper.c
@@ -213,8 +213,7 @@ void ext_ino_foreach_block(ext_cache* cache,
}
struct read_block_packet {
- void* buffer;
- size_t buffer_offset;
+ uint32_t* blocks;
size_t count;
size_t start_offset;
size_t current_offset;
@@ -233,18 +232,7 @@ static iterate_decision read_cb(ext_cache* cache, ext_inode* inode, uint32_t *bl
decision = ITERATE_DECISION_STOP;
goto out1;
}
- void* const buff = (void*)((uintptr_t)packet->buffer + packet->buffer_offset);
- if (!block)
- memzero(buff, cache->block_size); // sparse block
- else
- {
- page* pg = nullptr;
- void* data = ext_read_block(cache, *block, &pg);
- MmH_RefPage(pg);
- memcpy(buff, data, OBOS_MIN(packet->count - packet->buffer_offset, cache->block_size));
- MmH_DerefPage(pg);
- }
- packet->buffer_offset += cache->block_size;
+ packet->blocks[(packet->current_offset - packet->start_offset) / cache->block_size] = block ? *block : UINT32_MAX;
out1:
packet->current_offset += cache->block_size;
@@ -262,11 +250,97 @@ obos_status ext_ino_read_blocks(ext_cache* cache, uint32_t ino, size_t offset, s
return OBOS_STATUS_INVALID_ARGUMENT;
if ((offset + count) > inode->blocks*512)
count = (offset + count) - inode->blocks*512;
- struct read_block_packet userdata = {.buffer=buffer,.start_offset=offset,.count=count,.buffer_offset=0};
+ uint32_t nBlocks = count /= cache->block_size;
+ uint32_t* blocks = ZeroAllocate(OBOS_KernelAllocator, nBlocks, sizeof(uint32_t), nullptr);
+ struct read_block_packet userdata = {.blocks=blocks,.start_offset=offset,.count=count};
ext_ino_foreach_block(cache, ino, read_cb, &userdata);
MmH_DerefPage(pg);
+ uint32_t current_block_base = 0;
+ uint32_t current_block_index = 0;
+ uint32_t current_block_count = 0;
+ bool read_current = false;
+ irp** irps = nullptr;
+ size_t nIrps = 0;
+ bool refresh_next = true;
+ for (uint32_t i = 0; i < nBlocks; i++)
+ {
+ if (blocks[i] == UINT32_MAX)
+ {
+ // TODO: Make that asynchronous?
+ memzero((void*)((uintptr_t)buffer + i*cache->block_size), cache->block_size);
+ refresh_next = true;
+ continue;
+ }
+ if (refresh_next)
+ {
+ read_current = false;
+ refresh_next = false;
+ current_block_base = blocks[i];
+ ++current_block_count;
+ current_block_index = i;
+ continue;
+ }
+ if (blocks[i] == (current_block_base + current_block_count))
+ {
+ read_current = false;
+ ++current_block_count;
+ continue;
+ }
+ irp* req = VfsH_IRPAllocate();
+ VfsH_IRPBytesToBlockCount(cache->vn, current_block_count*cache->block_size, &req->blkCount);
+ VfsH_IRPBytesToBlockCount(cache->vn, current_block_base*cache->block_size, &req->blkOffset);
+ req->vn = cache->vn;
+ req->buff = (void*)((uintptr_t)buffer + current_block_index*cache->block_size);
+ req->op = IRP_READ;
+ VfsH_IRPSubmit(req, nullptr);
+ read_current = true;
+ if (req->evnt && !Core_EventGetState(req->evnt))
+ {
+ size_t oldsize = nIrps*sizeof(irp*);
+ nIrps++;
+ irps = Reallocate(OBOS_KernelAllocator, irps, nIrps*sizeof(irp*), oldsize, nullptr);
+ irps[nIrps-1] = req;
+ }
+ if (blocks[i] == UINT32_MAX)
+ continue;
+ current_block_index = i;
+ current_block_base = blocks[i];
+ current_block_count++;
+ }
+ if (!read_current)
+ {
+ irp* req = VfsH_IRPAllocate();
+ VfsH_IRPBytesToBlockCount(cache->vn, current_block_count*cache->block_size, &req->blkCount);
+ VfsH_IRPBytesToBlockCount(cache->vn, current_block_base*cache->block_size, &req->blkOffset);
+ req->vn = cache->vn;
+ req->buff = (void*)((uintptr_t)buffer + current_block_index*cache->block_size);
+ req->op = IRP_READ;
+ VfsH_IRPSubmit(req, nullptr);
+ read_current = true;
+ if (req->evnt && !Core_EventGetState(req->evnt))
+ {
+ size_t oldsize = nIrps*sizeof(irp*);
+ nIrps++;
+ irps = Reallocate(OBOS_KernelAllocator, irps, nIrps*sizeof(irp*), oldsize, nullptr);
+ irps[nIrps-1] = req;
+ }
+ else
+ {
+ VfsH_IRPWait(req);
+ VfsH_IRPUnref(req);
+ }
+ }
+ for (size_t i = 0; i < nIrps; i++)
+ {
+ VfsH_IRPWait(irps[i]);
+ VfsH_IRPUnref(irps[i]);
+ irps[i] = nullptr;
+ }
+ Free(OBOS_KernelAllocator, irps, nIrps*sizeof(irp*));
+
+ Free(OBOS_KernelAllocator, blocks, nBlocks*sizeof(uint32_t));
if (nRead)
- *nRead = userdata.buffer_offset;
+ *nRead = count;
return userdata.status;
}
@@ -628,6 +702,7 @@ uint32_t allocate_bmp(ext_cache* cache, const uint32_t* block_group_ptr, int wha
buffer = ext_read_block(cache, block, &pg);
MmH_RefPage(pg);
}
+ OBOS_ENSURE(buffer);
if (buffer[i] != 0xff)
{
uint8_t bit = __builtin_ctz(~buffer[i]);
@@ -663,7 +738,13 @@ uint32_t allocate_bmp(ext_cache* cache, const uint32_t* block_group_ptr, int wha
uint32_t ext_ino_allocate(ext_cache* cache, const uint32_t* block_group_ptr)
{
- return allocate_bmp(cache, block_group_ptr, ALLOC_INODE);
+ uint32_t ret = allocate_bmp(cache, block_group_ptr, ALLOC_INODE);
+ ext_bgd* bgd = &cache->bgdt[ext_ino_get_block_group(cache, ret)];
+ bgd->free_inodes--;
+ cache->superblock.free_inode_count--;
+ ext_writeback_sb(cache);
+ ext_writeback_bgd(cache, ext_ino_get_block_group(cache, ret));
+ return ret;
}
void ext_ino_free(ext_cache* cache, uint32_t ino)
@@ -706,7 +787,13 @@ void ext_ino_free(ext_cache* cache, uint32_t ino)
uint32_t ext_blk_allocate(ext_cache* cache, const uint32_t* block_group_ptr)
{
- return allocate_bmp(cache, block_group_ptr, ALLOC_BLOCK);
+ uint32_t blk = allocate_bmp(cache, block_group_ptr, ALLOC_BLOCK);
+ ext_bgd* bgd = &cache->bgdt[blk/cache->blocks_per_group];
+ bgd->free_blocks--;
+ cache->superblock.free_block_count--;
+ ext_writeback_sb(cache);
+ ext_writeback_bgd(cache, blk/cache->blocks_per_group);
+ return blk;
}
void ext_blk_free(ext_cache* cache, uint32_t blk)
diff --git a/src/drivers/generic/extfs/interface.c b/src/drivers/generic/extfs/interface.c
index f3a453e0..6b5d232b 100644
--- a/src/drivers/generic/extfs/interface.c
+++ b/src/drivers/generic/extfs/interface.c
@@ -210,6 +210,7 @@ obos_status vnode_search(void** vn_found, dev_desc desc, void* dev_vn)
ext_inode_handle* hnd = (void*)desc;
cache = hnd->cache;
ino = hnd->ino;
+ OBOS_ENSURE(cache);
}
*vn_found = ext_make_vnode(cache, ino, nullptr);
@@ -322,11 +323,14 @@ static void on_match(ext_inode** const inode,
ext_cache* const cache)
{
uint32_t ino = dent->ino;
- size_t old_size = *nToRead;
- *nToRead = le32_to_host((*inode)->blocks) * 512;
- *buffer = Reallocate(EXT_Allocator, *buffer, *nToRead, old_size, nullptr);
- ext_ino_read_blocks(cache, ino, 0, *nToRead, *buffer, nullptr);
- *offset = 0;
+ if (dent->file_type == EXT2_FT_DIR)
+ {
+ size_t old_size = *nToRead;
+ *nToRead = le32_to_host((*inode)->blocks) * 512;
+ *buffer = Reallocate(EXT_Allocator, *buffer, *nToRead, old_size, nullptr);
+ ext_ino_read_blocks(cache, ino, 0, *nToRead, *buffer, nullptr);
+ *offset = 0;
+ }
MmH_DerefPage(*pg);
*inode = ext_read_inode_pg(cache, ino, pg);
MmH_RefPage(*pg);
@@ -334,7 +338,7 @@ static void on_match(ext_inode** const inode,
obos_status path_search(dev_desc* found, void* vn, const char* path, dev_desc parent)
{
- if (!found || !vn || !path)
+ if (!found || (!vn && parent == UINTPTR_MAX) || !path)
return OBOS_STATUS_INVALID_ARGUMENT;
uint32_t parent_ino = 0;
@@ -410,7 +414,10 @@ obos_status path_search(dev_desc* found, void* vn, const char* path, dev_desc pa
{
get_next_tok();
if (tok == (path + path_len))
+ {
*found = get_desc(cache, ent->ino);
+ break;
+ }
on_match(&inode,
&pg,
&buffer,
@@ -418,10 +425,6 @@ obos_status path_search(dev_desc* found, void* vn, const char* path, dev_desc pa
&offset,
ent,
cache);
- if (!(*found))
- continue;
- else
- break;
}
}
diff --git a/src/drivers/generic/extfs/probe.c b/src/drivers/generic/extfs/probe.c
index f9cfcfa2..898fe9f5 100644
--- a/src/drivers/generic/extfs/probe.c
+++ b/src/drivers/generic/extfs/probe.c
@@ -140,7 +140,10 @@ vnode* ext_make_vnode(ext_cache* cache, uint32_t ino, mount* mnt)
}
ext_inode* inode = ext_read_inode(cache, ino);
-
+ OBOS_ASSERT(inode);
+ if (!inode)
+ return nullptr;
+
uint32_t vtype = 0;
if (ext_ino_test_type(inode, EXT2_S_IFDIR))
vtype = VNODE_TYPE_DIR;
@@ -163,8 +166,8 @@ vnode* ext_make_vnode(ext_cache* cache, uint32_t ino, mount* mnt)
vn->desc = (dev_desc)handle;
vn->vtype = vtype;
vn->blkSize = 1;
- vn->owner_uid = inode->uid;
- vn->group_uid = inode->gid;
+ vn->uid = inode->uid;
+ vn->gid = inode->gid;
vn->filesize = (uint64_t)inode->size | (ext_sb_supports_64bit_filesize ? (uint64_t)inode->dir_acl << 32 : 0);
vn->times.access = inode->access_time;
vn->times.birth = inode->creation_time;
diff --git a/src/drivers/generic/freebsd-e1000/CMakeLists.txt b/src/drivers/generic/freebsd-e1000/CMakeLists.txt
index 4d2655c4..f5c7fa8e 100644
--- a/src/drivers/generic/freebsd-e1000/CMakeLists.txt
+++ b/src/drivers/generic/freebsd-e1000/CMakeLists.txt
@@ -17,6 +17,10 @@ target_compile_options(e1000
PRIVATE $<$:-Wno-error>
)
+if (OBOS_ENABLE_FANALYZER)
+ target_compile_options(e1000 PRIVATE "-fno-analyzer")
+endif()
+
set_property(TARGET e1000 PROPERTY link_depends ${DRIVER_LINKER_SCRIPT})
target_include_directories(e1000
diff --git a/src/drivers/generic/freebsd-e1000/dev.h b/src/drivers/generic/freebsd-e1000/dev.h
index 7ff1f103..c7b3f6f7 100644
--- a/src/drivers/generic/freebsd-e1000/dev.h
+++ b/src/drivers/generic/freebsd-e1000/dev.h
@@ -1,6 +1,7 @@
#pragma once
#include
+#include
#include
@@ -19,7 +20,8 @@
#include
#define RX_QUEUE_SIZE (32)
-#define TX_QUEUE_SIZE (8)
+#define TX_QUEUE_SIZE (32)
+#define TX_BUFFER_PAGES (4)
typedef struct e1000_frame {
void* buff;
@@ -51,6 +53,7 @@ typedef struct e1000_device {
page* tx_ring_phys_pg;
size_t tx_index;
event tx_done_evnt;
+ uintptr_t tx_buffers[TX_QUEUE_SIZE];
size_t refs;
@@ -80,7 +83,7 @@ typedef struct e1000_handle {
void e1000_init_rx(e1000_device* dev);
void e1000_init_tx(e1000_device* dev);
-event* e1000_tx_packet(e1000_device* dev, const void* buffer, size_t size, bool dry);
+event* e1000_tx_packet(e1000_device* dev, const void* buffer, size_t size, bool dry, obos_status* status);
void e1000_irq_handler(struct irq* i, interrupt_frame* frame, void* userdata, irql oldIrql);
bool e1000_check_irq_callback(struct irq* i, void* userdata);
\ No newline at end of file
diff --git a/src/drivers/generic/freebsd-e1000/io.c b/src/drivers/generic/freebsd-e1000/io.c
index feaba376..a3b1e90e 100644
--- a/src/drivers/generic/freebsd-e1000/io.c
+++ b/src/drivers/generic/freebsd-e1000/io.c
@@ -7,6 +7,7 @@
*/
#include
+#include
#include
@@ -17,6 +18,7 @@
#include
#include
+#include
#include
@@ -24,8 +26,11 @@
#include
+#include
+
#include "dev.h"
+
LIST_GENERATE(e1000_frame_list, e1000_frame, node);
#define EM_RADV 64
@@ -191,13 +196,6 @@ void e1000_init_tx(e1000_device* dev)
{
dev->tx_ring_phys_pg = MmH_PgAllocatePhysical(false, false);
dev->tx_ring = dev->tx_ring_phys_pg->phys;
- struct e1000_tx_desc* desc = ((struct e1000_tx_desc*)MmS_MapVirtFromPhys(dev->tx_ring));
- for (size_t i = 0; i < TX_QUEUE_SIZE; i++)
- {
- desc[i].buffer_addr = 0;
- desc[i].lower.data = 0;
- desc[i].upper.fields.status = E1000_TXD_STAT_DD;
- }
// Copied from managarm
E1000_WRITE_REG(&dev->hw, E1000_TDLEN(0), TX_QUEUE_SIZE * sizeof(struct e1000_tx_desc));
@@ -205,8 +203,8 @@ void e1000_init_tx(e1000_device* dev)
E1000_WRITE_REG(&dev->hw, E1000_TDBAL(0), (u32)dev->tx_ring);
/* Init the HEAD/TAIL indices */
- E1000_WRITE_REG(&dev->hw, E1000_TDT(0), 0);
E1000_WRITE_REG(&dev->hw, E1000_TDH(0), 0);
+ E1000_WRITE_REG(&dev->hw, E1000_TDT(0), 0);
u32 txdctl = 0; /* clear txdctl */
txdctl |= 0x1f; /* PTHRESH */
@@ -273,7 +271,7 @@ void e1000_init_tx(e1000_device* dev)
/* Program the Transmit Control Register */
u32 tctl = E1000_READ_REG(&dev->hw, E1000_TCTL);
tctl &= ~E1000_TCTL_CT;
- tctl |= (E1000_TCTL_RTLC | E1000_TCTL_EN | (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT));
+ tctl |= (E1000_TCTL_RTLC | E1000_TCTL_EN | E1000_TCTL_PSP | (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT));
if (dev->hw.mac.type >= e1000_82571)
tctl |= E1000_TCTL_MULR;
@@ -293,14 +291,24 @@ void e1000_init_tx(e1000_device* dev)
reg |= E1000_TARC0_CB_MULTIQ_2_REQ;
E1000_WRITE_REG(&dev->hw, E1000_TARC(0), reg);
}
+
+ struct e1000_tx_desc* desc = ((struct e1000_tx_desc*)MmS_MapVirtFromPhys(dev->tx_ring));
+ for (size_t i = 0; i < TX_QUEUE_SIZE; i++)
+ {
+ dev->tx_buffers[i] = Mm_AllocatePhysicalPages(TX_BUFFER_PAGES, 1, nullptr);
+ desc[i].buffer_addr = dev->tx_buffers[i];
+ desc[i].lower.data = 0;
+ desc[i].upper.data = 0;
+ }
+ OBOS_ENSURE(memcmp_b(desc, 0, sizeof(*desc)*TX_QUEUE_SIZE) == false);
}
void e1000_tx_reap(e1000_device* dev);
-event* e1000_tx_packet(e1000_device* dev, const void* buffer, size_t size, bool dry)
+event* e1000_tx_packet(e1000_device* dev, const void* buffer, size_t size, bool dry, obos_status* status)
{
e1000_tx_reap(dev);
- struct e1000_tx_desc* desc = &((struct e1000_tx_desc*)MmS_MapVirtFromPhys(dev->tx_ring))[dev->tx_index % TX_QUEUE_SIZE];
+ volatile struct e1000_tx_desc* desc = &((volatile struct e1000_tx_desc*)MmS_MapVirtFromPhys(dev->tx_ring))[dev->tx_index % TX_QUEUE_SIZE];
if (dry)
return nullptr;
irql oldIrql = Core_RaiseIrql(IRQL_E1000);
@@ -308,18 +316,24 @@ event* e1000_tx_packet(e1000_device* dev, const void* buffer, size_t size, bool
size_t nPages = size / OBOS_PAGE_SIZE;
if (size % OBOS_PAGE_SIZE)
nPages++;
- uintptr_t buff = Mm_AllocatePhysicalPages(nPages, 1, nullptr);
+ if (nPages > TX_BUFFER_PAGES)
+ return nullptr;
+ uintptr_t buff = dev->tx_buffers[dev->tx_index % TX_QUEUE_SIZE];
memcpy(MmS_MapVirtFromPhys(buff), buffer, size);
desc->buffer_addr = buff;
desc->upper.data = 0;
desc->lower.data = size | E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS;
+ E1000_WRITE_REG(&dev->hw, E1000_TDBAH(0), (u32)(dev->tx_ring >> 32));
+ E1000_WRITE_REG(&dev->hw, E1000_TDBAL(0), (u32)dev->tx_ring);
E1000_WRITE_REG(&dev->hw, E1000_TDT(0), ++dev->tx_index % TX_QUEUE_SIZE);
-
- while (~desc->upper.data & E1000_TXD_STAT_DD)
- continue;
- // printf("ret from %s, upper.data=0x%x, lower.data=0x%x, buffer=0x%p\n", __func__, desc->upper.data, desc->lower.data, desc->buffer_addr);
-
+
Core_LowerIrql(oldIrql);
+
+ uintptr_t deadline = CoreS_GetTimerTick() + CoreH_TimeFrameToTick(1*1000*1000);
+ while (~desc->upper.data & E1000_TXD_STAT_DD && CoreS_GetTimerTick() < deadline)
+ Core_Yield();
+ if (~desc->upper.data & E1000_TXD_STAT_DD)
+ *status = OBOS_STATUS_TIMED_OUT;
return nullptr;
}
@@ -373,15 +387,16 @@ static void tx_event_set_dpc(dpc* d, void* udata)
}
void e1000_tx_reap(e1000_device* dev)
{
- struct e1000_tx_desc* desc = &((struct e1000_tx_desc*)MmS_MapVirtFromPhys(dev->tx_ring))[0];
+ volatile struct e1000_tx_desc* desc = &((struct e1000_tx_desc*)MmS_MapVirtFromPhys(dev->tx_ring))[0];
size_t i = dev->tx_index;
for (; ; )
{
- if (~desc[i].upper.fields.status & E1000_TXD_STAT_DD)
+ if (~desc[i].upper.data & E1000_TXD_STAT_DD)
break;
desc[i].upper.fields.status = 0;
- desc[i].lower.data = 0;
- desc[i].buffer_addr = 0;
+ desc[i].lower.data = 0;
+ desc[i].buffer_addr = 0;
+ i++;
}
dev->tx_index = i;
}
diff --git a/src/drivers/generic/freebsd-e1000/main.c b/src/drivers/generic/freebsd-e1000/main.c
index 6d531ee6..61ceaf47 100644
--- a/src/drivers/generic/freebsd-e1000/main.c
+++ b/src/drivers/generic/freebsd-e1000/main.c
@@ -6,6 +6,7 @@
#include
#include
+#include
#include
@@ -29,6 +30,7 @@
#include
#include "dev.h"
+#include "e1000/e1000_defines.h"
OBOS_PAGEABLE_FUNCTION obos_status get_blk_size(dev_desc desc, size_t* blkSize)
{
@@ -124,9 +126,11 @@ static void irp_on_tx_event_set(irp* req)
e1000_handle* hnd = (void*)req->desc;
if (req->evnt)
Core_EventClear(req->evnt);
- req->evnt = e1000_tx_packet(hnd->dev, req->cbuff,req->blkCount, req->dryOp);
+ req->status = OBOS_STATUS_SUCCESS;
+ req->evnt = e1000_tx_packet(hnd->dev, req->cbuff,req->blkCount, req->dryOp, &req->status);
req->on_event_set = nullptr;
- req->status = req->evnt ? OBOS_STATUS_IRP_RETRY : OBOS_STATUS_SUCCESS;
+ if (obos_is_success(req->status))
+ req->status = req->evnt ? OBOS_STATUS_IRP_RETRY : OBOS_STATUS_SUCCESS;
if (req->status)
req->nBlkWritten = req->blkCount;
}
@@ -152,9 +156,9 @@ obos_status submit_irp(void* request)
}
else
{
- req->evnt = e1000_tx_packet(hnd->dev, req->cbuff, req->blkCount, req->dryOp);
+ req->status = OBOS_STATUS_SUCCESS;
+ req->evnt = e1000_tx_packet(hnd->dev, req->cbuff, req->blkCount, req->dryOp, &req->status);
req->on_event_set = irp_on_tx_event_set;
- req->status = req->evnt ? OBOS_STATUS_IRP_RETRY : OBOS_STATUS_SUCCESS;
if (obos_is_success(req->status))
req->nBlkWritten = req->blkCount;
}
@@ -272,6 +276,7 @@ static void* map_registers(uintptr_t phys, size_t size, bool uc, bool mmio, bool
MmH_RefPage(pg);
MmS_SetPageMapping(Mm_KernelContext.pt, &page, phys + offset, false);
}
+ Drv_TLBShootdown(Mm_KernelContext.pt, (uintptr_t)virt, size);
return virt+phys_page_offset;
}
@@ -326,7 +331,10 @@ static void search_bus(pci_bus* bus)
Devices = OBOS_NonPagedPoolAllocator->Reallocate(OBOS_NonPagedPoolAllocator, Devices, nDevices*sizeof(e1000_device), (nDevices-1)*sizeof(e1000_device), nullptr);
memzero(&Devices[nDevices-1], sizeof(Devices[nDevices-1]));
- dev->resource_cmd_register->cmd_register |= 0x7; // io space + memspace + bus master
+ // for (volatile bool b = true; b;)
+ // OBOSS_SpinlockHint();
+
+ dev->resource_cmd_register->cmd_register |= 0x7;
Drv_PCISetResource(dev->resource_cmd_register);
Devices[nDevices-1].hw.back = &Devices[nDevices-1].osdep;
@@ -393,16 +401,6 @@ static void search_bus(pci_bus* bus)
e1000_get_bus_info(&Devices[nDevices-1].hw);
- if (e1000_reset_hw(&Devices[nDevices-1].hw) != E1000_SUCCESS)
- {
- Mm_VirtualMemoryFree(&Mm_KernelContext, (void*)Devices[nDevices-1].osdep.membase, bar0->bar->size);
- nDevices--;
- Devices = Reallocate(OBOS_NonPagedPoolAllocator, Devices, nDevices*sizeof(e1000_device), (nDevices+1)*sizeof(e1000_device), nullptr);
- OBOS_Warning("%02x:%02x:%02x: Bogus E1000 PCI node.", dev->location.bus, dev->location.slot, dev->location.function);
- dev = LIST_GET_NEXT(pci_device_list, &bus->devices, dev);
- continue;
- }
-
Devices[nDevices-1].hw.mac.autoneg = 1;
Devices[nDevices-1].hw.phy.autoneg_wait_to_complete = false;
Devices[nDevices-1].hw.phy.autoneg_advertised = (ADVERTISE_10_HALF | ADVERTISE_10_FULL | ADVERTISE_100_HALF | ADVERTISE_100_FULL | ADVERTISE_1000_FULL);
@@ -414,6 +412,27 @@ static void search_bus(pci_bus* bus)
}
Devices[nDevices-1].hw.mac.report_tx_early = true;
+
+ if (e1000_reset_hw(&Devices[nDevices-1].hw) != E1000_SUCCESS)
+ {
+ Mm_VirtualMemoryFree(&Mm_KernelContext, (void*)Devices[nDevices-1].osdep.membase, bar0->bar->size);
+ nDevices--;
+ Devices = Reallocate(OBOS_NonPagedPoolAllocator, Devices, nDevices*sizeof(e1000_device), (nDevices+1)*sizeof(e1000_device), nullptr);
+ OBOS_Warning("%02x:%02x:%02x: Bogus E1000 PCI node.", dev->location.bus, dev->location.slot, dev->location.function);
+ dev = LIST_GET_NEXT(pci_device_list, &bus->devices, dev);
+ continue;
+ }
+ e1000_power_up_phy(&Devices[nDevices-1].hw);
+
+ if (e1000_validate_nvm_checksum(&Devices[nDevices-1].hw) != E1000_SUCCESS)
+ {
+ Mm_VirtualMemoryFree(&Mm_KernelContext, (void*)Devices[nDevices-1].osdep.membase, bar0->bar->size);
+ nDevices--;
+ Devices = Reallocate(OBOS_NonPagedPoolAllocator, Devices, nDevices*sizeof(e1000_device), (nDevices+1)*sizeof(e1000_device), nullptr);
+ OBOS_Warning("%02x:%02x:%02x: Bogus E1000 PCI node.", dev->location.bus, dev->location.slot, dev->location.function);
+ dev = LIST_GET_NEXT(pci_device_list, &bus->devices, dev);
+ continue;
+ }
// if (e1000_init_hw(&Devices[nDevices-1].hw) != E1000_SUCCESS)
// {
@@ -425,7 +444,6 @@ static void search_bus(pci_bus* bus)
// continue;
// }
- e1000_power_up_phy(&Devices[nDevices-1].hw);
e1000_disable_ulp_lpt_lp(&Devices[nDevices-1].hw, true);
Devices[nDevices-1].rx_evnt = EVENT_INITIALIZE(EVENT_NOTIFICATION);
@@ -444,8 +462,8 @@ static void search_bus(pci_bus* bus)
Devices[nDevices-1].irq.irqCheckerUserdata = Devices + nDevices - 1;
Devices[nDevices-1].irq.handlerUserdata = Devices + nDevices - 1;
- e1000_init_tx(&Devices[nDevices-1]);
e1000_init_rx(&Devices[nDevices-1]);
+ e1000_init_tx(&Devices[nDevices-1]);
e1000_clear_hw_cntrs_base_generic(&Devices[nDevices-1].hw);
E1000_WRITE_REG(&Devices[nDevices-1].hw, E1000_IMS, IMS_ENABLE_MASK);
diff --git a/src/drivers/generic/initrd/main.c b/src/drivers/generic/initrd/main.c
index 0932982c..a94981d0 100644
--- a/src/drivers/generic/initrd/main.c
+++ b/src/drivers/generic/initrd/main.c
@@ -177,7 +177,6 @@ static int64_t strrfind(const char* str, char ch)
initrd_inode* create_inode_boot(const ustar_hdr* hdr)
{
initrd_inode* ino = ZeroAllocate(OBOS_KernelAllocator, 1, sizeof(initrd_inode), nullptr);
- ino->ino = CurrentInodeNumber++;
bool path_needs_slash = hdr->filename[0] != '/' && (*hdr->prefix && hdr->prefix[strnlen(hdr->prefix, 155)-1] != '/');
ino->path_len = strnlen(hdr->filename, 100) + strnlen(hdr->prefix, 155) + path_needs_slash;
@@ -201,8 +200,6 @@ initrd_inode* create_inode_boot(const ustar_hdr* hdr)
ino->name = Allocate(OBOS_KernelAllocator, ino->name_len+1, nullptr);
memcpy(ino->name, ino->path+index, ino->name_len);
ino->name[ino->name_len] = 0;
- ino->filesize = oct2bin(hdr->filesize, strnlen(hdr->filesize, 12));
- ino->data = (char*)hdr + 512;
// ino->data = Allocate(OBOS_NonPagedPoolAllocator, ino->filesize, nullptr);
// if (!ino->data)
// {
@@ -213,6 +210,7 @@ initrd_inode* create_inode_boot(const ustar_hdr* hdr)
// return nullptr;
// }
// memcpy(ino->data, (char*)hdr + 512, ino->filesize);
+ back:
switch (hdr->type) {
case AREGTYPE:
case REGTYPE:
@@ -221,13 +219,29 @@ initrd_inode* create_inode_boot(const ustar_hdr* hdr)
case DIRTYPE:
ino->type = FILE_TYPE_DIRECTORY;
break;
- case LNKTYPE:
case SYMTYPE:
ino->type = FILE_TYPE_SYMBOLIC_LINK;
break;
+ case LNKTYPE:
+ {
+ obos_status status = OBOS_STATUS_SUCCESS;
+ hdr = GetFile(hdr->linked, &status);
+ if (obos_is_error(status))
+ {
+ Free(OBOS_KernelAllocator, ino->name, ino->name_size);
+ Free(OBOS_KernelAllocator, ino->path, ino->path_size);
+ Free(OBOS_KernelAllocator, ino, sizeof(*ino));
+ return nullptr;
+ }
+ goto back;
+ break;
+ }
default:
OBOS_ENSURE(!"Unrecognized header type");
}
+ ino->filesize = oct2bin(hdr->filesize, strnlen(hdr->filesize, 12));
+ ino->data = (char*)hdr + 512;
+
uint16_t filemode = oct2bin(hdr->filemode, strnlen(hdr->filemode, 8));
ino->perm.group_read = filemode & FILEMODE_GROUP_READ;
ino->perm.owner_read = filemode & FILEMODE_OWNER_READ;
@@ -242,13 +256,12 @@ initrd_inode* create_inode_boot(const ustar_hdr* hdr)
ino->perm.set_gid = filemode & 02000;
ino->linked_path = hdr->linked;
-
ino->vnode = Vfs_Calloc(1, sizeof(vnode));
ino->vnode->desc = (uintptr_t)ino;
ino->vnode->filesize = ino->filesize;
ino->vnode->blkSize = 1;
- ino->vnode->owner_uid = 0;
- ino->vnode->group_uid = 0;
+ ino->vnode->uid = 0;
+ ino->vnode->gid = 0;
ino->vnode->inode = ino->ino;
ino->vnode->perm = ino->perm;
ino->vnode->times.change = oct2bin(hdr->last_mod, strnlen(hdr->last_mod, 12));
@@ -270,6 +283,8 @@ initrd_inode* create_inode_boot(const ustar_hdr* hdr)
}
ino->hdr = hdr;
+ ino->ino = CurrentInodeNumber++;
+
return ino;
}
driver_init_status OBOS_DriverEntry(driver_id* this)
@@ -315,6 +330,8 @@ driver_init_status OBOS_DriverEntry(driver_id* this)
goto down;
initrd_inode* ino = create_inode_boot(hdr);
+ if (!ino)
+ return (driver_init_status){.status=OBOS_STATUS_INTERNAL_ERROR,.fatal=false};
ino->parent = InitrdRoot;
if (!ino->parent->children.head)
ino->parent->children.head = ino;
@@ -472,6 +489,8 @@ initrd_inode* create_inode_with_parents(const char* path, const ustar_hdr* hdr)
return nullptr;
initrd_inode* ino = create_inode_boot(hdr);
+ if (!ino)
+ return nullptr;
// Get our parent.
int64_t index = strrfind(ino->path, '/');
if (index == -1)
@@ -508,6 +527,13 @@ initrd_inode* create_inode_with_parents(const char* path, const ustar_hdr* hdr)
goto down;
initrd_inode* sub_ino = create_inode_boot(sub_hdr);
+ if (!sub_ino)
+ {
+ Free(OBOS_KernelAllocator, ino->name, ino->name_size);
+ Free(OBOS_KernelAllocator, ino->path, ino->path_size);
+ Free(OBOS_KernelAllocator, ino, sizeof(*ino));
+ return nullptr;
+ }
sub_ino->parent = ino->parent;
// printf("%s %s\n", iter, sub_ino->parent->name);
if (!sub_ino->parent->children.head)
@@ -618,7 +644,7 @@ OBOS_PAGEABLE_FUNCTION obos_status list_dir(dev_desc dir_, void* unused, iterate
initrd_inode *ino = DirentLookupFrom(hdr_path, dir);
if (!ino)
ino = create_inode_with_parents(hdr_path, hdr);
- if (ino->dead)
+ if (!ino || ino->dead)
goto down;
if (cb((dev_desc)ino, 1, ino->filesize, userdata, ino->name) == ITERATE_DECISION_STOP)
{
diff --git a/src/drivers/generic/libps2/keyboard.c b/src/drivers/generic/libps2/keyboard.c
index 02822840..cef6ad7b 100644
--- a/src/drivers/generic/libps2/keyboard.c
+++ b/src/drivers/generic/libps2/keyboard.c
@@ -155,7 +155,9 @@ static obos_status read_code(void* handle, keycode* out, bool block)
if (!Core_EventGetState(port->data_ready_event) && !block)
return OBOS_STATUS_WOULD_BLOCK;
- Core_WaitOnObject(WAITABLE_OBJECT(*port->data_ready_event));
+ obos_status status = Core_WaitOnObject(WAITABLE_OBJECT(*port->data_ready_event));
+ if (obos_is_error(status))
+ return status;
}
return PS2_RingbufferFetchKeycode(&data->input, &hnd->in_ptr, out);
@@ -282,10 +284,9 @@ OBOS_PAGEABLE_FUNCTION void PS2_InitializeKeyboard(ps2_port* port)
// 'true' is not an error, see PS2_StartKeyboard
port->suppress_irqs = true;
-
-
data->set = set;
+ data->input.e = EVENT_INITIALIZE(EVENT_NOTIFICATION);
port->data_ready_event = &data->input.e;
port->read_code = read_code;
port->make_handle = make_handle;
diff --git a/src/drivers/generic/libps2/mouse.c b/src/drivers/generic/libps2/mouse.c
index 29b197a8..5c3768bc 100644
--- a/src/drivers/generic/libps2/mouse.c
+++ b/src/drivers/generic/libps2/mouse.c
@@ -36,7 +36,9 @@ static obos_status read_pckt(void* handle, mouse_packet* out, bool block)
if (!Core_EventGetState(port->data_ready_event) && !block)
return OBOS_STATUS_WOULD_BLOCK;
- Core_WaitOnObject(WAITABLE_OBJECT(*port->data_ready_event));
+ obos_status status = Core_WaitOnObject(WAITABLE_OBJECT(*port->data_ready_event));
+ if (obos_is_error(status))
+ return status;
}
return PS2_RingbufferFetchMousePacket(&data->packets, &hnd->in_ptr, out);
diff --git a/src/drivers/generic/r8169/device.c b/src/drivers/generic/r8169/device.c
index 17a549be..ebd72b27 100644
--- a/src/drivers/generic/r8169/device.c
+++ b/src/drivers/generic/r8169/device.c
@@ -385,6 +385,7 @@ static void* map_registers(uintptr_t phys, size_t size, bool uc, bool mmio, bool
MmH_RefPage(pg);
MmS_SetPageMapping(Mm_KernelContext.pt, &page, phys + offset, false);
}
+ Drv_TLBShootdown(Mm_KernelContext.pt, (uintptr_t)virt, size);
return virt+phys_page_offset;
}
diff --git a/src/drivers/test_driver/fireworks.c b/src/drivers/test_driver/fireworks.c
index ed3b4c1e..7e099a39 100644
--- a/src/drivers/test_driver/fireworks.c
+++ b/src/drivers/test_driver/fireworks.c
@@ -290,7 +290,7 @@ void particle_handler(void* udata)
udata[3] = t.lastTimeTicked;
if (obos_is_error(status))
goto die;
- Core_WaitOnObject(WAITABLE_OBJECT(e));
+ status = Core_WaitOnObject(WAITABLE_OBJECT(e));
goto die;
}
int t = 0;
diff --git a/src/init/main.c b/src/init/main.c
index 339db47a..16d945a6 100644
--- a/src/init/main.c
+++ b/src/init/main.c
@@ -144,13 +144,13 @@ int main(int argc, char** argv)
setenv("PATH", "/usr/bin:/bin:/usr/sbin:/sbin", 1);
+ nm_initialize_hostname();
+ nm_initialize_interfaces("/etc/interfaces.json");
+
int ret = print_motd();
if (ret != 0)
return ret;
- nm_initialize_hostname();
- nm_initialize_interfaces("/etc/interfaces.json");
-
syscall1(Sys_SetKLogLevel, final_log_level);
// Start a shell, I guess.
@@ -179,7 +179,7 @@ int main(int argc, char** argv)
top:
waitpid(pid, &status, 0);
if (WIFSIGNALED(status))
- printf("Child exitted due to signal %d\n", WTERMSIG(status));
+ printf("Handoff process exited due to signal %d\n", WTERMSIG(status));
if (!WIFEXITED(status) && !WIFSIGNALED(status))
goto top;
sigchld_handler(SIGCHLD);
diff --git a/src/init/nm.c b/src/init/nm.c
index 3b6ea998..9a2546d4 100644
--- a/src/init/nm.c
+++ b/src/init/nm.c
@@ -146,6 +146,8 @@ bool nm_initialize_interface(cJSON* top_level)
pid_t pid = 0;
if ((pid = fork()) == 0)
{
+ setpgrp();
+ tcsetpgrp(0, getpgrp());
char *argv[3] = {
"obos_dhcpc",
(char*)interface_name,
@@ -189,19 +191,37 @@ bool nm_initialize_interface(cJSON* top_level)
for (size_t i = 0; i < ip_table_len; i++)
{
if (ip_table[i].address.addr && ip_table[i].broadcast.addr && ip_table[i].subnet)
- ioctl(fd, IOCTL_IFACE_ADD_IP_TABLE_ENTRY, &ip_table[i]);
+ {
+ if (ioctl(fd, IOCTL_IFACE_ADD_IP_TABLE_ENTRY, &ip_table[i]) != 0)
+ {
+ fprintf(stderr, "ioctl(IOCTL_IFACE_ADD_IP_TABLE_ENTRY): %s\nIs the interface already configured?\n", strerror(errno));
+ return false;
+ }
+ }
else
fprintf(stderr, "NM: %s: Skipping invalid ip table entry\n", interface_name);
}
for (size_t i = 0; i < nGateways; i++)
{
if (gateways[i].src.addr && gateways[i].dest.addr)
- ioctl(fd, IOCTL_IFACE_ADD_ROUTING_TABLE_ENTRY, &gateways[i]);
+ {
+ if (ioctl(fd, IOCTL_IFACE_ADD_ROUTING_TABLE_ENTRY, &gateways[i]) != 0)
+ {
+ fprintf(stderr, "ioctl(IOCTL_IFACE_ADD_ROUTING_TABLE_ENTRY): %s\nIs the router up, or is the interface already configured?\n", strerror(errno));
+ return false;
+ }
+ }
else
fprintf(stderr, "NM: %s: Skipping invalid static route\n", interface_name);
}
if (default_gateway.addr)
- ioctl(fd, IOCTL_IFACE_SET_DEFAULT_GATEWAY, &default_gateway);
+ {
+ if (ioctl(fd, IOCTL_IFACE_SET_DEFAULT_GATEWAY, &default_gateway) != 0)
+ {
+ fprintf(stderr, "ioctl(IOCTL_IFACE_SET_DEFAULT_GATEWAY): %s\nIs the router up, or is the interface already configured?\n", strerror(errno));
+ return false;
+ }
+ }
else
fprintf(stderr, "NM: %s: Skipping default gateway\n", interface_name);
@@ -264,7 +284,7 @@ void nm_initialize_interfaces(const char* config_file)
if (nm_initialize_interface(obj))
nInterfacesInitialized++;
}
- printf("NM: Initialized %ld interfaces (%ld failed)\n", nInterfacesInitialized, nInterfaces-nInterfacesInitialized);
+ printf("NM: Initialized %ld interfaces (%ld failed)\n\n", nInterfacesInitialized, nInterfaces-nInterfacesInitialized);
cJSON_Delete(top_level);
}
diff --git a/src/isogen/isogen.cmake b/src/isogen/isogen.cmake
index da04ffbe..85027121 100644
--- a/src/isogen/isogen.cmake
+++ b/src/isogen/isogen.cmake
@@ -14,9 +14,6 @@ endif()
if (NOT EXISTS ${ISODIR}/obos)
file (MAKE_DIRECTORY ${ISODIR}/obos)
endif()
-if (NOT EXISTS ${CMAKE_SOURCE_DIR}/config/hyper.cfg)
- message(FATAL_ERROR "No hyper configuration file detected!")
-endif()
if (CMAKE_HOST_WIN32)
set(SUPPRESS_OUTPUT > NUL 2>&1)
@@ -24,24 +21,48 @@ elseif(CMAKE_HOST_LINUX)
set(SUPPRESS_OUTPUT > /dev/null 2>&1)
endif()
+if (OBOS_USE_LIMINE)
+ set (LIMINE_ENABLED "true")
+ set (LIMINE_NOT_ENABLED "false")
+ set(BIOS_INSTALL ${limine_exe} bios-install ${OUTPUT_DIR}/obos.iso ${SUPPRESS_OUTPUT})
+ set(BIOS_PRE_XORRISO fallocate -l16M ${ISODIR}/obos/flanterm_buff && cmake -E make_directory ${ISODIR}/limine/ && cmake -E copy ${CMAKE_SOURCE_DIR}/dependencies/limine/limine-bios.sys ${ISODIR}/limine/)
+ set(BTLDR_CONF "limine.conf")
+ set(xorriso_bios_cd_path "dependencies/limine/limine-bios-cd.bin")
+ set(xorriso_uefi_cd_path "dependencies/limine/limine-uefi-cd.bin")
+ set(xorriso_uefi_cd_name "limine-uefi-cd.bin")
+ set(xorriso_bios_cd_name "limine-bios-cd.bin")
+else()
+ set(BIOS_INSTALL ${hyper_install} ${OUTPUT_DIR}/obos.iso ${SUPPRESS_OUTPUT})
+ set(BIOS_PRE_XORRISO true)
+ set(BTLDR_CONF "hyper.cfg")
+ set(xorriso_bios_cd_path "dependencies/hyper/hyper_iso_boot")
+ set(xorriso_uefi_cd_path "config/hyper_uefi_boot.bin")
+ set(xorriso_uefi_cd_name "hyper_uefi_boot.bin")
+ set(xorriso_bios_cd_name "hyper_iso_boot")
+endif()
+
+if (NOT EXISTS ${CMAKE_SOURCE_DIR}/config/${BTLDR_CONF})
+ message(FATAL_ERROR "No bootloader configuration file detected!")
+endif()
+
add_custom_command(OUTPUT ${OUTPUT_DIR}/obos.iso
COMMAND ${OBJCOPY} -g ${OUTPUT_DIR}/oboskrnl ${ISODIR}/obos/oboskrnl ${SUPPRESS_OUTPUT}
- COMMAND cmake -E copy ${CMAKE_SOURCE_DIR}/config/hyper.cfg ${ISODIR}/ ${SUPPRESS_OUTPUT}
- COMMAND cmake -E copy ${CMAKE_SOURCE_DIR}/dependencies/hyper/hyper_iso_boot ${ISODIR} ${SUPPRESS_OUTPUT}
- COMMAND cmake -E copy ${CMAKE_SOURCE_DIR}/config/hyper_uefi_boot.bin ${ISODIR} ${SUPPRESS_OUTPUT}
+ COMMAND cmake -E copy ${CMAKE_SOURCE_DIR}/config/${BTLDR_CONF} ${ISODIR}/ ${SUPPRESS_OUTPUT}
+ COMMAND cmake -E copy ${CMAKE_SOURCE_DIR}/${xorriso_bios_cd_path} ${ISODIR} ${SUPPRESS_OUTPUT}
+ COMMAND cmake -E copy ${CMAKE_SOURCE_DIR}/${xorriso_uefi_cd_path} ${ISODIR} ${SUPPRESS_OUTPUT}
COMMAND cmake -E copy ${CMAKE_SOURCE_DIR}/out/initrd ${ISODIR}/obos ${SUPPRESS_OUTPUT}
COMMAND cmake -E copy ${CMAKE_SOURCE_DIR}/config/initrd.tar ${ISODIR}/obos ${SUPPRESS_OUTPUT}
- COMMAND xorriso -as mkisofs -b hyper_iso_boot -no-emul-boot -boot-load-size 4 -boot-info-table --efi-boot hyper_uefi_boot.bin -efi-boot-part --efi-boot-image --protective-msdos-label out/isodir -o ${OUTPUT_DIR}/obos.iso ${SUPPRESS_OUTPUT}
- COMMAND chmod +x ${hyper_install}
- COMMAND ${hyper_install} ${OUTPUT_DIR}/obos.iso ${SUPPRESS_OUTPUT}
- BYPRODUCTS ${ISODIR}/hyper.cfg
- ${ISODIR}/hyper_iso_boot
- ${ISODIR}/hyper_uefi_boot.bin
+ COMMAND ${BIOS_PRE_XORRISO}
+ COMMAND xorriso -as mkisofs -b ${xorriso_bios_cd_name} -no-emul-boot -boot-load-size 4 -boot-info-table --efi-boot ${xorriso_uefi_cd_name} -efi-boot-part --efi-boot-image --protective-msdos-label out/isodir -o ${OUTPUT_DIR}/obos.iso ${SUPPRESS_OUTPUT}
+ COMMAND ${BIOS_INSTALL}
+ BYPRODUCTS ${ISODIR}/${BTLDR_CONF}
+ ${ISODIR}/${xorriso_bios_cd_name}
+ ${ISODIR}/${xorriso_uefi_cd_name}
${ISODIR}/obos/oboskrnl
${ISODIR}/obos/initrd
${ISODIR}/obos/initrd.tar
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
- DEPENDS ${CMAKE_SOURCE_DIR}/config/initrd.tar ${CMAKE_SOURCE_DIR}/config/hyper.cfg oboskrnl initrd
+ DEPENDS ${CMAKE_SOURCE_DIR}/config/initrd.tar ${CMAKE_SOURCE_DIR}/config/${BTLDR_CONF} oboskrnl initrd
)
add_custom_target (isogen ALL
DEPENDS oboskrnl initrd ${OUTPUT_DIR}/obos.iso
diff --git a/src/oboskrnl/allocators/base.h b/src/oboskrnl/allocators/base.h
index 45cc6002..4645996f 100644
--- a/src/oboskrnl/allocators/base.h
+++ b/src/oboskrnl/allocators/base.h
@@ -66,8 +66,8 @@ typedef struct allocator_info
OBOS_EXPORT obos_status Free(struct allocator_info* This, void* base, size_t nBytes);
#ifndef __clang__
-OBOS_EXPORT __attribute__((malloc, malloc(Free, 2))) void* Allocate(struct allocator_info* This, size_t nBytes, obos_status* status);
-OBOS_EXPORT __attribute__((malloc, malloc(Free, 2))) void* ZeroAllocate(struct allocator_info* This, size_t nObjects, size_t bytesPerObject, obos_status* status);
+OBOS_EXPORT __attribute__((malloc, malloc(Free, 2), returns_nonnull)) void* Allocate(struct allocator_info* This, size_t nBytes, obos_status* status);
+OBOS_EXPORT __attribute__((malloc, malloc(Free, 2), returns_nonnull)) void* ZeroAllocate(struct allocator_info* This, size_t nObjects, size_t bytesPerObject, obos_status* status);
#else
OBOS_EXPORT void* Allocate(struct allocator_info* This, size_t nBytes, obos_status* status);
OBOS_EXPORT void* ZeroAllocate(struct allocator_info* This, size_t nObjects, size_t bytesPerObject, obos_status* status);
diff --git a/src/oboskrnl/arch/m68k/entry.c b/src/oboskrnl/arch/m68k/entry.c
index 01d6aa2e..baea8904 100644
--- a/src/oboskrnl/arch/m68k/entry.c
+++ b/src/oboskrnl/arch/m68k/entry.c
@@ -175,6 +175,7 @@ void Arch_KernelEntryBootstrap()
CoreH_ThreadInitialize(&idle_thread, THREAD_PRIORITY_IDLE, Core_DefaultThreadAffinity, &ctx);
CoreH_ThreadReadyNode(&kmain_thread, &kmain_node);
CoreH_ThreadReadyNode(&idle_thread, &idle_thread_node);
+ bsp_cpu.nReadyThreads--;
Core_LowerIrql(oldIrql);
// Finally, yield.
diff --git a/src/oboskrnl/arch/m68k/gf_tty.c b/src/oboskrnl/arch/m68k/gf_tty.c
index c9783f97..8ba91c72 100644
--- a/src/oboskrnl/arch/m68k/gf_tty.c
+++ b/src/oboskrnl/arch/m68k/gf_tty.c
@@ -4,6 +4,7 @@
* Copyright (c) 2025 Omar Berrow
*/
+#include "error.h"
#include
#include
@@ -92,7 +93,8 @@ static void poll_gf_tty(struct gf_tty_iface* iface)
// struct gf_tty* dev = (void*)Arch_TTYBase;
while (1)
{
- Core_WaitOnObject(WAITABLE_OBJECT(iface->data_ready_evnt));
+ if (obos_is_error(Core_WaitOnObject(WAITABLE_OBJECT(iface->data_ready_evnt))))
+ continue;
irql oldIrql = Core_RaiseIrql(IRQL_DISPATCH);
if (iface->data_ready)
{
diff --git a/src/oboskrnl/arch/m68k/syscall.c b/src/oboskrnl/arch/m68k/syscall.c
index 4ce9df1c..859f9ce2 100644
--- a/src/oboskrnl/arch/m68k/syscall.c
+++ b/src/oboskrnl/arch/m68k/syscall.c
@@ -160,6 +160,14 @@ const char *syscall_to_string[] = {
"Sys_UMask",
"Sys_RenameAt",
"Sys_UTimeNSAt",
+ "Sys_ThreadGetStack",
+ "Sys_SetRESUid",
+ "Sys_SetRESGid",
+ "Sys_GetRESUid",
+ "Sys_GetRESGid",
+ "Sys_SigPending",
+ "Sys_SetGroups",
+ "Sys_GetGroups",
};
const char* status_to_string[] = {
diff --git a/src/oboskrnl/arch/x86_64/boot_info.h b/src/oboskrnl/arch/x86_64/boot_info.h
index 4bc49dcd..eebfe263 100644
--- a/src/oboskrnl/arch/x86_64/boot_info.h
+++ b/src/oboskrnl/arch/x86_64/boot_info.h
@@ -6,6 +6,8 @@
#pragma once
+#if !OBOS_USE_LIMINE
+
#include
extern volatile struct ultra_memory_map_attribute* Arch_MemoryMap;
@@ -14,4 +16,21 @@ extern volatile struct ultra_kernel_info_attribute* Arch_KernelInfo;
extern volatile struct ultra_module_info_attribute* Arch_KernelBinary;
extern volatile struct ultra_module_info_attribute* Arch_InitialSwapBuffer;
extern volatile struct ultra_framebuffer* Arch_Framebuffer;
-extern volatile struct ultra_boot_context* Arch_BootContext;
\ No newline at end of file
+extern volatile struct ultra_boot_context* Arch_BootContext;
+#else
+
+#include
+#include
+
+extern volatile struct limine_framebuffer_request Arch_LimineFBRequest;
+extern volatile struct limine_memmap_request Arch_LimineMemmapRequest;
+extern volatile struct limine_module_request Arch_LimineModuleRequest;
+extern volatile struct limine_hhdm_request Arch_LimineHHDMRequest;
+extern volatile struct limine_executable_file_request Arch_LimineKernelInfoRequest;
+extern volatile struct limine_executable_address_request Arch_LimineKernelAddressRequest;
+extern volatile struct limine_executable_cmdline_request Arch_LimineKernelCmdlineRequest;
+extern volatile struct limine_bootloader_info_request Arch_LimineBtldrInfoRequest;
+extern volatile struct ultra_framebuffer* Arch_Framebuffer; // Artificially created
+extern struct limine_file* Arch_KernelBinary;
+#endif
+extern uintptr_t Arch_RSDPBase;
\ No newline at end of file
diff --git a/src/oboskrnl/arch/x86_64/cpu_local_arch.h b/src/oboskrnl/arch/x86_64/cpu_local_arch.h
index 910e089b..ccc7b479 100644
--- a/src/oboskrnl/arch/x86_64/cpu_local_arch.h
+++ b/src/oboskrnl/arch/x86_64/cpu_local_arch.h
@@ -1,7 +1,7 @@
/*
- oboskrnl/arch/x86_64/cpu_local_arch.h
-
- Copyright (c) 2024 Omar Berrow
+ * oboskrnl/arch/x86_64/cpu_local_arch.h
+ *
+ * Copyright (c) 2024 Omar Berrow
*/
#pragma once
@@ -14,6 +14,8 @@
#include
+#include
+
typedef struct cpu_local_arch
{
uint64_t gdtEntries[7];
@@ -45,4 +47,5 @@ typedef struct cpu_local_arch
dpc dbg_dpc;
uint64_t stack_check_guard;
uint8_t lapicId;
+ struct tlb_shootdown_packet* curr_pckt;
} cpu_local_arch;
diff --git a/src/oboskrnl/arch/x86_64/entry.asm b/src/oboskrnl/arch/x86_64/entry.asm
index 18a50d06..79176293 100644
--- a/src/oboskrnl/arch/x86_64/entry.asm
+++ b/src/oboskrnl/arch/x86_64/entry.asm
@@ -14,10 +14,12 @@ extern Arch_disablePIC
extern Arch_KernelEntry
global Arch_KernelEntryBootstrap:function hidden
Arch_KernelEntryBootstrap:
+%if !OBOS_USE_LIMINE
cmp rsi, 0x554c5442
je .ok ; should triple fault on failure
xor rax,rax
jmp rax ; All hope is lost.
+%endif
.ok:
push rdi
push rsi
diff --git a/src/oboskrnl/arch/x86_64/entry.c b/src/oboskrnl/arch/x86_64/entry.c
index d5d7b948..aec4cae1 100644
--- a/src/oboskrnl/arch/x86_64/entry.c
+++ b/src/oboskrnl/arch/x86_64/entry.c
@@ -10,6 +10,8 @@
#include
#include
#include
+#include
+#include
#include
#define FLANTERM_IN_FLANTERM
@@ -47,12 +49,16 @@
#include
#include
-#include "gdbstub/connection.h"
-#include "gdbstub/gdb_udp_backend.h"
-#include "gdbstub/debug.h"
-
#include
+#include
+
+#include
+
+#if OBOS_USE_LIMINE
+# include
+#endif
+
extern void Arch_InitBootGDT();
static char thr_stack[0x4000];
@@ -168,15 +174,16 @@ static void init_flanterm_backend()
OBOS_AddLogSource(&backend);
}
-static struct ultra_module_info_attribute* Arch_FlantermBumpAllocator;
+static struct {
+ uintptr_t address;
+ uintptr_t size;
+} Arch_FlantermBumpAllocator = {};
static void *flanterm_malloc(size_t sz)
{
- if (!Arch_FlantermBumpAllocator)
- return nullptr;
static size_t bump_off = 0;
- if ((bump_off + sz) > Arch_FlantermBumpAllocator->size)
+ if ((bump_off + sz) > Arch_FlantermBumpAllocator.size)
return nullptr;
- void* ret = (void*)(Arch_FlantermBumpAllocator->address + bump_off);
+ void* ret = (void*)(Arch_FlantermBumpAllocator.address + bump_off);
bump_off += sz;
return ret;
}
@@ -186,7 +193,55 @@ static void flanterm_free(void* blk, size_t sz)
return;
}
+#if OBOS_USE_LIMINE
+volatile struct limine_framebuffer_request Arch_LimineFBRequest = {
+ .id = LIMINE_FRAMEBUFFER_REQUEST_ID,
+ .revision = 1,
+};
+volatile struct limine_memmap_request Arch_LimineMemmapRequest = {
+ .id = LIMINE_MEMMAP_REQUEST_ID,
+ .revision = 0,
+};
+volatile struct limine_module_request Arch_LimineModuleRequest = {
+ .id = LIMINE_MODULE_REQUEST_ID,
+ .revision = 1,
+};
+volatile struct limine_hhdm_request Arch_LimineHHDMRequest = {
+ .id = LIMINE_HHDM_REQUEST_ID,
+ .revision = 0,
+};
+volatile struct limine_executable_file_request Arch_LimineKernelInfoRequest = {
+ .id = LIMINE_EXECUTABLE_FILE_REQUEST_ID,
+ .revision = 0,
+};
+volatile struct limine_executable_address_request Arch_LimineKernelAddressRequest = {
+ .id = LIMINE_EXECUTABLE_ADDRESS_REQUEST_ID,
+ .revision = 0,
+};
+volatile struct limine_executable_cmdline_request Arch_LimineKernelCmdlineRequest = {
+ .id = LIMINE_EXECUTABLE_CMDLINE_REQUEST_ID,
+ .revision = 0,
+};
+volatile struct limine_rsdp_request Arch_LimineRSDPRequest = {
+ .id = LIMINE_RSDP_REQUEST_ID,
+ .revision = 0,
+};
+volatile struct limine_bootloader_info_request Arch_LimineBtldrInfoRequest = {
+ .id = LIMINE_BOOTLOADER_INFO_REQUEST_ID,
+ .revision = 0,
+};
+volatile struct ultra_framebuffer limine_fb0 = {};
+volatile struct ultra_framebuffer* Arch_Framebuffer = &limine_fb0;
+struct limine_file* Arch_KernelBinary = nullptr;
+#endif
+
+uintptr_t Arch_RSDPBase = 0;
+
+#if !OBOS_USE_LIMINE
OBOS_PAGEABLE_FUNCTION void __attribute__((no_stack_protector)) Arch_KernelEntry(struct ultra_boot_context* bcontext)
+#else
+OBOS_PAGEABLE_FUNCTION void __attribute__((no_stack_protector)) Arch_KernelEntry()
+#endif
{
bsp_cpu.id = 0;
bsp_cpu.isBSP = true;
@@ -200,18 +255,6 @@ OBOS_PAGEABLE_FUNCTION void __attribute__((no_stack_protector)) Arch_KernelEntry
wrmsr(0xC0000101, (uintptr_t)&Core_CpuInfo[0]);
- ParseBootContext(bcontext);
- Arch_BootContext = bcontext;
- OBOS_ParseCMDLine();
- asm("sti");
-
- uint64_t log_level = OBOS_GetOPTD_Ex("log-level", LOG_LEVEL_LOG);
- if (log_level > 4)
- log_level = LOG_LEVEL_DEBUG;
- OBOS_SetLogLevel(log_level);
- extern uint64_t Arch_KernelCR3;
- Arch_KernelCR3 = getCR3();
-
#if !OBOS_ENABLE_PROFILING
{
uint32_t ecx = 0;
@@ -225,30 +268,71 @@ OBOS_PAGEABLE_FUNCTION void __attribute__((no_stack_protector)) Arch_KernelEntry
}
#endif
+#if !OBOS_USE_LIMINE
+ ParseBootContext(bcontext);
+ Arch_BootContext = bcontext;
+#else
+ OBOS_KernelCmdLine = Arch_LimineKernelCmdlineRequest.response->cmdline;
+ Arch_KernelBinary = Arch_LimineKernelInfoRequest.response->executable_file;
+ Arch_RSDPBase = Arch_UnmapFromHHDM(Arch_LimineRSDPRequest.response->address);
+#endif
+
+ basicmm_region bump_region = {};
+ struct boot_module bump_region_module = {};
+ OBOSS_GetModule(&bump_region_module, "BUMP_REGION");
+ if (!bump_region_module.address)
+ OBOS_Panic(OBOS_PANIC_FATAL_ERROR, "Could not find BUMP_REGION kernel module\n");
+ bump_region.addr = (uintptr_t)bump_region_module.address;
+ bump_region.size = bump_region_module.size;
+ OBOSH_BasicMMSetBumpRegion(&bump_region);
+
+ struct boot_module flanterm_buff = {};
+ OBOSS_GetModule(&flanterm_buff, "FLANTERM_BUFF");
+ if (!flanterm_buff.address)
+ OBOS_Panic(OBOS_PANIC_FATAL_ERROR, "Could not find FLANTERM_BUFF kernel module\n");
+ Arch_FlantermBumpAllocator.address = (uintptr_t)flanterm_buff.address;
+ Arch_FlantermBumpAllocator.size = flanterm_buff.size;
+
+ OBOS_ParseCMDLine();
+ asm("sti");
+
+ uint64_t log_level = OBOS_GetOPTD_Ex("log-level", LOG_LEVEL_LOG);
+ if (log_level > 4)
+ log_level = LOG_LEVEL_DEBUG;
+ OBOS_SetLogLevel(log_level);
+ extern uint64_t Arch_KernelCR3;
+ Arch_KernelCR3 = getCR3();
+
#if 0
init_serial_log_backend();
#endif
+ static uint32_t ansi_colors[8] = {
+ __builtin_bswap32(0x000000) >> 8,
+ __builtin_bswap32(0xbb0000) >> 8,
+ __builtin_bswap32(0x00bb00) >> 8,
+ __builtin_bswap32(0xbbbb00) >> 8,
+ __builtin_bswap32(0x0000bb) >> 8,
+ __builtin_bswap32(0xbb00bb) >> 8,
+ __builtin_bswap32(0x00bbbb) >> 8,
+ __builtin_bswap32(0xbbbbbb) >> 8,
+ };
+ static uint32_t ansi_bright_colors[8] = {
+ __builtin_bswap32(0x555555) >> 8,
+ __builtin_bswap32(0xff5555) >> 8,
+ __builtin_bswap32(0x55ff55) >> 8,
+ __builtin_bswap32(0xffff55) >> 8,
+ __builtin_bswap32(0x5555aa) >> 8,
+ __builtin_bswap32(0xff55ff) >> 8,
+ __builtin_bswap32(0x55ffff) >> 8,
+ __builtin_bswap32(0xffffff) >> 8,
+ };
+ OBOS_UNUSED(ansi_bright_colors && ansi_colors);
+#if !OBOS_USE_LIMINE
if (!Arch_Framebuffer)
OBOS_Warning("No framebuffer passed by the bootloader. All kernel logs will be on port 0xE9.\n");
else
{
- // OBOS_TextRendererState.fg_color = 0xffffffff;
- // OBOS_TextRendererState.fb.base = Arch_MapToHHDM(Arch_Framebuffer->physical_address);
- // OBOS_TextRendererState.fb.bpp = Arch_Framebuffer->bpp;
- // OBOS_TextRendererState.fb.format = Arch_Framebuffer->format;
- // OBOS_TextRendererState.fb.height = Arch_Framebuffer->height;
- // OBOS_TextRendererState.fb.width = Arch_Framebuffer->width;
- // OBOS_TextRendererState.fb.pitch = Arch_Framebuffer->pitch;
- // for (size_t y = 0; y < Arch_Framebuffer->height; y++)
- // for (size_t x = 0; x < Arch_Framebuffer->width; x++)
- // OBOS_PlotPixel(OBOS_TEXT_BACKGROUND, &((uint8_t*)OBOS_TextRendererState.fb.base)[y*Arch_Framebuffer->pitch+x*Arch_Framebuffer->bpp/8], OBOS_TextRendererState.fb.format);
- // OBOS_TextRendererState.column = 0;
- // OBOS_TextRendererState.row = 0;
- // OBOS_TextRendererState.font = font_bin;
- // OBOS_AddLogSource(&OBOS_ConsoleOutputCallback);
- // if (Arch_Framebuffer->format == ULTRA_FB_FORMAT_INVALID)
- // return;
uint8_t red_mask_size = 8, red_mask_shift = 0;
uint8_t green_mask_size = 8, green_mask_shift = 0;
uint8_t blue_mask_size = 8, blue_mask_shift = 0;
@@ -276,29 +360,7 @@ OBOS_PAGEABLE_FUNCTION void __attribute__((no_stack_protector)) Arch_KernelEntry
blue_mask_shift = 16;
bg = bg >> 8;
break;
-
}
- static uint32_t ansi_colors[8] = {
- __builtin_bswap32(0x000000) >> 8,
- __builtin_bswap32(0xbb0000) >> 8,
- __builtin_bswap32(0x00bb00) >> 8,
- __builtin_bswap32(0xbbbb00) >> 8,
- __builtin_bswap32(0x0000bb) >> 8,
- __builtin_bswap32(0xbb00bb) >> 8,
- __builtin_bswap32(0x00bbbb) >> 8,
- __builtin_bswap32(0xbbbbbb) >> 8,
- };
- static uint32_t ansi_bright_colors[8] = {
- __builtin_bswap32(0x555555) >> 8,
- __builtin_bswap32(0xff5555) >> 8,
- __builtin_bswap32(0x55ff55) >> 8,
- __builtin_bswap32(0xffff55) >> 8,
- __builtin_bswap32(0x5555aa) >> 8,
- __builtin_bswap32(0xff55ff) >> 8,
- __builtin_bswap32(0x55ffff) >> 8,
- __builtin_bswap32(0xffffff) >> 8,
-
- };
OBOS_FlantermContext = flanterm_fb_init(
flanterm_malloc, flanterm_free,
Arch_MapToHHDM(Arch_Framebuffer->physical_address), Arch_Framebuffer->width, Arch_Framebuffer->height, Arch_Framebuffer->pitch,
@@ -318,6 +380,54 @@ OBOS_PAGEABLE_FUNCTION void __attribute__((no_stack_protector)) Arch_KernelEntry
if (Arch_LdrPlatformInfo->page_table_depth != 4)
OBOS_Panic(OBOS_PANIC_FATAL_ERROR, "5-level paging is unsupported by oboskrnl.\n");
+#else
+ if (Arch_LimineFBRequest.response->framebuffer_count)
+ {
+ struct limine_framebuffer *fb = Arch_LimineFBRequest.response->framebuffers[0];
+ OBOS_FlantermContext = flanterm_fb_init(
+ flanterm_malloc, flanterm_free,
+ fb->address, fb->width, fb->height, fb->pitch,
+ fb->red_mask_size, fb->red_mask_shift,
+ fb->green_mask_size, fb->green_mask_shift,
+ fb->blue_mask_size, fb->blue_mask_shift,
+ nullptr, nullptr,
+ nullptr, nullptr,
+ nullptr, nullptr,
+ nullptr,
+ // (void*)font_bin, 8, 16, 0,
+ nullptr, 8, 16, 0,
+ 0,0,
+ 0);
+ init_flanterm_backend();
+ limine_fb0.physical_address = Arch_UnmapFromHHDM(fb->address);
+ limine_fb0.bpp = fb->bpp;
+ limine_fb0.width = fb->width;
+ limine_fb0.height = fb->height;
+ limine_fb0.pitch = fb->pitch;
+ do {
+ if (limine_fb0.bpp == 24)
+ {
+ if (fb->blue_mask_shift == 0 && fb->green_mask_shift == 8 && fb->red_mask_shift == 16)
+ limine_fb0.format = ULTRA_FB_FORMAT_RGB888;
+ if (fb->red_mask_shift == 0 && fb->green_mask_shift == 8 && fb->blue_mask_shift == 16)
+ limine_fb0.format = ULTRA_FB_FORMAT_BGR888;
+ break;
+ }
+ else if (limine_fb0.bpp == 32)
+ {
+ uint8_t x_shift = 0;
+ if (fb->red_mask_shift == 16) x_shift = 24;
+ else if (fb->red_mask_shift == 24) x_shift = 0;
+ if (x_shift == 0 && fb->blue_mask_shift == 8 && fb->green_mask_shift == 16 && fb->red_mask_shift == 24)
+ limine_fb0.format = ULTRA_FB_FORMAT_RGBX8888;
+ if (fb->blue_mask_shift == 0 && fb->green_mask_shift == 8 && fb->red_mask_shift == 16 && x_shift == 24)
+ limine_fb0.format = ULTRA_FB_FORMAT_XRGB8888;
+ break;
+ }
+ } while(0);
+ }
+#endif
+
#if OBOS_RELEASE
OBOS_Log("Booting OBOS %s committed on %s. Build time: %s.\n", GIT_SHA1, GIT_DATE, __DATE__ " " __TIME__);
@@ -333,8 +443,15 @@ OBOS_PAGEABLE_FUNCTION void __attribute__((no_stack_protector)) Arch_KernelEntry
__cpuid__(0x80000003, 0, (uint32_t*)&brand_string[16], (uint32_t*)&brand_string[20], (uint32_t*)&brand_string[24], (uint32_t*)&brand_string[28]);
__cpuid__(0x80000004, 0, (uint32_t*)&brand_string[32], (uint32_t*)&brand_string[36], (uint32_t*)&brand_string[40], (uint32_t*)&brand_string[44]);
OBOS_Log("Running on a %s processor, cpu brand string, %s. We are currently %srunning on a hypervisor\n", cpu_vendor, brand_string, isHypervisor ? "" : "not ");
+
+#if OBOS_USE_LIMINE
+ OBOS_Log("Bootloader is %s-%s\n", Arch_LimineBtldrInfoRequest.response->name, Arch_LimineBtldrInfoRequest.response->version);
+#else
+ OBOS_Log("Bootloader is %.32s\n", Arch_LdrPlatformInfo->loader_name, Arch_LdrPlatformInfo->loader_major, Arch_LdrPlatformInfo->loader_minor);
#endif
+#endif
+
OBOS_Debug("%s: Initializing the Boot GDT.\n", __func__);
Arch_InitBootGDT();
@@ -373,6 +490,8 @@ OBOS_PAGEABLE_FUNCTION void __attribute__((no_stack_protector)) Arch_KernelEntry
CoreH_ThreadReady(&kernelMainThread);
CoreH_ThreadReady(&bsp_idleThread);
Core_CpuInfo->idleThread = &bsp_idleThread;
+ Core_CpuInfo->nReadyThreads--;
+ Core_ReadyThreadCount--;
// Initialize the CPU's GDT.
Arch_CPUInitializeGDT(&Core_CpuInfo[0], (uintptr_t)Arch_InitialISTStack, sizeof(Arch_InitialISTStack));
@@ -391,6 +510,7 @@ OBOS_PAGEABLE_FUNCTION void __attribute__((no_stack_protector)) Arch_KernelEntry
asm volatile("nop" : : :);
}
+#if !OBOS_USE_LIMINE
volatile struct ultra_memory_map_attribute* Arch_MemoryMap;
volatile struct ultra_platform_info_attribute* Arch_LdrPlatformInfo;
volatile struct ultra_kernel_info_attribute* Arch_KernelInfo;
@@ -437,8 +557,6 @@ static OBOS_PAGEABLE_FUNCTION OBOS_NO_KASAN OBOS_NO_UBSAN void ParseBootContext(
struct ultra_module_info_attribute* module = (struct ultra_module_info_attribute*)header;
if (strcmp(module->name, "__KERNEL__"))
Arch_KernelBinary = module;
- else if (strcmp(module->name, "FLANTERM_BUFF"))
- Arch_FlantermBumpAllocator = module;
break;
}
case ULTRA_ATTRIBUTE_INVALID:
@@ -458,9 +576,9 @@ static OBOS_PAGEABLE_FUNCTION OBOS_NO_KASAN OBOS_NO_UBSAN void ParseBootContext(
OBOS_Panic(OBOS_PANIC_FATAL_ERROR, "Invalid partition type %d.\n", Arch_KernelInfo->partition_type);
if (!Arch_KernelBinary)
OBOS_Panic(OBOS_PANIC_FATAL_ERROR, "Could not find the kernel module in boot context!\nDo you set kernel-as-module to true in the hyper.cfg?\n");
- if (!Arch_FlantermBumpAllocator)
- OBOS_Panic(OBOS_PANIC_FATAL_ERROR, "Could not find the FLANTERM_BUFF module in boot context!\nMake sure to pass a module named FLANTERM_BUFF with a size big enough for width*pitch?\n");
+ Arch_RSDPBase = Arch_LdrPlatformInfo->acpi_rsdp_address;
}
+#endif
extern obos_status Arch_InitializeKernelPageTable();
@@ -548,6 +666,7 @@ void OBOSS_InitializeSMP()
Core_GetCurrentThread()->masterCPU = CoreS_GetCPULocalPtr();
}
+#if !OBOS_USE_LIMINE
static void ultra_module_to_boot_module(const struct ultra_module_info_attribute *ultra_module, struct boot_module* out_module)
{
if (!ultra_module || !out_module)
@@ -572,6 +691,42 @@ void OBOSS_GetKernelModule(struct boot_module *module)
{
ultra_module_to_boot_module((void*)Arch_KernelBinary, module);
}
+#else
+static void limine_file_to_boot_module(const struct limine_file *file, struct boot_module* out_module)
+{
+ if (!file || !out_module)
+ return;
+ out_module->address = file->address;
+ out_module->size = file->size;
+ out_module->name = file->string;
+ out_module->is_memory = false;
+ out_module->is_kernel = file == Arch_LimineKernelInfoRequest.response->executable_file;
+ return;
+}
+static struct limine_file* find_module(const char* name, size_t name_len)
+{
+ for (size_t i = 0; i < Arch_LimineModuleRequest.response->module_count; i++)
+ {
+ struct limine_file* cur = Arch_LimineModuleRequest.response->modules[i];
+ if (strncmp(cur->string, name, name_len))
+ return cur;
+ }
+ return nullptr;
+}
+
+void OBOSS_GetModule(struct boot_module *module, const char* name)
+{
+ limine_file_to_boot_module(find_module(name, strlen(name)), module);
+}
+void OBOSS_GetModuleLen(struct boot_module *module, const char* name, size_t name_len)
+{
+ limine_file_to_boot_module(find_module(name, name_len), module);
+}
+void OBOSS_GetKernelModule(struct boot_module *module)
+{
+ limine_file_to_boot_module(Arch_LimineKernelInfoRequest.response->executable_file, module);
+}
+#endif
void OBOSS_MakeTTY()
{
diff --git a/src/oboskrnl/arch/x86_64/except.c b/src/oboskrnl/arch/x86_64/except.c
index 87192ef5..d57f0b4a 100644
--- a/src/oboskrnl/arch/x86_64/except.c
+++ b/src/oboskrnl/arch/x86_64/except.c
@@ -94,7 +94,7 @@ __attribute__((no_instrument_function)) OBOS_NO_UBSAN OBOS_NO_KASAN void Arch_Pa
if (frame->cs & 3)
{
OBOS_Log("User thread %d SIGSEGV (rip 0x%p, cr2 0x%p, error code 0x%08x)\n", Core_GetCurrentThread()->tid, frame->rip, getCR2(), frame->errorCode);
- Core_GetCurrentThread()->signal_info->signals[SIGSEGV].addr = (void*)getCR2();
+ Core_GetCurrentThread()->proc->signal_handlers[SIGSEGV].addr = (void*)getCR2();
OBOS_Kill(Core_GetCurrentThread(), Core_GetCurrentThread(), SIGSEGV);
// OBOS_SyncPendingSignal(frame);
OBOS_RunSignal(SIGSEGV, frame); // Ensure SIGSEGV runs.
diff --git a/src/oboskrnl/arch/x86_64/execve.c b/src/oboskrnl/arch/x86_64/execve.c
index 792bc124..17556c38 100644
--- a/src/oboskrnl/arch/x86_64/execve.c
+++ b/src/oboskrnl/arch/x86_64/execve.c
@@ -160,6 +160,8 @@ OBOS_NORETURN OBOS_NO_KASAN void OBOSS_HandControlTo(struct context* ctx, struct
// Core_GetCurrentThread()->context.fs_base = 0;
// Core_GetCurrentThread()->context.gs_base = 0;
+ Mm_VirtualMemoryFree(&Mm_KernelContext, init_vals, szAllocation);
+
OBOS_Debug("Handing off control to user program.\n");
OBOS_Debug("NOTE: RSP=0x%p.\n", Core_GetCurrentThread()->context.frame.rsp);
@@ -180,6 +182,8 @@ void OBOSS_HandOffToInit(struct exec_aux_values* aux)
Core_GetCurrentThread()->context.stackBase = Mm_VirtualMemoryAlloc(ctx, nullptr, 4*1024*1024, OBOS_PROTECTION_USER_PAGE, VMA_FLAGS_GUARD_PAGE, nullptr, nullptr);
Core_GetCurrentThread()->context.stackSize = 4*1024*1024;
+ Core_GetCurrentThread()->stackFree = CoreH_VMAStackFree;
+ Core_GetCurrentThread()->stackFreeUserdata = ctx;
CoreS_SetThreadPageTable(&Core_GetCurrentThread()->context, ctx->pt);
diff --git a/src/oboskrnl/arch/x86_64/gdbstub/connection.c b/src/oboskrnl/arch/x86_64/gdbstub/connection.c
index a3f7d15a..cedc56f9 100644
--- a/src/oboskrnl/arch/x86_64/gdbstub/connection.c
+++ b/src/oboskrnl/arch/x86_64/gdbstub/connection.c
@@ -432,7 +432,8 @@ obos_status SysS_GDBStubStart()
CoreH_ThreadInitialize(&gdb_thread, THREAD_PRIORITY_NORMAL, Core_DefaultThreadAffinity, &ctx);
Core_ProcessAppendThread(OBOS_KernelProcess, &gdb_thread);
CoreH_ThreadReady(&gdb_thread);
- Core_WaitOnObject(WAITABLE_OBJECT(gdb_connected));
-
- return OBOS_STATUS_SUCCESS;
+ obos_status status = Core_WaitOnObject(WAITABLE_OBJECT(gdb_connected));
+ if (CoreS_ForceYieldOnSyscallReturn)
+ CoreS_ForceYieldOnSyscallReturn();
+ return status;
}
\ No newline at end of file
diff --git a/src/oboskrnl/arch/x86_64/gdbstub/gdb_udp_backend.c b/src/oboskrnl/arch/x86_64/gdbstub/gdb_udp_backend.c
index 70ada517..f2a46ec0 100644
--- a/src/oboskrnl/arch/x86_64/gdbstub/gdb_udp_backend.c
+++ b/src/oboskrnl/arch/x86_64/gdbstub/gdb_udp_backend.c
@@ -79,7 +79,9 @@ static obos_status read_sync(dev_desc desc, void* buf, size_t blkCount, size_t b
while (!hnd->curr_rx)
{
- Core_WaitOnObject(WAITABLE_OBJECT(hnd->bound_port->recv_event));
+ obos_status status = Core_WaitOnObject(WAITABLE_OBJECT(hnd->bound_port->recv_event));
+ if (obos_is_error(status))
+ return status;
Core_EventClear(&hnd->bound_port->recv_event);
udp_recv_packet* recv_packet = LIST_GET_HEAD(frame_queue, &hnd->bound_port->packets);
if (!recv_packet)
diff --git a/src/oboskrnl/arch/x86_64/gdbstub/vFile.c b/src/oboskrnl/arch/x86_64/gdbstub/vFile.c
index 44b0907f..e5b4adf2 100644
--- a/src/oboskrnl/arch/x86_64/gdbstub/vFile.c
+++ b/src/oboskrnl/arch/x86_64/gdbstub/vFile.c
@@ -197,8 +197,8 @@ static obos_status common_stat(vnode* vn, struct gdb_stat* out)
out->st_dev = 0;
out->st_ino = vn->inode;
out->st_nlink = vn->refs;
- out->st_uid = vn->owner_uid;
- out->st_gid = vn->group_uid;
+ out->st_uid = vn->uid;
+ out->st_gid = vn->gid;
out->st_rdev = 0;
out->st_size = vn->filesize;
out->st_blksize = vn->blkSize;
diff --git a/src/oboskrnl/arch/x86_64/ioapic.c b/src/oboskrnl/arch/x86_64/ioapic.c
index f0149aaf..4c877898 100644
--- a/src/oboskrnl/arch/x86_64/ioapic.c
+++ b/src/oboskrnl/arch/x86_64/ioapic.c
@@ -32,7 +32,7 @@ size_t Arch_IOAPICCount;
static OBOS_PAGEABLE_FUNCTION OBOS_NO_UBSAN obos_status ParseMADT()
{
// Find the MADT in the ACPI tables.
- ACPIRSDPHeader* rsdp = (ACPIRSDPHeader*)Arch_MapToHHDM(Arch_LdrPlatformInfo->acpi_rsdp_address);
+ ACPIRSDPHeader* rsdp = (ACPIRSDPHeader*)Arch_MapToHHDM(Arch_RSDPBase);
bool tables32 = rsdp->Revision < 2;
ACPISDTHeader* xsdt = tables32 ? (ACPISDTHeader*)(uintptr_t)rsdp->RsdtAddress : (ACPISDTHeader*)rsdp->XsdtAddress;
xsdt = (ACPISDTHeader*)Arch_MapToHHDM((uintptr_t)xsdt);
diff --git a/src/oboskrnl/arch/x86_64/map.c b/src/oboskrnl/arch/x86_64/map.c
index 93ef56d0..c9125ec6 100644
--- a/src/oboskrnl/arch/x86_64/map.c
+++ b/src/oboskrnl/arch/x86_64/map.c
@@ -14,7 +14,7 @@
#include
#include
-
+#include
#include
#include
@@ -29,8 +29,12 @@
#include
#include
+#include
+
#include
+#include
+
#include
#include
@@ -144,8 +148,6 @@ bool Arch_FreePageMapAt(uintptr_t pml4Base, uintptr_t at, uint8_t maxDepth)
return true;
}
-static obos_status invlpg_impl(uintptr_t at);
-
static bool has_xd()
{
static bool ret = false, init = false;
@@ -166,14 +168,11 @@ obos_status Arch_MapPage(uintptr_t cr3, void* at_, uintptr_t phys, uintptr_t fla
phys = Arch_MaskPhysicalAddressFromEntry(phys);
uintptr_t* pm = Arch_AllocatePageMapAt(cr3, at, flags & ~512, 3);
uintptr_t entry = phys | flags;
- bool shouldInvplg = pm[AddressToIndex(at, 0)] != entry;
// for (volatile bool b = !(flags & 1); b; )
// ;
pm[AddressToIndex(at, 0)] = entry;
if (free_pte && ~flags & BIT_TYPE(0, UL))
Arch_FreePageMapAt(cr3, at, 3);
- if (shouldInvplg)
- invlpg_impl(at);
return OBOS_STATUS_SUCCESS;
}
obos_status Arch_MapHugePage(uintptr_t cr3, void* at_, uintptr_t phys, uintptr_t flags, bool free_pte)
@@ -191,36 +190,12 @@ obos_status Arch_MapHugePage(uintptr_t cr3, void* at_, uintptr_t phys, uintptr_t
phys = Arch_MaskPhysicalAddressFromEntry(phys);
uintptr_t* pm = Arch_AllocatePageMapAt(cr3, at, flags & ~512, 2);
uintptr_t entry = phys | flags | ((uintptr_t)1 << 7);
- bool shouldInvplg = (entry != pm[AddressToIndex(at, 1)]);
pm[AddressToIndex(at, 1)] = entry;
if (free_pte && ~flags & BIT_TYPE(0, UL))
Arch_FreePageMapAt(cr3, at, 2);
- if (shouldInvplg)
- invlpg_impl(at);
return OBOS_STATUS_SUCCESS;
}
-static struct {
- spinlock lock;
- uintptr_t addr;
- uintptr_t cr3;
- atomic_size_t nCPUsRan;
- bool active;
- irq* irq;
- cpu_local* sender;
-} invlpg_ipi_packet;
-bool Arch_InvlpgIPI(interrupt_frame* frame)
-{
- OBOS_UNUSED(frame);
- if (!invlpg_ipi_packet.active)
- return false;
- if (getCR3() == invlpg_ipi_packet.cr3)
- invlpg(invlpg_ipi_packet.addr);
- invlpg_ipi_packet.nCPUsRan++;
- if (invlpg_ipi_packet.nCPUsRan >= Core_CpuCount)
- invlpg_ipi_packet.active = false;
- // Arch_LAPICAddress->eoi = 0;
- return true;
-}
+
extern bool Arch_SMPInitialized;
obos_status Arch_UnmapPage(uintptr_t cr3, void* at_, bool free_pte)
{
@@ -242,8 +217,61 @@ obos_status Arch_UnmapPage(uintptr_t cr3, void* at_, bool free_pte)
pt[AddressToIndex(at, (uint8_t)isHugePage)] &= ~BIT(0);
if (free_pte)
Arch_FreePageMapAt(cr3, at, 3 - (uint8_t)isHugePage);
- return invlpg_impl(at);
+ return OBOS_STATUS_SUCCESS;
+}
+
+static irq* invlpg_irq;
+typedef struct tlb_shootdown_packet {
+ uintptr_t base;
+ size_t size;
+ atomic_size_t refcount;
+ LIST_NODE(tlb_shootdown_queue, struct tlb_shootdown_packet) node;
+} tlb_shootdown_packet;
+typedef LIST_HEAD(tlb_shootdown_queue, tlb_shootdown_packet) tlb_shootdown_queue;
+LIST_GENERATE_STATIC(tlb_shootdown_queue, tlb_shootdown_packet, node);
+tlb_shootdown_queue g_tlb_shootdown_queue;
+spinlock g_tlb_shootdown_queue_lock;
+
+static void deref_tlb_shootdown_pckt(tlb_shootdown_packet* pckt)
+{
+ if (!--pckt->refcount)
+ {
+ irql oldIrql = Core_SpinlockAcquire(&g_tlb_shootdown_queue_lock);
+ LIST_REMOVE(tlb_shootdown_queue, &g_tlb_shootdown_queue, pckt);
+ Core_SpinlockRelease(&g_tlb_shootdown_queue_lock, oldIrql);
+ Free(Mm_Allocator, pckt, sizeof(*pckt));
+ }
+}
+
+bool Arch_InvlpgIPI(interrupt_frame* frame)
+{
+ OBOS_UNUSED(frame);
+ if (!LIST_GET_NODE_COUNT(tlb_shootdown_queue, &g_tlb_shootdown_queue))
+ return false;
+ tlb_shootdown_packet* curr = CoreS_GetCPULocalPtr()->arch_specific.curr_pckt;
+ if (!curr)
+ curr = LIST_GET_HEAD(tlb_shootdown_queue, &g_tlb_shootdown_queue);
+ else
+ curr = LIST_GET_NEXT(tlb_shootdown_queue, &g_tlb_shootdown_queue, curr);
+
+ while (curr)
+ {
+ for (uintptr_t addr = curr->base; addr <= (curr->base+curr->size); addr += OBOS_PAGE_SIZE)
+ {
+ OBOS_ENSURE(addr >= curr->base);
+ invlpg(addr);
+ }
+
+ if (curr != LIST_GET_TAIL(tlb_shootdown_queue, &g_tlb_shootdown_queue))
+ deref_tlb_shootdown_pckt(curr);
+ else
+ CoreS_GetCPULocalPtr()->arch_specific.curr_pckt = curr;
+ curr = LIST_GET_NEXT(tlb_shootdown_queue, &g_tlb_shootdown_queue, curr);
+ }
+
+ return true;
}
+
static void invlpg_ipi_bootstrap(struct irq* i, interrupt_frame* frame, void* userdata, irql oldIrql)
{
OBOS_UNUSED(i);
@@ -251,67 +279,68 @@ static void invlpg_ipi_bootstrap(struct irq* i, interrupt_frame* frame, void* us
OBOS_UNUSED(oldIrql);
Arch_InvlpgIPI(frame);
}
-static obos_status invlpg_impl(uintptr_t at)
+
+#define issue_nmi() \
+ Arch_LAPICSendIPI((ipi_lapic_info){.isShorthand=true,.info.shorthand=LAPIC_DESTINATION_SHORTHAND_ALL}, \
+ (ipi_vector_info){.deliveryMode=LAPIC_DELIVERY_MODE_NMI})
+
+
+extern uintptr_t Arch_KernelCR3;
+
+enum { IRQL_INVLPG_IPI=15 };
+
+obos_status MmS_TLBShootdown(page_table pt, uintptr_t base, size_t size)
{
- invlpg(at);
-#ifndef OBOS_UP
- if (!Arch_SMPInitialized || Core_CpuCount == 1)
- return OBOS_STATUS_SUCCESS;
- enum { IRQL_INVLPG_IPI=15 };
- if (!invlpg_ipi_packet.irq && Core_IrqInterfaceInitialized())
+ if (Core_CpuCount == 1 || !Arch_SMPInitialized)
{
- static irq irq;
- invlpg_ipi_packet.irq = &irq;
- Core_IrqObjectInitializeIRQL(&irq, IRQL_INVLPG_IPI, false, true);
- irq.handler = invlpg_ipi_bootstrap;
- irq.handlerUserdata = nullptr;
+ for (uintptr_t addr = base; addr < (base + size); addr += OBOS_PAGE_SIZE)
+ invlpg(addr);
+ return OBOS_STATUS_SUCCESS;
}
- extern bool Arch_HaltCPUs;
- if (Arch_LAPICAddress->interruptRequest224_255 & (1<<16))
+
+#if OBOS_UP
+ return OBOS_STATUS_SUCCESS;
+#endif
+
+ if (pt != Arch_KernelCR3)
+ goto ipi;
+
+ // Can this allocation cause problems?
+ // i sure do hope not...
+ tlb_shootdown_packet* pckt = ZeroAllocate(Mm_Allocator, 1, sizeof(tlb_shootdown_packet), nullptr);
+ pckt->base = base;
+ pckt->size = size;
+ pckt->refcount = Core_CpuCount;
+ irql oldIrql = Core_SpinlockAcquire(&g_tlb_shootdown_queue_lock);
+ LIST_APPEND(tlb_shootdown_queue, &g_tlb_shootdown_queue, pckt);
+ Core_SpinlockRelease(&g_tlb_shootdown_queue_lock, oldIrql);
+
+ ipi:
+ // Issue the IPI.
+
+ if (Core_IrqInterfaceInitialized())
{
- irql oldIrql = Core_GetIrql();
- if (oldIrql >= IRQL_INVLPG_IPI)
+ static ipi_vector_info vec = {};
+ static ipi_lapic_info dest = {.isShorthand=true,.info.shorthand=LAPIC_DESTINATION_SHORTHAND_ALL};
+ if (!invlpg_irq)
{
- Core_LowerIrql(IRQL_DISPATCH);
- irql unused = Core_RaiseIrql(oldIrql);
- OBOS_UNUSED(unused);
+ static irq irq;
+ invlpg_irq = &irq;
+ Core_IrqObjectInitializeIRQL(&irq, IRQL_INVLPG_IPI, false, true);
+ irq.handler = invlpg_ipi_bootstrap;
+ irq.handlerUserdata = nullptr;
+
+ vec.deliveryMode = LAPIC_DELIVERY_MODE_FIXED;
+ vec.info.vector = irq.vector->id + 0x20;
}
+ Arch_LAPICSendIPI(dest, vec);
}
- size_t spin = 0;
- while (invlpg_ipi_packet.active && ++spin <= 10000)
- pause();
- Arch_HaltCPUs = false;
- irql oldIrql = Core_SpinlockAcquireExplicit(&invlpg_ipi_packet.lock, IRQL_MASKED, false);
- ipi_lapic_info lapic = {
- .isShorthand=true,
- .info.shorthand = LAPIC_DESTINATION_SHORTHAND_ALL_BUT_SELF
- };
- ipi_vector_info vector = {};
- if (invlpg_ipi_packet.irq)
- {
- vector.deliveryMode = LAPIC_DELIVERY_MODE_FIXED;
- vector.info.vector = invlpg_ipi_packet.irq->vector->id+0x20;
- }
- else
- {
- vector.deliveryMode = LAPIC_DELIVERY_MODE_NMI;
- vector.info.vector = 0;
- }
- invlpg_ipi_packet.active = true;
- invlpg_ipi_packet.addr = at;
- invlpg_ipi_packet.cr3 = getCR3();
- invlpg_ipi_packet.nCPUsRan = 1;
- invlpg_ipi_packet.sender = CoreS_GetCPULocalPtr();
- obos_status status = Arch_LAPICSendIPI(lapic, vector);
- OBOS_ASSERT(obos_is_success(status));
- OBOS_UNUSED(status);
- // This can be done async.
- // while (invlpg_ipi_packet.nCPUsRan != Core_CpuCount)
- // pause();
- Core_SpinlockRelease(&invlpg_ipi_packet.lock, oldIrql);
-#endif
+ else if (pt != Arch_KernelCR3)
+ issue_nmi();
+
return OBOS_STATUS_SUCCESS;
}
+
obos_status OBOSS_MapPage_RW_XD(void* at_, uintptr_t phys)
{
return Arch_MapPage(getCR3(), at_, phys, 0x8000000000000003, false);
@@ -343,24 +372,23 @@ obos_status OBOSS_GetPagePhysicalAddress(void* at_, uintptr_t* oPhys)
static basicmm_region kernel_region;
static basicmm_region hhdm_region;
-static void FreePageTables(uintptr_t* pm, uint8_t level, uint32_t beginIndex, uint32_t* indices)
+static void FreePageTables(uintptr_t* pm, uint8_t level, uint32_t beginIndex, bool user, uint32_t* indices)
{
if (!pm)
return;
pm = (uintptr_t*)MmS_MapVirtFromPhys((uintptr_t)pm);
- for (indices[level] = beginIndex; indices[level] < 512; indices[level]++)
+ for (indices[level] = beginIndex; indices[level] < (user ? 256 : 512); indices[level]++)
{
if (!pm[indices[level]])
continue;
if (pm[indices[level]] & ((uintptr_t)1<<7) || level == 0)
continue;
- FreePageTables((uintptr_t*)Arch_MaskPhysicalAddressFromEntry(pm[indices[level]]), level - 1, 0, indices);
+ FreePageTables((uintptr_t*)Arch_MaskPhysicalAddressFromEntry(pm[indices[level]]), level - 1, 0, false, indices);
Mm_FreePhysicalPages(Arch_MaskPhysicalAddressFromEntry(pm[indices[level]]), 1);
}
}
uintptr_t MmS_KernelBaseAddress;
uintptr_t MmS_KernelEndAddress;
-extern uintptr_t Arch_KernelCR3;
obos_status Arch_InitializeKernelPageTable()
{
obos_status status = OBOS_STATUS_SUCCESS;
@@ -373,6 +401,7 @@ obos_status Arch_InitializeKernelPageTable()
Elf64_Ehdr* ehdr = (Elf64_Ehdr*)Arch_KernelBinary->address;
Elf64_Phdr* phdrs = (Elf64_Phdr*)(Arch_KernelBinary->address + ehdr->e_phoff);
size_t i = 0;
+ uintptr_t kernel_limit = 0;
for (; i < ehdr->e_phnum; i++)
{
Elf64_Phdr* phdr = phdrs + i;
@@ -386,8 +415,10 @@ obos_status Arch_InitializeKernelPageTable()
if (phdr->p_flags & PF_W)
flags |= 2;
uintptr_t base = phdr->p_vaddr & ~0xfff;
+#if !OBOS_USE_LIMINE
if (base < Arch_KernelInfo->virtual_base)
OBOS_Panic(OBOS_PANIC_FATAL_ERROR, "Fatal error. Bootloader made a whoopsie! (line %d in file %s). Expression: base < Arch_KernelInfo->virtual_base.\n", __LINE__, __FILE__);
+#endif
uintptr_t limit = phdr->p_vaddr + phdr->p_memsz;
if (limit & 0xfff)
limit = (limit + 0xfff) & ~0xfff;
@@ -397,6 +428,7 @@ obos_status Arch_InitializeKernelPageTable()
OBOS_ASSERT(phys);
Arch_MapPage(newCR3, (void*)virt, phys, flags, false);
}
+ kernel_limit = kernel_limit > limit ? kernel_limit : limit;
}
OBOS_Debug("%s: Mapping HHDM.\n", __func__);
for (uintptr_t off = 0; off < Mm_PhysicalMemoryBoundaries; off += 0x200000)
@@ -404,10 +436,18 @@ obos_status Arch_InitializeKernelPageTable()
asm volatile("mov %0, %%cr3;" : :"r"(newCR3));
// Reclaim old page tables.
uint32_t indices[4] = { 0,0,0,0 };
- FreePageTables((uintptr_t*)oldCR3, 3, AddressToIndex(0xffff800000000000, 3), indices);
+ FreePageTables((uintptr_t*)oldCR3, 3, AddressToIndex(0xffff800000000000, 3), false, indices);
Mm_FreePhysicalPages((uintptr_t)oldCR3, 1);
+#if OBOS_USE_LIMINE
+ OBOSH_BasicMMAddRegion(
+ &kernel_region,
+ (void*)Arch_LimineKernelAddressRequest.response->virtual_base,
+ kernel_limit - Arch_LimineKernelAddressRequest.response->virtual_base);
+ OBOSH_BasicMMAddRegion(&hhdm_region, (void*)Arch_LimineHHDMRequest.response->offset, Mm_PhysicalMemoryBoundaries);
+#else
OBOSH_BasicMMAddRegion(&kernel_region, (void*)Arch_KernelInfo->virtual_base, Arch_KernelInfo->size);
OBOSH_BasicMMAddRegion(&hhdm_region, (void*)Arch_LdrPlatformInfo->higher_half_base, Mm_PhysicalMemoryBoundaries);
+#endif
Arch_KernelCR3 = newCR3;
return OBOS_STATUS_SUCCESS;
}
@@ -514,7 +554,13 @@ static void map_range(uintptr_t cached_root, uintptr_t base, uintptr_t top, uint
top &= ~0xfff;
for (uintptr_t addr = base; addr < top; addr += 0x1000)
{
- uintptr_t phys = Arch_MaskPhysicalAddressFromEntry(Arch_GetPML1Entry(Arch_KernelCR3, addr));
+ uintptr_t phys = 0;
+ uintptr_t pml2ent = Arch_GetPML2Entry(Arch_KernelCR3, addr);
+ if (pml2ent & BIT_TYPE(7, UL))
+ phys = Arch_MaskPhysicalAddressFromEntry(pml2ent) + (addr & (OBOS_HUGE_PAGE_SIZE-1));
+ else
+ phys = Arch_MaskPhysicalAddressFromEntry(Arch_GetPML1Entry(Arch_KernelCR3, addr));
+ OBOS_ENSURE(phys != 0);
Arch_MapPage(cached_root, (void*)addr, phys, flags, false);
}
}
@@ -554,7 +600,8 @@ page_table MmS_AllocatePageTable()
}
void MmS_FreePageTable(page_table pt)
{
- // uint32_t indices[4] = {};
- // FreePageTables(MmS_MapVirtFromPhys(pt), 3, 0, indices);
+ OBOS_ENSURE(pt != Arch_KernelCR3);
+ uint32_t indices[4] = {};
+ FreePageTables((uintptr_t*)pt, 3, 0, true, indices);
Mm_FreePhysicalPages(pt, 1);
}
diff --git a/src/oboskrnl/arch/x86_64/pmm.c b/src/oboskrnl/arch/x86_64/pmm.c
index 43108692..5654d4e1 100644
--- a/src/oboskrnl/arch/x86_64/pmm.c
+++ b/src/oboskrnl/arch/x86_64/pmm.c
@@ -11,6 +11,7 @@
#include
+#if !OBOS_USE_LIMINE
#include
extern struct ultra_memory_map_attribute* Arch_MemoryMap;
@@ -34,6 +35,32 @@ obos_pmem_map_entry* MmS_GetNextPMemMapEntry(obos_pmem_map_entry* current, uintp
#define MAP_TO_HHDM(addr, type) ((type*)(Arch_LdrPlatformInfo->higher_half_base + (uintptr_t)(addr)))
#define UNMAP_FROM_HHDM(addr) ((uintptr_t)(addr) - Arch_LdrPlatformInfo->higher_half_base)
+#else
+
+#include
+
+obos_pmem_map_entry* MmS_GetFirstPMemMapEntry(uintptr_t* index)
+{
+ *index = 0;
+ return Arch_LimineMemmapRequest.response->entries[0];
+}
+// returns nullptr at the end of the list.
+obos_pmem_map_entry* MmS_GetNextPMemMapEntry(obos_pmem_map_entry* current, uintptr_t* index)
+{
+ OBOS_UNUSED(current);
+ size_t nEntries = Arch_LimineMemmapRequest.response->entry_count;
+ if (!nEntries)
+ OBOS_Panic(OBOS_PANIC_FATAL_ERROR, "No memory map entries.\n");
+ if ((*index) >= nEntries)
+ return nullptr;
+ return Arch_LimineMemmapRequest.response->entries[++(*index)];
+}
+
+#define MAP_TO_HHDM(addr, type) ((type*)(Arch_LimineHHDMRequest.response->offset + (uintptr_t)(addr)))
+#define UNMAP_FROM_HHDM(addr) ((uintptr_t)(addr) - Arch_LimineHHDMRequest.response->offset)
+
+#endif
+
OBOS_NO_KASAN OBOS_NO_UBSAN __attribute__((no_instrument_function)) void* Arch_MapToHHDM(uintptr_t phys)
{
return MAP_TO_HHDM(phys, void);
diff --git a/src/oboskrnl/arch/x86_64/pmm.h b/src/oboskrnl/arch/x86_64/pmm.h
index cb767ca4..cec0032f 100644
--- a/src/oboskrnl/arch/x86_64/pmm.h
+++ b/src/oboskrnl/arch/x86_64/pmm.h
@@ -9,6 +9,8 @@
#include
#include
+#if !OBOS_USE_LIMINE
+
#include
typedef struct ultra_memory_map_entry obos_pmem_map_entry;
@@ -19,5 +21,19 @@ typedef struct ultra_memory_map_entry obos_pmem_map_entry;
#define PHYSICAL_MEMORY_TYPE_RECLAIMABLE ULTRA_MEMORY_TYPE_RECLAIMABLE
#define PHYSICAL_MEMORY_TYPE_LOADER_RECLAIMABLE ULTRA_MEMORY_TYPE_LOADER_RECLAIMABLE
+#else
+
+#include
+
+typedef struct limine_memmap_entry obos_pmem_map_entry;
+#define pmem_map_base base
+#define pmem_map_size length
+#define pmem_map_type type
+#define PHYSICAL_MEMORY_TYPE_USABLE LIMINE_MEMMAP_USABLE
+#define PHYSICAL_MEMORY_TYPE_RECLAIMABLE LIMINE_MEMMAP_ACPI_RECLAIMABLE
+#define PHYSICAL_MEMORY_TYPE_LOADER_RECLAIMABLE LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE
+
+#endif
+
void* Arch_MapToHHDM(uintptr_t phys);
uintptr_t Arch_UnmapFromHHDM(void* virt);
\ No newline at end of file
diff --git a/src/oboskrnl/arch/x86_64/smp.c b/src/oboskrnl/arch/x86_64/smp.c
index ff71a8ca..f51f16fa 100644
--- a/src/oboskrnl/arch/x86_64/smp.c
+++ b/src/oboskrnl/arch/x86_64/smp.c
@@ -49,7 +49,7 @@ obos_status Arch_MapPage(uintptr_t cr3, void* at_, uintptr_t phys, uintptr_t fla
static OBOS_NO_UBSAN void ParseMADT()
{
// Find the MADT in the ACPI tables.
- ACPIRSDPHeader* rsdp = (ACPIRSDPHeader*)Arch_MapToHHDM(Arch_LdrPlatformInfo->acpi_rsdp_address);
+ ACPIRSDPHeader* rsdp = (ACPIRSDPHeader*)Arch_MapToHHDM(Arch_RSDPBase);
bool tables32 = rsdp->Revision < 2;
ACPISDTHeader* xsdt = tables32 ? (ACPISDTHeader*)(uintptr_t)rsdp->RsdtAddress : (ACPISDTHeader*)rsdp->XsdtAddress;
xsdt = (ACPISDTHeader*)Arch_MapToHHDM((uintptr_t)xsdt);
@@ -157,6 +157,8 @@ void __attribute__((no_stack_protector)) Arch_APEntry(cpu_local* info)
thread* idleThread = CoreH_ThreadAllocate(nullptr);
CoreH_ThreadInitialize(idleThread, THREAD_PRIORITY_IDLE, ((thread_affinity)1<id), &ctx);
CoreH_ThreadReady(idleThread);
+ info->nReadyThreads--;
+ Core_ReadyThreadCount--;
Core_ProcessAppendThread(OBOS_KernelProcess, idleThread);
info->idleThread = idleThread;
Arch_LAPICInitialize(false);
@@ -185,14 +187,17 @@ void Arch_SMPStartup()
Arch_SaveMTRRs();
Arch_RawRegisterInterrupt(0x2, (uintptr_t)nmiHandler);
ParseMADT();
+ bool up = false;
#ifdef OBOS_UP
OBOS_Log("Uniprocessor-build of OBOS. No other cores will be initialized.\n");
- s_nLAPICIDs = 1;
+ // s_nLAPICIDs = 1;
+ up = true;
#else
if (OBOS_GetOPTF("no-smp"))
{
OBOS_Log("Running OBOS as Uniprocessor. No other cores will be initialized.\n");
- s_nLAPICIDs = 1;
+ up = true;
+ // s_nLAPICIDs = 1;
}
#endif
// if (s_nLAPICIDs == 1)
@@ -206,7 +211,7 @@ void Arch_SMPStartup()
Arch_MapPage(getCR3(), (void*)0x1000, 0x1000, 0x3, false);
Arch_SMPTrampolineCR3 = getCR3();
Core_CpuInfo = cpu_info;
- Core_CpuCount = s_nLAPICIDs;
+ Core_CpuCount = up ? 1 : s_nLAPICIDs;
// irql oldIrql = Core_RaiseIrql(0xf);
for (size_t i = 0; i < s_nLAPICIDs; i++)
{
@@ -353,3 +358,17 @@ void CoreS_SetKernelStack(void* stck)
if (!stck) return;
CoreS_GetCPULocalPtr()->arch_specific.tss.rsp0 = (uintptr_t)stck+0x10000;
}
+
+void CoreS_ForceYieldOnSyscallReturn()
+{
+ ipi_vector_info vector = {
+ .deliveryMode = LAPIC_DELIVERY_MODE_FIXED,
+ .info.vector = Core_SchedulerIRQ->vector->id + 0x20
+ };
+ asm volatile ("cli");
+ static ipi_lapic_info self = {
+ .isShorthand=true,
+ .info.shorthand=LAPIC_DESTINATION_SHORTHAND_SELF
+ };
+ Arch_LAPICSendIPI(self, vector);
+}
\ No newline at end of file
diff --git a/src/oboskrnl/arch/x86_64/ssignal.c b/src/oboskrnl/arch/x86_64/ssignal.c
index d759453c..6fbcd6e9 100644
--- a/src/oboskrnl/arch/x86_64/ssignal.c
+++ b/src/oboskrnl/arch/x86_64/ssignal.c
@@ -60,7 +60,7 @@ void OBOSS_RunSignalImpl(int sigval, interrupt_frame* frame)
{
// if (!(frame->cs & 0x3))
// return;
- sigaction* sig = &Core_GetCurrentThread()->signal_info->signals[sigval-1];
+ sigaction* sig = &Core_GetCurrentThread()->proc->signal_handlers[sigval-1];
if (sig->un.handler == SIG_IGN)
return;
ucontext_t ctx = { .frame=*frame,.gs_base=rdmsr(!(frame->cs & 0x3) ? GS_BASE : KERNEL_GS_BASE),.fs_base=rdmsr(FS_BASE),.cr3=frame->cr3 };
diff --git a/src/oboskrnl/arch/x86_64/syscall.asm b/src/oboskrnl/arch/x86_64/syscall.asm
index d125c255..6b1e0e8a 100644
--- a/src/oboskrnl/arch/x86_64/syscall.asm
+++ b/src/oboskrnl/arch/x86_64/syscall.asm
@@ -119,6 +119,7 @@ Arch_SyscallTrapHandler:
pop rcx
mov cr3, r9
+ cli
mov rsp, r10
swapgs
o64 sysret
diff --git a/src/oboskrnl/arch/x86_64/syscall.c b/src/oboskrnl/arch/x86_64/syscall.c
index b4bc586d..a85fa143 100644
--- a/src/oboskrnl/arch/x86_64/syscall.c
+++ b/src/oboskrnl/arch/x86_64/syscall.c
@@ -245,6 +245,14 @@ const char* syscall_to_string[] = {
"Sys_UMask",
"Sys_RenameAt",
"Sys_UTimeNSAt",
+ "Sys_ThreadGetStack",
+ "Sys_SetRESUid",
+ "Sys_SetRESGid",
+ "Sys_GetRESUid",
+ "Sys_GetRESGid",
+ "Sys_SigPending",
+ "Sys_SetGroups",
+ "Sys_GetGroups",
};
const char* status_to_string[] = {
diff --git a/src/oboskrnl/arch/x86_64/timer.c b/src/oboskrnl/arch/x86_64/timer.c
index c29235ff..5e9be3b4 100644
--- a/src/oboskrnl/arch/x86_64/timer.c
+++ b/src/oboskrnl/arch/x86_64/timer.c
@@ -80,7 +80,7 @@ static OBOS_PAGEABLE_FUNCTION OBOS_NO_UBSAN void InitializeHPET()
{
static basicmm_region hpet_region;
hpet_region.mmioRange = true;
- ACPIRSDPHeader* rsdp = (ACPIRSDPHeader*)Arch_MapToHHDM(Arch_LdrPlatformInfo->acpi_rsdp_address);
+ ACPIRSDPHeader* rsdp = (ACPIRSDPHeader*)Arch_MapToHHDM(Arch_RSDPBase);
bool tables32 = rsdp->Revision < 2;
ACPISDTHeader* xsdt = tables32 ? (ACPISDTHeader*)(uintptr_t)rsdp->RsdtAddress : (ACPISDTHeader*)rsdp->XsdtAddress;
xsdt = (ACPISDTHeader*)Arch_MapToHHDM((uintptr_t)xsdt);
diff --git a/src/oboskrnl/arch/x86_64/wake.c b/src/oboskrnl/arch/x86_64/wake.c
index d38e55fa..a881fac0 100644
--- a/src/oboskrnl/arch/x86_64/wake.c
+++ b/src/oboskrnl/arch/x86_64/wake.c
@@ -41,6 +41,10 @@
#include
+#if OBOS_USE_LIMINE
+# include
+#endif
+
struct {
HPET_Timer timer0;
uint64_t mainCounterValue;
@@ -111,6 +115,23 @@ void OBOSS_SuspendSavePlatformState()
index = 0;
size_t nvs_index = 0;
+# if OBOS_USE_LIMINE
+ for (obos_pmem_map_entry* entry = MmS_GetFirstPMemMapEntry(&index); entry; )
+ {
+ if (entry->type == LIMINE_MEMMAP_ACPI_NVS)
+ {
+ saved_nvs[nvs_index].region_address = Arch_MapToHHDM(entry->base);
+ saved_nvs[nvs_index].size = entry->length;
+ saved_nvs[nvs_index].saved_region = Allocate(OBOS_NonPagedPoolAllocator,
+ saved_nvs[nvs_index].size,
+ nullptr);
+ memcpy(saved_nvs[nvs_index].saved_region, saved_nvs[nvs_index].region_address, saved_nvs[nvs_index].size);
+ nvs_index++;
+ }
+
+ entry = MmS_GetNextPMemMapEntry(entry, &index);
+ }
+# else
for (obos_pmem_map_entry* entry = MmS_GetFirstPMemMapEntry(&index); entry; )
{
if (entry->type == ULTRA_MEMORY_TYPE_NVS)
@@ -118,14 +139,15 @@ void OBOSS_SuspendSavePlatformState()
saved_nvs[nvs_index].region_address = Arch_MapToHHDM(entry->physical_address);
saved_nvs[nvs_index].size = entry->size;
saved_nvs[nvs_index].saved_region = Allocate(OBOS_NonPagedPoolAllocator,
- saved_nvs[nvs_index].size,
- nullptr);
+ saved_nvs[nvs_index].size,
+ nullptr);
memcpy(saved_nvs[nvs_index].saved_region, saved_nvs[nvs_index].region_address, saved_nvs[nvs_index].size);
nvs_index++;
}
entry = MmS_GetNextPMemMapEntry(entry, &index);
}
+# endif
}
#endif
}
diff --git a/src/oboskrnl/driver_interface/drv_sys.c b/src/oboskrnl/driver_interface/drv_sys.c
index 06c41145..2d99ee15 100644
--- a/src/oboskrnl/driver_interface/drv_sys.c
+++ b/src/oboskrnl/driver_interface/drv_sys.c
@@ -24,9 +24,10 @@
handle Sys_LoadDriver(const void* file, size_t szFile, obos_status* ustatus)
{
- if (Core_GetCurrentThread()->proc->currentUID != ROOT_UID)
+ if (Core_GetCurrentThread()->proc->euid != ROOT_UID)
{
- if (ustatus) *ustatus = OBOS_STATUS_ACCESS_DENIED;
+ obos_status status = OBOS_STATUS_ACCESS_DENIED;
+ if (ustatus) memcpy_k_to_usr(ustatus, &status, sizeof(obos_status));
return HANDLE_INVALID;
}
@@ -62,7 +63,7 @@ handle Sys_LoadDriver(const void* file, size_t szFile, obos_status* ustatus)
}
#define perm_check_impl(ret) do {\
- if (Core_GetCurrentThread()->proc->currentUID != ROOT_UID)\
+ if (Core_GetCurrentThread()->proc->euid != ROOT_UID)\
return (ret);\
} while(0)
#define perm_check() perm_check_impl(OBOS_STATUS_ACCESS_DENIED)
diff --git a/src/oboskrnl/driver_interface/loader.c b/src/oboskrnl/driver_interface/loader.c
index 96e23551..957cfc65 100644
--- a/src/oboskrnl/driver_interface/loader.c
+++ b/src/oboskrnl/driver_interface/loader.c
@@ -308,6 +308,7 @@ OBOS_NO_UBSAN driver_id *Drv_LoadDriver(const void* file_, size_t szFile, obos_s
OBOS_Log("%s: Loaded driver '%s' at 0x%p.\n", __func__, driver->header.driverName, driver->base);
else
OBOS_Log("%s: Loaded driver at 0x%p.\n", __func__, driver->header.driverName, driver->base);
+ driver->refCnt++;
return driver;
}
diff --git a/src/oboskrnl/driver_interface/pci.c b/src/oboskrnl/driver_interface/pci.c
index 8e6a86cc..22407ba1 100644
--- a/src/oboskrnl/driver_interface/pci.c
+++ b/src/oboskrnl/driver_interface/pci.c
@@ -322,6 +322,7 @@ static void initialize_irq_resources(pci_device* dev)
pci_resource* resource = ZeroAllocate(OBOS_KernelAllocator, 1, sizeof(pci_resource), nullptr);
resource->type = PCI_RESOURCE_IRQ;
+ resource->owner = dev;
resource->irq = ZeroAllocate(OBOS_KernelAllocator, 1, sizeof(pci_irq_handle), nullptr);
resource->owner = dev;
@@ -341,6 +342,7 @@ static void initialize_cmd_register_resource(pci_device* dev)
resource->cmd_register = cmd_register & 0xffff;
LIST_APPEND(pci_resource_list, &dev->resources, resource);
+ resource->owner = dev;
dev->resource_cmd_register = resource;
}
diff --git a/src/oboskrnl/driver_interface/pci_irq.c b/src/oboskrnl/driver_interface/pci_irq.c
index 4ce507bd..dd9b367d 100644
--- a/src/oboskrnl/driver_interface/pci_irq.c
+++ b/src/oboskrnl/driver_interface/pci_irq.c
@@ -40,6 +40,7 @@ static void* map_registers(uintptr_t phys, size_t size, bool uc)
page.prot.uc = uc;
MmS_SetPageMapping(Mm_KernelContext.pt, &page, phys + offset, false);
}
+ MmS_TLBShootdown(Mm_KernelContext.pt, (uintptr_t)virt, size);
return virt+phys_page_offset;
}
static void pci_irq_move_callback(struct irq* i, struct irq_vector* from, struct irq_vector* to, void* userdata)
diff --git a/src/oboskrnl/elf/load.c b/src/oboskrnl/elf/load.c
index b859217d..ebc69f37 100644
--- a/src/oboskrnl/elf/load.c
+++ b/src/oboskrnl/elf/load.c
@@ -131,7 +131,7 @@ obos_status OBOS_LoadELF(context* ctx, const void* file, size_t szFile, elf_info
uintptr_t real_limit = phdrs[i].p_vaddr+phdrs[i].p_memsz;
if (real_limit % OBOS_PAGE_SIZE)
real_limit += (OBOS_PAGE_SIZE-(real_limit%OBOS_PAGE_SIZE));
- // printf("ELF: Allocating 0x%p bytes (memsz=0x%p, real_base=0x%p, real_limit=0x%p, vaddr=0x%p)", real_limit-real_base, phdrs[i].p_memsz, real_base, real_limit, phdrs[i].p_vaddr);
+ // printf("ELF: Allocating 0x%p bytes (memsz=0x%p, real_base=0x%p, real_limit=0x%p, vaddr=0x%p)\n", real_limit-real_base, phdrs[i].p_memsz, real_base, real_limit, phdrs[i].p_vaddr);
ubase = Mm_VirtualMemoryAlloc(ctx,
(void*)real_base,
real_limit-real_base,
@@ -159,6 +159,8 @@ obos_status OBOS_LoadELF(context* ctx, const void* file, size_t szFile, elf_info
real_limit += base;
}
+ OBOS_ENSURE(phdrs[i].p_filesz <= (real_limit - real_base));
+
kbase = Mm_MapViewOfUserMemory(ctx,
(void*)real_base,
nullptr,
diff --git a/src/oboskrnl/execve.c b/src/oboskrnl/execve.c
index c09fec4a..12c2f6d6 100644
--- a/src/oboskrnl/execve.c
+++ b/src/oboskrnl/execve.c
@@ -141,11 +141,11 @@ obos_status Sys_ExecVE(const char* upath, char* const* argv, char* const* envp)
return status;
Core_GetCurrentThread()->proc->exec_file = VfsH_DirentPath(VfsH_DirentLookup(path), nullptr);
size_t szBuf = file.vn->filesize;
- void* kbuf = Mm_VirtualMemoryAlloc(&Mm_KernelContext, nullptr, szBuf, 0, VMA_FLAGS_PRIVATE|VMA_FLAGS_PREFAULT, &file, nullptr);
+ void* kbuf = Mm_VirtualMemoryAlloc(&Mm_KernelContext, nullptr, szBuf, OBOS_PROTECTION_READ_ONLY, 0, &file, nullptr);
bool set_uid = file.vn->perm.set_uid;
bool set_gid = file.vn->perm.set_gid;
- uid target_uid = set_uid ? file.vn->owner_uid : Core_GetCurrentThread()->proc->currentUID;
- gid target_gid = set_gid ? file.vn->group_uid : Core_GetCurrentThread()->proc->currentGID;
+ uid target_euid = set_uid ? file.vn->uid : Core_GetCurrentThread()->proc->euid;
+ gid target_egid = set_gid ? file.vn->gid : Core_GetCurrentThread()->proc->egid;
Vfs_FdClose(&file);
char** kargv = allocate_user_vector_as_kernel(ctx, argv, &argc, &status);
@@ -309,8 +309,10 @@ obos_status Sys_ExecVE(const char* upath, char* const* argv, char* const* envp)
aux.at_secure = set_gid || set_uid;
- Core_GetCurrentThread()->proc->currentUID = target_uid;
- Core_GetCurrentThread()->proc->currentGID = target_gid;
+ Core_GetCurrentThread()->proc->euid = target_euid;
+ Core_GetCurrentThread()->proc->egid = target_egid;
+ Core_GetCurrentThread()->proc->sgid = target_euid;
+ Core_GetCurrentThread()->proc->sgid = target_egid;
OBOSS_HandControlTo(ctx, &aux);
}
diff --git a/src/oboskrnl/gpt.c b/src/oboskrnl/gpt.c
index e1ff87e2..d9f16d5f 100644
--- a/src/oboskrnl/gpt.c
+++ b/src/oboskrnl/gpt.c
@@ -35,7 +35,8 @@ obos_status OBOS_IdentifyGPTPartitions(fd *desc, partition *partition_list, size
size_t filesize = desc->vn->filesize;
if (filesize < sizeof(mbr_t))
return OBOS_STATUS_EOF;
- mbr_t *protective_mbr = ZeroAllocate(OBOS_KernelAllocator, 1, sizeof(mbr_t), nullptr);
+ OBOS_ASSERT(OBOS_PAGE_SIZE > sizeof(mbr_t));
+ mbr_t *protective_mbr = ZeroAllocate(OBOS_KernelAllocator, 1, OBOS_PAGE_SIZE, nullptr);
obos_status status =
Vfs_FdRead(desc, protective_mbr, sizeof(*protective_mbr), &nRead);
if (obos_is_error(status))
@@ -44,7 +45,7 @@ obos_status OBOS_IdentifyGPTPartitions(fd *desc, partition *partition_list, size
return OBOS_STATUS_INTERNAL_ERROR;
if (protective_mbr->signature != MBR_BOOT_SIGNATURE)
return OBOS_STATUS_INVALID_FILE;
- Free(OBOS_KernelAllocator, protective_mbr, sizeof(*protective_mbr));
+ Free(OBOS_KernelAllocator, protective_mbr, OBOS_PAGE_SIZE);
size_t blkSize = Vfs_FdGetBlkSz(desc);
OBOS_ASSERT(__builtin_popcount(blkSize) == 1);
diff --git a/src/oboskrnl/init_proc.c b/src/oboskrnl/init_proc.c
index 2ec81d50..b2d1db5a 100644
--- a/src/oboskrnl/init_proc.c
+++ b/src/oboskrnl/init_proc.c
@@ -61,7 +61,7 @@ void OBOS_LoadInit()
if (obos_is_error(status))
OBOS_Panic(OBOS_PANIC_FATAL_ERROR, "Could not open %s. Status: %d\n", init_path, status);
- context* new_ctx = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(context), nullptr);
+ context* new_ctx = ZeroAllocate(Mm_Allocator, 1, sizeof(context), nullptr);
Mm_ConstructContext(new_ctx);
process* new = Core_ProcessAllocate(nullptr);
new->ctx = new_ctx;
diff --git a/src/oboskrnl/irq/timer.c b/src/oboskrnl/irq/timer.c
index 90ce66eb..ae70bf03 100644
--- a/src/oboskrnl/irq/timer.c
+++ b/src/oboskrnl/irq/timer.c
@@ -4,6 +4,7 @@
* Copyright (c) 2024 Omar Berrow
*/
+#include "locks/event.h"
#include
#include
#include
@@ -240,3 +241,18 @@ OBOS_EXPORT uint64_t CoreH_TickToNS(timer_tick tick, bool native_tick)
return tick * cached_rate;
}
}
+
+static void tm_evnt_hnd(void* udata)
+{
+ event* evnt = udata;
+ Core_EventSet(evnt, false);
+}
+
+void CoreH_MakeTimerEvent(timer** otm, uint64_t us, event* evnt, bool recurring)
+{
+ OBOS_ASSERT(otm);
+ *otm = Core_TimerObjectAllocate(nullptr);
+ (*otm)->handler = tm_evnt_hnd;
+ (*otm)->userdata = (void*)evnt;
+ Core_TimerObjectInitialize(*otm, recurring ? TIMER_MODE_INTERVAL : TIMER_MODE_DEADLINE, us);
+}
\ No newline at end of file
diff --git a/src/oboskrnl/irq/timer.h b/src/oboskrnl/irq/timer.h
index 8f54a8af..e1d8dd54 100644
--- a/src/oboskrnl/irq/timer.h
+++ b/src/oboskrnl/irq/timer.h
@@ -13,6 +13,8 @@
#include
#include
+#include
+
typedef uint64_t timer_tick;
typedef uint64_t timer_frequency;
@@ -111,6 +113,15 @@ OBOS_EXPORT timer_tick CoreH_TimeFrameToTick(uint64_t us);
/// The tick count in nanoseconds..
OBOS_EXPORT uint64_t CoreH_TickToNS(timer_tick tick, bool native_tick);
+///
+/// Starts a timer for 'us' microseconds, setting evnt when it is triggered.
+/// Useful for timeouts.
+///
+/// [out] The timer object used.
+/// The time period to start the timer for
+/// The event to set when the timer finishes
+/// Whether the timer should be an interval or deadline timer
+OBOS_EXPORT void CoreH_MakeTimerEvent(timer** otm, uint64_t us, event* evnt, bool recurring);
uint64_t CoreS_TimerTickToNS(timer_tick tp);
@@ -122,4 +133,4 @@ uint64_t CoreS_TimerTickToNS(timer_tick tp);
OBOS_WEAK obos_status CoreS_InitializeTimer(irq_handler handler);
#ifdef OBOS_TIMER_IS_DEADLINE
obos_status CoreS_ResetTimer();
-#endif
+#endif
\ No newline at end of file
diff --git a/src/oboskrnl/locks/pushlock.c b/src/oboskrnl/locks/pushlock.c
index cd11dca2..9ae44e0e 100644
--- a/src/oboskrnl/locks/pushlock.c
+++ b/src/oboskrnl/locks/pushlock.c
@@ -33,7 +33,10 @@ obos_status Core_PushlockAcquire(pushlock* lock, bool reader /* false: writer, t
// Hopefully this is right.
// maybe a possible race condition.
try_again:
- Core_WaitOnObject(&lock->hdr);
+ (void)0;
+ obos_status status = Core_WaitOnObject(&lock->hdr);
+ if (obos_is_error(status))
+ return status;
CoreH_ClearSignaledState(&lock->hdr);
if (lock->nWaitingReaders)
goto try_again;
diff --git a/src/oboskrnl/locks/semaphore.c b/src/oboskrnl/locks/semaphore.c
index a7f1b19a..8a9e7ca1 100644
--- a/src/oboskrnl/locks/semaphore.c
+++ b/src/oboskrnl/locks/semaphore.c
@@ -35,7 +35,9 @@ obos_status Core_SemaphoreAcquire(semaphore* sem)
}
Core_SpinlockRelease(&sem->lock, oldIrql);
// Add the current thread to the waiting list.
- Core_WaitOnObject(&sem->hdr);
+ obos_status status = Core_WaitOnObject(&sem->hdr);
+ if (obos_is_error(status))
+ return status;
oldIrql = Core_SpinlockAcquire(&sem->lock);
sem->count--;
Core_SpinlockRelease(&sem->lock, oldIrql);
diff --git a/src/oboskrnl/locks/spinlock.c b/src/oboskrnl/locks/spinlock.c
index a2ff6833..afe8e4a2 100644
--- a/src/oboskrnl/locks/spinlock.c
+++ b/src/oboskrnl/locks/spinlock.c
@@ -1,7 +1,7 @@
/*
- oboskrnl/locks/spinlock.c
+ oboskrnl/locks/spinlock.c
- Copyright (c) 2024-2025 Omar Berrow
+ Copyright (c) 2024-2025 Omar Berrow
*/
#include
@@ -20,76 +20,78 @@
static uint64_t nanoseconds_since_boot()
{
#if !OBOS_ENABLE_LOCK_PROFILING
- return 0;
+ return 0;
#else
- if (!CoreS_GetNativeTimerFrequency())
- return 0;
- return CoreH_TickToNS(CoreS_GetNativeTimerTick(), true);
+ if (!CoreS_GetNativeTimerFrequency())
+ return 0;
+ return CoreH_TickToNS(CoreS_GetNativeTimerTick(), true);
#endif
}
__attribute__((no_instrument_function)) OBOS_NO_UBSAN irql Core_SpinlockAcquireExplicit(spinlock* const lock, irql minIrql, bool irqlNthrVariant)
{
- // IRQL_INVALID is used to specify not to raise the irql at all
- // this way, LowerIrql can lock the DPC queue without breaking.
- irql oldIrql = IRQL_INVALID;
- if (Core_GetIrql() < minIrql)
- oldIrql = Core_RaiseIrqlNoThread(minIrql);
- if (!atomic_flag_test_and_set_explicit(&lock->val, memory_order_acq_rel))
+ // IRQL_INVALID is used to specify not to raise the irql at all
+ // this way, LowerIrql can lock the DPC queue without breaking.
+ irql oldIrql = IRQL_INVALID;
+ if (obos_expect(Core_GetIrql() < minIrql, false))
+ oldIrql = Core_RaiseIrqlNoThread(minIrql);
+ if (!atomic_flag_test_and_set_explicit(&lock->val, memory_order_acq_rel))
goto done_wait;
while (atomic_flag_test_and_set_explicit(&lock->val, memory_order_acq_rel))
- OBOSS_SpinlockHint();
+ OBOSS_SpinlockHint();
done_wait:
- lock->locked = true;
- return oldIrql;
+ lock->locked = true;
+ return oldIrql;
}
__attribute__((no_instrument_function)) OBOS_NO_UBSAN irql Core_SpinlockAcquire(spinlock* const lock)
{
irql oldIrql = IRQL_INVALID;
- if (Core_GetIrql() < IRQL_DISPATCH)
+ if (obos_expect(Core_GetIrql() < IRQL_DISPATCH, false))
oldIrql = Core_RaiseIrqlNoThread(IRQL_DISPATCH);
if (!atomic_flag_test_and_set_explicit(&lock->val, memory_order_acq_rel))
goto locked;
- while (atomic_flag_test_and_set_explicit(&lock->val, memory_order_acq_rel))
- OBOSS_SpinlockHint();
+ while (atomic_flag_test_and_set_explicit(&lock->val, memory_order_acq_rel))
+ OBOSS_SpinlockHint();
locked:
- lock->locked = true;
+ lock->locked = true;
#if OBOS_ENABLE_LOCK_PROFILING
- lock->lastLockTimeNS = nanoseconds_since_boot();
+ lock->lastLockTimeNS = nanoseconds_since_boot();
#endif
- return oldIrql;
+ return oldIrql;
}
__attribute__((no_instrument_function)) OBOS_NO_UBSAN obos_status Core_SpinlockRelease(spinlock* const lock, irql oldIrql)
{
- if (oldIrql & 0xf0 && oldIrql != IRQL_INVALID)
- {
- OBOS_ASSERT(!"funny stuff");
- return OBOS_STATUS_INVALID_IRQL;
- }
- atomic_flag_clear_explicit(&lock->val, memory_order_relaxed);
- lock->locked = false;
- Core_LowerIrqlNoThread(oldIrql);
+#if OBOS_DEBUG
+ if (oldIrql & 0xf0 && oldIrql != IRQL_INVALID)
+ {
+ OBOS_ASSERT(!"funny stuff");
+ return OBOS_STATUS_INVALID_IRQL;
+ }
+#endif
+ atomic_flag_clear_explicit(&lock->val, memory_order_relaxed);
+ lock->locked = false;
+ Core_LowerIrqlNoThread(oldIrql);
#if OBOS_ENABLE_LOCK_PROFILING
- lock->lastLockTimeNS = nanoseconds_since_boot() - lock->lastLockTimeNS;
+ lock->lastLockTimeNS = nanoseconds_since_boot() - lock->lastLockTimeNS;
#endif
- return OBOS_STATUS_SUCCESS;
+ return OBOS_STATUS_SUCCESS;
}
/*
* No.
OBOS_NO_UBSAN void Core_SpinlockForcedRelease(spinlock* const lock)
{
- atomic_flag_clear_explicit(&lock->val, memory_order_seq_cst);
- lock->irqlNThrVariant = false;
+ atomic_flag_clear_explicit(&lock->val, memory_order_seq_cst);
+ lock->irqlNThrVariant = false;
#ifdef OBOS_DEBUG
- lock->owner = nullptr;
+ lock->owner = nullptr;
#endif
- lock->locked = false;
+ lock->locked = false;
}*/
__attribute__((no_instrument_function)) bool Core_SpinlockAcquired(spinlock* const lock)
{
- return lock ? lock->locked : false;
+ return lock ? lock->locked : false;
}
diff --git a/src/oboskrnl/locks/sys_futex.c b/src/oboskrnl/locks/sys_futex.c
index 9661f9cc..e86d6acb 100644
--- a/src/oboskrnl/locks/sys_futex.c
+++ b/src/oboskrnl/locks/sys_futex.c
@@ -92,6 +92,8 @@ obos_status Sys_FutexWait(uint32_t *futex, uint32_t cmp_with, uint64_t timeout)
// Mm_VirtualMemoryUnlock(CoreS_GetCPULocalPtr()->currentThread->proc->ctx, futex, sizeof(*futex));
obos_status status = Core_WaitOnObject(WAITABLE_OBJECT(*obj));
deref_futex(obj);
+ if (CoreS_ForceYieldOnSyscallReturn)
+ CoreS_ForceYieldOnSyscallReturn();
return status;
}
diff --git a/src/oboskrnl/locks/wait.c b/src/oboskrnl/locks/wait.c
index bc725a1a..4644874b 100644
--- a/src/oboskrnl/locks/wait.c
+++ b/src/oboskrnl/locks/wait.c
@@ -24,7 +24,7 @@
#if OBOS_DEBUG
# define assert_initialized() OBOS_ASSERT(obj->initialized == true)
#else
-# define assert_initialized() (true)
+# define assert_initialized() (void)(true)
#endif
obos_status Core_WaitOnObject(struct waitable_header* obj)
diff --git a/src/oboskrnl/locks/wait.h b/src/oboskrnl/locks/wait.h
index 9598a069..0ad93c8a 100644
--- a/src/oboskrnl/locks/wait.h
+++ b/src/oboskrnl/locks/wait.h
@@ -35,9 +35,11 @@ struct waitable_header
// otherwise, this will not work, and will corrupt stuff.
#define WAITABLE_OBJECT(obj) (struct waitable_header*)(&(obj))
-OBOS_EXPORT obos_status Core_WaitOnObject(struct waitable_header* obj);
+OBOS_EXPORT
+ OBOS_NODISCARD_REASON("Handle errors from Core_WaitOnObject") obos_status Core_WaitOnObject(struct waitable_header* obj);
// Waits until at least one object is signaled.
-OBOS_EXPORT obos_status Core_WaitOnObjects(size_t nObjects, struct waitable_header** objs, struct waitable_header** signaled);
+OBOS_EXPORT
+ OBOS_NODISCARD_REASON("Handle errors from Core_WaitOnObjects") obos_status Core_WaitOnObjects(size_t nObjects, struct waitable_header** objs, struct waitable_header** signaled);
OBOS_EXPORT obos_status CoreH_SignalWaitingThreads(struct waitable_header* obj, bool all, bool boostPriority);
OBOS_EXPORT void CoreH_ClearSignaledState(struct waitable_header* obj);
OBOS_EXPORT obos_status CoreH_AbortWaitingThreads(struct waitable_header* obj);
\ No newline at end of file
diff --git a/src/oboskrnl/mm/aging.c b/src/oboskrnl/mm/aging.c
index c483d757..decdb72b 100644
--- a/src/oboskrnl/mm/aging.c
+++ b/src/oboskrnl/mm/aging.c
@@ -67,7 +67,7 @@ obos_status Mm_AgingPRA(context* ctx)
if (ent->free)
{
MmH_RemovePageFromWorkingset(ctx, node_save);
- Mm_Allocator->Free(Mm_Allocator, ent, sizeof(*ent));
+ Free(Mm_Allocator, ent, sizeof(*ent));
continue;
}
page_info info = {};
@@ -91,8 +91,8 @@ obos_status Mm_AgingPRA(context* ctx)
REMOVE_WORKINGSET_PAGE_NODE(ctx->referenced, node);
if (ent->free)
{
- Mm_Allocator->Free(Mm_Allocator, node, sizeof(*node));
- Mm_Allocator->Free(Mm_Allocator, ent, sizeof(*ent));
+ Free(Mm_Allocator, node, sizeof(*node));
+ Free(Mm_Allocator, ent, sizeof(*ent));
continue;
}
ent->age <<= 1;
diff --git a/src/oboskrnl/mm/alloc.c b/src/oboskrnl/mm/alloc.c
index 42f23cbb..7b65237d 100644
--- a/src/oboskrnl/mm/alloc.c
+++ b/src/oboskrnl/mm/alloc.c
@@ -289,7 +289,7 @@ void* Mm_VirtualMemoryAllocEx(context* ctx, void* base_, size_t size, prot_flags
if (!rng)
{
- rng = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr);
+ rng = ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr);
present = rng->prot.present = !(flags & VMA_FLAGS_RESERVE);
rng->prot.huge_page = flags & VMA_FLAGS_HUGE_PAGE;
@@ -493,8 +493,8 @@ obos_status Mm_VirtualMemoryFree(context* ctx, void* base_, size_t size)
return OBOS_STATUS_INVALID_ARGUMENT;
}
// We need two ranges, one for the range behind base, and another for the range after.
- page_range* before = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr);
- page_range* after = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr);
+ page_range* before = ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr);
+ page_range* after = ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr);
memcpy(before, rng, sizeof(*before));
memcpy(after, rng, sizeof(*before));
before->size = base-before->virt;
@@ -510,7 +510,7 @@ obos_status Mm_VirtualMemoryFree(context* ctx, void* base_, size_t size)
if (curr->data->info.virt >= before->virt && curr->data->info.virt < after->virt)
{
curr->data->free = true; // mark for deletion.
- Mm_Allocator->Free(Mm_Allocator, curr, sizeof(*curr));
+ Free(Mm_Allocator, curr, sizeof(*curr));
curr = next;
continue;
}
@@ -532,7 +532,7 @@ obos_status Mm_VirtualMemoryFree(context* ctx, void* base_, size_t size)
RB_INSERT(page_tree, &ctx->pages, before);
RB_INSERT(page_tree, &ctx->pages, after);
rng->ctx = nullptr;
- Mm_Allocator->Free(Mm_Allocator, rng, sizeof(*rng));
+ Free(Mm_Allocator, rng, sizeof(*rng));
rng = nullptr;
}
else if (rng->virt == base || rng->size == size)
@@ -547,7 +547,7 @@ obos_status Mm_VirtualMemoryFree(context* ctx, void* base_, size_t size)
{
REMOVE_WORKINGSET_PAGE_NODE(rng->working_set_nodes, &curr->data->pr_node);
curr->data->free = true;
- Mm_Allocator->Free(Mm_Allocator, curr, sizeof(*curr));
+ Free(Mm_Allocator, curr, sizeof(*curr));
}
curr = next;
}
@@ -576,6 +576,7 @@ obos_status Mm_VirtualMemoryFree(context* ctx, void* base_, size_t size)
}
MmS_SetPageMapping(ctx->pt, &pg, 0, true);
}
+ MmS_TLBShootdown(ctx->pt, base, size);
if (rng)
{
@@ -614,11 +615,11 @@ obos_status Mm_VirtualMemoryFree(context* ctx, void* base_, size_t size)
// working_set_node* next = curr->next;
// REMOVE_WORKINGSET_PAGE_NODE(rng->working_set_nodes, &curr->data->pr_node);
// curr->data->free = true;
- // Mm_Allocator->Free(Mm_Allocator, curr, sizeof(*curr));
+ // Free(Mm_Allocator, curr, sizeof(*curr));
// curr = next;
// }
RB_REMOVE(page_tree, &ctx->pages, rng);
- Mm_Allocator->Free(Mm_Allocator, rng, sizeof(*rng));
+ Free(Mm_Allocator, rng, sizeof(*rng));
}
Core_SpinlockRelease(&ctx->lock, oldIrql);
@@ -689,9 +690,9 @@ obos_status Mm_VirtualMemoryProtect(context* ctx, void* base_, size_t size, prot
return OBOS_STATUS_INVALID_ARGUMENT;
}
// We need three ranges, one for the range behind base, another for the range after, and another for the new protection flags.
- page_range* before = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr);
- page_range* after = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr);
- page_range* new = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr);
+ page_range* before = ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr);
+ page_range* after = ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr);
+ page_range* new = ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr);
memcpy(new, rng, sizeof(*rng));
memcpy(before, rng, sizeof(*rng));
memcpy(after, rng, sizeof(*rng));
@@ -746,16 +747,16 @@ obos_status Mm_VirtualMemoryProtect(context* ctx, void* base_, size_t size, prot
if (before->size)
RB_INSERT(page_tree, &ctx->pages, before);
else
- Mm_Allocator->Free(Mm_Allocator, before, sizeof(page_range));
+ Free(Mm_Allocator, before, sizeof(page_range));
if (after->size)
RB_INSERT(page_tree, &ctx->pages, after);
else
- Mm_Allocator->Free(Mm_Allocator, after, sizeof(page_range));
+ Free(Mm_Allocator, after, sizeof(page_range));
if (new->size)
RB_INSERT(page_tree, &ctx->pages, new);
else
- Mm_Allocator->Free(Mm_Allocator, before, sizeof(page_range));
- Mm_Allocator->Free(Mm_Allocator, rng, sizeof(*rng));
+ Free(Mm_Allocator, before, sizeof(page_range));
+ Free(Mm_Allocator, rng, sizeof(*rng));
rng = new;
}
else if (rng->virt == base || rng->size == size)
@@ -766,7 +767,7 @@ obos_status Mm_VirtualMemoryProtect(context* ctx, void* base_, size_t size, prot
// "0x%p-0x%p\n",
// rng->virt, rng->virt+rng->size
// );
- page_range* new = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr);
+ page_range* new = ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr);
memcpy(new, rng, sizeof(*rng));
new->size = size;
rng->size = (rng->size-size);
@@ -817,6 +818,7 @@ obos_status Mm_VirtualMemoryProtect(context* ctx, void* base_, size_t size, prot
pg.prot.present = info.prot.present;
MmS_SetPageMapping(ctx->pt, &pg, info.phys, false);
}
+ MmS_TLBShootdown(ctx->pt, base, size);
Core_SpinlockRelease(&ctx->lock, oldIrql);
return OBOS_STATUS_SUCCESS;
}
@@ -868,11 +870,12 @@ void* Mm_MapViewOfUserMemory(context* const user_context, void* ubase_, void* kb
}
}
- page_range* rng = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr);
+ page_range* rng = ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr);
rng->virt = kbase;
rng->ctx = &Mm_KernelContext;
rng->phys32 = false;
rng->hasGuardPage = false;
+ rng->pageable = false;
rng->size = size;
rng->prot.huge_page = false;
rng->prot.rw = !(prot & OBOS_PROTECTION_READ_ONLY);
@@ -909,6 +912,7 @@ void* Mm_MapViewOfUserMemory(context* const user_context, void* ubase_, void* kb
if (~prot & OBOS_PROTECTION_READ_ONLY)
Mm_MarkAsDirtyPhys(phys);
}
+ OBOS_ENSURE(phys);
if (phys && phys->cow_type && ~prot & OBOS_PROTECTION_READ_ONLY)
{
@@ -934,7 +938,7 @@ void* Mm_MapViewOfUserMemory(context* const user_context, void* ubase_, void* kb
info.accessed = false;
info.range = rng;
info.prot = rng->prot;
- info.prot.present = !!phys;
+ info.prot.present = info.phys != 0;
info.prot.rw = rng->prot.rw;
OBOS_ENSURE(info.phys);
MmS_SetPageMapping(Mm_KernelContext.pt, &info, info.phys, false);
@@ -991,7 +995,7 @@ void* Mm_QuickVMAllocate(size_t sz, bool non_pageable)
uintptr_t base = (uintptr_t)blk;
- page_range* rng = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr);
+ page_range* rng = ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr);
rng->ctx = ctx;
rng->size = sz;
rng->virt = base;
diff --git a/src/oboskrnl/mm/alloc.h b/src/oboskrnl/mm/alloc.h
index 521ac3ee..3c3ed17a 100644
--- a/src/oboskrnl/mm/alloc.h
+++ b/src/oboskrnl/mm/alloc.h
@@ -75,9 +75,14 @@ extern OBOS_EXPORT page* Mm_UserAnonPage;
OBOS_EXPORT void* MmH_FindAvailableAddress(context* ctx, size_t size, vma_flags flags, obos_status* status);
// file can be nullptr for a anonymous mapping.
+OBOS_EXPORT obos_status Mm_VirtualMemoryFree(context* ctx, void* base, size_t size);
+#ifndef __clang__
+OBOS_EXPORT __attribute__((malloc, malloc(Mm_VirtualMemoryFree, 2))) void* Mm_VirtualMemoryAlloc(context* ctx, void* base, size_t size, prot_flags prot, vma_flags flags, fd* file, obos_status* status);
+OBOS_EXPORT __attribute__((malloc, malloc(Mm_VirtualMemoryFree, 2))) void* Mm_VirtualMemoryAllocEx(context* ctx, void* base, size_t size, prot_flags prot, vma_flags flags, fd* file, uoff_t offset, obos_status* status);
+#else
OBOS_EXPORT void* Mm_VirtualMemoryAlloc(context* ctx, void* base, size_t size, prot_flags prot, vma_flags flags, fd* file, obos_status* status);
OBOS_EXPORT void* Mm_VirtualMemoryAllocEx(context* ctx, void* base, size_t size, prot_flags prot, vma_flags flags, fd* file, uoff_t offset, obos_status* status);
-OBOS_EXPORT obos_status Mm_VirtualMemoryFree(context* ctx, void* base, size_t size);
+#endif
// Note: base must be the exact address as returned by VirtualMemoryAlloc.
// isPageable values:
// 0: Non-pageable
@@ -90,21 +95,10 @@ OBOS_EXPORT obos_status Mm_VirtualMemoryProtect(context* ctx, void* base, size_t
// NOTE: The returned address is not aligned down to the page size.
OBOS_EXPORT void* Mm_MapViewOfUserMemory(context* const user_context, void* ubase, void* kbase, size_t nBytes, prot_flags protection, bool respectUserProtection, obos_status* status);
-typedef enum unmap_behavior {
- // Default behavior.
- // Allow the pages to be unmapped from the address space, but do not unlock the backing memory.
- UNMAP_FLAGS_ALLOW = 0,
- // Defers the unmap until the pages are unlocked manually.
- UNMAP_FLAGS_DEFER,
- // Unlocks the pages on unmap, then unmaps them.
- UNMAP_FLAGS_UNLOCK,
-} unmap_behavior;
-
// Locks pages from base to base+sz in the working-set.
// If space is not avaliable in the working-set, pages are removed until space can be satisified.
// If the working-set's capacity is too small, then it can be inflated until the pages are unlocked.
-// The unmap_
-OBOS_EXPORT obos_status Mm_VirtualMemoryLock(context* ctx, void* base, size_t sz, unmap_behavior unmap_action);
+OBOS_EXPORT obos_status Mm_VirtualMemoryLock(context* ctx, void* base, size_t sz);
// Unlocks pages from base to base+sz from the working-set.
// If the pages caused the working-set capacity to be inflated, then it is deflated once again.
OBOS_EXPORT obos_status Mm_VirtualMemoryUnlock(context* ctx, void* base, size_t sz);
diff --git a/src/oboskrnl/mm/bare_map.c b/src/oboskrnl/mm/bare_map.c
index e2357e6c..d6168308 100644
--- a/src/oboskrnl/mm/bare_map.c
+++ b/src/oboskrnl/mm/bare_map.c
@@ -49,28 +49,18 @@ static OBOS_PAGEABLE_FUNCTION void Unlock(irql oldIrql)
Core_SpinlockRelease(&s_regionListLock, oldIrql);
}
+void OBOSH_BasicMMSetBumpRegion(basicmm_region* region)
+{
+ irql oldIrql = Lock();
+ bump_region = *region;
+ Unlock(oldIrql);
+}
+
OBOS_NO_KASAN OBOS_PAGEABLE_FUNCTION void* OBOS_BasicMMAllocatePages(size_t sz, obos_status* status)
{
irql oldIrql = Lock();
if (!bump_region.addr)
- {
- // OBOS_ALIGNAS(OBOS_PAGE_SIZE) static uint8_t region[256*1024*1024]; // 256M
- OBOS_ALIGNAS(OBOS_PAGE_SIZE) static uint8_t region[4*1024*1024]; // 4M
- bump_region.size = sizeof(region);
- bump_region.addr = (uintptr_t)region;
- // for (uintptr_t addr = bump_region.addr; addr < (bump_region.addr + bump_region.size); addr += OBOS_PAGE_SIZE)
- // {
- // obos_status stat = OBOS_STATUS_SUCCESS;
- // uintptr_t mem = Mm_AllocatePhysicalPages(1, 1, &stat);
- // if (stat != OBOS_STATUS_SUCCESS)
- // {
- // if (status)
- // *status = stat;
- // return nullptr;
- // }
- // OBOSS_MapPage_RW_XD((void*)addr, mem);
- // }
- }
+ OBOS_Panic(OBOS_PANIC_ALLOCATOR_ERROR, "BasicMM: No region specified by platform code.\n");
sz += (OBOS_PAGE_SIZE-(sz%OBOS_PAGE_SIZE));
if ((bump_offset + sz) >= bump_region.size)
OBOS_Panic(OBOS_PANIC_NO_MEMORY, "BasicMM: No more space in bump allocator.\n");
diff --git a/src/oboskrnl/mm/bare_map.h b/src/oboskrnl/mm/bare_map.h
index 7840af33..dfe2f51d 100644
--- a/src/oboskrnl/mm/bare_map.h
+++ b/src/oboskrnl/mm/bare_map.h
@@ -67,4 +67,6 @@ void OBOSH_BasicMMAddRegion(basicmm_region* nodeBase, void* base, size_t sz);
///
/// The call back. Returns true to continue iteration, otherwise false. Takes in the current region, and the passed user data.
/// The user data to pass.
-void OBOSH_BasicMMIterateRegions(bool(*callback)(basicmm_region*, void*), void* udata);
\ No newline at end of file
+void OBOSH_BasicMMIterateRegions(bool(*callback)(basicmm_region*, void*), void* udata);
+
+void OBOSH_BasicMMSetBumpRegion(basicmm_region* region);
\ No newline at end of file
diff --git a/src/oboskrnl/mm/context.c b/src/oboskrnl/mm/context.c
index b319fe48..99212fdb 100644
--- a/src/oboskrnl/mm/context.c
+++ b/src/oboskrnl/mm/context.c
@@ -107,7 +107,7 @@ page* MmH_AllocatePage(uintptr_t phys, bool huge)
{
if (!phys)
return nullptr;
- page* buf = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(page), nullptr);
+ page* buf = ZeroAllocate(Mm_Allocator, 1, sizeof(page), nullptr);
buf->phys = phys;
if (huge)
buf->flags |= PHYS_PAGE_HUGE_PAGE;
@@ -154,7 +154,7 @@ void MmH_DerefPage(page* buf)
}
}
Mm_PhysicalMemoryUsage -= ((buf->flags & PHYS_PAGE_HUGE_PAGE) ? OBOS_HUGE_PAGE_SIZE : OBOS_PAGE_SIZE);
- Mm_Allocator->Free(Mm_Allocator, buf, sizeof(*buf));
+ Free(Mm_Allocator, buf, sizeof(*buf));
}
}
memstat Mm_GlobalMemoryUsage;
@@ -173,7 +173,7 @@ OBOS_NODISCARD swap_allocation* MmH_LookupSwapAllocation(uintptr_t id)
}
swap_allocation* MmH_AddSwapAllocation(uintptr_t id)
{
- swap_allocation* new = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(swap_allocation), nullptr);
+ swap_allocation* new = ZeroAllocate(Mm_Allocator, 1, sizeof(swap_allocation), nullptr);
new->id = id;
new->provider = Mm_SwapProvider;
new->refs = 0;
@@ -198,7 +198,7 @@ void MmH_DerefSwapAllocation(swap_allocation* alloc)
if (alloc->provider->free_obj)
alloc->provider->free_obj(alloc->provider);
}
- Mm_Allocator->Free(Mm_Allocator, alloc, sizeof(*alloc));
+ Free(Mm_Allocator, alloc, sizeof(*alloc));
}
}
LIST_GENERATE(swap_allocation_list, struct swap_allocation, node);
@@ -210,3 +210,10 @@ void Mm_ConstructContext(context* ctx)
ctx->pt = MmS_AllocatePageTable();
ctx->lock = Core_SpinlockCreate();
}
+
+OBOS_EXPORT obos_status Drv_TLBShootdown(page_table pt, uintptr_t base, size_t size)
+{
+ if (MmS_TLBShootdown)
+ return MmS_TLBShootdown(pt, base, size);
+ return OBOS_STATUS_UNIMPLEMENTED;
+}
\ No newline at end of file
diff --git a/src/oboskrnl/mm/context.h b/src/oboskrnl/mm/context.h
index d94862de..f2ca8dca 100644
--- a/src/oboskrnl/mm/context.h
+++ b/src/oboskrnl/mm/context.h
@@ -43,6 +43,10 @@ OBOS_EXPORT page_table MmS_GetCurrentPageTable();
/// The status of the function.
OBOS_EXPORT obos_status MmS_SetPageMapping(page_table pt, const page_info* page, uintptr_t phys, bool free_pte);
+OBOS_WEAK obos_status MmS_TLBShootdown(page_table pt, uintptr_t base, size_t size);
+
+OBOS_EXPORT obos_status Drv_TLBShootdown(page_table pt, uintptr_t base, size_t size);
+
typedef struct working_set
{
struct {
diff --git a/src/oboskrnl/mm/fork.c b/src/oboskrnl/mm/fork.c
index 69214d66..d861c55d 100644
--- a/src/oboskrnl/mm/fork.c
+++ b/src/oboskrnl/mm/fork.c
@@ -50,7 +50,7 @@ obos_status Mm_ForkContext(context* into, context* toFork)
* Map both page ranges as Sym CoW
* Go to the next range
*/
- page_range* clone = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr);
+ page_range* clone = ZeroAllocate(Mm_Allocator, 1, sizeof(page_range), nullptr);
memcpy(clone, curr, sizeof(*curr));
clone->ctx = into;
memzero(&clone->rb_node, sizeof(clone->rb_node));
@@ -90,6 +90,7 @@ obos_status Mm_ForkContext(context* into, context* toFork)
down:
MmS_SetPageMapping(into->pt, &info, info.phys, false);
}
+ MmS_TLBShootdown(toFork->pt, curr->virt, curr->size);
}
}
Core_SpinlockRelease(&toFork->lock, oldIrql);
diff --git a/src/oboskrnl/mm/handler.c b/src/oboskrnl/mm/handler.c
index f348e7d1..6a6f5fbb 100644
--- a/src/oboskrnl/mm/handler.c
+++ b/src/oboskrnl/mm/handler.c
@@ -65,6 +65,7 @@ static void map_file_region(page_range* rng, uintptr_t addr, uint32_t ec, fault_
info->prot.rw = rng->prot.rw && !(ec & PF_EC_RW);
MmS_SetPageMapping(rng->ctx->pt, info, phys->phys, false);
+ MmS_TLBShootdown(rng->ctx->pt, info->virt, info->prot.huge_page ? OBOS_HUGE_PAGE_SIZE : OBOS_PAGE_SIZE);
}
static bool sym_cow_cpy(context* ctx, page_range* rng, uintptr_t addr, uint32_t ec, page* pg, page_info* info)
@@ -77,6 +78,7 @@ static bool sym_cow_cpy(context* ctx, page_range* rng, uintptr_t addr, uint32_t
info->prot.rw = true;
info->prot.ro = false;
MmS_SetPageMapping(ctx->pt, info, pg->phys, false);
+ MmS_TLBShootdown(ctx->pt, info->virt, info->prot.huge_page ? OBOS_HUGE_PAGE_SIZE : OBOS_PAGE_SIZE);
pg->cow_type = COW_DISABLED;
return true;
}
@@ -86,6 +88,7 @@ static bool sym_cow_cpy(context* ctx, page_range* rng, uintptr_t addr, uint32_t
info->prot.rw = true;
info->prot.ro = false;
MmS_SetPageMapping(ctx->pt, info, new->phys, false);
+ MmS_TLBShootdown(ctx->pt, info->virt, info->prot.huge_page ? OBOS_HUGE_PAGE_SIZE : OBOS_PAGE_SIZE);
MmH_DerefPage(pg);
return true;
}
@@ -107,14 +110,14 @@ static obos_status ref_page(context* ctx, const page_info *curr)
bool allocated_ent = false;
if (!ent)
{
- ent = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(working_set_entry), nullptr);
+ ent = ZeroAllocate(Mm_Allocator, 1, sizeof(working_set_entry), nullptr);
ent->info.virt = curr->virt;
ent->info.prot = curr->prot;
ent->info.range = rng;
allocated_ent = true;
}
ent->refs++;
- working_set_node* node = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(working_set_node), nullptr);
+ working_set_node* node = ZeroAllocate(Mm_Allocator, 1, sizeof(working_set_node), nullptr);
node->data = ent;
#if defined(OBOS_PAGE_REPLACEMENT_AGING)
status = Mm_AgingReferencePage(ctx, node);
@@ -123,9 +126,9 @@ static obos_status ref_page(context* ctx, const page_info *curr)
#endif
if (obos_is_error(status))
{
- Mm_Allocator->Free(Mm_Allocator, node, sizeof(*node));
+ Free(Mm_Allocator, node, sizeof(*node));
if (allocated_ent)
- Mm_Allocator->Free(Mm_Allocator, ent, sizeof(*ent));
+ Free(Mm_Allocator, ent, sizeof(*ent));
return status;
}
APPEND_WORKINGSET_PAGE_NODE(ctx->referenced, node);
@@ -168,6 +171,7 @@ static bool asym_cow_cpy(context* ctx, page_range* rng, uintptr_t addr, uint32_t
}
done:
MmS_SetPageMapping(ctx->pt, info, pg->phys, false);
+ MmS_TLBShootdown(rng->ctx->pt, info->virt, info->prot.huge_page ? OBOS_HUGE_PAGE_SIZE : OBOS_PAGE_SIZE);
info->range = rng;
if (ec & PF_EC_RW)
Mm_MarkAsDirtyPhys(pg);
@@ -332,7 +336,7 @@ void MmH_RemovePageFromWorkingset(context* ctx, working_set_node* node)
}
if (!ent->free)
REMOVE_WORKINGSET_PAGE_NODE(ent->info.range->working_set_nodes, &ent->pr_node);
- Mm_Allocator->Free(Mm_Allocator, ent, sizeof(*ent));
+ Free(Mm_Allocator, ent, sizeof(*ent));
}
- Mm_Allocator->Free(Mm_Allocator, node, sizeof(*node));
+ Free(Mm_Allocator, node, sizeof(*node));
}
diff --git a/src/oboskrnl/mm/handler.h b/src/oboskrnl/mm/handler.h
index c2a6b394..dfa97625 100644
--- a/src/oboskrnl/mm/handler.h
+++ b/src/oboskrnl/mm/handler.h
@@ -54,7 +54,7 @@ typedef enum {
/// The virtual address that faulted.
/// The page fault's error code.
/// OBOS_STATUS_SUCCESS if the page fault was handled, OBOS_STATUS_UNHANDLED if the page fault went unhandled, otherwise an error.
-obos_status Mm_HandlePageFault(context* ctx, uintptr_t addr, uint32_t ec);
+OBOS_EXPORT obos_status Mm_HandlePageFault(context* ctx, uintptr_t addr, uint32_t ec);
///
/// Runs the page replacement algorithm on pages in a context.
/// This essentially chooses pages from within the context, and puts them within the working-set of the context.
diff --git a/src/oboskrnl/mm/mm_sys.c b/src/oboskrnl/mm/mm_sys.c
index f1adf076..df4b6d0b 100644
--- a/src/oboskrnl/mm/mm_sys.c
+++ b/src/oboskrnl/mm/mm_sys.c
@@ -116,7 +116,7 @@ handle Sys_MakeNewContext(size_t ws_capacity)
ws_capacity = OBOS_DEFAULT_WS_CAPACITY;
if (ws_capacity % OBOS_HUGE_PAGE_SIZE)
ws_capacity += (OBOS_HUGE_PAGE_SIZE-(ws_capacity%OBOS_HUGE_PAGE_SIZE));
- context* ctx = Mm_Allocator->ZeroAllocate(Mm_Allocator, 1, sizeof(context), nullptr);
+ context* ctx = ZeroAllocate(Mm_Allocator, 1, sizeof(context), nullptr);
Mm_ConstructContext(ctx);
ctx->workingSet.capacity = ws_capacity;
OBOS_LockHandleTable(OBOS_CurrentHandleTable());
diff --git a/src/oboskrnl/mm/swap.c b/src/oboskrnl/mm/swap.c
index 42404e52..7ad49510 100644
--- a/src/oboskrnl/mm/swap.c
+++ b/src/oboskrnl/mm/swap.c
@@ -60,6 +60,7 @@ obos_status Mm_SwapOut(uintptr_t virt, page_range* rng)
return status;
page.prot.present = false;
status = MmS_SetPageMapping(rng->ctx->pt, &page, phys, false);
+ MmS_TLBShootdown(rng->ctx->pt, page.virt, page.prot.huge_page ? OBOS_HUGE_PAGE_SIZE : OBOS_PAGE_SIZE);
if (obos_is_error(status))
return status;
if (page.dirty)
@@ -106,7 +107,7 @@ obos_status Mm_SwapIn(page_info* page, fault_type* type)
node->pagedCount++;
page->prot.present = true;
obos_status status = MmS_SetPageMapping(page->range->ctx->pt, page, node->phys, false);
- // Mm_Allocator->Free(Mm_Allocator, node, sizeof(*node));
+ // Free(Mm_Allocator, node, sizeof(*node));
if (obos_expect(obos_is_error(status), false))
{
// Unlikely error.
@@ -176,7 +177,8 @@ static __attribute__((no_instrument_function)) void page_writer()
// const char* const This = "Page Writer";
while (1)
{
- Core_WaitOnObject(WAITABLE_OBJECT(page_writer_wake));
+ obos_status status = Core_WaitOnObject(WAITABLE_OBJECT(page_writer_wake));
+ OBOS_ENSURE(obos_is_success(status));
Core_EventClear(&page_writer_done);
if (!Mm_PageWriterOperation)
Mm_PageWriterOperation = PAGE_WRITER_SYNC_ALL;
@@ -365,8 +367,10 @@ void Mm_WakePageWriter(bool wait)
{
OBOS_ASSERT(page_writer_thread.status);
Core_EventPulse(&page_writer_wake, true);
+ obos_status status = OBOS_STATUS_SUCCESS;
if (wait)
- Core_WaitOnObject(WAITABLE_OBJECT(page_writer_done));
+ status = Core_WaitOnObject(WAITABLE_OBJECT(page_writer_done));
+ OBOS_UNUSED(status);
}
irql Mm_TakeSwapLock()
diff --git a/src/oboskrnl/net/arp.c b/src/oboskrnl/net/arp.c
index 0e6226a7..1e0d3d83 100644
--- a/src/oboskrnl/net/arp.c
+++ b/src/oboskrnl/net/arp.c
@@ -4,6 +4,8 @@
* Copyright (c) 2025 Omar Berrow
*/
+#include "irq/timer.h"
+#include "locks/wait.h"
#include
#include
#include
@@ -47,9 +49,12 @@ obos_status NetH_ARPRequest(vnode* nic, ip_addr addr, mac_address* out, address_
address_table_entry* ent = RB_FIND(address_table, &nic->net_tables->arp_cache, &what);
Core_PushlockRelease(&nic->net_tables->arp_cache_lock, true);
+ obos_status status = OBOS_STATUS_SUCCESS;
if (ent)
{
- Core_WaitOnObject(WAITABLE_OBJECT(ent->sync));
+ status = Core_WaitOnObject(WAITABLE_OBJECT(ent->sync));
+ if (obos_is_error(status))
+ return status;
if (memcmp_b(ent->phys, 0, sizeof(mac_address)))
{
Core_PushlockAcquire(&nic->net_tables->arp_cache_lock, true);
@@ -89,26 +94,65 @@ obos_status NetH_ARPRequest(vnode* nic, ip_addr addr, mac_address* out, address_
memcpy(payload->sender_mac, nic->net_tables->mac, sizeof(mac_address));
payload->target_ip = addr;
memzero(payload->target_mac, sizeof(payload->target_mac));
-
- shared_ptr *eth = NetH_FormatEthernetPacket(nic, MAC_BROADCAST, hdr, sz_hdr, ETHERNET2_TYPE_ARP);
- obos_status status = NetH_SendEthernetPacket(nic, OBOS_SharedPtrCopy(eth));
- if (obos_is_error(status))
+
+ event tm_evnt = EVENT_INITIALIZE(EVENT_NOTIFICATION);
+ timer* tm = nullptr;
+ CoreH_MakeTimerEvent(&tm, 1000*1000, &tm_evnt, true);
+
+ struct waitable_header* signaled = nullptr;
+ struct waitable_header* objs[2] = {
+ WAITABLE_OBJECT(tm_evnt),
+ WAITABLE_OBJECT(ent->sync)
+ };
+
+ size_t nTimeouts = 0;
+
+ do
{
- Core_PushlockAcquire(&nic->net_tables->table_lock, false);
- RB_REMOVE(address_table, &nic->net_tables->arp_cache, ent);
- Core_PushlockRelease(&nic->net_tables->table_lock, false);
- Free(OBOS_KernelAllocator, ent, sizeof(*ent));
- return status; // hdr_ptr isn't leaked, as we never reference it
- }
+ shared_ptr *eth = NetH_FormatEthernetPacket(nic, MAC_BROADCAST, hdr, sz_hdr, ETHERNET2_TYPE_ARP);
+ status = NetH_SendEthernetPacket(nic, OBOS_SharedPtrCopy(eth));
+ if (obos_is_error(status))
+ {
+ Core_CancelTimer(tm);
+ Core_TimerObjectFree(tm);
+ Core_PushlockAcquire(&nic->net_tables->table_lock, false);
+ RB_REMOVE(address_table, &nic->net_tables->arp_cache, ent);
+ Core_PushlockRelease(&nic->net_tables->table_lock, false);
+ Free(OBOS_KernelAllocator, ent, sizeof(*ent));
+ return status; // hdr_ptr isn't leaked, as we never reference it
+ }
- status = Core_WaitOnObject(WAITABLE_OBJECT(ent->sync));
- if (obos_is_error(status))
+ status = Core_WaitOnObjects(2, objs, &signaled);
+ if (obos_is_error(status))
+ {
+ Core_CancelTimer(tm);
+ Core_TimerObjectFree(tm);
+ Core_PushlockAcquire(&nic->net_tables->arp_cache_lock, true);
+ RB_REMOVE(address_table, &nic->net_tables->arp_cache, ent);
+ Core_PushlockRelease(&nic->net_tables->arp_cache_lock, true);
+ Free(OBOS_KernelAllocator, ent, sizeof(*ent));
+ return status;
+ }
+ if (signaled == WAITABLE_OBJECT(ent->sync))
+ break;
+ Core_EventClear(&tm_evnt);
+ // We timed out.
+ continue;
+ } while (++nTimeouts <= 10);
+
+ Core_CancelTimer(tm);
+ Core_TimerObjectFree(tm);
+
+ if (signaled != WAITABLE_OBJECT(ent->sync))
{
+ status = OBOS_STATUS_TIMED_OUT;
Core_PushlockAcquire(&nic->net_tables->arp_cache_lock, true);
RB_REMOVE(address_table, &nic->net_tables->arp_cache, ent);
Core_PushlockRelease(&nic->net_tables->arp_cache_lock, true);
+ Free(OBOS_KernelAllocator, ent, sizeof(*ent));
return status;
}
+
if (out)
memcpy(*out, ent->phys, sizeof(mac_address));
if (address_table_ent)
diff --git a/src/oboskrnl/net/lo.c b/src/oboskrnl/net/lo.c
index 4ee2288d..421134b8 100644
--- a/src/oboskrnl/net/lo.c
+++ b/src/oboskrnl/net/lo.c
@@ -138,6 +138,7 @@ static obos_status finalize_irp(void* req_)
memcpy(pckt->buffer, req->cbuff, req->blkCount);
pckt->refs = hnd->dev->refs;
pckt->size = req->blkCount;
+ // printf("LO: TX Packet (size: %d)\n", pckt->size);
Core_MutexAcquire(&hnd->dev->lock);
LIST_APPEND(lo_packet_queue, &hnd->dev->recv, pckt);
@@ -165,6 +166,7 @@ static obos_status ioctl(dev_desc what, uint32_t request, void* argp)
switch (request) {
case IOCTL_IFACE_MAC_REQUEST:
memzero(argp, sizeof(mac_address));
+ ((uint8_t*)argp)[0] |= BIT(1);
return OBOS_STATUS_SUCCESS;
default:
return Net_InterfaceIoctl(Net_LoopbackDevice, request, argp);
diff --git a/src/oboskrnl/net/route.c b/src/oboskrnl/net/route.c
index 04c34689..1a8ffff9 100644
--- a/src/oboskrnl/net/route.c
+++ b/src/oboskrnl/net/route.c
@@ -262,7 +262,9 @@ obos_status NetH_AddressRoute(net_tables** interface, ip_table_entry** routing_e
shared_ptr data = {};
OBOS_SharedPtrConstruct(&data, &hdr);
NetH_SendIPv4Packet(curr->iface->interface, curr->ent, destination, 0x11, curr->ttl, 0, OBOS_SharedPtrCopy(&data));
- Core_WaitOnObject(WAITABLE_OBJECT(port->recv_event));
+ obos_status status = Core_WaitOnObject(WAITABLE_OBJECT(port->recv_event));
+ if (obos_is_error(status))
+ return status;
icmp_header* icmp_hdr = port->icmp_header;
shared_ptr* icmp_hdr_ptr = port->icmp_header_ptr;
diff --git a/src/oboskrnl/net/tcp.c b/src/oboskrnl/net/tcp.c
index da53f5ac..a043e1a9 100644
--- a/src/oboskrnl/net/tcp.c
+++ b/src/oboskrnl/net/tcp.c
@@ -4,6 +4,8 @@
* Copyright (c) 2025 Omar Berrow
*/
+#include "error.h"
+#include "irq/irql.h"
#include
#include
#include
@@ -118,13 +120,14 @@ obos_status NetH_SendTCPSegment(vnode* nic, tcp_connection* con, void* ent_ /* i
hdr->chksum = tcp_chksum(&ip_psuedo_header, sizeof(ip_psuedo_header), hdr, sz);
hdr->chksum = be16_to_host(hdr->chksum);
- // OBOS_Debug("tcp tx segment: hdr->flags=0x%x, hdr->ack=0x%x, hdr->seq=0x%x\n", hdr->flags, be32_to_host(hdr->ack), be32_to_host(hdr->seq));
+ //printf("tcp tx segment (%d->%d): hdr->flags=0x%x, hdr->ack=0x%x, hdr->seq=0x%x\n", be16_to_host(hdr->src_port), be16_to_host(hdr->dest_port), hdr->flags, be32_to_host(hdr->ack), be32_to_host(hdr->seq));
// NOTE: Keep the list locked until we append the unacked segment
// since if we get an ACK immediately (this includes if we get preempted!),
// and the TCP handler sees no unACKed segment, then this segment will be
// spuriously retransmitted, which is probably bad.
+ irql oldIrql = Core_RaiseIrql(IRQL_DISPATCH);
if (con)
Core_PushlockAcquire(&con->unacked_segments.lock, false);
@@ -143,13 +146,17 @@ obos_status NetH_SendTCPSegment(vnode* nic, tcp_connection* con, void* ent_ /* i
if (obos_is_error(status))
{
+ Core_LowerIrql(oldIrql);
if (con)
Core_PushlockRelease(&con->unacked_segments.lock, false);
return status;
}
if (!con)
+ {
+ Core_LowerIrql(oldIrql);
return OBOS_STATUS_SUCCESS;
+ }
tcp_unacked_segment* seg = ZeroAllocate(OBOS_KernelAllocator, 1, sizeof(tcp_unacked_segment), nullptr);
OBOS_SharedPtrConstructSz(&seg->ptr, seg, sizeof(*seg));
@@ -186,6 +193,8 @@ obos_status NetH_SendTCPSegment(vnode* nic, tcp_connection* con, void* ent_ /* i
Core_PushlockRelease(&con->unacked_segments.lock, false);
+ Core_LowerIrql(oldIrql);
+
return OBOS_STATUS_SUCCESS;
}
@@ -270,20 +279,25 @@ PacketProcessSignature(TCP, ip_header*)
.addr=ip_hdr->dest_address,
.port=be16_to_host(hdr->dest_port),
},
- .is_client = true,
+ .is_client = false,
};
- Core_PushlockAcquire(&nic->net_tables->tcp_connections_lock, true);
- tcp_connection* con = RB_FIND(tcp_connection_tree, &nic->net_tables->tcp_outgoing_connections, &conn_key);
- Core_PushlockRelease(&nic->net_tables->tcp_connections_lock, true);
-
+ tcp_connection* con = nullptr;
+
if (port)
{
Core_PushlockAcquire(&port->connection_tree_lock, true);
- conn_key.is_client = false;
con = RB_FIND(tcp_connection_tree, &port->connections, &conn_key);
Core_PushlockRelease(&port->connection_tree_lock, true);
}
+ if (!con)
+ {
+ Core_PushlockAcquire(&nic->net_tables->tcp_connections_lock, true);
+ conn_key.is_client = true;
+ con = RB_FIND(tcp_connection_tree, &nic->net_tables->tcp_outgoing_connections, &conn_key);
+ Core_PushlockRelease(&nic->net_tables->tcp_connections_lock, true);
+ }
+
if ((!con || con->state.state == TCP_STATE_CLOSED) && !port)
{
@@ -296,12 +310,7 @@ PacketProcessSignature(TCP, ip_header*)
resp.seq = be32_to_host(hdr->ack);
else
{
- // TODO: Is this check valid?
-#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
uint8_t header_length = (hdr->data_offset >> 4) * 4;
-#else
- uint8_t header_length = (hdr->data_offset & 0xf) * 4;
-#endif
uint32_t segment_length = be16_to_host(ip_hdr->packet_length)-IPv4_GET_HEADER_LENGTH(ip_hdr) - header_length;
resp.seq = 0;
resp.ack = be32_to_host(hdr->seq)+segment_length+1;
@@ -477,8 +486,8 @@ PacketProcessSignature(TCP, ip_header*)
{
// This is UNACCEPTABLE!
// (pun intended)
- // OBOS_Debug("received unacceptable segment! discarding\n");
- // OBOS_Debug("NOTE: PCKT.SEQ=%d, PCKT.ACK=%d, RCV.NXT=%d, RCV.WND=%d, PCKT.LEN=%d\n",
+ //printf("received unacceptable segment! discarding\n");
+ //printf("NOTE: PCKT.SEQ=%d, PCKT.ACK=%d, RCV.NXT=%d, RCV.WND=%d, PCKT.LEN=%d\n",
// be32_to_host(hdr->seq)-con->state.rcv.irs, be32_to_host(hdr->ack)-con->state.snd.iss,
// con->state.rcv.nxt, con->state.rcv.wnd, segment_length
// );
@@ -640,8 +649,8 @@ PacketProcessSignature(TCP, ip_header*)
size_t nPushed = 0;
Net_TCPPushReceivedData(con, segment_data, segment_length, &nPushed);
con->state.rcv.nxt += nPushed;
- // OBOS_Debug("TCP window (%d, %d) receive window %d->%d\n", con->dest.port, con->src.port, con->state.rcv.wnd, con->state.rcv.wnd-nPushed);
- // OBOS_Debug("TCP: Expecting SEQ=%d next (current SEQ=%d)\n", con->state.rcv.nxt-con->state.rcv.irs, be32_to_host(hdr->seq) - con->state.rcv.irs);
+ //printf("TCP window (%d, %d) receive window %d->%d\n", con->dest.port, con->src.port, con->state.rcv.wnd, con->state.rcv.wnd-nPushed);
+ //printf("TCP: Expecting SEQ=%d next (current SEQ=%d)\n", con->state.rcv.nxt-con->state.rcv.irs, be32_to_host(hdr->seq) - con->state.rcv.irs);
con->state.rcv.wnd -= nPushed;
struct tcp_pseudo_hdr resp = {};
resp.src_port = be16_to_host(hdr->dest_port);
@@ -744,26 +753,26 @@ void Net_TCPPushReceivedData(tcp_connection* con, const void* buffer, size_t sz,
return;
}
-static const char* state_strs[] = {
- "INVALID",
- "LISTEN",
- "SYN_SENT",
- "SYN_RECEIVED",
- "ESTABLISHED",
- "FIN_WAIT1",
- "FIN_WAIT2",
- "CLOSE_WAIT",
- "CLOSING",
- "LAST_ACK",
- "TIME_WAIT",
- "CLOSED",
-};
+// static const char* state_strs[] = {
+// "INVALID",
+// "LISTEN",
+// "SYN_SENT",
+// "SYN_RECEIVED",
+// "ESTABLISHED",
+// "FIN_WAIT1",
+// "FIN_WAIT2",
+// "CLOSE_WAIT",
+// "CLOSING",
+// "LAST_ACK",
+// "TIME_WAIT",
+// "CLOSED",
+// };
void Net_TCPChangeConnectionState(tcp_connection* con, int state)
{
if (state > TCP_STATE_CLOSED || state < TCP_STATE_INVALID)
return;
- // OBOS_Debug("TCP: Changing from %s to %s\n", con->state.state[state_strs], state[state_strs]);
+ //printf("TCP: Changing from %s to %s\n", con->state.state[state_strs], state[state_strs]);
con->state.state = state;
Core_EventPulse(&con->state.state_change_event, false);
if (state == TCP_STATE_ESTABLISHED)
@@ -810,7 +819,7 @@ bool Net_TCPRemoteACKedSegment(tcp_connection* con, uint32_t ack)
nBytesACKed -= seg->nBytesUnACKed;
con->state.snd.una += seg->nBytesUnACKed;
seg->nBytesUnACKed = 0;
- // OBOS_Debug("remote acked packet flags=0x%x remote acked 0x%p seg.seq=0x%p\n", seg->segment.flags, ack - con->state.snd.iss, seg->segment.seq - con->state.snd.iss);
+ //printf("remote acked packet flags=0x%x remote acked 0x%p seg.seq=0x%p\n", seg->segment.flags, ack - con->state.snd.iss, seg->segment.seq - con->state.snd.iss);
}
else
{
@@ -998,6 +1007,19 @@ void Net_TCPPushDataToRemote(tcp_connection* con, const void* buffer, size_t siz
}
+void Net_TCPReset(tcp_connection* con)
+{
+ struct tcp_pseudo_hdr hdr = {};
+ hdr.ack = con->state.rcv.nxt;
+ hdr.seq = con->state.snd.nxt;
+ hdr.flags = TCP_RST;
+ hdr.src_port = con->src.port;
+ hdr.dest_port = con->dest.port;
+ hdr.ttl = con->ttl;
+ NetH_SendTCPSegment(con->nic, nullptr, con->ip_ent, con->dest.addr, &hdr);
+ Net_TCPChangeConnectionState(con, TCP_STATE_CLOSED);
+}
+
// LIST_GENERATE(tcp_incoming_list, tcp_incoming_packet, node);
RB_GENERATE(tcp_connection_tree, tcp_connection, node, tcp_connection_cmp);
RB_GENERATE(tcp_port_tree, tcp_port, node, tcp_port_cmp);
@@ -1035,7 +1057,10 @@ void tcp_free(socket_desc* socket)
if (!s->is_server)
{
- Net_TCPSocketBackend.shutdown(socket, SHUT_RDWR);
+ // Net_TCPSocketBackend.shutdown(socket, SHUT_RDWR);
+ // Reset the connection.
+ if (s->connection->state.state < TCP_STATE_TIME_WAIT)
+ Net_TCPReset(s->connection);
net_tables* iface = s->connection->nic->net_tables;
Core_PushlockAcquire(&iface->tcp_connections_lock, false);
@@ -1174,9 +1199,16 @@ static void internal_listen_thread(void* udata)
objs[i] = WAITABLE_OBJECT(s->serv.bound_ports[i-1]->connection_event);
while (1)
{
- Core_WaitOnObjects(s->serv.bound_port_count+1, objs, &signaled);
+ obos_status status = OBOS_STATUS_SUCCESS;
+ if (obos_is_error(status = Core_WaitOnObjects(s->serv.bound_port_count+1, objs, &signaled)))
+ {
+ NetError("Net: %s: Core_WaitOnObjects returned %d, aborting.\n", __func__, status);
+ break;
+ }
+
if (signaled == objs[0])
break;
+
for (size_t i = 0; i < s->serv.bound_port_count; i++)
{
if (signaled == WAITABLE_OBJECT(s->serv.bound_ports[i]->connection_event))
@@ -1387,8 +1419,8 @@ obos_status tcp_connect(socket_desc* socket, struct sockaddr* saddr, size_t addr
while (s->connection->state.state != TCP_STATE_ESTABLISHED)
{
- Core_WaitOnObject(WAITABLE_OBJECT(s->connection->state.state_change_event));
- if (s->connection->reset)
+ status = Core_WaitOnObject(WAITABLE_OBJECT(s->connection->state.state_change_event));
+ if (s->connection->reset || obos_is_error(status))
{
Core_PushlockAcquire(&iface->tcp_connections_lock, false);
RB_REMOVE(tcp_connection_tree, &iface->tcp_outgoing_connections, s->connection);
@@ -1502,8 +1534,8 @@ static void irp_on_event_set(irp* req)
if (req->dryOp)
return;
- if (req->socket_flags)
- // OBOS_Debug("TCP: Recv got 0x%p for flags\n", req->socket_flags);
+ // if (req->socket_flags)
+ //printf("TCP: Recv got 0x%p for flags\n", req->socket_flags);
Core_MutexAcquire(&s->connection->recv_buffer.lock);
@@ -1512,8 +1544,8 @@ static void irp_on_event_set(irp* req)
if (~req->socket_flags & MSG_PEEK)
{
s->connection->recv_buffer.in_ptr += read_size;
- // OBOS_Debug("TCP: Read %d bytes\n", read_size);
- // OBOS_Debug("TCP window (%d, %d) receive window %d->%d\n", s->connection->dest.port, s->connection->src.port, s->connection->state.rcv.wnd, s->connection->state.rcv.wnd+read_size);
+ //printf("TCP: Read %d bytes\n", read_size);
+ //printf("TCP window (%d, %d) receive window %d->%d\n", s->connection->dest.port, s->connection->src.port, s->connection->state.rcv.wnd, s->connection->state.rcv.wnd+read_size);
s->connection->state.rcv.wnd += read_size;
OBOS_ENSURE(s->connection->recv_buffer.in_ptr <= s->connection->recv_buffer.ptr);
if (s->connection->recv_buffer.in_ptr == s->connection->recv_buffer.ptr)
@@ -1684,15 +1716,15 @@ socket_ops Net_TCPSocketBackend = {
.proto_type.protocol = IPPROTO_TCP,
.domain = AF_INET,
.create = tcp_create,
- .free = tcp_free,
- .accept = tcp_accept,
- .bind = tcp_bind,
- .connect = tcp_connect,
- .getpeername = tcp_getpeername,
- .getsockname = tcp_getsockname,
- .listen = tcp_listen,
- .submit_irp = tcp_submit_irp,
- .finalize_irp = tcp_finalize_irp,
- .shutdown = tcp_shutdown,
- .sockatmark = tcp_sockatmark
+ .free = tcp_free,
+ .accept = tcp_accept,
+ .bind = tcp_bind,
+ .connect = tcp_connect,
+ .getpeername = tcp_getpeername,
+ .getsockname = tcp_getsockname,
+ .listen = tcp_listen,
+ .submit_irp = tcp_submit_irp,
+ .finalize_irp = tcp_finalize_irp,
+ .shutdown = tcp_shutdown,
+ .sockatmark = tcp_sockatmark
};
\ No newline at end of file
diff --git a/src/oboskrnl/net/tcp.h b/src/oboskrnl/net/tcp.h
index a1cd0d45..9d38cf9a 100644
--- a/src/oboskrnl/net/tcp.h
+++ b/src/oboskrnl/net/tcp.h
@@ -226,6 +226,7 @@ void Net_TCPCancelAllOutstandingSegments(tcp_connection* con);
void Net_TCPChangeConnectionState(tcp_connection* con, int state);
void Net_TCPPushReceivedData(tcp_connection* con, const void* buffer, size_t size, size_t *nPushed);
void Net_TCPPushDataToRemote(tcp_connection* con, const void* buffer, size_t size, bool oob);
+void Net_TCPReset(tcp_connection* con);
static inline int tcp_connection_cmp(tcp_connection* lhs, tcp_connection* rhs)
{
diff --git a/src/oboskrnl/net/udp.c b/src/oboskrnl/net/udp.c
index a7db1e39..ba6c3c33 100644
--- a/src/oboskrnl/net/udp.c
+++ b/src/oboskrnl/net/udp.c
@@ -231,7 +231,12 @@ static void internal_read_thread(void* userdata)
while (!ports->read_closed)
{
struct waitable_header* signaled = nullptr;
- Core_WaitOnObjects(1+ports->nPorts, events, &signaled);
+ obos_status status = Core_WaitOnObjects(1+ports->nPorts, events, &signaled);
+ if (obos_is_error(status))
+ {
+ NetError("Net: %s: Core_WaitOnObjects returned %d, aborting.\n", __func__, status);
+ break;
+ }
if (signaled == WAITABLE_OBJECT(ports->wake_read_thread))
break;
for (size_t i = 0; i < ports->nPorts; i++)
diff --git a/src/oboskrnl/power/shutdown.c b/src/oboskrnl/power/shutdown.c
index ebf012d2..1a6ea0af 100644
--- a/src/oboskrnl/power/shutdown.c
+++ b/src/oboskrnl/power/shutdown.c
@@ -41,6 +41,7 @@ OBOS_NORETURN void OBOS_Reboot()
{
if (Mm_SwapProvider->deinit_dev)
Mm_SwapProvider->deinit_dev(Mm_SwapProvider);
+ irql oldIrql = Core_RaiseIrql(IRQL_MASKED);
Core_SuspendScheduler(true);
Core_WaitForSchedulerSuspend();
uacpi_reboot();
@@ -55,6 +56,7 @@ OBOS_NORETURN void OBOS_Reboot()
// We should not be here anymore.
OBOS_UNREACHABLE;
#endif
+ (void)oldIrql;
while(1)
asm volatile("");
}
diff --git a/src/oboskrnl/scheduler/process.c b/src/oboskrnl/scheduler/process.c
index 1601acef..36569a20 100644
--- a/src/oboskrnl/scheduler/process.c
+++ b/src/oboskrnl/scheduler/process.c
@@ -86,6 +86,12 @@ OBOS_PAGEABLE_FUNCTION obos_status Core_ProcessStart(process* proc, thread* main
proc->prev = proc->parent->children.tail;
proc->parent->children.tail = proc;
proc->parent->children.nChildren++;
+ proc->ruid = proc->parent->ruid;
+ proc->euid = proc->parent->euid;
+ proc->suid = proc->parent->suid;
+ proc->rgid = proc->parent->rgid;
+ proc->egid = proc->parent->egid;
+ proc->sgid = proc->parent->sgid;
proc->refcount++;
Core_SetProcessGroup(proc, proc->parent->pgrp->pgid);
proc->waiting_threads = WAITABLE_HEADER_INITIALIZE(false, true);
@@ -225,7 +231,7 @@ uintptr_t ExitCurrentProcess(uintptr_t unused)
}
MmS_FreePageTable(proc->ctx->pt);
- Mm_Allocator->Free(Mm_Allocator, proc->ctx, sizeof(context));
+ Free(Mm_Allocator, proc->ctx, sizeof(context));
thread* ready = nullptr;
thread* running = nullptr;
@@ -324,6 +330,7 @@ void Core_ExitProcessGroup()
Core_MutexRelease(&Core_ProcessGroupTreeLock);
}
Core_MutexRelease(&pgrp->lock);
+ proc->refcount--;
}
obos_status Core_SetProcessGroup(process* proc, uint32_t pgid)
@@ -363,6 +370,7 @@ obos_status Core_SetProcessGroup(process* proc, uint32_t pgid)
Core_MutexAcquire(&pgrp->lock);
LIST_APPEND(process_list, &pgrp->processes, proc);
+ proc->refcount++;
proc->pgrp = pgrp;
Core_MutexRelease(&pgrp->lock);
diff --git a/src/oboskrnl/scheduler/process.h b/src/oboskrnl/scheduler/process.h
index b97d0af2..e77fc051 100644
--- a/src/oboskrnl/scheduler/process.h
+++ b/src/oboskrnl/scheduler/process.h
@@ -9,6 +9,7 @@
#include
#include
#include
+#include
#include
@@ -36,8 +37,12 @@ typedef struct process
struct process_group* pgrp;
- uid currentUID;
- gid currentGID;
+ uid euid, ruid, suid;
+ gid egid, rgid, sgid;
+ struct {
+ gid *list;
+ size_t nEntries;
+ } groups;
uint32_t exitCode;
bool dead;
@@ -59,6 +64,8 @@ typedef struct process
// Only exists for POSIX, ignored in most parts of the kernel.
uint32_t umask;
+ sigaction signal_handlers[64];
+
LIST_NODE(process_list, struct process) node;
} process;
typedef LIST_HEAD(process_list, process) process_list;
diff --git a/src/oboskrnl/scheduler/sched_sys.c b/src/oboskrnl/scheduler/sched_sys.c
index cdcd7053..45d5a7d4 100644
--- a/src/oboskrnl/scheduler/sched_sys.c
+++ b/src/oboskrnl/scheduler/sched_sys.c
@@ -4,7 +4,6 @@
* Copyright (c) 2024-2025 Omar Berrow
*/
-#include "vfs/mount.h"
#include
#include
#include
@@ -24,6 +23,8 @@
#include
#include
+#include
+
#include
#include
@@ -184,7 +185,6 @@ handle Sys_ThreadCreate(thread_priority priority, thread_affinity affinity, hand
thr->references++;
OBOS_UnlockHandleTable(OBOS_CurrentHandleTable());
- memcpy(thr->signal_info->signals, Core_GetCurrentThread()->signal_info->signals, sizeof(thr->signal_info->signals));
thr->signal_info->mask = Core_GetCurrentThread()->signal_info->mask;
return hnd;
@@ -472,6 +472,7 @@ handle Sys_ProcessStart(handle mainThread, handle vmmContext, bool is_fork)
OBOS_LockHandleTable(OBOS_CurrentHandleTable());
handle_desc* desc = nullptr;
+ new->refcount++;
handle hnd = OBOS_HandleAllocate(OBOS_CurrentHandleTable(), HANDLE_TYPE_PROCESS, &desc);
desc->un.process = new;
OBOS_UnlockHandleTable(OBOS_CurrentHandleTable());
@@ -663,29 +664,187 @@ obos_status Sys_WaitProcess(handle proc, int* wstatus, int options, uint32_t* pi
return status;
}
+uid Sys_GetUid()
+{ return Core_GetCurrentThread()->proc->ruid; }
+gid Sys_GetGid()
+{ return Core_GetCurrentThread()->proc->rgid; }
-obos_status Sys_SetUid(uid to)
+static bool check_unpriv_uid(uid uid)
{
- process* proc = Core_GetCurrentThread()->proc;
- if (proc->currentUID != 0)
- return OBOS_STATUS_ACCESS_DENIED;
- proc->currentUID = to;
+ return (uid != Core_GetCurrentThread()->proc->ruid) &&
+ (uid != Core_GetCurrentThread()->proc->euid) &&
+ (uid != Core_GetCurrentThread()->proc->suid);
+}
+static bool check_unpriv_gid(gid gid)
+{
+ return (gid != Core_GetCurrentThread()->proc->rgid) &&
+ (gid != Core_GetCurrentThread()->proc->egid) &&
+ (gid != Core_GetCurrentThread()->proc->sgid);
+}
+
+obos_status Sys_SetRESUid(uid ruid, uid euid, uid suid)
+{
+ if (Core_GetCurrentThread()->proc->euid != 0)
+ {
+ if ((ruid != -1) && !check_unpriv_uid(ruid))
+ return OBOS_STATUS_ACCESS_DENIED;
+ if ((euid != -1) && !check_unpriv_uid(euid))
+ return OBOS_STATUS_ACCESS_DENIED;
+ if ((suid != -1) && !check_unpriv_uid(suid))
+ return OBOS_STATUS_ACCESS_DENIED;
+ if (ruid != -1)
+ Core_GetCurrentThread()->proc->ruid = ruid;
+ if (euid != -1)
+ Core_GetCurrentThread()->proc->euid = euid;
+ if (suid != -1)
+ Core_GetCurrentThread()->proc->suid = suid;
+ }
+ else
+ {
+ if (ruid != -1) Core_GetCurrentThread()->proc->ruid = ruid;
+ if (euid != -1) Core_GetCurrentThread()->proc->euid = euid;
+ if (suid != -1) Core_GetCurrentThread()->proc->suid = suid;
+ }
return OBOS_STATUS_SUCCESS;
}
-obos_status Sys_SetGid(gid to)
+obos_status Sys_SetRESGid(gid rgid, gid egid, gid sgid)
{
- process* proc = Core_GetCurrentThread()->proc;
- if (proc->currentUID != 0)
- return OBOS_STATUS_ACCESS_DENIED;
- proc->currentGID = to;
+ if (Core_GetCurrentThread()->proc->euid != 0)
+ {
+ if ((rgid != -1) && !check_unpriv_gid(rgid))
+ return OBOS_STATUS_ACCESS_DENIED;
+ if ((egid != -1) && !check_unpriv_gid(egid))
+ return OBOS_STATUS_ACCESS_DENIED;
+ if ((sgid != -1) && !check_unpriv_gid(sgid))
+ return OBOS_STATUS_ACCESS_DENIED;
+ if (rgid != -1)
+ Core_GetCurrentThread()->proc->rgid = rgid;
+ if (egid != -1)
+ Core_GetCurrentThread()->proc->egid = egid;
+ if (sgid != -1)
+ Core_GetCurrentThread()->proc->sgid = sgid;
+ }
+ else
+ {
+ if (rgid != -1) Core_GetCurrentThread()->proc->rgid = rgid;
+ if (egid != -1) Core_GetCurrentThread()->proc->egid = egid;
+ if (sgid != -1) Core_GetCurrentThread()->proc->sgid = sgid;
+ }
return OBOS_STATUS_SUCCESS;
}
-uid Sys_GetUid()
-{ return Core_GetCurrentThread()->proc->currentUID; }
-gid Sys_GetGid()
-{ return Core_GetCurrentThread()->proc->currentGID; }
+obos_status Sys_GetRESUid(uid* ruid, uid* euid, uid* suid)
+{
+ if (ruid)
+ memcpy_k_to_usr(ruid, &Core_GetCurrentThread()->proc->ruid, sizeof(uid));
+ if (euid)
+ memcpy_k_to_usr(euid, &Core_GetCurrentThread()->proc->euid, sizeof(uid));
+ if (suid)
+ memcpy_k_to_usr(suid, &Core_GetCurrentThread()->proc->suid, sizeof(uid));
+ return OBOS_STATUS_SUCCESS;
+}
+
+obos_status Sys_GetRESGid(gid* rgid, gid* egid, gid* sgid)
+{
+ if (rgid)
+ memcpy_k_to_usr(rgid, &Core_GetCurrentThread()->proc->rgid, sizeof(gid));
+ if (egid)
+ memcpy_k_to_usr(egid, &Core_GetCurrentThread()->proc->egid, sizeof(gid));
+ if (sgid)
+ memcpy_k_to_usr(sgid, &Core_GetCurrentThread()->proc->sgid, sizeof(gid));
+ return OBOS_STATUS_SUCCESS;
+}
+
+obos_status Sys_SetUid(uid uid)
+{
+ if (Core_GetCurrentThread()->proc->euid == 0)
+ {
+ Core_GetCurrentThread()->proc->ruid = uid;
+ Core_GetCurrentThread()->proc->euid = uid;
+ Core_GetCurrentThread()->proc->suid = uid;
+ return OBOS_STATUS_SUCCESS;
+ }
+ return OBOS_STATUS_ACCESS_DENIED;
+}
+
+obos_status Sys_SetGid(gid gid)
+{
+ if (Core_GetCurrentThread()->proc->euid == 0)
+ {
+ Core_GetCurrentThread()->proc->rgid = gid;
+ Core_GetCurrentThread()->proc->egid = gid;
+ Core_GetCurrentThread()->proc->sgid = gid;
+ return OBOS_STATUS_SUCCESS;
+ }
+ return OBOS_STATUS_ACCESS_DENIED;
+}
+
+obos_status Sys_SetGroups(handle process, size_t size, gid* ulist)
+{
+ struct process* proc =
+ HANDLE_TYPE(process) == HANDLE_TYPE_CURRENT ?
+ Core_GetCurrentThread()->proc :
+ nullptr;
+ obos_status status = OBOS_STATUS_SUCCESS;
+ if (!proc)
+ {
+ OBOS_LockHandleTable(OBOS_CurrentHandleTable());
+ handle_desc* desc = OBOS_HandleLookup(OBOS_CurrentHandleTable(), process, HANDLE_TYPE_PROCESS, false, &status);
+ if (!desc)
+ {
+ OBOS_UnlockHandleTable(OBOS_CurrentHandleTable());
+ return status;
+ }
+ proc = desc->un.process;
+ OBOS_UnlockHandleTable(OBOS_CurrentHandleTable());
+ }
+
+ gid* list = Mm_MapViewOfUserMemory(Core_GetCurrentThread()->proc->ctx,
+ ulist, nullptr,
+ size * sizeof(gid),
+ OBOS_PROTECTION_READ_ONLY, true,
+ &status);
+ if (obos_is_error(status) && size)
+ return status;
+
+ proc->groups.list = Reallocate(OBOS_KernelAllocator, proc->groups.list, size*sizeof(gid), proc->groups.nEntries*sizeof(gid), nullptr);
+ if (list)
+ memcpy(proc->groups.list, list, size * sizeof(gid));
+ proc->groups.nEntries = size;
+
+ if (size)
+ Mm_VirtualMemoryFree(&Mm_KernelContext, list, size*sizeof(gid));
+ return OBOS_STATUS_SUCCESS;
+}
+obos_status Sys_GetGroups(handle process, size_t *size, gid* list)
+{
+ struct process* proc =
+ HANDLE_TYPE(process) == HANDLE_TYPE_CURRENT ?
+ Core_GetCurrentThread()->proc :
+ nullptr;
+ obos_status status = OBOS_STATUS_SUCCESS;
+ if (!proc)
+ {
+ OBOS_LockHandleTable(OBOS_CurrentHandleTable());
+ handle_desc* desc = OBOS_HandleLookup(OBOS_CurrentHandleTable(), process, HANDLE_TYPE_PROCESS, false, &status);
+ if (!desc)
+ {
+ OBOS_UnlockHandleTable(OBOS_CurrentHandleTable());
+ return status;
+ }
+ proc = desc->un.process;
+ OBOS_UnlockHandleTable(OBOS_CurrentHandleTable());
+ }
+ size_t sz = 0;
+ status = memcpy_usr_to_k(&sz, size, sizeof(sz));
+ if (obos_is_error(status))
+ return status;
+ status = memcpy_k_to_usr(list, proc->groups.list, OBOS_MIN(sz, proc->groups.nEntries) * sizeof(gid));
+ if (obos_is_error(status))
+ return status;
+ return memcpy_k_to_usr(size, &proc->groups.nEntries, sizeof(size_t));
+}
obos_status Sys_SetProcessGroup(handle process, uint32_t pgid)
{
diff --git a/src/oboskrnl/scheduler/sched_sys.h b/src/oboskrnl/scheduler/sched_sys.h
index d0381dc5..06d8b31d 100644
--- a/src/oboskrnl/scheduler/sched_sys.h
+++ b/src/oboskrnl/scheduler/sched_sys.h
@@ -66,10 +66,17 @@ handle Sys_ProcessGetChildHandle();
// If HANDLE_ANY to make it choose an arbitrary child process.
obos_status Sys_WaitProcess(handle proc, int* status, int options, uint32_t* ret_pid);
-obos_status Sys_SetUid(uid to);
-obos_status Sys_SetGid(gid to);
uid Sys_GetUid();
gid Sys_GetGid();
+obos_status Sys_SetRESUid(uid ruid, uid euid, uid suid);
+obos_status Sys_SetRESGid(gid rgid, gid egid, gid sgid);
+obos_status Sys_GetRESUid(uid* ruid, uid* euid, uid* suid);
+obos_status Sys_GetRESGid(gid* rgid, gid* egid, gid* sgid);
+obos_status Sys_SetUid(uid uid);
+obos_status Sys_SetGid(gid gid);
+
+obos_status Sys_SetGroups(handle proc, size_t size, gid* list);
+obos_status Sys_GetGroups(handle proc, size_t *size, gid* list);
obos_status Sys_SetProcessGroup(handle proc, uint32_t pgid);
obos_status Sys_GetProcessGroup(handle proc, uint32_t* pgid);
\ No newline at end of file
diff --git a/src/oboskrnl/scheduler/thread.h b/src/oboskrnl/scheduler/thread.h
index b115df02..0e2d7081 100644
--- a/src/oboskrnl/scheduler/thread.h
+++ b/src/oboskrnl/scheduler/thread.h
@@ -219,3 +219,10 @@ OBOS_EXPORT thread_affinity CoreH_CPUIdToAffinity(uint32_t cpuId);
/// Exits the current thread.
///
OBOS_NORETURN OBOS_EXPORT void Core_ExitCurrentThread();
+
+///
+/// Forces a yield on syscall return. Should only be called before the syscall returns.
+/// This function exists so that blocking syscalls can give any signals a chance to run
+/// if it was interrupted by a signal.
+///
+OBOS_WEAK void CoreS_ForceYieldOnSyscallReturn();
\ No newline at end of file
diff --git a/src/oboskrnl/signal.c b/src/oboskrnl/signal.c
index 1631d02f..3871a937 100644
--- a/src/oboskrnl/signal.c
+++ b/src/oboskrnl/signal.c
@@ -11,6 +11,7 @@
#include
#include
#include
+#include
#include
#include
@@ -44,6 +45,8 @@ obos_status OBOS_Kill(struct thread* as, struct thread* thr, int sigval)
return OBOS_STATUS_INVALID_OPERATION;
if (thr->proc->pid == 0)
return OBOS_STATUS_INVALID_OPERATION;
+ if (thr->proc->euid != as->proc->euid && as->proc->euid != 0)
+ return OBOS_STATUS_ACCESS_DENIED;
if (sigval == 0)
return OBOS_STATUS_SUCCESS; // see man fork.2, "If sig is 0, then no signal is sent, but existence and permission checks are still performed"
@@ -74,22 +77,27 @@ obos_status OBOS_Kill(struct thread* as, struct thread* thr, int sigval)
else if (sigval == SIGSTOP)
{
// Stop the thread.
- thr->signal_info->signals[sigval].sender = as;
+ thr->proc->signal_handlers[sigval].sender = as;
CoreH_ThreadBlock(thr, true);
Core_MutexRelease(&thr->signal_info->lock);
return OBOS_STATUS_SUCCESS;
}
+ if (thr->proc->signal_handlers[sigval-1].un.handler == SIG_IGN)
+ {
+ Core_MutexRelease(&thr->signal_info->lock);
+ return OBOS_STATUS_SUCCESS;
+ }
thr->signal_info->pending |= BIT(sigval - 1);
// set these up before the call to kill.
- // thr->signal_info->signals[sigval].addr = nullptr;
- // thr->signal_info->signals[sigval].status = 0;
- // thr->signal_info->signals[sigval].udata = 0;
- // thr->signal_info->signals[sigval].sigcode = 0;
- thr->signal_info->signals[sigval].sender = as;
+ // thr->proc->signal_handlers[sigval].addr = nullptr;
+ // thr->proc->signal_handlers[sigval].status = 0;
+ // thr->proc->signal_handlers[sigval].udata = 0;
+ // thr->proc->signal_handlers[sigval].sigcode = 0;
+ thr->proc->signal_handlers[sigval].sender = as;
Core_MutexRelease(&thr->signal_info->lock);
if (thr->status == THREAD_STATUS_BLOCKED)
{
- if (sigval == SIGTSTP && thr->signal_info->mask & BIT(SIGTSTP - 1))
+ if (thr->signal_info->mask & BIT(SIGTSTP - 1))
return OBOS_STATUS_SUCCESS;
// TODO: Use CoreH_AbortWaitingThreads instead of this?
thr->interrupted = true;
@@ -104,13 +112,13 @@ obos_status OBOS_SigAction(int signum, const sigaction* act, sigaction* oldact)
if (!(signum >= 0 && signum < SIGMAX))
return OBOS_STATUS_INVALID_ARGUMENT;
if (oldact)
- *oldact = Core_GetCurrentThread()->signal_info->signals[signum];
+ *oldact = Core_GetCurrentThread()->proc->signal_handlers[signum];
if (act)
{
Core_MutexAcquire(&Core_GetCurrentThread()->signal_info->lock);
- Core_GetCurrentThread()->signal_info->signals[signum - 1] = *act;
+ Core_GetCurrentThread()->proc->signal_handlers[signum - 1] = *act;
// what.
- // Core_GetCurrentThread()->signal_info->signals[signum].un.handler = SIG_DFL /* default handler is the kernel */;
+ // Core_GetCurrentThread()->proc->signal_handlers[signum].un.handler = SIG_DFL /* default handler is the kernel */;
Core_MutexRelease(&Core_GetCurrentThread()->signal_info->lock);
}
return OBOS_STATUS_SUCCESS;
@@ -120,7 +128,8 @@ obos_status OBOS_SigSuspend(sigset_t mask)
Core_MutexAcquire(&Core_GetCurrentThread()->signal_info->lock);
sigset_t old = Core_GetCurrentThread()->signal_info->mask;
Core_GetCurrentThread()->signal_info->mask = mask;
- Core_WaitOnObject(WAITABLE_OBJECT(Core_GetCurrentThread()->signal_info->event));
+ obos_status status = Core_WaitOnObject(WAITABLE_OBJECT(Core_GetCurrentThread()->signal_info->event));
+ if (obos_is_error(status)) return status;
Core_GetCurrentThread()->signal_info->mask = old;
Core_MutexRelease(&Core_GetCurrentThread()->signal_info->lock);
return OBOS_STATUS_SUCCESS;
@@ -200,8 +209,12 @@ obos_status OBOS_KillProcess(struct process* proc, int sigval)
case SIGCONT:
case SIGSTOP:
case SIGTSTP:
- OBOS_Kill(Core_GetCurrentThread(), thr, sigval);
+ {
+ obos_status status = OBOS_Kill(Core_GetCurrentThread(), thr, sigval);
+ if (obos_is_error(status))
+ return status;
continue;
+ }
default:
break;
}
@@ -270,7 +283,7 @@ obos_status OBOS_KillProcessGroup(process_group* pgrp, int sigval)
void OBOS_RunSignal(int sigval, interrupt_frame* frame)
{
- sigaction* sig = &Core_GetCurrentThread()->signal_info->signals[sigval];
+ sigaction* sig = &Core_GetCurrentThread()->proc->signal_handlers[sigval];
if (!(sig->flags & SA_NODEFER))
Core_GetCurrentThread()->signal_info->mask |= BIT_TYPE(sigval-1, L);
Core_EventSet(&Core_GetCurrentThread()->signal_info->event, false);
@@ -295,7 +308,7 @@ OBOS_NO_UBSAN bool OBOS_SyncPendingSignal(interrupt_frame* frame)
sigval += 1;
Core_MutexRelease(&Core_GetCurrentThread()->signal_info->lock);
OBOS_RunSignal(sigval, frame);
- return Core_GetCurrentThread()->signal_info->signals[sigval-1].un.handler != SIG_IGN;
+ return Core_GetCurrentThread()->proc->signal_handlers[sigval-1].un.handler != SIG_IGN;
}
#define T SIGNAL_DEFAULT_TERMINATE_PROC,
diff --git a/src/oboskrnl/signal.h b/src/oboskrnl/signal.h
index de6c02bf..49cecafc 100644
--- a/src/oboskrnl/signal.h
+++ b/src/oboskrnl/signal.h
@@ -26,78 +26,8 @@
#define SIG_DFL (nullptr)
#define SIG_IGN ((void*)1)
-// Public
-enum {
- SIGHUP = 1 , SIGINT, SIGQUIT, SIGILL, SIGTRAP,
- SIGABRT , SIGBUS, SIGFPE, SIGKILL, SIGUSR1,
- SIGSEGV , SIGUSR2, SIGPIPE, SIGALRM, SIGTERM,
- SIGSTKFLT , SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP,
- SIGTTIN , SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ,
- SIGVTALRM , SIGSYS, SIGMAX = 64,
-};
-
-// Public
-typedef uint64_t sigset_t;
+#include
-// Public
-enum {
- SA_SIGINFO = BIT(0),
- SA_ONSTACK = BIT(1),
- SA_RESETHAND = BIT(2),
- SA_NODEFER = BIT(3),
- SA_NOCLDWAIT = BIT(4), // unimplemented
- SA_NOCLDSTOP = BIT(5), // unimplemented
-};
-// Public
-typedef struct siginfo_t
-{
- int signum;
- int sigcode;
- struct thread* sender;
- void* addr;
- int status;
- union {
- void* ptr;
- uintptr_t integer;
- } udata;
-} siginfo_t;
-// Public
-typedef struct user_sigaction {
- union {
- void(*handler)(int signum);
- void(*sa_sigaction)(int signum, siginfo_t* info, void* unknown);
- } un;
- // NOTE(oberrow): Set to __mlibc_restorer in the mlibc sysdeps.
- uintptr_t trampoline_base; // required
- uint32_t flags;
-} user_sigaction;
-typedef struct sigaction {
- union {
- void(*handler)(int signum);
- void(*sa_sigaction)(int signum, siginfo_t* info, void* unknown);
- } un;
- // NOTE(oberrow): Set to __mlibc_restorer in the mlibc sysdeps.
- uintptr_t trampoline_base; // required
- uint32_t flags;
- // The following fields are not to be carried to userspace.
- // Fields of 'siginfo_t' are set with this
- uintptr_t udata;
- void* addr;
- int status;
- int sigcode;
- struct thread* sender;
-} sigaction;
-// Internal
-typedef struct signal_header {
- // NOTE: To get the first signal to dispatch, use __builtin_ctzll(pending & ~masked)
- sigaction signals[64];
- sigset_t pending;
- sigset_t mask;
- uintptr_t sp;
- size_t stack_size; // Unused in the actual signal implemtation, only exists for Sys_SigAltStack.
- mutex lock; // take when modifying this structure.
- event event; // set when a signal runs, clear when it exits (sigreturn)
-} signal_header;
signal_header* OBOSH_AllocateSignalHeader();
obos_status OBOS_Kill(struct thread* as, struct thread* thr, int sigval);
@@ -126,17 +56,6 @@ OBOS_WEAK void OBOSS_SigReturn(ucontext_t* frame);
OBOS_WEAK void OBOSS_RunSignalImpl(int sigval, interrupt_frame* frame);
-enum signal_default_action
-{
- // When this is the default, the signal runner returns normally.
- SIGNAL_DEFAULT_IGNORE,
- // When this is the default, the current thread is exited.
- SIGNAL_DEFAULT_TERMINATE_PROC,
- // Blocks the thread.
- SIGNAL_DEFAULT_STOP,
- // Readies the thread.
- SIGNAL_DEFAULT_CONTINUE,
-};
extern enum signal_default_action OBOS_SignalDefaultActions[SIGMAX+1];
void OBOS_DefaultSignalHandler(int signum, siginfo_t* info, void* unknown);
diff --git a/src/oboskrnl/signal_def.h b/src/oboskrnl/signal_def.h
new file mode 100644
index 00000000..997dd5e2
--- /dev/null
+++ b/src/oboskrnl/signal_def.h
@@ -0,0 +1,90 @@
+#pragma once
+
+#include
+
+#include
+#include
+
+enum signal_default_action
+{
+ // When this is the default, the signal runner returns normally.
+ SIGNAL_DEFAULT_IGNORE,
+ // When this is the default, the current thread is exited.
+ SIGNAL_DEFAULT_TERMINATE_PROC,
+ // Blocks the thread.
+ SIGNAL_DEFAULT_STOP,
+ // Readies the thread.
+ SIGNAL_DEFAULT_CONTINUE,
+};
+
+// Public
+enum {
+ SIGHUP = 1 , SIGINT, SIGQUIT, SIGILL, SIGTRAP,
+ SIGABRT , SIGBUS, SIGFPE, SIGKILL, SIGUSR1,
+ SIGSEGV , SIGUSR2, SIGPIPE, SIGALRM, SIGTERM,
+ SIGSTKFLT , SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP,
+ SIGTTIN , SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ,
+ SIGVTALRM , SIGSYS, SIGMAX = 64,
+};
+
+// Public
+typedef uint64_t sigset_t;
+
+// Public
+enum {
+ SA_SIGINFO = BIT(0),
+ SA_ONSTACK = BIT(1),
+ SA_RESETHAND = BIT(2),
+ SA_NODEFER = BIT(3),
+ SA_NOCLDWAIT = BIT(4), // unimplemented
+ SA_NOCLDSTOP = BIT(5), // unimplemented
+};
+// Public
+typedef struct siginfo_t
+{
+ int signum;
+ int sigcode;
+ struct thread* sender;
+ void* addr;
+ int status;
+ union {
+ void* ptr;
+ uintptr_t integer;
+ } udata;
+} siginfo_t;
+// Public
+typedef struct user_sigaction {
+ union {
+ void(*handler)(int signum);
+ void(*sa_sigaction)(int signum, siginfo_t* info, void* unknown);
+ } un;
+ // NOTE(oberrow): Set to __mlibc_restorer in the mlibc sysdeps.
+ uintptr_t trampoline_base; // required
+ uint32_t flags;
+} user_sigaction;
+typedef struct sigaction {
+ union {
+ void(*handler)(int signum);
+ void(*sa_sigaction)(int signum, siginfo_t* info, void* unknown);
+ } un;
+ // NOTE(oberrow): Set to __mlibc_restorer in the mlibc sysdeps.
+ uintptr_t trampoline_base; // required
+ uint32_t flags;
+ // The following fields are not to be carried to userspace.
+ // Fields of 'siginfo_t' are set with this
+ uintptr_t udata;
+ void* addr;
+ int status;
+ int sigcode;
+ struct thread* sender;
+} sigaction;
+// Internal
+typedef struct signal_header {
+ // NOTE: To get the first signal to dispatch, use __builtin_ctzll(pending & ~masked)
+ sigset_t pending;
+ sigset_t mask;
+ uintptr_t sp;
+ size_t stack_size; // Unused in the actual signal implemtation, only exists for Sys_SigAltStack.
+ mutex lock; // take when modifying this structure.
+ event event; // set when a signal runs, clear when it exits (sigreturn)
+} signal_header;
\ No newline at end of file
diff --git a/src/oboskrnl/syscall.c b/src/oboskrnl/syscall.c
index 98eed26a..da8a315b 100644
--- a/src/oboskrnl/syscall.c
+++ b/src/oboskrnl/syscall.c
@@ -89,7 +89,7 @@ void Sys_LibCLog(const char* ustr)
static handle Sys_MmFork()
{
// Zeroed in Mm_ConstructContext
- context* ctx = Mm_Allocator->Allocate(Mm_Allocator, sizeof(context), nullptr);
+ context* ctx = Allocate(Mm_Allocator, sizeof(context), nullptr);
Mm_ConstructContext(ctx);
Mm_ForkContext(ctx, Core_GetCurrentThread()->proc->ctx);
ctx->workingSet.capacity = Core_GetCurrentThread()->proc->ctx->workingSet.capacity;
@@ -165,6 +165,8 @@ obos_status Sys_SleepMS(uint64_t ms, uint64_t* uleft)
timer_tick deadline = CoreS_GetTimerTick() + CoreH_TimeFrameToTick(ms*1000);
while (deadline > CoreS_GetTimerTick())
OBOSS_SpinlockHint();
+ if (CoreS_ForceYieldOnSyscallReturn)
+ CoreS_ForceYieldOnSyscallReturn();
return OBOS_STATUS_SUCCESS;
}
@@ -285,15 +287,70 @@ obos_status Sys_IsATTY(handle desc)
return OBOS_STATUS_SUCCESS;
}
+obos_status Sys_ThreadGetStack(handle thr, void** stack_base, size_t *stack_size)
+{
+ thread* thread = HANDLE_TYPE(thr) == HANDLE_TYPE_CURRENT ? Core_GetCurrentThread() : nullptr;
+ if (!thread)
+ {
+ obos_status status = OBOS_STATUS_SUCCESS;
+ handle_desc* hnd = OBOS_HandleLookup(OBOS_CurrentHandleTable(), thr, HANDLE_TYPE_THREAD, false, &status);
+ if (obos_is_error(status))
+ {
+ OBOS_UnlockHandleTable(OBOS_CurrentHandleTable());
+ return status;
+ }
+ OBOS_UnlockHandleTable(OBOS_CurrentHandleTable());
+ thread = hnd->un.thread;
+ }
+
+ if (!stack_base && !stack_size)
+ return OBOS_STATUS_SUCCESS;
+
+ void* res_base = nullptr;
+ size_t res_size = 0;
+
+ res_base = CoreS_GetThreadStack(&thread->context);
+ res_size = CoreS_GetThreadStackSize(&thread->context);
+
+ if (stack_base)
+ memcpy_k_to_usr(stack_base, &res_base, sizeof(*stack_base));
+ if (stack_base)
+ memcpy_k_to_usr(stack_base, &res_size, sizeof(*stack_size));
+
+ return OBOS_STATUS_SUCCESS;
+}
+
+obos_status Sys_Shutdown()
+{
+ if (Core_GetCurrentThread()->proc->euid != 0)
+ return OBOS_STATUS_ACCESS_DENIED;
+ OBOS_Shutdown();
+ OBOS_UNREACHABLE;
+}
+obos_status Sys_Reboot()
+{
+ if (Core_GetCurrentThread()->proc->euid != 0)
+ return OBOS_STATUS_ACCESS_DENIED;
+ OBOS_Reboot();
+ OBOS_UNREACHABLE;
+}
+obos_status Sys_Suspend()
+{
+ if (Core_GetCurrentThread()->proc->euid != 0)
+ return OBOS_STATUS_ACCESS_DENIED;
+ OBOS_Suspend();
+ OBOS_UNREACHABLE;
+}
+
uintptr_t OBOS_SyscallTable[SYSCALL_END-SYSCALL_BEGIN] = {
(uintptr_t)Core_ExitCurrentThread,
(uintptr_t)Core_Yield,
- (uintptr_t)OBOS_Reboot,
- (uintptr_t)OBOS_Shutdown,
+ (uintptr_t)Sys_Reboot,
+ (uintptr_t)Sys_Shutdown,
(uintptr_t)Sys_HandleClose,
(uintptr_t)Sys_HandleClone,
(uintptr_t)Sys_ThreadContextCreate, // 6
- (uintptr_t)OBOS_Suspend,
+ (uintptr_t)Sys_Suspend,
(uintptr_t)Sys_ThreadOpen,
(uintptr_t)Sys_ThreadCreate,
(uintptr_t)Sys_ThreadReady,
@@ -422,6 +479,14 @@ uintptr_t OBOS_SyscallTable[SYSCALL_END-SYSCALL_BEGIN] = {
(uintptr_t)Sys_UMask,
(uintptr_t)Sys_RenameAt,
(uintptr_t)Sys_UTimeNSAt,
+ (uintptr_t)Sys_ThreadGetStack,
+ (uintptr_t)Sys_SetRESUid,
+ (uintptr_t)Sys_SetRESGid,
+ (uintptr_t)Sys_GetRESUid,
+ (uintptr_t)Sys_GetRESGid,
+ (uintptr_t)Sys_SigPending,
+ (uintptr_t)Sys_SetGroups,
+ (uintptr_t)Sys_GetGroups,
};
// Arch syscall table is defined per-arch
diff --git a/src/oboskrnl/vfs/create.c b/src/oboskrnl/vfs/create.c
index 6ca818a2..c4dae200 100644
--- a/src/oboskrnl/vfs/create.c
+++ b/src/oboskrnl/vfs/create.c
@@ -23,27 +23,6 @@
#include
#include
-static bool has_write_perm(vnode* parent)
-{
- uid current_uid = Core_GetCurrentThread()->proc->currentUID;
- uid current_gid = Core_GetCurrentThread()->proc->currentGID;
- if (parent->flags & VFLAGS_MOUNTPOINT)
- {
- drv_fs_info info = {};
- parent->un.mounted->fs_driver->driver->header.ftable.stat_fs_info(parent->un.mounted->device, &info);
- if (parent->owner_uid == current_uid || parent->group_uid == current_gid)
- return ~info.flags & FS_FLAGS_RDONLY;
- else
- return false;
- }
- if (parent->owner_uid == current_uid)
- return parent->perm.owner_write;
- else if (parent->group_uid == current_gid)
- return parent->perm.group_write;
- else
- return parent->perm.other_write;
-}
-
#ifdef __x86_64__
# include
#endif
@@ -54,17 +33,29 @@ obos_status Vfs_CreateNode(dirent* parent, const char* name, uint32_t vtype, fil
parent = Vfs_Root;
if (!name || !vtype || vtype >= VNODE_TYPE_BAD)
return OBOS_STATUS_INVALID_ARGUMENT;
+
+ obos_status status = Vfs_Access(parent->vnode,
+ false,
+ true,
+ false);
+ if (obos_is_error(status))
+ return status;
+
vnode* parent_vn = parent->vnode;
if (!parent_vn)
return OBOS_STATUS_INVALID_ARGUMENT;
if (parent_vn->vtype != VNODE_TYPE_DIR)
return OBOS_STATUS_INVALID_ARGUMENT;
- if (!has_write_perm(parent_vn))
- return OBOS_STATUS_ACCESS_DENIED;
- mount *parent_mnt = parent_vn->flags & VFLAGS_MOUNTPOINT ?
- parent_vn->un.mounted:
- parent_vn->mount_point;
- driver_ftable* ftable = &parent_mnt->fs_driver->driver->header.ftable;
+
+ mount *parent_mnt = Vfs_GetVnodeMount(parent->vnode);
+ driver_header* header = Vfs_GetVnodeDriver(parent_mnt->root->vnode);
+ if (!header)
+ return OBOS_STATUS_INTERNAL_ERROR;
+
+ driver_ftable* ftable = &header->ftable;
+ if (!ftable->remove_file)
+ return OBOS_STATUS_UNIMPLEMENTED;
+
if (!ftable->mk_file)
return OBOS_STATUS_UNIMPLEMENTED;
@@ -94,8 +85,8 @@ obos_status Vfs_CreateNode(dirent* parent, const char* name, uint32_t vtype, fil
return OBOS_STATUS_INVALID_ARGUMENT;
}
vnode* vn = Vfs_Calloc(1, sizeof(vnode));
- vn->group_uid = Core_GetCurrentThread()->proc->currentGID;
- vn->owner_uid = Core_GetCurrentThread()->proc->currentUID;
+ vn->gid = Core_GetCurrentThread()->proc->egid;
+ vn->uid = Core_GetCurrentThread()->proc->euid;
vn->perm = mode;
vn->flags = 0;
vn->vtype = vtype;
@@ -114,7 +105,7 @@ obos_status Vfs_CreateNode(dirent* parent, const char* name, uint32_t vtype, fil
OBOS_InitString(&ent->name, name);
ent->vnode = vn;
vnode* mount_vn = parent_mnt->device;
- obos_status status = OBOS_STATUS_SUCCESS;
+ status = OBOS_STATUS_SUCCESS;
if (parent_mnt->fs_driver->driver->header.flags & DRIVER_HEADER_DIRENT_CB_PATHS)
{
char* parent_path = VfsH_DirentPath(parent, parent_mnt->root);
@@ -144,19 +135,29 @@ OBOS_EXPORT obos_status Vfs_UnlinkNode(dirent* node)
return OBOS_STATUS_SUCCESS;
if (node->d_children.nChildren)
return OBOS_STATUS_IN_USE; // cannot remove a directory with children
- if (!has_write_perm(node->d_parent->vnode))
- return OBOS_STATUS_ACCESS_DENIED;
+ obos_status status = Vfs_Access(node->d_parent->vnode,
+ false,
+ true,
+ false);
+ if (obos_is_error(status))
+ return status;
- mount *parent_mnt = node->vnode->flags & VFLAGS_MOUNTPOINT ?
- node->vnode->un.mounted:
- node->vnode->mount_point;
- driver_ftable* ftable = &parent_mnt->fs_driver->driver->header.ftable;
+ mount *parent_mnt = Vfs_GetVnodeMount(node->vnode);
+ if (!parent_mnt)
+ return OBOS_STATUS_INTERNAL_ERROR;
+ OBOS_ENSURE(parent_mnt->root);
+ driver_header* header = Vfs_GetVnodeDriver(parent_mnt->root->vnode);
+ if (!header)
+ return OBOS_STATUS_INTERNAL_ERROR;
+
+ driver_ftable* ftable = &header->ftable;
if (!ftable->remove_file)
return OBOS_STATUS_UNIMPLEMENTED;
+
if (LIST_GET_NODE_COUNT(fd_list, &node->vnode->opened))
return OBOS_STATUS_IN_USE; // TODO: Handle correctly (when the last FD is closed, then free+delete the vnode)
- obos_status status = OBOS_STATUS_SUCCESS;
+ status = OBOS_STATUS_SUCCESS;
if (node->vnode->vtype == VNODE_TYPE_DIR || node->vnode->vtype == VNODE_TYPE_REG || node->vnode->vtype == VNODE_TYPE_LNK)
{
@@ -212,6 +213,13 @@ obos_status Vfs_RenameNode(dirent* node, dirent* newparent, const char* name)
if (!header)
return OBOS_STATUS_INVALID_ARGUMENT;
+ obos_status status = Vfs_Access((newparent ? newparent : node->d_parent)->vnode,
+ false,
+ true,
+ false);
+ if (obos_is_error(status))
+ return status;
+
// Rename the entry
if (!newparent || newparent == node->d_parent)
{
@@ -268,7 +276,7 @@ obos_status Vfs_RenameNode(dirent* node, dirent* newparent, const char* name)
// Move and rename the entry.
- obos_status status = OBOS_STATUS_SUCCESS;
+ status = OBOS_STATUS_SUCCESS;
if (header->flags & DRIVER_HEADER_DIRENT_CB_PATHS)
{
char* node_path = VfsH_DirentPath(node, Vfs_Root);
diff --git a/src/oboskrnl/vfs/dirent.c b/src/oboskrnl/vfs/dirent.c
index 4c110ce8..25ea9463 100644
--- a/src/oboskrnl/vfs/dirent.c
+++ b/src/oboskrnl/vfs/dirent.c
@@ -42,6 +42,7 @@ static vnode* create_vnode(mount* mountpoint, dev_desc desc, file_type* t)
obos_status status = mountpoint->fs_driver->driver->header.ftable.vnode_search((void**)&vn, desc, mountpoint->fs_driver);
if (obos_is_success(status))
{
+ OBOS_ENSURE(vn);
vn->mount_point = mountpoint;
if (t)
{
@@ -303,6 +304,7 @@ static dirent* lookup(const char* path, dirent* root_par, bool only_cache)
if (!last)
break;
mountpoint = last->vnode->flags & VFLAGS_MOUNTPOINT ? last->vnode->un.mounted : last->vnode->mount_point;
+ fs_driver = mountpoint->fs_driver;
currentPath = VfsH_DirentPath(last, mountpoint->root);
currentPathLen = strlen(currentPath);
if (currentPath[currentPathLen-1] != '/')
@@ -312,6 +314,11 @@ static dirent* lookup(const char* path, dirent* root_par, bool only_cache)
currentPath[++currentPathLen] = 0;
}
}
+ else
+ {
+ mountpoint = last->vnode->flags & VFLAGS_MOUNTPOINT ? last->vnode->un.mounted : last->vnode->mount_point;
+ fs_driver = mountpoint->fs_driver;
+ }
tok += str_search(tok, '/');
size_t currentPathLen2 = strlen(tok)-1;
@@ -461,8 +468,8 @@ vnode* Drv_AllocateVNode(driver_id* drv, dev_desc desc, size_t filesize, vdev**
vn->inode = devfs_inode++;
vn->perm = default_fileperm;
vn->vtype = type;
- vn->group_uid = ROOT_GID;
- vn->owner_uid = ROOT_UID;
+ vn->gid = ROOT_GID;
+ vn->uid = ROOT_UID;
vn->times.access = get_current_time();
vn->times.birth = vn->times.access;
vn->times.change = vn->times.access;
@@ -512,7 +519,8 @@ static iterate_decision populate_cb(dev_desc desc, size_t blkSize, size_t blkCou
child = child->d_next_child;
}
- mount* point = dent->vnode->mount_point ? dent->vnode->mount_point : dent->vnode->un.mounted;
+
+ mount* point = Vfs_GetVnodeMount(dent->vnode);
vnode* vn = create_vnode(point, desc, nullptr);
dirent* new = Vfs_Calloc(1, sizeof(dirent));
OBOS_StringSetAllocator(&new->name, Vfs_Allocator);
@@ -525,12 +533,16 @@ static iterate_decision populate_cb(dev_desc desc, size_t blkSize, size_t blkCou
void Vfs_PopulateDirectory(dirent* dent)
{
- mount* point = dent->vnode->mount_point ? dent->vnode->mount_point : dent->vnode->un.mounted;
- const driver_header* driver = &point->fs_driver->driver->header;
+ mount* point = Vfs_GetVnodeMount(dent->vnode);
+ driver_header* driver = Vfs_GetVnodeDriver(dent->vnode);
if (dent->vnode->vtype != VNODE_TYPE_DIR)
return;
if (driver->ftable.list_dir)
- OBOS_ENSURE(obos_is_success(driver->ftable.list_dir(dent->vnode->desc, point->device, populate_cb, dent)));
+ {
+ obos_status status = driver->ftable.list_dir(dent->vnode->flags & VFLAGS_MOUNTPOINT ? UINTPTR_MAX : dent->vnode->desc, point->device, populate_cb, dent);
+ if (obos_is_error(status))
+ OBOS_Error("list_dir returned %d!\n", status);
+ }
else
OBOS_Error("driver->ftable.list_dir == nullptr!\n");
}
@@ -650,15 +662,7 @@ char* VfsH_DirentPath(dirent* ent, dirent* relative_to)
static bool check_chdir_perms(dirent* ent)
{
- uid uid = Core_GetCurrentThread()->proc->currentUID;
- gid gid = Core_GetCurrentThread()->proc->currentGID;
-
- if (uid == ent->vnode->owner_uid)
- return ent->vnode->perm.owner_exec;
- else if (gid == ent->vnode->group_uid)
- return ent->vnode->perm.group_exec;
- else
- return ent->vnode->perm.other_exec;
+ return Vfs_Access(ent->vnode, false, false, true) == OBOS_STATUS_SUCCESS;
}
obos_status VfsH_Chdir(void* target_, const char *path)
@@ -785,5 +789,73 @@ mount* Vfs_GetVnodeMount(vnode* vn)
return nullptr;
if (vn->vtype == VNODE_TYPE_FIFO || vn->vtype == VNODE_TYPE_SOCK)
return nullptr;
- return vn->mount_point ? vn->mount_point : vn->un.mounted;
+ return vn->flags & VFLAGS_MOUNTPOINT ? vn->un.mounted : vn->mount_point;
+}
+
+obos_status Vfs_Access(vnode* vn, bool read, bool write, bool exec)
+{
+ uid euid = Core_GetCurrentThread() && Core_GetCurrentThread()->proc ? Core_GetCurrentThread()->proc->euid : 0;
+ gid egid = Core_GetCurrentThread() && Core_GetCurrentThread()->proc ? Core_GetCurrentThread()->proc->egid : 0;
+ obos_status status = Vfs_AccessAs(euid, egid, vn, read, write, exec);
+ if (obos_is_success(status))
+ return OBOS_STATUS_SUCCESS;
+ if (!Core_GetCurrentThread() || !Core_GetCurrentThread()->proc)
+ return status;
+ if (status == OBOS_STATUS_READ_ONLY)
+ return OBOS_STATUS_READ_ONLY;
+ for (size_t i = 0; i < Core_GetCurrentThread()->proc->groups.nEntries; i++)
+ {
+ status = Vfs_AccessAs(euid, Core_GetCurrentThread()->proc->groups.list[i], vn, read, write, exec);
+ if (obos_is_success(status))
+ return OBOS_STATUS_SUCCESS;
+ }
+ return status;
}
+
+obos_status Vfs_AccessAs(uid asUid, gid asGid, vnode* vn, bool read, bool write, bool exec)
+{
+ if (write)
+ {
+ drv_fs_info info = {};
+ driver_header* header = Vfs_GetVnodeDriver(vn);
+ mount* mount = Vfs_GetVnodeMount(vn);
+ if (header && mount && header->ftable.stat_fs_info)
+ header->ftable.stat_fs_info(mount->device, &info);
+ if (info.flags & FS_FLAGS_RDONLY)
+ return OBOS_STATUS_READ_ONLY;
+ }
+
+ if (vn->uid == asUid || asUid == 0)
+ {
+ if (!vn->perm.owner_read && read)
+ return OBOS_STATUS_ACCESS_DENIED;
+ else if (!vn->perm.owner_write && write)
+ return OBOS_STATUS_ACCESS_DENIED;
+ else if (!vn->perm.owner_exec && exec)
+ return OBOS_STATUS_ACCESS_DENIED;
+ else
+ return OBOS_STATUS_SUCCESS;
+ }
+ else if (vn->gid == asGid)
+ {
+ if (!vn->perm.group_read && read)
+ return OBOS_STATUS_ACCESS_DENIED;
+ else if (!vn->perm.group_write && write)
+ return OBOS_STATUS_ACCESS_DENIED;
+ else if (!vn->perm.group_exec && exec)
+ return OBOS_STATUS_ACCESS_DENIED;
+ else
+ return OBOS_STATUS_SUCCESS;
+ }
+ else
+ {
+ if (!vn->perm.other_read && read)
+ return OBOS_STATUS_ACCESS_DENIED;
+ else if (!vn->perm.other_write && write)
+ return OBOS_STATUS_ACCESS_DENIED;
+ else if (!vn->perm.other_exec && exec)
+ return OBOS_STATUS_ACCESS_DENIED;
+ else
+ return OBOS_STATUS_SUCCESS;
+ }
+}
\ No newline at end of file
diff --git a/src/oboskrnl/vfs/dummy_devices.c b/src/oboskrnl/vfs/dummy_devices.c
index 0275881d..a4e043d5 100644
--- a/src/oboskrnl/vfs/dummy_devices.c
+++ b/src/oboskrnl/vfs/dummy_devices.c
@@ -417,8 +417,8 @@ static void init_desc(dev_desc desc)
dirent* ent = Vfs_Calloc(1, sizeof(dirent));
vnode* vn = Vfs_Calloc(1, sizeof(vnode));
- vn->owner_uid = 0;
- vn->group_uid = 0;
+ vn->uid = 0;
+ vn->gid = 0;
vn->desc = desc;
get_max_blk_count(desc, &vn->filesize);
diff --git a/src/oboskrnl/vfs/fd.c b/src/oboskrnl/vfs/fd.c
index 33f98597..533eba8a 100644
--- a/src/oboskrnl/vfs/fd.c
+++ b/src/oboskrnl/vfs/fd.c
@@ -91,46 +91,19 @@ OBOS_EXPORT obos_status Vfs_FdOpenVnode(fd* const desc, void* vn, uint32_t oflag
if (vnode->vtype == VNODE_TYPE_DIR || vnode->vtype == VNODE_TYPE_LNK)
return OBOS_STATUS_NOT_A_FILE;
desc->vn = vnode;
- desc->flags |= FD_FLAGS_OPEN;
- desc->flags |= FD_FLAGS_READ;
- desc->flags |= FD_FLAGS_WRITE;
- if (desc->vn->owner_uid == Core_GetCurrentThread()->proc->currentUID || Core_GetCurrentThread()->proc->currentUID == 0)
- {
- // We have owner perms.
- struct vnode* const vn = desc->vn;
- if (!vn->perm.owner_read)
- desc->flags &= ~FD_FLAGS_READ;
- if (!vn->perm.owner_write)
- desc->flags &= ~FD_FLAGS_WRITE;
- if (oflags & FD_OFLAGS_EXECUTE && !vn->perm.owner_exec)
- return OBOS_STATUS_ACCESS_DENIED;
- }
- else if (desc->vn->group_uid == Core_GetCurrentThread()->proc->currentGID)
- {
- // We have group perms.
- struct vnode* const vn = desc->vn;
- if (!vn->perm.group_read)
- desc->flags &= ~FD_FLAGS_READ;
- if (!vn->perm.group_write)
- desc->flags &= ~FD_FLAGS_WRITE;
- if (oflags & FD_OFLAGS_EXECUTE && !vn->perm.group_exec)
- return OBOS_STATUS_ACCESS_DENIED;
- }
- else
- {
- // We have other perms.
- struct vnode* const vn = desc->vn;
- if (!vn->perm.other_read)
- desc->flags &= ~FD_FLAGS_READ;
- if (!vn->perm.other_write)
- desc->flags &= ~FD_FLAGS_WRITE;
- if (oflags & FD_OFLAGS_EXECUTE && !vn->perm.other_exec)
- return OBOS_STATUS_ACCESS_DENIED;
- }
- if (~oflags & FD_OFLAGS_READ)
- desc->flags &= ~FD_FLAGS_READ;
- if (~oflags & FD_OFLAGS_WRITE)
- desc->flags &= ~FD_FLAGS_WRITE;
+
+ obos_status status = Vfs_Access(vnode,
+ oflags & FD_OFLAGS_READ,
+ oflags & FD_OFLAGS_WRITE,
+ oflags & FD_OFLAGS_EXECUTE);
+ if (obos_is_error(status))
+ return status;
+
+ if (oflags & FD_OFLAGS_READ)
+ desc->flags |= FD_FLAGS_READ;
+ if (oflags & FD_OFLAGS_WRITE)
+ desc->flags |= FD_FLAGS_WRITE;
+
if (oflags & FD_OFLAGS_UNCACHED)
desc->flags |= FD_FLAGS_UNCACHED;
if (oflags & FD_OFLAGS_NOEXEC)
@@ -139,6 +112,11 @@ OBOS_EXPORT obos_status Vfs_FdOpenVnode(fd* const desc, void* vn, uint32_t oflag
desc->flags |= FD_FLAGS_UNCACHED;
if (vnode->flags & VFLAGS_EVENT_DEV)
desc->flags &= ~(FD_FLAGS_READ|FD_FLAGS_WRITE);
+ else
+ {
+ if (!(desc->flags & (FD_FLAGS_WRITE|FD_FLAGS_READ)))
+ return OBOS_STATUS_ACCESS_DENIED;
+ }
desc->vn->refs++;
LIST_APPEND(fd_list, &desc->vn->opened, desc);
if (~desc->vn->flags & VFLAGS_EVENT_DEV)
diff --git a/src/oboskrnl/vfs/fd_sys.c b/src/oboskrnl/vfs/fd_sys.c
index 66f6e654..50ab5462 100644
--- a/src/oboskrnl/vfs/fd_sys.c
+++ b/src/oboskrnl/vfs/fd_sys.c
@@ -15,6 +15,7 @@
#include
+#include
#include
#include
#include
@@ -89,6 +90,10 @@ static file_perm unix_to_obos_mode(uint32_t mode, bool respect_umask)
real_mode.owner_write = true;
if (mode & 0400)
real_mode.owner_read = true;
+ if (mode & 04000)
+ real_mode.set_uid = true;
+ if (mode & 02000)
+ real_mode.set_gid = true;
return real_mode;
}
obos_status Sys_FdOpenEx(handle desc, const char* upath, uint32_t oflags, uint32_t mode)
@@ -287,6 +292,9 @@ obos_status Sys_FdWrite(handle desc, const void* buf, size_t nBytes, size_t* nWr
Mm_VirtualMemoryFree(&Mm_KernelContext, kbuf, nBytes);
+ if (CoreS_ForceYieldOnSyscallReturn)
+ CoreS_ForceYieldOnSyscallReturn();
+
return OBOS_STATUS_SUCCESS;
}
@@ -323,6 +331,9 @@ obos_status Sys_FdRead(handle desc, void* buf, size_t nBytes, size_t* nRead)
Mm_VirtualMemoryFree(&Mm_KernelContext, kbuf, nBytes);
+ if (CoreS_ForceYieldOnSyscallReturn)
+ CoreS_ForceYieldOnSyscallReturn();
+
return OBOS_STATUS_SUCCESS;
}
@@ -366,6 +377,9 @@ obos_status Sys_FdPWrite(handle desc, const void* buf, size_t nBytes, size_t* nW
Mm_VirtualMemoryFree(&Mm_KernelContext, kbuf, nBytes);
+ if (CoreS_ForceYieldOnSyscallReturn)
+ CoreS_ForceYieldOnSyscallReturn();
+
return OBOS_STATUS_SUCCESS;
}
@@ -399,7 +413,10 @@ obos_status Sys_FdPRead(handle desc, void* buf, size_t nBytes, size_t* nRead, si
}
Mm_VirtualMemoryFree(&Mm_KernelContext, kbuf, nBytes);
-
+
+ if (CoreS_ForceYieldOnSyscallReturn)
+ CoreS_ForceYieldOnSyscallReturn();
+
return OBOS_STATUS_SUCCESS;
}
@@ -506,6 +523,8 @@ obos_status Sys_FdIoctl(handle desc, uintptr_t request, void* argp, size_t sz_ar
obos_status Sys_FdFlush(handle desc)
{
+ if (HANDLE_TYPE(desc) == HANDLE_TYPE_DIRENT)
+ return OBOS_STATUS_SUCCESS;
OBOS_LockHandleTable(OBOS_CurrentHandleTable());
obos_status status = OBOS_STATUS_SUCCESS;
handle_desc* fd = OBOS_HandleLookup(OBOS_CurrentHandleTable(), desc, HANDLE_TYPE_FD, false, &status);
@@ -607,6 +626,10 @@ obos_status Sys_Stat(int fsfdt, handle desc, const char* upath, int flags, struc
return status;
st.st_size = to_stat->filesize;
st.st_mode = 0;
+ if (to_stat->perm.set_uid)
+ st.st_mode |= 04000;
+ if (to_stat->perm.set_gid)
+ st.st_mode |= 02000;
if (to_stat->perm.owner_read)
st.st_mode |= 0400;
if (to_stat->perm.owner_write)
@@ -665,8 +688,8 @@ obos_status Sys_Stat(int fsfdt, handle desc, const char* upath, int flags, struc
st.st_atim.tv_nsec = 0;
st.st_ctim.tv_nsec = 0;
st.st_mtim.tv_nsec = 0;
- st.st_gid = to_stat->group_uid;
- st.st_uid = to_stat->owner_uid;
+ st.st_gid = to_stat->gid;
+ st.st_uid = to_stat->uid;
st.st_ino = to_stat->inode;
if (to_stat->flags & VFLAGS_EVENT_DEV && ~to_stat->flags & VFLAGS_DRIVER_DEAD)
goto done;
@@ -790,6 +813,8 @@ obos_status Sys_ReadLinkAt(handle parent, const char *upath, void* ubuff, size_t
if (length)
memcpy_k_to_usr(length, &len, sizeof(size_t));
+ Mm_VirtualMemoryFree(&Mm_KernelContext, buff, max_size);
+
return OBOS_STATUS_SUCCESS;
}
@@ -847,6 +872,16 @@ handle Sys_OpenDir(const char* upath, obos_status *statusp)
dent = VfsH_FollowLink(dent);
+ if (dent->vnode)
+ {
+ obos_status status = Vfs_Access(dent->vnode,
+ true,
+ false,
+ false);
+ if (obos_is_error(status))
+ return status;
+ }
+
Vfs_PopulateDirectory(dent);
handle_desc* desc = nullptr;
@@ -1309,8 +1344,8 @@ obos_status Sys_CreateNamedPipe(handle dirfd, const char* upath, int mode, size_
fifo_name = path;
}
- gid current_gid = Core_GetCurrentThread()->proc->currentGID;
- uid current_uid = Core_GetCurrentThread()->proc->currentUID;
+ gid current_gid = Core_GetCurrentThread()->proc->egid;
+ uid current_uid = Core_GetCurrentThread()->proc->euid;
status = Vfs_CreateNamedPipe(perm, current_gid, current_uid, parent, fifo_name, pipesize);
Free(OBOS_KernelAllocator, path, sz_path);
@@ -1377,7 +1412,9 @@ obos_status Sys_PSelect(size_t nFds, uint8_t* uread_set, uint8_t *uwrite_set, ui
if (!uread_set && !uwrite_set && !uexcept_set)
return OBOS_STATUS_SUCCESS; // We waited for nothing, so assume success.
OBOS_UNUSED(uexcept_set && "We can't really monitor exceptional cases...");
-
+ if (uexcept_set)
+ return OBOS_STATUS_UNIMPLEMENTED;
+
uint8_t *read_set = Mm_MapViewOfUserMemory(CoreS_GetCPULocalPtr()->currentContext, uread_set, nullptr, 128, 0, true, &status);
if (obos_is_error(status) && uread_set)
return status;
@@ -1388,7 +1425,6 @@ obos_status Sys_PSelect(size_t nFds, uint8_t* uread_set, uint8_t *uwrite_set, ui
return status;
}
-
sigset_t sigmask = 0, oldmask = 0;
if (extra.sigmask)
{
@@ -1479,7 +1515,13 @@ obos_status Sys_PSelect(size_t nFds, uint8_t* uread_set, uint8_t *uwrite_set, ui
waitable_list[unsignaledIRPIndex] = WAITABLE_OBJECT(tm_evnt);
}
- Core_WaitOnObjects(nWaitableObjects, waitable_list, nullptr);
+ status = Core_WaitOnObjects(nWaitableObjects, waitable_list, nullptr);
+ if (obos_is_error(status))
+ {
+ Core_CancelTimer(&tm);
+ CoreH_FreeDPC(&tm.handler_dpc, false);
+ goto timeout;
+ }
if (tm.mode == TIMER_EXPIRED)
{
// Just In Case
@@ -1509,6 +1551,10 @@ obos_status Sys_PSelect(size_t nFds, uint8_t* uread_set, uint8_t *uwrite_set, ui
out2:
Mm_VirtualMemoryFree(CoreS_GetCPULocalPtr()->currentContext, read_set, 128);
Mm_VirtualMemoryFree(CoreS_GetCPULocalPtr()->currentContext, write_set, 128);
+
+ if (CoreS_ForceYieldOnSyscallReturn)
+ CoreS_ForceYieldOnSyscallReturn();
+
return status;
}
@@ -1665,7 +1711,13 @@ obos_status Sys_PPoll(struct pollfd* ufds, size_t nFds, const uintptr_t* utimeou
}
struct waitable_header* signaled = nullptr;
- Core_WaitOnObjects(n_waitable_objects, waitable_list, &signaled);
+ status = Core_WaitOnObjects(n_waitable_objects, waitable_list, &signaled);
+ if (obos_is_error(status))
+ {
+ Core_CancelTimer(&tm);
+ CoreH_FreeDPC(&tm.handler_dpc, false);
+ goto out;
+ }
if (signaled == WAITABLE_OBJECT(tm_evnt))
{
Core_CancelTimer(&tm);
@@ -1689,6 +1741,9 @@ obos_status Sys_PPoll(struct pollfd* ufds, size_t nFds, const uintptr_t* utimeou
OBOS_SigProcMask(SIG_SETMASK, &oldmask, nullptr);
Mm_VirtualMemoryFree(&Mm_KernelContext, fds, nFds*sizeof(struct pollfd));
+ if (CoreS_ForceYieldOnSyscallReturn)
+ CoreS_ForceYieldOnSyscallReturn();
+
return status;
}
@@ -2466,6 +2521,9 @@ obos_status Sys_SendTo(handle desc, const void* buffer, size_t size, int flags,
OBOS_MAYBE_UNUSED fail1:
Mm_VirtualMemoryFree(&Mm_KernelContext, (void*)params, sizeof(*params));
+ if (CoreS_ForceYieldOnSyscallReturn)
+ CoreS_ForceYieldOnSyscallReturn();
+
return status;
}
@@ -2518,6 +2576,9 @@ obos_status Sys_RecvFrom(handle desc, void* buffer, size_t size, int flags, stru
OBOS_MAYBE_UNUSED fail1:
Mm_VirtualMemoryFree(&Mm_KernelContext, params, sizeof(*params));
+ if (CoreS_ForceYieldOnSyscallReturn)
+ CoreS_ForceYieldOnSyscallReturn();
+
return status;
}
@@ -2574,6 +2635,9 @@ obos_status Sys_Accept(handle desc, handle empty_fd, sockaddr* uaddr_ptr, size_t
OBOS_MAYBE_UNUSED fail1:
Free(OBOS_KernelAllocator, buf, addr_length);
+ if (CoreS_ForceYieldOnSyscallReturn)
+ CoreS_ForceYieldOnSyscallReturn();
+
return status;
}
@@ -2626,6 +2690,9 @@ obos_status Sys_Connect(handle desc, const sockaddr *uaddr, size_t addr_length)
OBOS_MAYBE_UNUSED fail1:
Free(OBOS_KernelAllocator, buf, addr_length);
+ if (CoreS_ForceYieldOnSyscallReturn)
+ CoreS_ForceYieldOnSyscallReturn();
+
return status;
}
@@ -2781,17 +2848,40 @@ obos_status Sys_FChmodAt(handle dirfd, const char* upathname, int mode, int flag
pathname = ZeroAllocate(OBOS_KernelAllocator, sz_path+1, sizeof(char), nullptr);
OBOSH_ReadUserString(upathname, pathname, nullptr);
+ vnode* target = nullptr;
+
dirent* parent = nullptr;
const char* name = nullptr;
if (dirfd != AT_FDCWD)
{
+ if (HANDLE_TYPE(dirfd) != HANDLE_TYPE_DIRENT && HANDLE_TYPE(dirfd) != HANDLE_TYPE_FD)
+ {
+ status = OBOS_STATUS_INVALID_ARGUMENT;
+ goto fail;
+ }
+ if (HANDLE_TYPE(dirfd) == HANDLE_TYPE_FD && strlen(pathname))
+ {
+ status = OBOS_STATUS_INVALID_ARGUMENT;
+ goto fail;
+ }
OBOS_LockHandleTable(OBOS_CurrentHandleTable());
- handle_desc* desc = OBOS_HandleLookup(OBOS_CurrentHandleTable(), dirfd, HANDLE_TYPE_DIRENT, false, &status);
+ handle_desc* desc = OBOS_HandleLookup(OBOS_CurrentHandleTable(), dirfd, 0, true, &status);
if (obos_is_error(status))
{
OBOS_UnlockHandleTable(OBOS_CurrentHandleTable());
goto fail;
}
+ if (HANDLE_TYPE(dirfd) == HANDLE_TYPE_FD)
+ {
+ target = desc->un.fd->vn;
+ OBOS_UnlockHandleTable(OBOS_CurrentHandleTable());
+ if (!target)
+ {
+ status = OBOS_STATUS_INVALID_ARGUMENT;
+ goto fail;
+ }
+ goto have_target;
+ }
parent = desc->un.dirent->parent;
OBOS_UnlockHandleTable(OBOS_CurrentHandleTable());
@@ -2823,18 +2913,22 @@ obos_status Sys_FChmodAt(handle dirfd, const char* upathname, int mode, int flag
name = pathname;
}
- dirent* target = VfsH_DirentLookupFrom(name, parent);
- if (!target)
+ dirent* targetd = VfsH_DirentLookupFrom(name, parent);
+ if (!targetd)
{
status = OBOS_STATUS_NOT_FOUND;
goto fail;
}
if (~flags & AT_SYMLINK_NOFOLLOW)
- target = VfsH_FollowLink(target);
+ targetd = VfsH_FollowLink(targetd);
// NOTE(oberrow): AT_EMPTY_PATH is the default on obos, and can actually not be
// changed, because of the nature of the lookup() function
+
+ target = targetd->vnode;
+
+ have_target:
- if (target->vnode->owner_uid != Sys_GetUid() && Sys_GetUid() != ROOT_UID)
+ if (target->uid != Sys_GetUid() && Sys_GetUid() != ROOT_UID)
{
status = OBOS_STATUS_ACCESS_DENIED;
goto fail;
@@ -2842,18 +2936,19 @@ obos_status Sys_FChmodAt(handle dirfd, const char* upathname, int mode, int flag
file_perm real_mode = unix_to_obos_mode(mode, true);
- driver_header* header = Vfs_GetVnodeDriver(target->vnode);
+ mount* mount = Vfs_GetVnodeMount(target);
+ driver_header* header = Vfs_GetVnodeDriver(mount->root->vnode);
if (!header)
{
status = OBOS_STATUS_INTERNAL_ERROR;
goto fail;
}
- status = !header->ftable.set_file_perms ? OBOS_STATUS_UNIMPLEMENTED : header->ftable.set_file_perms(target->vnode->desc, real_mode);
+ status = !header->ftable.set_file_perms ? OBOS_STATUS_UNIMPLEMENTED : header->ftable.set_file_perms(target->desc, real_mode);
if (obos_is_error(status))
goto fail;
- target->vnode->perm = real_mode;
+ target->perm = real_mode;
fail:
Free(OBOS_KernelAllocator, pathname, sz_path);
@@ -2869,24 +2964,44 @@ obos_status Sys_FChownAt(handle dirfd, const char *upathname, uid owner, gid gro
size_t sz_path = 0;
status = OBOSH_ReadUserString(upathname, nullptr, &sz_path);
if (obos_is_error(status))
- {
- Free(OBOS_KernelAllocator, pathname, sz_path);
return status;
- }
pathname = ZeroAllocate(OBOS_KernelAllocator, sz_path+1, sizeof(char), nullptr);
OBOSH_ReadUserString(upathname, pathname, nullptr);
+ vnode* target = nullptr;
+
dirent* parent = nullptr;
const char* name = nullptr;
if (dirfd != AT_FDCWD)
{
+ if (HANDLE_TYPE(dirfd) != HANDLE_TYPE_DIRENT && HANDLE_TYPE(dirfd) != HANDLE_TYPE_FD)
+ {
+ status = OBOS_STATUS_INVALID_ARGUMENT;
+ goto fail;
+ }
+ if (HANDLE_TYPE(dirfd) == HANDLE_TYPE_FD && strlen(pathname))
+ {
+ status = OBOS_STATUS_INVALID_ARGUMENT;
+ goto fail;
+ }
OBOS_LockHandleTable(OBOS_CurrentHandleTable());
- handle_desc* desc = OBOS_HandleLookup(OBOS_CurrentHandleTable(), dirfd, HANDLE_TYPE_DIRENT, false, &status);
+ handle_desc* desc = OBOS_HandleLookup(OBOS_CurrentHandleTable(), dirfd, 0, true, &status);
if (obos_is_error(status))
{
OBOS_UnlockHandleTable(OBOS_CurrentHandleTable());
goto fail;
}
+ if (HANDLE_TYPE(dirfd) == HANDLE_TYPE_FD)
+ {
+ target = desc->un.fd->vn;
+ OBOS_UnlockHandleTable(OBOS_CurrentHandleTable());
+ if (!target)
+ {
+ status = OBOS_STATUS_INVALID_ARGUMENT;
+ goto fail;
+ }
+ goto have_target;
+ }
parent = desc->un.dirent->parent;
OBOS_UnlockHandleTable(OBOS_CurrentHandleTable());
@@ -2918,38 +3033,43 @@ obos_status Sys_FChownAt(handle dirfd, const char *upathname, uid owner, gid gro
name = pathname;
}
- dirent* target = VfsH_DirentLookupFrom(name, parent);
- if (!target)
+ dirent* targetd = VfsH_DirentLookupFrom(name, parent);
+ if (!targetd)
{
status = OBOS_STATUS_NOT_FOUND;
goto fail;
}
if (~flags & AT_SYMLINK_NOFOLLOW)
- target = VfsH_FollowLink(target);
+ targetd = VfsH_FollowLink(targetd);
// NOTE(oberrow): AT_EMPTY_PATH is the default on obos, and can actually not be
// changed, because of the nature of the lookup() function
+
+ target = targetd->vnode;
+
+ have_target:
+ OBOS_ENSURE(target);
- if (target->vnode->owner_uid != Sys_GetUid() && Sys_GetUid() != ROOT_UID)
+ if (Sys_GetUid() != ROOT_UID)
{
status = OBOS_STATUS_ACCESS_DENIED;
goto fail;
}
- driver_header* header = Vfs_GetVnodeDriver(target->vnode);
+ driver_header* header = Vfs_GetVnodeDriver(target);
if (!header)
{
status = OBOS_STATUS_INTERNAL_ERROR;
goto fail;
}
- status = !header->ftable.set_file_owner ? OBOS_STATUS_UNIMPLEMENTED : header->ftable.set_file_owner(target->vnode->desc, owner, group);
+ status = !header->ftable.set_file_owner ? OBOS_STATUS_UNIMPLEMENTED : header->ftable.set_file_owner(target->desc, owner, group);
if (obos_is_error(status))
goto fail;
if (owner != -1)
- target->vnode->owner_uid = owner;
+ target->uid = owner;
if (group != -1)
- target->vnode->group_uid = group;
+ target->gid = group;
fail:
Free(OBOS_KernelAllocator, pathname, sz_path);
diff --git a/src/oboskrnl/vfs/local_socket.c b/src/oboskrnl/vfs/local_socket.c
index 872769f8..2091c18e 100644
--- a/src/oboskrnl/vfs/local_socket.c
+++ b/src/oboskrnl/vfs/local_socket.c
@@ -371,7 +371,9 @@ static obos_status stream_accept(socket_desc* socket, struct sockaddr* addr, siz
if (!Core_EventGetState(&s->serv.doorbell) && nonblocking)
return OBOS_STATUS_WOULD_BLOCK;
- Core_WaitOnObject(WAITABLE_OBJECT(s->serv.doorbell));
+ obos_status status = Core_WaitOnObject(WAITABLE_OBJECT(s->serv.doorbell));
+ if (obos_is_error(status))
+ return status;
Core_EventClear(&s->serv.doorbell);
Core_MutexAcquire(&s->serv.lock);
diff --git a/src/oboskrnl/vfs/mount.c b/src/oboskrnl/vfs/mount.c
index c269bc88..297b7634 100644
--- a/src/oboskrnl/vfs/mount.c
+++ b/src/oboskrnl/vfs/mount.c
@@ -183,6 +183,8 @@ obos_status Vfs_Mount(const char* at_, vnode* on, vdev* fs_driver, mount** pMoun
at->vnode->un.mounted = mountpoint;
// at->vnode->mount_point = mountpoint;
at->vnode->flags |= VFLAGS_MOUNTPOINT;
+ mountpoint->old_root_desc = at->vnode->desc;
+ at->vnode->desc = UINTPTR_MAX;
mountpoint->root = at;
mountpoint->lock = MUTEX_INITIALIZE();
// uintptr_t udata[3] = {
@@ -313,6 +315,7 @@ obos_status Vfs_Unmount(mount* what)
Vfs_Root->vnode->mount_point = nullptr;
Vfs_Root->vnode->un.mounted = nullptr;
}
+ what->root->vnode->desc = what->old_root_desc;
what->awaitingFree = true;
if (!what->nWaiting)
Vfs_Free(what);
diff --git a/src/oboskrnl/vfs/mount.h b/src/oboskrnl/vfs/mount.h
index 0c0bb862..5de4f51b 100644
--- a/src/oboskrnl/vfs/mount.h
+++ b/src/oboskrnl/vfs/mount.h
@@ -23,6 +23,7 @@ typedef struct mount
LIST_NODE(mount_list, struct mount) node;
mutex lock;
dirent* root;
+ dev_desc old_root_desc;
vdev* fs_driver;
vnode* device; // the block device the filesystem is situated on.
vnode* mounted_on;
diff --git a/src/oboskrnl/vfs/pagecache.h b/src/oboskrnl/vfs/pagecache.h
index a962f489..c842d741 100644
--- a/src/oboskrnl/vfs/pagecache.h
+++ b/src/oboskrnl/vfs/pagecache.h
@@ -31,6 +31,8 @@ static inline page* VfsH_PageCacheCreateEntry(vnode* vn, size_t offset)
page* phys = MmH_PgAllocatePhysical(false, false);
phys->backing_vn = vn;
phys->file_offset = offset;
+ phys->file_offset -= (phys->file_offset % OBOS_PAGE_SIZE);
+ phys->end_offset = phys->file_offset + OBOS_PAGE_SIZE;
RB_INSERT(pagecache_tree, &vn->cache, phys);
driver_header* driver = Vfs_GetVnodeDriver(vn);
if (!driver) return nullptr;
diff --git a/src/oboskrnl/vfs/pipe.c b/src/oboskrnl/vfs/pipe.c
index 34e27764..3be564d1 100644
--- a/src/oboskrnl/vfs/pipe.c
+++ b/src/oboskrnl/vfs/pipe.c
@@ -148,7 +148,7 @@ static obos_status write_sync(dev_desc desc, const void* buf, size_t blkCount, s
else
{
OBOS_Kill(Core_GetCurrentThread(), Core_GetCurrentThread(), SIGPIPE);
- return OBOS_STATUS_SUCCESS;
+ return OBOS_STATUS_PIPE_CLOSED;
}
}
@@ -159,7 +159,11 @@ static obos_status write_sync(dev_desc desc, const void* buf, size_t blkCount, s
const char* write_buf = buf;
obos_status status = OBOS_STATUS_SUCCESS;
while ((written_count += tmp) < blkCount && obos_is_success(status))
+ {
+ if (Core_GetCurrentThread()->signal_info && Core_GetCurrentThread()->signal_info->pending & BIT(SIGPIPE-1))
+ break;
status = write_sync(desc, write_buf + written_count, (blkCount - written_count) % pipe->size, 0, &tmp);
+ }
if (nBlkWritten)
*nBlkWritten = written_count;
return status;
@@ -171,7 +175,9 @@ static obos_status write_sync(dev_desc desc, const void* buf, size_t blkCount, s
pipe_ready_count(pipe, &ready_count);
if ((pipe->size - ready_count) >= blkCount)
break;
- Core_WaitOnObject(WAITABLE_OBJECT(pipe->write_evnt));
+ obos_status status = Core_WaitOnObject(WAITABLE_OBJECT(pipe->write_evnt));
+ if (obos_is_error(status))
+ return status;
}
pipe_write(pipe, buf, blkCount, nBlkWritten);
@@ -436,8 +442,8 @@ obos_status Vfs_CreateNamedPipe(file_perm perm, gid group_uid, uid owner_uid, di
dirent* ent = Vfs_Calloc(1, sizeof(dirent));
vnode* vn = Vfs_Calloc(1, sizeof(vnode));
desc->vn = vn;
- vn->owner_uid = owner_uid;
- vn->group_uid = group_uid;
+ vn->uid = owner_uid;
+ vn->gid = group_uid;
vn->desc = (uintptr_t)desc;
vn->perm = perm;
vn->vtype = VNODE_TYPE_FIFO;
diff --git a/src/oboskrnl/vfs/socket.c b/src/oboskrnl/vfs/socket.c
index c4ead232..6d255377 100644
--- a/src/oboskrnl/vfs/socket.c
+++ b/src/oboskrnl/vfs/socket.c
@@ -113,6 +113,8 @@ static obos_status reference_device(dev_desc* pdesc)
static obos_status unreference_device(dev_desc desc)
{
socket_desc* socket = (void*)desc;
+ if (!socket)
+ return OBOS_STATUS_INVALID_ARGUMENT;
if (!(--socket->refs))
socket->ops->free(socket);
return OBOS_STATUS_SUCCESS;
@@ -558,4 +560,4 @@ void VfsH_InitializeSocketInterface()
NetH_AddSocketBackend(&Net_TCPSocketBackend);
NetH_AddSocketBackend(&Vfs_LocalDgramSocketBackend);
NetH_AddSocketBackend(&Vfs_LocalStreamSocketBackend);
-}
\ No newline at end of file
+}
diff --git a/src/oboskrnl/vfs/tty.c b/src/oboskrnl/vfs/tty.c
index b8c20cbb..bece653b 100644
--- a/src/oboskrnl/vfs/tty.c
+++ b/src/oboskrnl/vfs/tty.c
@@ -290,19 +290,19 @@ static obos_status tty_ioctl(dev_desc what, uint32_t request, void *argp)
}
case TTY_IOCTL_FLOW:
switch (*(uint32_t*)argp) {
- case TCION:
+ case TCOON:
tty->paused = true;
break;
- case TCIOFF:
+ case TCOOFF:
tty->paused = false;
break;
- case TCOOFF:
+ case TCIOFF:
{
char ch = tty->termios.iflag & IXON ? tty->termios.cc[VSTOP] : '\023' /* assume it is this */;
tty->interface.write(tty, &ch, 1);
break;
}
- case TCOON:
+ case TCION:
{
char ch = tty->termios.iflag & IXON ? tty->termios.cc[VSTART] : '\021' /* assume it is this */;
tty->interface.write(tty, &ch, 1);
@@ -439,29 +439,44 @@ static size_t strrfind(const char* str, char ch)
return SIZE_MAX;
}
+static bool char_is_nl(tty* tty, char ch)
+{
+ return ch == '\n' || ch == '\r' ||
+ (tty->termios.cc[VEOL] == ch && tty->termios.cc[VEOL]) ||
+ (tty->termios.cc[VEOL2] == ch && tty->termios.cc[VEOL2]);
+}
+
void erase_bytes(tty* tty, size_t nBytesToErase)
{
if (nBytesToErase == SIZE_MAX)
nBytesToErase = tty->input_buffer.out_ptr % tty->input_buffer.size;
for (size_t j = 0; j < nBytesToErase && tty->input_buffer.out_ptr > 0; j++)
{
+ if (char_is_nl(tty, tty->input_buffer.buf[tty->input_buffer.out_ptr]) || char_is_nl(tty, tty->input_buffer.buf[tty->input_buffer.out_ptr-1]))
+ {
+ if (tty->input_buffer.buf[tty->input_buffer.out_ptr] != '\n' && tty->input_buffer.buf[tty->input_buffer.out_ptr-1] == '\n')
+ tty->input_buffer.out_ptr--;
+ if (tty->input_buffer.in_ptr > tty->input_buffer.out_ptr)
+ tty->input_buffer.in_ptr = tty->input_buffer.out_ptr;
+ break;
+ }
if (tty->input_buffer.out_ptr == tty->input_buffer.in_ptr)
tty->input_buffer.in_ptr--;
tty->input_buffer.buf[tty->input_buffer.out_ptr-- % tty->input_buffer.size] = 0;
- tty->interface.write(tty, "\b", 1);
+ tty->interface.write(tty, "\b \b", 3);
}
}
static void tty_kill(tty* tty, int sigval)
{
- if (tty->termios.lflag & ISIG)
- OBOS_KillProcessGroup(tty->fg_job, sigval);
+ OBOS_KillProcessGroup(tty->fg_job, sigval);
}
static void data_ready(void *tty_, const void *buf, size_t nBytesReady)
{
tty *tty = (struct tty *)tty_;
const uint8_t *buf8 = buf;
+ bool inserted_any_bytes = false;
for (size_t i = 0; i < nBytesReady; i++)
{
char ch = buf8[i];
@@ -520,6 +535,7 @@ static void data_ready(void *tty_, const void *buf, size_t nBytesReady)
tty->quoted = false;
if (!insert_byte)
continue;
+ inserted_any_bytes = true;
if (tty->termios.lflag & ECHO)
tty_write_sync((dev_desc)tty, &ch, 1, 0, nullptr);
if (tty->termios.lflag & ICANON)
@@ -533,6 +549,8 @@ static void data_ready(void *tty_, const void *buf, size_t nBytesReady)
toupper(ch & mask) :
(ch & mask);
}
+ if (!inserted_any_bytes)
+ return;
if (tty->termios.lflag & ICANON)
find_eol(tty, &tty->input_buffer.buf[(tty->input_buffer.out_ptr - 1) % tty->input_buffer.size]) == SIZE_MAX ? (void)0 : Core_EventSet(&tty->data_ready_evnt, true);
else
@@ -567,6 +585,7 @@ obos_status Vfs_RegisterTTY(const tty_interface *i, dirent **onode, bool pty)
VNODE_TYPE_CHR);
vn->flags |= VFLAGS_IS_TTY;
vn->data = tty;
+ vn->gid = 5; // tty
size_t index = pty ? last_pty_index++ : last_tty_index++;
size_t szName = snprintf(nullptr, 0, "tty%ld", index);
char *name = nullptr;
@@ -641,7 +660,7 @@ static void poll_keyboard(struct screen_tty* data)
while (1)
{
while (data->input_paused)
- OBOSS_SpinlockHint();
+ Core_Yield();
size_t nReady = 1;
irp* req = VfsH_IRPAllocate();
req->vn = data->keyboard.vn;
diff --git a/src/oboskrnl/vfs/vnode.h b/src/oboskrnl/vfs/vnode.h
index d0475e83..537bc422 100644
--- a/src/oboskrnl/vfs/vnode.h
+++ b/src/oboskrnl/vfs/vnode.h
@@ -90,8 +90,8 @@ typedef struct vnode
size_t refs;
file_perm perm;
size_t filesize; // filesize.
- uid owner_uid; // the owner's UID.
- gid group_uid; // the group's GID.
+ uid uid; // the owner's UID.
+ gid gid; // the group's GID.
dev_desc desc; // the cached device descriptor.
fd_list opened;
size_t nMappedRegions;
@@ -119,4 +119,7 @@ OBOS_EXPORT vnode* Drv_AllocateVNode(driver_id* drv, dev_desc desc, size_t files
OBOS_EXPORT driver_header* Vfs_GetVnodeDriver(vnode* vn);
// For files that can and can't have I/O on them (directories, symbolic links, FIFOs, regular files, CHR/BLK devices, and sockets)
OBOS_EXPORT driver_header* Vfs_GetVnodeDriverStat(vnode* vn);
-OBOS_EXPORT struct mount* Vfs_GetVnodeMount(vnode* vn);
\ No newline at end of file
+OBOS_EXPORT struct mount* Vfs_GetVnodeMount(vnode* vn);
+
+OBOS_EXPORT obos_status Vfs_Access(vnode* vn, bool read, bool write, bool exec);
+OBOS_EXPORT obos_status Vfs_AccessAs(uid asUid, gid asGid, vnode* vn, bool read, bool write, bool exec);
\ No newline at end of file
diff --git a/src/uACPI/CMakeLists.txt b/src/uACPI/CMakeLists.txt
index 72b4b86a..abb3f543 100644
--- a/src/uACPI/CMakeLists.txt
+++ b/src/uACPI/CMakeLists.txt
@@ -23,11 +23,13 @@ if (OBOS_ENABLE_PROFILER)
target_compile_options(uacpi PRIVATE $<$:-finstrument-functions>)
endif()
+if (OBOS_ENABLE_FANALYZER)
+ target_compile_options(uacpi PRIVATE "-fno-analyzer")
+endif()
+
# All symbols exported, except for the kernel api of course.
set_source_files_properties("kernel_api.c" PROPERTIES COMPILE_OPTIONS "-fvisibility=hidden")
-message(${OBOSKRNL_EXTERNAL_INCLUDES})
-
target_include_directories(uacpi PRIVATE "${CMAKE_SOURCE_DIR}/src/oboskrnl")
target_include_directories(uacpi PRIVATE "${CMAKE_SOURCE_DIR}/src/sanitizers")
target_include_directories(uacpi PRIVATE ${OBOSKRNL_EXTERNAL_INCLUDES})
diff --git a/src/uACPI/kernel_api.c b/src/uACPI/kernel_api.c
index b8f77090..5f9a65c7 100644
--- a/src/uACPI/kernel_api.c
+++ b/src/uACPI/kernel_api.c
@@ -571,7 +571,7 @@ uacpi_status uacpi_kernel_get_rsdp(uacpi_phys_addr* out)
{
uintptr_t rsdp = 0;
#ifdef __x86_64__
- rsdp = Arch_LdrPlatformInfo->acpi_rsdp_address;
+ rsdp = Arch_RSDPBase;
#endif
*out = rsdp;
return UACPI_STATUS_OK;
diff --git a/src/uHDA/hdadev.c b/src/uHDA/hdadev.c
index 060a6aa1..c0ce2efa 100644
--- a/src/uHDA/hdadev.c
+++ b/src/uHDA/hdadev.c
@@ -264,7 +264,8 @@ void fd_fill_worker(void* user)
struct fd_fill_userdata *udata = user;
while (!udata->request_thread_kill)
{
- Core_WaitOnObject(WAITABLE_OBJECT(udata->wake_thr));
+ if (obos_is_error(Core_WaitOnObject(WAITABLE_OBJECT(udata->wake_thr))))
+ break;
Core_EventClear(&udata->wake_thr);
if (udata->request_thread_kill)
break;
diff --git a/src/uHDA/kernel_api.c b/src/uHDA/kernel_api.c
index 6f5683be..54bcffc4 100644
--- a/src/uHDA/kernel_api.c
+++ b/src/uHDA/kernel_api.c
@@ -157,6 +157,7 @@ static void* map_registers(uintptr_t phys, size_t size, bool uc)
page.phys = phys+offset;
MmS_SetPageMapping(Mm_KernelContext.pt, &page, phys + offset, false);
}
+ Drv_TLBShootdown(Mm_KernelContext.pt, (uintptr_t)virt, size);
return virt+phys_page_offset;
}
diff --git a/src/user-utilities/CMakeLists.txt b/src/user-utilities/CMakeLists.txt
index df2357a9..eb538c32 100644
--- a/src/user-utilities/CMakeLists.txt
+++ b/src/user-utilities/CMakeLists.txt
@@ -29,10 +29,14 @@ add_executable (lsmod "lsmod.c")
add_executable (ldmod "ldmod.c")
add_executable (stmod "stmod.c")
add_executable (rmmod "rmmod.c")
-install(TARGETS powerctl klog-level fork-test mem-usage mount umount swapon mkswap sync-anon lsmod ldmod stmod rmmod)
+add_executable (login "login.c")
+target_link_libraries(login crypt)
+install(TARGETS powerctl klog-level fork-test mem-usage mount umount swapon mkswap sync-anon)
+install(TARGETS lsmod ldmod stmod rmmod login DESTINATION sbin)
if (${OBOS_ARCHITECTURE} STREQUAL "x86_64")
add_executable(obos-gettime "x86_obos-gettime.c")
add_executable(enable-kgdbstub "x86_enable-kgdbstub.c")
- install(TARGETS obos-gettime enable-kgdbstub)
+ install(TARGETS obos-gettime)
+ install(TARGETS enable-kgdbstub DESTINATION sbin)
endif()
diff --git a/src/user-utilities/login.c b/src/user-utilities/login.c
new file mode 100644
index 00000000..f7dd3646
--- /dev/null
+++ b/src/user-utilities/login.c
@@ -0,0 +1,271 @@
+#define _GNU_SOURCE
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#if __obos__
+#include
+#endif
+
+char g_hostname[32];
+
+static char* readline()
+{
+ char* buf = NULL;
+ size_t size = 0;
+ while (1)
+ {
+ char ch = getchar();
+ if (ch == '\n')
+ break;
+ buf = realloc(buf, ++size);
+ buf[size-1] = ch;
+ }
+ buf = realloc(buf, size + 1);
+ buf[size] = 0;
+ return buf;
+}
+
+static void prompt(char** ousername, char** opassword)
+{
+ struct termios tc = {};
+ tcgetattr(0, &tc);
+ tc.c_lflag |= ECHO;
+ tc.c_iflag |= ICRNL;
+ tcsetattr(0, 0, &tc);
+
+ retry_uname_prompt:
+ fprintf(stderr, "%.*s login: ", (int)sizeof(g_hostname), g_hostname);
+ *ousername = readline();
+ if (!strlen(*ousername))
+ {
+ free(*ousername);
+ goto retry_uname_prompt;
+ }
+ fprintf(stderr, "%s password: ", *ousername);
+ struct termios old_tc = tc;
+ tc.c_lflag &= ~ECHO;
+ tc.c_lflag |= ECHONL;
+ tcsetattr(0, 0, &tc);
+ *opassword = readline();
+ tcsetattr(0, 0, &old_tc);
+}
+
+#define invalid_pwd_timeout (5)
+#define invalid_pwd_msg "Invalid username or password"
+
+static int login(char* username, char* password, struct passwd** ouser)
+{
+ struct passwd* user = getpwnam(username);
+ if (!user)
+ return 0;
+
+ // Check password
+ if (strcmp(user->pw_passwd, "x") == 0)
+ {
+ struct spwd* ent = getspnam(user->pw_name);
+ if (!ent)
+ {
+ endspent();
+ if (errno == 0)
+ return 1; // authenticated
+ else
+ {
+ perror("getspnam");
+ return 0;
+ }
+ }
+ if (strlen(ent->sp_pwdp) == 0)
+ {
+ endspent();
+ goto success;
+ }
+ // Verify password.
+ // NOTE: If the user account cannot be signed in using a password,
+ // then this code will still be able to handle that, as ent->sp_pwdp
+ // would be invalid.
+ char* hash = crypt(password, ent->sp_pwdp);
+ if (!hash)
+ {
+ perror("crypt_ra");
+ return 0;
+ }
+ if (strcmp(hash, ent->sp_pwdp) == 0)
+ {
+ endspent();
+ goto success;
+ }
+ endspent();
+ return 0;
+ }
+ else
+ {
+ if (strcmp(user->pw_passwd, password) == 0)
+ goto success;
+ return 0;
+ }
+
+ success:
+
+ *ouser = user;
+ return 1;
+}
+
+int do_waitpid(int child)
+{
+ int status = 0;
+ do {
+ if (waitpid(child, &status, 0) == 0)
+ break;
+ switch (errno) {
+ case EINTR:
+ errno = 0;
+ continue;
+ case ECHILD:
+ break;
+ case 0:
+ break;
+ default:
+ status = -1;
+ perror("waitpid");
+ continue;
+ }
+ break;
+ } while(1);
+ return status;
+}
+
+int main()
+{
+ if (geteuid() != 0)
+ {
+ fprintf(stderr, "FATAL: euid != 0\n");
+ return -1;
+ }
+
+ signal(SIGINT, SIG_IGN);
+ signal(SIGTSTP, SIG_IGN);
+
+ gethostname(g_hostname, sizeof(g_hostname));
+
+ while (1)
+ {
+ char* username = NULL;
+ char* password = NULL;
+ prompt(&username, &password);
+
+ struct passwd* user = NULL;
+
+ if (!login(username, password, &user))
+ {
+ sleep(invalid_pwd_timeout);
+ puts(invalid_pwd_msg);
+ free(username);
+ memset(password, 0xde, strlen(password));
+#if __obos__
+ // Make sure the cleared password is noted in the swap.
+ // Note: Ideally we would not have the password on swap at all.
+ // (TODO)
+ syscall0(Sys_SyncAnonPages);
+#endif
+ free(password);
+ continue;
+ }
+
+ free(username);
+ memset(password, 0xde, strlen(password));
+#if __obos__
+ // Make sure the cleared password is noted in the swap.
+ // Ideally we would not have the password on swap at all.
+ // (TODO)
+ syscall0(Sys_SyncAnonPages);
+#endif
+ free(password);
+
+ int child = fork();
+ if (child == 0)
+ {
+ // TODO: Session IDs?
+ // TODO: Parse /etc/environment
+
+ if (setresgid(user->pw_gid, user->pw_gid, user->pw_gid) != 0)
+ {
+ perror("setresgid");
+ exit(-1);
+ }
+
+ int ngroups = 0;
+ gid_t* groups = 0;
+ getgrouplist(user->pw_name, user->pw_gid, groups, &ngroups);
+ groups = calloc(ngroups, sizeof(gid_t));
+ getgrouplist(user->pw_name, user->pw_gid, groups, &ngroups);
+
+ setgroups(0, NULL);
+ int ret = setgroups(ngroups, groups);
+ if (ret == -1)
+ {
+ switch (errno) {
+ case ENOSYS:
+ break;
+ default:
+ perror("setgroups");
+ return -1;
+ }
+ }
+
+ if (setresuid(user->pw_uid, user->pw_uid, user->pw_uid) != 0)
+ {
+ perror("setresuid");
+ exit(-1);
+ }
+
+ const char* term = getenv("TERM");
+ clearenv();
+ setenv("HOME", user->pw_dir, 1);
+ setenv("TERM", term, 1);
+ setenv("SHELL", user->pw_shell, 1);
+ setenv("USER", user->pw_name, 1);
+ setenv("LOGNAME", user->pw_name, 1);
+ // Sensible value?
+ if (user->pw_uid == 0)
+ setenv("PATH", "/usr/local/bin:/usr/bin:/usr/sbin", 1);
+ else
+ setenv("PATH", "/usr/local/bin:/usr/bin:/usr/local/games:/usr/games", 1);
+ char* argv[3] = { user->pw_shell, NULL, NULL };
+ if (strcmp(basename(user->pw_shell), "bash") == 0)
+ argv[1] = "--login";
+
+ if (chdir(user->pw_dir) == -1)
+ {
+ perror("chdir(user->pw_dir)");
+ return -1;
+ }
+
+ execvp(user->pw_shell, argv);
+
+ perror("execvp");
+ return -1;
+ }
+ else
+ {
+ if (do_waitpid(child) == 0)
+ // god forgive me
+ system("reset");
+ else
+ continue;
+ }
+ }
+
+ return 0;
+}
\ No newline at end of file
diff --git a/src/user-utilities/x86_enable-kgdbstub.c b/src/user-utilities/x86_enable-kgdbstub.c
index ab27937f..f09f8b47 100644
--- a/src/user-utilities/x86_enable-kgdbstub.c
+++ b/src/user-utilities/x86_enable-kgdbstub.c
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include
#include
#include