Skip to content

Conversation

@AlexOrozco1256
Copy link
Contributor

We are working with the project Oak team to enable running Oak Containers on cloud hypervisor. These containers are SEV-SNP enlightened and can be used alongside with the rest of the oak suite for attestation and measurement of the cvm.

Here is the functionality we are adding to CHV.

  1. Implmenting the sev-snp APIs previously defined (sev_snp_init, import_isolated_pages, complete_isolated_import).
  2. Expanded the igvm loader to support booting KVM + SEV-SNP enabled VMs. (Note that we can also use the igvm loader to boot VMs with standard cloud images with/without sev-snp enabled as seen here (https://github.com/AlexOrozco1256/chv-demo)
  3. Added a fw_cfg device with DMA enabled. Oak's Stage0 firmware uses fw_cfg for loading various parameters into the VM.

Additional design/implementation details can be found here: https://tinyurl.com/chv-kvm-sev-snp

See: #6653

@AlexOrozco1256 AlexOrozco1256 requested a review from a team as a code owner June 4, 2025 17:36
@AlexOrozco1256
Copy link
Contributor Author

AlexOrozco1256 commented Jun 4, 2025

Here is how I tested the fw_cfg device. These are the same steps as the direct kernel boot instructions in the README for the chv repo.

The only difference is that we must enable CONFIG_FW_CFG_SYSFS in the cloud hypervisor linux kernel.

Here is how to build and run the vm with fw_cfg device.

git clone --depth 1 https://github.com/cloud-hypervisor/linux.git -b ch-6.12.8 linux-cloud-hypervisor
### ENABLE CONFIG_FW_CFG_SYSFS in arch/x86/configs/ch_defconfig
pushd linux-cloud-hypervisor
make ch_defconfig
KCFLAGS="-Wa,-mx86-used-note=no" make bzImage -j `nproc`
popd

wget https://cloud-images.ubuntu.com/oracular/current/oracular-server-cloudimg-amd64.img
qemu-img convert -p -f qcow2 -O raw oracular-server-cloudimg-amd64.img oracular-server-cloudimg-amd64.raw

echo "Hello from fw_cfg!" > /tmp/fw_cfg_test_item

git clone https://github.com/AlexOrozco1256/chv-g.git -b pr-fw_cfg
pushd chv-g
cargo build --features fw_cfg
./scripts/create-cloud-init.sh
popd

./chv-g/target/debug/cloud-hypervisor \
	--kernel linux-cloud-hypervisor/arch/x86/boot/compressed/vmlinux.bin \
	--disk path=oracular-server-cloudimg-amd64.raw path=/tmp/ubuntu-cloudinit.img\
	--cmdline "console=hvc0 root=/dev/vda1 rw" \
	--cpus boot=4 \
	--memory size=4G \
        --fw-cfg-config initramfs=off,items=[name=opt/org.test/fw_cfg_test_item,file=/tmp/fw_cfg_test_item] \
	--net "tap=,mac=,ip=,mask="

Now log into the vm with:
User: cloud
Password:cloud123

sudo cat /sys/firmware/qemu_fw_cfg/by_name/opt/org.test/fw_cfg_test_item/raw
Hello from fw_cfg!

@rbradford
Copy link
Member

@AlexOrozco1256 Please can you rebase to get rid of the merge commit?

@AlexOrozco1256
Copy link
Contributor Author

@AlexOrozco1256 Please can you rebase to get rid of the merge commit?

Done.

Copy link
Member

@rbradford rbradford left a comment

Choose a reason for hiding this comment

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

I'm happy to go ahead with this (with those logging nits fixed) - i've mainly focused my review time on the generic changes.

Thank you so much for your patience!

Let's also think about the route to making this non-feature flag so that we can use it for booting a (less modified) edk2.

rbradford
rbradford previously approved these changes Jun 10, 2025
Copy link
Member

@rbradford rbradford left a comment

Choose a reason for hiding this comment

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

Still lgtm! Thanks.

@likebreath likebreath self-requested a review June 10, 2025 19:23
@AlexOrozco1256
Copy link
Contributor Author

I'm happy to go ahead with this (with those logging nits fixed) - i've mainly focused my review time on the generic changes.

Thank you so much for your patience!

Let's also think about the route to making this non-feature flag so that we can use it for booting a (less modified) edk2.

Thanks for the review! I will look into edk2 to see what else besides fw_cfg is missing.

Copy link
Member

@likebreath likebreath left a comment

Choose a reason for hiding this comment

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

Thank you for the good work. Besides comments below, couple other thoughts:

  1. Please extend our GH workflows (mostly quality.yaml and build.yaml) to cover the fw_cfg feature flag;
  2. Please add a documentation to explain what it does and how to use it;

Also, looks like adding CONFIG_FW_CFG_SYSFS to the guest kernel config is the only missing bit to add an integration test on fw_cfg, as what you described here.

If that's the case, It'd be great to have that integration test added, and I can help with adding the missing kernel config to reference kernel being used by our CI. (This is not required, since we don't require integration test for features behind feature flags).

Comment on lines +198 to +499
#[cfg(target_arch = "x86_64")]
let mut mem_regions = vec![
(GuestAddress(0), EBDA_START.0 as usize, RegionType::Ram),
(
MEM_32BIT_DEVICES_START,
MEM_32BIT_DEVICES_SIZE as usize,
RegionType::Reserved,
),
(
PCI_MMCONFIG_START,
PCI_MMCONFIG_SIZE as usize,
RegionType::Reserved,
),
(STAGE0_START_ADDRESS, STAGE0_SIZE, RegionType::Reserved),
];
#[cfg(target_arch = "aarch64")]
let mut mem_regions = arch::aarch64::arch_memory_regions();
if mem_size < MEM_32BIT_DEVICES_START.0 as usize {
mem_regions.push((
HIGH_RAM_START,
mem_size - HIGH_RAM_START.0 as usize,
RegionType::Ram,
));
} else {
mem_regions.push((
HIGH_RAM_START,
MEM_32BIT_RESERVED_START.0 as usize - HIGH_RAM_START.0 as usize,
RegionType::Ram,
));
mem_regions.push((
RAM_64BIT_START,
mem_size - (MEM_32BIT_DEVICES_START.0 as usize),
RegionType::Ram,
));
}
Copy link
Member

Choose a reason for hiding this comment

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

We also calculate the e820 maps from couple of other places, say from configure_pvh and configure_32bit_entry on x86 (not sure what's done on aarch64). I wonder if it would be beneficial to refactor related code so that they can be reused?

@rbradford You know this area much better than me.

Copy link
Member

Choose a reason for hiding this comment

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

Good point but might be tricky as there are lots of very similar but subtly different formats for conveying the same information about e.g. the memory holes.

@rbradford rbradford dismissed their stale review June 11, 2025 08:54

@likebreath found some good gaps in my review.

@AlexOrozco1256 AlexOrozco1256 force-pushed the pr-fw_cfg branch 5 times, most recently from c7a4b63 to 263743f Compare June 12, 2025 18:11
@AlexOrozco1256
Copy link
Contributor Author

Thank you for the good work. Besides comments below, couple other thoughts:

  1. Please extend our GH workflows (mostly quality.yaml and build.yaml) to cover the fw_cfg feature flag;
  2. Please add a documentation to explain what it does and how to use it;

Also, looks like adding CONFIG_FW_CFG_SYSFS to the guest kernel config is the only missing bit to add an integration test on fw_cfg, as what you described here.

If that's the case, It'd be great to have that integration test added, and I can help with adding the missing kernel config to reference kernel being used by our CI. (This is not required, since we don't require integration test for features behind feature flags).

I added an integration test that does exactly what my comment here was doing. I use direct kernel boot to boot a vm and verify that the item I added to the fw_cfg device is accessible from within the guest and has the correct contents.

I would just need help from @likebreath to enable the CONFIG_FW_CFG_SYSFS option in the reference kernel.

@likebreath
Copy link
Member

I would just need help from @likebreath to enable the CONFIG_FW_CFG_SYSFS option in the reference kernel.

Of course. I will try to get to it tomorrow. Thanks for the quick turn-around.

likebreath added a commit to cloud-hypervisor/linux that referenced this pull request Jun 13, 2025
This enables integration test of the `fw_cfg` device [1].

[1] cloud-hypervisor/cloud-hypervisor#7117

Signed-off-by: Bo Chen <[email protected]>
likebreath added a commit to cloud-hypervisor/linux that referenced this pull request Jun 13, 2025
This enables integration test of the `fw_cfg` device [1].

[1] cloud-hypervisor/cloud-hypervisor#7117

Signed-off-by: Bo Chen <[email protected]>
@likebreath
Copy link
Member

I would just need help from @likebreath to enable the CONFIG_FW_CFG_SYSFS option in the reference kernel.

Of course. I will try to get to it tomorrow. Thanks for the quick turn-around.

@AlexOrozco1256 Okay. New kernel release was out, plus changes to consume it #7137. I also pushed few commits to kick-off the added fw_cfg tests here. Let's rebase and squash the couple commits into the integration test commit later.

FWIW, I ran the test locally on a aarch64 machine, and found the test failed. I looked into the guest and found the "/sys/firmware/qemu_fw_cfg/by_name/opt/org.test/fw_cfg_test_item/raw" is missing while "/sys/firmware/qemu_fw_cfg/". I believe the arm64 worker will fail for the same reason. PTAL. Thanks.

@AlexOrozco1256 AlexOrozco1256 force-pushed the pr-fw_cfg branch 3 times, most recently from 6069a50 to 393271b Compare June 16, 2025 18:03
Copy link
Member

@likebreath likebreath left a comment

Choose a reason for hiding this comment

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

Some comments below around CLI, which should all be relatively easy to resolve.

I believe we are very close to land this large PR, once #7226 is landed (and you can rebase). Thanks again for the persistency.

.map(|p| p.kernel.as_ref().map(File::open))
.unwrap_or_default()
.transpose()
.map_err(Error::MissingFwCfgKernelFile)?;
Copy link
Member

Choose a reason for hiding this comment

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

It should be handled in a central place for the validation of CLI options for the combination of payload. See my comments from #7166.

I just want to call it out here and let's leave it for future cleanup once #7166 is landed when @phip1611 is back.

@AlexOrozco1256 AlexOrozco1256 force-pushed the pr-fw_cfg branch 3 times, most recently from 232cbcc to 2156cfe Compare August 7, 2025 15:32
@AlexOrozco1256
Copy link
Contributor Author

last force push:

  1. fixed clippy (changed !.is_some() -> .is_none())
  2. added fw_cfg to vmm::feature_list()

Copy link
Member

@likebreath likebreath left a comment

Choose a reason for hiding this comment

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

LGTM. Only two minor comments added. Can you please rebase? I think we are ready to merge.

I was hoping to get the new "linux-loader" release, but that's alright to not include that.

@AlexOrozco1256
Copy link
Contributor Author

I was hoping to get the new "linux-loader" release, but that's alright to not include that.

I can fix this in a follow-up PR. Thanks for the review! I really appreciate it

Here we add the fw_cfg device as a legacy device to the device manager.
It is guarded behind a fw_cfg flag in vmm at creation of the
DeviceManager. In this cl we implement the fw_cfg device with one
function (signature).

Signed-off-by: Alex Orozco <[email protected]>
The kernel and initramfs are passed to the fw_cfg device as
file references. The cmdline is passed directly.

Signed-off-by: Alex Orozco <[email protected]>
We build the memory map in the fw_cfg device based on the memory size.

Signed-off-by: Alex Orozco <[email protected]>
The acpi tables are created in the same place the acpi tables would be
created for the regular bootflow, except here we add them to the
fw_cfg device to be measured by the fw and then the fw will put the
acpi tables into memory.

Signed-off-by: Alex Orozco <[email protected]>
We pass a reference to the guest memory when we create the device
in DeviceManager. This allows us to access the guest memory for DMA.

Signed-off-by: Alex Orozco <[email protected]>
This allows the fw_cfg device to be recognized by the guest linux
kernel. This becomes more relavnt in the following cl where I add
the option to load files into the guest via fw_cfg. The Linux kernel
already has a fw_cfg driver that will automatically load these files
under /sys when CONFIG_FW_CFG_SYSFS is enabled in the kernel config

For arm we must add fw_cfg to the devices tree

Signed-off-by: Alex Orozco <[email protected]>
This allows us to enable/disable the fw_cfg device via the cli

We can also now upload files into the guest vm using fw_cfg_items
via the cli

Signed-off-by: Alex Orozco <[email protected]>
This test verifies that we can see custom items added to the fw_cfg
device from inside the guest

Signed-off-by: Alex Orozco <[email protected]>
@AlexOrozco1256
Copy link
Contributor Author

last push I:

Copy link
Member

@likebreath likebreath left a comment

Choose a reason for hiding this comment

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

Thanks again for the good work and persistency. We are now ready to land it. :)

@likebreath likebreath added this pull request to the merge queue Aug 11, 2025
Merged via the queue into cloud-hypervisor:main with commit 5d478c5 Aug 11, 2025
40 of 41 checks passed
@AlexOrozco1256 AlexOrozco1256 deleted the pr-fw_cfg branch August 13, 2025 15:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants