From f0b6eb6932e21010ae83bfcddd2d58880c4bbd19 Mon Sep 17 00:00:00 2001 From: Pankaj Raghav Date: Fri, 5 May 2023 14:37:26 +0200 Subject: [PATCH] Kernel: Implement helpers to manipulate MSI(x) data structures MSIx table entry is used to program interrupt vectors and it is architecture specific. Add helper functions declaration in Arch/PCIMSI.h. The definition of the function is placed in the respective arch specific code. --- Kernel/Arch/PCIMSI.h | 42 ++++++++++++++++++++++++++++ Kernel/Arch/x86_64/PCI/MSI.cpp | 50 ++++++++++++++++++++++++++++++++++ Kernel/Arch/x86_64/PCI/MSI.h | 22 +++++++++++++++ Kernel/CMakeLists.txt | 1 + 4 files changed, 115 insertions(+) create mode 100644 Kernel/Arch/PCIMSI.h create mode 100644 Kernel/Arch/x86_64/PCI/MSI.cpp create mode 100644 Kernel/Arch/x86_64/PCI/MSI.h diff --git a/Kernel/Arch/PCIMSI.h b/Kernel/Arch/PCIMSI.h new file mode 100644 index 0000000000..fa5b3f4988 --- /dev/null +++ b/Kernel/Arch/PCIMSI.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023, Pankaj R + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Kernel { +#if ARCH(X86_64) +u64 msi_address_register(u8 destination_id, bool redirection_hint, bool destination_mode); +u32 msi_data_register(u8 vector, bool level_trigger, bool assert); +u32 msix_vector_control_register(u32 vector_control, bool mask); +void msi_signal_eoi(); +#elif ARCH(AARCH64) +[[maybe_unused]] static u64 msi_address_register([[maybe_unused]] u8 destination_id, [[maybe_unused]] bool redirection_hint, [[maybe_unused]] bool destination_mode) +{ + TODO_AARCH64(); + return 0; +} + +[[maybe_unused]] static u32 msi_data_register([[maybe_unused]] u8 vector, [[maybe_unused]] bool level_trigger, [[maybe_unused]] bool assert) +{ + TODO_AARCH64(); + return 0; +} + +[[maybe_unused]] static u32 msix_vector_control_register([[maybe_unused]] u32 vector_control, [[maybe_unused]] bool mask) +{ + TODO_AARCH64(); + return 0; +} + +[[maybe_unused]] static void msi_signal_eoi() +{ + TODO_AARCH64(); + return; +} +#endif +} diff --git a/Kernel/Arch/x86_64/PCI/MSI.cpp b/Kernel/Arch/x86_64/PCI/MSI.cpp new file mode 100644 index 0000000000..874f9aae94 --- /dev/null +++ b/Kernel/Arch/x86_64/PCI/MSI.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023, Pankaj R + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include + +namespace Kernel { +u64 msi_address_register(u8 destination_id, bool redirection_hint, bool destination_mode) +{ + u64 flags = 0; + if (redirection_hint) { + flags |= msi_redirection_hint; + if (destination_mode) + flags |= msi_destination_mode_logical; + } + return (msi_address_base | (destination_id << msi_destination_shift) | flags); +} + +u32 msi_data_register(u8 vector, bool level_trigger, bool assert) +{ + u32 flags = 0; + + if (level_trigger) { + flags |= msi_trigger_mode_level; + if (assert) + flags |= msi_level_assert; + } + return ((vector + IRQ_VECTOR_BASE) & msi_data_vector_mask) | flags; +} + +u32 msix_vector_control_register(u32 vector_control, bool mask) +{ + if (!mask) + return (vector_control & msi_vector_control_unmask); + return (vector_control | msi_vector_control_mask); +} + +void msi_signal_eoi() +{ + InterruptDisabler disabler; + APIC::the().eoi(); +} + +} diff --git a/Kernel/Arch/x86_64/PCI/MSI.h b/Kernel/Arch/x86_64/PCI/MSI.h new file mode 100644 index 0000000000..efe38c2888 --- /dev/null +++ b/Kernel/Arch/x86_64/PCI/MSI.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023, Pankaj R + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +// Address register +static constexpr u32 msi_address_base = 0xfee00000; +static constexpr u8 msi_destination_shift = 12; +static constexpr u32 msi_redirection_hint = 0x00000008; +static constexpr u32 msi_destination_mode_logical = 0x00000004; + +// Data register +static constexpr u8 msi_data_vector_mask = 0xff; +static constexpr u32 msi_trigger_mode_level = 0x00008000; +static constexpr u32 msi_level_assert = 0x00004000; + +// Vector control +static constexpr u32 msi_vector_control_mask = 0x1; +static constexpr u32 msi_vector_control_unmask = ~(0x1); diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index 54d7ae41ef..067fe7f63f 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -393,6 +393,7 @@ if ("${SERENITY_ARCH}" STREQUAL "x86_64") Arch/x86_64/PCI/Controller/HostBridge.cpp Arch/x86_64/PCI/IDELegacyModeController.cpp Arch/x86_64/PCI/Initializer.cpp + Arch/x86_64/PCI/MSI.cpp Arch/x86_64/VGA/IOArbiter.cpp