Microkernel thing OS experiment (Zig ⚡)
1const arch = @import("root.zig"); 2const out = arch.port.out; 3const in = arch.port.in; 4 5pub var tsc_khz: usize = 0; 6 7pub inline fn rdtsc() u64 { 8 var low: u32 = undefined; 9 var high: u32 = undefined; 10 11 asm volatile ("rdtsc" 12 : [low] "={eax}" (low), 13 [high] "={edx}" (high), 14 ); 15 16 return (@as(u64, high) << 32) | @as(u64, low); 17} 18 19/// This should be called if we cannot get the TSC rate from 20/// CPUID.15h and 16h on Intel platforms. The calibration will be done 21/// against the 8254 PIT. 22pub fn calibrate_pit() !void { 23 // Set up the PIC 24 arch.interrupts.pic.init(); 25 26 out(u8, 0x61, in(u8, 0x61) & 0b1111_1101 | 0x01); 27 28 var pollcnt: u32 = 0; 29 var start: usize = 0; 30 var end: usize = 0; 31 var prev_end: usize = 0; 32 var delta: usize = 0; 33 34 arch.interrupts.pit.mode0(50); 35 start = rdtsc(); 36 end = start; 37 while (in(u8, 0x61) & 0x20 == 0) { 38 end = rdtsc(); 39 delta = end - prev_end; 40 prev_end = end; 41 42 pollcnt += 1; 43 } 44 45 if (pollcnt < 1000) return error.PitError; 46 47 tsc_khz = (end - start) / 50; 48} 49 50/// Delay for a set amount of ms using crappy polling 51pub fn delay_poll(ms: usize) void { 52 const start = rdtsc(); 53 const target = start + ms * tsc_khz; 54 while (rdtsc() < target) {} 55}