diff mbox

[2/2] qemu: add host/target Linux version check

Message ID 1418249519-15794-3-git-send-email-thomas.petazzoni@free-electrons.com
State Accepted
Headers show

Commit Message

Thomas Petazzoni Dec. 10, 2014, 10:11 p.m. UTC
Raise an error if the host is using an older kernel than the target.
Since qemu-user passes emulated system calls to the host kernel,
this prevents usage of qemu-user in situations where those system
calls will fail.

This is based on an original patch from Frank Hunleth
<fhunleth@troodon-software.com>, but completely rewritten in a
different way:

 * Instead of using shell based testing, we use pure make tests, which
   allows to detect the problem not when host-qemu starts to build,
   but at the very beginning of the entire Buildroot build.

 * Instead of looking at $(STAGING_DIR)/usr/include/linux/version.h
   (which requires having a dependency on the 'toolchain' package,
   which is a bit unusual for a host package), we use the
   BR2_TOOLCHAIN_HEADERS_AT_LEAST Config.in option which tells us the
   version of the kernel headers used in the toolchain.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 package/qemu/qemu.mk | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

Comments

Frank Hunleth Dec. 12, 2014, 1:56 p.m. UTC | #1
Hi Thomas,

On Wed, Dec 10, 2014 at 5:11 PM, Thomas Petazzoni
<thomas.petazzoni@free-electrons.com> wrote:
>
> Raise an error if the host is using an older kernel than the target.
> Since qemu-user passes emulated system calls to the host kernel,
> this prevents usage of qemu-user in situations where those system
> calls will fail.
>
> This is based on an original patch from Frank Hunleth
> <fhunleth@troodon-software.com>, but completely rewritten in a
> different way:
>
>  * Instead of using shell based testing, we use pure make tests, which
>    allows to detect the problem not when host-qemu starts to build,
>    but at the very beginning of the entire Buildroot build.
>
>  * Instead of looking at $(STAGING_DIR)/usr/include/linux/version.h
>    (which requires having a dependency on the 'toolchain' package,
>    which is a bit unusual for a host package), we use the
>    BR2_TOOLCHAIN_HEADERS_AT_LEAST Config.in option which tells us the
>    version of the kernel headers used in the toolchain.
>
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>

Thanks for revisiting and improving the old host-qemu patch. I'm using
your new changes to qemu.mk right now and everything seems to work as
expected. So,

Tested-by: Frank Hunleth <fhunleth@troodon-software.com>

Thanks,
Frank

> ---
>  package/qemu/qemu.mk | 28 ++++++++++++++++++++++++++++
>  1 file changed, 28 insertions(+)
>
> diff --git a/package/qemu/qemu.mk b/package/qemu/qemu.mk
> index 9cff5ed..6c5ddf3 100644
> --- a/package/qemu/qemu.mk
> +++ b/package/qemu/qemu.mk
> @@ -59,6 +59,34 @@ HOST_QEMU_ARCH = ppc
>  endif
>  HOST_QEMU_TARGETS = $(HOST_QEMU_ARCH)-linux-user
>
> +ifeq ($(BR2_PACKAGE_HOST_QEMU),y)
> +HOST_QEMU_HOST_SYSTEM_TYPE = $(shell uname -s)
> +ifneq ($(HOST_QEMU_HOST_SYSTEM_TYPE),Linux)
> +$(error "qemu-user can only be used on Linux hosts")
> +endif
> +
> +HOST_QEMU_HOST_SYSTEM_VERSION_MAJOR = $(shell uname -r | cut -f1 -d'.')
> +HOST_QEMU_HOST_SYSTEM_VERSION_MINOR = $(shell uname -r | cut -f2 -d'.')
> +HOST_QEMU_TARGET_SYSTEM_VERSION_MAJOR = $(shell echo $(BR2_TOOLCHAIN_HEADERS_AT_LEAST) | cut -f1 -d'.')
> +HOST_QEMU_TARGET_SYSTEM_VERSION_MINOR = $(shell echo $(BR2_TOOLCHAIN_HEADERS_AT_LEAST) | cut -f2 -d'.')
> +HOST_QEMU_COMPARE_VERSION_MAJOR = $(shell test $(HOST_QEMU_HOST_SYSTEM_VERSION_MAJOR) -ge $(HOST_QEMU_TARGET_SYSTEM_VERSION_MAJOR) && echo OK)
> +HOST_QEMU_COMPARE_VERSION_MINOR = $(shell test $(HOST_QEMU_HOST_SYSTEM_VERSION_MINOR) -ge $(HOST_QEMU_TARGET_SYSTEM_VERSION_MINOR) && echo OK)
> +
> +#
> +# The principle of qemu-user is that it emulates the instructions of
> +# the target architecture when running the binary, and then when this
> +# binary does a system call, it converts this system call into a
> +# system call on the host machine. This mechanism makes an assumption:
> +# that the target binary will not do system calls that do not exist on
> +# the host. This basically requires that the target binary should be
> +# built with kernel headers that are older or the same as the kernel
> +# version running on the host machine.
> +#
> +ifneq ($(HOST_QEMU_COMPARE_VERSION_MAJOR)$(HOST_QEMU_COMPARE_VERSION_MINOR),OKOK)
> +$(error "Refusing to build qemu-user: target Linux version newer than host's.")
> +endif
> +endif
> +
>  define HOST_QEMU_CONFIGURE_CMDS
>         cd $(@D); $(HOST_CONFIGURE_OPTS) ./configure    \
>                 --target-list="$(HOST_QEMU_TARGETS)"    \
> --
> 2.1.0
>
Bernd Kuhls May 21, 2015, 7:51 a.m. UTC | #2
Thomas Petazzoni
<thomas.petazzoni@free-electrons.com> wrote
in
news:1418249519-15794-3-git-send-email-thomas.petazzoni@free-electrons.com:

