kernel/memop.rs
1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Implementation of the MEMOP family of syscalls.
6
7use crate::process::Process;
8use crate::syscall::SyscallReturn;
9use crate::utilities::capability_ptr::{CapabilityPtr, CapabilityPtrPermissions};
10use crate::ErrorCode;
11
12/// Handle the `memop` syscall.
13///
14/// ### `memop_num`
15///
16/// - `0`: BRK. Change the location of the program break and return a
17/// SyscallReturn.
18/// - `1`: SBRK. Change the location of the program break and return the
19/// previous break address.
20/// - `2`: Get the address of the start of the application's RAM allocation.
21/// - `3`: Get the address pointing to the first address after the end of the
22/// application's RAM allocation.
23/// - `4`: Get the address of the start of the application's flash region. This
24/// is where the TBF header is located.
25/// - `5`: Get the address pointing to the first address after the end of the
26/// application's flash region.
27/// - `6`: Get the address of the lowest address of the grant region for the
28/// app.
29/// - `7`: Get the number of writeable flash regions defined in the header of
30/// this app.
31/// - `8`: Get the start address of the writeable region indexed from 0 by r1.
32/// Returns (void*) -1 on failure, meaning the selected writeable region
33/// does not exist.
34/// - `9`: Get the end address of the writeable region indexed by r1. Returns
35/// (void*) -1 on failure, meaning the selected writeable region does not
36/// exist.
37/// - `10`: Specify where the start of the app stack is. This tells the kernel
38/// where the app has put the start of its stack. This is not strictly
39/// necessary for correct operation, but allows for better debugging if the
40/// app crashes.
41/// - `11`: Specify where the start of the app heap is. This tells the kernel
42/// where the app has put the start of its heap. This is not strictly
43/// necessary for correct operation, but allows for better debugging if the
44/// app crashes.
45pub(crate) fn memop(process: &dyn Process, op_type: usize, r1: usize) -> SyscallReturn {
46 match op_type {
47 // Op Type 0: BRK
48 0 => process
49 .brk(r1 as *const u8)
50 .map(|_| SyscallReturn::Success)
51 .unwrap_or(SyscallReturn::Failure(ErrorCode::NOMEM)),
52
53 // Op Type 1: SBRK
54 1 => process
55 .sbrk(r1 as isize)
56 .map(|addr| SyscallReturn::SuccessPtr(addr))
57 .unwrap_or(SyscallReturn::Failure(ErrorCode::NOMEM)),
58
59 // Op Type 2: Process memory start
60 2 => SyscallReturn::SuccessPtr(unsafe {
61 let addresses = process.get_addresses();
62 CapabilityPtr::new_with_authority(
63 addresses.sram_start as *const _,
64 addresses.sram_start,
65 addresses.sram_app_brk - addresses.sram_start,
66 CapabilityPtrPermissions::ReadWrite,
67 )
68 }),
69
70 // Op Type 3: Process memory end
71 3 => SyscallReturn::SuccessPtr(unsafe {
72 let addresses = process.get_addresses();
73 CapabilityPtr::new_with_authority(
74 addresses.sram_end as *const _,
75 addresses.sram_start,
76 addresses.sram_end - addresses.sram_start,
77 CapabilityPtrPermissions::ReadWrite,
78 )
79 }),
80
81 // Op Type 4: Process flash start
82 4 => SyscallReturn::SuccessPtr(unsafe {
83 let addresses = process.get_addresses();
84 CapabilityPtr::new_with_authority(
85 addresses.flash_start as *const _,
86 addresses.flash_start,
87 addresses.flash_end - addresses.flash_start,
88 CapabilityPtrPermissions::Execute,
89 )
90 }),
91
92 // Op Type 5: Process flash end
93 5 => SyscallReturn::SuccessPtr(unsafe {
94 let addresses = process.get_addresses();
95 CapabilityPtr::new_with_authority(
96 addresses.flash_end as *const _,
97 addresses.flash_start,
98 addresses.flash_end - addresses.flash_start,
99 CapabilityPtrPermissions::Execute,
100 )
101 }),
102
103 // Op Type 6: Grant region begin
104 6 => SyscallReturn::SuccessAddr(process.get_addresses().sram_grant_start),
105
106 // Op Type 7: Number of defined writeable regions in the TBF header.
107 7 => SyscallReturn::SuccessU32(process.number_writeable_flash_regions() as u32),
108
109 // Op Type 8: The start address of the writeable region indexed by r1.
110 8 => {
111 let flash_start = process.get_addresses().flash_start;
112 let (offset, size) = process.get_writeable_flash_region(r1);
113 if size == 0 {
114 SyscallReturn::Failure(ErrorCode::FAIL)
115 } else {
116 SyscallReturn::SuccessPtr(unsafe {
117 CapabilityPtr::new_with_authority(
118 (flash_start + offset) as *const _,
119 flash_start + offset,
120 size,
121 CapabilityPtrPermissions::ReadWrite,
122 )
123 })
124 }
125 }
126
127 // Op Type 9: The end address of the writeable region indexed by r1.
128 // Returns (void*) -1 on failure, meaning the selected writeable region
129 // does not exist.
130 9 => {
131 let flash_start = process.get_addresses().flash_start;
132 let (offset, size) = process.get_writeable_flash_region(r1);
133 if size == 0 {
134 SyscallReturn::Failure(ErrorCode::FAIL)
135 } else {
136 SyscallReturn::SuccessPtr(unsafe {
137 CapabilityPtr::new_with_authority(
138 (flash_start + offset + size) as *const _,
139 flash_start + offset,
140 size,
141 CapabilityPtrPermissions::ReadWrite,
142 )
143 })
144 }
145 }
146
147 // Op Type 10: Specify where the start of the app stack is.
148 10 => {
149 process.update_stack_start_pointer(r1 as *const u8);
150 SyscallReturn::Success
151 }
152
153 // Op Type 11: Specify where the start of the app heap is.
154 11 => {
155 process.update_heap_start_pointer(r1 as *const u8);
156 SyscallReturn::Success
157 }
158
159 _ => SyscallReturn::Failure(ErrorCode::NOSUPPORT),
160 }
161}