Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Morello] Change the PCS to pass memory arguments through C9 instead of passing them on the stack #205

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

sbaranga-arm
Copy link
Contributor

In practice for non-compartment calls the arguments are still passed on the stack, although now there is no explicit requirement for this.

Variadic arguments are still passed through C9 in the same way, at the first 16-byte aligned location after the last non-variadic argument.

This is done is such a way that reading more variadic arguments than were passed is guaranteed to cause an out-of-bounds fault.

Implements #158.

@@ -380,7 +380,7 @@ Additionally, a stack-pointer register, SP in a 64-bit context or CSP in a capab
+------------+----------+----------------------------------------------------------------------------------------------------+
| r10-r15 | | Temporary registers. |
+------------+----------+----------------------------------------------------------------------------------------------------+
| r9 | | Parameter register for variadic calls, temporary register otherwise. |
| r9 | | Parameter register for memory passed arguments, temporary register otherwise. |

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think "memory-passed" would be clearer (there is normally a dash between a noun and the adjective it modifies).

| | If any parameters are memory passed in AAPCS64-cap, the Arguments Memory Area is |
| | allocated. |
| | The Arguments Memory area is 16-byte aligned. The Arguments Capability has the |
| | bounds of the Arguments Memory area and Arguments Memory area and the address of the |

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"and Arguments Memory area" is repeated.

@@ -808,7 +815,7 @@ The ``va_list`` type may refer to any parameter in a parameter list. All Anonymo
The va_start() macro
--------------------

The ``va_start`` macro shall initialize the ``va_list`` argument to the value of C9 as seen in the entry of the callee.
The ``va_start`` macro shall initialize the ``va_list`` argument to the value of derived from C9 with the address of the first Anonymous argument.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/of derived/derived/
It also feels strange to say the value derived from [...], rather a value? Using "value" feels a bit confusing too as it seems to refer to the capability address in other places.

+------------------------------+------------------------------------------------------------------------------------------+


.. note::
The Arguments Capability is a capability that has the bounds of the arguments memory area and its address will be that of the first memory passed argument. The address of the Arguments Capability is 16-byte aligned. The capability offset of the Arguments Capability may not be zero. The capability offset is such that the first 16-byte aligned location after the last memory passed argument will be larger or equal than capability limit of the Arguments Capability.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"larger than or equal to the capability limit..."

I wonder if this paragraph shouldn't start by explaining how the Arguments Memory Area is defined. I don't really understand how it all fits in terms of bounds representability right now.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree about the precision issues, but also it'd be very useful to include a diagram here. I don't know if we have the infrastructure for that in this document, but it would really help.

I'm a bit confused about the relationship between the offset and bounds at various points. For example, here the "address will be that of the first memory passed argument", but also its offset may not be zero. However, won't the first memory-passed argument be allocated to the first slot in the arguments memory area, and therefore require an offset of zero?

It's likely that I've just misunderstood something obvious!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I'll try to clarify this in some way and look at adding a diagram. We need to add some padding at the start of the arguments area to make the length representable. So the 'offset' (maybe this should be 'capability offset'?) is just the size of the padding, and the first argument (and first slot) is located at the address (capability value in Morello terms) of C9.

We don't say how the (capability) offset is computed and leave that up to the implementation. In practice the way to do this would be to run the algorithm once to get the number of bytes that we need for argument passing and compute from that the minimal amount of padding required to make everything representable. With the current wording we can have multiple legal values of offset, but just one being minimal/optimal.

Hopefully this clarifies things?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, that does clarify things, but couldn't the offset still be zero in the (common) case where the area is precisely representable without padding?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the moment any sane implementation should give a zero offset in this case. We could add the additional constraint that the offset needs to be minimal, which would then require a zero offset. Any thoughts?


In AAPCS64-cap if the callee is variadic and there are fewer than 4096 Anonymous arguments, the length of C9 divided by 16 is equal to the number of Anonymous arguments. The length of C9 divided by 16 is always greater or equal to the number of Anonymous arguments.
.. note::
In AAPCS64-cap if the callee is variadic the number of Anonymous arguments is equal to (length(C)-offset(C)/16) where C is the adjusted value of C9 that has the address of the first Anonymous Argument.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be (length(C)-offset(C))/16 instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, thanks for catching that.

@@ -808,7 +815,7 @@ The ``va_list`` type may refer to any parameter in a parameter list. All Anonymo
The va_start() macro
--------------------

The ``va_start`` macro shall initialize the ``va_list`` argument to the value of C9 as seen in the entry of the callee.
The ``va_start`` macro shall initialize the ``va_list`` argument to the value of derived from C9 with the address of the first Anonymous argument.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than C9, consider referring to "the Arguments Capability". A compiler might need to spill it (or move it to something callee-saved) before va_start is called.

+------------------------------+------------------------------------------------------------------------------------------+


.. note::
The Arguments Capability is a capability that has the bounds of the arguments memory area and its address will be that of the first memory passed argument. The address of the Arguments Capability is 16-byte aligned. The capability offset of the Arguments Capability may not be zero. The capability offset is such that the first 16-byte aligned location after the last memory passed argument will be larger or equal than capability limit of the Arguments Capability.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree about the precision issues, but also it'd be very useful to include a diagram here. I don't know if we have the infrastructure for that in this document, but it would really help.

I'm a bit confused about the relationship between the offset and bounds at various points. For example, here the "address will be that of the first memory passed argument", but also its offset may not be zero. However, won't the first memory-passed argument be allocated to the first slot in the arguments memory area, and therefore require an offset of zero?

It's likely that I've just misunderstood something obvious!


The Rounded Memory Arguments Length (RMAL) is the least representable capability length greater or equal to MAL.

The size of the Arguments Memory Area is equal to RNML. The minimal alignment of the Arguments Memory Area is 16 bytes. The alignment of the Arguments Memory Area is large enough to allow the bounds of the Arguments Memory Area to be exactly representable by a capability.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't find the defiinition of RNML, could it be RMAL?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Yes, it should have been RMAL.

instead of passing them on the stack.

In practice for non-compartment calls the arguments are
still passed on the stack, although now there is no explicit
requirement for this.

Variadic arguments are still passed through C9 in the same
way, at the first 16-byte aligned location after the last
non-variadic argument.

This is done is such a way that reading more variadic
arguments than were passed is guaranteed to cause an
out-of-bounds fault.

Implements ARM-software#158.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants