Re: mpc870 support in the powerpc arch?

2010-06-25 Thread Shawn Jin
On Mon, May 17, 2010 at 12:54 PM, Scott Wood scottw...@freescale.com wrote:
 On Fri, May 14, 2010 at 02:41:29PM -0700, Shawn Jin wrote:
 Hi,

 Is mpc870 fully supported in the powerpc arch? I know it's an old
 processor but 8xx is still one of platforms in the powerpc arch. If
 it's not supported, how much effort will it be to resurrect mpc870 in
 the new arch considering we have substantial 8xx support?

 It should work, with appropriate board support -- MPC875 and MPC885 have
 been used with arch/powerpc, and MPC870 is very similar (albeit with fewer
 devices).

Thanks Scott. I found your implementation in the kernel. I use
adder875 as my base to port my board support. But I'm having a problem
in the last step to create the cuImage. You may know what I did wrong.
The error message is as follows.

  WRAParch/powerpc/boot/cuImage.my870
ppc_8xx-ld: arch/powerpc/boot/cuboot-my870.o: No such file: No such
file or directory
make[1]: *** [arch/powerpc/boot/cuImage.my870] Error 1

I believe the default cuboot-8xx.c should be enough for my board to
fix up the board settings. I don't know why the linker was looking for
this cuboot-my870.o object file.

BTW, my kernel is 2.6.33.5.

Thanks,
-Shawn.
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH] kvm/ppc: fix build warning

2010-06-25 Thread Alexander Graf

On 25.06.2010, at 11:02, Denis Kirjanov wrote:

 On 06/25/2010 12:42 AM, Alexander Graf wrote:
 
 On 24.06.2010, at 21:44, Denis Kirjanov wrote:
 
 Fix build warning:
 arch/powerpc/kvm/book3s_64_mmu.c: In function 
 'kvmppc_mmu_book3s_64_esid_to_vsid':
 arch/powerpc/kvm/book3s_64_mmu.c:446: warning: 'slb' may be used 
 uninitialized in this function
 Signed-off-by: Denis Kirjanovdkirja...@kernel.org
 
 Are you sure this isn't a broken compiler? I don't see where it could be 
 used uninitialized.
 
 I'm using gcc version 4.3.4 (Gentoo 4.3.4 p1.1, pie-10.1.5)
 slb pointer initialized inside conditional branch
 and used later in the case case MSR_DR|MSR_IR
 

Oh, I'm apparently looking at completely different code. The same function in 
git://git.kernel.org/pub/scm/virt/kvm/kvm.git is good. Which tree did you use?


Alex

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH] Adjust arch/powerpc inline asms for recent gcc change

2010-06-25 Thread Jakub Jelinek
Hi!

I've recently changed gcc handling of inline-asm, such that it by default
disallows side-effects on memory operands of inline-asm and only allows
them if  or  constraint is present for the operand.
See http://gcc.gnu.org/PR44492 and http://bugzilla.redhat.com/602359
for details.  The change prevents miscompilations with inline-asm using m,
g etc. constraints and either not using the the operand at all, or not
in an instruction (e.g. in some data section, comment, etc.), or using it
twice or more, or on architectures that require it such as PowerPC or IA-64
not using it in instructions that handle the side-effects, or not using
on PowerPC %UN corresponding to the operand, or on IA-64 not using %PN.
It might penalize asm written with side-effects in mind.
This completely untested patch adjusts the constraints of such inline-asm
operands in powerpc kernel (and fixes one bug where %U was used for
incorrect operand).

Signed-off-by: Jakub Jelinek ja...@redhat.com

 boot/io.h |   12 ++--
 include/asm/atomic.h  |8 
 include/asm/io.h  |4 ++--
 include/asm/pgtable.h |4 ++--
 4 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/arch/powerpc/boot/io.h b/arch/powerpc/boot/io.h
index 7c09f48..3dd1462 100644
--- a/arch/powerpc/boot/io.h
+++ b/arch/powerpc/boot/io.h
@@ -13,14 +13,14 @@ static inline int in_8(const volatile unsigned char *addr)
int ret;
 
__asm__ __volatile__(lbz%U1%X1 %0,%1; twi 0,%0,0; isync
-: =r (ret) : m (*addr));
+: =r (ret) : m (*addr));
return ret;
 }
 
 static inline void out_8(volatile unsigned char *addr, int val)
 {
__asm__ __volatile__(stb%U0%X0 %1,%0; sync
-: =m (*addr) : r (val));
+: =m (*addr) : r (val));
 }
 
 static inline unsigned in_le16(const volatile u16 *addr)
@@ -38,7 +38,7 @@ static inline unsigned in_be16(const volatile u16 *addr)
unsigned ret;
 
__asm__ __volatile__(lhz%U1%X1 %0,%1; twi 0,%0,0; isync
-: =r (ret) : m (*addr));
+: =r (ret) : m (*addr));
return ret;
 }
 
@@ -51,7 +51,7 @@ static inline void out_le16(volatile u16 *addr, int val)
 static inline void out_be16(volatile u16 *addr, int val)
 {
__asm__ __volatile__(sth%U0%X0 %1,%0; sync
-: =m (*addr) : r (val));
+: =m (*addr) : r (val));
 }
 
 static inline unsigned in_le32(const volatile unsigned *addr)
@@ -68,7 +68,7 @@ static inline unsigned in_be32(const volatile unsigned *addr)
unsigned ret;
 
__asm__ __volatile__(lwz%U1%X1 %0,%1; twi 0,%0,0; isync
-: =r (ret) : m (*addr));
+: =r (ret) : m (*addr));
return ret;
 }
 
@@ -81,7 +81,7 @@ static inline void out_le32(volatile unsigned *addr, int val)
 static inline void out_be32(volatile unsigned *addr, int val)
 {
__asm__ __volatile__(stw%U0%X0 %1,%0; sync
-: =m (*addr) : r (val));
+: =m (*addr) : r (val));
 }
 
 static inline void sync(void)
diff --git a/arch/powerpc/include/asm/atomic.h 
b/arch/powerpc/include/asm/atomic.h
index b8f152e..288d8b2 100644
--- a/arch/powerpc/include/asm/atomic.h
+++ b/arch/powerpc/include/asm/atomic.h
@@ -19,14 +19,14 @@ static __inline__ int atomic_read(const atomic_t *v)
 {
int t;
 
-   __asm__ __volatile__(lwz%U1%X1 %0,%1 : =r(t) : m(v-counter));
+   __asm__ __volatile__(lwz%U1%X1 %0,%1 : =r(t) : m(v-counter));
 
return t;
 }
 
 static __inline__ void atomic_set(atomic_t *v, int i)
 {
-   __asm__ __volatile__(stw%U0%X0 %1,%0 : =m(v-counter) : r(i));
+   __asm__ __volatile__(stw%U0%X0 %1,%0 : =m(v-counter) : r(i));
 }
 
 static __inline__ void atomic_add(int a, atomic_t *v)
@@ -257,14 +257,14 @@ static __inline__ long atomic64_read(const atomic64_t *v)
 {
long t;
 
-   __asm__ __volatile__(ld%U1%X1 %0,%1 : =r(t) : m(v-counter));
+   __asm__ __volatile__(ld%U1%X1 %0,%1 : =r(t) : m(v-counter));
 
return t;
 }
 
 static __inline__ void atomic64_set(atomic64_t *v, long i)
 {
-   __asm__ __volatile__(std%U0%X0 %1,%0 : =m(v-counter) : r(i));
+   __asm__ __volatile__(std%U0%X0 %1,%0 : =m(v-counter) : r(i));
 }
 
 static __inline__ void atomic64_add(long a, atomic64_t *v)
diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h
index 001f2f1..f05db20 100644
--- a/arch/powerpc/include/asm/io.h
+++ b/arch/powerpc/include/asm/io.h
@@ -137,7 +137,7 @@ static inline u##size name(const volatile u##size __iomem 
*addr)\
 {  \
u##size ret;\
__asm__ __volatile__(sync;#insn%U1%X1 %0,%1;twi 0,%0,0;isync\
-   : =r (ret) : m (*addr) : memory);   

Re: [PATCH] Adjust arch/powerpc inline asms for recent gcc change

2010-06-25 Thread Segher Boessenkool
 - stw%U0%X0 %L2,%1
 - : =m (*ptep), =m (*((unsigned char *)ptep+4))
 + stw%U1%X1 %L2,%1
 + : =m (*ptep), =m (*((unsigned char *)ptep+4))
   : r (pte) : memory);

This still isn't correct -- the constraint says that a byte
is written, but the insn changes a word.  Probably should just
be ptep[1] ?


Segher

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH] Adjust arch/powerpc inline asms for recent gcc change

2010-06-25 Thread Jakub Jelinek
On Fri, Jun 25, 2010 at 01:08:23PM +0200, Segher Boessenkool wrote:
  -   stw%U0%X0 %L2,%1
  -   : =m (*ptep), =m (*((unsigned char *)ptep+4))
  +   stw%U1%X1 %L2,%1
  +   : =m (*ptep), =m (*((unsigned char *)ptep+4))
  : r (pte) : memory);
 
 This still isn't correct -- the constraint says that a byte
 is written, but the insn changes a word.  Probably should just
 be ptep[1] ?

Yeah.

Jakub
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


HWCAP for fsqrt vs PPC64

2010-06-25 Thread Kumar Gala
Guys,

We seem to be using the PPC_FEATURE_64 HWCAP to imply fsqrt support.  However, 
the new e5500 core from Freescale that is 64-bit does NOT implement fsqrt so 
this assumption is wrong:

sysdeps/powerpc/fpu/math_private.h

# if __WORDSIZE == 64 || defined _ARCH_PWR4
#  define __CPU_HAS_FSQRT 1
# else
#  define __CPU_HAS_FSQRT ((GLRO(dl_hwcap)  PPC_FEATURE_64) != 0)
# endif

Open to suggestions on how to fix this as its a kernel/libc interaction point.

- k
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


cpio initrd booting failed on powerpc p4080

2010-06-25 Thread wilbur.chan
Hi All!


We are planning to port linux 2.6.21.7 to powerpc p4080  using ramdisk
file system,   but to find it failed at :

run_init_process(ramdisk_execute_command)

The exact failing place is at  run_init_process---
do_execve---search_binary_handler --- load_elf_binary ---   if
(memcmp(loc-elf_ex.e_ident, ELFMAG, SELFMAG) != 0)


which means that, 'init'  is not of  'ELF' format .

And we ad some codes before execute  'init' ,  to sys_read content
from  'init' file , but to find it having  many 'zero'   value in it.



Then we add some test codes , before calling
run_init_process(ramdisk_execute_command) , which take the
following steps:

1) create a file  A  ,   using sys_open(CREATE)
2) write values into A   , using  sys_write
3) close A
4)open A again , and read content from it,using sys_read

We found in step 4 that , we read in some 'zero' value from the file ,
that is to say,  sys_write failed at some points.



To avoid cache affect , we use sys_sync after step 3 (close A) but to
find it no use.


So, why sys_write failed to update the file content?

Thx
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: mpc870 support in the powerpc arch?

2010-06-25 Thread Scott Wood

On 06/25/2010 04:08 AM, Shawn Jin wrote:

On Mon, May 17, 2010 at 12:54 PM, Scott Woodscottw...@freescale.com  wrote:

On Fri, May 14, 2010 at 02:41:29PM -0700, Shawn Jin wrote:

Hi,

Is mpc870 fully supported in the powerpc arch? I know it's an old
processor but 8xx is still one of platforms in the powerpc arch. If
it's not supported, how much effort will it be to resurrect mpc870 in
the new arch considering we have substantial 8xx support?


It should work, with appropriate board support -- MPC875 and MPC885 have
been used with arch/powerpc, and MPC870 is very similar (albeit with fewer
devices).


Thanks Scott. I found your implementation in the kernel. I use
adder875 as my base to port my board support. But I'm having a problem
in the last step to create the cuImage. You may know what I did wrong.
The error message is as follows.

   WRAParch/powerpc/boot/cuImage.my870
ppc_8xx-ld: arch/powerpc/boot/cuboot-my870.o: No such file: No such
file or directory
make[1]: *** [arch/powerpc/boot/cuImage.my870] Error 1


You need to update the case statement arch/powerpc/boot/wrapper to 
recognize your board and select cuboot-8xx.o, as is done for adder875. 
Otherwise it defaults to looking for a file for your specific board.


-Scott
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 0/2 v3] mpc5200 ac97 gpio reset

2010-06-25 Thread Grant Likely
On Tue, Jun 22, 2010 at 5:00 PM, Mark Brown
broo...@opensource.wolfsonmicro.com wrote:
 On Tue, Jun 15, 2010 at 12:05:05PM -0400, Eric Millbrandt wrote:
 These patches reimplement the reset fuction in the ac97 to use gpio pins
 instead of using the mpc5200 ac97 reset functionality in the psc.  This
 avoids a problem in which attached ac97 devices go into test mode appear
 unresponsive.

 These patches were tested on a pcm030 baseboard and on custom hardware with
 a wm9715 audio codec/touchscreen controller.

 Grant, are you OK with this series?

Yes, I'm going to pick it up.

g.
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH] KVM: PPC: Book3S_32 MMU debug compile fixes

2010-06-25 Thread Alexander Graf
Due to previous changes, the Book3S_32 guest MMU code didn't compile properly
when enabling debugging.

This patch repairs the broken code paths, making it possible to define DEBUG_MMU
and friends again.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/kvm/book3s_32_mmu.c |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kvm/book3s_32_mmu.c b/arch/powerpc/kvm/book3s_32_mmu.c
index 3292d76..079760b 100644
--- a/arch/powerpc/kvm/book3s_32_mmu.c
+++ b/arch/powerpc/kvm/book3s_32_mmu.c
@@ -104,7 +104,7 @@ static hva_t kvmppc_mmu_book3s_32_get_pteg(struct 
kvmppc_vcpu_book3s *vcpu_book3
pteg = (vcpu_book3s-sdr1  0x) | hash;
 
dprintk(MMU: pc=0x%lx eaddr=0x%lx sdr1=0x%llx pteg=0x%x vsid=0x%x\n,
-   vcpu_book3s-vcpu.arch.pc, eaddr, vcpu_book3s-sdr1, pteg,
+   kvmppc_get_pc(vcpu_book3s-vcpu), eaddr, vcpu_book3s-sdr1, 
pteg,
sre-vsid);
 
r = gfn_to_hva(vcpu_book3s-vcpu.kvm, pteg  PAGE_SHIFT);
@@ -269,7 +269,7 @@ no_page_found:
dprintk_pte(KVM MMU: No PTE found (sdr1=0x%llx ptegp=0x%lx)\n,
to_book3s(vcpu)-sdr1, ptegp);
for (i=0; i16; i+=2) {
-   dprintk_pte(   %02d: 0x%x - 0x%x (0x%llx)\n,
+   dprintk_pte(   %02d: 0x%x - 0x%x (0x%x)\n,
i, pteg[i], pteg[i+1], ptem);
}
}
-- 
1.6.0.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH] KVM: PPC: Make use of hash based Shadow MMU

2010-06-25 Thread Alexander Graf
We just introduced generic functions to handle shadow pages on PPC.
This patch makes the respective backends make use of them, getting
rid of a lot of duplicate code along the way.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/include/asm/kvm_book3s.h |7 ++
 arch/powerpc/include/asm/kvm_host.h   |   18 +-
 arch/powerpc/kvm/Makefile |2 +
 arch/powerpc/kvm/book3s_32_mmu_host.c |  104 +++-
 arch/powerpc/kvm/book3s_64_mmu_host.c |   98 ++
 5 files changed, 41 insertions(+), 188 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_book3s.h 
b/arch/powerpc/include/asm/kvm_book3s.h
index 4e99559..a96e405 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -115,6 +115,13 @@ extern void kvmppc_mmu_book3s_32_init(struct kvm_vcpu 
*vcpu);
 extern int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte);
 extern int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr);
 extern void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu);
+
+extern void kvmppc_mmu_hpte_cache_map(struct kvm_vcpu *vcpu, struct hpte_cache 
*pte);
+extern struct hpte_cache *kvmppc_mmu_hpte_cache_next(struct kvm_vcpu *vcpu);
+extern void kvmppc_mmu_hpte_destroy(struct kvm_vcpu *vcpu);
+extern int kvmppc_mmu_hpte_init(struct kvm_vcpu *vcpu);
+extern void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache 
*pte);
+
 extern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, 
bool data);
 extern int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, 
bool data);
 extern void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int 
vec);
diff --git a/arch/powerpc/include/asm/kvm_host.h 
b/arch/powerpc/include/asm/kvm_host.h
index 0c9ad86..895eb63 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -38,7 +38,13 @@
 #define KVM_NR_PAGE_SIZES  1
 #define KVM_PAGES_PER_HPAGE(x) (1UL31)
 
-#define HPTEG_CACHE_NUM 1024
+#define HPTEG_CACHE_NUM(1  15)
+#define HPTEG_HASH_BITS_PTE13
+#define HPTEG_HASH_BITS_VPTE   13
+#define HPTEG_HASH_BITS_VPTE_LONG  5
+#define HPTEG_HASH_NUM_PTE (1  HPTEG_HASH_BITS_PTE)
+#define HPTEG_HASH_NUM_VPTE(1  HPTEG_HASH_BITS_VPTE)
+#define HPTEG_HASH_NUM_VPTE_LONG   (1  HPTEG_HASH_BITS_VPTE_LONG)
 
 struct kvm;
 struct kvm_run;
