blob: 69df902a073259a4f1c8c5a9031b4dc073b93966 [file] [log] [blame]
// Copyright 2018 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_HYPERVISOR_INCLUDE_HYPERVISOR_PAGE_H_
#define ZIRCON_KERNEL_HYPERVISOR_INCLUDE_HYPERVISOR_PAGE_H_
#include <vm/physmap.h>
#include <vm/pmm.h>
namespace hypervisor {
class Page {
public:
Page() = default;
DISALLOW_COPY_ASSIGN_AND_MOVE(Page);
~Page() {
if (page_ != nullptr) {
pmm_free_page(page_);
}
}
zx_status_t Alloc(uint8_t fill) {
zx_status_t status = pmm_alloc_page(0, &page_, &pa_);
if (status != ZX_OK) {
return status;
}
page_->set_state(vm_page_state::WIRED);
memset(VirtualAddress(), fill, PAGE_SIZE);
return ZX_OK;
}
void* VirtualAddress() const {
DEBUG_ASSERT(pa_ != 0);
return paddr_to_physmap(pa_);
}
template <typename T>
T* VirtualAddress() const {
return static_cast<T*>(VirtualAddress());
}
zx_paddr_t PhysicalAddress() const {
DEBUG_ASSERT(pa_ != 0);
return pa_;
}
bool IsAllocated() const { return pa_ != 0; }
private:
vm_page* page_ = nullptr;
zx_paddr_t pa_ = 0;
};
template <typename T>
class PagePtr {
public:
zx_status_t Alloc() {
zx_status_t status = page_.Alloc(0);
if (status != ZX_OK) {
return status;
}
ptr_ = page_.VirtualAddress<T>();
new (ptr_) T;
return ZX_OK;
}
zx_paddr_t PhysicalAddress() const { return page_.PhysicalAddress(); }
T* get() const { return ptr_; }
T* operator->() const { return ptr_; }
private:
Page page_;
T* ptr_;
};
} // namespace hypervisor
#endif // ZIRCON_KERNEL_HYPERVISOR_INCLUDE_HYPERVISOR_PAGE_H_