Skip to content

Commit 13acc92

Browse files
page_cache: read directly to the allocate page
Signed-off-by: Andy-Python-Programmer <andypythonappdeveloper@gmail.com>
1 parent 67821c1 commit 13acc92

File tree

3 files changed

+76
-21
lines changed

3 files changed

+76
-21
lines changed

src/aero_kernel/src/drivers/block/ide/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,15 @@ impl BlockDeviceInterface for IdeDrive {
7070
todo!()
7171
}
7272

73+
fn read_dma(
74+
&self,
75+
_sector: usize,
76+
_start: crate::mem::paging::PhysAddr,
77+
_size: usize,
78+
) -> Option<usize> {
79+
unimplemented!()
80+
}
81+
7382
fn write_block(&self, _sector: usize, _buf: &[u8]) -> Option<usize> {
7483
unimplemented!()
7584
}

src/aero_kernel/src/drivers/block/nvme/mod.rs

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -231,11 +231,10 @@ struct Namespace<'a> {
231231
}
232232

233233
impl<'a> Namespace<'a> {
234-
fn read(&self, sector: usize, dest: &mut [MaybeUninit<u8>]) {
235-
let size_bytes = dest.len();
236-
let blocks = size_bytes.ceil_div(self.block_size);
234+
fn read(&self, sector: usize, start: PhysAddr, size_bytes: usize) {
235+
assert!(size_bytes != 0);
237236

238-
let buffer = Dma::<u8>::new_uninit_slice(dest.len());
237+
let blocks = size_bytes.ceil_div(self.block_size);
239238
let mut read_cmd = ReadWriteCommand::default();
240239

241240
read_cmd.opcode = CommandOpcode::Read as u8;
@@ -252,21 +251,16 @@ impl<'a> Namespace<'a> {
252251
let mut prps = self.prps.lock();
253252

254253
for i in 0..prp_num {
255-
prps[i]
256-
.write((buffer.addr().as_u64() + Size4KiB::SIZE) + (Size4KiB::SIZE * i as u64));
254+
prps[i].write((start.as_u64() + Size4KiB::SIZE) + (Size4KiB::SIZE * i as u64));
257255
}
258256

259-
read_cmd.data_ptr.prp1 = buffer.addr().as_u64();
257+
read_cmd.data_ptr.prp1 = start.as_u64();
260258
read_cmd.data_ptr.prp2 = prps.addr().as_u64();
261259
} else {
262-
read_cmd.data_ptr.prp1 = buffer.addr().as_u64();
260+
read_cmd.data_ptr.prp1 = start.as_u64();
263261
}
264262

265263
self.controller.io_queue.lock_irq().submit_command(read_cmd);
266-
267-
// SAFETY: The buffer is initialized above.
268-
let buffer = unsafe { buffer.assume_init() };
269-
MaybeUninit::write_slice(dest, &*buffer);
270264
}
271265
}
272266

@@ -468,8 +462,17 @@ impl<'a> Controller<'a> {
468462
}
469463

470464
impl<'a> BlockDeviceInterface for Controller<'a> {
465+
fn read_dma(&self, sector: usize, start: PhysAddr, size: usize) -> Option<usize> {
466+
self.namespaces.lock()[0].read(sector, start, size);
467+
Some(size)
468+
}
469+
471470
fn read_block(&self, sector: usize, dest: &mut [MaybeUninit<u8>]) -> Option<usize> {
472-
self.namespaces.lock()[0].read(sector, dest);
471+
let buffer = Dma::<u8>::new_uninit_slice(dest.len());
472+
self.namespaces.lock()[0].read(sector, buffer.addr(), dest.len());
473+
474+
// SAFETY: The buffer is initialized above.
475+
dest.copy_from_slice(&buffer);
473476
Some(dest.len())
474477
}
475478

src/aero_kernel/src/fs/block/mod.rs

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ impl CachedPage {
7070
unsafe { core::slice::from_raw_parts_mut(data_ptr, Size4KiB::SIZE as usize) }
7171
}
7272

73+
fn data_addr(&self) -> PhysAddr {
74+
self.page.start_address()
75+
}
76+
7377
fn make_key(device: Weak<dyn CachedAccess>, offset: usize) -> PageCacheKey {
7478
(device.as_ptr() as *const u8 as usize, offset)
7579
}
@@ -107,12 +111,10 @@ impl Cache<PageCacheKey, CachedPage> {
107111
let device = device.upgrade().expect("page_cache: device dropped");
108112

109113
let aligned_offset = align_down(offset as u64, Size4KiB::SIZE) as usize;
114+
let sector = aligned_offset / device.block_size();
110115

111116
device
112-
// FIXME(perf,mem): internally read_block makes use of the DMA API (cc drivers::nvme::dma), which in turn
113-
// allocates another frame in order to make sure the destination buffer is DMA capable. In this
114-
// case, this is not required since we have already allocated a DMA capable frame.
115-
.read_block(aligned_offset / device.block_size(), page.data_mut())
117+
.read_dma(sector, page.data_addr(), Size4KiB::SIZE as usize)
116118
.expect("page_cache: failed to read block");
117119

118120
PAGE_CACHE.make_item_cached(page)
@@ -122,6 +124,8 @@ impl Cache<PageCacheKey, CachedPage> {
122124
pub trait BlockDeviceInterface: Send + Sync {
123125
fn block_size(&self) -> usize;
124126

127+
fn read_dma(&self, sector: usize, start: PhysAddr, size: usize) -> Option<usize>;
128+
125129
fn read_block(&self, sector: usize, dest: &mut [MaybeUninit<u8>]) -> Option<usize>;
126130
fn write_block(&self, sector: usize, buf: &[u8]) -> Option<usize>;
127131
}
@@ -147,6 +151,33 @@ pub trait CachedAccess: BlockDeviceInterface {
147151

148152
Some(loc)
149153
}
154+
155+
/// Writes the given data to the device at the given offset and returns the
156+
/// number of bytes written.
157+
///
158+
/// ## Notes
159+
///
160+
/// * This function does **not** sync the written data to the disk.
161+
fn write(&self, mut offset: usize, buffer: &[u8]) -> Option<usize> {
162+
let mut loc = 0;
163+
164+
while loc < buffer.len() {
165+
let page = PAGE_CACHE.get_page(self.sref(), offset);
166+
167+
let page_offset = offset % Size4KiB::SIZE as usize;
168+
let size = core::cmp::min(Size4KiB::SIZE as usize - page_offset, buffer.len() - loc);
169+
170+
MaybeUninit::write_slice(
171+
&mut page.data_mut()[page_offset..page_offset + size],
172+
&buffer[loc..loc + size],
173+
);
174+
175+
loc += size;
176+
offset += align_down(offset as u64 + Size4KiB::SIZE, Size4KiB::SIZE) as usize;
177+
}
178+
179+
Some(loc)
180+
}
150181
}
151182

152183
static BLOCK_DEVS: Mutex<BTreeMap<usize, Arc<BlockDevice>>> = Mutex::new(BTreeMap::new());
@@ -189,6 +220,10 @@ impl BlockDeviceInterface for BlockDevice {
189220
self.dev.block_size()
190221
}
191222

223+
fn read_dma(&self, sector: usize, start: PhysAddr, size: usize) -> Option<usize> {
224+
self.dev.read_dma(sector, start, size)
225+
}
226+
192227
fn read_block(&self, sector: usize, dest: &mut [MaybeUninit<u8>]) -> Option<usize> {
193228
self.dev.read_block(sector, dest)
194229
}
@@ -249,17 +284,25 @@ impl BlockDeviceInterface for PartitionBlockDevice {
249284
self.device.read_block(self.offset + sector, dest)
250285
}
251286

252-
fn block_size(&self) -> usize {
253-
self.device.block_size()
254-
}
255-
256287
fn write_block(&self, sector: usize, buf: &[u8]) -> Option<usize> {
257288
if sector >= self.size {
258289
return None;
259290
}
260291

261292
self.device.write_block(self.offset + sector, buf)
262293
}
294+
295+
fn read_dma(&self, sector: usize, start: PhysAddr, size: usize) -> Option<usize> {
296+
if sector >= self.size {
297+
return None;
298+
}
299+
300+
self.device.read_dma(self.offset + sector, start, size)
301+
}
302+
303+
fn block_size(&self) -> usize {
304+
self.device.block_size()
305+
}
263306
}
264307

265308
impl CachedAccess for PartitionBlockDevice {

0 commit comments

Comments
 (0)