--- /dev/null
+#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
--- /dev/null
+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
--- /dev/null
+#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
--- /dev/null
+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