All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/10] KVM Support for MIPS32 Processors
@ 2013-12-16 14:12 ` James Hogan
  0 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-16 14:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, Aurelien Jarno, Gleb Natapov, Paolo Bonzini, Sanjay Lal,
	James Hogan

This patchset implements KVM support for MIPS32 processors, using Trap &
Emulation.

In KVM mode, CPU virtualization is handled via the kvm kernel module,
while system and I/O virtualization leverage the Malta model already
present in QEMU.

Both Guest kernel and Guest Userspace execute in UM. The Guest address
space is as folows:
Guest User address space:   0x00000000 -> 0x40000000
Guest Kernel Unmapped:      0x40000000 -> 0x60000000
Guest Kernel Mapped:        0x60000000 -> 0x80000000

As a result, Guest Usermode virtual memory is limited to 1GB.

KVM support (by trap and emulate) was added to the Linux kernel in
v3.10.

This patchset is based on Sanjay Lal's V1 patchset from 2nd March 2013:
https://patchwork.kernel.org/project/kvm/list/?submitter=51991&state=*&q=qemu-devel

I think I've addressed all the V1 feedback. The other main change is the
removal of the boot-CPS ROM code binary blob and GIC/SMP support since
it's all slightly orthogonal to KVM support. Instead the existing
minimal bootloader code for Malta has been updated to work with KVM T&E.

A git tag for this version of the patchset can also be found on github:
https://github.com/jahogan/qemu-kvm-mips.git kvm-mips-v2

Changes in v2:
 - Expand commit messages
 - Rebase on v1.7.0
 - Misc checkpatch and other cleanups
 - Some interrupt bug fixes from Yann Le Du <ledu@kymasys.com>
 - Add get/set register functionality from Yann Le Du <ledu@kymasys.com>
 - Use new 64 bit compatible ABI from Cavium from Sanjay Lal
   <sanjayl@kymasys.com>
 - Add dummy kvm_arch_init_irq_routing()
   The common KVM code insists on calling kvm_arch_init_irq_routing() as
   soon as it sees kernel header support for it (regardless of whether
   QEMU supports it). Provide a dummy function to satisfy this.
 - Remove request_interrupt_window code (Peter Maydell)
 - Remove #ifdef CONFIG_KVM where guarded by kvm_enabled() already
 - Removal of cps / GIC / SMP support
 - Minimal bootloader modified to execute safely from RAM
 - Create asm-mips symlink using generic code and move above default
   case (Peter Maydell)
 - Remove redundant check of target_name = cpu = mips
 - Remove mipsel cross compilation fix, which is now fixed by commit
   61cc919f73ea (configure: detect endian via compile test)
 - Add translation of guest kernel segments to allow an attached gdb to
   see kernel memory correctly

James Hogan (3):
  target-mips: get_physical_address: Add defines for segment bases
  target-mips: get_physical_address: Add KVM awareness
  hw/mips: malta: Add KVM support

Sanjay Lal (7):
  hw/mips/cputimer: Don't start periodic timer in KVM mode
  hw/mips: Add API to convert KVM guest KSEG0 <-> GPA
  kvm: Set sigmask length to 16 for MIPS targets
  target-mips: Set target page size to 16K in KVM mode
  target-mips: kvm: Add main KVM support for MIPS
  hw/mips: In KVM mode, inject IRQ2 (I/O) interupts via ioctls
  target-mips: Enable KVM support in build system

 configure                 |   6 +-
 hw/mips/addr.c            |  10 +
 hw/mips/cputimer.c        |  13 +-
 hw/mips/mips_int.c        |  11 ++
 hw/mips/mips_malta.c      |  85 ++++++---
 include/hw/mips/cpudevs.h |   4 +
 kvm-all.c                 |   5 +
 target-mips/Makefile.objs |   1 +
 target-mips/helper.c      |  51 +++--
 target-mips/kvm.c         | 463 ++++++++++++++++++++++++++++++++++++++++++++++
 target-mips/kvm_mips.h    |  28 +++
 target-mips/mips-defs.h   |   5 +
 12 files changed, 643 insertions(+), 39 deletions(-)
 create mode 100644 target-mips/kvm.c
 create mode 100644 target-mips/kvm_mips.h

-- 
1.8.1.2



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

* [Qemu-devel] [PATCH v2 00/10] KVM Support for MIPS32 Processors
@ 2013-12-16 14:12 ` James Hogan
  0 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-16 14:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: James Hogan, kvm, Gleb Natapov, Sanjay Lal, Paolo Bonzini,
	Aurelien Jarno

This patchset implements KVM support for MIPS32 processors, using Trap &
Emulation.

In KVM mode, CPU virtualization is handled via the kvm kernel module,
while system and I/O virtualization leverage the Malta model already
present in QEMU.

Both Guest kernel and Guest Userspace execute in UM. The Guest address
space is as folows:
Guest User address space:   0x00000000 -> 0x40000000
Guest Kernel Unmapped:      0x40000000 -> 0x60000000
Guest Kernel Mapped:        0x60000000 -> 0x80000000

As a result, Guest Usermode virtual memory is limited to 1GB.

KVM support (by trap and emulate) was added to the Linux kernel in
v3.10.

This patchset is based on Sanjay Lal's V1 patchset from 2nd March 2013:
https://patchwork.kernel.org/project/kvm/list/?submitter=51991&state=*&q=qemu-devel

I think I've addressed all the V1 feedback. The other main change is the
removal of the boot-CPS ROM code binary blob and GIC/SMP support since
it's all slightly orthogonal to KVM support. Instead the existing
minimal bootloader code for Malta has been updated to work with KVM T&E.

A git tag for this version of the patchset can also be found on github:
https://github.com/jahogan/qemu-kvm-mips.git kvm-mips-v2

Changes in v2:
 - Expand commit messages
 - Rebase on v1.7.0
 - Misc checkpatch and other cleanups
 - Some interrupt bug fixes from Yann Le Du <ledu@kymasys.com>
 - Add get/set register functionality from Yann Le Du <ledu@kymasys.com>
 - Use new 64 bit compatible ABI from Cavium from Sanjay Lal
   <sanjayl@kymasys.com>
 - Add dummy kvm_arch_init_irq_routing()
   The common KVM code insists on calling kvm_arch_init_irq_routing() as
   soon as it sees kernel header support for it (regardless of whether
   QEMU supports it). Provide a dummy function to satisfy this.
 - Remove request_interrupt_window code (Peter Maydell)
 - Remove #ifdef CONFIG_KVM where guarded by kvm_enabled() already
 - Removal of cps / GIC / SMP support
 - Minimal bootloader modified to execute safely from RAM
 - Create asm-mips symlink using generic code and move above default
   case (Peter Maydell)
 - Remove redundant check of target_name = cpu = mips
 - Remove mipsel cross compilation fix, which is now fixed by commit
   61cc919f73ea (configure: detect endian via compile test)
 - Add translation of guest kernel segments to allow an attached gdb to
   see kernel memory correctly

James Hogan (3):
  target-mips: get_physical_address: Add defines for segment bases
  target-mips: get_physical_address: Add KVM awareness
  hw/mips: malta: Add KVM support

Sanjay Lal (7):
  hw/mips/cputimer: Don't start periodic timer in KVM mode
  hw/mips: Add API to convert KVM guest KSEG0 <-> GPA
  kvm: Set sigmask length to 16 for MIPS targets
  target-mips: Set target page size to 16K in KVM mode
  target-mips: kvm: Add main KVM support for MIPS
  hw/mips: In KVM mode, inject IRQ2 (I/O) interupts via ioctls
  target-mips: Enable KVM support in build system

 configure                 |   6 +-
 hw/mips/addr.c            |  10 +
 hw/mips/cputimer.c        |  13 +-
 hw/mips/mips_int.c        |  11 ++
 hw/mips/mips_malta.c      |  85 ++++++---
 include/hw/mips/cpudevs.h |   4 +
 kvm-all.c                 |   5 +
 target-mips/Makefile.objs |   1 +
 target-mips/helper.c      |  51 +++--
 target-mips/kvm.c         | 463 ++++++++++++++++++++++++++++++++++++++++++++++
 target-mips/kvm_mips.h    |  28 +++
 target-mips/mips-defs.h   |   5 +
 12 files changed, 643 insertions(+), 39 deletions(-)
 create mode 100644 target-mips/kvm.c
 create mode 100644 target-mips/kvm_mips.h

-- 
1.8.1.2

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

* [PATCH v2 01/10] hw/mips/cputimer: Don't start periodic timer in KVM mode
  2013-12-16 14:12 ` [Qemu-devel] " James Hogan
@ 2013-12-16 14:12   ` James Hogan
  -1 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-16 14:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, Aurelien Jarno, Gleb Natapov, Paolo Bonzini, Sanjay Lal,
	James Hogan

From: Sanjay Lal <sanjayl@kymasys.com>

Compare/Count timer interrupts are handled in-kernel for KVM, so don't
bother starting it in QEMU.

Signed-off-by: Sanjay Lal <sanjayl@kymasys.com>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
---
Changes in v2:
 - Expand commit message
 - Rebase on v1.7.0
 - Wrap comment
---
 hw/mips/cputimer.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/hw/mips/cputimer.c b/hw/mips/cputimer.c
index c8b4b00..52570fd 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
 
@@ -141,7 +142,13 @@ 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);
+    /*
+     * If we're in KVM mode, don't start the periodic timer, that is handled in
+     * kernel.
+     */
+    if (!kvm_enabled()) {
+        env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb, env);
+        env->CP0_Compare = 0;
+        cpu_mips_store_count(env, 1);
+    }
 }
-- 
1.8.1.2



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

* [Qemu-devel] [PATCH v2 01/10] hw/mips/cputimer: Don't start periodic timer in KVM mode
@ 2013-12-16 14:12   ` James Hogan
  0 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-16 14:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: James Hogan, kvm, Gleb Natapov, Sanjay Lal, Paolo Bonzini,
	Aurelien Jarno

From: Sanjay Lal <sanjayl@kymasys.com>

Compare/Count timer interrupts are handled in-kernel for KVM, so don't
bother starting it in QEMU.

Signed-off-by: Sanjay Lal <sanjayl@kymasys.com>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
---
Changes in v2:
 - Expand commit message
 - Rebase on v1.7.0
 - Wrap comment
---
 hw/mips/cputimer.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/hw/mips/cputimer.c b/hw/mips/cputimer.c
index c8b4b00..52570fd 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
 
@@ -141,7 +142,13 @@ 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);
+    /*
+     * If we're in KVM mode, don't start the periodic timer, that is handled in
+     * kernel.
+     */
+    if (!kvm_enabled()) {
+        env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb, env);
+        env->CP0_Compare = 0;
+        cpu_mips_store_count(env, 1);
+    }
 }
-- 
1.8.1.2

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

* [PATCH v2 02/10] hw/mips: Add API to convert KVM guest KSEG0 <-> GPA
  2013-12-16 14:12 ` [Qemu-devel] " James Hogan
@ 2013-12-16 14:12   ` James Hogan
  -1 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-16 14:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, Aurelien Jarno, Gleb Natapov, Paolo Bonzini, Sanjay Lal,
	James Hogan

From: Sanjay Lal <sanjayl@kymasys.com>

Add APIs for converting between KVM guest KSEG0 addresses and guest
physical addresses. These will be used for translating addresses when
loading a kernel ELF in KVM mode.

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>
---
Changes in v2:
 - Expand commit message
 - Remove unnecessary include
---
 hw/mips/addr.c            | 10 ++++++++++
 include/hw/mips/cpudevs.h |  4 ++++
 2 files changed, 14 insertions(+)

diff --git a/hw/mips/addr.c b/hw/mips/addr.c
index 99488f1..e62d6f4 100644
--- a/hw/mips/addr.c
+++ b/hw/mips/addr.c
@@ -28,7 +28,17 @@ uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr)
     return addr & 0x7fffffffll;
 }
 
+uint64_t cpu_mips_kvm_um_kseg0_to_phys(void *opaque, uint64_t addr)
+{
+    return addr & 0x3fffffffll;
+}
+
 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..9e5af37 100644
--- a/include/hw/mips/cpudevs.h
+++ b/include/hw/mips/cpudevs.h
@@ -6,6 +6,10 @@
 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_kseg0_to_phys(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.8.1.2



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

* [Qemu-devel] [PATCH v2 02/10] hw/mips: Add API to convert KVM guest KSEG0 <-> GPA
@ 2013-12-16 14:12   ` James Hogan
  0 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-16 14:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: James Hogan, kvm, Gleb Natapov, Sanjay Lal, Paolo Bonzini,
	Aurelien Jarno

From: Sanjay Lal <sanjayl@kymasys.com>

Add APIs for converting between KVM guest KSEG0 addresses and guest
physical addresses. These will be used for translating addresses when
loading a kernel ELF in KVM mode.

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>
---
Changes in v2:
 - Expand commit message
 - Remove unnecessary include
---
 hw/mips/addr.c            | 10 ++++++++++
 include/hw/mips/cpudevs.h |  4 ++++
 2 files changed, 14 insertions(+)

diff --git a/hw/mips/addr.c b/hw/mips/addr.c
index 99488f1..e62d6f4 100644
--- a/hw/mips/addr.c
+++ b/hw/mips/addr.c
@@ -28,7 +28,17 @@ uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr)
     return addr & 0x7fffffffll;
 }
 
+uint64_t cpu_mips_kvm_um_kseg0_to_phys(void *opaque, uint64_t addr)
+{
+    return addr & 0x3fffffffll;
+}
+
 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..9e5af37 100644
--- a/include/hw/mips/cpudevs.h
+++ b/include/hw/mips/cpudevs.h
@@ -6,6 +6,10 @@
 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_kseg0_to_phys(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.8.1.2

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

* [PATCH v2 03/10] target-mips: get_physical_address: Add defines for segment bases
  2013-12-16 14:12 ` [Qemu-devel] " James Hogan
@ 2013-12-16 14:12   ` James Hogan
  -1 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-16 14:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, Aurelien Jarno, Gleb Natapov, Paolo Bonzini, Sanjay Lal,
	James Hogan

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>
Cc: Aurelien Jarno <aurelien@aurel32.net>
---
 target-mips/helper.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/target-mips/helper.c b/target-mips/helper.c
index 33e0e88..2e96655 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.8.1.2



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

* [Qemu-devel] [PATCH v2 03/10] target-mips: get_physical_address: Add defines for segment bases
@ 2013-12-16 14:12   ` James Hogan
  0 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-16 14:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: James Hogan, kvm, Gleb Natapov, Sanjay Lal, Paolo Bonzini,
	Aurelien Jarno

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>
Cc: Aurelien Jarno <aurelien@aurel32.net>
---
 target-mips/helper.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/target-mips/helper.c b/target-mips/helper.c
index 33e0e88..2e96655 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.8.1.2

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

* [PATCH v2 04/10] target-mips: get_physical_address: Add KVM awareness
  2013-12-16 14:12 ` [Qemu-devel] " James Hogan
@ 2013-12-16 14:12   ` James Hogan
  -1 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-16 14:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, Aurelien Jarno, Gleb Natapov, Paolo Bonzini, Sanjay Lal,
	James Hogan

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>
---
 target-mips/helper.c | 33 ++++++++++++++++++++++++++-------
 1 file changed, 26 insertions(+), 7 deletions(-)

diff --git a/target-mips/helper.c b/target-mips/helper.c
index 2e96655..c4be887 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.8.1.2



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

* [Qemu-devel] [PATCH v2 04/10] target-mips: get_physical_address: Add KVM awareness
@ 2013-12-16 14:12   ` James Hogan
  0 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-16 14:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: James Hogan, kvm, Gleb Natapov, Sanjay Lal, Paolo Bonzini,
	Aurelien Jarno

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>
---
 target-mips/helper.c | 33 ++++++++++++++++++++++++++-------
 1 file changed, 26 insertions(+), 7 deletions(-)

diff --git a/target-mips/helper.c b/target-mips/helper.c
index 2e96655..c4be887 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.8.1.2

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

* [PATCH v2 05/10] kvm: Set sigmask length to 16 for MIPS targets
  2013-12-16 14:12 ` [Qemu-devel] " James Hogan
@ 2013-12-16 14:12   ` James Hogan
  -1 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-16 14:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, Aurelien Jarno, Gleb Natapov, Paolo Bonzini, Sanjay Lal,
	James Hogan

From: Sanjay Lal <sanjayl@kymasys.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 correct kvm_set_signal_mask to pass the correct sigmask->len to
KVM_SET_SIGNAL_MASK.

Signed-off-by: Sanjay Lal <sanjayl@kymasys.com>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Gleb Natapov <gleb@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
---
Changes in v2:
 - Expand commit message
 - Reword comment
---
 kvm-all.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/kvm-all.c b/kvm-all.c
index 4478969..c831326 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -2044,7 +2044,12 @@ int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset)
 
     sigmask = g_malloc(sizeof(*sigmask) + sizeof(*sigset));
 
+#ifdef TARGET_MIPS
+    /* MIPS has 128 signals */
+    sigmask->len = 16;
+#else
     sigmask->len = 8;
+#endif
     memcpy(sigmask->sigset, sigset, sizeof(*sigset));
     r = kvm_vcpu_ioctl(cpu, KVM_SET_SIGNAL_MASK, sigmask);
     g_free(sigmask);
-- 
1.8.1.2



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

* [Qemu-devel] [PATCH v2 05/10] kvm: Set sigmask length to 16 for MIPS targets
@ 2013-12-16 14:12   ` James Hogan
  0 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-16 14:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: James Hogan, kvm, Gleb Natapov, Sanjay Lal, Paolo Bonzini,
	Aurelien Jarno

From: Sanjay Lal <sanjayl@kymasys.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 correct kvm_set_signal_mask to pass the correct sigmask->len to
KVM_SET_SIGNAL_MASK.

Signed-off-by: Sanjay Lal <sanjayl@kymasys.com>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Gleb Natapov <gleb@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
---
Changes in v2:
 - Expand commit message
 - Reword comment
---
 kvm-all.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/kvm-all.c b/kvm-all.c
index 4478969..c831326 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -2044,7 +2044,12 @@ int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset)
 
     sigmask = g_malloc(sizeof(*sigmask) + sizeof(*sigset));
 
+#ifdef TARGET_MIPS
+    /* MIPS has 128 signals */
+    sigmask->len = 16;
+#else
     sigmask->len = 8;
+#endif
     memcpy(sigmask->sigset, sigset, sizeof(*sigset));
     r = kvm_vcpu_ioctl(cpu, KVM_SET_SIGNAL_MASK, sigmask);
     g_free(sigmask);
-- 
1.8.1.2

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

* [PATCH v2 06/10] target-mips: Set target page size to 16K in KVM mode
  2013-12-16 14:12 ` [Qemu-devel] " James Hogan
@ 2013-12-16 14:12   ` James Hogan
  -1 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-16 14:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, Aurelien Jarno, Gleb Natapov, Paolo Bonzini, Sanjay Lal,
	James Hogan

From: Sanjay Lal <sanjayl@kymasys.com>

With larger set associative caches KVM can open the possibility of cache
aliasing between the memory that QEMU allocates with mmap and the
mapping into the guest address space. Therefore increase the target page
size to 16K when KVM is configured.

Signed-off-by: Sanjay Lal <sanjayl@kymasys.com>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
---
Changes in v2:
 - Expand commit message
---
 target-mips/mips-defs.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h
index bf094a3..473ddf8 100644
--- a/target-mips/mips-defs.h
+++ b/target-mips/mips-defs.h
@@ -5,7 +5,12 @@
 //#define USE_HOST_FLOAT_REGS
 
 /* Real pages are variable size... */
+#ifdef CONFIG_KVM
+/* For KVM/MIPS the minimum page size is 16K due to cache aliasing issues */
+#define TARGET_PAGE_BITS 14
+#else
 #define TARGET_PAGE_BITS 12
+#endif
 #define MIPS_TLB_MAX 128
 
 #if defined(TARGET_MIPS64)
-- 
1.8.1.2



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

* [Qemu-devel] [PATCH v2 06/10] target-mips: Set target page size to 16K in KVM mode
@ 2013-12-16 14:12   ` James Hogan
  0 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-16 14:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: James Hogan, kvm, Gleb Natapov, Sanjay Lal, Paolo Bonzini,
	Aurelien Jarno

From: Sanjay Lal <sanjayl@kymasys.com>

With larger set associative caches KVM can open the possibility of cache
aliasing between the memory that QEMU allocates with mmap and the
mapping into the guest address space. Therefore increase the target page
size to 16K when KVM is configured.

Signed-off-by: Sanjay Lal <sanjayl@kymasys.com>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
---
Changes in v2:
 - Expand commit message
