qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL 00/14] Pending KVM patches for 2.1
@ 2014-06-20 12:11 Paolo Bonzini
  2014-06-20 12:11 ` [Qemu-devel] [PULL 01/14] KVM: Fix GSI number space limit Paolo Bonzini
                   ` (14 more replies)
  0 siblings, 15 replies; 16+ messages in thread
From: Paolo Bonzini @ 2014-06-20 12:11 UTC (permalink / raw)
  To: qemu-devel

The following changes since commit af44da87e926ff64260b95f4350d338c4fc113ca:

  Merge remote-tracking branch 'remotes/agraf/tags/signed-ppc-for-upstream' into staging (2014-06-16 18:26:21 +0100)

are available in the git repository at:


  git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.git uq/master

for you to fetch changes up to 3c5d0be553b18d47361ac3a701e2bff86b8256b0:

  hw/mips: malta: Don't boot from flash with KVM T&E (2014-06-20 13:51:29 +0200)

The highlight (covering 13/14th of the series) is MIPS Malta support
for trap-and-emulate KVM.  The QEMU<->kernel interface to implement
the equivalent of QEMU_CLOCK_VIRTUAL, that James came up with, is
particularly cool and a good model for other architectures to look at.

Alexander Graf (1):
      KVM: Fix GSI number space limit

James Hogan (8):
      target-mips: Reset CPU timer consistently
      target-mips: get_physical_address: Add defines for segment bases
      target-mips: get_physical_address: Add KVM awareness
      kvm: Allow arch to set sigmask length
      target-mips: Call kvm_mips_reset_vcpu() from mips_cpu_reset()
      hw/mips: malta: Add KVM support
      MAINTAINERS: Add entry for MIPS KVM
      hw/mips: malta: Don't boot from flash with KVM T&E

Sanjay Lal (5):
      hw/mips/cputimer: Don't start periodic timer in KVM mode
      hw/mips: Add API to convert KVM guest KSEG0 <-> GPA
      target-mips: kvm: Add main KVM support for MIPS
      hw/mips: In KVM mode, inject IRQ2 (I/O) interrupts via ioctls
      target-mips: Enable KVM support in build system

 MAINTAINERS               |    5 +
 configure                 |    6 +-
 hw/mips/addr.c            |    7 +-
 hw/mips/cputimer.c        |   18 +-
 hw/mips/mips_int.c        |   11 +
 hw/mips/mips_malta.c      |   79 ++++--
 include/hw/mips/cpudevs.h |    2 +
 include/sysemu/kvm.h      |    2 +
 kvm-all.c                 |   13 +-
 target-mips/Makefile.objs |    1 +
 target-mips/cpu.c         |    8 +
 target-mips/helper.c      |   51 +++-
 target-mips/kvm.c         |  683 +++++++++++++++++++++++++++++++++++++++++++++
 target-mips/kvm_mips.h    |   26 ++
 target-mips/translate.c   |    2 +
 15 files changed, 873 insertions(+), 41 deletions(-)
 create mode 100644 target-mips/kvm.c
 create mode 100644 target-mips/kvm_mips.h

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PULL 01/14] KVM: Fix GSI number space limit
  2014-06-20 12:11 [Qemu-devel] [PULL 00/14] Pending KVM patches for 2.1 Paolo Bonzini
@ 2014-06-20 12:11 ` Paolo Bonzini
  2014-06-20 12:11 ` [Qemu-devel] [PULL 02/14] target-mips: Reset CPU timer consistently Paolo Bonzini
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2014-06-20 12:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: Alexander Graf, qemu-stable

From: Alexander Graf <agraf@suse.de>

KVM tells us the number of GSIs it can handle inside the kernel. That value is
basically KVM_MAX_IRQ_ROUTES. However when we try to set the GSI mapping table,
it checks for

    r = -EINVAL;
    if (routing.nr >= KVM_MAX_IRQ_ROUTES)
        goto out;

erroring out even when we're only using all of the GSIs. To make sure we never
hit that limit, let's reduce the number of GSIs we get from KVM by one.

