diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore
index e0936a1..8b05d09 100644
--- a/arch/arm/boot/compressed/.gitignore
+++ b/arch/arm/boot/compressed/.gitignore
@@ -1,5 +1,6 @@
 font.c
 lib1funcs.S
+hyp-stub.S
 piggy.gzip
 piggy.lzo
 piggy.lzma
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index cf0a64c..2a597d1 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -30,6 +30,11 @@ FONTC	= $(srctree)/drivers/video/console/font_acorn_8x8.c
 OBJS		+= string.o
 CFLAGS_string.o	:= -Os
 
+ifeq ($(CONFIG_ARM_VIRT),y)
+OBJS		+= hyp-stub.o
+AFLAGS_hyp-stub.o := -Wa,-march=armv7-a+virt
+endif
+
 #
 # Architecture dependencies
 #
@@ -189,3 +194,6 @@ $(obj)/font.c: $(FONTC)
 
 $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile $(KCONFIG_CONFIG)
 	@sed "$(SEDFLAGS)" < $< > $@
+
+$(obj)/hyp-stub.S: $(srctree)/arch/$(SRCARCH)/kernel/hyp-stub.S
+	$(call cmd,shipped)
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index c5d6025..1f9b498 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -9,6 +9,7 @@
  * published by the Free Software Foundation.
  */
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 
 /*
  * Debugging stuff
@@ -132,7 +133,13 @@ start:
 		.word	start			@ absolute load/run zImage address
 		.word	_edata			@ zImage end address
  THUMB(		.thumb			)
-1:		mov	r7, r1			@ save architecture ID
+1:
+#ifdef CONFIG_ARM_VIRT
+		bl	__hyp_stub_install	@ get into SVC mode, reversibly
+#endif
+		safe_svcmode_maskall r4
+
+		mov	r7, r1			@ save architecture ID
 		mov	r8, r2			@ save atags pointer
 
 #ifndef __ARM_ARCH_2__
@@ -458,11 +465,27 @@ not_relocated:	mov	r0, #0
 		bl	decompress_kernel
 		bl	cache_clean_flush
 		bl	cache_off
-		mov	r0, #0			@ must be zero
 		mov	r1, r7			@ restore architecture number
 		mov	r2, r8			@ restore atags pointer
- ARM(		mov	pc, r4	)		@ call kernel
- THUMB(		bx	r4	)		@ entry point is always ARM
+
+#ifdef CONFIG_ARM_VIRT
+		ldr	r0, =__boot_cpu_mode
+		and	r0, r0, #MODE_MASK
+		cmp	r0, #HYP_MODE		@ if not booted in HYP mode...
+		bne	__enter_kernel		@ boot kernel directly
+	
+		adr	r12, .L__hyp_reentry_vectors_offset
+		ldr	r0, [r12]
+		add	r0, r0, r12
+	
+		bl	__hyp_set_vectors
+		hvc	#0			@ otherwise bounce via HVC call
+
+		b	.			@ should never be reached
+
+		.align	2
+.L__hyp_reentry_vectors_offset:	.long	__hyp_set_vectors - .
+#endif
 
 		.align	2
 		.type	LC0, #object
@@ -1220,6 +1243,25 @@ memdump:	mov	r12, r0
 #endif
 
 		.ltorg
+
+#ifdef CONFIG_ARM_VIRT
+.align 5
+__hyp_reentry_vectors:
+		W(b)	.			@ reset
+		W(b)	.			@ undef
+		W(b)	.			@ svc
+		W(b)	.			@ pabort
+		W(b)	.			@ dabort
+						@ hyp trap is at __enter_kernel
+#endif /* CONFIG_ARM_VIRT */
+
+		@ Don't insert any code here unless you know what you're doing!
+
+__enter_kernel:					
+		mov	r0, #0			@ must be 0
+ ARM(		mov	pc, r4	)		@ call kernel
+ THUMB(		bx	r4	)		@ entry point is always ARM
+
 reloc_code_end:
 
 		.align
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index b6e65de..fab3ca1 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -233,6 +233,21 @@
 #endif
 
 /*
+ * Helper macro to enter SVC mode cleanly and mask interrupts.  reg is a
+ * scratch register available for the macro to overwrite.
+ */
+.macro safe_svcmode_maskall reg:req
+	mrs	\reg , cpsr
+	orr	\reg , \reg , #PSR_A_BIT | PSR_I_BIT | PSR_F_BIT
+	bic	\reg , \reg , #MODE_MASK
+	orr	\reg , \reg , #SVC_MODE
+	msr	spsr_cxsf, \reg
+	adr	\reg , BSYM(1f)
+	movs	pc, \reg
+1:
+.endm
+
+/*
  * STRT/LDRT access macros with ARM and Thumb-2 variants
  */
 #ifdef CONFIG_THUMB2_KERNEL
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index bafaf99..ab1a941 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -64,21 +64,6 @@
 #endif
 
 /*
- * Helper macro to enter SVC mode cleanly and mask interrupts.  reg is a
- * scratch register available for the macro to overwrite.
- */
-.macro safe_svcmode_maskall reg:req
-	mrs	\reg , cpsr
-	orr	\reg , \reg , #PSR_A_BIT | PSR_I_BIT | PSR_F_BIT
-	bic	\reg , \reg , #MODE_MASK
-	orr	\reg , \reg , #SVC_MODE
-	msr	spsr_cxsf, \reg
-	adr	\reg , BSYM(1f)
-	movs	pc, \reg
-1:
-.endm
-
-/*
  * Kernel startup entry point.
  * ---------------------------
  *
