/kernel/trunk/arch/ia64/src/start.S |
---|
0,0 → 1,132 |
# |
# Copyright (C) 2005 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/register.h> |
#include <arch/mm/page.h> |
#include <arch/mm/asid.h> |
#include <mm/asid.h> |
#define RR_MASK (0xFFFFFFFF00000002) |
#define RID_SHIFT 8 |
#define PS_SHIFT 2 |
#define KERNEL_TRANSLATION_I 0x0010000000000661 |
#define KERNEL_TRANSLATION_D 0x0010000000000661 |
.section K_TEXT_START, "ax" |
.global kernel_image_start |
stack0: |
kernel_image_start: |
.auto |
# Fill TR.i and TR.d using Region Register #VRN_KERNEL |
movl r8=(VRN_KERNEL<<VRN_SHIFT) |
mov r9=rr[r8] |
movl r10=(RR_MASK) |
and r9=r10,r9 |
movl r10=((RID_KERNEL<<RID_SHIFT)|(KERNEL_PAGE_WIDTH<<PS_SHIFT)) |
or r9=r10,r9 |
mov rr[r8]=r9 |
movl r8=(VRN_KERNEL<<VRN_SHIFT) |
mov cr.ifa=r8 |
movl r10=(KERNEL_PAGE_WIDTH<<PS_SHIFT) |
mov cr.itir=r10 |
movl r10=(KERNEL_TRANSLATION_I) |
itr.i itr[r0]=r10 |
movl r10=(KERNEL_TRANSLATION_D) |
itr.d dtr[r0]=r10 |
# initialize PSR |
mov psr.l = r0 |
srlz.i |
srlz.d |
movl r10=(PSR_DT_MASK|PSR_RT_MASK|PSR_IT_MASK|PSR_IC_MASK) /* Enable paging */ |
mov r9=psr |
or r10=r10,r9 |
mov cr.ipsr=r10 |
mov cr.ifs=r0 |
movl r8=paging_start |
mov cr.iip=r8 |
srlz.d |
srlz.i |
.explicit |
/* |
* Return From Interupt is the only the way to fill upper half word of PSR. |
*/ |
rfi;; |
.global paging_start |
paging_start: |
/* |
* Now we are paging. |
*/ |
# switch to register bank 1 |
bsw.1 |
# initialize register stack |
mov ar.rsc = r0 |
movl r8=(VRN_KERNEL<<VRN_SHIFT) ;; |
mov ar.bspstore = r8 |
loadrs |
# initialize memory stack to some sane value |
movl r12 = stack0;; |
add r12 = - 16, r12 /* allocate a scratch area on the stack */ |
# initialize gp (Global Pointer) register |
movl r1 = _hardcoded_load_address |
/* |
* Initialize hardcoded_* variables. |
*/ |
movl r14 = _hardcoded_ktext_size |
movl r15 = _hardcoded_kdata_size |
movl r16 = _hardcoded_load_address ;; |
addl r17 = @gprel(hardcoded_ktext_size), gp |
addl r18 = @gprel(hardcoded_kdata_size), gp |
addl r19 = @gprel(hardcoded_load_address), gp |
;; |
st8 [r17] = r14 |
st8 [r18] = r15 |
st8 [r19] = r16 |
movl r18=main_bsp ;; |
mov b1=r18 ;; |
br.call.sptk.many b0=b1 |
0: |
br 0b |
/kernel/trunk/arch/ia64/src/ivt.S |
---|
0,0 → 1,473 |
# |
# Copyright (C) 2005 Jakub Vana |
# Copyright (C) 2005 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/stack.h> |
#include <arch/register.h> |
#include <arch/mm/page.h> |
#include <align.h> |
#define STACK_ITEMS 18 |
#define STACK_FRAME_SIZE ALIGN_UP((STACK_ITEMS*STACK_ITEM_SIZE) + STACK_SCRATCH_AREA_SIZE, STACK_ALIGNMENT) |
#if (STACK_ITEMS % 2 == 0) |
# define STACK_FRAME_BIAS 8 |
#else |
# define STACK_FRAME_BIAS 16 |
#endif |
/** Partitioning of bank 0 registers. */ |
#define R_OFFS r16 |
#define R_HANDLER r17 |
#define R_RET r18 |
#define R_TMP r19 |
#define R_KSTACK_BSP r22 /* keep in sync with before_thread_runs_arch() */ |
#define R_KSTACK r23 /* keep in sync with before_thread_runs_arch() */ |
/** Heavyweight interrupt handler |
* |
* This macro roughly follows steps from 1 to 19 described in |
* Intel Itanium Architecture Software Developer's Manual, Chapter 3.4.2. |
* |
* HEAVYWEIGHT_HANDLER macro must cram into 16 bundles (48 instructions). |
* This goal is achieved by using procedure calls after RSE becomes operational. |
* |
* Some steps are skipped (enabling and disabling interrupts). |
* Some steps are not fully supported yet (e.g. dealing with floating-point |
* context). |
* |
* @param offs Offset from the beginning of IVT. |
* @param handler Interrupt handler address. |
*/ |
.macro HEAVYWEIGHT_HANDLER offs, handler=universal_handler |
.org ivt + \offs |
mov R_OFFS = \offs |
movl R_HANDLER = \handler ;; |
br heavyweight_handler |
.endm |
.global heavyweight_handler |
heavyweight_handler: |
/* 1. copy interrupt registers into bank 0 */ |
/* |
* Note that r24-r31 from bank 0 can be used only as long as PSR.ic = 0. |
*/ |
mov r24 = cr.iip |
mov r25 = cr.ipsr |
mov r26 = cr.iipa |
mov r27 = cr.isr |
mov r28 = cr.ifa |
/* 2. preserve predicate register into bank 0 */ |
mov r29 = pr ;; |
/* 3. switch to kernel memory stack */ |
mov r30 = cr.ipsr |
shr.u r31 = r12, VRN_SHIFT ;; |
shr.u r30 = r30, PSR_CPL_SHIFT ;; |
and r30 = PSR_CPL_MASK_SHIFTED, r30 ;; |
/* |
* Set p3 to true if the interrupted context executed in kernel mode. |
* Set p4 to false if the interrupted context didn't execute in kernel mode. |
*/ |
cmp.eq p3, p4 = r30, r0 ;; |
cmp.eq p1, p2 = r30, r0 ;; /* remember IPSR setting in p1 and p2 */ |
/* |
* Set p3 to true if the stack register references kernel address space. |
* Set p4 to false if the stack register doesn't reference kernel address space. |
*/ |
(p3) cmp.eq p3, p4 = VRN_KERNEL, r31 ;; |
/* |
* Now, p4 is true iff the stack needs to be switched to kernel stack. |
*/ |
mov r30 = r12 |
(p4) mov r12 = R_KSTACK ;; |
add r31 = -STACK_FRAME_BIAS, r12 ;; |
add r12 = -STACK_FRAME_SIZE, r12 |
/* 4. save registers in bank 0 into memory stack */ |
/* |
* If this is break_instruction handler, |
* copy input parameters to stack. |
*/ |
mov R_TMP = 0x2c00 ;; |
cmp.eq p6,p5 = R_OFFS, R_TMP ;; |
/* |
* From now on, if this is break_instruction handler, p6 is true and p5 is false. |
* Otherwise p6 is false and p5 is true. |
* Note that p5 is a preserved predicate register and we make use of it. |
*/ |
(p6) st8 [r31] = r35, -8 ;; /* save in3 */ |
(p6) st8 [r31] = r34, -8 ;; /* save in2 */ |
(p6) st8 [r31] = r33, -8 ;; /* save in1 */ |
(p6) st8 [r31] = r32, -8 ;; /* save in0 */ |
(p5) add r31 = -32, r31 ;; |
st8 [r31] = r30, -8 ;; /* save old stack pointer */ |
st8 [r31] = r29, -8 ;; /* save predicate registers */ |
st8 [r31] = r24, -8 ;; /* save cr.iip */ |
st8 [r31] = r25, -8 ;; /* save cr.ipsr */ |
st8 [r31] = r26, -8 ;; /* save cr.iipa */ |
st8 [r31] = r27, -8 ;; /* save cr.isr */ |
st8 [r31] = r28, -8 ;; /* save cr.ifa */ |
/* 5. RSE switch from interrupted context */ |
mov r24 = ar.rsc |
mov r25 = ar.pfs |
cover |
mov r26 = cr.ifs |
st8 [r31] = r24, -8 ;; /* save ar.rsc */ |
st8 [r31] = r25, -8 ;; /* save ar.pfs */ |
st8 [r31] = r26, -8 /* save ar.ifs */ |
and r24 = ~(RSC_PL_MASK), r24 ;; |
and r30 = ~(RSC_MODE_MASK), r24 ;; |
mov ar.rsc = r30 ;; /* update RSE state */ |
mov r27 = ar.rnat |
mov r28 = ar.bspstore ;; |
/* |
* Inspect BSPSTORE to figure out whether it is necessary to switch to kernel BSPSTORE. |
*/ |
(p1) shr.u r30 = r28, VRN_SHIFT ;; |
(p1) cmp.eq p1, p2 = VRN_KERNEL, r30 ;; |
/* |
* If BSPSTORE needs to be switched, p1 is false and p2 is true. |
*/ |
(p1) mov r30 = r28 |
(p2) mov r30 = R_KSTACK_BSP ;; |
(p2) mov ar.bspstore = r30 ;; |
mov r29 = ar.bsp |
st8 [r31] = r27, -8 ;; /* save ar.rnat */ |
st8 [r31] = r30, -8 ;; /* save new value written to ar.bspstore */ |
st8 [r31] = r28, -8 ;; /* save ar.bspstore */ |
st8 [r31] = r29, -8 /* save ar.bsp */ |
mov ar.rsc = r24 /* restore RSE's setting + kernel privileges */ |
/* steps 6 - 15 are done by heavyweight_handler_inner() */ |
mov R_RET = b0 /* save b0 belonging to interrupted context */ |
br.call.sptk.many b0 = heavyweight_handler_inner |
0: mov b0 = R_RET /* restore b0 belonging to the interrupted context */ |
/* 16. RSE switch to interrupted context */ |
cover /* allocate zerro size frame (step 1 (from Intel Docs)) */ |
add r31 = STACK_SCRATCH_AREA_SIZE, r12 ;; |
ld8 r30 = [r31], +8 ;; /* load ar.bsp */ |
ld8 r29 = [r31], +8 ;; /* load ar.bspstore */ |
ld8 r28 = [r31], +8 ;; /* load ar.bspstore_new */ |
sub r27 = r30 , r28 ;; /* calculate loadrs (step 2) */ |
shl r27 = r27, 16 |
mov r24 = ar.rsc ;; |
and r30 = ~3, r24 ;; |
or r24 = r30 , r27 ;; |
mov ar.rsc = r24 ;; /* place RSE in enforced lazy mode */ |
loadrs /* (step 3) */ |
ld8 r27 = [r31], +8 ;; /* load ar.rnat */ |
ld8 r26 = [r31], +8 ;; /* load cr.ifs */ |
ld8 r25 = [r31], +8 ;; /* load ar.pfs */ |
ld8 r24 = [r31], +8 ;; /* load ar.rsc */ |
mov ar.bspstore = r29 ;; /* (step 4) */ |
mov ar.rnat = r27 /* (step 5) */ |
mov ar.pfs = r25 /* (step 6) */ |
mov cr.ifs = r26 |
mov ar.rsc = r24 /* (step 7) */ |
/* 17. restore interruption state from memory stack */ |
ld8 r28 = [r31], +8 ;; /* load cr.ifa */ |
ld8 r27 = [r31], +8 ;; /* load cr.isr */ |
ld8 r26 = [r31], +8 ;; /* load cr.iipa */ |
ld8 r25 = [r31], +8 ;; /* load cr.ipsr */ |
ld8 r24 = [r31], +8 ;; /* load cr.iip */ |
mov cr.iip = r24 |
mov cr.ipsr = r25 |
mov cr.iipa = r26 |
mov cr.isr = r27 |
mov cr.ifa = r28 |
/* 18. restore predicate registers from memory stack */ |
ld8 r29 = [r31], +8 ;; /* load predicate registers */ |
mov pr = r29 |
/* 19. return from interruption */ |
ld8 r12 = [r31] /* load stack pointer */ |
rfi ;; |
.global heavyweight_handler_inner |
heavyweight_handler_inner: |
/* |
* From this point, the rest of the interrupted context |
* will be preserved in stacked registers and backing store. |
*/ |
alloc loc0 = ar.pfs, 0, 47, 2, 0 ;; |
/* bank 0 is going to be shadowed, copy essential data from there */ |
mov loc1 = R_RET /* b0 belonging to interrupted context */ |
mov loc2 = R_HANDLER |
mov out0 = R_OFFS |
add out1 = STACK_SCRATCH_AREA_SIZE, r12 |
/* 6. switch to bank 1 and reenable PSR.ic */ |
ssm PSR_IC_MASK |
bsw.1 ;; |
srlz.d |
/* 7. preserve branch and application registers */ |
mov loc3 = ar.unat |
mov loc4 = ar.lc |
mov loc5 = ar.ec |
mov loc6 = ar.ccv |
mov loc7 = ar.csd |
mov loc8 = ar.ssd |
mov loc9 = b0 |
mov loc10 = b1 |
mov loc11 = b2 |
mov loc12 = b3 |
mov loc13 = b4 |
mov loc14 = b5 |
mov loc15 = b6 |
mov loc16 = b7 |
/* 8. preserve general and floating-point registers */ |
/* TODO: save floating-point context */ |
mov loc17 = r1 |
mov loc18 = r2 |
mov loc19 = r3 |
mov loc20 = r4 |
mov loc21 = r5 |
mov loc22 = r6 |
mov loc23 = r7 |
(p5) mov loc24 = r8 /* only if not in break_instruction handler */ |
mov loc25 = r9 |
mov loc26 = r10 |
mov loc27 = r11 |
/* skip r12 (stack pointer) */ |
mov loc28 = r13 |
mov loc29 = r14 |
mov loc30 = r15 |
mov loc31 = r16 |
mov loc32 = r17 |
mov loc33 = r18 |
mov loc34 = r19 |
mov loc35 = r20 |
mov loc36 = r21 |
mov loc37 = r22 |
mov loc38 = r23 |
mov loc39 = r24 |
mov loc40 = r25 |
mov loc41 = r26 |
mov loc42 = r27 |
mov loc43 = r28 |
mov loc44 = r29 |
mov loc45 = r30 |
mov loc46 = r31 |
/* 9. skipped (will not enable interrupts) */ |
/* |
* ssm PSR_I_MASK |
* ;; |
* srlz.d |
*/ |
/* 10. call handler */ |
movl r1 = _hardcoded_load_address |
mov b1 = loc2 |
br.call.sptk.many b0 = b1 |
/* 11. return from handler */ |
0: |
/* 12. skipped (will not disable interrupts) */ |
/* |
* rsm PSR_I_MASK |
* ;; |
* srlz.d |
*/ |
/* 13. restore general and floating-point registers */ |
/* TODO: restore floating-point context */ |
mov r1 = loc17 |
mov r2 = loc18 |
mov r3 = loc19 |
mov r4 = loc20 |
mov r5 = loc21 |
mov r6 = loc22 |
mov r7 = loc23 |
(p5) mov r8 = loc24 /* only if not in break_instruction handler */ |
mov r9 = loc25 |
mov r10 = loc26 |
mov r11 = loc27 |
/* skip r12 (stack pointer) */ |
mov r13 = loc28 |
mov r14 = loc29 |
mov r15 = loc30 |
mov r16 = loc31 |
mov r17 = loc32 |
mov r18 = loc33 |
mov r19 = loc34 |
mov r20 = loc35 |
mov r21 = loc36 |
mov r22 = loc37 |
mov r23 = loc38 |
mov r24 = loc39 |
mov r25 = loc40 |
mov r26 = loc41 |
mov r27 = loc42 |
mov r28 = loc43 |
mov r29 = loc44 |
mov r30 = loc45 |
mov r31 = loc46 |
/* 14. restore branch and application registers */ |
mov ar.unat = loc3 |
mov ar.lc = loc4 |
mov ar.ec = loc5 |
mov ar.ccv = loc6 |
mov ar.csd = loc7 |
mov ar.ssd = loc8 |
mov b0 = loc9 |
mov b1 = loc10 |
mov b2 = loc11 |
mov b3 = loc12 |
mov b4 = loc13 |
mov b5 = loc14 |
mov b6 = loc15 |
mov b7 = loc16 |
/* 15. disable PSR.ic and switch to bank 0 */ |
rsm PSR_IC_MASK |
bsw.0 ;; |
srlz.d |
mov R_RET = loc1 |
mov ar.pfs = loc0 |
br.ret.sptk.many b0 |
.global ivt |
.align 32768 |
ivt: |
HEAVYWEIGHT_HANDLER 0x0000 |
HEAVYWEIGHT_HANDLER 0x0400 |
HEAVYWEIGHT_HANDLER 0x0800 |
HEAVYWEIGHT_HANDLER 0x0c00 alternate_instruction_tlb_fault |
HEAVYWEIGHT_HANDLER 0x1000 alternate_data_tlb_fault |
HEAVYWEIGHT_HANDLER 0x1400 data_nested_tlb_fault |
HEAVYWEIGHT_HANDLER 0x1800 |
HEAVYWEIGHT_HANDLER 0x1c00 |
HEAVYWEIGHT_HANDLER 0x2000 data_dirty_bit_fault |
HEAVYWEIGHT_HANDLER 0x2400 instruction_access_bit_fault |
HEAVYWEIGHT_HANDLER 0x2800 data_access_bit_fault |
HEAVYWEIGHT_HANDLER 0x2c00 break_instruction |
HEAVYWEIGHT_HANDLER 0x3000 external_interrupt /* For external interrupt, heavyweight handler is used. */ |
HEAVYWEIGHT_HANDLER 0x3400 |
HEAVYWEIGHT_HANDLER 0x3800 |
HEAVYWEIGHT_HANDLER 0x3c00 |
HEAVYWEIGHT_HANDLER 0x4000 |
HEAVYWEIGHT_HANDLER 0x4400 |
HEAVYWEIGHT_HANDLER 0x4800 |
HEAVYWEIGHT_HANDLER 0x4c00 |
HEAVYWEIGHT_HANDLER 0x5000 page_not_present |
HEAVYWEIGHT_HANDLER 0x5100 |
HEAVYWEIGHT_HANDLER 0x5200 |
HEAVYWEIGHT_HANDLER 0x5300 |
HEAVYWEIGHT_HANDLER 0x5400 general_exception |
HEAVYWEIGHT_HANDLER 0x5500 |
HEAVYWEIGHT_HANDLER 0x5600 |
HEAVYWEIGHT_HANDLER 0x5700 |
HEAVYWEIGHT_HANDLER 0x5800 |
HEAVYWEIGHT_HANDLER 0x5900 |
HEAVYWEIGHT_HANDLER 0x5a00 |
HEAVYWEIGHT_HANDLER 0x5b00 |
HEAVYWEIGHT_HANDLER 0x5c00 |
HEAVYWEIGHT_HANDLER 0x5d00 |
HEAVYWEIGHT_HANDLER 0x5e00 |
HEAVYWEIGHT_HANDLER 0x5f00 |
HEAVYWEIGHT_HANDLER 0x6000 |
HEAVYWEIGHT_HANDLER 0x6100 |
HEAVYWEIGHT_HANDLER 0x6200 |
HEAVYWEIGHT_HANDLER 0x6300 |
HEAVYWEIGHT_HANDLER 0x6400 |
HEAVYWEIGHT_HANDLER 0x6500 |
HEAVYWEIGHT_HANDLER 0x6600 |
HEAVYWEIGHT_HANDLER 0x6700 |
HEAVYWEIGHT_HANDLER 0x6800 |
HEAVYWEIGHT_HANDLER 0x6900 |
HEAVYWEIGHT_HANDLER 0x6a00 |
HEAVYWEIGHT_HANDLER 0x6b00 |
HEAVYWEIGHT_HANDLER 0x6c00 |
HEAVYWEIGHT_HANDLER 0x6d00 |
HEAVYWEIGHT_HANDLER 0x6e00 |
HEAVYWEIGHT_HANDLER 0x6f00 |
HEAVYWEIGHT_HANDLER 0x7000 |
HEAVYWEIGHT_HANDLER 0x7100 |
HEAVYWEIGHT_HANDLER 0x7200 |
HEAVYWEIGHT_HANDLER 0x7300 |
HEAVYWEIGHT_HANDLER 0x7400 |
HEAVYWEIGHT_HANDLER 0x7500 |
HEAVYWEIGHT_HANDLER 0x7600 |
HEAVYWEIGHT_HANDLER 0x7700 |
HEAVYWEIGHT_HANDLER 0x7800 |
HEAVYWEIGHT_HANDLER 0x7900 |
HEAVYWEIGHT_HANDLER 0x7a00 |
HEAVYWEIGHT_HANDLER 0x7b00 |
HEAVYWEIGHT_HANDLER 0x7c00 |
HEAVYWEIGHT_HANDLER 0x7d00 |
HEAVYWEIGHT_HANDLER 0x7e00 |
HEAVYWEIGHT_HANDLER 0x7f00 |
/kernel/trunk/arch/ia64/src/interrupt.c |
---|
0,0 → 1,221 |
/* |
* Copyright (C) 2005 Jakub Jermar |
* 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 <arch/interrupt.h> |
#include <panic.h> |
#include <print.h> |
#include <console/console.h> |
#include <arch/types.h> |
#include <arch/asm.h> |
#include <arch/barrier.h> |
#include <arch/register.h> |
#include <arch/drivers/it.h> |
#include <arch.h> |
#include <symtab.h> |
#include <debug.h> |
#include <syscall/syscall.h> |
#include <print.h> |
#define VECTORS_64_BUNDLE 20 |
#define VECTORS_16_BUNDLE 48 |
#define VECTORS_16_BUNDLE_START 0x5000 |
#define VECTOR_MAX 0x7f00 |
#define BUNDLE_SIZE 16 |
char *vector_names_64_bundle[VECTORS_64_BUNDLE] = { |
"VHPT Translation vector", |
"Instruction TLB vector", |
"Data TLB vector", |
"Alternate Instruction TLB vector", |
"Alternate Data TLB vector", |
"Data Nested TLB vector", |
"Instruction Key Miss vector", |
"Data Key Miss vector", |
"Dirty-Bit vector", |
"Instruction Access-Bit vector", |
"Data Access-Bit vector" |
"Break Instruction vector", |
"External Interrupt vector" |
"Reserved", |
"Reserved", |
"Reserved", |
"Reserved", |
"Reserved", |
"Reserved", |
"Reserved" |
}; |
char *vector_names_16_bundle[VECTORS_16_BUNDLE] = { |
"Page Not Present vector", |
"Key Permission vector", |
"Instruction Access rights vector", |
"Data Access Rights vector", |
"General Exception vector", |
"Disabled FP-Register vector", |
"NaT Consumption vector", |
"Speculation vector", |
"Reserved", |
"Debug vector", |
"Unaligned Reference vector", |
"Unsupported Data Reference vector", |
"Floating-point Fault vector", |
"Floating-point Trap vector", |
"Lower-Privilege Transfer Trap vector", |
"Taken Branch Trap vector", |
"Single STep Trap vector", |
"Reserved", |
"Reserved", |
"Reserved", |
"Reserved", |
"Reserved", |
"Reserved", |
"Reserved", |
"Reserved", |
"IA-32 Exception vector", |
"IA-32 Intercept vector", |
"IA-32 Interrupt vector", |
"Reserved", |
"Reserved", |
"Reserved" |
}; |
static char *vector_to_string(__u16 vector); |
static void dump_interrupted_context(struct exception_regdump *pstate); |
char *vector_to_string(__u16 vector) |
{ |
ASSERT(vector <= VECTOR_MAX); |
if (vector >= VECTORS_16_BUNDLE_START) |
return vector_names_16_bundle[(vector-VECTORS_16_BUNDLE_START)/(16*BUNDLE_SIZE)]; |
else |
return vector_names_64_bundle[vector/(64*BUNDLE_SIZE)]; |
} |
void dump_interrupted_context(struct exception_regdump *pstate) |
{ |
char *ifa, *iipa, *iip; |
ifa = get_symtab_entry(pstate->cr_ifa); |
iipa = get_symtab_entry(pstate->cr_iipa); |
iip = get_symtab_entry(pstate->cr_iip); |
putchar('\n'); |
printf("Interrupted context dump:\n"); |
printf("ar.bsp=%P\tar.bspstore=%P\n", pstate->ar_bsp, pstate->ar_bspstore); |
printf("ar.rnat=%Q\tar.rsc=%Q\n", pstate->ar_rnat, pstate->ar_rsc); |
printf("ar.ifs=%Q\tar.pfs=%Q\n", pstate->ar_ifs, pstate->ar_pfs); |
printf("cr.isr=%Q\tcr.ipsr=%Q\t\n", pstate->cr_isr.value, pstate->cr_ipsr); |
printf("cr.iip=%Q, #%d\t(%s)\n", pstate->cr_iip, pstate->cr_isr.ei ,iip ? iip : "?"); |
printf("cr.iipa=%Q\t(%s)\n", pstate->cr_iipa, iipa ? iipa : "?"); |
printf("cr.ifa=%Q\t(%s)\n", pstate->cr_ifa, ifa ? ifa : "?"); |
} |
void general_exception(__u64 vector, struct exception_regdump *pstate) |
{ |
char *desc = ""; |
dump_interrupted_context(pstate); |
switch (pstate->cr_isr.ge_code) { |
case GE_ILLEGALOP: |
desc = "Illegal Operation fault"; |
break; |
case GE_PRIVOP: |
desc = "Privileged Operation fault"; |
break; |
case GE_PRIVREG: |
desc = "Privileged Register fault"; |
break; |
case GE_RESREGFLD: |
desc = "Reserved Register/Field fault"; |
break; |
case GE_DISBLDISTRAN: |
desc = "Disabled Instruction Set Transition fault"; |
break; |
case GE_ILLEGALDEP: |
desc = "Illegal Dependency fault"; |
break; |
default: |
desc = "unknown"; |
break; |
} |
panic("General Exception (%s)\n", desc); |
} |
/** Handle syscall. */ |
int break_instruction(__u64 vector, struct exception_regdump *pstate) |
{ |
/* |
* Move to next instruction after BREAK. |
*/ |
if (pstate->cr_ipsr.ri == 2) { |
pstate->cr_ipsr.ri = 0; |
pstate->cr_iip += 16; |
} else { |
pstate->cr_ipsr.ri++; |
} |
if (pstate->in0 < SYSCALL_END) |
return syscall_table[pstate->in0](pstate->in1, pstate->in2, pstate->in3); |
else |
panic("Undefined syscall %d", pstate->in0); |
return -1; |
} |
void universal_handler(__u64 vector, struct exception_regdump *pstate) |
{ |
dump_interrupted_context(pstate); |
panic("Interruption: %W (%s)\n", (__u16) vector, vector_to_string(vector)); |
} |
void external_interrupt(__u64 vector, struct exception_regdump *pstate) |
{ |
cr_ivr_t ivr; |
ivr.value = ivr_read(); |
srlz_d(); |
switch(ivr.vector) { |
case INTERRUPT_TIMER: |
it_interrupt(); |
break; |
case INTERRUPT_SPURIOUS: |
printf("cpu%d: spurious interrupt\n", CPU->id); |
break; |
default: |
panic("\nUnhandled External Interrupt Vector %d\n", ivr.vector); |
break; |
} |
} |
/kernel/trunk/arch/ia64/src/asm.S |
---|
0,0 → 1,89 |
# |
# Copyright (C) 2005 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/register.h> |
.text |
.global memcpy |
memcpy: |
br _memcpy |
.global memsetb |
memsetb: |
br _memsetb |
.global cpu_halt |
cpu_halt: |
br cpu_halt |
.global panic_printf |
panic_printf: |
{ |
br.call.sptk.many b0=printf |
} |
br halt |
/** Switch to userspace - low level code. |
* |
* @param in0 Userspace entry point address. |
* @param in1 Userspace stack pointer address. |
* @param in2 Userspace register stack pointer address. |
* @param in3 Value to be stored in IPSR. |
* @param in4 Value to be stored in RSC. |
*/ |
.global switch_to_userspace |
switch_to_userspace: |
alloc loc0 = ar.pfs, 5, 3, 0, 0 |
rsm (PSR_IC_MASK | PSR_I_MASK) /* disable interruption collection and interrupts */ |
srlz.d ;; |
srlz.i ;; |
mov cr.ipsr = in3 |
mov cr.iip = in0 |
mov r12 = in1 |
xor r1 = r1, r1 |
mov loc1 = cr.ifs |
movl loc2 = PFM_MASK ;; |
and loc1 = loc2, loc1 ;; |
mov cr.ifs = loc1 ;; /* prevent decrementing BSP by rfi */ |
invala |
mov loc1 = ar.rsc ;; |
and loc1 = ~3, loc1 ;; |
mov ar.rsc = loc1 ;; /* put RSE into enforced lazy mode */ |
flushrs ;; |
mov ar.bspstore = in2 ;; |
mov ar.rsc = in4 ;; |
rfi ;; |
/kernel/trunk/arch/ia64/src/ia64.c |
---|
0,0 → 1,91 |
/* |
* Copyright (C) 2005 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.h> |
#include <arch/ski/ski.h> |
#include <arch/drivers/it.h> |
#include <arch/interrupt.h> |
#include <arch/barrier.h> |
#include <arch/asm.h> |
#include <arch/register.h> |
#include <arch/types.h> |
#include <arch/context.h> |
#include <arch/mm/page.h> |
#include <mm/as.h> |
#include <config.h> |
#include <userspace.h> |
#include <console/console.h> |
void arch_pre_mm_init(void) |
{ |
/* Set Interruption Vector Address (i.e. location of interruption vector table). */ |
iva_write((__address) &ivt); |
srlz_d(); |
ski_init_console(); |
it_init(); |
config.init_addr = INIT_ADDRESS; |
config.init_size = INIT_SIZE; |
} |
void arch_post_mm_init(void) |
{ |
} |
void arch_pre_smp_init(void) |
{ |
} |
void arch_post_smp_init(void) |
{ |
} |
/** Enter userspace and never return. */ |
void userspace(void) |
{ |
psr_t psr; |
rsc_t rsc; |
psr.value = psr_read(); |
psr.cpl = PL_USER; |
psr.i = true; /* start with interrupts enabled */ |
psr.ic = true; |
psr.ri = 0; /* start with instruction #0 */ |
__asm__ volatile ("mov %0 = ar.rsc\n" : "=r" (rsc.value)); |
rsc.loadrs = 0; |
rsc.be = false; |
rsc.pl = PL_USER; |
rsc.mode = 3; /* eager mode */ |
switch_to_userspace(UTEXT_ADDRESS, USTACK_ADDRESS+PAGE_SIZE-1, USTACK_ADDRESS, psr.value, rsc.value); |
while (1) { |
; |
} |
} |
/kernel/trunk/arch/ia64/src/mm/tlb.c |
---|
0,0 → 1,462 |
/* |
* 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. |
*/ |
/* |
* TLB management. |
*/ |
#include <mm/tlb.h> |
#include <mm/asid.h> |
#include <mm/page.h> |
#include <mm/as.h> |
#include <arch/mm/tlb.h> |
#include <arch/mm/page.h> |
#include <arch/barrier.h> |
#include <arch/interrupt.h> |
#include <typedefs.h> |
#include <panic.h> |
#include <arch.h> |
/** Invalidate all TLB entries. */ |
void tlb_invalidate_all(void) |
{ |
/* TODO */ |
} |
/** Invalidate entries belonging to an address space. |
* |
* @param asid Address space identifier. |
*/ |
void tlb_invalidate_asid(asid_t asid) |
{ |
/* TODO */ |
} |
/** Insert data into data translation cache. |
* |
* @param va Virtual page address. |
* @param asid Address space identifier. |
* @param entry The rest of TLB entry as required by TLB insertion format. |
*/ |
void dtc_mapping_insert(__address va, asid_t asid, tlb_entry_t entry) |
{ |
tc_mapping_insert(va, asid, entry, true); |
} |
/** Insert data into instruction translation cache. |
* |
* @param va Virtual page address. |
* @param asid Address space identifier. |
* @param entry The rest of TLB entry as required by TLB insertion format. |
*/ |
void itc_mapping_insert(__address va, asid_t asid, tlb_entry_t entry) |
{ |
tc_mapping_insert(va, asid, entry, false); |
} |
/** Insert data into instruction or data translation cache. |
* |
* @param va Virtual page address. |
* @param asid Address space identifier. |
* @param entry The rest of TLB entry as required by TLB insertion format. |
* @param dtc If true, insert into data translation cache, use instruction translation cache otherwise. |
*/ |
void tc_mapping_insert(__address va, asid_t asid, tlb_entry_t entry, bool dtc) |
{ |
region_register rr; |
bool restore_rr = false; |
rr.word = rr_read(VA2VRN(va)); |
if ((restore_rr = (rr.map.rid != ASID2RID(asid, VA2VRN(va))))) { |
/* |
* The selected region register does not contain required RID. |
* Save the old content of the register and replace the RID. |
*/ |
region_register rr0; |
rr0 = rr; |
rr0.map.rid = ASID2RID(asid, VA2VRN(va)); |
rr_write(VA2VRN(va), rr0.word); |
srlz_d(); |
srlz_i(); |
} |
__asm__ volatile ( |
"mov r8=psr;;\n" |
"rsm %0;;\n" /* PSR_IC_MASK */ |
"srlz.d;;\n" |
"srlz.i;;\n" |
"mov cr.ifa=%1\n" /* va */ |
"mov cr.itir=%2;;\n" /* entry.word[1] */ |
"cmp.eq p6,p7 = %4,r0;;\n" /* decide between itc and dtc */ |
"(p6) itc.i %3;;\n" |
"(p7) itc.d %3;;\n" |
"mov psr.l=r8;;\n" |
"srlz.d;;\n" |
: |
: "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]), "r" (entry.word[0]), "r" (dtc) |
: "p6", "p7", "r8" |
); |
if (restore_rr) { |
rr_write(VA2VRN(va), rr.word); |
srlz_d(); |
srlz_i(); |
} |
} |
/** Insert data into instruction translation register. |
* |
* @param va Virtual page address. |
* @param asid Address space identifier. |
* @param entry The rest of TLB entry as required by TLB insertion format. |
* @param tr Translation register. |
*/ |
void itr_mapping_insert(__address va, asid_t asid, tlb_entry_t entry, index_t tr) |
{ |
tr_mapping_insert(va, asid, entry, false, tr); |
} |
/** Insert data into data translation register. |
* |
* @param va Virtual page address. |
* @param asid Address space identifier. |
* @param entry The rest of TLB entry as required by TLB insertion format. |
* @param tr Translation register. |
*/ |
void dtr_mapping_insert(__address va, asid_t asid, tlb_entry_t entry, index_t tr) |
{ |
tr_mapping_insert(va, asid, entry, true, tr); |
} |
/** Insert data into instruction or data translation register. |
* |
* @param va Virtual page address. |
* @param asid Address space identifier. |
* @param entry The rest of TLB entry as required by TLB insertion format. |
* @param dtc If true, insert into data translation register, use instruction translation register otherwise. |
* @param tr Translation register. |
*/ |
void tr_mapping_insert(__address va, asid_t asid, tlb_entry_t entry, bool dtr, index_t tr) |
{ |
region_register rr; |
bool restore_rr = false; |
rr.word = rr_read(VA2VRN(va)); |
if ((restore_rr = (rr.map.rid != ASID2RID(asid, VA2VRN(va))))) { |
/* |
* The selected region register does not contain required RID. |
* Save the old content of the register and replace the RID. |
*/ |
region_register rr0; |
rr0 = rr; |
rr0.map.rid = ASID2RID(asid, VA2VRN(va)); |
rr_write(VA2VRN(va), rr0.word); |
srlz_d(); |
srlz_i(); |
} |
__asm__ volatile ( |
"mov r8=psr;;\n" |
"rsm %0;;\n" /* PSR_IC_MASK */ |
"srlz.d;;\n" |
"srlz.i;;\n" |
"mov cr.ifa=%1\n" /* va */ |
"mov cr.itir=%2;;\n" /* entry.word[1] */ |
"cmp.eq p6,p7=%5,r0;;\n" /* decide between itr and dtr */ |
"(p6) itr.i itr[%4]=%3;;\n" |
"(p7) itr.d dtr[%4]=%3;;\n" |
"mov psr.l=r8;;\n" |
"srlz.d;;\n" |
: |
: "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]), "r" (entry.word[0]), "r" (tr), "r" (dtr) |
: "p6", "p7", "r8" |
); |
if (restore_rr) { |
rr_write(VA2VRN(va), rr.word); |
srlz_d(); |
srlz_i(); |
} |
} |
/** Insert data into DTLB. |
* |
* @param va Virtual page address. |
* @param asid Address space identifier. |
* @param entry The rest of TLB entry as required by TLB insertion format. |
* @param dtr If true, insert into data translation register, use data translation cache otherwise. |
* @param tr Translation register if dtr is true, ignored otherwise. |
*/ |
void dtlb_kernel_mapping_insert(__address page, __address frame, bool dtr, index_t tr) |
{ |
tlb_entry_t entry; |
entry.word[0] = 0; |
entry.word[1] = 0; |
entry.p = true; /* present */ |
entry.ma = MA_WRITEBACK; |
entry.a = true; /* already accessed */ |
entry.d = true; /* already dirty */ |
entry.pl = PL_KERNEL; |
entry.ar = AR_READ | AR_WRITE; |
entry.ppn = frame >> PPN_SHIFT; |
entry.ps = PAGE_WIDTH; |
if (dtr) |
dtr_mapping_insert(page, ASID_KERNEL, entry, tr); |
else |
dtc_mapping_insert(page, ASID_KERNEL, entry); |
} |
/** Copy content of PTE into data translation cache. |
* |
* @param t PTE. |
*/ |
void dtc_pte_copy(pte_t *t) |
{ |
tlb_entry_t entry; |
entry.word[0] = 0; |
entry.word[1] = 0; |
entry.p = t->p; |
entry.ma = t->c ? MA_WRITEBACK : MA_UNCACHEABLE; |
entry.a = t->a; |
entry.d = t->d; |
entry.pl = t->k ? PL_KERNEL : PL_USER; |
entry.ar = t->w ? AR_WRITE : AR_READ; |
entry.ppn = t->frame >> PPN_SHIFT; |
entry.ps = PAGE_WIDTH; |
dtc_mapping_insert(t->page, t->as->asid, entry); |
} |
/** Copy content of PTE into instruction translation cache. |
* |
* @param t PTE. |
*/ |
void itc_pte_copy(pte_t *t) |
{ |
tlb_entry_t entry; |
entry.word[0] = 0; |
entry.word[1] = 0; |
ASSERT(t->x); |
entry.p = t->p; |
entry.ma = t->c ? MA_WRITEBACK : MA_UNCACHEABLE; |
entry.a = t->a; |
entry.pl = t->k ? PL_KERNEL : PL_USER; |
entry.ar = t->x ? (AR_EXECUTE | AR_READ) : AR_READ; |
entry.ppn = t->frame >> PPN_SHIFT; |
entry.ps = PAGE_WIDTH; |
itc_mapping_insert(t->page, t->as->asid, entry); |
} |
/** Instruction TLB fault handler for faults with VHPT turned off. |
* |
* @param vector Interruption vector. |
* @param pstate Structure with saved interruption state. |
*/ |
void alternate_instruction_tlb_fault(__u64 vector, struct exception_regdump *pstate) |
{ |
region_register rr; |
__address va; |
pte_t *t; |
va = pstate->cr_ifa; /* faulting address */ |
t = page_mapping_find(AS, va); |
if (t) { |
/* |
* The mapping was found in software page hash table. |
* Insert it into data translation cache. |
*/ |
itc_pte_copy(t); |
} else { |
/* |
* Forward the page fault to address space page fault handler. |
*/ |
if (!as_page_fault(va)) { |
panic("%s: va=%P, rid=%d\n", __FUNCTION__, pstate->cr_ifa, rr.map.rid); |
} |
} |
} |
/** Data TLB fault handler for faults with VHPT turned off. |
* |
* @param vector Interruption vector. |
* @param pstate Structure with saved interruption state. |
*/ |
void alternate_data_tlb_fault(__u64 vector, struct exception_regdump *pstate) |
{ |
region_register rr; |
rid_t rid; |
__address va; |
pte_t *t; |
va = pstate->cr_ifa; /* faulting address */ |
rr.word = rr_read(VA2VRN(va)); |
rid = rr.map.rid; |
if (RID2ASID(rid) == ASID_KERNEL) { |
if (VA2VRN(va) == VRN_KERNEL) { |
/* |
* Provide KA2PA(identity) mapping for faulting piece of |
* kernel address space. |
*/ |
dtlb_kernel_mapping_insert(va, KA2PA(va), false, 0); |
return; |
} |
} |
t = page_mapping_find(AS, va); |
if (t) { |
/* |
* The mapping was found in software page hash table. |
* Insert it into data translation cache. |
*/ |
dtc_pte_copy(t); |
} else { |
/* |
* Forward the page fault to address space page fault handler. |
*/ |
if (!as_page_fault(va)) { |
panic("%s: va=%P, rid=%d\n", __FUNCTION__, pstate->cr_ifa, rr.map.rid); |
} |
} |
} |
/** Data nested TLB fault handler. |
* |
* This fault should not occur. |
* |
* @param vector Interruption vector. |
* @param pstate Structure with saved interruption state. |
*/ |
void data_nested_tlb_fault(__u64 vector, struct exception_regdump *pstate) |
{ |
panic("%s\n", __FUNCTION__); |
} |
/** Data Dirty bit fault handler. |
* |
* @param vector Interruption vector. |
* @param pstate Structure with saved interruption state. |
*/ |
void data_dirty_bit_fault(__u64 vector, struct exception_regdump *pstate) |
{ |
pte_t *t; |
t = page_mapping_find(AS, pstate->cr_ifa); |
ASSERT(t && t->p); |
if (t && t->p) { |
/* |
* Update the Dirty bit in page tables and reinsert |
* the mapping into DTC. |
*/ |
t->d = true; |
dtc_pte_copy(t); |
} |
} |
/** Instruction access bit fault handler. |
* |
* @param vector Interruption vector. |
* @param pstate Structure with saved interruption state. |
*/ |
void instruction_access_bit_fault(__u64 vector, struct exception_regdump *pstate) |
{ |
pte_t *t; |
t = page_mapping_find(AS, pstate->cr_ifa); |
ASSERT(t && t->p); |
if (t && t->p) { |
/* |
* Update the Accessed bit in page tables and reinsert |
* the mapping into ITC. |
*/ |
t->a = true; |
itc_pte_copy(t); |
} |
} |
/** Data access bit fault handler. |
* |
* @param vector Interruption vector. |
* @param pstate Structure with saved interruption state. |
*/ |
void data_access_bit_fault(__u64 vector, struct exception_regdump *pstate) |
{ |
pte_t *t; |
t = page_mapping_find(AS, pstate->cr_ifa); |
ASSERT(t && t->p); |
if (t && t->p) { |
/* |
* Update the Accessed bit in page tables and reinsert |
* the mapping into DTC. |
*/ |
t->a = true; |
dtc_pte_copy(t); |
} |
} |
/** Page not present fault handler. |
* |
* @param vector Interruption vector. |
* @param pstate Structure with saved interruption state. |
*/ |
void page_not_present(__u64 vector, struct exception_regdump *pstate) |
{ |
region_register rr; |
__address va; |
pte_t *t; |
va = pstate->cr_ifa; /* faulting address */ |
t = page_mapping_find(AS, va); |
ASSERT(t); |
if (t->p) { |
/* |
* If the Present bit is set in page hash table, just copy it |
* and update ITC/DTC. |
*/ |
if (t->x) |
itc_pte_copy(t); |
else |
dtc_pte_copy(t); |
} else { |
if (!as_page_fault(va)) { |
panic("%s: va=%P, rid=%d\n", __FUNCTION__, pstate->cr_ifa, rr.map.rid); |
} |
} |
} |
/kernel/trunk/arch/ia64/src/mm/page.c |
---|
0,0 → 1,246 |
/* |
* Copyright (C) 2006 Jakub Jermar |
* Copyright (C) 2006 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 <arch/mm/page.h> |
#include <genarch/mm/page_ht.h> |
#include <mm/asid.h> |
#include <arch/mm/asid.h> |
#include <arch/types.h> |
#include <typedefs.h> |
#include <print.h> |
#include <mm/page.h> |
#include <mm/frame.h> |
#include <config.h> |
#include <panic.h> |
#include <arch/asm.h> |
#include <arch/barrier.h> |
#include <memstr.h> |
static void set_environment(void); |
/** Initialize ia64 virtual address translation subsystem. */ |
void page_arch_init(void) |
{ |
page_mapping_operations = &ht_mapping_operations; |
pk_disable(); |
set_environment(); |
} |
/** Initialize VHPT and region registers. */ |
void set_environment(void) |
{ |
region_register rr; |
pta_register pta; |
int i; |
/* |
* First set up kernel region register. |
* This is redundant (see start.S) but we keep it here just for sure. |
*/ |
rr.word = rr_read(VRN_KERNEL); |
rr.map.ve = 0; /* disable VHPT walker */ |
rr.map.ps = PAGE_WIDTH; |
rr.map.rid = ASID2RID(ASID_KERNEL, VRN_KERNEL); |
rr_write(VRN_KERNEL, rr.word); |
srlz_i(); |
srlz_d(); |
/* |
* And setup the rest of region register. |
*/ |
for(i = 0; i < REGION_REGISTERS; i++) { |
/* skip kernel rr */ |
if (i == VRN_KERNEL) |
continue; |
rr.word = rr_read(i); |
rr.map.ve = 0; /* disable VHPT walker */ |
rr.map.rid = RID_KERNEL; |
rr.map.ps = PAGE_WIDTH; |
rr_write(i, rr.word); |
srlz_i(); |
srlz_d(); |
} |
/* |
* Set up PTA register. |
*/ |
pta.word = pta_read(); |
pta.map.ve = 0; /* disable VHPT walker */ |
pta.map.vf = 1; /* large entry format */ |
pta.map.size = VHPT_WIDTH; |
pta.map.base = VHPT_BASE >> PTA_BASE_SHIFT; |
pta_write(pta.word); |
srlz_i(); |
srlz_d(); |
} |
/** Calculate address of collision chain from VPN and ASID. |
* |
* Interrupts must be disabled. |
* |
* @param page Address of virtual page including VRN bits. |
* @param asid Address space identifier. |
* |
* @return VHPT entry address. |
*/ |
vhpt_entry_t *vhpt_hash(__address page, asid_t asid) |
{ |
region_register rr_save, rr; |
index_t vrn; |
rid_t rid; |
vhpt_entry_t *v; |
vrn = page >> VRN_SHIFT; |
rid = ASID2RID(asid, vrn); |
rr_save.word = rr_read(vrn); |
if (rr_save.map.rid == rid) { |
/* |
* The RID is already in place, compute thash and return. |
*/ |
v = (vhpt_entry_t *) thash(page); |
return v; |
} |
/* |
* The RID must be written to some region register. |
* To speed things up, register indexed by vrn is used. |
*/ |
rr.word = rr_save.word; |
rr.map.rid = rid; |
rr_write(vrn, rr.word); |
srlz_i(); |
v = (vhpt_entry_t *) thash(page); |
rr_write(vrn, rr_save.word); |
srlz_i(); |
srlz_d(); |
return v; |
} |
/** Compare ASID and VPN against PTE. |
* |
* Interrupts must be disabled. |
* |
* @param page Address of virtual page including VRN bits. |
* @param asid Address space identifier. |
* |
* @return True if page and asid match the page and asid of t, false otherwise. |
*/ |
bool vhpt_compare(__address page, asid_t asid, vhpt_entry_t *v) |
{ |
region_register rr_save, rr; |
index_t vrn; |
rid_t rid; |
bool match; |
ASSERT(v); |
vrn = page >> VRN_SHIFT; |
rid = ASID2RID(asid, vrn); |
rr_save.word = rr_read(vrn); |
if (rr_save.map.rid == rid) { |
/* |
* The RID is already in place, compare ttag with t and return. |
*/ |
return ttag(page) == v->present.tag.tag_word; |
} |
/* |
* The RID must be written to some region register. |
* To speed things up, register indexed by vrn is used. |
*/ |
rr.word = rr_save.word; |
rr.map.rid = rid; |
rr_write(vrn, rr.word); |
srlz_i(); |
match = (ttag(page) == v->present.tag.tag_word); |
rr_write(vrn, rr_save.word); |
srlz_i(); |
srlz_d(); |
return match; |
} |
/** Set up one VHPT entry. |
* |
* @param t VHPT entry to be set up. |
* @param page Virtual address of the page mapped by the entry. |
* @param asid Address space identifier of the address space to which page belongs. |
* @param frame Physical address of the frame to wich page is mapped. |
* @param flags Different flags for the mapping. |
*/ |
void vhpt_set_record(vhpt_entry_t *v, __address page, asid_t asid, __address frame, int flags) |
{ |
region_register rr_save, rr; |
index_t vrn; |
rid_t rid; |
__u64 tag; |
ASSERT(v); |
vrn = page >> VRN_SHIFT; |
rid = ASID2RID(asid, vrn); |
/* |
* Compute ttag. |
*/ |
rr_save.word = rr_read(vrn); |
rr.word = rr_save.word; |
rr.map.rid = rid; |
rr_write(vrn, rr.word); |
srlz_i(); |
tag = ttag(page); |
rr_write(vrn, rr_save.word); |
srlz_i(); |
srlz_d(); |
/* |
* Clear the entry. |
*/ |
v->word[0] = 0; |
v->word[1] = 0; |
v->word[2] = 0; |
v->word[3] = 0; |
v->present.p = true; |
v->present.ma = (flags & PAGE_CACHEABLE) ? MA_WRITEBACK : MA_UNCACHEABLE; |
v->present.a = false; /* not accessed */ |
v->present.d = false; /* not dirty */ |
v->present.pl = (flags & PAGE_USER) ? PL_USER : PL_KERNEL; |
v->present.ar = (flags & PAGE_WRITE) ? AR_WRITE : AR_READ; |
v->present.ar |= (flags & PAGE_EXEC) ? AR_EXECUTE : 0; |
v->present.ppn = frame >> PPN_SHIFT; |
v->present.ed = false; /* exception not deffered */ |
v->present.ps = PAGE_WIDTH; |
v->present.key = 0; |
v->present.tag.tag_word = tag; |
} |
/kernel/trunk/arch/ia64/src/mm/as.c |
---|
0,0 → 1,80 |
/* |
* 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 <arch/mm/as.h> |
#include <arch/mm/asid.h> |
#include <arch/mm/page.h> |
#include <genarch/mm/as_ht.h> |
#include <genarch/mm/asid_fifo.h> |
#include <mm/asid.h> |
#include <arch.h> |
#include <arch/barrier.h> |
#include <synch/spinlock.h> |
/** Architecture dependent address space init. */ |
void as_arch_init(void) |
{ |
as_operations = &as_ht_operations; |
asid_fifo_init(); |
} |
/** Prepare registers for switching to another address space. |
* |
* @param as Address space. |
*/ |
void as_install_arch(as_t *as) |
{ |
ipl_t ipl; |
region_register rr; |
int i; |
ipl = interrupts_disable(); |
spinlock_lock(&as->lock); |
ASSERT(as->asid != ASID_INVALID); |
/* |
* Load respective ASID (7 consecutive RIDs) to |
* region registers. |
*/ |
for (i = 0; i < REGION_REGISTERS; i++) { |
if (i == VRN_KERNEL) |
continue; |
rr.word = rr_read(i); |
rr.map.ve = false; /* disable VHPT walker */ |
rr.map.rid = ASID2RID(as->asid, i); |
rr.map.ps = PAGE_WIDTH; |
rr_write(i, rr.word); |
} |
srlz_d(); |
srlz_i(); |
spinlock_unlock(&as->lock); |
interrupts_restore(ipl); |
} |
/kernel/trunk/arch/ia64/src/mm/frame.c |
---|
0,0 → 1,49 |
/* |
* Copyright (C) 2005 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/frame.h> |
#include <mm/frame.h> |
#include <config.h> |
#include <panic.h> |
/* |
* This is Ski-specific and certainly not sufficient |
* for real ia64 systems that provide memory map. |
*/ |
#define ROM_BASE 0xa0000 |
#define ROM_SIZE (384*1024) |
void frame_arch_init(void) |
{ |
zone_create(0, config.memory_size >> FRAME_WIDTH, 1, 0); |
/* |
* Blacklist ROM regions. |
*/ |
frame_mark_unavailable(ADDR2PFN(ROM_BASE), ROM_SIZE >> FRAME_WIDTH); |
} |
/kernel/trunk/arch/ia64/src/dummy.s |
---|
0,0 → 1,48 |
# |
# Copyright (C) 2005 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 calibrate_delay_loop |
.global asm_delay_loop |
.global cpu_sleep |
.global dummy |
.global fpu_enable |
.global fpu_disable |
.global fpu_init |
calibrate_delay_loop: |
asm_delay_loop: |
cpu_sleep: |
fpu_init: |
fpu_enable: |
fpu_disable: |
dummy: |
br.ret.sptk.many b0 |
/kernel/trunk/arch/ia64/src/proc/scheduler.c |
---|
0,0 → 1,71 |
/* |
* 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/scheduler.h> |
#include <proc/thread.h> |
#include <arch.h> |
#include <arch/register.h> |
#include <arch/context.h> |
#include <arch/stack.h> |
#include <arch/mm/tlb.h> |
#include <config.h> |
#include <align.h> |
/** Prepare kernel stack pointers in bank 0 r22 and r23 and make sure the stack is mapped in DTR. */ |
void before_thread_runs_arch(void) |
{ |
__address base; |
base = ALIGN_DOWN(config.base, 1<<KERNEL_PAGE_WIDTH); |
if ((__address) THREAD->kstack < base || (__address) THREAD->kstack > base + (1<<KERNEL_PAGE_WIDTH)) { |
/* |
* Kernel stack of this thread is not mapped by DTR[TR_KERNEL]. |
* Use DTR[TR_KSTACK] to map it. |
*/ |
dtlb_kernel_mapping_insert((__address) THREAD->kstack, KA2PA(THREAD->kstack), true, DTR_KSTACK); |
} |
/* |
* Record address of kernel backing store to bank 0 r22. |
* Record address of kernel stack to bank 0 r23. |
* These values will be found there after switch from userspace. |
*/ |
__asm__ volatile ( |
"bsw.0\n" |
"mov r22 = %0\n" |
"mov r23 = %1\n" |
"bsw.1\n" |
: |
: "r" (((__address) THREAD->kstack) + ALIGN_UP(sizeof(the_t), REGISTER_STACK_ALIGNMENT)), |
"r" (&THREAD->kstack[THREAD_STACK_SIZE - SP_DELTA])); |
} |
void after_thread_ran_arch(void) |
{ |
} |
/kernel/trunk/arch/ia64/src/ski/ski.c |
---|
0,0 → 1,157 |
/* |
* Copyright (C) 2005 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/ski/ski.h> |
#include <console/console.h> |
#include <console/chardev.h> |
static chardev_t ski_console; |
static bool kb_disable; |
static void ski_putchar(chardev_t *d, const char ch); |
static __s32 ski_getchar(void); |
/** Display character on debug console |
* |
* Use SSC (Simulator System Call) to |
* display character on debug console. |
* |
* @param d Character device. |
* @param ch Character to be printed. |
*/ |
void ski_putchar(chardev_t *d, const char ch) |
{ |
__asm__ volatile ( |
"mov r15=%0\n" |
"mov r32=%1\n" /* r32 is in0 */ |
"break 0x80000\n" /* modifies r8 */ |
: |
: "i" (SKI_PUTCHAR), "r" (ch) |
: "r15", "in0", "r8" |
); |
if (ch == '\n') |
ski_putchar(d, '\r'); |
} |
/** Ask debug console if a key was pressed. |
* |
* Use SSC (Simulator System Call) to |
* get character from debug console. |
* |
* This call is non-blocking. |
* |
* @return ASCII code of pressed key or 0 if no key pressed. |
*/ |
__s32 ski_getchar(void) |
{ |
__u64 ch; |
__asm__ volatile ( |
"mov r15=%1\n" |
"break 0x80000;;\n" /* modifies r8 */ |
"mov %0=r8;;\n" |
: "=r" (ch) |
: "i" (SKI_GETCHAR) |
: "r15", "r8" |
); |
return (__s32) ch; |
} |
/** |
* This is a blocking wrapper for ski_getchar(). |
* To be used when the kernel crashes. |
*/ |
static char ski_getchar_blocking(chardev_t *d) |
{ |
int ch; |
while(!(ch=ski_getchar())) |
; |
if(ch == '\r') |
ch = '\n'; |
return (char) ch; |
} |
/** Ask keyboard if a key was pressed. */ |
void poll_keyboard(void) |
{ |
char ch; |
if (kb_disable) |
return; |
ch = ski_getchar(); |
if(ch == '\r') |
ch = '\n'; |
if (ch) |
chardev_push_character(&ski_console, ch); |
} |
/* Called from getc(). */ |
static void ski_kb_enable(chardev_t *d) |
{ |
kb_disable = false; |
} |
/* Called from getc(). */ |
static void ski_kb_disable(chardev_t *d) |
{ |
kb_disable = true; |
} |
static chardev_operations_t ski_ops = { |
.resume = ski_kb_enable, |
.suspend = ski_kb_disable, |
.write = ski_putchar, |
.read = ski_getchar_blocking |
}; |
/** Initialize debug console |
* |
* Issue SSC (Simulator System Call) to |
* to open debug console. |
*/ |
void ski_init_console(void) |
{ |
__asm__ volatile ( |
"mov r15=%0\n" |
"break 0x80000\n" |
: |
: "i" (SKI_INIT_CONSOLE) |
: "r15", "r8" |
); |
chardev_initialize("ski_console", &ski_console, &ski_ops); |
stdin = &ski_console; |
stdout = &ski_console; |
} |
/kernel/trunk/arch/ia64/src/putchar.c |
---|
0,0 → 1,35 |
/* |
* Copyright (C) 2005 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 <putchar.h> |
#include <arch/ski/ski.h> |
void putchar(const char ch) |
{ |
ski_write(ch); |
} |
/kernel/trunk/arch/ia64/src/drivers/it.c |
---|
0,0 → 1,69 |
/* |
* Copyright (C) 2005 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. |
*/ |
/** Interval Timer driver. */ |
#include <arch/drivers/it.h> |
#include <arch/ski/ski.h> |
#include <arch/interrupt.h> |
#include <arch/register.h> |
#include <arch/asm.h> |
#include <arch/barrier.h> |
#include <time/clock.h> |
/** Initialize Interval Timer. */ |
void it_init(void) |
{ |
cr_itv_t itv; |
/* initialize Interval Timer external interrupt vector */ |
itv.value = itv_read(); |
itv.vector = INTERRUPT_TIMER; |
itv.m = 0; |
itv_write(itv.value); |
/* set Interval Timer Counter to zero */ |
itc_write(0); |
/* generate first Interval Timer interrupt in IT_DELTA ticks */ |
itm_write(IT_DELTA); |
/* propagate changes */ |
srlz_d(); |
} |
/** Process Interval Timer interrupt. */ |
void it_interrupt(void) |
{ |
eoi_write(EOI); |
itm_write(itc_read() + IT_DELTA); /* program next interruption */ |
srlz_d(); /* propagate changes */ |
clock(); |
poll_keyboard(); |
} |
/kernel/trunk/arch/ia64/src/cpu/cpu.c |
---|
0,0 → 1,67 |
/* |
* Copyright (C) 2005 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 <cpu.h> |
#include <arch.h> |
#include <arch/register.h> |
#include <print.h> |
void cpu_arch_init(void) |
{ |
} |
void cpu_identify(void) |
{ |
CPU->arch.cpuid0 = cpuid_read(0); |
CPU->arch.cpuid1 = cpuid_read(1); |
CPU->arch.cpuid3.value = cpuid_read(3); |
} |
void cpu_print_report(cpu_t *m) |
{ |
char *family_str; |
char vendor[2*sizeof(__u64)+1]; |
*((__u64 *) &vendor[0*sizeof(__u64)]) = CPU->arch.cpuid0; |
*((__u64 *) &vendor[1*sizeof(__u64)]) = CPU->arch.cpuid1; |
vendor[sizeof(vendor)-1] = '\0'; |
switch(m->arch.cpuid3.family) { |
case FAMILY_ITANIUM: |
family_str = "Itanium"; |
break; |
case FAMILY_ITANIUM2: |
family_str = "Itanium 2"; |
break; |
default: |
family_str = "Unknown"; |
break; |
} |
printf("cpu%d: %s (%s), archrev=%d, model=%d, revision=%d\n", CPU->id, family_str, vendor, CPU->arch.cpuid3.archrev, CPU->arch.cpuid3.model, CPU->arch.cpuid3.revision); |
} |
/kernel/trunk/arch/ia64/src/context.S |
---|
0,0 → 1,196 |
# |
# Copyright (C) 2005 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 |
context_save_arch: |
alloc loc0 = ar.pfs, 1, 8, 0, 0 |
mov loc1 = ar.unat ;; |
/* loc2 */ |
mov loc3 = ar.rsc |
.auto |
/* |
* Flush dirty registers to backing store. |
* After this ar.bsp and ar.bspstore are equal. |
*/ |
flushrs |
mov loc4 = ar.bsp |
/* |
* Put RSE to enforced lazy mode. |
* So that ar.rnat can be read. |
*/ |
and loc5 = ~3, loc3 |
mov ar.rsc = loc5 |
mov loc5 = ar.rnat |
.explicit |
mov loc6 = ar.lc |
/* |
* Save application registers |
*/ |
st8 [in0] = loc0, 8 ;; /* save ar.pfs */ |
st8 [in0] = loc1, 8 ;; /* save ar.unat (caller) */ |
mov loc2 = in0 ;; |
add in0 = 8, in0 ;; /* skip ar.unat (callee) */ |
st8 [in0] = loc3, 8 ;; /* save ar.rsc */ |
st8 [in0] = loc4, 8 ;; /* save ar.bsp */ |
st8 [in0] = loc5, 8 ;; /* save ar.rnat */ |
st8 [in0] = loc6, 8 ;; /* save ar.lc */ |
/* |
* Save general registers including NaT bits |
*/ |
st8.spill [in0] = r1, 8 ;; |
st8.spill [in0] = r4, 8 ;; |
st8.spill [in0] = r5, 8 ;; |
st8.spill [in0] = r6, 8 ;; |
st8.spill [in0] = r7, 8 ;; |
st8.spill [in0] = r12, 8 ;; /* save sp */ |
st8.spill [in0] = r13, 8 ;; |
mov loc3 = ar.unat ;; |
st8 [loc2] = loc3 /* save ar.unat (callee) */ |
/* |
* Save branch registers |
*/ |
mov loc2 = b0 ;; |
st8 [in0] = loc2, 8 /* save pc */ |
mov loc3 = b1 ;; |
st8 [in0] = loc3, 8 |
mov loc4 = b2 ;; |
st8 [in0] = loc4, 8 |
mov loc5 = b3 ;; |
st8 [in0] = loc5, 8 |
mov loc6 = b4 ;; |
st8 [in0] = loc6, 8 |
mov loc7 = b5 ;; |
st8 [in0] = loc7, 8 |
/* |
* Save predicate registers |
*/ |
mov loc2 = pr ;; |
st8 [in0] = loc2, 8 |
mov ar.unat = loc1 |
add r8 = r0, r0, 1 /* context_save returns 1 */ |
br.ret.sptk.many b0 |
context_restore_arch: |
alloc loc0 = ar.pfs, 1, 9, 0, 0 ;; |
ld8 loc0 = [in0], 8 ;; /* load ar.pfs */ |
ld8 loc1 = [in0], 8 ;; /* load ar.unat (caller) */ |
ld8 loc2 = [in0], 8 ;; /* load ar.unat (callee) */ |
ld8 loc3 = [in0], 8 ;; /* load ar.rsc */ |
ld8 loc4 = [in0], 8 ;; /* load ar.bsp */ |
ld8 loc5 = [in0], 8 ;; /* load ar.rnat */ |
ld8 loc6 = [in0], 8 ;; /* load ar.lc */ |
.auto |
/* |
* Invalidate the ALAT |
*/ |
invala |
/* |
* Put RSE to enforced lazy mode. |
* So that ar.bspstore and ar.rnat can be written. |
*/ |
movl loc8 = ~3 |
and loc8 = loc3, loc8 |
mov ar.rsc = loc8 |
/* |
* Flush dirty registers to backing store. |
* We do this because we want the following move |
* to ar.bspstore to assign the same value to ar.bsp. |
*/ |
flushrs |
/* |
* Restore application registers |
*/ |
mov ar.bspstore = loc4 /* rse.bspload = ar.bsp = ar.bspstore = loc4 */ |
mov ar.rnat = loc5 |
mov ar.pfs = loc0 |
mov ar.rsc = loc3 |
.explicit |
mov ar.unat = loc2 ;; |
mov ar.lc = loc6 |
/* |
* Restore general registers including NaT bits |
*/ |
ld8.fill r1 = [in0], 8 ;; |
ld8.fill r4 = [in0], 8 ;; |
ld8.fill r5 = [in0], 8 ;; |
ld8.fill r6 = [in0], 8 ;; |
ld8.fill r7 = [in0], 8 ;; |
ld8.fill r12 = [in0], 8 ;; /* restore sp */ |
ld8.fill r13 = [in0], 8 ;; |
/* |
* Restore branch registers |
*/ |
ld8 loc2 = [in0], 8 ;; /* restore pc */ |
mov b0 = loc2 |
ld8 loc3 = [in0], 8 ;; |
mov b1 = loc3 |
ld8 loc4 = [in0], 8 ;; |
mov b2 = loc4 |
ld8 loc5 = [in0], 8 ;; |
mov b3 = loc5 |
ld8 loc6 = [in0], 8 ;; |
mov b4 = loc6 |
ld8 loc7 = [in0], 8 ;; |
mov b5 = loc7 |
/* |
* Restore predicate registers |
*/ |
ld8 loc2 = [in0], 8 ;; |
mov pr = loc2, ~0 |
mov ar.unat = loc1 |
mov r8 = r0 /* context_restore returns 0 */ |
br.ret.sptk.many b0 |
/kernel/trunk/arch/ia64/src/fpu_context.c |
---|
0,0 → 1,40 |
/* |
* 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> |
void fpu_context_save(fpu_context_t *fctx) |
{ |
} |
void fpu_context_restore(fpu_context_t *fctx) |
{ |
} |