Subversion Repositories HelenOS

Compare Revisions

No changes between revisions

Ignore whitespace Rev 3342 → Rev 3343

/branches/sparc/kernel/arch/amd64/src/asm_utils.S
0,0 → 1,334
#
# 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 get_cycle
.global read_efer_flag
.global set_efer_flag
.global memsetb
.global memsetw
.global memcpy
.global memcpy_from_uspace
.global memcpy_to_uspace
.global memcpy_from_uspace_failover_address
.global memcpy_to_uspace_failover_address
 
# Wrapper for generic memsetb
memsetb:
jmp _memsetb
 
# Wrapper for generic memsetw
memsetw:
jmp _memsetw
 
#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_DST on success, 0 on failure.
*/
memcpy:
memcpy_from_uspace:
memcpy_to_uspace:
movq MEMCPY_DST, %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
 
get_cycle:
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
cld
 
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:
 
## Low-level syscall handler
#
# Registers on entry:
#
# @param rcx Userspace return address.
# @param r11 Userspace RLFAGS.
#
# @param rax Syscall number.
# @param rdi 1st syscall argument.
# @param rsi 2nd syscall argument.
# @param rdx 3rd syscall argument.
# @param r10 4th syscall argument. Used instead of RCX because the
# SYSCALL instruction clobbers it.
# @param r8 5th syscall argument.
# @param r9 6th syscall argument.
#
# @return Return value is in rax.
#
syscall_entry:
swapgs # Switch to hidden gs
#
# %gs:0 Scratch space for this thread's user RSP
# %gs:8 Address to be used as this thread's kernel RSP
#
movq %rsp, %gs:0 # Save this thread's user RSP
movq %gs:8, %rsp # Set this thread's kernel RSP
swapgs # Switch back to remain consistent
sti
pushq %rcx
pushq %r11
 
movq %r10, %rcx # Copy the 4th argument where it is expected
pushq %rax
call syscall_handler
addq $8, %rsp
popq %r11
popq %rcx
 
cli
swapgs
movq %gs:0, %rsp # Restore the user RSP
swapgs
 
sysretq
 
.data
.global interrupt_handler_size
 
interrupt_handler_size: .quad (h_end-h_start)/IDT_ITEMS
/branches/sparc/kernel/arch/amd64/src/userspace.c
0,0 → 1,83
/*
* 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.
*/
 
/** @addtogroup amd64
* @{
*/
/** @file
*/
 
#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"
/* %rdi is defined to hold pcb_ptr - set it to 0 */
"xorq %%rdi, %%rdi\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(;;)
;
}
 
/** @}
*/
/branches/sparc/kernel/arch/amd64/src/debugger.c
0,0 → 1,408
/*
* 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.
*/
 
/** @addtogroup amd64debug
* @{
*/
/** @file
*/
 
#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 {
uintptr_t 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 __attribute__((unused)))
{
unsigned int i;
char *symbol;
 
#ifdef __32_BITS__
printf("# Count Address In symbol\n");
printf("-- ----- ---------- ---------\n");
#endif
 
#ifdef __64_BITS__
printf("# Count Address In symbol\n");
printf("-- ----- ------------------ ---------\n");
#endif
for (i = 0; i < BKPOINTS_MAX; i++)
if (breakpoints[i].address) {
symbol = get_symtab_entry(breakpoints[i].address);
 
#ifdef __32_BITS__
printf("%-2u %-5d %#10zx %s\n", i,
breakpoints[i].counter, breakpoints[i].address,
symbol);
#endif
 
#ifdef __64_BITS__
printf("%-2u %-5d %#18zx %s\n", i,
breakpoints[i].counter, breakpoints[i].address,
symbol);
#endif
 
}
return 1;
}
 
/* Setup DR register according to table */
static void setup_dr(int curidx)
{
unative_t 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 {
#ifdef __32_BITS__
dr7 |= ((unative_t) 0x3) << (18 + 4 * curidx);
#endif
 
#ifdef __64_BITS__
dr7 |= ((unative_t) 0x2) << (18 + 4 * curidx);
#endif
if ((flags & BKPOINT_WRITE))
dr7 |= ((unative_t) 0x1) << (16 + 4 * curidx);
else if ((flags & BKPOINT_READ_WRITE))
dr7 |= ((unative_t) 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(const void *where, const 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 = (uintptr_t) 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 (*((unative_t *) breakpoints[slot].address) != 0)
return;
printf("*** Found ZERO on address %lx (slot %d) ***\n",
breakpoints[slot].address, slot);
} else {
printf("Data watchpoint - new data: %lx\n",
*((unative_t *) breakpoints[slot].address));
}
}
printf("Reached breakpoint %d:%lx(%s)\n", slot, getip(istate),
get_symtab_entry(getip(istate)));
printf("***Type 'exit' to exit kconsole.\n");
atomic_set(&haltstate,1);
kconsole((void *) "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)
{
unative_t bpno = argv->intval;
if (bpno > 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 __attribute__((unused)), istate_t *istate)
{
unative_t 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 __attribute__((unused)),
istate_t *istate __attribute__((unused)))
{
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
}
 
/** @}
*/
/branches/sparc/kernel/arch/amd64/src/pm.c
0,0 → 1,254
/*
* Copyright (c) 2008 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.
*/
 
/** @addtogroup amd64
* @{
*/
/** @file
*/
 
#include <arch.h>
#include <arch/pm.h>
#include <arch/asm.h>
#include <mm/as.h>
#include <mm/frame.h>
#include <memstr.h>
#include <mm/slab.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 = (uint64_t) gdt };
ptr_16_64_t idtr = {.limit = sizeof(idt), .base = (uint64_t) idt };
 
static tss_t tss;
tss_t *tss_p = NULL;
 
void gdt_tss_setbase(descriptor_t *d, uintptr_t 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, uint32_t 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, uintptr_t 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(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, ((uintptr_t) interrupt_handlers) +
i * interrupt_handler_size);
}
}
 
/** 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((uintptr_t) AS_KERNEL->genarch.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], (uintptr_t) 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));
}
 
/* Reboot the machine by initiating
* a triple fault
*/
void arch_reboot(void)
{
preemption_disable();
ipl_t ipl = interrupts_disable();
memsetb(idt, sizeof(idt), 0);
idtr_load(&idtr);
interrupts_restore(ipl);
asm volatile (
"int $0x03\n"
"cli\n"
"hlt\n"
);
}
 
/** @}
*/
/branches/sparc/kernel/arch/amd64/src/proc/thread.c
0,0 → 1,53
/*
* 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.
*/
 
/** @addtogroup amd64proc
* @{
*/
/** @file
*/
 
#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;
t->arch.syscall_rsp[SYSCALL_USTACK_RSP] = 0;
/*
* Kernel RSP can be precalculated at thread creation time.
*/
t->arch.syscall_rsp[SYSCALL_KSTACK_RSP] =
(uintptr_t) &t->kstack[PAGE_SIZE - sizeof(uint64_t)];
}
 
/** @}
*/
/branches/sparc/kernel/arch/amd64/src/proc/scheduler.c
0,0 → 1,85
/*
* 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.
*/
 
/** @addtogroup amd64proc
* @{
*/
/** @file
*/
 
#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 =
(uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE - SP_DELTA];
 
/*
* Syscall support.
*/
swapgs();
write_msr(AMD_MSR_GS, (uintptr_t)THREAD->arch.syscall_rsp);
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)
{
}
 
/** @}
*/
/branches/sparc/kernel/arch/amd64/src/proc/task.c
0,0 → 1,60
/*
* 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.
*/
 
/** @addtogroup amd64proc
* @{
*/
/** @file
*/
 
#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);
}
 
/** @}
*/
/branches/sparc/kernel/arch/amd64/src/syscall.c
0,0 → 1,73
/*
* 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.
*/
 
/** @addtogroup amd64
* @{
*/
/** @file
*/
 
#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,
((uint64_t)(gdtselector(KDATA_DES) | PL_USER) << 48) |
((uint64_t)(gdtselector(KTEXT_DES) | PL_KERNEL) << 32));
write_msr(AMD_MSR_LSTAR, (uint64_t)syscall_entry);
/* Mask RFLAGS on syscall
* - disable interrupts, until we exchange the stack register
* (mask the IF bit)
* - clear DF so that the string instructions operate in
* the right direction
*/
write_msr(AMD_MSR_SFMASK, RFLAGS_IF | RFLAGS_DF);
}
 
/** @}
*/
/branches/sparc/kernel/arch/amd64/src/boot/boot.S
0,0 → 1,677
 
# Copyright (c) 2005 Ondrej Palkovsky
# Copyright (c) 2006 Martin Decky
# Copyright (c) 2008 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/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:
cld
movl $START_STACK, %esp # initialize stack pointer
lgdtl 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
# Protected 32-bit. We want to reuse the code-seg descriptor,
# the Default operand size must not be 1 when entering long mode
movl $(INTEL_CPUID_EXTENDED), %eax
cpuid
cmp $(INTEL_CPUID_EXTENDED), %eax
ja extended_cpuid_supported
movl $extended_cpuid_msg, %esi
jmp error_halt
extended_cpuid_supported:
movl $(AMD_CPUID_EXTENDED), %eax
cpuid
bt $(AMD_EXT_LONG_MODE), %edx
jc long_mode_supported
movl $long_mode_msg, %esi
jmp error_halt
 
long_mode_supported:
bt $(AMD_EXT_NOEXECUTE), %edx
jc noexecute_supported
movl $noexecute_msg, %esi
jmp error_halt
noexecute_supported:
movl $(INTEL_CPUID_STANDARD), %eax
cpuid
bt $(INTEL_FXSAVE), %edx
jc fx_supported
movl $fx_msg, %esi
jmp error_halt
fx_supported:
bt $(INTEL_SSE2), %edx
jc sse2_supported
movl $sse2_msg, %esi
jmp error_halt
sse2_supported:
#ifdef CONFIG_FB
mov $vesa_init, %esi
mov $VESA_INIT_SEGMENT << 4, %edi
mov $e_vesa_init - vesa_init, %ecx
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
# Enable 64-bit page translation 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, e820counter
jmp invalid_boot
valid_boot:
movl (%ebx), %eax # ebx = physical address of struct multiboot_info
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
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_ATTRIBUTES_OFFSET 0
#define VESA_MODE_LIST_PTR_OFFSET 14
#define VESA_MODE_SCANLINE_OFFSET 16
#define VESA_MODE_WIDTH_OFFSET 18
#define VESA_MODE_HEIGHT_OFFSET 20
#define VESA_MODE_BPP_OFFSET 25
#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 VESA_SET_PALETTE 0x4f09
 
#define CONFIG_VESA_BPP_a 255
 
#if CONFIG_VESA_BPP == 24
#define CONFIG_VESA_BPP_VARIANT 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
 
#ifdef CONFIG_VESA_BPP_VARIANT
jz 2f
mov $CONFIG_VESA_BPP_VARIANT, %al
cmp VESA_MODE_BPP_OFFSET(%di), %al
#endif
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
 
#if CONFIG_VESA_BPP == 8
# Set 3:2:3 VGA palette
mov VESA_MODE_ATTRIBUTES_OFFSET(%di), %ax
push %di
mov $vga323 - vesa_init, %di
mov $0x100, %ecx
bt $5, %ax # Test if VGA compatible registers are present
jnc vga_compat
# Try VESA routine to set palette
mov $VESA_SET_PALETTE, %ax
xor %bl, %bl
xor %dx, %dx
int $0x10
jmp vga_not_compat
vga_compat:
# Try VGA registers to set palette
movw $0x3c6, %dx # Set palette mask
movb $0xff, %al
outb %al, %dx
movw $0x3c8, %dx # First index to set
xor %al, %al
outb %al, %dx
movw $0x3c9, %dx # Data port
vga_loop:
movb %es:2(%di), %al
outb %al, %dx
movb %es:1(%di), %al
outb %al, %dx
movb %es:(%di), %al
outb %al, %dx
addw $4, %di
loop vga_loop
vga_not_compat:
pop %di
#endif
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
 
vga323:
#include "vga323.pal"
.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
movl $START_STACK, %esp # initialize stack pointer
jmpl $gdtselector(KTEXT32_DES), $vesa_meeting_point
.align 4
e_vesa_init:
#endif
 
# Print string from %esi to EGA display (in red) and halt
error_halt:
movl $0xb8000, %edi # base of EGA text mode memory
xorl %eax, %eax
movw $0x3d4, %dx # read bits 8 - 15 of the cursor address
movb $0xe, %al
outb %al, %dx
movw $0x3d5, %dx
inb %dx, %al
shl $8, %ax
movw $0x3d4, %dx # read bits 0 - 7 of the cursor address
movb $0xf, %al
outb %al, %dx
movw $0x3d5, %dx
inb %dx, %al
cmp $1920, %ax
jbe cursor_ok
movw $1920, %ax # sanity check for the cursor on the last line
cursor_ok:
movw %ax, %bx
shl $1, %eax
addl %eax, %edi
movw $0x0c00, %ax # black background, light red foreground
ploop:
lodsb
cmp $0, %al
je ploop_end
stosw
inc %bx
jmp ploop
ploop_end:
movw $0x3d4, %dx # write bits 8 - 15 of the cursor address
movb $0xe, %al
outb %al, %dx
movw $0x3d5, %dx
movb %bh, %al
outb %al, %dx
movw $0x3d4, %dx # write bits 0 - 7 of the cursor address
movb $0xf, %al
outb %al, %dx
movw $0x3d5, %dx
movb %bl, %al
outb %al, %dx
cli
hlt
 
