Arch: CPU mechanisms and feature contracts

These declarations come from public header files. Selection, lifecycle, supported execution modes and physical authorization remain bounded by the corresponding design and support records.

arch.h

CPU-local mask, context, ordering and cycle snapshot contract.

Author

Nexus Team

Functions

nx_arch_irq_state_t nx_arch_irq_save(void)

Save incoming local mask and mask configurable exceptions.

Note

Privileged Task/configurable-IRQ short metadata sections only; do not block, allocate, call OS functions, copy large buffers or invoke callbacks. NMI/HardFault remain unmasked. Native uses a recursive host exclusion model, not physical IRQ timing or signal safety. NMI/HardFault must not access shared metadata protected by this mask. ARM unprivileged callers need an explicit privileged gateway owned by their OS.

Returns:

Token to restore exactly once in reverse nesting order.

void nx_arch_irq_restore(nx_arch_irq_state_t previous)

Restore the incoming mask, preserving nested exclusions.

Note

Privileged contexts only. Restores PRIMASK only; BASEPRI/FAULTMASK, where present, are not modified.

Parameters:
  • previous – [in] Token from this CPU/thread’s latest unmatched save.

nx_arch_irq_masks_t nx_arch_irq_masks(void)

Snapshot the implemented local interrupt-mask registers.

Note

Bounded read-only privileged task/IRQ query. Does not mask interrupts or grant a stable critical section. Values refer to this CPU/security state, not another security world or an SMP peer. Unprivileged reads do not establish mask state.

Returns:

Current PRIMASK and implemented BASEPRI/FAULTMASK values.

bool nx_arch_irq_is_masked(void)

Test masks that could prevent required completion progress.

Note

Bounded privileged task/IRQ query, no state change. ARM unprivileged reads do not establish the actual mask state.

Returns:

True for PRIMASK, implemented BASEPRI/FAULTMASK, or Native thread nesting. Baseline Cortex-M cores query PRIMASK only.

uint32_t nx_arch_exception_number(void)

Query the exact current CPU exception identity.

Note

Bounded read-only task/IRQ query. The identity belongs to the current CPU/security state; it is not a portable SoC IRQ number or evidence that a kernel ISR call is allowed.

Returns:

IPSR exception number, zero for Thread mode or Native.

bool nx_arch_is_privileged(void)

Query privilege in the current CPU execution context.

Note

Bounded read-only task/IRQ query. Handler privilege does not depend on the interrupted Thread’s CONTROL.nPRIV. This query does not establish Secure-world ownership.

Returns:

True in Handler mode or privileged Thread mode. Native always returns true because it has no CPU privilege model.

bool nx_arch_in_isr(void)

Query current CPU exception context.

Returns:

Cortex-M IPSR is nonzero; Native has no hardware ISR and always returns false. Host signals are unsupported contexts.

void nx_arch_dmb(void)

Order explicit data memory accesses in the CPU domain.

Note

Cortex-M DMB; Native sequentially consistent thread fence. Does not prove DMA idle or clean noncoherent cache lines.

void nx_arch_dsb(void)

Complete preceding explicit memory accesses.

Note

Cortex-M DSB; Native thread fence is a behavioral model, not a physical bus/DMA completion guarantee.

void nx_arch_isb(void)

Synchronize subsequent CPU instruction execution.

Note

Cortex-M ISB; Native thread fence has no pipeline semantics.

bool nx_arch_cycle_snapshot(uint32_t *cycles)

Snapshot an already enabled free-running cycle counter.

Note

Counter frequency follows CPU clock. Use unsigned snapshot subtraction only for intervals shorter than 2^32 cycles; this counter is neither shared monotonic time nor a deadline.

Parameters:
  • cycles – [out] DWT CYCCNT snapshot, unchanged when unavailable.

Returns:

True when a maintained CPU counter is enabled; false on Native, an unreviewed/disabled/unavailable DWT, or an unprivileged caller. Does not enable/reset it. Only a reviewed CPU profile may read the optional DWT registers.

struct nx_arch_irq_state_t
#include <arch.h>

Saved incoming PRIMASK or calling-thread Native nesting.

Note

Restore on the same CPU/thread in strict reverse order. This is neither a FreeRTOS BASEPRI token nor an SMP lock.

Public Members

