Re: [PATCH] x86/dmi: Switch dmi_remap to ioremap_cache

From: Julian Brost
Date: Thu Mar 09 2017 - 13:45:38 EST


On 26.01.2016 08:06, Andy Lutomirski wrote:
> DMI cacheability is very confused on x86.
>
> dmi_early_remap uses early_ioremap, which uses FIXMAP_PAGE_IO, which
> is __PAGE_KERNEL_IO, which is __PAGE_KERNEL, which is cached. Don't
> ask me why this makes any sense.
>
> dmi_remap uses ioremap, which requests an uncached mapping.
> However, on non-EFI systems, the DMI data generally lives between
> 0xf0000 and 0x100000, which is in the legacy ISA range, which
> triggers a special case in the PAT code that overrides the cache
> mode requested by ioremap and forces a WB mapping.
>
> On a UEFI boot, however, the DMI table can live at any physical
> address. On my laptop, it's around 0x77dd0000. That's nowhere near
> the legacy ISA range, so the ioremap implicit uncached type is
> honored and we end up with a UC- mapping.
>
> UC- is a very, very slow way to read from main memory, so dmi_walk
> is likely to take much longer than necessary.
>
> Given that, even on UEFI, we do early cached DMI reads, it seems
> safe to just ask for cached access. Switch to ioremap_cache.
>
> I haven't tried to benchmark this, but I'd guess it saves several
> milliseconds of boot time.
>
> Signed-off-by: Andy Lutomirski <luto@xxxxxxxxxx>
> ---
> arch/x86/include/asm/dmi.h | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/x86/include/asm/dmi.h b/arch/x86/include/asm/dmi.h
> index 535192f6bfad..3c69fed215c5 100644
> --- a/arch/x86/include/asm/dmi.h
> +++ b/arch/x86/include/asm/dmi.h
> @@ -15,7 +15,7 @@ static __always_inline __init void *dmi_alloc(unsigned len)
> /* Use early IO mappings for DMI because it's initialized early */
> #define dmi_early_remap early_ioremap
> #define dmi_early_unmap early_iounmap
> -#define dmi_remap ioremap
> +#define dmi_remap ioremap_cache
> #define dmi_unmap iounmap
>
> #endif /* _ASM_X86_DMI_H */
>

Hi,

after updating from kernel 4.4 to 4.9, the hp-health tools stopped
working on our HP servers (ProLiant DL380p Gen8 and DL380 Gen9, no
others tested). Bisecting has shown commit ce1143a to be the cause.
Reverting it on top of 4.9.13 solved the issue for us.

In more detail, the hp-health tools fail to start because hpasmlited
segfaults with the following log messages:

hpasmlited[3218]: (SendRecv_CHIF) CpqCiSend: error=4, "Bad name for the
target connection object.".
hpasmlited[3218]: (SendRecv_CHIF) CpqCiSend: error=4, "Bad name for the
target connection object.".
hpasmlited[3218]: ehpsmb_parse_SMBIOS: SMBIOSInitTable was not successful.
hpasrd[3272]: WARNING: Can not open /dev/cpqhealth/casr.
hpasrd[3272]: ERROR: Failed to get ASR enabled state.
kernel: x86/PAT: hpasmlited:3218 map pfn expected mapping type
uncached-minus for [mem 0xbfbdb000-0xbfbdcfff], got write-back
kernel: hpasmlited[3218]: segfault at 0 ip 000000000040605b sp
00007ffea5f3beb0 error 4 in hpasmlited[400000+3a000]

According to strace, this is one of the last actions of hpasmlited
before it segfaults:

mmap(NULL, 6176, PROT_READ, MAP_SHARED, 13</dev/mem>, 0xbfbdb000) = -1
EAGAIN (Resource temporarily unavailable)

I'm note entirely sure whether it's actually the kernel or HP to blame,
but for now, hp-health is completely broken on 4.9 (probably on
everything starting from 4.6), so this patch should be reviewed again.

Regards,
Julian

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature