blob: 86f18c1d4b8de8253fef22328892e581b566dafb [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
Karl Meakin7a664f62024-07-24 17:20:29 +010011#include "hf/arch/plat/ffa/notifications.h"
Daniel Boulby960be202024-08-22 10:53:11 +010012
Daniel Boulbyf3cf28c2024-08-22 10:46:23 +010013#include "hf/cpu.h"
14#include "hf/plat/interrupts.h"
15
16/** Interrupt priority for Inter-Processor Interrupt. */
17#define IPI_PRIORITY 0x0U
18
19/**
20 * Initialize the IPI SGI.
21 */
22void hf_ipi_init_interrupt(void)
23{
24 /* Configure as a Secure SGI. */
25 struct interrupt_descriptor ipi_desc = {
26 .interrupt_id = HF_IPI_INTID,
27 .type = INT_DESC_TYPE_SGI,
28 .sec_state = INT_DESC_SEC_STATE_S,
29 .priority = IPI_PRIORITY,
30 .valid = true,
Daniel Boulby84d49b62024-11-04 18:25:59 +000031 .enabled = true,
Daniel Boulbyf3cf28c2024-08-22 10:46:23 +010032 };
33
34 plat_interrupts_configure_interrupt(ipi_desc);
35}
36
37/**
38 * Returns the target_vcpu for the pending IPI on the current CPU and
39 * resets the item in the list to NULL to show it has been retrieved.
40 */
41struct vcpu *hf_ipi_get_pending_target_vcpu(struct cpu *current)
42{
Daniel Boulby84d49b62024-11-04 18:25:59 +000043 struct vcpu *ret;
44
45 sl_lock(&current->lock);
46
47 ret = current->ipi_target_vcpu;
Daniel Boulbyf3cf28c2024-08-22 10:46:23 +010048
49 current->ipi_target_vcpu = NULL;
Daniel Boulby84d49b62024-11-04 18:25:59 +000050
51 sl_unlock(&current->lock);
52
Daniel Boulbyf3cf28c2024-08-22 10:46:23 +010053 return ret;
54}
55
56/**
57 * Send and record the IPI for the target vCPU.
58 */
59void hf_ipi_send_interrupt(struct vm *vm, ffa_vcpu_index_t target_vcpu_index)
60{
61 struct vcpu *target_vcpu = vm_get_vcpu(vm, target_vcpu_index);
62 struct cpu *target_cpu = target_vcpu->cpu;
63
Daniel Boulby84d49b62024-11-04 18:25:59 +000064 sl_lock(&target_cpu->lock);
65
Daniel Boulbyf3cf28c2024-08-22 10:46:23 +010066 target_cpu->ipi_target_vcpu = target_vcpu;
Daniel Boulby84d49b62024-11-04 18:25:59 +000067
68 sl_unlock(&target_cpu->lock);
Daniel Boulbyf3cf28c2024-08-22 10:46:23 +010069 plat_interrupts_send_sgi(HF_IPI_INTID, target_cpu, true);
70}
71
72/**
73 * IPI IRQ specific handling for the secure interrupt for each vCPU state:
J-Alves180a65a2024-10-08 17:12:08 +010074 * - WAITING: Trigger an SRI so the NWd can schedule to target vCPU to run.
75 * - RUNNING:
76 * - PREEMPTED/BLOCKED: Return and allow the normal secure interrupt handling
77 * to handle the interrupt as usual.
78 * For all cases we must also mark the interrupt as complete from the
79 * SPMC perspective.
Daniel Boulbyf3cf28c2024-08-22 10:46:23 +010080 * Returns True if the IPI SGI has been handled.
81 * False if further secure interrupt handling is required.
82 */
83bool hf_ipi_handle(struct vcpu_locked target_vcpu_locked)
84{
85 struct vcpu *target_vcpu = target_vcpu_locked.vcpu;
86
87 switch (target_vcpu->state) {
Daniel Boulby960be202024-08-22 10:53:11 +010088 case VCPU_STATE_WAITING:
Daniel Boulby960be202024-08-22 10:53:11 +010089 plat_ffa_sri_trigger_not_delayed(target_vcpu->cpu);
90 return true;
J-Alves180a65a2024-10-08 17:12:08 +010091 case VCPU_STATE_RUNNING:
92 case VCPU_STATE_BLOCKED:
93 case VCPU_STATE_PREEMPTED:
94 /*
95 * Let the normal secure interrupt handling handle the
96 * interrupt as usual.
97 */
98 return false;
Daniel Boulbyf3cf28c2024-08-22 10:46:23 +010099 default:
J-Alves180a65a2024-10-08 17:12:08 +0100100 dlog_error("Unexpected state: %u handling an IPI for [%x %u]",
101 target_vcpu->state, target_vcpu->vm->id,
102 vcpu_index(target_vcpu));
Daniel Boulbyf3cf28c2024-08-22 10:46:23 +0100103 return true;
104 }
105}