uint32_t value
struct nx_arch_irq_masks_t
#include <arch.h>

Read-only snapshot of implemented local interrupt masks.

Note

Absent BASEPRI/FAULTMASK registers are zero. Native reports PRIMASK as zero or one according to current thread nesting. This snapshot is neither a restore token nor a kernel lock.

Public Members

uint32_t primask
uint32_t basepri
uint32_t faultmask

atomic.h

Inline naturally aligned 32-bit publication and RMW ports.

Author

Nexus Team

Note

Storage is a live, naturally aligned uint32_t; all concurrent accesses use these helpers or compatible compiler atomics. Initialize before publishing storage. Load/store use compiler acquire/release operations on all maintained CPUs and never mask interrupts. Other than ARMv6-M, RMW uses compiler lock-free operations; exclusive instruction retries do not establish a fixed cycle bound.

Note

ARMv6-M RMW is CPU-local, bounded saved-PRIMASK exclusion. Only privileged Thread/configurable-IRQ contexts on one CPU may access this domain. NMI/HardFault, unprivileged callers, another core, DMA and another security domain must not access its storage concurrently. It is not an SMP or bus atomic operation. No callback, allocation, blocking call or payload copy occurs while masked.

Functions

static inline uint32_t nx_atomic_u32_load_relaxed(const uint32_t *value)

Read one word without publishing or acquiring other data.

static inline uint32_t nx_atomic_u32_load_acquire(const uint32_t *value)

Read one word and acquire data from the observed publication.

static inline void nx_atomic_u32_store_relaxed(uint32_t *value, uint32_t desired)

Store one word without publishing other data.

static inline void nx_atomic_u32_store_release(uint32_t *value, uint32_t desired)

Publish preceding data through one aligned release store.

static inline bool nx_atomic_u32_compare_exchange_acq_rel(uint32_t *value, uint32_t *expected, uint32_t desired)

Strong acq_rel compare/exchange, acquire on failure.

Parameters:
  • value – [inout] Live naturally aligned word in the caller-owned atomic domain; all concurrent accesses use this contract.

  • expected – [inout] Separate, private caller storage; failure replaces it with the observed value. Success leaves it unchanged.

  • desired – [in] Replacement word stored only when comparison succeeds.

Returns:

True only when the original word equals expected and the desired word was stored. No spurious failure is allowed.

static inline uint32_t nx_atomic_u32_fetch_add_acq_rel(uint32_t *value, uint32_t amount)

Add modulo 2^32 with acq_rel ordering, returning the original word.

static inline uint32_t nx_atomic_u32_fetch_add_release(uint32_t *value, uint32_t amount)

Add modulo 2^32 with release ordering; return original word.

Note

ARMv6-M conservatively acquires the observed word too.

static inline uint32_t nx_atomic_u32_fetch_sub_acq_rel(uint32_t *value, uint32_t amount)

Subtract modulo 2^32 with acq_rel ordering; return original.

static inline uint32_t nx_atomic_u32_fetch_sub_release(uint32_t *value, uint32_t amount)

Subtract modulo 2^32 with release ordering; return original.

Note

ARMv6-M conservatively acquires the observed word too.

cache.h

Explicit whole-line CPU cache maintenance mechanisms.

Author

Nexus Team

Functions

nx_arch_result_t nx_arch_dcache_clean(uintptr_t address, size_t bytes)

Publish dirty data cache lines to the point of coherency.

Note

Privileged task/configurable-IRQ context in the current security domain only. The caller excludes other CPU, security-world and DMA users of every complete line until return, and keeps cache configuration stable. No hidden IRQ mask, allocation or cache enable occurs. Supported geometry is an explicitly reviewed 32-byte line; range rounding is forbidden. Work is bounded by bytes/32 and is not a DMA drain, device completion or transfer of ownership.

Parameters:
  • address – [in] First byte of exclusively owned complete lines.

  • bytes – [in] Nonzero whole-line length in the CPU address space.

Returns:

OK after maintenance and barriers; INVALID for partial lines or an overflowing/non-32-bit range; CONTEXT for an unprivileged caller; UNSUPPORTED for an absent or disabled reviewed cache. Rejection performs no maintenance writes.

nx_arch_result_t nx_arch_dcache_invalidate(uintptr_t address, size_t bytes)

Discard complete data cache lines without writing them.

Note

