Support for SMP on x86_64.
No major changes to the kernel: just compiled in arch_smp.cpp and fixed the IDT load in arch_cpu_init_percpu to use the correct limit for x86_64 (uses sizeof(interrupt_descriptor)). In the boot loader, changed smp_boot_other_cpus to construct a temporary GDT and get the page directory address from CR3, as what's in kernel_args will be 64-bit stuff and will not work to switch the CPUs into 32-bit mode in the trampoline code. Refactored 64-bit kernel entry code to not use the stack after disabling paging, as the secondary CPUs are given a 32-bit virtual stack address by the SMP trampoline code which will no longer work.
This commit is contained in:
@@ -50,6 +50,10 @@ typedef struct segment_descriptor {
|
||||
uint32 base_31_24 : 8; // 24 - 31
|
||||
} segment_descriptor;
|
||||
|
||||
typedef struct interrupt_descriptor {
|
||||
uint32 a, b;
|
||||
} interrupt_descriptor;
|
||||
|
||||
struct tss {
|
||||
uint16 prev_task;
|
||||
uint16 unused0;
|
||||
|
||||
@@ -83,11 +83,6 @@ struct interrupt_frame {
|
||||
uint32 eflags;
|
||||
};
|
||||
|
||||
struct interrupt_descriptor {
|
||||
uint32 a;
|
||||
uint32 b;
|
||||
};
|
||||
|
||||
|
||||
static interrupt_descriptor sDebugIDT[DEBUG_IDT_SLOT_COUNT];
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <kernel.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "smp.h"
|
||||
#include "mmu.h"
|
||||
|
||||
|
||||
@@ -31,6 +32,13 @@ static const uint64 kLargePageMappingFlags = 0x183;
|
||||
static const uint64 kPageMappingFlags = 0x103;
|
||||
// Global, R/W, Present
|
||||
|
||||
extern "C" void long_enter_kernel(int currentCPU, uint64 stackTop);
|
||||
|
||||
extern uint32 gLongPhysicalGDT;
|
||||
extern uint64 gLongVirtualGDT;
|
||||
extern uint32 gLongPhysicalPML4;
|
||||
extern uint64 gLongKernelEntry;
|
||||
|
||||
|
||||
/*! Convert a 32-bit address to a 64-bit address. */
|
||||
static inline uint64
|
||||
@@ -71,6 +79,10 @@ long_gdt_init()
|
||||
DPL_USER);
|
||||
set_segment_descriptor(&gdt[USER_DATA_SEG / 8], DT_DATA_WRITEABLE,
|
||||
DPL_USER);
|
||||
|
||||
// Used by long_enter_kernel().
|
||||
gLongPhysicalGDT = gKernelArgs.arch_args.phys_gdt;
|
||||
gLongVirtualGDT = gKernelArgs.arch_args.vir_gdt;
|
||||
}
|
||||
|
||||
|
||||
@@ -222,6 +234,8 @@ long_mmu_init()
|
||||
gKernelArgs.virtual_allocated_range[i].start,
|
||||
gKernelArgs.virtual_allocated_range[i].size);
|
||||
}
|
||||
|
||||
gLongPhysicalPML4 = gKernelArgs.arch_args.phys_pgdir;
|
||||
}
|
||||
|
||||
|
||||
@@ -275,12 +289,6 @@ convert_kernel_args()
|
||||
gKernelArgs.kernel_args_range[i].size);
|
||||
}
|
||||
|
||||
// Set correct kernel stack addresses.
|
||||
for (uint32 i = 0; i < gKernelArgs.num_cpus; i++) {
|
||||
gKernelArgs.cpu_kstack[i].start = fix_address(
|
||||
gKernelArgs.cpu_kstack[i].start);
|
||||
}
|
||||
|
||||
// Fix driver settings files.
|
||||
driver_settings_file* file = gKernelArgs.driver_settings;
|
||||
fix_address(gKernelArgs.driver_settings);
|
||||
@@ -293,6 +301,27 @@ convert_kernel_args()
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
long_smp_start_kernel(void)
|
||||
{
|
||||
uint32 cpu = smp_get_current_cpu();
|
||||
|
||||
// Important. Make sure supervisor threads can fault on read only pages...
|
||||
asm("movl %%eax, %%cr0" : : "a" ((1 << 31) | (1 << 16) | (1 << 5) | 1));
|
||||
asm("cld");
|
||||
asm("fninit");
|
||||
|
||||
// Fix our kernel stack address.
|
||||
gKernelArgs.cpu_kstack[cpu].start
|
||||
= fix_address(gKernelArgs.cpu_kstack[cpu].start);
|
||||
|
||||
long_enter_kernel(cpu, gKernelArgs.cpu_kstack[cpu].start
|
||||
+ gKernelArgs.cpu_kstack[cpu].size);
|
||||
|
||||
panic("Shouldn't get here");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
long_start_kernel()
|
||||
{
|
||||
@@ -305,8 +334,7 @@ long_start_kernel()
|
||||
preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>(
|
||||
gKernelArgs.kernel_image.Pointer());
|
||||
|
||||
// TODO: x86_64 SMP, disable for now.
|
||||
gKernelArgs.num_cpus = 1;
|
||||
smp_init_other_cpus();
|
||||
|
||||
long_gdt_init();
|
||||
long_idt_init();
|
||||
@@ -315,23 +343,22 @@ long_start_kernel()
|
||||
|
||||
debug_cleanup();
|
||||
|
||||
// Calculate the arguments for long_enter_kernel().
|
||||
uint64 entry = image->elf_header.e_entry;
|
||||
uint64 stackTop = gKernelArgs.cpu_kstack[0].start
|
||||
+ gKernelArgs.cpu_kstack[0].size;
|
||||
uint64 kernelArgs = (addr_t)&gKernelArgs;
|
||||
// Save the kernel entry point address.
|
||||
gLongKernelEntry = image->elf_header.e_entry;
|
||||
dprintf("kernel entry at %#llx\n", gLongKernelEntry);
|
||||
|
||||
dprintf("kernel entry at %#llx, stack %#llx, args %#llx\n", entry,
|
||||
stackTop, kernelArgs);
|
||||
// Fix our kernel stack address.
|
||||
gKernelArgs.cpu_kstack[0].start
|
||||
= fix_address(gKernelArgs.cpu_kstack[0].start);
|
||||
|
||||
// We're about to enter the kernel -- disable console output.
|
||||
stdout = NULL;
|
||||
|
||||
smp_boot_other_cpus(long_smp_start_kernel);
|
||||
|
||||
// Enter the kernel!
|
||||
long_enter_kernel(gKernelArgs.arch_args.phys_pgdir,
|
||||
gKernelArgs.arch_args.phys_gdt, gKernelArgs.arch_args.vir_gdt,
|
||||
entry, stackTop, kernelArgs, 0);
|
||||
long_enter_kernel(0, gKernelArgs.cpu_kstack[0].start
|
||||
+ gKernelArgs.cpu_kstack[0].size);
|
||||
|
||||
panic("Shouldn't get here");
|
||||
}
|
||||
|
||||
|
||||
@@ -9,10 +9,6 @@
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
extern "C" void long_enter_kernel(uint32 physPML4, uint32 physGDT,
|
||||
uint64 virtGDT, uint64 entry, uint64 stackTop, uint64 kernelArgs,
|
||||
int currentCPU);
|
||||
|
||||
extern void long_start_kernel();
|
||||
|
||||
|
||||
|
||||
@@ -17,15 +17,17 @@
|
||||
.code32
|
||||
|
||||
|
||||
/*! void long_enter_kernel(uint32 physPML4, uint32 physGDT, uint64 virtGDT,
|
||||
uint64 entry, uint64 stackTop, uint64 kernelArgs, int currentCPU);
|
||||
*/
|
||||
/*! void long_enter_kernel(int currentCPU, uint64 stackTop); */
|
||||
FUNCTION(long_enter_kernel):
|
||||
// Preserve the arguments. We may no longer be able to use the stack once
|
||||
// paging is disabled.
|
||||
movl 4(%esp), %ebx
|
||||
movl 8(%esp), %edi
|
||||
movl 12(%esp), %esi
|
||||
|
||||
// We're about to disable paging, so we need to load the the physical
|
||||
// address of our GDT.
|
||||
movl 8(%esp), %eax
|
||||
movl %eax, (long_gdtr + 2)
|
||||
lgdtl (long_gdtr)
|
||||
lgdtl long_phys_gdtr
|
||||
|
||||
// Currently running with 32-bit paging tables at an identity mapped
|
||||
// address. To switch to 64-bit paging we must first disable 32-bit paging,
|
||||
@@ -40,11 +42,11 @@ FUNCTION(long_enter_kernel):
|
||||
movl %eax, %cr4
|
||||
|
||||
// Point CR3 to the kernel's PML4.
|
||||
movl 4(%esp), %eax
|
||||
movl gLongPhysicalPML4, %eax
|
||||
movl %eax, %cr3
|
||||
|
||||
// Enable long mode by setting EFER.LME.
|
||||
movl $0xC0000080, %ecx
|
||||
movl $0xc0000080, %ecx
|
||||
rdmsr
|
||||
orl $(1 << 8), %eax
|
||||
wrmsr
|
||||
@@ -68,32 +70,41 @@ FUNCTION(long_enter_kernel):
|
||||
mov %ax, %fs
|
||||
mov %ax, %gs
|
||||
|
||||
// Clear the high 32 bits of RSP.
|
||||
movl %esp, %esp
|
||||
|
||||
// Load the virtual address of the GDT.
|
||||
movq 12(%rsp), %rax
|
||||
movq %rax, long_gdtr + 2(%rip)
|
||||
lgdtq long_gdtr(%rip)
|
||||
lgdtq long_virt_gdtr(%rip)
|
||||
|
||||
// Get the entry point address, arguments and new stack pointer.
|
||||
movq 20(%rsp), %rax
|
||||
movq 36(%rsp), %rdi
|
||||
movl 44(%rsp), %esi
|
||||
movq 28(%rsp), %rsp
|
||||
// Set the stack pointer.
|
||||
movl %edi, %esp
|
||||
shl $32, %rsi
|
||||
orq %rsi, %rsp
|
||||
|
||||
// Clear the stack frame/RFLAGS.
|
||||
xorq %rbp, %rbp
|
||||
push $0
|
||||
popf
|
||||
|
||||
// Call the kernel entry point.
|
||||
// Get arguments and call the kernel entry point.
|
||||
leaq gKernelArgs(%rip), %rdi
|
||||
movl %ebx, %esi
|
||||
movq gLongKernelEntry(%rip), %rax
|
||||
call *%rax
|
||||
|
||||
|
||||
.data
|
||||
|
||||
|
||||
long_gdtr:
|
||||
long_phys_gdtr:
|
||||
.word GDT_LIMIT - 1
|
||||
SYMBOL(gLongPhysicalGDT):
|
||||
.long 0
|
||||
|
||||
long_virt_gdtr:
|
||||
.word GDT_LIMIT - 1
|
||||
SYMBOL(gLongVirtualGDT):
|
||||
.quad 0
|
||||
|
||||
SYMBOL(gLongPhysicalPML4):
|
||||
.long 0
|
||||
|
||||
SYMBOL(gLongKernelEntry):
|
||||
.quad 0
|
||||
|
||||
@@ -20,8 +20,10 @@
|
||||
#include <boot/menu.h>
|
||||
#include <arch/x86/apic.h>
|
||||
#include <arch/x86/arch_acpi.h>
|
||||
#include <arch/x86/arch_cpu.h>
|
||||
#include <arch/x86/arch_smp.h>
|
||||
#include <arch/x86/arch_system_info.h>
|
||||
#include <arch/x86/descriptors.h>
|
||||
|
||||
#include "mmu.h"
|
||||
#include "acpi.h"
|
||||
@@ -37,10 +39,6 @@
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
struct gdt_idt_descr {
|
||||
uint16 a;
|
||||
uint32 *b;
|
||||
} _PACKED;
|
||||
|
||||
static struct scan_spots_struct smp_scan_spots[] = {
|
||||
{ 0x9fc00, 0xa0000, 0xa0000 - 0x9fc00 },
|
||||
@@ -54,9 +52,6 @@ extern "C" void smp_trampoline(void);
|
||||
extern "C" void smp_trampoline_end(void);
|
||||
|
||||
|
||||
static int smp_get_current_cpu(void);
|
||||
|
||||
|
||||
static uint32
|
||||
apic_read(uint32 offset)
|
||||
{
|
||||
@@ -71,22 +66,6 @@ apic_write(uint32 offset, uint32 data)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
smp_get_current_cpu(void)
|
||||
{
|
||||
if (gKernelArgs.arch_args.apic == NULL)
|
||||
return 0;
|
||||
|
||||
uint8 apicID = apic_read(APIC_ID) >> 24;
|
||||
for (uint32 i = 0; i < gKernelArgs.num_cpus; i++) {
|
||||
if (gKernelArgs.arch_args.cpu_apic_id[i] == apicID)
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static mp_floating_struct *
|
||||
smp_mp_probe(uint32 base, uint32 limit)
|
||||
{
|
||||
@@ -341,56 +320,6 @@ smp_do_acpi_config(void)
|
||||
}
|
||||
|
||||
|
||||
/*! Target function of the trampoline code.
|
||||
The trampoline code should have the pgdir and a gdt set up for us,
|
||||
along with us being on the final stack for this processor. We need
|
||||
to set up the local APIC and load the global idt and gdt. When we're
|
||||
done, we'll jump into the kernel with the cpu number as an argument.
|
||||
*/
|
||||
static int
|
||||
smp_cpu_ready(void)
|
||||
{
|
||||
uint32 curr_cpu = smp_get_current_cpu();
|
||||
struct gdt_idt_descr idt_descr;
|
||||
struct gdt_idt_descr gdt_descr;
|
||||
|
||||
//TRACE(("smp_cpu_ready: entry cpu %ld\n", curr_cpu));
|
||||
|
||||
preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>(
|
||||
gKernelArgs.kernel_image.Pointer());
|
||||
|
||||
// Important. Make sure supervisor threads can fault on read only pages...
|
||||
asm("movl %%eax, %%cr0" : : "a" ((1 << 31) | (1 << 16) | (1 << 5) | 1));
|
||||
asm("cld");
|
||||
asm("fninit");
|
||||
|
||||
// Set up the final idt
|
||||
idt_descr.a = IDT_LIMIT - 1;
|
||||
idt_descr.b = (uint32 *)(addr_t)gKernelArgs.arch_args.vir_idt;
|
||||
|
||||
asm("lidt %0;"
|
||||
: : "m" (idt_descr));
|
||||
|
||||
// Set up the final gdt
|
||||
gdt_descr.a = GDT_LIMIT - 1;
|
||||
gdt_descr.b = (uint32 *)gKernelArgs.arch_args.vir_gdt;
|
||||
|
||||
asm("lgdt %0;"
|
||||
: : "m" (gdt_descr));
|
||||
|
||||
asm("pushl %0; " // push the cpu number
|
||||
"pushl %1; " // kernel args
|
||||
"pushl $0x0;" // dummy retval for call to main
|
||||
"pushl %2; " // this is the start address
|
||||
"ret; " // jump.
|
||||
: : "g" (curr_cpu), "g" (&gKernelArgs),
|
||||
"g" (image->elf_header.e_entry));
|
||||
|
||||
// no where to return to
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
calculate_apic_timer_conversion_factor(void)
|
||||
{
|
||||
@@ -429,6 +358,22 @@ calculate_apic_timer_conversion_factor(void)
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
int
|
||||
smp_get_current_cpu(void)
|
||||
{
|
||||
if (gKernelArgs.arch_args.apic == NULL)
|
||||
return 0;
|
||||
|
||||
uint8 apicID = apic_read(APIC_ID) >> 24;
|
||||
for (uint32 i = 0; i < gKernelArgs.num_cpus; i++) {
|
||||
if (gKernelArgs.arch_args.cpu_apic_id[i] == apicID)
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
smp_init_other_cpus(void)
|
||||
{
|
||||
@@ -476,7 +421,7 @@ smp_init_other_cpus(void)
|
||||
|
||||
|
||||
void
|
||||
smp_boot_other_cpus(void)
|
||||
smp_boot_other_cpus(void (*entryFunc)())
|
||||
{
|
||||
if (gKernelArgs.num_cpus < 2)
|
||||
return;
|
||||
@@ -516,7 +461,7 @@ smp_boot_other_cpus(void)
|
||||
tempStack = (finalStack
|
||||
+ (KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE)
|
||||
/ sizeof(uint32)) - 1;
|
||||
*tempStack = (uint32)&smp_cpu_ready;
|
||||
*tempStack = (uint32)entryFunc;
|
||||
|
||||
// set the trampoline stack up
|
||||
tempStack = (uint32 *)(trampolineStack + B_PAGE_SIZE - 4);
|
||||
@@ -525,15 +470,20 @@ smp_boot_other_cpus(void)
|
||||
+ KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE - sizeof(uint32);
|
||||
tempStack--;
|
||||
// page dir
|
||||
*tempStack = gKernelArgs.arch_args.phys_pgdir;
|
||||
*tempStack = x86_read_cr3() & 0xfffff000;
|
||||
|
||||
// put a gdt descriptor at the bottom of the stack
|
||||
*((uint16 *)trampolineStack) = 0x18 - 1; // LIMIT
|
||||
*((uint32 *)(trampolineStack + 2)) = trampolineStack + 8;
|
||||
|
||||
// put the gdt at the bottom
|
||||
memcpy(&((uint32 *)trampolineStack)[2],
|
||||
(void *)gKernelArgs.arch_args.vir_gdt, 6 * 4);
|
||||
// construct a temporary gdt at the bottom
|
||||
segment_descriptor* tempGDT
|
||||
= (segment_descriptor*)&((uint32 *)trampolineStack)[2];
|
||||
clear_segment_descriptor(&tempGDT[0]);
|
||||
set_segment_descriptor(&tempGDT[1], 0, 0xffffffff, DT_CODE_READABLE,
|
||||
DPL_KERNEL);
|
||||
set_segment_descriptor(&tempGDT[2], 0, 0xffffffff, DT_DATA_WRITEABLE,
|
||||
DPL_KERNEL);
|
||||
|
||||
/* clear apic errors */
|
||||
if (gKernelArgs.arch_args.cpu_apic_version[i] & 0xf0) {
|
||||
|
||||
@@ -19,7 +19,9 @@ extern "C" {
|
||||
|
||||
extern void smp_init(void);
|
||||
extern void smp_init_other_cpus(void);
|
||||
extern void smp_boot_other_cpus(void);
|
||||
extern void smp_boot_other_cpus(void (*entryFunc)());
|
||||
|
||||
extern int smp_get_current_cpu(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -73,6 +73,55 @@ platform_boot_options(void)
|
||||
}
|
||||
|
||||
|
||||
/*! Target function of the SMP trampoline code.
|
||||
The trampoline code should have the pgdir and a gdt set up for us,
|
||||
along with us being on the final stack for this processor. We need
|
||||
to set up the local APIC and load the global idt and gdt. When we're
|
||||
done, we'll jump into the kernel with the cpu number as an argument.
|
||||
*/
|
||||
static void
|
||||
smp_start_kernel(void)
|
||||
{
|
||||
uint32 curr_cpu = smp_get_current_cpu();
|
||||
struct gdt_idt_descr idt_descr;
|
||||
struct gdt_idt_descr gdt_descr;
|
||||
|
||||
//TRACE(("smp_cpu_ready: entry cpu %ld\n", curr_cpu));
|
||||
|
||||
preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>(
|
||||
gKernelArgs.kernel_image.Pointer());
|
||||
|
||||
// Important. Make sure supervisor threads can fault on read only pages...
|
||||
asm("movl %%eax, %%cr0" : : "a" ((1 << 31) | (1 << 16) | (1 << 5) | 1));
|
||||
asm("cld");
|
||||
asm("fninit");
|
||||
|
||||
// Set up the final idt
|
||||
idt_descr.limit = IDT_LIMIT - 1;
|
||||
idt_descr.base = (uint32 *)(addr_t)gKernelArgs.arch_args.vir_idt;
|
||||
|
||||
asm("lidt %0;"
|
||||
: : "m" (idt_descr));
|
||||
|
||||
// Set up the final gdt
|
||||
gdt_descr.limit = GDT_LIMIT - 1;
|
||||
gdt_descr.base = (uint32 *)gKernelArgs.arch_args.vir_gdt;
|
||||
|
||||
asm("lgdt %0;"
|
||||
: : "m" (gdt_descr));
|
||||
|
||||
asm("pushl %0; " // push the cpu number
|
||||
"pushl %1; " // kernel args
|
||||
"pushl $0x0;" // dummy retval for call to main
|
||||
"pushl %2; " // this is the start address
|
||||
"ret; " // jump.
|
||||
: : "g" (curr_cpu), "g" (&gKernelArgs),
|
||||
"g" (image->elf_header.e_entry));
|
||||
|
||||
panic("kernel returned!\n");
|
||||
}
|
||||
|
||||
|
||||
extern "C" void
|
||||
platform_start_kernel(void)
|
||||
{
|
||||
@@ -99,7 +148,7 @@ platform_start_kernel(void)
|
||||
// We're about to enter the kernel -- disable console output.
|
||||
stdout = NULL;
|
||||
|
||||
smp_boot_other_cpus();
|
||||
smp_boot_other_cpus(smp_start_kernel);
|
||||
|
||||
dprintf("kernel entry at %lx\n", image->elf_header.e_entry);
|
||||
|
||||
|
||||
@@ -62,10 +62,7 @@ static const int kInterruptNameCount = 20;
|
||||
|
||||
#define MAX_ARGS 16
|
||||
|
||||
typedef struct {
|
||||
uint32 a, b;
|
||||
} desc_table;
|
||||
static desc_table* sIDTs[B_MAX_CPU_COUNT];
|
||||
static interrupt_descriptor* sIDTs[B_MAX_CPU_COUNT];
|
||||
|
||||
// table with functions handling respective interrupts
|
||||
typedef void interrupt_handler_function(struct iframe* frame);
|
||||
@@ -80,7 +77,7 @@ extern void hardware_interrupt(struct iframe* frame);
|
||||
/*! Initializes a descriptor in an IDT.
|
||||
*/
|
||||
static void
|
||||
set_gate(desc_table *gate_addr, addr_t addr, int type, int dpl)
|
||||
set_gate(interrupt_descriptor *gate_addr, addr_t addr, int type, int dpl)
|
||||
{
|
||||
unsigned int gate1; // first byte of gate desc
|
||||
unsigned int gate2; // second byte of gate desc
|
||||
@@ -353,7 +350,7 @@ arch_int_init(struct kernel_args *args)
|
||||
interrupt_handler_function** table;
|
||||
|
||||
// set the global sIDT variable
|
||||
sIDTs[0] = (desc_table *)(addr_t)args->arch_args.vir_idt;
|
||||
sIDTs[0] = (interrupt_descriptor *)(addr_t)args->arch_args.vir_idt;
|
||||
|
||||
// setup the standard programmable interrupt controller
|
||||
pic_init();
|
||||
@@ -668,7 +665,7 @@ arch_int_init_post_vm(struct kernel_args *args)
|
||||
int32 cpuCount = smp_get_num_cpus();
|
||||
if (cpuCount > 0) {
|
||||
size_t areaSize = ROUNDUP(cpuCount * idtSize, B_PAGE_SIZE);
|
||||
desc_table* idt;
|
||||
interrupt_descriptor* idt;
|
||||
virtual_address_restrictions virtualRestrictions = {};
|
||||
virtualRestrictions.address_specification = B_ANY_KERNEL_ADDRESS;
|
||||
physical_address_restrictions physicalRestrictions = {};
|
||||
|
||||
@@ -270,34 +270,6 @@ arch_debug_call_with_fault_handler(cpu_ent* cpu, jmp_buf jumpBuffer,
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
arch_smp_init(kernel_args *args)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
arch_smp_per_cpu_init(kernel_args *args, int32 cpu)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
arch_smp_send_broadcast_ici(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
arch_smp_send_ici(int32 target_cpu)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
// The software breakpoint instruction (int3).
|
||||
const uint8 kX86SoftwareBreakpoint[1] = { 0xcc };
|
||||
|
||||
|
||||
@@ -48,7 +48,6 @@ if $(TARGET_ARCH) = x86_64 {
|
||||
|
||||
arch_commpage.cpp
|
||||
arch_debug.cpp
|
||||
arch_smp.cpp
|
||||
arch_user_debugger.cpp
|
||||
apm.cpp
|
||||
bios.cpp
|
||||
@@ -83,6 +82,7 @@ local archGenericSources =
|
||||
arch_int.cpp
|
||||
arch_platform.cpp
|
||||
arch_real_time_clock.cpp
|
||||
arch_smp.cpp
|
||||
arch_system_info.cpp
|
||||
arch_thread.cpp
|
||||
arch_timer.cpp
|
||||
|
||||
@@ -349,7 +349,7 @@ x86_init_fpu(void)
|
||||
static void
|
||||
load_tss(int cpu)
|
||||
{
|
||||
short seg = ((TSS_BASE_SEGMENT + cpu) << 3) | DPL_KERNEL;
|
||||
short seg = (TSS_SEGMENT(cpu) << 3) | DPL_KERNEL;
|
||||
asm("ltr %%ax" : : "a" (seg));
|
||||
}
|
||||
|
||||
@@ -789,7 +789,8 @@ arch_cpu_init_percpu(kernel_args* args, int cpu)
|
||||
uint16 limit;
|
||||
void* address;
|
||||
} _PACKED descriptor = {
|
||||
256 * 8 - 1, // 256 descriptors, 8 bytes each (-1 for "limit")
|
||||
256 * sizeof(interrupt_descriptor) - 1,
|
||||
// 256 descriptors (-1 for "limit")
|
||||
x86_get_idt(cpu)
|
||||
};
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ static int32
|
||||
x86_spurious_interrupt(void *data)
|
||||
{
|
||||
// spurious interrupt
|
||||
TRACE(("spurious interrupt on cpu %ld\n", smp_get_current_cpu()));
|
||||
TRACE(("spurious interrupt on cpu %" B_PRId32 "\n", smp_get_current_cpu()));
|
||||
|
||||
// spurious interrupts must not be acknowledged as it does not expect
|
||||
// a end of interrupt - if we still do it we would loose the next best
|
||||
@@ -65,7 +65,7 @@ static int32
|
||||
x86_smp_error_interrupt(void *data)
|
||||
{
|
||||
// smp error interrupt
|
||||
TRACE(("smp error interrupt on cpu %ld\n", smp_get_current_cpu()));
|
||||
TRACE(("smp error interrupt on cpu %" B_PRId32 "\n", smp_get_current_cpu()));
|
||||
return B_HANDLED_INTERRUPT;
|
||||
}
|
||||
|
||||
@@ -104,7 +104,8 @@ status_t
|
||||
arch_smp_per_cpu_init(kernel_args *args, int32 cpu)
|
||||
{
|
||||
// set up the local apic on the current cpu
|
||||
TRACE(("arch_smp_init_percpu: setting up the apic on cpu %ld\n", cpu));
|
||||
TRACE(("arch_smp_init_percpu: setting up the apic on cpu %" B_PRId32 "\n",
|
||||
cpu));
|
||||
apic_per_cpu_init(args, cpu);
|
||||
|
||||
// setup FPU and SSE if supported
|
||||
@@ -154,7 +155,7 @@ arch_smp_send_ici(int32 target_cpu)
|
||||
asm volatile ("pause;");
|
||||
|
||||
if (timeout == 0)
|
||||
panic("arch_smp_send_ici: timeout, target_cpu %ld", target_cpu);
|
||||
panic("arch_smp_send_ici: timeout, target_cpu %" B_PRId32, target_cpu);
|
||||
|
||||
restore_interrupts(state);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user