diff -Nru opensbi-1.1/debian/changelog opensbi-1.3/debian/changelog --- opensbi-1.1/debian/changelog 2022-11-25 06:45:21.000000000 +0100 +++ opensbi-1.3/debian/changelog 2023-07-12 14:43:34.000000000 +0200 @@ -1,3 +1,9 @@ +opensbi (1.3-1ubuntu0.23.04.1) lunar; urgency=medium + + * New upstream release (LP: #2026588) + + -- Heinrich Schuchardt Wed, 12 Jul 2023 14:43:34 +0200 + opensbi (1.1-2) unstable; urgency=medium [ Lintian Brush ] diff -Nru opensbi-1.1/debian/control opensbi-1.3/debian/control --- opensbi-1.1/debian/control 2022-07-01 00:46:23.000000000 +0200 +++ opensbi-1.3/debian/control 2023-07-12 14:43:34.000000000 +0200 @@ -1,15 +1,17 @@ Source: opensbi Section: misc Priority: optional -Maintainer: Vagrant Cascadian +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Vagrant Cascadian Uploaders: Karsten Merker Build-Depends: debhelper-compat (=13), gcc-riscv64-linux-gnu, -Standards-Version: 4.6.1 + python3, +Standards-Version: 4.6.2 Rules-Requires-Root: no Vcs-Browser: https://salsa.debian.org/opensbi-team/opensbi Vcs-Git: https://salsa.debian.org/opensbi-team/opensbi.git -Homepage: https://github.com/riscv/opensbi +Homepage: https://github.com/riscv-software-src/opensbi Package: opensbi Architecture: all diff -Nru opensbi-1.1/debian/copyright opensbi-1.3/debian/copyright --- opensbi-1.1/debian/copyright 2022-07-01 00:46:23.000000000 +0200 +++ opensbi-1.3/debian/copyright 2023-07-01 02:32:56.000000000 +0200 @@ -1,6 +1,6 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: opensbi -Source: https://github.com/riscv/opensbi +Source: https://github.com/riscv-software-src/opensbi Files: * Copyright: 2019-2020 Western Digital Corporation or its affiliates and @@ -13,6 +13,10 @@ 2021 SiFive 2021-2022 Samuel Holland 2022 Ventana Micro Systems Inc. + 2022 Andes Technology Corporation + 2022 StarFive Technology Co., Ltd. + 2022 Renesas Electronics Corporation + 2023 RISC-V International License: BSD-2-clause Files: include/sbi_utils/sys/htif.h @@ -24,14 +28,14 @@ Copyright: 2019-2022 Vagrant Cascadian License: BSD-2-clause +Files: platform/generic/renesas/rzfive/rzfive.c +Copyright: 2022 Renesas Electronics Corp. +License: GPL-2 + Files: platform/fpga/ariane/* Copyright: 2019 FORTH-ICS/CARV License: BSD-2-clause -Files: platform/andes/* -Copyright: 2019 Andes Technology Corporation -License: BSD-2-clause - Files: lib/utils/libfdt/* Copyright: 2006-2012 David Gibson, IBM Corporation. 2012 Kim Phillips, Freescale Semiconductor. @@ -72,6 +76,10 @@ 2021 Western Digital Corporation or its affiliates. License: BSD-2-clause +Files: scripts/Kconfiglib/* +Copyright: 2011-2019, Ulf Magnusson +License: ISC + License: BSD-2-clause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -140,4 +148,30 @@ . On Debian systems, the complete text of the GNU General Public License Version 2.0 can be found in - `/usr/share/common-licenses/GPL-2.0'. + `/usr/share/common-licenses/GPL-2'. + +License: GPL-2 + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; version 2 of the + License. + . + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA + . + On Debian systems, the complete text of the GNU General Public + License Version 2.0 can be found in + `/usr/share/common-licenses/GPL-2'. + +License: ISC + Permission to use, copy, modify, and/or distribute this software for + any purpose with or without fee is hereby granted, provided that the + above copyright notice and this permission notice appear in all + copies. diff -Nru opensbi-1.1/debian/patches/lib-sbi_illegal_insn-Fix-FENCE.TSO-emulation-infinit.patch opensbi-1.3/debian/patches/lib-sbi_illegal_insn-Fix-FENCE.TSO-emulation-infinit.patch --- opensbi-1.1/debian/patches/lib-sbi_illegal_insn-Fix-FENCE.TSO-emulation-infinit.patch 2022-11-15 02:23:00.000000000 +0100 +++ opensbi-1.3/debian/patches/lib-sbi_illegal_insn-Fix-FENCE.TSO-emulation-infinit.patch 1970-01-01 01:00:00.000000000 +0100 @@ -1,36 +0,0 @@ -From 111afc12306e4368fa112f97d31ea802c4561294 Mon Sep 17 00:00:00 2001 -From: Rahul Pathak -Date: Fri, 12 Aug 2022 19:24:42 +0530 -Subject: [PATCH] lib: sbi_illegal_insn: Fix FENCE.TSO emulation infinite trap - loop - -In case of missing "FENCE.TSO" instruction implementation, -opensbi can emulate the "FENCE.TSO" with "FENCE RW,RW", but -mepc was not incremented to continue from the next instruction -causing infinite trap. - -Fixes: cb8271c8 ("lib: sbi_illegal_insn: Add emulation for fence.tso") -Signed-off-by: Rahul Pathak -Reviewed-by: Andrew Jones -Reviewed-by: Xiang W -Reviewed-by: Samuel Holland -Origin: https://github.com/riscv-software-src/opensbi/commit/111afc12306e4368fa112f97d31ea802c4561294 ---- - lib/sbi/sbi_illegal_insn.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/lib/sbi/sbi_illegal_insn.c b/lib/sbi/sbi_illegal_insn.c -index ecd3508..9691bce 100644 ---- a/lib/sbi/sbi_illegal_insn.c -+++ b/lib/sbi/sbi_illegal_insn.c -@@ -40,6 +40,7 @@ static int misc_mem_opcode_insn(ulong insn, struct sbi_trap_regs *regs) - /* Errata workaround: emulate `fence.tso` as `fence rw, rw`. */ - if ((insn & INSN_MASK_FENCE_TSO) == INSN_MATCH_FENCE_TSO) { - smp_mb(); -+ regs->mepc += 4; - return 0; - } - --- -2.37.2 - diff -Nru opensbi-1.1/debian/patches/series opensbi-1.3/debian/patches/series --- opensbi-1.1/debian/patches/series 2022-11-15 02:23:00.000000000 +0100 +++ opensbi-1.3/debian/patches/series 1970-01-01 01:00:00.000000000 +0100 @@ -1 +0,0 @@ -lib-sbi_illegal_insn-Fix-FENCE.TSO-emulation-infinit.patch diff -Nru opensbi-1.1/debian/upstream/metadata opensbi-1.3/debian/upstream/metadata --- opensbi-1.1/debian/upstream/metadata 2022-08-08 21:49:41.000000000 +0200 +++ opensbi-1.3/debian/upstream/metadata 2023-07-01 02:32:56.000000000 +0200 @@ -1,5 +1,5 @@ --- -Bug-Database: https://github.com/riscv/opensbi/issues -Bug-Submit: https://github.com/riscv/opensbi/issues/new -Repository: https://github.com/riscv/opensbi.git -Repository-Browse: https://github.com/riscv/opensbi +Bug-Database: https://github.com/riscv-software-src/opensbi/issues +Bug-Submit: https://github.com/riscv-software-src/opensbi/issues/new +Repository: https://github.com/riscv-software-src/opensbi.git +Repository-Browse: https://github.com/riscv-software-src/opensbi diff -Nru opensbi-1.1/debian/watch opensbi-1.3/debian/watch --- opensbi-1.1/debian/watch 2022-07-01 00:46:23.000000000 +0200 +++ opensbi-1.3/debian/watch 2023-07-01 02:32:56.000000000 +0200 @@ -1,3 +1,3 @@ version=4 opts=filenamemangle=s/\/(.*)v/@PACKAGE@-/ \ - https://github.com/riscv/@PACKAGE@/releases .*/v@ANY_VERSION@.tar.gz + https://github.com/riscv-software-src/@PACKAGE@/tags .*/v@ANY_VERSION@.tar.gz diff -Nru opensbi-1.1/docs/contributing.md opensbi-1.3/docs/contributing.md --- opensbi-1.1/docs/contributing.md 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/docs/contributing.md 2023-06-23 07:31:49.000000000 +0200 @@ -29,7 +29,7 @@ 5. Maintainers should use "Rebase and Merge" when using GitHub to merge pull requests to avoid creating unnecessary merge commits. 6. Maintainers should avoid creating branches directly in the main -riscv/opensbi repository. Instead prefer using a fork of the riscv/opensbi main +riscv/opensbi repository. Instead, prefer using a fork of the riscv/opensbi main repository and branches within that fork to create pull requests. 7. A maintainer cannot merge his own pull requests in the riscv/opensbi main repository. diff -Nru opensbi-1.1/docs/domain_support.md opensbi-1.3/docs/domain_support.md --- opensbi-1.1/docs/domain_support.md 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/docs/domain_support.md 2023-06-23 07:31:49.000000000 +0200 @@ -2,7 +2,7 @@ ====================== An OpenSBI domain is a system-level partition (subset) of underlying hardware -having it's own memory regions (RAM and MMIO devices) and HARTs. The OpenSBI +having its own memory regions (RAM and MMIO devices) and HARTs. The OpenSBI will try to achieve secure isolation between domains using RISC-V platform features such as PMP, ePMP, IOPMP, SiFive Shield, etc. @@ -15,7 +15,7 @@ Each HART of a RISC-V platform must have an OpenSBI domain assigned to it. The OpenSBI platform support is responsible for populating domains and providing HART id to domain mapping. The OpenSBI domain support will by -default assign **the ROOT domain** to all HARTs of a RISC-V platform so +default assign **the ROOT domain** to all HARTs of a RISC-V platform, so it is not mandatory for the OpenSBI platform support to populate domains. Domain Memory Region @@ -29,7 +29,7 @@ * **base** - The base address of a memory region is **2 ^ order** aligned start address * **flags** - The flags of a memory region represent memory type (i.e. - RAM or MMIO) and allowed accesses (i.e. READ, WRITE, EXECUTE, etc) + RAM or MMIO) and allowed accesses (i.e. READ, WRITE, EXECUTE, etc.) Domain Instance --------------- @@ -52,6 +52,7 @@ * **next_mode** - Privilege mode of the next booting stage for this domain. This can be either S-mode or U-mode. * **system_reset_allowed** - Is domain allowed to reset the system? +* **system_suspend_allowed** - Is domain allowed to suspend the system? The memory regions represented by **regions** in **struct sbi_domain** have following additional constraints to align with RISC-V PMP requirements: @@ -91,6 +92,7 @@ * **next_mode** - Next booting stage mode in coldboot HART scratch space is the next mode for the ROOT domain * **system_reset_allowed** - The ROOT domain is allowed to reset the system +* **system_suspend_allowed** - The ROOT domain is allowed to suspend the system Domain Effects -------------- @@ -124,6 +126,9 @@ * **compatible** (Mandatory) - The compatible string of the domain configuration. This DT property should have value *"opensbi,domain,config"* +* **system-suspend-test** (Optional) - When present, enable a system + suspend test implementation which simply waits five seconds and issues a WFI. + ### Domain Memory Region Node The domain memory region DT node describes details of a memory region and @@ -160,8 +165,16 @@ * **regions** (Optional) - The list of domain memory region DT node phandle and access permissions for the domain instance. Each list entry is a pair of DT node phandle and access permissions. The access permissions are - represented as a 32bit bitmask having bits: **readable** (BIT[0]), - **writeable** (BIT[1]), **executable** (BIT[2]), and **m-mode** (BIT[3]). + represented as a 32bit bitmask having bits: **M readable** (BIT[0]), + **M writeable** (BIT[1]), **M executable** (BIT[2]), **SU readable** + (BIT[3]), **SU writable** (BIT[4]), and **SU executable** (BIT[5]). + The enforce permission bit (BIT[6]), if set, will lock the permissions + in the PMP. This will enforce the permissions on M-mode as well which + otherwise will have unrestricted access. This bit must be used with + caution because no changes can be made to a PMP entry once its locked + until the hart is reset. + Any region of a domain defined in DT node cannot have only M-bits set + in access permissions i.e. it cannot be an m-mode only accessible region. * **boot-hart** (Optional) - The DT node phandle of the HART booting the domain instance. If coldboot HART is assigned to the domain instance then this DT property is ignored and the coldboot HART is assumed to be the @@ -180,13 +193,15 @@ is used as default value. * **next-mode** (Optional) - The 32 bit next booting stage mode for the domain instance. The possible values of this DT property are: **0x1** - (s-mode), and **0x0** (u-mode). If this DT property is not available + (S-mode), and **0x0** (U-mode). If this DT property is not available and coldboot HART is not assigned to the domain instance then **0x1** is used as default value. If this DT property is not available and coldboot HART is assigned to the domain instance then **next booting stage mode of coldboot HART** is used as default value. * **system-reset-allowed** (Optional) - A boolean flag representing whether the domain instance is allowed to do system reset. +* **system-suspend-allowed** (Optional) - A boolean flag representing + whether the domain instance is allowed to do system suspend. ### Assigning HART To Domain Instance @@ -195,9 +210,9 @@ platform specific callback. The HART to domain instance assignment can be parsed from the device tree -using optional DT property **opensbi,domain** in each CPU DT node. The -value of DT property **opensbi,domain** is the DT phandle of the domain -instance DT node. If **opensbi,domain** DT property is not specified then +using optional DT property **opensbi-domain** in each CPU DT node. The +value of DT property **opensbi-domain** is the DT phandle of the domain +instance DT node. If **opensbi-domain** DT property is not specified then corresponding HART is assigned to **the ROOT domain**. ### Domain Configuration Only Accessible to OpenSBI @@ -222,6 +237,7 @@ chosen { opensbi-domains { compatible = "opensbi,domain,config"; + system-suspend-test; tmem: tmem { compatible = "opensbi,domain,memregion"; @@ -246,18 +262,19 @@ tdomain: trusted-domain { compatible = "opensbi,domain,instance"; possible-harts = <&cpu0>; - regions = <&tmem 0x7>, <&tuart 0x7>; + regions = <&tmem 0x3f>, <&tuart 0x3f>; boot-hart = <&cpu0>; next-arg1 = <0x0 0x0>; next-addr = <0x0 0x80100000>; next-mode = <0x0>; system-reset-allowed; + system-suspend-allowed; }; udomain: untrusted-domain { compatible = "opensbi,domain,instance"; possible-harts = <&cpu1 &cpu2 &cpu3 &cpu4>; - regions = <&tmem 0x0>, <&tuart 0x0>, <&allmem 0x7>; + regions = <&tmem 0x0>, <&tuart 0x0>, <&allmem 0x3f>; }; }; }; diff -Nru opensbi-1.1/docs/firmware/fw_dynamic.md opensbi-1.3/docs/firmware/fw_dynamic.md --- opensbi-1.1/docs/firmware/fw_dynamic.md 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/docs/firmware/fw_dynamic.md 2023-06-23 07:31:49.000000000 +0200 @@ -20,7 +20,7 @@ A platform can enable *FW_DYNAMIC* firmware using any of the following methods. 1. Specifying `FW_DYNAMIC=y` on the top level `make` command line. -2. Specifying `FW_DYNAMIC=y` in the target platform *config.mk* configuration +2. Specifying `FW_DYNAMIC=y` in the target platform *objects.mk* configuration file. The compiled *FW_DYNAMIC* firmware ELF file is named *fw_dynamic.elf*. It's @@ -31,6 +31,6 @@ *FW_DYNAMIC* Firmware Configuration Options ------------------------------------------- -The *FW_DYNAMIC* firmware does not requires any platform specific configuration +The *FW_DYNAMIC* firmware does not require any platform specific configuration parameters because all required information is passed by previous booting stage at runtime via *struct fw_dynamic_info*. diff -Nru opensbi-1.1/docs/firmware/fw_jump.md opensbi-1.3/docs/firmware/fw_jump.md --- opensbi-1.1/docs/firmware/fw_jump.md 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/docs/firmware/fw_jump.md 2023-06-23 07:31:49.000000000 +0200 @@ -15,7 +15,7 @@ A platform *FW_JUMP* firmware can be enabled by any of the following methods: 1. Specifying `FW_JUMP=y` on the top level `make` command line. -2. Specifying `FW_JUMP=y` in the target platform *config.mk* configuration file. +2. Specifying `FW_JUMP=y` in the target platform *objects.mk* configuration file. The compiled *FW_JUMP* firmware ELF file is named *fw_jump.elf*. Its expanded image file is *fw_jump.bin*. Both files are created in the platform-specific @@ -26,7 +26,7 @@ To operate correctly, a *FW_JUMP* firmware requires some configuration parameters to be defined using either the top level `make` command line or the -target platform *config.mk* configuration file. The possible parameters are as +target platform *objects.mk* configuration file. The possible parameters are as follows: * **FW_JUMP_ADDR** - Address of the entry point of the booting stage to be @@ -41,6 +41,22 @@ provided, then the OpenSBI firmware will pass the FDT address passed by the previous booting stage to the next booting stage. + When using the default *FW_JUMP_FDT_ADDR* with *PLATFORM=generic*, you must + ensure *FW_JUMP_FDT_ADDR* is set high enough to avoid overwriting the kernel. + You can use the following method (e.g., using bash or zsh): + + ``` + ${CROSS_COMPILE}objdump -h $KERNEL_ELF | sort -k 5,5 | awk -n ' + /^ +[0-9]+ / {addr="0x"$3; size="0x"$5; printf "0x""%x\n",addr+size}' | + (( `tail -1` > (FW_JUMP_FDT_ADDR - FW_JUMP_ADDR) )) && + echo fdt overlaps kernel, increase FW_JUMP_FDT_ADDR + + ${LLVM}objdump -h --show-lma $KERNEL_ELF | sort -k 5,5 | awk -n ' + /^ +[0-9]+ / {addr="0x"$3; size="0x"$5; printf "0x""%x\n",addr+size}' | + (( `tail -1` > (FW_JUMP_FDT_ADDR - FW_JUMP_ADDR) )) && + echo fdt overlaps kernel, increase FW_JUMP_FDT_ADDR + ``` + *FW_JUMP* Example ----------------- diff -Nru opensbi-1.1/docs/firmware/fw.md opensbi-1.3/docs/firmware/fw.md --- opensbi-1.1/docs/firmware/fw.md 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/docs/firmware/fw.md 2023-06-23 07:31:49.000000000 +0200 @@ -53,7 +53,7 @@ A *FW_PAYLOAD* firmware is also useful for cases where the booting stage prior to OpenSBI firmware does not pass a *flattened device tree (FDT file)*. In such case, a *FW_PAYLOAD* firmware allows embedding a flattened device tree in the -.text section of the final firmware. +.rodata section of the final firmware. Firmware Configuration and Compilation -------------------------------------- @@ -61,7 +61,7 @@ All firmware types support the following common compile time configuration parameters: -* **FW_TEXT_ADDR** - Defines the execution address of the OpenSBI firmware. +* **FW_TEXT_START** - Defines the execution address of the OpenSBI firmware. This configuration parameter is mandatory. * **FW_FDT_PATH** - Path to an external flattened device tree binary file to be embedded in the *.rodata* section of the final firmware. If this option diff -Nru opensbi-1.1/docs/firmware/fw_payload.md opensbi-1.3/docs/firmware/fw_payload.md --- opensbi-1.1/docs/firmware/fw_payload.md 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/docs/firmware/fw_payload.md 2023-06-23 07:31:49.000000000 +0200 @@ -12,7 +12,7 @@ A *FW_PAYLOAD* firmware is also useful for cases where the booting stage prior to the OpenSBI firmware does not pass a *flattened device tree (FDT file)*. In such a case, a *FW_PAYLOAD* firmware allows embedding a flattened device tree -in the .text section of the final firmware. +in the .rodata section of the final firmware. Enabling *FW_PAYLOAD* compilation --------------------------------- @@ -20,7 +20,7 @@ The *FW_PAYLOAD* firmware can be enabled by any of the following methods: 1. Specifying `FW_PAYLOAD=y` on the top level `make` command line. -2. Specifying `FW_PAYLOAD=y` in the target platform *config.mk* configuration +2. Specifying `FW_PAYLOAD=y` in the target platform *objects.mk* configuration file. The compiled *FW_PAYLOAD* firmware ELF file is named *fw_jump.elf*. Its @@ -33,7 +33,7 @@ A *FW_PAYLOAD* firmware is built according to configuration parameters and options. These configuration parameters can be defined using either the top -level `make` command line or the target platform *config.mk* configuration +level `make` command line or the target platform *objects.mk* configuration file. The parameters currently defined are as follows: * **FW_PAYLOAD_OFFSET** - Offset from *FW_TEXT_BASE* where the payload binary diff -Nru opensbi-1.1/docs/library_usage.md opensbi-1.3/docs/library_usage.md --- opensbi-1.1/docs/library_usage.md 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/docs/library_usage.md 2023-06-23 07:31:49.000000000 +0200 @@ -8,11 +8,7 @@ hooks for the execution of this interface must be provided by the firmware or bootloader linking with this library. This library is installed as */lib/libsbi.a* -2. *libsbiutils.a* - A static library that will contain all common code required - by any platform supported in OpenSBI. It will be built by default and included - in libplatsbi.a. This library is installed as - */lib/libsbiutils.a*. -3. *libplatsbi.a* - An example platform-specific static library integrating +2. *libplatsbi.a* - An example platform-specific static library integrating *libsbi.a* with platform-specific hooks. This library is available only for the platforms supported by OpenSBI. This library is installed as */platform//lib/libplatsbi.a* @@ -77,7 +73,7 @@ **OPENSBI_EXTERNAL_SBI_TYPES** identifier is introduced to *sbi_types.h* for selecting external header file during the build preprocess in order to define OpensSBI data types based on external firmware data type binding. -For example, *bool* is declared as *int* in sbi_types.h. However in EDK2 build system, +For example, *bool* is declared as *int* in sbi_types.h. However, in EDK2 build system, *bool* is declared as *BOOLEAN* which is defined as *unsigned char* data type. External firmware can define **OPENSBI_EXTERNAL_SBI_TYPES** in CFLAGS and specify it to the diff -Nru opensbi-1.1/docs/platform/andes-ae350.md opensbi-1.3/docs/platform/andes-ae350.md --- opensbi-1.1/docs/platform/andes-ae350.md 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/docs/platform/andes-ae350.md 2023-06-23 07:31:49.000000000 +0200 @@ -8,7 +8,7 @@ as a starting point to jump start SoC designs. To build platform specific library and firmwares, provide the -*PLATFORM=andes/ae350* parameter to the top level make command. +*PLATFORM=generic* parameter to the top level `make` command. Platform Options ---------------- @@ -18,13 +18,190 @@ Building Andes AE350 Platform ----------------------------- -To use Linux v5.2 should be used to build Andes AE350 OpenSBI binaries by using -the compile time option FW_FDT_PATH. - -AE350's dts is included in https://github.com/andestech/linux/tree/ast-v3_2_0-release-public +AE350's dts is included in https://github.com/andestech/linux/tree/RISCV-Linux-5.4-ast-v5_1_0-branch **Linux Kernel Payload** ``` -make PLATFORM=andes/ae350 FW_PAYLOAD_PATH=/arch/riscv/boot/Image FW_FDT_PATH= +make PLATFORM=generic FW_PAYLOAD_PATH=/arch/riscv/boot/Image FW_FDT_PATH= +``` + +DTS Example: (Quad-core AX45MP) +------------------------------- + +``` + compatible = "andestech,ae350"; + cpus { + #address-cells = <1>; + #size-cells = <0>; + timebase-frequency = <60000000>; + + CPU0: cpu@0 { + device_type = "cpu"; + reg = <0>; + status = "okay"; + compatible = "riscv"; + riscv,isa = "rv64imafdc"; + riscv,priv-major = <1>; + riscv,priv-minor = <10>; + mmu-type = "riscv,sv48"; + clock-frequency = <60000000>; + i-cache-size = <0x8000>; + i-cache-sets = <256>; + i-cache-line-size = <64>; + i-cache-block-size = <64>; + d-cache-size = <0x8000>; + d-cache-sets = <128>; + d-cache-line-size = <64>; + d-cache-block-size = <64>; + next-level-cache = <&L2>; + CPU0_intc: interrupt-controller { + #interrupt-cells = <1>; + interrupt-controller; + compatible = "riscv,cpu-intc"; + }; + }; + CPU1: cpu@1 { + device_type = "cpu"; + reg = <1>; + status = "okay"; + compatible = "riscv"; + riscv,isa = "rv64imafdc"; + riscv,priv-major = <1>; + riscv,priv-minor = <10>; + mmu-type = "riscv,sv48"; + clock-frequency = <60000000>; + i-cache-size = <0x8000>; + i-cache-sets = <256>; + i-cache-line-size = <64>; + i-cache-block-size = <64>; + d-cache-size = <0x8000>; + d-cache-sets = <128>; + d-cache-line-size = <64>; + d-cache-block-size = <64>; + next-level-cache = <&L2>; + CPU1_intc: interrupt-controller { + #interrupt-cells = <1>; + interrupt-controller; + compatible = "riscv,cpu-intc"; + }; + }; + CPU2: cpu@2 { + device_type = "cpu"; + reg = <2>; + status = "okay"; + compatible = "riscv"; + riscv,isa = "rv64imafdc"; + riscv,priv-major = <1>; + riscv,priv-minor = <10>; + mmu-type = "riscv,sv48"; + clock-frequency = <60000000>; + i-cache-size = <0x8000>; + i-cache-sets = <256>; + i-cache-line-size = <64>; + i-cache-block-size = <64>; + d-cache-size = <0x8000>; + d-cache-sets = <128>; + d-cache-line-size = <64>; + d-cache-block-size = <64>; + next-level-cache = <&L2>; + CPU2_intc: interrupt-controller { + #interrupt-cells = <1>; + interrupt-controller; + compatible = "riscv,cpu-intc"; + }; + }; + CPU3: cpu@3 { + device_type = "cpu"; + reg = <3>; + status = "okay"; + compatible = "riscv"; + riscv,isa = "rv64imafdc"; + riscv,priv-major = <1>; + riscv,priv-minor = <10>; + mmu-type = "riscv,sv48"; + clock-frequency = <60000000>; + i-cache-size = <0x8000>; + i-cache-sets = <256>; + i-cache-line-size = <64>; + i-cache-block-size = <64>; + d-cache-size = <0x8000>; + d-cache-sets = <128>; + d-cache-line-size = <64>; + d-cache-block-size = <64>; + next-level-cache = <&L2>; + CPU3_intc: interrupt-controller { + #interrupt-cells = <1>; + interrupt-controller; + compatible = "riscv,cpu-intc"; + }; + }; + }; + + soc { + #address-cells = <2>; + #size-cells = <2>; + compatible = "andestech,riscv-ae350-soc", "simple-bus"; + ranges; + + plic0: interrupt-controller@e4000000 { + compatible = "riscv,plic0"; + reg = <0x00000000 0xe4000000 0x00000000 0x02000000>; + interrupts-extended = < &CPU0_intc 11 &CPU0_intc 9 + &CPU1_intc 11 &CPU1_intc 9 + &CPU2_intc 11 &CPU2_intc 9 + &CPU3_intc 11 &CPU3_intc 9 >; + interrupt-controller; + #address-cells = <2>; + #interrupt-cells = <2>; + riscv,ndev = <71>; + }; + + plicsw: interrupt-controller@e6400000 { + compatible = "andestech,plicsw"; + reg = <0x00000000 0xe6400000 0x00000000 0x00400000>; + interrupts-extended = < &CPU0_intc 3 + &CPU1_intc 3 + &CPU2_intc 3 + &CPU3_intc 3 >; + interrupt-controller; + #address-cells = <2>; + #interrupt-cells = <2>; + }; + + plmt0: plmt0@e6000000 { + compatible = "andestech,plmt0"; + reg = <0x00000000 0xe6000000 0x00000000 0x00100000>; + interrupts-extended = < &CPU0_intc 7 + &CPU1_intc 7 + &CPU2_intc 7 + &CPU3_intc 7 >; + }; + + wdt: watchdog@f0500000 { + compatible = "andestech,atcwdt200"; + reg = <0x00000000 0xf0500000 0x00000000 0x00001000>; + interrupts = <3 4>; + interrupt-parent = <&plic0>; + clock-frequency = <15000000>; + }; + + serial0: serial@f0300000 { + compatible = "andestech,uart16550", "ns16550a"; + reg = <0x00000000 0xf0300000 0x00000000 0x00001000>; + interrupts = <9 4>; + interrupt-parent = <&plic0>; + clock-frequency = <19660800>; + current-speed = <38400>; + reg-shift = <2>; + reg-offset = <32>; + reg-io-width = <4>; + no-loopback-test = <1>; + }; + + smu: smu@f0100000 { + compatible = "andestech,atcsmu"; + reg = <0x00000000 0xf0100000 0x00000000 0x00001000>; + }; + }; ``` diff -Nru opensbi-1.1/docs/platform/fpga-ariane.md opensbi-1.3/docs/platform/fpga-ariane.md --- opensbi-1.1/docs/platform/fpga-ariane.md 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/docs/platform/fpga-ariane.md 2023-06-23 07:31:49.000000000 +0200 @@ -7,7 +7,7 @@ The FPGA SoC currently contains the following peripherals: - DDR3 memory controller -- SPI controller to conncet to an SDCard +- SPI controller to connect to an SDCard - Ethernet controller - JTAG port (see debugging section below) - Bootrom containing zero stage bootloader and device tree. diff -Nru opensbi-1.1/docs/platform/generic.md opensbi-1.3/docs/platform/generic.md --- opensbi-1.1/docs/platform/generic.md 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/docs/platform/generic.md 2023-06-23 07:31:49.000000000 +0200 @@ -45,13 +45,17 @@ RISC-V Platforms Using Generic Platform --------------------------------------- +* **Andes AE350 Platform** (*[andes-ae350.md]*) * **QEMU RISC-V Virt Machine** (*[qemu_virt.md]*) +* **Renesas RZ/Five SoC** (*[renesas-rzfive.md]*) * **Shakti C-class SoC Platform** (*[shakti_cclass.md]*) * **SiFive HiFive Unleashed** (*[sifive_fu540.md]*) * **Spike** (*[spike.md]*) * **T-HEAD C9xx series Processors** (*[thead-c9xx.md]*) +[andes-ae350.md]: andes-ae350.md [qemu_virt.md]: qemu_virt.md +[renesas-rzfive.md]: renesas-rzfive.md [shakti_cclass.md]: shakti_cclass.md [sifive_fu540.md]: sifive_fu540.md [spike.md]: spike.md diff -Nru opensbi-1.1/docs/platform/platform.md opensbi-1.3/docs/platform/platform.md --- opensbi-1.1/docs/platform/platform.md 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/docs/platform/platform.md 2023-06-23 07:31:49.000000000 +0200 @@ -39,11 +39,15 @@ processor based SOCs. More details on this platform can be found in the file *[shakti_cclass.md]*. +* **Renesas RZ/Five SoC**: Platform support for Renesas RZ/Five (R9A07G043F) SoC + used on the Renesas RZ/Five SMARC EVK board. More details on this platform can + be found in the file *[renesas-rzfive.md]*. + The code for these supported platforms can be used as example to implement support for other platforms. The *platform/template* directory also provides -template files for implementing support for a new platform. The *object.mk*, -*config.mk* and *platform.c* template files provides enough comments to -facilitate the implementation. +template files for implementing support for a new platform. The *objects.mk*, +*Kconfig*, *configs/defconfig* and *platform.c* template files provides enough +comments to facilitate the implementation. [generic.md]: generic.md [qemu_virt.md]: qemu_virt.md @@ -54,3 +58,4 @@ [spike.md]: spike.md [fpga-openpiton.md]: fpga-openpiton.md [shakti_cclass.md]: shakti_cclass.md +[renesas-rzfive.md]: renesas-rzfive.md diff -Nru opensbi-1.1/docs/platform/renesas-rzfive.md opensbi-1.3/docs/platform/renesas-rzfive.md --- opensbi-1.1/docs/platform/renesas-rzfive.md 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/docs/platform/renesas-rzfive.md 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,160 @@ +Renesas RZ/Five SoC (R9A07G043F) Platform +========================================= +The RZ/Five microprocessor includes a single RISC-V CPU Core (Andes AX45MP) +1.0 GHz, 16-bit DDR3L/DDR4 interface. Supported interfaces include: +- Memory controller for DDR4-1600 / DDR3L-1333 with 16 bits +- System RAM (RAM of 128 Kbytes (ECC)) +- SPI Multi I/O Bus Controller 1ch +- SD Card Host Interface/Multimedia Card Interface (SD/MMC) 2ch +- Serial Sound Interface (SSI) 4ch +- Sampling Rate Converter (SRC) 1ch +- USB2.0 host/function interface 2ch (ch0: Host-Function ch1: Host only) +- Gigabit Ethernet Interface (GbE) 2ch +- Controller Area Network Interface (CAN) 2ch (CAN-FD ISO 11898-1 (CD2014) compliant) +- Multi-function Timer Pulse Unit 3 (MTU3a) 9 ch (16 bits × 8 channels, 32 bits × 1 channel) +- Port Output Enable 3 (POE3) +- Watchdog Timer (WDT) 1ch +- General Timer (GTM) 3ch (32bits) +- I2C Bus Interface (I2C) 4ch +- Serial Communication Interface with FIFO (SCIFA) 5ch +- Serial Communication Interface (SCI) 2ch +- Renesas Serial Peripheral Interface (RSPI) 3ch +- A/D Converter (ADC) 2ch +making it ideal for applications such as entry-class social infrastructure +gateway control and industrial gateway control. More details can be found at +below link [0]. + +[0] https://www.renesas.com/us/en/products/microcontrollers-microprocessors/rz-mpus/rzfive-general-purpose-microprocessors-risc-v-cpu-core-andes-ax45mp-single-10-ghz-2ch-gigabit-ethernet + +To build platform specific library and firmwares, provide the +*PLATFORM=generic* parameter to the top level make command. + +Platform Options +---------------- + +The Renesas RZ/Five platform does not have any platform-specific options. + +Building Renesas RZ/Five Platform +--------------------------------- + +``` +make PLATFORM=generic +``` + +DTS Example: (RZ/Five AX45MP) +----------------------------- + +``` + compatible = "renesas,r9a07g043f01", "renesas,r9a07g043"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + timebase-frequency = <12000000>; + + cpu0: cpu@0 { + compatible = "andestech,ax45mp", "riscv"; + device_type = "cpu"; + reg = <0x0>; + status = "okay"; + riscv,isa = "rv64imafdc"; + mmu-type = "riscv,sv39"; + i-cache-size = <0x8000>; + i-cache-line-size = <0x40>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + clocks = <&cpg CPG_CORE R9A07G043_CLK_I>; + + cpu0_intc: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + ranges; + + scif0: serial@1004b800 { + compatible = "renesas,scif-r9a07g043", + "renesas,scif-r9a07g044"; + reg = <0 0x1004b800 0 0x400>; + interrupts = <412 IRQ_TYPE_LEVEL_HIGH>, + <414 IRQ_TYPE_LEVEL_HIGH>, + <415 IRQ_TYPE_LEVEL_HIGH>, + <413 IRQ_TYPE_LEVEL_HIGH>, + <416 IRQ_TYPE_LEVEL_HIGH>, + <416 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "eri", "rxi", "txi", + "bri", "dri", "tei"; + clocks = <&cpg CPG_MOD R9A07G043_SCIF0_CLK_PCK>; + clock-names = "fck"; + power-domains = <&cpg>; + resets = <&cpg R9A07G043_SCIF0_RST_SYSTEM_N>; + status = "disabled"; + }; + + cpg: clock-controller@11010000 { + compatible = "renesas,r9a07g043-cpg"; + reg = <0 0x11010000 0 0x10000>; + clocks = <&extal_clk>; + clock-names = "extal"; + #clock-cells = <2>; + #reset-cells = <1>; + #power-domain-cells = <0>; + }; + + sysc: system-controller@11020000 { + compatible = "renesas,r9a07g043-sysc"; + reg = <0 0x11020000 0 0x10000>; + status = "disabled"; + }; + + pinctrl: pinctrl@11030000 { + compatible = "renesas,r9a07g043-pinctrl"; + reg = <0 0x11030000 0 0x10000>; + gpio-controller; + #gpio-cells = <2>; + #interrupt-cells = <2>; + interrupt-controller; + gpio-ranges = <&pinctrl 0 0 152>; + clocks = <&cpg CPG_MOD R9A07G043_GPIO_HCLK>; + power-domains = <&cpg>; + resets = <&cpg R9A07G043_GPIO_RSTN>, + <&cpg R9A07G043_GPIO_PORT_RESETN>, + <&cpg R9A07G043_GPIO_SPARE_RESETN>; + }; + + plmt0: plmt0@110c0000 { + compatible = "andestech,plmt0", "riscv,plmt0"; + reg = <0x0 0x110c0000 0x0 0x10000>; + interrupts-extended = <&cpu0_intc 7>; + }; + + plic: interrupt-controller@12c00000 { + compatible = "renesas,r9a07g043-plic", "andestech,nceplic100"; + #interrupt-cells = <2>; + #address-cells = <0>; + riscv,ndev = <511>; + interrupt-controller; + reg = <0x0 0x12c00000 0x0 0x400000>; + clocks = <&cpg CPG_MOD R9A07G043_NCEPLIC_ACLK>; + power-domains = <&cpg>; + resets = <&cpg R9A07G043_NCEPLIC_ARESETN>; + interrupts-extended = <&cpu0_intc 11 &cpu0_intc 9>; + }; + + plicsw: interrupt-controller@13000000 { + compatible = "andestech,plicsw"; + reg = <0x0 0x13000000 0x0 0x400000>; + interrupts-extended = <&cpu0_intc 3>; + interrupt-controller; + #address-cells = <2>; + #interrupt-cells = <2>; + }; + }; +``` diff -Nru opensbi-1.1/docs/platform/sifive_fu540.md opensbi-1.3/docs/platform/sifive_fu540.md --- opensbi-1.1/docs/platform/sifive_fu540.md 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/docs/platform/sifive_fu540.md 2023-06-23 07:31:49.000000000 +0200 @@ -150,7 +150,7 @@ same instructions above, with the exception of not passing FW_FDT_PATH. This is because QEMU generates a device tree blob on the fly based on the -command line parameters and it's compatible with the one used in the upstream +command line parameters, and it's compatible with the one used in the upstream Linux kernel. When U-Boot v2021.07 (or higher) is used as the payload, as the SiFive FU540 diff -Nru opensbi-1.1/docs/platform/thead-c9xx.md opensbi-1.3/docs/platform/thead-c9xx.md --- opensbi-1.1/docs/platform/thead-c9xx.md 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/docs/platform/thead-c9xx.md 2023-06-23 07:31:49.000000000 +0200 @@ -13,7 +13,7 @@ ---------------- The *T-HEAD C9xx* does not have any platform-specific compile options -because it use generic platform. +because it uses generic platform. ``` CROSS_COMPILE=riscv64-linux-gnu- PLATFORM=generic /usr/bin/make diff -Nru opensbi-1.1/docs/platform_guide.md opensbi-1.3/docs/platform_guide.md --- opensbi-1.1/docs/platform_guide.md 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/docs/platform_guide.md 2023-06-23 07:31:49.000000000 +0200 @@ -28,11 +28,12 @@ Support for a new platform named *<xyz>* can be added as follows: 1. Create a directory named *<xyz>* under the *platform/* directory. -2. Create a platform configuration file named *config.mk* under the - *platform/<xyz>/* directory. This configuration file will provide +2. Create platform configuration files named *Kconfig* and *configs/defconfig* + under the *platform/<xyz>/* directory. These configuration files will + provide the build time configuration for the sources to be compiled. +3. Create a *platform/<xyz>/objects.mk* file for listing the platform + object files to be compiled. This file also provides platform-specific compiler flags, and select firmware options. -3. Create a *platform/<xyz>/objects.mk* file for listing the - platform-specific object files to be compiled. 4. Create a *platform/<xyz>/platform.c* file providing a *struct sbi_platform* instance. diff -Nru opensbi-1.1/docs/platform_requirements.md opensbi-1.3/docs/platform_requirements.md --- opensbi-1.1/docs/platform_requirements.md 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/docs/platform_requirements.md 2023-06-23 07:31:49.000000000 +0200 @@ -10,7 +10,7 @@ 2. **Release specific platform requirements** which apply to a OpenSBI release and later releases -Currently, we don't have any **Release specific platform requirements** +Currently, we don't have any **Release specific platform requirements**, but such platform requirements will be added in future. Base Platform Requirements diff -Nru opensbi-1.1/docs/pmu_support.md opensbi-1.3/docs/pmu_support.md --- opensbi-1.1/docs/pmu_support.md 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/docs/pmu_support.md 2023-06-23 07:31:49.000000000 +0200 @@ -1,14 +1,11 @@ OpenSBI SBI PMU extension support ================================== SBI PMU extension supports allow supervisor software to configure/start/stop -any performance counter at anytime. Thus, an user can leverage full +any performance counter at anytime. Thus, a user can leverage full capability of performance analysis tools such as perf if SBI PMU extension is enabled. The OpenSBI implementation makes the following assumptions about the hardware platform. - * MCOUNTINHIBIT CSR must be implemented in the hardware. Otherwise, SBI PMU -extension will not be enabled. - * The platform must provide information about PMU event to counter mapping via device tree or platform specific hooks. Otherwise, SBI PMU extension will not be enabled. @@ -25,7 +22,7 @@ ---------------------------- Platforms may choose to describe PMU event selector and event to counter mapping -values via device tree. The following sections describes the PMU DT node +values via device tree. The following sections describe the PMU DT node bindings in details. * **compatible** (Mandatory) - The compatible string of SBI PMU device tree node. @@ -42,21 +39,21 @@ * **riscv,event-to-mhpmcounters**(Optional) - It represents a MANY-to-MANY mapping between a range of events and all the MHPMCOUNTERx in a bitmap format that can be used to monitor these range of events. The information is encoded in -a table format where each row represent a certain range of events and +a table format where each row represents a certain range of events and corresponding counters. The first column represents starting of the pmu event id and 2nd column represents the end of the pmu event id. The third column represent a bitmap of all the MHPMCOUNTERx. This property is mandatory if -event-to-mhpmevent is present. Otherwise, it can be omitted. This property +riscv,event-to-mhpmevent is present. Otherwise, it can be omitted. This property shouldn't encode any raw event. * **riscv,raw-event-to-mhpmcounters**(Optional) - It represents an ONE-to-MANY or MANY-to-MANY mapping between the raw event(s) and all the MHPMCOUNTERx in a bitmap format that can be used to monitor that raw event. The encoding of the raw events are platform specific. The information is encoded in a table format -where each row represent the specific raw event(s). The first column is a 64bit +where each row represents the specific raw event(s). The first column is a 64bit match value where the invariant bits of range of events are set. The second column is a 64 bit mask that will have all the variant bits of the range of -events cleared. Every other bits should be set in the mask. +events cleared. All other bits should be set in the mask. The third column is a 32bit value to represent bitmap of all MHPMCOUNTERx that can monitor these set of event(s). If a platform directly encodes each raw PMU event as a unique ID, the value of @@ -70,17 +67,17 @@ ``` pmu { compatible = "riscv,pmu"; - riscv,event-to-mhpmevent = <0x0000B 0x0000 0x0001>, + riscv,event-to-mhpmevent = <0x0000B 0x0000 0x0001>; riscv,event-to-mhpmcounters = <0x00001 0x00001 0x00000001>, <0x00002 0x00002 0x00000004>, <0x00003 0x0000A 0x00000ff8>, - <0x10000 0x10033 0x000ff000>, + <0x10000 0x10033 0x000ff000>; /* For event ID 0x0002 */ riscv,raw-event-to-mhpmcounters = <0x0000 0x0002 0xffffffff 0xffffffff 0x00000f8>, /* For event ID 0-4 */ <0x0 0x0 0xffffffff 0xfffffff0 0x00000ff0>, /* For event ID 0xffffffff0000000f - 0xffffffff000000ff */ - <0xffffffff 0x0 0xffffffff 0xffffff0f 0x00000ff0>, + <0xffffffff 0x0 0xffffffff 0xffffff0f 0x00000ff0>; }; ``` @@ -90,11 +87,41 @@ /* * For HiFive Unmatched board. The encodings can be found here * https://sifive.cdn.prismic.io/sifive/1a82e600-1f93-4f41-b2d8-86ed8b16acba_fu740-c000-manual-v1p6.pdf + * This example also binds standard SBI PMU hardware id's to U74 PMU event codes, U74 uses bitfield for + * events encoding, so several U74 events can be bound to single perf id. + * See SBI PMU hardware id's in include/sbi/sbi_ecall_interface.h */ pmu { compatible = "riscv,pmu"; - riscv,raw-event-to-mhpmcounters = <0x0 0x0 0xffffffff 0xfc0000ff 0xc>, - <0x0 0x1 0xffffffff 0xfff800ff 0xc>, - <0x0 0x2 0xffffffff 0xffffe0ff 0xc>; + riscv,event-to-mhpmevent = +/* SBI_PMU_HW_CACHE_REFERENCES -> Instruction cache/ITIM busy | Data cache/DTIM busy */ + <0x00003 0x00000000 0x1801>, +/* SBI_PMU_HW_CACHE_MISSES -> Instruction cache miss | Data cache miss or memory-mapped I/O access */ + <0x00004 0x00000000 0x0302>, +/* SBI_PMU_HW_BRANCH_INSTRUCTIONS -> Conditional branch retired */ + <0x00005 0x00000000 0x4000>, +/* SBI_PMU_HW_BRANCH_MISSES -> Branch direction misprediction | Branch/jump target misprediction */ + <0x00006 0x00000000 0x6001>, +/* L1D_READ_MISS -> Data cache miss or memory-mapped I/O access */ + <0x10001 0x00000000 0x0202>, +/* L1D_WRITE_ACCESS -> Data cache write-back */ + <0x10002 0x00000000 0x0402>, +/* L1I_READ_ACCESS -> Instruction cache miss */ + <0x10009 0x00000000 0x0102>, +/* LL_READ_MISS -> UTLB miss */ + <0x10011 0x00000000 0x2002>, +/* DTLB_READ_MISS -> Data TLB miss */ + <0x10019 0x00000000 0x1002>, +/* ITLB_READ_MISS-> Instruction TLB miss */ + <0x10021 0x00000000 0x0802>; + riscv,event-to-mhpmcounters = <0x00003 0x00006 0x18>, + <0x10001 0x10002 0x18>, + <0x10009 0x10009 0x18>, + <0x10011 0x10011 0x18>, + <0x10019 0x10019 0x18>, + <0x10021 0x10021 0x18>; + riscv,raw-event-to-mhpmcounters = <0x0 0x0 0xffffffff 0xfc0000ff 0x18>, + <0x0 0x1 0xffffffff 0xfff800ff 0x18>, + <0x0 0x2 0xffffffff 0xffffe0ff 0x18>; }; ``` Binary files /tmp/situTvWC1Q/opensbi-1.1/docs/riscv_opensbi_logo_final_color.png and /tmp/OnFvKhVCkP/opensbi-1.3/docs/riscv_opensbi_logo_final_color.png differ Binary files /tmp/situTvWC1Q/opensbi-1.1/docs/riscv_opensbi_logo_final_grey.png and /tmp/OnFvKhVCkP/opensbi-1.3/docs/riscv_opensbi_logo_final_grey.png differ diff -Nru opensbi-1.1/firmware/fw_base.ldS opensbi-1.3/firmware/fw_base.ldS --- opensbi-1.1/firmware/fw_base.ldS 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/firmware/fw_base.ldS 2023-06-23 07:31:49.000000000 +0200 @@ -24,27 +24,49 @@ PROVIDE(_text_end = .); } - . = ALIGN(0x1000); /* Ensure next section is page aligned */ - /* End of the code sections */ + . = ALIGN(0x1000); /* Ensure next section is page aligned */ + /* Beginning of the read-only data sections */ - . = ALIGN(0x1000); /* Ensure next section is page aligned */ + PROVIDE(_rodata_start = .); .rodata : { - PROVIDE(_rodata_start = .); *(.rodata .rodata.*) . = ALIGN(8); - PROVIDE(_rodata_end = .); } + . = ALIGN(0x1000); /* Ensure next section is page aligned */ + + .dynsym : { + PROVIDE(__dyn_sym_start = .); + *(.dynsym) + PROVIDE(__dyn_sym_end = .); + } + + .rela.dyn : { + PROVIDE(__rel_dyn_start = .); + *(.rela*) + . = ALIGN(8); + PROVIDE(__rel_dyn_end = .); + } + + PROVIDE(_rodata_end = .); + /* End of the read-only data sections */ - /* Beginning of the read-write data sections */ + /* + * PMP regions must be to be power-of-2. RX/RW will have separate + * regions, so ensure that the split is power-of-2. + */ + . = ALIGN(1 << LOG2CEIL((SIZEOF(.rodata) + SIZEOF(.text) + + SIZEOF(.dynsym) + SIZEOF(.rela.dyn)))); - . = ALIGN(0x1000); /* Ensure next section is page aligned */ + PROVIDE(_fw_rw_start = .); + + /* Beginning of the read-write data sections */ .data : { @@ -61,19 +83,6 @@ PROVIDE(_data_end = .); } - .dynsym : { - PROVIDE(__dyn_sym_start = .); - *(.dynsym) - PROVIDE(__dyn_sym_end = .); - } - - .rela.dyn : { - PROVIDE(__rel_dyn_start = .); - *(.rela*) - . = ALIGN(8); - PROVIDE(__rel_dyn_end = .); - } - . = ALIGN(0x1000); /* Ensure next section is page aligned */ .bss : diff -Nru opensbi-1.1/firmware/fw_base.S opensbi-1.3/firmware/fw_base.S --- opensbi-1.1/firmware/fw_base.S 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/firmware/fw_base.S 2023-06-23 07:31:49.000000000 +0200 @@ -79,13 +79,12 @@ lla t0, __rel_dyn_start lla t1, __rel_dyn_end beq t0, t1, _relocate_done - j 5f 2: - REG_L t5, -(REGBYTES*2)(t0) /* t5 <-- relocation info:type */ + REG_L t5, REGBYTES(t0) /* t5 <-- relocation info:type */ li t3, R_RISCV_RELATIVE /* reloc type R_RISCV_RELATIVE */ bne t5, t3, 3f - REG_L t3, -(REGBYTES*3)(t0) - REG_L t5, -(REGBYTES)(t0) /* t5 <-- addend */ + REG_L t3, 0(t0) + REG_L t5, (REGBYTES * 2)(t0) /* t5 <-- addend */ add t5, t5, t2 add t3, t3, t2 REG_S t5, 0(t3) /* store runtime address to the GOT entry */ @@ -95,18 +94,17 @@ lla t4, __dyn_sym_start 4: - REG_L t5, -(REGBYTES*2)(t0) /* t5 <-- relocation info:type */ srli t6, t5, SYM_INDEX /* t6 <--- sym table index */ andi t5, t5, 0xFF /* t5 <--- relocation type */ li t3, RELOC_TYPE bne t5, t3, 5f /* address R_RISCV_64 or R_RISCV_32 cases*/ - REG_L t3, -(REGBYTES*3)(t0) + REG_L t3, 0(t0) li t5, SYM_SIZE mul t6, t6, t5 add s5, t4, t6 - REG_L t6, -(REGBYTES)(t0) /* t0 <-- addend */ + REG_L t6, (REGBYTES * 2)(t0) /* t0 <-- addend */ REG_L t5, REGBYTES(s5) add t5, t5, t6 add t5, t5, t2 /* t5 <-- location to fix up in RAM */ @@ -114,8 +112,8 @@ REG_S t5, 0(t3) /* store runtime address to the variable */ 5: - addi t0, t0, (REGBYTES*3) - ble t0, t1, 2b + addi t0, t0, (REGBYTES * 3) + blt t0, t1, 2b j _relocate_done _wait_relocate_copy_done: j _wait_for_boot_hart @@ -128,9 +126,9 @@ REG_L t1, 0(t1) lla t2, _load_start REG_L t2, 0(t2) + beq t0, t2, _relocate_done sub t3, t1, t0 add t3, t3, t2 - beq t0, t2, _relocate_done lla t4, _relocate_done sub t4, t4, t2 add t4, t4, t0 @@ -257,20 +255,28 @@ /* Preload HART details * s7 -> HART Count * s8 -> HART Stack Size + * s9 -> Heap Size + * s10 -> Heap Offset */ lla a4, platform #if __riscv_xlen > 32 lwu s7, SBI_PLATFORM_HART_COUNT_OFFSET(a4) lwu s8, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(a4) + lwu s9, SBI_PLATFORM_HEAP_SIZE_OFFSET(a4) #else lw s7, SBI_PLATFORM_HART_COUNT_OFFSET(a4) lw s8, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(a4) + lw s9, SBI_PLATFORM_HEAP_SIZE_OFFSET(a4) #endif /* Setup scratch space for all the HARTs*/ lla tp, _fw_end mul a5, s7, s8 add tp, tp, a5 + /* Setup heap base address */ + lla s10, _fw_start + sub s10, tp, s10 + add tp, tp, s9 /* Keep a copy of tp */ add t3, tp, zero /* Counter */ @@ -285,8 +291,11 @@ * t3 -> the firmware end address * s7 -> HART count * s8 -> HART stack size + * s9 -> Heap Size + * s10 -> Heap Offset */ add tp, t3, zero + sub tp, tp, s9 mul a5, s8, t1 sub tp, tp, a5 li a5, SBI_SCRATCH_SIZE @@ -298,6 +307,16 @@ sub a5, t3, a4 REG_S a4, SBI_SCRATCH_FW_START_OFFSET(tp) REG_S a5, SBI_SCRATCH_FW_SIZE_OFFSET(tp) + + /* Store R/W section's offset in scratch space */ + lla a4, __fw_rw_offset + REG_L a5, 0(a4) + REG_S a5, SBI_SCRATCH_FW_RW_OFFSET(tp) + + /* Store fw_heap_offset and fw_heap_size in scratch space */ + REG_S s10, SBI_SCRATCH_FW_HEAP_OFFSET(tp) + REG_S s9, SBI_SCRATCH_FW_HEAP_SIZE_OFFSET(tp) + /* Store next arg1 in scratch space */ MOV_3R s0, a0, s1, a1, s2, a2 call fw_next_arg1 @@ -422,9 +441,8 @@ li ra, 0 call _reset_regs - /* Disable and clear all interrupts */ + /* Disable all interrupts */ csrw CSR_MIE, zero - csrw CSR_MIP, zero /* Find HART count and HART stack size */ lla a4, platform @@ -453,7 +471,6 @@ add s9, s9, 4 add a4, a4, 1 blt a4, s7, 1b - li a4, -1 2: add s6, a4, zero 3: bge s6, s7, _start_hang @@ -519,6 +536,8 @@ RISCV_PTR FW_TEXT_START _link_end: RISCV_PTR _fw_reloc_end +__fw_rw_offset: + RISCV_PTR _fw_rw_start - _fw_start .section .entry, "ax", %progbits .align 3 diff -Nru opensbi-1.1/firmware/Kconfig opensbi-1.3/firmware/Kconfig --- opensbi-1.1/firmware/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/firmware/Kconfig 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1 @@ +# SPDX-License-Identifier: BSD-2-Clause diff -Nru opensbi-1.1/firmware/payloads/test.elf.ldS opensbi-1.3/firmware/payloads/test.elf.ldS --- opensbi-1.1/firmware/payloads/test.elf.ldS 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/firmware/payloads/test.elf.ldS 2023-06-23 07:31:49.000000000 +0200 @@ -33,14 +33,12 @@ PROVIDE(_text_end = .); } - . = ALIGN(0x1000); /* Ensure next section is page aligned */ - /* End of the code sections */ - /* Beginning of the read-only data sections */ - . = ALIGN(0x1000); /* Ensure next section is page aligned */ + /* Beginning of the read-only data sections */ + .rodata : { PROVIDE(_rodata_start = .); @@ -51,10 +49,10 @@ /* End of the read-only data sections */ - /* Beginning of the read-write data sections */ - . = ALIGN(0x1000); /* Ensure next section is page aligned */ + /* Beginning of the read-write data sections */ + .data : { PROVIDE(_data_start = .); diff -Nru opensbi-1.1/.gitignore opensbi-1.3/.gitignore --- opensbi-1.1/.gitignore 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/.gitignore 2023-06-23 07:31:49.000000000 +0200 @@ -9,3 +9,5 @@ # Development friendly files tags +cscope* +*.swp diff -Nru opensbi-1.1/include/sbi/riscv_encoding.h opensbi-1.3/include/sbi/riscv_encoding.h --- opensbi-1.1/include/sbi/riscv_encoding.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi/riscv_encoding.h 2023-06-23 07:31:49.000000000 +0200 @@ -38,10 +38,14 @@ #define MSTATUS_SXL _ULL(0x0000000C00000000) #define MSTATUS_SBE _ULL(0x0000001000000000) #define MSTATUS_MBE _ULL(0x0000002000000000) +#define MSTATUS_GVA _ULL(0x0000004000000000) +#define MSTATUS_GVA_SHIFT 38 #define MSTATUS_MPV _ULL(0x0000008000000000) #else #define MSTATUSH_SBE _UL(0x00000010) #define MSTATUSH_MBE _UL(0x00000020) +#define MSTATUSH_GVA _UL(0x00000040) +#define MSTATUSH_GVA_SHIFT 6 #define MSTATUSH_MPV _UL(0x00000080) #endif #define MSTATUS32_SD _UL(0x80000000) @@ -308,8 +312,6 @@ /* Supervisor Trap Setup */ #define CSR_SSTATUS 0x100 -#define CSR_SEDELEG 0x102 -#define CSR_SIDELEG 0x103 #define CSR_SIE 0x104 #define CSR_STVEC 0x105 #define CSR_SCOUNTEREN 0x106 @@ -734,6 +736,8 @@ #define SMSTATEEN0_CS (_ULL(1) << SMSTATEEN0_CS_SHIFT) #define SMSTATEEN0_FCSR_SHIFT 1 #define SMSTATEEN0_FCSR (_ULL(1) << SMSTATEEN0_FCSR_SHIFT) +#define SMSTATEEN0_CONTEXT_SHIFT 57 +#define SMSTATEEN0_CONTEXT (_ULL(1) << SMSTATEEN0_CONTEXT_SHIFT) #define SMSTATEEN0_IMSIC_SHIFT 58 #define SMSTATEEN0_IMSIC (_ULL(1) << SMSTATEEN0_IMSIC_SHIFT) #define SMSTATEEN0_AIA_SHIFT 59 diff -Nru opensbi-1.1/include/sbi/sbi_bitops.h opensbi-1.3/include/sbi/sbi_bitops.h --- opensbi-1.1/include/sbi/sbi_bitops.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi/sbi_bitops.h 2023-06-23 07:31:49.000000000 +0200 @@ -12,13 +12,7 @@ #include -#if __SIZEOF_POINTER__ == 8 -#define BITS_PER_LONG 64 -#elif __SIZEOF_POINTER__ == 4 -#define BITS_PER_LONG 32 -#else -#error "Unexpected __SIZEOF_POINTER__" -#endif +#define BITS_PER_LONG (8 * __SIZEOF_LONG__) #define EXTRACT_FIELD(val, which) \ (((val) & (which)) / ((which) & ~((which)-1))) diff -Nru opensbi-1.1/include/sbi/sbi_byteorder.h opensbi-1.3/include/sbi/sbi_byteorder.h --- opensbi-1.1/include/sbi/sbi_byteorder.h 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/include/sbi/sbi_byteorder.h 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,61 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Ventana Micro Systems Inc. + */ + +#ifndef __SBI_BYTEORDER_H__ +#define __SBI_BYTEORDER_H__ + +#include + +#define BSWAP16(x) ((((x) & 0x00ff) << 8) | \ + (((x) & 0xff00) >> 8)) +#define BSWAP32(x) ((((x) & 0x000000ff) << 24) | \ + (((x) & 0x0000ff00) << 8) | \ + (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0xff000000) >> 24)) +#define BSWAP64(x) ((((x) & 0x00000000000000ffULL) << 56) | \ + (((x) & 0x000000000000ff00ULL) << 40) | \ + (((x) & 0x0000000000ff0000ULL) << 24) | \ + (((x) & 0x00000000ff000000ULL) << 8) | \ + (((x) & 0x000000ff00000000ULL) >> 8) | \ + (((x) & 0x0000ff0000000000ULL) >> 24) | \ + (((x) & 0x00ff000000000000ULL) >> 40) | \ + (((x) & 0xff00000000000000ULL) >> 56)) + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ /* CPU(little-endian) */ +#define cpu_to_be16(x) ((uint16_t)BSWAP16(x)) +#define cpu_to_be32(x) ((uint32_t)BSWAP32(x)) +#define cpu_to_be64(x) ((uint64_t)BSWAP64(x)) + +#define be16_to_cpu(x) ((uint16_t)BSWAP16(x)) +#define be32_to_cpu(x) ((uint32_t)BSWAP32(x)) +#define be64_to_cpu(x) ((uint64_t)BSWAP64(x)) + +#define cpu_to_le16(x) ((uint16_t)(x)) +#define cpu_to_le32(x) ((uint32_t)(x)) +#define cpu_to_le64(x) ((uint64_t)(x)) + +#define le16_to_cpu(x) ((uint16_t)(x)) +#define le32_to_cpu(x) ((uint32_t)(x)) +#define le64_to_cpu(x) ((uint64_t)(x)) +#else /* CPU(big-endian) */ +#define cpu_to_be16(x) ((uint16_t)(x)) +#define cpu_to_be32(x) ((uint32_t)(x)) +#define cpu_to_be64(x) ((uint64_t)(x)) + +#define be16_to_cpu(x) ((uint16_t)(x)) +#define be32_to_cpu(x) ((uint32_t)(x)) +#define be64_to_cpu(x) ((uint64_t)(x)) + +#define cpu_to_le16(x) ((uint16_t)BSWAP16(x)) +#define cpu_to_le32(x) ((uint32_t)BSWAP32(x)) +#define cpu_to_le64(x) ((uint64_t)BSWAP64(x)) + +#define le16_to_cpu(x) ((uint16_t)BSWAP16(x)) +#define le32_to_cpu(x) ((uint32_t)BSWAP32(x)) +#define le64_to_cpu(x) ((uint64_t)BSWAP64(x)) +#endif + +#endif /* __SBI_BYTEORDER_H__ */ diff -Nru opensbi-1.1/include/sbi/sbi_console.h opensbi-1.3/include/sbi/sbi_console.h --- opensbi-1.1/include/sbi/sbi_console.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi/sbi_console.h 2023-06-23 07:31:49.000000000 +0200 @@ -19,6 +19,9 @@ /** Write a character to the console output */ void (*console_putc)(char ch); + /** Write a character string to the console output */ + unsigned long (*console_puts)(const char *str, unsigned long len); + /** Read a character from the console input */ int (*console_getc)(void); }; @@ -33,8 +36,12 @@ void sbi_puts(const char *str); +unsigned long sbi_nputs(const char *str, unsigned long len); + void sbi_gets(char *s, int maxwidth, char endchar); +unsigned long sbi_ngets(char *str, unsigned long len); + int __printf(2, 3) sbi_sprintf(char *out, const char *format, ...); int __printf(3, 4) sbi_snprintf(char *out, u32 out_sz, const char *format, ...); diff -Nru opensbi-1.1/include/sbi/sbi_cppc.h opensbi-1.3/include/sbi/sbi_cppc.h --- opensbi-1.1/include/sbi/sbi_cppc.h 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/include/sbi/sbi_cppc.h 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,35 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Ventana Micro Systems Inc. + * + */ + +#ifndef __SBI_CPPC_H__ +#define __SBI_CPPC_H__ + +#include + +/** CPPC device */ +struct sbi_cppc_device { + /** Name of the CPPC device */ + char name[32]; + + /** probe - returns register width if implemented, 0 otherwise */ + int (*cppc_probe)(unsigned long reg); + + /** read the cppc register*/ + int (*cppc_read)(unsigned long reg, uint64_t *val); + + /** write to the cppc register*/ + int (*cppc_write)(unsigned long reg, uint64_t val); +}; + +int sbi_cppc_probe(unsigned long reg); +int sbi_cppc_read(unsigned long reg, uint64_t *val); +int sbi_cppc_write(unsigned long reg, uint64_t val); + +const struct sbi_cppc_device *sbi_cppc_get_device(void); +void sbi_cppc_set_device(const struct sbi_cppc_device *dev); + +#endif diff -Nru opensbi-1.1/include/sbi/sbi_domain.h opensbi-1.3/include/sbi/sbi_domain.h --- opensbi-1.1/include/sbi/sbi_domain.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi/sbi_domain.h 2023-06-23 07:31:49.000000000 +0200 @@ -36,11 +36,53 @@ */ unsigned long base; /** Flags representing memory region attributes */ -#define SBI_DOMAIN_MEMREGION_READABLE (1UL << 0) -#define SBI_DOMAIN_MEMREGION_WRITEABLE (1UL << 1) -#define SBI_DOMAIN_MEMREGION_EXECUTABLE (1UL << 2) -#define SBI_DOMAIN_MEMREGION_MMODE (1UL << 3) -#define SBI_DOMAIN_MEMREGION_ACCESS_MASK (0xfUL) +#define SBI_DOMAIN_MEMREGION_M_READABLE (1UL << 0) +#define SBI_DOMAIN_MEMREGION_M_WRITABLE (1UL << 1) +#define SBI_DOMAIN_MEMREGION_M_EXECUTABLE (1UL << 2) +#define SBI_DOMAIN_MEMREGION_SU_READABLE (1UL << 3) +#define SBI_DOMAIN_MEMREGION_SU_WRITABLE (1UL << 4) +#define SBI_DOMAIN_MEMREGION_SU_EXECUTABLE (1UL << 5) + +/** Bit to control if permissions are enforced on all modes */ +#define SBI_DOMAIN_MEMREGION_ENF_PERMISSIONS (1UL << 6) + +#define SBI_DOMAIN_MEMREGION_M_RWX \ + (SBI_DOMAIN_MEMREGION_M_READABLE | \ + SBI_DOMAIN_MEMREGION_M_WRITABLE | \ + SBI_DOMAIN_MEMREGION_M_EXECUTABLE) + +#define SBI_DOMAIN_MEMREGION_SU_RWX \ + (SBI_DOMAIN_MEMREGION_SU_READABLE | \ + SBI_DOMAIN_MEMREGION_SU_WRITABLE | \ + SBI_DOMAIN_MEMREGION_SU_EXECUTABLE) + +/* Unrestricted M-mode accesses but enfoced on SU-mode */ +#define SBI_DOMAIN_MEMREGION_READABLE \ + (SBI_DOMAIN_MEMREGION_SU_READABLE | \ + SBI_DOMAIN_MEMREGION_M_RWX) +#define SBI_DOMAIN_MEMREGION_WRITEABLE \ + (SBI_DOMAIN_MEMREGION_SU_WRITABLE | \ + SBI_DOMAIN_MEMREGION_M_RWX) +#define SBI_DOMAIN_MEMREGION_EXECUTABLE \ + (SBI_DOMAIN_MEMREGION_SU_EXECUTABLE | \ + SBI_DOMAIN_MEMREGION_M_RWX) + +/* Enforced accesses across all modes */ +#define SBI_DOMAIN_MEMREGION_ENF_READABLE \ + (SBI_DOMAIN_MEMREGION_SU_READABLE | \ + SBI_DOMAIN_MEMREGION_M_READABLE) +#define SBI_DOMAIN_MEMREGION_ENF_WRITABLE \ + (SBI_DOMAIN_MEMREGION_SU_WRITABLE | \ + SBI_DOMAIN_MEMREGION_M_WRITABLE) +#define SBI_DOMAIN_MEMREGION_ENF_EXECUTABLE \ + (SBI_DOMAIN_MEMREGION_SU_EXECUTABLE | \ + SBI_DOMAIN_MEMREGION_M_EXECUTABLE) + +#define SBI_DOMAIN_MEMREGION_ACCESS_MASK (0x3fUL) +#define SBI_DOMAIN_MEMREGION_M_ACCESS_MASK (0x7UL) +#define SBI_DOMAIN_MEMREGION_SU_ACCESS_MASK (0x38UL) + +#define SBI_DOMAIN_MEMREGION_SU_ACCESS_SHIFT (3) #define SBI_DOMAIN_MEMREGION_MMIO (1UL << 31) unsigned long flags; @@ -78,17 +120,17 @@ unsigned long next_mode; /** Is domain allowed to reset the system */ bool system_reset_allowed; + /** Is domain allowed to suspend the system */ + bool system_suspend_allowed; + /** Identifies whether to include the firmware region */ + bool fw_region_inited; }; /** The root domain instance */ extern struct sbi_domain root; -/** HART id to domain table */ -extern struct sbi_domain *hartid_to_domain_table[]; - /** Get pointer to sbi_domain from HART id */ -#define sbi_hartid_to_domain(__hartid) \ - hartid_to_domain_table[__hartid] +struct sbi_domain *sbi_hartid_to_domain(u32 hartid); /** Get pointer to sbi_domain for current HART */ #define sbi_domain_thishart_ptr() \ @@ -113,7 +155,7 @@ * Check whether given HART is assigned to specified domain * @param dom pointer to domain * @param hartid the HART ID - * @return TRUE if HART is assigned to domain otherwise FALSE + * @return true if HART is assigned to domain otherwise false */ bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartid); @@ -148,12 +190,27 @@ * @param addr the address to be checked * @param mode the privilege mode of access * @param access_flags bitmask of domain access types (enum sbi_domain_access) - * @return TRUE if access allowed otherwise FALSE + * @return true if access allowed otherwise false */ bool sbi_domain_check_addr(const struct sbi_domain *dom, unsigned long addr, unsigned long mode, unsigned long access_flags); +/** + * Check whether we can access specified address range for given mode and + * memory region flags under a domain + * @param dom pointer to domain + * @param addr the start of the address range to be checked + * @param size the size of the address range to be checked + * @param mode the privilege mode of access + * @param access_flags bitmask of domain access types (enum sbi_domain_access) + * @return TRUE if access allowed otherwise FALSE + */ +bool sbi_domain_check_addr_range(const struct sbi_domain *dom, + unsigned long addr, unsigned long size, + unsigned long mode, + unsigned long access_flags); + /** Dump domain details on the console */ void sbi_domain_dump(const struct sbi_domain *dom, const char *suffix); @@ -175,11 +232,25 @@ * @param reg pointer to the memory region to be added * * @return 0 on success - * @return SBI_EALREADY if memory region conflicts with existing + * @return SBI_EALREADY if memory region conflicts with the existing one * @return SBI_EINVAL otherwise */ int sbi_domain_root_add_memregion(const struct sbi_domain_memregion *reg); +/** + * Add a memory range with its flags to the root domain + * @param addr start physical address of memory range + * @param size physical size of memory range + * @param align alignment of memory region + * @param region_flags memory range flags + * + * @return 0 on success + * @return SBI_EALREADY if memory region conflicts with the existing one + * @return SBI_EINVAL otherwise + */ +int sbi_domain_root_add_memrange(unsigned long addr, unsigned long size, + unsigned long align, unsigned long region_flags); + /** Finalize domain tables and startup non-root domains */ int sbi_domain_finalize(struct sbi_scratch *scratch, u32 cold_hartid); diff -Nru opensbi-1.1/include/sbi/sbi_ecall.h opensbi-1.3/include/sbi/sbi_ecall.h --- opensbi-1.1/include/sbi/sbi_ecall.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi/sbi_ecall.h 2023-06-23 07:31:49.000000000 +0200 @@ -21,26 +21,52 @@ struct sbi_trap_info; struct sbi_ecall_extension { + /* head is used by the extension list */ struct sbi_dlist head; + /* + * extid_start and extid_end specify the range for this extension. As + * the initial range may be wider than the valid runtime range, the + * register_extensions callback is responsible for narrowing the range + * before other callbacks may be invoked. + */ unsigned long extid_start; unsigned long extid_end; + /* + * register_extensions + * + * Calls sbi_ecall_register_extension() one or more times to register + * extension ID range(s) which should be handled by this extension. + * More than one sbi_ecall_extension struct and + * sbi_ecall_register_extension() call is necessary when the supported + * extension ID ranges have gaps. Additionally, extension availability + * must be checked before registering, which means, when this callback + * returns, only valid extension IDs from the initial range, which are + * also available, have been registered. + */ + int (* register_extensions)(void); + /* + * probe + * + * Implements the Base extension's probe function for the extension. As + * the register_extensions callback ensures that no other extension + * callbacks will be invoked when the extension is not available, then + * probe can never fail. However, an extension may choose to set + * out_val to a nonzero value other than one. In those cases, it should + * implement this callback. + */ int (* probe)(unsigned long extid, unsigned long *out_val); + /* + * handle + * + * This is the extension handler. register_extensions ensures it is + * never invoked with an invalid or unavailable extension ID. + */ int (* handle)(unsigned long extid, unsigned long funcid, const struct sbi_trap_regs *regs, unsigned long *out_val, struct sbi_trap_info *out_trap); }; -extern struct sbi_ecall_extension ecall_base; -extern struct sbi_ecall_extension ecall_legacy; -extern struct sbi_ecall_extension ecall_time; -extern struct sbi_ecall_extension ecall_rfence; -extern struct sbi_ecall_extension ecall_ipi; -extern struct sbi_ecall_extension ecall_vendor; -extern struct sbi_ecall_extension ecall_hsm; -extern struct sbi_ecall_extension ecall_srst; -extern struct sbi_ecall_extension ecall_pmu; - u16 sbi_ecall_version_major(void); u16 sbi_ecall_version_minor(void); diff -Nru opensbi-1.1/include/sbi/sbi_ecall_interface.h opensbi-1.3/include/sbi/sbi_ecall_interface.h --- opensbi-1.1/include/sbi/sbi_ecall_interface.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi/sbi_ecall_interface.h 2023-06-23 07:31:49.000000000 +0200 @@ -29,6 +29,9 @@ #define SBI_EXT_HSM 0x48534D #define SBI_EXT_SRST 0x53525354 #define SBI_EXT_PMU 0x504D55 +#define SBI_EXT_DBCN 0x4442434E +#define SBI_EXT_SUSP 0x53555350 +#define SBI_EXT_CPPC 0x43505043 /* SBI function IDs for BASE extension*/ #define SBI_EXT_BASE_GET_SPEC_VERSION 0x0 @@ -99,6 +102,7 @@ #define SBI_EXT_PMU_COUNTER_START 0x3 #define SBI_EXT_PMU_COUNTER_STOP 0x4 #define SBI_EXT_PMU_COUNTER_FW_READ 0x5 +#define SBI_EXT_PMU_COUNTER_FW_READ_HI 0x6 /** General pmu event codes specified in SBI PMU extension */ enum sbi_pmu_hw_generic_events_t { @@ -182,6 +186,17 @@ SBI_PMU_FW_HFENCE_VVMA_ASID_SENT = 20, SBI_PMU_FW_HFENCE_VVMA_ASID_RCVD = 21, SBI_PMU_FW_MAX, + /* + * Event codes 22 to 255 are reserved for future use. + * Event codes 256 to 65534 are reserved for SBI implementation + * specific custom firmware events. + */ + SBI_PMU_FW_RESERVED_MAX = 0xFFFE, + /* + * Event code 0xFFFF is used for platform specific firmware + * events where the event data contains any event specific information. + */ + SBI_PMU_FW_PLATFORM = 0xFFFF, }; /** SBI PMU event idx type */ @@ -200,14 +215,20 @@ }; /* Helper macros to decode event idx */ -#define SBI_PMU_EVENT_IDX_OFFSET 20 #define SBI_PMU_EVENT_IDX_MASK 0xFFFFF +#define SBI_PMU_EVENT_IDX_TYPE_OFFSET 16 +#define SBI_PMU_EVENT_IDX_TYPE_MASK (0xF << SBI_PMU_EVENT_IDX_TYPE_OFFSET) #define SBI_PMU_EVENT_IDX_CODE_MASK 0xFFFF -#define SBI_PMU_EVENT_IDX_TYPE_MASK 0xF0000 #define SBI_PMU_EVENT_RAW_IDX 0x20000 #define SBI_PMU_EVENT_IDX_INVALID 0xFFFFFFFF +#define SBI_PMU_EVENT_HW_CACHE_OPS_RESULT 0x1 +#define SBI_PMU_EVENT_HW_CACHE_OPS_ID_MASK 0x6 +#define SBI_PMU_EVENT_HW_CACHE_OPS_ID_OFFSET 1 +#define SBI_PMU_EVENT_HW_CACHE_ID_MASK 0xfff8 +#define SBI_PMU_EVENT_HW_CACHE_ID_OFFSET 3 + /* Flags defined for config matching function */ #define SBI_PMU_CFG_FLAG_SKIP_MATCH (1 << 0) #define SBI_PMU_CFG_FLAG_CLEAR_VALUE (1 << 1) @@ -224,6 +245,51 @@ /* Flags defined for counter stop function */ #define SBI_PMU_STOP_FLAG_RESET (1 << 0) +/* SBI function IDs for DBCN extension */ +#define SBI_EXT_DBCN_CONSOLE_WRITE 0x0 +#define SBI_EXT_DBCN_CONSOLE_READ 0x1 +#define SBI_EXT_DBCN_CONSOLE_WRITE_BYTE 0x2 + +/* SBI function IDs for SUSP extension */ +#define SBI_EXT_SUSP_SUSPEND 0x0 + +#define SBI_SUSP_SLEEP_TYPE_SUSPEND 0x0 +#define SBI_SUSP_SLEEP_TYPE_LAST SBI_SUSP_SLEEP_TYPE_SUSPEND +#define SBI_SUSP_PLATFORM_SLEEP_START 0x80000000 + +/* SBI function IDs for CPPC extension */ +#define SBI_EXT_CPPC_PROBE 0x0 +#define SBI_EXT_CPPC_READ 0x1 +#define SBI_EXT_CPPC_READ_HI 0x2 +#define SBI_EXT_CPPC_WRITE 0x3 + +enum sbi_cppc_reg_id { + SBI_CPPC_HIGHEST_PERF = 0x00000000, + SBI_CPPC_NOMINAL_PERF = 0x00000001, + SBI_CPPC_LOW_NON_LINEAR_PERF = 0x00000002, + SBI_CPPC_LOWEST_PERF = 0x00000003, + SBI_CPPC_GUARANTEED_PERF = 0x00000004, + SBI_CPPC_DESIRED_PERF = 0x00000005, + SBI_CPPC_MIN_PERF = 0x00000006, + SBI_CPPC_MAX_PERF = 0x00000007, + SBI_CPPC_PERF_REDUC_TOLERANCE = 0x00000008, + SBI_CPPC_TIME_WINDOW = 0x00000009, + SBI_CPPC_CTR_WRAP_TIME = 0x0000000A, + SBI_CPPC_REFERENCE_CTR = 0x0000000B, + SBI_CPPC_DELIVERED_CTR = 0x0000000C, + SBI_CPPC_PERF_LIMITED = 0x0000000D, + SBI_CPPC_ENABLE = 0x0000000E, + SBI_CPPC_AUTO_SEL_ENABLE = 0x0000000F, + SBI_CPPC_AUTO_ACT_WINDOW = 0x00000010, + SBI_CPPC_ENERGY_PERF_PREFERENCE = 0x00000011, + SBI_CPPC_REFERENCE_PERF = 0x00000012, + SBI_CPPC_LOWEST_FREQ = 0x00000013, + SBI_CPPC_NOMINAL_FREQ = 0x00000014, + SBI_CPPC_ACPI_LAST = SBI_CPPC_NOMINAL_FREQ, + SBI_CPPC_TRANSITION_LATENCY = 0x80000000, + SBI_CPPC_NON_ACPI_LAST = SBI_CPPC_TRANSITION_LATENCY, +}; + /* SBI base specification related macros */ #define SBI_SPEC_VERSION_MAJOR_OFFSET 24 #define SBI_SPEC_VERSION_MAJOR_MASK 0x7f diff -Nru opensbi-1.1/include/sbi/sbi_hart.h opensbi-1.3/include/sbi/sbi_hart.h --- opensbi-1.1/include/sbi/sbi_hart.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi/sbi_hart.h 2023-06-23 07:31:49.000000000 +0200 @@ -30,8 +30,8 @@ SBI_HART_EXT_SSCOFPMF = 0, /** HART has HW time CSR (extension name not available) */ SBI_HART_EXT_TIME, - /** HART has AIA CSRs (extension name not available) */ - SBI_HART_EXT_AIA, + /** HART has AIA M-mode CSRs */ + SBI_HART_EXT_SMAIA, /** HART has Smstateen CSR **/ SBI_HART_EXT_SMSTATEEN, /** HART has Sstc extension */ @@ -41,6 +41,17 @@ SBI_HART_EXT_MAX, }; +struct sbi_hart_features { + bool detected; + int priv_version; + unsigned long extensions; + unsigned int pmp_count; + unsigned int pmp_addr_bits; + unsigned long pmp_gran; + unsigned int mhpm_count; + unsigned int mhpm_bits; +}; + struct sbi_scratch; int sbi_hart_reinit(struct sbi_scratch *scratch); diff -Nru opensbi-1.1/include/sbi/sbi_heap.h opensbi-1.3/include/sbi/sbi_heap.h --- opensbi-1.1/include/sbi/sbi_heap.h 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/include/sbi/sbi_heap.h 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,44 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Ventana Micro Systems Inc. + * + * Authors: + * Anup Patel + */ + +#ifndef __SBI_HEAP_H__ +#define __SBI_HEAP_H__ + +#include + +struct sbi_scratch; + +/** Allocate from heap area */ +void *sbi_malloc(size_t size); + +/** Zero allocate from heap area */ +void *sbi_zalloc(size_t size); + +/** Allocate array from heap area */ +static inline void *sbi_calloc(size_t nitems, size_t size) +{ + return sbi_zalloc(nitems * size); +} + +/** Free-up to heap area */ +void sbi_free(void *ptr); + +/** Amount (in bytes) of free space in the heap area */ +unsigned long sbi_heap_free_space(void); + +/** Amount (in bytes) of used space in the heap area */ +unsigned long sbi_heap_used_space(void); + +/** Amount (in bytes) of reserved space in the heap area */ +unsigned long sbi_heap_reserved_space(void); + +/** Initialize heap area */ +int sbi_heap_init(struct sbi_scratch *scratch); + +#endif diff -Nru opensbi-1.1/include/sbi/sbi_hsm.h opensbi-1.3/include/sbi/sbi_hsm.h --- opensbi-1.1/include/sbi/sbi_hsm.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi/sbi_hsm.h 2023-06-23 07:31:49.000000000 +0200 @@ -21,8 +21,12 @@ int (*hart_start)(u32 hartid, ulong saddr); /** - * Stop (or power-down) the current hart from running. This call - * doesn't expect to return if success. + * Stop (or power-down) the current hart from running. + * + * Return SBI_ENOTSUPP if the hart does not support platform-specific + * stop actions. + * + * For successful stop, the call won't return. */ int (*hart_stop)(void); @@ -59,15 +63,21 @@ int sbi_hsm_hart_start(struct sbi_scratch *scratch, const struct sbi_domain *dom, - u32 hartid, ulong saddr, ulong smode, ulong priv); + u32 hartid, ulong saddr, ulong smode, ulong arg1); int sbi_hsm_hart_stop(struct sbi_scratch *scratch, bool exitnow); void sbi_hsm_hart_resume_start(struct sbi_scratch *scratch); -void sbi_hsm_hart_resume_finish(struct sbi_scratch *scratch); +void __noreturn sbi_hsm_hart_resume_finish(struct sbi_scratch *scratch, + u32 hartid); int sbi_hsm_hart_suspend(struct sbi_scratch *scratch, u32 suspend_type, - ulong raddr, ulong rmode, ulong priv); + ulong raddr, ulong rmode, ulong arg1); +bool sbi_hsm_hart_change_state(struct sbi_scratch *scratch, long oldstate, + long newstate); +int __sbi_hsm_hart_get_state(u32 hartid); int sbi_hsm_hart_get_state(const struct sbi_domain *dom, u32 hartid); int sbi_hsm_hart_interruptible_mask(const struct sbi_domain *dom, ulong hbase, ulong *out_hmask); -void sbi_hsm_prepare_next_jump(struct sbi_scratch *scratch, u32 hartid); +void __sbi_hsm_suspend_non_ret_save(struct sbi_scratch *scratch); +void __noreturn sbi_hsm_hart_start_finish(struct sbi_scratch *scratch, + u32 hartid); #endif diff -Nru opensbi-1.1/include/sbi/sbi_init.h opensbi-1.3/include/sbi/sbi_init.h --- opensbi-1.1/include/sbi/sbi_init.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi/sbi_init.h 2023-06-23 07:31:49.000000000 +0200 @@ -16,6 +16,8 @@ void __noreturn sbi_init(struct sbi_scratch *scratch); +unsigned long sbi_entry_count(u32 hartid); + unsigned long sbi_init_count(u32 hartid); void __noreturn sbi_exit(struct sbi_scratch *scratch); diff -Nru opensbi-1.1/include/sbi/sbi_ipi.h opensbi-1.3/include/sbi/sbi_ipi.h --- opensbi-1.1/include/sbi/sbi_ipi.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi/sbi_ipi.h 2023-06-23 07:31:49.000000000 +0200 @@ -30,6 +30,12 @@ void (*ipi_clear)(u32 target_hart); }; +enum sbi_ipi_update_type { + SBI_IPI_UPDATE_SUCCESS, + SBI_IPI_UPDATE_BREAK, + SBI_IPI_UPDATE_RETRY, +}; + struct sbi_scratch; /** IPI event operations or callbacks */ @@ -41,6 +47,10 @@ * Update callback to save/enqueue data for remote HART * Note: This is an optional callback and it is called just before * triggering IPI to remote HART. + * @return < 0, error or failure + * @return SBI_IPI_UPDATE_SUCCESS, success + * @return SBI_IPI_UPDATE_BREAK, break IPI, done on local hart + * @return SBI_IPI_UPDATE_RETRY, need retry */ int (* update)(struct sbi_scratch *scratch, struct sbi_scratch *remote_scratch, @@ -75,7 +85,9 @@ void sbi_ipi_process(void); -void sbi_ipi_raw_send(u32 target_hart); +int sbi_ipi_raw_send(u32 target_hart); + +void sbi_ipi_raw_clear(u32 target_hart); const struct sbi_ipi_device *sbi_ipi_get_device(void); diff -Nru opensbi-1.1/include/sbi/sbi_list.h opensbi-1.3/include/sbi/sbi_list.h --- opensbi-1.1/include/sbi/sbi_list.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi/sbi_list.h 2023-06-23 07:31:49.000000000 +0200 @@ -31,7 +31,7 @@ #define SBI_INIT_LIST_HEAD(ptr) \ do { \ (ptr)->next = ptr; (ptr)->prev = ptr; \ -} while (0); +} while (0) static inline void __sbi_list_add(struct sbi_dlist *new, struct sbi_dlist *prev, @@ -47,7 +47,7 @@ * Checks if the list is empty or not. * @param head List head * - * Retruns TRUE if list is empty, FALSE otherwise. + * Returns true if list is empty, false otherwise. */ static inline bool sbi_list_empty(struct sbi_dlist *head) { diff -Nru opensbi-1.1/include/sbi/sbi_platform.h opensbi-1.3/include/sbi/sbi_platform.h --- opensbi-1.1/include/sbi/sbi_platform.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi/sbi_platform.h 2023-06-23 07:31:49.000000000 +0200 @@ -29,12 +29,16 @@ #define SBI_PLATFORM_HART_COUNT_OFFSET (0x50) /** Offset of hart_stack_size in struct sbi_platform */ #define SBI_PLATFORM_HART_STACK_SIZE_OFFSET (0x54) +/** Offset of heap_size in struct sbi_platform */ +#define SBI_PLATFORM_HEAP_SIZE_OFFSET (0x58) +/** Offset of reserved in struct sbi_platform */ +#define SBI_PLATFORM_RESERVED_OFFSET (0x5c) /** Offset of platform_ops_addr in struct sbi_platform */ -#define SBI_PLATFORM_OPS_OFFSET (0x58) +#define SBI_PLATFORM_OPS_OFFSET (0x60) /** Offset of firmware_context in struct sbi_platform */ -#define SBI_PLATFORM_FIRMWARE_CONTEXT_OFFSET (0x58 + __SIZEOF_POINTER__) +#define SBI_PLATFORM_FIRMWARE_CONTEXT_OFFSET (0x60 + __SIZEOF_POINTER__) /** Offset of hart_index2id in struct sbi_platform */ -#define SBI_PLATFORM_HART_INDEX2ID_OFFSET (0x58 + (__SIZEOF_POINTER__ * 2)) +#define SBI_PLATFORM_HART_INDEX2ID_OFFSET (0x60 + (__SIZEOF_POINTER__ * 2)) #define SBI_PLATFORM_TLB_RANGE_FLUSH_LIMIT_DEFAULT (1UL << 12) @@ -48,6 +52,7 @@ struct sbi_domain_memregion; struct sbi_trap_info; struct sbi_trap_regs; +struct sbi_hart_features; /** Possible feature flags of a platform */ enum sbi_platform_features { @@ -64,6 +69,9 @@ /** Platform functions */ struct sbi_platform_operations { + /* Check if specified HART is allowed to do cold boot */ + bool (*cold_boot_allowed)(u32 hartid); + /* Platform nascent initialization */ int (*nascent_init)(void); @@ -90,7 +98,7 @@ int (*misa_get_xlen)(void); /** Initialize (or populate) HART extensions for the platform */ - int (*extensions_init)(void); + int (*extensions_init)(struct sbi_hart_features *hfeatures); /** Initialize (or populate) domains for the platform */ int (*domains_init)(void); @@ -122,10 +130,10 @@ /** Exit platform timer for current HART */ void (*timer_exit)(void); - /** platform specific SBI extension implementation probe function */ - int (*vendor_ext_check)(long extid); + /** Check if SBI vendor extension is implemented or not */ + bool (*vendor_ext_check)(void); /** platform specific SBI extension implementation provider */ - int (*vendor_ext_provider)(long extid, long funcid, + int (*vendor_ext_provider)(long funcid, const struct sbi_trap_regs *regs, unsigned long *out_value, struct sbi_trap_info *out_trap); @@ -134,6 +142,10 @@ /** Platform default per-HART stack size for exception/interrupt handling */ #define SBI_PLATFORM_DEFAULT_HART_STACK_SIZE 8192 +/** Platform default heap size */ +#define SBI_PLATFORM_DEFAULT_HEAP_SIZE(__num_hart) \ + (0x8000 + 0x800 * (__num_hart)) + /** Representation of a platform */ struct sbi_platform { /** @@ -156,6 +168,10 @@ u32 hart_count; /** Per-HART stack size for exception/interrupt handling */ u32 hart_stack_size; + /** Size of heap shared by all HARTs */ + u32 heap_size; + /** Reserved for future use */ + u32 reserved; /** Pointer to sbi platform operations */ unsigned long platform_ops_addr; /** Pointer to system firmware specific context */ @@ -343,16 +359,33 @@ * @param plat pointer to struct sbi_platform * @param hartid HART ID * - * @return TRUE if HART is invalid and FALSE otherwise + * @return true if HART is invalid and false otherwise */ static inline bool sbi_platform_hart_invalid(const struct sbi_platform *plat, u32 hartid) { if (!plat) - return TRUE; + return true; if (plat->hart_count <= sbi_platform_hart_index(plat, hartid)) - return TRUE; - return FALSE; + return true; + return false; +} + +/** + * Check whether given HART is allowed to do cold boot + * + * @param plat pointer to struct sbi_platform + * @param hartid HART ID + * + * @return true if HART is allowed to do cold boot and false otherwise + */ +static inline bool sbi_platform_cold_boot_allowed( + const struct sbi_platform *plat, + u32 hartid) +{ + if (plat && sbi_platform_ops(plat)->cold_boot_allowed) + return sbi_platform_ops(plat)->cold_boot_allowed(hartid); + return true; } /** @@ -376,7 +409,7 @@ * Early initialization for current HART * * @param plat pointer to struct sbi_platform - * @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE) + * @param cold_boot whether cold boot (true) or warm_boot (false) * * @return 0 on success and negative error code on failure */ @@ -392,7 +425,7 @@ * Final initialization for current HART * * @param plat pointer to struct sbi_platform - * @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE) + * @param cold_boot whether cold boot (true) or warm_boot (false) * * @return 0 on success and negative error code on failure */ @@ -464,10 +497,11 @@ * @return 0 on success and negative error code on failure */ static inline int sbi_platform_extensions_init( - const struct sbi_platform *plat) + const struct sbi_platform *plat, + struct sbi_hart_features *hfeatures) { if (plat && sbi_platform_ops(plat)->extensions_init) - return sbi_platform_ops(plat)->extensions_init(); + return sbi_platform_ops(plat)->extensions_init(hfeatures); return 0; } @@ -536,7 +570,7 @@ * Initialize the platform interrupt controller for current HART * * @param plat pointer to struct sbi_platform - * @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE) + * @param cold_boot whether cold boot (true) or warm_boot (false) * * @return 0 on success and negative error code on failure */ @@ -563,7 +597,7 @@ * Initialize the platform IPI support for current HART * * @param plat pointer to struct sbi_platform - * @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE) + * @param cold_boot whether cold boot (true) or warm_boot (false) * * @return 0 on success and negative error code on failure */ @@ -590,7 +624,7 @@ * Initialize the platform timer for current HART * * @param plat pointer to struct sbi_platform - * @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE) + * @param cold_boot whether cold boot (true) or warm_boot (false) * * @return 0 on success and negative error code on failure */ @@ -614,27 +648,25 @@ } /** - * Check if a vendor extension is implemented or not. + * Check if SBI vendor extension is implemented or not. * * @param plat pointer to struct sbi_platform - * @param extid vendor SBI extension id * - * @return 0 if extid is not implemented and 1 if implemented + * @return false if not implemented and true if implemented */ -static inline int sbi_platform_vendor_ext_check(const struct sbi_platform *plat, - long extid) +static inline bool sbi_platform_vendor_ext_check( + const struct sbi_platform *plat) { if (plat && sbi_platform_ops(plat)->vendor_ext_check) - return sbi_platform_ops(plat)->vendor_ext_check(extid); + return sbi_platform_ops(plat)->vendor_ext_check(); - return 0; + return false; } /** * Invoke platform specific vendor SBI extension implementation. * * @param plat pointer to struct sbi_platform - * @param extid vendor SBI extension id * @param funcid SBI function id within the extension id * @param regs pointer to trap registers passed by the caller * @param out_value output value that can be filled by the callee @@ -644,14 +676,14 @@ */ static inline int sbi_platform_vendor_ext_provider( const struct sbi_platform *plat, - long extid, long funcid, + long funcid, const struct sbi_trap_regs *regs, unsigned long *out_value, struct sbi_trap_info *out_trap) { if (plat && sbi_platform_ops(plat)->vendor_ext_provider) { - return sbi_platform_ops(plat)->vendor_ext_provider(extid, - funcid, regs, + return sbi_platform_ops(plat)->vendor_ext_provider(funcid, + regs, out_value, out_trap); } diff -Nru opensbi-1.1/include/sbi/sbi_pmu.h opensbi-1.3/include/sbi/sbi_pmu.h --- opensbi-1.1/include/sbi/sbi_pmu.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi/sbi_pmu.h 2023-06-23 07:31:49.000000000 +0200 @@ -11,29 +11,101 @@ #define __SBI_PMU_H__ #include -#include -#include -#include + +struct sbi_scratch; /* Event related macros */ /* Maximum number of hardware events that can mapped by OpenSBI */ #define SBI_PMU_HW_EVENT_MAX 256 -/* Maximum number of firmware events that can mapped by OpenSBI */ -#define SBI_PMU_FW_EVENT_MAX 32 - /* Counter related macros */ #define SBI_PMU_FW_CTR_MAX 16 #define SBI_PMU_HW_CTR_MAX 32 #define SBI_PMU_CTR_MAX (SBI_PMU_HW_CTR_MAX + SBI_PMU_FW_CTR_MAX) #define SBI_PMU_FIXED_CTR_MASK 0x07 +struct sbi_pmu_device { + /** Name of the PMU platform device */ + char name[32]; + + /** + * Validate event code of custom firmware event + */ + int (*fw_event_validate_encoding)(uint32_t hartid, uint64_t event_data); + + /** + * Match custom firmware counter with custom firmware event + * Note: 0 <= counter_index < SBI_PMU_FW_CTR_MAX + */ + bool (*fw_counter_match_encoding)(uint32_t hartid, + uint32_t counter_index, + uint64_t event_data); + + /** + * Fetch the max width of this counter in number of bits. + */ + int (*fw_counter_width)(void); + + /** + * Read value of custom firmware counter + * Note: 0 <= counter_index < SBI_PMU_FW_CTR_MAX + */ + uint64_t (*fw_counter_read_value)(uint32_t hartid, + uint32_t counter_index); + + /** + * Write value to custom firmware counter + * Note: 0 <= counter_index < SBI_PMU_FW_CTR_MAX + */ + void (*fw_counter_write_value)(uint32_t hartid, uint32_t counter_index, + uint64_t value); + + /** + * Start custom firmware counter + * Note: 0 <= counter_index < SBI_PMU_FW_CTR_MAX + */ + int (*fw_counter_start)(uint32_t hartid, uint32_t counter_index, + uint64_t event_data); + + /** + * Stop custom firmware counter + * Note: 0 <= counter_index < SBI_PMU_FW_CTR_MAX + */ + int (*fw_counter_stop)(uint32_t hartid, uint32_t counter_index); + + /** + * Custom enable irq for hardware counter + * Note: 0 <= counter_index < SBI_PMU_HW_CTR_MAX + */ + void (*hw_counter_enable_irq)(uint32_t counter_index); + + /** + * Custom disable irq for hardware counter + * Note: 0 <= counter_index < SBI_PMU_HW_CTR_MAX + */ + void (*hw_counter_disable_irq)(uint32_t counter_index); + + /** + * Custom function returning the machine-specific irq-bit. + */ + int (*hw_counter_irq_bit)(void); +}; + +/** Get the PMU platform device */ +const struct sbi_pmu_device *sbi_pmu_get_device(void); + +/** Set the PMU platform device */ +void sbi_pmu_set_device(const struct sbi_pmu_device *dev); + /** Initialize PMU */ int sbi_pmu_init(struct sbi_scratch *scratch, bool cold_boot); /** Reset PMU during hart exit */ void sbi_pmu_exit(struct sbi_scratch *scratch); +/** Return the pmu irq bit depending on extension existence */ +int sbi_pmu_irq_bit(void); + /** * Add the hardware event to counter mapping information. This should be called * from the platform code to update the mapping table. @@ -53,7 +125,7 @@ int sbi_pmu_add_raw_event_counter_map(uint64_t select, uint64_t select_mask, u32 cmap); -int sbi_pmu_ctr_read(uint32_t cidx, unsigned long *cval); +int sbi_pmu_ctr_fw_read(uint32_t cidx, uint64_t *cval); int sbi_pmu_ctr_stop(unsigned long cidx_base, unsigned long cidx_mask, unsigned long flag); diff -Nru opensbi-1.1/include/sbi/sbi_scratch.h opensbi-1.3/include/sbi/sbi_scratch.h --- opensbi-1.1/include/sbi/sbi_scratch.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi/sbi_scratch.h 2023-06-23 07:31:49.000000000 +0200 @@ -18,26 +18,32 @@ #define SBI_SCRATCH_FW_START_OFFSET (0 * __SIZEOF_POINTER__) /** Offset of fw_size member in sbi_scratch */ #define SBI_SCRATCH_FW_SIZE_OFFSET (1 * __SIZEOF_POINTER__) +/** Offset (in sbi_scratch) of the R/W Offset */ +#define SBI_SCRATCH_FW_RW_OFFSET (2 * __SIZEOF_POINTER__) +/** Offset of fw_heap_offset member in sbi_scratch */ +#define SBI_SCRATCH_FW_HEAP_OFFSET (3 * __SIZEOF_POINTER__) +/** Offset of fw_heap_size_offset member in sbi_scratch */ +#define SBI_SCRATCH_FW_HEAP_SIZE_OFFSET (4 * __SIZEOF_POINTER__) /** Offset of next_arg1 member in sbi_scratch */ -#define SBI_SCRATCH_NEXT_ARG1_OFFSET (2 * __SIZEOF_POINTER__) +#define SBI_SCRATCH_NEXT_ARG1_OFFSET (5 * __SIZEOF_POINTER__) /** Offset of next_addr member in sbi_scratch */ -#define SBI_SCRATCH_NEXT_ADDR_OFFSET (3 * __SIZEOF_POINTER__) +#define SBI_SCRATCH_NEXT_ADDR_OFFSET (6 * __SIZEOF_POINTER__) /** Offset of next_mode member in sbi_scratch */ -#define SBI_SCRATCH_NEXT_MODE_OFFSET (4 * __SIZEOF_POINTER__) +#define SBI_SCRATCH_NEXT_MODE_OFFSET (7 * __SIZEOF_POINTER__) /** Offset of warmboot_addr member in sbi_scratch */ -#define SBI_SCRATCH_WARMBOOT_ADDR_OFFSET (5 * __SIZEOF_POINTER__) +#define SBI_SCRATCH_WARMBOOT_ADDR_OFFSET (8 * __SIZEOF_POINTER__) /** Offset of platform_addr member in sbi_scratch */ -#define SBI_SCRATCH_PLATFORM_ADDR_OFFSET (6 * __SIZEOF_POINTER__) +#define SBI_SCRATCH_PLATFORM_ADDR_OFFSET (9 * __SIZEOF_POINTER__) /** Offset of hartid_to_scratch member in sbi_scratch */ -#define SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET (7 * __SIZEOF_POINTER__) +#define SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET (10 * __SIZEOF_POINTER__) /** Offset of trap_exit member in sbi_scratch */ -#define SBI_SCRATCH_TRAP_EXIT_OFFSET (8 * __SIZEOF_POINTER__) +#define SBI_SCRATCH_TRAP_EXIT_OFFSET (11 * __SIZEOF_POINTER__) /** Offset of tmp0 member in sbi_scratch */ -#define SBI_SCRATCH_TMP0_OFFSET (9 * __SIZEOF_POINTER__) +#define SBI_SCRATCH_TMP0_OFFSET (12 * __SIZEOF_POINTER__) /** Offset of options member in sbi_scratch */ -#define SBI_SCRATCH_OPTIONS_OFFSET (10 * __SIZEOF_POINTER__) +#define SBI_SCRATCH_OPTIONS_OFFSET (13 * __SIZEOF_POINTER__) /** Offset of extra space in sbi_scratch */ -#define SBI_SCRATCH_EXTRA_SPACE_OFFSET (11 * __SIZEOF_POINTER__) +#define SBI_SCRATCH_EXTRA_SPACE_OFFSET (14 * __SIZEOF_POINTER__) /** Maximum size of sbi_scratch (4KB) */ #define SBI_SCRATCH_SIZE (0x1000) @@ -53,11 +59,17 @@ unsigned long fw_start; /** Size (in bytes) of firmware linked to OpenSBI library */ unsigned long fw_size; + /** Offset (in bytes) of the R/W section */ + unsigned long fw_rw_offset; + /** Offset (in bytes) of the heap area */ + unsigned long fw_heap_offset; + /** Size (in bytes) of the heap area */ + unsigned long fw_heap_size; /** Arg1 (or 'a1' register) of next booting stage for this HART */ unsigned long next_arg1; /** Address of next booting stage for this HART */ unsigned long next_addr; - /** Priviledge mode of next booting stage for this HART */ + /** Privilege mode of next booting stage for this HART */ unsigned long next_mode; /** Warm boot entry point address for this HART */ unsigned long warmboot_addr; @@ -163,6 +175,9 @@ /** Free-up extra space in sbi_scratch */ void sbi_scratch_free_offset(unsigned long offset); +/** Amount (in bytes) of used space in in sbi_scratch */ +unsigned long sbi_scratch_used_space(void); + /** Get pointer from offset in sbi_scratch */ #define sbi_scratch_offset_ptr(scratch, offset) (void *)((char *)(scratch) + (offset)) @@ -170,6 +185,23 @@ #define sbi_scratch_thishart_offset_ptr(offset) \ (void *)((char *)sbi_scratch_thishart_ptr() + (offset)) +/** Allocate offset for a data type in sbi_scratch */ +#define sbi_scratch_alloc_type_offset(__type) \ + sbi_scratch_alloc_offset(sizeof(__type)) + +/** Read a data type from sbi_scratch at given offset */ +#define sbi_scratch_read_type(__scratch, __type, __offset) \ +({ \ + *((__type *)sbi_scratch_offset_ptr((__scratch), (__offset))); \ +}) + +/** Write a data type to sbi_scratch at given offset */ +#define sbi_scratch_write_type(__scratch, __type, __offset, __ptr) \ +do { \ + *((__type *)sbi_scratch_offset_ptr((__scratch), (__offset))) \ + = (__type)(__ptr); \ +} while (0) + /** HART id to scratch table */ extern struct sbi_scratch *hartid_to_scratch_table[]; diff -Nru opensbi-1.1/include/sbi/sbi_system.h opensbi-1.3/include/sbi/sbi_system.h --- opensbi-1.1/include/sbi/sbi_system.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi/sbi_system.h 2023-06-23 07:31:49.000000000 +0200 @@ -43,4 +43,38 @@ void __noreturn sbi_system_reset(u32 reset_type, u32 reset_reason); +/** System suspend device */ +struct sbi_system_suspend_device { + /** Name of the system suspend device */ + char name[32]; + + /** + * Check whether sleep type is supported by the device + * + * Returns 0 when @sleep_type supported, SBI_ERR_INVALID_PARAM + * when @sleep_type is reserved, or SBI_ERR_NOT_SUPPORTED when + * @sleep_type is not reserved and is implemented, but the + * platform doesn't support it due to missing dependencies. + */ + int (*system_suspend_check)(u32 sleep_type); + + /** + * Suspend the system + * + * @sleep_type: The sleep type identifier passed to the SBI call. + * @mmode_resume_addr: + * This is the same as sbi_scratch.warmboot_addr. Some platforms + * may not be able to return from system_suspend(), so they will + * jump directly to this address instead. Platforms which can + * return from system_suspend() may ignore this parameter. + */ + int (*system_suspend)(u32 sleep_type, unsigned long mmode_resume_addr); +}; + +const struct sbi_system_suspend_device *sbi_system_suspend_get_device(void); +void sbi_system_suspend_set_device(struct sbi_system_suspend_device *dev); +void sbi_system_suspend_test_enable(void); +bool sbi_system_suspend_supported(u32 sleep_type); +int sbi_system_suspend(u32 sleep_type, ulong resume_addr, ulong opaque); + #endif diff -Nru opensbi-1.1/include/sbi/sbi_timer.h opensbi-1.3/include/sbi/sbi_timer.h --- opensbi-1.1/include/sbi/sbi_timer.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi/sbi_timer.h 2023-06-23 07:31:49.000000000 +0200 @@ -48,6 +48,24 @@ sbi_timer_delay_loop(usecs, 1000000, NULL, NULL); } +/** + * A blocking function that will wait until @p predicate returns true or + * @p timeout_ms milliseconds elapsed. @p arg will be passed as argument to + * @p predicate function. + * + * @param predicate Pointer to a function that returns true if certain + * condition is met. It shouldn't block the code execution. + * @param arg Argument to pass to @p predicate. + * @param timeout_ms Timeout value in milliseconds. The function will return + * false if @p timeout_ms time period elapsed but still @p predicate doesn't + * return true. + * + * @return true if @p predicate returns true within @p timeout_ms, false + * otherwise. + */ +bool sbi_timer_waitms_until(bool (*predicate)(void *), void *arg, + uint64_t timeout_ms); + /** Get timer value for current HART */ u64 sbi_timer_value(void); diff -Nru opensbi-1.1/include/sbi/sbi_trap.h opensbi-1.3/include/sbi/sbi_trap.h --- opensbi-1.1/include/sbi/sbi_trap.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi/sbi_trap.h 2023-06-23 07:31:49.000000000 +0200 @@ -10,6 +10,8 @@ #ifndef __SBI_TRAP_H__ #define __SBI_TRAP_H__ +#include + /* clang-format off */ /** Index of zero member in sbi_trap_regs */ @@ -95,8 +97,10 @@ #define SBI_TRAP_INFO_tval2 3 /** Index of tinst member in sbi_trap_info */ #define SBI_TRAP_INFO_tinst 4 +/** Index of gva member in sbi_trap_info */ +#define SBI_TRAP_INFO_gva 5 /** Last member index in sbi_trap_info */ -#define SBI_TRAP_INFO_last 5 +#define SBI_TRAP_INFO_last 6 /* clang-format on */ @@ -200,8 +204,26 @@ unsigned long tval2; /** tinst Trap instruction */ unsigned long tinst; + /** gva Guest virtual address in tval flag */ + unsigned long gva; }; +static inline unsigned long sbi_regs_gva(const struct sbi_trap_regs *regs) +{ + /* + * If the hypervisor extension is not implemented, mstatus[h].GVA is a + * WPRI field, which is guaranteed to read as zero. In addition, in this + * case we don't read mstatush and instead pretend it is zero, which + * handles privileged spec version < 1.12. + */ + +#if __riscv_xlen == 32 + return (regs->mstatusH & MSTATUSH_GVA) ? 1 : 0; +#else + return (regs->mstatus & MSTATUS_GVA) ? 1 : 0; +#endif +} + int sbi_trap_redirect(struct sbi_trap_regs *regs, struct sbi_trap_info *trap); diff -Nru opensbi-1.1/include/sbi/sbi_types.h opensbi-1.3/include/sbi/sbi_types.h --- opensbi-1.1/include/sbi/sbi_types.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi/sbi_types.h 2023-06-23 07:31:49.000000000 +0200 @@ -54,16 +54,22 @@ typedef unsigned long physical_addr_t; typedef unsigned long physical_size_t; -#define TRUE 1 -#define FALSE 0 -#define true TRUE -#define false FALSE +typedef uint16_t le16_t; +typedef uint16_t be16_t; +typedef uint32_t le32_t; +typedef uint32_t be32_t; +typedef uint64_t le64_t; +typedef uint64_t be64_t; + +#define true 1 +#define false 0 #define NULL ((void *)0) #define __packed __attribute__((packed)) #define __noreturn __attribute__((noreturn)) #define __aligned(x) __attribute__((aligned(x))) +#define __always_inline inline __attribute__((always_inline)) #define likely(x) __builtin_expect((x), 1) #define unlikely(x) __builtin_expect((x), 0) diff -Nru opensbi-1.1/include/sbi/sbi_version.h opensbi-1.3/include/sbi/sbi_version.h --- opensbi-1.1/include/sbi/sbi_version.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi/sbi_version.h 2023-06-23 07:31:49.000000000 +0200 @@ -11,7 +11,7 @@ #define __SBI_VERSION_H__ #define OPENSBI_VERSION_MAJOR 1 -#define OPENSBI_VERSION_MINOR 1 +#define OPENSBI_VERSION_MINOR 3 /** * OpenSBI 32-bit version with: diff -Nru opensbi-1.1/include/sbi_utils/fdt/fdt_domain.h opensbi-1.3/include/sbi_utils/fdt/fdt_domain.h --- opensbi-1.1/include/sbi_utils/fdt/fdt_domain.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi_utils/fdt/fdt_domain.h 2023-06-23 07:31:49.000000000 +0200 @@ -13,6 +13,8 @@ #include +#ifdef CONFIG_FDT_DOMAIN + struct sbi_domain; /** @@ -70,4 +72,11 @@ */ int fdt_domains_populate(void *fdt); +#else + +static inline void fdt_domain_fixup(void *fdt) { } +static inline int fdt_domains_populate(void *fdt) { return 0; } + +#endif + #endif /* __FDT_DOMAIN_H__ */ diff -Nru opensbi-1.1/include/sbi_utils/fdt/fdt_fixup.h opensbi-1.3/include/sbi_utils/fdt/fdt_fixup.h --- opensbi-1.1/include/sbi_utils/fdt/fdt_fixup.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi_utils/fdt/fdt_fixup.h 2023-06-23 07:31:49.000000000 +0200 @@ -9,6 +9,29 @@ #ifndef __FDT_FIXUP_H__ #define __FDT_FIXUP_H__ +struct sbi_cpu_idle_state { + const char *name; + uint32_t suspend_param; + bool local_timer_stop; + uint32_t entry_latency_us; + uint32_t exit_latency_us; + uint32_t min_residency_us; + uint32_t wakeup_latency_us; +}; + +/** + * Add CPU idle states to cpu nodes in the DT + * + * Add information about CPU idle states to the devicetree. This function + * assumes that CPU idle states are not already present in the devicetree, and + * that all CPU states are equally applicable to all CPUs. + * + * @param fdt: device tree blob + * @param states: array of idle state descriptions, ending with empty element + * @return zero on success and -ve on failure + */ +int fdt_add_cpu_idle_states(void *dtb, const struct sbi_cpu_idle_state *state); + /** * Fix up the CPU node in the device tree * @@ -71,20 +94,6 @@ int fdt_reserved_memory_fixup(void *fdt); /** - * Fix up the reserved memory subnodes in the device tree - * - * This routine adds the no-map property to the reserved memory subnodes so - * that the OS does not map those PMP protected memory regions. - * - * Platform codes must call this helper in their final_init() after fdt_fixups() - * if the OS should not map the PMP protected reserved regions. - * - * @param fdt: device tree blob - * @return zero on success and -ve on failure - */ -int fdt_reserved_memory_nomap_fixup(void *fdt); - -/** * General device tree fix-up * * This routine do all required device tree fix-ups for a typical platform. diff -Nru opensbi-1.1/include/sbi_utils/fdt/fdt_helper.h opensbi-1.3/include/sbi_utils/fdt/fdt_helper.h --- opensbi-1.1/include/sbi_utils/fdt/fdt_helper.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi_utils/fdt/fdt_helper.h 2023-06-23 07:31:49.000000000 +0200 @@ -11,7 +11,7 @@ #define __FDT_HELPER_H__ #include -#include +#include struct fdt_match { const char *compatible; @@ -59,14 +59,17 @@ int fdt_parse_gaisler_uart_node(void *fdt, int nodeoffset, struct platform_uart_data *uart); +int fdt_parse_renesas_scif_node(void *fdt, int nodeoffset, + struct platform_uart_data *uart); + int fdt_parse_shakti_uart_node(void *fdt, int nodeoffset, struct platform_uart_data *uart); int fdt_parse_sifive_uart_node(void *fdt, int nodeoffset, struct platform_uart_data *uart); -int fdt_parse_uart8250_node(void *fdt, int nodeoffset, - struct platform_uart_data *uart); +int fdt_parse_uart_node(void *fdt, int nodeoffset, + struct platform_uart_data *uart); int fdt_parse_uart8250(void *fdt, struct platform_uart_data *uart, const char *compatible); @@ -95,12 +98,18 @@ unsigned long *out_addr2, unsigned long *out_size2, u32 *out_first_hartid, u32 *out_hart_count); +int fdt_parse_plmt_node(void *fdt, int nodeoffset, unsigned long *plmt_base, + unsigned long *plmt_size, u32 *hart_count); + +int fdt_parse_plicsw_node(void *fdt, int nodeoffset, unsigned long *plicsw_base, + unsigned long *size, u32 *hart_count); + int fdt_parse_compat_addr(void *fdt, uint64_t *addr, const char *compatible); static inline void *fdt_get_address(void) { - return sbi_scratch_thishart_arg1_ptr(); + return (void *)root.next_arg1; } #endif /* __FDT_HELPER_H__ */ diff -Nru opensbi-1.1/include/sbi_utils/fdt/fdt_pmu.h opensbi-1.3/include/sbi_utils/fdt/fdt_pmu.h --- opensbi-1.1/include/sbi_utils/fdt/fdt_pmu.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi_utils/fdt/fdt_pmu.h 2023-06-23 07:31:49.000000000 +0200 @@ -13,6 +13,8 @@ #include +#ifdef CONFIG_FDT_PMU + /** * Fix up the PMU node in the device tree * @@ -43,4 +45,12 @@ */ uint64_t fdt_pmu_get_select_value(uint32_t event_idx); +#else + +static inline void fdt_pmu_fixup(void *fdt) { } +static inline int fdt_pmu_setup(void *fdt) { return 0; } +static inline uint64_t fdt_pmu_get_select_value(uint32_t event_idx) { return 0; } + +#endif + #endif diff -Nru opensbi-1.1/include/sbi_utils/i2c/dw_i2c.h opensbi-1.3/include/sbi_utils/i2c/dw_i2c.h --- opensbi-1.1/include/sbi_utils/i2c/dw_i2c.h 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/include/sbi_utils/i2c/dw_i2c.h 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,21 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 StarFive Technology Co., Ltd. + * + * Author: Minda Chen + */ + +#ifndef __DW_I2C_H__ +#define __DW_I2C_H__ + +#include + +int dw_i2c_init(struct i2c_adapter *, int nodeoff); + +struct dw_i2c_adapter { + unsigned long addr; + struct i2c_adapter adapter; +}; + +#endif diff -Nru opensbi-1.1/include/sbi_utils/ipi/andes_plicsw.h opensbi-1.3/include/sbi_utils/ipi/andes_plicsw.h --- opensbi-1.1/include/sbi_utils/ipi/andes_plicsw.h 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/include/sbi_utils/ipi/andes_plicsw.h 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,46 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Andes Technology Corporation + * + * Authors: + * Zong Li + * Nylon Chen + * Leo Yu-Chi Liang + * Yu Chien Peter Lin + */ + +#ifndef _IPI_ANDES_PLICSW_H_ +#define _IPI_ANDES_PLICSW_H_ + +#define PLICSW_PRIORITY_BASE 0x4 + +#define PLICSW_PENDING_BASE 0x1000 +#define PLICSW_PENDING_STRIDE 0x8 + +#define PLICSW_ENABLE_BASE 0x2000 +#define PLICSW_ENABLE_STRIDE 0x80 + +#define PLICSW_CONTEXT_BASE 0x200000 +#define PLICSW_CONTEXT_STRIDE 0x1000 +#define PLICSW_CONTEXT_CLAIM 0x4 + +#define PLICSW_HART_MASK 0x01010101 + +#define PLICSW_HART_MAX_NR 8 + +#define PLICSW_REGION_ALIGN 0x1000 + +struct plicsw_data { + unsigned long addr; + unsigned long size; + uint32_t hart_count; + /* hart id to source id table */ + uint32_t source_id[PLICSW_HART_MAX_NR]; +}; + +int plicsw_warm_ipi_init(void); + +int plicsw_cold_ipi_init(struct plicsw_data *plicsw); + +#endif /* _IPI_ANDES_PLICSW_H_ */ diff -Nru opensbi-1.1/include/sbi_utils/ipi/fdt_ipi.h opensbi-1.3/include/sbi_utils/ipi/fdt_ipi.h --- opensbi-1.1/include/sbi_utils/ipi/fdt_ipi.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi_utils/ipi/fdt_ipi.h 2023-06-23 07:31:49.000000000 +0200 @@ -12,6 +12,8 @@ #include +#ifdef CONFIG_FDT_IPI + struct fdt_ipi { const struct fdt_match *match_table; int (*cold_init)(void *fdt, int nodeoff, const struct fdt_match *match); @@ -23,4 +25,11 @@ int fdt_ipi_init(bool cold_boot); +#else + +static inline void fdt_ipi_exit(void) { } +static inline int fdt_ipi_init(bool cold_boot) { return 0; } + +#endif + #endif diff -Nru opensbi-1.1/include/sbi_utils/irqchip/fdt_irqchip.h opensbi-1.3/include/sbi_utils/irqchip/fdt_irqchip.h --- opensbi-1.1/include/sbi_utils/irqchip/fdt_irqchip.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi_utils/irqchip/fdt_irqchip.h 2023-06-23 07:31:49.000000000 +0200 @@ -12,6 +12,8 @@ #include +#ifdef CONFIG_FDT_IRQCHIP + struct fdt_irqchip { const struct fdt_match *match_table; int (*cold_init)(void *fdt, int nodeoff, const struct fdt_match *match); @@ -23,4 +25,12 @@ int fdt_irqchip_init(bool cold_boot); +#else + +static inline void fdt_irqchip_exit(void) { } + +static inline int fdt_irqchip_init(bool cold_boot) { return 0; } + +#endif + #endif diff -Nru opensbi-1.1/include/sbi_utils/irqchip/fdt_irqchip_plic.h opensbi-1.3/include/sbi_utils/irqchip/fdt_irqchip_plic.h --- opensbi-1.1/include/sbi_utils/irqchip/fdt_irqchip_plic.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi_utils/irqchip/fdt_irqchip_plic.h 2023-06-23 07:31:49.000000000 +0200 @@ -9,13 +9,24 @@ #include -void fdt_plic_priority_save(u8 *priority); +/** + * Save the PLIC priority state + * @param priority pointer to the memory region for the saved priority + * @param num size of the memory region including interrupt source 0 + */ +void fdt_plic_priority_save(u8 *priority, u32 num); + +/** + * Restore the PLIC priority state + * @param priority pointer to the memory region for the saved priority + * @param num size of the memory region including interrupt source 0 + */ +void fdt_plic_priority_restore(const u8 *priority, u32 num); -void fdt_plic_priority_restore(const u8 *priority); +void fdt_plic_context_save(bool smode, u32 *enable, u32 *threshold, u32 num); -void fdt_plic_context_save(bool smode, u32 *enable, u32 *threshold); - -void fdt_plic_context_restore(bool smode, const u32 *enable, u32 threshold); +void fdt_plic_context_restore(bool smode, const u32 *enable, u32 threshold, + u32 num); void thead_plic_restore(void); diff -Nru opensbi-1.1/include/sbi_utils/irqchip/imsic.h opensbi-1.3/include/sbi_utils/irqchip/imsic.h --- opensbi-1.1/include/sbi_utils/irqchip/imsic.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi_utils/irqchip/imsic.h 2023-06-23 07:31:49.000000000 +0200 @@ -33,6 +33,8 @@ struct imsic_regs regs[IMSIC_MAX_REGS]; }; +#ifdef CONFIG_IRQCHIP_IMSIC + int imsic_map_hartid_to_data(u32 hartid, struct imsic_data *imsic, int file); struct imsic_data *imsic_get_data(u32 hartid); @@ -47,4 +49,12 @@ int imsic_cold_irqchip_init(struct imsic_data *imsic); +#else + +static inline void imsic_local_irqchip_init(void) { } + +static inline int imsic_data_check(struct imsic_data *imsic) { return 0; } + +#endif + #endif diff -Nru opensbi-1.1/include/sbi_utils/irqchip/plic.h opensbi-1.3/include/sbi_utils/irqchip/plic.h --- opensbi-1.1/include/sbi_utils/irqchip/plic.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi_utils/irqchip/plic.h 2023-06-23 07:31:49.000000000 +0200 @@ -18,15 +18,16 @@ }; /* So far, priorities on all consumers of these functions fit in 8 bits. */ -void plic_priority_save(const struct plic_data *plic, u8 *priority); +void plic_priority_save(const struct plic_data *plic, u8 *priority, u32 num); -void plic_priority_restore(const struct plic_data *plic, const u8 *priority); +void plic_priority_restore(const struct plic_data *plic, const u8 *priority, + u32 num); void plic_context_save(const struct plic_data *plic, int context_id, - u32 *enable, u32 *threshold); + u32 *enable, u32 *threshold, u32 num); void plic_context_restore(const struct plic_data *plic, int context_id, - const u32 *enable, u32 threshold); + const u32 *enable, u32 threshold, u32 num); int plic_context_init(const struct plic_data *plic, int context_id, bool enable, u32 threshold); diff -Nru opensbi-1.1/include/sbi_utils/reset/fdt_reset.h opensbi-1.3/include/sbi_utils/reset/fdt_reset.h --- opensbi-1.1/include/sbi_utils/reset/fdt_reset.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi_utils/reset/fdt_reset.h 2023-06-23 07:31:49.000000000 +0200 @@ -17,6 +17,8 @@ int (*init)(void *fdt, int nodeoff, const struct fdt_match *match); }; +#ifdef CONFIG_FDT_RESET + /** * fdt_reset_driver_init() - initialize reset driver based on the device-tree */ @@ -29,4 +31,14 @@ */ void fdt_reset_init(void); +#else + +static inline int fdt_reset_driver_init(void *fdt, struct fdt_reset *drv) +{ + return 0; +} +static inline void fdt_reset_init(void) { } + +#endif + #endif diff -Nru opensbi-1.1/include/sbi_utils/serial/cadence-uart.h opensbi-1.3/include/sbi_utils/serial/cadence-uart.h --- opensbi-1.1/include/sbi_utils/serial/cadence-uart.h 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/include/sbi_utils/serial/cadence-uart.h 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,16 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 StarFive Technology Co., Ltd. + * + * Author: Jun Liang Tan + */ + +#ifndef __SERIAL_CADENCE_UART_H__ +#define __SERIAL_CADENCE_UART_H__ + +#include + +int cadence_uart_init(unsigned long base, u32 in_freq, u32 baudrate); + +#endif diff -Nru opensbi-1.1/include/sbi_utils/serial/fdt_serial.h opensbi-1.3/include/sbi_utils/serial/fdt_serial.h --- opensbi-1.1/include/sbi_utils/serial/fdt_serial.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi_utils/serial/fdt_serial.h 2023-06-23 07:31:49.000000000 +0200 @@ -12,6 +12,8 @@ #include +#ifdef CONFIG_FDT_SERIAL + struct fdt_serial { const struct fdt_match *match_table; int (*init)(void *fdt, int nodeoff, const struct fdt_match *match); @@ -19,4 +21,10 @@ int fdt_serial_init(void); +#else + +static inline int fdt_serial_init(void) { return 0; } + +#endif + #endif diff -Nru opensbi-1.1/include/sbi_utils/serial/renesas-scif.h opensbi-1.3/include/sbi_utils/serial/renesas-scif.h --- opensbi-1.1/include/sbi_utils/serial/renesas-scif.h 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/include/sbi_utils/serial/renesas-scif.h 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2022 Renesas Electronics Corporation + */ + +#ifndef __SERIAL_RENESAS_SCIF_H__ +#define __SERIAL_RENESAS_SCIF_H__ + +int renesas_scif_init(unsigned long base, u32 in_freq, u32 baudrate); + +#endif /* __SERIAL_RENESAS_SCIF_H__ */ diff -Nru opensbi-1.1/include/sbi_utils/serial/semihosting.h opensbi-1.3/include/sbi_utils/serial/semihosting.h --- opensbi-1.1/include/sbi_utils/serial/semihosting.h 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/include/sbi_utils/serial/semihosting.h 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,47 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Ventana Micro Systems Inc. + * + * Authors: + * Anup Patel + * Kautuk Consul + */ + +#ifndef __SERIAL_SEMIHOSTING_H__ +#define __SERIAL_SEMIHOSTING_H__ + +#include + +/** + * enum semihosting_open_mode - Numeric file modes for use with semihosting_open() + * MODE_READ: 'r' + * MODE_BINARY: 'b' + * MODE_PLUS: '+' + * MODE_WRITE: 'w' + * MODE_APPEND: 'a' + * + * These modes represent the mode string used by fopen(3) in a form which can + * be passed to semihosting_open(). These do NOT correspond directly to %O_RDONLY, + * %O_CREAT, etc; see fopen(3) for details. In particular, @MODE_PLUS + * effectively results in adding %O_RDWR, and @MODE_WRITE will add %O_TRUNC. + * For compatibility, @MODE_BINARY should be added when opening non-text files + * (such as images). + */ +enum semihosting_open_mode { + MODE_READ = 0x0, + MODE_BINARY = 0x1, + MODE_PLUS = 0x2, + MODE_WRITE = 0x4, + MODE_APPEND = 0x8, +}; + +#ifdef CONFIG_SERIAL_SEMIHOSTING +int semihosting_init(void); +int semihosting_enabled(void); +#else +static inline int semihosting_init(void) { return SBI_ENODEV; } +static inline int semihosting_enabled(void) { return 0; } +#endif + +#endif diff -Nru opensbi-1.1/include/sbi_utils/sys/atcsmu.h opensbi-1.3/include/sbi_utils/sys/atcsmu.h --- opensbi-1.1/include/sbi_utils/sys/atcsmu.h 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/include/sbi_utils/sys/atcsmu.h 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,59 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2023 Andes Technology Corporation + */ + +#ifndef _SYS_ATCSMU_H +#define _SYS_ATCSMU_H + +#include + +/* clang-format off */ + +#define PCS0_WE_OFFSET 0x90 +#define PCSm_WE_OFFSET(i) ((i + 3) * 0x20 + PCS0_WE_OFFSET) + +#define PCS0_CTL_OFFSET 0x94 +#define PCSm_CTL_OFFSET(i) ((i + 3) * 0x20 + PCS0_CTL_OFFSET) +#define PCS_CTL_CMD_SHIFT 0 +#define PCS_CTL_PARAM_SHIFT 3 +#define SLEEP_CMD 0x3 +#define WAKEUP_CMD (0x0 | (1 << PCS_CTL_PARAM_SHIFT)) +#define LIGHTSLEEP_MODE 0 +#define DEEPSLEEP_MODE 1 +#define LIGHT_SLEEP_CMD (SLEEP_CMD | (LIGHTSLEEP_MODE << PCS_CTL_PARAM_SHIFT)) +#define DEEP_SLEEP_CMD (SLEEP_CMD | (DEEPSLEEP_MODE << PCS_CTL_PARAM_SHIFT)) + +#define PCS0_CFG_OFFSET 0x80 +#define PCSm_CFG_OFFSET(i) ((i + 3) * 0x20 + PCS0_CFG_OFFSET) +#define PCS_CFG_LIGHT_SLEEP_SHIFT 2 +#define PCS_CFG_LIGHT_SLEEP (1 << PCS_CFG_LIGHT_SLEEP_SHIFT) +#define PCS_CFG_DEEP_SLEEP_SHIFT 3 +#define PCS_CFG_DEEP_SLEEP (1 << PCS_CFG_DEEP_SLEEP_SHIFT) + +#define RESET_VEC_LO_OFFSET 0x50 +#define RESET_VEC_HI_OFFSET 0x60 +#define RESET_VEC_8CORE_OFFSET 0x1a0 +#define HARTn_RESET_VEC_LO(n) (RESET_VEC_LO_OFFSET + \ + ((n) < 4 ? 0 : RESET_VEC_8CORE_OFFSET) + \ + ((n) * 0x4)) +#define HARTn_RESET_VEC_HI(n) (RESET_VEC_HI_OFFSET + \ + ((n) < 4 ? 0 : RESET_VEC_8CORE_OFFSET) + \ + ((n) * 0x4)) + +#define PCS_MAX_NR 8 +#define FLASH_BASE 0x80000000ULL + +/* clang-format on */ + +struct smu_data { + unsigned long addr; +}; + +int smu_set_wakeup_events(struct smu_data *smu, u32 events, u32 hartid); +bool smu_support_sleep_mode(struct smu_data *smu, u32 sleep_mode, u32 hartid); +int smu_set_command(struct smu_data *smu, u32 pcs_ctl, u32 hartid); +int smu_set_reset_vector(struct smu_data *smu, ulong wakeup_addr, u32 hartid); + +#endif /* _SYS_ATCSMU_H */ diff -Nru opensbi-1.1/include/sbi_utils/timer/aclint_mtimer.h opensbi-1.3/include/sbi_utils/timer/aclint_mtimer.h --- opensbi-1.1/include/sbi_utils/timer/aclint_mtimer.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi_utils/timer/aclint_mtimer.h 2023-06-23 07:31:49.000000000 +0200 @@ -22,6 +22,8 @@ #define CLINT_MTIMER_OFFSET 0x4000 +#define MTIMER_REGION_ALIGN 0x1000 + struct aclint_mtimer_data { /* Public details */ unsigned long mtime_freq; diff -Nru opensbi-1.1/include/sbi_utils/timer/andes_plmt.h opensbi-1.3/include/sbi_utils/timer/andes_plmt.h --- opensbi-1.1/include/sbi_utils/timer/andes_plmt.h 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/include/sbi_utils/timer/andes_plmt.h 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,29 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Andes Technology Corporation + * + * Authors: + * Zong Li + * Nylon Chen + * Yu Chien Peter Lin + */ + +#ifndef __TIMER_ANDES_PLMT_H__ +#define __TIMER_ANDES_PLMT_H__ + +#define DEFAULT_AE350_PLMT_FREQ 60000000 +#define PLMT_REGION_ALIGN 0x1000 + +struct plmt_data { + u32 hart_count; + unsigned long size; + unsigned long timer_freq; + volatile u64 *time_val; + volatile u64 *time_cmp; +}; + +int plmt_cold_timer_init(struct plmt_data *plmt); +int plmt_warm_timer_init(void); + +#endif /* __TIMER_ANDES_PLMT_H__ */ diff -Nru opensbi-1.1/include/sbi_utils/timer/fdt_timer.h opensbi-1.3/include/sbi_utils/timer/fdt_timer.h --- opensbi-1.1/include/sbi_utils/timer/fdt_timer.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/include/sbi_utils/timer/fdt_timer.h 2023-06-23 07:31:49.000000000 +0200 @@ -12,6 +12,8 @@ #include +#ifdef CONFIG_FDT_TIMER + struct fdt_timer { const struct fdt_match *match_table; int (*cold_init)(void *fdt, int nodeoff, const struct fdt_match *match); @@ -23,4 +25,11 @@ int fdt_timer_init(bool cold_boot); +#else + +static inline void fdt_timer_exit(void) { } +static inline int fdt_timer_init(bool cold_boot) { return 0; } + +#endif + #endif diff -Nru opensbi-1.1/Kconfig opensbi-1.3/Kconfig --- opensbi-1.1/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/Kconfig 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: BSD-2-Clause + +mainmenu "OpenSBI $(OPENSBI_PLATFORM) Configuration" + +config OPENSBI_SRC_DIR + string + option env="OPENSBI_SRC_DIR" + +config OPENSBI_PLATFORM + string + option env="OPENSBI_PLATFORM" + +config OPENSBI_PLATFORM_SRC_DIR + string + option env="OPENSBI_PLATFORM_SRC_DIR" + +menu "Platform Options" +source "$(OPENSBI_PLATFORM_SRC_DIR)/Kconfig" +endmenu + +source "$(OPENSBI_SRC_DIR)/lib/sbi/Kconfig" + +source "$(OPENSBI_SRC_DIR)/lib/utils/Kconfig" + +source "$(OPENSBI_SRC_DIR)/firmware/Kconfig" diff -Nru opensbi-1.1/lib/sbi/Kconfig opensbi-1.3/lib/sbi/Kconfig --- opensbi-1.1/lib/sbi/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/sbi/Kconfig 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: BSD-2-Clause + +menu "SBI Extension Support" + +config SBI_ECALL_TIME + bool "Timer extension" + default y + +config SBI_ECALL_RFENCE + bool "RFENCE extension" + default y + +config SBI_ECALL_IPI + bool "IPI extension" + default y + +config SBI_ECALL_HSM + bool "Hart State Management extension" + default y + +config SBI_ECALL_SRST + bool "System Reset extension" + default y + +config SBI_ECALL_SUSP + bool "System Suspend extension" + default y + +config SBI_ECALL_PMU + bool "Performance Monitoring Unit extension" + default y + +config SBI_ECALL_DBCN + bool "Debug Console extension" + default y + +config SBI_ECALL_CPPC + bool "CPPC extension" + default y + +config SBI_ECALL_LEGACY + bool "SBI v0.1 legacy extensions" + default y + +config SBI_ECALL_VENDOR + bool "Platform-defined vendor extensions" + default y + +endmenu diff -Nru opensbi-1.1/lib/sbi/objects.mk opensbi-1.3/lib/sbi/objects.mk --- opensbi-1.1/lib/sbi/objects.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/objects.mk 2023-06-23 07:31:49.000000000 +0200 @@ -12,20 +12,54 @@ libsbi-objs-y += riscv_hardfp.o libsbi-objs-y += riscv_locks.o +libsbi-objs-y += sbi_ecall.o +libsbi-objs-y += sbi_ecall_exts.o + +# The order of below extensions is performance optimized +carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_TIME) += ecall_time +libsbi-objs-$(CONFIG_SBI_ECALL_TIME) += sbi_ecall_time.o + +carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_RFENCE) += ecall_rfence +libsbi-objs-$(CONFIG_SBI_ECALL_RFENCE) += sbi_ecall_rfence.o + +carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_IPI) += ecall_ipi +libsbi-objs-$(CONFIG_SBI_ECALL_IPI) += sbi_ecall_ipi.o + +carray-sbi_ecall_exts-y += ecall_base +libsbi-objs-y += sbi_ecall_base.o + +carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_HSM) += ecall_hsm +libsbi-objs-$(CONFIG_SBI_ECALL_HSM) += sbi_ecall_hsm.o + +carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_SRST) += ecall_srst +libsbi-objs-$(CONFIG_SBI_ECALL_SRST) += sbi_ecall_srst.o + +carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_SUSP) += ecall_susp +libsbi-objs-$(CONFIG_SBI_ECALL_SUSP) += sbi_ecall_susp.o + +carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_PMU) += ecall_pmu +libsbi-objs-$(CONFIG_SBI_ECALL_PMU) += sbi_ecall_pmu.o + +carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_DBCN) += ecall_dbcn +libsbi-objs-$(CONFIG_SBI_ECALL_DBCN) += sbi_ecall_dbcn.o + +carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_CPPC) += ecall_cppc +libsbi-objs-$(CONFIG_SBI_ECALL_CPPC) += sbi_ecall_cppc.o + +carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_LEGACY) += ecall_legacy +libsbi-objs-$(CONFIG_SBI_ECALL_LEGACY) += sbi_ecall_legacy.o + +carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_VENDOR) += ecall_vendor +libsbi-objs-$(CONFIG_SBI_ECALL_VENDOR) += sbi_ecall_vendor.o + libsbi-objs-y += sbi_bitmap.o libsbi-objs-y += sbi_bitops.o libsbi-objs-y += sbi_console.o libsbi-objs-y += sbi_domain.o -libsbi-objs-y += sbi_ecall.o -libsbi-objs-y += sbi_ecall_base.o -libsbi-objs-y += sbi_ecall_hsm.o -libsbi-objs-y += sbi_ecall_legacy.o -libsbi-objs-y += sbi_ecall_pmu.o -libsbi-objs-y += sbi_ecall_replace.o -libsbi-objs-y += sbi_ecall_vendor.o libsbi-objs-y += sbi_emulate_csr.o libsbi-objs-y += sbi_fifo.o libsbi-objs-y += sbi_hart.o +libsbi-objs-y += sbi_heap.o libsbi-objs-y += sbi_math.o libsbi-objs-y += sbi_hfence.o libsbi-objs-y += sbi_hsm.o @@ -44,3 +78,4 @@ libsbi-objs-y += sbi_trap.o libsbi-objs-y += sbi_unpriv.o libsbi-objs-y += sbi_expected_trap.o +libsbi-objs-y += sbi_cppc.o diff -Nru opensbi-1.1/lib/sbi/riscv_asm.c opensbi-1.3/lib/sbi/riscv_asm.c --- opensbi-1.1/lib/sbi/riscv_asm.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/riscv_asm.c 2023-06-23 07:31:49.000000000 +0200 @@ -152,7 +152,7 @@ default: sbi_panic("%s: Unknown CSR %#x", __func__, csr_num); break; - }; + } return ret; @@ -220,7 +220,7 @@ default: sbi_panic("%s: Unknown CSR %#x", __func__, csr_num); break; - }; + } #undef switchcase_csr_write_64 #undef switchcase_csr_write_32 diff -Nru opensbi-1.1/lib/sbi/sbi_console.c opensbi-1.3/lib/sbi/sbi_console.c --- opensbi-1.1/lib/sbi/sbi_console.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_console.c 2023-06-23 07:31:49.000000000 +0200 @@ -12,17 +12,22 @@ #include #include #include +#include + +#define CONSOLE_TBUF_MAX 256 static const struct sbi_console_device *console_dev = NULL; +static char console_tbuf[CONSOLE_TBUF_MAX]; +static u32 console_tbuf_len; static spinlock_t console_out_lock = SPIN_LOCK_INITIALIZER; bool sbi_isprintable(char c) { if (((31 < c) && (c < 127)) || (c == '\f') || (c == '\r') || (c == '\n') || (c == '\t')) { - return TRUE; + return true; } - return FALSE; + return false; } int sbi_getc(void) @@ -41,14 +46,47 @@ } } +static unsigned long nputs(const char *str, unsigned long len) +{ + unsigned long i, ret; + + if (console_dev && console_dev->console_puts) { + ret = console_dev->console_puts(str, len); + } else { + for (i = 0; i < len; i++) + sbi_putc(str[i]); + ret = len; + } + + return ret; +} + +static void nputs_all(const char *str, unsigned long len) +{ + unsigned long p = 0; + + while (p < len) + p += nputs(&str[p], len - p); +} + void sbi_puts(const char *str) { + unsigned long len = sbi_strlen(str); + spin_lock(&console_out_lock); - while (*str) { - sbi_putc(*str); - str++; - } + nputs_all(str, len); + spin_unlock(&console_out_lock); +} + +unsigned long sbi_nputs(const char *str, unsigned long len) +{ + unsigned long ret; + + spin_lock(&console_out_lock); + ret = nputs(str, len); spin_unlock(&console_out_lock); + + return ret; } void sbi_gets(char *s, int maxwidth, char endchar) @@ -64,6 +102,21 @@ *retval = '\0'; } +unsigned long sbi_ngets(char *str, unsigned long len) +{ + int ch; + unsigned long i; + + for (i = 0; i < len; i++) { + ch = sbi_getc(); + if (ch < 0) + break; + str[i] = ch; + } + + return i; +} + #define PAD_RIGHT 1 #define PAD_ZERO 2 #define PAD_ALTERNATE 4 @@ -76,20 +129,22 @@ static void printc(char **out, u32 *out_len, char ch) { - if (out) { - if (*out) { - if (out_len && (0 < *out_len)) { - **out = ch; - ++(*out); - (*out_len)--; - } else { - **out = ch; - ++(*out); - } - } - } else { + if (!out) { sbi_putc(ch); + return; + } + + /* + * The *printf entry point functions have enforced that (*out) can + * only be null when out_len is non-null and its value is zero. + */ + if (!out_len || *out_len > 1) { + *(*out)++ = ch; + **out = '\0'; } + + if (out_len && *out_len > 0) + --(*out_len); } static int prints(char **out, u32 *out_len, const char *string, int width, @@ -181,19 +236,37 @@ static int print(char **out, u32 *out_len, const char *format, va_list args) { - int width, flags, acnt = 0; - int pc = 0; - char scr[2]; + int width, flags, pc = 0; + char scr[2], *tout; + bool use_tbuf = (!out) ? true : false; unsigned long long tmp; + /* + * The console_tbuf is protected by console_out_lock and + * print() is always called with console_out_lock held + * when out == NULL. + */ + if (use_tbuf) { + console_tbuf_len = CONSOLE_TBUF_MAX; + tout = console_tbuf; + out = &tout; + out_len = &console_tbuf_len; + } + for (; *format != 0; ++format) { + if (use_tbuf && !console_tbuf_len) { + nputs_all(console_tbuf, CONSOLE_TBUF_MAX); + console_tbuf_len = CONSOLE_TBUF_MAX; + tout = console_tbuf; + } + if (*format == '%') { ++format; width = flags = 0; if (*format == '\0') break; if (*format == '%') - goto out; + goto literal; /* Get flags */ if (*format == '-') { ++format; @@ -214,7 +287,6 @@ } if (*format == 's') { char *s = va_arg(args, char *); - acnt += sizeof(char *); pc += prints(out, out_len, s ? s : "(null)", width, flags); continue; @@ -222,61 +294,40 @@ if ((*format == 'd') || (*format == 'i')) { pc += printi(out, out_len, va_arg(args, int), 10, 1, width, flags, '0'); - acnt += sizeof(int); continue; } if (*format == 'x') { pc += printi(out, out_len, va_arg(args, unsigned int), 16, 0, width, flags, 'a'); - acnt += sizeof(unsigned int); continue; } if (*format == 'X') { pc += printi(out, out_len, va_arg(args, unsigned int), 16, 0, width, flags, 'A'); - acnt += sizeof(unsigned int); continue; } if (*format == 'u') { pc += printi(out, out_len, va_arg(args, unsigned int), 10, 0, width, flags, 'a'); - acnt += sizeof(unsigned int); continue; } if (*format == 'p') { pc += printi(out, out_len, va_arg(args, unsigned long), 16, 0, width, flags, 'a'); - acnt += sizeof(unsigned long); continue; } if (*format == 'P') { pc += printi(out, out_len, va_arg(args, unsigned long), 16, 0, width, flags, 'A'); - acnt += sizeof(unsigned long); continue; } if (*format == 'l' && *(format + 1) == 'l') { - while (acnt & - (sizeof(unsigned long long) - 1)) { - va_arg(args, int); - acnt += sizeof(int); - } - if (sizeof(unsigned long long) == - sizeof(unsigned long)) { - tmp = va_arg(args, unsigned long long); - acnt += sizeof(unsigned long long); - } else { - ((unsigned long *)&tmp)[0] = - va_arg(args, unsigned long); - ((unsigned long *)&tmp)[1] = - va_arg(args, unsigned long); - acnt += 2 * sizeof(unsigned long); - } + tmp = va_arg(args, unsigned long long); if (*(format + 2) == 'u') { format += 2; pc += printi(out, out_len, tmp, 10, 0, @@ -308,19 +359,16 @@ out, out_len, va_arg(args, unsigned long), 16, 0, width, flags, 'a'); - acnt += sizeof(unsigned long); } else if (*(format + 1) == 'X') { format += 1; pc += printi( out, out_len, va_arg(args, unsigned long), 16, 0, width, flags, 'A'); - acnt += sizeof(unsigned long); } else { pc += printi(out, out_len, va_arg(args, long), 10, 1, width, flags, '0'); - acnt += sizeof(long); } } if (*format == 'c') { @@ -328,17 +376,17 @@ scr[0] = va_arg(args, int); scr[1] = '\0'; pc += prints(out, out_len, scr, width, flags); - acnt += sizeof(int); continue; } } else { - out: +literal: printc(out, out_len, *format); ++pc; } } - if (out) - **out = '\0'; + + if (use_tbuf && console_tbuf_len < CONSOLE_TBUF_MAX) + nputs_all(console_tbuf, CONSOLE_TBUF_MAX - console_tbuf_len); return pc; } @@ -348,6 +396,9 @@ va_list args; int retval; + if (unlikely(!out)) + sbi_panic("sbi_sprintf called with NULL output string\n"); + va_start(args, format); retval = print(&out, NULL, format, args); va_end(args); @@ -360,6 +411,10 @@ va_list args; int retval; + if (unlikely(!out && out_sz != 0)) + sbi_panic("sbi_snprintf called with NULL output string and " + "output size is not zero\n"); + va_start(args, format); retval = print(&out, &out_sz, format, args); va_end(args); @@ -426,5 +481,11 @@ int sbi_console_init(struct sbi_scratch *scratch) { - return sbi_platform_console_init(sbi_platform_ptr(scratch)); + int rc = sbi_platform_console_init(sbi_platform_ptr(scratch)); + + /* console is not a necessary device */ + if (rc == SBI_ENODEV) + return 0; + + return rc; } diff -Nru opensbi-1.1/lib/sbi/sbi_cppc.c opensbi-1.3/lib/sbi/sbi_cppc.c --- opensbi-1.1/lib/sbi/sbi_cppc.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/sbi/sbi_cppc.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,110 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Ventana Micro Systems Inc. + * + */ + +#include +#include + +static const struct sbi_cppc_device *cppc_dev = NULL; + +const struct sbi_cppc_device *sbi_cppc_get_device(void) +{ + return cppc_dev; +} + +void sbi_cppc_set_device(const struct sbi_cppc_device *dev) +{ + if (!dev || cppc_dev) + return; + + cppc_dev = dev; +} + +static bool sbi_cppc_is_reserved(unsigned long reg) +{ + if ((reg > SBI_CPPC_ACPI_LAST && reg < SBI_CPPC_TRANSITION_LATENCY) || + reg > SBI_CPPC_NON_ACPI_LAST) + return true; + + return false; +} + +static bool sbi_cppc_readable(unsigned long reg) +{ + /* there are no write-only cppc registers currently */ + return true; +} + +static bool sbi_cppc_writable(unsigned long reg) +{ + switch (reg) { + case SBI_CPPC_HIGHEST_PERF: + case SBI_CPPC_NOMINAL_PERF: + case SBI_CPPC_LOW_NON_LINEAR_PERF: + case SBI_CPPC_LOWEST_PERF: + case SBI_CPPC_GUARANTEED_PERF: + case SBI_CPPC_CTR_WRAP_TIME: + case SBI_CPPC_REFERENCE_CTR: + case SBI_CPPC_DELIVERED_CTR: + case SBI_CPPC_REFERENCE_PERF: + case SBI_CPPC_LOWEST_FREQ: + case SBI_CPPC_NOMINAL_FREQ: + case SBI_CPPC_TRANSITION_LATENCY: + return false; + } + + return true; +} + +int sbi_cppc_probe(unsigned long reg) +{ + if (!cppc_dev || !cppc_dev->cppc_probe) + return SBI_EFAIL; + + /* Check whether register is reserved */ + if (sbi_cppc_is_reserved(reg)) + return SBI_ERR_INVALID_PARAM; + + return cppc_dev->cppc_probe(reg); +} + +int sbi_cppc_read(unsigned long reg, uint64_t *val) +{ + int ret; + + if (!cppc_dev || !cppc_dev->cppc_read) + return SBI_EFAIL; + + /* Check whether register is implemented */ + ret = sbi_cppc_probe(reg); + if (ret <= 0) + return SBI_ERR_NOT_SUPPORTED; + + /* Check whether the register is write-only */ + if (!sbi_cppc_readable(reg)) + return SBI_ERR_DENIED; + + return cppc_dev->cppc_read(reg, val); +} + +int sbi_cppc_write(unsigned long reg, uint64_t val) +{ + int ret; + + if (!cppc_dev || !cppc_dev->cppc_write) + return SBI_EFAIL; + + /* Check whether register is implemented */ + ret = sbi_cppc_probe(reg); + if (ret <= 0) + return SBI_ERR_NOT_SUPPORTED; + + /* Check whether the register is read-only */ + if (!sbi_cppc_writable(reg)) + return SBI_ERR_DENIED; + + return cppc_dev->cppc_write(reg, val); +} diff -Nru opensbi-1.1/lib/sbi/sbi_domain.c opensbi-1.3/lib/sbi/sbi_domain.c --- opensbi-1.1/lib/sbi/sbi_domain.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_domain.c 2023-06-23 07:31:49.000000000 +0200 @@ -11,37 +11,63 @@ #include #include #include +#include #include #include #include #include #include -struct sbi_domain *hartid_to_domain_table[SBI_HARTMASK_MAX_BITS] = { 0 }; -struct sbi_domain *domidx_to_domain_table[SBI_DOMAIN_MAX_INDEX] = { 0 }; +/* + * We allocate an extra element because sbi_domain_for_each() expects + * the array to be null-terminated. + */ +struct sbi_domain *domidx_to_domain_table[SBI_DOMAIN_MAX_INDEX + 1] = { 0 }; static u32 domain_count = 0; static bool domain_finalized = false; -static struct sbi_hartmask root_hmask = { 0 }; - #define ROOT_REGION_MAX 16 static u32 root_memregs_count = 0; -static struct sbi_domain_memregion root_fw_region; -static struct sbi_domain_memregion root_memregs[ROOT_REGION_MAX + 1] = { 0 }; struct sbi_domain root = { .name = "root", - .possible_harts = &root_hmask, - .regions = root_memregs, - .system_reset_allowed = TRUE, + .possible_harts = NULL, + .regions = NULL, + .system_reset_allowed = true, + .system_suspend_allowed = true, + .fw_region_inited = false, }; +static unsigned long domain_hart_ptr_offset; + +struct sbi_domain *sbi_hartid_to_domain(u32 hartid) +{ + struct sbi_scratch *scratch; + + scratch = sbi_hartid_to_scratch(hartid); + if (!scratch || !domain_hart_ptr_offset) + return NULL; + + return sbi_scratch_read_type(scratch, void *, domain_hart_ptr_offset); +} + +static void update_hartid_to_domain(u32 hartid, struct sbi_domain *dom) +{ + struct sbi_scratch *scratch; + + scratch = sbi_hartid_to_scratch(hartid); + if (!scratch) + return; + + sbi_scratch_write_type(scratch, void *, domain_hart_ptr_offset, dom); +} + bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartid) { if (dom) return sbi_hartmask_test_hart(hartid, &dom->assigned_harts); - return FALSE; + return false; } ulong sbi_domain_get_assigned_hartmask(const struct sbi_domain *dom, @@ -64,14 +90,6 @@ return ret; } -static void domain_memregion_initfw(struct sbi_domain_memregion *reg) -{ - if (!reg) - return; - - sbi_memcpy(reg, &root_fw_region, sizeof(*reg)); -} - void sbi_domain_memregion_init(unsigned long addr, unsigned long size, unsigned long flags, @@ -105,51 +123,64 @@ unsigned long addr, unsigned long mode, unsigned long access_flags) { - bool mmio = FALSE; + bool rmmio, mmio = false; struct sbi_domain_memregion *reg; - unsigned long rstart, rend, rflags, rwx = 0; + unsigned long rstart, rend, rflags, rwx = 0, rrwx = 0; if (!dom) - return FALSE; + return false; + /* + * Use M_{R/W/X} bits because the SU-bits are at the + * same relative offsets. If the mode is not M, the SU + * bits will fall at same offsets after the shift. + */ if (access_flags & SBI_DOMAIN_READ) - rwx |= SBI_DOMAIN_MEMREGION_READABLE; + rwx |= SBI_DOMAIN_MEMREGION_M_READABLE; + if (access_flags & SBI_DOMAIN_WRITE) - rwx |= SBI_DOMAIN_MEMREGION_WRITEABLE; + rwx |= SBI_DOMAIN_MEMREGION_M_WRITABLE; + if (access_flags & SBI_DOMAIN_EXECUTE) - rwx |= SBI_DOMAIN_MEMREGION_EXECUTABLE; + rwx |= SBI_DOMAIN_MEMREGION_M_EXECUTABLE; + if (access_flags & SBI_DOMAIN_MMIO) - mmio = TRUE; + mmio = true; sbi_domain_for_each_memregion(dom, reg) { rflags = reg->flags; - if (mode == PRV_M && !(rflags & SBI_DOMAIN_MEMREGION_MMODE)) - continue; + rrwx = (mode == PRV_M ? + (rflags & SBI_DOMAIN_MEMREGION_M_ACCESS_MASK) : + (rflags & SBI_DOMAIN_MEMREGION_SU_ACCESS_MASK) + >> SBI_DOMAIN_MEMREGION_SU_ACCESS_SHIFT); rstart = reg->base; rend = (reg->order < __riscv_xlen) ? rstart + ((1UL << reg->order) - 1) : -1UL; if (rstart <= addr && addr <= rend) { - if ((mmio && !(rflags & SBI_DOMAIN_MEMREGION_MMIO)) || - (!mmio && (rflags & SBI_DOMAIN_MEMREGION_MMIO))) - return FALSE; - return ((rflags & rwx) == rwx) ? TRUE : FALSE; + rmmio = (rflags & SBI_DOMAIN_MEMREGION_MMIO) ? true : false; + if (mmio != rmmio) + return false; + return ((rrwx & rwx) == rwx) ? true : false; } } - return (mode == PRV_M) ? TRUE : FALSE; + return (mode == PRV_M) ? true : false; } /* Check if region complies with constraints */ static bool is_region_valid(const struct sbi_domain_memregion *reg) { if (reg->order < 3 || __riscv_xlen < reg->order) - return FALSE; + return false; - if (reg->base & (BIT(reg->order) - 1)) - return FALSE; + if (reg->order == __riscv_xlen && reg->base != 0) + return false; - return TRUE; + if (reg->order < __riscv_xlen && (reg->base & (BIT(reg->order) - 1))) + return false; + + return true; } /** Check if regionA is sub-region of regionB */ @@ -165,9 +196,9 @@ (regA_start < regB_end) && (regB_start < regA_end) && (regA_end <= regB_end)) - return TRUE; + return true; - return FALSE; + return false; } /** Check if regionA conflicts regionB */ @@ -176,9 +207,9 @@ { if ((is_region_subset(regA, regB) || is_region_subset(regB, regA)) && regA->flags == regB->flags) - return TRUE; + return true; - return FALSE; + return false; } /** Check if regionA should be placed before regionB */ @@ -186,20 +217,57 @@ const struct sbi_domain_memregion *regB) { if (regA->order < regB->order) - return TRUE; + return true; if ((regA->order == regB->order) && (regA->base < regB->base)) - return TRUE; + return true; - return FALSE; + return false; +} + +static const struct sbi_domain_memregion *find_region( + const struct sbi_domain *dom, + unsigned long addr) +{ + unsigned long rstart, rend; + struct sbi_domain_memregion *reg; + + sbi_domain_for_each_memregion(dom, reg) { + rstart = reg->base; + rend = (reg->order < __riscv_xlen) ? + rstart + ((1UL << reg->order) - 1) : -1UL; + if (rstart <= addr && addr <= rend) + return reg; + } + + return NULL; +} + +static const struct sbi_domain_memregion *find_next_subset_region( + const struct sbi_domain *dom, + const struct sbi_domain_memregion *reg, + unsigned long addr) +{ + struct sbi_domain_memregion *sreg, *ret = NULL; + + sbi_domain_for_each_memregion(dom, sreg) { + if (sreg == reg || (sreg->base <= addr) || + !is_region_subset(sreg, reg)) + continue; + + if (!ret || (sreg->base < ret->base) || + ((sreg->base == ret->base) && (sreg->order < ret->order))) + ret = sreg; + } + + return ret; } static int sanitize_domain(const struct sbi_platform *plat, struct sbi_domain *dom) { u32 i, j, count; - bool have_fw_reg; struct sbi_domain_memregion treg, *reg, *reg1; /* Check possible HARTs */ @@ -214,7 +282,7 @@ "hart %d\n", __func__, dom->name, i); return SBI_EINVAL; } - }; + } /* Check memory regions */ if (!dom->regions) { @@ -232,17 +300,13 @@ } } - /* Count memory regions and check presence of firmware region */ + /* Count memory regions */ count = 0; - have_fw_reg = FALSE; - sbi_domain_for_each_memregion(dom, reg) { - if (reg->order == root_fw_region.order && - reg->base == root_fw_region.base && - reg->flags == root_fw_region.flags) - have_fw_reg = TRUE; + sbi_domain_for_each_memregion(dom, reg) count++; - } - if (!have_fw_reg) { + + /* Check presence of firmware regions */ + if (!dom->fw_region_inited) { sbi_printf("%s: %s does not have firmware region\n", __func__, dom->name); return SBI_EINVAL; @@ -282,7 +346,7 @@ /* * Check next mode * - * We only allow next mode to be S-mode or U-mode.so that we can + * We only allow next mode to be S-mode or U-mode, so that we can * protect M-mode context and enforce checks on memory accesses. */ if (dom->next_mode != PRV_S && @@ -292,7 +356,7 @@ return SBI_EINVAL; } - /* Check next address and next mode*/ + /* Check next address and next mode */ if (!sbi_domain_check_addr(dom, dom->next_addr, dom->next_mode, SBI_DOMAIN_EXECUTE)) { sbi_printf("%s: %s next booting stage address 0x%lx can't " @@ -303,6 +367,37 @@ return 0; } +bool sbi_domain_check_addr_range(const struct sbi_domain *dom, + unsigned long addr, unsigned long size, + unsigned long mode, + unsigned long access_flags) +{ + unsigned long max = addr + size; + const struct sbi_domain_memregion *reg, *sreg; + + if (!dom) + return false; + + while (addr < max) { + reg = find_region(dom, addr); + if (!reg) + return false; + + if (!sbi_domain_check_addr(dom, addr, mode, access_flags)) + return false; + + sreg = find_next_subset_region(dom, reg, addr); + if (sreg) + addr = sreg->base; + else if (reg->order < __riscv_xlen) + addr = reg->base + (1UL << reg->order); + else + break; + } + + return true; +} + void sbi_domain_dump(const struct sbi_domain *dom, const char *suffix) { u32 i, k; @@ -332,15 +427,25 @@ dom->index, i, suffix, rstart, rend); k = 0; - if (reg->flags & SBI_DOMAIN_MEMREGION_MMODE) - sbi_printf("%cM", (k++) ? ',' : '('); + + sbi_printf("M: "); if (reg->flags & SBI_DOMAIN_MEMREGION_MMIO) sbi_printf("%cI", (k++) ? ',' : '('); - if (reg->flags & SBI_DOMAIN_MEMREGION_READABLE) + if (reg->flags & SBI_DOMAIN_MEMREGION_M_READABLE) + sbi_printf("%cR", (k++) ? ',' : '('); + if (reg->flags & SBI_DOMAIN_MEMREGION_M_WRITABLE) + sbi_printf("%cW", (k++) ? ',' : '('); + if (reg->flags & SBI_DOMAIN_MEMREGION_M_EXECUTABLE) + sbi_printf("%cX", (k++) ? ',' : '('); + sbi_printf("%s ", (k++) ? ")" : "()"); + + k = 0; + sbi_printf("S/U: "); + if (reg->flags & SBI_DOMAIN_MEMREGION_SU_READABLE) sbi_printf("%cR", (k++) ? ',' : '('); - if (reg->flags & SBI_DOMAIN_MEMREGION_WRITEABLE) + if (reg->flags & SBI_DOMAIN_MEMREGION_SU_WRITABLE) sbi_printf("%cW", (k++) ? ',' : '('); - if (reg->flags & SBI_DOMAIN_MEMREGION_EXECUTABLE) + if (reg->flags & SBI_DOMAIN_MEMREGION_SU_EXECUTABLE) sbi_printf("%cX", (k++) ? ',' : '('); sbi_printf("%s\n", (k++) ? ")" : "()"); @@ -367,10 +472,13 @@ default: sbi_printf("Unknown\n"); break; - }; + } sbi_printf("Domain%d SysReset %s: %s\n", dom->index, suffix, (dom->system_reset_allowed) ? "yes" : "no"); + + sbi_printf("Domain%d SysSuspend %s: %s\n", + dom->index, suffix, (dom->system_suspend_allowed) ? "yes" : "no"); } void sbi_domain_dump_all(const char *suffix) @@ -434,11 +542,11 @@ if (!sbi_hartmask_test_hart(i, dom->possible_harts)) continue; - tdom = hartid_to_domain_table[i]; + tdom = sbi_hartid_to_domain(i); if (tdom) sbi_hartmask_clear_hart(i, &tdom->assigned_harts); - hartid_to_domain_table[i] = dom; + update_hartid_to_domain(i, dom); sbi_hartmask_set_hart(i, &dom->assigned_harts); /* @@ -464,8 +572,7 @@ const struct sbi_platform *plat = sbi_platform_thishart_ptr(); /* Sanity checks */ - if (!reg || domain_finalized || - (root.regions != root_memregs) || + if (!reg || domain_finalized || !root.regions || (ROOT_REGION_MAX <= root_memregs_count)) return SBI_EINVAL; @@ -480,10 +587,10 @@ } /* Append the memregion to root memregions */ - nreg = &root_memregs[root_memregs_count]; + nreg = &root.regions[root_memregs_count]; sbi_memcpy(nreg, reg, sizeof(*reg)); root_memregs_count++; - root_memregs[root_memregs_count].order = 0; + root.regions[root_memregs_count].order = 0; /* Sort and optimize root regions */ do { @@ -522,6 +629,33 @@ return 0; } +int sbi_domain_root_add_memrange(unsigned long addr, unsigned long size, + unsigned long align, unsigned long region_flags) +{ + int rc; + unsigned long pos, end, rsize; + struct sbi_domain_memregion reg; + + pos = addr; + end = addr + size; + while (pos < end) { + rsize = pos & (align - 1); + if (rsize) + rsize = 1UL << sbi_ffs(pos); + else + rsize = ((end - pos) < align) ? + (end - pos) : align; + + sbi_domain_memregion_init(pos, rsize, region_flags, ®); + rc = sbi_domain_root_add_memregion(®); + if (rc) + return rc; + pos += rsize; + } + + return 0; +} + int sbi_domain_finalize(struct sbi_scratch *scratch, u32 cold_hartid) { int rc; @@ -586,12 +720,57 @@ int sbi_domain_init(struct sbi_scratch *scratch, u32 cold_hartid) { u32 i; + int rc; + struct sbi_hartmask *root_hmask; + struct sbi_domain_memregion *root_memregs; const struct sbi_platform *plat = sbi_platform_ptr(scratch); + if (scratch->fw_rw_offset == 0 || + (scratch->fw_rw_offset & (scratch->fw_rw_offset - 1)) != 0) { + sbi_printf("%s: fw_rw_offset is not a power of 2 (0x%lx)\n", + __func__, scratch->fw_rw_offset); + return SBI_EINVAL; + } + + if ((scratch->fw_start & (scratch->fw_rw_offset - 1)) != 0) { + sbi_printf("%s: fw_start and fw_rw_offset not aligned\n", + __func__); + return SBI_EINVAL; + } + + domain_hart_ptr_offset = sbi_scratch_alloc_type_offset(void *); + if (!domain_hart_ptr_offset) + return SBI_ENOMEM; + + root_memregs = sbi_calloc(sizeof(*root_memregs), ROOT_REGION_MAX + 1); + if (!root_memregs) { + sbi_printf("%s: no memory for root regions\n", __func__); + rc = SBI_ENOMEM; + goto fail_free_domain_hart_ptr_offset; + } + root.regions = root_memregs; + + root_hmask = sbi_zalloc(sizeof(*root_hmask)); + if (!root_hmask) { + sbi_printf("%s: no memory for root hartmask\n", __func__); + rc = SBI_ENOMEM; + goto fail_free_root_memregs; + } + root.possible_harts = root_hmask; + /* Root domain firmware memory region */ - sbi_domain_memregion_init(scratch->fw_start, scratch->fw_size, 0, - &root_fw_region); - domain_memregion_initfw(&root_memregs[root_memregs_count++]); + sbi_domain_memregion_init(scratch->fw_start, scratch->fw_rw_offset, + (SBI_DOMAIN_MEMREGION_M_READABLE | + SBI_DOMAIN_MEMREGION_M_EXECUTABLE), + &root_memregs[root_memregs_count++]); + + sbi_domain_memregion_init((scratch->fw_start + scratch->fw_rw_offset), + (scratch->fw_size - scratch->fw_rw_offset), + (SBI_DOMAIN_MEMREGION_M_READABLE | + SBI_DOMAIN_MEMREGION_M_WRITABLE), + &root_memregs[root_memregs_count++]); + + root.fw_region_inited = true; /* Root domain allow everything memory region */ sbi_domain_memregion_init(0, ~0UL, @@ -615,8 +794,21 @@ for (i = 0; i < SBI_HARTMASK_MAX_BITS; i++) { if (sbi_platform_hart_invalid(plat, i)) continue; - sbi_hartmask_set_hart(i, &root_hmask); + sbi_hartmask_set_hart(i, root_hmask); } - return sbi_domain_register(&root, &root_hmask); + /* Finally register the root domain */ + rc = sbi_domain_register(&root, root_hmask); + if (rc) + goto fail_free_root_hmask; + + return 0; + +fail_free_root_hmask: + sbi_free(root_hmask); +fail_free_root_memregs: + sbi_free(root_memregs); +fail_free_domain_hart_ptr_offset: + sbi_scratch_free_offset(domain_hart_ptr_offset); + return rc; } diff -Nru opensbi-1.1/lib/sbi/sbi_ecall_base.c opensbi-1.3/lib/sbi/sbi_ecall_base.c --- opensbi-1.1/lib/sbi/sbi_ecall_base.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_ecall_base.c 2023-06-23 07:31:49.000000000 +0200 @@ -72,8 +72,16 @@ return ret; } +struct sbi_ecall_extension ecall_base; + +static int sbi_ecall_base_register_extensions(void) +{ + return sbi_ecall_register_extension(&ecall_base); +} + struct sbi_ecall_extension ecall_base = { - .extid_start = SBI_EXT_BASE, - .extid_end = SBI_EXT_BASE, - .handle = sbi_ecall_base_handler, + .extid_start = SBI_EXT_BASE, + .extid_end = SBI_EXT_BASE, + .register_extensions = sbi_ecall_base_register_extensions, + .handle = sbi_ecall_base_handler, }; diff -Nru opensbi-1.1/lib/sbi/sbi_ecall.c opensbi-1.3/lib/sbi/sbi_ecall.c --- opensbi-1.1/lib/sbi/sbi_ecall.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_ecall.c 2023-06-23 07:31:49.000000000 +0200 @@ -13,6 +13,9 @@ #include #include +extern struct sbi_ecall_extension *sbi_ecall_exts[]; +extern unsigned long sbi_ecall_exts_size; + u16 sbi_ecall_version_major(void) { return SBI_ECALL_VERSION_MAJOR; @@ -75,7 +78,7 @@ void sbi_ecall_unregister_extension(struct sbi_ecall_extension *ext) { - bool found = FALSE; + bool found = false; struct sbi_ecall_extension *t; if (!ext) @@ -83,7 +86,7 @@ sbi_list_for_each_entry(t, &ecall_exts_list, head) { if (t == ext) { - found = TRUE; + found = true; break; } } @@ -117,7 +120,9 @@ trap.epc = regs->mepc; sbi_trap_redirect(regs, &trap); } else { - if (ret < SBI_LAST_ERR) { + if (ret < SBI_LAST_ERR || + (extension_id != SBI_EXT_0_1_CONSOLE_GETCHAR && + SBI_SUCCESS < ret)) { sbi_printf("%s: Invalid error %d for ext=0x%lx " "func=0x%lx\n", __func__, ret, extension_id, func_id); @@ -144,35 +149,18 @@ int sbi_ecall_init(void) { int ret; + struct sbi_ecall_extension *ext; + unsigned long i; - /* The order of below registrations is performance optimized */ - ret = sbi_ecall_register_extension(&ecall_time); - if (ret) - return ret; - ret = sbi_ecall_register_extension(&ecall_rfence); - if (ret) - return ret; - ret = sbi_ecall_register_extension(&ecall_ipi); - if (ret) - return ret; - ret = sbi_ecall_register_extension(&ecall_base); - if (ret) - return ret; - ret = sbi_ecall_register_extension(&ecall_hsm); - if (ret) - return ret; - ret = sbi_ecall_register_extension(&ecall_srst); - if (ret) - return ret; - ret = sbi_ecall_register_extension(&ecall_pmu); - if (ret) - return ret; - ret = sbi_ecall_register_extension(&ecall_legacy); - if (ret) - return ret; - ret = sbi_ecall_register_extension(&ecall_vendor); - if (ret) - return ret; + for (i = 0; i < sbi_ecall_exts_size; i++) { + ext = sbi_ecall_exts[i]; + ret = SBI_ENODEV; + + if (ext->register_extensions) + ret = ext->register_extensions(); + if (ret) + return ret; + } return 0; } diff -Nru opensbi-1.1/lib/sbi/sbi_ecall_cppc.c opensbi-1.3/lib/sbi/sbi_ecall_cppc.c --- opensbi-1.1/lib/sbi/sbi_ecall_cppc.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/sbi/sbi_ecall_cppc.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,67 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Ventana Micro Systems Inc. + * + */ + +#include +#include +#include +#include +#include + +static int sbi_ecall_cppc_handler(unsigned long extid, unsigned long funcid, + const struct sbi_trap_regs *regs, + unsigned long *out_val, + struct sbi_trap_info *out_trap) +{ + int ret = 0; + uint64_t temp; + + switch (funcid) { + case SBI_EXT_CPPC_READ: + ret = sbi_cppc_read(regs->a0, &temp); + *out_val = temp; + break; + case SBI_EXT_CPPC_READ_HI: +#if __riscv_xlen == 32 + ret = sbi_cppc_read(regs->a0, &temp); + *out_val = temp >> 32; +#else + *out_val = 0; +#endif + break; + case SBI_EXT_CPPC_WRITE: + ret = sbi_cppc_write(regs->a0, regs->a1); + break; + case SBI_EXT_CPPC_PROBE: + ret = sbi_cppc_probe(regs->a0); + if (ret >= 0) { + *out_val = ret; + ret = 0; + } + break; + default: + ret = SBI_ENOTSUPP; + } + + return ret; +} + +struct sbi_ecall_extension ecall_cppc; + +static int sbi_ecall_cppc_register_extensions(void) +{ + if (!sbi_cppc_get_device()) + return 0; + + return sbi_ecall_register_extension(&ecall_cppc); +} + +struct sbi_ecall_extension ecall_cppc = { + .extid_start = SBI_EXT_CPPC, + .extid_end = SBI_EXT_CPPC, + .register_extensions = sbi_ecall_cppc_register_extensions, + .handle = sbi_ecall_cppc_handler, +}; diff -Nru opensbi-1.1/lib/sbi/sbi_ecall_dbcn.c opensbi-1.3/lib/sbi/sbi_ecall_dbcn.c --- opensbi-1.1/lib/sbi/sbi_ecall_dbcn.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/sbi/sbi_ecall_dbcn.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,79 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Ventana Micro Systems Inc. + * + * Authors: + * Anup Patel + */ + +#include +#include +#include +#include +#include +#include +#include + +static int sbi_ecall_dbcn_handler(unsigned long extid, unsigned long funcid, + const struct sbi_trap_regs *regs, + unsigned long *out_val, + struct sbi_trap_info *out_trap) +{ + ulong smode = (csr_read(CSR_MSTATUS) & MSTATUS_MPP) >> + MSTATUS_MPP_SHIFT; + + switch (funcid) { + case SBI_EXT_DBCN_CONSOLE_WRITE: + case SBI_EXT_DBCN_CONSOLE_READ: + /* + * On RV32, the M-mode can only access the first 4GB of + * the physical address space because M-mode does not have + * MMU to access full 34-bit physical address space. + * + * Based on above, we simply fail if the upper 32bits of + * the physical address (i.e. a2 register) is non-zero on + * RV32. + * + * Analogously, we fail if the upper 64bit of the + * physical address (i.e. a2 register) is non-zero on + * RV64. + */ + if (regs->a2) + return SBI_ERR_FAILED; + + if (!sbi_domain_check_addr_range(sbi_domain_thishart_ptr(), + regs->a1, regs->a0, smode, + SBI_DOMAIN_READ|SBI_DOMAIN_WRITE)) + return SBI_ERR_INVALID_PARAM; + if (funcid == SBI_EXT_DBCN_CONSOLE_WRITE) + *out_val = sbi_nputs((const char *)regs->a1, regs->a0); + else + *out_val = sbi_ngets((char *)regs->a1, regs->a0); + return 0; + case SBI_EXT_DBCN_CONSOLE_WRITE_BYTE: + sbi_putc(regs->a0); + return 0; + default: + break; + } + + return SBI_ENOTSUPP; +} + +struct sbi_ecall_extension ecall_dbcn; + +static int sbi_ecall_dbcn_register_extensions(void) +{ + if (!sbi_console_get_device()) + return 0; + + return sbi_ecall_register_extension(&ecall_dbcn); +} + +struct sbi_ecall_extension ecall_dbcn = { + .extid_start = SBI_EXT_DBCN, + .extid_end = SBI_EXT_DBCN, + .register_extensions = sbi_ecall_dbcn_register_extensions, + .handle = sbi_ecall_dbcn_handler, +}; diff -Nru opensbi-1.1/lib/sbi/sbi_ecall_exts.carray opensbi-1.3/lib/sbi/sbi_ecall_exts.carray --- opensbi-1.1/lib/sbi/sbi_ecall_exts.carray 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/sbi/sbi_ecall_exts.carray 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,3 @@ +HEADER: sbi/sbi_ecall.h +TYPE: struct sbi_ecall_extension +NAME: sbi_ecall_exts diff -Nru opensbi-1.1/lib/sbi/sbi_ecall_hsm.c opensbi-1.3/lib/sbi/sbi_ecall_hsm.c --- opensbi-1.1/lib/sbi/sbi_ecall_hsm.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_ecall_hsm.c 2023-06-23 07:31:49.000000000 +0200 @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -33,7 +32,7 @@ regs->a0, regs->a1, smode, regs->a2); break; case SBI_EXT_HSM_HART_STOP: - ret = sbi_hsm_hart_stop(scratch, TRUE); + ret = sbi_hsm_hart_stop(scratch, true); break; case SBI_EXT_HSM_HART_GET_STATUS: ret = sbi_hsm_hart_get_state(sbi_domain_thishart_ptr(), @@ -45,7 +44,8 @@ break; default: ret = SBI_ENOTSUPP; - }; + } + if (ret >= 0) { *out_val = ret; ret = 0; @@ -54,8 +54,16 @@ return ret; } +struct sbi_ecall_extension ecall_hsm; + +static int sbi_ecall_hsm_register_extensions(void) +{ + return sbi_ecall_register_extension(&ecall_hsm); +} + struct sbi_ecall_extension ecall_hsm = { - .extid_start = SBI_EXT_HSM, - .extid_end = SBI_EXT_HSM, - .handle = sbi_ecall_hsm_handler, + .extid_start = SBI_EXT_HSM, + .extid_end = SBI_EXT_HSM, + .register_extensions = sbi_ecall_hsm_register_extensions, + .handle = sbi_ecall_hsm_handler, }; diff -Nru opensbi-1.1/lib/sbi/sbi_ecall_ipi.c opensbi-1.3/lib/sbi/sbi_ecall_ipi.c --- opensbi-1.1/lib/sbi/sbi_ecall_ipi.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/sbi/sbi_ecall_ipi.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,44 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel + * Atish Patra + */ + +#include +#include +#include +#include +#include + +static int sbi_ecall_ipi_handler(unsigned long extid, unsigned long funcid, + const struct sbi_trap_regs *regs, + unsigned long *out_val, + struct sbi_trap_info *out_trap) +{ + int ret = 0; + + if (funcid == SBI_EXT_IPI_SEND_IPI) + ret = sbi_ipi_send_smode(regs->a0, regs->a1); + else + ret = SBI_ENOTSUPP; + + return ret; +} + +struct sbi_ecall_extension ecall_ipi; + +static int sbi_ecall_ipi_register_extensions(void) +{ + return sbi_ecall_register_extension(&ecall_ipi); +} + +struct sbi_ecall_extension ecall_ipi = { + .extid_start = SBI_EXT_IPI, + .extid_end = SBI_EXT_IPI, + .register_extensions = sbi_ecall_ipi_register_extensions, + .handle = sbi_ecall_ipi_handler, +}; diff -Nru opensbi-1.1/lib/sbi/sbi_ecall_legacy.c opensbi-1.3/lib/sbi/sbi_ecall_legacy.c --- opensbi-1.1/lib/sbi/sbi_ecall_legacy.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_ecall_legacy.c 2023-06-23 07:31:49.000000000 +0200 @@ -112,13 +112,21 @@ break; default: ret = SBI_ENOTSUPP; - }; + } return ret; } +struct sbi_ecall_extension ecall_legacy; + +static int sbi_ecall_legacy_register_extensions(void) +{ + return sbi_ecall_register_extension(&ecall_legacy); +} + struct sbi_ecall_extension ecall_legacy = { - .extid_start = SBI_EXT_0_1_SET_TIMER, - .extid_end = SBI_EXT_0_1_SHUTDOWN, - .handle = sbi_ecall_legacy_handler, + .extid_start = SBI_EXT_0_1_SET_TIMER, + .extid_end = SBI_EXT_0_1_SHUTDOWN, + .register_extensions = sbi_ecall_legacy_register_extensions, + .handle = sbi_ecall_legacy_handler, }; diff -Nru opensbi-1.1/lib/sbi/sbi_ecall_pmu.c opensbi-1.3/lib/sbi/sbi_ecall_pmu.c --- opensbi-1.1/lib/sbi/sbi_ecall_pmu.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_ecall_pmu.c 2023-06-23 07:31:49.000000000 +0200 @@ -51,7 +51,16 @@ break; case SBI_EXT_PMU_COUNTER_FW_READ: - ret = sbi_pmu_ctr_read(regs->a0, out_val); + ret = sbi_pmu_ctr_fw_read(regs->a0, &temp); + *out_val = temp; + break; + case SBI_EXT_PMU_COUNTER_FW_READ_HI: +#if __riscv_xlen == 32 + ret = sbi_pmu_ctr_fw_read(regs->a0, &temp); + *out_val = temp >> 32; +#else + *out_val = 0; +#endif break; case SBI_EXT_PMU_COUNTER_START: @@ -67,21 +76,21 @@ break; default: ret = SBI_ENOTSUPP; - }; + } return ret; } -static int sbi_ecall_pmu_probe(unsigned long extid, unsigned long *out_val) +struct sbi_ecall_extension ecall_pmu; + +static int sbi_ecall_pmu_register_extensions(void) { - /* PMU extension is always enabled */ - *out_val = 1; - return 0; + return sbi_ecall_register_extension(&ecall_pmu); } struct sbi_ecall_extension ecall_pmu = { - .extid_start = SBI_EXT_PMU, - .extid_end = SBI_EXT_PMU, - .handle = sbi_ecall_pmu_handler, - .probe = sbi_ecall_pmu_probe, + .extid_start = SBI_EXT_PMU, + .extid_end = SBI_EXT_PMU, + .register_extensions = sbi_ecall_pmu_register_extensions, + .handle = sbi_ecall_pmu_handler, }; diff -Nru opensbi-1.1/lib/sbi/sbi_ecall_replace.c opensbi-1.3/lib/sbi/sbi_ecall_replace.c --- opensbi-1.1/lib/sbi/sbi_ecall_replace.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_ecall_replace.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,196 +0,0 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2020 Western Digital Corporation or its affiliates. - * - * Authors: - * Anup Patel - * Atish Patra - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int sbi_ecall_time_handler(unsigned long extid, unsigned long funcid, - const struct sbi_trap_regs *regs, - unsigned long *out_val, - struct sbi_trap_info *out_trap) -{ - int ret = 0; - - if (funcid == SBI_EXT_TIME_SET_TIMER) { -#if __riscv_xlen == 32 - sbi_timer_event_start((((u64)regs->a1 << 32) | (u64)regs->a0)); -#else - sbi_timer_event_start((u64)regs->a0); -#endif - } else - ret = SBI_ENOTSUPP; - - return ret; -} - -struct sbi_ecall_extension ecall_time = { - .extid_start = SBI_EXT_TIME, - .extid_end = SBI_EXT_TIME, - .handle = sbi_ecall_time_handler, -}; - -static int sbi_ecall_rfence_handler(unsigned long extid, unsigned long funcid, - const struct sbi_trap_regs *regs, - unsigned long *out_val, - struct sbi_trap_info *out_trap) -{ - int ret = 0; - unsigned long vmid; - struct sbi_tlb_info tlb_info; - u32 source_hart = current_hartid(); - - if (funcid >= SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID && - funcid <= SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA) - if (!misa_extension('H')) - return SBI_ENOTSUPP; - - switch (funcid) { - case SBI_EXT_RFENCE_REMOTE_FENCE_I: - SBI_TLB_INFO_INIT(&tlb_info, 0, 0, 0, 0, - sbi_tlb_local_fence_i, source_hart); - ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info); - break; - case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA: - SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, 0, 0, - sbi_tlb_local_hfence_gvma, source_hart); - ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info); - break; - case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID: - SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, 0, regs->a4, - sbi_tlb_local_hfence_gvma_vmid, - source_hart); - ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info); - break; - case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA: - vmid = (csr_read(CSR_HGATP) & HGATP_VMID_MASK); - vmid = vmid >> HGATP_VMID_SHIFT; - SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, 0, vmid, - sbi_tlb_local_hfence_vvma, source_hart); - ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info); - break; - case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID: - vmid = (csr_read(CSR_HGATP) & HGATP_VMID_MASK); - vmid = vmid >> HGATP_VMID_SHIFT; - SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, regs->a4, - vmid, sbi_tlb_local_hfence_vvma_asid, - source_hart); - ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info); - break; - case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA: - SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, 0, 0, - sbi_tlb_local_sfence_vma, source_hart); - ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info); - break; - case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID: - SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, regs->a4, 0, - sbi_tlb_local_sfence_vma_asid, source_hart); - ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info); - break; - default: - ret = SBI_ENOTSUPP; - }; - - return ret; -} - -struct sbi_ecall_extension ecall_rfence = { - .extid_start = SBI_EXT_RFENCE, - .extid_end = SBI_EXT_RFENCE, - .handle = sbi_ecall_rfence_handler, -}; - -static int sbi_ecall_ipi_handler(unsigned long extid, unsigned long funcid, - const struct sbi_trap_regs *regs, - unsigned long *out_val, - struct sbi_trap_info *out_trap) -{ - int ret = 0; - - if (funcid == SBI_EXT_IPI_SEND_IPI) - ret = sbi_ipi_send_smode(regs->a0, regs->a1); - else - ret = SBI_ENOTSUPP; - - return ret; -} - -struct sbi_ecall_extension ecall_ipi = { - .extid_start = SBI_EXT_IPI, - .extid_end = SBI_EXT_IPI, - .handle = sbi_ecall_ipi_handler, -}; - -static int sbi_ecall_srst_handler(unsigned long extid, unsigned long funcid, - const struct sbi_trap_regs *regs, - unsigned long *out_val, - struct sbi_trap_info *out_trap) -{ - if (funcid == SBI_EXT_SRST_RESET) { - if ((((u32)-1U) <= ((u64)regs->a0)) || - (((u32)-1U) <= ((u64)regs->a1))) - return SBI_EINVAL; - - switch (regs->a0) { - case SBI_SRST_RESET_TYPE_SHUTDOWN: - case SBI_SRST_RESET_TYPE_COLD_REBOOT: - case SBI_SRST_RESET_TYPE_WARM_REBOOT: - break; - default: - return SBI_EINVAL; - } - - switch (regs->a1) { - case SBI_SRST_RESET_REASON_NONE: - case SBI_SRST_RESET_REASON_SYSFAIL: - break; - default: - return SBI_EINVAL; - } - - if (sbi_system_reset_supported(regs->a0, regs->a1)) - sbi_system_reset(regs->a0, regs->a1); - } - - return SBI_ENOTSUPP; -} - -static int sbi_ecall_srst_probe(unsigned long extid, unsigned long *out_val) -{ - u32 type, count = 0; - - /* - * At least one standard reset types should be supported by - * the platform for SBI SRST extension to be usable. - */ - - for (type = 0; type <= SBI_SRST_RESET_TYPE_LAST; type++) { - if (sbi_system_reset_supported(type, - SBI_SRST_RESET_REASON_NONE)) - count++; - } - - *out_val = (count) ? 1 : 0; - return 0; -} - -struct sbi_ecall_extension ecall_srst = { - .extid_start = SBI_EXT_SRST, - .extid_end = SBI_EXT_SRST, - .handle = sbi_ecall_srst_handler, - .probe = sbi_ecall_srst_probe, -}; diff -Nru opensbi-1.1/lib/sbi/sbi_ecall_rfence.c opensbi-1.3/lib/sbi/sbi_ecall_rfence.c --- opensbi-1.1/lib/sbi/sbi_ecall_rfence.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/sbi/sbi_ecall_rfence.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,94 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel + * Atish Patra + */ + +#include +#include +#include +#include +#include +#include + +static int sbi_ecall_rfence_handler(unsigned long extid, unsigned long funcid, + const struct sbi_trap_regs *regs, + unsigned long *out_val, + struct sbi_trap_info *out_trap) +{ + int ret = 0; + unsigned long vmid; + struct sbi_tlb_info tlb_info; + u32 source_hart = current_hartid(); + + if (funcid >= SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID && + funcid <= SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA) + if (!misa_extension('H')) + return SBI_ENOTSUPP; + + switch (funcid) { + case SBI_EXT_RFENCE_REMOTE_FENCE_I: + SBI_TLB_INFO_INIT(&tlb_info, 0, 0, 0, 0, + sbi_tlb_local_fence_i, source_hart); + ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info); + break; + case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA: + SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, 0, 0, + sbi_tlb_local_hfence_gvma, source_hart); + ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info); + break; + case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID: + SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, 0, regs->a4, + sbi_tlb_local_hfence_gvma_vmid, + source_hart); + ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info); + break; + case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA: + vmid = (csr_read(CSR_HGATP) & HGATP_VMID_MASK); + vmid = vmid >> HGATP_VMID_SHIFT; + SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, 0, vmid, + sbi_tlb_local_hfence_vvma, source_hart); + ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info); + break; + case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID: + vmid = (csr_read(CSR_HGATP) & HGATP_VMID_MASK); + vmid = vmid >> HGATP_VMID_SHIFT; + SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, regs->a4, + vmid, sbi_tlb_local_hfence_vvma_asid, + source_hart); + ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info); + break; + case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA: + SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, 0, 0, + sbi_tlb_local_sfence_vma, source_hart); + ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info); + break; + case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID: + SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, regs->a4, 0, + sbi_tlb_local_sfence_vma_asid, source_hart); + ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info); + break; + default: + ret = SBI_ENOTSUPP; + } + + return ret; +} + +struct sbi_ecall_extension ecall_rfence; + +static int sbi_ecall_rfence_register_extensions(void) +{ + return sbi_ecall_register_extension(&ecall_rfence); +} + +struct sbi_ecall_extension ecall_rfence = { + .extid_start = SBI_EXT_RFENCE, + .extid_end = SBI_EXT_RFENCE, + .register_extensions = sbi_ecall_rfence_register_extensions, + .handle = sbi_ecall_rfence_handler, +}; diff -Nru opensbi-1.1/lib/sbi/sbi_ecall_srst.c opensbi-1.3/lib/sbi/sbi_ecall_srst.c --- opensbi-1.1/lib/sbi/sbi_ecall_srst.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/sbi/sbi_ecall_srst.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,83 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel + * Atish Patra + */ + +#include +#include +#include +#include +#include + +static int sbi_ecall_srst_handler(unsigned long extid, unsigned long funcid, + const struct sbi_trap_regs *regs, + unsigned long *out_val, + struct sbi_trap_info *out_trap) +{ + if (funcid == SBI_EXT_SRST_RESET) { + if ((((u32)-1U) <= ((u64)regs->a0)) || + (((u32)-1U) <= ((u64)regs->a1))) + return SBI_EINVAL; + + switch (regs->a0) { + case SBI_SRST_RESET_TYPE_SHUTDOWN: + case SBI_SRST_RESET_TYPE_COLD_REBOOT: + case SBI_SRST_RESET_TYPE_WARM_REBOOT: + break; + default: + return SBI_EINVAL; + } + + switch (regs->a1) { + case SBI_SRST_RESET_REASON_NONE: + case SBI_SRST_RESET_REASON_SYSFAIL: + break; + default: + return SBI_EINVAL; + } + + if (sbi_system_reset_supported(regs->a0, regs->a1)) + sbi_system_reset(regs->a0, regs->a1); + } + + return SBI_ENOTSUPP; +} + +static bool srst_available(void) +{ + u32 type; + + /* + * At least one standard reset types should be supported by + * the platform for SBI SRST extension to be usable. + */ + for (type = 0; type <= SBI_SRST_RESET_TYPE_LAST; type++) { + if (sbi_system_reset_supported(type, + SBI_SRST_RESET_REASON_NONE)) + return true; + } + + return false; +} + +struct sbi_ecall_extension ecall_srst; + +static int sbi_ecall_srst_register_extensions(void) +{ + if (!srst_available()) + return 0; + + return sbi_ecall_register_extension(&ecall_srst); +} + +struct sbi_ecall_extension ecall_srst = { + .extid_start = SBI_EXT_SRST, + .extid_end = SBI_EXT_SRST, + .register_extensions = sbi_ecall_srst_register_extensions, + .handle = sbi_ecall_srst_handler, +}; diff -Nru opensbi-1.1/lib/sbi/sbi_ecall_susp.c opensbi-1.3/lib/sbi/sbi_ecall_susp.c --- opensbi-1.1/lib/sbi/sbi_ecall_susp.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/sbi/sbi_ecall_susp.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: BSD-2-Clause +#include +#include +#include +#include +#include + +static int sbi_ecall_susp_handler(unsigned long extid, unsigned long funcid, + const struct sbi_trap_regs *regs, + unsigned long *out_val, + struct sbi_trap_info *out_trap) +{ + int ret = SBI_ENOTSUPP; + + if (funcid == SBI_EXT_SUSP_SUSPEND) + ret = sbi_system_suspend(regs->a0, regs->a1, regs->a2); + + if (ret >= 0) { + *out_val = ret; + ret = 0; + } + + return ret; +} + +static bool susp_available(void) +{ + u32 type; + + /* + * At least one suspend type should be supported by the + * platform for the SBI SUSP extension to be usable. + */ + for (type = 0; type <= SBI_SUSP_SLEEP_TYPE_LAST; type++) { + if (sbi_system_suspend_supported(type)) + return true; + } + + return false; +} + +struct sbi_ecall_extension ecall_susp; + +static int sbi_ecall_susp_register_extensions(void) +{ + if (!susp_available()) + return 0; + + return sbi_ecall_register_extension(&ecall_susp); +} + +struct sbi_ecall_extension ecall_susp = { + .extid_start = SBI_EXT_SUSP, + .extid_end = SBI_EXT_SUSP, + .register_extensions = sbi_ecall_susp_register_extensions, + .handle = sbi_ecall_susp_handler, +}; diff -Nru opensbi-1.1/lib/sbi/sbi_ecall_time.c opensbi-1.3/lib/sbi/sbi_ecall_time.c --- opensbi-1.1/lib/sbi/sbi_ecall_time.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/sbi/sbi_ecall_time.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,48 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel + * Atish Patra + */ + +#include +#include +#include +#include +#include + +static int sbi_ecall_time_handler(unsigned long extid, unsigned long funcid, + const struct sbi_trap_regs *regs, + unsigned long *out_val, + struct sbi_trap_info *out_trap) +{ + int ret = 0; + + if (funcid == SBI_EXT_TIME_SET_TIMER) { +#if __riscv_xlen == 32 + sbi_timer_event_start((((u64)regs->a1 << 32) | (u64)regs->a0)); +#else + sbi_timer_event_start((u64)regs->a0); +#endif + } else + ret = SBI_ENOTSUPP; + + return ret; +} + +struct sbi_ecall_extension ecall_time; + +static int sbi_ecall_time_register_extensions(void) +{ + return sbi_ecall_register_extension(&ecall_time); +} + +struct sbi_ecall_extension ecall_time = { + .extid_start = SBI_EXT_TIME, + .extid_end = SBI_EXT_TIME, + .register_extensions = sbi_ecall_time_register_extensions, + .handle = sbi_ecall_time_handler, +}; diff -Nru opensbi-1.1/lib/sbi/sbi_ecall_vendor.c opensbi-1.3/lib/sbi/sbi_ecall_vendor.c --- opensbi-1.1/lib/sbi/sbi_ecall_vendor.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_ecall_vendor.c 2023-06-23 07:31:49.000000000 +0200 @@ -13,13 +13,13 @@ #include #include #include +#include -static int sbi_ecall_vendor_probe(unsigned long extid, - unsigned long *out_val) +static inline unsigned long sbi_ecall_vendor_id(void) { - *out_val = sbi_platform_vendor_ext_check(sbi_platform_thishart_ptr(), - extid); - return 0; + return SBI_EXT_VENDOR_START + + (csr_read(CSR_MVENDORID) & + (SBI_EXT_VENDOR_END - SBI_EXT_VENDOR_START)); } static int sbi_ecall_vendor_handler(unsigned long extid, unsigned long funcid, @@ -28,13 +28,28 @@ struct sbi_trap_info *out_trap) { return sbi_platform_vendor_ext_provider(sbi_platform_thishart_ptr(), - extid, funcid, regs, + funcid, regs, out_val, out_trap); } +struct sbi_ecall_extension ecall_vendor; + +static int sbi_ecall_vendor_register_extensions(void) +{ + unsigned long extid = sbi_ecall_vendor_id(); + + if (!sbi_platform_vendor_ext_check(sbi_platform_thishart_ptr())) + return 0; + + ecall_vendor.extid_start = extid; + ecall_vendor.extid_end = extid; + + return sbi_ecall_register_extension(&ecall_vendor); +} + struct sbi_ecall_extension ecall_vendor = { - .extid_start = SBI_EXT_VENDOR_START, - .extid_end = SBI_EXT_VENDOR_END, - .probe = sbi_ecall_vendor_probe, - .handle = sbi_ecall_vendor_handler, + .extid_start = SBI_EXT_VENDOR_START, + .extid_end = SBI_EXT_VENDOR_END, + .register_extensions = sbi_ecall_vendor_register_extensions, + .handle = sbi_ecall_vendor_handler, }; diff -Nru opensbi-1.1/lib/sbi/sbi_emulate_csr.c opensbi-1.3/lib/sbi/sbi_emulate_csr.c --- opensbi-1.1/lib/sbi/sbi_emulate_csr.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_emulate_csr.c 2023-06-23 07:31:49.000000000 +0200 @@ -39,7 +39,7 @@ cen = 0; } - return ((cen >> hpm_num) & 1) ? TRUE : FALSE; + return ((cen >> hpm_num) & 1) ? true : false; } int sbi_emulate_csr_read(int csr_num, struct sbi_trap_regs *regs, @@ -49,9 +49,9 @@ struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); ulong prev_mode = (regs->mstatus & MSTATUS_MPP) >> MSTATUS_MPP_SHIFT; #if __riscv_xlen == 32 - bool virt = (regs->mstatusH & MSTATUSH_MPV) ? TRUE : FALSE; + bool virt = (regs->mstatusH & MSTATUSH_MPV) ? true : false; #else - bool virt = (regs->mstatus & MSTATUS_MPV) ? TRUE : FALSE; + bool virt = (regs->mstatus & MSTATUS_MPV) ? true : false; #endif switch (csr_num) { @@ -149,7 +149,7 @@ default: ret = SBI_ENOTSUPP; break; - }; + } if (ret) sbi_dprintf("%s: hartid%d: invalid csr_num=0x%x\n", @@ -164,9 +164,9 @@ int ret = 0; ulong prev_mode = (regs->mstatus & MSTATUS_MPP) >> MSTATUS_MPP_SHIFT; #if __riscv_xlen == 32 - bool virt = (regs->mstatusH & MSTATUSH_MPV) ? TRUE : FALSE; + bool virt = (regs->mstatusH & MSTATUSH_MPV) ? true : false; #else - bool virt = (regs->mstatus & MSTATUS_MPV) ? TRUE : FALSE; + bool virt = (regs->mstatus & MSTATUS_MPV) ? true : false; #endif switch (csr_num) { @@ -187,7 +187,7 @@ default: ret = SBI_ENOTSUPP; break; - }; + } if (ret) sbi_dprintf("%s: hartid%d: invalid csr_num=0x%x\n", diff -Nru opensbi-1.1/lib/sbi/sbi_expected_trap.S opensbi-1.3/lib/sbi/sbi_expected_trap.S --- opensbi-1.1/lib/sbi/sbi_expected_trap.S 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_expected_trap.S 2023-06-23 07:31:49.000000000 +0200 @@ -11,7 +11,7 @@ #include /* - * We assume that faulting instruction is is 4-byte long and blindly + * We assume that faulting instruction is 4-byte long and blindly * increment SEPC by 4. * * The trap info will be saved as follows: @@ -22,7 +22,7 @@ .align 3 .global __sbi_expected_trap __sbi_expected_trap: - /* Without H-extension so, MTVAL2 and MTINST CSRs not available */ + /* Without H-extension so, MTVAL2 and MTINST CSRs and GVA not available */ csrr a4, CSR_MEPC REG_S a4, SBI_TRAP_INFO_OFFSET(epc)(a3) csrr a4, CSR_MCAUSE @@ -31,6 +31,7 @@ REG_S a4, SBI_TRAP_INFO_OFFSET(tval)(a3) REG_S zero, SBI_TRAP_INFO_OFFSET(tval2)(a3) REG_S zero, SBI_TRAP_INFO_OFFSET(tinst)(a3) + REG_S zero, SBI_TRAP_INFO_OFFSET(gva)(a3) csrr a4, CSR_MEPC addi a4, a4, 4 csrw CSR_MEPC, a4 @@ -39,7 +40,7 @@ .align 3 .global __sbi_expected_trap_hext __sbi_expected_trap_hext: - /* With H-extension so, MTVAL2 and MTINST CSRs available */ + /* With H-extension so, MTVAL2 and MTINST CSRs and GVA available */ csrr a4, CSR_MEPC REG_S a4, SBI_TRAP_INFO_OFFSET(epc)(a3) csrr a4, CSR_MCAUSE @@ -50,6 +51,18 @@ REG_S a4, SBI_TRAP_INFO_OFFSET(tval2)(a3) csrr a4, CSR_MTINST REG_S a4, SBI_TRAP_INFO_OFFSET(tinst)(a3) + + /* Extract GVA bit from MSTATUS or MSTATUSH */ +#if __riscv_xlen == 32 + csrr a4, CSR_MSTATUSH + srli a4, a4, MSTATUSH_GVA_SHIFT +#else + csrr a4, CSR_MSTATUS + srli a4, a4, MSTATUS_GVA_SHIFT +#endif + andi a4, a4, 1 + REG_S a4, SBI_TRAP_INFO_OFFSET(gva)(a3) + csrr a4, CSR_MEPC addi a4, a4, 4 csrw CSR_MEPC, a4 diff -Nru opensbi-1.1/lib/sbi/sbi_fifo.c opensbi-1.3/lib/sbi/sbi_fifo.c --- opensbi-1.1/lib/sbi/sbi_fifo.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_fifo.c 2023-06-23 07:31:49.000000000 +0200 @@ -26,7 +26,7 @@ /* Note: must be called with fifo->qlock held */ static inline bool __sbi_fifo_is_full(struct sbi_fifo *fifo) { - return (fifo->avail == fifo->num_entries) ? TRUE : FALSE; + return (fifo->avail == fifo->num_entries) ? true : false; } u16 sbi_fifo_avail(struct sbi_fifo *fifo) @@ -75,7 +75,7 @@ /* Note: must be called with fifo->qlock held */ static inline bool __sbi_fifo_is_empty(struct sbi_fifo *fifo) { - return (fifo->avail == 0) ? TRUE : FALSE; + return (fifo->avail == 0) ? true : false; } int sbi_fifo_is_empty(struct sbi_fifo *fifo) @@ -105,13 +105,13 @@ bool sbi_fifo_reset(struct sbi_fifo *fifo) { if (!fifo) - return FALSE; + return false; spin_lock(&fifo->qlock); __sbi_fifo_reset(fifo); spin_unlock(&fifo->qlock); - return TRUE; + return true; } /** diff -Nru opensbi-1.1/lib/sbi/sbi_hart.c opensbi-1.3/lib/sbi/sbi_hart.c --- opensbi-1.1/lib/sbi/sbi_hart.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_hart.c 2023-06-23 07:31:49.000000000 +0200 @@ -19,24 +19,16 @@ #include #include #include +#include #include #include +#include extern void __sbi_expected_trap(void); extern void __sbi_expected_trap_hext(void); void (*sbi_hart_expected_trap)(void) = &__sbi_expected_trap; -struct hart_features { - bool detected; - int priv_version; - unsigned long extensions; - unsigned int pmp_count; - unsigned int pmp_addr_bits; - unsigned long pmp_gran; - unsigned int mhpm_count; - unsigned int mhpm_bits; -}; static unsigned long hart_features_offset; static void mstatus_init(struct sbi_scratch *scratch) @@ -98,9 +90,10 @@ mstateen_val |= ((uint64_t)csr_read(CSR_MSTATEEN0H)) << 32; #endif mstateen_val |= SMSTATEEN_STATEN; + mstateen_val |= SMSTATEEN0_CONTEXT; mstateen_val |= SMSTATEEN0_HSENVCFG; - if (sbi_hart_has_extension(scratch, SBI_HART_EXT_AIA)) + if (sbi_hart_has_extension(scratch, SBI_HART_EXT_SMAIA)) mstateen_val |= (SMSTATEEN0_AIA | SMSTATEEN0_SVSLCT | SMSTATEEN0_IMSIC); else @@ -208,8 +201,7 @@ /* Send M-mode interrupts and most exceptions to S-mode */ interrupts = MIP_SSIP | MIP_STIP | MIP_SEIP; - if (sbi_hart_has_extension(scratch, SBI_HART_EXT_SSCOFPMF)) - interrupts |= MIP_LCOFIP; + interrupts |= sbi_pmu_irq_bit(); exceptions = (1U << CAUSE_MISALIGNED_FETCH) | (1U << CAUSE_BREAKPOINT) | (1U << CAUSE_USER_ECALL); @@ -254,7 +246,7 @@ unsigned int sbi_hart_mhpm_count(struct sbi_scratch *scratch) { - struct hart_features *hfeatures = + struct sbi_hart_features *hfeatures = sbi_scratch_offset_ptr(scratch, hart_features_offset); return hfeatures->mhpm_count; @@ -262,7 +254,7 @@ unsigned int sbi_hart_pmp_count(struct sbi_scratch *scratch) { - struct hart_features *hfeatures = + struct sbi_hart_features *hfeatures = sbi_scratch_offset_ptr(scratch, hart_features_offset); return hfeatures->pmp_count; @@ -270,7 +262,7 @@ unsigned long sbi_hart_pmp_granularity(struct sbi_scratch *scratch) { - struct hart_features *hfeatures = + struct sbi_hart_features *hfeatures = sbi_scratch_offset_ptr(scratch, hart_features_offset); return hfeatures->pmp_gran; @@ -278,7 +270,7 @@ unsigned int sbi_hart_pmp_addrbits(struct sbi_scratch *scratch) { - struct hart_features *hfeatures = + struct sbi_hart_features *hfeatures = sbi_scratch_offset_ptr(scratch, hart_features_offset); return hfeatures->pmp_addr_bits; @@ -286,7 +278,7 @@ unsigned int sbi_hart_mhpm_bits(struct sbi_scratch *scratch) { - struct hart_features *hfeatures = + struct sbi_hart_features *hfeatures = sbi_scratch_offset_ptr(scratch, hart_features_offset); return hfeatures->mhpm_bits; @@ -312,14 +304,20 @@ break; pmp_flags = 0; - if (reg->flags & SBI_DOMAIN_MEMREGION_READABLE) + + /* + * If permissions are to be enforced for all modes on this + * region, the lock bit should be set. + */ + if (reg->flags & SBI_DOMAIN_MEMREGION_ENF_PERMISSIONS) + pmp_flags |= PMP_L; + + if (reg->flags & SBI_DOMAIN_MEMREGION_SU_READABLE) pmp_flags |= PMP_R; - if (reg->flags & SBI_DOMAIN_MEMREGION_WRITEABLE) + if (reg->flags & SBI_DOMAIN_MEMREGION_SU_WRITABLE) pmp_flags |= PMP_W; - if (reg->flags & SBI_DOMAIN_MEMREGION_EXECUTABLE) + if (reg->flags & SBI_DOMAIN_MEMREGION_SU_EXECUTABLE) pmp_flags |= PMP_X; - if (reg->flags & SBI_DOMAIN_MEMREGION_MMODE) - pmp_flags |= PMP_L; pmp_addr = reg->base >> PMP_SHIFT; if (pmp_gran_log2 <= reg->order && pmp_addr < pmp_addr_max) @@ -331,12 +329,33 @@ } } + /* + * As per section 3.7.2 of privileged specification v1.12, + * virtual address translations can be speculatively performed + * (even before actual access). These, along with PMP traslations, + * can be cached. This can pose a problem with CPU hotplug + * and non-retentive suspend scenario because PMP states are + * not preserved. + * It is advisable to flush the caching structures under such + * conditions. + */ + if (misa_extension('S')) { + __asm__ __volatile__("sfence.vma"); + + /* + * If hypervisor mode is supported, flush caching + * structures in guest mode too. + */ + if (misa_extension('H')) + __sbi_hfence_gvma_all(); + } + return 0; } int sbi_hart_priv_version(struct sbi_scratch *scratch) { - struct hart_features *hfeatures = + struct sbi_hart_features *hfeatures = sbi_scratch_offset_ptr(scratch, hart_features_offset); return hfeatures->priv_version; @@ -346,7 +365,7 @@ char *version_str, int nvstr) { char *temp; - struct hart_features *hfeatures = + struct sbi_hart_features *hfeatures = sbi_scratch_offset_ptr(scratch, hart_features_offset); switch (hfeatures->priv_version) { @@ -368,7 +387,7 @@ } static inline void __sbi_hart_update_extension( - struct hart_features *hfeatures, + struct sbi_hart_features *hfeatures, enum sbi_hart_extensions ext, bool enable) { @@ -389,7 +408,7 @@ enum sbi_hart_extensions ext, bool enable) { - struct hart_features *hfeatures = + struct sbi_hart_features *hfeatures = sbi_scratch_offset_ptr(scratch, hart_features_offset); __sbi_hart_update_extension(hfeatures, ext, enable); @@ -405,7 +424,7 @@ bool sbi_hart_has_extension(struct sbi_scratch *scratch, enum sbi_hart_extensions ext) { - struct hart_features *hfeatures = + struct sbi_hart_features *hfeatures = sbi_scratch_offset_ptr(scratch, hart_features_offset); if (hfeatures->extensions & BIT(ext)) @@ -425,8 +444,8 @@ case SBI_HART_EXT_TIME: estr = "time"; break; - case SBI_HART_EXT_AIA: - estr = "aia"; + case SBI_HART_EXT_SMAIA: + estr = "smaia"; break; case SBI_HART_EXT_SSTC: estr = "sstc"; @@ -453,7 +472,7 @@ void sbi_hart_get_extensions_str(struct sbi_scratch *scratch, char *extensions_str, int nestr) { - struct hart_features *hfeatures = + struct sbi_hart_features *hfeatures = sbi_scratch_offset_ptr(scratch, hart_features_offset); int offset = 0, ext = 0; char *temp; @@ -539,7 +558,7 @@ static int hart_detect_features(struct sbi_scratch *scratch) { struct sbi_trap_info trap = {0}; - struct hart_features *hfeatures = + struct sbi_hart_features *hfeatures = sbi_scratch_offset_ptr(scratch, hart_features_offset); unsigned long val, oldval; int rc; @@ -663,7 +682,7 @@ csr_read_allowed(CSR_MTOPI, (unsigned long)&trap); if (!trap.cause) __sbi_hart_update_extension(hfeatures, - SBI_HART_EXT_AIA, true); + SBI_HART_EXT_SMAIA, true); /* Detect if hart supports stimecmp CSR(Sstc extension) */ if (hfeatures->priv_version >= SBI_HART_PRIV_VER_1_12) { @@ -682,7 +701,8 @@ } /* Let platform populate extensions */ - rc = sbi_platform_extensions_init(sbi_platform_thishart_ptr()); + rc = sbi_platform_extensions_init(sbi_platform_thishart_ptr(), + hfeatures); if (rc) return rc; @@ -713,12 +733,18 @@ { int rc; + /* + * Clear mip CSR before proceeding with init to avoid any spurious + * external interrupts in S-mode. + */ + csr_write(CSR_MIP, 0); + if (cold_boot) { if (misa_extension('H')) sbi_hart_expected_trap = &__sbi_expected_trap_hext; hart_features_offset = sbi_scratch_alloc_offset( - sizeof(struct hart_features)); + sizeof(struct sbi_hart_features)); if (!hart_features_offset) return SBI_ENOMEM; } @@ -769,19 +795,12 @@ #if __riscv_xlen == 32 if (misa_extension('H')) { valH = csr_read(CSR_MSTATUSH); - if (next_virt) - valH = INSERT_FIELD(valH, MSTATUSH_MPV, 1); - else - valH = INSERT_FIELD(valH, MSTATUSH_MPV, 0); + valH = INSERT_FIELD(valH, MSTATUSH_MPV, next_virt); csr_write(CSR_MSTATUSH, valH); } #else - if (misa_extension('H')) { - if (next_virt) - val = INSERT_FIELD(val, MSTATUS_MPV, 1); - else - val = INSERT_FIELD(val, MSTATUS_MPV, 0); - } + if (misa_extension('H')) + val = INSERT_FIELD(val, MSTATUS_MPV, next_virt); #endif csr_write(CSR_MSTATUS, val); csr_write(CSR_MEPC, next_addr); diff -Nru opensbi-1.1/lib/sbi/sbi_heap.c opensbi-1.3/lib/sbi/sbi_heap.c --- opensbi-1.1/lib/sbi/sbi_heap.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/sbi/sbi_heap.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,206 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Ventana Micro Systems Inc. + * + * Authors: + * Anup Patel + */ + +#include +#include +#include +#include +#include +#include + +/* Alignment of heap base address and size */ +#define HEAP_BASE_ALIGN 1024 +/* Minimum size and alignment of heap allocations */ +#define HEAP_ALLOC_ALIGN 64 +#define HEAP_HOUSEKEEPING_FACTOR 16 + +struct heap_node { + struct sbi_dlist head; + unsigned long addr; + unsigned long size; +}; + +struct heap_control { + spinlock_t lock; + unsigned long base; + unsigned long size; + unsigned long hkbase; + unsigned long hksize; + struct sbi_dlist free_node_list; + struct sbi_dlist free_space_list; + struct sbi_dlist used_space_list; +}; + +static struct heap_control hpctrl; + +void *sbi_malloc(size_t size) +{ + void *ret = NULL; + struct heap_node *n, *np; + + if (!size) + return NULL; + + size += HEAP_ALLOC_ALIGN - 1; + size &= ~((unsigned long)HEAP_ALLOC_ALIGN - 1); + + spin_lock(&hpctrl.lock); + + np = NULL; + sbi_list_for_each_entry(n, &hpctrl.free_space_list, head) { + if (size <= n->size) { + np = n; + break; + } + } + if (np) { + if ((size < np->size) && + !sbi_list_empty(&hpctrl.free_node_list)) { + n = sbi_list_first_entry(&hpctrl.free_node_list, + struct heap_node, head); + sbi_list_del(&n->head); + n->addr = np->addr + np->size - size; + n->size = size; + np->size -= size; + sbi_list_add_tail(&n->head, &hpctrl.used_space_list); + ret = (void *)n->addr; + } else if (size == np->size) { + sbi_list_del(&np->head); + sbi_list_add_tail(&np->head, &hpctrl.used_space_list); + ret = (void *)np->addr; + } + } + + spin_unlock(&hpctrl.lock); + + return ret; +} + +void *sbi_zalloc(size_t size) +{ + void *ret = sbi_malloc(size); + + if (ret) + sbi_memset(ret, 0, size); + return ret; +} + +void sbi_free(void *ptr) +{ + struct heap_node *n, *np; + + if (!ptr) + return; + + spin_lock(&hpctrl.lock); + + np = NULL; + sbi_list_for_each_entry(n, &hpctrl.used_space_list, head) { + if ((n->addr <= (unsigned long)ptr) && + ((unsigned long)ptr < (n->addr + n->size))) { + np = n; + break; + } + } + if (!np) { + spin_unlock(&hpctrl.lock); + return; + } + + sbi_list_del(&np->head); + + sbi_list_for_each_entry(n, &hpctrl.free_space_list, head) { + if ((np->addr + np->size) == n->addr) { + n->addr = np->addr; + n->size += np->size; + sbi_list_add_tail(&np->head, &hpctrl.free_node_list); + np = NULL; + break; + } else if (np->addr == (n->addr + n->size)) { + n->size += np->size; + sbi_list_add_tail(&np->head, &hpctrl.free_node_list); + np = NULL; + break; + } else if ((n->addr + n->size) < np->addr) { + sbi_list_add(&np->head, &n->head); + np = NULL; + break; + } + } + if (np) + sbi_list_add_tail(&np->head, &hpctrl.free_space_list); + + spin_unlock(&hpctrl.lock); +} + +unsigned long sbi_heap_free_space(void) +{ + struct heap_node *n; + unsigned long ret = 0; + + spin_lock(&hpctrl.lock); + sbi_list_for_each_entry(n, &hpctrl.free_space_list, head) + ret += n->size; + spin_unlock(&hpctrl.lock); + + return ret; +} + +unsigned long sbi_heap_used_space(void) +{ + return hpctrl.size - hpctrl.hksize - sbi_heap_free_space(); +} + +unsigned long sbi_heap_reserved_space(void) +{ + return hpctrl.hksize; +} + +int sbi_heap_init(struct sbi_scratch *scratch) +{ + unsigned long i; + struct heap_node *n; + + /* Sanity checks on heap offset and size */ + if (!scratch->fw_heap_size || + (scratch->fw_heap_size & (HEAP_BASE_ALIGN - 1)) || + (scratch->fw_heap_offset < scratch->fw_rw_offset) || + (scratch->fw_size < (scratch->fw_heap_offset + scratch->fw_heap_size)) || + (scratch->fw_heap_offset & (HEAP_BASE_ALIGN - 1))) + return SBI_EINVAL; + + /* Initialize heap control */ + SPIN_LOCK_INIT(hpctrl.lock); + hpctrl.base = scratch->fw_start + scratch->fw_heap_offset; + hpctrl.size = scratch->fw_heap_size; + hpctrl.hkbase = hpctrl.base; + hpctrl.hksize = hpctrl.size / HEAP_HOUSEKEEPING_FACTOR; + hpctrl.hksize &= ~((unsigned long)HEAP_BASE_ALIGN - 1); + SBI_INIT_LIST_HEAD(&hpctrl.free_node_list); + SBI_INIT_LIST_HEAD(&hpctrl.free_space_list); + SBI_INIT_LIST_HEAD(&hpctrl.used_space_list); + + /* Prepare free node list */ + for (i = 0; i < (hpctrl.hksize / sizeof(*n)); i++) { + n = (struct heap_node *)(hpctrl.hkbase + (sizeof(*n) * i)); + SBI_INIT_LIST_HEAD(&n->head); + n->addr = n->size = 0; + sbi_list_add_tail(&n->head, &hpctrl.free_node_list); + } + + /* Prepare free space list */ + n = sbi_list_first_entry(&hpctrl.free_node_list, + struct heap_node, head); + sbi_list_del(&n->head); + n->addr = hpctrl.hkbase + hpctrl.hksize; + n->size = hpctrl.size - hpctrl.hksize; + sbi_list_add_tail(&n->head, &hpctrl.free_space_list); + + return 0; +} diff -Nru opensbi-1.1/lib/sbi/sbi_hsm.c opensbi-1.3/lib/sbi/sbi_hsm.c --- opensbi-1.1/lib/sbi/sbi_hsm.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_hsm.c 2023-06-23 07:31:49.000000000 +0200 @@ -26,6 +26,15 @@ #include #include +#define __sbi_hsm_hart_change_state(hdata, oldstate, newstate) \ +({ \ + long state = atomic_cmpxchg(&(hdata)->state, oldstate, newstate); \ + if (state != (oldstate)) \ + sbi_printf("%s: ERR: The hart is in invalid state [%lu]\n", \ + __func__, state); \ + state == (oldstate); \ +}) + static const struct sbi_hsm_device *hsm_dev = NULL; static unsigned long hart_data_offset; @@ -35,9 +44,18 @@ unsigned long suspend_type; unsigned long saved_mie; unsigned long saved_mip; + atomic_t start_ticket; }; -static inline int __sbi_hsm_hart_get_state(u32 hartid) +bool sbi_hsm_hart_change_state(struct sbi_scratch *scratch, long oldstate, + long newstate) +{ + struct sbi_hsm_data *hdata = sbi_scratch_offset_ptr(scratch, + hart_data_offset); + return __sbi_hsm_hart_change_state(hdata, oldstate, newstate); +} + +int __sbi_hsm_hart_get_state(u32 hartid) { struct sbi_hsm_data *hdata; struct sbi_scratch *scratch; @@ -58,6 +76,32 @@ return __sbi_hsm_hart_get_state(hartid); } +/* + * Try to acquire the ticket for the given target hart to make sure only + * one hart prepares the start of the target hart. + * Returns true if the ticket has been acquired, false otherwise. + * + * The function has "acquire" semantics: no memory operations following it + * in the current hart can be seen before it by other harts. + * atomic_cmpxchg() provides the memory barriers needed for that. + */ +static bool hsm_start_ticket_acquire(struct sbi_hsm_data *hdata) +{ + return (atomic_cmpxchg(&hdata->start_ticket, 0, 1) == 0); +} + +/* + * Release the ticket for the given target hart. + * + * The function has "release" semantics: no memory operations preceding it + * in the current hart can be seen after it by other harts. + */ +static void hsm_start_ticket_release(struct sbi_hsm_data *hdata) +{ + RISCV_FENCE(rw, w); + atomic_write(&hdata->start_ticket, 0); +} + /** * Get ulong HART mask for given HART base ID * @param dom the domain to be used for output HART mask @@ -93,16 +137,25 @@ return 0; } -void sbi_hsm_prepare_next_jump(struct sbi_scratch *scratch, u32 hartid) +void __noreturn sbi_hsm_hart_start_finish(struct sbi_scratch *scratch, + u32 hartid) { - u32 oldstate; + unsigned long next_arg1; + unsigned long next_addr; + unsigned long next_mode; struct sbi_hsm_data *hdata = sbi_scratch_offset_ptr(scratch, hart_data_offset); - oldstate = atomic_cmpxchg(&hdata->state, SBI_HSM_STATE_START_PENDING, - SBI_HSM_STATE_STARTED); - if (oldstate != SBI_HSM_STATE_START_PENDING) + if (!__sbi_hsm_hart_change_state(hdata, SBI_HSM_STATE_START_PENDING, + SBI_HSM_STATE_STARTED)) sbi_hart_hang(); + + next_arg1 = scratch->next_arg1; + next_addr = scratch->next_addr; + next_mode = scratch->next_mode; + hsm_start_ticket_release(hdata); + + sbi_hart_switch_mode(hartid, next_arg1, next_addr, next_mode, false); } static void sbi_hsm_hart_wait(struct sbi_scratch *scratch, u32 hartid) @@ -116,10 +169,10 @@ /* Set MSIE and MEIE bits to receive IPI */ csr_set(CSR_MIE, MIP_MSIP | MIP_MEIP); - /* Wait for hart_add call*/ + /* Wait for state transition requested by sbi_hsm_hart_start() */ while (atomic_read(&hdata->state) != SBI_HSM_STATE_START_PENDING) { wfi(); - }; + } /* Restore MIE CSR */ csr_write(CSR_MIE, saved_mie); @@ -207,6 +260,7 @@ (i == hartid) ? SBI_HSM_STATE_START_PENDING : SBI_HSM_STATE_STOPPED); + ATOMIC_INIT(&hdata->start_ticket, 0); } } else { sbi_hsm_hart_wait(scratch, hartid); @@ -217,20 +271,17 @@ void __noreturn sbi_hsm_exit(struct sbi_scratch *scratch) { - u32 hstate; struct sbi_hsm_data *hdata = sbi_scratch_offset_ptr(scratch, hart_data_offset); void (*jump_warmboot)(void) = (void (*)(void))scratch->warmboot_addr; - hstate = atomic_cmpxchg(&hdata->state, SBI_HSM_STATE_STOP_PENDING, - SBI_HSM_STATE_STOPPED); - if (hstate != SBI_HSM_STATE_STOP_PENDING) + if (!__sbi_hsm_hart_change_state(hdata, SBI_HSM_STATE_STOP_PENDING, + SBI_HSM_STATE_STOPPED)) goto fail_exit; if (hsm_device_has_hart_hotplug()) { - hsm_device_hart_stop(); - /* It should never reach here */ - goto fail_exit; + if (hsm_device_hart_stop() != SBI_ENOTSUPP) + goto fail_exit; } /** @@ -248,12 +299,13 @@ int sbi_hsm_hart_start(struct sbi_scratch *scratch, const struct sbi_domain *dom, - u32 hartid, ulong saddr, ulong smode, ulong priv) + u32 hartid, ulong saddr, ulong smode, ulong arg1) { - unsigned long init_count; + unsigned long init_count, entry_count; unsigned int hstate; struct sbi_scratch *rscratch; struct sbi_hsm_data *hdata; + int rc; /* For now, we only allow start mode to be S-mode or U-mode. */ if (smode != PRV_S && smode != PRV_U) @@ -267,37 +319,55 @@ rscratch = sbi_hartid_to_scratch(hartid); if (!rscratch) return SBI_EINVAL; + hdata = sbi_scratch_offset_ptr(rscratch, hart_data_offset); + if (!hsm_start_ticket_acquire(hdata)) + return SBI_EINVAL; + + init_count = sbi_init_count(hartid); + entry_count = sbi_entry_count(hartid); + + rscratch->next_arg1 = arg1; + rscratch->next_addr = saddr; + rscratch->next_mode = smode; + + /* + * atomic_cmpxchg() is an implicit barrier. It makes sure that + * other harts see reading of init_count and writing to *rscratch + * before hdata->state is set to SBI_HSM_STATE_START_PENDING. + */ hstate = atomic_cmpxchg(&hdata->state, SBI_HSM_STATE_STOPPED, SBI_HSM_STATE_START_PENDING); - if (hstate == SBI_HSM_STATE_STARTED) - return SBI_EALREADY; + if (hstate == SBI_HSM_STATE_STARTED) { + rc = SBI_EALREADY; + goto err; + } /** * if a hart is already transition to start or stop, another start call * is considered as invalid request. */ - if (hstate != SBI_HSM_STATE_STOPPED) - return SBI_EINVAL; - - init_count = sbi_init_count(hartid); - rscratch->next_arg1 = priv; - rscratch->next_addr = saddr; - rscratch->next_mode = smode; + if (hstate != SBI_HSM_STATE_STOPPED) { + rc = SBI_EINVAL; + goto err; + } - if (hsm_device_has_hart_hotplug() || + if ((hsm_device_has_hart_hotplug() && (entry_count == init_count)) || (hsm_device_has_hart_secondary_boot() && !init_count)) { - return hsm_device_hart_start(hartid, scratch->warmboot_addr); + rc = hsm_device_hart_start(hartid, scratch->warmboot_addr); } else { - sbi_ipi_raw_send(hartid); + rc = sbi_ipi_raw_send(hartid); } - return 0; + if (!rc) + return 0; +err: + hsm_start_ticket_release(hdata); + return rc; } int sbi_hsm_hart_stop(struct sbi_scratch *scratch, bool exitnow) { - int oldstate; const struct sbi_domain *dom = sbi_domain_thishart_ptr(); struct sbi_hsm_data *hdata = sbi_scratch_offset_ptr(scratch, hart_data_offset); @@ -305,13 +375,9 @@ if (!dom) return SBI_EFAIL; - oldstate = atomic_cmpxchg(&hdata->state, SBI_HSM_STATE_STARTED, - SBI_HSM_STATE_STOP_PENDING); - if (oldstate != SBI_HSM_STATE_STARTED) { - sbi_printf("%s: ERR: The hart is in invalid state [%u]\n", - __func__, oldstate); + if (!__sbi_hsm_hart_change_state(hdata, SBI_HSM_STATE_STARTED, + SBI_HSM_STATE_STOP_PENDING)) return SBI_EFAIL; - } if (exitnow) sbi_exit(scratch); @@ -327,7 +393,7 @@ return 0; } -static void __sbi_hsm_suspend_non_ret_save(struct sbi_scratch *scratch) +void __sbi_hsm_suspend_non_ret_save(struct sbi_scratch *scratch) { struct sbi_hsm_data *hdata = sbi_scratch_offset_ptr(scratch, hart_data_offset); @@ -356,62 +422,55 @@ hart_data_offset); csr_write(CSR_MIE, hdata->saved_mie); - csr_write(CSR_MIP, (hdata->saved_mip & (MIP_SSIP | MIP_STIP))); + csr_set(CSR_MIP, (hdata->saved_mip & (MIP_SSIP | MIP_STIP))); } void sbi_hsm_hart_resume_start(struct sbi_scratch *scratch) { - int oldstate; struct sbi_hsm_data *hdata = sbi_scratch_offset_ptr(scratch, hart_data_offset); /* If current HART was SUSPENDED then set RESUME_PENDING state */ - oldstate = atomic_cmpxchg(&hdata->state, SBI_HSM_STATE_SUSPENDED, - SBI_HSM_STATE_RESUME_PENDING); - if (oldstate != SBI_HSM_STATE_SUSPENDED) { - sbi_printf("%s: ERR: The hart is in invalid state [%u]\n", - __func__, oldstate); + if (!__sbi_hsm_hart_change_state(hdata, SBI_HSM_STATE_SUSPENDED, + SBI_HSM_STATE_RESUME_PENDING)) sbi_hart_hang(); - } hsm_device_hart_resume(); } -void sbi_hsm_hart_resume_finish(struct sbi_scratch *scratch) +void __noreturn sbi_hsm_hart_resume_finish(struct sbi_scratch *scratch, + u32 hartid) { - u32 oldstate; struct sbi_hsm_data *hdata = sbi_scratch_offset_ptr(scratch, hart_data_offset); /* If current HART was RESUME_PENDING then set STARTED state */ - oldstate = atomic_cmpxchg(&hdata->state, SBI_HSM_STATE_RESUME_PENDING, - SBI_HSM_STATE_STARTED); - if (oldstate != SBI_HSM_STATE_RESUME_PENDING) { - sbi_printf("%s: ERR: The hart is in invalid state [%u]\n", - __func__, oldstate); + if (!__sbi_hsm_hart_change_state(hdata, SBI_HSM_STATE_RESUME_PENDING, + SBI_HSM_STATE_STARTED)) sbi_hart_hang(); - } /* * Restore some of the M-mode CSRs which we are re-configured by * the warm-boot sequence. */ __sbi_hsm_suspend_non_ret_restore(scratch); + + sbi_hart_switch_mode(hartid, scratch->next_arg1, + scratch->next_addr, + scratch->next_mode, false); } int sbi_hsm_hart_suspend(struct sbi_scratch *scratch, u32 suspend_type, - ulong raddr, ulong rmode, ulong priv) + ulong raddr, ulong rmode, ulong arg1) { - int oldstate, ret; + int ret; const struct sbi_domain *dom = sbi_domain_thishart_ptr(); struct sbi_hsm_data *hdata = sbi_scratch_offset_ptr(scratch, hart_data_offset); - /* For now, we only allow suspend from S-mode or U-mode. */ - /* Sanity check on domain assigned to current HART */ if (!dom) - return SBI_EINVAL; + return SBI_EFAIL; /* Sanity check on suspend type */ if (SBI_HSM_SUSPEND_RET_DEFAULT < suspend_type && @@ -423,27 +482,26 @@ /* Additional sanity check for non-retentive suspend */ if (suspend_type & SBI_HSM_SUSP_NON_RET_BIT) { + /* + * For now, we only allow non-retentive suspend from + * S-mode or U-mode. + */ if (rmode != PRV_S && rmode != PRV_U) - return SBI_EINVAL; + return SBI_EFAIL; if (dom && !sbi_domain_check_addr(dom, raddr, rmode, SBI_DOMAIN_EXECUTE)) return SBI_EINVALID_ADDR; } /* Save the resume address and resume mode */ - scratch->next_arg1 = priv; + scratch->next_arg1 = arg1; scratch->next_addr = raddr; scratch->next_mode = rmode; /* Directly move from STARTED to SUSPENDED state */ - oldstate = atomic_cmpxchg(&hdata->state, SBI_HSM_STATE_STARTED, - SBI_HSM_STATE_SUSPENDED); - if (oldstate != SBI_HSM_STATE_STARTED) { - sbi_printf("%s: ERR: The hart is in invalid state [%u]\n", - __func__, oldstate); - ret = SBI_EDENIED; - goto fail_restore_state; - } + if (!__sbi_hsm_hart_change_state(hdata, SBI_HSM_STATE_STARTED, + SBI_HSM_STATE_SUSPENDED)) + return SBI_EFAIL; /* Save the suspend type */ hdata->suspend_type = suspend_type; @@ -478,18 +536,13 @@ jump_warmboot(); } -fail_restore_state: /* * We might have successfully resumed from retentive suspend * or suspend failed. In both cases, we restore state of hart. */ - oldstate = atomic_cmpxchg(&hdata->state, SBI_HSM_STATE_SUSPENDED, - SBI_HSM_STATE_STARTED); - if (oldstate != SBI_HSM_STATE_SUSPENDED) { - sbi_printf("%s: ERR: The hart is in invalid state [%u]\n", - __func__, oldstate); + if (!__sbi_hsm_hart_change_state(hdata, SBI_HSM_STATE_SUSPENDED, + SBI_HSM_STATE_STARTED)) sbi_hart_hang(); - } return ret; } diff -Nru opensbi-1.1/lib/sbi/sbi_illegal_insn.c opensbi-1.3/lib/sbi/sbi_illegal_insn.c --- opensbi-1.1/lib/sbi/sbi_illegal_insn.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_illegal_insn.c 2023-06-23 07:31:49.000000000 +0200 @@ -30,6 +30,7 @@ trap.tval = insn; trap.tval2 = 0; trap.tinst = 0; + trap.gva = 0; return sbi_trap_redirect(regs, &trap); } @@ -39,6 +40,7 @@ /* Errata workaround: emulate `fence.tso` as `fence rw, rw`. */ if ((insn & INSN_MASK_FENCE_TSO) == INSN_MATCH_FENCE_TSO) { smp_mb(); + regs->mepc += 4; return 0; } @@ -88,7 +90,7 @@ break; default: return truly_illegal_insn(insn, regs); - }; + } if (do_write && sbi_emulate_csr_write(csr_num, regs, new_csr_val)) return truly_illegal_insn(insn, regs); diff -Nru opensbi-1.1/lib/sbi/sbi_init.c opensbi-1.3/lib/sbi/sbi_init.c --- opensbi-1.1/lib/sbi/sbi_init.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_init.c 2023-06-23 07:31:49.000000000 +0200 @@ -12,10 +12,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -63,11 +65,14 @@ static void sbi_boot_print_general(struct sbi_scratch *scratch) { char str[128]; + const struct sbi_pmu_device *pdev; const struct sbi_hsm_device *hdev; const struct sbi_ipi_device *idev; const struct sbi_timer_device *tdev; const struct sbi_console_device *cdev; const struct sbi_system_reset_device *srdev; + const struct sbi_system_suspend_device *susp_dev; + const struct sbi_cppc_device *cppc_dev; const struct sbi_platform *plat = sbi_platform_ptr(scratch); if (scratch->options & SBI_SCRATCH_NO_BOOT_PRINTS) @@ -93,17 +98,41 @@ hdev = sbi_hsm_get_device(); sbi_printf("Platform HSM Device : %s\n", (hdev) ? hdev->name : "---"); + pdev = sbi_pmu_get_device(); + sbi_printf("Platform PMU Device : %s\n", + (pdev) ? pdev->name : "---"); srdev = sbi_system_reset_get_device(SBI_SRST_RESET_TYPE_COLD_REBOOT, 0); sbi_printf("Platform Reboot Device : %s\n", (srdev) ? srdev->name : "---"); srdev = sbi_system_reset_get_device(SBI_SRST_RESET_TYPE_SHUTDOWN, 0); sbi_printf("Platform Shutdown Device : %s\n", (srdev) ? srdev->name : "---"); + susp_dev = sbi_system_suspend_get_device(); + sbi_printf("Platform Suspend Device : %s\n", + (susp_dev) ? susp_dev->name : "---"); + cppc_dev = sbi_cppc_get_device(); + sbi_printf("Platform CPPC Device : %s\n", + (cppc_dev) ? cppc_dev->name : "---"); /* Firmware details */ sbi_printf("Firmware Base : 0x%lx\n", scratch->fw_start); sbi_printf("Firmware Size : %d KB\n", (u32)(scratch->fw_size / 1024)); + sbi_printf("Firmware RW Offset : 0x%lx\n", scratch->fw_rw_offset); + sbi_printf("Firmware RW Size : %d KB\n", + (u32)((scratch->fw_size - scratch->fw_rw_offset) / 1024)); + sbi_printf("Firmware Heap Offset : 0x%lx\n", scratch->fw_heap_offset); + sbi_printf("Firmware Heap Size : " + "%d KB (total), %d KB (reserved), %d KB (used), %d KB (free)\n", + (u32)(scratch->fw_heap_size / 1024), + (u32)(sbi_heap_reserved_space() / 1024), + (u32)(sbi_heap_used_space() / 1024), + (u32)(sbi_heap_free_space() / 1024)); + sbi_printf("Firmware Scratch Size : " + "%d B (total), %d B (used), %d B (free)\n", + SBI_SCRATCH_SIZE, + (u32)sbi_scratch_used_space(), + (u32)(SBI_SCRATCH_SIZE - sbi_scratch_used_space())); /* SBI details */ sbi_printf("Runtime SBI Version : %d.%d\n", @@ -186,7 +215,7 @@ wfi(); cmip = csr_read(CSR_MIP); } while (!(cmip & (MIP_MSIP | MIP_MEIP))); - }; + } /* Acquire coldboot lock */ spin_lock(&coldboot_lock); @@ -229,12 +258,13 @@ spin_unlock(&coldboot_lock); } +static unsigned long entry_count_offset; static unsigned long init_count_offset; static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid) { int rc; - unsigned long *init_count; + unsigned long *count; const struct sbi_platform *plat = sbi_platform_ptr(scratch); /* Note: This has to be first thing in coldboot init sequence */ @@ -243,23 +273,35 @@ sbi_hart_hang(); /* Note: This has to be second thing in coldboot init sequence */ + rc = sbi_heap_init(scratch); + if (rc) + sbi_hart_hang(); + + /* Note: This has to be the third thing in coldboot init sequence */ rc = sbi_domain_init(scratch, hartid); if (rc) sbi_hart_hang(); + entry_count_offset = sbi_scratch_alloc_offset(__SIZEOF_POINTER__); + if (!entry_count_offset) + sbi_hart_hang(); + init_count_offset = sbi_scratch_alloc_offset(__SIZEOF_POINTER__); if (!init_count_offset) sbi_hart_hang(); - rc = sbi_hsm_init(scratch, hartid, TRUE); + count = sbi_scratch_offset_ptr(scratch, entry_count_offset); + (*count)++; + + rc = sbi_hsm_init(scratch, hartid, true); if (rc) sbi_hart_hang(); - rc = sbi_platform_early_init(plat, TRUE); + rc = sbi_platform_early_init(plat, true); if (rc) sbi_hart_hang(); - rc = sbi_hart_init(scratch, TRUE); + rc = sbi_hart_init(scratch, true); if (rc) sbi_hart_hang(); @@ -267,43 +309,40 @@ if (rc) sbi_hart_hang(); - rc = sbi_pmu_init(scratch, TRUE); - if (rc) + rc = sbi_pmu_init(scratch, true); + if (rc) { + sbi_printf("%s: pmu init failed (error %d)\n", + __func__, rc); sbi_hart_hang(); + } sbi_boot_print_banner(scratch); - rc = sbi_irqchip_init(scratch, TRUE); + rc = sbi_irqchip_init(scratch, true); if (rc) { sbi_printf("%s: irqchip init failed (error %d)\n", __func__, rc); sbi_hart_hang(); } - rc = sbi_ipi_init(scratch, TRUE); + rc = sbi_ipi_init(scratch, true); if (rc) { sbi_printf("%s: ipi init failed (error %d)\n", __func__, rc); sbi_hart_hang(); } - rc = sbi_tlb_init(scratch, TRUE); + rc = sbi_tlb_init(scratch, true); if (rc) { sbi_printf("%s: tlb init failed (error %d)\n", __func__, rc); sbi_hart_hang(); } - rc = sbi_timer_init(scratch, TRUE); + rc = sbi_timer_init(scratch, true); if (rc) { sbi_printf("%s: timer init failed (error %d)\n", __func__, rc); sbi_hart_hang(); } - rc = sbi_ecall_init(); - if (rc) { - sbi_printf("%s: ecall init failed (error %d)\n", __func__, rc); - sbi_hart_hang(); - } - /* * Note: Finalize domains after HSM initialization so that we * can startup non-root domains. @@ -325,16 +364,28 @@ } /* - * Note: Platform final initialization should be last so that - * it sees correct domain assignment and PMP configuration. + * Note: Platform final initialization should be after finalizing + * domains so that it sees correct domain assignment and PMP + * configuration for FDT fixups. */ - rc = sbi_platform_final_init(plat, TRUE); + rc = sbi_platform_final_init(plat, true); if (rc) { sbi_printf("%s: platform final init failed (error %d)\n", __func__, rc); sbi_hart_hang(); } + /* + * Note: Ecall initialization should be after platform final + * initialization so that all available platform devices are + * already registered. + */ + rc = sbi_ecall_init(); + if (rc) { + sbi_printf("%s: ecall init failed (error %d)\n", __func__, rc); + sbi_hart_hang(); + } + sbi_boot_print_general(scratch); sbi_boot_print_domains(scratch); @@ -343,52 +394,54 @@ wake_coldboot_harts(scratch, hartid); - init_count = sbi_scratch_offset_ptr(scratch, init_count_offset); - (*init_count)++; + count = sbi_scratch_offset_ptr(scratch, init_count_offset); + (*count)++; - sbi_hsm_prepare_next_jump(scratch, hartid); - sbi_hart_switch_mode(hartid, scratch->next_arg1, scratch->next_addr, - scratch->next_mode, FALSE); + sbi_hsm_hart_start_finish(scratch, hartid); } -static void init_warm_startup(struct sbi_scratch *scratch, u32 hartid) +static void __noreturn init_warm_startup(struct sbi_scratch *scratch, + u32 hartid) { int rc; - unsigned long *init_count; + unsigned long *count; const struct sbi_platform *plat = sbi_platform_ptr(scratch); - if (!init_count_offset) + if (!entry_count_offset || !init_count_offset) sbi_hart_hang(); - rc = sbi_hsm_init(scratch, hartid, FALSE); + count = sbi_scratch_offset_ptr(scratch, entry_count_offset); + (*count)++; + + rc = sbi_hsm_init(scratch, hartid, false); if (rc) sbi_hart_hang(); - rc = sbi_platform_early_init(plat, FALSE); + rc = sbi_platform_early_init(plat, false); if (rc) sbi_hart_hang(); - rc = sbi_hart_init(scratch, FALSE); + rc = sbi_hart_init(scratch, false); if (rc) sbi_hart_hang(); - rc = sbi_pmu_init(scratch, FALSE); + rc = sbi_pmu_init(scratch, false); if (rc) sbi_hart_hang(); - rc = sbi_irqchip_init(scratch, FALSE); + rc = sbi_irqchip_init(scratch, false); if (rc) sbi_hart_hang(); - rc = sbi_ipi_init(scratch, FALSE); + rc = sbi_ipi_init(scratch, false); if (rc) sbi_hart_hang(); - rc = sbi_tlb_init(scratch, FALSE); + rc = sbi_tlb_init(scratch, false); if (rc) sbi_hart_hang(); - rc = sbi_timer_init(scratch, FALSE); + rc = sbi_timer_init(scratch, false); if (rc) sbi_hart_hang(); @@ -396,17 +449,18 @@ if (rc) sbi_hart_hang(); - rc = sbi_platform_final_init(plat, FALSE); + rc = sbi_platform_final_init(plat, false); if (rc) sbi_hart_hang(); - init_count = sbi_scratch_offset_ptr(scratch, init_count_offset); - (*init_count)++; + count = sbi_scratch_offset_ptr(scratch, init_count_offset); + (*count)++; - sbi_hsm_prepare_next_jump(scratch, hartid); + sbi_hsm_hart_start_finish(scratch, hartid); } -static void init_warm_resume(struct sbi_scratch *scratch) +static void __noreturn init_warm_resume(struct sbi_scratch *scratch, + u32 hartid) { int rc; @@ -420,7 +474,7 @@ if (rc) sbi_hart_hang(); - sbi_hsm_hart_resume_finish(scratch); + sbi_hsm_hart_resume_finish(scratch, hartid); } static void __noreturn init_warmboot(struct sbi_scratch *scratch, u32 hartid) @@ -433,14 +487,12 @@ if (hstate < 0) sbi_hart_hang(); - if (hstate == SBI_HSM_STATE_SUSPENDED) - init_warm_resume(scratch); - else + if (hstate == SBI_HSM_STATE_SUSPENDED) { + init_warm_resume(scratch, hartid); + } else { + sbi_ipi_raw_clear(hartid); init_warm_startup(scratch, hartid); - - sbi_hart_switch_mode(hartid, scratch->next_arg1, - scratch->next_addr, - scratch->next_mode, FALSE); + } } static atomic_t coldboot_lottery = ATOMIC_INITIALIZER(0); @@ -459,8 +511,8 @@ */ void __noreturn sbi_init(struct sbi_scratch *scratch) { - bool next_mode_supported = FALSE; - bool coldboot = FALSE; + bool next_mode_supported = false; + bool coldboot = false; u32 hartid = current_hartid(); const struct sbi_platform *plat = sbi_platform_ptr(scratch); @@ -470,15 +522,15 @@ switch (scratch->next_mode) { case PRV_M: - next_mode_supported = TRUE; + next_mode_supported = true; break; case PRV_S: if (misa_extension('S')) - next_mode_supported = TRUE; + next_mode_supported = true; break; case PRV_U: if (misa_extension('U')) - next_mode_supported = TRUE; + next_mode_supported = true; break; default: sbi_hart_hang(); @@ -494,8 +546,11 @@ * HARTs which satisfy above condition. */ - if (next_mode_supported && atomic_xchg(&coldboot_lottery, 1) == 0) - coldboot = TRUE; + if (sbi_platform_cold_boot_allowed(plat, hartid)) { + if (next_mode_supported && + atomic_xchg(&coldboot_lottery, 1) == 0) + coldboot = true; + } /* * Do platform specific nascent (very early) initialization so @@ -511,6 +566,23 @@ init_warmboot(scratch, hartid); } +unsigned long sbi_entry_count(u32 hartid) +{ + struct sbi_scratch *scratch; + unsigned long *entry_count; + + if (!entry_count_offset) + return 0; + + scratch = sbi_hartid_to_scratch(hartid); + if (!scratch) + return 0; + + entry_count = sbi_scratch_offset_ptr(scratch, entry_count_offset); + + return *entry_count; +} + unsigned long sbi_init_count(u32 hartid) { struct sbi_scratch *scratch; diff -Nru opensbi-1.1/lib/sbi/sbi_ipi.c opensbi-1.3/lib/sbi/sbi_ipi.c --- opensbi-1.1/lib/sbi/sbi_ipi.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_ipi.c 2023-06-23 07:31:49.000000000 +0200 @@ -53,7 +53,7 @@ if (ipi_ops->update) { ret = ipi_ops->update(scratch, remote_scratch, remote_hartid, data); - if (ret < 0) + if (ret != SBI_IPI_UPDATE_SUCCESS) return ret; } @@ -69,6 +69,18 @@ sbi_pmu_ctr_incr_fw(SBI_PMU_FW_IPI_SENT); + return 0; +} + +static int sbi_ipi_sync(struct sbi_scratch *scratch, u32 event) +{ + const struct sbi_ipi_event_ops *ipi_ops; + + if ((SBI_IPI_EVENT_MAX <= event) || + !ipi_ops_array[event]) + return SBI_EINVAL; + ipi_ops = ipi_ops_array[event]; + if (ipi_ops->sync) ipi_ops->sync(scratch); @@ -83,33 +95,49 @@ int sbi_ipi_send_many(ulong hmask, ulong hbase, u32 event, void *data) { int rc; + bool retry_needed; ulong i, m; + struct sbi_hartmask target_mask = {0}; struct sbi_domain *dom = sbi_domain_thishart_ptr(); struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); + /* Find the target harts */ if (hbase != -1UL) { rc = sbi_hsm_hart_interruptible_mask(dom, hbase, &m); if (rc) return rc; m &= hmask; - /* Send IPIs */ for (i = hbase; m; i++, m >>= 1) { if (m & 1UL) - sbi_ipi_send(scratch, i, event, data); + sbi_hartmask_set_hart(i, &target_mask); } } else { hbase = 0; while (!sbi_hsm_hart_interruptible_mask(dom, hbase, &m)) { - /* Send IPIs */ for (i = hbase; m; i++, m >>= 1) { if (m & 1UL) - sbi_ipi_send(scratch, i, event, data); + sbi_hartmask_set_hart(i, &target_mask); } hbase += BITS_PER_LONG; } } + /* Send IPIs */ + do { + retry_needed = false; + sbi_hartmask_for_each_hart(i, &target_mask) { + rc = sbi_ipi_send(scratch, i, event, data); + if (rc == SBI_IPI_UPDATE_RETRY) + retry_needed = true; + else + sbi_hartmask_clear_hart(i, &target_mask); + } + } while (retry_needed); + + /* Sync IPIs */ + sbi_ipi_sync(scratch, event); + return 0; } @@ -163,7 +191,7 @@ static void sbi_ipi_process_halt(struct sbi_scratch *scratch) { - sbi_hsm_hart_stop(scratch, TRUE); + sbi_hsm_hart_stop(scratch, true); } static struct sbi_ipi_event_ops ipi_halt_ops = { @@ -195,23 +223,29 @@ ipi_type = atomic_raw_xchg_ulong(&ipi_data->ipi_type, 0); ipi_event = 0; while (ipi_type) { - if (!(ipi_type & 1UL)) - goto skip; - - ipi_ops = ipi_ops_array[ipi_event]; - if (ipi_ops && ipi_ops->process) - ipi_ops->process(scratch); - -skip: + if (ipi_type & 1UL) { + ipi_ops = ipi_ops_array[ipi_event]; + if (ipi_ops && ipi_ops->process) + ipi_ops->process(scratch); + } ipi_type = ipi_type >> 1; ipi_event++; - }; + } } -void sbi_ipi_raw_send(u32 target_hart) +int sbi_ipi_raw_send(u32 target_hart) { - if (ipi_dev && ipi_dev->ipi_send) - ipi_dev->ipi_send(target_hart); + if (!ipi_dev || !ipi_dev->ipi_send) + return SBI_EINVAL; + + ipi_dev->ipi_send(target_hart); + return 0; +} + +void sbi_ipi_raw_clear(u32 target_hart) +{ + if (ipi_dev && ipi_dev->ipi_clear) + ipi_dev->ipi_clear(target_hart); } const struct sbi_ipi_device *sbi_ipi_get_device(void) diff -Nru opensbi-1.1/lib/sbi/sbi_misaligned_ldst.c opensbi-1.3/lib/sbi/sbi_misaligned_ldst.c --- opensbi-1.1/lib/sbi/sbi_misaligned_ldst.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_misaligned_ldst.c 2023-06-23 07:31:49.000000000 +0200 @@ -129,6 +129,7 @@ uptrap.tval = addr; uptrap.tval2 = tval2; uptrap.tinst = tinst; + uptrap.gva = sbi_regs_gva(regs); return sbi_trap_redirect(regs, &uptrap); } @@ -244,6 +245,7 @@ uptrap.tval = addr; uptrap.tval2 = tval2; uptrap.tinst = tinst; + uptrap.gva = sbi_regs_gva(regs); return sbi_trap_redirect(regs, &uptrap); } diff -Nru opensbi-1.1/lib/sbi/sbi_pmu.c opensbi-1.3/lib/sbi/sbi_pmu.c --- opensbi-1.1/lib/sbi/sbi_pmu.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_pmu.c 2023-06-23 07:31:49.000000000 +0200 @@ -10,7 +10,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -33,18 +35,6 @@ uint64_t select_mask; }; -/** Representation of a firmware event */ -struct sbi_pmu_fw_event { - /* Event associated with the particular counter */ - uint32_t event_idx; - - /* Current value of the counter */ - unsigned long curr_count; - - /* A flag indicating pmu event monitoring is started */ - bool bStarted; -}; - /* Information about PMU counters as per SBI specification */ union sbi_pmu_ctr_info { unsigned long value; @@ -60,14 +50,43 @@ }; }; -/* Mapping between event range and possible counters */ -static struct sbi_pmu_hw_event hw_event_map[SBI_PMU_HW_EVENT_MAX] = {0}; +#if SBI_PMU_FW_CTR_MAX >= BITS_PER_LONG +#error "Can't handle firmware counters beyond BITS_PER_LONG" +#endif + +/** Per-HART state of the PMU counters */ +struct sbi_pmu_hart_state { + /* HART to which this state belongs */ + uint32_t hartid; + /* Counter to enabled event mapping */ + uint32_t active_events[SBI_PMU_HW_CTR_MAX + SBI_PMU_FW_CTR_MAX]; + /* Bitmap of firmware counters started */ + unsigned long fw_counters_started; + /* + * Counter values for SBI firmware events and event codes + * for platform firmware events. Both are mutually exclusive + * and hence can optimally share the same memory. + */ + uint64_t fw_counters_data[SBI_PMU_FW_CTR_MAX]; +}; + +/** Offset of pointer to PMU HART state in scratch space */ +static unsigned long phs_ptr_offset; + +#define pmu_get_hart_state_ptr(__scratch) \ + sbi_scratch_read_type((__scratch), void *, phs_ptr_offset) + +#define pmu_thishart_state_ptr() \ + pmu_get_hart_state_ptr(sbi_scratch_thishart_ptr()) -/* counter to enabled event mapping */ -static uint32_t active_events[SBI_HARTMASK_MAX_BITS][SBI_PMU_HW_CTR_MAX + SBI_PMU_FW_CTR_MAX]; +#define pmu_set_hart_state_ptr(__scratch, __phs) \ + sbi_scratch_write_type((__scratch), void *, phs_ptr_offset, (__phs)) -/* Contains all the information about firmwares events */ -static struct sbi_pmu_fw_event fw_event_map[SBI_HARTMASK_MAX_BITS][SBI_PMU_FW_EVENT_MAX] = {0}; +/* Platform specific PMU device */ +static const struct sbi_pmu_device *pmu_dev = NULL; + +/* Mapping between event range and possible counters */ +static struct sbi_pmu_hw_event *hw_event_map; /* Maximum number of hardware events available */ static uint32_t num_hw_events; @@ -78,7 +97,8 @@ static uint32_t total_ctrs; /* Helper macros to retrieve event idx and code type */ -#define get_cidx_type(x) ((x & SBI_PMU_EVENT_IDX_TYPE_MASK) >> 16) +#define get_cidx_type(x) \ + (((x) & SBI_PMU_EVENT_IDX_TYPE_MASK) >> SBI_PMU_EVENT_IDX_TYPE_OFFSET) #define get_cidx_code(x) (x & SBI_PMU_EVENT_IDX_CODE_MASK) /** @@ -86,7 +106,7 @@ * @param evtA Pointer to the existing hw event structure * @param evtB Pointer to the new hw event structure * - * Return FALSE if the range doesn't overlap, TRUE otherwise + * Return false if the range doesn't overlap, true otherwise */ static bool pmu_event_range_overlap(struct sbi_pmu_hw_event *evtA, struct sbi_pmu_hw_event *evtB) @@ -94,83 +114,117 @@ /* check if the range of events overlap with a previous entry */ if (((evtA->end_idx < evtB->start_idx) && (evtA->end_idx < evtB->end_idx)) || ((evtA->start_idx > evtB->start_idx) && (evtA->start_idx > evtB->end_idx))) - return FALSE; - return TRUE; + return false; + return true; } static bool pmu_event_select_overlap(struct sbi_pmu_hw_event *evt, uint64_t select_val, uint64_t select_mask) { if ((evt->select == select_val) && (evt->select_mask == select_mask)) - return TRUE; + return true; - return FALSE; + return false; } -static int pmu_ctr_validate(uint32_t cidx, uint32_t *event_idx_code) +static int pmu_event_validate(struct sbi_pmu_hart_state *phs, + unsigned long event_idx, uint64_t edata) { - uint32_t event_idx_val; - uint32_t event_idx_type; - u32 hartid = current_hartid(); - - event_idx_val = active_events[hartid][cidx]; - - if (cidx >= total_ctrs || (event_idx_val == SBI_PMU_EVENT_IDX_INVALID)) - return SBI_EINVAL; + uint32_t event_idx_type = get_cidx_type(event_idx); + uint32_t event_idx_code = get_cidx_code(event_idx); + uint32_t event_idx_code_max = -1; + uint32_t cache_ops_result, cache_ops_id, cache_id; + + switch(event_idx_type) { + case SBI_PMU_EVENT_TYPE_HW: + event_idx_code_max = SBI_PMU_HW_GENERAL_MAX; + break; + case SBI_PMU_EVENT_TYPE_FW: + if ((event_idx_code >= SBI_PMU_FW_MAX && + event_idx_code <= SBI_PMU_FW_RESERVED_MAX) || + event_idx_code > SBI_PMU_FW_PLATFORM) + return SBI_EINVAL; - event_idx_type = get_cidx_type(event_idx_val); - if (event_idx_type >= SBI_PMU_EVENT_TYPE_MAX) + if (SBI_PMU_FW_PLATFORM == event_idx_code && + pmu_dev && pmu_dev->fw_event_validate_encoding) + return pmu_dev->fw_event_validate_encoding(phs->hartid, + edata); + else + event_idx_code_max = SBI_PMU_FW_MAX; + break; + case SBI_PMU_EVENT_TYPE_HW_CACHE: + cache_ops_result = event_idx_code & + SBI_PMU_EVENT_HW_CACHE_OPS_RESULT; + cache_ops_id = (event_idx_code & + SBI_PMU_EVENT_HW_CACHE_OPS_ID_MASK) >> + SBI_PMU_EVENT_HW_CACHE_OPS_ID_OFFSET; + cache_id = (event_idx_code & + SBI_PMU_EVENT_HW_CACHE_ID_MASK) >> + SBI_PMU_EVENT_HW_CACHE_ID_OFFSET; + if ((cache_ops_result < SBI_PMU_HW_CACHE_RESULT_MAX) && + (cache_ops_id < SBI_PMU_HW_CACHE_OP_MAX) && + (cache_id < SBI_PMU_HW_CACHE_MAX)) + return event_idx_type; + else + return SBI_EINVAL; + break; + case SBI_PMU_EVENT_TYPE_HW_RAW: + event_idx_code_max = 1; // event_idx.code should be zero + break; + default: return SBI_EINVAL; + } - *event_idx_code = get_cidx_code(event_idx_val); + if (event_idx_code < event_idx_code_max) + return event_idx_type; - return event_idx_type; + return SBI_EINVAL; } -static int pmu_ctr_read_fw(uint32_t cidx, unsigned long *cval, - uint32_t fw_evt_code) +static int pmu_ctr_validate(struct sbi_pmu_hart_state *phs, + uint32_t cidx, uint32_t *event_idx_code) { - u32 hartid = current_hartid(); - struct sbi_pmu_fw_event fevent; - - fevent = fw_event_map[hartid][fw_evt_code]; - *cval = fevent.curr_count; + uint32_t event_idx_val; + uint32_t event_idx_type; - return 0; -} + if (cidx >= total_ctrs) + return SBI_EINVAL; -/* Add a hardware counter read for completeness for future purpose */ -static int pmu_ctr_read_hw(uint32_t cidx, uint64_t *cval) -{ - /* Check for invalid hw counter read requests */ - if (unlikely(cidx == 1)) + event_idx_val = phs->active_events[cidx]; + event_idx_type = get_cidx_type(event_idx_val); + if (event_idx_val == SBI_PMU_EVENT_IDX_INVALID || + event_idx_type >= SBI_PMU_EVENT_TYPE_MAX) return SBI_EINVAL; -#if __riscv_xlen == 32 - uint32_t temp, temph = 0; - temp = csr_read_num(CSR_MCYCLE + cidx); - temph = csr_read_num(CSR_MCYCLEH + cidx); - *cval = ((uint64_t)temph << 32) | temp; -#else - *cval = csr_read_num(CSR_MCYCLE + cidx); -#endif + *event_idx_code = get_cidx_code(event_idx_val); - return 0; + return event_idx_type; } -int sbi_pmu_ctr_read(uint32_t cidx, unsigned long *cval) +int sbi_pmu_ctr_fw_read(uint32_t cidx, uint64_t *cval) { int event_idx_type; uint32_t event_code; - uint64_t cval64; + struct sbi_pmu_hart_state *phs = pmu_thishart_state_ptr(); - event_idx_type = pmu_ctr_validate(cidx, &event_code); - if (event_idx_type < 0) + event_idx_type = pmu_ctr_validate(phs, cidx, &event_code); + if (event_idx_type != SBI_PMU_EVENT_TYPE_FW) + return SBI_EINVAL; + + if ((event_code >= SBI_PMU_FW_MAX && + event_code <= SBI_PMU_FW_RESERVED_MAX) || + event_code > SBI_PMU_FW_PLATFORM) return SBI_EINVAL; - else if (event_idx_type == SBI_PMU_EVENT_TYPE_FW) - pmu_ctr_read_fw(cidx, cval, event_code); - else - pmu_ctr_read_hw(cidx, &cval64); + + if (SBI_PMU_FW_PLATFORM == event_code) { + if (pmu_dev && pmu_dev->fw_counter_read_value) + *cval = pmu_dev->fw_counter_read_value(phs->hartid, + cidx - + num_hw_ctrs); + else + *cval = 0; + } else + *cval = phs->fw_counters_data[cidx - num_hw_ctrs]; return 0; } @@ -315,6 +369,8 @@ if (sbi_hart_has_extension(scratch, SBI_HART_EXT_SSCOFPMF)) pmu_ctr_enable_irq_hw(cidx); + if (pmu_dev && pmu_dev->hw_counter_enable_irq) + pmu_dev->hw_counter_enable_irq(cidx); csr_write(CSR_MCOUNTINHIBIT, mctr_inhbt); skip_inhibit_update: @@ -324,16 +380,49 @@ return 0; } -static int pmu_ctr_start_fw(uint32_t cidx, uint32_t fw_evt_code, - uint64_t ival, bool ival_update) +int sbi_pmu_irq_bit(void) { - u32 hartid = current_hartid(); - struct sbi_pmu_fw_event *fevent; + struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); - fevent = &fw_event_map[hartid][fw_evt_code]; - if (ival_update) - fevent->curr_count = ival; - fevent->bStarted = TRUE; + if (sbi_hart_has_extension(scratch, SBI_HART_EXT_SSCOFPMF)) + return MIP_LCOFIP; + if (pmu_dev && pmu_dev->hw_counter_irq_bit) + return pmu_dev->hw_counter_irq_bit(); + + return 0; +} + +static int pmu_ctr_start_fw(struct sbi_pmu_hart_state *phs, + uint32_t cidx, uint32_t event_code, + uint64_t event_data, uint64_t ival, + bool ival_update) +{ + if ((event_code >= SBI_PMU_FW_MAX && + event_code <= SBI_PMU_FW_RESERVED_MAX) || + event_code > SBI_PMU_FW_PLATFORM) + return SBI_EINVAL; + + if (SBI_PMU_FW_PLATFORM == event_code) { + if (!pmu_dev || + !pmu_dev->fw_counter_write_value || + !pmu_dev->fw_counter_start) { + return SBI_EINVAL; + } + + if (ival_update) + pmu_dev->fw_counter_write_value(phs->hartid, + cidx - num_hw_ctrs, + ival); + + return pmu_dev->fw_counter_start(phs->hartid, + cidx - num_hw_ctrs, + event_data); + } else { + if (ival_update) + phs->fw_counters_data[cidx - num_hw_ctrs] = ival; + } + + phs->fw_counters_started |= BIT(cidx - num_hw_ctrs); return 0; } @@ -341,27 +430,35 @@ int sbi_pmu_ctr_start(unsigned long cbase, unsigned long cmask, unsigned long flags, uint64_t ival) { + struct sbi_pmu_hart_state *phs = pmu_thishart_state_ptr(); int event_idx_type; uint32_t event_code; - unsigned long ctr_mask = cmask << cbase; int ret = SBI_EINVAL; - bool bUpdate = FALSE; + bool bUpdate = false; + int i, cidx; + uint64_t edata; - if (sbi_fls(ctr_mask) >= total_ctrs) + if ((cbase + sbi_fls(cmask)) >= total_ctrs) return ret; if (flags & SBI_PMU_START_FLAG_SET_INIT_VALUE) - bUpdate = TRUE; + bUpdate = true; - for_each_set_bit_from(cbase, &ctr_mask, total_ctrs) { - event_idx_type = pmu_ctr_validate(cbase, &event_code); + for_each_set_bit(i, &cmask, total_ctrs) { + cidx = i + cbase; + event_idx_type = pmu_ctr_validate(phs, cidx, &event_code); if (event_idx_type < 0) /* Continue the start operation for other counters */ continue; - else if (event_idx_type == SBI_PMU_EVENT_TYPE_FW) - ret = pmu_ctr_start_fw(cbase, event_code, ival, bUpdate); + else if (event_idx_type == SBI_PMU_EVENT_TYPE_FW) { + edata = (event_code == SBI_PMU_FW_PLATFORM) ? + phs->fw_counters_data[cidx - num_hw_ctrs] + : 0x0; + ret = pmu_ctr_start_fw(phs, cidx, event_code, edata, + ival, bUpdate); + } else - ret = pmu_ctr_start_hw(cbase, ival, bUpdate); + ret = pmu_ctr_start_hw(cidx, ival, bUpdate); } return ret; @@ -389,11 +486,24 @@ return SBI_EALREADY_STOPPED; } -static int pmu_ctr_stop_fw(uint32_t cidx, uint32_t fw_evt_code) +static int pmu_ctr_stop_fw(struct sbi_pmu_hart_state *phs, + uint32_t cidx, uint32_t event_code) { - u32 hartid = current_hartid(); + int ret; + + if ((event_code >= SBI_PMU_FW_MAX && + event_code <= SBI_PMU_FW_RESERVED_MAX) || + event_code > SBI_PMU_FW_PLATFORM) + return SBI_EINVAL; - fw_event_map[hartid][fw_evt_code].bStarted = FALSE; + if (SBI_PMU_FW_PLATFORM == event_code && + pmu_dev && pmu_dev->fw_counter_stop) { + ret = pmu_dev->fw_counter_stop(phs->hartid, cidx - num_hw_ctrs); + if (ret) + return ret; + } + + phs->fw_counters_started &= ~BIT(cidx - num_hw_ctrs); return 0; } @@ -417,29 +527,30 @@ int sbi_pmu_ctr_stop(unsigned long cbase, unsigned long cmask, unsigned long flag) { - u32 hartid = current_hartid(); + struct sbi_pmu_hart_state *phs = pmu_thishart_state_ptr(); int ret = SBI_EINVAL; int event_idx_type; uint32_t event_code; - unsigned long ctr_mask = cmask << cbase; + int i, cidx; - if (sbi_fls(ctr_mask) >= total_ctrs) + if ((cbase + sbi_fls(cmask)) >= total_ctrs) return SBI_EINVAL; - for_each_set_bit_from(cbase, &ctr_mask, total_ctrs) { - event_idx_type = pmu_ctr_validate(cbase, &event_code); + for_each_set_bit(i, &cmask, total_ctrs) { + cidx = i + cbase; + event_idx_type = pmu_ctr_validate(phs, cidx, &event_code); if (event_idx_type < 0) /* Continue the stop operation for other counters */ continue; else if (event_idx_type == SBI_PMU_EVENT_TYPE_FW) - ret = pmu_ctr_stop_fw(cbase, event_code); + ret = pmu_ctr_stop_fw(phs, cidx, event_code); else - ret = pmu_ctr_stop_hw(cbase); + ret = pmu_ctr_stop_hw(cidx); - if (flag & SBI_PMU_STOP_FLAG_RESET) { - active_events[hartid][cbase] = SBI_PMU_EVENT_IDX_INVALID; - pmu_reset_hw_mhpmevent(cbase); + if (cidx > (CSR_INSTRET - CSR_CYCLE) && flag & SBI_PMU_STOP_FLAG_RESET) { + phs->active_events[cidx] = SBI_PMU_EVENT_IDX_INVALID; + pmu_reset_hw_mhpmevent(cidx); } } @@ -480,6 +591,9 @@ mhpmevent_val = (mhpmevent_val & ~MHPMEVENT_SSCOF_MASK) | MHPMEVENT_MINH | MHPMEVENT_OF; + if (pmu_dev && pmu_dev->hw_counter_disable_irq) + pmu_dev->hw_counter_disable_irq(ctr_idx); + /* Update the inhibit flags based on inhibit flags received from supervisor */ pmu_update_inhibit_flags(flags, &mhpmevent_val); @@ -506,14 +620,15 @@ return SBI_EINVAL; } -static int pmu_ctr_find_hw(unsigned long cbase, unsigned long cmask, unsigned long flags, +static int pmu_ctr_find_hw(struct sbi_pmu_hart_state *phs, + unsigned long cbase, unsigned long cmask, + unsigned long flags, unsigned long event_idx, uint64_t data) { unsigned long ctr_mask; int i, ret = 0, fixed_ctr, ctr_idx = SBI_ENOTSUPP; struct sbi_pmu_hw_event *temp; unsigned long mctr_inhbt = 0; - u32 hartid = current_hartid(); struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); if (cbase >= num_hw_ctrs) @@ -552,7 +667,7 @@ * Some of the platform may not support mcountinhibit. * Checking the active_events is enough for them */ - if (active_events[hartid][cbase] != SBI_PMU_EVENT_IDX_INVALID) + if (phs->active_events[cbase] != SBI_PMU_EVENT_IDX_INVALID) continue; /* If mcountinhibit is supported, the bit must be enabled */ if ((sbi_hart_priv_version(scratch) >= SBI_HART_PRIV_VER_1_11) && @@ -587,21 +702,33 @@ * Thus, select the first available fw counter after sanity * check. */ -static int pmu_ctr_find_fw(unsigned long cbase, unsigned long cmask, u32 hartid) +static int pmu_ctr_find_fw(struct sbi_pmu_hart_state *phs, + unsigned long cbase, unsigned long cmask, + uint32_t event_code, uint64_t edata) { - int i = 0; - int fw_base; - unsigned long ctr_mask = cmask << cbase; + int i, cidx; - if (cbase < num_hw_ctrs) - fw_base = num_hw_ctrs; - else - fw_base = cbase; + if ((event_code >= SBI_PMU_FW_MAX && + event_code <= SBI_PMU_FW_RESERVED_MAX) || + event_code > SBI_PMU_FW_PLATFORM) + return SBI_EINVAL; - for (i = fw_base; i < total_ctrs; i++) - if ((active_events[hartid][i] == SBI_PMU_EVENT_IDX_INVALID) && - ((1UL << i) & ctr_mask)) - return i; + for_each_set_bit(i, &cmask, BITS_PER_LONG) { + cidx = i + cbase; + if (cidx < num_hw_ctrs || total_ctrs <= cidx) + continue; + if (phs->active_events[i] != SBI_PMU_EVENT_IDX_INVALID) + continue; + if (SBI_PMU_FW_PLATFORM == event_code && + pmu_dev && pmu_dev->fw_counter_match_encoding) { + if (!pmu_dev->fw_counter_match_encoding(phs->hartid, + cidx - num_hw_ctrs, + edata)) + continue; + } + + return i; + } return SBI_ENOTSUPP; } @@ -610,40 +737,51 @@ unsigned long flags, unsigned long event_idx, uint64_t event_data) { - int ctr_idx = SBI_ENOTSUPP; - u32 hartid = current_hartid(); - int event_type = get_cidx_type(event_idx); - struct sbi_pmu_fw_event *fevent; - uint32_t fw_evt_code; - unsigned long tmp = cidx_mask << cidx_base; + struct sbi_pmu_hart_state *phs = pmu_thishart_state_ptr(); + int ret, event_type, ctr_idx = SBI_ENOTSUPP; + u32 event_code; /* Do a basic sanity check of counter base & mask */ - if (sbi_fls(tmp) >= total_ctrs || event_type >= SBI_PMU_EVENT_TYPE_MAX) + if ((cidx_base + sbi_fls(cidx_mask)) >= total_ctrs) + return SBI_EINVAL; + + event_type = pmu_event_validate(phs, event_idx, event_data); + if (event_type < 0) return SBI_EINVAL; + event_code = get_cidx_code(event_idx); if (flags & SBI_PMU_CFG_FLAG_SKIP_MATCH) { /* The caller wants to skip the match because it already knows the * counter idx for the given event. Verify that the counter idx * is still valid. + * As per the specification, we should "unconditionally select + * the first counter from the set of counters specified by the + * counter_idx_base and counter_idx_mask". */ - if (active_events[hartid][cidx_base] == SBI_PMU_EVENT_IDX_INVALID) + unsigned long cidx_first = cidx_base + sbi_ffs(cidx_mask); + + if (phs->active_events[cidx_first] == SBI_PMU_EVENT_IDX_INVALID) return SBI_EINVAL; - ctr_idx = cidx_base; + ctr_idx = cidx_first; goto skip_match; } if (event_type == SBI_PMU_EVENT_TYPE_FW) { /* Any firmware counter can be used track any firmware event */ - ctr_idx = pmu_ctr_find_fw(cidx_base, cidx_mask, hartid); + ctr_idx = pmu_ctr_find_fw(phs, cidx_base, cidx_mask, + event_code, event_data); + if (event_code == SBI_PMU_FW_PLATFORM) + phs->fw_counters_data[ctr_idx - num_hw_ctrs] = + event_data; } else { - ctr_idx = pmu_ctr_find_hw(cidx_base, cidx_mask, flags, event_idx, - event_data); + ctr_idx = pmu_ctr_find_hw(phs, cidx_base, cidx_mask, flags, + event_idx, event_data); } if (ctr_idx < 0) return SBI_ENOTSUPP; - active_events[hartid][ctr_idx] = event_idx; + phs->active_events[ctr_idx] = event_idx; skip_match: if (event_type == SBI_PMU_EVENT_TYPE_HW) { if (flags & SBI_PMU_CFG_FLAG_CLEAR_VALUE) @@ -651,30 +789,46 @@ if (flags & SBI_PMU_CFG_FLAG_AUTO_START) pmu_ctr_start_hw(ctr_idx, 0, false); } else if (event_type == SBI_PMU_EVENT_TYPE_FW) { - fw_evt_code = get_cidx_code(event_idx); - fevent = &fw_event_map[hartid][fw_evt_code]; if (flags & SBI_PMU_CFG_FLAG_CLEAR_VALUE) - fevent->curr_count = 0; - if (flags & SBI_PMU_CFG_FLAG_AUTO_START) - fevent->bStarted = TRUE; + phs->fw_counters_data[ctr_idx - num_hw_ctrs] = 0; + if (flags & SBI_PMU_CFG_FLAG_AUTO_START) { + if (SBI_PMU_FW_PLATFORM == event_code && + pmu_dev && pmu_dev->fw_counter_start) { + ret = pmu_dev->fw_counter_start( + phs->hartid, + ctr_idx - num_hw_ctrs, event_data); + if (ret) + return ret; + } + phs->fw_counters_started |= BIT(ctr_idx - num_hw_ctrs); + } } return ctr_idx; } -inline int sbi_pmu_ctr_incr_fw(enum sbi_pmu_fw_event_code_id fw_id) +int sbi_pmu_ctr_incr_fw(enum sbi_pmu_fw_event_code_id fw_id) { - u32 hartid = current_hartid(); - struct sbi_pmu_fw_event *fevent; + u32 cidx; + uint64_t *fcounter = NULL; + struct sbi_pmu_hart_state *phs = pmu_thishart_state_ptr(); + + if (likely(!phs->fw_counters_started)) + return 0; if (unlikely(fw_id >= SBI_PMU_FW_MAX)) return SBI_EINVAL; - fevent = &fw_event_map[hartid][fw_id]; + for (cidx = num_hw_ctrs; cidx < total_ctrs; cidx++) { + if (get_cidx_code(phs->active_events[cidx]) == fw_id && + (phs->fw_counters_started & BIT(cidx - num_hw_ctrs))) { + fcounter = &phs->fw_counters_data[cidx - num_hw_ctrs]; + break; + } + } - /* PMU counters will be only enabled during performance debugging */ - if (unlikely(fevent->bStarted)) - fevent->curr_count++; + if (fcounter) + (*fcounter)++; return 0; } @@ -686,6 +840,7 @@ int sbi_pmu_ctr_get_info(uint32_t cidx, unsigned long *ctr_info) { + int width; union sbi_pmu_ctr_info cinfo = {0}; struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); @@ -705,8 +860,13 @@ } else { /* it's a firmware counter */ cinfo.type = SBI_PMU_CTR_TYPE_FW; - /* Firmware counters are XLEN bits wide */ - cinfo.width = BITS_PER_LONG - 1; + /* Firmware counters are always 64 bits wide */ + cinfo.width = 63; + if (pmu_dev && pmu_dev->fw_counter_width) { + width = pmu_dev->fw_counter_width(); + if (width) + cinfo.width = width - 1; + } } *ctr_info = cinfo.value; @@ -714,36 +874,59 @@ return 0; } -static void pmu_reset_event_map(u32 hartid) +static void pmu_reset_event_map(struct sbi_pmu_hart_state *phs) { int j; /* Initialize the counter to event mapping table */ for (j = 3; j < total_ctrs; j++) - active_events[hartid][j] = SBI_PMU_EVENT_IDX_INVALID; + phs->active_events[j] = SBI_PMU_EVENT_IDX_INVALID; for (j = 0; j < SBI_PMU_FW_CTR_MAX; j++) - sbi_memset(&fw_event_map[hartid][j], 0, - sizeof(struct sbi_pmu_fw_event)); + phs->fw_counters_data[j] = 0; + phs->fw_counters_started = 0; } -void sbi_pmu_exit(struct sbi_scratch *scratch) +const struct sbi_pmu_device *sbi_pmu_get_device(void) { - u32 hartid = current_hartid(); + return pmu_dev; +} + +void sbi_pmu_set_device(const struct sbi_pmu_device *dev) +{ + if (!dev || pmu_dev) + return; + pmu_dev = dev; +} + +void sbi_pmu_exit(struct sbi_scratch *scratch) +{ if (sbi_hart_priv_version(scratch) >= SBI_HART_PRIV_VER_1_11) csr_write(CSR_MCOUNTINHIBIT, 0xFFFFFFF8); if (sbi_hart_priv_version(scratch) >= SBI_HART_PRIV_VER_1_10) csr_write(CSR_MCOUNTEREN, -1); - pmu_reset_event_map(hartid); + + pmu_reset_event_map(pmu_get_hart_state_ptr(scratch)); } int sbi_pmu_init(struct sbi_scratch *scratch, bool cold_boot) { + struct sbi_pmu_hart_state *phs; const struct sbi_platform *plat; - u32 hartid = current_hartid(); if (cold_boot) { + hw_event_map = sbi_calloc(sizeof(*hw_event_map), + SBI_PMU_HW_EVENT_MAX); + if (!hw_event_map) + return SBI_ENOMEM; + + phs_ptr_offset = sbi_scratch_alloc_type_offset(void *); + if (!phs_ptr_offset) { + sbi_free(hw_event_map); + return SBI_ENOMEM; + } + plat = sbi_platform_ptr(scratch); /* Initialize hw pmu events */ sbi_platform_pmu_init(plat); @@ -753,14 +936,23 @@ total_ctrs = num_hw_ctrs + SBI_PMU_FW_CTR_MAX; } - pmu_reset_event_map(hartid); + phs = pmu_get_hart_state_ptr(scratch); + if (!phs) { + phs = sbi_zalloc(sizeof(*phs)); + if (!phs) + return SBI_ENOMEM; + phs->hartid = current_hartid(); + pmu_set_hart_state_ptr(scratch, phs); + } + + pmu_reset_event_map(phs); /* First three counters are fixed by the priv spec and we enable it by default */ - active_events[hartid][0] = SBI_PMU_EVENT_TYPE_HW << SBI_PMU_EVENT_IDX_OFFSET | - SBI_PMU_HW_CPU_CYCLES; - active_events[hartid][1] = SBI_PMU_EVENT_IDX_INVALID; - active_events[hartid][2] = SBI_PMU_EVENT_TYPE_HW << SBI_PMU_EVENT_IDX_OFFSET | - SBI_PMU_HW_INSTRUCTIONS; + phs->active_events[0] = (SBI_PMU_EVENT_TYPE_HW << SBI_PMU_EVENT_IDX_TYPE_OFFSET) | + SBI_PMU_HW_CPU_CYCLES; + phs->active_events[1] = SBI_PMU_EVENT_IDX_INVALID; + phs->active_events[2] = (SBI_PMU_EVENT_TYPE_HW << SBI_PMU_EVENT_IDX_TYPE_OFFSET) | + SBI_PMU_HW_INSTRUCTIONS; return 0; } diff -Nru opensbi-1.1/lib/sbi/sbi_scratch.c opensbi-1.3/lib/sbi/sbi_scratch.c --- opensbi-1.1/lib/sbi/sbi_scratch.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_scratch.c 2023-06-23 07:31:49.000000000 +0200 @@ -59,8 +59,8 @@ if (!size) return 0; - if (size & (__SIZEOF_POINTER__ - 1)) - size = (size & ~(__SIZEOF_POINTER__ - 1)) + __SIZEOF_POINTER__; + size += __SIZEOF_POINTER__ - 1; + size &= ~((unsigned long)__SIZEOF_POINTER__ - 1); spin_lock(&extra_lock); @@ -97,3 +97,14 @@ * brain-dead allocator. */ } + +unsigned long sbi_scratch_used_space(void) +{ + unsigned long ret = 0; + + spin_lock(&extra_lock); + ret = extra_offset; + spin_unlock(&extra_lock); + + return ret; +} diff -Nru opensbi-1.1/lib/sbi/sbi_string.c opensbi-1.3/lib/sbi/sbi_string.c --- opensbi-1.1/lib/sbi/sbi_string.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_string.c 2023-06-23 07:31:49.000000000 +0200 @@ -59,7 +59,6 @@ while (*str != '\0' && ret < count) { ret++; str++; - count--; } return ret; diff -Nru opensbi-1.1/lib/sbi/sbi_system.c opensbi-1.3/lib/sbi/sbi_system.c --- opensbi-1.1/lib/sbi/sbi_system.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_system.c 2023-06-23 07:31:49.000000000 +0200 @@ -17,6 +17,7 @@ #include #include #include +#include static SBI_LIST_HEAD(reset_devices_list); @@ -79,7 +80,7 @@ } /* Stop current HART */ - sbi_hsm_hart_stop(scratch, FALSE); + sbi_hsm_hart_stop(scratch, false); /* Platform specific reset if domain allowed system reset */ if (dom->system_reset_allowed) { @@ -92,3 +93,116 @@ /* If platform specific reset did not work then do sbi_exit() */ sbi_exit(scratch); } + +static const struct sbi_system_suspend_device *suspend_dev = NULL; + +const struct sbi_system_suspend_device *sbi_system_suspend_get_device(void) +{ + return suspend_dev; +} + +void sbi_system_suspend_set_device(struct sbi_system_suspend_device *dev) +{ + if (!dev || suspend_dev) + return; + + suspend_dev = dev; +} + +static int sbi_system_suspend_test_check(u32 sleep_type) +{ + return sleep_type == SBI_SUSP_SLEEP_TYPE_SUSPEND ? 0 : SBI_EINVAL; +} + +static int sbi_system_suspend_test_suspend(u32 sleep_type, + unsigned long mmode_resume_addr) +{ + if (sleep_type != SBI_SUSP_SLEEP_TYPE_SUSPEND) + return SBI_EINVAL; + + sbi_timer_mdelay(5000); + + /* Wait for interrupt */ + wfi(); + + return SBI_OK; +} + +static struct sbi_system_suspend_device sbi_system_suspend_test = { + .name = "system-suspend-test", + .system_suspend_check = sbi_system_suspend_test_check, + .system_suspend = sbi_system_suspend_test_suspend, +}; + +void sbi_system_suspend_test_enable(void) +{ + sbi_system_suspend_set_device(&sbi_system_suspend_test); +} + +bool sbi_system_suspend_supported(u32 sleep_type) +{ + return suspend_dev && suspend_dev->system_suspend_check && + suspend_dev->system_suspend_check(sleep_type) == 0; +} + +int sbi_system_suspend(u32 sleep_type, ulong resume_addr, ulong opaque) +{ + const struct sbi_domain *dom = sbi_domain_thishart_ptr(); + struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); + void (*jump_warmboot)(void) = (void (*)(void))scratch->warmboot_addr; + unsigned int hartid = current_hartid(); + unsigned long prev_mode; + unsigned long i; + int ret; + + if (!dom || !dom->system_suspend_allowed) + return SBI_EFAIL; + + if (!suspend_dev || !suspend_dev->system_suspend || + !suspend_dev->system_suspend_check) + return SBI_EFAIL; + + ret = suspend_dev->system_suspend_check(sleep_type); + if (ret != SBI_OK) + return ret; + + prev_mode = (csr_read(CSR_MSTATUS) & MSTATUS_MPP) >> MSTATUS_MPP_SHIFT; + if (prev_mode != PRV_S && prev_mode != PRV_U) + return SBI_EFAIL; + + sbi_hartmask_for_each_hart(i, &dom->assigned_harts) { + if (i == hartid) + continue; + if (__sbi_hsm_hart_get_state(i) != SBI_HSM_STATE_STOPPED) + return SBI_EFAIL; + } + + if (!sbi_domain_check_addr(dom, resume_addr, prev_mode, + SBI_DOMAIN_EXECUTE)) + return SBI_EINVALID_ADDR; + + if (!sbi_hsm_hart_change_state(scratch, SBI_HSM_STATE_STARTED, + SBI_HSM_STATE_SUSPENDED)) + return SBI_EFAIL; + + /* Prepare for resume */ + scratch->next_mode = prev_mode; + scratch->next_addr = resume_addr; + scratch->next_arg1 = opaque; + + __sbi_hsm_suspend_non_ret_save(scratch); + + /* Suspend */ + ret = suspend_dev->system_suspend(sleep_type, scratch->warmboot_addr); + if (ret != SBI_OK) { + if (!sbi_hsm_hart_change_state(scratch, SBI_HSM_STATE_SUSPENDED, + SBI_HSM_STATE_STARTED)) + sbi_hart_hang(); + return ret; + } + + /* Resume */ + jump_warmboot(); + + __builtin_unreachable(); +} diff -Nru opensbi-1.1/lib/sbi/sbi_timer.c opensbi-1.3/lib/sbi/sbi_timer.c --- opensbi-1.1/lib/sbi/sbi_timer.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_timer.c 2023-06-23 07:31:49.000000000 +0200 @@ -76,6 +76,19 @@ delay_fn(opaque); } +bool sbi_timer_waitms_until(bool (*predicate)(void *), void *arg, + uint64_t timeout_ms) +{ + uint64_t start_time = sbi_timer_value(); + uint64_t ticks = + (sbi_timer_get_device()->timer_freq / 1000) * + timeout_ms; + while(!predicate(arg)) + if (sbi_timer_value() - start_time >= ticks) + return false; + return true; +} + u64 sbi_timer_value(void) { if (get_time_val) diff -Nru opensbi-1.1/lib/sbi/sbi_tlb.c opensbi-1.3/lib/sbi/sbi_tlb.c --- opensbi-1.1/lib/sbi/sbi_tlb.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_tlb.c 2023-06-23 07:31:49.000000000 +0200 @@ -215,7 +215,7 @@ { u32 rhartid; struct sbi_scratch *rscratch = NULL; - unsigned long *rtlb_sync = NULL; + atomic_t *rtlb_sync = NULL; tinfo->local_fn(tinfo); @@ -225,47 +225,40 @@ continue; rtlb_sync = sbi_scratch_offset_ptr(rscratch, tlb_sync_off); - while (atomic_raw_xchg_ulong(rtlb_sync, 1)) ; + atomic_sub_return(rtlb_sync, 1); } } -static void tlb_process_count(struct sbi_scratch *scratch, int count) +static bool tlb_process_once(struct sbi_scratch *scratch) { struct sbi_tlb_info tinfo; - unsigned int deq_count = 0; struct sbi_fifo *tlb_fifo = sbi_scratch_offset_ptr(scratch, tlb_fifo_off); - while (!sbi_fifo_dequeue(tlb_fifo, &tinfo)) { + if (!sbi_fifo_dequeue(tlb_fifo, &tinfo)) { tlb_entry_process(&tinfo); - deq_count++; - if (deq_count > count) - break; - + return true; } + + return false; } static void tlb_process(struct sbi_scratch *scratch) { - struct sbi_tlb_info tinfo; - struct sbi_fifo *tlb_fifo = - sbi_scratch_offset_ptr(scratch, tlb_fifo_off); - - while (!sbi_fifo_dequeue(tlb_fifo, &tinfo)) - tlb_entry_process(&tinfo); + while (tlb_process_once(scratch)); } static void tlb_sync(struct sbi_scratch *scratch) { - unsigned long *tlb_sync = + atomic_t *tlb_sync = sbi_scratch_offset_ptr(scratch, tlb_sync_off); - while (!atomic_raw_xchg_ulong(tlb_sync, 0)) { + while (atomic_read(tlb_sync) > 0) { /* * While we are waiting for remote hart to set the sync, * consume fifo requests to avoid deadlock. */ - tlb_process_count(scratch, 1); + tlb_process_once(scratch); } return; @@ -343,6 +336,7 @@ u32 remote_hartid, void *data) { int ret; + atomic_t *tlb_sync; struct sbi_fifo *tlb_fifo_r; struct sbi_tlb_info *tinfo = data; u32 curr_hartid = current_hartid(); @@ -363,17 +357,14 @@ */ if (remote_hartid == curr_hartid) { tinfo->local_fn(tinfo); - return -1; + return SBI_IPI_UPDATE_BREAK; } tlb_fifo_r = sbi_scratch_offset_ptr(remote_scratch, tlb_fifo_off); ret = sbi_fifo_inplace_update(tlb_fifo_r, data, tlb_update_cb); - if (ret != SBI_FIFO_UNCHANGED) { - return 1; - } - while (sbi_fifo_enqueue(tlb_fifo_r, data) < 0) { + if (ret == SBI_FIFO_UNCHANGED && sbi_fifo_enqueue(tlb_fifo_r, data) < 0) { /** * For now, Busy loop until there is space in the fifo. * There may be case where target hart is also @@ -382,12 +373,16 @@ * TODO: Introduce a wait/wakeup event mechanism to handle * this properly. */ - tlb_process_count(scratch, 1); + tlb_process_once(scratch); sbi_dprintf("hart%d: hart%d tlb fifo full\n", curr_hartid, remote_hartid); + return SBI_IPI_UPDATE_RETRY; } - return 0; + tlb_sync = sbi_scratch_offset_ptr(scratch, tlb_sync_off); + atomic_add_return(tlb_sync, 1); + + return SBI_IPI_UPDATE_SUCCESS; } static struct sbi_ipi_event_ops tlb_ops = { @@ -413,7 +408,7 @@ { int ret; void *tlb_mem; - unsigned long *tlb_sync; + atomic_t *tlb_sync; struct sbi_fifo *tlb_q; const struct sbi_platform *plat = sbi_platform_ptr(scratch); @@ -455,7 +450,7 @@ tlb_q = sbi_scratch_offset_ptr(scratch, tlb_fifo_off); tlb_mem = sbi_scratch_offset_ptr(scratch, tlb_fifo_mem_off); - *tlb_sync = 0; + ATOMIC_INIT(tlb_sync, 0); sbi_fifo_init(tlb_q, tlb_mem, SBI_TLB_FIFO_NUM_ENTRIES, SBI_TLB_INFO_SIZE); diff -Nru opensbi-1.1/lib/sbi/sbi_trap.c opensbi-1.3/lib/sbi/sbi_trap.c --- opensbi-1.1/lib/sbi/sbi_trap.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_trap.c 2023-06-23 07:31:49.000000000 +0200 @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -87,12 +88,12 @@ { ulong hstatus, vsstatus, prev_mode; #if __riscv_xlen == 32 - bool prev_virt = (regs->mstatusH & MSTATUSH_MPV) ? TRUE : FALSE; + bool prev_virt = (regs->mstatusH & MSTATUSH_MPV) ? true : false; #else - bool prev_virt = (regs->mstatus & MSTATUS_MPV) ? TRUE : FALSE; + bool prev_virt = (regs->mstatus & MSTATUS_MPV) ? true : false; #endif /* By default, we redirect to HS-mode */ - bool next_virt = FALSE; + bool next_virt = false; /* Sanity check on previous mode */ prev_mode = (regs->mstatus & MSTATUS_MPP) >> MSTATUS_MPP_SHIFT; @@ -105,7 +106,7 @@ if (misa_extension('H') && prev_virt) { if ((trap->cause < __riscv_xlen) && (csr_read(CSR_HEDELEG) & BIT(trap->cause))) { - next_virt = TRUE; + next_virt = true; } } @@ -118,14 +119,18 @@ regs->mstatus |= (next_virt) ? MSTATUS_MPV : 0UL; #endif - /* Update HSTATUS for VS/VU-mode to HS-mode transition */ - if (misa_extension('H') && prev_virt && !next_virt) { - /* Update HSTATUS SPVP and SPV bits */ + /* Update hypervisor CSRs if going to HS-mode */ + if (misa_extension('H') && !next_virt) { hstatus = csr_read(CSR_HSTATUS); - hstatus &= ~HSTATUS_SPVP; - hstatus |= (prev_mode == PRV_S) ? HSTATUS_SPVP : 0; + if (prev_virt) { + /* hstatus.SPVP is only updated if coming from VS/VU-mode */ + hstatus &= ~HSTATUS_SPVP; + hstatus |= (prev_mode == PRV_S) ? HSTATUS_SPVP : 0; + } hstatus &= ~HSTATUS_SPV; hstatus |= (prev_virt) ? HSTATUS_SPV : 0; + hstatus &= ~HSTATUS_GVA; + hstatus |= (trap->gva) ? HSTATUS_GVA : 0; csr_write(CSR_HSTATUS, hstatus); csr_write(CSR_HTVAL, trap->tval2); csr_write(CSR_HTINST, trap->tinst); @@ -207,7 +212,7 @@ return sbi_irqchip_process(regs); default: return SBI_ENOENT; - }; + } return 0; } @@ -270,7 +275,7 @@ if (mcause & (1UL << (__riscv_xlen - 1))) { if (sbi_hart_has_extension(sbi_scratch_thishart_ptr(), - SBI_HART_EXT_AIA)) + SBI_HART_EXT_SMAIA)) rc = sbi_trap_aia_irq(regs, mcause); else rc = sbi_trap_nonaia_irq(regs, mcause); @@ -311,9 +316,11 @@ trap.tval = mtval; trap.tval2 = mtval2; trap.tinst = mtinst; + trap.gva = sbi_regs_gva(regs); + rc = sbi_trap_redirect(regs, &trap); break; - }; + } trap_error: if (rc) diff -Nru opensbi-1.1/lib/sbi/sbi_unpriv.c opensbi-1.3/lib/sbi/sbi_unpriv.c --- opensbi-1.1/lib/sbi/sbi_unpriv.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/sbi/sbi_unpriv.c 2023-06-23 07:31:49.000000000 +0200 @@ -163,7 +163,7 @@ break; default: break; - }; + } return insn; } diff -Nru opensbi-1.1/lib/utils/fdt/fdt_domain.c opensbi-1.3/lib/utils/fdt/fdt_domain.c --- opensbi-1.1/lib/utils/fdt/fdt_domain.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/fdt/fdt_domain.c 2023-06-23 07:31:49.000000000 +0200 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -219,14 +220,13 @@ fdt_nop_node(fdt, poffset); } -#define FDT_DOMAIN_MAX_COUNT 8 #define FDT_DOMAIN_REGION_MAX_COUNT 16 -static u32 fdt_domains_count; -static struct sbi_domain fdt_domains[FDT_DOMAIN_MAX_COUNT]; -static struct sbi_hartmask fdt_masks[FDT_DOMAIN_MAX_COUNT]; -static struct sbi_domain_memregion - fdt_regions[FDT_DOMAIN_MAX_COUNT][FDT_DOMAIN_REGION_MAX_COUNT + 1]; +struct parse_region_data { + struct sbi_domain *dom; + u32 region_count; + u32 max_regions; +}; static int __fdt_parse_region(void *fdt, int domain_offset, int region_offset, u32 region_access, @@ -236,17 +236,29 @@ u32 val32; u64 val64; const u32 *val; - u32 *region_count = opaque; + struct parse_region_data *preg = opaque; struct sbi_domain_memregion *region; - /* Find next region of the domain */ - if (FDT_DOMAIN_REGION_MAX_COUNT <= *region_count) + /* + * Non-root domains cannot add a region with only M-mode + * access permissions. M-mode regions can only be part of + * root domain. + * + * SU permission bits can't be all zeroes when M-mode permission + * bits have at least one bit set. + */ + if (!(region_access & SBI_DOMAIN_MEMREGION_SU_ACCESS_MASK) + && (region_access & SBI_DOMAIN_MEMREGION_M_ACCESS_MASK)) return SBI_EINVAL; - region = &fdt_regions[fdt_domains_count][*region_count]; + + /* Find next region of the domain */ + if (preg->max_regions <= preg->region_count) + return SBI_ENOSPC; + region = &preg->dom->regions[preg->region_count]; /* Read "base" DT property */ val = fdt_getprop(fdt, region_offset, "base", &len); - if (!val && len >= 8) + if (!val || len != 8) return SBI_EINVAL; val64 = fdt32_to_cpu(val[0]); val64 = (val64 << 32) | fdt32_to_cpu(val[1]); @@ -254,7 +266,7 @@ /* Read "order" DT property */ val = fdt_getprop(fdt, region_offset, "order", &len); - if (!val && len >= 4) + if (!val || len != 4) return SBI_EINVAL; val32 = fdt32_to_cpu(*val); if (val32 < 3 || __riscv_xlen < val32) @@ -266,7 +278,7 @@ if (fdt_get_property(fdt, region_offset, "mmio", NULL)) region->flags |= SBI_DOMAIN_MEMREGION_MMIO; - (*region_count)++; + preg->region_count++; return 0; } @@ -279,16 +291,30 @@ struct sbi_domain *dom; struct sbi_hartmask *mask; struct sbi_hartmask assign_mask; + struct parse_region_data preg; int *cold_domain_offset = opaque; - struct sbi_domain_memregion *reg, *regions; - int i, err, len, cpus_offset, cpu_offset, doffset; + struct sbi_domain_memregion *reg; + int i, err = 0, len, cpus_offset, cpu_offset, doffset; - /* Sanity check on maximum domains we can handle */ - if (FDT_DOMAIN_MAX_COUNT <= fdt_domains_count) - return SBI_EINVAL; - dom = &fdt_domains[fdt_domains_count]; - mask = &fdt_masks[fdt_domains_count]; - regions = &fdt_regions[fdt_domains_count][0]; + dom = sbi_zalloc(sizeof(*dom)); + if (!dom) + return SBI_ENOMEM; + + dom->regions = sbi_calloc(sizeof(*dom->regions), + FDT_DOMAIN_REGION_MAX_COUNT + 1); + if (!dom->regions) { + err = SBI_ENOMEM; + goto fail_free_domain; + } + preg.dom = dom; + preg.region_count = 0; + preg.max_regions = FDT_DOMAIN_REGION_MAX_COUNT; + + mask = sbi_zalloc(sizeof(*mask)); + if (!mask) { + err = SBI_ENOMEM; + goto fail_free_regions; + } /* Read DT node name */ strncpy(dom->name, fdt_get_name(fdt, domain_offset, NULL), @@ -304,12 +330,14 @@ for (i = 0; i < len; i++) { cpu_offset = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(val[i])); - if (cpu_offset < 0) - return cpu_offset; + if (cpu_offset < 0) { + err = cpu_offset; + goto fail_free_all; + } err = fdt_parse_hart_id(fdt, cpu_offset, &val32); if (err) - return err; + goto fail_free_all; if (!fdt_node_is_enabled(fdt, cpu_offset)) continue; @@ -319,14 +347,10 @@ } /* Setup memregions from DT */ - val32 = 0; - memset(regions, 0, - sizeof(*regions) * (FDT_DOMAIN_REGION_MAX_COUNT + 1)); - dom->regions = regions; - err = fdt_iterate_each_memregion(fdt, domain_offset, &val32, + err = fdt_iterate_each_memregion(fdt, domain_offset, &preg, __fdt_parse_region); if (err) - return err; + goto fail_free_all; /* * Copy over root domain memregions which don't allow @@ -338,14 +362,17 @@ * 2) mmio regions protecting M-mode only mmio devices */ sbi_domain_for_each_memregion(&root, reg) { - if ((reg->flags & SBI_DOMAIN_MEMREGION_READABLE) || - (reg->flags & SBI_DOMAIN_MEMREGION_WRITEABLE) || - (reg->flags & SBI_DOMAIN_MEMREGION_EXECUTABLE)) + if ((reg->flags & SBI_DOMAIN_MEMREGION_SU_READABLE) || + (reg->flags & SBI_DOMAIN_MEMREGION_SU_WRITABLE) || + (reg->flags & SBI_DOMAIN_MEMREGION_SU_EXECUTABLE)) continue; - if (FDT_DOMAIN_REGION_MAX_COUNT <= val32) - return SBI_EINVAL; - memcpy(®ions[val32++], reg, sizeof(*reg)); + if (preg.max_regions <= preg.region_count) { + err = SBI_EINVAL; + goto fail_free_all; + } + memcpy(&dom->regions[preg.region_count++], reg, sizeof(*reg)); } + dom->fw_region_inited = root.fw_region_inited; /* Read "boot-hart" DT property */ val32 = -1U; @@ -401,14 +428,23 @@ /* Read "system-reset-allowed" DT property */ if (fdt_get_property(fdt, domain_offset, "system-reset-allowed", NULL)) - dom->system_reset_allowed = TRUE; + dom->system_reset_allowed = true; else - dom->system_reset_allowed = FALSE; + dom->system_reset_allowed = false; + + /* Read "system-suspend-allowed" DT property */ + if (fdt_get_property(fdt, domain_offset, + "system-suspend-allowed", NULL)) + dom->system_suspend_allowed = true; + else + dom->system_suspend_allowed = false; /* Find /cpus DT node */ cpus_offset = fdt_path_offset(fdt, "/cpus"); - if (cpus_offset < 0) - return cpus_offset; + if (cpus_offset < 0) { + err = cpus_offset; + goto fail_free_all; + } /* HART to domain assignment mask based on CPU DT nodes */ sbi_hartmask_clear_all(&assign_mask); @@ -424,22 +460,35 @@ continue; val = fdt_getprop(fdt, cpu_offset, "opensbi-domain", &len); - if (!val || len < 4) - return SBI_EINVAL; + if (!val || len < 4) { + err = SBI_EINVAL; + goto fail_free_all; + } doffset = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*val)); - if (doffset < 0) - return doffset; + if (doffset < 0) { + err = doffset; + goto fail_free_all; + } if (doffset == domain_offset) sbi_hartmask_set_hart(val32, &assign_mask); } - /* Increment domains count */ - fdt_domains_count++; - /* Register the domain */ - return sbi_domain_register(dom, &assign_mask); + err = sbi_domain_register(dom, &assign_mask); + if (err) + goto fail_free_all; + + return 0; + +fail_free_all: + sbi_free(mask); +fail_free_regions: + sbi_free(dom->regions); +fail_free_domain: + sbi_free(dom); + return err; } int fdt_domains_populate(void *fdt) diff -Nru opensbi-1.1/lib/utils/fdt/fdt_fixup.c opensbi-1.3/lib/utils/fdt/fdt_fixup.c --- opensbi-1.1/lib/utils/fdt/fdt_fixup.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/fdt/fdt_fixup.c 2023-06-23 07:31:49.000000000 +0200 @@ -1,3 +1,4 @@ + // SPDX-License-Identifier: BSD-2-Clause /* * fdt_fixup.c - Flat Device Tree parsing helper routines @@ -14,10 +15,96 @@ #include #include #include +#include #include #include #include +int fdt_add_cpu_idle_states(void *fdt, const struct sbi_cpu_idle_state *state) +{ + int cpu_node, cpus_node, err, idle_states_node; + uint32_t count, phandle; + + err = fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + 1024); + if (err < 0) + return err; + + err = fdt_find_max_phandle(fdt, &phandle); + phandle++; + if (err < 0) + return err; + + cpus_node = fdt_path_offset(fdt, "/cpus"); + if (cpus_node < 0) + return cpus_node; + + /* Do nothing if the idle-states node already exists. */ + idle_states_node = fdt_subnode_offset(fdt, cpus_node, "idle-states"); + if (idle_states_node >= 0) + return 0; + + /* Create the idle-states node and its child nodes. */ + idle_states_node = fdt_add_subnode(fdt, cpus_node, "idle-states"); + if (idle_states_node < 0) + return idle_states_node; + + for (count = 0; state->name; count++, phandle++, state++) { + int idle_state_node; + + idle_state_node = fdt_add_subnode(fdt, idle_states_node, + state->name); + if (idle_state_node < 0) + return idle_state_node; + + fdt_setprop_string(fdt, idle_state_node, "compatible", + "riscv,idle-state"); + fdt_setprop_u32(fdt, idle_state_node, + "riscv,sbi-suspend-param", + state->suspend_param); + if (state->local_timer_stop) + fdt_setprop_empty(fdt, idle_state_node, + "local-timer-stop"); + fdt_setprop_u32(fdt, idle_state_node, "entry-latency-us", + state->entry_latency_us); + fdt_setprop_u32(fdt, idle_state_node, "exit-latency-us", + state->exit_latency_us); + fdt_setprop_u32(fdt, idle_state_node, "min-residency-us", + state->min_residency_us); + if (state->wakeup_latency_us) + fdt_setprop_u32(fdt, idle_state_node, + "wakeup-latency-us", + state->wakeup_latency_us); + fdt_setprop_u32(fdt, idle_state_node, "phandle", phandle); + } + + if (count == 0) + return 0; + + /* Link each cpu node to the idle state nodes. */ + fdt_for_each_subnode(cpu_node, fdt, cpus_node) { + const char *device_type; + fdt32_t *value; + + /* Only process child nodes with device_type = "cpu". */ + device_type = fdt_getprop(fdt, cpu_node, "device_type", NULL); + if (!device_type || strcmp(device_type, "cpu")) + continue; + + /* Allocate space for the list of phandles. */ + err = fdt_setprop_placeholder(fdt, cpu_node, "cpu-idle-states", + count * sizeof(phandle), + (void **)&value); + if (err < 0) + return err; + + /* Fill in the phandles of the idle state nodes. */ + for (uint32_t i = 0; i < count; ++i) + value[i] = cpu_to_fdt32(phandle - count + i); + } + + return 0; +} + void fdt_cpu_fixup(void *fdt) { struct sbi_domain *dom = sbi_domain_thishart_ptr(); @@ -74,22 +161,23 @@ } } -void fdt_aplic_fixup(void *fdt) +static void fdt_fixup_node(void *fdt, const char *compatible) { int noff = 0; while ((noff = fdt_node_offset_by_compatible(fdt, noff, - "riscv,aplic")) >= 0) + compatible)) >= 0) fdt_domain_based_fixup_one(fdt, noff); } -void fdt_imsic_fixup(void *fdt) +void fdt_aplic_fixup(void *fdt) { - int noff = 0; + fdt_fixup_node(fdt, "riscv,aplic"); +} - while ((noff = fdt_node_offset_by_compatible(fdt, noff, - "riscv,imsics")) >= 0) - fdt_domain_based_fixup_one(fdt, noff); +void fdt_imsic_fixup(void *fdt) +{ + fdt_fixup_node(fdt, "riscv,imsics"); } void fdt_plic_fixup(void *fdt) @@ -122,7 +210,7 @@ static int fdt_resv_memory_update_node(void *fdt, unsigned long addr, unsigned long size, int index, - int parent, bool no_map) + int parent) { int na = fdt_address_cells(fdt, 0); int ns = fdt_size_cells(fdt, 0); @@ -151,16 +239,14 @@ if (subnode < 0) return subnode; - if (no_map) { - /* - * Tell operating system not to create a virtual - * mapping of the region as part of its standard - * mapping of system memory. - */ - err = fdt_setprop_empty(fdt, subnode, "no-map"); - if (err < 0) - return err; - } + /* + * Tell operating system not to create a virtual + * mapping of the region as part of its standard + * mapping of system memory. + */ + err = fdt_setprop_empty(fdt, subnode, "no-map"); + if (err < 0) + return err; /* encode the property value */ val = reg; @@ -198,9 +284,10 @@ { struct sbi_domain_memregion *reg; struct sbi_domain *dom = sbi_domain_thishart_ptr(); - struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); + unsigned long filtered_base[PMP_COUNT] = { 0 }; + unsigned char filtered_order[PMP_COUNT] = { 0 }; unsigned long addr, size; - int err, parent, i; + int err, parent, i, j; int na = fdt_address_cells(fdt, 0); int ns = fdt_size_cells(fdt, 0); @@ -258,42 +345,41 @@ /* Ignore MMIO or READABLE or WRITABLE or EXECUTABLE regions */ if (reg->flags & SBI_DOMAIN_MEMREGION_MMIO) continue; - if (reg->flags & SBI_DOMAIN_MEMREGION_READABLE) + if (reg->flags & SBI_DOMAIN_MEMREGION_SU_READABLE) continue; - if (reg->flags & SBI_DOMAIN_MEMREGION_WRITEABLE) + if (reg->flags & SBI_DOMAIN_MEMREGION_SU_WRITABLE) continue; - if (reg->flags & SBI_DOMAIN_MEMREGION_EXECUTABLE) + if (reg->flags & SBI_DOMAIN_MEMREGION_SU_EXECUTABLE) continue; + if (i >= PMP_COUNT) { + sbi_printf("%s: Too many memory regions to fixup.\n", + __func__); + return SBI_ENOSPC; + } + + bool overlap = false; addr = reg->base; - size = 1UL << reg->order; - fdt_resv_memory_update_node(fdt, addr, size, i, parent, - (sbi_hart_pmp_count(scratch)) ? false : true); - i++; + for (j = 0; j < i; j++) { + if (addr == filtered_base[j] + && filtered_order[j] < reg->order) { + overlap = true; + filtered_order[j] = reg->order; + break; + } + } + + if (!overlap) { + filtered_base[i] = reg->base; + filtered_order[i] = reg->order; + i++; + } } - return 0; -} - -int fdt_reserved_memory_nomap_fixup(void *fdt) -{ - int parent, subnode; - int err; - - /* Locate the reserved memory node */ - parent = fdt_path_offset(fdt, "/reserved-memory"); - if (parent < 0) - return parent; - - fdt_for_each_subnode(subnode, fdt, parent) { - /* - * Tell operating system not to create a virtual - * mapping of the region as part of its standard - * mapping of system memory. - */ - err = fdt_setprop_empty(fdt, subnode, "no-map"); - if (err < 0) - return err; + for (j = 0; j < i; j++) { + addr = filtered_base[j]; + size = 1UL << filtered_order[j]; + fdt_resv_memory_update_node(fdt, addr, size, j, parent); } return 0; diff -Nru opensbi-1.1/lib/utils/fdt/fdt_helper.c opensbi-1.3/lib/utils/fdt/fdt_helper.c --- opensbi-1.1/lib/utils/fdt/fdt_helper.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/fdt/fdt_helper.c 2023-06-23 07:31:49.000000000 +0200 @@ -23,12 +23,11 @@ #define DEFAULT_UART_REG_IO_WIDTH 1 #define DEFAULT_UART_REG_OFFSET 0 +#define DEFAULT_RENESAS_SCIF_FREQ 100000000 +#define DEFAULT_RENESAS_SCIF_BAUD 115200 + #define DEFAULT_SIFIVE_UART_FREQ 0 #define DEFAULT_SIFIVE_UART_BAUD 115200 -#define DEFAULT_SIFIVE_UART_REG_SHIFT 0 -#define DEFAULT_SIFIVE_UART_REG_IO_WIDTH 4 - -#define DEFAULT_GAISLER_UART_REG_IO_WIDTH 4 #define DEFAULT_SHAKTI_UART_FREQ 50000000 #define DEFAULT_SHAKTI_UART_BAUD 115200 @@ -128,7 +127,7 @@ int i, rlen; int cell_addr, cell_size; const fdt32_t *ranges; - uint64_t offset = 0, caddr = 0, paddr = 0, rsize = 0; + uint64_t offset, caddr = 0, paddr = 0, rsize = 0; cell_addr = fdt_address_cells(fdt, parent); if (cell_addr < 1) @@ -314,8 +313,10 @@ return 0; } -int fdt_parse_gaisler_uart_node(void *fdt, int nodeoffset, - struct platform_uart_data *uart) +static int fdt_parse_uart_node_common(void *fdt, int nodeoffset, + struct platform_uart_data *uart, + unsigned long default_freq, + unsigned long default_baud) { int len, rc; const fdt32_t *val; @@ -338,126 +339,60 @@ if (len > 0 && val) uart->freq = fdt32_to_cpu(*val); else - uart->freq = DEFAULT_UART_FREQ; + uart->freq = default_freq; val = (fdt32_t *)fdt_getprop(fdt, nodeoffset, "current-speed", &len); if (len > 0 && val) uart->baud = fdt32_to_cpu(*val); else - uart->baud = DEFAULT_UART_BAUD; - - /* For Gaisler APBUART, the reg-shift and reg-io-width are fixed .*/ - uart->reg_shift = DEFAULT_UART_REG_SHIFT; - uart->reg_io_width = DEFAULT_GAISLER_UART_REG_IO_WIDTH; + uart->baud = default_baud; return 0; } -int fdt_parse_shakti_uart_node(void *fdt, int nodeoffset, - struct platform_uart_data *uart) +int fdt_parse_gaisler_uart_node(void *fdt, int nodeoffset, + struct platform_uart_data *uart) { - int len, rc; - const fdt32_t *val; - uint64_t reg_addr, reg_size; - - if (nodeoffset < 0 || !uart || !fdt) - return SBI_ENODEV; - - rc = fdt_get_node_addr_size(fdt, nodeoffset, 0, - ®_addr, ®_size); - if (rc < 0 || !reg_addr || !reg_size) - return SBI_ENODEV; - uart->addr = reg_addr; - - /** - * UART address is mandaotry. clock-frequency and current-speed - * may not be present. Don't return error. - */ - val = (fdt32_t *)fdt_getprop(fdt, nodeoffset, "clock-frequency", &len); - if (len > 0 && val) - uart->freq = fdt32_to_cpu(*val); - else - uart->freq = DEFAULT_SHAKTI_UART_FREQ; + return fdt_parse_uart_node_common(fdt, nodeoffset, uart, + DEFAULT_UART_FREQ, + DEFAULT_UART_BAUD); +} - val = (fdt32_t *)fdt_getprop(fdt, nodeoffset, "current-speed", &len); - if (len > 0 && val) - uart->baud = fdt32_to_cpu(*val); - else - uart->baud = DEFAULT_SHAKTI_UART_BAUD; +int fdt_parse_renesas_scif_node(void *fdt, int nodeoffset, + struct platform_uart_data *uart) +{ + return fdt_parse_uart_node_common(fdt, nodeoffset, uart, + DEFAULT_RENESAS_SCIF_FREQ, + DEFAULT_RENESAS_SCIF_BAUD); +} - return 0; +int fdt_parse_shakti_uart_node(void *fdt, int nodeoffset, + struct platform_uart_data *uart) +{ + return fdt_parse_uart_node_common(fdt, nodeoffset, uart, + DEFAULT_SHAKTI_UART_FREQ, + DEFAULT_SHAKTI_UART_BAUD); } int fdt_parse_sifive_uart_node(void *fdt, int nodeoffset, struct platform_uart_data *uart) { - int len, rc; - const fdt32_t *val; - uint64_t reg_addr, reg_size; - - if (nodeoffset < 0 || !uart || !fdt) - return SBI_ENODEV; - - rc = fdt_get_node_addr_size(fdt, nodeoffset, 0, - ®_addr, ®_size); - if (rc < 0 || !reg_addr || !reg_size) - return SBI_ENODEV; - uart->addr = reg_addr; - - /** - * UART address is mandaotry. clock-frequency and current-speed - * may not be present. Don't return error. - */ - val = (fdt32_t *)fdt_getprop(fdt, nodeoffset, "clock-frequency", &len); - if (len > 0 && val) - uart->freq = fdt32_to_cpu(*val); - else - uart->freq = DEFAULT_SIFIVE_UART_FREQ; - - val = (fdt32_t *)fdt_getprop(fdt, nodeoffset, "current-speed", &len); - if (len > 0 && val) - uart->baud = fdt32_to_cpu(*val); - else - uart->baud = DEFAULT_SIFIVE_UART_BAUD; - - /* For SiFive UART, the reg-shift and reg-io-width are fixed .*/ - uart->reg_shift = DEFAULT_SIFIVE_UART_REG_SHIFT; - uart->reg_io_width = DEFAULT_SIFIVE_UART_REG_IO_WIDTH; - - return 0; + return fdt_parse_uart_node_common(fdt, nodeoffset, uart, + DEFAULT_SIFIVE_UART_FREQ, + DEFAULT_SIFIVE_UART_BAUD); } -int fdt_parse_uart8250_node(void *fdt, int nodeoffset, - struct platform_uart_data *uart) +int fdt_parse_uart_node(void *fdt, int nodeoffset, + struct platform_uart_data *uart) { int len, rc; const fdt32_t *val; - uint64_t reg_addr, reg_size; - if (nodeoffset < 0 || !uart || !fdt) - return SBI_ENODEV; - - rc = fdt_get_node_addr_size(fdt, nodeoffset, 0, - ®_addr, ®_size); - if (rc < 0 || !reg_addr || !reg_size) - return SBI_ENODEV; - uart->addr = reg_addr; - - /** - * UART address is mandaotry. clock-frequency and current-speed - * may not be present. Don't return error. - */ - val = (fdt32_t *)fdt_getprop(fdt, nodeoffset, "clock-frequency", &len); - if (len > 0 && val) - uart->freq = fdt32_to_cpu(*val); - else - uart->freq = DEFAULT_UART_FREQ; - - val = (fdt32_t *)fdt_getprop(fdt, nodeoffset, "current-speed", &len); - if (len > 0 && val) - uart->baud = fdt32_to_cpu(*val); - else - uart->baud = DEFAULT_UART_BAUD; + rc = fdt_parse_uart_node_common(fdt, nodeoffset, uart, + DEFAULT_UART_FREQ, + DEFAULT_UART_BAUD); + if (rc) + return rc; val = (fdt32_t *)fdt_getprop(fdt, nodeoffset, "reg-shift", &len); if (len > 0 && val) @@ -492,25 +427,13 @@ if (nodeoffset < 0) return nodeoffset; - return fdt_parse_uart8250_node(fdt, nodeoffset, uart); + return fdt_parse_uart_node(fdt, nodeoffset, uart); } int fdt_parse_xlnx_uartlite_node(void *fdt, int nodeoffset, struct platform_uart_data *uart) { - int rc; - uint64_t reg_addr, reg_size; - - if (nodeoffset < 0 || !uart || !fdt) - return SBI_ENODEV; - - rc = fdt_get_node_addr_size(fdt, nodeoffset, 0, - ®_addr, ®_size); - if (rc < 0 || !reg_addr || !reg_size) - return SBI_ENODEV; - uart->addr = reg_addr; - - return 0; + return fdt_parse_uart_node_common(fdt, nodeoffset, uart, 0, 0); } int fdt_parse_aplic_node(void *fdt, int nodeoff, struct aplic_data *aplic) @@ -766,7 +689,7 @@ break; regs->addr = reg_addr; regs->size = reg_size; - }; + } if (!imsic->regs[0].size) return SBI_EINVAL; @@ -860,7 +783,7 @@ continue; cpu_offset = fdt_parent_offset(fdt, cpu_intc_offset); - if (cpu_intc_offset < 0) + if (cpu_offset < 0) continue; rc = fdt_parse_hart_id(fdt, cpu_offset, &hartid); @@ -887,6 +810,118 @@ return 0; } + +int fdt_parse_plmt_node(void *fdt, int nodeoffset, unsigned long *plmt_base, + unsigned long *plmt_size, u32 *hart_count) +{ + const fdt32_t *val; + int rc, i, count; + uint64_t reg_addr, reg_size; + u32 phandle, hwirq, hartid, hcount; + + if (nodeoffset < 0 || !fdt || !plmt_base || + !hart_count || !plmt_size) + return SBI_EINVAL; + + rc = fdt_get_node_addr_size(fdt, nodeoffset, 0, + ®_addr, ®_size); + if (rc < 0) + return SBI_ENODEV; + *plmt_base = reg_addr; + *plmt_size = reg_size; + + val = fdt_getprop(fdt, nodeoffset, "interrupts-extended", &count); + if (!val || count < sizeof(fdt32_t)) + return 0; + count = count / sizeof(fdt32_t); + + hcount = 0; + for (i = 0; i < (count / 2); i++) { + int cpu_offset, cpu_intc_offset; + + phandle = fdt32_to_cpu(val[2 * i]); + hwirq = fdt32_to_cpu(val[2 * i + 1]); + + cpu_intc_offset = fdt_node_offset_by_phandle(fdt, phandle); + if (cpu_intc_offset < 0) + continue; + + cpu_offset = fdt_parent_offset(fdt, cpu_intc_offset); + if (cpu_offset < 0) + continue; + + rc = fdt_parse_hart_id(fdt, cpu_offset, &hartid); + + if (rc) + continue; + + if (SBI_HARTMASK_MAX_BITS <= hartid) + continue; + + if (hwirq == IRQ_M_TIMER) + hcount++; + } + + *hart_count = hcount; + + return 0; +} + +int fdt_parse_plicsw_node(void *fdt, int nodeoffset, unsigned long *plicsw_base, + unsigned long *size, u32 *hart_count) +{ + const fdt32_t *val; + int rc, i, count; + uint64_t reg_addr, reg_size; + u32 phandle, hwirq, hartid, hcount; + + if (nodeoffset < 0 || !fdt || !plicsw_base || + !hart_count || !size) + return SBI_EINVAL; + + rc = fdt_get_node_addr_size(fdt, nodeoffset, 0, + ®_addr, ®_size); + if (rc < 0) + return SBI_ENODEV; + *plicsw_base = reg_addr; + *size = reg_size; + + val = fdt_getprop(fdt, nodeoffset, "interrupts-extended", &count); + if (!val || count < sizeof(fdt32_t)) + return 0; + count = count / sizeof(fdt32_t); + + hcount = 0; + for (i = 0; i < (count / 2); i++) { + int cpu_offset, cpu_intc_offset; + + phandle = fdt32_to_cpu(val[2 * i]); + hwirq = fdt32_to_cpu(val[2 * i + 1]); + + cpu_intc_offset = fdt_node_offset_by_phandle(fdt, phandle); + if (cpu_intc_offset < 0) + continue; + + cpu_offset = fdt_parent_offset(fdt, cpu_intc_offset); + if (cpu_offset < 0) + continue; + + rc = fdt_parse_hart_id(fdt, cpu_offset, &hartid); + + if (rc) + continue; + + if (SBI_HARTMASK_MAX_BITS <= hartid) + continue; + + if (hwirq == IRQ_M_SOFT) + hcount++; + } + + *hart_count = hcount; + + return 0; +} int fdt_parse_compat_addr(void *fdt, uint64_t *addr, const char *compatible) diff -Nru opensbi-1.1/lib/utils/fdt/fdt_pmu.c opensbi-1.3/lib/utils/fdt/fdt_pmu.c --- opensbi-1.1/lib/utils/fdt/fdt_pmu.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/fdt/fdt_pmu.c 2023-06-23 07:31:49.000000000 +0200 @@ -12,6 +12,7 @@ #include #include #include +#include #include #define FDT_PMU_HW_EVENT_MAX (SBI_PMU_HW_EVENT_MAX * 2) @@ -75,42 +76,52 @@ if (pmu_offset < 0) return SBI_EFAIL; - event_ctr_map = fdt_getprop(fdt, pmu_offset, "riscv,event-to-mhpmcounters", &len); - if (!event_ctr_map || len < 8) - return SBI_EFAIL; - len = len / (sizeof(u32) * 3); - for (i = 0; i < len; i++) { - event_idx_start = fdt32_to_cpu(event_ctr_map[3 * i]); - event_idx_end = fdt32_to_cpu(event_ctr_map[3 * i + 1]); - ctr_map = fdt32_to_cpu(event_ctr_map[3 * i + 2]); - sbi_pmu_add_hw_event_counter_map(event_idx_start, event_idx_end, ctr_map); + event_ctr_map = fdt_getprop(fdt, pmu_offset, + "riscv,event-to-mhpmcounters", &len); + if (event_ctr_map && len >= 8) { + len = len / (sizeof(u32) * 3); + for (i = 0; i < len; i++) { + event_idx_start = fdt32_to_cpu(event_ctr_map[3 * i]); + event_idx_end = fdt32_to_cpu(event_ctr_map[3 * i + 1]); + ctr_map = fdt32_to_cpu(event_ctr_map[3 * i + 2]); + result = sbi_pmu_add_hw_event_counter_map( + event_idx_start, event_idx_end, ctr_map); + if (result) + return result; + } } - event_val = fdt_getprop(fdt, pmu_offset, "riscv,event-to-mhpmevent", &len); - if (!event_val || len < 8) - return SBI_EFAIL; - len = len / (sizeof(u32) * 3); - for (i = 0; i < len; i++) { - event = &fdt_pmu_evt_select[hw_event_count]; - event->eidx = fdt32_to_cpu(event_val[3 * i]); - event->select = fdt32_to_cpu(event_val[3 * i + 1]); - event->select = (event->select << 32) | fdt32_to_cpu(event_val[3 * i + 2]); - hw_event_count++; + event_val = fdt_getprop(fdt, pmu_offset, + "riscv,event-to-mhpmevent", &len); + if (event_val && len >= 8) { + len = len / (sizeof(u32) * 3); + for (i = 0; i < len; i++) { + event = &fdt_pmu_evt_select[hw_event_count]; + event->eidx = fdt32_to_cpu(event_val[3 * i]); + event->select = fdt32_to_cpu(event_val[3 * i + 1]); + event->select = (event->select << 32) | + fdt32_to_cpu(event_val[3 * i + 2]); + hw_event_count++; + } } - event_val = fdt_getprop(fdt, pmu_offset, "riscv,raw-event-to-mhpmcounters", &len); - if (!event_val || len < 20) - return SBI_EFAIL; - len = len / (sizeof(u32) * 5); - for (i = 0; i < len; i++) { - raw_selector = fdt32_to_cpu(event_val[5 * i]); - raw_selector = (raw_selector << 32) | fdt32_to_cpu(event_val[5 * i + 1]); - select_mask = fdt32_to_cpu(event_val[5 * i + 2]); - select_mask = (select_mask << 32) | fdt32_to_cpu(event_val[5 * i + 3]); - ctr_map = fdt32_to_cpu(event_val[5 * i + 4]); - result = sbi_pmu_add_raw_event_counter_map(raw_selector, select_mask, ctr_map); - if (!result) - hw_event_count++; + event_val = fdt_getprop(fdt, pmu_offset, + "riscv,raw-event-to-mhpmcounters", &len); + if (event_val && len >= 20) { + len = len / (sizeof(u32) * 5); + for (i = 0; i < len; i++) { + raw_selector = fdt32_to_cpu(event_val[5 * i]); + raw_selector = (raw_selector << 32) | + fdt32_to_cpu(event_val[5 * i + 1]); + select_mask = fdt32_to_cpu(event_val[5 * i + 2]); + select_mask = (select_mask << 32) | + fdt32_to_cpu(event_val[5 * i + 3]); + ctr_map = fdt32_to_cpu(event_val[5 * i + 4]); + result = sbi_pmu_add_raw_event_counter_map( + raw_selector, select_mask, ctr_map); + if (result) + return result; + } } return 0; diff -Nru opensbi-1.1/lib/utils/fdt/Kconfig opensbi-1.3/lib/utils/fdt/Kconfig --- opensbi-1.1/lib/utils/fdt/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/fdt/Kconfig 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: BSD-2-Clause + +menuconfig FDT + bool "Flattened Device Tree (FDT) support" + select LIBFDT + default n + +if FDT + +config FDT_DOMAIN + bool "FDT domain support" + default n + +config FDT_PMU + bool "FDT performance monitoring unit (PMU) support" + default n + +endif diff -Nru opensbi-1.1/lib/utils/fdt/objects.mk opensbi-1.3/lib/utils/fdt/objects.mk --- opensbi-1.1/lib/utils/fdt/objects.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/fdt/objects.mk 2023-06-23 07:31:49.000000000 +0200 @@ -4,7 +4,7 @@ # Copyright (C) 2020 Bin Meng # -libsbiutils-objs-y += fdt/fdt_domain.o -libsbiutils-objs-y += fdt/fdt_pmu.o -libsbiutils-objs-y += fdt/fdt_helper.o -libsbiutils-objs-y += fdt/fdt_fixup.o +libsbiutils-objs-$(CONFIG_FDT_DOMAIN) += fdt/fdt_domain.o +libsbiutils-objs-$(CONFIG_FDT_PMU) += fdt/fdt_pmu.o +libsbiutils-objs-$(CONFIG_FDT) += fdt/fdt_helper.o +libsbiutils-objs-$(CONFIG_FDT) += fdt/fdt_fixup.o diff -Nru opensbi-1.1/lib/utils/gpio/fdt_gpio_sifive.c opensbi-1.3/lib/utils/gpio/fdt_gpio_sifive.c --- opensbi-1.1/lib/utils/gpio/fdt_gpio_sifive.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/gpio/fdt_gpio_sifive.c 2023-06-23 07:31:49.000000000 +0200 @@ -9,11 +9,10 @@ #include #include +#include #include #include -#define SIFIVE_GPIO_CHIP_MAX 2 - #define SIFIVE_GPIO_PINS_MIN 1 #define SIFIVE_GPIO_PINS_MAX 32 #define SIFIVE_GPIO_PINS_DEF 16 @@ -27,9 +26,6 @@ struct gpio_chip chip; }; -static unsigned int sifive_gpio_chip_count; -static struct sifive_gpio_chip sifive_gpio_chip_array[SIFIVE_GPIO_CHIP_MAX]; - static int sifive_gpio_direction_output(struct gpio_pin *gp, int value) { unsigned int v; @@ -73,13 +69,15 @@ struct sifive_gpio_chip *chip; uint64_t addr; - if (SIFIVE_GPIO_CHIP_MAX <= sifive_gpio_chip_count) - return SBI_ENOSPC; - chip = &sifive_gpio_chip_array[sifive_gpio_chip_count]; + chip = sbi_zalloc(sizeof(*chip)); + if (!chip) + return SBI_ENOMEM; rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &addr, NULL); - if (rc) + if (rc) { + sbi_free(chip); return rc; + } chip->addr = addr; chip->chip.driver = &fdt_gpio_sifive; @@ -88,10 +86,11 @@ chip->chip.direction_output = sifive_gpio_direction_output; chip->chip.set = sifive_gpio_set; rc = gpio_chip_add(&chip->chip); - if (rc) + if (rc) { + sbi_free(chip); return rc; + } - sifive_gpio_chip_count++; return 0; } diff -Nru opensbi-1.1/lib/utils/gpio/fdt_gpio_starfive.c opensbi-1.3/lib/utils/gpio/fdt_gpio_starfive.c --- opensbi-1.1/lib/utils/gpio/fdt_gpio_starfive.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/gpio/fdt_gpio_starfive.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,117 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Starfive + * + * Authors: + * Minda.chen + */ + +#include +#include +#include +#include +#include +#include + +#define STARFIVE_GPIO_PINS_DEF 64 +#define STARFIVE_GPIO_OUTVAL 0x40 +#define STARFIVE_GPIO_MASK 0xff +#define STARFIVE_GPIO_REG_SHIFT_MASK 0x3 +#define STARFIVE_GPIO_SHIFT_BITS 0x3 + +struct starfive_gpio_chip { + unsigned long addr; + struct gpio_chip chip; +}; + +static int starfive_gpio_direction_output(struct gpio_pin *gp, int value) +{ + u32 val; + unsigned long reg_addr; + u32 bit_mask, shift_bits; + struct starfive_gpio_chip *chip = + container_of(gp->chip, struct starfive_gpio_chip, chip); + + /* set out en*/ + reg_addr = chip->addr + gp->offset; + reg_addr &= ~(STARFIVE_GPIO_REG_SHIFT_MASK); + + val = readl((void *)(reg_addr)); + shift_bits = (gp->offset & STARFIVE_GPIO_REG_SHIFT_MASK) + << STARFIVE_GPIO_SHIFT_BITS; + bit_mask = STARFIVE_GPIO_MASK << shift_bits; + + val = readl((void *)reg_addr); + val &= ~bit_mask; + writel(val, (void *)reg_addr); + + return 0; +} + +static void starfive_gpio_set(struct gpio_pin *gp, int value) +{ + u32 val; + unsigned long reg_addr; + u32 bit_mask, shift_bits; + struct starfive_gpio_chip *chip = + container_of(gp->chip, struct starfive_gpio_chip, chip); + + reg_addr = chip->addr + gp->offset; + reg_addr &= ~(STARFIVE_GPIO_REG_SHIFT_MASK); + + shift_bits = (gp->offset & STARFIVE_GPIO_REG_SHIFT_MASK) + << STARFIVE_GPIO_SHIFT_BITS; + bit_mask = STARFIVE_GPIO_MASK << shift_bits; + /* set output value */ + val = readl((void *)(reg_addr + STARFIVE_GPIO_OUTVAL)); + val &= ~bit_mask; + val |= value << shift_bits; + writel(val, (void *)(reg_addr + STARFIVE_GPIO_OUTVAL)); +} + +extern struct fdt_gpio fdt_gpio_starfive; + +static int starfive_gpio_init(void *fdt, int nodeoff, u32 phandle, + const struct fdt_match *match) +{ + int rc; + struct starfive_gpio_chip *chip; + u64 addr; + + chip = sbi_zalloc(sizeof(*chip)); + if (!chip) + return SBI_ENOMEM; + + rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &addr, NULL); + if (rc) { + sbi_free(chip); + return rc; + } + + chip->addr = addr; + chip->chip.driver = &fdt_gpio_starfive; + chip->chip.id = phandle; + chip->chip.ngpio = STARFIVE_GPIO_PINS_DEF; + chip->chip.direction_output = starfive_gpio_direction_output; + chip->chip.set = starfive_gpio_set; + rc = gpio_chip_add(&chip->chip); + if (rc) { + sbi_free(chip); + return rc; + } + + return 0; +} + +static const struct fdt_match starfive_gpio_match[] = { + { .compatible = "starfive,jh7110-sys-pinctrl" }, + { .compatible = "starfive,iomux-pinctrl" }, + { }, +}; + +struct fdt_gpio fdt_gpio_starfive = { + .match_table = starfive_gpio_match, + .xlate = fdt_gpio_simple_xlate, + .init = starfive_gpio_init, +}; diff -Nru opensbi-1.1/lib/utils/gpio/Kconfig opensbi-1.3/lib/utils/gpio/Kconfig --- opensbi-1.1/lib/utils/gpio/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/gpio/Kconfig 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: BSD-2-Clause + +menu "GPIO Support" + +config FDT_GPIO + bool "FDT based GPIO drivers" + depends on FDT + select GPIO + default n + +if FDT_GPIO + +config FDT_GPIO_SIFIVE + bool "SiFive GPIO FDT driver" + default n + +config FDT_GPIO_STARFIVE + bool "StarFive GPIO FDT driver" + default n +endif + +config GPIO + bool "GPIO support" + default n + +endmenu diff -Nru opensbi-1.1/lib/utils/gpio/objects.mk opensbi-1.3/lib/utils/gpio/objects.mk --- opensbi-1.1/lib/utils/gpio/objects.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/gpio/objects.mk 2023-06-23 07:31:49.000000000 +0200 @@ -7,10 +7,13 @@ # Anup Patel # -libsbiutils-objs-y += gpio/fdt_gpio.o -libsbiutils-objs-y += gpio/fdt_gpio_drivers.o +libsbiutils-objs-$(CONFIG_FDT_GPIO) += gpio/fdt_gpio.o +libsbiutils-objs-$(CONFIG_FDT_GPIO) += gpio/fdt_gpio_drivers.o -carray-fdt_gpio_drivers-y += fdt_gpio_sifive -libsbiutils-objs-y += gpio/fdt_gpio_sifive.o +carray-fdt_gpio_drivers-$(CONFIG_FDT_GPIO_SIFIVE) += fdt_gpio_sifive +libsbiutils-objs-$(CONFIG_FDT_GPIO_SIFIVE) += gpio/fdt_gpio_sifive.o -libsbiutils-objs-y += gpio/gpio.o +carray-fdt_gpio_drivers-$(CONFIG_FDT_GPIO_STARFIVE) += fdt_gpio_starfive +libsbiutils-objs-$(CONFIG_FDT_GPIO_STARFIVE) += gpio/fdt_gpio_starfive.o + +libsbiutils-objs-$(CONFIG_GPIO) += gpio/gpio.o diff -Nru opensbi-1.1/lib/utils/i2c/dw_i2c.c opensbi-1.3/lib/utils/i2c/dw_i2c.c --- opensbi-1.1/lib/utils/i2c/dw_i2c.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/i2c/dw_i2c.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,190 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 starfivetech.com + * + * Authors: + * Minda Chen + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DW_IC_CON 0x00 +#define DW_IC_TAR 0x04 +#define DW_IC_SAR 0x08 +#define DW_IC_DATA_CMD 0x10 +#define DW_IC_SS_SCL_HCNT 0x14 +#define DW_IC_SS_SCL_LCNT 0x18 +#define DW_IC_FS_SCL_HCNT 0x1c +#define DW_IC_FS_SCL_LCNT 0x20 +#define DW_IC_HS_SCL_HCNT 0x24 +#define DW_IC_HS_SCL_LCNT 0x28 +#define DW_IC_INTR_STAT 0x2c +#define DW_IC_INTR_MASK 0x30 +#define DW_IC_RAW_INTR_STAT 0x34 +#define DW_IC_RX_TL 0x38 +#define DW_IC_TX_TL 0x3c +#define DW_IC_CLR_INTR 0x40 +#define DW_IC_CLR_RX_UNDER 0x44 +#define DW_IC_CLR_RX_OVER 0x48 +#define DW_IC_CLR_TX_OVER 0x4c +#define DW_IC_CLR_RD_REQ 0x50 +#define DW_IC_CLR_TX_ABRT 0x54 +#define DW_IC_CLR_RX_DONE 0x58 +#define DW_IC_CLR_ACTIVITY 0x5c +#define DW_IC_CLR_STOP_DET 0x60 +#define DW_IC_CLR_START_DET 0x64 +#define DW_IC_CLR_GEN_CALL 0x68 +#define DW_IC_ENABLE 0x6c +#define DW_IC_STATUS 0x70 +#define DW_IC_TXFLR 0x74 +#define DW_IC_RXFLR 0x78 +#define DW_IC_SDA_HOLD 0x7c +#define DW_IC_TX_ABRT_SOURCE 0x80 +#define DW_IC_ENABLE_STATUS 0x9c +#define DW_IC_CLR_RESTART_DET 0xa8 +#define DW_IC_COMP_PARAM_1 0xf4 +#define DW_IC_COMP_VERSION 0xf8 + +#define DW_I2C_STATUS_TXFIFO_EMPTY BIT(2) +#define DW_I2C_STATUS_RXFIFO_NOT_EMPTY BIT(3) + +#define IC_DATA_CMD_READ BIT(8) +#define IC_DATA_CMD_STOP BIT(9) +#define IC_DATA_CMD_RESTART BIT(10) +#define IC_INT_STATUS_STOPDET BIT(9) + +static inline void dw_i2c_setreg(struct dw_i2c_adapter *adap, + u8 reg, u32 value) +{ + writel(value, (void *)adap->addr + reg); +} + +static inline u32 dw_i2c_getreg(struct dw_i2c_adapter *adap, + u32 reg) +{ + return readl((void *)adap->addr + reg); +} + +static int dw_i2c_adapter_poll(struct dw_i2c_adapter *adap, + u32 mask, u32 addr, + bool inverted) +{ + unsigned int timeout = 10; /* msec */ + int count = 0; + u32 val; + + do { + val = dw_i2c_getreg(adap, addr); + if (inverted) { + if (!(val & mask)) + return 0; + } else { + if (val & mask) + return 0; + } + sbi_timer_udelay(2); + count += 1; + if (count == (timeout * 1000)) + return SBI_ETIMEDOUT; + } while (1); +} + +#define dw_i2c_adapter_poll_rxrdy(adap) \ + dw_i2c_adapter_poll(adap, DW_I2C_STATUS_RXFIFO_NOT_EMPTY, DW_IC_STATUS, 0) +#define dw_i2c_adapter_poll_txfifo_ready(adap) \ + dw_i2c_adapter_poll(adap, DW_I2C_STATUS_TXFIFO_EMPTY, DW_IC_STATUS, 0) + +static int dw_i2c_write_addr(struct dw_i2c_adapter *adap, u8 addr) +{ + dw_i2c_setreg(adap, DW_IC_ENABLE, 0); + dw_i2c_setreg(adap, DW_IC_TAR, addr); + dw_i2c_setreg(adap, DW_IC_ENABLE, 1); + + return 0; +} + +static int dw_i2c_adapter_read(struct i2c_adapter *ia, u8 addr, + u8 reg, u8 *buffer, int len) +{ + struct dw_i2c_adapter *adap = + container_of(ia, struct dw_i2c_adapter, adapter); + int rc; + + dw_i2c_write_addr(adap, addr); + + rc = dw_i2c_adapter_poll_txfifo_ready(adap); + if (rc) + return rc; + + /* set register address */ + dw_i2c_setreg(adap, DW_IC_DATA_CMD, reg); + + /* set value */ + while (len) { + if (len == 1) + dw_i2c_setreg(adap, DW_IC_DATA_CMD, + IC_DATA_CMD_READ | IC_DATA_CMD_STOP); + else + dw_i2c_setreg(adap, DW_IC_DATA_CMD, IC_DATA_CMD_READ); + + rc = dw_i2c_adapter_poll_rxrdy(adap); + if (rc) + return rc; + + *buffer = dw_i2c_getreg(adap, DW_IC_DATA_CMD) & 0xff; + buffer++; + len--; + } + + return 0; +} + +static int dw_i2c_adapter_write(struct i2c_adapter *ia, u8 addr, + u8 reg, u8 *buffer, int len) +{ + struct dw_i2c_adapter *adap = + container_of(ia, struct dw_i2c_adapter, adapter); + int rc; + + dw_i2c_write_addr(adap, addr); + + rc = dw_i2c_adapter_poll_txfifo_ready(adap); + if (rc) + return rc; + + /* set register address */ + dw_i2c_setreg(adap, DW_IC_DATA_CMD, reg); + + while (len) { + rc = dw_i2c_adapter_poll_txfifo_ready(adap); + if (rc) + return rc; + + if (len == 1) + dw_i2c_setreg(adap, DW_IC_DATA_CMD, *buffer | IC_DATA_CMD_STOP); + else + dw_i2c_setreg(adap, DW_IC_DATA_CMD, *buffer); + + buffer++; + len--; + } + rc = dw_i2c_adapter_poll_txfifo_ready(adap); + + return rc; +} + +int dw_i2c_init(struct i2c_adapter *adapter, int nodeoff) +{ + adapter->id = nodeoff; + adapter->write = dw_i2c_adapter_write; + adapter->read = dw_i2c_adapter_read; + + return i2c_adapter_add(adapter); +} diff -Nru opensbi-1.1/lib/utils/i2c/fdt_i2c_dw.c opensbi-1.3/lib/utils/i2c/fdt_i2c_dw.c --- opensbi-1.1/lib/utils/i2c/fdt_i2c_dw.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/i2c/fdt_i2c_dw.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,58 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 starfivetech.com + * + * Authors: + * Minda Chen + */ + +#include +#include +#include +#include +#include +#include +#include + +extern struct fdt_i2c_adapter fdt_i2c_adapter_dw; + +static int fdt_dw_i2c_init(void *fdt, int nodeoff, + const struct fdt_match *match) +{ + int rc; + struct dw_i2c_adapter *adapter; + u64 addr; + + adapter = sbi_zalloc(sizeof(*adapter)); + if (!adapter) + return SBI_ENOMEM; + + rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &addr, NULL); + if (rc) { + sbi_free(adapter); + return rc; + } + + adapter->addr = addr; + adapter->adapter.driver = &fdt_i2c_adapter_dw; + + rc = dw_i2c_init(&adapter->adapter, nodeoff); + if (rc) { + sbi_free(adapter); + return rc; + } + + return 0; +} + +static const struct fdt_match fdt_dw_i2c_match[] = { + { .compatible = "snps,designware-i2c" }, + { .compatible = "starfive,jh7110-i2c" }, + { }, +}; + +struct fdt_i2c_adapter fdt_i2c_adapter_dw = { + .match_table = fdt_dw_i2c_match, + .init = fdt_dw_i2c_init, +}; diff -Nru opensbi-1.1/lib/utils/i2c/fdt_i2c_sifive.c opensbi-1.3/lib/utils/i2c/fdt_i2c_sifive.c --- opensbi-1.1/lib/utils/i2c/fdt_i2c_sifive.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/i2c/fdt_i2c_sifive.c 2023-06-23 07:31:49.000000000 +0200 @@ -9,12 +9,11 @@ #include #include +#include #include #include #include -#define SIFIVE_I2C_ADAPTER_MAX 2 - #define SIFIVE_I2C_PRELO 0x00 #define SIFIVE_I2C_PREHI 0x04 #define SIFIVE_I2C_CTR 0x08 @@ -47,10 +46,6 @@ struct i2c_adapter adapter; }; -static unsigned int sifive_i2c_adapter_count; -static struct sifive_i2c_adapter - sifive_i2c_adapter_array[SIFIVE_I2C_ADAPTER_MAX]; - extern struct fdt_i2c_adapter fdt_i2c_adapter_sifive; static inline void sifive_i2c_setreg(struct sifive_i2c_adapter *adap, @@ -244,14 +239,15 @@ struct sifive_i2c_adapter *adapter; uint64_t addr; - if (sifive_i2c_adapter_count >= SIFIVE_I2C_ADAPTER_MAX) - return SBI_ENOSPC; - - adapter = &sifive_i2c_adapter_array[sifive_i2c_adapter_count]; + adapter = sbi_zalloc(sizeof(*adapter)); + if (!adapter) + return SBI_ENOMEM; rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &addr, NULL); - if (rc) + if (rc) { + sbi_free(adapter); return rc; + } adapter->addr = addr; adapter->adapter.driver = &fdt_i2c_adapter_sifive; @@ -259,10 +255,11 @@ adapter->adapter.write = sifive_i2c_adapter_write; adapter->adapter.read = sifive_i2c_adapter_read; rc = i2c_adapter_add(&adapter->adapter); - if (rc) + if (rc) { + sbi_free(adapter); return rc; + } - sifive_i2c_adapter_count++; return 0; } diff -Nru opensbi-1.1/lib/utils/i2c/Kconfig opensbi-1.3/lib/utils/i2c/Kconfig --- opensbi-1.1/lib/utils/i2c/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/i2c/Kconfig 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: BSD-2-Clause + +menu "I2C Support" + +config FDT_I2C + bool "FDT based I2C drivers" + depends on FDT + select I2C + default n + +if FDT_I2C + +config FDT_I2C_SIFIVE + bool "SiFive I2C FDT driver" + default n + +config FDT_I2C_DW + bool "Synopsys Designware I2C FDT driver" + select I2C_DW + default n +endif + +config I2C_DW + bool "Synopsys Designware I2C support" + default n + +config I2C + bool "I2C support" + default n + +endmenu diff -Nru opensbi-1.1/lib/utils/i2c/objects.mk opensbi-1.3/lib/utils/i2c/objects.mk --- opensbi-1.1/lib/utils/i2c/objects.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/i2c/objects.mk 2023-06-23 07:31:49.000000000 +0200 @@ -7,10 +7,15 @@ # Nikita Shubin # -libsbiutils-objs-y += i2c/i2c.o +libsbiutils-objs-$(CONFIG_I2C) += i2c/i2c.o -libsbiutils-objs-y += i2c/fdt_i2c.o -libsbiutils-objs-y += i2c/fdt_i2c_adapter_drivers.o +libsbiutils-objs-$(CONFIG_FDT_I2C) += i2c/fdt_i2c.o +libsbiutils-objs-$(CONFIG_FDT_I2C) += i2c/fdt_i2c_adapter_drivers.o -carray-fdt_i2c_adapter_drivers-y += fdt_i2c_adapter_sifive -libsbiutils-objs-y += i2c/fdt_i2c_sifive.o +carray-fdt_i2c_adapter_drivers-$(CONFIG_FDT_I2C_SIFIVE) += fdt_i2c_adapter_sifive +libsbiutils-objs-$(CONFIG_FDT_I2C_SIFIVE) += i2c/fdt_i2c_sifive.o + +carray-fdt_i2c_adapter_drivers-$(CONFIG_FDT_I2C_DW) += fdt_i2c_adapter_dw +libsbiutils-objs-$(CONFIG_FDT_I2C_DW) += i2c/fdt_i2c_dw.o + +libsbiutils-objs-$(CONFIG_I2C_DW) += i2c/dw_i2c.o diff -Nru opensbi-1.1/lib/utils/ipi/aclint_mswi.c opensbi-1.3/lib/utils/ipi/aclint_mswi.c --- opensbi-1.1/lib/utils/ipi/aclint_mswi.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/ipi/aclint_mswi.c 2023-06-23 07:31:49.000000000 +0200 @@ -12,21 +12,30 @@ #include #include #include -#include #include +#include #include #include -static struct aclint_mswi_data *mswi_hartid2data[SBI_HARTMASK_MAX_BITS]; +static unsigned long mswi_ptr_offset; + +#define mswi_get_hart_data_ptr(__scratch) \ + sbi_scratch_read_type((__scratch), void *, mswi_ptr_offset) + +#define mswi_set_hart_data_ptr(__scratch, __mswi) \ + sbi_scratch_write_type((__scratch), void *, mswi_ptr_offset, (__mswi)) static void mswi_ipi_send(u32 target_hart) { u32 *msip; + struct sbi_scratch *scratch; struct aclint_mswi_data *mswi; - if (SBI_HARTMASK_MAX_BITS <= target_hart) + scratch = sbi_hartid_to_scratch(target_hart); + if (!scratch) return; - mswi = mswi_hartid2data[target_hart]; + + mswi = mswi_get_hart_data_ptr(scratch); if (!mswi) return; @@ -38,11 +47,14 @@ static void mswi_ipi_clear(u32 target_hart) { u32 *msip; + struct sbi_scratch *scratch; struct aclint_mswi_data *mswi; - if (SBI_HARTMASK_MAX_BITS <= target_hart) + scratch = sbi_hartid_to_scratch(target_hart); + if (!scratch) return; - mswi = mswi_hartid2data[target_hart]; + + mswi = mswi_get_hart_data_ptr(scratch); if (!mswi) return; @@ -69,26 +81,40 @@ { u32 i; int rc; + struct sbi_scratch *scratch; unsigned long pos, region_size; struct sbi_domain_memregion reg; /* Sanity checks */ if (!mswi || (mswi->addr & (ACLINT_MSWI_ALIGN - 1)) || (mswi->size < (mswi->hart_count * sizeof(u32))) || - (mswi->first_hartid >= SBI_HARTMASK_MAX_BITS) || - (mswi->hart_count > ACLINT_MSWI_MAX_HARTS)) + (!mswi->hart_count || mswi->hart_count > ACLINT_MSWI_MAX_HARTS)) return SBI_EINVAL; - /* Update MSWI hartid table */ - for (i = 0; i < mswi->hart_count; i++) - mswi_hartid2data[mswi->first_hartid + i] = mswi; + /* Allocate scratch space pointer */ + if (!mswi_ptr_offset) { + mswi_ptr_offset = sbi_scratch_alloc_type_offset(void *); + if (!mswi_ptr_offset) + return SBI_ENOMEM; + } + + /* Update MSWI pointer in scratch space */ + for (i = 0; i < mswi->hart_count; i++) { + scratch = sbi_hartid_to_scratch(mswi->first_hartid + i); + if (!scratch) + return SBI_ENOENT; + mswi_set_hart_data_ptr(scratch, mswi); + } /* Add MSWI regions to the root domain */ for (pos = 0; pos < mswi->size; pos += ACLINT_MSWI_ALIGN) { region_size = ((mswi->size - pos) < ACLINT_MSWI_ALIGN) ? (mswi->size - pos) : ACLINT_MSWI_ALIGN; sbi_domain_memregion_init(mswi->addr + pos, region_size, - SBI_DOMAIN_MEMREGION_MMIO, ®); + (SBI_DOMAIN_MEMREGION_MMIO | + SBI_DOMAIN_MEMREGION_M_READABLE | + SBI_DOMAIN_MEMREGION_M_WRITABLE), + ®); rc = sbi_domain_root_add_memregion(®); if (rc) return rc; diff -Nru opensbi-1.1/lib/utils/ipi/andes_plicsw.c opensbi-1.3/lib/utils/ipi/andes_plicsw.c --- opensbi-1.1/lib/utils/ipi/andes_plicsw.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/ipi/andes_plicsw.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,137 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Andes Technology Corporation + * + * Authors: + * Zong Li + * Nylon Chen + * Leo Yu-Chi Liang + * Yu Chien Peter Lin + */ + +#include +#include +#include +#include +#include + +struct plicsw_data plicsw; + +static inline void plicsw_claim(void) +{ + u32 hartid = current_hartid(); + + if (plicsw.hart_count <= hartid) + ebreak(); + + plicsw.source_id[hartid] = + readl((void *)plicsw.addr + PLICSW_CONTEXT_BASE + + PLICSW_CONTEXT_CLAIM + PLICSW_CONTEXT_STRIDE * hartid); +} + +static inline void plicsw_complete(void) +{ + u32 hartid = current_hartid(); + u32 source = plicsw.source_id[hartid]; + + writel(source, (void *)plicsw.addr + PLICSW_CONTEXT_BASE + + PLICSW_CONTEXT_CLAIM + + PLICSW_CONTEXT_STRIDE * hartid); +} + +static inline void plic_sw_pending(u32 target_hart) +{ + /* + * The pending array registers are w1s type. + * IPI pending array mapping as following: + * + * Pending array start address: base + 0x1000 + * --------------------------------- + * | hart3 | hart2 | hart1 | hart0 | + * --------------------------------- + * Each hartX can send IPI to another hart by setting the + * bitY to its own region (see the below). + * + * In each hartX region: + * <---------- PICSW_PENDING_STRIDE --------> + * | bit7 | ... | bit3 | bit2 | bit1 | bit0 | + * ------------------------------------------ + * The bitY of hartX region indicates that hartX sends an + * IPI to hartY. + */ + u32 hartid = current_hartid(); + u32 word_index = hartid / 4; + u32 per_hart_offset = PLICSW_PENDING_STRIDE * hartid; + u32 val = 1 << target_hart << per_hart_offset; + + writel(val, (void *)plicsw.addr + PLICSW_PENDING_BASE + word_index * 4); +} + +static void plicsw_ipi_send(u32 target_hart) +{ + if (plicsw.hart_count <= target_hart) + ebreak(); + + /* Set PLICSW IPI */ + plic_sw_pending(target_hart); +} + +static void plicsw_ipi_clear(u32 target_hart) +{ + if (plicsw.hart_count <= target_hart) + ebreak(); + + /* Clear PLICSW IPI */ + plicsw_claim(); + plicsw_complete(); +} + +static struct sbi_ipi_device plicsw_ipi = { + .name = "andes_plicsw", + .ipi_send = plicsw_ipi_send, + .ipi_clear = plicsw_ipi_clear +}; + +int plicsw_warm_ipi_init(void) +{ + u32 hartid = current_hartid(); + + /* Clear PLICSW IPI */ + plicsw_ipi_clear(hartid); + + return 0; +} + +int plicsw_cold_ipi_init(struct plicsw_data *plicsw) +{ + int rc; + + /* Setup source priority */ + uint32_t *priority = (void *)plicsw->addr + PLICSW_PRIORITY_BASE; + + for (int i = 0; i < plicsw->hart_count; i++) + writel(1, &priority[i]); + + /* Setup target enable */ + uint32_t enable_mask = PLICSW_HART_MASK; + + for (int i = 0; i < plicsw->hart_count; i++) { + uint32_t *enable = (void *)plicsw->addr + PLICSW_ENABLE_BASE + + PLICSW_ENABLE_STRIDE * i; + writel(enable_mask, enable); + writel(enable_mask, enable + 1); + enable_mask <<= 1; + } + + /* Add PLICSW region to the root domain */ + rc = sbi_domain_root_add_memrange(plicsw->addr, plicsw->size, + PLICSW_REGION_ALIGN, + SBI_DOMAIN_MEMREGION_MMIO); + if (rc) + return rc; + + sbi_ipi_set_device(&plicsw_ipi); + + return 0; +} diff -Nru opensbi-1.1/lib/utils/ipi/fdt_ipi.c opensbi-1.3/lib/utils/ipi/fdt_ipi.c --- opensbi-1.1/lib/utils/ipi/fdt_ipi.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/ipi/fdt_ipi.c 2023-06-23 07:31:49.000000000 +0200 @@ -16,24 +16,17 @@ extern struct fdt_ipi *fdt_ipi_drivers[]; extern unsigned long fdt_ipi_drivers_size; -static struct fdt_ipi dummy = { - .match_table = NULL, - .cold_init = NULL, - .warm_init = NULL, - .exit = NULL, -}; - -static struct fdt_ipi *current_driver = &dummy; +static struct fdt_ipi *current_driver = NULL; void fdt_ipi_exit(void) { - if (current_driver->exit) + if (current_driver && current_driver->exit) current_driver->exit(); } static int fdt_ipi_warm_init(void) { - if (current_driver->warm_init) + if (current_driver && current_driver->warm_init) return current_driver->warm_init(); return 0; } @@ -51,20 +44,28 @@ noff = -1; while ((noff = fdt_find_match(fdt, noff, drv->match_table, &match)) >= 0) { - if (drv->cold_init) { - rc = drv->cold_init(fdt, noff, match); - if (rc == SBI_ENODEV) - continue; - if (rc) - return rc; - } + /* drv->cold_init must not be NULL */ + if (drv->cold_init == NULL) + return SBI_EFAIL; + + rc = drv->cold_init(fdt, noff, match); + if (rc == SBI_ENODEV) + continue; + if (rc) + return rc; current_driver = drv; - } - if (current_driver != &dummy) - break; + /* + * We will have multiple IPI devices on multi-die or + * multi-socket systems so we cannot break here. + */ + } } + /* + * On some single-hart system there is no need for ipi, + * so we cannot return a failure here + */ return 0; } diff -Nru opensbi-1.1/lib/utils/ipi/fdt_ipi_mswi.c opensbi-1.3/lib/utils/ipi/fdt_ipi_mswi.c --- opensbi-1.1/lib/utils/ipi/fdt_ipi_mswi.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/ipi/fdt_ipi_mswi.c 2023-06-23 07:31:49.000000000 +0200 @@ -8,15 +8,11 @@ */ #include +#include #include #include #include -#define MSWI_MAX_NR 16 - -static unsigned long mswi_count = 0; -static struct aclint_mswi_data mswi[MSWI_MAX_NR]; - static int ipi_mswi_cold_init(void *fdt, int nodeoff, const struct fdt_match *match) { @@ -24,15 +20,17 @@ unsigned long offset; struct aclint_mswi_data *ms; - if (MSWI_MAX_NR <= mswi_count) - return SBI_ENOSPC; - ms = &mswi[mswi_count]; + ms = sbi_zalloc(sizeof(*ms)); + if (!ms) + return SBI_ENOMEM; rc = fdt_parse_aclint_node(fdt, nodeoff, false, &ms->addr, &ms->size, NULL, NULL, &ms->first_hartid, &ms->hart_count); - if (rc) + if (rc) { + sbi_free(ms); return rc; + } if (match->data) { /* Adjust MSWI address and size for CLINT device */ @@ -44,10 +42,11 @@ } rc = aclint_mswi_cold_init(ms); - if (rc) + if (rc) { + sbi_free(ms); return rc; + } - mswi_count++; return 0; } @@ -56,6 +55,7 @@ static const struct fdt_match ipi_mswi_match[] = { { .compatible = "riscv,clint0", .data = &clint_offset }, { .compatible = "sifive,clint0", .data = &clint_offset }, + { .compatible = "thead,c900-clint", .data = &clint_offset }, { .compatible = "riscv,aclint-mswi" }, { }, }; diff -Nru opensbi-1.1/lib/utils/ipi/fdt_ipi_plicsw.c opensbi-1.3/lib/utils/ipi/fdt_ipi_plicsw.c --- opensbi-1.1/lib/utils/ipi/fdt_ipi_plicsw.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/ipi/fdt_ipi_plicsw.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,47 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Andes Technology Corporation + * + * Authors: + * Zong Li + * Nylon Chen + * Leo Yu-Chi Liang + * Yu Chien Peter Lin + */ + +#include +#include +#include +#include + +extern struct plicsw_data plicsw; + +int fdt_plicsw_cold_ipi_init(void *fdt, int nodeoff, + const struct fdt_match *match) +{ + int rc; + + rc = fdt_parse_plicsw_node(fdt, nodeoff, &plicsw.addr, &plicsw.size, + &plicsw.hart_count); + if (rc) + return rc; + + rc = plicsw_cold_ipi_init(&plicsw); + if (rc) + return rc; + + return 0; +} + +static const struct fdt_match ipi_plicsw_match[] = { + { .compatible = "andestech,plicsw" }, + {}, +}; + +struct fdt_ipi fdt_ipi_plicsw = { + .match_table = ipi_plicsw_match, + .cold_init = fdt_plicsw_cold_ipi_init, + .warm_init = plicsw_warm_ipi_init, + .exit = NULL, +}; diff -Nru opensbi-1.1/lib/utils/ipi/Kconfig opensbi-1.3/lib/utils/ipi/Kconfig --- opensbi-1.1/lib/utils/ipi/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/ipi/Kconfig 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: BSD-2-Clause + +menu "IPI Device Support" + +config FDT_IPI + bool "FDT based ipi drivers" + depends on FDT + default n + +if FDT_IPI + +config FDT_IPI_MSWI + bool "ACLINT MSWI FDT driver" + select IPI_MSWI + default n + +config FDT_IPI_PLICSW + bool "Andes PLICSW FDT driver" + select IPI_PLICSW + default n + +endif + +config IPI_MSWI + bool "ACLINT MSWI support" + default n + +config IPI_PLICSW + bool "Andes PLICSW support" + default n + +endmenu diff -Nru opensbi-1.1/lib/utils/ipi/objects.mk opensbi-1.3/lib/utils/ipi/objects.mk --- opensbi-1.1/lib/utils/ipi/objects.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/ipi/objects.mk 2023-06-23 07:31:49.000000000 +0200 @@ -7,10 +7,14 @@ # Anup Patel # -libsbiutils-objs-y += ipi/aclint_mswi.o +libsbiutils-objs-$(CONFIG_IPI_MSWI) += ipi/aclint_mswi.o +libsbiutils-objs-$(CONFIG_IPI_PLICSW) += ipi/andes_plicsw.o -libsbiutils-objs-y += ipi/fdt_ipi.o -libsbiutils-objs-y += ipi/fdt_ipi_drivers.o +libsbiutils-objs-$(CONFIG_FDT_IPI) += ipi/fdt_ipi.o +libsbiutils-objs-$(CONFIG_FDT_IPI) += ipi/fdt_ipi_drivers.o -carray-fdt_ipi_drivers-y += fdt_ipi_mswi -libsbiutils-objs-y += ipi/fdt_ipi_mswi.o +carray-fdt_ipi_drivers-$(CONFIG_FDT_IPI_MSWI) += fdt_ipi_mswi +libsbiutils-objs-$(CONFIG_FDT_IPI_MSWI) += ipi/fdt_ipi_mswi.o + +carray-fdt_ipi_drivers-$(CONFIG_FDT_IPI_PLICSW) += fdt_ipi_plicsw +libsbiutils-objs-$(CONFIG_FDT_IPI_PLICSW) += ipi/fdt_ipi_plicsw.o diff -Nru opensbi-1.1/lib/utils/irqchip/aplic.c opensbi-1.3/lib/utils/irqchip/aplic.c --- opensbi-1.1/lib/utils/irqchip/aplic.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/irqchip/aplic.c 2023-06-23 07:31:49.000000000 +0200 @@ -269,7 +269,10 @@ (last_deleg_irq == aplic->num_source) && (first_deleg_irq == 1))) { sbi_domain_memregion_init(aplic->addr, aplic->size, - SBI_DOMAIN_MEMREGION_MMIO, ®); + (SBI_DOMAIN_MEMREGION_MMIO | + SBI_DOMAIN_MEMREGION_M_READABLE | + SBI_DOMAIN_MEMREGION_M_WRITABLE), + ®); rc = sbi_domain_root_add_memregion(®); if (rc) return rc; diff -Nru opensbi-1.1/lib/utils/irqchip/fdt_irqchip_aplic.c opensbi-1.3/lib/utils/irqchip/fdt_irqchip_aplic.c --- opensbi-1.1/lib/utils/irqchip/fdt_irqchip_aplic.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/irqchip/fdt_irqchip_aplic.c 2023-06-23 07:31:49.000000000 +0200 @@ -11,15 +11,11 @@ #include #include #include +#include #include #include #include -#define APLIC_MAX_NR 16 - -static unsigned long aplic_count = 0; -static struct aplic_data aplic[APLIC_MAX_NR]; - static int irqchip_aplic_warm_init(void) { /* Nothing to do here. */ @@ -32,15 +28,23 @@ int rc; struct aplic_data *pd; - if (APLIC_MAX_NR <= aplic_count) - return SBI_ENOSPC; - pd = &aplic[aplic_count++]; + pd = sbi_zalloc(sizeof(*pd)); + if (!pd) + return SBI_ENOMEM; rc = fdt_parse_aplic_node(fdt, nodeoff, pd); if (rc) - return rc; + goto fail_free_data; + + rc = aplic_cold_irqchip_init(pd); + if (rc) + goto fail_free_data; + + return 0; - return aplic_cold_irqchip_init(pd); +fail_free_data: + sbi_free(pd); + return rc; } static const struct fdt_match irqchip_aplic_match[] = { diff -Nru opensbi-1.1/lib/utils/irqchip/fdt_irqchip_imsic.c opensbi-1.3/lib/utils/irqchip/fdt_irqchip_imsic.c --- opensbi-1.1/lib/utils/irqchip/fdt_irqchip_imsic.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/irqchip/fdt_irqchip_imsic.c 2023-06-23 07:31:49.000000000 +0200 @@ -11,16 +11,11 @@ #include #include #include -#include +#include #include #include #include -#define IMSIC_MAX_NR 16 - -static unsigned long imsic_count = 0; -static struct imsic_data imsic[IMSIC_MAX_NR]; - static int irqchip_imsic_update_hartid_table(void *fdt, int nodeoff, struct imsic_data *id) { @@ -48,8 +43,6 @@ err = fdt_parse_hart_id(fdt, cpu_offset, &hartid); if (err) return SBI_EINVAL; - if (SBI_HARTMASK_MAX_BITS <= hartid) - return SBI_EINVAL; switch (hwirq) { case IRQ_M_EXT: @@ -71,27 +64,27 @@ int rc; struct imsic_data *id; - if (IMSIC_MAX_NR <= imsic_count) - return SBI_ENOSPC; - id = &imsic[imsic_count]; + id = sbi_zalloc(sizeof(*id)); + if (!id) + return SBI_ENOMEM; rc = fdt_parse_imsic_node(fdt, nodeoff, id); - if (rc) - return rc; - if (!id->targets_mmode) - return 0; - - rc = irqchip_imsic_update_hartid_table(fdt, nodeoff, id); - if (rc) - return rc; + if (rc || !id->targets_mmode) + goto fail_free_data; rc = imsic_cold_irqchip_init(id); if (rc) - return rc; + goto fail_free_data; - imsic_count++; + rc = irqchip_imsic_update_hartid_table(fdt, nodeoff, id); + if (rc) + goto fail_free_data; return 0; + +fail_free_data: + sbi_free(id); + return rc; } static const struct fdt_match irqchip_imsic_match[] = { diff -Nru opensbi-1.1/lib/utils/irqchip/fdt_irqchip_plic.c opensbi-1.3/lib/utils/irqchip/fdt_irqchip_plic.c --- opensbi-1.1/lib/utils/irqchip/fdt_irqchip_plic.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/irqchip/fdt_irqchip_plic.c 2023-06-23 07:31:49.000000000 +0200 @@ -11,58 +11,78 @@ #include #include #include -#include +#include +#include #include #include #include -#define PLIC_MAX_NR 16 +static unsigned long plic_ptr_offset; -static unsigned long plic_count = 0; -static struct plic_data plic[PLIC_MAX_NR]; +#define plic_get_hart_data_ptr(__scratch) \ + sbi_scratch_read_type((__scratch), void *, plic_ptr_offset) -static struct plic_data *plic_hartid2data[SBI_HARTMASK_MAX_BITS]; -static int plic_hartid2context[SBI_HARTMASK_MAX_BITS][2]; +#define plic_set_hart_data_ptr(__scratch, __plic) \ + sbi_scratch_write_type((__scratch), void *, plic_ptr_offset, (__plic)) -void fdt_plic_priority_save(u8 *priority) +static unsigned long plic_mcontext_offset; + +#define plic_get_hart_mcontext(__scratch) \ + (sbi_scratch_read_type((__scratch), long, plic_mcontext_offset) - 1) + +#define plic_set_hart_mcontext(__scratch, __mctx) \ + sbi_scratch_write_type((__scratch), long, plic_mcontext_offset, (__mctx) + 1) + +static unsigned long plic_scontext_offset; + +#define plic_get_hart_scontext(__scratch) \ + (sbi_scratch_read_type((__scratch), long, plic_scontext_offset) - 1) + +#define plic_set_hart_scontext(__scratch, __sctx) \ + sbi_scratch_write_type((__scratch), long, plic_scontext_offset, (__sctx) + 1) + +void fdt_plic_priority_save(u8 *priority, u32 num) { - struct plic_data *plic = plic_hartid2data[current_hartid()]; + struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); - plic_priority_save(plic, priority); + plic_priority_save(plic_get_hart_data_ptr(scratch), priority, num); } -void fdt_plic_priority_restore(const u8 *priority) +void fdt_plic_priority_restore(const u8 *priority, u32 num) { - struct plic_data *plic = plic_hartid2data[current_hartid()]; + struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); - plic_priority_restore(plic, priority); + plic_priority_restore(plic_get_hart_data_ptr(scratch), priority, num); } -void fdt_plic_context_save(bool smode, u32 *enable, u32 *threshold) +void fdt_plic_context_save(bool smode, u32 *enable, u32 *threshold, u32 num) { - u32 hartid = current_hartid(); + struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); - plic_context_save(plic_hartid2data[hartid], - plic_hartid2context[hartid][smode], - enable, threshold); + plic_context_save(plic_get_hart_data_ptr(scratch), + smode ? plic_get_hart_scontext(scratch) : + plic_get_hart_mcontext(scratch), + enable, threshold, num); } -void fdt_plic_context_restore(bool smode, const u32 *enable, u32 threshold) +void fdt_plic_context_restore(bool smode, const u32 *enable, u32 threshold, + u32 num) { - u32 hartid = current_hartid(); + struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); - plic_context_restore(plic_hartid2data[hartid], - plic_hartid2context[hartid][smode], - enable, threshold); + plic_context_restore(plic_get_hart_data_ptr(scratch), + smode ? plic_get_hart_scontext(scratch) : + plic_get_hart_mcontext(scratch), + enable, threshold, num); } static int irqchip_plic_warm_init(void) { - u32 hartid = current_hartid(); + struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); - return plic_warm_irqchip_init(plic_hartid2data[hartid], - plic_hartid2context[hartid][0], - plic_hartid2context[hartid][1]); + return plic_warm_irqchip_init(plic_get_hart_data_ptr(scratch), + plic_get_hart_mcontext(scratch), + plic_get_hart_scontext(scratch)); } static int irqchip_plic_update_hartid_table(void *fdt, int nodeoff, @@ -70,6 +90,7 @@ { const fdt32_t *val; u32 phandle, hwirq, hartid; + struct sbi_scratch *scratch; int i, err, count, cpu_offset, cpu_intc_offset; val = fdt_getprop(fdt, nodeoff, "interrupts-extended", &count); @@ -86,23 +107,24 @@ continue; cpu_offset = fdt_parent_offset(fdt, cpu_intc_offset); - if (cpu_intc_offset < 0) + if (cpu_offset < 0) continue; err = fdt_parse_hart_id(fdt, cpu_offset, &hartid); if (err) continue; - if (SBI_HARTMASK_MAX_BITS <= hartid) + scratch = sbi_hartid_to_scratch(hartid); + if (!scratch) continue; - plic_hartid2data[hartid] = pd; + plic_set_hart_data_ptr(scratch, pd); switch (hwirq) { case IRQ_M_EXT: - plic_hartid2context[hartid][0] = i / 2; + plic_set_hart_mcontext(scratch, i / 2); break; case IRQ_S_EXT: - plic_hartid2context[hartid][1] = i / 2; + plic_set_hart_scontext(scratch, i / 2); break; } } @@ -113,16 +135,34 @@ static int irqchip_plic_cold_init(void *fdt, int nodeoff, const struct fdt_match *match) { - int i, rc; + int rc; struct plic_data *pd; - if (PLIC_MAX_NR <= plic_count) - return SBI_ENOSPC; - pd = &plic[plic_count++]; + if (!plic_ptr_offset) { + plic_ptr_offset = sbi_scratch_alloc_type_offset(void *); + if (!plic_ptr_offset) + return SBI_ENOMEM; + } + + if (!plic_mcontext_offset) { + plic_mcontext_offset = sbi_scratch_alloc_type_offset(long); + if (!plic_mcontext_offset) + return SBI_ENOMEM; + } + + if (!plic_scontext_offset) { + plic_scontext_offset = sbi_scratch_alloc_type_offset(long); + if (!plic_scontext_offset) + return SBI_ENOMEM; + } + + pd = sbi_zalloc(sizeof(*pd)); + if (!pd) + return SBI_ENOMEM; rc = fdt_parse_plic_node(fdt, nodeoff, pd); if (rc) - return rc; + goto fail_free_data; if (match->data) { void (*plic_plat_init)(struct plic_data *) = match->data; @@ -131,17 +171,17 @@ rc = plic_cold_irqchip_init(pd); if (rc) - return rc; + goto fail_free_data; - if (plic_count == 1) { - for (i = 0; i < SBI_HARTMASK_MAX_BITS; i++) { - plic_hartid2data[i] = NULL; - plic_hartid2context[i][0] = -1; - plic_hartid2context[i][1] = -1; - } - } + rc = irqchip_plic_update_hartid_table(fdt, nodeoff, pd); + if (rc) + goto fail_free_data; + + return 0; - return irqchip_plic_update_hartid_table(fdt, nodeoff, pd); +fail_free_data: + sbi_free(pd); + return rc; } #define THEAD_PLIC_CTRL_REG 0x1ffffc @@ -153,17 +193,19 @@ void thead_plic_restore(void) { - struct plic_data *plic = plic_hartid2data[current_hartid()]; + struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); + struct plic_data *plic = plic_get_hart_data_ptr(scratch); thead_plic_plat_init(plic); } static const struct fdt_match irqchip_plic_match[] = { + { .compatible = "andestech,nceplic100" }, { .compatible = "riscv,plic0" }, { .compatible = "sifive,plic-1.0.0" }, { .compatible = "thead,c900-plic", .data = thead_plic_plat_init }, - { }, + { /* sentinel */ } }; struct fdt_irqchip fdt_irqchip_plic = { diff -Nru opensbi-1.1/lib/utils/irqchip/imsic.c opensbi-1.3/lib/utils/irqchip/imsic.c --- opensbi-1.1/lib/utils/irqchip/imsic.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/irqchip/imsic.c 2023-06-23 07:31:49.000000000 +0200 @@ -13,10 +13,10 @@ #include #include #include -#include #include #include #include +#include #include #define IMSIC_MMIO_PAGE_LE 0x00 @@ -79,33 +79,65 @@ csr_clear(CSR_MIREG, __v); \ } while (0) -static struct imsic_data *imsic_hartid2data[SBI_HARTMASK_MAX_BITS]; -static int imsic_hartid2file[SBI_HARTMASK_MAX_BITS]; +static unsigned long imsic_ptr_offset; + +#define imsic_get_hart_data_ptr(__scratch) \ + sbi_scratch_read_type((__scratch), void *, imsic_ptr_offset) + +#define imsic_set_hart_data_ptr(__scratch, __imsic) \ + sbi_scratch_write_type((__scratch), void *, imsic_ptr_offset, (__imsic)) + +static unsigned long imsic_file_offset; + +#define imsic_get_hart_file(__scratch) \ + sbi_scratch_read_type((__scratch), long, imsic_file_offset) + +#define imsic_set_hart_file(__scratch, __file) \ + sbi_scratch_write_type((__scratch), long, imsic_file_offset, (__file)) int imsic_map_hartid_to_data(u32 hartid, struct imsic_data *imsic, int file) { - if (!imsic || !imsic->targets_mmode || - (SBI_HARTMASK_MAX_BITS <= hartid)) + struct sbi_scratch *scratch; + + if (!imsic || !imsic->targets_mmode) return SBI_EINVAL; - imsic_hartid2data[hartid] = imsic; - imsic_hartid2file[hartid] = file; + /* + * We don't need to fail if scratch pointer is not available + * because we might be dealing with hartid of a HART disabled + * in device tree. For HARTs disabled in device tree, the + * imsic_get_data() and imsic_get_target_file() will anyway + * fail. + */ + scratch = sbi_hartid_to_scratch(hartid); + if (!scratch) + return 0; + + imsic_set_hart_data_ptr(scratch, imsic); + imsic_set_hart_file(scratch, file); return 0; } struct imsic_data *imsic_get_data(u32 hartid) { - if (SBI_HARTMASK_MAX_BITS <= hartid) + struct sbi_scratch *scratch; + + scratch = sbi_hartid_to_scratch(hartid); + if (!scratch) return NULL; - return imsic_hartid2data[hartid]; + + return imsic_get_hart_data_ptr(scratch); } int imsic_get_target_file(u32 hartid) { - if ((SBI_HARTMASK_MAX_BITS <= hartid) || - !imsic_hartid2data[hartid]) + struct sbi_scratch *scratch; + + scratch = sbi_hartid_to_scratch(hartid); + if (!scratch) return SBI_ENOENT; - return imsic_hartid2file[hartid]; + + return imsic_get_hart_file(scratch); } static int imsic_external_irqfn(struct sbi_trap_regs *regs) @@ -133,9 +165,16 @@ { unsigned long reloff; struct imsic_regs *regs; - struct imsic_data *data = imsic_hartid2data[target_hart]; - int file = imsic_hartid2file[target_hart]; + struct imsic_data *data; + struct sbi_scratch *scratch; + int file; + + scratch = sbi_hartid_to_scratch(target_hart); + if (!scratch) + return; + data = imsic_get_hart_data_ptr(scratch); + file = imsic_get_hart_file(scratch); if (!data || !data->targets_mmode) return; @@ -204,7 +243,7 @@ int imsic_warm_irqchip_init(void) { - struct imsic_data *imsic = imsic_hartid2data[current_hartid()]; + struct imsic_data *imsic = imsic_get_data(current_hartid()); /* Sanity checks */ if (!imsic || !imsic->targets_mmode) @@ -306,6 +345,20 @@ if (!imsic->targets_mmode) return SBI_EINVAL; + /* Allocate scratch space pointer */ + if (!imsic_ptr_offset) { + imsic_ptr_offset = sbi_scratch_alloc_type_offset(void *); + if (!imsic_ptr_offset) + return SBI_ENOMEM; + } + + /* Allocate scratch space file */ + if (!imsic_file_offset) { + imsic_file_offset = sbi_scratch_alloc_type_offset(long); + if (!imsic_file_offset) + return SBI_ENOMEM; + } + /* Setup external interrupt function for IMSIC */ sbi_irqchip_set_irqfn(imsic_external_irqfn); @@ -313,7 +366,10 @@ for (i = 0; i < IMSIC_MAX_REGS && imsic->regs[i].size; i++) { sbi_domain_memregion_init(imsic->regs[i].addr, imsic->regs[i].size, - SBI_DOMAIN_MEMREGION_MMIO, ®); + (SBI_DOMAIN_MEMREGION_MMIO | + SBI_DOMAIN_MEMREGION_M_READABLE | + SBI_DOMAIN_MEMREGION_M_WRITABLE), + ®); rc = sbi_domain_root_add_memregion(®); if (rc) return rc; diff -Nru opensbi-1.1/lib/utils/irqchip/Kconfig opensbi-1.3/lib/utils/irqchip/Kconfig --- opensbi-1.1/lib/utils/irqchip/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/irqchip/Kconfig 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: BSD-2-Clause + +menu "Interrupt Controller Support" + +config FDT_IRQCHIP + bool "FDT based interrupt controller drivers" + depends on FDT + default n + +if FDT_IRQCHIP + +config FDT_IRQCHIP_APLIC + bool "Advanced Platform Level Interrupt Controller (APLIC) FDT driver" + select IRQCHIP_APLIC + default n + +config FDT_IRQCHIP_IMSIC + bool "Incoming Message Signalled Interrupt Controller (IMSIC) FDT driver" + select IRQCHIP_IMSIC + default n + +config FDT_IRQCHIP_PLIC + bool "Platform Level Interrupt Controller (PLIC) FDT driver" + select IRQCHIP_PLIC + default n + +endif + +config IRQCHIP_APLIC + bool "Advanced Platform Level Interrupt Controller (APLIC) support" + default n + +config IRQCHIP_IMSIC + bool "Incoming Message Signalled Interrupt Controller (IMSIC) support" + default n + +config IRQCHIP_PLIC + bool "Platform Level Interrupt Controller (PLIC) support" + default n + +endmenu diff -Nru opensbi-1.1/lib/utils/irqchip/objects.mk opensbi-1.3/lib/utils/irqchip/objects.mk --- opensbi-1.1/lib/utils/irqchip/objects.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/irqchip/objects.mk 2023-06-23 07:31:49.000000000 +0200 @@ -7,18 +7,18 @@ # Anup Patel # -libsbiutils-objs-y += irqchip/fdt_irqchip.o -libsbiutils-objs-y += irqchip/fdt_irqchip_drivers.o +libsbiutils-objs-$(CONFIG_FDT_IRQCHIP) += irqchip/fdt_irqchip.o +libsbiutils-objs-$(CONFIG_FDT_IRQCHIP) += irqchip/fdt_irqchip_drivers.o -carray-fdt_irqchip_drivers-y += fdt_irqchip_aplic -libsbiutils-objs-y += irqchip/fdt_irqchip_aplic.o +carray-fdt_irqchip_drivers-$(CONFIG_FDT_IRQCHIP_APLIC) += fdt_irqchip_aplic +libsbiutils-objs-$(CONFIG_FDT_IRQCHIP_APLIC) += irqchip/fdt_irqchip_aplic.o -carray-fdt_irqchip_drivers-y += fdt_irqchip_imsic -libsbiutils-objs-y += irqchip/fdt_irqchip_imsic.o +carray-fdt_irqchip_drivers-$(CONFIG_FDT_IRQCHIP_IMSIC) += fdt_irqchip_imsic +libsbiutils-objs-$(CONFIG_FDT_IRQCHIP_IMSIC) += irqchip/fdt_irqchip_imsic.o -carray-fdt_irqchip_drivers-y += fdt_irqchip_plic -libsbiutils-objs-y += irqchip/fdt_irqchip_plic.o +carray-fdt_irqchip_drivers-$(CONFIG_FDT_IRQCHIP_PLIC) += fdt_irqchip_plic +libsbiutils-objs-$(CONFIG_FDT_IRQCHIP_PLIC) += irqchip/fdt_irqchip_plic.o -libsbiutils-objs-y += irqchip/aplic.o -libsbiutils-objs-y += irqchip/imsic.o -libsbiutils-objs-y += irqchip/plic.o +libsbiutils-objs-$(CONFIG_IRQCHIP_APLIC) += irqchip/aplic.o +libsbiutils-objs-$(CONFIG_IRQCHIP_IMSIC) += irqchip/imsic.o +libsbiutils-objs-$(CONFIG_IRQCHIP_PLIC) += irqchip/plic.o diff -Nru opensbi-1.1/lib/utils/irqchip/plic.c opensbi-1.3/lib/utils/irqchip/plic.c --- opensbi-1.1/lib/utils/irqchip/plic.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/irqchip/plic.c 2023-06-23 07:31:49.000000000 +0200 @@ -36,15 +36,16 @@ writel(val, plic_priority); } -void plic_priority_save(const struct plic_data *plic, u8 *priority) +void plic_priority_save(const struct plic_data *plic, u8 *priority, u32 num) { - for (u32 i = 0; i < plic->num_src; i++) + for (u32 i = 1; i <= num; i++) priority[i] = plic_get_priority(plic, i); } -void plic_priority_restore(const struct plic_data *plic, const u8 *priority) +void plic_priority_restore(const struct plic_data *plic, const u8 *priority, + u32 num) { - for (u32 i = 0; i < plic->num_src; i++) + for (u32 i = 1; i <= num; i++) plic_set_priority(plic, i, priority[i]); } @@ -91,22 +92,28 @@ } void plic_context_save(const struct plic_data *plic, int context_id, - u32 *enable, u32 *threshold) + u32 *enable, u32 *threshold, u32 num) { - u32 ie_words = (plic->num_src + 31) / 32; + u32 ie_words = plic->num_src / 32 + 1; - for (u32 i = 0; i < ie_words; i++) + if (num > ie_words) + num = ie_words; + + for (u32 i = 0; i < num; i++) enable[i] = plic_get_ie(plic, context_id, i); *threshold = plic_get_thresh(plic, context_id); } void plic_context_restore(const struct plic_data *plic, int context_id, - const u32 *enable, u32 threshold) + const u32 *enable, u32 threshold, u32 num) { - u32 ie_words = (plic->num_src + 31) / 32; + u32 ie_words = plic->num_src / 32 + 1; - for (u32 i = 0; i < ie_words; i++) + if (num > ie_words) + num = ie_words; + + for (u32 i = 0; i < num; i++) plic_set_ie(plic, context_id, i, enable[i]); plic_set_thresh(plic, context_id, threshold); @@ -120,7 +127,7 @@ if (!plic || context_id < 0) return SBI_EINVAL; - ie_words = (plic->num_src + 31) / 32; + ie_words = plic->num_src / 32 + 1; ie_value = enable ? 0xffffffffU : 0U; for (u32 i = 0; i < ie_words; i++) diff -Nru opensbi-1.1/lib/utils/Kconfig opensbi-1.3/lib/utils/Kconfig --- opensbi-1.1/lib/utils/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/Kconfig 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: BSD-2-Clause + +menu "Utils and Drivers Support" + +source "$(OPENSBI_SRC_DIR)/lib/utils/fdt/Kconfig" + +source "$(OPENSBI_SRC_DIR)/lib/utils/gpio/Kconfig" + +source "$(OPENSBI_SRC_DIR)/lib/utils/i2c/Kconfig" + +source "$(OPENSBI_SRC_DIR)/lib/utils/ipi/Kconfig" + +source "$(OPENSBI_SRC_DIR)/lib/utils/irqchip/Kconfig" + +source "$(OPENSBI_SRC_DIR)/lib/utils/libfdt/Kconfig" + +source "$(OPENSBI_SRC_DIR)/lib/utils/reset/Kconfig" + +source "$(OPENSBI_SRC_DIR)/lib/utils/serial/Kconfig" + +source "$(OPENSBI_SRC_DIR)/lib/utils/sys/Kconfig" + +source "$(OPENSBI_SRC_DIR)/lib/utils/timer/Kconfig" + +endmenu diff -Nru opensbi-1.1/lib/utils/libfdt/fdt_overlay.c opensbi-1.3/lib/utils/libfdt/fdt_overlay.c --- opensbi-1.1/lib/utils/libfdt/fdt_overlay.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/libfdt/fdt_overlay.c 2023-06-23 07:31:49.000000000 +0200 @@ -404,7 +404,7 @@ name, name_len, poffset, &phandle_prop, sizeof(phandle_prop)); -}; +} /** * overlay_fixup_phandle - Set an overlay phandle to the base one diff -Nru opensbi-1.1/lib/utils/libfdt/Kconfig opensbi-1.3/lib/utils/libfdt/Kconfig --- opensbi-1.1/lib/utils/libfdt/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/libfdt/Kconfig 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: BSD-2-Clause + +config LIBFDT + bool + default n diff -Nru opensbi-1.1/lib/utils/libfdt/libfdt_env.h opensbi-1.3/lib/utils/libfdt/libfdt_env.h --- opensbi-1.1/lib/utils/libfdt/libfdt_env.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/libfdt/libfdt_env.h 2023-06-23 07:31:49.000000000 +0200 @@ -9,6 +9,7 @@ #include #include +#include #define INT_MAX ((int)(~0U >> 1)) #define UINT_MAX ((unsigned int)~0U) @@ -37,49 +38,39 @@ #define strlen sbi_strlen #define strnlen sbi_strnlen -typedef uint16_t FDT_BITWISE fdt16_t; -typedef uint32_t FDT_BITWISE fdt32_t; -typedef uint64_t FDT_BITWISE fdt64_t; - -#define EXTRACT_BYTE(x, n) ((unsigned long long)((uint8_t *)&x)[n]) -#define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1)) -#define CPU_TO_FDT32(x) ((EXTRACT_BYTE(x, 0) << 24) | (EXTRACT_BYTE(x, 1) << 16) | \ - (EXTRACT_BYTE(x, 2) << 8) | EXTRACT_BYTE(x, 3)) -#define CPU_TO_FDT64(x) ((EXTRACT_BYTE(x, 0) << 56) | (EXTRACT_BYTE(x, 1) << 48) | \ - (EXTRACT_BYTE(x, 2) << 40) | (EXTRACT_BYTE(x, 3) << 32) | \ - (EXTRACT_BYTE(x, 4) << 24) | (EXTRACT_BYTE(x, 5) << 16) | \ - (EXTRACT_BYTE(x, 6) << 8) | EXTRACT_BYTE(x, 7)) +typedef be16_t FDT_BITWISE fdt16_t; +typedef be32_t FDT_BITWISE fdt32_t; +typedef be64_t FDT_BITWISE fdt64_t; static inline uint16_t fdt16_to_cpu(fdt16_t x) { - return (FDT_FORCE uint16_t)CPU_TO_FDT16(x); + return (FDT_FORCE uint16_t)be16_to_cpu(x); } + static inline fdt16_t cpu_to_fdt16(uint16_t x) { - return (FDT_FORCE fdt16_t)CPU_TO_FDT16(x); + return (FDT_FORCE fdt16_t)cpu_to_be16(x); } static inline uint32_t fdt32_to_cpu(fdt32_t x) { - return (FDT_FORCE uint32_t)CPU_TO_FDT32(x); + return (FDT_FORCE uint32_t)be32_to_cpu(x); } + static inline fdt32_t cpu_to_fdt32(uint32_t x) { - return (FDT_FORCE fdt32_t)CPU_TO_FDT32(x); + return (FDT_FORCE fdt32_t)cpu_to_be32(x); } static inline uint64_t fdt64_to_cpu(fdt64_t x) { - return (FDT_FORCE uint64_t)CPU_TO_FDT64(x); + return (FDT_FORCE uint64_t)be64_to_cpu(x); } + static inline fdt64_t cpu_to_fdt64(uint64_t x) { - return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x); + return (FDT_FORCE fdt64_t)cpu_to_be64(x); } -#undef CPU_TO_FDT64 -#undef CPU_TO_FDT32 -#undef CPU_TO_FDT16 -#undef EXTRACT_BYTE #ifdef __APPLE__ #include diff -Nru opensbi-1.1/lib/utils/libfdt/objects.mk opensbi-1.3/lib/utils/libfdt/objects.mk --- opensbi-1.1/lib/utils/libfdt/objects.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/libfdt/objects.mk 2023-06-23 07:31:49.000000000 +0200 @@ -12,5 +12,5 @@ $(foreach file, $(libfdt_files), \ $(eval CFLAGS_$(file) = -I$(src)/../../utils/libfdt)) -libsbiutils-objs-y += $(addprefix libfdt/,$(libfdt_files)) +libsbiutils-objs-$(CONFIG_LIBFDT) += $(addprefix libfdt/,$(libfdt_files)) libsbiutils-genflags-y += -I$(libsbiutils_dir)/libfdt/ diff -Nru opensbi-1.1/lib/utils/reset/fdt_reset_atcwdt200.c opensbi-1.3/lib/utils/reset/fdt_reset_atcwdt200.c --- opensbi-1.1/lib/utils/reset/fdt_reset_atcwdt200.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/reset/fdt_reset_atcwdt200.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,117 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Andes Technology Corporation + * + * Authors: + * Yu Chien Peter Lin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ATCWDT200_WP_NUM 0x5aa5 +#define WREN_REG 0x18 +#define CTRL_REG 0x10 +#define RST_TIME_OFF 8 +#define RST_TIME_MSK (0x3 << RST_TIME_OFF) +#define RST_CLK_128 (0 << RST_TIME_OFF) +#define RST_CLK_256 (1 << RST_TIME_OFF) +#define RST_CLK_512 (2 << RST_TIME_OFF) +#define RST_CLK_1024 (3 << RST_TIME_OFF) +#define INT_TIME_OFF 4 +#define INT_TIME_MSK (0xf << INT_TIME_OFF) +#define INT_CLK_64 (0 << INT_TIME_OFF) +#define INT_CLK_256 (1 << INT_TIME_OFF) +#define INT_CLK_1024 (2 << INT_TIME_OFF) +#define INT_CLK_2048 (3 << INT_TIME_OFF) +#define INT_CLK_4096 (4 << INT_TIME_OFF) +#define INT_CLK_8192 (5 << INT_TIME_OFF) +#define INT_CLK_16384 (6 << INT_TIME_OFF) +#define INT_CLK_32768 (7 << INT_TIME_OFF) +#define RST_EN (1 << 3) +#define INT_EN (1 << 2) +#define CLK_PCLK (1 << 1) +#define WDT_EN (1 << 0) + +static volatile char *wdt_addr = NULL; +static struct smu_data smu = { 0 }; + +static int ae350_system_reset_check(u32 type, u32 reason) +{ + switch (type) { + case SBI_SRST_RESET_TYPE_COLD_REBOOT: + return 1; + case SBI_SRST_RESET_TYPE_SHUTDOWN: + case SBI_SRST_RESET_TYPE_WARM_REBOOT: + default: + return 0; + } +} + +static void ae350_system_reset(u32 type, u32 reason) +{ + const struct sbi_platform *plat = sbi_platform_thishart_ptr(); + + for (int i = 0; i < sbi_platform_hart_count(plat); i++) + if (smu_set_reset_vector(&smu, FLASH_BASE, i)) + goto fail; + + /* Program WDT control register */ + writew(ATCWDT200_WP_NUM, wdt_addr + WREN_REG); + writel(INT_CLK_32768 | INT_EN | RST_CLK_128 | RST_EN | WDT_EN, + wdt_addr + CTRL_REG); + +fail: + sbi_hart_hang(); +} + +static struct sbi_system_reset_device atcwdt200_reset = { + .name = "atcwdt200", + .system_reset_check = ae350_system_reset_check, + .system_reset = ae350_system_reset, +}; + +static int atcwdt200_reset_init(void *fdt, int nodeoff, + const struct fdt_match *match) +{ + uint64_t reg_addr; + int rc; + + rc = fdt_get_node_addr_size(fdt, nodeoff, 0, ®_addr, NULL); + if (rc < 0 || !reg_addr) + return SBI_ENODEV; + + wdt_addr = (volatile char *)(unsigned long)reg_addr; + + /* + * The reset device requires smu to program the reset + * vector for each hart. + */ + if (fdt_parse_compat_addr(fdt, ®_addr, "andestech,atcsmu")) + return SBI_ENODEV; + + smu.addr = (unsigned long)reg_addr; + + sbi_system_reset_add_device(&atcwdt200_reset); + + return 0; +} + +static const struct fdt_match atcwdt200_reset_match[] = { + { .compatible = "andestech,atcwdt200" }, + {}, +}; + +struct fdt_reset fdt_reset_atcwdt200 = { + .match_table = atcwdt200_reset_match, + .init = atcwdt200_reset_init, +}; diff -Nru opensbi-1.1/lib/utils/reset/fdt_reset_gpio.c opensbi-1.3/lib/utils/reset/fdt_reset_gpio.c --- opensbi-1.1/lib/utils/reset/fdt_reset_gpio.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/reset/fdt_reset_gpio.c 2023-06-23 07:31:49.000000000 +0200 @@ -77,7 +77,7 @@ static int gpio_system_poweroff_check(u32 type, u32 reason) { - if (gpio_reset_get(FALSE, type)) + if (gpio_reset_get(false, type)) return 128; return 0; @@ -85,7 +85,7 @@ static void gpio_system_poweroff(u32 type, u32 reason) { - gpio_reset_exec(gpio_reset_get(FALSE, type)); + gpio_reset_exec(gpio_reset_get(false, type)); } static struct sbi_system_reset_device gpio_poweroff = { @@ -96,7 +96,7 @@ static int gpio_system_restart_check(u32 type, u32 reason) { - if (gpio_reset_get(TRUE, type)) + if (gpio_reset_get(true, type)) return 128; return 0; @@ -104,7 +104,7 @@ static void gpio_system_restart(u32 type, u32 reason) { - gpio_reset_exec(gpio_reset_get(TRUE, type)); + gpio_reset_exec(gpio_reset_get(true, type)); } static struct sbi_system_reset_device gpio_restart = { @@ -149,7 +149,7 @@ } static const struct fdt_match gpio_poweroff_match[] = { - { .compatible = "gpio-poweroff", .data = (const void *)FALSE }, + { .compatible = "gpio-poweroff", .data = (const void *)false }, { }, }; @@ -159,7 +159,7 @@ }; static const struct fdt_match gpio_reset_match[] = { - { .compatible = "gpio-restart", .data = (const void *)TRUE }, + { .compatible = "gpio-restart", .data = (const void *)true }, { }, }; diff -Nru opensbi-1.1/lib/utils/reset/Kconfig opensbi-1.3/lib/utils/reset/Kconfig --- opensbi-1.1/lib/utils/reset/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/reset/Kconfig 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: BSD-2-Clause + +menu "System Reset Support" + +config FDT_RESET + bool "FDT based reset drivers" + depends on FDT + default n + +if FDT_RESET + +config FDT_RESET_ATCWDT200 + bool "Andes WDT FDT reset driver" + depends on SYS_ATCSMU + default n + +config FDT_RESET_GPIO + bool "GPIO FDT reset driver" + depends on FDT_GPIO + default n + +config FDT_RESET_HTIF + bool "Host transfer interface (HTIF) FDT reset driver" + select SYS_HTIF + default n + +config FDT_RESET_SIFIVE_TEST + bool "SiFive Test FDT reset driver" + select SYS_SIFIVE_TEST + default n + +config FDT_RESET_SUNXI_WDT + bool "Sunxi WDT FDT reset driver" + default n + +config FDT_RESET_THEAD + bool "T-HEAD FDT reset driver" + default n + +endif + +endmenu diff -Nru opensbi-1.1/lib/utils/reset/objects.mk opensbi-1.3/lib/utils/reset/objects.mk --- opensbi-1.1/lib/utils/reset/objects.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/reset/objects.mk 2023-06-23 07:31:49.000000000 +0200 @@ -7,22 +7,25 @@ # Anup Patel # -libsbiutils-objs-y += reset/fdt_reset.o -libsbiutils-objs-y += reset/fdt_reset_drivers.o +libsbiutils-objs-$(CONFIG_FDT_RESET) += reset/fdt_reset.o +libsbiutils-objs-$(CONFIG_FDT_RESET) += reset/fdt_reset_drivers.o -carray-fdt_reset_drivers-y += fdt_poweroff_gpio -carray-fdt_reset_drivers-y += fdt_reset_gpio -libsbiutils-objs-y += reset/fdt_reset_gpio.o +carray-fdt_reset_drivers-$(CONFIG_FDT_RESET_ATCWDT200) += fdt_reset_atcwdt200 +libsbiutils-objs-$(CONFIG_FDT_RESET_ATCWDT200) += reset/fdt_reset_atcwdt200.o -carray-fdt_reset_drivers-y += fdt_reset_htif -libsbiutils-objs-y += reset/fdt_reset_htif.o +carray-fdt_reset_drivers-$(CONFIG_FDT_RESET_GPIO) += fdt_poweroff_gpio +carray-fdt_reset_drivers-$(CONFIG_FDT_RESET_GPIO) += fdt_reset_gpio +libsbiutils-objs-$(CONFIG_FDT_RESET_GPIO) += reset/fdt_reset_gpio.o -carray-fdt_reset_drivers-y += fdt_reset_sifive_test -libsbiutils-objs-y += reset/fdt_reset_sifive_test.o +carray-fdt_reset_drivers-$(CONFIG_FDT_RESET_HTIF) += fdt_reset_htif +libsbiutils-objs-$(CONFIG_FDT_RESET_HTIF) += reset/fdt_reset_htif.o -carray-fdt_reset_drivers-y += fdt_reset_sunxi_wdt -libsbiutils-objs-y += reset/fdt_reset_sunxi_wdt.o +carray-fdt_reset_drivers-$(CONFIG_FDT_RESET_SIFIVE_TEST) += fdt_reset_sifive_test +libsbiutils-objs-$(CONFIG_FDT_RESET_SIFIVE_TEST) += reset/fdt_reset_sifive_test.o -carray-fdt_reset_drivers-y += fdt_reset_thead -libsbiutils-objs-y += reset/fdt_reset_thead.o -libsbiutils-objs-y += reset/fdt_reset_thead_asm.o +carray-fdt_reset_drivers-$(CONFIG_FDT_RESET_SUNXI_WDT) += fdt_reset_sunxi_wdt +libsbiutils-objs-$(CONFIG_FDT_RESET_SUNXI_WDT) += reset/fdt_reset_sunxi_wdt.o + +carray-fdt_reset_drivers-$(CONFIG_FDT_RESET_THEAD) += fdt_reset_thead +libsbiutils-objs-$(CONFIG_FDT_RESET_THEAD) += reset/fdt_reset_thead.o +libsbiutils-objs-$(CONFIG_FDT_RESET_THEAD) += reset/fdt_reset_thead_asm.o diff -Nru opensbi-1.1/lib/utils/serial/cadence-uart.c opensbi-1.3/lib/utils/serial/cadence-uart.c --- opensbi-1.1/lib/utils/serial/cadence-uart.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/serial/cadence-uart.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,128 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 StarFive Technology Co., Ltd. + * + * Author: Jun Liang Tan + */ + +#include +#include +#include + +/* clang-format off */ + +#define UART_REG_CTRL 0x00 +#define UART_REG_MODE 0x04 +#define UART_REG_IDR 0x0C +#define UART_REG_BRGR 0x18 +#define UART_REG_CSR 0x2C +#define UART_REG_RFIFO_TFIFO 0x30 +#define UART_REG_BDIVR 0x34 + +#define UART_CTRL_RXRES 0x00000001 +#define UART_CTRL_TXRES 0x00000002 +#define UART_CTRL_RXEN 0x00000004 +#define UART_CTRL_RXDIS 0x00000008 +#define UART_CTRL_TXEN 0x00000010 +#define UART_CTRL_TXDIS 0x00000020 + +#define UART_MODE_PAR_NONE 0x00000020 /* No parity set */ + +#define UART_BRGR_CD_CLKDIVISOR 0x00000001 /* baud_sample = sel_clk */ + +#define UART_CSR_REMPTY 0x00000002 +#define UART_CSR_TFUL 0x00000010 + +/* clang-format on */ + +static volatile void *uart_base; +static u32 uart_in_freq; +static u32 uart_baudrate; + +/* + * Find minimum divisor divides in_freq to max_target_hz; + * Based on SiFive UART driver (sifive-uart.c) + */ +static inline unsigned int uart_min_clk_divisor(uint64_t in_freq, + uint64_t max_target_hz) +{ + uint64_t quotient = (in_freq + max_target_hz - 1) / (max_target_hz); + + /* Avoid underflow */ + if (quotient == 0) + return 0; + else + return quotient - 1; +} + +static u32 get_reg(u32 offset) +{ + return readl(uart_base + offset); +} + +static void set_reg(u32 offset, u32 val) +{ + writel(val, uart_base + offset); +} + +static void cadence_uart_putc(char ch) +{ + while (get_reg(UART_REG_CSR) & UART_CSR_TFUL) + ; + + set_reg(UART_REG_RFIFO_TFIFO, ch); +} + +static int cadence_uart_getc(void) +{ + u32 ret = get_reg(UART_REG_CSR); + + if (!(ret & UART_CSR_REMPTY)) + return get_reg(UART_REG_RFIFO_TFIFO); + + return -1; +} + +static struct sbi_console_device cadence_console = { + .name = "cadence_uart", + .console_putc = cadence_uart_putc, + .console_getc = cadence_uart_getc +}; + +int cadence_uart_init(unsigned long base, u32 in_freq, u32 baudrate) +{ + uart_base = (volatile void *)base; + uart_in_freq = in_freq; + uart_baudrate = baudrate; + + /* Disable interrupts */ + set_reg(UART_REG_IDR, 0xFFFFFFFF); + + /* Disable TX RX */ + set_reg(UART_REG_CTRL, UART_CTRL_TXDIS | UART_CTRL_RXDIS); + + /* Configure baudrate */ + if (in_freq && baudrate) { + set_reg(UART_REG_BRGR, UART_BRGR_CD_CLKDIVISOR); + set_reg(UART_REG_BDIVR, + uart_min_clk_divisor(in_freq, baudrate)); + } + + /* Software reset TX RX data path and enable TX RX */ + set_reg(UART_REG_CTRL, UART_CTRL_TXRES | UART_CTRL_RXRES + | UART_CTRL_TXEN | UART_CTRL_RXEN); + + /* + * Set: + * 1 stop bit, bits[07:06] = 0x00, + * no parity set, bits[05:03] = 0x100, + * 8 bits character length, bits[02:01] = 0x00, + * sel_clk = uart_clk, bit[0] = 0x0 + */ + set_reg(UART_REG_MODE, UART_MODE_PAR_NONE); + + sbi_console_set_device(&cadence_console); + + return 0; +} diff -Nru opensbi-1.1/lib/utils/serial/fdt_serial.c opensbi-1.3/lib/utils/serial/fdt_serial.c --- opensbi-1.1/lib/utils/serial/fdt_serial.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/serial/fdt_serial.c 2023-06-23 07:31:49.000000000 +0200 @@ -17,13 +17,6 @@ extern struct fdt_serial *fdt_serial_drivers[]; extern unsigned long fdt_serial_drivers_size; -static struct fdt_serial dummy = { - .match_table = NULL, - .init = NULL, -}; - -static struct fdt_serial *current_driver = &dummy; - int fdt_serial_init(void) { const void *prop; @@ -57,20 +50,15 @@ if (!match) continue; - if (drv->init) { - rc = drv->init(fdt, noff, match); - if (rc == SBI_ENODEV) - continue; - if (rc) - return rc; - } - current_driver = drv; - break; - } + /* drv->init must not be NULL */ + if (drv->init == NULL) + return SBI_EFAIL; - /* Check if we found desired driver */ - if (current_driver != &dummy) - goto done; + rc = drv->init(fdt, noff, match); + if (rc == SBI_ENODEV) + continue; + return rc; + } /* Lastly check all DT nodes */ for (pos = 0; pos < fdt_serial_drivers_size; pos++) { @@ -80,17 +68,15 @@ if (noff < 0) continue; - if (drv->init) { - rc = drv->init(fdt, noff, match); - if (rc == SBI_ENODEV) - continue; - if (rc) - return rc; - } - current_driver = drv; - break; + /* drv->init must not be NULL */ + if (drv->init == NULL) + return SBI_EFAIL; + + rc = drv->init(fdt, noff, match); + if (rc == SBI_ENODEV) + continue; + return rc; } -done: - return 0; + return SBI_ENODEV; } diff -Nru opensbi-1.1/lib/utils/serial/fdt_serial_cadence.c opensbi-1.3/lib/utils/serial/fdt_serial_cadence.c --- opensbi-1.1/lib/utils/serial/fdt_serial_cadence.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/serial/fdt_serial_cadence.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,36 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 StarFive Technology Co., Ltd. + * + * Author: Jun Liang Tan + */ + +#include +#include +#include + +static int serial_cadence_init(void *fdt, int nodeoff, + const struct fdt_match *match) +{ + int rc; + struct platform_uart_data uart = { 0 }; + + rc = fdt_parse_uart_node(fdt, nodeoff, &uart); + if (rc) + return rc; + + return cadence_uart_init(uart.addr, uart.freq, uart.baud); +} + +static const struct fdt_match serial_cadence_match[] = { + { .compatible = "cdns,uart-r1p8", }, + { .compatible = "cdns,uart-r1p12" }, + { .compatible = "starfive,jh8100-uart" }, + { }, +}; + +struct fdt_serial fdt_serial_cadence = { + .match_table = serial_cadence_match, + .init = serial_cadence_init +}; diff -Nru opensbi-1.1/lib/utils/serial/fdt_serial_gaisler.c opensbi-1.3/lib/utils/serial/fdt_serial_gaisler.c --- opensbi-1.1/lib/utils/serial/fdt_serial_gaisler.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/serial/fdt_serial_gaisler.c 2023-06-23 07:31:49.000000000 +0200 @@ -15,7 +15,7 @@ const struct fdt_match *match) { int rc; - struct platform_uart_data uart; + struct platform_uart_data uart = { 0 }; rc = fdt_parse_gaisler_uart_node(fdt, nodeoff, &uart); if (rc) diff -Nru opensbi-1.1/lib/utils/serial/fdt_serial_renesas_scif.c opensbi-1.3/lib/utils/serial/fdt_serial_renesas_scif.c --- opensbi-1.1/lib/utils/serial/fdt_serial_renesas_scif.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/serial/fdt_serial_renesas_scif.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2022 Renesas Electronics Corporation + */ + +#include +#include +#include + +static int serial_renesas_scif_init(void *fdt, int nodeoff, + const struct fdt_match *match) +{ + struct platform_uart_data uart = { 0 }; + int ret; + + ret = fdt_parse_renesas_scif_node(fdt, nodeoff, &uart); + if (ret) + return ret; + + return renesas_scif_init(uart.addr, uart.freq, uart.baud); +} + +static const struct fdt_match serial_renesas_scif_match[] = { + { .compatible = "renesas,scif-r9a07g043" }, + { /* sentinel */ } +}; + +struct fdt_serial fdt_serial_renesas_scif = { + .match_table = serial_renesas_scif_match, + .init = serial_renesas_scif_init +}; diff -Nru opensbi-1.1/lib/utils/serial/fdt_serial_shakti.c opensbi-1.3/lib/utils/serial/fdt_serial_shakti.c --- opensbi-1.1/lib/utils/serial/fdt_serial_shakti.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/serial/fdt_serial_shakti.c 2023-06-23 07:31:49.000000000 +0200 @@ -13,7 +13,7 @@ const struct fdt_match *match) { int rc; - struct platform_uart_data uart; + struct platform_uart_data uart = { 0 }; rc = fdt_parse_shakti_uart_node(fdt, nodeoff, &uart); if (rc) diff -Nru opensbi-1.1/lib/utils/serial/fdt_serial_sifive.c opensbi-1.3/lib/utils/serial/fdt_serial_sifive.c --- opensbi-1.1/lib/utils/serial/fdt_serial_sifive.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/serial/fdt_serial_sifive.c 2023-06-23 07:31:49.000000000 +0200 @@ -15,7 +15,7 @@ const struct fdt_match *match) { int rc; - struct platform_uart_data uart; + struct platform_uart_data uart = { 0 }; rc = fdt_parse_sifive_uart_node(fdt, nodeoff, &uart); if (rc) diff -Nru opensbi-1.1/lib/utils/serial/fdt_serial_uart8250.c opensbi-1.3/lib/utils/serial/fdt_serial_uart8250.c --- opensbi-1.1/lib/utils/serial/fdt_serial_uart8250.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/serial/fdt_serial_uart8250.c 2023-06-23 07:31:49.000000000 +0200 @@ -15,9 +15,9 @@ const struct fdt_match *match) { int rc; - struct platform_uart_data uart; + struct platform_uart_data uart = { 0 }; - rc = fdt_parse_uart8250_node(fdt, nodeoff, &uart); + rc = fdt_parse_uart_node(fdt, nodeoff, &uart); if (rc) return rc; diff -Nru opensbi-1.1/lib/utils/serial/fdt_serial_xlnx_uartlite.c opensbi-1.3/lib/utils/serial/fdt_serial_xlnx_uartlite.c --- opensbi-1.1/lib/utils/serial/fdt_serial_xlnx_uartlite.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/serial/fdt_serial_xlnx_uartlite.c 2023-06-23 07:31:49.000000000 +0200 @@ -15,7 +15,7 @@ const struct fdt_match *match) { int rc; - struct platform_uart_data uart; + struct platform_uart_data uart = { 0 }; rc = fdt_parse_xlnx_uartlite_node(fdt, nodeoff, &uart); if (rc) diff -Nru opensbi-1.1/lib/utils/serial/gaisler-uart.c opensbi-1.3/lib/utils/serial/gaisler-uart.c --- opensbi-1.1/lib/utils/serial/gaisler-uart.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/serial/gaisler-uart.c 2023-06-23 07:31:49.000000000 +0200 @@ -70,7 +70,7 @@ uart_base = (volatile char *)base; /* Configure baudrate */ - if (in_freq) + if (in_freq && baudrate) set_reg(UART_REG_SCALER, in_freq / (baudrate * 8 + 7)); ctrl = get_reg(UART_REG_CTRL); diff -Nru opensbi-1.1/lib/utils/serial/Kconfig opensbi-1.3/lib/utils/serial/Kconfig --- opensbi-1.1/lib/utils/serial/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/serial/Kconfig 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,95 @@ +# SPDX-License-Identifier: BSD-2-Clause + +menu "Serial Device Support" + +config FDT_SERIAL + bool "FDT based serial drivers" + depends on FDT + default n + +if FDT_SERIAL + +config FDT_SERIAL_CADENCE + bool "Cadence UART FDT driver" + select SERIAL_CADENCE + default n + +config FDT_SERIAL_GAISLER + bool "Gaisler UART FDT driver" + select SERIAL_GAISLER + default n + +config FDT_SERIAL_HTIF + bool "Host transfer interface (HTIF) UART FDT driver" + select SYS_HTIF + default n + +config FDT_SERIAL_RENESAS_SCIF + bool "Renesas SCIF FDT driver" + select SERIAL_RENESAS_SCIF + default n + +config FDT_SERIAL_SHAKTI + bool "Shakti UART FDT driver" + select SERIAL_SHAKTI + default n + +config FDT_SERIAL_SIFIVE + bool "SiFive UART FDT driver" + select SERIAL_SIFIVE + default n + +config FDT_SERIAL_LITEX + bool "LiteX UART FDT driver" + select SERIAL_LITEX + default n + +config FDT_SERIAL_UART8250 + bool "8250 UART FDT driver" + select SERIAL_UART8250 + default n + +config FDT_SERIAL_XILINX_UARTLITE + bool "Xilinx UART Lite FDT driver" + select SERIAL_XILINX_UARTLITE + default n + +endif + +config SERIAL_CADENCE + bool "Cadence UART support" + default n + +config SERIAL_GAISLER + bool "Gaisler UART support" + default n + +config SERIAL_RENESAS_SCIF + bool "Renesas SCIF support" + default n + +config SERIAL_SHAKTI + bool "Shakti UART support" + default n + +config SERIAL_SIFIVE + bool "SiFive UART support" + default n + +config SERIAL_LITEX + bool "LiteX UART support" + default n + +config SERIAL_UART8250 + bool "8250 UART support" + default n + +config SERIAL_XILINX_UARTLITE + bool "Xilinx UART Lite support" + default n + +config SERIAL_SEMIHOSTING + bool "Semihosting support" + default n + +endmenu diff -Nru opensbi-1.1/lib/utils/serial/objects.mk opensbi-1.3/lib/utils/serial/objects.mk --- opensbi-1.1/lib/utils/serial/objects.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/serial/objects.mk 2023-06-23 07:31:49.000000000 +0200 @@ -7,33 +7,42 @@ # Anup Patel # -libsbiutils-objs-y += serial/fdt_serial.o -libsbiutils-objs-y += serial/fdt_serial_drivers.o +libsbiutils-objs-$(CONFIG_FDT_SERIAL) += serial/fdt_serial.o +libsbiutils-objs-$(CONFIG_FDT_SERIAL) += serial/fdt_serial_drivers.o -carray-fdt_serial_drivers-y += fdt_serial_gaisler -libsbiutils-objs-y += serial/fdt_serial_gaisler.o +carray-fdt_serial_drivers-$(CONFIG_FDT_SERIAL_CADENCE) += fdt_serial_cadence +libsbiutils-objs-$(CONFIG_FDT_SERIAL_CADENCE) += serial/fdt_serial_cadence.o -carray-fdt_serial_drivers-y += fdt_serial_htif -libsbiutils-objs-y += serial/fdt_serial_htif.o +carray-fdt_serial_drivers-$(CONFIG_FDT_SERIAL_GAISLER) += fdt_serial_gaisler +libsbiutils-objs-$(CONFIG_FDT_SERIAL_GAISLER) += serial/fdt_serial_gaisler.o -carray-fdt_serial_drivers-y += fdt_serial_shakti -libsbiutils-objs-y += serial/fdt_serial_shakti.o +carray-fdt_serial_drivers-$(CONFIG_FDT_SERIAL_HTIF) += fdt_serial_htif +libsbiutils-objs-$(CONFIG_FDT_SERIAL_HTIF) += serial/fdt_serial_htif.o -carray-fdt_serial_drivers-y += fdt_serial_sifive -libsbiutils-objs-y += serial/fdt_serial_sifive.o +carray-fdt_serial_drivers-$(CONFIG_FDT_SERIAL_RENESAS_SCIF) += fdt_serial_renesas_scif +libsbiutils-objs-$(CONFIG_FDT_SERIAL_RENESAS_SCIF) += serial/fdt_serial_renesas_scif.o -carray-fdt_serial_drivers-y += fdt_serial_litex -libsbiutils-objs-y += serial/fdt_serial_litex.o +carray-fdt_serial_drivers-$(CONFIG_FDT_SERIAL_SHAKTI) += fdt_serial_shakti +libsbiutils-objs-$(CONFIG_FDT_SERIAL_SHAKTI) += serial/fdt_serial_shakti.o -carray-fdt_serial_drivers-y += fdt_serial_uart8250 -libsbiutils-objs-y += serial/fdt_serial_uart8250.o +carray-fdt_serial_drivers-$(CONFIG_FDT_SERIAL_SIFIVE) += fdt_serial_sifive +libsbiutils-objs-$(CONFIG_FDT_SERIAL_SIFIVE) += serial/fdt_serial_sifive.o -carray-fdt_serial_drivers-y += fdt_serial_xlnx_uartlite -libsbiutils-objs-y += serial/fdt_serial_xlnx_uartlite.o +carray-fdt_serial_drivers-$(CONFIG_FDT_SERIAL_LITEX) += fdt_serial_litex +libsbiutils-objs-$(CONFIG_FDT_SERIAL_LITEX) += serial/fdt_serial_litex.o -libsbiutils-objs-y += serial/gaisler-uart.o -libsbiutils-objs-y += serial/shakti-uart.o -libsbiutils-objs-y += serial/sifive-uart.o -libsbiutils-objs-y += serial/litex-uart.o -libsbiutils-objs-y += serial/uart8250.o -libsbiutils-objs-y += serial/xlnx-uartlite.o +carray-fdt_serial_drivers-$(CONFIG_FDT_SERIAL_UART8250) += fdt_serial_uart8250 +libsbiutils-objs-$(CONFIG_FDT_SERIAL_UART8250) += serial/fdt_serial_uart8250.o + +carray-fdt_serial_drivers-$(CONFIG_FDT_SERIAL_XILINX_UARTLITE) += fdt_serial_xlnx_uartlite +libsbiutils-objs-$(CONFIG_FDT_SERIAL_XILINX_UARTLITE) += serial/fdt_serial_xlnx_uartlite.o + +libsbiutils-objs-$(CONFIG_SERIAL_CADENCE) += serial/cadence-uart.o +libsbiutils-objs-$(CONFIG_SERIAL_GAISLER) += serial/gaisler-uart.o +libsbiutils-objs-$(CONFIG_SERIAL_RENESAS_SCIF) += serial/renesas_scif.o +libsbiutils-objs-$(CONFIG_SERIAL_SHAKTI) += serial/shakti-uart.o +libsbiutils-objs-$(CONFIG_SERIAL_SIFIVE) += serial/sifive-uart.o +libsbiutils-objs-$(CONFIG_SERIAL_LITEX) += serial/litex-uart.o +libsbiutils-objs-$(CONFIG_SERIAL_UART8250) += serial/uart8250.o +libsbiutils-objs-$(CONFIG_SERIAL_XILINX_UARTLITE) += serial/xlnx-uartlite.o +libsbiutils-objs-$(CONFIG_SERIAL_SEMIHOSTING) += serial/semihosting.o diff -Nru opensbi-1.1/lib/utils/serial/renesas_scif.c opensbi-1.3/lib/utils/serial/renesas_scif.c --- opensbi-1.1/lib/utils/serial/renesas_scif.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/serial/renesas_scif.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2022 Renesas Electronics Corporation + */ + +#include +#include +#include +#include + +/* clang-format off */ + +#define SCIF_REG_SMR 0x0 +#define SCIF_REG_BRR 0x2 +#define SCIF_REG_SCR 0x4 +#define SCIF_REG_FTDR 0x6 +#define SCIF_REG_FSR 0x8 +#define SCIF_REG_FCR 0xc +#define SCIF_REG_LSR 0x12 +#define SCIF_REG_SEMR 0x14 + +#define SCIF_FCR_RFRST 0x2 /* Reset assert receive-FIFO (bit[1]) */ +#define SCIF_FCR_TFRST 0x4 /* Reset assert transmit-FIFO(bit[2]) */ + +#define SCIF_FCR_RST_ASSRT_RFTF (SCIF_FCR_RFRST | SCIF_FCR_TFRST) /* Reset assert tx-FIFO & rx-FIFO */ +#define SCIF_FCR_RST_NGATE_RFTF 0x0 /* Reset negate tx-FIFO & rx-FIFO */ + +#define SCIF_SCR_RE 0x10 /* Enable receive (bit[4]) */ +#define SCIF_SCR_TE 0x20 /* Enable transmit(bit[5]) */ +#define SCIF_SCR_RCV_TRN_EN (SCIF_SCR_RE | SCIF_SCR_TE) /* Enable receive & transmit */ +#define SCIF_SCR_RCV_TRN_DIS 0x0 /* Disable receive & transmit */ + +#define SCIF_FSR_ER 0x80 /* Receive error flag */ +#define SCIF_FSR_TEND 0x40 /* Transmit End Flag */ +#define SCIF_FSR_TDFE 0x20 /* Transmit FIFO Data Empty Flag */ +#define SCIF_FSR_BRK 0x10 /* Detect break flag */ +#define SCIF_FSR_DR 0x1 /* Receive data ready flag */ + +#define SCIF_FSR_TXD_CHK (SCIF_FSR_TEND | SCIF_FSR_TDFE) + +#define SCIF_SEMR_MDDRS 0x10 /* MDDR access enable */ + +#define SCIF_REG_8BIT(reg) ((reg == SCIF_REG_BRR) || \ + (reg == SCIF_REG_FTDR) || \ + (reg == SCIF_REG_SEMR)) + +#define SCBRR_VALUE(clk, baudrate) ((clk) / (32 * (baudrate)) - 1) + +/* clang-format on */ + +static volatile char *scif_base; + +static u32 get_reg(u32 offset) +{ + if (SCIF_REG_8BIT(offset)) + return readb(scif_base + offset); + + return readw(scif_base + offset); +} + +static void set_reg(u32 offset, u32 val) +{ + if (SCIF_REG_8BIT(offset)) + writeb(val, scif_base + offset); + else + writew(val, scif_base + offset); +} + +static void renesas_scif_putc(char ch) +{ + uint16_t reg; + + while (!(SCIF_FSR_TXD_CHK & get_reg(SCIF_REG_FSR))) + ; + + set_reg(SCIF_REG_FTDR, ch); + reg = get_reg(SCIF_REG_FSR); + reg &= ~SCIF_FSR_TXD_CHK; + set_reg(SCIF_REG_FSR, reg); +} + +static struct sbi_console_device renesas_scif_console = { + .name = "renesas_scif", + .console_putc = renesas_scif_putc, +}; + +int renesas_scif_init(unsigned long base, u32 in_freq, u32 baudrate) +{ + uint16_t data16; + + scif_base = (volatile char *)base; + + set_reg(SCIF_REG_SCR, SCIF_SCR_RCV_TRN_DIS); + set_reg(SCIF_REG_FCR, SCIF_FCR_RST_ASSRT_RFTF); + + data16 = get_reg(SCIF_REG_FSR); /* Dummy read */ + set_reg(SCIF_REG_FSR, 0x0); /* Clear all error bit */ + + data16 = get_reg(SCIF_REG_LSR); /* Dummy read */ + set_reg(SCIF_REG_LSR, 0x0); /* Clear ORER bit */ + + set_reg(SCIF_REG_SCR, 0x0); + + set_reg(SCIF_REG_SMR, 0x0); + + data16 = get_reg(SCIF_REG_SEMR); + set_reg(SCIF_REG_SEMR, data16 & (~SCIF_SEMR_MDDRS)); + set_reg(SCIF_REG_BRR, SCBRR_VALUE(in_freq, baudrate)); + + set_reg(SCIF_REG_FCR, SCIF_FCR_RST_NGATE_RFTF); + set_reg(SCIF_REG_SCR, SCIF_SCR_RCV_TRN_EN); + + sbi_console_set_device(&renesas_scif_console); + + return 0; +} diff -Nru opensbi-1.1/lib/utils/serial/semihosting.c opensbi-1.3/lib/utils/serial/semihosting.c --- opensbi-1.1/lib/utils/serial/semihosting.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/serial/semihosting.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,215 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Ventana Micro Systems Inc. + * + * Authors: + * Anup Patel + * Kautuk Consul + */ + +#include +#include +#include +#include + +#define SYSOPEN 0x01 +#define SYSWRITEC 0x03 +#define SYSWRITE 0x05 +#define SYSREAD 0x06 +#define SYSREADC 0x07 +#define SYSERRNO 0x13 + +static long semihosting_trap(int sysnum, void *addr) +{ + register int ret asm ("a0") = sysnum; + register void *param0 asm ("a1") = addr; + + asm volatile ( + " .align 4\n" + " .option push\n" + " .option norvc\n" + + " slli zero, zero, 0x1f\n" + " ebreak\n" + " srai zero, zero, 7\n" + + " .option pop\n" + : "+r" (ret) : "r" (param0) : "memory"); + + return ret; +} + +static bool _semihosting_enabled = true; +static bool try_semihosting = true; + +bool semihosting_enabled(void) +{ + register int ret asm ("a0") = SYSERRNO; + register void *param0 asm ("a1") = NULL; + unsigned long tmp = 0; + + if (!try_semihosting) + return _semihosting_enabled; + + asm volatile ( + " .align 4\n" + " .option push\n" + " .option norvc\n" + + " j _semihost_test_vector_next\n" + " .align 4\n" + "_semihost_test_vector:\n" + " csrr %[en], mepc\n" + " addi %[en], %[en], 4\n" + " csrw mepc, %[en]\n" + " add %[en], zero, zero\n" + " mret\n" + "_semihost_test_vector_next:\n" + + " la %[tmp], _semihost_test_vector\n" + " csrrw %[tmp], mtvec, %[tmp]\n" + " .align 4\n" + " slli zero, zero, 0x1f\n" + " ebreak\n" + " srai zero, zero, 7\n" + " csrw mtvec, %[tmp]\n" + + " .option pop\n" + : [tmp] "+r" (tmp), [en] "+r" (_semihosting_enabled), + [ret] "+r" (ret) + : "r" (param0) : "memory"); + + try_semihosting = false; + return _semihosting_enabled; +} + +static int semihosting_errno(void) +{ + long ret = semihosting_trap(SYSERRNO, NULL); + + if (ret > 0) + return -ret; + return SBI_EIO; +} + +static int semihosting_infd = SBI_ENODEV; +static int semihosting_outfd = SBI_ENODEV; + +static long semihosting_open(const char *fname, enum semihosting_open_mode mode) +{ + long fd; + struct semihosting_open_s { + const char *fname; + unsigned long mode; + size_t len; + } open; + + open.fname = fname; + open.len = sbi_strlen(fname); + open.mode = mode; + + /* Open the file on the host */ + fd = semihosting_trap(SYSOPEN, &open); + if (fd == -1) + return semihosting_errno(); + return fd; +} + +/** + * struct semihosting_rdwr_s - Arguments for read and write + * @fd: A file descriptor returned from semihosting_open() + * @memp: Pointer to a buffer of memory of at least @len bytes + * @len: The number of bytes to read or write + */ +struct semihosting_rdwr_s { + long fd; + void *memp; + size_t len; +}; + +static long semihosting_read(long fd, void *memp, size_t len) +{ + long ret; + struct semihosting_rdwr_s read; + + read.fd = fd; + read.memp = memp; + read.len = len; + + ret = semihosting_trap(SYSREAD, &read); + if (ret < 0) + return semihosting_errno(); + return len - ret; +} + +static long semihosting_write(long fd, const void *memp, size_t len) +{ + long ret; + struct semihosting_rdwr_s write; + + write.fd = fd; + write.memp = (void *)memp; + write.len = len; + + ret = semihosting_trap(SYSWRITE, &write); + if (ret < 0) + return semihosting_errno(); + return len - ret; +} + +/* clang-format on */ + +static void semihosting_putc(char ch) +{ + semihosting_trap(SYSWRITEC, &ch); +} + +static unsigned long semihosting_puts(const char *str, unsigned long len) +{ + char ch; + long ret; + unsigned long i; + + if (semihosting_outfd < 0) { + for (i = 0; i < len; i++) { + ch = str[i]; + semihosting_trap(SYSWRITEC, &ch); + } + ret = len; + } else + ret = semihosting_write(semihosting_outfd, str, len); + + return (ret < 0) ? 0 : ret; +} + +static int semihosting_getc(void) +{ + char ch = 0; + int ret; + + if (semihosting_infd < 0) { + ret = semihosting_trap(SYSREADC, NULL); + ret = ret < 0 ? -1 : ret; + } else + ret = semihosting_read(semihosting_infd, &ch, 1) > 0 ? ch : -1; + + return ret; +} + +static struct sbi_console_device semihosting_console = { + .name = "semihosting", + .console_putc = semihosting_putc, + .console_puts = semihosting_puts, + .console_getc = semihosting_getc +}; + +int semihosting_init(void) +{ + semihosting_infd = semihosting_open(":tt", MODE_READ); + semihosting_outfd = semihosting_open(":tt", MODE_WRITE); + + sbi_console_set_device(&semihosting_console); + + return 0; +} diff -Nru opensbi-1.1/lib/utils/serial/shakti-uart.c opensbi-1.3/lib/utils/serial/shakti-uart.c --- opensbi-1.1/lib/utils/serial/shakti-uart.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/serial/shakti-uart.c 2023-06-23 07:31:49.000000000 +0200 @@ -19,21 +19,21 @@ #define REG_RX_THRES 0x20 #define UART_TX_FULL 0x2 +#define UART_RX_NOT_EMPTY 0x4 #define UART_RX_FULL 0x8 static volatile char *uart_base; static void shakti_uart_putc(char ch) { - while((readw(uart_base + REG_STATUS) & UART_TX_FULL)) + while ((readb(uart_base + REG_STATUS) & UART_TX_FULL)) ; writeb(ch, uart_base + REG_TX); } static int shakti_uart_getc(void) { - u16 status = readw(uart_base + REG_STATUS); - if (status & UART_RX_FULL) + if (readb(uart_base + REG_STATUS) & UART_RX_NOT_EMPTY) return readb(uart_base + REG_RX); return -1; } @@ -47,8 +47,12 @@ int shakti_uart_init(unsigned long base, u32 in_freq, u32 baudrate) { uart_base = (volatile char *)base; - u16 baud = (u16)(in_freq/(16 * baudrate)); - writew(baud, uart_base + REG_BAUD); + u16 baud; + + if (baudrate) { + baud = (u16)(in_freq / (16 * baudrate)); + writew(baud, uart_base + REG_BAUD); + } sbi_console_set_device(&shakti_console); diff -Nru opensbi-1.1/lib/utils/serial/sifive-uart.c opensbi-1.3/lib/utils/serial/sifive-uart.c --- opensbi-1.1/lib/utils/serial/sifive-uart.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/serial/sifive-uart.c 2023-06-23 07:31:49.000000000 +0200 @@ -48,12 +48,12 @@ uint64_t max_target_hz) { uint64_t quotient = (in_freq + max_target_hz - 1) / (max_target_hz); + /* Avoid underflow */ - if (quotient == 0) { + if (quotient == 0) return 0; - } else { + else return quotient - 1; - } } static u32 get_reg(u32 num) @@ -77,8 +77,10 @@ static int sifive_uart_getc(void) { u32 ret = get_reg(UART_REG_RXFIFO); + if (!(ret & UART_RXFIFO_EMPTY)) return ret & UART_RXFIFO_DATA; + return -1; } @@ -95,12 +97,15 @@ uart_baudrate = baudrate; /* Configure baudrate */ - if (in_freq) + if (in_freq && baudrate) set_reg(UART_REG_DIV, uart_min_clk_divisor(in_freq, baudrate)); + /* Disable interrupts */ set_reg(UART_REG_IE, 0); + /* Enable TX */ set_reg(UART_REG_TXCTRL, UART_TXCTRL_TXEN); + /* Enable Rx */ set_reg(UART_REG_RXCTRL, UART_RXCTRL_RXEN); diff -Nru opensbi-1.1/lib/utils/serial/uart8250.c opensbi-1.3/lib/utils/serial/uart8250.c --- opensbi-1.1/lib/utils/serial/uart8250.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/serial/uart8250.c 2023-06-23 07:31:49.000000000 +0200 @@ -93,7 +93,7 @@ int uart8250_init(unsigned long base, u32 in_freq, u32 baudrate, u32 reg_shift, u32 reg_width, u32 reg_offset) { - u16 bdiv; + u16 bdiv = 0; uart8250_base = (volatile char *)base + reg_offset; uart8250_reg_shift = reg_shift; @@ -101,7 +101,10 @@ uart8250_in_freq = in_freq; uart8250_baudrate = baudrate; - bdiv = (uart8250_in_freq + 8 * uart8250_baudrate) / (16 * uart8250_baudrate); + if (uart8250_baudrate) { + bdiv = (uart8250_in_freq + 8 * uart8250_baudrate) / + (16 * uart8250_baudrate); + } /* Disable all interrupts */ set_reg(UART_IER_OFFSET, 0x00); diff -Nru opensbi-1.1/lib/utils/sys/atcsmu.c opensbi-1.3/lib/utils/sys/atcsmu.c --- opensbi-1.1/lib/utils/sys/atcsmu.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/sys/atcsmu.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,92 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2023 Andes Technology Corporation + * + * Authors: + * Yu Chien Peter Lin + */ + +#include +#include +#include +#include +#include + +inline int smu_set_wakeup_events(struct smu_data *smu, u32 events, u32 hartid) +{ + if (smu) { + writel(events, (void *)(smu->addr + PCSm_WE_OFFSET(hartid))); + return 0; + } else + return SBI_EINVAL; +} + +inline bool smu_support_sleep_mode(struct smu_data *smu, u32 sleep_mode, + u32 hartid) +{ + u32 pcs_cfg; + + if (!smu) { + sbi_printf("%s(): Failed to access smu_data\n", __func__); + return false; + } + + pcs_cfg = readl((void *)(smu->addr + PCSm_CFG_OFFSET(hartid))); + + switch (sleep_mode) { + case LIGHTSLEEP_MODE: + if (EXTRACT_FIELD(pcs_cfg, PCS_CFG_LIGHT_SLEEP) == 0) { + sbi_printf( + "SMU: hart%d (PCS%d) does not support light sleep mode\n", + hartid, hartid + 3); + return false; + } + break; + case DEEPSLEEP_MODE: + if (EXTRACT_FIELD(pcs_cfg, PCS_CFG_DEEP_SLEEP) == 0) { + sbi_printf( + "SMU: hart%d (PCS%d) does not support deep sleep mode\n", + hartid, hartid + 3); + return false; + } + break; + } + + return true; +} + +inline int smu_set_command(struct smu_data *smu, u32 pcs_ctl, u32 hartid) +{ + if (smu) { + writel(pcs_ctl, (void *)(smu->addr + PCSm_CTL_OFFSET(hartid))); + return 0; + } else + return SBI_EINVAL; +} + +inline int smu_set_reset_vector(struct smu_data *smu, ulong wakeup_addr, + u32 hartid) +{ + u32 vec_lo, vec_hi; + u64 reset_vector; + + if (!smu) + return SBI_EINVAL; + + writel(wakeup_addr, (void *)(smu->addr + HARTn_RESET_VEC_LO(hartid))); + writel((u64)wakeup_addr >> 32, + (void *)(smu->addr + HARTn_RESET_VEC_HI(hartid))); + + vec_lo = readl((void *)(smu->addr + HARTn_RESET_VEC_LO(hartid))); + vec_hi = readl((void *)(smu->addr + HARTn_RESET_VEC_HI(hartid))); + reset_vector = ((u64)vec_hi << 32) | vec_lo; + + if (reset_vector != (u64)wakeup_addr) { + sbi_printf( + "hard%d (PCS%d): Failed to program the reset vector.\n", + hartid, hartid + 3); + return SBI_EFAIL; + } else + return 0; +} diff -Nru opensbi-1.1/lib/utils/sys/htif.c opensbi-1.3/lib/utils/sys/htif.c --- opensbi-1.1/lib/utils/sys/htif.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/sys/htif.c 2023-06-23 07:31:49.000000000 +0200 @@ -135,11 +135,11 @@ __set_tohost(HTIF_DEV_SYSTEM, cmd, data); while (1) { - uint64_t fh = fromhost; + uint64_t fh = __read_fromhost(); if (fh) { if (FROMHOST_DEV(fh) == HTIF_DEV_SYSTEM && FROMHOST_CMD(fh) == cmd) { - fromhost = 0; + __write_fromhost(0); break; } __check_fromhost(); diff -Nru opensbi-1.1/lib/utils/sys/Kconfig opensbi-1.3/lib/utils/sys/Kconfig --- opensbi-1.1/lib/utils/sys/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/sys/Kconfig 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: BSD-2-Clause + +menu "System Device Support" + +config SYS_ATCSMU + bool "Andes System Management Unit (SMU) support" + default n + +config SYS_HTIF + bool "Host transfere interface (HTIF) support" + default n + +config SYS_SIFIVE_TEST + bool "SiFive test support" + default n + +endmenu diff -Nru opensbi-1.1/lib/utils/sys/objects.mk opensbi-1.3/lib/utils/sys/objects.mk --- opensbi-1.1/lib/utils/sys/objects.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/sys/objects.mk 2023-06-23 07:31:49.000000000 +0200 @@ -7,5 +7,6 @@ # Anup Patel # -libsbiutils-objs-y += sys/htif.o -libsbiutils-objs-y += sys/sifive_test.o +libsbiutils-objs-$(CONFIG_SYS_HTIF) += sys/htif.o +libsbiutils-objs-$(CONFIG_SYS_SIFIVE_TEST) += sys/sifive_test.o +libsbiutils-objs-$(CONFIG_SYS_ATCSMU) += sys/atcsmu.o diff -Nru opensbi-1.1/lib/utils/timer/aclint_mtimer.c opensbi-1.3/lib/utils/timer/aclint_mtimer.c --- opensbi-1.1/lib/utils/timer/aclint_mtimer.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/timer/aclint_mtimer.c 2023-06-23 07:31:49.000000000 +0200 @@ -13,12 +13,17 @@ #include #include #include -#include -#include +#include #include #include -static struct aclint_mtimer_data *mtimer_hartid2data[SBI_HARTMASK_MAX_BITS]; +static unsigned long mtimer_ptr_offset; + +#define mtimer_get_hart_data_ptr(__scratch) \ + sbi_scratch_read_type((__scratch), void *, mtimer_ptr_offset) + +#define mtimer_set_hart_data_ptr(__scratch, __mtimer) \ + sbi_scratch_write_type((__scratch), void *, mtimer_ptr_offset, (__mtimer)) #if __riscv_xlen != 32 static u64 mtimer_time_rd64(volatile u64 *addr) @@ -53,30 +58,54 @@ static u64 mtimer_value(void) { - struct aclint_mtimer_data *mt = mtimer_hartid2data[current_hartid()]; - u64 *time_val = (void *)mt->mtime_addr; + struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); + struct aclint_mtimer_data *mt; + + mt = mtimer_get_hart_data_ptr(scratch); + if (!mt) + return 0; /* Read MTIMER Time Value */ - return mt->time_rd(time_val); + return mt->time_rd((void *)mt->mtime_addr); } static void mtimer_event_stop(void) { u32 target_hart = current_hartid(); - struct aclint_mtimer_data *mt = mtimer_hartid2data[target_hart]; - u64 *time_cmp = (void *)mt->mtimecmp_addr; + struct sbi_scratch *scratch; + struct aclint_mtimer_data *mt; + u64 *time_cmp; + + scratch = sbi_hartid_to_scratch(target_hart); + if (!scratch) + return; + + mt = mtimer_get_hart_data_ptr(scratch); + if (!mt) + return; /* Clear MTIMER Time Compare */ + time_cmp = (void *)mt->mtimecmp_addr; mt->time_wr(true, -1ULL, &time_cmp[target_hart - mt->first_hartid]); } static void mtimer_event_start(u64 next_event) { u32 target_hart = current_hartid(); - struct aclint_mtimer_data *mt = mtimer_hartid2data[target_hart]; - u64 *time_cmp = (void *)mt->mtimecmp_addr; + struct sbi_scratch *scratch; + struct aclint_mtimer_data *mt; + u64 *time_cmp; + + scratch = sbi_hartid_to_scratch(target_hart); + if (!scratch) + return; + + mt = mtimer_get_hart_data_ptr(scratch); + if (!mt) + return; /* Program MTIMER Time Compare */ + time_cmp = (void *)mt->mtimecmp_addr; mt->time_wr(true, next_event, &time_cmp[target_hart - mt->first_hartid]); } @@ -126,8 +155,14 @@ { u64 *mt_time_cmp; u32 target_hart = current_hartid(); - struct aclint_mtimer_data *mt = mtimer_hartid2data[target_hart]; + struct sbi_scratch *scratch; + struct aclint_mtimer_data *mt; + + scratch = sbi_hartid_to_scratch(target_hart); + if (!scratch) + return SBI_ENOENT; + mt = mtimer_get_hart_data_ptr(scratch); if (!mt) return SBI_ENODEV; @@ -142,53 +177,32 @@ return 0; } -static int aclint_mtimer_add_regions(unsigned long addr, unsigned long size) -{ -#define MTIMER_ADD_REGION_ALIGN 0x1000 - int rc; - unsigned long pos, end, rsize; - struct sbi_domain_memregion reg; - - pos = addr; - end = addr + size; - while (pos < end) { - rsize = pos & (MTIMER_ADD_REGION_ALIGN - 1); - if (rsize) - rsize = 1UL << sbi_ffs(pos); - else - rsize = ((end - pos) < MTIMER_ADD_REGION_ALIGN) ? - (end - pos) : MTIMER_ADD_REGION_ALIGN; - - sbi_domain_memregion_init(pos, rsize, - SBI_DOMAIN_MEMREGION_MMIO, ®); - rc = sbi_domain_root_add_memregion(®); - if (rc) - return rc; - pos += rsize; - } - - return 0; -} - int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt, struct aclint_mtimer_data *reference) { u32 i; int rc; + struct sbi_scratch *scratch; /* Sanity checks */ - if (!mt || !mt->mtime_size || + if (!mt || (mt->hart_count && !mt->mtimecmp_size) || - (mt->mtime_addr & (ACLINT_MTIMER_ALIGN - 1)) || - (mt->mtime_size & (ACLINT_MTIMER_ALIGN - 1)) || + (mt->mtime_size && (mt->mtime_addr & (ACLINT_MTIMER_ALIGN - 1))) || + (mt->mtime_size && (mt->mtime_size & (ACLINT_MTIMER_ALIGN - 1))) || (mt->mtimecmp_addr & (ACLINT_MTIMER_ALIGN - 1)) || (mt->mtimecmp_size & (ACLINT_MTIMER_ALIGN - 1)) || - (mt->first_hartid >= SBI_HARTMASK_MAX_BITS) || (mt->hart_count > ACLINT_MTIMER_MAX_HARTS)) return SBI_EINVAL; if (reference && mt->mtime_freq != reference->mtime_freq) return SBI_EINVAL; + /* Allocate scratch space pointer */ + if (!mtimer_ptr_offset) { + mtimer_ptr_offset = sbi_scratch_alloc_type_offset(void *); + if (!mtimer_ptr_offset) + return SBI_ENOMEM; + } + /* Initialize private data */ aclint_mtimer_set_reference(mt, reference); mt->time_rd = mtimer_time_rd32; @@ -202,29 +216,52 @@ } #endif - /* Update MTIMER hartid table */ - for (i = 0; i < mt->hart_count; i++) - mtimer_hartid2data[mt->first_hartid + i] = mt; + /* Update MTIMER pointer in scratch space */ + for (i = 0; i < mt->hart_count; i++) { + scratch = sbi_hartid_to_scratch(mt->first_hartid + i); + if (!scratch) + return SBI_ENOENT; + mtimer_set_hart_data_ptr(scratch, mt); + } + + if (!mt->mtime_size) { + /* Disable reading mtime when mtime is not available */ + mtimer.timer_value = NULL; + } /* Add MTIMER regions to the root domain */ if (mt->mtime_addr == (mt->mtimecmp_addr + mt->mtimecmp_size)) { - rc = aclint_mtimer_add_regions(mt->mtimecmp_addr, - mt->mtime_size + mt->mtimecmp_size); + rc = sbi_domain_root_add_memrange(mt->mtimecmp_addr, + mt->mtime_size + mt->mtimecmp_size, + MTIMER_REGION_ALIGN, + (SBI_DOMAIN_MEMREGION_MMIO | + SBI_DOMAIN_MEMREGION_M_READABLE | + SBI_DOMAIN_MEMREGION_M_WRITABLE)); if (rc) return rc; } else if (mt->mtimecmp_addr == (mt->mtime_addr + mt->mtime_size)) { - rc = aclint_mtimer_add_regions(mt->mtime_addr, - mt->mtime_size + mt->mtimecmp_size); + rc = sbi_domain_root_add_memrange(mt->mtime_addr, + mt->mtime_size + mt->mtimecmp_size, + MTIMER_REGION_ALIGN, + (SBI_DOMAIN_MEMREGION_MMIO | + SBI_DOMAIN_MEMREGION_M_READABLE | + SBI_DOMAIN_MEMREGION_M_WRITABLE)); if (rc) return rc; } else { - rc = aclint_mtimer_add_regions(mt->mtime_addr, - mt->mtime_size); + rc = sbi_domain_root_add_memrange(mt->mtime_addr, + mt->mtime_size, MTIMER_REGION_ALIGN, + (SBI_DOMAIN_MEMREGION_MMIO | + SBI_DOMAIN_MEMREGION_M_READABLE | + SBI_DOMAIN_MEMREGION_M_WRITABLE)); if (rc) return rc; - rc = aclint_mtimer_add_regions(mt->mtimecmp_addr, - mt->mtimecmp_size); + rc = sbi_domain_root_add_memrange(mt->mtimecmp_addr, + mt->mtimecmp_size, MTIMER_REGION_ALIGN, + (SBI_DOMAIN_MEMREGION_MMIO | + SBI_DOMAIN_MEMREGION_M_READABLE | + SBI_DOMAIN_MEMREGION_M_WRITABLE)); if (rc) return rc; } diff -Nru opensbi-1.1/lib/utils/timer/andes_plmt.c opensbi-1.3/lib/utils/timer/andes_plmt.c --- opensbi-1.1/lib/utils/timer/andes_plmt.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/timer/andes_plmt.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,104 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Andes Technology Corporation + * + * Authors: + * Yu Chien Peter Lin + */ + +#include +#include +#include +#include +#include +#include + +struct plmt_data plmt; + +static u64 plmt_timer_value(void) +{ +#if __riscv_xlen == 64 + return readq_relaxed(plmt.time_val); +#else + u32 lo, hi; + + do { + hi = readl_relaxed((void *)plmt.time_val + 0x04); + lo = readl_relaxed(plmt.time_val); + } while (hi != readl_relaxed((void *)plmt.time_val + 0x04)); + + return ((u64)hi << 32) | (u64)lo; +#endif +} + +static void plmt_timer_event_stop(void) +{ + u32 target_hart = current_hartid(); + + if (plmt.hart_count <= target_hart) + ebreak(); + + /* Clear PLMT Time Compare */ +#if __riscv_xlen == 64 + writeq_relaxed(-1ULL, &plmt.time_cmp[target_hart]); +#else + writel_relaxed(-1UL, &plmt.time_cmp[target_hart]); + writel_relaxed(-1UL, (void *)(&plmt.time_cmp[target_hart]) + 0x04); +#endif +} + +static void plmt_timer_event_start(u64 next_event) +{ + u32 target_hart = current_hartid(); + + if (plmt.hart_count <= target_hart) + ebreak(); + + /* Program PLMT Time Compare */ +#if __riscv_xlen == 64 + writeq_relaxed(next_event, &plmt.time_cmp[target_hart]); +#else + u32 mask = -1UL; + + writel_relaxed(next_event & mask, &plmt.time_cmp[target_hart]); + writel_relaxed(next_event >> 32, + (void *)(&plmt.time_cmp[target_hart]) + 0x04); +#endif +} + +static struct sbi_timer_device plmt_timer = { + .name = "andes_plmt", + .timer_freq = DEFAULT_AE350_PLMT_FREQ, + .timer_value = plmt_timer_value, + .timer_event_start = plmt_timer_event_start, + .timer_event_stop = plmt_timer_event_stop +}; + +int plmt_cold_timer_init(struct plmt_data *plmt) +{ + int rc; + + /* Add PLMT region to the root domain */ + rc = sbi_domain_root_add_memrange( + (unsigned long)plmt->time_val, plmt->size, PLMT_REGION_ALIGN, + SBI_DOMAIN_MEMREGION_MMIO | SBI_DOMAIN_MEMREGION_READABLE); + if (rc) + return rc; + + plmt_timer.timer_freq = plmt->timer_freq; + + sbi_timer_set_device(&plmt_timer); + + return 0; +} + +int plmt_warm_timer_init(void) +{ + if (!plmt.time_val) + return SBI_ENODEV; + + plmt_timer_event_stop(); + + return 0; +} diff -Nru opensbi-1.1/lib/utils/timer/fdt_timer.c opensbi-1.3/lib/utils/timer/fdt_timer.c --- opensbi-1.1/lib/utils/timer/fdt_timer.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/timer/fdt_timer.c 2023-06-23 07:31:49.000000000 +0200 @@ -16,24 +16,17 @@ extern struct fdt_timer *fdt_timer_drivers[]; extern unsigned long fdt_timer_drivers_size; -static struct fdt_timer dummy = { - .match_table = NULL, - .cold_init = NULL, - .warm_init = NULL, - .exit = NULL, -}; - -static struct fdt_timer *current_driver = &dummy; +static struct fdt_timer *current_driver = NULL; void fdt_timer_exit(void) { - if (current_driver->exit) + if (current_driver && current_driver->exit) current_driver->exit(); } static int fdt_timer_warm_init(void) { - if (current_driver->warm_init) + if (current_driver && current_driver->warm_init) return current_driver->warm_init(); return 0; } @@ -51,20 +44,28 @@ noff = -1; while ((noff = fdt_find_match(fdt, noff, drv->match_table, &match)) >= 0) { - if (drv->cold_init) { - rc = drv->cold_init(fdt, noff, match); - if (rc == SBI_ENODEV) - continue; - if (rc) - return rc; - } + /* drv->cold_init must not be NULL */ + if (drv->cold_init == NULL) + return SBI_EFAIL; + + rc = drv->cold_init(fdt, noff, match); + if (rc == SBI_ENODEV) + continue; + if (rc) + return rc; current_driver = drv; - } - if (current_driver != &dummy) - break; + /* + * We will have multiple timer devices on multi-die or + * multi-socket systems so we cannot break here. + */ + } } + /* + * We can't fail here since systems with Sstc might not provide + * mtimer/clint DT node in the device tree. + */ return 0; } diff -Nru opensbi-1.1/lib/utils/timer/fdt_timer_mtimer.c opensbi-1.3/lib/utils/timer/fdt_timer_mtimer.c --- opensbi-1.1/lib/utils/timer/fdt_timer_mtimer.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/timer/fdt_timer_mtimer.c 2023-06-23 07:31:49.000000000 +0200 @@ -9,43 +9,54 @@ #include #include +#include +#include #include #include #include -#define MTIMER_MAX_NR 16 - struct timer_mtimer_quirks { unsigned int mtime_offset; bool has_64bit_mmio; + bool without_mtime; +}; + +struct timer_mtimer_node { + struct sbi_dlist head; + struct aclint_mtimer_data data; }; +static SBI_LIST_HEAD(mtn_list); -static unsigned long mtimer_count = 0; -static struct aclint_mtimer_data mtimer[MTIMER_MAX_NR]; static struct aclint_mtimer_data *mt_reference = NULL; static int timer_mtimer_cold_init(void *fdt, int nodeoff, const struct fdt_match *match) { - int i, rc; + int rc; unsigned long addr[2], size[2]; + struct timer_mtimer_node *mtn, *n; struct aclint_mtimer_data *mt; - if (MTIMER_MAX_NR <= mtimer_count) - return SBI_ENOSPC; - mt = &mtimer[mtimer_count]; + mtn = sbi_zalloc(sizeof(*mtn)); + if (!mtn) + return SBI_ENOMEM; + mt = &mtn->data; rc = fdt_parse_aclint_node(fdt, nodeoff, true, &addr[0], &size[0], &addr[1], &size[1], &mt->first_hartid, &mt->hart_count); - if (rc) + if (rc) { + sbi_free(mtn); return rc; + } mt->has_64bit_mmio = true; mt->has_shared_mtime = false; rc = fdt_parse_timebase_frequency(fdt, &mt->mtime_freq); - if (rc) + if (rc) { + sbi_free(mtn); return rc; + } if (match->data) { /* SiFive CLINT */ const struct timer_mtimer_quirks *quirks = match->data; @@ -53,12 +64,16 @@ /* Set CLINT addresses */ mt->mtimecmp_addr = addr[0] + ACLINT_DEFAULT_MTIMECMP_OFFSET; mt->mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE; - mt->mtime_addr = addr[0] + ACLINT_DEFAULT_MTIME_OFFSET; - mt->mtime_size = size[0] - mt->mtimecmp_size; - /* Adjust MTIMER address and size for CLINT device */ - mt->mtime_addr += quirks->mtime_offset; + if (!quirks->without_mtime) { + mt->mtime_addr = addr[0] + ACLINT_DEFAULT_MTIME_OFFSET; + mt->mtime_size = size[0] - mt->mtimecmp_size; + /* Adjust MTIMER address and size for CLINT device */ + mt->mtime_addr += quirks->mtime_offset; + mt->mtime_size -= quirks->mtime_offset; + } else { + mt->mtime_addr = mt->mtime_size = 0; + } mt->mtimecmp_addr += quirks->mtime_offset; - mt->mtime_size -= quirks->mtime_offset; /* Apply additional CLINT quirks */ mt->has_64bit_mmio = quirks->has_64bit_mmio; } else { /* RISC-V ACLINT MTIMER */ @@ -70,18 +85,25 @@ } /* Check if MTIMER device has shared MTIME address */ - mt->has_shared_mtime = false; - for (i = 0; i < mtimer_count; i++) { - if (mtimer[i].mtime_addr == mt->mtime_addr) { - mt->has_shared_mtime = true; - break; + if (mt->mtime_size) { + mt->has_shared_mtime = false; + sbi_list_for_each_entry(n, &mtn_list, head) { + if (n->data.mtime_addr == mt->mtime_addr) { + mt->has_shared_mtime = true; + break; + } } + } else { + /* Assume shared time CSR */ + mt->has_shared_mtime = true; } /* Initialize the MTIMER device */ rc = aclint_mtimer_cold_init(mt, mt_reference); - if (rc) + if (rc) { + sbi_free(mtn); return rc; + } /* * Select first MTIMER device with no associated HARTs as our @@ -96,16 +118,17 @@ * Set reference for already propbed MTIMER devices * with non-shared MTIME */ - for (i = 0; i < mtimer_count; i++) - if (!mtimer[i].has_shared_mtime) - aclint_mtimer_set_reference(&mtimer[i], mt); + sbi_list_for_each_entry(n, &mtn_list, head) { + if (!n->data.has_shared_mtime) + aclint_mtimer_set_reference(&n->data, mt); + } } /* Explicitly sync-up MTIMER devices not associated with any HARTs */ if (!mt->hart_count) aclint_mtimer_sync(mt); - mtimer_count++; + sbi_list_add_tail(&mtn->head, &mtn_list); return 0; } @@ -114,9 +137,15 @@ .has_64bit_mmio = true, }; +static const struct timer_mtimer_quirks thead_clint_quirks = { + .mtime_offset = CLINT_MTIMER_OFFSET, + .without_mtime = true, +}; + static const struct fdt_match timer_mtimer_match[] = { { .compatible = "riscv,clint0", .data = &sifive_clint_quirks }, { .compatible = "sifive,clint0", .data = &sifive_clint_quirks }, + { .compatible = "thead,c900-clint", .data = &thead_clint_quirks }, { .compatible = "riscv,aclint-mtimer" }, { }, }; diff -Nru opensbi-1.1/lib/utils/timer/fdt_timer_plmt.c opensbi-1.3/lib/utils/timer/fdt_timer_plmt.c --- opensbi-1.1/lib/utils/timer/fdt_timer_plmt.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/timer/fdt_timer_plmt.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,51 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Andes Technology Corporation + * + * Authors: + * Yu Chien Peter Lin + */ + +#include +#include +#include + +extern struct plmt_data plmt; + +static int fdt_plmt_cold_timer_init(void *fdt, int nodeoff, + const struct fdt_match *match) +{ + int rc; + unsigned long plmt_base; + + rc = fdt_parse_plmt_node(fdt, nodeoff, &plmt_base, &plmt.size, + &plmt.hart_count); + if (rc) + return rc; + + plmt.time_val = (u64 *)plmt_base; + plmt.time_cmp = (u64 *)(plmt_base + 0x8); + + rc = fdt_parse_timebase_frequency(fdt, &plmt.timer_freq); + if (rc) + return rc; + + rc = plmt_cold_timer_init(&plmt); + if (rc) + return rc; + + return 0; +} + +static const struct fdt_match timer_plmt_match[] = { + { .compatible = "andestech,plmt0" }, + {}, +}; + +struct fdt_timer fdt_timer_plmt = { + .match_table = timer_plmt_match, + .cold_init = fdt_plmt_cold_timer_init, + .warm_init = plmt_warm_timer_init, + .exit = NULL, +}; diff -Nru opensbi-1.1/lib/utils/timer/Kconfig opensbi-1.3/lib/utils/timer/Kconfig --- opensbi-1.1/lib/utils/timer/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/lib/utils/timer/Kconfig 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: BSD-2-Clause + +menu "Timer Device Support" + +config FDT_TIMER + bool "FDT based timer drivers" + depends on FDT + default n + +if FDT_TIMER + +config FDT_TIMER_MTIMER + bool "ACLINT MTIMER FDT driver" + select TIMER_MTIMER + default n + +config FDT_TIMER_PLMT + bool "Andes PLMT FDT driver" + select TIMER_PLMT + default n + +endif + +config TIMER_MTIMER + bool "ACLINT MTIMER support" + default n + +config TIMER_PLMT + bool "Andes PLMT support" + default n + +endmenu diff -Nru opensbi-1.1/lib/utils/timer/objects.mk opensbi-1.3/lib/utils/timer/objects.mk --- opensbi-1.1/lib/utils/timer/objects.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/lib/utils/timer/objects.mk 2023-06-23 07:31:49.000000000 +0200 @@ -7,10 +7,14 @@ # Anup Patel # -libsbiutils-objs-y += timer/aclint_mtimer.o +libsbiutils-objs-$(CONFIG_TIMER_MTIMER) += timer/aclint_mtimer.o +libsbiutils-objs-$(CONFIG_TIMER_PLMT) += timer/andes_plmt.o -libsbiutils-objs-y += timer/fdt_timer.o -libsbiutils-objs-y += timer/fdt_timer_drivers.o +libsbiutils-objs-$(CONFIG_FDT_TIMER) += timer/fdt_timer.o +libsbiutils-objs-$(CONFIG_FDT_TIMER) += timer/fdt_timer_drivers.o -carray-fdt_timer_drivers-y += fdt_timer_mtimer -libsbiutils-objs-y += timer/fdt_timer_mtimer.o +carray-fdt_timer_drivers-$(CONFIG_FDT_TIMER_MTIMER) += fdt_timer_mtimer +libsbiutils-objs-$(CONFIG_FDT_TIMER_MTIMER) += timer/fdt_timer_mtimer.o + +carray-fdt_timer_drivers-$(CONFIG_FDT_TIMER_PLMT) += fdt_timer_plmt +libsbiutils-objs-$(CONFIG_FDT_TIMER_PLMT) += timer/fdt_timer_plmt.o diff -Nru opensbi-1.1/Makefile opensbi-1.3/Makefile --- opensbi-1.1/Makefile 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/Makefile 2023-06-23 07:31:49.000000000 +0200 @@ -47,11 +47,14 @@ platform_parent_dir=$(platform_dir_path) else PLATFORM=$(shell basename $(platform_dir_path)) - platform_parent_dir=$(subst $(PLATFORM),,$(platform_dir_path)) + platform_parent_dir=$(shell realpath ${platform_dir_path}/..) endif else platform_parent_dir=$(src_dir)/platform endif +ifndef PLATFORM_DEFCONFIG +PLATFORM_DEFCONFIG=defconfig +endif # Check if verbosity is ON for build process CMD_PREFIX_DEFAULT := @ @@ -70,6 +73,20 @@ export libsbiutils_dir=$(CURDIR)/lib/utils export firmware_dir=$(CURDIR)/firmware +# Setup variables for kconfig +ifdef PLATFORM +export PYTHONDONTWRITEBYTECODE=1 +export KCONFIG_DIR=$(platform_build_dir)/kconfig +export KCONFIG_AUTOLIST=$(KCONFIG_DIR)/auto.list +export KCONFIG_AUTOHEADER=$(KCONFIG_DIR)/autoconf.h +export KCONFIG_AUTOCMD=$(KCONFIG_DIR)/auto.conf.cmd +export KCONFIG_CONFIG=$(KCONFIG_DIR)/.config +# Additional exports for include paths in Kconfig files +export OPENSBI_SRC_DIR=$(src_dir) +export OPENSBI_PLATFORM=$(PLATFORM) +export OPENSBI_PLATFORM_SRC_DIR=$(platform_src_dir) +endif + # Find library version OPENSBI_VERSION_MAJOR=`grep "define OPENSBI_VERSION_MAJOR" $(include_dir)/sbi/sbi_version.h | sed 's/.*MAJOR.*\([0-9][0-9]*\)/\1/'` OPENSBI_VERSION_MINOR=`grep "define OPENSBI_VERSION_MINOR" $(include_dir)/sbi/sbi_version.h | sed 's/.*MINOR.*\([0-9][0-9]*\)/\1/'` @@ -183,12 +200,38 @@ libsbiutils-object-mks=$(shell if [ -d $(libsbiutils_dir) ]; then find $(libsbiutils_dir) -iname "objects.mk" | sort -r; fi) firmware-object-mks=$(shell if [ -d $(firmware_dir) ]; then find $(firmware_dir) -iname "objects.mk" | sort -r; fi) -# Include platform specifig config.mk +# The "make all" rule should always be first rule +.PHONY: all +all: + +# Include platform specific .config ifdef PLATFORM -include $(platform_src_dir)/config.mk +.PHONY: menuconfig +menuconfig: $(platform_src_dir)/Kconfig $(src_dir)/Kconfig + $(CMD_PREFIX)mkdir -p $(KCONFIG_DIR) + $(CMD_PREFIX)$(src_dir)/scripts/Kconfiglib/menuconfig.py $(src_dir)/Kconfig + $(CMD_PREFIX)$(src_dir)/scripts/Kconfiglib/genconfig.py --header-path $(KCONFIG_AUTOHEADER) --sync-deps $(KCONFIG_DIR) --file-list $(KCONFIG_AUTOLIST) $(src_dir)/Kconfig + +.PHONY: savedefconfig +savedefconfig: $(platform_src_dir)/Kconfig $(src_dir)/Kconfig + $(CMD_PREFIX)mkdir -p $(KCONFIG_DIR) + $(CMD_PREFIX)$(src_dir)/scripts/Kconfiglib/savedefconfig.py --kconfig $(src_dir)/Kconfig --out $(KCONFIG_DIR)/defconfig + +$(KCONFIG_CONFIG): $(platform_src_dir)/configs/$(PLATFORM_DEFCONFIG) $(platform_src_dir)/Kconfig $(src_dir)/Kconfig + $(CMD_PREFIX)mkdir -p $(KCONFIG_DIR) + $(CMD_PREFIX)$(src_dir)/scripts/Kconfiglib/defconfig.py --kconfig $(src_dir)/Kconfig $(platform_src_dir)/configs/$(PLATFORM_DEFCONFIG) + $(CMD_PREFIX)$(src_dir)/scripts/Kconfiglib/genconfig.py --header-path $(KCONFIG_AUTOHEADER) --sync-deps $(KCONFIG_DIR) --file-list $(KCONFIG_AUTOLIST) $(src_dir)/Kconfig + +$(KCONFIG_AUTOCMD): $(KCONFIG_CONFIG) + $(CMD_PREFIX)mkdir -p $(KCONFIG_DIR) + $(CMD_PREFIX)printf "%s: " $(KCONFIG_CONFIG) > $(KCONFIG_AUTOCMD) + $(CMD_PREFIX)cat $(KCONFIG_AUTOLIST) | tr '\n' ' ' >> $(KCONFIG_AUTOCMD) + +include $(KCONFIG_CONFIG) +include $(KCONFIG_AUTOCMD) endif -# Include all object.mk files +# Include all objects.mk files ifdef PLATFORM include $(platform-object-mks) endif @@ -198,8 +241,8 @@ # Setup list of objects libsbi-objs-path-y=$(foreach obj,$(libsbi-objs-y),$(build_dir)/lib/sbi/$(obj)) -libsbiutils-objs-path-y=$(foreach obj,$(libsbiutils-objs-y),$(build_dir)/lib/utils/$(obj)) ifdef PLATFORM +libsbiutils-objs-path-y=$(foreach obj,$(libsbiutils-objs-y),$(platform_build_dir)/lib/utils/$(obj)) platform-objs-path-y=$(foreach obj,$(platform-objs-y),$(platform_build_dir)/$(obj)) firmware-bins-path-y=$(foreach bin,$(firmware-bins-y),$(platform_build_dir)/firmware/$(bin)) endif @@ -211,6 +254,7 @@ deps-y+=$(libsbi-objs-path-y:.o=.dep) deps-y+=$(libsbiutils-objs-path-y:.o=.dep) deps-y+=$(firmware-objs-path-y:.o=.dep) +deps-y+=$(firmware-elfs-path-y:=.dep) # Setup platform ABI, ISA and Code Model ifndef PLATFORM_RISCV_ABI @@ -280,11 +324,19 @@ GENFLAGS += -DOPENSBI_BUILD_TIME_STAMP="\"$(OPENSBI_BUILD_TIME_STAMP)\"" GENFLAGS += -DOPENSBI_BUILD_COMPILER_VERSION="\"$(OPENSBI_BUILD_COMPILER_VERSION)\"" endif +ifdef PLATFORM +GENFLAGS += -include $(KCONFIG_AUTOHEADER) +endif GENFLAGS += $(libsbiutils-genflags-y) GENFLAGS += $(platform-genflags-y) GENFLAGS += $(firmware-genflags-y) -CFLAGS = -g -Wall -Werror -ffreestanding -nostdlib -fno-stack-protector -fno-strict-aliasing -O2 +CFLAGS = -g -Wall -Werror -ffreestanding -nostdlib -fno-stack-protector -fno-strict-aliasing +ifneq ($(DEBUG),) +CFLAGS += -O0 +else +CFLAGS += -O2 +endif CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls -mstrict-align # enable -m(no-)save-restore option by CC_SUPPORT_SAVE_RESTORE ifeq ($(CC_SUPPORT_SAVE_RESTORE),y) @@ -323,7 +375,7 @@ ARFLAGS = rcs ELFFLAGS += $(USE_LD_FLAG) -ELFFLAGS += -Wl,--build-id=none -Wl,-N +ELFFLAGS += -Wl,--build-id=none ELFFLAGS += $(platform-ldflags-y) ELFFLAGS += $(firmware-ldflags-y) @@ -349,10 +401,10 @@ cat $(2) > $(1) copy_file = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \ echo " COPY $(subst $(build_dir)/,,$(1))"; \ - cp -f $(2) $(1) + cp -L -f $(2) $(1) inst_file = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \ echo " INSTALL $(subst $(install_root_dir)/,,$(1))"; \ - cp -f $(2) $(1) + cp -L -f $(2) $(1) inst_file_list = $(CMD_PREFIX)if [ ! -z "$(4)" ]; then \ mkdir -p $(1)/$(3); \ for file in $(4) ; do \ @@ -361,12 +413,17 @@ dest_dir=`dirname $$dest_file`; \ echo " INSTALL "$(3)"/"`echo $$rel_file`; \ mkdir -p $$dest_dir; \ - cp -f $$file $$dest_file; \ + cp -L -f $$file $$dest_file; \ done \ fi inst_header_dir = $(CMD_PREFIX)mkdir -p $(1); \ echo " INSTALL $(subst $(install_root_dir)/,,$(1))"; \ - cp -rf $(2) $(1) + cp -L -rf $(2) $(1) +compile_cpp_dep = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \ + echo " CPP-DEP $(subst $(build_dir)/,,$(1))"; \ + printf %s `dirname $(1)`/ > $(1) && \ + $(CC) $(CPPFLAGS) -x c -MM $(3) \ + -MT `basename $(1:.dep=$(2))` >> $(1) || rm -f $(1) compile_cpp = $(CMD_PREFIX)mkdir -p `dirname $(1)`; \ echo " CPP $(subst $(build_dir)/,,$(1))"; \ $(CPP) $(CPPFLAGS) -x c $(2) | grep -v "\#" > $(1) @@ -413,29 +470,33 @@ echo "$(1:.dep=$(2)): $(3)" >> $(1) targets-y = $(build_dir)/lib/libsbi.a -targets-y += $(build_dir)/lib/libsbiutils.a ifdef PLATFORM targets-y += $(platform_build_dir)/lib/libplatsbi.a endif targets-y += $(firmware-bins-path-y) -# Default rule "make" should always be first rule +# The default "make all" rule .PHONY: all all: $(targets-y) # Preserve all intermediate files .SECONDARY: +# Rules for lib/sbi sources $(build_dir)/lib/libsbi.a: $(libsbi-objs-path-y) $(call compile_ar,$@,$^) -$(build_dir)/lib/libsbiutils.a: $(libsbi-objs-path-y) $(libsbiutils-objs-path-y) - $(call compile_ar,$@,$^) - $(platform_build_dir)/lib/libplatsbi.a: $(libsbi-objs-path-y) $(libsbiutils-objs-path-y) $(platform-objs-path-y) $(call compile_ar,$@,$^) -$(build_dir)/%.dep: $(src_dir)/%.c +$(build_dir)/%.dep: $(src_dir)/%.carray $(KCONFIG_CONFIG) + $(call compile_gen_dep,$@,.c,$< $(KCONFIG_CONFIG)) + $(call compile_gen_dep,$@,.o,$(@:.dep=.c)) + +$(build_dir)/%.c: $(src_dir)/%.carray + $(call compile_carray,$@,$<) + +$(build_dir)/%.dep: $(src_dir)/%.c $(KCONFIG_CONFIG) $(call compile_cc_dep,$@,$<) $(build_dir)/%.o: $(src_dir)/%.c @@ -449,32 +510,24 @@ $(call compile_cc,$@,$<) endif -$(build_dir)/%.dep: $(src_dir)/%.S +$(build_dir)/%.dep: $(src_dir)/%.S $(KCONFIG_CONFIG) $(call compile_as_dep,$@,$<) $(build_dir)/%.o: $(src_dir)/%.S $(call compile_as,$@,$<) -$(build_dir)/%.dep: $(src_dir)/%.carray - $(call compile_gen_dep,$@,.c,$<) +# Rules for platform sources +$(platform_build_dir)/%.dep: $(platform_src_dir)/%.carray $(KCONFIG_CONFIG) + $(call compile_gen_dep,$@,.c,$< $(KCONFIG_CONFIG)) $(call compile_gen_dep,$@,.o,$(@:.dep=.c)) -$(build_dir)/%.c: $(src_dir)/%.carray +$(platform_build_dir)/%.c: $(platform_src_dir)/%.carray $(call compile_carray,$@,$<) -$(platform_build_dir)/%.bin: $(platform_build_dir)/%.elf - $(call compile_objcopy,$@,$<) - -$(platform_build_dir)/%.elf: $(platform_build_dir)/%.o $(platform_build_dir)/%.elf.ld $(platform_build_dir)/lib/libplatsbi.a - $(call compile_elf,$@,$@.ld,$< $(platform_build_dir)/lib/libplatsbi.a) - -$(platform_build_dir)/%.ld: $(src_dir)/%.ldS - $(call compile_cpp,$@,$<) - -$(platform_build_dir)/%.dep: $(platform_src_dir)/%.c +$(platform_build_dir)/%.dep: $(platform_src_dir)/%.c $(KCONFIG_CONFIG) $(call compile_cc_dep,$@,$<) -$(platform_build_dir)/%.o: $(platform_src_dir)/%.c +$(platform_build_dir)/%.o: $(platform_src_dir)/%.c $(KCONFIG_CONFIG) $(call compile_cc,$@,$<) $(platform_build_dir)/%.dep: $(platform_src_dir)/%.S @@ -483,8 +536,8 @@ $(platform_build_dir)/%.o: $(platform_src_dir)/%.S $(call compile_as,$@,$<) -$(platform_build_dir)/%.dep: $(platform_src_dir)/%.dts - $(call compile_gen_dep,$@,.dtb,$<) +$(platform_build_dir)/%.dep: $(platform_src_dir)/%.dts $(KCONFIG_CONFIG) + $(call compile_gen_dep,$@,.dtb,$< $(KCONFIG_CONFIG)) $(call compile_gen_dep,$@,.c,$(@:.dep=.dtb)) $(call compile_gen_dep,$@,.o,$(@:.dep=.c)) @@ -494,13 +547,33 @@ $(platform_build_dir)/%.dtb: $(platform_src_dir)/%.dts $(call compile_dts,$@,$<) -$(platform_build_dir)/%.dep: $(src_dir)/%.c +# Rules for lib/utils and firmware sources +$(platform_build_dir)/%.bin: $(platform_build_dir)/%.elf + $(call compile_objcopy,$@,$<) + +$(platform_build_dir)/%.elf: $(platform_build_dir)/%.o $(platform_build_dir)/%.elf.ld $(platform_build_dir)/lib/libplatsbi.a + $(call compile_elf,$@,$@.ld,$< $(platform_build_dir)/lib/libplatsbi.a) + +$(platform_build_dir)/%.dep: $(src_dir)/%.ldS $(KCONFIG_CONFIG) + $(call compile_cpp_dep,$@,.ld,$<) + +$(platform_build_dir)/%.ld: $(src_dir)/%.ldS + $(call compile_cpp,$@,$<) + +$(platform_build_dir)/%.dep: $(src_dir)/%.carray $(KCONFIG_CONFIG) + $(call compile_gen_dep,$@,.c,$< $(KCONFIG_CONFIG)) + $(call compile_gen_dep,$@,.o,$(@:.dep=.c)) + +$(platform_build_dir)/%.c: $(src_dir)/%.carray + $(call compile_carray,$@,$<) + +$(platform_build_dir)/%.dep: $(src_dir)/%.c $(KCONFIG_CONFIG) $(call compile_cc_dep,$@,$<) $(platform_build_dir)/%.o: $(src_dir)/%.c $(call compile_cc,$@,$<) -$(platform_build_dir)/%.dep: $(src_dir)/%.S +$(platform_build_dir)/%.dep: $(src_dir)/%.S $(KCONFIG_CONFIG) $(call compile_as_dep,$@,$<) $(platform_build_dir)/%.o: $(src_dir)/%.S @@ -544,7 +617,6 @@ endif install_targets-y = install_libsbi -install_targets-y += install_libsbiutils ifdef PLATFORM install_targets-y += install_libplatsbi install_targets-y += install_firmwares @@ -559,17 +631,12 @@ $(call inst_header_dir,$(install_root_dir)/$(install_include_path),$(include_dir)/sbi) $(call inst_file,$(install_root_dir)/$(install_lib_path)/libsbi.a,$(build_dir)/lib/libsbi.a) -.PHONY: install_libsbiutils -install_libsbiutils: $(build_dir)/lib/libsbiutils.a - $(call inst_header_dir,$(install_root_dir)/$(install_include_path),$(include_dir)/sbi_utils) - $(call inst_file,$(install_root_dir)/$(install_lib_path)/libsbiutils.a,$(build_dir)/lib/libsbiutils.a) - .PHONY: install_libplatsbi -install_libplatsbi: $(platform_build_dir)/lib/libplatsbi.a $(build_dir)/lib/libsbi.a $(build_dir)/lib/libsbiutils.a +install_libplatsbi: $(platform_build_dir)/lib/libplatsbi.a $(build_dir)/lib/libsbi.a $(call inst_file,$(install_root_dir)/$(install_lib_path)/opensbi/$(platform_subdir)/lib/libplatsbi.a,$(platform_build_dir)/lib/libplatsbi.a) .PHONY: install_firmwares -install_firmwares: $(platform_build_dir)/lib/libplatsbi.a $(build_dir)/lib/libsbi.a $(build_dir)/lib/libsbiutils.a $(firmware-bins-path-y) +install_firmwares: $(platform_build_dir)/lib/libplatsbi.a $(build_dir)/lib/libsbi.a $(firmware-bins-path-y) $(call inst_file_list,$(install_root_dir),$(build_dir),$(install_firmware_path)/$(platform_subdir)/firmware,$(firmware-elfs-path-y)) $(call inst_file_list,$(install_root_dir),$(build_dir),$(install_firmware_path)/$(platform_subdir)/firmware,$(firmware-bins-path-y)) @@ -577,6 +644,17 @@ install_docs: $(build_dir)/docs/latex/refman.pdf $(call inst_file,$(install_root_dir)/$(install_docs_path)/refman.pdf,$(build_dir)/docs/latex/refman.pdf) +.PHONY: cscope +cscope: + $(CMD_PREFIX)find \ + "$(src_dir)/firmware" \ + "$(src_dir)/include" \ + "$(src_dir)/lib" \ + "$(platform_src_dir)" \ + -name "*.[chS]" -print > cscope.files + $(CMD_PREFIX)echo "$(KCONFIG_AUTOHEADER)" >> cscope.files + $(CMD_PREFIX)cscope -bkq -i cscope.files -f cscope.out + # Rule for "make clean" .PHONY: clean clean: @@ -606,6 +684,8 @@ $(if $(V), @echo " RM $(install_root_dir_default)") $(CMD_PREFIX)rm -rf $(install_root_dir_default) endif + $(if $(V), @echo " RM $(src_dir)/cscope*") + $(CMD_PREFIX)rm -f $(src_dir)/cscope* .PHONY: FORCE FORCE: diff -Nru opensbi-1.1/platform/andes/ae350/cache.c opensbi-1.3/platform/andes/ae350/cache.c --- opensbi-1.1/platform/andes/ae350/cache.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/andes/ae350/cache.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,89 +0,0 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2020 Andes Technology Corporation - * - * Authors: - * Nylon Chen - */ - -#include -#include -#include -#include "platform.h" - -uintptr_t mcall_set_mcache_ctl(unsigned long input) -{ - csr_clear(CSR_MCACHECTL, V5_MCACHE_CTL_MASK); - csr_write(CSR_MCACHECTL, input); - return 0; -} - -uintptr_t mcall_set_mmisc_ctl(unsigned long input) -{ - csr_clear(CSR_MMISCCTL, V5_MMISC_CTL_MASK); - csr_write(CSR_MMISCCTL, input); - return 0; -} - -uintptr_t mcall_icache_op(unsigned int enable) -{ - if (enable) { - csr_set(CSR_MCACHECTL, V5_MCACHE_CTL_IC_EN); - } else { - csr_clear(CSR_MCACHECTL, V5_MCACHE_CTL_IC_EN); - asm volatile("fence.i\n\t"); - } - return 0; -} - -uintptr_t mcall_dcache_op(unsigned int enable) -{ - if (enable) { - csr_set(CSR_MCACHECTL, V5_MCACHE_CTL_DC_EN); - } else { - csr_clear(CSR_MCACHECTL, V5_MCACHE_CTL_DC_EN); - csr_write(CSR_MCCTLCOMMAND, V5_UCCTL_L1D_WBINVAL_ALL); - } - return 0; -} - -uintptr_t mcall_l1_cache_i_prefetch_op(unsigned long enable) -{ - if (enable) { - csr_set(CSR_MCACHECTL, V5_MCACHE_CTL_L1I_PREFETCH_EN); - } else { - csr_clear(CSR_MCACHECTL, V5_MCACHE_CTL_L1I_PREFETCH_EN); - } - return 0; -} - -uintptr_t mcall_l1_cache_d_prefetch_op(unsigned long enable) -{ - if (enable) { - csr_set(CSR_MCACHECTL, V5_MCACHE_CTL_L1D_PREFETCH_EN); - } else { - csr_clear(CSR_MCACHECTL, V5_MCACHE_CTL_L1D_PREFETCH_EN); - } - return 0; -} - -uintptr_t mcall_non_blocking_load_store(unsigned long enable) -{ - if (enable) { - csr_set(CSR_MCACHECTL, V5_MMISC_CTL_NON_BLOCKING_EN); - } else { - csr_clear(CSR_MCACHECTL, V5_MMISC_CTL_NON_BLOCKING_EN); - } - return 0; -} - -uintptr_t mcall_write_around(unsigned long enable) -{ - if (enable) { - csr_set(CSR_MCACHECTL, V5_MCACHE_CTL_DC_WAROUND_1_EN); - } else { - csr_clear(CSR_MCACHECTL, V5_MCACHE_CTL_DC_WAROUND_1_EN); - } - return 0; -} diff -Nru opensbi-1.1/platform/andes/ae350/cache.h opensbi-1.3/platform/andes/ae350/cache.h --- opensbi-1.1/platform/andes/ae350/cache.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/andes/ae350/cache.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,17 +0,0 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2020 Andes Technology Corporation - * - * Authors: - * Nylon Chen - */ - -uintptr_t mcall_set_mcache_ctl(unsigned long input); -uintptr_t mcall_set_mmisc_ctl(unsigned long input); -uintptr_t mcall_icache_op(unsigned int enable); -uintptr_t mcall_dcache_op(unsigned int enable); -uintptr_t mcall_l1_cache_i_prefetch_op(unsigned long enable); -uintptr_t mcall_l1_cache_d_prefetch_op(unsigned long enable); -uintptr_t mcall_non_blocking_load_store(unsigned long enable); -uintptr_t mcall_write_around(unsigned long enable); diff -Nru opensbi-1.1/platform/andes/ae350/config.mk opensbi-1.3/platform/andes/ae350/config.mk --- opensbi-1.1/platform/andes/ae350/config.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/andes/ae350/config.mk 1970-01-01 01:00:00.000000000 +0100 @@ -1,36 +0,0 @@ -# -# SPDX-License-Identifier: BSD-2-Clause -# -# Copyright (c) 2019 Andes Technology Corporation -# -# Authors: -# Zong Li -# Nylon Chen - -# Compiler flags -platform-cppflags-y = -platform-cflags-y = -platform-asflags-y = -platform-ldflags-y = - -# Blobs to build -FW_TEXT_START=0x00000000 - -FW_DYNAMIC=y - -FW_JUMP=y -ifeq ($(PLATFORM_RISCV_XLEN), 32) - FW_JUMP_ADDR=0x400000 -else - FW_JUMP_ADDR=0x200000 -endif -FW_JUMP_FDT_ADDR=0x2000000 - -FW_PAYLOAD=y -ifeq ($(PLATFORM_RISCV_XLEN), 32) - FW_PAYLOAD_OFFSET=0x400000 -else - FW_PAYLOAD_OFFSET=0x200000 -endif - -FW_PAYLOAD_FDT_ADDR=0x2000000 diff -Nru opensbi-1.1/platform/andes/ae350/objects.mk opensbi-1.3/platform/andes/ae350/objects.mk --- opensbi-1.1/platform/andes/ae350/objects.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/andes/ae350/objects.mk 1970-01-01 01:00:00.000000000 +0100 @@ -1,11 +0,0 @@ -# -# SPDX-License-Identifier: BSD-2-Clause -# -# Copyright (c) 2019 Andes Technology Corporation -# -# Authors: -# Zong Li -# Nylon Chen -# - -platform-objs-y += cache.o platform.o plicsw.o plmt.o diff -Nru opensbi-1.1/platform/andes/ae350/platform.c opensbi-1.3/platform/andes/ae350/platform.c --- opensbi-1.1/platform/andes/ae350/platform.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/andes/ae350/platform.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,196 +0,0 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 Andes Technology Corporation - * - * Authors: - * Zong Li - * Nylon Chen - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "platform.h" -#include "plicsw.h" -#include "plmt.h" -#include "cache.h" - -static struct plic_data plic = { - .addr = AE350_PLIC_ADDR, - .num_src = AE350_PLIC_NUM_SOURCES, -}; - -/* Platform final initialization. */ -static int ae350_final_init(bool cold_boot) -{ - void *fdt; - - /* enable L1 cache */ - uintptr_t mcache_ctl_val = csr_read(CSR_MCACHECTL); - - if (!(mcache_ctl_val & V5_MCACHE_CTL_IC_EN)) - mcache_ctl_val |= V5_MCACHE_CTL_IC_EN; - if (!(mcache_ctl_val & V5_MCACHE_CTL_DC_EN)) - mcache_ctl_val |= V5_MCACHE_CTL_DC_EN; - if (!(mcache_ctl_val & V5_MCACHE_CTL_CCTL_SUEN)) - mcache_ctl_val |= V5_MCACHE_CTL_CCTL_SUEN; - csr_write(CSR_MCACHECTL, mcache_ctl_val); - - /* enable L2 cache */ - uint32_t *l2c_ctl_base = (void *)AE350_L2C_ADDR + V5_L2C_CTL_OFFSET; - uint32_t l2c_ctl_val = *l2c_ctl_base; - - if (!(l2c_ctl_val & V5_L2C_CTL_ENABLE_MASK)) - l2c_ctl_val |= V5_L2C_CTL_ENABLE_MASK; - *l2c_ctl_base = l2c_ctl_val; - - if (!cold_boot) - return 0; - - fdt = fdt_get_address(); - fdt_fixups(fdt); - - return 0; -} - -/* Initialize the platform console. */ -static int ae350_console_init(void) -{ - return uart8250_init(AE350_UART_ADDR, - AE350_UART_FREQUENCY, - AE350_UART_BAUDRATE, - AE350_UART_REG_SHIFT, - AE350_UART_REG_WIDTH, - AE350_UART_REG_OFFSET); -} - -/* Initialize the platform interrupt controller for current HART. */ -static int ae350_irqchip_init(bool cold_boot) -{ - u32 hartid = current_hartid(); - int ret; - - if (cold_boot) { - ret = plic_cold_irqchip_init(&plic); - if (ret) - return ret; - } - - return plic_warm_irqchip_init(&plic, 2 * hartid, 2 * hartid + 1); -} - -static struct sbi_ipi_device plicsw_ipi = { - .name = "ae350_plicsw", - .ipi_send = plicsw_ipi_send, - .ipi_clear = plicsw_ipi_clear -}; - -/* Initialize IPI for current HART. */ -static int ae350_ipi_init(bool cold_boot) -{ - int ret; - - if (cold_boot) { - ret = plicsw_cold_ipi_init(AE350_PLICSW_ADDR, - AE350_HART_COUNT); - if (ret) - return ret; - - sbi_ipi_set_device(&plicsw_ipi); - } - - return plicsw_warm_ipi_init(); -} - -/* Initialize platform timer for current HART. */ -static int ae350_timer_init(bool cold_boot) -{ - int ret; - - if (cold_boot) { - ret = plmt_cold_timer_init(AE350_PLMT_ADDR, - AE350_HART_COUNT); - if (ret) - return ret; - } - - return plmt_warm_timer_init(); -} - -/* Vendor-Specific SBI handler */ -static int ae350_vendor_ext_provider(long extid, long funcid, - const struct sbi_trap_regs *regs, unsigned long *out_value, - struct sbi_trap_info *out_trap) -{ - int ret = 0; - switch (funcid) { - case SBI_EXT_ANDES_GET_MCACHE_CTL_STATUS: - *out_value = csr_read(CSR_MCACHECTL); - break; - case SBI_EXT_ANDES_GET_MMISC_CTL_STATUS: - *out_value = csr_read(CSR_MMISCCTL); - break; - case SBI_EXT_ANDES_SET_MCACHE_CTL: - ret = mcall_set_mcache_ctl(regs->a0); - break; - case SBI_EXT_ANDES_SET_MMISC_CTL: - ret = mcall_set_mmisc_ctl(regs->a0); - break; - case SBI_EXT_ANDES_ICACHE_OP: - ret = mcall_icache_op(regs->a0); - break; - case SBI_EXT_ANDES_DCACHE_OP: - ret = mcall_dcache_op(regs->a0); - break; - case SBI_EXT_ANDES_L1CACHE_I_PREFETCH: - ret = mcall_l1_cache_i_prefetch_op(regs->a0); - break; - case SBI_EXT_ANDES_L1CACHE_D_PREFETCH: - ret = mcall_l1_cache_d_prefetch_op(regs->a0); - break; - case SBI_EXT_ANDES_NON_BLOCKING_LOAD_STORE: - ret = mcall_non_blocking_load_store(regs->a0); - break; - case SBI_EXT_ANDES_WRITE_AROUND: - ret = mcall_write_around(regs->a0); - break; - default: - sbi_printf("Unsupported vendor sbi call : %ld\n", funcid); - asm volatile("ebreak"); - } - return ret; -} - -/* Platform descriptor. */ -const struct sbi_platform_operations platform_ops = { - .final_init = ae350_final_init, - - .console_init = ae350_console_init, - - .irqchip_init = ae350_irqchip_init, - - .ipi_init = ae350_ipi_init, - - .timer_init = ae350_timer_init, - - .vendor_ext_provider = ae350_vendor_ext_provider -}; - -const struct sbi_platform platform = { - .opensbi_version = OPENSBI_VERSION, - .platform_version = SBI_PLATFORM_VERSION(0x0, 0x01), - .name = "Andes AE350", - .features = SBI_PLATFORM_DEFAULT_FEATURES, - .hart_count = AE350_HART_COUNT, - .hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE, - .platform_ops_addr = (unsigned long)&platform_ops -}; diff -Nru opensbi-1.1/platform/andes/ae350/platform.h opensbi-1.3/platform/andes/ae350/platform.h --- opensbi-1.1/platform/andes/ae350/platform.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/andes/ae350/platform.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,126 +0,0 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 Andes Technology Corporation - * - * Authors: - * Zong Li - * Nylon Chen - */ - -#ifndef _AE350_PLATFORM_H_ -#define _AE350_PLATFORM_H_ - -#define AE350_HART_COUNT 4 - -#define AE350_PLIC_ADDR 0xe4000000 -#define AE350_PLIC_NUM_SOURCES 71 - -#define AE350_PLICSW_ADDR 0xe6400000 - -#define AE350_PLMT_ADDR 0xe6000000 - -#define AE350_L2C_ADDR 0xe0500000 - -#define AE350_UART_ADDR_OFFSET 0x20 -#define AE350_UART_ADDR (0xf0300000 + AE350_UART_ADDR_OFFSET) -#define AE350_UART_FREQUENCY 19660800 -#define AE350_UART_BAUDRATE 38400 -#define AE350_UART_REG_SHIFT 2 -#define AE350_UART_REG_WIDTH 0 -#define AE350_UART_REG_OFFSET 0 - -/*Memory and Miscellaneous Registers*/ -#define CSR_MILMB 0x7c0 -#define CSR_MDLMB 0x7c1 -#define CSR_MECC_CDOE 0x7c2 -#define CSR_MNVEC 0x7c3 -#define CSR_MPFTCTL 0x7c5 -#define CSR_MCACHECTL 0x7ca -#define CSR_MCCTLBEGINADDR 0x7cb -#define CSR_MCCTLCOMMAND 0x7cc -#define CSR_MCCTLDATA 0x7cc -#define CSR_SCCTLDATA 0x9cd -#define CSR_UCCTLBEGINADDR 0x80c -#define CSR_MMISCCTL 0x7d0 - -enum sbi_ext_andes_fid { - SBI_EXT_ANDES_GET_MCACHE_CTL_STATUS = 0, - SBI_EXT_ANDES_GET_MMISC_CTL_STATUS, - SBI_EXT_ANDES_SET_MCACHE_CTL, - SBI_EXT_ANDES_SET_MMISC_CTL, - SBI_EXT_ANDES_ICACHE_OP, - SBI_EXT_ANDES_DCACHE_OP, - SBI_EXT_ANDES_L1CACHE_I_PREFETCH, - SBI_EXT_ANDES_L1CACHE_D_PREFETCH, - SBI_EXT_ANDES_NON_BLOCKING_LOAD_STORE, - SBI_EXT_ANDES_WRITE_AROUND, -}; - -/* nds v5 mmisc_ctl register*/ -#define V5_MMISC_CTL_VEC_PLIC_OFFSET 1 -#define V5_MMISC_CTL_RVCOMPM_OFFSET 2 -#define V5_MMISC_CTL_BRPE_OFFSET 3 -#define V5_MMISC_CTL_MSA_OR_UNA_OFFSET 6 -#define V5_MMISC_CTL_NON_BLOCKING_OFFSET 8 -#define V5_MCACHE_CTL_L1I_PREFETCH_OFFSET 9 -#define V5_MCACHE_CTL_L1D_PREFETCH_OFFSET 10 -#define V5_MCACHE_CTL_DC_WAROUND_OFFSET_1 13 -#define V5_MCACHE_CTL_DC_WAROUND_OFFSET_2 14 - -#define V5_MMISC_CTL_VEC_PLIC_EN (1UL << V5_MMISC_CTL_VEC_PLIC_OFFSET) -#define V5_MMISC_CTL_RVCOMPM_EN (1UL << V5_MMISC_CTL_RVCOMPM_OFFSET) -#define V5_MMISC_CTL_BRPE_EN (1UL << V5_MMISC_CTL_BRPE_OFFSET) -#define V5_MMISC_CTL_MSA_OR_UNA_EN (1UL << V5_MMISC_CTL_MSA_OR_UNA_OFFSET) -#define V5_MMISC_CTL_NON_BLOCKING_EN (1UL << V5_MMISC_CTL_NON_BLOCKING_OFFSET) -#define V5_MCACHE_CTL_L1I_PREFETCH_EN (1UL << V5_MCACHE_CTL_L1I_PREFETCH_OFFSET) -#define V5_MCACHE_CTL_L1D_PREFETCH_EN (1UL << V5_MCACHE_CTL_L1D_PREFETCH_OFFSET) -#define V5_MCACHE_CTL_DC_WAROUND_1_EN (1UL << V5_MCACHE_CTL_DC_WAROUND_OFFSET_1) -#define V5_MCACHE_CTL_DC_WAROUND_2_EN (1UL << V5_MCACHE_CTL_DC_WAROUND_OFFSET_2) - -#define V5_MMISC_CTL_MASK (V5_MMISC_CTL_VEC_PLIC_EN | V5_MMISC_CTL_RVCOMPM_EN \ - | V5_MMISC_CTL_BRPE_EN | V5_MMISC_CTL_MSA_OR_UNA_EN | V5_MMISC_CTL_NON_BLOCKING_EN) - -/* nds mcache_ctl register*/ -#define V5_MCACHE_CTL_IC_EN_OFFSET 0 -#define V5_MCACHE_CTL_DC_EN_OFFSET 1 -#define V5_MCACHE_CTL_IC_ECCEN_OFFSET 2 -#define V5_MCACHE_CTL_DC_ECCEN_OFFSET 4 -#define V5_MCACHE_CTL_IC_RWECC_OFFSET 6 -#define V5_MCACHE_CTL_DC_RWECC_OFFSET 7 -#define V5_MCACHE_CTL_CCTL_SUEN_OFFSET 8 - -/*nds cctl command*/ -#define V5_UCCTL_L1D_WBINVAL_ALL 6 -#define V5_UCCTL_L1D_WB_ALL 7 - -#define V5_MCACHE_CTL_IC_EN (1UL << V5_MCACHE_CTL_IC_EN_OFFSET) -#define V5_MCACHE_CTL_DC_EN (1UL << V5_MCACHE_CTL_DC_EN_OFFSET) -#define V5_MCACHE_CTL_IC_RWECC (1UL << V5_MCACHE_CTL_IC_RWECC_OFFSET) -#define V5_MCACHE_CTL_DC_RWECC (1UL << V5_MCACHE_CTL_DC_RWECC_OFFSET) -#define V5_MCACHE_CTL_CCTL_SUEN (1UL << V5_MCACHE_CTL_CCTL_SUEN_OFFSET) - -#define V5_MCACHE_CTL_MASK (V5_MCACHE_CTL_IC_EN | V5_MCACHE_CTL_DC_EN \ - | V5_MCACHE_CTL_IC_RWECC | V5_MCACHE_CTL_DC_RWECC \ - | V5_MCACHE_CTL_CCTL_SUEN | V5_MCACHE_CTL_L1I_PREFETCH_EN \ - | V5_MCACHE_CTL_L1D_PREFETCH_EN | V5_MCACHE_CTL_DC_WAROUND_1_EN \ - | V5_MCACHE_CTL_DC_WAROUND_2_EN) - -#define V5_L2C_CTL_OFFSET 0x8 -#define V5_L2C_CTL_ENABLE_OFFSET 0 -#define V5_L2C_CTL_IPFDPT_OFFSET 3 -#define V5_L2C_CTL_DPFDPT_OFFSET 5 -#define V5_L2C_CTL_TRAMOCTL_OFFSET 8 -#define V5_L2C_CTL_TRAMICTL_OFFSET 10 -#define V5_L2C_CTL_DRAMOCTL_OFFSET 11 -#define V5_L2C_CTL_DRAMICTL_OFFSET 13 - -#define V5_L2C_CTL_ENABLE_MASK (1UL << V5_L2C_CTL_ENABLE_OFFSET) -#define V5_L2C_CTL_IPFDPT_MASK (3UL << V5_L2C_CTL_IPFDPT_OFFSET) -#define V5_L2C_CTL_DPFDPT_MASK (3UL << V5_L2C_CTL_DPFDPT_OFFSET) -#define V5_L2C_CTL_TRAMOCTL_MASK (3UL << V5_L2C_CTL_TRAMOCTL_OFFSET) -#define V5_L2C_CTL_TRAMICTL_MASK (1UL << V5_L2C_CTL_TRAMICTL_OFFSET) -#define V5_L2C_CTL_DRAMOCTL_MASK (3UL << V5_L2C_CTL_DRAMOCTL_OFFSET) -#define V5_L2C_CTL_DRAMICTL_MASK (1UL << V5_L2C_CTL_DRAMICTL_OFFSET) - -#endif /* _AE350_PLATFORM_H_ */ diff -Nru opensbi-1.1/platform/andes/ae350/plicsw.c opensbi-1.3/platform/andes/ae350/plicsw.c --- opensbi-1.1/platform/andes/ae350/plicsw.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/andes/ae350/plicsw.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,139 +0,0 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 Andes Technology Corporation - * - * Authors: - * Zong Li - * Nylon Chen - */ - -#include -#include -#include -#include "plicsw.h" -#include "platform.h" - -static u32 plicsw_ipi_hart_count; -static struct plicsw plicsw_dev[AE350_HART_COUNT]; - -static inline void plicsw_claim(void) -{ - u32 source_hart = current_hartid(); - - plicsw_dev[source_hart].source_id = - readl(plicsw_dev[source_hart].plicsw_claim); -} - -static inline void plicsw_complete(void) -{ - u32 source_hart = current_hartid(); - u32 source = plicsw_dev[source_hart].source_id; - - writel(source, plicsw_dev[source_hart].plicsw_claim); -} - -static inline void plic_sw_pending(u32 target_hart) -{ - /* - * The pending array registers are w1s type. - * IPI pending array mapping as following: - * - * Pending array start address: base + 0x1000 - * ------------------------------------- - * | hart 3 | hart 2 | hart 1 | hart 0 | - * ------------------------------------- - * Each hart X can send IPI to another hart by setting the - * corresponding bit in hart X own region(see the below). - * - * In each hart region: - * ----------------------------------------------- - * | bit 7 | bit 6 | bit 5 | bit 4 | ... | bit 0 | - * ----------------------------------------------- - * The bit 7 is used to send IPI to hart 0 - * The bit 6 is used to send IPI to hart 1 - * The bit 5 is used to send IPI to hart 2 - * The bit 4 is used to send IPI to hart 3 - */ - u32 source_hart = current_hartid(); - u32 target_offset = (PLICSW_PENDING_PER_HART - 1) - target_hart; - u32 per_hart_offset = PLICSW_PENDING_PER_HART * source_hart; - u32 val = 1 << target_offset << per_hart_offset; - - writel(val, plicsw_dev[source_hart].plicsw_pending); -} - -void plicsw_ipi_send(u32 target_hart) -{ - if (plicsw_ipi_hart_count <= target_hart) - return; - - /* Set PLICSW IPI */ - plic_sw_pending(target_hart); -} - -void plicsw_ipi_clear(u32 target_hart) -{ - if (plicsw_ipi_hart_count <= target_hart) - return; - - /* Clear PLICSW IPI */ - plicsw_claim(); - plicsw_complete(); -} - -int plicsw_warm_ipi_init(void) -{ - u32 hartid = current_hartid(); - - if (!plicsw_dev[hartid].plicsw_pending - && !plicsw_dev[hartid].plicsw_enable - && !plicsw_dev[hartid].plicsw_claim) - return -1; - - /* Clear PLICSW IPI */ - plicsw_ipi_clear(hartid); - - return 0; -} - -int plicsw_cold_ipi_init(unsigned long base, u32 hart_count) -{ - /* Setup source priority */ - uint32_t *priority = (void *)base + PLICSW_PRIORITY_BASE; - - for (int i = 0; i < AE350_HART_COUNT * PLICSW_PENDING_PER_HART; i++) - writel(1, &priority[i]); - - /* Setup target enable */ - uint32_t enable_mask = PLICSW_HART_MASK; - - for (int i = 0; i < AE350_HART_COUNT; i++) { - uint32_t *enable = (void *)base + PLICSW_ENABLE_BASE - + PLICSW_ENABLE_PER_HART * i; - writel(enable_mask, &enable[0]); - enable_mask >>= 1; - } - - /* Figure-out PLICSW IPI register address */ - plicsw_ipi_hart_count = hart_count; - - for (u32 hartid = 0; hartid < AE350_HART_COUNT; hartid++) { - plicsw_dev[hartid].source_id = 0; - plicsw_dev[hartid].plicsw_pending = - (void *)base - + PLICSW_PENDING_BASE - + ((hartid / 4) * 4); - plicsw_dev[hartid].plicsw_enable = - (void *)base - + PLICSW_ENABLE_BASE - + PLICSW_ENABLE_PER_HART * hartid; - plicsw_dev[hartid].plicsw_claim = - (void *)base - + PLICSW_CONTEXT_BASE - + PLICSW_CONTEXT_CLAIM - + PLICSW_CONTEXT_PER_HART * hartid; - } - - return 0; -} diff -Nru opensbi-1.1/platform/andes/ae350/plicsw.h opensbi-1.3/platform/andes/ae350/plicsw.h --- opensbi-1.1/platform/andes/ae350/plicsw.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/andes/ae350/plicsw.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,44 +0,0 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 Andes Technology Corporation - * - * Authors: - * Zong Li - * Nylon Chen - */ - -#ifndef _AE350_PLICSW_H_ -#define _AE350_PLICSW_H_ - -#define PLICSW_PRIORITY_BASE 0x4 - -#define PLICSW_PENDING_BASE 0x1000 -#define PLICSW_PENDING_PER_HART 0x8 - -#define PLICSW_ENABLE_BASE 0x2000 -#define PLICSW_ENABLE_PER_HART 0x80 - -#define PLICSW_CONTEXT_BASE 0x200000 -#define PLICSW_CONTEXT_PER_HART 0x1000 -#define PLICSW_CONTEXT_CLAIM 0x4 - -#define PLICSW_HART_MASK 0x80808080 - -struct plicsw { - u32 source_id; - - volatile uint32_t *plicsw_pending; - volatile uint32_t *plicsw_enable; - volatile uint32_t *plicsw_claim; -}; - -void plicsw_ipi_send(u32 target_hart); - -void plicsw_ipi_clear(u32 target_hart); - -int plicsw_warm_ipi_init(void); - -int plicsw_cold_ipi_init(unsigned long base, u32 hart_count); - -#endif /* _AE350_PLICSW_H_ */ diff -Nru opensbi-1.1/platform/andes/ae350/plmt.c opensbi-1.3/platform/andes/ae350/plmt.c --- opensbi-1.1/platform/andes/ae350/plmt.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/andes/ae350/plmt.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,107 +0,0 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 Andes Technology Corporation - * - * Authors: - * Zong Li - * Nylon Chen - */ - -#include -#include -#include - -static u32 plmt_time_hart_count; -static volatile void *plmt_time_base; -static volatile u64 *plmt_time_val; -static volatile u64 *plmt_time_cmp; - -static u64 plmt_timer_value(void) -{ -#if __riscv_xlen == 64 - return readq_relaxed(plmt_time_val); -#else - u32 lo, hi; - - do { - hi = readl_relaxed((void *)plmt_time_val + 0x04); - lo = readl_relaxed(plmt_time_val); - } while (hi != readl_relaxed((void *)plmt_time_val + 0x04)); - - return ((u64)hi << 32) | (u64)lo; -#endif -} - -static void plmt_timer_event_stop(void) -{ - u32 target_hart = current_hartid(); - - if (plmt_time_hart_count <= target_hart) - return; - - /* Clear PLMT Time Compare */ -#if __riscv_xlen == 64 - writeq_relaxed(-1ULL, &plmt_time_cmp[target_hart]); -#else - writel_relaxed(-1UL, &plmt_time_cmp[target_hart]); - writel_relaxed(-1UL, (void *)(&plmt_time_cmp[target_hart]) + 0x04); -#endif -} - -static void plmt_timer_event_start(u64 next_event) -{ - u32 target_hart = current_hartid(); - - if (plmt_time_hart_count <= target_hart) - return; - - /* Program PLMT Time Compare */ -#if __riscv_xlen == 64 - writeq_relaxed(next_event, &plmt_time_cmp[target_hart]); -#else - u32 mask = -1UL; - - writel_relaxed(next_event & mask, &plmt_time_cmp[target_hart]); - writel_relaxed(next_event >> 32, - (void *)(&plmt_time_cmp[target_hart]) + 0x04); -#endif - -} - -static struct sbi_timer_device plmt_timer = { - .name = "ae350_plmt", - .timer_value = plmt_timer_value, - .timer_event_start = plmt_timer_event_start, - .timer_event_stop = plmt_timer_event_stop -}; - -int plmt_warm_timer_init(void) -{ - u32 target_hart = current_hartid(); - - if (plmt_time_hart_count <= target_hart || !plmt_time_base) - return -1; - - /* Clear PLMT Time Compare */ -#if __riscv_xlen == 64 - writeq_relaxed(-1ULL, &plmt_time_cmp[target_hart]); -#else - writel_relaxed(-1UL, &plmt_time_cmp[target_hart]); - writel_relaxed(-1UL, (void *)(&plmt_time_cmp[target_hart]) + 0x04); -#endif - - return 0; -} - -int plmt_cold_timer_init(unsigned long base, u32 hart_count) -{ - plmt_time_hart_count = hart_count; - plmt_time_base = (void *)base; - plmt_time_val = (u64 *)(plmt_time_base); - plmt_time_cmp = (u64 *)(plmt_time_base + 0x8); - - sbi_timer_set_device(&plmt_timer); - - return 0; -} diff -Nru opensbi-1.1/platform/andes/ae350/plmt.h opensbi-1.3/platform/andes/ae350/plmt.h --- opensbi-1.1/platform/andes/ae350/plmt.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/andes/ae350/plmt.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,17 +0,0 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 Andes Technology Corporation - * - * Authors: - * Zong Li - */ - -#ifndef _AE350_PLMT_H_ -#define _AE350_PLMT_H_ - -int plmt_warm_timer_init(void); - -int plmt_cold_timer_init(unsigned long base, u32 hart_count); - -#endif /* _AE350_PLMT_H_ */ diff -Nru opensbi-1.1/platform/fpga/ariane/config.mk opensbi-1.3/platform/fpga/ariane/config.mk --- opensbi-1.1/platform/fpga/ariane/config.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/fpga/ariane/config.mk 1970-01-01 01:00:00.000000000 +0100 @@ -1,36 +0,0 @@ -# -# SPDX-License-Identifier: BSD-2-Clause -# -# Copyright (C) 2019 FORTH-ICS/CARV -# Panagiotis Peristerakis -# - -#for more infos, check out /platform/template/config.mk - -PLATFORM_RISCV_XLEN = 64 - -# Blobs to build -FW_TEXT_START=0x80000000 -FW_JUMP=n - -ifeq ($(PLATFORM_RISCV_XLEN), 32) - # This needs to be 4MB aligned for 32-bit support - FW_JUMP_ADDR=0x80400000 - else - # This needs to be 2MB aligned for 64-bit support - FW_JUMP_ADDR=0x80200000 - endif -FW_JUMP_FDT_ADDR=0x82200000 - -# Firmware with payload configuration. -FW_PAYLOAD=y - -ifeq ($(PLATFORM_RISCV_XLEN), 32) -# This needs to be 4MB aligned for 32-bit support - FW_PAYLOAD_OFFSET=0x400000 -else -# This needs to be 2MB aligned for 64-bit support - FW_PAYLOAD_OFFSET=0x200000 -endif -FW_PAYLOAD_FDT_ADDR=0x82200000 -FW_PAYLOAD_ALIGN=0x1000 diff -Nru opensbi-1.1/platform/fpga/ariane/Kconfig opensbi-1.3/platform/fpga/ariane/Kconfig --- opensbi-1.1/platform/fpga/ariane/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/platform/fpga/ariane/Kconfig 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-2-Clause + +config PLATFORM_ARIANE_FPGA + bool + select FDT + select IPI_MSWI + select IRQCHIP_PLIC + select SERIAL_UART8250 + select TIMER_MTIMER + default y diff -Nru opensbi-1.1/platform/fpga/ariane/objects.mk opensbi-1.3/platform/fpga/ariane/objects.mk --- opensbi-1.1/platform/fpga/ariane/objects.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/fpga/ariane/objects.mk 2023-06-23 07:31:49.000000000 +0200 @@ -5,4 +5,39 @@ # Panagiotis Peristerakis # +# Compiler flags +platform-cppflags-y = +platform-cflags-y = +platform-asflags-y = +platform-ldflags-y = + +# Object to build platform-objs-y += platform.o + +PLATFORM_RISCV_XLEN = 64 + +# Blobs to build +FW_TEXT_START=0x80000000 +FW_JUMP=n + +ifeq ($(PLATFORM_RISCV_XLEN), 32) + # This needs to be 4MB aligned for 32-bit support + FW_JUMP_ADDR=0x80400000 + else + # This needs to be 2MB aligned for 64-bit support + FW_JUMP_ADDR=0x80200000 + endif +FW_JUMP_FDT_ADDR=0x82200000 + +# Firmware with payload configuration. +FW_PAYLOAD=y + +ifeq ($(PLATFORM_RISCV_XLEN), 32) +# This needs to be 4MB aligned for 32-bit support + FW_PAYLOAD_OFFSET=0x400000 +else +# This needs to be 2MB aligned for 64-bit support + FW_PAYLOAD_OFFSET=0x200000 +endif +FW_PAYLOAD_FDT_ADDR=0x82200000 +FW_PAYLOAD_ALIGN=0x1000 diff -Nru opensbi-1.1/platform/fpga/ariane/platform.c opensbi-1.3/platform/fpga/ariane/platform.c --- opensbi-1.1/platform/fpga/ariane/platform.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/fpga/ariane/platform.c 2023-06-23 07:31:49.000000000 +0200 @@ -56,7 +56,7 @@ .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE, .first_hartid = 0, .hart_count = ARIANE_HART_COUNT, - .has_64bit_mmio = TRUE, + .has_64bit_mmio = true, }; /* @@ -185,5 +185,6 @@ .features = SBI_PLATFORM_DEFAULT_FEATURES, .hart_count = ARIANE_HART_COUNT, .hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE, + .heap_size = SBI_PLATFORM_DEFAULT_HEAP_SIZE(ARIANE_HART_COUNT), .platform_ops_addr = (unsigned long)&platform_ops }; diff -Nru opensbi-1.1/platform/fpga/openpiton/config.mk opensbi-1.3/platform/fpga/openpiton/config.mk --- opensbi-1.1/platform/fpga/openpiton/config.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/fpga/openpiton/config.mk 1970-01-01 01:00:00.000000000 +0100 @@ -1,35 +0,0 @@ -# -# SPDX-License-Identifier: BSD-2-Clause -# -# Copyright (c) 2020 Western Digital Corporation or its affiliates. -# - -#for more infos, check out /platform/template/config.mk - -PLATFORM_RISCV_XLEN = 64 - -# Blobs to build -FW_TEXT_START=0x80000000 -FW_JUMP=n - -ifeq ($(PLATFORM_RISCV_XLEN), 32) - # This needs to be 4MB aligned for 32-bit support - FW_JUMP_ADDR=0x80400000 - else - # This needs to be 2MB aligned for 64-bit support - FW_JUMP_ADDR=0x80200000 - endif -FW_JUMP_FDT_ADDR=0x82200000 - -# Firmware with payload configuration. -FW_PAYLOAD=y - -ifeq ($(PLATFORM_RISCV_XLEN), 32) -# This needs to be 4MB aligned for 32-bit support - FW_PAYLOAD_OFFSET=0x400000 -else -# This needs to be 2MB aligned for 64-bit support - FW_PAYLOAD_OFFSET=0x200000 -endif -FW_PAYLOAD_FDT_ADDR=0x82200000 -FW_PAYLOAD_ALIGN=0x1000 diff -Nru opensbi-1.1/platform/fpga/openpiton/Kconfig opensbi-1.3/platform/fpga/openpiton/Kconfig --- opensbi-1.1/platform/fpga/openpiton/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/platform/fpga/openpiton/Kconfig 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-2-Clause + +config PLATFORM_OPENPITON_FPGA + bool + select FDT + select IPI_MSWI + select IRQCHIP_PLIC + select SERIAL_UART8250 + select TIMER_MTIMER + default y diff -Nru opensbi-1.1/platform/fpga/openpiton/objects.mk opensbi-1.3/platform/fpga/openpiton/objects.mk --- opensbi-1.1/platform/fpga/openpiton/objects.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/fpga/openpiton/objects.mk 2023-06-23 07:31:49.000000000 +0200 @@ -4,4 +4,39 @@ # Copyright (c) 2020 Western Digital Corporation or its affiliates. # +# Compiler flags +platform-cppflags-y = +platform-cflags-y = +platform-asflags-y = +platform-ldflags-y = + +# Objects to build platform-objs-y += platform.o + +PLATFORM_RISCV_XLEN = 64 + +# Blobs to build +FW_TEXT_START=0x80000000 +FW_JUMP=n + +ifeq ($(PLATFORM_RISCV_XLEN), 32) + # This needs to be 4MB aligned for 32-bit support + FW_JUMP_ADDR=0x80400000 + else + # This needs to be 2MB aligned for 64-bit support + FW_JUMP_ADDR=0x80200000 + endif +FW_JUMP_FDT_ADDR=0x82200000 + +# Firmware with payload configuration. +FW_PAYLOAD=y + +ifeq ($(PLATFORM_RISCV_XLEN), 32) +# This needs to be 4MB aligned for 32-bit support + FW_PAYLOAD_OFFSET=0x400000 +else +# This needs to be 2MB aligned for 64-bit support + FW_PAYLOAD_OFFSET=0x200000 +endif +FW_PAYLOAD_FDT_ADDR=0x82200000 +FW_PAYLOAD_ALIGN=0x1000 diff -Nru opensbi-1.1/platform/fpga/openpiton/platform.c opensbi-1.3/platform/fpga/openpiton/platform.c --- opensbi-1.1/platform/fpga/openpiton/platform.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/fpga/openpiton/platform.c 2023-06-23 07:31:49.000000000 +0200 @@ -60,7 +60,7 @@ .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE, .first_hartid = 0, .hart_count = OPENPITON_DEFAULT_HART_COUNT, - .has_64bit_mmio = TRUE, + .has_64bit_mmio = true, }; /* @@ -69,7 +69,7 @@ static int openpiton_early_init(bool cold_boot) { void *fdt; - struct platform_uart_data uart_data; + struct platform_uart_data uart_data = { 0 }; struct plic_data plic_data; unsigned long aclint_freq; uint64_t clint_addr; @@ -220,5 +220,7 @@ .features = SBI_PLATFORM_DEFAULT_FEATURES, .hart_count = OPENPITON_DEFAULT_HART_COUNT, .hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE, + .heap_size = + SBI_PLATFORM_DEFAULT_HEAP_SIZE(OPENPITON_DEFAULT_HART_COUNT), .platform_ops_addr = (unsigned long)&platform_ops }; diff -Nru opensbi-1.1/platform/generic/allwinner/objects.mk opensbi-1.3/platform/generic/allwinner/objects.mk --- opensbi-1.1/platform/generic/allwinner/objects.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/generic/allwinner/objects.mk 2023-06-23 07:31:49.000000000 +0200 @@ -2,5 +2,5 @@ # SPDX-License-Identifier: BSD-2-Clause # -carray-platform_override_modules-y += sun20i_d1 -platform-objs-y += allwinner/sun20i-d1.o +carray-platform_override_modules-$(CONFIG_PLATFORM_ALLWINNER_D1) += sun20i_d1 +platform-objs-$(CONFIG_PLATFORM_ALLWINNER_D1) += allwinner/sun20i-d1.o diff -Nru opensbi-1.1/platform/generic/allwinner/sun20i-d1.c opensbi-1.3/platform/generic/allwinner/sun20i-d1.c --- opensbi-1.1/platform/generic/allwinner/sun20i-d1.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/generic/allwinner/sun20i-d1.c 2023-06-23 07:31:49.000000000 +0200 @@ -5,11 +5,16 @@ */ #include +#include +#include #include #include #include #include #include +#include +#include +#include #include #include @@ -67,24 +72,25 @@ * PLIC */ -#define PLIC_SOURCES 176 -#define PLIC_IE_WORDS ((PLIC_SOURCES + 31) / 32) +#define PLIC_SOURCES 175 +#define PLIC_IE_WORDS (PLIC_SOURCES / 32 + 1) -static u8 plic_priority[PLIC_SOURCES]; +static u8 plic_priority[1 + PLIC_SOURCES]; static u32 plic_sie[PLIC_IE_WORDS]; static u32 plic_threshold; static void sun20i_d1_plic_save(void) { - fdt_plic_context_save(true, plic_sie, &plic_threshold); - fdt_plic_priority_save(plic_priority); + fdt_plic_context_save(true, plic_sie, &plic_threshold, PLIC_IE_WORDS); + fdt_plic_priority_save(plic_priority, PLIC_SOURCES); } static void sun20i_d1_plic_restore(void) { thead_plic_restore(); - fdt_plic_priority_restore(plic_priority); - fdt_plic_context_restore(true, plic_sie, plic_threshold); + fdt_plic_priority_restore(plic_priority, PLIC_SOURCES); + fdt_plic_context_restore(true, plic_sie, plic_threshold, + PLIC_IE_WORDS); } /* @@ -144,14 +150,14 @@ static void sun20i_d1_riscv_cfg_init(void) { - unsigned long entry = sbi_hartid_to_scratch(0)->warmboot_addr; + u64 entry = sbi_hartid_to_scratch(0)->warmboot_addr; /* Enable MMIO access. */ writel_relaxed(CCU_BGR_ENABLE, SUN20I_D1_CCU_BASE + RISCV_CFG_BGR_REG); /* Program the reset entry address. */ - writel_relaxed((u32)entry, SUN20I_D1_RISCV_CFG_BASE + RESET_ENTRY_LO_REG); - writel_relaxed((u64)entry >> 32, SUN20I_D1_RISCV_CFG_BASE + RESET_ENTRY_HI_REG); + writel_relaxed(entry, SUN20I_D1_RISCV_CFG_BASE + RESET_ENTRY_LO_REG); + writel_relaxed(entry >> 32, SUN20I_D1_RISCV_CFG_BASE + RESET_ENTRY_HI_REG); } static int sun20i_d1_hart_suspend(u32 suspend_type) @@ -199,6 +205,79 @@ return 0; } +static const struct sbi_cpu_idle_state sun20i_d1_cpu_idle_states[] = { + { + .name = "cpu-nonretentive", + .suspend_param = SBI_HSM_SUSPEND_NON_RET_DEFAULT, + .local_timer_stop = true, + .entry_latency_us = 40, + .exit_latency_us = 67, + .min_residency_us = 1100, + .wakeup_latency_us = 67, + }, + { } +}; + +static int sun20i_d1_fdt_fixup(void *fdt, const struct fdt_match *match) +{ + return fdt_add_cpu_idle_states(fdt, sun20i_d1_cpu_idle_states); +} + +static void thead_c9xx_pmu_ctr_enable_irq(uint32_t ctr_idx) +{ + unsigned long mip_val; + + if (ctr_idx >= SBI_PMU_HW_CTR_MAX) + return; + + mip_val = csr_read(CSR_MIP); + /** + * Clear out the OF bit so that next interrupt can be enabled. + * This should be done only when the corresponding overflow interrupt + * bit is cleared. That indicates that software has already handled the + * previous interrupts or the hardware yet to set an overflow interrupt. + * Otherwise, there will be race conditions where we may clear the bit + * the software is yet to handle the interrupt. + */ + if (!(mip_val & THEAD_C9XX_MIP_MOIP)) + csr_clear(THEAD_C9XX_CSR_MCOUNTEROF, BIT(ctr_idx)); + + /** + * SSCOFPMF uses the OF bit for enabling/disabling the interrupt, + * while the C9XX has designated enable bits. + * So enable per-counter interrupt on C9xx here. + */ + csr_set(THEAD_C9XX_CSR_MCOUNTERINTEN, BIT(ctr_idx)); +} + +static void thead_c9xx_pmu_ctr_disable_irq(uint32_t ctr_idx) +{ + csr_clear(THEAD_C9XX_CSR_MCOUNTERINTEN, BIT(ctr_idx)); +} + +static int thead_c9xx_pmu_irq_bit(void) +{ + return THEAD_C9XX_MIP_MOIP; +} + +const struct sbi_pmu_device thead_c9xx_pmu_device = { + .hw_counter_enable_irq = thead_c9xx_pmu_ctr_enable_irq, + .hw_counter_disable_irq = thead_c9xx_pmu_ctr_disable_irq, + .hw_counter_irq_bit = thead_c9xx_pmu_irq_bit, +}; + +static int sun20i_d1_extensions_init(const struct fdt_match *match, + struct sbi_hart_features *hfeatures) +{ + sbi_pmu_set_device(&thead_c9xx_pmu_device); + + /* auto-detection doesn't work on t-head c9xx cores */ + hfeatures->mhpm_count = 29; + hfeatures->mhpm_bits = 64; + + return 0; +} + static const struct fdt_match sun20i_d1_match[] = { { .compatible = "allwinner,sun20i-d1" }, { }, @@ -207,4 +286,6 @@ const struct platform_override sun20i_d1 = { .match_table = sun20i_d1_match, .final_init = sun20i_d1_final_init, + .fdt_fixup = sun20i_d1_fdt_fixup, + .extensions_init = sun20i_d1_extensions_init, }; diff -Nru opensbi-1.1/platform/generic/andes/ae350.c opensbi-1.3/platform/generic/andes/ae350.c --- opensbi-1.1/platform/generic/andes/ae350.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/platform/generic/andes/ae350.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,121 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Andes Technology Corporation + * + * Authors: + * Yu Chien Peter Lin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct smu_data smu = { 0 }; +extern void __ae350_enable_coherency_warmboot(void); +extern void __ae350_disable_coherency(void); + +static __always_inline bool is_andes25(void) +{ + ulong marchid = csr_read(CSR_MARCHID); + return !!(EXTRACT_FIELD(marchid, CSR_MARCHID_MICROID) == 0xa25); +} + +static int ae350_hart_start(u32 hartid, ulong saddr) +{ + /* Don't send wakeup command at boot-time */ + if (!sbi_init_count(hartid) || (is_andes25() && hartid == 0)) + return sbi_ipi_raw_send(hartid); + + /* Write wakeup command to the sleep hart */ + smu_set_command(&smu, WAKEUP_CMD, hartid); + + return 0; +} + +static int ae350_hart_stop(void) +{ + int rc; + u32 hartid = current_hartid(); + + /** + * For Andes AX25MP, the hart0 shares power domain with + * L2-cache, instead of turning it off, it should fall + * through and jump to warmboot_addr. + */ + if (is_andes25() && hartid == 0) + return SBI_ENOTSUPP; + + if (!smu_support_sleep_mode(&smu, DEEPSLEEP_MODE, hartid)) + return SBI_ENOTSUPP; + + /** + * disable all events, the current hart will be + * woken up from reset vector when other hart + * writes its PCS (power control slot) control + * register + */ + smu_set_wakeup_events(&smu, 0x0, hartid); + smu_set_command(&smu, DEEP_SLEEP_CMD, hartid); + + rc = smu_set_reset_vector(&smu, (ulong)__ae350_enable_coherency_warmboot, + hartid); + if (rc) + goto fail; + + __ae350_disable_coherency(); + + wfi(); + +fail: + /* It should never reach here */ + sbi_hart_hang(); + return 0; +} + +static const struct sbi_hsm_device andes_smu = { + .name = "andes_smu", + .hart_start = ae350_hart_start, + .hart_stop = ae350_hart_stop, +}; + +static void ae350_hsm_device_init(void) +{ + int rc; + void *fdt; + + fdt = fdt_get_address(); + + rc = fdt_parse_compat_addr(fdt, (uint64_t *)&smu.addr, + "andestech,atcsmu"); + + if (!rc) { + sbi_hsm_set_device(&andes_smu); + } +} + +static int ae350_final_init(bool cold_boot, const struct fdt_match *match) +{ + if (cold_boot) + ae350_hsm_device_init(); + + return 0; +} + +static const struct fdt_match andes_ae350_match[] = { + { .compatible = "andestech,ae350" }, + { }, +}; + +const struct platform_override andes_ae350 = { + .match_table = andes_ae350_match, + .final_init = ae350_final_init, +}; diff -Nru opensbi-1.1/platform/generic/andes/andes45-pma.c opensbi-1.3/platform/generic/andes/andes45-pma.c --- opensbi-1.1/platform/generic/andes/andes45-pma.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/platform/generic/andes/andes45-pma.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,350 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Renesas Electronics Corp. + * + * Copyright (c) 2020 Andes Technology Corporation + * + * Authors: + * Nick Hu + * Nylon Chen + * Lad Prabhakar + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Configuration Registers */ +#define ANDES45_CSR_MMSC_CFG 0xFC2 +#define ANDES45_CSR_MMSC_PPMA_OFFSET (1 << 30) + +#define ANDES45_PMAADDR_0 0xBD0 + +#define ANDES45_PMACFG_0 0xBC0 + +static inline unsigned long andes45_pma_read_cfg(unsigned int pma_cfg_off) +{ +#define switchcase_pma_cfg_read(__pma_cfg_off, __val) \ + case __pma_cfg_off: \ + __val = csr_read(__pma_cfg_off); \ + break; +#define switchcase_pma_cfg_read_2(__pma_cfg_off, __val) \ + switchcase_pma_cfg_read(__pma_cfg_off + 0, __val) \ + switchcase_pma_cfg_read(__pma_cfg_off + 2, __val) + + unsigned long ret = 0; + + switch (pma_cfg_off) { + switchcase_pma_cfg_read_2(ANDES45_PMACFG_0, ret) + + default: + sbi_panic("%s: Unknown PMA CFG offset %#x", __func__, pma_cfg_off); + break; + } + + return ret; + +#undef switchcase_pma_cfg_read_2 +#undef switchcase_pma_cfg_read +} + +static inline void andes45_pma_write_cfg(unsigned int pma_cfg_off, unsigned long val) +{ +#define switchcase_pma_cfg_write(__pma_cfg_off, __val) \ + case __pma_cfg_off: \ + csr_write(__pma_cfg_off, __val); \ + break; +#define switchcase_pma_cfg_write_2(__pma_cfg_off, __val) \ + switchcase_pma_cfg_write(__pma_cfg_off + 0, __val) \ + switchcase_pma_cfg_write(__pma_cfg_off + 2, __val) + + switch (pma_cfg_off) { + switchcase_pma_cfg_write_2(ANDES45_PMACFG_0, val) + + default: + sbi_panic("%s: Unknown PMA CFG offset %#x", __func__, pma_cfg_off); + break; + } + +#undef switchcase_pma_cfg_write_2 +#undef switchcase_pma_cfg_write +} + +static inline void andes45_pma_write_addr(unsigned int pma_addr_off, unsigned long val) +{ +#define switchcase_pma_write(__pma_addr_off, __val) \ + case __pma_addr_off: \ + csr_write(__pma_addr_off, __val); \ + break; +#define switchcase_pma_write_2(__pma_addr_off, __val) \ + switchcase_pma_write(__pma_addr_off + 0, __val) \ + switchcase_pma_write(__pma_addr_off + 1, __val) +#define switchcase_pma_write_4(__pma_addr_off, __val) \ + switchcase_pma_write_2(__pma_addr_off + 0, __val) \ + switchcase_pma_write_2(__pma_addr_off + 2, __val) +#define switchcase_pma_write_8(__pma_addr_off, __val) \ + switchcase_pma_write_4(__pma_addr_off + 0, __val) \ + switchcase_pma_write_4(__pma_addr_off + 4, __val) +#define switchcase_pma_write_16(__pma_addr_off, __val) \ + switchcase_pma_write_8(__pma_addr_off + 0, __val) \ + switchcase_pma_write_8(__pma_addr_off + 8, __val) + + switch (pma_addr_off) { + switchcase_pma_write_16(ANDES45_PMAADDR_0, val) + + default: + sbi_panic("%s: Unknown PMA ADDR offset %#x", __func__, pma_addr_off); + break; + } + +#undef switchcase_pma_write_16 +#undef switchcase_pma_write_8 +#undef switchcase_pma_write_4 +#undef switchcase_pma_write_2 +#undef switchcase_pma_write +} + +static inline unsigned long andes45_pma_read_addr(unsigned int pma_addr_off) +{ +#define switchcase_pma_read(__pma_addr_off, __val) \ + case __pma_addr_off: \ + __val = csr_read(__pma_addr_off); \ + break; +#define switchcase_pma_read_2(__pma_addr_off, __val) \ + switchcase_pma_read(__pma_addr_off + 0, __val) \ + switchcase_pma_read(__pma_addr_off + 1, __val) +#define switchcase_pma_read_4(__pma_addr_off, __val) \ + switchcase_pma_read_2(__pma_addr_off + 0, __val) \ + switchcase_pma_read_2(__pma_addr_off + 2, __val) +#define switchcase_pma_read_8(__pma_addr_off, __val) \ + switchcase_pma_read_4(__pma_addr_off + 0, __val) \ + switchcase_pma_read_4(__pma_addr_off + 4, __val) +#define switchcase_pma_read_16(__pma_addr_off, __val) \ + switchcase_pma_read_8(__pma_addr_off + 0, __val) \ + switchcase_pma_read_8(__pma_addr_off + 8, __val) + + unsigned long ret = 0; + + switch (pma_addr_off) { + switchcase_pma_read_16(ANDES45_PMAADDR_0, ret) + + default: + sbi_panic("%s: Unknown PMA ADDR offset %#x", __func__, pma_addr_off); + break; + } + + return ret; + +#undef switchcase_pma_read_16 +#undef switchcase_pma_read_8 +#undef switchcase_pma_read_4 +#undef switchcase_pma_read_2 +#undef switchcase_pma_read +} + +static unsigned long +andes45_pma_setup(const struct andes45_pma_region *pma_region, + unsigned int entry_id) +{ + unsigned long size = pma_region->size; + unsigned long addr = pma_region->pa; + unsigned int pma_cfg_addr; + unsigned long pmacfg_val; + unsigned long pmaaddr; + char *pmaxcfg; + + /* Check for 4KiB granularity */ + if (size < (1 << 12)) + return SBI_EINVAL; + + /* Check size is power of 2 */ + if (size & (size - 1)) + return SBI_EINVAL; + + if (entry_id > 15) + return SBI_EINVAL; + + if (!(pma_region->flags & ANDES45_PMACFG_ETYP_NAPOT)) + return SBI_EINVAL; + + if ((addr & (size - 1)) != 0) + return SBI_EINVAL; + + pma_cfg_addr = entry_id / 8 ? ANDES45_PMACFG_0 + 2 : ANDES45_PMACFG_0; + pmacfg_val = andes45_pma_read_cfg(pma_cfg_addr); + pmaxcfg = (char *)&pmacfg_val + (entry_id % 8); + *pmaxcfg = 0; + *pmaxcfg = pma_region->flags; + + andes45_pma_write_cfg(pma_cfg_addr, pmacfg_val); + + pmaaddr = (addr >> 2) + (size >> 3) - 1; + + andes45_pma_write_addr(ANDES45_PMAADDR_0 + entry_id, pmaaddr); + + return andes45_pma_read_addr(ANDES45_PMAADDR_0 + entry_id) == pmaaddr ? + pmaaddr : SBI_EINVAL; +} + +static int andes45_fdt_pma_resv(void *fdt, const struct andes45_pma_region *pma, + unsigned int index, int parent) +{ + int na = fdt_address_cells(fdt, 0); + int ns = fdt_size_cells(fdt, 0); + static bool dma_default = false; + fdt32_t addr_high, addr_low; + fdt32_t size_high, size_low; + int subnode, err; + fdt32_t reg[4]; + fdt32_t *val; + char name[32]; + + addr_high = (u64)pma->pa >> 32; + addr_low = pma->pa; + size_high = (u64)pma->size >> 32; + size_low = pma->size; + + if (na > 1 && addr_high) + sbi_snprintf(name, sizeof(name), + "pma_resv%d@%x,%x", index, + addr_high, addr_low); + else + sbi_snprintf(name, sizeof(name), + "pma_resv%d@%x", index, + addr_low); + + subnode = fdt_add_subnode(fdt, parent, name); + if (subnode < 0) + return subnode; + + if (pma->shared_dma) { + err = fdt_setprop_string(fdt, subnode, "compatible", "shared-dma-pool"); + if (err < 0) + return err; + } + + if (pma->no_map) { + err = fdt_setprop_empty(fdt, subnode, "no-map"); + if (err < 0) + return err; + } + + /* Linux allows single linux,dma-default region. */ + if (pma->dma_default) { + if (dma_default) + return SBI_EINVAL; + + err = fdt_setprop_empty(fdt, subnode, "linux,dma-default"); + if (err < 0) + return err; + dma_default = true; + } + + /* encode the property value */ + val = reg; + if (na > 1) + *val++ = cpu_to_fdt32(addr_high); + *val++ = cpu_to_fdt32(addr_low); + if (ns > 1) + *val++ = cpu_to_fdt32(size_high); + *val++ = cpu_to_fdt32(size_low); + + err = fdt_setprop(fdt, subnode, "reg", reg, + (na + ns) * sizeof(fdt32_t)); + if (err < 0) + return err; + + return 0; +} + +static int andes45_fdt_reserved_memory_fixup(void *fdt, + const struct andes45_pma_region *pma, + unsigned int entry) +{ + int parent; + + /* try to locate the reserved memory node */ + parent = fdt_path_offset(fdt, "/reserved-memory"); + if (parent < 0) { + int na = fdt_address_cells(fdt, 0); + int ns = fdt_size_cells(fdt, 0); + int err; + + /* if such node does not exist, create one */ + parent = fdt_add_subnode(fdt, 0, "reserved-memory"); + if (parent < 0) + return parent; + + err = fdt_setprop_empty(fdt, parent, "ranges"); + if (err < 0) + return err; + + err = fdt_setprop_u32(fdt, parent, "#size-cells", ns); + if (err < 0) + return err; + + err = fdt_setprop_u32(fdt, parent, "#address-cells", na); + if (err < 0) + return err; + } + + return andes45_fdt_pma_resv(fdt, pma, entry, parent); +} + +int andes45_pma_setup_regions(const struct andes45_pma_region *pma_regions, + unsigned int pma_regions_count) +{ + unsigned long mmsc = csr_read(ANDES45_CSR_MMSC_CFG); + unsigned int dt_populate_cnt; + unsigned int i, j; + unsigned long pa; + void *fdt; + int ret; + + if (!pma_regions || !pma_regions_count) + return 0; + + if (pma_regions_count > ANDES45_MAX_PMA_REGIONS) + return SBI_EINVAL; + + if ((mmsc & ANDES45_CSR_MMSC_PPMA_OFFSET) == 0) + return SBI_ENOTSUPP; + + /* Configure the PMA regions */ + for (i = 0; i < pma_regions_count; i++) { + pa = andes45_pma_setup(&pma_regions[i], i); + if (pa == SBI_EINVAL) + return SBI_EINVAL; + } + + dt_populate_cnt = 0; + for (i = 0; i < pma_regions_count; i++) { + if (!pma_regions[i].dt_populate) + continue; + dt_populate_cnt++; + } + + if (!dt_populate_cnt) + return 0; + + fdt = fdt_get_address(); + + ret = fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + (64 * dt_populate_cnt)); + if (ret < 0) + return ret; + + for (i = 0, j = 0; i < pma_regions_count; i++) { + if (!pma_regions[i].dt_populate) + continue; + + ret = andes45_fdt_reserved_memory_fixup(fdt, &pma_regions[i], j++); + if (ret) + return ret; + } + + return 0; +} diff -Nru opensbi-1.1/platform/generic/andes/andes_sbi.c opensbi-1.3/platform/generic/andes/andes_sbi.c --- opensbi-1.1/platform/generic/andes/andes_sbi.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/platform/generic/andes/andes_sbi.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2023 Renesas Electronics Corp. + * + */ +#include +#include +#include +#include + +enum sbi_ext_andes_fid { + SBI_EXT_ANDES_FID0 = 0, /* Reserved for future use */ + SBI_EXT_ANDES_IOCP_SW_WORKAROUND, +}; + +static bool andes45_cache_controllable(void) +{ + return (((csr_read(CSR_MICM_CFG) & MICM_CFG_ISZ_MASK) || + (csr_read(CSR_MDCM_CFG) & MDCM_CFG_DSZ_MASK)) && + (csr_read(CSR_MMSC_CFG) & MMSC_CFG_CCTLCSR_MASK) && + (csr_read(CSR_MCACHE_CTL) & MCACHE_CTL_CCTL_SUEN_MASK) && + misa_extension('U')); +} + +static bool andes45_iocp_disabled(void) +{ + return (csr_read(CSR_MMSC_CFG) & MMSC_IOCP_MASK) ? false : true; +} + +static bool andes45_apply_iocp_sw_workaround(void) +{ + return andes45_cache_controllable() & andes45_iocp_disabled(); +} + +int andes_sbi_vendor_ext_provider(long funcid, + const struct sbi_trap_regs *regs, + unsigned long *out_value, + struct sbi_trap_info *out_trap, + const struct fdt_match *match) +{ + switch (funcid) { + case SBI_EXT_ANDES_IOCP_SW_WORKAROUND: + *out_value = andes45_apply_iocp_sw_workaround(); + break; + + default: + return SBI_EINVAL; + } + + return 0; +} diff -Nru opensbi-1.1/platform/generic/andes/Kconfig opensbi-1.3/platform/generic/andes/Kconfig --- opensbi-1.1/platform/generic/andes/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/platform/generic/andes/Kconfig 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: BSD-2-Clause + +config ANDES45_PMA + bool "Andes PMA support" + default n + +config ANDES_SBI + bool "Andes SBI support" + default n diff -Nru opensbi-1.1/platform/generic/andes/objects.mk opensbi-1.3/platform/generic/andes/objects.mk --- opensbi-1.1/platform/generic/andes/objects.mk 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/platform/generic/andes/objects.mk 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,9 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# + +carray-platform_override_modules-$(CONFIG_PLATFORM_ANDES_AE350) += andes_ae350 +platform-objs-$(CONFIG_PLATFORM_ANDES_AE350) += andes/ae350.o andes/sleep.o + +platform-objs-$(CONFIG_ANDES45_PMA) += andes/andes45-pma.o +platform-objs-$(CONFIG_ANDES_SBI) += andes/andes_sbi.o diff -Nru opensbi-1.1/platform/generic/andes/sleep.S opensbi-1.3/platform/generic/andes/sleep.S --- opensbi-1.1/platform/generic/andes/sleep.S 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/platform/generic/andes/sleep.S 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,70 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Andes Technology Corporation + * + * Authors: + * Yu Chien Peter Lin + */ + +#include +#include +#include + + .section .text, "ax", %progbits + .align 3 + .global __ae350_disable_coherency +__ae350_disable_coherency: + /* flush d-cache */ + csrw CSR_MCCTLCOMMAND, 0x6 + /* disable i/d-cache */ + csrc CSR_MCACHE_CTL, 0x3 + /* disable d-cache coherency */ + lui t1, 0x80 + csrc CSR_MCACHE_CTL, t1 + /* + * wait for mcache_ctl.DC_COHSTA to be cleared, + * the bit is hard-wired 0 on platforms w/o CM + * (Coherence Manager) + */ +check_cm_disabled: + csrr t1, CSR_MCACHE_CTL + srli t1, t1, 20 + andi t1, t1, 0x1 + bnez t1, check_cm_disabled + + ret + + .section .text, "ax", %progbits + .align 3 + .global __ae350_enable_coherency +__ae350_enable_coherency: + /* enable d-cache coherency */ + lui t1, 0x80 + csrs CSR_MCACHE_CTL, t1 + /* + * mcache_ctl.DC_COHEN is hard-wired 0 on platforms + * w/o CM support + */ + csrr t1, CSR_MCACHE_CTL + srli t1, t1, 19 + andi t1, t1, 0x1 + beqz t1, enable_L1_cache + /* wait for mcache_ctl.DC_COHSTA to be set */ +check_cm_enabled: + csrr t1, CSR_MCACHE_CTL + srli t1, t1, 20 + andi t1, t1, 0x1 + beqz t1, check_cm_enabled +enable_L1_cache: + /* enable i/d-cache */ + csrs CSR_MCACHE_CTL, 0x3 + + ret + + .section .text, "ax", %progbits + .align 3 + .global __ae350_enable_coherency_warmboot +__ae350_enable_coherency_warmboot: + call ra, __ae350_enable_coherency + j _start_warm diff -Nru opensbi-1.1/platform/generic/config.mk opensbi-1.3/platform/generic/config.mk --- opensbi-1.1/platform/generic/config.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/generic/config.mk 1970-01-01 01:00:00.000000000 +0100 @@ -1,40 +0,0 @@ -# -# SPDX-License-Identifier: BSD-2-Clause -# -# Copyright (c) 2020 Western Digital Corporation or its affiliates. -# -# Authors: -# Anup Patel -# - -# Compiler flags -platform-cppflags-y = -platform-cflags-y = -platform-asflags-y = -platform-ldflags-y = - -# Command for platform specific "make run" -platform-runcmd = qemu-system-riscv$(PLATFORM_RISCV_XLEN) -M virt -m 256M \ - -nographic -bios $(build_dir)/platform/generic/firmware/fw_payload.elf - -# Blobs to build -FW_TEXT_START=0x80000000 -FW_DYNAMIC=y -FW_JUMP=y -ifeq ($(PLATFORM_RISCV_XLEN), 32) - # This needs to be 4MB aligned for 32-bit system - FW_JUMP_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x400000))) -else - # This needs to be 2MB aligned for 64-bit system - FW_JUMP_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x200000))) -endif -FW_JUMP_FDT_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x2200000))) -FW_PAYLOAD=y -ifeq ($(PLATFORM_RISCV_XLEN), 32) - # This needs to be 4MB aligned for 32-bit system - FW_PAYLOAD_OFFSET=0x400000 -else - # This needs to be 2MB aligned for 64-bit system - FW_PAYLOAD_OFFSET=0x200000 -endif -FW_PAYLOAD_FDT_ADDR=$(FW_JUMP_FDT_ADDR) diff -Nru opensbi-1.1/platform/generic/configs/defconfig opensbi-1.3/platform/generic/configs/defconfig --- opensbi-1.1/platform/generic/configs/defconfig 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/platform/generic/configs/defconfig 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,40 @@ +CONFIG_PLATFORM_ALLWINNER_D1=y +CONFIG_PLATFORM_ANDES_AE350=y +CONFIG_PLATFORM_RENESAS_RZFIVE=y +CONFIG_PLATFORM_SIFIVE_FU540=y +CONFIG_PLATFORM_SIFIVE_FU740=y +CONFIG_PLATFORM_STARFIVE_JH7110=y +CONFIG_FDT_GPIO=y +CONFIG_FDT_GPIO_SIFIVE=y +CONFIG_FDT_GPIO_STARFIVE=y +CONFIG_FDT_I2C=y +CONFIG_FDT_I2C_SIFIVE=y +CONFIG_FDT_I2C_DW=y +CONFIG_FDT_IPI=y +CONFIG_FDT_IPI_MSWI=y +CONFIG_FDT_IPI_PLICSW=y +CONFIG_FDT_IRQCHIP=y +CONFIG_FDT_IRQCHIP_APLIC=y +CONFIG_FDT_IRQCHIP_IMSIC=y +CONFIG_FDT_IRQCHIP_PLIC=y +CONFIG_FDT_RESET=y +CONFIG_FDT_RESET_ATCWDT200=y +CONFIG_FDT_RESET_GPIO=y +CONFIG_FDT_RESET_HTIF=y +CONFIG_FDT_RESET_SIFIVE_TEST=y +CONFIG_FDT_RESET_SUNXI_WDT=y +CONFIG_FDT_RESET_THEAD=y +CONFIG_FDT_SERIAL=y +CONFIG_FDT_SERIAL_CADENCE=y +CONFIG_FDT_SERIAL_GAISLER=y +CONFIG_FDT_SERIAL_HTIF=y +CONFIG_FDT_SERIAL_RENESAS_SCIF=y +CONFIG_FDT_SERIAL_SHAKTI=y +CONFIG_FDT_SERIAL_SIFIVE=y +CONFIG_FDT_SERIAL_LITEX=y +CONFIG_FDT_SERIAL_UART8250=y +CONFIG_FDT_SERIAL_XILINX_UARTLITE=y +CONFIG_FDT_TIMER=y +CONFIG_FDT_TIMER_MTIMER=y +CONFIG_FDT_TIMER_PLMT=y +CONFIG_SERIAL_SEMIHOSTING=y diff -Nru opensbi-1.1/platform/generic/include/andes/andes45.h opensbi-1.3/platform/generic/include/andes/andes45.h --- opensbi-1.1/platform/generic/include/andes/andes45.h 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/platform/generic/include/andes/andes45.h 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,29 @@ +#ifndef _RISCV_ANDES45_H +#define _RISCV_ANDES45_H + +#define CSR_MARCHID_MICROID 0xfff + +/* Memory and Miscellaneous Registers */ +#define CSR_MCACHE_CTL 0x7ca +#define CSR_MCCTLCOMMAND 0x7cc + +/* Configuration Control & Status Registers */ +#define CSR_MICM_CFG 0xfc0 +#define CSR_MDCM_CFG 0xfc1 +#define CSR_MMSC_CFG 0xfc2 + +#define MICM_CFG_ISZ_OFFSET 6 +#define MICM_CFG_ISZ_MASK (0x7 << MICM_CFG_ISZ_OFFSET) + +#define MDCM_CFG_DSZ_OFFSET 6 +#define MDCM_CFG_DSZ_MASK (0x7 << MDCM_CFG_DSZ_OFFSET) + +#define MMSC_CFG_CCTLCSR_OFFSET 16 +#define MMSC_CFG_CCTLCSR_MASK (0x1 << MMSC_CFG_CCTLCSR_OFFSET) +#define MMSC_IOCP_OFFSET 47 +#define MMSC_IOCP_MASK (0x1ULL << MMSC_IOCP_OFFSET) + +#define MCACHE_CTL_CCTL_SUEN_OFFSET 8 +#define MCACHE_CTL_CCTL_SUEN_MASK (0x1 << MCACHE_CTL_CCTL_SUEN_OFFSET) + +#endif /* _RISCV_ANDES45_H */ diff -Nru opensbi-1.1/platform/generic/include/andes/andes45_pma.h opensbi-1.3/platform/generic/include/andes/andes45_pma.h --- opensbi-1.1/platform/generic/include/andes/andes45_pma.h 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/platform/generic/include/andes/andes45_pma.h 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2023 Renesas Electronics Corp. + */ + +#ifndef _ANDES45_PMA_H_ +#define _ANDES45_PMA_H_ + +#include + +#define ANDES45_MAX_PMA_REGIONS 16 + +/* Naturally aligned power of 2 region */ +#define ANDES45_PMACFG_ETYP_NAPOT 3 + +/* Memory, Non-cacheable, Bufferable */ +#define ANDES45_PMACFG_MTYP_MEM_NON_CACHE_BUF (3 << 2) + +/** + * struct andes45_pma_region - Describes PMA regions + * + * @pa: Address to be configured in the PMA + * @size: Size of the region + * @flags: Flags to be set for the PMA region + * @dt_populate: Boolean flag indicating if the DT entry should be + * populated for the given PMA region + * @shared_dma: Boolean flag if set "shared-dma-pool" property will + * be set in the DT node + * @no_map: Boolean flag if set "no-map" property will be set in the + * DT node + * @dma_default: Boolean flag if set "linux,dma-default" property will + * be set in the DT node. Note Linux expects single node + * with this property set. + */ +struct andes45_pma_region { + unsigned long pa; + unsigned long size; + u8 flags:7; + bool dt_populate; + bool shared_dma; + bool no_map; + bool dma_default; +}; + +int andes45_pma_setup_regions(const struct andes45_pma_region *pma_regions, + unsigned int pma_regions_count); + +#endif /* _ANDES45_PMA_H_ */ diff -Nru opensbi-1.1/platform/generic/include/andes/andes_sbi.h opensbi-1.3/platform/generic/include/andes/andes_sbi.h --- opensbi-1.1/platform/generic/include/andes/andes_sbi.h 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/platform/generic/include/andes/andes_sbi.h 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-2-Clause + +#ifndef _RISCV_ANDES_SBI_H +#define _RISCV_ANDES_SBI_H + +#include +#include + +int andes_sbi_vendor_ext_provider(long funcid, + const struct sbi_trap_regs *regs, + unsigned long *out_value, + struct sbi_trap_info *out_trap, + const struct fdt_match *match); + +#endif /* _RISCV_ANDES_SBI_H */ diff -Nru opensbi-1.1/platform/generic/include/platform_override.h opensbi-1.3/platform/generic/include/platform_override.h --- opensbi-1.1/platform/generic/include/platform_override.h 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/generic/include/platform_override.h 2023-06-23 07:31:49.000000000 +0200 @@ -10,6 +10,7 @@ #ifndef __PLATFORM_OVERRIDE_H__ #define __PLATFORM_OVERRIDE_H__ +#include #include #include @@ -17,13 +18,16 @@ const struct fdt_match *match_table; u64 (*features)(const struct fdt_match *match); u64 (*tlbr_flush_limit)(const struct fdt_match *match); + bool (*cold_boot_allowed)(u32 hartid, const struct fdt_match *match); int (*early_init)(bool cold_boot, const struct fdt_match *match); int (*final_init)(bool cold_boot, const struct fdt_match *match); void (*early_exit)(const struct fdt_match *match); void (*final_exit)(const struct fdt_match *match); int (*fdt_fixup)(void *fdt, const struct fdt_match *match); - int (*vendor_ext_check)(long extid, const struct fdt_match *match); - int (*vendor_ext_provider)(long extid, long funcid, + int (*extensions_init)(const struct fdt_match *match, + struct sbi_hart_features *hfeatures); + void (*fw_init)(void *fdt, const struct fdt_match *match); + int (*vendor_ext_provider)(long funcid, const struct sbi_trap_regs *regs, unsigned long *out_value, struct sbi_trap_info *out_trap, diff -Nru opensbi-1.1/platform/generic/include/thead_c9xx.h opensbi-1.3/platform/generic/include/thead_c9xx.h --- opensbi-1.1/platform/generic/include/thead_c9xx.h 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/platform/generic/include/thead_c9xx.h 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,127 @@ +#ifndef __RISCV_THEAD_C9XX_H____ +#define __RISCV_THEAD_C9XX_H____ + +/* T-HEAD C9xx M mode CSR. */ +#define THEAD_C9XX_CSR_MXSTATUS 0x7c0 +#define THEAD_C9XX_CSR_MHCR 0x7c1 +#define THEAD_C9XX_CSR_MCOR 0x7c2 +#define THEAD_C9XX_CSR_MCCR2 0x7c3 +#define THEAD_C9XX_CSR_MCER2 0x7c4 +#define THEAD_C9XX_CSR_MHINT 0x7c5 +#define THEAD_C9XX_CSR_MRMR 0x7c6 +#define THEAD_C9XX_CSR_MRVBR 0x7c7 +#define THEAD_C9XX_CSR_MCER 0x7c8 +#define THEAD_C9XX_CSR_MCOUNTERWEN 0x7c9 +#define THEAD_C9XX_CSR_MCOUNTERINTEN 0x7ca +#define THEAD_C9XX_CSR_MCOUNTEROF 0x7cb +#define THEAD_C9XX_CSR_MHINT2 0x7cc +#define THEAD_C9XX_CSR_MHINT3 0x7cd +#define THEAD_C9XX_CSR_MRADDR 0x7e0 +#define THEAD_C9XX_CSR_MEXSTATUS 0x7e1 +#define THEAD_C9XX_CSR_MNMICAUSE 0x7e2 +#define THEAD_C9XX_CSR_MNMIPC 0x7e3 +#define THEAD_C9XX_CSR_MHPMCR 0x7f0 +#define THEAD_C9XX_CSR_MHPMSR 0x7f1 +#define THEAD_C9XX_CSR_MHPMER 0x7f2 +#define THEAD_C9XX_CSR_MSMPR 0x7f3 +#define THEAD_C9XX_CSR_MTEECFG 0x7f4 +#define THEAD_C9XX_CSR_MZONEID 0x7f5 +#define THEAD_C9XX_CSR_ML2CPID 0x7f6 +#define THEAD_C9XX_CSR_ML2WP 0x7f7 +#define THEAD_C9XX_CSR_MDTCMCR 0x7f8 +#define THEAD_C9XX_CSR_USP 0x7d1 +#define THEAD_C9XX_CSR_MCINS 0x7d2 +#define THEAD_C9XX_CSR_MCINDEX 0x7d3 +#define THEAD_C9XX_CSR_MCDATA0 0x7d4 +#define THEAD_C9XX_CSR_MCDATA1 0x7d5 +#define THEAD_C9XX_CSR_MEICR 0x7d6 +#define THEAD_C9XX_CSR_MEICR2 0x7d7 +#define THEAD_C9XX_CSR_MBEADDR 0x7d8 +#define THEAD_C9XX_CSR_MCPUID 0xfc0 +#define THEAD_C9XX_CSR_MAPBADDR 0xfc1 +#define THEAD_C9XX_CSR_MWMSR 0xfc2 +#define THEAD_C9XX_CSR_MHALTCAUSE 0xfe0 +#define THEAD_C9XX_CSR_MDBGINFO 0xfe1 +#define THEAD_C9XX_CSR_MPCFIFO 0xfe2 + +/* T-HEAD C9xx S mode CSR. */ +#define THEAD_C9XX_CSR_SXSTATUS 0x5c0 +#define THEAD_C9XX_CSR_SHCR 0x5c1 +#define THEAD_C9XX_CSR_SCER2 0x5c2 +#define THEAD_C9XX_CSR_SCER 0x5c3 +#define THEAD_C9XX_CSR_SCOUNTERINTEN 0x5c4 +#define THEAD_C9XX_CSR_SCOUNTEROF 0x5c5 +#define THEAD_C9XX_CSR_SHINT 0x5c6 +#define THEAD_C9XX_CSR_SHINT2 0x5c7 +#define THEAD_C9XX_CSR_SHPMINHIBIT 0x5c8 +#define THEAD_C9XX_CSR_SHPMCR 0x5c9 +#define THEAD_C9XX_CSR_SHPMSR 0x5ca +#define THEAD_C9XX_CSR_SHPMER 0x5cb +#define THEAD_C9XX_CSR_SL2CPID 0x5cc +#define THEAD_C9XX_CSR_SL2WP 0x5cd +#define THEAD_C9XX_CSR_SBEADDR 0x5d0 +#define THEAD_C9XX_CSR_SCYCLE 0x5e0 +#define THEAD_C9XX_CSR_SHPMCOUNTER1 0x5e1 +#define THEAD_C9XX_CSR_SHPMCOUNTER2 0x5e2 +#define THEAD_C9XX_CSR_SHPMCOUNTER3 0x5e3 +#define THEAD_C9XX_CSR_SHPMCOUNTER4 0x5e4 +#define THEAD_C9XX_CSR_SHPMCOUNTER5 0x5e5 +#define THEAD_C9XX_CSR_SHPMCOUNTER6 0x5e6 +#define THEAD_C9XX_CSR_SHPMCOUNTER7 0x5e7 +#define THEAD_C9XX_CSR_SHPMCOUNTER8 0x5e8 +#define THEAD_C9XX_CSR_SHPMCOUNTER9 0x5e9 +#define THEAD_C9XX_CSR_SHPMCOUNTER10 0x5ea +#define THEAD_C9XX_CSR_SHPMCOUNTER11 0x5eb +#define THEAD_C9XX_CSR_SHPMCOUNTER12 0x5ec +#define THEAD_C9XX_CSR_SHPMCOUNTER13 0x5ed +#define THEAD_C9XX_CSR_SHPMCOUNTER14 0x5ee +#define THEAD_C9XX_CSR_SHPMCOUNTER15 0x5ef +#define THEAD_C9XX_CSR_SHPMCOUNTER16 0x5f0 +#define THEAD_C9XX_CSR_SHPMCOUNTER17 0x5f1 +#define THEAD_C9XX_CSR_SHPMCOUNTER18 0x5f2 +#define THEAD_C9XX_CSR_SHPMCOUNTER19 0x5f3 +#define THEAD_C9XX_CSR_SHPMCOUNTER20 0x5f4 +#define THEAD_C9XX_CSR_SHPMCOUNTER21 0x5f5 +#define THEAD_C9XX_CSR_SHPMCOUNTER22 0x5f6 +#define THEAD_C9XX_CSR_SHPMCOUNTER23 0x5f7 +#define THEAD_C9XX_CSR_SHPMCOUNTER24 0x5f8 +#define THEAD_C9XX_CSR_SHPMCOUNTER25 0x5f9 +#define THEAD_C9XX_CSR_SHPMCOUNTER26 0x5fa +#define THEAD_C9XX_CSR_SHPMCOUNTER27 0x5fb +#define THEAD_C9XX_CSR_SHPMCOUNTER28 0x5fc +#define THEAD_C9XX_CSR_SHPMCOUNTER29 0x5fd +#define THEAD_C9XX_CSR_SHPMCOUNTER30 0x5fe +#define THEAD_C9XX_CSR_SHPMCOUNTER31 0x5ff + +/* T-HEAD C9xx U mode CSR. */ +#define THEAD_C9XX_CSR_FXCR 0x800 + +/* T-HEAD C9xx MMU extentions. */ +#define THEAD_C9XX_CSR_SMIR 0x9c0 +#define THEAD_C9XX_CSR_SMEL 0x9c1 +#define THEAD_C9XX_CSR_SMEH 0x9c2 +#define THEAD_C9XX_CSR_SMCIR 0x9c3 + +/* T-HEAD C9xx Security CSR(May be droped). */ +#define THEAD_C9XX_CSR_MEBR 0xbe0 +#define THEAD_C9XX_CSR_NT_MSTATUS 0xbe1 +#define THEAD_C9XX_CSR_NT_MIE 0xbe2 +#define THEAD_C9XX_CSR_NT_MTVEC 0xbe3 +#define THEAD_C9XX_CSR_NT_MTVT 0xbe4 +#define THEAD_C9XX_CSR_NT_MEPC 0xbe5 +#define THEAD_C9XX_CSR_NT_MCAUSE 0xbe6 +#define THEAD_C9XX_CSR_NT_MIP 0xbe7 +#define THEAD_C9XX_CSR_NT_MINTSTATE 0xbe8 +#define THEAD_C9XX_CSR_NT_MXSTATUS 0xbe9 +#define THEAD_C9XX_CSR_NT_MEBR 0xbea +#define THEAD_C9XX_CSR_NT_MSP 0xbeb +#define THEAD_C9XX_CSR_T_USP 0xbec +#define THEAD_C9XX_CSR_T_MDCR 0xbed +#define THEAD_C9XX_CSR_T_MPCR 0xbee +#define THEAD_C9XX_CSR_PMPTEECFG 0xbef + +/* T-HEAD C9xx MIP CSR extension */ +#define THEAD_C9XX_IRQ_PMU_OVF 17 +#define THEAD_C9XX_MIP_MOIP (_UL(1) << THEAD_C9XX_IRQ_PMU_OVF) + +#endif diff -Nru opensbi-1.1/platform/generic/Kconfig opensbi-1.3/platform/generic/Kconfig --- opensbi-1.1/platform/generic/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/platform/generic/Kconfig 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: BSD-2-Clause + +config PLATFORM_GENERIC + bool + select FDT + select FDT_DOMAIN + select FDT_PMU + default y + +if PLATFORM_GENERIC + +config PLATFORM_GENERIC_NAME + string "Platform default name" + default "Generic" + +config PLATFORM_GENERIC_MAJOR_VER + int "Platform major version" + range 0 65535 + default 0 + +config PLATFORM_GENERIC_MINOR_VER + int "Platform minor version" + range 0 65535 + default 1 + +config PLATFORM_ALLWINNER_D1 + bool "Allwinner D1 support" + depends on FDT_IRQCHIP_PLIC + default n + +config PLATFORM_ANDES_AE350 + bool "Andes AE350 support" + select SYS_ATCSMU + default n + +config PLATFORM_RENESAS_RZFIVE + bool "Renesas RZ/Five support" + select ANDES45_PMA + select ANDES_SBI + default n + +config PLATFORM_SIFIVE_FU540 + bool "SiFive FU540 support" + default n + +config PLATFORM_SIFIVE_FU740 + bool "SiFive FU740 support" + depends on FDT_RESET && FDT_I2C + default n + +config PLATFORM_STARFIVE_JH7110 + bool "StarFive JH7110 support" + default n + +source "$(OPENSBI_SRC_DIR)/platform/generic/andes/Kconfig" + +endif diff -Nru opensbi-1.1/platform/generic/objects.mk opensbi-1.3/platform/generic/objects.mk --- opensbi-1.1/platform/generic/objects.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/generic/objects.mk 2023-06-23 07:31:49.000000000 +0200 @@ -7,5 +7,38 @@ # Anup Patel # +# Compiler flags +platform-cppflags-y = +platform-cflags-y = +platform-asflags-y = +platform-ldflags-y = + +# Command for platform specific "make run" +platform-runcmd = qemu-system-riscv$(PLATFORM_RISCV_XLEN) -M virt -m 256M \ + -nographic -bios $(build_dir)/platform/generic/firmware/fw_payload.elf + +# Objects to build platform-objs-y += platform.o platform-objs-y += platform_override_modules.o + +# Blobs to build +FW_TEXT_START=0x80000000 +FW_DYNAMIC=y +FW_JUMP=y +ifeq ($(PLATFORM_RISCV_XLEN), 32) + # This needs to be 4MB aligned for 32-bit system + FW_JUMP_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x400000))) +else + # This needs to be 2MB aligned for 64-bit system + FW_JUMP_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x200000))) +endif +FW_JUMP_FDT_ADDR=$(shell printf "0x%X" $$(($(FW_TEXT_START) + 0x2200000))) +FW_PAYLOAD=y +ifeq ($(PLATFORM_RISCV_XLEN), 32) + # This needs to be 4MB aligned for 32-bit system + FW_PAYLOAD_OFFSET=0x400000 +else + # This needs to be 2MB aligned for 64-bit system + FW_PAYLOAD_OFFSET=0x200000 +endif +FW_PAYLOAD_FDT_ADDR=$(FW_JUMP_FDT_ADDR) diff -Nru opensbi-1.1/platform/generic/platform.c opensbi-1.3/platform/generic/platform.c --- opensbi-1.1/platform/generic/platform.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/generic/platform.c 2023-06-23 07:31:49.000000000 +0200 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,7 @@ #include #include #include +#include /* List of platform override modules generated at compile time */ extern const struct platform_override *platform_override_modules[]; @@ -33,17 +35,17 @@ static void fw_platform_lookup_special(void *fdt, int root_offset) { - int pos, noff; const struct platform_override *plat; const struct fdt_match *match; + int pos; for (pos = 0; pos < platform_override_modules_size; pos++) { plat = platform_override_modules[pos]; if (!plat->match_table) continue; - noff = fdt_find_match(fdt, -1, plat->match_table, &match); - if (noff < 0) + match = fdt_match_node(fdt, root_offset, plat->match_table); + if (!match) continue; generic_plat = plat; @@ -84,6 +86,9 @@ fw_platform_lookup_special(fdt, root_offset); + if (generic_plat && generic_plat->fw_init) + generic_plat->fw_init(fdt, generic_plat_match); + model = fdt_getprop(fdt, root_offset, "model", &len); if (model) sbi_strncpy(platform.name, model, sizeof(platform.name) - 1); @@ -110,7 +115,7 @@ } platform.hart_count = hart_count; - + platform.heap_size = SBI_PLATFORM_DEFAULT_HEAP_SIZE(hart_count); platform_has_mlevel_imsic = fdt_check_imsic_mlevel(fdt); /* Return original FDT pointer */ @@ -121,6 +126,14 @@ wfi(); } +static bool generic_cold_boot_allowed(u32 hartid) +{ + if (generic_plat && generic_plat->cold_boot_allowed) + return generic_plat->cold_boot_allowed( + hartid, generic_plat_match); + return true; +} + static int generic_nascent_init(void) { if (platform_has_mlevel_imsic) @@ -130,6 +143,9 @@ static int generic_early_init(bool cold_boot) { + if (cold_boot) + fdt_reset_init(); + if (!generic_plat || !generic_plat->early_init) return 0; @@ -141,9 +157,6 @@ void *fdt; int rc; - if (cold_boot) - fdt_reset_init(); - if (generic_plat && generic_plat->final_init) { rc = generic_plat->final_init(cold_boot, generic_plat_match); if (rc) @@ -168,27 +181,20 @@ return 0; } -static int generic_vendor_ext_check(long extid) +static bool generic_vendor_ext_check(void) { - if (generic_plat && generic_plat->vendor_ext_check) - return generic_plat->vendor_ext_check(extid, - generic_plat_match); - - return 0; + return (generic_plat && generic_plat->vendor_ext_provider) ? + true : false; } -static int generic_vendor_ext_provider(long extid, long funcid, +static int generic_vendor_ext_provider(long funcid, const struct sbi_trap_regs *regs, unsigned long *out_value, struct sbi_trap_info *out_trap) { - if (generic_plat && generic_plat->vendor_ext_provider) { - return generic_plat->vendor_ext_provider(extid, funcid, regs, - out_value, out_trap, - generic_plat_match); - } - - return SBI_ENOTSUPP; + return generic_plat->vendor_ext_provider(funcid, regs, + out_value, out_trap, + generic_plat_match); } static void generic_early_exit(void) @@ -203,9 +209,35 @@ generic_plat->final_exit(generic_plat_match); } +static int generic_extensions_init(struct sbi_hart_features *hfeatures) +{ + if (generic_plat && generic_plat->extensions_init) + return generic_plat->extensions_init(generic_plat_match, + hfeatures); + + return 0; +} + static int generic_domains_init(void) { - return fdt_domains_populate(fdt_get_address()); + void *fdt = fdt_get_address(); + int offset, ret; + + ret = fdt_domains_populate(fdt); + if (ret < 0) + return ret; + + offset = fdt_path_offset(fdt, "/chosen"); + + if (offset >= 0) { + offset = fdt_node_offset_by_compatible(fdt, offset, + "opensbi,domain,config"); + if (offset >= 0 && + fdt_get_property(fdt, offset, "system-suspend-test", NULL)) + sbi_system_suspend_test_enable(); + } + + return 0; } static u64 generic_tlbr_flush_limit(void) @@ -242,14 +274,24 @@ return evt_val; } +static int generic_console_init(void) +{ + if (semihosting_enabled()) + return semihosting_init(); + else + return fdt_serial_init(); +} + const struct sbi_platform_operations platform_ops = { + .cold_boot_allowed = generic_cold_boot_allowed, .nascent_init = generic_nascent_init, .early_init = generic_early_init, .final_init = generic_final_init, .early_exit = generic_early_exit, .final_exit = generic_final_exit, + .extensions_init = generic_extensions_init, .domains_init = generic_domains_init, - .console_init = fdt_serial_init, + .console_init = generic_console_init, .irqchip_init = fdt_irqchip_init, .irqchip_exit = fdt_irqchip_exit, .ipi_init = fdt_ipi_init, @@ -265,11 +307,14 @@ struct sbi_platform platform = { .opensbi_version = OPENSBI_VERSION, - .platform_version = SBI_PLATFORM_VERSION(0x0, 0x01), - .name = "Generic", + .platform_version = + SBI_PLATFORM_VERSION(CONFIG_PLATFORM_GENERIC_MAJOR_VER, + CONFIG_PLATFORM_GENERIC_MINOR_VER), + .name = CONFIG_PLATFORM_GENERIC_NAME, .features = SBI_PLATFORM_DEFAULT_FEATURES, .hart_count = SBI_HARTMASK_MAX_BITS, .hart_index2id = generic_hart_index2id, .hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE, + .heap_size = SBI_PLATFORM_DEFAULT_HEAP_SIZE(0), .platform_ops_addr = (unsigned long)&platform_ops }; diff -Nru opensbi-1.1/platform/generic/renesas/rzfive/objects.mk opensbi-1.3/platform/generic/renesas/rzfive/objects.mk --- opensbi-1.1/platform/generic/renesas/rzfive/objects.mk 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/platform/generic/renesas/rzfive/objects.mk 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,8 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (C) 2022 Renesas Electronics Corp. +# + +carray-platform_override_modules-$(CONFIG_PLATFORM_RENESAS_RZFIVE) += renesas_rzfive +platform-objs-$(CONFIG_PLATFORM_RENESAS_RZFIVE) += renesas/rzfive/rzfive.o diff -Nru opensbi-1.1/platform/generic/renesas/rzfive/rzfive.c opensbi-1.3/platform/generic/renesas/rzfive/rzfive.c --- opensbi-1.1/platform/generic/renesas/rzfive/rzfive.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/platform/generic/renesas/rzfive/rzfive.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 Renesas Electronics Corp. + * + */ + +#include +#include +#include +#include +#include + +static const struct andes45_pma_region renesas_rzfive_pma_regions[] = { + { + .pa = 0x58000000, + .size = 0x8000000, + .flags = ANDES45_PMACFG_ETYP_NAPOT | + ANDES45_PMACFG_MTYP_MEM_NON_CACHE_BUF, + .dt_populate = true, + .shared_dma = true, + .no_map = true, + .dma_default = true, + }, +}; + +static int renesas_rzfive_final_init(bool cold_boot, const struct fdt_match *match) +{ + return andes45_pma_setup_regions(renesas_rzfive_pma_regions, + array_size(renesas_rzfive_pma_regions)); +} + +int renesas_rzfive_early_init(bool cold_boot, const struct fdt_match *match) +{ + /* + * Renesas RZ/Five RISC-V SoC has Instruction local memory and + * Data local memory (ILM & DLM) mapped between region 0x30000 + * to 0x4FFFF. When a virtual address falls within this range, + * the MMU doesn't trigger a page fault; it assumes the virtual + * address is a physical address which can cause undesired + * behaviours for statically linked applications/libraries. To + * avoid this, add the ILM/DLM memory regions to the root domain + * region of the PMPU with permissions set to 0x0 for S/U modes + * so that any access to these regions gets blocked and for M-mode + * we grant full access. + */ + return sbi_domain_root_add_memrange(0x30000, 0x20000, 0x1000, + SBI_DOMAIN_MEMREGION_M_RWX); +} + +static const struct fdt_match renesas_rzfive_match[] = { + { .compatible = "renesas,r9a07g043f01" }, + { /* sentinel */ } +}; + +const struct platform_override renesas_rzfive = { + .match_table = renesas_rzfive_match, + .early_init = renesas_rzfive_early_init, + .final_init = renesas_rzfive_final_init, + .vendor_ext_provider = andes_sbi_vendor_ext_provider, +}; diff -Nru opensbi-1.1/platform/generic/sifive/fu540.c opensbi-1.3/platform/generic/sifive/fu540.c --- opensbi-1.1/platform/generic/sifive/fu540.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/generic/sifive/fu540.c 2023-06-23 07:31:49.000000000 +0200 @@ -20,18 +20,6 @@ return 0; } -static int sifive_fu540_fdt_fixup(void *fdt, const struct fdt_match *match) -{ - /* - * SiFive Freedom U540 has an erratum that prevents S-mode software - * to access a PMP protected region using 1GB page table mapping, so - * always add the no-map attribute on this platform. - */ - fdt_reserved_memory_nomap_fixup(fdt); - - return 0; -} - static const struct fdt_match sifive_fu540_match[] = { { .compatible = "sifive,fu540" }, { .compatible = "sifive,fu540g" }, @@ -43,5 +31,4 @@ const struct platform_override sifive_fu540 = { .match_table = sifive_fu540_match, .tlbr_flush_limit = sifive_fu540_tlbr_flush_limit, - .fdt_fixup = sifive_fu540_fdt_fixup, }; diff -Nru opensbi-1.1/platform/generic/sifive/fu740.c opensbi-1.3/platform/generic/sifive/fu740.c --- opensbi-1.1/platform/generic/sifive/fu740.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/generic/sifive/fu740.c 2023-06-23 07:31:49.000000000 +0200 @@ -205,7 +205,7 @@ } static const struct fdt_match da9063_reset_match[] = { - { .compatible = "dlg,da9063", .data = (void *)TRUE }, + { .compatible = "dlg,da9063", .data = (void *)true }, { }, }; diff -Nru opensbi-1.1/platform/generic/sifive/objects.mk opensbi-1.3/platform/generic/sifive/objects.mk --- opensbi-1.1/platform/generic/sifive/objects.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/generic/sifive/objects.mk 2023-06-23 07:31:49.000000000 +0200 @@ -2,8 +2,8 @@ # SPDX-License-Identifier: BSD-2-Clause # -carray-platform_override_modules-y += sifive_fu540 -platform-objs-y += sifive/fu540.o +carray-platform_override_modules-$(CONFIG_PLATFORM_SIFIVE_FU540) += sifive_fu540 +platform-objs-$(CONFIG_PLATFORM_SIFIVE_FU540) += sifive/fu540.o -carray-platform_override_modules-y += sifive_fu740 -platform-objs-y += sifive/fu740.o +carray-platform_override_modules-$(CONFIG_PLATFORM_SIFIVE_FU740) += sifive_fu740 +platform-objs-$(CONFIG_PLATFORM_SIFIVE_FU740) += sifive/fu740.o diff -Nru opensbi-1.1/platform/generic/starfive/jh7110.c opensbi-1.3/platform/generic/starfive/jh7110.c --- opensbi-1.1/platform/generic/starfive/jh7110.c 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/platform/generic/starfive/jh7110.c 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,319 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 StarFive + * + * Authors: + * Wei Liang Lim + * Minda Chen + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct pmic { + struct i2c_adapter *adapter; + u32 dev_addr; + const char *compatible; +}; + +struct jh7110 { + u64 pmu_reg_base; + u64 clk_reg_base; + u32 i2c_index; +}; + +static struct pmic pmic_inst; +static struct jh7110 jh7110_inst; +static u32 selected_hartid = -1; + +/* PMU register define */ +#define HW_EVENT_TURN_ON_MASK 0x04 +#define HW_EVENT_TURN_OFF_MASK 0x08 +#define SW_TURN_ON_POWER_MODE 0x0C +#define SW_TURN_OFF_POWER_MODE 0x10 +#define SW_ENCOURAGE 0x44 +#define PMU_INT_MASK 0x48 +#define PCH_BYPASS 0x4C +#define PCH_PSTATE 0x50 +#define PCH_TIMEOUT 0x54 +#define LP_TIMEOUT 0x58 +#define HW_TURN_ON_MODE 0x5C +#define CURR_POWER_MODE 0x80 +#define PMU_EVENT_STATUS 0x88 +#define PMU_INT_STATUS 0x8C + +/* sw encourage cfg */ +#define SW_MODE_ENCOURAGE_EN_LO 0x05 +#define SW_MODE_ENCOURAGE_EN_HI 0x50 +#define SW_MODE_ENCOURAGE_DIS_LO 0x0A +#define SW_MODE_ENCOURAGE_DIS_HI 0xA0 +#define SW_MODE_ENCOURAGE_ON 0xFF + +#define DEVICE_PD_MASK 0xfc +#define SYSTOP_CPU_PD_MASK 0x3 + +#define TIMEOUT_COUNT 100000 +#define AXP15060_POWER_REG 0x32 +#define AXP15060_POWER_OFF_BIT BIT(7) +#define AXP15060_RESET_BIT BIT(6) + +#define I2C_APB_CLK_OFFSET 0x228 +#define I2C_APB_CLK_ENABLE_BIT BIT(31) + +static int pm_system_reset_check(u32 type, u32 reason) +{ + switch (type) { + case SBI_SRST_RESET_TYPE_SHUTDOWN: + return 1; + case SBI_SRST_RESET_TYPE_COLD_REBOOT: + return 255; + default: + break; + } + + return 0; +} + +static int wait_pmu_pd_state(u32 mask) +{ + int count = 0; + unsigned long addr = jh7110_inst.pmu_reg_base; + u32 val; + + do { + val = readl((void *)(addr + CURR_POWER_MODE)); + if (val == mask) + return 0; + + sbi_timer_udelay(2); + count += 1; + if (count == TIMEOUT_COUNT) + return SBI_ETIMEDOUT; + } while (1); +} + +static int shutdown_device_power_domain(void) +{ + unsigned long addr = jh7110_inst.pmu_reg_base; + u32 curr_mode; + int ret = 0; + + curr_mode = readl((void *)(addr + CURR_POWER_MODE)); + curr_mode &= DEVICE_PD_MASK; + + if (curr_mode) { + writel(curr_mode, (void *)(addr + SW_TURN_OFF_POWER_MODE)); + writel(SW_MODE_ENCOURAGE_ON, (void *)(addr + SW_ENCOURAGE)); + writel(SW_MODE_ENCOURAGE_DIS_LO, (void *)(addr + SW_ENCOURAGE)); + writel(SW_MODE_ENCOURAGE_DIS_HI, (void *)(addr + SW_ENCOURAGE)); + ret = wait_pmu_pd_state(SYSTOP_CPU_PD_MASK); + if (ret) + sbi_printf("%s shutdown device power %x error\n", + __func__, curr_mode); + } + return ret; +} + +static void pmic_ops(struct pmic *pmic, int type) +{ + int ret = 0; + u8 val; + + ret = shutdown_device_power_domain(); + + if (ret) + return; + + if (!sbi_strcmp("stf,axp15060-regulator", pmic->compatible)) { + ret = i2c_adapter_reg_read(pmic->adapter, pmic->dev_addr, + AXP15060_POWER_REG, &val); + + if (ret) { + sbi_printf("%s: cannot read pmic power register\n", + __func__); + return; + } + + val |= AXP15060_POWER_OFF_BIT; + if (type == SBI_SRST_RESET_TYPE_SHUTDOWN) + val |= AXP15060_POWER_OFF_BIT; + else + val |= AXP15060_RESET_BIT; + + ret = i2c_adapter_reg_write(pmic->adapter, pmic->dev_addr, + AXP15060_POWER_REG, val); + if (ret) + sbi_printf("%s: cannot write pmic power register\n", + __func__); + } +} + +static void pmic_i2c_clk_enable(void) +{ + unsigned long clock_base; + unsigned int val; + + clock_base = jh7110_inst.clk_reg_base + + I2C_APB_CLK_OFFSET + + (jh7110_inst.i2c_index << 2); + + val = readl((void *)clock_base); + + if (!val) + writel(I2C_APB_CLK_ENABLE_BIT, (void *)clock_base); +} + +static void pm_system_reset(u32 type, u32 reason) +{ + if (pmic_inst.adapter) { + switch (type) { + case SBI_SRST_RESET_TYPE_SHUTDOWN: + case SBI_SRST_RESET_TYPE_COLD_REBOOT: + /* i2c clk may be disabled by kernel driver */ + pmic_i2c_clk_enable(); + pmic_ops(&pmic_inst, type); + break; + default: + break; + } + } + + sbi_hart_hang(); +} + +static struct sbi_system_reset_device pm_reset = { + .name = "pm-reset", + .system_reset_check = pm_system_reset_check, + .system_reset = pm_system_reset +}; + +static int pm_reset_init(void *fdt, int nodeoff, + const struct fdt_match *match) +{ + int rc; + int i2c_bus; + struct i2c_adapter *adapter; + u64 addr; + + rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &addr, NULL); + if (rc) + return rc; + + pmic_inst.dev_addr = addr; + pmic_inst.compatible = match->compatible; + + i2c_bus = fdt_parent_offset(fdt, nodeoff); + if (i2c_bus < 0) + return i2c_bus; + + /* i2c adapter get */ + rc = fdt_i2c_adapter_get(fdt, i2c_bus, &adapter); + if (rc) + return rc; + + pmic_inst.adapter = adapter; + + sbi_system_reset_add_device(&pm_reset); + + return 0; +} + +static const struct fdt_match pm_reset_match[] = { + { .compatible = "stf,axp15060-regulator", .data = (void *)true }, + { }, +}; + +static struct fdt_reset fdt_reset_pmic = { + .match_table = pm_reset_match, + .init = pm_reset_init, +}; + +static int starfive_jh7110_inst_init(void *fdt) +{ + int noff, rc = 0; + const char *name; + u64 addr; + + noff = fdt_node_offset_by_compatible(fdt, -1, "starfive,jh7110-pmu"); + if (-1 < noff) { + rc = fdt_get_node_addr_size(fdt, noff, 0, &addr, NULL); + if (rc) + goto err; + jh7110_inst.pmu_reg_base = addr; + } + + noff = fdt_node_offset_by_compatible(fdt, -1, "starfive,jh7110-clkgen"); + if (-1 < noff) { + rc = fdt_get_node_addr_size(fdt, noff, 0, &addr, NULL); + if (rc) + goto err; + jh7110_inst.clk_reg_base = addr; + } + + if (pmic_inst.adapter) { + name = fdt_get_name(fdt, pmic_inst.adapter->id, NULL); + if (!sbi_strncmp(name, "i2c", 3)) + jh7110_inst.i2c_index = name[3] - '0'; + else + rc = SBI_EINVAL; + } +err: + return rc; +} + +static int starfive_jh7110_final_init(bool cold_boot, + const struct fdt_match *match) +{ + void *fdt = fdt_get_address(); + + if (cold_boot) { + fdt_reset_driver_init(fdt, &fdt_reset_pmic); + return starfive_jh7110_inst_init(fdt); + } + + return 0; +} + +static bool starfive_jh7110_cold_boot_allowed(u32 hartid, + const struct fdt_match *match) +{ + if (selected_hartid != -1) + return (selected_hartid == hartid); + + return true; +} + +static void starfive_jh7110_fw_init(void *fdt, const struct fdt_match *match) +{ + const fdt32_t *val; + int len, coff; + + coff = fdt_path_offset(fdt, "/chosen"); + if (-1 < coff) { + val = fdt_getprop(fdt, coff, "starfive,boot-hart-id", &len); + if (val && len >= sizeof(fdt32_t)) + selected_hartid = (u32) fdt32_to_cpu(*val); + } +} + +static const struct fdt_match starfive_jh7110_match[] = { + { .compatible = "starfive,jh7110" }, + { }, +}; + +const struct platform_override starfive_jh7110 = { + .match_table = starfive_jh7110_match, + .cold_boot_allowed = starfive_jh7110_cold_boot_allowed, + .fw_init = starfive_jh7110_fw_init, + .final_init = starfive_jh7110_final_init, +}; diff -Nru opensbi-1.1/platform/generic/starfive/objects.mk opensbi-1.3/platform/generic/starfive/objects.mk --- opensbi-1.1/platform/generic/starfive/objects.mk 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/platform/generic/starfive/objects.mk 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,6 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# + +carray-platform_override_modules-$(CONFIG_PLATFORM_STARFIVE_JH7110) += starfive_jh7110 +platform-objs-$(CONFIG_PLATFORM_STARFIVE_JH7110) += starfive/jh7110.o diff -Nru opensbi-1.1/platform/kendryte/k210/config.mk opensbi-1.3/platform/kendryte/k210/config.mk --- opensbi-1.1/platform/kendryte/k210/config.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/kendryte/k210/config.mk 1970-01-01 01:00:00.000000000 +0100 @@ -1,19 +0,0 @@ -# -# SPDX-License-Identifier: BSD-2-Clause -# -# Copyright (c) 2019 Western Digital Corporation or its affiliates. -# -# Authors: -# Damien Le Moal -# - -# Compiler flags -platform-cppflags-y = -platform-cflags-y = -platform-asflags-y = -platform-ldflags-y = - -# Blobs to build -FW_TEXT_START=0x80000000 -FW_PAYLOAD=y -FW_PAYLOAD_ALIGN=0x1000 diff -Nru opensbi-1.1/platform/kendryte/k210/Kconfig opensbi-1.3/platform/kendryte/k210/Kconfig --- opensbi-1.1/platform/kendryte/k210/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/platform/kendryte/k210/Kconfig 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-2-Clause + +config PLATFORM_KENDRYTE_K210 + bool + select FDT + select IPI_MSWI + select IRQCHIP_PLIC + select SERIAL_SIFIVE + select TIMER_MTIMER + default y diff -Nru opensbi-1.1/platform/kendryte/k210/objects.mk opensbi-1.3/platform/kendryte/k210/objects.mk --- opensbi-1.1/platform/kendryte/k210/objects.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/kendryte/k210/objects.mk 2023-06-23 07:31:49.000000000 +0200 @@ -7,8 +7,20 @@ # Damien Le Moal # +# Compiler flags +platform-cppflags-y = +platform-cflags-y = +platform-asflags-y = +platform-ldflags-y = + +# Objects to build platform-objs-y += platform.o platform-objs-y += k210.o platform-varprefix-k210.o = dt_k210 platform-padding-k210.o = 2048 + +# Blobs to build +FW_TEXT_START=0x80000000 +FW_PAYLOAD=y +FW_PAYLOAD_ALIGN=0x1000 diff -Nru opensbi-1.1/platform/kendryte/k210/platform.c opensbi-1.3/platform/kendryte/k210/platform.c --- opensbi-1.1/platform/kendryte/k210/platform.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/kendryte/k210/platform.c 2023-06-23 07:31:49.000000000 +0200 @@ -52,7 +52,7 @@ .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE, .first_hartid = 0, .hart_count = K210_HART_COUNT, - .has_64bit_mmio = TRUE, + .has_64bit_mmio = true, }; static u32 k210_get_clk_freq(void) @@ -196,5 +196,7 @@ .features = 0, .hart_count = K210_HART_COUNT, .hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE, + .heap_size = + SBI_PLATFORM_DEFAULT_HEAP_SIZE(K210_HART_COUNT), .platform_ops_addr = (unsigned long)&platform_ops }; diff -Nru opensbi-1.1/platform/nuclei/ux600/config.mk opensbi-1.3/platform/nuclei/ux600/config.mk --- opensbi-1.1/platform/nuclei/ux600/config.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/nuclei/ux600/config.mk 1970-01-01 01:00:00.000000000 +0100 @@ -1,30 +0,0 @@ -# -# SPDX-License-Identifier: BSD-2-Clause -# -# Copyright (c) 2020 Nuclei Corporation or its affiliates. -# -# Authors: -# lujun -# hqfang <578567190@qq.com> -# - -# Compiler flags -platform-cppflags-y = -platform-cflags-y = -platform-asflags-y = -platform-ldflags-y = - -# Command for platform specific "make run" -platform-runcmd = xl_spike \ - $(build_dir)/platform/nuclei/ux600/firmware/fw_payload.elf - -# Blobs to build -FW_TEXT_START=0xA0000000 -FW_DYNAMIC=y -FW_JUMP=y - -FW_JUMP_ADDR=0xA0200000 -FW_JUMP_FDT_ADDR=0xA8000000 -FW_PAYLOAD=y -FW_PAYLOAD_OFFSET=0x200000 -FW_PAYLOAD_FDT_ADDR=0xA8000000 diff -Nru opensbi-1.1/platform/nuclei/ux600/Kconfig opensbi-1.3/platform/nuclei/ux600/Kconfig --- opensbi-1.1/platform/nuclei/ux600/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/platform/nuclei/ux600/Kconfig 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-2-Clause + +config PLATFORM_NUCLEI_UX600 + bool + select FDT + select IPI_MSWI + select IRQCHIP_PLIC + select SERIAL_SIFIVE + select TIMER_MTIMER + default y diff -Nru opensbi-1.1/platform/nuclei/ux600/objects.mk opensbi-1.3/platform/nuclei/ux600/objects.mk --- opensbi-1.1/platform/nuclei/ux600/objects.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/nuclei/ux600/objects.mk 2023-06-23 07:31:49.000000000 +0200 @@ -8,4 +8,26 @@ # hqfang <578567190@qq.com> # +# Compiler flags +platform-cppflags-y = +platform-cflags-y = +platform-asflags-y = +platform-ldflags-y = + +# Command for platform specific "make run" +platform-runcmd = xl_spike \ + $(build_dir)/platform/nuclei/ux600/firmware/fw_payload.elf + +# Objects to build platform-objs-y += platform.o + +# Blobs to build +FW_TEXT_START=0xA0000000 +FW_DYNAMIC=y +FW_JUMP=y + +FW_JUMP_ADDR=0xA0200000 +FW_JUMP_FDT_ADDR=0xA8000000 +FW_PAYLOAD=y +FW_PAYLOAD_OFFSET=0x200000 +FW_PAYLOAD_FDT_ADDR=0xA8000000 diff -Nru opensbi-1.1/platform/nuclei/ux600/platform.c opensbi-1.3/platform/nuclei/ux600/platform.c --- opensbi-1.1/platform/nuclei/ux600/platform.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/nuclei/ux600/platform.c 2023-06-23 07:31:49.000000000 +0200 @@ -8,7 +8,6 @@ * hqfang <578567190@qq.com> */ -#include #include #include #include @@ -84,7 +83,7 @@ .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE, .first_hartid = 0, .hart_count = UX600_HART_COUNT, - .has_64bit_mmio = TRUE, + .has_64bit_mmio = true, }; static u32 measure_cpu_freq(u32 n) @@ -245,5 +244,7 @@ .features = SBI_PLATFORM_DEFAULT_FEATURES, .hart_count = UX600_HART_COUNT, .hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE, + .heap_size = + SBI_PLATFORM_DEFAULT_HEAP_SIZE(UX600_HART_COUNT), .platform_ops_addr = (unsigned long)&platform_ops }; diff -Nru opensbi-1.1/platform/template/config.mk opensbi-1.3/platform/template/config.mk --- opensbi-1.1/platform/template/config.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/template/config.mk 1970-01-01 01:00:00.000000000 +0100 @@ -1,77 +0,0 @@ -# -# SPDX-License-Identifier: BSD-2-Clause -# -# Copyright (c) 2019 Western Digital Corporation or its affiliates. -# - -# Compiler pre-processor flags -platform-cppflags-y = - -# C Compiler and assembler flags. -platform-cflags-y = -platform-asflags-y = - -# Linker flags: additional libraries and object files that the platform -# code needs can be added here -platform-ldflags-y = - -# -# Command for platform specific "make run" -# Useful for development and debugging on plaftform simulator (such as QEMU) -# -# platform-runcmd = your_platform_run.sh - -# -# Platform RISC-V XLEN, ABI, ISA and Code Model configuration. -# These are optional parameters but platforms can optionaly provide it. -# Some of these are guessed based on GCC compiler capabilities -# -# PLATFORM_RISCV_XLEN = 64 -# PLATFORM_RISCV_ABI = lp64 -# PLATFORM_RISCV_ISA = rv64imafdc -# PLATFORM_RISCV_CODE_MODEL = medany - -# Firmware load address configuration. This is mandatory. -FW_TEXT_START=0x80000000 - -# Optional parameter for path to external FDT -# FW_FDT_PATH="path to platform flattened device tree file" - -# -# Dynamic firmware configuration. -# Optional parameters are commented out. Uncomment and define these parameters -# as needed. -# -FW_DYNAMIC= - -# -# Jump firmware configuration. -# Optional parameters are commented out. Uncomment and define these parameters -# as needed. -# -FW_JUMP= -# This needs to be 4MB aligned for 32-bit support -# This needs to be 2MB aligned for 64-bit support -# ifeq ($(PLATFORM_RISCV_XLEN), 32) -# FW_JUMP_ADDR=0x80400000 -# else -# FW_JUMP_ADDR=0x80200000 -# endif -# FW_JUMP_FDT_ADDR=0x82200000 - -# -# Firmware with payload configuration. -# Optional parameters are commented out. Uncomment and define these parameters -# as needed. -# -FW_PAYLOAD= -# This needs to be 4MB aligned for 32-bit support -# This needs to be 2MB aligned for 64-bit support -ifeq ($(PLATFORM_RISCV_XLEN), 32) -FW_PAYLOAD_OFFSET=0x400000 -else -FW_PAYLOAD_OFFSET=0x200000 -endif -# FW_PAYLOAD_ALIGN=0x1000 -# FW_PAYLOAD_PATH="path to next boot stage binary image file" -# FW_PAYLOAD_FDT_ADDR=0x82200000 diff -Nru opensbi-1.1/platform/template/Kconfig opensbi-1.3/platform/template/Kconfig --- opensbi-1.1/platform/template/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/platform/template/Kconfig 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: BSD-2-Clause + +# +# All mandatory drivers or libraries for this platform should +# be directly selected by the PLATFORM_xyz kconfig symbol. +# +# All optional drivers or libraries for this platform should +# be enabled via configs/defconfig of this platform. +# +config PLATFORM_TEMPLATE + bool + select IPI_MSWI + select IRQCHIP_PLIC + select SERIAL_UART8250 + select TIMER_MTIMER + default y diff -Nru opensbi-1.1/platform/template/objects.mk opensbi-1.3/platform/template/objects.mk --- opensbi-1.1/platform/template/objects.mk 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/template/objects.mk 2023-06-23 07:31:49.000000000 +0200 @@ -4,6 +4,33 @@ # Copyright (c) 2019 Western Digital Corporation or its affiliates. # +# Compiler pre-processor flags +platform-cppflags-y = + +# C Compiler and assembler flags. +platform-cflags-y = +platform-asflags-y = + +# Linker flags: additional libraries and object files that the platform +# code needs can be added here +platform-ldflags-y = + +# +# Command for platform specific "make run" +# Useful for development and debugging on plaftform simulator (such as QEMU) +# +# platform-runcmd = your_platform_run.sh + +# +# Platform RISC-V XLEN, ABI, ISA and Code Model configuration. +# These are optional parameters but platforms can optionaly provide it. +# Some of these are guessed based on GCC compiler capabilities +# +# PLATFORM_RISCV_XLEN = 64 +# PLATFORM_RISCV_ABI = lp64 +# PLATFORM_RISCV_ISA = rv64imafdc +# PLATFORM_RISCV_CODE_MODEL = medany + # Space separated list of object file names to be compiled for the platform platform-objs-y += platform.o @@ -13,3 +40,48 @@ # source file be in the form
.dts # # platform-objs-y +=
.o + +# Firmware load address configuration. This is mandatory. +FW_TEXT_START=0x80000000 + +# Optional parameter for path to external FDT +# FW_FDT_PATH="path to platform flattened device tree file" + +# +# Dynamic firmware configuration. +# Optional parameters are commented out. Uncomment and define these parameters +# as needed. +# +FW_DYNAMIC= + +# +# Jump firmware configuration. +# Optional parameters are commented out. Uncomment and define these parameters +# as needed. +# +FW_JUMP= +# This needs to be 4MB aligned for 32-bit support +# This needs to be 2MB aligned for 64-bit support +# ifeq ($(PLATFORM_RISCV_XLEN), 32) +# FW_JUMP_ADDR=0x80400000 +# else +# FW_JUMP_ADDR=0x80200000 +# endif +# FW_JUMP_FDT_ADDR=0x82200000 + +# +# Firmware with payload configuration. +# Optional parameters are commented out. Uncomment and define these parameters +# as needed. +# +FW_PAYLOAD= +# This needs to be 4MB aligned for 32-bit support +# This needs to be 2MB aligned for 64-bit support +ifeq ($(PLATFORM_RISCV_XLEN), 32) +FW_PAYLOAD_OFFSET=0x400000 +else +FW_PAYLOAD_OFFSET=0x200000 +endif +# FW_PAYLOAD_ALIGN=0x1000 +# FW_PAYLOAD_PATH="path to next boot stage binary image file" +# FW_PAYLOAD_FDT_ADDR=0x82200000 diff -Nru opensbi-1.1/platform/template/platform.c opensbi-1.3/platform/template/platform.c --- opensbi-1.1/platform/template/platform.c 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/platform/template/platform.c 2023-06-23 07:31:49.000000000 +0200 @@ -11,7 +11,7 @@ /* * Include these files as needed. - * See config.mk PLATFORM_xxx configuration parameters. + * See objects.mk PLATFORM_xxx configuration parameters. */ #include #include @@ -53,7 +53,7 @@ .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE, .first_hartid = 0, .hart_count = PLATFORM_HART_COUNT, - .has_64bit_mmio = TRUE, + .has_64bit_mmio = true, }; /* @@ -152,5 +152,6 @@ .features = SBI_PLATFORM_DEFAULT_FEATURES, .hart_count = 1, .hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE, + .heap_size = SBI_PLATFORM_DEFAULT_HEAP_SIZE(1), .platform_ops_addr = (unsigned long)&platform_ops }; diff -Nru opensbi-1.1/README.md opensbi-1.3/README.md --- opensbi-1.1/README.md 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/README.md 2023-06-23 07:31:49.000000000 +0200 @@ -1,11 +1,15 @@ RISC-V Open Source Supervisor Binary Interface (OpenSBI) ======================================================== +![RISC-V OpenSBI](docs/riscv_opensbi_logo_final_color.png) + Copyright and License --------------------- -The OpenSBI project is copyright (c) 2019 Western Digital Corporation -or its affiliates and other contributors. +The OpenSBI project is: + +* Copyright (c) 2019 Western Digital Corporation or its affiliates +* Copyright (c) 2023 RISC-V International It is distributed under the terms of the BSD 2-clause license ("Simplified BSD License" or "FreeBSD License", SPDX: *BSD-2-Clause*). @@ -92,8 +96,8 @@ as it doesn't need to boot all the harts. The operating system should be capable enough to bring up all other non-booting harts using HSM extension. -Required Toolchain ------------------- +Required Toolchain and Packages +------------------------------- OpenSBI can be compiled natively or cross-compiled on a x86 host. For cross-compilation, you can build your own toolchain, download a prebuilt one @@ -115,6 +119,14 @@ Please note that only a 64-bit version of the toolchain is available in the Bootlin toolchain repository for now. +In addition to a toolchain, OpenSBI also requires the following packages on +the host: + +1. device-tree-compiler: The device tree compiler for compiling device + tree sources (DTS files). +2. python3: The python 3.0 (or compatible) language support for various + scripts. + Building and Installing the OpenSBI Platform-Independent Library ---------------------------------------------------------------- @@ -196,6 +208,19 @@ *docs/platform/.md* files and *docs/firmware/.md* files. +All OpenSBI platforms support Kconfig style build-time configuration. Users +can change the build-time configuration of a platform using a graphical +interface as follows: +``` +make PLATFORM= menuconfig +``` + +Alternately, an OpenSBI platform can have multiple default configurations +and users can select a custom default configuration as follows: +``` +make PLATFORM= PLATFORM_DEFCONFIG= +``` + Building 32-bit / 64-bit OpenSBI Images --------------------------------------- By default, building OpenSBI generates 32-bit or 64-bit images based on the @@ -277,6 +302,19 @@ purpose, and should NOT be used in a product which follows "reproducible builds". +Building with optimization off for debugging +-------------------------------------------- + +When debugging OpenSBI, we may want to turn off the compiler optimization and +make debugging produce the expected results for a better debugging experience. +To build with optimization off we can just simply add `DEBUG=1`, like: +``` +make DEBUG=1 +``` + +This definition is ONLY for development and debug purpose, and should NOT be +used in a product build. + Contributing to OpenSBI ----------------------- diff -Nru opensbi-1.1/scripts/carray.sh opensbi-1.3/scripts/carray.sh --- opensbi-1.1/scripts/carray.sh 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/scripts/carray.sh 2023-06-23 07:31:49.000000000 +0200 @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash function usage() { diff -Nru opensbi-1.1/scripts/create-binary-archive.sh opensbi-1.3/scripts/create-binary-archive.sh --- opensbi-1.1/scripts/create-binary-archive.sh 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/scripts/create-binary-archive.sh 2023-06-23 07:31:49.000000000 +0200 @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash function usage() { @@ -103,7 +103,6 @@ BUILD_PLATFORM_SUBDIR+=("kendryte/k210") BUILD_PLATFORM_SUBDIR+=("fpga/ariane") BUILD_PLATFORM_SUBDIR+=("fpga/openpiton") - BUILD_PLATFORM_SUBDIR+=("andes/ae350") BUILD_PLATFORM_SUBDIR+=("generic") ;; *) @@ -118,7 +117,7 @@ # Build and install generic library echo "Build and install generic library XLEN=${BUILD_RISCV_XLEN}" echo "" - make -C "${BUILD_OPENSBI_SOURCE_PATH}" O="${BUILD_OUTPUT_PATH}/${BUILD_NAME}" I="${BUILD_OUTPUT_PATH}/${BUILD_ARCHIVE_NAME}" PLATFORM_RISCV_XLEN="${BUILD_RISCV_XLEN}" install_libsbi install_libsbiutils -j "${BUILD_NUM_THREADS}" + make -C "${BUILD_OPENSBI_SOURCE_PATH}" O="${BUILD_OUTPUT_PATH}/${BUILD_NAME}" I="${BUILD_OUTPUT_PATH}/${BUILD_ARCHIVE_NAME}" PLATFORM_RISCV_XLEN="${BUILD_RISCV_XLEN}" install_libsbi -j "${BUILD_NUM_THREADS}" echo "" # Build and install relevant platforms diff -Nru opensbi-1.1/scripts/d2c.sh opensbi-1.3/scripts/d2c.sh --- opensbi-1.1/scripts/d2c.sh 2022-06-25 05:42:10.000000000 +0200 +++ opensbi-1.3/scripts/d2c.sh 2023-06-23 07:31:49.000000000 +0200 @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash function usage() { diff -Nru opensbi-1.1/scripts/Kconfiglib/allnoconfig.py opensbi-1.3/scripts/Kconfiglib/allnoconfig.py --- opensbi-1.1/scripts/Kconfiglib/allnoconfig.py 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/scripts/Kconfiglib/allnoconfig.py 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2018-2019, Ulf Magnusson +# SPDX-License-Identifier: ISC + +""" +Writes a configuration file where as many symbols as possible are set to 'n'. + +The default output filename is '.config'. A different filename can be passed +in the KCONFIG_CONFIG environment variable. + +Usage for the Linux kernel: + + $ make [ARCH=] scriptconfig SCRIPT=Kconfiglib/allnoconfig.py +""" + +# See examples/allnoconfig_walk.py for another way to implement this script + +import kconfiglib + + +def main(): + kconf = kconfiglib.standard_kconfig(__doc__) + + # Avoid warnings that would otherwise get printed by Kconfiglib for the + # following: + # + # 1. Assigning a value to a symbol without a prompt, which never has any + # effect + # + # 2. Assigning values invalid for the type (only bool/tristate symbols + # accept 0/1/2, for n/m/y). The assignments will be ignored for other + # symbol types, which is what we want. + kconf.warn = False + for sym in kconf.unique_defined_syms: + sym.set_value(2 if sym.is_allnoconfig_y else 0) + kconf.warn = True + + kconf.load_allconfig("allno.config") + + print(kconf.write_config()) + + +if __name__ == "__main__": + main() diff -Nru opensbi-1.1/scripts/Kconfiglib/allyesconfig.py opensbi-1.3/scripts/Kconfiglib/allyesconfig.py --- opensbi-1.1/scripts/Kconfiglib/allyesconfig.py 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/scripts/Kconfiglib/allyesconfig.py 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2018-2019, Ulf Magnusson +# SPDX-License-Identifier: ISC + +""" +Writes a configuration file where as many symbols as possible are set to 'y'. + +The default output filename is '.config'. A different filename can be passed +in the KCONFIG_CONFIG environment variable. + +Usage for the Linux kernel: + + $ make [ARCH=] scriptconfig SCRIPT=Kconfiglib/allyesconfig.py +""" +import kconfiglib + + +def main(): + kconf = kconfiglib.standard_kconfig(__doc__) + + # See allnoconfig.py + kconf.warn = False + + # Try to set all symbols to 'y'. Dependencies might truncate the value down + # later, but this will at least give the highest possible value. + # + # Assigning 0/1/2 to non-bool/tristate symbols has no effect (int/hex + # symbols still take a string, because they preserve formatting). + for sym in kconf.unique_defined_syms: + # Set choice symbols to 'm'. This value will be ignored for choices in + # 'y' mode (the "normal" mode), which will instead just get their + # default selection, but will set all symbols in m-mode choices to 'm', + # which is as high as they can go. + # + # Here's a convoluted example of how you might get an m-mode choice + # even during allyesconfig: + # + # choice + # tristate "weird choice" + # depends on m + sym.set_value(1 if sym.choice else 2) + + # Set all choices to the highest possible mode + for choice in kconf.unique_choices: + choice.set_value(2) + + kconf.warn = True + + kconf.load_allconfig("allyes.config") + + print(kconf.write_config()) + + +if __name__ == "__main__": + main() diff -Nru opensbi-1.1/scripts/Kconfiglib/defconfig.py opensbi-1.3/scripts/Kconfiglib/defconfig.py --- opensbi-1.1/scripts/Kconfiglib/defconfig.py 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/scripts/Kconfiglib/defconfig.py 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2019, Ulf Magnusson +# SPDX-License-Identifier: ISC + +""" +Reads a specified configuration file, then writes a new configuration file. +This can be used to initialize the configuration from e.g. an arch-specific +configuration file. This input configuration file would usually be a minimal +configuration file, as generated by e.g. savedefconfig. + +The default output filename is '.config'. A different filename can be passed in +the KCONFIG_CONFIG environment variable. +""" +import argparse + +import kconfiglib + + +def main(): + parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description=__doc__) + + parser.add_argument( + "--kconfig", + default="Kconfig", + help="Top-level Kconfig file (default: Kconfig)") + + parser.add_argument( + "config", + metavar="CONFIGURATION", + help="Input configuration file") + + args = parser.parse_args() + + kconf = kconfiglib.Kconfig(args.kconfig, suppress_traceback=True) + print(kconf.load_config(args.config)) + print(kconf.write_config()) + + +if __name__ == "__main__": + main() diff -Nru opensbi-1.1/scripts/Kconfiglib/genconfig.py opensbi-1.3/scripts/Kconfiglib/genconfig.py --- opensbi-1.1/scripts/Kconfiglib/genconfig.py 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/scripts/Kconfiglib/genconfig.py 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,154 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2018-2019, Ulf Magnusson +# SPDX-License-Identifier: ISC + +""" +Generates a header file with #defines from the configuration, matching the +format of include/generated/autoconf.h in the Linux kernel. + +Optionally, also writes the configuration output as a .config file. See +--config-out. + +The --sync-deps, --file-list, and --env-list options generate information that +can be used to avoid needless rebuilds/reconfigurations. + +Before writing a header or configuration file, Kconfiglib compares the old +contents of the file against the new contents. If there's no change, the write +is skipped. This avoids updating file metadata like the modification time, and +might save work depending on your build setup. + +By default, the configuration is generated from '.config'. A different +configuration file can be passed in the KCONFIG_CONFIG environment variable. + +A custom header string can be inserted at the beginning of generated +configuration and header files by setting the KCONFIG_CONFIG_HEADER and +KCONFIG_AUTOHEADER_HEADER environment variables, respectively (this also works +for other scripts). The string is not automatically made a comment (this is by +design, to allow anything to be added), and no trailing newline is added, so +add '/* */', '#', and newlines as appropriate. + +See https://www.gnu.org/software/make/manual/make.html#Multi_002dLine for a +handy way to define multi-line variables in makefiles, for use with custom +headers. Remember to export the variable to the environment. +""" +import argparse +import os +import sys + +import kconfiglib + + +DEFAULT_SYNC_DEPS_PATH = "deps/" + + +def main(): + parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description=__doc__) + + parser.add_argument( + "--header-path", + metavar="HEADER_FILE", + help=""" +Path to write the generated header file to. If not specified, the path in the +environment variable KCONFIG_AUTOHEADER is used if it is set, and 'config.h' +otherwise. +""") + + parser.add_argument( + "--config-out", + metavar="CONFIG_FILE", + help=""" +Write the configuration to CONFIG_FILE. This is useful if you include .config +files in Makefiles, as the generated configuration file will be a full .config +file even if .config is outdated. The generated configuration matches what +olddefconfig would produce. If you use sync-deps, you can include +deps/auto.conf instead. --config-out is meant for cases where incremental build +information isn't needed. +""") + + parser.add_argument( + "--sync-deps", + metavar="OUTPUT_DIR", + nargs="?", + const=DEFAULT_SYNC_DEPS_PATH, + help=""" +Enable generation of symbol dependency information for incremental builds, +optionally specifying the output directory (default: {}). See the docstring of +Kconfig.sync_deps() in Kconfiglib for more information. +""".format(DEFAULT_SYNC_DEPS_PATH)) + + parser.add_argument( + "--file-list", + metavar="OUTPUT_FILE", + help=""" +Write a list of all Kconfig files to OUTPUT_FILE, with one file per line. The +paths are relative to $srctree (or to the current directory if $srctree is +unset). Files appear in the order they're 'source'd. +""") + + parser.add_argument( + "--env-list", + metavar="OUTPUT_FILE", + help=""" +Write a list of all environment variables referenced in Kconfig files to +OUTPUT_FILE, with one variable per line. Each line has the format NAME=VALUE. +Only environment variables referenced with the preprocessor $(VAR) syntax are +included, and not variables referenced with the older $VAR syntax (which is +only supported for backwards compatibility). +""") + + parser.add_argument( + "kconfig", + metavar="KCONFIG", + nargs="?", + default="Kconfig", + help="Top-level Kconfig file (default: Kconfig)") + + args = parser.parse_args() + + + kconf = kconfiglib.Kconfig(args.kconfig, suppress_traceback=True) + kconf.load_config() + + if args.header_path is None: + if "KCONFIG_AUTOHEADER" in os.environ: + kconf.write_autoconf() + else: + # Kconfiglib defaults to include/generated/autoconf.h to be + # compatible with the C tools. 'config.h' is used here instead for + # backwards compatibility. It's probably a saner default for tools + # as well. + kconf.write_autoconf("config.h") + else: + kconf.write_autoconf(args.header_path) + + if args.config_out is not None: + kconf.write_config(args.config_out, save_old=False) + + if args.sync_deps is not None: + kconf.sync_deps(args.sync_deps) + + if args.file_list is not None: + with _open_write(args.file_list) as f: + for path in kconf.kconfig_filenames: + f.write(path + "\n") + + if args.env_list is not None: + with _open_write(args.env_list) as f: + for env_var in kconf.env_vars: + f.write("{}={}\n".format(env_var, os.environ[env_var])) + + +def _open_write(path): + # Python 2/3 compatibility. io.open() is available on both, but makes + # write() expect 'unicode' strings on Python 2. + + if sys.version_info[0] < 3: + return open(path, "w") + return open(path, "w", encoding="utf-8") + + +if __name__ == "__main__": + main() diff -Nru opensbi-1.1/scripts/Kconfiglib/kconfiglib.py opensbi-1.3/scripts/Kconfiglib/kconfiglib.py --- opensbi-1.1/scripts/Kconfiglib/kconfiglib.py 1970-01-01 01:00:00.000000000 +0100 +++ opensbi-1.3/scripts/Kconfiglib/kconfiglib.py 2023-06-23 07:31:49.000000000 +0200 @@ -0,0 +1,7160 @@ +# Copyright (c) 2011-2019, Ulf Magnusson +# SPDX-License-Identifier: ISC + +""" +Overview +======== + +Kconfiglib is a Python 2/3 library for scripting and extracting information +from Kconfig (https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt) +configuration systems. + +See the homepage at https://github.com/ulfalizer/Kconfiglib for a longer +overview. + +Since Kconfiglib 12.0.0, the library version is available in +kconfiglib.VERSION, which is a (, , ) tuple, e.g. +(12, 0, 0). + + +Using Kconfiglib on the Linux kernel with the Makefile targets +============================================================== + +For the Linux kernel, a handy interface is provided by the +scripts/kconfig/Makefile patch, which can be applied with either 'git am' or +the 'patch' utility: + + $ wget -qO- https://raw.githubusercontent.com/ulfalizer/Kconfiglib/master/makefile.patch | git am + $ wget -qO- https://raw.githubusercontent.com/ulfalizer/Kconfiglib/master/makefile.patch | patch -p1 + +Warning: Not passing -p1 to patch will cause the wrong file to be patched. + +Please tell me if the patch does not apply. It should be trivial to apply +manually, as it's just a block of text that needs to be inserted near the other +*conf: targets in scripts/kconfig/Makefile. + +Look further down for a motivation for the Makefile patch and for instructions +on how you can use Kconfiglib without it. + +If you do not wish to install Kconfiglib via pip, the Makefile patch is set up +so that you can also just clone Kconfiglib into the kernel root: + + $ git clone git://github.com/ulfalizer/Kconfiglib.git + $ git am Kconfiglib/makefile.patch (or 'patch -p1 < Kconfiglib/makefile.patch') + +Warning: The directory name Kconfiglib/ is significant in this case, because +it's added to PYTHONPATH by the new targets in makefile.patch. + +The targets added by the Makefile patch are described in the following +sections. + + +make kmenuconfig +---------------- + +This target runs the curses menuconfig interface with Python 3. As of +Kconfiglib 12.2.0, both Python 2 and Python 3 are supported (previously, only +Python 3 was supported, so this was a backport). + + +make guiconfig +-------------- + +This target runs the Tkinter menuconfig interface. Both Python 2 and Python 3 +are supported. To change the Python interpreter used, pass +PYTHONCMD= to 'make'. The default is 'python'. + + +make [ARCH=] iscriptconfig +-------------------------------- + +This target gives an interactive Python prompt where a Kconfig instance has +been preloaded and is available in 'kconf'. To change the Python interpreter +used, pass PYTHONCMD= to 'make'. The default is 'python'. + +To get a feel for the API, try evaluating and printing the symbols in +kconf.defined_syms, and explore the MenuNode menu tree starting at +kconf.top_node by following 'next' and 'list' pointers. + +The item contained in a menu node is found in MenuNode.item (note that this can +be one of the constants kconfiglib.MENU and kconfiglib.COMMENT), and all +symbols and choices have a 'nodes' attribute containing their menu nodes +(usually only one). Printing a menu node will print its item, in Kconfig +format. + +If you want to look up a symbol by name, use the kconf.syms dictionary. + + +make scriptconfig SCRIPT=