Browse Source

Kernel: Consolidate features into CPUFeature enum

This allows us to consolidate printing out all the CPU features
into one log statement. Also expose them in /proc/cpuinfo
Tom 5 years ago
parent
commit
9b4e6f6a23

+ 155 - 121
Kernel/Arch/i386/CPU.cpp

@@ -26,6 +26,7 @@
 
 
 #include <AK/Assertions.h>
 #include <AK/Assertions.h>
 #include <AK/String.h>
 #include <AK/String.h>
+#include <AK/StringBuilder.h>
 #include <AK/Types.h>
 #include <AK/Types.h>
 #include <Kernel/Arch/i386/CPU.h>
 #include <Kernel/Arch/i386/CPU.h>
 #include <Kernel/Arch/i386/ProcessorInfo.h>
 #include <Kernel/Arch/i386/ProcessorInfo.h>
@@ -633,7 +634,7 @@ void exit_trap(TrapFrame* trap)
     return Processor::current().exit_trap(*trap);
     return Processor::current().exit_trap(*trap);
 }
 }
 
 
-void sse_init()
+static void sse_init()
 {
 {
     asm volatile(
     asm volatile(
         "mov %cr0, %eax\n"
         "mov %cr0, %eax\n"
@@ -645,181 +646,215 @@ void sse_init()
         "mov %eax, %cr4\n");
         "mov %eax, %cr4\n");
 }
 }
 
 
-bool g_cpu_supports_nx;
-bool g_cpu_supports_pae;
-bool g_cpu_supports_pge;
-bool g_cpu_supports_rdrand;
-bool g_cpu_supports_rdseed;
-bool g_cpu_supports_smap;
-bool g_cpu_supports_smep;
-bool g_cpu_supports_sse;
-bool g_cpu_supports_tsc;
-bool g_cpu_supports_umip;
-
-void cpu_detect()
+u32 read_cr0()
+{
+    u32 cr0;
+    asm("movl %%cr0, %%eax"
+        : "=a"(cr0));
+    return cr0;
+}
+
+u32 read_cr3()
+{
+    u32 cr3;
+    asm("movl %%cr3, %%eax"
+        : "=a"(cr3));
+    return cr3;
+}
+
+void write_cr3(u32 cr3)
+{
+    asm volatile("movl %%eax, %%cr3" ::"a"(cr3)
+                 : "memory");
+}
+
+u32 read_cr4()
+{
+    u32 cr4;
+    asm("movl %%cr4, %%eax"
+        : "=a"(cr4));
+    return cr4;
+}
+
+u32 read_dr6()
+{
+    u32 dr6;
+    asm("movl %%dr6, %%eax"
+        : "=a"(dr6));
+    return dr6;
+}
+
+FPUState Processor::s_clean_fpu_state;
+
+static Vector<Processor*>* s_processors;
+static SpinLock s_processor_lock;
+
+Vector<Processor*>& Processor::processors()
 {
 {
+    ASSERT(s_processors);
+    return *s_processors;
+}
+
+Processor& Processor::by_id(u32 cpu)
+{
+    // s_processors does not need to be protected by a lock of any kind.
+    // It is populated early in the boot process, and the BSP is waiting
+    // for all APs to finish, after which this array never gets modified
+    // again, so it's safe to not protect access to it here
+    auto& procs = processors();
+    ASSERT(procs[cpu] != nullptr);
+    ASSERT(procs.size() > cpu);
+    return *procs[cpu];
+}
+
+
+void Processor::cpu_detect()
+{
+    // NOTE: This is called during Processor::early_initialize, we cannot
+    //       safely log at this point because we don't have kmalloc
+    //       initialized yet!
+    auto set_feature =
+        [&](CPUFeature f) {
+            m_features = static_cast<CPUFeature>(static_cast<u32>(m_features) | static_cast<u32>(f));
+        };
+    m_features = static_cast<CPUFeature>(0);
+
     CPUID processor_info(0x1);
     CPUID processor_info(0x1);
-    g_cpu_supports_pae = (processor_info.edx() & (1 << 6));
-    g_cpu_supports_pge = (processor_info.edx() & (1 << 13));
-    g_cpu_supports_sse = (processor_info.edx() & (1 << 25));
-    g_cpu_supports_tsc = (processor_info.edx() & (1 << 4));
-    g_cpu_supports_rdrand = (processor_info.ecx() & (1 << 30));
+    if (processor_info.edx() & (1 << 6))
+        set_feature(CPUFeature::PAE);
+    if (processor_info.edx() & (1 << 13))
+        set_feature(CPUFeature::PGE);
+    if (processor_info.edx() & (1 << 25))
+        set_feature(CPUFeature::SSE);
+    if (processor_info.edx() & (1 << 4))
+        set_feature(CPUFeature::TSC);
+    if (processor_info.ecx() & (1 << 30))
+        set_feature(CPUFeature::RDRAND);
 
 
     CPUID extended_processor_info(0x80000001);
     CPUID extended_processor_info(0x80000001);
-    g_cpu_supports_nx = (extended_processor_info.edx() & (1 << 20));
+    if (extended_processor_info.edx() & (1 << 20))
+        set_feature(CPUFeature::NX);
 
 
     CPUID extended_features(0x7);
     CPUID extended_features(0x7);
-    g_cpu_supports_smap = (extended_features.ebx() & (1 << 20));
-    g_cpu_supports_smep = (extended_features.ebx() & (1 << 7));
-    g_cpu_supports_umip = (extended_features.ecx() & (1 << 2));
-    g_cpu_supports_rdseed = (extended_features.ebx() & (1 << 18));
+    if (extended_features.ebx() & (1 << 20))
+        set_feature(CPUFeature::SMAP);
+    if (extended_features.ebx() & (1 << 7))
+        set_feature(CPUFeature::SMEP);
+    if (extended_features.ecx() & (1 << 2))
+        set_feature(CPUFeature::UMIP);
+    if (extended_features.ebx() & (1 << 18))
+        set_feature(CPUFeature::RDSEED);
 }
 }
 
 
