From e15bd3975a8af29751891140d6fece0b17a92919 Mon Sep 17 00:00:00 2001 From: Pat Rogers Date: Sat, 21 Mar 2026 17:03:49 -0500 Subject: [PATCH] Fix cache line alignment in Cache_Maintenance The generic Cache_Maintenance procedure used the raw Start address as the initial DCCMVAC write address without first aligning it down to a cache line boundary. If Start was not 32-byte aligned, the first cache line was only partially cleaned. Additionally, Len was not extended to account for the trimmed prefix bytes, leaving the final partial cache line unflushed. Fix by aligning Op_Addr down to the nearest cache line boundary and extending Op_Size by the corresponding offset, ensuring all cache lines covering [Start, Start+Len) are cleaned. correct new copyright date formatting for readability --- arch/ARM/cortex_m/src/cache/cortex_m-cache.adb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/ARM/cortex_m/src/cache/cortex_m-cache.adb b/arch/ARM/cortex_m/src/cache/cortex_m-cache.adb index eada3cf3c..b8238d680 100644 --- a/arch/ARM/cortex_m/src/cache/cortex_m-cache.adb +++ b/arch/ARM/cortex_m/src/cache/cortex_m-cache.adb @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- -- --- Copyright (C) 2015-2016, AdaCore -- +-- Copyright (C) 2015-2026, AdaCore -- -- -- -- Redistribution and use in source and binary forms, with or without -- -- modification, are permitted provided that the following conditions are -- @@ -90,24 +90,24 @@ package body Cortex_M.Cache is if not D_Cache_Enabled then return; end if; - declare function To_U32 is new Ada.Unchecked_Conversion (System.Address, UInt32); - - Op_Size : Integer_32 := Integer_32 (Len); - Op_Addr : UInt32 := To_U32 (Start); - Reg : UInt32 with Volatile, Address => Reg_Address; - + Aligned_Addr : constant UInt32 := To_U32 (Start) and not (Data_Cache_Line_Size - 1); + Aligned_Size : constant UInt32 := UInt32 (Len) + (To_U32 (Start) - Aligned_Addr); + Op_Size : Integer_32 := Integer_32 (Aligned_Size); + -- Op_Size is extended by the number of bytes trimmed from the start, + -- ensuring the final partial line is covered + Op_Addr : UInt32 := Aligned_Addr; + -- Op_Addr starts at Start rounded down to the nearest cache line + Reg : UInt32 with Volatile, Address => Reg_Address; begin DSB; - while Op_Size > 0 loop Reg := Op_Addr; Op_Addr := Op_Addr + Data_Cache_Line_Size; Op_Size := Op_Size - Integer_32 (Data_Cache_Line_Size); end loop; - DSB; ISB; end;