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_thread_state_general_regs_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_thread_state_general_regs_t {
21    fn from(val: ThreadStartInfo) -> Self {
22        if val.arch_width.is_arch32() {
23            // Mask in 32-bit mode.
24            let mut cpsr: u64 = 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_thread_state_general_regs_t {
32                pc: (val.entry.ptr() & !1) as u64,
33                sp: val.stack.ptr() as u64,
34                cpsr,
35                ..Default::default()
36            };
37            reg.r[13] = reg.sp;
38            reg.r[14] = reg.pc;
39            reg.r[0] = reg.sp; // argc
40            reg.r[1] = reg.sp + (size_of::<u32>() as u64); // argv
41            reg.r[2] = val.environ.ptr() as u64; // envp
42            reg
43        } else {
44            zx_thread_state_general_regs_t {
45                pc: val.entry.ptr() as u64,
46                sp: val.stack.ptr() as u64,
47                ..Default::default()
48            }
49        }
50    }
51}
52
53#[cfg(target_arch = "riscv64")]
54impl From<ThreadStartInfo> for zx_thread_state_general_regs_t {
55    fn from(val: ThreadStartInfo) -> Self {
56        zx_thread_state_general_regs_t {
57            pc: val.entry.ptr() as u64,
58            sp: val.stack.ptr() as u64,
59            ..Default::default()
60        }
61    }
62}
63
64#[cfg(target_arch = "x86_64")]
65impl From<ThreadStartInfo> for zx_thread_state_general_regs_t {
66    fn from(val: ThreadStartInfo) -> Self {
67        zx_thread_state_general_regs_t {
68            rip: val.entry.ptr() as u64,
69            rsp: val.stack.ptr() as u64,
70            ..Default::default()
71        }
72    }
73}