.section K_INI_PTLS, "aw", @progbits
 
#
# Macro for generating initial page table contents.
# @param cnt Number of entries to generat. Must be multiple of 8.
# @param g Number of GB that will be added to the mapping.
#
.macro ptl2gen cnt g
.if \cnt
ptl2gen "\cnt - 8" \g
.quad ((\cnt - 8) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
.quad ((\cnt - 7) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
.quad ((\cnt - 6) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
.quad ((\cnt - 5) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
.quad ((\cnt - 4) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
.quad ((\cnt - 3) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
.quad ((\cnt - 2) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
.quad ((\cnt - 1) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
.endif
.endm
 
# Page table for pages in the first gigabyte.
.align 4096
.global ptl_2_0g
ptl_2_0g:
ptl2gen 512 0
 
# Page table for pages in the second gigabyte.
.align 4096
.global ptl_2_1g
ptl_2_1g:
ptl2gen 512 1
 
# Page table for pages in the third gigabyte.
.align 4096
.global ptl_2_2g
ptl_2_2g:
ptl2gen 512 2
 
# Page table for pages in the fourth gigabyte.
.align 4096
.global ptl_2_3g
ptl_2_3g:
ptl2gen 512 3
 
.align 4096
.global ptl_1
ptl_1:
# Identity mapping for [0; 4G)
.quad ptl_2_0g + (PTL_WRITABLE | PTL_PRESENT)
.quad ptl_2_1g + (PTL_WRITABLE | PTL_PRESENT)
.quad ptl_2_2g + (PTL_WRITABLE | PTL_PRESENT)
.quad ptl_2_3g + (PTL_WRITABLE | PTL_PRESENT)
.fill 506, 8, 0
# Mapping of [0; 1G) at -2G
.quad ptl_2_0g + (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)
 
.section K_DATA_START, "aw", @progbits
 
.global bootstrap_gdtr
bootstrap_gdtr:
.word gdtselector(GDT_ITEMS)
.long KA2PA(gdt)
 
grub_eax:
.long 0
 
grub_ebx:
.long 0
 
extended_cpuid_msg:
.asciz "Extended CPUID not supported. System halted."
long_mode_msg:
.asciz "64 bit long mode not supported. System halted."
noexecute_msg:
.asciz "No-execute pages not supported. System halted."
fx_msg:
.asciz "FXSAVE/FXRESTORE instructions not supported. System halted."
sse2_msg:
.asciz "SSE2 instructions not supported. System halted."
/branches/sparc/kernel/arch/amd64/src/boot/memmap.c
0,0 → 1,41
/*
* 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.
*/
 
/** @addtogroup amd64mm
* @{
*/
/** @file
*/
 
#include <arch/boot/memmap.h>
 
uint8_t e820counter = 0xff;
e820memmap_t e820table[MEMMAP_E820_MAX_RECORDS];
 
/** @}
*/
/branches/sparc/kernel/arch/amd64/src/boot/vga323.pal
0,0 → 1,0
link ../../../ia32/src/boot/vga323.pal
Property changes:
Added: svn:special
+*
\ No newline at end of property
/branches/sparc/kernel/arch/amd64/src/cpu/cpu.c
0,0 → 1,173
/*
* 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.
*/
 
/** @addtogroup amd64
* @{
*/
/** @file
*/
 
#include <cpu.h>
#include <arch/cpu.h>
#include <arch/cpuid.h>
#include <arch/pm.h>
 
#include <arch.h>
#include <arch/types.h>
#include <print.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] -
((uint8_t *) 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);
}
 
/** @}
*/
/branches/sparc/kernel/arch/amd64/src/context.S
0,0 → 1,64
#
# 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
CONTEXT_SAVE_ARCH_CORE %rdi %rdx
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:
 
CONTEXT_RESTORE_ARCH_CORE %rdi %rdx
 
movq %rdx,(%rsp)
 
xorq %rax,%rax # context_restore returns 0
ret
/branches/sparc/kernel/arch/amd64/src/mm/page.c
0,0 → 1,218
/*
* 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.
*/
 
/** @addtogroup amd64mm
* @{
*/
/** @file
*/
 
#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), (uintptr_t)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), (uintptr_t)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), (uintptr_t)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), (uintptr_t)KA2PA(tgt)); \
SET_FRAME_FLAGS_ARCH(ptl3, PTL3_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \
}
 
 
void page_arch_init(void)
{
uintptr_t cur;
unsigned int i;
int identity_flags = PAGE_CACHEABLE | PAGE_EXEC | PAGE_GLOBAL | PAGE_WRITE;
 
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 (cur = config.stack_base; cur < config.stack_base + config.stack_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].addr + 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((uintptr_t) AS_KERNEL->genarch.page_table);
} else
write_cr3((uintptr_t) AS_KERNEL->genarch.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)
{
uintptr_t page;
static uintptr_t 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)
{
uintptr_t 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);
 
decode_istate(n, istate);
printf("Page fault address: %llx\n", page);
panic("page fault\n");
}
}
 
 
uintptr_t hw_map(uintptr_t 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)
uintptr_t 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 | PAGE_WRITE);
last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE);
return virtaddr;
}
 
/** @}
*/
/branches/sparc/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
/branches/sparc/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
/branches/sparc/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
/branches/sparc/kernel/arch/amd64/src/amd64.c
0,0 → 1,222
/*
* 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.
*/
 
/** @addtogroup amd64
* @{
*/
/** @file
*/
 
#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/kbd/i8042.h>
#include <arch/drivers/i8254.h>
#include <arch/drivers/i8259.h>
 
#ifdef CONFIG_SMP
#include <arch/smp/apic.h>
#endif
 
#include <arch/bios/bios.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>
#include <ddi/irq.h>
#include <ddi/device.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\n"
"pop %%rax\n"
"and $~(0x7000), %%rax\n"
"pushq %%rax\n"
"popfq\n"
:
:
: "%rax"
);
}
 
