arm64: alternative:flush cache with unpatched code
PATCH 1/1 arm64: alternative:flush cache with unpatched code
In the current implementation, __apply_alternatives patches flush_icache_range and then executes it without invalidating the icache. Thus, icache can contain some of the old instructions for flush_icache_range. This can cause unpredictable behavior as during execution we can get a mix of old and new instructions for flush_icache_range.
This patch :
1. Adds a new function clean_dcache_range_nopatch for flushing kernel memory range. This function uses non hot-patched code and can be safely used to flush cache during code patching.
2. Modifies __apply_alternatives so that it uses clean_dcache_range_nopatch to flush the cache range after patching code.
--- arch/arm64/include/asm/sysreg.h | 3 +++ arch/arm64/kernel/alternative.c | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-)
arch/arm64/include/asm/sysreg.h +3 -0
@@ -617,6 +617,9 @@#define MVFR1_FPDNAN_SHIFT 4#define MVFR1_FPFTZ_SHIFT 0 +/* SYS_CTR_EL0 */ +#define SYS_CTR_ISIZE_SHIFT 0 +#define SYS_CTR_DSIZE_SHIFT 16#define ID_AA64MMFR0_TGRAN4_SHIFT 28#define ID_AA64MMFR0_TGRAN64_SHIFT 24
arch/arm64/kernel/alternative.c +36 -1
@@ -122,6 +122,41 @@ static void patch_alternative(struct alt_instr *alt, } } +/* This is used for flushing kernel memory range after +* __apply_alternatives has patched kernel code +*/ +static void clean_dcache_range_nopatch (void *start,void *end) +{ +u64 d_start, i_start, d_size, i_size, ctr_el0; + +/* use sanitised value of ctr_el0 rather than raw value from CPU */ + ctr_el0 =read_sanitised_ftr_reg (SYS_CTR_EL0 ); +/* size in bytes */ + d_size =cpuid_feature_extract_unsigned_field (ctr_el0, +SYS_CTR_DSIZE_SHIFT ); + i_size =cpuid_feature_extract_unsigned_field (ctr_el0, +SYS_CTR_ISIZE_SHIFT ); + + d_start = (u64 )start & ~(d_size -1 ); +while (d_start <= (u64 )end) { +/* Use civac instead of cvau. This is required +* due to ARM errata 826319, 827319, 824069, +* 819472 on A53 +*/ + asmvolatile ("dc civac, %0" : :"r" (d_start)); + d_start += d_size; + } +dsb (ish); + + i_start = (u64 )start & ~(i_size -1 ); +while (i_start <= (u64 )end) { + asmvolatile ("ic ivau, %0" : :"r" (i_start)); + i_start += i_size; + } +dsb (ish); +isb (); +} +static void __apply_alternatives (void *alt_region,bool use_linear_alias) {struct alt_instr *alt;
@@ -155,7 +190,7 @@ static void __apply_alternatives(void *alt_region, bool use_linear_alias)alt_cb (alt, origptr, updptr, nr_inst); -flush_icache_range ((uintptr_t )origptr, +clean_dcache_range_nopatch ((uintptr_t )origptr, (uintptr_t )(origptr + nr_inst)); } }
Signature · 1 line
2.1.4
Mark Rutland
reviewerPATCH 1/1 arm64: alternative:flush cache with unpatched code
Hi,
As a general thing, could you please add a version number to patches in future? i.e. this should be PATCHv4.
It really helps keeping track of patches, distinguishing versions, etc.
Quoted 27 lines · Rohit Khanna
In the current implementation,
__apply_alternativespatchesflush_icache_rangeand then executes it without invalidating the icache. Thus, icache can contain some of the old instructions forflush_icache_range. This can cause unpredictable behavior as during execution we can get a mix of old and new instructions forflush_icache_range.This patch :
1. Adds a new function
clean_dcache_range_nopatchfor flushing kernel memory range. This function uses non hot-patched code and can be safely used to flush cache during code patching.2. Modifies
__apply_alternativesso that it usesclean_dcache_range_nopatchto flush the cache range after patching code.Signed-off-by Rohit Khanna <[email protected]>--- arch/arm64/include/asm/sysreg.h | 3 +++ arch/arm64/kernel/alternative.c | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-)arch/arm64/include/asm/sysreg.h +0
-0
arch/arm64/include/asm/sysreg.h line 622
Quoted 6 lines
arch/arm64/include/asm/sysreg.h +3
-0@@ -617,6 +617,9 @@#define MVFR1_FPDNAN_SHIFT 4#define MVFR1_FPFTZ_SHIFT 0 +/* SYS_CTR_EL0 */ +#define SYS_CTR_ISIZE_SHIFT 0 +#define SYS_CTR_DSIZE_SHIFT 16
We already have CTR_DMINLINE_SHIFT in <asm/cache.h>
Can we please add CTR_IMINLIN_SHIFT there too?
Maybe those should be moved into sysreg.h, but that can be a separate cleanup.
Quoted 7 lines
arch/arm64/include/asm/sysreg.h +0
-0#define ID_AA64MMFR0_TGRAN4_SHIFT 28#define ID_AA64MMFR0_TGRAN64_SHIFT 24arch/arm64/kernel/alternative.c +0
-0
arch/arm64/kernel/alternative.c static void patch_alternative(struct alt_instr *alt, · line 130
Quoted 9 lines
arch/arm64/kernel/alternative.c +6
-0@@ -122,6 +122,41 @@ static void patch_alternative(struct alt_instr *alt, } } +/* This is used for flushing kernel memory range after +* __apply_alternatives has patched kernel code +*/ +static void clean_dcache_range_nopatch (void *start,void *end) +{ +u64 d_start, i_start, d_size, i_size, ctr_el0;
I don't think we need separate i_start and d_start variables. A 'start' or 'cur' variable could be used for both.
arch/arm64/kernel/alternative.c static void patch_alternative(struct alt_instr *alt, · line 138
Quoted 8 lines
arch/arm64/kernel/alternative.c +8
-0+ +/* use sanitised value of ctr_el0 rather than raw value from CPU */ + ctr_el0 =read_sanitised_ftr_reg (SYS_CTR_EL0 ); +/* size in bytes */ + d_size =cpuid_feature_extract_unsigned_field (ctr_el0, +SYS_CTR_DSIZE_SHIFT ); + i_size =cpuid_feature_extract_unsigned_field (ctr_el0, +SYS_CTR_ISIZE_SHIFT );
This isn't the size in bytes. Each is log2 the number of (4-byte) words.
i.e. the size in bytes is (xMinLine << 2).
arch/arm64/kernel/alternative.c static void patch_alternative(struct alt_instr *alt, · line 146
Quoted 8 lines
arch/arm64/kernel/alternative.c +8
-0+ + d_start = (u64 )start & ~(d_size -1 ); +while (d_start <= (u64 )end) { +/* Use civac instead of cvau. This is required +* due to ARM errata 826319, 827319, 824069, +* 819472 on A53 +*/ + asmvolatile ("dc civac, %0" : :"r" (d_start));
Either this needs a memory clobber, or we need barrier() first, to ensure that the compiler doesn't re-order this against some of the patching code, however unlikely that may be.
arch/arm64/kernel/alternative.c static void patch_alternative(struct alt_instr *alt, · line 148
Quoted 2 lines
arch/arm64/kernel/alternative.c +2
-0+ d_start += d_size; + }
The loop can be simplified to:
do {
asm ( ... );
} while (d_start += d_size, d_start < (u64)end)arch/arm64/kernel/alternative.c static void patch_alternative(struct alt_instr *alt, · line 155
Quoted 7 lines
arch/arm64/kernel/alternative.c +7
-0+dsb (ish); + + i_start = (u64 )start & ~(i_size -1 ); +while (i_start <= (u64 )end) { + asmvolatile ("ic ivau, %0" : :"r" (i_start)); + i_start += i_size; + }
Likewise here.
Thanks,
Mark.
Quoted 19 lines
arch/arm64/kernel/alternative.c +5
-1+dsb (ish); +isb (); +} +static void __apply_alternatives (void *alt_region,bool use_linear_alias) {struct alt_instr *alt;@@ -155,7 +190,7 @@ static void __apply_alternatives(void *alt_region, bool use_linear_alias)alt_cb (alt, origptr, updptr, nr_inst); -flush_icache_range ((uintptr_t )origptr, +clean_dcache_range_nopatch ((uintptr_t )origptr, (uintptr_t )(origptr + nr_inst)); } }Signature · 1 line
2.1.4
PATCH 1/1 arm64: alternative:flush cache with unpatched code
[RK] - Thanks for the comments Mark. Reply inlined.
Thanks
Rohit
________________________________________
From: Mark Rutland <[email protected]>
Sent: Friday, June 1, 2018 2:03 AM
To: Rohit Khanna
Cc: catalin.marinas at arm.com; robin.murphy at arm.com; Suzuki.Poulose at arm.com; linux-arm-kernel at lists.infradead.org; Alexander Van Brunt; Bo Yan; will.deacon at arm.com
Subject: Re: [PATCH] arm64: alternative:flush cache with unpatched code
Hi,
As a general thing, could you please add a version number to patches in future? i.e. this should be PATCHv4.
It really helps keeping track of patches, distinguishing versions, etc.
Quoted 27 lines · Rohit Khanna
In the current implementation,
__apply_alternativespatchesflush_icache_rangeand then executes it without invalidating the icache. Thus, icache can contain some of the old instructions forflush_icache_range. This can cause unpredictable behavior as during execution we can get a mix of old and new instructions forflush_icache_range.This patch :
1. Adds a new function
clean_dcache_range_nopatchfor flushing kernel memory range. This function uses non hot-patched code and can be safely used to flush cache during code patching.2. Modifies
__apply_alternativesso that it usesclean_dcache_range_nopatchto flush the cache range after patching code.Signed-off-by Rohit Khanna <[email protected]>--- arch/arm64/include/asm/sysreg.h | 3 +++ arch/arm64/kernel/alternative.c | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-)arch/arm64/include/asm/sysreg.h +0
-0
arch/arm64/include/asm/sysreg.h line 622
Quoted 6 lines
arch/arm64/include/asm/sysreg.h +3
-0@@ -617,6 +617,9 @@#define MVFR1_FPDNAN_SHIFT 4#define MVFR1_FPFTZ_SHIFT 0 +/* SYS_CTR_EL0 */ +#define SYS_CTR_ISIZE_SHIFT 0 +#define SYS_CTR_DSIZE_SHIFT 16
We already have CTR_DMINLINE_SHIFT in <asm/cache.h>
Can we please add CTR_IMINLIN_SHIFT there too?
Maybe those should be moved into sysreg.h, but that can be a separate cleanup.
[RK] - <asm/cache.h> doesnt contain CTR_DMINLINE_SHIFT.
Quoted 7 lines
arch/arm64/include/asm/sysreg.h +0
-0#define ID_AA64MMFR0_TGRAN4_SHIFT 28#define ID_AA64MMFR0_TGRAN64_SHIFT 24arch/arm64/kernel/alternative.c +0
-0
arch/arm64/kernel/alternative.c static void patch_alternative(struct alt_instr *alt, · line 130
Quoted 9 lines
arch/arm64/kernel/alternative.c +6
-0@@ -122,6 +122,41 @@ static void patch_alternative(struct alt_instr *alt, } } +/* This is used for flushing kernel memory range after +* __apply_alternatives has patched kernel code +*/ +static void clean_dcache_range_nopatch (void *start,void *end) +{ +u64 d_start, i_start, d_size, i_size, ctr_el0;
I don't think we need separate i_start and d_start variables. A 'start' or 'cur' variable could be used for both.
[RK] - ok.
arch/arm64/kernel/alternative.c static void patch_alternative(struct alt_instr *alt, · line 138
Quoted 8 lines
arch/arm64/kernel/alternative.c +8
-0+ +/* use sanitised value of ctr_el0 rather than raw value from CPU */ + ctr_el0 =read_sanitised_ftr_reg (SYS_CTR_EL0 ); +/* size in bytes */ + d_size =cpuid_feature_extract_unsigned_field (ctr_el0, +SYS_CTR_DSIZE_SHIFT ); + i_size =cpuid_feature_extract_unsigned_field (ctr_el0, +SYS_CTR_ISIZE_SHIFT );
This isn't the size in bytes. Each is log2 the number of (4-byte) words.
i.e. the size in bytes is (xMinLine << 2).
[RK] - This doesnt seem right. For eg if IMinLine = 4 or 0b100
then with above formula ICacheSize in Bytes = 4 << 2 = 16 The correct formula should be (4 << xMinLine).
So in case IMinLine = 4 or 0b100, ICacheSizeBytes = 4 << 4 = 64B
arch/arm64/kernel/alternative.c static void patch_alternative(struct alt_instr *alt, · line 146
Quoted 8 lines
arch/arm64/kernel/alternative.c +8
-0+ + d_start = (u64 )start & ~(d_size -1 ); +while (d_start <= (u64 )end) { +/* Use civac instead of cvau. This is required +* due to ARM errata 826319, 827319, 824069, +* 819472 on A53 +*/ + asmvolatile ("dc civac, %0" : :"r" (d_start));
Either this needs a memory clobber, or we need barrier() first, to ensure that the compiler doesn't re-order this against some of the patching code, however unlikely that may be.
[RK] - So add barrier() before calling clean_dcache_range_nopatch() ?
arch/arm64/kernel/alternative.c static void patch_alternative(struct alt_instr *alt, · line 148
Quoted 2 lines
arch/arm64/kernel/alternative.c +2
-0+ d_start += d_size; + }
The loop can be simplified to:
do {
asm ( ... );
} while (d_start += d_size, d_start < (u64)end)[RK] - ok
arch/arm64/kernel/alternative.c static void patch_alternative(struct alt_instr *alt, · line 155
Quoted 7 lines
arch/arm64/kernel/alternative.c +7
-0+dsb (ish); + + i_start = (u64 )start & ~(i_size -1 ); +while (i_start <= (u64 )end) { + asmvolatile ("ic ivau, %0" : :"r" (i_start)); + i_start += i_size; + }
Likewise here.
[RK] - ok
Thanks,
Mark.
Quoted 19 lines
arch/arm64/kernel/alternative.c +5
-2+dsb (ish); +isb (); +} +static void __apply_alternatives (void *alt_region,bool use_linear_alias) {struct alt_instr *alt;@@ -155,7 +190,7 @@ static void __apply_alternatives(void *alt_region, bool use_linear_alias)alt_cb (alt, origptr, updptr, nr_inst); -flush_icache_range ((uintptr_t )origptr, +clean_dcache_range_nopatch ((uintptr_t )origptr, (uintptr_t )(origptr + nr_inst)); } } --2.1.4
PATCH 1/1 arm64: alternative:flush cache with unpatched code
1 more comment inline.
Thanks
Rohit
________________________________________
From: linux-arm-kernel <[email protected]> on behalf of Rohit Khanna <[email protected]>
Sent: Friday, June 1, 2018 12:52 PM
To: Mark Rutland
Cc: Suzuki.Poulose at arm.com; catalin.marinas at arm.com; will.deacon at arm.com; Bo Yan; robin.murphy at arm.com; Alexander Van Brunt; linux-arm-kernel at lists.infradead.org
Subject: Re: [PATCH] arm64: alternative:flush cache with unpatched code
[RK] - Thanks for the comments Mark. Reply inlined.
Thanks
Rohit
________________________________________
From: Mark Rutland <[email protected]>
Sent: Friday, June 1, 2018 2:03 AM
To: Rohit Khanna
Cc: catalin.marinas at arm.com; robin.murphy at arm.com; Suzuki.Poulose at arm.com; linux-arm-kernel at lists.infradead.org; Alexander Van Brunt; Bo Yan; will.deacon at arm.com
Subject: Re: [PATCH] arm64: alternative:flush cache with unpatched code
Hi,
As a general thing, could you please add a version number to patches in future? i.e. this should be PATCHv4.
It really helps keeping track of patches, distinguishing versions, etc.
Quoted 27 lines · Rohit Khanna
In the current implementation,
__apply_alternativespatchesflush_icache_rangeand then executes it without invalidating the icache. Thus, icache can contain some of the old instructions forflush_icache_range. This can cause unpredictable behavior as during execution we can get a mix of old and new instructions forflush_icache_range.This patch :
1. Adds a new function
clean_dcache_range_nopatchfor flushing kernel memory range. This function uses non hot-patched code and can be safely used to flush cache during code patching.2. Modifies
__apply_alternativesso that it usesclean_dcache_range_nopatchto flush the cache range after patching code.Signed-off-by Rohit Khanna <[email protected]>--- arch/arm64/include/asm/sysreg.h | 3 +++ arch/arm64/kernel/alternative.c | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-)arch/arm64/include/asm/sysreg.h +0
-0
arch/arm64/include/asm/sysreg.h line 622
Quoted 6 lines
arch/arm64/include/asm/sysreg.h +3
-0@@ -617,6 +617,9 @@#define MVFR1_FPDNAN_SHIFT 4#define MVFR1_FPFTZ_SHIFT 0 +/* SYS_CTR_EL0 */ +#define SYS_CTR_ISIZE_SHIFT 0 +#define SYS_CTR_DSIZE_SHIFT 16
We already have CTR_DMINLINE_SHIFT in <asm/cache.h>
Can we please add CTR_IMINLIN_SHIFT there too?
Maybe those should be moved into sysreg.h, but that can be a separate cleanup.
[RK] - <asm/cache.h> doesnt contain CTR_DMINLINE_SHIFT.
[RK ] - Sorry, I was looking at kernel-4.14 and couldnt find it there. I can find it in linux-next repo.
Quoted 7 lines
arch/arm64/include/asm/sysreg.h +0
-0#define ID_AA64MMFR0_TGRAN4_SHIFT 28#define ID_AA64MMFR0_TGRAN64_SHIFT 24arch/arm64/kernel/alternative.c +0
-0
arch/arm64/kernel/alternative.c static void patch_alternative(struct alt_instr *alt, · line 130
Quoted 9 lines
arch/arm64/kernel/alternative.c +6
-0@@ -122,6 +122,41 @@ static void patch_alternative(struct alt_instr *alt, } } +/* This is used for flushing kernel memory range after +* __apply_alternatives has patched kernel code +*/ +static void clean_dcache_range_nopatch (void *start,void *end) +{ +u64 d_start, i_start, d_size, i_size, ctr_el0;
I don't think we need separate i_start and d_start variables. A 'start' or 'cur' variable could be used for both.
[RK] - ok.
arch/arm64/kernel/alternative.c static void patch_alternative(struct alt_instr *alt, · line 138
Quoted 8 lines
arch/arm64/kernel/alternative.c +8
-0+ +/* use sanitised value of ctr_el0 rather than raw value from CPU */ + ctr_el0 =read_sanitised_ftr_reg (SYS_CTR_EL0 ); +/* size in bytes */ + d_size =cpuid_feature_extract_unsigned_field (ctr_el0, +SYS_CTR_DSIZE_SHIFT ); + i_size =cpuid_feature_extract_unsigned_field (ctr_el0, +SYS_CTR_ISIZE_SHIFT );
This isn't the size in bytes. Each is log2 the number of (4-byte) words.
i.e. the size in bytes is (xMinLine << 2).
[RK] - This doesnt seem right. For eg if IMinLine = 4 or 0b100
then with above formula ICacheSize in Bytes = 4 << 2 = 16 The correct formula should be (4 << xMinLine).
So in case IMinLine = 4 or 0b100, ICacheSizeBytes = 4 << 4 = 64B
arch/arm64/kernel/alternative.c static void patch_alternative(struct alt_instr *alt, · line 146
Quoted 8 lines
arch/arm64/kernel/alternative.c +8
-0+ + d_start = (u64 )start & ~(d_size -1 ); +while (d_start <= (u64 )end) { +/* Use civac instead of cvau. This is required +* due to ARM errata 826319, 827319, 824069, +* 819472 on A53 +*/ + asmvolatile ("dc civac, %0" : :"r" (d_start));
Either this needs a memory clobber, or we need barrier() first, to ensure that the compiler doesn't re-order this against some of the patching code, however unlikely that may be.
[RK] - So add barrier() before calling clean_dcache_range_nopatch() ?
arch/arm64/kernel/alternative.c static void patch_alternative(struct alt_instr *alt, · line 148
Quoted 2 lines
arch/arm64/kernel/alternative.c +2
-0+ d_start += d_size; + }
The loop can be simplified to:
do {
asm ( ... );
} while (d_start += d_size, d_start < (u64)end)[RK] - ok
arch/arm64/kernel/alternative.c static void patch_alternative(struct alt_instr *alt, · line 155
Quoted 7 lines
arch/arm64/kernel/alternative.c +7
-0+dsb (ish); + + i_start = (u64 )start & ~(i_size -1 ); +while (i_start <= (u64 )end) { + asmvolatile ("ic ivau, %0" : :"r" (i_start)); + i_start += i_size; + }
Likewise here.
[RK] - ok
Thanks,
Mark.
Quoted 17 lines
arch/arm64/kernel/alternative.c +5
-2+dsb (ish); +isb (); +} +static void __apply_alternatives (void *alt_region,bool use_linear_alias) {struct alt_instr *alt;@@ -155,7 +190,7 @@ static void __apply_alternatives(void *alt_region, bool use_linear_alias)alt_cb (alt, origptr, updptr, nr_inst); -flush_icache_range ((uintptr_t )origptr, +clean_dcache_range_nopatch ((uintptr_t )origptr, (uintptr_t )(origptr + nr_inst)); } } --
Quoted 2 lines
2.1.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Mark Rutland
reviewerPATCH 1/1 arm64: alternative:flush cache with unpatched code
In reply to Rohit KhannaQuoted 10 lines · Rohit Khanna
[RK] - Thanks for the comments Mark. Reply inlined.
Thanks
Rohit
________________________________________
From: Mark Rutland <[email protected]>
Sent: Friday, June 1, 2018 2:03 AM
To: Rohit Khanna
Cc: catalin.marinas at arm.com; robin.murphy at arm.com; Suzuki.Poulose at arm.com; linux-arm-kernel at lists.infradead.org; Alexander Van Brunt; Bo Yan; will.deacon at arm.com
Subject: Re: [PATCH] arm64: alternative:flush cache with unpatched code
[...]
Quoted 12 lines
arch/arm64/include/asm/sysreg.h line 622
Quoted 9 lines
arch/arm64/include/asm/sysreg.h +3
-0@@ -617,6 +617,9 @@#define MVFR1_FPDNAN_SHIFT 4#define MVFR1_FPFTZ_SHIFT 0 +/* SYS_CTR_EL0 */ +#define SYS_CTR_ISIZE_SHIFT 0 +#define SYS_CTR_DSIZE_SHIFT 16We already have
CTR_DMINLINE_SHIFTin <asm/cache.h>
Quoted 5 lines
Can we please add
CTR_IMINLIN_SHIFTthere too?Maybe those should be moved into
sysreg.h, but that can be a separate cleanup.[RK] - <
asm/cache.h> doesnt containCTR_DMINLINE_SHIFT.
It's on line 23 of arch/arm64/include/asm/cache.h, looking at v4.17.
[...]
Quoted 8 lines
arch/arm64/include/asm/sysreg.h
Quoted 7 lines
arch/arm64/include/asm/sysreg.h +7
-0+/* use sanitised value of ctr_el0 rather than raw value from CPU */ + ctr_el0 =read_sanitised_ftr_reg (SYS_CTR_EL0 ); +/* size in bytes */ + d_size =cpuid_feature_extract_unsigned_field (ctr_el0, +SYS_CTR_DSIZE_SHIFT ); + i_size =cpuid_feature_extract_unsigned_field (ctr_el0, +SYS_CTR_ISIZE_SHIFT );
Quoted 8 lines
This isn't the size in bytes. Each is log2 the number of (4-byte) words.
i.e. the size in bytes is (xMinLine << 2).
[RK] - This doesnt seem right. For eg if IMinLine = 4 or 0b100
then with above formula ICacheSize in Bytes = 4 << 2 = 16 The correct formula should be (4 << xMinLine).
So in case IMinLine = 4 or 0b100, ICacheSizeBytes = 4 << 4 = 64B
Whoops. You are correct with 4 << xMinLine.
[...]
Quoted 8 lines
arch/arm64/include/asm/sysreg.h
Quoted 7 lines
arch/arm64/include/asm/sysreg.h +7
-0+ d_start = (u64 )start & ~(d_size -1 ); +while (d_start <= (u64 )end) { +/* Use civac instead of cvau. This is required +* due to ARM errata 826319, 827319, 824069, +* 819472 on A53 +*/ + asmvolatile ("dc civac, %0" : :"r" (d_start));
Quoted 4 lines
Either this needs a memory clobber, or we need
barrier()first, to ensure that the compiler doesn't re-order this against some of the patching code, however unlikely that may be.
[RK] - So addbarrier()before callingclean_dcache_range_nopatch()?
I'd put it before the loop here so that it's clearly associated with the DC CIVAC.
Thanks,
Mark.