-void cpu_setup(u32 cpu)
+void Processor::cpu_setup()
 {
 {
-    if (cpu == 0)
-        cpu_detect();
+    // NOTE: This is called during Processor::early_initialize, we cannot
+    //       safely log at this point because we don't have kmalloc
+    //       initialized yet!
+    cpu_detect();
 
 
-    if (g_cpu_supports_sse) {
+    if (has_feature(CPUFeature::SSE))
         sse_init();
         sse_init();
-        klog() << "x86: SSE support enabled";
-    }
 
 
     asm volatile(
     asm volatile(
         "movl %%cr0, %%eax\n"
         "movl %%cr0, %%eax\n"
         "orl $0x00010000, %%eax\n"
         "orl $0x00010000, %%eax\n"
         "movl %%eax, %%cr0\n" ::
         "movl %%eax, %%cr0\n" ::
             : "%eax", "memory");
             : "%eax", "memory");
-    klog() << "x86: WP support enabled";
 
 
-    if (g_cpu_supports_pge) {
+    if (has_feature(CPUFeature::PGE)) {
         // Turn on CR4.PGE so the CPU will respect the G bit in page tables.
         // Turn on CR4.PGE so the CPU will respect the G bit in page tables.
         asm volatile(
         asm volatile(
             "mov %cr4, %eax\n"
             "mov %cr4, %eax\n"
             "orl $0x80, %eax\n"
             "orl $0x80, %eax\n"
             "mov %eax, %cr4\n");
             "mov %eax, %cr4\n");
-        klog() << "x86: PGE support enabled";
-    } else {
-        klog() << "x86: PGE support not detected";
     }
     }
 
 
-    if (g_cpu_supports_nx) {
+    if (has_feature(CPUFeature::NX)) {
         // Turn on IA32_EFER.NXE
         // Turn on IA32_EFER.NXE
         asm volatile(
         asm volatile(
             "movl $0xc0000080, %ecx\n"
             "movl $0xc0000080, %ecx\n"
             "rdmsr\n"
             "rdmsr\n"
             "orl $0x800, %eax\n"
             "orl $0x800, %eax\n"
             "wrmsr\n");
             "wrmsr\n");
-        klog() << "x86: NX support enabled";
-    } else {
-        klog() << "x86: NX support not detected";
     }
     }
 
 
-    if (g_cpu_supports_smep) {
+    if (has_feature(CPUFeature::SMEP)) {
         // Turn on CR4.SMEP
         // Turn on CR4.SMEP
         asm volatile(
         asm volatile(
             "mov %cr4, %eax\n"
             "mov %cr4, %eax\n"
             "orl $0x100000, %eax\n"
             "orl $0x100000, %eax\n"
             "mov %eax, %cr4\n");
             "mov %eax, %cr4\n");
-        klog() << "x86: SMEP support enabled";
-    } else {
-        klog() << "x86: SMEP support not detected";
     }
     }
 
 
-    if (g_cpu_supports_smap) {
+    if (has_feature(CPUFeature::SMAP)) {
         // Turn on CR4.SMAP
         // Turn on CR4.SMAP
-        klog() << "x86: Enabling SMAP";
         asm volatile(
         asm volatile(
             "mov %cr4, %eax\n"
             "mov %cr4, %eax\n"
             "orl $0x200000, %eax\n"
             "orl $0x200000, %eax\n"
             "mov %eax, %cr4\n");
             "mov %eax, %cr4\n");
-        klog() << "x86: SMAP support enabled";
-    } else {
-        klog() << "x86: SMAP support not detected";
     }
     }
 
 
-    if (g_cpu_supports_umip) {
+    if (has_feature(CPUFeature::UMIP)) {
         asm volatile(
         asm volatile(
             "mov %cr4, %eax\n"
             "mov %cr4, %eax\n"
             "orl $0x800, %eax\n"
             "orl $0x800, %eax\n"
             "mov %eax, %cr4\n");
             "mov %eax, %cr4\n");
-        klog() << "x86: UMIP support enabled";
     }
     }
 
 
-    if (g_cpu_supports_tsc) {
+    if (has_feature(CPUFeature::TSC)) {
         asm volatile(
         asm volatile(
             "mov %cr4, %eax\n"
             "mov %cr4, %eax\n"
             "orl $0x4, %eax\n"
             "orl $0x4, %eax\n"
             "mov %eax, %cr4\n");
             "mov %eax, %cr4\n");
-        klog() << "x86: RDTSC support restricted";
     }
     }
-
-    if (g_cpu_supports_rdrand) {
-        klog() << "x86: Using RDRAND for good randomness";
-    } else {
-        klog() << "x86: No RDRAND support detected, randomness will be poor";
-    }
-}
-
-u32 read_cr0()
-{
-    u32 cr0;
-    asm("movl %%cr0, %%eax"
-        : "=a"(cr0));
-    return cr0;
 }
 }
 
 
