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

I'd like to have this squeezed into 2.0 (if at all possible), so any
final review from KVM people would be much appreciated. 

Thanks to everybody who has already taken part in review.

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.

Changes in v4:

Changes mostly addressing a few review comments from v3 patchset.

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-v4

 - Rebase on v2.0.0-rc0.
 - Use int32_t instead of int32 (which is for softfloat) in kvm register
   accessors (Andreas Färber).
 - Use uint64_t instead of __u64 (which is really just for kernel
   headers) in the kvm register accessors (Andreas Färber).
 - Cast pointer to uintptr_t rather than target_ulong in kvm register
   accessors.
 - Remove some redundant casts in kvm register accessors.
 - Add MAINTAINERS entry for MIPS KVM.

Changes in v3:

Changes mostly addressing review comments from v2 patchset.

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-v3

 - Remove "target-mips: Set target page size to 16K in KVM mode". It
   should actually work fine with 4k TARGET_PAGE_SIZE as long as there
   is no cache aliasing or both host and guest kernels are configured to
   a sufficient page size to avoid aliasing (which the kernel
   arch/mips/kvm/00README.txt alludes to anyway).
 - Rewrote kvm sigmask patch to allow sigmask length to be set by
   kvm_arch_init(), so that MIPS can set it to 16 as it has 128 signals.
   This is better than cluttering kvm-all.c with TARGET_* ifdefs (Peter
   Maydell).
 - Set sigmask length to 16 from kvm_arch_init() since MIPS Linux has
   128 signals. This is better than cluttering kvm_all.c with TARGET_*
   ifdefs (Peter Maydell).
 - s/dprintf/DPRINTF/ (Andreas Färber).
 - Use "cs" rather than "cpu" or "env" for CPUState variable names
   (Andreas Färber).
 - Use CPUMIPSState rather than CPUArchState (Andreas Färber).
 - Pass MIPSCPU to cpu_mips_io_interrupts_pending() rather than
   CPUMIPSState (Andreas Färber).
 - Remove spurious parentheses around cpu_mips_io_interrupts_pending()
   call (Andreas Färber).
 - Pass MIPSCPU to kvm_mips_set_[ipi_]interrupt (Andreas Färber).
 - Make use of error_report (Andreas Färber) and clean up error messages
   a little to include __func__.
 - Remove inline kvm_mips_{put,get}_one_[ul]reg() declarations from
   kvm_mips.h. They're only used in target-mips/kvm.c anyway.
 - Make kvm_arch_{put,get}_registers static within target-mips/kvm.c and
   remove from kvm_mips.h.
 - Remove unnecessary includes from Malta patch, especially linux/kvm.h
   which isn't a good idea on non-Linux (Peter Maydell).

Changes in v2:

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

 - 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 (5):
  target-mips: get_physical_address: Add defines for segment bases
  target-mips: get_physical_address: Add KVM awareness
  kvm: Allow arch to set sigmask length
  hw/mips: malta: Add KVM support
  MAINTAINERS: Add entry for MIPS KVM

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

 MAINTAINERS               |   5 +
 configure                 |   6 +-
 hw/mips/addr.c            |  10 +
 hw/mips/cputimer.c        |  13 +-
 hw/mips/mips_int.c        |  11 ++
 hw/mips/mips_malta.c      |  82 +++++---
 include/hw/mips/cpudevs.h |   4 +
 include/sysemu/kvm.h      |   2 +
 kvm-all.c                 |  11 +-
 target-mips/Makefile.objs |   1 +
 target-mips/helper.c      |  51 +++--
 target-mips/kvm.c         | 472 ++++++++++++++++++++++++++++++++++++++++++++++
 target-mips/kvm_mips.h    |  19 ++
 13 files changed, 647 insertions(+), 40 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] 50+ messages in thread

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

I'd like to have this squeezed into 2.0 (if at all possible), so any
final review from KVM people would be much appreciated. 

Thanks to everybody who has already taken part in review.

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.

Changes in v4:

Changes mostly addressing a few review comments from v3 patchset.

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-v4

 - Rebase on v2.0.0-rc0.
 - Use int32_t instead of int32 (which is for softfloat) in kvm register
   accessors (Andreas Färber).
 - Use uint64_t instead of __u64 (which is really just for kernel
   headers) in the kvm register accessors (Andreas Färber).
 - Cast pointer to uintptr_t rather than target_ulong in kvm register
   accessors.
 - Remove some redundant casts in kvm register accessors.
 - Add MAINTAINERS entry for MIPS KVM.

Changes in v3:

Changes mostly addressing review comments from v2 patchset.

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-v3

 - Remove "target-mips: Set target page size to 16K in KVM mode". It
   should actually work fine with 4k TARGET_PAGE_SIZE as long as there
   is no cache aliasing or both host and guest kernels are configured to
   a sufficient page size to avoid aliasing (which the kernel
   arch/mips/kvm/00README.txt alludes to anyway).
 - Rewrote kvm sigmask patch to allow sigmask length to be set by
   kvm_arch_init(), so that MIPS can set it to 16 as it has 128 signals.
   This is better than cluttering kvm-all.c with TARGET_* ifdefs (Peter
   Maydell).
 - Set sigmask length to 16 from kvm_arch_init() since MIPS Linux has
   128 signals. This is better than cluttering kvm_all.c with TARGET_*
   ifdefs (Peter Maydell).
 - s/dprintf/DPRINTF/ (Andreas Färber).
 - Use "cs" rather than "cpu" or "env" for CPUState variable names
   (Andreas Färber).
 - Use CPUMIPSState rather than CPUArchState (Andreas Färber).
 - Pass MIPSCPU to cpu_mips_io_interrupts_pending() rather than
   CPUMIPSState (Andreas Färber).
 - Remove spurious parentheses around cpu_mips_io_interrupts_pending()
   call (Andreas Färber).
 - Pass MIPSCPU to kvm_mips_set_[ipi_]interrupt (Andreas Färber).
 - Make use of error_report (Andreas Färber) and clean up error messages
   a little to include __func__.
 - Remove inline kvm_mips_{put,get}_one_[ul]reg() declarations from
   kvm_mips.h. They're only used in target-mips/kvm.c anyway.
 - Make kvm_arch_{put,get}_registers static within target-mips/kvm.c and
   remove from kvm_mips.h.
 - Remove unnecessary includes from Malta patch, especially linux/kvm.h
   which isn't a good idea on non-Linux (Peter Maydell).

Changes in v2:

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

 - 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 (5):
  target-mips: get_physical_address: Add defines for segment bases
  target-mips: get_physical_address: Add KVM awareness
  kvm: Allow arch to set sigmask length
  hw/mips: malta: Add KVM support
  MAINTAINERS: Add entry for MIPS KVM

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

 MAINTAINERS               |   5 +
 configure                 |   6 +-
 hw/mips/addr.c            |  10 +
 hw/mips/cputimer.c        |  13 +-
 hw/mips/mips_int.c        |  11 ++
 hw/mips/mips_malta.c      |  82 +++++---
 include/hw/mips/cpudevs.h |   4 +
 include/sysemu/kvm.h      |   2 +
 kvm-all.c                 |  11 +-
 target-mips/Makefile.objs |   1 +
 target-mips/helper.c      |  51 +++--
 target-mips/kvm.c         | 472 ++++++++++++++++++++++++++++++++++++++++++++++
 target-mips/kvm_mips.h    |  19 ++
 13 files changed, 647 insertions(+), 40 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] 50+ messages in thread

* [PATCH v4 01/10] hw/mips/cputimer: Don't start periodic timer in KVM mode
  2014-03-14 12:47 ` [Qemu-devel] " James Hogan
@ 2014-03-14 12:47   ` James Hogan
  -1 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-14 12:47 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>
Reviewed-by: 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] 50+ messages in thread

* [Qemu-devel] [PATCH v4 01/10] hw/mips/cputimer: Don't start periodic timer in KVM mode
@ 2014-03-14 12:47   ` James Hogan
  0 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-14 12:47 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>
Reviewed-by: 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] 50+ messages in thread

* [PATCH v4 02/10] hw/mips: Add API to convert KVM guest KSEG0 <-> GPA
  2014-03-14 12:47 ` [Qemu-devel] " James Hogan
@ 2014-03-14 12:47   ` James Hogan
  -1 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-14 12:47 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>
Reviewed-by: 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] 50+ messages in thread

* [Qemu-devel] [PATCH v4 02/10] hw/mips: Add API to convert KVM guest KSEG0 <-> GPA
@ 2014-03-14 12:47   ` James Hogan
  0 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-14 12:47 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>
Reviewed-by: 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] 50+ messages in thread

* [PATCH v4 03/10] target-mips: get_physical_address: Add defines for segment bases
  2014-03-14 12:47 ` [Qemu-devel] " James Hogan
@ 2014-03-14 12:47   ` James Hogan
  -1 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-14 12:47 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>
Reviewed-by: 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 b28ae9b..2b30fc2 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] 50+ messages in thread

* [Qemu-devel] [PATCH v4 03/10] target-mips: get_physical_address: Add defines for segment bases
@ 2014-03-14 12:47   ` James Hogan
  0 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-14 12:47 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>
Reviewed-by: 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 b28ae9b..2b30fc2 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] 50+ messages in thread

* [PATCH v4 04/10] target-mips: get_physical_address: Add KVM awareness
  2014-03-14 12:47 ` [Qemu-devel] " James Hogan
