Skip to content

Commit

Permalink
Kernel: Take some baby steps towards x86_64
Browse files Browse the repository at this point in the history
Make more of the kernel compile in 64-bit mode, and make some things
pointer-size-agnostic (by using FlatPtr.)

There's a lot of work to do here before the kernel will even compile.
  • Loading branch information
awesomekling committed Feb 25, 2021
1 parent eb08a0e commit 8f70528
Show file tree
Hide file tree
Showing 12 changed files with 187 additions and 118 deletions.
2 changes: 1 addition & 1 deletion Kernel/API/Syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ struct SC_futex_params {
u32 val;
union {
const timespec* timeout;
u32 val2;
uintptr_t val2;
};
u32* userspace_address2;
u32 val3;
Expand Down
90 changes: 66 additions & 24 deletions Kernel/Arch/i386/CPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,7 @@ void page_fault_handler(TrapFrame* trap)
clac();

auto& regs = *trap->regs;
u32 fault_address;
asm("movl %%cr2, %%eax"
: "=a"(fault_address));
auto fault_address = read_cr2();

if constexpr (PAGE_FAULT_DEBUG) {
u32 fault_page_directory = read_cr3();
Expand Down Expand Up @@ -717,14 +715,22 @@ void exit_trap(TrapFrame* trap)
return Processor::current().exit_trap(*trap);
}

UNMAP_AFTER_INIT void write_cr0(u32 value)
UNMAP_AFTER_INIT void write_cr0(FlatPtr value)
{
asm volatile("movl %%eax, %%cr0" ::"a"(value));
#if ARCH(I386)
asm volatile("mov %%eax, %%cr0" ::"a"(value));
#else
asm volatile("mov %%rax, %%cr0" ::"a"(value));
#endif
}

UNMAP_AFTER_INIT void write_cr4(u32 value)
UNMAP_AFTER_INIT void write_cr4(FlatPtr value)
{
asm volatile("movl %%eax, %%cr4" ::"a"(value));
#if ARCH(I386)
asm volatile("mov %%eax, %%cr4" ::"a"(value));
#else
asm volatile("mov %%rax, %%cr4" ::"a"(value));
#endif
}

UNMAP_AFTER_INIT static void sse_init()
Expand All @@ -733,50 +739,80 @@ UNMAP_AFTER_INIT static void sse_init()
write_cr4(read_cr4() | 0x600);
}