@@ -151,6 +157,9 @@ struct kvmppc_mmu {
 };
 
 struct hpte_cache {
+   struct list_head list_pte;
+   struct list_head list_vpte;
+   struct list_head list_vpte_long;
u64 host_va;
u64 pfn;
ulong slot;
@@ -282,8 +291,11 @@ struct kvm_vcpu_arch {
unsigned long pending_exceptions;
 
 #ifdef CONFIG_PPC_BOOK3S
-   struct hpte_cache hpte_cache[HPTEG_CACHE_NUM];
-   int hpte_cache_offset;
+   struct kmem_cache *hpte_cache;
+   struct list_head hpte_hash_pte[HPTEG_HASH_NUM_PTE];
+   struct list_head hpte_hash_vpte[HPTEG_HASH_NUM_VPTE];
+   struct list_head hpte_hash_vpte_long[HPTEG_HASH_NUM_VPTE_LONG];
+   int hpte_cache_count;
 #endif
 };
 
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
index ff43606..d45c818 100644
--- a/arch/powerpc/kvm/Makefile
+++ b/arch/powerpc/kvm/Makefile
@@ -45,6 +45,7 @@ kvm-book3s_64-objs := \
book3s.o \
book3s_emulate.o \
book3s_interrupts.o \
+   book3s_mmu_hpte.o \
book3s_64_mmu_host.o \
book3s_64_mmu.o \
book3s_32_mmu.o
@@ -57,6 +58,7 @@ kvm-book3s_32-objs := \
book3s.o \
book3s_emulate.o \
book3s_interrupts.o \
+   book3s_mmu_hpte.o \
book3s_32_mmu_host.o \
book3s_32_mmu.o
 kvm-objs-$(CONFIG_KVM_BOOK3S_32) := $(kvm-book3s_32-objs)
diff --git a/arch/powerpc/kvm/book3s_32_mmu_host.c 
b/arch/powerpc/kvm/book3s_32_mmu_host.c
index 904f5ac..0b51ef8 100644
--- a/arch/powerpc/kvm/book3s_32_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_32_mmu_host.c
@@ -58,105 +58,19 @@
 static ulong htab;
 static u32 htabmask;
 
-static void invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
+void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
 {
volatile u32 *pteg;
 
-   dprintk_mmu(KVM: Flushing SPTE: 0x%llx (0x%llx) - 0x%llx\n,
-   pte-pte.eaddr, pte-pte.vpage, pte-host_va);
-
+   /* Remove from host HTAB */
pteg = (u32*)pte-slot;
-
pteg[0] = 0;
+
+   /* And make sure it's gone from the TLB too */
asm volatile (sync);
asm volatile (tlbie %0 : : r (pte-pte.eaddr) : memory);
asm volatile (sync);
asm volatile (tlbsync);
-
-   pte-host_va = 0;
-
-   if (pte-pte.may_write)
-   kvm_release_pfn_dirty(pte-pfn);
-   else
-   kvm_release_pfn_clean(pte-pfn);
-}
-
-void kvmppc_mmu_pte_flush(struct kvm_vcpu *vcpu, ulong guest_ea, ulong 

[PATCH] Faster MMU lookups for Book3s

2010-06-25 Thread Alexander Graf
Book3s suffered from my really bad shadow MMU implementation so far. So
I finally got around to implement a combined hash and list mechanism that
allows for much faster lookup of mapped pages.

To show that it really is faster, I tried to run simple process spawning
code inside the guest with and without these patches:

[without]

debian-powerpc:~# time for i in {1..1000}; do /bin/echo hello  /dev/null; done

real0m20.235s
user0m10.418s
sys 0m9.766s

[with]

debian-powerpc:~# time for i in {1..1000}; do /bin/echo hello  /dev/null; done

real0m14.659s
user0m8.967s
sys 0m5.688s

So as you can see, performance improved significantly.

Alexander Graf (2):
  KVM: PPC: Add generic hpte management functions
  KVM: PPC: Make use of hash based Shadow MMU

 arch/powerpc/include/asm/kvm_book3s.h |7 +
 arch/powerpc/include/asm/kvm_host.h   |   18 ++-
 arch/powerpc/kvm/Makefile |2 +
 arch/powerpc/kvm/book3s_32_mmu_host.c |  104 ++---
 arch/powerpc/kvm/book3s_64_mmu_host.c |   98 +---
 arch/powerpc/kvm/book3s_mmu_hpte.c|  286 +
 6 files changed, 327 insertions(+), 188 deletions(-)
 create mode 100644 arch/powerpc/kvm/book3s_mmu_hpte.c

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH] KVM: PPC: Add generic hpte management functions

2010-06-25 Thread Alexander Graf
Currently the shadow paging code keeps an array of entries it knows about.
Whenever the guest invalidates an entry, we loop through that entry,
trying to invalidate matching parts.

While this is a really simple implementation, it is probably the most
ineffective one possible. So instead, let's keep an array of lists around
that are indexed by a hash. This way each PTE can be added by 4 list_add,
removed by 4 list_del invocations and the search only needs to loop through
entries that share the same hash.

This patch implements said lookup and exports generic functions that both
the 32-bit and 64-bit backend can use.

Signed-off-by: Alexander Graf ag...@suse.de

---

v1 - v2:

  - remove hpte_all list
  - lookup all using vpte_long lists
  - decrease size of vpte_long hash
  - fix missing brackets
---
 arch/powerpc/kvm/book3s_mmu_hpte.c |  286 
 1 files changed, 286 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/kvm/book3s_mmu_hpte.c

diff --git a/arch/powerpc/kvm/book3s_mmu_hpte.c 
b/arch/powerpc/kvm/book3s_mmu_hpte.c
new file mode 100644
index 000..5826e61
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_mmu_hpte.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2010 SUSE Linux Products GmbH. All rights reserved.
+ *
+ * Authors:
+ * Alexander Graf ag...@suse.de
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include linux/kvm_host.h
+#include linux/hash.h
+#include linux/slab.h
+
+#include asm/kvm_ppc.h
+#include asm/kvm_book3s.h
+#include asm/machdep.h
+#include asm/mmu_context.h
+#include asm/hw_irq.h
+
+#define PTE_SIZE   12
+
+/* #define DEBUG_MMU */
+
+#ifdef DEBUG_MMU
+#define dprintk_mmu(a, ...) printk(KERN_INFO a, __VA_ARGS__)
+#else
+#define dprintk_mmu(a, ...) do { } while(0)
+#endif
+
+static inline u64 kvmppc_mmu_hash_pte(u64 eaddr) {
+   return hash_64(eaddr  PTE_SIZE, HPTEG_HASH_BITS_PTE);
+}
+
+static inline u64 kvmppc_mmu_hash_vpte(u64 vpage) {
+   return hash_64(vpage  0xfULL, HPTEG_HASH_BITS_VPTE);
+}
+
+static inline u64 kvmppc_mmu_hash_vpte_long(u64 vpage) {
+   return hash_64((vpage  0xff000ULL)  12,
+  HPTEG_HASH_BITS_VPTE_LONG);
+}
+
+void kvmppc_mmu_hpte_cache_map(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
+{
+   u64 index;
+
+   /* Add to ePTE list */
+   index = kvmppc_mmu_hash_pte(pte-pte.eaddr);
+   list_add(pte-list_pte, vcpu-arch.hpte_hash_pte[index]);
+
+   /* Add to vPTE list */
+   index = kvmppc_mmu_hash_vpte(pte-pte.vpage);
+   list_add(pte-list_vpte, vcpu-arch.hpte_hash_vpte[index]);
+
+   /* Add to vPTE_long list */
+   index = kvmppc_mmu_hash_vpte_long(pte-pte.vpage);
+   list_add(pte-list_vpte_long, vcpu-arch.hpte_hash_vpte_long[index]);
+}
+
+static void invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
+{
+   dprintk_mmu(KVM: Flushing SPT: 0x%lx (0x%llx) - 0x%llx\n,
+   pte-pte.eaddr, pte-pte.vpage, pte-host_va);
+
+   /* Different for 32 and 64 bit */
+   kvmppc_mmu_invalidate_pte(vcpu, pte);
+
+   if (pte-pte.may_write)
+   kvm_release_pfn_dirty(pte-pfn);
+   else
+   kvm_release_pfn_clean(pte-pfn);
+
+   list_del(pte-list_pte);
+   list_del(pte-list_vpte);
+   list_del(pte-list_vpte_long);
+
+   kmem_cache_free(vcpu-arch.hpte_cache, pte);
+}
+
+static void kvmppc_mmu_pte_flush_all(struct kvm_vcpu *vcpu)
+{
+   struct hpte_cache *pte, *tmp;
+   int i;
+
+   for (i = 0; i  HPTEG_HASH_NUM_VPTE_LONG; i++) {
+   struct list_head *list = vcpu-arch.hpte_hash_vpte_long[i];
+
+   list_for_each_entry_safe(pte, tmp, list, list_vpte_long) {
+   /* Jump over the helper entry */
+   if (pte-list_vpte_long == list)
+   continue;
+
+   invalidate_pte(vcpu, pte);
+   }
+   }
+}
+
+void kvmppc_mmu_pte_flush(struct kvm_vcpu *vcpu, ulong guest_ea, ulong ea_mask)
+{
+   u64 i;
+
+   dprintk_mmu(KVM: Flushing %d Shadow PTEs: 0x%lx  0x%lx\n,
+   vcpu-arch.hpte_cache_count, guest_ea, ea_mask);
+
+   guest_ea = ea_mask;
+
+   switch (ea_mask) {
+   case ~0xfffUL:
+   {
+   struct list_head *list;
+   struct hpte_cache *pte, *tmp;
+
+   

Re: [PATCH] KVM: PPC: Add generic hpte management functions

2010-06-25 Thread Alexander Graf

On 26.06.2010, at 01:16, Alexander Graf wrote:

 Currently the shadow paging code keeps an array of entries it knows about.
 Whenever the guest invalidates an entry, we loop through that entry,
 trying to invalidate matching parts.
 
 While this is a really simple implementation, it is probably the most
 ineffective one possible. So instead, let's keep an array of lists around
 that are indexed by a hash. This way each PTE can be added by 4 list_add,
 removed by 4 list_del invocations and the search only needs to loop through
 entries that share the same hash.
 
 This patch implements said lookup and exports generic functions that both
 the 32-bit and 64-bit backend can use.

Yikes - I forgot -n.

This is patch 1/2.


Alex

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 00/26] KVM PPC PV framework

2010-06-25 Thread Alexander Graf
On PPC we run PR=0 (kernel mode) code in PR=1 (user mode) and don't use the
hypervisor extensions.

While that is all great to show that virtualization is possible, there are
quite some cases where the emulation overhead of privileged instructions is
killing performance.

This patchset tackles exactly that issue. It introduces a paravirtual framework
using which KVM and Linux share a page to exchange register state with. That
way we don't have to switch to the hypervisor just to change a value of a
privileged register.

To prove my point, I ran the same test I did for the MMU optimizations against
the PV framework. Here are the results:

[without]

debian-powerpc:~# time for i in {1..1000}; do /bin/echo hello  /dev/null; done

real0m14.659s
user0m8.967s
sys 0m5.688s

[with]

debian-powerpc:~# time for i in {1..1000}; do /bin/echo hello  /dev/null; done

real0m7.557s
user0m4.121s
sys 0m3.426s


So this is a significant performance improvement! I'm quite happy how fast this
whole thing becomes :)

I tried to take all comments I've heard from people so far about such a PV
framework into account. In case you told me something before that is a no-go
and I still did it, please just tell me again.

Now go and have fun with fast VMs on PPC! Get yourself a G5 on ebay and start
experiencing the power yourself. - heh

Alexander Graf (26):
  KVM: PPC: Introduce shared page
  KVM: PPC: Convert MSR to shared page
  KVM: PPC: Convert DSISR to shared page
  KVM: PPC: Convert DAR to shared page.
  KVM: PPC: Convert SRR0 and SRR1 to shared page
  KVM: PPC: Convert SPRG[0-4] to shared page
  KVM: PPC: Implement hypervisor interface
  KVM: PPC: Add PV guest critical sections
  KVM: PPC: Add PV guest scratch registers
  KVM: PPC: Tell guest about pending interrupts
  KVM: PPC: Make RMO a define
  KVM: PPC: First magic page steps
  KVM: PPC: Magic Page Book3s support
  KVM: PPC: Magic Page BookE support
  KVM: PPC: Expose magic page support to guest
  KVM: Move kvm_guest_init out of generic code
  KVM: PPC: Generic KVM PV guest support
  KVM: PPC: KVM PV guest stubs
  KVM: PPC: PV instructions to loads and stores
  KVM: PPC: PV tlbsync to nop
  KVM: PPC: Introduce kvm_tmp framework
  KVM: PPC: PV assembler helpers
  KVM: PPC: PV mtmsrd L=1
  KVM: PPC: PV mtmsrd L=0 and mtmsr
  KVM: PPC: PV wrteei
  KVM: PPC: Add Documentation about PV interface

 Documentation/kvm/ppc-pv.txt |  164 
 arch/powerpc/include/asm/kvm_book3s.h|1 -
 arch/powerpc/include/asm/kvm_host.h  |   14 +-
 arch/powerpc/include/asm/kvm_para.h  |  121 +-
 arch/powerpc/include/asm/kvm_ppc.h   |1 +
 arch/powerpc/kernel/Makefile |2 +
 arch/powerpc/kernel/asm-offsets.c|   18 ++-
 arch/powerpc/kernel/kvm.c|  399 ++
 arch/powerpc/kernel/kvm_emul.S   |  237 ++
 arch/powerpc/kvm/44x.c   |7 +
 arch/powerpc/kvm/44x_tlb.c   |8 +-
 arch/powerpc/kvm/book3s.c|  162 -
 arch/powerpc/kvm/book3s_32_mmu.c |   28 ++-
 arch/powerpc/kvm/book3s_32_mmu_host.c|   16 +-
 arch/powerpc/kvm/book3s_64_mmu.c |   42 +++-
 arch/powerpc/kvm/book3s_64_mmu_host.c|   16 +-
 arch/powerpc/kvm/book3s_emulate.c|   25 +-
 arch/powerpc/kvm/book3s_paired_singles.c |   11 +-
 arch/powerpc/kvm/booke.c |  110 +++--
 arch/powerpc/kvm/booke.h |6 +-
 arch/powerpc/kvm/booke_emulate.c |   14 +-
 arch/powerpc/kvm/booke_interrupts.S  |3 +-
 arch/powerpc/kvm/e500.c  |7 +
 arch/powerpc/kvm/e500_tlb.c  |   31 ++-
 arch/powerpc/kvm/e500_tlb.h  |2 +-
 arch/powerpc/kvm/emulate.c   |   47 +++-
 arch/powerpc/kvm/powerpc.c   |   42 +++-
 arch/powerpc/platforms/Kconfig   |   10 +
 arch/x86/include/asm/kvm_para.h  |6 +
 include/linux/kvm_para.h |7 +-
 30 files changed, 1383 insertions(+), 174 deletions(-)
 create mode 100644 Documentation/kvm/ppc-pv.txt
 create mode 100644 arch/powerpc/kernel/kvm.c
 create mode 100644 arch/powerpc/kernel/kvm_emul.S

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 03/26] KVM: PPC: Convert DSISR to shared page

2010-06-25 Thread Alexander Graf
The DSISR register contains information about a data page fault. It is fully
read/write from inside the guest context and we don't need to worry about
interacting based on writes of this register.

This patch converts all users of the current field to the shared page.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/include/asm/kvm_book3s.h|1 -
 arch/powerpc/include/asm/kvm_para.h  |1 +
 arch/powerpc/kvm/book3s.c|   11 ++-
 arch/powerpc/kvm/book3s_emulate.c|6 +++---
 arch/powerpc/kvm/book3s_paired_singles.c |2 +-
 5 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_book3s.h 
b/arch/powerpc/include/asm/kvm_book3s.h
index a96e405..4f29caa 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -85,7 +85,6 @@ struct kvmppc_vcpu_book3s {
u64 hid[6];
u64 gqr[8];
int slb_nr;
-   u32 dsisr;
u64 sdr1;
u64 hior;
u64 msr_mask;
diff --git a/arch/powerpc/include/asm/kvm_para.h 
b/arch/powerpc/include/asm/kvm_para.h
index a17dc52..9f7565b 100644
--- a/arch/powerpc/include/asm/kvm_para.h
+++ b/arch/powerpc/include/asm/kvm_para.h
@@ -24,6 +24,7 @@
 
 struct kvm_vcpu_arch_shared {
__u64 msr;
+   __u32 dsisr;
 };
 
 #ifdef __KERNEL__
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 3dd3003..57fd73e 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -595,15 +595,16 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct 
kvm_vcpu *vcpu,
if (page_found == -ENOENT) {
/* Page not found in guest PTE entries */
vcpu-arch.dear = kvmppc_get_fault_dar(vcpu);
-   to_book3s(vcpu)-dsisr = to_svcpu(vcpu)-fault_dsisr;
+   vcpu-arch.shared-dsisr = to_svcpu(vcpu)-fault_dsisr;
vcpu-arch.shared-msr |=
(to_svcpu(vcpu)-shadow_srr1  0xf800ULL);
kvmppc_book3s_queue_irqprio(vcpu, vec);
} else if (page_found == -EPERM) {
/* Storage protection */
vcpu-arch.dear = kvmppc_get_fault_dar(vcpu);
-   to_book3s(vcpu)-dsisr = to_svcpu(vcpu)-fault_dsisr  
~DSISR_NOHPTE;
-   to_book3s(vcpu)-dsisr |= DSISR_PROTFAULT;
+   vcpu-arch.shared-dsisr =
+   to_svcpu(vcpu)-fault_dsisr  ~DSISR_NOHPTE;
+   vcpu-arch.shared-dsisr |= DSISR_PROTFAULT;
vcpu-arch.shared-msr |=
(to_svcpu(vcpu)-shadow_srr1  0xf800ULL);
kvmppc_book3s_queue_irqprio(vcpu, vec);
@@ -867,7 +868,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu 
*vcpu,
r = kvmppc_handle_pagefault(run, vcpu, dar, exit_nr);
} else {
vcpu-arch.dear = dar;
-   to_book3s(vcpu)-dsisr = to_svcpu(vcpu)-fault_dsisr;
+   vcpu-arch.shared-dsisr = to_svcpu(vcpu)-fault_dsisr;
kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
kvmppc_mmu_pte_flush(vcpu, vcpu-arch.dear, ~0xFFFUL);
r = RESUME_GUEST;
@@ -994,7 +995,7 @@ program_interrupt:
}
case BOOK3S_INTERRUPT_ALIGNMENT:
if (kvmppc_read_inst(vcpu) == EMULATE_DONE) {
-   to_book3s(vcpu)-dsisr = kvmppc_alignment_dsisr(vcpu,
+   vcpu-arch.shared-dsisr = kvmppc_alignment_dsisr(vcpu,
kvmppc_get_last_inst(vcpu));
vcpu-arch.dear = kvmppc_alignment_dar(vcpu,
kvmppc_get_last_inst(vcpu));
diff --git a/arch/powerpc/kvm/book3s_emulate.c 
b/arch/powerpc/kvm/book3s_emulate.c
index 35d3c16..9982ff1 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -221,7 +221,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct 
kvm_vcpu *vcpu,
else if (r == -EPERM)
dsisr |= DSISR_PROTFAULT;
 
-   to_book3s(vcpu)-dsisr = dsisr;
+   vcpu-arch.shared-dsisr = dsisr;
to_svcpu(vcpu)-fault_dsisr = dsisr;
 
kvmppc_book3s_queue_irqprio(vcpu,
@@ -327,7 +327,7 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int 
sprn, int rs)
to_book3s(vcpu)-sdr1 = spr_val;
break;
case SPRN_DSISR:
-   to_book3s(vcpu)-dsisr = spr_val;
+   vcpu-arch.shared-dsisr = spr_val;
break;
case SPRN_DAR:
vcpu-arch.dear = spr_val;
@@ -440,7 +440,7 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int 
sprn, int rt)
kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)-sdr1);

[PATCH 05/26] KVM: PPC: Convert SRR0 and SRR1 to shared page

2010-06-25 Thread Alexander Graf
The SRR0 and SRR1 registers contain cached values of the PC and MSR
respectively. They get written to by the hypervisor when an interrupt
occurs or directly by the kernel. They are also used to tell the rfi(d)
instruction where to jump to.

Because it only gets touched on defined events that, it's very simple to
share with the guest. Hypervisor and guest both have full r/w access.

This patch converts all users of the current field to the shared page.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/include/asm/kvm_host.h |2 --
 arch/powerpc/include/asm/kvm_para.h |2 ++
 arch/powerpc/kvm/book3s.c   |   12 ++--
 arch/powerpc/kvm/book3s_emulate.c   |4 ++--
 arch/powerpc/kvm/booke.c|   15 ---
 arch/powerpc/kvm/booke_emulate.c|4 ++--
 arch/powerpc/kvm/emulate.c  |   12 
 7 files changed, 28 insertions(+), 23 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_host.h 
b/arch/powerpc/include/asm/kvm_host.h
index 108dabc..6bcf62f 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -224,8 +224,6 @@ struct kvm_vcpu_arch {
ulong sprg5;
ulong sprg6;
ulong sprg7;
-   ulong srr0;
-   ulong srr1;
ulong csrr0;
ulong csrr1;
ulong dsrr0;
diff --git a/arch/powerpc/include/asm/kvm_para.h 
b/arch/powerpc/include/asm/kvm_para.h
index ec72a1c..d7fc6c2 100644
--- a/arch/powerpc/include/asm/kvm_para.h
+++ b/arch/powerpc/include/asm/kvm_para.h
@@ -23,6 +23,8 @@
 #include linux/types.h
 
 struct kvm_vcpu_arch_shared {
+   __u64 srr0;
+   __u64 srr1;
__u64 dar;
__u64 msr;
__u32 dsisr;
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 245bd2d..b144697 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -162,8 +162,8 @@ void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
 
 void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags)
 {
-   vcpu-arch.srr0 = kvmppc_get_pc(vcpu);
-   vcpu-arch.srr1 = vcpu-arch.shared-msr | flags;
+   vcpu-arch.shared-srr0 = kvmppc_get_pc(vcpu);
+   vcpu-arch.shared-srr1 = vcpu-arch.shared-msr | flags;
kvmppc_set_pc(vcpu, to_book3s(vcpu)-hior + vec);
vcpu-arch.mmu.reset_msr(vcpu);
 }
@@ -1059,8 +1059,8 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, 
struct kvm_regs *regs)
regs-lr = kvmppc_get_lr(vcpu);
regs-xer = kvmppc_get_xer(vcpu);
regs-msr = vcpu-arch.shared-msr;
-   regs-srr0 = vcpu-arch.srr0;
-   regs-srr1 = vcpu-arch.srr1;
+   regs-srr0 = vcpu-arch.shared-srr0;
+   regs-srr1 = vcpu-arch.shared-srr1;
regs-pid = vcpu-arch.pid;
regs-sprg0 = vcpu-arch.sprg0;
regs-sprg1 = vcpu-arch.sprg1;
@@ -1086,8 +1086,8 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, 
struct kvm_regs *regs)
kvmppc_set_lr(vcpu, regs-lr);
kvmppc_set_xer(vcpu, regs-xer);
kvmppc_set_msr(vcpu, regs-msr);
-   vcpu-arch.srr0 = regs-srr0;
-   vcpu-arch.srr1 = regs-srr1;
+   vcpu-arch.shared-srr0 = regs-srr0;
+   vcpu-arch.shared-srr1 = regs-srr1;
vcpu-arch.sprg0 = regs-sprg0;
vcpu-arch.sprg1 = regs-sprg1;
vcpu-arch.sprg2 = regs-sprg2;
diff --git a/arch/powerpc/kvm/book3s_emulate.c 
b/arch/powerpc/kvm/book3s_emulate.c
index c147864..f333cb4 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -73,8 +73,8 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct 
kvm_vcpu *vcpu,
switch (get_xop(inst)) {
case OP_19_XOP_RFID:
case OP_19_XOP_RFI:
-   kvmppc_set_pc(vcpu, vcpu-arch.srr0);
-   kvmppc_set_msr(vcpu, vcpu-arch.srr1);
+   kvmppc_set_pc(vcpu, vcpu-arch.shared-srr0);
+   kvmppc_set_msr(vcpu, vcpu-arch.shared-srr1);
*advance = 0;
break;
 
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 5844bcf..8b546fe 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -64,7 +64,8 @@ void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu)
 
printk(pc:   %08lx msr:  %08llx\n, vcpu-arch.pc, 
vcpu-arch.shared-msr);
printk(lr:   %08lx ctr:  %08lx\n, vcpu-arch.lr, vcpu-arch.ctr);
-   printk(srr0: %08lx srr1: %08lx\n, vcpu-arch.srr0, vcpu-arch.srr1);
+   printk(srr0: %08llx srr1: %08llx\n, vcpu-arch.shared-srr0,
+   vcpu-arch.shared-srr1);
 
printk(exceptions: %08lx\n, vcpu-arch.pending_exceptions);
 
@@ -189,8 +190,8 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu 
*vcpu,
}
 