@ 2014-03-14 12:47   ` James Hogan
  -1 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-14 12:47 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 2b30fc2..4053d50 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] 50+ messages in thread

* [Qemu-devel] [PATCH v4 04/10] target-mips: get_physical_address: Add KVM awareness
@ 2014-03-14 12:47   ` James Hogan
  0 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-14 12:47 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 2b30fc2..4053d50 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] 50+ messages in thread

* [PATCH v4 05/10] kvm: Allow arch to set sigmask length
  2014-03-14 12:47 ` [Qemu-devel] " James Hogan
@ 2014-03-14 12:47   ` James Hogan
  -1 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-14 12:47 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, Aurelien Jarno, Gleb Natapov, Paolo Bonzini, Sanjay Lal,
	James Hogan, Peter Maydell

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

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Sanjay Lal <sanjayl@kymasys.com>
Cc: Gleb Natapov <gleb@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
---
Changes in v3:
 - Rewrote to allow sigmask length to be set by kvm_arch_init(), so that
   MIPS can set it to 16 as it has 128 signals. This is better than
   cluttering kvm-all.c with TARGET_* ifdefs (Peter Maydell).

Changes in v2:
 - Expand commit message
 - Reword comment
---
 include/sysemu/kvm.h |  2 ++
 kvm-all.c            | 11 ++++++++++-
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 0bee1e8..e9cdb0c 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -297,6 +297,8 @@ int kvm_check_extension(KVMState *s, unsigned int extension);
 uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function,
                                       uint32_t index, int reg);
 
+void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len);
+
 #if !defined(CONFIG_USER_ONLY)
 int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr,
                                        hwaddr *phys_addr);
diff --git a/kvm-all.c b/kvm-all.c
index 82a9119..d3be5ae 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -98,6 +98,7 @@ struct KVMState
      * they're not.  Linux, glibc and *BSD all treat ioctl numbers as
      * unsigned, and treating them as signed here can break things */
     unsigned irq_set_ioctl;
+    unsigned int sigmask_len;
 #ifdef KVM_CAP_IRQ_ROUTING
     struct kvm_irq_routing *irq_routes;
     int nr_allocated_irq_routes;
@@ -1372,6 +1373,8 @@ int kvm_init(QEMUMachine *machine)
     assert(TARGET_PAGE_SIZE <= getpagesize());
     page_size_init();
 
+    s->sigmask_len = 8;
+
 #ifdef KVM_CAP_SET_GUEST_DEBUG
     QTAILQ_INIT(&s->kvm_sw_breakpoints);
 #endif
@@ -1548,6 +1551,11 @@ err:
     return ret;
 }
 
+void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len)
+{
+    s->sigmask_len = sigmask_len;
+}
+
 static void kvm_handle_io(uint16_t port, void *data, int direction, int size,
                           uint32_t count)
 {
@@ -2068,6 +2076,7 @@ void kvm_remove_all_breakpoints(CPUState *cpu)
 
 int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset)
 {
+    KVMState *s = kvm_state;
     struct kvm_signal_mask *sigmask;
     int r;
 
@@ -2077,7 +2086,7 @@ int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset)
 
     sigmask = g_malloc(sizeof(*sigmask) + sizeof(*sigset));
 
-    sigmask->len = 8;
+    sigmask->len = s->sigmask_len;
     memcpy(sigmask->sigset, sigset, sizeof(*sigset));
     r = kvm_vcpu_ioctl(cpu, KVM_SET_SIGNAL_MASK, sigmask);
     g_free(sigmask);
-- 
1.8.1.2


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

* [Qemu-devel] [PATCH v4 05/10] kvm: Allow arch to set sigmask length
@ 2014-03-14 12:47   ` James Hogan
  0 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-14 12:47 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, James Hogan, kvm, Gleb Natapov, Sanjay Lal,
	Paolo Bonzini, Aurelien Jarno

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

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Sanjay Lal <sanjayl@kymasys.com>
Cc: Gleb Natapov <gleb@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
---
Changes in v3:
 - Rewrote to allow sigmask length to be set by kvm_arch_init(), so that
   MIPS can set it to 16 as it has 128 signals. This is better than
   cluttering kvm-all.c with TARGET_* ifdefs (Peter Maydell).

Changes in v2:
 - Expand commit message
 - Reword comment
---
 include/sysemu/kvm.h |  2 ++
 kvm-all.c            | 11 ++++++++++-
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 0bee1e8..e9cdb0c 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -297,6 +297,8 @@ int kvm_check_extension(KVMState *s, unsigned int extension);
 uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function,
                                       uint32_t index, int reg);
 
+void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len);
+
 #if !defined(CONFIG_USER_ONLY)
 int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr,
                                        hwaddr *phys_addr);
diff --git a/kvm-all.c b/kvm-all.c
index 82a9119..d3be5ae 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -98,6 +98,7 @@ struct KVMState
      * they're not.  Linux, glibc and *BSD all treat ioctl numbers as
      * unsigned, and treating them as signed here can break things */
     unsigned irq_set_ioctl;
+    unsigned int sigmask_len;
 #ifdef KVM_CAP_IRQ_ROUTING
     struct kvm_irq_routing *irq_routes;
     int nr_allocated_irq_routes;
@@ -1372,6 +1373,8 @@ int kvm_init(QEMUMachine *machine)
     assert(TARGET_PAGE_SIZE <= getpagesize());
     page_size_init();
 
+    s->sigmask_len = 8;
+
 #ifdef KVM_CAP_SET_GUEST_DEBUG
     QTAILQ_INIT(&s->kvm_sw_breakpoints);
 #endif
@@ -1548,6 +1551,11 @@ err:
     return ret;
 }
 
+void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len)
+{
+    s->sigmask_len = sigmask_len;
+}
+
 static void kvm_handle_io(uint16_t port, void *data, int direction, int size,
                           uint32_t count)
 {
@@ -2068,6 +2076,7 @@ void kvm_remove_all_breakpoints(CPUState *cpu)
 
 int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset)
 {
+    KVMState *s = kvm_state;
     struct kvm_signal_mask *sigmask;
     int r;
 
@@ -2077,7 +2086,7 @@ int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset)
 
     sigmask = g_malloc(sizeof(*sigmask) + sizeof(*sigset));
 
-    sigmask->len = 8;
+    sigmask->len = s->sigmask_len;
     memcpy(sigmask->sigset, sigset, sizeof(*sigset));
     r = kvm_vcpu_ioctl(cpu, KVM_SET_SIGNAL_MASK, sigmask);
     g_free(sigmask);
-- 
1.8.1.2

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

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

From: Sanjay Lal <sanjayl@kymasys.com>

Implement the main KVM arch API for MIPS.

Signed-off-by: Sanjay Lal <sanjayl@kymasys.com>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Gleb Natapov <gleb@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Andreas Färber <afaerber@suse.de>
Cc: Peter Maydell <peter.maydell@linaro.org>
---
Changes in v4:
(No functional changes, assembly output unchanged)
 - Use int32_t instead of int32 (which is for softfloat) in kvm register
   accessors (Andreas Färber).
 - Use uint64_t instead of __u64 (which is really just for kernel
   headers) in the kvm register accessors (Andreas Färber).
 - Cast pointer to uintptr_t rather than target_ulong in kvm register
   accessors.
 - Remove some redundant casts in kvm register accessors.

Changes in v3:
 - s/dprintf/DPRINTF/ (Andreas Färber).
 - Use "cs" rather than "cpu" or "env" for CPUState variable names
   (Andreas Färber).
 - Use CPUMIPSState rather than CPUArchState (Andreas Färber).
 - Pass MIPSCPU to cpu_mips_io_interrupts_pending() rather than
   CPUMIPSState (Andreas Färber).
 - Remove spurious parentheses around cpu_mips_io_interrupts_pending()
   call (Andreas Färber).
 - Pass MIPSCPU to kvm_mips_set_[ipi_]interrupt (Andreas Färber).
 - Make use of error_report (Andreas Färber) and clean up error messages
   a little to include __func__.
 - Remove inline kvm_mips_{put,get}_one_[ul]reg() declarations from
   kvm_mips.h. They're only used in target-mips/kvm.c anyway.
 - Make kvm_arch_{put,get}_registers static within target-mips/kvm.c and
   remove from kvm_mips.h.
 - Set sigmask length to 16 from kvm_arch_init() since MIPS Linux has
   128 signals. This is better than cluttering kvm_all.c with TARGET_*
   ifdefs (Peter Maydell).

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      | 472 +++++++++++++++++++++++++++++++++++++++++++++++++
 target-mips/kvm_mips.h |  19 ++
 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..ee477a3
--- /dev/null
+++ b/target-mips/kvm.c
@@ -0,0 +1,472 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * KVM/MIPS: MIPS specific KVM APIs
+ *
+ * Copyright (C) 2012-2014 Imagination Technologies Ltd.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+*/
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include <linux/kvm.h>
+
+#include "qemu-common.h"
+#include "qemu/error-report.h"
+#include "qemu/timer.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/kvm.h"
+#include "cpu.h"
+#include "sysemu/cpus.h"
+#include "kvm_mips.h"
+
+#define DEBUG_KVM 0
+
+#define DPRINTF(fmt, ...) \
+    do { if (DEBUG_KVM) { fprintf(stderr, fmt, ## __VA_ARGS__); } } while (0)
+
+const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
+    KVM_CAP_LAST_INFO
+};
+
+unsigned long kvm_arch_vcpu_id(CPUState *cs)
+{
+    return cs->cpu_index;
+}
+
+int kvm_arch_init(KVMState *s)
+{
+    /* MIPS has 128 signals */
+    kvm_set_sigmask_len(s, 16);
+
+    DPRINTF("%s\n", __func__);
+    return 0;
+}
+
+int kvm_arch_init_vcpu(CPUState *cs)
+{
+    int ret = 0;
+    DPRINTF("%s\n", __func__);
+    return ret;
+}
+
+void kvm_arch_reset_vcpu(CPUState *cs)
+{
+    DPRINTF("%s\n", __func__);
+}
+
+int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
+{
+    DPRINTF("%s\n", __func__);
+    return 0;
+}
+
+int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
+{
+    DPRINTF("%s\n", __func__);
+    return 0;
+}
+
+static inline int cpu_mips_io_interrupts_pending(MIPSCPU *cpu)
+{
+    CPUMIPSState *env = &cpu->env;
+
+    DPRINTF("%s: %#x\n", __func__, env->CP0_Cause & (1 << (2 + CP0Ca_IP)));
+    return env->CP0_Cause & (0x1 << (2 + CP0Ca_IP));
+}
+
+
+void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
+{
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    int r;
+    struct kvm_mips_interrupt intr;
+
+    if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
+            cpu_mips_io_interrupts_pending(cpu)) {
+        intr.cpu = -1;
+        intr.irq = 2;
+        r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
+        if (r < 0) {
+            error_report("%s: cpu %d: failed to inject IRQ %x",
+                         __func__, cs->cpu_index, intr.irq);
+        }
+    }
+}
+
+void kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
+{
+    DPRINTF("%s\n", __func__);
+}
+
+int kvm_arch_process_async_events(CPUState *cs)
+{
+    return cs->halted;
+}
+
+int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
+{
+    int ret;
+
+    DPRINTF("%s\n", __func__);
+    switch (run->exit_reason) {
+    default:
+        error_report("%s: unknown exit reason %d",
+                     __func__, run->exit_reason);
+        ret = -1;
+        break;
+    }
+
+    return ret;
+}
+
+bool kvm_arch_stop_on_emulation_error(CPUState *cs)
+{
+    DPRINTF("%s\n", __func__);
+    return true;
+}
+
+int kvm_arch_on_sigbus_vcpu(CPUState *cs, int code, void *addr)
+{
+    DPRINTF("%s\n", __func__);
+    return 1;
+}
+
+int kvm_arch_on_sigbus(int code, void *addr)
+{
+    DPRINTF("%s\n", __func__);
+    return 1;
+}
+
+void kvm_arch_init_irq_routing(KVMState *s)
+{
+}
+
+int kvm_mips_set_interrupt(MIPSCPU *cpu, int irq, int level)
+{
+    CPUState *cs = CPU(cpu);
+    struct kvm_mips_interrupt intr;
+
+    if (!kvm_enabled()) {
+        return 0;
+    }
+
+    intr.cpu = -1;
+
+    if (level) {
+        intr.irq = irq;
+    } else {
+        intr.irq = -irq;
+    }
+
+    kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
+
+    return 0;
+}
+
+int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level)
+{
+    CPUState *cs = current_cpu;
+    CPUState *dest_cs = CPU(cpu);
+    struct kvm_mips_interrupt intr;
+
+    if (!kvm_enabled()) {
+        return 0;
+    }
+
+    intr.cpu = dest_cs->cpu_index;
+
+    if (level) {
+        intr.irq = irq;
+    } else {
+        intr.irq = -irq;
+    }
+
+    DPRINTF("%s: CPU %d, IRQ: %d\n", __func__, intr.cpu, intr.irq);
+
+    kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
+
+    return 0;
+}
+
+#define 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)
+
+static inline int kvm_mips_put_one_reg(CPUState *cs, int reg_id, int32_t *addr)
+{
+    uint64_t val64 = *addr;
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (uintptr_t)&val64
+    };
+
+    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
+}
+
+static inline int kvm_mips_put_one_ulreg(CPUState *cs, int reg_id,
+                                         target_ulong *addr)
+{
+    uint64_t val64 = *addr;
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (uintptr_t)&val64
+    };
+
+    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
+}
+
+static inline int kvm_mips_get_one_reg(CPUState *cs, int reg_id, int32_t *addr)
+{
+    int ret;
+    uint64_t val64 = 0;
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (uintptr_t)&val64
+    };
+
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
+    if (ret < 0) {
+        return ret;
+    }
+
+    *addr = val64;
+    return ret;
+}
+
+static inline int kvm_mips_get_one_ulreg(CPUState *cs, int reg_id,
+                                         target_ulong *addr)
+{
+    int ret;
+    uint64_t val64 = 0;
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (uintptr_t)&val64
+    };
+
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
+    if (ret < 0) {
+        return ret;
+    }
+
+    *addr = val64;
+    return ret;
+}
+
+static 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;
+}
+
+static 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;
+}
+
+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;
+}
diff --git a/target-mips/kvm_mips.h b/target-mips/kvm_mips.h
new file mode 100644
index 0000000..7ada267
--- /dev/null
+++ b/target-mips/kvm_mips.h
@@ -0,0 +1,19 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * KVM/MIPS: MIPS specific KVM APIs
+ *
+ * Copyright (C) 2012-2014 Imagination Technologies Ltd.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+*/
+
+#ifndef __KVM_MIPS_H__
+#define __KVM_MIPS_H__
+
+
+int kvm_mips_set_interrupt(MIPSCPU *cpu, int irq, int level);
+int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level);
+
+#endif /* __KVM_MIPS_H__ */
-- 
1.8.1.2


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

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

From: Sanjay Lal <sanjayl@kymasys.com>

Implement the main KVM arch API for MIPS.

Signed-off-by: Sanjay Lal <sanjayl@kymasys.com>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Gleb Natapov <gleb@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Andreas Färber <afaerber@suse.de>
Cc: Peter Maydell <peter.maydell@linaro.org>
---
Changes in v4:
(No functional changes, assembly output unchanged)
 - Use int32_t instead of int32 (which is for softfloat) in kvm register
   accessors (Andreas Färber).
 - Use uint64_t instead of __u64 (which is really just for kernel
   headers) in the kvm register accessors (Andreas Färber).
 - Cast pointer to uintptr_t rather than target_ulong in kvm register
   accessors.
 - Remove some redundant casts in kvm register accessors.

Changes in v3:
 - s/dprintf/DPRINTF/ (Andreas Färber).
 - Use "cs" rather than "cpu" or "env" for CPUState variable names
   (Andreas Färber).
 - Use CPUMIPSState rather than CPUArchState (Andreas Färber).
 - Pass MIPSCPU to cpu_mips_io_interrupts_pending() rather than
   CPUMIPSState (Andreas Färber).
 - Remove spurious parentheses around cpu_mips_io_interrupts_pending()
   call (Andreas Färber).
 - Pass MIPSCPU to kvm_mips_set_[ipi_]interrupt (Andreas Färber).
 - Make use of error_report (Andreas Färber) and clean up error messages
   a little to include __func__.
 - Remove inline kvm_mips_{put,get}_one_[ul]reg() declarations from
   kvm_mips.h. They're only used in target-mips/kvm.c anyway.
 - Make kvm_arch_{put,get}_registers static within target-mips/kvm.c and
   remove from kvm_mips.h.
 - Set sigmask length to 16 from kvm_arch_init() since MIPS Linux has
   128 signals. This is better than cluttering kvm_all.c with TARGET_*
   ifdefs (Peter Maydell).

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      | 472 +++++++++++++++++++++++++++++++++++++++++++++++++
 target-mips/kvm_mips.h |  19 ++
 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..ee477a3
--- /dev/null
+++ b/target-mips/kvm.c
@@ -0,0 +1,472 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * KVM/MIPS: MIPS specific KVM APIs
+ *
+ * Copyright (C) 2012-2014 Imagination Technologies Ltd.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+*/
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include <linux/kvm.h>
+
+#include "qemu-common.h"
+#include "qemu/error-report.h"
+#include "qemu/timer.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/kvm.h"
+#include "cpu.h"
+#include "sysemu/cpus.h"
+#include "kvm_mips.h"
+
+#define DEBUG_KVM 0
+
+#define DPRINTF(fmt, ...) \
+    do { if (DEBUG_KVM) { fprintf(stderr, fmt, ## __VA_ARGS__); } } while (0)
+
+const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
+    KVM_CAP_LAST_INFO
+};
+
+unsigned long kvm_arch_vcpu_id(CPUState *cs)
+{
+    return cs->cpu_index;
+}
+
+int kvm_arch_init(KVMState *s)
+{
+    /* MIPS has 128 signals */
+    kvm_set_sigmask_len(s, 16);
+
+    DPRINTF("%s\n", __func__);
+    return 0;
+}
+
+int kvm_arch_init_vcpu(CPUState *cs)
+{
+    int ret = 0;
+    DPRINTF("%s\n", __func__);
+    return ret;
+}
+
+void kvm_arch_reset_vcpu(CPUState *cs)
+{
+    DPRINTF("%s\n", __func__);
+}
+
+int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
+{
+    DPRINTF("%s\n", __func__);
+    return 0;
+}
+
+int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
+{
+    DPRINTF("%s\n", __func__);
+    return 0;
+}
+
+static inline int cpu_mips_io_interrupts_pending(MIPSCPU *cpu)
+{
+    CPUMIPSState *env = &cpu->env;
+
+    DPRINTF("%s: %#x\n", __func__, env->CP0_Cause & (1 << (2 + CP0Ca_IP)));
+    return env->CP0_Cause & (0x1 << (2 + CP0Ca_IP));
+}
+
+
+void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
+{
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    int r;
+    struct kvm_mips_interrupt intr;
+
+    if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
+            cpu_mips_io_interrupts_pending(cpu)) {
+        intr.cpu = -1;
+        intr.irq = 2;
+        r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
+        if (r < 0) {
+            error_report("%s: cpu %d: failed to inject IRQ %x",
+                         __func__, cs->cpu_index, intr.irq);
+        }
+    }
+}
+
+void kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
+{
+    DPRINTF("%s\n", __func__);
+}
+
+int kvm_arch_process_async_events(CPUState *cs)
+{
+    return cs->halted;
+}
+
+int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
+{
+    int ret;
+
+    DPRINTF("%s\n", __func__);
+    switch (run->exit_reason) {
+    default:
+        error_report("%s: unknown exit reason %d",
+                     __func__, run->exit_reason);
+        ret = -1;
+        break;
+    }
+
+    return ret;
+}
+
+bool kvm_arch_stop_on_emulation_error(CPUState *cs)
+{
+    DPRINTF("%s\n", __func__);
+    return true;
+}
+
+int kvm_arch_on_sigbus_vcpu(CPUState *cs, int code, void *addr)
+{
+    DPRINTF("%s\n", __func__);
+    return 1;
+}
+
+int kvm_arch_on_sigbus(int code, void *addr)
+{
+    DPRINTF("%s\n", __func__);
+    return 1;
+}
+
+void kvm_arch_init_irq_routing(KVMState *s)
+{
+}
+
+int kvm_mips_set_interrupt(MIPSCPU *cpu, int irq, int level)
+{
+    CPUState *cs = CPU(cpu);
+    struct kvm_mips_interrupt intr;
+
+    if (!kvm_enabled()) {
+        return 0;
+    }
+
+    intr.cpu = -1;
+
+    if (level) {
+        intr.irq = irq;
+    } else {
+        intr.irq = -irq;
+    }
+
+    kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
+
+    return 0;
+}
+
+int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level)
+{
+    CPUState *cs = current_cpu;
+    CPUState *dest_cs = CPU(cpu);
+    struct kvm_mips_interrupt intr;
+
+    if (!kvm_enabled()) {
+        return 0;
+    }
+
+    intr.cpu = dest_cs->cpu_index;
+
+    if (level) {
+        intr.irq = irq;
+    } else {
+        intr.irq = -irq;
+    }
+
+    DPRINTF("%s: CPU %d, IRQ: %d\n", __func__, intr.cpu, intr.irq);
+
+    kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
+
+    return 0;
+}
+
+#define 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)
+
+static inline int kvm_mips_put_one_reg(CPUState *cs, int reg_id, int32_t *addr)
+{
+    uint64_t val64 = *addr;
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (uintptr_t)&val64
+    };
+
+    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
+}
+
+static inline int kvm_mips_put_one_ulreg(CPUState *cs, int reg_id,
+                                         target_ulong *addr)
+{
+    uint64_t val64 = *addr;
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (uintptr_t)&val64
+    };
+
+    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
+}
+
+static inline int kvm_mips_get_one_reg(CPUState *cs, int reg_id, int32_t *addr)
+{
+    int ret;
+    uint64_t val64 = 0;
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (uintptr_t)&val64
+    };
+
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
+    if (ret < 0) {
+        return ret;
+    }
+
+    *addr = val64;
+    return ret;
+}
+
+static inline int kvm_mips_get_one_ulreg(CPUState *cs, int reg_id,
+                                         target_ulong *addr)
+{
+    int ret;
+    uint64_t val64 = 0;
+    struct kvm_one_reg cp0reg = {
+        .id = reg_id,
+        .addr = (uintptr_t)&val64
+    };
+
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
+    if (ret < 0) {
+        return ret;
+    }
+
+    *addr = val64;
+    return ret;
+}
+
+static 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;
+}
+
+static 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;
+}
+
+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;
+}
diff --git a/target-mips/kvm_mips.h b/target-mips/kvm_mips.h
new file mode 100644
index 0000000..7ada267
--- /dev/null
+++ b/target-mips/kvm_mips.h
@@ -0,0 +1,19 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * KVM/MIPS: MIPS specific KVM APIs
+ *
+ * Copyright (C) 2012-2014 Imagination Technologies Ltd.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+*/
+
+#ifndef __KVM_MIPS_H__
+#define __KVM_MIPS_H__
+
+
+int kvm_mips_set_interrupt(MIPSCPU *cpu, int irq, int level);
+int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level);
+
+#endif /* __KVM_MIPS_H__ */
-- 
1.8.1.2

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

* [PATCH v4 07/10] hw/mips: In KVM mode, inject IRQ2 (I/O) interupts via ioctls
  2014-03-14 12:47 ` [Qemu-devel] " James Hogan
@ 2014-03-14 12:47   ` James Hogan
  -1 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-14 12:47 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>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Andreas Färber <afaerber@suse.de>
---
Changes in v3:
 - Pass MIPSCPU to kvm_mips_set_[ipi_]interrupt (Andreas Färber).

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


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

* [Qemu-devel] [PATCH v4 07/10] hw/mips: In KVM mode, inject IRQ2 (I/O) interupts via ioctls
@ 2014-03-14 12:47   ` James Hogan
  0 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-14 12:47 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>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Andreas Färber <afaerber@suse.de>
---
Changes in v3:
 - Pass MIPSCPU to kvm_mips_set_[ipi_]interrupt (Andreas Färber).

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

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

* [PATCH v4 08/10] hw/mips: malta: Add KVM support
  2014-03-14 12:47 ` [Qemu-devel] " James Hogan
@ 2014-03-14 12:47   ` James Hogan
  -1 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-14 12:47 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, Aurelien Jarno, Gleb Natapov, Paolo Bonzini, Sanjay Lal,
	James Hogan, Peter Maydell

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

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

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Sanjay Lal <sanjayl@kymasys.com>
---
Changes in v3:
 - Remove unnecessary includes, especially linux/kvm.h which isn't a
   good idea on non-Linux (Peter Maydell).

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 | 82 ++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 60 insertions(+), 22 deletions(-)

diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index ac5ec44..90b20d6 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -51,6 +51,7 @@
 #include "sysemu/qtest.h"
 #include "qemu/error-report.h"
 #include "hw/empty_slot.h"
+#include "sysemu/kvm.h"
 
 //#define DEBUG_BOARD_INIT
 
@@ -603,29 +604,31 @@ static void network_init(PCIBus *pci_bus)
 */
 
 static void write_bootloader (CPUMIPSState *env, uint8_t *base,
-                              int64_t kernel_entry)
+                              int64_t run_addr, int64_t kernel_entry)
 {
     uint32_t *p;
 
     /* Small bootloader */
     p = (uint32_t *)base;
-    stl_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 +704,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 +777,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 +787,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 +834,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 +843,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 +878,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 +898,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 +913,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 +1032,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] 50+ messages in thread

* [Qemu-devel] [PATCH v4 08/10] hw/mips: malta: Add KVM support
@ 2014-03-14 12:47   ` James Hogan
  0 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-14 12:47 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, 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>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Sanjay Lal <sanjayl@kymasys.com>
---
Changes in v3:
 - Remove unnecessary includes, especially linux/kvm.h which isn't a
   good idea on non-Linux (Peter Maydell).

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 | 82 ++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 60 insertions(+), 22 deletions(-)

diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index ac5ec44..90b20d6 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -51,6 +51,7 @@
 #include "sysemu/qtest.h"
 #include "qemu/error-report.h"
 #include "hw/empty_slot.h"
+#include "sysemu/kvm.h"
 
 //#define DEBUG_BOARD_INIT
 
@@ -603,29 +604,31 @@ static void network_init(PCIBus *pci_bus)
 */
 
 static void write_bootloader (CPUMIPSState *env, uint8_t *base,
-                              int64_t kernel_entry)
+                              int64_t run_addr, int64_t kernel_entry)
 {
     uint32_t *p;
 
     /* Small bootloader */
     p = (uint32_t *)base;
-    stl_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 +704,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 +777,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 +787,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 +834,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 +843,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 +878,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 +898,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 +913,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 +1032,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] 50+ messages in thread

* [PATCH v4 09/10] target-mips: Enable KVM support in build system
  2014-03-14 12:47 ` [Qemu-devel] " James Hogan
@ 2014-03-14 12:48   ` James Hogan
  -1 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-14 12:48 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>
Reviewed-by: 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 8c2838e..279344f 100755
--- a/configure
+++ b/configure
@@ -4712,6 +4712,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"
@@ -4901,7 +4904,7 @@ case "$target_name" in
   *)
 esac
 case "$target_name" in
-  aarch64|arm|i386|x86_64|ppcemb|ppc|ppc64|s390x)
+  aarch64|arm|i386|x86_64|ppcemb|ppc|ppc64|s390x|mipsel|mips)
     # Make sure the target and host cpus are compatible
     if test "$kvm" = "yes" -a "$target_softmmu" = "yes" -a \
       \( "$target_name" = "$cpu" -o \
@@ -4909,6 +4912,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] 50+ messages in thread

* [Qemu-devel] [PATCH v4 09/10] target-mips: Enable KVM support in build system
@ 2014-03-14 12:48   ` James Hogan
  0 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-14 12:48 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>
Reviewed-by: 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 8c2838e..279344f 100755
--- a/configure
+++ b/configure
@@ -4712,6 +4712,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"
@@ -4901,7 +4904,7 @@ case "$target_name" in
   *)
 esac
 case "$target_name" in
-  aarch64|arm|i386|x86_64|ppcemb|ppc|ppc64|s390x)
+  aarch64|arm|i386|x86_64|ppcemb|ppc|ppc64|s390x|mipsel|mips)
     # Make sure the target and host cpus are compatible
     if test "$kvm" = "yes" -a "$target_softmmu" = "yes" -a \
       \( "$target_name" = "$cpu" -o \
@@ -4909,6 +4912,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] 50+ messages in thread

* [PATCH v4 10/10] MAINTAINERS: Add entry for MIPS KVM
  2014-03-14 12:47 ` [Qemu-devel] " James Hogan
@ 2014-03-14 12:48   ` James Hogan
  -1 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-14 12:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, Aurelien Jarno, Gleb Natapov, Paolo Bonzini, Sanjay Lal,
	James Hogan

Add MAINTAINERS entry for MIPS KVM.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
---
Changes in v4:
 - Add MAINTAINERS entry for MIPS KVM.
---
 MAINTAINERS | 5 +++++
 1 file changed, 5 insertions(+)

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


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

* [Qemu-devel] [PATCH v4 10/10] MAINTAINERS: Add entry for MIPS KVM
@ 2014-03-14 12:48   ` James Hogan
  0 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-14 12:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: James Hogan, kvm, Gleb Natapov, Sanjay Lal, Paolo Bonzini,
	Aurelien Jarno

Add MAINTAINERS entry for MIPS KVM.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
---
Changes in v4:
 - Add MAINTAINERS entry for MIPS KVM.
---
 MAINTAINERS | 5 +++++
 1 file changed, 5 insertions(+)

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

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

* Re: [Qemu-devel] [PATCH v4 00/10] KVM Support for MIPS32 Processors
  2014-03-14 12:47 ` [Qemu-devel] " James Hogan
@ 2014-03-14 13:27   ` Peter Maydell
  -1 siblings, 0 replies; 50+ messages in thread
From: Peter Maydell @ 2014-03-14 13:27 UTC (permalink / raw)
  To: James Hogan
  Cc: QEMU Developers, kvm-devel, Gleb Natapov, Sanjay Lal,
	Paolo Bonzini, Aurelien Jarno

On 14 March 2014 12:47, James Hogan <james.hogan@imgtec.com> wrote:
> I'd like to have this squeezed into 2.0 (if at all possible), so any
> final review from KVM people would be much appreciated.

Unfortunately we're already in hardfreeze, which means
bug fixes only at this point. I don't think we can really
justify putting this patchset in at this point :-(

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v4 00/10] KVM Support for MIPS32 Processors
@ 2014-03-14 13:27   ` Peter Maydell
  0 siblings, 0 replies; 50+ messages in thread
From: Peter Maydell @ 2014-03-14 13:27 UTC (permalink / raw)
  To: James Hogan
  Cc: kvm-devel, Gleb Natapov, QEMU Developers, Sanjay Lal,
	Paolo Bonzini, Aurelien Jarno

On 14 March 2014 12:47, James Hogan <james.hogan@imgtec.com> wrote:
> I'd like to have this squeezed into 2.0 (if at all possible), so any
> final review from KVM people would be much appreciated.

Unfortunately we're already in hardfreeze, which means
bug fixes only at this point. I don't think we can really
justify putting this patchset in at this point :-(

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v4 00/10] KVM Support for MIPS32 Processors
  2014-03-14 13:27   ` Peter Maydell
@ 2014-03-14 13:29     ` James Hogan
  -1 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-14 13:29 UTC (permalink / raw)
  To: Peter Maydell
  Cc: QEMU Developers, kvm-devel, Gleb Natapov, Sanjay Lal,
	Paolo Bonzini, Aurelien Jarno

On 14/03/14 13:27, Peter Maydell wrote:
> On 14 March 2014 12:47, James Hogan <james.hogan@imgtec.com> wrote:
>> I'd like to have this squeezed into 2.0 (if at all possible), so any
>> final review from KVM people would be much appreciated.
> 
> Unfortunately we're already in hardfreeze, which means
> bug fixes only at this point. I don't think we can really
> justify putting this patchset in at this point :-(

Okay, fair enough.

Thanks
James

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

* Re: [Qemu-devel] [PATCH v4 00/10] KVM Support for MIPS32 Processors
@ 2014-03-14 13:29     ` James Hogan
  0 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-14 13:29 UTC (permalink / raw)
  To: Peter Maydell
  Cc: kvm-devel, Gleb Natapov, QEMU Developers, Sanjay Lal,
	Paolo Bonzini, Aurelien Jarno

On 14/03/14 13:27, Peter Maydell wrote:
> On 14 March 2014 12:47, James Hogan <james.hogan@imgtec.com> wrote:
>> I'd like to have this squeezed into 2.0 (if at all possible), so any
>> final review from KVM people would be much appreciated.
> 
> Unfortunately we're already in hardfreeze, which means
> bug fixes only at this point. I don't think we can really
> justify putting this patchset in at this point :-(

Okay, fair enough.

Thanks
James

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

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

Il 14/03/2014 13:47, James Hogan ha scritto:
> 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>
> Reviewed-by: 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);
> +    }
>  }
>

I hate to make you do unrelated changes, but... initializing CP0_Compare 
is unnecessary, it should already be 0; and for CP0_Count it should not 
be done here. but in cpu_state_reset function.  Then here you can call 
qemu_register_reset to register another reset callback, and call 
cpu_mips_timer_update in that callback.

I'm asking because while

     if (!kvm_enabled()) {
         env->timer = ...
         qemu_register_reset(...);
     }

is fine, changing values of registers conditionally is not.

Also, I noticed two things in the implementation of the CPU timer that 
should be fixed:

1) right now the hypervisor's frequency is hardcoded to 1/4th of the 
host, while QEMU's is 100 MHz.  It would be nice to make them either 
consistent, or customizable (you can use another ONE_REG interface to 
set CPU parameters).

2) in KVM, CP0_Count does not start at the same value on guest reset. 
There is a comment that "Linux doesn't seem to write into COUNT", but 
QEMU does.  So KVM should implement CP0_Count writes and adjust the 
"bias" of the guest CP0_Count.

In fact, right now kvm_mips_te_put_cp0_registers should always return 
-EINVAL because KVM_REG_MIPS_CP0_COUNT is not handled in 
kvm_mips_get/set_reg.  Am I missing something?

Paolo

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

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

Il 14/03/2014 13:47, James Hogan ha scritto:
> 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>
> Reviewed-by: 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);
> +    }
>  }
>

I hate to make you do unrelated changes, but... initializing CP0_Compare 
is unnecessary, it should already be 0; and for CP0_Count it should not 
be done here. but in cpu_state_reset function.  Then here you can call 
qemu_register_reset to register another reset callback, and call 
cpu_mips_timer_update in that callback.

I'm asking because while

     if (!kvm_enabled()) {
         env->timer = ...
         qemu_register_reset(...);
     }

is fine, changing values of registers conditionally is not.

Also, I noticed two things in the implementation of the CPU timer that 
should be fixed:

1) right now the hypervisor's frequency is hardcoded to 1/4th of the 
host, while QEMU's is 100 MHz.  It would be nice to make them either 
consistent, or customizable (you can use another ONE_REG interface to 
set CPU parameters).

2) in KVM, CP0_Count does not start at the same value on guest reset. 
There is a comment that "Linux doesn't seem to write into COUNT", but 
QEMU does.  So KVM should implement CP0_Count writes and adjust the 
"bias" of the guest CP0_Count.

In fact, right now kvm_mips_te_put_cp0_registers should always return 
-EINVAL because KVM_REG_MIPS_CP0_COUNT is not handled in 
kvm_mips_get/set_reg.  Am I missing something?

Paolo

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

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

Il 14/03/2014 13:47, James Hogan ha scritto:
> +    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;
> +            }
> +        }
> +    }

Besides changing the segment bases, is there anything else to do to run 
KVM-enabled kernels under TCG?  (I know nothing about MIPS and it 
shows).  We should consider adding a knob to run them in TCG mode.

This is not blocking this series, and I'm okay with helping or even 
doing the work, if somebody tells me what to do. :)

Paolo

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

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

Il 14/03/2014 13:47, James Hogan ha scritto:
> +    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;
> +            }
> +        }
> +    }

Besides changing the segment bases, is there anything else to do to run 
KVM-enabled kernels under TCG?  (I know nothing about MIPS and it 
shows).  We should consider adding a knob to run them in TCG mode.

This is not blocking this series, and I'm okay with helping or even 
doing the work, if somebody tells me what to do. :)

Paolo

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

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

Il 14/03/2014 13:47, James Hogan ha scritto:
> Add preprocessor definitions for 32bit segment bases for use in
> get_physical_address(). These will also be taken advantage of in the
> next patch which adds KVM awareness.
>
> Signed-off-by: James Hogan <james.hogan@imgtec.com>
> Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
> ---
>  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 b28ae9b..2b30fc2 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
> +

Please put these outside the function.  (Same for those in patch 4).

> +    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);
>


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

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

Il 14/03/2014 13:47, James Hogan ha scritto:
> Add preprocessor definitions for 32bit segment bases for use in
> get_physical_address(). These will also be taken advantage of in the
> next patch which adds KVM awareness.
>
> Signed-off-by: James Hogan <james.hogan@imgtec.com>
> Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
> ---
>  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 b28ae9b..2b30fc2 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
> +

Please put these outside the function.  (Same for those in patch 4).

> +    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);
>

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

* Re: [PATCH v4 08/10] hw/mips: malta: Add KVM support
  2014-03-14 12:47   ` [Qemu-devel] " James Hogan
@ 2014-03-19 16:39     ` Paolo Bonzini
  -1 siblings, 0 replies; 50+ messages in thread
From: Paolo Bonzini @ 2014-03-19 16:39 UTC (permalink / raw)
  To: James Hogan, qemu-devel
  Cc: kvm, Aurelien Jarno, Gleb Natapov, Sanjay Lal, Peter Maydell

Il 14/03/2014 13:47, James Hogan ha scritto:
>      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 +787,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 +834,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 +843,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));
>

Why do you need the function pointers?  Can 
cpu_mips_kseg0_to_phys/cpu_mips_phys_to_kseg0 just use kvm_enabled()?

Paolo

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

* Re: [Qemu-devel] [PATCH v4 08/10] hw/mips: malta: Add KVM support
@ 2014-03-19 16:39     ` Paolo Bonzini
  0 siblings, 0 replies; 50+ messages in thread
From: Paolo Bonzini @ 2014-03-19 16:39 UTC (permalink / raw)
  To: James Hogan, qemu-devel
  Cc: Sanjay Lal, Gleb Natapov, Aurelien Jarno, kvm, Peter Maydell

Il 14/03/2014 13:47, James Hogan ha scritto:
>      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 +787,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 +834,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 +843,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));
>

Why do you need the function pointers?  Can 
cpu_mips_kseg0_to_phys/cpu_mips_phys_to_kseg0 just use kvm_enabled()?

Paolo

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

* Re: [PATCH v4 00/10] KVM Support for MIPS32 Processors
  2014-03-14 12:47 ` [Qemu-devel] " James Hogan
@ 2014-03-19 16:39   ` Paolo Bonzini
  -1 siblings, 0 replies; 50+ messages in thread
From: Paolo Bonzini @ 2014-03-19 16:39 UTC (permalink / raw)
  To: James Hogan, qemu-devel; +Cc: kvm, Aurelien Jarno, Gleb Natapov, Sanjay Lal

Il 14/03/2014 13:47, James Hogan ha scritto:
> 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.

Just a few comments.  With what version of the kernel can this be tested?

Paolo

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

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

Il 14/03/2014 13:47, James Hogan ha scritto:
> 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.

Just a few comments.  With what version of the kernel can this be tested?

Paolo

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

* Re: [PATCH v4 01/10] hw/mips/cputimer: Don't start periodic timer in KVM mode
  2014-03-19 16:29     ` [Qemu-devel] " Paolo Bonzini
@ 2014-03-20  9:57       ` James Hogan
  -1 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-20  9:57 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel, kvm, Aurelien Jarno, Gleb Natapov, Sanjay Lal

[-- Attachment #1: Type: text/plain, Size: 3740 bytes --]

On 19/03/14 16:29, Paolo Bonzini wrote:
> Il 14/03/2014 13:47, James Hogan ha scritto:
>> 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>
>> Reviewed-by: 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);
>> +    }
>>  }
>>
> 
> I hate to make you do unrelated changes, but... initializing CP0_Compare
> is unnecessary, it should already be 0;

You mean because of the memset in object_initialize_with_type, when
object_new is called? Although that wouldn't handle reset, although
technically the reset state of Compare is undefined.

> and for CP0_Count it should not
> be done here. but in cpu_state_reset function.  Then here you can call
> qemu_register_reset to register another reset callback, and call
> cpu_mips_timer_update in that callback.
> 
> I'm asking because while
> 
>     if (!kvm_enabled()) {
>         env->timer = ...
>         qemu_register_reset(...);
>     }
> 
> is fine, changing values of registers conditionally is not.

Okay, makes sense.

> 
> Also, I noticed two things in the implementation of the CPU timer that
> should be fixed:
> 
> 1) right now the hypervisor's frequency is hardcoded to 1/4th of the
> host, while QEMU's is 100 MHz.  It would be nice to make them either
> consistent, or customizable (you can use another ONE_REG interface to
> set CPU parameters).

Agreed. I'm in the middle of fixing the count/compare timer in KVM to be
based on real time (ktime_get()), so I'll make it default to 100MHz to
match QEMU for now. I can imagine it being useful to be able to control
it too depending on whether you're running on a slow FPGA/emulator or
fast silicon.

> 2) in KVM, CP0_Count does not start at the same value on guest reset.
> There is a comment that "Linux doesn't seem to write into COUNT", but
> QEMU does.  So KVM should implement CP0_Count writes and adjust the
> "bias" of the guest CP0_Count.

True, I hadn't considered qemu writing those registers yet.

Am I right that the correct way to prevent clock drift is for
kvm_arch_put_registers to only set the Count register if level !=
KVM_PUT_RUNTIME_STATE?

> In fact, right now kvm_mips_te_put_cp0_registers should always return
> -EINVAL because KVM_REG_MIPS_CP0_COUNT is not handled in
> kvm_mips_get/set_reg.  Am I missing something?

Yes, you appear to be right!

Thanks a lot for reviewing

Cheers
James


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [Qemu-devel] [PATCH v4 01/10] hw/mips/cputimer: Don't start periodic timer in KVM mode
@ 2014-03-20  9:57       ` James Hogan
  0 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-20  9:57 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Aurelien Jarno, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

[-- Attachment #1: Type: text/plain, Size: 3740 bytes --]

On 19/03/14 16:29, Paolo Bonzini wrote:
> Il 14/03/2014 13:47, James Hogan ha scritto:
>> 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>
>> Reviewed-by: 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);
>> +    }
>>  }
>>
> 
> I hate to make you do unrelated changes, but... initializing CP0_Compare
> is unnecessary, it should already be 0;

You mean because of the memset in object_initialize_with_type, when
object_new is called? Although that wouldn't handle reset, although
technically the reset state of Compare is undefined.

> and for CP0_Count it should not
> be done here. but in cpu_state_reset function.  Then here you can call
> qemu_register_reset to register another reset callback, and call
> cpu_mips_timer_update in that callback.
> 
> I'm asking because while
> 
>     if (!kvm_enabled()) {
>         env->timer = ...
>         qemu_register_reset(...);
>     }
> 
> is fine, changing values of registers conditionally is not.

Okay, makes sense.

> 
> Also, I noticed two things in the implementation of the CPU timer that
> should be fixed:
> 
> 1) right now the hypervisor's frequency is hardcoded to 1/4th of the
> host, while QEMU's is 100 MHz.  It would be nice to make them either
> consistent, or customizable (you can use another ONE_REG interface to
> set CPU parameters).

Agreed. I'm in the middle of fixing the count/compare timer in KVM to be
based on real time (ktime_get()), so I'll make it default to 100MHz to
match QEMU for now. I can imagine it being useful to be able to control
it too depending on whether you're running on a slow FPGA/emulator or
fast silicon.

> 2) in KVM, CP0_Count does not start at the same value on guest reset.
> There is a comment that "Linux doesn't seem to write into COUNT", but
> QEMU does.  So KVM should implement CP0_Count writes and adjust the
> "bias" of the guest CP0_Count.

True, I hadn't considered qemu writing those registers yet.

Am I right that the correct way to prevent clock drift is for
kvm_arch_put_registers to only set the Count register if level !=
KVM_PUT_RUNTIME_STATE?

> In fact, right now kvm_mips_te_put_cp0_registers should always return
> -EINVAL because KVM_REG_MIPS_CP0_COUNT is not handled in
> kvm_mips_get/set_reg.  Am I missing something?

Yes, you appear to be right!

Thanks a lot for reviewing

Cheers
James


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [PATCH v4 00/10] KVM Support for MIPS32 Processors
  2014-03-19 16:39   ` [Qemu-devel] " Paolo Bonzini
@ 2014-03-20 10:00     ` James Hogan
  -1 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-20 10:00 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel, kvm, Aurelien Jarno, Gleb Natapov, Sanjay Lal

[-- Attachment #1: Type: text/plain, Size: 798 bytes --]

On 19/03/14 16:39, Paolo Bonzini wrote:
> Il 14/03/2014 13:47, James Hogan ha scritto:
>> 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.
> 
> Just a few comments.  With what version of the kernel can this be tested?

KVM support was added in v3.10, including defconfigs and a
CONFIG_KVM_GUEST to ensure the kernel is linked to the different address.

Cheerse
James


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [Qemu-devel] [PATCH v4 00/10] KVM Support for MIPS32 Processors
@ 2014-03-20 10:00     ` James Hogan
  0 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-20 10:00 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Aurelien Jarno, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

