blob: 0964c13ff75bc60c8cf5e4136f2b511845ba9796 [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"
Karl Meakin902af082024-11-28 14:58:38 +000012#include "hf/ffa/notifications.h"
Daniel Boulbyf3cf28c2024-08-22 10:46:23 +010013#include "hf/plat/interrupts.h"
14
15/** Interrupt priority for Inter-Processor Interrupt. */
16#define IPI_PRIORITY 0x0U
17
18/**
19 * Initialize the IPI SGI.
20 */
21void hf_ipi_init_interrupt(void)
22{
23 /* Configure as a Secure SGI. */
24 struct interrupt_descriptor ipi_desc = {
25 .interrupt_id = HF_IPI_INTID,
26 .type = INT_DESC_TYPE_SGI,
27 .sec_state = INT_DESC_SEC_STATE_S,
28 .priority = IPI_PRIORITY,
29 .valid = true,
Daniel Boulby84d49b62024-11-04 18:25:59 +000030 .enabled = true,
Daniel Boulbyf3cf28c2024-08-22 10:46:23 +010031 };
32
33 plat_interrupts_configure_interrupt(ipi_desc);
34}
35
36/**
37 * Returns the target_vcpu for the pending IPI on the current CPU and
38 * resets the item in the list to NULL to show it has been retrieved.
39 */
40struct vcpu *hf_ipi_get_pending_target_vcpu(struct cpu *current)
41{
Daniel Boulby84d49b62024-11-04 18:25:59 +000042 struct vcpu *ret;
43
44 sl_lock(&current->lock);
45
46 ret = current->ipi_target_vcpu;
Daniel Boulbyf3cf28c2024-08-22 10:46:23 +010047
48 current->ipi_target_vcpu = NULL;
Daniel Boulby84d49b62024-11-04 18:25:59 +000049
50 sl_unlock(&current->lock);
51
Daniel Boulbyf3cf28c2024-08-22 10:46:23 +010052 return ret;
53}
54
55/**
56 * Send and record the IPI for the target vCPU.
57 */
58void hf_ipi_send_interrupt(struct vm *vm, ffa_vcpu_index_t target_vcpu_index)
59{
60 struct vcpu *target_vcpu = vm_get_vcpu(vm, target_vcpu_index);
61 struct cpu *target_cpu = target_vcpu->cpu;
62
Daniel Boulby84d49b62024-11-04 18:25:59 +000063 sl_lock(&target_cpu->lock);
64
Daniel Boulbyf3cf28c2024-08-22 10:46:23 +010065 target_cpu->ipi_target_vcpu = target_vcpu;
Daniel Boulby84d49b62024-11-04 18:25:59 +000066
67 sl_unlock(&target_cpu->lock);
Daniel Boulbyf3cf28c2024-08-22 10:46:23 +010068 plat_interrupts_send_sgi(HF_IPI_INTID, target_cpu, true);
69}
70
71/**
72 * IPI IRQ specific handling for the secure interrupt for each vCPU state:
J-Alves180a65a2024-10-08 17:12:08 +010073 * - WAITING: Trigger an SRI so the NWd can schedule to target vCPU to run.
74 * - RUNNING:
75 * - PREEMPTED/BLOCKED: Return and allow the normal secure interrupt handling
76 * to handle the interrupt as usual.
77 * For all cases we must also mark the interrupt as complete from the
78 * SPMC perspective.
Daniel Boulbyf3cf28c2024-08-22 10:46:23 +010079 * Returns True if the IPI SGI has been handled.
80 * False if further secure interrupt handling is required.
81 */
82bool hf_ipi_handle(struct vcpu_locked target_vcpu_locked)
83{
84 struct vcpu *target_vcpu = target_vcpu_locked.vcpu;
85
86 switch (target_vcpu->state) {
Daniel Boulby960be202024-08-22 10:53:11 +010087 case VCPU_STATE_WAITING:
Daniel Boulby960be202024-08-22 10:53:11 +010088 plat_ffa_sri_trigger_not_delayed(target_vcpu->cpu);
89 return true;
J-Alves180a65a2024-10-08 17:12:08 +010090 case VCPU_STATE_RUNNING:
91 case VCPU_STATE_BLOCKED:
92 case VCPU_STATE_PREEMPTED:
93 /*
94 * Let the normal secure interrupt handling handle the
95 * interrupt as usual.
96 */
97 return false;
Daniel Boulbyf3cf28c2024-08-22 10:46:23 +010098 default:
J-Alves180a65a2024-10-08 17:12:08 +010099 dlog_error("Unexpected state: %u handling an IPI for [%x %u]",
100 target_vcpu->state, target_vcpu->vm->id,
101 vcpu_index(target_vcpu));
Daniel Boulbyf3cf28c2024-08-22 10:46:23 +0100102 return true;
103 }
104}