Kernel: Move Prekernel assembly utils to aarch64/ASM_wrapper.h

By moving these functions to the ASM_wrapper.h file, we can get rid of
another Prekernel file.
This commit is contained in:
Timon Kruiper 2022-05-09 23:09:44 +02:00 committed by Linus Groh
parent e80d8d697c
commit e7c5fd978b
Notes: sideshowbarker 2024-07-17 10:56:17 +09:00
8 changed files with 44 additions and 77 deletions

View File

@ -1,5 +1,8 @@
/* /*
* Copyright (c) 2021, James Mintram <me@jamesrm.com> * Copyright (c) 2021, James Mintram <me@jamesrm.com>
* Copyright (c) 2021, Nico Weber <thakis@chromium.org>
* Copyright (c) 2021, Marcin Undak <mcinek@gmail.com>
* Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
@ -51,4 +54,38 @@ inline ExceptionLevel get_current_exception_level()
return static_cast<ExceptionLevel>(current_exception_level); return static_cast<ExceptionLevel>(current_exception_level);
} }
inline void wait_cycles(int n)
{
// This is probably too fast when caching and branch prediction is turned on.
// FIXME: Make timer-based.
asm("mov x0, %[value]\n"
"0:\n"
" subs x0, x0, #1\n"
" bne 0b" ::[value] "r"(n)
: "x0");
}
inline void el1_vector_table_install(void* vector_table)
{
asm("msr VBAR_EL1, %[value]" ::[value] "r"(vector_table));
}
inline void enter_el2_from_el3()
{
asm volatile(" adr x0, entered_el2\n"
" msr elr_el3, x0\n"
" eret\n"
"entered_el2:" ::
: "x0");
}
inline void enter_el1_from_el2()
{
asm volatile(" adr x0, entered_el1\n"
" msr elr_el2, x0\n"
" eret\n"
"entered_el1:" ::
: "x0");
}
} }

View File

@ -1,48 +0,0 @@
/*
* Copyright (c) 2021, Nico Weber <thakis@chromium.org>
* Copyright (c) 2021, Marcin Undak <mcinek@gmail.com>
* Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
.global wait_cycles
.type wait_cycles, @function
wait_cycles:
Lstart:
// This is probably too fast when caching and branch prediction is turned on.
// FIXME: Make timer-based.
subs x0, x0, #1
bne Lstart
ret
.global enter_el2_from_el3
.type enter_el2_from_el3, @function
enter_el2_from_el3:
adr x0, entered_el2
msr elr_el3, x0
eret
entered_el2:
ret
.global enter_el1_from_el2
.type enter_el1_from_el2, @function
enter_el1_from_el2:
adr x0, entered_el1
msr elr_el2, x0
eret
entered_el1:
ret
//
// Installs the EL1 vector table
// Args:
// x0 - Address of vector table
//
// This function doesn't return a value
//
.global el1_vector_table_install
.type el1_vector_table_install, @function
el1_vector_table_install:
msr VBAR_EL1, x0
ret

View File

@ -1,14 +0,0 @@
/*
* Copyright (c) 2021, Marcin Undak <mcinek@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
extern "C" void wait_cycles(int n);
extern "C" void el1_vector_table_install(void* vector_table);
// CPU initialization functions
extern "C" [[noreturn]] void return_from_el2();
extern "C" [[noreturn]] void return_from_el3();

View File

@ -5,14 +5,10 @@
*/ */
#include <Kernel/Arch/aarch64/ASM_wrapper.h> #include <Kernel/Arch/aarch64/ASM_wrapper.h>
#include <Kernel/Arch/aarch64/Prekernel/Aarch64_asm_utils.h>
#include <Kernel/Arch/aarch64/Prekernel/Prekernel.h> #include <Kernel/Arch/aarch64/Prekernel/Prekernel.h>
#include <Kernel/Arch/aarch64/Registers.h> #include <Kernel/Arch/aarch64/Registers.h>
#include <Kernel/Panic.h> #include <Kernel/Panic.h>
extern "C" void enter_el2_from_el3();
extern "C" void enter_el1_from_el2();
using namespace Kernel; using namespace Kernel;
namespace Prekernel { namespace Prekernel {
@ -43,8 +39,9 @@ static void drop_to_el2()
Aarch64::SPSR_EL3::write(saved_program_status_register_el3); Aarch64::SPSR_EL3::write(saved_program_status_register_el3);
// This will jump into os_start() below // This will jump into os_start() below
enter_el2_from_el3(); Aarch64::Asm::enter_el2_from_el3();
} }
static void drop_to_el1() static void drop_to_el1()
{ {
Aarch64::HCR_EL2 hypervisor_configuration_register_el2 = {}; Aarch64::HCR_EL2 hypervisor_configuration_register_el2 = {};
@ -62,7 +59,7 @@ static void drop_to_el1()
saved_program_status_register_el2.M = Aarch64::SPSR_EL2::Mode::EL1t; saved_program_status_register_el2.M = Aarch64::SPSR_EL2::Mode::EL1t;
Aarch64::SPSR_EL2::write(saved_program_status_register_el2); Aarch64::SPSR_EL2::write(saved_program_status_register_el2);
enter_el1_from_el2(); Aarch64::Asm::enter_el1_from_el2();
} }
static void set_up_el1() static void set_up_el1()

View File

@ -8,7 +8,6 @@
#include <Kernel/Arch/Processor.h> #include <Kernel/Arch/Processor.h>
#include <Kernel/Arch/aarch64/ASM_wrapper.h> #include <Kernel/Arch/aarch64/ASM_wrapper.h>
#include <Kernel/Arch/aarch64/Prekernel/Aarch64_asm_utils.h>
#include <Kernel/Arch/aarch64/Prekernel/Prekernel.h> #include <Kernel/Arch/aarch64/Prekernel/Prekernel.h>
extern "C" uintptr_t vector_table_el1; extern "C" uintptr_t vector_table_el1;
@ -28,7 +27,7 @@ void Processor::initialize(u32 cpu)
Prekernel::drop_to_exception_level_1(); Prekernel::drop_to_exception_level_1();
// Load EL1 vector table // Load EL1 vector table
el1_vector_table_install(&vector_table_el1); Kernel::Aarch64::Asm::el1_vector_table_install(&vector_table_el1);
g_current_processor = this; g_current_processor = this;
} }

View File

@ -4,11 +4,10 @@
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
#include <Kernel/Arch/aarch64/ASM_wrapper.h>
#include <Kernel/Arch/aarch64/RPi/GPIO.h> #include <Kernel/Arch/aarch64/RPi/GPIO.h>
#include <Kernel/Arch/aarch64/RPi/MMIO.h> #include <Kernel/Arch/aarch64/RPi/MMIO.h>
extern "C" void wait_cycles(int n);
namespace Prekernel { namespace Prekernel {
// See BCM2835-ARM-Peripherals.pdf section "6 General Purpose I/O" or bcm2711-peripherals.pdf "Chapter 5. General Purpose I/O". // See BCM2835-ARM-Peripherals.pdf section "6 General Purpose I/O" or bcm2711-peripherals.pdf "Chapter 5. General Purpose I/O".
@ -73,7 +72,7 @@ void GPIO::internal_enable_pins(u32 enable[2], PullUpDownState state)
m_registers->pull_up_down_enable = static_cast<u32>(state); m_registers->pull_up_down_enable = static_cast<u32>(state);
// 2. Wait 150 cycles this provides the required set-up time for the control signal // 2. Wait 150 cycles this provides the required set-up time for the control signal
wait_cycles(150); Kernel::Aarch64::Asm::wait_cycles(150);
// 3. Write to GPPUDCLK0/1 to clock the control signal into the GPIO pads you wish to // 3. Write to GPPUDCLK0/1 to clock the control signal into the GPIO pads you wish to
// modify NOTE only the pads which receive a clock will be modified, all others will // modify NOTE only the pads which receive a clock will be modified, all others will
@ -82,7 +81,7 @@ void GPIO::internal_enable_pins(u32 enable[2], PullUpDownState state)
m_registers->pull_up_down_enable_clock.bits[1] = enable[1]; m_registers->pull_up_down_enable_clock.bits[1] = enable[1];
// 4. Wait 150 cycles this provides the required hold time for the control signal // 4. Wait 150 cycles this provides the required hold time for the control signal
wait_cycles(150); Kernel::Aarch64::Asm::wait_cycles(150);
// 5. Write to GPPUD to remove the control signal // 5. Write to GPPUD to remove the control signal
m_registers->pull_up_down_enable = 0; m_registers->pull_up_down_enable = 0;

View File

@ -23,8 +23,6 @@
static void draw_logo(); static void draw_logo();
static u32 query_firmware_version(); static u32 query_firmware_version();
extern "C" void wait_cycles(int n);
struct TrapFrame { struct TrapFrame {
u64 x[31]; // Saved general purpose registers u64 x[31]; // Saved general purpose registers
u64 spsr_el1; // Save Processor Status Register, EL1 u64 spsr_el1; // Save Processor Status Register, EL1

View File

@ -398,7 +398,6 @@ if (NOT "${SERENITY_ARCH}" STREQUAL "aarch64")
) )
else() else()
set(PREKERNEL_SOURCES set(PREKERNEL_SOURCES
Arch/aarch64/Prekernel/Aarch64_asm_utils.S
Arch/aarch64/Prekernel/boot.S Arch/aarch64/Prekernel/boot.S
Arch/aarch64/Prekernel/PrekernelExceptions.cpp Arch/aarch64/Prekernel/PrekernelExceptions.cpp
Arch/aarch64/Prekernel/PrekernelMMU.cpp Arch/aarch64/Prekernel/PrekernelMMU.cpp