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

td-shim: remove the use of Vec in e820 #700

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 56 additions & 28 deletions td-shim/src/bin/td-shim/e820.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,30 @@
// SPDX-License-Identifier: BSD-2-Clause-Patent

use core::ptr::slice_from_raw_parts;

use alloc::vec::Vec;
use td_shim::e820::{E820Entry, E820Type};

// Linux BootParam supports 128 e820 entries, so...
const MAX_E820_ENTRY: usize = 128;

#[derive(Debug)]
pub struct E820Table {
entries: Vec<E820Entry>,
entries: [E820Entry; MAX_E820_ENTRY],
num_entries: usize,
}

#[derive(Debug)]
pub enum E820Error {
RangeAlreadyExists,
RangeNotExists,
TooManyEntries,
InvalidIndex,
}

impl Default for E820Table {
fn default() -> Self {
Self {
entries: Vec::new(),
entries: [E820Entry::default(); MAX_E820_ENTRY],
num_entries: 0,
}
}
}
Expand All @@ -39,7 +40,7 @@ impl E820Table {
unsafe {
&*slice_from_raw_parts(
self.entries.as_ptr() as *const u8,
core::mem::size_of::<E820Entry>() * self.entries.len(),
core::mem::size_of::<E820Entry>() * self.num_entries,
)
}
}
Expand All @@ -51,8 +52,8 @@ impl E820Table {
start: u64,
length: u64,
) -> Result<(), E820Error> {
let mut pos = self.entries.len();
for (i, e) in self.entries.iter().enumerate() {
let mut pos = self.num_entries;
for (i, e) in self.entries[..self.num_entries].iter().enumerate() {
if start >= e.addr && start < e.addr + e.size {
return Err(E820Error::RangeAlreadyExists);
}
Expand All @@ -61,11 +62,10 @@ impl E820Table {
break;
}
}
if self.entries.len() == MAX_E820_ENTRY && !self.able_to_merge(pos, r#type, start, length) {
if self.num_entries == MAX_E820_ENTRY && !self.able_to_merge(pos, r#type, start, length) {
return Err(E820Error::TooManyEntries);
}
self.entries
.insert(pos, E820Entry::new(start, length, r#type));
self.insert_entry(pos, E820Entry::new(start, length, r#type));
self.merge();
Ok(())
}
Expand All @@ -77,10 +77,9 @@ impl E820Table {
start: u64,
length: u64,
) -> Result<(), E820Error> {
let entry_num = self.entries.len();
let mut idx = 0;
loop {
if idx == entry_num {
if idx == self.num_entries {
break;
}
let entry_end = self.entries[idx].addr + self.entries[idx].size;
Expand All @@ -101,37 +100,34 @@ impl E820Table {
// if the entry num of e820 table has reached the maximum, and
// the new entry cannot be merged with an exits one, then return
// an error.
if entry_num == MAX_E820_ENTRY
if self.num_entries == MAX_E820_ENTRY
&& !self.able_to_merge(idx, r#type, start, length)
{
return Err(E820Error::TooManyEntries);
}
self.entries[idx].size -= length;
self.entries[idx].addr = start + length;
self.entries
.insert(idx, E820Entry::new(start, length, r#type))
self.insert_entry(idx, E820Entry::new(start, length, r#type))?;
} else if self.entries[idx].addr + self.entries[idx].size == start + length {
// check if the new entry can be merged with the right one
if entry_num == MAX_E820_ENTRY
if self.num_entries == MAX_E820_ENTRY
&& !self.able_to_merge(idx, r#type, start, length)
{
return Err(E820Error::TooManyEntries);
}
self.entries[idx].size -= length;
self.entries
.insert(idx + 1, E820Entry::new(start, length, r#type))
self.insert_entry(idx + 1, E820Entry::new(start, length, r#type))?;
} else {
self.entries[idx].size = start - self.entries[idx].addr;
self.entries
.insert(idx + 1, E820Entry::new(start, length, r#type));
self.entries.insert(
self.insert_entry(idx + 1, E820Entry::new(start, length, r#type))?;
self.insert_entry(
idx + 2,
E820Entry::new(
start + length,
entry_end - (start + length),
self.entries[idx].r#type.into(),
),
);
)?;
}
self.merge();
return Ok(());
Expand All @@ -147,7 +143,7 @@ impl E820Table {
if (pos > 0
&& self.entries[pos - 1].r#type == r#type as u32
&& self.entries[pos - 1].addr + self.entries[pos - 1].size == start)
|| (pos + 1 < self.entries.len()
|| (pos + 1 < self.num_entries
&& self.entries[pos + 1].r#type == r#type as u32
&& self.entries[pos + 1].addr == start + length)
{
Expand All @@ -158,27 +154,58 @@ impl E820Table {
}

fn merge(&mut self) {
let mut entry_num = self.entries.len();
let mut idx = 0;
loop {
if idx == entry_num - 1 {
if idx == self.num_entries - 1 {
break;
}
let entry_end = self.entries[idx].addr + self.entries[idx].size;
if entry_end == self.entries[idx + 1].addr
&& self.entries[idx].r#type == self.entries[idx + 1].r#type
{
self.entries[idx].size += self.entries[idx + 1].size;
self.entries.remove(idx + 1);
entry_num -= 1;
self.remove_entry(idx + 1);
continue;
}
idx += 1;
}
}

fn insert_entry(&mut self, index: usize, entry: E820Entry) -> Result<(), E820Error> {
if self.num_entries >= MAX_E820_ENTRY {
return Err(E820Error::TooManyEntries);
}
if index > self.num_entries {
return Err(E820Error::InvalidIndex);
}

// Move all entries after the index back one position
for idx in (index..self.num_entries).rev() {
self.entries[idx + 1] = self.entries[idx];
}

self.entries[index] = entry;
self.num_entries += 1;
Ok(())
}

fn remove_entry(&mut self, index: usize) -> Result<(), E820Error> {
if index >= self.num_entries {
Copy link
Member

Choose a reason for hiding this comment

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

What if self.num_entries is 0 ?

Copy link
Member Author

Choose a reason for hiding this comment

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

if self.num_entries == 0, the index >= self.num_entries will always be true, then it will return error

return Err(E820Error::InvalidIndex);
}

// Move all entries after the index forward one position
for idx in index..self.num_entries - 1 {
self.entries[idx] = self.entries[idx + 1];
}

self.entries[self.num_entries - 1] = E820Entry::default();
self.num_entries -= 1;
Ok(())
}

pub fn as_slice(&self) -> &[E820Entry] {
&self.entries
&self.entries[..self.num_entries]
}
}

Expand All @@ -191,6 +218,7 @@ mod tests {
let mut table = E820Table::new();
table.add_range(E820Type::Memory, 0x0, 0x1000).unwrap();
table.add_range(E820Type::Memory, 0x2000, 0x1000).unwrap();
std::println!("table: {:x?}", table);
assert_eq!(table.as_slice().len(), 2);
table.add_range(E820Type::Memory, 0x1000, 0x1000).unwrap();
assert_eq!(table.as_slice().len(), 1);
Expand Down