/tags/0.2.0.1/kernel/arch/amd64/src/boot/boot.S |
---|
0,0 → 1,515 |
# |
# Copyright (C) 2005 Ondrej Palkovsky |
# Copyright (C) 2006 Martin Decky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - 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. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <arch/boot/boot.h> |
#include <arch/boot/memmap.h> |
#include <arch/mm/page.h> |
#include <arch/mm/ptl.h> |
#include <arch/pm.h> |
#include <arch/cpu.h> |
#include <arch/cpuid.h> |
#define START_STACK (BOOT_OFFSET - BOOT_STACK_SIZE) |
.section K_TEXT_START, "ax" |
.code32 |
.align 4 |
.global multiboot_image_start |
multiboot_header: |
.long MULTIBOOT_HEADER_MAGIC |
.long MULTIBOOT_HEADER_FLAGS |
.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) # checksum |
.long multiboot_header |
.long unmapped_ktext_start |
.long 0 |
.long 0 |
.long multiboot_image_start |
multiboot_image_start: |
movl $START_STACK, %esp # initialize stack pointer |
lgdt bootstrap_gdtr # initialize Global Descriptor Table register |
movw $gdtselector(KDATA_DES), %cx |
movw %cx, %es |
movw %cx, %ds # kernel data + stack |
movw %cx, %ss |
# Simics seems to remove hidden part of GS on entering user mode |
# when _visible_ part of GS does not point to user-mode segment |
movw $gdtselector(UDATA_DES), %cx |
movw %cx, %fs |
movw %cx, %gs |
jmpl $gdtselector(KTEXT32_DES), $multiboot_meeting_point |
multiboot_meeting_point: |
movl %eax, grub_eax # save parameters from GRUB |
movl %ebx, grub_ebx |
#ifdef CONFIG_FB |
mov $vesa_init, %esi; |
mov $VESA_INIT_SEGMENT << 4, %edi |
mov $e_vesa_init - vesa_init, %ecx |
cld |
rep movsb |
mov $VESA_INIT_SEGMENT << 4, %edi |
jmpl *%edi |
vesa_meeting_point: |
mov %esi, KA2PA(vesa_ph_addr) |
mov %di, KA2PA(vesa_height) |
shr $16, %edi |
mov %di, KA2PA(vesa_width) |
mov %bx, KA2PA(vesa_scanline) |
shr $16, %ebx |
mov %bx, KA2PA(vesa_bpp) |
#endif |
# Protected 32-bit. We want to reuse the code-seg descriptor, |
# the Default operand size must not be 1 when entering long mode |
movl $0x80000000, %eax |
cpuid |
cmp $0x80000000, %eax # any function > 80000000h? |
jbe long_mode_unsupported |
movl $(AMD_CPUID_EXTENDED), %eax # Extended function code 80000001 |
cpuid |
bt $29, %edx # Test if long mode is supported. |
jc long_mode_supported |
long_mode_unsupported: |
cli |
hlt |
long_mode_supported: |
# Enable 64-bit page transaltion entries - CR4.PAE = 1. |
# Paging is not enabled until after long mode is enabled |
movl %cr4, %eax |
btsl $5, %eax |
movl %eax, %cr4 |
# Set up paging tables |
leal ptl_0, %eax |
movl %eax, %cr3 |
# Enable long mode |
movl $EFER_MSR_NUM, %ecx # EFER MSR number |
rdmsr # Read EFER |
btsl $AMD_LME_FLAG, %eax # Set LME=1 |
wrmsr # Write EFER |
# Enable paging to activate long mode (set CR0.PG=1) |
movl %cr0, %eax |
btsl $31, %eax |
movl %eax, %cr0 |
# At this point we are in compatibility mode |
jmpl $gdtselector(KTEXT_DES), $start64 |
.code64 |
start64: |
movq $(PA2KA(START_STACK)), %rsp |
movl grub_eax, %eax |
movl grub_ebx, %ebx |
cmpl $MULTIBOOT_LOADER_MAGIC, %eax # compare GRUB signature |
je valid_boot |
xorl %ecx, %ecx # no memory size or map available |
movl %ecx, e801memorysize |
movl %ecx, e820counter |
jmp invalid_boot |
valid_boot: |
movl (%ebx), %eax # ebx = physical address of struct multiboot_info |
bt $0, %eax # mbi->flags[0] (mem_lower, mem_upper valid) |
jc mem_valid |
xorl %ecx, %ecx |
jmp mem_invalid |
mem_valid: |
movl 4(%ebx), %ecx # mbi->mem_lower |
addl 8(%ebx), %ecx # mbi->mem_upper |
mem_invalid: |
movl %ecx, e801memorysize |
bt $3, %eax # mbi->flags[3] (mods_count, mods_addr valid) |
jc mods_valid |
xorq %rcx, %rcx |
movq %rcx, init |
jmp mods_end |
mods_valid: |
xorq %rcx, %rcx |
movl 20(%ebx), %ecx # mbi->mods_count |
movq %rcx, init |
cmpl $0, %ecx |
je mods_end |
movl 24(%ebx), %esi # mbi->mods_addr |
movq $init, %rdi |
mods_loop: |
xorq %rdx, %rdx |
movl 0(%esi), %edx # mods->mod_start |
movq $0xffff800000000000, %r10 |
addq %r10, %rdx |
movq %rdx, 8(%rdi) |
xorq %rdx, %rdx |
movl 4(%esi), %edx |
subl 0(%esi), %edx # mods->mod_end - mods->mod_start |
movq %rdx, 16(%rdi) |
addl $16, %esi |
addq $16, %rdi |
loop mods_loop |
mods_end: |
bt $6, %eax # mbi->flags[6] (mmap_length, mmap_addr valid) |
jc mmap_valid |
xorl %edx, %edx |
jmp mmap_invalid |
mmap_valid: |
movl 44(%ebx), %ecx # mbi->mmap_length |
movl 48(%ebx), %esi # mbi->mmap_addr |
movq $e820table, %rdi |
xorl %edx, %edx |
mmap_loop: |
cmpl $0, %ecx |
jle mmap_end |
movl 4(%esi), %eax # mmap->base_addr_low |
movl %eax, (%rdi) |
movl 8(%esi), %eax # mmap->base_addr_high |
movl %eax, 4(%rdi) |
movl 12(%esi), %eax # mmap->length_low |
movl %eax, 8(%rdi) |
movl 16(%esi), %eax # mmap->length_high |
movl %eax, 12(%rdi) |
movl 20(%esi), %eax # mmap->type |
movl %eax, 16(%rdi) |
movl (%esi), %eax # mmap->size |
addl $0x4, %eax |
addl %eax, %esi |
subl %eax, %ecx |
addq $MEMMAP_E820_RECORD_SIZE, %rdi |
incl %edx |
jmp mmap_loop |
mmap_end: |
mmap_invalid: |
movl %edx, e820counter |
invalid_boot: |
#ifdef CONFIG_SMP |
# copy AP bootstrap routines below 1 MB |
movq $BOOT_OFFSET, %rsi |
movq $AP_BOOT_OFFSET, %rdi |
movq $_hardcoded_unmapped_size, %rcx |
cld |
rep movsb |
#endif |
call main_bsp # never returns |
cli |
hlt |
#ifdef CONFIG_FB |
.code32 |
vesa_init: |
jmp $gdtselector(VESA_INIT_DES), $vesa_init_real - vesa_init |
.code16 |
vesa_init_real: |
mov %cr0, %eax |
and $~1, %eax |
mov %eax, %cr0 |
jmp $VESA_INIT_SEGMENT, $vesa_init_real2 - vesa_init |
vesa_init_real2: |
mov $VESA_INIT_SEGMENT, %bx |
mov %bx, %es |
mov %bx, %fs |
mov %bx, %gs |
mov %bx, %ds |
mov %bx, %ss |
movl $0x0000fffc, %esp |
movl $0x0000fffc, %ebp |
#define VESA_INFO_SIZE 1024 |
#define VESA_MODE_LIST_PTR_OFFSET 14 |
#define VESA_MODE_WIDTH_OFFSET 18 |
#define VESA_MODE_HEIGHT_OFFSET 20 |
#define VESA_MODE_BPP_OFFSET 25 |
#define VESA_MODE_SCANLINE_OFFSET 16 |
#define VESA_MODE_PHADDR_OFFSET 40 |
#define VESA_END_OF_MODES 0xffff |
#define VESA_OK 0x4f |
#define VESA_GET_INFO 0x4f00 |
#define VESA_GET_MODE_INFO 0x4f01 |
#define VESA_SET_MODE 0x4f02 |
#define CONFIG_VESA_BPP_a 255 |
#if CONFIG_VESA_BPP == 24 |
#undef CONFIG_VESA_BPP_a |
#define CONFIG_VESA_BPP_a 32 |
#endif |
mov $VESA_GET_INFO, %ax |
mov $e_vesa_init - vesa_init, %di |
push %di |
int $0x10 |
pop %di |
cmp $VESA_OK, %al |
jnz 0f |
mov 2 + VESA_MODE_LIST_PTR_OFFSET(%di), %si |
mov %si, %gs |
mov VESA_MODE_LIST_PTR_OFFSET(%di), %si |
add $VESA_INFO_SIZE, %di |
1:# Try next mode |
mov %gs:(%si), %cx |
cmp $VESA_END_OF_MODES, %cx |
jz 0f |
inc %si |
inc %si |
push %cx |
push %di |
push %si |
mov $VESA_GET_MODE_INFO, %ax |
int $0x10 |
pop %si |
pop %di |
pop %cx |
cmp $VESA_OK, %al |
jnz 0f |
mov $CONFIG_VESA_WIDTH, %ax |
cmp VESA_MODE_WIDTH_OFFSET(%di), %ax |
jnz 1b |
mov $CONFIG_VESA_HEIGHT, %ax |
cmp VESA_MODE_HEIGHT_OFFSET(%di), %ax |
jnz 1b |
mov $CONFIG_VESA_BPP, %al |
cmp VESA_MODE_BPP_OFFSET(%di), %al |
jz 2f |
mov $CONFIG_VESA_BPP_a, %al |
cmp VESA_MODE_BPP_OFFSET(%di), %al |
jnz 1b |
2: |
mov %cx, %bx |
or $0xc000, %bx |
push %di |
mov $VESA_SET_MODE, %ax |
int $0x10 |
pop %di |
cmp $VESA_OK, %al |
jnz 0f |
mov VESA_MODE_PHADDR_OFFSET(%di), %esi |
mov VESA_MODE_WIDTH_OFFSET(%di), %ax |
shl $16, %eax |
mov VESA_MODE_HEIGHT_OFFSET(%di), %ax |
mov VESA_MODE_BPP_OFFSET(%di), %bl |
xor %bh, %bh |
shl $16, %ebx |
mov VESA_MODE_SCANLINE_OFFSET(%di), %bx |
mov %eax, %edi |
8: |
mov %cr0, %eax |
or $1, %eax |
mov %eax, %cr0 |
jmp 9f |
9: |
ljmpl $gdtselector(KTEXT32_DES), $(vesa_init_protect - vesa_init + VESA_INIT_SEGMENT << 4) |
0:# No prefered mode found |
mov $0x111, %cx |
push %di |
push %cx |
mov $VESA_GET_MODE_INFO, %ax |
int $0x10 |
pop %cx |
pop %di |
cmp $VESA_OK, %al |
jnz 1f |
jz 2b # Force relative jump |
1: |
mov $0x0003, %ax |
int $0x10 |
mov $0xffffffff, %edi # EGA text mode used, because of problems with VESA |
xor %ax, %ax |
jz 8b # Force relative jump |
.code32 |
vesa_init_protect: |
movw $gdtselector(KDATA_DES), %cx |
movw %cx, %es |
movw %cx, %ds # kernel data + stack |
movw %cx, %ss |
# Simics seems to remove hidden part of GS on entering user mode |
# when _visible_ part of GS does not point to user-mode segment |
movw $gdtselector(UDATA_DES), %cx |
movw %cx, %fs |
movw %cx, %gs |
jmpl $gdtselector(KTEXT32_DES), $vesa_meeting_point |
.align 4 |
e_vesa_init: |
#endif |
.section K_DATA_START, "aw", @progbits |
.align 4096 |
# Identical mapping of first 64MB and the same of -2GB -> 0 |
.global ptl_2 |
ptl_2: |
.quad 0x0 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x200000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x400000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x600000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x800000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0xa00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0xc00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0xe00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x1000000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x1200000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x1400000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x1600000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x1800000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x1a00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x1c00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x1e00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x2000000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x2200000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x2400000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x2600000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x2800000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x2a00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x2c00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x2e00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x3000000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x3200000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x3400000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x3600000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x3800000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x3a00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x3c00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.quad 0x3e00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE) |
.align 4096 |
.global ptl_1 |
ptl_1: |
.quad ptl_2 + (PTL_WRITABLE | PTL_PRESENT) |
.fill 509,8,0 |
.quad ptl_2 + (PTL_WRITABLE | PTL_PRESENT) |
.fill 1,8,0 |
.align 4096 |
.global ptl_0 |
ptl_0: |
.quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT) |
.fill 255,8,0 |
.quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT) |
.fill 254,8,0 |
.quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT) |
.global bootstrap_gdtr |
bootstrap_gdtr: |
.word gdtselector(GDT_ITEMS) |
.long KA2PA(gdt) |
grub_eax: |
.long 0 |
grub_ebx: |
.long 0 |
/tags/0.2.0.1/kernel/arch/amd64/src/mm/page.c |
---|
0,0 → 1,208 |
/* |
* Copyright (C) 2001-2004 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - 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. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <arch/mm/page.h> |
#include <genarch/mm/page_pt.h> |
#include <arch/mm/frame.h> |
#include <mm/page.h> |
#include <mm/frame.h> |
#include <mm/as.h> |
#include <arch/interrupt.h> |
#include <arch/asm.h> |
#include <config.h> |
#include <memstr.h> |
#include <interrupt.h> |
#include <print.h> |
#include <panic.h> |
#include <align.h> |
/* Definitions for identity page mapper */ |
pte_t helper_ptl1[512] __attribute__((aligned (PAGE_SIZE))); |
pte_t helper_ptl2[512] __attribute__((aligned (PAGE_SIZE))); |
pte_t helper_ptl3[512] __attribute__((aligned (PAGE_SIZE))); |
extern pte_t ptl_0; /* From boot.S */ |
#define PTL1_PRESENT(ptl0, page) (!(GET_PTL1_FLAGS_ARCH(ptl0, PTL0_INDEX_ARCH(page)) & PAGE_NOT_PRESENT)) |
#define PTL2_PRESENT(ptl1, page) (!(GET_PTL2_FLAGS_ARCH(ptl1, PTL1_INDEX_ARCH(page)) & PAGE_NOT_PRESENT)) |
#define PTL3_PRESENT(ptl2, page) (!(GET_PTL3_FLAGS_ARCH(ptl2, PTL2_INDEX_ARCH(page)) & PAGE_NOT_PRESENT)) |
#define PTL1_ADDR(ptl0, page) ((pte_t *)PA2KA(GET_PTL1_ADDRESS_ARCH(ptl0, PTL0_INDEX_ARCH(page)))) |
#define PTL2_ADDR(ptl1, page) ((pte_t *)PA2KA(GET_PTL2_ADDRESS_ARCH(ptl1, PTL1_INDEX_ARCH(page)))) |
#define PTL3_ADDR(ptl2, page) ((pte_t *)PA2KA(GET_PTL3_ADDRESS_ARCH(ptl2, PTL2_INDEX_ARCH(page)))) |
#define SETUP_PTL1(ptl0, page, tgt) { \ |
SET_PTL1_ADDRESS_ARCH(ptl0, PTL0_INDEX_ARCH(page), (__address)KA2PA(tgt)); \ |
SET_PTL1_FLAGS_ARCH(ptl0, PTL0_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \ |
} |
#define SETUP_PTL2(ptl1, page, tgt) { \ |
SET_PTL2_ADDRESS_ARCH(ptl1, PTL1_INDEX_ARCH(page), (__address)KA2PA(tgt)); \ |
SET_PTL2_FLAGS_ARCH(ptl1, PTL1_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \ |
} |
#define SETUP_PTL3(ptl2, page, tgt) { \ |
SET_PTL3_ADDRESS_ARCH(ptl2, PTL2_INDEX_ARCH(page), (__address)KA2PA(tgt)); \ |
SET_PTL3_FLAGS_ARCH(ptl2, PTL2_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \ |
} |
#define SETUP_FRAME(ptl3, page, tgt) { \ |
SET_FRAME_ADDRESS_ARCH(ptl3, PTL3_INDEX_ARCH(page), (__address)KA2PA(tgt)); \ |
SET_FRAME_FLAGS_ARCH(ptl3, PTL3_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \ |
} |
void page_arch_init(void) |
{ |
__address cur; |
int i; |
int identity_flags = PAGE_CACHEABLE | PAGE_EXEC | PAGE_GLOBAL; |
if (config.cpu_active == 1) { |
page_mapping_operations = &pt_mapping_operations; |
/* |
* PA2KA(identity) mapping for all frames. |
*/ |
for (cur = 0; cur < last_frame; cur += FRAME_SIZE) { |
/* Standard identity mapping */ |
page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, identity_flags); |
} |
/* Upper kernel mapping |
* - from zero to top of kernel (include bottom addresses |
* because some are needed for init ) |
*/ |
for (cur = PA2KA_CODE(0); cur < config.base+config.kernel_size; cur += FRAME_SIZE) { |
page_mapping_insert(AS_KERNEL, cur, KA2PA(cur), identity_flags); |
} |
for (i=0; i < init.cnt; i++) { |
for (cur=init.tasks[i].addr;cur < init.tasks[i].size; cur += FRAME_SIZE) { |
page_mapping_insert(AS_KERNEL, PA2KA_CODE(KA2PA(cur)), KA2PA(cur), identity_flags); |
} |
} |
exc_register(14, "page_fault", (iroutine)page_fault); |
write_cr3((__address) AS_KERNEL->page_table); |
} |
else { |
write_cr3((__address) AS_KERNEL->page_table); |
} |
} |
/** Identity page mapper |
* |
* We need to map whole physical memory identically before the page subsystem |
* is initializaed. This thing clears page table and fills in the specific |
* items. |
*/ |
void ident_page_fault(int n, istate_t *istate) |
{ |
__address page; |
static __address oldpage = 0; |
pte_t *aptl_1, *aptl_2, *aptl_3; |
page = read_cr2(); |
if (oldpage) { |
/* Unmap old address */ |
aptl_1 = PTL1_ADDR(&ptl_0, oldpage); |
aptl_2 = PTL2_ADDR(aptl_1, oldpage); |
aptl_3 = PTL3_ADDR(aptl_2, oldpage); |
SET_FRAME_FLAGS_ARCH(aptl_3, PTL3_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT); |
if (KA2PA(aptl_3) == KA2PA(helper_ptl3)) |
SET_PTL3_FLAGS_ARCH(aptl_2, PTL2_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT); |
if (KA2PA(aptl_2) == KA2PA(helper_ptl2)) |
SET_PTL2_FLAGS_ARCH(aptl_1, PTL1_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT); |
if (KA2PA(aptl_1) == KA2PA(helper_ptl1)) |
SET_PTL1_FLAGS_ARCH(&ptl_0, PTL0_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT); |
} |
if (PTL1_PRESENT(&ptl_0, page)) |
aptl_1 = PTL1_ADDR(&ptl_0, page); |
else { |
SETUP_PTL1(&ptl_0, page, helper_ptl1); |
aptl_1 = helper_ptl1; |
} |
if (PTL2_PRESENT(aptl_1, page)) |
aptl_2 = PTL2_ADDR(aptl_1, page); |
else { |
SETUP_PTL2(aptl_1, page, helper_ptl2); |
aptl_2 = helper_ptl2; |
} |
if (PTL3_PRESENT(aptl_2, page)) |
aptl_3 = PTL3_ADDR(aptl_2, page); |
else { |
SETUP_PTL3(aptl_2, page, helper_ptl3); |
aptl_3 = helper_ptl3; |
} |
SETUP_FRAME(aptl_3, page, page); |
oldpage = page; |
} |
void page_fault(int n, istate_t *istate) |
{ |
__address page; |
pf_access_t access; |
page = read_cr2(); |
if (istate->error_word & PFERR_CODE_RSVD) |
panic("Reserved bit set in page table entry.\n"); |
if (istate->error_word & PFERR_CODE_RW) |
access = PF_ACCESS_WRITE; |
else if (istate->error_word & PFERR_CODE_ID) |
access = PF_ACCESS_EXEC; |
else |
access = PF_ACCESS_READ; |
if (as_page_fault(page, access, istate) == AS_PF_FAULT) { |
fault_if_from_uspace(istate, "Page fault: %#x", page); |
print_info_errcode(n, istate); |
printf("Page fault address: %llX\n", page); |
panic("page fault\n"); |
} |
} |
__address hw_map(__address physaddr, size_t size) |
{ |
if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH)) |
panic("Unable to map physical memory %p (%d bytes)", physaddr, size) |
__address virtaddr = PA2KA(last_frame); |
pfn_t i; |
for (i = 0; i < ADDR2PFN(ALIGN_UP(size, PAGE_SIZE)); i++) |
page_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i), physaddr + PFN2ADDR(i), PAGE_NOT_CACHEABLE); |
last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE); |
return virtaddr; |
} |
/tags/0.2.0.1/kernel/arch/amd64/src/mm/memory_init.c |
---|
0,0 → 1,71 |
/* |
* Copyright (C) 2005 Josef Cejka |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - 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. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <arch/boot/memmap.h> |
#include <arch/mm/memory_init.h> |
#include <arch/mm/page.h> |
#include <print.h> |
__u8 e820counter = 0xff; |
struct e820memmap_ e820table[MEMMAP_E820_MAX_RECORDS]; |
__u32 e801memorysize; |
size_t get_memory_size(void) |
{ |
return e801memorysize*1024; |
} |
void memory_print_map(void) |
{ |
__u8 i; |
for (i=0;i<e820counter;i++) { |
printf("E820 base: %#llX size: %#llX type: ", e820table[i].base_address, e820table[i].size); |
switch (e820table[i].type) { |
case MEMMAP_MEMORY_AVAILABLE: |
printf("available memory\n"); |
break; |
case MEMMAP_MEMORY_RESERVED: |
printf("reserved memory\n"); |
break; |
case MEMMAP_MEMORY_ACPI: |
printf("ACPI table\n"); |
break; |
case MEMMAP_MEMORY_NVS: |
printf("NVS\n"); |
break; |
case MEMMAP_MEMORY_UNUSABLE: |
printf("unusable memory\n"); |
break; |
default: |
printf("undefined memory type\n"); |
} |
} |
} |
/tags/0.2.0.1/kernel/arch/amd64/src/mm/as.c |
---|
0,0 → 1,0 |
link ../../../ia32/src/mm/as.c |
Property changes: |
Added: svn:special |
+* |
\ No newline at end of property |
/tags/0.2.0.1/kernel/arch/amd64/src/mm/tlb.c |
---|
0,0 → 1,0 |
link ../../../ia32/src/mm/tlb.c |
Property changes: |
Added: svn:special |
+* |
\ No newline at end of property |
/tags/0.2.0.1/kernel/arch/amd64/src/mm/frame.c |
---|
0,0 → 1,0 |
link ../../../ia32/src/mm/frame.c |
Property changes: |
Added: svn:special |
+* |
\ No newline at end of property |
/tags/0.2.0.1/kernel/arch/amd64/src/interrupt.c |
---|
0,0 → 1,176 |
/* |
* Copyright (C) 2001-2004 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - 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. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <arch/interrupt.h> |
#include <print.h> |
#include <debug.h> |
#include <panic.h> |
#include <arch/drivers/i8259.h> |
#include <func.h> |
#include <cpu.h> |
#include <arch/asm.h> |
#include <mm/tlb.h> |
#include <mm/as.h> |
#include <arch.h> |
#include <symtab.h> |
#include <arch/asm.h> |
#include <proc/scheduler.h> |
#include <proc/thread.h> |
#include <proc/task.h> |
#include <synch/spinlock.h> |
#include <arch/ddi/ddi.h> |
#include <interrupt.h> |
#include <ipc/irq.h> |
void print_info_errcode(int n, istate_t *istate) |
{ |
char *symbol; |
/* __u64 *x = &istate->stack[0]; */ |
if (!(symbol=get_symtab_entry(istate->rip))) |
symbol = ""; |
printf("-----EXCEPTION(%d) OCCURED----- ( %s )\n",n, __FUNCTION__); |
printf("%%rip: %#llX (%s)\n",istate->rip, symbol); |
printf("ERROR_WORD=%#llX\n", istate->error_word); |
printf("%%rcs=%#llX, flags=%#llX, %%cr0=%#llX\n", istate->cs, istate->rflags,read_cr0()); |
printf("%%rax=%#llX, %%rcx=%#llX, %%rdx=%#llX\n",istate->rax,istate->rcx,istate->rdx); |
printf("%%rsi=%#llX, %%rdi=%#llX, %%r8 =%#llX\n",istate->rsi,istate->rdi,istate->r8); |
printf("%%r9 =%#llX, %%r10 =%#llX, %%r11=%#llX\n",istate->r9,istate->r10,istate->r11); |
#ifdef CONFIG_DEBUG_ALLREGS |
printf("%%r12=%#llX, %%r13=%#llX, %%r14=%#llX\n",istate->r12,istate->r13,istate->r14); |
printf("%%r15=%#llX, %%rbx=%#llX, %%rbp=%#llX\n",istate->r15,istate->rbx,&istate->rbp); |
#endif |
printf("%%rsp=%#llX\n",&istate->stack[0]); |
} |
/* |
* Interrupt and exception dispatching. |
*/ |
void (* disable_irqs_function)(__u16 irqmask) = NULL; |
void (* enable_irqs_function)(__u16 irqmask) = NULL; |
void (* eoi_function)(void) = NULL; |
void null_interrupt(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "unserviced interrupt: %d", n); |
print_info_errcode(n, istate); |
panic("unserviced interrupt\n"); |
} |
/** General Protection Fault. */ |
void gp_fault(int n, istate_t *istate) |
{ |
if (TASK) { |
count_t ver; |
spinlock_lock(&TASK->lock); |
ver = TASK->arch.iomapver; |
spinlock_unlock(&TASK->lock); |
if (CPU->arch.iomapver_copy != ver) { |
/* |
* This fault can be caused by an early access |
* to I/O port because of an out-dated |
* I/O Permission bitmap installed on CPU. |
* Install the fresh copy and restart |
* the instruction. |
*/ |
io_perm_bitmap_install(); |
return; |
} |
fault_if_from_uspace(istate, "general protection fault"); |
} |
print_info_errcode(n, istate); |
panic("general protection fault\n"); |
} |
void ss_fault(int n, istate_t *istate) |
{ |
fault_if_from_uspace(istate, "stack fault"); |
print_info_errcode(n, istate); |
panic("stack fault\n"); |
} |
void nm_fault(int n, istate_t *istate) |
{ |
#ifdef CONFIG_FPU_LAZY |
scheduler_fpu_lazy_request(); |
#else |
fault_if_from_uspace(istate, "fpu fault"); |
panic("fpu fault"); |
#endif |
} |
void tlb_shootdown_ipi(int n, istate_t *istate) |
{ |
trap_virtual_eoi(); |
tlb_shootdown_ipi_recv(); |
} |
void trap_virtual_enable_irqs(__u16 irqmask) |
{ |
if (enable_irqs_function) |
enable_irqs_function(irqmask); |
else |
panic("no enable_irqs_function\n"); |
} |
void trap_virtual_disable_irqs(__u16 irqmask) |
{ |
if (disable_irqs_function) |
disable_irqs_function(irqmask); |
else |
panic("no disable_irqs_function\n"); |
} |
void trap_virtual_eoi(void) |
{ |
if (eoi_function) |
eoi_function(); |
else |
panic("no eoi_function\n"); |
} |
static void ipc_int(int n, istate_t *istate) |
{ |
trap_virtual_eoi(); |
ipc_irq_send_notif(n-IVT_IRQBASE); |
} |
/* Reregister irq to be IPC-ready */ |
void irq_ipc_bind_arch(__native irq) |
{ |
if (irq == IRQ_CLK) |
return; |
exc_register(IVT_IRQBASE+irq, "ipc_int", ipc_int); |
} |
/tags/0.2.0.1/kernel/arch/amd64/src/proc/task.c |
---|
0,0 → 1,51 |
/* |
* Copyright (C) 2006 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - 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. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <proc/task.h> |
#include <mm/slab.h> |
#include <arch/types.h> |
/** Perform amd64 specific task initialization. |
* |
* @param t Task to be initialized. |
*/ |
void task_create_arch(task_t *t) |
{ |
t->arch.iomapver = 0; |
bitmap_initialize(&t->arch.iomap, NULL, 0); |
} |
/** Perform amd64 specific task destruction. |
* |
* @param t Task to be initialized. |
*/ |
void task_destroy_arch(task_t *t) |
{ |
if (t->arch.iomap.map) |
free(t->arch.iomap.map); |
} |
/tags/0.2.0.1/kernel/arch/amd64/src/proc/scheduler.c |
---|
0,0 → 1,75 |
/* |
* Copyright (C) 2005 Ondrej Palkovsky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - 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. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <proc/scheduler.h> |
#include <cpu.h> |
#include <proc/task.h> |
#include <proc/thread.h> |
#include <arch.h> |
#include <arch/context.h> /* SP_DELTA */ |
#include <arch/asm.h> |
#include <arch/debugger.h> |
#include <print.h> |
#include <arch/pm.h> |
#include <arch/ddi/ddi.h> |
/** Perform amd64 specific tasks needed before the new task is run. |
* |
* Interrupts are disabled. |
*/ |
void before_task_runs_arch(void) |
{ |
io_perm_bitmap_install(); |
} |
/** Perform amd64 specific tasks needed before the new thread is scheduled. */ |
void before_thread_runs_arch(void) |
{ |
CPU->arch.tss->rsp0 = (__address) &THREAD->kstack[THREAD_STACK_SIZE-SP_DELTA]; |
/* Syscall support - write address of thread stack pointer to |
* hidden part of gs */ |
swapgs(); |
write_msr(AMD_MSR_GS, (__u64)&THREAD->kstack); |
swapgs(); |
/* TLS support - set FS to thread local storage */ |
write_msr(AMD_MSR_FS, THREAD->arch.tls); |
#ifdef CONFIG_DEBUG_AS_WATCHPOINT |
/* Set watchpoint on AS to ensure that nobody sets it to zero */ |
if (CPU->id < BKPOINTS_MAX) |
breakpoint_add(&((the_t *) THREAD->kstack)->as, |
BKPOINT_WRITE | BKPOINT_CHECK_ZERO, |
CPU->id); |
#endif |
} |
void after_thread_ran_arch(void) |
{ |
} |
/tags/0.2.0.1/kernel/arch/amd64/src/proc/thread.c |
---|
0,0 → 1,38 |
/* |
* Copyright (C) 2006 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - 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. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <proc/thread.h> |
/** Perform amd64 specific thread initialization. |
* |
* @param t Thread to be initialized. |
*/ |
void thread_create_arch(thread_t *t) |
{ |
t->arch.tls = 0; |
} |
/tags/0.2.0.1/kernel/arch/amd64/src/amd64.c |
---|
0,0 → 1,203 |
/* |
* Copyright (C) 2005 Ondrej Palkovsky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - 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. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <arch.h> |
#include <arch/types.h> |
#include <config.h> |
#include <proc/thread.h> |
#include <arch/drivers/ega.h> |
#include <arch/drivers/vesa.h> |
#include <genarch/i8042/i8042.h> |
#include <arch/drivers/i8254.h> |
#include <arch/drivers/i8259.h> |
#include <arch/bios/bios.h> |
#include <arch/mm/memory_init.h> |
#include <arch/cpu.h> |
#include <print.h> |
#include <arch/cpuid.h> |
#include <genarch/acpi/acpi.h> |
#include <panic.h> |
#include <interrupt.h> |
#include <arch/syscall.h> |
#include <arch/debugger.h> |
#include <syscall/syscall.h> |
#include <console/console.h> |
/** Disable I/O on non-privileged levels |
* |
* Clean IOPL(12,13) and NT(14) flags in EFLAGS register |
*/ |
static void clean_IOPL_NT_flags(void) |
{ |
asm |
( |
"pushfq;" |
"pop %%rax;" |
"and $~(0x7000),%%rax;" |
"pushq %%rax;" |
"popfq;" |
: |
: |
:"%rax" |
); |
} |
/** Disable alignment check |
* |
* Clean AM(18) flag in CR0 register |
*/ |
static void clean_AM_flag(void) |
{ |
asm |
( |
"mov %%cr0,%%rax;" |
"and $~(0x40000),%%rax;" |
"mov %%rax,%%cr0;" |
: |
: |
:"%rax" |
); |
} |
void arch_pre_mm_init(void) |
{ |
struct cpu_info cpuid_s; |
cpuid(AMD_CPUID_EXTENDED,&cpuid_s); |
if (! (cpuid_s.cpuid_edx & (1<<AMD_EXT_NOEXECUTE))) |
panic("Processor does not support No-execute pages.\n"); |
cpuid(INTEL_CPUID_STANDARD,&cpuid_s); |
if (! (cpuid_s.cpuid_edx & (1<<INTEL_FXSAVE))) |
panic("Processor does not support FXSAVE/FXRESTORE.\n"); |
if (! (cpuid_s.cpuid_edx & (1<<INTEL_SSE2))) |
panic("Processor does not support SSE2 instructions.\n"); |
/* Enable No-execute pages */ |
set_efer_flag(AMD_NXE_FLAG); |
/* Enable FPU */ |
cpu_setup_fpu(); |
/* Initialize segmentation */ |
pm_init(); |
/* Disable I/O on nonprivileged levels |
* clear the NT(nested-thread) flag |
*/ |
clean_IOPL_NT_flags(); |
/* Disable alignment check */ |
clean_AM_flag(); |
if (config.cpu_active == 1) { |
bios_init(); |
i8259_init(); /* PIC */ |
i8254_init(); /* hard clock */ |
#ifdef CONFIG_SMP |
exc_register(VECTOR_TLB_SHOOTDOWN_IPI, "tlb_shootdown", |
tlb_shootdown_ipi); |
#endif /* CONFIG_SMP */ |
} |
} |
void arch_post_mm_init(void) |
{ |
if (config.cpu_active == 1) { |
#ifdef CONFIG_FB |
if (vesa_present()) |
vesa_init(); |
else |
#endif |
ega_init(); /* video */ |
/* Enable debugger */ |
debugger_init(); |
/* Merge all memory zones to 1 big zone */ |
zone_merge_all(); |
} |
/* Setup fast SYSCALL/SYSRET */ |
syscall_setup_cpu(); |
} |
void arch_pre_smp_init(void) |
{ |
if (config.cpu_active == 1) { |
memory_print_map(); |
#ifdef CONFIG_SMP |
acpi_init(); |
#endif /* CONFIG_SMP */ |
} |
} |
void arch_post_smp_init(void) |
{ |
i8042_init(); /* keyboard controller */ |
} |
void calibrate_delay_loop(void) |
{ |
i8254_calibrate_delay_loop(); |
i8254_normal_operation(); |
} |
/** Set thread-local-storage pointer |
* |
* TLS pointer is set in FS register. Unfortunately the 64-bit |
* part can be set only in CPL0 mode. |
* |
* The specs say, that on %fs:0 there is stored contents of %fs register, |
* we need not to go to CPL0 to read it. |
*/ |
__native sys_tls_set(__native addr) |
{ |
THREAD->arch.tls = addr; |
write_msr(AMD_MSR_FS, addr); |
return 0; |
} |
/** Acquire console back for kernel |
* |
*/ |
void arch_grab_console(void) |
{ |
i8042_grab(); |
} |
/** Return console to userspace |
* |
*/ |
void arch_release_console(void) |
{ |
i8042_release(); |
} |
/tags/0.2.0.1/kernel/arch/amd64/src/pm.c |
---|
0,0 → 1,235 |
/* |
* Copyright (C) 2001-2004 Jakub Jermar |
* Copyright (C) 2005-2006 Ondrej Palkovsky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - 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. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <arch/pm.h> |
#include <arch/mm/page.h> |
#include <arch/types.h> |
#include <arch/interrupt.h> |
#include <arch/asm.h> |
#include <interrupt.h> |
#include <mm/as.h> |
#include <config.h> |
#include <memstr.h> |
#include <mm/slab.h> |
#include <debug.h> |
/* |
* There is no segmentation in long mode so we set up flat mode. In this |
* mode, we use, for each privilege level, two segments spanning the |
* whole memory. One is for code and one is for data. |
*/ |
descriptor_t gdt[GDT_ITEMS] = { |
/* NULL descriptor */ |
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, |
/* KTEXT descriptor */ |
{ .limit_0_15 = 0xffff, |
.base_0_15 = 0, |
.base_16_23 = 0, |
.access = AR_PRESENT | AR_CODE | DPL_KERNEL | AR_READABLE , |
.limit_16_19 = 0xf, |
.available = 0, |
.longmode = 1, |
.special = 0, |
.granularity = 1, |
.base_24_31 = 0 }, |
/* KDATA descriptor */ |
{ .limit_0_15 = 0xffff, |
.base_0_15 = 0, |
.base_16_23 = 0, |
.access = AR_PRESENT | AR_DATA | AR_WRITABLE | DPL_KERNEL, |
.limit_16_19 = 0xf, |
.available = 0, |
.longmode = 0, |
.special = 0, |
.granularity = 1, |
.base_24_31 = 0 }, |
/* UDATA descriptor */ |
{ .limit_0_15 = 0xffff, |
.base_0_15 = 0, |
.base_16_23 = 0, |
.access = AR_PRESENT | AR_DATA | AR_WRITABLE | DPL_USER, |
.limit_16_19 = 0xf, |
.available = 0, |
.longmode = 0, |
.special = 1, |
.granularity = 1, |
.base_24_31 = 0 }, |
/* UTEXT descriptor */ |
{ .limit_0_15 = 0xffff, |
.base_0_15 = 0, |
.base_16_23 = 0, |
.access = AR_PRESENT | AR_CODE | DPL_USER, |
.limit_16_19 = 0xf, |
.available = 0, |
.longmode = 1, |
.special = 0, |
.granularity = 1, |
.base_24_31 = 0 }, |
/* KTEXT 32-bit protected, for protected mode before long mode */ |
{ .limit_0_15 = 0xffff, |
.base_0_15 = 0, |
.base_16_23 = 0, |
.access = AR_PRESENT | AR_CODE | DPL_KERNEL | AR_READABLE, |
.limit_16_19 = 0xf, |
.available = 0, |
.longmode = 0, |
.special = 1, |
.granularity = 1, |
.base_24_31 = 0 }, |
/* TSS descriptor - set up will be completed later, |
* on AMD64 it is 64-bit - 2 items in table */ |
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, |
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, |
/* VESA Init descriptor */ |
#ifdef CONFIG_FB |
{ 0xffff, 0, VESA_INIT_SEGMENT>>12, AR_PRESENT | AR_CODE | DPL_KERNEL, 0xf, 0, 0, 0, 0, 0 } |
#endif |
}; |
idescriptor_t idt[IDT_ITEMS]; |
ptr_16_64_t gdtr = {.limit = sizeof(gdt), .base= (__u64) gdt }; |
ptr_16_64_t idtr = {.limit = sizeof(idt), .base= (__u64) idt }; |
static tss_t tss; |
tss_t *tss_p = NULL; |
void gdt_tss_setbase(descriptor_t *d, __address base) |
{ |
tss_descriptor_t *td = (tss_descriptor_t *) d; |
td->base_0_15 = base & 0xffff; |
td->base_16_23 = ((base) >> 16) & 0xff; |
td->base_24_31 = ((base) >> 24) & 0xff; |
td->base_32_63 = ((base) >> 32); |
} |
void gdt_tss_setlimit(descriptor_t *d, __u32 limit) |
{ |
struct tss_descriptor *td = (tss_descriptor_t *) d; |
td->limit_0_15 = limit & 0xffff; |
td->limit_16_19 = (limit >> 16) & 0xf; |
} |
void idt_setoffset(idescriptor_t *d, __address offset) |
{ |
/* |
* Offset is a linear address. |
*/ |
d->offset_0_15 = offset & 0xffff; |
d->offset_16_31 = offset >> 16 & 0xffff; |
d->offset_32_63 = offset >> 32; |
} |
void tss_initialize(tss_t *t) |
{ |
memsetb((__address) t, sizeof(tss_t), 0); |
} |
/* |
* This function takes care of proper setup of IDT and IDTR. |
*/ |
void idt_init(void) |
{ |
idescriptor_t *d; |
int i; |
for (i = 0; i < IDT_ITEMS; i++) { |
d = &idt[i]; |
d->unused = 0; |
d->selector = gdtselector(KTEXT_DES); |
d->present = 1; |
d->type = AR_INTERRUPT; /* masking interrupt */ |
idt_setoffset(d, ((__address) interrupt_handlers) + i*interrupt_handler_size); |
exc_register(i, "undef", (iroutine)null_interrupt); |
} |
exc_register( 7, "nm_fault", nm_fault); |
exc_register(12, "ss_fault", ss_fault); |
exc_register(13, "gp_fault", gp_fault); |
exc_register(14, "ident_mapper", ident_page_fault); |
} |
/** Initialize segmentation - code/data/idt tables |
* |
*/ |
void pm_init(void) |
{ |
descriptor_t *gdt_p = (struct descriptor *) gdtr.base; |
tss_descriptor_t *tss_desc; |
/* |
* Each CPU has its private GDT and TSS. |
* All CPUs share one IDT. |
*/ |
if (config.cpu_active == 1) { |
idt_init(); |
/* |
* NOTE: bootstrap CPU has statically allocated TSS, because |
* the heap hasn't been initialized so far. |
*/ |
tss_p = &tss; |
} |
else { |
/* We are going to use malloc, which may return |
* non boot-mapped pointer, initialize the CR3 register |
* ahead of page_init */ |
write_cr3((__address) AS_KERNEL->page_table); |
tss_p = (struct tss *) malloc(sizeof(tss_t), FRAME_ATOMIC); |
if (!tss_p) |
panic("could not allocate TSS\n"); |
} |
tss_initialize(tss_p); |
tss_desc = (tss_descriptor_t *) (&gdt_p[TSS_DES]); |
tss_desc->present = 1; |
tss_desc->type = AR_TSS; |
tss_desc->dpl = PL_KERNEL; |
gdt_tss_setbase(&gdt_p[TSS_DES], (__address) tss_p); |
gdt_tss_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE - 1); |
gdtr_load(&gdtr); |
idtr_load(&idtr); |
/* |
* As of this moment, the current CPU has its own GDT pointing |
* to its own TSS. We just need to load the TR register. |
*/ |
tr_load(gdtselector(TSS_DES)); |
} |
/tags/0.2.0.1/kernel/arch/amd64/src/asm_utils.S |
---|
0,0 → 1,303 |
# |
# Copyright (C) 2005 Ondrej Palkovsky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - 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. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. |
# |
#define IREGISTER_SPACE 120 |
#define IOFFSET_RAX 0x0 |
#define IOFFSET_RBX 0x8 |
#define IOFFSET_RCX 0x10 |
#define IOFFSET_RDX 0x18 |
#define IOFFSET_RSI 0x20 |
#define IOFFSET_RDI 0x28 |
#define IOFFSET_R8 0x30 |
#define IOFFSET_R9 0x38 |
#define IOFFSET_R10 0x40 |
#define IOFFSET_R11 0x48 |
#define IOFFSET_R12 0x50 |
#define IOFFSET_R13 0x58 |
#define IOFFSET_R14 0x60 |
#define IOFFSET_R15 0x68 |
#define IOFFSET_RBP 0x70 |
# Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int has no error word |
# and 1 means interrupt with error word |
#define ERROR_WORD_INTERRUPT_LIST 0x00027D00 |
#include <arch/pm.h> |
#include <arch/mm/page.h> |
.text |
.global interrupt_handlers |
.global syscall_entry |
.global panic_printf |
panic_printf: |
movq $halt, (%rsp) |
jmp printf |
.global cpuid |
.global has_cpuid |
.global rdtsc |
.global read_efer_flag |
.global set_efer_flag |
.global memcpy |
.global memcpy_from_uspace |
.global memcpy_to_uspace |
.global memcpy_from_uspace_failover_address |
.global memcpy_to_uspace_failover_address |
#define MEMCPY_DST %rdi |
#define MEMCPY_SRC %rsi |
#define MEMCPY_SIZE %rdx |
/** |
* Copy memory from/to userspace. |
* |
* This is almost conventional memcpy(). |
* The difference is that there is a failover part |
* to where control is returned from a page fault if |
* the page fault occurs during copy_from_uspace() |
* or copy_to_uspace(). |
* |
* @param MEMCPY_DST Destination address. |
* @param MEMCPY_SRC Source address. |
* @param MEMCPY_SIZE Number of bytes to copy. |
* |
* @retrun MEMCPY_SRC on success, 0 on failure. |
*/ |
memcpy: |
memcpy_from_uspace: |
memcpy_to_uspace: |
movq MEMCPY_SRC, %rax |
movq MEMCPY_SIZE, %rcx |
shrq $3, %rcx /* size / 8 */ |
rep movsq /* copy as much as possible word by word */ |
movq MEMCPY_SIZE, %rcx |
andq $7, %rcx /* size % 8 */ |
jz 0f |
rep movsb /* copy the rest byte by byte */ |
0: |
ret /* return MEMCPY_SRC, success */ |
memcpy_from_uspace_failover_address: |
memcpy_to_uspace_failover_address: |
xorq %rax, %rax /* return 0, failure */ |
ret |
## Determine CPUID support |
# |
# Return 0 in EAX if CPUID is not support, 1 if supported. |
# |
has_cpuid: |
pushfq # store flags |
popq %rax # read flags |
movq %rax,%rdx # copy flags |
btcl $21,%edx # swap the ID bit |
pushq %rdx |
popfq # propagate the change into flags |
pushfq |
popq %rdx # read flags |
andl $(1<<21),%eax # interested only in ID bit |
andl $(1<<21),%edx |
xorl %edx,%eax # 0 if not supported, 1 if supported |
ret |
cpuid: |
movq %rbx, %r10 # we have to preserve rbx across function calls |
movl %edi,%eax # load the command into %eax |
cpuid |
movl %eax,0(%rsi) |
movl %ebx,4(%rsi) |
movl %ecx,8(%rsi) |
movl %edx,12(%rsi) |
movq %r10, %rbx |
ret |
rdtsc: |
xorq %rax,%rax |
rdtsc |
ret |
set_efer_flag: |
movq $0xc0000080, %rcx |
rdmsr |
btsl %edi, %eax |
wrmsr |
ret |
read_efer_flag: |
movq $0xc0000080, %rcx |
rdmsr |
ret |
# Push all general purpose registers on stack except %rbp, %rsp |
.macro save_all_gpr |
movq %rax, IOFFSET_RAX(%rsp) |
movq %rcx, IOFFSET_RCX(%rsp) |
movq %rdx, IOFFSET_RDX(%rsp) |
movq %rsi, IOFFSET_RSI(%rsp) |
movq %rdi, IOFFSET_RDI(%rsp) |
movq %r8, IOFFSET_R8(%rsp) |
movq %r9, IOFFSET_R9(%rsp) |
movq %r10, IOFFSET_R10(%rsp) |
movq %r11, IOFFSET_R11(%rsp) |
#ifdef CONFIG_DEBUG_ALLREGS |
movq %rbx, IOFFSET_RBX(%rsp) |
movq %rbp, IOFFSET_RBP(%rsp) |
movq %r12, IOFFSET_R12(%rsp) |
movq %r13, IOFFSET_R13(%rsp) |
movq %r14, IOFFSET_R14(%rsp) |
movq %r15, IOFFSET_R15(%rsp) |
#endif |
.endm |
.macro restore_all_gpr |
movq IOFFSET_RAX(%rsp), %rax |
movq IOFFSET_RCX(%rsp), %rcx |
movq IOFFSET_RDX(%rsp), %rdx |
movq IOFFSET_RSI(%rsp), %rsi |
movq IOFFSET_RDI(%rsp), %rdi |
movq IOFFSET_R8(%rsp), %r8 |
movq IOFFSET_R9(%rsp), %r9 |
movq IOFFSET_R10(%rsp), %r10 |
movq IOFFSET_R11(%rsp), %r11 |
#ifdef CONFIG_DEBUG_ALLREGS |
movq IOFFSET_RBX(%rsp), %rbx |
movq IOFFSET_RBP(%rsp), %rbp |
movq IOFFSET_R12(%rsp), %r12 |
movq IOFFSET_R13(%rsp), %r13 |
movq IOFFSET_R14(%rsp), %r14 |
movq IOFFSET_R15(%rsp), %r15 |
#endif |
.endm |
#ifdef CONFIG_DEBUG_ALLREGS |
# define INTERRUPT_ALIGN 256 |
#else |
# define INTERRUPT_ALIGN 128 |
#endif |
## Declare interrupt handlers |
# |
# Declare interrupt handlers for n interrupt |
# vectors starting at vector i. |
# |
# The handlers call exc_dispatch(). |
# |
.macro handler i n |
/* |
* Choose between version with error code and version without error code. |
* Both versions have to be of the same size. amd64 assembly is, however, |
* a little bit tricky. For instance, subq $0x80, %rsp and subq $0x78, %rsp |
* can result in two instructions with different op-code lengths. |
* Therefore we align the interrupt handlers. |
*/ |
.iflt \i-32 |
.if (1 << \i) & ERROR_WORD_INTERRUPT_LIST |
/* |
* Version with error word. |
*/ |
subq $IREGISTER_SPACE, %rsp |
.else |
/* |
* Version without error word, |
*/ |
subq $(IREGISTER_SPACE+8), %rsp |
.endif |
.else |
/* |
* Version without error word, |
*/ |
subq $(IREGISTER_SPACE+8), %rsp |
.endif |
save_all_gpr |
movq $(\i), %rdi # %rdi - first parameter |
movq %rsp, %rsi # %rsi - pointer to istate |
call exc_dispatch # exc_dispatch(i, istate) |
restore_all_gpr |
# $8 = Skip error word |
addq $(IREGISTER_SPACE+8), %rsp |
iretq |
.align INTERRUPT_ALIGN |
.if (\n-\i)-1 |
handler "(\i+1)",\n |
.endif |
.endm |
.align INTERRUPT_ALIGN |
interrupt_handlers: |
h_start: |
handler 0 IDT_ITEMS |
h_end: |
syscall_entry: |
# Switch to hidden gs |
swapgs |
# %gs:0 now points to pointer to stack page |
mov %gs:0, %r10 # We have a ptr to stack page in r10 |
addq $PAGE_SIZE-16, %r10 # We need some space to store old %sp |
movq %rsp, 0(%r10) # Save old stack pointer to stack |
movq %r10, %rsp # Change to new stack |
pushq %rcx # Return address |
pushq %r11 # Save flags |
# Switch back to remain consistent |
swapgs |
sti |
movq %r9, %rcx # Exchange last parameter as a third |
call syscall_handler |
cli # We will be touching stack pointer |
popq %r11 |
popq %rcx |
movq 0(%rsp), %rsp |
sysretq |
.data |
.global interrupt_handler_size |
interrupt_handler_size: .quad (h_end-h_start)/IDT_ITEMS |
/tags/0.2.0.1/kernel/arch/amd64/src/ddi/ddi.c |
---|
0,0 → 1,157 |
/* |
* Copyright (C) 2006 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - 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. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <ddi/ddi.h> |
#include <arch/ddi/ddi.h> |
#include <proc/task.h> |
#include <arch/types.h> |
#include <typedefs.h> |
#include <adt/bitmap.h> |
#include <mm/slab.h> |
#include <arch/pm.h> |
#include <errno.h> |
#include <arch/cpu.h> |
#include <arch.h> |
#include <align.h> |
/** Enable I/O space range for task. |
* |
* Interrupts are disabled and task is locked. |
* |
* @param task Task. |
* @param ioaddr Startign I/O space address. |
* @param size Size of the enabled I/O range. |
* |
* @return 0 on success or an error code from errno.h. |
*/ |
int ddi_iospace_enable_arch(task_t *task, __address ioaddr, size_t size) |
{ |
count_t bits; |
bits = ioaddr + size; |
if (bits > IO_PORTS) |
return ENOENT; |
if (task->arch.iomap.bits < bits) { |
bitmap_t oldiomap; |
__u8 *newmap; |
/* |
* The I/O permission bitmap is too small and needs to be grown. |
*/ |
newmap = (__u8 *) malloc(BITS2BYTES(bits), FRAME_ATOMIC); |
if (!newmap) |
return ENOMEM; |
bitmap_initialize(&oldiomap, task->arch.iomap.map, task->arch.iomap.bits); |
bitmap_initialize(&task->arch.iomap, newmap, bits); |
/* |
* Mark the new range inaccessible. |
*/ |
bitmap_set_range(&task->arch.iomap, oldiomap.bits, bits - oldiomap.bits); |
/* |
* In case there really existed smaller iomap, |
* copy its contents and deallocate it. |
*/ |
if (oldiomap.bits) { |
bitmap_copy(&task->arch.iomap, &oldiomap, oldiomap.bits); |
free(oldiomap.map); |
} |
} |
/* |
* Enable the range and we are done. |
*/ |
bitmap_clear_range(&task->arch.iomap, (index_t) ioaddr, (count_t) size); |
/* |
* Increment I/O Permission bitmap generation counter. |
*/ |
task->arch.iomapver++; |
return 0; |
} |
/** Install I/O Permission bitmap. |
* |
* Current task's I/O permission bitmap, if any, is installed |
* in the current CPU's TSS. |
* |
* Interrupts must be disabled prior this call. |
*/ |
void io_perm_bitmap_install(void) |
{ |
count_t bits; |
ptr_16_64_t cpugdtr; |
descriptor_t *gdt_p; |
tss_descriptor_t *tss_desc; |
count_t ver; |
/* First, copy the I/O Permission Bitmap. */ |
spinlock_lock(&TASK->lock); |
ver = TASK->arch.iomapver; |
if ((bits = TASK->arch.iomap.bits)) { |
bitmap_t iomap; |
ASSERT(TASK->arch.iomap.map); |
bitmap_initialize(&iomap, CPU->arch.tss->iomap, TSS_IOMAP_SIZE * 8); |
bitmap_copy(&iomap, &TASK->arch.iomap, TASK->arch.iomap.bits); |
/* |
* It is safe to set the trailing eight bits because of the extra |
* convenience byte in TSS_IOMAP_SIZE. |
*/ |
bitmap_set_range(&iomap, ALIGN_UP(TASK->arch.iomap.bits, 8), 8); |
} |
spinlock_unlock(&TASK->lock); |
/* |
* Second, adjust TSS segment limit. |
* Take the extra ending byte will all bits set into account. |
*/ |
gdtr_store(&cpugdtr); |
gdt_p = (descriptor_t *) cpugdtr.base; |
gdt_tss_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE + BITS2BYTES(bits)); |
gdtr_load(&cpugdtr); |
/* |
* Before we load new TSS limit, the current TSS descriptor |
* type must be changed to describe inactive TSS. |
*/ |
tss_desc = (tss_descriptor_t *) &gdt_p[TSS_DES]; |
tss_desc->type = AR_TSS; |
tr_load(gdtselector(TSS_DES)); |
/* |
* Update the generation count so that faults caused by |
* early accesses can be serviced. |
*/ |
CPU->arch.iomapver_copy = ver; |
} |
/tags/0.2.0.1/kernel/arch/amd64/src/smp/ap.S |
---|
0,0 → 1,115 |
# |
# Copyright (C) 2001-2004 Jakub Jermar |
# Copyright (C) 2005-2006 Martin Decky |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - 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. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. |
# |
# |
# Init code for application processors. |
# |
#include <arch/boot/boot.h> |
#include <arch/boot/memmap.h> |
#include <arch/mm/page.h> |
#include <arch/pm.h> |
#include <arch/cpu.h> |
#include <arch/cpuid.h> |
.section K_TEXT_START, "ax" |
#ifdef CONFIG_SMP |
.global unmapped_ap_boot |
# This piece of code is real-mode and is meant to be alligned at 4K boundary. |
# The requirement for such an alignment comes from MP Specification's STARTUP IPI |
# requirements. |
.align 4096 |
unmapped_ap_boot: |
.code16 |
cli |
xorw %ax, %ax |
movw %ax, %ds |
lgdtl ap_gdtr # initialize Global Descriptor Table register |
movl %cr0, %eax |
orl $1, %eax |
movl %eax, %cr0 # switch to protected mode |
jmpl $gdtselector(KTEXT32_DES), $jump_to_kernel - BOOT_OFFSET + AP_BOOT_OFFSET |
jump_to_kernel: |
.code32 |
movw $gdtselector(KDATA_DES), %ax |
movw %ax, %ds |
movw %ax, %es |
movw %ax, %ss |
movw $gdtselector(UDATA_DES), %ax |
movw %ax, %gs |
# Enable 64-bit page transaltion entries - CR4.PAE = 1. |
# Paging is not enabled until after long mode is enabled |
movl %cr4, %eax |
btsl $5, %eax |
movl %eax, %cr4 |
leal ptl_0, %eax |
movl %eax, %cr3 |
# Enable long mode |
movl $EFER_MSR_NUM, %ecx # EFER MSR number |
rdmsr # Read EFER |
btsl $AMD_LME_FLAG, %eax # Set LME=1 |
wrmsr # Write EFER |
# Enable paging to activate long mode (set CR0.PG=1) |
movl %cr0, %eax |
btsl $31, %eax |
movl %eax, %cr0 |
# At this point we are in compatibility mode |
jmpl $gdtselector(KTEXT_DES), $start64 - BOOT_OFFSET + AP_BOOT_OFFSET |
.code64 |
start64: |
movq (ctx), %rsp |
call main_ap - AP_BOOT_OFFSET + BOOT_OFFSET # never returns |
#endif /* CONFIG_SMP */ |
.section K_DATA_START, "aw", @progbits |
#ifdef CONFIG_SMP |
.global unmapped_ap_gdtr |
unmapped_ap_gdtr: |
.word 0 |
.long 0 |
#endif /* CONFIG_SMP */ |
/tags/0.2.0.1/kernel/arch/amd64/src/smp/mps.c |
---|
0,0 → 1,0 |
link ../../../ia32/src/smp/mps.c |
Property changes: |
Added: svn:special |
+* |
\ No newline at end of property |
/tags/0.2.0.1/kernel/arch/amd64/src/smp/smp.c |
---|
0,0 → 1,0 |
link ../../../ia32/src/smp/smp.c |
Property changes: |
Added: svn:special |
+* |
\ No newline at end of property |
/tags/0.2.0.1/kernel/arch/amd64/src/smp/ipi.c |
---|
0,0 → 1,0 |
link ../../../ia32/src/smp/ipi.c |
Property changes: |
Added: svn:special |
+* |
\ No newline at end of property |
/tags/0.2.0.1/kernel/arch/amd64/src/smp/apic.c |
---|
0,0 → 1,0 |
link ../../../ia32/src/smp/apic.c |
Property changes: |
Added: svn:special |
+* |
\ No newline at end of property |
/tags/0.2.0.1/kernel/arch/amd64/src/debugger.c |
---|
0,0 → 1,377 |
/* |
* Copyright (C) 2006 Ondrej Palkovsky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - 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. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <arch/debugger.h> |
#include <console/kconsole.h> |
#include <console/cmd.h> |
#include <symtab.h> |
#include <print.h> |
#include <panic.h> |
#include <interrupt.h> |
#include <arch/asm.h> |
#include <arch/cpu.h> |
#include <debug.h> |
#include <func.h> |
#include <smp/ipi.h> |
typedef struct { |
__address address; /**< Breakpoint address */ |
int flags; /**< Flags regarding breakpoint */ |
int counter; /**< How many times the exception occured */ |
} bpinfo_t; |
static bpinfo_t breakpoints[BKPOINTS_MAX]; |
SPINLOCK_INITIALIZE(bkpoint_lock); |
static int cmd_print_breakpoints(cmd_arg_t *argv); |
static cmd_info_t bkpts_info = { |
.name = "bkpts", |
.description = "Print breakpoint table.", |
.func = cmd_print_breakpoints, |
.argc = 0, |
}; |
#ifndef CONFIG_DEBUG_AS_WATCHPOINT |
static int cmd_del_breakpoint(cmd_arg_t *argv); |
static cmd_arg_t del_argv = { |
.type = ARG_TYPE_INT |
}; |
static cmd_info_t delbkpt_info = { |
.name = "delbkpt", |
.description = "delbkpt <number> - Delete breakpoint.", |
.func = cmd_del_breakpoint, |
.argc = 1, |
.argv = &del_argv |
}; |
static int cmd_add_breakpoint(cmd_arg_t *argv); |
static cmd_arg_t add_argv = { |
.type = ARG_TYPE_INT |
}; |
static cmd_info_t addbkpt_info = { |
.name = "addbkpt", |
.description = "addbkpt <&symbol> - new breakpoint.", |
.func = cmd_add_breakpoint, |
.argc = 1, |
.argv = &add_argv |
}; |
static cmd_arg_t addw_argv = { |
.type = ARG_TYPE_INT |
}; |
static cmd_info_t addwatchp_info = { |
.name = "addwatchp", |
.description = "addbwatchp <&symbol> - new write watchpoint.", |
.func = cmd_add_breakpoint, |
.argc = 1, |
.argv = &addw_argv |
}; |
#endif |
/** Print table of active breakpoints */ |
int cmd_print_breakpoints(cmd_arg_t *argv) |
{ |
int i; |
char *symbol; |
printf("Breakpoint table.\n"); |
for (i=0; i < BKPOINTS_MAX; i++) |
if (breakpoints[i].address) { |
symbol = get_symtab_entry(breakpoints[i].address); |
printf("%d. %p in %s\n",i, |
breakpoints[i].address, symbol); |
printf(" Count(%d) ", breakpoints[i].counter); |
printf("\n"); |
} |
return 1; |
} |
/* Setup DR register according to table */ |
static void setup_dr(int curidx) |
{ |
__native dr7; |
bpinfo_t *cur = &breakpoints[curidx]; |
int flags = breakpoints[curidx].flags; |
/* Disable breakpoint in DR7 */ |
dr7 = read_dr7(); |
dr7 &= ~(0x2 << (curidx*2)); |
if (cur->address) { /* Setup DR register */ |
/* Set breakpoint to debug registers */ |
switch (curidx) { |
case 0: |
write_dr0(cur->address); |
break; |
case 1: |
write_dr1(cur->address); |
break; |
case 2: |
write_dr2(cur->address); |
break; |
case 3: |
write_dr3(cur->address); |
break; |
} |
/* Set type to requested breakpoint & length*/ |
dr7 &= ~ (0x3 << (16 + 4*curidx)); |
dr7 &= ~ (0x3 << (18 + 4*curidx)); |
if ((flags & BKPOINT_INSTR)) { |
; |
} else { |
if (sizeof(int) == 4) |
dr7 |= ((__native) 0x3) << (18 + 4*curidx); |
else /* 8 */ |
dr7 |= ((__native) 0x2) << (18 + 4*curidx); |
if ((flags & BKPOINT_WRITE)) |
dr7 |= ((__native) 0x1) << (16 + 4*curidx); |
else if ((flags & BKPOINT_READ_WRITE)) |
dr7 |= ((__native) 0x3) << (16 + 4*curidx); |
} |
/* Enable global breakpoint */ |
dr7 |= 0x2 << (curidx*2); |
write_dr7(dr7); |
} |
} |
/** Enable hardware breakpoint |
* |
* |
* @param where Address of HW breakpoint |
* @param flags Type of breakpoint (EXECUTE, WRITE) |
* @return Debug slot on success, -1 - no available HW breakpoint |
*/ |
int breakpoint_add(void * where, int flags, int curidx) |
{ |
ipl_t ipl; |
int i; |
bpinfo_t *cur; |
ASSERT( flags & (BKPOINT_INSTR | BKPOINT_WRITE | BKPOINT_READ_WRITE)); |
ipl = interrupts_disable(); |
spinlock_lock(&bkpoint_lock); |
if (curidx == -1) { |
/* Find free space in slots */ |
for (i=0; i<BKPOINTS_MAX; i++) |
if (!breakpoints[i].address) { |
curidx = i; |
break; |
} |
if (curidx == -1) { |
/* Too many breakpoints */ |
spinlock_unlock(&bkpoint_lock); |
interrupts_restore(ipl); |
return -1; |
} |
} |
cur = &breakpoints[curidx]; |
cur->address = (__address) where; |
cur->flags = flags; |
cur->counter = 0; |
setup_dr(curidx); |
spinlock_unlock(&bkpoint_lock); |
interrupts_restore(ipl); |
/* Send IPI */ |
#ifdef CONFIG_SMP |
// ipi_broadcast(VECTOR_DEBUG_IPI); |
#endif |
return curidx; |
} |
#ifdef amd64 |
# define getip(x) ((x)->rip) |
#else |
# define getip(x) ((x)->eip) |
#endif |
static void handle_exception(int slot, istate_t *istate) |
{ |
ASSERT(breakpoints[slot].address); |
/* Handle zero checker */ |
if (! (breakpoints[slot].flags & BKPOINT_INSTR)) { |
if ((breakpoints[slot].flags & BKPOINT_CHECK_ZERO)) { |
if (*((__native *) breakpoints[slot].address) != 0) |
return; |
printf("**** Found ZERO on address %p ****\n", |
slot, breakpoints[slot].address); |
} else { |
printf("Data watchpoint - new data: %p\n", |
*((__native *) breakpoints[slot].address)); |
} |
} |
printf("Reached breakpoint %d:%p(%s)\n", slot, getip(istate), |
get_symtab_entry(getip(istate))); |
printf("***Type 'exit' to exit kconsole.\n"); |
atomic_set(&haltstate,1); |
kconsole("debug"); |
atomic_set(&haltstate,0); |
} |
void breakpoint_del(int slot) |
{ |
bpinfo_t *cur; |
ipl_t ipl; |
ipl = interrupts_disable(); |
spinlock_lock(&bkpoint_lock); |
cur = &breakpoints[slot]; |
if (!cur->address) { |
spinlock_unlock(&bkpoint_lock); |
interrupts_restore(ipl); |
return; |
} |
cur->address = NULL; |
setup_dr(slot); |
spinlock_unlock(&bkpoint_lock); |
interrupts_restore(ipl); |
#ifdef CONFIG_SMP |
// ipi_broadcast(VECTOR_DEBUG_IPI); |
#endif |
} |
#ifndef CONFIG_DEBUG_AS_WATCHPOINT |
/** Remove breakpoint from table */ |
int cmd_del_breakpoint(cmd_arg_t *argv) |
{ |
if (argv->intval < 0 || argv->intval > BKPOINTS_MAX) { |
printf("Invalid breakpoint number.\n"); |
return 0; |
} |
breakpoint_del(argv->intval); |
return 1; |
} |
/** Add new breakpoint to table */ |
static int cmd_add_breakpoint(cmd_arg_t *argv) |
{ |
int flags; |
int id; |
if (argv == &add_argv) { |
flags = BKPOINT_INSTR; |
} else { /* addwatchp */ |
flags = BKPOINT_WRITE; |
} |
printf("Adding breakpoint on address: %p\n", argv->intval); |
id = breakpoint_add((void *)argv->intval, flags, -1); |
if (id < 0) |
printf("Add breakpoint failed.\n"); |
else |
printf("Added breakpoint %d.\n", id); |
return 1; |
} |
#endif |
static void debug_exception(int n, istate_t *istate) |
{ |
__native dr6; |
int i; |
/* Set RF to restart the instruction */ |
#ifdef amd64 |
istate->rflags |= RFLAGS_RF; |
#else |
istate->eflags |= EFLAGS_RF; |
#endif |
dr6 = read_dr6(); |
for (i=0; i < BKPOINTS_MAX; i++) { |
if (dr6 & (1 << i)) { |
dr6 &= ~ (1 << i); |
write_dr6(dr6); |
handle_exception(i, istate); |
} |
} |
} |
#ifdef CONFIG_SMP |
static void debug_ipi(int n, istate_t *istate) |
{ |
int i; |
spinlock_lock(&bkpoint_lock); |
for (i=0; i < BKPOINTS_MAX; i++) |
setup_dr(i); |
spinlock_unlock(&bkpoint_lock); |
} |
#endif |
/** Initialize debugger */ |
void debugger_init() |
{ |
int i; |
for (i=0; i<BKPOINTS_MAX; i++) |
breakpoints[i].address = NULL; |
cmd_initialize(&bkpts_info); |
if (!cmd_register(&bkpts_info)) |
panic("could not register command %s\n", bkpts_info.name); |
#ifndef CONFIG_DEBUG_AS_WATCHPOINT |
cmd_initialize(&delbkpt_info); |
if (!cmd_register(&delbkpt_info)) |
panic("could not register command %s\n", delbkpt_info.name); |
cmd_initialize(&addbkpt_info); |
if (!cmd_register(&addbkpt_info)) |
panic("could not register command %s\n", addbkpt_info.name); |
cmd_initialize(&addwatchp_info); |
if (!cmd_register(&addwatchp_info)) |
panic("could not register command %s\n", addwatchp_info.name); |
#endif |
exc_register(VECTOR_DEBUG, "debugger", |
debug_exception); |
#ifdef CONFIG_SMP |
exc_register(VECTOR_DEBUG_IPI, "debugger_smp", |
debug_ipi); |
#endif |
} |
/tags/0.2.0.1/kernel/arch/amd64/src/cpu/cpu.c |
---|
0,0 → 1,159 |
/* |
* Copyright (C) 2001-2004 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - 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. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <arch/cpu.h> |
#include <arch/cpuid.h> |
#include <arch/pm.h> |
#include <arch.h> |
#include <arch/types.h> |
#include <print.h> |
#include <typedefs.h> |
#include <fpu_context.h> |
/* |
* Identification of CPUs. |
* Contains only non-MP-Specification specific SMP code. |
*/ |
#define AMD_CPUID_EBX 0x68747541 |
#define AMD_CPUID_ECX 0x444d4163 |
#define AMD_CPUID_EDX 0x69746e65 |
#define INTEL_CPUID_EBX 0x756e6547 |
#define INTEL_CPUID_ECX 0x6c65746e |
#define INTEL_CPUID_EDX 0x49656e69 |
enum vendor { |
VendorUnknown=0, |
VendorAMD, |
VendorIntel |
}; |
static char *vendor_str[] = { |
"Unknown Vendor", |
"AuthenticAMD", |
"GenuineIntel" |
}; |
/** Setup flags on processor so that we can use the FPU |
* |
* cr0.osfxsr = 1 -> we do support fxstor/fxrestor |
* cr0.em = 0 -> we do not emulate coprocessor |
* cr0.mp = 1 -> we do want lazy context switch |
*/ |
void cpu_setup_fpu(void) |
{ |
__asm__ volatile ( |
"movq %%cr0, %%rax;" |
"btsq $1, %%rax;" /* cr0.mp */ |
"btrq $2, %%rax;" /* cr0.em */ |
"movq %%rax, %%cr0;" |
"movq %%cr4, %%rax;" |
"bts $9, %%rax;" /* cr4.osfxsr */ |
"movq %%rax, %%cr4;" |
: |
: |
:"%rax" |
); |
} |
/** Set the TS flag to 1. |
* |
* If a thread accesses coprocessor, exception is run, which |
* does a lazy fpu context switch. |
* |
*/ |
void fpu_disable(void) |
{ |
__asm__ volatile ( |
"mov %%cr0,%%rax;" |
"bts $3,%%rax;" |
"mov %%rax,%%cr0;" |
: |
: |
:"%rax" |
); |
} |
void fpu_enable(void) |
{ |
__asm__ volatile ( |
"mov %%cr0,%%rax;" |
"btr $3,%%rax;" |
"mov %%rax,%%cr0;" |
: |
: |
:"%rax" |
); |
} |
void cpu_arch_init(void) |
{ |
CPU->arch.tss = tss_p; |
CPU->arch.tss->iomap_base = &CPU->arch.tss->iomap[0] - ((__u8 *) CPU->arch.tss); |
CPU->fpu_owner = NULL; |
} |
void cpu_identify(void) |
{ |
cpu_info_t info; |
CPU->arch.vendor = VendorUnknown; |
if (has_cpuid()) { |
cpuid(0, &info); |
/* |
* Check for AMD processor. |
*/ |
if (info.cpuid_ebx==AMD_CPUID_EBX && info.cpuid_ecx==AMD_CPUID_ECX && info.cpuid_edx==AMD_CPUID_EDX) { |
CPU->arch.vendor = VendorAMD; |
} |
/* |
* Check for Intel processor. |
*/ |
if (info.cpuid_ebx==INTEL_CPUID_EBX && info.cpuid_ecx==INTEL_CPUID_ECX && info.cpuid_edx==INTEL_CPUID_EDX) { |
CPU->arch.vendor = VendorIntel; |
} |
cpuid(1, &info); |
CPU->arch.family = (info.cpuid_eax>>8)&0xf; |
CPU->arch.model = (info.cpuid_eax>>4)&0xf; |
CPU->arch.stepping = (info.cpuid_eax>>0)&0xf; |
} |
} |
void cpu_print_report(cpu_t* m) |
{ |
printf("cpu%d: (%s family=%d model=%d stepping=%d) %dMHz\n", |
m->id, vendor_str[m->arch.vendor], m->arch.family, m->arch.model, m->arch.stepping, |
m->frequency_mhz); |
} |
/tags/0.2.0.1/kernel/arch/amd64/src/userspace.c |
---|
0,0 → 1,72 |
/* |
* Copyright (C) 2005 Ondrej Palkovsky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - 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. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <userspace.h> |
#include <arch/pm.h> |
#include <arch/types.h> |
#include <arch.h> |
#include <proc/uarg.h> |
#include <mm/as.h> |
/** Enter userspace |
* |
* Change CPU protection level to 3, enter userspace. |
* |
*/ |
void userspace(uspace_arg_t *kernel_uarg) |
{ |
ipl_t ipl; |
ipl = interrupts_disable(); |
/* Clear CF,PF,AF,ZF,SF,DF,OF */ |
ipl &= ~(0xcd4); |
__asm__ volatile ("" |
"pushq %0\n" |
"pushq %1\n" |
"pushq %2\n" |
"pushq %3\n" |
"pushq %4\n" |
"movq %5, %%rax\n" |
"iretq\n" |
: : |
"i" (gdtselector(UDATA_DES) | PL_USER), |
"r" (kernel_uarg->uspace_stack+THREAD_STACK_SIZE), |
"r" (ipl), |
"i" (gdtselector(UTEXT_DES) | PL_USER), |
"r" (kernel_uarg->uspace_entry), |
"r" (kernel_uarg->uspace_uarg) |
: "rax" |
); |
/* Unreachable */ |
for(;;) |
; |
} |
/tags/0.2.0.1/kernel/arch/amd64/src/syscall.c |
---|
0,0 → 1,62 |
/* |
* Copyright (C) 2006 Ondrej Palkovsky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - 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. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <syscall/syscall.h> |
#include <arch/syscall.h> |
#include <panic.h> |
#include <arch/cpu.h> |
#include <arch/pm.h> |
#include <arch/asm.h> |
#include <print.h> |
#include <arch/cpu.h> |
extern void syscall_entry(void); |
/** Enable & setup support for SYSCALL/SYSRET */ |
void syscall_setup_cpu(void) |
{ |
/* Enable SYSCALL/SYSRET */ |
set_efer_flag(AMD_SCE_FLAG); |
/* Setup syscall entry address */ |
/* This is _mess_ - the 64-bit CS is argument+16, |
* the SS is argument+8. The order is: |
* +0(KDATA_DES), +8(UDATA_DES), +16(UTEXT_DES) |
*/ |
write_msr(AMD_MSR_STAR, |
((__u64)(gdtselector(KDATA_DES) | PL_USER)<<48) \ |
| ((__u64)(gdtselector(KTEXT_DES) | PL_KERNEL)<<32)); |
write_msr(AMD_MSR_LSTAR, (__u64)syscall_entry); |
/* Mask RFLAGS on syscall |
* - disable interrupts, until we exchange the stack register |
* (mask the IE bit) |
*/ |
write_msr(AMD_MSR_SFMASK, 0x200); |
} |
/tags/0.2.0.1/kernel/arch/amd64/src/fpu_context.c |
---|
0,0 → 1,58 |
/* |
* Copyright (C) 2005 Jakub Vana |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - 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. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <fpu_context.h> |
#include <arch.h> |
#include <cpu.h> |
/** Save FPU (mmx, sse) context using fxsave instruction */ |
void fpu_context_save(fpu_context_t *fctx) |
{ |
__asm__ volatile ( |
"fxsave %0" |
: "=m"(*fctx) |
); |
} |
/** Restore FPU (mmx,sse) context using fxrstor instruction */ |
void fpu_context_restore(fpu_context_t *fctx) |
{ |
__asm__ volatile ( |
"fxrstor %0" |
: "=m"(*fctx) |
); |
} |
void fpu_init() |
{ |
/* TODO: Zero all SSE, MMX etc. registers */ |
__asm__ volatile ( |
"fninit;" |
); |
} |
/tags/0.2.0.1/kernel/arch/amd64/src/bios |
---|
0,0 → 1,0 |
link ../../ia32/src/bios |
Property changes: |
Added: svn:special |
+* |
\ No newline at end of property |
/tags/0.2.0.1/kernel/arch/amd64/src/drivers |
---|
0,0 → 1,0 |
link ../../ia32/src/drivers |
Property changes: |
Added: svn:special |
+* |
\ No newline at end of property |
/tags/0.2.0.1/kernel/arch/amd64/src/context.S |
---|
0,0 → 1,78 |
# |
# Copyright (C) 2001-2004 Jakub Jermar |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - 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. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. |
# |
.text |
.global context_save_arch |
.global context_restore_arch |
#include <arch/context_offset.h> |
## Save current CPU context |
# |
# Save CPU context to context_t variable |
# pointed by the 1st argument. Returns 1 in EAX. |
# |
context_save_arch: |
movq (%rsp), %rdx # the caller's return %eip |
# In %edi is passed 1st argument |
movq %rdx, OFFSET_PC(%rdi) |
movq %rsp, OFFSET_SP(%rdi) |
movq %rbx, OFFSET_RBX(%rdi) |
movq %rbp, OFFSET_RBP(%rdi) |
movq %r12, OFFSET_R12(%rdi) |
movq %r13, OFFSET_R13(%rdi) |
movq %r14, OFFSET_R14(%rdi) |
movq %r15, OFFSET_R15(%rdi) |
xorq %rax,%rax # context_save returns 1 |
incq %rax |
ret |
## Restore current CPU context |
# |
# Restore CPU context from context_t variable |
# pointed by the 1st argument. Returns 0 in EAX. |
# |
context_restore_arch: |
movq OFFSET_R15(%rdi), %r15 |
movq OFFSET_R14(%rdi), %r14 |
movq OFFSET_R13(%rdi), %r13 |
movq OFFSET_R12(%rdi), %r12 |
movq OFFSET_RBP(%rdi), %rbp |
movq OFFSET_RBX(%rdi), %rbx |
movq OFFSET_SP(%rdi), %rsp # ctx->sp -> %rsp |
movq OFFSET_PC(%rdi), %rdx |
movq %rdx,(%rsp) |
xorq %rax,%rax # context_restore returns 0 |
ret |
/tags/0.2.0.1/kernel/arch/amd64/src/delay.S |
---|
0,0 → 1,46 |
# |
# Copyright (C) 2001-2004 Jakub Jermar |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - 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. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. |
# |
# |
# Micro second delay loop functions. |
# |
.text |
.global asm_delay_loop |
.global asm_fake_loop |
asm_delay_loop: |
0: dec %rdi |
jnz 0b |
ret |
asm_fake_loop: |
0: dec %rdi |
jz 0b |
ret |