---
 target-mips/mips-defs.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h
index bf094a3..473ddf8 100644
--- a/target-mips/mips-defs.h
+++ b/target-mips/mips-defs.h
@@ -5,7 +5,12 @@
 //#define USE_HOST_FLOAT_REGS
 
 /* Real pages are variable size... */
+#ifdef CONFIG_KVM
+/* For KVM/MIPS the minimum page size is 16K due to cache aliasing issues */
+#define TARGET_PAGE_BITS 14
+#else
 #define TARGET_PAGE_BITS 12
+#endif
 #define MIPS_TLB_MAX 128
 
 #if defined(TARGET_MIPS64)
-- 
1.8.1.2

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

* [PATCH v2 07/10] target-mips: kvm: Add main KVM support for MIPS
  2013-12-16 14:12 ` [Qemu-devel] " James Hogan
@ 2013-12-16 14:12   ` James Hogan
  -1 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-16 14:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, Aurelien Jarno, Gleb Natapov, Paolo Bonzini, Sanjay Lal,
	James Hogan

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>
---
Changes in v2:
 - Expand commit message
 - Checkpatch cleanups.
 - Some interrupt bug fixes from Yann Le Du <ledu@kymasys.com>
 - Add get/set register functionality from Yann Le Du <ledu@kymasys.com>
 - Use new 64 bit compatible ABI from Cavium from Sanjay Lal
   <sanjayl@kymasys.com>
 - Add dummy kvm_arch_init_irq_routing()
   The common KVM code insists on calling kvm_arch_init_irq_routing() as
   soon as it sees kernel header support for it (regardless of whether
   QEMU supports it). Provide a dummy function to satisfy this.
 - Remove request_interrupt_window code (Peter Maydell)
---
 target-mips/kvm.c      | 463 +++++++++++++++++++++++++++++++++++++++++++++++++
 target-mips/kvm_mips.h |  28 +++
 2 files changed, 491 insertions(+)
 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..951959b
--- /dev/null
+++ b/target-mips/kvm.c
@@ -0,0 +1,463 @@
+/*
+ * 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-2013 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/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
+};
+
+unsigned long kvm_arch_vcpu_id(CPUState *cpu)
+{
+    return cpu->cpu_index;
+}
+
+int kvm_arch_init(KVMState *s)
+{
+    dprintf("%s\n", __func__);
+    return 0;
+}
+
+int kvm_arch_init_vcpu(CPUState *env)
+{
+    int ret = 0;
+    dprintf("%s\n", __func__);
+    return ret;
+}
+
+void kvm_arch_reset_vcpu(CPUState *env)
+{
+    dprintf("%s\n", __func__);
+}
+
+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_te_put_cp0_registers(cs, KVM_PUT_FULL_STATE);
+    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_te_get_cp0_registers(cs);
+
+    return ret;
+}
+
+int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
+{
+    dprintf("%s\n", __func__);
+    return 0;
+}
+
+int kvm_arch_remove_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
+{
+    dprintf("%s\n", __func__);
+    return 0;
+}
+
+static inline int cpu_mips_io_interrupts_pending(CPUArchState *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);
+    CPUMIPSState *env = &cpu->env;
+    int r;
+    struct kvm_mips_interrupt intr;
+
+    if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
+            (cpu_mips_io_interrupts_pending(env))) {
+        intr.cpu = -1;
+        intr.irq = 2;
+        r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
+        if (r < 0) {
+            printf("cpu %d fail inject %x\n", cs->cpu_index, intr.irq);
+        }
+    }
+}
+
+void kvm_arch_post_run(CPUState *env, 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 *env, struct kvm_run *run)
+{
+    int ret;
+
+    dprintf("%s\n", __func__);
+    switch (run->exit_reason) {
+    default:
+        fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
+        ret = -1;
+        break;
+    }
+
+    return ret;
+}
+
+bool kvm_arch_stop_on_emulation_error(CPUState *env)
+{
+    dprintf("%s\n", __func__);
+    return true;
+}
+
+int kvm_arch_on_sigbus_vcpu(CPUState *env, 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(CPUMIPSState *env, int irq, int level)
+{
+    CPUState *cs = ENV_GET_CPU(env);
+    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(CPUArchState *env, int irq, int level)
+{
+    CPUState *cs = current_cpu;
+    CPUState *dest_cs = ENV_GET_CPU(env);
+    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 KVM_REG_MIPS_CP0_INDEX     (0x10000 + (8 *  0) + 0)
+#define KVM_REG_MIPS_CP0_ENTRYLO0  (0x10000 + (8 *  2) + 0)
+#define KVM_REG_MIPS_CP0_ENTRYLO1  (0x10000 + (8 *  3) + 0)
+#define KVM_REG_MIPS_CP0_CONTEXT   (0x10000 + (8 *  4) + 0)
+#define KVM_REG_MIPS_CP0_USERLOCAL (0x10000 + (8 *  4) + 2)
+#define KVM_REG_MIPS_CP0_PAGEMASK  (0x10000 + (8 *  5) + 0)
+#define KVM_REG_MIPS_CP0_PAGEGRAIN (0x10000 + (8 *  5) + 1)
+#define KVM_REG_MIPS_CP0_WIRED     (0x10000 + (8 *  6) + 0)
+#define KVM_REG_MIPS_CP0_HWRENA    (0x10000 + (8 *  7) + 0)
+#define KVM_REG_MIPS_CP0_BADVADDR  (0x10000 + (8 *  8) + 0)
+#define KVM_REG_MIPS_CP0_COUNT     (0x10000 + (8 *  9) + 0)
+#define KVM_REG_MIPS_CP0_ENTRYHI   (0x10000 + (8 * 10) + 0)
+#define KVM_REG_MIPS_CP0_COMPARE   (0x10000 + (8 * 11) + 0)
+#define KVM_REG_MIPS_CP0_STATUS    (0x10000 + (8 * 12) + 0)
+#define KVM_REG_MIPS_CP0_INTCTL    (0x10000 + (8 * 12) + 1)
+#define KVM_REG_MIPS_CP0_CAUSE     (0x10000 + (8 * 13) + 0)
+#define KVM_REG_MIPS_CP0_EPC       (0x10000 + (8 * 14) + 0)
+#define KVM_REG_MIPS_CP0_PRID      (0x10000 + (8 * 15) + 0)
+#define KVM_REG_MIPS_CP0_EBASE     (0x10000 + (8 * 15) + 1)
+#define KVM_REG_MIPS_CP0_CONFIG    (0x10000 + (8 * 16) + 0)
+#define KVM_REG_MIPS_CP0_CONFIG1   (0x10000 + (8 * 16) + 1)
+#define KVM_REG_MIPS_CP0_CONFIG2   (0x10000 + (8 * 16) + 2)
+#define KVM_REG_MIPS_CP0_CONFIG3   (0x10000 + (8 * 16) + 3)
+#define KVM_REG_MIPS_CP0_CONFIG4   (0x10000 + (8 * 16) + 4)
+#define KVM_REG_MIPS_CP0_CONFIG5   (0x10000 + (8 * 16) + 5)
+#define KVM_REG_MIPS_CP0_CONFIG7   (0x10000 + (8 * 16) + 7)
+#define KVM_REG_MIPS_CP0_XCONTEXT  (0x10000 + (8 * 20) + 0)
+#define KVM_REG_MIPS_CP0_ERROREPC  (0x10000 + (8 * 30) + 0)
+
+inline int kvm_mips_put_one_reg(CPUState *cs, int reg_id, int32 *addr)
+{
+    __u64 val64 = (__u64)*addr;
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (__u64)((target_ulong)&val64)
+    };
+
+    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
+}
+
+inline int kvm_mips_put_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr)
+{
+    __u64 val64 = (__u64)*addr;
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (__u64)((target_ulong)&val64)
+    };
+
+    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
+}
+
+inline int kvm_mips_get_one_reg(CPUState *cs, int reg_id, int32 *addr)
+{
+    int ret;
+    __u64 val64 = 0;
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (__u64)((target_ulong)&val64)
+    };
+
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
+    if (ret < 0) {
+        return ret;
+    }
+
+    *addr = (int32)val64;
+    return ret;
+}
+
+inline int kvm_mips_get_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr)
+{
+    int ret;
+    __u64 val64 = 0;
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (__u64)((target_ulong)&val64)
+    };
+
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
+    if (ret < 0) {
+        return ret;
+    }
+
+    *addr = (target_ulong)val64;
+    return ret;
+}
+
+int kvm_mips_te_put_cp0_registers(CPUState *cs, int level)
+{
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    CPUMIPSState *env = &cpu->env;
+    int ret;
+
+    (void)level;
+
+    ret = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
+                                  &env->CP0_Context);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK,
+                                &env->CP0_PageMask);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR,
+                                  &env->CP0_BadVAddr);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI,
+                                  &env->CP0_EntryHi);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE,
+                                &env->CP0_Compare);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
+                                  &env->CP0_ErrorEPC);
+    if (ret < 0) {
+        return ret;
+    }
+
+    return ret;
+}
+
+int kvm_mips_te_get_cp0_registers(CPUState *cs)
+{
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    CPUMIPSState *env = &cpu->env;
+    int ret;
+
+    ret = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
+                                  &env->CP0_Context);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK,
+                                &env->CP0_PageMask);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR,
+                                  &env->CP0_BadVAddr);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI,
+                                  &env->CP0_EntryHi);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE,
+                                &env->CP0_Compare);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
+                                  &env->CP0_ErrorEPC);
+    if (ret < 0) {
+        return ret;
+    }
+
+    return ret;
+}
diff --git a/target-mips/kvm_mips.h b/target-mips/kvm_mips.h
new file mode 100644
index 0000000..0da4edf
--- /dev/null
+++ b/target-mips/kvm_mips.h
@@ -0,0 +1,28 @@
+/*
+ * 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-2013 Imagination Technologies Ltd.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+*/
+
+#ifndef __KVM_MIPS_H__
+#define __KVM_MIPS_H__
+
+
+int kvm_mips_set_interrupt(CPUMIPSState *env, int irq, int level);
+
+int kvm_mips_set_ipi_interrupt(CPUArchState *env, int irq, int level);
+
+inline int kvm_mips_put_one_reg(CPUState *cs, int reg_id, int32 *addr);
+inline int kvm_mips_put_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr);
+inline int kvm_mips_get_one_reg(CPUState *cs, int reg_id, int32 *addr);
+inline int kvm_mips_get_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr);
+
+int kvm_mips_te_put_cp0_registers(CPUState *cs, int level);
+int kvm_mips_te_get_cp0_registers(CPUState *cs);
+
+#endif /* __KVM_MIPS_H__ */
-- 
1.8.1.2



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

* [Qemu-devel] [PATCH v2 07/10] target-mips: kvm: Add main KVM support for MIPS
@ 2013-12-16 14:12   ` James Hogan
  0 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-16 14:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: James Hogan, kvm, Gleb Natapov, Sanjay Lal, Paolo Bonzini,
	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>
---
Changes in v2:
 - Expand commit message
 - Checkpatch cleanups.
 - Some interrupt bug fixes from Yann Le Du <ledu@kymasys.com>
 - Add get/set register functionality from Yann Le Du <ledu@kymasys.com>
 - Use new 64 bit compatible ABI from Cavium from Sanjay Lal
   <sanjayl@kymasys.com>
 - Add dummy kvm_arch_init_irq_routing()
   The common KVM code insists on calling kvm_arch_init_irq_routing() as
   soon as it sees kernel header support for it (regardless of whether
   QEMU supports it). Provide a dummy function to satisfy this.
 - Remove request_interrupt_window code (Peter Maydell)
---
 target-mips/kvm.c      | 463 +++++++++++++++++++++++++++++++++++++++++++++++++
 target-mips/kvm_mips.h |  28 +++
 2 files changed, 491 insertions(+)
 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..951959b
--- /dev/null
+++ b/target-mips/kvm.c
@@ -0,0 +1,463 @@
+/*
+ * 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-2013 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/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
+};
+
+unsigned long kvm_arch_vcpu_id(CPUState *cpu)
+{
+    return cpu->cpu_index;
+}
+
+int kvm_arch_init(KVMState *s)
+{
+    dprintf("%s\n", __func__);
+    return 0;
+}
+
+int kvm_arch_init_vcpu(CPUState *env)
+{
+    int ret = 0;
+    dprintf("%s\n", __func__);
+    return ret;
+}
+
+void kvm_arch_reset_vcpu(CPUState *env)
+{
+    dprintf("%s\n", __func__);
+}
+
+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_te_put_cp0_registers(cs, KVM_PUT_FULL_STATE);
+    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_te_get_cp0_registers(cs);
+
+    return ret;
+}
+
+int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
+{
+    dprintf("%s\n", __func__);
+    return 0;
+}
+
+int kvm_arch_remove_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
+{
+    dprintf("%s\n", __func__);
+    return 0;
+}
+
+static inline int cpu_mips_io_interrupts_pending(CPUArchState *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);
+    CPUMIPSState *env = &cpu->env;
+    int r;
+    struct kvm_mips_interrupt intr;
+
+    if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
+            (cpu_mips_io_interrupts_pending(env))) {
+        intr.cpu = -1;
+        intr.irq = 2;
+        r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
+        if (r < 0) {
+            printf("cpu %d fail inject %x\n", cs->cpu_index, intr.irq);
+        }
+    }
+}
+
+void kvm_arch_post_run(CPUState *env, 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 *env, struct kvm_run *run)
+{
+    int ret;
+
+    dprintf("%s\n", __func__);
+    switch (run->exit_reason) {
+    default:
+        fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
+        ret = -1;
+        break;
+    }
+
+    return ret;
+}
+
+bool kvm_arch_stop_on_emulation_error(CPUState *env)
+{
+    dprintf("%s\n", __func__);
+    return true;
+}
+
+int kvm_arch_on_sigbus_vcpu(CPUState *env, 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(CPUMIPSState *env, int irq, int level)
+{
+    CPUState *cs = ENV_GET_CPU(env);
+    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(CPUArchState *env, int irq, int level)
+{
+    CPUState *cs = current_cpu;
+    CPUState *dest_cs = ENV_GET_CPU(env);
+    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 KVM_REG_MIPS_CP0_INDEX     (0x10000 + (8 *  0) + 0)
+#define KVM_REG_MIPS_CP0_ENTRYLO0  (0x10000 + (8 *  2) + 0)
+#define KVM_REG_MIPS_CP0_ENTRYLO1  (0x10000 + (8 *  3) + 0)
+#define KVM_REG_MIPS_CP0_CONTEXT   (0x10000 + (8 *  4) + 0)
+#define KVM_REG_MIPS_CP0_USERLOCAL (0x10000 + (8 *  4) + 2)
+#define KVM_REG_MIPS_CP0_PAGEMASK  (0x10000 + (8 *  5) + 0)
+#define KVM_REG_MIPS_CP0_PAGEGRAIN (0x10000 + (8 *  5) + 1)
+#define KVM_REG_MIPS_CP0_WIRED     (0x10000 + (8 *  6) + 0)
+#define KVM_REG_MIPS_CP0_HWRENA    (0x10000 + (8 *  7) + 0)
+#define KVM_REG_MIPS_CP0_BADVADDR  (0x10000 + (8 *  8) + 0)
+#define KVM_REG_MIPS_CP0_COUNT     (0x10000 + (8 *  9) + 0)
+#define KVM_REG_MIPS_CP0_ENTRYHI   (0x10000 + (8 * 10) + 0)
+#define KVM_REG_MIPS_CP0_COMPARE   (0x10000 + (8 * 11) + 0)
+#define KVM_REG_MIPS_CP0_STATUS    (0x10000 + (8 * 12) + 0)
+#define KVM_REG_MIPS_CP0_INTCTL    (0x10000 + (8 * 12) + 1)
+#define KVM_REG_MIPS_CP0_CAUSE     (0x10000 + (8 * 13) + 0)
+#define KVM_REG_MIPS_CP0_EPC       (0x10000 + (8 * 14) + 0)
+#define KVM_REG_MIPS_CP0_PRID      (0x10000 + (8 * 15) + 0)
+#define KVM_REG_MIPS_CP0_EBASE     (0x10000 + (8 * 15) + 1)
+#define KVM_REG_MIPS_CP0_CONFIG    (0x10000 + (8 * 16) + 0)
+#define KVM_REG_MIPS_CP0_CONFIG1   (0x10000 + (8 * 16) + 1)
+#define KVM_REG_MIPS_CP0_CONFIG2   (0x10000 + (8 * 16) + 2)
+#define KVM_REG_MIPS_CP0_CONFIG3   (0x10000 + (8 * 16) + 3)
+#define KVM_REG_MIPS_CP0_CONFIG4   (0x10000 + (8 * 16) + 4)
+#define KVM_REG_MIPS_CP0_CONFIG5   (0x10000 + (8 * 16) + 5)
+#define KVM_REG_MIPS_CP0_CONFIG7   (0x10000 + (8 * 16) + 7)
+#define KVM_REG_MIPS_CP0_XCONTEXT  (0x10000 + (8 * 20) + 0)
+#define KVM_REG_MIPS_CP0_ERROREPC  (0x10000 + (8 * 30) + 0)
+
+inline int kvm_mips_put_one_reg(CPUState *cs, int reg_id, int32 *addr)
+{
+    __u64 val64 = (__u64)*addr;
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (__u64)((target_ulong)&val64)
+    };
+
+    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
+}
+
+inline int kvm_mips_put_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr)
+{
+    __u64 val64 = (__u64)*addr;
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (__u64)((target_ulong)&val64)
+    };
+
+    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
+}
+
+inline int kvm_mips_get_one_reg(CPUState *cs, int reg_id, int32 *addr)
+{
+    int ret;
+    __u64 val64 = 0;
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (__u64)((target_ulong)&val64)
+    };
+
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
+    if (ret < 0) {
+        return ret;
+    }
+
+    *addr = (int32)val64;
+    return ret;
+}
+
+inline int kvm_mips_get_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr)
+{
+    int ret;
+    __u64 val64 = 0;
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (__u64)((target_ulong)&val64)
+    };
+
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
+    if (ret < 0) {
+        return ret;
+    }
+
+    *addr = (target_ulong)val64;
+    return ret;
+}
+
+int kvm_mips_te_put_cp0_registers(CPUState *cs, int level)
+{
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    CPUMIPSState *env = &cpu->env;
+    int ret;
+
+    (void)level;
+
+    ret = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
+                                  &env->CP0_Context);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK,
+                                &env->CP0_PageMask);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR,
+                                  &env->CP0_BadVAddr);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI,
+                                  &env->CP0_EntryHi);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE,
+                                &env->CP0_Compare);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
+                                  &env->CP0_ErrorEPC);
+    if (ret < 0) {
+        return ret;
+    }
+
+    return ret;
+}
+
+int kvm_mips_te_get_cp0_registers(CPUState *cs)
+{
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    CPUMIPSState *env = &cpu->env;
+    int ret;
+
+    ret = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
+                                  &env->CP0_Context);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK,
+                                &env->CP0_PageMask);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR,
+                                  &env->CP0_BadVAddr);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI,
+                                  &env->CP0_EntryHi);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE,
+                                &env->CP0_Compare);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC);
+    if (ret < 0) {
+        return ret;
+    }
+    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
+                                  &env->CP0_ErrorEPC);
+    if (ret < 0) {
+        return ret;
+    }
+
+    return ret;
+}
diff --git a/target-mips/kvm_mips.h b/target-mips/kvm_mips.h
new file mode 100644
index 0000000..0da4edf
--- /dev/null
+++ b/target-mips/kvm_mips.h
@@ -0,0 +1,28 @@
+/*
+ * 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-2013 Imagination Technologies Ltd.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+*/
+
+#ifndef __KVM_MIPS_H__
+#define __KVM_MIPS_H__
+
+
+int kvm_mips_set_interrupt(CPUMIPSState *env, int irq, int level);
+
+int kvm_mips_set_ipi_interrupt(CPUArchState *env, int irq, int level);
+
+inline int kvm_mips_put_one_reg(CPUState *cs, int reg_id, int32 *addr);
+inline int kvm_mips_put_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr);
+inline int kvm_mips_get_one_reg(CPUState *cs, int reg_id, int32 *addr);
+inline int kvm_mips_get_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr);
+
+int kvm_mips_te_put_cp0_registers(CPUState *cs, int level);
+int kvm_mips_te_get_cp0_registers(CPUState *cs);
+
+#endif /* __KVM_MIPS_H__ */
-- 
1.8.1.2

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

* [PATCH v2 08/10] hw/mips: In KVM mode, inject IRQ2 (I/O) interupts via ioctls
  2013-12-16 14:12 ` [Qemu-devel] " James Hogan
