| // 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_LIB_USERABI_INCLUDE_LIB_USERABI_VDSO_H_ |
| #define ZIRCON_KERNEL_LIB_USERABI_INCLUDE_LIB_USERABI_VDSO_H_ |
| |
| #include <lib/userabi/rodso.h> |
| #include <lib/userabi/userboot.h> |
| |
| #include <vm/vm_object.h> |
| |
| class VmMapping; |
| |
| class VDso : public RoDso { |
| public: |
| // This is called only once, at boot time. |
| // |
| // The created VDso will retain RefPtrs to the created VmObjectDispatchers, |
| // but ownership of the wrapping handles are given to the caller. |
| // |
| // The RoDso VMO is created in vmo_kernel_handles[0], with the VDso variants |
| // following. |
| static const VDso* Create(KernelHandle<VmObjectDispatcher>* vmo_kernel_handles); |
| |
| static bool vmo_is_vdso(const fbl::RefPtr<VmObject>& vmo) { |
| return likely(instance_) && instance_->vmo_is_vdso_impl(vmo); |
| } |
| |
| static bool valid_code_mapping(uint64_t vmo_offset, size_t size) { |
| return instance_->RoDso::valid_code_mapping(vmo_offset, size); |
| } |
| |
| // Given VmAspace::vdso_code_mapping_, return the vDSO base address or 0. |
| static uintptr_t base_address(const fbl::RefPtr<VmMapping>& code_mapping); |
| |
| // Forward declaration of generated class. |
| // This class is defined in the file vdso-valid-sysret.h, |
| // which is generated by scripts/gen-vdso-valid-sysret.sh. |
| // It has a static method named after each syscall: |
| // static bool <syscall-name>(uintptr_t offset); |
| // This tests whether <start of vDSO code>+offset is a valid PC |
| // for entering the kernel with <syscall-name>'s syscall number. |
| struct ValidSyscallPC; |
| |
| private: |
| using Variant = userboot::VdsoVariant; |
| |
| VDso(KernelHandle<VmObjectDispatcher>* vmo_kernel_handles); |
| void CreateVariant(Variant, KernelHandle<VmObjectDispatcher>* vmo_kernel_handle); |
| |
| bool vmo_is_vdso_impl(const fbl::RefPtr<VmObject>& vmo_ref) const { |
| if (vmo_ref == vmo()->vmo()) |
| return true; |
| for (const auto& v : variant_vmo_) { |
| if (vmo_ref == v->vmo()) |
| return true; |
| } |
| return false; |
| } |
| |
| static constexpr size_t variant_index(Variant v) { |
| DEBUG_ASSERT(v > Variant::FULL); |
| return static_cast<size_t>(v) - 1; |
| } |
| |
| fbl::RefPtr<VmObjectDispatcher> variant_vmo_[static_cast<size_t>(Variant::COUNT) - 1]; |
| |
| static const VDso* instance_; |
| }; |
| |
| #endif // ZIRCON_KERNEL_LIB_USERABI_INCLUDE_LIB_USERABI_VDSO_H_ |