[PATCH 01/10] Add dbsr in kvm_vcpu_arch
Kernel for E500 need clear dbsr when startup. So add dbsr register in kvm_vcpu_arch for BOOKE. Signed-off-by: Liu Yu yu@freescale.com --- arch/powerpc/include/asm/kvm_host.h |1 + arch/powerpc/kvm/booke_emulate.c|4 2 files changed, 5 insertions(+), 0 deletions(-) diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 850c41e..63962fa 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -163,6 +163,7 @@ struct kvm_vcpu_arch { u32 ccr1; u32 dbcr0; u32 dbcr1; + u32 dbsr; #ifdef CONFIG_KVM_EXIT_TIMING struct kvmppc_exit_timing timing_exit; diff --git a/arch/powerpc/kvm/booke_emulate.c b/arch/powerpc/kvm/booke_emulate.c index 2fe9429..aaa304f 100644 --- a/arch/powerpc/kvm/booke_emulate.c +++ b/arch/powerpc/kvm/booke_emulate.c @@ -111,6 +111,8 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) vcpu-arch.dbcr0 = vcpu-arch.gpr[rs]; break; case SPRN_DBCR1: vcpu-arch.dbcr1 = vcpu-arch.gpr[rs]; break; + case SPRN_DBSR: + vcpu-arch.dbsr = ~vcpu-arch.gpr[rs]; break; case SPRN_TSR: vcpu-arch.tsr = ~vcpu-arch.gpr[rs]; break; case SPRN_TCR: @@ -204,6 +206,8 @@ int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt) vcpu-arch.gpr[rt] = vcpu-arch.dbcr0; break; case SPRN_DBCR1: vcpu-arch.gpr[rt] = vcpu-arch.dbcr1; break; + case SPRN_DBSR: + vcpu-arch.gpr[rt] = vcpu-arch.dbsr; break; case SPRN_IVOR0: vcpu-arch.gpr[rt] = vcpu-arch.ivor[BOOKE_IRQPRIO_CRITICAL]; -- 1.5.4 -- To unsubscribe from this list: send the line unsubscribe kvm-ppc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 03/10] Put iccci into 44x specific code
E500 deosn't support this instruction. Signed-off-by: Liu Yu yu@freescale.com --- arch/powerpc/kvm/booke_interrupts.S |2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S index 084ebcd..4679ec2 100644 --- a/arch/powerpc/kvm/booke_interrupts.S +++ b/arch/powerpc/kvm/booke_interrupts.S @@ -347,7 +347,9 @@ lightweight_exit: lwz r3, VCPU_SHADOW_PID(r4) mtspr SPRN_PID, r3 +#ifdef CONFIG_44x iccci 0, 0 /* XXX hack */ +#endif /* Load some guest volatiles. */ lwz r0, VCPU_GPR(r0)(r4) -- 1.5.4 -- To unsubscribe from this list: send the line unsubscribe kvm-ppc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 04/10] E500 core-specific code
Signed-off-by: Liu Yu yu@freescale.com --- arch/powerpc/include/asm/kvm_e500.h | 67 +++ arch/powerpc/kvm/e500.c | 151 +++ 2 files changed, 218 insertions(+), 0 deletions(-) create mode 100644 arch/powerpc/include/asm/kvm_e500.h create mode 100644 arch/powerpc/kvm/e500.c diff --git a/arch/powerpc/include/asm/kvm_e500.h b/arch/powerpc/include/asm/kvm_e500.h new file mode 100644 index 000..9d497ce --- /dev/null +++ b/arch/powerpc/include/asm/kvm_e500.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved. + * + * Author: Yu Liu, yu@freescale.com + * + * Description: + * This file is derived from arch/powerpc/include/asm/kvm_44x.h, + * by Hollis Blanchard holl...@us.ibm.com. + * + * 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. + */ + +#ifndef __ASM_KVM_E500_H__ +#define __ASM_KVM_E500_H__ + +#include linux/kvm_host.h + +#define BOOKE_INTERRUPT_SIZE 36 + +#define E500_PID_NUM 3 +#define E500_TLB_NUM 2 + +struct tlbe{ + u32 mas1; + u32 mas2; + u32 mas3; + u32 mas7; +}; + +struct kvmppc_vcpu_e500 { + /* Unmodified copy of the guest's TLB. */ + struct tlbe *guest_tlb[E500_TLB_NUM]; + /* TLB that's actually used when the guest is running. */ + struct tlbe *shadow_tlb[E500_TLB_NUM]; + /* Pages which are referenced in the shadow TLB. */ + struct page **shadow_pages[E500_TLB_NUM]; + + unsigned int guest_tlb_size[E500_TLB_NUM]; + unsigned int shadow_tlb_size[E500_TLB_NUM]; + unsigned int guest_tlb_nv[E500_TLB_NUM]; + + u32 host_pid[E500_PID_NUM]; + u32 pid[E500_PID_NUM]; + + u32 mas0; + u32 mas1; + u32 mas2; + u32 mas3; + u32 mas4; + u32 mas5; + u32 mas6; + u32 mas7; + u32 l1csr1; + u32 hid0; + u32 hid1; + + struct kvm_vcpu vcpu; +}; + +static inline struct kvmppc_vcpu_e500 *to_e500(struct kvm_vcpu *vcpu) +{ + return container_of(vcpu, struct kvmppc_vcpu_e500, vcpu); +} + +#endif /* __ASM_KVM_E500_H__ */ diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c new file mode 100644 index 000..7992da4 --- /dev/null +++ b/arch/powerpc/kvm/e500.c @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved. + * + * Author: Yu Liu, yu@freescale.com + * + * Description: + * This file is derived from arch/powerpc/kvm/44x.c, + * by Hollis Blanchard holl...@us.ibm.com. + * + * 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. + */ + +#include linux/kvm_host.h +#include linux/err.h + +#include asm/reg.h +#include asm/cputable.h +#include asm/tlbflush.h +#include asm/kvm_e500.h +#include asm/kvm_ppc.h + +#include e500_tlb.h + +void kvmppc_core_load_host_debugstate(struct kvm_vcpu *vcpu) +{ +} + +void kvmppc_core_load_guest_debugstate(struct kvm_vcpu *vcpu) +{ +} + +void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) +{ + kvmppc_e500_tlb_load(vcpu, cpu); +} + +void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) +{ + kvmppc_e500_tlb_put(vcpu); +} + +int kvmppc_core_check_processor_compat(void) +{ + int r; + + if (strcmp(cur_cpu_spec-cpu_name, e500v2) == 0) + r = 0; + else + r = -ENOTSUPP; + + return r; +} + +int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu) +{ + struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); + + kvmppc_e500_tlb_setup(vcpu_e500); + + /* Use the same core vertion as host's */ + vcpu-arch.pvr = mfspr(SPRN_PVR); + + return 0; +} + +/* 'linear_address' is actually an encoding of AS|PID|EADDR . */ +int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu, + struct kvm_translation *tr) +{ + int index; + gva_t eaddr; + u8 pid; + u8 as; + + eaddr = tr-linear_address; + pid = (tr-linear_address 32) 0xff; + as = (tr-linear_address 40) 0x1; + + index = kvmppc_e500_tlb_search(vcpu, eaddr, pid, as); + if (index 0) { + tr-valid = 0; + return 0; + } + + tr-physical_address = kvmppc_mmu_xlate(vcpu, index, eaddr); + /* XXX what does writeable and usermode even mean? */ + tr-valid = 1; + + return 0; +} + +struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) +{ + struct kvmppc_vcpu_e500 *vcpu_e500; + struct kvm_vcpu *vcpu; + int err; + + vcpu_e500 = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); + if (!vcpu_e500) { + err = -ENOMEM; + goto out; + } + + vcpu = vcpu_e500-vcpu; + err =
[PATCH 06/10] E500 TLB emulation
Signed-off-by: Liu Yu yu@freescale.com --- arch/powerpc/kvm/e500_tlb.c | 737 +++ arch/powerpc/kvm/e500_tlb.h | 184 +++ 2 files changed, 921 insertions(+), 0 deletions(-) create mode 100644 arch/powerpc/kvm/e500_tlb.c create mode 100644 arch/powerpc/kvm/e500_tlb.h diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c new file mode 100644 index 000..6a50340 --- /dev/null +++ b/arch/powerpc/kvm/e500_tlb.c @@ -0,0 +1,737 @@ +/* + * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved. + * + * Author: Yu Liu, yu@freescale.com + * + * Description: + * This file is based on arch/powerpc/kvm/44x_tlb.c, + * by Hollis Blanchard holl...@us.ibm.com. + * + * 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. + */ + +#include linux/types.h +#include linux/string.h +#include linux/kvm.h +#include linux/kvm_host.h +#include linux/highmem.h +#include asm/kvm_ppc.h +#include asm/kvm_e500.h + +#include e500_tlb.h + +#define to_htlb1_esel(esel) (tlb1_entry_num - (esel) - 1) + +static unsigned int tlb1_entry_num; + +void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu) +{ + struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); + struct tlbe *tlbe; + int i, tlbsel; + + printk(| %8s | %8s | %8s | %8s | %8s |\n, + nr, mas1, mas2, mas3, mas7); + + for (tlbsel = 0; tlbsel 2; tlbsel++) { + printk(Guest TLB%d:\n, tlbsel); + for (i = 0; i vcpu_e500-guest_tlb_size[tlbsel]; i++) { + tlbe = vcpu_e500-guest_tlb[tlbsel][i]; + if (tlbe-mas1 MAS1_VALID) + printk( G[%d][%3d] | %08X | %08X | %08X | %08X |\n, + tlbsel, i, tlbe-mas1, tlbe-mas2, + tlbe-mas3, tlbe-mas7); + } + } + + for (tlbsel = 0; tlbsel 2; tlbsel++) { + printk(Shadow TLB%d:\n, tlbsel); + for (i = 0; i vcpu_e500-shadow_tlb_size[tlbsel]; i++) { + tlbe = vcpu_e500-shadow_tlb[tlbsel][i]; + if (tlbe-mas1 MAS1_VALID) + printk( S[%d][%3d] | %08X | %08X | %08X | %08X |\n, + tlbsel, i, tlbe-mas1, tlbe-mas2, + tlbe-mas3, tlbe-mas7); + } + } +} + +static inline unsigned int tlb0_get_next_victim( + struct kvmppc_vcpu_e500 *vcpu_e500) +{ + unsigned int victim; + + victim = vcpu_e500-guest_tlb_nv[0]++; + if (unlikely(vcpu_e500-guest_tlb_nv[0] = KVM_E500_TLB0_WAY_NUM)) + vcpu_e500-guest_tlb_nv[0] = 0; + + return victim; +} + +static inline unsigned int tlb1_max_shadow_size(void) +{ + return tlb1_entry_num - tlbcam_index; +} + +static inline int tlbe_is_writable(struct tlbe *tlbe) +{ + return tlbe-mas3 (MAS3_SW|MAS3_UW); +} + +static inline u32 e500_shadow_mas3_attrib(u32 mas3, int usermode) +{ + /* Mask off reserved bits. */ + mas3 = MAS3_ATTRIB_MASK; + + if (!usermode) { + /* Guest is in supervisor mode, +* so we need to translate guest +* supervisor permissions into user permissions. */ + mas3 = ~E500_TLB_USER_PERM_MASK; + mas3 |= (mas3 E500_TLB_SUPER_PERM_MASK) 1; + } + + return mas3 | E500_TLB_SUPER_PERM_MASK; +} + +static inline u32 e500_shadow_mas2_attrib(u32 mas2, int usermode) +{ + return mas2 MAS2_ATTRIB_MASK; +} + +/* + * writing shadow tlb entry to host TLB + */ +static inline void __write_host_tlbe(struct tlbe *stlbe) +{ + mtspr(SPRN_MAS1, stlbe-mas1); + mtspr(SPRN_MAS2, stlbe-mas2); + mtspr(SPRN_MAS3, stlbe-mas3); + mtspr(SPRN_MAS7, stlbe-mas7); + __asm__ __volatile__ (tlbwe\n : : ); +} + +static inline void write_host_tlbe(struct kvmppc_vcpu_e500 *vcpu_e500, + int tlbsel, int esel) +{ + struct tlbe *stlbe = vcpu_e500-shadow_tlb[tlbsel][esel]; + + local_irq_disable(); + if (tlbsel == 0) { + __write_host_tlbe(stlbe); + } else { + unsigned register mas0; + + mas0 = mfspr(SPRN_MAS0); + + mtspr(SPRN_MAS0, MAS0_TLBSEL(1) | MAS0_ESEL(to_htlb1_esel(esel))); + __write_host_tlbe(stlbe); + + mtspr(SPRN_MAS0, mas0); + } + local_irq_enable(); +} + +void kvmppc_e500_tlb_load(struct kvm_vcpu *vcpu, int cpu) +{ + struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); + int i; + unsigned register mas0; + + /* Load all valid TLB1 entries to reduce guest tlb miss fault */ + local_irq_disable(); + mas0 = mfspr(SPRN_MAS0); + for (i = 0; i
[PATCH 09/10] Fix IRQ priority search confusion
Although BOOKE_MAX_INTERRUPT has the right value, the meaning is not match. Signed-off-by: Liu Yu yu@freescale.com --- arch/powerpc/kvm/booke.c |2 +- arch/powerpc/kvm/booke.h |1 + 2 files changed, 2 insertions(+), 1 deletions(-) diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 933c406..f192fbe 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c @@ -163,7 +163,7 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu) unsigned int priority; priority = __ffs(*pending); - while (priority = BOOKE_MAX_INTERRUPT) { + while (priority = BOOKE_IRQPRIO_MAX) { if (kvmppc_booke_irqprio_deliver(vcpu, priority)) break; diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h index 311fdbc..7ceeb3e 100644 --- a/arch/powerpc/kvm/booke.h +++ b/arch/powerpc/kvm/booke.h @@ -42,6 +42,7 @@ #define BOOKE_IRQPRIO_EXTERNAL 13 #define BOOKE_IRQPRIO_FIT 14 #define BOOKE_IRQPRIO_DECREMENTER 15 +#define BOOKE_IRQPRIO_MAX 15 /* Helper function for full MSR writes. No need to call this if only EE is * changing. */ -- 1.5.4 -- To unsubscribe from this list: send the line unsubscribe kvm-ppc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 10/10] Add extra E500 exceptions
Signed-off-by: Liu Yu yu@freescale.com --- arch/powerpc/include/asm/kvm_asm.h |7 ++- arch/powerpc/include/asm/kvm_host.h |2 +- arch/powerpc/kvm/booke.c| 18 ++ arch/powerpc/kvm/booke.h| 30 ++ arch/powerpc/kvm/booke_interrupts.S |3 +++ arch/powerpc/kvm/e500.c | 20 +++- arch/powerpc/kvm/e500_emulate.c | 27 +++ 7 files changed, 92 insertions(+), 15 deletions(-) diff --git a/arch/powerpc/include/asm/kvm_asm.h b/arch/powerpc/include/asm/kvm_asm.h index 2197764..56bfae5 100644 --- a/arch/powerpc/include/asm/kvm_asm.h +++ b/arch/powerpc/include/asm/kvm_asm.h @@ -42,7 +42,12 @@ #define BOOKE_INTERRUPT_DTLB_MISS 13 #define BOOKE_INTERRUPT_ITLB_MISS 14 #define BOOKE_INTERRUPT_DEBUG 15 -#define BOOKE_MAX_INTERRUPT 15 + +/* E500 */ +#define BOOKE_INTERRUPT_SPE_UNAVAIL 32 +#define BOOKE_INTERRUPT_SPE_FP_DATA 33 +#define BOOKE_INTERRUPT_SPE_FP_ROUND 34 +#define BOOKE_INTERRUPT_PERFORMANCE_MONITOR 35 #define RESUME_FLAG_NV (10) /* Reload guest nonvolatile state? */ #define RESUME_FLAG_HOST(11) /* Resume host? */ diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 63962fa..5e22681 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -150,7 +150,7 @@ struct kvm_vcpu_arch { u32 tbu; u32 tcr; u32 tsr; - u32 ivor[16]; + u32 ivor[64]; ulong ivpr; u32 pir; diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index f192fbe..642e420 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c @@ -118,6 +118,9 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu, case BOOKE_IRQPRIO_DATA_STORAGE: case BOOKE_IRQPRIO_INST_STORAGE: case BOOKE_IRQPRIO_FP_UNAVAIL: + case BOOKE_IRQPRIO_SPE_UNAVAIL: + case BOOKE_IRQPRIO_SPE_FP_DATA: + case BOOKE_IRQPRIO_SPE_FP_ROUND: case BOOKE_IRQPRIO_AP_UNAVAIL: case BOOKE_IRQPRIO_ALIGNMENT: allowed = 1; @@ -261,6 +264,21 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, r = RESUME_GUEST; break; + case BOOKE_INTERRUPT_SPE_UNAVAIL: + kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_UNAVAIL); + r = RESUME_GUEST; + break; + + case BOOKE_INTERRUPT_SPE_FP_DATA: + kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_FP_DATA); + r = RESUME_GUEST; + break; + + case BOOKE_INTERRUPT_SPE_FP_ROUND: + kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_FP_ROUND); + r = RESUME_GUEST; + break; + case BOOKE_INTERRUPT_DATA_STORAGE: vcpu-arch.dear = vcpu-arch.fault_dear; vcpu-arch.esr = vcpu-arch.fault_esr; diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h index 7ceeb3e..d59bcca 100644 --- a/arch/powerpc/kvm/booke.h +++ b/arch/powerpc/kvm/booke.h @@ -31,18 +31,24 @@ #define BOOKE_IRQPRIO_ALIGNMENT 2 #define BOOKE_IRQPRIO_PROGRAM 3 #define BOOKE_IRQPRIO_FP_UNAVAIL 4 -#define BOOKE_IRQPRIO_SYSCALL 5 -#define BOOKE_IRQPRIO_AP_UNAVAIL 6 -#define BOOKE_IRQPRIO_DTLB_MISS 7 -#define BOOKE_IRQPRIO_ITLB_MISS 8 -#define BOOKE_IRQPRIO_MACHINE_CHECK 9 -#define BOOKE_IRQPRIO_DEBUG 10 -#define BOOKE_IRQPRIO_CRITICAL 11 -#define BOOKE_IRQPRIO_WATCHDOG 12 -#define BOOKE_IRQPRIO_EXTERNAL 13 -#define BOOKE_IRQPRIO_FIT 14 -#define BOOKE_IRQPRIO_DECREMENTER 15 -#define BOOKE_IRQPRIO_MAX 15 +#define BOOKE_IRQPRIO_SPE_UNAVAIL 5 +#define BOOKE_IRQPRIO_SPE_FP_DATA 6 +#define BOOKE_IRQPRIO_SPE_FP_ROUND 7 +#define BOOKE_IRQPRIO_SYSCALL 8 +#define BOOKE_IRQPRIO_AP_UNAVAIL 9 +#define BOOKE_IRQPRIO_DTLB_MISS 10 +#define BOOKE_IRQPRIO_ITLB_MISS 11 +#define BOOKE_IRQPRIO_MACHINE_CHECK 12 +#define BOOKE_IRQPRIO_DEBUG 13 +#define BOOKE_IRQPRIO_CRITICAL 14 +#define BOOKE_IRQPRIO_WATCHDOG 15 +#define BOOKE_IRQPRIO_EXTERNAL 16 +#define BOOKE_IRQPRIO_FIT 17 +#define BOOKE_IRQPRIO_DECREMENTER 18 +#define BOOKE_IRQPRIO_PERFORMANCE_MONITOR 19 +#define BOOKE_IRQPRIO_MAX 19 + +extern unsigned long kvmppc_booke_handlers; /* Helper function for full MSR writes. No need to call this if only EE is * changing. */ diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S index 4679ec2..d0c6f84 100644 --- a/arch/powerpc/kvm/booke_interrupts.S +++ b/arch/powerpc/kvm/booke_interrupts.S @@ -86,6 +86,9 @@ KVM_HANDLER BOOKE_INTERRUPT_WATCHDOG KVM_HANDLER BOOKE_INTERRUPT_DTLB_MISS KVM_HANDLER BOOKE_INTERRUPT_ITLB_MISS KVM_HANDLER BOOKE_INTERRUPT_DEBUG +KVM_HANDLER BOOKE_INTERRUPT_SPE_UNAVAIL +KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_DATA +KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_ROUND _GLOBAL(kvmppc_handler_len) .long kvmppc_handler_1 - kvmppc_handler_0 diff
[PATCH 08/10] Enable E500 in KVM
Signed-off-by: Liu Yu yu@freescale.com --- arch/powerpc/kvm/Kconfig | 13 + arch/powerpc/kvm/Makefile |9 + 2 files changed, 22 insertions(+), 0 deletions(-) diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig index 6dbdc48..1465705 100644 --- a/arch/powerpc/kvm/Kconfig +++ b/arch/powerpc/kvm/Kconfig @@ -43,6 +43,19 @@ config KVM_EXIT_TIMING If unsure, say N. +config KVM_E500 + bool KVM support for PowerPC E500 processors + depends on EXPERIMENTAL E500 + select KVM + ---help--- + Support running unmodified E500 guest kernels in virtual machines on + E500 host processors. + + This module provides access to the hardware capabilities through + a character device node named /dev/kvm. + + If unsure, say N. + config KVM_TRACE bool KVM trace support depends on KVM MARKERS SYSFS diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile index 3ef5261..4b2df66 100644 --- a/arch/powerpc/kvm/Makefile +++ b/arch/powerpc/kvm/Makefile @@ -22,3 +22,12 @@ kvm-440-objs := \ 44x_tlb.o \ 44x_emulate.o obj-$(CONFIG_KVM_440) += kvm-440.o + +kvm-e500-objs := \ + booke.o \ + booke_emulate.o \ + booke_interrupts.o \ + e500.o \ + e500_tlb.o \ + e500_emulate.o +obj-$(CONFIG_KVM_E500) += kvm-e500.o -- 1.5.4 -- To unsubscribe from this list: send the line unsubscribe kvm-ppc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 07/10] Add kvmppc_mmu_dtlb/itlb_miss for booke
On Thu, 2008-12-18 at 20:22 +0800, Liu Yu wrote: When itlb or dtlb miss happens, E500 needs to update some mmu registers. So that the auto-load mechanism can work on E500 when write a tlb entry. Signed-off-by: Liu Yu yu@freescale.com --- arch/powerpc/include/asm/kvm_ppc.h |2 ++ arch/powerpc/kvm/44x_tlb.c |8 arch/powerpc/kvm/booke.c |2 ++ 3 files changed, 12 insertions(+), 0 deletions(-) diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index f4b041b..82547c8 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h @@ -63,6 +63,8 @@ extern int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr); extern int kvmppc_mmu_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr); extern gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int gtlb_index, gva_t eaddr); +extern void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu); +extern void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu); extern struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id); diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c index e67b731..4a16f47 100644 --- a/arch/powerpc/kvm/44x_tlb.c +++ b/arch/powerpc/kvm/44x_tlb.c @@ -232,6 +232,14 @@ int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr) return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu-arch.pid, as); } +void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu) +{ +} + +void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu) +{ +} + static void kvmppc_44x_shadow_release(struct kvmppc_vcpu_44x *vcpu_44x, unsigned int stlb_index) { diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index a73b395..933c406 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c @@ -295,6 +295,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DTLB_MISS); vcpu-arch.dear = vcpu-arch.fault_dear; vcpu-arch.esr = vcpu-arch.fault_esr; + kvmppc_mmu_dtlb_miss(vcpu); kvmppc_account_exit(vcpu, DTLB_REAL_MISS_EXITS); r = RESUME_GUEST; break; @@ -337,6 +338,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, if (gtlb_index 0) { /* The guest didn't have a mapping for it. */ kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ITLB_MISS); + kvmppc_mmu_itlb_miss(vcpu); kvmppc_account_exit(vcpu, ITLB_REAL_MISS_EXITS); break; } I don't think you've supplied an implementation of these hooks for e500. Does it build with this patch series applied? -- Hollis Blanchard IBM Linux Technology Center -- To unsubscribe from this list: send the line unsubscribe kvm-ppc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH 07/10] Add kvmppc_mmu_dtlb/itlb_miss for booke
-Original Message- From: kvm-ppc-ow...@vger.kernel.org [mailto:kvm-ppc-ow...@vger.kernel.org] On Behalf Of Hollis Blanchard Sent: Friday, December 19, 2008 7:49 AM To: Liu Yu-B13201 Cc: kvm-ppc@vger.kernel.org Subject: Re: [PATCH 07/10] Add kvmppc_mmu_dtlb/itlb_miss for booke On Thu, 2008-12-18 at 20:22 +0800, Liu Yu wrote: When itlb or dtlb miss happens, E500 needs to update some mmu registers. So that the auto-load mechanism can work on E500 when write a tlb entry. Signed-off-by: Liu Yu yu@freescale.com --- arch/powerpc/include/asm/kvm_ppc.h |2 ++ arch/powerpc/kvm/44x_tlb.c |8 arch/powerpc/kvm/booke.c |2 ++ 3 files changed, 12 insertions(+), 0 deletions(-) diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index f4b041b..82547c8 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h @@ -63,6 +63,8 @@ extern int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr); extern int kvmppc_mmu_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr); extern gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int gtlb_index, gva_t eaddr); +extern void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu); +extern void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu); extern struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id); diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c index e67b731..4a16f47 100644 --- a/arch/powerpc/kvm/44x_tlb.c +++ b/arch/powerpc/kvm/44x_tlb.c @@ -232,6 +232,14 @@ int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr) return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu-arch.pid, as); } +void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu) +{ +} + +void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu) +{ +} + static void kvmppc_44x_shadow_release(struct kvmppc_vcpu_44x *vcpu_44x, unsigned int stlb_index) { diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index a73b395..933c406 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c @@ -295,6 +295,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DTLB_MISS); vcpu-arch.dear = vcpu-arch.fault_dear; vcpu-arch.esr = vcpu-arch.fault_esr; + kvmppc_mmu_dtlb_miss(vcpu); kvmppc_account_exit(vcpu, DTLB_REAL_MISS_EXITS); r = RESUME_GUEST; break; @@ -337,6 +338,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, if (gtlb_index 0) { /* The guest didn't have a mapping for it. */ kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ITLB_MISS); + kvmppc_mmu_itlb_miss(vcpu); kvmppc_account_exit(vcpu, ITLB_REAL_MISS_EXITS); break; } I don't think you've supplied an implementation of these hooks for e500. Does it build with this patch series applied? Sorry, these hooks for e500 exists in [PATCH 06/10] E500 TLB emulation. -- +static inline void kvmppc_e500_deliver_tlb_miss(struct kvm_vcpu *vcpu, + unsigned int eaddr, int as) +{ + struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); + unsigned int victim, pidsel, tsized; + int tlbsel; + + /* since we only have two TLBs, only lower bit is used. */ + tlbsel = (vcpu_e500-mas4 28) 0x1; + victim = (tlbsel == 0) ? tlb0_get_next_victim(vcpu_e500) : 0; + pidsel = (vcpu_e500-mas4 16) 0xf; + tsized = (vcpu_e500-mas4 8) 0xf; + + vcpu_e500-mas0 = MAS0_TLBSEL(tlbsel) | MAS0_ESEL(victim) + | MAS0_NV(vcpu_e500-guest_tlb_nv[tlbsel]); + vcpu_e500-mas1 = MAS1_VALID | (as ? MAS1_TS : 0) + | MAS1_TID(vcpu_e500-pid[pidsel]) + | MAS1_TSIZE(tsized); + vcpu_e500-mas2 = (eaddr MAS2_EPN) + | (vcpu_e500-mas4 MAS2_ATTRIB_MASK); + vcpu_e500-mas3 = MAS3_U0 | MAS3_U1 | MAS3_U2 | MAS3_U3; + vcpu_e500-mas6 = (vcpu_e500-mas6 MAS6_SPID1) + | (get_cur_pid(vcpu) 16) + | (as ? MAS6_SAS : 0); + vcpu_e500-mas7 = 0; +} +void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu) +{ + unsigned int as = !!(vcpu-arch.msr MSR_IS); + + kvmppc_e500_deliver_tlb_miss(vcpu, vcpu-arch.pc, as); +} + +void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu) +{ + unsigned int as = !!(vcpu-arch.msr MSR_DS); + + kvmppc_e500_deliver_tlb_miss(vcpu, vcpu-arch.fault_dear, as); +} -- To unsubscribe from this list: send the line unsubscribe kvm-ppc in the body of a message
[PATCH 06/10 v3] E500 TLB emulation
Signed-off-by: Liu Yu yu@freescale.com --- [v2] 1. rename a lot functions in e500_tlb.c in order to get a clearer hierarchy. 2. remove unmatched comments. 3. adjust mask to make sure tlbsel always be safe. [v3] fix wrong spelling in comments. arch/powerpc/kvm/e500_tlb.c | 737 +++ arch/powerpc/kvm/e500_tlb.h | 184 +++ 2 files changed, 921 insertions(+), 0 deletions(-) create mode 100644 arch/powerpc/kvm/e500_tlb.c create mode 100644 arch/powerpc/kvm/e500_tlb.h diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c new file mode 100644 index 000..30ce5c7 --- /dev/null +++ b/arch/powerpc/kvm/e500_tlb.c @@ -0,0 +1,737 @@ +/* + * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved. + * + * Author: Yu Liu, yu@freescale.com + * + * Description: + * This file is based on arch/powerpc/kvm/44x_tlb.c, + * by Hollis Blanchard holl...@us.ibm.com. + * + * 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. + */ + +#include linux/types.h +#include linux/string.h +#include linux/kvm.h +#include linux/kvm_host.h +#include linux/highmem.h +#include asm/kvm_ppc.h +#include asm/kvm_e500.h + +#include e500_tlb.h + +#define to_htlb1_esel(esel) (tlb1_entry_num - (esel) - 1) + +static unsigned int tlb1_entry_num; + +void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu) +{ + struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); + struct tlbe *tlbe; + int i, tlbsel; + + printk(| %8s | %8s | %8s | %8s | %8s |\n, + nr, mas1, mas2, mas3, mas7); + + for (tlbsel = 0; tlbsel 2; tlbsel++) { + printk(Guest TLB%d:\n, tlbsel); + for (i = 0; i vcpu_e500-guest_tlb_size[tlbsel]; i++) { + tlbe = vcpu_e500-guest_tlb[tlbsel][i]; + if (tlbe-mas1 MAS1_VALID) + printk( G[%d][%3d] | %08X | %08X | %08X | %08X |\n, + tlbsel, i, tlbe-mas1, tlbe-mas2, + tlbe-mas3, tlbe-mas7); + } + } + + for (tlbsel = 0; tlbsel 2; tlbsel++) { + printk(Shadow TLB%d:\n, tlbsel); + for (i = 0; i vcpu_e500-shadow_tlb_size[tlbsel]; i++) { + tlbe = vcpu_e500-shadow_tlb[tlbsel][i]; + if (tlbe-mas1 MAS1_VALID) + printk( S[%d][%3d] | %08X | %08X | %08X | %08X |\n, + tlbsel, i, tlbe-mas1, tlbe-mas2, + tlbe-mas3, tlbe-mas7); + } + } +} + +static inline unsigned int tlb0_get_next_victim( + struct kvmppc_vcpu_e500 *vcpu_e500) +{ + unsigned int victim; + + victim = vcpu_e500-guest_tlb_nv[0]++; + if (unlikely(vcpu_e500-guest_tlb_nv[0] = KVM_E500_TLB0_WAY_NUM)) + vcpu_e500-guest_tlb_nv[0] = 0; + + return victim; +} + +static inline unsigned int tlb1_max_shadow_size(void) +{ + return tlb1_entry_num - tlbcam_index; +} + +static inline int tlbe_is_writable(struct tlbe *tlbe) +{ + return tlbe-mas3 (MAS3_SW|MAS3_UW); +} + +static inline u32 e500_shadow_mas3_attrib(u32 mas3, int usermode) +{ + /* Mask off reserved bits. */ + mas3 = MAS3_ATTRIB_MASK; + + if (!usermode) { + /* Guest is in supervisor mode, +* so we need to translate guest +* supervisor permissions into user permissions. */ + mas3 = ~E500_TLB_USER_PERM_MASK; + mas3 |= (mas3 E500_TLB_SUPER_PERM_MASK) 1; + } + + return mas3 | E500_TLB_SUPER_PERM_MASK; +} + +static inline u32 e500_shadow_mas2_attrib(u32 mas2, int usermode) +{ + return mas2 MAS2_ATTRIB_MASK; +} + +/* + * Writing shadow tlb entry to host TLB + */ +static inline void __write_host_tlbe(struct tlbe *stlbe) +{ + mtspr(SPRN_MAS1, stlbe-mas1); + mtspr(SPRN_MAS2, stlbe-mas2); + mtspr(SPRN_MAS3, stlbe-mas3); + mtspr(SPRN_MAS7, stlbe-mas7); + __asm__ __volatile__ (tlbwe\n : : ); +} + +static inline void write_host_tlbe(struct kvmppc_vcpu_e500 *vcpu_e500, + int tlbsel, int esel) +{ + struct tlbe *stlbe = vcpu_e500-shadow_tlb[tlbsel][esel]; + + local_irq_disable(); + if (tlbsel == 0) { + __write_host_tlbe(stlbe); + } else { + unsigned register mas0; + + mas0 = mfspr(SPRN_MAS0); + + mtspr(SPRN_MAS0, MAS0_TLBSEL(1) | MAS0_ESEL(to_htlb1_esel(esel))); + __write_host_tlbe(stlbe); + + mtspr(SPRN_MAS0, mas0); + } + local_irq_enable(); +} + +void kvmppc_e500_tlb_load(struct kvm_vcpu *vcpu, int cpu) +{ + struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); + int
RE: [PATCH 07/10] Add kvmppc_mmu_dtlb/itlb_miss for booke
-Original Message- From: kvm-ppc-ow...@vger.kernel.org [mailto:kvm-ppc-ow...@vger.kernel.org] On Behalf Of Hollis Blanchard Sent: Friday, December 19, 2008 7:49 AM To: Liu Yu-B13201 Cc: kvm-ppc@vger.kernel.org Subject: Re: [PATCH 07/10] Add kvmppc_mmu_dtlb/itlb_miss for booke I don't think you've supplied an implementation of these hooks for e500. Does it build with this patch series applied? Yes. I have git-am all this patch series, rebuilt and retested them. -- To unsubscribe from this list: send the line unsubscribe kvm-ppc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html