mbox series

[v3,0/7] iOS and Apple Silicon host support

Message ID 20201028030701.14086-1-j@getutm.app
Headers show
Series iOS and Apple Silicon host support | expand

Message

Joelle van Dyne Oct. 28, 2020, 3:06 a.m. UTC
Based-on: 20201026191540.12434-1-j@getutm.app
([PATCH RESEND 0/4] Mirror map JIT memory for TCG)

These set of changes brings QEMU TCG to iOS devices and future Apple Silicon
devices. They were originally developed last year and have been working in the
UTM app. Recently, we ported the changes to master, re-wrote a lot of the build
script changes for meson, and broke up the patches into more distinct units.

A summary of the changes:

* `CONFIG_IOS` defined when building for iOS and iOS specific changes (as well
  as unsupported code) are gated behind it.
* A new dependency, libucontext is added since iOS does not have native ucontext
  and broken support for sigaltstack. libucontext is available as a new option
  for coroutine backend.
* On stock iOS devices, there is a workaround for running JIT code without
  any special entitlement. It requires the JIT region to be mirror mapped with
  one region RW and another one RX. To support this style of JIT, TCG is changed
  to support writing to a different code_ptr. This change is submitted in a
  different patch set and this one depends on it.
* For (recent) jailbroken iOS devices as well as upcoming Apple Silicon devices,
  there are new rules for applications supporting JIT (with the proper
  entitlement). These rules are implemented as well.

Since v3:

* Moved mirror JIT support to a different patch set.
* Removed dependency on `pthread_jit_write_protect_np` because it was redundent
  and also crashes if called on a non-jailbroken iOS device.
* Removed `--enable-cross-compile` option
* Fixed checkpatch errors
* Fixed iOS build on master due to new test recently added which calls system()

Since v2:

* Changed getting mirror pointer from a macro to inline functions
* Split constification of TCG code pointers to separate patch
* Removed slirp updates (will send future patch once slirp changes are in)
* Removed shared library patch (will send future patch)

-j

Joelle van Dyne (7):
  configure: option to disable host block devices
  configure: cross-compiling with empty cross_prefix
  qemu: add support for iOS host
  coroutine: add libucontext as external library
  slirp: update build flags for iOS resolv fix
  tcg: implement JIT for iOS and Apple Silicon
  block: check availablity for preadv/pwritev on mac

 docs/devel/index.rst           |   1 +
 docs/devel/ios.rst             |  39 ++++++++++++
 configure                      |  77 ++++++++++++++++++++++--
 meson.build                    |  34 ++++++++++-
 include/exec/exec-all.h        |   2 +
 include/tcg/tcg-apple-jit.h    | 106 +++++++++++++++++++++++++++++++++
 include/tcg/tcg.h              |   3 +
 tcg/aarch64/tcg-target.h       |   7 +++
 accel/tcg/cpu-exec-common.c    |   2 +
 accel/tcg/cpu-exec.c           |   2 +
 accel/tcg/translate-all.c      |  87 ++++++++++++++++++++++++++-
 block.c                        |   2 +-
 block/file-posix.c             |  51 ++++++++++++----
 net/slirp.c                    |  16 ++---
 qga/commands-posix.c           |   6 ++
 target/arm/arm-semi.c          |   2 +
 target/m68k/m68k-semi.c        |   2 +
 target/nios2/nios2-semi.c      |   2 +
 tcg/tcg.c                      |   4 ++
 tests/qtest/libqos/virtio-9p.c |   8 +++
 util/coroutine-ucontext.c      |   9 +++
 .gitmodules                    |   3 +
 libucontext                    |   1 +
 meson_options.txt              |   2 +
 tests/qtest/meson.build        |   7 +--
 25 files changed, 440 insertions(+), 35 deletions(-)
 create mode 100644 docs/devel/ios.rst
 create mode 100644 include/tcg/tcg-apple-jit.h
 create mode 160000 libucontext

Comments

Stefan Hajnoczi Oct. 28, 2020, 11:22 a.m. UTC | #1
On Tue, Oct 27, 2020 at 08:06:55PM -0700, Joelle van Dyne wrote:
> Some hosts (iOS) have a sandboxed filesystem and do not provide low-level
> APIs for interfacing with host block devices.
> 
> Signed-off-by: Joelle van Dyne <j@getutm.app>
> ---
>  configure          | 4 ++++
>  meson.build        | 1 +
>  block/file-posix.c | 8 +++++++-
>  3 files changed, 12 insertions(+), 1 deletion(-)

