Skip to content

Commit

Permalink
contrib: gunyah-hypervisor update 09/2023
Browse files Browse the repository at this point in the history
Gunyah updates:
 * memdb_bitmap module
 * cyclomatic complexity improvements
 * code style
 * many fixes and improvements

Signed-off-by: Carl van Schaik <[email protected]>
  • Loading branch information
quic-cvanscha committed Sep 20, 2023
1 parent 3d40144 commit a7c9ecb
Show file tree
Hide file tree
Showing 157 changed files with 4,508 additions and 2,264 deletions.
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The Gunyah Hypervisor was developed by Qualcomm in Sydney Australia.
## Type-1 Hypervisor Concept

Gunyah is a Type-1 hypervisor, meaning that it runs independently of any
high-level OS kernel - such as Linux, and runs in a higher CPU privilege level
high-level OS kernel such as Linux and runs in a higher CPU privilege level
than VMs. It does not depend on any lower-privileged OS kernel/code for its
core functionality. This increases its security and can support a much smaller
trusted computing base than a Type-2 like hosted-hypervisors.
Expand Down Expand Up @@ -64,8 +64,14 @@ supported in future contributions.

## Getting Started
- [Terminology](docs/terminology.md)
- Other required Gunyah related repositories:
- [Setup Tools and Scripts](https://github.com/quic/gunyah-support-scripts) (Start setup here..!!)
- [Hypervisor](https://github.com/quic/gunyah-hypervisor.git) (Gunyah core hypervisor, this repository)
- [Resource Manager](https://github.com/quic/gunyah-resource-manager.git) (Platform policy engine)
- [C Runtime](https://github.com/quic/gunyah-c-runtime.git) (C runtime environment for Resource Manager)

- [Setup Instructions](docs/setup.md)
+ [Quick Start Instructions](https://github.com/quic/gunyah-support-scripts/blob/develop/quickstart.md)
+ [Quick Start Instructions](https://github.com/quic/gunyah-support-scripts/blob/develop/quickstart.md) (will take to the setup tools and scripts repository)
- [Build Instructions](docs/build.md)
- [Status and Changelog](CHANGELOG.md)

Expand Down
1 change: 0 additions & 1 deletion config/arch/gic-700-vlpi.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
#
# SPDX-License-Identifier: BSD-3-Clause

configs GICV3_EXT_IRQS=0
configs GICV3_HAS_ITS=1
configs GICV3_HAS_LPI=1
configs GICV3_HAS_VLPI=1
Expand Down
5 changes: 3 additions & 2 deletions config/featureset/gunyah-rm-qemu.conf
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ module ipc/doorbell
module ipc/msgqueue
module mem/allocator_list
module mem/allocator_boot
module mem/memdb
module mem/memdb_gpt
module mem/hyp_aspace
module mem/pgtable
module mem/addrspace
Expand All @@ -46,11 +46,12 @@ module misc/prng_simple
module misc/trace_standard
module misc/smc_trace
module misc/log_standard
module misc/qcbor
module misc/root_env
module platform/arm_generic
module platform/arm_smccc
module platform/arm_trng_fi
arch_module aarch64 misc/spectre_arm
module misc/qcbor
module vm/rootvm
module vm/rootvm_package
module vm/slat
Expand Down
2 changes: 1 addition & 1 deletion config/featureset/unittests-qemu.conf
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ module debug/symbol_version
module mem/allocator_list
configs ALLOCATOR_DEBUG=1
module mem/allocator_boot
module mem/memdb
module mem/memdb_gpt
module mem/hyp_aspace
module mem/pgtable
module mem/addrspace
Expand Down
3 changes: 2 additions & 1 deletion config/quality/production.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
#
# SPDX-License-Identifier: BSD-3-Clause

configs VERBOSE_TRACE=1
# Uncomment for additional traces
# configs VERBOSE_TRACE=1
configs RESET_ON_ABORT=1
configs QUALITY=prod
flags -flto -O3 -g
Expand Down
44 changes: 32 additions & 12 deletions docs/api/gunyah_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -668,13 +668,20 @@ Also see: [Capability Errors](#capability-errors)

#### Doorbell Send

Sets flags in the Doorbell. If following the send, the set of enabled flags as defined by the bitwise-AND of the DoorBell flags with the EnableMask, is non-zero, any bound virtual interrupt will be asserted.
Sets flags in the Doorbell, and possibly asserts the bound virtual interrupt.

The specified NewFlags will be set (with a bitwise-OR) in the Doorbell flags.

If a VIRQ has been bound to the Doorbell, it will be asserted after setting the flags if either of the following is true:

* The enabled Doorbell flags, as defined by the bitwise-AND of the flags and the EnableFlags argument to the most recent `doorbell_mask` call, is non-zero.
* The VIRQ is edge-triggered.

| **Hypercall**: | `doorbell_send` |
|-------------------------|---------------------------------------------------|
| Call number: | `hvc 0x6012` |
| Inputs: | X0: Doorbell CapID |
| | X1: NewFlags FlagsBitmap – Must be non-zero. |
| | X1: NewFlags FlagsBitmap |
| | X2: Reserved — Must be Zero |
| Outputs: | X0: Error Result |
| | X1: OldFlags FlagsBitmap |
Expand All @@ -689,13 +696,25 @@ FlagsBitmap: unsigned 64-bit bitmap

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

ERROR_ARGUMENT_INVALID – if a zero NewFlags value is passed in.

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

#### Doorbell Receive

Reads and clears the flags of the Doorbell. If there is a pending bound virtual interrupt, it will be de-asserted.
Reads and clears the flags of the Doorbell, and possibly clears the bound virtual interrupt.

The specified ClearFlags will be set in the Doorbell flags. These must be nonzero; otherwise the call would have no effect.

If a VIRQ has been bound to the Doorbell, it will be cleared after clearing the flags if all of the following are true:

* The enabled Doorbell flags, as defined by the bitwise-AND of the flags and the EnableFlags argument to the most recent `doorbell_mask` call, is zero.
* The VIRQ is level-triggered.

The implementation does not guarantee that the VIRQ is cleared before the call returns. If level-triggered, the VIRQ is guaranteed to have been cleared before either of the following events occurs:

* The VIRQ is delivered after being individually unmasked using a platform-specific Virtual Interrupt Controller API. This includes EOI events, if the implementation supports them.
* An unspecified finite period of time has elapsed after the call is made.

If the VIRQ is edge-triggered, then this call's effect on it is unspecified.

| **Hypercall**: | `doorbell_receive` |
|-------------------------|-------------------------------------------------------|
Expand Down Expand Up @@ -1695,11 +1714,13 @@ For operations that affect address space mappings, the hypervisor will automatic

*MemExtent Modify Operation:*

| Modify Operation | Integer Value | Description |
|------------------------------------|-------------------|-------------------------------------------------------------------------------------------------|
| MEMEXTENT_MODIFY_OP_UNMAP_ALL | 0 | Unmap the memory extent from all address spaces it was mapped into. |
| MEMEXTENT_MODIFY_OP_ZERO_RANGE | 1 | Zero the owned memory of an extent within the specified range. The NoSync flag must be set. |
| MEMEXTENT_MODIFY_OP_SYNC_ALL | 255 | Synchronise all previous memory extent operations. The NoSync flag must not be set. |
| Modify Operation | Integer Value | Description |
|-------------------------------------------|-------------------|--------------------------------------------------------------------------------------------------------|
| MEMEXTENT_MODIFY_OP_UNMAP_ALL | 0 | Unmap the memory extent from all address spaces it was mapped into. |
| MEMEXTENT_MODIFY_OP_ZERO_RANGE | 1 | Zero the owned memory of an extent within the specified range. The NoSync flag must be set. |
| MEMEXTENT_MODIFY_OP_CACHE_CLEAN_RANGE | 2 | Cache clean the owned memory of an extent within the specified range. The NoSync flag must be set. |
| MEMEXTENT_MODIFY_OP_CACHE_FLUSH_RANGE | 3 | Cache flush the owned memory of an extent within the specified range. The NoSync flag must be set. |
| MEMEXTENT_MODIFY_OP_SYNC_ALL | 255 | Synchronise all previous memory extent operations. The NoSync flag must not be set. |

**Errors:**

Expand Down Expand Up @@ -2873,10 +2894,9 @@ The backend should make this call, when its VIRQ is asserted, to get a bitmap of
|-|---|-----|
| 0 | `0x1` | 1 = NEW_BUFFER: notifies the device that there are new buffers to process in a queue. |
| 1 | `0x2` | 1 = RESET_RQST: notifies the device that a device reset has been requested. |
| 2 | `0x4` | 1 = INTERRUPT_ACK: notifies the device that the frontend wrote to the InterruptACK register. |
| 3 | `0x8` | 1 = DRIVER_OK: notifies the device that the frontend has set the DRIVER_OK bit of the Status register. |
| 4 | `0x10` | 1 = FAILED: notifies the device that the frontend has set the FAILED bit of the Status register. |
| 63:5 | `0xFFFFFFFF.FFFFFFE0` | Reserved = 0 [TBD notify reasons] |
| 63:5,2 | `0xFFFFFFFF.FFFFFFE4` | Reserved = 0 [TBD notify reasons] |

**Errors:**

Expand Down
2 changes: 1 addition & 1 deletion docs/build.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ The build system has several configuration parameters that must be set:

* `platform`: selects the target hardware platform
* `featureset`: selects a named hypervisor architecture configuration
* `quality`: specifies the build quality, e.g. `debug`, `production` etc., which modify the build - such as including runtime assertions, compiler optimisations etc.
* `quality`: specifies the build quality, e.g. `debug`, `production` etc., which modify the build, such as including runtime assertions, compiler optimisations etc.

These parameters must be set on the build system's command line; if one or more
of them is left unset, the build system will print the known values for the
Expand Down
13 changes: 0 additions & 13 deletions hyp/arch/aarch64/include/asm/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,6 @@

#define asm_event_wait(p) __asm__ volatile("wfe" ::"m"(*p))

#if defined(CLANG_CTU_AST)

// Clang CTU analysis does not support _Generic in ASTs; use the default
// definition of load-before-wait.
#include <asm-generic/event.h>

// Ensure this is never compiled to object code
__asm__(".error");

#else

// clang-format off
#define asm_event_load_before_wait(p) _Generic( \
(p), \
Expand Down Expand Up @@ -74,5 +63,3 @@ asm_event_load64_before_wait(_Atomic uint64_t *p)
__asm__("ldaxr %0, %1" : "=r"(ret) : "Q"(*p));
return ret;
}

#endif // !defined(CLANG_CTU_AST)
24 changes: 14 additions & 10 deletions hyp/arch/aarch64/include/asm/sysregs.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,33 @@

#define sysreg64_read(reg, val) \
do { \
register_t val_; \
__asm__ volatile("mrs %0, " #reg ";" : "=r"(val_)); \
val = (__typeof__(val))val_; \
register_t reg##_read_val; \
/* Read 64-bit system register */ \
__asm__ volatile("mrs %0, " #reg ";" : "=r"(reg##_read_val)); \
val = (__typeof__(val))reg##_read_val; \
} while (0)

#define sysreg64_read_ordered(reg, val, ordering_var) \
do { \
register_t val_; \
register_t reg##_read_val; \
/* Read 64-bit system register with ordering */ \
__asm__ volatile("mrs %0, " #reg ";" \
: "=r"(val_), "+m"(ordering_var)); \
val = (__typeof__(val))val_; \
: "=r"(reg##_read_val), "+m"(ordering_var)); \
val = (__typeof__(val))reg##_read_val; \
} while (0)

#define sysreg64_write(reg, val) \
do { \
register_t reg = (register_t)val; \
__asm__ volatile("msr " #reg ", %0" : : "r"(reg)); \
register_t reg##_write_val = (register_t)val; \
/* Write 64-bit system register */ \
__asm__ volatile("msr " #reg ", %0" : : "r"(reg##_write_val)); \
} while (0)

#define sysreg64_write_ordered(reg, val, ordering_var) \
do { \
register_t reg = (register_t)val; \
register_t reg##_write_val = (register_t)val; \
/* Write 64-bit system register with ordering */ \
__asm__ volatile("msr " #reg ", %1" \
: "+m"(ordering_var) \
: "r"(reg)); \
: "r"(reg##_write_val)); \
} while (0)
2 changes: 2 additions & 0 deletions hyp/arch/aarch64/include/asm/system_registers.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
#define ISS_MRS_MSR_ID_AA64MMFR0_EL1 ISS_OP0_OP1_CRN_CRM_OP2(3, 0, 0, 7, 0)
#define ISS_MRS_MSR_ID_AA64MMFR1_EL1 ISS_OP0_OP1_CRN_CRM_OP2(3, 0, 0, 7, 1)
#define ISS_MRS_MSR_ID_AA64MMFR2_EL1 ISS_OP0_OP1_CRN_CRM_OP2(3, 0, 0, 7, 2)
#define ISS_MRS_MSR_ID_AA64MMFR3_EL1 ISS_OP0_OP1_CRN_CRM_OP2(3, 0, 0, 7, 3)
#define ISS_MRS_MSR_ID_AA64MMFR4_EL1 ISS_OP0_OP1_CRN_CRM_OP2(3, 0, 0, 7, 4)
#define ISS_MRS_MSR_AIDR_EL1 ISS_OP0_OP1_CRN_CRM_OP2(3, 1, 0, 0, 7)
#define ISS_MRS_MSR_PMCR_EL0 ISS_OP0_OP1_CRN_CRM_OP2(3, 3, 9, 12, 0)
#define ISS_MRS_MSR_PMCNTENSET_EL0 ISS_OP0_OP1_CRN_CRM_OP2(3, 3, 9, 12, 1)
Expand Down
2 changes: 2 additions & 0 deletions hyp/arch/aarch64/link.lds
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/

#define __ASSEMBLER__
#include <hypconstants.h>

#if ((PLATFORM_LMA_BASE & ((1 << 21) - 1)) != 0)
Expand Down Expand Up @@ -91,6 +92,7 @@ SECTIONS
#endif

. = ALIGN(64);
. = ALIGN(MEMDB_MIN_SIZE);
#if PLATFORM_RW_DATA_SIZE < 0x200000
#error PLATFORM_RW_DATA_SIZE too small
#endif
Expand Down
5 changes: 5 additions & 0 deletions hyp/arch/aarch64/registers.reg
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ ID_AA64ISAR2_EL1 r
ID_AA64MMFR0_EL1 r
ID_AA64MMFR1_EL1 r
ID_AA64MMFR2_EL1 r
// Replace with the correct register names once we upgrade to a version of LLVM
// that recognises them
// FIXME:
S3_0_C0_C7_3 [ID_AA64MMFR3_EL1!] r
S3_0_C0_C7_4 [ID_AA64MMFR4_EL1!] r
ID_AA64PFR0_EL1 r
ID_AA64PFR1_EL1 r
//ID_AA64ZFR0_EL1 r
Expand Down
98 changes: 55 additions & 43 deletions hyp/core/base/aarch64/src/core_id.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,54 +30,66 @@ platform_cpu_get_coreid(MIDR_EL1_t midr)
static core_id_t
get_core_id(uint16_t partnum, uint8_t variant, uint8_t revision)
{
static const coreid_info_t core_id_data[] = {
{ .part_num = 0xD03, .core_ID = CORE_ID_CORTEX_A53 },
{ .part_num = 0xD05, .core_ID = CORE_ID_CORTEX_A55 },
{ .part_num = 0xD07, .core_ID = CORE_ID_CORTEX_A57 },
{ .part_num = 0xD08, .core_ID = CORE_ID_CORTEX_A72 },
{ .part_num = 0xD09, .core_ID = CORE_ID_CORTEX_A73 },
{ .part_num = 0xD0A, .core_ID = CORE_ID_CORTEX_A75 },
{ .part_num = 0xD0B, .core_ID = CORE_ID_CORTEX_A76 },
{ .part_num = 0xD0C, .core_ID = CORE_ID_NEOVERSE_N1 },
{ .part_num = 0xD0D, .core_ID = CORE_ID_CORTEX_A77 },
{ .part_num = 0xD0E, .core_ID = CORE_ID_CORTEX_A76AE },
{ .part_num = 0xD40, .core_ID = CORE_ID_NEOVERSE_V1 },
{ .part_num = 0xD41, .core_ID = CORE_ID_CORTEX_A78 },
{ .part_num = 0xD42, .core_ID = CORE_ID_CORTEX_A78AE },
{ .part_num = 0xD44, .core_ID = CORE_ID_CORTEX_X1 },
{ .part_num = 0xD46, .core_ID = CORE_ID_CORTEX_A510 },
{ .part_num = 0xD47, .core_ID = CORE_ID_CORTEX_A710 },
{ .part_num = 0xD48, .core_ID = CORE_ID_CORTEX_X2 },
{ .part_num = 0xD49, .core_ID = CORE_ID_NEOVERSE_N2 },
{ .part_num = 0xD4B, .core_ID = CORE_ID_CORTEX_A78C },
{ .part_num = 0xD4D, .core_ID = CORE_ID_CORTEX_A715 },
{ .part_num = 0xD4E, .core_ID = CORE_ID_CORTEX_X3 },
static const core_id_info_t core_id_map[] = {
{ .part_num = 0xD03U, .core_id = CORE_ID_CORTEX_A53 },
{ .part_num = 0xD05U, .core_id = CORE_ID_CORTEX_A55 },
{ .part_num = 0xD07U, .core_id = CORE_ID_CORTEX_A57 },
{ .part_num = 0xD08U, .core_id = CORE_ID_CORTEX_A72 },
{ .part_num = 0xD09U, .core_id = CORE_ID_CORTEX_A73 },
{ .part_num = 0xD0AU, .core_id = CORE_ID_CORTEX_A75 },
{ .part_num = 0xD0BU, .core_id = CORE_ID_CORTEX_A76 },
{ .part_num = 0xD0CU, .core_id = CORE_ID_NEOVERSE_N1 },
{ .part_num = 0xD0DU, .core_id = CORE_ID_CORTEX_A77 },
{ .part_num = 0xD0EU, .core_id = CORE_ID_CORTEX_A76AE },
{ .part_num = 0xD40U, .core_id = CORE_ID_NEOVERSE_V1 },
{ .part_num = 0xD41U, .core_id = CORE_ID_CORTEX_A78 },
{ .part_num = 0xD42U, .core_id = CORE_ID_CORTEX_A78AE },
{ .part_num = 0xD44U, .core_id = CORE_ID_CORTEX_X1 },
{ .part_num = 0xD46U, .core_id = CORE_ID_CORTEX_A510 },
{ .part_num = 0xD47U, .core_id = CORE_ID_CORTEX_A710 },
{ .part_num = 0xD48U, .core_id = CORE_ID_CORTEX_X2 },
{ .part_num = 0xD49U, .core_id = CORE_ID_NEOVERSE_N2 },
{ .part_num = 0xD4BU, .core_id = CORE_ID_CORTEX_A78C },
{ .part_num = 0xD4DU, .core_id = CORE_ID_CORTEX_A715 },
{ .part_num = 0xD4EU, .core_id = CORE_ID_CORTEX_X3 },
{ .part_num = 0xD80U, .core_id = CORE_ID_CORTEX_A520 },
};
// List of cores that have specific revisions.
// If multiple revisions are assigned different core IDs, then keep
// them sorted by highest (variant_min,revision_min) first.
static const core_id_rev_info_t core_id_rev_map[] = {
{ .part_num = 0xD81U,
.core_id = CORE_ID_CORTEX_A720,
.variant_min = 0,
.revision_min = 1 },
{ .part_num = 0xD82U,
.core_id = CORE_ID_CORTEX_X4,
.variant_min = 0,
.revision_min = 1 }
};

core_id_t coreid;
index_t i;

for (i = 0U; i < util_array_size(core_id_map); i++) {
if (partnum == core_id_map[i].part_num) {
coreid = core_id_map[i].core_id;
goto out;
}
}

static const count_t NUM_CORE_ID =
(count_t)util_array_size(core_id_data);
core_id_t coreid = CORE_ID_UNKNOWN;

uint32_t start;

bool core_identified = false;

for (start = 0; ((start < NUM_CORE_ID) && (!core_identified));
start++) {
if (partnum == core_id_data[start].part_num) {
if ((partnum == 0xD81U) || (partnum == 0xD82U)) {
if ((variant == 0U) && (revision == 0U)) {
coreid = core_id_data[start].core_ID;
} else {
coreid = CORE_ID_UNKNOWN;
}
} else {
coreid = core_id_data[start].core_ID;
}
core_identified = true;
for (i = 0U; i < util_array_size(core_id_rev_map); i++) {
if ((partnum == core_id_rev_map[i].part_num) ||
(variant > core_id_rev_map[i].variant_min) ||
((variant == core_id_rev_map[i].variant_min) &&
(revision >= core_id_rev_map[i].revision_min))) {
coreid = core_id_rev_map[i].core_id;
goto out;
}
}

coreid = CORE_ID_UNKNOWN;
out:
return coreid;
}

Expand Down
Loading

0 comments on commit a7c9ecb

Please sign in to comment.