]> pd.if.org Git - zos/commitdiff
amd64 processor low level functions
authorNathan Wagner <nw@hydaspes.if.org>
Tue, 25 Oct 2016 01:28:42 +0000 (20:28 -0500)
committerNathan Wagner <nw@hydaspes.if.org>
Tue, 25 Oct 2016 01:40:26 +0000 (20:40 -0500)
cpu.h [new file with mode: 0644]
cpu.s [new file with mode: 0644]
spinlock.h [new file with mode: 0644]
spinlock.s [new file with mode: 0644]

diff --git a/cpu.h b/cpu.h
new file mode 100644 (file)
index 0000000..4103335
--- /dev/null
+++ b/cpu.h
@@ -0,0 +1,17 @@
+#ifndef _ZOS_CPU_H_
+#define _ZOS_CPU_H_
+
+#define MSR_LSTAR 0xC0000081
+
+uint64_t readtsc(void);
+void writemsr(uint32_t msr, uint64_t val);
+uint64_t readmsr(uint32_t msr);
+void enable_syscall();
+void disable_syscall();
+uint64_t setdr0(uint64_t);
+uint64_t setdr1(uint64_t);
+uint64_t setdr2(uint64_t);
+uint64_t setdr3(uint64_t);
+uint64_t nextrip(void);
+
+#endif
diff --git a/cpu.s b/cpu.s
new file mode 100644 (file)
index 0000000..30ca25e
--- /dev/null
+++ b/cpu.s
@@ -0,0 +1,70 @@
+global readtsc:function
+global readmsr:function
+global writemsr:function
+global enable_syscall:function
+global disable_syscall:function
+global setdr0:function
+global setdr1:function
+global setdr2:function
+global setdr3:function
+global nextrip:function
+
+setdr0:
+       mov rax, dr0
+       mov dr0, rdi
+       ret
+
+setdr1:
+       mov rax, dr1
+       mov dr1, rdi
+       ret
+setdr2:
+       mov rax, dr2
+       mov dr2, rdi
+       ret
+setdr3:
+       mov rax, dr3
+       mov dr3, rdi
+       ret
+
+nextrip:
+       pop rax
+       push rax
+       ret
+       
+readtsc:
+       rdtsc
+       shl rdx, 32
+       or rax, rdx
+       ret
+
+writemsr:
+       ; rdi is msr, rsi is value to write
+       mov ecx, edi
+       ; edx is high order bits, eax is low order bits to write
+       mov eax, esi
+       shr rsi, 32
+       mov edx, esi
+       wrmsr
+       ret
+
+readmsr:
+       mov ecx, edi
+       rdmsr
+       shl rdx, 32
+       or rax, rdx
+
+%define EFER 0xc0000080
+enable_syscall:
+       mov ecx, EFER
+       rdmsr
+       or eax, 0x1
+       wrmsr
+       ret
+
+disable_syscall:
+       mov ecx, EFER
+       rdmsr
+       and eax, DWORD ~0x1
+       wrmsr
+       ret
diff --git a/spinlock.h b/spinlock.h
new file mode 100644 (file)
index 0000000..7a70a0d
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _SPINLOCK_H_
+#define _SPINLOCK_H_ 1
+struct spinlock_t {
+       uint32_t ticket;
+       uint32_t counter;
+};
+
+void spinlock_release(struct spinlock_t *);
+void spinlock_init(struct spinlock_t *);
+void spinlock_acquire(struct spinlock_t *);
+#endif
diff --git a/spinlock.s b/spinlock.s
new file mode 100644 (file)
index 0000000..37849b2
--- /dev/null
@@ -0,0 +1,30 @@
+global spinlock_acquire:function
+global spinlock_release:function
+global spinlock_init:function
+
+; spinlock addr in rdi
+; low four bytes is ticket number
+; high four bytes is turn counter
+
+spinlock_init:
+       mov rax, 0
+       mov [rdi], rax
+       ret
+
+spinlock_acquire:
+       mov eax, 1
+       lock xadd [rdi], eax   ; eax = my ticket number
+
+       cmp [rdi+4], eax        ; is it my turn?
+       je .acquired             ; yes
+
+.retry:
+       pause
+       cmp [rdi+4], eax        ; is it my turn?
+       jne .retry                ; keep waiting
+.acquired:
+       ret
+
+spinlock_release:
+       lock inc dword [rdi+4]
+       ret