[-- Attachment #1: Type: text/plain, Size: 798 bytes --]

On 19/03/14 16:39, Paolo Bonzini wrote:
> Il 14/03/2014 13:47, James Hogan ha scritto:
>> 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.
> 
> Just a few comments.  With what version of the kernel can this be tested?

KVM support was added in v3.10, including defconfigs and a
CONFIG_KVM_GUEST to ensure the kernel is linked to the different address.

Cheerse
James


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [PATCH v4 04/10] target-mips: get_physical_address: Add KVM awareness
  2014-03-19 16:33     ` [Qemu-devel] " Paolo Bonzini
@ 2014-03-20 10:08       ` James Hogan
  -1 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-20 10:08 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel, kvm, Aurelien Jarno, Gleb Natapov, Sanjay Lal

[-- Attachment #1: Type: text/plain, Size: 1283 bytes --]

On 19/03/14 16:33, Paolo Bonzini wrote:
> Il 14/03/2014 13:47, James Hogan ha scritto:
>> +    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;
>> +            }
>> +        }
>> +    }
> 
> Besides changing the segment bases, is there anything else to do to run
> KVM-enabled kernels under TCG?  (I know nothing about MIPS and it
> shows).  We should consider adding a knob to run them in TCG mode.
> 
> This is not blocking this series, and I'm okay with helping or even
> doing the work, if somebody tells me what to do. :)

That's a good idea. It's pretty much just the extra segments I think. In
TCG mode the bootloader wouldn't even need to do anything different
since it can translate fine from the reset vector in kseg1 (where a KVM
guest cannot execute from) and it'll still jump to the kernel entry
point from the ELF.

I'll add it to my list :)

Cheers
James


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [Qemu-devel] [PATCH v4 04/10] target-mips: get_physical_address: Add KVM awareness
@ 2014-03-20 10:08       ` James Hogan
  0 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-20 10:08 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Aurelien Jarno, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

[-- Attachment #1: Type: text/plain, Size: 1283 bytes --]

On 19/03/14 16:33, Paolo Bonzini wrote:
> Il 14/03/2014 13:47, James Hogan ha scritto:
>> +    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;
>> +            }
>> +        }
>> +    }
> 
> Besides changing the segment bases, is there anything else to do to run
> KVM-enabled kernels under TCG?  (I know nothing about MIPS and it
> shows).  We should consider adding a knob to run them in TCG mode.
> 
> This is not blocking this series, and I'm okay with helping or even
> doing the work, if somebody tells me what to do. :)

That's a good idea. It's pretty much just the extra segments I think. In
TCG mode the bootloader wouldn't even need to do anything different
since it can translate fine from the reset vector in kseg1 (where a KVM
guest cannot execute from) and it'll still jump to the kernel entry
point from the ELF.

I'll add it to my list :)

Cheers
James


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [PATCH v4 08/10] hw/mips: malta: Add KVM support
  2014-03-19 16:39     ` [Qemu-devel] " Paolo Bonzini
@ 2014-03-20 10:17       ` James Hogan
  -1 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-20 10:17 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: qemu-devel, kvm, Aurelien Jarno, Gleb Natapov, Sanjay Lal, Peter Maydell

[-- Attachment #1: Type: text/plain, Size: 2622 bytes --]

On 19/03/14 16:39, Paolo Bonzini wrote:
> Il 14/03/2014 13:47, James Hogan ha scritto:
>>      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 +787,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 +834,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 +843,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));
>>
> 
> Why do you need the function pointers?  Can
> cpu_mips_kseg0_to_phys/cpu_mips_phys_to_kseg0 just use kvm_enabled()?

Maybe because of its use as an argument to load_elf, which presumably
calls it multiple times. Although looking at glue(load_elf, SZ) I think
it's only used for each load section so I doubt it would make a
difference. I'll change it.

Cheers
James


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [Qemu-devel] [PATCH v4 08/10] hw/mips: malta: Add KVM support
@ 2014-03-20 10:17       ` James Hogan
  0 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-20 10:17 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Peter Maydell, kvm, Gleb Natapov, qemu-devel, Sanjay Lal, Aurelien Jarno

[-- Attachment #1: Type: text/plain, Size: 2622 bytes --]

On 19/03/14 16:39, Paolo Bonzini wrote:
> Il 14/03/2014 13:47, James Hogan ha scritto:
>>      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 +787,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 +834,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 +843,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));
>>
> 
> Why do you need the function pointers?  Can
> cpu_mips_kseg0_to_phys/cpu_mips_phys_to_kseg0 just use kvm_enabled()?

Maybe because of its use as an argument to load_elf, which presumably
calls it multiple times. Although looking at glue(load_elf, SZ) I think
it's only used for each load section so I doubt it would make a
difference. I'll change it.

Cheers
James


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [PATCH v4 00/10] KVM Support for MIPS32 Processors
  2014-03-20 10:00     ` [Qemu-devel] " James Hogan
@ 2014-03-20 12:44       ` Paolo Bonzini
  -1 siblings, 0 replies; 50+ messages in thread
From: Paolo Bonzini @ 2014-03-20 12:44 UTC (permalink / raw)
  To: James Hogan; +Cc: qemu-devel, kvm, Aurelien Jarno, Gleb Natapov, Sanjay Lal

Il 20/03/2014 11:00, James Hogan ha scritto:
>> > Just a few comments.  With what version of the kernel can this be tested?
> KVM support was added in v3.10, including defconfigs and a
> CONFIG_KVM_GUEST to ensure the kernel is linked to the different address.

Yes, but you still need support for CP0_COUNT/CP0_COMPARE in the onereg 
interface.  I haven't checked if other registers are missing.

Paolo

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

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

Il 20/03/2014 11:00, James Hogan ha scritto:
>> > Just a few comments.  With what version of the kernel can this be tested?
> KVM support was added in v3.10, including defconfigs and a
> CONFIG_KVM_GUEST to ensure the kernel is linked to the different address.

Yes, but you still need support for CP0_COUNT/CP0_COMPARE in the onereg 
interface.  I haven't checked if other registers are missing.

Paolo

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

* Re: [PATCH v4 01/10] hw/mips/cputimer: Don't start periodic timer in KVM mode
  2014-03-20  9:57       ` [Qemu-devel] " James Hogan
@ 2014-03-20 22:36         ` Paolo Bonzini
  -1 siblings, 0 replies; 50+ messages in thread
From: Paolo Bonzini @ 2014-03-20 22:36 UTC (permalink / raw)
  To: James Hogan; +Cc: qemu-devel, kvm, Aurelien Jarno, Gleb Natapov, Sanjay Lal

Il 20/03/2014 10:57, James Hogan ha scritto:
> On 19/03/14 16:29, Paolo Bonzini wrote:
>> Il 14/03/2014 13:47, James Hogan ha scritto:
>>> 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>
>>> Reviewed-by: 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);
>>> +    }
>>>  }
>>>
>>
>> I hate to make you do unrelated changes, but... initializing CP0_Compare
>> is unnecessary, it should already be 0;
> 
> You mean because of the memset in object_initialize_with_type, when
> object_new is called? Although that wouldn't handle reset, although
> technically the reset state of Compare is undefined.

No, see mips_cpu_reset:

static void mips_cpu_reset(CPUState *s)
{
    MIPSCPU *cpu = MIPS_CPU(s);
    MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(cpu);
    CPUMIPSState *env = &cpu->env;

    mcc->parent_reset(s);

    memset(env, 0, offsetof(CPUMIPSState, mvp));
    tlb_flush(s, 1);

    cpu_state_reset(env);
}

Fields before mvp are reset to zero (including CP0_Compare and CP0_Count).

> Am I right that the correct way to prevent clock drift is for
> kvm_arch_put_registers to only set the Count register if level !=
> KVM_PUT_RUNTIME_STATE?

Yes, that makes sense.  Or, better, do not provide a set_onereg 
interface for CP0_Count.  Instead, in the kernel you can base the CPU 
timer on the value of CLOCK_MONOTONIC, like this:

+static inline u64 get_monotonic_ns(void)
+{
+	struct timespec ts;
+
+	ktime_get_ts(&ts);
+	return timespec_to_ns(&ts);
+}
+

Then you provide three set_onereg interfaces.  One is normal cp0_count, 
but it is only used if the timer is not running (according to 
cp0_cause).  The second is the rate at which the timer counts 
(cp0_count_hz).  The third is used when the timer is running, and
it is:

	cp0_count_bias
	   = cp0_count * 10^9 / cp0_count_hz - get_monotonic_ns()

So when the timer is running cp0_count is computed as follows:

	cp0_count =
	  = (get_monotonic_ns() + cp0_count_bias) * cp0_count_hz / 10^9

QEMU can then set:

  cp0_count = cpu_mips_get_count(env)
  cp0_count_bias =
     cpu_mips_get_count(env) * 10^9 / cp0_count_hz - qemu_get_clock_ns(rt_clock)

Note that QEMU's qemu_get_clock_ns(rt_clock) == kernel's get_monotonic_ns().

So when the guest reads cp0_count (and the timer was running at the time
kvm_arch_put_registers was set), the kernel will return:

	cp0_count =
	 = (get_monotonic_ns() + cp0_count_bias) * cp0_count_hz / 10^9
	 = env->cp0_count
           + (get_monotonic_ns() - qemu_get_clock_ns(rt_clock)
                                 + qemu_get_clock_ns(vm_clock)) * cp0_count_hz / 10^9
	 = env->cp0_count + qemu_get_clock_ns(vm_clock) * cp0_count_hz / 10^9
         = cpu_mips_get_count(env)
	
Paolo

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