The caller permits all dirty data in these lines to be discarded and satisfies clean’s exclusion/context contract. No adjacent line is touched or rounded into the range. For DMA receive, providers coordinate both pre-DMA and post-drain maintenance; this call does not establish idle.

Parameters:
  • address – [in] First byte of exclusively owned complete lines.

  • bytes – [in] Nonzero whole-line length in the CPU address space.

Returns:

The same context, range and capability results as clean.

nx_arch_result_t nx_arch_dcache_clean_invalidate(uintptr_t address, size_t bytes)

Publish dirty data and discard the complete cache lines.

Note

Satisfies clean’s exclusion/context contract. Distinct from invalidate: dirty contents are written before discard.

Parameters:
  • address – [in] First byte of exclusively owned complete lines.

  • bytes – [in] Nonzero whole-line length in the CPU address space.

Returns:

The same context, range and capability results as clean.

nx_arch_result_t nx_arch_instruction_sync(uintptr_t address, size_t bytes)

Make a complete owned range coherent for CPU instructions.

Note

Satisfies clean’s exclusion/context contract. All present caches are checked before any maintenance. With only one reviewed cache, only that cache is maintained. The caller prevents execution from the changing range, including other security-world users. This is not code validation, an MPU policy change or a global cache/branch-predictor flush.

Parameters:
  • address – [in] First byte of exclusively owned complete lines.

  • bytes – [in] Nonzero whole-line length in the CPU address space.

Returns:

OK after data clean, instruction invalidate and execution barriers; INVALID/CONTEXT as above; UNSUPPORTED when both reviewed caches are absent or a present cache is disabled.

cache_control.h

Explicit owned Cortex-M7 cold cache transitions.

Author

Nexus Team

Defines

NX_ARCH_CACHE_DATA

Data-cache ownership bit, independent of the hardware CCR layout.

NX_ARCH_CACHE_INSTRUCTION

Instruction-cache ownership bit.

Enums

enum nx_arch_cache_control_result_t

Cold-transition admission or execution result.

Values:

enumerator NX_ARCH_CACHE_OK
enumerator NX_ARCH_CACHE_INVALID
enumerator NX_ARCH_CACHE_CONTEXT
enumerator NX_ARCH_CACHE_UNSUPPORTED
enumerator NX_ARCH_CACHE_STATE
enumerator NX_ARCH_CACHE_IO

Functions

nx_arch_cache_control_result_t nx_arch_cache_cold_enable(nx_arch_cache_control_t *control, uint32_t mask)

Admit cold caches and enable the explicitly selected ones.

Note

Reviewed M7 only. Requires privileged Thread, PRIMASK=1, BASEPRI=FAULTMASK=0 and known-clean caches from a trusted reset or prior successful owned clean/disable. CCR bits being zero alone do not prove clean foreign state; never adopt an unknown bootloader state. Caller excludes all other cache users, DMA, NMI and HardFault access to affected memory throughout the transition. It owns memory attributes, execution and coherency policy; enabling a cache does not establish DMA coherence. No IRQ mask changes, allocation or cache adoption occur. Rejected initial admission has no retained responsibility. An IO failure can retain owned_mask/selector_pending; call cold_disable and retain storage until it succeeds.

Parameters:
  • control – [inout] Exclusively owned, initially empty control object.

  • mask – [in] Nonzero combination of DATA and INSTRUCTION bits.

Returns:

OK after verified enable and selector restoration; INVALID for arguments; CONTEXT for unsafe context; UNSUPPORTED for an unreviewed CPU/geometry; STATE for live/foreign caches; IO when a register write is not confirmed by readback.

nx_arch_cache_control_result_t nx_arch_cache_cold_disable(nx_arch_cache_control_t *control)

Clean and disable caches owned by this control object.

Note

Satisfies enable’s exclusion and context contract after every DMA/provider has drained. Rejects enabled caches outside owned_mask. The data clean/disable transition uses a stack-free leaf so no local dirty line can appear between the final clean and CCR update. Its bounded work is four ways times the verified set count, not constant latency. Failed operations remain retryable without adopting a new cache or forgetting the original selector. A zero object is an idempotent no-op on a supported CPU profile.

Parameters:
  • control – [inout] Same live object passed to cold_enable.

Returns:

