2023-03-15 08:53:41

by Huacai Chen

[permalink] [raw]
Subject: [PATCH V3] LoongArch: Make WriteCombine configurable for ioremap()

LoongArch maintains cache coherency in hardware, but when paired with
LS7A chipsets the WUC attribute (Weak-ordered UnCached, which is similar
to WriteCombine) is out of the scope of cache coherency machanism for
PCIe devices (this is a PCIe protocol violation, which may be fixed in
newer chipsets).

This means WUC can only used for write-only memory regions now, so this
option is disabled by default, making WUC silently fallback to SUC for
ioremap(). You can enable this option if the kernel is ensured to run on
hardware without this bug.

Kernel parameter writecombine=on/off can be used to override the Kconfig
option.

Suggested-by: WANG Xuerui <[email protected]>
Signed-off-by: Huacai Chen <[email protected]>
---
V2: Add kernel prameter and update commit messages.
V3: Add a warning message for invalid kernel parameters.

arch/loongarch/Kconfig | 16 ++++++++++++++++
arch/loongarch/include/asm/io.h | 4 +++-
arch/loongarch/kernel/setup.c | 21 +++++++++++++++++++++
3 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
index 7fd51257e0ed..3ddde336e6a5 100644
--- a/arch/loongarch/Kconfig
+++ b/arch/loongarch/Kconfig
@@ -447,6 +447,22 @@ config ARCH_IOREMAP
protection support. However, you can enable LoongArch DMW-based
ioremap() for better performance.

+config ARCH_WRITECOMBINE
+ bool "Enable WriteCombine (WUC) for ioremap()"
+ help
+ LoongArch maintains cache coherency in hardware, but when paired
+ with LS7A chipsets the WUC attribute (Weak-ordered UnCached, which
+ is similar to WriteCombine) is out of the scope of cache coherency
+ machanism for PCIe devices (this is a PCIe protocol violation, which
+ may be fixed in newer chipsets).
+
+ This means WUC can only used for write-only memory regions now, so
+ this option is disabled by default, making WUC silently fallback to
+ SUC for ioremap(). You can enable this option if the kernel is ensured
+ to run on hardware without this bug.
+
+ You can override this setting via writecombine=on/off boot parameter.
+
config ARCH_STRICT_ALIGN
bool "Enable -mstrict-align to prevent unaligned accesses" if EXPERT
default y
diff --git a/arch/loongarch/include/asm/io.h b/arch/loongarch/include/asm/io.h
index 402a7d9e3a53..545e2708fbf7 100644
--- a/arch/loongarch/include/asm/io.h
+++ b/arch/loongarch/include/asm/io.h
@@ -54,8 +54,10 @@ static inline void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
* @offset: bus address of the memory
* @size: size of the resource to map
*/
+extern pgprot_t pgprot_wc;
+
#define ioremap_wc(offset, size) \
- ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL_WUC))
+ ioremap_prot((offset), (size), pgprot_val(pgprot_wc))

#define ioremap_cache(offset, size) \
ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL))
diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c
index bae84ccf6d36..27f71f9531e1 100644
--- a/arch/loongarch/kernel/setup.c
+++ b/arch/loongarch/kernel/setup.c
@@ -160,6 +160,27 @@ static void __init smbios_parse(void)
dmi_walk(find_tokens, NULL);
}

+#ifdef CONFIG_ARCH_WRITECOMBINE
+pgprot_t pgprot_wc = PAGE_KERNEL_WUC;
+#else
+pgprot_t pgprot_wc = PAGE_KERNEL_SUC;
+#endif
+
+EXPORT_SYMBOL(pgprot_wc);
+
+static int __init setup_writecombine(char *p)
+{
+ if (!strcmp(p, "on"))
+ pgprot_wc = PAGE_KERNEL_WUC;
+ else if (!strcmp(p, "off"))
+ pgprot_wc = PAGE_KERNEL_SUC;
+ else
+ pr_warn("Unknown writecombine setting \"%s\".\n", p);
+
+ return 0;
+}
+early_param("writecombine", setup_writecombine);
+
static int usermem __initdata;

static int __init early_parse_mem(char *p)
--
2.39.1



2023-03-16 04:35:05

by WANG Xuerui

[permalink] [raw]
Subject: Re: [PATCH V3] LoongArch: Make WriteCombine configurable for ioremap()

On 3/15/23 16:53, Huacai Chen wrote:
> LoongArch maintains cache coherency in hardware, but when paired with
> LS7A chipsets the WUC attribute (Weak-ordered UnCached, which is similar
> to WriteCombine) is out of the scope of cache coherency machanism for
> PCIe devices (this is a PCIe protocol violation, which may be fixed in
> newer chipsets).
>
> This means WUC can only used for write-only memory regions now, so this
"can only be used for". Same for the Kconfig change.
> option is disabled by default, making WUC silently fallback to SUC for
> ioremap(). You can enable this option if the kernel is ensured to run on
> hardware without this bug.
>
> Kernel parameter writecombine=on/off can be used to override the Kconfig
> option.
We normally want to document this in
Documentation/admin-guide/kernel-parameters too. This can be done later
(by you or me).
>
> Suggested-by: WANG Xuerui <[email protected]>
> Signed-off-by: Huacai Chen <[email protected]>
> ---
> V2: Add kernel prameter and update commit messages.
> V3: Add a warning message for invalid kernel parameters.
>
> arch/loongarch/Kconfig | 16 ++++++++++++++++
> arch/loongarch/include/asm/io.h | 4 +++-
> arch/loongarch/kernel/setup.c | 21 +++++++++++++++++++++
> 3 files changed, 40 insertions(+), 1 deletion(-)
>
> diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
> index 7fd51257e0ed..3ddde336e6a5 100644
> --- a/arch/loongarch/Kconfig
> +++ b/arch/loongarch/Kconfig
> @@ -447,6 +447,22 @@ config ARCH_IOREMAP
> protection support. However, you can enable LoongArch DMW-based
> ioremap() for better performance.
>
> +config ARCH_WRITECOMBINE
> + bool "Enable WriteCombine (WUC) for ioremap()"
> + help
> + LoongArch maintains cache coherency in hardware, but when paired
> + with LS7A chipsets the WUC attribute (Weak-ordered UnCached, which
> + is similar to WriteCombine) is out of the scope of cache coherency
> + machanism for PCIe devices (this is a PCIe protocol violation, which
> + may be fixed in newer chipsets).
> +
> + This means WUC can only used for write-only memory regions now, so
> + this option is disabled by default, making WUC silently fallback to
> + SUC for ioremap(). You can enable this option if the kernel is ensured
> + to run on hardware without this bug.
> +
> + You can override this setting via writecombine=on/off boot parameter.
via the ...
> +
> config ARCH_STRICT_ALIGN
> bool "Enable -mstrict-align to prevent unaligned accesses" if EXPERT
> default y
> diff --git a/arch/loongarch/include/asm/io.h b/arch/loongarch/include/asm/io.h
> index 402a7d9e3a53..545e2708fbf7 100644
> --- a/arch/loongarch/include/asm/io.h
> +++ b/arch/loongarch/include/asm/io.h
> @@ -54,8 +54,10 @@ static inline void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
> * @offset: bus address of the memory
> * @size: size of the resource to map
> */
> +extern pgprot_t pgprot_wc;
> +
> #define ioremap_wc(offset, size) \
> - ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL_WUC))
> + ioremap_prot((offset), (size), pgprot_val(pgprot_wc))
>
> #define ioremap_cache(offset, size) \
> ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL))
> diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c
> index bae84ccf6d36..27f71f9531e1 100644
> --- a/arch/loongarch/kernel/setup.c
> +++ b/arch/loongarch/kernel/setup.c
> @@ -160,6 +160,27 @@ static void __init smbios_parse(void)
> dmi_walk(find_tokens, NULL);
> }
>
> +#ifdef CONFIG_ARCH_WRITECOMBINE
> +pgprot_t pgprot_wc = PAGE_KERNEL_WUC;
> +#else
> +pgprot_t pgprot_wc = PAGE_KERNEL_SUC;
> +#endif
> +
> +EXPORT_SYMBOL(pgprot_wc);
> +
> +static int __init setup_writecombine(char *p)
> +{
> + if (!strcmp(p, "on"))
> + pgprot_wc = PAGE_KERNEL_WUC;
> + else if (!strcmp(p, "off"))
> + pgprot_wc = PAGE_KERNEL_SUC;
> + else
> + pr_warn("Unknown writecombine setting \"%s\".\n", p);
> +
> + return 0;
> +}
> +early_param("writecombine", setup_writecombine);
> +
> static int usermem __initdata;
>
> static int __init early_parse_mem(char *p)

With the nits addressed:

Reviewed-by: WANG Xuerui <[email protected]>

--
WANG "xen0n" Xuerui

Linux/LoongArch mailing list: https://lore.kernel.org/loongarch/


2023-03-16 06:44:50

by Huacai Chen

[permalink] [raw]
Subject: Re: [PATCH V3] LoongArch: Make WriteCombine configurable for ioremap()

OK, V4 is coming.

Huacai

