blob: 43346898a522663ae8d26ddb95b5364b67906d7f [file] [log] [blame]
// 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
#pragma once
#include <lib/rodso.h>
#include <vm/vm_object.h>
class VmMapping;
class VDso : public RoDso {
public:
// This is called only once, at boot time.
static const VDso* Create();
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;
enum class Variant {
FULL,
TEST1,
TEST2,
COUNT
};
static constexpr size_t variants() {
return static_cast<size_t>(Variant::COUNT);
}
// Return a handle to the VMO for the given variant.
HandleOwner vmo_handle(Variant) const;
private:
VDso();
void CreateVariant(Variant);
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_;
};