[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [IA64] support FPSWA emulation
# HG changeset patch # User awilliam@xxxxxxxxxxx # Node ID faae893d428e989148743bb92bce234dfead281c # Parent 7c406cefc1aa82a33296086e41a9f61a504277ed [IA64] support FPSWA emulation Signed-off-by: Masaki Kanno <kanno.masaki@xxxxxxxxxxxxxx> --- xen/arch/ia64/xen/process.c | 110 +++++++++++++++++++++++++-- xen/arch/ia64/xen/xensetup.c | 3 xen/include/asm-ia64/linux/asm/README.origin | 1 xen/include/asm-ia64/linux/asm/fpswa.h | 73 +++++++++++++++++ 4 files changed, 180 insertions(+), 7 deletions(-) diff -r 7c406cefc1aa -r faae893d428e xen/arch/ia64/xen/process.c --- a/xen/arch/ia64/xen/process.c Thu May 25 15:38:16 2006 -0600 +++ b/xen/arch/ia64/xen/process.c Thu May 25 15:47:33 2006 -0600 @@ -33,6 +33,7 @@ #include "hpsim_ssc.h" #include <xen/multicall.h> #include <asm/debugger.h> +#include <asm/fpswa.h> extern void die_if_kernel(char *str, struct pt_regs *regs, long err); /* FIXME: where these declarations shold be there ? */ @@ -392,6 +393,99 @@ void ia64_do_page_fault (unsigned long a PSCB(current,iha) = iha; PSCB(current,ifa) = address; reflect_interruption(isr, regs, fault); +} + +fpswa_interface_t *fpswa_interface = 0; + +void trap_init (void) +{ + if (ia64_boot_param->fpswa) + /* FPSWA fixup: make the interface pointer a virtual address: */ + fpswa_interface = __va(ia64_boot_param->fpswa); + else + printk("No FPSWA supported.\n"); +} + +static fpswa_ret_t +fp_emulate (int fp_fault, void *bundle, long *ipsr, long *fpsr, long *isr, long *pr, long *ifs, + struct pt_regs *regs) +{ + fp_state_t fp_state; + fpswa_ret_t ret; + + if (!fpswa_interface) + return ((fpswa_ret_t) {-1, 0, 0, 0}); + + memset(&fp_state, 0, sizeof(fp_state_t)); + + /* + * compute fp_state. only FP registers f6 - f11 are used by the + * kernel, so set those bits in the mask and set the low volatile + * pointer to point to these registers. + */ + fp_state.bitmask_low64 = 0xfc0; /* bit6..bit11 */ + + fp_state.fp_state_low_volatile = (fp_state_low_volatile_t *) ®s->f6; + /* + * unsigned long (*EFI_FPSWA) ( + * unsigned long trap_type, + * void *Bundle, + * unsigned long *pipsr, + * unsigned long *pfsr, + * unsigned long *pisr, + * unsigned long *ppreds, + * unsigned long *pifs, + * void *fp_state); + */ + ret = (*fpswa_interface->fpswa)((unsigned long) fp_fault, bundle, + (unsigned long *) ipsr, (unsigned long *) fpsr, + (unsigned long *) isr, (unsigned long *) pr, + (unsigned long *) ifs, &fp_state); + + return ret; +} + +/* + * Handle floating-point assist faults and traps for domain. + */ +static unsigned long +handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr) +{ + struct vcpu *v = current; + IA64_BUNDLE bundle; + IA64_BUNDLE __get_domain_bundle(UINT64); + unsigned long fault_ip; + fpswa_ret_t ret; + + fault_ip = regs->cr_iip; + /* + * When the FP trap occurs, the trapping instruction is completed. + * If ipsr.ri == 0, there is the trapping instruction in previous bundle. + */ + if (!fp_fault && (ia64_psr(regs)->ri == 0)) + fault_ip -= 16; + bundle = __get_domain_bundle(fault_ip); + if (!bundle.i64[0] && !bundle.i64[1]) { + printk("%s: floating-point bundle at 0x%lx not mapped\n", + __FUNCTION__, fault_ip); + return -1; + } + + ret = fp_emulate(fp_fault, &bundle, ®s->cr_ipsr, ®s->ar_fpsr, + &isr, ®s->pr, ®s->cr_ifs, regs); + + if (ret.status) { + PSCBX(v, fpswa_ret) = ret; + printk("%s(%s): fp_emulate() returned %ld\n", + __FUNCTION__, fp_fault?"fault":"trap", ret.status); + } else { + if (fp_fault) { + /* emulation was successful */ + vcpu_increment_iip(v); + } + } + + return ret.status; } void @@ -758,29 +852,31 @@ ia64_handle_reflection (unsigned long if vector = IA64_NAT_CONSUMPTION_VECTOR; break; } #endif -printf("*** NaT fault... attempting to handle as privop\n"); -printf("isr=%016lx, ifa=%016lx, iip=%016lx, ipsr=%016lx\n", - isr, ifa, regs->cr_iip, psr); + printf("*** NaT fault... attempting to handle as privop\n"); + printf("isr=%016lx, ifa=%016lx, iip=%016lx, ipsr=%016lx\n", + isr, ifa, regs->cr_iip, psr); //regs->eml_unat = 0; FIXME: DO WE NEED THIS??? // certain NaT faults are higher priority than privop faults vector = priv_emulate(v,regs,isr); if (vector == IA64_NO_FAULT) { -printf("*** Handled privop masquerading as NaT fault\n"); + printf("*** Handled privop masquerading as NaT fault\n"); return; } vector = IA64_NAT_CONSUMPTION_VECTOR; break; case 27: -//printf("*** Handled speculation vector, itc=%lx!\n",ia64_get_itc()); + //printf("*** Handled speculation vector, itc=%lx!\n",ia64_get_itc()); PSCB(current,iim) = iim; vector = IA64_SPECULATION_VECTOR; break; case 30: // FIXME: Should we handle unaligned refs in Xen?? vector = IA64_UNALIGNED_REF_VECTOR; break; case 32: - printf("ia64_handle_reflection: handling FP fault"); + if (!(handle_fpu_swa(1, regs, isr))) return; + printf("ia64_handle_reflection: handling FP fault\n"); vector = IA64_FP_FAULT_VECTOR; break; case 33: - printf("ia64_handle_reflection: handling FP trap"); + if (!(handle_fpu_swa(0, regs, isr))) return; + printf("ia64_handle_reflection: handling FP trap\n"); vector = IA64_FP_TRAP_VECTOR; break; case 34: printf("ia64_handle_reflection: handling lowerpriv trap"); diff -r 7c406cefc1aa -r faae893d428e xen/arch/ia64/xen/xensetup.c --- a/xen/arch/ia64/xen/xensetup.c Thu May 25 15:38:16 2006 -0600 +++ b/xen/arch/ia64/xen/xensetup.c Thu May 25 15:47:33 2006 -0600 @@ -53,6 +53,7 @@ extern void setup_per_cpu_areas(void); extern void setup_per_cpu_areas(void); extern void mem_init(void); extern void init_IRQ(void); +extern void trap_init(void); /* opt_nosmp: If true, secondary processors are ignored. */ static int opt_nosmp = 0; @@ -321,6 +322,8 @@ void start_kernel(void) init_frametable(); + trap_init(); + alloc_dom0(); end_boot_allocator(); diff -r 7c406cefc1aa -r faae893d428e xen/include/asm-ia64/linux/asm/README.origin --- a/xen/include/asm-ia64/linux/asm/README.origin Thu May 25 15:38:16 2006 -0600 +++ b/xen/include/asm-ia64/linux/asm/README.origin Thu May 25 15:47:33 2006 -0600 @@ -16,6 +16,7 @@ delay.h -> linux/include/asm-ia64/dela delay.h -> linux/include/asm-ia64/delay.h div64.h -> linux/include/asm-ia64/div64.h dma.h -> linux/include/asm-ia64/dma.h +fpswa.h -> linux/include/asm-ia64/fpswa.h fpu.h -> linux/include/asm-ia64/fpu.h hardirq.h -> linux/include/asm-ia64/hardirq.h hdreg.h -> linux/include/asm-ia64/hdreg.h diff -r 7c406cefc1aa -r faae893d428e xen/include/asm-ia64/linux/asm/fpswa.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/include/asm-ia64/linux/asm/fpswa.h Thu May 25 15:47:33 2006 -0600 @@ -0,0 +1,73 @@ +#ifndef _ASM_IA64_FPSWA_H +#define _ASM_IA64_FPSWA_H + +/* + * Floating-point Software Assist + * + * Copyright (C) 1999 Intel Corporation. + * Copyright (C) 1999 Asit Mallick <asit.k.mallick@xxxxxxxxx> + * Copyright (C) 1999 Goutham Rao <goutham.rao@xxxxxxxxx> + */ + +typedef struct { + /* 4 * 128 bits */ + unsigned long fp_lp[4*2]; +} fp_state_low_preserved_t; + +typedef struct { + /* 10 * 128 bits */ + unsigned long fp_lv[10 * 2]; +} fp_state_low_volatile_t; + +typedef struct { + /* 16 * 128 bits */ + unsigned long fp_hp[16 * 2]; +} fp_state_high_preserved_t; + +typedef struct { + /* 96 * 128 bits */ + unsigned long fp_hv[96 * 2]; +} fp_state_high_volatile_t; + +/** + * floating point state to be passed to the FP emulation library by + * the trap/fault handler + */ +typedef struct { + unsigned long bitmask_low64; + unsigned long bitmask_high64; + fp_state_low_preserved_t *fp_state_low_preserved; + fp_state_low_volatile_t *fp_state_low_volatile; + fp_state_high_preserved_t *fp_state_high_preserved; + fp_state_high_volatile_t *fp_state_high_volatile; +} fp_state_t; + +typedef struct { + unsigned long status; + unsigned long err0; + unsigned long err1; + unsigned long err2; +} fpswa_ret_t; + +/** + * function header for the Floating Point software assist + * library. This function is invoked by the Floating point software + * assist trap/fault handler. + */ +typedef fpswa_ret_t (*efi_fpswa_t) (unsigned long trap_type, void *bundle, unsigned long *ipsr, + unsigned long *fsr, unsigned long *isr, unsigned long *preds, + unsigned long *ifs, fp_state_t *fp_state); + +/** + * This is the FPSWA library interface as defined by EFI. We need to pass a + * pointer to the interface itself on a call to the assist library + */ +typedef struct { + unsigned int revision; + unsigned int reserved; + efi_fpswa_t fpswa; +} fpswa_interface_t; + +extern fpswa_interface_t *fpswa_interface; + +#endif /* _ASM_IA64_FPSWA_H */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |