+2
-1
components/ukernel/arch/amd64/boot.zig
+2
-1
components/ukernel/arch/amd64/boot.zig
+1
-1
components/ukernel/arch/amd64/interrupts/pic.zig
+1
-1
components/ukernel/arch/amd64/interrupts/pic.zig
+13
components/ukernel/arch/amd64/interrupts/pit.zig
+13
components/ukernel/arch/amd64/interrupts/pit.zig
···
4
4
const Idt = arch.structures.Idt;
5
5
const PIT_HZ = 1_193_180;
6
6
const DATA_PORT = 0x40;
7
+
const DATA_PORT_1 = 0x41;
8
+
const DATA_PORT_2 = 0x42;
7
9
const CMD_PORT = 0x43;
8
10
11
+
// If we want a repeating square wave
9
12
pub fn set_frequency(hz: u32) void {
10
13
const divider = PIT_HZ / hz;
11
14
@import("std").log.debug("divider = {}", .{divider});
···
16
19
out(u8, DATA_PORT, @truncate(divider));
17
20
out(u8, DATA_PORT, @truncate(divider >> 8));
18
21
}
22
+
23
+
pub inline fn mode0(ms: u32) void {
24
+
out(u8, CMD_PORT, 0xb0);
25
+
26
+
// Interrupt On Terminal Count
27
+
const latch = (PIT_HZ / (1000 / ms));
28
+
out(u8, 0x42, @truncate(latch));
29
+
out(u8, 0x42, @truncate(latch >> 8));
30
+
}
31
+
19
32
var ctr: usize = 0;
20
33
pub fn handler(_: *Idt.InterruptStackFrame) callconv(.{ .x86_64_interrupt = .{} }) void {
21
34
if (ctr % 1000 == 0)
+26
-6
components/ukernel/arch/amd64/tsc.zig
+26
-6
components/ukernel/arch/amd64/tsc.zig
···
1
1
const arch = @import("root.zig");
2
+
const out = arch.port.out;
3
+
const in = arch.port.in;
4
+
2
5
pub inline fn rdtsc() u64 {
3
6
var low: u32 = undefined;
4
7
var high: u32 = undefined;
5
8
6
9
asm volatile ("rdtsc"
7
10
: [low] "={eax}" (low),
8
-
[high] "={eax}" (high),
11
+
[high] "={edx}" (high),
9
12
);
10
13
11
14
return (@as(u64, high) << 32) | @as(u64, low);
···
14
17
/// This should be called if we cannot get the TSC rate from
15
18
/// CPUID.15h and 16h on Intel platforms. The calibration will be done
16
19
/// against the 8254 PIT.
17
-
pub fn calibrate() void {
20
+
pub fn get_tsc_rate() ?usize {
18
21
// Set up the PIC
19
22
arch.interrupts.pic.init();
20
23
21
-
// Set up the PIT at 1 kHz
22
-
arch.interrupts.pit.set_frequency(1000);
24
+
out(u8, 0x61, in(u8, 0x61) & 0b1111_1101 | 0x01);
23
25
24
-
// Enable interrupts
25
-
// arch.interrupts.enable();
26
+
var pollcnt: u32 = 0;
27
+
var start: usize = 0;
28
+
var end: usize = 0;
29
+
var prev_end: usize = 0;
30
+
var delta: usize = 0;
31
+
32
+
arch.interrupts.pit.mode0(50);
33
+
start = rdtsc();
34
+
end = start;
35
+
while (in(u8, 0x61) & 0x20 == 0) {
36
+
end = rdtsc();
37
+
delta = end - prev_end;
38
+
prev_end = end;
39
+
40
+
pollcnt += 1;
41
+
}
42
+
43
+
if (pollcnt < 1000) return null;
44
+
45
+
return (end - start) / 50;
26
46
}