if (allowed) {
-   vcpu-arch.srr0 = vcpu-arch.pc;
-   vcpu-arch.srr1 = vcpu-arch.shared-msr;
+   vcpu-arch.shared-srr0 = vcpu-arch.pc;
+   

[PATCH 04/26] KVM: PPC: Convert DAR to shared page.

2010-06-25 Thread Alexander Graf
The DAR register contains the address a data page fault occured at. This
register behaves pretty much like a simple data storage register that gets
written to on data faults. There is no hypervisor interaction required on
read or write.

This patch converts all users of the current field to the shared page.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/include/asm/kvm_host.h  |1 -
 arch/powerpc/include/asm/kvm_para.h  |1 +
 arch/powerpc/kvm/book3s.c|   14 +++---
 arch/powerpc/kvm/book3s_emulate.c|6 +++---
 arch/powerpc/kvm/book3s_paired_singles.c |2 +-
 arch/powerpc/kvm/booke.c |2 +-
 arch/powerpc/kvm/booke_emulate.c |4 ++--
 7 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_host.h 
b/arch/powerpc/include/asm/kvm_host.h
index 249c242..108dabc 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -230,7 +230,6 @@ struct kvm_vcpu_arch {
ulong csrr1;
ulong dsrr0;
ulong dsrr1;
-   ulong dear;
ulong esr;
u32 dec;
u32 decar;
diff --git a/arch/powerpc/include/asm/kvm_para.h 
b/arch/powerpc/include/asm/kvm_para.h
index 9f7565b..ec72a1c 100644
--- a/arch/powerpc/include/asm/kvm_para.h
+++ b/arch/powerpc/include/asm/kvm_para.h
@@ -23,6 +23,7 @@
 #include linux/types.h
 
 struct kvm_vcpu_arch_shared {
+   __u64 dar;
__u64 msr;
__u32 dsisr;
 };
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 57fd73e..245bd2d 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -594,14 +594,14 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct 
kvm_vcpu *vcpu,
 
if (page_found == -ENOENT) {
/* Page not found in guest PTE entries */
-   vcpu-arch.dear = kvmppc_get_fault_dar(vcpu);
+   vcpu-arch.shared-dar = kvmppc_get_fault_dar(vcpu);
vcpu-arch.shared-dsisr = to_svcpu(vcpu)-fault_dsisr;
vcpu-arch.shared-msr |=
(to_svcpu(vcpu)-shadow_srr1  0xf800ULL);
kvmppc_book3s_queue_irqprio(vcpu, vec);
} else if (page_found == -EPERM) {
/* Storage protection */
-   vcpu-arch.dear = kvmppc_get_fault_dar(vcpu);
+   vcpu-arch.shared-dar = kvmppc_get_fault_dar(vcpu);
vcpu-arch.shared-dsisr =
to_svcpu(vcpu)-fault_dsisr  ~DSISR_NOHPTE;
vcpu-arch.shared-dsisr |= DSISR_PROTFAULT;
@@ -610,7 +610,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct 
kvm_vcpu *vcpu,
kvmppc_book3s_queue_irqprio(vcpu, vec);
} else if (page_found == -EINVAL) {
/* Page not found in guest SLB */
-   vcpu-arch.dear = kvmppc_get_fault_dar(vcpu);
+   vcpu-arch.shared-dar = kvmppc_get_fault_dar(vcpu);
kvmppc_book3s_queue_irqprio(vcpu, vec + 0x80);
} else if (!is_mmio 
   kvmppc_visible_gfn(vcpu, pte.raddr  PAGE_SHIFT)) {
@@ -867,17 +867,17 @@ int kvmppc_handle_exit(struct kvm_run *run, struct 
kvm_vcpu *vcpu,
if (to_svcpu(vcpu)-fault_dsisr  DSISR_NOHPTE) {
r = kvmppc_handle_pagefault(run, vcpu, dar, exit_nr);
} else {
-   vcpu-arch.dear = dar;
+   vcpu-arch.shared-dar = dar;
vcpu-arch.shared-dsisr = to_svcpu(vcpu)-fault_dsisr;
kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
-   kvmppc_mmu_pte_flush(vcpu, vcpu-arch.dear, ~0xFFFUL);
+   kvmppc_mmu_pte_flush(vcpu, dar, ~0xFFFUL);
r = RESUME_GUEST;
}
break;
}
case BOOK3S_INTERRUPT_DATA_SEGMENT:
if (kvmppc_mmu_map_segment(vcpu, kvmppc_get_fault_dar(vcpu))  
0) {
-   vcpu-arch.dear = kvmppc_get_fault_dar(vcpu);
+   vcpu-arch.shared-dar = kvmppc_get_fault_dar(vcpu);
kvmppc_book3s_queue_irqprio(vcpu,
BOOK3S_INTERRUPT_DATA_SEGMENT);
}
@@ -997,7 +997,7 @@ program_interrupt:
if (kvmppc_read_inst(vcpu) == EMULATE_DONE) {
vcpu-arch.shared-dsisr = kvmppc_alignment_dsisr(vcpu,
kvmppc_get_last_inst(vcpu));
-   vcpu-arch.dear = kvmppc_alignment_dar(vcpu,
+   vcpu-arch.shared-dar = kvmppc_alignment_dar(vcpu,
kvmppc_get_last_inst(vcpu));
kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
}
diff --git a/arch/powerpc/kvm/book3s_emulate.c 
b/arch/powerpc/kvm/book3s_emulate.c
index 9982ff1..c147864 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ 

[PATCH 02/26] KVM: PPC: Convert MSR to shared page

2010-06-25 Thread Alexander Graf
One of the most obvious registers to share with the guest directly is the
MSR. The MSR contains the interrupts enabled flag which the guest has to
toggle in critical sections.

So in order to bring the overhead of interrupt en- and disabling down, let's
put msr into the shared page. Keep in mind that even though you can fully read
its contents, writing to it doesn't always update all state. There are a few
safe fields that don't require hypervisor interaction. See the guest
implementation that follows later for reference.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/include/asm/kvm_host.h  |1 -
 arch/powerpc/include/asm/kvm_para.h  |1 +
 arch/powerpc/kernel/asm-offsets.c|2 +-
 arch/powerpc/kvm/44x_tlb.c   |8 ++--
 arch/powerpc/kvm/book3s.c|   65 --
 arch/powerpc/kvm/book3s_32_mmu.c |   12 +++---
 arch/powerpc/kvm/book3s_32_mmu_host.c|4 +-
 arch/powerpc/kvm/book3s_64_mmu.c |   12 +++---
 arch/powerpc/kvm/book3s_64_mmu_host.c|4 +-
 arch/powerpc/kvm/book3s_emulate.c|9 ++--
 arch/powerpc/kvm/book3s_paired_singles.c |7 ++-
 arch/powerpc/kvm/booke.c |   20 +-
 arch/powerpc/kvm/booke.h |6 +-
 arch/powerpc/kvm/booke_emulate.c |6 +-
 arch/powerpc/kvm/booke_interrupts.S  |3 +-
 arch/powerpc/kvm/e500_tlb.c  |   12 +++---
 arch/powerpc/kvm/e500_tlb.h  |2 +-
 arch/powerpc/kvm/powerpc.c   |3 +-
 18 files changed, 93 insertions(+), 84 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_host.h 
b/arch/powerpc/include/asm/kvm_host.h
index bca9391..249c242 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -210,7 +210,6 @@ struct kvm_vcpu_arch {
u32 cr;
 #endif
 
-   ulong msr;
 #ifdef CONFIG_PPC_BOOK3S
ulong shadow_msr;
ulong hflags;
diff --git a/arch/powerpc/include/asm/kvm_para.h 
b/arch/powerpc/include/asm/kvm_para.h
index 1485ba8..a17dc52 100644
--- a/arch/powerpc/include/asm/kvm_para.h
+++ b/arch/powerpc/include/asm/kvm_para.h
@@ -23,6 +23,7 @@
 #include linux/types.h
 
 struct kvm_vcpu_arch_shared {
+   __u64 msr;
 };
 
 #ifdef __KERNEL__
diff --git a/arch/powerpc/kernel/asm-offsets.c 
b/arch/powerpc/kernel/asm-offsets.c
index 944f593..a55d47e 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -394,13 +394,13 @@ int main(void)
DEFINE(VCPU_HOST_STACK, offsetof(struct kvm_vcpu, arch.host_stack));
DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid));
DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr));
-   DEFINE(VCPU_MSR, offsetof(struct kvm_vcpu, arch.msr));
DEFINE(VCPU_SPRG4, offsetof(struct kvm_vcpu, arch.sprg4));
DEFINE(VCPU_SPRG5, offsetof(struct kvm_vcpu, arch.sprg5));
DEFINE(VCPU_SPRG6, offsetof(struct kvm_vcpu, arch.sprg6));
DEFINE(VCPU_SPRG7, offsetof(struct kvm_vcpu, arch.sprg7));
DEFINE(VCPU_SHADOW_PID, offsetof(struct kvm_vcpu, arch.shadow_pid));
DEFINE(VCPU_SHARED, offsetof(struct kvm_vcpu, arch.shared));
+   DEFINE(VCPU_SHARED_MSR, offsetof(struct kvm_vcpu_arch_shared, msr));
 
/* book3s */
 #ifdef CONFIG_PPC_BOOK3S
diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c
index 8123125..4cbbca7 100644
--- a/arch/powerpc/kvm/44x_tlb.c
+++ b/arch/powerpc/kvm/44x_tlb.c
@@ -221,14 +221,14 @@ gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned 
int gtlb_index,
 
 int kvmppc_mmu_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr)
 {
-   unsigned int as = !!(vcpu-arch.msr  MSR_IS);
+   unsigned int as = !!(vcpu-arch.shared-msr  MSR_IS);
 
return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu-arch.pid, as);
 }
 
 int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr)
 {
-   unsigned int as = !!(vcpu-arch.msr  MSR_DS);
+   unsigned int as = !!(vcpu-arch.shared-msr  MSR_DS);
 
return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu-arch.pid, as);
 }
@@ -353,7 +353,7 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, 
gpa_t gpaddr,
 
stlbe.word1 = (hpaddr  0xfc00) | ((hpaddr  32)  0xf);
stlbe.word2 = kvmppc_44x_tlb_shadow_attrib(flags,
-   vcpu-arch.msr  MSR_PR);
+   vcpu-arch.shared-msr  
MSR_PR);
stlbe.tid = !(asid  0xff);
 
/* Keep track of the reference so we can properly release it later. */
@@ -422,7 +422,7 @@ static int tlbe_is_host_safe(const struct kvm_vcpu *vcpu,
 
/* Does it match current guest AS? */
/* XXX what about IS != DS? */
-   if (get_tlb_ts(tlbe) != !!(vcpu-arch.msr  MSR_IS))
+   if (get_tlb_ts(tlbe) != !!(vcpu-arch.shared-msr  MSR_IS))
return 0;
 
gpa = get_tlb_raddr(tlbe);
diff --git 

[PATCH 11/26] KVM: PPC: Make RMO a define

2010-06-25 Thread Alexander Graf
On PowerPC it's very normal to not support all of the physical RAM in real mode.
To check if we're matching on the shared page or not, we need to know the limits
so we can restrain ourselves to that range.

So let's make it a define instead of open-coding it. And while at it, let's also
increase it.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/include/asm/kvm_host.h |2 ++
 arch/powerpc/kvm/book3s.c   |4 ++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_host.h 
b/arch/powerpc/include/asm/kvm_host.h
index 83c45ea..e35c1ac 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -47,6 +47,8 @@
 #define HPTEG_HASH_NUM_VPTE(1  HPTEG_HASH_BITS_VPTE)
 #define HPTEG_HASH_NUM_VPTE_LONG   (1  HPTEG_HASH_BITS_VPTE_LONG)
 
+#define KVM_RMO0x0fffULL
+
 struct kvm;
 struct kvm_run;
 struct kvm_vcpu;
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index e76c950..2f55aa5 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -462,7 +462,7 @@ static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, 
bool data,
r = vcpu-arch.mmu.xlate(vcpu, eaddr, pte, data);
} else {
pte-eaddr = eaddr;
-   pte-raddr = eaddr  0x;
+   pte-raddr = eaddr  KVM_RMO;
pte-vpage = VSID_REAL | eaddr  12;
pte-may_read = true;
pte-may_write = true;
@@ -576,7 +576,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct 
kvm_vcpu *vcpu,
pte.may_execute = true;
pte.may_read = true;
pte.may_write = true;
-   pte.raddr = eaddr  0x;
+   pte.raddr = eaddr  KVM_RMO;
pte.eaddr = eaddr;
pte.vpage = eaddr  12;
}
-- 
1.6.0.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 15/26] KVM: PPC: Expose magic page support to guest

2010-06-25 Thread Alexander Graf
Now that we have the shared page in place and the MMU code knows about
the magic page, we can expose that capability to the guest!

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/include/asm/kvm_para.h |2 ++
 arch/powerpc/kvm/powerpc.c  |   11 +++
 2 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_para.h 
b/arch/powerpc/include/asm/kvm_para.h
index c7305d7..9f8efa4 100644
--- a/arch/powerpc/include/asm/kvm_para.h
+++ b/arch/powerpc/include/asm/kvm_para.h
@@ -43,6 +43,8 @@ struct kvm_vcpu_arch_shared {
 #define KVM_SC_MAGIC_R30x4b564d52 /* KVMR */
 #define KVM_SC_MAGIC_R40x554c455a /* ULEZ */
 
+#define KVM_FEATURE_MAGIC_PAGE 1
+
 #ifdef __KERNEL__
 
 static inline int kvm_para_available(void)
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index fe7a1c8..1d28a81 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -60,8 +60,19 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
}
 
switch (nr) {
+   case KVM_HC_PPC_MAP_MAGIC_PAGE:
+   {
+   vcpu-arch.magic_page_pa = param1;
+   vcpu-arch.magic_page_ea = param2;
+
+   r = 0;
+   break;
+   }
case KVM_HC_FEATURES:
r = 0;
+#if !defined(CONFIG_KVM_440) /* XXX missing bits on 440 */
+   r |= (1  KVM_FEATURE_MAGIC_PAGE);
+#endif
break;
default:
r = -KVM_ENOSYS;
-- 
1.6.0.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 07/26] KVM: PPC: Implement hypervisor interface

2010-06-25 Thread Alexander Graf
To communicate with KVM directly we need to plumb some sort of interface
between the guest and KVM. Usually those interfaces use hypercalls.

This hypercall implementation is described in the last patch of the series
in a special documentation file. Please read that for further information.

This patch implements stubs to handle KVM PPC hypercalls on the host and
guest side alike.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/include/asm/kvm_para.h |  100 ++-
 arch/powerpc/include/asm/kvm_ppc.h  |1 +
 arch/powerpc/kvm/book3s.c   |   10 +++-
 arch/powerpc/kvm/booke.c|   11 -
 arch/powerpc/kvm/emulate.c  |   11 -
 arch/powerpc/kvm/powerpc.c  |   28 ++
 include/linux/kvm_para.h|1 +
 7 files changed, 156 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_para.h 
b/arch/powerpc/include/asm/kvm_para.h
index e402999..eaab306 100644
--- a/arch/powerpc/include/asm/kvm_para.h
+++ b/arch/powerpc/include/asm/kvm_para.h
@@ -34,16 +34,112 @@ struct kvm_vcpu_arch_shared {
__u32 dsisr;
 };
 
+#define KVM_PVR_PARA   0x4b564d3f /* KVM? */
+#define KVM_SC_MAGIC_R30x4b564d52 /* KVMR */
+#define KVM_SC_MAGIC_R40x554c455a /* ULEZ */
+
 #ifdef __KERNEL__
 
 static inline int kvm_para_available(void)
 {
-   return 0;
+   unsigned long pvr = KVM_PVR_PARA;
+
+   asm volatile(mfpvr %0 : =r(pvr) : 0(pvr));
+   return pvr == KVM_PVR_PARA;
+}
+
+static inline long kvm_hypercall0(unsigned int nr)
+{
+   unsigned long register r3 asm(r3) = KVM_SC_MAGIC_R3;
+   unsigned long register r4 asm(r4) = KVM_SC_MAGIC_R4;
+   unsigned long register _nr asm(r5) = nr;
+
+   asm volatile(sc
+: =r(r3)
+: r(r3), r(r4), r(_nr)
+: memory);
+
+   return r3;
 }
 
+static inline long kvm_hypercall1(unsigned int nr, unsigned long p1)
+{
+   unsigned long register r3 asm(r3) = KVM_SC_MAGIC_R3;
+   unsigned long register r4 asm(r4) = KVM_SC_MAGIC_R4;
+   unsigned long register _nr asm(r5) = nr;
+   unsigned long register _p1 asm(r6) = p1;
+
+   asm volatile(sc
+: =r(r3)
+: r(r3), r(r4), r(_nr), r(_p1)
+: memory);
+
+   return r3;
+}
+
+static inline long kvm_hypercall2(unsigned int nr, unsigned long p1,
+ unsigned long p2)
+{
+   unsigned long register r3 asm(r3) = KVM_SC_MAGIC_R3;
+   unsigned long register r4 asm(r4) = KVM_SC_MAGIC_R4;
+   unsigned long register _nr asm(r5) = nr;
+   unsigned long register _p1 asm(r6) = p1;
+   unsigned long register _p2 asm(r7) = p2;
+
+   asm volatile(sc
+: =r(r3)
+: r(r3), r(r4), r(_nr), r(_p1), r(_p2)
+: memory);
+
+   return r3;
+}
+
+static inline long kvm_hypercall3(unsigned int nr, unsigned long p1,
+ unsigned long p2, unsigned long p3)
+{
+   unsigned long register r3 asm(r3) = KVM_SC_MAGIC_R3;
+   unsigned long register r4 asm(r4) = KVM_SC_MAGIC_R4;
+   unsigned long register _nr asm(r5) = nr;
+   unsigned long register _p1 asm(r6) = p1;
+   unsigned long register _p2 asm(r7) = p2;
+   unsigned long register _p3 asm(r8) = p3;
+
+   asm volatile(sc
+: =r(r3)
+: r(r3), r(r4), r(_nr), r(_p1), r(_p2), r(_p3)
+: memory);
+
+   return r3;
+}
+
+static inline long kvm_hypercall4(unsigned int nr, unsigned long p1,
+ unsigned long p2, unsigned long p3,
+ unsigned long p4)
+{
+   unsigned long register r3 asm(r3) = KVM_SC_MAGIC_R3;
+   unsigned long register r4 asm(r4) = KVM_SC_MAGIC_R4;
+   unsigned long register _nr asm(r5) = nr;
+   unsigned long register _p1 asm(r6) = p1;
+   unsigned long register _p2 asm(r7) = p2;
+   unsigned long register _p3 asm(r8) = p3;
+   unsigned long register _p4 asm(r9) = p4;
+
+   asm volatile(sc
+: =r(r3)
+: r(r3), r(r4), r(_nr), r(_p1), r(_p2), r(_p3),
+  r(_p4)
+: memory);
+
+   return r3;
+}
+
+
 static inline unsigned int kvm_arch_para_features(void)
 {
-   return 0;
+   if (!kvm_para_available())
+   return 0;
+
+   return kvm_hypercall0(KVM_HC_FEATURES);
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/powerpc/include/asm/kvm_ppc.h 
b/arch/powerpc/include/asm/kvm_ppc.h
index 18d139e..ecb3bc7 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -107,6 +107,7 @@ extern int kvmppc_booke_init(void);
 extern void kvmppc_booke_exit(void);
 
 extern void kvmppc_core_destroy_mmu(struct kvm_vcpu *vcpu);
+extern int kvmppc_kvm_pv(struct kvm_vcpu *vcpu);

[PATCH 09/26] KVM: PPC: Add PV guest scratch registers

2010-06-25 Thread Alexander Graf
While running in hooked code we need to store register contents out because
we must not clobber any registers.

So let's add some fields to the shared page we can just happily write to.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/include/asm/kvm_para.h |3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_para.h 
b/arch/powerpc/include/asm/kvm_para.h
index d1fe9ae..edf8f83 100644
--- a/arch/powerpc/include/asm/kvm_para.h
+++ b/arch/powerpc/include/asm/kvm_para.h
@@ -23,6 +23,9 @@
 #include linux/types.h
 
 struct kvm_vcpu_arch_shared {
+   __u64 scratch1;
+   __u64 scratch2;
+   __u64 scratch3;
__u64 critical; /* Guest may not get interrupts if == r1 */
__u64 sprg0;
__u64 sprg1;
-- 
1.6.0.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 01/26] KVM: PPC: Introduce shared page

2010-06-25 Thread Alexander Graf
For transparent variable sharing between the hypervisor and guest, I introduce
a shared page. This shared page will contain all the registers the guest can
read and write safely without exiting guest context.

This patch only implements the stubs required for the basic structure of the
shared page. The actual register moving follows.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/include/asm/kvm_host.h |2 ++
 arch/powerpc/include/asm/kvm_para.h |5 +
 arch/powerpc/kernel/asm-offsets.c   |1 +
 arch/powerpc/kvm/44x.c  |7 +++
 arch/powerpc/kvm/book3s.c   |7 +++
 arch/powerpc/kvm/e500.c |7 +++
 6 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_host.h 
b/arch/powerpc/include/asm/kvm_host.h
index 895eb63..bca9391 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -25,6 +25,7 @@
 #include linux/interrupt.h
 #include linux/types.h
 #include linux/kvm_types.h
+#include linux/kvm_para.h
 #include asm/kvm_asm.h
 
 #define KVM_MAX_VCPUS 1
@@ -289,6 +290,7 @@ struct kvm_vcpu_arch {
struct tasklet_struct tasklet;
u64 dec_jiffies;
unsigned long pending_exceptions;
+   struct kvm_vcpu_arch_shared *shared;
 
 #ifdef CONFIG_PPC_BOOK3S
struct kmem_cache *hpte_cache;
diff --git a/arch/powerpc/include/asm/kvm_para.h 
b/arch/powerpc/include/asm/kvm_para.h
index 2d48f6a..1485ba8 100644
--- a/arch/powerpc/include/asm/kvm_para.h
+++ b/arch/powerpc/include/asm/kvm_para.h
@@ -20,6 +20,11 @@
 #ifndef __POWERPC_KVM_PARA_H__
 #define __POWERPC_KVM_PARA_H__
 
+#include linux/types.h
+
+struct kvm_vcpu_arch_shared {
+};
+
 #ifdef __KERNEL__
 
 static inline int kvm_para_available(void)
diff --git a/arch/powerpc/kernel/asm-offsets.c 
b/arch/powerpc/kernel/asm-offsets.c
index 496cc5b..944f593 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -400,6 +400,7 @@ int main(void)
DEFINE(VCPU_SPRG6, offsetof(struct kvm_vcpu, arch.sprg6));
DEFINE(VCPU_SPRG7, offsetof(struct kvm_vcpu, arch.sprg7));
DEFINE(VCPU_SHADOW_PID, offsetof(struct kvm_vcpu, arch.shadow_pid));
+   DEFINE(VCPU_SHARED, offsetof(struct kvm_vcpu, arch.shared));
 
/* book3s */
 #ifdef CONFIG_PPC_BOOK3S
diff --git a/arch/powerpc/kvm/44x.c b/arch/powerpc/kvm/44x.c
index 73c0a3f..e7b1f3f 100644
--- a/arch/powerpc/kvm/44x.c
+++ b/arch/powerpc/kvm/44x.c
@@ -123,8 +123,14 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, 
unsigned int id)
if (err)
goto free_vcpu;
 
+   vcpu-arch.shared = (void*)__get_free_page(GFP_KERNEL|__GFP_ZERO);
+   if (!vcpu-arch.shared)
+   goto uninit_vcpu;
+
return vcpu;
 
+uninit_vcpu:
+   kvm_vcpu_uninit(vcpu);
 free_vcpu:
kmem_cache_free(kvm_vcpu_cache, vcpu_44x);
 out:
@@ -135,6 +141,7 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu)
 {
struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
 
+   free_page((unsigned long)vcpu-arch.shared);
kvm_vcpu_uninit(vcpu);
kmem_cache_free(kvm_vcpu_cache, vcpu_44x);
 }
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 884d4a5..ba79b35 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -1247,6 +1247,10 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm 
*kvm, unsigned int id)
if (err)
goto free_shadow_vcpu;
 
+   vcpu-arch.shared = (void*)__get_free_page(GFP_KERNEL|__GFP_ZERO);
+   if (!vcpu-arch.shared)
+   goto uninit_vcpu;
+
vcpu-arch.host_retip = kvm_return_point;
vcpu-arch.host_msr = mfmsr();
 #ifdef CONFIG_PPC_BOOK3S_64
@@ -1277,6 +1281,8 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, 
unsigned int id)
 
return vcpu;
 
+uninit_vcpu:
+   kvm_vcpu_uninit(vcpu);
 free_shadow_vcpu:
kfree(vcpu_book3s-shadow_vcpu);
 free_vcpu:
@@ -1289,6 +1295,7 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu)
 {
struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu);
 
+   free_page((unsigned long)vcpu-arch.shared);
kvm_vcpu_uninit(vcpu);
kfree(vcpu_book3s-shadow_vcpu);
vfree(vcpu_book3s);
diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c
index e8a00b0..71750f2 100644
--- a/arch/powerpc/kvm/e500.c
+++ b/arch/powerpc/kvm/e500.c
@@ -117,8 +117,14 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, 
unsigned int id)
if (err)
goto uninit_vcpu;
 
+   vcpu-arch.shared = (void*)__get_free_page(GFP_KERNEL|__GFP_ZERO);
+   if (!vcpu-arch.shared)
+   goto uninit_tlb;
+
return vcpu;
 
+uninit_tlb:
+   kvmppc_e500_tlb_uninit(vcpu_e500);
 uninit_vcpu:
kvm_vcpu_uninit(vcpu);
 free_vcpu:
