[sysmem] Store more inspect information about every heap

Add inspect information about every heap, along with an ID. This makes
it possible to specify what heap a VMO is allocated from. Also add more
properties giving the VMO size and a koid for the channel that's keeping
it alive.

Change-Id: I40cf50ee739a68a2b02662a44c90c95544800840
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/475898
Reviewed-by: Dustin Green <dustingreen@google.com>
Commit-Queue: John Bauman <jbauman@google.com>
diff --git a/src/devices/sysmem/drivers/sysmem/buffer_collection.cc b/src/devices/sysmem/drivers/sysmem/buffer_collection.cc
index 39e3f49..105c1b6 100644
--- a/src/devices/sysmem/drivers/sysmem/buffer_collection.cc
+++ b/src/devices/sysmem/drivers/sysmem/buffer_collection.cc
@@ -80,6 +80,16 @@
   (void)binding_.Close();
 }
 
+void BufferCollection::Bind(zx::channel server_request) {
+  zx_info_handle_basic_t info;
+  zx_status_t status =
+      server_request.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr);
+  if (status == ZX_OK) {
+    node_.CreateUint("channel_koid", info.koid, &properties_);
+  }
+  FidlServer::Bind(std::move(server_request));
+}
+
 zx_status_t BufferCollection::SetEventSink(zx_handle_t buffer_collection_events_client_param) {
   zx::channel buffer_collection_events_client(buffer_collection_events_client_param);
   if (is_done_) {
diff --git a/src/devices/sysmem/drivers/sysmem/buffer_collection.h b/src/devices/sysmem/drivers/sysmem/buffer_collection.h
index a95bdbf..a46054d 100644
--- a/src/devices/sysmem/drivers/sysmem/buffer_collection.h
+++ b/src/devices/sysmem/drivers/sysmem/buffer_collection.h
@@ -29,6 +29,8 @@
  public:
   ~BufferCollection();
 
+  void Bind(zx::channel server_request);
+
   //
   // fuchsia.sysmem.BufferCollection interface methods
   //
@@ -165,6 +167,7 @@
   inspect::Node node_;
   inspect::UintProperty debug_id_property_;
   inspect::StringProperty debug_name_property_;
+  inspect::ValueList properties_;
 };
 
 }  // namespace sysmem_driver
diff --git a/src/devices/sysmem/drivers/sysmem/buffer_collection_token.cc b/src/devices/sysmem/drivers/sysmem/buffer_collection_token.cc
index fd3b2b6..2cf531c 100644
--- a/src/devices/sysmem/drivers/sysmem/buffer_collection_token.cc
+++ b/src/devices/sysmem/drivers/sysmem/buffer_collection_token.cc
@@ -39,6 +39,12 @@
 }
 
 void BufferCollectionToken::Bind(zx::channel channel) {
+  zx_info_handle_basic_t info;
+  zx_status_t status =
+      channel.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr);
+  if (status == ZX_OK) {
+    node_.CreateUint("channel_koid", info.koid, &properties_);
+  }
   auto res = fidl::BindServer(
       parent_device_->dispatcher(), std::move(channel), this,
       fidl::OnUnboundFn<BufferCollectionToken>(
diff --git a/src/devices/sysmem/drivers/sysmem/buffer_collection_token.h b/src/devices/sysmem/drivers/sysmem/buffer_collection_token.h
index 6a55cac..f4a5d90 100644
--- a/src/devices/sysmem/drivers/sysmem/buffer_collection_token.h
+++ b/src/devices/sysmem/drivers/sysmem/buffer_collection_token.h
@@ -107,6 +107,7 @@
   inspect::Node node_;
   inspect::UintProperty debug_id_property_;
   inspect::StringProperty debug_name_property_;
+  inspect::ValueList properties_;
 };
 
 }  // namespace sysmem_driver
