summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Pau Monné <royger@FreeBSD.org>2014-03-11 10:20:42 +0000
committerRoger Pau Monné <royger@FreeBSD.org>2014-03-11 10:20:42 +0000
commit5f05c79450788b33bd82738ee27bf6d0ceeb12ca (patch)
treea6c082deb8c080bacb519b882baaa752822f1a89
parent09982c99b2ec5df06bf084d9c0ce113c192a330b (diff)
Notes
-rw-r--r--sys/amd64/amd64/machdep.c6
-rw-r--r--sys/amd64/include/clock.h2
-rw-r--r--sys/conf/files.amd641
-rw-r--r--sys/conf/files.i3861
-rw-r--r--sys/conf/files.pc982
-rw-r--r--sys/dev/xen/timer/timer.c34
-rw-r--r--sys/dev/xen/timer/timer.h35
-rw-r--r--sys/i386/i386/machdep.c11
-rw-r--r--sys/i386/include/clock.h2
-rw-r--r--sys/i386/xen/clock.c2
-rw-r--r--sys/pc98/pc98/machdep.c9
-rw-r--r--sys/x86/include/init.h2
-rw-r--r--sys/x86/isa/clock.c64
-rw-r--r--sys/x86/x86/delay.c106
-rw-r--r--sys/x86/xen/pv.c4
15 files changed, 222 insertions, 59 deletions
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index dc4b09c9c2e7..d52020ccb6bd 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -172,6 +172,8 @@ static caddr_t native_parse_preload_data(u_int64_t);
/* Default init_ops implementation. */
struct init_ops init_ops = {
.parse_preload_data = native_parse_preload_data,
+ .early_clock_source_init = i8254_init,
+ .early_delay = i8254_delay,
};
/*
@@ -1822,10 +1824,10 @@ hammer_time(u_int64_t modulep, u_int64_t physfree)
lidt(&r_idt);
/*
- * Initialize the i8254 before the console so that console
+ * Initialize the clock before the console so that console
* initialization can use DELAY().
*/
- i8254_init();
+ clock_init();
/*
* Initialize the console before we print anything out.
diff --git a/sys/amd64/include/clock.h b/sys/amd64/include/clock.h
index d7f7d828b6c5..65bf8bd93bb4 100644
--- a/sys/amd64/include/clock.h
+++ b/sys/amd64/include/clock.h
@@ -25,6 +25,8 @@ extern int smp_tsc;
#endif
void i8254_init(void);
+void i8254_delay(int);
+void clock_init(void);
/*
* Driver to clock driver interface.
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index a6eb12acad6f..45c092730019 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -554,6 +554,7 @@ x86/x86/mptable_pci.c optional mptable pci
x86/x86/msi.c optional pci
x86/x86/nexus.c standard
x86/x86/tsc.c standard
+x86/x86/delay.c standard
x86/xen/hvm.c optional xenhvm
x86/xen/xen_intr.c optional xen | xenhvm
x86/xen/pv.c optional xenhvm
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index 5408908c6e84..8d724ca95927 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -593,5 +593,6 @@ x86/x86/mptable_pci.c optional apic native pci
x86/x86/msi.c optional apic pci
x86/x86/nexus.c standard
x86/x86/tsc.c standard
+x86/x86/delay.c standard
x86/xen/hvm.c optional xenhvm
x86/xen/xen_intr.c optional xen | xenhvm
diff --git a/sys/conf/files.pc98 b/sys/conf/files.pc98
index 0c315e4ddac1..92696ee9c08b 100644
--- a/sys/conf/files.pc98
+++ b/sys/conf/files.pc98
@@ -259,3 +259,5 @@ x86/x86/mptable_pci.c optional apic pci
x86/x86/msi.c optional apic pci
x86/x86/nexus.c standard
x86/x86/tsc.c standard
+x86/x86/tsc.c standard
+x86/x86/delay.c standard
diff --git a/sys/dev/xen/timer/timer.c b/sys/dev/xen/timer/timer.c
index 6c0a140ec762..ed611d03e3a3 100644
--- a/sys/dev/xen/timer/timer.c
+++ b/sys/dev/xen/timer/timer.c
@@ -60,6 +60,8 @@ __FBSDID("$FreeBSD$");
#include <machine/_inttypes.h>
#include <machine/smp.h>
+#include <dev/xen/timer/timer.h>
+
#include "clock_if.h"
static devclass_t xentimer_devclass;
@@ -592,6 +594,38 @@ xentimer_suspend(device_t dev)
return (0);
}
+/*
+ * Xen early clock init
+ */
+void
+xen_clock_init(void)
+{
+}
+
+/*
+ * Xen PV DELAY function
+ *
+ * When running on PVH mode we don't have an emulated i8524, so
+ * make use of the Xen time info in order to code a simple DELAY
+ * function that can be used during early boot.
+ */
+void
+xen_delay(int n)
+{
+ struct vcpu_info *vcpu = &HYPERVISOR_shared_info->vcpu_info[0];
+ uint64_t end_ns;
+ uint64_t current;
+
+ end_ns = xen_fetch_vcpu_time(vcpu);
+ end_ns += n * NSEC_IN_USEC;
+
+ for (;;) {
+ current = xen_fetch_vcpu_time(vcpu);
+ if (current >= end_ns)
+ break;
+ }
+}
+
static device_method_t xentimer_methods[] = {
DEVMETHOD(device_identify, xentimer_identify),
DEVMETHOD(device_probe, xentimer_probe),
diff --git a/sys/dev/xen/timer/timer.h b/sys/dev/xen/timer/timer.h
new file mode 100644
index 000000000000..38518cb394c6
--- /dev/null
+++ b/sys/dev/xen/timer/timer.h
@@ -0,0 +1,35 @@
+/*-
+ * Copyright (c) 2013 Roger Pau Monné <roger.pau@citrix.com>
+ * 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 _XEN_TIMER_H_
+#define _XEN_TIMER_H_
+
+void xen_clock_init(void);
+void xen_delay(int);
+
+#endif /* _XEN_TIMER_H_ */
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index 929a22518eb8..a4a680445ede 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -132,6 +132,7 @@ __FBSDID("$FreeBSD$");
#include <machine/sigframe.h>
#include <machine/specialreg.h>
#include <machine/vm86.h>
+#include <x86/init.h>
#ifdef PERFMON
#include <machine/perfmon.h>
#endif
@@ -253,6 +254,12 @@ struct mtx icu_lock;
struct mem_range_softc mem_range_softc;
+ /* Default init_ops implementation. */
+ struct init_ops init_ops = {
+ .early_clock_source_init = i8254_init,
+ .early_delay = i8254_delay,
+ };
+
static void
cpu_startup(dummy)
void *dummy;
@@ -2977,10 +2984,10 @@ init386(first)
#endif /* XBOX */
/*
- * Initialize the i8254 before the console so that console
+ * Initialize the clock before the console so that console
* initialization can use DELAY().
*/
- i8254_init();
+ clock_init();
/*
* Initialize the console before we print anything out.
diff --git a/sys/i386/include/clock.h b/sys/i386/include/clock.h
index d980ec7bd6d9..564d231dde0c 100644
--- a/sys/i386/include/clock.h
+++ b/sys/i386/include/clock.h
@@ -22,6 +22,8 @@ extern int tsc_is_invariant;
extern int tsc_perf_stat;
void i8254_init(void);
+void i8254_delay(int);
+void clock_init(void);
/*
* Driver to clock driver interface.
diff --git a/sys/i386/xen/clock.c b/sys/i386/xen/clock.c
index 075f5675cad1..5d03d2648028 100644
--- a/sys/i386/xen/clock.c
+++ b/sys/i386/xen/clock.c
@@ -192,7 +192,7 @@ i8254_init(void)
* Note: timer had better have been programmed before this is first used!
*/
void
-DELAY(int n)
+i8254_delay(int n)
{
int delta, ticks_left;
uint32_t tick, prev_tick;
diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c
index b6cdcdcb8f7b..ab978deca8d1 100644
--- a/sys/pc98/pc98/machdep.c
+++ b/sys/pc98/pc98/machdep.c
@@ -129,6 +129,7 @@ __FBSDID("$FreeBSD$");
#include <machine/sigframe.h>
#include <machine/specialreg.h>
#include <machine/vm86.h>
+#include <x86/init.h>
#ifdef PERFMON
#include <machine/perfmon.h>
#endif
@@ -220,6 +221,12 @@ struct mtx icu_lock;
struct mem_range_softc mem_range_softc;
+ /* Default init_ops implementation. */
+ struct init_ops init_ops = {
+ .early_clock_source_init = i8254_init,
+ .early_delay = i8254_delay,
+ };
+
static void
cpu_startup(dummy)
void *dummy;
@@ -2267,7 +2274,7 @@ init386(first)
* Initialize the i8254 before the console so that console
* initialization can use DELAY().
*/
- i8254_init();
+ clock_init();
/*
* Initialize the console before we print anything out.
diff --git a/sys/x86/include/init.h b/sys/x86/include/init.h
index 7e032df214fe..c72889f0209b 100644
--- a/sys/x86/include/init.h
+++ b/sys/x86/include/init.h
@@ -36,6 +36,8 @@
*/
struct init_ops {
caddr_t (*parse_preload_data)(u_int64_t);
+ void (*early_clock_source_init)(void);
+ void (*early_delay)(int);
};
extern struct init_ops init_ops;
diff --git a/sys/x86/isa/clock.c b/sys/x86/isa/clock.c
index a12e17514a91..8ed68e0f97d6 100644
--- a/sys/x86/isa/clock.c
+++ b/sys/x86/isa/clock.c
@@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
#include <machine/intr_machdep.h>
#include <machine/ppireg.h>
#include <machine/timerreg.h>
+#include <x86/init.h>
#ifdef PC98
#include <pc98/pc98/pc98_machdep.h>
@@ -139,6 +140,15 @@ static u_char timer2_state;
static unsigned i8254_get_timecount(struct timecounter *tc);
static void set_i8254_freq(int mode, uint32_t period);
+void
+clock_init(void)
+{
+ /* Init the clock lock */
+ mtx_init(&clock_lock, "clk", NULL, MTX_SPIN | MTX_NOPROFILE);
+ /* Init the clock in order to use DELAY */
+ init_ops.early_clock_source_init();
+}
+
static int
clkintr(void *arg)
{
@@ -247,61 +257,13 @@ getit(void)
return ((high << 8) | low);
}
-#ifndef DELAYDEBUG
-static u_int
-get_tsc(__unused struct timecounter *tc)
-{
-
- return (rdtsc32());
-}
-
-static __inline int
-delay_tc(int n)
-{
- struct timecounter *tc;
- timecounter_get_t *func;
- uint64_t end, freq, now;
- u_int last, mask, u;
-
- tc = timecounter;
- freq = atomic_load_acq_64(&tsc_freq);
- if (tsc_is_invariant && freq != 0) {
- func = get_tsc;
- mask = ~0u;
- } else {
- if (tc->tc_quality <= 0)
- return (0);
- func = tc->tc_get_timecount;
- mask = tc->tc_counter_mask;
- freq = tc->tc_frequency;
- }
- now = 0;
- end = freq * n / 1000000;
- if (func == get_tsc)
- sched_pin();
- last = func(tc) & mask;
- do {
- cpu_spinwait();
- u = func(tc) & mask;
- if (u < last)
- now += mask - last + u + 1;
- else
- now += u - last;
- last = u;
- } while (now < end);
- if (func == get_tsc)
- sched_unpin();
- return (1);
-}
-#endif
-
/*
* Wait "n" microseconds.
* Relies on timer 1 counting down from (i8254_freq / hz)
* Note: timer had better have been programmed before this is first used!
*/
void
-DELAY(int n)
+i8254_delay(int n)
{
int delta, prev_tick, tick, ticks_left;
#ifdef DELAYDEBUG
@@ -317,9 +279,6 @@ DELAY(int n)
}
if (state == 1)
printf("DELAY(%d)...", n);
-#else
- if (delay_tc(n))
- return;
#endif
/*
* Read the counter first, so that the rest of the setup overhead is
@@ -499,7 +458,6 @@ void
i8254_init(void)
{
- mtx_init(&clock_lock, "clk", NULL, MTX_SPIN | MTX_NOPROFILE);
#ifdef PC98
if (pc98_machine_type & M_8M)
i8254_freq = 1996800L; /* 1.9968 MHz */
diff --git a/sys/x86/x86/delay.c b/sys/x86/x86/delay.c
new file mode 100644
index 000000000000..8cbe6012a96b
--- /dev/null
+++ b/sys/x86/x86/delay.c
@@ -0,0 +1,106 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 2010 Alexander Motin <mav@FreeBSD.org>
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz and Don Ahn.
+ *
+ * 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)clock.c 7.2 (Berkeley) 5/12/91
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/* Generic x86 routines to handle delay */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/timetc.h>
+#include <sys/proc.h>
+#include <sys/kernel.h>
+#include <sys/sched.h>
+
+#include <machine/clock.h>
+#include <machine/cpu.h>
+#include <x86/init.h>
+
+static u_int
+get_tsc(__unused struct timecounter *tc)
+{
+
+ return (rdtsc32());
+}
+
+static int
+delay_tc(int n)
+{
+ struct timecounter *tc;
+ timecounter_get_t *func;
+ uint64_t end, freq, now;
+ u_int last, mask, u;
+
+ tc = timecounter;
+ freq = atomic_load_acq_64(&tsc_freq);
+ if (tsc_is_invariant && freq != 0) {
+ func = get_tsc;
+ mask = ~0u;
+ } else {
+ if (tc->tc_quality <= 0)
+ return (0);
+ func = tc->tc_get_timecount;
+ mask = tc->tc_counter_mask;
+ freq = tc->tc_frequency;
+ }
+ now = 0;
+ end = freq * n / 1000000;
+ if (func == get_tsc)
+ sched_pin();
+ last = func(tc) & mask;
+ do {
+ cpu_spinwait();
+ u = func(tc) & mask;
+ if (u < last)
+ now += mask - last + u + 1;
+ else
+ now += u - last;
+ last = u;
+ } while (now < end);
+ if (func == get_tsc)
+ sched_unpin();
+ return (1);
+}
+
+void
+DELAY(int n)
+{
+
+ if (delay_tc(n))
+ return;
+
+ init_ops.early_delay(n);
+}
diff --git a/sys/x86/xen/pv.c b/sys/x86/xen/pv.c
index 63dc39b92709..4bc7e86b23c0 100644
--- a/sys/x86/xen/pv.c
+++ b/sys/x86/xen/pv.c
@@ -53,6 +53,8 @@ __FBSDID("$FreeBSD$");
#include <xen/xen-os.h>
#include <xen/hypervisor.h>
+#include <dev/xen/timer/timer.h>
+
/* Native initial function */
extern u_int64_t hammer_time(u_int64_t, u_int64_t);
/* Xen initial function */
@@ -65,6 +67,8 @@ static caddr_t xen_pv_parse_preload_data(u_int64_t);
/* Xen init_ops implementation. */
struct init_ops xen_init_ops = {
.parse_preload_data = xen_pv_parse_preload_data,
+ .early_clock_source_init = xen_clock_init,
+ .early_delay = xen_delay,
};
/*-------------------------------- Xen PV init -------------------------------*/