Skip to content

Commit 0a04ca2

Browse files
committed
Update lk build target to support arm32 builds
1 parent 7834af2 commit 0a04ca2

File tree

6 files changed

+70
-15
lines changed

6 files changed

+70
-15
lines changed

pycheribuild/config/compilation_targets.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,8 @@ def base_sysroot_targets(cls, target: "CrossCompileTarget", config: "CheriConfig
10331033

10341034
@classmethod
10351035
def triple_for_target(cls, target: "CrossCompileTarget", config: "CheriConfig", *, include_version: bool) -> str:
1036+
if target.cpu_architecture == CPUArchitecture.ARM32:
1037+
return "armv7-unknown-none-eabi" # TODO: Use an ArmV8 triple once QEMU supports it
10361038
return target.cpu_architecture.value + "-unknown-elf"
10371039

10381040
@property
@@ -1336,6 +1338,8 @@ class CompilationTargets(BasicCompilationTargets):
13361338
BAREMETAL_NEWLIB_RISCV64_HYBRID,
13371339
BAREMETAL_NEWLIB_RISCV64_PURECAP,
13381340
)
1341+
FREESTANDING_ARM32 = CrossCompileTarget("arm32", CPUArchitecture.ARM32, BaremetalFreestandingTargetInfo)
1342+
FREESTANDING_AARCH64 = CrossCompileTarget("aarch64", CPUArchitecture.AARCH64, BaremetalFreestandingTargetInfo)
13391343
FREESTANDING_MIPS64 = CrossCompileTarget("mips64", CPUArchitecture.MIPS64, BaremetalFreestandingTargetInfo)
13401344
FREESTANDING_MORELLO_NO_CHERI = CrossCompileTarget(
13411345
"morello-aarch64",
@@ -1389,6 +1393,8 @@ class CompilationTargets(BasicCompilationTargets):
13891393
hybrid_target=FREESTANDING_RISCV64_HYBRID,
13901394
)
13911395
ALL_FREESTANDING_TARGETS = (
1396+
FREESTANDING_AARCH64,
1397+
FREESTANDING_ARM32,
13921398
FREESTANDING_MIPS64,
13931399
FREESTANDING_MORELLO_NO_CHERI,
13941400
FREESTANDING_MORELLO_HYBRID,

pycheribuild/config/target_info.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -971,6 +971,9 @@ def is_riscv64(self, include_purecap: Optional[bool] = None) -> bool:
971971
def is_riscv(self, include_purecap: Optional[bool] = None) -> bool:
972972
return self.is_riscv32(include_purecap) or self.is_riscv64(include_purecap)
973973

974+
def is_arm32(self, include_purecap: Optional[bool] = None) -> bool:
975+
return self._check_arch(CPUArchitecture.ARM32, include_purecap)
976+
974977
def is_aarch64(self, include_purecap: Optional[bool] = None) -> bool:
975978
return self._check_arch(CPUArchitecture.AARCH64, include_purecap)
976979

pycheribuild/projects/cross/littlekernel.py

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
from .compiler_rt import BuildCompilerRtBuiltins
2929
from .crosscompileproject import CompilationTargets, CrossCompileMakefileProject, GitRepository
30+
from ..build_qemu import BuildQEMU
3031
from ..project import DefaultInstallDir
3132
from ..run_qemu import LaunchQEMUBase
3233
from ..simple_project import BoolConfigOption
@@ -39,8 +40,11 @@ class BuildLittleKernel(CrossCompileMakefileProject):
3940
target = "littlekernel"
4041
default_directory_basename = "lk"
4142
supported_architectures = (
43+
CompilationTargets.FREESTANDING_ARM32,
44+
CompilationTargets.FREESTANDING_AARCH64,
4245
CompilationTargets.FREESTANDING_MORELLO_NO_CHERI,
4346
CompilationTargets.FREESTANDING_MORELLO_PURECAP,
47+
CompilationTargets.FREESTANDING_RISCV32,
4448
CompilationTargets.FREESTANDING_RISCV64,
4549
CompilationTargets.FREESTANDING_RISCV64_PURECAP,
4650
)
@@ -97,22 +101,28 @@ def setup(self):
97101
self.make_args.set(BUILDROOT=self.build_dir)
98102
if self.config.verbose:
99103
self.make_args.set(NOECHO="")
100-
for var in ["CFLAGS", "CPPFLAGS", "CXXFLAGS", "LDFLAGS"]:
104+
for var in ["CFLAGS", "CPPFLAGS", "CXXFLAGS", "LDFLAGS", "AR"]:
101105
del self.make_args.env_vars[var]
102-
toolchain_prefix = str(self.sdk_bindir) + "/"
103-
if self.compiling_for_riscv(include_purecap=True):
104-
# Use hardfloat to avoid libgcc deps
105-
self.make_args.set(RISCV_FPU=True)
106106
if self.compiling_for_cheri():
107107
self.make_args.set(ARCH_COMPILEFLAGS="") # dont' override the default -mabi=
108108

109+
if self.compiling_for_arm32():
110+
# Work around "error: unknown argument: '-mthumb-interwork'"
111+
self.make_args.set(ENABLE_THUMB=0)
112+
109113
self.set_make_cmd_with_args("LD", self.target_info.linker, ["--unresolved-symbols=report-all"])
110-
if self.crosscompile_target.is_riscv(include_purecap=True) and self.use_mmu:
114+
if self.crosscompile_target.is_riscv64(include_purecap=True) and self.use_mmu:
111115
self.make_args.set(RISCV_MMU="sv39", RISCV_MODE="supervisor")
116+
# Use hardfloat to avoid libgcc deps
117+
self.make_args.set(RISCV_FPU=1)
118+
elif self.crosscompile_target.is_riscv32(include_purecap=True):
119+
if self.use_mmu:
120+
self.make_args.set(RISCV_MMU="sv32", RISCV_MODE="supervisor")
121+
# Use softfloat to match compiler-rt ABI
122+
self.make_args.set(RISCV_FPU=0)
112123
self.make_args.set(
113-
TOOLCHAIN_PREFIX=toolchain_prefix,
114-
ARCH_arm64_TOOLCHAIN_PREFIX=toolchain_prefix,
115-
ARCH_riscv64_TOOLCHAIN_PREFIX=toolchain_prefix,
124+
TOOLCHAIN_PREFIX=str(self.sdk_bindir) + "/llvm-",
125+
CPPFILT=self.sdk_bindir / "llvm-cxxfilt", # does not match the normal llvm-<binutil> pattern
116126
)
117127

118128
def setup_late(self) -> None:
@@ -123,15 +133,20 @@ def setup_late(self) -> None:
123133
def kernel_path(self) -> Path:
124134
if self.compiling_for_aarch64(include_purecap=True):
125135
return self.build_dir / "build-qemu-virt-arm64-test/lk.elf"
126-
elif self.compiling_for_riscv(include_purecap=True):
136+
elif self.crosscompile_target.is_riscv32(include_purecap=True):
137+
return self.build_dir / "build-qemu-virt-riscv32-test/lk.elf"
138+
elif self.crosscompile_target.is_riscv64(include_purecap=True):
127139
return self.build_dir / "build-qemu-virt-riscv64-test/lk.elf"
140+
elif self.compiling_for_arm32():
141+
return self.build_dir / "build-qemu-virt-arm32-test/lk.elf"
128142
else:
129143
raise ValueError("Unsupported arch")
130144

131145
def run_tests(self):
146+
qemu = BuildQEMU.qemu_binary(self, xtarget=self.crosscompile_target)
132147
if self.compiling_for_aarch64(include_purecap=True):
133148
cmd = [
134-
self.config.qemu_bindir / "qemu-system-aarch64",
149+
qemu,
135150
"-cpu",
136151
"cortex-a53",
137152
"-m",
@@ -151,9 +166,9 @@ def run_tests(self):
151166
if self.use_mmu:
152167
bios_args = riscv_bios_arguments(self.crosscompile_target, self)
153168
cmd = [
154-
self.config.qemu_bindir / "qemu-system-riscv64cheri",
169+
qemu,
155170
"-cpu",
156-
"rv64",
171+
"rv64" if self.crosscompile_target.is_riscv64(include_purecap=True) else "rv32",
157172
"-m",
158173
"512",
159174
"-smp",
@@ -167,6 +182,23 @@ def run_tests(self):
167182
self.kernel_path,
168183
*bios_args,
169184
]
185+
elif self.compiling_for_arm32():
186+
cmd = [
187+
qemu,
188+
"-cpu",
189+
"cortex-a15",
190+
"-m",
191+
"512",
192+
"-smp",
193+
"1",
194+
"-machine",
195+
"virt,highmem=off",
196+
"-net",
197+
"none",
198+
"-nographic",
199+
"-kernel",
200+
self.kernel_path,
201+
]
170202
else:
171203
return self.fatal("Unsupported arch")
172204
self.run_cmd(cmd, cwd=self.build_dir, give_tty_control=True)
@@ -175,7 +207,10 @@ def compile(self, **kwargs):
175207
if self.compiling_for_aarch64(include_purecap=True):
176208
self.run_make("qemu-virt-arm64-test", cwd=self.source_dir, parallel=True)
177209
elif self.compiling_for_riscv(include_purecap=True):
178-
self.run_make("qemu-virt-riscv64-test", cwd=self.source_dir, parallel=True)
210+
xlen = 64 if self.crosscompile_target.is_riscv64(include_purecap=True) else 32
211+
self.run_make(f"qemu-virt-riscv{xlen}-test", cwd=self.source_dir, parallel=True)
212+
elif self.compiling_for_arm32():
213+
self.run_make("qemu-virt-arm32-test", cwd=self.source_dir, parallel=True)
179214
else:
180215
return self.fatal("Unsupported arch")
181216

pycheribuild/projects/run_qemu.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,11 @@ def get_chosen_qemu(cls, config: CheriConfig):
261261
supported_qemu_classes += [BuildQEMU]
262262
if not xtarget.is_hybrid_or_purecap_cheri():
263263
supported_qemu_classes += [BuildUpstreamQEMU, None]
264-
elif xtarget.is_any_x86() or xtarget.is_aarch64(include_purecap=False):
264+
elif xtarget.is_arm32(include_purecap=False):
265+
can_provide_src_via_smb = True
266+
# Prefer CHERI QEMU for AArch64 like other architectures.
267+
supported_qemu_classes += [BuildQEMU, BuildUpstreamQEMU, None]
268+
elif xtarget.is_any_x86():
265269
# Default to CHERI QEMU instead of the system QEMU (for now)
266270
# Note: x86_64 can be either CHERI QEMU or system QEMU:
267271
supported_qemu_classes += [BuildQEMU, BuildUpstreamQEMU, None]

pycheribuild/projects/simple_project.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,9 @@ def compiling_for_riscv(self, include_purecap: bool) -> bool:
789789
def compiling_for_aarch64(self, include_purecap: bool) -> bool:
790790
return self.crosscompile_target.is_aarch64(include_purecap=include_purecap)
791791

792+
def compiling_for_arm32(self) -> bool:
793+
return self.crosscompile_target.is_arm32()
794+
792795
def build_configuration_suffix(self, target: Optional[CrossCompileTarget] = None) -> str:
793796
"""
794797
:param target: the target to use

pycheribuild/qemu_utils.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ def __init__(self, xtarget: CrossCompileTarget, want_debugger=False) -> None:
8686
self.qemu_arch_sufffix = "aarch64"
8787
self.can_boot_kernel_directly = False # boot from disk
8888
self.machine_flags = ["-M", "virt,gic-version=3", "-cpu", "cortex-a72", "-bios", "edk2-aarch64-code.fd"]
89+
elif xtarget.is_arm32(include_purecap=False):
90+
self.qemu_arch_sufffix = "arm"
91+
self.can_boot_kernel_directly = False # boot from disk
92+
self.machine_flags = ["-M", "virt", "-cpu", "cortex-15"]
8993
else:
9094
raise ValueError("Unknown target " + str(xtarget))
9195

0 commit comments

Comments
 (0)