{"id":20446296,"url":"https://github.com/rust-embedded/qemu-exit","last_synced_at":"2025-12-12T15:02:23.140Z","repository":{"id":36464719,"uuid":"225437555","full_name":"rust-embedded/qemu-exit","owner":"rust-embedded","description":"Exit QEMU with user-defined code","archived":false,"fork":false,"pushed_at":"2025-04-26T23:46:01.000Z","size":414,"stargazers_count":46,"open_issues_count":1,"forks_count":11,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-04-27T00:24:28.493Z","etag":null,"topics":["aarch64","arm64","exit","qemu","session","x86","x86-64"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rust-embedded.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-12-02T18:03:27.000Z","updated_at":"2025-04-26T23:46:04.000Z","dependencies_parsed_at":"2022-07-15T20:17:15.761Z","dependency_job_id":"71091642-7c72-4ed6-9c29-972dc0186772","html_url":"https://github.com/rust-embedded/qemu-exit","commit_stats":null,"previous_names":["andre-richter/qemu-exit"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/rust-embedded/qemu-exit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rust-embedded%2Fqemu-exit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rust-embedded%2Fqemu-exit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rust-embedded%2Fqemu-exit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rust-embedded%2Fqemu-exit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rust-embedded","download_url":"https://codeload.github.com/rust-embedded/qemu-exit/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rust-embedded%2Fqemu-exit/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268636482,"owners_count":24282096,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-03T02:00:12.545Z","response_time":2577,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aarch64","arm64","exit","qemu","session","x86","x86-64"],"created_at":"2024-11-15T10:19:06.106Z","updated_at":"2025-12-12T15:02:22.842Z","avatar_url":"https://github.com/rust-embedded.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![crates.io](https://img.shields.io/crates/d/qemu-exit.svg)](https://crates.io/crates/qemu-exit)\n[![crates.io](https://img.shields.io/crates/v/qemu-exit.svg)](https://crates.io/crates/qemu-exit)\n![Build](https://github.com/rust-embedded/qemu-exit/workflows/Build/badge.svg)\n\n# qemu-exit\n\nExit QEMU with user-defined code.\n\nQuit a running QEMU session with user-defined exit code. Useful for unit or integration tests using\nQEMU.\n\nThis project is developed and maintained by the [libs team].\n\n## TL;DR\n\n```rust\nuse qemu_exit::QEMUExit;\n\n#[cfg(target_arch = \"aarch64\")]\nlet qemu_exit_handle = qemu_exit::AArch64::new();\n\n// addr: The address of sifive_test.\n#[cfg(target_arch = \"riscv64\")]\nlet qemu_exit_handle = qemu_exit::RISCV64::new(addr);\n\n// io_base:             I/O-base of isa-debug-exit.\n// custom_exit_success: A custom success code; Must be an odd number.\n#[cfg(any(target_arch = \"x86\", target_arch = \"x86_64\"))]\nlet qemu_exit_handle = qemu_exit::X86::new(io_base, custom_exit_success);\n\nqemu_exit_handle.exit(1337);\nqemu_exit_handle.exit_success();\nqemu_exit_handle.exit_failure();\n```\n\n## Architecture Specific Configuration\n\n### AArch64/AArch32\n\nPass the `-semihosting` argument to the QEMU invocation, e.g.:\n```\nqemu-system-aarch64 -M raspi3 -serial stdio -semihosting -kernel kernel8.img\nqemu-system-arm -nographic -M mps2-an500 -cpu cortex-m7 -serial mon:stdio -semihosting -kernel\nkernel.img\n```\n\n### RISCV64\n\nYou need to chose a machine with the `sifive_test` device, for exemple `-M virt`:\n```\nqemu-system-riscv64 -M virt -nographic -monitor none -serial stdio -kernel kernel.elf\n```\n\n### x86/x86_64\n\nAdd the special ISA debug exit device by passing the flags:\n```\n-device isa-debug-exit,iobase=0xf4,iosize=0x04\n```\n\nWhen instantiating the handle with `qemu_exit::X86::new()`, `iobase` must be given as the first\nparameter.\n\nThe second parameter must be an `EXIT_SUCCESS` code of your choice that is an odd number, aka\nbit number zero must be `1`. This is needed because in QEMU, the provided code is internally\nbinary-OR'ed with `0x1`. This is hardcoded and therefore, with `isa-debug-exit`, it is not\npossible to let QEMU invoke `exit(0)`.\n\n```rust\nlet qemu_exit_handle = qemu_exit::X86::new(io_base, custom_exit_success);\n```\n\n#### x86/x86_64 Linux\n\nTo use this mechanism from Linux userspace, the kernel must be compiled with\n`CONFIG_X86_IOPL_IOPERM=y` (which is the default) and the process must start with root privileges\n(or `CAP_SYS_RAWIO`) and call: [`ioperm(2)`](https://man7.org/linux/man-pages/man2/ioperm.2.html):\n```rust\nnix::errno::Errno::result(unsafe { libc::ioperm( 0xf4, 4, 1 )}).expect(\"ioperm failed\");\n```\n\nPrivileges/capabilities can then be dropped. Normal users can subsequently call\n`qemu_exit_handle.exit*()`.\n\n## Literature\n\n- [Semihosting for AArch32 and AArch64](https://github.com/ARM-software/abi-aa/blob/main/semihosting/semihosting.rst)\n- [QEMU isa-debug-exit source](https://gitlab.com/qemu-project/qemu/-/blob/master/hw/misc/debugexit.c)\n- [QEMU sifive_test source](https://gitlab.com/qemu-project/qemu/-/blob/master/hw/misc/sifive_test.c)\n\n## Authors\n\n- [**@andre-richter**](https://github.com/andre-richter) Andre Richter\n- [**@Skallwar**](https://github.com/Skallwar) Esteban Blanc\n\n## License\n\nLicensed under either of\n\n- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)\n- MIT License ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)\n\nat your option.\n\nSee the [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md) for more information about utilized third\nparty projects and their respective licenses.\n\n### Contribution\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the\nwork by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any\nadditional terms or conditions.\n\n[libs team]: https://github.com/rust-embedded/wg#the-libs-team\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frust-embedded%2Fqemu-exit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frust-embedded%2Fqemu-exit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frust-embedded%2Fqemu-exit/lists"}