-u32 read_cr3()
+String Processor::features_string() const
 {
 {
-    u32 cr3;
-    asm("movl %%cr3, %%eax"
-        : "=a"(cr3));
-    return cr3;
-}
-
-void write_cr3(u32 cr3)
-{
-    asm volatile("movl %%eax, %%cr3" ::"a"(cr3)
-                 : "memory");
-}
-
-u32 read_cr4()
-{
-    u32 cr4;
-    asm("movl %%cr4, %%eax"
-        : "=a"(cr4));
-    return cr4;
-}
-
-u32 read_dr6()
-{
-    u32 dr6;
-    asm("movl %%dr6, %%eax"
-        : "=a"(dr6));
-    return dr6;
-}
-
-FPUState Processor::s_clean_fpu_state;
-
-static Vector<Processor*>* s_processors;
-static SpinLock s_processor_lock;
-
-Vector<Processor*>& Processor::processors()
-{
-    ASSERT(s_processors);
-    return *s_processors;
-}
-
-Processor& Processor::by_id(u32 cpu)
-{
-    // s_processors does not need to be protected by a lock of any kind.
-    // It is populated early in the boot process, and the BSP is waiting
-    // for all APs to finish, after which this array never gets modified
-    // again, so it's safe to not protect access to it here
-    auto& procs = processors();
-    ASSERT(procs[cpu] != nullptr);
-    ASSERT(procs.size() > cpu);
-    return *procs[cpu];
+    StringBuilder builder;
+    auto feature_to_str =
+        [](CPUFeature f) -> const char*
+        {
+            switch (f) {
+                case CPUFeature::NX:
+                    return "nx";
+                case CPUFeature::PAE:
+                    return "pae";
+                case CPUFeature::PGE:
+                    return "pge";
+                case CPUFeature::RDRAND:
+                    return "rdrand";
+                case CPUFeature::RDSEED:
+                    return "rdseed";
+                case CPUFeature::SMAP:
+                    return "smap";
+                case CPUFeature::SMEP:
+                    return "smep";
+                case CPUFeature::SSE:
+                    return "sse";
+                case CPUFeature::TSC:
+                    return "tsc";
+                case CPUFeature::UMIP:
+                    return "umip";
+                // no default statement here intentionally so that we get
+                // a warning if a new feature is forgotten to be added here
+            }
+            // Shouldn't ever happen
+            return "???";
+        };
+    bool first = true;
+    for (u32 flag = 1; flag < sizeof(m_features) * 8; flag <<= 1) {
+       if ((static_cast<u32>(m_features) & flag) != 0) {
+           if (first)
+               first = false;
+           else
+               builder.append(' ');
+           auto str = feature_to_str(static_cast<CPUFeature>(flag));
+           builder.append(str, strlen(str));
+       }
+    }
+    return builder.build();
 }
 }
 
 
 void Processor::early_initialize(u32 cpu)
 void Processor::early_initialize(u32 cpu)
