Compare commits
No commits in common. "fc0f3157eaa3fa52467be4a1cb34dd450c25b308" and "c84a30d4dd054741e5171af2c1aadf28bcd88e31" have entirely different histories.
fc0f3157ea
...
c84a30d4dd
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <BAN/Iterators.h>
|
||||
#include <BAN/Iteration.h>
|
||||
#include <BAN/Swap.h>
|
||||
#include <BAN/Traits.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ asm_syscall_handler:
|
|||
andl $-16, %esp
|
||||
|
||||
# push arguments
|
||||
subl $8, %esp
|
||||
subl $4, %esp
|
||||
pushl %ebp
|
||||
addl $24, (%esp)
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %edx
|
||||
|
|
@ -63,7 +65,7 @@ sys_fork_trampoline:
|
|||
|
||||
call read_ip
|
||||
testl %eax, %eax
|
||||
jz .done
|
||||
jz .reload_stack
|
||||
|
||||
movl %esp, %ebx
|
||||
|
||||
|
|
@ -79,3 +81,9 @@ sys_fork_trampoline:
|
|||
popl %ebx
|
||||
popl %ebp
|
||||
ret
|
||||
|
||||
.reload_stack:
|
||||
call get_thread_start_sp
|
||||
movl %eax, %esp
|
||||
xorl %eax, %eax
|
||||
jmp .done
|
||||
|
|
|
|||
|
|
@ -184,13 +184,6 @@ enable_sse:
|
|||
movl %eax, %cr4
|
||||
ret
|
||||
|
||||
enable_tsc:
|
||||
# allow userspace to use RDTSC
|
||||
movl %cr4, %ecx
|
||||
andl $0xFFFFFFFB, %ecx
|
||||
movl %ecx, %cr4
|
||||
ret
|
||||
|
||||
initialize_paging:
|
||||
# enable PAE
|
||||
movl %cr4, %ecx
|
||||
|
|
@ -233,7 +226,6 @@ gdt_flush:
|
|||
# do processor initialization
|
||||
call check_requirements
|
||||
call enable_sse
|
||||
call enable_tsc
|
||||
call initialize_paging
|
||||
|
||||
# load higher half stack pointer
|
||||
|
|
@ -310,7 +302,6 @@ ap_protected_mode:
|
|||
movb $1, AP_V2P(ap_stack_loaded)
|
||||
|
||||
leal V2P(enable_sse), %ecx; call *%ecx
|
||||
leal V2P(enable_tsc), %ecx; call *%ecx
|
||||
leal V2P(initialize_paging), %ecx; call *%ecx
|
||||
|
||||
# load boot gdt and enter long mode
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
.macro maybe_load_kernel_segments, n
|
||||
testb $3, \n(%esp)
|
||||
jz 1f; jnp 1f
|
||||
cmpb $0x08, \n(%esp)
|
||||
je 1f
|
||||
|
||||
movw $0x10, %ax
|
||||
movw %ax, %ds
|
||||
|
|
@ -13,8 +13,8 @@
|
|||
.endm
|
||||
|
||||
.macro maybe_load_userspace_segments, n
|
||||
testb $3, \n(%esp)
|
||||
jz 1f; jnp 1f
|
||||
cmpb $0x08, \n(%esp)
|
||||
je 1f
|
||||
|
||||
movw $(0x20 | 3), %bx
|
||||
movw %bx, %ds
|
||||
|
|
|
|||
|
|
@ -1,26 +1,50 @@
|
|||
// arguments in RAX, RBX, RCX, RDX, RSI, RDI
|
||||
// System V ABI: RDI, RSI, RDX, RCX, R8, R9
|
||||
.global asm_syscall_handler
|
||||
asm_syscall_handler:
|
||||
swapgs
|
||||
|
||||
movq %rsp, %rax
|
||||
movq %gs:8, %rsp
|
||||
|
||||
pushq $(0x20 | 3)
|
||||
pushq %rax
|
||||
pushq %r11
|
||||
pushq $(0x28 | 3)
|
||||
pushq %rbx
|
||||
pushq %rcx
|
||||
subq $8, %rsp
|
||||
pushq %rdx
|
||||
pushq %rdi
|
||||
pushq %rsi
|
||||
pushq %rbp
|
||||
pushq %r8
|
||||
pushq %r9
|
||||
pushq %r10
|
||||
pushq %r11
|
||||
pushq %r12
|
||||
pushq %r13
|
||||
pushq %r14
|
||||
pushq %r15
|
||||
cld
|
||||
|
||||
movq %r10, %rcx
|
||||
movq %rsi, %r8
|
||||
movq %rdi, %r9
|
||||
movq %rax, %rdi
|
||||
movq %rbx, %rsi
|
||||
xchgq %rcx, %rdx
|
||||
leaq 112(%rsp), %rbx
|
||||
pushq %rbx
|
||||
call cpp_syscall_handler
|
||||
addq $8, %rsp
|
||||
|
||||
movq 8(%rsp), %rcx
|
||||
movq 24(%rsp), %r11
|
||||
movq 32(%rsp), %rsp
|
||||
|
||||
popq %r15
|
||||
popq %r14
|
||||
popq %r13
|
||||
popq %r12
|
||||
popq %r11
|
||||
popq %r10
|
||||
popq %r9
|
||||
popq %r8
|
||||
popq %rbp
|
||||
popq %rsi
|
||||
popq %rdi
|
||||
popq %rdx
|
||||
popq %rcx
|
||||
popq %rbx
|
||||
swapgs
|
||||
sysretq
|
||||
iretq
|
||||
|
||||
.global sys_fork_trampoline
|
||||
sys_fork_trampoline:
|
||||
|
|
@ -33,7 +57,7 @@ sys_fork_trampoline:
|
|||
|
||||
call read_ip
|
||||
testq %rax, %rax
|
||||
je .done
|
||||
je .reload_stack
|
||||
|
||||
movq %rax, %rsi
|
||||
movq %rsp, %rdi
|
||||
|
|
@ -47,3 +71,9 @@ sys_fork_trampoline:
|
|||
popq %rbp
|
||||
popq %rbx
|
||||
ret
|
||||
|
||||
.reload_stack:
|
||||
call get_thread_start_sp
|
||||
movq %rax, %rsp
|
||||
xorq %rax, %rax
|
||||
jmp .done
|
||||
|
|
|
|||
|
|
@ -179,13 +179,6 @@ enable_sse:
|
|||
movl %eax, %cr4
|
||||
ret
|
||||
|
||||
enable_tsc:
|
||||
# allow userspace to use RDTSC
|
||||
movl %cr4, %ecx
|
||||
andl $0xFFFFFFFB, %ecx
|
||||
movl %ecx, %cr4
|
||||
ret
|
||||
|
||||
initialize_paging:
|
||||
# enable PAE
|
||||
movl %cr4, %ecx
|
||||
|
|
@ -222,7 +215,6 @@ _start:
|
|||
|
||||
call check_requirements
|
||||
call enable_sse
|
||||
call enable_tsc
|
||||
call initialize_paging
|
||||
|
||||
# flush gdt and jump to 64 bit
|
||||
|
|
@ -309,7 +301,6 @@ ap_protected_mode:
|
|||
movb $1, AP_V2P(ap_stack_loaded)
|
||||
|
||||
leal V2P(enable_sse), %ecx; call *%ecx
|
||||
leal V2P(enable_tsc), %ecx; call *%ecx
|
||||
leal V2P(initialize_paging), %ecx; call *%ecx
|
||||
|
||||
# load boot gdt and enter long mode
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
.macro swapgs_if_necessary, n
|
||||
testb $3, \n(%rsp)
|
||||
jz 1f; jnp 1f
|
||||
cmpb $0x08, \n(%rsp)
|
||||
je 1f
|
||||
swapgs
|
||||
1:
|
||||
.endm
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Kernel::API
|
||||
{
|
||||
|
||||
enum SharedPageFeature : uint32_t
|
||||
{
|
||||
SPF_GETTIME = 1 << 0,
|
||||
};
|
||||
|
||||
struct SharedPage
|
||||
{
|
||||
uint8_t __sequence[0x100];
|
||||
|
||||
uint32_t features;
|
||||
|
||||
struct
|
||||
{
|
||||
uint8_t shift;
|
||||
uint64_t mult;
|
||||
uint64_t realtime_seconds;
|
||||
} gettime_shared;
|
||||
|
||||
struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t seq;
|
||||
uint64_t last_ns;
|
||||
uint64_t last_tsc;
|
||||
} gettime_local;
|
||||
} cpus[];
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <kernel/Attributes.h>
|
||||
#include <kernel/IDT.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
ALWAYS_INLINE long syscall(int syscall, uintptr_t arg1 = 0, uintptr_t arg2 = 0, uintptr_t arg3 = 0, uintptr_t arg4 = 0, uintptr_t arg5 = 0)
|
||||
{
|
||||
long ret;
|
||||
#if ARCH(x86_64)
|
||||
register uintptr_t r10 asm("r10") = arg3;
|
||||
register uintptr_t r8 asm( "r8") = arg4;
|
||||
register uintptr_t r9 asm( "r9") = arg5;
|
||||
asm volatile(
|
||||
"syscall"
|
||||
: "=a"(ret)
|
||||
, "+D"(syscall)
|
||||
, "+S"(arg1)
|
||||
, "+d"(arg2)
|
||||
, "+r"(r10)
|
||||
, "+r"(r8)
|
||||
, "+r"(r9)
|
||||
:: "rcx", "r11", "memory");
|
||||
#elif ARCH(i686)
|
||||
asm volatile(
|
||||
"int %[irq]"
|
||||
: "=a"(ret)
|
||||
: [irq]"i"(static_cast<int>(IRQ_SYSCALL)) // WTF GCC 15
|
||||
, "a"(syscall)
|
||||
, "b"(arg1)
|
||||
, "c"(arg2)
|
||||
, "d"(arg3)
|
||||
, "S"(arg4)
|
||||
, "D"(arg5)
|
||||
: "memory");
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -81,6 +81,5 @@ namespace CPUID
|
|||
bool has_pge();
|
||||
bool has_pat();
|
||||
bool has_1gib_pages();
|
||||
bool has_invariant_tsc();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,8 +151,8 @@ namespace Kernel
|
|||
|
||||
private:
|
||||
#if ARCH(x86_64)
|
||||
BAN::Array<SegmentDescriptor, 8> m_gdt; // null, kernel code, kernel data, user code (32 bit), user data, user code (64 bit), tss low, tss high
|
||||
static constexpr uint16_t m_tss_offset = 0x30;
|
||||
BAN::Array<SegmentDescriptor, 7> m_gdt; // null, kernel code, kernel data, user code, user data, tss low, tss high
|
||||
static constexpr uint16_t m_tss_offset = 0x28;
|
||||
#elif ARCH(i686)
|
||||
BAN::Array<SegmentDescriptor, 9> m_gdt; // null, kernel code, kernel data, user code, user data, processor data, fsbase, gsbase, tss
|
||||
static constexpr uint16_t m_tss_offset = 0x40;
|
||||
|
|
|
|||
|
|
@ -18,10 +18,7 @@ namespace Kernel
|
|||
|
||||
constexpr uint8_t IRQ_VECTOR_BASE = 0x20;
|
||||
constexpr uint8_t IRQ_MSI_BASE = 0x80;
|
||||
constexpr uint8_t IRQ_MSI_END = 0xF0;
|
||||
#if ARCH(i686)
|
||||
constexpr uint8_t IRQ_SYSCALL = 0xF0;
|
||||
#endif
|
||||
constexpr uint8_t IRQ_YIELD = 0xF1;
|
||||
constexpr uint8_t IRQ_IPI = 0xF2;
|
||||
constexpr uint8_t IRQ_TIMER = 0xF3;
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ namespace Kernel::PCI
|
|||
void initialize_impl();
|
||||
|
||||
private:
|
||||
static constexpr uint8_t m_msi_count = IRQ_MSI_END - IRQ_MSI_BASE;
|
||||
static constexpr uint8_t m_msi_count = IRQ_SYSCALL - IRQ_MSI_BASE;
|
||||
using PCIBus = BAN::Array<BAN::Array<Device, 8>, 32>;
|
||||
BAN::Array<PCIBus, 256> m_buses;
|
||||
BAN::Array<paddr_t, 256> m_bus_pcie_paddr;
|
||||
|
|
|
|||
|
|
@ -228,8 +228,6 @@ namespace Kernel
|
|||
|
||||
static Process& current() { return Thread::current().process(); }
|
||||
|
||||
vaddr_t shared_page_vaddr() const { return m_shared_page_vaddr; }
|
||||
|
||||
PageTable& page_table() { return m_page_table ? *m_page_table : PageTable::kernel(); }
|
||||
|
||||
size_t proc_meminfo(off_t offset, BAN::ByteSpan) const;
|
||||
|
|
@ -344,8 +342,6 @@ namespace Kernel
|
|||
VirtualFileSystem::File m_working_directory;
|
||||
VirtualFileSystem::File m_root_file;
|
||||
|
||||
vaddr_t m_shared_page_vaddr { 0 };
|
||||
|
||||
BAN::Vector<Thread*> m_threads;
|
||||
|
||||
struct pthread_info_t
|
||||
|
|
|
|||
|
|
@ -3,12 +3,10 @@
|
|||
#include <BAN/Atomic.h>
|
||||
#include <BAN/ForwardList.h>
|
||||
|
||||
#include <kernel/API/SharedPage.h>
|
||||
#include <kernel/Arch.h>
|
||||
#include <kernel/GDT.h>
|
||||
#include <kernel/IDT.h>
|
||||
#include <kernel/InterruptStack.h>
|
||||
#include <kernel/Memory/Types.h>
|
||||
#include <kernel/ProcessorID.h>
|
||||
#include <kernel/Scheduler.h>
|
||||
|
||||
|
|
@ -35,7 +33,6 @@ namespace Kernel
|
|||
FlushTLB,
|
||||
NewThread,
|
||||
UnblockThread,
|
||||
UpdateTSC,
|
||||
StackTrace,
|
||||
};
|
||||
SMPMessage* next { nullptr };
|
||||
|
|
@ -58,7 +55,6 @@ namespace Kernel
|
|||
static Processor& initialize();
|
||||
|
||||
static ProcessorID current_id() { return read_gs_sized<ProcessorID>(offsetof(Processor, m_id)); }
|
||||
static uint8_t current_index() { return read_gs_sized<uint8_t>(offsetof(Processor, m_index)); }
|
||||
static ProcessorID id_from_index(size_t index);
|
||||
|
||||
static uint8_t count() { return s_processor_count; }
|
||||
|
|
@ -82,11 +78,8 @@ namespace Kernel
|
|||
|
||||
static InterruptState get_interrupt_state()
|
||||
{
|
||||
#if ARCH(x86_64)
|
||||
const auto flags = __builtin_ia32_readeflags_u64();
|
||||
#elif ARCH(i686)
|
||||
const auto flags = __builtin_ia32_readeflags_u32();
|
||||
#endif
|
||||
uintptr_t flags;
|
||||
asm volatile("pushf; pop %0" : "=rm"(flags));
|
||||
if (flags & (1 << 9))
|
||||
return InterruptState::Enabled;
|
||||
return InterruptState::Disabled;
|
||||
|
|
@ -105,8 +98,6 @@ namespace Kernel
|
|||
uintptr_t stack_bottom() const { return reinterpret_cast<uintptr_t>(m_stack); }
|
||||
uintptr_t stack_top() const { return stack_bottom() + s_stack_size; }
|
||||
|
||||
static void set_thread_syscall_stack(vaddr_t vaddr) { write_gs_sized<vaddr_t>(offsetof(Processor, m_thread_syscall_stack), vaddr); }
|
||||
|
||||
static GDT& gdt() { return *read_gs_sized<GDT*>(offsetof(Processor, m_gdt)); }
|
||||
static IDT& idt() { return *read_gs_sized<IDT*>(offsetof(Processor, m_idt)); }
|
||||
|
||||
|
|
@ -116,13 +107,6 @@ namespace Kernel
|
|||
static void yield();
|
||||
static Scheduler& scheduler() { return *read_gs_sized<Scheduler*>(offsetof(Processor, m_scheduler)); }
|
||||
|
||||
static void initialize_tsc(uint8_t shift, uint64_t mult, uint64_t realtime_seconds);
|
||||
static void update_tsc();
|
||||
static uint64_t ns_since_boot_tsc();
|
||||
|
||||
static paddr_t shared_page_paddr() { return s_shared_page_paddr; }
|
||||
static volatile API::SharedPage& shared_page() { return *reinterpret_cast<API::SharedPage*>(s_shared_page_vaddr); }
|
||||
|
||||
static void handle_ipi();
|
||||
|
||||
static void handle_smp_messages();
|
||||
|
|
@ -140,14 +124,6 @@ namespace Kernel
|
|||
static ProcessorID read_processor_id();
|
||||
|
||||
static void initialize_smp();
|
||||
static void initialize_shared_page();
|
||||
|
||||
static void dummy()
|
||||
{
|
||||
#if ARCH(x86_64)
|
||||
static_assert(offsetof(Processor, m_thread_syscall_stack) == 8, "This is hardcoded in Syscall.S");
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T read_gs_sized(uintptr_t offset) requires(sizeof(T) <= 8)
|
||||
|
|
@ -186,13 +162,8 @@ namespace Kernel
|
|||
static BAN::Atomic<uint8_t> s_processor_count;
|
||||
static BAN::Atomic<bool> s_is_smp_enabled;
|
||||
static BAN::Atomic<bool> s_should_print_cpu_load;
|
||||
static paddr_t s_shared_page_paddr;
|
||||
static vaddr_t s_shared_page_vaddr;
|
||||
|
||||
ProcessorID m_id { 0 };
|
||||
uint8_t m_index { 0xFF };
|
||||
|
||||
vaddr_t m_thread_syscall_stack;
|
||||
|
||||
static constexpr size_t s_stack_size { 4096 };
|
||||
void* m_stack { nullptr };
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
#pragma once
|
||||
|
||||
#include <kernel/Attributes.h>
|
||||
#include <kernel/IDT.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
ALWAYS_INLINE long syscall(int syscall, uintptr_t arg1 = 0, uintptr_t arg2 = 0, uintptr_t arg3 = 0, uintptr_t arg4 = 0, uintptr_t arg5 = 0)
|
||||
{
|
||||
long ret;
|
||||
asm volatile("int %[irq]"
|
||||
: "=a"(ret)
|
||||
: [irq]"i"(static_cast<int>(IRQ_SYSCALL)) // WTF GCC 15
|
||||
, "a"(syscall)
|
||||
, "b"((uintptr_t)arg1)
|
||||
, "c"((uintptr_t)arg2)
|
||||
, "d"((uintptr_t)arg3)
|
||||
, "S"((uintptr_t)arg4)
|
||||
, "D"((uintptr_t)arg5)
|
||||
: "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -122,8 +122,6 @@ namespace Kernel
|
|||
void set_cpu_time_start();
|
||||
void set_cpu_time_stop();
|
||||
|
||||
void update_processor_index_address();
|
||||
|
||||
void set_fsbase(vaddr_t base) { m_fsbase = base; }
|
||||
vaddr_t get_fsbase() const { return m_fsbase; }
|
||||
void set_gsbase(vaddr_t base) { m_gsbase = base; }
|
||||
|
|
|
|||
|
|
@ -35,8 +35,6 @@ namespace Kernel
|
|||
static SystemTimer& get();
|
||||
static bool is_initialized();
|
||||
|
||||
void initialize_tsc();
|
||||
|
||||
virtual uint64_t ms_since_boot() const override;
|
||||
virtual uint64_t ns_since_boot() const override;
|
||||
virtual timespec time_since_boot() const override;
|
||||
|
|
@ -49,9 +47,6 @@ namespace Kernel
|
|||
|
||||
void dont_invoke_scheduler() { m_timer->m_should_invoke_scheduler = false; }
|
||||
|
||||
void update_tsc() const;
|
||||
uint64_t ns_since_boot_no_tsc() const;
|
||||
|
||||
timespec real_time() const;
|
||||
|
||||
private:
|
||||
|
|
@ -59,14 +54,10 @@ namespace Kernel
|
|||
|
||||
void initialize_timers(bool force_pic);
|
||||
|
||||
uint64_t get_tsc_frequency() const;
|
||||
|
||||
private:
|
||||
uint64_t m_boot_time { 0 };
|
||||
BAN::UniqPtr<RTC> m_rtc;
|
||||
BAN::UniqPtr<Timer> m_timer;
|
||||
bool m_has_invariant_tsc { false };
|
||||
mutable uint32_t m_timer_ticks { 0 };
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,7 +75,6 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<void> initialize();
|
||||
|
||||
const USBDeviceDescriptor& device_descriptor() const { return m_descriptor.descriptor; }
|
||||
const BAN::Vector<ConfigurationDescriptor>& configurations() { return m_descriptor.configurations; }
|
||||
|
||||
virtual BAN::ErrorOr<uint8_t> initialize_device_on_hub_port(uint8_t port_id, USB::SpeedClass) = 0;
|
||||
|
|
|
|||
|
|
@ -75,16 +75,6 @@ namespace CPUID
|
|||
return buffer[3] & (1 << 26);
|
||||
}
|
||||
|
||||
bool has_invariant_tsc()
|
||||
{
|
||||
uint32_t buffer[4] {};
|
||||
get_cpuid(0x80000000, buffer);
|
||||
if (buffer[0] < 0x80000007)
|
||||
return false;
|
||||
get_cpuid(0x80000007, buffer);
|
||||
return buffer[3] & (1 << 8);
|
||||
}
|
||||
|
||||
const char* feature_string_ecx(uint32_t feat)
|
||||
{
|
||||
switch (feat)
|
||||
|
|
|
|||
|
|
@ -15,23 +15,23 @@ namespace Kernel
|
|||
ASSERT(gdt);
|
||||
|
||||
#if ARCH(x86_64)
|
||||
gdt->write_entry(0x00, 0x00000000, 0x00000, 0x00, 0x0); // null
|
||||
gdt->write_entry(0x08, 0x00000000, 0xFFFFF, 0x9A, 0xA); // kernel code
|
||||
gdt->write_entry(0x10, 0x00000000, 0xFFFFF, 0x92, 0xC); // kernel data
|
||||
gdt->write_entry(0x18, 0x00000000, 0xFFFFF, 0xFA, 0xC); // user code (32 bit)
|
||||
gdt->write_entry(0x20, 0x00000000, 0xFFFFF, 0xF2, 0xC); // user data
|
||||
gdt->write_entry(0x28, 0x00000000, 0xFFFFF, 0xFA, 0xA); // user code (64 bit)
|
||||
constexpr uint8_t code_flags = 0xA;
|
||||
constexpr uint8_t data_flags = 0xC;
|
||||
#elif ARCH(i686)
|
||||
gdt->write_entry(0x00, 0x00000000, 0x00000, 0x00, 0x0); // null
|
||||
gdt->write_entry(0x08, 0x00000000, 0xFFFFF, 0x9A, 0xC); // kernel code
|
||||
gdt->write_entry(0x10, 0x00000000, 0xFFFFF, 0x92, 0xC); // kernel data
|
||||
gdt->write_entry(0x18, 0x00000000, 0xFFFFF, 0xFA, 0xC); // user code
|
||||
gdt->write_entry(0x20, 0x00000000, 0xFFFFF, 0xF2, 0xC); // user data
|
||||
gdt->write_entry(0x28, reinterpret_cast<uint32_t>(processor), sizeof(Processor), 0x92, 0x4); // processor data
|
||||
gdt->write_entry(0x30, 0x00000000, 0x00000, 0xF2, 0xC); // fsbase
|
||||
gdt->write_entry(0x38, 0x00000000, 0x00000, 0xF2, 0xC); // gsbase
|
||||
constexpr uint8_t code_flags = 0xC;
|
||||
constexpr uint8_t data_flags = 0xC;
|
||||
#endif
|
||||
|
||||
gdt->write_entry(0x00, 0x00000000, 0x00000, 0x00, 0x0); // null
|
||||
gdt->write_entry(0x08, 0x00000000, 0xFFFFF, 0x9A, code_flags); // kernel code
|
||||
gdt->write_entry(0x10, 0x00000000, 0xFFFFF, 0x92, data_flags); // kernel data
|
||||
gdt->write_entry(0x18, 0x00000000, 0xFFFFF, 0xFA, code_flags); // user code
|
||||
gdt->write_entry(0x20, 0x00000000, 0xFFFFF, 0xF2, data_flags); // user data
|
||||
#if ARCH(i686)
|
||||
gdt->write_entry(0x28, reinterpret_cast<uint32_t>(processor), sizeof(Processor), 0x92, 0x4); // processor data
|
||||
gdt->write_entry(0x30, 0x00000000, 0x00000, 0xF2, data_flags); // fsbase
|
||||
gdt->write_entry(0x38, 0x00000000, 0x00000, 0xF2, data_flags); // gsbase
|
||||
#endif
|
||||
gdt->write_tss();
|
||||
|
||||
return gdt;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@
|
|||
X(160) X(161) X(162) X(163) X(164) X(165) X(166) X(167) X(168) X(169) X(170) X(171) X(172) X(173) X(174) X(175) X(176) X(177) X(178) X(179) X(180) X(181) X(182) X(183) X(184) X(185) X(186) X(187) X(188) X(189) X(190) X(191) \
|
||||
X(192) X(193) X(194) X(195) X(196) X(197) X(198) X(199) X(200) X(201) X(202) X(203) X(204) X(205) X(206) X(207)
|
||||
|
||||
static_assert(Kernel::IRQ_SYSCALL == Kernel::IRQ_VECTOR_BASE + 208);
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
|
|
@ -444,9 +446,7 @@ namespace Kernel
|
|||
extern "C" void asm_yield_handler();
|
||||
extern "C" void asm_ipi_handler();
|
||||
extern "C" void asm_timer_handler();
|
||||
#if ARCH(i686)
|
||||
extern "C" void asm_syscall_handler();
|
||||
#endif
|
||||
|
||||
IDT* IDT::create()
|
||||
{
|
||||
|
|
@ -480,9 +480,7 @@ namespace Kernel
|
|||
idt->register_interrupt_handler(IRQ_YIELD, asm_yield_handler);
|
||||
idt->register_interrupt_handler(IRQ_IPI, asm_ipi_handler);
|
||||
idt->register_interrupt_handler(IRQ_TIMER, asm_timer_handler);
|
||||
#if ARCH(i686)
|
||||
idt->register_syscall_handler(IRQ_SYSCALL, asm_syscall_handler);
|
||||
#endif
|
||||
|
||||
return idt;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,20 +152,6 @@ namespace Kernel
|
|||
}));
|
||||
}
|
||||
|
||||
process->m_shared_page_vaddr = process->page_table().reserve_free_page(process->m_mapped_regions.back()->vaddr(), USERSPACE_END);
|
||||
if (process->m_shared_page_vaddr == 0)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
process->page_table().map_page_at(
|
||||
Processor::shared_page_paddr(),
|
||||
process->m_shared_page_vaddr,
|
||||
PageTable::UserSupervisor | PageTable::Present
|
||||
);
|
||||
|
||||
TRY(auxiliary_vector.push_back({
|
||||
.a_type = LibELF::AT_SHARED_PAGE,
|
||||
.a_un = { .a_ptr = reinterpret_cast<void*>(process->m_shared_page_vaddr) },
|
||||
}));
|
||||
|
||||
TRY(auxiliary_vector.push_back({
|
||||
.a_type = LibELF::AT_NULL,
|
||||
.a_un = { .a_val = 0 },
|
||||
|
|
@ -697,13 +683,6 @@ namespace Kernel
|
|||
for (auto& mapped_region : m_mapped_regions)
|
||||
MUST(mapped_regions.push_back(TRY(mapped_region->clone(*page_table))));
|
||||
|
||||
const vaddr_t shared_page_vaddr = m_shared_page_vaddr;
|
||||
page_table->map_page_at(
|
||||
Processor::shared_page_paddr(),
|
||||
shared_page_vaddr,
|
||||
PageTable::UserSupervisor | PageTable::Present
|
||||
);
|
||||
|
||||
Process* forked = create_process(m_credentials, m_pid, m_sid, m_pgrp);
|
||||
forked->m_controlling_terminal = m_controlling_terminal;
|
||||
forked->m_working_directory = BAN::move(working_directory);
|
||||
|
|
@ -712,7 +691,6 @@ namespace Kernel
|
|||
forked->m_environ = BAN::move(environ);
|
||||
forked->m_executable = BAN::move(executable);
|
||||
forked->m_page_table = BAN::move(page_table);
|
||||
forked->m_shared_page_vaddr = BAN::move(shared_page_vaddr);
|
||||
forked->m_open_file_descriptors = BAN::move(*open_file_descriptors);
|
||||
forked->m_mapped_regions = BAN::move(mapped_regions);
|
||||
forked->m_has_called_exec = false;
|
||||
|
|
@ -788,20 +766,6 @@ namespace Kernel
|
|||
}));
|
||||
}
|
||||
|
||||
const vaddr_t shared_page_vaddr = new_page_table->reserve_free_page(new_mapped_regions.back()->vaddr(), USERSPACE_END);
|
||||
if (shared_page_vaddr == 0)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
new_page_table->map_page_at(
|
||||
Processor::shared_page_paddr(),
|
||||
shared_page_vaddr,
|
||||
PageTable::UserSupervisor | PageTable::Present
|
||||
);
|
||||
|
||||
TRY(auxiliary_vector.push_back({
|
||||
.a_type = LibELF::AT_SHARED_PAGE,
|
||||
.a_un = { .a_ptr = reinterpret_cast<void*>(shared_page_vaddr) },
|
||||
}));
|
||||
|
||||
TRY(auxiliary_vector.push_back({
|
||||
.a_type = LibELF::AT_NULL,
|
||||
.a_un = { .a_val = 0 },
|
||||
|
|
@ -873,9 +837,6 @@ namespace Kernel
|
|||
m_mapped_regions = BAN::move(new_mapped_regions);
|
||||
m_page_table = BAN::move(new_page_table);
|
||||
|
||||
m_shared_page_vaddr = shared_page_vaddr;
|
||||
m_threads.front()->update_processor_index_address();
|
||||
|
||||
execfd_guard.disable();
|
||||
|
||||
m_cmdline = BAN::move(str_argv);
|
||||
|
|
|
|||
|
|
@ -13,19 +13,12 @@ namespace Kernel
|
|||
static constexpr uint32_t MSR_IA32_FS_BASE = 0xC0000100;
|
||||
static constexpr uint32_t MSR_IA32_GS_BASE = 0xC0000101;
|
||||
static constexpr uint32_t MSR_IA32_KERNEL_GS_BASE = 0xC0000102;
|
||||
|
||||
static constexpr uint32_t MSR_IA32_EFER = 0xC0000080;
|
||||
static constexpr uint32_t MSR_IA32_STAR = 0xC0000081;
|
||||
static constexpr uint32_t MSR_IA32_LSTAR = 0xC0000082;
|
||||
static constexpr uint32_t MSR_IA32_FMASK = 0xC0000084;
|
||||
#endif
|
||||
|
||||
ProcessorID Processor::s_bsp_id { PROCESSOR_NONE };
|
||||
BAN::Atomic<uint8_t> Processor::s_processor_count { 0 };
|
||||
BAN::Atomic<bool> Processor::s_is_smp_enabled { false };
|
||||
BAN::Atomic<bool> Processor::s_should_print_cpu_load { false };
|
||||
paddr_t Processor::s_shared_page_paddr { 0 };
|
||||
vaddr_t Processor::s_shared_page_vaddr { 0 };
|
||||
ProcessorID Processor::s_bsp_id { PROCESSOR_NONE };
|
||||
BAN::Atomic<uint8_t> Processor::s_processor_count { 0 };
|
||||
BAN::Atomic<bool> Processor::s_is_smp_enabled { false };
|
||||
BAN::Atomic<bool> Processor::s_should_print_cpu_load { false };
|
||||
|
||||
static BAN::Atomic<uint8_t> s_processors_created { 0 };
|
||||
|
||||
|
|
@ -35,8 +28,6 @@ namespace Kernel
|
|||
static BAN::Array<Processor, 0xFF> s_processors;
|
||||
static BAN::Array<ProcessorID, 0xFF> s_processor_ids { PROCESSOR_NONE };
|
||||
|
||||
extern "C" void asm_syscall_handler();
|
||||
|
||||
ProcessorID Processor::read_processor_id()
|
||||
{
|
||||
uint32_t id;
|
||||
|
|
@ -94,53 +85,13 @@ namespace Kernel
|
|||
|
||||
// initialize GS
|
||||
#if ARCH(x86_64)
|
||||
{
|
||||
// set gs base to pointer to this processor
|
||||
const uint64_t val = reinterpret_cast<uint64_t>(&processor);
|
||||
const uint32_t val_hi = val >> 32;
|
||||
const uint32_t val_lo = val & 0xFFFFFFFF;
|
||||
asm volatile("wrmsr" :: "d"(val_hi), "a"(val_lo), "c"(MSR_IA32_GS_BASE));
|
||||
}
|
||||
// set gs base to pointer to this processor
|
||||
uint64_t ptr = reinterpret_cast<uint64_t>(&processor);
|
||||
uint32_t ptr_hi = ptr >> 32;
|
||||
uint32_t ptr_lo = ptr & 0xFFFFFFFF;
|
||||
asm volatile("wrmsr" :: "d"(ptr_hi), "a"(ptr_lo), "c"(MSR_IA32_GS_BASE));
|
||||
#elif ARCH(i686)
|
||||
asm volatile("movw %0, %%gs" :: "r"(0x28));
|
||||
#endif
|
||||
|
||||
#if ARCH(x86_64)
|
||||
// enable syscall instruction
|
||||
asm volatile("rdmsr; orb $1, %%al; wrmsr" :: "c"(MSR_IA32_EFER) : "eax", "edx");
|
||||
|
||||
{
|
||||
union STAR
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t : 32;
|
||||
uint16_t sel_ring0;
|
||||
uint16_t sel_ring3;
|
||||
};
|
||||
uint64_t raw;
|
||||
};
|
||||
|
||||
// set kernel and user segments
|
||||
const uint64_t val = STAR { .sel_ring0 = 0x08, .sel_ring3 = 0x18 | 3 }.raw;
|
||||
const uint32_t val_hi = val >> 32;
|
||||
const uint32_t val_lo = val & 0xFFFFFFFF;
|
||||
asm volatile("wrmsr" :: "d"(val_hi), "a"(val_lo), "c"(MSR_IA32_STAR));
|
||||
}
|
||||
{
|
||||
// set syscall handler address
|
||||
const uint64_t val = reinterpret_cast<uint64_t>(&asm_syscall_handler);
|
||||
const uint32_t val_hi = val >> 32;
|
||||
const uint32_t val_lo = val & 0xFFFFFFFF;
|
||||
asm volatile("wrmsr" :: "d"(val_hi), "a"(val_lo), "c"(MSR_IA32_LSTAR));
|
||||
}
|
||||
{
|
||||
// mask DF and IF
|
||||
const uint64_t val = (1 << 10) | (1 << 9);
|
||||
const uint32_t val_hi = val >> 32;
|
||||
const uint32_t val_lo = val & 0xFFFFFFFF;
|
||||
asm volatile("wrmsr" :: "d"(val_hi), "a"(val_lo), "c"(MSR_IA32_FMASK));
|
||||
}
|
||||
asm volatile("movw $0x28, %%ax; movw %%ax, %%gs" ::: "ax");
|
||||
#endif
|
||||
|
||||
ASSERT(processor.m_idt);
|
||||
|
|
@ -177,33 +128,6 @@ namespace Kernel
|
|||
processor.m_smp_free = smp_storage;
|
||||
}
|
||||
|
||||
void Processor::initialize_shared_page()
|
||||
{
|
||||
[[maybe_unused]] constexpr size_t max_processors = (PAGE_SIZE - sizeof(API::SharedPage)) / sizeof(decltype(*API::SharedPage::cpus));
|
||||
ASSERT(s_processors_created < max_processors);
|
||||
|
||||
s_shared_page_paddr = Heap::get().take_free_page();
|
||||
ASSERT(s_shared_page_paddr);
|
||||
|
||||
s_shared_page_vaddr = PageTable::kernel().reserve_free_page(KERNEL_OFFSET);
|
||||
ASSERT(s_shared_page_vaddr);
|
||||
|
||||
PageTable::kernel().map_page_at(
|
||||
s_shared_page_paddr,
|
||||
s_shared_page_vaddr,
|
||||
PageTable::ReadWrite | PageTable::Present
|
||||
);
|
||||
|
||||
memset(reinterpret_cast<void*>(s_shared_page_vaddr), 0, PAGE_SIZE);
|
||||
|
||||
auto& shared_page = *reinterpret_cast<volatile API::SharedPage*>(s_shared_page_vaddr);
|
||||
for (size_t i = 0; i <= 0xFF; i++)
|
||||
shared_page.__sequence[i] = i;
|
||||
shared_page.features = 0;
|
||||
|
||||
ASSERT(Processor::count() + sizeof(Kernel::API::SharedPage) <= PAGE_SIZE);
|
||||
}
|
||||
|
||||
ProcessorID Processor::id_from_index(size_t index)
|
||||
{
|
||||
ASSERT(index < s_processor_count);
|
||||
|
|
@ -218,11 +142,8 @@ namespace Kernel
|
|||
// wait until bsp is ready
|
||||
if (current_is_bsp())
|
||||
{
|
||||
initialize_shared_page();
|
||||
|
||||
s_processor_count = 1;
|
||||
s_processor_ids[0] = current_id();
|
||||
s_processors[current_id().as_u32()].m_index = 0;
|
||||
|
||||
// single processor system
|
||||
if (s_processors_created == 1)
|
||||
|
|
@ -246,10 +167,9 @@ namespace Kernel
|
|||
while (s_processor_count == 0)
|
||||
__builtin_ia32_pause();
|
||||
|
||||
const auto index = s_processor_count++;
|
||||
ASSERT(s_processor_ids[index] == PROCESSOR_NONE);
|
||||
s_processor_ids[index] = current_id();
|
||||
s_processors[current_id().as_u32()].m_index = index;
|
||||
auto lookup_index = s_processor_count++;
|
||||
ASSERT(s_processor_ids[lookup_index] == PROCESSOR_NONE);
|
||||
s_processor_ids[lookup_index] = current_id();
|
||||
|
||||
uint32_t expected = static_cast<uint32_t>(-1);
|
||||
s_first_ap_ready_ms.compare_exchange(expected, SystemTimer::get().ms_since_boot());
|
||||
|
|
@ -271,62 +191,6 @@ namespace Kernel
|
|||
}
|
||||
}
|
||||
|
||||
void Processor::initialize_tsc(uint8_t shift, uint64_t mult, uint64_t realtime_seconds)
|
||||
{
|
||||
auto& shared_page = Processor::shared_page();
|
||||
|
||||
shared_page.gettime_shared.shift = shift;
|
||||
shared_page.gettime_shared.mult = mult;
|
||||
shared_page.gettime_shared.realtime_seconds = realtime_seconds;
|
||||
|
||||
update_tsc();
|
||||
|
||||
broadcast_smp_message({
|
||||
.type = SMPMessage::Type::UpdateTSC,
|
||||
.dummy = 0,
|
||||
});
|
||||
|
||||
bool everyone_initialized { false };
|
||||
while (!everyone_initialized)
|
||||
{
|
||||
everyone_initialized = true;
|
||||
for (size_t i = 0; i < count(); i++)
|
||||
{
|
||||
if (shared_page.cpus[i].gettime_local.seq != 0)
|
||||
continue;
|
||||
everyone_initialized = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
shared_page.features |= API::SPF_GETTIME;
|
||||
}
|
||||
|
||||
void Processor::update_tsc()
|
||||
{
|
||||
auto& sgettime = shared_page().cpus[current_index()].gettime_local;
|
||||
sgettime.seq = sgettime.seq + 1;
|
||||
sgettime.last_ns = SystemTimer::get().ns_since_boot_no_tsc();
|
||||
sgettime.last_tsc = __builtin_ia32_rdtsc();
|
||||
sgettime.seq = sgettime.seq + 1;
|
||||
}
|
||||
|
||||
uint64_t Processor::ns_since_boot_tsc()
|
||||
{
|
||||
const auto& shared_page = Processor::shared_page();
|
||||
const auto& sgettime = shared_page.gettime_shared;
|
||||
const auto& lgettime = shared_page.cpus[current_index()].gettime_local;
|
||||
|
||||
auto state = get_interrupt_state();
|
||||
set_interrupt_state(InterruptState::Disabled);
|
||||
|
||||
const auto current_ns = lgettime.last_ns + (((__builtin_ia32_rdtsc() - lgettime.last_tsc) * sgettime.mult) >> sgettime.shift);
|
||||
|
||||
set_interrupt_state(state);
|
||||
|
||||
return current_ns;
|
||||
}
|
||||
|
||||
void Processor::handle_ipi()
|
||||
{
|
||||
handle_smp_messages();
|
||||
|
|
@ -376,9 +240,6 @@ namespace Kernel
|
|||
case SMPMessage::Type::UnblockThread:
|
||||
processor.m_scheduler->unblock_thread(message->unblock_thread);
|
||||
break;
|
||||
case SMPMessage::Type::UpdateTSC:
|
||||
update_tsc();
|
||||
break;
|
||||
#if WITH_PROFILING
|
||||
case SMPMessage::Type::StartProfiling:
|
||||
processor.start_profiling();
|
||||
|
|
@ -405,17 +266,36 @@ namespace Kernel
|
|||
|
||||
void Processor::load_segments()
|
||||
{
|
||||
load_fsbase();
|
||||
load_gsbase();
|
||||
{
|
||||
const auto addr = scheduler().current_thread().get_fsbase();
|
||||
#if ARCH(x86_64)
|
||||
uint32_t ptr_hi = addr >> 32;
|
||||
uint32_t ptr_lo = addr & 0xFFFFFFFF;
|
||||
asm volatile("wrmsr" :: "d"(ptr_hi), "a"(ptr_lo), "c"(MSR_IA32_FS_BASE));
|
||||
#elif ARCH(i686)
|
||||
gdt().set_fsbase(addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
const auto addr = scheduler().current_thread().get_gsbase();
|
||||
#if ARCH(x86_64)
|
||||
uint32_t ptr_hi = addr >> 32;
|
||||
uint32_t ptr_lo = addr & 0xFFFFFFFF;
|
||||
asm volatile("wrmsr" :: "d"(ptr_hi), "a"(ptr_lo), "c"(MSR_IA32_KERNEL_GS_BASE));
|
||||
#elif ARCH(i686)
|
||||
gdt().set_gsbase(addr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void Processor::load_fsbase()
|
||||
{
|
||||
const auto addr = scheduler().current_thread().get_fsbase();
|
||||
#if ARCH(x86_64)
|
||||
const uint32_t addr_hi = addr >> 32;
|
||||
const uint32_t addr_lo = addr & 0xFFFFFFFF;
|
||||
asm volatile("wrmsr" :: "d"(addr_hi), "a"(addr_lo), "c"(MSR_IA32_FS_BASE));
|
||||
uint32_t ptr_hi = addr >> 32;
|
||||
uint32_t ptr_lo = addr & 0xFFFFFFFF;
|
||||
asm volatile("wrmsr" :: "d"(ptr_hi), "a"(ptr_lo), "c"(MSR_IA32_FS_BASE));
|
||||
#elif ARCH(i686)
|
||||
gdt().set_fsbase(addr);
|
||||
#endif
|
||||
|
|
@ -425,9 +305,9 @@ namespace Kernel
|
|||
{
|
||||
const auto addr = scheduler().current_thread().get_gsbase();
|
||||
#if ARCH(x86_64)
|
||||
const uint32_t addr_hi = addr >> 32;
|
||||
const uint32_t addr_lo = addr & 0xFFFFFFFF;
|
||||
asm volatile("wrmsr" :: "d"(addr_hi), "a"(addr_lo), "c"(MSR_IA32_KERNEL_GS_BASE));
|
||||
uint32_t ptr_hi = addr >> 32;
|
||||
uint32_t ptr_lo = addr & 0xFFFFFFFF;
|
||||
asm volatile("wrmsr" :: "d"(ptr_hi), "a"(ptr_lo), "c"(MSR_IA32_KERNEL_GS_BASE));
|
||||
#elif ARCH(i686)
|
||||
gdt().set_gsbase(addr);
|
||||
#endif
|
||||
|
|
@ -495,14 +375,13 @@ namespace Kernel
|
|||
if (!is_smp_enabled())
|
||||
return;
|
||||
|
||||
const auto state = get_interrupt_state();
|
||||
auto state = get_interrupt_state();
|
||||
set_interrupt_state(InterruptState::Disabled);
|
||||
|
||||
const auto current_id = Processor::current_id();
|
||||
for (size_t i = 0; i < Processor::count(); i++)
|
||||
{
|
||||
const auto processor_id = s_processor_ids[i];
|
||||
if (processor_id != current_id)
|
||||
auto processor_id = s_processor_ids[i];
|
||||
if (processor_id != current_id())
|
||||
send_smp_message(processor_id, message, false);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -284,14 +284,9 @@ namespace Kernel
|
|||
thread->set_cpu_time_start();
|
||||
}
|
||||
|
||||
Processor::gdt().set_tss_stack(thread->kernel_stack_top());
|
||||
if (thread->is_userspace())
|
||||
{
|
||||
const vaddr_t kernel_stack_top = thread->kernel_stack_top();
|
||||
Processor::gdt().set_tss_stack(kernel_stack_top);
|
||||
Processor::set_thread_syscall_stack(kernel_stack_top);
|
||||
Processor::load_segments();
|
||||
}
|
||||
|
||||
*interrupt_stack = thread->interrupt_stack();
|
||||
*interrupt_registers = thread->interrupt_registers();
|
||||
|
||||
|
|
@ -392,9 +387,6 @@ namespace Kernel
|
|||
else
|
||||
m_block_queue.add_thread_with_wake_time(node);
|
||||
|
||||
if (auto* thread = node->thread; thread->is_userspace() && thread->has_process())
|
||||
thread->update_processor_index_address();
|
||||
|
||||
m_thread_count++;
|
||||
|
||||
Processor::set_interrupt_state(state);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
#include <BAN/Bitcast.h>
|
||||
#include <kernel/API/Syscall.h>
|
||||
#include <kernel/Debug.h>
|
||||
#include <kernel/InterruptStack.h>
|
||||
#include <kernel/Process.h>
|
||||
#include <kernel/Scheduler.h>
|
||||
#include <kernel/Syscall.h>
|
||||
#include <kernel/Timer/Timer.h>
|
||||
|
||||
#include <termios.h>
|
||||
|
|
@ -40,8 +40,10 @@ namespace Kernel
|
|||
|
||||
static bool is_restartable_syscall(int syscall);
|
||||
|
||||
extern "C" long cpp_syscall_handler(int syscall, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5)
|
||||
extern "C" long cpp_syscall_handler(int syscall, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, InterruptStack* interrupt_stack)
|
||||
{
|
||||
ASSERT(GDT::is_user_segment(interrupt_stack->cs));
|
||||
|
||||
Processor::set_interrupt_state(InterruptState::Enabled);
|
||||
|
||||
Process::current().wait_while_stopped();
|
||||
|
|
|
|||
|
|
@ -295,20 +295,6 @@ namespace Kernel
|
|||
m_cpu_time_start_ns = UINT64_MAX;
|
||||
}
|
||||
|
||||
void Thread::update_processor_index_address()
|
||||
{
|
||||
if (!is_userspace() || !has_process())
|
||||
return;
|
||||
|
||||
const vaddr_t vaddr = process().shared_page_vaddr() + Processor::current_index();
|
||||
|
||||
#if ARCH(x86_64)
|
||||
set_gsbase(vaddr);
|
||||
#elif ARCH(i686)
|
||||
set_fsbase(vaddr);
|
||||
#endif
|
||||
}
|
||||
|
||||
BAN::ErrorOr<Thread*> Thread::pthread_create(entry_t entry, void* arg)
|
||||
{
|
||||
auto* thread = TRY(create_userspace(m_process, m_process->page_table()));
|
||||
|
|
@ -490,11 +476,7 @@ namespace Kernel
|
|||
write_to_stack(cur_sp, 0x20 | 3);
|
||||
write_to_stack(cur_sp, sp);
|
||||
write_to_stack(cur_sp, 0x202);
|
||||
#if ARCH(x86_64)
|
||||
write_to_stack(cur_sp, 0x28 | 3);
|
||||
#elif ARCH(i686)
|
||||
write_to_stack(cur_sp, 0x18 | 3);
|
||||
#endif
|
||||
write_to_stack(cur_sp, ip);
|
||||
});
|
||||
|
||||
|
|
@ -908,9 +890,9 @@ namespace Kernel
|
|||
void Thread::save_sse()
|
||||
{
|
||||
#if ARCH(x86_64)
|
||||
__builtin_ia32_fxsave64(m_sse_storage);
|
||||
asm volatile("fxsave64 %0" :: "m"(m_sse_storage));
|
||||
#elif ARCH(i686)
|
||||
__builtin_ia32_fxsave(m_sse_storage);
|
||||
asm volatile("fxsave %0" :: "m"(m_sse_storage));
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
|
|
@ -919,9 +901,9 @@ namespace Kernel
|
|||
void Thread::load_sse()
|
||||
{
|
||||
#if ARCH(x86_64)
|
||||
__builtin_ia32_fxrstor64(m_sse_storage);
|
||||
asm volatile("fxrstor64 %0" :: "m"(m_sse_storage));
|
||||
#elif ARCH(i686)
|
||||
__builtin_ia32_fxrstor(m_sse_storage);
|
||||
asm volatile("fxrstor %0" :: "m"(m_sse_storage));
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -272,8 +272,6 @@ namespace Kernel
|
|||
m_last_ticks = current_ticks;
|
||||
}
|
||||
|
||||
SystemTimer::get().update_tsc();
|
||||
|
||||
if (should_invoke_scheduler())
|
||||
Processor::scheduler().timer_interrupt();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,8 +58,6 @@ namespace Kernel
|
|||
m_system_time_ms++;
|
||||
}
|
||||
|
||||
SystemTimer::get().update_tsc();
|
||||
|
||||
if (should_invoke_scheduler())
|
||||
Processor::scheduler().timer_interrupt();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
#include <BAN/Sort.h>
|
||||
|
||||
#include <kernel/CPUID.h>
|
||||
#include <kernel/Scheduler.h>
|
||||
#include <kernel/Timer/HPET.h>
|
||||
#include <kernel/Timer/PIT.h>
|
||||
|
|
@ -57,100 +54,19 @@ namespace Kernel
|
|||
Kernel::panic("Could not initialize any timer");
|
||||
}
|
||||
|
||||
void SystemTimer::initialize_tsc()
|
||||
{
|
||||
if (!CPUID::has_invariant_tsc())
|
||||
{
|
||||
dwarnln("CPU does not have an invariant TSC");
|
||||
return;
|
||||
}
|
||||
|
||||
const uint64_t tsc_freq = get_tsc_frequency();
|
||||
|
||||
dprintln("Initialized invariant TSC ({} Hz)", tsc_freq);
|
||||
|
||||
const uint8_t tsc_shift = 22;
|
||||
const uint64_t tsc_mult = (static_cast<uint64_t>(1'000'000'000) << tsc_shift) / tsc_freq;
|
||||
Processor::initialize_tsc(tsc_shift, tsc_mult, m_boot_time);
|
||||
|
||||
m_has_invariant_tsc = true;
|
||||
}
|
||||
|
||||
uint64_t SystemTimer::get_tsc_frequency() const
|
||||
{
|
||||
// take 5x 50 ms samples and use the median value
|
||||
|
||||
constexpr size_t tsc_sample_count = 5;
|
||||
constexpr size_t tsc_sample_ns = 50'000'000;
|
||||
|
||||
uint64_t tsc_freq_samples[tsc_sample_count];
|
||||
for (size_t i = 0; i < tsc_sample_count; i++)
|
||||
{
|
||||
const auto start_ns = m_timer->ns_since_boot();
|
||||
|
||||
const auto start_tsc = ({ __builtin_ia32_lfence(); __builtin_ia32_rdtsc(); });
|
||||
while (m_timer->ns_since_boot() < start_ns + tsc_sample_ns)
|
||||
Processor::pause();
|
||||
const auto stop_tsc = ({ __builtin_ia32_lfence(); __builtin_ia32_rdtsc(); });
|
||||
|
||||
const auto stop_ns = m_timer->ns_since_boot();
|
||||
|
||||
const auto duration_ns = stop_ns - start_ns;
|
||||
const auto count_tsc = stop_tsc - start_tsc;
|
||||
|
||||
tsc_freq_samples[i] = count_tsc * 1'000'000'000 / duration_ns;
|
||||
}
|
||||
|
||||
BAN::sort::sort(tsc_freq_samples, tsc_freq_samples + tsc_sample_count);
|
||||
|
||||
return tsc_freq_samples[tsc_sample_count / 2];
|
||||
}
|
||||
|
||||
void SystemTimer::update_tsc() const
|
||||
{
|
||||
if (!m_has_invariant_tsc)
|
||||
return;
|
||||
|
||||
// only update every 100 ms
|
||||
if (++m_timer_ticks < 100)
|
||||
return;
|
||||
m_timer_ticks = 0;
|
||||
|
||||
Processor::update_tsc();
|
||||
Processor::broadcast_smp_message({
|
||||
.type = Processor::SMPMessage::Type::UpdateTSC,
|
||||
.dummy = 0,
|
||||
});
|
||||
}
|
||||
|
||||
uint64_t SystemTimer::ns_since_boot_no_tsc() const
|
||||
{
|
||||
return m_timer->ns_since_boot();
|
||||
}
|
||||
|
||||
uint64_t SystemTimer::ms_since_boot() const
|
||||
{
|
||||
if (!m_has_invariant_tsc)
|
||||
return m_timer->ms_since_boot();
|
||||
return Processor::ns_since_boot_tsc() / 1'000'000;
|
||||
return m_timer->ms_since_boot();
|
||||
}
|
||||
|
||||
uint64_t SystemTimer::ns_since_boot() const
|
||||
{
|
||||
if (!m_has_invariant_tsc)
|
||||
return m_timer->ns_since_boot();
|
||||
return Processor::ns_since_boot_tsc();
|
||||
return m_timer->ns_since_boot();
|
||||
}
|
||||
|
||||
timespec SystemTimer::time_since_boot() const
|
||||
{
|
||||
if (!m_has_invariant_tsc)
|
||||
return m_timer->time_since_boot();
|
||||
const auto ns_since_boot = Processor::ns_since_boot_tsc();
|
||||
return {
|
||||
.tv_sec = static_cast<time_t>(ns_since_boot / 1'000'000'000),
|
||||
.tv_nsec = static_cast<long>(ns_since_boot % 1'000'000'000)
|
||||
};
|
||||
return m_timer->time_since_boot();
|
||||
}
|
||||
|
||||
bool SystemTimer::pre_scheduler_sleep_needs_lock() const
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include <kernel/Processor.h>
|
||||
#include <kernel/Random.h>
|
||||
#include <kernel/Scheduler.h>
|
||||
#include <kernel/Syscall.h>
|
||||
#include <kernel/Terminal/FramebufferTerminal.h>
|
||||
#include <kernel/Terminal/Serial.h>
|
||||
#include <kernel/Terminal/VirtualTTY.h>
|
||||
|
|
@ -207,8 +208,6 @@ static void init2(void*)
|
|||
|
||||
dprintln("Scheduler started");
|
||||
|
||||
SystemTimer::get().initialize_tsc();
|
||||
|
||||
auto console = MUST(DevFileSystem::get().root_inode()->find_inode(cmdline.console));
|
||||
ASSERT(console->is_tty());
|
||||
static_cast<Kernel::TTY*>(console.ptr())->set_as_current();
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
#!/bin/bash ../install.sh
|
||||
|
||||
NAME='freetype'
|
||||
VERSION='2.14.1'
|
||||
DOWNLOAD_URL="https://download.savannah.gnu.org/releases/freetype/freetype-$VERSION.tar.xz#32427e8c471ac095853212a37aef816c60b42052d4d9e48230bab3bdf2936ccc"
|
||||
VERSION='2.13.3'
|
||||
DOWNLOAD_URL="https://download.savannah.gnu.org/releases/freetype/freetype-$VERSION.tar.gz#5c3a8e78f7b24c20b25b54ee575d6daa40007a5f4eea2845861c3409b3021747"
|
||||
DEPENDENCIES=('zlib' 'libpng')
|
||||
CONFIG_SUB=('builds/unix/config.sub')
|
||||
CONFIGURE_OPTIONS=(
|
||||
|
|
|
|||
|
|
@ -3,11 +3,12 @@
|
|||
NAME='openal-soft'
|
||||
VERSION='1.24.3'
|
||||
DOWNLOAD_URL="https://github.com/kcat/openal-soft/archive/refs/tags/$VERSION.tar.gz#7e1fecdeb45e7f78722b776c5cf30bd33934b961d7fd2a11e0494e064cc631ce"
|
||||
DEPENDENCIES=('SDL2' 'zlib' 'libsndfile')
|
||||
DEPENDENCIES=('zlib' 'libsndfile')
|
||||
|
||||
configure() {
|
||||
$BANAN_CMAKE -B build -S . -G Ninja --fresh \
|
||||
$BANAN_CMAKE \
|
||||
--toolchain="$BANAN_TOOLCHAIN_DIR/Toolchain.txt" \
|
||||
-B build -G Ninja --fresh . \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DALSOFT_EXAMPLES=OFF \
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
#!/bin/bash ../install.sh
|
||||
|
||||
NAME='openssl'
|
||||
VERSION='3.6.0'
|
||||
DOWNLOAD_URL="https://github.com/openssl/openssl/releases/download/openssl-$VERSION/openssl-$VERSION.tar.gz#b6a5f44b7eb69e3fa35dbf15524405b44837a481d43d81daddde3ff21fcbb8e9"
|
||||
VERSION='3.3.1'
|
||||
DOWNLOAD_URL="https://github.com/openssl/openssl/releases/download/openssl-$VERSION/openssl-$VERSION.tar.gz#777cd596284c883375a2a7a11bf5d2786fc5413255efab20c50d6ffe6d020b7e"
|
||||
DEPENDENCIES=('zlib')
|
||||
MAKE_INSTALL_TARGETS=('install_sw' 'install_ssldirs')
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
diff -ruN openssl-3.3.1/crypto/bio/bss_dgram.c openssl-3.3.1-banan_os/crypto/bio/bss_dgram.c
|
||||
--- openssl-3.3.1/crypto/bio/bss_dgram.c 2024-06-04 15:53:04.000000000 +0300
|
||||
+++ openssl-3.3.1-banan_os/crypto/bio/bss_dgram.c 2025-06-01 19:48:55.088806701 +0300
|
||||
@@ -61,7 +61,7 @@
|
||||
# define NO_RECVMMSG
|
||||
# endif
|
||||
# endif
|
||||
-# if defined(__GNU__)
|
||||
+# if defined(__GNU__) || defined(__banan_os__)
|
||||
/* GNU/Hurd does not have IP_PKTINFO yet */
|
||||
#undef NO_RECVMSG
|
||||
#define NO_RECVMSG
|
||||
|
|
@ -34,16 +34,10 @@ NET_ARGS="-device e1000e,netdev=net $NET_ARGS"
|
|||
|
||||
USB_ARGS='-device qemu-xhci -device usb-kbd,port=1 -device usb-hub,port=2 -device usb-tablet,port=2.1'
|
||||
|
||||
#SOUND_ARGS='-device ac97'
|
||||
SOUND_ARGS='-device intel-hda -device hda-output'
|
||||
|
||||
if [[ $@ == *"-accel kvm"* ]]; then
|
||||
CPU_ARGS='-cpu host,migratable=off'
|
||||
fi
|
||||
SOUND_ARGS='-device ac97'
|
||||
|
||||
qemu-system-$QEMU_ARCH \
|
||||
-m 1G -smp 4 \
|
||||
$CPU_ARGS \
|
||||
$BIOS_ARGS \
|
||||
$USB_ARGS \
|
||||
$DISK_ARGS \
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@
|
|||
#include <BAN/Debug.h>
|
||||
#include <BAN/Math.h>
|
||||
|
||||
#include <kernel/API/SharedPage.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <langinfo.h>
|
||||
|
|
@ -17,53 +15,9 @@ int daylight;
|
|||
long timezone;
|
||||
char* tzname[2];
|
||||
|
||||
extern volatile Kernel::API::SharedPage* g_shared_page;
|
||||
|
||||
int clock_gettime(clockid_t clock_id, struct timespec* tp)
|
||||
{
|
||||
if (clock_id != CLOCK_MONOTONIC && clock_id != CLOCK_REALTIME)
|
||||
return syscall(SYS_CLOCK_GETTIME, clock_id, tp);
|
||||
|
||||
if (g_shared_page == nullptr || !(g_shared_page->features & Kernel::API::SPF_GETTIME))
|
||||
return syscall(SYS_CLOCK_GETTIME, clock_id, tp);
|
||||
|
||||
const auto get_cpu =
|
||||
[]() -> uint8_t {
|
||||
uint8_t cpu;
|
||||
#if defined(__x86_64__)
|
||||
asm volatile("movb %%gs:0, %0" : "=r"(cpu));
|
||||
#elif defined(__i686__)
|
||||
asm volatile("movb %%fs:0, %0" : "=q"(cpu));
|
||||
#endif
|
||||
return cpu;
|
||||
};
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const auto cpu = get_cpu();
|
||||
|
||||
const auto& sgettime = g_shared_page->gettime_shared;
|
||||
const auto& lgettime = g_shared_page->cpus[cpu].gettime_local;
|
||||
|
||||
const auto old_seq = lgettime.seq;
|
||||
if (old_seq & 1)
|
||||
continue;
|
||||
|
||||
const auto monotonic_ns = lgettime.last_ns + (((__builtin_ia32_rdtsc() - lgettime.last_tsc) * sgettime.mult) >> sgettime.shift);
|
||||
|
||||
if (old_seq != lgettime.seq || cpu != get_cpu())
|
||||
continue;
|
||||
|
||||
*tp = {
|
||||
.tv_sec = static_cast<time_t>(monotonic_ns / 1'000'000'000),
|
||||
.tv_nsec = static_cast<long>(monotonic_ns % 1'000'000'000)
|
||||
};
|
||||
|
||||
if (clock_id == CLOCK_REALTIME)
|
||||
tp->tv_sec += sgettime.realtime_seconds;
|
||||
|
||||
return monotonic_ns;
|
||||
}
|
||||
return syscall(SYS_CLOCK_GETTIME, clock_id, tp);
|
||||
}
|
||||
|
||||
int clock_getres(clockid_t clock_id, struct timespec* res)
|
||||
|
|
|
|||
|
|
@ -2,11 +2,8 @@
|
|||
#include <BAN/Debug.h>
|
||||
#include <BAN/StringView.h>
|
||||
|
||||
#include <LibELF/AuxiliaryVector.h>
|
||||
|
||||
#include <kernel/API/SharedPage.h>
|
||||
#include <kernel/API/Syscall.h>
|
||||
#include <kernel/Memory/Types.h>
|
||||
#include <kernel/Syscall.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <dlfcn.h>
|
||||
|
|
@ -34,8 +31,6 @@ struct init_funcs_t
|
|||
|
||||
extern "C" char** environ;
|
||||
|
||||
volatile Kernel::API::SharedPage* g_shared_page = nullptr;
|
||||
|
||||
#define DUMP_BACKTRACE 1
|
||||
#define DEMANGLE_BACKTRACE 0
|
||||
|
||||
|
|
@ -45,28 +40,11 @@ volatile Kernel::API::SharedPage* g_shared_page = nullptr;
|
|||
|
||||
static void __dump_backtrace(int, siginfo_t*, void*);
|
||||
|
||||
static LibELF::AuxiliaryVector* find_auxv(char** envp)
|
||||
{
|
||||
if (envp == nullptr)
|
||||
return nullptr;
|
||||
|
||||
char** null_env = envp;
|
||||
while (*null_env)
|
||||
null_env++;
|
||||
|
||||
return reinterpret_cast<LibELF::AuxiliaryVector*>(null_env + 1);
|
||||
}
|
||||
|
||||
extern "C" void _init_libc(char** environ, init_funcs_t init_funcs, init_funcs_t fini_funcs)
|
||||
{
|
||||
if (::environ == nullptr)
|
||||
::environ = environ;
|
||||
|
||||
if (auto* auxv = find_auxv(environ))
|
||||
for (auto* aux = auxv; aux->a_type != LibELF::AT_NULL; aux++)
|
||||
if (aux->a_type == LibELF::AT_SHARED_PAGE)
|
||||
g_shared_page = static_cast<Kernel::API::SharedPage*>(aux->a_un.a_ptr);
|
||||
|
||||
#if defined(__x86_64__)
|
||||
if (uthread* self = reinterpret_cast<uthread*>(syscall(SYS_GET_FSBASE)))
|
||||
#elif defined(__i686__)
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@ namespace LibELF
|
|||
AT_PHDR = 3,
|
||||
AT_PHENT = 4,
|
||||
AT_PHNUM = 5,
|
||||
|
||||
AT_SHARED_PAGE = 0xFFFF0001,
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <BAN/Traits.h>
|
||||
#include <kernel/API/Syscall.h>
|
||||
#include <kernel/Syscall.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
|
|
|||
Loading…
Reference in New Issue