// 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

#include "context_table_state.h"

#include <ktl/unique_ptr.h>
#include <ktl/move.h>
#include <new>

#include "device_context.h"
#include "hw.h"
#include "iommu_impl.h"

namespace intel_iommu {

ContextTableState::ContextTableState(uint8_t bus, bool extended, bool upper,
                                     IommuImpl* parent, volatile ds::RootEntrySubentry* root_entry,
                                     IommuPage page)
        : parent_(parent), root_entry_(root_entry), page_(ktl::move(page)),
          bus_(bus), extended_(extended), upper_(upper) {
}

ContextTableState::~ContextTableState() {
    ds::RootEntrySubentry entry;
    entry.ReadFrom(root_entry_);
    entry.set_present(0);
    entry.WriteTo(root_entry_);

    // When modifying a present (extended) root entry, we must serially
    // invalidate the context-cache, the PASID-cache, then the IOTLB (see
    // 6.2.2.1 "Context-Entry Programming Considerations" in the VT-d spec,
    // Oct 2014 rev).
    parent_->InvalidateContextCacheGlobal();
    // TODO(teisenbe): Invalidate the PASID cache once we support those
    parent_->InvalidateIotlbGlobal();
}

zx_status_t ContextTableState::Create(uint8_t bus, bool extended, bool upper,
                                      IommuImpl* parent, volatile ds::RootEntrySubentry* root_entry,
                                      ktl::unique_ptr<ContextTableState>* table) {
    ds::RootEntrySubentry entry;
    entry.ReadFrom(root_entry);
    DEBUG_ASSERT(!entry.present());

    IommuPage page;
    zx_status_t status = IommuPage::AllocatePage(&page);
    if (status != ZX_OK) {
        return status;
    }

    fbl::AllocChecker ac;
    ktl::unique_ptr<ContextTableState> tbl(new (&ac) ContextTableState(bus, extended, upper,
                                                                       parent, root_entry,
                                                                       ktl::move(page)));
    if (!ac.check()) {
        return ZX_ERR_NO_MEMORY;
    }

    entry.set_present(1);
    entry.set_context_table(tbl->page_.paddr() >> 12);
    entry.WriteTo(root_entry);

    *table = ktl::move(tbl);
    return ZX_OK;
}

zx_status_t ContextTableState::CreateDeviceContext(ds::Bdf bdf, uint32_t domain_id,
                                                   DeviceContext** context) {
    DEBUG_ASSERT(bus_ == bdf.bus());

    ktl::unique_ptr<DeviceContext> dev;
    zx_status_t status;
    if (extended_) {
        DEBUG_ASSERT(upper_ == (bdf.dev() >= 16));
        volatile ds::ExtendedContextTable* tbl = extended_table();
        volatile ds::ExtendedContextEntry* entry = &tbl->entry[bdf.packed_dev_and_func() & 0x7f];
        status = DeviceContext::Create(bdf, domain_id, parent_, entry, &dev);
    } else {
        volatile ds::ContextTable* tbl = table();
        volatile ds::ContextEntry* entry = &tbl->entry[bdf.packed_dev_and_func()];
        status = DeviceContext::Create(bdf, domain_id, parent_, entry, &dev);
    }
    if (status != ZX_OK) {
        return status;
    }

    *context = dev.get();
    devices_.push_back(ktl::move(dev));
    return ZX_OK;
}

zx_status_t ContextTableState::GetDeviceContext(ds::Bdf bdf, DeviceContext** context) {
    for (auto& dev : devices_) {
        if (dev.is_bdf(bdf)) {
            *context = &dev;
            return ZX_OK;
        }
    }
    return ZX_ERR_NOT_FOUND;
}

} // namespace intel_iommu
