cpu.h 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Copyright 2023 Red Hat
  4. */
  5. #ifndef UDS_CPU_H
  6. #define UDS_CPU_H
  7. #include <linux/cache.h>
  8. /**
  9. * uds_prefetch_address() - Minimize cache-miss latency by attempting to move data into a CPU cache
  10. * before it is accessed.
  11. *
  12. * @address: the address to fetch (may be invalid)
  13. * @for_write: must be constant at compile time--false if for reading, true if for writing
  14. */
  15. static inline void uds_prefetch_address(const void *address, bool for_write)
  16. {
  17. /*
  18. * for_write won't be a constant if we are compiled with optimization turned off, in which
  19. * case prefetching really doesn't matter. clang can't figure out that if for_write is a
  20. * constant, it can be passed as the second, mandatorily constant argument to prefetch(),
  21. * at least currently on llvm 12.
  22. */
  23. if (__builtin_constant_p(for_write)) {
  24. if (for_write)
  25. __builtin_prefetch(address, true);
  26. else
  27. __builtin_prefetch(address, false);
  28. }
  29. }
  30. /**
  31. * uds_prefetch_range() - Minimize cache-miss latency by attempting to move a range of addresses
  32. * into a CPU cache before they are accessed.
  33. *
  34. * @start: the starting address to fetch (may be invalid)
  35. * @size: the number of bytes in the address range
  36. * @for_write: must be constant at compile time--false if for reading, true if for writing
  37. */
  38. static inline void uds_prefetch_range(const void *start, unsigned int size,
  39. bool for_write)
  40. {
  41. /*
  42. * Count the number of cache lines to fetch, allowing for the address range to span an
  43. * extra cache line boundary due to address alignment.
  44. */
  45. const char *address = (const char *) start;
  46. unsigned int offset = ((uintptr_t) address % L1_CACHE_BYTES);
  47. unsigned int cache_lines = (1 + ((size + offset) / L1_CACHE_BYTES));
  48. while (cache_lines-- > 0) {
  49. uds_prefetch_address(address, for_write);
  50. address += L1_CACHE_BYTES;
  51. }
  52. }
  53. #endif /* UDS_CPU_H */