From 559adb10ad58ce7f62aa6165589241c3122ccfbc Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Thu, 29 Jun 2006 19:59:18 +0000 Subject: [PATCH] Partial support for branch long emulation. This only emulates the branch long jump and not the branch long call. Support for that is forthcoming. --- sys/conf/files.ia64 | 1 + sys/ia64/ia64/emulate.c | 89 +++++++++++++++++++++++++++++++++++++++ sys/ia64/ia64/trap.c | 22 +++++++++- sys/ia64/include/md_var.h | 1 + 4 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 sys/ia64/ia64/emulate.c diff --git a/sys/conf/files.ia64 b/sys/conf/files.ia64 index 9683af49b3c..5dfddffe186 100644 --- a/sys/conf/files.ia64 +++ b/sys/conf/files.ia64 @@ -93,6 +93,7 @@ ia64/ia64/db_machdep.c optional ddb ia64/ia64/dump_machdep.c standard ia64/ia64/efi.c standard ia64/ia64/elf_machdep.c standard +ia64/ia64/emulate.c standard ia64/ia64/exception.S standard ia64/ia64/gdb_machdep.c optional gdb ia64/ia64/in_cksum.c optional inet diff --git a/sys/ia64/ia64/emulate.c b/sys/ia64/ia64/emulate.c new file mode 100644 index 00000000000..37fcf5595e7 --- /dev/null +++ b/sys/ia64/ia64/emulate.c @@ -0,0 +1,89 @@ +/*- + * Copyright (c) 2006 Marcel Moolenaar + * All rights reserved. + * + * 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 ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include +#include + +#include + +int +ia64_emulate(struct trapframe *tf, struct thread *td) +{ + struct asm_bundle bundle; + struct asm_inst *i; + int slot; + + if (!asm_decode(tf->tf_special.iip, &bundle)) + return (SIGILL); + + slot = ((tf->tf_special.psr & IA64_PSR_RI) == IA64_PSR_RI_0) ? 0 : + ((tf->tf_special.psr & IA64_PSR_RI) == IA64_PSR_RI_1) ? 1 : 2; + if (slot == 1 && bundle.b_templ[slot] == 'L') + slot++; + + i = bundle.b_inst + slot; + switch (i->i_op) { + case ASM_OP_BRL: + /* + * We get the fault even if the predicate is false, so we + * need to check the predicate first and simply advance to + * the next bundle in that case. + */ + if (!(tf->tf_special.pr & (1UL << i->i_oper[0].o_value))) { + tf->tf_special.psr &= ~IA64_PSR_RI; + tf->tf_special.iip += 16; + return (0); + } + /* + * The brl.cond is the simplest form. We only have to set + * the IP to the address in the instruction and return. + */ + if (i->i_cmpltr[0].c_type == ASM_CT_COND) { + tf->tf_special.psr &= ~IA64_PSR_RI; + tf->tf_special.iip += i->i_oper[1].o_value; + return (0); + } + /* Sanity check... */ + if (i->i_cmpltr[0].c_type != ASM_CT_CALL) + break; + /* + * The brl.call is more difficult as we need to set-up the + * call properly. + */ + break; + default: + break; + } + + return (SIGILL); +} diff --git a/sys/ia64/ia64/trap.c b/sys/ia64/ia64/trap.c index 7ca498d4d53..116795f6971 100644 --- a/sys/ia64/ia64/trap.c +++ b/sys/ia64/ia64/trap.c @@ -608,7 +608,27 @@ trap(int vector, struct trapframe *tf) break; } - case IA64_VEC_GENERAL_EXCEPTION: + case IA64_VEC_GENERAL_EXCEPTION: { + int code; + + if (!user) + trap_panic(vector, tf); + + code = tf->tf_special.isr & (IA64_ISR_CODE & 0xf0ull); + switch (code) { + case 0x0: /* Illegal Operation Fault. */ + sig = ia64_emulate(tf, td); + break; + default: + sig = SIGILL; + break; + } + if (sig == 0) + goto out; + ucode = vector; + break; + } + case IA64_VEC_NAT_CONSUMPTION: case IA64_VEC_SPECULATION: case IA64_VEC_UNSUPP_DATA_REFERENCE: diff --git a/sys/ia64/include/md_var.h b/sys/ia64/include/md_var.h index eef42402bf7..8695cd871a0 100644 --- a/sys/ia64/include/md_var.h +++ b/sys/ia64/include/md_var.h @@ -77,6 +77,7 @@ void cpu_mp_add(u_int, u_int, u_int); int do_ast(struct trapframe *); void ia32_trap(int, struct trapframe *); int ia64_count_cpus(void); +int ia64_emulate(struct trapframe *, struct thread *); int ia64_flush_dirty(struct thread *, struct _special *); uint64_t ia64_get_hcdp(void); int ia64_highfp_drop(struct thread *); -- 2.45.2