mirror of
https://github.com/SerenityOS/serenity.git
synced 2026-11-07 04:29:30 -10:00
Meta+Kernel: Automatically generate a RISC-V extension header
This header will be used to generate the RISC-V CPUFeature definition and set the feature bits based on the "riscv,isa-extensions" devicetree property.
This commit is contained in:
1 parent
568a02293c
commit
9a5589c695
3 files changed
+253
No files matched your search
@@ -537,6 +537,19 @@ elseif("${SERENITY_ARCH}" STREQUAL "aarch64")
|
||||
# by the compiler. The CPU cannot access global variables without the MMU as the kernel is linked for a virtual address in high memory.
|
||||
set_source_files_properties(${SOURCES_RUNNING_WITHOUT_MMU} PROPERTIES COMPILE_FLAGS "-fno-stack-protector -fno-sanitize=all")
|
||||
elseif("${SERENITY_ARCH}" STREQUAL "riscv64")
|
||||
find_package(Python3 COMPONENTS Interpreter REQUIRED)
|
||||
|
||||
set(extensions_header "${CMAKE_CURRENT_BINARY_DIR}/Arch/riscv64/Extensions.h")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${extensions_header}"
|
||||
COMMAND ${Python3_EXECUTABLE} "${SerenityOS_SOURCE_DIR}/Meta/riscv_extensions_generator.py" "${SerenityOS_SOURCE_DIR}/Meta/riscv-extensions.txt" -o "${extensions_header}"
|
||||
DEPENDS "${SerenityOS_SOURCE_DIR}/Meta/riscv_extensions_generator.py" "${SerenityOS_SOURCE_DIR}/Meta/riscv-extensions.txt"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
add_custom_target(generate_riscv_extensions_header DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/Arch/riscv64/Extensions.h")
|
||||
|
||||
set(SOURCES_RUNNING_WITHOUT_MMU
|
||||
Arch/riscv64/MMU.cpp
|
||||
Arch/riscv64/pre_init.cpp
|
||||
@@ -550,6 +563,8 @@ elseif("${SERENITY_ARCH}" STREQUAL "riscv64")
|
||||
${KERNEL_SOURCES}
|
||||
${SOURCES_RUNNING_WITHOUT_MMU}
|
||||
|
||||
"${extensions_header}"
|
||||
|
||||
Arch/Processor.cpp
|
||||
kprintf.cpp
|
||||
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
# This file is used to generate the RISC-V Extensions.h header.
|
||||
# It is automatically sorted by Meta/riscv_extensions_generator.py to keep the canonical extension order defined by the RISC-V ISA manual.
|
||||
# To add an extension, simply insert it anywhere in this file and run the script to sort it correctly.
|
||||
|
||||
# Single-letter extensions
|
||||
I
|
||||
M
|
||||
A
|
||||
F
|
||||
D
|
||||
Q
|
||||
C
|
||||
V
|
||||
H
|
||||
|
||||
# Unprivileged extensions
|
||||
Zicbom
|
||||
Zicbop
|
||||
Zicboz
|
||||
Ziccrse
|
||||
Zicntr
|
||||
Zicond
|
||||
Zicsr
|
||||
Zifencei
|
||||
Zihintntl
|
||||
Zihintpause
|
||||
Zihpm
|
||||
Zimop
|
||||
Zaamo
|
||||
Zabha
|
||||
Zacas
|
||||
Zalrsc
|
||||
Zawrs
|
||||
Zfa
|
||||
Zfbfmin
|
||||
Zfh
|
||||
Zfhmin
|
||||
Zca
|
||||
Zcb
|
||||
Zcd
|
||||
Zcf
|
||||
Zcmop
|
||||
Zba
|
||||
Zbb
|
||||
Zbc
|
||||
Zbkb
|
||||
Zbkc
|
||||
Zbkx
|
||||
Zbs
|
||||
Zk
|
||||
Zkn
|
||||
Zknd
|
||||
Zkne
|
||||
Zknh
|
||||
Zkr
|
||||
Zks
|
||||
Zksed
|
||||
Zksh
|
||||
Zkt
|
||||
Ztso
|
||||
Zvbb
|
||||
Zvbc
|
||||
Zve32f
|
||||
Zve32x
|
||||
Zve64d
|
||||
Zve64f
|
||||
Zve64x
|
||||
Zvfbfmin
|
||||
Zvfbfwma
|
||||
Zvfh
|
||||
Zvfhmin
|
||||
Zvkb
|
||||
Zvkg
|
||||
Zvkn
|
||||
Zvknc
|
||||
Zvkned
|
||||
Zvkng
|
||||
Zvknha
|
||||
Zvknhb
|
||||
Zvks
|
||||
Zvksc
|
||||
Zvksed
|
||||
Zvksg
|
||||
Zvksh
|
||||
Zvkt
|
||||
|
||||
# Supervisor extensions
|
||||
Ssaia
|
||||
Sscofpmf
|
||||
Ssnpm
|
||||
Sstc
|
||||
Svade
|
||||
Svadu
|
||||
Svinval
|
||||
Svnapot
|
||||
Svpbmt
|
||||
Svvptc
|
||||
|
||||
# Hypervisor extensions
|
||||
|
||||
# Machine extensions
|
||||
Smaia
|
||||
Smmpm
|
||||
Smnpm
|
||||
Smstateen
|
||||
|
||||
# Non-standard extensions
|
||||
|
||||
Executable
+130
@@ -0,0 +1,130 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("extension_file")
|
||||
parser.add_argument("-o", "--output")
|
||||
args = parser.parse_args()
|
||||
|
||||
SINGLE_LETTER_EXTENSION_ORDER = "iemafdgqlcbkjtpvh"
|
||||
|
||||
single_letter_extensions = set()
|
||||
unprivileged_extensions = set() # Z*
|
||||
supervisor_extensions = set() # Ss*, Sv*
|
||||
hypervisor_extensions = set() # Sh*
|
||||
machine_extensions = set() # Sm*
|
||||
non_standard_extensions = set() # X*
|
||||
|
||||
with open(args.extension_file) as extension_file:
|
||||
for line in extension_file.readlines():
|
||||
extension = line.partition("#")[0].strip()
|
||||
|
||||
if not extension:
|
||||
continue
|
||||
|
||||
extension = extension.lower()
|
||||
|
||||
if extension.startswith("z"):
|
||||
unprivileged_extensions.add(extension)
|
||||
elif extension.startswith("ss") or extension.startswith("sv"):
|
||||
supervisor_extensions.add(extension)
|
||||
elif extension.startswith("sh"):
|
||||
hypervisor_extensions.add(extension)
|
||||
elif extension.startswith("sm"):
|
||||
machine_extensions.add(extension)
|
||||
elif extension.startswith("x"):
|
||||
non_standard_extensions.add(extension)
|
||||
elif len(extension) == 1:
|
||||
single_letter_extensions.add(extension)
|
||||
else:
|
||||
raise Exception(f"Unknown extension category: {extension}")
|
||||
|
||||
|
||||
def unprivileged_extension_sort_key(extension):
|
||||
# Z* extensions are sorted first by their related single-letter extension and then alphabetically.
|
||||
related_single_letter_extension = extension[1]
|
||||
return SINGLE_LETTER_EXTENSION_ORDER.index(related_single_letter_extension), extension[2:]
|
||||
|
||||
|
||||
sorted_single_letter_extensions = sorted(single_letter_extensions, key=SINGLE_LETTER_EXTENSION_ORDER.index)
|
||||
sorted_unprivileged_extensions = sorted(unprivileged_extensions, key=unprivileged_extension_sort_key)
|
||||
sorted_supervisor_extensions = sorted(supervisor_extensions)
|
||||
sorted_hypervisor_extensions = sorted(hypervisor_extensions)
|
||||
sorted_machine_extensions = sorted(machine_extensions)
|
||||
sorted_non_standard_extensions = sorted(non_standard_extensions)
|
||||
|
||||
sorted_extension_file = """\
|
||||
# This file is used to generate the RISC-V Extensions.h header.
|
||||
# It is automatically sorted by Meta/riscv_extensions_generator.py to keep the canonical extension order defined by the RISC-V ISA manual.
|
||||
# To add an extension, simply insert it anywhere in this file and run the script to sort it correctly.
|
||||
|
||||
""" # noqa: E501
|
||||
|
||||
extension_header = """\
|
||||
// This file was automatically generated by Meta/riscv_extensions_generator.py.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
// The extensions are sorted in canonical order, see https://github.com/riscv/riscv-isa-manual/blob/main/src/naming.adoc.
|
||||
|
||||
// 1st argument: extension name (used as our CPUFeature flag name)
|
||||
// 2nd argument: lowercase extension name (used in the devicetree, see https://www.kernel.org/doc/Documentation/devicetree/bindings/riscv/extensions.yaml)
|
||||
// 3rd argument: CPUFeature bitmask index
|
||||
#define ENUMERATE_RISCV_EXTENSIONS(E) \\
|
||||
""" # noqa: E501
|
||||
|
||||
i = 0
|
||||
|
||||
for extension_category, extension_list in (
|
||||
("Single-letter extensions", sorted_single_letter_extensions),
|
||||
("Unprivileged extensions", sorted_unprivileged_extensions),
|
||||
("Supervisor extensions", sorted_supervisor_extensions),
|
||||
("Hypervisor extensions", sorted_hypervisor_extensions),
|
||||
("Machine extensions", sorted_machine_extensions),
|
||||
("Non-standard extensions", sorted_non_standard_extensions),
|
||||
):
|
||||
sorted_extension_file += f"# {extension_category}\n"
|
||||
|
||||
for extension in extension_list:
|
||||
capitalized_extension = extension[0].upper() + extension[1:]
|
||||
extension_header += f" E({capitalized_extension}, {extension}, {i}) \\\n"
|
||||
|
||||
sorted_extension_file += capitalized_extension + "\n"
|
||||
|
||||
i += 1
|
||||
|
||||
sorted_extension_file += "\n"
|
||||
|
||||
# Remove the last trailing " \".
|
||||
extension_header = extension_header.removesuffix(" \\\n")
|
||||
|
||||
extension_header += "\n\n}"
|
||||
|
||||
|
||||
# FIXME: Share this function with TIFFGenerator.py.
|
||||
def update_file(target: Path, new_content: str):
|
||||
should_update = True
|
||||
|
||||
if target.exists():
|
||||
with target.open('r') as file:
|
||||
content = file.read()
|
||||
if content == new_content:
|
||||
should_update = False
|
||||
|
||||
if should_update:
|
||||
with target.open('w') as file:
|
||||
file.write(new_content)
|
||||
|
||||
|
||||
extension_file_path = Path(args.extension_file)
|
||||
extension_header_path = Path(args.output)
|
||||
|
||||
update_file(extension_file_path, sorted_extension_file)
|
||||
|
||||
os.makedirs(extension_header_path.parent, exist_ok=True)
|
||||
update_file(extension_header_path, extension_header)
|
||||
Reference in new issue
Block a user