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