摘要
新增記憶體對應。
宣告
#include <zircon/syscalls.h>
zx_status_t zx_vmar_map(zx_handle_t handle,
zx_vm_option_t options,
size_t vmar_offset,
zx_handle_t vmo,
uint64_t vmo_offset,
size_t len,
zx_vaddr_t* mapped_addr);
說明
將指定的 VMO 對應至指定的虛擬記憶體位址區域。對應關係會保留對基礎虛擬記憶體物件的參照,因此關閉 VMO 控制代碼不會移除這個函式新增的對應關係。
options 是下列項目的位元向量:
ZX_VM_SPECIFIC使用 vmar_offset 放置對應,如果 handle 沒有ZX_VM_CAN_MAP_SPECIFIC權限,則無效。vmar_offset 是相對於指定 VMAR 基本位址的偏移量。指定與其他 VMAR 或對應重疊的範圍會發生錯誤。ZX_VM_SPECIFIC_OVERWRITE與ZX_VM_SPECIFIC相同,但可以與其他對應重疊。部分重疊另一個 VMAR 仍會發生錯誤。如果範圍符合這些規定,系統會以原子方式 (相對於所有其他對應/取消對應/保護作業),取代 vmar_offset 和 len 指定範圍中的現有對應。如果該範圍與任何對應關係部分重疊,則範圍外的對應關係部分仍會保持對應。ZX_VM_OFFSET_IS_UPPER_LIMIT將 vmar_offset 解讀為上限,藉此限制核心選取的偏移量。如果 handle 沒有ZX_VM_CAN_MAP_SPECIFIC權限,這個值就會無效。產生的對應項目會具有偏移量 + len,且該偏移量 <= vmar_base + vmar_offset。如果使用ZX_VM_SPECIFIC或ZX_VM_SPECIFIC_OVERWRITE,則無法指定這個選項。ZX_VM_PERM_READ將 vmo 對應為可讀取。 如果 handle 沒有ZX_VM_CAN_MAP_READ權限、handle 沒有ZX_RIGHT_READ權限,或 vmo handle 沒有ZX_RIGHT_READ權限,就會發生錯誤。ZX_VM_PERM_WRITE將 Map vmo 設為可寫入。 如果 控制代碼 沒有ZX_VM_CAN_MAP_WRITE權限、控制代碼 沒有ZX_RIGHT_WRITE權限、vmo 控制代碼沒有ZX_RIGHT_WRITE權限,或 選項 未指定ZX_VM_PERM_READ,則會發生錯誤。ZX_VM_PERM_EXECUTE將 vmo 對應為可執行檔。如果 handle 沒有ZX_VM_CAN_MAP_EXECUTE權限、handle 控制代碼沒有ZX_RIGHT_EXECUTE權限、vmo 控制代碼沒有ZX_RIGHT_EXECUTE權限,或 options 未指定ZX_VM_PERM_READ,就會發生錯誤。ZX_VM_MAP_RANGE立即將所有 VMO 的備份區域分頁到新對應中。如果使用ZX_VM_SPECIFIC_OVERWRITE,則無法指定這個選項。ZX_VM_ALLOW_FAULTS如果建立的對應項目可能會產生錯誤,則為必填欄位。特別是當 vmo 可調整大小、設定ZX_VM_FAULT_BEYOND_STREAM_SIZE、vmo 不可調整大小但對應項延伸超過 vmo 結尾、vmo 可捨棄,或是 vmo 是從zx_pager_create_vmo()建立時,就必須提供這項資訊。ZX_VM_PERM_READ_IF_XOM_UNSUPPORTED如果系統不支援對應僅供執行的頁面,請將 vmo 對應為可讀取。如果系統可以對應僅執行的旗標,系統會忽略這個旗標。ZX_VM_REQUIRE_NON_RESIZABLE如果 vmo 可調整大小,則會失敗。ZX_VM_FAULT_BEYOND_STREAM_SIZE如果記憶體存取超出串流大小 (向上捨入至頁面邊界),就會發生錯誤。需要「ZX_VM_ALLOW_FAULTS」欄。
如果 options 未設定 ZX_VM_SPECIFIC、ZX_VM_SPECIFIC_OVERWRITE 或 ZX_VM_OFFSET_IS_UPPER_LIMIT,vmar_offset 必須為 0。
ZX_VM_OFFSET_IS_UPPER_LIMIT 用於限制選取範圍,否則行為與未設定 ZX_VM_SPECIFIC 或 ZX_VM_SPECIFIC_OVERWRITE 的情況類似,對應會由核心隨機指派偏移量 (分配器由目標 VMAR 上設定的政策決定)。
len 不得為零,且會在內部向上捨入,以與頁面對齊。
此外,還可以新增下列其中一個 2 的冪對齊標記:
ZX_VM_ALIGN_1KB會將 child_addr 對齊至少 1 KB 的 2 的乘方。ZX_VM_ALIGN_2KB會將 child_addr 對齊至至少 2K 位元組的 2 的乘方。ZX_VM_ALIGN_4KB會將 child_addr 對齊至至少 4K 位元組的 2 的冪。ZX_VM_ALIGN_8KB會將 child_addr 對齊至至少 8K 位元組的 2 的乘方。
並持續到
ZX_VM_ALIGN_4GB會將 child_addr 對齊至少 4G 位元組的 2 的乘方。
如果 vmar 基本位址 + vmo_offset 未與要求的值對齊,則搭配 ZX_VM_SPECIFIC 使用 ZX_VM_ALIGN 旗標會失敗。
權限
handle 必須為 ZX_OBJ_TYPE_VMAR 類型。
vmo 必須為 ZX_OBJ_TYPE_VMO 類型。
傳回值
zx_vmar_map() 會傳回 ZX_OK 和對應的絕對基準位址 (透過 mapped_addr)。基底位址會與頁面對齊,且不得為零。如果失敗,系統會傳回負數錯誤值。
錯誤
ZX_ERR_BAD_HANDLE handle 或 vmo 不是有效的控制代碼。
ZX_ERR_WRONG_TYPE handle 或 vmo 不是 VMAR 或 VMO 控制代碼。
ZX_ERR_BAD_STATE handle 是指已毀損的 VMAR。
ZX_ERR_INVALID_ARGS,適用於下列任一情況:
- mapped_addr 或 options 無效。
- 如果未指定
ZX_VM_SPECIFIC、ZX_VM_SPECIFIC_OVERWRITE或ZX_VM_OFFSET_IS_UPPER_LIMIT,vmar_offset 就不得為零。 - 同時指定
ZX_VM_SPECIFIC_OVERWRITE和ZX_VM_MAP_RANGE。 ZX_VM_OFFSET_IS_UPPER_LIMIT與ZX_VM_SPECIFIC或ZX_VM_SPECIFIC_OVERWRITE一併指定。- vmar_offset 和 len 說明因超出區域界限而無法滿足的分配。
- vmar_offset 或 vmo_offset 未與網頁對齊。
- len 為 0。
已指定 ZX_ERR_ALREADY_EXISTS ZX_VM_SPECIFIC,但未指定 ZX_VM_SPECIFIC_OVERWRITE,且要求的範圍與其他對應重疊。
ZX_ERR_NO_RESOURCES VMAR 中找不到可建立對應的地點。
ZX_ERR_ACCESS_DENIED 權限不足,無法進行要求的對應。
ZX_ERR_NOT_SUPPORTED 如果 vmo 可調整大小、可捨棄或由分頁器支援,但未設定 ZX_VM_ALLOW_FAULTS。
ZX_ERR_NOT_SUPPORTED 如果 vmo 可調整大小,且已設定 ZX_VM_REQUIRE_NON_RESIZABLE。或者,ZX_VM_FAULT_BEYOND_STREAM_SIZE 已設定,且 vmo 是實體或連續。
ZX_ERR_BUFFER_TOO_SMALL VMO 無法調整大小,且對應範圍超出 VMO 結尾,但 ZX_VM_ALLOW_FAULTS 未設定。
ZX_ERR_NO_MEMORY 記憶體不足,因此失敗。
使用者空間無法妥善處理這項 (不太可能發生的) 錯誤。
這個錯誤不會出現在日後的版本中。
ZX_ERR_OUT_OF_RANGE vmo_offset + ROUNDUP(len, PAGE_SIZE) 溢位。
附註
支援記憶體對應的 VMO 可以縮小大小。這會導致執行緒讀取或寫入 VMAR 區域時發生錯誤。為避免這種危險,從用戶端接收 VMO 的服務應使用 ZX_VM_REQUIRE_NON_RESIZABLE 對應 VMO。