···4848 * Delete dead variables and functions.4949 * Reorder to remove the need for forward declarations and to consolidate5050 * related code.5151+ *5252+ * 2005-08-12 Keith Owens <kaos@sgi.com>5353+ * Convert MCA/INIT handlers to use per event stacks and SAL/OS state.5154 */5255#include <linux/config.h>5356#include <linux/types.h>···8077#include <asm/irq.h>8178#include <asm/hw_irq.h>82798080+#include "entry.h"8181+8382#if defined(IA64_MCA_DEBUG_INFO)8483# define IA64_MCA_DEBUG(fmt...) printk(fmt)8584#else···8984#endif90859186/* Used by mca_asm.S */9292-ia64_mca_sal_to_os_state_t ia64_sal_to_os_handoff_state;9393-ia64_mca_os_to_sal_state_t ia64_os_to_sal_handoff_state;9494-u64 ia64_mca_serialize;8787+u32 ia64_mca_serialize;9588DEFINE_PER_CPU(u64, ia64_mca_data); /* == __per_cpu_mca[smp_processor_id()] */9689DEFINE_PER_CPU(u64, ia64_mca_per_cpu_pte); /* PTE to map per-CPU area */9790DEFINE_PER_CPU(u64, ia64_mca_pal_pte); /* PTE to map PAL code */···9895unsigned long __per_cpu_mca[NR_CPUS];999610097/* In mca_asm.S */101101-extern void ia64_monarch_init_handler (void);102102-extern void ia64_slave_init_handler (void);9898+extern void ia64_os_init_dispatch_monarch (void);9999+extern void ia64_os_init_dispatch_slave (void);100100+101101+static int monarch_cpu = -1;103102104103static ia64_mc_info_t ia64_mc_info;105104···239234 * This function retrieves a specified error record type from SAL240235 * and wakes up any processes waiting for error records.241236 *242242- * Inputs : sal_info_type (Type of error record MCA/CMC/CPE/INIT)237237+ * Inputs : sal_info_type (Type of error record MCA/CMC/CPE)238238+ * FIXME: remove MCA and irq_safe.243239 */244240static void245241ia64_mca_log_sal_error_record(int sal_info_type)···248242 u8 *buffer;249243 sal_log_record_header_t *rh;250244 u64 size;251251- int irq_safe = sal_info_type != SAL_INFO_TYPE_MCA && sal_info_type != SAL_INFO_TYPE_INIT;245245+ int irq_safe = sal_info_type != SAL_INFO_TYPE_MCA;252246#ifdef IA64_MCA_DEBUG_INFO253247 static const char * const rec_name[] = { "MCA", "INIT", "CMC", "CPE" };254248#endif···335329}336330337331#endif /* CONFIG_ACPI */338338-339339-static void340340-show_min_state (pal_min_state_area_t *minstate)341341-{342342- u64 iip = minstate->pmsa_iip + ((struct ia64_psr *)(&minstate->pmsa_ipsr))->ri;343343- u64 xip = minstate->pmsa_xip + ((struct ia64_psr *)(&minstate->pmsa_xpsr))->ri;344344-345345- printk("NaT bits\t%016lx\n", minstate->pmsa_nat_bits);346346- printk("pr\t\t%016lx\n", minstate->pmsa_pr);347347- printk("b0\t\t%016lx ", minstate->pmsa_br0); print_symbol("%s\n", minstate->pmsa_br0);348348- printk("ar.rsc\t\t%016lx\n", minstate->pmsa_rsc);349349- printk("cr.iip\t\t%016lx ", iip); print_symbol("%s\n", iip);350350- printk("cr.ipsr\t\t%016lx\n", minstate->pmsa_ipsr);351351- printk("cr.ifs\t\t%016lx\n", minstate->pmsa_ifs);352352- printk("xip\t\t%016lx ", xip); print_symbol("%s\n", xip);353353- printk("xpsr\t\t%016lx\n", minstate->pmsa_xpsr);354354- printk("xfs\t\t%016lx\n", minstate->pmsa_xfs);355355- printk("b1\t\t%016lx ", minstate->pmsa_br1);356356- print_symbol("%s\n", minstate->pmsa_br1);357357-358358- printk("\nstatic registers r0-r15:\n");359359- printk(" r0- 3 %016lx %016lx %016lx %016lx\n",360360- 0UL, minstate->pmsa_gr[0], minstate->pmsa_gr[1], minstate->pmsa_gr[2]);361361- printk(" r4- 7 %016lx %016lx %016lx %016lx\n",362362- minstate->pmsa_gr[3], minstate->pmsa_gr[4],363363- minstate->pmsa_gr[5], minstate->pmsa_gr[6]);364364- printk(" r8-11 %016lx %016lx %016lx %016lx\n",365365- minstate->pmsa_gr[7], minstate->pmsa_gr[8],366366- minstate->pmsa_gr[9], minstate->pmsa_gr[10]);367367- printk("r12-15 %016lx %016lx %016lx %016lx\n",368368- minstate->pmsa_gr[11], minstate->pmsa_gr[12],369369- minstate->pmsa_gr[13], minstate->pmsa_gr[14]);370370-371371- printk("\nbank 0:\n");372372- printk("r16-19 %016lx %016lx %016lx %016lx\n",373373- minstate->pmsa_bank0_gr[0], minstate->pmsa_bank0_gr[1],374374- minstate->pmsa_bank0_gr[2], minstate->pmsa_bank0_gr[3]);375375- printk("r20-23 %016lx %016lx %016lx %016lx\n",376376- minstate->pmsa_bank0_gr[4], minstate->pmsa_bank0_gr[5],377377- minstate->pmsa_bank0_gr[6], minstate->pmsa_bank0_gr[7]);378378- printk("r24-27 %016lx %016lx %016lx %016lx\n",379379- minstate->pmsa_bank0_gr[8], minstate->pmsa_bank0_gr[9],380380- minstate->pmsa_bank0_gr[10], minstate->pmsa_bank0_gr[11]);381381- printk("r28-31 %016lx %016lx %016lx %016lx\n",382382- minstate->pmsa_bank0_gr[12], minstate->pmsa_bank0_gr[13],383383- minstate->pmsa_bank0_gr[14], minstate->pmsa_bank0_gr[15]);384384-385385- printk("\nbank 1:\n");386386- printk("r16-19 %016lx %016lx %016lx %016lx\n",387387- minstate->pmsa_bank1_gr[0], minstate->pmsa_bank1_gr[1],388388- minstate->pmsa_bank1_gr[2], minstate->pmsa_bank1_gr[3]);389389- printk("r20-23 %016lx %016lx %016lx %016lx\n",390390- minstate->pmsa_bank1_gr[4], minstate->pmsa_bank1_gr[5],391391- minstate->pmsa_bank1_gr[6], minstate->pmsa_bank1_gr[7]);392392- printk("r24-27 %016lx %016lx %016lx %016lx\n",393393- minstate->pmsa_bank1_gr[8], minstate->pmsa_bank1_gr[9],394394- minstate->pmsa_bank1_gr[10], minstate->pmsa_bank1_gr[11]);395395- printk("r28-31 %016lx %016lx %016lx %016lx\n",396396- minstate->pmsa_bank1_gr[12], minstate->pmsa_bank1_gr[13],397397- minstate->pmsa_bank1_gr[14], minstate->pmsa_bank1_gr[15]);398398-}399399-400400-static void401401-fetch_min_state (pal_min_state_area_t *ms, struct pt_regs *pt, struct switch_stack *sw)402402-{403403- u64 *dst_banked, *src_banked, bit, shift, nat_bits;404404- int i;405405-406406- /*407407- * First, update the pt-regs and switch-stack structures with the contents stored408408- * in the min-state area:409409- */410410- if (((struct ia64_psr *) &ms->pmsa_ipsr)->ic == 0) {411411- pt->cr_ipsr = ms->pmsa_xpsr;412412- pt->cr_iip = ms->pmsa_xip;413413- pt->cr_ifs = ms->pmsa_xfs;414414- } else {415415- pt->cr_ipsr = ms->pmsa_ipsr;416416- pt->cr_iip = ms->pmsa_iip;417417- pt->cr_ifs = ms->pmsa_ifs;418418- }419419- pt->ar_rsc = ms->pmsa_rsc;420420- pt->pr = ms->pmsa_pr;421421- pt->r1 = ms->pmsa_gr[0];422422- pt->r2 = ms->pmsa_gr[1];423423- pt->r3 = ms->pmsa_gr[2];424424- sw->r4 = ms->pmsa_gr[3];425425- sw->r5 = ms->pmsa_gr[4];426426- sw->r6 = ms->pmsa_gr[5];427427- sw->r7 = ms->pmsa_gr[6];428428- pt->r8 = ms->pmsa_gr[7];429429- pt->r9 = ms->pmsa_gr[8];430430- pt->r10 = ms->pmsa_gr[9];431431- pt->r11 = ms->pmsa_gr[10];432432- pt->r12 = ms->pmsa_gr[11];433433- pt->r13 = ms->pmsa_gr[12];434434- pt->r14 = ms->pmsa_gr[13];435435- pt->r15 = ms->pmsa_gr[14];436436- dst_banked = &pt->r16; /* r16-r31 are contiguous in struct pt_regs */437437- src_banked = ms->pmsa_bank1_gr;438438- for (i = 0; i < 16; ++i)439439- dst_banked[i] = src_banked[i];440440- pt->b0 = ms->pmsa_br0;441441- sw->b1 = ms->pmsa_br1;442442-443443- /* construct the NaT bits for the pt-regs structure: */444444-# define PUT_NAT_BIT(dst, addr) \445445- do { \446446- bit = nat_bits & 1; nat_bits >>= 1; \447447- shift = ((unsigned long) addr >> 3) & 0x3f; \448448- dst = ((dst) & ~(1UL << shift)) | (bit << shift); \449449- } while (0)450450-451451- /* Rotate the saved NaT bits such that bit 0 corresponds to pmsa_gr[0]: */452452- shift = ((unsigned long) &ms->pmsa_gr[0] >> 3) & 0x3f;453453- nat_bits = (ms->pmsa_nat_bits >> shift) | (ms->pmsa_nat_bits << (64 - shift));454454-455455- PUT_NAT_BIT(sw->caller_unat, &pt->r1);456456- PUT_NAT_BIT(sw->caller_unat, &pt->r2);457457- PUT_NAT_BIT(sw->caller_unat, &pt->r3);458458- PUT_NAT_BIT(sw->ar_unat, &sw->r4);459459- PUT_NAT_BIT(sw->ar_unat, &sw->r5);460460- PUT_NAT_BIT(sw->ar_unat, &sw->r6);461461- PUT_NAT_BIT(sw->ar_unat, &sw->r7);462462- PUT_NAT_BIT(sw->caller_unat, &pt->r8); PUT_NAT_BIT(sw->caller_unat, &pt->r9);463463- PUT_NAT_BIT(sw->caller_unat, &pt->r10); PUT_NAT_BIT(sw->caller_unat, &pt->r11);464464- PUT_NAT_BIT(sw->caller_unat, &pt->r12); PUT_NAT_BIT(sw->caller_unat, &pt->r13);465465- PUT_NAT_BIT(sw->caller_unat, &pt->r14); PUT_NAT_BIT(sw->caller_unat, &pt->r15);466466- nat_bits >>= 16; /* skip over bank0 NaT bits */467467- PUT_NAT_BIT(sw->caller_unat, &pt->r16); PUT_NAT_BIT(sw->caller_unat, &pt->r17);468468- PUT_NAT_BIT(sw->caller_unat, &pt->r18); PUT_NAT_BIT(sw->caller_unat, &pt->r19);469469- PUT_NAT_BIT(sw->caller_unat, &pt->r20); PUT_NAT_BIT(sw->caller_unat, &pt->r21);470470- PUT_NAT_BIT(sw->caller_unat, &pt->r22); PUT_NAT_BIT(sw->caller_unat, &pt->r23);471471- PUT_NAT_BIT(sw->caller_unat, &pt->r24); PUT_NAT_BIT(sw->caller_unat, &pt->r25);472472- PUT_NAT_BIT(sw->caller_unat, &pt->r26); PUT_NAT_BIT(sw->caller_unat, &pt->r27);473473- PUT_NAT_BIT(sw->caller_unat, &pt->r28); PUT_NAT_BIT(sw->caller_unat, &pt->r29);474474- PUT_NAT_BIT(sw->caller_unat, &pt->r30); PUT_NAT_BIT(sw->caller_unat, &pt->r31);475475-}476476-477477-static void478478-init_handler_platform (pal_min_state_area_t *ms,479479- struct pt_regs *pt, struct switch_stack *sw)480480-{481481- struct unw_frame_info info;482482-483483- /* if a kernel debugger is available call it here else just dump the registers */484484-485485- /*486486- * Wait for a bit. On some machines (e.g., HP's zx2000 and zx6000, INIT can be487487- * generated via the BMC's command-line interface, but since the console is on the488488- * same serial line, the user will need some time to switch out of the BMC before489489- * the dump begins.490490- */491491- printk("Delaying for 5 seconds...\n");492492- udelay(5*1000000);493493- show_min_state(ms);494494-495495- printk("Backtrace of current task (pid %d, %s)\n", current->pid, current->comm);496496- fetch_min_state(ms, pt, sw);497497- unw_init_from_interruption(&info, current, pt, sw);498498- ia64_do_show_stack(&info, NULL);499499-500500- if (read_trylock(&tasklist_lock)) {501501- struct task_struct *g, *t;502502- do_each_thread (g, t) {503503- if (t == current)504504- continue;505505-506506- printk("\nBacktrace of pid %d (%s)\n", t->pid, t->comm);507507- show_stack(t, NULL);508508- } while_each_thread (g, t);509509- }510510-511511- printk("\nINIT dump complete. Please reboot now.\n");512512- while (1); /* hang city if no debugger */513513-}514332515333#ifdef CONFIG_ACPI516334/*···478648}479649480650/*481481- * ia64_mca_wakeup_ipi_wait482482- *483483- * Wait for the inter-cpu interrupt to be sent by the484484- * monarch processor once it is done with handling the485485- * MCA.486486- *487487- * Inputs : None488488- * Outputs : None489489- */490490-static void491491-ia64_mca_wakeup_ipi_wait(void)492492-{493493- int irr_num = (IA64_MCA_WAKEUP_VECTOR >> 6);494494- int irr_bit = (IA64_MCA_WAKEUP_VECTOR & 0x3f);495495- u64 irr = 0;496496-497497- do {498498- switch(irr_num) {499499- case 0:500500- irr = ia64_getreg(_IA64_REG_CR_IRR0);501501- break;502502- case 1:503503- irr = ia64_getreg(_IA64_REG_CR_IRR1);504504- break;505505- case 2:506506- irr = ia64_getreg(_IA64_REG_CR_IRR2);507507- break;508508- case 3:509509- irr = ia64_getreg(_IA64_REG_CR_IRR3);510510- break;511511- }512512- cpu_relax();513513- } while (!(irr & (1UL << irr_bit))) ;514514-}515515-516516-/*517651 * ia64_mca_wakeup518652 *519653 * Send an inter-cpu interrupt to wake-up a particular cpu···542748 */543749 ia64_sal_mc_rendez();544750545545- /* Wait for the wakeup IPI from the monarch546546- * This waiting is done by polling on the wakeup-interrupt547547- * vector bit in the processor's IRRs548548- */549549- ia64_mca_wakeup_ipi_wait();751751+ /* Wait for the monarch cpu to exit. */752752+ while (monarch_cpu != -1)753753+ cpu_relax(); /* spin until monarch leaves */550754551755 /* Enable all interrupts */552756 local_irq_restore(flags);···572780 return IRQ_HANDLED;573781}574782575575-/*576576- * ia64_return_to_sal_check577577- *578578- * This is function called before going back from the OS_MCA handler579579- * to the OS_MCA dispatch code which finally takes the control back580580- * to the SAL.581581- * The main purpose of this routine is to setup the OS_MCA to SAL582582- * return state which can be used by the OS_MCA dispatch code583583- * just before going back to SAL.584584- *585585- * Inputs : None586586- * Outputs : None587587- */588588-589589-static void590590-ia64_return_to_sal_check(int recover)591591-{592592-593593- /* Copy over some relevant stuff from the sal_to_os_mca_handoff594594- * so that it can be used at the time of os_mca_to_sal_handoff595595- */596596- ia64_os_to_sal_handoff_state.imots_sal_gp =597597- ia64_sal_to_os_handoff_state.imsto_sal_gp;598598-599599- ia64_os_to_sal_handoff_state.imots_sal_check_ra =600600- ia64_sal_to_os_handoff_state.imsto_sal_check_ra;601601-602602- if (recover)603603- ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_CORRECTED;604604- else605605- ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_COLD_BOOT;606606-607607- /* Default = tell SAL to return to same context */608608- ia64_os_to_sal_handoff_state.imots_context = IA64_MCA_SAME_CONTEXT;609609-610610- ia64_os_to_sal_handoff_state.imots_new_min_state =611611- (u64 *)ia64_sal_to_os_handoff_state.pal_min_state;612612-613613-}614614-615783/* Function pointer for extra MCA recovery */616784int (*ia64_mca_ucmc_extension)617617- (void*,ia64_mca_sal_to_os_state_t*,ia64_mca_os_to_sal_state_t*)785785+ (void*,struct ia64_sal_os_state*)618786 = NULL;619787620788int621621-ia64_reg_MCA_extension(void *fn)789789+ia64_reg_MCA_extension(int (*fn)(void *, struct ia64_sal_os_state *))622790{623791 if (ia64_mca_ucmc_extension)624792 return 1;···597845EXPORT_SYMBOL(ia64_reg_MCA_extension);598846EXPORT_SYMBOL(ia64_unreg_MCA_extension);599847848848+849849+static inline void850850+copy_reg(const u64 *fr, u64 fnat, u64 *tr, u64 *tnat)851851+{852852+ u64 fslot, tslot, nat;853853+ *tr = *fr;854854+ fslot = ((unsigned long)fr >> 3) & 63;855855+ tslot = ((unsigned long)tr >> 3) & 63;856856+ *tnat &= ~(1UL << tslot);857857+ nat = (fnat >> fslot) & 1;858858+ *tnat |= (nat << tslot);859859+}860860+861861+/* On entry to this routine, we are running on the per cpu stack, see862862+ * mca_asm.h. The original stack has not been touched by this event. Some of863863+ * the original stack's registers will be in the RBS on this stack. This stack864864+ * also contains a partial pt_regs and switch_stack, the rest of the data is in865865+ * PAL minstate.866866+ *867867+ * The first thing to do is modify the original stack to look like a blocked868868+ * task so we can run backtrace on the original task. Also mark the per cpu869869+ * stack as current to ensure that we use the correct task state, it also means870870+ * that we can do backtrace on the MCA/INIT handler code itself.871871+ */872872+873873+static task_t *874874+ia64_mca_modify_original_stack(struct pt_regs *regs,875875+ const struct switch_stack *sw,876876+ struct ia64_sal_os_state *sos,877877+ const char *type)878878+{879879+ char *p, comm[sizeof(current->comm)];880880+ ia64_va va;881881+ extern char ia64_leave_kernel[]; /* Need asm address, not function descriptor */882882+ const pal_min_state_area_t *ms = sos->pal_min_state;883883+ task_t *previous_current;884884+ struct pt_regs *old_regs;885885+ struct switch_stack *old_sw;886886+ unsigned size = sizeof(struct pt_regs) +887887+ sizeof(struct switch_stack) + 16;888888+ u64 *old_bspstore, *old_bsp;889889+ u64 *new_bspstore, *new_bsp;890890+ u64 old_unat, old_rnat, new_rnat, nat;891891+ u64 slots, loadrs = regs->loadrs;892892+ u64 r12 = ms->pmsa_gr[12-1], r13 = ms->pmsa_gr[13-1];893893+ u64 ar_bspstore = regs->ar_bspstore;894894+ u64 ar_bsp = regs->ar_bspstore + (loadrs >> 16);895895+ const u64 *bank;896896+ const char *msg;897897+ int cpu = smp_processor_id();898898+899899+ previous_current = curr_task(cpu);900900+ set_curr_task(cpu, current);901901+ if ((p = strchr(current->comm, ' ')))902902+ *p = '\0';903903+904904+ /* Best effort attempt to cope with MCA/INIT delivered while in905905+ * physical mode.906906+ */907907+ regs->cr_ipsr = ms->pmsa_ipsr;908908+ if (ia64_psr(regs)->dt == 0) {909909+ va.l = r12;910910+ if (va.f.reg == 0) {911911+ va.f.reg = 7;912912+ r12 = va.l;913913+ }914914+ va.l = r13;915915+ if (va.f.reg == 0) {916916+ va.f.reg = 7;917917+ r13 = va.l;918918+ }919919+ }920920+ if (ia64_psr(regs)->rt == 0) {921921+ va.l = ar_bspstore;922922+ if (va.f.reg == 0) {923923+ va.f.reg = 7;924924+ ar_bspstore = va.l;925925+ }926926+ va.l = ar_bsp;927927+ if (va.f.reg == 0) {928928+ va.f.reg = 7;929929+ ar_bsp = va.l;930930+ }931931+ }932932+933933+ /* mca_asm.S ia64_old_stack() cannot assume that the dirty registers934934+ * have been copied to the old stack, the old stack may fail the935935+ * validation tests below. So ia64_old_stack() must restore the dirty936936+ * registers from the new stack. The old and new bspstore probably937937+ * have different alignments, so loadrs calculated on the old bsp938938+ * cannot be used to restore from the new bsp. Calculate a suitable939939+ * loadrs for the new stack and save it in the new pt_regs, where940940+ * ia64_old_stack() can get it.941941+ */942942+ old_bspstore = (u64 *)ar_bspstore;943943+ old_bsp = (u64 *)ar_bsp;944944+ slots = ia64_rse_num_regs(old_bspstore, old_bsp);945945+ new_bspstore = (u64 *)((u64)current + IA64_RBS_OFFSET);946946+ new_bsp = ia64_rse_skip_regs(new_bspstore, slots);947947+ regs->loadrs = (new_bsp - new_bspstore) * 8 << 16;948948+949949+ /* Verify the previous stack state before we change it */950950+ if (user_mode(regs)) {951951+ msg = "occurred in user space";952952+ goto no_mod;953953+ }954954+ if (r13 != sos->prev_IA64_KR_CURRENT) {955955+ msg = "inconsistent previous current and r13";956956+ goto no_mod;957957+ }958958+ if ((r12 - r13) >= KERNEL_STACK_SIZE) {959959+ msg = "inconsistent r12 and r13";960960+ goto no_mod;961961+ }962962+ if ((ar_bspstore - r13) >= KERNEL_STACK_SIZE) {963963+ msg = "inconsistent ar.bspstore and r13";964964+ goto no_mod;965965+ }966966+ va.p = old_bspstore;967967+ if (va.f.reg < 5) {968968+ msg = "old_bspstore is in the wrong region";969969+ goto no_mod;970970+ }971971+ if ((ar_bsp - r13) >= KERNEL_STACK_SIZE) {972972+ msg = "inconsistent ar.bsp and r13";973973+ goto no_mod;974974+ }975975+ size += (ia64_rse_skip_regs(old_bspstore, slots) - old_bspstore) * 8;976976+ if (ar_bspstore + size > r12) {977977+ msg = "no room for blocked state";978978+ goto no_mod;979979+ }980980+981981+ /* Change the comm field on the MCA/INT task to include the pid that982982+ * was interrupted, it makes for easier debugging. If that pid was 0983983+ * (swapper or nested MCA/INIT) then use the start of the previous comm984984+ * field suffixed with its cpu.985985+ */986986+ if (previous_current->pid)987987+ snprintf(comm, sizeof(comm), "%s %d",988988+ current->comm, previous_current->pid);989989+ else {990990+ int l;991991+ if ((p = strchr(previous_current->comm, ' ')))992992+ l = p - previous_current->comm;993993+ else994994+ l = strlen(previous_current->comm);995995+ snprintf(comm, sizeof(comm), "%s %*s %d",996996+ current->comm, l, previous_current->comm,997997+ previous_current->thread_info->cpu);998998+ }999999+ memcpy(current->comm, comm, sizeof(current->comm));10001000+10011001+ /* Make the original task look blocked. First stack a struct pt_regs,10021002+ * describing the state at the time of interrupt. mca_asm.S built a10031003+ * partial pt_regs, copy it and fill in the blanks using minstate.10041004+ */10051005+ p = (char *)r12 - sizeof(*regs);10061006+ old_regs = (struct pt_regs *)p;10071007+ memcpy(old_regs, regs, sizeof(*regs));10081008+ /* If ipsr.ic then use pmsa_{iip,ipsr,ifs}, else use10091009+ * pmsa_{xip,xpsr,xfs}10101010+ */10111011+ if (ia64_psr(regs)->ic) {10121012+ old_regs->cr_iip = ms->pmsa_iip;10131013+ old_regs->cr_ipsr = ms->pmsa_ipsr;10141014+ old_regs->cr_ifs = ms->pmsa_ifs;10151015+ } else {10161016+ old_regs->cr_iip = ms->pmsa_xip;10171017+ old_regs->cr_ipsr = ms->pmsa_xpsr;10181018+ old_regs->cr_ifs = ms->pmsa_xfs;10191019+ }10201020+ old_regs->pr = ms->pmsa_pr;10211021+ old_regs->b0 = ms->pmsa_br0;10221022+ old_regs->loadrs = loadrs;10231023+ old_regs->ar_rsc = ms->pmsa_rsc;10241024+ old_unat = old_regs->ar_unat;10251025+ copy_reg(&ms->pmsa_gr[1-1], ms->pmsa_nat_bits, &old_regs->r1, &old_unat);10261026+ copy_reg(&ms->pmsa_gr[2-1], ms->pmsa_nat_bits, &old_regs->r2, &old_unat);10271027+ copy_reg(&ms->pmsa_gr[3-1], ms->pmsa_nat_bits, &old_regs->r3, &old_unat);10281028+ copy_reg(&ms->pmsa_gr[8-1], ms->pmsa_nat_bits, &old_regs->r8, &old_unat);10291029+ copy_reg(&ms->pmsa_gr[9-1], ms->pmsa_nat_bits, &old_regs->r9, &old_unat);10301030+ copy_reg(&ms->pmsa_gr[10-1], ms->pmsa_nat_bits, &old_regs->r10, &old_unat);10311031+ copy_reg(&ms->pmsa_gr[11-1], ms->pmsa_nat_bits, &old_regs->r11, &old_unat);10321032+ copy_reg(&ms->pmsa_gr[12-1], ms->pmsa_nat_bits, &old_regs->r12, &old_unat);10331033+ copy_reg(&ms->pmsa_gr[13-1], ms->pmsa_nat_bits, &old_regs->r13, &old_unat);10341034+ copy_reg(&ms->pmsa_gr[14-1], ms->pmsa_nat_bits, &old_regs->r14, &old_unat);10351035+ copy_reg(&ms->pmsa_gr[15-1], ms->pmsa_nat_bits, &old_regs->r15, &old_unat);10361036+ if (ia64_psr(old_regs)->bn)10371037+ bank = ms->pmsa_bank1_gr;10381038+ else10391039+ bank = ms->pmsa_bank0_gr;10401040+ copy_reg(&bank[16-16], ms->pmsa_nat_bits, &old_regs->r16, &old_unat);10411041+ copy_reg(&bank[17-16], ms->pmsa_nat_bits, &old_regs->r17, &old_unat);10421042+ copy_reg(&bank[18-16], ms->pmsa_nat_bits, &old_regs->r18, &old_unat);10431043+ copy_reg(&bank[19-16], ms->pmsa_nat_bits, &old_regs->r19, &old_unat);10441044+ copy_reg(&bank[20-16], ms->pmsa_nat_bits, &old_regs->r20, &old_unat);10451045+ copy_reg(&bank[21-16], ms->pmsa_nat_bits, &old_regs->r21, &old_unat);10461046+ copy_reg(&bank[22-16], ms->pmsa_nat_bits, &old_regs->r22, &old_unat);10471047+ copy_reg(&bank[23-16], ms->pmsa_nat_bits, &old_regs->r23, &old_unat);10481048+ copy_reg(&bank[24-16], ms->pmsa_nat_bits, &old_regs->r24, &old_unat);10491049+ copy_reg(&bank[25-16], ms->pmsa_nat_bits, &old_regs->r25, &old_unat);10501050+ copy_reg(&bank[26-16], ms->pmsa_nat_bits, &old_regs->r26, &old_unat);10511051+ copy_reg(&bank[27-16], ms->pmsa_nat_bits, &old_regs->r27, &old_unat);10521052+ copy_reg(&bank[28-16], ms->pmsa_nat_bits, &old_regs->r28, &old_unat);10531053+ copy_reg(&bank[29-16], ms->pmsa_nat_bits, &old_regs->r29, &old_unat);10541054+ copy_reg(&bank[30-16], ms->pmsa_nat_bits, &old_regs->r30, &old_unat);10551055+ copy_reg(&bank[31-16], ms->pmsa_nat_bits, &old_regs->r31, &old_unat);10561056+10571057+ /* Next stack a struct switch_stack. mca_asm.S built a partial10581058+ * switch_stack, copy it and fill in the blanks using pt_regs and10591059+ * minstate.10601060+ *10611061+ * In the synthesized switch_stack, b0 points to ia64_leave_kernel,10621062+ * ar.pfs is set to 0.10631063+ *10641064+ * unwind.c::unw_unwind() does special processing for interrupt frames.10651065+ * It checks if the PRED_NON_SYSCALL predicate is set, if the predicate10661066+ * is clear then unw_unwind() does _not_ adjust bsp over pt_regs. Not10671067+ * that this is documented, of course. Set PRED_NON_SYSCALL in the10681068+ * switch_stack on the original stack so it will unwind correctly when10691069+ * unwind.c reads pt_regs.10701070+ *10711071+ * thread.ksp is updated to point to the synthesized switch_stack.10721072+ */10731073+ p -= sizeof(struct switch_stack);10741074+ old_sw = (struct switch_stack *)p;10751075+ memcpy(old_sw, sw, sizeof(*sw));10761076+ old_sw->caller_unat = old_unat;10771077+ old_sw->ar_fpsr = old_regs->ar_fpsr;10781078+ copy_reg(&ms->pmsa_gr[4-1], ms->pmsa_nat_bits, &old_sw->r4, &old_unat);10791079+ copy_reg(&ms->pmsa_gr[5-1], ms->pmsa_nat_bits, &old_sw->r5, &old_unat);10801080+ copy_reg(&ms->pmsa_gr[6-1], ms->pmsa_nat_bits, &old_sw->r6, &old_unat);10811081+ copy_reg(&ms->pmsa_gr[7-1], ms->pmsa_nat_bits, &old_sw->r7, &old_unat);10821082+ old_sw->b0 = (u64)ia64_leave_kernel;10831083+ old_sw->b1 = ms->pmsa_br1;10841084+ old_sw->ar_pfs = 0;10851085+ old_sw->ar_unat = old_unat;10861086+ old_sw->pr = old_regs->pr | (1UL << PRED_NON_SYSCALL);10871087+ previous_current->thread.ksp = (u64)p - 16;10881088+10891089+ /* Finally copy the original stack's registers back to its RBS.10901090+ * Registers from ar.bspstore through ar.bsp at the time of the event10911091+ * are in the current RBS, copy them back to the original stack. The10921092+ * copy must be done register by register because the original bspstore10931093+ * and the current one have different alignments, so the saved RNAT10941094+ * data occurs at different places.10951095+ *10961096+ * mca_asm does cover, so the old_bsp already includes all registers at10971097+ * the time of MCA/INIT. It also does flushrs, so all registers before10981098+ * this function have been written to backing store on the MCA/INIT10991099+ * stack.11001100+ */11011101+ new_rnat = ia64_get_rnat(ia64_rse_rnat_addr(new_bspstore));11021102+ old_rnat = regs->ar_rnat;11031103+ while (slots--) {11041104+ if (ia64_rse_is_rnat_slot(new_bspstore)) {11051105+ new_rnat = ia64_get_rnat(new_bspstore++);11061106+ }11071107+ if (ia64_rse_is_rnat_slot(old_bspstore)) {11081108+ *old_bspstore++ = old_rnat;11091109+ old_rnat = 0;11101110+ }11111111+ nat = (new_rnat >> ia64_rse_slot_num(new_bspstore)) & 1UL;11121112+ old_rnat &= ~(1UL << ia64_rse_slot_num(old_bspstore));11131113+ old_rnat |= (nat << ia64_rse_slot_num(old_bspstore));11141114+ *old_bspstore++ = *new_bspstore++;11151115+ }11161116+ old_sw->ar_bspstore = (unsigned long)old_bspstore;11171117+ old_sw->ar_rnat = old_rnat;11181118+11191119+ sos->prev_task = previous_current;11201120+ return previous_current;11211121+11221122+no_mod:11231123+ printk(KERN_INFO "cpu %d, %s %s, original stack not modified\n",11241124+ smp_processor_id(), type, msg);11251125+ return previous_current;11261126+}11271127+11281128+/* The monarch/slave interaction is based on monarch_cpu and requires that all11291129+ * slaves have entered rendezvous before the monarch leaves. If any cpu has11301130+ * not entered rendezvous yet then wait a bit. The assumption is that any11311131+ * slave that has not rendezvoused after a reasonable time is never going to do11321132+ * so. In this context, slave includes cpus that respond to the MCA rendezvous11331133+ * interrupt, as well as cpus that receive the INIT slave event.11341134+ */11351135+11361136+static void11371137+ia64_wait_for_slaves(int monarch)11381138+{11391139+ int c, wait = 0;11401140+ for_each_online_cpu(c) {11411141+ if (c == monarch)11421142+ continue;11431143+ if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) {11441144+ udelay(1000); /* short wait first */11451145+ wait = 1;11461146+ break;11471147+ }11481148+ }11491149+ if (!wait)11501150+ return;11511151+ for_each_online_cpu(c) {11521152+ if (c == monarch)11531153+ continue;11541154+ if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) {11551155+ udelay(5*1000000); /* wait 5 seconds for slaves (arbitrary) */11561156+ break;11571157+ }11581158+ }11591159+}11601160+6001161/*601601- * ia64_mca_ucmc_handler11621162+ * ia64_mca_handler6021163 *6031164 * This is uncorrectable machine check handler called from OS_MCA6041165 * dispatch code which is in turn called from SAL_CHECK().···922857 * further MCA logging is enabled by clearing logs.923858 * Monarch also has the duty of sending wakeup-IPIs to pull the924859 * slave processors out of rendezvous spinloop.925925- *926926- * Inputs : None927927- * Outputs : None928860 */929861void930930-ia64_mca_ucmc_handler(void)862862+ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,863863+ struct ia64_sal_os_state *sos)931864{932865 pal_processor_state_info_t *psp = (pal_processor_state_info_t *)933933- &ia64_sal_to_os_handoff_state.proc_state_param;934934- int recover; 866866+ &sos->proc_state_param;867867+ int recover, cpu = smp_processor_id();868868+ task_t *previous_current;869869+870870+ oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */871871+ previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA");872872+ monarch_cpu = cpu;873873+ ia64_wait_for_slaves(cpu);874874+875875+ /* Wakeup all the processors which are spinning in the rendezvous loop.876876+ * They will leave SAL, then spin in the OS with interrupts disabled877877+ * until this monarch cpu leaves the MCA handler. That gets control878878+ * back to the OS so we can backtrace the other cpus, backtrace when879879+ * spinning in SAL does not work.880880+ */881881+ ia64_mca_wakeup_all();935882936883 /* Get the MCA error record and log it */937884 ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA);···951874 /* TLB error is only exist in this SAL error record */952875 recover = (psp->tc && !(psp->cc || psp->bc || psp->rc || psp->uc))953876 /* other error recovery */954954- || (ia64_mca_ucmc_extension 877877+ || (ia64_mca_ucmc_extension955878 && ia64_mca_ucmc_extension(956879 IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_MCA),957957- &ia64_sal_to_os_handoff_state,958958- &ia64_os_to_sal_handoff_state)); 880880+ sos));959881960882 if (recover) {961883 sal_log_record_header_t *rh = IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_MCA);962884 rh->severity = sal_log_severity_corrected;963885 ia64_sal_clear_state_info(SAL_INFO_TYPE_MCA);886886+ sos->os_status = IA64_MCA_CORRECTED;964887 }965965- /*966966- * Wakeup all the processors which are spinning in the rendezvous967967- * loop.968968- */969969- ia64_mca_wakeup_all();970888971971- /* Return to SAL */972972- ia64_return_to_sal_check(recover);889889+ set_curr_task(cpu, previous_current);890890+ monarch_cpu = -1;973891}974892975893static DECLARE_WORK(cmc_disable_work, ia64_mca_cmc_vector_disable_keventd, NULL);···11881116/*11891117 * C portion of the OS INIT handler11901118 *11911191- * Called from ia64_monarch_init_handler11191119+ * Called from ia64_os_init_dispatch11921120 *11931193- * Inputs: pointer to pt_regs where processor info was saved.11211121+ * Inputs: pointer to pt_regs where processor info was saved. SAL/OS state for11221122+ * this event. This code is used for both monarch and slave INIT events, see11231123+ * sos->monarch.11941124 *11951195- * Returns:11961196- * 0 if SAL must warm boot the System11971197- * 1 if SAL must return to interrupted context using PAL_MC_RESUME11981198- *11251125+ * All INIT events switch to the INIT stack and change the previous process to11261126+ * blocked status. If one of the INIT events is the monarch then we are11271127+ * probably processing the nmi button/command. Use the monarch cpu to dump all11281128+ * the processes. The slave INIT events all spin until the monarch cpu11291129+ * returns. We can also get INIT slave events for MCA, in which case the MCA11301130+ * process is the monarch.11991131 */12001200-void12011201-ia64_init_handler (struct pt_regs *pt, struct switch_stack *sw)12021202-{12031203- pal_min_state_area_t *ms;1204113212051205- oops_in_progress = 1; /* avoid deadlock in printk, but it makes recovery dodgy */11331133+void11341134+ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,11351135+ struct ia64_sal_os_state *sos)11361136+{11371137+ static atomic_t slaves;11381138+ static atomic_t monarchs;11391139+ task_t *previous_current;11401140+ int cpu = smp_processor_id(), c;11411141+ struct task_struct *g, *t;11421142+11431143+ oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */12061144 console_loglevel = 15; /* make sure printks make it to console */1207114512081208- printk(KERN_INFO "Entered OS INIT handler. PSP=%lx\n",12091209- ia64_sal_to_os_handoff_state.proc_state_param);11461146+ printk(KERN_INFO "Entered OS INIT handler. PSP=%lx cpu=%d monarch=%ld\n",11471147+ sos->proc_state_param, cpu, sos->monarch);11481148+ salinfo_log_wakeup(SAL_INFO_TYPE_INIT, NULL, 0, 0);11491149+11501150+ previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "INIT");11511151+ sos->os_status = IA64_INIT_RESUME;11521152+11531153+ /* FIXME: Workaround for broken proms that drive all INIT events as11541154+ * slaves. The last slave that enters is promoted to be a monarch.11551155+ * Remove this code in September 2006, that gives platforms a year to11561156+ * fix their proms and get their customers updated.11571157+ */11581158+ if (!sos->monarch && atomic_add_return(1, &slaves) == num_online_cpus()) {11591159+ printk(KERN_WARNING "%s: Promoting cpu %d to monarch.\n",11601160+ __FUNCTION__, cpu);11611161+ atomic_dec(&slaves);11621162+ sos->monarch = 1;11631163+ }11641164+11651165+ /* FIXME: Workaround for broken proms that drive all INIT events as11661166+ * monarchs. Second and subsequent monarchs are demoted to slaves.11671167+ * Remove this code in September 2006, that gives platforms a year to11681168+ * fix their proms and get their customers updated.11691169+ */11701170+ if (sos->monarch && atomic_add_return(1, &monarchs) > 1) {11711171+ printk(KERN_WARNING "%s: Demoting cpu %d to slave.\n",11721172+ __FUNCTION__, cpu);11731173+ atomic_dec(&monarchs);11741174+ sos->monarch = 0;11751175+ }11761176+11771177+ if (!sos->monarch) {11781178+ ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_INIT;11791179+ while (monarch_cpu == -1)11801180+ cpu_relax(); /* spin until monarch enters */11811181+ while (monarch_cpu != -1)11821182+ cpu_relax(); /* spin until monarch leaves */11831183+ printk("Slave on cpu %d returning to normal service.\n", cpu);11841184+ set_curr_task(cpu, previous_current);11851185+ ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;11861186+ atomic_dec(&slaves);11871187+ return;11881188+ }11891189+11901190+ monarch_cpu = cpu;1210119112111192 /*12121212- * Address of minstate area provided by PAL is physical,12131213- * uncacheable (bit 63 set). Convert to Linux virtual12141214- * address in region 6.11931193+ * Wait for a bit. On some machines (e.g., HP's zx2000 and zx6000, INIT can be11941194+ * generated via the BMC's command-line interface, but since the console is on the11951195+ * same serial line, the user will need some time to switch out of the BMC before11961196+ * the dump begins.12151197 */12161216- ms = (pal_min_state_area_t *)(ia64_sal_to_os_handoff_state.pal_min_state | (6ul<<61));12171217-12181218- init_handler_platform(ms, pt, sw); /* call platform specific routines */11981198+ printk("Delaying for 5 seconds...\n");11991199+ udelay(5*1000000);12001200+ ia64_wait_for_slaves(cpu);12011201+ printk(KERN_ERR "Processes interrupted by INIT -");12021202+ for_each_online_cpu(c) {12031203+ struct ia64_sal_os_state *s;12041204+ t = __va(__per_cpu_mca[c] + IA64_MCA_CPU_INIT_STACK_OFFSET);12051205+ s = (struct ia64_sal_os_state *)((char *)t + MCA_SOS_OFFSET);12061206+ g = s->prev_task;12071207+ if (g) {12081208+ if (g->pid)12091209+ printk(" %d", g->pid);12101210+ else12111211+ printk(" %d (cpu %d task 0x%p)", g->pid, task_cpu(g), g);12121212+ }12131213+ }12141214+ printk("\n\n");12151215+ if (read_trylock(&tasklist_lock)) {12161216+ do_each_thread (g, t) {12171217+ printk("\nBacktrace of pid %d (%s)\n", t->pid, t->comm);12181218+ show_stack(t, NULL);12191219+ } while_each_thread (g, t);12201220+ read_unlock(&tasklist_lock);12211221+ }12221222+ printk("\nINIT dump complete. Monarch on cpu %d returning to normal service.\n", cpu);12231223+ atomic_dec(&monarchs);12241224+ set_curr_task(cpu, previous_current);12251225+ monarch_cpu = -1;12261226+ return;12191227}1220122812211229static int __init···13451193};13461194#endif /* CONFIG_ACPI */1347119511961196+/* Minimal format of the MCA/INIT stacks. The pseudo processes that run on11971197+ * these stacks can never sleep, they cannot return from the kernel to user11981198+ * space, they do not appear in a normal ps listing. So there is no need to11991199+ * format most of the fields.12001200+ */12011201+12021202+static void12031203+format_mca_init_stack(void *mca_data, unsigned long offset,12041204+ const char *type, int cpu)12051205+{12061206+ struct task_struct *p = (struct task_struct *)((char *)mca_data + offset);12071207+ struct thread_info *ti;12081208+ memset(p, 0, KERNEL_STACK_SIZE);12091209+ ti = (struct thread_info *)((char *)p + IA64_TASK_SIZE);12101210+ ti->flags = _TIF_MCA_INIT;12111211+ ti->preempt_count = 1;12121212+ ti->task = p;12131213+ ti->cpu = cpu;12141214+ p->thread_info = ti;12151215+ p->state = TASK_UNINTERRUPTIBLE;12161216+ __set_bit(cpu, &p->cpus_allowed);12171217+ INIT_LIST_HEAD(&p->tasks);12181218+ p->parent = p->real_parent = p->group_leader = p;12191219+ INIT_LIST_HEAD(&p->children);12201220+ INIT_LIST_HEAD(&p->sibling);12211221+ strncpy(p->comm, type, sizeof(p->comm)-1);12221222+}12231223+13481224/* Do per-CPU MCA-related initialization. */1349122513501226void __devinit···13851205 int cpu;1386120613871207 mca_data = alloc_bootmem(sizeof(struct ia64_mca_cpu)13881388- * NR_CPUS);12081208+ * NR_CPUS + KERNEL_STACK_SIZE);12091209+ mca_data = (void *)(((unsigned long)mca_data +12101210+ KERNEL_STACK_SIZE - 1) &12111211+ (-KERNEL_STACK_SIZE));13891212 for (cpu = 0; cpu < NR_CPUS; cpu++) {12131213+ format_mca_init_stack(mca_data,12141214+ offsetof(struct ia64_mca_cpu, mca_stack),12151215+ "MCA", cpu);12161216+ format_mca_init_stack(mca_data,12171217+ offsetof(struct ia64_mca_cpu, init_stack),12181218+ "INIT", cpu);13901219 __per_cpu_mca[cpu] = __pa(mca_data);13911220 mca_data += sizeof(struct ia64_mca_cpu);13921221 }13931222 }1394122313951395- /*13961396- * The MCA info structure was allocated earlier and its13971397- * physical address saved in __per_cpu_mca[cpu]. Copy that13981398- * address * to ia64_mca_data so we can access it as a per-CPU13991399- * variable.14001400- */12241224+ /*12251225+ * The MCA info structure was allocated earlier and its12261226+ * physical address saved in __per_cpu_mca[cpu]. Copy that12271227+ * address * to ia64_mca_data so we can access it as a per-CPU12281228+ * variable.12291229+ */14011230 __get_cpu_var(ia64_mca_data) = __per_cpu_mca[smp_processor_id()];1402123114031232 /*···14161227 __get_cpu_var(ia64_mca_per_cpu_pte) =14171228 pte_val(mk_pte_phys(__pa(cpu_data), PAGE_KERNEL));1418122914191419- /*14201420- * Also, stash away a copy of the PAL address and the PTE14211421- * needed to map it.14221422- */14231423- pal_vaddr = efi_get_pal_addr();12301230+ /*12311231+ * Also, stash away a copy of the PAL address and the PTE12321232+ * needed to map it.12331233+ */12341234+ pal_vaddr = efi_get_pal_addr();14241235 if (!pal_vaddr)14251236 return;14261237 __get_cpu_var(ia64_mca_pal_base) =···14521263void __init14531264ia64_mca_init(void)14541265{14551455- ia64_fptr_t *mon_init_ptr = (ia64_fptr_t *)ia64_monarch_init_handler;14561456- ia64_fptr_t *slave_init_ptr = (ia64_fptr_t *)ia64_slave_init_handler;12661266+ ia64_fptr_t *init_hldlr_ptr_monarch = (ia64_fptr_t *)ia64_os_init_dispatch_monarch;12671267+ ia64_fptr_t *init_hldlr_ptr_slave = (ia64_fptr_t *)ia64_os_init_dispatch_slave;14571268 ia64_fptr_t *mca_hldlr_ptr = (ia64_fptr_t *)ia64_os_mca_dispatch;14581269 int i;14591270 s64 rc;···15311342 * XXX - disable SAL checksum by setting size to 0, should be15321343 * size of the actual init handler in mca_asm.S.15331344 */15341534- ia64_mc_info.imi_monarch_init_handler = ia64_tpa(mon_init_ptr->fp);13451345+ ia64_mc_info.imi_monarch_init_handler = ia64_tpa(init_hldlr_ptr_monarch->fp);15351346 ia64_mc_info.imi_monarch_init_handler_size = 0;15361536- ia64_mc_info.imi_slave_init_handler = ia64_tpa(slave_init_ptr->fp);13471347+ ia64_mc_info.imi_slave_init_handler = ia64_tpa(init_hldlr_ptr_slave->fp);15371348 ia64_mc_info.imi_slave_init_handler_size = 0;1538134915391350 IA64_MCA_DEBUG("%s: OS INIT handler at %lx\n", __FUNCTION__,
+759-681
arch/ia64/kernel/mca_asm.S
···1616// 04/11/12 Russ Anderson <rja@sgi.com>1717// Added per cpu MCA/INIT stack save areas.1818//1919+// 12/08/05 Keith Owens <kaos@sgi.com>2020+// Use per cpu MCA/INIT stacks for all data.2121+//1922#include <linux/config.h>2023#include <linux/threads.h>2124···2825#include <asm/mca_asm.h>2926#include <asm/mca.h>30273131-/*3232- * When we get a machine check, the kernel stack pointer is no longer3333- * valid, so we need to set a new stack pointer.3434- */3535-#define MINSTATE_PHYS /* Make sure stack access is physical for MINSTATE */3636-3737-/*3838- * Needed for return context to SAL3939- */4040-#define IA64_MCA_SAME_CONTEXT 04141-#define IA64_MCA_COLD_BOOT -24242-4343-#include "minstate.h"4444-4545-/*4646- * SAL_TO_OS_MCA_HANDOFF_STATE (SAL 3.0 spec)4747- * 1. GR1 = OS GP4848- * 2. GR8 = PAL_PROC physical address4949- * 3. GR9 = SAL_PROC physical address5050- * 4. GR10 = SAL GP (physical)5151- * 5. GR11 = Rendez state5252- * 6. GR12 = Return address to location within SAL_CHECK5353- */5454-#define SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(_tmp) \5555- LOAD_PHYSICAL(p0, _tmp, ia64_sal_to_os_handoff_state);; \5656- st8 [_tmp]=r1,0x08;; \5757- st8 [_tmp]=r8,0x08;; \5858- st8 [_tmp]=r9,0x08;; \5959- st8 [_tmp]=r10,0x08;; \6060- st8 [_tmp]=r11,0x08;; \6161- st8 [_tmp]=r12,0x08;; \6262- st8 [_tmp]=r17,0x08;; \6363- st8 [_tmp]=r18,0x086464-6565-/*6666- * OS_MCA_TO_SAL_HANDOFF_STATE (SAL 3.0 spec)6767- * (p6) is executed if we never entered virtual mode (TLB error)6868- * (p7) is executed if we entered virtual mode as expected (normal case)6969- * 1. GR8 = OS_MCA return status7070- * 2. GR9 = SAL GP (physical)7171- * 3. GR10 = 0/1 returning same/new context7272- * 4. GR22 = New min state save area pointer7373- * returns ptr to SAL rtn save loc in _tmp7474- */7575-#define OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(_tmp) \7676- movl _tmp=ia64_os_to_sal_handoff_state;; \7777- DATA_VA_TO_PA(_tmp);; \7878- ld8 r8=[_tmp],0x08;; \7979- ld8 r9=[_tmp],0x08;; \8080- ld8 r10=[_tmp],0x08;; \8181- ld8 r22=[_tmp],0x08;;8282- // now _tmp is pointing to SAL rtn save location8383-8484-/*8585- * COLD_BOOT_HANDOFF_STATE() sets ia64_mca_os_to_sal_state8686- * imots_os_status=IA64_MCA_COLD_BOOT8787- * imots_sal_gp=SAL GP8888- * imots_context=IA64_MCA_SAME_CONTEXT8989- * imots_new_min_state=Min state save area pointer9090- * imots_sal_check_ra=Return address to location within SAL_CHECK9191- *9292- */9393-#define COLD_BOOT_HANDOFF_STATE(sal_to_os_handoff,os_to_sal_handoff,tmp)\9494- movl tmp=IA64_MCA_COLD_BOOT; \9595- movl sal_to_os_handoff=__pa(ia64_sal_to_os_handoff_state); \9696- movl os_to_sal_handoff=__pa(ia64_os_to_sal_handoff_state);; \9797- st8 [os_to_sal_handoff]=tmp,8;; \9898- ld8 tmp=[sal_to_os_handoff],48;; \9999- st8 [os_to_sal_handoff]=tmp,8;; \100100- movl tmp=IA64_MCA_SAME_CONTEXT;; \101101- st8 [os_to_sal_handoff]=tmp,8;; \102102- ld8 tmp=[sal_to_os_handoff],-8;; \103103- st8 [os_to_sal_handoff]=tmp,8;; \104104- ld8 tmp=[sal_to_os_handoff];; \105105- st8 [os_to_sal_handoff]=tmp;;2828+#include "entry.h"1062910730#define GET_IA64_MCA_DATA(reg) \10831 GET_THIS_PADDR(reg, ia64_mca_data) \10932 ;; \11033 ld8 reg=[reg]11134112112- .global ia64_os_mca_dispatch113113- .global ia64_os_mca_dispatch_end114114- .global ia64_sal_to_os_handoff_state115115- .global ia64_os_to_sal_handoff_state11635 .global ia64_do_tlb_purge3636+ .global ia64_os_mca_dispatch3737+ .global ia64_os_init_dispatch_monarch3838+ .global ia64_os_init_dispatch_slave1173911840 .text11941 .align 164242+4343+//StartMain////////////////////////////////////////////////////////////////////1204412145/*12246 * Just the TLB purge part is moved to a separate function···137207 br.sptk.many b1138208 ;;139209140140-ia64_os_mca_dispatch:210210+//EndMain//////////////////////////////////////////////////////////////////////141211212212+//StartMain////////////////////////////////////////////////////////////////////213213+214214+ia64_os_mca_dispatch:142215 // Serialize all MCA processing143216 mov r3=1;;144217 LOAD_PHYSICAL(p0,r2,ia64_mca_serialize);;145218ia64_os_mca_spin:146146- xchg8 r4=[r2],r3;;219219+ xchg4 r4=[r2],r3;;147220 cmp.ne p6,p0=r4,r0148221(p6) br ia64_os_mca_spin149222150150- // Save the SAL to OS MCA handoff state as defined151151- // by SAL SPEC 3.0152152- // NOTE : The order in which the state gets saved153153- // is dependent on the way the C-structure154154- // for ia64_mca_sal_to_os_state_t has been155155- // defined in include/asm/mca.h156156- SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2)223223+ mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET // use the MCA stack224224+ LOAD_PHYSICAL(p0,r2,1f) // return address225225+ mov r19=1 // All MCA events are treated as monarch (for now)226226+ br.sptk ia64_state_save // save the state that is not in minstate227227+1:228228+229229+ GET_IA64_MCA_DATA(r2)230230+ // Using MCA stack, struct ia64_sal_os_state, variable proc_state_param157231 ;;158158-159159- // LOG PROCESSOR STATE INFO FROM HERE ON..160160-begin_os_mca_dump:161161- br ia64_os_mca_proc_state_dump;;162162-163163-ia64_os_mca_done_dump:164164-165165- LOAD_PHYSICAL(p0,r16,ia64_sal_to_os_handoff_state+56)232232+ add r3=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_SOS_OFFSET+IA64_SAL_OS_STATE_PROC_STATE_PARAM_OFFSET, r2166233 ;;167167- ld8 r18=[r16] // Get processor state parameter on existing PALE_CHECK.234234+ ld8 r18=[r3] // Get processor state parameter on existing PALE_CHECK.168235 ;;169236 tbit.nz p6,p7=r18,60170237(p7) br.spnt done_tlb_purge_and_reload···250323 itr.d dtr[r20]=r16251324 ;;252325 srlz.d253253- ;;254254- br.sptk.many done_tlb_purge_and_reload255255-err:256256- COLD_BOOT_HANDOFF_STATE(r20,r21,r22)257257- br.sptk.many ia64_os_mca_done_restore258326259327done_tlb_purge_and_reload:260328261261- // Setup new stack frame for OS_MCA handling262262- GET_IA64_MCA_DATA(r2)263263- ;;264264- add r3 = IA64_MCA_CPU_STACKFRAME_OFFSET, r2265265- add r2 = IA64_MCA_CPU_RBSTORE_OFFSET, r2266266- ;;267267- rse_switch_context(r6,r3,r2);; // RSC management in this new context329329+ // switch to per cpu MCA stack330330+ mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET // use the MCA stack331331+ LOAD_PHYSICAL(p0,r2,1f) // return address332332+ br.sptk ia64_new_stack333333+1:268334335335+ // everything saved, now we can set the kernel registers336336+ mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET // use the MCA stack337337+ LOAD_PHYSICAL(p0,r2,1f) // return address338338+ br.sptk ia64_set_kernel_registers339339+1:340340+341341+ // This must be done in physical mode269342 GET_IA64_MCA_DATA(r2)270343 ;;271271- add r2 = IA64_MCA_CPU_STACK_OFFSET+IA64_MCA_STACK_SIZE-16, r2272272- ;;273273- mov r12=r2 // establish new stack-pointer344344+ mov r7=r2274345275346 // Enter virtual mode from physical mode276347 VIRTUAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_begin, r4)277277-ia64_os_mca_virtual_begin:348348+349349+ // This code returns to SAL via SOS r2, in general SAL has no unwind350350+ // data. To get a clean termination when backtracing the C MCA/INIT351351+ // handler, set a dummy return address of 0 in this routine. That352352+ // requires that ia64_os_mca_virtual_begin be a global function.353353+ENTRY(ia64_os_mca_virtual_begin)354354+ .prologue355355+ .save rp,r0356356+ .body357357+358358+ mov ar.rsc=3 // set eager mode for C handler359359+ mov r2=r7 // see GET_IA64_MCA_DATA above360360+ ;;278361279362 // Call virtual mode handler280280- movl r2=ia64_mca_ucmc_handler;;281281- mov b6=r2;;282282- br.call.sptk.many b0=b6;;283283-.ret0:363363+ alloc r14=ar.pfs,0,0,3,0364364+ ;;365365+ DATA_PA_TO_VA(r2,r7)366366+ ;;367367+ add out0=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_PT_REGS_OFFSET, r2368368+ add out1=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_SWITCH_STACK_OFFSET, r2369369+ add out2=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_SOS_OFFSET, r2370370+ br.call.sptk.many b0=ia64_mca_handler371371+284372 // Revert back to physical mode before going back to SAL285373 PHYSICAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_end, r4)286374ia64_os_mca_virtual_end:287375288288- // restore the original stack frame here289289- GET_IA64_MCA_DATA(r2)290290- ;;291291- add r2 = IA64_MCA_CPU_STACKFRAME_OFFSET, r2292292- ;;293293- movl r4=IA64_PSR_MC294294- ;;295295- rse_return_context(r4,r3,r2) // switch from interrupt context for RSE376376+END(ia64_os_mca_virtual_begin)296377297297- // let us restore all the registers from our PSI structure298298- mov r8=gp299299- ;;300300-begin_os_mca_restore:301301- br ia64_os_mca_proc_state_restore;;378378+ // switch back to previous stack379379+ alloc r14=ar.pfs,0,0,0,0 // remove the MCA handler frame380380+ mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET // use the MCA stack381381+ LOAD_PHYSICAL(p0,r2,1f) // return address382382+ br.sptk ia64_old_stack383383+1:302384303303-ia64_os_mca_done_restore:304304- OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(r2);;305305- // branch back to SALE_CHECK306306- ld8 r3=[r2];;307307- mov b0=r3;; // SAL_CHECK return address385385+ mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET // use the MCA stack386386+ LOAD_PHYSICAL(p0,r2,1f) // return address387387+ br.sptk ia64_state_restore // restore the SAL state388388+1:389389+390390+ mov b0=r12 // SAL_CHECK return address308391309392 // release lock310310- movl r3=ia64_mca_serialize;;311311- DATA_VA_TO_PA(r3);;312312- st8.rel [r3]=r0393393+ LOAD_PHYSICAL(p0,r3,ia64_mca_serialize);;394394+ st4.rel [r3]=r0313395314396 br b0315315- ;;316316-ia64_os_mca_dispatch_end:397397+317398//EndMain//////////////////////////////////////////////////////////////////////318399400400+//StartMain////////////////////////////////////////////////////////////////////319401320320-//++321321-// Name:322322-// ia64_os_mca_proc_state_dump()323402//324324-// Stub Description:403403+// SAL to OS entry point for INIT on all processors. This has been defined for404404+// registration purposes with SAL as a part of ia64_mca_init. Monarch and405405+// slave INIT have identical processing, except for the value of the406406+// sos->monarch flag in r19.325407//326326-// This stub dumps the processor state during MCHK to a data area327327-//328328-//--329408330330-ia64_os_mca_proc_state_dump:331331-// Save bank 1 GRs 16-31 which will be used by c-language code when we switch332332-// to virtual addressing mode.409409+ia64_os_init_dispatch_monarch:410410+ mov r19=1 // Bow, bow, ye lower middle classes!411411+ br.sptk ia64_os_init_dispatch412412+413413+ia64_os_init_dispatch_slave:414414+ mov r19=0 // <igor>yeth, mathter</igor>415415+416416+ia64_os_init_dispatch:417417+418418+ mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET // use the INIT stack419419+ LOAD_PHYSICAL(p0,r2,1f) // return address420420+ br.sptk ia64_state_save // save the state that is not in minstate421421+1:422422+423423+ // switch to per cpu INIT stack424424+ mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET // use the INIT stack425425+ LOAD_PHYSICAL(p0,r2,1f) // return address426426+ br.sptk ia64_new_stack427427+1:428428+429429+ // everything saved, now we can set the kernel registers430430+ mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET // use the INIT stack431431+ LOAD_PHYSICAL(p0,r2,1f) // return address432432+ br.sptk ia64_set_kernel_registers433433+1:434434+435435+ // This must be done in physical mode333436 GET_IA64_MCA_DATA(r2)334437 ;;335335- add r2 = IA64_MCA_CPU_PROC_STATE_DUMP_OFFSET, r2336336- ;;337337-// save ar.NaT338338- mov r5=ar.unat // ar.unat339339-340340-// save banked GRs 16-31 along with NaT bits341341- bsw.1;;342342- st8.spill [r2]=r16,8;;343343- st8.spill [r2]=r17,8;;344344- st8.spill [r2]=r18,8;;345345- st8.spill [r2]=r19,8;;346346- st8.spill [r2]=r20,8;;347347- st8.spill [r2]=r21,8;;348348- st8.spill [r2]=r22,8;;349349- st8.spill [r2]=r23,8;;350350- st8.spill [r2]=r24,8;;351351- st8.spill [r2]=r25,8;;352352- st8.spill [r2]=r26,8;;353353- st8.spill [r2]=r27,8;;354354- st8.spill [r2]=r28,8;;355355- st8.spill [r2]=r29,8;;356356- st8.spill [r2]=r30,8;;357357- st8.spill [r2]=r31,8;;358358-359359- mov r4=ar.unat;;360360- st8 [r2]=r4,8 // save User NaT bits for r16-r31361361- mov ar.unat=r5 // restore original unat362362- bsw.0;;363363-364364-//save BRs365365- add r4=8,r2 // duplicate r2 in r4366366- add r6=2*8,r2 // duplicate r2 in r4367367-368368- mov r3=b0369369- mov r5=b1370370- mov r7=b2;;371371- st8 [r2]=r3,3*8372372- st8 [r4]=r5,3*8373373- st8 [r6]=r7,3*8;;374374-375375- mov r3=b3376376- mov r5=b4377377- mov r7=b5;;378378- st8 [r2]=r3,3*8379379- st8 [r4]=r5,3*8380380- st8 [r6]=r7,3*8;;381381-382382- mov r3=b6383383- mov r5=b7;;384384- st8 [r2]=r3,2*8385385- st8 [r4]=r5,2*8;;386386-387387-cSaveCRs:388388-// save CRs389389- add r4=8,r2 // duplicate r2 in r4390390- add r6=2*8,r2 // duplicate r2 in r4391391-392392- mov r3=cr.dcr393393- mov r5=cr.itm394394- mov r7=cr.iva;;395395-396396- st8 [r2]=r3,8*8397397- st8 [r4]=r5,3*8398398- st8 [r6]=r7,3*8;; // 48 byte rements399399-400400- mov r3=cr.pta;;401401- st8 [r2]=r3,8*8;; // 64 byte rements402402-403403-// if PSR.ic=0, reading interruption registers causes an illegal operation fault404404- mov r3=psr;;405405- tbit.nz.unc p6,p0=r3,PSR_IC;; // PSI Valid Log bit pos. test406406-(p6) st8 [r2]=r0,9*8+160 // increment by 232 byte inc.407407-begin_skip_intr_regs:408408-(p6) br SkipIntrRegs;;409409-410410- add r4=8,r2 // duplicate r2 in r4411411- add r6=2*8,r2 // duplicate r2 in r6412412-413413- mov r3=cr.ipsr414414- mov r5=cr.isr415415- mov r7=r0;;416416- st8 [r2]=r3,3*8417417- st8 [r4]=r5,3*8418418- st8 [r6]=r7,3*8;;419419-420420- mov r3=cr.iip421421- mov r5=cr.ifa422422- mov r7=cr.itir;;423423- st8 [r2]=r3,3*8424424- st8 [r4]=r5,3*8425425- st8 [r6]=r7,3*8;;426426-427427- mov r3=cr.iipa428428- mov r5=cr.ifs429429- mov r7=cr.iim;;430430- st8 [r2]=r3,3*8431431- st8 [r4]=r5,3*8432432- st8 [r6]=r7,3*8;;433433-434434- mov r3=cr25;; // cr.iha435435- st8 [r2]=r3,160;; // 160 byte rement436436-437437-SkipIntrRegs:438438- st8 [r2]=r0,152;; // another 152 byte .439439-440440- add r4=8,r2 // duplicate r2 in r4441441- add r6=2*8,r2 // duplicate r2 in r6442442-443443- mov r3=cr.lid444444-// mov r5=cr.ivr // cr.ivr, don't read it445445- mov r7=cr.tpr;;446446- st8 [r2]=r3,3*8447447- st8 [r4]=r5,3*8448448- st8 [r6]=r7,3*8;;449449-450450- mov r3=r0 // cr.eoi => cr67451451- mov r5=r0 // cr.irr0 => cr68452452- mov r7=r0;; // cr.irr1 => cr69453453- st8 [r2]=r3,3*8454454- st8 [r4]=r5,3*8455455- st8 [r6]=r7,3*8;;456456-457457- mov r3=r0 // cr.irr2 => cr70458458- mov r5=r0 // cr.irr3 => cr71459459- mov r7=cr.itv;;460460- st8 [r2]=r3,3*8461461- st8 [r4]=r5,3*8462462- st8 [r6]=r7,3*8;;463463-464464- mov r3=cr.pmv465465- mov r5=cr.cmcv;;466466- st8 [r2]=r3,7*8467467- st8 [r4]=r5,7*8;;468468-469469- mov r3=r0 // cr.lrr0 => cr80470470- mov r5=r0;; // cr.lrr1 => cr81471471- st8 [r2]=r3,23*8472472- st8 [r4]=r5,23*8;;473473-474474- adds r2=25*8,r2;;475475-476476-cSaveARs:477477-// save ARs478478- add r4=8,r2 // duplicate r2 in r4479479- add r6=2*8,r2 // duplicate r2 in r6480480-481481- mov r3=ar.k0482482- mov r5=ar.k1483483- mov r7=ar.k2;;484484- st8 [r2]=r3,3*8485485- st8 [r4]=r5,3*8486486- st8 [r6]=r7,3*8;;487487-488488- mov r3=ar.k3489489- mov r5=ar.k4490490- mov r7=ar.k5;;491491- st8 [r2]=r3,3*8492492- st8 [r4]=r5,3*8493493- st8 [r6]=r7,3*8;;494494-495495- mov r3=ar.k6496496- mov r5=ar.k7497497- mov r7=r0;; // ar.kr8498498- st8 [r2]=r3,10*8499499- st8 [r4]=r5,10*8500500- st8 [r6]=r7,10*8;; // rement by 72 bytes501501-502502- mov r3=ar.rsc503503- mov ar.rsc=r0 // put RSE in enforced lazy mode504504- mov r5=ar.bsp505505- ;;506506- mov r7=ar.bspstore;;507507- st8 [r2]=r3,3*8508508- st8 [r4]=r5,3*8509509- st8 [r6]=r7,3*8;;510510-511511- mov r3=ar.rnat;;512512- st8 [r2]=r3,8*13 // increment by 13x8 bytes513513-514514- mov r3=ar.ccv;;515515- st8 [r2]=r3,8*4516516-517517- mov r3=ar.unat;;518518- st8 [r2]=r3,8*4519519-520520- mov r3=ar.fpsr;;521521- st8 [r2]=r3,8*4522522-523523- mov r3=ar.itc;;524524- st8 [r2]=r3,160 // 160525525-526526- mov r3=ar.pfs;;527527- st8 [r2]=r3,8528528-529529- mov r3=ar.lc;;530530- st8 [r2]=r3,8531531-532532- mov r3=ar.ec;;533533- st8 [r2]=r3534534- add r2=8*62,r2 //padding535535-536536-// save RRs537537- mov ar.lc=0x08-1538538- movl r4=0x00;;539539-540540-cStRR:541541- dep.z r5=r4,61,3;;542542- mov r3=rr[r5];;543543- st8 [r2]=r3,8544544- add r4=1,r4545545- br.cloop.sptk.few cStRR546546- ;;547547-end_os_mca_dump:548548- br ia64_os_mca_done_dump;;549549-550550-//EndStub//////////////////////////////////////////////////////////////////////551551-552552-553553-//++554554-// Name:555555-// ia64_os_mca_proc_state_restore()556556-//557557-// Stub Description:558558-//559559-// This is a stub to restore the saved processor state during MCHK560560-//561561-//--562562-563563-ia64_os_mca_proc_state_restore:564564-565565-// Restore bank1 GR16-31566566- GET_IA64_MCA_DATA(r2)567567- ;;568568- add r2 = IA64_MCA_CPU_PROC_STATE_DUMP_OFFSET, r2569569-570570-restore_GRs: // restore bank-1 GRs 16-31571571- bsw.1;;572572- add r3=16*8,r2;; // to get to NaT of GR 16-31573573- ld8 r3=[r3];;574574- mov ar.unat=r3;; // first restore NaT575575-576576- ld8.fill r16=[r2],8;;577577- ld8.fill r17=[r2],8;;578578- ld8.fill r18=[r2],8;;579579- ld8.fill r19=[r2],8;;580580- ld8.fill r20=[r2],8;;581581- ld8.fill r21=[r2],8;;582582- ld8.fill r22=[r2],8;;583583- ld8.fill r23=[r2],8;;584584- ld8.fill r24=[r2],8;;585585- ld8.fill r25=[r2],8;;586586- ld8.fill r26=[r2],8;;587587- ld8.fill r27=[r2],8;;588588- ld8.fill r28=[r2],8;;589589- ld8.fill r29=[r2],8;;590590- ld8.fill r30=[r2],8;;591591- ld8.fill r31=[r2],8;;592592-593593- ld8 r3=[r2],8;; // increment to skip NaT594594- bsw.0;;595595-596596-restore_BRs:597597- add r4=8,r2 // duplicate r2 in r4598598- add r6=2*8,r2;; // duplicate r2 in r4599599-600600- ld8 r3=[r2],3*8601601- ld8 r5=[r4],3*8602602- ld8 r7=[r6],3*8;;603603- mov b0=r3604604- mov b1=r5605605- mov b2=r7;;606606-607607- ld8 r3=[r2],3*8608608- ld8 r5=[r4],3*8609609- ld8 r7=[r6],3*8;;610610- mov b3=r3611611- mov b4=r5612612- mov b5=r7;;613613-614614- ld8 r3=[r2],2*8615615- ld8 r5=[r4],2*8;;616616- mov b6=r3617617- mov b7=r5;;618618-619619-restore_CRs:620620- add r4=8,r2 // duplicate r2 in r4621621- add r6=2*8,r2;; // duplicate r2 in r4622622-623623- ld8 r3=[r2],8*8624624- ld8 r5=[r4],3*8625625- ld8 r7=[r6],3*8;; // 48 byte increments626626- mov cr.dcr=r3627627- mov cr.itm=r5628628- mov cr.iva=r7;;629629-630630- ld8 r3=[r2],8*8;; // 64 byte increments631631-// mov cr.pta=r3632632-633633-634634-// if PSR.ic=1, reading interruption registers causes an illegal operation fault635635- mov r3=psr;;636636- tbit.nz.unc p6,p0=r3,PSR_IC;; // PSI Valid Log bit pos. test637637-(p6) st8 [r2]=r0,9*8+160 // increment by 232 byte inc.638638-639639-begin_rskip_intr_regs:640640-(p6) br rSkipIntrRegs;;641641-642642- add r4=8,r2 // duplicate r2 in r4643643- add r6=2*8,r2;; // duplicate r2 in r4644644-645645- ld8 r3=[r2],3*8646646- ld8 r5=[r4],3*8647647- ld8 r7=[r6],3*8;;648648- mov cr.ipsr=r3649649-// mov cr.isr=r5 // cr.isr is read only650650-651651- ld8 r3=[r2],3*8652652- ld8 r5=[r4],3*8653653- ld8 r7=[r6],3*8;;654654- mov cr.iip=r3655655- mov cr.ifa=r5656656- mov cr.itir=r7;;657657-658658- ld8 r3=[r2],3*8659659- ld8 r5=[r4],3*8660660- ld8 r7=[r6],3*8;;661661- mov cr.iipa=r3662662- mov cr.ifs=r5663663- mov cr.iim=r7664664-665665- ld8 r3=[r2],160;; // 160 byte increment666666- mov cr.iha=r3667667-668668-rSkipIntrRegs:669669- ld8 r3=[r2],152;; // another 152 byte inc.670670-671671- add r4=8,r2 // duplicate r2 in r4672672- add r6=2*8,r2;; // duplicate r2 in r6673673-674674- ld8 r3=[r2],8*3675675- ld8 r5=[r4],8*3676676- ld8 r7=[r6],8*3;;677677- mov cr.lid=r3678678-// mov cr.ivr=r5 // cr.ivr is read only679679- mov cr.tpr=r7;;680680-681681- ld8 r3=[r2],8*3682682- ld8 r5=[r4],8*3683683- ld8 r7=[r6],8*3;;684684-// mov cr.eoi=r3685685-// mov cr.irr0=r5 // cr.irr0 is read only686686-// mov cr.irr1=r7;; // cr.irr1 is read only687687-688688- ld8 r3=[r2],8*3689689- ld8 r5=[r4],8*3690690- ld8 r7=[r6],8*3;;691691-// mov cr.irr2=r3 // cr.irr2 is read only692692-// mov cr.irr3=r5 // cr.irr3 is read only693693- mov cr.itv=r7;;694694-695695- ld8 r3=[r2],8*7696696- ld8 r5=[r4],8*7;;697697- mov cr.pmv=r3698698- mov cr.cmcv=r5;;699699-700700- ld8 r3=[r2],8*23701701- ld8 r5=[r4],8*23;;702702- adds r2=8*23,r2703703- adds r4=8*23,r4;;704704-// mov cr.lrr0=r3705705-// mov cr.lrr1=r5706706-707707- adds r2=8*2,r2;;708708-709709-restore_ARs:710710- add r4=8,r2 // duplicate r2 in r4711711- add r6=2*8,r2;; // duplicate r2 in r4712712-713713- ld8 r3=[r2],3*8714714- ld8 r5=[r4],3*8715715- ld8 r7=[r6],3*8;;716716- mov ar.k0=r3717717- mov ar.k1=r5718718- mov ar.k2=r7;;719719-720720- ld8 r3=[r2],3*8721721- ld8 r5=[r4],3*8722722- ld8 r7=[r6],3*8;;723723- mov ar.k3=r3724724- mov ar.k4=r5725725- mov ar.k5=r7;;726726-727727- ld8 r3=[r2],10*8728728- ld8 r5=[r4],10*8729729- ld8 r7=[r6],10*8;;730730- mov ar.k6=r3731731- mov ar.k7=r5732732- ;;733733-734734- ld8 r3=[r2],3*8735735- ld8 r5=[r4],3*8736736- ld8 r7=[r6],3*8;;737737-// mov ar.rsc=r3738738-// mov ar.bsp=r5 // ar.bsp is read only739739- mov ar.rsc=r0 // make sure that RSE is in enforced lazy mode740740- ;;741741- mov ar.bspstore=r7;;742742-743743- ld8 r9=[r2],8*13;;744744- mov ar.rnat=r9745745-746746- mov ar.rsc=r3747747- ld8 r3=[r2],8*4;;748748- mov ar.ccv=r3749749-750750- ld8 r3=[r2],8*4;;751751- mov ar.unat=r3752752-753753- ld8 r3=[r2],8*4;;754754- mov ar.fpsr=r3755755-756756- ld8 r3=[r2],160;; // 160757757-// mov ar.itc=r3758758-759759- ld8 r3=[r2],8;;760760- mov ar.pfs=r3761761-762762- ld8 r3=[r2],8;;763763- mov ar.lc=r3764764-765765- ld8 r3=[r2];;766766- mov ar.ec=r3767767- add r2=8*62,r2;; // padding768768-769769-restore_RRs:770770- mov r5=ar.lc771771- mov ar.lc=0x08-1772772- movl r4=0x00;;773773-cStRRr:774774- dep.z r7=r4,61,3775775- ld8 r3=[r2],8;;776776- mov rr[r7]=r3 // what are its access previledges?777777- add r4=1,r4778778- br.cloop.sptk.few cStRRr779779- ;;780780- mov ar.lc=r5781781- ;;782782-end_os_mca_restore:783783- br ia64_os_mca_done_restore;;784784-785785-//EndStub//////////////////////////////////////////////////////////////////////786786-787787-788788-// ok, the issue here is that we need to save state information so789789-// it can be useable by the kernel debugger and show regs routines.790790-// In order to do this, our best bet is save the current state (plus791791-// the state information obtain from the MIN_STATE_AREA) into a pt_regs792792-// format. This way we can pass it on in a useable format.793793-//794794-795795-//796796-// SAL to OS entry point for INIT on the monarch processor797797-// This has been defined for registration purposes with SAL798798-// as a part of ia64_mca_init.799799-//800800-// When we get here, the following registers have been801801-// set by the SAL for our use802802-//803803-// 1. GR1 = OS INIT GP804804-// 2. GR8 = PAL_PROC physical address805805-// 3. GR9 = SAL_PROC physical address806806-// 4. GR10 = SAL GP (physical)807807-// 5. GR11 = Init Reason808808-// 0 = Received INIT for event other than crash dump switch809809-// 1 = Received wakeup at the end of an OS_MCA corrected machine check810810-// 2 = Received INIT dude to CrashDump switch assertion811811-//812812-// 6. GR12 = Return address to location within SAL_INIT procedure813813-814814-815815-GLOBAL_ENTRY(ia64_monarch_init_handler)438438+ mov r7=r2439439+440440+ // Enter virtual mode from physical mode441441+ VIRTUAL_MODE_ENTER(r2, r3, ia64_os_init_virtual_begin, r4)442442+443443+ // This code returns to SAL via SOS r2, in general SAL has no unwind444444+ // data. To get a clean termination when backtracing the C MCA/INIT445445+ // handler, set a dummy return address of 0 in this routine. That446446+ // requires that ia64_os_init_virtual_begin be a global function.447447+ENTRY(ia64_os_init_virtual_begin)816448 .prologue817817- // stash the information the SAL passed to os818818- SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2)819819- ;;820820- SAVE_MIN_WITH_COVER821821- ;;822822- mov r8=cr.ifa823823- mov r9=cr.isr824824- adds r3=8,r2 // set up second base pointer825825- ;;826826- SAVE_REST827827-828828-// ok, enough should be saved at this point to be dangerous, and supply829829-// information for a dump830830-// We need to switch to Virtual mode before hitting the C functions.831831-832832- movl r2=IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN833833- mov r3=psr // get the current psr, minimum enabled at this point834834- ;;835835- or r2=r2,r3836836- ;;837837- movl r3=IVirtual_Switch838838- ;;839839- mov cr.iip=r3 // short return to set the appropriate bits840840- mov cr.ipsr=r2 // need to do an rfi to set appropriate bits841841- ;;842842- rfi843843- ;;844844-IVirtual_Switch:845845- //846846- // We should now be running virtual847847- //848848- // Let's call the C handler to get the rest of the state info849849- //850850- alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!)851851- ;;852852- adds out0=16,sp // out0 = pointer to pt_regs853853- ;;854854- DO_SAVE_SWITCH_STACK449449+ .save rp,r0855450 .body856856- adds out1=16,sp // out0 = pointer to switch_stack857451858858- br.call.sptk.many rp=ia64_init_handler859859-.ret1:452452+ mov ar.rsc=3 // set eager mode for C handler453453+ mov r2=r7 // see GET_IA64_MCA_DATA above454454+ ;;860455861861-return_from_init:862862- br.sptk return_from_init863863-END(ia64_monarch_init_handler)456456+ // Call virtual mode handler457457+ alloc r14=ar.pfs,0,0,3,0458458+ ;;459459+ DATA_PA_TO_VA(r2,r7)460460+ ;;461461+ add out0=IA64_MCA_CPU_INIT_STACK_OFFSET+MCA_PT_REGS_OFFSET, r2462462+ add out1=IA64_MCA_CPU_INIT_STACK_OFFSET+MCA_SWITCH_STACK_OFFSET, r2463463+ add out2=IA64_MCA_CPU_INIT_STACK_OFFSET+MCA_SOS_OFFSET, r2464464+ br.call.sptk.many b0=ia64_init_handler864465466466+ // Revert back to physical mode before going back to SAL467467+ PHYSICAL_MODE_ENTER(r2, r3, ia64_os_init_virtual_end, r4)468468+ia64_os_init_virtual_end:469469+470470+END(ia64_os_init_virtual_begin)471471+472472+ mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET // use the INIT stack473473+ LOAD_PHYSICAL(p0,r2,1f) // return address474474+ br.sptk ia64_state_restore // restore the SAL state475475+1:476476+477477+ // switch back to previous stack478478+ alloc r14=ar.pfs,0,0,0,0 // remove the INIT handler frame479479+ mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET // use the INIT stack480480+ LOAD_PHYSICAL(p0,r2,1f) // return address481481+ br.sptk ia64_old_stack482482+1:483483+484484+ mov b0=r12 // SAL_CHECK return address485485+ br b0486486+487487+//EndMain//////////////////////////////////////////////////////////////////////488488+489489+// common defines for the stubs490490+#define ms r4491491+#define regs r5492492+#define temp1 r2 /* careful, it overlaps with input registers */493493+#define temp2 r3 /* careful, it overlaps with input registers */494494+#define temp3 r7495495+#define temp4 r14496496+497497+498498+//++499499+// Name:500500+// ia64_state_save()865501//866866-// SAL to OS entry point for INIT on the slave processor867867-// This has been defined for registration purposes with SAL868868-// as a part of ia64_mca_init.502502+// Stub Description:869503//504504+// Save the state that is not in minstate. This is sensitive to the layout of505505+// struct ia64_sal_os_state in mca.h.506506+//507507+// r2 contains the return address, r3 contains either508508+// IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.509509+//510510+// The OS to SAL section of struct ia64_sal_os_state is set to a default511511+// value of cold boot (MCA) or warm boot (INIT) and return to the same512512+// context. ia64_sal_os_state is also used to hold some registers that513513+// need to be saved and restored across the stack switches.514514+//515515+// Most input registers to this stub come from PAL/SAL516516+// r1 os gp, physical517517+// r8 pal_proc entry point518518+// r9 sal_proc entry point519519+// r10 sal gp520520+// r11 MCA - rendevzous state, INIT - reason code521521+// r12 sal return address522522+// r17 pal min_state523523+// r18 processor state parameter524524+// r19 monarch flag, set by the caller of this routine525525+//526526+// In addition to the SAL to OS state, this routine saves all the527527+// registers that appear in struct pt_regs and struct switch_stack,528528+// excluding those that are already in the PAL minstate area. This529529+// results in a partial pt_regs and switch_stack, the C code copies the530530+// remaining registers from PAL minstate to pt_regs and switch_stack. The531531+// resulting structures contain all the state of the original process when532532+// MCA/INIT occurred.533533+//534534+//--870535871871-GLOBAL_ENTRY(ia64_slave_init_handler)872872-1: br.sptk 1b873873-END(ia64_slave_init_handler)536536+ia64_state_save:537537+ add regs=MCA_SOS_OFFSET, r3538538+ add ms=MCA_SOS_OFFSET+8, r3539539+ mov b0=r2 // save return address540540+ cmp.eq p1,p2=IA64_MCA_CPU_MCA_STACK_OFFSET, r3541541+ ;;542542+ GET_IA64_MCA_DATA(temp2)543543+ ;;544544+ add temp1=temp2, regs // struct ia64_sal_os_state on MCA or INIT stack545545+ add temp2=temp2, ms // struct ia64_sal_os_state+8 on MCA or INIT stack546546+ ;;547547+ mov regs=temp1 // save the start of sos548548+ st8 [temp1]=r1,16 // os_gp549549+ st8 [temp2]=r8,16 // pal_proc550550+ ;;551551+ st8 [temp1]=r9,16 // sal_proc552552+ st8 [temp2]=r11,16 // rv_rc553553+ mov r11=cr.iipa554554+ ;;555555+ st8 [temp1]=r18,16 // proc_state_param556556+ st8 [temp2]=r19,16 // monarch557557+ mov r6=IA64_KR(CURRENT)558558+ ;;559559+ st8 [temp1]=r12,16 // sal_ra560560+ st8 [temp2]=r10,16 // sal_gp561561+ mov r12=cr.isr562562+ ;;563563+ st8 [temp1]=r17,16 // pal_min_state564564+ st8 [temp2]=r6,16 // prev_IA64_KR_CURRENT565565+ mov r6=cr.ifa566566+ ;;567567+ st8 [temp1]=r0,16 // prev_task, starts off as NULL568568+ st8 [temp2]=r12,16 // cr.isr569569+ mov r12=cr.itir570570+ ;;571571+ st8 [temp1]=r6,16 // cr.ifa572572+ st8 [temp2]=r12,16 // cr.itir573573+ mov r12=cr.iim574574+ ;;575575+ st8 [temp1]=r11,16 // cr.iipa576576+ st8 [temp2]=r12,16 // cr.iim577577+ mov r6=cr.iha578578+(p1) mov r12=IA64_MCA_COLD_BOOT579579+(p2) mov r12=IA64_INIT_WARM_BOOT580580+ ;;581581+ st8 [temp1]=r6,16 // cr.iha582582+ st8 [temp2]=r12 // os_status, default is cold boot583583+ mov r6=IA64_MCA_SAME_CONTEXT584584+ ;;585585+ st8 [temp1]=r6 // context, default is same context586586+587587+ // Save the pt_regs data that is not in minstate. The previous code588588+ // left regs at sos.589589+ add regs=MCA_PT_REGS_OFFSET-MCA_SOS_OFFSET, regs590590+ ;;591591+ add temp1=PT(B6), regs592592+ mov temp3=b6593593+ mov temp4=b7594594+ add temp2=PT(B7), regs595595+ ;;596596+ st8 [temp1]=temp3,PT(AR_CSD)-PT(B6) // save b6597597+ st8 [temp2]=temp4,PT(AR_SSD)-PT(B7) // save b7598598+ mov temp3=ar.csd599599+ mov temp4=ar.ssd600600+ cover // must be last in group601601+ ;;602602+ st8 [temp1]=temp3,PT(AR_UNAT)-PT(AR_CSD) // save ar.csd603603+ st8 [temp2]=temp4,PT(AR_PFS)-PT(AR_SSD) // save ar.ssd604604+ mov temp3=ar.unat605605+ mov temp4=ar.pfs606606+ ;;607607+ st8 [temp1]=temp3,PT(AR_RNAT)-PT(AR_UNAT) // save ar.unat608608+ st8 [temp2]=temp4,PT(AR_BSPSTORE)-PT(AR_PFS) // save ar.pfs609609+ mov temp3=ar.rnat610610+ mov temp4=ar.bspstore611611+ ;;612612+ st8 [temp1]=temp3,PT(LOADRS)-PT(AR_RNAT) // save ar.rnat613613+ st8 [temp2]=temp4,PT(AR_FPSR)-PT(AR_BSPSTORE) // save ar.bspstore614614+ mov temp3=ar.bsp615615+ ;;616616+ sub temp3=temp3, temp4 // ar.bsp - ar.bspstore617617+ mov temp4=ar.fpsr618618+ ;;619619+ shl temp3=temp3,16 // compute ar.rsc to be used for "loadrs"620620+ ;;621621+ st8 [temp1]=temp3,PT(AR_CCV)-PT(LOADRS) // save loadrs622622+ st8 [temp2]=temp4,PT(F6)-PT(AR_FPSR) // save ar.fpsr623623+ mov temp3=ar.ccv624624+ ;;625625+ st8 [temp1]=temp3,PT(F7)-PT(AR_CCV) // save ar.ccv626626+ stf.spill [temp2]=f6,PT(F8)-PT(F6)627627+ ;;628628+ stf.spill [temp1]=f7,PT(F9)-PT(F7)629629+ stf.spill [temp2]=f8,PT(F10)-PT(F8)630630+ ;;631631+ stf.spill [temp1]=f9,PT(F11)-PT(F9)632632+ stf.spill [temp2]=f10633633+ ;;634634+ stf.spill [temp1]=f11635635+636636+ // Save the switch_stack data that is not in minstate nor pt_regs. The637637+ // previous code left regs at pt_regs.638638+ add regs=MCA_SWITCH_STACK_OFFSET-MCA_PT_REGS_OFFSET, regs639639+ ;;640640+ add temp1=SW(F2), regs641641+ add temp2=SW(F3), regs642642+ ;;643643+ stf.spill [temp1]=f2,32644644+ stf.spill [temp2]=f3,32645645+ ;;646646+ stf.spill [temp1]=f4,32647647+ stf.spill [temp2]=f5,32648648+ ;;649649+ stf.spill [temp1]=f12,32650650+ stf.spill [temp2]=f13,32651651+ ;;652652+ stf.spill [temp1]=f14,32653653+ stf.spill [temp2]=f15,32654654+ ;;655655+ stf.spill [temp1]=f16,32656656+ stf.spill [temp2]=f17,32657657+ ;;658658+ stf.spill [temp1]=f18,32659659+ stf.spill [temp2]=f19,32660660+ ;;661661+ stf.spill [temp1]=f20,32662662+ stf.spill [temp2]=f21,32663663+ ;;664664+ stf.spill [temp1]=f22,32665665+ stf.spill [temp2]=f23,32666666+ ;;667667+ stf.spill [temp1]=f24,32668668+ stf.spill [temp2]=f25,32669669+ ;;670670+ stf.spill [temp1]=f26,32671671+ stf.spill [temp2]=f27,32672672+ ;;673673+ stf.spill [temp1]=f28,32674674+ stf.spill [temp2]=f29,32675675+ ;;676676+ stf.spill [temp1]=f30,SW(B2)-SW(F30)677677+ stf.spill [temp2]=f31,SW(B3)-SW(F31)678678+ mov temp3=b2679679+ mov temp4=b3680680+ ;;681681+ st8 [temp1]=temp3,16 // save b2682682+ st8 [temp2]=temp4,16 // save b3683683+ mov temp3=b4684684+ mov temp4=b5685685+ ;;686686+ st8 [temp1]=temp3,SW(AR_LC)-SW(B4) // save b4687687+ st8 [temp2]=temp4 // save b5688688+ mov temp3=ar.lc689689+ ;;690690+ st8 [temp1]=temp3 // save ar.lc691691+692692+ // FIXME: Some proms are incorrectly accessing the minstate area as693693+ // cached data. The C code uses region 6, uncached virtual. Ensure694694+ // that there is no cache data lying around for the first 1K of the695695+ // minstate area.696696+ // Remove this code in September 2006, that gives platforms a year to697697+ // fix their proms and get their customers updated.698698+699699+ add r1=32*1,r17700700+ add r2=32*2,r17701701+ add r3=32*3,r17702702+ add r4=32*4,r17703703+ add r5=32*5,r17704704+ add r6=32*6,r17705705+ add r7=32*7,r17706706+ ;;707707+ fc r17708708+ fc r1709709+ fc r2710710+ fc r3711711+ fc r4712712+ fc r5713713+ fc r6714714+ fc r7715715+ add r17=32*8,r17716716+ add r1=32*8,r1717717+ add r2=32*8,r2718718+ add r3=32*8,r3719719+ add r4=32*8,r4720720+ add r5=32*8,r5721721+ add r6=32*8,r6722722+ add r7=32*8,r7723723+ ;;724724+ fc r17725725+ fc r1726726+ fc r2727727+ fc r3728728+ fc r4729729+ fc r5730730+ fc r6731731+ fc r7732732+ add r17=32*8,r17733733+ add r1=32*8,r1734734+ add r2=32*8,r2735735+ add r3=32*8,r3736736+ add r4=32*8,r4737737+ add r5=32*8,r5738738+ add r6=32*8,r6739739+ add r7=32*8,r7740740+ ;;741741+ fc r17742742+ fc r1743743+ fc r2744744+ fc r3745745+ fc r4746746+ fc r5747747+ fc r6748748+ fc r7749749+ add r17=32*8,r17750750+ add r1=32*8,r1751751+ add r2=32*8,r2752752+ add r3=32*8,r3753753+ add r4=32*8,r4754754+ add r5=32*8,r5755755+ add r6=32*8,r6756756+ add r7=32*8,r7757757+ ;;758758+ fc r17759759+ fc r1760760+ fc r2761761+ fc r3762762+ fc r4763763+ fc r5764764+ fc r6765765+ fc r7766766+767767+ br.sptk b0768768+769769+//EndStub//////////////////////////////////////////////////////////////////////770770+771771+772772+//++773773+// Name:774774+// ia64_state_restore()775775+//776776+// Stub Description:777777+//778778+// Restore the SAL/OS state. This is sensitive to the layout of struct779779+// ia64_sal_os_state in mca.h.780780+//781781+// r2 contains the return address, r3 contains either782782+// IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.783783+//784784+// In addition to the SAL to OS state, this routine restores all the785785+// registers that appear in struct pt_regs and struct switch_stack,786786+// excluding those in the PAL minstate area.787787+//788788+//--789789+790790+ia64_state_restore:791791+ // Restore the switch_stack data that is not in minstate nor pt_regs.792792+ add regs=MCA_SWITCH_STACK_OFFSET, r3793793+ mov b0=r2 // save return address794794+ ;;795795+ GET_IA64_MCA_DATA(temp2)796796+ ;;797797+ add regs=temp2, regs798798+ ;;799799+ add temp1=SW(F2), regs800800+ add temp2=SW(F3), regs801801+ ;;802802+ ldf.fill f2=[temp1],32803803+ ldf.fill f3=[temp2],32804804+ ;;805805+ ldf.fill f4=[temp1],32806806+ ldf.fill f5=[temp2],32807807+ ;;808808+ ldf.fill f12=[temp1],32809809+ ldf.fill f13=[temp2],32810810+ ;;811811+ ldf.fill f14=[temp1],32812812+ ldf.fill f15=[temp2],32813813+ ;;814814+ ldf.fill f16=[temp1],32815815+ ldf.fill f17=[temp2],32816816+ ;;817817+ ldf.fill f18=[temp1],32818818+ ldf.fill f19=[temp2],32819819+ ;;820820+ ldf.fill f20=[temp1],32821821+ ldf.fill f21=[temp2],32822822+ ;;823823+ ldf.fill f22=[temp1],32824824+ ldf.fill f23=[temp2],32825825+ ;;826826+ ldf.fill f24=[temp1],32827827+ ldf.fill f25=[temp2],32828828+ ;;829829+ ldf.fill f26=[temp1],32830830+ ldf.fill f27=[temp2],32831831+ ;;832832+ ldf.fill f28=[temp1],32833833+ ldf.fill f29=[temp2],32834834+ ;;835835+ ldf.fill f30=[temp1],SW(B2)-SW(F30)836836+ ldf.fill f31=[temp2],SW(B3)-SW(F31)837837+ ;;838838+ ld8 temp3=[temp1],16 // restore b2839839+ ld8 temp4=[temp2],16 // restore b3840840+ ;;841841+ mov b2=temp3842842+ mov b3=temp4843843+ ld8 temp3=[temp1],SW(AR_LC)-SW(B4) // restore b4844844+ ld8 temp4=[temp2] // restore b5845845+ ;;846846+ mov b4=temp3847847+ mov b5=temp4848848+ ld8 temp3=[temp1] // restore ar.lc849849+ ;;850850+ mov ar.lc=temp3851851+852852+ // Restore the pt_regs data that is not in minstate. The previous code853853+ // left regs at switch_stack.854854+ add regs=MCA_PT_REGS_OFFSET-MCA_SWITCH_STACK_OFFSET, regs855855+ ;;856856+ add temp1=PT(B6), regs857857+ add temp2=PT(B7), regs858858+ ;;859859+ ld8 temp3=[temp1],PT(AR_CSD)-PT(B6) // restore b6860860+ ld8 temp4=[temp2],PT(AR_SSD)-PT(B7) // restore b7861861+ ;;862862+ mov b6=temp3863863+ mov b7=temp4864864+ ld8 temp3=[temp1],PT(AR_UNAT)-PT(AR_CSD) // restore ar.csd865865+ ld8 temp4=[temp2],PT(AR_PFS)-PT(AR_SSD) // restore ar.ssd866866+ ;;867867+ mov ar.csd=temp3868868+ mov ar.ssd=temp4869869+ ld8 temp3=[temp1] // restore ar.unat870870+ add temp1=PT(AR_CCV)-PT(AR_UNAT), temp1871871+ ld8 temp4=[temp2],PT(AR_FPSR)-PT(AR_PFS) // restore ar.pfs872872+ ;;873873+ mov ar.unat=temp3874874+ mov ar.pfs=temp4875875+ // ar.rnat, ar.bspstore, loadrs are restore in ia64_old_stack.876876+ ld8 temp3=[temp1],PT(F6)-PT(AR_CCV) // restore ar.ccv877877+ ld8 temp4=[temp2],PT(F7)-PT(AR_FPSR) // restore ar.fpsr878878+ ;;879879+ mov ar.ccv=temp3880880+ mov ar.fpsr=temp4881881+ ldf.fill f6=[temp1],PT(F8)-PT(F6)882882+ ldf.fill f7=[temp2],PT(F9)-PT(F7)883883+ ;;884884+ ldf.fill f8=[temp1],PT(F10)-PT(F8)885885+ ldf.fill f9=[temp2],PT(F11)-PT(F9)886886+ ;;887887+ ldf.fill f10=[temp1]888888+ ldf.fill f11=[temp2]889889+890890+ // Restore the SAL to OS state. The previous code left regs at pt_regs.891891+ add regs=MCA_SOS_OFFSET-MCA_PT_REGS_OFFSET, regs892892+ ;;893893+ add temp1=IA64_SAL_OS_STATE_COMMON_OFFSET, regs894894+ add temp2=IA64_SAL_OS_STATE_COMMON_OFFSET+8, regs895895+ ;;896896+ ld8 r12=[temp1],16 // sal_ra897897+ ld8 r9=[temp2],16 // sal_gp898898+ ;;899899+ ld8 r22=[temp1],24 // pal_min_state, virtual. skip prev_task900900+ ld8 r21=[temp2],16 // prev_IA64_KR_CURRENT901901+ ;;902902+ ld8 temp3=[temp1],16 // cr.isr903903+ ld8 temp4=[temp2],16 // cr.ifa904904+ ;;905905+ mov cr.isr=temp3906906+ mov cr.ifa=temp4907907+ ld8 temp3=[temp1],16 // cr.itir908908+ ld8 temp4=[temp2],16 // cr.iipa909909+ ;;910910+ mov cr.itir=temp3911911+ mov cr.iipa=temp4912912+ ld8 temp3=[temp1],16 // cr.iim913913+ ld8 temp4=[temp2],16 // cr.iha914914+ ;;915915+ mov cr.iim=temp3916916+ mov cr.iha=temp4917917+ dep r22=0,r22,62,2 // pal_min_state, physical, uncached918918+ mov IA64_KR(CURRENT)=r21919919+ ld8 r8=[temp1] // os_status920920+ ld8 r10=[temp2] // context921921+922922+ br.sptk b0923923+924924+//EndStub//////////////////////////////////////////////////////////////////////925925+926926+927927+//++928928+// Name:929929+// ia64_new_stack()930930+//931931+// Stub Description:932932+//933933+// Switch to the MCA/INIT stack.934934+//935935+// r2 contains the return address, r3 contains either936936+// IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.937937+//938938+// On entry RBS is still on the original stack, this routine switches RBS939939+// to use the MCA/INIT stack.940940+//941941+// On entry, sos->pal_min_state is physical, on exit it is virtual.942942+//943943+//--944944+945945+ia64_new_stack:946946+ add regs=MCA_PT_REGS_OFFSET, r3947947+ add temp2=MCA_SOS_OFFSET+IA64_SAL_OS_STATE_PAL_MIN_STATE_OFFSET, r3948948+ mov b0=r2 // save return address949949+ GET_IA64_MCA_DATA(temp1)950950+ invala951951+ ;;952952+ add temp2=temp2, temp1 // struct ia64_sal_os_state.pal_min_state on MCA or INIT stack953953+ add regs=regs, temp1 // struct pt_regs on MCA or INIT stack954954+ ;;955955+ // Address of minstate area provided by PAL is physical, uncacheable.956956+ // Convert to Linux virtual address in region 6 for C code.957957+ ld8 ms=[temp2] // pal_min_state, physical958958+ ;;959959+ dep temp1=-1,ms,62,2 // set region 6960960+ mov temp3=IA64_RBS_OFFSET-MCA_PT_REGS_OFFSET961961+ ;;962962+ st8 [temp2]=temp1 // pal_min_state, virtual963963+964964+ add temp4=temp3, regs // start of bspstore on new stack965965+ ;;966966+ mov ar.bspstore=temp4 // switch RBS to MCA/INIT stack967967+ ;;968968+ flushrs // must be first in group969969+ br.sptk b0970970+971971+//EndStub//////////////////////////////////////////////////////////////////////972972+973973+974974+//++975975+// Name:976976+// ia64_old_stack()977977+//978978+// Stub Description:979979+//980980+// Switch to the old stack.981981+//982982+// r2 contains the return address, r3 contains either983983+// IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.984984+//985985+// On entry, pal_min_state is virtual, on exit it is physical.986986+//987987+// On entry RBS is on the MCA/INIT stack, this routine switches RBS988988+// back to the previous stack.989989+//990990+// The psr is set to all zeroes. SAL return requires either all zeroes or991991+// just psr.mc set. Leaving psr.mc off allows INIT to be issued if this992992+// code does not perform correctly.993993+//994994+// The dirty registers at the time of the event were flushed to the995995+// MCA/INIT stack in ia64_pt_regs_save(). Restore the dirty registers996996+// before reverting to the previous bspstore.997997+//--998998+999999+ia64_old_stack:10001000+ add regs=MCA_PT_REGS_OFFSET, r310011001+ mov b0=r2 // save return address10021002+ GET_IA64_MCA_DATA(temp2)10031003+ LOAD_PHYSICAL(p0,temp1,1f)10041004+ ;;10051005+ mov cr.ipsr=r010061006+ mov cr.ifs=r010071007+ mov cr.iip=temp110081008+ ;;10091009+ invala10101010+ rfi10111011+1:10121012+10131013+ add regs=regs, temp2 // struct pt_regs on MCA or INIT stack10141014+ ;;10151015+ add temp1=PT(LOADRS), regs10161016+ ;;10171017+ ld8 temp2=[temp1],PT(AR_BSPSTORE)-PT(LOADRS) // restore loadrs10181018+ ;;10191019+ ld8 temp3=[temp1],PT(AR_RNAT)-PT(AR_BSPSTORE) // restore ar.bspstore10201020+ mov ar.rsc=temp210211021+ ;;10221022+ loadrs10231023+ ld8 temp4=[temp1] // restore ar.rnat10241024+ ;;10251025+ mov ar.bspstore=temp3 // back to old stack10261026+ ;;10271027+ mov ar.rnat=temp410281028+ ;;10291029+10301030+ br.sptk b010311031+10321032+//EndStub//////////////////////////////////////////////////////////////////////10331033+10341034+10351035+//++10361036+// Name:10371037+// ia64_set_kernel_registers()10381038+//10391039+// Stub Description:10401040+//10411041+// Set the registers that are required by the C code in order to run on an10421042+// MCA/INIT stack.10431043+//10441044+// r2 contains the return address, r3 contains either10451045+// IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.10461046+//10471047+//--10481048+10491049+ia64_set_kernel_registers:10501050+ add temp3=MCA_SP_OFFSET, r310511051+ add temp4=MCA_SOS_OFFSET+IA64_SAL_OS_STATE_OS_GP_OFFSET, r310521052+ mov b0=r2 // save return address10531053+ GET_IA64_MCA_DATA(temp1)10541054+ ;;10551055+ add temp4=temp4, temp1 // &struct ia64_sal_os_state.os_gp10561056+ add r12=temp1, temp3 // kernel stack pointer on MCA/INIT stack10571057+ add r13=temp1, r3 // set current to start of MCA/INIT stack10581058+ ;;10591059+ ld8 r1=[temp4] // OS GP from SAL OS state10601060+ ;;10611061+ DATA_PA_TO_VA(r1,temp1)10621062+ DATA_PA_TO_VA(r12,temp2)10631063+ DATA_PA_TO_VA(r13,temp3)10641064+ ;;10651065+ mov IA64_KR(CURRENT)=r1310661066+10671067+ // FIXME: do I need to wire IA64_KR_CURRENT_STACK and IA64_TR_CURRENT_STACK?10681068+10691069+ br.sptk b010701070+10711071+//EndStub//////////////////////////////////////////////////////////////////////10721072+10731073+#undef ms10741074+#undef regs10751075+#undef temp110761076+#undef temp210771077+#undef temp310781078+#undef temp410791079+10801080+10811081+// Support function for mca.c, it is here to avoid using inline asm. Given the10821082+// address of an rnat slot, if that address is below the current ar.bspstore10831083+// then return the contents of that slot, otherwise return the contents of10841084+// ar.rnat.10851085+GLOBAL_ENTRY(ia64_get_rnat)10861086+ alloc r14=ar.pfs,1,0,0,010871087+ mov ar.rsc=010881088+ ;;10891089+ mov r14=ar.bspstore10901090+ ;;10911091+ cmp.lt p6,p7=in0,r1410921092+ ;;10931093+(p6) ld8 r8=[in0]10941094+(p7) mov r8=ar.rnat10951095+ mov ar.rsc=310961096+ br.ret.sptk.many rp10971097+END(ia64_get_rnat)
+17-20
arch/ia64/kernel/mca_drv.c
···44 *55 * Copyright (C) 2004 FUJITSU LIMITED66 * Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com)77+ * Copyright (C) 2005 Silicon Graphics, Inc88+ * Copyright (C) 2005 Keith Owens <kaos@sgi.com>79 */810#include <linux/config.h>911#include <linux/types.h>···39374038/* max size of SAL error record (default) */4139static int sal_rec_max = 10000;4242-4343-/* from mca.c */4444-static ia64_mca_sal_to_os_state_t *sal_to_os_handoff_state;4545-static ia64_mca_os_to_sal_state_t *os_to_sal_handoff_state;46404741/* from mca_drv_asm.S */4842extern void *mca_handler_bhhook(void);···314316 */315317316318static mca_type_t317317-is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci)319319+is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci,320320+ struct ia64_sal_os_state *sos)318321{319322 pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);320323···326327 * Therefore it is local MCA when rendezvous has not been requested.327328 * Failed to rendezvous, the system must be down.328329 */329329- switch (sal_to_os_handoff_state->imsto_rendez_state) {330330+ switch (sos->rv_rc) {330331 case -1: /* SAL rendezvous unsuccessful */331332 return MCA_IS_GLOBAL;332333 case 0: /* SAL rendezvous not required */···387388 */388389389390static int390390-recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci)391391+recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci,392392+ struct ia64_sal_os_state *sos)391393{392394 sal_log_mod_error_info_t *smei;393395 pal_min_state_area_t *pmsa;···426426 * setup for resume to bottom half of MCA,427427 * "mca_handler_bhhook"428428 */429429- pmsa = (pal_min_state_area_t *)(sal_to_os_handoff_state->pal_min_state | (6ul<<61));429429+ pmsa = sos->pal_min_state;430430 /* pass to bhhook as 1st argument (gr8) */431431 pmsa->pmsa_gr[8-1] = smei->target_identifier;432432 /* set interrupted return address (but no use) */···459459 */460460461461static int462462-recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci)462462+recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci,463463+ struct ia64_sal_os_state *sos)463464{464465 int status = 0;465466 pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);···470469 case 1: /* partial read */471470 case 3: /* full line(cpu) read */472471 case 9: /* I/O space read */473473- status = recover_from_read_error(slidx, peidx, pbci);472472+ status = recover_from_read_error(slidx, peidx, pbci, sos);474473 break;475474 case 0: /* unknown */476475 case 2: /* partial write */···509508 */510509511510static int512512-recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci)511511+recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci,512512+ struct ia64_sal_os_state *sos)513513{514514 pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);515515···547545 * This means "there are some platform errors".548546 */549547 if (platform) 550550- return recover_from_platform_error(slidx, peidx, pbci);548548+ return recover_from_platform_error(slidx, peidx, pbci, sos);551549 /* 552550 * On account of strange SAL error record, we cannot recover. 553551 */···564562565563static int566564mca_try_to_recover(void *rec, 567567- ia64_mca_sal_to_os_state_t *sal_to_os_state,568568- ia64_mca_os_to_sal_state_t *os_to_sal_state)565565+ struct ia64_sal_os_state *sos)569566{570567 int platform_err;571568 int n_proc_err;572569 slidx_table_t slidx;573570 peidx_table_t peidx;574571 pal_bus_check_info_t pbci;575575-576576- /* handoff state from/to mca.c */577577- sal_to_os_handoff_state = sal_to_os_state;578578- os_to_sal_handoff_state = os_to_sal_state;579572580573 /* Make index of SAL error record */581574 platform_err = mca_make_slidx(rec, &slidx);···594597 *((u64*)&pbci) = peidx_check_info(&peidx, bus_check, 0);595598596599 /* Check whether MCA is global or not */597597- if (is_mca_global(&peidx, &pbci))600600+ if (is_mca_global(&peidx, &pbci, sos))598601 return 0;599602600603 /* Try to recover a processor error */601601- return recover_from_processor_error(platform_err, &slidx, &peidx, &pbci);604604+ return recover_from_processor_error(platform_err, &slidx, &peidx, &pbci, sos);602605}603606604607/*
+18-70
arch/ia64/kernel/minstate.h
···55#include "entry.h"6677/*88- * For ivt.s we want to access the stack virtually so we don't have to disable translation99- * on interrupts.1010- *1111- * On entry:1212- * r1: pointer to current task (ar.k6)1313- */1414-#define MINSTATE_START_SAVE_MIN_VIRT \1515-(pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \1616- ;; \1717-(pUStk) mov.m r24=ar.rnat; \1818-(pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of RBS */ \1919-(pKStk) mov r1=sp; /* get sp */ \2020- ;; \2121-(pUStk) lfetch.fault.excl.nt1 [r22]; \2222-(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1; /* compute base of memory stack */ \2323-(pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \2424- ;; \2525-(pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \2626-(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \2727- ;; \2828-(pUStk) mov r18=ar.bsp; \2929-(pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */3030-3131-#define MINSTATE_END_SAVE_MIN_VIRT \3232- bsw.1; /* switch back to bank 1 (must be last in insn group) */ \3333- ;;3434-3535-/*3636- * For mca_asm.S we want to access the stack physically since the state is saved before we3737- * go virtual and don't want to destroy the iip or ipsr.3838- */3939-#define MINSTATE_START_SAVE_MIN_PHYS \4040-(pKStk) mov r3=IA64_KR(PER_CPU_DATA);; \4141-(pKStk) addl r3=THIS_CPU(ia64_mca_data),r3;; \4242-(pKStk) ld8 r3 = [r3];; \4343-(pKStk) addl r3=IA64_MCA_CPU_INIT_STACK_OFFSET,r3;; \4444-(pKStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r3; \4545-(pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \4646-(pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of register backing store */ \4747- ;; \4848-(pUStk) mov r24=ar.rnat; \4949-(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1; /* compute base of memory stack */ \5050-(pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \5151-(pUStk) dep r22=-1,r22,61,3; /* compute kernel virtual addr of RBS */ \5252- ;; \5353-(pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \5454- ;; \5555-(pUStk) mov r18=ar.bsp; \5656-(pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \5757-5858-#define MINSTATE_END_SAVE_MIN_PHYS \5959- dep r12=-1,r12,61,3; /* make sp a kernel virtual address */ \6060- ;;6161-6262-#ifdef MINSTATE_VIRT6363-# define MINSTATE_GET_CURRENT(reg) mov reg=IA64_KR(CURRENT)6464-# define MINSTATE_START_SAVE_MIN MINSTATE_START_SAVE_MIN_VIRT6565-# define MINSTATE_END_SAVE_MIN MINSTATE_END_SAVE_MIN_VIRT6666-#endif6767-6868-#ifdef MINSTATE_PHYS6969-# define MINSTATE_GET_CURRENT(reg) mov reg=IA64_KR(CURRENT);; tpa reg=reg7070-# define MINSTATE_START_SAVE_MIN MINSTATE_START_SAVE_MIN_PHYS7171-# define MINSTATE_END_SAVE_MIN MINSTATE_END_SAVE_MIN_PHYS7272-#endif7373-7474-/*758 * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves769 * the minimum state necessary that allows us to turn psr.ic back7710 * on.···3097 * we can pass interruption state as arguments to a handler.3198 */3299#define DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA) \3333- MINSTATE_GET_CURRENT(r16); /* M (or M;;I) */ \100100+ mov r16=IA64_KR(CURRENT); /* M */ \34101 mov r27=ar.rsc; /* M */ \35102 mov r20=r1; /* A */ \36103 mov r25=ar.unat; /* M */ \···51118 SAVE_IFS; \52119 cmp.eq pKStk,pUStk=r0,r17; /* are we in kernel mode already? */ \53120 ;; \5454- MINSTATE_START_SAVE_MIN \121121+(pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \122122+ ;; \123123+(pUStk) mov.m r24=ar.rnat; \124124+(pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of RBS */ \125125+(pKStk) mov r1=sp; /* get sp */ \126126+ ;; \127127+(pUStk) lfetch.fault.excl.nt1 [r22]; \128128+(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1; /* compute base of memory stack */ \129129+(pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \130130+ ;; \131131+(pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \132132+(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \133133+ ;; \134134+(pUStk) mov r18=ar.bsp; \135135+(pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \55136 adds r17=2*L1_CACHE_BYTES,r1; /* really: biggest cache-line size */ \56137 adds r16=PT(CR_IPSR),r1; \57138 ;; \···128181 EXTRA; \129182 movl r1=__gp; /* establish kernel global pointer */ \130183 ;; \131131- MINSTATE_END_SAVE_MIN184184+ bsw.1; /* switch back to bank 1 (must be last in insn group) */ \185185+ ;;132186133187/*134188 * SAVE_REST saves the remainder of pt_regs (with psr.ic on).
+66-61
arch/ia64/kernel/palinfo.c
···307307308308 if ((status = ia64_pal_vm_summary(&vm_info_1, &vm_info_2)) !=0) {309309 printk(KERN_ERR "ia64_pal_vm_summary=%ld\n", status);310310- return 0;311311- }310310+ } else {312311313313-314314- p += sprintf(p,312312+ p += sprintf(p,315313 "Physical Address Space : %d bits\n"316314 "Virtual Address Space : %d bits\n"317315 "Protection Key Registers(PKR) : %d\n"···317319 "Hash Tag ID : 0x%x\n"318320 "Size of RR.rid : %d\n",319321 vm_info_1.pal_vm_info_1_s.phys_add_size,320320- vm_info_2.pal_vm_info_2_s.impl_va_msb+1, vm_info_1.pal_vm_info_1_s.max_pkr+1,321321- vm_info_1.pal_vm_info_1_s.key_size, vm_info_1.pal_vm_info_1_s.hash_tag_id,322322+ vm_info_2.pal_vm_info_2_s.impl_va_msb+1,323323+ vm_info_1.pal_vm_info_1_s.max_pkr+1,324324+ vm_info_1.pal_vm_info_1_s.key_size,325325+ vm_info_1.pal_vm_info_1_s.hash_tag_id,322326 vm_info_2.pal_vm_info_2_s.rid_size);323323-324324- if (ia64_pal_mem_attrib(&attrib) != 0)325325- return 0;326326-327327- p += sprintf(p, "Supported memory attributes : ");328328- sep = "";329329- for (i = 0; i < 8; i++) {330330- if (attrib & (1 << i)) {331331- p += sprintf(p, "%s%s", sep, mem_attrib[i]);332332- sep = ", ";333333- }334327 }335335- p += sprintf(p, "\n");328328+329329+ if (ia64_pal_mem_attrib(&attrib) == 0) {330330+ p += sprintf(p, "Supported memory attributes : ");331331+ sep = "";332332+ for (i = 0; i < 8; i++) {333333+ if (attrib & (1 << i)) {334334+ p += sprintf(p, "%s%s", sep, mem_attrib[i]);335335+ sep = ", ";336336+ }337337+ }338338+ p += sprintf(p, "\n");339339+ }336340337341 if ((status = ia64_pal_vm_page_size(&tr_pages, &vw_pages)) !=0) {338342 printk(KERN_ERR "ia64_pal_vm_page_size=%ld\n", status);339339- return 0;343343+ } else {344344+345345+ p += sprintf(p,346346+ "\nTLB walker : %simplemented\n"347347+ "Number of DTR : %d\n"348348+ "Number of ITR : %d\n"349349+ "TLB insertable page sizes : ",350350+ vm_info_1.pal_vm_info_1_s.vw ? "" : "not ",351351+ vm_info_1.pal_vm_info_1_s.max_dtr_entry+1,352352+ vm_info_1.pal_vm_info_1_s.max_itr_entry+1);353353+354354+355355+ p = bitvector_process(p, tr_pages);356356+357357+ p += sprintf(p, "\nTLB purgeable page sizes : ");358358+359359+ p = bitvector_process(p, vw_pages);340360 }341341-342342- p += sprintf(p,343343- "\nTLB walker : %simplemented\n"344344- "Number of DTR : %d\n"345345- "Number of ITR : %d\n"346346- "TLB insertable page sizes : ",347347- vm_info_1.pal_vm_info_1_s.vw ? "" : "not ",348348- vm_info_1.pal_vm_info_1_s.max_dtr_entry+1,349349- vm_info_1.pal_vm_info_1_s.max_itr_entry+1);350350-351351-352352- p = bitvector_process(p, tr_pages);353353-354354- p += sprintf(p, "\nTLB purgeable page sizes : ");355355-356356- p = bitvector_process(p, vw_pages);357357-358361 if ((status=ia64_get_ptce(&ptce)) != 0) {359362 printk(KERN_ERR "ia64_get_ptce=%ld\n", status);360360- return 0;361361- }362362-363363- p += sprintf(p,363363+ } else {364364+ p += sprintf(p,364365 "\nPurge base address : 0x%016lx\n"365366 "Purge outer loop count : %d\n"366367 "Purge inner loop count : %d\n"367368 "Purge outer loop stride : %d\n"368369 "Purge inner loop stride : %d\n",369369- ptce.base, ptce.count[0], ptce.count[1], ptce.stride[0], ptce.stride[1]);370370+ ptce.base, ptce.count[0], ptce.count[1],371371+ ptce.stride[0], ptce.stride[1]);370372371371- p += sprintf(p,373373+ p += sprintf(p,372374 "TC Levels : %d\n"373375 "Unique TC(s) : %d\n",374376 vm_info_1.pal_vm_info_1_s.num_tc_levels,375377 vm_info_1.pal_vm_info_1_s.max_unique_tcs);376378377377- for(i=0; i < vm_info_1.pal_vm_info_1_s.num_tc_levels; i++) {378378- for (j=2; j>0 ; j--) {379379- tc_pages = 0; /* just in case */379379+ for(i=0; i < vm_info_1.pal_vm_info_1_s.num_tc_levels; i++) {380380+ for (j=2; j>0 ; j--) {381381+ tc_pages = 0; /* just in case */380382381383382382- /* even without unification, some levels may not be present */383383- if ((status=ia64_pal_vm_info(i,j, &tc_info, &tc_pages)) != 0) {384384- continue;385385- }384384+ /* even without unification, some levels may not be present */385385+ if ((status=ia64_pal_vm_info(i,j, &tc_info, &tc_pages)) != 0) {386386+ continue;387387+ }386388387387- p += sprintf(p,389389+ p += sprintf(p,388390 "\n%s Translation Cache Level %d:\n"389391 "\tHash sets : %d\n"390392 "\tAssociativity : %d\n"391393 "\tNumber of entries : %d\n"392394 "\tFlags : ",393393- cache_types[j+tc_info.tc_unified], i+1, tc_info.tc_num_sets,394394- tc_info.tc_associativity, tc_info.tc_num_entries);395395+ cache_types[j+tc_info.tc_unified], i+1,396396+ tc_info.tc_num_sets,397397+ tc_info.tc_associativity,398398+ tc_info.tc_num_entries);395399396396- if (tc_info.tc_pf) p += sprintf(p, "PreferredPageSizeOptimized ");397397- if (tc_info.tc_unified) p += sprintf(p, "Unified ");398398- if (tc_info.tc_reduce_tr) p += sprintf(p, "TCReduction");400400+ if (tc_info.tc_pf)401401+ p += sprintf(p, "PreferredPageSizeOptimized ");402402+ if (tc_info.tc_unified)403403+ p += sprintf(p, "Unified ");404404+ if (tc_info.tc_reduce_tr)405405+ p += sprintf(p, "TCReduction");399406400400- p += sprintf(p, "\n\tSupported page sizes: ");407407+ p += sprintf(p, "\n\tSupported page sizes: ");401408402402- p = bitvector_process(p, tc_pages);409409+ p = bitvector_process(p, tc_pages);403410404404- /* when unified date (j=2) is enough */405405- if (tc_info.tc_unified) break;411411+ /* when unified date (j=2) is enough */412412+ if (tc_info.tc_unified)413413+ break;414414+ }406415 }407416 }408417 p += sprintf(p, "\n");···445440 p += sprintf(p, "\n");446441 }447442448448- if (ia64_pal_rse_info(&phys_stacked, &hints) != 0) return 0;443443+ if (ia64_pal_rse_info(&phys_stacked, &hints) == 0) {449444450445 p += sprintf(p,451446 "RSE stacked physical registers : %ld\n"452447 "RSE load/store hints : %ld (%s)\n",453448 phys_stacked, hints.ph_data,454449 hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(??)");455455-450450+ }456451 if (ia64_pal_debug_info(&iregs, &dregs))457452 return 0;458453
+34-28
arch/ia64/kernel/salinfo.c
···2222 *2323 * Dec 5 2004 kaos@sgi.com2424 * Standardize which records are cleared automatically.2525+ *2626+ * Aug 18 2005 kaos@sgi.com2727+ * mca.c may not pass a buffer, a NULL buffer just indicates that a new2828+ * record is available in SAL.2929+ * Replace some NR_CPUS by cpus_online, for hotplug cpu.2530 */26312732#include <linux/types.h>···198193 * The buffer passed from mca.c points to the output from ia64_log_get. This is199194 * a persistent buffer but its contents can change between the interrupt and200195 * when user space processes the record. Save the record id to identify201201- * changes.196196+ * changes. If the buffer is NULL then just update the bitmap.202197 */203198void204199salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe)···211206212207 BUG_ON(type >= ARRAY_SIZE(salinfo_log_name));213208214214- if (irqsafe)215215- spin_lock_irqsave(&data_saved_lock, flags);216216- for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) {217217- if (!data_saved->buffer)218218- break;209209+ if (buffer) {210210+ if (irqsafe)211211+ spin_lock_irqsave(&data_saved_lock, flags);212212+ for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) {213213+ if (!data_saved->buffer)214214+ break;215215+ }216216+ if (i == saved_size) {217217+ if (!data->saved_num) {218218+ shift1_data_saved(data, 0);219219+ data_saved = data->data_saved + saved_size - 1;220220+ } else221221+ data_saved = NULL;222222+ }223223+ if (data_saved) {224224+ data_saved->cpu = smp_processor_id();225225+ data_saved->id = ((sal_log_record_header_t *)buffer)->id;226226+ data_saved->size = size;227227+ data_saved->buffer = buffer;228228+ }229229+ if (irqsafe)230230+ spin_unlock_irqrestore(&data_saved_lock, flags);219231 }220220- if (i == saved_size) {221221- if (!data->saved_num) {222222- shift1_data_saved(data, 0);223223- data_saved = data->data_saved + saved_size - 1;224224- } else225225- data_saved = NULL;226226- }227227- if (data_saved) {228228- data_saved->cpu = smp_processor_id();229229- data_saved->id = ((sal_log_record_header_t *)buffer)->id;230230- data_saved->size = size;231231- data_saved->buffer = buffer;232232- }233233- if (irqsafe)234234- spin_unlock_irqrestore(&data_saved_lock, flags);235232236233 if (!test_and_set_bit(smp_processor_id(), &data->cpu_event)) {237234 if (irqsafe)···251244 int i;252245 if (!data->open)253246 return;254254- for (i = 0; i < NR_CPUS; ++i) {247247+ for_each_online_cpu(i) {255248 if (test_bit(i, &data->cpu_event)) {256249 /* double up() is not a problem, user space will see no257250 * records for the additional "events".···298291299292 n = data->cpu_check;300293 for (i = 0; i < NR_CPUS; i++) {301301- if (test_bit(n, &data->cpu_event)) {294294+ if (test_bit(n, &data->cpu_event) && cpu_online(n)) {302295 cpu = n;303296 break;304297 }···592585593586 /* we missed any events before now */594587 online = 0;595595- for (j = 0; j < NR_CPUS; j++)596596- if (cpu_online(j)) {597597- set_bit(j, &data->cpu_event);598598- ++online;599599- }588588+ for_each_online_cpu(j) {589589+ set_bit(j, &data->cpu_event);590590+ ++online;591591+ }600592 sema_init(&data->sem, online);601593602594 *sdir++ = dir;
···382382383383 if (impl_va_bits < 51 || impl_va_bits > 61)384384 panic("CPU has bogus IMPL_VA_MSB value of %lu!\n", impl_va_bits - 1);385385+ /*386386+ * mapped_space_bits - PAGE_SHIFT is the total number of ptes we need,387387+ * which must fit into "vmlpt_bits - pte_bits" slots. Second half of388388+ * the test makes sure that our mapped space doesn't overlap the389389+ * unimplemented hole in the middle of the region.390390+ */391391+ if ((mapped_space_bits - PAGE_SHIFT > vmlpt_bits - pte_bits) ||392392+ (mapped_space_bits > impl_va_bits - 1))393393+ panic("Cannot build a big enough virtual-linear page table"394394+ " to cover mapped address space.\n"395395+ " Try using a smaller page size.\n");396396+385397386398 /* place the VMLPT at the end of each page-table mapped region: */387399 pta = POW2(61) - POW2(vmlpt_bits);388400389389- if (POW2(mapped_space_bits) >= pta)390390- panic("mm/init: overlap between virtually mapped linear page table and "391391- "mapped kernel space!");392401 /*393402 * Set the (virtually mapped linear) page table address. Bit394403 * 8 selects between the short and long format, bits 2-7 the
+19-11
arch/ia64/sn/kernel/setup.c
···4949#include <asm/sn/clksupport.h>5050#include <asm/sn/sn_sal.h>5151#include <asm/sn/geo.h>5252+#include <asm/sn/sn_feature_sets.h>5253#include "xtalk/xwidgetdev.h"5354#include "xtalk/hubdev.h"5455#include <asm/sn/klconfig.h>···9897int sn_prom_type; /* 0=hardware, 1=medusa/realprom, 2=medusa/fakeprom */999810099short physical_node_map[MAX_PHYSNODE_ID];100100+static unsigned long sn_prom_features[MAX_PROM_FEATURE_SETS];101101102102EXPORT_SYMBOL(physical_node_map);103103···273271 u32 version = sn_sal_rev();274272 extern void sn_cpu_init(void);275273276276- ia64_sn_plat_set_error_handling_features();274274+ ia64_sn_plat_set_error_handling_features(); // obsolete275275+ ia64_sn_set_os_feature(OSF_MCA_SLV_TO_OS_INIT_SLV);276276+ ia64_sn_set_os_feature(OSF_FEAT_LOG_SBES);277277+277278278279#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)279280 /*···318313 }319314320315 printk("SGI SAL version %x.%02x\n", version >> 8, version & 0x00FF);321321-322322- /*323323- * Confirm the SAL we're running on is recent enough...324324- */325325- if (version < SN_SAL_MIN_VERSION) {326326- printk(KERN_ERR "This kernel needs SGI SAL version >= "327327- "%x.%02x\n", SN_SAL_MIN_VERSION >> 8,328328- SN_SAL_MIN_VERSION & 0x00FF);329329- panic("PROM version too old\n");330330- }331316332317 master_nasid = boot_get_nasid();333318···474479 */475480 if (nodepdaindr[0] == NULL)476481 return;482482+483483+ for (i = 0; i < MAX_PROM_FEATURE_SETS; i++)484484+ if (ia64_sn_get_prom_feature_set(i, &sn_prom_features[i]) != 0)485485+ break;477486478487 cpuid = smp_processor_id();479488 cpuphyid = get_sapicid();···650651651652 return -1;652653}654654+655655+int sn_prom_feature_available(int id)656656+{657657+ if (id >= BITS_PER_LONG * MAX_PROM_FEATURE_SETS)658658+ return 0;659659+ return test_bit(id, sn_prom_features);660660+}661661+EXPORT_SYMBOL(sn_prom_feature_available);662662+
+64-38
include/asm-ia64/mca.h
···1111#ifndef _ASM_IA64_MCA_H1212#define _ASM_IA64_MCA_H13131414-#define IA64_MCA_STACK_SIZE 81921515-1614#if !defined(__ASSEMBLY__)17151816#include <linux/interrupt.h>···46484749enum {4850 IA64_MCA_RENDEZ_CHECKIN_NOTDONE = 0x0,4949- IA64_MCA_RENDEZ_CHECKIN_DONE = 0x15151+ IA64_MCA_RENDEZ_CHECKIN_DONE = 0x1,5252+ IA64_MCA_RENDEZ_CHECKIN_INIT = 0x2,5053};51545255/* Information maintained by the MC infrastructure */···62636364} ia64_mc_info_t;64656565-typedef struct ia64_mca_sal_to_os_state_s {6666- u64 imsto_os_gp; /* GP of the os registered with the SAL */6767- u64 imsto_pal_proc; /* PAL_PROC entry point - physical addr */6868- u64 imsto_sal_proc; /* SAL_PROC entry point - physical addr */6969- u64 imsto_sal_gp; /* GP of the SAL - physical */7070- u64 imsto_rendez_state; /* Rendez state information */7171- u64 imsto_sal_check_ra; /* Return address in SAL_CHECK while going7272- * back to SAL from OS after MCA handling.7373- */7474- u64 pal_min_state; /* from PAL in r17 */7575- u64 proc_state_param; /* from PAL in r18. See SDV 2:268 11.3.2.1 */7676-} ia64_mca_sal_to_os_state_t;6666+/* Handover state from SAL to OS and vice versa, for both MCA and INIT events.6767+ * Besides the handover state, it also contains some saved registers from the6868+ * time of the event.6969+ * Note: mca_asm.S depends on the precise layout of this structure.7070+ */7171+7272+struct ia64_sal_os_state {7373+ /* SAL to OS, must be at offset 0 */7474+ u64 os_gp; /* GP of the os registered with the SAL, physical */7575+ u64 pal_proc; /* PAL_PROC entry point, physical */7676+ u64 sal_proc; /* SAL_PROC entry point, physical */7777+ u64 rv_rc; /* MCA - Rendezvous state, INIT - reason code */7878+ u64 proc_state_param; /* from R18 */7979+ u64 monarch; /* 1 for a monarch event, 0 for a slave */8080+ /* common, must follow SAL to OS */8181+ u64 sal_ra; /* Return address in SAL, physical */8282+ u64 sal_gp; /* GP of the SAL - physical */8383+ pal_min_state_area_t *pal_min_state; /* from R17. physical in asm, virtual in C */8484+ u64 prev_IA64_KR_CURRENT; /* previous value of IA64_KR(CURRENT) */8585+ struct task_struct *prev_task; /* previous task, NULL if it is not useful */8686+ /* Some interrupt registers are not saved in minstate, pt_regs or8787+ * switch_stack. Because MCA/INIT can occur when interrupts are8888+ * disabled, we need to save the additional interrupt registers over8989+ * MCA/INIT and resume.9090+ */9191+ u64 isr;9292+ u64 ifa;9393+ u64 itir;9494+ u64 iipa;9595+ u64 iim;9696+ u64 iha;9797+ /* OS to SAL, must follow common */9898+ u64 os_status; /* OS status to SAL, enum below */9999+ u64 context; /* 0 if return to same context100100+ 1 if return to new context */101101+};7710278103enum {79104 IA64_MCA_CORRECTED = 0x0, /* Error has been corrected by OS_MCA */···10784};1088510986enum {8787+ IA64_INIT_RESUME = 0x0, /* Resume after return from INIT */8888+ IA64_INIT_WARM_BOOT = -1, /* Warm boot of the system need from SAL */8989+};9090+9191+enum {11092 IA64_MCA_SAME_CONTEXT = 0x0, /* SAL to return to same context */11193 IA64_MCA_NEW_CONTEXT = -1 /* SAL to return to new context */11294};11395114114-typedef struct ia64_mca_os_to_sal_state_s {115115- u64 imots_os_status; /* OS status to SAL as to what happened116116- * with the MCA handling.117117- */118118- u64 imots_sal_gp; /* GP of the SAL - physical */119119- u64 imots_context; /* 0 if return to same context120120- 1 if return to new context */121121- u64 *imots_new_min_state; /* Pointer to structure containing122122- * new values of registers in the min state123123- * save area.124124- */125125- u64 imots_sal_check_ra; /* Return address in SAL_CHECK while going126126- * back to SAL from OS after MCA handling.127127- */128128-} ia64_mca_os_to_sal_state_t;129129-13096/* Per-CPU MCA state that is too big for normal per-CPU variables. */1319713298struct ia64_mca_cpu {133133- u64 stack[IA64_MCA_STACK_SIZE/8]; /* MCA memory-stack */134134- u64 proc_state_dump[512];135135- u64 stackframe[32];136136- u64 rbstore[IA64_MCA_STACK_SIZE/8]; /* MCA reg.-backing store */9999+ u64 mca_stack[KERNEL_STACK_SIZE/8];137100 u64 init_stack[KERNEL_STACK_SIZE/8];138138-} __attribute__ ((aligned(16)));101101+};139102140103/* Array of physical addresses of each CPU's MCA area. */141104extern unsigned long __per_cpu_mca[NR_CPUS];···130121extern void ia64_mca_cpu_init(void *);131122extern void ia64_os_mca_dispatch(void);132123extern void ia64_os_mca_dispatch_end(void);133133-extern void ia64_mca_ucmc_handler(void);124124+extern void ia64_mca_ucmc_handler(struct pt_regs *, struct ia64_sal_os_state *);125125+extern void ia64_init_handler(struct pt_regs *,126126+ struct switch_stack *,127127+ struct ia64_sal_os_state *);134128extern void ia64_monarch_init_handler(void);135129extern void ia64_slave_init_handler(void);136130extern void ia64_mca_cmc_vector_setup(void);137137-extern int ia64_reg_MCA_extension(void*);131131+extern int ia64_reg_MCA_extension(int (*fn)(void *, struct ia64_sal_os_state *));138132extern void ia64_unreg_MCA_extension(void);133133+extern u64 ia64_get_rnat(u64 *);134134+135135+#else /* __ASSEMBLY__ */136136+137137+#define IA64_MCA_CORRECTED 0x0 /* Error has been corrected by OS_MCA */138138+#define IA64_MCA_WARM_BOOT -1 /* Warm boot of the system need from SAL */139139+#define IA64_MCA_COLD_BOOT -2 /* Cold boot of the system need from SAL */140140+#define IA64_MCA_HALT -3 /* System to be halted by SAL */141141+142142+#define IA64_INIT_RESUME 0x0 /* Resume after return from INIT */143143+#define IA64_INIT_WARM_BOOT -1 /* Warm boot of the system need from SAL */144144+145145+#define IA64_MCA_SAME_CONTEXT 0x0 /* SAL to return to same context */146146+#define IA64_MCA_NEW_CONTEXT -1 /* SAL to return to new context */139147140148#endif /* !__ASSEMBLY__ */141149#endif /* _ASM_IA64_MCA_H */
+27-98
include/asm-ia64/mca_asm.h
···88 * Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com>99 * Copyright (C) 2002 Intel Corp.1010 * Copyright (C) 2002 Jenna Hall <jenna.s.hall@intel.com>1111+ * Copyright (C) 2005 Silicon Graphics, Inc1212+ * Copyright (C) 2005 Keith Owens <kaos@sgi.com>1113 */1214#ifndef _ASM_IA64_MCA_ASM_H1315#define _ASM_IA64_MCA_ASM_H···209207 ;;210208211209/*212212- * The following offsets capture the order in which the213213- * RSE related registers from the old context are214214- * saved onto the new stack frame.210210+ * The MCA and INIT stacks in struct ia64_mca_cpu look like normal kernel211211+ * stacks, except that the SAL/OS state and a switch_stack are stored near the212212+ * top of the MCA/INIT stack. To support concurrent entry to MCA or INIT, as213213+ * well as MCA over INIT, each event needs its own SAL/OS state. All entries214214+ * are 16 byte aligned.215215 *216216- * +-----------------------+217217- * |NDIRTY [BSP - BSPSTORE]|218218- * +-----------------------+219219- * | RNAT |220220- * +-----------------------+221221- * | BSPSTORE |222222- * +-----------------------+223223- * | IFS |224224- * +-----------------------+225225- * | PFS |226226- * +-----------------------+227227- * | RSC |228228- * +-----------------------+ <-------- Bottom of new stack frame216216+ * +---------------------------+217217+ * | pt_regs |218218+ * +---------------------------+219219+ * | switch_stack |220220+ * +---------------------------+221221+ * | SAL/OS state |222222+ * +---------------------------+223223+ * | 16 byte scratch area |224224+ * +---------------------------+ <-------- SP at start of C MCA handler225225+ * | ..... |226226+ * +---------------------------+227227+ * | RBS for MCA/INIT handler |228228+ * +---------------------------+229229+ * | struct task for MCA/INIT |230230+ * +---------------------------+ <-------- Bottom of MCA/INIT stack229231 */230230-#define rse_rsc_offset 0231231-#define rse_pfs_offset (rse_rsc_offset+0x08)232232-#define rse_ifs_offset (rse_pfs_offset+0x08)233233-#define rse_bspstore_offset (rse_ifs_offset+0x08)234234-#define rse_rnat_offset (rse_bspstore_offset+0x08)235235-#define rse_ndirty_offset (rse_rnat_offset+0x08)236232237237-/*238238- * rse_switch_context239239- *240240- * 1. Save old RSC onto the new stack frame241241- * 2. Save PFS onto new stack frame242242- * 3. Cover the old frame and start a new frame.243243- * 4. Save IFS onto new stack frame244244- * 5. Save the old BSPSTORE on the new stack frame245245- * 6. Save the old RNAT on the new stack frame246246- * 7. Write BSPSTORE with the new backing store pointer247247- * 8. Read and save the new BSP to calculate the #dirty registers248248- * NOTE: Look at pages 11-10, 11-11 in PRM Vol 2249249- */250250-#define rse_switch_context(temp,p_stackframe,p_bspstore) \251251- ;; \252252- mov temp=ar.rsc;; \253253- st8 [p_stackframe]=temp,8;; \254254- mov temp=ar.pfs;; \255255- st8 [p_stackframe]=temp,8; \256256- cover ;; \257257- mov temp=cr.ifs;; \258258- st8 [p_stackframe]=temp,8;; \259259- mov temp=ar.bspstore;; \260260- st8 [p_stackframe]=temp,8;; \261261- mov temp=ar.rnat;; \262262- st8 [p_stackframe]=temp,8; \263263- mov ar.bspstore=p_bspstore;; \264264- mov temp=ar.bsp;; \265265- sub temp=temp,p_bspstore;; \266266- st8 [p_stackframe]=temp,8;;267267-268268-/*269269- * rse_return_context270270- * 1. Allocate a zero-sized frame271271- * 2. Store the number of dirty registers RSC.loadrs field272272- * 3. Issue a loadrs to insure that any registers from the interrupted273273- * context which were saved on the new stack frame have been loaded274274- * back into the stacked registers275275- * 4. Restore BSPSTORE276276- * 5. Restore RNAT277277- * 6. Restore PFS278278- * 7. Restore IFS279279- * 8. Restore RSC280280- * 9. Issue an RFI281281- */282282-#define rse_return_context(psr_mask_reg,temp,p_stackframe) \283283- ;; \284284- alloc temp=ar.pfs,0,0,0,0; \285285- add p_stackframe=rse_ndirty_offset,p_stackframe;; \286286- ld8 temp=[p_stackframe];; \287287- shl temp=temp,16;; \288288- mov ar.rsc=temp;; \289289- loadrs;; \290290- add p_stackframe=-rse_ndirty_offset+rse_bspstore_offset,p_stackframe;;\291291- ld8 temp=[p_stackframe];; \292292- mov ar.bspstore=temp;; \293293- add p_stackframe=-rse_bspstore_offset+rse_rnat_offset,p_stackframe;;\294294- ld8 temp=[p_stackframe];; \295295- mov ar.rnat=temp;; \296296- add p_stackframe=-rse_rnat_offset+rse_pfs_offset,p_stackframe;; \297297- ld8 temp=[p_stackframe];; \298298- mov ar.pfs=temp;; \299299- add p_stackframe=-rse_pfs_offset+rse_ifs_offset,p_stackframe;; \300300- ld8 temp=[p_stackframe];; \301301- mov cr.ifs=temp;; \302302- add p_stackframe=-rse_ifs_offset+rse_rsc_offset,p_stackframe;; \303303- ld8 temp=[p_stackframe];; \304304- mov ar.rsc=temp ; \305305- mov temp=psr;; \306306- or temp=temp,psr_mask_reg;; \307307- mov cr.ipsr=temp;; \308308- mov temp=ip;; \309309- add temp=0x30,temp;; \310310- mov cr.iip=temp;; \311311- srlz.i;; \312312- rfi;;233233+#define ALIGN16(x) ((x)&~15)234234+#define MCA_PT_REGS_OFFSET ALIGN16(KERNEL_STACK_SIZE-IA64_PT_REGS_SIZE)235235+#define MCA_SWITCH_STACK_OFFSET ALIGN16(MCA_PT_REGS_OFFSET-IA64_SWITCH_STACK_SIZE)236236+#define MCA_SOS_OFFSET ALIGN16(MCA_SWITCH_STACK_OFFSET-IA64_SAL_OS_STATE_SIZE)237237+#define MCA_SP_OFFSET ALIGN16(MCA_SOS_OFFSET-16)313238314239#endif /* _ASM_IA64_MCA_ASM_H */
+1-1
include/asm-ia64/ptrace.h
···119119 unsigned long ar_unat; /* interrupted task's NaT register (preserved) */120120 unsigned long ar_pfs; /* prev function state */121121 unsigned long ar_rsc; /* RSE configuration */122122- /* The following two are valid only if cr_ipsr.cpl > 0: */122122+ /* The following two are valid only if cr_ipsr.cpl > 0 || ti->flags & _TIF_MCA_INIT */123123 unsigned long ar_rnat; /* RSE NaT */124124 unsigned long ar_bspstore; /* RSE bspstore */125125
+57
include/asm-ia64/sn/sn_feature_sets.h
···11+#ifndef _ASM_IA64_SN_FEATURE_SETS_H22+#define _ASM_IA64_SN_FEATURE_SETS_H33+44+/*55+ * SN PROM Features66+ *77+ * This file is subject to the terms and conditions of the GNU General Public88+ * License. See the file "COPYING" in the main directory of this archive99+ * for more details.1010+ *1111+ * Copyright (c) 2005 Silicon Graphics, Inc. All rights reserved.1212+ */1313+1414+1515+#include <asm/types.h>1616+#include <asm/bitops.h>1717+1818+/* --------------------- PROM Features -----------------------------*/1919+extern int sn_prom_feature_available(int id);2020+2121+#define MAX_PROM_FEATURE_SETS 22222+2323+/*2424+ * The following defines features that may or may not be supported by the2525+ * current PROM. The OS uses sn_prom_feature_available(feature) to test for2626+ * the presence of a PROM feature. Down rev (old) PROMs will always test2727+ * "false" for new features.2828+ *2929+ * Use:3030+ * if (sn_prom_feature_available(PRF_FEATURE_XXX))3131+ * ...3232+ */3333+3434+/*3535+ * Example: feature XXX3636+ */3737+#define PRF_FEATURE_XXX 03838+3939+4040+4141+/* --------------------- OS Features -------------------------------*/4242+4343+/*4444+ * The following defines OS features that are optionally present in4545+ * the operating system.4646+ * During boot, PROM is notified of these features via a series of calls:4747+ *4848+ * ia64_sn_set_os_feature(feature1);4949+ *5050+ * Once enabled, a feature cannot be disabled.5151+ *5252+ * By default, features are disabled unless explicitly enabled.5353+ */5454+#define OSF_MCA_SLV_TO_OS_INIT_SLV 05555+#define OSF_FEAT_LOG_SBES 15656+5757+#endif /* _ASM_IA64_SN_FEATURE_SETS_H */
···35773577}3578357835793579/**35803580+ * curr_task - return the current task for a given cpu.35813581+ * @cpu: the processor in question.35823582+ */35833583+task_t *curr_task(int cpu)35843584+{35853585+ return cpu_curr(cpu);35863586+}35873587+35883588+/**35893589+ * set_curr_task - set the current task for a given cpu.35903590+ * @cpu: the processor in question.35913591+ * @p: the task pointer to set.35923592+ *35933593+ * Description: This function must only be used when non-maskable interrupts35943594+ * are serviced on a separate stack. It allows the architecture to switch the35953595+ * notion of the current task on a cpu in a non-blocking manner. This function35963596+ * must be called with interrupts disabled, the caller must save the original35973597+ * value of the current task (see curr_task() above) and restore that value35983598+ * before reenabling interrupts.35993599+ */36003600+void set_curr_task(int cpu, task_t *p)36013601+{36023602+ cpu_curr(cpu) = p;36033603+}36043604+36053605+/**35803606 * find_process_by_pid - find a process with a matching PID value.35813607 * @pid: the pid in question.35823608 */