@@ -838,6 +873,8 @@ void Processor::early_initialize(u32 cpu)
     m_mm_data = nullptr;
     m_mm_data = nullptr;
     m_info = nullptr;
     m_info = nullptr;
 
 
+    cpu_setup();
+
     gdt_init();
     gdt_init();
     ASSERT(&current() == this); // sanity check
     ASSERT(&current() == this); // sanity check
 }
 }
@@ -847,12 +884,9 @@ void Processor::initialize(u32 cpu)
     ASSERT(m_self == this);
     ASSERT(m_self == this);
     ASSERT(&current() == this); // sanity check
     ASSERT(&current() == this); // sanity check
 
 
-    m_cpu = cpu;
-    m_in_irq = 0;
-
-    m_idle_thread = nullptr;
-    m_current_thread = nullptr;
-    m_mm_data = nullptr;
+    klog() << "CPU[" << id() << "]: Supported features: " << features_string();
+    if (!has_feature(CPUFeature::RDRAND))
+        klog() << "CPU[" << id() << "]: No RDRAND support detected, randomness will be poor";
 
 
     if (cpu == 0)
     if (cpu == 0)
         idt_init();
         idt_init();

+ 28 - 16
Kernel/Arch/i386/CPU.h

@@ -265,7 +265,6 @@ struct RegisterState;
 
 
 const DescriptorTablePointer& get_gdtr();
 const DescriptorTablePointer& get_gdtr();
 const DescriptorTablePointer& get_idtr();
 const DescriptorTablePointer& get_idtr();
-void sse_init();
 void register_interrupt_handler(u8 number, void (*f)());
 void register_interrupt_handler(u8 number, void (*f)());
 void register_user_callable_interrupt_handler(u8 number, void (*f)());
 void register_user_callable_interrupt_handler(u8 number, void (*f)());
 GenericInterruptHandler& get_interrupt_handler(u8 interrupt_number);
 GenericInterruptHandler& get_interrupt_handler(u8 interrupt_number);
@@ -599,6 +598,19 @@ private:
     SplitQword m_start;
     SplitQword m_start;
 };
 };
 
 
+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),
+    UMIP = (1 << 9)
+};
+
 class Thread;
 class Thread;
 struct TrapFrame;
 struct TrapFrame;
 
 
