diff options
author | Marcelo Tosatti <mtosatti@redhat.com> | 2012-11-27 20:28:55 -0500 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2012-11-27 20:29:09 -0500 |
commit | 71056ae22d43f58d7e0f793af18ace2eaf5b74eb (patch) | |
tree | 02433f7fac25fbbb18405a0fe7a2b5f9925d3610 | |
parent | 582b336ec2c0f0076f5650a029fcc9abd4a906f7 (diff) |
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>
-rw-r--r-- | arch/x86/include/asm/clocksource.h | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/fixmap.h | 5 | ||||
-rw-r--r-- | arch/x86/include/asm/pvclock.h | 12 | ||||
-rw-r--r-- | arch/x86/kernel/pvclock.c | 73 |
4 files changed, 91 insertions, 0 deletions
diff --git a/arch/x86/include/asm/clocksource.h b/arch/x86/include/asm/clocksource.h index 0bdbbb3b9ce7..16a57f4ed64d 100644 --- a/arch/x86/include/asm/clocksource.h +++ b/arch/x86/include/asm/clocksource.h | |||
@@ -8,6 +8,7 @@ | |||
8 | #define VCLOCK_NONE 0 /* No vDSO clock available. */ | 8 | #define VCLOCK_NONE 0 /* No vDSO clock available. */ |
9 | #define VCLOCK_TSC 1 /* vDSO should use vread_tsc. */ | 9 | #define VCLOCK_TSC 1 /* vDSO should use vread_tsc. */ |
10 | #define VCLOCK_HPET 2 /* vDSO should use vread_hpet. */ | 10 | #define VCLOCK_HPET 2 /* vDSO should use vread_hpet. */ |
11 | #define VCLOCK_PVCLOCK 3 /* vDSO should use vread_pvclock. */ | ||
11 | 12 | ||
12 | struct arch_clocksource_data { | 13 | struct arch_clocksource_data { |
13 | int vclock_mode; | 14 | int vclock_mode; |
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h index 4da3c0c4c974..a09c28571064 100644 --- a/arch/x86/include/asm/fixmap.h +++ b/arch/x86/include/asm/fixmap.h | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <asm/acpi.h> | 19 | #include <asm/acpi.h> |
20 | #include <asm/apicdef.h> | 20 | #include <asm/apicdef.h> |
21 | #include <asm/page.h> | 21 | #include <asm/page.h> |
22 | #include <asm/pvclock.h> | ||
22 | #ifdef CONFIG_X86_32 | 23 | #ifdef CONFIG_X86_32 |
23 | #include <linux/threads.h> | 24 | #include <linux/threads.h> |
24 | #include <asm/kmap_types.h> | 25 | #include <asm/kmap_types.h> |
@@ -81,6 +82,10 @@ enum fixed_addresses { | |||
81 | VVAR_PAGE, | 82 | VVAR_PAGE, |
82 | VSYSCALL_HPET, | 83 | VSYSCALL_HPET, |
83 | #endif | 84 | #endif |
85 | #ifdef CONFIG_PARAVIRT_CLOCK | ||
86 | PVCLOCK_FIXMAP_BEGIN, | ||
87 | PVCLOCK_FIXMAP_END = PVCLOCK_FIXMAP_BEGIN+PVCLOCK_VSYSCALL_NR_PAGES-1, | ||
88 | #endif | ||
84 | FIX_DBGP_BASE, | 89 | FIX_DBGP_BASE, |
85 | FIX_EARLYCON_MEM_BASE, | 90 | FIX_EARLYCON_MEM_BASE, |
86 | #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT | 91 | #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT |
diff --git a/arch/x86/include/asm/pvclock.h b/arch/x86/include/asm/pvclock.h index 63f91679af73..109a9dd5d454 100644 --- a/arch/x86/include/asm/pvclock.h +++ b/arch/x86/include/asm/pvclock.h | |||
@@ -91,4 +91,16 @@ unsigned __pvclock_read_cycles(const struct pvclock_vcpu_time_info *src, | |||
91 | return version; | 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 | #endif /* _ASM_X86_PVCLOCK_H */ | 106 | #endif /* _ASM_X86_PVCLOCK_H */ |
diff --git a/arch/x86/kernel/pvclock.c b/arch/x86/kernel/pvclock.c index c8fb043a8695..85c39590c1a4 100644 --- a/arch/x86/kernel/pvclock.c +++ b/arch/x86/kernel/pvclock.c | |||
@@ -17,6 +17,11 @@ | |||
17 | 17 | ||
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/percpu.h> | 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 | #include <asm/pvclock.h> | 25 | #include <asm/pvclock.h> |
21 | 26 | ||
22 | static u8 valid_flags __read_mostly = 0; | 27 | static u8 valid_flags __read_mostly = 0; |
@@ -122,3 +127,71 @@ void pvclock_read_wallclock(struct pvclock_wall_clock *wall_clock, | |||
122 | 127 | ||
123 | set_normalized_timespec(ts, now.tv_sec, now.tv_nsec); | 128 | set_normalized_timespec(ts, now.tv_sec, now.tv_nsec); |
124 | } | 129 | } |
130 | |||
131 | static struct pvclock_vsyscall_time_info *pvclock_vdso_info; | ||
132 | |||
133 | static struct pvclock_vsyscall_time_info * | ||
134 | pvclock_get_vsyscall_user_time_info(int cpu) | ||
135 | { | ||
136 | if (!pvclock_vdso_info) { | ||
137 | BUG(); | ||
138 | return NULL; | ||
139 | } | ||
140 | |||
141 | return &pvclock_vdso_info[cpu]; | ||
142 | } | ||
143 | |||
144 | struct pvclock_vcpu_time_info *pvclock_get_vsyscall_time_info(int cpu) | ||
145 | { | ||
146 | return &pvclock_get_vsyscall_user_time_info(cpu)->pvti; | ||
147 | } | ||
148 | |||
149 | #ifdef CONFIG_X86_64 | ||
150 | static int pvclock_task_migrate(struct notifier_block *nb, unsigned long l, | ||
151 | void *v) | ||
152 | { | ||
153 | struct task_migration_notifier *mn = v; | ||
154 | struct pvclock_vsyscall_time_info *pvti; | ||
155 | |||
156 | pvti = pvclock_get_vsyscall_user_time_info(mn->from_cpu); | ||
157 | |||
158 | /* this is NULL when pvclock vsyscall is not initialized */ | ||
159 | if (unlikely(pvti == NULL)) | ||
160 | return NOTIFY_DONE; | ||
161 | |||
162 | pvti->migrate_count++; | ||
163 | |||
164 | return NOTIFY_DONE; | ||
165 | } | ||
166 | |||
167 | static struct notifier_block pvclock_migrate = { | ||
168 | .notifier_call = pvclock_task_migrate, | ||
169 | }; | ||
170 | |||
171 | /* | ||
172 | * Initialize the generic pvclock vsyscall state. This will allocate | ||
173 | * a/some page(s) for the per-vcpu pvclock information, set up a | ||
174 | * fixmap mapping for the page(s) | ||
175 | */ | ||
176 | |||
177 | int __init pvclock_init_vsyscall(struct pvclock_vsyscall_time_info *i, | ||
178 | int size) | ||
179 | { | ||
180 | int idx; | ||
181 | |||
182 | WARN_ON (size != PVCLOCK_VSYSCALL_NR_PAGES*PAGE_SIZE); | ||
183 | |||
184 | pvclock_vdso_info = i; | ||
185 | |||
186 | for (idx = 0; idx <= (PVCLOCK_FIXMAP_END-PVCLOCK_FIXMAP_BEGIN); idx++) { | ||
187 | __set_fixmap(PVCLOCK_FIXMAP_BEGIN + idx, | ||
188 | __pa_symbol(i) + (idx*PAGE_SIZE), | ||
189 | PAGE_KERNEL_VVAR); | ||
190 | } | ||
191 | |||
192 | |||
193 | register_task_migration_notifier(&pvclock_migrate); | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | #endif | ||