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

Wire up viona notify fast path #754

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

pfmooney
Copy link
Collaborator

The viona driver has the ability to hook an ioport (as specified by the userspace vmm) in order to more efficiently process notifications from the guest that virtqueues have new available entries. This cuts down on the number of VM exits which must be processed by userspace.

The viona driver has the ability to hook an ioport (as specified by the
userspace vmm) in order to more efficiently process notifications from
the guest that virtqueues have new available entries.  This cuts down on
the number of VM exits which must be processed by userspace.
Copy link
Member

@hawkw hawkw left a comment

Choose a reason for hiding this comment

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

This is a pretty cursory review, since I don't know a whole lot about the viona API --- probably worth getting a look from someone who does. Overall, though, this looks good, at least as far as I can tell.

lib/propolis/src/hw/pci/bar.rs Show resolved Hide resolved
Comment on lines 654 to 655
if (inner.pio_en() && def.is_pio())
|| (inner.mmio_en() && def.is_mmio())
Copy link
Member

Choose a reason for hiding this comment

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

nit, take it or leave it: I wonder if there ought to be a method like

impl State {
    fn should_register_bar(&self, bar: &BarDefine) -> bool {
         (self.pio_en() && bar.is_pio()) || (self.mmio_en() && def.is_mmio())
    }
}

that could be called both here and in cfg_std_write, above?

Not sure if it's worth factoring out or not, just noticed that it was repeated.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done (with slightly tweaked naming)

Comment on lines +80 to +82
poller: None,
iop_state: None,
vring_state: [Default::default(); 2],
Copy link
Member

Choose a reason for hiding this comment

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

take it or leave it: this is identical to what a derived Default implementation would do...

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

When there are state variables involved, I sometimes prefer to spell it out by hand. I go either way sometimes. For this one, I think I'm going to leave it (at least for now).

@@ -648,6 +687,14 @@ impl VionaHdl {
Ok(())
}

fn set_notify_iop(&self, port: Option<u16>) -> io::Result<()> {
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps this is just because I don't have an illumos background, but it took a bit for me to realize that "IOP" here referred to "IO port"...I might prefer to expand it to set_notify_io_port? I note that we have a function above notify_port_update that calls this function, so perhaps we could call this set_notify_port to mirror that? But, if you prefer to more closely mirror the name of the ioctl, that's fair, too. :)

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'd like to keep the name consistent with the ioctl here in VionaHdl. I've written up a doc comment which hopefully makes it clearer.

@@ -475,6 +504,16 @@ impl PciVirtio for PciVirtioViona {
fn pci_state(&self) -> &pci::DeviceState {
&self.pci_state
}
fn notify_port_update(&self, port: Option<u16>) {
Copy link
Member

Choose a reason for hiding this comment

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

It might be worth a comment explaining the difference between notify_port_update and set_notify_iop, which this calls if the device is running? It could be helpful if we explained when this should be called, and when it's okay to call set_notify_iop unconditionally?

Comment on lines +138 to +142
IndicatedState::from_usize(self.0.load(Ordering::SeqCst))
}

fn state_change(&self, new: IndicatedState) {
let old = self.0.swap(new as usize, Ordering::SeqCst);
Copy link
Member

Choose a reason for hiding this comment

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

I don't think sequentially-consistent ordering is required here. I don't believe there is another memory location that we want to have a total ordering of sequentially-consistent stores/loads with, so AcqRel should be sufficient here?

I doubt the performance penalty for sequentially-consistent stores matters a whole lot here, though, so 🤷‍♀️

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 gravitate towards using excessively strong ordering until performance sensitivities prove otherwise. Also, is AcqRel functionally different than SeqCst on amd64?

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.

2 participants