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

virtio-blk storage via mmio using virtio-drivers [v2] #542

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

osteffenrh
Copy link
Contributor

@osteffenrh osteffenrh commented Nov 28, 2024

This is version 2 of #343.

Add support for virtio-blk storage devices using the virtio-mmio transport.
MMIO accesses are done via explicit vmgexits. Interrupts are not used (-> polling).

The virtio-drivers crate from the rcore-os project is used. It required some modifications: osteffenrh/virtio-drivers#2
Crate License: MIT.

This PR requires a patched version of Qemu (coconut-svsm/qemu#13), adding virtio-mmio slots to the Q35 machine model.

This build on #531

How to test:

ToDo:

  • Write block size / buffer size is limited to max 4k, needs improvement of bounce buffer handling
  • Proper error codes for the block layer and driver impl.
  • Supply the MMIO base address via IGVM file

Fixes since V1:

  • SMP works, mmio range is mapped for all cpus
  • rebased to latest versions of Coconut and virtio-drivers

Things for future PRs:

  • encryption layer
  • file system

CC: @stefano-garzarella ;-)

@joergroedel joergroedel added the wait-for-review PR needs for approval by reviewers label Dec 5, 2024
@osteffenrh osteffenrh force-pushed the virtio-pr-2 branch 5 times, most recently from 8f52f24 to 3aaa640 Compare December 9, 2024 09:44
Use the latest version of the zerocopy crate, to match the one used by
the virtio-drivers crate.

Signed-off-by: Oliver Steffen <[email protected]>
Add mmio read and write functions.

ToDo: Improve read_buffer() to be similar to write_buffer().

Signed-off-by: Oliver Steffen <[email protected]>
@osteffenrh osteffenrh force-pushed the virtio-pr-2 branch 2 times, most recently from 0383221 to 1f1362b Compare December 9, 2024 20:07
osteffenrh and others added 6 commits December 9, 2024 21:19
Add the virtio-drivers crate; implement a Hal for Coconut that uses
the ghcb mmio functions, and manages bounce-buffers in host-shared memory.

The buffers use SharedBox and are currently limited to 1 page in size.
The SharedBoxes need to be kept around between the share() and unshare()
calls, thus a global manager was added that holds them.

ToDo: Allow arbitrary buffer sizes.

Signed-off-by: Oliver Steffen <[email protected]>
Add a simple block layer api trait.

Co-developed-by: Oliver Steffen <[email protected]>
Signed-off-by: Oliver Steffen <[email protected]>
Signed-off-by: Stefano Garzarella <[email protected]>
Add command line option to add a virtio-blk MMIO device to the CVM.

Signed-off-by: Stefano Garzarella <[email protected]>
Add a block device driver that uses the virito-blk via
mmio transport.

ToDo: Return proper error codes.

Co-developed-by: Oliver Steffen <[email protected]>
Signed-off-by: Oliver Steffen <[email protected]>
Signed-off-by: Stefano Garzarella <[email protected]>
Add simple write+readback tests for the VirtioBlkDriver.

Signed-off-by: Oliver Steffen <[email protected]>
Add a virtio-blk device to the in-svsm test setup to allow
the VirtioBlkDriver tests to run.

Signed-off-by: Oliver Steffen <[email protected]>
Copy link
Member

@joergroedel joergroedel left a comment

Choose a reason for hiding this comment

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

I think this is a great start for getting block-device support into COCONUT-SVSM. The PR uncovers some problems in the code base and I think we should seriously consider pulling the virtio-drivers directly into our code-base and change the interfaces to our needs.

Comment on lines +14 to +15
fn read_blocks(&self, block_id: usize, buf: &mut [u8]) -> Result<(), BlockDeviceError>;
fn write_blocks(&self, block_id: usize, buf: &[u8]) -> Result<(), BlockDeviceError>;
Copy link
Member

Choose a reason for hiding this comment

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

This interface makes the safe-unsafe memory boundary a bit blurry and looks unsafe in itself (due to the slice parameters). I have seen this interface somewhat resembles the interface of the virtio-blk driver crate. Maybe it is the best strategy to import the drivers into our code-base and improve their interfaces.

Some things I'd like to see:

  • Asynchronous interface with a separate request tracking data structure and polling methods.
  • Better abstractions for the source/target memory regions of block access.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

About async:
The virtio-drivers crate has non-blocking read/write functions, see https://github.com/osteffenrh/virtio-drivers/blob/63c5450f08bd557f609e0ffad7a5bd6281d6562e/src/device/blk.rs#L248
But I did not try that yet.

About the second point:
The buffer supplied to these functions is copied over to a new one, allocated via SharedBox when writing (and the reverse for reading). We are not sharing existing allocations with the host.

Comment on lines +322 to +326
{
use svsm::block::virtio_blk;
static MMIO_BASE: u64 = 0xfef03000;
let _blk = virtio_blk::VirtIOBlkDriver::new(PhysAddr::from(MMIO_BASE));
}
Copy link
Member

Choose a reason for hiding this comment

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

We should start thinking about a proper detection mechanism for SVSM-assigned devices.

Copy link
Member

Choose a reason for hiding this comment

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

@joergroedel yeah, should be some runtime discover mechanism (e.g. fw-cfg) or a static configuration through IGVM? Or both?

Copy link

Choose a reason for hiding this comment

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

The qemu patch adds four virtio-mmio transport slots at 0xfef00000 ... 0xfef03fff. So the very minimum would be to loop over these four slots, check whenever a virtio device is present, if so what kind of virtio device it is. Only after that attach a driver.

Separate question is whenever we'll just hardcode those four slots in both qemu and svsm, or whenever it makes sense to communicate the range from qemu to svsm via fw_cfg. I honestly don't see much benefit in making this configurable. There are not that many options to place the virtio-mmio transport slots anyway ...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

How about build time option that puts it into the igvm file as a start.
And use the range @kraxel picked as the default on both sides (Coconut and Qemu).

Comment on lines +22 to +24
struct PageStore {
pages: Vec<(PhysAddr, SharedBox<[u8; PAGE_SIZE]>)>,
}
Copy link
Member

Choose a reason for hiding this comment

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

Nothing wrong with this code, but I think this uncovers a fundamental problem with SharedBox which we need to solve separately. Reading any any memory in a SharedBox is UB, so it should have a read()/write() interface instead of direct data access.

@joergroedel joergroedel added in-review PR is under active review and not yet approved and removed wait-for-review PR needs for approval by reviewers labels Dec 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in-review PR is under active review and not yet approved
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants