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 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 majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/