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

[WIP] Update get/set Standard Registers to use VP register page #183

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

Conversation

russell-islam
Copy link
Collaborator

Summary of the PR

Please summarize here why the changes in this PR are needed.

Requirements

Before submitting your PR, please make sure you addressed the following
requirements:

  • All commits in this PR have Signed-Off-By trailers (with
    git commit -s), and the commit message has max 60 characters for the
    summary and max 75 characters for each description line.
  • All added/changed functionality has a corresponding unit/integration
    test.
  • All added/changed public-facing functionality has entries in the "Upcoming
    Release" section of CHANGELOG.md (if no such section exists, please create one).
  • Any newly added unsafe code is properly documented.

@russell-islam russell-islam force-pushed the muislam/reg-page-initial branch from 53c3cea to 349a0b5 Compare January 9, 2025 07:55
@russell-islam russell-islam changed the title Update get/set Standard register to use VP register page Update get/set Standard Registers to use VP register page Jan 9, 2025
@russell-islam
Copy link
Collaborator Author

russell-islam commented Jan 9, 2025

@jinankjain What do you think about arm64? I added the wrapper struct to lib.rs, I am open to add a similar regs.rs to arm64 and add the RegisterPage wrapper struct there.

@russell-islam russell-islam force-pushed the muislam/reg-page-initial branch from 349a0b5 to 05d26e5 Compare January 9, 2025 20:31
@jinankjain
Copy link
Collaborator

Yes there would be similar regs for ARM64, but I haven't finalized the set of registers we would need.

Copy link
Collaborator

@NunoDasNeves NunoDasNeves left a comment

Choose a reason for hiding this comment

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

It looks like we need to handle the case where the register page is unavailable, e.g. in encrypted partitions.

#[derive(Debug)]
pub struct RegisterPage(pub *mut hv_vp_register_page);

// SAFETY: struct is based on reguster page in the hypervisor,
Copy link
Collaborator

Choose a reason for hiding this comment

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

typo: reguser -> register

@@ -64,6 +69,11 @@ impl AsRawFd for VcpuFd {
}

impl VcpuFd {
/// Get mut refeferenc eof VP register page
Copy link
Collaborator

Choose a reason for hiding this comment

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

typo: refeferenc -> reference

@@ -46,15 +46,20 @@ macro_rules! set_registers_64 {
pub struct VcpuFd {
index: u32,
vcpu: File,
vp_page: RegisterPage,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Have you checked that this will always be available? Wondering if we should make it an Option

Copy link
Collaborator

Choose a reason for hiding this comment

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

I just checked the driver code to be sure. We don't map the register page if it's an encrypted partition, so we need to make this optional.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes. This should be optional

/// Sets the vCPU general purpose registers
#[cfg(not(target_arch = "aarch64"))]
pub fn set_regs(&self, regs: &StandardRegisters) -> Result<()> {
let reg_assocs = [
Copy link
Collaborator

Choose a reason for hiding this comment

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

I had suggested keeping the existing set_regs() and adding a new API. Maybe RegisterPage.set_gpregs() or something.
The semantics are not exactly the same - e.g. if you set a register using the register page, then before restarting the VP, get a register using the IOCTL, you won't get the value you just put in the page. So it might be better to differentiate these cases or be explicit that this is using the register page method.

Copy link
Collaborator

Choose a reason for hiding this comment

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

We don't have the page in some cases, so we need to do this a different way.
We could have set_regs() dispatch to either the IOCTL or the register page, if it is available.
Then it will always pick the fastest way. It would still be nice to differentiate using the IOCTL vs using the register page, for reasons I mentioned above, as well.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We don't have the page in some cases, so we need to do this a different way. We could have set_regs() dispatch to either the IOCTL or the register page, if it is available. Then it will always pick the fastest way. It would still be nice to differentiate using the IOCTL vs using the register page, for reasons I mentioned above, as well.

Ar the moment it is always available except encrypted VM. How dowe exactly check is the page is available here? Checking the option?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I had suggested keeping the existing set_regs() and adding a new API. Maybe RegisterPage.set_gpregs() or something. The semantics are not exactly the same - e.g. if you set a register using the register page, then before restarting the VP, get a register using the IOCTL, you won't get the value you just put in the page. So it might be better to differentiate these cases or be explicit that this is using the register page method.

We need to have this part of vcpu API for vmm to use. Are you suggesting make the set_regs conditioonal inside? For encrypted case this API will never be called BTW.

Copy link
Collaborator

Choose a reason for hiding this comment

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

How dowe exactly check is the page is available here? Checking the option?

Yes

We need to have this part of vcpu API for vmm to use.

We can change it however we like and as long as we make the matching changes on the VMM side.

Are you suggesting make the set_regs conditioonal inside

It might be the easiest way to do it, because we wouldn't have to change much in the VMM.

But, making it transparent to the VMM like that could lead to cases where IOCTL and register page usage are mixed, so differentiating those methods might save some trouble in future.

Ar the moment it is always available except encrypted VM.
...
For encrypted case this API will never be called BTW.

Ok, maybe just replacing the current set_regs() etc is fine then... I think I'd still like it better if the API made it clear this was a different method of setting the registers than using set_reg()/set_registers_64!.
E.g. renaming set_regs to set_vp_page_gp_regs or something

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This sounds good.

Define a new struct RegisterPage with mutable pointer
to hv_vp_register_page.

Signed-off-by: Muminul Islam <[email protected]>
Include the register page in vcpu object for later use
to read and write the VP registers.

Signed-off-by: Muminul Islam <[email protected]>
One more API to VCPU implementation sin signature
get_vp_reg_page, that return mutable reference to
VP register page. This API could be used by VMM or other
VCPU implementations.

Signed-off-by: Muminul Islam <[email protected]>
@russell-islam russell-islam force-pushed the muislam/reg-page-initial branch from 05d26e5 to e42898d Compare January 12, 2025 22:41
This API use mapped VP register page to set the registers.

Signed-off-by: Muminul Islam <[email protected]>
@russell-islam russell-islam force-pushed the muislam/reg-page-initial branch from e42898d to 5d883df Compare January 12, 2025 22:48
This API uses VP register page to populate the registers.

Signed-off-by: Muminul Islam <[email protected]>
@russell-islam russell-islam force-pushed the muislam/reg-page-initial branch from 5d883df to 5a74c89 Compare January 12, 2025 22:54
@russell-islam
Copy link
Collaborator Author

@NunoDasNeves Please take another look.

@liuw
Copy link
Member

liuw commented Jan 13, 2025

If KVM supports a similar interface, can you check if they require the VMM to explicitly opt-in / enable to use this feature?

We want to be careful here. The kernel may decide some day that it also wants to touch that page.

@russell-islam
Copy link
Collaborator Author

russell-islam commented Jan 13, 2025

If KVM supports a similar interface, can you check if they require the VMM to explicitly opt-in / enable to use this feature?

We want to be careful here. The kernel may decide some day that it also wants to touch that page.

I do not see any such feature in KVM. @NunoDasNeves What is the kernel scenario in our driver code. Can the driver change the page contents?

@liuw
Copy link
Member

liuw commented Jan 14, 2025

If KVM supports a similar interface, can you check if they require the VMM to explicitly opt-in / enable to use this feature?
We want to be careful here. The kernel may decide some day that it also wants to touch that page.

I do not see any such feature in KVM. @NunoDasNeves What is the kernel scenario in our driver code. Can the driver change the page contents?

It is all very nebulous in my head, but supposedly one day we may decide we want to do code emulation in Linux kernel, or make the kernel to directly inspect / modify guest register states.

We need to be thorough here. If such use cases arise, we need to make sure correctness is maintained. With the current code, the VMM blindly maps the page. It may or may not be okay. I'm looking for the reasoning why the current scheme is okay; if not, what needs to be done.

@russell-islam
Copy link
Collaborator Author

If KVM supports a similar interface, can you check if they require the VMM to explicitly opt-in / enable to use this feature?
We want to be careful here. The kernel may decide some day that it also wants to touch that page.

I do not see any such feature in KVM. @NunoDasNeves What is the kernel scenario in our driver code. Can the driver change the page contents?

It is all very nebulous in my head, but supposedly one day we may decide we want to do code emulation in Linux kernel, or make the kernel to directly inspect / modify guest register states.

We need to be thorough here. If such use cases arise, we need to make sure correctness is maintained. With the current code, the VMM blindly maps the page. It may or may not be okay. I'm looking for the reasoning why the current scheme is okay; if not, what needs to be done.

The whole purpose of this PR is to speed up the boot process. Mainly the emulation code is accessing GP and Control registers. If you move the emulation in the Kernel later we might remove this mapping from the VMM.

@liuw
Copy link
Member

liuw commented Jan 14, 2025

Actually the code as-is already makes a case for gating that feature with a flag. Mapping the register page can be separated from the guest type.

  1. You don't need to carry the knowledge of the guest type in that particular code path.
  2. You don't prevent a possible improvement in the future if hardware allows you to access a snapshot of the register page for an encrypted guest.

In general, you should always provide a mechanism to discover features across component boundary.

@@ -64,6 +69,13 @@ impl AsRawFd for VcpuFd {
}

impl VcpuFd {
/// Get mut reference of VP register page
pub fn get_vp_reg_page(&self) -> *mut hv_vp_register_page {
Copy link
Member

Choose a reason for hiding this comment

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

If this can fail, you should return an Option. That's far better than expecting someone to read your comment in the function.

match self.vp_page { Some(p) => p, None => None }.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We can just return as is self.vp_page.

In your example two incompatible return type.

@russell-islam
Copy link
Collaborator Author

russell-islam commented Jan 14, 2025

Actually the code as-is already makes a case for gating that feature with a flag. Mapping the register page can be separated from the guest type.

1. You don't need to carry the knowledge of the guest type in that particular code path.

2. You don't prevent a possible improvement in the future if hardware allows you to access a snapshot of the register page for an encrypted guest.

In general, you should always provide a mechanism to discover features across component boundary.

For encrypted guest, there is no register page in the driver. that means mmap will fail and we have to store None.
In your comment I am not sure about the flag you are referring.

@skinsbursky
Copy link
Collaborator

If KVM supports a similar interface, can you check if they require the VMM to explicitly opt-in / enable to use this feature?

We want to be careful here. The kernel may decide some day that it also wants to touch that page.

Why this might be a problem from your POV?
Kernel does touch the page to inject the interrupt vectors upon VP dispatch and it's not mutually exclusive with other potential setters.
At the end it's just a memory page with some numbers until the VP is dispatched, isn't it?

@russell-islam
Copy link
Collaborator Author

After a discussion with Wei, I think we need to have some feature sets returned from the Kernel driver and make appropriate features available in the VMM. As a result, I am making this PR draft and continue to work on the Kernel and resume here once Kernel implementation is done.

@russell-islam russell-islam changed the title Update get/set Standard Registers to use VP register page [WIP] Update get/set Standard Registers to use VP register page Jan 14, 2025
@russell-islam russell-islam marked this pull request as draft January 14, 2025 23:47
@liuw
Copy link
Member

liuw commented Jan 15, 2025

If KVM supports a similar interface, can you check if they require the VMM to explicitly opt-in / enable to use this feature?
We want to be careful here. The kernel may decide some day that it also wants to touch that page.

Why this might be a problem from your POV? Kernel does touch the page to inject the interrupt vectors upon VP dispatch and it's not mutually exclusive with other potential setters. At the end it's just a memory page with some numbers until the VP is dispatched, isn't it?

When two entities modify the same page in an overlapping manner, there needs to be a way to synchronize them. We don't have a clear model yet.

Having a mechanism to clearly denote what feature is available gives us some leeway if something happens in the future.

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.

5 participants