@ 2013-12-16 14:12   ` James Hogan
  -1 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-16 14:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, Aurelien Jarno, Gleb Natapov, Paolo Bonzini, 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>
Cc: Aurelien Jarno <aurelien@aurel32.net>
---
Changes in v2:
 - Expand commit message
 - Remove #ifdef CONFIG_KVM since it's guarded by kvm_enabled() already
---
 hw/mips/mips_int.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c
index 7dbd24d..1b9981e 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(env, irq, level);
+        }
+
     } else {
         env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
+
+        if (kvm_enabled() && irq == 2) {
+            kvm_mips_set_interrupt(env, irq, level);
+        }
     }
 
     if (env->CP0_Cause & CP0Ca_IP_mask) {
-- 
1.8.1.2



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

* [Qemu-devel] [PATCH v2 08/10] hw/mips: In KVM mode, inject IRQ2 (I/O) interupts via ioctls
@ 2013-12-16 14:12   ` James Hogan
  0 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-16 14:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: James Hogan, kvm, Gleb Natapov, Sanjay Lal, Paolo Bonzini,
	Aurelien Jarno

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>
Cc: Aurelien Jarno <aurelien@aurel32.net>
---
Changes in v2:
 - Expand commit message
 - Remove #ifdef CONFIG_KVM since it's guarded by kvm_enabled() already
---
 hw/mips/mips_int.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c
index 7dbd24d..1b9981e 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(env, irq, level);
+        }
+
     } else {
         env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
+
+        if (kvm_enabled() && irq == 2) {
+            kvm_mips_set_interrupt(env, irq, level);
+        }
     }
 
     if (env->CP0_Cause & CP0Ca_IP_mask) {
-- 
1.8.1.2

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

* [PATCH v2 09/10] hw/mips: malta: Add KVM support
  2013-12-16 14:12 ` [Qemu-devel] " James Hogan
@ 2013-12-16 14:12   ` James Hogan
  -1 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-16 14:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, Aurelien Jarno, Gleb Natapov, Paolo Bonzini, Sanjay Lal,
	James Hogan

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>
Cc: Aurelien Jarno <aurelien@aurel32.net>
---
Changes in v2:
 - Removal of cps / GIC / SMP support
 - Minimal bootloader modified to execute safely from RAM
 - Remove "Writing bootloader to final 1MB of RAM" printf
---
 hw/mips/mips_malta.c | 85 ++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 63 insertions(+), 22 deletions(-)

diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index 05c8771..3fff07c 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -51,6 +51,10 @@
 #include "sysemu/qtest.h"
 #include "qemu/error-report.h"
 #include "hw/empty_slot.h"
+#include "qemu/bitmap.h"
+#include "sysemu/kvm.h"
+#include "linux/kvm.h"
+#include "kvm_mips.h"
 
 //#define DEBUG_BOARD_INIT
 
@@ -603,29 +607,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_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
+
+    stl_raw(p++, 0x08000000 |                                      /* j 0x1fc00580 */
+                 ((run_addr + 0x580) & 0x0fffffff) >> 2);
     stl_raw(p++, 0x00000000);                                      /* nop */
 
     /* YAMON service vector */
-    stl_raw(base + 0x500, 0xbfc00580);      /* start: */
-    stl_raw(base + 0x504, 0xbfc0083c);      /* print_count: */
-    stl_raw(base + 0x520, 0xbfc00580);      /* start: */
-    stl_raw(base + 0x52c, 0xbfc00800);      /* flush_cache: */
-    stl_raw(base + 0x534, 0xbfc00808);      /* print: */
-    stl_raw(base + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
-    stl_raw(base + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
-    stl_raw(base + 0x540, 0xbfc00800);      /* reg_ic_isr: */
-    stl_raw(base + 0x544, 0xbfc00800);      /* unred_ic_isr: */
-    stl_raw(base + 0x548, 0xbfc00800);      /* reg_esr: */
-    stl_raw(base + 0x54c, 0xbfc00800);      /* unreg_esr: */
-    stl_raw(base + 0x550, 0xbfc00800);      /* getchar: */
-    stl_raw(base + 0x554, 0xbfc00800);      /* syscon_read: */
+    stl_raw(base + 0x500, run_addr + 0x0580);      /* start: */
+    stl_raw(base + 0x504, run_addr + 0x083c);      /* print_count: */
+    stl_raw(base + 0x520, run_addr + 0x0580);      /* start: */
+    stl_raw(base + 0x52c, run_addr + 0x0800);      /* flush_cache: */
+    stl_raw(base + 0x534, run_addr + 0x0808);      /* print: */
+    stl_raw(base + 0x538, run_addr + 0x0800);      /* reg_cpu_isr: */
+    stl_raw(base + 0x53c, run_addr + 0x0800);      /* unred_cpu_isr: */
+    stl_raw(base + 0x540, run_addr + 0x0800);      /* reg_ic_isr: */
+    stl_raw(base + 0x544, run_addr + 0x0800);      /* unred_ic_isr: */
+    stl_raw(base + 0x548, run_addr + 0x0800);      /* reg_esr: */
+    stl_raw(base + 0x54c, run_addr + 0x0800);      /* unreg_esr: */
+    stl_raw(base + 0x550, run_addr + 0x0800);      /* getchar: */
+    stl_raw(base + 0x554, run_addr + 0x0800);      /* syscon_read: */
 
 
     /* Second part of the bootloader */
@@ -701,7 +707,7 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base,
     p = (uint32_t *) (base + 0x800);
     stl_raw(p++, 0x03e00008);                                     /* jr ra */
     stl_raw(p++, 0x24020000);                                     /* li v0,0 */
-   /* 808 YAMON print */
+    /* 808 YAMON print */
     stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
     stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
     stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
@@ -774,6 +780,9 @@ static int64_t load_kernel (void)
     uint32_t *prom_buf;
     long prom_size;
     int prom_index = 0;
+    uint64_t (*xlate_to_phys) (void *opaque, uint64_t addr);
+    uint64_t (*xlate_to_kseg0) (void *opaque, uint64_t addr);
+
 
 #ifdef TARGET_WORDS_BIGENDIAN
     big_endian = 1;
@@ -781,7 +790,15 @@ static int64_t load_kernel (void)
     big_endian = 0;
 #endif
 
-    if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
+    if (kvm_enabled()) {
+        xlate_to_phys = cpu_mips_kvm_um_kseg0_to_phys;
+        xlate_to_kseg0 = cpu_mips_kvm_um_phys_to_kseg0;
+    } else {
+        xlate_to_phys = cpu_mips_kseg0_to_phys;
+        xlate_to_kseg0 = cpu_mips_phys_to_kseg0;
+    }
+
+    if (load_elf(loaderparams.kernel_filename, xlate_to_phys, NULL,
                  (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
                  big_endian, ELF_MACHINE, 1) < 0) {
         fprintf(stderr, "qemu: could not load kernel '%s'\n",
@@ -820,7 +837,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,12 +846,13 @@ 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);
 
     rom_add_blob_fixed("prom", prom_buf, prom_size,
-                       cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR));
+                       xlate_to_phys(NULL, ENVP_ADDR));
 
     return kernel_entry;
 }
@@ -863,6 +881,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 +901,7 @@ static
 void mips_malta_init(QEMUMachineInitArgs *args)
 {
     ram_addr_t ram_size = args->ram_size;
+    ram_addr_t ram_low_size;
     const char *cpu_model = args->cpu_model;
     const char *kernel_filename = args->kernel_filename;
     const char *kernel_cmdline = args->kernel_cmdline;
@@ -892,7 +916,7 @@ void mips_malta_init(QEMUMachineInitArgs *args)
     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 +1035,30 @@ void mips_malta_init(QEMUMachineInitArgs *args)
     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.8.1.2



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

* [Qemu-devel] [PATCH v2 09/10] hw/mips: malta: Add KVM support
@ 2013-12-16 14:12   ` James Hogan
  0 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-16 14:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: James Hogan, kvm, Gleb Natapov, Sanjay Lal, Paolo Bonzini,
	Aurelien Jarno

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>
Cc: Aurelien Jarno <aurelien@aurel32.net>
---
Changes in v2:
 - Removal of cps / GIC / SMP support
 - Minimal bootloader modified to execute safely from RAM
 - Remove "Writing bootloader to final 1MB of RAM" printf
---
 hw/mips/mips_malta.c | 85 ++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 63 insertions(+), 22 deletions(-)

diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index 05c8771..3fff07c 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -51,6 +51,10 @@
 #include "sysemu/qtest.h"
 #include "qemu/error-report.h"
 #include "hw/empty_slot.h"
+#include "qemu/bitmap.h"
+#include "sysemu/kvm.h"
+#include "linux/kvm.h"
+#include "kvm_mips.h"
 
 //#define DEBUG_BOARD_INIT
 
@@ -603,29 +607,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_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
+
+    stl_raw(p++, 0x08000000 |                                      /* j 0x1fc00580 */
+                 ((run_addr + 0x580) & 0x0fffffff) >> 2);
     stl_raw(p++, 0x00000000);                                      /* nop */
 
     /* YAMON service vector */
-    stl_raw(base + 0x500, 0xbfc00580);      /* start: */
-    stl_raw(base + 0x504, 0xbfc0083c);      /* print_count: */
-    stl_raw(base + 0x520, 0xbfc00580);      /* start: */
-    stl_raw(base + 0x52c, 0xbfc00800);      /* flush_cache: */
-    stl_raw(base + 0x534, 0xbfc00808);      /* print: */
-    stl_raw(base + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
-    stl_raw(base + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
-    stl_raw(base + 0x540, 0xbfc00800);      /* reg_ic_isr: */
-    stl_raw(base + 0x544, 0xbfc00800);      /* unred_ic_isr: */
-    stl_raw(base + 0x548, 0xbfc00800);      /* reg_esr: */
-    stl_raw(base + 0x54c, 0xbfc00800);      /* unreg_esr: */
-    stl_raw(base + 0x550, 0xbfc00800);      /* getchar: */
-    stl_raw(base + 0x554, 0xbfc00800);      /* syscon_read: */
+    stl_raw(base + 0x500, run_addr + 0x0580);      /* start: */
+    stl_raw(base + 0x504, run_addr + 0x083c);      /* print_count: */
+    stl_raw(base + 0x520, run_addr + 0x0580);      /* start: */
+    stl_raw(base + 0x52c, run_addr + 0x0800);      /* flush_cache: */
+    stl_raw(base + 0x534, run_addr + 0x0808);      /* print: */
+    stl_raw(base + 0x538, run_addr + 0x0800);      /* reg_cpu_isr: */
+    stl_raw(base + 0x53c, run_addr + 0x0800);      /* unred_cpu_isr: */
+    stl_raw(base + 0x540, run_addr + 0x0800);      /* reg_ic_isr: */
+    stl_raw(base + 0x544, run_addr + 0x0800);      /* unred_ic_isr: */
+    stl_raw(base + 0x548, run_addr + 0x0800);      /* reg_esr: */
+    stl_raw(base + 0x54c, run_addr + 0x0800);      /* unreg_esr: */
+    stl_raw(base + 0x550, run_addr + 0x0800);      /* getchar: */
+    stl_raw(base + 0x554, run_addr + 0x0800);      /* syscon_read: */
 
 
     /* Second part of the bootloader */
@@ -701,7 +707,7 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base,
     p = (uint32_t *) (base + 0x800);
     stl_raw(p++, 0x03e00008);                                     /* jr ra */
     stl_raw(p++, 0x24020000);                                     /* li v0,0 */
-   /* 808 YAMON print */
+    /* 808 YAMON print */
     stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
     stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
     stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
@@ -774,6 +780,9 @@ static int64_t load_kernel (void)
     uint32_t *prom_buf;
     long prom_size;
     int prom_index = 0;
+    uint64_t (*xlate_to_phys) (void *opaque, uint64_t addr);
+    uint64_t (*xlate_to_kseg0) (void *opaque, uint64_t addr);
+
 
 #ifdef TARGET_WORDS_BIGENDIAN
     big_endian = 1;
@@ -781,7 +790,15 @@ static int64_t load_kernel (void)
     big_endian = 0;
 #endif
 
-    if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
+    if (kvm_enabled()) {
+        xlate_to_phys = cpu_mips_kvm_um_kseg0_to_phys;
+        xlate_to_kseg0 = cpu_mips_kvm_um_phys_to_kseg0;
+    } else {
+        xlate_to_phys = cpu_mips_kseg0_to_phys;
+        xlate_to_kseg0 = cpu_mips_phys_to_kseg0;
+    }
+
+    if (load_elf(loaderparams.kernel_filename, xlate_to_phys, NULL,
                  (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
                  big_endian, ELF_MACHINE, 1) < 0) {
         fprintf(stderr, "qemu: could not load kernel '%s'\n",
@@ -820,7 +837,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,12 +846,13 @@ 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);
 
     rom_add_blob_fixed("prom", prom_buf, prom_size,
-                       cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR));
+                       xlate_to_phys(NULL, ENVP_ADDR));
 
     return kernel_entry;
 }
@@ -863,6 +881,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 +901,7 @@ static
 void mips_malta_init(QEMUMachineInitArgs *args)
 {
     ram_addr_t ram_size = args->ram_size;
+    ram_addr_t ram_low_size;
     const char *cpu_model = args->cpu_model;
     const char *kernel_filename = args->kernel_filename;
     const char *kernel_cmdline = args->kernel_cmdline;
@@ -892,7 +916,7 @@ void mips_malta_init(QEMUMachineInitArgs *args)
     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 +1035,30 @@ void mips_malta_init(QEMUMachineInitArgs *args)
     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.8.1.2

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

* [PATCH v2 10/10] target-mips: Enable KVM support in build system
  2013-12-16 14:12 ` [Qemu-devel] " James Hogan
@ 2013-12-16 14:12   ` James Hogan
  -1 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-16 14:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, Aurelien Jarno, Gleb Natapov, Paolo Bonzini, 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>
Cc: Aurelien Jarno <aurelien@aurel32.net>
---
Changes in v2:
 - Expand commit message
 - Remove GIC code
 - Create asm-mips symlink using generic code and move above default
   case (Peter Maydell)
 - Remove redundant check of target_name = cpu = mips
 - Remove mipsel cross compilation fix, which is now fixed by
   commit 61cc919f73ea (configure: detect endian via compile test)
---
 configure                 | 6 +++++-
 target-mips/Makefile.objs | 1 +
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/configure b/configure
index 0666228..7d86eea 100755
--- a/configure
+++ b/configure
@@ -4329,6 +4329,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"
@@ -4518,7 +4521,7 @@ case "$target_name" in
   *)
 esac
 case "$target_name" in
-  arm|i386|x86_64|ppcemb|ppc|ppc64|s390x)
+  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 \
@@ -4526,6 +4529,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.8.1.2



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

* [Qemu-devel] [PATCH v2 10/10] target-mips: Enable KVM support in build system
@ 2013-12-16 14:12   ` James Hogan
  0 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-16 14:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: James Hogan, kvm, Gleb Natapov, Sanjay Lal, Paolo Bonzini,
	Aurelien Jarno

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>
Cc: Aurelien Jarno <aurelien@aurel32.net>
---
Changes in v2:
 - Expand commit message
 - Remove GIC code
 - Create asm-mips symlink using generic code and move above default
   case (Peter Maydell)
 - Remove redundant check of target_name = cpu = mips
 - Remove mipsel cross compilation fix, which is now fixed by
   commit 61cc919f73ea (configure: detect endian via compile test)
---
 configure                 | 6 +++++-
 target-mips/Makefile.objs | 1 +
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/configure b/configure
index 0666228..7d86eea 100755
--- a/configure
+++ b/configure
@@ -4329,6 +4329,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"
@@ -4518,7 +4521,7 @@ case "$target_name" in
   *)
 esac
 case "$target_name" in
-  arm|i386|x86_64|ppcemb|ppc|ppc64|s390x)
+  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 \
@@ -4526,6 +4529,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.8.1.2

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

* Re: [PATCH v2 01/10] hw/mips/cputimer: Don't start periodic timer in KVM mode
  2013-12-16 14:12   ` [Qemu-devel] " James Hogan
@ 2013-12-21 15:34     ` Aurelien Jarno
  -1 siblings, 0 replies; 58+ messages in thread
From: Aurelien Jarno @ 2013-12-21 15:34 UTC (permalink / raw)
  To: James Hogan; +Cc: Paolo Bonzini, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

On Mon, Dec 16, 2013 at 02:12:36PM +0000, James Hogan wrote:
> From: Sanjay Lal <sanjayl@kymasys.com>
> 
> Compare/Count timer interrupts are handled in-kernel for KVM, so don't
> bother starting it in QEMU.
> 
> Signed-off-by: Sanjay Lal <sanjayl@kymasys.com>
> Signed-off-by: James Hogan <james.hogan@imgtec.com>
> Cc: Aurelien Jarno <aurelien@aurel32.net>
> ---
> Changes in v2:
>  - Expand commit message
>  - Rebase on v1.7.0
>  - Wrap comment
> ---
>  hw/mips/cputimer.c | 13 ++++++++++---
>  1 file changed, 10 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/mips/cputimer.c b/hw/mips/cputimer.c
> index c8b4b00..52570fd 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
>  
> @@ -141,7 +142,13 @@ 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);
> +    /*
> +     * If we're in KVM mode, don't start the periodic timer, that is handled in
> +     * kernel.
> +     */
> +    if (!kvm_enabled()) {
> +        env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb, env);
> +        env->CP0_Compare = 0;
> +        cpu_mips_store_count(env, 1);
> +    }
>  }

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 01/10] hw/mips/cputimer: Don't start periodic timer in KVM mode
@ 2013-12-21 15:34     ` Aurelien Jarno
  0 siblings, 0 replies; 58+ messages in thread
From: Aurelien Jarno @ 2013-12-21 15:34 UTC (permalink / raw)
  To: James Hogan; +Cc: Paolo Bonzini, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

On Mon, Dec 16, 2013 at 02:12:36PM +0000, James Hogan wrote:
> From: Sanjay Lal <sanjayl@kymasys.com>
> 
> Compare/Count timer interrupts are handled in-kernel for KVM, so don't
> bother starting it in QEMU.
> 
> Signed-off-by: Sanjay Lal <sanjayl@kymasys.com>
> Signed-off-by: James Hogan <james.hogan@imgtec.com>
> Cc: Aurelien Jarno <aurelien@aurel32.net>
> ---
> Changes in v2:
>  - Expand commit message
>  - Rebase on v1.7.0
>  - Wrap comment
> ---
>  hw/mips/cputimer.c | 13 ++++++++++---
>  1 file changed, 10 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/mips/cputimer.c b/hw/mips/cputimer.c
> index c8b4b00..52570fd 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
>  
> @@ -141,7 +142,13 @@ 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);
> +    /*
> +     * If we're in KVM mode, don't start the periodic timer, that is handled in
> +     * kernel.
> +     */
> +    if (!kvm_enabled()) {
> +        env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb, env);
> +        env->CP0_Compare = 0;
> +        cpu_mips_store_count(env, 1);
> +    }
>  }

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH v2 02/10] hw/mips: Add API to convert KVM guest KSEG0 <-> GPA
  2013-12-16 14:12   ` [Qemu-devel] " James Hogan
@ 2013-12-21 15:34     ` Aurelien Jarno
  -1 siblings, 0 replies; 58+ messages in thread
From: Aurelien Jarno @ 2013-12-21 15:34 UTC (permalink / raw)
  To: James Hogan; +Cc: Paolo Bonzini, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

On Mon, Dec 16, 2013 at 02:12:37PM +0000, James Hogan wrote:
> From: Sanjay Lal <sanjayl@kymasys.com>
> 
> Add APIs for converting between KVM guest KSEG0 addresses and guest
> physical addresses. These will be used for translating addresses when
> loading a kernel ELF in KVM mode.
> 
> 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>
> ---
> Changes in v2:
>  - Expand commit message
>  - Remove unnecessary include
> ---
>  hw/mips/addr.c            | 10 ++++++++++
>  include/hw/mips/cpudevs.h |  4 ++++
>  2 files changed, 14 insertions(+)
> 
> diff --git a/hw/mips/addr.c b/hw/mips/addr.c
> index 99488f1..e62d6f4 100644
> --- a/hw/mips/addr.c
> +++ b/hw/mips/addr.c
> @@ -28,7 +28,17 @@ uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr)
>      return addr & 0x7fffffffll;
>  }
>  
> +uint64_t cpu_mips_kvm_um_kseg0_to_phys(void *opaque, uint64_t addr)
> +{
> +    return addr & 0x3fffffffll;
> +}
> +
>  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..9e5af37 100644
> --- a/include/hw/mips/cpudevs.h
> +++ b/include/hw/mips/cpudevs.h
> @@ -6,6 +6,10 @@
>  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_kseg0_to_phys(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);
>  

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 02/10] hw/mips: Add API to convert KVM guest KSEG0 <-> GPA
@ 2013-12-21 15:34     ` Aurelien Jarno
  0 siblings, 0 replies; 58+ messages in thread
From: Aurelien Jarno @ 2013-12-21 15:34 UTC (permalink / raw)
  To: James Hogan; +Cc: Paolo Bonzini, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

On Mon, Dec 16, 2013 at 02:12:37PM +0000, James Hogan wrote:
> From: Sanjay Lal <sanjayl@kymasys.com>
> 
> Add APIs for converting between KVM guest KSEG0 addresses and guest
> physical addresses. These will be used for translating addresses when
> loading a kernel ELF in KVM mode.
> 
> 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>
> ---
> Changes in v2:
>  - Expand commit message
>  - Remove unnecessary include
> ---
>  hw/mips/addr.c            | 10 ++++++++++
>  include/hw/mips/cpudevs.h |  4 ++++
>  2 files changed, 14 insertions(+)
> 
> diff --git a/hw/mips/addr.c b/hw/mips/addr.c
> index 99488f1..e62d6f4 100644
> --- a/hw/mips/addr.c
> +++ b/hw/mips/addr.c
> @@ -28,7 +28,17 @@ uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr)
>      return addr & 0x7fffffffll;
>  }
>  
> +uint64_t cpu_mips_kvm_um_kseg0_to_phys(void *opaque, uint64_t addr)
> +{
> +    return addr & 0x3fffffffll;
> +}
> +
>  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..9e5af37 100644
> --- a/include/hw/mips/cpudevs.h
> +++ b/include/hw/mips/cpudevs.h
> @@ -6,6 +6,10 @@
>  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_kseg0_to_phys(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);
>  

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH v2 03/10] target-mips: get_physical_address: Add defines for segment bases
  2013-12-16 14:12   ` [Qemu-devel] " James Hogan
@ 2013-12-21 15:34     ` Aurelien Jarno
  -1 siblings, 0 replies; 58+ messages in thread
From: Aurelien Jarno @ 2013-12-21 15:34 UTC (permalink / raw)
  To: James Hogan; +Cc: Paolo Bonzini, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

On Mon, Dec 16, 2013 at 02:12:38PM +0000, James Hogan wrote:
> 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>
> Cc: Aurelien Jarno <aurelien@aurel32.net>
> ---
>  target-mips/helper.c | 18 ++++++++++++------
>  1 file changed, 12 insertions(+), 6 deletions(-)
> 
> diff --git a/target-mips/helper.c b/target-mips/helper.c
> index 33e0e88..2e96655 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);

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 03/10] target-mips: get_physical_address: Add defines for segment bases
@ 2013-12-21 15:34     ` Aurelien Jarno
  0 siblings, 0 replies; 58+ messages in thread
From: Aurelien Jarno @ 2013-12-21 15:34 UTC (permalink / raw)
  To: James Hogan; +Cc: Paolo Bonzini, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

On Mon, Dec 16, 2013 at 02:12:38PM +0000, James Hogan wrote:
> 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>
> Cc: Aurelien Jarno <aurelien@aurel32.net>
> ---
>  target-mips/helper.c | 18 ++++++++++++------
>  1 file changed, 12 insertions(+), 6 deletions(-)
> 
> diff --git a/target-mips/helper.c b/target-mips/helper.c
> index 33e0e88..2e96655 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);

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH v2 04/10] target-mips: get_physical_address: Add KVM awareness
  2013-12-16 14:12   ` [Qemu-devel] " James Hogan
@ 2013-12-21 15:34     ` Aurelien Jarno
  -1 siblings, 0 replies; 58+ messages in thread
From: Aurelien Jarno @ 2013-12-21 15:34 UTC (permalink / raw)
  To: James Hogan; +Cc: Paolo Bonzini, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

On Mon, Dec 16, 2013 at 02:12:39PM +0000, James Hogan wrote:
> 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>
> ---
>  target-mips/helper.c | 33 ++++++++++++++++++++++++++-------
>  1 file changed, 26 insertions(+), 7 deletions(-)
> 
> diff --git a/target-mips/helper.c b/target-mips/helper.c
> index 2e96655..c4be887 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;
>          }

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 04/10] target-mips: get_physical_address: Add KVM awareness
@ 2013-12-21 15:34     ` Aurelien Jarno
  0 siblings, 0 replies; 58+ messages in thread
From: Aurelien Jarno @ 2013-12-21 15:34 UTC (permalink / raw)
  To: James Hogan; +Cc: Paolo Bonzini, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

On Mon, Dec 16, 2013 at 02:12:39PM +0000, James Hogan wrote:
> 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>
> ---
>  target-mips/helper.c | 33 ++++++++++++++++++++++++++-------
>  1 file changed, 26 insertions(+), 7 deletions(-)
> 
> diff --git a/target-mips/helper.c b/target-mips/helper.c
> index 2e96655..c4be887 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;
>          }

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH v2 05/10] kvm: Set sigmask length to 16 for MIPS targets
  2013-12-16 14:12   ` [Qemu-devel] " James Hogan
@ 2013-12-21 15:34     ` Aurelien Jarno
  -1 siblings, 0 replies; 58+ messages in thread
From: Aurelien Jarno @ 2013-12-21 15:34 UTC (permalink / raw)
  To: James Hogan; +Cc: Paolo Bonzini, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

On Mon, Dec 16, 2013 at 02:12:40PM +0000, James Hogan wrote:
> From: Sanjay Lal <sanjayl@kymasys.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 correct kvm_set_signal_mask to pass the correct sigmask->len to
> KVM_SET_SIGNAL_MASK.
> 
> Signed-off-by: Sanjay Lal <sanjayl@kymasys.com>
> Signed-off-by: James Hogan <james.hogan@imgtec.com>
> Cc: Gleb Natapov <gleb@redhat.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> ---
> Changes in v2:
>  - Expand commit message
>  - Reword comment
> ---
>  kvm-all.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/kvm-all.c b/kvm-all.c
> index 4478969..c831326 100644
> --- a/kvm-all.c
> +++ b/kvm-all.c
> @@ -2044,7 +2044,12 @@ int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset)
>  
>      sigmask = g_malloc(sizeof(*sigmask) + sizeof(*sigset));
>  
> +#ifdef TARGET_MIPS
> +    /* MIPS has 128 signals */
> +    sigmask->len = 16;
> +#else
>      sigmask->len = 8;
> +#endif
>      memcpy(sigmask->sigset, sigset, sizeof(*sigset));
>      r = kvm_vcpu_ioctl(cpu, KVM_SET_SIGNAL_MASK, sigmask);
>      g_free(sigmask);

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 05/10] kvm: Set sigmask length to 16 for MIPS targets
@ 2013-12-21 15:34     ` Aurelien Jarno
  0 siblings, 0 replies; 58+ messages in thread
From: Aurelien Jarno @ 2013-12-21 15:34 UTC (permalink / raw)
  To: James Hogan; +Cc: Paolo Bonzini, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

On Mon, Dec 16, 2013 at 02:12:40PM +0000, James Hogan wrote:
> From: Sanjay Lal <sanjayl@kymasys.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 correct kvm_set_signal_mask to pass the correct sigmask->len to
> KVM_SET_SIGNAL_MASK.
> 
> Signed-off-by: Sanjay Lal <sanjayl@kymasys.com>
> Signed-off-by: James Hogan <james.hogan@imgtec.com>
> Cc: Gleb Natapov <gleb@redhat.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> ---
> Changes in v2:
>  - Expand commit message
>  - Reword comment
> ---
>  kvm-all.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/kvm-all.c b/kvm-all.c
> index 4478969..c831326 100644
> --- a/kvm-all.c
> +++ b/kvm-all.c
> @@ -2044,7 +2044,12 @@ int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset)
>  
>      sigmask = g_malloc(sizeof(*sigmask) + sizeof(*sigset));
>  
> +#ifdef TARGET_MIPS
> +    /* MIPS has 128 signals */
> +    sigmask->len = 16;
> +#else
>      sigmask->len = 8;
> +#endif
>      memcpy(sigmask->sigset, sigset, sizeof(*sigset));
>      r = kvm_vcpu_ioctl(cpu, KVM_SET_SIGNAL_MASK, sigmask);
>      g_free(sigmask);

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH v2 06/10] target-mips: Set target page size to 16K in KVM mode
  2013-12-16 14:12   ` [Qemu-devel] " James Hogan
@ 2013-12-21 15:34     ` Aurelien Jarno
  -1 siblings, 0 replies; 58+ messages in thread
From: Aurelien Jarno @ 2013-12-21 15:34 UTC (permalink / raw)
  To: James Hogan; +Cc: Paolo Bonzini, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

On Mon, Dec 16, 2013 at 02:12:41PM +0000, James Hogan wrote:
> From: Sanjay Lal <sanjayl@kymasys.com>
> 
> With larger set associative caches KVM can open the possibility of cache
> aliasing between the memory that QEMU allocates with mmap and the
> mapping into the guest address space. Therefore increase the target page
> size to 16K when KVM is configured.
> 
> Signed-off-by: Sanjay Lal <sanjayl@kymasys.com>
> Signed-off-by: James Hogan <james.hogan@imgtec.com>
> Cc: Aurelien Jarno <aurelien@aurel32.net>
> ---
> Changes in v2:
>  - Expand commit message
> ---
>  target-mips/mips-defs.h | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h
> index bf094a3..473ddf8 100644
> --- a/target-mips/mips-defs.h
> +++ b/target-mips/mips-defs.h
> @@ -5,7 +5,12 @@
>  //#define USE_HOST_FLOAT_REGS
>  
>  /* Real pages are variable size... */
> +#ifdef CONFIG_KVM
> +/* For KVM/MIPS the minimum page size is 16K due to cache aliasing issues */
> +#define TARGET_PAGE_BITS 14
> +#else
>  #define TARGET_PAGE_BITS 12
> +#endif
>  #define MIPS_TLB_MAX 128
>  
>  #if defined(TARGET_MIPS64)

I am not sure it is something correct. It means that the emulated CPU
won't support 4K pages anymore, even when running in TCG mode without
KVM. If the kernel maps a 4K page, in practice a 16K page is going to be
mapped by the qemu tlb.

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 06/10] target-mips: Set target page size to 16K in KVM mode
@ 2013-12-21 15:34     ` Aurelien Jarno
  0 siblings, 0 replies; 58+ messages in thread
From: Aurelien Jarno @ 2013-12-21 15:34 UTC (permalink / raw)
  To: James Hogan; +Cc: Paolo Bonzini, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

On Mon, Dec 16, 2013 at 02:12:41PM +0000, James Hogan wrote:
> From: Sanjay Lal <sanjayl@kymasys.com>
> 
> With larger set associative caches KVM can open the possibility of cache
> aliasing between the memory that QEMU allocates with mmap and the
> mapping into the guest address space. Therefore increase the target page
> size to 16K when KVM is configured.
> 
> Signed-off-by: Sanjay Lal <sanjayl@kymasys.com>
> Signed-off-by: James Hogan <james.hogan@imgtec.com>
> Cc: Aurelien Jarno <aurelien@aurel32.net>
> ---
> Changes in v2:
>  - Expand commit message
> ---
>  target-mips/mips-defs.h | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h
> index bf094a3..473ddf8 100644
> --- a/target-mips/mips-defs.h
> +++ b/target-mips/mips-defs.h
> @@ -5,7 +5,12 @@
>  //#define USE_HOST_FLOAT_REGS
>  
>  /* Real pages are variable size... */
> +#ifdef CONFIG_KVM
> +/* For KVM/MIPS the minimum page size is 16K due to cache aliasing issues */
> +#define TARGET_PAGE_BITS 14
> +#else
>  #define TARGET_PAGE_BITS 12
> +#endif
>  #define MIPS_TLB_MAX 128
>  
>  #if defined(TARGET_MIPS64)

I am not sure it is something correct. It means that the emulated CPU
won't support 4K pages anymore, even when running in TCG mode without
KVM. If the kernel maps a 4K page, in practice a 16K page is going to be
mapped by the qemu tlb.

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH v2 07/10] target-mips: kvm: Add main KVM support for MIPS
  2013-12-16 14:12   ` [Qemu-devel] " James Hogan
@ 2013-12-21 15:35     ` Aurelien Jarno
  -1 siblings, 0 replies; 58+ messages in thread
From: Aurelien Jarno @ 2013-12-21 15:35 UTC (permalink / raw)
  To: James Hogan; +Cc: Paolo Bonzini, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

On Mon, Dec 16, 2013 at 02:12:42PM +0000, James Hogan wrote:
> 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>
> ---
> Changes in v2:
>  - Expand commit message
>  - Checkpatch cleanups.
>  - Some interrupt bug fixes from Yann Le Du <ledu@kymasys.com>
>  - Add get/set register functionality from Yann Le Du <ledu@kymasys.com>
>  - Use new 64 bit compatible ABI from Cavium from Sanjay Lal
>    <sanjayl@kymasys.com>
>  - Add dummy kvm_arch_init_irq_routing()
>    The common KVM code insists on calling kvm_arch_init_irq_routing() as
>    soon as it sees kernel header support for it (regardless of whether
>    QEMU supports it). Provide a dummy function to satisfy this.
>  - Remove request_interrupt_window code (Peter Maydell)
> ---
>  target-mips/kvm.c      | 463 +++++++++++++++++++++++++++++++++++++++++++++++++
>  target-mips/kvm_mips.h |  28 +++
>  2 files changed, 491 insertions(+)
>  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..951959b
> --- /dev/null
> +++ b/target-mips/kvm.c
> @@ -0,0 +1,463 @@
> +/*
> + * 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-2013 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/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
> +};
> +
> +unsigned long kvm_arch_vcpu_id(CPUState *cpu)
> +{
> +    return cpu->cpu_index;
> +}
> +
> +int kvm_arch_init(KVMState *s)
> +{
> +    dprintf("%s\n", __func__);
> +    return 0;
> +}
> +
> +int kvm_arch_init_vcpu(CPUState *env)
> +{
> +    int ret = 0;
> +    dprintf("%s\n", __func__);
> +    return ret;
> +}
> +
> +void kvm_arch_reset_vcpu(CPUState *env)
> +{
> +    dprintf("%s\n", __func__);
> +}
> +
> +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_te_put_cp0_registers(cs, KVM_PUT_FULL_STATE);
> +    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_te_get_cp0_registers(cs);
> +
> +    return ret;
> +}
> +
> +int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
> +{
> +    dprintf("%s\n", __func__);
> +    return 0;
> +}
> +
> +int kvm_arch_remove_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
> +{
> +    dprintf("%s\n", __func__);
> +    return 0;
> +}
> +
> +static inline int cpu_mips_io_interrupts_pending(CPUArchState *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);
> +    CPUMIPSState *env = &cpu->env;
> +    int r;
> +    struct kvm_mips_interrupt intr;
> +
> +    if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
> +            (cpu_mips_io_interrupts_pending(env))) {
> +        intr.cpu = -1;
> +        intr.irq = 2;
> +        r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
> +        if (r < 0) {
> +            printf("cpu %d fail inject %x\n", cs->cpu_index, intr.irq);
> +        }
> +    }
> +}
> +
> +void kvm_arch_post_run(CPUState *env, 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 *env, struct kvm_run *run)
> +{
> +    int ret;
> +
> +    dprintf("%s\n", __func__);
> +    switch (run->exit_reason) {
> +    default:
> +        fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
> +        ret = -1;
> +        break;
> +    }
> +
> +    return ret;
> +}
> +
> +bool kvm_arch_stop_on_emulation_error(CPUState *env)
> +{
> +    dprintf("%s\n", __func__);
> +    return true;
> +}
> +
> +int kvm_arch_on_sigbus_vcpu(CPUState *env, 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(CPUMIPSState *env, int irq, int level)
> +{
> +    CPUState *cs = ENV_GET_CPU(env);
> +    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(CPUArchState *env, int irq, int level)
> +{
> +    CPUState *cs = current_cpu;
> +    CPUState *dest_cs = ENV_GET_CPU(env);
> +    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 KVM_REG_MIPS_CP0_INDEX     (0x10000 + (8 *  0) + 0)
> +#define KVM_REG_MIPS_CP0_ENTRYLO0  (0x10000 + (8 *  2) + 0)
> +#define KVM_REG_MIPS_CP0_ENTRYLO1  (0x10000 + (8 *  3) + 0)
> +#define KVM_REG_MIPS_CP0_CONTEXT   (0x10000 + (8 *  4) + 0)
> +#define KVM_REG_MIPS_CP0_USERLOCAL (0x10000 + (8 *  4) + 2)
> +#define KVM_REG_MIPS_CP0_PAGEMASK  (0x10000 + (8 *  5) + 0)
> +#define KVM_REG_MIPS_CP0_PAGEGRAIN (0x10000 + (8 *  5) + 1)
> +#define KVM_REG_MIPS_CP0_WIRED     (0x10000 + (8 *  6) + 0)
> +#define KVM_REG_MIPS_CP0_HWRENA    (0x10000 + (8 *  7) + 0)
> +#define KVM_REG_MIPS_CP0_BADVADDR  (0x10000 + (8 *  8) + 0)
> +#define KVM_REG_MIPS_CP0_COUNT     (0x10000 + (8 *  9) + 0)
> +#define KVM_REG_MIPS_CP0_ENTRYHI   (0x10000 + (8 * 10) + 0)
> +#define KVM_REG_MIPS_CP0_COMPARE   (0x10000 + (8 * 11) + 0)
> +#define KVM_REG_MIPS_CP0_STATUS    (0x10000 + (8 * 12) + 0)
> +#define KVM_REG_MIPS_CP0_INTCTL    (0x10000 + (8 * 12) + 1)
> +#define KVM_REG_MIPS_CP0_CAUSE     (0x10000 + (8 * 13) + 0)
> +#define KVM_REG_MIPS_CP0_EPC       (0x10000 + (8 * 14) + 0)
> +#define KVM_REG_MIPS_CP0_PRID      (0x10000 + (8 * 15) + 0)
> +#define KVM_REG_MIPS_CP0_EBASE     (0x10000 + (8 * 15) + 1)
> +#define KVM_REG_MIPS_CP0_CONFIG    (0x10000 + (8 * 16) + 0)
> +#define KVM_REG_MIPS_CP0_CONFIG1   (0x10000 + (8 * 16) + 1)
> +#define KVM_REG_MIPS_CP0_CONFIG2   (0x10000 + (8 * 16) + 2)
> +#define KVM_REG_MIPS_CP0_CONFIG3   (0x10000 + (8 * 16) + 3)
> +#define KVM_REG_MIPS_CP0_CONFIG4   (0x10000 + (8 * 16) + 4)
> +#define KVM_REG_MIPS_CP0_CONFIG5   (0x10000 + (8 * 16) + 5)
> +#define KVM_REG_MIPS_CP0_CONFIG7   (0x10000 + (8 * 16) + 7)
> +#define KVM_REG_MIPS_CP0_XCONTEXT  (0x10000 + (8 * 20) + 0)
> +#define KVM_REG_MIPS_CP0_ERROREPC  (0x10000 + (8 * 30) + 0)
> +
> +inline int kvm_mips_put_one_reg(CPUState *cs, int reg_id, int32 *addr)
> +{
> +    __u64 val64 = (__u64)*addr;
> +    struct kvm_one_reg cp0reg = {
> +        .id = reg_id,
> +        .addr = (__u64)((target_ulong)&val64)
> +    };
> +
> +    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
> +}
> +
> +inline int kvm_mips_put_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr)
> +{
> +    __u64 val64 = (__u64)*addr;
> +    struct kvm_one_reg cp0reg = {
> +        .id = reg_id,
> +        .addr = (__u64)((target_ulong)&val64)
> +    };
> +
> +    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
> +}
> +
> +inline int kvm_mips_get_one_reg(CPUState *cs, int reg_id, int32 *addr)
> +{
> +    int ret;
> +    __u64 val64 = 0;
> +    struct kvm_one_reg cp0reg = {
> +        .id = reg_id,
> +        .addr = (__u64)((target_ulong)&val64)
> +    };
> +
> +    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +
> +    *addr = (int32)val64;
> +    return ret;
> +}
> +
> +inline int kvm_mips_get_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr)
> +{
> +    int ret;
> +    __u64 val64 = 0;
> +    struct kvm_one_reg cp0reg = {
> +        .id = reg_id,
> +        .addr = (__u64)((target_ulong)&val64)
> +    };
> +
> +    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +
> +    *addr = (target_ulong)val64;
> +    return ret;
> +}
> +
> +int kvm_mips_te_put_cp0_registers(CPUState *cs, int level)
> +{
> +    MIPSCPU *cpu = MIPS_CPU(cs);
> +    CPUMIPSState *env = &cpu->env;
> +    int ret;
> +
> +    (void)level;
> +
> +    ret = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
> +                                  &env->CP0_Context);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK,
> +                                &env->CP0_PageMask);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR,
> +                                  &env->CP0_BadVAddr);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI,
> +                                  &env->CP0_EntryHi);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE,
> +                                &env->CP0_Compare);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
> +                                  &env->CP0_ErrorEPC);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +
> +    return ret;
> +}
> +
> +int kvm_mips_te_get_cp0_registers(CPUState *cs)
> +{
> +    MIPSCPU *cpu = MIPS_CPU(cs);
> +    CPUMIPSState *env = &cpu->env;
> +    int ret;
> +
> +    ret = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
> +                                  &env->CP0_Context);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK,
> +                                &env->CP0_PageMask);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR,
> +                                  &env->CP0_BadVAddr);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI,
> +                                  &env->CP0_EntryHi);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE,
> +                                &env->CP0_Compare);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
> +                                  &env->CP0_ErrorEPC);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +
> +    return ret;
> +}
> diff --git a/target-mips/kvm_mips.h b/target-mips/kvm_mips.h
> new file mode 100644
> index 0000000..0da4edf
> --- /dev/null
> +++ b/target-mips/kvm_mips.h
> @@ -0,0 +1,28 @@
> +/*
> + * 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-2013 Imagination Technologies Ltd.
> + * Authors: Sanjay Lal <sanjayl@kymasys.com>
> +*/
> +
> +#ifndef __KVM_MIPS_H__
> +#define __KVM_MIPS_H__
> +
> +
> +int kvm_mips_set_interrupt(CPUMIPSState *env, int irq, int level);
> +
> +int kvm_mips_set_ipi_interrupt(CPUArchState *env, int irq, int level);
> +
> +inline int kvm_mips_put_one_reg(CPUState *cs, int reg_id, int32 *addr);
> +inline int kvm_mips_put_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr);
> +inline int kvm_mips_get_one_reg(CPUState *cs, int reg_id, int32 *addr);
> +inline int kvm_mips_get_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr);
> +
> +int kvm_mips_te_put_cp0_registers(CPUState *cs, int level);
> +int kvm_mips_te_get_cp0_registers(CPUState *cs);
> +
> +#endif /* __KVM_MIPS_H__ */

This doesn't look bad, but I don't have a good enough knowledge of KVM
to review this patch.


-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 07/10] target-mips: kvm: Add main KVM support for MIPS
@ 2013-12-21 15:35     ` Aurelien Jarno
  0 siblings, 0 replies; 58+ messages in thread
From: Aurelien Jarno @ 2013-12-21 15:35 UTC (permalink / raw)
  To: James Hogan; +Cc: Paolo Bonzini, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

On Mon, Dec 16, 2013 at 02:12:42PM +0000, James Hogan wrote:
> 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>
> ---
> Changes in v2:
>  - Expand commit message
>  - Checkpatch cleanups.
>  - Some interrupt bug fixes from Yann Le Du <ledu@kymasys.com>
>  - Add get/set register functionality from Yann Le Du <ledu@kymasys.com>
>  - Use new 64 bit compatible ABI from Cavium from Sanjay Lal
>    <sanjayl@kymasys.com>
>  - Add dummy kvm_arch_init_irq_routing()
>    The common KVM code insists on calling kvm_arch_init_irq_routing() as
>    soon as it sees kernel header support for it (regardless of whether
>    QEMU supports it). Provide a dummy function to satisfy this.
>  - Remove request_interrupt_window code (Peter Maydell)
> ---
>  target-mips/kvm.c      | 463 +++++++++++++++++++++++++++++++++++++++++++++++++
>  target-mips/kvm_mips.h |  28 +++
>  2 files changed, 491 insertions(+)
>  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..951959b
> --- /dev/null
> +++ b/target-mips/kvm.c
> @@ -0,0 +1,463 @@
> +/*
> + * 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-2013 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/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
> +};
> +
> +unsigned long kvm_arch_vcpu_id(CPUState *cpu)
> +{
> +    return cpu->cpu_index;
> +}
> +
> +int kvm_arch_init(KVMState *s)
> +{
> +    dprintf("%s\n", __func__);
> +    return 0;
> +}
> +
> +int kvm_arch_init_vcpu(CPUState *env)
> +{
> +    int ret = 0;
> +    dprintf("%s\n", __func__);
> +    return ret;
> +}
> +
> +void kvm_arch_reset_vcpu(CPUState *env)
> +{
> +    dprintf("%s\n", __func__);
> +}
> +
> +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_te_put_cp0_registers(cs, KVM_PUT_FULL_STATE);
> +    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_te_get_cp0_registers(cs);
> +
> +    return ret;
> +}
> +
> +int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
> +{
> +    dprintf("%s\n", __func__);
> +    return 0;
> +}
> +
> +int kvm_arch_remove_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
> +{
> +    dprintf("%s\n", __func__);
> +    return 0;
> +}
> +
> +static inline int cpu_mips_io_interrupts_pending(CPUArchState *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);
> +    CPUMIPSState *env = &cpu->env;
> +    int r;
> +    struct kvm_mips_interrupt intr;
> +
> +    if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
> +            (cpu_mips_io_interrupts_pending(env))) {
> +        intr.cpu = -1;
> +        intr.irq = 2;
> +        r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
> +        if (r < 0) {
> +            printf("cpu %d fail inject %x\n", cs->cpu_index, intr.irq);
> +        }
> +    }
> +}
> +
> +void kvm_arch_post_run(CPUState *env, 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 *env, struct kvm_run *run)
> +{
> +    int ret;
> +
> +    dprintf("%s\n", __func__);
> +    switch (run->exit_reason) {
> +    default:
> +        fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
> +        ret = -1;
> +        break;
> +    }
> +
> +    return ret;
> +}
> +
> +bool kvm_arch_stop_on_emulation_error(CPUState *env)
> +{
> +    dprintf("%s\n", __func__);
> +    return true;
> +}
> +
> +int kvm_arch_on_sigbus_vcpu(CPUState *env, 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(CPUMIPSState *env, int irq, int level)
> +{
> +    CPUState *cs = ENV_GET_CPU(env);
> +    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(CPUArchState *env, int irq, int level)
> +{
> +    CPUState *cs = current_cpu;
> +    CPUState *dest_cs = ENV_GET_CPU(env);
> +    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 KVM_REG_MIPS_CP0_INDEX     (0x10000 + (8 *  0) + 0)
> +#define KVM_REG_MIPS_CP0_ENTRYLO0  (0x10000 + (8 *  2) + 0)
> +#define KVM_REG_MIPS_CP0_ENTRYLO1  (0x10000 + (8 *  3) + 0)
> +#define KVM_REG_MIPS_CP0_CONTEXT   (0x10000 + (8 *  4) + 0)
> +#define KVM_REG_MIPS_CP0_USERLOCAL (0x10000 + (8 *  4) + 2)
> +#define KVM_REG_MIPS_CP0_PAGEMASK  (0x10000 + (8 *  5) + 0)
> +#define KVM_REG_MIPS_CP0_PAGEGRAIN (0x10000 + (8 *  5) + 1)
> +#define KVM_REG_MIPS_CP0_WIRED     (0x10000 + (8 *  6) + 0)
> +#define KVM_REG_MIPS_CP0_HWRENA    (0x10000 + (8 *  7) + 0)
> +#define KVM_REG_MIPS_CP0_BADVADDR  (0x10000 + (8 *  8) + 0)
> +#define KVM_REG_MIPS_CP0_COUNT     (0x10000 + (8 *  9) + 0)
> +#define KVM_REG_MIPS_CP0_ENTRYHI   (0x10000 + (8 * 10) + 0)
> +#define KVM_REG_MIPS_CP0_COMPARE   (0x10000 + (8 * 11) + 0)
> +#define KVM_REG_MIPS_CP0_STATUS    (0x10000 + (8 * 12) + 0)
> +#define KVM_REG_MIPS_CP0_INTCTL    (0x10000 + (8 * 12) + 1)
> +#define KVM_REG_MIPS_CP0_CAUSE     (0x10000 + (8 * 13) + 0)
> +#define KVM_REG_MIPS_CP0_EPC       (0x10000 + (8 * 14) + 0)
> +#define KVM_REG_MIPS_CP0_PRID      (0x10000 + (8 * 15) + 0)
> +#define KVM_REG_MIPS_CP0_EBASE     (0x10000 + (8 * 15) + 1)
> +#define KVM_REG_MIPS_CP0_CONFIG    (0x10000 + (8 * 16) + 0)
> +#define KVM_REG_MIPS_CP0_CONFIG1   (0x10000 + (8 * 16) + 1)
> +#define KVM_REG_MIPS_CP0_CONFIG2   (0x10000 + (8 * 16) + 2)
> +#define KVM_REG_MIPS_CP0_CONFIG3   (0x10000 + (8 * 16) + 3)
> +#define KVM_REG_MIPS_CP0_CONFIG4   (0x10000 + (8 * 16) + 4)
> +#define KVM_REG_MIPS_CP0_CONFIG5   (0x10000 + (8 * 16) + 5)
> +#define KVM_REG_MIPS_CP0_CONFIG7   (0x10000 + (8 * 16) + 7)
> +#define KVM_REG_MIPS_CP0_XCONTEXT  (0x10000 + (8 * 20) + 0)
> +#define KVM_REG_MIPS_CP0_ERROREPC  (0x10000 + (8 * 30) + 0)
> +
> +inline int kvm_mips_put_one_reg(CPUState *cs, int reg_id, int32 *addr)
> +{
> +    __u64 val64 = (__u64)*addr;
> +    struct kvm_one_reg cp0reg = {
> +        .id = reg_id,
> +        .addr = (__u64)((target_ulong)&val64)
> +    };
> +
> +    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
> +}
> +
> +inline int kvm_mips_put_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr)
> +{
> +    __u64 val64 = (__u64)*addr;
> +    struct kvm_one_reg cp0reg = {
> +        .id = reg_id,
> +        .addr = (__u64)((target_ulong)&val64)
> +    };
> +
> +    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
> +}
> +
> +inline int kvm_mips_get_one_reg(CPUState *cs, int reg_id, int32 *addr)
> +{
> +    int ret;
> +    __u64 val64 = 0;
> +    struct kvm_one_reg cp0reg = {
> +        .id = reg_id,
> +        .addr = (__u64)((target_ulong)&val64)
> +    };
> +
> +    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +
> +    *addr = (int32)val64;
> +    return ret;
> +}
> +
> +inline int kvm_mips_get_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr)
> +{
> +    int ret;
> +    __u64 val64 = 0;
> +    struct kvm_one_reg cp0reg = {
> +        .id = reg_id,
> +        .addr = (__u64)((target_ulong)&val64)
> +    };
> +
> +    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +
> +    *addr = (target_ulong)val64;
> +    return ret;
> +}
> +
> +int kvm_mips_te_put_cp0_registers(CPUState *cs, int level)
> +{
> +    MIPSCPU *cpu = MIPS_CPU(cs);
> +    CPUMIPSState *env = &cpu->env;
> +    int ret;
> +
> +    (void)level;
> +
> +    ret = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
> +                                  &env->CP0_Context);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK,
> +                                &env->CP0_PageMask);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR,
> +                                  &env->CP0_BadVAddr);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI,
> +                                  &env->CP0_EntryHi);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE,
> +                                &env->CP0_Compare);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
> +                                  &env->CP0_ErrorEPC);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +
> +    return ret;
> +}
> +
> +int kvm_mips_te_get_cp0_registers(CPUState *cs)
> +{
> +    MIPSCPU *cpu = MIPS_CPU(cs);
> +    CPUMIPSState *env = &cpu->env;
> +    int ret;
> +
> +    ret = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
> +                                  &env->CP0_Context);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK,
> +                                &env->CP0_PageMask);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR,
> +                                  &env->CP0_BadVAddr);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI,
> +                                  &env->CP0_EntryHi);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE,
> +                                &env->CP0_Compare);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
> +                                  &env->CP0_ErrorEPC);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +
> +    return ret;
> +}
> diff --git a/target-mips/kvm_mips.h b/target-mips/kvm_mips.h
> new file mode 100644
> index 0000000..0da4edf
> --- /dev/null
> +++ b/target-mips/kvm_mips.h
> @@ -0,0 +1,28 @@
> +/*
> + * 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-2013 Imagination Technologies Ltd.
> + * Authors: Sanjay Lal <sanjayl@kymasys.com>
> +*/
> +
> +#ifndef __KVM_MIPS_H__
> +#define __KVM_MIPS_H__
> +
> +
> +int kvm_mips_set_interrupt(CPUMIPSState *env, int irq, int level);
> +
> +int kvm_mips_set_ipi_interrupt(CPUArchState *env, int irq, int level);
> +
> +inline int kvm_mips_put_one_reg(CPUState *cs, int reg_id, int32 *addr);
> +inline int kvm_mips_put_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr);
> +inline int kvm_mips_get_one_reg(CPUState *cs, int reg_id, int32 *addr);
> +inline int kvm_mips_get_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr);
> +
> +int kvm_mips_te_put_cp0_registers(CPUState *cs, int level);
> +int kvm_mips_te_get_cp0_registers(CPUState *cs);
> +
> +#endif /* __KVM_MIPS_H__ */

This doesn't look bad, but I don't have a good enough knowledge of KVM
to review this patch.


-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH v2 09/10] hw/mips: malta: Add KVM support
  2013-12-16 14:12   ` [Qemu-devel] " James Hogan
@ 2013-12-21 15:37     ` Aurelien Jarno
  -1 siblings, 0 replies; 58+ messages in thread
From: Aurelien Jarno @ 2013-12-21 15:37 UTC (permalink / raw)
  To: James Hogan; +Cc: Paolo Bonzini, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

On Mon, Dec 16, 2013 at 02:12:44PM +0000, James Hogan wrote:
> 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>
> Cc: Aurelien Jarno <aurelien@aurel32.net>
> ---
> Changes in v2:
>  - Removal of cps / GIC / SMP support
>  - Minimal bootloader modified to execute safely from RAM
>  - Remove "Writing bootloader to final 1MB of RAM" printf
> ---
>  hw/mips/mips_malta.c | 85 ++++++++++++++++++++++++++++++++++++++--------------
>  1 file changed, 63 insertions(+), 22 deletions(-)
> 
> diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
> index 05c8771..3fff07c 100644
> --- a/hw/mips/mips_malta.c
> +++ b/hw/mips/mips_malta.c
> @@ -51,6 +51,10 @@
>  #include "sysemu/qtest.h"
>  #include "qemu/error-report.h"
>  #include "hw/empty_slot.h"
> +#include "qemu/bitmap.h"
> +#include "sysemu/kvm.h"
> +#include "linux/kvm.h"
> +#include "kvm_mips.h"
>  
>  //#define DEBUG_BOARD_INIT
>  
> @@ -603,29 +607,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_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
> +
> +    stl_raw(p++, 0x08000000 |                                      /* j 0x1fc00580 */
> +                 ((run_addr + 0x580) & 0x0fffffff) >> 2);
>      stl_raw(p++, 0x00000000);                                      /* nop */
>  
>      /* YAMON service vector */
> -    stl_raw(base + 0x500, 0xbfc00580);      /* start: */
> -    stl_raw(base + 0x504, 0xbfc0083c);      /* print_count: */
> -    stl_raw(base + 0x520, 0xbfc00580);      /* start: */
> -    stl_raw(base + 0x52c, 0xbfc00800);      /* flush_cache: */
> -    stl_raw(base + 0x534, 0xbfc00808);      /* print: */
> -    stl_raw(base + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
> -    stl_raw(base + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
> -    stl_raw(base + 0x540, 0xbfc00800);      /* reg_ic_isr: */
> -    stl_raw(base + 0x544, 0xbfc00800);      /* unred_ic_isr: */
> -    stl_raw(base + 0x548, 0xbfc00800);      /* reg_esr: */
> -    stl_raw(base + 0x54c, 0xbfc00800);      /* unreg_esr: */
> -    stl_raw(base + 0x550, 0xbfc00800);      /* getchar: */
> -    stl_raw(base + 0x554, 0xbfc00800);      /* syscon_read: */
> +    stl_raw(base + 0x500, run_addr + 0x0580);      /* start: */
> +    stl_raw(base + 0x504, run_addr + 0x083c);      /* print_count: */
> +    stl_raw(base + 0x520, run_addr + 0x0580);      /* start: */
> +    stl_raw(base + 0x52c, run_addr + 0x0800);      /* flush_cache: */
> +    stl_raw(base + 0x534, run_addr + 0x0808);      /* print: */
> +    stl_raw(base + 0x538, run_addr + 0x0800);      /* reg_cpu_isr: */
> +    stl_raw(base + 0x53c, run_addr + 0x0800);      /* unred_cpu_isr: */
> +    stl_raw(base + 0x540, run_addr + 0x0800);      /* reg_ic_isr: */
> +    stl_raw(base + 0x544, run_addr + 0x0800);      /* unred_ic_isr: */
> +    stl_raw(base + 0x548, run_addr + 0x0800);      /* reg_esr: */
> +    stl_raw(base + 0x54c, run_addr + 0x0800);      /* unreg_esr: */
> +    stl_raw(base + 0x550, run_addr + 0x0800);      /* getchar: */
> +    stl_raw(base + 0x554, run_addr + 0x0800);      /* syscon_read: */
>  
>  
>      /* Second part of the bootloader */
> @@ -701,7 +707,7 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base,
>      p = (uint32_t *) (base + 0x800);
>      stl_raw(p++, 0x03e00008);                                     /* jr ra */
>      stl_raw(p++, 0x24020000);                                     /* li v0,0 */
> -   /* 808 YAMON print */
> +    /* 808 YAMON print */
>      stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
>      stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
>      stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
> @@ -774,6 +780,9 @@ static int64_t load_kernel (void)
>      uint32_t *prom_buf;
>      long prom_size;
>      int prom_index = 0;
> +    uint64_t (*xlate_to_phys) (void *opaque, uint64_t addr);
> +    uint64_t (*xlate_to_kseg0) (void *opaque, uint64_t addr);
> +
>  
>  #ifdef TARGET_WORDS_BIGENDIAN
>      big_endian = 1;
> @@ -781,7 +790,15 @@ static int64_t load_kernel (void)
>      big_endian = 0;
>  #endif
>  
> -    if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
> +    if (kvm_enabled()) {
> +        xlate_to_phys = cpu_mips_kvm_um_kseg0_to_phys;
> +        xlate_to_kseg0 = cpu_mips_kvm_um_phys_to_kseg0;
> +    } else {
> +        xlate_to_phys = cpu_mips_kseg0_to_phys;
> +        xlate_to_kseg0 = cpu_mips_phys_to_kseg0;
> +    }
> +
> +    if (load_elf(loaderparams.kernel_filename, xlate_to_phys, NULL,
>                   (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
>                   big_endian, ELF_MACHINE, 1) < 0) {
>          fprintf(stderr, "qemu: could not load kernel '%s'\n",
> @@ -820,7 +837,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,12 +846,13 @@ 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);
>  
>      rom_add_blob_fixed("prom", prom_buf, prom_size,
> -                       cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR));
> +                       xlate_to_phys(NULL, ENVP_ADDR));
>  
>      return kernel_entry;
>  }
> @@ -863,6 +881,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 +901,7 @@ static
>  void mips_malta_init(QEMUMachineInitArgs *args)
>  {
>      ram_addr_t ram_size = args->ram_size;
> +    ram_addr_t ram_low_size;
>      const char *cpu_model = args->cpu_model;
>      const char *kernel_filename = args->kernel_filename;
>      const char *kernel_cmdline = args->kernel_cmdline;
> @@ -892,7 +916,7 @@ void mips_malta_init(QEMUMachineInitArgs *args)
>      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 +1035,30 @@ void mips_malta_init(QEMUMachineInitArgs *args)
>      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) {

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 09/10] hw/mips: malta: Add KVM support
@ 2013-12-21 15:37     ` Aurelien Jarno
  0 siblings, 0 replies; 58+ messages in thread
From: Aurelien Jarno @ 2013-12-21 15:37 UTC (permalink / raw)
  To: James Hogan; +Cc: Paolo Bonzini, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

