From 4e9baad8f5cb2040e802eff484fad7e721b21c0b Mon Sep 17 00:00:00 2001 From: Rudolf Marek Date: Tue, 8 May 2007 17:22:01 +0200 Subject: i386: Add safe variants of rdmsr_on_cpu and wrmsr_on_cpu Add safe (exception handled) variants of rdmsr_on_cpu and wrmsr_on_cpu. You should use these when the target MSR may not actually exist, as doing so could trigger an exception which the regular functions do not handle. The safe variants are slower, though. The upcoming coretemp hardware monitoring driver will need this. Signed-off-by: Rudolf Marek Cc: Alexey Dobriyan Cc: Dave Jones Signed-off-by: Jean Delvare --- arch/i386/lib/msr-on-cpu.c | 73 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/i386/lib/msr-on-cpu.c b/arch/i386/lib/msr-on-cpu.c index 1c46bda409ff..7767962f25d3 100644 --- a/arch/i386/lib/msr-on-cpu.c +++ b/arch/i386/lib/msr-on-cpu.c @@ -6,6 +6,7 @@ struct msr_info { u32 msr_no; u32 l, h; + int err; }; static void __rdmsr_on_cpu(void *info) @@ -15,20 +16,38 @@ static void __rdmsr_on_cpu(void *info) rdmsr(rv->msr_no, rv->l, rv->h); } -void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) +static void __rdmsr_safe_on_cpu(void *info) { + struct msr_info *rv = info; + + rv->err = rdmsr_safe(rv->msr_no, &rv->l, &rv->h); +} + +static int _rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h, int safe) +{ + int err = 0; preempt_disable(); if (smp_processor_id() == cpu) - rdmsr(msr_no, *l, *h); + if (safe) + err = rdmsr_safe(msr_no, l, h); + else + rdmsr(msr_no, *l, *h); else { struct msr_info rv; rv.msr_no = msr_no; - smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 0, 1); + if (safe) { + smp_call_function_single(cpu, __rdmsr_safe_on_cpu, + &rv, 0, 1); + err = rv.err; + } else { + smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 0, 1); + } *l = rv.l; *h = rv.h; } preempt_enable(); + return err; } static void __wrmsr_on_cpu(void *info) @@ -38,21 +57,63 @@ static void __wrmsr_on_cpu(void *info) wrmsr(rv->msr_no, rv->l, rv->h); } -void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) +static void __wrmsr_safe_on_cpu(void *info) { + struct msr_info *rv = info; + + rv->err = wrmsr_safe(rv->msr_no, rv->l, rv->h); +} + +static int _wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h, int safe) +{ + int err = 0; preempt_disable(); if (smp_processor_id() == cpu) - wrmsr(msr_no, l, h); + if (safe) + err = wrmsr_safe(msr_no, l, h); + else + wrmsr(msr_no, l, h); else { struct msr_info rv; rv.msr_no = msr_no; rv.l = l; rv.h = h; - smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 0, 1); + if (safe) { + smp_call_function_single(cpu, __wrmsr_safe_on_cpu, + &rv, 0, 1); + err = rv.err; + } else { + smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 0, 1); + } } preempt_enable(); + return err; +} + +void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) +{ + _wrmsr_on_cpu(cpu, msr_no, l, h, 0); +} + +void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) +{ + _rdmsr_on_cpu(cpu, msr_no, l, h, 0); +} + +/* These "safe" variants are slower and should be used when the target MSR + may not actually exist. */ +int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) +{ + return _wrmsr_on_cpu(cpu, msr_no, l, h, 1); +} + +int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) +{ + return _rdmsr_on_cpu(cpu, msr_no, l, h, 1); } EXPORT_SYMBOL(rdmsr_on_cpu); EXPORT_SYMBOL(wrmsr_on_cpu); +EXPORT_SYMBOL(rdmsr_safe_on_cpu); +EXPORT_SYMBOL(wrmsr_safe_on_cpu); -- cgit v1.2.3 From 78a62d2c9817dc1adfc563f5a7654df2c89be416 Mon Sep 17 00:00:00 2001 From: Nicolas Boichat Date: Tue, 8 May 2007 17:22:01 +0200 Subject: i386: Use functions from library in msr driver Use safe MSR functions provided by arch/*/lib/msr-on-cpu.c in arch/i386/kernel/msr.c. Signed-off-by: Nicolas Boichat Cc: H. Peter Anvin Signed-off-by: Jean Delvare --- arch/i386/kernel/msr.c | 106 ++----------------------------------------------- 1 file changed, 4 insertions(+), 102 deletions(-) (limited to 'arch') diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c index bcaa6e9b6197..8cd0a91ce107 100644 --- a/arch/i386/kernel/msr.c +++ b/arch/i386/kernel/msr.c @@ -45,104 +45,6 @@ static struct class *msr_class; -static inline int wrmsr_eio(u32 reg, u32 eax, u32 edx) -{ - int err; - - err = wrmsr_safe(reg, eax, edx); - if (err) - err = -EIO; - return err; -} - -static inline int rdmsr_eio(u32 reg, u32 *eax, u32 *edx) -{ - int err; - - err = rdmsr_safe(reg, eax, edx); - if (err) - err = -EIO; - return err; -} - -#ifdef CONFIG_SMP - -struct msr_command { - int err; - u32 reg; - u32 data[2]; -}; - -static void msr_smp_wrmsr(void *cmd_block) -{ - struct msr_command *cmd = (struct msr_command *)cmd_block; - - cmd->err = wrmsr_eio(cmd->reg, cmd->data[0], cmd->data[1]); -} - -static void msr_smp_rdmsr(void *cmd_block) -{ - struct msr_command *cmd = (struct msr_command *)cmd_block; - - cmd->err = rdmsr_eio(cmd->reg, &cmd->data[0], &cmd->data[1]); -} - -static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx) -{ - struct msr_command cmd; - int ret; - - preempt_disable(); - if (cpu == smp_processor_id()) { - ret = wrmsr_eio(reg, eax, edx); - } else { - cmd.reg = reg; - cmd.data[0] = eax; - cmd.data[1] = edx; - - smp_call_function_single(cpu, msr_smp_wrmsr, &cmd, 1, 1); - ret = cmd.err; - } - preempt_enable(); - return ret; -} - -static inline int do_rdmsr(int cpu, u32 reg, u32 * eax, u32 * edx) -{ - struct msr_command cmd; - int ret; - - preempt_disable(); - if (cpu == smp_processor_id()) { - ret = rdmsr_eio(reg, eax, edx); - } else { - cmd.reg = reg; - - smp_call_function_single(cpu, msr_smp_rdmsr, &cmd, 1, 1); - - *eax = cmd.data[0]; - *edx = cmd.data[1]; - - ret = cmd.err; - } - preempt_enable(); - return ret; -} - -#else /* ! CONFIG_SMP */ - -static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx) -{ - return wrmsr_eio(reg, eax, edx); -} - -static inline int do_rdmsr(int cpu, u32 reg, u32 *eax, u32 *edx) -{ - return rdmsr_eio(reg, eax, edx); -} - -#endif /* ! CONFIG_SMP */ - static loff_t msr_seek(struct file *file, loff_t offset, int orig) { loff_t ret = -EINVAL; @@ -174,9 +76,9 @@ static ssize_t msr_read(struct file *file, char __user * buf, return -EINVAL; /* Invalid chunk size */ for (; count; count -= 8) { - err = do_rdmsr(cpu, reg, &data[0], &data[1]); + err = rdmsr_safe_on_cpu(cpu, reg, &data[0], &data[1]); if (err) - return err; + return -EIO; if (copy_to_user(tmp, &data, 8)) return -EFAULT; tmp += 2; @@ -200,9 +102,9 @@ static ssize_t msr_write(struct file *file, const char __user *buf, for (; count; count -= 8) { if (copy_from_user(&data, tmp, 8)) return -EFAULT; - err = do_wrmsr(cpu, reg, data[0], data[1]); + err = wrmsr_safe_on_cpu(cpu, reg, data[0], data[1]); if (err) - return err; + return -EIO; tmp += 2; } -- cgit v1.2.3