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