diff mbox series

[2/2] riscv: mm: add pgprot_dmacoherent for zicbom

Message ID 20230307205834.1426289-3-ben.dooks@codethink.co.uk (mailing list archive)
State Changes Requested
Headers show
Series [1/2] riscv: alternatives: add 3-config alternative set | expand

Checks

Context Check Description
conchuod/cover_letter success Single patches do not need cover letters
conchuod/tree_selection success Guessed tree name to be for-next
conchuod/fixes_present success Fixes tag not required for -next series
conchuod/maintainers_pattern success MAINTAINERS pattern errors before the patch: 1 and now 1
conchuod/verify_signedoff success Signed-off-by tag matches author and committer
conchuod/kdoc success Errors and warnings before: 0 this patch: 0
conchuod/build_rv64_clang_allmodconfig success Errors and warnings before: 2275 this patch: 2275
conchuod/module_param success Was 0 now: 0
conchuod/build_rv64_gcc_allmodconfig success Errors and warnings before: 17609 this patch: 17609
conchuod/alphanumeric_selects success Out of order selects before the patch: 728 and now 728
conchuod/build_rv32_defconfig success Build OK
conchuod/dtb_warn_rv64 success Errors and warnings before: 3 this patch: 3
conchuod/header_inline success No static functions without inline keyword in header files
conchuod/checkpatch warning CHECK: Please don't use multiple blank lines
conchuod/source_inline success Was 0 now: 0
conchuod/build_rv64_nommu_k210_defconfig success Build OK
conchuod/verify_fixes success No Fixes tag
conchuod/build_rv64_nommu_virt_defconfig success Build OK

Commit Message

Ben Dooks March 7, 2023, 8:58 p.m. UTC
If the system uses both ZICBOM and SVPBMT then currently SVPBMT will be
used for DMA allocated memory even though ZICBOM gives us the cache ops
to use cached memory and clean/flush them as needed by the DMA code.

Fix this by adding pgprot_dmacoherent() which is used by the allocator
code to map the dma memory, thus allowing the return of suitably mapped
memory for any use of dma_alloc_attrs() code. This s uses the added
riscv_page_dmacoherent() which will work out the correct page flags to
return using ALT_SVPBMT_ZICBOM() to runtime patch the right result.

Note, we can't just disable SVPBMT as it will be neede for things like
ioremap() which don't have assoicated cache management operations.

Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
---
 arch/riscv/include/asm/errata_list.h | 16 ++++++++++++++++
 arch/riscv/include/asm/pgtable-64.h  | 10 ++++++++++
 2 files changed, 26 insertions(+)

Comments

Ben Dooks March 8, 2023, 9:35 a.m. UTC | #1
On 07/03/2023 20:58, Ben Dooks wrote:
> If the system uses both ZICBOM and SVPBMT then currently SVPBMT will be
> used for DMA allocated memory even though ZICBOM gives us the cache ops
> to use cached memory and clean/flush them as needed by the DMA code.
> 
> Fix this by adding pgprot_dmacoherent() which is used by the allocator
> code to map the dma memory, thus allowing the return of suitably mapped
> memory for any use of dma_alloc_attrs() code. This s uses the added
> riscv_page_dmacoherent() which will work out the correct page flags to
> return using ALT_SVPBMT_ZICBOM() to runtime patch the right result.
> 
> Note, we can't just disable SVPBMT as it will be neede for things like
> ioremap() which don't have assoicated cache management operations.
> 
> Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
> ---
>   arch/riscv/include/asm/errata_list.h | 16 ++++++++++++++++
>   arch/riscv/include/asm/pgtable-64.h  | 10 ++++++++++
>   2 files changed, 26 insertions(+)
> 
> diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h
> index fb1a810f3d8c..49ed2e7984a7 100644
> --- a/arch/riscv/include/asm/errata_list.h
> +++ b/arch/riscv/include/asm/errata_list.h
> @@ -62,6 +62,22 @@ asm(ALTERNATIVE_2("li %0, 0\t\nnop",					\
>   		  "I"(ALT_SVPBMT_SHIFT),				\
>   		  "I"(ALT_THEAD_PBMT_SHIFT))
>   
> +#define ALT_SVPBMT_ZICBOM(_val, prot)					\
> +asm(ALTERNATIVE_3("li %0, 0\t\nnop",					\
> +		  "li %0, %1\t\nslli %0,%0,%3", 0,			\
> +			RISCV_ISA_EXT_SVPBMT, CONFIG_RISCV_ISA_SVPBMT,	\
> +		  "li %0, 0\t\nnop", 0,					\
> +			RISCV_ISA_EXT_ZICBOM, CONFIG_RISCV_ISA_ZICBOM,	\

so, I tink this needs to be selected on CONFIG_RISCV_DMA_NONCOHERENT
as just having ZICBOM in the ISA isn't enough to actually use it, you'll
need the dma-noncoherent.o being built to do the cache management.

> +		  "li %0, %2\t\nslli %0,%0,%4", THEAD_VENDOR_ID,	\
> +			ERRATA_THEAD_PBMT, CONFIG_ERRATA_THEAD_PBMT)	\
> +		: "=r"(_val)						\
> +		: "I"(prot##_SVPBMT >> ALT_SVPBMT_SHIFT),		\
> +		  "I"(prot##_THEAD >> ALT_THEAD_PBMT_SHIFT),		\
> +		  "I"(ALT_SVPBMT_SHIFT),				\
> +		  "I"(ALT_THEAD_PBMT_SHIFT))
> +
> +
> +
>   #ifdef CONFIG_ERRATA_THEAD_PBMT
>   /*
>    * IO/NOCACHE memory types are handled together with svpbmt,
> diff --git a/arch/riscv/include/asm/pgtable-64.h b/arch/riscv/include/asm/pgtable-64.h
> index 42a042c0e13e..e0d2e5fda5a4 100644
> --- a/arch/riscv/include/asm/pgtable-64.h
> +++ b/arch/riscv/include/asm/pgtable-64.h
> @@ -126,10 +126,20 @@ static inline u64 riscv_page_io(void)
>   	return val;
>   }
>   
> +static inline u64 riscv_page_dmacoherent(void)
> +{
> +	u64 val;
> +
> +	ALT_SVPBMT_ZICBOM(val, _PAGE_IO);
> +	return val;
> +}
> +
>   #define _PAGE_NOCACHE		riscv_page_nocache()
>   #define _PAGE_IO		riscv_page_io()
>   #define _PAGE_MTMASK		riscv_page_mtmask()
>   
> +#define pgprot_dmacoherent(__prot) __pgprot(pgprot_val(__prot) | riscv_page_dmacoherent())
> +
>   /* Set of bits to preserve across pte_modify() */
>   #define _PAGE_CHG_MASK  (~(unsigned long)(_PAGE_PRESENT | _PAGE_READ |	\
>   					  _PAGE_WRITE | _PAGE_EXEC |	\
Conor Dooley March 8, 2023, 10:13 a.m. UTC | #2
On Wed, Mar 08, 2023 at 09:35:14AM +0000, Ben Dooks wrote:
> On 07/03/2023 20:58, Ben Dooks wrote:
> > If the system uses both ZICBOM and SVPBMT then currently SVPBMT will be
> > used for DMA allocated memory even though ZICBOM gives us the cache ops
> > to use cached memory and clean/flush them as needed by the DMA code.
> > 
> > Fix this by adding pgprot_dmacoherent() which is used by the allocator
> > code to map the dma memory, thus allowing the return of suitably mapped
> > memory for any use of dma_alloc_attrs() code. This s uses the added
> > riscv_page_dmacoherent() which will work out the correct page flags to
> > return using ALT_SVPBMT_ZICBOM() to runtime patch the right result.
> > 
> > Note, we can't just disable SVPBMT as it will be neede for things like
> > ioremap() which don't have assoicated cache management operations.
> > 
> > Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
> > ---
> >   arch/riscv/include/asm/errata_list.h | 16 ++++++++++++++++
> >   arch/riscv/include/asm/pgtable-64.h  | 10 ++++++++++
> >   2 files changed, 26 insertions(+)
> > 
> > diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h
> > index fb1a810f3d8c..49ed2e7984a7 100644
> > --- a/arch/riscv/include/asm/errata_list.h
> > +++ b/arch/riscv/include/asm/errata_list.h
> > @@ -62,6 +62,22 @@ asm(ALTERNATIVE_2("li %0, 0\t\nnop",					\
> >   		  "I"(ALT_SVPBMT_SHIFT),				\
> >   		  "I"(ALT_THEAD_PBMT_SHIFT))
> > +#define ALT_SVPBMT_ZICBOM(_val, prot)					\
> > +asm(ALTERNATIVE_3("li %0, 0\t\nnop",					\
> > +		  "li %0, %1\t\nslli %0,%0,%3", 0,			\
> > +			RISCV_ISA_EXT_SVPBMT, CONFIG_RISCV_ISA_SVPBMT,	\
> > +		  "li %0, 0\t\nnop", 0,					\
> > +			RISCV_ISA_EXT_ZICBOM, CONFIG_RISCV_ISA_ZICBOM,	\
> 
> so, I tink this needs to be selected on CONFIG_RISCV_DMA_NONCOHERENT
> as just having ZICBOM in the ISA isn't enough to actually use it, you'll
> need the dma-noncoherent.o being built to do the cache management.

I think we are okay here w/ ZICBOM, as it selects RISCV_DMA_NONCOHERENT:
config RISCV_ISA_ZICBOM
	bool "Zicbom extension support for non-coherent DMA operation"
	depends on !XIP_KERNEL && MMU
	default y
	select RISCV_ALTERNATIVE
	select RISCV_DMA_NONCOHERENT

In fact, I think that RISCV_DMA_NONCOHERENT would not be correct here,
as the THEAD CMO erratum selects RISCV_DMA_NONCOHERENT, so its presence
doesn't mean that the kernel supports Zicbom.

> > +		  "li %0, %2\t\nslli %0,%0,%4", THEAD_VENDOR_ID,	\
> > +			ERRATA_THEAD_PBMT, CONFIG_ERRATA_THEAD_PBMT)	\
> > +		: "=r"(_val)						\
> > +		: "I"(prot##_SVPBMT >> ALT_SVPBMT_SHIFT),		\
> > +		  "I"(prot##_THEAD >> ALT_THEAD_PBMT_SHIFT),		\
> > +		  "I"(ALT_SVPBMT_SHIFT),				\
> > +		  "I"(ALT_THEAD_PBMT_SHIFT))
> > +
> > +
> > +
> >   #ifdef CONFIG_ERRATA_THEAD_PBMT
> >   /*
> >    * IO/NOCACHE memory types are handled together with svpbmt,
> > diff --git a/arch/riscv/include/asm/pgtable-64.h b/arch/riscv/include/asm/pgtable-64.h
> > index 42a042c0e13e..e0d2e5fda5a4 100644
> > --- a/arch/riscv/include/asm/pgtable-64.h
> > +++ b/arch/riscv/include/asm/pgtable-64.h
> > @@ -126,10 +126,20 @@ static inline u64 riscv_page_io(void)
> >   	return val;
> >   }
> > +static inline u64 riscv_page_dmacoherent(void)
> > +{
> > +	u64 val;
> > +
> > +	ALT_SVPBMT_ZICBOM(val, _PAGE_IO);
> > +	return val;
> > +}
> > +
> >   #define _PAGE_NOCACHE		riscv_page_nocache()
> >   #define _PAGE_IO		riscv_page_io()
> >   #define _PAGE_MTMASK		riscv_page_mtmask()
> > +#define pgprot_dmacoherent(__prot) __pgprot(pgprot_val(__prot) | riscv_page_dmacoherent())
> > +
> >   /* Set of bits to preserve across pte_modify() */
> >   #define _PAGE_CHG_MASK  (~(unsigned long)(_PAGE_PRESENT | _PAGE_READ |	\
> >   					  _PAGE_WRITE | _PAGE_EXEC |	\
> 
> -- 
> Ben Dooks				http://www.codethink.co.uk/
> Senior Engineer				Codethink - Providing Genius
> 
> https://www.codethink.co.uk/privacy.html
> 
> 
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv
Heiko Stuebner March 8, 2023, 1:19 p.m. UTC | #3
Am Mittwoch, 8. März 2023, 10:35:14 CET schrieb Ben Dooks:
> On 07/03/2023 20:58, Ben Dooks wrote:
> > If the system uses both ZICBOM and SVPBMT then currently SVPBMT will be
> > used for DMA allocated memory even though ZICBOM gives us the cache ops
> > to use cached memory and clean/flush them as needed by the DMA code.
> > 
> > Fix this by adding pgprot_dmacoherent() which is used by the allocator
> > code to map the dma memory, thus allowing the return of suitably mapped
> > memory for any use of dma_alloc_attrs() code. This s uses the added
> > riscv_page_dmacoherent() which will work out the correct page flags to
> > return using ALT_SVPBMT_ZICBOM() to runtime patch the right result.
> > 
> > Note, we can't just disable SVPBMT as it will be neede for things like
> > ioremap() which don't have assoicated cache management operations.
> > 
> > Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
> > ---
> >   arch/riscv/include/asm/errata_list.h | 16 ++++++++++++++++
> >   arch/riscv/include/asm/pgtable-64.h  | 10 ++++++++++
> >   2 files changed, 26 insertions(+)
> > 
> > diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h
> > index fb1a810f3d8c..49ed2e7984a7 100644
> > --- a/arch/riscv/include/asm/errata_list.h
> > +++ b/arch/riscv/include/asm/errata_list.h
> > @@ -62,6 +62,22 @@ asm(ALTERNATIVE_2("li %0, 0\t\nnop",					\
> >   		  "I"(ALT_SVPBMT_SHIFT),				\
> >   		  "I"(ALT_THEAD_PBMT_SHIFT))
> >   
> > +#define ALT_SVPBMT_ZICBOM(_val, prot)					\
> > +asm(ALTERNATIVE_3("li %0, 0\t\nnop",					\
> > +		  "li %0, %1\t\nslli %0,%0,%3", 0,			\
> > +			RISCV_ISA_EXT_SVPBMT, CONFIG_RISCV_ISA_SVPBMT,	\
> > +		  "li %0, 0\t\nnop", 0,					\
> > +			RISCV_ISA_EXT_ZICBOM, CONFIG_RISCV_ISA_ZICBOM,	\
> 
> so, I tink this needs to be selected on CONFIG_RISCV_DMA_NONCOHERENT
> as just having ZICBOM in the ISA isn't enough to actually use it, you'll
> need the dma-noncoherent.o being built to do the cache management.

CONFIG_RISCV_ISA_ZICBOM does a
	select RISCV_DMA_NONCOHERENT
same as CONFIG_ERRATA_THEAD_CMO

So dma-noncoherent gets build if you enable at least one of them.
What am I missing?


> > +		  "li %0, %2\t\nslli %0,%0,%4", THEAD_VENDOR_ID,	\
> > +			ERRATA_THEAD_PBMT, CONFIG_ERRATA_THEAD_PBMT)	\
> > +		: "=r"(_val)						\
> > +		: "I"(prot##_SVPBMT >> ALT_SVPBMT_SHIFT),		\
> > +		  "I"(prot##_THEAD >> ALT_THEAD_PBMT_SHIFT),		\
> > +		  "I"(ALT_SVPBMT_SHIFT),				\
> > +		  "I"(ALT_THEAD_PBMT_SHIFT))
> > +
> > +
> > +
> >   #ifdef CONFIG_ERRATA_THEAD_PBMT
> >   /*
> >    * IO/NOCACHE memory types are handled together with svpbmt,
> > diff --git a/arch/riscv/include/asm/pgtable-64.h b/arch/riscv/include/asm/pgtable-64.h
> > index 42a042c0e13e..e0d2e5fda5a4 100644
> > --- a/arch/riscv/include/asm/pgtable-64.h
> > +++ b/arch/riscv/include/asm/pgtable-64.h
> > @@ -126,10 +126,20 @@ static inline u64 riscv_page_io(void)
> >   	return val;
> >   }
> >   
> > +static inline u64 riscv_page_dmacoherent(void)
> > +{
> > +	u64 val;
> > +
> > +	ALT_SVPBMT_ZICBOM(val, _PAGE_IO);
> > +	return val;
> > +}
> > +
> >   #define _PAGE_NOCACHE		riscv_page_nocache()
> >   #define _PAGE_IO		riscv_page_io()
> >   #define _PAGE_MTMASK		riscv_page_mtmask()
> >   
> > +#define pgprot_dmacoherent(__prot) __pgprot(pgprot_val(__prot) | riscv_page_dmacoherent())
> > +
> >   /* Set of bits to preserve across pte_modify() */
> >   #define _PAGE_CHG_MASK  (~(unsigned long)(_PAGE_PRESENT | _PAGE_READ |	\
> >   					  _PAGE_WRITE | _PAGE_EXEC |	\
> 
>
Ben Dooks March 8, 2023, 2:48 p.m. UTC | #4
On 08/03/2023 13:19, heiko@sntech.de wrote:
> Am Mittwoch, 8. März 2023, 10:35:14 CET schrieb Ben Dooks:
>> On 07/03/2023 20:58, Ben Dooks wrote:
>>> If the system uses both ZICBOM and SVPBMT then currently SVPBMT will be
>>> used for DMA allocated memory even though ZICBOM gives us the cache ops
>>> to use cached memory and clean/flush them as needed by the DMA code.
>>>
>>> Fix this by adding pgprot_dmacoherent() which is used by the allocator
>>> code to map the dma memory, thus allowing the return of suitably mapped
>>> memory for any use of dma_alloc_attrs() code. This s uses the added
>>> riscv_page_dmacoherent() which will work out the correct page flags to
>>> return using ALT_SVPBMT_ZICBOM() to runtime patch the right result.
>>>
>>> Note, we can't just disable SVPBMT as it will be neede for things like
>>> ioremap() which don't have assoicated cache management operations.
>>>
>>> Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
>>> ---
>>>    arch/riscv/include/asm/errata_list.h | 16 ++++++++++++++++
>>>    arch/riscv/include/asm/pgtable-64.h  | 10 ++++++++++
>>>    2 files changed, 26 insertions(+)
>>>
>>> diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h
>>> index fb1a810f3d8c..49ed2e7984a7 100644
>>> --- a/arch/riscv/include/asm/errata_list.h
>>> +++ b/arch/riscv/include/asm/errata_list.h
>>> @@ -62,6 +62,22 @@ asm(ALTERNATIVE_2("li %0, 0\t\nnop",					\
>>>    		  "I"(ALT_SVPBMT_SHIFT),				\
>>>    		  "I"(ALT_THEAD_PBMT_SHIFT))
>>>    
>>> +#define ALT_SVPBMT_ZICBOM(_val, prot)					\
>>> +asm(ALTERNATIVE_3("li %0, 0\t\nnop",					\
>>> +		  "li %0, %1\t\nslli %0,%0,%3", 0,			\
>>> +			RISCV_ISA_EXT_SVPBMT, CONFIG_RISCV_ISA_SVPBMT,	\
>>> +		  "li %0, 0\t\nnop", 0,					\
>>> +			RISCV_ISA_EXT_ZICBOM, CONFIG_RISCV_ISA_ZICBOM,	\
>>
>> so, I tink this needs to be selected on CONFIG_RISCV_DMA_NONCOHERENT
>> as just having ZICBOM in the ISA isn't enough to actually use it, you'll
>> need the dma-noncoherent.o being built to do the cache management.
> 
> CONFIG_RISCV_ISA_ZICBOM does a
> 	select RISCV_DMA_NONCOHERENT
> same as CONFIG_ERRATA_THEAD_CMO
> 
> So dma-noncoherent gets build if you enable at least one of them.
> What am I missing?

Ah, I think (and Connor also pointed out) that currently the config
is selceted from either user of the dma-noncoherent.c code. I think
thereore we can probably keep this as is.
Ben Dooks March 24, 2023, 5:30 p.m. UTC | #5
On 08/03/2023 14:48, Ben Dooks wrote:
> On 08/03/2023 13:19, heiko@sntech.de wrote:
>> Am Mittwoch, 8. März 2023, 10:35:14 CET schrieb Ben Dooks:
>>> On 07/03/2023 20:58, Ben Dooks wrote:
>>>> If the system uses both ZICBOM and SVPBMT then currently SVPBMT will be
>>>> used for DMA allocated memory even though ZICBOM gives us the cache ops
>>>> to use cached memory and clean/flush them as needed by the DMA code.
>>>>
>>>> Fix this by adding pgprot_dmacoherent() which is used by the allocator
>>>> code to map the dma memory, thus allowing the return of suitably mapped
>>>> memory for any use of dma_alloc_attrs() code. This s uses the added
>>>> riscv_page_dmacoherent() which will work out the correct page flags to
>>>> return using ALT_SVPBMT_ZICBOM() to runtime patch the right result.
>>>>
>>>> Note, we can't just disable SVPBMT as it will be neede for things like
>>>> ioremap() which don't have assoicated cache management operations.
>>>>
>>>> Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
>>>> ---
>>>>    arch/riscv/include/asm/errata_list.h | 16 ++++++++++++++++
>>>>    arch/riscv/include/asm/pgtable-64.h  | 10 ++++++++++
>>>>    2 files changed, 26 insertions(+)
>>>>
>>>> diff --git a/arch/riscv/include/asm/errata_list.h 
>>>> b/arch/riscv/include/asm/errata_list.h
>>>> index fb1a810f3d8c..49ed2e7984a7 100644
>>>> --- a/arch/riscv/include/asm/errata_list.h
>>>> +++ b/arch/riscv/include/asm/errata_list.h
>>>> @@ -62,6 +62,22 @@ asm(ALTERNATIVE_2("li %0, 
>>>> 0\t\nnop",                    \
>>>>              "I"(ALT_SVPBMT_SHIFT),                \
>>>>              "I"(ALT_THEAD_PBMT_SHIFT))
>>>> +#define ALT_SVPBMT_ZICBOM(_val, prot)                    \
>>>> +asm(ALTERNATIVE_3("li %0, 0\t\nnop",                    \
>>>> +          "li %0, %1\t\nslli %0,%0,%3", 0,            \
>>>> +            RISCV_ISA_EXT_SVPBMT, CONFIG_RISCV_ISA_SVPBMT,    \
>>>> +          "li %0, 0\t\nnop", 0,                    \
>>>> +            RISCV_ISA_EXT_ZICBOM, CONFIG_RISCV_ISA_ZICBOM,    \
>>>
>>> so, I tink this needs to be selected on CONFIG_RISCV_DMA_NONCOHERENT
>>> as just having ZICBOM in the ISA isn't enough to actually use it, you'll
>>> need the dma-noncoherent.o being built to do the cache management.
>>
>> CONFIG_RISCV_ISA_ZICBOM does a
>>     select RISCV_DMA_NONCOHERENT
>> same as CONFIG_ERRATA_THEAD_CMO
>>
>> So dma-noncoherent gets build if you enable at least one of them.
>> What am I missing?
> 
> Ah, I think (and Connor also pointed out) that currently the config
> is selceted from either user of the dma-noncoherent.c code. I think
> thereore we can probably keep this as is

After a discussion with Arnd it looks like I was using the DMA api
wrong and was after dma_alloc_noncoherent or similar.

These patches can be dropped
diff mbox series

Patch

diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h
index fb1a810f3d8c..49ed2e7984a7 100644
--- a/arch/riscv/include/asm/errata_list.h
+++ b/arch/riscv/include/asm/errata_list.h
@@ -62,6 +62,22 @@  asm(ALTERNATIVE_2("li %0, 0\t\nnop",					\
 		  "I"(ALT_SVPBMT_SHIFT),				\
 		  "I"(ALT_THEAD_PBMT_SHIFT))
 
+#define ALT_SVPBMT_ZICBOM(_val, prot)					\
+asm(ALTERNATIVE_3("li %0, 0\t\nnop",					\
+		  "li %0, %1\t\nslli %0,%0,%3", 0,			\
+			RISCV_ISA_EXT_SVPBMT, CONFIG_RISCV_ISA_SVPBMT,	\
+		  "li %0, 0\t\nnop", 0,					\
+			RISCV_ISA_EXT_ZICBOM, CONFIG_RISCV_ISA_ZICBOM,	\
+		  "li %0, %2\t\nslli %0,%0,%4", THEAD_VENDOR_ID,	\
+			ERRATA_THEAD_PBMT, CONFIG_ERRATA_THEAD_PBMT)	\
+		: "=r"(_val)						\
+		: "I"(prot##_SVPBMT >> ALT_SVPBMT_SHIFT),		\
+		  "I"(prot##_THEAD >> ALT_THEAD_PBMT_SHIFT),		\
+		  "I"(ALT_SVPBMT_SHIFT),				\
+		  "I"(ALT_THEAD_PBMT_SHIFT))
+
+
+
 #ifdef CONFIG_ERRATA_THEAD_PBMT
 /*
  * IO/NOCACHE memory types are handled together with svpbmt,
diff --git a/arch/riscv/include/asm/pgtable-64.h b/arch/riscv/include/asm/pgtable-64.h
index 42a042c0e13e..e0d2e5fda5a4 100644
--- a/arch/riscv/include/asm/pgtable-64.h
+++ b/arch/riscv/include/asm/pgtable-64.h
@@ -126,10 +126,20 @@  static inline u64 riscv_page_io(void)
 	return val;
 }
 
+static inline u64 riscv_page_dmacoherent(void)
+{
+	u64 val;
+
+	ALT_SVPBMT_ZICBOM(val, _PAGE_IO);
+	return val;
+}
+
 #define _PAGE_NOCACHE		riscv_page_nocache()
 #define _PAGE_IO		riscv_page_io()
 #define _PAGE_MTMASK		riscv_page_mtmask()
 
+#define pgprot_dmacoherent(__prot) __pgprot(pgprot_val(__prot) | riscv_page_dmacoherent())
+
 /* Set of bits to preserve across pte_modify() */
 #define _PAGE_CHG_MASK  (~(unsigned long)(_PAGE_PRESENT | _PAGE_READ |	\
 					  _PAGE_WRITE | _PAGE_EXEC |	\