Currently, clear_page() uses DC ZVA instruction unconditionally. But it
should make sure that DCZID_EL0.DZP, which indicates whether or not use
of DC ZVA instruction is prohibited, is zero when using the instruction.
Use stp as memset does instead when DCZID_EL0.DZP == 1.
Signed-off-by: Reiji Watanabe <redacted>
---
arch/arm64/lib/clear_page.S | 11 +++++++++++
1 file changed, 11 insertions(+)
On Mon, Oct 25, 2021 at 08:48:44PM -0700, Reiji Watanabe wrote:
Currently, clear_page() uses DC ZVA instruction unconditionally. But it
should make sure that DCZID_EL0.DZP, which indicates whether or not use
of DC ZVA instruction is prohibited, is zero when using the instruction.
Use stp as memset does instead when DCZID_EL0.DZP == 1.
For correctness, this is fine, but have you come across a system that
has DZP == 1 (or hypervisor setting HCR_EL2.TDZ)?
--
Catalin
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
On Tue, Oct 26, 2021 at 2:06 AM Catalin Marinas [off-list ref] wrote:
On Mon, Oct 25, 2021 at 08:48:44PM -0700, Reiji Watanabe wrote:
quoted
Currently, clear_page() uses DC ZVA instruction unconditionally. But it
should make sure that DCZID_EL0.DZP, which indicates whether or not use
of DC ZVA instruction is prohibited, is zero when using the instruction.
Use stp as memset does instead when DCZID_EL0.DZP == 1.
For correctness, this is fine, but have you come across a system that
has DZP == 1 (or hypervisor setting HCR_EL2.TDZ)?
We are thinking of setting HCR_EL2.TDZ considering live migration
support between two systems with different DCZID_EL0.BS.
Thanks,
Reiji
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Robin Murphy <robin.murphy@arm.com> Date: 2021-10-26 11:23:47
On 2021-10-26 04:48, Reiji Watanabe wrote:
quoted hunk
Currently, clear_page() uses DC ZVA instruction unconditionally. But it
should make sure that DCZID_EL0.DZP, which indicates whether or not use
of DC ZVA instruction is prohibited, is zero when using the instruction.
Use stp as memset does instead when DCZID_EL0.DZP == 1.
Signed-off-by: Reiji Watanabe <redacted>
---
arch/arm64/lib/clear_page.S | 11 +++++++++++
1 file changed, 11 insertions(+)
Out of curiosity, what's this for? It's not like we need to worry about
PAGE_SIZE or page addresses being misaligned. I don't really see why
we'd need a different condition from the DC ZVA loop.
Robin.
From: Mark Rutland <mark.rutland@arm.com> Date: 2021-10-26 12:25:06
On Tue, Oct 26, 2021 at 12:22:20PM +0100, Robin Murphy wrote:
On 2021-10-26 04:48, Reiji Watanabe wrote:
quoted
Currently, clear_page() uses DC ZVA instruction unconditionally. But it
should make sure that DCZID_EL0.DZP, which indicates whether or not use
of DC ZVA instruction is prohibited, is zero when using the instruction.
Use stp as memset does instead when DCZID_EL0.DZP == 1.
Signed-off-by: Reiji Watanabe <redacted>
---
arch/arm64/lib/clear_page.S | 11 +++++++++++
1 file changed, 11 insertions(+)
@@ -16,6 +16,7 @@*/SYM_FUNC_START_PI(clear_page)mrsx1,dczid_el0+tbnzx1,#4, 2f /* Branch if DC GVA is prohibited */
DCZID_EL0.DZP (AKA DCZID_EL0[4]) says whether all of DC {ZVA,GVA,GZVA}
are prohibited. This loop uses DZ ZVA, not GC GVA, so it'd be nice to
s/GVA/ZVA/ here.
Howver, `DC GVA` and `DC GZVA` are both used in mte_set_mem_tag_range(),
which'll need a similar update...
Out of curiosity, what's this for? It's not like we need to worry about
PAGE_SIZE or page addresses being misaligned. I don't really see why we'd
need a different condition from the DC ZVA loop.
I believe this was copied from arch/arm64/lib/memset.S, in the
`.Lnot_short` case, where we have:
| .Lnot_short:
| sub dst, dst, #16/* Pre-bias. */
| sub count, count, #64
| 1:
| stp A_l, A_l, [dst, #16]
| stp A_l, A_l, [dst, #32]
| stp A_l, A_l, [dst, #48]
| stp A_l, A_l, [dst, #64]!
| subs count, count, #64
| b.ge 1b
On Tue, Oct 26, 2021 at 5:23 AM Mark Rutland [off-list ref] wrote:
On Tue, Oct 26, 2021 at 12:22:20PM +0100, Robin Murphy wrote:
quoted
On 2021-10-26 04:48, Reiji Watanabe wrote:
quoted
Currently, clear_page() uses DC ZVA instruction unconditionally. But it
should make sure that DCZID_EL0.DZP, which indicates whether or not use
of DC ZVA instruction is prohibited, is zero when using the instruction.
Use stp as memset does instead when DCZID_EL0.DZP == 1.
Signed-off-by: Reiji Watanabe <redacted>
---
arch/arm64/lib/clear_page.S | 11 +++++++++++
1 file changed, 11 insertions(+)
@@ -16,6 +16,7 @@*/SYM_FUNC_START_PI(clear_page)mrsx1,dczid_el0+tbnzx1,#4, 2f /* Branch if DC GVA is prohibited */
DCZID_EL0.DZP (AKA DCZID_EL0[4]) says whether all of DC {ZVA,GVA,GZVA}
are prohibited. This loop uses DZ ZVA, not GC GVA, so it'd be nice to
s/GVA/ZVA/ here.
Thank you for catching it ! I will fix that.
Howver, `DC GVA` and `DC GZVA` are both used in mte_set_mem_tag_range(),
which'll need a similar update...
Yes, I'm aware of that and mte_zero_clear_page_tags() needs to get
updated as well. But, Since I'm not familiar with MTE (and I don't
have any plans to use MTE yet), I didn't work on them (I'm not sure
how I can test them).
I might try to fix them separately later as well when I have time
(not so soon most likely though).
Out of curiosity, what's this for? It's not like we need to worry about
PAGE_SIZE or page addresses being misaligned. I don't really see why we'd
need a different condition from the DC ZVA loop.
I believe this was copied from arch/arm64/lib/memset.S, in the
`.Lnot_short` case, where we have:
Yes, I used the same code as memset. I couldn't come up with any
other implementation that could get same performance with fewer
number of instructions in the loop than that.
FWIW, I'd also prefer consistency with the existing loop, i.e.
2: stp xzr, xzr, [x0, #0]
stp xzr, xzr, [x0, #16]
stp xzr, xzr, [x0, #32]
stp xzr, xzr, [x0, #48]
add x0, x0, #64
tst x0, #(PAGE_SIZE - 1)
b.ne 2b
ret
Thank you for the suggestion. Yes, I agree that it would be better
in terms of consistency with the existing loop.
I will fix this as you suggested in the v2 patch.
Thanks,
Reiji
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Mark Rutland <mark.rutland@arm.com> Date: 2021-10-27 11:11:20
On Tue, Oct 26, 2021 at 11:44:51PM -0700, Reiji Watanabe wrote:
On Tue, Oct 26, 2021 at 5:23 AM Mark Rutland [off-list ref] wrote:
quoted
On Tue, Oct 26, 2021 at 12:22:20PM +0100, Robin Murphy wrote:
quoted
On 2021-10-26 04:48, Reiji Watanabe wrote:
quoted
Currently, clear_page() uses DC ZVA instruction unconditionally. But it
should make sure that DCZID_EL0.DZP, which indicates whether or not use
of DC ZVA instruction is prohibited, is zero when using the instruction.
Use stp as memset does instead when DCZID_EL0.DZP == 1.
Signed-off-by: Reiji Watanabe <redacted>
---
arch/arm64/lib/clear_page.S | 11 +++++++++++
1 file changed, 11 insertions(+)
@@ -16,6 +16,7 @@*/SYM_FUNC_START_PI(clear_page)mrsx1,dczid_el0+tbnzx1,#4, 2f /* Branch if DC GVA is prohibited */
DCZID_EL0.DZP (AKA DCZID_EL0[4]) says whether all of DC {ZVA,GVA,GZVA}
are prohibited. This loop uses DZ ZVA, not GC GVA, so it'd be nice to
s/GVA/ZVA/ here.
Thank you for catching it ! I will fix that.
quoted
Howver, `DC GVA` and `DC GZVA` are both used in mte_set_mem_tag_range(),
which'll need a similar update...
Yes, I'm aware of that and mte_zero_clear_page_tags() needs to get
updated as well. But, Since I'm not familiar with MTE (and I don't
have any plans to use MTE yet), I didn't work on them (I'm not sure
how I can test them).
I might try to fix them separately later as well when I have time
(not so soon most likely though).
My view is that we should either:
* Document that we require DCZID_EL0.DZP==0, as is implicitly the case
today.
* Fix *all* usage of DC {ZVA,GVZ,GZVA} to work with DCZID_EL0.DZP==1.
... otherwise we're just hiding the problem rather than fixing it.
QEMU TCG mode has MTE support, so it should be possible to test using
that in a configuration such as:
-machine virt,virtualization=on,mte=on -cpu max
... then you can hack the EL2 stub code in head.S to initialize
HCR_EL2.TDZ=1 before dropping to EL1 (and reporting that the kernel
started at EL1).
Thanks,
Mark.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
On Wed, Oct 27, 2021 at 4:09 AM Mark Rutland [off-list ref] wrote:
On Tue, Oct 26, 2021 at 11:44:51PM -0700, Reiji Watanabe wrote:
quoted
On Tue, Oct 26, 2021 at 5:23 AM Mark Rutland [off-list ref] wrote:
quoted
On Tue, Oct 26, 2021 at 12:22:20PM +0100, Robin Murphy wrote:
quoted
On 2021-10-26 04:48, Reiji Watanabe wrote:
quoted
Currently, clear_page() uses DC ZVA instruction unconditionally. But it
should make sure that DCZID_EL0.DZP, which indicates whether or not use
of DC ZVA instruction is prohibited, is zero when using the instruction.
Use stp as memset does instead when DCZID_EL0.DZP == 1.
Signed-off-by: Reiji Watanabe <redacted>
---
arch/arm64/lib/clear_page.S | 11 +++++++++++
1 file changed, 11 insertions(+)
@@ -16,6 +16,7 @@*/SYM_FUNC_START_PI(clear_page)mrsx1,dczid_el0+tbnzx1,#4, 2f /* Branch if DC GVA is prohibited */
DCZID_EL0.DZP (AKA DCZID_EL0[4]) says whether all of DC {ZVA,GVA,GZVA}
are prohibited. This loop uses DZ ZVA, not GC GVA, so it'd be nice to
s/GVA/ZVA/ here.
Thank you for catching it ! I will fix that.
quoted
Howver, `DC GVA` and `DC GZVA` are both used in mte_set_mem_tag_range(),
which'll need a similar update...
Yes, I'm aware of that and mte_zero_clear_page_tags() needs to get
updated as well. But, Since I'm not familiar with MTE (and I don't
have any plans to use MTE yet), I didn't work on them (I'm not sure
how I can test them).
I might try to fix them separately later as well when I have time
(not so soon most likely though).
My view is that we should either:
* Document that we require DCZID_EL0.DZP==0, as is implicitly the case
today.
* Fix *all* usage of DC {ZVA,GVZ,GZVA} to work with DCZID_EL0.DZP==1.
... otherwise we're just hiding the problem rather than fixing it.
QEMU TCG mode has MTE support, so it should be possible to test using
that in a configuration such as:
-machine virt,virtualization=on,mte=on -cpu max
... then you can hack the EL2 stub code in head.S to initialize
HCR_EL2.TDZ=1 before dropping to EL1 (and reporting that the kernel
started at EL1).
Understood.
I will work on the MTE fixes and include them into the v2 patch.
Thank you so much for all the comments and information.
Regards,
Reiji
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Will Deacon <will@kernel.org> Date: 2021-10-28 07:47:35
On Wed, Oct 27, 2021 at 12:09:47PM +0100, Mark Rutland wrote:
On Tue, Oct 26, 2021 at 11:44:51PM -0700, Reiji Watanabe wrote:
quoted
On Tue, Oct 26, 2021 at 5:23 AM Mark Rutland [off-list ref] wrote:
quoted
On Tue, Oct 26, 2021 at 12:22:20PM +0100, Robin Murphy wrote:
quoted
On 2021-10-26 04:48, Reiji Watanabe wrote:
quoted
Currently, clear_page() uses DC ZVA instruction unconditionally. But it
should make sure that DCZID_EL0.DZP, which indicates whether or not use
of DC ZVA instruction is prohibited, is zero when using the instruction.
Use stp as memset does instead when DCZID_EL0.DZP == 1.
Signed-off-by: Reiji Watanabe <redacted>
---
arch/arm64/lib/clear_page.S | 11 +++++++++++
1 file changed, 11 insertions(+)
@@ -16,6 +16,7 @@*/SYM_FUNC_START_PI(clear_page)mrsx1,dczid_el0+tbnzx1,#4, 2f /* Branch if DC GVA is prohibited */
DCZID_EL0.DZP (AKA DCZID_EL0[4]) says whether all of DC {ZVA,GVA,GZVA}
are prohibited. This loop uses DZ ZVA, not GC GVA, so it'd be nice to
s/GVA/ZVA/ here.
Thank you for catching it ! I will fix that.
quoted
Howver, `DC GVA` and `DC GZVA` are both used in mte_set_mem_tag_range(),
which'll need a similar update...
Yes, I'm aware of that and mte_zero_clear_page_tags() needs to get
updated as well. But, Since I'm not familiar with MTE (and I don't
have any plans to use MTE yet), I didn't work on them (I'm not sure
how I can test them).
I might try to fix them separately later as well when I have time
(not so soon most likely though).
My view is that we should either:
* Document that we require DCZID_EL0.DZP==0, as is implicitly the case
today.
I disagree with that. There's nothing wrong in trapping this stuff, as long
as you go ahead and emulate it, which is exactly why we aren't checking it at
the moment as EL2 should be prepared to handle the trap. The Arm ARM talks
about the instructions being "prohibited" but that doesn't mean anything --
the reality is that they trap to EL2.
We could document *that* though?
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Mark Rutland <mark.rutland@arm.com> Date: 2021-10-28 09:06:37
On Thu, Oct 28, 2021 at 08:46:10AM +0100, Will Deacon wrote:
On Wed, Oct 27, 2021 at 12:09:47PM +0100, Mark Rutland wrote:
quoted
On Tue, Oct 26, 2021 at 11:44:51PM -0700, Reiji Watanabe wrote:
quoted
On Tue, Oct 26, 2021 at 5:23 AM Mark Rutland [off-list ref] wrote:
quoted
On Tue, Oct 26, 2021 at 12:22:20PM +0100, Robin Murphy wrote:
quoted
On 2021-10-26 04:48, Reiji Watanabe wrote:
quoted
Currently, clear_page() uses DC ZVA instruction unconditionally. But it
should make sure that DCZID_EL0.DZP, which indicates whether or not use
of DC ZVA instruction is prohibited, is zero when using the instruction.
Use stp as memset does instead when DCZID_EL0.DZP == 1.
Signed-off-by: Reiji Watanabe <redacted>
---
arch/arm64/lib/clear_page.S | 11 +++++++++++
1 file changed, 11 insertions(+)
@@ -16,6 +16,7 @@*/SYM_FUNC_START_PI(clear_page)mrsx1,dczid_el0+tbnzx1,#4, 2f /* Branch if DC GVA is prohibited */
DCZID_EL0.DZP (AKA DCZID_EL0[4]) says whether all of DC {ZVA,GVA,GZVA}
are prohibited. This loop uses DZ ZVA, not GC GVA, so it'd be nice to
s/GVA/ZVA/ here.
Thank you for catching it ! I will fix that.
quoted
Howver, `DC GVA` and `DC GZVA` are both used in mte_set_mem_tag_range(),
which'll need a similar update...
Yes, I'm aware of that and mte_zero_clear_page_tags() needs to get
updated as well. But, Since I'm not familiar with MTE (and I don't
have any plans to use MTE yet), I didn't work on them (I'm not sure
how I can test them).
I might try to fix them separately later as well when I have time
(not so soon most likely though).
My view is that we should either:
* Document that we require DCZID_EL0.DZP==0, as is implicitly the case
today.
I disagree with that. There's nothing wrong in trapping this stuff, as long
as you go ahead and emulate it, which is exactly why we aren't checking it at
the moment as EL2 should be prepared to handle the trap. The Arm ARM talks
about the instructions being "prohibited" but that doesn't mean anything --
the reality is that they trap to EL2.
TBH, I think trapping DC ZVA rather than forcing it to be UNDEF was an
architectural mistake.
I think the intent of the "prohibited" wording (and exposure of
DCZID_EL0.DZP to EL0 and EL1) is clearly that SW should *avoid* DC ZVA and
friends when DCZID_EL0.DZP is set (and libc and the Arm optimized
routines have *always* checked that), and performance would be abysmal
with emulated DC ZVA, so at minimum we want to avoid hitting emulation
in the common case.
We could document *that* though?
I guess; though it makes me uneasy since the architecture clearly pushes
people to read CTR_EL0.DZP, and heavily implies that there's no need to
emulate, so I don't think we have much of a leg to stand on from an
architecture PoV.
If we need to support this, my preference would be to support
DCZID_EL0.DZP==1 by avoiding the trapped instructions entirely.
I realise the problem as ever is "what does userspace do?".
Thanks,
Mark.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel