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

Implement function for creating a gdt in a const environment. #413

Merged
merged 1 commit into from
Mar 26, 2024

Conversation

uglyoldbob
Copy link
Contributor

@uglyoldbob uglyoldbob commented Mar 18, 2023

As mentioned in another pull request, the form for this function was preferred over the other implementation.
#406

Copy link
Member

@Freax13 Freax13 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 your contribution!

I apologize for the long delay with the review! I had somehow missed this.

Comment on lines 63 to 117
/// Returns the length of the descriptor table
pub const fn len(&self) -> usize {
self.len
}
Copy link
Member

Choose a reason for hiding this comment

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

Length can have a couple of meanings here:

  1. The amount of entries.
  2. The amount of bytes
  3. The amount of bytes minus one (this representation is used when the descriptor table is loaded)

Can you clarify in the comment which of those is used here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The goal of this function is to be able to create a GdtPointer that can be used with the lgdt instruction. Currently, I am using (GDT_TABLE.len() * 8 - 1) as u16 for the size parameter of the gdtpointer, where GDT_TABLE is an instance of GlobalDescriptorTable. Maybe more beneficial to introduce a GdtPointer type to the library and a const fn to create one?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The implementation for the GdtPointer is slightly different than the one already in this crate. I'm not sure what makes the most sense to do here. I am generating the gdt stuff with rust at compile-time, but actually loading it in some assembly bootstrap code.

/// A struct for creating a global descriptor table pointer, suitable for loading with lidtr
#[repr(C, packed)]
pub struct GdtPointer<'a> {
    /// The size of the gdt table in bytes minus 1. See x86 processor manual for more information.
    size: u16,
    /// The address of the global descriptor table.
    address: &'a GlobalDescriptorTable,
}

/// Descriptor::kernel_data_segment()
/// ]);
/// ```
pub const fn from_descriptors<const N: usize>(
Copy link
Member

Choose a reason for hiding this comment

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

This function will panic if the capacity is exceeded. This should be mentioned in the doc comment.

self.len
}

///Creates a filled out GDT.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
///Creates a filled out GDT.
/// Creates a GDT with the provided descriptors.

Comment on lines 83 to 84
loop {
if index < N {
Copy link
Member

Choose a reason for hiding this comment

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

This can be expressed using a while loop.

if index < N {
match descriptors[index] {
Descriptor::UserSegment(value) => {
assert!(outindex <= data.len().saturating_sub(1));
Copy link
Member

Choose a reason for hiding this comment

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

Are this assert and the one below needed? Shouldn't out of bounds accesses also be caught by the index operations in line 88, 95 and 99?

@Freax13 Freax13 added the waiting-on-author Waiting for the author to act on review feedback. label Sep 15, 2023
@uglyoldbob
Copy link
Contributor Author

For some reason, I am just now seeing your comments on the pull request. I will look into it in the next week or so.

@uglyoldbob
Copy link
Contributor Author

uglyoldbob commented Mar 25, 2024

@Freax13 I think the function I added with this pull request is a bit redundant now that I see the const_fn feature in the crate, however I do need a way to generate a GdtTablePointer with a const fn.

@Freax13
Copy link
Member

Freax13 commented Mar 25, 2024

@Freax13 I think the function I added with this pull request is a bit redundant now that I see the const_fn feature in the crate,

Yeah, you're right. I'm sorry about that, we had some breaking changes in the next branch for a really long time to the point where even we maintainers forgot some of the changes.

however I do need a way to generate a GdtTablePointer with a const fn.

That won't be easy. Our DescriptorTablePointer type uses a VirtAddr for the base field. VirtAddr stores the address as a u64 and Rust doesn't allow casting a pointer to a u64 during const evaluation. I think the best way here is to go with your original plan of adding a len function to query the number of entries in the GDT and then use that with your custom type.

Just out of curiosity, what's your use case for creating the pointer at compile time?

@uglyoldbob
Copy link
Contributor Author

No worries on the changes.
I am writing a kernel, that boots into a 32-bit assembly stub to bring the system into long mode. I need a valid gdt pointer for the lgdt command and containing the struct in rust code seemed more convenient than trying to do the same thing in an assembly file. See here and here for some details.

@uglyoldbob
Copy link
Contributor Author

Any thoughts on what the name of this function should be?

@Freax13
Copy link
Member

Freax13 commented Mar 26, 2024

Any thoughts on what the name of this function should be?

limit seems reasonable to me. Can you move the function down (before or after pointer) and also change pointer to use it?

@josephlr
Copy link
Contributor

@uglyoldbob @tepperson2 something seems to have gotten messed up on this PR, it's showing >1000 lines changed. Could you fix this PR to only include the last two commits?

@uglyoldbob
Copy link
Contributor Author

I wasn't quite sure the best way to fix it, so i redid the last commit and force pushed it without the merge.

@josephlr
Copy link
Contributor

I wasn't quite sure the best way to fix it, so i redid the last commit and force pushed it without the merge.

Can you rebase onto the latest master so that there aren't conflicts?

@uglyoldbob
Copy link
Contributor Author

It should be ready. I combined it into a single commit.

@josephlr josephlr requested a review from Freax13 March 26, 2024 22:08
@josephlr josephlr dismissed Freax13’s stale review March 26, 2024 22:09

Changes have been addressed.

@josephlr josephlr merged commit 2fbf90c into rust-osdev:master Mar 26, 2024
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
waiting-on-author Waiting for the author to act on review feedback.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants