All of lore.kernel.org
 help / color / mirror / Atom feed
From: marc.zyngier@arm.com (Marc Zyngier)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v4 0/7] ARM: KVM: Revamping the HYP init code for fun and profit
Date: Fri, 12 Apr 2013 19:12:00 +0100	[thread overview]
Message-ID: <1365790327-2138-1-git-send-email-marc.zyngier@arm.com> (raw)

Over the past few weeks, I've gradually realized how broken our HYP
idmap code is. Badly broken.

The main problem is about supporting CPU hotplug. Imagine a CPU being
initialized normally, running VMs, and then being powered down. So
far, so good. Now mentally bring it back online. The CPU will come
back via the secondary CPU boot path, and then what? We cannot use it
anymore, because we need an idmap which is long gone, and because our
page tables are now live, containing the world-switch code, VM
structures, and other bits and pieces.

Another fun issue is that we don't have any TLB invalidation in the
HYP init code. And guess what? we cannot do it! HYP TLB invalidation
has to occur in HYP, and once we've installed the runtime page tables,
it is already too late. It is actually fairly easy to construct a
scenario where idmap and runtime pages have colliding translations.

The nail on the coffin was provided by Catalin Marinas who told me how
much he disliked the arm64 HYP idmap code, and made me realize that we
already have all the necessary code in arch/arm/kvm/mmu.c. It just
needs a tiny bit of care and affection. With a chainsaw.

The solution to the first two issues is a bit tricky, but doesn't
involve a lot of code. The hotplug problem mandates that we keep two
sets of page tables (boot and runtime). The TLB problem mandates that
we're able to transition from one PGD to another while in HYP,
invalidating the TLBs in the process.

To be able to do this, we need to share a page between the two page
tables. A page that will have the same VA in both configurations. All
we need is a VA that has the following properties:
- This VA can't be used to represent a kernel mapping.
- This VA will not conflict with the physical address of the kernel
  text

The vectors page VA seems to satisfy this requirement:
- The kernel never maps anything else there
- The kernel text being copied at the beginning of the physical
  memory, it is unlikely to use the last 64kB (I doubt we'll ever
  support KVM on a system with something like 4MB of RAM, but patches
  are very welcome).

Let's call this VA the trampoline VA.

Now, we map our init page at 3 locations:
- idmap in the boot pgd
- trampoline VA in the boot pgd
- trampoline VA in the runtime pgd

The init scenario is now the following:
- We jump in HYP with four parameters: boot HYP pgd, runtime HYP pgd,
  runtime stack, runtime vectors
- Enable the MMU with the boot pgd
- Jump to a target into the trampoline page (remember, this is the
  same physical page!)
- Now switch to the runtime pgd (same VA, and still the same physical
  page!)
- Invalidate TLBs
- Set stack and vectors
- Profit! (or eret, if you only care about the code).

Once we have this infrastructure in place, supporting CPU hot-plug is
a piece of cake. Just wire a cpu-notifier in the existing code.

This has been tested on both arm (VE TC2) and arm64 (Foundation Model).

>From v3:
- Remove stray conflict left in the middle of patch 6/7.
  Always send the patch series you're actually testing...

>From v2:
- Change the init.S calling convention to pass the PGD in r2-r3,
  removing the horrible endianess-dependant split of the 64bit
  physical address.
- Fix the HYP page table freeing code by getting rid of it. Our
  stage-2 code does it a lot better, and I'd rather fix bugs only
  once.
- Flush HYP page tables to the Point of Coherency. This ensures that
  the incoming CPU will see the page tables, even with cache disabled
  (spotted by Will).
- Use kmalloc instead of kzalloc for the bounce page (spotted by
  Christoffer).

>From v1:
- Reduce the mandatory alignement of the init code page, and use a
  bounce page if the code is crossing a page boundary.
- Add some more comments to the code (as requested by Christoffer)
- Fixed compilation issue with older toolchains (spotted by Geoff)

Marc Zyngier (7):
  ARM: KVM: simplify HYP mapping population
  ARM: KVM: fix HYP mapping limitations around zero
  ARM: KVM: move to a KVM provided HYP idmap
  ARM: KVM: enforce maximum size for identity mapped code
  ARM: KVM: rework HYP page table freeing
  ARM: KVM: switch to a dual-step HYP init code
  ARM: KVM: perform HYP initilization for hotplugged CPUs

 arch/arm/include/asm/idmap.h    |   1 -
 arch/arm/include/asm/kvm_host.h |  31 +--
 arch/arm/include/asm/kvm_mmu.h  |  28 ++-
 arch/arm/kernel/vmlinux.lds.S   |   7 +-
 arch/arm/kvm/arm.c              |  62 ++++--
 arch/arm/kvm/init.S             |  78 +++++--
 arch/arm/kvm/mmu.c              | 455 +++++++++++++++++++++++-----------------
 arch/arm/mm/idmap.c             |  32 +--
 8 files changed, 404 insertions(+), 290 deletions(-)

-- 
1.8.1.4

             reply	other threads:[~2013-04-12 18:12 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-04-12 18:12 Marc Zyngier [this message]
2013-04-12 18:12 ` [PATCH v4 1/7] ARM: KVM: simplify HYP mapping population Marc Zyngier
2013-04-26 10:45   ` Catalin Marinas
2013-04-26 10:59     ` Marc Zyngier
2013-04-12 18:12 ` [PATCH v4 2/7] ARM: KVM: fix HYP mapping limitations around zero Marc Zyngier
2013-04-12 18:12 ` [PATCH v4 3/7] ARM: KVM: move to a KVM provided HYP idmap Marc Zyngier
2013-04-17 19:37   ` Christoffer Dall
2013-04-18  9:08     ` Will Deacon
2013-04-12 18:12 ` [PATCH v4 4/7] ARM: KVM: enforce maximum size for identity mapped code Marc Zyngier
2013-04-12 18:12 ` [PATCH v4 5/7] ARM: KVM: rework HYP page table freeing Marc Zyngier
2013-04-26 11:05   ` Catalin Marinas
2013-04-26 16:45     ` Marc Zyngier
2013-04-26 21:07       ` Christoffer Dall
2013-04-27 15:21         ` Catalin Marinas
2013-04-12 18:12 ` [PATCH v4 6/7] ARM: KVM: switch to a dual-step HYP init code Marc Zyngier
2013-04-12 18:12 ` [PATCH v4 7/7] ARM: KVM: perform HYP initilization for hotplugged CPUs Marc Zyngier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1365790327-2138-1-git-send-email-marc.zyngier@arm.com \
    --to=marc.zyngier@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.