On Mon, Dec 16, 2013 at 02:12:44PM +0000, James Hogan wrote:
> 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>
> Cc: Aurelien Jarno <aurelien@aurel32.net>
> ---
> Changes in v2:
>  - Removal of cps / GIC / SMP support
>  - Minimal bootloader modified to execute safely from RAM
>  - Remove "Writing bootloader to final 1MB of RAM" printf
> ---
>  hw/mips/mips_malta.c | 85 ++++++++++++++++++++++++++++++++++++++--------------
>  1 file changed, 63 insertions(+), 22 deletions(-)
> 
> diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
> index 05c8771..3fff07c 100644
> --- a/hw/mips/mips_malta.c
> +++ b/hw/mips/mips_malta.c
> @@ -51,6 +51,10 @@
>  #include "sysemu/qtest.h"
>  #include "qemu/error-report.h"
>  #include "hw/empty_slot.h"
> +#include "qemu/bitmap.h"
> +#include "sysemu/kvm.h"
> +#include "linux/kvm.h"
> +#include "kvm_mips.h"
>  
>  //#define DEBUG_BOARD_INIT
>  
> @@ -603,29 +607,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_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
> +
> +    stl_raw(p++, 0x08000000 |                                      /* j 0x1fc00580 */
> +                 ((run_addr + 0x580) & 0x0fffffff) >> 2);
>      stl_raw(p++, 0x00000000);                                      /* nop */
>  
>      /* YAMON service vector */
> -    stl_raw(base + 0x500, 0xbfc00580);      /* start: */
> -    stl_raw(base + 0x504, 0xbfc0083c);      /* print_count: */
> -    stl_raw(base + 0x520, 0xbfc00580);      /* start: */
> -    stl_raw(base + 0x52c, 0xbfc00800);      /* flush_cache: */
> -    stl_raw(base + 0x534, 0xbfc00808);      /* print: */
> -    stl_raw(base + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
> -    stl_raw(base + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
> -    stl_raw(base + 0x540, 0xbfc00800);      /* reg_ic_isr: */
> -    stl_raw(base + 0x544, 0xbfc00800);      /* unred_ic_isr: */
> -    stl_raw(base + 0x548, 0xbfc00800);      /* reg_esr: */
> -    stl_raw(base + 0x54c, 0xbfc00800);      /* unreg_esr: */
> -    stl_raw(base + 0x550, 0xbfc00800);      /* getchar: */
> -    stl_raw(base + 0x554, 0xbfc00800);      /* syscon_read: */
> +    stl_raw(base + 0x500, run_addr + 0x0580);      /* start: */
> +    stl_raw(base + 0x504, run_addr + 0x083c);      /* print_count: */
> +    stl_raw(base + 0x520, run_addr + 0x0580);      /* start: */
> +    stl_raw(base + 0x52c, run_addr + 0x0800);      /* flush_cache: */
> +    stl_raw(base + 0x534, run_addr + 0x0808);      /* print: */
> +    stl_raw(base + 0x538, run_addr + 0x0800);      /* reg_cpu_isr: */
> +    stl_raw(base + 0x53c, run_addr + 0x0800);      /* unred_cpu_isr: */
> +    stl_raw(base + 0x540, run_addr + 0x0800);      /* reg_ic_isr: */
> +    stl_raw(base + 0x544, run_addr + 0x0800);      /* unred_ic_isr: */
> +    stl_raw(base + 0x548, run_addr + 0x0800);      /* reg_esr: */
> +    stl_raw(base + 0x54c, run_addr + 0x0800);      /* unreg_esr: */
> +    stl_raw(base + 0x550, run_addr + 0x0800);      /* getchar: */
> +    stl_raw(base + 0x554, run_addr + 0x0800);      /* syscon_read: */
>  
>  
>      /* Second part of the bootloader */
> @@ -701,7 +707,7 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base,
>      p = (uint32_t *) (base + 0x800);
>      stl_raw(p++, 0x03e00008);                                     /* jr ra */
>      stl_raw(p++, 0x24020000);                                     /* li v0,0 */
> -   /* 808 YAMON print */
> +    /* 808 YAMON print */
>      stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
>      stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
>      stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
> @@ -774,6 +780,9 @@ static int64_t load_kernel (void)
>      uint32_t *prom_buf;
>      long prom_size;
>      int prom_index = 0;
> +    uint64_t (*xlate_to_phys) (void *opaque, uint64_t addr);
> +    uint64_t (*xlate_to_kseg0) (void *opaque, uint64_t addr);
> +
>  
>  #ifdef TARGET_WORDS_BIGENDIAN
>      big_endian = 1;
> @@ -781,7 +790,15 @@ static int64_t load_kernel (void)
>      big_endian = 0;
>  #endif
>  
> -    if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
> +    if (kvm_enabled()) {
> +        xlate_to_phys = cpu_mips_kvm_um_kseg0_to_phys;
> +        xlate_to_kseg0 = cpu_mips_kvm_um_phys_to_kseg0;
> +    } else {
> +        xlate_to_phys = cpu_mips_kseg0_to_phys;
> +        xlate_to_kseg0 = cpu_mips_phys_to_kseg0;
> +    }
> +
> +    if (load_elf(loaderparams.kernel_filename, xlate_to_phys, NULL,
>                   (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
>                   big_endian, ELF_MACHINE, 1) < 0) {
>          fprintf(stderr, "qemu: could not load kernel '%s'\n",
> @@ -820,7 +837,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,12 +846,13 @@ 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);
>  
>      rom_add_blob_fixed("prom", prom_buf, prom_size,
> -                       cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR));
> +                       xlate_to_phys(NULL, ENVP_ADDR));
>  
>      return kernel_entry;
>  }
> @@ -863,6 +881,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 +901,7 @@ static
>  void mips_malta_init(QEMUMachineInitArgs *args)
>  {
>      ram_addr_t ram_size = args->ram_size;
> +    ram_addr_t ram_low_size;
>      const char *cpu_model = args->cpu_model;
>      const char *kernel_filename = args->kernel_filename;
>      const char *kernel_cmdline = args->kernel_cmdline;
> @@ -892,7 +916,7 @@ void mips_malta_init(QEMUMachineInitArgs *args)
>      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 +1035,30 @@ void mips_malta_init(QEMUMachineInitArgs *args)
>      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) {

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH v2 10/10] target-mips: Enable KVM support in build system
  2013-12-16 14:12   ` [Qemu-devel] " James Hogan
@ 2013-12-21 15:38     ` Aurelien Jarno
  -1 siblings, 0 replies; 58+ messages in thread
From: Aurelien Jarno @ 2013-12-21 15:38 UTC (permalink / raw)
  To: James Hogan; +Cc: Paolo Bonzini, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

On Mon, Dec 16, 2013 at 02:12:45PM +0000, James Hogan wrote:
> 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>
> Cc: Aurelien Jarno <aurelien@aurel32.net>
> ---
> Changes in v2:
>  - Expand commit message
>  - Remove GIC code
>  - Create asm-mips symlink using generic code and move above default
>    case (Peter Maydell)
>  - Remove redundant check of target_name = cpu = mips
>  - Remove mipsel cross compilation fix, which is now fixed by
>    commit 61cc919f73ea (configure: detect endian via compile test)
> ---
>  configure                 | 6 +++++-
>  target-mips/Makefile.objs | 1 +
>  2 files changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/configure b/configure
> index 0666228..7d86eea 100755
> --- a/configure
> +++ b/configure
> @@ -4329,6 +4329,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"
> @@ -4518,7 +4521,7 @@ case "$target_name" in
>    *)
>  esac
>  case "$target_name" in
> -  arm|i386|x86_64|ppcemb|ppc|ppc64|s390x)
> +  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 \
> @@ -4526,6 +4529,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

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 10/10] target-mips: Enable KVM support in build system
@ 2013-12-21 15:38     ` Aurelien Jarno
  0 siblings, 0 replies; 58+ messages in thread
From: Aurelien Jarno @ 2013-12-21 15:38 UTC (permalink / raw)
  To: James Hogan; +Cc: Paolo Bonzini, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

On Mon, Dec 16, 2013 at 02:12:45PM +0000, James Hogan wrote:
> 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>
> Cc: Aurelien Jarno <aurelien@aurel32.net>
> ---
> Changes in v2:
>  - Expand commit message
>  - Remove GIC code
>  - Create asm-mips symlink using generic code and move above default
>    case (Peter Maydell)
>  - Remove redundant check of target_name = cpu = mips
>  - Remove mipsel cross compilation fix, which is now fixed by
>    commit 61cc919f73ea (configure: detect endian via compile test)
> ---
>  configure                 | 6 +++++-
>  target-mips/Makefile.objs | 1 +
>  2 files changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/configure b/configure
> index 0666228..7d86eea 100755
> --- a/configure
> +++ b/configure
> @@ -4329,6 +4329,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"
> @@ -4518,7 +4521,7 @@ case "$target_name" in
>    *)
>  esac
>  case "$target_name" in
> -  arm|i386|x86_64|ppcemb|ppc|ppc64|s390x)
> +  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 \
> @@ -4526,6 +4529,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

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH v2 08/10] hw/mips: In KVM mode, inject IRQ2 (I/O) interupts via ioctls
  2013-12-16 14:12   ` [Qemu-devel] " James Hogan
@ 2013-12-21 15:41     ` Aurelien Jarno
  -1 siblings, 0 replies; 58+ messages in thread
From: Aurelien Jarno @ 2013-12-21 15:41 UTC (permalink / raw)
  To: James Hogan; +Cc: Paolo Bonzini, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

On Mon, Dec 16, 2013 at 02:12:43PM +0000, James Hogan wrote:
> 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>
> Cc: Aurelien Jarno <aurelien@aurel32.net>
> ---
> Changes in v2:
>  - Expand commit message
>  - Remove #ifdef CONFIG_KVM since it's guarded by kvm_enabled() already
> ---
>  hw/mips/mips_int.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c
> index 7dbd24d..1b9981e 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(env, irq, level);
> +        }
> +
>      } else {
>          env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
> +
> +        if (kvm_enabled() && irq == 2) {
> +            kvm_mips_set_interrupt(env, irq, level);
> +        }
>      }
>  
>      if (env->CP0_Cause & CP0Ca_IP_mask) {

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 08/10] hw/mips: In KVM mode, inject IRQ2 (I/O) interupts via ioctls
@ 2013-12-21 15:41     ` Aurelien Jarno
  0 siblings, 0 replies; 58+ messages in thread
From: Aurelien Jarno @ 2013-12-21 15:41 UTC (permalink / raw)
  To: James Hogan; +Cc: Paolo Bonzini, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

On Mon, Dec 16, 2013 at 02:12:43PM +0000, James Hogan wrote:
> 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>
> Cc: Aurelien Jarno <aurelien@aurel32.net>
> ---
> Changes in v2:
>  - Expand commit message
>  - Remove #ifdef CONFIG_KVM since it's guarded by kvm_enabled() already
> ---
>  hw/mips/mips_int.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c
> index 7dbd24d..1b9981e 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(env, irq, level);
> +        }
> +
>      } else {
>          env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
> +
> +        if (kvm_enabled() && irq == 2) {
> +            kvm_mips_set_interrupt(env, irq, level);
> +        }
>      }
>  
>      if (env->CP0_Cause & CP0Ca_IP_mask) {

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH v2 10/10] target-mips: Enable KVM support in build system
  2013-12-16 14:12   ` [Qemu-devel] " James Hogan
@ 2013-12-21 18:59     ` Peter Maydell
  -1 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2013-12-21 18:59 UTC (permalink / raw)
  To: James Hogan
  Cc: kvm-devel, Gleb Natapov, QEMU Developers, Sanjay Lal,
	Paolo Bonzini, Aurelien Jarno

On 16 December 2013 14:12, James Hogan <james.hogan@imgtec.com> wrote:
> 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>
> Cc: Aurelien Jarno <aurelien@aurel32.net>
> ---
> Changes in v2:
>  - Expand commit message
>  - Remove GIC code
>  - Create asm-mips symlink using generic code and move above default
>    case (Peter Maydell)
>  - Remove redundant check of target_name = cpu = mips
>  - Remove mipsel cross compilation fix, which is now fixed by
>    commit 61cc919f73ea (configure: detect endian via compile test)
> ---
>  configure                 | 6 +++++-
>  target-mips/Makefile.objs | 1 +
>  2 files changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/configure b/configure
> index 0666228..7d86eea 100755
> --- a/configure
> +++ b/configure
> @@ -4329,6 +4329,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"
> @@ -4518,7 +4521,7 @@ case "$target_name" in
>    *)
>  esac
>  case "$target_name" in
> -  arm|i386|x86_64|ppcemb|ppc|ppc64|s390x)
> +  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 \
> @@ -4526,6 +4529,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

Really no support for mips64 or mips64el targets?

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v2 10/10] target-mips: Enable KVM support in build system
@ 2013-12-21 18:59     ` Peter Maydell
  0 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2013-12-21 18:59 UTC (permalink / raw)
  To: James Hogan
  Cc: kvm-devel, Gleb Natapov, QEMU Developers, Sanjay Lal,
	Paolo Bonzini, Aurelien Jarno

On 16 December 2013 14:12, James Hogan <james.hogan@imgtec.com> wrote:
> 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>
> Cc: Aurelien Jarno <aurelien@aurel32.net>
> ---
> Changes in v2:
>  - Expand commit message
>  - Remove GIC code
>  - Create asm-mips symlink using generic code and move above default
>    case (Peter Maydell)
>  - Remove redundant check of target_name = cpu = mips
>  - Remove mipsel cross compilation fix, which is now fixed by
>    commit 61cc919f73ea (configure: detect endian via compile test)
> ---
>  configure                 | 6 +++++-
>  target-mips/Makefile.objs | 1 +
>  2 files changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/configure b/configure
> index 0666228..7d86eea 100755
> --- a/configure
> +++ b/configure
> @@ -4329,6 +4329,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"
> @@ -4518,7 +4521,7 @@ case "$target_name" in
>    *)
>  esac
>  case "$target_name" in
> -  arm|i386|x86_64|ppcemb|ppc|ppc64|s390x)
> +  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 \
> @@ -4526,6 +4529,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

Really no support for mips64 or mips64el targets?

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v2 05/10] kvm: Set sigmask length to 16 for MIPS targets
  2013-12-16 14:12   ` [Qemu-devel] " James Hogan
@ 2013-12-21 20:18     ` Peter Maydell
  -1 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2013-12-21 20:18 UTC (permalink / raw)
  To: James Hogan
  Cc: QEMU Developers, kvm-devel, Gleb Natapov, Sanjay Lal,
	Paolo Bonzini, Aurelien Jarno

On 16 December 2013 14:12, James Hogan <james.hogan@imgtec.com> wrote:
> From: Sanjay Lal <sanjayl@kymasys.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 correct kvm_set_signal_mask to pass the correct sigmask->len to
> KVM_SET_SIGNAL_MASK.
>
> Signed-off-by: Sanjay Lal <sanjayl@kymasys.com>
> Signed-off-by: James Hogan <james.hogan@imgtec.com>
> Cc: Gleb Natapov <gleb@redhat.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> ---
> Changes in v2:
>  - Expand commit message
>  - Reword comment
> ---
>  kvm-all.c | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/kvm-all.c b/kvm-all.c
> index 4478969..c831326 100644
> --- a/kvm-all.c
> +++ b/kvm-all.c
> @@ -2044,7 +2044,12 @@ int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset)
>
>      sigmask = g_malloc(sizeof(*sigmask) + sizeof(*sigset));
>
> +#ifdef TARGET_MIPS
> +    /* MIPS has 128 signals */
> +    sigmask->len = 16;
> +#else
>      sigmask->len = 8;
> +#endif
>      memcpy(sigmask->sigset, sigset, sizeof(*sigset));
>      r = kvm_vcpu_ioctl(cpu, KVM_SET_SIGNAL_MASK, sigmask);
>      g_free(sigmask);

kvm-all.c is mostly free of TARGET_FOO ifdefs; I think maybe
it would be better to have the signal mask length be something
the target-specific code configures in kvm_arch_init().

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v2 05/10] kvm: Set sigmask length to 16 for MIPS targets
@ 2013-12-21 20:18     ` Peter Maydell
  0 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2013-12-21 20:18 UTC (permalink / raw)
  To: James Hogan
  Cc: kvm-devel, Gleb Natapov, QEMU Developers, Sanjay Lal,
	Paolo Bonzini, Aurelien Jarno

On 16 December 2013 14:12, James Hogan <james.hogan@imgtec.com> wrote:
> From: Sanjay Lal <sanjayl@kymasys.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 correct kvm_set_signal_mask to pass the correct sigmask->len to
> KVM_SET_SIGNAL_MASK.
>
> Signed-off-by: Sanjay Lal <sanjayl@kymasys.com>
> Signed-off-by: James Hogan <james.hogan@imgtec.com>
> Cc: Gleb Natapov <gleb@redhat.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> ---
> Changes in v2:
>  - Expand commit message
>  - Reword comment
> ---
>  kvm-all.c | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/kvm-all.c b/kvm-all.c
> index 4478969..c831326 100644
> --- a/kvm-all.c
> +++ b/kvm-all.c
> @@ -2044,7 +2044,12 @@ int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset)
>
>      sigmask = g_malloc(sizeof(*sigmask) + sizeof(*sigset));
>
> +#ifdef TARGET_MIPS
> +    /* MIPS has 128 signals */
> +    sigmask->len = 16;
> +#else
>      sigmask->len = 8;
> +#endif
>      memcpy(sigmask->sigset, sigset, sizeof(*sigset));
>      r = kvm_vcpu_ioctl(cpu, KVM_SET_SIGNAL_MASK, sigmask);
>      g_free(sigmask);

kvm-all.c is mostly free of TARGET_FOO ifdefs; I think maybe
it would be better to have the signal mask length be something
the target-specific code configures in kvm_arch_init().

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v2 08/10] hw/mips: In KVM mode, inject IRQ2 (I/O) interupts via ioctls
  2013-12-16 14:12   ` [Qemu-devel] " James Hogan
@ 2013-12-21 20:40     ` Peter Maydell
  -1 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2013-12-21 20:40 UTC (permalink / raw)
  To: James Hogan
  Cc: QEMU Developers, kvm-devel, Gleb Natapov, Sanjay Lal,
	Paolo Bonzini, Aurelien Jarno

On 16 December 2013 14:12, James Hogan <james.hogan@imgtec.com> wrote:
> 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>
> Cc: Aurelien Jarno <aurelien@aurel32.net>
> ---
> Changes in v2:
>  - Expand commit message
>  - Remove #ifdef CONFIG_KVM since it's guarded by kvm_enabled() already
> ---
>  hw/mips/mips_int.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
>
> diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c
> index 7dbd24d..1b9981e 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(env, irq, level);
> +        }
> +
>      } else {
>          env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
> +
> +        if (kvm_enabled() && irq == 2) {
> +            kvm_mips_set_interrupt(env, irq, level);
> +        }
>      }
>
>      if (env->CP0_Cause & CP0Ca_IP_mask) {

For ARM we got rid of the arm_cpu_pic functions (which were more
or less like these) completely, because we can just model CPU
interrupt lines as actual irq lines on the CPU object. See commits
7c1840b686e3 to b643e4b90bb0b. That's not necessary for
KVM support but it might be worth considering as a cleanup for
MIPS at some point: it helps to get the "is this kvm or tcg?" code
out of the device emulation stuff in hw/, and also means there's
less hw/ code grubbing around in CPUState.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v2 08/10] hw/mips: In KVM mode, inject IRQ2 (I/O) interupts via ioctls
@ 2013-12-21 20:40     ` Peter Maydell
  0 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2013-12-21 20:40 UTC (permalink / raw)
  To: James Hogan
  Cc: kvm-devel, Gleb Natapov, QEMU Developers, Sanjay Lal,
	Paolo Bonzini, Aurelien Jarno

On 16 December 2013 14:12, James Hogan <james.hogan@imgtec.com> wrote:
> 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>
> Cc: Aurelien Jarno <aurelien@aurel32.net>
> ---
> Changes in v2:
>  - Expand commit message
>  - Remove #ifdef CONFIG_KVM since it's guarded by kvm_enabled() already
> ---
>  hw/mips/mips_int.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
>
> diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c
> index 7dbd24d..1b9981e 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(env, irq, level);
> +        }
> +
>      } else {
>          env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
> +
> +        if (kvm_enabled() && irq == 2) {
> +            kvm_mips_set_interrupt(env, irq, level);
> +        }
>      }
>
>      if (env->CP0_Cause & CP0Ca_IP_mask) {

For ARM we got rid of the arm_cpu_pic functions (which were more
or less like these) completely, because we can just model CPU
interrupt lines as actual irq lines on the CPU object. See commits
7c1840b686e3 to b643e4b90bb0b. That's not necessary for
KVM support but it might be worth considering as a cleanup for
MIPS at some point: it helps to get the "is this kvm or tcg?" code
out of the device emulation stuff in hw/, and also means there's
less hw/ code grubbing around in CPUState.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v2 09/10] hw/mips: malta: Add KVM support
  2013-12-16 14:12   ` [Qemu-devel] " James Hogan
