blob: 30ba21b73e23b38e69b484c424a6e25895212858 [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
#pragma once
#include <fbl/intrusive_double_list.h>
#include <fbl/macros.h>
#include <fbl/unique_ptr.h>
#include <vm/vm_object.h>
#include "hw.h"
#include "second_level_pt.h"
namespace intel_iommu {
class IommuImpl;
class DeviceContext : public fbl::DoublyLinkedListable<fbl::unique_ptr<DeviceContext>> {
public:
~DeviceContext();
// Create a new DeviceContext representing the given BDF. It is a fatal error
// to try to create a context for a BDF that already has one.
static zx_status_t Create(ds::Bdf bdf, uint32_t domain_id, IommuImpl* parent,
volatile ds::ExtendedContextEntry* context_entry,
fbl::unique_ptr<DeviceContext>* device);
static zx_status_t Create(ds::Bdf bdf, uint32_t domain_id, IommuImpl* parent,
volatile ds::ContextEntry* context_entry,
fbl::unique_ptr<DeviceContext>* device);
// Check if this DeviceContext is for the given BDF
bool is_bdf(ds::Bdf bdf) const {
return bdf_ == bdf;
}
uint32_t domain_id() const { return domain_id_; }
// Use the second-level translation table to map the host pages in the given
// range on |vmo| to the guest's address |*virt_paddr|. |size| is in bytes.
// |mapped_len| may be larger than |size|, if |size| was not page-aligned.
//
// This function may return a partial mapping, in which case |mapped_len|
// will indicate how many bytes were actually mapped.
zx_status_t SecondLevelMap(const fbl::RefPtr<VmObject>& vmo,
uint64_t offset, size_t size, uint32_t perms,
paddr_t* virt_paddr, size_t* mapped_len);
zx_status_t SecondLevelUnmap(paddr_t virt_paddr, size_t size);
private:
DeviceContext(ds::Bdf bdf, uint32_t domain_id, IommuImpl* parent,
volatile ds::ExtendedContextEntry* context_entry);
DeviceContext(ds::Bdf bdf, uint32_t domain_id, IommuImpl* parent,
volatile ds::ContextEntry* context_entry);
DISALLOW_COPY_ASSIGN_AND_MOVE(DeviceContext);
IommuImpl* const parent_;
union {
volatile ds::ExtendedContextEntry* const extended_context_entry_;
volatile ds::ContextEntry* const context_entry_;
};
// Page tables used for translating requests-without-PASID and for nested
// translation of requests-with-PASID.
SecondLevelPageTable second_level_pt_;
const ds::Bdf bdf_;
const bool extended_;
const uint32_t domain_id_;
};
} // namespace intel_iommu