blob: b0221a12c19a552d26a096f57360dbdc47988136 [file] [log] [blame]
Daniel Boulbyf3cf28c2024-08-22 10:46:23 +01001/*
2 * Copyright 2024 The Hafnium Authors.
3 *
4 * Use of this source code is governed by a BSD-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/BSD-3-Clause.
7 */
8
9#include "hf/hf_ipi.h"
10
11#include "hf/cpu.h"
12#include "hf/plat/interrupts.h"
13
14/** Interrupt priority for Inter-Processor Interrupt. */
15#define IPI_PRIORITY 0x0U
16
17/**
18 * Initialize the IPI SGI.
19 */
20void hf_ipi_init_interrupt(void)
21{
22 /* Configure as a Secure SGI. */
23 struct interrupt_descriptor ipi_desc = {
24 .interrupt_id = HF_IPI_INTID,
25 .type = INT_DESC_TYPE_SGI,
26 .sec_state = INT_DESC_SEC_STATE_S,
27 .priority = IPI_PRIORITY,
28 .valid = true,
29 };
30
31 plat_interrupts_configure_interrupt(ipi_desc);
32}
33
34/**
35 * Returns the target_vcpu for the pending IPI on the current CPU and
36 * resets the item in the list to NULL to show it has been retrieved.
37 */
38struct vcpu *hf_ipi_get_pending_target_vcpu(struct cpu *current)
39{
40 struct vcpu *ret = current->ipi_target_vcpu;
41
42 current->ipi_target_vcpu = NULL;
43 return ret;
44}
45
46/**
47 * Send and record the IPI for the target vCPU.
48 */
49void hf_ipi_send_interrupt(struct vm *vm, ffa_vcpu_index_t target_vcpu_index)
50{
51 struct vcpu *target_vcpu = vm_get_vcpu(vm, target_vcpu_index);
52 struct cpu *target_cpu = target_vcpu->cpu;
53
54 target_cpu->ipi_target_vcpu = target_vcpu;
55 plat_interrupts_send_sgi(HF_IPI_INTID, target_cpu, true);
56}
57
58/**
59 * IPI IRQ specific handling for the secure interrupt for each vCPU state:
60 * - RUNNING: Continue secure interrupt handling as normal, injecting
61 * a virtual interrupt to the vCPU.
62 * - Other states are not currently supported so exit the handler.
63 * Returns True if the IPI SGI has been handled.
64 * False if further secure interrupt handling is required.
65 */
66bool hf_ipi_handle(struct vcpu_locked target_vcpu_locked)
67{
68 struct vcpu *target_vcpu = target_vcpu_locked.vcpu;
69
70 switch (target_vcpu->state) {
71 case VCPU_STATE_RUNNING:
72 return false;
73 default:
74 dlog_verbose(
75 "IPIs not currently supported for when the target_vcpu "
76 "is in the state %d\n",
77 target_vcpu->state);
78 /*
79 * Mark the interrupt as completed so it can be signalled again.
80 */
81 plat_interrupts_end_of_interrupt(HF_IPI_INTID);
82 return true;
83 }
84}