u32 read_cr0()
FlatPtr read_cr0()
{
u32 cr0;
asm("movl %%cr0, %%eax"
FlatPtr cr0;
#if ARCH(I386)
asm("mov %%cr0, %%eax"
: "=a"(cr0));
#else
asm("mov %%cr0, %%rax"
: "=a"(cr0));
#endif
return cr0;
}

u32 read_cr2()
FlatPtr read_cr2()
{
u32 cr2;
asm("movl %%cr2, %%eax"
FlatPtr cr2;
#if ARCH(I386)
asm("mov %%cr2, %%eax"
: "=a"(cr2));
#else
asm("mov %%cr2, %%rax"
: "=a"(cr2));
#endif
return cr2;
}

u32 read_cr3()
FlatPtr read_cr3()
{
u32 cr3;
asm("movl %%cr3, %%eax"
FlatPtr cr3;
#if ARCH(I386)
asm("mov %%cr3, %%eax"
: "=a"(cr3));
#else
asm("mov %%cr3, %%rax"
: "=a"(cr3));
#endif
return cr3;
}

void write_cr3(u32 cr3)
void write_cr3(FlatPtr cr3)
{
// NOTE: If you're here from a GPF crash, it's very likely that a PDPT entry is incorrect, not this!
asm volatile("movl %%eax, %%cr3" ::"a"(cr3)
#if ARCH(I386)
asm volatile("mov %%eax, %%cr3" ::"a"(cr3)
: "memory");
#else
asm volatile("mov %%rax, %%cr3" ::"a"(cr3)
: "memory");
#endif
}

u32 read_cr4()
FlatPtr read_cr4()
{
u32 cr4;
asm("movl %%cr4, %%eax"
FlatPtr cr4;
#if ARCH(I386)
asm("mov %%cr4, %%eax"
: "=a"(cr4));
#else
asm("mov %%cr4, %%rax"
: "=a"(cr4));
#endif
return cr4;
}

u32 read_dr6()
FlatPtr read_dr6()
{
u32 dr6;
asm("movl %%dr6, %%eax"
FlatPtr dr6;
#if ARCH(I386)
asm("mov %%dr6, %%eax"
: "=a"(dr6));
#else
asm("mov %%dr6, %%rax"
: "=a"(dr6));
#endif
return dr6;
}

Expand Down Expand Up @@ -1291,6 +1327,7 @@ void Processor::switch_context(Thread*& from_thread, Thread*& to_thread)
dbgln_if(CONTEXT_SWITCH_DEBUG, "switch_context --> switching out of: {} {}", VirtualAddress(from_thread), *from_thread);
from_thread->save_critical(m_in_critical);

#if ARCH(I386)
// clang-format off
// Switch to new thread context, passing from_thread and to_thread
// through to the new context using registers edx and eax
Expand Down Expand Up @@ -1333,6 +1370,9 @@ void Processor::switch_context(Thread*& from_thread, Thread*& to_thread)
: "memory"
);
// clang-format on
#else
PANIC("Context switching not implemented.");
#endif

dbgln_if(CONTEXT_SWITCH_DEBUG, "switch_context <-- from {} {} to {} {}", VirtualAddress(from_thread), *from_thread, VirtualAddress(to_thread), *to_thread);

Expand Down Expand Up @@ -1576,6 +1616,7 @@ UNMAP_AFTER_INIT void Processor::initialize_context_switching(Thread& initial_th

m_scheduler_initialized = true;

#if ARCH(I386)
// clang-format off
asm volatile(
"movl %[new_esp], %%esp \n" // switch to new stack
Expand All @@ -1601,6 +1642,7 @@ UNMAP_AFTER_INIT void Processor::initialize_context_switching(Thread& initial_th
[cpu] "c" (id())
);
// clang-format on
#endif

VERIFY_NOT_REACHED();
}
Expand Down
72 changes: 42 additions & 30 deletions Kernel/Arch/i386/CPU.h
Original file line number Diff line number Diff line change
Expand Up @@ -296,9 +296,9 @@ void load_task_register(u16 selector);
#define sti() asm volatile("sti" :: \
: "memory")

inline u32 cpu_flags()
inline FlatPtr cpu_flags()
{
u32 flags;
FlatPtr flags;
asm volatile(
"pushf\n"
"pop %0\n"
Expand Down Expand Up @@ -441,29 +441,36 @@ class PageFault {
};

struct [[gnu::packed]] RegisterState {
u32 ss;
u32 gs;
u32 fs;
u32 es;
u32 ds;
u32 edi;
u32 esi;
u32 ebp;
u32 esp;
u32 ebx;
u32 edx;
u32 ecx;
u32 eax;
FlatPtr ss;
FlatPtr gs;
FlatPtr fs;
FlatPtr es;
FlatPtr ds;
FlatPtr edi;
FlatPtr esi;
FlatPtr ebp;
FlatPtr esp;
FlatPtr ebx;
FlatPtr edx;
FlatPtr ecx;
FlatPtr eax;
u16 exception_code;
u16 isr_number;
u32 eip;
u32 cs;
u32 eflags;
u32 userspace_esp;
u32 userspace_ss;
#if ARCH(X86_64)
u32 padding;
#endif
FlatPtr eip;
FlatPtr cs;
FlatPtr eflags;
FlatPtr userspace_esp;
FlatPtr userspace_ss;
};

#define REGISTER_STATE_SIZE (19 * 4)
#if ARCH(I386)
# define REGISTER_STATE_SIZE (19 * 4)
#else
# define REGISTER_STATE_SIZE (19 * 8)
#endif
static_assert(REGISTER_STATE_SIZE == sizeof(RegisterState));

void copy_kernel_registers_into_ptrace_registers(PtraceRegisters&, const RegisterState&);
Expand Down Expand Up @@ -494,16 +501,16 @@ inline FlatPtr offset_in_page(const void* address)
return offset_in_page((FlatPtr)address);
}

u32 read_cr0();
u32 read_cr2();
u32 read_cr3();
u32 read_cr4();
FlatPtr read_cr0();
FlatPtr read_cr2();
FlatPtr read_cr3();
FlatPtr read_cr4();

void write_cr0(u32);
void write_cr3(u32);
void write_cr4(u32);
void write_cr0(FlatPtr);
void write_cr3(FlatPtr);
void write_cr4(FlatPtr);

u32 read_dr6();
FlatPtr read_dr6();

static inline bool is_kernel_mode()
{
Expand Down Expand Up @@ -1071,7 +1078,12 @@ struct TrapFrame {
TrapFrame& operator=(TrapFrame&&) = delete;
};

#define TRAP_FRAME_SIZE (3 * sizeof(FlatPtr))
#if ARCH(I386)
# define TRAP_FRAME_SIZE (3 * 4)
#else
# define TRAP_FRAME_SIZE (3 * 8)
#endif

static_assert(TRAP_FRAME_SIZE == sizeof(TrapFrame));

extern "C" void enter_trap_no_irq(TrapFrame*);
Expand Down
2 changes: 2 additions & 0 deletions Kernel/Heap/SlabAllocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,9 @@ static SlabAllocator<32> s_slab_allocator_32;
static SlabAllocator<64> s_slab_allocator_64;
static SlabAllocator<128> s_slab_allocator_128;

#if ARCH(I386)
static_assert(sizeof(Region) <= s_slab_allocator_128.slab_size());
#endif

template<typename Callback>
void for_each_allocator(Callback callback)
Expand Down
6 changes: 3 additions & 3 deletions Kernel/KSyms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ static u8 parse_hex_digit(char nibble)
return 10 + (nibble - 'a');
}

u32 address_for_kernel_symbol(const StringView& name)
FlatPtr address_for_kernel_symbol(const StringView& name)
{
for (size_t i = 0; i < s_symbol_count; ++i) {
if (!strncmp(name.characters_without_null_termination(), s_symbols[i].name, name.length()))
Expand All @@ -57,7 +57,7 @@ u32 address_for_kernel_symbol(const StringView& name)
return 0;
}

const KernelSymbol* symbolicate_kernel_address(u32 address)
const KernelSymbol* symbolicate_kernel_address(FlatPtr address)
{
if (address < g_lowest_kernel_symbol_address || address > g_highest_kernel_symbol_address)
return nullptr;
Expand Down Expand Up @@ -147,7 +147,7 @@ NEVER_INLINE static void dump_backtrace_impl(FlatPtr base_pointer, bool use_ksym
FlatPtr* stack_ptr = (FlatPtr*)base_pointer;
while (stack_ptr && safe_memcpy(copied_stack_ptr, stack_ptr, sizeof(copied_stack_ptr), fault_at)) {
FlatPtr retaddr = copied_stack_ptr[1];
dbgln("{:p} (next: {:p})", retaddr, stack_ptr ? (u32*)copied_stack_ptr[0] : 0);
dbgln("{:p} (next: {:p})", retaddr, stack_ptr ? (FlatPtr*)copied_stack_ptr[0] : 0);
stack_ptr = (FlatPtr*)copied_stack_ptr[0];
}
return;
Expand Down
6 changes: 3 additions & 3 deletions Kernel/KSyms.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@
namespace Kernel {

struct KernelSymbol {
u32 address;
FlatPtr address;
const char* name;
};

u32 address_for_kernel_symbol(const StringView& name);
const KernelSymbol* symbolicate_kernel_address(u32 address);
FlatPtr address_for_kernel_symbol(const StringView& name);
const KernelSymbol* symbolicate_kernel_address(FlatPtr);
void load_kernel_symbol_table();

extern bool g_kernel_symbols_available;
Expand Down
4 changes: 4 additions & 0 deletions Kernel/Process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ Process::~Process()
extern void signal_trampoline_dummy();
void signal_trampoline_dummy()
{
#if ARCH(I386)
// The trampoline preserves the current eax, pushes the signal code and
// then calls the signal handler. We do this because, when interrupting a
// blocking syscall, that syscall may return some special error code in eax;
Expand All @@ -280,6 +281,9 @@ void signal_trampoline_dummy()
"int 0x82\n" // sigreturn syscall
"asm_signal_trampoline_end:\n"
".att_syntax" ::"i"(Syscall::SC_sigreturn));
#else
// FIXME: Implement trampoline for other architectures.
#endif
}

extern "C" void asm_signal_trampoline(void);
Expand Down
6 changes: 3 additions & 3 deletions Kernel/Process.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,8 @@ class Process
[[noreturn]] void sys$exit(int status);
int sys$sigreturn(RegisterState& registers);
pid_t sys$waitid(Userspace<const Syscall::SC_waitid_params*>);
void* sys$mmap(Userspace<const Syscall::SC_mmap_params*>);
void* sys$mremap(Userspace<const Syscall::SC_mremap_params*>);
FlatPtr sys$mmap(Userspace<const Syscall::SC_mmap_params*>);
FlatPtr sys$mremap(Userspace<const Syscall::SC_mremap_params*>);
int sys$munmap(void*, size_t size);
int sys$set_mmap_name(Userspace<const Syscall::SC_set_mmap_name_params*>);
int sys$mprotect(void*, size_t, int prot);
Expand Down Expand Up @@ -352,7 +352,7 @@ class Process
int sys$recvfd(int sockfd, int options);
long sys$sysconf(int name);
int sys$disown(ProcessID);
void* sys$allocate_tls(size_t);
FlatPtr sys$allocate_tls(size_t);
int sys$prctl(int option, FlatPtr arg1, FlatPtr arg2);
int sys$set_coredump_metadata(Userspace<const Syscall::SC_set_coredump_metadata_params*>);
void sys$abort();
Expand Down
Loading

0 comments on commit 8f70528

Please sign in to comment.