[flashrom] Patch to fix wrmsr for some toolchains
Mart Raudsepp
mart.raudsepp at artecdesign.ee
Tue May 18 14:19:57 CEST 2010
Hello,
On E, 2010-05-17 at 16:20 -0700, ron minnich wrote:
> Hi, I'd like to know a bit more.
>
> This basic use of the msr device has worked for a very long time. I'm
> not saying there is not a problem, but if there is, it might be best
> to change the struct than to add this code.
Right. This got broken on our toolchains ever since this struct was
introduced to flashrom fater 0.9 release.
I'm not even sure the same thing hit me now and him back in October, but
the same patch fixes it.
It would be weird if this is a new regression in newer GCC version
though, as that would be an ABI break I believe..
Do however note that rdmsr goes through a temporary uint32_t array as
well, just like this patch makes wrmsr. So with this patch it's sort of
uniform that way too.
> Do you have some assembly code showing how it failed?
No I didn't. But now I got some :)
Attached is the physmap.c file from r998 compiled to assembly with all
the same optimization and other flags as the object file is made, just
saved to assembly with -S option. So if anyone can read from that what's
going on, then feel free to; I don't speak assembler well :(
> For example ... certainly, in user mode, why isn't the msr_t just a
> 64-bit number?
Don't really know. All I know is that C language does not really give a
guarantee of structs being tightly packed (are there other rules though,
like for default alignment instead of compiler specific?), unless using
compiler extensions like GCC packed attribute. I have it hard to imagine
why it would be adding alignment padding in there either, if that's what
it is doing per the attached assembler.
However sizeof(msr_t) seem to be returning 8 as desired...
Mart
-------------- next part --------------
.file "physmap.c"
.section .rodata.str1.1,"aMS", at progbits,1
.LC0:
.string "No MSR initialized.\n"
.text
.globl cleanup_cpu_msr
.type cleanup_cpu_msr, @function
cleanup_cpu_msr:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
movl fd_msr, %eax
cmpl $-1, %eax
jne .L2
pushl %eax
pushl %eax
pushl $.LC0
pushl $1
call print
jmp .L5
.L2:
subl $12, %esp
pushl %eax
call close
movl $-1, fd_msr
.L5:
addl $16, %esp
leave
ret
.size cleanup_cpu_msr, .-cleanup_cpu_msr
.section .rodata.str1.1
.LC1:
.string "Could not lseek() to MSR"
.LC2:
.string "Could not write() MSR"
.text
.globl wrmsr
.type wrmsr, @function
wrmsr:
pushl %ebp
movl %esp, %ebp
subl $12, %esp
pushl $0
pushl 8(%ebp)
pushl fd_msr
call lseek
addl $16, %esp
incl %eax
jne .L8
subl $12, %esp
pushl $.LC1
jmp .L13
.L8:
pushl %ecx
pushl $8
leal 12(%ebp), %eax
pushl %eax
pushl fd_msr
call write
addl $16, %esp
cmpl $8, %eax
je .L9
call __errno_location
cmpl $5, (%eax)
je .L9
subl $12, %esp
pushl $.LC2
.L13:
call perror
popl %edx
pushl fd_msr
call close
movl $1, (%esp)
call exit
.L9:
call __errno_location
cmpl $5, (%eax)
setne %al
movzbl %al, %eax
decl %eax
leave
ret
.size wrmsr, .-wrmsr
.section .rodata.str1.1
.LC3:
.string "Could not read() MSR"
.text
.globl rdmsr
.type rdmsr, @function
rdmsr:
pushl %ebp
movl %esp, %ebp
pushl %ebx
subl $24, %esp
movl 8(%ebp), %ebx
pushl $0
pushl 12(%ebp)
pushl fd_msr
call lseek
addl $16, %esp
incl %eax
jne .L15
subl $12, %esp
pushl $.LC1
jmp .L20
.L15:
pushl %eax
pushl $8
leal -16(%ebp), %eax
pushl %eax
pushl fd_msr
call read
addl $16, %esp
cmpl $8, %eax
jne .L16
movl -16(%ebp), %eax
movl %eax, 4(%ebx)
movl -12(%ebp), %eax
movl %eax, (%ebx)
jmp .L14
.L16:
call __errno_location
cmpl $5, (%eax)
je .L18
subl $12, %esp
pushl $.LC3
.L20:
call perror
popl %ebx
pushl fd_msr
call close
movl $1, (%esp)
call exit
.L18:
movl $-1, 4(%ebx)
movl $-1, (%ebx)
.L14:
movl %ebx, %eax
movl -4(%ebp), %ebx
leave
ret $4
.size rdmsr, .-rdmsr
.section .rodata.str1.1
.LC4:
.string "Not unmapping zero size at %p\n"
.text
.globl physunmap
.type physunmap, @function
physunmap:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
movl 8(%ebp), %eax
movl 12(%ebp), %edx
testl %edx, %edx
jne .L22
pushl %edx
pushl %eax
pushl $.LC4
pushl $3
call print
addl $16, %esp
leave
ret
.L22:
movl %edx, 12(%ebp)
movl %eax, 8(%ebp)
leave
jmp munmap
.size physunmap, .-physunmap
.section .rodata.str1.1
.LC5:
.string "/dev/mem"
.LC6:
.string "Critical error: open(/dev/mem): %s"
.text
.globl sys_physmap_ro_cached
.type sys_physmap_ro_cached, @function
sys_physmap_ro_cached:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
cmpl $-1, fd_mem_cached
jne .L26
pushl %eax
pushl %eax
pushl $2
pushl $.LC5
call open
movl %eax, fd_mem_cached
addl $16, %esp
incl %eax
jne .L26
call __errno_location
subl $12, %esp
pushl (%eax)
call strerror
addl $12, %esp
pushl %eax
pushl $.LC6
pushl $0
call print
movl $2, (%esp)
call exit
.L26:
pushl %ecx
pushl %ecx
pushl 8(%ebp)
pushl fd_mem_cached
pushl $1
pushl $1
pushl 12(%ebp)
pushl $0
call mmap
addl $32, %esp
xorl %edx, %edx
cmpl $-1, %eax
setne %dl
negl %edx
andl %edx, %eax
leave
ret
.size sys_physmap_ro_cached, .-sys_physmap_ro_cached
.section .rodata.str1.1
.LC7:
.string "Critical error: open(/dev/mem)"
.text
.globl sys_physmap_rw_uncached
.type sys_physmap_rw_uncached, @function
sys_physmap_rw_uncached:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
cmpl $-1, fd_mem
jne .L30
pushl %ecx
pushl %ecx
pushl $4098
pushl $.LC5
call open
movl %eax, fd_mem
addl $16, %esp
incl %eax
jne .L30
subl $12, %esp
pushl $.LC7
call perror
movl $2, (%esp)
call exit
.L30:
pushl %edx
pushl %edx
pushl 8(%ebp)
pushl fd_mem
pushl $1
pushl $3
pushl 12(%ebp)
pushl $0
call mmap
addl $32, %esp
xorl %edx, %edx
cmpl $-1, %eax
setne %dl
negl %edx
andl %edx, %eax
leave
ret
.size sys_physmap_rw_uncached, .-sys_physmap_rw_uncached
.section .rodata.str1.1
.LC8:
.string "Not mapping %s, zero size at 0x%08lx.\n"
.LC9:
.string "Mapping %s at 0x%08lx, unaligned size 0x%lx.\n"
.LC10:
.string "Mapping %s, 0x%lx bytes at unaligned 0x%08lx.\n"
.LC11:
.string "memory"
.LC12:
.string "Error accessing %s, 0x%lx bytes at 0x%08lx\n"
.LC13:
.string "/dev/mem mmap failed"
.LC14:
.string "In Linux this error can be caused by the CONFIG_NONPROMISC_DEVMEM (<2.6.27),\n"
.LC15:
.string "CONFIG_STRICT_DEVMEM (>=2.6.27) and CONFIG_X86_PAT kernel options.\n"
.LC16:
.string "Please check if either is enabled in your kernel before reporting a failure.\n"
.LC17:
.string "You can override CONFIG_X86_PAT at boot with the nopat kernel parameter but\n"
.LC18:
.string "disabling the other option unfortunately requires a kernel recompile. Sorry!\n"
.text
.globl physmap_common
.type physmap_common, @function
physmap_common:
pushl %ebp
movl %esp, %ebp
pushl %edi
pushl %esi
pushl %ebx
subl $28, %esp
movl 8(%ebp), %edi
movl 12(%ebp), %esi
movl 16(%ebp), %ebx
testl %ebx, %ebx
jne .L34
pushl %esi
pushl %edi
pushl $.LC8
pushl $3
call print
xorl %edx, %edx
addl $16, %esp
jmp .L35
.L34:
call getpagesize
decl %eax
movl %eax, -28(%ebp)
testl %ebx, %eax
je .L36
subl $12, %esp
pushl %ebx
pushl %esi
pushl %edi
pushl $.LC9
pushl $0
call print
addl $32, %esp
.L36:
testl %esi, -28(%ebp)
je .L37
subl $12, %esp
pushl %esi
pushl %ebx
pushl %edi
pushl $.LC10
pushl $0
call print
addl $32, %esp
.L37:
cmpl $0, 24(%ebp)
je .L38
pushl %edx
pushl %edx
pushl %ebx
pushl %esi
call sys_physmap_ro_cached
jmp .L43
.L38:
pushl %eax
pushl %eax
pushl %ebx
pushl %esi
call sys_physmap_rw_uncached
.L43:
movl %eax, %edx
addl $16, %esp
testl %eax, %eax
jne .L35
testl %edi, %edi
jne .L40
movl $.LC11, %edi
.L40:
subl $12, %esp
pushl %esi
pushl %ebx
pushl %edi
pushl $.LC12
pushl $0
movl %edx, -32(%ebp)
call print
addl $20, %esp
pushl $.LC13
call perror
call __errno_location
addl $16, %esp
cmpl $22, (%eax)
movl -32(%ebp), %edx
jne .L41
pushl %edi
pushl %edi
pushl $.LC14
pushl $0
call print
popl %ebx
popl %esi
pushl $.LC15
pushl $0
call print
popl %edx
popl %ecx
pushl $.LC16
pushl $0
call print
popl %edi
popl %eax
pushl $.LC17
pushl $0
call print
popl %ebx
popl %esi
pushl $.LC18
pushl $0
call print
addl $16, %esp
movl -32(%ebp), %edx
.L41:
cmpl $0, 20(%ebp)
jne .L35
subl $12, %esp
pushl $3
call exit
.L35:
movl %edx, %eax
leal -12(%ebp), %esp
popl %ebx
popl %esi
popl %edi
popl %ebp
ret
.size physmap_common, .-physmap_common
.globl physmap_try_ro
.type physmap_try_ro, @function
physmap_try_ro:
pushl %ebp
movl %esp, %ebp
subl $20, %esp
pushl $1
pushl $1
pushl 16(%ebp)
pushl 12(%ebp)
pushl 8(%ebp)
call physmap_common
leave
ret
.size physmap_try_ro, .-physmap_try_ro
.globl physmap
.type physmap, @function
physmap:
pushl %ebp
movl %esp, %ebp
subl $20, %esp
pushl $0
pushl $0
pushl 16(%ebp)
pushl 12(%ebp)
pushl 8(%ebp)
call physmap_common
leave
ret
.size physmap, .-physmap
.section .rodata.str1.1
.LC19:
.string "/dev/cpu/%d/msr"
.LC20:
.string "MSR was already initialized\n"
.LC21:
.string "Error while opening /dev/cpu/0/msr"
.LC22:
.string "Did you run 'modprobe msr'?\n"
.text
.globl setup_cpu_msr
.type setup_cpu_msr, @function
setup_cpu_msr:
pushl %ebp
movl %esp, %ebp
pushl %edi
pushl %ebx
subl $76, %esp
cld
leal -72(%ebp), %ebx
movl $16, %ecx
xorl %eax, %eax
movl %ebx, %edi
rep stosl
pushl 8(%ebp)
pushl $.LC19
pushl $64
pushl $1
pushl %ebx
call __sprintf_chk
addl $32, %esp
cmpl $-1, fd_msr
je .L49
pushl %eax
pushl %eax
pushl $.LC20
jmp .L53
.L49:
pushl %edi
pushl %edi
pushl $2
pushl %ebx
call open
movl %eax, %edx
movl %eax, fd_msr
addl $16, %esp
xorl %eax, %eax
testl %edx, %edx
jns .L50
subl $12, %esp
pushl $.LC21
call perror
popl %ecx
popl %ebx
pushl $.LC22
.L53:
pushl $1
call print
orl $-1, %eax
addl $16, %esp
.L50:
leal -8(%ebp), %esp
popl %ebx
popl %edi
popl %ebp
ret
.size setup_cpu_msr, .-setup_cpu_msr
.data
.align 4
.type fd_msr, @object
.size fd_msr, 4
fd_msr:
.long -1
.align 4
.type fd_mem_cached, @object
.size fd_mem_cached, 4
fd_mem_cached:
.long -1
.align 4
.type fd_mem, @object
.size fd_mem, 4
fd_mem:
.long -1
.ident "GCC: (Gentoo 4.4.3 p1.0) 4.4.3"
.section .note.GNU-stack,"", at progbits
More information about the flashrom
mailing list