diff --git a/src/devices/sysmem/drivers/sysmem/contiguous_pooled_memory_allocator.cc b/src/devices/sysmem/drivers/sysmem/contiguous_pooled_memory_allocator.cc
index 28e0554..a94940c 100644
--- a/src/devices/sysmem/drivers/sysmem/contiguous_pooled_memory_allocator.cc
+++ b/src/devices/sysmem/drivers/sysmem/contiguous_pooled_memory_allocator.cc
@@ -54,7 +54,8 @@
   // Ensure NUL-terminated.
   child_name_[sizeof(child_name_) - 1] = 0;
   node_ = parent_node->CreateChild(allocation_name);
-  size_property_ = node_.CreateUint("size", size);
+  node_.CreateUint("size", size, &properties_);
+  node_.CreateUint("id", id(), &properties_);
   high_water_mark_property_ = node_.CreateUint("high_water_mark", 0);
   free_at_high_water_mark_property_ = node_.CreateUint("free_at_high_water_mark", size);
   used_size_property_ = node_.CreateUint("used_size", 0);
diff --git a/src/devices/sysmem/drivers/sysmem/contiguous_pooled_memory_allocator.h b/src/devices/sysmem/drivers/sysmem/contiguous_pooled_memory_allocator.h
index 258e4e87..265d484 100644
--- a/src/devices/sysmem/drivers/sysmem/contiguous_pooled_memory_allocator.h
+++ b/src/devices/sysmem/drivers/sysmem/contiguous_pooled_memory_allocator.h
@@ -93,6 +93,7 @@
   uint64_t max_free_size_at_high_water_mark_{};
 
   inspect::Node node_;
+  inspect::ValueList properties_;
   inspect::UintProperty size_property_;
   inspect::UintProperty high_water_mark_property_;
   inspect::UintProperty used_size_property_;
diff --git a/src/devices/sysmem/drivers/sysmem/device.cc b/src/devices/sysmem/drivers/sysmem/device.cc
index 667fd0b..fcd4da94a 100644
--- a/src/devices/sysmem/drivers/sysmem/device.cc
+++ b/src/devices/sysmem/drivers/sysmem/device.cc
@@ -26,6 +26,7 @@
 
 #include <ddk/device.h>
 #include <ddk/platform-defs.h>
+#include <fbl/string_printf.h>
 
 #include "allocator.h"
 #include "buffer_collection_token.h"
@@ -83,12 +84,15 @@
 
 class SystemRamMemoryAllocator : public MemoryAllocator {
  public:
-  SystemRamMemoryAllocator()
+  SystemRamMemoryAllocator(Owner* parent_device)
       : MemoryAllocator(BuildHeapPropertiesWithCoherencyDomainSupport(
             true /*cpu*/, true /*ram*/, true /*inaccessible*/,
             // Zircon guarantees created VMO are filled with 0; sysmem doesn't
             // need to clear it once again.
-            false /*need_clear*/)) {}
+            false /*need_clear*/)) {
+    node_ = parent_device->heap_node()->CreateChild("SysmemRamMemoryAllocator");
+    node_.CreateUint("id", id(), &properties_);
+  }
 
   zx_status_t Allocate(uint64_t size, std::optional<std::string> name,
                        zx::vmo* parent_vmo) override {
@@ -115,6 +119,10 @@
   // allocator since the VMOs independently track what pages they're using.  So this allocator can
   // always claim is_empty() true.
   bool is_empty() override { return true; }
+
+ private:
+  inspect::Node node_;
+  inspect::ValueList properties_;
 };
 
 class ContiguousSystemRamMemoryAllocator : public MemoryAllocator {
@@ -125,7 +133,10 @@
             // Zircon guarantees contagious VMO created are filled with 0;
             // sysmem doesn't need to clear it once again.
             false /*need_clear*/)),