Cc: qemu-stable@nongnu.org
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 kvm-all.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/kvm-all.c b/kvm-all.c
index 4e19eff..56a251b 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -938,7 +938,7 @@ void kvm_init_irq_routing(KVMState *s)
 {
     int gsi_count, i;
 
-    gsi_count = kvm_check_extension(s, KVM_CAP_IRQ_ROUTING);
+    gsi_count = kvm_check_extension(s, KVM_CAP_IRQ_ROUTING) - 1;
     if (gsi_count > 0) {
         unsigned int gsi_bits, i;
 
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PULL 02/14] target-mips: Reset CPU timer consistently
  2014-06-20 12:11 [Qemu-devel] [PULL 00/14] Pending KVM patches for 2.1 Paolo Bonzini
  2014-06-20 12:11 ` [Qemu-devel] [PULL 01/14] KVM: Fix GSI number space limit Paolo Bonzini
@ 2014-06-20 12:11 ` Paolo Bonzini
  2014-06-20 12:11 ` [Qemu-devel] [PULL 03/14] hw/mips/cputimer: Don't start periodic timer in KVM mode Paolo Bonzini
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2014-06-20 12:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: James Hogan, Aurelien Jarno

From: James Hogan <james.hogan@imgtec.com>

The MIPS CPU timer (CP0 Count/Compare registers & QEMU timer) is
reset at machine initialisation, including starting the timeout. Both
registers however are placed before mvp in CPUMIPSState so they will
both be zeroed on reset by the memset in mips_cpu_reset() including soon
after init. This doesn't take into account that the timer may be
running, in which case env->CP0_Count will represent the delta against
the VM clock and the timeout will need updating.

At init time (cpu_mips_clock_init()), lets only create the timer.
Setting Count = 1 and starting the timer (cpu_mips_store_count()) can be
done at reset time from cpu_state_reset(), which is after the memset.
There is also no need to set CP0_Compare = 0 as that is already handled
by the memset.

Note that a reset occurs from mips_cpu_realizefn() which is before the
machine init callback has had a chance to set up the CPU interrupts and
the CPU timer, so env->timer will be NULL. This case is handled
explicitly in cpu_mips_store_count(), treating the timer as disabled
(which will also be the right thing to do when KVM support is added).

Reported-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/mips/cputimer.c      |    9 ++++++---
 target-mips/translate.c |    2 ++
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/hw/mips/cputimer.c b/hw/mips/cputimer.c
index c8b4b00..6900a74 100644
--- a/hw/mips/cputimer.c
+++ b/hw/mips/cputimer.c
@@ -85,7 +85,12 @@ uint32_t cpu_mips_get_count (CPUMIPSState *env)
 
 void cpu_mips_store_count (CPUMIPSState *env, uint32_t count)
 {
-    if (env->CP0_Cause & (1 << CP0Ca_DC))
+    /*
+     * This gets called from cpu_state_reset(), potentially before timer init.
+     * So env->timer may be NULL, which is also the case with KVM enabled so
+     * treat timer as disabled in that case.
+     */
+    if (env->CP0_Cause & (1 << CP0Ca_DC) || !env->timer)
         env->CP0_Count = count;
     else {
         /* Store new count register */
@@ -142,6 +147,4 @@ static void mips_timer_cb (void *opaque)
 void cpu_mips_clock_init (CPUMIPSState *env)
 {
     env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb, env);
-    env->CP0_Compare = 0;
-    cpu_mips_store_count(env, 1);
 }
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 76deb7b..d95ab9e 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -16043,6 +16043,8 @@ void cpu_state_reset(CPUMIPSState *env)
     /* Count register increments in debug mode, EJTAG version 1 */
     env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
 
+    cpu_mips_store_count(env, 1);
+
     if (env->CP0_Config3 & (1 << CP0C3_MT)) {
         int i;
 
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PULL 03/14] hw/mips/cputimer: Don't start periodic timer in KVM mode
  2014-06-20 12:11 [Qemu-devel] [PULL 00/14] Pending KVM patches for 2.1 Paolo Bonzini
  2014-06-20 12:11 ` [Qemu-devel] [PULL 01/14] KVM: Fix GSI number space limit Paolo Bonzini
  2014-06-20 12:11 ` [Qemu-devel] [PULL 02/14] target-mips: Reset CPU timer consistently Paolo Bonzini
@ 2014-06-20 12:11 ` Paolo Bonzini
  2014-06-20 12:11 ` [Qemu-devel] [PULL 04/14] hw/mips: Add API to convert KVM guest KSEG0 <-> GPA Paolo Bonzini
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2014-06-20 12:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: Sanjay Lal, James Hogan, Aurelien Jarno

From: Sanjay Lal <sanjayl@kymasys.com>

Compare/Count timer interrupts are handled in-kernel for KVM. Therefore
don't bother creating the timer at init time if KVM is enabled. This
will conveniently avoid attempts to set the timeout when
cpu_mips_store_count() is called at reset with KVM enabled, treating the
timer as stopped so that CP0_Count is modified directly.

Signed-off-by: Sanjay Lal <sanjayl@kymasys.com>
[james.hogan@imgtec.com: Update after "target-mips: Reset CPU timer
consistently" which moves timer start to reset time]
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/mips/cputimer.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/hw/mips/cputimer.c b/hw/mips/cputimer.c
index 6900a74..577c9ae 100644
--- a/hw/mips/cputimer.c
+++ b/hw/mips/cputimer.c
@@ -23,6 +23,7 @@
 #include "hw/hw.h"
 #include "hw/mips/cpudevs.h"
 #include "qemu/timer.h"
+#include "sysemu/kvm.h"
 
 #define TIMER_FREQ	100 * 1000 * 1000
 
@@ -146,5 +147,11 @@ static void mips_timer_cb (void *opaque)
 
 void cpu_mips_clock_init (CPUMIPSState *env)
 {
-    env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb, env);
+    /*
+     * If we're in KVM mode, don't create the periodic timer, that is handled in
+     * kernel.
+     */
+    if (!kvm_enabled()) {
+        env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb, env);
+    }
 }
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PULL 04/14] hw/mips: Add API to convert KVM guest KSEG0 <-> GPA
  2014-06-20 12:11 [Qemu-devel] [PULL 00/14] Pending KVM patches for 2.1 Paolo Bonzini
                   ` (2 preceding siblings ...)
  2014-06-20 12:11 ` [Qemu-devel] [PULL 03/14] hw/mips/cputimer: Don't start periodic timer in KVM mode Paolo Bonzini
@ 2014-06-20 12:11 ` Paolo Bonzini
  2014-06-20 12:11 ` [Qemu-devel] [PULL 05/14] target-mips: get_physical_address: Add defines for segment bases Paolo Bonzini
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2014-06-20 12:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: Sanjay Lal, James Hogan, Aurelien Jarno

From: Sanjay Lal <sanjayl@kymasys.com>

Add API for converting physical addresses to KVM guest KSEG0 addresses,
and fix the existing API for converting KSEG0 addresses to physical
addresses to work in the KVM case. Both have the same sized KSEG0, so
it's just a case of fixing the mask.

In KVM trap and emulate mode both the guest kernel and guest userspace
execute in useg:
    Guest User address space:   0x00000000..0x3fffffff
    Guest Kernel Unmapped:      0x40000000..0x5fffffff
    Guest Kernel Mapped:        0x60000000..0x7fffffff

Signed-off-by: Sanjay Lal <sanjayl@kymasys.com>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/mips/addr.c            |    7 ++++++-
 include/hw/mips/cpudevs.h |    2 ++
 2 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/hw/mips/addr.c b/hw/mips/addr.c
index 99488f1..ff3b952 100644
--- a/hw/mips/addr.c
+++ b/hw/mips/addr.c
@@ -25,10 +25,15 @@
 
 uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr)
 {
-    return addr & 0x7fffffffll;
+    return addr & 0x1fffffffll;
 }
 
 uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr)
 {
     return addr | ~0x7fffffffll;
 }
+
+uint64_t cpu_mips_kvm_um_phys_to_kseg0(void *opaque, uint64_t addr)
+{
+    return addr | 0x40000000ll;
+}
diff --git a/include/hw/mips/cpudevs.h b/include/hw/mips/cpudevs.h
index 6bea24b..b2626f2 100644
--- a/include/hw/mips/cpudevs.h
+++ b/include/hw/mips/cpudevs.h
@@ -5,6 +5,8 @@
 /* mips_addr.c */
 uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr);
 uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr);
+uint64_t cpu_mips_kvm_um_phys_to_kseg0(void *opaque, uint64_t addr);
+
 
 /* mips_int.c */
 void cpu_mips_irq_init_cpu(CPUMIPSState *env);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PULL 05/14] target-mips: get_physical_address: Add defines for segment bases
  2014-06-20 12:11 [Qemu-devel] [PULL 00/14] Pending KVM patches for 2.1 Paolo Bonzini
                   ` (3 preceding siblings ...)
  2014-06-20 12:11 ` [Qemu-devel] [PULL 04/14] hw/mips: Add API to convert KVM guest KSEG0 <-> GPA Paolo Bonzini
@ 2014-06-20 12:11 ` Paolo Bonzini
  2014-06-20 12:11 ` [Qemu-devel] [PULL 06/14] target-mips: get_physical_address: Add KVM awareness Paolo Bonzini
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2014-06-20 12:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: James Hogan

From: James Hogan <james.hogan@imgtec.com>

Add preprocessor definitions for 32bit segment bases for use in
get_physical_address(). These will also be taken advantage of in the
next patch which adds KVM awareness.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target-mips/helper.c |   18 ++++++++++++------
 1 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/target-mips/helper.c b/target-mips/helper.c
index 064622c..caacd76 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -118,7 +118,13 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical,
     qemu_log("user mode %d h %08x\n", user_mode, env->hflags);
 #endif
 
-    if (address <= (int32_t)0x7FFFFFFFUL) {
+#define USEG_LIMIT      0x7FFFFFFFUL
+#define KSEG0_BASE      0x80000000UL
+#define KSEG1_BASE      0xA0000000UL
+#define KSEG2_BASE      0xC0000000UL
+#define KSEG3_BASE      0xE0000000UL
+
+    if (address <= USEG_LIMIT) {
         /* useg */
         if (env->CP0_Status & (1 << CP0St_ERL)) {
             *physical = address & 0xFFFFFFFF;
@@ -160,23 +166,23 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical,
             ret = TLBRET_BADADDR;
         }
 #endif
-    } else if (address < (int32_t)0xA0000000UL) {
+    } else if (address < (int32_t)KSEG1_BASE) {
         /* kseg0 */
         if (kernel_mode) {
-            *physical = address - (int32_t)0x80000000UL;
+            *physical = address - (int32_t)KSEG0_BASE;
             *prot = PAGE_READ | PAGE_WRITE;
         } else {
             ret = TLBRET_BADADDR;
         }
-    } else if (address < (int32_t)0xC0000000UL) {
+    } else if (address < (int32_t)KSEG2_BASE) {
         /* kseg1 */
         if (kernel_mode) {
-            *physical = address - (int32_t)0xA0000000UL;
+            *physical = address - (int32_t)KSEG1_BASE;
             *prot = PAGE_READ | PAGE_WRITE;
         } else {
             ret = TLBRET_BADADDR;
         }
-    } else if (address < (int32_t)0xE0000000UL) {
+    } else if (address < (int32_t)KSEG3_BASE) {
         /* sseg (kseg2) */
         if (supervisor_mode || kernel_mode) {
             ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PULL 06/14] target-mips: get_physical_address: Add KVM awareness
  2014-06-20 12:11 [Qemu-devel] [PULL 00/14] Pending KVM patches for 2.1 Paolo Bonzini
                   ` (4 preceding siblings ...)
  2014-06-20 12:11 ` [Qemu-devel] [PULL 05/14] target-mips: get_physical_address: Add defines for segment bases Paolo Bonzini
@ 2014-06-20 12:11 ` Paolo Bonzini
  2014-06-20 12:11 ` [Qemu-devel] [PULL 07/14] kvm: Allow arch to set sigmask length Paolo Bonzini
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2014-06-20 12:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: James Hogan, Aurelien Jarno

From: James Hogan <james.hogan@imgtec.com>

MIPS KVM trap & emulate mode (which is currently the only supported
mode) has to add an extra kseg0/kseg1 at 0x40000000 and an extra
kseg2/kseg3 at 0x60000000. Take this into account in
get_physical_address() so that debug memory access works.

This is done by translating the address to a standard kseg0 or kseg2
address before doing the normal address translation. The real virtual
address is still used for TLB lookups.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target-mips/helper.c |   33 ++++++++++++++++++++++++++-------
 1 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/target-mips/helper.c b/target-mips/helper.c
index caacd76..8a997e4 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -24,6 +24,7 @@
 #include <signal.h>
 
 #include "cpu.h"
+#include "sysemu/kvm.h"
 
 enum {
     TLBRET_DIRTY = -4,
@@ -100,7 +101,7 @@ int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
 }
 
 static int get_physical_address (CPUMIPSState *env, hwaddr *physical,
-                                int *prot, target_ulong address,
+                                int *prot, target_ulong real_address,
                                 int rw, int access_type)
 {
     /* User mode can only access useg/xuseg */
@@ -113,6 +114,8 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical,
     int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0;
 #endif
     int ret = TLBRET_MATCH;
+    /* effective address (modified for KVM T&E kernel segments) */
+    target_ulong address = real_address;
 
 #if 0
     qemu_log("user mode %d h %08x\n", user_mode, env->hflags);
@@ -124,19 +127,35 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical,
 #define KSEG2_BASE      0xC0000000UL
 #define KSEG3_BASE      0xE0000000UL
 
+#define KVM_KSEG0_BASE  0x40000000UL
+#define KVM_KSEG2_BASE  0x60000000UL
+
+    if (kvm_enabled()) {
+        /* KVM T&E adds guest kernel segments in useg */
+        if (real_address >= KVM_KSEG0_BASE) {
+            if (real_address < KVM_KSEG2_BASE) {
+                /* kseg0 */
+                address += KSEG0_BASE - KVM_KSEG0_BASE;
+            } else if (real_address <= USEG_LIMIT) {
+                /* kseg2/3 */
+                address += KSEG2_BASE - KVM_KSEG2_BASE;
+            }
+        }
+    }
+
     if (address <= USEG_LIMIT) {
         /* useg */
         if (env->CP0_Status & (1 << CP0St_ERL)) {
             *physical = address & 0xFFFFFFFF;
             *prot = PAGE_READ | PAGE_WRITE;
         } else {
-            ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
+            ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type);
         }
 #if defined(TARGET_MIPS64)
     } else if (address < 0x4000000000000000ULL) {
         /* xuseg */
         if (UX && address <= (0x3FFFFFFFFFFFFFFFULL & env->SEGMask)) {
-            ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
+            ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type);
         } else {
             ret = TLBRET_BADADDR;
         }
@@ -144,7 +163,7 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical,
         /* xsseg */
         if ((supervisor_mode || kernel_mode) &&
             SX && address <= (0x7FFFFFFFFFFFFFFFULL & env->SEGMask)) {
-            ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
+            ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type);
         } else {
             ret = TLBRET_BADADDR;
         }
@@ -161,7 +180,7 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical,
         /* xkseg */
         if (kernel_mode && KX &&
             address <= (0xFFFFFFFF7FFFFFFFULL & env->SEGMask)) {
-            ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
+            ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type);
         } else {
             ret = TLBRET_BADADDR;
         }
@@ -185,7 +204,7 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical,
     } else if (address < (int32_t)KSEG3_BASE) {
         /* sseg (kseg2) */
         if (supervisor_mode || kernel_mode) {
-            ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
+            ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type);
         } else {
             ret = TLBRET_BADADDR;
         }
@@ -193,7 +212,7 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical,
         /* kseg3 */
         /* XXX: debug segment is not emulated */
         if (kernel_mode) {
-            ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
+            ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type);
         } else {
             ret = TLBRET_BADADDR;
         }
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PULL 07/14] kvm: Allow arch to set sigmask length
  2014-06-20 12:11 [Qemu-devel] [PULL 00/14] Pending KVM patches for 2.1 Paolo Bonzini
                   ` (5 preceding siblings ...)
  2014-06-20 12:11 ` [Qemu-devel] [PULL 06/14] target-mips: get_physical_address: Add KVM awareness Paolo Bonzini
@ 2014-06-20 12:11 ` Paolo Bonzini
  2014-06-20 12:11 ` [Qemu-devel] [PULL 08/14] target-mips: kvm: Add main KVM support for MIPS Paolo Bonzini
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2014-06-20 12:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: Sanjay Lal, James Hogan, Gleb Natapov, Aurelien Jarno,
	Peter Maydell

From: James Hogan <james.hogan@imgtec.com>

MIPS/Linux is unusual in having 128 signals rather than just 64 like
most other architectures. This means its sigmask is 16 bytes instead of
8, so allow arches to override the sigmask->len value passed to the
KVM_SET_SIGNAL_MASK ioctl in kvm_set_signal_mask() by calling
kvm_set_sigmask_len() from kvm_arch_init(). Otherwise default to 8
bytes.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Sanjay Lal <sanjayl@kymasys.com>
Cc: Gleb Natapov <gleb@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 include/sysemu/kvm.h |    2 ++
 kvm-all.c            |   11 ++++++++++-
 2 files changed, 12 insertions(+), 1 deletions(-)

diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index e79e92c..de4bdaa 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -325,6 +325,8 @@ int kvm_check_extension(KVMState *s, unsigned int extension);
 uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function,
                                       uint32_t index, int reg);
 
+void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len);
+
 #if !defined(CONFIG_USER_ONLY)
 int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr,
                                        hwaddr *phys_addr);
diff --git a/kvm-all.c b/kvm-all.c
index 56a251b..3142335 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -99,6 +99,7 @@ struct KVMState
      * they're not.  Linux, glibc and *BSD all treat ioctl numbers as
      * unsigned, and treating them as signed here can break things */
     unsigned irq_set_ioctl;
+    unsigned int sigmask_len;
 #ifdef KVM_CAP_IRQ_ROUTING
     struct kvm_irq_routing *irq_routes;
     int nr_allocated_irq_routes;
@@ -1397,6 +1398,8 @@ int kvm_init(MachineClass *mc)
     assert(TARGET_PAGE_SIZE <= getpagesize());
     page_size_init();
 
+    s->sigmask_len = 8;
+
 #ifdef KVM_CAP_SET_GUEST_DEBUG
     QTAILQ_INIT(&s->kvm_sw_breakpoints);
 #endif
@@ -1575,6 +1578,11 @@ err:
     return ret;
 }
 
+void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len)
+{
+    s->sigmask_len = sigmask_len;
+}
+
 static void kvm_handle_io(uint16_t port, void *data, int direction, int size,
                           uint32_t count)
 {
@@ -2095,6 +2103,7 @@ void kvm_remove_all_breakpoints(CPUState *cpu)
 
 int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset)
 {
+    KVMState *s = kvm_state;
     struct kvm_signal_mask *sigmask;
     int r;
 
@@ -2104,7 +2113,7 @@ int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset)
 
     sigmask = g_malloc(sizeof(*sigmask) + sizeof(*sigset));
 
-    sigmask->len = 8;
+    sigmask->len = s->sigmask_len;
     memcpy(sigmask->sigset, sigset, sizeof(*sigset));
     r = kvm_vcpu_ioctl(cpu, KVM_SET_SIGNAL_MASK, sigmask);
     g_free(sigmask);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PULL 08/14] target-mips: kvm: Add main KVM support for MIPS
  2014-06-20 12:11 [Qemu-devel] [PULL 00/14] Pending KVM patches for 2.1 Paolo Bonzini
                   ` (6 preceding siblings ...)
  2014-06-20 12:11 ` [Qemu-devel] [PULL 07/14] kvm: Allow arch to set sigmask length Paolo Bonzini
@ 2014-06-20 12:11 ` Paolo Bonzini
  2014-06-20 12:11 ` [Qemu-devel] [PULL 09/14] target-mips: Call kvm_mips_reset_vcpu() from mips_cpu_reset() Paolo Bonzini
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2014-06-20 12:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, James Hogan, Gleb Natapov, Sanjay Lal,
	Andreas Färber, Aurelien Jarno

From: Sanjay Lal <sanjayl@kymasys.com>

Implement the main KVM arch API for MIPS.

Signed-off-by: Sanjay Lal <sanjayl@kymasys.com>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Gleb Natapov <gleb@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Andreas Färber <afaerber@suse.de>
Cc: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target-mips/kvm.c      |  683 ++++++++++++++++++++++++++++++++++++++++++++++++
 target-mips/kvm_mips.h |   26 ++
 2 files changed, 709 insertions(+), 0 deletions(-)
 create mode 100644 target-mips/kvm.c
 create mode 100644 target-mips/kvm_mips.h

diff --git a/target-mips/kvm.c b/target-mips/kvm.c
new file mode 100644
index 0000000..844e5bb
--- /dev/null
+++ b/target-mips/kvm.c
@@ -0,0 +1,683 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * KVM/MIPS: MIPS specific KVM APIs
+ *
+ * Copyright (C) 2012-2014 Imagination Technologies Ltd.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+*/
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include <linux/kvm.h>
+
+#include "qemu-common.h"
+#include "qemu/error-report.h"
+#include "qemu/timer.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/kvm.h"
+#include "cpu.h"
+#include "sysemu/cpus.h"
+#include "kvm_mips.h"
+
+#define DEBUG_KVM 0
+
+#define DPRINTF(fmt, ...) \
+    do { if (DEBUG_KVM) { fprintf(stderr, fmt, ## __VA_ARGS__); } } while (0)
+
+const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
+    KVM_CAP_LAST_INFO
+};
+
+static void kvm_mips_update_state(void *opaque, int running, RunState state);
+
+unsigned long kvm_arch_vcpu_id(CPUState *cs)
+{
+    return cs->cpu_index;
+}
+
+int kvm_arch_init(KVMState *s)
+{
+    /* MIPS has 128 signals */
+    kvm_set_sigmask_len(s, 16);
+
+    DPRINTF("%s\n", __func__);
+    return 0;
+}
+
+int kvm_arch_init_vcpu(CPUState *cs)
+{
+    int ret = 0;
+
+    qemu_add_vm_change_state_handler(kvm_mips_update_state, cs);
+
+    DPRINTF("%s\n", __func__);
+    return ret;
+}
+
+void kvm_mips_reset_vcpu(MIPSCPU *cpu)
+{
+    DPRINTF("%s\n", __func__);
+}
+
+int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
+{
+    DPRINTF("%s\n", __func__);
+    return 0;
+}
+
+int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
+{
+    DPRINTF("%s\n", __func__);
+    return 0;
+}
+
+static inline int cpu_mips_io_interrupts_pending(MIPSCPU *cpu)
+{
+    CPUMIPSState *env = &cpu->env;
+
+    DPRINTF("%s: %#x\n", __func__, env->CP0_Cause & (1 << (2 + CP0Ca_IP)));
+    return env->CP0_Cause & (0x1 << (2 + CP0Ca_IP));
+}
+
+
+void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
+{
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    int r;
+    struct kvm_mips_interrupt intr;
+
+    if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
+            cpu_mips_io_interrupts_pending(cpu)) {
+        intr.cpu = -1;
+        intr.irq = 2;
+        r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
+        if (r < 0) {
+            error_report("%s: cpu %d: failed to inject IRQ %x",
+                         __func__, cs->cpu_index, intr.irq);
+        }
+    }
+}
+
+void kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
+{
+    DPRINTF("%s\n", __func__);
+}
+
+int kvm_arch_process_async_events(CPUState *cs)
+{
+    return cs->halted;
+}
+
+int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
+{
+    int ret;
+
+    DPRINTF("%s\n", __func__);
+    switch (run->exit_reason) {
+    default:
+        error_report("%s: unknown exit reason %d",
+                     __func__, run->exit_reason);
+        ret = -1;
+        break;
+    }
+
+    return ret;
+}
+
+bool kvm_arch_stop_on_emulation_error(CPUState *cs)
+{
+    DPRINTF("%s\n", __func__);
+    return true;
+}
+
+int kvm_arch_on_sigbus_vcpu(CPUState *cs, int code, void *addr)
+{
+    DPRINTF("%s\n", __func__);
+    return 1;
+}
+
+int kvm_arch_on_sigbus(int code, void *addr)
+{
+    DPRINTF("%s\n", __func__);
+    return 1;
+}
+
+void kvm_arch_init_irq_routing(KVMState *s)
+{
+}
+
+int kvm_mips_set_interrupt(MIPSCPU *cpu, int irq, int level)
+{
+    CPUState *cs = CPU(cpu);
+    struct kvm_mips_interrupt intr;
+
+    if (!kvm_enabled()) {
+        return 0;
+    }
+
+    intr.cpu = -1;
+
+    if (level) {
+        intr.irq = irq;
+    } else {
+        intr.irq = -irq;
+    }
+
+    kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
+
+    return 0;
+}
+
+int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level)
+{
+    CPUState *cs = current_cpu;
+    CPUState *dest_cs = CPU(cpu);
+    struct kvm_mips_interrupt intr;
+
+    if (!kvm_enabled()) {
+        return 0;
+    }
+
+    intr.cpu = dest_cs->cpu_index;
+
+    if (level) {
+        intr.irq = irq;
+    } else {
+        intr.irq = -irq;
+    }
+
+    DPRINTF("%s: CPU %d, IRQ: %d\n", __func__, intr.cpu, intr.irq);
+
+    kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
+
+    return 0;
+}
+
+#define MIPS_CP0_32(_R, _S)                                     \
+    (KVM_REG_MIPS | KVM_REG_SIZE_U32 | 0x10000 | (8 * (_R) + (_S)))
+
+#define MIPS_CP0_64(_R, _S)                                     \
+    (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 0x10000 | (8 * (_R) + (_S)))
+
+#define KVM_REG_MIPS_CP0_INDEX          MIPS_CP0_32(0, 0)
+#define KVM_REG_MIPS_CP0_CONTEXT        MIPS_CP0_64(4, 0)
+#define KVM_REG_MIPS_CP0_USERLOCAL      MIPS_CP0_64(4, 2)
+#define KVM_REG_MIPS_CP0_PAGEMASK       MIPS_CP0_32(5, 0)
+#define KVM_REG_MIPS_CP0_WIRED          MIPS_CP0_32(6, 0)
+#define KVM_REG_MIPS_CP0_HWRENA         MIPS_CP0_32(7, 0)
+#define KVM_REG_MIPS_CP0_BADVADDR       MIPS_CP0_64(8, 0)
+#define KVM_REG_MIPS_CP0_COUNT          MIPS_CP0_32(9, 0)
+#define KVM_REG_MIPS_CP0_ENTRYHI        MIPS_CP0_64(10, 0)
+#define KVM_REG_MIPS_CP0_COMPARE        MIPS_CP0_32(11, 0)
+#define KVM_REG_MIPS_CP0_STATUS         MIPS_CP0_32(12, 0)
+#define KVM_REG_MIPS_CP0_CAUSE          MIPS_CP0_32(13, 0)
+#define KVM_REG_MIPS_CP0_EPC            MIPS_CP0_64(14, 0)
+#define KVM_REG_MIPS_CP0_ERROREPC       MIPS_CP0_64(30, 0)
+
+/* CP0_Count control */
+#define KVM_REG_MIPS_COUNT_CTL          (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \
+                                         0x20000 | 0)
+#define KVM_REG_MIPS_COUNT_CTL_DC       0x00000001      /* master disable */
+/* CP0_Count resume monotonic nanoseconds */
+#define KVM_REG_MIPS_COUNT_RESUME       (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \
+                                         0x20000 | 1)
+/* CP0_Count rate in Hz */
+#define KVM_REG_MIPS_COUNT_HZ           (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \
+                                         0x20000 | 2)
+
+static inline int kvm_mips_put_one_reg(CPUState *cs, uint64_t reg_id,
+                                       int32_t *addr)
+{
+    uint64_t val64 = *addr;
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (uintptr_t)&val64
+    };
+
+    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
+}
+
+static inline int kvm_mips_put_one_ulreg(CPUState *cs, uint64_t reg_id,
+                                         target_ulong *addr)
+{
+    uint64_t val64 = *addr;
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (uintptr_t)&val64
+    };
+
+    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
+}
+
+static inline int kvm_mips_put_one_reg64(CPUState *cs, uint64_t reg_id,
+                                         uint64_t *addr)
+{
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (uintptr_t)addr
+    };
+
+    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
+}
+
+static inline int kvm_mips_get_one_reg(CPUState *cs, uint64_t reg_id,
+                                       int32_t *addr)
+{
+    int ret;
+    uint64_t val64 = 0;
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (uintptr_t)&val64
+    };
+
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
+    if (ret >= 0) {
+        *addr = val64;
+    }
+    return ret;
+}
+
+static inline int kvm_mips_get_one_ulreg(CPUState *cs, uint64 reg_id,
+                                         target_ulong *addr)
+{
+    int ret;
+    uint64_t val64 = 0;
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (uintptr_t)&val64
+    };
+
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
+    if (ret >= 0) {
+        *addr = val64;
+    }
+    return ret;
+}
+
+static inline int kvm_mips_get_one_reg64(CPUState *cs, uint64 reg_id,
+                                         uint64_t *addr)
+{
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (uintptr_t)addr
+    };
+
+    return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
+}
+
+/*
+ * We freeze the KVM timer when either the VM clock is stopped or the state is
+ * saved (the state is dirty).
+ */
+
+/*
+ * Save the state of the KVM timer when VM clock is stopped or state is synced
+ * to QEMU.
+ */
+static int kvm_mips_save_count(CPUState *cs)
+{
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    CPUMIPSState *env = &cpu->env;
+    uint64_t count_ctl;
+    int err, ret = 0;
+
+    /* freeze KVM timer */
+    err = kvm_mips_get_one_reg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get COUNT_CTL (%d)\n", __func__, err);
+        ret = err;
+    } else if (!(count_ctl & KVM_REG_MIPS_COUNT_CTL_DC)) {
+        count_ctl |= KVM_REG_MIPS_COUNT_CTL_DC;
+        err = kvm_mips_put_one_reg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl);
+        if (err < 0) {
+            DPRINTF("%s: Failed to set COUNT_CTL.DC=1 (%d)\n", __func__, err);
+            ret = err;
+        }
+    }
+
+    /* read CP0_Cause */
+    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_CAUSE (%d)\n", __func__, err);
+        ret = err;
+    }
+
+    /* read CP0_Count */
+    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_COUNT (%d)\n", __func__, err);
+        ret = err;
+    }
+
+    return ret;
+}
+
+/*
+ * Restore the state of the KVM timer when VM clock is restarted or state is
+ * synced to KVM.
+ */
+static int kvm_mips_restore_count(CPUState *cs)
+{
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    CPUMIPSState *env = &cpu->env;
+    uint64_t count_ctl;
+    int err_dc, err, ret = 0;
+
+    /* check the timer is frozen */
+    err_dc = kvm_mips_get_one_reg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl);
+    if (err_dc < 0) {
+        DPRINTF("%s: Failed to get COUNT_CTL (%d)\n", __func__, err_dc);
+        ret = err_dc;
+    } else if (!(count_ctl & KVM_REG_MIPS_COUNT_CTL_DC)) {
+        /* freeze timer (sets COUNT_RESUME for us) */
+        count_ctl |= KVM_REG_MIPS_COUNT_CTL_DC;
+        err = kvm_mips_put_one_reg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl);
+        if (err < 0) {
+            DPRINTF("%s: Failed to set COUNT_CTL.DC=1 (%d)\n", __func__, err);
+            ret = err;
+        }
+    }
+
+    /* load CP0_Cause */
+    err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_CAUSE (%d)\n", __func__, err);
+        ret = err;
+    }
+
+    /* load CP0_Count */
+    err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_COUNT (%d)\n", __func__, err);
+        ret = err;
+    }
+
+    /* resume KVM timer */
+    if (err_dc >= 0) {
+        count_ctl &= ~KVM_REG_MIPS_COUNT_CTL_DC;
+        err = kvm_mips_put_one_reg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl);
+        if (err < 0) {
+            DPRINTF("%s: Failed to set COUNT_CTL.DC=0 (%d)\n", __func__, err);
+            ret = err;
+        }
+    }
+
+    return ret;
+}
+
+/*
+ * Handle the VM clock being started or stopped
+ */
+static void kvm_mips_update_state(void *opaque, int running, RunState state)
+{
+    CPUState *cs = opaque;
+    int ret;
+    uint64_t count_resume;
+
+    /*
+     * If state is already dirty (synced to QEMU) then the KVM timer state is
+     * already saved and can be restored when it is synced back to KVM.
+     */
+    if (!running) {
+        if (!cs->kvm_vcpu_dirty) {
+            ret = kvm_mips_save_count(cs);
+            if (ret < 0) {
+                fprintf(stderr, "Failed saving count\n");
+            }
+        }
+    } else {
+        /* Set clock restore time to now */
+        count_resume = get_clock();
+        ret = kvm_mips_put_one_reg64(cs, KVM_REG_MIPS_COUNT_RESUME,
+                                     &count_resume);
+        if (ret < 0) {
+            fprintf(stderr, "Failed setting COUNT_RESUME\n");
+            return;
+        }
+
+        if (!cs->kvm_vcpu_dirty) {
+            ret = kvm_mips_restore_count(cs);
+            if (ret < 0) {
+                fprintf(stderr, "Failed restoring count\n");
+            }
+        }
+    }
+}
+
+static int kvm_mips_put_cp0_registers(CPUState *cs, int level)
+{
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    CPUMIPSState *env = &cpu->env;
+    int err, ret = 0;
+
+    (void)level;
+
+    err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_INDEX (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
+                                 &env->CP0_Context);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_CONTEXT (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_USERLOCAL,
+                                 &env->active_tc.CP0_UserLocal);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_USERLOCAL (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK,
+                               &env->CP0_PageMask);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_PAGEMASK (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_WIRED (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_HWRENA (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR,
+                                 &env->CP0_BadVAddr);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_BADVADDR (%d)\n", __func__, err);
+        ret = err;
+    }
+
+    /* If VM clock stopped then state will be restored when it is restarted */
+    if (runstate_is_running()) {
+        err = kvm_mips_restore_count(cs);
+        if (err < 0) {
+            ret = err;
+        }
+    }
+
+    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI,
+                                 &env->CP0_EntryHi);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_ENTRYHI (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE,
+                               &env->CP0_Compare);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_COMPARE (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_STATUS (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_EPC (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
+                                 &env->CP0_ErrorEPC);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_ERROREPC (%d)\n", __func__, err);
+        ret = err;
+    }
+
+    return ret;
+}
+
+static int kvm_mips_get_cp0_registers(CPUState *cs)
+{
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    CPUMIPSState *env = &cpu->env;
+    int err, ret = 0;
+
+    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_INDEX (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
+                                 &env->CP0_Context);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_CONTEXT (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_USERLOCAL,
+                                 &env->active_tc.CP0_UserLocal);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_USERLOCAL (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK,
+                               &env->CP0_PageMask);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_PAGEMASK (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_WIRED (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_HWRENA (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR,
+                                 &env->CP0_BadVAddr);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_BADVADDR (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI,
+                                 &env->CP0_EntryHi);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_ENTRYHI (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE,
+                               &env->CP0_Compare);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_COMPARE (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_STATUS (%d)\n", __func__, err);
+        ret = err;
+    }
+
+    /* If VM clock stopped then state was already saved when it was stopped */
+    if (runstate_is_running()) {
+        err = kvm_mips_save_count(cs);
+        if (err < 0) {
+            ret = err;
+        }
+    }
+
+    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_EPC (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
+                                 &env->CP0_ErrorEPC);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_ERROREPC (%d)\n", __func__, err);
+        ret = err;
+    }
+
+    return ret;
+}
+
+int kvm_arch_put_registers(CPUState *cs, int level)
+{
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    CPUMIPSState *env = &cpu->env;
+    struct kvm_regs regs;
+    int ret;
+    int i;
+
+    /* Set the registers based on QEMU's view of things */
+    for (i = 0; i < 32; i++) {
+        regs.gpr[i] = env->active_tc.gpr[i];
+    }
+
+    regs.hi = env->active_tc.HI[0];
+    regs.lo = env->active_tc.LO[0];
+    regs.pc = env->active_tc.PC;
+
+    ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, &regs);
+
+    if (ret < 0) {
+        return ret;
+    }
+
+    ret = kvm_mips_put_cp0_registers(cs, level);
+    if (ret < 0) {
+        return ret;
+    }
+
+    return ret;
+}
+
+int kvm_arch_get_registers(CPUState *cs)
+{
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    CPUMIPSState *env = &cpu->env;
+    int ret = 0;
+    struct kvm_regs regs;
+    int i;
+
+    /* Get the current register set as KVM seems it */
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, &regs);
+
+    if (ret < 0) {
+        return ret;
+    }
+
+    for (i = 0; i < 32; i++) {
+        env->active_tc.gpr[i] = regs.gpr[i];
+    }
+
+    env->active_tc.HI[0] = regs.hi;
+    env->active_tc.LO[0] = regs.lo;
+    env->active_tc.PC = regs.pc;
+
+    kvm_mips_get_cp0_registers(cs);
+
+    return ret;
+}
diff --git a/target-mips/kvm_mips.h b/target-mips/kvm_mips.h
new file mode 100644
index 0000000..54f5965
--- /dev/null
+++ b/target-mips/kvm_mips.h
@@ -0,0 +1,26 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * KVM/MIPS: MIPS specific KVM APIs
+ *
+ * Copyright (C) 2012-2014 Imagination Technologies Ltd.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+*/
+
+#ifndef __KVM_MIPS_H__
+#define __KVM_MIPS_H__
+
+/**
+ * kvm_mips_reset_vcpu:
+ * @cpu: MIPSCPU
+ *
+ * Called at reset time to set kernel registers to their initial values.
+ */
+void kvm_mips_reset_vcpu(MIPSCPU *cpu);
+
+int kvm_mips_set_interrupt(MIPSCPU *cpu, int irq, int level);
+int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level);
+
+#endif /* __KVM_MIPS_H__ */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PULL 09/14] target-mips: Call kvm_mips_reset_vcpu() from mips_cpu_reset()
  2014-06-20 12:11 [Qemu-devel] [PULL 00/14] Pending KVM patches for 2.1 Paolo Bonzini
                   ` (7 preceding siblings ...)
  2014-06-20 12:11 ` [Qemu-devel] [PULL 08/14] target-mips: kvm: Add main KVM support for MIPS Paolo Bonzini
@ 2014-06-20 12:11 ` Paolo Bonzini
  2014-06-20 12:11 ` [Qemu-devel] [PULL 10/14] hw/mips: In KVM mode, inject IRQ2 (I/O) interrupts via ioctls Paolo Bonzini
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2014-06-20 12:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: James Hogan, Gleb Natapov, Aurelien Jarno

From: James Hogan <james.hogan@imgtec.com>

When KVM is enabled call kvm_mips_reset_vcpu() from mips_cpu_reset() as
done for other targets since commit 50a2c6e55fa2 (kvm: reset state from
the CPU's reset method).

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target-mips/cpu.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/target-mips/cpu.c b/target-mips/cpu.c
index dd954fc..b3e0e6c 100644
--- a/target-mips/cpu.c
+++ b/target-mips/cpu.c
@@ -19,7 +19,9 @@
  */
 
 #include "cpu.h"
+#include "kvm_mips.h"
 #include "qemu-common.h"
+#include "sysemu/kvm.h"
 
 
 static void mips_cpu_set_pc(CPUState *cs, vaddr value)
@@ -87,6 +89,12 @@ static void mips_cpu_reset(CPUState *s)
     tlb_flush(s, 1);
 
     cpu_state_reset(env);
+
+#ifndef CONFIG_USER_ONLY
+    if (kvm_enabled()) {
+        kvm_mips_reset_vcpu(cpu);
+    }
+#endif
 }
 
 static void mips_cpu_realizefn(DeviceState *dev, Error **errp)
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PULL 10/14] hw/mips: In KVM mode, inject IRQ2 (I/O) interrupts via ioctls
  2014-06-20 12:11 [Qemu-devel] [PULL 00/14] Pending KVM patches for 2.1 Paolo Bonzini
                   ` (8 preceding siblings ...)
  2014-06-20 12:11 ` [Qemu-devel] [PULL 09/14] target-mips: Call kvm_mips_reset_vcpu() from mips_cpu_reset() Paolo Bonzini
@ 2014-06-20 12:11 ` Paolo Bonzini
  2014-06-20 12:11 ` [Qemu-devel] [PULL 11/14] hw/mips: malta: Add KVM support Paolo Bonzini
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2014-06-20 12:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: Sanjay Lal, James Hogan

From: Sanjay Lal <sanjayl@kymasys.com>

COP0 emulation is in-kernel for KVM, so inject IRQ2 (I/O) interrupts via
ioctls.

Signed-off-by: Sanjay Lal <sanjayl@kymasys.com>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/mips/mips_int.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c
index 7dbd24d..d740046 100644
--- a/hw/mips/mips_int.c
+++ b/hw/mips/mips_int.c
@@ -23,6 +23,8 @@
 #include "hw/hw.h"
 #include "hw/mips/cpudevs.h"
 #include "cpu.h"
+#include "sysemu/kvm.h"
+#include "kvm_mips.h"
 
 static void cpu_mips_irq_request(void *opaque, int irq, int level)
 {
@@ -35,8 +37,17 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level)
 
     if (level) {
         env->CP0_Cause |= 1 << (irq + CP0Ca_IP);
+
+        if (kvm_enabled() && irq == 2) {
+            kvm_mips_set_interrupt(cpu, irq, level);
+        }
+
     } else {
         env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
+
+        if (kvm_enabled() && irq == 2) {
+            kvm_mips_set_interrupt(cpu, irq, level);
+        }
     }
 
     if (env->CP0_Cause & CP0Ca_IP_mask) {
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PULL 11/14] hw/mips: malta: Add KVM support
  2014-06-20 12:11 [Qemu-devel] [PULL 00/14] Pending KVM patches for 2.1 Paolo Bonzini
                   ` (9 preceding siblings ...)
  2014-06-20 12:11 ` [Qemu-devel] [PULL 10/14] hw/mips: In KVM mode, inject IRQ2 (I/O) interrupts via ioctls Paolo Bonzini
@ 2014-06-20 12:11 ` Paolo Bonzini
  2014-06-20 12:11 ` [Qemu-devel] [PULL 12/14] target-mips: Enable KVM support in build system Paolo Bonzini
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2014-06-20 12:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, James Hogan, Sanjay Lal

From: James Hogan <james.hogan@imgtec.com>

In KVM mode the bootrom is loaded and executed from the last 1MB of
DRAM.

Based on "[PATCH 12/12] KVM/MIPS: General KVM support and support for
SMP Guests" by Sanjay Lal <sanjayl@kymasys.com>.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Sanjay Lal <sanjayl@kymasys.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/mips/mips_malta.c |   73 ++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 53 insertions(+), 20 deletions(-)

diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index f4a7d47..8bc5392 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -51,6 +51,7 @@
 #include "sysemu/qtest.h"
 #include "qemu/error-report.h"
 #include "hw/empty_slot.h"
+#include "sysemu/kvm.h"
 
 //#define DEBUG_BOARD_INIT
 
@@ -603,29 +604,31 @@ static void network_init(PCIBus *pci_bus)
 */
 
 static void write_bootloader (CPUMIPSState *env, uint8_t *base,
-                              int64_t kernel_entry)
+                              int64_t run_addr, int64_t kernel_entry)
 {
     uint32_t *p;
 
     /* Small bootloader */
     p = (uint32_t *)base;
-    stl_p(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
+
+    stl_p(p++, 0x08000000 |                                      /* j 0x1fc00580 */
+                 ((run_addr + 0x580) & 0x0fffffff) >> 2);
     stl_p(p++, 0x00000000);                                      /* nop */
 
     /* YAMON service vector */
-    stl_p(base + 0x500, 0xbfc00580);      /* start: */
-    stl_p(base + 0x504, 0xbfc0083c);      /* print_count: */
-    stl_p(base + 0x520, 0xbfc00580);      /* start: */
-    stl_p(base + 0x52c, 0xbfc00800);      /* flush_cache: */
-    stl_p(base + 0x534, 0xbfc00808);      /* print: */
-    stl_p(base + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
-    stl_p(base + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
-    stl_p(base + 0x540, 0xbfc00800);      /* reg_ic_isr: */
-    stl_p(base + 0x544, 0xbfc00800);      /* unred_ic_isr: */
-    stl_p(base + 0x548, 0xbfc00800);      /* reg_esr: */
-    stl_p(base + 0x54c, 0xbfc00800);      /* unreg_esr: */
-    stl_p(base + 0x550, 0xbfc00800);      /* getchar: */
-    stl_p(base + 0x554, 0xbfc00800);      /* syscon_read: */
+    stl_p(base + 0x500, run_addr + 0x0580);      /* start: */
+    stl_p(base + 0x504, run_addr + 0x083c);      /* print_count: */
+    stl_p(base + 0x520, run_addr + 0x0580);      /* start: */
+    stl_p(base + 0x52c, run_addr + 0x0800);      /* flush_cache: */
+    stl_p(base + 0x534, run_addr + 0x0808);      /* print: */
+    stl_p(base + 0x538, run_addr + 0x0800);      /* reg_cpu_isr: */
+    stl_p(base + 0x53c, run_addr + 0x0800);      /* unred_cpu_isr: */
+    stl_p(base + 0x540, run_addr + 0x0800);      /* reg_ic_isr: */
+    stl_p(base + 0x544, run_addr + 0x0800);      /* unred_ic_isr: */
+    stl_p(base + 0x548, run_addr + 0x0800);      /* reg_esr: */
+    stl_p(base + 0x54c, run_addr + 0x0800);      /* unreg_esr: */
+    stl_p(base + 0x550, run_addr + 0x0800);      /* getchar: */
+    stl_p(base + 0x554, run_addr + 0x0800);      /* syscon_read: */
 
 
     /* Second part of the bootloader */
@@ -701,7 +704,7 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base,
     p = (uint32_t *) (base + 0x800);
     stl_p(p++, 0x03e00008);                                     /* jr ra */
     stl_p(p++, 0x24020000);                                     /* li v0,0 */
-   /* 808 YAMON print */
+    /* 808 YAMON print */
     stl_p(p++, 0x03e06821);                                     /* move t5,ra */
     stl_p(p++, 0x00805821);                                     /* move t3,a0 */
     stl_p(p++, 0x00a05021);                                     /* move t2,a1 */
@@ -774,6 +777,7 @@ static int64_t load_kernel (void)
     uint32_t *prom_buf;
     long prom_size;
     int prom_index = 0;
+    uint64_t (*xlate_to_kseg0) (void *opaque, uint64_t addr);
 
 #ifdef TARGET_WORDS_BIGENDIAN
     big_endian = 1;
@@ -788,6 +792,11 @@ static int64_t load_kernel (void)
                 loaderparams.kernel_filename);
         exit(1);
     }
+    if (kvm_enabled()) {
+        xlate_to_kseg0 = cpu_mips_kvm_um_phys_to_kseg0;
+    } else {
+        xlate_to_kseg0 = cpu_mips_phys_to_kseg0;
+    }
 
     /* load initrd */
     initrd_size = 0;
@@ -820,7 +829,7 @@ static int64_t load_kernel (void)
     prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_filename);
     if (initrd_size > 0) {
         prom_set(prom_buf, prom_index++, "rd_start=0x%" PRIx64 " rd_size=%li %s",
-                 cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size,
+                 xlate_to_kseg0(NULL, initrd_offset), initrd_size,
                  loaderparams.kernel_cmdline);
     } else {
         prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_cmdline);
@@ -829,6 +838,7 @@ static int64_t load_kernel (void)
     prom_set(prom_buf, prom_index++, "memsize");
     prom_set(prom_buf, prom_index++, "%i",
              MIN(loaderparams.ram_size, 256 << 20));
+
     prom_set(prom_buf, prom_index++, "modetty0");
     prom_set(prom_buf, prom_index++, "38400n8r");
     prom_set(prom_buf, prom_index++, NULL);
@@ -863,6 +873,11 @@ static void main_cpu_reset(void *opaque)
     }
 
     malta_mips_config(cpu);
+
+    if (kvm_enabled()) {
+        /* Start running from the bootloader we wrote to end of RAM */
+        env->active_tc.PC = 0x40000000 + loaderparams.ram_size;
+    }
 }
 
 static void cpu_request_exit(void *opaque, int irq, int level)
@@ -878,6 +893,7 @@ static
 void mips_malta_init(MachineState *machine)
 {
     ram_addr_t ram_size = machine->ram_size;
+    ram_addr_t ram_low_size;
     const char *cpu_model = machine->cpu_model;
     const char *kernel_filename = machine->kernel_filename;
     const char *kernel_cmdline = machine->kernel_cmdline;
@@ -892,7 +908,7 @@ void mips_malta_init(MachineState *machine)
     target_long bios_size = FLASH_SIZE;
     const size_t smbus_eeprom_size = 8 * 256;
     uint8_t *smbus_eeprom_buf = g_malloc0(smbus_eeprom_size);
-    int64_t kernel_entry;
+    int64_t kernel_entry, bootloader_run_addr;
     PCIBus *pci_bus;
     ISABus *isa_bus;
     MIPSCPU *cpu;
@@ -1011,13 +1027,30 @@ void mips_malta_init(MachineState *machine)
     bios = pflash_cfi01_get_memory(fl);
     fl_idx++;
     if (kernel_filename) {
+        ram_low_size = MIN(ram_size, 256 << 20);
+        /* For KVM T&E we reserve 1MB of RAM for running bootloader */
+        if (kvm_enabled()) {
+            ram_low_size -= 0x100000;
+            bootloader_run_addr = 0x40000000 + ram_low_size;
+        } else {
+            bootloader_run_addr = 0xbfc00000;
+        }
+
         /* Write a small bootloader to the flash location. */
-        loaderparams.ram_size = MIN(ram_size, 256 << 20);
+        loaderparams.ram_size = ram_low_size;
         loaderparams.kernel_filename = kernel_filename;
         loaderparams.kernel_cmdline = kernel_cmdline;
         loaderparams.initrd_filename = initrd_filename;
         kernel_entry = load_kernel();
-        write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
+
+        write_bootloader(env, memory_region_get_ram_ptr(bios),
+                         bootloader_run_addr, kernel_entry);
+        if (kvm_enabled()) {
+            /* Write the bootloader code @ the end of RAM, 1MB reserved */
+            write_bootloader(env, memory_region_get_ram_ptr(ram_low_preio) +
+                                    ram_low_size,
+                             bootloader_run_addr, kernel_entry);
+        }
     } else {
         /* Load firmware from flash. */
         if (!dinfo) {
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PULL 12/14] target-mips: Enable KVM support in build system
  2014-06-20 12:11 [Qemu-devel] [PULL 00/14] Pending KVM patches for 2.1 Paolo Bonzini
                   ` (10 preceding siblings ...)
  2014-06-20 12:11 ` [Qemu-devel] [PULL 11/14] hw/mips: malta: Add KVM support Paolo Bonzini
@ 2014-06-20 12:11 ` Paolo Bonzini
  2014-06-20 12:11 ` [Qemu-devel] [PULL 13/14] MAINTAINERS: Add entry for MIPS KVM Paolo Bonzini
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2014-06-20 12:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: Sanjay Lal, James Hogan

From: Sanjay Lal <sanjayl@kymasys.com>

Enable KVM support for MIPS in the build system.

Signed-off-by: Sanjay Lal <sanjayl@kymasys.com>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 configure                 |    6 +++++-
 target-mips/Makefile.objs |    1 +
 2 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/configure b/configure
index 27d84d9..a32e651 100755
--- a/configure
+++ b/configure
@@ -4830,6 +4830,9 @@ if test "$linux" = "yes" ; then
   aarch64)
     linux_arch=arm64
     ;;
+  mips64)
+    linux_arch=mips
+    ;;
   *)
     # For most CPUs the kernel architecture name and QEMU CPU name match.
     linux_arch="$cpu"
@@ -5028,7 +5031,7 @@ case "$target_name" in
   *)
 esac
 case "$target_name" in
-  aarch64|arm|i386|x86_64|ppcemb|ppc|ppc64|s390x)
+  aarch64|arm|i386|x86_64|ppcemb|ppc|ppc64|s390x|mipsel|mips)
     # Make sure the target and host cpus are compatible
     if test "$kvm" = "yes" -a "$target_softmmu" = "yes" -a \
       \( "$target_name" = "$cpu" -o \
@@ -5036,6 +5039,7 @@ case "$target_name" in
       \( "$target_name" = "ppc64"  -a "$cpu" = "ppc" \) -o \
       \( "$target_name" = "ppc"    -a "$cpu" = "ppc64" \) -o \
       \( "$target_name" = "ppcemb" -a "$cpu" = "ppc64" \) -o \
+      \( "$target_name" = "mipsel" -a "$cpu" = "mips" \) -o \
       \( "$target_name" = "x86_64" -a "$cpu" = "i386"   \) -o \
       \( "$target_name" = "i386"   -a "$cpu" = "x86_64" \) \) ; then
       echo "CONFIG_KVM=y" >> $config_target_mak
diff --git a/target-mips/Makefile.objs b/target-mips/Makefile.objs
index 0277d56..716244f 100644
--- a/target-mips/Makefile.objs
+++ b/target-mips/Makefile.objs
@@ -1,3 +1,4 @@
 obj-y += translate.o dsp_helper.o op_helper.o lmi_helper.o helper.o cpu.o
 obj-y += gdbstub.o
 obj-$(CONFIG_SOFTMMU) += machine.o
+obj-$(CONFIG_KVM) += kvm.o
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PULL 13/14] MAINTAINERS: Add entry for MIPS KVM
  2014-06-20 12:11 [Qemu-devel] [PULL 00/14] Pending KVM patches for 2.1 Paolo Bonzini
                   ` (11 preceding siblings ...)
  2014-06-20 12:11 ` [Qemu-devel] [PULL 12/14] target-mips: Enable KVM support in build system Paolo Bonzini
@ 2014-06-20 12:11 ` Paolo Bonzini
  2014-06-20 12:11 ` [Qemu-devel] [PULL 14/14] hw/mips: malta: Don't boot from flash with KVM T&E Paolo Bonzini
  2014-06-20 19:01 ` [Qemu-devel] [PULL 00/14] Pending KVM patches for 2.1 Peter Maydell
  14 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2014-06-20 12:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: James Hogan

From: James Hogan <james.hogan@imgtec.com>

Add MAINTAINERS entry for MIPS KVM.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 MAINTAINERS |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 51a6f51..0a637c9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -176,6 +176,11 @@ M: Peter Maydell <peter.maydell@linaro.org>
 S: Maintained
 F: target-arm/kvm.c
 
+MIPS
+M: James Hogan <james.hogan@imgtec.com>
+S: Maintained
+F: target-mips/kvm.c
+
 PPC
 M: Alexander Graf <agraf@suse.de>
 S: Maintained
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PULL 14/14] hw/mips: malta: Don't boot from flash with KVM T&E
  2014-06-20 12:11 [Qemu-devel] [PULL 00/14] Pending KVM patches for 2.1 Paolo Bonzini
                   ` (12 preceding siblings ...)
  2014-06-20 12:11 ` [Qemu-devel] [PULL 13/14] MAINTAINERS: Add entry for MIPS KVM Paolo Bonzini