@@ -131,6 +137,7 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu)
 {
struct kvmppc_vcpu_e500 *vcpu_e500 = 

[PATCH 21/26] KVM: PPC: Introduce kvm_tmp framework

2010-06-25 Thread Alexander Graf
We will soon require more sophisticated methods to replace single instructions
with multiple instructions. We do that by branching to a memory region where we
write replacement code for the instruction to.

This region needs to be within 32 MB of the patched instruction though, because
that's the furthest we can jump with immediate branches.

So we keep 1MB of free space around in bss. After we're done initing we can just
tell the mm system that the unused pages are free, but until then we have enough
space to fit all our code in.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/kernel/kvm.c |   41 +++--
 1 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index b091f94..7e8fe6f 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -64,6 +64,8 @@
 #define KVM_INST_TLBSYNC   0x7c00046c
 
 static bool kvm_patching_worked = true;
+static char kvm_tmp[1024 * 1024];
+static int kvm_tmp_index;
 
 static void kvm_patch_ins_ld(u32 *inst, long addr, u32 rt)
 {
@@ -98,6 +100,23 @@ static void kvm_patch_ins_nop(u32 *inst)
*inst = KVM_INST_NOP;
 }
 
+static u32 *kvm_alloc(int len)
+{
+   u32 *p;
+
+   if ((kvm_tmp_index + len)  ARRAY_SIZE(kvm_tmp)) {
+   printk(KERN_ERR KVM: No more space (%d + %d)\n,
+   kvm_tmp_index, len);
+   kvm_patching_worked = false;
+   return NULL;
+   }
+
+   p = (void*)kvm_tmp[kvm_tmp_index];
+   kvm_tmp_index += len;
+
+   return p;
+}
+
 static void kvm_map_magic_page(void *data)
 {
kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
@@ -197,12 +216,27 @@ static void kvm_use_magic_page(void)
kvm_check_ins(p);
 }
 
+static void kvm_free_tmp(void)
+{
+   unsigned long start, end;
+
+   start = (ulong)kvm_tmp[kvm_tmp_index + (PAGE_SIZE - 1)]  PAGE_MASK;
+   end = (ulong)kvm_tmp[ARRAY_SIZE(kvm_tmp)]  PAGE_MASK;
+
+   /* Free the tmp space we don't need */
+   for (; start  end; start += PAGE_SIZE) {
+   ClearPageReserved(virt_to_page(start));
+   init_page_count(virt_to_page(start));
+   free_page(start);
+   totalram_pages++;
+   }
+}
+
 static int __init kvm_guest_init(void)
 {
-   char *p;
 
if (!kvm_para_available())
-   return 0;
+   goto free_tmp;
 
if (kvm_para_has_feature(KVM_FEATURE_MAGIC_PAGE))
kvm_use_magic_page();
@@ -210,6 +244,9 @@ static int __init kvm_guest_init(void)
printk(KERN_INFO KVM: Live patching for a fast VM %s\n,
 kvm_patching_worked ? worked : failed);
 
+free_tmp:
+   kvm_free_tmp();
+
return 0;
 }
 
-- 
1.6.0.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 06/26] KVM: PPC: Convert SPRG[0-4] to shared page

2010-06-25 Thread Alexander Graf
When in kernel mode there are 4 additional registers available that are
simple data storage. Instead of exiting to the hypervisor to read and
write those, we can just share them with the guest using the page.

This patch converts all users of the current field to the shared page.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/include/asm/kvm_host.h |4 
 arch/powerpc/include/asm/kvm_para.h |4 
 arch/powerpc/kvm/book3s.c   |   16 
 arch/powerpc/kvm/booke.c|   16 
 arch/powerpc/kvm/emulate.c  |   24 
 5 files changed, 36 insertions(+), 28 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_host.h 
b/arch/powerpc/include/asm/kvm_host.h
index 6bcf62f..83c45ea 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -216,10 +216,6 @@ struct kvm_vcpu_arch {
ulong guest_owned_ext;
 #endif
u32 mmucr;
-   ulong sprg0;
-   ulong sprg1;
-   ulong sprg2;
-   ulong sprg3;
ulong sprg4;
ulong sprg5;
ulong sprg6;
diff --git a/arch/powerpc/include/asm/kvm_para.h 
b/arch/powerpc/include/asm/kvm_para.h
index d7fc6c2..e402999 100644
--- a/arch/powerpc/include/asm/kvm_para.h
+++ b/arch/powerpc/include/asm/kvm_para.h
@@ -23,6 +23,10 @@
 #include linux/types.h
 
 struct kvm_vcpu_arch_shared {
+   __u64 sprg0;
+   __u64 sprg1;
+   __u64 sprg2;
+   __u64 sprg3;
__u64 srr0;
__u64 srr1;
__u64 dar;
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index b144697..5a6f055 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -1062,10 +1062,10 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, 
struct kvm_regs *regs)
regs-srr0 = vcpu-arch.shared-srr0;
regs-srr1 = vcpu-arch.shared-srr1;
regs-pid = vcpu-arch.pid;
-   regs-sprg0 = vcpu-arch.sprg0;
-   regs-sprg1 = vcpu-arch.sprg1;
-   regs-sprg2 = vcpu-arch.sprg2;
-   regs-sprg3 = vcpu-arch.sprg3;
+   regs-sprg0 = vcpu-arch.shared-sprg0;
+   regs-sprg1 = vcpu-arch.shared-sprg1;
+   regs-sprg2 = vcpu-arch.shared-sprg2;
+   regs-sprg3 = vcpu-arch.shared-sprg3;
regs-sprg5 = vcpu-arch.sprg4;
regs-sprg6 = vcpu-arch.sprg5;
regs-sprg7 = vcpu-arch.sprg6;
@@ -1088,10 +1088,10 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, 
struct kvm_regs *regs)
kvmppc_set_msr(vcpu, regs-msr);
vcpu-arch.shared-srr0 = regs-srr0;
vcpu-arch.shared-srr1 = regs-srr1;
-   vcpu-arch.sprg0 = regs-sprg0;
-   vcpu-arch.sprg1 = regs-sprg1;
-   vcpu-arch.sprg2 = regs-sprg2;
-   vcpu-arch.sprg3 = regs-sprg3;
+   vcpu-arch.shared-sprg0 = regs-sprg0;
+   vcpu-arch.shared-sprg1 = regs-sprg1;
+   vcpu-arch.shared-sprg2 = regs-sprg2;
+   vcpu-arch.shared-sprg3 = regs-sprg3;
vcpu-arch.sprg5 = regs-sprg4;
vcpu-arch.sprg6 = regs-sprg5;
vcpu-arch.sprg7 = regs-sprg6;
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 8b546fe..984c461 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -495,10 +495,10 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, 
struct kvm_regs *regs)
regs-srr0 = vcpu-arch.shared-srr0;
regs-srr1 = vcpu-arch.shared-srr1;
regs-pid = vcpu-arch.pid;
-   regs-sprg0 = vcpu-arch.sprg0;
-   regs-sprg1 = vcpu-arch.sprg1;
-   regs-sprg2 = vcpu-arch.sprg2;
-   regs-sprg3 = vcpu-arch.sprg3;
+   regs-sprg0 = vcpu-arch.shared-sprg0;
+   regs-sprg1 = vcpu-arch.shared-sprg1;
+   regs-sprg2 = vcpu-arch.shared-sprg2;
+   regs-sprg3 = vcpu-arch.shared-sprg3;
regs-sprg5 = vcpu-arch.sprg4;
regs-sprg6 = vcpu-arch.sprg5;
regs-sprg7 = vcpu-arch.sprg6;
@@ -521,10 +521,10 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, 
struct kvm_regs *regs)
kvmppc_set_msr(vcpu, regs-msr);
vcpu-arch.shared-srr0 = regs-srr0;
vcpu-arch.shared-srr1 = regs-srr1;
-   vcpu-arch.sprg0 = regs-sprg0;
-   vcpu-arch.sprg1 = regs-sprg1;
-   vcpu-arch.sprg2 = regs-sprg2;
-   vcpu-arch.sprg3 = regs-sprg3;
+   vcpu-arch.shared-sprg0 = regs-sprg0;
+   vcpu-arch.shared-sprg1 = regs-sprg1;
+   vcpu-arch.shared-sprg2 = regs-sprg2;
+   vcpu-arch.shared-sprg3 = regs-sprg3;
vcpu-arch.sprg5 = regs-sprg4;
vcpu-arch.sprg6 = regs-sprg5;
vcpu-arch.sprg7 = regs-sprg6;
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index ad0fa4f..454869b 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -263,13 +263,17 @@ int kvmppc_emulate_instruction(struct kvm_run *run, 
struct kvm_vcpu *vcpu)
kvmppc_set_gpr(vcpu, rt, get_tb()); break;
 
case SPRN_SPRG0:
-   kvmppc_set_gpr(vcpu, rt, 

[PATCH 13/26] KVM: PPC: Magic Page Book3s support

2010-06-25 Thread Alexander Graf
We need to override EA as well as PA lookups for the magic page. When the guest
tells us to project it, the magic page overrides any guest mappings.

In order to reflect that, we need to hook into all the MMU layers of KVM to
force map the magic page if necessary.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/kvm/book3s.c |7 +++
 arch/powerpc/kvm/book3s_32_mmu.c  |   16 
 arch/powerpc/kvm/book3s_32_mmu_host.c |   12 
 arch/powerpc/kvm/book3s_64_mmu.c  |   30 +-
 arch/powerpc/kvm/book3s_64_mmu_host.c |   12 
 5 files changed, 76 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 2f55aa5..6ce7fa1 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -551,6 +551,13 @@ mmio:
 
 static int kvmppc_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn)
 {
+   ulong mp_pa = vcpu-arch.magic_page_pa;
+
+   if (unlikely(mp_pa) 
+   unlikely((mp_pa  KVM_RMO)  PAGE_SHIFT == gfn)) {
+   return 1;
+   }
+
return kvm_is_visible_gfn(vcpu-kvm, gfn);
 }
 
diff --git a/arch/powerpc/kvm/book3s_32_mmu.c b/arch/powerpc/kvm/book3s_32_mmu.c
index 41130c8..d2bd1a6 100644
--- a/arch/powerpc/kvm/book3s_32_mmu.c
+++ b/arch/powerpc/kvm/book3s_32_mmu.c
@@ -281,8 +281,24 @@ static int kvmppc_mmu_book3s_32_xlate(struct kvm_vcpu 
*vcpu, gva_t eaddr,
  struct kvmppc_pte *pte, bool data)
 {
int r;
+   ulong mp_ea = vcpu-arch.magic_page_ea;
 
pte-eaddr = eaddr;
+
+   /* Magic page override */
+   if (unlikely(mp_ea) 
+   unlikely((eaddr  ~0xfffULL) == (mp_ea  ~0xfffULL)) 
+   !(vcpu-arch.shared-msr  MSR_PR)) {
+   pte-vpage = kvmppc_mmu_book3s_32_ea_to_vp(vcpu, eaddr, data);
+   pte-raddr = vcpu-arch.magic_page_pa | (pte-raddr  0xfff);
+   pte-raddr = KVM_RMO;
+   pte-may_execute = true;
+   pte-may_read = true;
+   pte-may_write = true;
+
+   return 0;
+   }
+
r = kvmppc_mmu_book3s_32_xlate_bat(vcpu, eaddr, pte, data);
if (r  0)
   r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte, data, true);
diff --git a/arch/powerpc/kvm/book3s_32_mmu_host.c 
b/arch/powerpc/kvm/book3s_32_mmu_host.c
index 67b8c38..658d3e0 100644
--- a/arch/powerpc/kvm/book3s_32_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_32_mmu_host.c
@@ -145,6 +145,16 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct 
kvmppc_pte *orig_pte)
bool primary = false;
bool evict = false;
struct hpte_cache *pte;
+   ulong mp_pa = vcpu-arch.magic_page_pa;
+
+   /* Magic page override */
+   if (unlikely(mp_pa) 
+   unlikely((orig_pte-raddr  ~0xfffUL  KVM_RMO) ==
+(mp_pa  ~0xfffUL  KVM_RMO))) {
+   hpaddr = (pfn_t)virt_to_phys(vcpu-arch.shared);
+   get_page(pfn_to_page(hpaddr  PAGE_SHIFT));
+   goto mapped;
+   }
 
/* Get host physical address for gpa */
hpaddr = gfn_to_pfn(vcpu-kvm, orig_pte-raddr  PAGE_SHIFT);
@@ -155,6 +165,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct 
kvmppc_pte *orig_pte)
}
hpaddr = PAGE_SHIFT;
 
+mapped:
+
/* and write the mapping ea - hpa into the pt */
vcpu-arch.mmu.esid_to_vsid(vcpu, orig_pte-eaddr  SID_SHIFT, vsid);
map = find_sid_vsid(vcpu, vsid);
diff --git a/arch/powerpc/kvm/book3s_64_mmu.c b/arch/powerpc/kvm/book3s_64_mmu.c
index 58aa840..4a2e5fc 100644
--- a/arch/powerpc/kvm/book3s_64_mmu.c
+++ b/arch/powerpc/kvm/book3s_64_mmu.c
@@ -163,6 +163,22 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu 
*vcpu, gva_t eaddr,
bool found = false;
bool perm_err = false;
int second = 0;
+   ulong mp_ea = vcpu-arch.magic_page_ea;
+
+   /* Magic page override */
+   if (unlikely(mp_ea) 
+   unlikely((eaddr  ~0xfffULL) == (mp_ea  ~0xfffULL)) 
+   !(vcpu-arch.shared-msr  MSR_PR)) {
+   gpte-eaddr = eaddr;
+   gpte-vpage = kvmppc_mmu_book3s_64_ea_to_vp(vcpu, eaddr, data);
+   gpte-raddr = vcpu-arch.magic_page_pa | (gpte-raddr  0xfff);
+   gpte-raddr = KVM_RMO;
+   gpte-may_execute = true;
+   gpte-may_read = true;
+   gpte-may_write = true;
+
+   return 0;
+   }
 
slbe = kvmppc_mmu_book3s_64_find_slbe(vcpu_book3s, eaddr);
if (!slbe)
@@ -445,6 +461,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct 
kvm_vcpu *vcpu, ulong esid,
ulong ea = esid  SID_SHIFT;
struct kvmppc_slb *slb;
u64 gvsid = esid;
+   ulong mp_ea = vcpu-arch.magic_page_ea;
 
