The TSC-based Master Timer approximation code will need a couple of
per-CPU offsets and coefficients to approximate the value of a hardware
"Master Timer" based on the value of TSC on whichever CPU it will be
running.
We want to be able to do these approximations in a vsyscall, so we need
all this data in vsyscall-mapped pages.
Signed-off-by: Jiri Bohac <[email protected]>
Index: linux-2.6.20-rc5/arch/x86_64/kernel/vsyscall.c
===================================================================
--- linux-2.6.20-rc5.orig/arch/x86_64/kernel/vsyscall.c
+++ linux-2.6.20-rc5/arch/x86_64/kernel/vsyscall.c
@@ -278,9 +278,11 @@ static void __init map_vsyscall(void)
{
extern char __vsyscall_0;
unsigned long physaddr_page0 = __pa_symbol(&__vsyscall_0);
+ int i;
/* Note that VSYSCALL_MAPPED_PAGES must agree with the code below. */
- __set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_page0, PAGE_KERNEL_VSYSCALL);
+ for (i = 0; i < VSYSCALL_MAPPED_PAGES; ++i)
+ __set_fixmap(VSYSCALL_FIRST_PAGE - i, physaddr_page0 + (i << 12), PAGE_KERNEL_VSYSCALL);
}
static int __init vsyscall_init(void)
Index: linux-2.6.20-rc5/include/asm-x86_64/vsyscall.h
===================================================================
--- linux-2.6.20-rc5.orig/include/asm-x86_64/vsyscall.h
+++ linux-2.6.20-rc5/include/asm-x86_64/vsyscall.h
@@ -10,7 +10,6 @@ enum vsyscall_num {
#define VSYSCALL_START (-10UL << 20)
#define VSYSCALL_SIZE 1024
#define VSYSCALL_END (-2UL << 20)
-#define VSYSCALL_MAPPED_PAGES 1
#define VSYSCALL_ADDR(vsyscall_nr) (VSYSCALL_START+VSYSCALL_SIZE*(vsyscall_nr))
#ifdef __KERNEL__
@@ -24,19 +23,40 @@ enum vsyscall_num {
#define __section_xtime __attribute__ ((unused, __section__ (".xtime"), aligned(16)))
#define __section_xtime_lock __attribute__ ((unused, __section__ (".xtime_lock"), aligned(16)))
-#define VXTIME_TSC 1
+#define VXTIME_TSC 1 /* estimate MT based on rdtsc (fast; UP or synced SMP only) */
+#define VXTIME_TSCS 2 /* estimate MT based on rdtsc in a syscall with locking */
+#define VXTIME_TSCM 3 /* estimate MT based on rdtsc in a syscall, ensure monotonicity */
+#define VXTIME_TSCP 4 /* estimate MT with the help of rdtscp (fast) */
+#define VXTIME_MT 5 /* read the MT, don't estimate (slowest) */
+
+#define VXTIME_TSC_INVALID 0x1
+#define VXTIME_TSC_CPUFREQ 0x2
#define VGETCPU_RDTSCP 1
#define VGETCPU_LSL 2
struct vxtime_data {
+ union {
+ struct {
+ u64 tsc_slope; /* TSC to MT coefficient */
+ u64 tsc_slope_avg; /* average tsc_slope */
+ u64 mt_base; /* approximated MT at the last LAPIC tick */
+ u64 mt_last; /* MT at the last LAPIC tick */
+ u64 tsc_last; /* TSC at the last LAPIC tick */
+ u64 last_mt_guess; /* ensures monotonicity in temporary MT mode */
+ char tsc_invalid; /* don't trust the TSC now (frequency changing) */
+ };
+ char pad[64]; /* cacheline alignment */
+ } cpu[NR_CPUS];
long hpet_address; /* HPET base address */
- int last;
- unsigned long last_tsc;
- long quot;
- long tsc_quot;
+ u64 mt_q; /* master timer to nsec quotient */
+ u64 mt_wall; /* MT ticks already covered by the jiffies */
+ s64 ns_drift; /* MT - xtime drift in the last tick in ns */
int mode;
};
+#define VSYSCALL_MAPPED_PAGES (1 + (sizeof(struct vxtime_data) + 4095) / 4096)
+
+#define TSC_SLOPE_SCALE 32
#define hpet_readl(a) readl((const void __iomem *)fix_to_virt(FIX_HPET_BASE) + a)
#define hpet_writel(d,a) writel(d, (void __iomem *)fix_to_virt(FIX_HPET_BASE) + a)
Index: linux-2.6.20-rc5/arch/x86_64/kernel/vmlinux.lds.S
===================================================================
--- linux-2.6.20-rc5.orig/arch/x86_64/kernel/vmlinux.lds.S
+++ linux-2.6.20-rc5/arch/x86_64/kernel/vmlinux.lds.S
@@ -87,13 +87,13 @@ SECTIONS
.vsyscall_0 : AT(VSYSCALL_PHYS_ADDR) { *(.vsyscall_0) } :user
__vsyscall_0 = VSYSCALL_VIRT_ADDR;
+ .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1)) { *(.vsyscall_1) }
+ .vsyscall_2 ADDR(.vsyscall_0) + 2048: AT(VLOAD(.vsyscall_2)) { *(.vsyscall_2) }
+ .vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3)) { *(.vsyscall_3) }
. = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
.xtime_lock : AT(VLOAD(.xtime_lock)) { *(.xtime_lock) }
xtime_lock = VVIRT(.xtime_lock);
- .vxtime : AT(VLOAD(.vxtime)) { *(.vxtime) }
- vxtime = VVIRT(.vxtime);
-
.vgetcpu_mode : AT(VLOAD(.vgetcpu_mode)) { *(.vgetcpu_mode) }
vgetcpu_mode = VVIRT(.vgetcpu_mode);
@@ -110,11 +110,15 @@ SECTIONS
.jiffies : AT(VLOAD(.jiffies)) { *(.jiffies) }
jiffies = VVIRT(.jiffies);
- .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1)) { *(.vsyscall_1) }
- .vsyscall_2 ADDR(.vsyscall_0) + 2048: AT(VLOAD(.vsyscall_2)) { *(.vsyscall_2) }
- .vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3)) { *(.vsyscall_3) }
+ . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
+
+ . = ALIGN(4096);
+
+ .vxtime : AT(VLOAD(.vxtime)) { *(.vxtime) }
+ vxtime = VVIRT(.vxtime);
+
+ . = (VSYSCALL_VIRT_ADDR + 4096 + (CONFIG_NR_CPUS * 64 + 40 + 4095)) & ~(4095);
- . = VSYSCALL_VIRT_ADDR + 4096;
#undef VSYSCALL_ADDR
#undef VSYSCALL_PHYS_ADDR
--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]