diff options
author | Hendiadyoin1 <leon2002.la@gmail.com> | 2021-07-01 14:51:41 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-07-01 17:32:34 +0200 |
commit | 5f6c51361045f26812eba26d8531a8e079d63807 (patch) | |
tree | 8188e83c709fda56f21b3348d558ffc52e273d29 /Kernel/Arch/x86 | |
parent | 6b9cf8376e17d46207637b16decc499ca75b83de (diff) | |
download | serenity-5f6c51361045f26812eba26d8531a8e079d63807.zip |
Kernel: Add support for 64-bit unaligned Mem-ops
Also let the compiler enforce the size and type restrictions
Diffstat (limited to 'Kernel/Arch/x86')
-rw-r--r-- | Kernel/Arch/x86/CPU.h | 45 |
1 files changed, 29 insertions, 16 deletions
diff --git a/Kernel/Arch/x86/CPU.h b/Kernel/Arch/x86/CPU.h index 298ed8d12a..6753fc89b1 100644 --- a/Kernel/Arch/x86/CPU.h +++ b/Kernel/Arch/x86/CPU.h @@ -7,6 +7,7 @@ #pragma once #include <AK/Atomic.h> +#include <AK/Concepts.h> #include <AK/Vector.h> #include <Kernel/Arch/x86/DescriptorTable.h> @@ -29,45 +30,57 @@ inline u32 get_iopl_from_eflags(u32 eflags) return (eflags & iopl_mask) >> 12; } -template<typename T> -void read_possibly_unaligned_data(u8* where, T& data) +template<Integral T> +void read_possibly_unaligned_data(u8* where, T& data) requires(sizeof(T) == 8 || sizeof(T) == 4 || sizeof(T) == 2) { - // FIXME: Implement 64 bit unaligned data access - VERIFY(sizeof(T) == 8 || sizeof(T) == 4 || sizeof(T) == 2); - if (((FlatPtr)where % sizeof(T)) == 0) { + if (((FlatPtr)where % alignof(T)) == 0) { data = *(T*)where; return; } - if (sizeof(T) == 2) { - data = *(u8*)where | ((u16)(*(where + 1)) << 8); + if constexpr (sizeof(T) == 2) { + data = *where | ((u16)(*(where + 1)) << 8); return; } - if (sizeof(T) == 4) { - data = *(u8*)where | (((u32) * (where + 1)) << 8) | (((u32) * (where + 2)) << 16) | (((u32) * (u8*)(where + 3)) << 24); + if constexpr (sizeof(T) == 4) { + data = *where | (((u32) * (where + 1)) << 8) | (((u32) * (where + 2)) << 16) | (((u32) * (where + 3)) << 24); + return; + } + if constexpr (sizeof(T) == 8) { + data = *where | (((u32) * (where + 1)) << 8) | (((u64) * (where + 2)) << 16) | (((u64) * (where + 3)) << 24) + | (((u64) * (where + 4)) << 32) | (((u64) * (where + 5)) << 40) | (((u64) * (where + 6)) << 48) | (((u64) * (where + 7)) << 56); return; } VERIFY_NOT_REACHED(); } -template<typename T> -void write_possibly_unaligned_data(u8* where, T data) +template<Integral T> +void write_possibly_unaligned_data(u8* where, T data) requires(sizeof(T) == 8 || sizeof(T) == 4 || sizeof(T) == 2) { - // FIXME: Implement 64 bit unaligned data access - VERIFY(sizeof(T) == 8 || sizeof(T) == 4 || sizeof(T) == 2); - if (((FlatPtr)where % sizeof(T)) == 0) { + if (((FlatPtr)where % alignof(T)) == 0) { *(T*)where = data; return; } - if (sizeof(T) == 2) { + if constexpr (sizeof(T) == 2) { + where[0] = (u8)(data & 0xFF); + where[1] = (u8)((data >> 8) & 0xFF); + return; + } + if constexpr (sizeof(T) == 4) { where[0] = (u8)(data & 0xFF); where[1] = (u8)((data >> 8) & 0xFF); + where[2] = (u8)((data >> 16) & 0xFF); + where[3] = (u8)((data >> 24) & 0xFF); return; } - if (sizeof(T) == 4) { + if constexpr (sizeof(T) == 8) { where[0] = (u8)(data & 0xFF); where[1] = (u8)((data >> 8) & 0xFF); where[2] = (u8)((data >> 16) & 0xFF); where[3] = (u8)((data >> 24) & 0xFF); + where[5] = (u8)(data >> 32 & 0xFF); + where[5] = (u8)((data >> 40) & 0xFF); + where[6] = (u8)((data >> 48) & 0xFF); + where[7] = (u8)((data >> 52) & 0xFF); return; } VERIFY_NOT_REACHED(); |