mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-21 22:47:50 +00:00
parent
f0f473392d
commit
cf3ff17c50
@ -6,4 +6,6 @@ SRC_S += bootstrap/spec/x86_64/crt0_translation_table.s
|
||||
|
||||
SRC_CC += hw/spec/64bit/memory_map.cc
|
||||
|
||||
NR_OF_CPUS = 32
|
||||
|
||||
include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc
|
||||
|
@ -20,7 +20,6 @@ SRC_CC += spec/x86_64/kernel/thread_exception.cc
|
||||
SRC_CC += spec/x86_64/platform_support.cc
|
||||
SRC_CC += spec/x86/platform_services.cc
|
||||
|
||||
SRC_CC += kernel/kernel.cc
|
||||
SRC_CC += spec/x86/io_port_session_component.cc
|
||||
SRC_CC += spec/x86/io_port_session_support.cc
|
||||
SRC_CC += spec/x86_64/bios_data_area.cc
|
||||
@ -30,10 +29,14 @@ SRC_CC += spec/x86_64/kernel/cpu.cc
|
||||
SRC_CC += spec/x86_64/kernel/thread.cc
|
||||
SRC_CC += spec/x86_64/kernel/thread.cc
|
||||
SRC_CC += spec/x86_64/platform_support_common.cc
|
||||
SRC_CC += spec/x86_64/smp/cpu.cc
|
||||
|
||||
SRC_CC += spec/64bit/memory_map.cc
|
||||
|
||||
vpath spec/64bit/memory_map.cc $(BASE_DIR)/../base-hw/src/lib/hw
|
||||
|
||||
NR_OF_CPUS = 32
|
||||
|
||||
# include less specific configuration
|
||||
include $(BASE_DIR)/../base-hw/lib/mk/core-hw.inc
|
||||
include $(BASE_DIR)/../base-hw/lib/mk/spec/smp/core-hw.inc
|
||||
|
@ -1 +1 @@
|
||||
a4ce6a1f3bc1209e4c9f8ecf163d7af354c188af
|
||||
e51f0c9bfe99c284b3cf3bcf5fb81f7e9052f8a6
|
||||
|
10
repos/base-hw/ports/muen.patch
Normal file
10
repos/base-hw/ports/muen.patch
Normal file
@ -0,0 +1,10 @@
|
||||
+++ src/kernel/muen/policy/xml/vcpu_subject_base_hw.xml
|
||||
@@ -9,7 +9,7 @@
|
||||
</vmx>
|
||||
<registers>
|
||||
<gpr>
|
||||
- <rip>16#0020_0028#</rip>
|
||||
+ <rip>16#0020_0078#</rip>
|
||||
<rsp>16#0000#</rsp>
|
||||
</gpr>
|
||||
</registers>
|
@ -6,6 +6,8 @@ URL(muen) := https://git.codelabs.ch/git/muen.git
|
||||
REV(muen) := 807cb0381e12329d84cb7e6b2f778b1e1559a2e8
|
||||
DIR(muen) := src/kernel/muen
|
||||
|
||||
PATCHES := ports/muen.patch
|
||||
|
||||
$(call check_tool,git)
|
||||
$(call check_tool,iasl)
|
||||
$(call check_tool,tidy)
|
||||
|
@ -4,16 +4,19 @@
|
||||
* \author Martin Stein
|
||||
* \author Reto Buerki
|
||||
* \author Stefan Kalkowski
|
||||
* \author Alexander Boettcher
|
||||
* \date 2015-02-06
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2011-2018 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
.set STACK_SIZE, 4096
|
||||
|
||||
.section ".text.crt0"
|
||||
|
||||
/* magic multi-boot 1 header */
|
||||
@ -34,9 +37,55 @@
|
||||
.long 0x8
|
||||
__mbi2_end:
|
||||
|
||||
/**********************************
|
||||
** Startup code for primary CPU **
|
||||
**********************************/
|
||||
|
||||
.macro SETUP_PAGING
|
||||
/* Enable PAE (prerequisite for IA-32e mode) */
|
||||
movl $0x20, %eax
|
||||
movl %eax, %cr4
|
||||
|
||||
/* Enable IA-32e mode and execute-disable */
|
||||
movl $0xc0000080, %ecx
|
||||
rdmsr
|
||||
btsl $8, %eax
|
||||
btsl $11, %eax
|
||||
wrmsr
|
||||
|
||||
/* Enable paging, write protection and caching */
|
||||
xorl %eax, %eax
|
||||
btsl $0, %eax /* protected mode */
|
||||
btsl $16, %eax /* write protect */
|
||||
btsl $31, %eax /* paging */
|
||||
movl %eax, %cr0
|
||||
.endm
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
** Startup code for non-primary CPU (AP - application processor) **
|
||||
*******************************************************************/
|
||||
|
||||
.code16
|
||||
.global _ap
|
||||
_ap:
|
||||
|
||||
/* Load initial pagetables */
|
||||
mov $_kernel_pml4, %eax
|
||||
mov %eax, %cr3
|
||||
|
||||
/* setup paging */
|
||||
SETUP_PAGING
|
||||
|
||||
/* setup GDT */
|
||||
lgdtl %cs:__gdt - _ap
|
||||
ljmpl $8, $_start64
|
||||
|
||||
__gdt:
|
||||
.word 55
|
||||
.long __gdt_start
|
||||
|
||||
|
||||
/**************************************************************
|
||||
** Startup code for primary CPU (bootstrap processor - BSP) **
|
||||
**************************************************************/
|
||||
|
||||
.code32
|
||||
.global _start
|
||||
@ -55,40 +104,30 @@
|
||||
xor %eax, %eax
|
||||
rep stosl
|
||||
|
||||
/* Enable PAE (prerequisite for IA-32e mode) */
|
||||
movl %cr4, %eax
|
||||
btsl $5, %eax
|
||||
movl %eax, %cr4
|
||||
|
||||
/* Load initial pagetables */
|
||||
leal _kernel_pml4, %eax
|
||||
mov %eax, %cr3
|
||||
|
||||
/* Enable IA-32e mode and execute-disable */
|
||||
movl $0xc0000080, %ecx
|
||||
rdmsr
|
||||
btsl $8, %eax
|
||||
btsl $11, %eax
|
||||
wrmsr
|
||||
/* setup paging */
|
||||
SETUP_PAGING
|
||||
|
||||
/* Enable paging, write protection and caching */
|
||||
movl %cr0, %eax
|
||||
btsl $16, %eax
|
||||
btrl $29, %eax
|
||||
btrl $30, %eax
|
||||
btsl $31, %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
/* Set up GDT */
|
||||
movl $__gdt_ptr+2, %eax
|
||||
movl $__gdt_start, (%eax)
|
||||
/* setup GDT */
|
||||
lgdt __gdt_ptr
|
||||
|
||||
/* Indirect long jump to 64-bit code */
|
||||
ljmp $8, $_start64
|
||||
ljmp $8, $_start64_bsp
|
||||
|
||||
|
||||
.code64
|
||||
_start64_bsp:
|
||||
|
||||
/* save rax & rbx, used to lookup multiboot structures */
|
||||
movq __initial_ax@GOTPCREL(%rip),%rax
|
||||
movq %rsi, (%rax)
|
||||
|
||||
movq __initial_bx@GOTPCREL(%rip),%rax
|
||||
movq %rbx, (%rax)
|
||||
|
||||
_start64:
|
||||
|
||||
/*
|
||||
@ -99,26 +138,38 @@
|
||||
mov %eax, %fs
|
||||
mov %eax, %gs
|
||||
|
||||
/*
|
||||
* Install initial temporary environment that is replaced later by the
|
||||
* environment that init_main_thread creates.
|
||||
*/
|
||||
leaq _stack_high@GOTPCREL(%rip),%rax
|
||||
/* increment CPU counter atomically */
|
||||
movq __cpus_booted@GOTPCREL(%rip),%rax
|
||||
movq $1, %rcx
|
||||
lock xaddq %rcx, (%rax)
|
||||
|
||||
/* if more CPUs started than supported, then stop them */
|
||||
cmp $NR_OF_CPUS, %rcx
|
||||
jge 1f
|
||||
|
||||
/* calculate stack depending on CPU counter */
|
||||
movq $STACK_SIZE, %rax
|
||||
inc %rcx
|
||||
mulq %rcx
|
||||
movq %rax, %rcx
|
||||
subq $8, %rcx
|
||||
leaq __bootstrap_stack@GOTPCREL(%rip),%rax
|
||||
movq (%rax), %rsp
|
||||
|
||||
movq __initial_ax@GOTPCREL(%rip),%rax
|
||||
movq %rsi, (%rax)
|
||||
|
||||
movq __initial_bx@GOTPCREL(%rip),%rax
|
||||
movq %rbx, (%rax)
|
||||
addq %rcx, %rsp
|
||||
|
||||
/* kernel-initialization */
|
||||
call init
|
||||
|
||||
/* catch erroneous return of the kernel initialization */
|
||||
1: jmp 1b
|
||||
1:
|
||||
hlt
|
||||
jmp 1b
|
||||
|
||||
|
||||
.global bootstrap_stack_size
|
||||
bootstrap_stack_size:
|
||||
.quad STACK_SIZE
|
||||
|
||||
/******************************************
|
||||
** Global Descriptor Table (GDT) **
|
||||
** See Intel SDM Vol. 3A, section 3.5.1 **
|
||||
@ -128,7 +179,7 @@
|
||||
.space 2
|
||||
__gdt_ptr:
|
||||
.word 55 /* limit */
|
||||
.long 0 /* base address */
|
||||
.long __gdt_start /* base address */
|
||||
|
||||
.set TSS_LIMIT, 0x68
|
||||
.set TSS_TYPE, 0x8900
|
||||
@ -171,12 +222,19 @@
|
||||
.bss
|
||||
|
||||
/* stack of the temporary initial environment */
|
||||
.p2align 8
|
||||
.space 32 * 1024
|
||||
_stack_high:
|
||||
.p2align 12
|
||||
.globl __bootstrap_stack
|
||||
__bootstrap_stack:
|
||||
.rept NR_OF_CPUS
|
||||
.space STACK_SIZE
|
||||
.endr
|
||||
|
||||
.globl __initial_ax
|
||||
__initial_ax:
|
||||
.space 8
|
||||
.globl __initial_bx
|
||||
__initial_bx:
|
||||
.space 8
|
||||
.globl __cpus_booted
|
||||
__cpus_booted:
|
||||
.quad 0
|
||||
|
@ -34,14 +34,15 @@
|
||||
/* PDP */
|
||||
.p2align MIN_PAGE_SIZE_LOG2
|
||||
_kernel_pdp:
|
||||
.quad _kernel_pd + 0xf
|
||||
.fill 2, 8, 0x0
|
||||
.quad _kernel_pd_503 + 0xf
|
||||
.quad _kernel_pd_0 + 0xf
|
||||
.fill 1, 8, 0x0
|
||||
.quad _kernel_pd_2 + 0xf
|
||||
.quad _kernel_pd_3 + 0xf
|
||||
.fill 508, 8, 0x0
|
||||
|
||||
/* PD */
|
||||
/* PD [0G-1G) */
|
||||
.p2align MIN_PAGE_SIZE_LOG2
|
||||
_kernel_pd:
|
||||
_kernel_pd_0:
|
||||
.quad _kernel_pt_bda + 0xf
|
||||
.set entry, 0x20018f
|
||||
.rept 511
|
||||
@ -49,9 +50,23 @@
|
||||
.set entry, entry + 0x200000
|
||||
.endr
|
||||
|
||||
/* PD [2G-3G) */
|
||||
.p2align MIN_PAGE_SIZE_LOG2
|
||||
_kernel_pd_503:
|
||||
.fill 502, 8, 0x0
|
||||
_kernel_pd_2:
|
||||
.set entry, 0x8000018f
|
||||
.rept 512
|
||||
.quad entry
|
||||
.set entry, entry + 0x200000
|
||||
.endr
|
||||
|
||||
/* PD [3G-4G) */
|
||||
.p2align MIN_PAGE_SIZE_LOG2
|
||||
_kernel_pd_3:
|
||||
.set entry, 0xc000018f
|
||||
.rept 502
|
||||
.quad entry
|
||||
.set entry, entry + 0x200000
|
||||
.endr
|
||||
.quad 0xfec0019f
|
||||
.quad 0xfee0019f
|
||||
.fill 8, 8, 0x0
|
||||
|
@ -2,11 +2,12 @@
|
||||
* \brief Platform implementations specific for x86_64
|
||||
* \author Reto Buerki
|
||||
* \author Stefan Kalkowski
|
||||
* \author Alexander Boettcher
|
||||
* \date 2015-05-04
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2015-2018 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -27,6 +28,39 @@ extern "C" Genode::addr_t __initial_ax;
|
||||
/* contains physical pointer to multiboot */
|
||||
extern "C" Genode::addr_t __initial_bx;
|
||||
|
||||
/* pointer to stack base */
|
||||
extern "C" Genode::addr_t __bootstrap_stack;
|
||||
|
||||
/* number of booted CPUs */
|
||||
extern "C" Genode::addr_t __cpus_booted;
|
||||
|
||||
/* stack size per CPU */
|
||||
extern "C" Genode::addr_t const bootstrap_stack_size;
|
||||
|
||||
|
||||
/* hardcoded physical page or AP CPUs boot code */
|
||||
enum { AP_BOOT_CODE_PAGE = 0x1000 };
|
||||
|
||||
extern "C" void * _start;
|
||||
extern "C" void * _ap;
|
||||
|
||||
static Hw::Acpi_rsdp search_rsdp(addr_t area, addr_t area_size)
|
||||
{
|
||||
if (area && area_size && area < area + area_size) {
|
||||
for (addr_t addr = 0; addr + sizeof(Hw::Acpi_rsdp) <= area_size;
|
||||
addr += sizeof(Hw::Acpi_rsdp::signature))
|
||||
{
|
||||
Hw::Acpi_rsdp * rsdp = reinterpret_cast<Hw::Acpi_rsdp *>(area + addr);
|
||||
if (rsdp->valid())
|
||||
return *rsdp;
|
||||
}
|
||||
}
|
||||
|
||||
Hw::Acpi_rsdp invalid;
|
||||
return invalid;
|
||||
}
|
||||
|
||||
|
||||
Bootstrap::Platform::Board::Board()
|
||||
: core_mmio(Memory_region { 0, 0x1000 },
|
||||
Memory_region { Hw::Cpu_memory_map::lapic_phys_base(), 0x1000 },
|
||||
@ -97,67 +131,178 @@ Bootstrap::Platform::Board::Board()
|
||||
|
||||
lambda(base, size);
|
||||
}
|
||||
|
||||
/* search ACPI RSDP pointer at known places */
|
||||
|
||||
/* BIOS range to scan for */
|
||||
enum { BIOS_BASE = 0xe0000, BIOS_SIZE = 0x20000 };
|
||||
acpi_rsdp = search_rsdp(BIOS_BASE, BIOS_SIZE);
|
||||
|
||||
if (!acpi_rsdp.valid()) {
|
||||
/* page 0 is remapped to 2M - 4k - see crt_translation table */
|
||||
addr_t const bios_addr = 2 * 1024 * 1024 - 4096;
|
||||
|
||||
/* search EBDA (BIOS addr + 0x40e) */
|
||||
addr_t ebda_phys = (*reinterpret_cast<uint16_t *>(bios_addr + 0x40e)) << 4;
|
||||
if (ebda_phys < 0x1000)
|
||||
ebda_phys = bios_addr;
|
||||
|
||||
acpi_rsdp = search_rsdp(ebda_phys, 0x1000 /* EBDA size */);
|
||||
}
|
||||
} else {
|
||||
error("invalid multiboot magic value: ", Hex(__initial_ax));
|
||||
}
|
||||
|
||||
if (!acpi_rsdp.valid())
|
||||
return;
|
||||
|
||||
uint64_t const table_addr = acpi_rsdp.xsdt ? acpi_rsdp.xsdt : acpi_rsdp.rsdt;
|
||||
|
||||
if (!table_addr)
|
||||
return;
|
||||
|
||||
/* find out the number of available CPUs */
|
||||
/* remember max supported CPUs and use ACPI to get the actual number */
|
||||
unsigned const max_cpus = cpus;
|
||||
cpus = 0;
|
||||
|
||||
Hw::Acpi_generic * table = reinterpret_cast<Hw::Acpi_generic *>(table_addr);
|
||||
if (!memcmp(table->signature, "RSDT", 4)) {
|
||||
Hw::for_each_rsdt_entry(*table, [&](uint32_t paddr_table) {
|
||||
addr_t const table_virt_addr = paddr_table;
|
||||
Hw::Acpi_generic * table = reinterpret_cast<Hw::Acpi_generic *>(table_virt_addr);
|
||||
/* scan ACPI tables to find out number of CPUs in this machine */
|
||||
if (acpi_rsdp.valid()) {
|
||||
uint64_t const table_addr = acpi_rsdp.xsdt ? acpi_rsdp.xsdt : acpi_rsdp.rsdt;
|
||||
|
||||
if (memcmp(table->signature, "APIC", 4))
|
||||
return;
|
||||
if (table_addr) {
|
||||
Hw::Acpi_generic * table = reinterpret_cast<Hw::Acpi_generic *>(table_addr);
|
||||
if (!memcmp(table->signature, "RSDT", 4)) {
|
||||
Hw::for_each_rsdt_entry(*table, [&](uint32_t paddr_table) {
|
||||
addr_t const table_virt_addr = paddr_table;
|
||||
Hw::Acpi_generic * table = reinterpret_cast<Hw::Acpi_generic *>(table_virt_addr);
|
||||
|
||||
Hw::for_each_apic_struct(*table,[&](Hw::Apic_madt const *e){
|
||||
if (e->type == Hw::Apic_madt::LAPIC) {
|
||||
Hw::Apic_madt::Lapic lapic(e);
|
||||
cpus ++;
|
||||
}
|
||||
});
|
||||
});
|
||||
} else if (!memcmp(table->signature, "XSDT", 4)) {
|
||||
Hw::for_each_xsdt_entry(*table, [&](uint64_t paddr_table) {
|
||||
addr_t const table_virt_addr = paddr_table;
|
||||
Hw::Acpi_generic * table = reinterpret_cast<Hw::Acpi_generic *>(table_virt_addr);
|
||||
if (memcmp(table->signature, "APIC", 4))
|
||||
return;
|
||||
|
||||
if (memcmp(table->signature, "APIC", 4))
|
||||
return;
|
||||
Hw::for_each_apic_struct(*table,[&](Hw::Apic_madt const *e){
|
||||
if (e->type == Hw::Apic_madt::LAPIC) {
|
||||
Hw::Apic_madt::Lapic lapic(e);
|
||||
cpus ++;
|
||||
}
|
||||
});
|
||||
});
|
||||
} else if (!memcmp(table->signature, "XSDT", 4)) {
|
||||
Hw::for_each_xsdt_entry(*table, [&](uint64_t paddr_table) {
|
||||
addr_t const table_virt_addr = paddr_table;
|
||||
Hw::Acpi_generic * table = reinterpret_cast<Hw::Acpi_generic *>(table_virt_addr);
|
||||
|
||||
Hw::for_each_apic_struct(*table,[&](Hw::Apic_madt const *e){
|
||||
if (e->type == Hw::Apic_madt::LAPIC) {
|
||||
Hw::Apic_madt::Lapic lapic(e);
|
||||
cpus ++;
|
||||
}
|
||||
});
|
||||
});
|
||||
} else
|
||||
Genode::error("unknown table signature");
|
||||
if (memcmp(table->signature, "APIC", 4))
|
||||
return;
|
||||
|
||||
Hw::for_each_apic_struct(*table,[&](Hw::Apic_madt const *e){
|
||||
if (e->type == Hw::Apic_madt::LAPIC) {
|
||||
Hw::Apic_madt::Lapic lapic(e);
|
||||
cpus ++;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!cpus || cpus > max_cpus) {
|
||||
Genode::warning("CPU count is unsupported ", cpus, "/", max_cpus);
|
||||
cpus = max_cpus;
|
||||
Genode::warning("CPU count is unsupported ", cpus, "/", max_cpus,
|
||||
acpi_rsdp.valid() ? " - invalid or missing RSDT/XSDT"
|
||||
: " - invalid RSDP");
|
||||
cpus = !cpus ? 1 : max_cpus;
|
||||
}
|
||||
|
||||
if (cpus > 1) {
|
||||
/* copy 16 bit boot code for AP CPUs */
|
||||
addr_t ap_code_size = (addr_t)&_start - (addr_t)&_ap;
|
||||
memcpy((void *)AP_BOOT_CODE_PAGE, &_ap, ap_code_size);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct Lapic : Mmio
|
||||
{
|
||||
struct Svr : Register<0x0f0, 32>
|
||||
{
|
||||
struct APIC_enable : Bitfield<8, 1> { };
|
||||
};
|
||||
struct Icr_low : Register<0x300, 32> {
|
||||
struct Vector : Bitfield< 0, 8> { };
|
||||
struct Delivery_mode : Bitfield< 8, 3> {
|
||||
enum Mode { INIT = 5, SIPI = 6 };
|
||||
};
|
||||
struct Delivery_status : Bitfield<12, 1> { };
|
||||
struct Level_assert : Bitfield<14, 1> { };
|
||||
struct Dest_shorthand : Bitfield<18, 2> {
|
||||
enum { ALL_OTHERS = 3 };
|
||||
};
|
||||
};
|
||||
struct Icr_high : Register<0x310, 32> {
|
||||
struct Destination : Bitfield<24, 8> { };
|
||||
};
|
||||
|
||||
Lapic(addr_t const addr) : Mmio(addr) { }
|
||||
};
|
||||
|
||||
static inline Genode::uint64_t rdtsc()
|
||||
{
|
||||
Genode::uint32_t lo, hi;
|
||||
asm volatile("rdtsc" : "=a" (lo), "=d" (hi));
|
||||
return (Genode::uint64_t)hi << 32 | lo;
|
||||
}
|
||||
|
||||
static inline void ipi_to_all(Lapic &lapic, unsigned const boot_frame,
|
||||
Lapic::Icr_low::Delivery_mode::Mode const mode)
|
||||
{
|
||||
/* wait until ready */
|
||||
while (lapic.read<Lapic::Icr_low::Delivery_status>())
|
||||
asm volatile ("pause":::"memory");
|
||||
|
||||
unsigned const apic_cpu_id = 0; /* unused for IPI to all */
|
||||
|
||||
Lapic::Icr_low::access_t icr_low = 0;
|
||||
|
||||
Lapic::Icr_low::Vector::set(icr_low, boot_frame);
|
||||
Lapic::Icr_low::Delivery_mode::set(icr_low, mode);
|
||||
Lapic::Icr_low::Level_assert::set(icr_low);
|
||||
Lapic::Icr_low::Level_assert::set(icr_low);
|
||||
Lapic::Icr_low::Dest_shorthand::set(icr_low, Lapic::Icr_low::Dest_shorthand::ALL_OTHERS);
|
||||
|
||||
/* program */
|
||||
lapic.write<Lapic::Icr_high::Destination>(apic_cpu_id);
|
||||
lapic.write<Lapic::Icr_low>(icr_low);
|
||||
}
|
||||
|
||||
unsigned Bootstrap::Platform::enable_mmu()
|
||||
{
|
||||
Cpu::Cr3::write(Cpu::Cr3::Pdb::masked((addr_t)core_pd->table_base));
|
||||
return 0;
|
||||
|
||||
addr_t const stack_base = reinterpret_cast<addr_t>(&__bootstrap_stack);
|
||||
addr_t const this_stack = reinterpret_cast<addr_t>(&stack_base);
|
||||
addr_t const cpu_id = (this_stack - stack_base) / bootstrap_stack_size;
|
||||
|
||||
/* we like to use local APIC */
|
||||
Cpu::IA32_apic_base::access_t lapic_msr = Cpu::IA32_apic_base::read();
|
||||
Cpu::IA32_apic_base::Lapic::set(lapic_msr);
|
||||
Cpu::IA32_apic_base::write(lapic_msr);
|
||||
|
||||
/* skip the SMP when ACPI parsing did not reveal the number of CPUs */
|
||||
if (board.cpus <= 1)
|
||||
return cpu_id;
|
||||
|
||||
Lapic lapic(board.core_mmio.virt_addr(Hw::Cpu_memory_map::lapic_phys_base()));
|
||||
|
||||
/* enable local APIC if required */
|
||||
if (!lapic.read<Lapic::Svr::APIC_enable>())
|
||||
lapic.write<Lapic::Svr::APIC_enable>(true);
|
||||
|
||||
if (!Cpu::IA32_apic_base::Bsp::get(lapic_msr))
|
||||
/* AP - done */
|
||||
return cpu_id;
|
||||
|
||||
/* BSP - we're primary CPU - wake now all other CPUs */
|
||||
|
||||
/* see Intel Multiprocessor documentation - we need to do INIT-SIPI-SIPI */
|
||||
ipi_to_all(lapic, 0 /* unused */, Lapic::Icr_low::Delivery_mode::INIT);
|
||||
/* wait 10 ms - debates ongoing whether this is still required */
|
||||
ipi_to_all(lapic, AP_BOOT_CODE_PAGE >> 12, Lapic::Icr_low::Delivery_mode::SIPI);
|
||||
/* wait 200 us - debates ongoing whether this is still required */
|
||||
/* debates ongoing whether the second SIPI is still required */
|
||||
ipi_to_all(lapic, AP_BOOT_CODE_PAGE >> 12, Lapic::Icr_low::Delivery_mode::SIPI);
|
||||
|
||||
return cpu_id;
|
||||
}
|
||||
|
||||
|
||||
|
@ -105,6 +105,10 @@ void Genode::Cpu::mmu_fault(Context & regs, Kernel::Thread_fault & fault)
|
||||
}
|
||||
|
||||
|
||||
extern void const * const kernel_stack;
|
||||
extern Genode::size_t const kernel_stack_size;
|
||||
|
||||
|
||||
void Genode::Cpu::switch_to(Context & context, Mmu_context &mmu_context)
|
||||
{
|
||||
_fpu.switch_to(context);
|
||||
@ -113,4 +117,19 @@ void Genode::Cpu::switch_to(Context & context, Mmu_context &mmu_context)
|
||||
Cr3::write(mmu_context.cr3);
|
||||
|
||||
tss.ist[0] = (addr_t)&context + sizeof(Genode::Cpu_state);
|
||||
|
||||
addr_t const stack_base = reinterpret_cast<addr_t>(&kernel_stack);
|
||||
context.kernel_stack = stack_base +
|
||||
(Cpu::executing_id() + 1) * kernel_stack_size -
|
||||
sizeof(addr_t);
|
||||
}
|
||||
|
||||
|
||||
unsigned Genode::Cpu::executing_id()
|
||||
{
|
||||
void * const stack_ptr = nullptr;
|
||||
addr_t const stack_addr = reinterpret_cast<addr_t>(&stack_ptr);
|
||||
addr_t const stack_base = reinterpret_cast<addr_t>(&kernel_stack);
|
||||
unsigned const cpu_id = (stack_addr - stack_base) / kernel_stack_size;
|
||||
return cpu_id;
|
||||
}
|
||||
|
@ -92,7 +92,10 @@ class Genode::Cpu : public Hw::X86_64_cpu
|
||||
/**
|
||||
* Extend basic CPU state by members relevant for 'base-hw' only
|
||||
*/
|
||||
struct alignas(16) Context : Cpu_state, Fpu::Context
|
||||
struct Kernel_stack { unsigned long kernel_stack { }; };
|
||||
|
||||
/* exception_vector.s depends on the position of the Kernel_stack */
|
||||
struct alignas(16) Context : Cpu_state, Kernel_stack, Fpu::Context
|
||||
{
|
||||
enum Eflags {
|
||||
EFLAGS_IF_SET = 1 << 9,
|
||||
@ -100,7 +103,7 @@ class Genode::Cpu : public Hw::X86_64_cpu
|
||||
};
|
||||
|
||||
Context(bool privileged);
|
||||
};
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
struct Mmu_context
|
||||
@ -121,7 +124,7 @@ class Genode::Cpu : public Hw::X86_64_cpu
|
||||
/**
|
||||
* Return kernel name of the executing CPU
|
||||
*/
|
||||
static unsigned executing_id() { return 0; }
|
||||
static unsigned executing_id();
|
||||
|
||||
/**
|
||||
* Return kernel name of the primary CPU
|
||||
|
@ -2,11 +2,12 @@
|
||||
* \brief Startup code for Genode 64Bit applications
|
||||
* \author Sebastian Sumpf
|
||||
* \author Martin Stein
|
||||
* \author Alexander Boettcher
|
||||
* \date 2011-05-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2011-2018 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -21,11 +22,20 @@
|
||||
.global _start
|
||||
_start:
|
||||
|
||||
/* load kernel stack size */
|
||||
movq kernel_stack_size@GOTPCREL(%rip), %rbx
|
||||
movq (%rbx), %rax
|
||||
|
||||
/* calculate stack top (rdi contains cpu_id), stack top is stored in rax */
|
||||
movq %rdi, %rbx
|
||||
inc %rbx
|
||||
mulq %rbx
|
||||
|
||||
/* switch to kernel stack */
|
||||
mov kernel_stack@GOTPCREL(%rip), %rax
|
||||
mov kernel_stack_size@GOTPCREL(%rip), %rbx
|
||||
add (%rbx), %rax
|
||||
mov %rax, %rsp
|
||||
movq kernel_stack@GOTPCREL(%rip), %rbx
|
||||
addq %rbx, %rax
|
||||
subq $8, %rax
|
||||
movq %rax, %rsp
|
||||
|
||||
/* jump to C entry code */
|
||||
jmp kernel_init
|
||||
|
@ -111,12 +111,22 @@
|
||||
pushq %r9
|
||||
pushq %r8
|
||||
|
||||
/**
|
||||
* Calculate offset into Kernel_stack member of Cpu::Context as defined
|
||||
* in cpu.h - struct Context : Cpu_state, Kernel_stack, Fpu_context
|
||||
*/
|
||||
.set REGISTER_COUNT, 22
|
||||
.set REGISTER_SIZE, 8
|
||||
.set SIZEOF_CPU_STATE, REGISTER_COUNT * REGISTER_SIZE /* sizeof (Cpu_state) */
|
||||
.set KERNEL_STACK_OFFSET, SIZEOF_CPU_STATE
|
||||
/* rsp contains pointer to Cpu::Context */
|
||||
|
||||
/* Restore kernel stack and continue kernel execution */
|
||||
_load_address kernel_stack rax
|
||||
_load_address kernel_stack_size rbx
|
||||
movq %rsp, %rax
|
||||
addq $KERNEL_STACK_OFFSET, %rax
|
||||
movq (%rax), %rsp
|
||||
|
||||
_load_address kernel rcx
|
||||
add (%rbx), %rax
|
||||
mov %rax, %rsp
|
||||
jmp *%rcx
|
||||
|
||||
|
||||
@ -159,5 +169,7 @@
|
||||
|
||||
.global idle_thread_main
|
||||
idle_thread_main:
|
||||
pause
|
||||
sti
|
||||
hlt
|
||||
cli
|
||||
jmp idle_thread_main
|
||||
|
@ -30,6 +30,7 @@ void Kernel::Cpu::init(Pic &pic)
|
||||
|
||||
/* enable timer interrupt */
|
||||
unsigned const cpu = Cpu::executing_id();
|
||||
pic.store_apic_id(cpu);
|
||||
pic.unmask(_timer.interrupt_id(), cpu);
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,7 @@ class Genode::Pic
|
||||
void mask(unsigned const) { }
|
||||
bool is_ip_interrupt(unsigned, unsigned) { return false; }
|
||||
void trigger_ip_interrupt(unsigned) { }
|
||||
void store_apic_id(unsigned const) { }
|
||||
|
||||
private:
|
||||
|
||||
|
@ -2,11 +2,12 @@
|
||||
* \brief Programmable interrupt controller for core
|
||||
* \author Adrian-Ken Rueegsegger
|
||||
* \author Reto Buerki
|
||||
* \author Alexander Boettcher
|
||||
* \date 2015-02-17
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2015-2018 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -23,6 +24,8 @@
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
uint8_t Pic::lapic_ids[NR_OF_CPUS];
|
||||
|
||||
enum {
|
||||
PIC_CMD_MASTER = 0x20,
|
||||
PIC_CMD_SLAVE = 0xa0,
|
||||
@ -99,6 +102,25 @@ inline unsigned Pic::get_lowest_bit(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Pic::send_ipi(unsigned const cpu_id) {
|
||||
|
||||
while (read<Icr_low::Delivery_status>())
|
||||
asm volatile("pause" : : : "memory");
|
||||
|
||||
Icr_high::access_t icr_high = 0;
|
||||
Icr_low::access_t icr_low = 0;
|
||||
|
||||
Icr_high::Destination::set(icr_high, lapic_ids[cpu_id]);
|
||||
|
||||
Icr_low::Vector::set(icr_low, Pic::IPI);
|
||||
Icr_low::Level_assert::set(icr_low);
|
||||
|
||||
/* program */
|
||||
write<Icr_high>(icr_high);
|
||||
write<Icr_low>(icr_low);
|
||||
|
||||
}
|
||||
|
||||
Ioapic::Irq_mode Ioapic::_irq_mode[IRQ_COUNT];
|
||||
|
||||
void Ioapic::setup_irq_mode(unsigned irq_number, unsigned trigger,
|
||||
|
@ -1,11 +1,12 @@
|
||||
/*
|
||||
* \brief Programmable interrupt controller for core
|
||||
* \author Reto Buerki
|
||||
* \author Alexander Boettcher
|
||||
* \date 2015-02-17
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2015-2018 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -142,6 +143,7 @@ class Genode::Pic : public Mmio
|
||||
* Registers
|
||||
*/
|
||||
|
||||
struct Id : Register<0x020, 32> { };
|
||||
struct EOI : Register<0x0b0, 32, true> { };
|
||||
struct Svr : Register<0x0f0, 32>
|
||||
{
|
||||
@ -155,6 +157,18 @@ class Genode::Pic : public Mmio
|
||||
*/
|
||||
struct Isr : Register_array<0x100, 32, 8 * 4, 32> { };
|
||||
|
||||
/*
|
||||
* Interrupt control register
|
||||
*/
|
||||
struct Icr_low : Register<0x300, 32, true> {
|
||||
struct Vector : Bitfield< 0, 8> { };
|
||||
struct Delivery_status : Bitfield<12, 1> { };
|
||||
struct Level_assert : Bitfield<14, 1> { };
|
||||
};
|
||||
struct Icr_high : Register<0x310, 32, true> {
|
||||
struct Destination : Bitfield<24, 8> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine lowest pending interrupt in ISR register
|
||||
*
|
||||
@ -163,6 +177,11 @@ class Genode::Pic : public Mmio
|
||||
*/
|
||||
inline unsigned get_lowest_bit(void);
|
||||
|
||||
/**
|
||||
* Mapping of our logical boot CPUs to the local APIC IDs
|
||||
*/
|
||||
static uint8_t lapic_ids[NR_OF_CPUS];
|
||||
|
||||
public:
|
||||
|
||||
enum {
|
||||
@ -190,12 +209,12 @@ class Genode::Pic : public Mmio
|
||||
|
||||
void mask(unsigned const i);
|
||||
|
||||
/*
|
||||
* Dummies
|
||||
*/
|
||||
void store_apic_id(unsigned const cpu_id) {
|
||||
Id::access_t const lapic_id = read<Id>();
|
||||
lapic_ids[cpu_id] = (lapic_id >> 24) & 0xff;
|
||||
}
|
||||
|
||||
bool is_ip_interrupt(unsigned, unsigned) { return false; }
|
||||
void trigger_ip_interrupt(unsigned) { }
|
||||
void send_ipi(unsigned const);
|
||||
};
|
||||
|
||||
namespace Kernel { using Genode::Pic; }
|
||||
|
25
repos/base-hw/src/core/spec/x86_64/smp/cpu.cc
Normal file
25
repos/base-hw/src/core/spec/x86_64/smp/cpu.cc
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* \brief Cpu class implementation specific to SMP
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2015-12-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/lock.h>
|
||||
#include <kernel/kernel.h>
|
||||
#include <kernel/cpu.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/unmanaged_singleton.h>
|
||||
|
||||
|
||||
/* spin-lock used to synchronize kernel access of different cpus */
|
||||
Kernel::Lock & Kernel::data_lock() {
|
||||
return *unmanaged_singleton<Kernel::Lock>(); }
|
@ -11,6 +11,7 @@ if {
|
||||
![expr [have_spec zynq] && ![have_spec zynq_qemu] ] &&
|
||||
![expr [have_spec x86_32] && [have_spec foc] ] &&
|
||||
![expr [have_spec x86_64] && [have_spec foc] ] &&
|
||||
![expr [have_spec x86_64] && [have_spec hw] ] &&
|
||||
![have_spec nova] &&
|
||||
![have_spec sel4]
|
||||
} {
|
||||
|
@ -40,7 +40,6 @@ if {[have_include "power_on/qemu"]} {
|
||||
if {[have_spec okl4]} { set want_cpus 1 }
|
||||
if {[have_spec pistachio]} { set want_cpus 1 }
|
||||
if {[have_spec fiasco]} { set want_cpus 1 }
|
||||
if {([have_spec x86_64] && [have_spec hw])} { set want_cpus 1 }
|
||||
if {[have_spec zynq]} { set want_cpus 1 }
|
||||
|
||||
append qemu_args " -nographic -smp $want_cpus,cores=$want_cpus "
|
||||
|
Loading…
Reference in New Issue
Block a user