From 5a6d8336c11140500330da69cd74490a07876fe1 Mon Sep 17 00:00:00 2001 From: Nathan Wagner Date: Mon, 24 Oct 2016 20:28:42 -0500 Subject: [PATCH] amd64 processor low level functions --- cpu.h | 17 +++++++++++++ cpu.s | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ spinlock.h | 11 +++++++++ spinlock.s | 30 +++++++++++++++++++++++ 4 files changed, 128 insertions(+) create mode 100644 cpu.h create mode 100644 cpu.s create mode 100644 spinlock.h create mode 100644 spinlock.s diff --git a/cpu.h b/cpu.h new file mode 100644 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 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 index 0000000..7a70a0d --- /dev/null +++ b/spinlock.h @@ -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 index 0000000..37849b2 --- /dev/null +++ b/spinlock.s @@ -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 -- 2.40.0