KCOVInstance.cpp 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. /*
  2. * Copyright (c) 2021, Patrick Meyer <git@the-space.agency>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <Kernel/Devices/KCOVInstance.h>
  7. namespace Kernel {
  8. KCOVInstance::KCOVInstance(ProcessID pid)
  9. {
  10. m_pid = pid;
  11. }
  12. ErrorOr<void> KCOVInstance::buffer_allocate(size_t buffer_size_in_entries)
  13. {
  14. if (buffer_size_in_entries < 2 || buffer_size_in_entries > KCOV_MAX_ENTRIES)
  15. return EINVAL;
  16. // first entry contains index of last PC
  17. m_buffer_size_in_entries = buffer_size_in_entries - 1;
  18. m_buffer_size_in_bytes = Memory::page_round_up(buffer_size_in_entries * KCOV_ENTRY_SIZE);
  19. // one single vmobject is representing the buffer
  20. // - we allocate one kernel region using that vmobject
  21. // - when an mmap call comes in, we allocate another userspace region,
  22. // backed by the same vmobject
  23. m_vmobject = TRY(Memory::AnonymousVMObject::try_create_with_size(m_buffer_size_in_bytes, AllocationStrategy::AllocateNow));
  24. auto region_name = TRY(KString::formatted("kcov_{}", m_pid));
  25. m_kernel_region = TRY(MM.allocate_kernel_region_with_vmobject(
  26. *m_vmobject, m_buffer_size_in_bytes, region_name->view(),
  27. Memory::Region::Access::ReadWrite));
  28. m_buffer = (u64*)m_kernel_region->vaddr().as_ptr();
  29. return {};
  30. }
  31. void KCOVInstance::buffer_add_pc(u64 pc)
  32. {
  33. auto idx = (u64)m_buffer[0];
  34. if (idx >= m_buffer_size_in_entries) {
  35. // the buffer is already full
  36. return;
  37. }
  38. m_buffer[idx + 1] = pc;
  39. m_buffer[0] = idx + 1;
  40. }
  41. }