Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86: pvclock: generic pvclock vsyscall initialization

Originally from Jeremy Fitzhardinge.

Introduce generic, non hypervisor specific, pvclock initialization
routines.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>

+91
+1
arch/x86/include/asm/clocksource.h
··· 8 8 #define VCLOCK_NONE 0 /* No vDSO clock available. */ 9 9 #define VCLOCK_TSC 1 /* vDSO should use vread_tsc. */ 10 10 #define VCLOCK_HPET 2 /* vDSO should use vread_hpet. */ 11 + #define VCLOCK_PVCLOCK 3 /* vDSO should use vread_pvclock. */ 11 12 12 13 struct arch_clocksource_data { 13 14 int vclock_mode;
+5
arch/x86/include/asm/fixmap.h
··· 19 19 #include <asm/acpi.h> 20 20 #include <asm/apicdef.h> 21 21 #include <asm/page.h> 22 + #include <asm/pvclock.h> 22 23 #ifdef CONFIG_X86_32 23 24 #include <linux/threads.h> 24 25 #include <asm/kmap_types.h> ··· 81 80 + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1, 82 81 VVAR_PAGE, 83 82 VSYSCALL_HPET, 83 + #endif 84 + #ifdef CONFIG_PARAVIRT_CLOCK 85 + PVCLOCK_FIXMAP_BEGIN, 86 + PVCLOCK_FIXMAP_END = PVCLOCK_FIXMAP_BEGIN+PVCLOCK_VSYSCALL_NR_PAGES-1, 84 87 #endif 85 88 FIX_DBGP_BASE, 86 89 FIX_EARLYCON_MEM_BASE,
+12
arch/x86/include/asm/pvclock.h
··· 91 91 return version; 92 92 } 93 93 94 + struct pvclock_vsyscall_time_info { 95 + struct pvclock_vcpu_time_info pvti; 96 + u32 migrate_count; 97 + } __attribute__((__aligned__(SMP_CACHE_BYTES))); 98 + 99 + #define PVTI_SIZE sizeof(struct pvclock_vsyscall_time_info) 100 + #define PVCLOCK_VSYSCALL_NR_PAGES (((NR_CPUS-1)/(PAGE_SIZE/PVTI_SIZE))+1) 101 + 102 + int __init pvclock_init_vsyscall(struct pvclock_vsyscall_time_info *i, 103 + int size); 104 + struct pvclock_vcpu_time_info *pvclock_get_vsyscall_time_info(int cpu); 105 + 94 106 #endif /* _ASM_X86_PVCLOCK_H */
+73
arch/x86/kernel/pvclock.c
··· 17 17 18 18 #include <linux/kernel.h> 19 19 #include <linux/percpu.h> 20 + #include <linux/notifier.h> 21 + #include <linux/sched.h> 22 + #include <linux/gfp.h> 23 + #include <linux/bootmem.h> 24 + #include <asm/fixmap.h> 20 25 #include <asm/pvclock.h> 21 26 22 27 static u8 valid_flags __read_mostly = 0; ··· 127 122 128 123 set_normalized_timespec(ts, now.tv_sec, now.tv_nsec); 129 124 } 125 + 126 + static struct pvclock_vsyscall_time_info *pvclock_vdso_info; 127 + 128 + static struct pvclock_vsyscall_time_info * 129 + pvclock_get_vsyscall_user_time_info(int cpu) 130 + { 131 + if (!pvclock_vdso_info) { 132 + BUG(); 133 + return NULL; 134 + } 135 + 136 + return &pvclock_vdso_info[cpu]; 137 + } 138 + 139 + struct pvclock_vcpu_time_info *pvclock_get_vsyscall_time_info(int cpu) 140 + { 141 + return &pvclock_get_vsyscall_user_time_info(cpu)->pvti; 142 + } 143 + 144 + #ifdef CONFIG_X86_64 145 + static int pvclock_task_migrate(struct notifier_block *nb, unsigned long l, 146 + void *v) 147 + { 148 + struct task_migration_notifier *mn = v; 149 + struct pvclock_vsyscall_time_info *pvti; 150 + 151 + pvti = pvclock_get_vsyscall_user_time_info(mn->from_cpu); 152 + 153 + /* this is NULL when pvclock vsyscall is not initialized */ 154 + if (unlikely(pvti == NULL)) 155 + return NOTIFY_DONE; 156 + 157 + pvti->migrate_count++; 158 + 159 + return NOTIFY_DONE; 160 + } 161 + 162 + static struct notifier_block pvclock_migrate = { 163 + .notifier_call = pvclock_task_migrate, 164 + }; 165 + 166 + /* 167 + * Initialize the generic pvclock vsyscall state. This will allocate 168 + * a/some page(s) for the per-vcpu pvclock information, set up a 169 + * fixmap mapping for the page(s) 170 + */ 171 + 172 + int __init pvclock_init_vsyscall(struct pvclock_vsyscall_time_info *i, 173 + int size) 174 + { 175 + int idx; 176 + 177 + WARN_ON (size != PVCLOCK_VSYSCALL_NR_PAGES*PAGE_SIZE); 178 + 179 + pvclock_vdso_info = i; 180 + 181 + for (idx = 0; idx <= (PVCLOCK_FIXMAP_END-PVCLOCK_FIXMAP_BEGIN); idx++) { 182 + __set_fixmap(PVCLOCK_FIXMAP_BEGIN + idx, 183 + __pa_symbol(i) + (idx*PAGE_SIZE), 184 + PAGE_KERNEL_VVAR); 185 + } 186 + 187 + 188 + register_task_migration_notifier(&pvclock_migrate); 189 + 190 + return 0; 191 + } 192 + #endif