blob: 0a1f27b47b0e2bb94867a8bad5d5ef7cf23b1043 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef GARNET_BIN_GUEST_VMM_ARCH_ARM64_GIC_DISTRIBUTOR_H_
#define GARNET_BIN_GUEST_VMM_ARCH_ARM64_GIC_DISTRIBUTOR_H_
#include <limits.h>
#include <mutex>
#include <unordered_map>
#include <vector>
#include <fuchsia/sysinfo/cpp/fidl.h>
#include "garnet/bin/guest/vmm/guest_config.h"
#include "garnet/bin/guest/vmm/io.h"
#include "garnet/bin/guest/vmm/platform_device.h"
class Guest;
// Implements GIC redistributor.
class GicRedistributor : public IoHandler {
public:
GicRedistributor(uint16_t id, bool last) : id_(id), last_(last) {}
zx_status_t Read(uint64_t addr, IoValue* value) const override;
zx_status_t Write(uint64_t addr, const IoValue& value) override;
bool IsEnabled(uint32_t vector) const;
private:
uint16_t id_;
bool last_;
// Tracks whether SGIs and PPIs are enabled.
uint32_t enabled_;
};
// Implements GIC distributor.
class GicDistributor : public IoHandler, public PlatformDevice {
public:
GicDistributor(Guest* guest);
zx_status_t Init(uint8_t num_cpus,
const std::vector<InterruptSpec>& interrupts)
__TA_NO_THREAD_SAFETY_ANALYSIS;
zx_status_t Interrupt(uint32_t vector);
// |IoHandler|
zx_status_t Read(uint64_t addr, IoValue* value) const override;
zx_status_t Write(uint64_t addr, const IoValue& value) override;
// |PlatformDevice|
zx_status_t ConfigureZbi(void* zbi_base, size_t zbi_max) const override;
zx_status_t ConfigureDtb(void* dtb) const override;
private:
// NOTE: This must match the same constant in arch/hypervisor.h within Zircon.
static constexpr size_t kNumInterrupts = 256;
static constexpr uint8_t kSpiBase = 32;
Guest* guest_;
fuchsia::sysinfo::InterruptControllerType type_ =
fuchsia::sysinfo::InterruptControllerType::GIC_V2;
std::unordered_map<uint32_t, zx::interrupt> interrupts_;
mutable std::mutex mutex_;
bool affinity_routing_ __TA_GUARDED(mutex_) = false;
std::vector<GicRedistributor> __TA_GUARDED(mutex_) redistributors_;
// Tracks whether SPIs are enabled.
uint8_t enabled_[(kNumInterrupts - kSpiBase) / CHAR_BIT] __TA_GUARDED(
mutex_) = {};
// SPI routing uses these CPU masks.
uint8_t cpu_masks_[kNumInterrupts - kSpiBase] __TA_GUARDED(mutex_) = {};
zx_status_t TargetInterrupt(uint32_t vector, uint8_t cpu_mask);
zx_status_t BindVcpus(uint32_t vector, uint8_t cpu_mask);
};
#endif // GARNET_BIN_GUEST_VMM_ARCH_ARM64_GIC_DISTRIBUTOR_H_