Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F111632267
D33206.id99268.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D33206.id99268.diff
View Options
Index: sys/x86/include/apicvar.h
===================================================================
--- sys/x86/include/apicvar.h
+++ sys/x86/include/apicvar.h
@@ -229,6 +229,9 @@
void (*disable_vector)(u_int, u_int);
void (*free_vector)(u_int, u_int, u_int);
+ /* Timer */
+ void (*calibrate_timer)(void);
+
/* PMC */
int (*enable_pmc)(void);
void (*disable_pmc)(void);
@@ -376,6 +379,13 @@
apic_ops.free_vector(apic_id, vector, irq);
}
+static inline void
+lapic_calibrate_timer(void)
+{
+
+ apic_ops.calibrate_timer();
+}
+
static inline int
lapic_enable_pmc(void)
{
Index: sys/x86/include/clock.h
===================================================================
--- sys/x86/include/clock.h
+++ sys/x86/include/clock.h
@@ -27,6 +27,7 @@
void i8254_init(void);
void i8254_delay(int);
void clock_init(void);
+void lapic_calibrate(void);
/*
* Driver to clock driver interface.
Index: sys/x86/isa/clock.c
===================================================================
--- sys/x86/isa/clock.c
+++ sys/x86/isa/clock.c
@@ -66,6 +66,7 @@
#include <machine/intr_machdep.h>
#include <machine/ppireg.h>
#include <machine/timerreg.h>
+#include <x86/apicvar.h>
#include <x86/init.h>
#include <isa/rtc.h>
@@ -411,6 +412,8 @@
int i;
td = curthread;
+
+ lapic_calibrate_timer();
cpu_initclocks_bsp();
CPU_FOREACH(i) {
if (i == 0)
@@ -425,6 +428,7 @@
sched_unbind(td);
thread_unlock(td);
#else
+ lapic_calibrate_timer();
cpu_initclocks_bsp();
#endif
}
Index: sys/x86/x86/local_apic.c
===================================================================
--- sys/x86/x86/local_apic.c
+++ sys/x86/x86/local_apic.c
@@ -221,7 +221,7 @@
#endif
static void lapic_calibrate_initcount(struct lapic *la);
-static void lapic_calibrate_deadline(struct lapic *la);
+static void lapic_setup_timer(struct lapic *la);
/*
* Use __nosanitizethread to exempt the LAPIC I/O accessors from KCSan
@@ -354,7 +354,6 @@
struct pic lapic_pic = { .pic_resume = lapic_resume };
-/* Forward declarations for apic_ops */
static void native_lapic_create(u_int apic_id, int boot_cpu);
static void native_lapic_init(vm_paddr_t addr);
static void native_lapic_xapic_mode(void);
@@ -373,6 +372,7 @@
static void native_apic_free_vector(u_int apic_id, u_int vector, u_int irq);
static void native_lapic_set_logical_id(u_int apic_id, u_int cluster,
u_int cluster_id);
+static void native_lapic_calibrate_timer(void);
static int native_lapic_enable_pmc(void);
static void native_lapic_disable_pmc(void);
static void native_lapic_reenable_pmc(void);
@@ -412,6 +412,7 @@
.enable_vector = native_apic_enable_vector,
.disable_vector = native_apic_disable_vector,
.free_vector = native_apic_free_vector,
+ .calibrate_timer = native_lapic_calibrate_timer,
.enable_pmc = native_lapic_enable_pmc,
.disable_pmc = native_lapic_disable_pmc,
.reenable_pmc = native_lapic_reenable_pmc,
@@ -803,40 +804,19 @@
LAPIC_LVT_PCINT));
}
- /* Program timer LVT. */
+ /*
+ * Program the timer LVT. Calibration is deferred until it is certain
+ * that we have a reliable timecounter.
+ */
la->lvt_timer_base = lvt_mode(la, APIC_LVT_TIMER,
lapic_read32(LAPIC_LVT_TIMER));
la->lvt_timer_last = la->lvt_timer_base;
lapic_write32(LAPIC_LVT_TIMER, la->lvt_timer_base);
- /* Calibrate the timer parameters using BSP. */
- if (boot && IS_BSP()) {
- lapic_calibrate_initcount(la);
- if (lapic_timer_tsc_deadline)
- lapic_calibrate_deadline(la);
- }
-
- /* Setup the timer if configured. */
- if (la->la_timer_mode != LAT_MODE_UNDEF) {
- KASSERT(la->la_timer_period != 0, ("lapic%u: zero divisor",
- lapic_id()));
- switch (la->la_timer_mode) {
- case LAT_MODE_PERIODIC:
- lapic_timer_set_divisor(lapic_timer_divisor);
- lapic_timer_periodic(la);
- break;
- case LAT_MODE_ONESHOT:
- lapic_timer_set_divisor(lapic_timer_divisor);
- lapic_timer_oneshot(la);
- break;
- case LAT_MODE_DEADLINE:
- lapic_timer_deadline(la);
- break;
- default:
- panic("corrupted la_timer_mode %p %d", la,
- la->la_timer_mode);
- }
- }
+ if (boot)
+ la->la_timer_mode = LAT_MODE_UNDEF;
+ else
+ lapic_setup_timer(la);
/* Program error LVT and clear any existing errors. */
lapic_write32(LAPIC_LVT_ERROR, lvt_mode(la, APIC_LVT_ERROR,
@@ -908,6 +888,21 @@
}
#endif
+static void
+native_lapic_calibrate_timer(void)
+{
+ struct lapic *la;
+ register_t intr;
+
+ intr = intr_disable();
+ la = &lapics[lapic_id()];
+
+ lapic_calibrate_initcount(la);
+ lapic_setup_timer(la);
+
+ intr_restore(intr);
+}
+
static int
native_lapic_enable_pmc(void)
{
@@ -999,12 +994,27 @@
}
static void
-lapic_calibrate_deadline(struct lapic *la __unused)
+lapic_setup_timer(struct lapic *la)
{
+ if (la->la_timer_mode == LAT_MODE_UNDEF)
+ return;
- if (bootverbose) {
- printf("lapic: deadline tsc mode, Frequency %ju Hz\n",
- (uintmax_t)tsc_freq);
+ KASSERT(la->la_timer_period != 0, ("lapic%u: zero divisor",
+ lapic_id()));
+ switch (la->la_timer_mode) {
+ case LAT_MODE_PERIODIC:
+ lapic_timer_set_divisor(lapic_timer_divisor);
+ lapic_timer_periodic(la);
+ break;
+ case LAT_MODE_ONESHOT:
+ lapic_timer_set_divisor(lapic_timer_divisor);
+ lapic_timer_oneshot(la);
+ break;
+ case LAT_MODE_DEADLINE:
+ lapic_timer_deadline(la);
+ break;
+ default:
+ panic("corrupted la_timer_mode %p %d", la, la->la_timer_mode);
}
}
@@ -1012,13 +1022,7 @@
lapic_change_mode(struct eventtimer *et, struct lapic *la,
enum lat_timer_mode newmode)
{
-
- /*
- * The TSC frequency may change during late calibration against other
- * timecounters (HPET or ACPI PMTimer).
- */
- if (la->la_timer_mode == newmode &&
- (newmode != LAT_MODE_DEADLINE || et->et_frequency == tsc_freq))
+ if (la->la_timer_mode == newmode)
return;
switch (newmode) {
case LAT_MODE_PERIODIC:
Index: sys/x86/xen/xen_apic.c
===================================================================
--- sys/x86/xen/xen_apic.c
+++ sys/x86/xen/xen_apic.c
@@ -223,6 +223,12 @@
XEN_APIC_UNSUPPORTED;
}
+static void
+xen_pv_lapic_calibrate_timer(void)
+{
+
+}
+
static void
xen_pv_lapic_set_logical_id(u_int apic_id, u_int cluster, u_int cluster_id)
{
@@ -420,6 +426,7 @@
.enable_vector = xen_pv_apic_enable_vector,
.disable_vector = xen_pv_apic_disable_vector,
.free_vector = xen_pv_apic_free_vector,
+ .calibrate_timer = xen_pv_lapic_calibrate_timer,
.enable_pmc = xen_pv_lapic_enable_pmc,
.disable_pmc = xen_pv_lapic_disable_pmc,
.reenable_pmc = xen_pv_lapic_reenable_pmc,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Mar 7, 7:00 AM (18 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17027080
Default Alt Text
D33206.id99268.diff (6 KB)
Attached To
Mode
D33206: x86: Defer LAPIC calibration until after timecounters are available
Attached
Detach File
Event Timeline
Log In to Comment