-        parent_device_(parent_device) {}
+        parent_device_(parent_device) {
+    node_ = parent_device_->heap_node()->CreateChild("ContiguousSystemRamMemoryAllocator");
+    node_.CreateUint("id", id(), &properties_);
+  }
 
   zx_status_t Allocate(uint64_t size, std::optional<std::string> name,
                        zx::vmo* parent_vmo) override {
@@ -176,6 +187,8 @@
 
  private:
   Owner* const parent_device_;
+  inspect::Node node_;
+  inspect::ValueList properties_;
 };
 
 class ExternalMemoryAllocator : public MemoryAllocator {
@@ -187,7 +200,11 @@
       : MemoryAllocator(std::move(properties)),
         owner_(owner),
         heap_(std::move(heap)),
-        wait_for_close_(std::move(wait_for_close)) {}
+        wait_for_close_(std::move(wait_for_close)) {
+    node_ = owner->heap_node()->CreateChild(
+        fbl::StringPrintf("ExternalMemoryAllocator-%ld", id()).c_str());
+    node_.CreateUint("id", id(), &properties_);
+  }
 
   ~ExternalMemoryAllocator() { ZX_DEBUG_ASSERT(is_empty()); }
 
@@ -258,6 +275,9 @@
 
   // From parent vmo handle to ID.
   std::map<zx_handle_t, uint64_t> allocations_;
+
+  inspect::Node node_;
+  inspect::ValueList properties_;
 };
 
 fuchsia_sysmem_DriverConnector_ops_t driver_connector_ops = {
@@ -402,7 +422,7 @@
   contiguous_memory_size = AlignUp(contiguous_memory_size, static_cast<int64_t>(ZX_PAGE_SIZE));
 
   allocators_[llcpp::fuchsia::sysmem2::HeapType::SYSTEM_RAM] =
-      std::make_unique<SystemRamMemoryAllocator>();
+      std::make_unique<SystemRamMemoryAllocator>(this);
 
   status = pdev_.GetBti(0, &bti_);
   if (status != ZX_OK) {
diff --git a/src/devices/sysmem/drivers/sysmem/device.h b/src/devices/sysmem/drivers/sysmem/device.h
index b7aa33a..a904aaf 100644
--- a/src/devices/sysmem/drivers/sysmem/device.h
+++ b/src/devices/sysmem/drivers/sysmem/device.h
@@ -79,6 +79,7 @@
   [[nodiscard]] zx_status_t CreatePhysicalVmo(uint64_t base, uint64_t size,
                                               zx::vmo* vmo_out) override;
   void CheckForUnbind() override;
+  inspect::Node* heap_node() override { return &heaps_; }
 
   [[nodiscard]] zx_status_t Connect(zx_handle_t allocator_request);
 
diff --git a/src/devices/sysmem/drivers/sysmem/logical_buffer_collection.cc b/src/devices/sysmem/drivers/sysmem/logical_buffer_collection.cc
index d682660..16b3fbe 100644
--- a/src/devices/sysmem/drivers/sysmem/logical_buffer_collection.cc
+++ b/src/devices/sysmem/drivers/sysmem/logical_buffer_collection.cc
@@ -1982,6 +1982,10 @@
     }
   }
 
+  node_.CreateUint("allocator_id", allocator->id(), &vmo_properties_);
+  node_.CreateUint("size_bytes", min_size_bytes, &vmo_properties_);
+  node_.CreateUint("heap", static_cast<uint64_t>(buffer_settings.heap()), &vmo_properties_);
+
   // Now that min_size_bytes accounts for any ImageFormatConstraints, we can just allocate
   // min_size_bytes buffers.
   //
diff --git a/src/devices/sysmem/drivers/sysmem/memory_allocator.cc b/src/devices/sysmem/drivers/sysmem/memory_allocator.cc
index 21302ec..ddb5297 100644
--- a/src/devices/sysmem/drivers/sysmem/memory_allocator.cc
+++ b/src/devices/sysmem/drivers/sysmem/memory_allocator.cc
@@ -6,10 +6,15 @@
 
 #include <zircon/assert.h>
 
+#include <atomic>
+
 namespace sysmem_driver {
 
 MemoryAllocator::MemoryAllocator(llcpp::fuchsia::sysmem2::HeapProperties properties)
-    : heap_properties_(std::move(properties)) {}
+    : heap_properties_(std::move(properties)) {
+  static std::atomic_uint64_t id;
+  id_ = id++;
+}
 
 MemoryAllocator::~MemoryAllocator() {
   for (auto& it : destroy_callbacks_) {
diff --git a/src/devices/sysmem/drivers/sysmem/memory_allocator.h b/src/devices/sysmem/drivers/sysmem/memory_allocator.h
index ed9d2cf..676e884 100644
--- a/src/devices/sysmem/drivers/sysmem/memory_allocator.h
+++ b/src/devices/sysmem/drivers/sysmem/memory_allocator.h
@@ -8,6 +8,7 @@
 #include <fuchsia/sysmem/llcpp/fidl.h>
 #include <fuchsia/sysmem2/llcpp/fidl.h>
 #include <lib/fit/function.h>
+#include <lib/inspect/cpp/inspect.h>
 #include <lib/zx/bti.h>
 #include <lib/zx/vmo.h>
 
@@ -21,6 +22,7 @@
   // enables a fake in tests where we don't have a real zx::bti etc.
   class Owner {
    public:
+    virtual inspect::Node* heap_node() = 0;
     virtual const zx::bti& bti() = 0;
     virtual zx_status_t CreatePhysicalVmo(uint64_t base, uint64_t size, zx::vmo* vmo_out) = 0;
     // Should be called after every delete that makes the allocator empty.
@@ -83,10 +85,14 @@
   // Allocators must be empty before they're deleted.
   virtual bool is_empty() = 0;
 
+  uint64_t id() const { return id_; }
+
  public:
   std::map<intptr_t, fit::callback<void()>> destroy_callbacks_;
 
  private:
+  // This is a unique ID for the allocator on this system.
+  uint64_t id_{};
   llcpp::fuchsia::sysmem2::HeapProperties heap_properties_;
 };
 
diff --git a/src/devices/sysmem/drivers/sysmem/test/contiguous_pooled_memory_allocator_test.cc b/src/devices/sysmem/drivers/sysmem/test/contiguous_pooled_memory_allocator_test.cc
index 6220958..2111e47 100644
--- a/src/devices/sysmem/drivers/sysmem/test/contiguous_pooled_memory_allocator_test.cc
+++ b/src/devices/sysmem/drivers/sysmem/test/contiguous_pooled_memory_allocator_test.cc
@@ -19,7 +19,12 @@
 
 class FakeOwner : public MemoryAllocator::Owner {
  public:
-  FakeOwner() { EXPECT_OK(fake_bti_create(bti_.reset_and_get_address())); }
+  explicit FakeOwner(inspect::Node* heap_node)
+      : heap_node_(heap_node)
+
+  {
+    EXPECT_OK(fake_bti_create(bti_.reset_and_get_address()));
+  }
 
   ~FakeOwner() {}
 
@@ -27,8 +32,10 @@
   zx_status_t CreatePhysicalVmo(uint64_t base, uint64_t size, zx::vmo* vmo_out) override {
     return zx::vmo::create(size, 0u, vmo_out);
   }
+  inspect::Node* heap_node() override { return heap_node_; }
 
  private:
+  inspect::Node* heap_node_;
   zx::bti bti_;
 };
 
@@ -47,8 +54,8 @@
   static constexpr uint32_t kVmoCount = 1024;
   static constexpr char kVmoName[] = "test-pool";
 
-  FakeOwner fake_owner_;
   inspect::Inspector inspector_;
+  FakeOwner fake_owner_{&inspector_.GetRoot()};
   ContiguousPooledMemoryAllocator allocator_;
 };