| // Copyright 2017 The Fuchsia Authors | 
 | // | 
 | // Use of this source code is governed by a MIT-style | 
 | // license that can be found in the LICENSE file or at | 
 | // https://opensource.org/licenses/MIT | 
 |  | 
 | #ifndef ZIRCON_KERNEL_INCLUDE_MEXEC_H_ | 
 | #define ZIRCON_KERNEL_INCLUDE_MEXEC_H_ | 
 |  | 
 | #define MEMMOV_OPS_DST_OFFSET (0) | 
 | #define MEMMOV_OPS_SRC_OFFSET (8) | 
 | #define MEMMOV_OPS_LEN_OFFSET (16) | 
 | #define MEMMOV_OPS_STRUCT_LEN (24) | 
 | #define MAX_OPS_PER_PAGE      (169)    // Calculated below | 
 |  | 
 | #ifndef __ASSEMBLER__ | 
 |  | 
 | #include <stddef.h> | 
 | #include <stdint.h> | 
 | #include <zircon/compiler.h> | 
 | #include <zircon/types.h> | 
 |  | 
 | #include <fbl/ref_ptr.h> | 
 | #include <vm/vm_object.h> | 
 |  | 
 | // Warning: The geometry of this struct is depended upon by the mexec assembly | 
 | //          function. Do not modify without also updating mexec.S. | 
 | typedef struct __PACKED { | 
 |   void* dst; | 
 |   void* src; | 
 |   size_t len; | 
 | } memmov_ops_t; | 
 |  | 
 | static_assert(sizeof(memmov_ops_t) == MEMMOV_OPS_STRUCT_LEN, | 
 |               "sizeof memmov_ops_t must match MEMMOV_OPS_STRUCT_LEN"); | 
 |  | 
 | #define MAX_OPS_PER_PAGE_DEF ((PAGE_SIZE / MEMMOV_OPS_STRUCT_LEN) - 1) | 
 | static_assert(MAX_OPS_PER_PAGE_DEF == MAX_OPS_PER_PAGE, | 
 |               "Calculated max ops per page must match literal value"); | 
 |  | 
 | // Implemented in assembly. Copies the new kernel into place and branches to it. | 
 | typedef void (*mexec_asm_func)(uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t aux, | 
 |                                memmov_ops_t* ops, void* new_kernel_addr); | 
 |  | 
 | // Save the crashlog for propagation to the next kernel. | 
 | void mexec_stash_crashlog(fbl::RefPtr<VmObject> vmo); | 
 |  | 
 | /* Allow the platform to patch the zbi structure with any platform specific | 
 |  * data that might be necessary for the kernel that mexec is chain-loading. | 
 |  */ | 
 | zx_status_t platform_mexec_patch_zbi(uint8_t* bootdata, const size_t len); | 
 |  | 
 | /* This function is called at the beginning of mexec.  Interrupts are not yet | 
 |  * disabled, but only one CPU is running. | 
 |  */ | 
 | void platform_mexec_prep(uintptr_t final_bootimage_addr, size_t final_bootimage_len); | 
 |  | 
 | /* Ask the platform to mexec into the next kernel. | 
 |  * This function is called after platform_mexec_prep(), with interrupts disabled. | 
 |  */ | 
 | void platform_mexec(mexec_asm_func mexec_assembly, memmov_ops_t* ops, uintptr_t new_bootimage_addr, | 
 |                     size_t new_bootimage_len, uintptr_t entry64_addr); | 
 |  | 
 | /* Allocate |count| pages where no page has a physical address less than | 
 |  * |lower_bound|. | 
 |  * Results are returned via the array pointed to by |paddrs| with the | 
 |  * assumption there is enough storage to contain |count| results. | 
 |  * |limit| defines the highest address to search before giving up. | 
 |  */ | 
 | zx_status_t alloc_pages_greater_than(paddr_t lower_bound, size_t count, size_t limit, | 
 |                                      paddr_t* paddrs); | 
 |  | 
 |  | 
 | static_assert(__offsetof(memmov_ops_t, dst) == MEMMOV_OPS_DST_OFFSET, ""); | 
 | static_assert(__offsetof(memmov_ops_t, src) == MEMMOV_OPS_SRC_OFFSET, ""); | 
 | static_assert(__offsetof(memmov_ops_t, len) == MEMMOV_OPS_LEN_OFFSET, ""); | 
 |  | 
 | #endif  // __ASSEMBLER__ | 
 |  | 
 | #endif  // ZIRCON_KERNEL_INCLUDE_MEXEC_H_ |