Skip to content

Commit

Permalink
arm: verification tweaks for SGI API
Browse files Browse the repository at this point in the history
- introduce arch interface for IRQControlCap dependencies as well as for
  isMDBParentOf (Arch_isIRQControlDescendant, Arch_isMDBParentOf). This
  mirrors the corresponding interface in the proofs and Haskell and
  avoids #ifdef proliferation in generic code.
- Arch_isIRQControlDescendant is currently only used for SGISignalCaps
- Arch_isMDBParentOf is used for SGISignalCaps and SMCCaps
- fix argument checking in Arch_decodeIRQControlInvocation (+ style
  tweak)
- Arch_sameObjectAs must return false for SGISignalCaps to align with
  finality definition of caps, i.e. SGISignalCaps are always final. This
  has no behaviour change, because finality doesn't matter for behaviour
  for SGISignalCaps, but we require for the proofs that the concept of
  finality aligns with the spec.
- simplify checks for IRQControlCap in sameObjectAs: sameObjectAs can
  never be true for IRQControlCap.

Signed-off-by: Gerwin Klein <gerwin.klein@proofcraft.systems>
  • Loading branch information
lsf37 committed Mar 14, 2024
1 parent c9e5e77 commit 0d4fe26
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 33 deletions.
49 changes: 49 additions & 0 deletions include/arch/arm/arch/object/objecttype.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,52 @@ word_t Arch_getObjectSize(word_t t);
static inline void Arch_postCapDeletion(cap_t cap)
{
}

/**
* Return true if the given arch cap can be a descendant of an IRQControlCap.
*/
static inline CONST bool_t Arch_isIRQControlDescendant(cap_t cap)
{
#if CONFIG_MAX_NUM_NODES == 1
return cap_get_capType(cap) == cap_sgi_signal_cap;
#else
return false;
#endif
}

/**
* isMDBParentOf for architecture caps. For most arch caps, this just returns
* true, but if there are badged versions of arch caps, this functions should
* perform the necessary checks.
*
* Called by the generic isMDBParentOf after the revocable bit has been checked
* and sameRegionAs has been established. This means we can assume both as true
* inside Arch_isMDBParentOf.
*/
static inline CONST bool_t Arch_isMDBParentOf(cap_t cap_a, cap_t cap_b, bool_t firstBadged)
{
switch (cap_get_capType(cap_a)) {
#if CONFIG_MAX_NUM_NODES == 1
case cap_sgi_signal_cap:
return !firstBadged;
break;
#endif

#ifdef CONFIG_ALLOW_SMC_CALLS
case cap_smc_cap: {
word_t badge;

badge = cap_smc_cap_get_capSMCBadge(cap_a);
if (badge == 0) {
return true;
}
return (badge == cap_smc_cap_get_capSMCBadge(cap_b)) &&
!firstBadged;
break;
}
#endif

default:
return true;
}
}
13 changes: 8 additions & 5 deletions include/arch/arm/arch/object/structures.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,20 @@

static inline bool_t CONST Arch_isCapRevocable(cap_t derivedCap, cap_t srcCap)
{
#ifdef CONFIG_ALLOW_SMC_CALLS
switch (cap_get_capType(derivedCap)) {

#if CONFIG_MAX_NUM_NODES == 1
case cap_sgi_signal_cap:
return cap_get_capType(srcCap) == cap_irq_control_cap;
#endif

#ifdef CONFIG_ALLOW_SMC_CALLS
case cap_smc_cap:
return (cap_smc_cap_get_capSMCBadge(derivedCap) !=
cap_smc_cap_get_capSMCBadge(srcCap));
#endif

default:
return false;
}
#endif
return false;
}


15 changes: 15 additions & 0 deletions include/arch/riscv/arch/object/objecttype.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,18 @@ static inline void Arch_postCapDeletion(cap_t cap)
{
}

/**
* Return true if the given arch cap can be a descendant of an IRQControlCap.
*/
static inline CONST bool_t Arch_isIRQControlDescendant(cap_t cap)
{
return false;
}

/**
* isMDBParentOf for architecture caps. See Arm version for more detailed docs.
*/
static inline CONST bool_t Arch_isMDBParentOf(cap_t cap_a, cap_t cap_b, bool_t firstBadged)
{
return true;
}
15 changes: 15 additions & 0 deletions include/arch/x86/arch/object/objecttype.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,18 @@ word_t Mode_getObjectSize(word_t t);

void Arch_postCapDeletion(cap_t cap);

/**
* Return true if the given arch cap can be a descendant of an IRQControlCap.
*/
static inline CONST bool_t Arch_isIRQControlDescendant(cap_t cap)
{
return false;
}

