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

Port of the pci crate #1019

Merged
merged 23 commits into from
Aug 20, 2023
Merged

Conversation

NathanRoyer
Copy link
Member

@NathanRoyer NathanRoyer commented Jul 25, 2023

This brings the following changes:

  • pci::scan_pci maps the pci config space on aarch64, in addition to what it used to do.
  • pci::PciLocation was modified so that it uses the mapping on aarch64
  • device_manager calls it (via pci_device_iter) on both platforms
  • I tried converting the const offsets to an enum but the capability "linked-list" from find_pci_capability needs the offset to be a raw u8, and I might also need custom offsets for USB support so I dropped this.
  • QEMU_FLAGS starts the virt machine with new options: highmem=on & highmem-mmio=on because without them, the PCI configuration space lies in "low memory" but its base address points to a bunch of zeros for some reason.

Note: while pci currently uses port-io on x86 and mmio on aarch64, x86 may also support memory-based PCI configuration in the future; port-io is the legacy way to access the config space.

kernel/pci/src/lib.rs Outdated Show resolved Hide resolved
kernel/pci/src/lib.rs Outdated Show resolved Hide resolved
kernel/pci/src/lib.rs Outdated Show resolved Hide resolved
kernel/pci/src/lib.rs Outdated Show resolved Hide resolved
kernel/pci/src/lib.rs Outdated Show resolved Hide resolved
kernel/pci/src/lib.rs Outdated Show resolved Hide resolved
@kevinaboos
Copy link
Member

Not sure if you're ready for me to re-review it or if you're still in the process of making changes. Once you're done, click the re-request review button at the top right under "Reviewers" so I know for sure.

@kevinaboos
Copy link
Member

I merged in #972, please update this PR to incorporate those changes. Thanks!

Copy link
Member

@kevinaboos kevinaboos left a comment

Choose a reason for hiding this comment

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

Just one small comment; most other changes look great!

How much have you tested this, e.g., does it fully work with all existing supported devices on aarch64 and x86_64?

kernel/device_manager/src/lib.rs Show resolved Hide resolved
kernel/pci/src/lib.rs Outdated Show resolved Hide resolved
kernel/pci/src/lib.rs Outdated Show resolved Hide resolved
@NathanRoyer NathanRoyer requested a review from kevinaboos August 8, 2023 08:35
Copy link
Member

@kevinaboos kevinaboos left a comment

Choose a reason for hiding this comment

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

haven't yet tested it on my machine, but i did leave a few more suggestions.

kernel/pci/src/lib.rs Outdated Show resolved Hide resolved
kernel/pci/src/lib.rs Outdated Show resolved Hide resolved
kernel/pci/src/lib.rs Outdated Show resolved Hide resolved
@kevinaboos
Copy link
Member

Disk I/O works correctly with your changes 👍

@NathanRoyer
Copy link
Member Author

NathanRoyer commented Aug 14, 2023

I just noticed something weird that is also present in the original implementation.

In pci_write, a shifted value is directly written to the data port; if the offset was to an unaligned byte, this can discard other bytes of the dword and replace them with zeros right?

@kevinaboos
Copy link
Member

I just noticed something weird that is also present in the original implementation.

In pci_write, a shifted value is directly written to the data port; if the offset was to an unaligned byte, this can discard other bytes of the dword and replace them with zeros right?

That's true, I think that's intentional though, as it's a "raw" inner function that is designed to be used by other public PCI functions. I suppose the idea is that if you wanted to preserve those bits, you would have read the existing value right before that and then passed in the updated value to that write function.

Copy link
Member

@kevinaboos kevinaboos left a comment

Choose a reason for hiding this comment

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

still waiting on the PciAddress-related fixes, some pending comments there. After that we can merge.

kernel/pci/src/lib.rs Outdated Show resolved Hide resolved
@NathanRoyer
Copy link
Member Author

NathanRoyer commented Aug 18, 2023

@kevinaboos I replaced the previous pci read/writers with this:

impl PciLocation {
    /// Read a 4-bytes register from the PCI Configuration Space.
    ///
    /// Panics if the register isn't a [`FullDword`]
    fn pci_read_32(&self, register: PciRegister) -> u32