OK only after cache disable and selector restoration; INVALID, CONTEXT, UNSUPPORTED, STATE or IO retain ownership.

struct nx_arch_cache_control_t
#include <cache_control.h>

Caller-owned cache responsibility and selector recovery.

Note

Zero initialize before first use; do not modify fields or copy a live object. Retain the object until owned_mask and selector_pending are both zero. owned_mask conservatively records cleanup responsibility, not enabled hardware bits.

Public Members

uint32_t owned_mask

Retained data/instruction cache responsibility.

uint32_t saved_selector

Original CSSELR for an unfinished operation.

bool selector_pending

Original selector restoration is outstanding.

features.h

Reviewed CPU mechanisms and allocation-free result types.

Author

Nexus Team

Enums

enum nx_arch_result_t

Result of a validated local CPU mechanism operation.

Values:

enumerator NX_ARCH_OK
enumerator NX_ARCH_INVALID
enumerator NX_ARCH_CONTEXT
enumerator NX_ARCH_UNSUPPORTED
enum nx_arch_security_state_t

Security state compiled for this firmware image.

Values:

enumerator NX_ARCH_SECURITY_SINGLE
enumerator NX_ARCH_SECURITY_SECURE
enumerator NX_ARCH_SECURITY_NONSECURE

Functions

nx_arch_features_t nx_arch_features(void)

Query immutable, compiled CPU mechanism capabilities.

Note

Read-only Task/IRQ query, no hardware access or discovery.

Returns:

Exact reviewed CPU facts; Native reports absent hardware.

struct nx_arch_features_t
#include <features.h>

Reviewed mechanisms in the exact compiled CPU profile.

Note

Cache sizes are zero when absent, MPU version is zero, seven or eight. These facts do not prove enabled hardware, memory reachability, cross-domain ownership or HIL status.

Public Members

uint32_t dcache_line_bytes
uint32_t icache_line_bytes
uint8_t mpu_version
bool dwt_cycle_counter
bool sau
nx_arch_security_state_t security_state

mpu.h

Distinct Armv7-M and Armv8-M MPU encoding mechanisms.

Author

Nexus Team

Functions

nx_arch_result_t nx_arch_mpu_v7_encode(const nx_arch_mpu_v7_region_t *region, nx_arch_mpu_v7_encoding_t *encoding)

Encode an exact Armv7-M region without accessing hardware.

Note

Pure bounded task/IRQ function. Inputs and output must not overlap. This encodes fields, not SoC memory reachability, cache ownership, DMA coherency or product protection policy.

Parameters:
  • region – [in] Size exponent 5..32, aligned base, AP 0/1/2/3/5/6, TEX 0..7 and raw S/C/B bits. Subregion mask is at most 255 and must be zero for sizes below 256 bytes. A 4 GiB region has base zero. Reserved/implementation-defined TEX/C/B encodings are rejected, never truncated or rounded.

  • encoding – [out] RBAR and enabled RASR; unchanged on failure.

Returns:

NX_ARCH_OK or NX_ARCH_INVALID, independent of CPU profile.

nx_arch_result_t nx_arch_mpu_v8_encode(const nx_arch_mpu_v8_region_t *region, nx_arch_mpu_v8_encoding_t *encoding)

Encode an exact Armv8-M region without accessing hardware.

Note

Pure bounded task/IRQ function. Inputs and output must not overlap. No address rounding or v7/v8 policy conversion.

Parameters:
  • region – [in] 32-byte aligned base, inclusive limit ending in 0x1f, base not above limit, AP 0..3, SH 0/2/3 and MAIR index 0..7. The caller owns the corresponding MAIR policy.

  • encoding – [out] RBAR and enabled RLAR; unchanged on failure.

Returns:

NX_ARCH_OK or NX_ARCH_INVALID, independent of CPU profile.

nx_arch_result_t nx_arch_mpu_v7_program(uint32_t index, const nx_arch_mpu_v7_region_t *region)

Program one disabled-MPU Armv7-M region in this world.

Note

Privileged Thread only with PRIMASK set and exclusive caller ownership of this MPU. NMI/HardFault/another security world must not modify it. Disables only the selected region, writes its fields, restores incoming RNR and leaves CTRL unchanged. No allocation, OS calls, implicit MPU enable, bulk clear or Secure access to the Non-secure alias.

