Skip to content

Commit

Permalink
contrib: gunyah-hypervisor update 12/2023
Browse files Browse the repository at this point in the history
Gunyah updates:
* cyclomatic complexity improvements
* Misra fixes
* trbe rename
* virtio-input device handling
* remote cpu halt on debug
* memdb bitmap object ID count increase to 16
* provide vcpu_runtime_flags bitfield
* Return cause of VCPU sleep from vcpu_run
* vgic hw_active tracking fixes
* vcpu dying power-on race fix
* vcpu power voting fixes
* vgic unbind fixes
* idle with wfi timeout support
* wait for slow irqs after cpu wake
* page table barriers for correct walk cache flushing
* vgic 1:N routing fixes
* defer per-cpu gic initialization
* Avoid unsafe casts in atomic bitfield ops
* new platform functional cpus api

Signed-off-by: Carl van Schaik <[email protected]>
  • Loading branch information
quic-cvanscha committed Jan 2, 2024
1 parent 41c15b6 commit 36ca3a2
Show file tree
Hide file tree
Showing 110 changed files with 3,150 additions and 1,196 deletions.
3 changes: 3 additions & 0 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ env_vars = {
'PATH': os.environ['PATH'],
}

if 'QCOM_LLVM' in os.environ:
env_vars['QCOM_LLVM'] = os.environ['QCOM_LLVM']

if 'LLVM' in os.environ:
env_vars['LLVM'] = os.environ['LLVM']

Expand Down
1 change: 1 addition & 0 deletions config/arch/gic-500.conf
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ configs GICV3_HAS_GICD_ICLAR=0
configs GICV3_HAS_SECURITY_DISABLED=0
configs PLATFORM_GICD_BASE=PLATFORM_GIC_BASE
configs PLATFORM_GICR_SIZE=(0x20000*PLATFORM_MAX_CORES)
configs PLATFORM_IDLE_WAKEUP_TIMEOUT_NS=5000
1 change: 1 addition & 0 deletions config/arch/gic-600.conf
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ configs PLATFORM_GITS_SIZE=(0x20000U*PLATFORM_GITS_COUNT)
configs PLATFORM_GICR_BASE=(PLATFORM_GITS_BASE+PLATFORM_GITS_SIZE)
configs PLATFORM_GICR_SIZE=(0x20000U*PLATFORM_GICR_COUNT)
configs PLATFORM_GIC_SIZE=(0x50000U+PLATFORM_GITS_SIZE+PLATFORM_GICR_SIZE)
configs PLATFORM_IDLE_WAKEUP_TIMEOUT_NS=5000
1 change: 1 addition & 0 deletions config/arch/gic-700-vlpi.conf
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ configs PLATFORM_GITS_SIZE=(0x40000U*PLATFORM_GITS_COUNT)
configs PLATFORM_GICR_BASE=(PLATFORM_GITS_BASE+PLATFORM_GITS_SIZE)
configs PLATFORM_GICR_SIZE=(0x40000U*PLATFORM_GICR_COUNT)
configs PLATFORM_GIC_SIZE=(0x50000U+PLATFORM_GITS_SIZE+PLATFORM_GICR_SIZE)
configs PLATFORM_IDLE_WAKEUP_TIMEOUT_NS=5000
1 change: 1 addition & 0 deletions config/arch/gic-qemu.conf
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ configs PLATFORM_GITS_SIZE=(0x20000U*PLATFORM_GITS_COUNT)
configs PLATFORM_GICR_BASE=(PLATFORM_GITS_BASE+PLATFORM_GITS_SIZE)
configs PLATFORM_GICR_SIZE=(0x20000U*PLATFORM_MAX_CORES)
configs PLATFORM_GIC_SIZE=(0x50000U+PLATFORM_GITS_SIZE+PLATFORM_GICR_SIZE)
configs PLATFORM_IDLE_WAKEUP_TIMEOUT_NS=0
3 changes: 3 additions & 0 deletions config/featureset/gunyah-rm-qemu.conf
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ module vm/slat
module vm/vcpu
module vm/vcpu_power
module vm/vcpu_run
module vm/virtio_mmio
module vm/virtio_input
module vm/vrtc_pl031
arch_module armv8 vm/smccc
arch_module armv8 vm/psci_pc
arch_module armv8 vm/vdebug
Expand Down
1 change: 1 addition & 0 deletions config/featureset/unittests-qemu.conf
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ module core/irq
module core/virq_null
module core/timer
module core/power
module core/globals
module debug/object_lists
module debug/symbol_version
module mem/allocator_list
Expand Down
2 changes: 2 additions & 0 deletions config/platform/qemu.conf
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,5 @@ configs PSCI_AFFINITY_LEVELS_NOT_SUPPORTED=1
configs PLATFORM_HAS_NO_DBGCLAIM_EL1=1
# QEMU supports version 0.2, which does not have set_suspend_mode call
configs PSCI_SET_SUSPEND_MODE_NOT_SUPPORTED=1

configs QCBOR_ENV_CONFIG_SIZE=0x4000
2 changes: 1 addition & 1 deletion config/quality/debug.conf
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ configs RESET_ON_ABORT=0
configs QUALITY=debug
flags -O1 -g -mstrict-align

#include include/debug_no_kaslr
include include/debug_no_kaslr
include include/debug_no_cspace_rand
include include/debug_no_rootvm_aslr

Expand Down
8 changes: 7 additions & 1 deletion docs/api/Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
%.pdf: %.md Makefile
pandoc -s --toc --pdf-engine=xelatex -N --top-level-division=part \
--metadata=title:'Gunyah Hypercall API' \
--metadata=date:"Generated: `date \"+%a %d %B %Y\"`" \
--variable=class:book \
--variable=mainfont:LiberationSans \
--variable=monofont:LiberationMono \
--variable=papersize:a4 \
--variable=margin-left:2.5cm \
--variable=margin-right:2.5cm \
--variable=margin-top:2.5cm \
--variable=margin-bottom:2.5cm \
$< -o $@

all: gunyah_api.pdf
all: gunyah_api.pdf gunyah_api_qcom.pdf
108 changes: 102 additions & 6 deletions docs/api/gunyah_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2649,27 +2649,45 @@ Also see: [Capability Errors](#capability-errors)

## Virtual IO MMIO Management

### Configure a Virtual IO MMIO
### Configure a Virtual IO Interface Object

Configure a Virtual IO MMIO whose state is OBJECT_STATE_INIT. The Virtual IO MMIO device needs to get a reference to memextent that covers its range.
Configure a Virtual IO Interface Object whose state is OBJECT_STATE_INIT.

Every Virtual IO device must be attached to a Memory Extent Object that contains its common registers and assumed to be mapped with write permissions into the backend VM's address space. The caller must also bind the backend IRQs to the backend VM's Virtual Interrupt Controller.

The number of queues presented by the device must be set at configuration time, so the hypervisor can allocate memory for tracking the queue states.

The Memory Extent must be 4KiB in size. Its layout matches the register layout specified for MMIO devices in section 4.2.2 of the Virtual I/O Device (VIRTIO) 1.1 specification, followed by optional device-specific configuration starting at offset 0x100. The caller must map it with read-only permissions into the frontend VM's address space, and bind the device's frontend IRQs to the frontend VM's Virtual Interrupt Controller.

If the device type valid flag is set, then the specified device type must be one that is known to the hypervisor, and any appropriate type-specific hypercalls must be made before the device is permitted to exit its reset state. Otherwise, the device type argument is ignored.

| **Hypercall**: | `virtio_mmio_configure` |
|-------------------------|--------------------------------------|
| Call number: | `hvc 0x6049` |
| Inputs: | X0: VirtioMMIO CapID |
| | X1: Memextent CapID |
| | X3: VQsNum |
| | X3: Reserved — Must be Zero |
| | X2: VQsNum Integer |
| | X3: VirtioOptionFlags |
| | X4: DeviceType Integer |
| | X5: DeviceConfigSize Integer |
| Outputs: | X0: Error Result |

**Types:**

*VirtioOptionFlags:*

| Bit Numbers | Mask | Description |
|-------------|-----------------------|-----------------------------------------|
| 6 | `0x40` | Device type argument is valid |
| 63:7,5:0 | `0xFFFFFFFF.FFFFFFBF` | Reserved — Must be Zero |

**Errors:**

OK – the operation was successful, and the result is valid.
OK – the operation was successful.

ERROR_OBJECT_STATE – if the Virtual IO MMIO object is not in OBJECT_STATE_INIT state.

ERROR_ARGUMENT_INVALID – a value passed in an argument was invalid. This could be due to a VQsNum out of range or if the specified memextent is not contiguous.
ERROR_ARGUMENT_INVALID – a value passed in an argument was invalid. This could be due to VQsNum being larger than the maximum, or the specified Memory Extent object being of an unsupported type.

Also see: [Capability Errors](#capability-errors)

Expand Down Expand Up @@ -2945,6 +2963,84 @@ ERROR_ARGUMENT_INVALID – A value passed in an argument was invalid.

Also see: [Capability Errors](#capability-errors)

## Virtio Input Config Hypercalls

### Virtio Input Configure

Allocate storage for the large data items and set the values of the small data items (`dev_ids` and `propbits`, which each fit in a single machine register). For the two types that support `subsel`, this call will specify the number of distinct valid `subsel` values (which may be sparse).

The `NumEVTypes` value must be between 0 and 32 inclusive. The `NumAbsAxes` value must be between 0 and 64 inclusive. If these limits are exceeded, the call will return `ERROR_ARGUMENT_SIZE`.



| **Hypercall**: | `virtio_input_configure` |
|-------------------------|--------------------------------------|
| Call number: | `hvc 0x605e` |
| Inputs: | X0: Virtio CapID |
| | X1: DevIDs |
| | X2: PropBits |
| | X3: NumEVTypes |
| | X4: NumAbsAxes |
| | X5: Reserved — Must be Zero |
| Outputs: | X0: Error Result |

**Types**:

_DevIDs_:

| Bits | Mask | Description |
|-|---|-----|
| 15:0 | `0xFFFF` | BusType |
| 31:16 | `0xFFFF0000` | Vendor |
| 47:32 | `0xFFFF.00000000` | Product |
| 63:48 | `0xFFFF0000.00000000` | Version |

**Errors:**

OK – The operation was successful, and the result is valid.

ERROR_ARGUMENT_INVALID – A value passed in an argument was invalid.

Also see: [Capability Errors](#capability-errors)

### Virtio Input Set Data

Copy data into the hypervisor's storage for one of the large data items, given its `sel` and `subsel` values, size, and the virtual address of a buffer in the caller's stage 1 address space. The data must not already have been configured for the given `sel` and `subsel` values.

| **Hypercall**: | `virtio_input_set_data` |
|-------------------------|--------------------------------------|
| Call number: | `hvc 0x605f` |
| Inputs: | X0: Virtio CapID |
| | X1: Sel |
| | X2: SubSel |
| | X3: Size |
| | X4: Data VMAddr |
| | X5: Reserved — Must be Zero |
| Outputs: | X0: Error Result |

The specified `VMAddr` must point to a buffer of the specified size that is mapped in the caller's stage 1 and stage 2 address spaces.

The `Sel`, `SubSel` and `Size` arguments must fall within one of the following ranges:

| Sel | SubSel | Size |
|------|--------|-------|
| 1 | 0 | 0–128 |
| 2 | 0 | 0–128 |
| 0x11 | 0–31 | 0–128 |
| 0x12 | 0–63 | 20 |

All other combinations are invalid. The call will return `ERROR_ARGUMENT_INVALID` if `Sel` or `SubSel` is invalid or out of range, and `ERROR_ARGUMENT_SIZE` if `Size` is out of range for the specified combination of `Sel` and `SubSel`.

Also, the call must not be repeated with `Sel` set to 0x11 or 0x12 and `Size` set to a nonzero value for more distinct values of `SubSel` than were specified with the `NumEVTypes` and `NumAbsAxes` arguments, respectively, of the most recent `virtio_input_configure` call. The call will return `ERROR_NORESOURCES` if these limits are exceeded.

**Errors:**

OK – The operation was successful, and the result is valid.

ERROR_ARGUMENT_INVALID – A value passed in an argument was invalid.

Also see: [Capability Errors](#capability-errors)

## PRNG Management

### PRNG Get Entropy
Expand Down
2 changes: 1 addition & 1 deletion hyp/arch/aarch64/registers.reg
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ TRCCLAIMCLR <uint64> Orw
TRCCLAIMSET <uint64> Orw
#endif

#if defined(MODULE_PLATFORM_TBRE)
#if defined(MODULE_PLATFORM_TRBE)
TRBLIMITR_EL1 Orw
TRBPTR_EL1 <uint64> Orw
TRBBASER_EL1 <uint64> Orw
Expand Down
28 changes: 28 additions & 0 deletions hyp/arch/armv8/include/asm/cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,36 @@
CACHE_OP_OBJECT(*x_, op); \
} while (0)

#define CACHE_DEFINE_ARRAY_OP(type, elements, name, op) \
static inline void cache_##name(type(*x)[elements]) \
{ \
CACHE_OP_OBJECT(*x, op); \
}

#define CACHE_DEFINE_CLEAN_ARRAY(type, elements, name) \
CACHE_DEFINE_ARRAY_OP(type, elements, clean_##name, CVAC)
#define CACHE_DEFINE_INVALIDATE_ARRAY(type, elements, name) \
CACHE_DEFINE_ARRAY_OP(type, elements, invalidate_##name, IVAC)
#define CACHE_DEFINE_CLEAN_INVALIDATE_ARRAY(type, elements, name) \
CACHE_DEFINE_ARRAY_OP(type, elements, clean_invalidate_##name, CIVAC)

#define CACHE_DEFINE_OP(type, name, op) \
static inline void cache_##name(type *x) \
{ \
CACHE_OP_OBJECT(*x, op); \
}

#define CACHE_DEFINE_CLEAN(type, name) CACHE_DEFINE_OP(type, clean_##name, CVAC)
#define CACHE_DEFINE_INVALIDATE(type, name) \
CACHE_DEFINE_OP(type, invalidate_##name, IVAC)
#define CACHE_DEFINE_CLEAN_INVALIDATE(type, name) \
CACHE_DEFINE_OP(type, clean_invalidate_##name, CIVAC)

#define CACHE_CLEAN_FIXED_RANGE(x, size) CACHE_OP_FIXED_RANGE(x, size, CVAC)
#define CACHE_INVALIDATE_FIXED_RANGE(x, size) \
CACHE_OP_FIXED_RANGE(x, size, IVAC)
#define CACHE_CLEAN_INVALIDATE_FIXED_RANGE(x, size) \
CACHE_OP_FIXED_RANGE(x, size, CIVAC)

void
cache_clean_range(const void *data, size_t size);
2 changes: 1 addition & 1 deletion hyp/core/api/aarch64/templates/c_wrapper.c.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
#for hypcall_num in sorted($hypcall_dict.keys())
#set $hypcall = $hypcall_dict[$hypcall_num]
#if len($hypcall.outputs) > 1
static_assert(sizeof(${return_type($hypcall)}) <= 8 * sizeof(register_t),
static_assert(sizeof(${return_type($hypcall)}) <= 8U * sizeof(register_t),
"Return structure must fit in 8 machine registers");

#end if
Expand Down
17 changes: 17 additions & 0 deletions hyp/core/base/aarch64/src/cache.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// © 2023 Qualcomm Innovation Center, Inc. All rights reserved.
//
// SPDX-License-Identifier: BSD-3-Clause

#include <assert.h>
#include <hyptypes.h>

#include <util.h>

#include <asm/cache.h>
#include <asm/cpu.h>

void
cache_clean_range(const void *data, size_t size)
{
CACHE_CLEAN_RANGE(data, size);
}
4 changes: 2 additions & 2 deletions hyp/core/base/aarch64/sysregs.tc
Original file line number Diff line number Diff line change
Expand Up @@ -1020,7 +1020,7 @@ extend MDCR_EL2 bitfield {
};
#endif

#if defined(ARCH_ARM_FEAT_SPEv1p1)
#if defined(ARCH_ARM_FEAT_SPE)
extend MDCR_EL2 bitfield {
13:12 E2PB uint8;
14 TPMS bool;
Expand All @@ -1039,7 +1039,7 @@ extend MDCR_EL2 bitfield {
};
#endif

#if defined(MODULE_PLATFORM_TBRE)
#if defined(MODULE_PLATFORM_TRBE)
extend ID_AA64DFR0_EL1 bitfield {
47:44 TraceBuffer uint8;
};
Expand Down
2 changes: 1 addition & 1 deletion hyp/core/base/build.conf
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
interface base
types types.tc
source base.c
arch_source aarch64 core_id.c
arch_source aarch64 core_id.c cache.c
arch_types armv8 enums.tc
arch_types aarch64 types.tc enums.tc sysregs.tc
arch_types cortex-a-v8_2 sysregs_cpu.tc
Expand Down
2 changes: 1 addition & 1 deletion hyp/core/boot/src/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ boot_do_memdb_walk(paddr_t base, size_t size, void *arg)
{
qcbor_enc_ctxt_t *qcbor_enc_ctxt = (qcbor_enc_ctxt_t *)arg;

if ((size == 0U) && (util_add_overflows(base, size - 1))) {
if ((size == 0U) && (util_add_overflows(base, size - 1U))) {
return ERROR_ARGUMENT_SIZE;
}

Expand Down
26 changes: 16 additions & 10 deletions hyp/core/boot/src/rel_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//
// SPDX-License-Identifier: BSD-3-Clause

#include <hyptypes.h>
#include <stddef.h>
#include <stdint.h>
#define USE_ELF64
Expand All @@ -17,32 +18,37 @@ __attribute__((no_stack_protector)) void
boot_rel_fixup(Elf_Dyn *dyni, Elf_Addr addr_offset, Elf_Addr rel_offset)
{
Elf_Xword dyn[DT_CNT];
Elf_Rel *rel = NULL;
Elf_Rela *rela = NULL;
Elf_Xword sz = 0;
Elf_Rel *rel = NULL;
Elf_Rel *rel_end = NULL;
Elf_Rela *rela = NULL;
Elf_Rela *rela_end = NULL;

for (int i = 0; i < DT_CNT; ++i) {
// We avoid zeroing the dyn array with an initialiser list as the
// compiler may optimise it to a memset, which may perform cache zeroing
// operations that are not supported when the MMU is disabled.
for (index_t i = 0; i < DT_CNT; i++) {
dyn[i] = 0;
}

for (; dyni->d_tag != DT_NULL; dyni += 1) {
if (dyni->d_tag < DT_CNT) {
dyn[dyni->d_tag] = (Elf_Xword)dyni->d_un.d_ptr;
}
}

rel = (Elf_Rel *)(dyn[DT_REL] + addr_offset);
sz = dyn[DT_RELSZ];
for (; sz > 0u; sz -= sizeof(*rel), ++rel) {
rel = (Elf_Rel *)(dyn[DT_REL] + addr_offset);
rel_end = (Elf_Rel *)(dyn[DT_REL] + addr_offset + dyn[DT_RELSZ]);
for (; rel < rel_end; rel++) {
if (!ARCH_CAN_PATCH(rel->r_info)) {
continue;
}
Elf_Addr *r = (Elf_Addr *)(rel->r_offset + addr_offset);
*r += rel_offset;
}

rela = (Elf_Rela *)(dyn[DT_RELA] + addr_offset);
sz = dyn[DT_RELASZ];
for (; sz > 0u; sz -= sizeof(*rela), ++rela) {
rela = (Elf_Rela *)(dyn[DT_RELA] + addr_offset);
rela_end = (Elf_Rela *)(dyn[DT_RELA] + addr_offset + dyn[DT_RELASZ]);
for (; rela < rela_end; rela++) {
if (!ARCH_CAN_PATCH(rela->r_info)) {
continue;
}
Expand Down
Loading

0 comments on commit 36ca3a2

Please sign in to comment.