/** Disable alignment check
*
* Clean AM(18) flag in CR0 register
*/
static void clean_AM_flag(void)
{
asm (
"mov %%cr0, %%rax\n"
"and $~(0x40000), %%rax\n"
"mov %%rax, %%cr0\n"
:
:
: "%rax"
);
}
 
void arch_pre_mm_init(void)
{
/* 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) {
interrupt_init();
bios_init();
/* PIC */
i8259_init();
}
}
 
 
void arch_post_mm_init(void)
{
if (config.cpu_active == 1) {
/* Initialize IRQ routing */
irq_init(IRQ_COUNT, IRQ_COUNT);
/* hard clock */
i8254_init();
#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_post_cpu_init()
{
#ifdef CONFIG_SMP
if (config.cpu_active > 1) {
l_apic_init();
l_apic_debug();
}
#endif
}
 
void arch_pre_smp_init(void)
{
if (config.cpu_active == 1) {
#ifdef CONFIG_SMP
acpi_init();
#endif /* CONFIG_SMP */
}
}
 
void arch_post_smp_init(void)
{
/* keyboard controller */
i8042_init(device_assign_devno(), IRQ_KBD, device_assign_devno(), IRQ_MOUSE);
}
 
void calibrate_delay_loop(void)
{
i8254_calibrate_delay_loop();
if (config.cpu_active == 1) {
/*
* This has to be done only on UP.
* On SMP, i8254 is not used for time keeping and its interrupt pin remains masked.
*/
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.
*/
unative_t sys_tls_set(unative_t 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();
}
 
/** @}
*/
/branches/sparc/kernel/arch/amd64/src/smp/ap.S
0,0 → 1,114
#
# Copyright (c) 2008 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 */
/branches/sparc/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
/branches/sparc/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
/branches/sparc/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
/branches/sparc/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
/branches/sparc/kernel/arch/amd64/src/ddi/ddi.c
0,0 → 1,169
/*
* 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.
*/
 
/** @addtogroup amd64ddi
* @{
*/
/** @file
*/
 
#include <ddi/ddi.h>
#include <arch/ddi/ddi.h>
#include <proc/task.h>
#include <arch/types.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, uintptr_t 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;
uint8_t *newmap;
/*
* The I/O permission bitmap is too small and needs to be grown.
*/
newmap = (uint8_t *) 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;
}
 
/** @}
*/
/branches/sparc/kernel/arch/amd64/src/interrupt.c
0,0 → 1,236
/*
* 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.
*/
 
/** @addtogroup amd64interrupt
* @{
*/
/** @file
*/
 
#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 <ddi/irq.h>
 
/*
* Interrupt and exception dispatching.
*/
 
void (* disable_irqs_function)(uint16_t irqmask) = NULL;
void (* enable_irqs_function)(uint16_t irqmask) = NULL;
void (* eoi_function)(void) = NULL;
 
void decode_istate(int n, istate_t *istate)
{
char *symbol;
/* uint64_t *x = &istate->stack[0]; */
 
if (!(symbol = get_symtab_entry(istate->rip)))
symbol = "";
 
printf("-----EXCEPTION(%d) OCCURED----- ( %s )\n", n, __func__);
printf("%%rip: %#llx (%s)\n", istate->rip, symbol);
printf("ERROR_WORD=%#llx\n", istate->error_word);
printf("%%cs=%#llx, rflags=%#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]);
}
 
static void trap_virtual_eoi(void)
{
if (eoi_function)
eoi_function();
else
panic("no eoi_function\n");
 
}
 
static void null_interrupt(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "unserviced interrupt: %d", n);
decode_istate(n, istate);
panic("unserviced interrupt\n");
}
 
/** General Protection Fault. */
static 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");
}
 
decode_istate(n, istate);
panic("general protection fault\n");
}
 
static void ss_fault(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "stack fault");
decode_istate(n, istate);
panic("stack fault\n");
}
 
static 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
}
 
static void tlb_shootdown_ipi(int n, istate_t *istate)
{
trap_virtual_eoi();
tlb_shootdown_ipi_recv();
}
 
/** Handler of IRQ exceptions */
static void irq_interrupt(int n, istate_t *istate)
{
ASSERT(n >= IVT_IRQBASE);
int inum = n - IVT_IRQBASE;
bool ack = false;
ASSERT(inum < IRQ_COUNT);
ASSERT((inum != IRQ_PIC_SPUR) && (inum != IRQ_PIC1));
irq_t *irq = irq_dispatch_and_lock(inum);
if (irq) {
/*
* The IRQ handler was found.
*/
if (irq->preack) {
/* Send EOI before processing the interrupt */
trap_virtual_eoi();
ack = true;
}
irq->handler(irq, irq->arg);
spinlock_unlock(&irq->lock);
} else {
/*
* Spurious interrupt.
*/
#ifdef CONFIG_DEBUG
printf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, inum);
#endif
}
if (!ack)
trap_virtual_eoi();
}
 
void interrupt_init(void)
{
int i;
for (i = 0; i < IVT_ITEMS; i++)
exc_register(i, "null", (iroutine) null_interrupt);
for (i = 0; i < IRQ_COUNT; i++) {
if ((i != IRQ_PIC_SPUR) && (i != IRQ_PIC1))
exc_register(IVT_IRQBASE + i, "irq",
(iroutine) irq_interrupt);
}
exc_register(7, "nm_fault", (iroutine) nm_fault);
exc_register(12, "ss_fault", (iroutine) ss_fault);
exc_register(13, "gp_fault", (iroutine) gp_fault);
exc_register(14, "ident_mapper", (iroutine) ident_page_fault);
#ifdef CONFIG_SMP
exc_register(VECTOR_TLB_SHOOTDOWN_IPI, "tlb_shootdown",
(iroutine) tlb_shootdown_ipi);
#endif
}
 
void trap_virtual_enable_irqs(uint16_t irqmask)
{
if (enable_irqs_function)
enable_irqs_function(irqmask);
else
panic("no enable_irqs_function\n");
}
 
void trap_virtual_disable_irqs(uint16_t irqmask)
{
if (disable_irqs_function)
disable_irqs_function(irqmask);
else
panic("no disable_irqs_function\n");
}
 
/** @}
*/
/branches/sparc/kernel/arch/amd64/src/fpu_context.c
0,0 → 1,65
/*
* 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.
*/
 
/** @addtogroup amd64
* @{
*/
/** @file
*
*/
 
#include <fpu_context.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;"
);
}
 
/** @}
*/
/branches/sparc/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
/branches/sparc/kernel/arch/amd64/src/bios
0,0 → 1,0
link ../../ia32/src/bios
Property changes:
Added: svn:special
+*
\ No newline at end of property
/branches/sparc/kernel/arch/amd64/src/drivers
0,0 → 1,0
link ../../ia32/src/drivers
Property changes:
Added: svn:special
+*
\ No newline at end of property