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

Add support for virtio #156

Merged
merged 10 commits into from
Aug 31, 2023
Merged

Add support for virtio #156

merged 10 commits into from
Aug 31, 2023

Conversation

zpzigi754
Copy link
Collaborator

@zpzigi754 zpzigi754 commented Aug 28, 2023

This PR enables realm to use virtio (e.g., file system access) by allowing shared pages to be accessed by the Host. With this PR, realm-linux will be able to boot to the shell with islet.

Memory sharing between Realm and the Host

Realm can modify its private region into a shared region by invoking RSI_IPA_STATE_SET with RIPAS:empty (Figure D2.1 Realm shared memory protocol flow in rmm-spec). With the following RMI_RTT_SET_RIPAS, this triggers a set of actions by the Host (e.g., RTT_SET_RIPAS->RTT_READ_ENTRY->DATA_DESTROY) according to the value of RTT entry for freeing regions (For more about detail, please refer to realm_tear_down_rtt_range() in nw-linux). This PR fills this flow.

About fault redirection

linux-cca controls the accesses to the encrypted/decrypted page with the bit 33 in Realm's page table entry (the bit location can be configured by the user). The previous RSI_REALM_CONFIG returns an incorrect value which resulted in improper fault generation. For example, the access to a decrypted page (e.g., 0x184c00000) always triggered a fault for its encrypted page (e.g., 0x84c00000), while it should have been treated as the decrypted page. With the fix, the two different kind of accesses can be distinguished and handled properly.

Using level in page table traversing

In page table traversing API, (input) level and (output) level are added which is useful for the fine-grained traversing. (input) level indicates the intended (maximum) level to reach, while (output) level is the actual level reached (e.g., If the user passes 3 for (input) level and there are upto level 2 page tables for the given address, it would return 2 for the (output) level).

Additional Notes

Currently, islet's page table traversing (e.g., ipa_to_pa()) in default checks its validity with bit 0. However, this cannot be done in stage 2 page table, as bit [0-1] is used as description type, and valid page table entry has that bit on.
In this PR, ipa_to_pte() is added and this function does not conduct the bit 0 based validity check (here no_valid_check: true is passed in entry()) and returns the whole entry's value.

Also, page table entry modification in default attaches unintended flags which is not compatible with stage 2 table entry (e.g., RIPAS, HIPAS field). To avoid incorrect bits to be set, I've added is_raw parameter in PTE modification APIs, which when set as true, only sets the flags that the users have provided.

Remaining issue

  • TF-A failure case (will be resolved in another PR)

The previous script seems to have a consistency issue, as using it
together with realm's new configuration regarding ipa bits (the
following commit) causes a fault while processing `parse_early_param()`
in ./arch/arm64/kernel/setup.c.
@jinbpark
Copy link
Collaborator

Not ready for review, but I want to say that this is a huge step forward! Great work in advance!

@zpzigi754 zpzigi754 changed the title [draft] Add support for virtio Add support for virtio Aug 30, 2023
@zpzigi754 zpzigi754 marked this pull request as ready for review August 30, 2023 01:32
@zpzigi754 zpzigi754 linked an issue Aug 30, 2023 that may be closed by this pull request
@zpzigi754
Copy link
Collaborator Author

Not ready for review, but I want to say that this is a huge step forward! Great work in advance!

Thank you for the comment. Now, it gets ready!

Copy link
Collaborator

@bitboom bitboom left a comment

Choose a reason for hiding this comment

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

What a great PR !!

rmm/armv9a/src/realm/registry.rs Outdated Show resolved Hide resolved
rmm/monitor/src/rmi/rtt.rs Outdated Show resolved Hide resolved
rmm/monitor/src/rmi/rtt.rs Outdated Show resolved Hide resolved
}