if (vcpu-arch.shared-msr  (MSR_DR|MSR_IR)) {
slb = kvmppc_mmu_book3s_64_find_slbe(to_book3s(vcpu), ea);
@@ -464,7 +481,7 @@ static int 

[PATCH 08/26] KVM: PPC: Add PV guest critical sections

2010-06-25 Thread Alexander Graf
When running in hooked code we need a way to disable interrupts without
clobbering any interrupts or exiting out to the hypervisor.

To achieve this, we have an additional critical field in the shared page. If
that field is equal to the r1 register of the guest, it tells the hypervisor
that we're in such a critical section and thus may not receive any interrupts.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/include/asm/kvm_para.h |1 +
 arch/powerpc/kvm/book3s.c   |   15 +--
 arch/powerpc/kvm/booke.c|   12 
 3 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_para.h 
b/arch/powerpc/include/asm/kvm_para.h
index eaab306..d1fe9ae 100644
--- a/arch/powerpc/include/asm/kvm_para.h
+++ b/arch/powerpc/include/asm/kvm_para.h
@@ -23,6 +23,7 @@
 #include linux/types.h
 
 struct kvm_vcpu_arch_shared {
+   __u64 critical; /* Guest may not get interrupts if == r1 */
__u64 sprg0;
__u64 sprg1;
__u64 sprg2;
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index e8001c5..f0e8047 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -251,14 +251,25 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, 
unsigned int priority)
int deliver = 1;
int vec = 0;
ulong flags = 0ULL;
+   ulong crit_raw = vcpu-arch.shared-critical;
+   ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
+   bool crit;
+
+   /* Truncate crit indicators in 32 bit mode */
+   if (!(vcpu-arch.shared-msr  MSR_SF)) {
+   crit_raw = 0x;
+   crit_r1 = 0x;
+   }
+
+   crit = (crit_raw == crit_r1);
 
switch (priority) {
case BOOK3S_IRQPRIO_DECREMENTER:
-   deliver = vcpu-arch.shared-msr  MSR_EE;
+   deliver = (vcpu-arch.shared-msr  MSR_EE)  !crit;
vec = BOOK3S_INTERRUPT_DECREMENTER;
break;
case BOOK3S_IRQPRIO_EXTERNAL:
-   deliver = vcpu-arch.shared-msr  MSR_EE;
+   deliver = (vcpu-arch.shared-msr  MSR_EE)  !crit;
vec = BOOK3S_INTERRUPT_EXTERNAL;
break;
case BOOK3S_IRQPRIO_SYSTEM_RESET:
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index e7d1216..485f8fa 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -147,6 +147,17 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu 
*vcpu,
int allowed = 0;
ulong uninitialized_var(msr_mask);
bool update_esr = false, update_dear = false;
+   ulong crit_raw = vcpu-arch.shared-critical;
+   ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
+   bool crit;
+
+   /* Truncate crit indicators in 32 bit mode */
+   if (!(vcpu-arch.shared-msr  MSR_SF)) {
+   crit_raw = 0x;
+   crit_r1 = 0x;
+   }
+
+   crit = (crit_raw == crit_r1);
 
switch (priority) {
case BOOKE_IRQPRIO_DTLB_MISS:
@@ -181,6 +192,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu 
*vcpu,
case BOOKE_IRQPRIO_DECREMENTER:
case BOOKE_IRQPRIO_FIT:
allowed = vcpu-arch.shared-msr  MSR_EE;
+   allowed = allowed  !crit;
msr_mask = MSR_CE|MSR_ME|MSR_DE;
break;
case BOOKE_IRQPRIO_DEBUG:
-- 
1.6.0.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 14/26] KVM: PPC: Magic Page BookE support

2010-06-25 Thread Alexander Graf
As we now have Book3s support for the magic page, we also need BookE to
join in on the party.

This patch implements generic magic page logic for BookE and specific
TLB logic for e500. I didn't have any 440 around, so I didn't dare to
blindly try and write up broken code.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/kvm/booke.c|   29 +
 arch/powerpc/kvm/e500_tlb.c |   19 +--
 2 files changed, 46 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 2229df9..7957aa4 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -241,6 +241,31 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
vcpu-arch.shared-int_pending = 0;
 }
 
+/* Check if a DTLB miss was on the magic page. Returns !0 if so. */
+int kvmppc_dtlb_magic_page(struct kvm_vcpu *vcpu, ulong eaddr)
+{
+   ulong mp_ea = vcpu-arch.magic_page_ea;
+   ulong gpaddr = vcpu-arch.magic_page_pa;
+   int gtlb_index = 11 | (1  16); /* Random number in TLB1 */
+
+   /* Check for existence of magic page */
+   if(likely(!mp_ea))
+   return 0;
+
+   /* Check if we're on the magic page */
+   if(likely((eaddr  12) != (mp_ea  12)))
+   return 0;
+
+   /* Don't map in user mode */
+   if(vcpu-arch.shared-msr  MSR_PR)
+   return 0;
+
+   kvmppc_mmu_map(vcpu, vcpu-arch.magic_page_ea, gpaddr, gtlb_index);
+   kvmppc_account_exit(vcpu, DTLB_VIRT_MISS_EXITS);
+
+   return 1;
+}
+
 /**
  * kvmppc_handle_exit
  *
@@ -308,6 +333,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu 
*vcpu,
r = RESUME_HOST;
break;
case EMULATE_FAIL:
+   case EMULATE_DO_MMIO:
/* XXX Deliver Program interrupt to guest. */
printk(KERN_CRIT %s: emulation at %lx failed (%08x)\n,
   __func__, vcpu-arch.pc, vcpu-arch.last_inst);
@@ -377,6 +403,9 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu 
*vcpu,
gpa_t gpaddr;
gfn_t gfn;
 
+   if (kvmppc_dtlb_magic_page(vcpu, eaddr))
+   break;
+
/* Check the guest TLB. */
gtlb_index = kvmppc_mmu_dtlb_index(vcpu, eaddr);
if (gtlb_index  0) {
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index 66845a5..f5582ca 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -295,9 +295,22 @@ static inline void kvmppc_e500_shadow_map(struct 
kvmppc_vcpu_e500 *vcpu_e500,
struct page *new_page;
struct tlbe *stlbe;
hpa_t hpaddr;
+   u32 mas2 = gtlbe-mas2;
+   u32 mas3 = gtlbe-mas3;
 
stlbe = vcpu_e500-shadow_tlb[tlbsel][esel];
 
+   if ((vcpu_e500-vcpu.arch.magic_page_ea) 
+   ((vcpu_e500-vcpu.arch.magic_page_pa  PAGE_SHIFT) == gfn) 
+   !(vcpu_e500-vcpu.arch.shared-msr  MSR_PR)) {
+   mas2 = 0;
+   mas3 = E500_TLB_SUPER_PERM_MASK;
+   hpaddr = virt_to_phys(vcpu_e500-vcpu.arch.shared);
+   new_page = pfn_to_page(hpaddr  PAGE_SHIFT);
+   get_page(new_page);
+   goto mapped;
+   }
+
/* Get reference to new page. */
new_page = gfn_to_page(vcpu_e500-vcpu.kvm, gfn);
if (is_error_page(new_page)) {
@@ -305,6 +318,8 @@ static inline void kvmppc_e500_shadow_map(struct 
kvmppc_vcpu_e500 *vcpu_e500,
kvm_release_page_clean(new_page);
return;
}
+
+mapped:
hpaddr = page_to_phys(new_page);
 
/* Drop reference to old page. */
@@ -316,10 +331,10 @@ static inline void kvmppc_e500_shadow_map(struct 
kvmppc_vcpu_e500 *vcpu_e500,
stlbe-mas1 = MAS1_TSIZE(BOOK3E_PAGESZ_4K)
| MAS1_TID(get_tlb_tid(gtlbe)) | MAS1_TS | MAS1_VALID;
stlbe-mas2 = (gvaddr  MAS2_EPN)
-   | e500_shadow_mas2_attrib(gtlbe-mas2,
+   | e500_shadow_mas2_attrib(mas2,
vcpu_e500-vcpu.arch.shared-msr  MSR_PR);
stlbe-mas3 = (hpaddr  MAS3_RPN)
-   | e500_shadow_mas3_attrib(gtlbe-mas3,
+   | e500_shadow_mas3_attrib(mas3,
vcpu_e500-vcpu.arch.shared-msr  MSR_PR);
stlbe-mas7 = (hpaddr  32)  MAS7_RPN;
 
-- 
1.6.0.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 17/26] KVM: PPC: Generic KVM PV guest support

2010-06-25 Thread Alexander Graf
We have all the hypervisor pieces in place now, but the guest parts are still
missing.

This patch implements basic awareness of KVM when running Linux as guest. It
doesn't do anything with it yet though.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/kernel/Makefile  |2 ++
 arch/powerpc/kernel/asm-offsets.c |   15 +++
 arch/powerpc/kernel/kvm.c |   34 ++
 arch/powerpc/kernel/kvm_emul.S|   27 +++
 arch/powerpc/platforms/Kconfig|   10 ++
 5 files changed, 88 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/kernel/kvm.c
 create mode 100644 arch/powerpc/kernel/kvm_emul.S

diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 58d0572..2d7eb9e 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -125,6 +125,8 @@ ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),)
 obj-y  += ppc_save_regs.o
 endif
 
+obj-$(CONFIG_KVM_GUEST) += kvm.o kvm_emul.o
+
 # Disable GCOV in odd or sensitive code
 GCOV_PROFILE_prom_init.o := n
 GCOV_PROFILE_ftrace.o := n
diff --git a/arch/powerpc/kernel/asm-offsets.c 
b/arch/powerpc/kernel/asm-offsets.c
index a55d47e..e3e740b 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -465,6 +465,21 @@ int main(void)
DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr));
 #endif /* CONFIG_PPC_BOOK3S */
 #endif
+
+#ifdef CONFIG_KVM_GUEST
+   DEFINE(KVM_MAGIC_SCRATCH1, offsetof(struct kvm_vcpu_arch_shared,
+   scratch1));
+   DEFINE(KVM_MAGIC_SCRATCH2, offsetof(struct kvm_vcpu_arch_shared,
+   scratch2));
+   DEFINE(KVM_MAGIC_SCRATCH3, offsetof(struct kvm_vcpu_arch_shared,
+   scratch3));
+   DEFINE(KVM_MAGIC_INT, offsetof(struct kvm_vcpu_arch_shared,
+  int_pending));
+   DEFINE(KVM_MAGIC_MSR, offsetof(struct kvm_vcpu_arch_shared, msr));
+   DEFINE(KVM_MAGIC_CRITICAL, offsetof(struct kvm_vcpu_arch_shared,
+   critical));
+#endif
+
 #ifdef CONFIG_44x
DEFINE(PGD_T_LOG2, PGD_T_LOG2);
DEFINE(PTE_T_LOG2, PTE_T_LOG2);
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
new file mode 100644
index 000..2d8dd73
--- /dev/null
+++ b/arch/powerpc/kernel/kvm.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010 SUSE Linux Products GmbH. All rights reserved.
+ *
+ * Authors:
+ * Alexander Graf ag...@suse.de
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include linux/kvm_host.h
+#include linux/init.h
+#include linux/kvm_para.h
+#include linux/slab.h
+
+#include asm/reg.h
+#include asm/kvm_ppc.h
+#include asm/sections.h
+#include asm/cacheflush.h
+#include asm/disassemble.h
+
+#define KVM_MAGIC_PAGE (-4096L)
+#define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
+
diff --git a/arch/powerpc/kernel/kvm_emul.S b/arch/powerpc/kernel/kvm_emul.S
new file mode 100644
index 000..c7b9fc9
--- /dev/null
+++ b/arch/powerpc/kernel/kvm_emul.S
@@ -0,0 +1,27 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright SUSE Linux Products GmbH 2010
+ *
+ * Authors: Alexander Graf ag...@suse.de
+ */
+
+#include asm/ppc_asm.h
+#include asm/kvm_asm.h
+#include asm/reg.h
+#include asm/page.h
+#include asm/asm-offsets.h
+
+#define KVM_MAGIC_PAGE (-4096)
+
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index d1663db..1744349 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -21,6 +21,16 @@ source 

[PATCH 19/26] KVM: PPC: PV instructions to loads and stores

2010-06-25 Thread Alexander Graf
Some instructions can simply be replaced by load and store instructions to
or from the magic page.

This patch replaces often called instructions that fall into the above category.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/kernel/kvm.c |  111 +
 1 files changed, 111 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index d873bc6..b165b20 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -32,8 +32,65 @@
 #define KVM_MAGIC_PAGE (-4096L)
 #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
 
+#define KVM_INST_LWZ   0x8000
+#define KVM_INST_STW   0x9000
+#define KVM_INST_LD0xe800
+#define KVM_INST_STD   0xf800
+#define KVM_INST_NOP   0x6000
+#define KVM_INST_B 0x4800
+#define KVM_INST_B_MASK0x03ff
+#define KVM_INST_B_MAX 0x01ff
+
+#define KVM_MASK_RT0x03e0
+#define KVM_INST_MFMSR 0x7ca6
+#define KVM_INST_MFSPR_SPRG0   0x7c1042a6
+#define KVM_INST_MFSPR_SPRG1   0x7c1142a6
+#define KVM_INST_MFSPR_SPRG2   0x7c1242a6
+#define KVM_INST_MFSPR_SPRG3   0x7c1342a6
+#define KVM_INST_MFSPR_SRR00x7c1a02a6
+#define KVM_INST_MFSPR_SRR10x7c1b02a6
+#define KVM_INST_MFSPR_DAR 0x7c1302a6
+#define KVM_INST_MFSPR_DSISR   0x7c1202a6
+
+#define KVM_INST_MTSPR_SPRG0   0x7c1043a6
+#define KVM_INST_MTSPR_SPRG1   0x7c1143a6
+#define KVM_INST_MTSPR_SPRG2   0x7c1243a6
+#define KVM_INST_MTSPR_SPRG3   0x7c1343a6
+#define KVM_INST_MTSPR_SRR00x7c1a03a6
+#define KVM_INST_MTSPR_SRR10x7c1b03a6
+#define KVM_INST_MTSPR_DAR 0x7c1303a6
+#define KVM_INST_MTSPR_DSISR   0x7c1203a6
+
 static bool kvm_patching_worked = true;
 
+static void kvm_patch_ins_ld(u32 *inst, long addr, u32 rt)
+{
+#ifdef CONFIG_64BIT
+   *inst = KVM_INST_LD | rt | (addr  0xfffc);
+#else
+   *inst = KVM_INST_LWZ | rt | ((addr + 4)  0xfffc);
+#endif
+}
+
+static void kvm_patch_ins_lwz(u32 *inst, long addr, u32 rt)
+{
+   *inst = KVM_INST_LWZ | rt | (addr  0x);
+}
+
+static void kvm_patch_ins_std(u32 *inst, long addr, u32 rt)
+{
+#ifdef CONFIG_64BIT
+   *inst = KVM_INST_STD | rt | (addr  0xfffc);
+#else
+   *inst = KVM_INST_STW | rt | ((addr + 4)  0xfffc);
+#endif
+}
+
+static void kvm_patch_ins_stw(u32 *inst, long addr, u32 rt)
+{
+   *inst = KVM_INST_STW | rt | (addr  0xfffc);
+}
+
 static void kvm_map_magic_page(void *data)
 {
kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
@@ -48,6 +105,60 @@ static void kvm_check_ins(u32 *inst)
u32 inst_rt = _inst  KVM_MASK_RT;
 
switch (inst_no_rt) {
+   /* Loads */
+   case KVM_INST_MFMSR:
+   kvm_patch_ins_ld(inst, magic_var(msr), inst_rt);
+   break;
+   case KVM_INST_MFSPR_SPRG0:
+   kvm_patch_ins_ld(inst, magic_var(sprg0), inst_rt);
+   break;
+   case KVM_INST_MFSPR_SPRG1:
+   kvm_patch_ins_ld(inst, magic_var(sprg1), inst_rt);
+   break;
+   case KVM_INST_MFSPR_SPRG2:
+   kvm_patch_ins_ld(inst, magic_var(sprg2), inst_rt);
+   break;
+   case KVM_INST_MFSPR_SPRG3:
+   kvm_patch_ins_ld(inst, magic_var(sprg3), inst_rt);
+   break;
+   case KVM_INST_MFSPR_SRR0:
+   kvm_patch_ins_ld(inst, magic_var(srr0), inst_rt);
+   break;
+   case KVM_INST_MFSPR_SRR1:
+   kvm_patch_ins_ld(inst, magic_var(srr1), inst_rt);
+   break;
+   case KVM_INST_MFSPR_DAR:
+   kvm_patch_ins_ld(inst, magic_var(dar), inst_rt);
+   break;
+   case KVM_INST_MFSPR_DSISR:
+   kvm_patch_ins_lwz(inst, magic_var(dsisr), inst_rt);
+   break;
+
+   /* Stores */
+   case KVM_INST_MTSPR_SPRG0:
+   kvm_patch_ins_std(inst, magic_var(sprg0), inst_rt);
+   break;
+   case KVM_INST_MTSPR_SPRG1:
+   kvm_patch_ins_std(inst, magic_var(sprg1), inst_rt);
+   break;
+   case KVM_INST_MTSPR_SPRG2:
+   kvm_patch_ins_std(inst, magic_var(sprg2), inst_rt);
+   break;
+   case KVM_INST_MTSPR_SPRG3:
+   kvm_patch_ins_std(inst, magic_var(sprg3), inst_rt);
+   break;
+   case KVM_INST_MTSPR_SRR0:
+   kvm_patch_ins_std(inst, magic_var(srr0), inst_rt);
+   break;
+   case KVM_INST_MTSPR_SRR1:
+   kvm_patch_ins_std(inst, magic_var(srr1), inst_rt);
+   break;
+   case KVM_INST_MTSPR_DAR:
+   kvm_patch_ins_std(inst, magic_var(dar), inst_rt);
+   break;
+   case KVM_INST_MTSPR_DSISR:
+   kvm_patch_ins_stw(inst, magic_var(dsisr), inst_rt);
+   break;
}
 
switch (_inst) {
-- 
1.6.0.2


[PATCH 10/26] KVM: PPC: Tell guest about pending interrupts

2010-06-25 Thread Alexander Graf
When the guest turns on interrupts again, it needs to know if we have an
interrupt pending for it. Because if so, it should rather get out of guest
context and get the interrupt.

So we introduce a new field in the shared page that we use to tell the guest
that there's a pending interrupt lying around.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/include/asm/kvm_para.h |1 +
 arch/powerpc/kvm/book3s.c   |7 +++
 arch/powerpc/kvm/booke.c|7 +++
 3 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_para.h 
b/arch/powerpc/include/asm/kvm_para.h
index edf8f83..c7305d7 100644
--- a/arch/powerpc/include/asm/kvm_para.h
+++ b/arch/powerpc/include/asm/kvm_para.h
@@ -36,6 +36,7 @@ struct kvm_vcpu_arch_shared {
__u64 dar;
__u64 msr;
__u32 dsisr;
+   __u32 int_pending;  /* Tells the guest if we have an interrupt */
 };
 
 #define KVM_PVR_PARA   0x4b564d3f /* KVM? */
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index f0e8047..e76c950 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -334,6 +334,7 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, 
unsigned int priority)
 void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
 {
unsigned long *pending = vcpu-arch.pending_exceptions;
+   unsigned long old_pending = vcpu-arch.pending_exceptions;
unsigned int priority;
 
 #ifdef EXIT_DEBUG
@@ -353,6 +354,12 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
 BITS_PER_BYTE * sizeof(*pending),
 priority + 1);
}
+
+   /* Tell the guest about our interrupt status */
+   if (*pending)
+   vcpu-arch.shared-int_pending = 1;
+   else if (old_pending)
+   vcpu-arch.shared-int_pending = 0;
 }
 
 void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr)
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 485f8fa..2229df9 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -221,6 +221,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu 
*vcpu,
 void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
 {
unsigned long *pending = vcpu-arch.pending_exceptions;
+   unsigned long old_pending = vcpu-arch.pending_exceptions;
unsigned int priority;
 
priority = __ffs(*pending);
@@ -232,6 +233,12 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
 BITS_PER_BYTE * sizeof(*pending),
 priority + 1);
}
+
+   /* Tell the guest about our interrupt status */
+   if (*pending)
+   vcpu-arch.shared-int_pending = 1;
+   else if (old_pending)
+   vcpu-arch.shared-int_pending = 0;
 }
 
 /**
-- 
1.6.0.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 22/26] KVM: PPC: PV assembler helpers

2010-06-25 Thread Alexander Graf
When we hook an instruction we need to make sure we don't clobber any of
the registers at that point. So we write them out to scratch space in the
magic page. To make sure we don't fall into a race with another piece of
hooked code, we need to disable interrupts.

To make the later patches and code in general easier readable, let's introduce
a set of defines that save and restore r30, r31 and cr. Let's also define some
helpers to read the lower 32 bits of a 64 bit field on 32 bit systems.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/kernel/kvm_emul.S |   29 +
 1 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kernel/kvm_emul.S b/arch/powerpc/kernel/kvm_emul.S
index c7b9fc9..7da835a 100644
--- a/arch/powerpc/kernel/kvm_emul.S
+++ b/arch/powerpc/kernel/kvm_emul.S
@@ -25,3 +25,32 @@
 
 #define KVM_MAGIC_PAGE (-4096)
 
+#ifdef CONFIG_64BIT
+#define LL64(reg, offs, reg2)  ld  reg, (offs)(reg2)
+#define STL64(reg, offs, reg2) std reg, (offs)(reg2)
+#else
+#define LL64(reg, offs, reg2)  lwz reg, (offs + 4)(reg2)
+#define STL64(reg, offs, reg2) stw reg, (offs + 4)(reg2)
+#endif
+
+#define SCRATCH_SAVE   \
+   /* Enable critical section. We are critical if  \
+  shared-critical == r1 */\
+   STL64(r1, KVM_MAGIC_PAGE + KVM_MAGIC_CRITICAL, 0);  \
+   \
+   /* Save state */\
+   PPC_STL r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH1)(0);  \
+   PPC_STL r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH2)(0);  \
+   mfcrr31;\
+   stw r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH3)(0);
+
+#define SCRATCH_RESTORE
\
+   /* Restore state */ \
+   PPC_LL  r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH1)(0);  \
+   lwz r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH3)(0);  \
+   mtcrr30;\
+   PPC_LL  r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH2)(0);  \
+   \
+   /* Disable critical section. We are critical if \
+  shared-critical == r1 and r2 is always != r1 */ \
+   STL64(r2, KVM_MAGIC_PAGE + KVM_MAGIC_CRITICAL, 0);
-- 
1.6.0.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 23/26] KVM: PPC: PV mtmsrd L=1

2010-06-25 Thread Alexander Graf
The PowerPC ISA has a special instruction for mtmsr that only changes the EE
and RI bits, namely the L=1 form.

Since that one is reasonably often occuring and simple to implement, let's
go with this first. Writing EE=0 is always just a store. Doing EE=1 also
requires us to check for pending interrupts and if necessary exit back to the
hypervisor.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/kernel/kvm.c  |   45 
 arch/powerpc/kernel/kvm_emul.S |   56 
 2 files changed, 101 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index 7e8fe6f..71153d0 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -62,6 +62,7 @@
 #define KVM_INST_MTSPR_DSISR   0x7c1203a6
 
 #define KVM_INST_TLBSYNC   0x7c00046c
+#define KVM_INST_MTMSRD_L1 0x7c010164
 
 static bool kvm_patching_worked = true;
 static char kvm_tmp[1024 * 1024];
@@ -117,6 +118,43 @@ static u32 *kvm_alloc(int len)
return p;
 }
 
+extern u32 kvm_emulate_mtmsrd_branch_offs;
+extern u32 kvm_emulate_mtmsrd_reg_offs;
+extern u32 kvm_emulate_mtmsrd_len;
+extern u32 kvm_emulate_mtmsrd[];
+
+static void kvm_patch_ins_mtmsrd(u32 *inst, u32 rt)
+{
+   u32 *p;
+   int distance_start;
+   int distance_end;
+   ulong next_inst;
+
+   p = kvm_alloc(kvm_emulate_mtmsrd_len * 4);
+   if (!p)
+   return;
+
+   /* Find out where we are and put everything there */
+   distance_start = (ulong)p - (ulong)inst;
+   next_inst = ((ulong)inst + 4);
+   distance_end = next_inst - (ulong)p[kvm_emulate_mtmsrd_branch_offs];
+
+   /* Make sure we only write valid b instructions */
+   if (distance_start  KVM_INST_B_MAX) {
+   kvm_patching_worked = false;
+   return;
+   }
+
+   /* Modify the chunk to fit the invocation */
+   memcpy(p, kvm_emulate_mtmsrd, kvm_emulate_mtmsrd_len * 4);
+   p[kvm_emulate_mtmsrd_branch_offs] |= distance_end  KVM_INST_B_MASK;
+   p[kvm_emulate_mtmsrd_reg_offs] |= rt;
+   flush_icache_range((ulong)p, (ulong)p + kvm_emulate_mtmsrd_len * 4);
+
+   /* Patch the invocation */
+   *inst = KVM_INST_B | (distance_start  KVM_INST_B_MASK);
+}
+
 static void kvm_map_magic_page(void *data)
 {
kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
@@ -190,6 +228,13 @@ static void kvm_check_ins(u32 *inst)
case KVM_INST_TLBSYNC:
kvm_patch_ins_nop(inst);
break;
+
+   /* Rewrites */
+   case KVM_INST_MTMSRD_L1:
+   /* We use r30 and r31 during the hook */
+   if (get_rt(inst_rt)  30)
+   kvm_patch_ins_mtmsrd(inst, inst_rt);
+   break;
}
 
switch (_inst) {
diff --git a/arch/powerpc/kernel/kvm_emul.S b/arch/powerpc/kernel/kvm_emul.S
index 7da835a..25e6683 100644
--- a/arch/powerpc/kernel/kvm_emul.S
+++ b/arch/powerpc/kernel/kvm_emul.S
@@ -54,3 +54,59 @@
/* Disable critical section. We are critical if \
   shared-critical == r1 and r2 is always != r1 */ \
STL64(r2, KVM_MAGIC_PAGE + KVM_MAGIC_CRITICAL, 0);
+
+.global kvm_emulate_mtmsrd
+kvm_emulate_mtmsrd:
+
+   SCRATCH_SAVE
+
+   /* Put MSR  ~(MSR_EE|MSR_RI) in r31 */
+   LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
+   lis r30, (~(MSR_EE | MSR_RI))@h
+   ori r30, r30, (~(MSR_EE | MSR_RI))@l
+   and r31, r31, r30
+
+   /* OR the register's (MSR_EE|MSR_RI) on MSR */
+kvm_emulate_mtmsrd_reg:
+   andi.   r30, r0, (MSR_EE|MSR_RI)
+   or  r31, r31, r30
+
+   /* Put MSR back into magic page */
+   STL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
+
+   /* Check if we have to fetch an interrupt */
+   lwz r31, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0)
+   cmpwi   r31, 0
+   beq+no_check
+
+   /* Check if we may trigger an interrupt */
+   andi.   r30, r30, MSR_EE
+   beq no_check
+
+   SCRATCH_RESTORE
+
+   /* Nag hypervisor */
+   tlbsync
+
+   b   kvm_emulate_mtmsrd_branch
+
+no_check:
+
+   SCRATCH_RESTORE
+
+   /* Go back to caller */
+kvm_emulate_mtmsrd_branch:
+   b   .
+kvm_emulate_mtmsrd_end:
+
+.global kvm_emulate_mtmsrd_branch_offs
+kvm_emulate_mtmsrd_branch_offs:
+   .long (kvm_emulate_mtmsrd_branch - kvm_emulate_mtmsrd) / 4
+
+.global kvm_emulate_mtmsrd_reg_offs
+kvm_emulate_mtmsrd_reg_offs:
+   .long (kvm_emulate_mtmsrd_reg - kvm_emulate_mtmsrd) / 4
+
+.global kvm_emulate_mtmsrd_len
+kvm_emulate_mtmsrd_len:
+   .long (kvm_emulate_mtmsrd_end - kvm_emulate_mtmsrd) / 4
-- 
1.6.0.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 26/26] KVM: PPC: Add Documentation about PV interface

2010-06-25 Thread Alexander Graf
We just introduced a new PV interface that screams for documentation. So here
it is - a shiny new and awesome text file describing the internal works of
the PPC KVM paravirtual interface.

Signed-off-by: Alexander Graf ag...@suse.de
---
 Documentation/kvm/ppc-pv.txt |  164 ++
 1 files changed, 164 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/kvm/ppc-pv.txt

diff --git a/Documentation/kvm/ppc-pv.txt b/Documentation/kvm/ppc-pv.txt
new file mode 100644
index 000..7cbcd51
--- /dev/null
+++ b/Documentation/kvm/ppc-pv.txt
@@ -0,0 +1,164 @@
+The PPC KVM paravirtual interface
+=
+
+The basic execution principle by which KVM on PowerPC works is to run all 
kernel
+space code in PR=1 which is user space. This way we trap all privileged
+instructions and can emulate them accordingly.
+
+Unfortunately that is also the downfall. There are quite some privileged
+instructions that needlessly return us to the hypervisor even though they
+could be handled differently.
+
+This is what the PPC PV interface helps with. It takes privileged instructions
+and transforms them into unprivileged ones with some help from the hypervisor.
+This cuts down virtualization costs by about 50% on some of my benchmarks.
+
+The code for that interface can be found in arch/powerpc/kernel/kvm*
+
+Querying for existence
+==
+
+To find out if we're running on KVM or not, we overlay the PVR register. 
Usually
+the PVR register contains an id that identifies your CPU type. If, however, you
+pass KVM_PVR_PARA in the register that you want the PVR result in, the register
+still contains KVM_PVR_PARA after the mfpvr call.
+
+   LOAD_REG_IMM(r5, KVM_PVR_PARA)
+   mfpvr   r5
+   [r5 still contains KVM_PVR_PARA]
+
+Once determined to run under a PV capable KVM, you can now use hypercalls as
+described below.
+
+PPC hypercalls
+==
+
+The only viable ways to reliably get from guest context to host context are:
+
+   1) Call an invalid instruction
+   2) Call the sc instruction with a parameter to sc
+   3) Call the sc instruction with parameters in GPRs
+
+Method 1 is always a bad idea. Invalid instructions can be replaced later on
+by valid instructions, rendering the interface broken.
+
+Method 2 also has downfalls. If the parameter to sc is != 0 the spec is
+rather unclear if the sc is targeted directly for the hypervisor or the
+supervisor. It would also require that we read the syscall issuing instruction
+every time a syscall is issued, slowing down guest syscalls.
+
+Method 3 is what KVM uses. We pass magic constants (KVM_SC_MAGIC_R3 and
+KVM_SC_MAGIC_R4) in r3 and r4 respectively. If a syscall instruction with these
+magic values arrives from the guest's kernel mode, we take the syscall as a
+hypercall.
+
+The parameters are as follows:
+
+   r3  KVM_SC_MAGIC_R3
+   r4  KVM_SC_MAGIC_R4
+   r5  Hypercall number
+   r6  First parameter
+   r7  Second parameter
+   r8  Third parameter
+   r9  Fourth parameter
+
+Hypercall definitions are shared in generic code, so the same hypercall numbers
+apply for x86 and powerpc alike.
+
+The magic page
+==
+
+To enable communication between the hypervisor and guest there is a new shared
+page that contains parts of supervisor visible register state. The guest can
+map this shared page using the KVM hypercall KVM_HC_PPC_MAP_MAGIC_PAGE.
+
+With this hypercall issued the guest always gets the magic page mapped at the
+desired location in effective and physical address space. For now, we always
+map the page to -4096. This way we can access it using absolute load and store
+functions. The following instruction reads the first field of the magic page:
+
+   ld  rX, -4096(0)
+
+The interface is designed to be extensible should there be need later to add
+additional registers to the magic page. If you add fields to the magic page,
+also define a new hypercall feature to indicate that the host can give you more
+registers. Only if the host supports the additional features, make use of them.
+
+The magic page has the following layout as described in
+arch/powerpc/include/asm/kvm_para.h:
+
+struct kvm_vcpu_arch_shared {
+   __u64 scratch1;
+   __u64 scratch2;
+   __u64 scratch3;
+   __u64 critical; /* Guest may not get interrupts if == r1 */
+   __u64 sprg0;
+   __u64 sprg1;
+   __u64 sprg2;
+   __u64 sprg3;
+   __u64 srr0;
+   __u64 srr1;
+   __u64 dar;
+   __u64 msr;
+   __u32 dsisr;
+   __u32 int_pending;  /* Tells the guest if we have an interrupt */
+};
+
+Additions to the page must only occur at the end. Struct fields are always 32
+bit aligned.
+
+Patched instructions
+
+
+The ld and std instructions are transormed to lwz and stw instructions

[PATCH 18/26] KVM: PPC: KVM PV guest stubs

2010-06-25 Thread Alexander Graf
We will soon start and replace instructions from the text section with
other, paravirtualized versions. To ease the readability of those patches
I split out the generic looping and magic page mapping code out.

This patch still only contains stubs. But at least it loops through the
text section :).

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/kernel/kvm.c |   59 +
 1 files changed, 59 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index 2d8dd73..d873bc6 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -32,3 +32,62 @@
 #define KVM_MAGIC_PAGE (-4096L)
 #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
 
+static bool kvm_patching_worked = true;
+
+static void kvm_map_magic_page(void *data)
+{
+   kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
+  KVM_MAGIC_PAGE,  /* Physical Address */
+  KVM_MAGIC_PAGE); /* Effective Address */
+}
+
+static void kvm_check_ins(u32 *inst)
+{
+   u32 _inst = *inst;
+   u32 inst_no_rt = _inst  ~KVM_MASK_RT;
+   u32 inst_rt = _inst  KVM_MASK_RT;
+
+   switch (inst_no_rt) {
+   }
+
+   switch (_inst) {
+   }
+
+   flush_icache_range((ulong)inst, (ulong)inst + 4);
+}
+
+static void kvm_use_magic_page(void)
+{
+   u32 *p;
+   u32 *start, *end;
+
+   /* Tell the host to map the magic page to -4096 on all CPUs */
+
+   on_each_cpu(kvm_map_magic_page, NULL, 1);
+
+   /* Now loop through all code and find instructions */
+
+   start = (void*)_stext;
+   end = (void*)_etext;
+
+   for (p = start; p  end; p++)
+   kvm_check_ins(p);
+}
+
+static int __init kvm_guest_init(void)
+{
+   char *p;
+
+   if (!kvm_para_available())
+   return 0;
+
+   if (kvm_para_has_feature(KVM_FEATURE_MAGIC_PAGE))
+   kvm_use_magic_page();
+
+   printk(KERN_INFO KVM: Live patching for a fast VM %s\n,
+kvm_patching_worked ? worked : failed);
+
+   return 0;
+}
+
+postcore_initcall(kvm_guest_init);
-- 
1.6.0.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 16/26] KVM: Move kvm_guest_init out of generic code

2010-06-25 Thread Alexander Graf
Currently x86 is the only architecture that uses kvm_guest_init(). With
PowerPC we're getting a second user, but the signature is different there
and we don't need to export it, as it uses the normal kernel init framework.

So let's move the x86 specific definition of that function over to the x86
specfic header file.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/x86/include/asm/kvm_para.h |6 ++
 include/linux/kvm_para.h|5 -
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h
index 05eba5e..7b562b6 100644
--- a/arch/x86/include/asm/kvm_para.h
+++ b/arch/x86/include/asm/kvm_para.h
@@ -158,6 +158,12 @@ static inline unsigned int kvm_arch_para_features(void)
return cpuid_eax(KVM_CPUID_FEATURES);
 }
 
+#ifdef CONFIG_KVM_GUEST
+void __init kvm_guest_init(void);
+#else
+#define kvm_guest_init() do { } while (0)
 #endif
 
+#endif /* __KERNEL__ */
+
 #endif /* _ASM_X86_KVM_PARA_H */
diff --git a/include/linux/kvm_para.h b/include/linux/kvm_para.h
index ac2015a..47a070b 100644
--- a/include/linux/kvm_para.h
+++ b/include/linux/kvm_para.h
@@ -26,11 +26,6 @@
 #include asm/kvm_para.h
 
 #ifdef __KERNEL__
-#ifdef CONFIG_KVM_GUEST
-void __init kvm_guest_init(void);
-#else
-#define kvm_guest_init() do { } while (0)
-#endif
 
 static inline int kvm_para_has_feature(unsigned int feature)
 {
-- 
1.6.0.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 20/26] KVM: PPC: PV tlbsync to nop

2010-06-25 Thread Alexander Graf
With our current MMU scheme we don't need to know about the tlbsync instruction.
So we can just nop it out.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/kernel/kvm.c |   12 
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index b165b20..b091f94 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -61,6 +61,8 @@
 #define KVM_INST_MTSPR_DAR 0x7c1303a6
 #define KVM_INST_MTSPR_DSISR   0x7c1203a6
 
+#define KVM_INST_TLBSYNC   0x7c00046c
+
 static bool kvm_patching_worked = true;
 
 static void kvm_patch_ins_ld(u32 *inst, long addr, u32 rt)
@@ -91,6 +93,11 @@ static void kvm_patch_ins_stw(u32 *inst, long addr, u32 rt)
*inst = KVM_INST_STW | rt | (addr  0xfffc);
 }
 
+static void kvm_patch_ins_nop(u32 *inst)
+{
+   *inst = KVM_INST_NOP;
+}
+
 static void kvm_map_magic_page(void *data)
 {
kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
@@ -159,6 +166,11 @@ static void kvm_check_ins(u32 *inst)
case KVM_INST_MTSPR_DSISR:
kvm_patch_ins_stw(inst, magic_var(dsisr), inst_rt);
break;
+
+   /* Nops */
+   case KVM_INST_TLBSYNC:
+   kvm_patch_ins_nop(inst);
+   break;
}
 
switch (_inst) {
-- 
1.6.0.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 12/26] KVM: PPC: First magic page steps

2010-06-25 Thread Alexander Graf
We will be introducing a method to project the shared page in guest context.
As soon as we're talking about this coupling, the shared page is colled magic
page.

This patch introduces simple defines, so the follow-up patches are easier to
read.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/include/asm/kvm_host.h |2 ++
 include/linux/kvm_para.h|1 +
 2 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_host.h 
b/arch/powerpc/include/asm/kvm_host.h
index e35c1ac..5f8c214 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -285,6 +285,8 @@ struct kvm_vcpu_arch {
u64 dec_jiffies;
unsigned long pending_exceptions;
struct kvm_vcpu_arch_shared *shared;
+   unsigned long magic_page_pa; /* phys addr to map the magic page to */
+   unsigned long magic_page_ea; /* effect. addr to map the magic page to */
 
 #ifdef CONFIG_PPC_BOOK3S
struct kmem_cache *hpte_cache;
diff --git a/include/linux/kvm_para.h b/include/linux/kvm_para.h
index 3b8080e..ac2015a 100644
--- a/include/linux/kvm_para.h
+++ b/include/linux/kvm_para.h
@@ -18,6 +18,7 @@
 #define KVM_HC_VAPIC_POLL_IRQ  1
 #define KVM_HC_MMU_OP  2
 #define KVM_HC_FEATURES3
+#define KVM_HC_PPC_MAP_MAGIC_PAGE  4
 
 /*
  * hypercalls use architecture specific
-- 
1.6.0.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH 24/26] KVM: PPC: PV mtmsrd L=0 and mtmsr

2010-06-25 Thread Alexander Graf
There is also a form of mtmsr where all bits need to be addressed. While the
PPC64 Linux kernel behaves resonably well here, the PPC32 one never uses the
L=1 form but does mtmsr even for simple things like only changing EE.

So we need to hook into that one as well and check for a mask of bits that we
deem safe to change from within guest context.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/kernel/kvm.c  |   51 
 arch/powerpc/kernel/kvm_emul.S |   84 
 2 files changed, 135 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index 71153d0..3557bc8 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -62,7 +62,9 @@
 #define KVM_INST_MTSPR_DSISR   0x7c1203a6
 
 #define KVM_INST_TLBSYNC   0x7c00046c
+#define KVM_INST_MTMSRD_L0 0x7c000164
 #define KVM_INST_MTMSRD_L1 0x7c010164
+#define KVM_INST_MTMSR 0x7c000124
 
 static bool kvm_patching_worked = true;
 static char kvm_tmp[1024 * 1024];
@@ -155,6 +157,49 @@ static void kvm_patch_ins_mtmsrd(u32 *inst, u32 rt)
*inst = KVM_INST_B | (distance_start  KVM_INST_B_MASK);
 }
 
+extern u32 kvm_emulate_mtmsr_branch_offs;
+extern u32 kvm_emulate_mtmsr_reg1_offs;
+extern u32 kvm_emulate_mtmsr_reg2_offs;
+extern u32 kvm_emulate_mtmsr_reg3_offs;
+extern u32 kvm_emulate_mtmsr_orig_ins_offs;
+extern u32 kvm_emulate_mtmsr_len;
+extern u32 kvm_emulate_mtmsr[];
+
+static void kvm_patch_ins_mtmsr(u32 *inst, u32 rt)
+{
+   u32 *p;
+   int distance_start;
+   int distance_end;
+   ulong next_inst;
+
+   p = kvm_alloc(kvm_emulate_mtmsr_len * 4);
+   if (!p)
+   return;
+
+   /* Find out where we are and put everything there */
+   distance_start = (ulong)p - (ulong)inst;
+   next_inst = ((ulong)inst + 4);
+   distance_end = next_inst - (ulong)p[kvm_emulate_mtmsr_branch_offs];
+
+   /* Make sure we only write valid b instructions */
+   if (distance_start  KVM_INST_B_MAX) {
+   kvm_patching_worked = false;
+   return;
+   }
+
+   /* Modify the chunk to fit the invocation */
+   memcpy(p, kvm_emulate_mtmsr, kvm_emulate_mtmsr_len * 4);
+   p[kvm_emulate_mtmsr_branch_offs] |= distance_end  KVM_INST_B_MASK;
+   p[kvm_emulate_mtmsr_reg1_offs] |= rt;
+   p[kvm_emulate_mtmsr_reg2_offs] |= rt;
+   p[kvm_emulate_mtmsr_reg3_offs] |= rt;
+   p[kvm_emulate_mtmsr_orig_ins_offs] = *inst;
+   flush_icache_range((ulong)p, (ulong)p + kvm_emulate_mtmsr_len * 4);
+
+   /* Patch the invocation */
+   *inst = KVM_INST_B | (distance_start  KVM_INST_B_MASK);
+}
+
 static void kvm_map_magic_page(void *data)
 {
kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
@@ -235,6 +280,12 @@ static void kvm_check_ins(u32 *inst)
if (get_rt(inst_rt)  30)
kvm_patch_ins_mtmsrd(inst, inst_rt);
break;
+   case KVM_INST_MTMSR:
+   case KVM_INST_MTMSRD_L0:
+   /* We use r30 and r31 during the hook */
+   if (get_rt(inst_rt)  30)
+   kvm_patch_ins_mtmsr(inst, inst_rt);
+   break;
}
 
switch (_inst) {
diff --git a/arch/powerpc/kernel/kvm_emul.S b/arch/powerpc/kernel/kvm_emul.S
index 25e6683..ccf5a42 100644
--- a/arch/powerpc/kernel/kvm_emul.S
+++ b/arch/powerpc/kernel/kvm_emul.S
@@ -110,3 +110,87 @@ kvm_emulate_mtmsrd_reg_offs:
 .global kvm_emulate_mtmsrd_len
 kvm_emulate_mtmsrd_len:
.long (kvm_emulate_mtmsrd_end - kvm_emulate_mtmsrd) / 4
+
+
+#define MSR_SAFE_BITS (MSR_EE | MSR_CE | MSR_ME | MSR_RI)
+#define MSR_CRITICAL_BITS ~MSR_SAFE_BITS
+
+.global kvm_emulate_mtmsr
+kvm_emulate_mtmsr:
+
+   SCRATCH_SAVE
+
+   /* Fetch old MSR in r31 */
+   LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
+
+   /* Find the changed bits between old and new MSR */
+kvm_emulate_mtmsr_reg1:
+   xor r31, r0, r31
+
+   /* Check if we need to really do mtmsr */
+   LOAD_REG_IMMEDIATE(r30, MSR_CRITICAL_BITS)
+   and.r31, r31, r30
+
+   /* No critical bits changed? Maybe we can stay in the guest. */
+   beq maybe_stay_in_guest
+
+do_mtmsr:
+
+   SCRATCH_RESTORE
+
+   /* Just fire off the mtmsr if it's critical */
+kvm_emulate_mtmsr_orig_ins:
+   mtmsr   r0
+
+   b   kvm_emulate_mtmsr_branch
+
+maybe_stay_in_guest:
+
+   /* Check if we have to fetch an interrupt */
+   lwz r31, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0)
+   cmpwi   r31, 0
+   beq+no_mtmsr
+
+   /* Check if we may trigger an interrupt */
+kvm_emulate_mtmsr_reg2:
+   andi.   r31, r0, MSR_EE
+   beq no_mtmsr
+
+   b   do_mtmsr
+
+no_mtmsr:
+
+   /* Put MSR into magic page because we don't call mtmsr */
+kvm_emulate_mtmsr_reg3:
+   STL64(r0, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
+
+   SCRATCH_RESTORE
+
+   /* Go back to 

[PATCH 25/26] KVM: PPC: PV wrteei

2010-06-25 Thread Alexander Graf
On BookE the preferred way to write the EE bit is the wrteei instruction. It
already encodes the EE bit in the instruction.

So in order to get BookE some speedups as well, let's also PV'nize thati
instruction.

Signed-off-by: Alexander Graf ag...@suse.de
---
 arch/powerpc/kernel/kvm.c  |   50 
 arch/powerpc/kernel/kvm_emul.S |   41 
 2 files changed, 91 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index 3557bc8..85e2163 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -66,6 +66,9 @@
 #define KVM_INST_MTMSRD_L1 0x7c010164
 #define KVM_INST_MTMSR 0x7c000124
 
+#define KVM_INST_WRTEEI_0  0x7c000146
+#define KVM_INST_WRTEEI_1  0x7c008146
+
 static bool kvm_patching_worked = true;
 static char kvm_tmp[1024 * 1024];
 static int kvm_tmp_index;
@@ -200,6 +203,47 @@ static void kvm_patch_ins_mtmsr(u32 *inst, u32 rt)
*inst = KVM_INST_B | (distance_start  KVM_INST_B_MASK);
 }
 
+#ifdef CONFIG_BOOKE
+
+extern u32 kvm_emulate_wrteei_branch_offs;
+extern u32 kvm_emulate_wrteei_ee_offs;
+extern u32 kvm_emulate_wrteei_len;
+extern u32 kvm_emulate_wrteei[];
+
+static void kvm_patch_ins_wrteei(u32 *inst)
+{
+   u32 *p;
+   int distance_start;
+   int distance_end;
+   ulong next_inst;
+
+   p = kvm_alloc(kvm_emulate_wrteei_len * 4);
+   if (!p)
+   return;
+
+   /* Find out where we are and put everything there */
+   distance_start = (ulong)p - (ulong)inst;
+   next_inst = ((ulong)inst + 4);
+   distance_end = next_inst - (ulong)p[kvm_emulate_wrteei_branch_offs];
+
+   /* Make sure we only write valid b instructions */
+   if (distance_start  KVM_INST_B_MAX) {
+   kvm_patching_worked = false;
+   return;
+   }
+
+   /* Modify the chunk to fit the invocation */
+   memcpy(p, kvm_emulate_wrteei, kvm_emulate_wrteei_len * 4);
+   p[kvm_emulate_wrteei_branch_offs] |= distance_end  KVM_INST_B_MASK;
+   p[kvm_emulate_wrteei_ee_offs] |= (*inst  MSR_EE);
+   flush_icache_range((ulong)p, (ulong)p + kvm_emulate_wrteei_len * 4);
+
+   /* Patch the invocation */
+   *inst = KVM_INST_B | (distance_start  KVM_INST_B_MASK);
+}
+
+#endif
+
 static void kvm_map_magic_page(void *data)
 {
kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
@@ -289,6 +333,12 @@ static void kvm_check_ins(u32 *inst)
}
 
switch (_inst) {
+#ifdef CONFIG_BOOKE
+   case KVM_INST_WRTEEI_0:
+   case KVM_INST_WRTEEI_1:
+   kvm_patch_ins_wrteei(inst);
+   break;
+#endif
}
 
flush_icache_range((ulong)inst, (ulong)inst + 4);
diff --git a/arch/powerpc/kernel/kvm_emul.S b/arch/powerpc/kernel/kvm_emul.S
index ccf5a42..b79b9de 100644
--- a/arch/powerpc/kernel/kvm_emul.S
+++ b/arch/powerpc/kernel/kvm_emul.S
@@ -194,3 +194,44 @@ kvm_emulate_mtmsr_orig_ins_offs:
 .global kvm_emulate_mtmsr_len
 kvm_emulate_mtmsr_len:
.long (kvm_emulate_mtmsr_end - kvm_emulate_mtmsr) / 4
+
+
+
+.global kvm_emulate_wrteei
+kvm_emulate_wrteei:
+
+   SCRATCH_SAVE
+
+   /* Fetch old MSR in r31 */
+   LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
+
+   /* Remove MSR_EE from old MSR */
+   li  r30, 0
+   ori r30, r30, MSR_EE
+   andcr31, r31, r30
+
+   /* OR new MSR_EE onto the old MSR */
+kvm_emulate_wrteei_ee:
+   ori r31, r31, 0
+
+   /* Write new MSR value back */
+   STL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
+
+   SCRATCH_RESTORE
+
+   /* Go back to caller */
+kvm_emulate_wrteei_branch:
+   b   .
+kvm_emulate_wrteei_end:
+
+.global kvm_emulate_wrteei_branch_offs
+kvm_emulate_wrteei_branch_offs:
+   .long (kvm_emulate_wrteei_branch - kvm_emulate_wrteei) / 4
+
+.global kvm_emulate_wrteei_ee_offs
+kvm_emulate_wrteei_ee_offs:
+   .long (kvm_emulate_wrteei_ee - kvm_emulate_wrteei) / 4
+
+.global kvm_emulate_wrteei_len
+kvm_emulate_wrteei_len:
+   .long (kvm_emulate_wrteei_end - kvm_emulate_wrteei) / 4
-- 
1.6.0.2

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


RE: JFFS2 corruption when mounting filesystem with filenames oflength 7

2010-06-25 Thread Steve Deiters
 -Original Message-
 From: linux-mtd-boun...@lists.infradead.org 
 [mailto:linux-mtd-boun...@lists.infradead.org] On Behalf Of 
 Steve Deiters
 Sent: Thursday, June 24, 2010 3:02 PM
 To: linux-...@lists.infradead.org
 Subject: RE: JFFS2 corruption when mounting filesystem with 
 filenames oflength 7
 
  -Original Message-
  From: linux-mtd-boun...@lists.infradead.org
  [mailto:linux-mtd-boun...@lists.infradead.org] On Behalf Of Steve 
  Deiters
  Sent: Wednesday, June 23, 2010 5:42 PM
  To: linux-...@lists.infradead.org
  Subject: RE: JFFS2 corruption when mounting filesystem with 
 filenames 
  oflength  7
  
   -Original Message-
   From: linux-mtd-boun...@lists.infradead.org
   [mailto:linux-mtd-boun...@lists.infradead.org] On Behalf Of Steve 
   Deiters
   Sent: Wednesday, June 23, 2010 5:21 PM
   To: linux-...@lists.infradead.org
   Subject: JFFS2 corruption when mounting filesystem with
  filenames of
   length  7
   
   I found an archived post which seems to be identical to my issue.
   However, this is quite old and there never seemed to be any 
   resolution.
   
   http://www.infradead.org/pipermail/linux-mtd/2006-September/01
   6491.html
   
   If I mount a filesystem that has filenames greater than 7
  characters
   in length, the files are corrupted when I mount.
   In my case, I am making a
   JFFS2 image with mkfs.jffs2 and flashing it in with u-boot.  
   However, I have attached a workflow where I erase the Flash
  and create
   a new filesystem completely within Linux and it gives the same 
   behavior.  I can list the files with the 'ls'
   command from within u-boot.  If I mount from within 
 Linux, and then 
   reboot into u-boot, it will not display any files that had
  a filename
   greater than 7 characters.
   
   I enabled the MTD debug verbosity at level 2 for the
  attached example
   session.
   
   I am running on a custom board with a MPC5121 and Linux 2.6.33.4.
   
   Thanks in advance for any help.
  
  
  Sorry for the jumbled mess.  Looks like the line endings are messed 
  up.
  Trying again.  I also provided this as an attachment in 
 case it gets 
  messed up again.
 
 Once again sorry for the mess.
 
 I tried this again with the DENX-v2.6.34 tag in the DENX git 
 repository (git://git.denx.de/linux-2.6-denx.git).  The only 
 modification I made was to add my dts file.  I still get the 
 same issue I had before.
 
 I've attached my kernel config if that gives any clues.
 
 Are there any thoughts on what may be causing this?
 
 Thanks.


I think there may be something weird going on with the memcpy in my
build.  If I use the following patch I no longer get errors when I mount
the filesystem.  All I did was replace the memcpy with a loop.

I'm not sure what's special about this particular use of memcpy.  I
can't believe that things would be working as well as they do if memcpy
was broken in general.

This is on a PowerPC 32 bit build for a MPC5121.  I am using a GCC 4.1.2
to compile.  Is anyone aware of any issues with memcpy in this
configuration?

Thanks.

---

diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 46f870d..673caa2 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -1038,7 +1038,10 @@ static int jffs2_scan_dirent_node(struct
jffs2_sb_info *c, struct jffs2_eraseblo
if (!fd) {
return -ENOMEM;
}
-   memcpy(fd-name, rd-name, checkedlen);
+   int i;
+   for(i = 0; i  checkedlen; i++)
+   ((unsigned char*)fd-name)[i] = ((const unsigned
char*)rd-name)[i];
+
fd-name[checkedlen] = 0;
 
crc = crc32(0, fd-name, rd-nsize);
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH] kvm/ppc: fix build warning

2010-06-25 Thread Denis Kirjanov

On 06/25/2010 12:42 AM, Alexander Graf wrote:


On 24.06.2010, at 21:44, Denis Kirjanov wrote:


Fix build warning:
arch/powerpc/kvm/book3s_64_mmu.c: In function 
'kvmppc_mmu_book3s_64_esid_to_vsid':
arch/powerpc/kvm/book3s_64_mmu.c:446: warning: 'slb' may be used uninitialized 
in this function
Signed-off-by: Denis Kirjanovdkirja...@kernel.org


Are you sure this isn't a broken compiler? I don't see where it could be used 
uninitialized.


I'm using gcc version 4.3.4 (Gentoo 4.3.4 p1.1, pie-10.1.5)
slb pointer initialized inside conditional branch
and used later in the case case MSR_DR|MSR_IR

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH] kvm/ppc: fix build warning

2010-06-25 Thread Denis Kirjanov

On 06/25/2010 01:02 PM, Denis Kirjanov wrote:

On 06/25/2010 12:42 AM, Alexander Graf wrote:


On 24.06.2010, at 21:44, Denis Kirjanov wrote:


Fix build warning:
arch/powerpc/kvm/book3s_64_mmu.c: In function
'kvmppc_mmu_book3s_64_esid_to_vsid':
arch/powerpc/kvm/book3s_64_mmu.c:446: warning: 'slb' may be used
uninitialized in this function
Signed-off-by: Denis Kirjanovdkirja...@kernel.org


Are you sure this isn't a broken compiler? I don't see where it could
be used uninitialized.


I'm using gcc version 4.3.4 (Gentoo 4.3.4 p1.1, pie-10.1.5)
slb pointer initialized inside conditional branch
and used later in the case case MSR_DR|MSR_IR


This is based on linux-next tree (-next-20100623)
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev