This repository was archived by the owner on Mar 24, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 167
[WIP] Lucet i686 (32-bit x86) support... ish #508
Draft
iximeow
wants to merge
1
commit into
main
Choose a base branch
from
ixi/i686
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+2,284
−773
Draft
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| pub mod val; |
318 changes: 318 additions & 0 deletions
318
lucet-runtime/lucet-runtime-internals/src/archdeps/i686/val.rs
This file contains hidden or 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,318 @@ | ||
| //! Typed values for passing into and returning from sandboxed | ||
| //! programs. | ||
| use libc::c_void; | ||
| use std::arch::x86::{ | ||
| __m128, _mm_castpd_ps, _mm_castps_pd, _mm_load_pd1, _mm_load_ps1, _mm_setzero_ps, | ||
| _mm_storeu_pd, _mm_storeu_ps, | ||
| }; | ||
|
|
||
| use lucet_module::ValueType; | ||
|
|
||
| impl Val { | ||
| pub fn value_type(&self) -> ValueType { | ||
| match self { | ||
| // USize, ISize, and CPtr are all as fits for definitions on the target architecture | ||
| // (wasm) which is all 32-bit. | ||
| Val::USize(_) | Val::ISize(_) | Val::CPtr(_) => ValueType::I32, | ||
| Val::GuestPtr(_) => ValueType::I32, | ||
| Val::I8(_) | Val::U8(_) | Val::I16(_) | Val::U16(_) | Val::I32(_) | Val::U32(_) => { | ||
| ValueType::I32 | ||
| } | ||
| Val::I64(_) | Val::U64(_) => ValueType::I64, | ||
| Val::Bool(_) => ValueType::I32, | ||
| Val::F32(_) => ValueType::F32, | ||
| Val::F64(_) => ValueType::F64, | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// Typed values used for passing arguments into guest functions. | ||
| #[derive(Clone, Copy, Debug)] | ||
| pub enum Val { | ||
| CPtr(*const c_void), | ||
| /// A WebAssembly linear memory address | ||
| GuestPtr(u32), | ||
| U8(u8), | ||
| U16(u16), | ||
| U32(u32), | ||
| U64(u64), | ||
| I8(i8), | ||
| I16(i16), | ||
| I32(i32), | ||
| I64(i64), | ||
| USize(usize), | ||
| ISize(isize), | ||
| Bool(bool), | ||
| F32(f32), | ||
| F64(f64), | ||
| } | ||
|
|
||
| // the pointer variant is just a wrapper; the caller will know they're still responsible for their | ||
| // safety | ||
| unsafe impl Send for Val {} | ||
| unsafe impl Sync for Val {} | ||
|
|
||
| impl<T> From<*const T> for Val { | ||
| fn from(x: *const T) -> Val { | ||
| Val::CPtr(x as *const c_void) | ||
| } | ||
| } | ||
|
|
||
| impl<T> From<*mut T> for Val { | ||
| fn from(x: *mut T) -> Val { | ||
| Val::CPtr(x as *mut c_void) | ||
| } | ||
| } | ||
|
|
||
| macro_rules! impl_from_scalars { | ||
| ( { $( $ctor:ident : $ty:ty ),* } ) => { | ||
| $( | ||
| impl From<$ty> for Val { | ||
| fn from(x: $ty) -> Val { | ||
| Val::$ctor(x) | ||
| } | ||
| } | ||
| )* | ||
| }; | ||
| } | ||
|
|
||
| // Since there is overlap in these enum variants, we can't have instances for all of them, such as | ||
| // GuestPtr | ||
| impl_from_scalars!({ | ||
| U8: u8, | ||
| U16: u16, | ||
| U32: u32, | ||
| U64: u64, | ||
| I8: i8, | ||
| I16: i16, | ||
| I32: i32, | ||
| I64: i64, | ||
| USize: usize, | ||
| ISize: isize, | ||
| Bool: bool, | ||
| F32: f32, | ||
| F64: f64 | ||
| }); | ||
|
|
||
| /// Register representation of `Val`. | ||
| /// | ||
| /// When mapping `Val`s to x86_64 registers, we map floating point | ||
| /// values into the SSE registers _xmmN_, and all other values into | ||
| /// general-purpose (integer) registers. | ||
| pub enum RegVal { | ||
| GpReg(u32), | ||
| FpReg(__m128), | ||
| } | ||
|
|
||
| /// Convert a `Val` to its representation when stored in an | ||
| /// argument register. | ||
| pub fn val_to_reg(val: &Val) -> RegVal { | ||
| use self::RegVal::*; | ||
| use self::Val::*; | ||
| match *val { | ||
| CPtr(v) => GpReg(v as u32), | ||
| GuestPtr(v) => GpReg(v as u32), | ||
| U8(v) => GpReg(v as u32), | ||
| U16(v) => GpReg(v as u32), | ||
| U32(v) => GpReg(v as u32), | ||
| U64(v) => GpReg(v as u32), // TODO: aaaaAAAAA | ||
| I8(v) => GpReg(v as u32), | ||
| I16(v) => GpReg(v as u32), | ||
| I32(v) => GpReg(v as u32), | ||
| I64(v) => GpReg(v as u32), // TODO: aaaaAAAA | ||
| USize(v) => GpReg(v as u32), | ||
| ISize(v) => GpReg(v as u32), | ||
| Bool(false) => GpReg(0u32), | ||
| Bool(true) => GpReg(1u32), | ||
| Val::F32(v) => FpReg(unsafe { _mm_load_ps1(&v as *const f32) }), | ||
| Val::F64(v) => FpReg(unsafe { _mm_castpd_ps(_mm_load_pd1(&v as *const f64)) }), | ||
| } | ||
| } | ||
|
|
||
| /// Convert a `Val` to its representation when spilled onto the | ||
| /// stack. | ||
| pub fn val_to_stack(val: &Val) -> u32 { | ||
| use self::Val::*; | ||
| match *val { | ||
| CPtr(v) => v as u32, | ||
| GuestPtr(v) => v as u32, | ||
| U8(v) => v as u32, | ||
| U16(v) => v as u32, | ||
| U32(v) => v as u32, | ||
| U64(v) => v as u32, // TODO: aaaAAA | ||
| I8(v) => v as u32, | ||
| I16(v) => v as u32, | ||
| I32(v) => v as u32, | ||
| I64(v) => v as u32, // TODO: aaaAAA | ||
| USize(v) => v as u32, | ||
| ISize(v) => v as u32, | ||
| Bool(false) => 0u32, | ||
| Bool(true) => 1u32, | ||
| F32(v) => v.to_bits(), | ||
| F64(v) => v.to_bits() as u32, // TODO: aaaAAA | ||
| } | ||
| } | ||
|
|
||
| /// A value returned by a guest function. | ||
| /// | ||
| /// Since the Rust type system cannot know the type of the returned value, the user must use the | ||
| /// appropriate `From` implementation or `as_T` method. | ||
| #[derive(Clone, Copy, Debug)] | ||
| pub struct UntypedRetVal { | ||
| fp: __m128, | ||
| gp: u32, | ||
| } | ||
|
|
||
| impl std::fmt::Display for UntypedRetVal { | ||
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
| write!(f, "<untyped return value>") | ||
| } | ||
| } | ||
|
|
||
| impl UntypedRetVal { | ||
| pub(crate) fn new(gp: u32, fp: __m128) -> UntypedRetVal { | ||
| UntypedRetVal { gp, fp } | ||
| } | ||
| } | ||
|
|
||
| impl From<RegVal> for UntypedRetVal { | ||
| fn from(reg: RegVal) -> UntypedRetVal { | ||
| match reg { | ||
| RegVal::GpReg(r) => UntypedRetVal::new(r, unsafe { _mm_setzero_ps() }), | ||
| RegVal::FpReg(r) => UntypedRetVal::new(0, r), | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl<T: Into<Val>> From<T> for UntypedRetVal { | ||
| fn from(v: T) -> UntypedRetVal { | ||
| val_to_reg(&v.into()).into() | ||
| } | ||
| } | ||
|
|
||
| macro_rules! impl_from_fp { | ||
| ( $ty:ty, $f:ident, $as:ident ) => { | ||
| impl From<UntypedRetVal> for $ty { | ||
| fn from(retval: UntypedRetVal) -> $ty { | ||
| $f(retval.fp) | ||
| } | ||
| } | ||
|
|
||
| impl From<&UntypedRetVal> for $ty { | ||
| fn from(retval: &UntypedRetVal) -> $ty { | ||
| $f(retval.fp) | ||
| } | ||
| } | ||
|
|
||
| impl UntypedRetVal { | ||
| pub fn $as(&self) -> $ty { | ||
| $f(self.fp) | ||
| } | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| impl_from_fp!(f32, __m128_as_f32, as_f32); | ||
| impl_from_fp!(f64, __m128_as_f64, as_f64); | ||
|
|
||
| macro_rules! impl_from_gp { | ||
| ( $ty:ty, $as:ident ) => { | ||
| impl From<UntypedRetVal> for $ty { | ||
| fn from(retval: UntypedRetVal) -> $ty { | ||
| retval.gp as $ty | ||
| } | ||
| } | ||
|
|
||
| impl From<&UntypedRetVal> for $ty { | ||
| fn from(retval: &UntypedRetVal) -> $ty { | ||
| retval.gp as $ty | ||
| } | ||
| } | ||
|
|
||
| impl UntypedRetVal { | ||
| pub fn $as(&self) -> $ty { | ||
| self.gp as $ty | ||
| } | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| impl_from_gp!(u8, as_u8); | ||
| impl_from_gp!(u16, as_u16); | ||
| impl_from_gp!(u32, as_u32); | ||
| impl_from_gp!(u64, as_u64); | ||
|
|
||
| impl_from_gp!(i8, as_i8); | ||
| impl_from_gp!(i16, as_i16); | ||
| impl_from_gp!(i32, as_i32); | ||
| impl_from_gp!(i64, as_i64); | ||
|
|
||
| impl From<UntypedRetVal> for bool { | ||
| fn from(retval: UntypedRetVal) -> bool { | ||
| retval.gp != 0 | ||
| } | ||
| } | ||
|
|
||
| impl From<&UntypedRetVal> for bool { | ||
| fn from(retval: &UntypedRetVal) -> bool { | ||
| retval.gp != 0 | ||
| } | ||
| } | ||
|
|
||
| impl UntypedRetVal { | ||
| pub fn as_bool(&self) -> bool { | ||
| self.gp != 0 | ||
| } | ||
|
|
||
| pub fn as_ptr<T>(&self) -> *const T { | ||
| self.gp as *const T | ||
| } | ||
|
|
||
| pub fn as_mut<T>(&self) -> *mut T { | ||
| self.gp as *mut T | ||
| } | ||
| } | ||
|
|
||
| impl Default for UntypedRetVal { | ||
| fn default() -> UntypedRetVal { | ||
| let fp = unsafe { _mm_setzero_ps() }; | ||
| UntypedRetVal { fp, gp: 0 } | ||
| } | ||
| } | ||
|
|
||
| pub trait UntypedRetValInternal { | ||
| fn fp(&self) -> __m128; | ||
| fn gp(&self) -> u32; | ||
| } | ||
|
|
||
| impl UntypedRetValInternal for UntypedRetVal { | ||
| fn fp(&self) -> __m128 { | ||
| self.fp | ||
| } | ||
|
|
||
| fn gp(&self) -> u32 { | ||
| self.gp | ||
| } | ||
| } | ||
|
|
||
| // Helpers that we might want to put in a utils module someday | ||
|
|
||
| /// Interpret the contents of a `__m128` register as an `f32`. | ||
| pub fn __m128_as_f32(v: __m128) -> f32 { | ||
| let mut out: [f32; 4] = [0.0; 4]; | ||
| unsafe { | ||
| _mm_storeu_ps(&mut out[0] as *mut f32, v); | ||
| } | ||
| out[0] | ||
| } | ||
|
|
||
| /// Interpret the contents of a `__m128` register as an `f64`. | ||
| pub fn __m128_as_f64(v: __m128) -> f64 { | ||
| let mut out: [f64; 2] = [0.0; 2]; | ||
| unsafe { | ||
| let vd = _mm_castps_pd(v); | ||
| _mm_storeu_pd(&mut out[0] as *mut f64, vd); | ||
| } | ||
| out[0] | ||
| } |
This file contains hidden or 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| use cfg_if::cfg_if; | ||
|
|
||
| cfg_if! { | ||
| if #[cfg(target_arch = "x86")] { | ||
| pub mod i686; | ||
| pub use i686 as arch_impl; | ||
| } else if #[cfg(target_arch = "x86_64")] { | ||
| pub mod x86_64; | ||
| pub use x86_64 as arch_impl; | ||
| } | ||
| } | ||
|
|
||
| pub mod val { | ||
| use crate::archdeps::arch_impl; | ||
| pub use arch_impl::val::Val as Val; | ||
| pub use arch_impl::val::RegVal as RegVal; | ||
| pub use arch_impl::val::UntypedRetVal as UntypedRetVal; | ||
| pub(crate) use arch_impl::val::UntypedRetValInternal as UntypedRetValInternal; | ||
| pub use arch_impl::val::val_to_reg as val_to_reg; | ||
| pub use arch_impl::val::val_to_stack as val_to_stack; | ||
| } |
1 change: 1 addition & 0 deletions
1
lucet-runtime/lucet-runtime-internals/src/archdeps/x86_64/mod.rs
This file contains hidden or 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| pub use val; |
File renamed without changes.
This file contains hidden or 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
738 changes: 6 additions & 732 deletions
738
lucet-runtime/lucet-runtime-internals/src/context/mod.rs
Large diffs are not rendered by default.
Oops, something went wrong.
226 changes: 226 additions & 0 deletions
226
lucet-runtime/lucet-runtime-internals/src/context/sysdep/i686/context_asm.S
This file contains hidden or 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,226 @@ | ||
| /* | ||
| The lucet_context_swap function is taken from Xudong Huang's | ||
| generator-rs project. Its MIT license is provided below. | ||
| Copyright (c) 2017 Xudong Huang | ||
| Permission is hereby granted, free of charge, to any | ||
| person obtaining a copy of this software and associated | ||
| documentation files (the "Software"), to deal in the | ||
| Software without restriction, including without | ||
| limitation the rights to use, copy, modify, merge, | ||
| publish, distribute, sublicense, and/or sell copies of | ||
| the Software, and to permit persons to whom the Software | ||
| is furnished to do so, subject to the following conditions: | ||
| The above copyright notice and this permission notice | ||
| shall be included in all copies or substantial portions | ||
| of the Software. | ||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF | ||
| ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED | ||
| TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | ||
| PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT | ||
| SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR | ||
| IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| DEALINGS IN THE SOFTWARE. | ||
| */ | ||
|
|
||
| .text | ||
| .globl lucet_context_bootstrap | ||
| #ifdef __ELF__ | ||
| .type lucet_context_bootstrap,@function | ||
| #else | ||
| .globl _lucet_context_bootstrap | ||
| #endif | ||
| .align 16 | ||
| lucet_context_bootstrap: | ||
| _lucet_context_bootstrap: | ||
| // Move each of the argument values into the corresponding call | ||
| // argument register. | ||
| // pop %r9 | ||
| // pop %r8 | ||
| pop %ecx | ||
| pop %edx | ||
| pop %esi | ||
| pop %edi | ||
|
|
||
| /* the next thing on the stack is the guest function - return to it */ | ||
| ret | ||
| #ifdef __ELF__ | ||
| .size lucet_context_bootstrap,.-lucet_context_bootstrap | ||
| #endif | ||
|
|
||
| .text | ||
| .globl lucet_context_backstop | ||
| #ifdef __ELF__ | ||
| .type lucet_context_backstop,@function | ||
| #else | ||
| .globl _lucet_context_backstop | ||
| #endif | ||
| .align 16 | ||
| lucet_context_backstop: | ||
| _lucet_context_backstop: | ||
| // Note that `rbp` here really has no relation to any stack! | ||
| // Instead, it's a pointer to the guest context. | ||
| mov (10*8 + 8*16 + 8*2 + 16)(%ebp), %edi /* load the parent context to forward values in return value registers */ | ||
| mov %eax, (10*8 + 8*16 + 8*0)(%ebp) /* store return values before swapping back -- offset is offsetof(struct lucet_context, retvals) */ | ||
| mov %edx, (10*8 + 8*16 + 8*1)(%ebp) | ||
| movdqu %xmm0, (10*8 + 8*16 + 8*2)(%ebp) /* floating-point return value */ | ||
|
|
||
| // load `backstop_callback`, but skip calling it if it's null | ||
| mov (10*8 + 8*16 + 8*2 + 16 + 8)(%ebp), %esi | ||
| test %esi, %esi | ||
| #ifdef __ELF__ | ||
| jz no_backstop_callback@PLT | ||
| #else | ||
| jz no_backstop_callback | ||
| #endif | ||
|
|
||
| // load `callback_data`, arg 1 | ||
| mov (10*8 + 8*16 + 8*2 + 16 + 8 + 8)(%ebp), %edi | ||
| // call `backstop_callback` | ||
| call *%esi | ||
|
|
||
| no_backstop_callback: | ||
| mov %ebp, %edi /* load the guest context to the "from" argument */ | ||
| mov (10*8 + 8*16 + 8*2 + 16)(%ebp), %esi /* load the parent context to the "to" argument */ | ||
|
|
||
| #ifdef __ELF__ | ||
| jmp lucet_context_swap@PLT | ||
| #else | ||
| jmp lucet_context_swap | ||
| #endif | ||
| #ifdef __ELF__ | ||
| .size lucet_context_backstop,.-lucet_context_backstop | ||
| #endif | ||
|
|
||
| .text | ||
| .globl lucet_context_swap | ||
| #ifdef __ELF__ | ||
| .type lucet_context_swap,@function | ||
| #else | ||
| .globl _lucet_context_swap | ||
| #endif | ||
| .align 16 | ||
| lucet_context_swap: | ||
| _lucet_context_swap: | ||
| // store everything in offsets from rdi (1st arg) | ||
| mov %ebx, (0*8)(%edi) | ||
| mov %esp, (1*8)(%edi) | ||
| mov %ebp, (2*8)(%edi) | ||
| mov %edi, (3*8)(%edi) | ||
| // mov %r12, (4*8)(%rdi) | ||
| // mov %r13, (5*8)(%rdi) | ||
| // mov %r14, (6*8)(%rdi) | ||
| // mov %r15, (7*8)(%rdi) | ||
| mov %esi, (8*8)(%edi) | ||
|
|
||
| movdqu %xmm0, (10*8 + 0*16)(%edi) | ||
| movdqu %xmm1, (10*8 + 1*16)(%edi) | ||
| movdqu %xmm2, (10*8 + 2*16)(%edi) | ||
| movdqu %xmm3, (10*8 + 3*16)(%edi) | ||
| movdqu %xmm4, (10*8 + 4*16)(%edi) | ||
| movdqu %xmm5, (10*8 + 5*16)(%edi) | ||
| movdqu %xmm6, (10*8 + 6*16)(%edi) | ||
| movdqu %xmm7, (10*8 + 7*16)(%edi) | ||
|
|
||
| // load everything from offsets from rsi (2nd arg) | ||
| mov (0*8)(%esi), %ebx | ||
| mov (1*8)(%esi), %esp | ||
| mov (2*8)(%esi), %ebp | ||
| mov (3*8)(%esi), %edi | ||
| // mov (4*8)(%rsi), %r12 | ||
| // mov (5*8)(%rsi), %r13 | ||
| // mov (6*8)(%rsi), %r14 | ||
| // mov (7*8)(%rsi), %r15 | ||
|
|
||
| movdqu (10*8 + 0*16)(%esi), %xmm0 | ||
| movdqu (10*8 + 1*16)(%esi), %xmm1 | ||
| movdqu (10*8 + 2*16)(%esi), %xmm2 | ||
| movdqu (10*8 + 3*16)(%esi), %xmm3 | ||
| movdqu (10*8 + 4*16)(%esi), %xmm4 | ||
| movdqu (10*8 + 5*16)(%esi), %xmm5 | ||
| movdqu (10*8 + 6*16)(%esi), %xmm6 | ||
| movdqu (10*8 + 7*16)(%esi), %xmm7 | ||
|
|
||
| // restore rsi when we're done with the context pointer | ||
| mov (8*8)(%esi), %esi | ||
|
|
||
| ret | ||
| #ifdef __ELF__ | ||
| .size lucet_context_swap,.-lucet_context_swap | ||
| #endif | ||
|
|
||
| .text | ||
| .globl lucet_context_set | ||
| #ifdef __ELF__ | ||
| .type lucet_context_set,@function | ||
| #else | ||
| .globl _lucet_context_set | ||
| #endif | ||
| .align 16 | ||
| lucet_context_set: | ||
| _lucet_context_set: | ||
| // load everything from offsets from rdi (1st arg) | ||
| mov (0*8)(%edi), %ebx | ||
| mov (1*8)(%edi), %esp | ||
| mov (2*8)(%edi), %ebp | ||
| // mov (4*8)(%edi), %r12 | ||
| // mov (5*8)(%edi), %r13 | ||
| // mov (6*8)(%edi), %r14 | ||
| // mov (7*8)(%edi), %r15 | ||
| mov (8*8)(%edi), %esi | ||
|
|
||
| movdqu (10*8 + 0*16)(%edi), %xmm0 | ||
| movdqu (10*8 + 1*16)(%edi), %xmm1 | ||
| movdqu (10*8 + 2*16)(%edi), %xmm2 | ||
| movdqu (10*8 + 3*16)(%edi), %xmm3 | ||
| movdqu (10*8 + 4*16)(%edi), %xmm4 | ||
| movdqu (10*8 + 5*16)(%edi), %xmm5 | ||
| movdqu (10*8 + 6*16)(%edi), %xmm6 | ||
| movdqu (10*8 + 7*16)(%edi), %xmm7 | ||
|
|
||
| // load rdi from itself last | ||
| mov (3*8)(%edi), %edi | ||
| ret | ||
| #ifdef __ELF__ | ||
| .size lucet_context_set,.-lucet_context_set | ||
| #endif | ||
|
|
||
| .text | ||
| .globl lucet_context_activate | ||
| #ifdef __ELF__ | ||
| .type lucet_context_activate,@function | ||
| #else | ||
| .globl _lucet_context_activate | ||
| #endif | ||
| .align 16 | ||
| // `lucet_context_activate` is essentially a function with three arguments: | ||
| // * rdi: the data for the entry callback. | ||
| // * rsi: the address of the entry callback. | ||
| // * rbx: the address of the guest code to execute. | ||
| // | ||
| // See `lucet_runtime_internals::context::lucet_context_activate` for more info. | ||
| // | ||
| // Note that `rbx` is used to store the address of the guest code because it is | ||
| // a callee-saved register in the System V calling convention. It is also a | ||
| // non-violatile register on Windows, which is a nice benefit. | ||
| lucet_context_activate: | ||
| _lucet_context_activate: | ||
| // First, we call the entry callback whose address is stored in `rsi`, | ||
| // passing along the value of `rdi` as the first argument. | ||
| call *%esi | ||
| // Now, jump to the guest code at the address in `rbx`. | ||
| jmp *%ebx | ||
| #ifdef __ELF__ | ||
| .size lucet_context_activate,.-lucet_context_activate | ||
| #endif | ||
|
|
||
| /* Mark that we don't need executable stack. */ | ||
| #if defined(__linux__) && defined(__ELF__) | ||
| .section .note.GNU-stack,"",%progbits | ||
| #endif |
730 changes: 730 additions & 0 deletions
730
lucet-runtime/lucet-runtime-internals/src/context/sysdep/i686/mod.rs
Large diffs are not rendered by default.
Oops, something went wrong.
11 changes: 11 additions & 0 deletions
11
lucet-runtime/lucet-runtime-internals/src/context/sysdep/mod.rs
This file contains hidden or 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| use cfg_if::cfg_if; | ||
|
|
||
| cfg_if! { | ||
| if #[cfg(target_arch = "x86")] { | ||
| pub mod i686; | ||
| pub use i686 as arch_impl; | ||
| } else if #[cfg(target_arch = "x86_64")] { | ||
| pub mod x86_64; | ||
| pub use x86_64 as arch_impl; | ||
| } | ||
| } |
File renamed without changes.
732 changes: 732 additions & 0 deletions
732
lucet-runtime/lucet-runtime-internals/src/context/sysdep/x86_64/mod.rs
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,18 @@ | ||
| use std::env; | ||
|
|
||
| fn main() { | ||
| // TODO: this should only be built for tests, but Cargo doesn't | ||
| // currently let you specify different build.rs options for tests: | ||
| // <https://github.com/rust-lang/cargo/issues/1581> | ||
| let traps_asm_file = match env::var("CARGO_CFG_TARGET_ARCH").unwrap().as_str() { | ||
| "x86_64" => "traps_x86_64.S", | ||
| "x86" => "traps_i686.S", | ||
| arch => { | ||
| panic!("unsupported architecture {}", arch); | ||
| } | ||
| }; | ||
|
|
||
| cc::Build::new() | ||
| .file("src/guest_fault/traps.S") | ||
| .compile("guest_fault_traps"); | ||
| .file(&format!("src/guest_fault/{}", traps_asm_file)) | ||
| .compile("context_context_asm"); | ||
| } |
70 changes: 70 additions & 0 deletions
70
lucet-runtime/lucet-runtime-tests/src/guest_fault/traps_i686.S
This file contains hidden or 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| .text | ||
| .globl guest_func_illegal_instr # -- Begin function guest_func_illegal_instr | ||
| #ifdef __ELF__ | ||
| .type guest_func_illegal_instr,@function | ||
| #else | ||
| .globl _guest_func_illegal_instr | ||
| #endif | ||
| .p2align 4, 0x90 | ||
| guest_func_illegal_instr: # @guest_func_illegal_instr | ||
| _guest_func_illegal_instr: | ||
| .cfi_startproc | ||
| # %bb.0: | ||
| push %ebp | ||
| .cfi_def_cfa_offset 8 | ||
| .cfi_offset %ebp, -8 | ||
| mov %esp, %ebp | ||
| .cfi_def_cfa_register %ebp | ||
| mov %edi, -4(%ebp) | ||
| #APP | ||
| ud2 | ||
| #NO_APP | ||
| pop %ebp | ||
| .cfi_def_cfa %esp, 4 | ||
| ret | ||
| .Lfunc_end0: | ||
| #ifdef ___ELF__ | ||
| .size guest_func_illegal_instr, .Lfunc_end0-guest_func_illegal_instr | ||
| #endif | ||
| .cfi_endproc | ||
| # -- End function | ||
| .globl guest_func_oob # -- Begin function guest_func_oob | ||
| #ifdef __ELF__ | ||
| .type guest_func_oob,@function | ||
| #else | ||
| .globl _guest_func_oob | ||
| #endif | ||
| .p2align 4, 0x90 | ||
| guest_func_oob: # @guest_func_oob | ||
| _guest_func_oob: | ||
| .cfi_startproc | ||
| # %bb.0: | ||
| push %ebp | ||
| .cfi_def_cfa_offset 8 | ||
| .cfi_offset %ebp, -8 | ||
| mov %esp, %ebp | ||
| .cfi_def_cfa_register %ebp | ||
| sub $8, %esp | ||
| mov %edi, -4(%ebp) | ||
| mov -4(%ebp), %edi | ||
| #ifdef __ELF__ | ||
| call lucet_vmctx_get_heap@PLT | ||
| #else | ||
| call _lucet_vmctx_get_heap | ||
| #endif | ||
| mov %eax, -8(%ebp) | ||
| mov -8(%ebp), %eax | ||
| movb $0, 65537(%eax) | ||
| add $8, %esp | ||
| pop %ebp | ||
| .cfi_def_cfa %esp, 4 | ||
| ret | ||
| .Lfunc_end1: | ||
| #ifdef __ELF__ | ||
| .size guest_func_oob, .Lfunc_end1-guest_func_oob | ||
| #endif | ||
| .cfi_endproc | ||
|
|
||
| #if defined(__linux__) && defined(__ELF__) | ||
| .section ".note.GNU-stack","",@progbits | ||
| #endif |
File renamed without changes.
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,10 @@ | ||
| use cranelift_codegen::ir; | ||
|
|
||
| #[cfg(target_pointer_width = "64")] | ||
| pub const NATIVE_POINTER: ir::Type = ir::types::I64; | ||
| #[cfg(target_pointer_width = "32")] | ||
| pub const NATIVE_POINTER: ir::Type = ir::types::I32; | ||
| #[cfg(target_pointer_width = "64")] | ||
| pub const NATIVE_POINTER_SIZE: usize = 8; | ||
| #[cfg(target_pointer_width = "32")] | ||
| pub const NATIVE_POINTER_SIZE: usize = 4; |
This file contains hidden or 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
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is only present because I was wildly flailing around trying to fix header issues that were caused by fiddling with an include path I shouldn't have. I left it because
lucet_types.hreferencessiginfo_twithout includingsignal.h. This isn't an issue becauselucet.hincludessignal.hbeforelucet_types.h, but someone usinglucet_types.hindividually for some reason would be in for a surprise.... I ought to make this a PR on its own.