A change along these lines is needed in qapi/block-core.json:

  { 'enum': 'BlockdevDriver',
    ...
    { 'name': 'host_device', 'if': 'defined(CONFIG_HOST_BLOCK_DEVICE)' }

That way the QAPI schema reflects the QEMU binary's actual features.

> 
> diff --git a/configure b/configure
> index 71bbe82ac5..4e68a5fefe 100755
> --- a/configure
> +++ b/configure
> @@ -448,6 +448,7 @@ ninja=""
>  skip_meson=no
>  gettext=""
>  mirror_jit="no"
> +host_block_device_support="yes"
>  
>  bogus_os="no"
>  malloc_trim="auto"
> @@ -5901,6 +5902,9 @@ if test "$default_devices" = "yes" ; then
>  else
>    echo "CONFIG_MINIKCONF_MODE=--allnoconfig" >> $config_host_mak
>  fi
> +if test "$host_block_device_support" = "yes" ; then
> +  echo "CONFIG_HOST_BLOCK_DEVICE=y" >> $config_host_mak
> +fi
>  if test "$debug_tcg" = "yes" ; then
>    echo "CONFIG_DEBUG_TCG=y" >> $config_host_mak
>  fi

How do you disable CONFIG_HOST_BLOCK_DEVICE? There is no ./configure
--disable-host-block-device option.
Stefan Hajnoczi Oct. 28, 2020, 11:48 a.m. UTC | #2
On Tue, Oct 27, 2020 at 08:06:59PM -0700, Joelle van Dyne wrote:
> A future libslirp update will use libresolv on Darwin systems, so we add the
> flags in QEMU build now.
> 
> Signed-off-by: Joelle van Dyne <j@getutm.app>
> ---
>  meson.build | 2 ++
>  1 file changed, 2 insertions(+)

Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Stefan Hajnoczi Oct. 28, 2020, 11:53 a.m. UTC | #3
On Tue, Oct 27, 2020 at 08:07:00PM -0700, Joelle van Dyne wrote:
> On iOS, we cannot allocate RWX pages without special entitlements. As a
> workaround, we can allocate a RX region and then mirror map it to a separate
> RX region. Then we can write to one region and execute from the other one.

"separate RW region"? The sentence doesn't seem to make sense if both
regions are RX.

> 
> When entitlements are available (macOS or jailbroken iOS), a hardware
> feature called APRR exists on newer Apple Silicon that can cheaply mark JIT
> pages as either RX or RW. Reverse engineered functions from
> libsystem_pthread.dylib are implemented to handle this.

What does "Reverse engineered functions" mean? We cannot accept code
into QEMU that is a potential liability if Apple could claim it has been
copied, derived, etc without permission. If libsystem_pthread.dylib is
open source, especially under a permissive license, then it's probably
okay.

Can you clarify?
Stefan Hajnoczi Oct. 28, 2020, 12:05 p.m. UTC | #4
On Tue, Oct 27, 2020 at 08:06:54PM -0700, Joelle van Dyne wrote:
> Based-on: 20201026191540.12434-1-j@getutm.app
> ([PATCH RESEND 0/4] Mirror map JIT memory for TCG)
> 
> These set of changes brings QEMU TCG to iOS devices and future Apple Silicon
> devices. They were originally developed last year and have been working in the
> UTM app. Recently, we ported the changes to master, re-wrote a lot of the build
> script changes for meson, and broke up the patches into more distinct units.
> 
> A summary of the changes:
> 
> * `CONFIG_IOS` defined when building for iOS and iOS specific changes (as well
>   as unsupported code) are gated behind it.
> * A new dependency, libucontext is added since iOS does not have native ucontext
>   and broken support for sigaltstack. libucontext is available as a new option
>   for coroutine backend.
> * On stock iOS devices, there is a workaround for running JIT code without
>   any special entitlement. It requires the JIT region to be mirror mapped with
>   one region RW and another one RX. To support this style of JIT, TCG is changed
>   to support writing to a different code_ptr. This change is submitted in a
>   different patch set and this one depends on it.
> * For (recent) jailbroken iOS devices as well as upcoming Apple Silicon devices,
>   there are new rules for applications supporting JIT (with the proper
>   entitlement). These rules are implemented as well.

These patches are in pretty good shape. I have posted comments, the main
request is to add a ./MAINTAINERS file entry and to look into continuous
integration support.

Stefan
Joelle van Dyne Oct. 29, 2020, 12:51 a.m. UTC | #5
On Wed, Oct 28, 2020 at 4:22 AM Stefan Hajnoczi <stefanha@gmail.com> wrote:
>
> On Tue, Oct 27, 2020 at 08:06:55PM -0700, Joelle van Dyne wrote:
> > Some hosts (iOS) have a sandboxed filesystem and do not provide low-level
> > APIs for interfacing with host block devices.
> >
> > Signed-off-by: Joelle van Dyne <j@getutm.app>
> > ---
> >  configure          | 4 ++++
> >  meson.build        | 1 +
> >  block/file-posix.c | 8 +++++++-
> >  3 files changed, 12 insertions(+), 1 deletion(-)
>
> A change along these lines is needed in qapi/block-core.json:
>
>   { 'enum': 'BlockdevDriver',
>     ...
>     { 'name': 'host_device', 'if': 'defined(CONFIG_HOST_BLOCK_DEVICE)' }
>
> That way the QAPI schema reflects the QEMU binary's actual features.
Will do.

>
> >
> > diff --git a/configure b/configure
> > index 71bbe82ac5..4e68a5fefe 100755
> > --- a/configure
> > +++ b/configure
> > @@ -448,6 +448,7 @@ ninja=""
> >  skip_meson=no
> >  gettext=""
> >  mirror_jit="no"
> > +host_block_device_support="yes"
> >
> >  bogus_os="no"
> >  malloc_trim="auto"
> > @@ -5901,6 +5902,9 @@ if test "$default_devices" = "yes" ; then
> >  else
> >    echo "CONFIG_MINIKCONF_MODE=--allnoconfig" >> $config_host_mak
> >  fi
> > +if test "$host_block_device_support" = "yes" ; then
> > +  echo "CONFIG_HOST_BLOCK_DEVICE=y" >> $config_host_mak
> > +fi
> >  if test "$debug_tcg" = "yes" ; then
> >    echo "CONFIG_DEBUG_TCG=y" >> $config_host_mak
> >  fi
>
> How do you disable CONFIG_HOST_BLOCK_DEVICE? There is no ./configure
> --disable-host-block-device option.
I don't see a value in disabling as an option. It's always enabled by
default and automatically disabled for iOS.

-j
Joelle van Dyne Oct. 29, 2020, 1:04 a.m. UTC | #6
Will fix the typo in the commit message.

Re: "reverse engineered functions", Apple does not provide any
documentation on their extensions to ARM architecture. APRR is one
such proprietary feature that is controlled by MRS/MSR writes to an
undocumented system register. We reverse engineered the functionality
by tracing how libsystem_pthread.dylib works and replicating the
MRS/MSR calls.

More details: https://siguza.github.io/APRR/

Legally, I don't think this is any different from reverse engineering
some hardware interface to write a Linux driver but IANAL.

-j

On Wed, Oct 28, 2020 at 4:54 AM Stefan Hajnoczi <stefanha@redhat.com> wrote:
>
> On Tue, Oct 27, 2020 at 08:07:00PM -0700, Joelle van Dyne wrote:
> > On iOS, we cannot allocate RWX pages without special entitlements. As a
> > workaround, we can allocate a RX region and then mirror map it to a separate
> > RX region. Then we can write to one region and execute from the other one.
>
> "separate RW region"? The sentence doesn't seem to make sense if both
> regions are RX.
>
> >
> > When entitlements are available (macOS or jailbroken iOS), a hardware
> > feature called APRR exists on newer Apple Silicon that can cheaply mark JIT
> > pages as either RX or RW. Reverse engineered functions from
> > libsystem_pthread.dylib are implemented to handle this.
>
> What does "Reverse engineered functions" mean? We cannot accept code
> into QEMU that is a potential liability if Apple could claim it has been
> copied, derived, etc without permission. If libsystem_pthread.dylib is
> open source, especially under a permissive license, then it's probably
> okay.
>
> Can you clarify?
Stefan Hajnoczi Oct. 29, 2020, 8:13 a.m. UTC | #7
On Wed, Oct 28, 2020 at 06:04:56PM -0700, Joelle van Dyne wrote:
> Will fix the typo in the commit message.
> 
> Re: "reverse engineered functions", Apple does not provide any
> documentation on their extensions to ARM architecture. APRR is one
> such proprietary feature that is controlled by MRS/MSR writes to an
> undocumented system register. We reverse engineered the functionality
> by tracing how libsystem_pthread.dylib works and replicating the
> MRS/MSR calls.
> 
> More details: https://siguza.github.io/APRR/
> 
> Legally, I don't think this is any different from reverse engineering
> some hardware interface to write a Linux driver but IANAL.

Thanks, I have taken the discussion off-list where we can get advice
regarding this case.

Stefan