PhysicalRegion.cpp 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. #include <AK/Bitmap.h>
  2. #include <AK/NonnullRefPtr.h>
  3. #include <AK/RefPtr.h>
  4. #include <Kernel/Assertions.h>
  5. #include <Kernel/PhysicalAddress.h>
  6. #include <Kernel/VM/PhysicalPage.h>
  7. #include <Kernel/VM/PhysicalRegion.h>
  8. NonnullRefPtr<PhysicalRegion> PhysicalRegion::create(PhysicalAddress lower, PhysicalAddress upper)
  9. {
  10. return adopt(*new PhysicalRegion(lower, upper));
  11. }
  12. PhysicalRegion::PhysicalRegion(PhysicalAddress lower, PhysicalAddress upper)
  13. : m_lower(lower)
  14. , m_upper(upper)
  15. , m_bitmap(Bitmap::create())
  16. {
  17. }
  18. void PhysicalRegion::expand(PhysicalAddress lower, PhysicalAddress upper)
  19. {
  20. ASSERT(!m_pages);
  21. m_lower = lower;
  22. m_upper = upper;
  23. }
  24. unsigned PhysicalRegion::finalize_capacity()
  25. {
  26. ASSERT(!m_pages);
  27. m_pages = (m_upper.get() - m_lower.get()) / PAGE_SIZE;
  28. m_bitmap.grow(m_pages, false);
  29. return size();
  30. }
  31. RefPtr<PhysicalPage> PhysicalRegion::take_free_page(bool supervisor)
  32. {
  33. ASSERT(m_pages);
  34. if (m_used == m_pages)
  35. return nullptr;
  36. // search from the last page we allocated
  37. for (unsigned page = m_last; page < m_pages; page++) {
  38. if (!m_bitmap.get(page)) {
  39. m_bitmap.set(page, true);
  40. m_used++;
  41. m_last = page + 1;
  42. return PhysicalPage::create(m_lower.offset(page * PAGE_SIZE), supervisor);
  43. }
  44. }
  45. // wrap back around to the start in case we missed something
  46. for (unsigned page = 0; page < m_last; page++) {
  47. if (!m_bitmap.get(page)) {
  48. m_bitmap.set(page, true);
  49. m_used++;
  50. m_last = page + 1;
  51. return PhysicalPage::create(m_lower.offset(page * PAGE_SIZE), supervisor);
  52. }
  53. }
  54. ASSERT_NOT_REACHED();
  55. return nullptr;
  56. }
  57. void PhysicalRegion::return_page_at(PhysicalAddress addr)
  58. {
  59. ASSERT(m_pages);
  60. if (m_used == 0) {
  61. ASSERT_NOT_REACHED();
  62. }
  63. int local_offset = addr.get() - m_lower.get();
  64. ASSERT(local_offset >= 0);
  65. ASSERT(local_offset < (int)(m_pages * PAGE_SIZE));
  66. auto page = (unsigned)local_offset / PAGE_SIZE;
  67. if (page < m_last)
  68. m_last = page;
  69. m_bitmap.set(page, false);
  70. m_used--;
  71. }