xref: /DragonOS/kernel/crates/klog_types/src/lib.rs (revision bd70d2d1f490aabd570a5301b858bd5eb04149fa)
1 #![no_std]
2 #![feature(const_refs_to_cell)]
3 #![feature(const_size_of_val)]
4 #![allow(clippy::needless_return)]
5 
6 extern crate alloc;
7 use core::{fmt::Debug, mem::size_of_val};
8 
9 use alloc::format;
10 use kdepends::{memoffset::offset_of, thingbuf::StaticThingBuf};
11 
12 #[repr(C)]
13 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
14 pub struct AllocatorLog {
15     /// 日志的id
16     pub id: u64,
17     /// 日志类型
18     pub type_: AllocatorLogType,
19     /// 日志的时间
20     pub time: u64,
21 
22     /// 日志的来源
23     pub source: LogSource,
24 
25     /// 日志的来源pid
26     pub pid: Option<usize>,
27 
28     pub checksum: u64,
29 }
30 
31 impl AllocatorLog {
32     /// 创建一个日志
33     ///
34     /// ## 参数
35     ///
36     /// - `id`:日志的id
37     /// - `type_`:日志类型
38     /// - `source`:日志来源
39     /// - `pid`:日志来源的pid
40     /// - `time`:日志的时间
new( id: u64, type_: AllocatorLogType, source: LogSource, pid: Option<usize>, time: u64, ) -> Self41     pub fn new(
42         id: u64,
43         type_: AllocatorLogType,
44         source: LogSource,
45         pid: Option<usize>,
46         time: u64,
47     ) -> Self {
48         let mut x = Self {
49             id,
50             type_,
51             time,
52             source,
53             pid,
54             checksum: 0,
55         };
56         let checksum = Self::calculate_checksum(&x);
57         x.checksum = checksum;
58         return x;
59     }
60 
zeroed() -> Self61     pub const fn zeroed() -> Self {
62         return Self {
63             id: 0,
64             type_: AllocatorLogType::Undefined,
65             time: 0,
66             source: LogSource::Undefined,
67             pid: None,
68             checksum: 0,
69         };
70     }
71 
72     /// 计算日志的校验和
calculate_checksum(value: &Self) -> u6473     pub fn calculate_checksum(value: &Self) -> u64 {
74         let buf = unsafe {
75             core::slice::from_raw_parts(
76                 value as *const _ as *const u8,
77                 core::mem::size_of::<Self>() - core::mem::size_of::<u64>(),
78             )
79         };
80         let checksum = kdepends::crc::crc64::crc64_be(0, buf);
81         return checksum;
82     }
83 
84     /// 验证日志的校验和
validate_checksum(&self) -> bool85     pub fn validate_checksum(&self) -> bool {
86         let checksum = Self::calculate_checksum(self);
87         return checksum == self.checksum;
88     }
89 
90     /// 当前日志是否有效
is_valid(&self) -> bool91     pub fn is_valid(&self) -> bool {
92         if !self.validate_checksum() {
93             return false;
94         }
95 
96         if self.id == 0 {
97             return false;
98         }
99 
100         return true;
101     }
102 }
103 
104 impl PartialOrd for AllocatorLog {
partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering>105     fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
106         Some(self.cmp(other))
107     }
108 }
109 
110 impl Ord for AllocatorLog {
cmp(&self, other: &Self) -> core::cmp::Ordering111     fn cmp(&self, other: &Self) -> core::cmp::Ordering {
112         return self.id.cmp(&other.id);
113     }
114 }
115 
116 /// 内存分配器日志类型
117 #[repr(C)]
118 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
119 pub enum AllocatorLogType {
120     Undefined,
121     Alloc(AllocLogItem),
122     AllocZeroed(AllocLogItem),
123     Free(AllocLogItem),
124     LazyAlloc(AllocLogItem),
125 }
126 
127 #[repr(C)]
128 #[derive(Copy, Clone, PartialEq, Eq)]
129 pub struct AllocLogItem {
130     pub layout: core::alloc::Layout,
131     pub vaddr: Option<usize>,
132     pub paddr: Option<usize>,
133 }
134 
135 impl AllocLogItem {
new(layout: core::alloc::Layout, vaddr: Option<usize>, paddr: Option<usize>) -> Self136     pub fn new(layout: core::alloc::Layout, vaddr: Option<usize>, paddr: Option<usize>) -> Self {
137         return Self {
138             layout,
139             vaddr,
140             paddr,
141         };
142     }
143 }
144 
145 impl Debug for AllocLogItem {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result146     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
147         f.debug_struct("AllocLogItem")
148             .field("layout", &self.layout)
149             .field(
150                 "vaddr",
151                 &format_args!("{:#x}", *self.vaddr.as_ref().unwrap_or(&0)),
152             )
153             .field(
154                 "paddr",
155                 &format_args!("{:#x}", self.paddr.as_ref().unwrap_or(&0)),
156             )
157             .finish()
158     }
159 }
160 
161 #[repr(u8)]
162 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
163 pub enum LogSource {
164     Undefined = 0,
165     Bump = 1,
166     Buddy = 2,
167     Slab = 3,
168 }
169 
170 pub struct MMLogCycle;
171 
172 impl MMLogCycle {
new() -> Self173     pub const fn new() -> Self {
174         Self {}
175     }
176 }
177 
178 impl Default for MMLogCycle {
default() -> Self179     fn default() -> Self {
180         Self::new()
181     }
182 }
183 
184 impl kdepends::thingbuf::Recycle<AllocatorLog> for MMLogCycle {
new_element(&self) -> AllocatorLog185     fn new_element(&self) -> AllocatorLog {
186         AllocatorLog::zeroed()
187     }
188 
recycle(&self, element: &mut AllocatorLog)189     fn recycle(&self, element: &mut AllocatorLog) {
190         *element = AllocatorLog::zeroed();
191     }
192 }
193 
194 /// 内存分配器日志通道
195 #[repr(C)]
196 pub struct MMLogChannel<const CAP: usize> {
197     pub magic: u32,
198     /// 日志元素的大小
199     pub element_size: u32,
200     /// 日志通道每个槽的大小(字节)
201     pub slot_size: u32,
202     pub capacity: u64,
203     pub slots_offset: u64,
204     pub buf: StaticThingBuf<AllocatorLog, CAP, MMLogCycle>,
205 }
206 
207 impl<const CAP: usize> Debug for MMLogChannel<CAP> {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result208     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
209         f.debug_struct("MMLogChannel")
210             .field("magic", &format!("{:#x}", self.magic))
211             .field("element_size", &self.element_size)
212             .field("capacity", &self.capacity)
213             .field("slots_offset", &self.slots_offset)
214             .field(
215                 "buf",
216                 &format!(
217                     "StaticThingBuf<AllocatorLog, {}, MMLogCycle>",
218                     self.capacity
219                 ),
220             )
221             .finish()
222     }
223 }
224 
225 impl<const CAP: usize> MMLogChannel<CAP> {
226     /// 日志通道的魔数
227     pub const MM_LOG_CHANNEL_MAGIC: u32 = 0x4d4c4348;
228 
229     /// 创建一个大小为`capacity`日志通道
new(capacity: usize) -> Self230     pub const fn new(capacity: usize) -> Self {
231         let buffer = StaticThingBuf::with_recycle(MMLogCycle::new());
232         assert!(buffer.offset_of_slots() != 0);
233         let slot_total_size = size_of_val(&buffer) - buffer.offset_of_slots();
234         let slot_size = slot_total_size / capacity;
235         assert!(slot_size != 0);
236         assert!(slot_size > size_of_val(&AllocatorLog::zeroed()));
237 
238         let r = Self {
239             magic: Self::MM_LOG_CHANNEL_MAGIC,
240             element_size: core::mem::size_of::<AllocatorLog>() as u32,
241             capacity: capacity as u64,
242             slot_size: slot_size as u32,
243             slots_offset: (offset_of!(MMLogChannel<CAP>, buf) + buffer.offset_of_slots()) as u64,
244             buf: buffer,
245         };
246 
247         return r;
248     }
249 }
250