> +ifneq
> ($(HOST_QEMU_COMPARE_VERSION_MAJOR)$(HOST_QEMU_COMPARE_VERSION_MINOR),OKO
> K) +$(error "Refusing to build qemu-user: target Linux version newer
> than host's.") +endif

Hi,

while testing an allyesconfig with "make source-check" this error was
raised. I had to comment this line in order to run the source-check. Is it
possible to run this check only during a build phase? 

Regards, Bernd
Thomas Petazzoni May 21, 2015, 8:27 a.m. UTC | #3
Dear Bernd Kuhls,

On Thu, 21 May 2015 09:51:43 +0200, Bernd Kuhls wrote:

> > +ifneq
> > ($(HOST_QEMU_COMPARE_VERSION_MAJOR)$(HOST_QEMU_COMPARE_VERSION_MINOR),OKO
> > K) +$(error "Refusing to build qemu-user: target Linux version newer
> > than host's.") +endif
> 
> while testing an allyesconfig with "make source-check" this error was
> raised. I had to comment this line in order to run the source-check. Is it
> possible to run this check only during a build phase? 

Yes, but that's not the proper solution. The proper solution is to
enclose the test with:

ifeq ($(BR_BUILDING),y)
...
endif

See how it's used in linux.mk or uboot.mk.

Best regards,

Thomas
diff mbox

Patch

diff --git a/package/qemu/qemu.mk b/package/qemu/qemu.mk
index 9cff5ed..6c5ddf3 100644
--- a/package/qemu/qemu.mk
+++ b/package/qemu/qemu.mk
@@ -59,6 +59,34 @@  HOST_QEMU_ARCH = ppc
 endif
 HOST_QEMU_TARGETS = $(HOST_QEMU_ARCH)-linux-user
 
+ifeq ($(BR2_PACKAGE_HOST_QEMU),y)
+HOST_QEMU_HOST_SYSTEM_TYPE = $(shell uname -s)
+ifneq ($(HOST_QEMU_HOST_SYSTEM_TYPE),Linux)
+$(error "qemu-user can only be used on Linux hosts")
+endif
+
+HOST_QEMU_HOST_SYSTEM_VERSION_MAJOR = $(shell uname -r | cut -f1 -d'.')
+HOST_QEMU_HOST_SYSTEM_VERSION_MINOR = $(shell uname -r | cut -f2 -d'.')
+HOST_QEMU_TARGET_SYSTEM_VERSION_MAJOR = $(shell echo $(BR2_TOOLCHAIN_HEADERS_AT_LEAST) | cut -f1 -d'.')
+HOST_QEMU_TARGET_SYSTEM_VERSION_MINOR = $(shell echo $(BR2_TOOLCHAIN_HEADERS_AT_LEAST) | cut -f2 -d'.')
+HOST_QEMU_COMPARE_VERSION_MAJOR = $(shell test $(HOST_QEMU_HOST_SYSTEM_VERSION_MAJOR) -ge $(HOST_QEMU_TARGET_SYSTEM_VERSION_MAJOR) && echo OK)
+HOST_QEMU_COMPARE_VERSION_MINOR = $(shell test $(HOST_QEMU_HOST_SYSTEM_VERSION_MINOR) -ge $(HOST_QEMU_TARGET_SYSTEM_VERSION_MINOR) && echo OK)
+
+#
+# The principle of qemu-user is that it emulates the instructions of
+# the target architecture when running the binary, and then when this
+# binary does a system call, it converts this system call into a
+# system call on the host machine. This mechanism makes an assumption:
+# that the target binary will not do system calls that do not exist on
+# the host. This basically requires that the target binary should be
+# built with kernel headers that are older or the same as the kernel
+# version running on the host machine.
+#
+ifneq ($(HOST_QEMU_COMPARE_VERSION_MAJOR)$(HOST_QEMU_COMPARE_VERSION_MINOR),OKOK)
+$(error "Refusing to build qemu-user: target Linux version newer than host's.")
+endif
+endif
+
 define HOST_QEMU_CONFIGURE_CMDS
 	cd $(@D); $(HOST_CONFIGURE_OPTS) ./configure    \
 		--target-list="$(HOST_QEMU_TARGETS)"    \