* Re: [Qemu-devel] [PATCH v4 01/10] hw/mips/cputimer: Don't start periodic timer in KVM mode
@ 2014-03-20 22:36         ` Paolo Bonzini
  0 siblings, 0 replies; 50+ messages in thread
From: Paolo Bonzini @ 2014-03-20 22:36 UTC (permalink / raw)
  To: James Hogan; +Cc: Aurelien Jarno, Gleb Natapov, qemu-devel, kvm, Sanjay Lal

Il 20/03/2014 10:57, James Hogan ha scritto:
> On 19/03/14 16:29, Paolo Bonzini wrote:
>> Il 14/03/2014 13:47, James Hogan ha scritto:
>>> 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>
>>> Reviewed-by: 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);
>>> +    }
>>>  }
>>>
>>
>> I hate to make you do unrelated changes, but... initializing CP0_Compare
>> is unnecessary, it should already be 0;
> 
> You mean because of the memset in object_initialize_with_type, when
> object_new is called? Although that wouldn't handle reset, although
> technically the reset state of Compare is undefined.

No, see mips_cpu_reset:

static void mips_cpu_reset(CPUState *s)
{
    MIPSCPU *cpu = MIPS_CPU(s);
    MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(cpu);
    CPUMIPSState *env = &cpu->env;

    mcc->parent_reset(s);

    memset(env, 0, offsetof(CPUMIPSState, mvp));
    tlb_flush(s, 1);

    cpu_state_reset(env);
}

Fields before mvp are reset to zero (including CP0_Compare and CP0_Count).

> Am I right that the correct way to prevent clock drift is for
> kvm_arch_put_registers to only set the Count register if level !=
> KVM_PUT_RUNTIME_STATE?

Yes, that makes sense.  Or, better, do not provide a set_onereg 
interface for CP0_Count.  Instead, in the kernel you can base the CPU 
timer on the value of CLOCK_MONOTONIC, like this:

+static inline u64 get_monotonic_ns(void)
+{
+	struct timespec ts;
+
+	ktime_get_ts(&ts);
+	return timespec_to_ns(&ts);
+}
+

Then you provide three set_onereg interfaces.  One is normal cp0_count, 
but it is only used if the timer is not running (according to 
cp0_cause).  The second is the rate at which the timer counts 
(cp0_count_hz).  The third is used when the timer is running, and
it is:

	cp0_count_bias
	   = cp0_count * 10^9 / cp0_count_hz - get_monotonic_ns()

So when the timer is running cp0_count is computed as follows:

	cp0_count =
	  = (get_monotonic_ns() + cp0_count_bias) * cp0_count_hz / 10^9

QEMU can then set:

  cp0_count = cpu_mips_get_count(env)
  cp0_count_bias =
     cpu_mips_get_count(env) * 10^9 / cp0_count_hz - qemu_get_clock_ns(rt_clock)

Note that QEMU's qemu_get_clock_ns(rt_clock) == kernel's get_monotonic_ns().

So when the guest reads cp0_count (and the timer was running at the time
kvm_arch_put_registers was set), the kernel will return:

	cp0_count =
	 = (get_monotonic_ns() + cp0_count_bias) * cp0_count_hz / 10^9
	 = env->cp0_count
           + (get_monotonic_ns() - qemu_get_clock_ns(rt_clock)
                                 + qemu_get_clock_ns(vm_clock)) * cp0_count_hz / 10^9
	 = env->cp0_count + qemu_get_clock_ns(vm_clock) * cp0_count_hz / 10^9
         = cpu_mips_get_count(env)
	
Paolo

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

* Re: [PATCH v4 00/10] KVM Support for MIPS32 Processors
  2014-03-20 12:44       ` [Qemu-devel] " Paolo Bonzini
@ 2014-03-21 16:51         ` James Hogan
  -1 siblings, 0 replies; 50+ messages in thread
From: James Hogan @ 2014-03-21 16:51 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel, kvm, Aurelien Jarno, Gleb Natapov, Sanjay Lal

[-- Attachment #1: Type: text/plain, Size: 912 bytes --]

On 20/03/14 12:44, Paolo Bonzini wrote:
> Il 20/03/2014 11:00, James Hogan ha scritto:
>>> > Just a few comments.  With what version of the kernel can this be
>>> tested?
>> KVM support was added in v3.10, including defconfigs and a
>> CONFIG_KVM_GUEST to ensure the kernel is linked to the different address.
> 
> Yes, but you still need support for CP0_COUNT/CP0_COMPARE in the onereg
> interface.  I haven't checked if other registers are missing.

Indeed, I'm working on fixing that now. EPC is missing too (there's a
comment in there about EPC which AFAICT seems to confuse the guest
CP0_EPC with the guest PC which are distinct state for full system
emulation).

Also unfortunately the CP0 register ids provided by QEMU all
(incorrectly) lack the size part too. Remarkably it generally works
quite well despite this since KVM takes care of most of the runtime details.

Cheers
James


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

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

[-- Attachment #1: Type: text/plain, Size: 912 bytes --]

On 20/03/14 12:44, Paolo Bonzini wrote:
> Il 20/03/2014 11:00, James Hogan ha scritto:
>>> > Just a few comments.  With what version of the kernel can this be
>>> tested?
>> KVM support was added in v3.10, including defconfigs and a
>> CONFIG_KVM_GUEST to ensure the kernel is linked to the different address.
> 
> Yes, but you still need support for CP0_COUNT/CP0_COMPARE in the onereg
> interface.  I haven't checked if other registers are missing.

Indeed, I'm working on fixing that now. EPC is missing too (there's a
comment in there about EPC which AFAICT seems to confuse the guest
CP0_EPC with the guest PC which are distinct state for full system
emulation).

Also unfortunately the CP0 register ids provided by QEMU all
(incorrectly) lack the size part too. Remarkably it generally works
quite well despite this since KVM takes care of most of the runtime details.

Cheers
James


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

end of thread, other threads:[~2014-03-21 16:51 UTC | newest]

Thread overview: 50+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-14 12:47 [PATCH v4 00/10] KVM Support for MIPS32 Processors James Hogan
2014-03-14 12:47 ` [Qemu-devel] " James Hogan
2014-03-14 12:47 ` [PATCH v4 01/10] hw/mips/cputimer: Don't start periodic timer in KVM mode James Hogan
2014-03-14 12:47   ` [Qemu-devel] " James Hogan
2014-03-19 16:29   ` Paolo Bonzini
2014-03-19 16:29     ` [Qemu-devel] " Paolo Bonzini
2014-03-20  9:57     ` James Hogan
2014-03-20  9:57       ` [Qemu-devel] " James Hogan
2014-03-20 22:36       ` Paolo Bonzini
2014-03-20 22:36         ` [Qemu-devel] " Paolo Bonzini
2014-03-14 12:47 ` [PATCH v4 02/10] hw/mips: Add API to convert KVM guest KSEG0 <-> GPA James Hogan
2014-03-14 12:47   ` [Qemu-devel] " James Hogan
2014-03-14 12:47 ` [PATCH v4 03/10] target-mips: get_physical_address: Add defines for segment bases James Hogan
2014-03-14 12:47   ` [Qemu-devel] " James Hogan
2014-03-19 16:33   ` Paolo Bonzini
2014-03-19 16:33     ` [Qemu-devel] " Paolo Bonzini
2014-03-14 12:47 ` [PATCH v4 04/10] target-mips: get_physical_address: Add KVM awareness James Hogan
2014-03-14 12:47   ` [Qemu-devel] " James Hogan
2014-03-19 16:33   ` Paolo Bonzini
2014-03-19 16:33     ` [Qemu-devel] " Paolo Bonzini
2014-03-20 10:08     ` James Hogan
2014-03-20 10:08       ` [Qemu-devel] " James Hogan
2014-03-14 12:47 ` [PATCH v4 05/10] kvm: Allow arch to set sigmask length James Hogan
2014-03-14 12:47   ` [Qemu-devel] " James Hogan
2014-03-14 12:47 ` [PATCH v4 06/10] target-mips: kvm: Add main KVM support for MIPS James Hogan
2014-03-14 12:47   ` [Qemu-devel] " James Hogan
2014-03-14 12:47 ` [PATCH v4 07/10] hw/mips: In KVM mode, inject IRQ2 (I/O) interupts via ioctls James Hogan
2014-03-14 12:47   ` [Qemu-devel] " James Hogan
2014-03-14 12:47 ` [PATCH v4 08/10] hw/mips: malta: Add KVM support James Hogan
2014-03-14 12:47   ` [Qemu-devel] " James Hogan
2014-03-19 16:39   ` Paolo Bonzini
2014-03-19 16:39     ` [Qemu-devel] " Paolo Bonzini
2014-03-20 10:17     ` James Hogan
2014-03-20 10:17       ` [Qemu-devel] " James Hogan
2014-03-14 12:48 ` [PATCH v4 09/10] target-mips: Enable KVM support in build system James Hogan
2014-03-14 12:48   ` [Qemu-devel] " James Hogan
2014-03-14 12:48 ` [PATCH v4 10/10] MAINTAINERS: Add entry for MIPS KVM James Hogan
2014-03-14 12:48   ` [Qemu-devel] " James Hogan
2014-03-14 13:27 ` [Qemu-devel] [PATCH v4 00/10] KVM Support for MIPS32 Processors Peter Maydell
2014-03-14 13:27   ` Peter Maydell
2014-03-14 13:29   ` James Hogan
2014-03-14 13:29     ` James Hogan
2014-03-19 16:39 ` Paolo Bonzini
2014-03-19 16:39   ` [Qemu-devel] " Paolo Bonzini
2014-03-20 10:00   ` James Hogan
2014-03-20 10:00     ` [Qemu-devel] " James Hogan
2014-03-20 12:44     ` Paolo Bonzini
2014-03-20 12:44       ` [Qemu-devel] " Paolo Bonzini
2014-03-21 16:51       ` James Hogan
2014-03-21 16:51         ` [Qemu-devel] " 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.