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