/**
* isMDBParentOf for architecture caps. See Arm version for more detailed docs.
*/
static inline CONST bool_t Arch_isMDBParentOf(cap_t cap_a, cap_t cap_b, bool_t firstBadged)
{
return true;
}
6 changes: 6 additions & 0 deletions src/arch/arm/32/object/objecttype.c
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,12 @@ bool_t CONST Arch_sameObjectAs(cap_t cap_a, cap_t cap_b)
return false;
}
}
#if CONFIG_MAX_NUM_NODES == 1
if (cap_get_capType(cap_a) == cap_sgi_signal_cap) {
return false;
}
#endif

return Arch_sameRegionAs(cap_a, cap_b);
}

Expand Down
6 changes: 6 additions & 0 deletions src/arch/arm/64/object/objecttype.c
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,12 @@ bool_t CONST Arch_sameObjectAs(cap_t cap_a, cap_t cap_b)
return false;
}
#endif
#if CONFIG_MAX_NUM_NODES == 1
if (cap_get_capType(cap_a) == cap_sgi_signal_cap) {
return false;
}
#endif

return Arch_sameRegionAs(cap_a, cap_b);
}

Expand Down
4 changes: 2 additions & 2 deletions src/arch/arm/object/interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ exception_t Arch_decodeIRQControlInvocation(word_t invLabel, word_t length,
return Arch_invokeIRQControl(irq, destSlot, srcSlot, trigger);
#if CONFIG_MAX_NUM_NODES == 1
} else if (invLabel == ARMIRQIssueSGISignal) {
if (length < 3 || current_extra_caps.excaprefs[0] == NULL) {
if (length < 4 || current_extra_caps.excaprefs[0] == NULL) {
userError("IRQControl: IssueSGISignal: Truncated message.");
current_syscall_error.type = seL4_TruncatedMessage;
return EXCEPTION_SYSCALL_ERROR;
Expand All @@ -107,7 +107,7 @@ exception_t Arch_decodeIRQControlInvocation(word_t invLabel, word_t length,
if (irq >= NUM_SGIS) {
current_syscall_error.type = seL4_RangeError;
current_syscall_error.rangeErrorMin = 0;
current_syscall_error.rangeErrorMax = NUM_SGIS -1;
current_syscall_error.rangeErrorMax = NUM_SGIS - 1;
userError("IRQControl: IssueSGISignal: Invalid SGI IRQ 0x%lx.", irq);
return EXCEPTION_SYSCALL_ERROR;
}
Expand Down
18 changes: 4 additions & 14 deletions src/object/cnode.c
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,10 @@ bool_t PURE isMDBParentOf(cte_t *cte_a, cte_t *cte_b)
if (!sameRegionAs(cte_a->cap, cte_b->cap)) {
return false;
}
if (!Arch_isMDBParentOf(cte_a->cap, cte_b->cap,
mdb_node_get_mdbFirstBadged(cte_b->cteMDBNode))) {
return false;
}
switch (cap_get_capType(cte_a->cap)) {
case cap_endpoint_cap: {
word_t badge;
Expand All @@ -805,20 +809,6 @@ bool_t PURE isMDBParentOf(cte_t *cte_a, cte_t *cte_b)
break;
}

#ifdef CONFIG_ALLOW_SMC_CALLS
case cap_smc_cap: {
word_t badge;

badge = cap_smc_cap_get_capSMCBadge(cte_a->cap);
if (badge == 0) {
return true;
}
return (badge == cap_smc_cap_get_capSMCBadge(cte_b->cap)) &&
!mdb_node_get_mdbFirstBadged(cte_b->cteMDBNode);
break;
}
#endif

default:
return true;
break;
Expand Down
15 changes: 3 additions & 12 deletions src/object/objecttype.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,10 +342,8 @@ bool_t CONST sameRegionAs(cap_t cap_a, cap_t cap_b)

case cap_irq_control_cap:
if (cap_get_capType(cap_b) == cap_irq_control_cap ||
#if CONFIG_MAX_NUM_NODES == 1
cap_get_capType(cap_b) == cap_sgi_signal_cap ||
#endif
cap_get_capType(cap_b) == cap_irq_handler_cap) {
cap_get_capType(cap_b) == cap_irq_handler_cap ||
Arch_isIRQControlDescendant(cap_b)) {
return true;
}
break;
Expand Down Expand Up @@ -388,16 +386,9 @@ bool_t CONST sameObjectAs(cap_t cap_a, cap_t cap_b)
if (cap_get_capType(cap_a) == cap_untyped_cap) {
return false;
}
if (cap_get_capType(cap_a) == cap_irq_control_cap &&
cap_get_capType(cap_b) == cap_irq_handler_cap) {
return false;
}
#if CONFIG_MAX_NUM_NODES == 1
if (cap_get_capType(cap_a) == cap_irq_control_cap &&
cap_get_capType(cap_b) == cap_sgi_signal_cap) {
if (cap_get_capType(cap_a) == cap_irq_control_cap) {
return false;
}
#endif
if (isArchCap(cap_a) && isArchCap(cap_b)) {
return Arch_sameObjectAs(cap_a, cap_b);
}
Expand Down

0 comments on commit 0d4fe26

Please sign in to comment.