Skip to content

Commit

Permalink
feat(ebpf): support Aya framework. (#1070)
Browse files Browse the repository at this point in the history
* feat(ebpf): support Aya framework.

1. fix the rbpf bug
2. use new Aya template
3. add kprobe related device files and attributes to sysfs

---
Signed-off-by: chenlinfeng <[email protected]>
  • Loading branch information
Godones authored Dec 7, 2024
1 parent c09af90 commit 72423f9
Show file tree
Hide file tree
Showing 53 changed files with 849 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
1 change: 0 additions & 1 deletion kernel/src/driver/base/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ pub fn driver_init() -> Result<(), SystemError> {
platform_bus_init()?;
serio_bus_init()?;
CpuDeviceManager::init()?;

// 至此,已完成设备驱动模型的初始化
return Ok(());
}
27 changes: 26 additions & 1 deletion kernel/src/filesystem/procfs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,31 @@ impl ProcFS {
} else {
panic!("create ksmg error");
}

// 这个文件是用来欺骗Aya框架识别内核版本
/* On Ubuntu LINUX_VERSION_CODE doesn't correspond to info.release,
* but Ubuntu provides /proc/version_signature file, as described at
* https://ubuntu.com/kernel, with an example contents below, which we
* can use to get a proper LINUX_VERSION_CODE.
*
* Ubuntu 5.4.0-12.15-generic 5.4.8
*
* In the above, 5.4.8 is what kernel is actually expecting, while
* uname() call will return 5.4.0 in info.release.
*/
let binding = inode.create("version_signature", FileType::File, ModeType::S_IRUGO);
if let Ok(version_signature) = binding {
let version_signature = version_signature
.as_any_ref()
.downcast_ref::<LockedProcFSInode>()
.unwrap();
version_signature.0.lock().fdata.ftype = ProcFileType::Default;
version_signature.0.lock().data = "DragonOS 6.0.0-generic 6.0.0\n"
.to_string()
.as_bytes()
.to_vec();
} else {
panic!("create version_signature error");
}
return result;
}

Expand Down Expand Up @@ -466,6 +490,7 @@ impl IndexNode for LockedProcFSInode {
let file_size = match inode.fdata.ftype {
ProcFileType::ProcStatus => inode.open_status(&mut private_data)?,
ProcFileType::ProcMeminfo => inode.open_meminfo(&mut private_data)?,
ProcFileType::Default => inode.data.len() as i64,
_ => {
todo!()
}
Expand Down
189 changes: 189 additions & 0 deletions kernel/src/misc/events/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::S_IRUGO
}

fn support(&self) -> SysFSOpsSupport {
SysFSOpsSupport::ATTR_SHOW
}
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)
}
}
31 changes: 31 additions & 0 deletions kernel/src/misc/events/kprobe/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use crate::driver::base::device::bus::Bus;
use crate::driver::base::device::{device_manager, device_register, sys_devices_kset, Device};
use crate::driver::base::kobject::KObject;
use crate::init::initcall::INITCALL_DEVICE;
use crate::misc::events::get_event_source_bus;
use crate::misc::events::kprobe::device::{KprobeAttr, KprobeDevice};
use alloc::sync::Arc;
use system_error::SystemError;
use unified_init::macros::unified_init;

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

#[unified_init(INITCALL_DEVICE)]
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(())
}
Loading

0 comments on commit 72423f9

Please sign in to comment.