Index: head/sys/ia64/ia64/clock.c =================================================================== --- head/sys/ia64/ia64/clock.c (revision 67521) +++ head/sys/ia64/ia64/clock.c (revision 67522) @@ -1,500 +1,497 @@ /* $FreeBSD$ */ /* $NetBSD: clock.c,v 1.20 1998/01/31 10:32:47 ross Exp $ */ /* * Copyright (c) 1988 University of Utah. * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department and Ralph Campbell. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: Utah Hdr: clock.c 1.18 91/01/21 * * @(#)clock.c 8.1 (Berkeley) 6/10/93 */ #include /* RCS ID & Copyright macro defns */ #include #include #include #include #include #include #include #include #include #include #include #define SECMIN ((unsigned)60) /* seconds per minute */ #define SECHOUR ((unsigned)(60*SECMIN)) /* seconds per hour */ #define SECDAY ((unsigned)(24*SECHOUR)) /* seconds per day */ #define SECYR ((unsigned)(365*SECDAY)) /* seconds per common year */ /* * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we * can use a simple formula for leap years. */ #define LEAPYEAR(y) (((y) % 4) == 0) device_t clockdev; int clockinitted; int tickfix; int tickfixinterval; int adjkerntz; /* local offset from GMT in seconds */ int disable_rtc_set; /* disable resettodr() if != 0 */ int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ static int beeping = 0; extern int cycles_per_sec; static timecounter_get_t ia64_get_timecount; static struct timecounter ia64_timecounter = { ia64_get_timecount, /* get_timecount */ 0, /* no poll_pps */ ~0u, /* counter_mask */ 0, /* frequency */ "IA64 ITC" /* name */ }; SYSCTL_OPAQUE(_debug, OID_AUTO, ia64_timecounter, CTLFLAG_RD, &ia64_timecounter, sizeof(ia64_timecounter), "S,timecounter", ""); /* Values for timerX_state: */ #define RELEASED 0 #define RELEASE_PENDING 1 #define ACQUIRED 2 #define ACQUIRE_PENDING 3 /* static u_char timer0_state; */ static u_char timer2_state; /* * Algorithm for missed clock ticks from Linux/alpha. */ /* * Shift amount by which scaled_ticks_per_cycle is scaled. Shifting * by 48 gives us 16 bits for HZ while keeping the accuracy good even * for large CPU clock rates. */ #define FIX_SHIFT 48 static u_int64_t scaled_ticks_per_cycle; static u_int32_t max_cycles_per_tick; static u_int32_t last_time; static u_int32_t calibrate_clocks(u_int32_t firmware_freq); void clockattach(device_t dev) { /* * Just bookkeeping. */ if (clockdev) panic("clockattach: multiple clocks"); clockdev = dev; cycles_per_sec = calibrate_clocks(cycles_per_sec); #ifdef EVCNT_COUNTERS evcnt_attach(dev, "intr", &clock_intr_evcnt); #endif + + /* + * Get the clock started. + */ + CLOCK_INIT(clockdev); } /* * Machine-dependent clock routines. * * Startrtclock restarts the real-time clock, which provides * hardclock interrupts to kern_clock.c. * * Inittodr initializes the time of day hardware which provides * date functions. Its primary function is to use some file * system information in case the hardare clock lost state. * * Resettodr restores the time of day hardware after a time change. */ /* * Start the real-time and statistics clocks. Leave stathz 0 since there * are no other timers available. */ void cpu_initclocks() { u_int32_t freq; - if (clockdev == NULL) - panic("cpu_initclocks: no clock attached"); - /* * We use cr.itc and cr.itm to implement a 1024hz clock. */ hz = 1024; tick = 1000000 / hz; /* number of microseconds between interrupts */ tickfix = 1000000 - (hz * tick); if (tickfix) { int ftp; ftp = min(ffs(tickfix), ffs(hz)); tickfix >>= (ftp - 1); tickfixinterval = hz >> (ftp - 1); } /* * XXX we should call SAL_FREQ_BASE_INTERVAL_TIMER here. */ cycles_per_sec = 70000000; ia64_set_itm(ia64_get_itc() + (cycles_per_sec + hz/2) / hz); ia64_set_itv(240); /* highest priority class */ freq = cycles_per_sec; last_time = ia64_get_itc(); scaled_ticks_per_cycle = ((u_int64_t)hz << FIX_SHIFT) / freq; max_cycles_per_tick = 2*freq / hz; ia64_timecounter.tc_frequency = freq; tc_init(&ia64_timecounter); stathz = 128; - - /* - * Get the clock started. - */ - CLOCK_INIT(clockdev); } static u_int32_t calibrate_clocks(u_int32_t firmware_freq) { u_int32_t start_pcc, stop_pcc; int sec, start_sec; if (bootverbose) printf("Calibrating clock(s) ... "); /* Read the mc146818A seconds counter. */ if (CLOCK_GETSECS(clockdev, &sec)) goto fail; /* Wait for the mC146818A seconds counter to change. */ start_sec = sec; for (;;) { if (CLOCK_GETSECS(clockdev, &sec)) goto fail; if (sec != start_sec) break; } /* Start keeping track of the PCC. */ start_pcc = ia64_get_itc(); /* * Wait for the mc146818A seconds counter to change. */ start_sec = sec; for (;;) { if (CLOCK_GETSECS(clockdev, &sec)) goto fail; if (sec != start_sec) break; } /* * Read the PCC again to work out frequency. */ stop_pcc = ia64_get_itc(); if (bootverbose) { printf("PCC clock: %u Hz (firmware %u Hz)\n", stop_pcc - start_pcc, firmware_freq); } return (stop_pcc - start_pcc); fail: if (bootverbose) printf("failed, using firmware default of %u Hz\n", firmware_freq); return (firmware_freq); } void handleclock(void* arg) { ia64_set_itm(ia64_get_itc() + (cycles_per_sec + hz/2) / hz); hardclock(arg); setdelayed(); } /* * We assume newhz is either stathz or profhz, and that neither will * change after being set up above. Could recalculate intervals here * but that would be a drag. */ void setstatclockrate(newhz) int newhz; { /* nothing we can do */ } /* * This code is defunct after 2099. * Will Unix still be here then?? */ static short dayyr[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; /* * Initialze the time of day register, based on the time base which is, e.g. * from a filesystem. Base provides the time to within six months, * and the time of year clock (if any) provides the rest. */ void inittodr(base) time_t base; { register int days, yr; struct clocktime ct; time_t deltat; int badbase; int s; struct timespec ts; if (base < 5*SECYR) { printf("WARNING: preposterous time in file system"); /* read the system clock anyway */ base = 6*SECYR + 186*SECDAY + SECDAY/2; badbase = 1; } else badbase = 0; CLOCK_GET(clockdev, base, &ct); clockinitted = 1; /* simple sanity checks */ if (ct.year < 70 || ct.mon < 1 || ct.mon > 12 || ct.day < 1 || ct.day > 31 || ct.hour > 23 || ct.min > 59 || ct.sec > 59) { /* * Believe the time in the file system for lack of * anything better, resetting the TODR. */ s = splclock(); ts.tv_sec = base; ts.tv_nsec = 0; tc_setclock(&ts); splx(s); if (!badbase) { printf("WARNING: preposterous clock chip time\n"); resettodr(); } goto bad; } days = 0; for (yr = 70; yr < ct.year; yr++) days += LEAPYEAR(yr) ? 366 : 365; days += dayyr[ct.mon - 1] + ct.day - 1; if (LEAPYEAR(yr) && ct.mon > 2) days++; /* now have days since Jan 1, 1970; the rest is easy... */ s = splclock(); ts.tv_sec = days * SECDAY + ct.hour * SECHOUR + ct.min * SECMIN + ct.sec; if (wall_cmos_clock) ts.tv_sec += adjkerntz; ts.tv_nsec = 0; tc_setclock(&ts); splx(s); if (!badbase) { /* * See if we gained/lost two or more days; * if so, assume something is amiss. */ deltat = ts.tv_sec - base; if (deltat < 0) deltat = -deltat; if (deltat < 2 * SECDAY) return; printf("WARNING: clock %s %d days", ts.tv_sec < base ? "lost" : "gained", deltat / SECDAY); } bad: printf(" -- CHECK AND RESET THE DATE!\n"); } /* * Reset the TODR based on the time value; used when the TODR * has a preposterous value and also when the time is reset * by the stime system call. Also called when the TODR goes past * TODRZERO + 100*(SECYEAR+2*SECDAY) (e.g. on Jan 2 just after midnight) * to wrap the TODR around. */ void resettodr() { register int t, t2, s; struct clocktime ct; unsigned long tm; if (disable_rtc_set) return; s = splclock(); tm = time_second; splx(s); if (!clockinitted) return; /* Calculate local time to put in RTC */ tm -= (wall_cmos_clock ? adjkerntz : 0); /* compute the day of week. */ t2 = tm / SECDAY; ct.dow = (t2 + 4) % 7; /* 1/1/1970 was thursday */ /* compute the year */ ct.year = 69; t = t2; /* XXX ? */ while (t2 >= 0) { /* whittle off years */ t = t2; ct.year++; t2 -= LEAPYEAR(ct.year) ? 366 : 365; } /* t = month + day; separate */ t2 = LEAPYEAR(ct.year); for (ct.mon = 1; ct.mon < 12; ct.mon++) if (t < dayyr[ct.mon] + (t2 && ct.mon > 1)) break; ct.day = t - dayyr[ct.mon - 1] + 1; if (t2 && ct.mon > 2) ct.day--; /* the rest is easy */ t = tm % SECDAY; ct.hour = t / SECHOUR; t %= 3600; ct.min = t / SECMIN; ct.sec = t % SECMIN; CLOCK_SET(clockdev, &ct); } static unsigned ia64_get_timecount(struct timecounter* tc) { return ia64_get_itc(); } int acquire_timer2(int mode) { if (timer2_state != RELEASED) return (-1); timer2_state = ACQUIRED; /* * This access to the timer registers is as atomic as possible * because it is a single instruction. We could do better if we * knew the rate. Use of splclock() limits glitches to 10-100us, * and this is probably good enough for timer2, so we aren't as * careful with it as with timer0. */ outb(TIMER_MODE, TIMER_SEL2 | (mode & 0x3f)); return (0); } int release_timer2() { if (timer2_state != ACQUIRED) return (-1); timer2_state = RELEASED; outb(TIMER_MODE, TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT); return (0); } static void sysbeepstop(void *chan) { outb(IO_PPI, inb(IO_PPI)&0xFC); /* disable counter2 output to speaker */ release_timer2(); beeping = 0; } /* * Frequency of all three count-down timers; (TIMER_FREQ/freq) is the * appropriate count to generate a frequency of freq hz. */ #ifndef TIMER_FREQ #define TIMER_FREQ 1193182 #endif #define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x)) int sysbeep(int pitch, int period) { int x = splhigh(); if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT)) if (!beeping) { /* Something else owns it. */ splx(x); return (-1); /* XXX Should be EBUSY, but nobody cares anyway. */ } if (pitch) pitch = TIMER_DIV(pitch); outb(TIMER_CNTR2, pitch); outb(TIMER_CNTR2, (pitch>>8)); if (!beeping) { /* enable counter2 output to speaker */ if (pitch) outb(IO_PPI, inb(IO_PPI) | 3); beeping = period; timeout(sysbeepstop, (void *)NULL, period); } splx(x); return (0); } Index: head/sys/ia64/ia64/exception.S =================================================================== --- head/sys/ia64/ia64/exception.S (revision 67521) +++ head/sys/ia64/ia64/exception.S (revision 67522) @@ -1,1449 +1,1462 @@ /*- * Copyright (c) 2000 Doug Rabson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include /* * ar.k7 = curproc * ar.k6 = ksp * ar.k5 = kbsp * ar.k4 = globalp */ /* * Call exception_save_regs to preserve the interrupted state in a * trapframe. Note that we don't use a call instruction because we * must be careful not to lose track of the RSE state. We then call * trap() with the value of _n_ as an argument to handle the * exception. We arrange for trap() to return to exception_restore * which will restore the interrupted state before executing an rfi to * resume it. */ #define TRAP(_n_) \ mov r16=b0; \ 1: mov r17=ip;; \ add r17=2f-1b,r17;; \ mov b0=r17; \ br.sptk.few exception_save; \ 2: (p3) ssm psr.i; \ alloc r15=ar.pfs,0,0,3,0; \ mov out0=_n_; \ mov out1=r14; \ mov out2=sp;; \ add sp=-16,sp;; \ br.call.sptk.few rp=trap; \ 3: br.sptk.many exception_restore /* * The IA64 Interrupt Vector Table (IVT) contains 20 slots with 64 * bundles per vector and 48 slots with 16 bundles per vector. */ .section .text.ivt,"ax" .align 32768 .global ia64_vector_table ia64_vector_table: /* 0x0000: VHPT Translation vector */ TRAP(0) .align 1024 /* 0x0400: Instruction TLB vector */ mov r16=cr.ifa mov r17=pr ;; thash r18=r16 ttag r19=r16 ;; add r21=16,r18 // tag add r20=24,r18 // collision chain ;; ld8 r21=[r21] // check VHPT tag ;; cmp.eq p1,p2=r21,r19 (p2) br.dpnt.few 1f ;; ld8 r21=[r18] // read pte ;; itc.i r21 // insert pte rfi // done ;; 1: ld8 r20=[r20] // first entry ;; rsm psr.dt // turn off data translations ;; srlz.d // serialize ;; 2: cmp.eq p1,p2=r0,r20 // done? (p1) br.cond.spnt.few 9f // bail if done ;; add r21=16,r20 // tag location ;; ld8 r21=[r21] // read tag ;; cmp.eq p1,p2=r21,r19 // compare tags (p2) br.cond.sptk.few 3f // if not, read next in chain ;; ld8 r21=[r20],8 // read pte ;; ld8 r22=[r20] // read rest of pte ;; dep r18=0,r18,61,3 // convert vhpt ptr to physical ;; add r20=16,r18 // address of tag ;; ld8.acq r23=[r20] // read old tag movl r24=(1<<63) // ti bit ;; or r23=r23,r24 // set ti bit ;; st8.rel [r20]=r23 // store old tag + ti ;; mf // make sure everyone sees ;; st8 [r18]=r21,8 // store pte ;; st8 [r18]=r22,8 ;; st8.rel [r18]=r19 // store new tag ;; mov pr=r17,0x1ffff // restore predicates ;; rfi // walker will retry the access 3: add r20=24,r20 // next in chain ;; ld8 r20=[r20] // read chain br.cond.sptk.few 2b // loop 9: mov pr=r17,0x1ffff // restore predicates ssm psr.dt ;; srlz.d ;; TRAP(20) // Page Not Present trap .align 1024 /* 0x0800: Data TLB vector */ mov r16=cr.ifa mov r17=pr ;; thash r18=r16 ttag r19=r16 ;; add r21=16,r18 // tag add r20=24,r18 // collision chain ;; ld8 r21=[r21] // check VHPT tag ;; cmp.eq p1,p2=r21,r19 br.dpnt.few 1f ;; ld8 r21=[r18] // read pte ;; itc.d r21 // insert pte rfi // done ;; 1: ld8 r20=[r20] // first entry ;; rsm psr.dt // turn off data translations ;; srlz.d // serialize ;; 2: cmp.eq p1,p2=r0,r20 // done? (p1) br.cond.spnt.few 9f // bail if done ;; add r21=16,r20 // tag location ;; ld8 r21=[r21] // read tag ;; cmp.eq p1,p2=r21,r19 // compare tags (p2) br.cond.sptk.few 3f // if not, read next in chain ;; ld8 r21=[r20],8 // read pte ;; ld8 r22=[r20] // read rest of pte ;; dep r18=0,r18,61,3 // convert vhpt ptr to physical ;; add r20=16,r18 // address of tag ;; ld8.acq r23=[r20] // read old tag movl r24=(1<<63) // ti bit ;; or r23=r23,r24 // set ti bit ;; st8.rel [r20]=r23 // store old tag + ti ;; mf // make sure everyone sees ;; st8 [r18]=r21,8 // store pte ;; st8 [r18]=r22,8 ;; st8.rel [r18]=r19 // store new tag ;; mov pr=r17,0x1ffff // restore predicates ;; rfi // walker will retry the access 3: add r20=24,r20 // next in chain ;; ld8 r20=[r20] // read chain br.cond.sptk.few 2b // loop 9: mov pr=r17,0x1ffff // restore predicates ssm psr.dt ;; srlz.d ;; TRAP(20) // Page Not Present trap .align 1024 /* 0x0c00: Alternate Instruction TLB vector */ mov r16=cr.ifa // where did it happen ;; mov r18=pr // save predicates ;; extr.u r17=r16,61,3 // get region number ;; cmp.eq p1,p2=7,r17 // RR7->p1, RR6->p2 ;; (p1) movl r17=PTE_P+PTE_MA_WB+PTE_A+PTE_D+PTE_PL_KERN+PTE_AR_RX (p2) movl r17=PTE_P+PTE_MA_UC+PTE_A+PTE_D+PTE_PL_KERN+PTE_AR_RX ;; dep r16=0,r16,50,14 // clear bits above PPN ;; dep r16=r17,r17,0,12 // put pte bits in 0..11 ;; itc.i r16 mov pr=r18,0x1ffff // restore predicates ;; rfi .align 1024 /* 0x1000: Alternate Data TLB vector */ mov r16=cr.ifa // where did it happen mov r18=pr // save predicates ;; extr.u r17=r16,61,3 // get region number ;; cmp.eq p1,p2=7,r17 // RR7->p1, RR6->p2 ;; (p1) movl r17=PTE_P+PTE_MA_WB+PTE_A+PTE_D+PTE_PL_KERN+PTE_AR_RW (p2) movl r17=PTE_P+PTE_MA_UC+PTE_A+PTE_D+PTE_PL_KERN+PTE_AR_RW ;; dep r16=0,r16,50,14 // clear bits above PPN ;; dep r16=r17,r17,0,12 // put pte bits in 0..11 ;; itc.d r16 mov pr=r18,0x1ffff // restore predicates ;; rfi .align 1024 /* 0x1400: Data Nested TLB vector */ TRAP(5) .align 1024 /* 0x1800: Instruction Key Miss vector */ TRAP(6) .align 1024 /* 0x1c00: Data Key Miss vector */ TRAP(7) .align 1024 /* 0x2000: Dirty-Bit vector */ mov r16=cr.ifa mov r17=pr mov r20=12<<2 // XXX get page size from VHPT ;; ptc.l r16,r20 // purge TLB thash r18=r16 ttag r19=r16 ;; srlz.d add r20=24,r18 // collision chain ;; ld8 r20=[r20] // first entry ;; rsm psr.dt // turn off data translations ;; srlz.d // serialize ;; 1: cmp.eq p1,p2=r0,r20 // done? (p1) br.cond.spnt.few 9f // bail if done ;; add r21=16,r20 // tag location ;; ld8 r21=[r21] // read tag ;; cmp.eq p1,p2=r21,r19 // compare tags (p2) br.cond.sptk.few 2f // if not, read next in chain ;; ld8 r21=[r20] // read pte mov r22=PTE_D ;; or r21=r22,r21 // set dirty bit ;; st8 [r20]=r21 // store back ;; ld8 r22=[r20] // read rest of pte ;; dep r18=0,r18,61,3 // convert vhpt ptr to physical ;; add r20=16,r18 // address of tag ;; ld8.acq r23=[r20] // read old tag movl r24=(1<<63) // ti bit ;; or r23=r23,r24 // set ti bit ;; st8.rel [r20]=r23 // store old tag + ti ;; mf // make sure everyone sees ;; st8 [r18]=r21,8 // store pte ;; st8 [r18]=r22,8 ;; st8.rel [r18]=r19 // store new tag ;; mov pr=r17,0x1ffff // restore predicates ;; rfi // walker will retry the access 2: add r20=24,r20 // next in chain ;; ld8 r20=[r20] // read chain br.cond.sptk.few 1b // loop 9: mov pr=r17,0x1ffff // restore predicates TRAP(8) // die horribly .align 1024 /* 0x2400: Instruction Access-Bit vector */ mov r16=cr.ifa mov r17=pr mov r20=12<<2 // XXX get page size from VHPT ;; ptc.l r16,r20 // purge TLB thash r18=r16 ttag r19=r16 ;; srlz.d add r20=24,r18 // collision chain ;; ld8 r20=[r20] // first entry ;; rsm psr.dt // turn off data translations ;; srlz.d // serialize ;; 1: cmp.eq p1,p2=r0,r20 // done? (p1) br.cond.spnt.few 9f // bail if done ;; add r21=16,r20 // tag location ;; ld8 r21=[r21] // read tag ;; cmp.eq p1,p2=r21,r19 // compare tags (p2) br.cond.sptk.few 2f // if not, read next in chain ;; ld8 r21=[r20] // read pte mov r22=PTE_A ;; or r21=r22,r21 // set accessed bit ;; st8 [r20]=r21 // store back ;; ld8 r22=[r20] // read rest of pte ;; dep r18=0,r18,61,3 // convert vhpt ptr to physical ;; add r20=16,r18 // address of tag ;; ld8.acq r23=[r20] // read old tag movl r24=(1<<63) // ti bit ;; or r23=r23,r24 // set ti bit ;; st8.rel [r20]=r23 // store old tag + ti ;; mf // make sure everyone sees ;; st8 [r18]=r21,8 // store pte ;; st8 [r18]=r22,8 ;; st8.rel [r18]=r19 // store new tag ;; mov pr=r17,0x1ffff // restore predicates ;; rfi // walker will retry the access 2: add r20=24,r20 // next in chain ;; ld8 r20=[r20] // read chain br.cond.sptk.few 1b // loop 9: mov pr=r17,0x1ffff // restore predicates TRAP(9) .align 1024 /* 0x2800: Data Access-Bit vector */ mov r16=cr.ifa mov r17=pr mov r20=12<<2 // XXX get page size from VHPT ;; ptc.l r16,r20 // purge TLB thash r18=r16 ttag r19=r16 ;; srlz.d add r20=24,r18 // collision chain ;; ld8 r20=[r20] // first entry ;; rsm psr.dt // turn off data translations ;; srlz.d // serialize ;; 1: cmp.eq p1,p2=r0,r20 // done? (p1) br.cond.spnt.few 9f // bail if done ;; add r21=16,r20 // tag location ;; ld8 r21=[r21] // read tag ;; cmp.eq p1,p2=r21,r19 // compare tags (p2) br.cond.sptk.few 2f // if not, read next in chain ;; ld8 r21=[r20] // read pte mov r22=PTE_A ;; or r21=r22,r21 // set accessed bit ;; st8 [r20]=r21 // store back ;; ld8 r22=[r20] // read rest of pte ;; dep r18=0,r18,61,3 // convert vhpt ptr to physical ;; add r20=16,r18 // address of tag ;; ld8.acq r23=[r20] // read old tag movl r24=(1<<63) // ti bit ;; or r23=r23,r24 // set ti bit ;; st8.rel [r20]=r23 // store old tag + ti ;; mf // make sure everyone sees ;; st8 [r18]=r21,8 // store pte ;; st8 [r18]=r22,8 ;; st8.rel [r18]=r19 // store new tag ;; mov pr=r17,0x1ffff // restore predicates ;; rfi // walker will retry the access 2: add r20=24,r20 // next in chain ;; ld8 r20=[r20] // read chain br.cond.sptk.few 1b // loop 9: mov pr=r17,0x1ffff // restore predicates TRAP(10) .align 1024 /* 0x2c00: Break Instruction vector */ mov r16=pr // save pr for a moment mov r17=cr.iim;; // read break value mov r18=0x100000;; // syscall number cmp.eq p1,p2=r18,r17;; // check for syscall (p2) br.dpnt.few 9f mov r17=cr.ipsr;; // check for user mode extr.u r17=r17,32,2;; cmp.eq p1,p2=r0,r17 (p1) br.dpnt.few 9f // trap if kernel mode br.sptk.many do_syscall ;; 9: mov pr=r16,0x1ffff // restore pr TRAP(11) .align 1024 /* 0x3000: External Interrupt vector */ mov r16=b0 // save user's b0 1: mov r17=ip;; // construct return address add r17=2f-1b,r17;; // for exception_save mov b0=r17 br.sptk.few exception_save // 'call' exception_save 2: alloc r14=ar.pfs,0,0,2,0 // make a frame for calling with mov out1=sp;; add sp=-16,sp;; 3: mov out0=cr.ivr // find interrupt vector ;; cmp.eq p6,p0=15,out0 // check for spurious vector number (p6) br.dpnt.few exception_restore // if spurious, we are done ;; ssm psr.i // re-enable interrupts ;; // now that we are in-progress srlz.d ;; br.call.sptk.many rp=interrupt // call high-level handler rsm psr.i // disable interrupts ;; srlz.d ;; mov cr.eoi=r0 // and ack the interrupt ;; srlz.d br.sptk.few 3b // loop for more .align 1024 /* 0x3400: Reserved */ TRAP(13) .align 1024 /* 0x3800: Reserved */ TRAP(14) .align 1024 /* 0x3c00: Reserved */ TRAP(15) .align 1024 /* 0x4000: Reserved */ TRAP(16) .align 1024 /* 0x4400: Reserved */ TRAP(17) .align 1024 /* 0x4800: Reserved */ TRAP(18) .align 1024 /* 0x4c00: Reserved */ TRAP(19) .align 1024 /* 0x5000: Page Not Present vector */ TRAP(20) .align 256 /* 0x5100: Key Permission vector */ TRAP(21) .align 256 /* 0x5200: Instruction Access Rights vector */ TRAP(22) .align 256 /* 0x5300: Data Access Rights vector */ TRAP(23) .align 256 /* 0x5400: General Exception vector */ TRAP(24) .align 256 /* 0x5500: Disabled FP-Register vector */ TRAP(25) .align 256 /* 0x5600: NaT Consumption vector */ TRAP(26) .align 256 /* 0x5700: Speculation vector */ TRAP(27) .align 256 /* 0x5800: Reserved */ TRAP(28) .align 256 /* 0x5900: Debug vector */ TRAP(29) .align 256 /* 0x5a00: Unaligned Reference vector */ TRAP(30) .align 256 /* 0x5b00: Unsupported Data Reference vector */ TRAP(31) .align 256 /* 0x5c00: Floating-point Fault vector */ TRAP(32) .align 256 /* 0x5d00: Floating-point Trap vector */ TRAP(33) .align 256 /* 0x5e00: Lower-Privilege Transfer Trap vector */ TRAP(34) .align 256 /* 0x5f00: Taken Branch Trap vector */ TRAP(35) .align 256 /* 0x6000: Single Step Trap vector */ TRAP(36) .align 256 /* 0x6100: Reserved */ TRAP(37) .align 256 /* 0x6200: Reserved */ TRAP(38) .align 256 /* 0x6300: Reserved */ TRAP(39) .align 256 /* 0x6400: Reserved */ TRAP(40) .align 256 /* 0x6500: Reserved */ TRAP(41) .align 256 /* 0x6600: Reserved */ TRAP(42) .align 256 /* 0x6700: Reserved */ TRAP(43) .align 256 /* 0x6800: Reserved */ TRAP(44) .align 256 /* 0x6900: IA-32 Exception vector */ TRAP(45) .align 256 /* 0x6a00: IA-32 Intercept vector */ TRAP(46) .align 256 /* 0x6b00: IA-32 Interrupt vector */ TRAP(47) .align 256 /* 0x6c00: Reserved */ TRAP(48) .align 256 /* 0x6d00: Reserved */ TRAP(49) .align 256 /* 0x6e00: Reserved */ TRAP(50) .align 256 /* 0x6f00: Reserved */ TRAP(51) .align 256 /* 0x7000: Reserved */ TRAP(52) .align 256 /* 0x7100: Reserved */ TRAP(53) .align 256 /* 0x7200: Reserved */ TRAP(54) .align 256 /* 0x7300: Reserved */ TRAP(55) .align 256 /* 0x7400: Reserved */ TRAP(56) .align 256 /* 0x7500: Reserved */ TRAP(57) .align 256 /* 0x7600: Reserved */ TRAP(58) .align 256 /* 0x7700: Reserved */ TRAP(59) .align 256 /* 0x7800: Reserved */ TRAP(60) .align 256 /* 0x7900: Reserved */ TRAP(61) .align 256 /* 0x7a00: Reserved */ TRAP(62) .align 256 /* 0x7b00: Reserved */ TRAP(63) .align 256 /* 0x7c00: Reserved */ TRAP(64) .align 256 /* 0x7d00: Reserved */ TRAP(65) .align 256 /* 0x7e00: Reserved */ TRAP(66) .align 256 /* 0x7f00: Reserved */ TRAP(67) .align 256 .section .data.vhpt,"aw" .global ia64_vhpt .align 32768 ia64_vhpt: .quad 0 .align 32768 .text #define rIIP r31 #define rIPSR r30 #define rISR r29 #define rIFA r28 #define rPR r27 #define rSP r26 #define rIFS r25 #define rR1 r24 #define rR2 r23 #define rBSPSTORE r22 #define rRNAT r21 #define rNDIRTY r27 /* overlay rPR */ #define rRSC r20 #define rPFS r19 #define rB0 r31 /* overlay rIIP */ /* * exception_restore: restore interrupted state * * Arguments: * sp+16 trapframe pointer * r4 ar.pfs before the alloc in TRAP() * */ ENTRY(exception_restore, 0) rsm psr.ic|psr.dt|psr.i // disable interrupt collection and vm add r3=16,sp; ;; srlz.d dep r3=0,r3,61,3 // physical address ;; add r16=TF_CR_IPSR,r3 ;; ld8 rIPSR=[r16] ;; extr.u r16=rIPSR,32,2 // extract ipsr.cpl ;; cmp.eq p1,p2=r0,r16 // test for return to kernel mode ;; (p2) add r16=SIZEOF_TRAPFRAME+16,sp // restore ar.k6 (kernel sp) ;; (p2) mov ar.k6=r16 add r1=SIZEOF_TRAPFRAME-16,r3 // r1=&tf_f[FRAME_F15] add r2=SIZEOF_TRAPFRAME-32,r3 // r2=&tf_f[FRAME_F14] ;; ldf.fill f15=[r1],-32 // r1=&tf_f[FRAME_F13] ldf.fill f14=[r2],-32 // r2=&tf_f[FRAME_F12] ;; ldf.fill f13=[r1],-32 // r1=&tf_f[FRAME_F11] ldf.fill f12=[r2],-32 // r2=&tf_f[FRAME_F10] ;; ldf.fill f11=[r1],-32 // r1=&tf_f[FRAME_F9] ldf.fill f10=[r2],-32 // r2=&tf_f[FRAME_F8] ;; ldf.fill f9=[r1],-32 // r1=&tf_f[FRAME_F7] ldf.fill f8=[r2],-32 // r2=&tf_f[FRAME_F6] ;; - ldf.fill f7=[r1],-32 // r1=&tf_r[FRAME_R31] - ldf.fill f6=[r2],-24 // r2=&tf_r[FRAME_R30] + ldf.fill f7=[r1],-24 // r1=&tf_r[FRAME_R31] + ldf.fill f6=[r2],-16 // r2=&tf_r[FRAME_R30] ;; ld8.fill r31=[r1],-16 // r1=&tf_r[FRAME_R29] ld8.fill r30=[r2],-16 // r2=&tf_r[FRAME_R28] ;; ld8.fill r29=[r1],-16 // r1=&tf_r[FRAME_R27] ld8.fill r28=[r2],-16 // r2=&tf_r[FRAME_R26] ;; ld8.fill r27=[r1],-16 // r1=&tf_r[FRAME_R25] ld8.fill r26=[r2],-16 // r2=&tf_r[FRAME_R24] ;; ld8.fill r25=[r1],-16 // r1=&tf_r[FRAME_R23] ld8.fill r24=[r2],-16 // r2=&tf_r[FRAME_R22] ;; ld8.fill r23=[r1],-16 // r1=&tf_r[FRAME_R21] ld8.fill r22=[r2],-16 // r2=&tf_r[FRAME_R20] ;; ld8.fill r21=[r1],-16 // r1=&tf_r[FRAME_R19] ld8.fill r20=[r2],-16 // r2=&tf_r[FRAME_R18] ;; ld8.fill r19=[r1],-16 // r1=&tf_r[FRAME_R17] ld8.fill r18=[r2],-16 // r2=&tf_r[FRAME_R16] ;; ld8.fill r17=[r1],-16 // r1=&tf_r[FRAME_R15] ld8.fill r16=[r2],-16 // r2=&tf_r[FRAME_R14] ;; bsw.0 // switch to bank 0 ;; ld8.fill r15=[r1],-16 // r1=&tf_r[FRAME_R13] ld8.fill r14=[r2],-16 // r2=&tf_r[FRAME_R12] ;; ld8.fill r13=[r1],-16 // r1=&tf_r[FRAME_R11] ld8.fill r12=[r2],-16 // r2=&tf_r[FRAME_R10] ;; ld8.fill r11=[r1],-16 // r1=&tf_r[FRAME_R9] ld8.fill r10=[r2],-16 // r2=&tf_r[FRAME_R8] ;; ld8.fill r9=[r1],-16 // r1=&tf_r[FRAME_R7] ld8.fill r8=[r2],-16 // r2=&tf_r[FRAME_R6] ;; ld8.fill r7=[r1],-16 // r1=&tf_r[FRAME_R5] ld8.fill r6=[r2],-16 // r2=&tf_r[FRAME_R4] ;; ld8.fill r5=[r1],-16 // r1=&tf_r[FRAME_R3] ld8.fill r4=[r2],-16 // r2=&tf_r[FRAME_R2] ;; ld8.fill r3=[r1],-16 // r1=&tf_r[FRAME_R1] ld8.fill rR2=[r2],-16 // r2=&tf_b[7] ;; ld8.fill rR1=[r1],-16 // r1=&tf_b[6] ld8 r16=[r2],-16 // r2=&tf_b[5] ;; mov b7=r16 ld8 r18=[r1],-16 // r1=&tf_b[4] ld8 r19=[r2],-16 // r2=&tf_b[3] ;; mov b6=r18 mov b5=r19 ld8 r16=[r1],-16 // r1=&tf_b[2] ld8 r17=[r2],-16 // r2=&tf_b[1] ;; mov b4=r16 mov b3=r17 ld8 r18=[r1],-16 // r1=&tf_b[0] ld8 r19=[r2],-16 // r2=&tf_ar_fpsr ;; mov b2=r18 mov b1=r19 ld8 r16=[r1],-16 // r1=&tf_ar_ccv ld8 r17=[r2],-16 // r2=&tf_ar_unat ;; mov b0=r16 mov ar.fpsr=r17 ld8 r18=[r1],-16 // r1=&tf_ndirty ld8 r19=[r2],-16 // r2=&tf_ar_rnat ;; mov ar.ccv=r18 mov ar.unat=r19 ld8 rNDIRTY=[r1],-16 // r1=&tf_ar_bspstore ld8 rRNAT=[r2],-16 // r2=&tf_cr_ifs ;; ld8 rBSPSTORE=[r1],-16 // r1=&tf_cr_pfs ld8 rIFS=[r2],-16 // r2=&tf_ar_rsc ;; (p1) br.cond.dpnt.few 1f // don't switch bs if kernel ;; alloc r16=ar.pfs,0,0,0,0 // discard current frame ;; shl r16=rNDIRTY,16 // value for ar.rsc ;; mov ar.rsc=r16 // setup for loadrs ;; loadrs // load user regs from kernel bs ;; mov ar.bspstore=rBSPSTORE ;; mov ar.rnat=rRNAT ;; 1: ld8 rPFS=[r1],-16 // r1=&tf_pr ld8 rRSC=[r2],-16 // r2=&tf_cr_ifa ;; ld8 rPR=[r1],-16 // r1=&tf_cr_isr ld8 rIFA=[r2],-16 // r2=&tf_cr_ipsr ;; ld8 rISR=[r1],-16 // r1=&tf_cr_iip ld8 rIPSR=[r2] ;; ld8 rIIP=[r1] ;; mov r1=rR1 mov r2=rR2 mov ar.pfs=rPFS mov cr.ifs=rIFS mov ar.rsc=rRSC mov pr=rPR,0x1ffff mov cr.ifa=rIFA mov cr.iip=rIIP mov cr.ipsr=rIPSR ;; rfi END(exception_restore) /* * exception_save: save interrupted state * * Arguments: * b0 return address * r16 saved b0 * * Return: * r14 cr.iim value for break traps * sp kernel stack pointer * p1 true if user mode * p2 true if kernel mode * p3 true if interrupts were enabled */ ENTRY(exception_save, 0) rsm psr.dt // turn off data translations ;; srlz.d // serialize ;; mov rIIP=cr.iip mov rIPSR=cr.ipsr mov rISR=cr.isr mov rIFA=cr.ifa mov rPR=pr ;; tbit.nz p3,p0=rIPSR,14 // check for interrupt enable state extr.u r17=rIPSR,32,2 // extract ipsr.cpl ;; cmp.eq p1,p2=r0,r17 // test for kernel mode ;; mov rSP=sp // save sp ;; (p2) mov sp=ar.k6 // and switch to kernel stack ;; add sp=-SIZEOF_TRAPFRAME,sp // reserve trapframe mov rR1=r1 mov rR2=r2 ;; - dep r1=0,sp,61,3 // r1=&tf_cr_iip + dep r1=0,sp,61,3 // r1=&tf_flags ;; - add r2=8,r1 // r2=&tf_cr_ipsr + add r2=16,r1 // r2=&tf_cr_ipsr + st8 [r1]=r0,8 // zero flags, r1=&tf_cr_iip ;; st8 [r1]=rIIP,16 // r1=&tf_cr_isr st8 [r2]=rIPSR,16 // r2=&tf_cr_ifa ;; st8 [r1]=rISR,16 // r1=&tf_pr st8 [r2]=rIFA,16 // r2=&tf_ar_rsc ;; st8 [r1]=rPR,16 // r1=&tf_cr_pfs mov rB0=r16 mov rRSC=ar.rsc mov rPFS=ar.pfs cover mov rIFS=cr.ifs ;; mov ar.rsc=0 ;; mov rBSPSTORE=ar.bspstore ;; (p2) mov r16=ar.k5 // kernel backing store mov rRNAT=ar.rnat ;; (p2) mov ar.bspstore=r16 // switch bspstore st8 [r2]=rRSC,16 // r2=&tf_cr_ifs ;; st8 [r1]=rPFS,16 // r1=&tf_ar_bspstore st8 [r2]=rIFS,16 // r2=&tf_ar_rnat (p2) mov r17=ar.bsp ;; (p2) sub r17=r17,r16 // ndirty (in bytes) (p1) mov r17=r0 ;; st8 [r1]=rBSPSTORE,16 // r1=&tf_ndirty st8 [r2]=rRNAT,16 // r2=&tf_ar_unat ;; st8 [r1]=r17,16 // r1=&tf_ar_ccv mov ar.rsc=3 // switch RSE back on mov r16=ar.unat ;; mov r17=ar.ccv st8 [r2]=r16,16 // r2=&tf_ar_fpsr mov r18=ar.fpsr ;; st8 [r1]=r17,16 // r1=&tf_b[0] st8 [r2]=r18,16 // r2=&tf_b[1] mov r17=b1 ;; st8 [r1]=rB0,16 // r1=&tf_b[2] mov r18=b2 st8 [r2]=r17,16 // r2=&tf_b[3] ;; mov r17=b3 st8 [r1]=r18,16 // r1=&tf_b[4] ;; mov r18=b4 st8 [r2]=r17,16 // r2=&tf_b[5] ;; mov r17=b5 st8 [r1]=r18,16 // r1=&tf_b[6] ;; mov r18=b6 st8 [r2]=r17,16 // r2=&tf_b[7] ;; mov r17=b7 st8 [r1]=r18,16 // r1=&tf_r[FRAME_R1] ;; st8 [r2]=r17,16 // r2=&tf_r[FRAME_R2] ;; .mem.offset 0,0 st8.spill [r1]=rR1,16 // r1=&tf_r[FRAME_R3] .mem.offset 8,0 st8.spill [r2]=rR2,16 // r2=&tf_r[FRAME_R4] ;; .mem.offset 0,0 st8.spill [r1]=r3,16 // r1=&tf_r[FRAME_R5] .mem.offset 8,0 st8.spill [r2]=r4,16 // r2=&tf_r[FRAME_R6] ;; .mem.offset 0,0 st8.spill [r1]=r5,16 // r1=&tf_r[FRAME_R7] .mem.offset 8,0 st8.spill [r2]=r6,16 // r2=&tf_r[FRAME_R8] ;; .mem.offset 0,0 st8.spill [r1]=r7,16 // r1=&tf_r[FRAME_R9] .mem.offset 8,0 st8.spill [r2]=r8,16 // r2=&tf_r[FRAME_R10] ;; .mem.offset 0,0 st8.spill [r1]=r9,16 // r1=&tf_r[FRAME_R11] .mem.offset 8,0 st8.spill [r2]=r10,16 // r2=&tf_r[FRAME_SP] ;; .mem.offset 0,0 st8.spill [r1]=r11,16 // r1=&tf_r[FRAME_R13] .mem.offset 8,0 st8.spill [r2]=rSP,16 // r2=&tf_r[FRAME_R14] ;; .mem.offset 0,0 st8.spill [r1]=r13,16 // r1=&tf_r[FRAME_R15] .mem.offset 8,0 st8.spill [r2]=r14,16 // r2=&tf_r[FRAME_R16] ;; .mem.offset 0,0 st8.spill [r1]=r15,16 // r1=&tf_r[FRAME_R17] ;; bsw.1 // switch to bank 1 ;; .mem.offset 8,0 st8.spill [r2]=r16,16 // r2=&tf_r[FRAME_R18] .mem.offset 0,0 st8.spill [r1]=r17,16 // r1=&tf_r[FRAME_R19] ;; .mem.offset 8,0 st8.spill [r2]=r18,16 // r2=&tf_r[FRAME_R20] .mem.offset 0,0 st8.spill [r1]=r19,16 // r1=&tf_r[FRAME_R21] ;; .mem.offset 8,0 st8.spill [r2]=r20,16 // r2=&tf_r[FRAME_R22] .mem.offset 0,0 st8.spill [r1]=r21,16 // r1=&tf_r[FRAME_R23] ;; .mem.offset 8,0 st8.spill [r2]=r22,16 // r2=&tf_r[FRAME_R24] .mem.offset 0,0 st8.spill [r1]=r23,16 // r1=&tf_r[FRAME_R25] ;; .mem.offset 8,0 st8.spill [r2]=r24,16 // r2=&tf_r[FRAME_R26] .mem.offset 0,0 st8.spill [r1]=r25,16 // r1=&tf_r[FRAME_R27] ;; .mem.offset 8,0 st8.spill [r2]=r26,16 // r2=&tf_r[FRAME_R28] .mem.offset 0,0 st8.spill [r1]=r27,16 // r1=&tf_r[FRAME_R29] ;; .mem.offset 8,0 st8.spill [r2]=r28,16 // r2=&tf_r[FRAME_R30] .mem.offset 0,0 st8.spill [r1]=r29,16 // r1=&tf_r[FRAME_R31] ;; .mem.offset 8,0 - st8.spill [r2]=r30,24 // r2=&tf_f[FRAME_F6] + st8.spill [r2]=r30,16 // r2=&tf_f[FRAME_F6] .mem.offset 0,0 - st8.spill [r1]=r31,32 // r1=&tf_f[FRAME_F7] + st8.spill [r1]=r31,24 // r1=&tf_f[FRAME_F7] ;; stf.spill [r2]=f6,32 // r2=&tf_f[FRAME_F8] stf.spill [r1]=f7,32 // r1=&tf_f[FRAME_F9] ;; stf.spill [r2]=f8,32 // r2=&tf_f[FRAME_F10] stf.spill [r1]=f9,32 // r1=&tf_f[FRAME_F11] ;; stf.spill [r2]=f10,32 // r2=&tf_f[FRAME_F12] stf.spill [r1]=f11,32 // r1=&tf_f[FRAME_F13] ;; stf.spill [r2]=f12,32 // r2=&tf_f[FRAME_F14] stf.spill [r1]=f13,32 // r1=&tf_f[FRAME_F15] ;; stf.spill [r2]=f14 // stf.spill [r1]=f15 // ;; movl r1=__gp // kernel globals mov r13=ar.k4 // processor globals mov r14=cr.iim // break immediate ssm psr.ic|psr.dt // enable interrupts & translation ;; srlz.d // serialize br.sptk.few b0 // not br.ret - we were not br.call'ed END(exception_save) /* * System call entry point (via Break Instruction vector). * * Arguments: * r16 saved predicates */ ENTRY(do_syscall, 0) rsm psr.dt // physical addressing for a moment mov r17=sp;; // save user sp srlz.d // serialize psr.dt mov sp=ar.k6;; // switch to kernel sp add sp=-SIZEOF_TRAPFRAME,sp;; // reserve trapframe dep r30=0,sp,61,3;; // physical address - add r31=8,r30;; // secondary pointer + add r31=16,r30;; // secondary pointer // save minimal state for syscall mov r18=cr.iip mov r19=cr.ipsr mov r20=cr.isr + mov r21=FRAME_SYSCALL ;; + st8 [r30]=r21,8 + ;; st8 [r30]=r18,16 // save cr.iip st8 [r31]=r19,16 // save cr.ipsr ;; st8 [r30]=r20,16 // save cr.isr add r31=16,r31 // skip cr.ifa mov r18=ar.rsc mov r19=ar.pfs ;; st8 [r30]=r16,16 // save pr st8 [r31]=r18,16 // save ar.rsc mov ar.rsc=0 // turn off rse ;; st8 [r30]=r19,16 // save ar.pfs add r31=16,r31 // skip cr.ifs mov r20=ar.bspstore mov r21=ar.rnat mov r22=ar.k5 ;; mov ar.bspstore=r22 // switch to kernel backing store ;; mov r23=ar.bsp // calculate ndirty ;; ;; st8 [r30]=r20,16 // save ar.bspstore st8 [r31]=r21,16 // save ar.rnat sub r16=r23,r22 // bytes of dirty regs mov r18=ar.unat ;; st8 [r30]=r16,16 // save ndirty st8 [r31]=r18,16 // save ar.unat mov r20=ar.ccv mov r21=ar.fpsr ;; st8 [r30]=r20,16 // save ar.ccv st8 [r31]=r21,16 // save ar.fpsr mov r16=b0 ;; - st8 [r30]=r16,TF_R-TF_B+FRAME_SP*8 // save b0, r1=&tf_r[FRAME_SP] + st8 [r30]=r16,TF_R-TF_B+FRAME_R4*8 // save b0, r1=&tf_r[FRAME_SP] ;; + st8.spill [r30]=r4,8 // save r4 + ;; + st8.spill [r30]=r5,8 // save r5 + ;; + st8.spill [r30]=r6,8 // save r6 + ;; + st8.spill [r30]=r7,(FRAME_SP-FRAME_R7)*8 // save r7 + ;; st8 [r30]=r17 // save user sp ;; bsw.1 // switch back to bank 1 ;; mov r18=sp // trapframe pointer ;; add sp=-(8*8),sp // reserve stack for arguments ;; br.call.sptk.few b0=Lsaveargs // dump args ;; mov r31=sp // point at args mov r20=ar.bsp // record bsp before the cover ;; cover // preserve arguments ;; mov r22=cr.ifs // record user's CFM add r23=TF_CR_IFS,r18 ;; ssm psr.dt|psr.ic|psr.i // safe to take interrupts again ;; srlz.d // serialize psr.dt and psr.ic ;; st8 [r23]=r22 // save cr.ifs ;; mov r21=ar.bsp // r21-r20 = size of user reg frame add r22=TF_NDIRTY,r18 ;; sub r20=r21,r20 ld8 r23=[r22] ;; add r23=r23,r20 // adjust ndirty ;; st8 [r22]=r23 ;; add sp=-16,sp // reserve scratch space alloc r14=ar.pfs,0,3,3,0 mov r13=ar.k4 // processor globals ;; mov loc0=r15 // save in case of restarts mov loc1=r18 // save so we can restore mov loc2=gp // save user gp mov out0=r15 // syscall number (from user) mov out1=r31 // arguments mov out2=r18 // trapframe pointer ;; movl gp=__gp // kernel globals ;; br.call.sptk.many rp=syscall // do the work - cmp.eq p6,p0=59,loc0 // do a full restore for execve + ld8 r14=[loc1] // check tf_flags ;; -(p6) add sp=-16,loc1 + tbit.z p6,p0=r14,0 // check FRAME_SYSCALL bit +(p6) add sp=-16,loc1 // do a full restore if clear (p6) br.dpnt.many exception_restore rsm psr.dt|psr.ic|psr.i // get ready to restore ;; srlz.d // serialise psr.dt and psr.ic dep r30=0,loc1,61,3 // physical address mov gp=loc2 // restore user gp add r16=SIZEOF_TRAPFRAME,loc1 ;; mov ar.k6=r16 // restore kernel sp add r30=TF_R+FRAME_SP*8,r30 // &tf_r[FRAME_SP] mov r15=loc0 // saved syscall number alloc r14=ar.pfs,0,0,0,0 // discard register frame ;; ld8 sp=[r30],-16 // restore user sp ;; ld8 r10=[r30],-8 // ret2 ;; ld8 r9=[r30],-8 // ret1 ;; ld8 r8=[r30],-(TF_R+7*8-TF_B) // ret0 ;; ld8 r16=[r30],-16 // restore b0 ;; mov b0=r16 add r31=8,r30 // secondary pointer, &tf_fpsr ;; ld8 r16=[r31],-16 // restore ar.fpsr ld8 r17=[r30],-16 // restore ar.ccv ;; ld8 r18=[r31],-16 // restore ar.unat ld8 r19=[r30],-16 // restore ndirty mov ar.fpsr=r16 mov ar.ccv=r17 ;; ld8 r16=[r31],-16 // restore ar.rnat ld8 r17=[r30],-16 // restore ar.bspstore mov ar.unat=r18 ;; shl r19=r19,16 // value for ar.rsc ;; mov ar.rsc=r19 // setup for loadrs ;; loadrs // restore user registers ;; mov ar.bspstore=r17 ;; mov ar.rnat=r16 ld8 r18=[r31],-16 // restore cr.ifs ld8 r19=[r30],-16 // restore ar.pfs ;; ld8 r16=[r31],-32 // restore ar.rsc ld8 r17=[r30],-32 // restore pr mov cr.ifs=r18 mov ar.pfs=r19 ;; ld8 r18=[r31],-16 // restore cr.ipsr ld8 r19=[r30],-16 // restore cr.iip mov ar.rsc=r16 mov pr=r16,0x1ffff ;; mov cr.ipsr=r18 mov cr.iip=r19 ;; rfi // This is done as a function call to make sure that we only // have output registers in the register frame. It also gives // us a chance to use alloc to round up to 8 arguments for // simplicity. // // We are still running in physical mode with psr.ic==0 because // we haven't yet covered the user's register frame to get a // value for cr.ifs Lsaveargs: alloc r14=ar.pfs,0,0,8,0 // round up to 8 outputs ;; extr.u r31=sp,0,61 // physical address ;; st8 [r31]=r32,8 st8 [r31]=r33,8 st8 [r31]=r34,8 st8 [r31]=r35,8 st8 [r31]=r36,8 st8 [r31]=r37,8 st8 [r31]=r38,8 st8 [r31]=r39 ;; br.ret.sptk.many b0 END(do_syscall) Index: head/sys/ia64/ia64/exception.s =================================================================== --- head/sys/ia64/ia64/exception.s (revision 67521) +++ head/sys/ia64/ia64/exception.s (revision 67522) @@ -1,1449 +1,1462 @@ /*- * Copyright (c) 2000 Doug Rabson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include /* * ar.k7 = curproc * ar.k6 = ksp * ar.k5 = kbsp * ar.k4 = globalp */ /* * Call exception_save_regs to preserve the interrupted state in a * trapframe. Note that we don't use a call instruction because we * must be careful not to lose track of the RSE state. We then call * trap() with the value of _n_ as an argument to handle the * exception. We arrange for trap() to return to exception_restore * which will restore the interrupted state before executing an rfi to * resume it. */ #define TRAP(_n_) \ mov r16=b0; \ 1: mov r17=ip;; \ add r17=2f-1b,r17;; \ mov b0=r17; \ br.sptk.few exception_save; \ 2: (p3) ssm psr.i; \ alloc r15=ar.pfs,0,0,3,0; \ mov out0=_n_; \ mov out1=r14; \ mov out2=sp;; \ add sp=-16,sp;; \ br.call.sptk.few rp=trap; \ 3: br.sptk.many exception_restore /* * The IA64 Interrupt Vector Table (IVT) contains 20 slots with 64 * bundles per vector and 48 slots with 16 bundles per vector. */ .section .text.ivt,"ax" .align 32768 .global ia64_vector_table ia64_vector_table: /* 0x0000: VHPT Translation vector */ TRAP(0) .align 1024 /* 0x0400: Instruction TLB vector */ mov r16=cr.ifa mov r17=pr ;; thash r18=r16 ttag r19=r16 ;; add r21=16,r18 // tag add r20=24,r18 // collision chain ;; ld8 r21=[r21] // check VHPT tag ;; cmp.eq p1,p2=r21,r19 (p2) br.dpnt.few 1f ;; ld8 r21=[r18] // read pte ;; itc.i r21 // insert pte rfi // done ;; 1: ld8 r20=[r20] // first entry ;; rsm psr.dt // turn off data translations ;; srlz.d // serialize ;; 2: cmp.eq p1,p2=r0,r20 // done? (p1) br.cond.spnt.few 9f // bail if done ;; add r21=16,r20 // tag location ;; ld8 r21=[r21] // read tag ;; cmp.eq p1,p2=r21,r19 // compare tags (p2) br.cond.sptk.few 3f // if not, read next in chain ;; ld8 r21=[r20],8 // read pte ;; ld8 r22=[r20] // read rest of pte ;; dep r18=0,r18,61,3 // convert vhpt ptr to physical ;; add r20=16,r18 // address of tag ;; ld8.acq r23=[r20] // read old tag movl r24=(1<<63) // ti bit ;; or r23=r23,r24 // set ti bit ;; st8.rel [r20]=r23 // store old tag + ti ;; mf // make sure everyone sees ;; st8 [r18]=r21,8 // store pte ;; st8 [r18]=r22,8 ;; st8.rel [r18]=r19 // store new tag ;; mov pr=r17,0x1ffff // restore predicates ;; rfi // walker will retry the access 3: add r20=24,r20 // next in chain ;; ld8 r20=[r20] // read chain br.cond.sptk.few 2b // loop 9: mov pr=r17,0x1ffff // restore predicates ssm psr.dt ;; srlz.d ;; TRAP(20) // Page Not Present trap .align 1024 /* 0x0800: Data TLB vector */ mov r16=cr.ifa mov r17=pr ;; thash r18=r16 ttag r19=r16 ;; add r21=16,r18 // tag add r20=24,r18 // collision chain ;; ld8 r21=[r21] // check VHPT tag ;; cmp.eq p1,p2=r21,r19 br.dpnt.few 1f ;; ld8 r21=[r18] // read pte ;; itc.d r21 // insert pte rfi // done ;; 1: ld8 r20=[r20] // first entry ;; rsm psr.dt // turn off data translations ;; srlz.d // serialize ;; 2: cmp.eq p1,p2=r0,r20 // done? (p1) br.cond.spnt.few 9f // bail if done ;; add r21=16,r20 // tag location ;; ld8 r21=[r21] // read tag ;; cmp.eq p1,p2=r21,r19 // compare tags (p2) br.cond.sptk.few 3f // if not, read next in chain ;; ld8 r21=[r20],8 // read pte ;; ld8 r22=[r20] // read rest of pte ;; dep r18=0,r18,61,3 // convert vhpt ptr to physical ;; add r20=16,r18 // address of tag ;; ld8.acq r23=[r20] // read old tag movl r24=(1<<63) // ti bit ;; or r23=r23,r24 // set ti bit ;; st8.rel [r20]=r23 // store old tag + ti ;; mf // make sure everyone sees ;; st8 [r18]=r21,8 // store pte ;; st8 [r18]=r22,8 ;; st8.rel [r18]=r19 // store new tag ;; mov pr=r17,0x1ffff // restore predicates ;; rfi // walker will retry the access 3: add r20=24,r20 // next in chain ;; ld8 r20=[r20] // read chain br.cond.sptk.few 2b // loop 9: mov pr=r17,0x1ffff // restore predicates ssm psr.dt ;; srlz.d ;; TRAP(20) // Page Not Present trap .align 1024 /* 0x0c00: Alternate Instruction TLB vector */ mov r16=cr.ifa // where did it happen ;; mov r18=pr // save predicates ;; extr.u r17=r16,61,3 // get region number ;; cmp.eq p1,p2=7,r17 // RR7->p1, RR6->p2 ;; (p1) movl r17=PTE_P+PTE_MA_WB+PTE_A+PTE_D+PTE_PL_KERN+PTE_AR_RX (p2) movl r17=PTE_P+PTE_MA_UC+PTE_A+PTE_D+PTE_PL_KERN+PTE_AR_RX ;; dep r16=0,r16,50,14 // clear bits above PPN ;; dep r16=r17,r17,0,12 // put pte bits in 0..11 ;; itc.i r16 mov pr=r18,0x1ffff // restore predicates ;; rfi .align 1024 /* 0x1000: Alternate Data TLB vector */ mov r16=cr.ifa // where did it happen mov r18=pr // save predicates ;; extr.u r17=r16,61,3 // get region number ;; cmp.eq p1,p2=7,r17 // RR7->p1, RR6->p2 ;; (p1) movl r17=PTE_P+PTE_MA_WB+PTE_A+PTE_D+PTE_PL_KERN+PTE_AR_RW (p2) movl r17=PTE_P+PTE_MA_UC+PTE_A+PTE_D+PTE_PL_KERN+PTE_AR_RW ;; dep r16=0,r16,50,14 // clear bits above PPN ;; dep r16=r17,r17,0,12 // put pte bits in 0..11 ;; itc.d r16 mov pr=r18,0x1ffff // restore predicates ;; rfi .align 1024 /* 0x1400: Data Nested TLB vector */ TRAP(5) .align 1024 /* 0x1800: Instruction Key Miss vector */ TRAP(6) .align 1024 /* 0x1c00: Data Key Miss vector */ TRAP(7) .align 1024 /* 0x2000: Dirty-Bit vector */ mov r16=cr.ifa mov r17=pr mov r20=12<<2 // XXX get page size from VHPT ;; ptc.l r16,r20 // purge TLB thash r18=r16 ttag r19=r16 ;; srlz.d add r20=24,r18 // collision chain ;; ld8 r20=[r20] // first entry ;; rsm psr.dt // turn off data translations ;; srlz.d // serialize ;; 1: cmp.eq p1,p2=r0,r20 // done? (p1) br.cond.spnt.few 9f // bail if done ;; add r21=16,r20 // tag location ;; ld8 r21=[r21] // read tag ;; cmp.eq p1,p2=r21,r19 // compare tags (p2) br.cond.sptk.few 2f // if not, read next in chain ;; ld8 r21=[r20] // read pte mov r22=PTE_D ;; or r21=r22,r21 // set dirty bit ;; st8 [r20]=r21 // store back ;; ld8 r22=[r20] // read rest of pte ;; dep r18=0,r18,61,3 // convert vhpt ptr to physical ;; add r20=16,r18 // address of tag ;; ld8.acq r23=[r20] // read old tag movl r24=(1<<63) // ti bit ;; or r23=r23,r24 // set ti bit ;; st8.rel [r20]=r23 // store old tag + ti ;; mf // make sure everyone sees ;; st8 [r18]=r21,8 // store pte ;; st8 [r18]=r22,8 ;; st8.rel [r18]=r19 // store new tag ;; mov pr=r17,0x1ffff // restore predicates ;; rfi // walker will retry the access 2: add r20=24,r20 // next in chain ;; ld8 r20=[r20] // read chain br.cond.sptk.few 1b // loop 9: mov pr=r17,0x1ffff // restore predicates TRAP(8) // die horribly .align 1024 /* 0x2400: Instruction Access-Bit vector */ mov r16=cr.ifa mov r17=pr mov r20=12<<2 // XXX get page size from VHPT ;; ptc.l r16,r20 // purge TLB thash r18=r16 ttag r19=r16 ;; srlz.d add r20=24,r18 // collision chain ;; ld8 r20=[r20] // first entry ;; rsm psr.dt // turn off data translations ;; srlz.d // serialize ;; 1: cmp.eq p1,p2=r0,r20 // done? (p1) br.cond.spnt.few 9f // bail if done ;; add r21=16,r20 // tag location ;; ld8 r21=[r21] // read tag ;; cmp.eq p1,p2=r21,r19 // compare tags (p2) br.cond.sptk.few 2f // if not, read next in chain ;; ld8 r21=[r20] // read pte mov r22=PTE_A ;; or r21=r22,r21 // set accessed bit ;; st8 [r20]=r21 // store back ;; ld8 r22=[r20] // read rest of pte ;; dep r18=0,r18,61,3 // convert vhpt ptr to physical ;; add r20=16,r18 // address of tag ;; ld8.acq r23=[r20] // read old tag movl r24=(1<<63) // ti bit ;; or r23=r23,r24 // set ti bit ;; st8.rel [r20]=r23 // store old tag + ti ;; mf // make sure everyone sees ;; st8 [r18]=r21,8 // store pte ;; st8 [r18]=r22,8 ;; st8.rel [r18]=r19 // store new tag ;; mov pr=r17,0x1ffff // restore predicates ;; rfi // walker will retry the access 2: add r20=24,r20 // next in chain ;; ld8 r20=[r20] // read chain br.cond.sptk.few 1b // loop 9: mov pr=r17,0x1ffff // restore predicates TRAP(9) .align 1024 /* 0x2800: Data Access-Bit vector */ mov r16=cr.ifa mov r17=pr mov r20=12<<2 // XXX get page size from VHPT ;; ptc.l r16,r20 // purge TLB thash r18=r16 ttag r19=r16 ;; srlz.d add r20=24,r18 // collision chain ;; ld8 r20=[r20] // first entry ;; rsm psr.dt // turn off data translations ;; srlz.d // serialize ;; 1: cmp.eq p1,p2=r0,r20 // done? (p1) br.cond.spnt.few 9f // bail if done ;; add r21=16,r20 // tag location ;; ld8 r21=[r21] // read tag ;; cmp.eq p1,p2=r21,r19 // compare tags (p2) br.cond.sptk.few 2f // if not, read next in chain ;; ld8 r21=[r20] // read pte mov r22=PTE_A ;; or r21=r22,r21 // set accessed bit ;; st8 [r20]=r21 // store back ;; ld8 r22=[r20] // read rest of pte ;; dep r18=0,r18,61,3 // convert vhpt ptr to physical ;; add r20=16,r18 // address of tag ;; ld8.acq r23=[r20] // read old tag movl r24=(1<<63) // ti bit ;; or r23=r23,r24 // set ti bit ;; st8.rel [r20]=r23 // store old tag + ti ;; mf // make sure everyone sees ;; st8 [r18]=r21,8 // store pte ;; st8 [r18]=r22,8 ;; st8.rel [r18]=r19 // store new tag ;; mov pr=r17,0x1ffff // restore predicates ;; rfi // walker will retry the access 2: add r20=24,r20 // next in chain ;; ld8 r20=[r20] // read chain br.cond.sptk.few 1b // loop 9: mov pr=r17,0x1ffff // restore predicates TRAP(10) .align 1024 /* 0x2c00: Break Instruction vector */ mov r16=pr // save pr for a moment mov r17=cr.iim;; // read break value mov r18=0x100000;; // syscall number cmp.eq p1,p2=r18,r17;; // check for syscall (p2) br.dpnt.few 9f mov r17=cr.ipsr;; // check for user mode extr.u r17=r17,32,2;; cmp.eq p1,p2=r0,r17 (p1) br.dpnt.few 9f // trap if kernel mode br.sptk.many do_syscall ;; 9: mov pr=r16,0x1ffff // restore pr TRAP(11) .align 1024 /* 0x3000: External Interrupt vector */ mov r16=b0 // save user's b0 1: mov r17=ip;; // construct return address add r17=2f-1b,r17;; // for exception_save mov b0=r17 br.sptk.few exception_save // 'call' exception_save 2: alloc r14=ar.pfs,0,0,2,0 // make a frame for calling with mov out1=sp;; add sp=-16,sp;; 3: mov out0=cr.ivr // find interrupt vector ;; cmp.eq p6,p0=15,out0 // check for spurious vector number (p6) br.dpnt.few exception_restore // if spurious, we are done ;; ssm psr.i // re-enable interrupts ;; // now that we are in-progress srlz.d ;; br.call.sptk.many rp=interrupt // call high-level handler rsm psr.i // disable interrupts ;; srlz.d ;; mov cr.eoi=r0 // and ack the interrupt ;; srlz.d br.sptk.few 3b // loop for more .align 1024 /* 0x3400: Reserved */ TRAP(13) .align 1024 /* 0x3800: Reserved */ TRAP(14) .align 1024 /* 0x3c00: Reserved */ TRAP(15) .align 1024 /* 0x4000: Reserved */ TRAP(16) .align 1024 /* 0x4400: Reserved */ TRAP(17) .align 1024 /* 0x4800: Reserved */ TRAP(18) .align 1024 /* 0x4c00: Reserved */ TRAP(19) .align 1024 /* 0x5000: Page Not Present vector */ TRAP(20) .align 256 /* 0x5100: Key Permission vector */ TRAP(21) .align 256 /* 0x5200: Instruction Access Rights vector */ TRAP(22) .align 256 /* 0x5300: Data Access Rights vector */ TRAP(23) .align 256 /* 0x5400: General Exception vector */ TRAP(24) .align 256 /* 0x5500: Disabled FP-Register vector */ TRAP(25) .align 256 /* 0x5600: NaT Consumption vector */ TRAP(26) .align 256 /* 0x5700: Speculation vector */ TRAP(27) .align 256 /* 0x5800: Reserved */ TRAP(28) .align 256 /* 0x5900: Debug vector */ TRAP(29) .align 256 /* 0x5a00: Unaligned Reference vector */ TRAP(30) .align 256 /* 0x5b00: Unsupported Data Reference vector */ TRAP(31) .align 256 /* 0x5c00: Floating-point Fault vector */ TRAP(32) .align 256 /* 0x5d00: Floating-point Trap vector */ TRAP(33) .align 256 /* 0x5e00: Lower-Privilege Transfer Trap vector */ TRAP(34) .align 256 /* 0x5f00: Taken Branch Trap vector */ TRAP(35) .align 256 /* 0x6000: Single Step Trap vector */ TRAP(36) .align 256 /* 0x6100: Reserved */ TRAP(37) .align 256 /* 0x6200: Reserved */ TRAP(38) .align 256 /* 0x6300: Reserved */ TRAP(39) .align 256 /* 0x6400: Reserved */ TRAP(40) .align 256 /* 0x6500: Reserved */ TRAP(41) .align 256 /* 0x6600: Reserved */ TRAP(42) .align 256 /* 0x6700: Reserved */ TRAP(43) .align 256 /* 0x6800: Reserved */ TRAP(44) .align 256 /* 0x6900: IA-32 Exception vector */ TRAP(45) .align 256 /* 0x6a00: IA-32 Intercept vector */ TRAP(46) .align 256 /* 0x6b00: IA-32 Interrupt vector */ TRAP(47) .align 256 /* 0x6c00: Reserved */ TRAP(48) .align 256 /* 0x6d00: Reserved */ TRAP(49) .align 256 /* 0x6e00: Reserved */ TRAP(50) .align 256 /* 0x6f00: Reserved */ TRAP(51) .align 256 /* 0x7000: Reserved */ TRAP(52) .align 256 /* 0x7100: Reserved */ TRAP(53) .align 256 /* 0x7200: Reserved */ TRAP(54) .align 256 /* 0x7300: Reserved */ TRAP(55) .align 256 /* 0x7400: Reserved */ TRAP(56) .align 256 /* 0x7500: Reserved */ TRAP(57) .align 256 /* 0x7600: Reserved */ TRAP(58) .align 256 /* 0x7700: Reserved */ TRAP(59) .align 256 /* 0x7800: Reserved */ TRAP(60) .align 256 /* 0x7900: Reserved */ TRAP(61) .align 256 /* 0x7a00: Reserved */ TRAP(62) .align 256 /* 0x7b00: Reserved */ TRAP(63) .align 256 /* 0x7c00: Reserved */ TRAP(64) .align 256 /* 0x7d00: Reserved */ TRAP(65) .align 256 /* 0x7e00: Reserved */ TRAP(66) .align 256 /* 0x7f00: Reserved */ TRAP(67) .align 256 .section .data.vhpt,"aw" .global ia64_vhpt .align 32768 ia64_vhpt: .quad 0 .align 32768 .text #define rIIP r31 #define rIPSR r30 #define rISR r29 #define rIFA r28 #define rPR r27 #define rSP r26 #define rIFS r25 #define rR1 r24 #define rR2 r23 #define rBSPSTORE r22 #define rRNAT r21 #define rNDIRTY r27 /* overlay rPR */ #define rRSC r20 #define rPFS r19 #define rB0 r31 /* overlay rIIP */ /* * exception_restore: restore interrupted state * * Arguments: * sp+16 trapframe pointer * r4 ar.pfs before the alloc in TRAP() * */ ENTRY(exception_restore, 0) rsm psr.ic|psr.dt|psr.i // disable interrupt collection and vm add r3=16,sp; ;; srlz.d dep r3=0,r3,61,3 // physical address ;; add r16=TF_CR_IPSR,r3 ;; ld8 rIPSR=[r16] ;; extr.u r16=rIPSR,32,2 // extract ipsr.cpl ;; cmp.eq p1,p2=r0,r16 // test for return to kernel mode ;; (p2) add r16=SIZEOF_TRAPFRAME+16,sp // restore ar.k6 (kernel sp) ;; (p2) mov ar.k6=r16 add r1=SIZEOF_TRAPFRAME-16,r3 // r1=&tf_f[FRAME_F15] add r2=SIZEOF_TRAPFRAME-32,r3 // r2=&tf_f[FRAME_F14] ;; ldf.fill f15=[r1],-32 // r1=&tf_f[FRAME_F13] ldf.fill f14=[r2],-32 // r2=&tf_f[FRAME_F12] ;; ldf.fill f13=[r1],-32 // r1=&tf_f[FRAME_F11] ldf.fill f12=[r2],-32 // r2=&tf_f[FRAME_F10] ;; ldf.fill f11=[r1],-32 // r1=&tf_f[FRAME_F9] ldf.fill f10=[r2],-32 // r2=&tf_f[FRAME_F8] ;; ldf.fill f9=[r1],-32 // r1=&tf_f[FRAME_F7] ldf.fill f8=[r2],-32 // r2=&tf_f[FRAME_F6] ;; - ldf.fill f7=[r1],-32 // r1=&tf_r[FRAME_R31] - ldf.fill f6=[r2],-24 // r2=&tf_r[FRAME_R30] + ldf.fill f7=[r1],-24 // r1=&tf_r[FRAME_R31] + ldf.fill f6=[r2],-16 // r2=&tf_r[FRAME_R30] ;; ld8.fill r31=[r1],-16 // r1=&tf_r[FRAME_R29] ld8.fill r30=[r2],-16 // r2=&tf_r[FRAME_R28] ;; ld8.fill r29=[r1],-16 // r1=&tf_r[FRAME_R27] ld8.fill r28=[r2],-16 // r2=&tf_r[FRAME_R26] ;; ld8.fill r27=[r1],-16 // r1=&tf_r[FRAME_R25] ld8.fill r26=[r2],-16 // r2=&tf_r[FRAME_R24] ;; ld8.fill r25=[r1],-16 // r1=&tf_r[FRAME_R23] ld8.fill r24=[r2],-16 // r2=&tf_r[FRAME_R22] ;; ld8.fill r23=[r1],-16 // r1=&tf_r[FRAME_R21] ld8.fill r22=[r2],-16 // r2=&tf_r[FRAME_R20] ;; ld8.fill r21=[r1],-16 // r1=&tf_r[FRAME_R19] ld8.fill r20=[r2],-16 // r2=&tf_r[FRAME_R18] ;; ld8.fill r19=[r1],-16 // r1=&tf_r[FRAME_R17] ld8.fill r18=[r2],-16 // r2=&tf_r[FRAME_R16] ;; ld8.fill r17=[r1],-16 // r1=&tf_r[FRAME_R15] ld8.fill r16=[r2],-16 // r2=&tf_r[FRAME_R14] ;; bsw.0 // switch to bank 0 ;; ld8.fill r15=[r1],-16 // r1=&tf_r[FRAME_R13] ld8.fill r14=[r2],-16 // r2=&tf_r[FRAME_R12] ;; ld8.fill r13=[r1],-16 // r1=&tf_r[FRAME_R11] ld8.fill r12=[r2],-16 // r2=&tf_r[FRAME_R10] ;; ld8.fill r11=[r1],-16 // r1=&tf_r[FRAME_R9] ld8.fill r10=[r2],-16 // r2=&tf_r[FRAME_R8] ;; ld8.fill r9=[r1],-16 // r1=&tf_r[FRAME_R7] ld8.fill r8=[r2],-16 // r2=&tf_r[FRAME_R6] ;; ld8.fill r7=[r1],-16 // r1=&tf_r[FRAME_R5] ld8.fill r6=[r2],-16 // r2=&tf_r[FRAME_R4] ;; ld8.fill r5=[r1],-16 // r1=&tf_r[FRAME_R3] ld8.fill r4=[r2],-16 // r2=&tf_r[FRAME_R2] ;; ld8.fill r3=[r1],-16 // r1=&tf_r[FRAME_R1] ld8.fill rR2=[r2],-16 // r2=&tf_b[7] ;; ld8.fill rR1=[r1],-16 // r1=&tf_b[6] ld8 r16=[r2],-16 // r2=&tf_b[5] ;; mov b7=r16 ld8 r18=[r1],-16 // r1=&tf_b[4] ld8 r19=[r2],-16 // r2=&tf_b[3] ;; mov b6=r18 mov b5=r19 ld8 r16=[r1],-16 // r1=&tf_b[2] ld8 r17=[r2],-16 // r2=&tf_b[1] ;; mov b4=r16 mov b3=r17 ld8 r18=[r1],-16 // r1=&tf_b[0] ld8 r19=[r2],-16 // r2=&tf_ar_fpsr ;; mov b2=r18 mov b1=r19 ld8 r16=[r1],-16 // r1=&tf_ar_ccv ld8 r17=[r2],-16 // r2=&tf_ar_unat ;; mov b0=r16 mov ar.fpsr=r17 ld8 r18=[r1],-16 // r1=&tf_ndirty ld8 r19=[r2],-16 // r2=&tf_ar_rnat ;; mov ar.ccv=r18 mov ar.unat=r19 ld8 rNDIRTY=[r1],-16 // r1=&tf_ar_bspstore ld8 rRNAT=[r2],-16 // r2=&tf_cr_ifs ;; ld8 rBSPSTORE=[r1],-16 // r1=&tf_cr_pfs ld8 rIFS=[r2],-16 // r2=&tf_ar_rsc ;; (p1) br.cond.dpnt.few 1f // don't switch bs if kernel ;; alloc r16=ar.pfs,0,0,0,0 // discard current frame ;; shl r16=rNDIRTY,16 // value for ar.rsc ;; mov ar.rsc=r16 // setup for loadrs ;; loadrs // load user regs from kernel bs ;; mov ar.bspstore=rBSPSTORE ;; mov ar.rnat=rRNAT ;; 1: ld8 rPFS=[r1],-16 // r1=&tf_pr ld8 rRSC=[r2],-16 // r2=&tf_cr_ifa ;; ld8 rPR=[r1],-16 // r1=&tf_cr_isr ld8 rIFA=[r2],-16 // r2=&tf_cr_ipsr ;; ld8 rISR=[r1],-16 // r1=&tf_cr_iip ld8 rIPSR=[r2] ;; ld8 rIIP=[r1] ;; mov r1=rR1 mov r2=rR2 mov ar.pfs=rPFS mov cr.ifs=rIFS mov ar.rsc=rRSC mov pr=rPR,0x1ffff mov cr.ifa=rIFA mov cr.iip=rIIP mov cr.ipsr=rIPSR ;; rfi END(exception_restore) /* * exception_save: save interrupted state * * Arguments: * b0 return address * r16 saved b0 * * Return: * r14 cr.iim value for break traps * sp kernel stack pointer * p1 true if user mode * p2 true if kernel mode * p3 true if interrupts were enabled */ ENTRY(exception_save, 0) rsm psr.dt // turn off data translations ;; srlz.d // serialize ;; mov rIIP=cr.iip mov rIPSR=cr.ipsr mov rISR=cr.isr mov rIFA=cr.ifa mov rPR=pr ;; tbit.nz p3,p0=rIPSR,14 // check for interrupt enable state extr.u r17=rIPSR,32,2 // extract ipsr.cpl ;; cmp.eq p1,p2=r0,r17 // test for kernel mode ;; mov rSP=sp // save sp ;; (p2) mov sp=ar.k6 // and switch to kernel stack ;; add sp=-SIZEOF_TRAPFRAME,sp // reserve trapframe mov rR1=r1 mov rR2=r2 ;; - dep r1=0,sp,61,3 // r1=&tf_cr_iip + dep r1=0,sp,61,3 // r1=&tf_flags ;; - add r2=8,r1 // r2=&tf_cr_ipsr + add r2=16,r1 // r2=&tf_cr_ipsr + st8 [r1]=r0,8 // zero flags, r1=&tf_cr_iip ;; st8 [r1]=rIIP,16 // r1=&tf_cr_isr st8 [r2]=rIPSR,16 // r2=&tf_cr_ifa ;; st8 [r1]=rISR,16 // r1=&tf_pr st8 [r2]=rIFA,16 // r2=&tf_ar_rsc ;; st8 [r1]=rPR,16 // r1=&tf_cr_pfs mov rB0=r16 mov rRSC=ar.rsc mov rPFS=ar.pfs cover mov rIFS=cr.ifs ;; mov ar.rsc=0 ;; mov rBSPSTORE=ar.bspstore ;; (p2) mov r16=ar.k5 // kernel backing store mov rRNAT=ar.rnat ;; (p2) mov ar.bspstore=r16 // switch bspstore st8 [r2]=rRSC,16 // r2=&tf_cr_ifs ;; st8 [r1]=rPFS,16 // r1=&tf_ar_bspstore st8 [r2]=rIFS,16 // r2=&tf_ar_rnat (p2) mov r17=ar.bsp ;; (p2) sub r17=r17,r16 // ndirty (in bytes) (p1) mov r17=r0 ;; st8 [r1]=rBSPSTORE,16 // r1=&tf_ndirty st8 [r2]=rRNAT,16 // r2=&tf_ar_unat ;; st8 [r1]=r17,16 // r1=&tf_ar_ccv mov ar.rsc=3 // switch RSE back on mov r16=ar.unat ;; mov r17=ar.ccv st8 [r2]=r16,16 // r2=&tf_ar_fpsr mov r18=ar.fpsr ;; st8 [r1]=r17,16 // r1=&tf_b[0] st8 [r2]=r18,16 // r2=&tf_b[1] mov r17=b1 ;; st8 [r1]=rB0,16 // r1=&tf_b[2] mov r18=b2 st8 [r2]=r17,16 // r2=&tf_b[3] ;; mov r17=b3 st8 [r1]=r18,16 // r1=&tf_b[4] ;; mov r18=b4 st8 [r2]=r17,16 // r2=&tf_b[5] ;; mov r17=b5 st8 [r1]=r18,16 // r1=&tf_b[6] ;; mov r18=b6 st8 [r2]=r17,16 // r2=&tf_b[7] ;; mov r17=b7 st8 [r1]=r18,16 // r1=&tf_r[FRAME_R1] ;; st8 [r2]=r17,16 // r2=&tf_r[FRAME_R2] ;; .mem.offset 0,0 st8.spill [r1]=rR1,16 // r1=&tf_r[FRAME_R3] .mem.offset 8,0 st8.spill [r2]=rR2,16 // r2=&tf_r[FRAME_R4] ;; .mem.offset 0,0 st8.spill [r1]=r3,16 // r1=&tf_r[FRAME_R5] .mem.offset 8,0 st8.spill [r2]=r4,16 // r2=&tf_r[FRAME_R6] ;; .mem.offset 0,0 st8.spill [r1]=r5,16 // r1=&tf_r[FRAME_R7] .mem.offset 8,0 st8.spill [r2]=r6,16 // r2=&tf_r[FRAME_R8] ;; .mem.offset 0,0 st8.spill [r1]=r7,16 // r1=&tf_r[FRAME_R9] .mem.offset 8,0 st8.spill [r2]=r8,16 // r2=&tf_r[FRAME_R10] ;; .mem.offset 0,0 st8.spill [r1]=r9,16 // r1=&tf_r[FRAME_R11] .mem.offset 8,0 st8.spill [r2]=r10,16 // r2=&tf_r[FRAME_SP] ;; .mem.offset 0,0 st8.spill [r1]=r11,16 // r1=&tf_r[FRAME_R13] .mem.offset 8,0 st8.spill [r2]=rSP,16 // r2=&tf_r[FRAME_R14] ;; .mem.offset 0,0 st8.spill [r1]=r13,16 // r1=&tf_r[FRAME_R15] .mem.offset 8,0 st8.spill [r2]=r14,16 // r2=&tf_r[FRAME_R16] ;; .mem.offset 0,0 st8.spill [r1]=r15,16 // r1=&tf_r[FRAME_R17] ;; bsw.1 // switch to bank 1 ;; .mem.offset 8,0 st8.spill [r2]=r16,16 // r2=&tf_r[FRAME_R18] .mem.offset 0,0 st8.spill [r1]=r17,16 // r1=&tf_r[FRAME_R19] ;; .mem.offset 8,0 st8.spill [r2]=r18,16 // r2=&tf_r[FRAME_R20] .mem.offset 0,0 st8.spill [r1]=r19,16 // r1=&tf_r[FRAME_R21] ;; .mem.offset 8,0 st8.spill [r2]=r20,16 // r2=&tf_r[FRAME_R22] .mem.offset 0,0 st8.spill [r1]=r21,16 // r1=&tf_r[FRAME_R23] ;; .mem.offset 8,0 st8.spill [r2]=r22,16 // r2=&tf_r[FRAME_R24] .mem.offset 0,0 st8.spill [r1]=r23,16 // r1=&tf_r[FRAME_R25] ;; .mem.offset 8,0 st8.spill [r2]=r24,16 // r2=&tf_r[FRAME_R26] .mem.offset 0,0 st8.spill [r1]=r25,16 // r1=&tf_r[FRAME_R27] ;; .mem.offset 8,0 st8.spill [r2]=r26,16 // r2=&tf_r[FRAME_R28] .mem.offset 0,0 st8.spill [r1]=r27,16 // r1=&tf_r[FRAME_R29] ;; .mem.offset 8,0 st8.spill [r2]=r28,16 // r2=&tf_r[FRAME_R30] .mem.offset 0,0 st8.spill [r1]=r29,16 // r1=&tf_r[FRAME_R31] ;; .mem.offset 8,0 - st8.spill [r2]=r30,24 // r2=&tf_f[FRAME_F6] + st8.spill [r2]=r30,16 // r2=&tf_f[FRAME_F6] .mem.offset 0,0 - st8.spill [r1]=r31,32 // r1=&tf_f[FRAME_F7] + st8.spill [r1]=r31,24 // r1=&tf_f[FRAME_F7] ;; stf.spill [r2]=f6,32 // r2=&tf_f[FRAME_F8] stf.spill [r1]=f7,32 // r1=&tf_f[FRAME_F9] ;; stf.spill [r2]=f8,32 // r2=&tf_f[FRAME_F10] stf.spill [r1]=f9,32 // r1=&tf_f[FRAME_F11] ;; stf.spill [r2]=f10,32 // r2=&tf_f[FRAME_F12] stf.spill [r1]=f11,32 // r1=&tf_f[FRAME_F13] ;; stf.spill [r2]=f12,32 // r2=&tf_f[FRAME_F14] stf.spill [r1]=f13,32 // r1=&tf_f[FRAME_F15] ;; stf.spill [r2]=f14 // stf.spill [r1]=f15 // ;; movl r1=__gp // kernel globals mov r13=ar.k4 // processor globals mov r14=cr.iim // break immediate ssm psr.ic|psr.dt // enable interrupts & translation ;; srlz.d // serialize br.sptk.few b0 // not br.ret - we were not br.call'ed END(exception_save) /* * System call entry point (via Break Instruction vector). * * Arguments: * r16 saved predicates */ ENTRY(do_syscall, 0) rsm psr.dt // physical addressing for a moment mov r17=sp;; // save user sp srlz.d // serialize psr.dt mov sp=ar.k6;; // switch to kernel sp add sp=-SIZEOF_TRAPFRAME,sp;; // reserve trapframe dep r30=0,sp,61,3;; // physical address - add r31=8,r30;; // secondary pointer + add r31=16,r30;; // secondary pointer // save minimal state for syscall mov r18=cr.iip mov r19=cr.ipsr mov r20=cr.isr + mov r21=FRAME_SYSCALL ;; + st8 [r30]=r21,8 + ;; st8 [r30]=r18,16 // save cr.iip st8 [r31]=r19,16 // save cr.ipsr ;; st8 [r30]=r20,16 // save cr.isr add r31=16,r31 // skip cr.ifa mov r18=ar.rsc mov r19=ar.pfs ;; st8 [r30]=r16,16 // save pr st8 [r31]=r18,16 // save ar.rsc mov ar.rsc=0 // turn off rse ;; st8 [r30]=r19,16 // save ar.pfs add r31=16,r31 // skip cr.ifs mov r20=ar.bspstore mov r21=ar.rnat mov r22=ar.k5 ;; mov ar.bspstore=r22 // switch to kernel backing store ;; mov r23=ar.bsp // calculate ndirty ;; ;; st8 [r30]=r20,16 // save ar.bspstore st8 [r31]=r21,16 // save ar.rnat sub r16=r23,r22 // bytes of dirty regs mov r18=ar.unat ;; st8 [r30]=r16,16 // save ndirty st8 [r31]=r18,16 // save ar.unat mov r20=ar.ccv mov r21=ar.fpsr ;; st8 [r30]=r20,16 // save ar.ccv st8 [r31]=r21,16 // save ar.fpsr mov r16=b0 ;; - st8 [r30]=r16,TF_R-TF_B+FRAME_SP*8 // save b0, r1=&tf_r[FRAME_SP] + st8 [r30]=r16,TF_R-TF_B+FRAME_R4*8 // save b0, r1=&tf_r[FRAME_SP] ;; + st8.spill [r30]=r4,8 // save r4 + ;; + st8.spill [r30]=r5,8 // save r5 + ;; + st8.spill [r30]=r6,8 // save r6 + ;; + st8.spill [r30]=r7,(FRAME_SP-FRAME_R7)*8 // save r7 + ;; st8 [r30]=r17 // save user sp ;; bsw.1 // switch back to bank 1 ;; mov r18=sp // trapframe pointer ;; add sp=-(8*8),sp // reserve stack for arguments ;; br.call.sptk.few b0=Lsaveargs // dump args ;; mov r31=sp // point at args mov r20=ar.bsp // record bsp before the cover ;; cover // preserve arguments ;; mov r22=cr.ifs // record user's CFM add r23=TF_CR_IFS,r18 ;; ssm psr.dt|psr.ic|psr.i // safe to take interrupts again ;; srlz.d // serialize psr.dt and psr.ic ;; st8 [r23]=r22 // save cr.ifs ;; mov r21=ar.bsp // r21-r20 = size of user reg frame add r22=TF_NDIRTY,r18 ;; sub r20=r21,r20 ld8 r23=[r22] ;; add r23=r23,r20 // adjust ndirty ;; st8 [r22]=r23 ;; add sp=-16,sp // reserve scratch space alloc r14=ar.pfs,0,3,3,0 mov r13=ar.k4 // processor globals ;; mov loc0=r15 // save in case of restarts mov loc1=r18 // save so we can restore mov loc2=gp // save user gp mov out0=r15 // syscall number (from user) mov out1=r31 // arguments mov out2=r18 // trapframe pointer ;; movl gp=__gp // kernel globals ;; br.call.sptk.many rp=syscall // do the work - cmp.eq p6,p0=59,loc0 // do a full restore for execve + ld8 r14=[loc1] // check tf_flags ;; -(p6) add sp=-16,loc1 + tbit.z p6,p0=r14,0 // check FRAME_SYSCALL bit +(p6) add sp=-16,loc1 // do a full restore if clear (p6) br.dpnt.many exception_restore rsm psr.dt|psr.ic|psr.i // get ready to restore ;; srlz.d // serialise psr.dt and psr.ic dep r30=0,loc1,61,3 // physical address mov gp=loc2 // restore user gp add r16=SIZEOF_TRAPFRAME,loc1 ;; mov ar.k6=r16 // restore kernel sp add r30=TF_R+FRAME_SP*8,r30 // &tf_r[FRAME_SP] mov r15=loc0 // saved syscall number alloc r14=ar.pfs,0,0,0,0 // discard register frame ;; ld8 sp=[r30],-16 // restore user sp ;; ld8 r10=[r30],-8 // ret2 ;; ld8 r9=[r30],-8 // ret1 ;; ld8 r8=[r30],-(TF_R+7*8-TF_B) // ret0 ;; ld8 r16=[r30],-16 // restore b0 ;; mov b0=r16 add r31=8,r30 // secondary pointer, &tf_fpsr ;; ld8 r16=[r31],-16 // restore ar.fpsr ld8 r17=[r30],-16 // restore ar.ccv ;; ld8 r18=[r31],-16 // restore ar.unat ld8 r19=[r30],-16 // restore ndirty mov ar.fpsr=r16 mov ar.ccv=r17 ;; ld8 r16=[r31],-16 // restore ar.rnat ld8 r17=[r30],-16 // restore ar.bspstore mov ar.unat=r18 ;; shl r19=r19,16 // value for ar.rsc ;; mov ar.rsc=r19 // setup for loadrs ;; loadrs // restore user registers ;; mov ar.bspstore=r17 ;; mov ar.rnat=r16 ld8 r18=[r31],-16 // restore cr.ifs ld8 r19=[r30],-16 // restore ar.pfs ;; ld8 r16=[r31],-32 // restore ar.rsc ld8 r17=[r30],-32 // restore pr mov cr.ifs=r18 mov ar.pfs=r19 ;; ld8 r18=[r31],-16 // restore cr.ipsr ld8 r19=[r30],-16 // restore cr.iip mov ar.rsc=r16 mov pr=r16,0x1ffff ;; mov cr.ipsr=r18 mov cr.iip=r19 ;; rfi // This is done as a function call to make sure that we only // have output registers in the register frame. It also gives // us a chance to use alloc to round up to 8 arguments for // simplicity. // // We are still running in physical mode with psr.ic==0 because // we haven't yet covered the user's register frame to get a // value for cr.ifs Lsaveargs: alloc r14=ar.pfs,0,0,8,0 // round up to 8 outputs ;; extr.u r31=sp,0,61 // physical address ;; st8 [r31]=r32,8 st8 [r31]=r33,8 st8 [r31]=r34,8 st8 [r31]=r35,8 st8 [r31]=r36,8 st8 [r31]=r37,8 st8 [r31]=r38,8 st8 [r31]=r39 ;; br.ret.sptk.many b0 END(do_syscall) Index: head/sys/ia64/ia64/genassym.c =================================================================== --- head/sys/ia64/ia64/genassym.c (revision 67521) +++ head/sys/ia64/ia64/genassym.c (revision 67522) @@ -1,135 +1,141 @@ /*- * Copyright (c) 1982, 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: @(#)genassym.c 5.11 (Berkeley) 5/10/91 * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include ASSYM(GD_CURPROC, offsetof(struct globaldata, gd_curproc)); ASSYM(GD_FPCURPROC, offsetof(struct globaldata, gd_fpcurproc)); ASSYM(GD_CURPCB, offsetof(struct globaldata, gd_curpcb)); ASSYM(GD_SWITCHTIME, offsetof(struct globaldata, gd_switchtime)); ASSYM(GD_CPUNO, offsetof(struct globaldata, gd_cpuno)); ASSYM(GD_ASTPENDING, offsetof(struct globaldata, gd_astpending)); ASSYM(MTX_LOCK, offsetof(struct mtx, mtx_lock)); ASSYM(MTX_RECURSE, offsetof(struct mtx, mtx_recurse)); ASSYM(MTX_SAVEINTR, offsetof(struct mtx, mtx_saveintr)); ASSYM(MTX_UNOWNED, MTX_UNOWNED); ASSYM(P_ADDR, offsetof(struct proc, p_addr)); ASSYM(P_MD_FLAGS, offsetof(struct proc, p_md.md_flags)); ASSYM(VM_MAXUSER_ADDRESS, VM_MAXUSER_ADDRESS); ASSYM(SIZEOF_USER, sizeof(struct user)); +ASSYM(FRAME_SYSCALL, FRAME_SYSCALL); + ASSYM(TF_CR_IPSR, offsetof(struct trapframe, tf_cr_ipsr)); ASSYM(TF_CR_IFS, offsetof(struct trapframe, tf_cr_ifs)); ASSYM(TF_NDIRTY, offsetof(struct trapframe, tf_ndirty)); ASSYM(TF_B, offsetof(struct trapframe, tf_b)); ASSYM(TF_R, offsetof(struct trapframe, tf_r)); ASSYM(TF_F, offsetof(struct trapframe, tf_f)); +ASSYM(FRAME_R4, FRAME_R4); +ASSYM(FRAME_R5, FRAME_R5); +ASSYM(FRAME_R6, FRAME_R6); +ASSYM(FRAME_R7, FRAME_R7); ASSYM(FRAME_SP, FRAME_SP); ASSYM(U_PCB_R4, offsetof(struct user, u_pcb.pcb_r4)); ASSYM(U_PCB_R5, offsetof(struct user, u_pcb.pcb_r5)); ASSYM(U_PCB_R6, offsetof(struct user, u_pcb.pcb_r6)); ASSYM(U_PCB_R7, offsetof(struct user, u_pcb.pcb_r7)); ASSYM(U_PCB_F2, offsetof(struct user, u_pcb.pcb_f2)); ASSYM(U_PCB_F3, offsetof(struct user, u_pcb.pcb_f3)); ASSYM(U_PCB_F4, offsetof(struct user, u_pcb.pcb_f4)); ASSYM(U_PCB_F5, offsetof(struct user, u_pcb.pcb_f5)); ASSYM(U_PCB_B0, offsetof(struct user, u_pcb.pcb_b0)); ASSYM(U_PCB_B1, offsetof(struct user, u_pcb.pcb_b1)); ASSYM(U_PCB_B2, offsetof(struct user, u_pcb.pcb_b2)); ASSYM(U_PCB_B3, offsetof(struct user, u_pcb.pcb_b3)); ASSYM(U_PCB_B4, offsetof(struct user, u_pcb.pcb_b4)); ASSYM(U_PCB_B5, offsetof(struct user, u_pcb.pcb_b5)); ASSYM(U_PCB_OLD_UNAT, offsetof(struct user, u_pcb.pcb_old_unat)); ASSYM(U_PCB_SP, offsetof(struct user, u_pcb.pcb_sp)); ASSYM(U_PCB_PFS, offsetof(struct user, u_pcb.pcb_pfs)); ASSYM(U_PCB_BSPSTORE, offsetof(struct user, u_pcb.pcb_bspstore)); ASSYM(U_PCB_UNAT, offsetof(struct user, u_pcb.pcb_unat)); ASSYM(U_PCB_RNAT, offsetof(struct user, u_pcb.pcb_rnat)); ASSYM(U_PCB_PR, offsetof(struct user, u_pcb.pcb_pr)); ASSYM(U_PCB_SCHEDNEST, offsetof(struct user, u_pcb.pcb_onfault)); ASSYM(U_PCB_ONFAULT, offsetof(struct user, u_pcb.pcb_onfault)); ASSYM(U_PCB_HIGHFP, offsetof(struct user, u_pcb.pcb_highfp)); ASSYM(UC_MCONTEXT_MC_AR_BSP, offsetof(ucontext_t, uc_mcontext.mc_ar_bsp)); ASSYM(UC_MCONTEXT_MC_AR_RNAT, offsetof(ucontext_t, uc_mcontext.mc_ar_rnat)); ASSYM(EFAULT, EFAULT); ASSYM(ENAMETOOLONG, ENAMETOOLONG); ASSYM(SIZEOF_TRAPFRAME, sizeof(struct trapframe)); Index: head/sys/ia64/ia64/interrupt.c =================================================================== --- head/sys/ia64/ia64/interrupt.c (revision 67521) +++ head/sys/ia64/ia64/interrupt.c (revision 67522) @@ -1,126 +1,126 @@ /* $FreeBSD$ */ /* $NetBSD: interrupt.c,v 1.23 1998/02/24 07:38:01 thorpej Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. * All rights reserved. * * Authors: Keith Bostic, Chris G. Demetriou * * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ /* * Additional Copyright (c) 1997 by Matthew Jacob for NASA/Ames Research Center. * Redistribute and modify at will, leaving only this additional copyright * notice. */ #include "opt_ddb.h" #include /* RCS ID & Copyright macro defns */ /* __KERNEL_RCSID(0, "$NetBSD: interrupt.c,v 1.23 1998/02/24 07:38:01 thorpej Exp $");*/ #include #include #include #include #include #include #include +#include #include #include #include -#include #ifdef EVCNT_COUNTERS struct evcnt clock_intr_evcnt; /* event counter for clock intrs. */ #else #include #endif #ifdef DDB #include #endif volatile int mc_expected, mc_received; static void dummy_perf(unsigned long vector, struct trapframe *framep) { printf("performance interrupt!\n"); } void (*perf_irq)(unsigned long, struct trapframe *) = dummy_perf; static u_int schedclk2; void interrupt(u_int64_t vector, struct trapframe *framep) { atomic_add_int(&PCPU_GET(intr_nesting_level), 1); switch (vector) { case 240: /* clock interrupt */ CTR0(KTR_INTR, "clock interrupt"); mtx_enter(&Giant, MTX_DEF); cnt.v_intr++; #ifdef EVCNT_COUNTERS clock_intr_evcnt.ev_count++; #else intrcnt[INTRCNT_CLOCK]++; #endif handleclock(framep); /* divide hz (1024) by 8 to get stathz (128) */ if((++schedclk2 & 0x7) == 0) statclock((struct clockframe *)framep); mtx_exit(&Giant, MTX_DEF); break; default: mtx_enter(&Giant, MTX_DEF); panic("unexpected interrupt: vec %ld\n", vector); /* NOTREACHED */ } atomic_subtract_int(&PCPU_GET(intr_nesting_level), 1); } int badaddr(addr, size) void *addr; size_t size; { return(badaddr_read(addr, size, NULL)); } int badaddr_read(addr, size, rptr) void *addr; size_t size; void *rptr; { return (1); /* XXX implement */ } Index: head/sys/ia64/ia64/locore.S =================================================================== --- head/sys/ia64/ia64/locore.S (revision 67521) +++ head/sys/ia64/ia64/locore.S (revision 67522) @@ -1,212 +1,215 @@ /*- * Copyright (c) 1998 Doug Rabson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. * All rights reserved. * * Author: Chris G. Demetriou * * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ #include #include #include #include #include #ifndef EVCNT_COUNTERS #define _LOCORE #include #endif .text /* * Not really a leaf but we can't return. */ ENTRY(locorestart, 1) movl r8=ia64_vector_table // set up IVT early movl r9=ia64_vhpt+(1<<8)+(15<<2)+1 // and VHPT ;; mov cr.iva=r8 mov cr.pta=r9 ;; srlz.i ;; srlz.d ;; movl gp=__gp // find kernel globals ;; br.call.sptk.many rp=ia64_init /* * switch to proc0 and then initialise the rest of the kernel. */ alloc r16=ar.pfs,0,0,1,0 ;; movl out0=proc0 ;; add out0=P_ADDR,out0 ;; ld8 out0=[out0] ;; add r16=U_PCB_B0,out0 // return to mi_startup movl r17=mi_startup ;; st8 [r16]=r17 ;; br.call.sptk.many rp=restorectx /* NOTREACHED */ END(locorestart) /**************************************************************************/ /* * Signal "trampoline" code. Invoked from RTE setup by sendsig(). * * On entry, registers look like: * * r14 signal number * r15 pointer to siginfo_t * r16 pointer to signal context frame (scp) * r17 address of handler function descriptor * r18 address of new backing store (if any) * sp+16 pointer to sigframe */ ENTRY(sigcode,0) ld8 r8=[r17],8 // function address ;; ld8 gp=[r17] // function's gp value mov b6=r8 // transfer to a branch register cover ;; alloc r5=ar.pfs,0,0,3,0 // register frame for call ;; mov out0=r14 // signal number add r8=UC_MCONTEXT_MC_AR_BSP,r16 // address or mc_ar_bsp mov r9=ar.bsp // save ar.bsp ;; st8 [r8]=r9 - cmp.eq p1,p0=r0,r18 // check for new bs + cmp.eq p1,p2=r0,r18 // check for new bs (p1) br.cond.sptk.few 1f // branch if not switching flushrs // flush out to old bs mov ar.rsc=0 // switch off RSE add r8=UC_MCONTEXT_MC_AR_RNAT,r16 // address of mc_ar_rnat ;; mov r9=ar.rnat // value of ar.rnat after flush mov ar.bspstore=r18 // point at new bs ;; st8 [r8]=r9 // remember ar.rnat mov ar.rsc=15 // XXX bogus value - check invala ;; 1: mov out1=r15 // siginfo mov out2=r16 // ucontext - mov r4=r17 // save ucontext pointer from call + mov r4=r16 // save from call br.call.sptk.few rp=b6 // call the signal handler + ;; (p1) br.cond.sptk.few 2f // note: p1 is preserved flushrs mov ar.rsc=0 add r8=UC_MCONTEXT_MC_AR_RNAT,r4 // address of mc_ar_rnat ;; ld8 r9=[r8] ;; add r8=UC_MCONTEXT_MC_AR_BSP,r4 // address of mc_ar_bsp ;; ld8 r10=[r8] ;; mov ar.bspstore=r10 ;; mov ar.rnat=r9 mov ar.rsc=15 -2: - CALLSYS_NOERROR(sigreturn) // and call sigreturn() with it. + +2: alloc r14=ar.pfs,0,0,0,0 // no frame for sigreturn + CALLSYS_NOERROR(sigreturn) // call sigreturn() + alloc r14=ar.pfs,0,0,1,0 ;; mov out0=ret0 // if that failed, get error code CALLSYS_NOERROR(exit) // and call exit() with it. XENTRY(esigcode) END(sigcode) .data EXPORT(szsigcode) .quad esigcode-sigcode .text /* * When starting init, call this to configure the process for user * mode. This will be inherited by other processes. */ ENTRY_NOPROFILE(prepare_usermode, 0) END(prepare_usermode) .data EXPORT(proc0paddr) .quad 0 .text /* XXX: make systat/vmstat happy */ .data EXPORT(intrnames) .asciz "clock" intr_n = 0 .rept INTRCNT_COUNT .ascii "intr " .byte intr_n / 10 + '0, intr_n % 10 + '0 .asciz " " /* space for platform-specific rewrite */ intr_n = intr_n + 1 .endr EXPORT(eintrnames) .align 8 EXPORT(intrcnt) .fill INTRCNT_COUNT + 1, 8, 0 EXPORT(eintrcnt) .text Index: head/sys/ia64/ia64/locore.s =================================================================== --- head/sys/ia64/ia64/locore.s (revision 67521) +++ head/sys/ia64/ia64/locore.s (revision 67522) @@ -1,212 +1,215 @@ /*- * Copyright (c) 1998 Doug Rabson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. * All rights reserved. * * Author: Chris G. Demetriou * * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ #include #include #include #include #include #ifndef EVCNT_COUNTERS #define _LOCORE #include #endif .text /* * Not really a leaf but we can't return. */ ENTRY(locorestart, 1) movl r8=ia64_vector_table // set up IVT early movl r9=ia64_vhpt+(1<<8)+(15<<2)+1 // and VHPT ;; mov cr.iva=r8 mov cr.pta=r9 ;; srlz.i ;; srlz.d ;; movl gp=__gp // find kernel globals ;; br.call.sptk.many rp=ia64_init /* * switch to proc0 and then initialise the rest of the kernel. */ alloc r16=ar.pfs,0,0,1,0 ;; movl out0=proc0 ;; add out0=P_ADDR,out0 ;; ld8 out0=[out0] ;; add r16=U_PCB_B0,out0 // return to mi_startup movl r17=mi_startup ;; st8 [r16]=r17 ;; br.call.sptk.many rp=restorectx /* NOTREACHED */ END(locorestart) /**************************************************************************/ /* * Signal "trampoline" code. Invoked from RTE setup by sendsig(). * * On entry, registers look like: * * r14 signal number * r15 pointer to siginfo_t * r16 pointer to signal context frame (scp) * r17 address of handler function descriptor * r18 address of new backing store (if any) * sp+16 pointer to sigframe */ ENTRY(sigcode,0) ld8 r8=[r17],8 // function address ;; ld8 gp=[r17] // function's gp value mov b6=r8 // transfer to a branch register cover ;; alloc r5=ar.pfs,0,0,3,0 // register frame for call ;; mov out0=r14 // signal number add r8=UC_MCONTEXT_MC_AR_BSP,r16 // address or mc_ar_bsp mov r9=ar.bsp // save ar.bsp ;; st8 [r8]=r9 - cmp.eq p1,p0=r0,r18 // check for new bs + cmp.eq p1,p2=r0,r18 // check for new bs (p1) br.cond.sptk.few 1f // branch if not switching flushrs // flush out to old bs mov ar.rsc=0 // switch off RSE add r8=UC_MCONTEXT_MC_AR_RNAT,r16 // address of mc_ar_rnat ;; mov r9=ar.rnat // value of ar.rnat after flush mov ar.bspstore=r18 // point at new bs ;; st8 [r8]=r9 // remember ar.rnat mov ar.rsc=15 // XXX bogus value - check invala ;; 1: mov out1=r15 // siginfo mov out2=r16 // ucontext - mov r4=r17 // save ucontext pointer from call + mov r4=r16 // save from call br.call.sptk.few rp=b6 // call the signal handler + ;; (p1) br.cond.sptk.few 2f // note: p1 is preserved flushrs mov ar.rsc=0 add r8=UC_MCONTEXT_MC_AR_RNAT,r4 // address of mc_ar_rnat ;; ld8 r9=[r8] ;; add r8=UC_MCONTEXT_MC_AR_BSP,r4 // address of mc_ar_bsp ;; ld8 r10=[r8] ;; mov ar.bspstore=r10 ;; mov ar.rnat=r9 mov ar.rsc=15 -2: - CALLSYS_NOERROR(sigreturn) // and call sigreturn() with it. + +2: alloc r14=ar.pfs,0,0,0,0 // no frame for sigreturn + CALLSYS_NOERROR(sigreturn) // call sigreturn() + alloc r14=ar.pfs,0,0,1,0 ;; mov out0=ret0 // if that failed, get error code CALLSYS_NOERROR(exit) // and call exit() with it. XENTRY(esigcode) END(sigcode) .data EXPORT(szsigcode) .quad esigcode-sigcode .text /* * When starting init, call this to configure the process for user * mode. This will be inherited by other processes. */ ENTRY_NOPROFILE(prepare_usermode, 0) END(prepare_usermode) .data EXPORT(proc0paddr) .quad 0 .text /* XXX: make systat/vmstat happy */ .data EXPORT(intrnames) .asciz "clock" intr_n = 0 .rept INTRCNT_COUNT .ascii "intr " .byte intr_n / 10 + '0, intr_n % 10 + '0 .asciz " " /* space for platform-specific rewrite */ intr_n = intr_n + 1 .endr EXPORT(eintrnames) .align 8 EXPORT(intrcnt) .fill INTRCNT_COUNT + 1, 8, 0 EXPORT(eintrcnt) .text Index: head/sys/ia64/ia64/machdep.c =================================================================== --- head/sys/ia64/ia64/machdep.c (revision 67521) +++ head/sys/ia64/ia64/machdep.c (revision 67522) @@ -1,1338 +1,1377 @@ /*- * Copyright (c) 2000 Doug Rabson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include "opt_compat.h" #include "opt_ddb.h" #include "opt_simos.h" #include "opt_msgbuf.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include u_int64_t cycles_per_usec; u_int32_t cycles_per_sec; int cold = 1; struct bootinfo_kernel bootinfo; struct cpuhead cpuhead; MUTEX_DECLARE( ,sched_lock); MUTEX_DECLARE( ,Giant); struct user *proc0paddr; char machine[] = "ia64"; SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); static char cpu_model[128]; SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, cpu_model, 0, ""); #ifdef DDB /* start and end of kernel symbol table */ void *ksym_start, *ksym_end; #endif int ia64_unaligned_print = 1; /* warn about unaligned accesses */ int ia64_unaligned_fix = 1; /* fix up unaligned accesses */ int ia64_unaligned_sigbus = 0; /* don't SIGBUS on fixed-up accesses */ SYSCTL_INT(_machdep, CPU_UNALIGNED_PRINT, unaligned_print, CTLFLAG_RW, &ia64_unaligned_print, 0, ""); SYSCTL_INT(_machdep, CPU_UNALIGNED_FIX, unaligned_fix, CTLFLAG_RW, &ia64_unaligned_fix, 0, ""); SYSCTL_INT(_machdep, CPU_UNALIGNED_SIGBUS, unaligned_sigbus, CTLFLAG_RW, &ia64_unaligned_sigbus, 0, ""); static void cpu_startup __P((void *)); SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) static MALLOC_DEFINE(M_MBUF, "mbuf", "mbuf"); struct msgbuf *msgbufp=0; int bootverbose = 0, Maxmem = 0; long dumplo; int totalphysmem; /* total amount of physical memory in system */ int physmem; /* physical memory used by NetBSD + some rsvd */ int resvmem; /* amount of memory reserved for PROM */ int unusedmem; /* amount of memory for OS that we don't use */ int unknownmem; /* amount of memory with an unknown use */ int ncpus; /* number of cpus */ vm_offset_t phys_avail[10]; static int sysctl_hw_physmem(SYSCTL_HANDLER_ARGS) { int error = sysctl_handle_int(oidp, 0, ia64_ptob(physmem), req); return (error); } SYSCTL_PROC(_hw, HW_PHYSMEM, physmem, CTLTYPE_INT|CTLFLAG_RD, 0, 0, sysctl_hw_physmem, "I", ""); static int sysctl_hw_usermem(SYSCTL_HANDLER_ARGS) { int error = sysctl_handle_int(oidp, 0, ia64_ptob(physmem - cnt.v_wire_count), req); return (error); } SYSCTL_PROC(_hw, HW_USERMEM, usermem, CTLTYPE_INT|CTLFLAG_RD, 0, 0, sysctl_hw_usermem, "I", ""); SYSCTL_INT(_hw, OID_AUTO, availpages, CTLFLAG_RD, &physmem, 0, ""); /* must be 2 less so 0 0 can signal end of chunks */ #define PHYS_AVAIL_ARRAY_END ((sizeof(phys_avail) / sizeof(vm_offset_t)) - 2) static void identifycpu __P((void)); static vm_offset_t buffer_sva, buffer_eva; vm_offset_t clean_sva, clean_eva; static vm_offset_t pager_sva, pager_eva; #define offsetof(type, member) ((size_t)(&((type *)0)->member)) static void cpu_startup(dummy) void *dummy; { unsigned int i; caddr_t v; vm_offset_t maxaddr; vm_size_t size = 0; vm_offset_t firstaddr; vm_offset_t minaddr; if (boothowto & RB_VERBOSE) bootverbose++; /* * Good {morning,afternoon,evening,night}. */ printf("%s", version); identifycpu(); /* startrtclock(); */ #ifdef PERFMON perfmon_init(); #endif printf("real memory = %ld (%ldK bytes)\n", ia64_ptob(Maxmem), ia64_ptob(Maxmem) / 1024); /* * Display any holes after the first chunk of extended memory. */ if (bootverbose) { int indx; printf("Physical memory chunk(s):\n"); for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) { int size1 = phys_avail[indx + 1] - phys_avail[indx]; printf("0x%08lx - 0x%08lx, %d bytes (%d pages)\n", phys_avail[indx], phys_avail[indx + 1] - 1, size1, size1 / PAGE_SIZE); } } /* * Calculate callout wheel size */ for (callwheelsize = 1, callwheelbits = 0; callwheelsize < ncallout; callwheelsize <<= 1, ++callwheelbits) ; callwheelmask = callwheelsize - 1; /* * Allocate space for system data structures. * The first available kernel virtual address is in "v". * As pages of kernel virtual memory are allocated, "v" is incremented. * As pages of memory are allocated and cleared, * "firstaddr" is incremented. * An index into the kernel page table corresponding to the * virtual memory address maintained in "v" is kept in "mapaddr". */ /* * Make two passes. The first pass calculates how much memory is * needed and allocates it. The second pass assigns virtual * addresses to the various data structures. */ firstaddr = 0; again: v = (caddr_t)firstaddr; #define valloc(name, type, num) \ (name) = (type *)v; v = (caddr_t)((name)+(num)) #define valloclim(name, type, num, lim) \ (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num))) valloc(callout, struct callout, ncallout); valloc(callwheel, struct callout_tailq, callwheelsize); /* * The nominal buffer size (and minimum KVA allocation) is BKVASIZE. * For the first 64MB of ram nominally allocate sufficient buffers to * cover 1/4 of our ram. Beyond the first 64MB allocate additional * buffers to cover 1/20 of our ram over 64MB. */ if (nbuf == 0) { int factor = 4 * BKVASIZE / PAGE_SIZE; nbuf = 50; if (physmem > 1024) nbuf += min((physmem - 1024) / factor, 16384 / factor); if (physmem > 16384) nbuf += (physmem - 16384) * 2 / (factor * 5); } nswbuf = max(min(nbuf/4, 64), 16); valloc(swbuf, struct buf, nswbuf); valloc(buf, struct buf, nbuf); v = bufhashinit(v); /* * End of first pass, size has been calculated so allocate memory */ if (firstaddr == 0) { size = (vm_size_t)(v - firstaddr); firstaddr = (vm_offset_t)kmem_alloc(kernel_map, round_page(size)); if (firstaddr == 0) panic("startup: no room for tables"); goto again; } /* * End of second pass, addresses have been assigned */ if ((vm_size_t)(v - firstaddr) != size) panic("startup: table size inconsistency"); clean_map = kmem_suballoc(kernel_map, &clean_sva, &clean_eva, (nbuf*BKVASIZE) + (nswbuf*MAXPHYS) + pager_map_size); buffer_map = kmem_suballoc(clean_map, &buffer_sva, &buffer_eva, (nbuf*BKVASIZE)); pager_map = kmem_suballoc(clean_map, &pager_sva, &pager_eva, (nswbuf*MAXPHYS) + pager_map_size); pager_map->system_map = 1; exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, (16*(ARG_MAX+(PAGE_SIZE*3)))); /* * Finally, allocate mbuf pool. Since mclrefcnt is an off-size * we use the more space efficient malloc in place of kmem_alloc. */ { vm_offset_t mb_map_size; mb_map_size = nmbufs * MSIZE + nmbclusters * MCLBYTES + (nmbclusters + nmbufs / 4) * sizeof(union mext_refcnt); mb_map_size = roundup2(mb_map_size, max(MCLBYTES, PAGE_SIZE)); mb_map = kmem_suballoc(kmem_map, (vm_offset_t *)&mbutl, &maxaddr, mb_map_size); mb_map->system_map = 1; } /* * Initialize callouts */ SLIST_INIT(&callfree); for (i = 0; i < ncallout; i++) { callout_init(&callout[i]); callout[i].c_flags = CALLOUT_LOCAL_ALLOC; SLIST_INSERT_HEAD(&callfree, &callout[i], c_links.sle); } for (i = 0; i < callwheelsize; i++) { TAILQ_INIT(&callwheel[i]); } #if defined(USERCONFIG) #if defined(USERCONFIG_BOOT) if (1) #else if (boothowto & RB_CONFIG) #endif { userconfig(); cninit(); /* the preferred console may have changed */ } #endif printf("avail memory = %ld (%ldK bytes)\n", ptoa(cnt.v_free_count), ptoa(cnt.v_free_count) / 1024); /* * Set up buffers, so they can be used to read disk labels. */ bufinit(); vm_pager_bufferinit(); } int register_netisr(num, handler) int num; netisr_t *handler; { if (num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs)) ) { printf("register_netisr: bad isr number: %d\n", num); return (EINVAL); } netisrs[num] = handler; return (0); } int unregister_netisr(num) int num; { if (num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs)) ) { printf("unregister_netisr: bad isr number: %d\n", num); return (EINVAL); } netisrs[num] = NULL; return (0); } static void identifycpu(void) { /* print cpu type & version */ } extern char kernel_text[], _end[]; #define DEBUG_MD void ia64_init() { int phys_avail_cnt; vm_offset_t kernstart, kernend; vm_offset_t kernstartpfn, kernendpfn, pfn0, pfn1; char *p; struct efi_memory_descriptor ski_md[2]; /* XXX */ struct efi_memory_descriptor *mdp; int mdcount, i; /* NO OUTPUT ALLOWED UNTIL FURTHER NOTICE */ /* * TODO: Disable interrupts, floating point etc. * Maybe flush cache and tlb */ __asm __volatile("mov ar.fpsr=%0" :: "r"(IA64_FPSR_DEFAULT)); /* * TODO: Get critical system information (if possible, from the * information provided by the boot program). */ /* * Initalize the (temporary) bootstrap console interface, so * we can use printf until the VM system starts being setup. * The real console is initialized before then. * TODO: I guess we start with a serial console here. */ ssccnattach(); /* OUTPUT NOW ALLOWED */ /* * Find the beginning and end of the kernel. */ kernstart = trunc_page(kernel_text); #ifdef DDBxx ksym_start = (void *)bootinfo.ssym; ksym_end = (void *)bootinfo.esym; kernend = (vm_offset_t)round_page(ksym_end); #else kernend = (vm_offset_t)round_page(_end); #endif /* But if the bootstrap tells us otherwise, believe it! */ if (bootinfo.kernend) kernend = round_page(bootinfo.kernend); preload_metadata = (caddr_t)bootinfo.modptr; kern_envp = bootinfo.envp; p = getenv("kernelname"); if (p) strncpy(kernelname, p, sizeof(kernelname) - 1); kernstartpfn = atop(IA64_RR_MASK(kernstart)); kernendpfn = atop(IA64_RR_MASK(kernend)); /* * Size the memory regions and load phys_avail[] with the results. */ /* * XXX hack for ski. In reality, the loader will probably ask * EFI and pass the results to us. Possibly, we will call EFI * directly. */ ski_md[0].emd_type = EFI_CONVENTIONAL_MEMORY; ski_md[0].emd_physical_start = 2L*1024*1024; ski_md[0].emd_virtul_start = 0; ski_md[0].emd_number_of_pages = (64L*1024*1024)>>12; ski_md[0].emd_attribute = EFI_MEMORY_WB; ski_md[1].emd_type = EFI_CONVENTIONAL_MEMORY; ski_md[1].emd_physical_start = 4096L*1024*1024; ski_md[1].emd_virtul_start = 0; ski_md[1].emd_number_of_pages = (32L*1024*1024)>>12; ski_md[1].emd_attribute = EFI_MEMORY_WB; mdcount = 1; /* ignore the high memory for now */ /* * Find out how much memory is available, by looking at * the memory descriptors. */ #ifdef DEBUG_MD printf("Memory descriptor count: %d\n", mdcount); #endif phys_avail_cnt = 0; for (i = 0; i < mdcount; i++) { mdp = &ski_md[i]; #ifdef DEBUG_MD printf("MD %d: type %d pa 0x%lx cnt 0x%lx\n", i, mdp->emd_type, mdp->emd_physical_start, mdp->emd_number_of_pages); #endif totalphysmem += mdp->emd_number_of_pages; if (mdp->emd_type != EFI_CONVENTIONAL_MEMORY) { resvmem += mdp->emd_number_of_pages; continue; } /* * We have a memory descriptors available for system * software use. We must determine if this cluster * holds the kernel. */ physmem += mdp->emd_number_of_pages; pfn0 = atop(mdp->emd_physical_start); pfn1 = pfn0 + mdp->emd_number_of_pages; if (pfn0 <= kernendpfn && kernstartpfn <= pfn1) { /* * Must compute the location of the kernel * within the segment. */ #ifdef DEBUG_MD printf("Descriptor %d contains kernel\n", i); #endif if (pfn0 < kernstartpfn) { /* * There is a chunk before the kernel. */ #ifdef DEBUG_MD printf("Loading chunk before kernel: " "0x%lx / 0x%lx\n", pfn0, kernstartpfn); #endif phys_avail[phys_avail_cnt] = ia64_ptob(pfn0); phys_avail[phys_avail_cnt+1] = ia64_ptob(kernstartpfn); phys_avail_cnt += 2; } if (kernendpfn < pfn1) { /* * There is a chunk after the kernel. */ #ifdef DEBUG_MD printf("Loading chunk after kernel: " "0x%lx / 0x%lx\n", kernendpfn, pfn1); #endif phys_avail[phys_avail_cnt] = ia64_ptob(kernendpfn); phys_avail[phys_avail_cnt+1] = ia64_ptob(pfn1); phys_avail_cnt += 2; } } else { /* * Just load this cluster as one chunk. */ #ifdef DEBUG_MD printf("Loading descriptor %d: 0x%lx / 0x%lx\n", i, pfn0, pfn1); #endif phys_avail[phys_avail_cnt] = ia64_ptob(pfn0); phys_avail[phys_avail_cnt+1] = ia64_ptob(pfn1); phys_avail_cnt += 2; } } phys_avail[phys_avail_cnt] = 0; Maxmem = physmem; /* * Initialize error message buffer (at end of core). */ { size_t sz = round_page(MSGBUF_SIZE); int i = phys_avail_cnt - 2; /* shrink so that it'll fit in the last segment */ if (phys_avail[i+1] - phys_avail[i] < sz) sz = phys_avail[i+1] - phys_avail[i]; phys_avail[i+1] -= sz; msgbufp = (struct msgbuf*) IA64_PHYS_TO_RR7(phys_avail[i+1]); msgbufinit(msgbufp, sz); /* Remove the last segment if it now has no pages. */ if (phys_avail[i] == phys_avail[i+1]) phys_avail[i] = 0; /* warn if the message buffer had to be shrunk */ if (sz != round_page(MSGBUF_SIZE)) printf("WARNING: %ld bytes not available for msgbuf in last cluster (%ld used)\n", round_page(MSGBUF_SIZE), sz); } /* * Init mapping for u page(s) for proc 0 */ proc0paddr = proc0.p_addr = (struct user *)pmap_steal_memory(UPAGES * PAGE_SIZE); /* * Setup the global data for the bootstrap cpu. */ { size_t sz = round_page(UPAGES * PAGE_SIZE); globalp = (struct globaldata *) pmap_steal_memory(sz); globaldata_init(globalp, 0, sz); ia64_set_k4((u_int64_t) globalp); PCPU_GET(next_asn) = 1; /* 0 used for proc0 pmap */ } /* * Initialize the virtual memory system, and set the * page table base register in proc 0's PCB. */ pmap_bootstrap(); /* * Initialize the rest of proc 0's PCB. * * Set the kernel sp, reserving space for an (empty) trapframe, * and make proc0's trapframe pointer point to it for sanity. * Initialise proc0's backing store to start after u area. */ proc0.p_addr->u_pcb.pcb_sp = (u_int64_t)proc0.p_addr + USPACE - sizeof(struct trapframe) - 16; proc0.p_addr->u_pcb.pcb_bspstore = (u_int64_t) (proc0.p_addr + 1); proc0.p_md.md_tf = (struct trapframe *)(proc0.p_addr->u_pcb.pcb_sp + 16); PCPU_SET(curproc, &proc0); /* * Record all cpus in a list. */ SLIST_INIT(&cpuhead); SLIST_INSERT_HEAD(&cpuhead, GLOBALP, gd_allcpu); /* * Initialise mutexes. */ mtx_init(&Giant, "Giant", MTX_DEF | MTX_COLD); mtx_init(&sched_lock, "sched lock", MTX_SPIN | MTX_COLD); #if 0 /* * Enable interrupts on first release (in switch_trampoline). */ sched_lock.mtx_saveipl = ALPHA_PSL_IPL_0; #endif /* * Look at arguments passed to us and compute boothowto. */ boothowto = 0; #ifdef KADB boothowto |= RB_KDB; #endif /* boothowto |= RB_KDB | RB_GDB; */ for (p = bootinfo.boot_flags; p && *p != '\0'; p++) { /* * Note that we'd really like to differentiate case here, * but the Ia64 AXP Architecture Reference Manual * says that we shouldn't. */ switch (*p) { case 'a': /* autoboot */ case 'A': boothowto &= ~RB_SINGLE; break; #ifdef DEBUG case 'c': /* crash dump immediately after autoconfig */ case 'C': boothowto |= RB_DUMP; break; #endif #if defined(DDB) case 'd': /* break into the kernel debugger ASAP */ case 'D': boothowto |= RB_KDB; break; case 'g': /* use kernel gdb */ case 'G': boothowto |= RB_GDB; break; #endif case 'h': /* always halt, never reboot */ case 'H': boothowto |= RB_HALT; break; #if 0 case 'm': /* mini root present in memory */ case 'M': boothowto |= RB_MINIROOT; break; #endif case 'n': /* askname */ case 'N': boothowto |= RB_ASKNAME; break; case 's': /* single-user (default, supported for sanity) */ case 'S': boothowto |= RB_SINGLE; break; case 'v': case 'V': boothowto |= RB_VERBOSE; bootverbose = 1; break; default: printf("Unrecognized boot flag '%c'.\n", *p); break; } } /* * Catch case of boot_verbose set in environment. */ if ((p = getenv("boot_verbose")) != NULL) { if (strcmp(p, "yes") == 0 || strcmp(p, "YES") == 0) { boothowto |= RB_VERBOSE; bootverbose = 1; } } /* * Force single-user for a while. */ boothowto |= RB_SINGLE; /* * Initialize debuggers, and break into them if appropriate. */ #ifdef DDB kdb_init(); if (boothowto & RB_KDB) { printf("Boot flags requested debugger\n"); breakpoint(); } #endif } void bzero(void *buf, size_t len) { caddr_t p = buf; while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) { *p++ = 0; len--; } while (len >= sizeof(u_long) * 8) { *(u_long*) p = 0; *((u_long*) p + 1) = 0; *((u_long*) p + 2) = 0; *((u_long*) p + 3) = 0; len -= sizeof(u_long) * 8; *((u_long*) p + 4) = 0; *((u_long*) p + 5) = 0; *((u_long*) p + 6) = 0; *((u_long*) p + 7) = 0; p += sizeof(u_long) * 8; } while (len >= sizeof(u_long)) { *(u_long*) p = 0; len -= sizeof(u_long); p += sizeof(u_long); } while (len) { *p++ = 0; len--; } } void DELAY(int n) { /* TODO */ } /* * Send an interrupt to process. * * Stack is set up to allow sigcode stored * at top to call routine, followed by kcall * to sigreturn routine below. After sigreturn * resets the signal mask, the stack, and the * frame pointer, it returns to the user * specified pc, psl. */ void sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) { struct proc *p = curproc; struct trapframe *frame; struct sigacts *psp = p->p_sigacts; struct sigframe sf, *sfp; u_int64_t sbs = 0; int oonstack, rndfsize; frame = p->p_md.md_tf; oonstack = (p->p_sigstk.ss_flags & SS_ONSTACK) ? 1 : 0; rndfsize = ((sizeof(sf) + 15) / 16) * 16; + /* + * Make sure that we restore the entire trapframe after a + * signal. + */ + frame->tf_flags &= ~FRAME_SYSCALL; + /* save user context */ bzero(&sf, sizeof(struct sigframe)); sf.sf_uc.uc_sigmask = *mask; sf.sf_uc.uc_stack = p->p_sigstk; sf.sf_uc.uc_mcontext.mc_flags = IA64_MC_FLAG_ONSTACK; - sf.sf_uc.uc_mcontext.mc_nat = 0; /* XXX */ + sf.sf_uc.uc_mcontext.mc_nat = 0; /* XXX */ sf.sf_uc.uc_mcontext.mc_sp = frame->tf_r[FRAME_SP]; - sf.sf_uc.uc_mcontext.mc_ip = frame->tf_cr_iip; - sf.sf_uc.uc_mcontext.mc_cfm = 0; /* XXX */ + sf.sf_uc.uc_mcontext.mc_ip = (frame->tf_cr_iip + | ((frame->tf_cr_ipsr >> 41) & 3)); + sf.sf_uc.uc_mcontext.mc_cfm = frame->tf_cr_ifs & ~(1<<31); sf.sf_uc.uc_mcontext.mc_um = frame->tf_cr_ipsr & 0x1fff; sf.sf_uc.uc_mcontext.mc_ar_rsc = frame->tf_ar_rsc; - sf.sf_uc.uc_mcontext.mc_ar_bsp = (frame->tf_ar_bspstore - + frame->tf_ndirty); + sf.sf_uc.uc_mcontext.mc_ar_bsp = frame->tf_ar_bspstore; sf.sf_uc.uc_mcontext.mc_ar_rnat = frame->tf_ar_rnat; sf.sf_uc.uc_mcontext.mc_ar_ccv = frame->tf_ar_ccv; sf.sf_uc.uc_mcontext.mc_ar_unat = frame->tf_ar_unat; sf.sf_uc.uc_mcontext.mc_ar_fpsr = frame->tf_ar_fpsr; sf.sf_uc.uc_mcontext.mc_ar_pfs = frame->tf_ar_pfs; sf.sf_uc.uc_mcontext.mc_pr = frame->tf_pr; bcopy(&frame->tf_b[0], &sf.sf_uc.uc_mcontext.mc_br[0], 8 * sizeof(unsigned long)); + sf.sf_uc.uc_mcontext.mc_gr[0] = 0; bcopy(&frame->tf_r[0], - &sf.sf_uc.uc_mcontext.mc_gr[0], + &sf.sf_uc.uc_mcontext.mc_gr[1], 31 * sizeof(unsigned long)); /* XXX mc_fr[] */ /* * Allocate and validate space for the signal handler * context. Note that if the stack is in P0 space, the * call to grow() is a nop, and the useracc() check * will fail if the process has not already allocated * the space with a `brk'. */ if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack && SIGISMEMBER(psp->ps_sigonstack, sig)) { sbs = (u_int64_t) p->p_sigstk.ss_sp; sfp = (struct sigframe *)((caddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size - rndfsize); p->p_sigstk.ss_flags |= SS_ONSTACK; + sf.sf_uc.uc_mcontext.mc_onstack |= 1; } else sfp = (struct sigframe *)(frame->tf_r[FRAME_SP] - rndfsize); (void)grow_stack(p, (u_long)sfp); #ifdef DEBUG if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) printf("sendsig(%d): sig %d ssp %p usp %p\n", p->p_pid, sig, &sf, sfp); #endif if (!useracc((caddr_t)sfp, sizeof(sf), VM_PROT_WRITE)) { #ifdef DEBUG if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) printf("sendsig(%d): useracc failed on sig %d\n", p->p_pid, sig); #endif /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ SIGACTION(p, SIGILL) = SIG_DFL; SIGDELSET(p->p_sigignore, SIGILL); SIGDELSET(p->p_sigcatch, SIGILL); SIGDELSET(p->p_sigmask, SIGILL); psignal(p, SIGILL); return; } #if 0 /* save the floating-point state, if necessary, then copy it. */ ia64_fpstate_save(p, 1); sf.sf_uc.uc_mcontext.mc_ownedfp = p->p_md.md_flags & MDP_FPUSED; bcopy(&p->p_addr->u_pcb.pcb_fp, (struct fpreg *)sf.sf_uc.uc_mcontext.mc_fpregs, sizeof(struct fpreg)); sf.sf_uc.uc_mcontext.mc_fp_control = p->p_addr->u_pcb.pcb_fp_control; #endif -#ifdef COMPAT_OSF1 /* - * XXX Create an OSF/1-style sigcontext and associated goo. - */ -#endif - - /* * copy the frame out to userland. */ (void) copyout((caddr_t)&sf, (caddr_t)sfp, sizeof(sf)); #ifdef DEBUG if (sigdebug & SDB_FOLLOW) printf("sendsig(%d): sig %d sfp %p code %lx\n", p->p_pid, sig, sfp, code); #endif /* * Set up the registers to return to sigcode. */ + frame->tf_cr_ipsr &= ~IA64_PSR_RI; frame->tf_cr_iip = PS_STRINGS - (esigcode - sigcode); frame->tf_r[FRAME_R1] = sig; if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { - frame->tf_r[FRAME_R2] = (u_int64_t)&(sfp->sf_si); + frame->tf_r[FRAME_R15] = (u_int64_t)&(sfp->sf_si); /* Fill in POSIX parts */ sf.sf_si.si_signo = sig; sf.sf_si.si_code = code; sf.sf_si.si_addr = (void*)frame->tf_cr_ifa; } else - frame->tf_r[FRAME_R2] = code; + frame->tf_r[FRAME_R15] = code; - frame->tf_r[FRAME_R3] = (u_int64_t)&(sfp->sf_uc); - frame->tf_r[FRAME_R4] = (u_int64_t)catcher; - frame->tf_r[FRAME_R5] = sbs; frame->tf_r[FRAME_SP] = (u_int64_t)sfp - 16; + frame->tf_r[FRAME_R14] = sig; + frame->tf_r[FRAME_R15] = (u_int64_t) &sfp->sf_si; + frame->tf_r[FRAME_R16] = (u_int64_t) &sfp->sf_uc; + frame->tf_r[FRAME_R17] = (u_int64_t)catcher; + frame->tf_r[FRAME_R18] = sbs; #ifdef DEBUG if (sigdebug & SDB_FOLLOW) printf("sendsig(%d): pc %lx, catcher %lx\n", p->p_pid, frame->tf_cr_iip, frame->tf_regs[FRAME_R4]); if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) printf("sendsig(%d): sig %d returns\n", p->p_pid, sig); #endif } /* * System call to cleanup state after a signal * has been taken. Reset signal mask and * stack state from context left by sendsig (above). * Return to previous pc and psl as specified by * context left by sendsig. Check carefully to * make sure that the user has not modified the * state to gain improper privileges. */ int osigreturn(struct proc *p, struct osigreturn_args /* { struct osigcontext *sigcntxp; } */ *uap) { return EOPNOTSUPP; } /* * System call to cleanup state after a signal * has been taken. Reset signal mask and * stack state from context left by sendsig (above). * Return to previous pc and psl as specified by * context left by sendsig. Check carefully to * make sure that the user has not modified the * state to gain improper privileges. */ int sigreturn(struct proc *p, struct sigreturn_args /* { ucontext_t *sigcntxp; } */ *uap) { -#if 0 ucontext_t uc, *ucp; struct pcb *pcb; - unsigned long val; + struct trapframe *frame = p->p_md.md_tf; + struct __mcontext *mcp; ucp = uap->sigcntxp; pcb = &p->p_addr->u_pcb; #ifdef DEBUG if (sigdebug & SDB_FOLLOW) printf("sigreturn: pid %d, scp %p\n", p->p_pid, ucp); #endif /* * Fetch the entire context structure at once for speed. + * We don't use a normal argument to simplify RSE handling. */ - if (copyin((caddr_t)ucp, (caddr_t)&uc, sizeof(ucontext_t))) + if (copyin((caddr_t)frame->tf_r[FRAME_R4], + (caddr_t)&uc, sizeof(ucontext_t))) return (EFAULT); /* * Restore the user-supplied information */ - set_regs(p, (struct reg *)uc.uc_mcontext.mc_regs); - val = (uc.uc_mcontext.mc_regs[R_PS] | IA64_PSL_USERSET) & - ~IA64_PSL_USERCLR; - p->p_md.md_tf->tf_regs[FRAME_PS] = val; - p->p_md.md_tf->tf_regs[FRAME_PC] = uc.uc_mcontext.mc_regs[R_PC]; - ia64_pal_wrusp(uc.uc_mcontext.mc_regs[R_SP]); + mcp = &uc.uc_mcontext; + bcopy(&mcp->mc_br[0], &frame->tf_b[0], 8*sizeof(u_int64_t)); + bcopy(&mcp->mc_gr[1], &frame->tf_r[0], 31*sizeof(u_int64_t)); + /* XXX mc_fr */ + frame->tf_flags &= ~FRAME_SYSCALL; + frame->tf_cr_iip = mcp->mc_ip & ~15; + frame->tf_cr_ipsr &= ~IA64_PSR_RI; + switch (mcp->mc_ip & 15) { + case 1: + frame->tf_cr_ipsr |= IA64_PSR_RI_1; + break; + case 2: + frame->tf_cr_ipsr |= IA64_PSR_RI_2; + break; + } + frame->tf_cr_ipsr = ((frame->tf_cr_ipsr & ~0x1fff) + | (mcp->mc_um & 0x1fff)); + frame->tf_pr = mcp->mc_pr; + frame->tf_ar_rsc = (mcp->mc_ar_rsc & 3) | 12; /* user, loadrs=0 */ + frame->tf_ar_pfs = mcp->mc_ar_pfs; + frame->tf_cr_ifs = mcp->mc_cfm | (1UL<<63); + frame->tf_ar_bspstore = mcp->mc_ar_bsp; + frame->tf_ar_rnat = mcp->mc_ar_rnat; + frame->tf_ndirty = 0; /* assumes flushrs in sigcode */ + frame->tf_ar_unat = mcp->mc_ar_unat; + frame->tf_ar_ccv = mcp->mc_ar_ccv; + frame->tf_ar_fpsr = mcp->mc_ar_fpsr; + + frame->tf_r[FRAME_SP] = mcp->mc_sp; + if (uc.uc_mcontext.mc_onstack & 1) p->p_sigstk.ss_flags |= SS_ONSTACK; else p->p_sigstk.ss_flags &= ~SS_ONSTACK; p->p_sigmask = uc.uc_sigmask; SIG_CANTMASK(p->p_sigmask); /* XXX ksc.sc_ownedfp ? */ ia64_fpstate_drop(p); +#if 0 bcopy((struct fpreg *)uc.uc_mcontext.mc_fpregs, &p->p_addr->u_pcb.pcb_fp, sizeof(struct fpreg)); - p->p_addr->u_pcb.pcb_fp_control = uc.uc_mcontext.mc_fp_control; + p->p_addr->u_pcb.pcb_fp_control = + uc.uc_mcontext.mc_fp_control; +#endif #ifdef DEBUG if (sigdebug & SDB_FOLLOW) printf("sigreturn(%d): returns\n", p->p_pid); #endif -#endif return (EJUSTRETURN); } /* * Machine dependent boot() routine * * I haven't seen anything to put here yet * Possibly some stuff might be grafted back here from boot() */ void cpu_boot(int howto) { } /* * Shutdown the CPU as much as possible */ void cpu_halt(void) { /* TODO */ } /* * Clear registers on exec */ void setregs(struct proc *p, u_long entry, u_long stack, u_long ps_strings) { struct trapframe *frame; frame = p->p_md.md_tf; + + /* + * Make sure that we restore the entire trapframe after an + * execve. + */ + frame->tf_flags &= ~FRAME_SYSCALL; bzero(frame->tf_r, sizeof(frame->tf_r)); bzero(frame->tf_f, sizeof(frame->tf_f)); frame->tf_cr_iip = entry; frame->tf_cr_ipsr = (IA64_PSR_IC | IA64_PSR_I | IA64_PSR_IT | IA64_PSR_DT | IA64_PSR_RT | IA64_PSR_DFH | IA64_PSR_BN | IA64_PSR_CPL_USER); frame->tf_r[FRAME_SP] = stack; frame->tf_r[FRAME_R14] = ps_strings; /* * Setup the new backing store and make sure the new image * starts executing with an empty register stack frame. */ frame->tf_ar_bspstore = p->p_md.md_bspstore; frame->tf_ndirty = 0; frame->tf_cr_ifs = (1L<<63); /* ifm=0, v=1 */ frame->tf_ar_rsc = 0xf; /* user mode rsc */ frame->tf_ar_fpsr = IA64_FPSR_DEFAULT; p->p_md.md_flags &= ~MDP_FPUSED; ia64_fpstate_drop(p); } int ptrace_set_pc(struct proc *p, unsigned long addr) { /* TODO set pc in trapframe */ return 0; } int ptrace_single_step(struct proc *p) { /* TODO arrange for user process to single step */ return 0; } int ptrace_read_u_check(struct proc *p, vm_offset_t addr, size_t len) { vm_offset_t gap; if ((vm_offset_t) (addr + len) < addr) return EPERM; if ((vm_offset_t) (addr + len) <= sizeof(struct user)) return 0; gap = (char *) p->p_md.md_tf - (char *) p->p_addr; if ((vm_offset_t) addr < gap) return EPERM; if ((vm_offset_t) (addr + len) <= (vm_offset_t) (gap + sizeof(struct trapframe))) return 0; return EPERM; } int ptrace_write_u(struct proc *p, vm_offset_t off, long data) { vm_offset_t min; #if 0 struct trapframe frame_copy; struct trapframe *tp; #endif /* * Privileged kernel state is scattered all over the user area. * Only allow write access to parts of regs and to fpregs. */ min = (char *)p->p_md.md_tf - (char *)p->p_addr; if (off >= min && off <= min + sizeof(struct trapframe) - sizeof(int)) { #if 0 tp = p->p_md.md_tf; frame_copy = *tp; *(int *)((char *)&frame_copy + (off - min)) = data; if (!EFLAGS_SECURE(frame_copy.tf_eflags, tp->tf_eflags) || !CS_SECURE(frame_copy.tf_cs)) return (EINVAL); #endif *(int*)((char *)p->p_addr + off) = data; return (0); } min = offsetof(struct user, u_pcb); if (off >= min && off <= min + sizeof(struct pcb)) { *(int*)((char *)p->p_addr + off) = data; return (0); } return (EFAULT); } int ia64_pa_access(vm_offset_t pa) { return VM_PROT_READ|VM_PROT_WRITE; } int fill_regs(p, regs) struct proc *p; struct reg *regs; { /* TODO copy trapframe to regs */ return (0); } int set_regs(p, regs) struct proc *p; struct reg *regs; { /* TODO copy regs to trapframe */ return (0); } int fill_fpregs(p, fpregs) struct proc *p; struct fpreg *fpregs; { /* TODO copy fpu state to fpregs */ ia64_fpstate_save(p, 0); #if 0 bcopy(&p->p_addr->u_pcb.pcb_fp, fpregs, sizeof *fpregs); #endif return (0); } int set_fpregs(p, fpregs) struct proc *p; struct fpreg *fpregs; { /* TODO copy fpregs fpu state */ ia64_fpstate_drop(p); #if 0 bcopy(fpregs, &p->p_addr->u_pcb.pcb_fp, sizeof *fpregs); #endif return (0); } #ifndef DDB void Debugger(const char *msg) { printf("Debugger(\"%s\") called.\n", msg); } #endif /* no DDB */ #include /* * Determine the size of the transfer, and make sure it is * within the boundaries of the partition. Adjust transfer * if needed, and signal errors or early completion. */ int bounds_check_with_label(struct bio *bp, struct disklabel *lp, int wlabel) { #if 0 struct partition *p = lp->d_partitions + dkpart(bp->bio_dev); int labelsect = lp->d_partitions[0].p_offset; int maxsz = p->p_size, sz = (bp->bio_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; /* overwriting disk label ? */ /* XXX should also protect bootstrap in first 8K */ if (bp->bio_blkno + p->p_offset <= LABELSECTOR + labelsect && #if LABELSECTOR != 0 bp->bio_blkno + p->p_offset + sz > LABELSECTOR + labelsect && #endif (bp->bio_cmd == BIO_WRITE) && wlabel == 0) { bp->bio_error = EROFS; goto bad; } #if defined(DOSBBSECTOR) && defined(notyet) /* overwriting master boot record? */ if (bp->bio_blkno + p->p_offset <= DOSBBSECTOR && (bp->bio_cmd == BIO_WRITE) && wlabel == 0) { bp->bio_error = EROFS; goto bad; } #endif /* beyond partition? */ if (bp->bio_blkno < 0 || bp->bio_blkno + sz > maxsz) { /* if exactly at end of disk, return an EOF */ if (bp->bio_blkno == maxsz) { bp->bio_resid = bp->bio_bcount; return(0); } /* or truncate if part of it fits */ sz = maxsz - bp->bio_blkno; if (sz <= 0) { bp->bio_error = EINVAL; goto bad; } bp->bio_bcount = sz << DEV_BSHIFT; } bp->bio_pblkno = bp->bio_blkno + p->p_offset; return(1); bad: bp->bio_flags |= BIO_ERROR; #endif return(-1); } static int sysctl_machdep_adjkerntz(SYSCTL_HANDLER_ARGS) { int error; error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); if (!error && req->newptr) resettodr(); return (error); } SYSCTL_PROC(_machdep, CPU_ADJKERNTZ, adjkerntz, CTLTYPE_INT|CTLFLAG_RW, &adjkerntz, 0, sysctl_machdep_adjkerntz, "I", ""); SYSCTL_INT(_machdep, CPU_DISRTCSET, disable_rtc_set, CTLFLAG_RW, &disable_rtc_set, 0, ""); SYSCTL_INT(_machdep, CPU_WALLCLOCK, wall_cmos_clock, CTLFLAG_RW, &wall_cmos_clock, 0, ""); void ia64_fpstate_check(struct proc *p) { if ((p->p_md.md_tf->tf_cr_ipsr & IA64_PSR_DFH) == 0) if (p != PCPU_GET(fpcurproc)) panic("ia64_check_fpcurproc: bogus"); } /* * Save the high floating point state in the pcb. Use this to get * read-only access to the floating point state. If write is true, the * current fp process is cleared so that fp state can safely be * modified. The process will automatically reload the changed state * by generating a disabled fp trap. */ void ia64_fpstate_save(struct proc *p, int write) { if (p == PCPU_GET(fpcurproc)) { /* * Save the state in the pcb. */ savehighfp(p->p_addr->u_pcb.pcb_highfp); if (write) { p->p_md.md_tf->tf_cr_ipsr |= IA64_PSR_DFH; PCPU_SET(fpcurproc, NULL); } } } /* * Relinquish ownership of the FP state. This is called instead of * ia64_save_fpstate() if the entire FP state is being changed * (e.g. on sigreturn). */ void ia64_fpstate_drop(struct proc *p) { if (p == PCPU_GET(fpcurproc)) { p->p_md.md_tf->tf_cr_ipsr |= IA64_PSR_DFH; PCPU_SET(fpcurproc, NULL); } } /* * Switch the current owner of the fp state to p, reloading the state * from the pcb. */ void ia64_fpstate_switch(struct proc *p) { if (PCPU_GET(fpcurproc)) { /* * Dump the old fp state if its valid. */ savehighfp(PCPU_GET(fpcurproc)->p_addr->u_pcb.pcb_highfp); PCPU_GET(fpcurproc)->p_md.md_tf->tf_cr_ipsr |= IA64_PSR_DFH; } /* * Remember the new FP owner and reload its state. */ PCPU_SET(fpcurproc, p); restorehighfp(p->p_addr->u_pcb.pcb_highfp); p->p_md.md_tf->tf_cr_ipsr &= ~IA64_PSR_DFH; p->p_md.md_flags |= MDP_FPUSED; } Index: head/sys/ia64/include/atomic.h =================================================================== --- head/sys/ia64/include/atomic.h (revision 67521) +++ head/sys/ia64/include/atomic.h (revision 67522) @@ -1,363 +1,375 @@ /*- * Copyright (c) 1998 Doug Rabson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_ATOMIC_H_ #define _MACHINE_ATOMIC_H_ /* * Various simple arithmetic on memory which is atomic in the presence * of interrupts and SMP safe. */ /* * Everything is built out of cmpxchg. */ #define IA64_CMPXCHG(sz, sem, type, p, cmpval, newval) \ ({ \ type _cmpval = cmpval; \ type _newval = newval; \ volatile type *_p = (volatile type *) p; \ type _ret; \ \ __asm __volatile ( \ "mov ar.ccv=%2;;\n\t" \ "cmpxchg" #sz "." #sem " %0=%4,%3,ar.ccv\n\t" \ : "=r" (_ret), "=m" (*_p) \ : "r" (_cmpval), "r" (_newval), "m" (*_p) \ : "memory"); \ _ret; \ }) /* * Some common forms of cmpxch. */ static __inline u_int32_t ia64_cmpxchg_acq_32(volatile u_int32_t* p, u_int32_t cmpval, u_int32_t newval) { return IA64_CMPXCHG(4, acq, u_int32_t, p, cmpval, newval); } static __inline u_int32_t ia64_cmpxchg_rel_32(volatile u_int32_t* p, u_int32_t cmpval, u_int32_t newval) { return IA64_CMPXCHG(4, rel, u_int32_t, p, cmpval, newval); } static __inline u_int64_t ia64_cmpxchg_acq_64(volatile u_int64_t* p, u_int64_t cmpval, u_int64_t newval) { return IA64_CMPXCHG(8, acq, u_int64_t, p, cmpval, newval); } static __inline u_int64_t ia64_cmpxchg_rel_64(volatile u_int64_t* p, u_int64_t cmpval, u_int64_t newval) { return IA64_CMPXCHG(8, rel, u_int64_t, p, cmpval, newval); } #define ATOMIC_STORE_LOAD(type, width, size) \ static __inline u_int##width##_t \ ia64_ld_acq_##width(volatile u_int##width##_t* p) \ { \ - u_int##width_t v; \ + u_int##width##_t v; \ \ __asm __volatile ("ld" size ".acq %0=%1" \ - : "r" (v) \ - : "=m" (*p) \ + : "=r" (v) \ + : "m" (*p) \ : "memory"); \ return (v); \ } \ \ static __inline u_int##width##_t \ atomic_load_acq_##width(volatile u_int##width##_t* p) \ { \ - u_int##width_t v; \ + u_int##width##_t v; \ \ __asm __volatile ("ld" size ".acq %0=%1" \ - : "r" (v) \ - : "=m" (*p) \ + : "=r" (v) \ + : "m" (*p) \ : "memory"); \ return (v); \ } \ \ static __inline u_int##width##_t \ atomic_load_acq_##type(volatile u_int##width##_t* p) \ { \ - u_int##width_t v; \ + u_int##width##_t v; \ \ __asm __volatile ("ld" size ".acq %0=%1" \ - : "r" (v) \ - : "=m" (*p) \ + : "=r" (v) \ + : "m" (*p) \ : "memory"); \ return (v); \ } \ \ static __inline void \ ia64_st_rel_##width(volatile u_int##width##_t* p, u_int##width##_t v)\ { \ __asm __volatile ("st" size ".rel %0=%1" \ : "=m" (*p) \ : "r" (v) \ : "memory"); \ } \ \ static __inline void \ atomic_store_rel_##width(volatile u_int##width##_t* p, u_int##width##_t v)\ { \ __asm __volatile ("st" size ".rel %0=%1" \ : "=m" (*p) \ : "r" (v) \ : "memory"); \ } \ \ static __inline void \ atomic_store_rel_##type(volatile u_int##width##_t* p, u_int##width##_t v)\ { \ __asm __volatile ("st" size ".rel %0=%1" \ : "=m" (*p) \ : "r" (v) \ : "memory"); \ } ATOMIC_STORE_LOAD(char, 8, "1") ATOMIC_STORE_LOAD(short, 16, "2") ATOMIC_STORE_LOAD(int, 32, "4") ATOMIC_STORE_LOAD(long, 64, "8") #undef ATOMIC_STORE_LOAD #define IA64_ATOMIC(sz, type, name, width, op) \ \ static __inline void \ atomic_##name##_acq_##width(volatile type *p, type v) \ { \ type old; \ do { \ old = *p; \ } while (IA64_CMPXCHG(sz, acq, type, p, old, old op v) != old); \ } \ \ static __inline void \ atomic_##name##_rel_##width(volatile type *p, type v) \ { \ type old; \ do { \ old = *p; \ } while (IA64_CMPXCHG(sz, rel, type, p, old, old op v) != old); \ } IA64_ATOMIC(1, u_int8_t, set, 8, |) IA64_ATOMIC(2, u_int16_t, set, 16, |) IA64_ATOMIC(4, u_int32_t, set, 32, |) IA64_ATOMIC(8, u_int64_t, set, 64, |) IA64_ATOMIC(1, u_int8_t, clear, 8, &~) IA64_ATOMIC(2, u_int16_t, clear, 16, &~) IA64_ATOMIC(4, u_int32_t, clear, 32, &~) IA64_ATOMIC(8, u_int64_t, clear, 64, &~) IA64_ATOMIC(1, u_int8_t, add, 8, +) IA64_ATOMIC(2, u_int16_t, add, 16, +) IA64_ATOMIC(4, u_int32_t, add, 32, +) IA64_ATOMIC(8, u_int64_t, add, 64, +) IA64_ATOMIC(1, u_int8_t, subtract, 8, -) IA64_ATOMIC(2, u_int16_t, subtract, 16, -) IA64_ATOMIC(4, u_int32_t, subtract, 32, -) IA64_ATOMIC(8, u_int64_t, subtract, 64, -) #undef IA64_ATOMIC #undef IA64_CMPXCHG #define atomic_set_8 atomic_set_acq_8 #define atomic_clear_8 atomic_clear_acq_8 #define atomic_add_8 atomic_add_acq_8 #define atomic_subtract_8 atomic_subtract_acq_8 #define atomic_set_16 atomic_set_acq_16 #define atomic_clear_16 atomic_clear_acq_16 #define atomic_add_16 atomic_add_acq_16 #define atomic_subtract_16 atomic_subtract_acq_16 #define atomic_set_32 atomic_set_acq_32 #define atomic_clear_32 atomic_clear_acq_32 #define atomic_add_32 atomic_add_acq_32 #define atomic_subtract_32 atomic_subtract_acq_32 #define atomic_set_64 atomic_set_acq_64 #define atomic_clear_64 atomic_clear_acq_64 #define atomic_add_64 atomic_add_acq_64 #define atomic_subtract_64 atomic_subtract_acq_64 #define atomic_set_char atomic_set_8 #define atomic_clear_char atomic_clear_8 #define atomic_add_char atomic_add_8 #define atomic_subtract_char atomic_subtract_8 #define atomic_set_acq_char atomic_set_acq_8 #define atomic_clear_acq_char atomic_clear_acq_8 #define atomic_add_acq_char atomic_add_acq_8 #define atomic_subtract_acq_char atomic_subtract_acq_8 #define atomic_set_rel_char atomic_set_rel_8 #define atomic_clear_rel_char atomic_clear_rel_8 #define atomic_add_rel_char atomic_add_rel_8 #define atomic_subtract_rel_char atomic_subtract_rel_8 #define atomic_set_short atomic_set_16 #define atomic_clear_short atomic_clear_16 #define atomic_add_short atomic_add_16 #define atomic_subtract_short atomic_subtract_16 #define atomic_set_acq_short atomic_set_acq_16 #define atomic_clear_acq_short atomic_clear_acq_16 #define atomic_add_acq_short atomic_add_acq_16 #define atomic_subtract_acq_short atomic_subtract_acq_16 #define atomic_set_rel_short atomic_set_rel_16 #define atomic_clear_rel_short atomic_clear_rel_16 #define atomic_add_rel_short atomic_add_rel_16 #define atomic_subtract_rel_short atomic_subtract_rel_16 #define atomic_set_int atomic_set_32 #define atomic_clear_int atomic_clear_32 #define atomic_add_int atomic_add_32 #define atomic_subtract_int atomic_subtract_32 #define atomic_set_acq_int atomic_set_acq_32 #define atomic_clear_acq_int atomic_clear_acq_32 #define atomic_add_acq_int atomic_add_acq_32 #define atomic_subtract_acq_int atomic_subtract_acq_32 #define atomic_set_rel_int atomic_set_rel_32 #define atomic_clear_rel_int atomic_clear_rel_32 #define atomic_add_rel_int atomic_add_rel_32 #define atomic_subtract_rel_int atomic_subtract_rel_32 #define atomic_set_long atomic_set_64 #define atomic_clear_long atomic_clear_64 #define atomic_add_long atomic_add_64 #define atomic_subtract_long atomic_subtract_64 #define atomic_set_acq_long atomic_set_acq_64 #define atomic_clear_acq_long atomic_clear_acq_64 #define atomic_add_acq_long atomic_add_acq_64 #define atomic_subtract_acq_long atomic_subtract_acq_64 #define atomic_set_rel_long atomic_set_rel_64 #define atomic_clear_rel_long atomic_clear_rel_64 #define atomic_add_rel_long atomic_add_rel_64 #define atomic_subtract_rel_long atomic_subtract_rel_64 + +static __inline void +atomic_set_ptr(volatile void *p, u_int64_t v) +{ + atomic_set_64((volatile u_int64_t *) p, v); +} + +static __inline void +atomic_clear_ptr(volatile void *p, u_int64_t v) +{ + atomic_clear_64((volatile u_int64_t *) p, v); +} /* * Atomically compare the value stored at *p with cmpval and if the * two values are equal, update the value of *p with newval. Returns * zero if the compare failed, nonzero otherwise. */ static __inline int atomic_cmpset_acq_32(volatile u_int32_t* p, u_int32_t cmpval, u_int32_t newval) { return ia64_cmpxchg_acq_32(p, cmpval, newval) == cmpval; } static __inline int atomic_cmpset_rel_32(volatile u_int32_t* p, u_int32_t cmpval, u_int32_t newval) { return ia64_cmpxchg_rel_32(p, cmpval, newval) == cmpval; } /* * Atomically compare the value stored at *p with cmpval and if the * two values are equal, update the value of *p with newval. Returns * zero if the compare failed, nonzero otherwise. */ static __inline int atomic_cmpset_acq_64(volatile u_int64_t* p, u_int64_t cmpval, u_int64_t newval) { return ia64_cmpxchg_acq_64(p, cmpval, newval) == cmpval; } static __inline int atomic_cmpset_rel_64(volatile u_int64_t* p, u_int64_t cmpval, u_int64_t newval) { return ia64_cmpxchg_rel_64(p, cmpval, newval) == cmpval; } #define atomic_cmpset_32 atomic_cmpset_acq_32 #define atomic_cmpset_64 atomic_cmpset_acq_64 #define atomic_cmpset_int atomic_cmpset_32 #define atomic_cmpset_long atomic_cmpset_64 #define atomic_cmpset_acq_int atomic_cmpset_acq_32 #define atomic_cmpset_rel_int atomic_cmpset_rel_32 #define atomic_cmpset_acq_long atomic_cmpset_acq_64 #define atomic_cmpset_rel_long atomic_cmpset_rel_64 static __inline int atomic_cmpset_acq_ptr(volatile void *dst, void *exp, void *src) { return atomic_cmpset_acq_long((volatile u_long *)dst, (u_long)exp, (u_long)src); } static __inline int atomic_cmpset_rel_ptr(volatile void *dst, void *exp, void *src) { return atomic_cmpset_rel_long((volatile u_long *)dst, (u_long)exp, (u_long)src); } #define atomic_cmpset_ptr atomic_cmpset_acq_ptr static __inline void * atomic_load_acq_ptr(volatile void *p) { return (void *)atomic_load_acq_long((volatile u_long *)p); } static __inline void atomic_store_rel_ptr(volatile void *p, void *v) { atomic_store_rel_long((volatile u_long *)p, (u_long)v); } static __inline u_int32_t atomic_readandclear_32(volatile u_int32_t* p) { u_int32_t val; do { val = *p; } while (!atomic_cmpset_32(p, val, 0)); return val; } static __inline u_int64_t atomic_readandclear_64(volatile u_int64_t* p) { u_int64_t val; do { val = *p; } while (!atomic_cmpset_64(p, val, 0)); return val; } #define atomic_readandclear_int atomic_readandclear_32 #define atomic_readandclear_long atomic_readandclear_64 #endif /* ! _MACHINE_ATOMIC_H_ */ Index: head/sys/ia64/include/frame.h =================================================================== --- head/sys/ia64/include/frame.h (revision 67521) +++ head/sys/ia64/include/frame.h (revision 67522) @@ -1,114 +1,112 @@ /*- * Copyright (c) 2000 Doug Rabson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_FRAME_H_ #define _MACHINE_FRAME_H_ #include /* * Software trap, exception, and syscall frame. - * - * This is loosely based on the Linux pt_regs structure. When I - * understand things better, I might change it. */ struct trapframe { + u_int64_t tf_flags; +#define FRAME_SYSCALL 1 /* syscalls use a partial trapframe */ + u_int64_t tf_cr_iip; u_int64_t tf_cr_ipsr; u_int64_t tf_cr_isr; u_int64_t tf_cr_ifa; u_int64_t tf_pr; u_int64_t tf_ar_rsc; u_int64_t tf_ar_pfs; u_int64_t tf_cr_ifs; u_int64_t tf_ar_bspstore; u_int64_t tf_ar_rnat; u_int64_t tf_ndirty; u_int64_t tf_ar_unat; u_int64_t tf_ar_ccv; u_int64_t tf_ar_fpsr; u_int64_t tf_b[8]; u_int64_t tf_r[31]; /* don't need to save r0 */ #define FRAME_R1 0 #define FRAME_GP 0 #define FRAME_R2 1 #define FRAME_R3 2 #define FRAME_R4 3 #define FRAME_R5 4 #define FRAME_R6 5 #define FRAME_R7 6 #define FRAME_R8 7 #define FRAME_R9 8 #define FRAME_R10 9 #define FRAME_R11 10 #define FRAME_R12 11 #define FRAME_SP 11 #define FRAME_R13 12 #define FRAME_TP 12 #define FRAME_R14 13 #define FRAME_R15 14 #define FRAME_R16 15 #define FRAME_R17 16 #define FRAME_R18 17 #define FRAME_R19 18 #define FRAME_R20 19 #define FRAME_R21 20 #define FRAME_R22 21 #define FRAME_R23 22 #define FRAME_R24 23 #define FRAME_R25 24 #define FRAME_R26 25 #define FRAME_R27 26 #define FRAME_R28 27 #define FRAME_R29 28 #define FRAME_R30 29 #define FRAME_R31 30 - - u_int64_t tf_pad1; /* * We rely on the compiler to save/restore f2-f5 and * f16-f31. We also tell the compiler to avoid f32-f127 * completely so we don't worry about them at all. */ struct ia64_fpreg tf_f[10]; #define FRAME_F6 0 #define FRAME_F7 1 #define FRAME_F8 2 #define FRAME_F9 3 #define FRAME_F10 3 #define FRAME_F11 3 #define FRAME_F12 3 #define FRAME_F13 3 #define FRAME_F14 3 #define FRAME_F15 3 }; #endif /* _MACHINE_FRAME_H_ */ Index: head/sys/ia64/include/ia64_cpu.h =================================================================== --- head/sys/ia64/include/ia64_cpu.h (revision 67521) +++ head/sys/ia64/include/ia64_cpu.h (revision 67522) @@ -1,431 +1,435 @@ /*- * Copyright (c) 2000 Doug Rabson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_IA64_CPU_H_ #define _MACHINE_IA64_CPU_H_ /* * Definition of PSR and IPSR bits. */ #define IA64_PSR_BE 0x0000000000000002 #define IA64_PSR_UP 0x0000000000000004 #define IA64_PSR_AC 0x0000000000000008 #define IA64_PSR_MFL 0x0000000000000010 #define IA64_PSR_MFH 0x0000000000000020 #define IA64_PSR_IC 0x0000000000002000 #define IA64_PSR_I 0x0000000000004000 #define IA64_PSR_PK 0x0000000000008000 #define IA64_PSR_DT 0x0000000000020000 #define IA64_PSR_DFL 0x0000000000040000 #define IA64_PSR_DFH 0x0000000000080000 #define IA64_PSR_SP 0x0000000000100000 #define IA64_PSR_PP 0x0000000000200000 #define IA64_PSR_DI 0x0000000000400000 #define IA64_PSR_SI 0x0000000000800000 #define IA64_PSR_DB 0x0000000001000000 #define IA64_PSR_LP 0x0000000002000000 #define IA64_PSR_TB 0x0000000004000000 #define IA64_PSR_RT 0x0000000008000000 #define IA64_PSR_CPL 0x0000000300000000 #define IA64_PSR_CPL_KERN 0x0000000000000000 #define IA64_PSR_CPL_1 0x0000000100000000 #define IA64_PSR_CPL_2 0x0000000200000000 #define IA64_PSR_CPL_USER 0x0000000300000000 #define IA64_PSR_IS 0x0000000400000000 #define IA64_PSR_MC 0x0000000800000000 #define IA64_PSR_IT 0x0000001000000000 #define IA64_PSR_ID 0x0000002000000000 #define IA64_PSR_DA 0x0000004000000000 #define IA64_PSR_DD 0x0000008000000000 #define IA64_PSR_SS 0x0000010000000000 #define IA64_PSR_RI 0x0000060000000000 #define IA64_PSR_RI_0 0x0000000000000000 #define IA64_PSR_RI_1 0x0000020000000000 #define IA64_PSR_RI_2 0x0000040000000000 #define IA64_PSR_ED 0x0000080000000000 #define IA64_PSR_BN 0x0000100000000000 #define IA64_PSR_IA 0x0000200000000000 /* * Definition of ISR bits. */ #define IA64_ISR_CODE 0x000000000000ffff #define IA64_ISR_VECTOR 0x0000000000ff0000 #define IA64_ISR_X 0x0000000100000000 #define IA64_ISR_W 0x0000000200000000 #define IA64_ISR_R 0x0000000400000000 #define IA64_ISR_NA 0x0000000800000000 #define IA64_ISR_SP 0x0000001000000000 #define IA64_ISR_RS 0x0000002000000000 #define IA64_ISR_IR 0x0000004000000000 #define IA64_ISR_NI 0x0000008000000000 #define IA64_ISR_SO 0x0000010000000000 #define IA64_ISR_EI 0x0000060000000000 #define IA64_ISR_EI_0 0x0000000000000000 #define IA64_ISR_EI_1 0x0000020000000000 #define IA64_ISR_EI_2 0x0000040000000000 #define IA64_ISR_ED 0x0000080000000000 /* * Vector numbers for various ia64 interrupts. */ #define IA64_VEC_VHPT 0 #define IA64_VEC_ITLB 1 #define IA64_VEC_DTLB 2 #define IA64_VEC_ALT_ITLB 3 #define IA64_VEC_ALT_DTLB 4 #define IA64_VEC_NESTED_DTLB 5 #define IA64_VEC_IKEY_MISS 6 #define IA64_VEC_DKEY_MISS 7 #define IA64_VEC_DIRTY_BIT 8 #define IA64_VEC_INST_ACCESS 9 #define IA64_VEC_DATA_ACCESS 10 #define IA64_VEC_BREAK 11 #define IA64_VEC_EXT_INTR 12 #define IA64_VEC_PAGE_NOT_PRESENT 20 #define IA64_VEC_KEY_PERMISSION 21 #define IA64_VEC_INST_ACCESS_RIGHTS 22 #define IA64_VEC_DATA_ACCESS_RIGHTS 23 #define IA64_VEC_GENERAL_EXCEPTION 24 #define IA64_VEC_DISABLED_FP 25 #define IA64_VEC_NAT_CONSUMPTION 26 #define IA64_VEC_SPECULATION 27 #define IA64_VEC_DEBUG 29 #define IA64_VEC_UNALIGNED_REFERENCE 30 #define IA64_VEC_UNSUPP_DATA_REFERENCE 31 #define IA64_VEC_FLOATING_POINT_FAULT 32 #define IA64_VEC_FLOATING_POINT_TRAP 33 #define IA64_VEC_LOWER_PRIVILEGE_TRANSFER 34 #define IA64_VEC_TAKEN_BRANCH_TRAP 35 #define IA64_VEC_SINGLE_STEP_TRAP 36 #define IA64_VEC_IA32_EXCEPTION 45 #define IA64_VEC_IA32_INTERCEPT 46 #define IA64_VEC_IA32_INTERRUPT 47 /* * Manipulating region bits of an address. */ #define IA64_RR_BASE(n) (((u_int64_t) (n)) << 61) #define IA64_RR_MASK(x) ((x) & ((1L << 61) - 1)) #define IA64_PHYS_TO_RR6(x) ((x) | IA64_RR_BASE(6)) #define IA64_PHYS_TO_RR7(x) ((x) | IA64_RR_BASE(7)) +#ifndef LOCORE + /* * Various special ia64 instructions. */ /* * Memory Fence. */ static __inline void ia64_mf(void) { __asm __volatile("mf"); } /* * Calculate address in VHPT for va. */ static __inline u_int64_t ia64_thash(u_int64_t va) { u_int64_t result; __asm __volatile("thash %0=%1" : "=r" (result) : "r" (va)); return result; } /* * Calculate VHPT tag for va. */ static __inline u_int64_t ia64_ttag(u_int64_t va) { u_int64_t result; __asm __volatile("ttag %0=%1" : "=r" (result) : "r" (va)); return result; } /* * Convert virtual address to physical. */ static __inline u_int64_t ia64_tpa(u_int64_t va) { u_int64_t result; __asm __volatile("tpa %0=%1" : "=r" (result) : "r" (va)); return result; } /* * Generate a ptc.e instruction. */ static __inline void ia64_ptc_e(u_int64_t v) { __asm __volatile("ptc.e %0;;" :: "r"(v)); } /* * Generate a ptc.g instruction. */ static __inline void ia64_ptc_g(u_int64_t va, u_int64_t log2size) { __asm __volatile("ptc.g %0,%1;;" :: "r"(va), "r"(log2size)); } /* * Generate a ptc.ga instruction. */ static __inline void ia64_ptc_ga(u_int64_t va, u_int64_t log2size) { __asm __volatile("ptc.ga %0,%1;;" :: "r"(va), "r"(log2size)); } /* * Generate a ptc.l instruction. */ static __inline void ia64_ptc_l(u_int64_t va, u_int64_t log2size) { __asm __volatile("ptc.l %0,%1;;" :: "r"(va), "r"(log2size)); } /* * Read the value of ar.k0. */ static __inline u_int64_t ia64_get_k0(void) { u_int64_t result; __asm __volatile("mov %0=ar.k0" : "=r" (result)); return result; } /* * Read the value of ar.k1. */ static __inline u_int64_t ia64_get_k1(void) { u_int64_t result; __asm __volatile("mov %0=ar.k1" : "=r" (result)); return result; } /* * Read the value of ar.k2. */ static __inline u_int64_t ia64_get_k2(void) { u_int64_t result; __asm __volatile("mov %0=ar.k2" : "=r" (result)); return result; } /* * Read the value of ar.k3. */ static __inline u_int64_t ia64_get_k3(void) { u_int64_t result; __asm __volatile("mov %0=ar.k3" : "=r" (result)); return result; } /* * Read the value of ar.k4. */ static __inline u_int64_t ia64_get_k4(void) { u_int64_t result; __asm __volatile("mov %0=ar.k4" : "=r" (result)); return result; } /* * Read the value of ar.k5. */ static __inline u_int64_t ia64_get_k5(void) { u_int64_t result; __asm __volatile("mov %0=ar.k5" : "=r" (result)); return result; } /* * Read the value of ar.k6. */ static __inline u_int64_t ia64_get_k6(void) { u_int64_t result; __asm __volatile("mov %0=ar.k6" : "=r" (result)); return result; } /* * Read the value of ar.k7. */ static __inline u_int64_t ia64_get_k7(void) { u_int64_t result; __asm __volatile("mov %0=ar.k7" : "=r" (result)); return result; } /* * Write the value of ar.k0. */ static __inline void ia64_set_k0(u_int64_t v) { __asm __volatile("mov ar.k0=%0" :: "r" (v)); } /* * Write the value of ar.k1. */ static __inline void ia64_set_k1(u_int64_t v) { __asm __volatile("mov ar.k1=%0" :: "r" (v)); } /* * Write the value of ar.k2. */ static __inline void ia64_set_k2(u_int64_t v) { __asm __volatile("mov ar.k2=%0" :: "r" (v)); } /* * Write the value of ar.k3. */ static __inline void ia64_set_k3(u_int64_t v) { __asm __volatile("mov ar.k3=%0" :: "r" (v)); } /* * Write the value of ar.k4. */ static __inline void ia64_set_k4(u_int64_t v) { __asm __volatile("mov ar.k4=%0" :: "r" (v)); } /* * Write the value of ar.k5. */ static __inline void ia64_set_k5(u_int64_t v) { __asm __volatile("mov ar.k5=%0" :: "r" (v)); } /* * Write the value of ar.k6. */ static __inline void ia64_set_k6(u_int64_t v) { __asm __volatile("mov ar.k6=%0" :: "r" (v)); } /* * Write the value of ar.k7. */ static __inline void ia64_set_k7(u_int64_t v) { __asm __volatile("mov ar.k7=%0" :: "r" (v)); } /* * Read the value of ar.itc. */ static __inline u_int64_t ia64_get_itc(void) { u_int64_t result; __asm __volatile("mov %0=ar.itc" : "=r" (result)); return result; } /* * Read the value of ar.itm. */ static __inline u_int64_t ia64_get_itm(void) { u_int64_t result; __asm __volatile("mov %0=cr.itm" : "=r" (result)); return result; } /* * Write the value of ar.itm. */ static __inline void ia64_set_itm(u_int64_t v) { __asm __volatile("mov cr.itm=%0" :: "r" (v)); } /* * Write the value of ar.itv. */ static __inline void ia64_set_itv(u_int64_t v) { __asm __volatile("mov cr.itv=%0" :: "r" (v)); } /* * Write a region register. */ static __inline void ia64_set_rr(u_int64_t rrbase, u_int64_t v) { __asm __volatile("mov rr[%0]=%1" :: "r"(rrbase), "r"(v) : "memory"); } + +#endif #endif /* _MACHINE_IA64_CPU_H_ */ Index: head/sys/ia64/include/mutex.h =================================================================== --- head/sys/ia64/include/mutex.h (revision 67521) +++ head/sys/ia64/include/mutex.h (revision 67522) @@ -1,101 +1,101 @@ /*- * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Berkeley Software Design Inc's name may not be used to endorse or * promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from BSDI $Id: mutex.h,v 2.7.2.35 2000/04/27 03:10:26 cp Exp $ * $FreeBSD$ */ #ifndef _MACHINE_MUTEX_H_ #define _MACHINE_MUTEX_H_ #include #ifndef LOCORE #ifdef _KERNEL /* * Debugging */ #ifdef MUTEX_DEBUG #ifdef _KERN_MUTEX_C_ char STR_IEN[] = "psr.i"; char STR_IDIS[] = "!psr.i"; -char STR_SIEN[] = "mpp->mtx_saveintr & PSR_I"; +char STR_SIEN[] = "mpp->mtx_saveintr & IA64_PSR_I"; #else /* _KERN_MUTEX_C_ */ extern char STR_IEN[]; extern char STR_IDIS[]; extern char STR_SIEN[]; #endif /* _KERN_MUTEX_C_ */ #endif /* MUTEX_DEBUG */ #define ASS_IEN MPASS2((save_intr() & IA64_PSR_I), STR_IEN) #define ASS_IDIS MPASS2(!(save_intr() & IA64_PSR_I), STR_IDIS) -#define ASS_SIEN(mpp) MPASS2((mpp)->mtx_saveintr & IA64_PSR_I), STR_SIEN) +#define ASS_SIEN(mpp) MPASS2(((mpp)->mtx_saveintr & IA64_PSR_I), STR_SIEN) -#define mtx_legal2block() ((save_intr() & IA64_PSL_I) +#define mtx_legal2block() ((save_intr() & IA64_PSR_I) #endif /* _KERNEL */ #else /* !LOCORE */ /* * Simple assembly macros to get and release non-recursive spin locks */ #define MTX_ENTER(lck, rPSR, rOLD, rNEW, rLCK) \ mov rPSR=psr ; \ mov rNEW=globalp ; \ addl rLCK=@ltoff(lck),gp ;; \ ld8 rLCK=[rLCK] ;; \ add rLCK=MTX_LOCK,rLCK ;; \ rsm psr.i ; \ mov ar.ccv=MTX_UNOWNED ; \ add rNEW=PC_CURPROC,rNEW ;; \ ld8 rNEW=[rNEW] ;; \ 1: cmpxchg8.acq rOLD=[rLCK],rNEW,ar.ccv ;; \ cmp.eq p1,p0=MTX_UNOWNED,rOLD ;; \ (p1) br.cond.spnt.few 1b ;; \ addl rLCK=@ltoff(lck),gp ;; \ ld8 rLCK=[rLCK] ;; \ add rLCK=MTX_SAVEINTR,rLCK ;; \ st4 [rLCK]=rPSR #define MTX_EXIT(lck, rTMP, rLCK) \ mov rTMP=MTX_UNOWNED ; \ addl rLCK=@ltoff(lck),gp;; \ ld8 rLCK=[rLCK];; \ add rLCK=MTX_LOCK,rLCK;; \ st8.rel [rLCK]=rTMP,MTX_SAVEINTR-MTX_LOCK ;; \ ld4 rTMP=[rLCK] ;; \ mov psr.l=rTMP ;; \ srlz.d #endif /* !LOCORE */ #endif /* __MACHINE_MUTEX_H */ Index: head/sys/ia64/include/signal.h =================================================================== --- head/sys/ia64/include/signal.h (revision 67521) +++ head/sys/ia64/include/signal.h (revision 67522) @@ -1,87 +1,88 @@ /* $FreeBSD$ */ /* From: NetBSD: signal.h,v 1.3 1997/04/06 08:47:43 cgd Exp */ /* * Copyright (c) 1994, 1995 Carnegie-Mellon University. * All rights reserved. * * Author: Chris G. Demetriou * * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ #ifndef _MACHINE_SIGNAL_H_ #define _MACHINE_SIGNAL_H_ typedef long sig_atomic_t; #ifndef _ANSI_SOURCE #ifndef _IA64_FPREG_DEFINED struct ia64_fpreg { unsigned long fpr_bits[2]; } __attribute__ ((aligned (16))); #define _IA64_FPREG_DEFINED #endif /* * Information pushed on stack when a signal is delivered. * This is used by the kernel to restore state following * execution of the signal handler. It is also made available * to the handler to allow it to restore state properly if * a non-standard exit is performed. * * Note that sc_regs[] and sc_fpregs[]+sc_fpcr are inline * representations of 'struct reg' and 'struct fpreg', respectively. */ typedef unsigned int osigset_t; struct osigcontext {}; /* * The sequence of the fields should match those in * mcontext_t. Keep them in sync! */ struct sigcontext { - sigset_t sc_mask; /* signal mask to restore */ + sigset_t sc_mask; /* signal mask to restore */ + unsigned long sc_onstack; unsigned long sc_flags; unsigned long sc_nat; unsigned long sc_sp; unsigned long sc_ip; unsigned long sc_cfm; unsigned long sc_um; unsigned long sc_ar_rsc; unsigned long sc_ar_bsp; unsigned long sc_ar_rnat; unsigned long sc_ar_ccv; unsigned long sc_ar_unat; unsigned long sc_ar_fpsr; unsigned long sc_ar_pfs; unsigned long sc_pr; unsigned long sc_br[8]; unsigned long sc_gr[32]; struct ia64_fpreg sc_fr[128]; }; #endif /* !_ANSI_SOURCE */ #endif /* !_MACHINE_SIGNAL_H_*/ Index: head/sys/ia64/include/ucontext.h =================================================================== --- head/sys/ia64/include/ucontext.h (revision 67521) +++ head/sys/ia64/include/ucontext.h (revision 67522) @@ -1,67 +1,65 @@ /*- * Copyright (c) 1999 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_UCONTEXT_H_ #define _MACHINE_UCONTEXT_H_ #define IA64_MC_FLAG_ONSTACK 0 #define IA64_MC_FLAG_IN_SYSCALL 1 #define IA64_MC_FLAG_FPH_VALID 2 typedef struct __mcontext { /* * These fields must match the definition * of struct sigcontext. That way we can support * struct sigcontext and ucontext_t at the same * time. - * - * We use the same layout as Linux/ia64 to make emulation - * easier. */ + long mc_onstack; /* XXX - sigcontext compat. */ unsigned long mc_flags; unsigned long mc_nat; unsigned long mc_sp; unsigned long mc_ip; unsigned long mc_cfm; unsigned long mc_um; unsigned long mc_ar_rsc; unsigned long mc_ar_bsp; unsigned long mc_ar_rnat; unsigned long mc_ar_ccv; unsigned long mc_ar_unat; unsigned long mc_ar_fpsr; unsigned long mc_ar_pfs; unsigned long mc_pr; unsigned long mc_br[8]; unsigned long mc_gr[32]; struct ia64_fpreg mc_fr[128]; } mcontext_t; #endif /* !_MACHINE_UCONTEXT_H_ */