| /* SPDX-License-Identifier: GPL-2.0-only */ | |
| /* | |
| * Copyright 2023 Red Hat | |
| */ | |
| #ifndef UDS_CPU_H | |
| #define UDS_CPU_H | |
| #include <linux/cache.h> | |
| /** | |
| * uds_prefetch_address() - Minimize cache-miss latency by attempting to move data into a CPU cache | |
| * before it is accessed. | |
| * | |
| * @address: the address to fetch (may be invalid) | |
| * @for_write: must be constant at compile time--false if for reading, true if for writing | |
| */ | |
| static inline void uds_prefetch_address(const void *address, bool for_write) | |
| { | |
| /* | |
| * for_write won't be a constant if we are compiled with optimization turned off, in which | |
| * case prefetching really doesn't matter. clang can't figure out that if for_write is a | |
| * constant, it can be passed as the second, mandatorily constant argument to prefetch(), | |
| * at least currently on llvm 12. | |
| */ | |
| if (__builtin_constant_p(for_write)) { | |
| if (for_write) | |
| __builtin_prefetch(address, true); | |
| else | |
| __builtin_prefetch(address, false); | |
| } | |
| } | |
| /** | |
| * uds_prefetch_range() - Minimize cache-miss latency by attempting to move a range of addresses | |
| * into a CPU cache before they are accessed. | |
| * | |
| * @start: the starting address to fetch (may be invalid) | |
| * @size: the number of bytes in the address range | |
| * @for_write: must be constant at compile time--false if for reading, true if for writing | |
| */ | |
| static inline void uds_prefetch_range(const void *start, unsigned int size, | |
| bool for_write) | |
| { | |
| /* | |
| * Count the number of cache lines to fetch, allowing for the address range to span an | |
| * extra cache line boundary due to address alignment. | |
| */ | |
| const char *address = (const char *) start; | |
| unsigned int offset = ((uintptr_t) address % L1_CACHE_BYTES); | |
| unsigned int cache_lines = (1 + ((size + offset) / L1_CACHE_BYTES)); | |
| while (cache_lines-- > 0) { | |
| uds_prefetch_address(address, for_write); | |
| address += L1_CACHE_BYTES; | |
| } | |
| } | |
| #endif /* UDS_CPU_H */ |