@@ -614,6 +626,8 @@ class ProcessorInfo;
 struct MemoryManagerData;
 struct MemoryManagerData;
 
 
 class Processor {
 class Processor {
+    friend class ProcessorInfo;
+
     Processor* m_self; // must be first field (%fs offset 0x0)
     Processor* m_self; // must be first field (%fs offset 0x0)
 
 
     DescriptorTablePointer m_gdtr;
     DescriptorTablePointer m_gdtr;
@@ -626,6 +640,7 @@ class Processor {
 
 
     TSS32 m_tss;
     TSS32 m_tss;
     static FPUState s_clean_fpu_state;
     static FPUState s_clean_fpu_state;
+    CPUFeature m_features;
 
 
     ProcessorInfo* m_info;
     ProcessorInfo* m_info;
     MemoryManagerData* m_mm_data;
     MemoryManagerData* m_mm_data;
@@ -640,6 +655,11 @@ class Processor {
     void write_gdt_entry(u16 selector, Descriptor& descriptor);
     void write_gdt_entry(u16 selector, Descriptor& descriptor);
     static Vector<Processor*>& processors();
     static Vector<Processor*>& processors();
 
 
+    void cpu_detect();
+    void cpu_setup();
+
+    String features_string() const;
+
 public:
 public:
     void early_initialize(u32 cpu);
     void early_initialize(u32 cpu);
     void initialize(u32 cpu);
     void initialize(u32 cpu);
@@ -740,6 +760,11 @@ public:
         return s_clean_fpu_state;
         return s_clean_fpu_state;
     }
     }
     
     
+    ALWAYS_INLINE bool has_feature(CPUFeature f) const
+    {
+        return (static_cast<u32>(m_features) & static_cast<u32>(f)) != 0;
+    }
+    
     void check_invoke_scheduler();
     void check_invoke_scheduler();
     void invoke_scheduler_async() { m_invoke_scheduler_async = true; }
     void invoke_scheduler_async() { m_invoke_scheduler_async = true; }
     
     
@@ -846,22 +871,9 @@ public:
     }
     }
 };
 };
 
 
-void cpu_setup(u32 cpu);
-
-extern bool g_cpu_supports_nx;
-extern bool g_cpu_supports_pae;
-extern bool g_cpu_supports_pge;
-extern bool g_cpu_supports_rdrand;
-extern bool g_cpu_supports_rdseed;
-extern bool g_cpu_supports_smap;
-extern bool g_cpu_supports_smep;
-extern bool g_cpu_supports_sse;
-extern bool g_cpu_supports_tsc;
-extern bool g_cpu_supports_umip;
-
 ALWAYS_INLINE void stac()
 ALWAYS_INLINE void stac()
 {
 {
-    if (!g_cpu_supports_smap)
+    if (!Processor::current().has_feature(CPUFeature::SMAP))
         return;
         return;
     asm volatile("stac" ::
     asm volatile("stac" ::
                      : "cc");
                      : "cc");
@@ -869,7 +881,7 @@ ALWAYS_INLINE void stac()
 
 
 ALWAYS_INLINE void clac()
 ALWAYS_INLINE void clac()
 {
 {
-    if (!g_cpu_supports_smap)
+    if (!Processor::current().has_feature(CPUFeature::SMAP))
         return;
         return;
     asm volatile("clac" ::
     asm volatile("clac" ::
                      : "cc");
                      : "cc");

+ 3 - 0
Kernel/Arch/i386/ProcessorInfo.cpp

@@ -88,6 +88,9 @@ ProcessorInfo::ProcessorInfo(Processor& processor):
         copy_brand_string_part_to_buffer(2);
         copy_brand_string_part_to_buffer(2);
         m_brandstr = buffer;
         m_brandstr = buffer;
     }
     }
+
+    // Cache the CPU feature string
+    m_features = m_processor.features_string();
 }
 }
 
 
 }
 }

+ 2 - 0
Kernel/Arch/i386/ProcessorInfo.h

@@ -37,6 +37,7 @@ class ProcessorInfo
     Processor& m_processor;
     Processor& m_processor;
     String m_cpuid;
     String m_cpuid;
     String m_brandstr;
     String m_brandstr;
+    String m_features;
     u32 m_display_model;
     u32 m_display_model;
     u32 m_display_family;
     u32 m_display_family;
     u32 m_stepping;
     u32 m_stepping;
@@ -47,6 +48,7 @@ public:
     
     
     const String& cpuid() const { return m_cpuid; }
     const String& cpuid() const { return m_cpuid; }
     const String& brandstr() const { return m_brandstr; }
     const String& brandstr() const { return m_brandstr; }
+    const String& features() const { return m_features; }
     u32 display_model() const { return m_display_model; }
     u32 display_model() const { return m_display_model; }
     u32 display_family() const { return m_display_family; }
     u32 display_family() const { return m_display_family; }
     u32 stepping() const { return m_stepping; }
     u32 stepping() const { return m_stepping; }

+ 1 - 0
Kernel/FileSystem/ProcFS.cpp

@@ -773,6 +773,7 @@ Optional<KBuffer> procfs$cpuinfo(InodeIdentifier)
             builder.appendf("processor: %u\n", proc.id());
             builder.appendf("processor: %u\n", proc.id());
             builder.appendf("cpuid:     %s\n", info.cpuid().characters());
             builder.appendf("cpuid:     %s\n", info.cpuid().characters());
             builder.appendf("family:    %u\n", info.display_family());
             builder.appendf("family:    %u\n", info.display_family());
