From d0a431c8603955773054529dff5c643105212046 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sat, 4 Feb 2023 17:46:05 +0000 Subject: [PATCH] kernel: add basic spinlocks --- arch/x86_64/hwlock.S | 103 +++++++++++++++++++++ arch/x86_64/include/socks/machine/hwlock.h | 14 +++ include/socks/compiler.h | 1 + include/socks/locks.h | 11 ++- kernel/spinlock.c | 14 --- 5 files changed, 125 insertions(+), 18 deletions(-) create mode 100644 arch/x86_64/hwlock.S create mode 100644 arch/x86_64/include/socks/machine/hwlock.h delete mode 100644 kernel/spinlock.c diff --git a/arch/x86_64/hwlock.S b/arch/x86_64/hwlock.S new file mode 100644 index 0000000..b659333 --- /dev/null +++ b/arch/x86_64/hwlock.S @@ -0,0 +1,103 @@ +/* x86_64 hardware locks + these are raw spinlocks with support for irq saving and restoring */ + + .global ml_hwlock_lock + .type ml_hwlock_lock, @function + + /* %rdi = pointer to ml_hwlock_t (int) */ +ml_hwlock_lock: + push %rbp + mov %rsp, %rbp + + mov $1, %ecx + + cli + mfence + +1: mov $0, %eax + lock cmpxchg %ecx, (%rdi) + jne 1b + + pop %rbp + ret + + .global ml_hwlock_unlock + .type ml_hwlock_unlock, @function + + /* %rdi = pointer to ml_hwlock_t (int) */ +ml_hwlock_unlock: + push %rbp + mov %rsp, %rbp + + movl $0, (%rdi) + mfence + sti + + pop %rbp + ret + + + .global ml_hwlock_lock_irqsave + .type ml_hwlock_lock_irqsave, @function + + /* %rdi = pointer to ml_hwlock_t (int) + %rsi = pointer to quadword to store rflags in */ +ml_hwlock_lock_irqsave: + push %rbp + mov %rsp, %rbp + + pushfq + popq (%rsi) + + cli + + mov $1, %ecx + + mfence + +1: mov $0, %eax + lock cmpxchg %ecx, (%rdi) + jne 1b + + pop %rbp + ret + + .global ml_hwlock_unlock_irqrestore + .type ml_hwlock_unlock_irqrestore, @function + + /* %rdi = pointer to ml_hwlock_t (int) + %rsi = quadword with saved rflags */ +ml_hwlock_unlock_irqrestore: + push %rbp + mov %rsp, %rbp + + movl $0, (%rdi) + mfence + + pushfq + popq %rax /* rax = the current rflags register */ + /* rsi = the saved rflags register */ + + andq $0x200, %rsi /* we only want to copy IF (bit 9, 0x200) */ + andq $0xFFFFFFFFFFFFFDFF, %rax + orq %rsi, %rax + + pushq %rsi + popfq + + pop %rbp + ret + + + .global get_rflags + .type get_rflags, @function + +get_rflags: + push %rbp + mov %rsp, %rbp + + pushfq + popq %rax + + pop %rbp + ret diff --git a/arch/x86_64/include/socks/machine/hwlock.h b/arch/x86_64/include/socks/machine/hwlock.h new file mode 100644 index 0000000..fa86265 --- /dev/null +++ b/arch/x86_64/include/socks/machine/hwlock.h @@ -0,0 +1,14 @@ +#ifndef SOCKS_X86_64_HWLOCK_H_ +#define SOCKS_X86_64_HWLOCK_H_ + +#define ML_HWLOCK_INIT (0) + +typedef int ml_hwlock_t; + +extern void ml_hwlock_lock(ml_hwlock_t *lck); +extern void ml_hwlock_unlock(ml_hwlock_t *lck); + +extern void ml_hwlock_lock_irqsave(ml_hwlock_t *lck, unsigned long *flags); +extern void ml_hwlock_unlock_irqrestore(ml_hwlock_t *lck, unsigned long flags); + +#endif diff --git a/include/socks/compiler.h b/include/socks/compiler.h index a79d015..61044bb 100644 --- a/include/socks/compiler.h +++ b/include/socks/compiler.h @@ -4,5 +4,6 @@ #define __used __attribute__((used)) #define __packed __attribute__((packed)) #define __section(name) __attribute__((section(name))) +#define __aligned(x) __attribute__((aligned(x))) #endif diff --git a/include/socks/locks.h b/include/socks/locks.h index 9b07aae..1a8f419 100644 --- a/include/socks/locks.h +++ b/include/socks/locks.h @@ -1,11 +1,14 @@ #ifndef SOCKS_LOCKS_H_ #define SOCKS_LOCKS_H_ -typedef int __attribute__((aligned(8))) spin_lock_t; +#include +#include -#define SPIN_LOCK_INIT ((spin_lock_t)0) +typedef __aligned(8) ml_hwlock_t spin_lock_t; -extern void spin_lock_irqsave(spin_lock_t *lck, unsigned long *flags); -extern void spin_unlock_irqrestore(spin_lock_t *lck, unsigned long flags); +#define SPIN_LOCK_INIT ML_HWLOCK_INIT + +#define spin_lock_irqsave(lck, flags) ml_hwlock_lock_irqsave(lck, flags); +#define spin_unlock_irqrestore(lck, flags) ml_hwlock_unlock_irqrestore(lck, flags); #endif diff --git a/kernel/spinlock.c b/kernel/spinlock.c deleted file mode 100644 index 0e247d9..0000000 --- a/kernel/spinlock.c +++ /dev/null @@ -1,14 +0,0 @@ -#include - -void spin_lock_irqsave(spin_lock_t *lck, unsigned long *flags) -{ - while (!__sync_bool_compare_and_swap(lck, 0, 1)) { - /* pause */ - } -} - -void spin_unlock_irqrestore(spin_lock_t *lck, unsigned long flags) -{ - __sync_lock_release(lck); -} -