summaryrefslogtreecommitdiffstats
path: root/sys/amd64/isa/clock.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2003-11-17 08:58:16 +0000
committerpeter <peter@FreeBSD.org>2003-11-17 08:58:16 +0000
commit9dedda25aa3f6dd18f44e322691c1351377f1927 (patch)
treeaabbe8bf492a150ee82a721cb9396dd2a5b08c50 /sys/amd64/isa/clock.c
parent71a2f6d14698b35350148cb96e1da0939b08ccb2 (diff)
downloadFreeBSD-src-9dedda25aa3f6dd18f44e322691c1351377f1927.zip
FreeBSD-src-9dedda25aa3f6dd18f44e322691c1351377f1927.tar.gz
Initial landing of SMP support for FreeBSD/amd64.
- This is heavily derived from John Baldwin's apic/pci cleanup on i386. - I have completely rewritten or drastically cleaned up some other parts. (in particular, bootstrap) - This is still a WIP. It seems that there are some highly bogus bioses on nVidia nForce3-150 boards. I can't stress how broken these boards are. I have a workaround in mind, but right now the Asus SK8N is broken. The Gigabyte K8NPro (nVidia based) is also mind-numbingly hosed. - Most of my testing has been with SCHED_ULE. SCHED_4BSD works. - the apic and acpi components are 'standard'. - If you have an nVidia nForce3-150 board, you are stuck with 'device atpic' in addition, because they somehow managed to forget to connect the 8254 timer to the apic, even though its in the same silicon! ARGH! This directly violates the ACPI spec.
Diffstat (limited to 'sys/amd64/isa/clock.c')
-rw-r--r--sys/amd64/isa/clock.c52
1 files changed, 22 insertions, 30 deletions
diff --git a/sys/amd64/isa/clock.c b/sys/amd64/isa/clock.c
index a11afb4..a2e751e 100644
--- a/sys/amd64/isa/clock.c
+++ b/sys/amd64/isa/clock.c
@@ -69,8 +69,12 @@ __FBSDID("$FreeBSD$");
#include <machine/clock.h>
#include <machine/frame.h>
+#include <machine/intr_machdep.h>
#include <machine/md_var.h>
#include <machine/psl.h>
+#ifdef SMP
+#include <machine/smp.h>
+#endif
#include <machine/specialreg.h>
#include <amd64/isa/icu.h>
@@ -81,8 +85,6 @@ __FBSDID("$FreeBSD$");
#endif
#include <amd64/isa/timerreg.h>
-#include <amd64/isa/intr_machdep.h>
-
/*
* 32-bit time_t's can't reach leap years before 1904 or after 2036, so we
* can use a simple formula for leap years.
@@ -112,6 +114,7 @@ static u_int hardclock_max_count;
static u_int32_t i8254_lastcount;
static u_int32_t i8254_offset;
static int i8254_ticked;
+static struct intsrc *i8254_intsrc;
static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
static u_char rtc_statusb = RTCSB_24HR | RTCSB_PINTR;
@@ -122,7 +125,6 @@ static u_char rtc_statusb = RTCSB_24HR | RTCSB_PINTR;
#define ACQUIRE_PENDING 3
static u_char timer2_state;
-static void (*timer_func)(struct clockframe *frame) = hardclock;
static unsigned i8254_get_timecount(struct timecounter *tc);
static void set_timer_freq(u_int freq, int intr_freq);
@@ -137,7 +139,7 @@ static struct timecounter i8254_timecounter = {
};
static void
-clkintr(struct clockframe frame)
+clkintr(struct clockframe *frame)
{
if (timecounter->tc_get_timecount == i8254_get_timecount) {
@@ -151,7 +153,10 @@ clkintr(struct clockframe frame)
clkintr_pending = 0;
mtx_unlock_spin(&clock_lock);
}
- timer_func(&frame);
+ hardclock(frame);
+#ifdef SMP
+ forward_hardclock();
+#endif
}
int
@@ -207,16 +212,19 @@ release_timer2()
* in the statistics, but the stat clock will no longer stop.
*/
static void
-rtcintr(struct clockframe frame)
+rtcintr(struct clockframe *frame)
{
while (rtcin(RTC_INTR) & RTCIR_PERIOD) {
if (profprocs != 0) {
if (--pscnt == 0)
pscnt = psdiv;
- profclock(&frame);
+ profclock(frame);
}
if (pscnt == psdiv)
- statclock(&frame);
+ statclock(frame);
+#ifdef SMP
+ forward_statclock();
+#endif
}
}
@@ -719,7 +727,6 @@ void
cpu_initclocks()
{
int diag;
- register_t crit;
if (statclock_disable) {
/*
@@ -735,19 +742,9 @@ cpu_initclocks()
profhz = RTC_PROFRATE;
}
- /* Finish initializing 8253 timer 0. */
- /*
- * XXX Check the priority of this interrupt handler. I
- * couldn't find anything suitable in the BSD/OS code (grog,
- * 19 July 2000).
- */
- inthand_add("clk", 0, (driver_intr_t *)clkintr, NULL,
+ /* Finish initializing 8254 timer 0. */
+ intr_add_handler("clk", 0, (driver_intr_t *)clkintr, NULL,
INTR_TYPE_CLK | INTR_FAST, NULL);
- crit = intr_disable();
- mtx_lock_spin(&icu_lock);
- INTREN(IRQ0);
- mtx_unlock_spin(&icu_lock);
- intr_restore(crit);
/* Initialize RTC. */
writertc(RTC_STATUSA, rtc_statusa);
@@ -760,14 +757,9 @@ cpu_initclocks()
if (diag != 0)
printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS);
- inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL,
+ intr_add_handler("rtc", 8, (driver_intr_t *)rtcintr, NULL,
INTR_TYPE_CLK | INTR_FAST, NULL);
-
- crit = intr_disable();
- mtx_lock_spin(&icu_lock);
- INTREN(IRQ8);
- mtx_unlock_spin(&icu_lock);
- intr_restore(crit);
+ i8254_intsrc = intr_lookup_source(8);
writertc(RTC_STATUSB, rtc_statusb);
@@ -833,8 +825,8 @@ i8254_get_timecount(struct timecounter *tc)
if (count < i8254_lastcount ||
(!i8254_ticked && (clkintr_pending ||
((count < 20 || (!(rflags & PSL_I) && count < timer0_max_count / 2u)) &&
- (inb(IO_ICU1) & 1)))
- )) {
+ i8254_intsrc != NULL &&
+ i8254_intsrc->is_pic->pic_source_pending(i8254_intsrc))))) {
i8254_ticked = 1;
i8254_offset += timer0_max_count;
}
OpenPOWER on IntegriCloud