Parameters:
  • index – [in] Region number below actual MPU_TYPE.DREGION.

  • region – [in] Fields validated by nx_arch_mpu_v7_encode.

Returns:

NX_ARCH_UNSUPPORTED before MMIO for a different/absent compiled MPU; NX_ARCH_INVALID for invalid fields or index; NX_ARCH_CONTEXT for an unprivileged, Handler, unmasked or enabled-MPU caller. Rejection performs no register writes.

nx_arch_result_t nx_arch_mpu_v8_program(uint32_t index, const nx_arch_mpu_v8_region_t *region)

Program one disabled-MPU Armv8-M region in this world.

Note

Privileged masked Thread, disabled MPU and exclusive local ownership required. No MAIR updates or cross-world alias access. Incoming RNR and CTRL are preserved.

Parameters:
  • index – [in] Region number below actual MPU_TYPE.DREGION.

  • region – [in] Fields validated by nx_arch_mpu_v8_encode.

Returns:

Same rejection and ownership rules as v7_program; the compiled MPU must specifically implement Armv8-M.

nx_arch_result_t nx_arch_mpu_v8_attribute_set(uint32_t index, uint32_t attribute)

Update one Armv8-M MAIR byte without changing its neighbors.

Note

Caller owns valid memory attributes and all regions using this slot. Privileged masked Thread, disabled MPU and exclusive local ownership required. No CTRL or RNR writes, no cache maintenance, and no cross-world register access.

Parameters:
  • index – [in] Attribute slot 0..7.

  • attribute – [in] Architectural MAIR byte, at most 255. Device encodings are 0x00/0x04/0x08/0x0c; Normal memory uses nonzero outer/inner nibbles other than reserved 0x8.

Returns:

NX_ARCH_OK, NX_ARCH_UNSUPPORTED for absent/v7 MPU, NX_ARCH_INVALID for an out-of-range field, or NX_ARCH_CONTEXT under the programming context rules.

struct nx_arch_mpu_v7_region_t
#include <mpu.h>

Armv7-M region fields, without an implicit memory policy.

Public Members

uint32_t base
uint32_t size_log2
uint32_t access
uint32_t tex
uint32_t subregion_disable
bool shareable
bool cacheable
bool bufferable
bool execute_never
struct nx_arch_mpu_v7_encoding_t
#include <mpu.h>

Armv7-M words targeting the caller-selected RNR, not RBAR.VALID.

Public Members

uint32_t rbar
uint32_t rasr
struct nx_arch_mpu_v8_region_t
#include <mpu.h>

Armv8-M fields; limit is the exact inclusive final byte.

Public Members

uint32_t base
uint32_t limit
uint32_t access
uint32_t shareability
uint32_t attribute_index
bool execute_never
struct nx_arch_mpu_v8_encoding_t
#include <mpu.h>

Armv8-M words retaining its separate MAIR indirection.

Public Members

uint32_t rbar
uint32_t rlar

nonsecure.h

Explicit NonSecure unprivileged address permission checks.

Author

Nexus Team

Enums

enum nx_arch_nonsecure_access_t

Requested NonSecure unprivileged CPU access, never execute access.

Values:

enumerator NX_ARCH_NONSECURE_READ
enumerator NX_ARCH_NONSECURE_READWRITE

Functions

nx_arch_result_t nx_arch_nonsecure_check(const void *address, size_t bytes, nx_arch_nonsecure_access_t access)

Check current NonSecure unprivileged access to a full span.

Note

Allocation-free permission observation only. Hardware CMSE checks both security attribution and NonSecure MPU rights as an unprivileged caller. Adjacent permitted regions may be conservatively rejected. No memory is copied, pinned or borrowed. Success neither authenticates a gateway caller nor proves RAM, DMA reachability, lifetime or fault safety. The integrating owner must exclude MMIO through its SoC RAM policy and prevent attribution/mapping changes through the subsequent access. Interrupts, another world, DMA and faults are not excluded here; no masks or hardware policy are changed. A gateway must separately snapshot its input and validate output before any irreversible operation.

Parameters:
  • address – [in] Non-null start; never dereferenced by this API.

  • bytes – [in] Positive length with a representable inclusive end.

  • access – [in] Exact READ or READWRITE access, never a bit mask.

Returns:

OK for complete current access; INVALID for malformed or denied spans; CONTEXT outside privileged Secure Thread; UNSUPPORTED in Native, single-state or NonSecure images.

