| // Copyright 2016 The Fuchsia Authors |
| // |
| // Use of this source code is governed by a MIT-style |
| // license that can be found in the LICENSE file or at |
| // https://opensource.org/licenses/MIT |
| |
| #ifndef ZIRCON_KERNEL_OBJECT_INCLUDE_OBJECT_VM_OBJECT_DISPATCHER_H_ |
| #define ZIRCON_KERNEL_OBJECT_INCLUDE_OBJECT_VM_OBJECT_DISPATCHER_H_ |
| |
| #include <lib/user_copy/user_iovec.h> |
| #include <lib/user_copy/user_ptr.h> |
| #include <lib/zx/result.h> |
| #include <sys/types.h> |
| #include <zircon/rights.h> |
| #include <zircon/types.h> |
| |
| #include <fbl/canary.h> |
| #include <fbl/intrusive_container_utils.h> |
| #include <fbl/intrusive_double_list.h> |
| #include <ktl/atomic.h> |
| #include <ktl/limits.h> |
| #include <object/dispatcher.h> |
| #include <object/handle.h> |
| #include <vm/content_size_manager.h> |
| #include <vm/vm_object.h> |
| |
| class VmObjectDispatcher final : public SoloDispatcher<VmObjectDispatcher, ZX_DEFAULT_VMO_RIGHTS>, |
| public VmObjectChildObserver { |
| public: |
| enum class InitialMutability { kMutable, kImmutable }; |
| |
| struct CreateStats { |
| uint32_t flags; |
| size_t size; |
| }; |
| |
| static zx::result<CreateStats> parse_create_syscall_flags(uint32_t flags, size_t size); |
| |
| static zx_status_t Create(fbl::RefPtr<VmObject> vmo, |
| fbl::RefPtr<ContentSizeManager> content_size_manager, |
| InitialMutability initial_mutability, |
| KernelHandle<VmObjectDispatcher>* handle, zx_rights_t* rights) { |
| return Create(ktl::move(vmo), ktl::move(content_size_manager), ZX_KOID_INVALID, |
| initial_mutability, handle, rights); |
| } |
| |
| static zx_status_t Create(fbl::RefPtr<VmObject> vmo, |
| fbl::RefPtr<ContentSizeManager> content_size_manager, |
| zx_koid_t pager_koid, InitialMutability initial_mutability, |
| KernelHandle<VmObjectDispatcher>* handle, zx_rights_t* rights); |
| ~VmObjectDispatcher() final; |
| |
| // VmObjectChildObserver implementation. |
| void OnZeroChild() final; |
| |
| // SoloDispatcher implementation. |
| zx_obj_type_t get_type() const final { return ZX_OBJ_TYPE_VMO; } |
| [[nodiscard]] zx_status_t get_name(char (&out_name)[ZX_MAX_NAME_LEN]) const final; |
| [[nodiscard]] zx_status_t set_name(const char* name, size_t len) final; |
| |
| // Dispatcher implementation. |
| void on_zero_handles() final; |
| |
| ContentSizeManager* content_size_manager() const { return content_size_mgr_.get(); } |
| |
| // VmObjectDispatcher own methods. |
| zx_status_t Read(user_out_ptr<char> user_data, size_t length, uint64_t offset, |
| size_t* out_actual); |
| zx_status_t ReadVector(user_out_iovec_t user_data, size_t length, uint64_t offset, |
| size_t* out_actual); |
| zx_status_t Write(user_in_ptr<const char> user_data, size_t length, uint64_t offset, |
| size_t* out_actual, |
| VmObject::OnWriteBytesTransferredCallback on_bytes_transferred = nullptr); |
| zx_status_t WriteVector(user_in_iovec_t user_data, size_t length, uint64_t offset, |
| size_t* out_actual, |
| VmObject::OnWriteBytesTransferredCallback on_bytes_transferred = nullptr); |
| zx_status_t SetSize(uint64_t); |
| zx_status_t GetSize(uint64_t* size); |
| zx_status_t RangeOp(uint32_t op, uint64_t offset, uint64_t size, user_inout_ptr<void> buffer, |
| size_t buffer_size, zx_rights_t rights); |
| zx_status_t CreateChild(uint32_t options, uint64_t offset, uint64_t size, bool copy_name, |
| fbl::RefPtr<VmObject>* child_vmo); |
| |
| zx_status_t SetMappingCachePolicy(uint32_t cache_policy); |
| |
| zx_info_vmo_t GetVmoInfo(zx_rights_t rights); |
| |
| zx_status_t SetContentSize(uint64_t); |
| uint64_t GetContentSize() const; |
| |
| // Tries to expand the VMO to a requested (byte-aligned) size, if the VMO is smaller than that |
| // size. Whether the VMO can be expanded is controlled by |can_resize_vmo|. Note that this will |
| // not modify the content size. |
| // |
| // Returns the actual size of the VMO in |out_actual| after attempting to expand. This value is |
| // set, even in the case of a failure. |
| zx_status_t ExpandIfNecessary(uint64_t requested_vmo_size, bool can_resize_vmo, |
| uint64_t* out_actual); |
| |
| const fbl::RefPtr<VmObject>& vmo() const { return vmo_; } |
| zx_koid_t pager_koid() const { return pager_koid_; } |
| |
| private: |
| explicit VmObjectDispatcher(fbl::RefPtr<VmObject> vmo, |
| fbl::RefPtr<ContentSizeManager> content_size_manager, |
| zx_koid_t pager_koid, InitialMutability initial_mutability); |
| |
| zx_status_t CreateChildInternal(uint32_t options, uint64_t offset, uint64_t size, bool copy_name, |
| fbl::RefPtr<VmObject>* child_vmo) TA_REQ(get_lock()); |
| |
| // The 'const' here is load bearing; we give a raw pointer to |
| // ourselves to |vmo_| so we have to ensure we don't reset vmo_ |
| // except during destruction. |
| fbl::RefPtr<VmObject> const vmo_; |
| |
| // Manages the content size associated with this VMO. The content size is used by streams created |
| // against this VMO. |
| fbl::RefPtr<ContentSizeManager> const content_size_mgr_; |
| |
| // The koid of the related pager object, or ZX_KOID_INVALID if |
| // there is no related pager. |
| const zx_koid_t pager_koid_; |
| |
| // Indicates whether the VMO was immutable at creation time. |
| const InitialMutability initial_mutability_; |
| }; |
| |
| enum class VmoOwnership { kHandle, kMapping, kIoBuffer }; |
| zx_info_vmo_t VmoToInfoEntry(const VmObject* vmo, VmoOwnership ownership, |
| zx_rights_t handle_rights); |
| |
| #endif // ZIRCON_KERNEL_OBJECT_INCLUDE_OBJECT_VM_OBJECT_DISPATCHER_H_ |