diff options
author | awilliam@xenbuild2.aw <awilliam@xenbuild2.aw> | 2007-02-15 13:13:36 -0700 |
---|---|---|
committer | awilliam@xenbuild2.aw <awilliam@xenbuild2.aw> | 2007-02-15 13:13:36 -0700 |
commit | 8a9e0cc712a69a1a0e8cd718cf88b53bd2896ffa (patch) | |
tree | 02ed46464ffe812a9ca07e30aaec90c2021b37be /extras/mini-os/arch | |
parent | 05325dd82113019dbf483c8c968909e7c13111aa (diff) | |
download | xen-8a9e0cc712a69a1a0e8cd718cf88b53bd2896ffa.tar.gz xen-8a9e0cc712a69a1a0e8cd718cf88b53bd2896ffa.tar.bz2 xen-8a9e0cc712a69a1a0e8cd718cf88b53bd2896ffa.zip |
[IA64][MINIOS] Port of mini-os to ia64
ia64 specific parts of mini-os.
Minimal config:
# Kernel image file.
kernel = "mini-os.gz"
# Initial memory allocation (in megabytes) for the new domain.
memory = 64
# A name for your domain.
name = "Mini-OS"
Signed-off-by: Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com>
Diffstat (limited to 'extras/mini-os/arch')
-rw-r--r-- | extras/mini-os/arch/ia64/Makefile | 56 | ||||
-rw-r--r-- | extras/mini-os/arch/ia64/__divdi3.S | 141 | ||||
-rw-r--r-- | extras/mini-os/arch/ia64/__udivdi3.S | 142 | ||||
-rw-r--r-- | extras/mini-os/arch/ia64/__umoddi3.S | 154 | ||||
-rw-r--r-- | extras/mini-os/arch/ia64/arch.mk | 5 | ||||
-rw-r--r-- | extras/mini-os/arch/ia64/common.c | 236 | ||||
-rw-r--r-- | extras/mini-os/arch/ia64/debug.c | 179 | ||||
-rw-r--r-- | extras/mini-os/arch/ia64/efi.c | 237 | ||||
-rw-r--r-- | extras/mini-os/arch/ia64/fw.S | 519 | ||||
-rw-r--r-- | extras/mini-os/arch/ia64/gen_off.c | 177 | ||||
-rw-r--r-- | extras/mini-os/arch/ia64/ia64.S | 224 | ||||
-rw-r--r-- | extras/mini-os/arch/ia64/ivt.S | 865 | ||||
-rw-r--r-- | extras/mini-os/arch/ia64/minios-ia64.lds | 54 | ||||
-rw-r--r-- | extras/mini-os/arch/ia64/mm.c | 132 | ||||
-rw-r--r-- | extras/mini-os/arch/ia64/sal.c | 103 | ||||
-rw-r--r-- | extras/mini-os/arch/ia64/sched.c | 74 | ||||
-rw-r--r-- | extras/mini-os/arch/ia64/time.c | 280 | ||||
-rw-r--r-- | extras/mini-os/arch/ia64/xencomm.c | 256 |
18 files changed, 3834 insertions, 0 deletions
diff --git a/extras/mini-os/arch/ia64/Makefile b/extras/mini-os/arch/ia64/Makefile new file mode 100644 index 0000000000..58f52caff1 --- /dev/null +++ b/extras/mini-os/arch/ia64/Makefile @@ -0,0 +1,56 @@ +# +# Special makefile for ia64. +# + +include arch.mk +include ../../minios.mk + +ARCH_SRCS := sal.c +ARCH_SRCS += efi.c +ARCH_SRCS += time.c +ARCH_SRCS += ivt.S +ARCH_SRCS += fw.S +ARCH_SRCS += common.c +ARCH_SRCS += time.c +ARCH_SRCS += mm.c +ARCH_SRCS += debug.c +ARCH_SRCS += sched.c +ARCH_SRCS += xencomm.c +ARCH_SRCS += __umoddi3.S +ARCH_SRCS += __udivdi3.S +ARCH_SRCS += __divdi3.S + +ARCH_OBJS := sal.o +ARCH_OBJS += efi.o +ARCH_OBJS += time.o +ARCH_OBJS += ivt.o +ARCH_OBJS += fw.o +ARCH_OBJS += common.o +ARCH_OBJS += time.o +ARCH_OBJS += mm.o +ARCH_OBJS += debug.o +ARCH_OBJS += sched.o +ARCH_OBJS += xencomm.o +ARCH_OBJS += __umoddi3.o +ARCH_OBJS += __udivdi3.o +ARCH_OBJS += __divdi3.o + +GEN_OFF_SRC := gen_off.c +GEN_OFF_BIN := gen_off +GEN_OFF_H := $(ARCH_SPEC_INC)/offsets.h + +all: $(ARCH_LIB) + +$(GEN_OFF_BIN): $(GEN_OFF_SRC) + $(CC) -o $@ $(CPPFLAGS) $< + +$(GEN_OFF_H): $(GEN_OFF_BIN) + ./$(GEN_OFF_BIN) > $(GEN_OFF_H) + +$(ARCH_LIB): $(GEN_OFF_H) $(ARCH_OBJS) $(HEAD_ARCH_OBJ) + $(AR) rv $(ARCH_LIB) $(ARCH_OBJS) + +clean: + rm -f $(ARCH_LIB) $(ARCH_OBJS) $(HEAD_ARCH_OBJ) + rm -f $(GEN_OFF_BIN) + rm -f $(GEN_OFF_H) diff --git a/extras/mini-os/arch/ia64/__divdi3.S b/extras/mini-os/arch/ia64/__divdi3.S new file mode 100644 index 0000000000..514163ca8f --- /dev/null +++ b/extras/mini-os/arch/ia64/__divdi3.S @@ -0,0 +1,141 @@ +.file "__divdi3.s" + +// $FreeBSD: src/sys/libkern/ia64/__divdi3.S,v 1.1 2000/10/04 17:53:03 dfr Exp $ +// +// Copyright (c) 2000, Intel Corporation +// All rights reserved. +// +// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, +// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, +// Intel Corporation. +// +// WARRANTY DISCLAIMER +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 INTEL OR ITS +// CONTRIBUTORS 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. +// +// Intel Corporation is the author of this code, and requests that all +// problem reports or change requests be submitted to it directly at +// http://developer.intel.com/opensource. +// + +.section .text +.proc __divdi3# +.align 32 +.global __divdi3# +.align 32 + +// 64-bit signed integer divide + +__divdi3: + +{ .mii + alloc r31=ar.pfs,2,0,0,0 + nop.i 0 + nop.i 0;; +} { .mmi + + // 64-BIT SIGNED INTEGER DIVIDE BEGINS HERE + + setf.sig f8=r32 + setf.sig f9=r33 + nop.i 0;; +} { .mfb + nop.m 0 + fcvt.xf f6=f8 + nop.b 0 +} { .mfb + nop.m 0 + fcvt.xf f7=f9 + nop.b 0;; +} { .mfi + nop.m 0 + // Step (1) + // y0 = 1 / b in f8 + frcpa.s1 f8,p6=f6,f7 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (2) + // e0 = 1 - b * y0 in f9 + (p6) fnma.s1 f9=f7,f8,f1 + nop.i 0 +} { .mfi + nop.m 0 + // Step (3) + // q0 = a * y0 in f10 + (p6) fma.s1 f10=f6,f8,f0 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (4) + // e1 = e0 * e0 in f11 + (p6) fma.s1 f11=f9,f9,f0 + nop.i 0 +} { .mfi + nop.m 0 + // Step (5) + // q1 = q0 + e0 * q0 in f10 + (p6) fma.s1 f10=f9,f10,f10 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (6) + // y1 = y0 + e0 * y0 in f8 + (p6) fma.s1 f8=f9,f8,f8 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (7) + // q2 = q1 + e1 * q1 in f9 + (p6) fma.s1 f9=f11,f10,f10 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (8) + // y2 = y1 + e1 * y1 in f8 + (p6) fma.s1 f8=f11,f8,f8 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (9) + // r2 = a - b * q2 in f10 + (p6) fnma.s1 f10=f7,f9,f6 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (10) + // q3 = q2 + r2 * y2 in f8 + (p6) fma.s1 f8=f10,f8,f9 + nop.i 0;; +} { .mfb + nop.m 0 + // Step (11) + // q = trunc (q3) + fcvt.fx.trunc.s1 f8=f8 + nop.b 0;; +} { .mmi + // quotient will be in r8 (if b != 0) + getf.sig r8=f8 + nop.m 0 + nop.i 0;; +} + + // 64-BIT SIGNED INTEGER DIVIDE ENDS HERE + +{ .mmb + nop.m 0 + nop.m 0 + br.ret.sptk b0;; +} + +.endp __divdi3 diff --git a/extras/mini-os/arch/ia64/__udivdi3.S b/extras/mini-os/arch/ia64/__udivdi3.S new file mode 100644 index 0000000000..6a1c367718 --- /dev/null +++ b/extras/mini-os/arch/ia64/__udivdi3.S @@ -0,0 +1,142 @@ +.file "__udivdi3.s" + +// $FreeBSD: src/sys/libkern/ia64/__udivdi3.S,v 1.1 2000/10/04 17:53:03 dfr Exp $ +// +// Copyright (c) 2000, Intel Corporation +// All rights reserved. +// +// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, +// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, +// Intel Corporation. +// +// WARRANTY DISCLAIMER +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 INTEL OR ITS +// CONTRIBUTORS 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. +// +// Intel Corporation is the author of this code, and requests that all +// problem reports or change requests be submitted to it directly at +// http://developer.intel.com/opensource. +// + +.section .text +.proc __udivdi3# +.align 32 +.global __udivdi3# +.align 32 + +// 64-bit unsigned integer divide + +__udivdi3: + +{ .mii + alloc r31=ar.pfs,2,0,0,0 + nop.i 0 + nop.i 0;; +} + +{ .mmi + + // 64-BIT UNSIGNED INTEGER DIVIDE BEGINS HERE + + setf.sig f8=r32 + setf.sig f9=r33 + nop.i 0;; +} { .mfb + nop.m 0 + fma.s1 f6=f8,f1,f0 + nop.b 0 +} { .mfb + nop.m 0 + fma.s1 f7=f9,f1,f0 + nop.b 0;; +} { .mfi + nop.m 0 + // Step (1) + // y0 = 1 / b in f8 + frcpa.s1 f8,p6=f6,f7 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (2) + // e0 = 1 - b * y0 in f9 + (p6) fnma.s1 f9=f7,f8,f1 + nop.i 0 +} { .mfi + nop.m 0 + // Step (3) + // q0 = a * y0 in f10 + (p6) fma.s1 f10=f6,f8,f0 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (4) + // e1 = e0 * e0 in f11 + (p6) fma.s1 f11=f9,f9,f0 + nop.i 0 +} { .mfi + nop.m 0 + // Step (5) + // q1 = q0 + e0 * q0 in f10 + (p6) fma.s1 f10=f9,f10,f10 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (6) + // y1 = y0 + e0 * y0 in f8 + (p6) fma.s1 f8=f9,f8,f8 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (7) + // q2 = q1 + e1 * q1 in f9 + (p6) fma.s1 f9=f11,f10,f10 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (8) + // y2 = y1 + e1 * y1 in f8 + (p6) fma.s1 f8=f11,f8,f8 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (9) + // r2 = a - b * q2 in f10 + (p6) fnma.s1 f10=f7,f9,f6 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (10) + // q3 = q2 + r2 * y2 in f8 + (p6) fma.s1 f8=f10,f8,f9 + nop.i 0;; +} { .mfb + nop.m 0 + // (11) q = trunc(q3) + fcvt.fxu.trunc.s1 f8=f8 + nop.b 0;; +} { .mmi + // quotient will be in r8 (if b != 0) + getf.sig r8=f8 + nop.m 0 + nop.i 0;; +} + + // 64-BIT UNSIGNED INTEGER DIVIDE ENDS HERE + +{ .mmb + nop.m 0 + nop.m 0 + br.ret.sptk b0;; +} + +.endp __udivdi3 diff --git a/extras/mini-os/arch/ia64/__umoddi3.S b/extras/mini-os/arch/ia64/__umoddi3.S new file mode 100644 index 0000000000..790317f655 --- /dev/null +++ b/extras/mini-os/arch/ia64/__umoddi3.S @@ -0,0 +1,154 @@ +.file "__umoddi3.s" + +// $FreeBSD: src/sys/libkern/ia64/__umoddi3.S,v 1.3 2003/02/11 20:15:11 schweikh Exp $ +// +// Copyright (c) 2000, Intel Corporation +// All rights reserved. +// +// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, +// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, +// Intel Corporation. +// +// WARRANTY DISCLAIMER +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 INTEL OR ITS +// CONTRIBUTORS 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. +// +// Intel Corporation is the author of this code, and requests that all +// problem reports or change requests be submitted to it directly at +// http://developer.intel.com/opensource. +// + +.section .text + + // 64-bit unsigned integer remainder + +.proc __umoddi3# +.align 32 +.global __umoddi3# +.align 32 + +__umoddi3: + +{ .mii + alloc r31=ar.pfs,3,0,0,0 + nop.i 0 + nop.i 0 +} { .mmb + + // 64-BIT UNSIGNED INTEGER REMAINDER BEGINS HERE + + // general register used: + // r32 - 64-bit unsigned integer dividend, called a below + // r33 - 64-bit unsigned integer divisor, called b below + // r8 - 64-bit unsigned integer result + // floating-point registers used: f6, f7, f8, f9, f10, f11, f12 + // predicate registers used: p6 + + setf.sig f12=r32 // holds a in integer form + setf.sig f7=r33 + nop.b 0;; +} { .mfi + // get 2s complement of b + sub r33=r0,r33 + fcvt.xuf.s1 f6=f12 + nop.i 0 +} { .mfi + nop.m 0 + fcvt.xuf.s1 f7=f7 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (1) + // y0 = 1 / b in f8 + frcpa.s1 f8,p6=f6,f7 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (2) + // q0 = a * y0 in f10 + (p6) fma.s1 f10=f6,f8,f0 + nop.i 0 +} { .mfi + nop.m 0 + // Step (3) + // e0 = 1 - b * y0 in f9 + (p6) fnma.s1 f9=f7,f8,f1 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (4) + // q1 = q0 + e0 * q0 in f10 + (p6) fma.s1 f10=f9,f10,f10 + nop.i 0 +} { .mfi + nop.m 0 + // Step (5) + // e1 = e0 * e0 in f11 + (p6) fma.s1 f11=f9,f9,f0 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (6) + // y1 = y0 + e0 * y0 in f8 + (p6) fma.s1 f8=f9,f8,f8 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (7) + // q2 = q1 + e1 * q1 in f9 + (p6) fma.s1 f9=f11,f10,f10 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (8) + // y2 = y1 + e1 * y1 in f8 + (p6) fma.s1 f8=f11,f8,f8 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (9) + // r2 = a - b * q2 in f10 + (p6) fnma.s1 f10=f7,f9,f6 + nop.i 0;; +} { .mfi + // f7=-b + setf.sig f7=r33 + // Step (10) + // q3 = q2 + r2 * y2 in f8 + (p6) fma.s1 f8=f10,f8,f9 + nop.i 0;; +} { .mfi + nop.m 0 + // (11) q = trunc(q3) + fcvt.fxu.trunc.s1 f8=f8 + nop.i 0;; +} { .mfi + nop.m 0 + // (12) r = a + (-b) * q + xma.l f8=f8,f7,f12 + nop.i 0;; +} { .mib + getf.sig r8=f8 + nop.i 0 + nop.b 0 +} + + // 64-BIT UNSIGNED INTEGER REMAINDER ENDS HERE + +{ .mib + nop.m 0 + nop.i 0 + br.ret.sptk b0;; +} + +.endp __umoddi3 diff --git a/extras/mini-os/arch/ia64/arch.mk b/extras/mini-os/arch/ia64/arch.mk new file mode 100644 index 0000000000..167e3a1f50 --- /dev/null +++ b/extras/mini-os/arch/ia64/arch.mk @@ -0,0 +1,5 @@ +ARCH_CFLAGS := -mfixed-range=f2-f5,f12-f15,f32-f127 -mconstant-gp +ARCH_CFLAGS += -O2 +ARCH_ASFLAGS := -x assembler-with-cpp +ARCH_ASFLAGS += -mfixed-range=f2-f5,f12-f15,f32-f127 -fomit-frame-pointer +ARCH_ASFLAGS += -fno-builtin -fno-common -fno-strict-aliasing -mconstant-gp diff --git a/extras/mini-os/arch/ia64/common.c b/extras/mini-os/arch/ia64/common.c new file mode 100644 index 0000000000..ee496338a2 --- /dev/null +++ b/extras/mini-os/arch/ia64/common.c @@ -0,0 +1,236 @@ +/* + * Done by Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com> + * + **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. + * + **************************************************************************** + * + * Parts are taken from FreeBSD. + * + */ + + +#include "os.h" +#include "types.h" +#include "lib.h" +#include "page.h" +#include "xen/xen.h" +#include "privop.h" +#include "xen/callback.h" +#include "ia64_cpu.h" +#include "hypervisor.h" +#include "events.h" +#include "console.h" +#include "time.h" +#include "xmalloc.h" + + +/* For more console boot messages. */ +int bootverbose; + +/* + * This structure contains start-of-day info, such as pagetable base pointer, + * address of the shared_info structure, and things like that. + */ +union start_info_union start_info_union; + +shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)XSI_BASE; + +struct machine_fw machineFwG; + + +struct xen_ia64_boot_param ia64BootParamG; +char boot_cmd_line[COMMAND_LINE_SIZE+1]; + + +void +ia64_write_itr_i(ia64_pte_t* pteP, u32 reg, uint64_t vAddr, + uint64_t ps, uint64_t pk) +{ + /* The virtual address. */ + __asm __volatile("mov cr.ifa=%0" :: "r"(vAddr)); + /* The page size */ + __asm __volatile("mov cr.itir=%0;;" :: "r"((ps << IA64_ITIR_PS)|(pk << IA64_ITIR_KEY))); + /* Put pte into instruction translation register. */ + __asm __volatile("itr.i itr[%0]=%1" :: "r"(reg), "r"(*(uint64_t*)pteP)); + /* Serialization */ + __asm __volatile("srlz.i"); +} + +void +map_pal_code(void) +{ + ia64_pte_t pte; + + xen_set_virtual_psr_ic(0); + memset(&pte, 0, sizeof(pte)); /* Prepare the pte */ + pte.pte_p = 1; /* present bit */ + pte.pte_ma = PTE_MA_WB; /* memory attribute */ + pte.pte_a = 1; /* accessed bit */ + pte.pte_d = 1; /* dirty bit */ + pte.pte_pl = PTE_PL_KERN; /* privilege level */ + pte.pte_ar = PTE_AR_RWX; /* access rights */ + pte.pte_ppn = ((uint64_t) __pa(machineFwG.ia64_pal_base)) >> 14; + pte.pte_ed = 0; /* exception deferral */ + + /* + * Must purge here because a itc/dtc with the same address + * may be in the tlb! + */ + ia64_ptc_l(machineFwG.ia64_pal_base, PTE_PS_16K); + ia64_write_itr_i(&pte, IA64_TR_PAL, + (uint64_t) machineFwG.ia64_pal_base, PTE_PS_16K, 0); + xen_set_virtual_psr_ic(1); +} + +extern char hypervisor_callback; + +static void +registerCallback(void) +{ + struct callback_register event = + { + .type = SWAP(CALLBACKTYPE_event), + .address = SWAP((unsigned long)&hypervisor_callback), + }; + HYPERVISOR_callback_op(CALLBACKOP_register, &event); +} + +static void +init_start_info(start_info_t* xen_start_info) +{ + /* Make a copy of the start_info structure */ + start_info.nr_pages = SWAP(xen_start_info->nr_pages); + start_info.shared_info = SWAP(xen_start_info->shared_info); + start_info.flags = SWAP(xen_start_info->flags); + start_info.store_mfn = SWAP(xen_start_info->store_mfn); + start_info.store_evtchn = SWAP(xen_start_info->store_evtchn); + start_info.console.domU.mfn = SWAP(xen_start_info->console.domU.mfn); + start_info.console.domU.evtchn = + SWAP(xen_start_info->console.domU.evtchn); + start_info.pt_base = SWAP(xen_start_info->pt_base); + start_info.nr_pt_frames = SWAP(xen_start_info->nr_pt_frames); + start_info.mfn_list = SWAP(xen_start_info->mfn_list); + start_info.mod_start = SWAP(xen_start_info->mod_start); + start_info.mod_len = SWAP(xen_start_info->mod_len); +} + +static void +init_boot_params(void) +{ + /* ia64_boot_paramP is initialised in ia64.S! */ + ia64BootParamG.command_line = SWAP(ia64_boot_paramP->command_line); + ia64BootParamG.efi_systab = SWAP(ia64_boot_paramP->efi_systab); + ia64BootParamG.efi_memmap = SWAP(ia64_boot_paramP->efi_memmap); + ia64BootParamG.efi_memmap_size = + SWAP(ia64_boot_paramP->efi_memmap_size); + ia64BootParamG.efi_memdesc_size = + SWAP(ia64_boot_paramP->efi_memdesc_size); + ia64BootParamG.efi_memdesc_version = + SWAP(ia64_boot_paramP->efi_memdesc_version); + ia64BootParamG.console_info.num_cols = + SWAP(ia64_boot_paramP->console_info.num_cols); + ia64BootParamG.console_info.num_rows = + SWAP(ia64_boot_paramP->console_info.num_rows); + ia64BootParamG.console_info.orig_x = + SWAP(ia64_boot_paramP->console_info.orig_x); + ia64BootParamG.console_info.orig_y = + SWAP(ia64_boot_paramP->console_info.orig_y); + ia64BootParamG.fpswa = SWAP(ia64_boot_paramP->fpswa); + ia64BootParamG.initrd_start = SWAP(ia64_boot_paramP->initrd_start); + ia64BootParamG.initrd_size = SWAP(ia64_boot_paramP->initrd_size); + ia64BootParamG.domain_start = SWAP(ia64_boot_paramP->domain_start); + ia64BootParamG.domain_size = SWAP(ia64_boot_paramP->domain_size); + + /* + * Copy and parse the boot command line. + * Currently only a check of bootverbose is done. + */ + memset(boot_cmd_line, 0, sizeof(boot_cmd_line)); + strncpy(boot_cmd_line, + (char*)__va(ia64BootParamG.command_line), COMMAND_LINE_SIZE); + boot_cmd_line[COMMAND_LINE_SIZE - 1] = '\0'; + + /* Look for bootverbose. */ + if (strstr(boot_cmd_line, "bootverbose")) + bootverbose = 1; +} + +void +arch_init(start_info_t *si) +{ + efi_time_t tm; + static int initialized; + + if (initialized) + return; + + init_start_info(si); + + init_boot_params(); + + init_efi(); + + map_pal_code(); + + ia64_sal_init(machineFwG.ia64_sal_tableP); + + if (efi_get_time(&tm)) { + printk("EFI-SystemTime: %d.%d.%d %d:%d:%d", + tm.Day, tm.Month, tm.Year, + tm.Hour, tm.Minute, tm.Second); + + if (tm.TimeZone == EFI_UNSPECIFIED_TIMEZONE) + printk(" Timezone not specified!\n"); + else + printk(" TimeZone: %d Daylight: 0x%x\n", + tm.TimeZone, tm.Daylight); + } else + printk("efi_get_time() failed\n"); + + registerCallback(); + initialized = 1; +} + +void +arch_print_info(void) +{ + int major, minor; + + minor = HYPERVISOR_xen_version(XENVER_version, 0); + major = minor >> 16; + minor &= ~0xffffffff; + printk("Running on Xen version: %d.%d\n", major, minor); + printk("machine addr of shared_info_t : 0x%lx\n", + start_info.shared_info); + printk("machine page number of shared page: 0x%lx\n", + start_info.store_mfn); + printk("evtchn for store communication : %d\n", + start_info.store_evtchn); + printk("MACHINE address of console page: 0x%lx\n", + start_info.console.domU.mfn); + printk("evtchn for console messages : %d\n", + start_info.console.domU.evtchn); + printk("xen_guest_cmdline : %s\n", boot_cmd_line); +} diff --git a/extras/mini-os/arch/ia64/debug.c b/extras/mini-os/arch/ia64/debug.c new file mode 100644 index 0000000000..d95252b4c3 --- /dev/null +++ b/extras/mini-os/arch/ia64/debug.c @@ -0,0 +1,179 @@ +/* + **************************************************************************** + * Done by Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com + * + * Description: ia64 specific part of the mini-os + * Prints debug information on a crash of mini-os + * + * Parts are taken from FreeBSD. + * + **************************************************************************** + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "os.h" + +static const char *ia64_vector_names[] = { + "VHPT Translation", /* 0 */ + "Instruction TLB", /* 1 */ + "Data TLB", /* 2 */ + "Alternate Instruction TLB", /* 3 */ + "Alternate Data TLB", /* 4 */ + "Data Nested TLB", /* 5 */ + "Instruction Key Miss", /* 6 */ + "Data Key Miss", /* 7 */ + "Dirty-Bit", /* 8 */ + "Instruction Access-Bit", /* 9 */ + "Data Access-Bit", /* 10 */ + "Break Instruction", /* 11 */ + "External Interrupt", /* 12 */ + "Reserved 13", /* 13 */ + "Reserved 14", /* 14 */ + "Reserved 15", /* 15 */ + "Reserved 16", /* 16 */ + "Reserved 17", /* 17 */ + "Reserved 18", /* 18 */ + "Reserved 19", /* 19 */ + "Page Not Present", /* 20 */ + "Key Permission", /* 21 */ + "Instruction Access Rights", /* 22 */ + "Data Access Rights", /* 23 */ + "General Exception", /* 24 */ + "Disabled FP-Register", /* 25 */ + "NaT Consumption", /* 26 */ + "Speculation", /* 27 */ + "Reserved 28", /* 28 */ + "Debug", /* 29 */ + "Unaligned Reference", /* 30 */ + "Unsupported Data Reference", /* 31 */ + "Floating-point Fault", /* 32 */ + "Floating-point Trap", /* 33 */ + "Lower-Privilege Transfer Trap", /* 34 */ + "Taken Branch Trap", /* 35 */ + "Single Step Trap", /* 36 */ + "Reserved 37", /* 37 */ + "Reserved 38", /* 38 */ + "Reserved 39", /* 39 */ + "Reserved 40", /* 40 */ + "Reserved 41", /* 41 */ + "Reserved 42", /* 42 */ + "Reserved 43", /* 43 */ + "Reserved 44", /* 44 */ + "IA-32 Exception", /* 45 */ + "IA-32 Intercept", /* 46 */ + "IA-32 Interrupt", /* 47 */ + "Reserved 48", /* 48 */ + "Reserved 49", /* 49 */ + "Reserved 50", /* 50 */ + "Reserved 51", /* 51 */ + "Reserved 52", /* 52 */ + "Reserved 53", /* 53 */ + "Reserved 54", /* 54 */ + "Reserved 55", /* 55 */ + "Reserved 56", /* 56 */ + "Reserved 57", /* 57 */ + "Reserved 58", /* 58 */ + "Reserved 59", /* 59 */ + "Reserved 60", /* 60 */ + "Reserved 61", /* 61 */ + "Reserved 62", /* 62 */ + "Reserved 63", /* 63 */ + "Reserved 64", /* 64 */ + "Reserved 65", /* 65 */ + "Reserved 66", /* 66 */ + "Reserved 67", /* 67 */ +}; + +typedef struct +{ +#if !defined(BIG_ENDIAN) + uint64_t sof :7; /* 0-6 size of frame */ + uint64_t sol :7; /* 7-13 size of locals (in + loc) */ + uint64_t sor :4; + uint64_t rrb_gr :7; + uint64_t rrb_fr :7; + uint64_t rrb_pr :6; + uint64_t res :25; /* reserved */ + uint64_t v :1; /* The v bit */ +#else /* !BIG_ENDIAN */ + uint64_t v :1; /* The v bit */ + uint64_t res :25; /* reserved */ + uint64_t rrb_pr :6; + uint64_t rrb_fr :7; + uint64_t rrb_gr :7; + uint64_t sor :4; + uint64_t sol :7; /* 7-13 size of locals (in + loc) */ + uint64_t sof :7; /* 0-6 size of frame */ +#endif /* BIG_ENDIAN */ +} ifs_t; + +void +do_trap_error(trap_frame_t* tf) +{ + ifs_t curIfs; + + printk("TRAP in mini-os:\n"); + printk(" trap: %d (%s)\n", tf->trap_num, + ia64_vector_names[tf->trap_num]); + printk(" iip : 0x%.16lx ifa: 0x%.16lx\n", tf->iip, tf->ifa); + printk(" ipsr: 0x%.16lx ifs: 0x%.16lx\n", tf->ipsr, tf->ifs); + printk(" isr : 0x%.16lx\n", tf->isr); + printk(" gp : 0x%.16lx sp : 0x%.16lx\n", tf->gp, tf->sp); + printk(" rp : 0x%.16lx tp : 0x%.16lx\n", tf->b0, tf->tp); + printk(" b6 : 0x%.16lx b7 : 0x%.16lx\n", tf->b6, tf->b7); + printk(" r8 : 0x%.16lx\n", tf->r8); + printk(" bsp : 0x%.16lx rsc: 0x%.16lx\n", tf->bsp, tf->rsc); + printk(" r14 : 0x%.16lx r15: 0x%.16lx\n", tf->r14, tf->r15); + printk(" r16 : 0x%.16lx r17: 0x%.16lx\n", tf->r16, tf->r17); + printk(" r18 : 0x%.16lx r19: 0x%.16lx\n", tf->r18, tf->r19); + printk(" r20 : 0x%.16lx r21: 0x%.16lx\n", tf->r20, tf->r21); + printk(" r22 : 0x%.16lx r23: 0x%.16lx\n", tf->r22, tf->r23); + printk(" r24 : 0x%.16lx r25: 0x%.16lx\n", tf->r24, tf->r25); + printk(" r26 : 0x%.16lx r27: 0x%.16lx\n", tf->r26, tf->r27); + printk(" r28 : 0x%.16lx r29: 0x%.16lx\n", tf->r28, tf->r29); + printk(" r30 : 0x%.16lx r31: 0x%.16lx\n", tf->r30, tf->r31); + + __asm __volatile("flushrs;;"); + curIfs = *((ifs_t*)((void*)(&tf->ifs))); + if (!curIfs.v) + printk(" ifs.v = 0"); + else { + uint64_t* regP; + uint32_t i; + + printk(" cfm.sof: %d cfm.sol: %d\n", curIfs.sof, curIfs.sol); + regP = (uint64_t *)(tf->bsp + tf->ndirty); + for (i = curIfs.sof; i != 0; ) { + if (i <= (((uint64_t)regP & 0x000001f8) >> 3)) { + regP -= i; + i = 0; + break; + } + i -= ((uint64_t)regP & 0x000001f8) >> 3; + regP = (uint64_t *)((uint64_t)regP & ~0x000001ff) - 1; + } + for (i = 0; i < curIfs.sof; i++) { + if (((uint64_t)regP & 0x000001f8) == 0x000001f8) + regP++; + printk(" r%d: 0x%lx\n", i+32, *regP); + regP++; + } + } + HYPERVISOR_shutdown(SHUTDOWN_poweroff); +} diff --git a/extras/mini-os/arch/ia64/efi.c b/extras/mini-os/arch/ia64/efi.c new file mode 100644 index 0000000000..498eac42ad --- /dev/null +++ b/extras/mini-os/arch/ia64/efi.c @@ -0,0 +1,237 @@ +/* + * Done by Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com> + * The code is partly taken from FreeBSD. + * + *************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 "os.h" +#include "efi.h" +#include "page.h" +#include "lib.h" +#include "console.h" + + +/* The implementation is in fw.S. */ +extern uint64_t +ia64_call_efi_func(uint64_t funcP,uint64_t a,uint64_t b,uint64_t c,uint64_t d); + +int +efi_get_time(efi_time_t* tmP) +{ + memset(tmP, 0, sizeof(efi_time_t)); + if (ia64_call_efi_func((uint64_t)machineFwG.efi.getTimeF, + (uint64_t)tmP, + (uint64_t)NULL, 0, 0) != EFI_SUCCESS) { + printk("efi.getTime() failed\n"); + return 0; + } + +#if defined(BIG_ENDIAN) + tmP->Year = SWAP(tmP->Year); + tmP->TimeZone = SWAP(tmP->TimeZone); + tmP->Nanosecond = SWAP(tmP->Nanosecond); +#endif + + return 1; +} + +/* + * The function compares two efi_guid_t and returns 0 on equality, otherwise 1. + */ +static int +efi_guid_cmp(efi_guid_t* a_le, efi_guid_t* b) +{ +#if defined(BIG_ENDIAN) + if(SWAP(a_le->Data1) != b->Data1) + return 1; + if(SWAP(a_le->Data2) != b->Data2) + return 1; + if(SWAP(a_le->Data3) != b->Data3) + return 1; + return memcmp(a_le->Data4, b->Data4, sizeof(uint8_t)*8); +#else + return memcmp(a_le, b, sizeof(efi_guid_t)); +#endif +} + +void +init_efi(void) +{ + efi_system_table_t* efiSysTableP; + int mdcnt, i, numConvMem; + efi_memory_descriptor_t *memdP, *mdP; + efi_status_t status; + char fwVendor[100] = "unknown"; + efi_char16_t* fwP; + efi_runtime_services_t* rsP; + + efi_configuration_table_t* confP = (efi_configuration_table_t*)0; + efi_guid_t sal = SAL_SYSTEM_TABLE_GUID; + efi_guid_t acpi = ACPI_TABLE_GUID; + efi_guid_t acpi20 = ACPI_20_TABLE_GUID; + + memset(&machineFwG, 0, sizeof(machineFwG)); + /* Read the efi_system_table. */ + efiSysTableP = (efi_system_table_t*)__va(ia64BootParamG.efi_systab); + machineFwG.efi.efiSysTableP = efiSysTableP; + PRINT_BV("EfiSystemTable at: %p\n", efiSysTableP); + fwP = (uint16_t*) __va(SWAP(efiSysTableP->FirmwareVendor)); + if (fwP) { + for (i = 0; i < (int)sizeof(fwVendor) - 1 && *fwP; ++i) + fwVendor[i] = SWAP(*fwP++); + fwVendor[i] = '\0'; + } + PRINT_BV(" EFI-FirmwareVendor : %s\n", fwVendor); + PRINT_BV(" EFI-FirmwareRevision : %d\n", + SWAP(efiSysTableP->FirmwareRevision)); + PRINT_BV(" EFI-SystemTable-Revision : %d.%d\n", + SWAP(efiSysTableP->Hdr.Revision)>>16, + SWAP(efiSysTableP->Hdr.Revision)&0xffff); + rsP = (efi_runtime_services_t*) + __va(SWAP(efiSysTableP->RuntimeServices)); + mdcnt = ia64BootParamG.efi_memmap_size / + ia64BootParamG.efi_memdesc_size; + memdP = (efi_memory_descriptor_t*) __va(ia64BootParamG.efi_memmap); + + PRINT_BV("EFI-Memorydescriptors: %d\n", mdcnt); + + for (i = numConvMem = 0, mdP = memdP; i < mdcnt; i++, + mdP = NextMemoryDescriptor(mdP, ia64BootParamG.efi_memdesc_size)) { + /* Relocate runtime memory segments for firmware. */ + PRINT_BV(" %d. Type: %x Attributes: 0x%lx\n", + i, SWAP(mdP->Type), SWAP(mdP->Attribute)); + PRINT_BV(" PhysStart: 0x%lx NumPages: 0x%lx\n", + SWAP(mdP->PhysicalStart), SWAP(mdP->NumberOfPages)); + switch (SWAP(mdP->Type)) { + case EfiRuntimeServicesData: + PRINT_BV(" -> EfiRuntimeServicesData\n"); + break; + case EfiACPIReclaimMemory: + PRINT_BV(" -> EfiACPIReclaimMemory\n"); + break; + case EfiACPIMemoryNVS: + PRINT_BV(" -> EfiACPIMemoryNVS\n"); + break; + case EfiConventionalMemory: + PRINT_BV(" -> EfiConventionalMemory\n"); + PRINT_BV(" start: 0x%lx end: 0x%lx\n", + SWAP(mdP->PhysicalStart), + SWAP(mdP->PhysicalStart)+ + SWAP(mdP->NumberOfPages)*EFI_PAGE_SIZE); + if (numConvMem) { + printk(" Currently only one efi " + "memory chunk supported !!!\n"); + break; + } + machineFwG.mach_mem_start = + SWAP(mdP->PhysicalStart); + machineFwG.mach_mem_size = + SWAP(mdP->NumberOfPages)*EFI_PAGE_SIZE; + numConvMem++; + break; + case EfiMemoryMappedIOPortSpace: + PRINT_BV(" -> EfiMemMappedIOPortSpace\n"); + break; + case EfiPalCode: + machineFwG.ia64_pal_base = + __va(SWAP(mdP->PhysicalStart)); + PRINT_BV(" -> EfiPalCode\n" + " start : %p\n", + machineFwG.ia64_pal_base); + break; + } + /* I have to setup the VirtualStart address of every + * RUNTIME-area in preparing the later call of + * SetVirtualAddressMap() therewidth the efi stuff uses + * virtual addressing and the efi runtime functions + * may be called directly. + */ + if (SWAP(mdP->Attribute) & EFI_MEMORY_RUNTIME) { + if (SWAP(mdP->Attribute) & EFI_MEMORY_WB) + mdP->VirtualStart = + SWAP(__va(mdP->PhysicalStart)); + else { + if (SWAP(mdP->Attribute) & EFI_MEMORY_UC) + printk("efi_init: RuntimeMemory with " + "UC attribute !!!!!!\n"); + /* + mdP->VirtualStart = + IA64_PHYS_TO_RR6(mdP->PhysicalStart); + */ + } + } + } + /* Now switch efi runtime stuff to virtual addressing. */ + status = ia64_call_efi_physical( + (void*)__va(SWAP((uint64_t)rsP->SetVirtualAddressMap)), + ia64BootParamG.efi_memmap_size, + ia64BootParamG.efi_memdesc_size, + ia64BootParamG.efi_memdesc_version, + ia64BootParamG.efi_memmap); + status = EFI_SUCCESS; + if (status != EFI_SUCCESS) { + printk("warning: unable to switch EFI into virtual " + "(status=%lu)\n", status); + return; + } + /* Getting efi function pointer for getEfiTime. */ + machineFwG.efi.getTimeF = + (efi_get_time_t)__va(SWAP((uint64_t)rsP->GetTime)); + /* Getting efi function pointer for resetSystem. */ + machineFwG.efi.resetSystemF = + (efi_reset_system_t)__va(SWAP((uint64_t)rsP->ResetSystem)); + + /* Scanning the Configuration table of the EfiSystemTable. */ + PRINT_BV("NumberOfConfigTableEntries: %ld\n", + SWAP(efiSysTableP->NumberOfTableEntries)); + + confP = (efi_configuration_table_t*) + __va(SWAP(efiSysTableP->ConfigurationTable)); + for (i = 0; i < SWAP(efiSysTableP->NumberOfTableEntries); i++) { + if (!efi_guid_cmp(&confP[i].VendorGuid, &sal)) { + machineFwG.ia64_sal_tableP = (sal_system_table_t*) + __va(SWAP((uint64_t) confP[i].VendorTable)); + PRINT_BV(" Found SalSystemTable at: 0x%lx\n", + (uint64_t) machineFwG.ia64_sal_tableP); + continue; + } + if (!efi_guid_cmp(&confP[i].VendorGuid, &acpi)) { + machineFwG.ia64_efi_acpi_table = + __va(SWAP((uint64_t) confP[i].VendorTable)); + PRINT_BV(" Found AcpiTable at: 0x%lx\n", + (uint64_t) machineFwG.ia64_efi_acpi_table); + continue; + } + if (!efi_guid_cmp(&confP[i].VendorGuid, &acpi20)) { + machineFwG.ia64_efi_acpi20_table = + __va(SWAP((uint64_t) confP[i].VendorTable)); + PRINT_BV(" Found Acpi20Table at: 0x%lx\n", + (uint64_t) machineFwG.ia64_efi_acpi20_table); + continue; + } + } +} diff --git a/extras/mini-os/arch/ia64/fw.S b/extras/mini-os/arch/ia64/fw.S new file mode 100644 index 0000000000..db89dfa934 --- /dev/null +++ b/extras/mini-os/arch/ia64/fw.S @@ -0,0 +1,519 @@ +/* + * Done by Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com> + * Parts taken from FreeBSD. + * + *************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 "asm.h" +#include "page.h" +#include "ia64_cpu.h" +#include "ia64_fpu.h" +#include "offsets.h" + + +/* + * ia64_change_mode: change mode to/from physical mode + * + * Arguments: + * r14 psr for desired mode + * + * Modifies: + * r15-r20 scratch + * ar.bsp translated to new mode + * sp translated to new mode + * iip translated to new mode + */ +ENTRY(ia64_change_mode) + rsm psr.i | psr.ic + mov r19=ar.rsc // save rsc while we change mode + tbit.nz p8,p9=r14,17 // Uses psr.dt-physical or virtual ? + // p8 == true: switch to virtual + // p9 == true: switch to physical + ;; + mov ar.rsc=IA64_RSE_LAZY // turn off RSE + mov r16=rp + ;; + flushrs // clean the rse + srlz.i + ;; +1: mov r15=ip + mov r17=ar.bsp + mov r18=ar.rnat + ;; + add r15=2f-1b,r15 // address to rfi to + /* !!! must be the same like in minios-ia64.lds */ +(p8) movl r20=(KERNEL_START - (1<<KERNEL_PHYS_START_SHIFT)) + ;; + // (p8): switch to virtual + // (p9): switch to physical + + // from virtual to physical +(p9) tpa r15=r15 // ip +(p9) tpa r16=r16 // rp +(p9) tpa r17=r17 // ar.bsp +(p9) tpa sp=sp // sp + ;; /* Needed only for assembler violate ... warnings. */ + // from physical to virtual +(p8) add r15=r20,r15 // ip +(p8) add r16=r20,r16 // rp +(p8) add r17=r20,r17 // ar.bsp +(p8) add sp=r20,sp // sp + ;; + mov ar.bspstore=r17 + mov rp=r16 + ;; + mov ar.rnat=r18 + mov cr.iip=r15 + mov cr.ipsr=r14 // psr for new mode + mov cr.ifs=r0 + ;; + rfi + ;; +2: mov ar.rsc=r19 // restore ar.rsc + ;; + br.ret.sptk.few rp // now in new mode +END(ia64_change_mode) + +/* + * ia64_physical_mode: change mode to physical mode + * + * Return: + * ret0 psr to restore + * + * Modifies: + * r15-r18 scratch + * ar.bsp tranlated to physical mode + * psr.i cleared + */ +ENTRY(ia64_physical_mode) + mov r14=psr + movl r15=(IA64_PSR_I|IA64_PSR_IT|IA64_PSR_DT| \ + IA64_PSR_RT|IA64_PSR_DFL|IA64_PSR_DFH) + ;; + mov ret0=r14 + movl r16=IA64_PSR_BN + ;; + andcm r14=r14,r15 // clear various xT bits + ;; + or r14=r14,r16 // make sure BN=1 + or ret0=ret0,r16 // make sure BN=1 + ;; + br.cond.sptk.many ia64_change_mode +END(ia64_physical_mode) + +/* + * ia64_call_efi_physical: call an EFI procedure in physical mode + * + * Arguments: + * in0 Address of EFI procedure descriptor + * in1-in5 Arguments to EFI procedure + * + * Return: + * ret0-ret3 return values from EFI + * + */ +ENTRY(ia64_call_efi_physical) + .prologue + .regstk 6,4,5,0 + .save ar.pfs,loc0 + alloc loc0=ar.pfs,6,4,5,0 + ;; + .save rp,loc1 + mov loc1=rp + ;; + .body + br.call.sptk.many rp=ia64_physical_mode + ;; + + mov loc2=r8 // psr to restore mode + mov loc3=gp // save kernel gp + ld8 r14=[in0],8 // function address + ;; + ld8 gp=[in0] // function gp value +#if defined(BIG_ENDIAN) + mux1 r14=r14,@rev // swap because mini-os is in BE + mov ar.rsc=3 + ;; +#endif + mov out0=in1 + mov out1=in2 + mov out2=in3 + mov out3=in4 + mov out4=in5 + mov b6=r14 + ;; +#if defined(BIG_ENDIAN) + mux1 gp=gp,@rev // swap because mini-os is in BE + rum IA64_PSR_BE + ;; +#endif + + br.call.sptk.many rp=b6 // call EFI procedure + +#if defined(BIG_ENDIAN) + ;; + sum IA64_PSR_BE + mov ar.rsc=IA64_RSE_EAGER +#endif + mov gp=loc3 // restore kernel gp + mov r14=loc2 // psr to restore mode + ;; + br.call.sptk.many rp=ia64_change_mode + ;; + mov rp=loc1 + mov ar.pfs=loc0 + ;; + br.ret.sptk.many rp +END(ia64_call_efi_physical) + + +/* + * struct ia64_pal_result ia64_call_pal_static(uint64_t proc, + * uint64_t arg1, uint64_t arg2, uint64_t arg3) + */ +ENTRY(ia64_call_pal_static) + + .regstk 4,5,0,0 +palret = loc0 +entry = loc1 +rpsave = loc2 +pfssave = loc3 +psrsave = loc4 + + alloc pfssave=ar.pfs,4,5,0,0 + ;; + mov rpsave=rp + + movl entry=@gprel(ia64_pal_entry) +1: mov palret=ip // for return address + ;; + add entry=entry,gp + mov psrsave=psr + mov r28=in0 // procedure number + ;; + ld8 entry=[entry] // read entry point + mov r29=in1 // copy arguments + mov r30=in2 + mov r31=in3 + ;; + mov b6=entry + add palret=2f-1b,palret // calculate return address + ;; + mov b0=palret + rsm psr.i // disable interrupts + ;; +#if defined(BIG_ENDIAN) + rum IA64_PSR_BE // set psr.be==0 + ;; +#endif + br.cond.sptk b6 // call into firmware + ;; +#if defined(BIG_ENDIAN) + sum IA64_PSR_BE // set psr.be==1 + ;; +#endif + ssm psr.i // enable interrupts + ;; +2: mov psr.l=psrsave + mov rp=rpsave + mov ar.pfs=pfssave + ;; + srlz.d + br.ret.sptk rp + +END(ia64_call_pal_static) + +/* + * Call a efi function. + * in0: func descriptor + * in1: param1 + * ... + * in5: param5 + */ +ENTRY(ia64_call_efi_func) + alloc loc0=ar.pfs,6,3,5,0 + + mov loc1=gp + mov loc2=rp + + mov out0=in1 + mov out1=in2 + mov out2=in3 + mov out3=in4 + mov out4=in5 + + ld8 r14=[in0],8 // get function address + ;; + ld8 gp=[in0] // function gp value + ;; +#if defined(BIG_ENDIAN) + mux1 r14=r14,@rev // swap if mini-os is in BE + mux1 gp=gp,@rev // swap if mini-os is in BE +#endif + ;; + mov b6=r14 + +#if defined(BIG_ENDIAN) + rum IA64_PSR_BE + ;; +#endif + + br.call.sptk.many rp=b6 // call EFI procedure + +#if defined(BIG_ENDIAN) + sum IA64_PSR_BE + ;; +#endif + + mov ar.pfs=loc0 + mov gp=loc1 + mov rp=loc2 + br.ret.sptk rp + +END(ia64_call_efi_func) + + +/* Restore the context from the thread context. + */ +ENTRY(restore_context) +{ .mmi + invala + mov ar.rsc=IA64_RSE_LAZY + add r29=SW_SP,in0 +} + add r30=SW_RP,in0 + add r31=SW_PR,in0 + ;; + ld8 r12=[r29],SW_LC-SW_SP // load sp + ld8 r16=[r30],SW_BSP-SW_RP // load rp + ;; + ld8 r17=[r31],SW_RNAT-SW_PR // load pr + ld8 r18=[r30],SW_PFS-SW_BSP // load bsp + mov rp=r16 + ;; + ld8 r16=[r31],SW_R4-SW_RNAT // load rnat + mov pr=r17,-1 // set pr + mov ar.bspstore=r18 + ;; + ld8 r18=[r30],SW_UNATA-SW_PFS // load pfs + ld8 r17=[r29],SW_UNATB-SW_LC // load lc + mov ar.rnat=r16 + ;; + ld8 r16=[r30],SW_R5-SW_UNATA // load unat_a + mov ar.pfs=r18 + mov ar.lc=r17 + ;; + ld8.fill r4=[r31],SW_R6-SW_R4 // load r4 + mov ar.unat=r16 + ;; + ld8.fill r5=[r30],SW_R7-SW_R5 // load r5 + ld8 r16=[r29],SW_B3-SW_UNATB // load unat_b + mov ar.rsc=IA64_RSE_EAGER + ;; + ld8.fill r6=[r31],SW_B1-SW_R6 // load r6 + ld8.fill r7=[r30],SW_B2-SW_R7 // load r7 + ;; + ld8 r17=[r31],SW_B4-SW_B1 // load b1 + ld8 r18=[r30],SW_B5-SW_B2 // load b2 + mov ar.unat=r16 // unat_b + ;; + ld8 r16=[r29],SW_F2-SW_B3 // load b3 + mov b1=r17 + mov b2=r18 + ;; + ld8 r17=[r31],SW_F3-SW_B4 // load b4 + ld8 r18=[r30],SW_F4-SW_B5 // load b5 + mov b3=r16 + ;; + ldf.fill f2=[r29] // load f2 + mov b4=r17 + mov b5=r18 + ;; + ldf.fill f3=[r31],SW_F5-SW_F3 // load f3 + ldf.fill f4=[r30],SW_F4-SW_F2 // load f4 + ;; + ldf.fill f5=[r31],SW_F5-SW_F3 // load f5 + ldf.fill f16=[r30],SW_F4-SW_F2 // load f16 + ;; + ldf.fill f17=[r31],SW_F5-SW_F3 // load f17 + ldf.fill f18=[r30],SW_F4-SW_F2 // load f18 + ;; + ldf.fill f19=[r31],SW_F5-SW_F3 // load f19 + ldf.fill f20=[r30],SW_F4-SW_F2 // load f20 + ;; + ldf.fill f21=[r31],SW_F5-SW_F3 // load f21 + ldf.fill f22=[r30],SW_F4-SW_F2 // load f22 + ;; + ldf.fill f23=[r31],SW_F5-SW_F3 // load f23 + ldf.fill f24=[r30],SW_F4-SW_F2 // load f24 + ;; + ldf.fill f25=[r31],SW_F5-SW_F3 // load f25 + ldf.fill f26=[r30],SW_F4-SW_F2 // load f26 + ;; + ldf.fill f27=[r31],SW_F5-SW_F3 // load f27 + ldf.fill f28=[r30],SW_F4-SW_F2 // load f28 + ;; + ldf.fill f29=[r31],SW_F5-SW_F3 // load f29 + ldf.fill f30=[r30],SW_F4-SW_F2 // load f30 + ;; + ldf.fill f31=[r30],SW_F4-SW_F2 // load f31 + add r8=1,r0 + br.ret.sptk rp + ;; +END(restore_context) + +/* + * void switch_context(struct thread* old, struct thread* new) + */ +ENTRY(switch_context) + + mov ar.rsc=IA64_RSE_LAZY + mov r16=ar.unat + add r31=SW_UNATB,in0 + add r30=SW_SP,in0 + ;; +{ .mmi + flushrs + st8 [r30]=sp,SW_RP-SW_SP // sp + mov r17=rp + ;; +} + st8 [r31]=r16,SW_PR-SW_UNATB // unat (before) + st8 [r30]=r17,SW_BSP-SW_RP // rp + mov r16=pr + ;; + st8 [r31]=r16,SW_PFS-SW_PR // pr + mov r17=ar.bsp + mov r16=ar.pfs + ;; + st8 [r31]=r16,SW_RNAT-SW_PFS // save pfs + st8 [r30]=r17,SW_R4-SW_BSP // save bsp + mov r16=ar.rnat + ;; + st8 [r31]=r16,SW_R5-SW_RNAT // save rnat + mov ar.rsc=IA64_RSE_EAGER + ;; +{ .mmi + .mem.offset 8,0 + st8.spill [r30]=r4,SW_R6-SW_R4 // r4 + .mem.offset 16,0 + st8.spill [r31]=r5,SW_R7-SW_R5 // r5 + mov r16=b1 + ;; +} +{ .mmi + .mem.offset 8,0 + st8.spill [r30]=r4,SW_B1-SW_R6 // r6 + .mem.offset 16,0 + st8.spill [r31]=r5,SW_B2-SW_R7 // r7 + mov r17=b2 + ;; +} + st8 [r30]=r16,SW_UNATA-SW_B1 // b1 + st8 [r31]=r17,SW_B3-SW_B2 // b2 + mov r18=ar.unat + mov r19=b3 + mov r20=b4 + mov r21=b5 + ;; + st8 [r30]=r18,SW_B4-SW_UNATA // unat (after) + st8 [r31]=r19,SW_B5-SW_B3 // b3 + ;; + st8 [r30]=r20,SW_LC-SW_B4 // b4 + st8 [r31]=r21,SW_F2-SW_B5 // b5 + mov r17=ar.lc + ;; + st8 [r30]=r17,SW_F3-SW_LC // ar.lc + stf.spill [r31]=f2,SW_F4-SW_F2 + ;; + stf.spill [r30]=f3,SW_F5-SW_F3 + stf.spill [r31]=f4,SW_F4-SW_F2 + ;; + stf.spill [r30]=f5,SW_F5-SW_F3 + stf.spill [r31]=f16,SW_F4-SW_F2 + ;; + stf.spill [r30]=f17,SW_F5-SW_F3 + stf.spill [r31]=f18,SW_F4-SW_F2 + ;; + stf.spill [r30]=f19,SW_F5-SW_F3 + stf.spill [r31]=f20,SW_F4-SW_F2 + ;; + stf.spill [r30]=f21,SW_F5-SW_F3 + stf.spill [r31]=f22,SW_F4-SW_F2 + ;; + stf.spill [r30]=f23,SW_F5-SW_F3 + stf.spill [r31]=f24,SW_F4-SW_F2 + ;; + stf.spill [r30]=f25,SW_F5-SW_F3 + stf.spill [r31]=f26,SW_F4-SW_F2 + ;; + stf.spill [r30]=f27,SW_F5-SW_F3 + stf.spill [r31]=f28,SW_F4-SW_F2 + ;; + stf.spill [r30]=f29,SW_F4-SW_F2 + stf.spill [r31]=f30 + ;; + stf.spill [r30]=f31 + add r8=0,r0 + mf +// br.ret.sptk rp + +{ .mfb + mov r32=r33 + nop 0 + br.sptk restore_context + ;; +} + +END(switch_context) + +/* + * The function is used to start a new thread. + */ +ENTRY(thread_starter) + + .prologue + .save ar.pfs,loc0 + alloc loc0=ar.pfs,0,1,1,0 + ;; + .body + ;; + mov b7=r4 // the function pointer + mov out0=r6 // the argument + ;; + br.call.sptk.many rp=b7 // Call the thread function + ;; + br.call.sptk.many rp=exit_thread // call exit_thread + ;; +END(thread_starter) + +ENTRY(__hypercall) + mov r2=r37 + break 0x1000 + br.ret.sptk.many b0 + ;; +END(__hypercall) diff --git a/extras/mini-os/arch/ia64/gen_off.c b/extras/mini-os/arch/ia64/gen_off.c new file mode 100644 index 0000000000..b5d2f15c1e --- /dev/null +++ b/extras/mini-os/arch/ia64/gen_off.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2007 Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com> + * + ****************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <stdio.h> +#include <stddef.h> +#include <string.h> +#include "types.h" +#include "sched.h" +#include "xen/xen.h" +#include "xen/arch-ia64.h" + +#define SZ(st,e) sizeof(((st *)0)->e) +#define OFF(st,e,d,o) print_define(fp, #d, offsetof(st, e) + o, SZ(st, e)) +#define TFOFF(e,d) OFF(trap_frame_t, e, d, 0) +#define SIZE(st,d) fprintf(fp, "#define %-30s\t0x%016lx\n", #d, sizeof(st)) + +#define SWOFF(e,d) OFF(struct thread, e, d, 0) + +/* shared_info_t from xen/xen.h */ +#define SI_OFF(e, d) OFF(shared_info_t, e, d,0) +/* mapped_regs_t from xen/arch-ia64.h */ +#define MR_OFF(e, d) OFF(mapped_regs_t, e, d, XMAPPEDREGS_OFS) + +void +print_define(FILE *fp, char *name, uint64_t val, int size) +{ + char ld_name[64]; + char st_name[64]; + char sz_name[64]; + + strcpy(ld_name, name); + strcat(ld_name, "_ld"); + strcpy(st_name, name); + strcat(st_name, "_st"); + strcpy(sz_name, name); + strcat(sz_name, "_sz"); + fprintf(fp, "#define %-30s\t0x%016lx\n", name, val); + fprintf(fp, "#define %-30s\t%u\n", sz_name, size); + switch (size) { + case 1: + fprintf(fp, "#define %-30s\tld1\n", ld_name); + fprintf(fp, "#define %-30s\tst1\n", st_name); + break; + case 2: + fprintf(fp, "#define %-30s\tld2\n", ld_name); + fprintf(fp, "#define %-30s\tst2\n", st_name); + break; + case 4: + fprintf(fp, "#define %-30s\tld4\n", ld_name); + fprintf(fp, "#define %-30s\tst4\n", st_name); + break; + case 8: + fprintf(fp, "#define %-30s\tld8\n", ld_name); + fprintf(fp, "#define %-30s\tst8\n", st_name); + break; + default: ; + } + return; +} + + +int +main(int argc, char ** argv) +{ + FILE *fp; + + fp = stdout; + + TFOFF(cfm, TF_CFM); + TFOFF(pfs, TF_PFS); + TFOFF(bsp, TF_BSP); + TFOFF(rnat, TF_RNAT); + TFOFF(csd, TF_CSD); + TFOFF(ccv, TF_CCV); + TFOFF(unat, TF_UNAT); + TFOFF(fpsr, TF_FPSR); + TFOFF(pr, TF_PR); + + TFOFF(sp, TF_SP); + TFOFF(gp, TF_GP); + TFOFF(tp, TF_TP); + + TFOFF(r2, TF_GREG2); + TFOFF(r3, TF_GREG3); + TFOFF(r16, TF_GREG16); + TFOFF(r17, TF_GREG17); + + TFOFF(b0, TF_BREG0); + TFOFF(b6, TF_BREG6); + TFOFF(b7, TF_BREG7); + + TFOFF(f6, TF_FREG6); + TFOFF(f7, TF_FREG7); + + TFOFF(rsc, TF_RSC); + TFOFF(ndirty, TF_NDIRTY); + TFOFF(ssd, TF_SSD); + TFOFF(iip, TF_IIP); + TFOFF(ipsr, TF_IPSR); + TFOFF(ifs, TF_IFS); + TFOFF(trap_num, TF_TRAP_NUM); + + TFOFF(ifa, TF_IFA); + TFOFF(isr, TF_ISR); + TFOFF(iim, TF_IIM); + + SIZE(trap_frame_t, TF_SIZE); + + SIZE(struct thread, SW_SIZE); + SWOFF(regs.unat_b, SW_UNATB); + SWOFF(regs.sp, SW_SP); + SWOFF(regs.rp, SW_RP); + SWOFF(regs.pr, SW_PR); + SWOFF(regs.pfs, SW_PFS); + SWOFF(regs.bsp, SW_BSP); + SWOFF(regs.rnat, SW_RNAT); + SWOFF(regs.lc, SW_LC); + //SWOFF(regs.fpsr, SW_FPSR); + //SWOFF(regs.psr, SW_PSR); + //SWOFF(regs.gp, SW_GP); + SWOFF(regs.unat_a, SW_UNATA); + SWOFF(regs.r4, SW_R4); + SWOFF(regs.r5, SW_R5); + SWOFF(regs.r6, SW_R6); + SWOFF(regs.r7, SW_R7); + SWOFF(regs.b1, SW_B1); + SWOFF(regs.b2, SW_B2); + SWOFF(regs.b3, SW_B3); + SWOFF(regs.b4, SW_B4); + SWOFF(regs.b5, SW_B5); + SWOFF(regs.f2, SW_F2); + SWOFF(regs.f3, SW_F3); + SWOFF(regs.f4, SW_F4); + SWOFF(regs.f5, SW_F5); + + SI_OFF(arch.start_info_pfn, START_INFO_PFN); + MR_OFF(interrupt_mask_addr, XSI_PSR_I_ADDR_OFS); + MR_OFF(interrupt_collection_enabled, XSI_PSR_IC_OFS); + MR_OFF(ipsr, XSI_IPSR_OFS); + MR_OFF(iip, XSI_IIP_OFS); + MR_OFF(ifs, XSI_IFS_OFS); + MR_OFF(ifa, XSI_IFA_OFS); + MR_OFF(iim, XSI_IIM_OFS); + MR_OFF(iim, XSI_IIM_OFS); + MR_OFF(iipa, XSI_IIPA_OFS); + MR_OFF(isr, XSI_ISR_OFS); + MR_OFF(banknum, XSI_BANKNUM_OFS); + MR_OFF(bank1_regs[0], XSI_BANK1_R16_OFS); + MR_OFF(precover_ifs, XSI_PRECOVER_IFS_OFS); + + return(0); +} diff --git a/extras/mini-os/arch/ia64/ia64.S b/extras/mini-os/arch/ia64/ia64.S new file mode 100644 index 0000000000..63721b4c36 --- /dev/null +++ b/extras/mini-os/arch/ia64/ia64.S @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2007 Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com> + * + ***************************************************************************** + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + + + +#include "asm.h" +#include "page.h" +#include "ia64_cpu.h" +#include "ia64_fpu.h" +#include "privop.h" +#include "offsets.h" + + + + /* + * Allocate kernel stack area. + * This is used for stack pointer (goes down from kstack+PAGE_SIZE) and + * RSE (goes up from kstack). + */ + .section .data.start,"aw" + .global kstack + .align PAGE_SIZE +kstack: .space KSTACK_PAGES * PAGE_SIZE + + .text + + /* + * Start the kernel. + * r28 points to the address of the boot parameter area, given + * from the bootloader. + * Execution reaches here in physical mode. + */ +ENTRY(_start) + .prologue + .save rp, r0 // terminate unwind chain with a NULL rp + .body + + alloc loc0=ar.pfs,0,1,1,0 + + rsm psr.i | psr.ic + ;; + srlz.i + ;; + + /* + * Initialize mini-os region registers: + * Currently only region registers 5 and 7 are used for addressing. + * rr[5] : virtual kernel address space + * rr[7] : directly mapped physically addresses. + */ + movl r2=0<<IA64_RR_IDX_POS + movl r3=1<<IA64_RR_IDX_POS + ;; + mov rr[r2]=r0 + mov rr[r3]=r0 + ;; + movl r2=2<<IA64_RR_IDX_POS + movl r3=3<<IA64_RR_IDX_POS + ;; + mov rr[r2]=r0 + mov rr[r3]=r0 + ;; + movl r2=4<<IA64_RR_IDX_POS + movl r3=6<<IA64_RR_IDX_POS + ;; + mov rr[r2]=r0 + mov rr[r3]=r0 + ;; + // Wired memory for kernel data and text. + movl r2=IA64_RR_VAL(KERNEL_TR_PAGE_SIZE,0) + movl r3=5<<IA64_RR_IDX_POS // region 5 + ;; + mov rr[r3]=r2 + ;; + /* + * Region 7 addresses are only for directly mapped physically + * addresses. + */ + movl r2=IA64_RR_VAL(PTE_PS_16K,0) + movl r3=7<<IA64_RR_IDX_POS // region 7 + ;; + mov rr[r3]=r2 + ;; + + /* + * Now pin mappings into the TLB for kernel text and data + */ + mov r18=KERNEL_TR_PAGE_SIZE<<2 + movl r17=KERNEL_START + ;; + mov cr.itir=r18 + mov cr.ifa=r17 + mov r16=IA64_TR_KERNEL + mov r3=ip + movl r18=PTE_KERNEL_ATTR + ;; + dep r2=0,r3,0,KERNEL_TR_PAGE_SIZE + ;; + or r18=r2,r18 + ;; + srlz.i + ;; + itr.i itr[r16]=r18 + ;; + itr.d dtr[r16]=r18 + ;; + srlz.i + + /* Switch into virtual mode */ + movl r16=STARTUP_PSR + ;; + mov cr.ipsr=r16 + movl r17=1f + ;; + mov cr.iip=r17 + mov cr.ifs=r0 + ;; + rfi + ;; +1: /* now we are in virtual mode */ + + movl r3=ia64_trap_table + ;; + mov cr.iva=r3 + ;; + + movl r2=IA64_FPSR_DEFAULT + movl r3=IA64_DCR_DEFAULT + ;; + srlz.i + movl gp=__gp + + mov ar.fpsr=r2 + mov cr.dcr=r3 + ;; + movl r2=kstack + movl r5=KSTACK_PAGES * PAGE_SIZE - 16 + mov ar.rsc=0 // place RSE in enforced lazy mode + ;; + loadrs // clear the dirty partition + ;; + mov ar.bspstore=r2 // establish the new RSE stack + add sp=r2,r5 + ;; + mov ar.rsc=IA64_RSE_EAGER // place RSE in eager mode + + ;; + movl r2=ia64_boot_paramP + mov r3=7 // make address virtual region 7. + ;; + dep r28=r3,r28,61,3 + ;; + // save the address of the boot param area + // passed by the bootloader + st8 [r2]=r28 + ;; + + /* Set xsi base. I use here XSI_BASE. */ +#define FW_HYPERCALL_SET_SHARED_INFO_VA 0x600 + mov r2=FW_HYPERCALL_SET_SHARED_INFO_VA + movl r28=XSI_BASE + ;; + break 0x1000 + ;; + /* + * I set up here the pointer to the global start_info structure. + * This structure will be initialized in arch_init(). + */ + movl out0=start_info_union + // Prepare out0 - the pointer to start_info_t. + movl r14=XSI_BASE + ;; + add r15=START_INFO_PFN,r14 // add offset to XSI_BASE + ;; + START_INFO_PFN_ld r14=[r15] // load the start_info_pfn + add r16=7, r0 + ;; +#if defined(BIG_ENDIAN) + mux1 r14=r14,@rev // swap because mini-os is in BE +#endif + ;; + shl r15=r14,PAGE_SHIFT_XEN_16K // pfn << PAGE_SHIFT_XEN_16K + shl r16=r16,IA64_RR_IDX_POS // (7<<IA64_RR_IDX_POS) + ;; + or out0=r16, r15 // make a region 7 address + ;; + + br.call.sptk.many rp=start_kernel + ;; + add r2=3,r0 + ;; + ld8 r3=[r2] + ;; + +self: hint @pause + br.sptk.many self // endless loop +END(_start) + + +ENTRY(do_nop) + nop 0x01 + add r15=1,r15 + br.ret.sptk.many rp +END(do_nop) diff --git a/extras/mini-os/arch/ia64/ivt.S b/extras/mini-os/arch/ia64/ivt.S new file mode 100644 index 0000000000..86f8bb4060 --- /dev/null +++ b/extras/mini-os/arch/ia64/ivt.S @@ -0,0 +1,865 @@ +/* + * Copyright (c) 2007 Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com> + * Description: ia64 specific trap handling. + * + **************************************************************************** + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + + +#include "asm.h" +#include "page.h" +#include "ia64_cpu.h" +#include "privop.h" +#include "offsets.h" + + +/* General register usage in interrupt handling: + * r16, r17, ... are used for input parameters of sub-routines + * r29: used to access memory which may raise nested TLB fault + * r30: b0 save register + * r31: predicates save register + * p30,p31: used for TLB stuff: (0,1)=data, (1,0)=instruction + */ + + +#define FILL_FP_PAIR(f1, f2, b1, b2) \ + ldf.fill f1=[b1],32 ;\ + ldf.fill f2=[b2],32 ;\ + ;; + +#define SPILL_FP_PAIR(f1, f2, b1, b2) \ + stf.spill [b1]=f1,32 ;\ + stf.spill [b2]=f2,32 ;\ + ;; + +#define FILL_REG_PAIR(r1, r2, b1, b2) \ + ld8.fill r1=[b1],16 ;\ + ld8.fill r2=[b2],16 ;\ + ;; + +#define SPILL_REG_PAIR(r1, r2, b1, b2) \ + .mem.offset 0,0 ;\ + st8.spill [b1]=r1,16 ;\ + .mem.offset 8,0 ;\ + st8.spill [b2]=r2,16 ;\ + ;; + + +/** + * The function does a store of the current processor context + * to the given exception frame address. + * These are some special and the scratch registers for calling + * C-functions later. + * The bspstore will be the same. A clean RSE is made with the + * cover instruction. + * + * The return is done through a jump to the next bundle after ip (r16). + * + * Used register: r16, r18, r19, r20, r21, r22 of bank 0 + * + * @param: r16 ip of the bundle with the jump. + * @param: r18 pointer to the trap frame. + * @param: r23 trap number/err val + * + */ + +ENTRY(save_tf_rse_switch) + movl r21=XSI_IPSR // XEN !! + movl r22=XSI_IIP // XEN !! + ;; + ld8 r21=[r21] // XEN.ipsr + ld8 r22=[r22];; // XEN.iip +#if defined(BIG_ENDIAN) + mux1 r21=r21,@rev // swap because mini-os is in BE + mux1 r22=r22,@rev // swap because mini-os is in BE + ;; +#endif + add r19=TF_IPSR,r18 + add r20=TF_IIP,r18 + ;; + st8 [r19]=r21 // store cr.ipsr + st8 [r20]=r22 // store cr.iip + ;; + //// r16 return jump pointer, r18 - trap frame base, + add r19=TF_UNAT,r18 + mov r20=ar.unat + ;; + st8 [r19]=r20 // store scratch unat + ;; + + add r19=TF_GP,r18 + add r20=TF_SP,r18 + ;; + st8 [r19]=gp,TF_TP-TF_GP // store gp + st8 [r20]=sp,TF_PR-TF_SP // store sp + mov r21=pr + ;; + st8 [r19]=r13 // store tp + st8 [r20]=r21 // store pr + ;; + add r19=TF_GREG2,r18 // Now first general regs. + add r20=TF_GREG3,r18 + ;; + SPILL_REG_PAIR( r2, r3,r19,r20) + SPILL_REG_PAIR( r8, r9,r19,r20) + SPILL_REG_PAIR(r10,r11,r19,r20) + SPILL_REG_PAIR(r14,r15,r19,r20) + ;; + mov r14=r18 // move trap frame base for bsw + mov r15=r16 // save return address + ;; + //bsw.1 // switch to bank 1 for saving these registers. + movl r30=XSI_BANKNUM // Switch to bank 1. + mov r31=1;; +#if defined(BIG_ENDIAN) + mux1 r31=r31,@rev // swap because mini-os is in BE + ;; +#endif + st4 [r30]=r31 + ;; + /* + * On XEN the hypervisor has stored the bank 1 registers + * r16-r31. I must reload these registers here to get + * access. + */ + movl r30=XSI_BANK1_R16; + movl r31=XSI_BANK1_R16+8;; + ld8 r16=[r30],16; ld8 r17=[r31],16;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 r16=r16,@rev; mux1 r17=r17,@rev;; +#endif + ld8 r18=[r30],16; ld8 r19=[r31],16;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 r18=r18,@rev; mux1 r19=r19,@rev;; +#endif + ld8 r20=[r30],16; ld8 r21=[r31],16;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 r20=r20,@rev; mux1 r21=r21,@rev;; +#endif + ld8 r22=[r30],16; ld8 r23=[r31],16;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 r22=r22,@rev; mux1 r23=r23,@rev;; +#endif + ld8 r24=[r30],16; ld8 r25=[r31],16;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 r24=r24,@rev; mux1 r25=r25,@rev;; +#endif + ld8 r26=[r30],16; ld8 r27=[r31],16;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 r26=r26,@rev; mux1 r27=r27,@rev;; +#endif + ld8 r28=[r30],16; ld8 r29=[r31],16;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 r28=r28,@rev; mux1 r29=r29,@rev;; +#endif + ld8 r30=[r30]; ld8 r31=[r31];; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 r30=r30,@rev; mux1 r31=r31,@rev;; +#endif + + add r2=TF_GREG16,r14 + add r3=TF_GREG17,r14 + ;; + SPILL_REG_PAIR(r16,r17,r2,r3) + SPILL_REG_PAIR(r18,r19,r2,r3) + SPILL_REG_PAIR(r20,r21,r2,r3) + SPILL_REG_PAIR(r22,r23,r2,r3) + SPILL_REG_PAIR(r24,r25,r2,r3) + SPILL_REG_PAIR(r26,r27,r2,r3) + SPILL_REG_PAIR(r28,r29,r2,r3) + SPILL_REG_PAIR(r30,r31,r2,r3) + ;; + //bsw.0 // back to interrupt bank 0 + movl r2=XSI_BANKNUM;; + st4 [r2]=r0 + ;; + mov r18=r14 // restore context pointer + mov r16=r15 // restore return address + ;; + //// r16 return jump pointer, r18 - trap frame base, + add r19=TF_CCV,r18 + add r20=TF_CSD,r18 + mov r21=ar.ccv + mov r22=ar.csd + ;; + st8 [r19]=r21 // ar.ccv + st8 [r20]=r22 // ar.csd + ;; + add r19=TF_SSD,r18 + mov r21=ar.ssd + ;; + st8 [r19]=r21 // ar.ssd + ;; + add r19=TF_FREG6,r18 + add r20=TF_FREG7,r18 + ;; + SPILL_FP_PAIR(f6, f7, r19, r20) + SPILL_FP_PAIR(f8, f9, r19, r20) + SPILL_FP_PAIR(f10, f11, r19, r20) + + add r19=TF_BREG0,r18 // b0, b6, b7 + add r20=TF_BREG6,r18 + mov r21=b0 + mov r22=b6 + ;; + st8 [r19]=r21,TF_BREG7-TF_BREG0 // store b0 + st8 [r20]=r22,16 // store b6 + ;; + mov r21=b7 + ;; + st8 [r19]=r21 // store b7 + + //// r16 return jump pointer, r18 - trap frame base, + + // Read and save RSC, PFS + add r19=TF_PFS,r18 + add r20=TF_RSC,r18 + mov r21=ar.pfs + mov r22=ar.rsc + ;; +{ .mmb + st8 [r19]=r21 // store ar.pfs + st8 [r20]=r22 // store ar.rsc + // Issue cover instruction + cover // must be the last instruction in bundle + //XEN_HYPER_COVER + ;; +} + // Read and save IFS + add r19=TF_IFS,r18 + add r20=TF_CFM,r18 + /* xen special handling for possibly lazy cover */ + movl r8=XSI_PRECOVER_IFS; + ;; + ld8 r21=[r8]; + ;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 r21=r21,@rev + ;; +#endif + st8 [r19]=r21 // store cr.ifs + dep.z r22=r21,0,38 // copy ifm part from ifs.ifm + ;; + st8 [r20]=r22 // store cfm + // RSE in enforced lazy mode + mov ar.rsc=IA64_RSE_LAZY + ;; + // Read and save BSPSTORE and RNAT + add r19=TF_BSP,r18 + add r20=TF_RNAT,r18 + mov r21=ar.bspstore + mov r22=ar.rnat + ;; + st8 [r19]=r21 // store ar.bspstore + st8 [r20]=r22 // store ar.rnat + ;; + // Write new BSPSTORE + //mov r21=ar.bsp + //;; + mov r22=r21 // new bspstore equal to old + ;; + mov ar.bspstore=r22 // the new bspstore + ;; + // Read and save the new BSP for calculating number of dirty regs. + mov r21=ar.bsp + ;; + sub r21=r21,r22 // r21 -> ndirty + add r19=TF_NDIRTY-TF_BSP,r19 // TF_NDIRTY pos in r19 + ;; + st8 [r19]=r21 // store ndirty + ;; + mov ar.rsc=IA64_RSE_EAGER // RSE on again + ;; + add r19=TF_FPSR,r18 + ;; + mov r21=ar.fpsr + ;; + st8 [r19]=r21 // ar.fpsr + ;; + //// r16 return jump pointer, r18 - trap frame base, + // Load the gp with our module __gp + movl gp=__gp + ;; + add r16=16,r16 // for jump to next bundle + ;; + mov b7=r16 + ;; + +{ .mfb + srlz.d + nop 0 + br.sptk b7 + ;; +} + +END(save_tf_rse_switch) + + +/** + * The function reloads the processor context stored in + * save_tf_rse_switch(). + * + * On calling the function the bank 0 must be activ. + * The return is done through a rfi. + * Used register: b7, r16, r18, r19, r20, r21, r22 of bank 0 + * + * @param: r18 pointer to the exception frame + * + */ +ENTRY(restore_tf_rse_switch) + add r19=TF_IPSR,r18 + add r20=TF_IIP,r18 + ;; + ld8 r21=[r19] // load cr.ipsr + ld8 r22=[r20] // load cr.iip +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + ;; + mux1 r21=r21,@rev + mux1 r22=r22,@rev + ;; +#endif + movl r16=XSI_IPSR // XEN !! + ;; + st8 [r16]=r21,XSI_IIP_OFS-XSI_IPSR_OFS // XEN.ipsr + mov r2=r21 // save for fp stuff below + ;; + st8 [r16]=r22 // XEN.iip + ;; + //// r18 - trap frame base + // Allocate a zero sized frame + alloc r30=ar.pfs,0,0,0,0 // discard current frame + ;; + // calc number of dirty regs and put this into rsc.loardrs + add r19=TF_NDIRTY,r18 + ;; + ld8 r22=[r19] // ndirty + ;; + shl r21=r22,16 // value for ar.rsc + //mov r19=(MOS_IA64_RSC_BE << IA64_RSC_BE) + ;; + or r21=(MOS_IA64_RSC_BE << IA64_RSC_BE),r21 + ;; + mov ar.rsc=r21 // setup for loadrs + ;; + // Issue a loadrs instruction +{ .mmi + loadrs // must be the first instruction + ;; + nop 0x0 + nop 0x0 +} + // Restore BSPSTORE from interrupted context + add r19=TF_BSP,r18 + add r20=TF_RNAT,r18 + ;; + ld8 r21=[r19] // load ar.bspstore + ld8 r22=[r20] // load ar.rnat + ;; + mov ar.bspstore=r21 // set ar.bspstore + ;; + // Restore RNAT + mov ar.rnat=r22 // set ar.rnat + ;; + // Restore PFS and IFS + add r19=TF_PFS,r18 + add r20=TF_IFS,r18 + movl r16=XSI_IFS // XEN !! + ;; + ld8 r21=[r19] // load ar.pfs + ld8 r22=[r20] // load cr.ifs + ;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 r22=r22,@rev + ;; +#endif + add r19=TF_RSC,r18 + mov ar.pfs=r21 + st8 [r16]=r22 // XEN.ifs + ;; + // Restore RSC + ld8 r21=[r19] // load ar.rsc + ;; + mov ar.rsc=r21 // set ar.rsc + //// r18 - trap frame base + add r19=TF_GP,r18 + add r20=TF_SP,r18 + ;; + ld8 gp=[r19],TF_TP-TF_GP // load gp + ld8 sp=[r20],TF_PR-TF_SP // load sp + ;; + ld8 r13=[r19] // load tp + ld8 r21=[r20] // load pr + ;; + mov pr=r21,-1 // set pr + ;; + add r19=TF_BREG0,r18 + add r20=TF_BREG6,r18 + ;; + ld8 r21=[r19],TF_BREG7-TF_BREG0 // load b0 + ld8 r22=[r20],16 // load b6 + ;; + mov b0=r21 + mov b6=r22 + ;; + ld8 r21=[r19] // load b7 + ld8 r22=[r20],16 // load b3 + ;; + mov b7=r21 + //// r18 - trap frame base + mov r14=r18 // Save the context pointer + ;; + // bsw.1 + movl r30=XSI_BANKNUM // Switch to bank 1. + mov r31=1;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 r31=r31,@rev + ;; +#endif + st4 [r30]=r31 + ;; + add r2=TF_GREG16,r14 + add r3=TF_GREG17,r14 + ;; + FILL_REG_PAIR(r16,r17,r2,r3) + FILL_REG_PAIR(r18,r19,r2,r3) + FILL_REG_PAIR(r20,r21,r2,r3) + FILL_REG_PAIR(r22,r23,r2,r3) + FILL_REG_PAIR(r24,r25,r2,r3) + FILL_REG_PAIR(r26,r27,r2,r3) + FILL_REG_PAIR(r28,r29,r2,r3) + FILL_REG_PAIR(r30,r31,r2,r3) + + /* + * On XEN I have to store the bank 1 register into the + * global XSI_... area. + */ + // r16-r31 all now hold bank1 values + movl r2=XSI_BANK1_R16 + movl r3=XSI_BANK1_R16+8 + ;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 r16=r16,@rev; mux1 r17=r17,@rev;; +#endif + .mem.offset 0,0; st8.spill [r2]=r16,16 + .mem.offset 8,0; st8.spill [r3]=r17,16 + ;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 r18=r18,@rev; mux1 r19=r19,@rev;; +#endif + .mem.offset 0,0; st8.spill [r2]=r18,16 + .mem.offset 8,0; st8.spill [r3]=r19,16 + ;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 r20=r20,@rev; mux1 r21=r21,@rev;; +#endif + .mem.offset 0,0; st8.spill [r2]=r20,16 + .mem.offset 8,0; st8.spill [r3]=r21,16 + ;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 r22=r22,@rev; mux1 r23=r23,@rev;; +#endif + .mem.offset 0,0; st8.spill [r2]=r22,16 + .mem.offset 8,0; st8.spill [r3]=r23,16 + ;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 r24=r24,@rev; mux1 r25=r25,@rev;; +#endif + .mem.offset 0,0; st8.spill [r2]=r24,16 + .mem.offset 8,0; st8.spill [r3]=r25,16 + ;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 r26=r26,@rev; mux1 r27=r27,@rev;; +#endif + .mem.offset 0,0; st8.spill [r2]=r26,16 + .mem.offset 8,0; st8.spill [r3]=r27,16 + ;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 r28=r28,@rev; mux1 r29=r29,@rev;; +#endif + .mem.offset 0,0; st8.spill [r2]=r28,16 + .mem.offset 8,0; st8.spill [r3]=r29,16 + ;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 r30=r30,@rev; mux1 r31=r31,@rev;; +#endif + .mem.offset 0,0; st8.spill [r2]=r30,16 + .mem.offset 8,0; st8.spill [r3]=r31,16 + ;; + // bsw.0 + movl r2=XSI_BANKNUM;; + st4 [r2]=r0; + + mov r18=r14 // Move back the context pointer + ;; + add r19=TF_GREG2,r18 + add r20=TF_GREG3,r18 + ;; + FILL_REG_PAIR( r2, r3,r19,r20) + FILL_REG_PAIR( r8, r9,r19,r20) + FILL_REG_PAIR(r10,r11,r19,r20) + FILL_REG_PAIR(r14,r15,r19,r20) + + //// r18 - trap frame base, + + add r19=TF_CCV,r18 + add r20=TF_CSD,r18 + ;; + ld8 r21=[r19] // ar.ccv + ld8 r22=[r20] // ar.csd + ;; + mov ar.ccv=r21 + mov ar.csd=r22 + add r19=TF_SSD,r18 + ;; + ld8 r21=[r19] // ar.ssd + ;; + mov ar.ssd=r21 + add r19=TF_FREG6,r18 + add r20=TF_FREG7,r18 + ;; + FILL_FP_PAIR(f6, f7, r19, r20) + FILL_FP_PAIR(f8, f9, r19, r20) + FILL_FP_PAIR(f10, f11, r19, r20) + add r19=TF_FPSR,r18 + ;; + ld8 r21=[r19] // ar.fpsr + ;; + mov ar.fpsr=r21 + add r19=TF_UNAT,r18 + ;; + ld8 r21=[r19] + ;; + mov ar.unat=r21 + ;; + srlz.i + ;; + //rfi + XEN_HYPER_RFI; + ;; +END(restore_tf_rse_switch) + + +ENTRY(save_special_regs) + alloc loc0=ar.pfs,1,7,0,0 + movl loc1=XSI_IFA // XEN !! + movl loc2=XSI_ISR // XEN !! + ;; + ld8 loc3=[loc1],XSI_IIM_OFS-XSI_IFA_OFS // load XEN.ifa + ld8 loc4=[loc2],XSI_IIPA_OFS-XSI_ISR_OFS // load XEN.isr + add loc5=TF_IFA,in0 + add loc6=TF_ISR,in0 + ;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 loc3=loc3,@rev; mux1 loc4=loc4,@rev;; +#endif + st8 [loc5]=loc3,TF_IIM-TF_IFA // store cr.ifa + st8 [loc6]=loc4 // store cr.isr + ;; + ld8 loc3=[loc1] // load XEN.iim + ;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 loc3=loc3,@rev;; +#endif + st8 [loc5]=loc3 // store cr.iim + ;; + mov ar.pfs=loc0 + ;; + br.ret.sptk.few rp +END(save_special_regs) + + +ENTRY(hypervisor_callback) + // Calculate the stack address for storing. + // Use the kernel stack here because it's mapped wired! + // -> no nested tlb faults! + movl r18=kstack+KSTACK_PAGES * PAGE_SIZE - 16 - TF_SIZE + + //add r18=-TF_SIZE,sp + add r30=0xabab,r0 + ;; +{ .mib + nop 0x02 + mov r16=ip // for jump back from save_tf_rse_switch + br.sptk save_tf_rse_switch + ;; +} + add sp=-16,r18 // the new stack + alloc r15=ar.pfs,0,0,1,0 // 1 out for do_trap_error + ;; + mov out0=r18 // the trap frame + movl r22=XSI_PSR_IC + mov r23=1;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 r23=r23,@rev;; +#endif + st8 [r22]=r23 // ssm psr.ic + ;; + br.call.sptk.few rp = do_hypervisor_callback + + movl r22=XSI_PSR_IC + ;; + st4 [r22]=r0 // rsm psr.ic + + add r16=16,sp // load EF-pointer again + ;; + //mov r18=sp + movl r18=kstack+KSTACK_PAGES * PAGE_SIZE - 16 - TF_SIZE + ;; + + // must have r18-efp, calls rfi at the end. + br.sptk restore_tf_rse_switch + ;; +END(hypervisor_callback) + + /* + * In: r30 - trap number + */ +ENTRY(trap_error) + // Calculate the stack address for storing. + add r18=-TF_SIZE,sp + ;; + add r20=TF_TRAP_NUM,r18 + ;; + st2 [r20]=r30 // save trap number + ;; + +{ .mib + nop 0x02 + mov r16=ip // for jumping back from save_tf_rse_switch + // Used register: r16, r18, r19, r20, r21, r22 of bank 0 + br.sptk save_tf_rse_switch + ;; +} + + alloc r15=ar.pfs,0,0,1,0 // 1 out for do_trap_error + ;; + mov out0=r18 // the trap frame + add sp=-16,r18 // C-call abi + ;; + + //bsw.1 + movl r30=XSI_BANKNUM + mov r31=1;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 r31=r31,@rev;; +#endif + st4 [r30]=r31;; + + /* Save extra interrupt registers to the trap frame. */ + br.call.sptk.few rp = save_special_regs + ;; + + movl r22=XSI_PSR_IC + movl r23=XSI_PSR_I_ADDR + ;; + ld8 r23=[r23] + mov r25=1 + ;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 r25=r25,@rev; mux1 r23=r23,@rev;; +#endif + st4 [r22]=r25 // ssm psr.ic + st1 [r23]=r0 // ssm psr.i + ;; + + br.call.sptk.few rp = do_trap_error + ;; + // --> currently not reached!!! + movl r23=XSI_PSR_I_ADDR + movl r22=XSI_PSR_IC + ;; + ld8 r23=[r23] + mov r25=1 + ;; +#if defined(BIG_ENDIAN) // swap because mini-os is in BE + mux1 r25=r25,@rev;; + mux1 r25=r25,@rev; mux1 r23=r23,@rev;; +#endif + st1 [r23]=r25 + st4 [r22]=r0 // note: clears both vpsr.i and vpsr.ic! + ;; + bsw.0 + ;; + add r18=16,sp // load EF-pointer again + ;; + mov sp=r18 + // must have r18-efp, calls rfi at the end. + br.sptk restore_tf_rse_switch + ;; +END(trap_error) + + +/* + * The trap handler stuff. + */ + +#define TRAP_ERR(num) \ + mov r30 = num; \ + ;; ; \ + br.sptk trap_error \ + ;; + +#define IVT_ENTRY(name, offset) \ + .org ia64_trap_table + offset; \ + .global hivt_##name; \ + .proc hivt_##name; \ + .prologue; \ + .body; \ +hivt_##name: + +#define IVT_END(name) \ + .endp hivt_##name; \ + .align 0x100 + +#define IVT_ERR(name, num, offset) \ + IVT_ENTRY(name, offset); \ + TRAP_ERR(num); \ + IVT_END(name) +/* + * The IA64 Interrupt Vector Table (IVT) contains 20 slots with 64 + * bundles per vector and 48 slots with 16 bundles per vector. + */ + + .section .text.hivt,"ax" + .align 32768 + .global ia64_trap_table + .size ia64_trap_table, 32768 +ia64_trap_table: + +IVT_ERR(VHPT_Translation, 0, 0x0) +IVT_ERR(Instruction_TLB, 1, 0x0400) +IVT_ERR(Data_TLB, 2, 0x0800) +IVT_ERR(Alternate_Instruction_TLB, 3, 0x0c00) + + +IVT_ENTRY(Alternate_Data_TLB, 0x1000) + mov r30=4 // trap number + mov r16=cr.ifa // where did it happen + mov r31=pr // save predicates + ;; + extr.u r17=r16,IA64_RR_IDX_POS,3 // get region number + ;; + cmp.eq p14,p15=7,r17 + ;; +//(p14) br.sptk adt_regf_addr // Check for region 7 - phys addresses +// ;; +// br.sptk trap_error +// // No return +// +//adt_regf_addr: +// extr.u r17=r16,60,4 // get region number +// ;; +// cmp.eq p14,p15=0xf,r17 +// ;; +(p14) br.sptk adt_reg7_addr // Check for region 7 - phys addresses + ;; + br.sptk trap_error + +adt_reg7_addr: + /* + * region 7 addresses are only directly mapped physically + * addresses. Currently I don't do a check. + */ + movl r20=~((7 << IA64_RR_IDX_POS) | 0xfff) + movl r18=((PTE_PS_16K<<IA64_ITIR_PS)|(0<<IA64_ITIR_KEY)) + ;; + movl r19= ((1<<PTE_OFF_P) | (PTE_MA_WB<<PTE_OFF_MA) | \ + (1<<PTE_OFF_A) | (1<<PTE_OFF_D) | \ + (PTE_PL_KERN<<PTE_OFF_PL) | (PTE_AR_RW<<PTE_OFF_AR)) + // clear the region bits and 0-11 + // extract the pfn from the ifa + mov cr.itir=r18 + and r20=r20, r16 + ;; + or r20=r20,r19 // put pfn into pte + ;; + mov pr=r31,-1 // restore predicates + itc.d r20 + ;; + XEN_HYPER_RFI; + ;; + +IVT_END(Alternate_Data_TLB) + + +IVT_ERR(Data_Nested_TLB, 5, 0x1400) +IVT_ERR(Instruction_Key_Miss, 6, 0x1800) +IVT_ERR(Data_Key_Miss, 7, 0x1c00) +IVT_ERR(Dirty_Bit, 8, 0x2000) +IVT_ERR(Instruction_Access_Bit, 9, 0x2400) +IVT_ERR(Data_Access_Bit, 10, 0x2800) +IVT_ERR(Break_Instruction, 11, 0x2c00) +IVT_ERR(External_Interrupt, 12, 0x3000) +IVT_ERR(Reserved_3400, 13, 0x3400) +IVT_ERR(Reserved_3800, 14, 0x3800) +IVT_ERR(Reserved_3c00, 15, 0x3c00) +IVT_ERR(Reserved_4000, 16, 0x4000) +IVT_ERR(Reserved_4400, 17, 0x4400) +IVT_ERR(Reserved_4800, 18, 0x4800) +IVT_ERR(Reserved_4c00, 19, 0x4c00) +IVT_ERR(Page_Not_Present, 20, 0x5000) +IVT_ERR(Key_Permission, 21, 0x5100) +IVT_ERR(Instruction_Access_Rights, 22, 0x5200) +IVT_ERR(Data_Access_Rights, 23, 0x5300) +IVT_ERR(General_Exception, 24, 0x5400) +IVT_ERR(Disabled_FP_Register, 25, 0x5500) +IVT_ERR(NaT_Consumption, 26, 0x5600) +IVT_ERR(Speculation, 27, 0x5700) +IVT_ERR(Reserved_5800, 28, 0x5800) +IVT_ERR(Debug, 29, 0x5900) +IVT_ERR(Unaligned_Reference, 30, 0x5a00) +IVT_ERR(Unsupported_Data_Reference, 31, 0x5b00) +IVT_ERR(Floating_Point_Fault, 32, 0x5c00) +IVT_ERR(Floating_Point_Trap, 33, 0x5d00) +IVT_ERR(Lower_Privilege_Transfer_Trap, 34, 0x5e00) +IVT_ERR(Taken_Branch_Trap, 35, 0x5f00) +IVT_ERR(Single_Step_Trap, 36, 0x6000) +IVT_ERR(Reserved_6100, 37, 0x6100) +IVT_ERR(Reserved_6200, 38, 0x6200) +IVT_ERR(Reserved_6300, 39, 0x6300) +IVT_ERR(Reserved_6400, 40, 0x6400) +IVT_ERR(Reserved_6500, 41, 0x6500) +IVT_ERR(Reserved_6600, 42, 0x6600) +IVT_ERR(Reserved_6700, 43, 0x6700) +IVT_ERR(Reserved_6800, 44, 0x6800) +IVT_ERR(IA_32_Exception, 45, 0x6900) +IVT_ERR(IA_32_Intercept, 46, 0x6a00) +IVT_ERR(IA_32_Interrupt, 47, 0x6b00) +IVT_ERR(Reserved_6c00, 48, 0x6c00) +IVT_ERR(Reserved_6d00, 49, 0x6d00) +IVT_ERR(Reserved_6e00, 50, 0x6e00) +IVT_ERR(Reserved_6f00, 51, 0x6f00) +IVT_ERR(Reserved_7000, 52, 0x7000) +IVT_ERR(Reserved_7100, 53, 0x7100) +IVT_ERR(Reserved_7200, 54, 0x7200) +IVT_ERR(Reserved_7300, 55, 0x7300) +IVT_ERR(Reserved_7400, 56, 0x7400) +IVT_ERR(Reserved_7500, 57, 0x7500) +IVT_ERR(Reserved_7600, 58, 0x7600) +IVT_ERR(Reserved_7700, 59, 0x7700) +IVT_ERR(Reserved_7800, 60, 0x7800) +IVT_ERR(Reserved_7900, 61, 0x7900) +IVT_ERR(Reserved_7a00, 62, 0x7a00) +IVT_ERR(Reserved_7b00, 63, 0x7b00) +IVT_ERR(Reserved_7c00, 64, 0x7c00) +IVT_ERR(Reserved_7d00, 65, 0x7d00) +IVT_ERR(Reserved_7e00, 66, 0x7e00) +IVT_ERR(Reserved_7f00, 67, 0x7f00) diff --git a/extras/mini-os/arch/ia64/minios-ia64.lds b/extras/mini-os/arch/ia64/minios-ia64.lds new file mode 100644 index 0000000000..70435de11e --- /dev/null +++ b/extras/mini-os/arch/ia64/minios-ia64.lds @@ -0,0 +1,54 @@ +OUTPUT_FORMAT("elf64-ia64-little") +OUTPUT_ARCH(ia64) + +ENTRY(phys_start) + +PHDRS +{ + code PT_LOAD; + data PT_LOAD; +} + +SECTIONS +{ + + phys_start = _start - (((5<<(61))+0x100000000) - (1 << 20)); + + code : { } :code + . = ((5<<(61))+0x100000000); + + _text = .; + + .text : AT(ADDR(.text) - (((5<<(61))+0x100000000) - (1 << 20))) + { + *(.text) + } + + _etext = .; + + data : { } :data + .data : AT(ADDR(.data) - (((5<<(61))+0x100000000) - (1 << 20))) + { *(.data) + } + + .sdata : AT(ADDR(.sdata) - (((5<<(61))+0x100000000) - (1 << 20))) + { *(.sdata) *(.sdata1) *(.srdata) } + + .rodata : AT(ADDR(.rodata) - (((5<<(61))+0x100000000) - (1 << 20))) + { *(.rodata) } + + .rodata.str1.8 : AT(ADDR(.rodata.str1.8) - (((5<<(61))+0x100000000) - (1 << 20))) + { *(.rodata.str1.8) } + + .IA_64.unwind_info : AT(ADDR(.IA_64.unwind_info) - (((5<<(61))+0x100000000) - (1 << 20))) + { *(.IA_64.unwind_info) } + + .IA_64.unwind : AT(ADDR(.IA_64.unwind) - (((5<<(61))+0x100000000) - (1 << 20))) + { *(.IA_64.unwind) } + + .bss : AT(ADDR(.bss) - (((5<<(61))+0x100000000) - (1 << 20))) + { *(.bss) } + + _end = .; + +} diff --git a/extras/mini-os/arch/ia64/mm.c b/extras/mini-os/arch/ia64/mm.c new file mode 100644 index 0000000000..ad5acccc7e --- /dev/null +++ b/extras/mini-os/arch/ia64/mm.c @@ -0,0 +1,132 @@ +/* + * Done by Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com> + * + * Description: Special ia64 memory management. + * Parts are taken from FreeBSD. + * + **************************************************************************** + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + + +#include "os.h" +#include "mm.h" + + +#define MAX_MEM_AREA 5 +paddr_t phys_avail[MAX_MEM_AREA * 2]; +int phys_avail_cnt; +uint64_t physmem; + +/* + * These variables are defined in the linker script minios_ia64.lds + * to get the size of the kernel. + */ +extern uint64_t _text[], _etext[], _end[], kstack[], phys_start[]; + +uint64_t kernstart, kernend, kernsize, kernpstart, kernpend; + +/* Print the available memory chunks. */ +static void +print_phys_avail(void) +{ + int i; + + printk("Physical memory chunk(s):\n"); + for (i = 0; phys_avail[i + 1] != 0; i += 2) { + int size = phys_avail[i + 1] - phys_avail[i]; + printk("0x%08lx - 0x%08lx, %d bytes (%d pages)\n", + phys_avail[i], phys_avail[i + 1] - 1, + size, size / PAGE_SIZE); + } +} + +void +arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p) +{ + uint64_t ms, me; + int i, j; + uint64_t m, n; + + kernstart = trunc_page(_text); + kernend = roundup_page(_end); + + kernpstart = trunc_page(ia64_tpa(kernstart)); + kernpend = roundup_page(kernpstart + (kernend - kernstart)); + kernsize = kernpend - kernpstart; + + ms = roundup_page(machineFwG.mach_mem_start); + me = trunc_page(machineFwG.mach_mem_start+machineFwG.mach_mem_size); + memset((void*)phys_avail, 0, sizeof(phys_avail)); + /* 1. Check where the kernel lies in physical memory. */ + physmem = me - ms; + if ((ms <= kernpend) && (kernpstart <= me)) { + if (ms < kernpstart) { /* There is a part before the kernel. */ + PRINT_BV(" Found chunk before kernel: 0x%lx - 0x%lx\n", + ms, kernpstart); + phys_avail[phys_avail_cnt] = ms; + phys_avail[phys_avail_cnt+1] = kernpstart; + phys_avail_cnt += 2; + } + if (kernpend < me) { /* There is a part behind the kernel. */ + PRINT_BV(" Found chunk behind kernel: 0x%lx - 0x%lx\n", + kernpend, me); + phys_avail[phys_avail_cnt] = kernpend; + phys_avail[phys_avail_cnt+1] = me; + phys_avail_cnt += 2; + } + } else { /* One big chunk */ + PRINT_BV(" Found big chunk: 0x%lx - 0x%lx\n", ms, me); + phys_avail[phys_avail_cnt] = ms; + phys_avail[phys_avail_cnt + 1] = me; + phys_avail_cnt += 2; + } + phys_avail[phys_avail_cnt] = 0; + + print_phys_avail(); + /* + * In this first version I only look for the biggest mem area. + */ + for (i = j = m = n = 0; i < phys_avail_cnt; i += 2) { + n = page_to_pfn(phys_avail[i + 1]) - page_to_pfn(phys_avail[i]); + if (n > m) { + m = n; + j = i; + } + } + *start_pfn_p = page_to_pfn(phys_avail[j]); + *max_pfn_p = page_to_pfn(phys_avail[j +1 ]); +} + +/* Currently only a dummy function. */ +void +arch_init_demand_mapping_area(unsigned long max_pfn) +{ + max_pfn = max_pfn; +} + +/* Helper function used in gnttab.c. */ +void* +map_frames(unsigned long* frames, unsigned long n) +{ + n = n; + return (void*) __va(frames[0] << PAGE_SHIFT); +} + diff --git a/extras/mini-os/arch/ia64/sal.c b/extras/mini-os/arch/ia64/sal.c new file mode 100644 index 0000000000..d087053287 --- /dev/null +++ b/extras/mini-os/arch/ia64/sal.c @@ -0,0 +1,103 @@ +/* + * Done by Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com> + * Mostly taken from FreeBSD. + * + **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 "os.h" +#include "lib.h" +#include "console.h" +#include "page.h" + + +static struct ia64_fdesc sal_fdesc; +uint64_t ia64_pal_entry; /* PAL_PROC entrypoint */ + + +struct ia64_sal_result +ia64_sal_call(uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, + uint64_t a5, uint64_t a6, uint64_t a7, uint64_t a8) +{ + return ia64_sal_entry(a1, a2, a3, a4, a5, a6, a7, a8); +} + +static struct ia64_sal_result +fake_sal(uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, + uint64_t a5, uint64_t a6, uint64_t a7, uint64_t a8) +{ + struct ia64_sal_result res; + res.sal_status = -3; + res.sal_result[0] = 0; + res.sal_result[1] = 0; + res.sal_result[2] = 0; + return res; +} + +/* + * Currently only the SAL_DESC_ENTRYPOINT is checked to get + * the entry points the pal and sal functions. + */ +void +ia64_sal_init(struct sal_system_table *saltab) +{ + static int sizes[6] = { 48, 32, 16, 32, 16, 16 }; + uint8_t *p; + int i; + + PRINT_BV("Reading SALtable:\n"); + ia64_sal_entry = fake_sal; + + if (memcmp((void*)(uint64_t)(saltab->sal_signature), SAL_SIGNATURE, 4)) + { + printk("Bad signature for SAL System Table\n"); + return; + } + p = (uint8_t *) (saltab + 1); + for (i = 0; i < SWAP(saltab->sal_entry_count); i++) { + switch (SWAP(*p)) { + case SAL_DESC_ENTRYPOINT: // 0 + { + struct sal_entrypoint_descriptor *dp; + + dp = (struct sal_entrypoint_descriptor*)p; + ia64_pal_entry = + IA64_PHYS_TO_RR7(SWAP(dp->sale_pal_proc)); + PRINT_BV(" PAL Proc at 0x%lx\n", ia64_pal_entry); + sal_fdesc.func = + IA64_PHYS_TO_RR7(SWAP(dp->sale_sal_proc)); + sal_fdesc.gp = IA64_PHYS_TO_RR7(SWAP(dp->sale_sal_gp)); + PRINT_BV(" SAL Proc at 0x%lx, GP at 0x%lx\n", + sal_fdesc.func, sal_fdesc.gp); + ia64_sal_entry = (sal_entry_t *) &sal_fdesc; + break; + } + default: + break; + } + p += sizes[*p]; + } +} + diff --git a/extras/mini-os/arch/ia64/sched.c b/extras/mini-os/arch/ia64/sched.c new file mode 100644 index 0000000000..64052b6fc5 --- /dev/null +++ b/extras/mini-os/arch/ia64/sched.c @@ -0,0 +1,74 @@ +/* + * Done by Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com + * + * Description: ia64 specific part of the scheduler for mini-os + * + **************************************************************************** + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + + +#include "types.h" +#include "sched.h" +#include "lib.h" +#include "xmalloc.h" +#include "mm.h" + +/* The function is implemented in fw.S */ +extern void thread_starter(void); + +struct thread* +arch_create_thread(char *name, void (*function)(void *), void *data) +{ + struct thread* _thread; + + _thread = (struct thread*)_xmalloc(sizeof(struct thread), 16); + /* Allocate 2 pages for stack, stack will be 2pages aligned */ + _thread->stack = (char *)alloc_pages(1); + _thread->name = name; + memset((void*)&(_thread->regs), 0, sizeof(_thread->regs)); + _thread->regs.sp = ((uint64_t)_thread->stack) + 2 * PAGE_SIZE - 16; + _thread->regs.bsp = ((uint64_t)_thread->stack) + 0x10; + _thread->regs.rp = FDESC_FUNC(thread_starter); + _thread->regs.pfs = 0x82; + _thread->regs.r4 = FDESC_FUNC(function); + _thread->regs.r6 = (uint64_t)data; + return _thread; +} + +extern void restore_context(struct thread*); +extern int switch_context(struct thread*, struct thread*); + +void +arch_switch_threads(struct thread* prev, struct thread* next) +{ + ia64_set_r13((uint64_t)next); + switch_context(prev, next); +} + +/* Everything initialised, start idle thread */ +void +run_idle_thread(void) +{ + //do_busy_loop(); + ia64_set_r13((uint64_t)idle_thread); + restore_context(idle_thread); + printk("%s: restore_context() returned - bad!\n", __func__); +} diff --git a/extras/mini-os/arch/ia64/time.c b/extras/mini-os/arch/ia64/time.c new file mode 100644 index 0000000000..2d943e8c7a --- /dev/null +++ b/extras/mini-os/arch/ia64/time.c @@ -0,0 +1,280 @@ +/* + * Done by Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com> + * Description: simple ia64 specific time handling + * mktime() is taken from Linux (see copyright below) + * Parts are taken from FreeBSD. + * + **************************************************************************** + * For the copy of the mktime() from linux. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 "os.h" +#include "console.h" +#include "time.h" +#include "efi.h" +#include "events.h" + +struct timespec os_time; +static uint64_t itc_alt; /* itc on last update. */ +static uint64_t itc_at_boot; /* itc on boot */ +static uint64_t itc_frequency; +static uint64_t processor_frequency; +static uint64_t itm_val; + + +/* + * mktime() is take from Linux. See copyright above. + * Converts Gregorian date to seconds since 1970-01-01 00:00:00. + * Assumes input in normal date format, i.e. 1980-12-31 23:59:59 + * => year=1980, mon=12, day=31, hour=23, min=59, sec=59. + * + * [For the Julian calendar (which was used in Russia before 1917, + * Britain & colonies before 1752, anywhere else before 1582, + * and is still in use by some communities) leave out the + * -year/100+year/400 terms, and add 10.] + * + * This algorithm was first published by Gauss (I think). + * + * WARNING: this function will overflow on 2106-02-07 06:28:16 on + * machines were long is 32-bit! (However, as time_t is signed, we + * will already get problems at other places on 2038-01-19 03:14:08) + */ +static unsigned long +mktime(const unsigned int year0, const unsigned int mon0, + const unsigned int day, const unsigned int hour, + const unsigned int min, const unsigned int sec) +{ + unsigned int mon = mon0, year = year0; + + /* 1..12 -> 11,12,1..10 */ + if (0 >= (int) (mon -= 2)) { + mon += 12; /* Puts Feb last since it has leap day */ + year -= 1; + } + + return ( + ( + ((unsigned long) + (year/4 - year/100 + year/400 + 367*mon/12 + day) + + year*365 - 719499 + ) * 24 + hour /* now have hours */ + ) * 60 + min /* now have minutes */ + ) * 60 + sec; /* finally seconds */ +} + +static inline uint64_t +ns_from_cycles(uint64_t cycles) +{ + return (cycles * (1000000000 / itc_frequency)); +} + +static inline uint64_t +ns_to_cycles(uint64_t ns) +{ + return (ns * (itc_frequency / 1000000000)); +} + +/* + * Block the domain until until(nanoseconds) is over. + * If block is called no timerinterrupts are delivered from xen! + */ +void +block_domain(s_time_t until) +{ + struct ia64_pal_result pal_res; + uint64_t c, new; + + c = ns_to_cycles(until); + new = ia64_get_itc() + c - NOW(); + ia64_set_itm(new); /* Reload cr.itm */ + /* + * PAL_HALT_LIGHT returns on every external interrupt, + * including timer interrupts. + */ + pal_res = ia64_call_pal_static(PAL_HALT_LIGHT, 0, 0, 0); + if (pal_res.pal_status != 0) + printk("%s: PAL_HALT_LIGHT returns an error\n"); + /* Reload the normal timer interrupt match. */ + new = ia64_get_itc() + itm_val; + ia64_set_itm(new); +} + +static void +calculate_time(void) +{ + uint64_t itc_new, new; + + itc_new = ia64_get_itc(); + if (itc_new < itc_alt) + new = ~0 - itc_alt + itc_new; + else + new = itc_new - itc_alt; + itc_alt = itc_new; + new = ns_from_cycles(new); + os_time.ts_nsec += new; + if (os_time.ts_nsec > 1000000000) { /* On overflow. */ + os_time.ts_sec++; + os_time.ts_nsec -= 1000000000; + } +} + +void +timer_interrupt(evtchn_port_t port, struct pt_regs* regsP, void *data) +{ + uint64_t new; + + calculate_time(); + new = ia64_get_itc() + itm_val; + ia64_set_itm(new); +} + +/* + * monotonic_clock(): returns # of nanoseconds passed since time_init() + */ +u64 +monotonic_clock(void) +{ + uint64_t delta; + + delta = ia64_get_itc() - itc_at_boot; + delta = ns_from_cycles(delta); + return delta; +} + +void +gettimeofday(struct timeval *tv) +{ + calculate_time(); + tv->tv_sec = os_time.ts_sec; /* seconds */ + tv->tv_usec = NSEC_TO_USEC(os_time.ts_nsec); /* microseconds */ +}; + +/* + * Read the clock frequencies from pal and sal for calculating + * the clock interrupt. + */ +static void +calculate_frequencies(void) +{ + struct ia64_sal_result sal_res; + struct ia64_pal_result pal_res; + + pal_res = ia64_call_pal_static(PAL_FREQ_RATIOS, 0, 0, 0); + //sal_res = ia64_sal_call(SAL_FREQ_BASE, 0, 0, 0, 0, 0, 0, 0); +#if defined(BIG_ENDIAN) +//#warning calculate_frequencies TODO + /* + * I have to do an own function with switching psr.be! + * Currently it's running because it's a break into the hypervisor + * behind the call.! + */ +#endif + sal_res = ia64_sal_entry(SAL_FREQ_BASE, 0, 0, 0, 0, 0, 0, 0); + + if (sal_res.sal_status == 0 && pal_res.pal_status == 0) { + processor_frequency = + sal_res.sal_result[0] * (pal_res.pal_result[0] >> 32) + / (pal_res.pal_result[0] & ((1L << 32) - 1)); + itc_frequency = + sal_res.sal_result[0] * (pal_res.pal_result[2] >> 32) + / (pal_res.pal_result[2] & ((1L << 32) - 1)); + PRINT_BV("Reading clock frequencies:\n"); + PRINT_BV(" Platform clock frequency %ld Hz\n", + sal_res.sal_result[0]); + PRINT_BV(" Processor ratio %ld/%ld, Bus ratio %ld/%ld, " + " ITC ratio %ld/%ld\n", + pal_res.pal_result[0] >> 32, + pal_res.pal_result[0] & ((1L << 32) - 1), + pal_res.pal_result[1] >> 32, + pal_res.pal_result[1] & ((1L << 32) - 1), + pal_res.pal_result[2] >> 32, + pal_res.pal_result[2] & ((1L << 32) - 1)); + + printk(" ITC frequency %ld\n", itc_frequency); + } else { + itc_frequency = 1000000000; + processor_frequency = 0; + printk("Reading clock frequencies failed!!! Using: %ld\n", + itc_frequency); + } +} + + +//#define HZ 1 +#define HZ 1000 // 1000 clock ticks per sec +#define IA64_TIMER_VECTOR 0xef + +void +init_time(void) +{ + uint64_t new; + efi_time_t tm; + int err = 0; + + printk("Initialising time\n"); + calculate_frequencies(); + + itm_val = (itc_frequency + HZ/2) / HZ; + printk(" itm_val: %ld\n", itm_val); + + os_time.ts_sec = 0; + os_time.ts_nsec = 0; + + if (efi_get_time(&tm)) { + printk(" EFI-Time: %d.%d.%d %d:%d:%d\n", tm.Day, + tm.Month, tm.Year, tm.Hour, tm.Minute, tm.Second); + os_time.ts_sec = mktime(SWAP(tm.Year), SWAP(tm.Month), + SWAP(tm.Day), SWAP(tm.Hour), + SWAP(tm.Minute), SWAP(tm.Second)); + os_time.ts_nsec = tm.Nanosecond; + } else + printk("efi_get_time() failed\n"); + + err = bind_virq(VIRQ_ITC, timer_interrupt, NULL); + if (err != 0) { + printk("XEN timer request chn bind failed %i\n", err); + return; + } + itc_alt = ia64_get_itc(); + itc_at_boot = itc_alt; + new = ia64_get_itc() + itm_val; + ia64_set_itv(IA64_TIMER_VECTOR); + ia64_set_itm(new); + ia64_srlz_d(); +} diff --git a/extras/mini-os/arch/ia64/xencomm.c b/extras/mini-os/arch/ia64/xencomm.c new file mode 100644 index 0000000000..587576a0b4 --- /dev/null +++ b/extras/mini-os/arch/ia64/xencomm.c @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2006 Hollis Blanchard <hollisb@us.ibm.com>, IBM Corporation + * Tristan Gingold <tristan.gingold@bull.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * This code is mostly taken from ia64-xen files xcom_mini.c and xencomm.c. + * Changes: Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com + */ + + +#include <os.h> +#include <hypervisor.h> +#include <xen/xencomm.h> +#include <xen/grant_table.h> + + +#define XENCOMM_MINI_ADDRS 3 +struct xencomm_mini +{ + struct xencomm_desc _desc; + uint64_t address[XENCOMM_MINI_ADDRS]; +}; + +#define xen_guest_handle(hnd) ((hnd).p) + + +/* Translate virtual address to physical address. */ +uint64_t +xencomm_vaddr_to_paddr(uint64_t vaddr) +{ + if (IA64_RR_EXTR(vaddr) == 5) + return KERN_VIRT_2_PHYS(vaddr); + + if (IA64_RR_EXTR(vaddr) == 7) + return __pa(vaddr); + + return 0; +} + +#define min(a,b) (((a) < (b)) ? (a) : (b)) +static int +xencomm_init_desc(struct xencomm_desc *desc, void *buffer, unsigned long bytes) +{ + unsigned long recorded = 0; + int i = 0; + + if ((buffer == NULL) && (bytes > 0)) + BUG(); + + /* record the physical pages used */ + if (buffer == NULL) + desc->nr_addrs = 0; + + while ((recorded < bytes) && (i < desc->nr_addrs)) { + unsigned long vaddr = (unsigned long)buffer + recorded; + unsigned long paddr; + int offset; + int chunksz; + + offset = vaddr % PAGE_SIZE; /* handle partial pages */ + chunksz = min(PAGE_SIZE - offset, bytes - recorded); + + paddr = xencomm_vaddr_to_paddr(vaddr); + if (paddr == ~0UL) { + printk("%s: couldn't translate vaddr %lx\n", + __func__, vaddr); + return -EINVAL; + } + + desc->address[i++] = SWAP(paddr); + recorded += chunksz; + } + if (recorded < bytes) { + printk("%s: could only translate %ld of %ld bytes\n", + __func__, recorded, bytes); + return -ENOSPC; + } + + /* mark remaining addresses invalid (just for safety) */ + while (i < desc->nr_addrs) + desc->address[i++] = SWAP(XENCOMM_INVALID); + desc->magic = SWAP(XENCOMM_MAGIC); + return 0; +} + +static void * +xencomm_alloc_mini(struct xencomm_mini *area, int *nbr_area) +{ + unsigned long base; + unsigned int pageoffset; + + while (*nbr_area >= 0) { + /* Allocate an area. */ + (*nbr_area)--; + + base = (unsigned long)(area + *nbr_area); + pageoffset = base % PAGE_SIZE; + + /* If the area does not cross a page, use it. */ + if ((PAGE_SIZE - pageoffset) >= sizeof(struct xencomm_mini)) + return &area[*nbr_area]; + } + /* No more area. */ + return NULL; +} + +int +xencomm_create_mini(struct xencomm_mini *area, int *nbr_area, + void *buffer, unsigned long bytes, + struct xencomm_handle **ret) +{ + struct xencomm_desc *desc; + int rc; + unsigned long res; + + desc = xencomm_alloc_mini(area, nbr_area); + if (!desc) + return -ENOMEM; + desc->nr_addrs = XENCOMM_MINI_ADDRS; + + rc = xencomm_init_desc(desc, buffer, bytes); + if (rc) + return rc; + + res = xencomm_vaddr_to_paddr((unsigned long)desc); + if (res == ~0UL) + return -EINVAL; + + *ret = (struct xencomm_handle*)res; + return 0; +} + +static int +xencommize_mini_grant_table_op(struct xencomm_mini *xc_area, int *nbr_area, + unsigned int cmd, void *op, unsigned int count, + struct xencomm_handle **desc) +{ + struct xencomm_handle *desc1; + unsigned int argsize=0; + int rc; + + switch (cmd) { + case GNTTABOP_map_grant_ref: + argsize = sizeof(struct gnttab_map_grant_ref); + break; + case GNTTABOP_unmap_grant_ref: + argsize = sizeof(struct gnttab_unmap_grant_ref); + break; + case GNTTABOP_setup_table: + { + struct gnttab_setup_table *setup = op; + + argsize = sizeof(*setup); + + if (count != 1) + return -EINVAL; + rc = xencomm_create_mini + (xc_area, nbr_area, + xen_guest_handle(setup->frame_list), + setup->nr_frames + * sizeof(*xen_guest_handle(setup->frame_list)), + &desc1); + if (rc) + return rc; + set_xen_guest_handle(setup->frame_list, (void *)desc1); + break; + } + case GNTTABOP_dump_table: + argsize = sizeof(struct gnttab_dump_table); + break; + case GNTTABOP_transfer: + argsize = sizeof(struct gnttab_transfer); + break; + case GNTTABOP_copy: + argsize = sizeof(struct gnttab_copy); + break; + default: + printk("%s: unknown mini grant table op %d\n", __func__, cmd); + BUG(); + } + + rc = xencomm_create_mini(xc_area, nbr_area, op, count * argsize, desc); + + return rc; +} + +int +xencomm_mini_hypercall_grant_table_op(unsigned int cmd, void *op, + unsigned int count) +{ + int rc; + struct xencomm_handle *desc; + int nbr_area = 2; + struct xencomm_mini xc_area[2]; + + rc = xencommize_mini_grant_table_op(xc_area, &nbr_area, + cmd, op, count, &desc); + if (rc) + return rc; + return xencomm_arch_hypercall_grant_table_op(cmd, desc, count); +} + +static void +gnttab_map_grant_ref_pre(struct gnttab_map_grant_ref *uop) +{ + uint32_t flags; + + flags = uop->flags; + + if (flags & GNTMAP_host_map) { + if (flags & GNTMAP_application_map) { + printk("GNTMAP_application_map is not supported yet: " + "flags 0x%x\n", flags); + BUG(); + } + if (flags & GNTMAP_contains_pte) { + printk("GNTMAP_contains_pte is not supported yet flags " + "0x%x\n", flags); + BUG(); + } + } else if (flags & GNTMAP_device_map) { + printk("GNTMAP_device_map is not supported yet 0x%x\n", flags); + BUG();//XXX not yet. actually this flag is not used. + } else { + BUG(); + } +} + +int +HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count) +{ + if (cmd == GNTTABOP_map_grant_ref) { + unsigned int i; + for (i = 0; i < count; i++) { + gnttab_map_grant_ref_pre( + (struct gnttab_map_grant_ref*)uop + i); + } + } + return xencomm_mini_hypercall_grant_table_op(cmd, uop, count); +} + |