On Thu, Mar 16, 2023 at 12:35 PM WANG Xuerui <[email protected]> wrote:
>
> On 3/15/23 16:53, Huacai Chen wrote:
> > LoongArch maintains cache coherency in hardware, but when paired with
> > LS7A chipsets the WUC attribute (Weak-ordered UnCached, which is similar
> > to WriteCombine) is out of the scope of cache coherency machanism for
> > PCIe devices (this is a PCIe protocol violation, which may be fixed in
> > newer chipsets).
> >
> > This means WUC can only used for write-only memory regions now, so this
> "can only be used for". Same for the Kconfig change.
> > option is disabled by default, making WUC silently fallback to SUC for
> > ioremap(). You can enable this option if the kernel is ensured to run on
> > hardware without this bug.
> >
> > Kernel parameter writecombine=on/off can be used to override the Kconfig
> > option.
> We normally want to document this in
> Documentation/admin-guide/kernel-parameters too. This can be done later
> (by you or me).
> >
> > Suggested-by: WANG Xuerui <[email protected]>
> > Signed-off-by: Huacai Chen <[email protected]>
> > ---
> > V2: Add kernel prameter and update commit messages.
> > V3: Add a warning message for invalid kernel parameters.
> >
> > arch/loongarch/Kconfig | 16 ++++++++++++++++
> > arch/loongarch/include/asm/io.h | 4 +++-
> > arch/loongarch/kernel/setup.c | 21 +++++++++++++++++++++
> > 3 files changed, 40 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
> > index 7fd51257e0ed..3ddde336e6a5 100644
> > --- a/arch/loongarch/Kconfig
> > +++ b/arch/loongarch/Kconfig
> > @@ -447,6 +447,22 @@ config ARCH_IOREMAP
> > protection support. However, you can enable LoongArch DMW-based
> > ioremap() for better performance.
> >
> > +config ARCH_WRITECOMBINE
> > + bool "Enable WriteCombine (WUC) for ioremap()"
> > + help
> > + LoongArch maintains cache coherency in hardware, but when paired
> > + with LS7A chipsets the WUC attribute (Weak-ordered UnCached, which
> > + is similar to WriteCombine) is out of the scope of cache coherency
> > + machanism for PCIe devices (this is a PCIe protocol violation, which
> > + may be fixed in newer chipsets).
> > +
> > + This means WUC can only used for write-only memory regions now, so
> > + this option is disabled by default, making WUC silently fallback to
> > + SUC for ioremap(). You can enable this option if the kernel is ensured
> > + to run on hardware without this bug.
> > +
> > + You can override this setting via writecombine=on/off boot parameter.
> via the ...
> > +
> > config ARCH_STRICT_ALIGN
> > bool "Enable -mstrict-align to prevent unaligned accesses" if EXPERT
> > default y
> > diff --git a/arch/loongarch/include/asm/io.h b/arch/loongarch/include/asm/io.h
> > index 402a7d9e3a53..545e2708fbf7 100644
> > --- a/arch/loongarch/include/asm/io.h
> > +++ b/arch/loongarch/include/asm/io.h
> > @@ -54,8 +54,10 @@ static inline void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
> > * @offset: bus address of the memory
> > * @size: size of the resource to map
> > */
> > +extern pgprot_t pgprot_wc;
> > +
> > #define ioremap_wc(offset, size) \
> > - ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL_WUC))
> > + ioremap_prot((offset), (size), pgprot_val(pgprot_wc))
> >
> > #define ioremap_cache(offset, size) \
> > ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL))
> > diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c
> > index bae84ccf6d36..27f71f9531e1 100644
> > --- a/arch/loongarch/kernel/setup.c
> > +++ b/arch/loongarch/kernel/setup.c
> > @@ -160,6 +160,27 @@ static void __init smbios_parse(void)
> > dmi_walk(find_tokens, NULL);
> > }
> >
> > +#ifdef CONFIG_ARCH_WRITECOMBINE
> > +pgprot_t pgprot_wc = PAGE_KERNEL_WUC;
> > +#else
> > +pgprot_t pgprot_wc = PAGE_KERNEL_SUC;
> > +#endif
> > +
> > +EXPORT_SYMBOL(pgprot_wc);
> > +
> > +static int __init setup_writecombine(char *p)
> > +{
> > + if (!strcmp(p, "on"))
> > + pgprot_wc = PAGE_KERNEL_WUC;
> > + else if (!strcmp(p, "off"))
> > + pgprot_wc = PAGE_KERNEL_SUC;
> > + else
> > + pr_warn("Unknown writecombine setting \"%s\".\n", p);
> > +
> > + return 0;
> > +}
> > +early_param("writecombine", setup_writecombine);
> > +
> > static int usermem __initdata;
> >
> > static int __init early_parse_mem(char *p)
>
> With the nits addressed:
>
> Reviewed-by: WANG Xuerui <[email protected]>
>
> --
> WANG "xen0n" Xuerui
>
> Linux/LoongArch mailing list: https://lore.kernel.org/loongarch/
>
>