clean_dcache_by_address misses the last cache line when addr is not line-aligned
I maintainer di solito rispondono entro 2 giorni
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 79/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- rust
- Ambito
- embedded-iot
Direzione di ricerca
Individua clean_dcache_by_address e clean_invalidate_dcache_by_address, che secondo il report usano lo stesso calcolo del numero di linee; segui gli helper di slice e di riferimento che chiamano la funzione di pulizia. Inizia controllando la dimensione della linea di cache e l’arrotondamento degli indirizzi in quelle implementazioni. Il lavoro è completato quando i buffer non allineati hanno tutte le linee di cache interessate pulite e il comportamento ai limiti è coerente con il calcolo dell’ultimo byte riportato.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
cortex-m 0.7.10 (same code on main), Cortex-M7.
Steps to reproduce (on a PC, the line count only):
cargo new lines && cd lines- Put the program below in
src/main.rs. cargo run -q
What the program does:
- Copies the line count of
clean_dcache_by_address. - Takes a 1460-byte buffer at three addresses.
- The first address is on a line.
- The second is 20 bytes into a line.
- The third is 28 bytes into a line.
- Computes the range the function cleans for each.
- Prints how many bytes at the end of the buffer are not cleaned.
Expected: 0 bytes not cleaned for every address.
The docs say the function cleans "until all of slice has been cleaned".
The docs only recommend alignment.
Got:
addr 0x24000000 size 1460: cleans 0x24000000..0x240005c0, buffer ends 0x240005b4, last 0 bytes not cleaned
addr 0x24000014 size 1460: cleans 0x24000000..0x240005c0, buffer ends 0x240005c8, last 8 bytes not cleaned
addr 0x2400001c size 1460: cleans 0x24000000..0x240005c0, buffer ends 0x240005d0, last 16 bytes not cleaned
On hardware (STM32H753, Cortex-M7, cortex-m 0.7.9, which has the same code):
- A 1460-byte buffer on the stack.
- The CPU writes the buffer.
clean_dcache_by_sliceon the buffer.- The USART's TX DMA sends the buffer.
Expected: the receiver gets the bytes the CPU wrote.
Got: the last 8 bytes were stale in 609 of 685 writes.
With the buffer aligned to 32 bytes: 0 wrong.
Cause:
clean_dcache_by_addressroundsaddrdown to its cache line:let mut addr = addr & mask;- It counts the lines from
sizealone:let num_lines = ((size - 1) / line_size) + 1; - A buffer that starts inside a line reaches one line further than
sizealone says. - That last line is never cleaned.
- The DMA reads old bytes from RAM there.
Also affected:
clean_invalidate_dcache_by_addresshas the same computation.clean_dcache_by_slicecallsclean_dcache_by_address.clean_dcache_by_refcallsclean_dcache_by_address.
Not affected in the same way:
invalidate_dcache_by_addresshas the same computation.- But it is
unsafe. - And it requires an aligned
addrandsize.
Fix:
- Round
addrdown to its line: the first line. - Round the last byte,
addr + size - 1, down to its line: the last line. - Count the lines from the first line to the last line.
let first = addr & mask;
let last = addr.saturating_add(size - 1) & mask;
let num_lines = (last - first) / line_size + 1;
Why the last byte and not the end:
- The end,
addr + size, rounded up can overflow at the top of the address space. - The last byte's address always fits.
saturating_addstops a range that runs past the top at the top.
Workaround until a release has the fix:
- Align the buffer to 32 bytes.
- Or round
addrdown andaddr + sizeup yourself before the call.
Program:
// The line count of cortex-m 0.7.10's SCB::clean_dcache_by_address, next to the lines a buffer touches.
const LINE: usize = 32;
fn cleaned(addr: usize, size: usize) -> (usize, usize) {
let num_lines = ((size - 1) / LINE) + 1; // as in clean_dcache_by_address
let start = addr & !(LINE - 1);
(start, start + num_lines * LINE) // [start, end) the function cleans
}
fn main() {
let size = 1460;
for addr in [0x2400_0000, 0x2400_0014, 0x2400_001c] {
let (start, end) = cleaned(addr, size);
let missed = (addr + size).saturating_sub(end);
println!("addr {addr:#x} size {size}: cleans {start:#x}..{end:#x}, buffer ends {:#x}, last {missed} bytes not cleaned", addr + size);
}
}
- Lingua principale
- Rust
- Stelle
- 1k
- Fork
- 202
- Merge medio
- 1g 4h
- PR unite (30g)
- 2
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di rust-embedded/cortex-m
-
Deprecation of `bare-metal`Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
rust-embedded/cortex-m#651 · 5 commenti ·
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
rust-embedded/cortex-m#637 ·
I maintainer di solito rispondono entro 2 giorni
-
enhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
rust-embedded/cortex-m#511 · 2 commenti ·
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 55/100
rust-embedded/cortex-m#700 · 1 commento ·
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
rust-embedded/cortex-m#695 ·
I maintainer di solito rispondono entro 2 giorni
Tutte le issue di rust-embedded/cortex-m
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 69/100
I maintainer di solito rispondono entro 1 giorno
-
A match arm above the largest i64 is compared as 0Forse già presa Una pull request collegata a questa issue è aperta o già unita. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 86/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 83/100
DioxusLabs/dioxus#6063 ·
I maintainer di solito rispondono entro 1 giorno
-
`nsh-core` fails to compile when taffy's default `calc` feature is enabled elsewhere in the graphAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
longbridge/nsh#966 ·
I maintainer di solito rispondono entro 1 giorno
-
Windows docs: pin a tested ConPTY version for Kitty graphics; 1.25.260930003 corrupts large uploadsAperta
Difficoltà 1/5 1-3 ore Idoneità per principianti 88/100
raphamorim/rio#2021 ·
I maintainer di solito rispondono entro 1 giorno