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

Add code for profiling #621

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
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
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ AR=ar
ARCREATE=cr

ifndef OPTFLAGS
OPTFALGS := -O
OPTFLAGS := -O
endif

CFLAGS = -Wall -Werror $(OPTFLAGS) -fno-omit-frame-pointer -ggdb
Expand Down Expand Up @@ -313,7 +313,7 @@ QEMUGDB = $(shell if $(QEMU) -help | grep -q '^-gdb'; \
then echo "-gdb tcp::$(GDBPORT)"; \
else echo "-s -p $(GDBPORT)"; fi)
ifndef CPUS
CPUS := 3
CPUS := 1
endif

QEMUOPTS = -machine virt -kernel $K/kernel -m 128M -smp $(CPUS) -nographic
Expand Down
2 changes: 1 addition & 1 deletion kernel-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ opt-level = 1

[profile.release]
panic = "abort"
lto = true
opt-level = 2

[dependencies]
array-macro = "2.1.0"
Expand Down
2 changes: 1 addition & 1 deletion kernel-rs/src/arch/arm/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ pub enum SmcFunctions {
///
/// Arguments must follow ARM SMC calling convention.
#[no_mangle]
pub unsafe fn smc_call(x0: u64, x1: u64, x2: u64, x3: u64) -> u64 {
pub unsafe fn smc_call(x0: u64, x1: u64, x2: u64, x3: u64) -> (u64, u64, u64, u64) {
let (r0, r1, r2, r3);
unsafe {
// NOTE: here use hvc for qemu without `virtualization=on`
Expand Down
14 changes: 13 additions & 1 deletion kernel-rs/src/arch/arm/timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ const TIMER_TICK_MS: u64 = 100;

impl TimeManager for Armv8 {
fn timer_init() {
let mut x: usize;

// for user-space clock time profiling.
unsafe {
asm!("mrs {}, cntkctl_el1", out(reg) x);
x &= !((3 << 8) | (1 << 1));
x |= 1;
asm!("msr cntkctl_el1, {}", in(reg) x);
}

set_next_timer();
}

Expand All @@ -26,7 +36,9 @@ impl TimeManager for Armv8 {
pub fn read_cntpct() -> u64 {
// Prevent that the counter is read ahead of time due to out-of-order execution.
unsafe { barrier::isb(barrier::SY) };
CNTPCT_EL0.get()
let ret = CNTPCT_EL0.get();
unsafe { barrier::isb(barrier::SY) };
ret
}

pub fn read_freq() -> u64 {
Expand Down
25 changes: 25 additions & 0 deletions kernel-rs/src/arch/arm/trap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::{
timer::set_next_timer,
Armv8,
},
// kernel::KERNEL,
memlayout::{TRAMPOLINE, TRAPFRAME},
trap::{IrqNum, IrqTypes, TrapTypes},
};
Expand Down Expand Up @@ -196,6 +197,7 @@ impl TrapManager for Armv8 {
trapframe: &mut TrapFrame,
kernel_stack: usize,
usertrap: usize,
_syscall_num: usize,
) -> ! {
// We're about to switch the destination of traps from
// kerneltrap() to usertrap(), so turn off interrupts until
Expand All @@ -219,6 +221,29 @@ impl TrapManager for Armv8 {
let fn_0: usize =
TRAMPOLINE + unsafe { userret.as_ptr().offset_from(trampoline.as_ptr()) } as usize;
let fn_0 = unsafe { mem::transmute::<_, unsafe extern "C" fn(usize, usize) -> !>(fn_0) };
// let clock = TargetArch::r_cycle();
// unsafe {
// TIME[3] = clock;
// }

// If it is getppid, print elapsed time per interval.
// if _syscall_num == 26 {
// unsafe {
// crate::kernel::kernel_ref(|kctx| {
// // for i in 0..8 {
// kctx.as_ref().write_fmt(format_args!(
// "Interval {}: {}\n",
// 0,
// TIME[0] - TIME[9]
// ));
// // }
// // for i in 0..4{
// // kctx.as_ref().write_fmt(format_args!("lap {}: {}\n", i, TIME[i]));
// // }
// })
// }
// }

unsafe { fn_0(TRAPFRAME, user_pagetable_addr) }
}

Expand Down
1 change: 1 addition & 0 deletions kernel-rs/src/arch/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ pub trait TrapManager {
trap: &mut <TargetArch as ProcManager>::TrapFrame,
kernel_stack: usize,
usertrap: usize,
syscall_num: usize,
) -> !;

fn save_trap_regs(store: &mut [usize; 10]);
Expand Down
1 change: 1 addition & 0 deletions kernel-rs/src/arch/riscv/trap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ impl TrapManager for RiscV {
trapframe: &mut TrapFrame,
kernel_stack: usize,
usertrap: usize,
_syscall_num: usize,
) -> ! {
// We're about to switch the destination of traps from
// kerneltrap() to usertrap(), so turn off interrupts until
Expand Down
9 changes: 7 additions & 2 deletions kernel-rs/src/kernel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@ use crate::{
const CONSOLE_IN_DEVSW: usize = 1;

/// The kernel.
static mut KERNEL: Kernel<TargetArch> = unsafe { Kernel::new() };
pub static mut KERNEL: Kernel<TargetArch> = unsafe { Kernel::new() };

pub static mut TIME: [usize; 10] = [0; 10];

/// Returns a shared reference to the `KERNEL`.
#[inline]
fn kernel<'s>() -> StrongPin<'s, Kernel<TargetArch>> {
pub fn kernel<'s>() -> StrongPin<'s, Kernel<TargetArch>> {
// SAFETY: there is no way to make a mutable reference to `KERNEL` except calling
// `kernel_builder_unchecked_pin`, which is unsafe.
unsafe { StrongPin::new_unchecked(&KERNEL) }
Expand Down Expand Up @@ -89,6 +91,8 @@ pub struct Kernel<A: Arch> {

#[pin]
file_system: DefaultFs,

pub time_data: [usize; 10],
}

/// A branded reference to a `Kernel`.
Expand Down Expand Up @@ -172,6 +176,7 @@ impl<A: Arch> Kernel<A> {
}; NDEV],
ftable: FileTable::new_ftable(),
file_system: DefaultFs::new(),
time_data: [0; 10],
}
}

Expand Down
24 changes: 22 additions & 2 deletions kernel-rs/src/proc/procs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use super::*;
use crate::{
addr::{Addr, UVAddr, PGSIZE},
arch::interface::TrapFrameManager,
arch::TargetArch,
fs::{DefaultFs, FileSystem, FileSystemExt},
hal::hal,
kalloc::Kmem,
Expand Down Expand Up @@ -465,11 +466,30 @@ impl<'id, 's> ProcsRef<'id, 's> {
}

// get the pid of current process's parent
pub fn get_parent_pid(&mut self, ctx: &mut KernelCtx<'id, '_>) -> Pid {
pub fn get_parent_pid(&self, ctx: &mut KernelCtx<'id, '_>) -> Pid {
// let before = TargetArch::r_cycle();
let mut parent_guard = self.wait_guard();

// let after = TargetArch::r_cycle();

// ctx.kernel().as_ref().write_fmt(format_args!("lap1: {}\n", after - before));

// let before = TargetArch::r_cycle();

let parent = *ctx.proc().get_mut_parent(&mut parent_guard);

// let after = TargetArch::r_cycle();

// ctx.kernel().as_ref().write_fmt(format_args!("lap2: {}\n", after - before));

// let before = TargetArch::r_cycle();

let lock = unsafe { (*parent).info.lock() };

// let after = TargetArch::r_cycle();

// ctx.kernel().as_ref().write_fmt(format_args!("lap3: {}\n", after - before));

lock.pid
}
}
Expand All @@ -491,7 +511,7 @@ unsafe fn forkret() -> ! {
// regular process (e.g., because it calls sleep), and thus cannot
// be run from main().
ctx.kernel().fs().init(ROOTDEV, &ctx);
unsafe { ctx.user_trap_ret() }
unsafe { ctx.user_trap_ret(0) }
};

unsafe { kernel_ctx(forkret_inner) }
Expand Down
16 changes: 14 additions & 2 deletions kernel-rs/src/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,12 @@ impl CurrentProc<'_, '_> {

impl KernelCtx<'_, '_> {
pub fn syscall(&mut self, num: i32) -> Result<usize, ()> {
match num {
// let clock = TargetArch::r_cycle();
// record end of stage 2 (begin of stage 3).
// unsafe {
// TIME[1] = clock;
// }
let ret = match num {
1 => self.sys_fork(),
2 => self.sys_exit(),
3 => self.sys_wait(),
Expand Down Expand Up @@ -128,7 +133,14 @@ impl KernelCtx<'_, '_> {
));
Err(())
}
}
};

// let clock = TargetArch::r_cycle();
// record end of stage 3 (begin of stage 4).
// unsafe {
// TIME[2] = clock;
// }
ret
}

/// Terminate the current process; status reported to wait(). No return.
Expand Down
25 changes: 21 additions & 4 deletions kernel-rs/src/trap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::{
arch::interface::{ProcManager, TrapFrameManager, TrapManager},
arch::TargetArch,
hal::hal,
kernel::TIME,
kernel::{kernel_ref, KernelRef},
ok_or,
proc::{kernel_ctx, KernelCtx, Procstate},
Expand Down Expand Up @@ -38,7 +39,12 @@ pub type IrqNum = usize;
/// Handle an interrupt, exception, or system call from user space.
/// Called from trampoline.S.
#[no_mangle]
pub unsafe extern "C" fn usertrap(arg: usize) {
pub unsafe extern "C" fn usertrap(arg: usize, _a: usize, time: usize) {
// record start of stage 2.
unsafe {
TIME[0] = time;
}

// SAFETY
// * usertrap can be reached only after the initialization of the kernel.
// * It's the beginning of this thread, so there's no exsiting `KernelCtx` or `CurrentProc`.
Expand Down Expand Up @@ -78,6 +84,8 @@ impl KernelCtx<'_, '_> {
TargetArch::before_handling_trap(&trap_type, Some(self.proc_mut().trap_frame_mut()));
}

let mut syscall_num = 0;

match &trap_type {
TrapTypes::Syscall => {
// system call
Expand All @@ -90,6 +98,7 @@ impl KernelCtx<'_, '_> {
// SAFETY: Interrupt handlers has been configured properly
unsafe { TargetArch::intr_on() };
let syscall_no = self.proc_mut().trap_frame_mut().get_param_reg(7.into()) as i32;
syscall_num = syscall_no;
*self.proc_mut().trap_frame_mut().param_reg_mut(0.into()) =
ok_or!(self.syscall(syscall_no), usize::MAX);
}
Expand Down Expand Up @@ -127,15 +136,15 @@ impl KernelCtx<'_, '_> {
self.yield_cpu();
}

unsafe { self.user_trap_ret() }
unsafe { self.user_trap_ret(syscall_num as usize) }
}

/// Return to user space.
///
/// # Safety
///
/// It must be called only by `user_trap`.
pub unsafe fn user_trap_ret(mut self) -> ! {
pub unsafe fn user_trap_ret(mut self, syscall_num: usize) -> ! {
// Tell trampoline.S the user page table to switch to.
let user_table = self.proc().memory().page_table_addr();

Expand All @@ -144,7 +153,15 @@ impl KernelCtx<'_, '_> {
let trapframe = self.proc_mut().trap_frame_mut();

// SAFETY: It is called by `user_trap_ret`, after handling the user trap.
unsafe { TargetArch::user_trap_ret(user_table, trapframe, kstack, usertrap as usize) };
unsafe {
TargetArch::user_trap_ret(
user_table,
trapframe,
kstack,
usertrap as usize,
syscall_num,
)
};
}
}

Expand Down
24 changes: 14 additions & 10 deletions kernel/arm/trampoline.S
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,6 @@
.globl trampoline
trampoline:

.macro flush_cache
isb sy
dsb sy
dsb ishst
tlbi vmalle1is
dsb ish
isb
.endm

.macro exception_1_entry
sub sp, sp, #272
Expand Down Expand Up @@ -73,6 +65,11 @@ trampoline:
// we don't use it.
msr tpidr_el1, x0

// record stage2 start time
mrs x0, cntpct_el0
msr tpidr_el0, x0


// assign TRAPFRAME address (fixed) to x0
movz x0, #0xe000
movk x0, #0xffff, lsl #16
Expand Down Expand Up @@ -138,8 +135,12 @@ trampoline:

msr ttbr0_el1, x24

mrs x3, cntpct_el0
msr tpidr_el0, x3

# flush all the caches
flush_cache
tlbi vmalle1is
isb
.endm

/* Exception vectors */
Expand Down Expand Up @@ -189,7 +190,9 @@ userret:
# switch to the user page table.
msr ttbr0_el1, x1

flush_cache
dsb nsh
tlbi vmalle1is
isb

# restore ELR, SPSR, LR, SP
ldp x21, x22, [x0, #16] /* SPSR, FPSR */
Expand Down Expand Up @@ -301,6 +304,7 @@ cur_el_spx_error:
.align 6
lower_el_aarch64_sync:
exception_0_entry
mrs x2, tpidr_el0
mov x0, #0
# jump to usertrap(), which does not return
br x1
Expand Down
Loading