diff options
author | marcel <marcel@FreeBSD.org> | 2010-03-31 05:05:28 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2010-03-31 05:05:28 +0000 |
commit | 5206b4a83362a7725d46782cc81fe7dac300fcdb (patch) | |
tree | d238c41109031e3445a68571e132b8b2494be6f9 | |
parent | 8528ddca3b119decb556267285d24c45d73206ed (diff) | |
download | FreeBSD-src-5206b4a83362a7725d46782cc81fe7dac300fcdb.zip FreeBSD-src-5206b4a83362a7725d46782cc81fe7dac300fcdb.tar.gz |
MFC rev 199727, 200888, 201031, 202904, 203054, 203106, 203572, 203884,
204183, 204184, 204185, 204425, 204904, 204905, 205172, 205234, 205357,
205428, 205429, 205431, 205432, 205433, 205434, 205435, 205454, 205665,
205713, 205723, 205726 and 205727:
Bring ia64 machine-dependent changes from 9-current to 8-stable.
37 files changed, 918 insertions, 907 deletions
diff --git a/sys/cddl/contrib/opensolaris/common/atomic/ia64/opensolaris_atomic.S b/sys/cddl/contrib/opensolaris/common/atomic/ia64/opensolaris_atomic.S index 409d759..1b7c580 100644 --- a/sys/cddl/contrib/opensolaris/common/atomic/ia64/opensolaris_atomic.S +++ b/sys/cddl/contrib/opensolaris/common/atomic/ia64/opensolaris_atomic.S @@ -76,7 +76,7 @@ ENTRY(atomic_or_8_nv, 2) END(atomic_or_8_nv) ENTRY(membar_producer, 0) - mf.a + mf ;; br.ret.sptk rp END(membar_producer) diff --git a/sys/conf/files.ia64 b/sys/conf/files.ia64 index d3fb610..1767331 100644 --- a/sys/conf/files.ia64 +++ b/sys/conf/files.ia64 @@ -45,8 +45,6 @@ contrib/ia64/libuwx/src/uwx_uinfo.c standard contrib/ia64/libuwx/src/uwx_utable.c standard crypto/blowfish/bf_enc.c optional crypto | ipsec crypto/des/des_enc.c optional crypto | ipsec | netsmb -dev/advansys/adv_isa.c optional adv isa -dev/aic/aic_isa.c optional aic isa dev/atkbdc/atkbd.c optional atkbd atkbdc dev/atkbdc/atkbd_atkbdc.c optional atkbd atkbdc dev/atkbdc/atkbdc.c optional atkbdc diff --git a/sys/ia64/conf/GENERIC b/sys/ia64/conf/GENERIC index 6b7411e..e0e739d 100644 --- a/sys/ia64/conf/GENERIC +++ b/sys/ia64/conf/GENERIC @@ -20,7 +20,7 @@ # # $FreeBSD$ -cpu ITANIUM +cpu ITANIUM2 ident GENERIC makeoptions DEBUG=-g # Build kernel with debug information. @@ -28,10 +28,12 @@ makeoptions DEBUG=-g # Build kernel with debug information. options AUDIT # Security event auditing options CD9660 # ISO 9660 Filesystem options COMPAT_43TTY # BSD 4.3 TTY compat (sgtty) -options COMPAT_FREEBSD6 # Compatible with FreeBSD6 options COMPAT_FREEBSD7 # Compatible with FreeBSD7 options FFS # Berkeley Fast Filesystem +options FLOWTABLE # per-cpu routing cache +options GDB # Support remote GDB options GEOM_LABEL # Provides labelization +options INCLUDE_CONFIG_FILE # Include this file in kernel options INET # InterNETworking options INET6 # IPv6 communications protocols options INVARIANTS # Enable calls of extra sanity checking @@ -41,9 +43,11 @@ options MAC # TrustedBSD MAC Framework options MD_ROOT # MD usable as root device options MSDOSFS # MSDOS Filesystem options NFSCLIENT # Network Filesystem Client -options NFSSERVER # Network Filesystem Server options NFSLOCKD # Network Lock Manager +options NFSSERVER # Network Filesystem Server options NFS_ROOT # NFS usable as root device +options P1003_1B_SEMAPHORES # POSIX-style semaphores +options PREEMPTION # Enable kernel thread preemption options PRINTF_BUFR_SIZE=128 # Printf buffering to limit interspersion options PROCFS # Process filesystem (/proc) options PSEUDOFS # Pseudo-filesystem framework @@ -56,13 +60,10 @@ options STACK # stack(9) support options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores options SYSVSHM # SYSV-style shared memory -options P1003_1B_SEMAPHORES # POSIX-style semaphores options UFS_ACL # Support for access control lists options UFS_DIRHASH # Hash-based directory lookup scheme options UFS_GJOURNAL # Enable gjournal-based UFS journaling options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B RT extensions -options HWPMC_HOOKS # Necessary kernel hooks for hwpmc(4) -options INCLUDE_CONFIG_FILE # Include this file in kernel # Various "busses" device firewire # FireWire bus code @@ -76,20 +77,25 @@ device ata # ATA controller device atadisk # ATA disk drives device atapicd # ATAPI CDROM drives device atapifd # ATAPI floppy drives +device atapist # ATAPI tape drives device ataraid # ATA RAID drives # SCSI Controllers device ahc # AHA2940 and AIC7xxx devices device ahd # AHA39320/29320 and AIC79xx devices +device hptiop # Highpoint RocketRaid 3xxx series device isp # Qlogic family device mpt # LSI-Logic MPT-Fusion device sym # NCR/Symbios Logic # RAID controllers interfaced to the SCSI subsystem +device amr # AMI MegaRAID device ciss # Compaq Smart RAID 5* device dpt # DPT Smartcache III, IV device iir # Intel Integrated RAID +device ips # IBM (Adaptec) ServeRAID device mly # Mylex AcceleRAID/eXtremeRAID +device twa # 3ware 9000 series PATA/SATA RAID # SCSI peripherals device cd # CD-ROM, DVD-ROM etc. @@ -102,7 +108,6 @@ device ses # Environmental Services (and SAF-TE) # RAID controllers device aac # Adaptec FSA RAID device aacp # SCSI passthrough for aac (requires CAM) -device amr # AMI MegaRAID device ida # Compaq Smart RAID device mlx # Mylex DAC960 family @@ -118,34 +123,58 @@ device ums # Mouse # PCI Ethernet NICs. device de # DEC/Intel DC21x4x (``Tulip'') -device em # Intel PRO/1000 adapter Gigabit Ethernet Card -device le # AMD Am7900 LANCE and Am79C9xx PCnet +device em # Intel PRO/1000 Gigabit Ethernet Family +device igb # Intel PRO/1000 PCIE Server Gigabit Family +device ixgbe # Intel PRO/10GbE PCIE Ethernet Family device txp # 3Com 3cR990 (``Typhoon'') -device vx # 3Com 3c590, 3c595 (``Vortex'') # PCI Ethernet NICs that use the common MII bus controller code. +device ae # Attansic/Atheros L2 FastEthernet +device age # Attansic/Atheros L1 Gigabit Ethernet +device alc # Atheros AR8131/AR8132 Ethernet +device ale # Atheros AR8121/AR8113/AR8114 Ethernet +device bce # Broadcom BCM5706/BCM5708 Gigabit Ethernet +device bfe # Broadcom BCM440x 10/100 Ethernet device bge # Broadcom BCM570xx Gigabit Ethernet -device dc # DEC/Intel 21143 and various workalikes +device et # Agere ET1310 10/100/Gigabit Ethernet +device jme # JMicron JMC250 Gigabit/JMC260 Fast Ethernet +device msk # Marvell/SysKonnect Yukon II Gigabit Ethernet +device nge # NatSemi DP83820 gigabit Ethernet device fxp # Intel EtherExpress PRO/100B (82557, 82558) -device pcn # AMD Am79C97x PCI 10/100 (precedence over 'le') device re # RealTek 8139C+/8169/8169S/8110S -device rl # RealTek 8129/8139 device sf # Adaptec AIC-6915 (``Starfire'') -device sis # Silicon Integrated Systems SiS 900/SiS 7016 +device sk # SysKonnect SK-984x & SK-982x gigabit Ethernet +device ste # Sundance ST201 (D-Link DFE-550TX) +device stge # Sundance/Tamarack TC9021 gigabit Ethernet +device tx # SMC EtherPower II (83c170 ``EPIC'') +device vge # VIA VT612x gigabit Ethernet device xl # 3Com 3c90x ("Boomerang", "Cyclone") # USB Ethernet device aue # ADMtek USB Ethernet +device axe # ASIX Electronics USB Ethernet device cdce # Generic USB over Ethernet device cue # CATC USB Ethernet device kue # Kawasaki LSI USB Ethernet +device rue # RealTek RTL8150 USB Ethernet +device udav # Davicom DM9601E USB + +# USB Serial +device uark # Technologies ARK3116 based serial adapters +device ubsa # Belkin F5U103 and compatible serial adapters +device uftdi # For FTDI usb serial adapters +device uipaq # Some WinCE based devices +device uplcom # Prolific PL-2303 serial adapters +device uslcom # SI Labs CP2101/CP2102 serial adapters +device uvisor # Visor and Palm devices +device uvscom # USB serial support for DDI pocket's PHS # FireWire support -#device sbp # SCSI over FireWire (need scbus & da) +device fwip # IP over FireWire (RFC 2734,3146) +device sbp # SCSI over FireWire (need scbus & da) # Various (pseudo) devices device ether # Ethernet support -device vlan # 802.1Q VLAN support device faith # IPv6-to-IPv4 relaying (translation) device gif # IPv6 and IPv4 tunneling device loop # Network loopback @@ -155,6 +184,7 @@ device puc # Multi I/O cards and multi-channel UARTs device random # Entropy device device tun # Packet tunnel. device uart # Serial port (UART) +device vlan # 802.1Q VLAN support device firmware # firmware assist module # The `bpf' device enables the Berkeley Packet Filter. diff --git a/sys/ia64/ia64/autoconf.c b/sys/ia64/ia64/autoconf.c index 5a380516..cf073c8 100644 --- a/sys/ia64/ia64/autoconf.c +++ b/sys/ia64/ia64/autoconf.c @@ -39,15 +39,9 @@ #include <sys/bus.h> #include <sys/cons.h> -#include <machine/md_var.h> #include <machine/bootinfo.h> - -#include <cam/cam.h> -#include <cam/cam_ccb.h> -#include <cam/cam_sim.h> -#include <cam/cam_periph.h> -#include <cam/cam_xpt_sim.h> -#include <cam/cam_debug.h> +#include <machine/intr.h> +#include <machine/md_var.h> static void configure_first(void *); static void configure(void *); @@ -97,12 +91,9 @@ static void configure_final(void *dummy) { - /* - * Now we're ready to handle (pending) interrupts. - * XXX this is slightly misplaced. - */ - enable_intr(); - cninit_finish(); + + ia64_enable_intr(); + cold = 0; } diff --git a/sys/ia64/ia64/clock.c b/sys/ia64/ia64/clock.c index a9c39fc..33dbb2e 100644 --- a/sys/ia64/ia64/clock.c +++ b/sys/ia64/ia64/clock.c @@ -29,19 +29,42 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/kernel.h> +#include <sys/bus.h> +#include <sys/interrupt.h> +#include <sys/priority.h> #include <sys/queue.h> #include <sys/sysctl.h> #include <sys/systm.h> -#include <sys/bus.h> #include <sys/timetc.h> #include <sys/pcpu.h> -#include <machine/clock.h> #include <machine/cpu.h> #include <machine/efi.h> +#include <machine/intr.h> +#include <machine/intrcnt.h> #include <machine/md_var.h> +#include <machine/smp.h> + +SYSCTL_NODE(_debug, OID_AUTO, clock, CTLFLAG_RW, 0, "clock statistics"); + +static int adjust_edges = 0; +SYSCTL_INT(_debug_clock, OID_AUTO, adjust_edges, CTLFLAG_RD, + &adjust_edges, 0, "Number of times ITC got more than 12.5% behind"); + +static int adjust_excess = 0; +SYSCTL_INT(_debug_clock, OID_AUTO, adjust_excess, CTLFLAG_RD, + &adjust_excess, 0, "Total number of ignored ITC interrupts"); + +static int adjust_lost = 0; +SYSCTL_INT(_debug_clock, OID_AUTO, adjust_lost, CTLFLAG_RD, + &adjust_lost, 0, "Total number of lost ITC interrupts"); -uint64_t ia64_clock_reload; +static int adjust_ticks = 0; +SYSCTL_INT(_debug_clock, OID_AUTO, adjust_ticks, CTLFLAG_RD, + &adjust_ticks, 0, "Total number of ITC interrupts with adjustment"); + +static u_int ia64_clock_xiv; +static uint64_t ia64_clock_reload; #ifndef SMP static timecounter_get_t ia64_get_timecount; @@ -54,26 +77,80 @@ static struct timecounter ia64_timecounter = { "ITC" /* name */ }; -static unsigned +static u_int ia64_get_timecount(struct timecounter* tc) { return ia64_get_itc(); } #endif -void -pcpu_initclock(void) +static u_int +ia64_ih_clock(struct thread *td, u_int xiv, struct trapframe *tf) { + uint64_t adj, clk, itc; + int64_t delta; + int count; - PCPU_SET(md.clockadj, 0); - PCPU_SET(md.clock, ia64_get_itc()); - ia64_set_itm(PCPU_GET(md.clock) + ia64_clock_reload); - ia64_set_itv(CLOCK_VECTOR); /* highest priority class */ - ia64_srlz_d(); + PCPU_INC(md.stats.pcs_nclks); + + if (PCPU_GET(cpuid) == 0) { + /* + * Clock processing on the BSP. + */ + intrcnt[INTRCNT_CLOCK]++; + + itc = ia64_get_itc(); + + adj = PCPU_GET(md.clockadj); + clk = PCPU_GET(md.clock); + + delta = itc - clk; + count = 0; + while (delta >= ia64_clock_reload) { +#ifdef SMP + ipi_all_but_self(ia64_clock_xiv); +#endif + hardclock(TRAPF_USERMODE(tf), TRAPF_PC(tf)); + if (profprocs != 0) + profclock(TRAPF_USERMODE(tf), TRAPF_PC(tf)); + statclock(TRAPF_USERMODE(tf)); + delta -= ia64_clock_reload; + clk += ia64_clock_reload; + if (adj != 0) + adjust_ticks++; + count++; + } + ia64_set_itm(ia64_get_itc() + ia64_clock_reload - adj); + ia64_srlz_d(); + if (count > 0) { + adjust_lost += count - 1; + if (delta > (ia64_clock_reload >> 3)) { + if (adj == 0) + adjust_edges++; + adj = ia64_clock_reload >> 4; + } else + adj = 0; + } else { + adj = 0; + adjust_excess++; + } + PCPU_SET(md.clock, clk); + PCPU_SET(md.clockadj, adj); + } else { + /* + * Clock processing on the BSP. + */ + hardclock_cpu(TRAPF_USERMODE(tf)); + if (profprocs != 0) + profclock(TRAPF_USERMODE(tf), TRAPF_PC(tf)); + statclock(TRAPF_USERMODE(tf)); + } + + return (0); } /* - * Start the real-time and statistics clocks. We use cr.itc and cr.itm + * Start the real-time and statistics clocks. We use ar.itc and cr.itm * to implement a 1000hz clock. */ void @@ -81,6 +158,11 @@ cpu_initclocks() { u_long itc_freq; + ia64_clock_xiv = ia64_xiv_alloc(PI_REALTIME, IA64_XIV_IPI, + ia64_ih_clock); + if (ia64_clock_xiv == 0) + panic("No XIV for clock interrupts"); + itc_freq = (u_long)ia64_itc_freq() * 1000000ul; stathz = hz; @@ -91,7 +173,11 @@ cpu_initclocks() tc_init(&ia64_timecounter); #endif - pcpu_initclock(); + PCPU_SET(md.clockadj, 0); + PCPU_SET(md.clock, ia64_get_itc()); + ia64_set_itm(PCPU_GET(md.clock) + ia64_clock_reload); + ia64_set_itv(ia64_clock_xiv); + ia64_srlz_d(); } void diff --git a/sys/ia64/ia64/context.S b/sys/ia64/ia64/context.S index 77a1821..84d8fd1 100644 --- a/sys/ia64/ia64/context.S +++ b/sys/ia64/ia64/context.S @@ -86,18 +86,18 @@ ENTRY(restorectx, 1) { .mmi ld8.fill r6=[r14],16 // r6 ld8.fill r7=[r15],16 // r7 - nop 1 + nop 0 ;; } { .mmi mov ar.unat=r16 mov ar.rsc=3 - nop 2 + nop 0 } { .mmi ld8 r17=[r14],16 // b1 ld8 r18=[r15],16 // b2 - nop 3 + nop 0 ;; } { .mmi @@ -286,7 +286,7 @@ ENTRY(swapctx, 2) (p15) br.ret.sptk rp ;; } -{ .mfb +{ .mib mov r32=r33 nop 0 br.sptk restorectx @@ -338,10 +338,10 @@ ENTRY(save_callee_saved, 1) mov r17=b5 ;; } -{ .mfi +{ .mii st8 [r14]=r17,16 // b5 - nop 0 mov r16=ar.lc + nop 0 ;; } { .mmb @@ -363,13 +363,13 @@ ENTRY(restore_callee_saved, 1) add r31=-8,r32 ;; } -{ .mmb +{ .mmi ld8.fill r4=[r31],16 // r4 ld8.fill r5=[r32],16 // r5 nop 0 ;; } -{ .mmb +{ .mmi ld8.fill r6=[r31],16 // r6 ld8.fill r7=[r32],16 // r7 nop 0 diff --git a/sys/ia64/ia64/db_machdep.c b/sys/ia64/ia64/db_machdep.c index d1163cb..2684bfe 100644 --- a/sys/ia64/ia64/db_machdep.c +++ b/sys/ia64/ia64/db_machdep.c @@ -577,6 +577,13 @@ db_write_bytes(vm_offset_t addr, size_t size, char *data) void db_show_mdpcpu(struct pcpu *pc) { + struct pcpu_md *md = &pc->pc_md; + + db_printf("MD: vhpt = %#lx\n", md->vhpt); + db_printf("MD: lid = %#lx\n", md->lid); + db_printf("MD: clock = %#lx/%#lx\n", md->clock, md->clockadj); + db_printf("MD: stats = %p\n", &md->stats); + db_printf("MD: pmap = %p\n", md->current_pmap); } void diff --git a/sys/ia64/ia64/exception.S b/sys/ia64/ia64/exception.S index 1a5fa32..755a467 100644 --- a/sys/ia64/ia64/exception.S +++ b/sys/ia64/ia64/exception.S @@ -89,10 +89,10 @@ xhead: data8 xtrace addl r29=1024*5*8,r0 ;; \ (p15) sub r27=r28,r29 ;; \ } ; \ -{ .mib ; \ +{ .mmi ; \ st8 [r28]=r27 ; \ - mov pr=r25,0x1ffff ; \ - nop 0 ;; \ + nop 0 ; \ + mov pr=r25,0x1ffff ;; \ } #else @@ -148,10 +148,10 @@ ENTRY_NOPROFILE(exception_save, 0) add r31=8,r30 ;; } -{ .mib +{ .mmi mov r22=cr.iip - addl r29=NTLBRT_SAVE,r0 // 22-bit restart token. nop 0 + addl r29=NTLBRT_SAVE,r0 // 22-bit restart token. ;; } @@ -235,7 +235,7 @@ exception_save_restart: nop 0 ;; } -{ .mmb +{ .mmi (p13) mov ar.rnat=r19 mov r18=ar.bsp nop 0 @@ -248,7 +248,7 @@ exception_save_restart: ;; } // r19=ifs, r22=iip -{ .mmb +{ .mmi st8 [r31]=r18,16 // ndirty st8 [r30]=r19,16 // cfm nop 0 @@ -260,7 +260,7 @@ exception_save_restart: add r29=16,r30 ;; } -{ .mmb +{ .mmi st8 [r30]=r17,24 // ifa st8 [r31]=r18,24 // isr nop 0 @@ -407,7 +407,7 @@ exception_save_restart: movl gp=__gp ;; } -{ .mfb +{ .mib srlz.d nop 0 br.sptk b7 @@ -567,7 +567,7 @@ ENTRY_NOPROFILE(exception_restore, 0) cmp.le p14,p15=5,r28 ;; } -{ .mmb +{ .mmi ld8 r25=[r30] // cfm ld8 r19=[r31] // ip nop 0 @@ -606,13 +606,13 @@ exception_restore_restart: dep r31=0,r31,0,13 // 8KB aligned ;; } -{ .mmb +{ .mmi mov ar.k6=r31 mov ar.rnat=r21 nop 0 ;; } -{ .mmb +{ .mmi mov ar.unat=r17 mov cr.iip=r19 nop 0 @@ -656,7 +656,7 @@ END(exception_restore) add out1=16,sp ; \ br.call.sptk rp=_func_ ;; \ } ; \ -{ .mfb ; \ +{ .mib ; \ nop 0 ; \ nop 0 ; \ br.sptk exception_restore ;; \ @@ -1021,10 +1021,10 @@ IVT_ENTRY(Data_Nested_TLB, 0x1400) movl r27=kstack ;; } -{ .mib +{ .mmi mov r28=sp - addl r27=KSTACK_PAGES*PAGE_SIZE-16,r0 nop 0 + addl r27=KSTACK_PAGES*PAGE_SIZE-16,r0 ;; } { .mmi @@ -1287,13 +1287,13 @@ IVT_ENTRY(Break_Instruction, 0x2c00) (p11) srlz.d add out1=16,sp } -{ .mfb +{ .mib nop 0 nop 0 br.call.sptk rp=trap ;; } -{ .mfb +{ .mib nop 0 nop 0 br.sptk exception_restore @@ -1303,24 +1303,24 @@ IVT_END(Break_Instruction) IVT_ENTRY(External_Interrupt, 0x3000) { .mib - mov r17=cr.ivr // Put the vector in the trap frame. + mov r17=ar.itc // Put the ITC in the trapframe. mov r16=ip br.sptk exception_save ;; } -{ .mfb +{ .mmi alloc r15=ar.pfs,0,0,1,0 nop 0 nop 0 ;; } -{ .mfb +{ .mib add out0=16,sp nop 0 - br.call.sptk rp=interrupt + br.call.sptk rp=ia64_handle_intr ;; } -{ .mfb +{ .mib nop 0 nop 0 br.sptk exception_restore diff --git a/sys/ia64/ia64/highfp.c b/sys/ia64/ia64/highfp.c index 145ee48..f18773b 100644 --- a/sys/ia64/ia64/highfp.c +++ b/sys/ia64/ia64/highfp.c @@ -53,7 +53,7 @@ ia64_highfp_ipi(struct pcpu *cpu) { int error; - ipi_send(cpu, IPI_HIGH_FP); + ipi_send(cpu, ia64_ipi_highfp); error = msleep_spin(&cpu->pc_fpcurthread, &ia64_highfp_mtx, "High FP", 0); return (error); @@ -92,8 +92,6 @@ ia64_highfp_enable(struct thread *td, struct trapframe *tf) pcb = td->td_pcb; mtx_lock_spin(&ia64_highfp_mtx); - KASSERT((tf->tf_special.psr & IA64_PSR_DFH) != 0, - ("(tf->tf_special.psr & IA64_PSR_DFH) == 0")); cpu = pcb->pcb_fpcpu; #ifdef SMP if (cpu != NULL && cpu != pcpup) { diff --git a/sys/ia64/ia64/interrupt.c b/sys/ia64/ia64/interrupt.c index 64b04eb..adb16ec 100644 --- a/sys/ia64/ia64/interrupt.c +++ b/sys/ia64/ia64/interrupt.c @@ -43,6 +43,7 @@ #include <sys/proc.h> #include <sys/vmmeter.h> #include <sys/bus.h> +#include <sys/interrupt.h> #include <sys/malloc.h> #include <sys/ktr.h> #include <sys/lock.h> @@ -52,246 +53,141 @@ #include <sys/sysctl.h> #include <sys/syslog.h> -#include <machine/clock.h> #include <machine/cpu.h> #include <machine/fpu.h> #include <machine/frame.h> #include <machine/intr.h> +#include <machine/intrcnt.h> #include <machine/md_var.h> #include <machine/pcb.h> #include <machine/reg.h> -#include <machine/sapicvar.h> #include <machine/smp.h> -#ifdef EVCNT_COUNTERS -struct evcnt clock_intr_evcnt; /* event counter for clock intrs. */ -#else -#include <sys/interrupt.h> -#include <machine/intrcnt.h> -#endif - #ifdef DDB #include <ddb/ddb.h> #endif -static void ia64_dispatch_intr(void *, u_int); - -static void -dummy_perf(unsigned long vector, struct trapframe *tf) -{ - printf("performance interrupt!\n"); -} - -void (*perf_irq)(unsigned long, struct trapframe *) = dummy_perf; - -SYSCTL_NODE(_debug, OID_AUTO, clock, CTLFLAG_RW, 0, "clock statistics"); - -static int adjust_edges = 0; -SYSCTL_INT(_debug_clock, OID_AUTO, adjust_edges, CTLFLAG_RD, - &adjust_edges, 0, "Number of times ITC got more than 12.5% behind"); +struct ia64_intr { + struct intr_event *event; /* interrupt event */ + volatile long *cntp; /* interrupt counter */ + struct sapic *sapic; + u_int irq; +}; -static int adjust_excess = 0; -SYSCTL_INT(_debug_clock, OID_AUTO, adjust_excess, CTLFLAG_RD, - &adjust_excess, 0, "Total number of ignored ITC interrupts"); +ia64_ihtype *ia64_handler[IA64_NXIVS]; -static int adjust_lost = 0; -SYSCTL_INT(_debug_clock, OID_AUTO, adjust_lost, CTLFLAG_RD, - &adjust_lost, 0, "Total number of lost ITC interrupts"); +static enum ia64_xiv_use ia64_xiv[IA64_NXIVS]; +static struct ia64_intr *ia64_intrs[IA64_NXIVS]; -static int adjust_ticks = 0; -SYSCTL_INT(_debug_clock, OID_AUTO, adjust_ticks, CTLFLAG_RD, - &adjust_ticks, 0, "Total number of ITC interrupts with adjustment"); +static ia64_ihtype ia64_ih_invalid; +static ia64_ihtype ia64_ih_irq; void -interrupt(struct trapframe *tf) +ia64_xiv_init(void) { - struct thread *td; - uint64_t adj, clk, itc; - int64_t delta; - u_int vector; - int count; - uint8_t inta; - - ia64_set_fpsr(IA64_FPSR_DEFAULT); - - td = curthread; + u_int xiv; - PCPU_INC(cnt.v_intr); + for (xiv = 0; xiv < IA64_NXIVS; xiv++) { + ia64_handler[xiv] = ia64_ih_invalid; + ia64_xiv[xiv] = IA64_XIV_FREE; + ia64_intrs[xiv] = NULL; + } + (void)ia64_xiv_reserve(15, IA64_XIV_ARCH, NULL); +} - vector = tf->tf_special.ifa; +int +ia64_xiv_free(u_int xiv, enum ia64_xiv_use what) +{ - next: - /* - * Handle ExtINT interrupts by generating an INTA cycle to - * read the vector. - * IPI_STOP_HARD is mapped to IPI_STOP so it is not necessary - * to add it to this switch-like construct. - */ - if (vector == 0) { - PCPU_INC(md.stats.pcs_nextints); - inta = ia64_ld1(&ia64_pib->ib_inta); - if (inta == 15) { - PCPU_INC(md.stats.pcs_nstrays); - __asm __volatile("mov cr.eoi = r0;; srlz.d"); - goto stray; - } - vector = (int)inta; - } else if (vector == 15) { - PCPU_INC(md.stats.pcs_nstrays); - goto stray; - } + if (xiv >= IA64_NXIVS) + return (EINVAL); + if (what == IA64_XIV_FREE || what == IA64_XIV_ARCH) + return (EINVAL); + if (ia64_xiv[xiv] != what) + return (ENXIO); + ia64_xiv[xiv] = IA64_XIV_FREE; + ia64_handler[xiv] = ia64_ih_invalid; + return (0); +} - if (vector == CLOCK_VECTOR) {/* clock interrupt */ - /* CTR0(KTR_INTR, "clock interrupt"); */ +int +ia64_xiv_reserve(u_int xiv, enum ia64_xiv_use what, ia64_ihtype ih) +{ - itc = ia64_get_itc(); + if (xiv >= IA64_NXIVS) + return (EINVAL); + if (what == IA64_XIV_FREE) + return (EINVAL); + if (ia64_xiv[xiv] != IA64_XIV_FREE) + return (EBUSY); + ia64_xiv[xiv] = what; + ia64_handler[xiv] = (ih == NULL) ? ia64_ih_invalid: ih; + if (bootverbose) + printf("XIV %u: use=%u, IH=%p\n", xiv, what, ih); + return (0); +} - PCPU_INC(md.stats.pcs_nclks); -#ifdef EVCNT_COUNTERS - clock_intr_evcnt.ev_count++; -#else - intrcnt[INTRCNT_CLOCK]++; -#endif +u_int +ia64_xiv_alloc(u_int prio, enum ia64_xiv_use what, ia64_ihtype ih) +{ + u_int hwprio; + u_int xiv0, xiv; - critical_enter(); - - adj = PCPU_GET(md.clockadj); - clk = PCPU_GET(md.clock); - delta = itc - clk; - count = 0; - while (delta >= ia64_clock_reload) { - /* Only the BSP runs the real clock */ - if (PCPU_GET(cpuid) == 0) - hardclock(TRAPF_USERMODE(tf), TRAPF_PC(tf)); - else - hardclock_cpu(TRAPF_USERMODE(tf)); - if (profprocs != 0) - profclock(TRAPF_USERMODE(tf), TRAPF_PC(tf)); - statclock(TRAPF_USERMODE(tf)); - delta -= ia64_clock_reload; - clk += ia64_clock_reload; - if (adj != 0) - adjust_ticks++; - count++; - } - ia64_set_itm(ia64_get_itc() + ia64_clock_reload - adj); - if (count > 0) { - adjust_lost += count - 1; - if (delta > (ia64_clock_reload >> 3)) { - if (adj == 0) - adjust_edges++; - adj = ia64_clock_reload >> 4; - } else - adj = 0; - } else { - adj = 0; - adjust_excess++; - } - PCPU_SET(md.clock, clk); - PCPU_SET(md.clockadj, adj); - critical_exit(); - ia64_srlz_d(); + hwprio = prio >> 2; + if (hwprio > IA64_MAX_HWPRIO) + hwprio = IA64_MAX_HWPRIO; -#ifdef SMP - } else if (vector == ipi_vector[IPI_AST]) { - PCPU_INC(md.stats.pcs_nasts); - CTR1(KTR_SMP, "IPI_AST, cpuid=%d", PCPU_GET(cpuid)); - } else if (vector == ipi_vector[IPI_HIGH_FP]) { - PCPU_INC(md.stats.pcs_nhighfps); - ia64_highfp_save_ipi(); - } else if (vector == ipi_vector[IPI_RENDEZVOUS]) { - PCPU_INC(md.stats.pcs_nrdvs); - CTR1(KTR_SMP, "IPI_RENDEZVOUS, cpuid=%d", PCPU_GET(cpuid)); - enable_intr(); - smp_rendezvous_action(); - disable_intr(); - } else if (vector == ipi_vector[IPI_STOP]) { - PCPU_INC(md.stats.pcs_nstops); - cpumask_t mybit = PCPU_GET(cpumask); - - savectx(PCPU_PTR(md.pcb)); - atomic_set_int(&stopped_cpus, mybit); - while ((started_cpus & mybit) == 0) - cpu_spinwait(); - atomic_clear_int(&started_cpus, mybit); - atomic_clear_int(&stopped_cpus, mybit); - } else if (vector == ipi_vector[IPI_PREEMPT]) { - PCPU_INC(md.stats.pcs_npreempts); - CTR1(KTR_SMP, "IPI_PREEMPT, cpuid=%d", PCPU_GET(cpuid)); - __asm __volatile("mov cr.eoi = r0;; srlz.d"); - enable_intr(); - sched_preempt(curthread); - disable_intr(); - goto stray; -#endif - } else { - PCPU_INC(md.stats.pcs_nhwints); - atomic_add_int(&td->td_intr_nesting_level, 1); - ia64_dispatch_intr(tf, vector); - atomic_subtract_int(&td->td_intr_nesting_level, 1); - } + xiv0 = IA64_NXIVS - (hwprio + 1) * 16; - __asm __volatile("mov cr.eoi = r0;; srlz.d"); - vector = ia64_get_ivr(); - if (vector != 15) - goto next; + KASSERT(xiv0 >= IA64_MIN_XIV, ("%s: min XIV", __func__)); + KASSERT(xiv0 < IA64_NXIVS, ("%s: max XIV", __func__)); -stray: - if (TRAPF_USERMODE(tf)) { - enable_intr(); - userret(td, tf); - mtx_assert(&Giant, MA_NOTOWNED); - do_ast(tf); - } -} + xiv = xiv0; + while (xiv < IA64_NXIVS && ia64_xiv_reserve(xiv, what, ih)) + xiv++; -/* - * Hardware irqs have vectors starting at this offset. - */ -#define IA64_HARDWARE_IRQ_BASE 0x20 + if (xiv < IA64_NXIVS) + return (xiv); -struct ia64_intr { - struct intr_event *event; /* interrupt event */ - volatile long *cntp; /* interrupt counter */ - struct sapic *sapic; - u_int irq; -}; + xiv = xiv0; + while (xiv >= IA64_MIN_XIV && ia64_xiv_reserve(xiv, what, ih)) + xiv--; -static struct ia64_intr *ia64_intrs[256]; + return ((xiv >= IA64_MIN_XIV) ? xiv : 0); +} static void ia64_intr_eoi(void *arg) { - u_int vector = (uintptr_t)arg; + u_int xiv = (uintptr_t)arg; struct ia64_intr *i; - i = ia64_intrs[vector]; - if (i != NULL) - sapic_eoi(i->sapic, vector); + i = ia64_intrs[xiv]; + KASSERT(i != NULL, ("%s", __func__)); + sapic_eoi(i->sapic, xiv); } static void ia64_intr_mask(void *arg) { - u_int vector = (uintptr_t)arg; + u_int xiv = (uintptr_t)arg; struct ia64_intr *i; - i = ia64_intrs[vector]; - if (i != NULL) { - sapic_mask(i->sapic, i->irq); - sapic_eoi(i->sapic, vector); - } + i = ia64_intrs[xiv]; + KASSERT(i != NULL, ("%s", __func__)); + sapic_mask(i->sapic, i->irq); + sapic_eoi(i->sapic, xiv); } static void ia64_intr_unmask(void *arg) { - u_int vector = (uintptr_t)arg; + u_int xiv = (uintptr_t)arg; struct ia64_intr *i; - i = ia64_intrs[vector]; - if (i != NULL) - sapic_unmask(i->sapic, i->irq); + i = ia64_intrs[xiv]; + KASSERT(i != NULL, ("%s", __func__)); + sapic_unmask(i->sapic, i->irq); } int @@ -301,57 +197,79 @@ ia64_setup_intr(const char *name, int irq, driver_filter_t filter, struct ia64_intr *i; struct sapic *sa; char *intrname; - u_int vector; + u_int prio, xiv; int error; - /* Get the I/O SAPIC that corresponds to the IRQ. */ - sa = sapic_lookup(irq); - if (sa == NULL) + prio = intr_priority(flags); + if (prio > PRI_MAX_ITHD) return (EINVAL); + /* XXX lock */ + + /* Get the I/O SAPIC and XIV that corresponds to the IRQ. */ + sa = sapic_lookup(irq, &xiv); + if (sa == NULL) { + /* XXX unlock */ + return (EINVAL); + } + + if (xiv == 0) { + /* XXX unlock */ + i = malloc(sizeof(struct ia64_intr), M_DEVBUF, + M_ZERO | M_WAITOK); + /* XXX lock */ + sa = sapic_lookup(irq, &xiv); + KASSERT(sa != NULL, ("sapic_lookup")); + if (xiv != 0) + free(i, M_DEVBUF); + } + /* - * XXX - There's a priority implied by the choice of vector. - * We should therefore relate the vector to the interrupt type. + * If the IRQ has no XIV assigned to it yet, assign one based + * on the priority. */ - vector = irq + IA64_HARDWARE_IRQ_BASE; - - i = ia64_intrs[vector]; - if (i == NULL) { - i = malloc(sizeof(struct ia64_intr), M_DEVBUF, M_NOWAIT); - if (i == NULL) - return (ENOMEM); + if (xiv == 0) { + xiv = ia64_xiv_alloc(prio, IA64_XIV_IRQ, ia64_ih_irq); + if (xiv == 0) { + /* XXX unlock */ + free(i, M_DEVBUF); + return (ENOSPC); + } - error = intr_event_create(&i->event, (void *)(uintptr_t)vector, + error = intr_event_create(&i->event, (void *)(uintptr_t)xiv, 0, irq, ia64_intr_mask, ia64_intr_unmask, ia64_intr_eoi, NULL, "irq%u:", irq); if (error) { + ia64_xiv_free(xiv, IA64_XIV_IRQ); + /* XXX unlock */ free(i, M_DEVBUF); return (error); } - if (!atomic_cmpset_ptr(&ia64_intrs[vector], NULL, i)) { - intr_event_destroy(i->event); - free(i, M_DEVBUF); - i = ia64_intrs[vector]; - } else { - i->sapic = sa; - i->irq = irq; - - i->cntp = intrcnt + irq + INTRCNT_ISA_IRQ; - if (name != NULL && *name != '\0') { - /* XXX needs abstraction. Too error prone. */ - intrname = intrnames + - (irq + INTRCNT_ISA_IRQ) * INTRNAME_LEN; - memset(intrname, ' ', INTRNAME_LEN - 1); - bcopy(name, intrname, strlen(name)); - } - - sapic_enable(i->sapic, irq, vector); + i->sapic = sa; + i->irq = irq; + i->cntp = intrcnt + xiv; + ia64_intrs[xiv] = i; + + /* XXX unlock */ + + sapic_enable(sa, irq, xiv); + + if (name != NULL && *name != '\0') { + /* XXX needs abstraction. Too error prone. */ + intrname = intrnames + xiv * INTRNAME_LEN; + memset(intrname, ' ', INTRNAME_LEN - 1); + bcopy(name, intrname, strlen(name)); } + } else { + i = ia64_intrs[xiv]; + /* XXX unlock */ } + KASSERT(i != NULL, ("XIV mapping bug")); + error = intr_event_add_handler(i->event, name, filter, handler, arg, - intr_priority(flags), flags, cookiep); + prio, flags, cookiep); return (error); } @@ -362,62 +280,134 @@ ia64_teardown_intr(void *cookie) return (intr_event_remove_handler(cookie)); } -static void -ia64_dispatch_intr(void *frame, u_int vector) +void +ia64_bind_intr(void) +{ + struct ia64_intr *i; + struct pcpu *pc; + u_int xiv; + int cpu; + + cpu = MAXCPU; + for (xiv = IA64_NXIVS - 1; xiv >= IA64_MIN_XIV; xiv--) { + if (ia64_xiv[xiv] != IA64_XIV_IRQ) + continue; + i = ia64_intrs[xiv]; + do { + cpu = (cpu == 0) ? MAXCPU - 1 : cpu - 1; + pc = cpuid_to_pcpu[cpu]; + } while (pc == NULL || !pc->pc_md.awake); + sapic_bind_intr(i->irq, pc); + } +} + +/* + * Interrupt handlers. + */ + +void +ia64_handle_intr(struct trapframe *tf) +{ + struct thread *td; + u_int xiv; + + td = curthread; + ia64_set_fpsr(IA64_FPSR_DEFAULT); + PCPU_INC(cnt.v_intr); + + xiv = ia64_get_ivr(); + ia64_srlz_d(); + if (xiv == 15) { + PCPU_INC(md.stats.pcs_nstrays); + goto out; + } + + critical_enter(); + + do { + CTR2(KTR_INTR, "INTR: ITC=%u, XIV=%u", + (u_int)tf->tf_special.ifa, xiv); + (ia64_handler[xiv])(td, xiv, tf); + ia64_set_eoi(0); + ia64_srlz_d(); + xiv = ia64_get_ivr(); + ia64_srlz_d(); + } while (xiv != 15); + + critical_exit(); + + out: + if (TRAPF_USERMODE(tf)) { + while (td->td_flags & (TDF_ASTPENDING|TDF_NEEDRESCHED)) { + ia64_enable_intr(); + ast(tf); + ia64_disable_intr(); + } + } +} + +static u_int +ia64_ih_invalid(struct thread *td, u_int xiv, struct trapframe *tf) +{ + + panic("invalid XIV: %u", xiv); + return (0); +} + +static u_int +ia64_ih_irq(struct thread *td, u_int xiv, struct trapframe *tf) { struct ia64_intr *i; struct intr_event *ie; /* our interrupt event */ - /* - * Find the interrupt thread for this vector. - */ - i = ia64_intrs[vector]; - KASSERT(i != NULL, ("%s: unassigned vector", __func__)); + PCPU_INC(md.stats.pcs_nhwints); + + /* Find the interrupt thread for this XIV. */ + i = ia64_intrs[xiv]; + KASSERT(i != NULL, ("%s: unassigned XIV", __func__)); (*i->cntp)++; ie = i->event; KASSERT(ie != NULL, ("%s: interrupt without event", __func__)); - if (intr_event_handle(ie, frame) != 0) { - /* - * XXX: The pre-INTR_FILTER code didn't mask stray - * interrupts. - */ - ia64_intr_mask((void *)(uintptr_t)vector); + if (intr_event_handle(ie, tf) != 0) { + ia64_intr_mask((void *)(uintptr_t)xiv); log(LOG_ERR, "stray irq%u\n", i->irq); } + + return (0); } #ifdef DDB static void -db_print_vector(u_int vector, int always) +db_print_xiv(u_int xiv, int always) { struct ia64_intr *i; - i = ia64_intrs[vector]; + i = ia64_intrs[xiv]; if (i != NULL) { - db_printf("vector %u (%p): ", vector, i); + db_printf("XIV %u (%p): ", xiv, i); sapic_print(i->sapic, i->irq); } else if (always) - db_printf("vector %u: unassigned\n", vector); + db_printf("XIV %u: unassigned\n", xiv); } -DB_SHOW_COMMAND(vector, db_show_vector) +DB_SHOW_COMMAND(xiv, db_show_xiv) { - u_int vector; + u_int xiv; if (have_addr) { - vector = ((addr >> 4) % 16) * 10 + (addr % 16); - if (vector >= 256) - db_printf("error: vector %u not in range [0..255]\n", - vector); + xiv = ((addr >> 4) % 16) * 10 + (addr % 16); + if (xiv >= IA64_NXIVS) + db_printf("error: XIV %u not in range [0..%u]\n", + xiv, IA64_NXIVS - 1); else - db_print_vector(vector, 1); + db_print_xiv(xiv, 1); } else { - for (vector = 0; vector < 256; vector++) - db_print_vector(vector, 0); + for (xiv = 0; xiv < IA64_NXIVS; xiv++) + db_print_xiv(xiv, 0); } } diff --git a/sys/ia64/ia64/locore.S b/sys/ia64/ia64/locore.S index 6b1d8f1..ce66dca 100644 --- a/sys/ia64/ia64/locore.S +++ b/sys/ia64/ia64/locore.S @@ -26,16 +26,13 @@ * $FreeBSD$ */ +#include <sys/syscall.h> #include <machine/asm.h> #include <machine/ia64_cpu.h> +#include <machine/intrcnt.h> #include <machine/pte.h> -#include <sys/syscall.h> -#include <assym.s> - -#ifndef EVCNT_COUNTERS -#define _LOCORE #include <machine/intrcnt.h> -#endif +#include <assym.s> .section .data.proc0,"aw" .global kstack @@ -98,13 +95,13 @@ ENTRY_NOPROFILE(__start, 1) mov out0=r0 // we are linked at the right address ;; // we just need to process fptrs } -{ .bbb +{ .mib nop 0 nop 0 br.call.sptk.many rp=_reloc ;; } -{ .bbb +{ .mib nop 0 nop 0 br.call.sptk.many rp=ia64_init @@ -112,21 +109,21 @@ ENTRY_NOPROFILE(__start, 1) } // We have the new bspstore in r8 and the new sp in r9. // Switch onto the new stack and call mi_startup(). -{ +{ .mmi mov ar.rsc = 0 ;; mov ar.bspstore = r8 mov sp = r9 ;; } -{ +{ .mmi loadrs ;; mov ar.rsc = 3 nop 0 ;; } -{ +{ .mib nop 0 nop 0 br.call.sptk.many rp=mi_startup @@ -163,7 +160,7 @@ ENTRY(fork_trampoline, 0) ld8 out1=[r16] nop 0 } -{ .mfb +{ .mib add out2=16,sp nop 0 br.call.sptk rp=fork_exit @@ -174,7 +171,7 @@ ENTRY(fork_trampoline, 0) .global enter_userland .type enter_userland, @function enter_userland: -{ .mfb +{ .mib nop 0 nop 0 br.sptk epc_syscall_return @@ -282,7 +279,7 @@ ENTRY_NOPROFILE(os_boot_rendez,0) add sp = r18, r16 ;; } -{ .mfb +{ .mib mov ar.rsc = 3 nop 0 br.call.sptk.few rp = ia64_ap_startup @@ -290,7 +287,7 @@ ENTRY_NOPROFILE(os_boot_rendez,0) } /* NOT REACHED */ 9: -{ .mfb +{ .mib nop 0 nop 0 br.sptk 9b @@ -310,7 +307,7 @@ EXPORT(intrnames) .ascii "clock" .fill INTRNAME_LEN - 5 - 1, 1, ' ' .byte 0 -intr_n = 0 +intr_n = 1 .rept INTRCNT_COUNT - 1 .ascii "#" .byte intr_n / 100 + '0' diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c index c3e7654..e2e9f91 100644 --- a/sys/ia64/ia64/machdep.c +++ b/sys/ia64/ia64/machdep.c @@ -80,7 +80,6 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_pager.h> #include <machine/bootinfo.h> -#include <machine/clock.h> #include <machine/cpu.h> #include <machine/efi.h> #include <machine/elf.h> @@ -100,8 +99,6 @@ __FBSDID("$FreeBSD$"); #include <machine/unwind.h> #include <machine/vmparam.h> -#include <i386/include/specialreg.h> - SYSCTL_NODE(_hw, OID_AUTO, freq, CTLFLAG_RD, 0, ""); SYSCTL_NODE(_machdep, OID_AUTO, cpu, CTLFLAG_RD, 0, ""); @@ -374,19 +371,12 @@ cpu_startup(void *dummy) SYSCTL_ADD_ULONG(&pc->pc_md.sysctl_ctx, SYSCTL_CHILDREN(pc->pc_md.sysctl_tree), OID_AUTO, "nstrays", CTLFLAG_RD, &pcs->pcs_nstrays, - "Number of stray vectors"); + "Number of stray interrupts"); } } SYSINIT(cpu_startup, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL); void -cpu_boot(int howto) -{ - - efi_reset_system(); -} - -void cpu_flush_dcache(void *ptr, size_t len) { vm_offset_t lim, va; @@ -441,7 +431,7 @@ void cpu_reset() { - cpu_boot(0); + efi_reset_system(); } void @@ -456,19 +446,23 @@ cpu_switch(struct thread *old, struct thread *new, struct mtx *mtx) if (PCPU_GET(fpcurthread) == old) old->td_frame->tf_special.psr |= IA64_PSR_DFH; if (!savectx(oldpcb)) { - old->td_lock = mtx; -#if defined(SCHED_ULE) && defined(SMP) - /* td_lock is volatile */ - while (new->td_lock == &blocked_lock) - ; -#endif + atomic_store_rel_ptr(&old->td_lock, mtx); + newpcb = new->td_pcb; oldpcb->pcb_current_pmap = pmap_switch(newpcb->pcb_current_pmap); + +#if defined(SCHED_ULE) && defined(SMP) + while (atomic_load_acq_ptr(&new->td_lock) == &blocked_lock) + cpu_spinwait(); +#endif + PCPU_SET(curthread, new); + #ifdef COMPAT_IA32 ia32_restorectx(newpcb); #endif + if (PCPU_GET(fpcurthread) == new) new->td_frame->tf_special.psr &= ~IA64_PSR_DFH; restorectx(newpcb); @@ -485,10 +479,18 @@ cpu_throw(struct thread *old __unused, struct thread *new) newpcb = new->td_pcb; (void)pmap_switch(newpcb->pcb_current_pmap); + +#if defined(SCHED_ULE) && defined(SMP) + while (atomic_load_acq_ptr(&new->td_lock) == &blocked_lock) + cpu_spinwait(); +#endif + PCPU_SET(curthread, new); + #ifdef COMPAT_IA32 ia32_restorectx(newpcb); #endif + restorectx(newpcb); /* We should not get here. */ panic("cpu_throw: restorectx() returned"); @@ -716,16 +718,6 @@ ia64_init(void) */ boothowto = bootinfo.bi_boothowto; - /* - * 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; - } - freeenv(p); - } - if (boothowto & RB_VERBOSE) bootverbose = 1; @@ -779,6 +771,7 @@ ia64_init(void) */ map_pal_code(); efi_boot_minimal(bootinfo.bi_systab); + ia64_xiv_init(); ia64_sal_init(); calculate_frequencies(); @@ -793,7 +786,7 @@ ia64_init(void) init_param1(); p = getenv("kernelname"); - if (p) { + if (p != NULL) { strncpy(kernelname, p, sizeof(kernelname) - 1); freeenv(p); } diff --git a/sys/ia64/ia64/mp_machdep.c b/sys/ia64/ia64/mp_machdep.c index c5ed48f..600803a 100644 --- a/sys/ia64/ia64/mp_machdep.c +++ b/sys/ia64/ia64/mp_machdep.c @@ -46,11 +46,6 @@ __FBSDID("$FreeBSD$"); #include <sys/sysctl.h> #include <sys/uuid.h> -#include <vm/vm.h> -#include <vm/pmap.h> -#include <vm/vm_extern.h> -#include <vm/vm_kern.h> - #include <machine/atomic.h> #include <machine/cpu.h> #include <machine/fpu.h> @@ -59,10 +54,13 @@ __FBSDID("$FreeBSD$"); #include <machine/md_var.h> #include <machine/pal.h> #include <machine/pcb.h> -#include <machine/pmap.h> #include <machine/sal.h> #include <machine/smp.h> -#include <i386/include/specialreg.h> + +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_extern.h> +#include <vm/vm_kern.h> MALLOC_DEFINE(M_SMP, "SMP", "SMP related allocations"); @@ -81,7 +79,68 @@ volatile int ap_delay; volatile int ap_awake; volatile int ap_spin; -static void cpu_mp_unleash(void *); +int ia64_ipi_ast; +int ia64_ipi_highfp; +int ia64_ipi_nmi; +int ia64_ipi_preempt; +int ia64_ipi_rndzvs; +int ia64_ipi_stop; + +static u_int +ia64_ih_ast(struct thread *td, u_int xiv, struct trapframe *tf) +{ + + PCPU_INC(md.stats.pcs_nasts); + CTR1(KTR_SMP, "IPI_AST, cpuid=%d", PCPU_GET(cpuid)); + return (0); +} + +static u_int +ia64_ih_highfp(struct thread *td, u_int xiv, struct trapframe *tf) +{ + + PCPU_INC(md.stats.pcs_nhighfps); + ia64_highfp_save_ipi(); + return (0); +} + +static u_int +ia64_ih_preempt(struct thread *td, u_int xiv, struct trapframe *tf) +{ + + PCPU_INC(md.stats.pcs_npreempts); + CTR1(KTR_SMP, "IPI_PREEMPT, cpuid=%d", PCPU_GET(cpuid)); + sched_preempt(curthread); + return (0); +} + +static u_int +ia64_ih_rndzvs(struct thread *td, u_int xiv, struct trapframe *tf) +{ + + PCPU_INC(md.stats.pcs_nrdvs); + CTR1(KTR_SMP, "IPI_RENDEZVOUS, cpuid=%d", PCPU_GET(cpuid)); + smp_rendezvous_action(); + return (0); +} + +static u_int +ia64_ih_stop(struct thread *td, u_int xiv, struct trapframe *tf) +{ + cpumask_t mybit; + + PCPU_INC(md.stats.pcs_nstops); + mybit = PCPU_GET(cpumask); + + savectx(PCPU_PTR(md.pcb)); + + atomic_set_int(&stopped_cpus, mybit); + while ((started_cpus & mybit) == 0) + cpu_spinwait(); + atomic_clear_int(&started_cpus, mybit); + atomic_clear_int(&stopped_cpus, mybit); + return (0); +} struct cpu_group * cpu_topo(void) @@ -116,7 +175,6 @@ void ia64_ap_startup(void) { uint64_t vhpt; - int vector; pcpup = ap_pcpu; ia64_set_k4((intptr_t)pcpup); @@ -148,24 +206,11 @@ ia64_ap_startup(void) CTR1(KTR_SMP, "SMP: cpu%d launched", PCPU_GET(cpuid)); - /* Acknowledge and EOI all interrupts. */ - vector = ia64_get_ivr(); - while (vector != 15) { - ia64_srlz_d(); - if (vector == 0) - vector = (int)ia64_ld1(&ia64_pib->ib_inta); - ia64_set_eoi(0); - ia64_srlz_d(); - vector = ia64_get_ivr(); - } - ia64_srlz_d(); - - /* kick off the clock on this AP */ - pcpu_initclock(); - + /* Mask interval timer interrupts on APs. */ + ia64_set_itv(0x10000); ia64_set_tpr(0); ia64_srlz_d(); - enable_intr(); + ia64_enable_intr(); sched_throw(NULL); /* NOTREACHED */ @@ -200,7 +245,7 @@ cpu_mp_probe(void) * case we can have multiple processors, but we simply can't wake * them up... */ - return (mp_ncpus > 1 && ipi_vector[IPI_AP_WAKEUP] != 0); + return (mp_ncpus > 1 && ia64_ipi_wakeup != 0); } void @@ -276,7 +321,7 @@ cpu_mp_start() if (bootverbose) printf("SMP: waking up cpu%d\n", pc->pc_cpuid); - ipi_send(pc, IPI_AP_WAKEUP); + ipi_send(pc, ia64_ipi_wakeup); do { DELAY(1000); @@ -300,6 +345,18 @@ cpu_mp_unleash(void *dummy) if (mp_ncpus <= 1) return; + /* Allocate XIVs for IPIs */ + ia64_ipi_ast = ia64_xiv_alloc(PI_DULL, IA64_XIV_IPI, ia64_ih_ast); + ia64_ipi_highfp = ia64_xiv_alloc(PI_AV, IA64_XIV_IPI, ia64_ih_highfp); + ia64_ipi_preempt = ia64_xiv_alloc(PI_SOFT, IA64_XIV_IPI, + ia64_ih_preempt); + ia64_ipi_rndzvs = ia64_xiv_alloc(PI_AV, IA64_XIV_IPI, ia64_ih_rndzvs); + ia64_ipi_stop = ia64_xiv_alloc(PI_REALTIME, IA64_XIV_IPI, ia64_ih_stop); + + /* Reserve the NMI vector for IPI_STOP_HARD if possible */ + ia64_ipi_nmi = (ia64_xiv_reserve(2, IA64_XIV_IPI, ia64_ih_stop) != 0) + ? ia64_ipi_stop : 0x400; /* DM=NMI, Vector=n/a */ + cpus = 0; smp_cpus = 0; SLIST_FOREACH(pc, &cpuhead, pc_allcpu) { @@ -325,6 +382,12 @@ cpu_mp_unleash(void *dummy) smp_active = 1; smp_started = 1; + + /* + * Now that all CPUs are up and running, bind interrupts to each of + * them. + */ + ia64_bind_intr(); } /* @@ -361,20 +424,18 @@ ipi_all_but_self(int ipi) * fields are used here. */ void -ipi_send(struct pcpu *cpu, int ipi) +ipi_send(struct pcpu *cpu, int xiv) { u_int lid; - uint8_t vector; + + KASSERT(xiv != 0, ("ipi_send")); lid = LID_SAPIC(cpu->pc_md.lid); - vector = ipi_vector[ipi]; - KASSERT(vector != 0, ("IPI %d is not assigned a vector", ipi)); ia64_mf(); - ia64_st8(&(ia64_pib->ib_ipi[lid][0]), vector); + ia64_st8(&(ia64_pib->ib_ipi[lid][0]), xiv); ia64_mf_a(); - CTR4(KTR_SMP, "ipi_send(%p, %ld): cpuid=%d, vector=%u", cpu, ipi, - PCPU_GET(cpuid), vector); + CTR3(KTR_SMP, "ipi_send(%p, %d): cpuid=%d", cpu, xiv, PCPU_GET(cpuid)); } SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, cpu_mp_unleash, NULL); diff --git a/sys/ia64/ia64/nexus.c b/sys/ia64/ia64/nexus.c index 5ce4731..9885b74 100644 --- a/sys/ia64/ia64/nexus.c +++ b/sys/ia64/ia64/nexus.c @@ -50,16 +50,15 @@ #include <machine/bus.h> #include <sys/rman.h> #include <sys/interrupt.h> +#include <sys/pcpu.h> #include <vm/vm.h> #include <vm/pmap.h> #include <machine/efi.h> #include <machine/intr.h> -#include <machine/nexusvar.h> #include <machine/pmap.h> #include <machine/resource.h> -#include <machine/sapicvar.h> #include <machine/vmparam.h> #include <contrib/dev/acpica/include/acpi.h> @@ -74,12 +73,11 @@ static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device"); struct nexus_device { struct resource_list nx_resources; - int nx_pcibus; }; #define DEVTONX(dev) ((struct nexus_device *)device_get_ivars(dev)) -static struct rman irq_rman, drq_rman, port_rman, mem_rman; +static struct rman irq_rman, port_rman, mem_rman; static int nexus_probe(device_t); static int nexus_attach(device_t); @@ -88,8 +86,6 @@ static device_t nexus_add_child(device_t bus, int order, const char *name, int unit); static struct resource *nexus_alloc_resource(device_t, device_t, int, int *, u_long, u_long, u_long, u_int); -static int nexus_read_ivar(device_t, device_t, int, uintptr_t *); -static int nexus_write_ivar(device_t, device_t, int, uintptr_t); static int nexus_activate_resource(device_t, device_t, int, int, struct resource *); static int nexus_deactivate_resource(device_t, device_t, int, int, @@ -106,6 +102,7 @@ static int nexus_set_resource(device_t, device_t, int, int, u_long, u_long); static int nexus_get_resource(device_t, device_t, int, int, u_long *, u_long *); static void nexus_delete_resource(device_t, device_t, int, int); +static int nexus_bind_intr(device_t, device_t, struct resource *, int); static int nexus_config_intr(device_t, int, enum intr_trigger, enum intr_polarity); @@ -124,8 +121,6 @@ static device_method_t nexus_methods[] = { /* Bus interface */ DEVMETHOD(bus_print_child, nexus_print_child), DEVMETHOD(bus_add_child, nexus_add_child), - DEVMETHOD(bus_read_ivar, nexus_read_ivar), - DEVMETHOD(bus_write_ivar, nexus_write_ivar), DEVMETHOD(bus_alloc_resource, nexus_alloc_resource), DEVMETHOD(bus_release_resource, nexus_release_resource), DEVMETHOD(bus_activate_resource, nexus_activate_resource), @@ -136,6 +131,7 @@ static device_method_t nexus_methods[] = { DEVMETHOD(bus_set_resource, nexus_set_resource), DEVMETHOD(bus_get_resource, nexus_get_resource), DEVMETHOD(bus_delete_resource, nexus_delete_resource), + DEVMETHOD(bus_bind_intr, nexus_bind_intr), DEVMETHOD(bus_config_intr, nexus_config_intr), /* Clock interface */ @@ -160,56 +156,15 @@ nexus_probe(device_t dev) device_quiet(dev); /* suppress attach message for neatness */ - /* - * XXX working notes: - * - * - IRQ resource creation should be moved to the PIC/APIC driver. - * - DRQ resource creation should be moved to the DMAC driver. - * - The above should be sorted to probe earlier than any child busses. - * - * - Leave I/O and memory creation here, as child probes may need them. - * (especially eg. ACPI) - */ - - /* - * IRQ's are on the mainboard on old systems, but on the ISA part - * of PCI->ISA bridges. There would be multiple sets of IRQs on - * multi-ISA-bus systems. PCI interrupts are routed to the ISA - * component, so in a way, PCI can be a partial child of an ISA bus(!). - * APIC interrupts are global though. - * - * XXX We depend on the AT PIC driver correctly claiming IRQ 2 - * to prevent its reuse elsewhere in the !APIC_IO case. - */ - irq_rman.rm_start = 0; irq_rman.rm_type = RMAN_ARRAY; irq_rman.rm_descr = "Interrupt request lines"; - irq_rman.rm_end = 255; + irq_rman.rm_start = 0; + irq_rman.rm_end = IA64_NXIVS - 1; if (rman_init(&irq_rman) || rman_manage_region(&irq_rman, irq_rman.rm_start, irq_rman.rm_end)) panic("nexus_probe irq_rman"); - /* - * ISA DMA on PCI systems is implemented in the ISA part of each - * PCI->ISA bridge and the channels can be duplicated if there are - * multiple bridges. (eg: laptops with docking stations) - */ - drq_rman.rm_start = 0; - drq_rman.rm_end = 7; - drq_rman.rm_type = RMAN_ARRAY; - drq_rman.rm_descr = "DMA request lines"; - /* XXX drq 0 not available on some machines */ - if (rman_init(&drq_rman) - || rman_manage_region(&drq_rman, - drq_rman.rm_start, drq_rman.rm_end)) - panic("nexus_probe drq_rman"); - - /* - * However, IO ports and Memory truely are global at this level, - * as are APIC interrupts (however many IO APICS there turn out - * to be on large systems..) - */ port_rman.rm_start = 0; port_rman.rm_end = 0xffff; port_rman.rm_type = RMAN_ARRAY; @@ -257,8 +212,6 @@ nexus_print_child(device_t bus, device_t child) retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx"); retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#lx"); retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); - if (ndev->nx_pcibus != -1) - retval += printf(" pcibus %d", ndev->nx_pcibus); if (device_get_flags(child)) retval += printf(" flags %#x", device_get_flags(child)); retval += printf(" on motherboard\n"); /* XXX "motherboard", ick */ @@ -276,7 +229,6 @@ nexus_add_child(device_t bus, int order, const char *name, int unit) if (!ndev) return(0); resource_list_init(&ndev->nx_resources); - ndev->nx_pcibus = -1; child = device_add_child_ordered(bus, order, name, unit); @@ -286,37 +238,6 @@ nexus_add_child(device_t bus, int order, const char *name, int unit) return(child); } -static int -nexus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) -{ - struct nexus_device *ndev = DEVTONX(child); - - switch (which) { - case NEXUS_IVAR_PCIBUS: - *result = ndev->nx_pcibus; - break; - default: - return ENOENT; - } - return 0; -} - - -static int -nexus_write_ivar(device_t dev, device_t child, int which, uintptr_t value) -{ - struct nexus_device *ndev = DEVTONX(child); - - switch (which) { - case NEXUS_IVAR_PCIBUS: - ndev->nx_pcibus = value; - break; - default: - return ENOENT; - } - return 0; -} - /* * Allocate a resource on behalf of child. NB: child is usually going to be a @@ -356,10 +277,6 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, rm = &irq_rman; break; - case SYS_RES_DRQ: - rm = &drq_rman; - break; - case SYS_RES_IOPORT: rm = &port_rman; break; @@ -548,6 +465,17 @@ nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, } static int +nexus_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu) +{ + struct pcpu *pc; + + pc = cpuid_to_pcpu[cpu]; + if (pc == NULL) + return (EINVAL); + return (sapic_bind_intr(rman_get_start(irq), pc)); +} + +static int nexus_gettime(device_t dev, struct timespec *ts) { struct clocktime ct; @@ -592,4 +520,3 @@ nexus_settime(device_t dev, struct timespec *ts) tm.tm_mday = ct.day; return (efi_set_time(&tm)); } - diff --git a/sys/ia64/ia64/pmap.c b/sys/ia64/ia64/pmap.c index f829746..6fe4cdf 100644 --- a/sys/ia64/ia64/pmap.c +++ b/sys/ia64/ia64/pmap.c @@ -238,7 +238,7 @@ static pv_entry_t get_pv_entry(pmap_t locked_pmap); static void pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot); static void pmap_free_pte(struct ia64_lpte *pte, vm_offset_t va); -static void pmap_invalidate_all(pmap_t pmap); +static void pmap_invalidate_all(void); static int pmap_remove_pte(pmap_t pmap, struct ia64_lpte *pte, vm_offset_t va, pv_entry_t pv, int freepte); static int pmap_remove_vhpt(vm_offset_t va); @@ -475,7 +475,7 @@ pmap_bootstrap() /* * Clear out any random TLB entries left over from booting. */ - pmap_invalidate_all(kernel_pmap); + pmap_invalidate_all(); map_gateway_page(); } @@ -536,21 +536,19 @@ pmap_init(void) ***************************************************/ static void -pmap_invalidate_page(pmap_t pmap, vm_offset_t va) +pmap_invalidate_page(vm_offset_t va) { struct ia64_lpte *pte; struct pcpu *pc; + uint64_t tag; u_int vhpt_ofs; - KASSERT((pmap == kernel_pmap || pmap == PCPU_GET(md.current_pmap)), - ("invalidating TLB for non-current pmap")); - - vhpt_ofs = ia64_thash(va) - PCPU_GET(md.vhpt); critical_enter(); + vhpt_ofs = ia64_thash(va) - PCPU_GET(md.vhpt); + tag = ia64_ttag(va); SLIST_FOREACH(pc, &cpuhead, pc_allcpu) { pte = (struct ia64_lpte *)(pc->pc_md.vhpt + vhpt_ofs); - if (pte->tag == ia64_ttag(va)) - pte->tag = 1UL << 63; + atomic_cmpset_64(&pte->tag, tag, 1UL << 63); } critical_exit(); mtx_lock_spin(&pmap_ptcmutex); @@ -577,16 +575,14 @@ pmap_invalidate_all_1(void *arg) } static void -pmap_invalidate_all(pmap_t pmap) +pmap_invalidate_all(void) { - KASSERT((pmap == kernel_pmap || pmap == PCPU_GET(md.current_pmap)), - ("invalidating TLB for non-current pmap")); - #ifdef SMP - if (mp_ncpus > 1) + if (mp_ncpus > 1) { smp_rendezvous(NULL, pmap_invalidate_all_1, NULL, NULL); - else + return; + } #endif pmap_invalidate_all_1(NULL); } @@ -794,7 +790,7 @@ retry: pte = pmap_find_vhpt(va); KASSERT(pte != NULL, ("pte")); pmap_remove_vhpt(va); - pmap_invalidate_page(pmap, va); + pmap_invalidate_page(va); pmap_switch(oldpmap); if (pmap_accessed(pte)) vm_page_flag_set(m, PG_REFERENCED); @@ -1160,9 +1156,6 @@ pmap_remove_pte(pmap_t pmap, struct ia64_lpte *pte, vm_offset_t va, int error; vm_page_t m; - KASSERT((pmap == kernel_pmap || pmap == PCPU_GET(md.current_pmap)), - ("removing pte for non-current pmap")); - /* * First remove from the VHPT. */ @@ -1170,7 +1163,7 @@ pmap_remove_pte(pmap_t pmap, struct ia64_lpte *pte, vm_offset_t va, if (error) return (error); - pmap_invalidate_page(pmap, va); + pmap_invalidate_page(va); if (pmap_wired(pte)) pmap->pm_stats.wired_count -= 1; @@ -1238,7 +1231,7 @@ pmap_qenter(vm_offset_t va, vm_page_t *m, int count) for (i = 0; i < count; i++) { pte = pmap_find_kpte(va); if (pmap_present(pte)) - pmap_invalidate_page(kernel_pmap, va); + pmap_invalidate_page(va); else pmap_enter_vhpt(pte, va); pmap_pte_prot(kernel_pmap, pte, VM_PROT_ALL); @@ -1261,7 +1254,7 @@ pmap_qremove(vm_offset_t va, int count) pte = pmap_find_kpte(va); if (pmap_present(pte)) { pmap_remove_vhpt(va); - pmap_invalidate_page(kernel_pmap, va); + pmap_invalidate_page(va); pmap_clear_present(pte); } va += PAGE_SIZE; @@ -1279,7 +1272,7 @@ pmap_kenter(vm_offset_t va, vm_offset_t pa) pte = pmap_find_kpte(va); if (pmap_present(pte)) - pmap_invalidate_page(kernel_pmap, va); + pmap_invalidate_page(va); else pmap_enter_vhpt(pte, va); pmap_pte_prot(kernel_pmap, pte, VM_PROT_ALL); @@ -1297,7 +1290,7 @@ pmap_kremove(vm_offset_t va) pte = pmap_find_kpte(va); if (pmap_present(pte)) { pmap_remove_vhpt(va); - pmap_invalidate_page(kernel_pmap, va); + pmap_invalidate_page(va); pmap_clear_present(pte); } } @@ -1321,23 +1314,6 @@ pmap_map(vm_offset_t *virt, vm_offset_t start, vm_offset_t end, int prot) } /* - * Remove a single page from a process address space - */ -static void -pmap_remove_page(pmap_t pmap, vm_offset_t va) -{ - struct ia64_lpte *pte; - - KASSERT((pmap == kernel_pmap || pmap == PCPU_GET(md.current_pmap)), - ("removing page for non-current pmap")); - - pte = pmap_find_vhpt(va); - if (pte != NULL) - pmap_remove_pte(pmap, pte, va, 0, 1); - return; -} - -/* * Remove the given range of addresses from the specified map. * * It is assumed that the start and end are properly @@ -1364,7 +1340,9 @@ pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) * code. */ if (sva + PAGE_SIZE == eva) { - pmap_remove_page(pmap, sva); + pte = pmap_find_vhpt(sva); + if (pte != NULL) + pmap_remove_pte(pmap, pte, sva, 0, 1); goto out; } @@ -1491,7 +1469,7 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) ia64_sync_icache(sva, PAGE_SIZE); pmap_pte_prot(pmap, pte, prot); - pmap_invalidate_page(pmap, sva); + pmap_invalidate_page(sva); } vm_page_unlock_queues(); pmap_switch(oldpmap); @@ -1582,7 +1560,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_prot_t access, vm_page_t m, else if (pmap_exec(&origpte)) icache_inval = FALSE; - pmap_invalidate_page(pmap, va); + pmap_invalidate_page(va); goto validate; } @@ -1929,7 +1907,8 @@ pmap_remove_pages(pmap_t pmap) pv_entry_t pv, npv; if (pmap != vmspace_pmap(curthread->td_proc->p_vmspace)) { - printf("warning: pmap_remove_pages called with non-current pmap\n"); + printf("warning: %s called with non-current pmap\n", + __func__); return; } @@ -1984,7 +1963,7 @@ pmap_ts_referenced(vm_page_t m) if (pmap_accessed(pte)) { count++; pmap_clear_accessed(pte); - pmap_invalidate_page(pv->pv_pmap, pv->pv_va); + pmap_invalidate_page(pv->pv_va); } pmap_switch(oldpmap); PMAP_UNLOCK(pv->pv_pmap); @@ -2063,7 +2042,7 @@ pmap_clear_modify(vm_page_t m) KASSERT(pte != NULL, ("pte")); if (pmap_dirty(pte)) { pmap_clear_dirty(pte); - pmap_invalidate_page(pv->pv_pmap, pv->pv_va); + pmap_invalidate_page(pv->pv_va); } pmap_switch(oldpmap); PMAP_UNLOCK(pv->pv_pmap); @@ -2092,7 +2071,7 @@ pmap_clear_reference(vm_page_t m) KASSERT(pte != NULL, ("pte")); if (pmap_accessed(pte)) { pmap_clear_accessed(pte); - pmap_invalidate_page(pv->pv_pmap, pv->pv_va); + pmap_invalidate_page(pv->pv_va); } pmap_switch(oldpmap); PMAP_UNLOCK(pv->pv_pmap); @@ -2128,7 +2107,7 @@ pmap_remove_write(vm_page_t m) } prot &= ~VM_PROT_WRITE; pmap_pte_prot(pmap, pte, prot); - pmap_invalidate_page(pmap, pv->pv_va); + pmap_invalidate_page(pv->pv_va); } pmap_switch(oldpmap); PMAP_UNLOCK(pmap); diff --git a/sys/ia64/ia64/sal.c b/sys/ia64/ia64/sal.c index 4f46d65..6f081be 100644 --- a/sys/ia64/ia64/sal.c +++ b/sys/ia64/ia64/sal.c @@ -29,21 +29,18 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> +#include <sys/bus.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <vm/vm.h> #include <vm/vm_kern.h> #include <machine/efi.h> +#include <machine/intr.h> #include <machine/md_var.h> #include <machine/sal.h> #include <machine/smp.h> -/* - * IPIs are used more genericly than only - * for inter-processor interrupts. Don't - * make it a SMP specific thing... - */ -int ipi_vector[IPI_COUNT]; +int ia64_ipi_wakeup; static struct ia64_fdesc sal_fdesc; static sal_entry_t fake_sal; @@ -66,22 +63,6 @@ fake_sal(u_int64_t a1, u_int64_t a2, u_int64_t a3, u_int64_t a4, return res; } -static void -setup_ipi_vectors(int ceil) -{ - int ipi; - - ipi_vector[IPI_MCA_RENDEZ] = ceil - 0x10; - - ipi = IPI_AST; /* First generic IPI. */ - ceil -= 0x20; /* First vector in group. */ - while (ipi < IPI_COUNT) - ipi_vector[ipi++] = ceil++; - - ipi_vector[IPI_HIGH_FP] = ceil - 0x30; - ipi_vector[IPI_MCA_CMCV] = ceil - 0x30 + 1; -} - void ia64_sal_init(void) { @@ -89,7 +70,7 @@ ia64_sal_init(void) 48, 32, 16, 32, 16, 16 }; u_int8_t *p; - int i; + int error, i; sal_systbl = efi_get_table(&sal_table); if (sal_systbl == NULL) @@ -132,36 +113,19 @@ ia64_sal_init(void) break; } - if (dp->sale_vector < 0x10 || dp->sale_vector > 0xff) { - printf("SAL: invalid AP wake-up vector " - "(0x%lx)\n", dp->sale_vector); - break; - } - - /* - * SAL documents that the wake-up vector should be - * high (close to 255). The MCA rendezvous vector - * should be less than the wake-up vector, but still - * "high". We use the following priority assignment: - * Wake-up: priority of the sale_vector - * Rendezvous: priority-1 - * Generic IPIs: priority-2 - * Special IPIs: priority-3 - * Consequently, the wake-up priority should be at - * least 4 (ie vector >= 0x40). - */ - if (dp->sale_vector < 0x40) { - printf("SAL: AP wake-up vector too low " - "(0x%lx)\n", dp->sale_vector); + /* Reserve the XIV so that we won't use it. */ + error = ia64_xiv_reserve(dp->sale_vector, + IA64_XIV_PLAT, NULL); + if (error) { + printf("SAL: invalid AP wake-up XIV (%#lx)\n", + dp->sale_vector); break; } + ia64_ipi_wakeup = dp->sale_vector; if (bootverbose) - printf("SAL: AP wake-up vector: 0x%lx\n", - dp->sale_vector); - - ipi_vector[IPI_AP_WAKEUP] = dp->sale_vector; - setup_ipi_vectors(dp->sale_vector & 0xf0); + printf("SAL: AP wake-up XIV: %#x\n", + ia64_ipi_wakeup); #ifdef SMP fd = (struct ia64_fdesc *) os_boot_rendez; @@ -175,7 +139,4 @@ ia64_sal_init(void) } p += sizes[*p]; } - - if (ipi_vector[IPI_AP_WAKEUP] == 0) - setup_ipi_vectors(0xf0); } diff --git a/sys/ia64/ia64/sapic.c b/sys/ia64/ia64/sapic.c index 88bd013..5aa1449 100644 --- a/sys/ia64/ia64/sapic.c +++ b/sys/ia64/ia64/sapic.c @@ -35,81 +35,105 @@ #include <sys/bus.h> #include <sys/lock.h> #include <sys/mutex.h> +#include <sys/pcpu.h> #include <sys/sysctl.h> #include <machine/intr.h> #include <machine/pal.h> -#include <machine/sapicreg.h> -#include <machine/sapicvar.h> #include <vm/vm.h> #include <vm/pmap.h> -static MALLOC_DEFINE(M_SAPIC, "sapic", "I/O SAPIC devices"); - -static int sysctl_machdep_apic(SYSCTL_HANDLER_ARGS); - -SYSCTL_OID(_machdep, OID_AUTO, apic, CTLTYPE_STRING|CTLFLAG_RD, - NULL, 0, sysctl_machdep_apic, "A", "(x)APIC redirection table entries"); +/* + * Offsets from the SAPIC base in memory. Most registers are accessed + * by indexing using the SAPIC_IO_SELECT register. + */ +#define SAPIC_IO_SELECT 0x00 +#define SAPIC_IO_WINDOW 0x10 +#define SAPIC_APIC_EOI 0x40 -struct sapic *ia64_sapics[16]; /* XXX make this resizable */ -int ia64_sapic_count; +/* + * Indexed registers. + */ +#define SAPIC_ID 0x00 +#define SAPIC_VERSION 0x01 +#define SAPIC_ARBITRATION_ID 0x02 +#define SAPIC_RTE_BASE 0x10 + +/* Interrupt polarity. */ +#define SAPIC_POLARITY_HIGH 0 +#define SAPIC_POLARITY_LOW 1 + +/* Interrupt trigger. */ +#define SAPIC_TRIGGER_EDGE 0 +#define SAPIC_TRIGGER_LEVEL 1 + +/* Interrupt delivery mode. */ +#define SAPIC_DELMODE_FIXED 0 +#define SAPIC_DELMODE_LOWPRI 1 +#define SAPIC_DELMODE_PMI 2 +#define SAPIC_DELMODE_NMI 4 +#define SAPIC_DELMODE_INIT 5 +#define SAPIC_DELMODE_EXTINT 7 + +struct sapic { + struct mtx sa_mtx; + uint64_t sa_registers; /* virtual address of sapic */ + u_int sa_id; /* I/O SAPIC Id */ + u_int sa_base; /* ACPI vector base */ + u_int sa_limit; /* last ACPI vector handled here */ +}; struct sapic_rte { - u_int64_t rte_vector :8; - u_int64_t rte_delivery_mode :3; - u_int64_t rte_destination_mode :1; - u_int64_t rte_delivery_status :1; - u_int64_t rte_polarity :1; - u_int64_t rte_rirr :1; - u_int64_t rte_trigger_mode :1; - u_int64_t rte_mask :1; - u_int64_t rte_flushen :1; - u_int64_t rte_reserved :30; - u_int64_t rte_destination_eid :8; - u_int64_t rte_destination_id :8; + uint64_t rte_vector :8; + uint64_t rte_delivery_mode :3; + uint64_t rte_destination_mode :1; + uint64_t rte_delivery_status :1; + uint64_t rte_polarity :1; + uint64_t rte_rirr :1; + uint64_t rte_trigger_mode :1; + uint64_t rte_mask :1; + uint64_t rte_flushen :1; + uint64_t rte_reserved :30; + uint64_t rte_destination_eid :8; + uint64_t rte_destination_id :8; }; -struct sapic * -sapic_lookup(u_int irq) -{ - struct sapic *sa; - int i; +MALLOC_DEFINE(M_SAPIC, "sapic", "I/O SAPIC devices"); - for (i = 0; i < ia64_sapic_count; i++) { - sa = ia64_sapics[i]; - if (irq >= sa->sa_base && irq <= sa->sa_limit) - return (sa); - } +struct sapic *ia64_sapics[16]; /* XXX make this resizable */ +int ia64_sapic_count; - return (NULL); -} +static int sysctl_machdep_apic(SYSCTL_HANDLER_ARGS); -static __inline u_int32_t +SYSCTL_OID(_machdep, OID_AUTO, apic, CTLTYPE_STRING|CTLFLAG_RD, + NULL, 0, sysctl_machdep_apic, "A", "(x)APIC redirection table entries"); + +static __inline uint32_t sapic_read(struct sapic *sa, int which) { - vm_offset_t reg = sa->sa_registers; + uint32_t value; - *(volatile u_int32_t *) (reg + SAPIC_IO_SELECT) = which; - ia64_mf(); - return *(volatile u_int32_t *) (reg + SAPIC_IO_WINDOW); + ia64_st4((void *)(sa->sa_registers + SAPIC_IO_SELECT), which); + ia64_mf_a(); + value = ia64_ld4((void *)(sa->sa_registers + SAPIC_IO_WINDOW)); + return (value); } static __inline void -sapic_write(struct sapic *sa, int which, u_int32_t value) +sapic_write(struct sapic *sa, int which, uint32_t value) { - vm_offset_t reg = sa->sa_registers; - *(volatile u_int32_t *) (reg + SAPIC_IO_SELECT) = which; - ia64_mf(); - *(volatile u_int32_t *) (reg + SAPIC_IO_WINDOW) = value; - ia64_mf(); + ia64_st4((void *)(sa->sa_registers + SAPIC_IO_SELECT), which); + ia64_mf_a(); + ia64_st4((void *)(sa->sa_registers + SAPIC_IO_WINDOW), value); + ia64_mf_a(); } static __inline void sapic_read_rte(struct sapic *sa, int which, struct sapic_rte *rte) { - u_int32_t *p = (u_int32_t *) rte; + uint32_t *p = (uint32_t *) rte; p[0] = sapic_read(sa, SAPIC_RTE_BASE + 2 * which); p[1] = sapic_read(sa, SAPIC_RTE_BASE + 2 * which + 1); @@ -118,10 +142,54 @@ sapic_read_rte(struct sapic *sa, int which, struct sapic_rte *rte) static __inline void sapic_write_rte(struct sapic *sa, int which, struct sapic_rte *rte) { - u_int32_t *p = (u_int32_t *) rte; + uint32_t *p = (uint32_t *) rte; + + sapic_write(sa, SAPIC_RTE_BASE + 2 * which, p[0]); + sapic_write(sa, SAPIC_RTE_BASE + 2 * which + 1, p[1]); +} + +struct sapic * +sapic_lookup(u_int irq, u_int *vecp) +{ + struct sapic_rte rte; + struct sapic *sa; + int i; + + for (i = 0; i < ia64_sapic_count; i++) { + sa = ia64_sapics[i]; + if (irq >= sa->sa_base && irq <= sa->sa_limit) { + if (vecp != NULL) { + mtx_lock_spin(&sa->sa_mtx); + sapic_read_rte(sa, irq - sa->sa_base, &rte); + mtx_unlock_spin(&sa->sa_mtx); + *vecp = rte.rte_vector; + } + return (sa); + } + } + + return (NULL); +} + + +int +sapic_bind_intr(u_int irq, struct pcpu *pc) +{ + struct sapic_rte rte; + struct sapic *sa; + + sa = sapic_lookup(irq, NULL); + if (sa == NULL) + return (EINVAL); - sapic_write(sa, SAPIC_RTE_BASE + 2 *which, p[0]); - sapic_write(sa, SAPIC_RTE_BASE + 2 *which + 1, p[1]); + mtx_lock_spin(&sa->sa_mtx); + sapic_read_rte(sa, irq - sa->sa_base, &rte); + rte.rte_destination_id = (pc->pc_md.lid >> 24) & 255; + rte.rte_destination_eid = (pc->pc_md.lid >> 16) & 255; + rte.rte_delivery_mode = SAPIC_DELMODE_FIXED; + sapic_write_rte(sa, irq - sa->sa_base, &rte); + mtx_unlock_spin(&sa->sa_mtx); + return (0); } int @@ -130,7 +198,7 @@ sapic_config_intr(u_int irq, enum intr_trigger trig, enum intr_polarity pol) struct sapic_rte rte; struct sapic *sa; - sa = sapic_lookup(irq); + sa = sapic_lookup(irq, NULL); if (sa == NULL) return (EINVAL); @@ -154,7 +222,7 @@ sapic_config_intr(u_int irq, enum intr_trigger trig, enum intr_polarity pol) } struct sapic * -sapic_create(u_int id, u_int base, u_int64_t address) +sapic_create(u_int id, u_int base, uint64_t address) { struct sapic_rte rte; struct sapic *sa; @@ -214,10 +282,9 @@ sapic_enable(struct sapic *sa, u_int irq, u_int vector) void sapic_eoi(struct sapic *sa, u_int vector) { - vm_offset_t reg = sa->sa_registers; - *(volatile u_int32_t *)(reg + SAPIC_APIC_EOI) = vector; - ia64_mf(); + ia64_st4((void *)(sa->sa_registers + SAPIC_APIC_EOI), vector); + ia64_mf_a(); } /* Expected to be called with interrupts disabled. */ diff --git a/sys/ia64/ia64/support.S b/sys/ia64/ia64/support.S index ea04276..1a82dd6 100644 --- a/sys/ia64/ia64/support.S +++ b/sys/ia64/ia64/support.S @@ -227,14 +227,14 @@ ENTRY(casuword, 3) nop 0 ;; } -{ .mfb +{ .mib st8.rel [r15]=r0 // Clear onfault nop 0 br.ret.sptk rp ;; } 1: -{ .mfb +{ .mib add ret0=-1,r0 nop 0 br.ret.sptk rp @@ -277,14 +277,14 @@ ENTRY(casuword32, 3) nop 0 ;; } -{ .mfb +{ .mib st8.rel [r15]=r0 // Clear onfault nop 0 br.ret.sptk rp ;; } 1: -{ .mfb +{ .mib add ret0=-1,r0 nop 0 br.ret.sptk rp @@ -338,7 +338,7 @@ ENTRY(subyte, 2) ;; } 1: -{ .mfb +{ .mib add ret0=-1,r0 nop 0 br.ret.sptk rp @@ -384,7 +384,7 @@ ENTRY(suword16, 2) ;; } 1: -{ .mfb +{ .mib add ret0=-1,r0 nop 0 br.ret.sptk rp @@ -430,7 +430,7 @@ ENTRY(suword32, 2) ;; } 1: -{ .mfb +{ .mib add ret0=-1,r0 nop 0 br.ret.sptk rp @@ -477,7 +477,7 @@ XENTRY(suword) ;; } 1: -{ .mfb +{ .mib add ret0=-1,r0 nop 0 br.ret.sptk rp @@ -531,7 +531,7 @@ ENTRY(fubyte, 1) ;; } 1: -{ .mfb +{ .mib add ret0=-1,r0 nop 0 br.ret.sptk rp @@ -577,7 +577,7 @@ ENTRY(fuword16, 2) ;; } 1: -{ .mfb +{ .mib add ret0=-1,r0 nop 0 br.ret.sptk rp @@ -623,7 +623,7 @@ ENTRY(fuword32, 2) ;; } 1: -{ .mfb +{ .mib add ret0=-1,r0 nop 0 br.ret.sptk rp @@ -670,7 +670,7 @@ XENTRY(fuword) ;; } 1: -{ .mfb +{ .mib add ret0=-1,r0 nop 0 br.ret.sptk rp @@ -684,7 +684,7 @@ END(fuword64) */ ENTRY(fuswintr, 1) -{ .mfb +{ .mib add ret0=-1,r0 nop 0 br.ret.sptk rp @@ -693,7 +693,7 @@ ENTRY(fuswintr, 1) END(fuswintr) ENTRY(suswintr, 0) -{ .mfb +{ .mib add ret0=-1,r0 nop 0 br.ret.sptk rp diff --git a/sys/ia64/ia64/syscall.S b/sys/ia64/ia64/syscall.S index 73f8da6..b35523a 100644 --- a/sys/ia64/ia64/syscall.S +++ b/sys/ia64/ia64/syscall.S @@ -102,13 +102,13 @@ gw_ret: ;; } gw_ret_ia32: -{ .mfb +{ .mmi flushrs nop 0 nop 0 ;; } -{ .mfb +{ .mib nop 0 nop 0 br.ia.sptk b6 @@ -193,7 +193,7 @@ ENTRY_NOPROFILE(epc_sigtramp, 0) mov b7=r16 ;; } -{ .mmb +{ .mmi alloc r14=ar.pfs, 0, 0, 3, 0 mov ar.rsc=15 nop 0 @@ -204,7 +204,7 @@ ENTRY_NOPROFILE(epc_sigtramp, 0) mov out0=r8 mov out1=r9 } -{ .mfb +{ .mib add out2=16,sp nop 0 br.call.sptk rp=b7 @@ -257,7 +257,7 @@ ENTRY_NOPROFILE(epc_syscall, 8) add r31=8,r30 ;; } -{ .mib +{ .mii mov r22=ar.fpsr sub r29=r14,r30 nop 0 @@ -380,7 +380,7 @@ ENTRY_NOPROFILE(epc_syscall, 8) } .global epc_syscall_return epc_syscall_return: -{ .mfb +{ .mib add out0=16,sp nop 0 br.call.sptk rp=do_ast @@ -392,7 +392,7 @@ epc_syscall_return: (p15) br.spnt 1b // restart syscall ;; } -{ .mfb +{ .mmi ld8 r14=[r14] // tf_flags nop 0 nop 0 @@ -422,7 +422,7 @@ epc_syscall_return: add r31=r31,sp ;; } -{ .mmb +{ .mmi ld8 r19=[r15],16 // pr ld8 r20=[r14],16 // pfs (syscall caller) nop 0 @@ -434,7 +434,7 @@ epc_syscall_return: mov pr=r19,0x1fffe ;; } -{ .mmb +{ .mmi ld8 r23=[r15],16 // tp ld8 r24=[r14],16 // rsc nop 0 @@ -488,7 +488,7 @@ epc_syscall_return: dep r30=0,r30,0,13 // 8KB aligned. ;; } -{ .mib +{ .mii mov ar.k6=r30 mov r13=r23 nop 0 diff --git a/sys/ia64/ia64/trap.c b/sys/ia64/ia64/trap.c index c966f0a..2e59d75 100644 --- a/sys/ia64/ia64/trap.c +++ b/sys/ia64/ia64/trap.c @@ -334,11 +334,11 @@ int do_ast(struct trapframe *tf) { - disable_intr(); + ia64_disable_intr(); while (curthread->td_flags & (TDF_ASTPENDING|TDF_NEEDRESCHED)) { - enable_intr(); + ia64_enable_intr(); ast(tf); - disable_intr(); + ia64_disable_intr(); } /* * Keep interrupts disabled. We return r10 as a favor to the EPC @@ -804,7 +804,7 @@ trap(int vector, struct trapframe *tf) * out of the gateway page we'll get back into the kernel * and then we enable single stepping. * Since this a rather round-about way of enabling single - * stepping, don't make things complicated even more by + * stepping, don't make things even more complicated by * calling userret() and do_ast(). We do that later... */ tf->tf_special.psr &= ~IA64_PSR_LP; @@ -815,13 +815,14 @@ trap(int vector, struct trapframe *tf) /* * Don't assume there aren't any branches other than the * branch that takes us out of the gateway page. Check the - * iip and raise SIGTRAP only when it's an user address. + * iip and enable single stepping only when it's an user + * address. */ if (tf->tf_special.iip >= VM_MAX_ADDRESS) return; tf->tf_special.psr &= ~IA64_PSR_TB; - sig = SIGTRAP; - break; + tf->tf_special.psr |= IA64_PSR_SS; + return; case IA64_VEC_IA32_EXCEPTION: case IA64_VEC_IA32_INTERCEPT: diff --git a/sys/ia64/ia64/vm_machdep.c b/sys/ia64/ia64/vm_machdep.c index 37af94b..6222d33 100644 --- a/sys/ia64/ia64/vm_machdep.c +++ b/sys/ia64/ia64/vm_machdep.c @@ -70,6 +70,7 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> +#include <sys/lock.h> #include <sys/malloc.h> #include <sys/bio.h> #include <sys/buf.h> @@ -89,14 +90,11 @@ #include <vm/vm.h> #include <vm/vm_param.h> -#include <sys/lock.h> #include <vm/vm_kern.h> #include <vm/vm_page.h> #include <vm/vm_map.h> #include <vm/vm_extern.h> -#include <i386/include/psl.h> - void cpu_thread_exit(struct thread *td) { diff --git a/sys/ia64/include/acpica_machdep.h b/sys/ia64/include/acpica_machdep.h index 26191c0..38efffd 100644 --- a/sys/ia64/include/acpica_machdep.h +++ b/sys/ia64/include/acpica_machdep.h @@ -56,8 +56,8 @@ #define ACPI_ASM_MACROS #define BREAKPOINT3 -#define ACPI_DISABLE_IRQS() disable_intr() -#define ACPI_ENABLE_IRQS() enable_intr() +#define ACPI_DISABLE_IRQS() ia64_disable_intr() +#define ACPI_ENABLE_IRQS() ia64_enable_intr() #define ACPI_FLUSH_CPU_CACHE() /* XXX ia64_fc()? */ diff --git a/sys/ia64/include/clock.h b/sys/ia64/include/clock.h index 772fc2a..6b87a89 100644 --- a/sys/ia64/include/clock.h +++ b/sys/ia64/include/clock.h @@ -9,12 +9,4 @@ #ifndef _MACHINE_CLOCK_H_ #define _MACHINE_CLOCK_H_ -#ifdef _KERNEL - -#define CLOCK_VECTOR 254 - -extern uint64_t ia64_clock_reload; - -#endif - #endif /* !_MACHINE_CLOCK_H_ */ diff --git a/sys/ia64/include/cpufunc.h b/sys/ia64/include/cpufunc.h index 9ae06a2..925d4ba 100644 --- a/sys/ia64/include/cpufunc.h +++ b/sys/ia64/include/cpufunc.h @@ -56,13 +56,13 @@ breakpoint(void) static __inline void -disable_intr(void) +ia64_disable_intr(void) { __asm __volatile ("rsm psr.i"); } static __inline void -enable_intr(void) +ia64_enable_intr(void) { __asm __volatile ("ssm psr.i;; srlz.d"); } @@ -71,8 +71,9 @@ static __inline register_t intr_disable(void) { register_t psr; + __asm __volatile ("mov %0=psr;;" : "=r"(psr)); - disable_intr(); + ia64_disable_intr(); return ((psr & IA64_PSR_I) ? 1 : 0); } @@ -80,7 +81,7 @@ static __inline void intr_restore(register_t ie) { if (ie) - enable_intr(); + ia64_enable_intr(); } #endif /* __GNUCLIKE_ASM */ diff --git a/sys/ia64/include/frame.h b/sys/ia64/include/frame.h index 262a8bf..683d164 100644 --- a/sys/ia64/include/frame.h +++ b/sys/ia64/include/frame.h @@ -29,7 +29,9 @@ #ifndef _MACHINE_FRAME_H_ #define _MACHINE_FRAME_H_ +#ifndef _MACHINE_REGSET_H_ #include <machine/_regset.h> +#endif /* * Software trap, exception, and syscall frame. diff --git a/sys/ia64/include/intr.h b/sys/ia64/include/intr.h index 8651fda..81603cf 100644 --- a/sys/ia64/include/intr.h +++ b/sys/ia64/include/intr.h @@ -30,6 +30,16 @@ #ifndef _MACHINE_INTR_H_ #define _MACHINE_INTR_H_ +#define IA64_NXIVS 256 /* External Interrupt Vectors */ +#define IA64_MIN_XIV 16 + +#define IA64_MAX_HWPRIO 14 + +struct pcpu; +struct sapic; +struct thread; +struct trapframe; + /* * Layout of the Processor Interrupt Block. */ @@ -44,10 +54,40 @@ struct ia64_pib uint8_t _rsvd4[0x1fff0]; }; +enum ia64_xiv_use { + IA64_XIV_FREE, + IA64_XIV_ARCH, /* Architecturally defined. */ + IA64_XIV_PLAT, /* Platform defined. */ + IA64_XIV_IPI, /* Used for IPIs. */ + IA64_XIV_IRQ /* Used for external interrupts. */ +}; + +typedef u_int (ia64_ihtype)(struct thread *, u_int, struct trapframe *); + extern struct ia64_pib *ia64_pib; -int ia64_setup_intr(const char *name, int irq, driver_filter_t filter, - driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep); -int ia64_teardown_intr(void *cookie); +void ia64_bind_intr(void); +void ia64_handle_intr(struct trapframe *); +int ia64_setup_intr(const char *, int, driver_filter_t, driver_intr_t, + void *, enum intr_type, void **); +int ia64_teardown_intr(void *); + +void ia64_xiv_init(void); +u_int ia64_xiv_alloc(u_int, enum ia64_xiv_use, ia64_ihtype); +int ia64_xiv_free(u_int, enum ia64_xiv_use); +int ia64_xiv_reserve(u_int, enum ia64_xiv_use, ia64_ihtype); + +int sapic_bind_intr(u_int, struct pcpu *); +int sapic_config_intr(u_int, enum intr_trigger, enum intr_polarity); +struct sapic *sapic_create(u_int, u_int, uint64_t); +int sapic_enable(struct sapic *, u_int, u_int); +void sapic_eoi(struct sapic *, u_int); +struct sapic *sapic_lookup(u_int, u_int *); +void sapic_mask(struct sapic *, u_int); +void sapic_unmask(struct sapic *, u_int); + +#ifdef DDB +void sapic_print(struct sapic *, u_int); +#endif #endif /* !_MACHINE_INTR_H_ */ diff --git a/sys/ia64/include/intrcnt.h b/sys/ia64/include/intrcnt.h index c4f73c0..5e165ea 100644 --- a/sys/ia64/include/intrcnt.h +++ b/sys/ia64/include/intrcnt.h @@ -29,11 +29,7 @@ */ #define INTRCNT_CLOCK 0 -#define INTRCNT_ISA_IRQ (INTRCNT_CLOCK + 1) -#define INTRCNT_ISA_IRQ_LEN 16 -#define INTRCNT_OTHER_BASE (INTRCNT_ISA_IRQ + INTRCNT_ISA_IRQ_LEN) -#define INTRCNT_OTHER_LEN 240 -#define INTRCNT_COUNT (INTRCNT_OTHER_BASE + INTRCNT_OTHER_LEN) +#define INTRCNT_COUNT 256 /* * Maximum name length in intrnames table (including terminating '\0'. diff --git a/sys/ia64/include/mca.h b/sys/ia64/include/mca.h index 75831c7..94926d1 100644 --- a/sys/ia64/include/mca.h +++ b/sys/ia64/include/mca.h @@ -39,6 +39,7 @@ struct mca_record_header { #define MCA_RH_ERROR_CORRECTED 2 uint8_t rh_flags; #define MCA_RH_FLAGS_PLATFORM_ID 0x01 /* Platform_id present. */ +#define MCA_RH_FLAGS_TIME_STAMP 0x02 /* Timestamp invalid. */ uint32_t rh_length; /* Size including header. */ uint8_t rh_time[8]; #define MCA_RH_TIME_SEC 0 diff --git a/sys/ia64/include/nexusvar.h b/sys/ia64/include/nexusvar.h deleted file mode 100644 index be38f33..0000000 --- a/sys/ia64/include/nexusvar.h +++ /dev/null @@ -1,43 +0,0 @@ -/*- - * Copyright (c) 2000 Peter Wemm <peter@FreeBSD.org> - * 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_NEXUSVAR_H_ -#define _MACHINE_NEXUSVAR_H_ 1 - -enum nexus_device_ivars { - NEXUS_IVAR_PCIBUS -}; - -#define NEXUS_ACCESSOR(var, ivar, type) \ - __BUS_ACCESSOR(nexus, var, NEXUS, ivar, type) - -NEXUS_ACCESSOR(pcibus, PCIBUS, u_int32_t) - -#undef NEXUS_ACCESSOR - -#endif /* !_MACHINE_NEXUSVAR_H_ */ diff --git a/sys/ia64/include/pcb.h b/sys/ia64/include/pcb.h index 5d250bf..59334bf 100644 --- a/sys/ia64/include/pcb.h +++ b/sys/ia64/include/pcb.h @@ -30,7 +30,9 @@ #ifndef _MACHINE_PCB_H_ #define _MACHINE_PCB_H_ +#ifndef _MACHINE_REGSET_H_ #include <machine/_regset.h> +#endif /* * PCB: process control block diff --git a/sys/ia64/include/pci_cfgreg.h b/sys/ia64/include/pci_cfgreg.h index b4d2702..a0bc6e1 100644 --- a/sys/ia64/include/pci_cfgreg.h +++ b/sys/ia64/include/pci_cfgreg.h @@ -1,4 +1,5 @@ /*- + * Copyright (c) 2010 Marcel Moolenaar <marcel@FreeBSD.org> * Copyright (c) 1997, Stefan Esser <se@freebsd.org> * All rights reserved. * @@ -24,9 +25,14 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ - * */ -extern int pci_cfgregopen(void); -extern u_int32_t pci_cfgregread(int bus, int slot, int func, int reg, int bytes); -extern void pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes); +#ifndef _MACHINE_PCI_CFGREG_H_ +#define _MACHINE_PCI_CFGREG_H_ + +int pci_cfgregopen(void); +uint32_t pci_cfgregread(int bus, int slot, int func, int reg, int len); +void pci_cfgregwrite(int bus, int slot, int func, int reg, uint32_t data, + int bytes); + +#endif /* _MACHINE_PCI_CFGREG_H_ */ diff --git a/sys/ia64/include/pcpu.h b/sys/ia64/include/pcpu.h index bc9fe08..3c6e6a7 100644 --- a/sys/ia64/include/pcpu.h +++ b/sys/ia64/include/pcpu.h @@ -70,6 +70,16 @@ struct pcpu; register struct pcpu *pcpup __asm__("r13"); +static __inline struct thread * +__curthread(void) +{ + struct thread *td; + + __asm __volatile("ld8.acq %0=[r13]" : "=r"(td)); + return (td); +} +#define curthread (__curthread()) + #define PCPU_GET(member) (pcpup->pc_ ## member) /* @@ -81,8 +91,6 @@ register struct pcpu *pcpup __asm__("r13"); #define PCPU_PTR(member) (&pcpup->pc_ ## member) #define PCPU_SET(member,value) (pcpup->pc_ ## member = (value)) -void pcpu_initclock(void); - #endif /* _KERNEL */ #endif /* !_MACHINE_PCPU_H_ */ diff --git a/sys/ia64/include/sapicreg.h b/sys/ia64/include/sapicreg.h deleted file mode 100644 index 8f7dfbd..0000000 --- a/sys/ia64/include/sapicreg.h +++ /dev/null @@ -1,48 +0,0 @@ -/*- - * Copyright (c) 2001 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_SAPICREG_H_ -#define _MACHINE_SAPICREG_H_ - -/* - * Offsets from the SAPIC base in memory. Most registers are accessed - * by indexing using the SAPIC_IO_SELECT register. - */ -#define SAPIC_IO_SELECT 0x00 -#define SAPIC_IO_WINDOW 0x10 -#define SAPIC_APIC_EOI 0x40 - -/* - * Indexed registers. - */ -#define SAPIC_ID 0x00 -#define SAPIC_VERSION 0x01 -#define SAPIC_ARBITRATION_ID 0x02 -#define SAPIC_RTE_BASE 0x10 - -#endif /* ! _MACHINE_SAPICREG_H_ */ diff --git a/sys/ia64/include/sapicvar.h b/sys/ia64/include/sapicvar.h deleted file mode 100644 index 30a353c..0000000 --- a/sys/ia64/include/sapicvar.h +++ /dev/null @@ -1,65 +0,0 @@ -/*- - * Copyright (c) 2001 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_SAPICVAR_H_ -#define _MACHINE_SAPICVAR_H_ - -struct sapic { - struct mtx sa_mtx; - vm_offset_t sa_registers; /* virtual address of sapic */ - u_int sa_id; /* I/O SAPIC Id */ - u_int sa_base; /* ACPI vector base */ - u_int sa_limit; /* last ACPI vector handled here */ -}; - -#define SAPIC_TRIGGER_EDGE 0 -#define SAPIC_TRIGGER_LEVEL 1 - -#define SAPIC_POLARITY_HIGH 0 -#define SAPIC_POLARITY_LOW 1 - -#define SAPIC_DELMODE_FIXED 0 -#define SAPIC_DELMODE_LOWPRI 1 -#define SAPIC_DELMODE_PMI 2 -#define SAPIC_DELMODE_NMI 4 -#define SAPIC_DELMODE_INIT 5 -#define SAPIC_DELMODE_EXTINT 7 - -int sapic_config_intr(u_int irq, enum intr_trigger, enum intr_polarity); -struct sapic *sapic_create(u_int id, u_int base, uint64_t address); -int sapic_enable(struct sapic *sa, u_int irq, u_int vector); -void sapic_eoi(struct sapic *sa, u_int vector); -struct sapic *sapic_lookup(u_int irq); -void sapic_mask(struct sapic *sa, u_int irq); -void sapic_unmask(struct sapic *sa, u_int irq); - -#ifdef DDB -void sapic_print(struct sapic *sa, u_int irq); -#endif - -#endif /* ! _MACHINE_SAPICVAR_H_ */ diff --git a/sys/ia64/include/smp.h b/sys/ia64/include/smp.h index 4eddf74..9f976de 100644 --- a/sys/ia64/include/smp.h +++ b/sys/ia64/include/smp.h @@ -6,31 +6,23 @@ #ifdef _KERNEL -/* - * Interprocessor interrupts for SMP. The following values are indices - * into the IPI vector table. The SAL gives us the vector used for AP - * wake-up. We base the other vectors on that. Keep IPI_AP_WAKEUP at - * index 0. See sal.c for details. - */ -/* Architecture specific IPIs. */ -#define IPI_AP_WAKEUP 0 -#define IPI_HIGH_FP 1 -#define IPI_MCA_CMCV 2 -#define IPI_MCA_RENDEZ 3 -/* Machine independent IPIs. */ -#define IPI_AST 4 -#define IPI_RENDEZVOUS 5 -#define IPI_STOP 6 -#define IPI_STOP_HARD 6 -#define IPI_PREEMPT 7 - -#define IPI_COUNT 8 +#define IPI_AST ia64_ipi_ast +#define IPI_PREEMPT ia64_ipi_preempt +#define IPI_RENDEZVOUS ia64_ipi_rndzvs +#define IPI_STOP ia64_ipi_stop +#define IPI_STOP_HARD ia64_ipi_nmi #ifndef LOCORE struct pcpu; -extern int ipi_vector[]; +extern int ia64_ipi_ast; +extern int ia64_ipi_highfp; +extern int ia64_ipi_nmi; +extern int ia64_ipi_preempt; +extern int ia64_ipi_rndzvs; +extern int ia64_ipi_stop; +extern int ia64_ipi_wakeup; void ipi_all_but_self(int ipi); void ipi_selected(cpumask_t cpus, int ipi); diff --git a/sys/ia64/pci/pci_cfgreg.c b/sys/ia64/pci/pci_cfgreg.c index cef743b..00d8397 100644 --- a/sys/ia64/pci/pci_cfgreg.c +++ b/sys/ia64/pci/pci_cfgreg.c @@ -1,4 +1,5 @@ /*- + * Copyright (c) 2010 Marcel Moolenaar * Copyright (c) 2001 Doug Rabson * All rights reserved. * @@ -27,38 +28,77 @@ */ #include <sys/param.h> +#include <machine/cpufunc.h> #include <machine/pci_cfgreg.h> #include <machine/sal.h> -#define SAL_PCI_ADDRESS(bus, slot, func, reg) \ - (((bus) << 16) | ((slot) << 11) | ((func) << 8) | (reg)) +static u_long +pci_sal_address(int dom, int bus, int slot, int func, int reg) +{ + u_long addr; + + addr = ~0ul; + if (dom >= 0 && dom <= 255 && bus >= 0 && bus <= 255 && + slot >= 0 && slot <= 31 && func >= 0 && func <= 7 && + reg >= 0 && reg <= 255) { + addr = ((u_long)dom << 24) | ((u_long)bus << 16) | + ((u_long)slot << 11) | ((u_long)func << 8) | (u_long)reg; + } + return (addr); +} + +static int +pci_valid_access(int reg, int len) +{ + int ok; + + ok = ((len == 1 || len == 2 || len == 4) && (reg & (len - 1)) == 0) + ? 1 : 0; + return (ok); +} int pci_cfgregopen(void) { - return 1; + return (1); } -u_int32_t -pci_cfgregread(int bus, int slot, int func, int reg, int bytes) +uint32_t +pci_cfgregread(int bus, int slot, int func, int reg, int len) { struct ia64_sal_result res; + register_t is; + u_long addr; - res = ia64_sal_entry(SAL_PCI_CONFIG_READ, - SAL_PCI_ADDRESS(bus, slot, func, reg), - bytes, 0, 0, 0, 0, 0); - if (res.sal_status < 0) + addr = pci_sal_address(0, bus, slot, func, reg); + if (addr == ~0ul) return (~0); - else - return (res.sal_result[0]); + + if (!pci_valid_access(reg, len)) + return (~0); + + is = intr_disable(); + res = ia64_sal_entry(SAL_PCI_CONFIG_READ, addr, len, 0, 0, 0, 0, 0); + intr_restore(is); + + return ((res.sal_status < 0) ? ~0 : res.sal_result[0]); } void -pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes) +pci_cfgregwrite(int bus, int slot, int func, int reg, uint32_t data, int len) { struct ia64_sal_result res; + register_t is; + u_long addr; + + addr = pci_sal_address(0, bus, slot, func, reg); + if (addr == ~0ul) + return; + + if (!pci_valid_access(reg, len)) + return; - res = ia64_sal_entry(SAL_PCI_CONFIG_WRITE, - SAL_PCI_ADDRESS(bus, slot, func, reg), - bytes, data, 0, 0, 0, 0); + is = intr_disable(); + res = ia64_sal_entry(SAL_PCI_CONFIG_WRITE, addr, len, data, 0, 0, 0, 0); + intr_restore(is); } diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 9b7d550..cad745d 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -562,10 +562,7 @@ _zfs= zfs .endif .if ${MACHINE_ARCH} == "ia64" -# Modules not enabled on ia64 (as compared to i386) include: -# aac acpi aout apm atspeaker drm ibcs2 linprocfs linux ncv -# nsp s3 sbni stg vesa -# acpi is not enabled because it is broken as a module on ia64 +_aac= aac _aic= aic _an= an _arcnet= arcnet @@ -578,12 +575,17 @@ _cm= cm _cmx= cmx _coff= coff _cpufreq= cpufreq +_dpt= dpt _em= em _ep= ep +_et= et _exca= exca _fe= fe +_hptiop= hptiop +_ida= ida _igb= igb _iir= iir +_ips= ips _mly= mly _pccard= pccard _scsi_low= scsi_low @@ -592,6 +594,7 @@ _sound= sound _splash= splash _sppp= sppp _streams= streams +_twa= twa _wi= wi _xe= xe .endif |