// Copyright 2021 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_INCLUDE_KERNEL_RESTRICTED_STATE_H_
#define ZIRCON_KERNEL_INCLUDE_KERNEL_RESTRICTED_STATE_H_

#include <lib/user_copy/internal.h>
#include <lib/zx/result.h>
#include <zircon/syscalls-next.h>

#include <arch/exception.h>
#include <arch/regs.h>
#include <fbl/macros.h>
#include <fbl/ref_ptr.h>
#include <ktl/unique_ptr.h>

// Per thread state to support restricted mode.
// Intentionally kept simple to keep the amount of kernel/thread.h dependencies to a minimum.

class VmObjectPaged;
class VmMapping;

// Must provide a definition of struct ArchSavedNormalState
#include <arch/restricted.h>

// Encapsulates a thread's restricted mode state.
//
// Note everything in this class should be accessed only by the thread that it belongs to,
// since there is no internal locking for efficiency reasons.
class RestrictedState {
 public:
  static zx::result<ktl::unique_ptr<RestrictedState>> Create();

  ~RestrictedState();
  DISALLOW_COPY_ASSIGN_AND_MOVE(RestrictedState);

  bool in_restricted() const { return in_restricted_; }
  uintptr_t vector_ptr() const { return vector_ptr_; }
  uintptr_t context() const { return context_; }
  bool in_thread_exceptions_enabled() const { return in_thread_exceptions_enabled_; }
  const ArchSavedNormalState& arch_normal_state() const { return arch_; }
  ArchSavedNormalState& arch_normal_state() { return arch_; }
  template <typename T>
  T* state_ptr_as() const {
    static_assert(internal::is_copy_allowed<T>::value);
    return reinterpret_cast<T*>(state_mapping_ptr_);
  }
  zx_restricted_state_t* state_ptr() const { return state_ptr_as<zx_restricted_state_t>(); }

  fbl::RefPtr<VmObjectPaged> vmo() const;

  void set_in_restricted(bool r) { in_restricted_ = r; }
  void set_vector_ptr(uintptr_t v) { vector_ptr_ = v; }
  void set_context(uintptr_t c) { context_ = c; }
  void set_in_thread_exceptions_enabled(bool enable) { in_thread_exceptions_enabled_ = enable; }

  // Each arch must fill out the following routines prefixed with Arch:
  //
  // Prior to entering restricted mode, ask the arch layer to validate the saved register state is
  // valid. Return ZX_OK if valid.
  // Possible invalid states: program counter outside of user space, invalid processor flags, etc.
  static zx_status_t ArchValidateStatePreRestrictedEntry(const zx_restricted_state_t& state);

  // Just prior to entering restricted mode, give the arch layer a chance to save any state it
  // may need for the return trip back to normal mode into the ArchSavedNormalState state argument.
  // For example, the GS/FS base is saved here for x86.
  static void ArchSaveStatePreRestrictedEntry(ArchSavedNormalState& state);

  // Use an architcturally-specific mechanism to directly enter user space in restricted mode.
  // Does not return.
  [[noreturn]] static void ArchEnterRestricted(const zx_restricted_state_t& state);

  // Having just exited from restricted mode via a syscall, save the necessary restricted mode
  // state from a pointer to the syscall state saved by the exception handler.
  static void ArchSaveRestrictedSyscallState(zx_restricted_state_t& state,
                                             const syscall_regs_t& regs);

  // Having just exited from restricted mode via an interrupt, save the necessary restricted mode
  // state from a pointer to the interrupt frame state saved by the exception handler.
  static void ArchSaveRestrictedIframeState(zx_restricted_state_t& state, const iframe_t& frame);

  // Having exited from restricted mode via a synchronous exception, save the necessary
  // restricted mode state.
  static void ArchSaveRestrictedExceptionState(zx_restricted_state_t& state);

  // Update the exception context so that we will return to normal mode to allow normal
  // mode to handle a restricted exception.
  static void ArchRedirectRestrictedExceptionToNormal(const ArchSavedNormalState& arch_state,
                                                      uintptr_t vector_table, uintptr_t context);
  // Enter normal mode at the address pointed to by vector_table with arguments code and context
  // in an architecturally specific register in an architecturally specific way.
  [[noreturn]] static void ArchEnterFull(const ArchSavedNormalState& arch_state,
                                         uintptr_t vector_table, uintptr_t context, uint64_t code);

  // Dump the architecturally specific state out of the restricted mode state
  static void ArchDump(const zx_restricted_state_t& state);

 private:
  RestrictedState(fbl::RefPtr<VmObjectPaged> state_vmo, fbl::RefPtr<VmMapping> state_mapping);

  bool in_restricted_ = false;
  bool in_thread_exceptions_enabled_ = false;
  uintptr_t vector_ptr_ = 0;
  uintptr_t context_ = 0;

  // Ref pointer to a vmo holding the restricted state and a kernel mapping of the first page.
  const fbl::RefPtr<VmObjectPaged> state_vmo_;
  const fbl::RefPtr<VmMapping> state_mapping_;

  // Cached pointer to the mapping, to avoid needing to deref the mapping on every access.
  void* const state_mapping_ptr_ = nullptr;

  // Arch specific part of the save state
  ArchSavedNormalState arch_;
};

#endif  // ZIRCON_KERNEL_INCLUDE_KERNEL_RESTRICTED_STATE_H_
