// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cheriot/cheriot_ibex_hw_revoker.h"

#include <cstdint>
#include <cstring>

#include "absl/log/log.h"
#include "cheriot/cheriot_register.h"
#include "mpact/sim/generic/data_buffer.h"
#include "mpact/sim/generic/instruction.h"
#include "mpact/sim/generic/ref_count.h"
#include "mpact/sim/util/memory/memory_interface.h"
#include "mpact/sim/util/memory/tagged_memory_interface.h"
#include "riscv//riscv_plic.h"

namespace mpact {
namespace sim {
namespace cheriot {

using ::mpact::sim::generic::DataBuffer;
using ::mpact::sim::generic::Instruction;
using ::mpact::sim::generic::ReferenceCount;
using ::mpact::sim::riscv::RiscVPlicIrqInterface;
using ::mpact::sim::util::MemoryInterface;
using ::mpact::sim::util::TaggedMemoryInterface;

CheriotIbexHWRevoker::CheriotIbexHWRevoker(RiscVPlicIrqInterface *plic_irq,
                                           uint64_t heap_base,
                                           uint64_t heap_size,
                                           TaggedMemoryInterface *heap_memory,
                                           uint64_t revocation_bits_base,
                                           MemoryInterface *revocation_memory)
    : plic_irq_(plic_irq),
      heap_base_(heap_base),
      heap_max_(heap_base + heap_size),
      heap_memory_(heap_memory),
      revocation_memory_(revocation_memory),
      revocation_bits_base_(revocation_bits_base) {
  cap_reg_ = new CheriotRegister(nullptr, "filter_cap");
  db_ = db_factory_.Allocate<uint32_t>(2);
  db_->Set<uint32_t>(0, 0);
  db_->Set<uint32_t>(1, 0);
  db_->set_latency(0);
  cap_reg_->SetDataBuffer(db_);
  db_->DecRef();
  // Allocate data buffers used in loads/stores.
  db_ = db_factory_.Allocate<uint8_t>(CheriotRegister::kCapabilitySizeInBytes);
  db_->set_latency(0);
  tag_db_ = db_factory_.Allocate<uint8_t>(1);
  tag_db_->set_latency(0);
  Reset();
}

CheriotIbexHWRevoker::CheriotIbexHWRevoker(uint64_t heap_base,
                                           uint64_t heap_size,
                                           TaggedMemoryInterface *heap_memory,
                                           uint64_t revocation_bits_base,
                                           MemoryInterface *revocation_memory)
    : CheriotIbexHWRevoker(nullptr, heap_base, heap_size, heap_memory,
                           revocation_bits_base, revocation_memory) {}

CheriotIbexHWRevoker::~CheriotIbexHWRevoker() {
  delete cap_reg_;
  db_->DecRef();
  tag_db_->DecRef();
}

// Reset state to initial values.
void CheriotIbexHWRevoker::Reset() {
  num_calls_ = 0;
  start_address_ = 0;
  end_address_ = 0;
  go_ = 0;
  epoch_ = 0;
  interrupt_enable_ = 0;
  interrupt_status_ = 0;
}

// This is called by the counter using the CounterValueSetInterface interface.
void CheriotIbexHWRevoker::SetValue(const uint64_t &val) {
  if (interrupt_status_) SetInterrupt(false);
  if (!sweep_in_progress_) return;
  num_calls_++;
  if (num_calls_ >= period_) {
    num_calls_ = 0;
    Revoke();
  }
}

// Reads from the MMRs.
void CheriotIbexHWRevoker::Load(uint64_t address, DataBuffer *db,
                                DataBuffer *tags, Instruction *inst,
                                ReferenceCount *context) {
  if (tags != nullptr) std::memset(tags->raw_ptr(), 0, tags->size<uint8_t>());
  Load(address, db, inst, context);
}

// Reads from the MMRs.
void CheriotIbexHWRevoker::Load(uint64_t address, DataBuffer *db,
                                Instruction *inst, ReferenceCount *context) {
  uint32_t offset = address & 0xffff;
  switch (db->size<uint8_t>()) {
    case 1:
      db->Set<uint32_t>(0, static_cast<uint8_t>(Read(offset)));
      break;
    case 2:
      db->Set<uint32_t>(0, static_cast<uint16_t>(Read(offset)));
      break;
    case 4:
      db->Set<uint32_t>(0, static_cast<uint32_t>(Read(offset)));
      break;
    case 8:
      db->Set<uint32_t>(0, static_cast<uint64_t>(Read(offset)));
      break;
    default:
      ::memset(db->raw_ptr(), 0, sizeof(db->size<uint8_t>()));
      break;
  }
  // Execute the instruction to process and write back the load data.
  if (nullptr != inst) {
    if (db->latency() > 0) {
      inst->IncRef();
      if (context != nullptr) context->IncRef();
      inst->state()->function_delay_line()->Add(db->latency(),
                                                [inst, context]() {
                                                  inst->Execute(context);
                                                  if (context != nullptr)
                                                    context->DecRef();
                                                  inst->DecRef();
                                                });
    } else {
      inst->Execute(context);
    }
  }
}

// Vector load is not supported.
void CheriotIbexHWRevoker::Load(DataBuffer *address_db, DataBuffer *mask_db,
                                int el_size, DataBuffer *db, Instruction *inst,
                                ReferenceCount *context) {
  // This is left unimplemented. Vector load is not supported.
  LOG(FATAL) << "Vector load not supported";  // Crash OK
}

// Writes to the MMRs.
void CheriotIbexHWRevoker::Store(uint64_t address, DataBuffer *db,
                                 DataBuffer *tags) {
  Store(address, db);
}

// Writes to the MMRs.
void CheriotIbexHWRevoker::Store(uint64_t address, DataBuffer *db) {
  uint32_t offset = address & 0xffff;
  switch (db->size<uint8_t>()) {
    case 1:
      return Write(offset, static_cast<uint32_t>(db->Get<uint8_t>(0)));
    case 2:
      return Write(offset, static_cast<uint32_t>(db->Get<uint16_t>(0)));
    case 4:
      return Write(offset, static_cast<uint32_t>(db->Get<uint32_t>(0)));
    case 8:
      return Write(offset, static_cast<uint32_t>(db->Get<uint32_t>(0)));
      return Write(offset + 4, static_cast<uint32_t>(db->Get<uint32_t>(1)));
    default:
      return;
  }
}

// Vector accesses are not supported.
void CheriotIbexHWRevoker::Store(DataBuffer *address, DataBuffer *mask,
                                 int el_size, DataBuffer *db) {
  // This is left unimplemented. Vector store is not supported.
  LOG(FATAL) << "Vector store not supported";  // Crash OK
}

uint32_t CheriotIbexHWRevoker::Read(uint32_t offset) {
  uint32_t value = 0;
  switch (offset) {
    case kStartAddressOffset:  // start address
      value = start_address_;
      break;
    case kEndAddressOffset:  // end address
      value = end_address_;
      break;
    case kGoOffset:  // go
      value = 0x5500'0000 | (go_ & 0x00ff'ffff);
      break;
    case kEpochOffset:  // epoch
      value = (epoch_ << 1) | (sweep_in_progress_ ? 0b1 : 0b0);
      break;
    case kStatusOffset:  // stat q
      value = interrupt_enable_ ? interrupt_status_ : 0;
      break;
    case kInterruptEnableOffset:  // interrupt enable
      value = interrupt_enable_ & 0b1;
      break;
    default:
      value = 0;
      break;
  }
  return value;
}

// Vector store is not supported.
void CheriotIbexHWRevoker::Write(uint32_t offset, uint32_t value) {
  switch (offset) {
    case kStartAddressOffset:  // start address
      start_address_ = value;
      break;
    case kEndAddressOffset:  // end address
      end_address_ = value;
      break;
    case kGoOffset:  // go
      WriteGo();
      go_ = value;
      break;
    // 0x000c:  Epoch is not writable.
    case kStatusOffset:
      interrupt_status_ = 0;
      plic_irq_->SetIrq(false);
      break;
    case kInterruptEnableOffset:  // interrupt enable
      interrupt_enable_ = value & 0b1;
      ;
      break;
    default:
      return;
  }
}

void CheriotIbexHWRevoker::WriteGo() {
  if (sweep_in_progress_) return;
  sweep_in_progress_ = true;
  current_cap_ = 0;
  num_calls_ = 0;
  epoch_ = 0;
}

void CheriotIbexHWRevoker::Revoke() {
  if (!sweep_in_progress_) return;
  uint64_t cap_address = start_address_ + (current_cap_++ << 3);
  // Align address to the capability size.
  cap_address &= ~0b111ULL;
  ProcessCapability(cap_address);
  // Check to see if we have reached the end of the region.
  if (cap_address >= end_address_) {
    // Increment the epoch.
    epoch_++;
    sweep_in_progress_ = false;
    SetInterrupt(true);
  }
}

// Process the capability at the given address.
void CheriotIbexHWRevoker::ProcessCapability(uint64_t address) {
  if ((address < start_address_) || (address >= end_address_)) return;
  // Load the capability.
  heap_memory_->Load(address, db_, tag_db_, nullptr, nullptr);
  // If the tag is 0, no need to go on.
  auto tag = tag_db_->Get<uint8_t>(0);
  if (tag == 0) return;

  // Expand the capability. Return if the tag is not valid.
  cap_reg_->Expand(db_->Get<uint32_t>(0), db_->Get<uint32_t>(1), tag);
  if (!cap_reg_->tag()) return;

  // Check for revocation.
  if (!MustRevoke(cap_reg_->base())) return;

  // Invalidate and store the capability back to memory.
  cap_reg_->Invalidate();
  db_->Set<uint32_t>(0, cap_reg_->address());
  db_->Set<uint32_t>(1, cap_reg_->Compress());
  tag_db_->Set<uint8_t>(0, cap_reg_->tag());
  heap_memory_->Store(address, db_, tag_db_);
}

// Check if the capability must be revoked.
bool CheriotIbexHWRevoker::MustRevoke(uint64_t address) {
  if (address < heap_base_) return false;
  if (address >= heap_max_) return false;
  // Compute the address of the byte containing the revocation information.
  uint64_t offset = address - heap_base_;
  // Shift by 3 for the size of the capability (8), and by 3 for 8 bits in a
  // byte.
  uint64_t revocation_offset = offset >> 6;
  revocation_memory_->Load(revocation_bits_base_ + revocation_offset, tag_db_,
                           nullptr, nullptr);
  // Get the revocation bit.
  uint8_t revocation_bits = tag_db_->Get<uint8_t>(0);
  int bit_offset = (offset >> 3) & 0b111;
  bool result = revocation_bits & (1 << bit_offset);
  return result;
}

void CheriotIbexHWRevoker::SetInterrupt(bool value) {
  if (!value) {
    plic_irq_->SetIrq(false);
    interrupt_status_ = 0;
    return;
  }
  interrupt_status_ = static_cast<uint32_t>(value);

  if (!interrupt_enable_) return;

  if (plic_irq_ != nullptr) plic_irq_->SetIrq(value);
}

}  // namespace cheriot
}  // namespace sim
}  // namespace mpact
