rcore-os / rCore-Tutorial-v3

Let's write an OS which can run on RISC-V in Rust from scratch!
https://rcore-os.github.io/rCore-Tutorial-Book-v3/index.html
GNU General Public License v3.0
1.58k stars 452 forks source link

Cache coherence #98

Closed PorterLu closed 1 year ago

PorterLu commented 1 year ago

Dear maintainer, There is a piece of code in ch2, asm!("fence.i") is used to flush I-Cache to maintain cache coherence. But considering the below figure, if we dont't use fence.i after loading code,we may fetch old code from memory. So I consider place fence.i at the end of load_app. Look forward to your response!

println!("[kernel] Loading app_{}", app_id);
// clear icache
asm!("fence.i");
// clear app area
core::slice::from_raw_parts_mut(APP_BASE_ADDRESS as *mut u8, APP_SIZE_LIMIT).fill(0);
let app_src = core::slice::from_raw_parts(
    self.app_start[app_id] as *const u8,
    self.app_start[app_id + 1] - self.app_start[app_id],
);
let app_dst = core::slice::from_raw_parts_mut(APP_BASE_ADDRESS as *mut u8, app_src.len());
app_dst.copy_from_slice(app_src);

wyfcyx commented 1 year ago

I agree with you. As you said, the fence.i instruction should be put at the end of the load_app function. However, I think it is nothing to do with the d-cache. Therefore, I cannot understand what you actually mean by the diagram. In fact, the fence.i instruction is a kind of memory fence instead of just an operation of flushing i-cache. From the spec, it is guaranteed that a subsequent instruction fetch after fence.i must observes all writes to the instruction memory before fence.i. Thus, fence.i must be executed after we have loaded the code of the next app into the instruction memory. I will update the code later 😃

PorterLu commented 1 year ago

I think “it is guaranteed that a subsequent instruction fetch after fence.i must observes all writes to the instruction memory before fence.i" is right. The figure is trying to explain a coherence problem from hardware view. STORE only writes data on D-Cache , so after that, the contents in I-Cache and D-Cache are different. When we fetch instruction at this state, we only get instructions from I-Cache or memory. Therefore, fence-i saves us. Thanks for your response!

wyfcyx commented 1 year ago

Great explanation. Thank you!