From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pj1-f52.google.com (mail-pj1-f52.google.com [209.85.216.52]) by mx.groups.io with SMTP id smtpd.web08.9710.1665766172693935793 for ; Fri, 14 Oct 2022 09:49:32 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@ventanamicro.com header.s=google header.b=MxZX5mWx; spf=pass (domain: ventanamicro.com, ip: 209.85.216.52, mailfrom: sunilvl@ventanamicro.com) Received: by mail-pj1-f52.google.com with SMTP id x31-20020a17090a38a200b0020d2afec803so5250565pjb.2 for ; Fri, 14 Oct 2022 09:49:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=95ZrmwIJ1cD+02a2zo3QSg/1XJROUEBbHLcSQ3NsDv4=; b=MxZX5mWxLp5hv5KabGXLuDANts9Io5SACyh3dWKPcsa9SMPdnRMWIOvFgMAJYt2Ban DUa/gICgnnwBcHCd5353mU45Llmj3Q409cv42VRHExJbhZ0n8ozoKg9FjbTst7CeUh4i 32dYBdtMin6jW/9UKZK+atfJ6uVuS0Mm5xAZf8HPdyTn9Yn0g+B5eqDk4kJHD86MNluA Gh0cGlTB6XkdQulNBWNGmH/6HgSwtyNhrFbVSUL16M67Ob7H8DE5X/WfIJ3P8kN6nTCt QB6pmPYCbj5o54756Iu8IJZ2V5SV95noyt0BlGrC8PRFJZt6l9m4ctEVaJVIg1HEvtSy GfQA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=95ZrmwIJ1cD+02a2zo3QSg/1XJROUEBbHLcSQ3NsDv4=; b=yZbQ2qLNIaNpBUdHre2gGdK1++ByYkQqVQnq68eq5vI+E6E7yRGF91tZqpsFJF/aMZ GIKmu2FQtlsf3JP+Ki8w9h4E5phPvSnJN46r3TLz3sWTCf6aBoCvJgVclEXPWX4LR27l 14gOsLfHIKzaCLgCNvFo/SP06mATRSaXFCHJh5jnxVET7vcJH0bOKn1hdJbBdTN1GGWF 5dv1BrqnPDt9uIzRtd0KZqZ1boYBq8ppj+LU83YreeVrna7EaSsKKkMkzMEEby8oWvV9 pcbziu2WduIlwT5kbpNyk5Q295VGZ1xPuLzC7wwXtWhqpMEA1fw4xZlAa231O2/ifSzK AEWQ== X-Gm-Message-State: ACrzQf3oJGHiLtswVAHkN2RmCeuSNtPgflJQfhPazzzYHhMU8uWooZTC Re7C//yGYO5MWbl0n0BQrzBiHYA9Z4cTyg== X-Google-Smtp-Source: AMsMyM4QEgDWEx/Qswx2z0iWkzFdhdAnwEG05TkbaZCPwu1A5WGo90fxK86Zvu0k2urFm40a+MXK5Q== X-Received: by 2002:a17:902:eb89:b0:185:33d:cb34 with SMTP id q9-20020a170902eb8900b00185033dcb34mr6257208plg.55.1665766171745; Fri, 14 Oct 2022 09:49:31 -0700 (PDT) Return-Path: Received: from localhost.localdomain ([49.206.13.138]) by smtp.gmail.com with ESMTPSA id f3-20020a62db03000000b0056265011136sm1963368pfg.112.2022.10.14.09.49.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 14 Oct 2022 09:49:31 -0700 (PDT) From: "Sunil V L" To: devel@edk2.groups.io Cc: Eric Dong , Ray Ni , Rahul Kumar , Daniel Schaefer Subject: [edk2-staging/RiscV64QemuVirt PATCH V4 18/34] UefiCpuPkg/CpuDxe: Add support for RISC-V Date: Fri, 14 Oct 2022 22:18:20 +0530 Message-Id: <20221014164836.1513036-19-sunilvl@ventanamicro.com> X-Mailer: git-send-email 2.38.0 In-Reply-To: <20221014164836.1513036-1-sunilvl@ventanamicro.com> References: <20221014164836.1513036-1-sunilvl@ventanamicro.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4076 This is copied from edk2-platforms/Silicon/RISC-V/ProcessorPkg/Universal/CpuDxe Cc: Eric Dong Cc: Ray Ni Cc: Rahul Kumar Cc: Daniel Schaefer Signed-off-by: Sunil V L --- UefiCpuPkg/CpuDxe/CpuDxe.inf | 8 + UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.h | 199 +++++++++++++ UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.c | 307 ++++++++++++++++++++ 3 files changed, 514 insertions(+) diff --git a/UefiCpuPkg/CpuDxe/CpuDxe.inf b/UefiCpuPkg/CpuDxe/CpuDxe.inf index 65961813f74b..235100d86274 100644 --- a/UefiCpuPkg/CpuDxe/CpuDxe.inf +++ b/UefiCpuPkg/CpuDxe/CpuDxe.inf @@ -44,6 +44,9 @@ [LibraryClasses.IA32, LibraryClasses.X64] MtrrLib UefiCpuLib +[LibraryClasses.RISCV64] + RiscVSbiLib + [Sources.IA32, Sources.X64] Ia32X64/CpuDxe.c Ia32X64/CpuDxe.h @@ -62,6 +65,10 @@ [Sources.X64] X64/CpuAsm.nasm X64/PagingAttribute.c +[Sources.RISCV64] + RiscV64/CpuDxe.c + RiscV64/CpuDxe.h + [Protocols] gEfiCpuArchProtocolGuid ## PRODUCES gEfiMpServiceProtocolGuid ## PRODUCES @@ -83,6 +90,7 @@ [Pcd] gUefiCpuPkgTokenSpaceGuid.PcdCpuStackSwitchExceptionList ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuKnownGoodStackSize ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdTdxSharedBitMask ## CONSUMES + gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency ## CONSUMES [Depex] TRUE diff --git a/UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.h b/UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.h new file mode 100644 index 000000000000..49f4e119665a --- /dev/null +++ b/UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.h @@ -0,0 +1,199 @@ +/** @file + RISC-V CPU DXE module header file. + + Copyright (c) 2016 - 2022, Hewlett Packard Enterprise Development LP. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef CPU_DXE_H_ +#define CPU_DXE_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Flush CPU data cache. If the instruction cache is fully coherent + with all DMA operations then function can just return EFI_SUCCESS. + + @param This Protocol instance structure + @param Start Physical address to start flushing from. + @param Length Number of bytes to flush. Round up to chipset + granularity. + @param FlushType Specifies the type of flush operation to perform. + + @retval EFI_SUCCESS If cache was flushed + @retval EFI_UNSUPPORTED If flush type is not supported. + @retval EFI_DEVICE_ERROR If requested range could not be flushed. + +**/ +EFI_STATUS +EFIAPI +CpuFlushCpuDataCache ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length, + IN EFI_CPU_FLUSH_TYPE FlushType + ); + +/** + Enables CPU interrupts. + + @param This Protocol instance structure + + @retval EFI_SUCCESS If interrupts were enabled in the CPU + @retval EFI_DEVICE_ERROR If interrupts could not be enabled on the CPU. + +**/ +EFI_STATUS +EFIAPI +CpuEnableInterrupt ( + IN EFI_CPU_ARCH_PROTOCOL *This + ); + +/** + Disables CPU interrupts. + + @param This Protocol instance structure + + @retval EFI_SUCCESS If interrupts were disabled in the CPU. + @retval EFI_DEVICE_ERROR If interrupts could not be disabled on the CPU. + +**/ +EFI_STATUS +EFIAPI +CpuDisableInterrupt ( + IN EFI_CPU_ARCH_PROTOCOL *This + ); + +/** + Return the state of interrupts. + + @param This Protocol instance structure + @param State Pointer to the CPU's current interrupt state + + @retval EFI_SUCCESS If interrupts were disabled in the CPU. + @retval EFI_INVALID_PARAMETER State is NULL. + +**/ +EFI_STATUS +EFIAPI +CpuGetInterruptState ( + IN EFI_CPU_ARCH_PROTOCOL *This, + OUT BOOLEAN *State + ); + +/** + Generates an INIT to the CPU. + + @param This Protocol instance structure + @param InitType Type of CPU INIT to perform + + @retval EFI_SUCCESS If CPU INIT occurred. This value should never be + seen. + @retval EFI_DEVICE_ERROR If CPU INIT failed. + @retval EFI_UNSUPPORTED Requested type of CPU INIT not supported. + +**/ +EFI_STATUS +EFIAPI +CpuInit ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_CPU_INIT_TYPE InitType + ); + +/** + Registers a function to be called from the CPU interrupt handler. + + @param This Protocol instance structure + @param InterruptType Defines which interrupt to hook. IA-32 + valid range is 0x00 through 0xFF + @param InterruptHandler A pointer to a function of type + EFI_CPU_INTERRUPT_HANDLER that is called + when a processor interrupt occurs. A null + pointer is an error condition. + + @retval EFI_SUCCESS If handler installed or uninstalled. + @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler + for InterruptType was previously installed. + @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for + InterruptType was not previously installed. + @retval EFI_UNSUPPORTED The interrupt specified by InterruptType + is not supported. + +**/ +EFI_STATUS +EFIAPI +CpuRegisterInterruptHandler ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ); + +/** + Returns a timer value from one of the CPU's internal timers. There is no + inherent time interval between ticks but is a function of the CPU frequency. + + @param This - Protocol instance structure. + @param TimerIndex - Specifies which CPU timer is requested. + @param TimerValue - Pointer to the returned timer value. + @param TimerPeriod - A pointer to the amount of time that passes + in femtoseconds (10-15) for each increment + of TimerValue. If TimerValue does not + increment at a predictable rate, then 0 is + returned. The amount of time that has + passed between two calls to GetTimerValue() + can be calculated with the formula + (TimerValue2 - TimerValue1) * TimerPeriod. + This parameter is optional and may be NULL. + + @retval EFI_SUCCESS - If the CPU timer count was returned. + @retval EFI_UNSUPPORTED - If the CPU does not have any readable timers. + @retval EFI_DEVICE_ERROR - If an error occurred while reading the timer. + @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is NULL. + +**/ +EFI_STATUS +EFIAPI +CpuGetTimerValue ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN UINT32 TimerIndex, + OUT UINT64 *TimerValue, + OUT UINT64 *TimerPeriod OPTIONAL + ); + +/** + Set memory cacheability attributes for given range of memeory. + + @param This Protocol instance structure + @param BaseAddress Specifies the start address of the + memory range + @param Length Specifies the length of the memory range + @param Attributes The memory cacheability for the memory range + + @retval EFI_SUCCESS If the cacheability of that memory range is + set successfully + @retval EFI_UNSUPPORTED If the desired operation cannot be done + @retval EFI_INVALID_PARAMETER The input parameter is not correct, + such as Length = 0 + +**/ +EFI_STATUS +EFIAPI +CpuSetMemoryAttributes ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ); + +#endif diff --git a/UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.c b/UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.c new file mode 100644 index 000000000000..9f557b776a09 --- /dev/null +++ b/UefiCpuPkg/CpuDxe/RiscV64/CpuDxe.c @@ -0,0 +1,307 @@ +/** @file + RISC-V CPU DXE driver. + + Copyright (c) 2016 - 2022, Hewlett Packard Enterprise Development LP. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "CpuDxe.h" + +// +// Global Variables +// +STATIC BOOLEAN mInterruptState = FALSE; +STATIC EFI_HANDLE mCpuHandle = NULL; + +EFI_CPU_ARCH_PROTOCOL gCpu = { + CpuFlushCpuDataCache, + CpuEnableInterrupt, + CpuDisableInterrupt, + CpuGetInterruptState, + CpuInit, + CpuRegisterInterruptHandler, + CpuGetTimerValue, + CpuSetMemoryAttributes, + 1, // NumberOfTimers + 4 // DmaBufferAlignment +}; + +// +// CPU Arch Protocol Functions +// + +/** + Flush CPU data cache. If the instruction cache is fully coherent + with all DMA operations then function can just return EFI_SUCCESS. + + @param This Protocol instance structure + @param Start Physical address to start flushing from. + @param Length Number of bytes to flush. Round up to chipset + granularity. + @param FlushType Specifies the type of flush operation to perform. + + @retval EFI_SUCCESS If cache was flushed + @retval EFI_UNSUPPORTED If flush type is not supported. + @retval EFI_DEVICE_ERROR If requested range could not be flushed. + +**/ +EFI_STATUS +EFIAPI +CpuFlushCpuDataCache ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length, + IN EFI_CPU_FLUSH_TYPE FlushType + ) +{ + return EFI_SUCCESS; +} + +/** + Enables CPU interrupts. + + @param This Protocol instance structure + + @retval EFI_SUCCESS If interrupts were enabled in the CPU + @retval EFI_DEVICE_ERROR If interrupts could not be enabled on the CPU. + +**/ +EFI_STATUS +EFIAPI +CpuEnableInterrupt ( + IN EFI_CPU_ARCH_PROTOCOL *This + ) +{ + EnableInterrupts (); + mInterruptState = TRUE; + return EFI_SUCCESS; +} + +/** + Disables CPU interrupts. + + @param This Protocol instance structure + + @retval EFI_SUCCESS If interrupts were disabled in the CPU. + @retval EFI_DEVICE_ERROR If interrupts could not be disabled on the CPU. + +**/ +EFI_STATUS +EFIAPI +CpuDisableInterrupt ( + IN EFI_CPU_ARCH_PROTOCOL *This + ) +{ + DisableInterrupts (); + mInterruptState = FALSE; + return EFI_SUCCESS; +} + +/** + Return the state of interrupts. + + @param This Protocol instance structure + @param State Pointer to the CPU's current interrupt state + + @retval EFI_SUCCESS If interrupts were disabled in the CPU. + @retval EFI_INVALID_PARAMETER State is NULL. + +**/ +EFI_STATUS +EFIAPI +CpuGetInterruptState ( + IN EFI_CPU_ARCH_PROTOCOL *This, + OUT BOOLEAN *State + ) +{ + if (State == NULL) { + return EFI_INVALID_PARAMETER; + } + + *State = mInterruptState; + return EFI_SUCCESS; +} + +/** + Generates an INIT to the CPU. + + @param This Protocol instance structure + @param InitType Type of CPU INIT to perform + + @retval EFI_SUCCESS If CPU INIT occurred. This value should never be + seen. + @retval EFI_DEVICE_ERROR If CPU INIT failed. + @retval EFI_UNSUPPORTED Requested type of CPU INIT not supported. + +**/ +EFI_STATUS +EFIAPI +CpuInit ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_CPU_INIT_TYPE InitType + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Registers a function to be called from the CPU interrupt handler. + + @param This Protocol instance structure + @param InterruptType Defines which interrupt to hook. IA-32 + valid range is 0x00 through 0xFF + @param InterruptHandler A pointer to a function of type + EFI_CPU_INTERRUPT_HANDLER that is called + when a processor interrupt occurs. A null + pointer is an error condition. + + @retval EFI_SUCCESS If handler installed or uninstalled. + @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler + for InterruptType was previously installed. + @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for + InterruptType was not previously installed. + @retval EFI_UNSUPPORTED The interrupt specified by InterruptType + is not supported. + +**/ +EFI_STATUS +EFIAPI +CpuRegisterInterruptHandler ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ) +{ + return RegisterCpuInterruptHandler (InterruptType, InterruptHandler); +} + +/** + Returns a timer value from one of the CPU's internal timers. There is no + inherent time interval between ticks but is a function of the CPU frequency. + + @param This - Protocol instance structure. + @param TimerIndex - Specifies which CPU timer is requested. + @param TimerValue - Pointer to the returned timer value. + @param TimerPeriod - A pointer to the amount of time that passes + in femtoseconds (10-15) for each increment + of TimerValue. If TimerValue does not + increment at a predictable rate, then 0 is + returned. The amount of time that has + passed between two calls to GetTimerValue() + can be calculated with the formula + (TimerValue2 - TimerValue1) * TimerPeriod. + This parameter is optional and may be NULL. + + @retval EFI_SUCCESS - If the CPU timer count was returned. + @retval EFI_UNSUPPORTED - If the CPU does not have any readable timers. + @retval EFI_DEVICE_ERROR - If an error occurred while reading the timer. + @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is NULL. + +**/ +EFI_STATUS +EFIAPI +CpuGetTimerValue ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN UINT32 TimerIndex, + OUT UINT64 *TimerValue, + OUT UINT64 *TimerPeriod OPTIONAL + ) +{ + if (TimerValue == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (TimerIndex != 0) { + return EFI_INVALID_PARAMETER; + } + + *TimerValue = (UINT64)RiscVReadTimer (); + if (TimerPeriod != NULL) { + *TimerPeriod = DivU64x32 ( + 1000000000000000u, + PcdGet64 (PcdCpuCoreCrystalClockFrequency) + ); + } + + return EFI_SUCCESS; +} + +/** + Implementation of SetMemoryAttributes() service of CPU Architecture Protocol. + + This function modifies the attributes for the memory region specified by BaseAddress and + Length from their current attributes to the attributes specified by Attributes. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param BaseAddress The physical address that is the start address of a memory region. + @param Length The size in bytes of the memory region. + @param Attributes The bit mask of attributes to set for the memory region. + + @retval EFI_SUCCESS The attributes were set for the memory region. + @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by + BaseAddress and Length cannot be modified. + @retval EFI_INVALID_PARAMETER Length is zero. + Attributes specified an illegal combination of attributes that + cannot be set together. + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of + the memory resource range. + @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory + resource range specified by BaseAddress and Length. + The bit mask of attributes is not support for the memory resource + range specified by BaseAddress and Length. + +**/ +EFI_STATUS +EFIAPI +CpuSetMemoryAttributes ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ) +{ + DEBUG ((DEBUG_INFO, "%a: Set memory attributes not supported yet\n", __FUNCTION__)); + return EFI_SUCCESS; +} + +/** + Initialize the state information for the CPU Architectural Protocol. + + @param ImageHandle Image handle this driver. + @param SystemTable Pointer to the System Table. + + @retval EFI_SUCCESS Thread can be successfully created + @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure + @retval EFI_DEVICE_ERROR Cannot create the thread + +**/ +EFI_STATUS +EFIAPI +InitializeCpu ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + InitializeCpuExceptionHandlers(NULL); + + // + // Make sure interrupts are disabled + // + DisableInterrupts (); + + // + // Install CPU Architectural Protocol + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mCpuHandle, + &gEfiCpuArchProtocolGuid, + &gCpu, + NULL + ); + ASSERT_EFI_ERROR (Status); + return Status; +} -- 2.38.0