Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/arch/arm64/kvm/hyp/nvhe/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 4 kB image not shown  

Quelle  stacktrace.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * KVM nVHE hypervisor stack tracing support.
 *
 * Copyright (C) 2022 Google LLC
 */

#include <asm/kvm_asm.h>
#include <asm/kvm_hyp.h>
#include <asm/memory.h>
#include <asm/percpu.h>

DEFINE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], overflow_stack)
 __aligned(16);

DEFINE_PER_CPU(struct kvm_nvhe_stacktrace_info, kvm_stacktrace_info);

/*
 * hyp_prepare_backtrace - Prepare non-protected nVHE backtrace.
 *
 * @fp : frame pointer at which to start the unwinding.
 * @pc : program counter at which to start the unwinding.
 *
 * Save the information needed by the host to unwind the non-protected
 * nVHE hypervisor stack in EL1.
 */

static void hyp_prepare_backtrace(unsigned long fp, unsigned long pc)
{
 struct kvm_nvhe_stacktrace_info *stacktrace_info = this_cpu_ptr(&kvm_stacktrace_info);
 struct kvm_nvhe_init_params *params = this_cpu_ptr(&kvm_init_params);

 stacktrace_info->stack_base = (unsigned long)(params->stack_hyp_va - NVHE_STACK_SIZE);
 stacktrace_info->overflow_stack_base = (unsigned long)this_cpu_ptr(overflow_stack);
 stacktrace_info->fp = fp;
 stacktrace_info->pc = pc;
}

#ifdef CONFIG_PROTECTED_NVHE_STACKTRACE
#include <asm/stacktrace/nvhe.h>

DEFINE_PER_CPU(unsigned long [NVHE_STACKTRACE_SIZE/sizeof(long)], pkvm_stacktrace);

static struct stack_info stackinfo_get_overflow(void)
{
 unsigned long low = (unsigned long)this_cpu_ptr(overflow_stack);
 unsigned long high = low + OVERFLOW_STACK_SIZE;

 return (struct stack_info) {
  .low = low,
  .high = high,
 };
}

static struct stack_info stackinfo_get_hyp(void)
{
 struct kvm_nvhe_init_params *params = this_cpu_ptr(&kvm_init_params);
 unsigned long high = params->stack_hyp_va;
 unsigned long low = high - NVHE_STACK_SIZE;

 return (struct stack_info) {
  .low = low,
  .high = high,
 };
}

static int unwind_next(struct unwind_state *state)
{
 return unwind_next_frame_record(state);
}

static void notrace unwind(struct unwind_state *state,
      stack_trace_consume_fn consume_entry,
      void *cookie)
{
 while (1) {
  int ret;

  if (!consume_entry(cookie, state->pc))
   break;
  ret = unwind_next(state);
  if (ret < 0)
   break;
 }
}

/*
 * pkvm_save_backtrace_entry - Saves a protected nVHE HYP stacktrace entry
 *
 * @arg    : index of the entry in the stacktrace buffer
 * @where  : the program counter corresponding to the stack frame
 *
 * Save the return address of a stack frame to the shared stacktrace buffer.
 * The host can access this shared buffer from EL1 to dump the backtrace.
 */

static bool pkvm_save_backtrace_entry(void *arg, unsigned long where)
{
 unsigned long *stacktrace = this_cpu_ptr(pkvm_stacktrace);
 int *idx = (int *)arg;

 /*
 * Need 2 free slots: 1 for current entry and 1 for the
 * delimiter.
 */

 if (*idx > ARRAY_SIZE(pkvm_stacktrace) - 2)
  return false;

 stacktrace[*idx] = where;
 stacktrace[++*idx] = 0UL;

 return true;
}

/*
 * pkvm_save_backtrace - Saves the protected nVHE HYP stacktrace
 *
 * @fp : frame pointer at which to start the unwinding.
 * @pc : program counter at which to start the unwinding.
 *
 * Save the unwinded stack addresses to the shared stacktrace buffer.
 * The host can access this shared buffer from EL1 to dump the backtrace.
 */

static void pkvm_save_backtrace(unsigned long fp, unsigned long pc)
{
 struct stack_info stacks[] = {
  stackinfo_get_overflow(),
  stackinfo_get_hyp(),
 };
 struct unwind_state state = {
  .stacks = stacks,
  .nr_stacks = ARRAY_SIZE(stacks),
 };
 int idx = 0;

 kvm_nvhe_unwind_init(&state, fp, pc);

 unwind(&state, pkvm_save_backtrace_entry, &idx);
}
#else /* !CONFIG_PROTECTED_NVHE_STACKTRACE */
static void pkvm_save_backtrace(unsigned long fp, unsigned long pc)
{
}
#endif /* CONFIG_PROTECTED_NVHE_STACKTRACE */

/*
 * kvm_nvhe_prepare_backtrace - prepare to dump the nVHE backtrace
 *
 * @fp : frame pointer at which to start the unwinding.
 * @pc : program counter at which to start the unwinding.
 *
 * Saves the information needed by the host to dump the nVHE hypervisor
 * backtrace.
 */

void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc)
{
 if (is_protected_kvm_enabled())
  pkvm_save_backtrace(fp, pc);
 else
  hyp_prepare_backtrace(fp, pc);
}

Messung V0.5
C=96 H=90 G=93

¤ Dauer der Verarbeitung: 0.23 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.