security.h

Local security-state and explicit SAU region mechanisms.

Author

Nexus Team

Functions

nx_arch_security_state_t nx_arch_security_state(void)

Query this image’s compiled security state.

Note

Bounded read-only Task/IRQ query, no hardware access. This does not grant access to another world’s memory or devices.

Returns:

Single-domain, Secure or NonSecure reviewed image state.

nx_arch_result_t nx_arch_sau_encode(const nx_arch_sau_region_t *region, nx_arch_sau_words_t *words)

Encode an explicit SAU region without hardware access.

Note

Pure Task/IRQ operation. Encoding marks the requested region enabled but does not enable SAU hardware. External policy owns overlap, IDAU restrictions and NSC veneers.

Parameters:
  • region – [in] Base aligned to 32 bytes; inclusive limit ending at a complete 32-byte boundary. Base must not exceed limit.

  • words – [out] Encoded region, unchanged on failure.

Returns:

OK or INVALID for null arguments or invalid boundaries.

nx_arch_result_t nx_arch_sau_write(uint32_t index, const nx_arch_sau_region_t *region)

Program one owned SAU region while the SAU is disabled.

Note

Secure privileged Thread with incoming PRIMASK set only. Caller excludes all other region/selector users and keeps NMI/HardFault outside this metadata. Requires reviewed SAU region support. Does not modify CTRL, ALLNS, another region, another security world’s registers or enable the SAU. Current RNR is restored; DSB/ISB complete region writes. Policy, secure gateways and IDAU configuration stay external.

Parameters:
  • index – [in] Region index below the actual hardware TYPE count.

  • region – [in] Explicit reviewed region and NSC permission.

Returns:

OK, INVALID, CONTEXT or UNSUPPORTED without retained state.

nx_arch_result_t nx_arch_sau_clear(uint32_t index)

Disable one owned SAU region while the SAU is disabled.

Note

Same context and ownership contract as nx_arch_sau_write. Preserves CTRL, ALLNS, other regions and incoming RNR.

Parameters:
  • index – [in] Region index below the actual hardware TYPE count.

Returns:

OK, INVALID, CONTEXT or UNSUPPORTED without other writes.

struct nx_arch_sau_region_t
#include <security.h>

Exact 32-byte-aligned SAU region owned by the Secure caller.

Public Members

uint32_t base
uint32_t limit
bool nonsecure_callable
struct nx_arch_sau_words_t
#include <security.h>

Validated SAU words; encoding never changes hardware.

Public Members

uint32_t rbar
uint32_t rlar

sleep.h

Reviewed single-CPU shallow sleep contracts.

Author

Nexus Team

Version

1.0.0

Date

2026-10-11

Copyright

Copyright (c) 2026 Nexus Team

Functions

nx_arch_result_t nx_arch_wait_for_interrupt(void)

Wait once with configurable exceptions already masked.

Note

Privileged Thread mode, incoming PRIMASK=1, BASEPRI and FAULTMASK clear. SCR.SLEEPDEEP must be clear. The caller owns the final readiness check and timer/wake source. WFI wakes for a pending enabled interrupt despite PRIMASK; the interrupt runs after the caller restores its saved mask. No register, mask, clock or pending interrupt is changed. Current CPU/security state only; no physical HIL claim.

Returns:

OK after wake, CONTEXT or UNSUPPORTED without sleeping.

nx_arch_result_t nx_arch_idle_if_unchanged(const uint32_t *sequence, uint32_t expected, bool *slept)

Atomically recheck a published sequence before WFI.

Note

Privileged Thread mode with all incoming masks clear. Saves PRIMASK, performs acquire observation under that mask, optionally sleeps, and restores the exact mask. Publishers must be same-CPU configurable IRQs or Threads; NMI/HardFault, DMA, SMP and other security-world publishers are excluded. The caller keeps storage alive, owns an enabled IRQ timer for finite deadlines, and retries the authoritative predicate after wake. Native is unsupported.

Parameters:
  • sequence – [in] Naturally aligned, shared 32-bit wake sequence.

  • expected – [in] Snapshot before the caller’s readiness check.

  • slept – [out] True only when WFI was executed.

Returns:

OK, INVALID, CONTEXT or UNSUPPORTED.