    /// Read a 2-bytes register from the PCI Configuration Space.
    ///
    /// Panics if the register isn't a [`Word0`] / [`Word1`]
    fn pci_read_16(&self, register: PciRegister) -> u16

    /// Read a one-byte register from the PCI Configuration Space.
    ///
    /// Panics if the register isn't a [`Byte0`] / [`Byte1`] / [`Byte2`] / [`Byte3`]
    fn pci_read_8(&self, register: PciRegister) -> u8;

    /// Write a 4-bytes register from the PCI Configuration Space.
    ///
    /// Panics if the register isn't a [`FullDword`]
    fn pci_write_32(&self, register: PciRegister, value: u32);
    /// Write a 2-bytes register from the PCI Configuration Space.
    ///
    /// Panics if the register isn't a [`Word0`] / [`Word1`]
    fn pci_write_16(&self, register: PciRegister, value: u16);

    /// Write a one-byte register from the PCI Configuration Space.
    ///
    /// Panics if the register isn't a [`Byte0`] / [`Byte1`] / [`Byte2`] / [`Byte3`]
    fn pci_write_8(&self, register: PciRegister, value: u8);
}

/// (PCI Config Space Dword Index, Register Span)
type PciRegister = (u8, RegisterSpan);

enum RegisterSpan {
    /// Bits [0:31]
    FullDword,
    /// Bits [0:15]
    Word0,
    /// Bits [16:31]
    Word1,
    /// Bits [0:7]
    Byte0,
    /// Bits [8:15]
    Byte1,
    /// Bits [16:23]
    Byte2,
    /// Bits [24:31]
    Byte3,
}

const PCI_VENDOR_ID:             PciRegister = (0x0, Word0);
const PCI_DEVICE_ID:             PciRegister = (0x0, Word1);
const PCI_COMMAND:               PciRegister = (0x1, Word0);
const PCI_STATUS:                PciRegister = (0x1, Word1);
const PCI_REVISION_ID:           PciRegister = (0x2, Byte0);
const PCI_PROG_IF:               PciRegister = (0x2, Byte1);
// ...

Copy link
Member

@kevinaboos kevinaboos left a comment

Choose a reason for hiding this comment

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

I made some changes to clean things up a bit. I like the introduction of all the new types, but we can actually go further to use traits and trait bounds to move all of the assertions into compile time type errors. We'll save that for the next PR.

@kevinaboos kevinaboos merged commit e979b80 into theseus-os:theseus_main Aug 20, 2023
github-actions bot pushed a commit that referenced this pull request Aug 20, 2023
* Support PCI on aarch64 via MMIO access mechanisms.

* Redesign the PCI addressing code to be very clear and use more types.
  Currently some checks are done at runtime with assertions,
  but these could easily be moved to compile time by introducing
  traits about register sizes that can be implemented by each `RegisterSpan`
  within the `PciRegister` type.

* Note: PCI currently uses Port I/O on x86 and MMIO on aarch64 to read/write,
  but x86_64 may also use MMIO-based access in the future, because Port I/O
  is the legacy method to access the PCI configuration space.

* The `device_manager` now initializes and scans the PCI bus on
  both the aarch64 and x86_64 platforms.
  * Scanning the PCI bus for the first time also maps the memory
    behind the configuration space.

Co-authored-by: Kevin Boos <[email protected]> e979b80
tsoutsman pushed a commit to tsoutsman/Theseus that referenced this pull request Sep 6, 2023
…eus-os#1019)

* Support PCI on aarch64 via MMIO access mechanisms.

* Redesign the PCI addressing code to be very clear and use more types.
  Currently some checks are done at runtime with assertions,
  but these could easily be moved to compile time by introducing
  traits about register sizes that can be implemented by each `RegisterSpan`
  within the `PciRegister` type.

* Note: PCI currently uses Port I/O on x86 and MMIO on aarch64 to read/write,
  but x86_64 may also use MMIO-based access in the future, because Port I/O
  is the legacy method to access the PCI configuration space.

* The `device_manager` now initializes and scans the PCI bus on
  both the aarch64 and x86_64 platforms. 
  * Scanning the PCI bus for the first time also maps the memory
    behind the configuration space.

Co-authored-by: Kevin Boos <[email protected]>
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