starnix_types/
thread_start_info.rs

1// Copyright 2025 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::arch::ArchWidth;
6use starnix_uapi::user_address::UserAddress;
7use zx::sys::zx_restricted_state_t;
8
9#[cfg(target_arch = "aarch64")]
10use starnix_uapi::user_address::ArchSpecific;
11
12pub struct ThreadStartInfo {
13    pub entry: UserAddress,
14    pub stack: UserAddress,
15    pub environ: UserAddress,
16    pub arch_width: ArchWidth,
17}
18
19#[cfg(target_arch = "aarch64")]
20impl From<ThreadStartInfo> for zx_restricted_state_t {
21    fn from(val: ThreadStartInfo) -> Self {
22        if val.arch_width.is_arch32() {
23            // Mask in 32-bit mode.
24            let mut cpsr = zx::sys::ZX_REG_CPSR_ARCH_32_MASK;
25            // Check if we're starting in thumb.
26            if (val.entry.ptr() & 0x1) == 0x1 {
27                // TODO(https://fxbug.dev/379669623) Need to have checked the ELF hw cap
28                // before this to make sure it's not just misaligned.
29                cpsr |= zx::sys::ZX_REG_CPSR_THUMB_MASK;
30            }
31            let mut reg = zx_restricted_state_t::default();
32            reg.pc = (val.entry.ptr() & !1) as u64;
33            reg.sp = val.stack.ptr() as u64;
34            reg.cpsr = cpsr as u32;
35            reg.r[13] = reg.sp;
36            reg.r[14] = reg.pc;
37            reg.r[0] = reg.sp; // argc
38            reg.r[1] = reg.sp + (size_of::<u32>() as u64); // argv
39            reg.r[2] = val.environ.ptr() as u64; // envp
40            reg
41        } else {
42            let mut reg = zx_restricted_state_t::default();
43            reg.pc = val.entry.ptr() as u64;
44            reg.sp = val.stack.ptr() as u64;
45            reg
46        }
47    }
48}
49
50#[cfg(target_arch = "riscv64")]
51impl From<ThreadStartInfo> for zx_restricted_state_t {
52    fn from(val: ThreadStartInfo) -> Self {
53        let mut reg = zx_restricted_state_t::default();
54        reg.pc = val.entry.ptr() as u64;
55        reg.sp = val.stack.ptr() as u64;
56        reg
57    }
58}
59
60#[cfg(target_arch = "x86_64")]
61impl From<ThreadStartInfo> for zx_restricted_state_t {
62    fn from(val: ThreadStartInfo) -> Self {
63        let mut reg = zx_restricted_state_t::default();
64        reg.ip = val.entry.ptr() as u64;
65        reg.rsp = val.stack.ptr() as u64;
66        reg
67    }
68}