You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: switch.rs
    path of file: ./repos/kernel/src/arch/aarch64/kernel
    
    the code of the file until where you have to start completion: use core::arch::asm;
use core::{mem, ptr};

macro_rules! kernel_function_impl {
	($kernel_function:ident($($arg:ident: $A:ident),*) { $($operands:tt)* }) => {
		/// Executes `f` on the kernel stack.
		#[allow(dead_code)]
		pub fn $kernel_function<R, $($A),*>(f: unsafe extern "C" fn($($A),*) -> R, $($arg: $A),*) -> R {
			unsafe {
				assert!(mem::size_of::<R>() <= mem::size_of::<usize>());

				$(
					assert!(mem::size_of::<$A>() <= mem::size_of::<usize>());
					let $arg = {
						let mut reg = 0_usize;
						// SAFETY: $A is smaller than usize and directly fits in a register
						// Since f takes $A as argument via C calling convention, any opper bytes do not matter.
						ptr::write(ptr::from_mut(&mut reg) as _, $arg);
						reg
					};
				)*

				let ret: u64;
				asm!(
					// Switch to kernel stack
					"msr spsel, {l1}",

					// To make sure, Rust manages t
    
		pub fn $kernel_function<R, $($A),*>(f: unsafe extern "C" fn($($A),*) -> R, $($arg: $A),*) -> R {
			unsafe {
				assert!(mem::size_of::<R>() <= mem::size_of::<usize>());

				$(
					assert!(mem::size_of::<$A>() <= mem::size_of::<usize>());
					let $arg = {
						let mut reg = 0_usize;
						// SAFETY: $A is smaller than usize and directly fits in a register
						// Since f takes $A as argument via C calling convention, any opper bytes do not matter.
						ptr::write(ptr::from_mut(&mut reg) as _, $arg);
						reg
					};
				)*

				let ret: u64;
				asm!(
					// Switch to kernel stack
					"msr spsel, {l1}",

					// To make sure, Rust manages the stack in `f` correctly,
					// we keep all arguments and return values in registers
					// until we switch the stack back. Thus follows the sizing
					// requirements for arguments and return types.
					"blr {f}",

					// Switch back to user stack
					"msr spsel, {l0}",

					l0 = const 0,
					l1 = const 1,
					f = in(reg) f,

					$($operands)*

					// Return argument in x0
					lateout("x0") ret,

					clobber_abi("C"),
				);

				// SAFETY: R is smaller than usize and directly fits in rax
				// Since f returns R, we can safely convert ret to R
				mem::transmute_copy(&ret)
			}
		}