@ 2013-12-21 20:42     ` Peter Maydell
  -1 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2013-12-21 20:42 UTC (permalink / raw)
  To: James Hogan
  Cc: QEMU Developers, kvm-devel, Gleb Natapov, Sanjay Lal,
	Paolo Bonzini, Aurelien Jarno

On 16 December 2013 14:12, James Hogan <james.hogan@imgtec.com> wrote:
> 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>
> Cc: Aurelien Jarno <aurelien@aurel32.net>
> ---
> Changes in v2:
>  - Removal of cps / GIC / SMP support
>  - Minimal bootloader modified to execute safely from RAM
>  - Remove "Writing bootloader to final 1MB of RAM" printf
> ---
>  hw/mips/mips_malta.c | 85 ++++++++++++++++++++++++++++++++++++++--------------
>  1 file changed, 63 insertions(+), 22 deletions(-)
>
> diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
> index 05c8771..3fff07c 100644
> --- a/hw/mips/mips_malta.c
> +++ b/hw/mips/mips_malta.c
> @@ -51,6 +51,10 @@
>  #include "sysemu/qtest.h"
>  #include "qemu/error-report.h"
>  #include "hw/empty_slot.h"
> +#include "qemu/bitmap.h"
> +#include "sysemu/kvm.h"
> +#include "linux/kvm.h"

You can't include linux/kvm.h like this -- on Linux this will pull in
whatever the host's system kvm.h happens to be, and on non-Linux
it won't compile:

/Users/pm215/src/qemu/hw/mips/mips_malta.c:56:10: fatal error:
'linux/kvm.h' file not found
#include "linux/kvm.h"
         ^
1 error generated.


thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v2 09/10] hw/mips: malta: Add KVM support
@ 2013-12-21 20:42     ` Peter Maydell
  0 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2013-12-21 20:42 UTC (permalink / raw)
  To: James Hogan
  Cc: kvm-devel, Gleb Natapov, QEMU Developers, Sanjay Lal,
	Paolo Bonzini, Aurelien Jarno

On 16 December 2013 14:12, James Hogan <james.hogan@imgtec.com> wrote:
> 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>
> Cc: Aurelien Jarno <aurelien@aurel32.net>
> ---
> Changes in v2:
>  - Removal of cps / GIC / SMP support
>  - Minimal bootloader modified to execute safely from RAM
>  - Remove "Writing bootloader to final 1MB of RAM" printf
> ---
>  hw/mips/mips_malta.c | 85 ++++++++++++++++++++++++++++++++++++++--------------
>  1 file changed, 63 insertions(+), 22 deletions(-)
>
> diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
> index 05c8771..3fff07c 100644
> --- a/hw/mips/mips_malta.c
> +++ b/hw/mips/mips_malta.c
> @@ -51,6 +51,10 @@
>  #include "sysemu/qtest.h"
>  #include "qemu/error-report.h"
>  #include "hw/empty_slot.h"
> +#include "qemu/bitmap.h"
> +#include "sysemu/kvm.h"
> +#include "linux/kvm.h"

You can't include linux/kvm.h like this -- on Linux this will pull in
whatever the host's system kvm.h happens to be, and on non-Linux
it won't compile:

/Users/pm215/src/qemu/hw/mips/mips_malta.c:56:10: fatal error:
'linux/kvm.h' file not found
#include "linux/kvm.h"
         ^
1 error generated.


thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v2 10/10] target-mips: Enable KVM support in build system
  2013-12-21 18:59     ` [Qemu-devel] " Peter Maydell
@ 2013-12-23 12:31       ` James Hogan
  -1 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-23 12:31 UTC (permalink / raw)
  To: Peter Maydell
  Cc: QEMU Developers, kvm-devel, Gleb Natapov, Sanjay Lal,
	Paolo Bonzini, Aurelien Jarno

Hi Peter,

On 21/12/13 18:59, Peter Maydell wrote:
>> @@ -4526,6 +4529,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
> 
> Really no support for mips64 or mips64el targets?

At present the MIPS Linux kernel only supports KVM T&E for MIPS32r2. I
would expect that to change eventually.

Thanks
James


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

* Re: [Qemu-devel] [PATCH v2 10/10] target-mips: Enable KVM support in build system
@ 2013-12-23 12:31       ` James Hogan
  0 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2013-12-23 12:31 UTC (permalink / raw)
  To: Peter Maydell
  Cc: kvm-devel, Gleb Natapov, QEMU Developers, Sanjay Lal,
	Paolo Bonzini, Aurelien Jarno

Hi Peter,

On 21/12/13 18:59, Peter Maydell wrote:
>> @@ -4526,6 +4529,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
> 
> Really no support for mips64 or mips64el targets?

At present the MIPS Linux kernel only supports KVM T&E for MIPS32r2. I
would expect that to change eventually.

Thanks
James

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

* Re: [Qemu-devel] [PATCH v2 07/10] target-mips: kvm: Add main KVM support for MIPS
  2013-12-16 14:12   ` [Qemu-devel] " James Hogan
@ 2014-02-10 14:07     ` Andreas Färber
  -1 siblings, 0 replies; 58+ messages in thread
From: Andreas Färber @ 2014-02-10 14:07 UTC (permalink / raw)
  To: James Hogan, qemu-devel
  Cc: kvm, Gleb Natapov, Sanjay Lal, Paolo Bonzini, Aurelien Jarno

Am 16.12.2013 15:12, schrieb James Hogan:
> 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>
> ---
> Changes in v2:
>  - Expand commit message
>  - Checkpatch cleanups.
>  - Some interrupt bug fixes from Yann Le Du <ledu@kymasys.com>
>  - Add get/set register functionality from Yann Le Du <ledu@kymasys.com>
>  - Use new 64 bit compatible ABI from Cavium from Sanjay Lal
>    <sanjayl@kymasys.com>
>  - Add dummy kvm_arch_init_irq_routing()
>    The common KVM code insists on calling kvm_arch_init_irq_routing() as
>    soon as it sees kernel header support for it (regardless of whether
>    QEMU supports it). Provide a dummy function to satisfy this.
>  - Remove request_interrupt_window code (Peter Maydell)
> ---
>  target-mips/kvm.c      | 463 +++++++++++++++++++++++++++++++++++++++++++++++++
>  target-mips/kvm_mips.h |  28 +++
>  2 files changed, 491 insertions(+)
>  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..951959b
> --- /dev/null
> +++ b/target-mips/kvm.c
> @@ -0,0 +1,463 @@
> +/*
> + * 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-2013 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/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, ...) \

dprintf is the name of a stdio.h function, so DPRINTF may be a better name.

> +    do { if (DEBUG_KVM) { fprintf(stderr, fmt, ## __VA_ARGS__); } } while (0)

This looks really modern, thanks. :)

> +
> +const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
> +    KVM_CAP_LAST_INFO
> +};
> +
> +unsigned long kvm_arch_vcpu_id(CPUState *cpu)
> +{
> +    return cpu->cpu_index;
> +}
> +
> +int kvm_arch_init(KVMState *s)
> +{
> +    dprintf("%s\n", __func__);
> +    return 0;
> +}
> +
> +int kvm_arch_init_vcpu(CPUState *env)

Please use "env" only for CPUMIPSState, use "cpu" or "cs" here. The
usual convention is "cs" for CPUState in target-*/ so that "cpu" can be
used for MIPSCPU.

> +{
> +    int ret = 0;
> +    dprintf("%s\n", __func__);
> +    return ret;
> +}
> +
> +void kvm_arch_reset_vcpu(CPUState *env)

Dito.

> +{
> +    dprintf("%s\n", __func__);
> +}
> +
> +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_te_put_cp0_registers(cs, KVM_PUT_FULL_STATE);
> +    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_te_get_cp0_registers(cs);
> +
> +    return ret;
> +}
> +
> +int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)

Dito.

> +{
> +    dprintf("%s\n", __func__);
> +    return 0;
> +}
> +
> +int kvm_arch_remove_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)

Dito.

> +{
> +    dprintf("%s\n", __func__);
> +    return 0;
> +}
> +
> +static inline int cpu_mips_io_interrupts_pending(CPUArchState *env)

Please don't use CPUArchState in MIPS-specific code, use CPUMIPSState.
Although in this trivial case MIPSCPU would be more future-proof.

> +{
> +    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);
> +    CPUMIPSState *env = &cpu->env;
> +    int r;
> +    struct kvm_mips_interrupt intr;
> +
> +    if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
> +            (cpu_mips_io_interrupts_pending(env))) {

Parentheses around cpu_mips_io_interrupts_pending() seem unnecessary
here FWIW.

> +        intr.cpu = -1;
> +        intr.irq = 2;
> +        r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
> +        if (r < 0) {
> +            printf("cpu %d fail inject %x\n", cs->cpu_index, intr.irq);

Should this really be a printf() rather than error_report() or trace point?

> +        }
> +    }
> +}
> +
> +void kvm_arch_post_run(CPUState *env, struct kvm_run *run)

"cs"

> +{
> +    dprintf("%s\n", __func__);
> +}
> +
> +int kvm_arch_process_async_events(CPUState *cs)
> +{
> +    return cs->halted;
> +}
> +
> +int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)

"cs"

> +{
> +    int ret;
> +
> +    dprintf("%s\n", __func__);
> +    switch (run->exit_reason) {
> +    default:
> +        fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);

error_report() and in that case without trailing \n.

> +        ret = -1;
> +        break;
> +    }
> +
> +    return ret;
> +}
> +
> +bool kvm_arch_stop_on_emulation_error(CPUState *env)

"cs"

> +{
> +    dprintf("%s\n", __func__);
> +    return true;
> +}
> +
> +int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr)

"cs"

> +{
> +    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(CPUMIPSState *env, int irq, int level)
> +{
> +    CPUState *cs = ENV_GET_CPU(env);

CPU(mips_env_get_cpu(env)) please - ENV_GET_CPU() is for generic code
only and supposed to go away.

Any chance a MIPSCPU *cpu (or CPUState *cs) argument can be used instead?

> +    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(CPUArchState *env, int irq, int level)
> +{
> +    CPUState *cs = current_cpu;
> +    CPUState *dest_cs = ENV_GET_CPU(env);

Similar question here.

> +    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 KVM_REG_MIPS_CP0_INDEX     (0x10000 + (8 *  0) + 0)
> +#define KVM_REG_MIPS_CP0_ENTRYLO0  (0x10000 + (8 *  2) + 0)
> +#define KVM_REG_MIPS_CP0_ENTRYLO1  (0x10000 + (8 *  3) + 0)
> +#define KVM_REG_MIPS_CP0_CONTEXT   (0x10000 + (8 *  4) + 0)
> +#define KVM_REG_MIPS_CP0_USERLOCAL (0x10000 + (8 *  4) + 2)
> +#define KVM_REG_MIPS_CP0_PAGEMASK  (0x10000 + (8 *  5) + 0)
> +#define KVM_REG_MIPS_CP0_PAGEGRAIN (0x10000 + (8 *  5) + 1)
> +#define KVM_REG_MIPS_CP0_WIRED     (0x10000 + (8 *  6) + 0)
> +#define KVM_REG_MIPS_CP0_HWRENA    (0x10000 + (8 *  7) + 0)
> +#define KVM_REG_MIPS_CP0_BADVADDR  (0x10000 + (8 *  8) + 0)
> +#define KVM_REG_MIPS_CP0_COUNT     (0x10000 + (8 *  9) + 0)
> +#define KVM_REG_MIPS_CP0_ENTRYHI   (0x10000 + (8 * 10) + 0)
> +#define KVM_REG_MIPS_CP0_COMPARE   (0x10000 + (8 * 11) + 0)
> +#define KVM_REG_MIPS_CP0_STATUS    (0x10000 + (8 * 12) + 0)
> +#define KVM_REG_MIPS_CP0_INTCTL    (0x10000 + (8 * 12) + 1)
> +#define KVM_REG_MIPS_CP0_CAUSE     (0x10000 + (8 * 13) + 0)
> +#define KVM_REG_MIPS_CP0_EPC       (0x10000 + (8 * 14) + 0)
> +#define KVM_REG_MIPS_CP0_PRID      (0x10000 + (8 * 15) + 0)
> +#define KVM_REG_MIPS_CP0_EBASE     (0x10000 + (8 * 15) + 1)
> +#define KVM_REG_MIPS_CP0_CONFIG    (0x10000 + (8 * 16) + 0)
> +#define KVM_REG_MIPS_CP0_CONFIG1   (0x10000 + (8 * 16) + 1)
> +#define KVM_REG_MIPS_CP0_CONFIG2   (0x10000 + (8 * 16) + 2)
> +#define KVM_REG_MIPS_CP0_CONFIG3   (0x10000 + (8 * 16) + 3)
> +#define KVM_REG_MIPS_CP0_CONFIG4   (0x10000 + (8 * 16) + 4)
> +#define KVM_REG_MIPS_CP0_CONFIG5   (0x10000 + (8 * 16) + 5)
> +#define KVM_REG_MIPS_CP0_CONFIG7   (0x10000 + (8 * 16) + 7)
> +#define KVM_REG_MIPS_CP0_XCONTEXT  (0x10000 + (8 * 20) + 0)
> +#define KVM_REG_MIPS_CP0_ERROREPC  (0x10000 + (8 * 30) + 0)
> +
> +inline int kvm_mips_put_one_reg(CPUState *cs, int reg_id, int32 *addr)
> +{
> +    __u64 val64 = (__u64)*addr;
> +    struct kvm_one_reg cp0reg = {
> +        .id = reg_id,
> +        .addr = (__u64)((target_ulong)&val64)
> +    };
> +
> +    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
> +}
> +
> +inline int kvm_mips_put_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr)
> +{
> +    __u64 val64 = (__u64)*addr;
> +    struct kvm_one_reg cp0reg = {
> +        .id = reg_id,
> +        .addr = (__u64)((target_ulong)&val64)
> +    };
> +
> +    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
> +}
> +
> +inline int kvm_mips_get_one_reg(CPUState *cs, int reg_id, int32 *addr)
> +{
> +    int ret;
> +    __u64 val64 = 0;
> +    struct kvm_one_reg cp0reg = {
> +        .id = reg_id,
> +        .addr = (__u64)((target_ulong)&val64)
> +    };
> +
> +    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +
> +    *addr = (int32)val64;
> +    return ret;
> +}
> +
> +inline int kvm_mips_get_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr)
> +{
> +    int ret;
> +    __u64 val64 = 0;
> +    struct kvm_one_reg cp0reg = {
> +        .id = reg_id,
> +        .addr = (__u64)((target_ulong)&val64)
> +    };
> +
> +    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +
> +    *addr = (target_ulong)val64;
> +    return ret;
> +}
> +
> +int kvm_mips_te_put_cp0_registers(CPUState *cs, int level)
> +{
> +    MIPSCPU *cpu = MIPS_CPU(cs);
> +    CPUMIPSState *env = &cpu->env;
> +    int ret;
> +
> +    (void)level;
> +
> +    ret = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
> +                                  &env->CP0_Context);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK,
> +                                &env->CP0_PageMask);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR,
> +                                  &env->CP0_BadVAddr);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI,
> +                                  &env->CP0_EntryHi);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE,
> +                                &env->CP0_Compare);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
> +                                  &env->CP0_ErrorEPC);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +
> +    return ret;
> +}
> +
> +int kvm_mips_te_get_cp0_registers(CPUState *cs)
> +{
> +    MIPSCPU *cpu = MIPS_CPU(cs);
> +    CPUMIPSState *env = &cpu->env;
> +    int ret;
> +
> +    ret = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
> +                                  &env->CP0_Context);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK,
> +                                &env->CP0_PageMask);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR,
> +                                  &env->CP0_BadVAddr);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI,
> +                                  &env->CP0_EntryHi);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE,
> +                                &env->CP0_Compare);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
> +                                  &env->CP0_ErrorEPC);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +
> +    return ret;
> +}
> diff --git a/target-mips/kvm_mips.h b/target-mips/kvm_mips.h
> new file mode 100644
> index 0000000..0da4edf
> --- /dev/null
> +++ b/target-mips/kvm_mips.h
> @@ -0,0 +1,28 @@
> +/*
> + * 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-2013 Imagination Technologies Ltd.
> + * Authors: Sanjay Lal <sanjayl@kymasys.com>
> +*/
> +
> +#ifndef __KVM_MIPS_H__
> +#define __KVM_MIPS_H__
> +
> +
> +int kvm_mips_set_interrupt(CPUMIPSState *env, int irq, int level);
> +
> +int kvm_mips_set_ipi_interrupt(CPUArchState *env, int irq, int level);
> +
> +inline int kvm_mips_put_one_reg(CPUState *cs, int reg_id, int32 *addr);
> +inline int kvm_mips_put_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr);
> +inline int kvm_mips_get_one_reg(CPUState *cs, int reg_id, int32 *addr);
> +inline int kvm_mips_get_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr);
> +
> +int kvm_mips_te_put_cp0_registers(CPUState *cs, int level);
> +int kvm_mips_te_get_cp0_registers(CPUState *cs);
> +
> +#endif /* __KVM_MIPS_H__ */

Regards,
Andreas

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

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

* Re: [Qemu-devel] [PATCH v2 07/10] target-mips: kvm: Add main KVM support for MIPS
@ 2014-02-10 14:07     ` Andreas Färber
  0 siblings, 0 replies; 58+ messages in thread
From: Andreas Färber @ 2014-02-10 14:07 UTC (permalink / raw)
  To: James Hogan, qemu-devel
  Cc: Sanjay Lal, Aurelien Jarno, Gleb Natapov, kvm, Paolo Bonzini

Am 16.12.2013 15:12, schrieb James Hogan:
> 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>
> ---
> Changes in v2:
>  - Expand commit message
>  - Checkpatch cleanups.
>  - Some interrupt bug fixes from Yann Le Du <ledu@kymasys.com>
>  - Add get/set register functionality from Yann Le Du <ledu@kymasys.com>
>  - Use new 64 bit compatible ABI from Cavium from Sanjay Lal
>    <sanjayl@kymasys.com>
>  - Add dummy kvm_arch_init_irq_routing()
>    The common KVM code insists on calling kvm_arch_init_irq_routing() as
>    soon as it sees kernel header support for it (regardless of whether
>    QEMU supports it). Provide a dummy function to satisfy this.
>  - Remove request_interrupt_window code (Peter Maydell)
> ---
>  target-mips/kvm.c      | 463 +++++++++++++++++++++++++++++++++++++++++++++++++
>  target-mips/kvm_mips.h |  28 +++
>  2 files changed, 491 insertions(+)
>  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..951959b
> --- /dev/null
> +++ b/target-mips/kvm.c
> @@ -0,0 +1,463 @@
> +/*
> + * 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-2013 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/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, ...) \

dprintf is the name of a stdio.h function, so DPRINTF may be a better name.

> +    do { if (DEBUG_KVM) { fprintf(stderr, fmt, ## __VA_ARGS__); } } while (0)

This looks really modern, thanks. :)

> +
> +const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
> +    KVM_CAP_LAST_INFO
> +};
> +
> +unsigned long kvm_arch_vcpu_id(CPUState *cpu)
> +{
> +    return cpu->cpu_index;
> +}
> +
> +int kvm_arch_init(KVMState *s)
> +{
> +    dprintf("%s\n", __func__);
> +    return 0;
> +}
> +
> +int kvm_arch_init_vcpu(CPUState *env)

Please use "env" only for CPUMIPSState, use "cpu" or "cs" here. The
usual convention is "cs" for CPUState in target-*/ so that "cpu" can be
used for MIPSCPU.

> +{
> +    int ret = 0;
> +    dprintf("%s\n", __func__);
> +    return ret;
> +}
> +
> +void kvm_arch_reset_vcpu(CPUState *env)

Dito.

> +{
> +    dprintf("%s\n", __func__);
> +}
> +
> +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_te_put_cp0_registers(cs, KVM_PUT_FULL_STATE);
> +    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_te_get_cp0_registers(cs);
> +
> +    return ret;
> +}
> +
> +int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)

Dito.

> +{
> +    dprintf("%s\n", __func__);
> +    return 0;
> +}
> +
> +int kvm_arch_remove_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)

Dito.

> +{
> +    dprintf("%s\n", __func__);
> +    return 0;
> +}
> +
> +static inline int cpu_mips_io_interrupts_pending(CPUArchState *env)

Please don't use CPUArchState in MIPS-specific code, use CPUMIPSState.
Although in this trivial case MIPSCPU would be more future-proof.