if ripas as u64 == RIPAS_EMPTY {
let ret = rmi.make_shared(rd.id(), ipa, level);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just question: is the given level always "3" (the last level == page) throughout the realm-linux booting?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good question. RMI_RTT_SET_RIPAS's level is actually determined by RSI_IPA_STATE_SET's level and realm-linux uses 3 throughout the booting. BTW, RMI_RTT_READ_ENTRY uses both of level 2 and 3.

let _ret = rmi.map(realm_id, ipa, ns_pa, granule_sz, prot.get());
let level = arg[2];
let host_s2tte = arg[3];
rmi.rtt_map_unprotected(realm_id, ipa, level, host_s2tte)?;
Copy link
Collaborator

@jinbpark jinbpark Aug 31, 2023

Choose a reason for hiding this comment

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

Just question:
doing RTT_MAP_PROTECTED through rtt_map_unprotected() but RTT_UNMAP_UNPROTECTED through the existing unmap(). Is it ok? (I guess it would be ok because what "unset_page" typically does it just set 0)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Frankly speaking, I am not sure, because I've not tested unmap_unprotected. Actually, there seems no call to RTT_UNMAP_PROTECTED in realm-linux booting, while there are several calls to RTT_MAP_PROTECTED.

linux-cca controls the accesses to the encrypted/decrypted page with
the bit 33 in Realm's page table entry (the bit location can be
configured by the user). The previous RSI_REALM_CONFIG returns an
incorrect value which resulted in improper fault generation. For example,
the access to a decrypted page (e.g., 0x184c00000) always triggered a
fault for its encrypted page (e.g., 0x84c00000), while it should have
been treated as the decrypted page. With the fix, the two different kind
of accesses can be distinguished and handled properly.

Reference (realm-linux) : __set_memory_encrypted() in arch/arm64/mm/pageattr.c
In page table traversing API, (input) level and (output) level are
added which is useful for the fine-grained traversing. (input) level
indicates the intended (maximum) level to reach, while (output) level
is the actual level reached. For example, if the user passes 3 for
(input) level and there are upto level 2 page tables for the given
address, it would return 2 for the (output) level.
This commit enables realm to use virtio (e.g., file system access) by
allowing shared pages to be accessed by the Host. With this commit,
realm-linux will be able to boot to the shell with islet.

[Memory sharing between Realm and the Host]

Realm can modify its private region into a shared region by invoking
`RSI_IPA_STATE_SET` with RIPAS:empty (ref. Figure D2.1 Realm shared
memory protocol flow in rmm-spec). With the following `RMI_RTT_SET_RIPAS`,
this triggers a set of actions by the Host (e.g., `RTT_SET_RIPAS`->
`RTT_READ_ENTRY`->`DATA_DESTROY`) according to the value of RTT entry
for freeing regions (For more about the detail, please refer to
realm_tear_down_rtt_range() in nw-linux). This commit fills this flow.

[Additional Notes]

Currently, `islet`'s page table traversing (e.g., ipa_to_pa()) in default
checks its validity with bit 0. However, this cannot be done in stage 2
page table, as bit [0-1] is used as description type and valid page table
entry has that bit on. In this commit, `ipa_to_pte()` does not conduct
the bit 0 based validity check (here `no_valid_check`: true is passed in
`entry()`).

Also, page table entry modification in default attaches unintended flags which
is not compatible with stage 2 table entry (e.g., RIPAS, HIPAS field).
To avoid incorrect bits to be set, I've added `is_raw` parameter in PTE
modification APIs, which when set as true, only sets the flags that
the users have provided.
(in realm linux booting)
...
[DEBUG]armv9a::exception::trap -- Synchronous: InstructionAbort | DataAbort
[DEBUG]armv9a::exception::trap -- fipa: 85ED5000
[TRACE]monitor::event -- RMI: REC_ENTER            [881781000, 881780000] > [0]
[ERROR]armv9a::panic -- RMM: panicked at 'OOM! memory allocation of 3146888 bytes
failed', rmm/armv9a/src/panic.rs:3:5
@zpzigi754 zpzigi754 merged commit 1f2c301 into islet-project:main Aug 31, 2023
5 checks passed
@zpzigi754 zpzigi754 deleted the virtio branch September 4, 2023 02:03
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.

Fix a bus fault in realm booting Realm linux kernel booting log (stuck point)
3 participants