diff --git a/zircon/kernel/vm/include/vm/vm_object.h b/zircon/kernel/vm/include/vm/vm_object.h index 7283185ba0531b41fda574df7f63e661d2034d13..65ec8dc2d837b060375fe3be02602460c57aa7ee 100644 --- a/zircon/kernel/vm/include/vm/vm_object.h +++ b/zircon/kernel/vm/include/vm/vm_object.h @@ -36,6 +36,10 @@ public: virtual void OnOneChild() = 0; }; +typedef struct vm_lock : fbl::RefCounted<struct vm_lock> { + DECLARE_MUTEX(struct vm_lock) lock; +} vm_lock_t; + // The base vm object that holds a range of bytes of data // // Can be created without mapping and used as a container of data, or mappable @@ -256,10 +260,7 @@ public: virtual void DetachSource() {} protected: - // private constructor (use Create()) - explicit VmObject(fbl::RefPtr<VmObject> parent); - VmObject() - : VmObject(nullptr) {} + VmObject(fbl::RefPtr<VmObject> parent, fbl::RefPtr<vm_lock_t> root_lock); // private destructor, only called from refptr virtual ~VmObject(); @@ -281,15 +282,11 @@ protected: // magic value fbl::Canary<fbl::magic("VMO_")> canary_; - // members - - // declare a local mutex and default to pointing at it - // if constructed with a parent vmo, point lock_ at the parent's lock -private: - DECLARE_MUTEX(VmObject) local_lock_; - -protected: + // The lock which protects this class. All VmObjects in a clone tree + // share the same lock. Lock<Mutex>& lock_; + // Pointer to the actual lock. + fbl::RefPtr<vm_lock_t> lock_ptr_; // list of every mapping fbl::DoublyLinkedList<VmMapping*> mapping_list_ TA_GUARDED(lock_); diff --git a/zircon/kernel/vm/include/vm/vm_object_paged.h b/zircon/kernel/vm/include/vm/vm_object_paged.h index f8ba70b079cd79ac658e85eb9b9e00238527c032..32a88890605a23988aabd3144cbecc4b309a92c6 100644 --- a/zircon/kernel/vm/include/vm/vm_object_paged.h +++ b/zircon/kernel/vm/include/vm/vm_object_paged.h @@ -141,7 +141,12 @@ private: // private constructor (use Create()) VmObjectPaged( uint32_t options, uint32_t pmm_alloc_flags, uint64_t size, - fbl::RefPtr<VmObject> parent, fbl::RefPtr<PageSource> page_source); + fbl::RefPtr<VmObject> parent, fbl::RefPtr<vm_lock_t> root_lock, + fbl::RefPtr<PageSource> page_source); + + static zx_status_t CreateCommon(uint32_t pmm_alloc_flags, + uint32_t options, + uint64_t size, fbl::RefPtr<VmObject>* vmo); // private destructor, only called from refptr ~VmObjectPaged() override; diff --git a/zircon/kernel/vm/include/vm/vm_object_physical.h b/zircon/kernel/vm/include/vm/vm_object_physical.h index b12c48e5bdca2dd2df3c4e6d0df913d7aa1d49e2..280543c19383498986bc50ab1db102c1025f6276 100644 --- a/zircon/kernel/vm/include/vm/vm_object_physical.h +++ b/zircon/kernel/vm/include/vm/vm_object_physical.h @@ -46,7 +46,7 @@ public: private: // private constructor (use Create()) - VmObjectPhysical(paddr_t base, uint64_t size); + VmObjectPhysical(fbl::RefPtr<vm_lock_t> lock, paddr_t base, uint64_t size); // private destructor, only called from refptr ~VmObjectPhysical() override; diff --git a/zircon/kernel/vm/vm_object.cpp b/zircon/kernel/vm/vm_object.cpp index a390712a2de2d8c8d4d1139c036fd65e027dea6a..6d7fa6414d1ec456500d628c44e2ea8b6fa6952b 100644 --- a/zircon/kernel/vm/vm_object.cpp +++ b/zircon/kernel/vm/vm_object.cpp @@ -29,10 +29,13 @@ VmObject::GlobalList VmObject::all_vmos_ = {}; -VmObject::VmObject(fbl::RefPtr<VmObject> parent) - : lock_(parent ? parent->lock_ref() : local_lock_), - parent_(ktl::move(parent)) { +VmObject::VmObject(fbl::RefPtr<VmObject> parent, fbl::RefPtr<vm_lock_t> lock_ptr) + : lock_(lock_ptr->lock), lock_ptr_(ktl::move(lock_ptr)), parent_(ktl::move(parent)) { LTRACEF("%p\n", this); + + if (parent_) { + DEBUG_ASSERT(lock_ptr_ == parent_->lock_ptr_); + } } VmObject::~VmObject() { diff --git a/zircon/kernel/vm/vm_object_paged.cpp b/zircon/kernel/vm/vm_object_paged.cpp index 0c84b2ad5e33e0eb7f5e8041b1ac0de730b4b1a9..bbcd18b4ca0df72ca30411461a73be381d8ba1a4 100644 --- a/zircon/kernel/vm/vm_object_paged.cpp +++ b/zircon/kernel/vm/vm_object_paged.cpp @@ -68,8 +68,9 @@ zx_status_t RoundSize(uint64_t size, uint64_t* out_size) { VmObjectPaged::VmObjectPaged( uint32_t options, uint32_t pmm_alloc_flags, uint64_t size, - fbl::RefPtr<VmObject> parent, fbl::RefPtr<PageSource> page_source) - : VmObject(ktl::move(parent)), + fbl::RefPtr<VmObject> parent, fbl::RefPtr<vm_lock_t> root_lock, + fbl::RefPtr<PageSource> page_source) + : VmObject(ktl::move(parent), ktl::move(root_lock)), options_(options), size_(size), pmm_alloc_flags_(pmm_alloc_flags), @@ -112,23 +113,23 @@ VmObjectPaged::~VmObjectPaged() { pmm_free(&list); } -zx_status_t VmObjectPaged::Create(uint32_t pmm_alloc_flags, - uint32_t options, - uint64_t size, fbl::RefPtr<VmObject>* obj) { +zx_status_t VmObjectPaged::CreateCommon(uint32_t pmm_alloc_flags, + uint32_t options, + uint64_t size, fbl::RefPtr<VmObject>* obj) { // make sure size is page aligned zx_status_t status = RoundSize(size, &size); if (status != ZX_OK) { return status; } - if (options & kContiguous) { - // Force callers to use CreateContiguous() instead. - return ZX_ERR_INVALID_ARGS; + fbl::AllocChecker ac; + auto lock = fbl::AdoptRef<vm_lock_t>(new (&ac) vm_lock_t); + if (!ac.check()) { + return ZX_ERR_NO_MEMORY; } - fbl::AllocChecker ac; auto vmo = fbl::AdoptRef<VmObject>( - new (&ac) VmObjectPaged(options, pmm_alloc_flags, size, nullptr, nullptr)); + new (&ac) VmObjectPaged(options, pmm_alloc_flags, size, nullptr, ktl::move(lock), nullptr)); if (!ac.check()) { return ZX_ERR_NO_MEMORY; } @@ -138,6 +139,17 @@ zx_status_t VmObjectPaged::Create(uint32_t pmm_alloc_flags, return ZX_OK; } +zx_status_t VmObjectPaged::Create(uint32_t pmm_alloc_flags, + uint32_t options, + uint64_t size, fbl::RefPtr<VmObject>* obj) { + if (options & kContiguous) { + // Force callers to use CreateContiguous() instead. + return ZX_ERR_INVALID_ARGS; + } + + return CreateCommon(pmm_alloc_flags, options, size, obj); +} + zx_status_t VmObjectPaged::CreateContiguous(uint32_t pmm_alloc_flags, uint64_t size, uint8_t alignment_log2, fbl::RefPtr<VmObject>* obj) { DEBUG_ASSERT(alignment_log2 < sizeof(uint64_t) * 8); @@ -147,11 +159,10 @@ zx_status_t VmObjectPaged::CreateContiguous(uint32_t pmm_alloc_flags, uint64_t s return status; } - fbl::AllocChecker ac; - auto vmo = fbl::AdoptRef<VmObject>( - new (&ac) VmObjectPaged(kContiguous, pmm_alloc_flags, size, nullptr, nullptr)); - if (!ac.check()) { - return ZX_ERR_NO_MEMORY; + fbl::RefPtr<VmObject> vmo; + status = CreateCommon(pmm_alloc_flags, kContiguous, size, &vmo); + if (status != ZX_OK) { + return status; } if (size == 0) { @@ -209,7 +220,7 @@ zx_status_t VmObjectPaged::CreateFromWiredPages(const void* data, size_t size, b LTRACEF("data %p, size %zu\n", data, size); fbl::RefPtr<VmObject> vmo; - zx_status_t status = Create(PMM_ALLOC_FLAG_ANY, 0, size, &vmo); + zx_status_t status = CreateCommon(PMM_ALLOC_FLAG_ANY, 0, size, &vmo); if (status != ZX_OK) { return status; } @@ -272,8 +283,13 @@ zx_status_t VmObjectPaged::CreateExternal(fbl::RefPtr<PageSource> src, uint32_t } fbl::AllocChecker ac; + auto lock = fbl::AdoptRef<vm_lock_t>(new (&ac) vm_lock_t); + if (!ac.check()) { + return ZX_ERR_NO_MEMORY; + } + auto vmo = fbl::AdoptRef<VmObject>(new (&ac) VmObjectPaged( - options, PMM_ALLOC_FLAG_ANY, size, nullptr, ktl::move(src))); + options, PMM_ALLOC_FLAG_ANY, size, nullptr, ktl::move(lock), ktl::move(src))); if (!ac.check()) { return ZX_ERR_NO_MEMORY; } @@ -302,7 +318,7 @@ zx_status_t VmObjectPaged::CreateCowClone(bool resizable, uint64_t offset, uint6 // been released because we share the lock and the vmo's dtor may acquire it fbl::AllocChecker ac; auto vmo = fbl::AdoptRef<VmObjectPaged>(new (&ac) VmObjectPaged( - options, pmm_alloc_flags_, size, fbl::WrapRefPtr(this), nullptr)); + options, pmm_alloc_flags_, size, fbl::WrapRefPtr(this), lock_ptr_, nullptr)); if (!ac.check()) { return ZX_ERR_NO_MEMORY; } diff --git a/zircon/kernel/vm/vm_object_physical.cpp b/zircon/kernel/vm/vm_object_physical.cpp index aabc8ea9912f12dd2ee838a63dd966c1cecb10e1..1897912c8bf87c7705dc9bce76b8ecc0a492e1be 100644 --- a/zircon/kernel/vm/vm_object_physical.cpp +++ b/zircon/kernel/vm/vm_object_physical.cpp @@ -22,8 +22,8 @@ #define LOCAL_TRACE MAX(VM_GLOBAL_TRACE, 0) -VmObjectPhysical::VmObjectPhysical(paddr_t base, uint64_t size) - : size_(size), base_(base) { +VmObjectPhysical::VmObjectPhysical(fbl::RefPtr<vm_lock_t> lock, paddr_t base, uint64_t size) + : VmObject(nullptr, ktl::move(lock)), size_(size), base_(base) { LTRACEF("%p, size %#" PRIx64 "\n", this, size_); DEBUG_ASSERT(IS_PAGE_ALIGNED(size_)); @@ -50,7 +50,12 @@ zx_status_t VmObjectPhysical::Create(paddr_t base, uint64_t size, fbl::RefPtr<Vm } fbl::AllocChecker ac; - auto vmo = fbl::AdoptRef<VmObject>(new (&ac) VmObjectPhysical(base, size)); + auto lock = fbl::AdoptRef<vm_lock_t>(new (&ac) vm_lock_t); + if (!ac.check()) { + return ZX_ERR_NO_MEMORY; + } + + auto vmo = fbl::AdoptRef<VmObject>(new (&ac) VmObjectPhysical(ktl::move(lock), base, size)); if (!ac.check()) { return ZX_ERR_NO_MEMORY; }