+            builder.appendf("features:  %s\n", info.features().characters());
             builder.appendf("model:     %u\n", info.display_model());
             builder.appendf("model:     %u\n", info.display_model());
             builder.appendf("stepping:  %u\n", info.stepping());
             builder.appendf("stepping:  %u\n", info.stepping());
             builder.appendf("type:      %u\n", info.type());
             builder.appendf("type:      %u\n", info.type());

+ 4 - 2
Kernel/Random.cpp

@@ -44,10 +44,12 @@ KernelRng& KernelRng::the()
 
 
 KernelRng::KernelRng()
 KernelRng::KernelRng()
 {
 {
-    if (g_cpu_supports_rdseed || g_cpu_supports_rdrand) {
+    bool supports_rdseed = Processor::current().has_feature(CPUFeature::RDSEED);
+    bool supports_rdrand = Processor::current().has_feature(CPUFeature::RDRAND);
+    if (supports_rdseed || supports_rdrand) {
         for (size_t i = 0; i < resource().pool_count * resource().reseed_threshold; ++i) {
         for (size_t i = 0; i < resource().pool_count * resource().reseed_threshold; ++i) {
             u32 value = 0;
             u32 value = 0;
-            if (g_cpu_supports_rdseed) {
+            if (supports_rdseed) {
                 asm volatile(
                 asm volatile(
                     "1:\n"
                     "1:\n"
                     "rdseed %0\n"
                     "rdseed %0\n"

+ 1 - 1
Kernel/VM/MemoryManager.cpp

@@ -80,7 +80,7 @@ void MemoryManager::protect_kernel_image()
         pte.set_writable(false);
         pte.set_writable(false);
     }
     }
 
 
-    if (g_cpu_supports_nx) {
+    if (Processor::current().has_feature(CPUFeature::NX)) {
         // Disable execution of the kernel data and bss segments.
         // Disable execution of the kernel data and bss segments.
         for (size_t i = (FlatPtr)&start_of_kernel_data; i < (FlatPtr)&end_of_kernel_bss; i += PAGE_SIZE) {
         for (size_t i = (FlatPtr)&start_of_kernel_data; i < (FlatPtr)&end_of_kernel_bss; i += PAGE_SIZE) {
             auto& pte = ensure_pte(kernel_page_directory(), VirtualAddress(i));
             auto& pte = ensure_pte(kernel_page_directory(), VirtualAddress(i));

+ 1 - 1
Kernel/VM/Region.cpp

@@ -237,7 +237,7 @@ void Region::map_individual_page_impl(size_t page_index)
             pte.set_writable(false);
             pte.set_writable(false);
         else
         else
             pte.set_writable(is_writable());
             pte.set_writable(is_writable());
-        if (g_cpu_supports_nx)
+        if (Processor::current().has_feature(CPUFeature::NX))
             pte.set_execute_disabled(!is_executable());
             pte.set_execute_disabled(!is_executable());
         pte.set_user_allowed(is_user_accessible());
         pte.set_user_allowed(is_user_accessible());
 #ifdef MM_DEBUG
 #ifdef MM_DEBUG

+ 0 - 2
Kernel/init.cpp

@@ -106,7 +106,6 @@ extern "C" [[noreturn]] void init()
     setup_serial_debug();
     setup_serial_debug();
 
 
     s_bsp_processor.early_initialize(0);
     s_bsp_processor.early_initialize(0);
-    cpu_setup(0);
 
 
     kmalloc_init();
     kmalloc_init();
     slab_alloc_init();
     slab_alloc_init();
@@ -169,7 +168,6 @@ extern "C" [[noreturn]] void init_ap(u32 cpu, Processor* processor_info)
 
 
     klog() << "CPU #" << cpu << " processor_info at " << VirtualAddress(FlatPtr(processor_info));
     klog() << "CPU #" << cpu << " processor_info at " << VirtualAddress(FlatPtr(processor_info));
 
 
-    cpu_setup(cpu);
     processor_info->initialize(cpu);
     processor_info->initialize(cpu);
     MemoryManager::initialize(cpu);
     MemoryManager::initialize(cpu);