Skip to content

Commit

Permalink
feat(ebpf): support Aya framework.
Browse files Browse the repository at this point in the history
1. fix the rbpf bug
2. use new Aya template
3. add kprobe related device files and attributes to sysfs
  • Loading branch information
Godones committed Dec 4, 2024
1 parent df3bf6d commit ce4d19e
Show file tree
Hide file tree
Showing 53 changed files with 858 additions and 511 deletions.
6 changes: 3 additions & 3 deletions kernel/crates/rbpf/src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -660,9 +660,9 @@ pub fn execute_program(
// Save the callee saved registers
pre_stack.save_registers(&reg[6..=9]);
// Save the return address
pre_stack.save_return_address(insn_ptr as u16);
pre_stack.save_return_address(insn_ptr as u64);
// save the stack pointer
pre_stack.save_sp(reg[10] as u16);
pre_stack.save_sp(reg[10]);
let mut stack = StackFrame::new();
log::trace!("BPF TO BPF CALL: new pc: {} + {} = {}",insn_ptr ,insn.imm,insn_ptr + insn.imm as usize);
reg[10] = stack.as_ptr() as u64 + stack.len() as u64;
Expand Down Expand Up @@ -695,7 +695,7 @@ pub fn execute_program(
// Restore the return address
insn_ptr = stack.get_return_address() as usize;
// Restore the stack pointer
reg[10] = stack.get_sp() as u64;
reg[10] = stack.get_sp();
log::trace!("EXIT: new pc: {}", insn_ptr);
}
}
Expand Down
12 changes: 6 additions & 6 deletions kernel/crates/rbpf/src/stack.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::{ebpf::STACK_SIZE, vec, Vec};

pub struct StackFrame {
return_address: u16,
return_address: u64,
saved_registers: [u64; 4],
sp: u16,
sp: u64,
frame: Vec<u8>,
}

Expand Down Expand Up @@ -54,22 +54,22 @@ impl StackFrame {
}

/// Save the return address
pub fn save_return_address(&mut self, address: u16) {
pub fn save_return_address(&mut self, address: u64) {
self.return_address = address;
}

/// Get the return address
pub fn get_return_address(&self) -> u16 {
pub fn get_return_address(&self) -> u64 {
self.return_address
}

/// Save the stack pointer
pub fn save_sp(&mut self, sp: u16) {
pub fn save_sp(&mut self, sp: u64) {
self.sp = sp;
}

/// Get the stack pointer
pub fn get_sp(&self) -> u16 {
pub fn get_sp(&self) -> u64 {
self.sp
}
}
3 changes: 2 additions & 1 deletion kernel/src/arch/x86_64/mm/fault.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,9 +267,10 @@ impl X86_64MMArch {
});
} else {
log::error!(
"No mapped vma, error_code: {:#b}, address: {:#x}",
"No mapped vma, error_code: {:#b}, address: {:#x}, flags: {:?}",
error_code,
address.data(),
flags
);
let pid = ProcessManager::current_pid();
let mut info =
Expand Down
1 change: 1 addition & 0 deletions kernel/src/bpf/helper/consts.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub const HELPER_MAP_LOOKUP_ELEM: u32 = 1;
pub const HELPER_MAP_UPDATE_ELEM: u32 = 2;
pub const HELPER_MAP_DELETE_ELEM: u32 = 3;
pub const HELPER_KTIME_GET_NS: u32 = 5;
pub const HELPER_MAP_FOR_EACH_ELEM: u32 = 164;
pub const HELPER_MAP_LOOKUP_PERCPU_ELEM: u32 = 195;
pub const HELPER_PERF_EVENT_OUTPUT: u32 = 25;
Expand Down
6 changes: 6 additions & 0 deletions kernel/src/bpf/helper/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::bpf::map::{BpfCallBackFn, BpfMap};
use crate::include::bindings::linux_bpf::BPF_F_CURRENT_CPU;
use crate::libs::lazy_init::Lazy;
use crate::smp::core::smp_get_processor_id;
use crate::time::Instant;
use alloc::{collections::BTreeMap, sync::Arc};
use core::ffi::c_void;
use system_error::SystemError;
Expand Down Expand Up @@ -300,6 +301,10 @@ pub fn map_peek_elem(map: &Arc<BpfMap>, value: &mut [u8]) -> Result<()> {
value
}

pub fn bpf_ktime_get_ns() -> u64 {
(Instant::now().total_micros() * 1000) as u64
}

pub static BPF_HELPER_FUN_SET: Lazy<BTreeMap<u32, RawBPFHelperFn>> = Lazy::new();

/// Initialize the helper functions.
Expand All @@ -311,6 +316,7 @@ pub fn init_helper_functions() {
map.insert(HELPER_MAP_LOOKUP_ELEM, define_func!(raw_map_lookup_elem));
map.insert(HELPER_MAP_UPDATE_ELEM, define_func!(raw_map_update_elem));
map.insert(HELPER_MAP_DELETE_ELEM, define_func!(raw_map_delete_elem));
map.insert(HELPER_KTIME_GET_NS, define_func!(bpf_ktime_get_ns));
map.insert(
HELPER_MAP_FOR_EACH_ELEM,
define_func!(raw_map_for_each_elem),
Expand Down
2 changes: 1 addition & 1 deletion kernel/src/bpf/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub fn bpf(cmd: bpf_cmd, attr: &bpf_attr) -> Result<usize> {
// Program related commands
bpf_cmd::BPF_PROG_LOAD => prog::bpf_prog_load(attr),
// Object creation commands
bpf_cmd::BPF_BTF_LOAD => {
bpf_cmd::BPF_BTF_LOAD | bpf_cmd::BPF_LINK_CREATE | bpf_cmd::BPF_OBJ_GET_INFO_BY_FD => {
error!("bpf cmd {:?} not implemented", cmd);
return Err(SystemError::ENOSYS);
}
Expand Down
1 change: 1 addition & 0 deletions kernel/src/driver/base/device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ pub enum DeviceType {
PlatformDev,
Char,
Pci,
Other,
}

/// @brief: 设备标识符类型
Expand Down
189 changes: 189 additions & 0 deletions kernel/src/driver/base/event_source/kprobe/device.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
use crate::driver::base::class::Class;
use crate::driver::base::device::bus::Bus;
use crate::driver::base::device::driver::Driver;
use crate::driver::base::device::{Device, DeviceCommonData, DeviceType, IdTable};
use crate::driver::base::kobject::{
KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState,
};
use crate::driver::base::kset::KSet;
use crate::filesystem::kernfs::KernFSInode;
use crate::filesystem::sysfs::{Attribute, SysFSOpsSupport};
use crate::filesystem::vfs::syscall::ModeType;
use crate::libs::rwlock::{RwLockReadGuard, RwLockWriteGuard};
use crate::libs::spinlock::{SpinLock, SpinLockGuard};
use alloc::string::{String, ToString};
use alloc::sync::{Arc, Weak};
use core::fmt::Debug;
use system_error::SystemError;

#[derive(Debug)]
#[cast_to([sync] Device)]
pub struct KprobeDevice {
inner: SpinLock<InnerKprobeDevice>,
kobj_state: LockedKObjectState,
name: String,
}

#[derive(Debug)]
struct InnerKprobeDevice {
kobject_common: KObjectCommonData,
device_common: DeviceCommonData,
}

impl KprobeDevice {
pub fn new(parent: Option<Weak<dyn KObject>>) -> Arc<Self> {
let bus_device = Self {
inner: SpinLock::new(InnerKprobeDevice {
kobject_common: KObjectCommonData::default(),
device_common: DeviceCommonData::default(),
}),
kobj_state: LockedKObjectState::new(None),
name: "kprobe".to_string(),
};
bus_device.set_parent(parent);
return Arc::new(bus_device);
}

fn inner(&self) -> SpinLockGuard<InnerKprobeDevice> {
self.inner.lock()
}
}

impl KObject for KprobeDevice {
fn as_any_ref(&self) -> &dyn core::any::Any {
self
}

fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
self.inner().kobject_common.kern_inode = inode;
}

fn inode(&self) -> Option<Arc<KernFSInode>> {
self.inner().kobject_common.kern_inode.clone()
}

fn parent(&self) -> Option<Weak<dyn KObject>> {
self.inner().kobject_common.parent.clone()
}

fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
self.inner().kobject_common.parent = parent;
}

fn kset(&self) -> Option<Arc<KSet>> {
self.inner().kobject_common.kset.clone()
}

fn set_kset(&self, kset: Option<Arc<KSet>>) {
self.inner().kobject_common.kset = kset;
}

fn kobj_type(&self) -> Option<&'static dyn KObjType> {
self.inner().kobject_common.kobj_type
}

fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
self.inner().kobject_common.kobj_type = ktype;
}

fn name(&self) -> String {
self.name.clone()
}

fn set_name(&self, _name: String) {}

fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
self.kobj_state.read()
}

fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
self.kobj_state.write()
}

fn set_kobj_state(&self, state: KObjectState) {
*self.kobj_state.write() = state;
}
}

impl Device for KprobeDevice {
#[inline]
#[allow(dead_code)]
fn dev_type(&self) -> DeviceType {
return DeviceType::Other;
}

#[inline]
fn id_table(&self) -> IdTable {
IdTable::new("kprobe".to_string(), None)
}

fn bus(&self) -> Option<Weak<dyn Bus>> {
self.inner().device_common.bus.clone()
}

fn set_bus(&self, bus: Option<Weak<dyn Bus>>) {
self.inner().device_common.bus = bus;
}

fn set_class(&self, class: Option<Weak<dyn Class>>) {
self.inner().device_common.class = class;
}

fn driver(&self) -> Option<Arc<dyn Driver>> {
self.inner().device_common.driver.clone()?.upgrade()
}

fn set_driver(&self, driver: Option<Weak<dyn Driver>>) {
self.inner().device_common.driver = driver;
}

#[inline]
fn is_dead(&self) -> bool {
false
}

fn can_match(&self) -> bool {
todo!()
}

fn set_can_match(&self, _can_match: bool) {
todo!()
}

fn state_synced(&self) -> bool {
todo!()
}

fn dev_parent(&self) -> Option<Weak<dyn Device>> {
self.inner().device_common.get_parent_weak_or_clear()
}

fn set_dev_parent(&self, dev_parent: Option<Weak<dyn Device>>) {
self.inner().device_common.parent = dev_parent;
}
}

#[derive(Debug)]
pub struct KprobeAttr;

impl Attribute for KprobeAttr {
fn name(&self) -> &str {
"type"
}

fn mode(&self) -> ModeType {
ModeType::from_bits_truncate(0o444)
}

fn support(&self) -> SysFSOpsSupport {
SysFSOpsSupport::ATTR_SHOW | SysFSOpsSupport::BATTR_READ
}
fn show(&self, _kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
if buf.is_empty() {
return Err(SystemError::EINVAL);
}
// perf_type_id::PERF_TYPE_MAX
buf[0] = b'6';
Ok(1)
}
}
28 changes: 28 additions & 0 deletions kernel/src/driver/base/event_source/kprobe/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use crate::driver::base::device::bus::Bus;
use crate::driver::base::device::{device_manager, device_register, sys_devices_kset, Device};
use crate::driver::base::event_source::get_event_source_bus;
use crate::driver::base::event_source::kprobe::device::{KprobeAttr, KprobeDevice};
use crate::driver::base::kobject::KObject;
use alloc::sync::Arc;
use system_error::SystemError;

pub mod device;
static mut KPROBE_DEVICE: Option<Arc<KprobeDevice>> = None;

pub fn kprobe_subsys_init() -> Result<(), SystemError> {
let kprobe_device = KprobeDevice::new(Some(Arc::downgrade(
&(sys_devices_kset() as Arc<dyn KObject>),
)));

let event_source_bus = get_event_source_bus().ok_or(SystemError::EINVAL)?;
kprobe_device.set_bus(Some(Arc::downgrade(&(event_source_bus as Arc<dyn Bus>))));

// 注册到/sys/devices下
device_register(kprobe_device.clone())?;
unsafe {
KPROBE_DEVICE = Some(kprobe_device.clone());
}

device_manager().create_file(&(kprobe_device as Arc<dyn Device>), &KprobeAttr)?;
Ok(())
}
25 changes: 25 additions & 0 deletions kernel/src/driver/base/event_source/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use crate::driver::base::device::bus::{bus_register, Bus};
use crate::driver::base::event_source::subsys::EventSourceBus;
use alloc::sync::Arc;
use system_error::SystemError;

mod kprobe;
mod subsys;

static mut EVENT_SOURCE_BUS: Option<Arc<EventSourceBus>> = None;

fn get_event_source_bus() -> Option<Arc<EventSourceBus>> {
unsafe { EVENT_SOURCE_BUS.clone() }
}

pub fn init_event_source_bus() -> Result<(), SystemError> {
let event_source_bus = EventSourceBus::new();
let r = bus_register(event_source_bus.clone() as Arc<dyn Bus>);
if r.is_err() {
unsafe { EVENT_SOURCE_BUS = None };
return r;
}
unsafe { EVENT_SOURCE_BUS = Some(event_source_bus.clone()) };
kprobe::kprobe_subsys_init()?;
Ok(())
}
Loading

0 comments on commit ce4d19e

Please sign in to comment.