Hello, This series of patches integrates msr.h header. What it really does, is a series of steps to allow us to get rid of duplicate code between i386 and x86_64 versions With this done, achieving paravirt for x86_64 gets really easy, just a couple of extra code. The first patch was already sent a while ago, but was not yet pushed to any tree , to my knowledge. So it is sent again. Also, patches 9 and 10 relies on b02f15537b3bf43e347214cf14bad80aeaef1caf, already in the x86 tree. Other than that, it should apply fine ontop of linus today git. Comments are welcome
The functions under #ifdef CONFIG_SMP in msr.h are the same for both x86_64 and i386, and this patches removes one of them, putting them in a single location Signed-off-by: Glauber de Oliveira Costa <gcosta@redhat.com> --- include/asm-x86/msr.h | 33 +++++++-------------------------- 1 files changed, 7 insertions(+), 26 deletions(-) diff --git a/include/asm-x86/msr.h b/include/asm-x86/msr.h index ba4b314..b3cd509 100644 --- a/include/asm-x86/msr.h +++ b/include/asm-x86/msr.h @@ -135,29 +135,6 @@ static inline int wrmsr_safe(u32 __msr, u32 __low, u32 __high) } while(0) #endif /* !CONFIG_PARAVIRT */ -#ifdef CONFIG_SMP -void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); -void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); -int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); -int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); -#else /* CONFIG_SMP */ -static inline void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) -{ - rdmsr(msr_no, *l, *h); -} -static inline void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) -{ - wrmsr(msr_no, l, h); -} -static inline int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) -{ - return rdmsr_safe(msr_no, l, h); -} -static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) -{ - return wrmsr_safe(msr_no, l, h); -} -#endif /* CONFIG_SMP */ #endif /* ! __ASSEMBLY__ */ #endif /* __KERNEL__ */ @@ -320,6 +297,12 @@ static inline unsigned int cpuid_edx(unsigned int op) return edx; } +#endif /* __ASSEMBLY__ */ + +#endif /* !__i386__ */ + +#ifndef __ASSEMBLY__ + #ifdef CONFIG_SMP void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); @@ -343,8 +326,6 @@ static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) return wrmsr_safe(msr_no, l, h); } #endif /* CONFIG_SMP */ -#endif /* __ASSEMBLY__ */ - -#endif /* !__i386__ */ +#endif /* __ASSEMBLY__ */ #endif -- 1.4.4.2
Glauber de Oliveira Costa
2007-Dec-04 05:54 UTC
[PATCH 3/10] allow sched clock to be overridden by paravirt
This patch turns the sched_clock into native_sched_clock. sched clock becomes a weak symbol, which can then give its place to a paravirt definition. Signed-off-by: Glauber de Oliveira Costa <gcosta@redhat.com> --- arch/x86/kernel/tsc_64.c | 15 ++++++++++++++- 1 files changed, 14 insertions(+), 1 deletions(-) diff --git a/arch/x86/kernel/tsc_64.c b/arch/x86/kernel/tsc_64.c index 9c70af4..5158476 100644 --- a/arch/x86/kernel/tsc_64.c +++ b/arch/x86/kernel/tsc_64.c @@ -30,7 +30,7 @@ static unsigned long long cycles_2_ns(unsigned long long cyc) return (cyc * cyc2ns_scale) >> NS_SCALE; } -unsigned long long sched_clock(void) +unsigned long long native_sched_clock(void) { unsigned long a = 0; @@ -44,6 +44,19 @@ unsigned long long sched_clock(void) return cycles_2_ns(a); } +/* We need to define a real function for sched_clock, to override the + weak default version */ +#ifdef CONFIG_PARAVIRT +unsigned long long sched_clock(void) +{ + return paravirt_sched_clock(); +} +#else +unsigned long long +sched_clock(void) __attribute__((alias("native_sched_clock"))); +#endif + + static int tsc_unstable; inline int check_tsc_unstable(void) -- 1.4.4.2
Glauber de Oliveira Costa
2007-Dec-04 05:54 UTC
[PATCH 1/10] Wipe out traditional opt from x86_64 Makefile
Among other things, using -traditional as a gcc option stops us from using macro token pasting, which is a feature we heavily rely on. There was still a use of -traditional in arch/x86/kernel/Makefile_64, which this patch removes. I don't see any problems building kernels in my x86_64 box without -traditional. Signed-off-by: Glauber de Oliveira Costa <gcosta@redhat.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org> Acked-by: Jeremy Fitzhardinge <jeremy@xensource.com> --- arch/x86/kernel/Makefile_64 | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/arch/x86/kernel/Makefile_64 b/arch/x86/kernel/Makefile_64 index 5a88890..da0b1e5 100644 --- a/arch/x86/kernel/Makefile_64 +++ b/arch/x86/kernel/Makefile_64 @@ -4,7 +4,6 @@ extra-y := head_64.o head64.o init_task.o vmlinux.lds CPPFLAGS_vmlinux.lds += -Ux86_64 -EXTRA_AFLAGS := -traditional obj-y := process_64.o signal_64.o entry_64.o traps_64.o irq_64.o \ ptrace_64.o time_64.o ioport_64.o ldt_64.o setup_64.o i8259_64.o sys_x86_64.o \ -- 1.4.4.2
the rdpmc instruction gets a counter argument in rcx. However, the i386 version was ignoring it. To make both x86_64 and i386 versions the same, as well as to comply with the instruction semantics, this parameter is added in the i386 version Signed-off-by: Glauber de Oliveira Costa <gcosta@redhat.com> --- include/asm-x86/msr.h | 6 +++--- include/asm-x86/paravirt.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/asm-x86/msr.h b/include/asm-x86/msr.h index 0296358..ce2a257 100644 --- a/include/asm-x86/msr.h +++ b/include/asm-x86/msr.h @@ -90,10 +90,10 @@ static inline unsigned long long native_read_tsc(void) return val; } -static inline unsigned long long native_read_pmc(void) +static inline unsigned long long native_read_pmc(int counter) { unsigned long long val; - asm volatile("rdpmc" : "=A" (val)); + asm volatile("rdpmc" : "=A" (val) : "c" (counter)); return val; } @@ -150,7 +150,7 @@ static inline int wrmsr_safe(u32 __msr, u32 __low, u32 __high) #define rdpmc(counter,low,high) \ do { \ - u64 _l = native_read_pmc(); \ + u64 _l = native_read_pmc(counter); \ (low) = (u32)_l; \ (high) = (u32)(_l >> 32); \ } while(0) diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h index f59d370..4a7be97 100644 --- a/include/asm-x86/paravirt.h +++ b/include/asm-x86/paravirt.h @@ -118,7 +118,7 @@ struct pv_cpu_ops { int (*write_msr)(unsigned int msr, u64 val); u64 (*read_tsc)(void); - u64 (*read_pmc)(void); + u64 (*read_pmc)(int counter); /* These two are jmp to, not actually called. */ void (*irq_enable_sysexit)(void); -- 1.4.4.2
Glauber de Oliveira Costa
2007-Dec-04 05:54 UTC
[PATCH 8/10] change write msr functions interface
This patche changes the native_write_msr() and friends interface to explicitly take 2 32-bit registers instead of a 64-bit value. The change will ease the merge with 64-bit code. As the 64-bit value will be passed as two registers anyway in i386, the PVOP_CALL interface has to account for that and use low/high parameters It would force the x86_64 version to be different. The change does not make i386 generated code less efficient. As said above, it would get the values from two registers anyway. Signed-off-by: Glauber de Oliveira Costa <gcosta@redhat.com> --- include/asm-x86/msr.h | 19 ++++++++++--------- include/asm-x86/paravirt.h | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/include/asm-x86/msr.h b/include/asm-x86/msr.h index ce2a257..9c695c7 100644 --- a/include/asm-x86/msr.h +++ b/include/asm-x86/msr.h @@ -59,13 +59,14 @@ static inline unsigned long long native_read_msr_safe(unsigned int msr, return val; } -static inline void native_write_msr(unsigned int msr, unsigned long long val) +static inline void native_write_msr(unsigned int msr, + unsigned low, unsigned high) { - asm volatile("wrmsr" : : "c" (msr), "A"(val)); + asm volatile("wrmsr" : : "c" (msr), "a"(low), "d" (high)); } static inline int native_write_msr_safe(unsigned int msr, - unsigned long long val) + unsigned low, unsigned high) { int err; asm volatile("2: wrmsr ; xorl %0,%0\n" @@ -78,7 +79,7 @@ static inline int native_write_msr_safe(unsigned int msr, " .long 2b,3b\n\t" ".previous" : "=a" (err) - : "c" (msr), "0" ((u32)val), "d" ((u32)(val>>32)), + : "c" (msr), "0" (low), "d" (high), "i" (-EFAULT)); return err; } @@ -114,20 +115,20 @@ static inline unsigned long long native_read_pmc(int counter) (val2) = (u32)(__val >> 32); \ } while(0) -static inline void wrmsr(u32 __msr, u32 __low, u32 __high) +static inline void wrmsr(unsigned msr, unsigned low, unsigned high) { - native_write_msr(__msr, ((u64)__high << 32) | __low); + native_write_msr(msr, low, high); } #define rdmsrl(msr,val) \ ((val) = native_read_msr(msr)) -#define wrmsrl(msr,val) native_write_msr(msr, val) +#define wrmsrl(msr,val) native_write_msr(msr, (u32)val, (u32)(val >> 32)) /* wrmsr with exception handling */ -static inline int wrmsr_safe(u32 __msr, u32 __low, u32 __high) +static inline int wrmsr_safe(unsigned msr, unsigned low, unsigned high) { - return native_write_msr_safe(__msr, ((u64)__high << 32) | __low); + return native_write_msr_safe(msr, low, high); } /* rdmsr with exception handling */ diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h index 4a7be97..6f837bb 100644 --- a/include/asm-x86/paravirt.h +++ b/include/asm-x86/paravirt.h @@ -115,7 +115,7 @@ struct pv_cpu_ops { /* MSR, PMC and TSR operations. err = 0/-EFAULT. wrmsr returns 0/-EFAULT. */ u64 (*read_msr)(unsigned int msr, int *err); - int (*write_msr)(unsigned int msr, u64 val); + int (*write_msr)(unsigned int msr, unsigned low, unsigned high); u64 (*read_tsc)(void); u64 (*read_pmc)(int counter); -- 1.4.4.2
* Glauber de Oliveira Costa <gcosta@redhat.com> wrote:> Hello, > > This series of patches integrates msr.h header. What it really does, > is a series of steps to allow us to get rid of duplicate code between > i386 and x86_64 versions > > With this done, achieving paravirt for x86_64 gets really easy, just a > couple of extra code.thanks, the patches look certainly sane and i've picked them up into x86.git. A quick build & boot test was successful on both 64-bit and 32-bit, with paravirt on/off. I've pushed out the latest tree into the 'mm' branch of: git://git.kernel.org/pub/scm/linux/kernel/git/mingo/linux-2.6-x86.git minor nit: some of your patches had scripts/checkpatch.pl failures, could you try to fix them up? (If possible then as a follow-up second patch series.) Thanks! [ btw., how far away are you from having Kconfig selectable 64-bit paravirt support? Just curious :-) ] Ingo
Glauber de Oliveira Costa
2007-Dec-04 10:48 UTC
[PATCH 3/10] allow sched clock to be overridden by paravirt
This patch turns the sched_clock into native_sched_clock. sched clock becomes a weak symbol, which can then give its place to a paravirt definition. Signed-off-by: Glauber de Oliveira Costa <gcosta@redhat.com> --- arch/x86/kernel/tsc_64.c | 15 ++++++++++++++- 1 files changed, 14 insertions(+), 1 deletions(-) diff --git a/arch/x86/kernel/tsc_64.c b/arch/x86/kernel/tsc_64.c index 9c70af4..5158476 100644 --- a/arch/x86/kernel/tsc_64.c +++ b/arch/x86/kernel/tsc_64.c @@ -30,7 +30,7 @@ static unsigned long long cycles_2_ns(unsigned long long cyc) return (cyc * cyc2ns_scale) >> NS_SCALE; } -unsigned long long sched_clock(void) +unsigned long long native_sched_clock(void) { unsigned long a = 0; @@ -44,6 +44,19 @@ unsigned long long sched_clock(void) return cycles_2_ns(a); } +/* We need to define a real function for sched_clock, to override the + weak default version */ +#ifdef CONFIG_PARAVIRT +unsigned long long sched_clock(void) +{ + return paravirt_sched_clock(); +} +#else +unsigned long long +sched_clock(void) __attribute__((alias("native_sched_clock"))); +#endif + + static int tsc_unstable; inline int check_tsc_unstable(void) -- 1.4.4.2
the rdpmc instruction gets a counter argument in rcx. However, the i386 version was ignoring it. To make both x86_64 and i386 versions the same, as well as to comply with the instruction semantics, this parameter is added in the i386 version Signed-off-by: Glauber de Oliveira Costa <gcosta@redhat.com> --- include/asm-x86/msr.h | 6 +++--- include/asm-x86/paravirt.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/asm-x86/msr.h b/include/asm-x86/msr.h index 0296358..ce2a257 100644 --- a/include/asm-x86/msr.h +++ b/include/asm-x86/msr.h @@ -90,10 +90,10 @@ static inline unsigned long long native_read_tsc(void) return val; } -static inline unsigned long long native_read_pmc(void) +static inline unsigned long long native_read_pmc(int counter) { unsigned long long val; - asm volatile("rdpmc" : "=A" (val)); + asm volatile("rdpmc" : "=A" (val) : "c" (counter)); return val; } @@ -150,7 +150,7 @@ static inline int wrmsr_safe(u32 __msr, u32 __low, u32 __high) #define rdpmc(counter,low,high) \ do { \ - u64 _l = native_read_pmc(); \ + u64 _l = native_read_pmc(counter); \ (low) = (u32)_l; \ (high) = (u32)(_l >> 32); \ } while(0) diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h index f59d370..4a7be97 100644 --- a/include/asm-x86/paravirt.h +++ b/include/asm-x86/paravirt.h @@ -118,7 +118,7 @@ struct pv_cpu_ops { int (*write_msr)(unsigned int msr, u64 val); u64 (*read_tsc)(void); - u64 (*read_pmc)(void); + u64 (*read_pmc)(int counter); /* These two are jmp to, not actually called. */ void (*irq_enable_sysexit)(void); -- 1.4.4.2
Glauber de Oliveira Costa
2007-Dec-04 10:54 UTC
[PATCH 8/10] change write msr functions interface
This patche changes the native_write_msr() and friends interface to explicitly take 2 32-bit registers instead of a 64-bit value. The change will ease the merge with 64-bit code. As the 64-bit value will be passed as two registers anyway in i386, the PVOP_CALL interface has to account for that and use low/high parameters It would force the x86_64 version to be different. The change does not make i386 generated code less efficient. As said above, it would get the values from two registers anyway. Signed-off-by: Glauber de Oliveira Costa <gcosta@redhat.com> --- include/asm-x86/msr.h | 19 ++++++++++--------- include/asm-x86/paravirt.h | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/include/asm-x86/msr.h b/include/asm-x86/msr.h index ce2a257..9c695c7 100644 --- a/include/asm-x86/msr.h +++ b/include/asm-x86/msr.h @@ -59,13 +59,14 @@ static inline unsigned long long native_read_msr_safe(unsigned int msr, return val; } -static inline void native_write_msr(unsigned int msr, unsigned long long val) +static inline void native_write_msr(unsigned int msr, + unsigned low, unsigned high) { - asm volatile("wrmsr" : : "c" (msr), "A"(val)); + asm volatile("wrmsr" : : "c" (msr), "a"(low), "d" (high)); } static inline int native_write_msr_safe(unsigned int msr, - unsigned long long val) + unsigned low, unsigned high) { int err; asm volatile("2: wrmsr ; xorl %0,%0\n" @@ -78,7 +79,7 @@ static inline int native_write_msr_safe(unsigned int msr, " .long 2b,3b\n\t" ".previous" : "=a" (err) - : "c" (msr), "0" ((u32)val), "d" ((u32)(val>>32)), + : "c" (msr), "0" (low), "d" (high), "i" (-EFAULT)); return err; } @@ -114,20 +115,20 @@ static inline unsigned long long native_read_pmc(int counter) (val2) = (u32)(__val >> 32); \ } while(0) -static inline void wrmsr(u32 __msr, u32 __low, u32 __high) +static inline void wrmsr(unsigned msr, unsigned low, unsigned high) { - native_write_msr(__msr, ((u64)__high << 32) | __low); + native_write_msr(msr, low, high); } #define rdmsrl(msr,val) \ ((val) = native_read_msr(msr)) -#define wrmsrl(msr,val) native_write_msr(msr, val) +#define wrmsrl(msr, val) native_write_msr(msr, (u32)val, (u32)(val >> 32)) /* wrmsr with exception handling */ -static inline int wrmsr_safe(u32 __msr, u32 __low, u32 __high) +static inline int wrmsr_safe(unsigned msr, unsigned low, unsigned high) { - return native_write_msr_safe(__msr, ((u64)__high << 32) | __low); + return native_write_msr_safe(msr, low, high); } /* rdmsr with exception handling */ diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h index 4a7be97..6f837bb 100644 --- a/include/asm-x86/paravirt.h +++ b/include/asm-x86/paravirt.h @@ -115,7 +115,7 @@ struct pv_cpu_ops { /* MSR, PMC and TSR operations. err = 0/-EFAULT. wrmsr returns 0/-EFAULT. */ u64 (*read_msr)(unsigned int msr, int *err); - int (*write_msr)(unsigned int msr, u64 val); + int (*write_msr)(unsigned int msr, unsigned low, unsigned high); u64 (*read_tsc)(void); u64 (*read_pmc)(int counter); -- 1.4.4.2
Andi Kleen
2007-Dec-04 13:31 UTC
[PATCH 3/10] allow sched clock to be overridden by paravirt
On Tue, Dec 04, 2007 at 09:09:57AM -0200, Glauber de Oliveira Costa wrote:> This patch turns the sched_clock into native_sched_clock. > sched clock becomes a weak symbol, which can then give its > place to a paravirt definition.I ended up regretting that solution on i386, it would be better to solve that more clearly with ifdefs. -Andi