> +{
> +    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);
> +    CPUMIPSState *env = &cpu->env;
> +    int r;
> +    struct kvm_mips_interrupt intr;
> +
> +    if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
> +            (cpu_mips_io_interrupts_pending(env))) {

Parentheses around cpu_mips_io_interrupts_pending() seem unnecessary
here FWIW.

> +        intr.cpu = -1;
> +        intr.irq = 2;
> +        r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
> +        if (r < 0) {
> +            printf("cpu %d fail inject %x\n", cs->cpu_index, intr.irq);

Should this really be a printf() rather than error_report() or trace point?

> +        }
> +    }
> +}
> +
> +void kvm_arch_post_run(CPUState *env, struct kvm_run *run)

"cs"

> +{
> +    dprintf("%s\n", __func__);
> +}
> +
> +int kvm_arch_process_async_events(CPUState *cs)
> +{
> +    return cs->halted;
> +}
> +
> +int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)

"cs"

> +{
> +    int ret;
> +
> +    dprintf("%s\n", __func__);
> +    switch (run->exit_reason) {
> +    default:
> +        fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);

error_report() and in that case without trailing \n.

> +        ret = -1;
> +        break;
> +    }
> +
> +    return ret;
> +}
> +
> +bool kvm_arch_stop_on_emulation_error(CPUState *env)

"cs"

> +{
> +    dprintf("%s\n", __func__);
> +    return true;
> +}
> +
> +int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr)

"cs"

> +{
> +    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(CPUMIPSState *env, int irq, int level)
> +{
> +    CPUState *cs = ENV_GET_CPU(env);

CPU(mips_env_get_cpu(env)) please - ENV_GET_CPU() is for generic code
only and supposed to go away.

Any chance a MIPSCPU *cpu (or CPUState *cs) argument can be used instead?

> +    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(CPUArchState *env, int irq, int level)
> +{
> +    CPUState *cs = current_cpu;
> +    CPUState *dest_cs = ENV_GET_CPU(env);

Similar question here.

> +    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 KVM_REG_MIPS_CP0_INDEX     (0x10000 + (8 *  0) + 0)
> +#define KVM_REG_MIPS_CP0_ENTRYLO0  (0x10000 + (8 *  2) + 0)
> +#define KVM_REG_MIPS_CP0_ENTRYLO1  (0x10000 + (8 *  3) + 0)
> +#define KVM_REG_MIPS_CP0_CONTEXT   (0x10000 + (8 *  4) + 0)
> +#define KVM_REG_MIPS_CP0_USERLOCAL (0x10000 + (8 *  4) + 2)
> +#define KVM_REG_MIPS_CP0_PAGEMASK  (0x10000 + (8 *  5) + 0)
> +#define KVM_REG_MIPS_CP0_PAGEGRAIN (0x10000 + (8 *  5) + 1)
> +#define KVM_REG_MIPS_CP0_WIRED     (0x10000 + (8 *  6) + 0)
> +#define KVM_REG_MIPS_CP0_HWRENA    (0x10000 + (8 *  7) + 0)
> +#define KVM_REG_MIPS_CP0_BADVADDR  (0x10000 + (8 *  8) + 0)
> +#define KVM_REG_MIPS_CP0_COUNT     (0x10000 + (8 *  9) + 0)
> +#define KVM_REG_MIPS_CP0_ENTRYHI   (0x10000 + (8 * 10) + 0)
> +#define KVM_REG_MIPS_CP0_COMPARE   (0x10000 + (8 * 11) + 0)
> +#define KVM_REG_MIPS_CP0_STATUS    (0x10000 + (8 * 12) + 0)
> +#define KVM_REG_MIPS_CP0_INTCTL    (0x10000 + (8 * 12) + 1)
> +#define KVM_REG_MIPS_CP0_CAUSE     (0x10000 + (8 * 13) + 0)
> +#define KVM_REG_MIPS_CP0_EPC       (0x10000 + (8 * 14) + 0)
> +#define KVM_REG_MIPS_CP0_PRID      (0x10000 + (8 * 15) + 0)
> +#define KVM_REG_MIPS_CP0_EBASE     (0x10000 + (8 * 15) + 1)
> +#define KVM_REG_MIPS_CP0_CONFIG    (0x10000 + (8 * 16) + 0)
> +#define KVM_REG_MIPS_CP0_CONFIG1   (0x10000 + (8 * 16) + 1)
> +#define KVM_REG_MIPS_CP0_CONFIG2   (0x10000 + (8 * 16) + 2)
> +#define KVM_REG_MIPS_CP0_CONFIG3   (0x10000 + (8 * 16) + 3)
> +#define KVM_REG_MIPS_CP0_CONFIG4   (0x10000 + (8 * 16) + 4)
> +#define KVM_REG_MIPS_CP0_CONFIG5   (0x10000 + (8 * 16) + 5)
> +#define KVM_REG_MIPS_CP0_CONFIG7   (0x10000 + (8 * 16) + 7)
> +#define KVM_REG_MIPS_CP0_XCONTEXT  (0x10000 + (8 * 20) + 0)
> +#define KVM_REG_MIPS_CP0_ERROREPC  (0x10000 + (8 * 30) + 0)
> +
> +inline int kvm_mips_put_one_reg(CPUState *cs, int reg_id, int32 *addr)
> +{
> +    __u64 val64 = (__u64)*addr;
> +    struct kvm_one_reg cp0reg = {
> +        .id = reg_id,
> +        .addr = (__u64)((target_ulong)&val64)
> +    };
> +
> +    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
> +}
> +
> +inline int kvm_mips_put_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr)
> +{
> +    __u64 val64 = (__u64)*addr;
> +    struct kvm_one_reg cp0reg = {
> +        .id = reg_id,
> +        .addr = (__u64)((target_ulong)&val64)
> +    };
> +
> +    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
> +}
> +
> +inline int kvm_mips_get_one_reg(CPUState *cs, int reg_id, int32 *addr)
> +{
> +    int ret;
> +    __u64 val64 = 0;
> +    struct kvm_one_reg cp0reg = {
> +        .id = reg_id,
> +        .addr = (__u64)((target_ulong)&val64)
> +    };
> +
> +    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +
> +    *addr = (int32)val64;
> +    return ret;
> +}
> +
> +inline int kvm_mips_get_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr)
> +{
> +    int ret;
> +    __u64 val64 = 0;
> +    struct kvm_one_reg cp0reg = {
> +        .id = reg_id,
> +        .addr = (__u64)((target_ulong)&val64)
> +    };
> +
> +    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +
> +    *addr = (target_ulong)val64;
> +    return ret;
> +}
> +
> +int kvm_mips_te_put_cp0_registers(CPUState *cs, int level)
> +{
> +    MIPSCPU *cpu = MIPS_CPU(cs);
> +    CPUMIPSState *env = &cpu->env;
> +    int ret;
> +
> +    (void)level;
> +
> +    ret = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
> +                                  &env->CP0_Context);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK,
> +                                &env->CP0_PageMask);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR,
> +                                  &env->CP0_BadVAddr);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI,
> +                                  &env->CP0_EntryHi);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE,
> +                                &env->CP0_Compare);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
> +                                  &env->CP0_ErrorEPC);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +
> +    return ret;
> +}
> +
> +int kvm_mips_te_get_cp0_registers(CPUState *cs)
> +{
> +    MIPSCPU *cpu = MIPS_CPU(cs);
> +    CPUMIPSState *env = &cpu->env;
> +    int ret;
> +
> +    ret = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
> +                                  &env->CP0_Context);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK,
> +                                &env->CP0_PageMask);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR,
> +                                  &env->CP0_BadVAddr);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI,
> +                                  &env->CP0_EntryHi);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE,
> +                                &env->CP0_Compare);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    ret |= kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
> +                                  &env->CP0_ErrorEPC);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +
> +    return ret;
> +}
> diff --git a/target-mips/kvm_mips.h b/target-mips/kvm_mips.h
> new file mode 100644
> index 0000000..0da4edf
> --- /dev/null
> +++ b/target-mips/kvm_mips.h
> @@ -0,0 +1,28 @@
> +/*
> + * 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-2013 Imagination Technologies Ltd.
> + * Authors: Sanjay Lal <sanjayl@kymasys.com>
> +*/
> +
> +#ifndef __KVM_MIPS_H__
> +#define __KVM_MIPS_H__
> +
> +
> +int kvm_mips_set_interrupt(CPUMIPSState *env, int irq, int level);
> +
> +int kvm_mips_set_ipi_interrupt(CPUArchState *env, int irq, int level);
> +
> +inline int kvm_mips_put_one_reg(CPUState *cs, int reg_id, int32 *addr);
> +inline int kvm_mips_put_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr);
> +inline int kvm_mips_get_one_reg(CPUState *cs, int reg_id, int32 *addr);
> +inline int kvm_mips_get_one_ulreg(CPUState *cs, int reg_id, target_ulong *addr);
> +
> +int kvm_mips_te_put_cp0_registers(CPUState *cs, int level);
> +int kvm_mips_te_get_cp0_registers(CPUState *cs);
> +
> +#endif /* __KVM_MIPS_H__ */

Regards,
Andreas

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

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

* Re: [Qemu-devel] [PATCH v2 07/10] target-mips: kvm: Add main KVM support for MIPS
  2014-02-10 14:07     ` Andreas Färber
@ 2014-02-11 10:54       ` James Hogan
  -1 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2014-02-11 10:54 UTC (permalink / raw)
  To: Andreas Färber
  Cc: qemu-devel, kvm, Gleb Natapov, Sanjay Lal, Paolo Bonzini, Aurelien Jarno

Hi Andreas,

On 10/02/14 14:07, Andreas Färber wrote:
>> +#define dprintf(fmt, ...) \
> 
> dprintf is the name of a stdio.h function, so DPRINTF may be a better name.

Okay.

>> +int kvm_arch_init_vcpu(CPUState *env)
> 
> Please use "env" only for CPUMIPSState, use "cpu" or "cs" here. The
> usual convention is "cs" for CPUState in target-*/ so that "cpu" can be
> used for MIPSCPU.

Okay.

>> +{
>> +    dprintf("%s\n", __func__);
>> +    return 0;
>> +}
>> +
>> +static inline int cpu_mips_io_interrupts_pending(CPUArchState *env)
> 
> Please don't use CPUArchState in MIPS-specific code, use CPUMIPSState.
> Although in this trivial case MIPSCPU would be more future-proof.

True.

>> +{
>> +    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);
>> +    CPUMIPSState *env = &cpu->env;
>> +    int r;
>> +    struct kvm_mips_interrupt intr;
>> +
>> +    if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
>> +            (cpu_mips_io_interrupts_pending(env))) {
> 
> Parentheses around cpu_mips_io_interrupts_pending() seem unnecessary
> here FWIW.

Good spot

>> +        intr.cpu = -1;
>> +        intr.irq = 2;
>> +        r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
>> +        if (r < 0) {
>> +            printf("cpu %d fail inject %x\n", cs->cpu_index, intr.irq);
> 
> Should this really be a printf() rather than error_report() or trace point?

It looks like error_report() would indeed be better, thanks

>> +int kvm_mips_set_interrupt(CPUMIPSState *env, int irq, int level)
>> +{
>> +    CPUState *cs = ENV_GET_CPU(env);
> 
> CPU(mips_env_get_cpu(env)) please - ENV_GET_CPU() is for generic code
> only and supposed to go away.
> 
> Any chance a MIPSCPU *cpu (or CPUState *cs) argument can be used instead?

Yep, MIPSCPU can happily be used here (I thought the same thing after
fixing cpu_mips_io_interrupts_pending above).

Thanks for taking the time to review!

Cheers
James


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

* Re: [Qemu-devel] [PATCH v2 07/10] target-mips: kvm: Add main KVM support for MIPS
@ 2014-02-11 10:54       ` James Hogan
  0 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2014-02-11 10:54 UTC (permalink / raw)
  To: Andreas Färber
  Cc: kvm, Gleb Natapov, qemu-devel, Sanjay Lal, Paolo Bonzini, Aurelien Jarno

Hi Andreas,

On 10/02/14 14:07, Andreas Färber wrote:
>> +#define dprintf(fmt, ...) \
> 
> dprintf is the name of a stdio.h function, so DPRINTF may be a better name.

Okay.

>> +int kvm_arch_init_vcpu(CPUState *env)
> 
> Please use "env" only for CPUMIPSState, use "cpu" or "cs" here. The
> usual convention is "cs" for CPUState in target-*/ so that "cpu" can be
> used for MIPSCPU.

Okay.

>> +{
>> +    dprintf("%s\n", __func__);
>> +    return 0;
>> +}
>> +
>> +static inline int cpu_mips_io_interrupts_pending(CPUArchState *env)
> 
> Please don't use CPUArchState in MIPS-specific code, use CPUMIPSState.
> Although in this trivial case MIPSCPU would be more future-proof.

True.

>> +{
>> +    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);
>> +    CPUMIPSState *env = &cpu->env;
>> +    int r;
>> +    struct kvm_mips_interrupt intr;
>> +
>> +    if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
>> +            (cpu_mips_io_interrupts_pending(env))) {
> 
> Parentheses around cpu_mips_io_interrupts_pending() seem unnecessary
> here FWIW.

Good spot

>> +        intr.cpu = -1;
>> +        intr.irq = 2;
>> +        r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
>> +        if (r < 0) {
>> +            printf("cpu %d fail inject %x\n", cs->cpu_index, intr.irq);
> 
> Should this really be a printf() rather than error_report() or trace point?

It looks like error_report() would indeed be better, thanks

>> +int kvm_mips_set_interrupt(CPUMIPSState *env, int irq, int level)
>> +{
>> +    CPUState *cs = ENV_GET_CPU(env);
> 
> CPU(mips_env_get_cpu(env)) please - ENV_GET_CPU() is for generic code
> only and supposed to go away.
> 
> Any chance a MIPSCPU *cpu (or CPUState *cs) argument can be used instead?

Yep, MIPSCPU can happily be used here (I thought the same thing after
fixing cpu_mips_io_interrupts_pending above).

Thanks for taking the time to review!

Cheers
James

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

* Re: [PATCH v2 09/10] hw/mips: malta: Add KVM support
  2013-12-21 20:42     ` Peter Maydell
@ 2014-02-12 15:07       ` James Hogan
  -1 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2014-02-12 15:07 UTC (permalink / raw)
  To: Peter Maydell
  Cc: kvm-devel, Gleb Natapov, QEMU Developers, Sanjay Lal,
	Paolo Bonzini, Aurelien Jarno

On 21/12/13 20:42, Peter Maydell wrote:
> On 16 December 2013 14:12, James Hogan <james.hogan@imgtec.com> wrote:
>> +#include "linux/kvm.h"
> 
> You can't include linux/kvm.h like this -- on Linux this will pull in
> whatever the host's system kvm.h happens to be, and on non-Linux
> it won't compile:
> 
> /Users/pm215/src/qemu/hw/mips/mips_malta.c:56:10: fatal error:
> 'linux/kvm.h' file not found
> #include "linux/kvm.h"
>          ^
> 1 error generated.

Thanks Peter, I've removed all these new includes except sysemu/kvm.h.

Cheers
James

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

* Re: [Qemu-devel] [PATCH v2 09/10] hw/mips: malta: Add KVM support
@ 2014-02-12 15:07       ` James Hogan
  0 siblings, 0 replies; 58+ messages in thread
From: James Hogan @ 2014-02-12 15:07 UTC (permalink / raw)
  To: Peter Maydell
  Cc: kvm-devel, Gleb Natapov, QEMU Developers, Sanjay Lal,
	Paolo Bonzini, Aurelien Jarno

On 21/12/13 20:42, Peter Maydell wrote:
> On 16 December 2013 14:12, James Hogan <james.hogan@imgtec.com> wrote:
>> +#include "linux/kvm.h"
> 
> You can't include linux/kvm.h like this -- on Linux this will pull in
> whatever the host's system kvm.h happens to be, and on non-Linux
> it won't compile:
> 
> /Users/pm215/src/qemu/hw/mips/mips_malta.c:56:10: fatal error:
> 'linux/kvm.h' file not found
> #include "linux/kvm.h"
>          ^
> 1 error generated.

Thanks Peter, I've removed all these new includes except sysemu/kvm.h.

Cheers
James

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

end of thread, other threads:[~2014-02-12 15:08 UTC | newest]

Thread overview: 58+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-12-16 14:12 [PATCH v2 00/10] KVM Support for MIPS32 Processors James Hogan
2013-12-16 14:12 ` [Qemu-devel] " James Hogan
2013-12-16 14:12 ` [PATCH v2 01/10] hw/mips/cputimer: Don't start periodic timer in KVM mode James Hogan
2013-12-16 14:12   ` [Qemu-devel] " James Hogan
2013-12-21 15:34   ` Aurelien Jarno
2013-12-21 15:34     ` [Qemu-devel] " Aurelien Jarno
2013-12-16 14:12 ` [PATCH v2 02/10] hw/mips: Add API to convert KVM guest KSEG0 <-> GPA James Hogan
2013-12-16 14:12   ` [Qemu-devel] " James Hogan
2013-12-21 15:34   ` Aurelien Jarno
2013-12-21 15:34     ` [Qemu-devel] " Aurelien Jarno
2013-12-16 14:12 ` [PATCH v2 03/10] target-mips: get_physical_address: Add defines for segment bases James Hogan
2013-12-16 14:12   ` [Qemu-devel] " James Hogan
2013-12-21 15:34   ` Aurelien Jarno
2013-12-21 15:34     ` [Qemu-devel] " Aurelien Jarno
2013-12-16 14:12 ` [PATCH v2 04/10] target-mips: get_physical_address: Add KVM awareness James Hogan
2013-12-16 14:12   ` [Qemu-devel] " James Hogan
2013-12-21 15:34   ` Aurelien Jarno
2013-12-21 15:34     ` [Qemu-devel] " Aurelien Jarno
2013-12-16 14:12 ` [PATCH v2 05/10] kvm: Set sigmask length to 16 for MIPS targets James Hogan
2013-12-16 14:12   ` [Qemu-devel] " James Hogan
2013-12-21 15:34   ` Aurelien Jarno
2013-12-21 15:34     ` [Qemu-devel] " Aurelien Jarno
2013-12-21 20:18   ` Peter Maydell
2013-12-21 20:18     ` Peter Maydell
2013-12-16 14:12 ` [PATCH v2 06/10] target-mips: Set target page size to 16K in KVM mode James Hogan
2013-12-16 14:12   ` [Qemu-devel] " James Hogan
2013-12-21 15:34   ` Aurelien Jarno
2013-12-21 15:34     ` [Qemu-devel] " Aurelien Jarno
2013-12-16 14:12 ` [PATCH v2 07/10] target-mips: kvm: Add main KVM support for MIPS James Hogan
2013-12-16 14:12   ` [Qemu-devel] " James Hogan
2013-12-21 15:35   ` Aurelien Jarno
2013-12-21 15:35     ` [Qemu-devel] " Aurelien Jarno
2014-02-10 14:07   ` Andreas Färber
2014-02-10 14:07     ` Andreas Färber
2014-02-11 10:54     ` James Hogan
2014-02-11 10:54       ` James Hogan
2013-12-16 14:12 ` [PATCH v2 08/10] hw/mips: In KVM mode, inject IRQ2 (I/O) interupts via ioctls James Hogan
2013-12-16 14:12   ` [Qemu-devel] " James Hogan
2013-12-21 15:41   ` Aurelien Jarno
2013-12-21 15:41     ` [Qemu-devel] " Aurelien Jarno
2013-12-21 20:40   ` Peter Maydell
2013-12-21 20:40     ` Peter Maydell
2013-12-16 14:12 ` [PATCH v2 09/10] hw/mips: malta: Add KVM support James Hogan
2013-12-16 14:12   ` [Qemu-devel] " James Hogan
2013-12-21 15:37   ` Aurelien Jarno
2013-12-21 15:37     ` [Qemu-devel] " Aurelien Jarno
2013-12-21 20:42   ` Peter Maydell
2013-12-21 20:42     ` Peter Maydell
2014-02-12 15:07     ` James Hogan
2014-02-12 15:07       ` [Qemu-devel] " James Hogan
2013-12-16 14:12 ` [PATCH v2 10/10] target-mips: Enable KVM support in build system James Hogan
2013-12-16 14:12   ` [Qemu-devel] " James Hogan
2013-12-21 15:38   ` Aurelien Jarno
2013-12-21 15:38     ` [Qemu-devel] " Aurelien Jarno
2013-12-21 18:59   ` Peter Maydell
2013-12-21 18:59     ` [Qemu-devel] " Peter Maydell
2013-12-23 12:31     ` James Hogan
2013-12-23 12:31       ` James Hogan

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.