Created
February 11, 2023 23:08
-
-
Save devsnek/ce17a9fa0e0f51bc7305dce6f4e92cbc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::io::Write; | |
fn make_code(ptr: *mut u8) -> usize { | |
use cranelift::prelude::*; | |
let mut flag_builder = settings::builder(); | |
flag_builder.set("is_pic", "true").unwrap(); | |
flag_builder.set("opt_level", "speed_and_size").unwrap(); | |
let flags = settings::Flags::new(flag_builder); | |
let isa = cranelift_native::builder().unwrap().finish(flags); | |
let mut sig = cranelift::codegen::ir::Signature::new(isa.default_call_conv()); | |
sig.params.push(AbiParam::new(types::I32)); | |
sig.params.push(AbiParam::new(types::I32)); | |
let mut ctx = cranelift::codegen::Context::new(); | |
let mut fn_builder_ctx = FunctionBuilderContext::new(); | |
ctx.func = cranelift::codegen::ir::Function::with_name_signature( | |
ExternalName::testcase("_test"), | |
sig, | |
); | |
let mut f = FunctionBuilder::new(&mut ctx.func, &mut fn_builder_ctx); | |
{ | |
let block = f.create_block(); | |
f.append_block_params_for_function_params(block); | |
f.switch_to_block(block); | |
let v0 = f.block_params(block)[0]; | |
let v1 = f.block_params(block)[1]; | |
let v2 = f.ins().iadd(v0, v1); | |
let addr = f.ins().iconst(types::I64, 0x42); | |
f.ins().store(MemFlags::trusted(), v2, addr, 0); | |
f.ins().trap(TrapCode::UnreachableCodeReached); | |
} | |
f.seal_all_blocks(); | |
f.finalize(); | |
cranelift::codegen::verifier::verify_function(&ctx.func, isa.flags()).unwrap(); | |
let code_info = ctx.compile(&*isa).unwrap(); | |
unsafe { | |
ctx.emit_to_memory( | |
ptr, | |
&mut cranelift::codegen::binemit::NullRelocSink {}, | |
&mut cranelift::codegen::binemit::NullTrapSink {}, | |
&mut cranelift::codegen::binemit::NullStackMapSink {}, | |
); | |
} | |
code_info.total_size as usize | |
} | |
fn main() { | |
let kvm = kvm_ioctls::Kvm::new().unwrap(); | |
let vm = kvm.create_vm().unwrap(); | |
let mem_size = 0x4000; | |
let guest_addr = 0x1000; | |
let load_addr: *mut u8 = unsafe { | |
libc::mmap( | |
std::ptr::null_mut(), | |
mem_size, | |
libc::PROT_READ | libc::PROT_WRITE, | |
libc::MAP_ANONYMOUS | libc::MAP_SHARED | libc::MAP_NORESERVE, | |
-1, | |
0, | |
) as *mut u8 | |
}; | |
let mem_region = kvm_bindings::kvm_userspace_memory_region { | |
slot: 0, | |
guest_phys_addr: guest_addr, | |
memory_size: mem_size as u64, | |
userspace_addr: load_addr as u64, | |
flags: 0, | |
}; | |
unsafe { vm.set_user_memory_region(mem_region).unwrap() }; | |
make_code(load_addr); | |
let vcpu_fd = vm.create_vcpu(0).unwrap(); | |
let mut vcpu_sregs = vcpu_fd.get_sregs().unwrap(); | |
vcpu_sregs.cs.base = 0; | |
vcpu_sregs.cs.selector = 0; | |
vcpu_fd.set_sregs(&vcpu_sregs).unwrap(); | |
let mut vcpu_regs = vcpu_fd.get_regs().unwrap(); | |
vcpu_regs.rip = guest_addr; | |
vcpu_regs.rax = 2; | |
vcpu_regs.rbx = 3; | |
vcpu_regs.rflags = 2; | |
vcpu_fd.set_regs(&vcpu_regs).unwrap(); | |
loop { | |
use kvm_ioctls::VcpuExit; | |
match vcpu_fd.run().expect("run failed") { | |
VcpuExit::IoOut(addr, data) => { | |
match addr { | |
0x80 => { | |
break; | |
} | |
0x3f8 => { | |
std::io::stdout().write(data).unwrap(); | |
} | |
_ => panic!("{}", addr), | |
} | |
} | |
e @ VcpuExit::InternalError => panic!("{:?}", e), | |
r => println!("Unexpected exit reason: {:?}", r), | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment