Hi Christoffer, On Sun, 2011-05-08 at 15:00 +0100, Christoffer Dall wrote: > --- /dev/null > +++ b/arch/arm/kvm/arm_interrupts.S ... > +__do_hyp_init: > + @ Copy the Hyp stack pointer > + mov sp, r0 > + mov lr, r1 > + > + @ Set the HTTBR to be the same as the TTBR1 holding the kernel > + @ level-1 page table > + mrrc p15, 1, r0, r1, c2 > + mcrr p15, 4, r0, r1, c2 > + > + @ Set the HTCR to the same shareability and cacheability settings as the > + @ non-secure TTBCR and with T0SZ == 0. > + mrc p15, 4, r0, c2, c0, 2 > + ldr r12, =HTCR_MASK > + bic r0, r0, r12 > + mrc p15, 0, r1, c2, c0, 2 > + and r1, r1, #(HTCR_MASK & ~TTBCR_T0SZ) > + orr r0, r0, r1 > + mcr p15, 4, r0, c2, c0, 2 If you set HTCR.T0SZ to 0, you have a different value than TTBCR.T1SZ. With a 3:1 memory split for Linux, TTBR1 (with LPAE) no longer uses 3 levels of page tables but 2 and TTBR1 points to level 2 tables only. Similarly, with 2:2 split TTBR1 skips the first 2 level 1 page table entries. But here you copy TTBR1 to HTCR directly but changing T0SZ. Anyway, I would not recommend changing the kernel pgd directly as per your init code but allocate a new one via identity_mapping_add. You than use this pgd to set HTTBR and T0SZ to 0 (as you need the full 32-bit address space for the identity mapping). Once the Hyp code starts and jumps to the virtual address (that the kernel is also using), you can change HTTBR to TTBR1 and HTCR.T0SZ to TTBCR.T1SZ. After that you can remove the original pgd via identity_mapping_del. But you need to pass an extra argument to your Hyp initialisation code for HTTBR. Here I'm more in favour of setting up a structure holding parameters like HTTBR, SP etc. and only pass a pointer to the Hyp code. -- Catalin