mips: Add KVM T&E segment support for TCG

MIPS KVM trap & emulate guest kernels have a different segment layout
compared with traditional MIPS kernels, to allow both the user and
kernel code to run from the user address segment without repeatedly
trapping to KVM.

QEMU currently supports this layout only for KVM, but its sometimes
useful to be able to run these kernels in QEMU on a PC, so enable it for
TCG too.

This also paves the way for MIPS KVM VZ support (which uses the normal
virtual memory layout) by abstracting whether user mode kernel segments
are in use.

Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Yongbok Kim <yongbok.kim@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org
Reviewed-by: Richard Henderson <rth@twiddle.net>
[Yongbok Kim:
  minor change]
Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com>
This commit is contained in:
James Hogan 2017-07-31 14:09:13 +01:00 committed by Yongbok Kim
parent 6743334568
commit d3d93c6c1e
5 changed files with 27 additions and 17 deletions

View file

@ -19,10 +19,10 @@
#include "qemu/osdep.h"
#include "cpu.h"
#include "sysemu/kvm.h"
#include "exec/exec-all.h"
#include "exec/cpu_ldst.h"
#include "exec/log.h"
#include "hw/mips/cpudevs.h"
enum {
TLBRET_XI = -6,
@ -225,7 +225,7 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical,
#define KVM_KSEG0_BASE ((target_ulong)(int32_t)0x40000000UL)
#define KVM_KSEG2_BASE ((target_ulong)(int32_t)0x60000000UL)
if (kvm_enabled()) {
if (mips_um_ksegs_enabled()) {
/* KVM T&E adds guest kernel segments in useg */
if (real_address >= KVM_KSEG0_BASE) {
if (real_address < KVM_KSEG2_BASE) {

View file

@ -27,10 +27,10 @@
#include "exec/exec-all.h"
#include "tcg-op.h"
#include "exec/cpu_ldst.h"
#include "hw/mips/cpudevs.h"
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
#include "sysemu/kvm.h"
#include "exec/semihost.h"
#include "target/mips/trace.h"
@ -20635,7 +20635,7 @@ void cpu_state_reset(CPUMIPSState *env)
env->CP0_Wired = 0;
env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
env->CP0_EBase = (cs->cpu_index & 0x3FF);
if (kvm_enabled()) {
if (mips_um_ksegs_enabled()) {
env->CP0_EBase |= 0x40000000;
} else {
env->CP0_EBase |= (int32_t)0x80000000;