提交 c10d52d6 编写于 作者: A Armin Wolf 提交者: Guenter Roeck

hwmon: (dell-smm) Improve assembly code

The new assembly code works on both 32 bit and 64 bit
cpus and allows for more compiler optimisations.
Since clang runs out of registers on 32 bit x86 when
using CC_OUT, we need to execute "setc" ourself.
Also modify the debug message so we can still see
the result (eax) when the carry flag was set.

Tested with 32 bit and 64 bit kernels on a Dell Inspiron 3505.
Signed-off-by: NArmin Wolf <W_Armin@gmx.de>
Link: https://lore.kernel.org/r/20220220190851.17965-1-W_Armin@gmx.de
[groeck: Rebased to v5.19-rc3]
Signed-off-by: NGuenter Roeck <linux@roeck-us.net>
上级 4a235369
...@@ -130,7 +130,7 @@ struct smm_regs { ...@@ -130,7 +130,7 @@ struct smm_regs {
unsigned int edx; unsigned int edx;
unsigned int esi; unsigned int esi;
unsigned int edi; unsigned int edi;
} __packed; };
static const char * const temp_labels[] = { static const char * const temp_labels[] = {
"CPU", "CPU",
...@@ -175,77 +175,35 @@ static int i8k_smm_func(void *par) ...@@ -175,77 +175,35 @@ static int i8k_smm_func(void *par)
struct smm_regs *regs = par; struct smm_regs *regs = par;
int eax = regs->eax; int eax = regs->eax;
int ebx = regs->ebx; int ebx = regs->ebx;
unsigned char carry;
long long duration; long long duration;
int rc;
/* SMM requires CPU 0 */ /* SMM requires CPU 0 */
if (smp_processor_id() != 0) if (smp_processor_id() != 0)
return -EBUSY; return -EBUSY;
#if defined(CONFIG_X86_64) asm volatile("out %%al,$0xb2\n\t"
asm volatile("pushq %%rax\n\t" "out %%al,$0x84\n\t"
"movl 0(%%rax),%%edx\n\t" "setc %0\n"
"pushq %%rdx\n\t" : "=mr" (carry),
"movl 4(%%rax),%%ebx\n\t" "+a" (regs->eax),
"movl 8(%%rax),%%ecx\n\t" "+b" (regs->ebx),
"movl 12(%%rax),%%edx\n\t" "+c" (regs->ecx),
"movl 16(%%rax),%%esi\n\t" "+d" (regs->edx),
"movl 20(%%rax),%%edi\n\t" "+S" (regs->esi),
"popq %%rax\n\t" "+D" (regs->edi));
"out %%al,$0xb2\n\t"
"out %%al,$0x84\n\t"
"xchgq %%rax,(%%rsp)\n\t"
"movl %%ebx,4(%%rax)\n\t"
"movl %%ecx,8(%%rax)\n\t"
"movl %%edx,12(%%rax)\n\t"
"movl %%esi,16(%%rax)\n\t"
"movl %%edi,20(%%rax)\n\t"
"popq %%rdx\n\t"
"movl %%edx,0(%%rax)\n\t"
"pushfq\n\t"
"popq %%rax\n\t"
"andl $1,%%eax\n"
: "=a"(rc)
: "a"(regs)
: "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
#else
asm volatile("pushl %%eax\n\t"
"movl 0(%%eax),%%edx\n\t"
"push %%edx\n\t"
"movl 4(%%eax),%%ebx\n\t"
"movl 8(%%eax),%%ecx\n\t"
"movl 12(%%eax),%%edx\n\t"
"movl 16(%%eax),%%esi\n\t"
"movl 20(%%eax),%%edi\n\t"
"popl %%eax\n\t"
"out %%al,$0xb2\n\t"
"out %%al,$0x84\n\t"
"xchgl %%eax,(%%esp)\n\t"
"movl %%ebx,4(%%eax)\n\t"
"movl %%ecx,8(%%eax)\n\t"
"movl %%edx,12(%%eax)\n\t"
"movl %%esi,16(%%eax)\n\t"
"movl %%edi,20(%%eax)\n\t"
"popl %%edx\n\t"
"movl %%edx,0(%%eax)\n\t"
"lahf\n\t"
"shrl $8,%%eax\n\t"
"andl $1,%%eax\n"
: "=a"(rc)
: "a"(regs)
: "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
#endif
if (rc != 0 || (regs->eax & 0xffff) == 0xffff || regs->eax == eax)
rc = -EINVAL;
duration = ktime_us_delta(ktime_get(), calltime); duration = ktime_us_delta(ktime_get(), calltime);
pr_debug("smm(0x%.4x 0x%.4x) = 0x%.4x (took %7lld usecs)\n", eax, ebx, pr_debug("smm(0x%.4x 0x%.4x) = 0x%.4x carry: %d (took %7lld usecs)\n",
(rc ? 0xffff : regs->eax & 0xffff), duration); eax, ebx, regs->eax & 0xffff, carry, duration);
if (duration > DELL_SMM_MAX_DURATION) if (duration > DELL_SMM_MAX_DURATION)
pr_warn_once("SMM call took %lld usecs!\n", duration); pr_warn_once("SMM call took %lld usecs!\n", duration);
return rc; if (carry || (regs->eax & 0xffff) == 0xffff || regs->eax == eax)
return -EINVAL;
return 0;
} }
/* /*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册