blob: f642c94504d54adc33f09b41d82170bd42dfd485 [file] [log] [blame] [view]
# Scheduler VM expectations
Hafnium requires there to be a special 'primary' or 'scheduler' VM which is
responsible for scheduling the other VMs. There are some particular expectations
on this VM that are required for the rest of the system to function normally.
[TOC]
## Scheduling
The scheduler VM is responsible for scheduling the vCPUs of all the other VMs.
It should request information about the VMs in the system using the
`FFA_PARTITION_INFO_GET` function, and then schedule their vCPUs as it wishes.
The recommended way of doing this is to create a kernel thread for each vCPU,
which will repeatedly run that vCPU by calling `FFA_RUN`.
`FFA_RUN` will return one of several possible functions, which must be handled
as follows:
### `FFA_INTERRUPT`
The vCPU has been preempted but still has work to do. If the scheduling quantum
has not expired, the scheduler MUST call `hf_vcpu_run` on the vCPU to allow it
to continue.
### `FFA_YIELD`
The vCPU has voluntarily yielded the CPU. The scheduler SHOULD take a scheduling
decision to give cycles to those that need them but MUST call `hf_vcpu_run` on
the vCPU at a later point.
### `FFA_MSG_WAIT`
The vCPU is blocked waiting for a message. The scheduler MUST take it off the
run queue and not call `FFA_RUN` on the vCPU until it has either:
* injected an interrupt
* sent it a message
* received `HF_FFA_RUN_WAKE_UP` for it from another vCPU
* the timeout provided in `w2` is not `FFA_SLEEP_INDEFINITE` and the
specified duration has expired.
### `FFA_MSG_SEND`
A message has been sent by the vCPU. If the recipient is the scheduler VM itself
then it can handle it as it pleases. Otherwise the scheduler MUST run a vCPU
from the recipient VM and priority SHOULD be given to those vCPUs that are
waiting for a message. The scheduler should call FFA_RUN again on the sending
VM as usual.
### `FFA_RX_RELEASE`
The vCPU has made the mailbox writable and there are pending waiters. The
scheduler MUST call `hf_mailbox_waiter_get()` repeatedly and notify all waiters
by injecting an `HF_MAILBOX_WRITABLE_INTID` interrupt. The scheduler should call
FFA_RUN again on the sending VM as usual.
### `HF_FFA_RUN_WAIT_FOR_INTERRUPT`
_This is a Hafnium-specific function not part of the FF-A standard._
The vCPU is blocked waiting for an interrupt. The scheduler MUST take it off the
run queue and not call `FFA_RUN` on the vCPU until it has either:
* injected an interrupt
* received `HF_FFA_RUN_WAKE_UP` for it from another vCPU
* the timeout provided in `w2` is not `FFA_SLEEP_INDEFINITE` and the
specified duration has expired.
### `HF_FFA_RUN_WAKE_UP`
_This is a Hafnium-specific function not part of the FF-A standard._
Hafnium would like `hf_vcpu_run` to be called on another vCPU, specified by
`hf_vcpu_run_return.wake_up`. The scheduler MUST either wake the vCPU in
question up if it is blocked, or preempt and re-run it if it is already running
somewhere. This gives Hafnium a chance to update any CPU state which might have
changed. The scheduler should call FFA_RUN again on the sending VM as usual.
### `FFA_ERROR`
#### `FFA_ABORTED`
The vCPU has aborted triggering the whole VM to abort. The scheduler MUST treat
this the same as `HF_FFA_RUN_WAKE_UP` for all the other vCPUs of the VM. For
this vCPU the scheduler SHOULD either never call FFA_RUN on the vCPU again, or
treat it the same as `HF_FFA_RUN_WAIT_FOR_INTERRUPT`.
#### Any other error code
This should not happen if the scheduler VM has called `FFA_RUN` correctly, but
in case there is some other error it should be logged. The scheduler SHOULD
either try again or suspend the vCPU indefinitely.
## Interrupt handling
The scheduler VM is responsible for handling all hardware interrupts. Many of
these will be intended for the scheduler VM itself and it can handle them as
usual. However, it must also:
* Enable, handle and ignore interrupts for the non-secure hypervisor physical
timer (PPI 10, IRQ 26).
* Forward interrupts intended for secondary VMs to an appropriate vCPU of the
VM by calling `hf_interrupt_inject` and then running the vCPU as usual with
`FFA_RUN`. (If the vCPU is already running at the time that
`hf_interrupt_inject` is called then it must be preempted and run again so
that Hafnium can inject the interrupt.)