summaryrefslogtreecommitdiff
path: root/Kernel/Arch/i386
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel/Arch/i386')
-rw-r--r--Kernel/Arch/i386/CPU.cpp20
-rw-r--r--Kernel/Arch/i386/CPU.h1143
-rw-r--r--Kernel/Arch/i386/ISRStubs.h206
-rw-r--r--Kernel/Arch/i386/InterruptEntry.cpp (renamed from Kernel/Arch/i386/Interrupts.h)42
-rw-r--r--Kernel/Arch/i386/ProcessorInfo.cpp4
-rw-r--r--Kernel/Arch/i386/ProcessorInfo.h61
-rw-r--r--Kernel/Arch/i386/SafeMem.cpp4
-rw-r--r--Kernel/Arch/i386/SafeMem.h120
8 files changed, 19 insertions, 1581 deletions
diff --git a/Kernel/Arch/i386/CPU.cpp b/Kernel/Arch/i386/CPU.cpp
index 9be852f6de..a26debf3ba 100644
--- a/Kernel/Arch/i386/CPU.cpp
+++ b/Kernel/Arch/i386/CPU.cpp
@@ -29,10 +29,10 @@
#include <AK/String.h>
#include <AK/StringBuilder.h>
#include <AK/Types.h>
-#include <Kernel/Arch/i386/CPU.h>
-#include <Kernel/Arch/i386/ISRStubs.h>
-#include <Kernel/Arch/i386/ProcessorInfo.h>
-#include <Kernel/Arch/i386/SafeMem.h>
+#include <Kernel/Arch/x86/CPU.h>
+#include <Kernel/Arch/x86/ISRStubs.h>
+#include <Kernel/Arch/x86/ProcessorInfo.h>
+#include <Kernel/Arch/x86/SafeMem.h>
#include <Kernel/Debug.h>
#include <Kernel/IO.h>
#include <Kernel/Interrupts/APIC.h>
@@ -2309,8 +2309,8 @@ UNMAP_AFTER_INIT void Processor::gdt_init()
tls_descriptor.dpl = 3;
tls_descriptor.segment_present = 1;
tls_descriptor.granularity = 0;
- tls_descriptor.zero = 0;
- tls_descriptor.operation_size = 1;
+ tls_descriptor.operation_size64 = 0;
+ tls_descriptor.operation_size32 = 1;
tls_descriptor.descriptor_type = 1;
tls_descriptor.type = 2;
write_gdt_entry(GDT_SELECTOR_TLS, tls_descriptor); // tls3
@@ -2321,8 +2321,8 @@ UNMAP_AFTER_INIT void Processor::gdt_init()
fs_descriptor.dpl = 0;
fs_descriptor.segment_present = 1;
fs_descriptor.granularity = 0;
- fs_descriptor.zero = 0;
- fs_descriptor.operation_size = 1;
+ fs_descriptor.operation_size64 = 0;
+ fs_descriptor.operation_size32 = 1;
fs_descriptor.descriptor_type = 1;
fs_descriptor.type = 2;
write_gdt_entry(GDT_SELECTOR_PROC, fs_descriptor); // fs0
@@ -2333,8 +2333,8 @@ UNMAP_AFTER_INIT void Processor::gdt_init()
tss_descriptor.dpl = 0;
tss_descriptor.segment_present = 1;
tss_descriptor.granularity = 0;
- tss_descriptor.zero = 0;
- tss_descriptor.operation_size = 1;
+ tss_descriptor.operation_size64 = 0;
+ tss_descriptor.operation_size32 = 1;
tss_descriptor.descriptor_type = 0;
tss_descriptor.type = 9;
write_gdt_entry(GDT_SELECTOR_TSS, tss_descriptor); // tss
diff --git a/Kernel/Arch/i386/CPU.h b/Kernel/Arch/i386/CPU.h
deleted file mode 100644
index 54a61eb8dc..0000000000
--- a/Kernel/Arch/i386/CPU.h
+++ /dev/null
@@ -1,1143 +0,0 @@
-/*
- * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#include <AK/Atomic.h>
-#include <AK/Badge.h>
-#include <AK/Noncopyable.h>
-#include <AK/Vector.h>
-#include <Kernel/PhysicalAddress.h>
-#include <Kernel/VirtualAddress.h>
-#include <LibC/sys/arch/i386/regs.h>
-
-#define READONLY_AFTER_INIT __attribute__((section(".ro_after_init")))
-#define UNMAP_AFTER_INIT NEVER_INLINE __attribute__((section(".unmap_after_init")))
-
-#define PAGE_SIZE 4096
-#define GENERIC_INTERRUPT_HANDLERS_COUNT (256 - IRQ_VECTOR_BASE)
-#define PAGE_MASK ((FlatPtr)0xfffff000u)
-
-namespace Kernel {
-
-class MemoryManager;
-class PageDirectory;
-class PageTableEntry;
-
-static constexpr u32 safe_eflags_mask = 0xdff;
-static constexpr u32 iopl_mask = 3u << 12;
-
-inline u32 get_iopl_from_eflags(u32 eflags)
-{
- return (eflags & iopl_mask) >> 12;
-}
-
-struct [[gnu::packed]] DescriptorTablePointer {
- u16 limit;
- void* address;
-};
-
-struct [[gnu::packed]] TSS32 {
- u16 backlink, __blh;
- u32 esp0;
- u16 ss0, __ss0h;
- u32 esp1;
- u16 ss1, __ss1h;
- u32 esp2;
- u16 ss2, __ss2h;
- u32 cr3, eip, eflags;
- u32 eax, ecx, edx, ebx, esp, ebp, esi, edi;
- u16 es, __esh;
- u16 cs, __csh;
- u16 ss, __ssh;
- u16 ds, __dsh;
- u16 fs, __fsh;
- u16 gs, __gsh;
- u16 ldt, __ldth;
- u16 trace, iomapbase;
-};
-
-union [[gnu::packed]] Descriptor {
- struct {
- u16 limit_lo;
- u16 base_lo;
- u8 base_hi;
- u8 type : 4;
- u8 descriptor_type : 1;
- u8 dpl : 2;
- u8 segment_present : 1;
- u8 limit_hi : 4;
- u8 : 1;
- u8 zero : 1;
- u8 operation_size : 1;
- u8 granularity : 1;
- u8 base_hi2;
- };
- struct {
- u32 low;
- u32 high;
- };
-
- enum Type {
- Invalid = 0,
- AvailableTSS_16bit = 0x1,
- LDT = 0x2,
- BusyTSS_16bit = 0x3,
- CallGate_16bit = 0x4,
- TaskGate = 0x5,
- InterruptGate_16bit = 0x6,
- TrapGate_16bit = 0x7,
- AvailableTSS_32bit = 0x9,
- BusyTSS_32bit = 0xb,
- CallGate_32bit = 0xc,
- InterruptGate_32bit = 0xe,
- TrapGate_32bit = 0xf,
- };
-
- VirtualAddress base() const
- {
- FlatPtr base = base_lo;
- base |= base_hi << 16u;
- base |= base_hi2 << 24u;
- return VirtualAddress { base };
- }
-
- void set_base(VirtualAddress base)
- {
- base_lo = base.get() & 0xffffu;
- base_hi = (base.get() >> 16u) & 0xffu;
- base_hi2 = (base.get() >> 24u) & 0xffu;
- }
-
- void set_limit(u32 length)
- {
- limit_lo = length & 0xffff;
- limit_hi = (length >> 16) & 0xf;
- }
-};
-
-class PageDirectoryEntry {
-public:
- const PageTableEntry* page_table_base() const { return reinterpret_cast<PageTableEntry*>(m_raw & 0xfffff000u); }
- PageTableEntry* page_table_base() { return reinterpret_cast<PageTableEntry*>(m_raw & 0xfffff000u); }
- void set_page_table_base(u32 value)
- {
- m_raw &= 0x8000000000000fffULL;
- m_raw |= value & 0xfffff000;
- }
-
- bool is_null() const { return m_raw == 0; }
- void clear() { m_raw = 0; }
-
- u64 raw() const { return m_raw; }
- void copy_from(Badge<PageDirectory>, const PageDirectoryEntry& other) { m_raw = other.m_raw; }
-
- enum Flags {
- Present = 1 << 0,
- ReadWrite = 1 << 1,
- UserSupervisor = 1 << 2,
- WriteThrough = 1 << 3,
- CacheDisabled = 1 << 4,
- Huge = 1 << 7,
- Global = 1 << 8,
- NoExecute = 0x8000000000000000ULL,
- };
-
- bool is_present() const { return raw() & Present; }
- void set_present(bool b) { set_bit(Present, b); }
-
- bool is_user_allowed() const { return raw() & UserSupervisor; }
- void set_user_allowed(bool b) { set_bit(UserSupervisor, b); }
-
- bool is_huge() const { return raw() & Huge; }
- void set_huge(bool b) { set_bit(Huge, b); }
-
- bool is_writable() const { return raw() & ReadWrite; }
- void set_writable(bool b) { set_bit(ReadWrite, b); }
-
- bool is_write_through() const { return raw() & WriteThrough; }
- void set_write_through(bool b) { set_bit(WriteThrough, b); }
-
- bool is_cache_disabled() const { return raw() & CacheDisabled; }
- void set_cache_disabled(bool b) { set_bit(CacheDisabled, b); }
-
- bool is_global() const { return raw() & Global; }
- void set_global(bool b) { set_bit(Global, b); }
-
- bool is_execute_disabled() const { return raw() & NoExecute; }
- void set_execute_disabled(bool b) { set_bit(NoExecute, b); }
-
- void set_bit(u64 bit, bool value)
- {
- if (value)
- m_raw |= bit;
- else
- m_raw &= ~bit;
- }
-
-private:
- u64 m_raw;
-};
-
-class PageTableEntry {
-public:
- void* physical_page_base() { return reinterpret_cast<void*>(m_raw & 0xfffff000u); }
- void set_physical_page_base(u32 value)
- {
- m_raw &= 0x8000000000000fffULL;
- m_raw |= value & 0xfffff000;
- }
-
- u64 raw() const { return (u32)m_raw; }
-
- enum Flags {
- Present = 1 << 0,
- ReadWrite = 1 << 1,
- UserSupervisor = 1 << 2,
- WriteThrough = 1 << 3,
- CacheDisabled = 1 << 4,
- Global = 1 << 8,
- NoExecute = 0x8000000000000000ULL,
- };
-
- bool is_present() const { return raw() & Present; }
- void set_present(bool b) { set_bit(Present, b); }
-
- bool is_user_allowed() const { return raw() & UserSupervisor; }
- void set_user_allowed(bool b) { set_bit(UserSupervisor, b); }
-
- bool is_writable() const { return raw() & ReadWrite; }
- void set_writable(bool b) { set_bit(ReadWrite, b); }
-
- bool is_write_through() const { return raw() & WriteThrough; }
- void set_write_through(bool b) { set_bit(WriteThrough, b); }
-
- bool is_cache_disabled() const { return raw() & CacheDisabled; }
- void set_cache_disabled(bool b) { set_bit(CacheDisabled, b); }
-
- bool is_global() const { return raw() & Global; }
- void set_global(bool b) { set_bit(Global, b); }
-
- bool is_execute_disabled() const { return raw() & NoExecute; }
- void set_execute_disabled(bool b) { set_bit(NoExecute, b); }
-
- bool is_null() const { return m_raw == 0; }
- void clear() { m_raw = 0; }
-
- void set_bit(u64 bit, bool value)
- {
- if (value)
- m_raw |= bit;
- else
- m_raw &= ~bit;
- }
-
-private:
- u64 m_raw;
-};
-
-static_assert(sizeof(PageDirectoryEntry) == 8);
-static_assert(sizeof(PageTableEntry) == 8);
-
-class PageDirectoryPointerTable {
-public:
- PageDirectoryEntry* directory(size_t index)
- {
- return (PageDirectoryEntry*)(raw[index] & ~0xfffu);
- }
-
- u64 raw[4];
-};
-
-class GenericInterruptHandler;
-struct RegisterState;
-
-const DescriptorTablePointer& get_gdtr();
-const DescriptorTablePointer& get_idtr();
-void register_interrupt_handler(u8 number, void (*handler)());
-void register_user_callable_interrupt_handler(u8 number, void (*handler)());
-GenericInterruptHandler& get_interrupt_handler(u8 interrupt_number);
-void register_generic_interrupt_handler(u8 number, GenericInterruptHandler&);
-void unregister_generic_interrupt_handler(u8 number, GenericInterruptHandler&);
-void flush_idt();
-void load_task_register(u16 selector);
-[[noreturn]] void handle_crash(RegisterState&, const char* description, int signal, bool out_of_memory = false);
-
-#define LSW(x) ((u32)(x)&0xFFFF)
-#define MSW(x) (((u32)(x) >> 16) & 0xFFFF)
-#define LSB(x) ((x)&0xFF)
-#define MSB(x) (((x) >> 8) & 0xFF)
-
-#define cli() asm volatile("cli" :: \
- : "memory")
-#define sti() asm volatile("sti" :: \
- : "memory")
-
-inline FlatPtr cpu_flags()
-{
- FlatPtr flags;
- asm volatile(
- "pushf\n"
- "pop %0\n"
- : "=rm"(flags)::"memory");
- return flags;
-}
-
-inline void set_fs(u16 segment)
-{
- asm volatile(
- "mov %%ax, %%fs" ::"a"(segment)
- : "memory");
-}
-
-inline void set_gs(u16 segment)
-{
- asm volatile(
- "mov %%ax, %%gs" ::"a"(segment)
- : "memory");
-}
-
-inline u16 get_fs()
-{
- u16 fs;
- asm("mov %%fs, %%eax"
- : "=a"(fs));
- return fs;
-}
-
-inline u16 get_gs()
-{
- u16 gs;
- asm("mov %%gs, %%eax"
- : "=a"(gs));
- return gs;
-}
-
-inline u32 read_fs_u32(u32 offset)
-{
- u32 val;
- asm volatile(
- "movl %%fs:%a[off], %k[val]"
- : [val] "=r"(val)
- : [off] "ir"(offset));
- return val;
-}
-
-inline FlatPtr read_fs_ptr(u32 offset)
-{
- return read_fs_u32(offset);
-}
-
-inline void write_fs_u32(u32 offset, u32 val)
-{
- asm volatile(
- "movl %k[val], %%fs:%a[off]" ::[off] "ir"(offset), [val] "ir"(val)
- : "memory");
-}
-
-inline bool are_interrupts_enabled()
-{
- return cpu_flags() & 0x200;
-}
-
-class InterruptDisabler {
-public:
- InterruptDisabler()
- {
- m_flags = cpu_flags();
- cli();
- }
-
- ~InterruptDisabler()
- {
- if (m_flags & 0x200)
- sti();
- }
-
-private:
- u32 m_flags;
-};
-
-class NonMaskableInterruptDisabler {
-public:
- NonMaskableInterruptDisabler();
- ~NonMaskableInterruptDisabler();
-};
-
-/* Map IRQ0-15 @ ISR 0x50-0x5F */
-#define IRQ_VECTOR_BASE 0x50
-
-struct PageFaultFlags {
- enum Flags {
- NotPresent = 0x00,
- ProtectionViolation = 0x01,
- Read = 0x00,
- Write = 0x02,
- UserMode = 0x04,
- SupervisorMode = 0x00,
- ReservedBitViolation = 0x08,
- InstructionFetch = 0x10,
- };
-};
-
-class PageFault {
-public:
- PageFault(u16 code, VirtualAddress vaddr)
- : m_code(code)
- , m_vaddr(vaddr)
- {
- }
-
- enum class Type {
- PageNotPresent = PageFaultFlags::NotPresent,
- ProtectionViolation = PageFaultFlags::ProtectionViolation,
- };
-
- enum class Access {
- Read = PageFaultFlags::Read,
- Write = PageFaultFlags::Write,
- };
-
- VirtualAddress vaddr() const { return m_vaddr; }
- u16 code() const { return m_code; }
-
- Type type() const { return (Type)(m_code & 1); }
- Access access() const { return (Access)(m_code & 2); }
-
- bool is_not_present() const { return (m_code & 1) == PageFaultFlags::NotPresent; }
- bool is_protection_violation() const { return (m_code & 1) == PageFaultFlags::ProtectionViolation; }
- bool is_read() const { return (m_code & 2) == PageFaultFlags::Read; }
- bool is_write() const { return (m_code & 2) == PageFaultFlags::Write; }
- bool is_user() const { return (m_code & 4) == PageFaultFlags::UserMode; }
- bool is_supervisor() const { return (m_code & 4) == PageFaultFlags::SupervisorMode; }
- bool is_instruction_fetch() const { return (m_code & 16) == PageFaultFlags::InstructionFetch; }
-
-private:
- u16 m_code;
- VirtualAddress m_vaddr;
-};
-
-struct [[gnu::packed]] RegisterState {
- 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;
-#if ARCH(X86_64)
- u32 padding;
-#endif
- FlatPtr eip;
- FlatPtr cs;
- FlatPtr eflags;
- FlatPtr userspace_esp;
- FlatPtr userspace_ss;
-};
-
-#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&);
-void copy_ptrace_registers_into_kernel_registers(RegisterState&, const PtraceRegisters&);
-
-struct [[gnu::aligned(16)]] FPUState
-{
- u8 buffer[512];
-};
-
-constexpr FlatPtr page_base_of(FlatPtr address)
-{
- return address & PAGE_MASK;
-}
-
-inline FlatPtr page_base_of(const void* address)
-{
- return page_base_of((FlatPtr)address);
-}
-
-constexpr FlatPtr offset_in_page(FlatPtr address)
-{
- return address & (~PAGE_MASK);
-}
-
-inline FlatPtr offset_in_page(const void* address)
-{
- return offset_in_page((FlatPtr)address);
-}
-
-FlatPtr read_cr0();
-FlatPtr read_cr2();
-FlatPtr read_cr3();
-FlatPtr read_cr4();
-u64 read_xcr0();
-
-void write_cr0(FlatPtr);
-void write_cr3(FlatPtr);
-void write_cr4(FlatPtr);
-void write_xcr0(u64);
-
-FlatPtr read_dr6();
-
-static inline bool is_kernel_mode()
-{
- u16 cs;
- asm volatile(
- "mov %%cs, %[cs] \n"
- : [cs] "=g"(cs));
- return (cs & 3) == 0;
-}
-
-class CPUID {
-public:
- explicit CPUID(u32 function) { asm volatile("cpuid"
- : "=a"(m_eax), "=b"(m_ebx), "=c"(m_ecx), "=d"(m_edx)
- : "a"(function), "c"(0)); }
- u32 eax() const { return m_eax; }
- u32 ebx() const { return m_ebx; }
- u32 ecx() const { return m_ecx; }
- u32 edx() const { return m_edx; }
-
-private:
- u32 m_eax { 0xffffffff };
- u32 m_ebx { 0xffffffff };
- u32 m_ecx { 0xffffffff };
- u32 m_edx { 0xffffffff };
-};
-
-inline void read_tsc(u32& lsw, u32& msw)
-{
- asm volatile("rdtsc"
- : "=d"(msw), "=a"(lsw));
-}
-
-inline u64 read_tsc()
-{
- u32 lsw;
- u32 msw;
- read_tsc(lsw, msw);
- return ((u64)msw << 32) | lsw;
-}
-
-// FIXME: This can't hold every CPU feature as-is.
-enum class CPUFeature : u32 {
- NX = (1 << 0),
- PAE = (1 << 1),
- PGE = (1 << 2),
- RDRAND = (1 << 3),
- RDSEED = (1 << 4),
- SMAP = (1 << 5),
- SMEP = (1 << 6),
- SSE = (1 << 7),
- TSC = (1 << 8),
- RDTSCP = (1 << 9),
- CONSTANT_TSC = (1 << 10),
- NONSTOP_TSC = (1 << 11),
- UMIP = (1 << 12),
- SEP = (1 << 13),
- SYSCALL = (1 << 14),
- MMX = (1 << 15),
- SSE2 = (1 << 16),
- SSE3 = (1 << 17),
- SSSE3 = (1 << 18),
- SSE4_1 = (1 << 19),
- SSE4_2 = (1 << 20),
- XSAVE = (1 << 21),
- AVX = (1 << 22),
-};
-
-class Thread;
-struct TrapFrame;
-
-#define GDT_SELECTOR_CODE0 0x08
-#define GDT_SELECTOR_DATA0 0x10
-#define GDT_SELECTOR_CODE3 0x18
-#define GDT_SELECTOR_DATA3 0x20
-#define GDT_SELECTOR_TLS 0x28
-#define GDT_SELECTOR_PROC 0x30
-#define GDT_SELECTOR_TSS 0x38
-
-// SYSENTER makes certain assumptions on how the GDT is structured:
-static_assert(GDT_SELECTOR_CODE0 + 8 == GDT_SELECTOR_DATA0); // SS0 = CS0 + 8
-
-// SYSEXIT makes certain assumptions on how the GDT is structured:
-static_assert(GDT_SELECTOR_CODE0 + 16 == GDT_SELECTOR_CODE3); // CS3 = CS0 + 16
-static_assert(GDT_SELECTOR_CODE0 + 24 == GDT_SELECTOR_DATA3); // SS3 = CS0 + 32
-
-class ProcessorInfo;
-class SchedulerPerProcessorData;
-struct MemoryManagerData;
-struct ProcessorMessageEntry;
-
-struct ProcessorMessage {
- enum Type {
- FlushTlb,
- Callback,
- CallbackWithData
- };
- Type type;
- volatile u32 refs; // atomic
- union {
- ProcessorMessage* next; // only valid while in the pool
- struct {
- void (*handler)();
- } callback;
- struct {
- void* data;
- void (*handler)(void*);
- void (*free)(void*);
- } callback_with_data;
- struct {
- const PageDirectory* page_directory;
- u8* ptr;
- size_t page_count;
- } flush_tlb;
- };
-
- volatile bool async;
-
- ProcessorMessageEntry* per_proc_entries;
-};
-
-struct ProcessorMessageEntry {
- ProcessorMessageEntry* next;
- ProcessorMessage* msg;
-};
-
-struct DeferredCallEntry {
- DeferredCallEntry* next;
- union {
- struct {
- void (*handler)();
- } callback;
- struct {
- void* data;
- void (*handler)(void*);
- void (*free)(void*);
- } callback_with_data;
- };
- bool have_data;
- bool was_allocated;
-};
-
-class Processor {
- friend class ProcessorInfo;
-
- AK_MAKE_NONCOPYABLE(Processor);
- AK_MAKE_NONMOVABLE(Processor);
-
- Processor* m_self;
-
- DescriptorTablePointer m_gdtr;
- Descriptor m_gdt[256];
- u32 m_gdt_length;
-
- u32 m_cpu;
- u32 m_in_irq;
- Atomic<u32, AK::MemoryOrder::memory_order_relaxed> m_in_critical;
- static Atomic<u32> s_idle_cpu_mask;
-
- TSS m_tss;
- static FPUState s_clean_fpu_state;
- CPUFeature m_features;
- static volatile u32 g_total_processors; // atomic
- u8 m_physical_address_bit_width;
-
- ProcessorInfo* m_info;
- MemoryManagerData* m_mm_data;
- SchedulerPerProcessorData* m_scheduler_data;
- Thread* m_current_thread;
- Thread* m_idle_thread;
-
- volatile ProcessorMessageEntry* m_message_queue; // atomic, LIFO
-
- bool m_invoke_scheduler_async;
- bool m_scheduler_initialized;
- Atomic<bool> m_halt_requested;
-
- DeferredCallEntry* m_pending_deferred_calls; // in reverse order
- DeferredCallEntry* m_free_deferred_call_pool_entry;
- DeferredCallEntry m_deferred_call_pool[5];
-
- void gdt_init();
- void write_raw_gdt_entry(u16 selector, u32 low, u32 high);
- void write_gdt_entry(u16 selector, Descriptor& descriptor);
- static Vector<Processor*>& processors();
-
- static void smp_return_to_pool(ProcessorMessage& msg);
- static ProcessorMessage& smp_get_from_pool();
- static void smp_cleanup_message(ProcessorMessage& msg);
- bool smp_queue_message(ProcessorMessage& msg);
- static void smp_unicast_message(u32 cpu, ProcessorMessage& msg, bool async);
- static void smp_broadcast_message(ProcessorMessage& msg);
- static void smp_broadcast_wait_sync(ProcessorMessage& msg);
- static void smp_broadcast_halt();
-
- void deferred_call_pool_init();
- void deferred_call_execute_pending();
- DeferredCallEntry* deferred_call_get_free();
- void deferred_call_return_to_pool(DeferredCallEntry*);
- void deferred_call_queue_entry(DeferredCallEntry*);
-
- void cpu_detect();
- void cpu_setup();
-
- String features_string() const;
-
-public:
- Processor() = default;
-
- void early_initialize(u32 cpu);
- void initialize(u32 cpu);
-
- void idle_begin()
- {
- s_idle_cpu_mask.fetch_or(1u << m_cpu, AK::MemoryOrder::memory_order_relaxed);
- }
-
- void idle_end()
- {
- s_idle_cpu_mask.fetch_and(~(1u << m_cpu), AK::MemoryOrder::memory_order_relaxed);
- }
-
- static u32 count()
- {
- // NOTE: because this value never changes once all APs are booted,
- // we don't really need to do an atomic_load() on this variable
- return g_total_processors;
- }
-
- ALWAYS_INLINE static void wait_check()
- {
- Processor::current().smp_process_pending_messages();
- // TODO: pause
- }
-
- [[noreturn]] static void halt();
-
- static void flush_entire_tlb_local()
- {
- write_cr3(read_cr3());
- }
-
- static void flush_tlb_local(VirtualAddress vaddr, size_t page_count);
- static void flush_tlb(const PageDirectory*, VirtualAddress, size_t);
-
- Descriptor& get_gdt_entry(u16 selector);
- void flush_gdt();
- const DescriptorTablePointer& get_gdtr();
-
- static Processor& by_id(u32 cpu);
-
- static size_t processor_count() { return processors().size(); }
-
- template<typename Callback>
- static inline IterationDecision for_each(Callback callback)
- {
- auto& procs = processors();
- size_t count = procs.size();
- for (size_t i = 0; i < count; i++) {
- if (callback(*procs[i]) == IterationDecision::Break)
- return IterationDecision::Break;
- }
- return IterationDecision::Continue;
- }
-
- ALWAYS_INLINE u8 physical_address_bit_width() const { return m_physical_address_bit_width; }
-
- ALWAYS_INLINE ProcessorInfo& info() { return *m_info; }
-
- ALWAYS_INLINE static Processor& current()
- {
- return *(Processor*)read_fs_ptr(__builtin_offsetof(Processor, m_self));
- }
-
- ALWAYS_INLINE static bool is_initialized()
- {
- return get_fs() == GDT_SELECTOR_PROC && read_fs_u32(__builtin_offsetof(Processor, m_self)) != 0;
- }
-
- ALWAYS_INLINE void set_scheduler_data(SchedulerPerProcessorData& scheduler_data)
- {
- m_scheduler_data = &scheduler_data;
- }
-
- ALWAYS_INLINE SchedulerPerProcessorData& get_scheduler_data() const
- {
- return *m_scheduler_data;
- }
-
- ALWAYS_INLINE void set_mm_data(MemoryManagerData& mm_data)
- {
- m_mm_data = &mm_data;
- }
-
- ALWAYS_INLINE MemoryManagerData& get_mm_data() const
- {
- return *m_mm_data;
- }
-
- ALWAYS_INLINE Thread* idle_thread() const
- {
- return m_idle_thread;
- }
-
- ALWAYS_INLINE void set_idle_thread(Thread& idle_thread)
- {
- m_idle_thread = &idle_thread;
- }
-
- ALWAYS_INLINE static Thread* current_thread()
- {
- // If we were to use Processor::current here, we'd have to
- // disable interrupts to prevent a race where we may get pre-empted
- // right after getting the Processor structure and then get moved
- // to another processor, which would lead us to get the wrong thread.
- // To avoid having to disable interrupts, we can just read the field
- // directly in an atomic fashion, similar to Processor::current.
- return (Thread*)read_fs_ptr(__builtin_offsetof(Processor, m_current_thread));
- }
-
- ALWAYS_INLINE static void set_current_thread(Thread& current_thread)
- {
- // See comment in Processor::current_thread
- write_fs_u32(__builtin_offsetof(Processor, m_current_thread), FlatPtr(&current_thread));
- }
-
- ALWAYS_INLINE u32 get_id() const
- {
- // NOTE: This variant should only be used when iterating over all
- // Processor instances, or when it's guaranteed that the thread
- // cannot move to another processor in between calling Processor::current
- // and Processor::get_id, or if this fact is not important.
- // All other cases should use Processor::id instead!
- return m_cpu;
- }
-
- ALWAYS_INLINE static u32 id()
- {
- // See comment in Processor::current_thread
- return read_fs_ptr(__builtin_offsetof(Processor, m_cpu));
- }
-
- ALWAYS_INLINE u32 raise_irq()
- {
- return m_in_irq++;
- }
-
- ALWAYS_INLINE void restore_irq(u32 prev_irq)
- {
- VERIFY(prev_irq <= m_in_irq);
- if (!prev_irq) {
- u32 prev_critical = 0;
- if (m_in_critical.compare_exchange_strong(prev_critical, 1)) {
- m_in_irq = prev_irq;
- deferred_call_execute_pending();
- auto prev_raised = m_in_critical.exchange(prev_critical);
- VERIFY(prev_raised == prev_critical + 1);
- check_invoke_scheduler();
- } else if (prev_critical == 0) {
- check_invoke_scheduler();
- }
- } else {
- m_in_irq = prev_irq;
- }
- }
-
- ALWAYS_INLINE u32& in_irq()
- {
- return m_in_irq;
- }
-
- ALWAYS_INLINE void restore_in_critical(u32 critical)
- {
- m_in_critical = critical;
- }
-
- ALWAYS_INLINE void enter_critical(u32& prev_flags)
- {
- prev_flags = cpu_flags();
- cli();
- m_in_critical++;
- }
-
- ALWAYS_INLINE void leave_critical(u32 prev_flags)
- {
- cli(); // Need to prevent IRQs from interrupting us here!
- VERIFY(m_in_critical > 0);
- if (m_in_critical == 1) {
- if (!m_in_irq) {
- deferred_call_execute_pending();
- VERIFY(m_in_critical == 1);
- }
- m_in_critical--;
- if (!m_in_irq)
- check_invoke_scheduler();
- } else {
- m_in_critical--;
- }
- if (prev_flags & 0x200)
- sti();
- else
- cli();
- }
-
- ALWAYS_INLINE u32 clear_critical(u32& prev_flags, bool enable_interrupts)
- {
- prev_flags = cpu_flags();
- u32 prev_crit = m_in_critical.exchange(0, AK::MemoryOrder::memory_order_acquire);
- if (!m_in_irq)
- check_invoke_scheduler();
- if (enable_interrupts)
- sti();
- return prev_crit;
- }
-
- ALWAYS_INLINE void restore_critical(u32 prev_crit, u32 prev_flags)
- {
- m_in_critical.store(prev_crit, AK::MemoryOrder::memory_order_release);
- VERIFY(!prev_crit || !(prev_flags & 0x200));
- if (prev_flags & 0x200)
- sti();
- else
- cli();
- }
-
- ALWAYS_INLINE u32 in_critical() { return m_in_critical.load(); }
-
- ALWAYS_INLINE const FPUState& clean_fpu_state() const
- {
- return s_clean_fpu_state;
- }
-
- static void smp_enable();
- bool smp_process_pending_messages();
-
- template<typename Callback>
- static void smp_broadcast(Callback callback, bool async)
- {
- auto* data = new Callback(move(callback));
- smp_broadcast(
- [](void* data) {
- (*reinterpret_cast<Callback*>(data))();
- },
- data,
- [](void* data) {
- delete reinterpret_cast<Callback*>(data);
- },
- async);
- }
- static void smp_broadcast(void (*callback)(), bool async);
- static void smp_broadcast(void (*callback)(void*), void* data, void (*free_data)(void*), bool async);
- template<typename Callback>
- static void smp_unicast(u32 cpu, Callback callback, bool async)
- {
- auto* data = new Callback(move(callback));
- smp_unicast(
- cpu,
- [](void* data) {
- (*reinterpret_cast<Callback*>(data))();
- },
- data,
- [](void* data) {
- delete reinterpret_cast<Callback*>(data);
- },
- async);
- }
- static void smp_unicast(u32 cpu, void (*callback)(), bool async);
- static void smp_unicast(u32 cpu, void (*callback)(void*), void* data, void (*free_data)(void*), bool async);
- static void smp_broadcast_flush_tlb(const PageDirectory*, VirtualAddress, size_t);
- static u32 smp_wake_n_idle_processors(u32 wake_count);
-
- template<typename Callback>
- static void deferred_call_queue(Callback callback)
- {
- auto* data = new Callback(move(callback));
- deferred_call_queue(
- [](void* data) {
- (*reinterpret_cast<Callback*>(data))();
- },
- data,
- [](void* data) {
- delete reinterpret_cast<Callback*>(data);
- });
- }
- static void deferred_call_queue(void (*callback)());
- static void deferred_call_queue(void (*callback)(void*), void* data, void (*free_data)(void*));
-
- ALWAYS_INLINE bool has_feature(CPUFeature f) const
- {
- return (static_cast<u32>(m_features) & static_cast<u32>(f)) != 0;
- }
-
- void check_invoke_scheduler();
- void invoke_scheduler_async() { m_invoke_scheduler_async = true; }
-
- void enter_trap(TrapFrame& trap, bool raise_irq);
-
- void exit_trap(TrapFrame& trap);
-
- [[noreturn]] void initialize_context_switching(Thread& initial_thread);
- void switch_context(Thread*& from_thread, Thread*& to_thread);
- [[noreturn]] static void assume_context(Thread& thread, FlatPtr flags);
- u32 init_context(Thread& thread, bool leave_crit);
- static Vector<FlatPtr> capture_stack_trace(Thread& thread, size_t max_frames = 0);
-
- String platform_string() const;
-};
-
-class ScopedCritical {
- AK_MAKE_NONCOPYABLE(ScopedCritical);
-
-public:
- ScopedCritical()
- {
- enter();
- }
-
- ~ScopedCritical()
- {
- if (m_valid)
- leave();
- }
-
- ScopedCritical(ScopedCritical&& from)
- : m_prev_flags(exchange(from.m_prev_flags, 0))
- , m_valid(exchange(from.m_valid, false))
- {
- }
-
- ScopedCritical& operator=(ScopedCritical&& from)
- {
- if (&from != this) {
- m_prev_flags = exchange(from.m_prev_flags, 0);
- m_valid = exchange(from.m_valid, false);
- }
- return *this;
- }
-
- void leave()
- {
- VERIFY(m_valid);
- m_valid = false;
- Processor::current().leave_critical(m_prev_flags);
- }
-
- void enter()
- {
- VERIFY(!m_valid);
- m_valid = true;
- Processor::current().enter_critical(m_prev_flags);
- }
-
-private:
- u32 m_prev_flags { 0 };
- bool m_valid { false };
-};
-
-struct TrapFrame {
- u32 prev_irq_level;
- TrapFrame* next_trap;
- RegisterState* regs; // must be last
-
- TrapFrame() = delete;
- TrapFrame(const TrapFrame&) = delete;
- TrapFrame(TrapFrame&&) = delete;
- TrapFrame& operator=(const TrapFrame&) = delete;
- TrapFrame& operator=(TrapFrame&&) = delete;
-};
-
-#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*);
-extern "C" void enter_trap(TrapFrame*);
-extern "C" void exit_trap(TrapFrame*);
-
-class MSR {
- uint32_t m_msr;
-
-public:
- static bool have()
- {
- CPUID id(1);
- return (id.edx() & (1 << 5)) != 0;
- }
-
- MSR(const MSR&) = delete;
- MSR& operator=(const MSR&) = delete;
-
- MSR(uint32_t msr)
- : m_msr(msr)
- {
- }
-
- void get(u32& low, u32& high)
- {
- asm volatile("rdmsr"
- : "=a"(low), "=d"(high)
- : "c"(m_msr));
- }
-
- void set(u32 low, u32 high)
- {
- asm volatile("wrmsr" ::"a"(low), "d"(high), "c"(m_msr));
- }
-};
-
-ALWAYS_INLINE void stac()
-{
- if (!Processor::current().has_feature(CPUFeature::SMAP))
- return;
- asm volatile("stac" ::
- : "cc");
-}
-
-ALWAYS_INLINE void clac()
-{
- if (!Processor::current().has_feature(CPUFeature::SMAP))
- return;
- asm volatile("clac" ::
- : "cc");
-}
-}
diff --git a/Kernel/Arch/i386/ISRStubs.h b/Kernel/Arch/i386/ISRStubs.h
deleted file mode 100644
index 86db4644a1..0000000000
--- a/Kernel/Arch/i386/ISRStubs.h
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#include <Kernel/Arch/i386/Interrupts.h>
-
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(80)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(81)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(82)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(83)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(84)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(85)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(86)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(87)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(88)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(89)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(90)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(91)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(92)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(93)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(94)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(95)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(96)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(97)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(98)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(99)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(100)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(101)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(102)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(103)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(104)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(105)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(106)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(107)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(108)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(109)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(110)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(111)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(112)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(113)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(114)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(115)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(116)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(117)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(118)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(119)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(120)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(121)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(122)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(123)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(124)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(125)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(126)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(127)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(128)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(129)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(130)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(131)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(132)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(133)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(134)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(135)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(136)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(137)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(138)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(139)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(140)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(141)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(142)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(143)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(144)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(145)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(146)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(147)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(148)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(149)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(150)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(151)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(152)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(153)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(154)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(155)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(156)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(157)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(158)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(159)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(160)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(161)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(162)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(163)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(164)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(165)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(166)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(167)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(168)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(169)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(170)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(171)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(172)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(173)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(174)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(175)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(176)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(177)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(178)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(179)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(180)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(181)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(182)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(183)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(184)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(185)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(186)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(187)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(188)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(189)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(190)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(191)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(192)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(193)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(194)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(195)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(196)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(197)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(198)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(199)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(200)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(201)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(202)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(203)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(204)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(205)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(206)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(207)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(208)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(209)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(210)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(211)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(212)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(213)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(214)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(215)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(216)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(217)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(218)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(219)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(220)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(221)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(222)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(223)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(224)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(225)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(226)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(227)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(228)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(229)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(230)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(231)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(232)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(233)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(234)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(235)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(236)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(237)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(238)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(239)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(240)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(241)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(242)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(243)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(244)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(245)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(246)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(247)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(248)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(249)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(250)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(251)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(252)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(253)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(254)
-GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(255)
diff --git a/Kernel/Arch/i386/Interrupts.h b/Kernel/Arch/i386/InterruptEntry.cpp
index cfa457da16..a86267b32e 100644
--- a/Kernel/Arch/i386/Interrupts.h
+++ b/Kernel/Arch/i386/InterruptEntry.cpp
@@ -24,24 +24,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#pragma once
-
-#include <AK/Assertions.h>
-#include <AK/Types.h>
-#include <Kernel/Arch/i386/CPU.h>
-
-extern "C" void interrupt_common_asm_entry();
-
-#if ARCH(I386)
-
-# define GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(isr_number) \
- extern "C" void interrupt_##isr_number##_asm_entry(); \
- asm(".globl interrupt_" #isr_number "_asm_entry\n" \
- "interrupt_" #isr_number "_asm_entry:\n" \
- " pushw $" #isr_number "\n" \
- " pushw $0\n" \
- " jmp interrupt_common_asm_entry\n");
-
+#include <Kernel/Arch/x86/CPU.h>
+#include <Kernel/Arch/x86/DescriptorTable.h>
// clang-format off
asm(
".globl interrupt_common_asm_entry\n"
@@ -68,9 +52,9 @@ asm(
" movl %ebx, 0(%esp) \n" // push pointer to TrapFrame
".globl common_trap_exit \n"
"common_trap_exit: \n"
- // another thread may have handled this trap at this point, so don't
- // make assumptions about the stack other than there's a TrapFrame
- // and a pointer to it.
+ // another thread may have handled this trap at this point, so don't
+ // make assumptions about the stack other than there's a TrapFrame
+ // and a pointer to it.
" call exit_trap \n"
" addl $" __STRINGIFY(TRAP_FRAME_SIZE + 4) ", %esp\n" // pop TrapFrame and pointer to it
".globl interrupt_common_asm_exit \n"
@@ -85,19 +69,3 @@ asm(
" iret\n"
);
// clang-format on
-
-#elif ARCH(X86_64)
-
-# define GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(isr_number) \
- extern "C" void interrupt_##isr_number##_asm_entry(); \
- asm(".globl interrupt_" #isr_number "_asm_entry\n" \
- "interrupt_" #isr_number "_asm_entry:\n" \
- " cli\n" \
- " hlt\n");
-
-asm(
- ".globl common_trap_exit\n"
- "common_trap_exit:\n"
- " cli;hlt\n");
-
-#endif
diff --git a/Kernel/Arch/i386/ProcessorInfo.cpp b/Kernel/Arch/i386/ProcessorInfo.cpp
index a7f8f4ec4d..b5f5196a35 100644
--- a/Kernel/Arch/i386/ProcessorInfo.cpp
+++ b/Kernel/Arch/i386/ProcessorInfo.cpp
@@ -26,8 +26,8 @@
#include <AK/StringBuilder.h>
#include <AK/Types.h>
-#include <Kernel/Arch/i386/CPU.h>
-#include <Kernel/Arch/i386/ProcessorInfo.h>
+#include <Kernel/Arch/x86/CPU.h>
+#include <Kernel/Arch/x86/ProcessorInfo.h>
namespace Kernel {
diff --git a/Kernel/Arch/i386/ProcessorInfo.h b/Kernel/Arch/i386/ProcessorInfo.h
deleted file mode 100644
index 7169184650..0000000000
--- a/Kernel/Arch/i386/ProcessorInfo.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#include <AK/String.h>
-
-namespace Kernel {
-
-class Processor;
-
-class ProcessorInfo {
- Processor& m_processor;
- String m_cpuid;
- String m_brandstr;
- String m_features;
- u32 m_display_model;
- u32 m_display_family;
- u32 m_stepping;
- u32 m_type;
- u32 m_apic_id;
-
-public:
- ProcessorInfo(Processor& processor);
-
- const String& cpuid() const { return m_cpuid; }
- const String& brandstr() const { return m_brandstr; }
- const String& features() const { return m_features; }
- u32 display_model() const { return m_display_model; }
- u32 display_family() const { return m_display_family; }
- u32 stepping() const { return m_stepping; }
- u32 type() const { return m_type; }
- u32 apic_id() const { return m_apic_id; }
-
- void set_apic_id(u32 apic_id) { m_apic_id = apic_id; }
-};
-
-}
diff --git a/Kernel/Arch/i386/SafeMem.cpp b/Kernel/Arch/i386/SafeMem.cpp
index a4be13e1d9..2e2eff662b 100644
--- a/Kernel/Arch/i386/SafeMem.cpp
+++ b/Kernel/Arch/i386/SafeMem.cpp
@@ -24,8 +24,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <Kernel/Arch/i386/CPU.h>
-#include <Kernel/Arch/i386/SafeMem.h>
+#include <Kernel/Arch/x86/CPU.h>
+#include <Kernel/Arch/x86/SafeMem.h>
#define CODE_SECTION(section_name) __attribute__((section(section_name)))
diff --git a/Kernel/Arch/i386/SafeMem.h b/Kernel/Arch/i386/SafeMem.h
deleted file mode 100644
index f66844ce4a..0000000000
--- a/Kernel/Arch/i386/SafeMem.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 2020, the SerenityOS developers.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <AK/Atomic.h>
-#include <AK/Optional.h>
-#include <AK/Types.h>
-
-#pragma once
-
-namespace Kernel {
-
-struct RegisterState;
-
-[[nodiscard]] bool safe_memcpy(void* dest_ptr, const void* src_ptr, size_t n, void*& fault_at);
-[[nodiscard]] ssize_t safe_strnlen(const char* str, size_t max_n, void*& fault_at);
-[[nodiscard]] bool safe_memset(void* dest_ptr, int c, size_t n, void*& fault_at);
-[[nodiscard]] Optional<u32> safe_atomic_fetch_add_relaxed(volatile u32* var, u32 val);
-[[nodiscard]] Optional<u32> safe_atomic_exchange_relaxed(volatile u32* var, u32 val);
-[[nodiscard]] Optional<u32> safe_atomic_load_relaxed(volatile u32* var);
-[[nodiscard]] bool safe_atomic_store_relaxed(volatile u32* var, u32 val);
-[[nodiscard]] Optional<bool> safe_atomic_compare_exchange_relaxed(volatile u32* var, u32& expected, u32 val);
-
-[[nodiscard]] ALWAYS_INLINE Optional<u32> safe_atomic_fetch_and_relaxed(volatile u32* var, u32 val)
-{
- auto expected_value = safe_atomic_load_relaxed(var);
- if (!expected_value.has_value())
- return {}; // fault
- u32& expected = expected_value.value();
- for (;;) {
- auto result = safe_atomic_compare_exchange_relaxed(var, expected, expected & val);
- if (!result.has_value())
- return {}; // fault
- if (result.value())
- return expected; // exchanged
-
- // This is only so that we don't saturate the bus...
- AK::atomic_thread_fence(AK::MemoryOrder::memory_order_acquire);
- }
-}
-
-[[nodiscard]] ALWAYS_INLINE Optional<u32> safe_atomic_fetch_and_not_relaxed(volatile u32* var, u32 val)
-{
- auto expected_value = safe_atomic_load_relaxed(var);
- if (!expected_value.has_value())
- return {}; // fault
- u32& expected = expected_value.value();
- for (;;) {
- auto result = safe_atomic_compare_exchange_relaxed(var, expected, expected & ~val);
- if (!result.has_value())
- return {}; // fault
- if (result.value())
- return expected; // exchanged
-
- // This is only so that we don't saturate the bus...
- AK::atomic_thread_fence(AK::MemoryOrder::memory_order_acquire);
- }
-}
-
-[[nodiscard]] ALWAYS_INLINE Optional<u32> safe_atomic_fetch_or_relaxed(volatile u32* var, u32 val)
-{
- auto expected_value = safe_atomic_load_relaxed(var);
- if (!expected_value.has_value())
- return {}; // fault
- u32& expected = expected_value.value();
- for (;;) {
- auto result = safe_atomic_compare_exchange_relaxed(var, expected, expected | val);
- if (!result.has_value())
- return {}; // fault
- if (result.value())
- return expected; // exchanged
-
- // This is only so that we don't saturate the bus...
- AK::atomic_thread_fence(AK::MemoryOrder::memory_order_acquire);
- }
-}
-
-[[nodiscard]] ALWAYS_INLINE Optional<u32> safe_atomic_fetch_xor_relaxed(volatile u32* var, u32 val)
-{
- auto expected_value = safe_atomic_load_relaxed(var);
- if (!expected_value.has_value())
- return {}; // fault
- u32& expected = expected_value.value();
- for (;;) {
- auto result = safe_atomic_compare_exchange_relaxed(var, expected, expected ^ val);
- if (!result.has_value())
- return {}; // fault
- if (result.value())
- return expected; // exchanged
-
- // This is only so that we don't saturate the bus...
- AK::atomic_thread_fence(AK::MemoryOrder::memory_order_acquire);
- }
-}
-
-bool handle_safe_access_fault(RegisterState& regs, u32 fault_address);
-
-}