@ 2014-06-20 12:11 ` Paolo Bonzini
  2014-06-20 19:01 ` [Qemu-devel] [PULL 00/14] Pending KVM patches for 2.1 Peter Maydell
  14 siblings, 0 replies; 16+ messages in thread
From: Paolo Bonzini @ 2014-06-20 12:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: James Hogan

From: James Hogan <james.hogan@imgtec.com>

In KVM trap & emulate (T&E) mode the flash reset region at 0xbfc00000
isn't executable, which is why the minimal kernel bootloader is loaded
and executed from the last 1MB of DRAM instead.

Therefore if no kernel is provided on the command line and KVM is
enabled, exit with an error since booting from flash will fail.

Reported-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/mips/mips_malta.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index 8bc5392..91b0ce5 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -1052,6 +1052,12 @@ void mips_malta_init(MachineState *machine)
                              bootloader_run_addr, kernel_entry);
         }
     } else {
+        /* The flash region isn't executable from a KVM T&E guest */
+        if (kvm_enabled()) {
+            error_report("KVM enabled but no -kernel argument was specified. "
+                         "Booting from flash is not supported with KVM T&E.");
+            exit(1);
+        }
         /* Load firmware from flash. */
         if (!dinfo) {
             /* Load a BIOS image. */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PULL 00/14] Pending KVM patches for 2.1
  2014-06-20 12:11 [Qemu-devel] [PULL 00/14] Pending KVM patches for 2.1 Paolo Bonzini
                   ` (13 preceding siblings ...)
  2014-06-20 12:11 ` [Qemu-devel] [PULL 14/14] hw/mips: malta: Don't boot from flash with KVM T&E Paolo Bonzini
@ 2014-06-20 19:01 ` Peter Maydell
  14 siblings, 0 replies; 16+ messages in thread
From: Peter Maydell @ 2014-06-20 19:01 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: QEMU Developers

On 20 June 2014 13:11, Paolo Bonzini <pbonzini@redhat.com> wrote:
> The following changes since commit af44da87e926ff64260b95f4350d338c4fc113ca:
>
>   Merge remote-tracking branch 'remotes/agraf/tags/signed-ppc-for-upstream' into staging (2014-06-16 18:26:21 +0100)
>
> are available in the git repository at:
>
>
>   git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.git uq/master
>
> for you to fetch changes up to 3c5d0be553b18d47361ac3a701e2bff86b8256b0:
>
>   hw/mips: malta: Don't boot from flash with KVM T&E (2014-06-20 13:51:29 +0200)
>
> The highlight (covering 13/14th of the series) is MIPS Malta support
> for trap-and-emulate KVM.  The QEMU<->kernel interface to implement
> the equivalent of QEMU_CLOCK_VIRTUAL, that James came up with, is
> particularly cool and a good model for other architectures to look at.

Applied, thanks.

-- PMM

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2014-06-20 19:02 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-06-20 12:11 [Qemu-devel] [PULL 00/14] Pending KVM patches for 2.1 Paolo Bonzini
2014-06-20 12:11 ` [Qemu-devel] [PULL 01/14] KVM: Fix GSI number space limit Paolo Bonzini
2014-06-20 12:11 ` [Qemu-devel] [PULL 02/14] target-mips: Reset CPU timer consistently Paolo Bonzini
2014-06-20 12:11 ` [Qemu-devel] [PULL 03/14] hw/mips/cputimer: Don't start periodic timer in KVM mode Paolo Bonzini
2014-06-20 12:11 ` [Qemu-devel] [PULL 04/14] hw/mips: Add API to convert KVM guest KSEG0 <-> GPA Paolo Bonzini
2014-06-20 12:11 ` [Qemu-devel] [PULL 05/14] target-mips: get_physical_address: Add defines for segment bases Paolo Bonzini
2014-06-20 12:11 ` [Qemu-devel] [PULL 06/14] target-mips: get_physical_address: Add KVM awareness Paolo Bonzini
2014-06-20 12:11 ` [Qemu-devel] [PULL 07/14] kvm: Allow arch to set sigmask length Paolo Bonzini
2014-06-20 12:11 ` [Qemu-devel] [PULL 08/14] target-mips: kvm: Add main KVM support for MIPS Paolo Bonzini
2014-06-20 12:11 ` [Qemu-devel] [PULL 09/14] target-mips: Call kvm_mips_reset_vcpu() from mips_cpu_reset() Paolo Bonzini
2014-06-20 12:11 ` [Qemu-devel] [PULL 10/14] hw/mips: In KVM mode, inject IRQ2 (I/O) interrupts via ioctls Paolo Bonzini
2014-06-20 12:11 ` [Qemu-devel] [PULL 11/14] hw/mips: malta: Add KVM support Paolo Bonzini
2014-06-20 12:11 ` [Qemu-devel] [PULL 12/14] target-mips: Enable KVM support in build system Paolo Bonzini
2014-06-20 12:11 ` [Qemu-devel] [PULL 13/14] MAINTAINERS: Add entry for MIPS KVM Paolo Bonzini
2014-06-20 12:11 ` [Qemu-devel] [PULL 14/14] hw/mips: malta: Don't boot from flash with KVM T&E Paolo Bonzini
2014-06-20 19:01 ` [Qemu-devel] [PULL 00/14] Pending KVM patches for 2.1 Peter Maydell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).