blob: 3702b49ae36018caf06502b7ce249ecbee087107 [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
Daniel Boulby960be202024-08-22 10:53:11 +010011#include "hf/arch/plat/ffa.h"
12
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:
74 * - RUNNING: Continue secure interrupt handling as normal, injecting
75 * a virtual interrupt to the vCPU.
Daniel Boulby960be202024-08-22 10:53:11 +010076 * - WAITING: Mark the IPI as complete from the SPMC perspective and
77 * trigger an SRI so the NWd can schedule to target vCPU to run.
Daniel Boulbyf3cf28c2024-08-22 10:46:23 +010078 * - Other states are not currently supported so exit the handler.
79 * 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) {
87 case VCPU_STATE_RUNNING:
88 return false;
Daniel Boulby960be202024-08-22 10:53:11 +010089 case VCPU_STATE_WAITING:
Daniel Boulby960be202024-08-22 10:53:11 +010090 plat_ffa_sri_trigger_not_delayed(target_vcpu->cpu);
91 return true;
Daniel Boulbyf3cf28c2024-08-22 10:46:23 +010092 default:
93 dlog_verbose(
94 "IPIs not currently supported for when the target_vcpu "
95 "is in the state %d\n",
96 target_vcpu->state);
Daniel Boulbyf3cf28c2024-08-22 10:46:23 +010097 return true;
98 }
99}