summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordfr <dfr@FreeBSD.org>2000-10-12 17:47:01 +0000
committerdfr <dfr@FreeBSD.org>2000-10-12 17:47:01 +0000
commit345b5e7cc0c5ecf57573b08d6267a32c42b03f45 (patch)
tree6e57d4a5961f88c11c44c3fb9e8bd756deb8a2bc
parent4795e9a3e1b9867c5849c23f44d7e0b38c083f90 (diff)
downloadFreeBSD-src-345b5e7cc0c5ecf57573b08d6267a32c42b03f45.zip
FreeBSD-src-345b5e7cc0c5ecf57573b08d6267a32c42b03f45.tar.gz
Implement a rudimentary interrupt handling system which should be good
enough for clock interrupts in SKI.
-rw-r--r--sys/ia64/ia64/autoconf.c2
-rw-r--r--sys/ia64/ia64/clock.c2
-rw-r--r--sys/ia64/ia64/exception.S39
-rw-r--r--sys/ia64/ia64/exception.s39
-rw-r--r--sys/ia64/ia64/interrupt.c79
-rw-r--r--sys/ia64/ia64/machdep.c2
-rw-r--r--sys/ia64/include/cpu.h3
-rw-r--r--sys/ia64/include/ia64_cpu.h9
8 files changed, 96 insertions, 79 deletions
diff --git a/sys/ia64/ia64/autoconf.c b/sys/ia64/ia64/autoconf.c
index 66230b7..59edff8 100644
--- a/sys/ia64/ia64/autoconf.c
+++ b/sys/ia64/ia64/autoconf.c
@@ -94,7 +94,7 @@ configure(void *dummy)
* Now we're ready to handle (pending) interrupts.
* XXX this is slightly misplaced.
*/
- spl0();
+ enable_intr();
cold = 0;
}
diff --git a/sys/ia64/ia64/clock.c b/sys/ia64/ia64/clock.c
index 01783c4..e2b5fa7 100644
--- a/sys/ia64/ia64/clock.c
+++ b/sys/ia64/ia64/clock.c
@@ -180,7 +180,7 @@ cpu_initclocks()
*/
cycles_per_sec = 700000000;
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();
diff --git a/sys/ia64/ia64/exception.S b/sys/ia64/ia64/exception.S
index ed815ad..8424a7e 100644
--- a/sys/ia64/ia64/exception.S
+++ b/sys/ia64/ia64/exception.S
@@ -52,7 +52,8 @@
add r17=2f-1b,r17;; \
mov b0=r17; \
br.sptk.few exception_save; \
-2: alloc r14=ar.pfs,0,0,2,0; \
+2: (p3) ssm psr.i; \
+ alloc r14=ar.pfs,0,0,2,0; \
movl r15=exception_restore; \
mov out0=_n_; \
mov out1=sp;; \
@@ -511,7 +512,37 @@ ia64_vector_table:
/* 0x3000: External Interrupt vector */
- TRAP(12)
+ 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 */
@@ -993,6 +1024,9 @@ ENTRY(exception_restore, 0)
*
* Return:
* 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
@@ -1005,6 +1039,7 @@ ENTRY(exception_save, 0)
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
diff --git a/sys/ia64/ia64/exception.s b/sys/ia64/ia64/exception.s
index ed815ad..8424a7e 100644
--- a/sys/ia64/ia64/exception.s
+++ b/sys/ia64/ia64/exception.s
@@ -52,7 +52,8 @@
add r17=2f-1b,r17;; \
mov b0=r17; \
br.sptk.few exception_save; \
-2: alloc r14=ar.pfs,0,0,2,0; \
+2: (p3) ssm psr.i; \
+ alloc r14=ar.pfs,0,0,2,0; \
movl r15=exception_restore; \
mov out0=_n_; \
mov out1=sp;; \
@@ -511,7 +512,37 @@ ia64_vector_table:
/* 0x3000: External Interrupt vector */
- TRAP(12)
+ 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 */
@@ -993,6 +1024,9 @@ ENTRY(exception_restore, 0)
*
* Return:
* 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
@@ -1005,6 +1039,7 @@ ENTRY(exception_save, 0)
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
diff --git a/sys/ia64/ia64/interrupt.c b/sys/ia64/ia64/interrupt.c
index ec0ac51..6fce339 100644
--- a/sys/ia64/ia64/interrupt.c
+++ b/sys/ia64/ia64/interrupt.c
@@ -76,41 +76,13 @@ void (*perf_irq)(unsigned long, struct trapframe *) = dummy_perf;
static u_int schedclk2;
void
-interrupt(a0, a1, a2, framep)
- unsigned long a0, a1, a2;
- struct trapframe *framep;
+interrupt(u_int64_t vector, struct trapframe *framep)
{
-#if 0
- /*
- * Find our per-cpu globals.
- */
- globalp = (struct globaldata *) alpha_pal_rdval();
-
atomic_add_int(&PCPU_GET(intr_nesting_level), 1);
- {
- struct proc* p = curproc;
- if (!p) p = &proc0;
- if ((caddr_t) framep < (caddr_t) p->p_addr + 1024) {
- mtx_enter(&Giant, MTX_DEF);
- panic("possible stack overflow\n");
- }
- }
- framep->tf_regs[FRAME_TRAPARG_A0] = a0;
- framep->tf_regs[FRAME_TRAPARG_A1] = a1;
- framep->tf_regs[FRAME_TRAPARG_A2] = a2;
- switch (a0) {
- case ALPHA_INTR_XPROC: /* interprocessor interrupt */
- CTR0(KTR_INTR|KTR_SMP, "interprocessor interrupt");
- smp_handle_ipi(framep); /* note: lock not taken */
- break;
-
- case ALPHA_INTR_CLOCK: /* clock interrupt */
+ switch (vector) {
+ case 240: /* clock interrupt */
CTR0(KTR_INTR, "clock interrupt");
- if (PCPU_GET(cpuno) != hwrpb->rpb_primary_cpu_id) {
- CTR0(KTR_INTR, "ignoring clock on secondary");
- return;
- }
mtx_enter(&Giant, MTX_DEF);
cnt.v_intr++;
@@ -119,53 +91,20 @@ interrupt(a0, a1, a2, framep)
#else
intrcnt[INTRCNT_CLOCK]++;
#endif
- if (platform.clockintr){
- (*platform.clockintr)(framep);
- /* divide hz (1024) by 8 to get stathz (128) */
- if((++schedclk2 & 0x7) == 0)
- statclock((struct clockframe *)framep);
- }
- mtx_exit(&Giant, MTX_DEF);
- break;
-
- case ALPHA_INTR_ERROR: /* Machine Check or Correctable Error */
- mtx_enter(&Giant, MTX_DEF);
- a0 = alpha_pal_rdmces();
- if (platform.mcheck_handler)
- (*platform.mcheck_handler)(a0, framep, a1, a2);
- else
- machine_check(a0, framep, a1, a2);
- mtx_exit(&Giant, MTX_DEF);
- break;
-
- case ALPHA_INTR_DEVICE: /* I/O device interrupt */
- mtx_enter(&Giant, MTX_DEF);
- cnt.v_intr++;
- if (platform.iointr)
- (*platform.iointr)(framep, a1);
- mtx_exit(&Giant, MTX_DEF);
- break;
-
- case ALPHA_INTR_PERF: /* interprocessor interrupt */
- mtx_enter(&Giant, MTX_DEF);
- perf_irq(a1, framep);
+ hardclock((struct clockframe *)framep);
+ setdelayed();
+ /* divide hz (1024) by 8 to get stathz (128) */
+ if((++schedclk2 & 0x7) == 0)
+ statclock((struct clockframe *)framep);
mtx_exit(&Giant, MTX_DEF);
break;
- case ALPHA_INTR_PASSIVE:
-#if 0
- printf("passive release interrupt vec 0x%lx (ignoring)\n", a1);
-#endif
- break;
-
default:
mtx_enter(&Giant, MTX_DEF);
- panic("unexpected interrupt: type 0x%lx vec 0x%lx a2 0x%lx\n",
- a0, a1, a2);
+ panic("unexpected interrupt: vec %ld\n", vector);
/* NOTREACHED */
}
atomic_subtract_int(&PCPU_GET(intr_nesting_level), 1);
-#endif
}
diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c
index 612c3f0..8aef59e 100644
--- a/sys/ia64/ia64/machdep.c
+++ b/sys/ia64/ia64/machdep.c
@@ -1033,7 +1033,7 @@ setregs(struct proc *p, u_long entry, u_long stack, u_long ps_strings)
bzero(frame->tf_f, sizeof(frame->tf_f));
frame->tf_cr_iip = entry;
frame->tf_cr_ipsr = (IA64_PSR_IC
- /* | IA64_PSR_I XXX not yet */
+ | IA64_PSR_I
| IA64_PSR_IT
| IA64_PSR_DT
| IA64_PSR_RT
diff --git a/sys/ia64/include/cpu.h b/sys/ia64/include/cpu.h
index f14c20e..d1f4f86 100644
--- a/sys/ia64/include/cpu.h
+++ b/sys/ia64/include/cpu.h
@@ -151,8 +151,7 @@ void ia64_fpstate_save __P((struct proc *p, int write));
void ia64_fpstate_drop __P((struct proc *p));
void ia64_fpstate_switch __P((struct proc *p));
void init_prom_interface __P((struct rpb*));
-void interrupt
- __P((unsigned long, unsigned long, unsigned long, struct trapframe *));
+void interrupt __P((u_int64_t, struct trapframe *));
void machine_check
__P((unsigned long, struct trapframe *, unsigned long, unsigned long));
u_int64_t hwrpb_checksum __P((void));
diff --git a/sys/ia64/include/ia64_cpu.h b/sys/ia64/include/ia64_cpu.h
index 186e136..2e10844 100644
--- a/sys/ia64/include/ia64_cpu.h
+++ b/sys/ia64/include/ia64_cpu.h
@@ -410,6 +410,15 @@ ia64_set_itm(u_int64_t 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
OpenPOWER on IntegriCloud