Re: [Qemu-devel] [PATCH v2 2/4] kvm: ppc: booke206: use MMU API

2011-08-31 Thread Alexander Graf

On 18.08.2011, at 22:38, Scott Wood wrote:

> Share the TLB array with KVM.  This allows us to set the initial TLB
> both on initial boot and reset, is useful for debugging, and could
> eventually be used to support migration.
> 
> Signed-off-by: Scott Wood 
> ---
> v2 (was 1/3 in v1):
> updated for kernel API change, removed kernel header ifdefs,
> minor changes as requested
> 
> hw/ppce500_mpc8544ds.c |2 +
> target-ppc/cpu.h   |2 +
> target-ppc/kvm.c   |   87 
> 3 files changed, 91 insertions(+), 0 deletions(-)
> 
> diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
> index b739ce2..3626e26 100644
> --- a/hw/ppce500_mpc8544ds.c
> +++ b/hw/ppce500_mpc8544ds.c
> @@ -202,6 +202,8 @@ static void mmubooke_create_initial_mapping(CPUState *env,
> tlb->mas2 = va & TARGET_PAGE_MASK;
> tlb->mas7_3 = pa & TARGET_PAGE_MASK;
> tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX;
> +
> +env->tlb_dirty = true;
> }
> 
> static void mpc8544ds_cpu_reset(void *opaque)
> diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
> index 024eb6f..0e38d4f 100644
> --- a/target-ppc/cpu.h
> +++ b/target-ppc/cpu.h
> @@ -919,6 +919,8 @@ struct CPUPPCState {
> ppc_tlb_t tlb;   /* TLB is optional. Allocate them only if needed
> */
> /* 403 dedicated access protection registers */
> target_ulong pb[4];
> +bool tlb_dirty;   /* Set to non-zero when modifying TLB  
> */
> +bool kvm_sw_tlb;  /* non-zero if KVM SW TLB API is active
> */
> #endif
> 
> /* Other registers */
> diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
> index 21f35af7..1e1e5db 100644
> --- a/target-ppc/kvm.c
> +++ b/target-ppc/kvm.c
> @@ -105,6 +105,54 @@ static int kvm_arch_sync_sregs(CPUState *cenv)
> return kvm_vcpu_ioctl(cenv, KVM_SET_SREGS, &sregs);
> }
> 
> +/* Set up a shared TLB array with KVM */
> +static int kvm_booke206_tlb_init(CPUState *env)
> +{
> +struct kvm_book3e_206_tlb_params params = {};
> +struct kvm_config_tlb cfg = {};
> +struct kvm_enable_cap encap = {};
> +size_t array_len;
> +unsigned int entries = 0;
> +int ret, i;
> +
> +if (!kvm_enabled() ||
> +!kvm_check_extension(env->kvm_state, KVM_CAP_SW_TLB)) {
> +return 0;
> +}
> +
> +assert(ARRAY_SIZE(params.tlb_sizes) == BOOKE206_MAX_TLBN);
> +
> +for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
> +params.tlb_sizes[i] = booke206_tlb_size(env, i);
> +params.tlb_ways[i] = booke206_tlb_ways(env, i);
> +entries += params.tlb_sizes[i];
> +}
> +
> +assert(entries == env->nb_tlb);
> +assert(sizeof(struct kvm_book3e_206_tlb_entry) == sizeof(ppcmas_tlb_t));
> +
> +array_len = sizeof(ppcmas_tlb_t) * entries;

/dev/shm/qemu/target-ppc/kvm.c: In function 'kvm_booke206_tlb_init':
/dev/shm/qemu/target-ppc/kvm.c:121:12: warning: variable 'array_len' set but 
not used [-Wunused-but-set-variable]


Alex




[Qemu-devel] [PATCH v2 2/4] kvm: ppc: booke206: use MMU API

2011-08-18 Thread Scott Wood
Share the TLB array with KVM.  This allows us to set the initial TLB
both on initial boot and reset, is useful for debugging, and could
eventually be used to support migration.

Signed-off-by: Scott Wood 
---
v2 (was 1/3 in v1):
updated for kernel API change, removed kernel header ifdefs,
minor changes as requested

 hw/ppce500_mpc8544ds.c |2 +
 target-ppc/cpu.h   |2 +
 target-ppc/kvm.c   |   87 
 3 files changed, 91 insertions(+), 0 deletions(-)

diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index b739ce2..3626e26 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -202,6 +202,8 @@ static void mmubooke_create_initial_mapping(CPUState *env,
 tlb->mas2 = va & TARGET_PAGE_MASK;
 tlb->mas7_3 = pa & TARGET_PAGE_MASK;
 tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX;
+
+env->tlb_dirty = true;
 }
 
 static void mpc8544ds_cpu_reset(void *opaque)
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 024eb6f..0e38d4f 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -919,6 +919,8 @@ struct CPUPPCState {
 ppc_tlb_t tlb;   /* TLB is optional. Allocate them only if needed*/
 /* 403 dedicated access protection registers */
 target_ulong pb[4];
+bool tlb_dirty;   /* Set to non-zero when modifying TLB  */
+bool kvm_sw_tlb;  /* non-zero if KVM SW TLB API is active*/
 #endif
 
 /* Other registers */
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 21f35af7..1e1e5db 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -105,6 +105,54 @@ static int kvm_arch_sync_sregs(CPUState *cenv)
 return kvm_vcpu_ioctl(cenv, KVM_SET_SREGS, &sregs);
 }
 
+/* Set up a shared TLB array with KVM */
+static int kvm_booke206_tlb_init(CPUState *env)
+{
+struct kvm_book3e_206_tlb_params params = {};
+struct kvm_config_tlb cfg = {};
+struct kvm_enable_cap encap = {};
+size_t array_len;
+unsigned int entries = 0;
+int ret, i;
+
+if (!kvm_enabled() ||
+!kvm_check_extension(env->kvm_state, KVM_CAP_SW_TLB)) {
+return 0;
+}
+
+assert(ARRAY_SIZE(params.tlb_sizes) == BOOKE206_MAX_TLBN);
+
+for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
+params.tlb_sizes[i] = booke206_tlb_size(env, i);
+params.tlb_ways[i] = booke206_tlb_ways(env, i);
+entries += params.tlb_sizes[i];
+}
+
+assert(entries == env->nb_tlb);
+assert(sizeof(struct kvm_book3e_206_tlb_entry) == sizeof(ppcmas_tlb_t));
+
+array_len = sizeof(ppcmas_tlb_t) * entries;
+env->tlb_dirty = true;
+
+cfg.array = (uintptr_t)env->tlb.tlbm;
+cfg.array_len = sizeof(ppcmas_tlb_t) * entries;
+cfg.params = (uintptr_t)¶ms;
+cfg.mmu_type = KVM_MMU_FSL_BOOKE_NOHV;
+
+encap.cap = KVM_CAP_SW_TLB;
+encap.args[0] = (uintptr_t)&cfg;
+
+ret = kvm_vcpu_ioctl(env, KVM_ENABLE_CAP, &encap);
+if (ret < 0) {
+fprintf(stderr, "%s: couldn't enable KVM_CAP_SW_TLB: %s\n",
+__func__, strerror(-ret));
+return ret;
+}
+
+env->kvm_sw_tlb = true;
+return 0;
+}
+
 int kvm_arch_init_vcpu(CPUState *cenv)
 {
 int ret;
@@ -116,6 +164,15 @@ int kvm_arch_init_vcpu(CPUState *cenv)
 
 idle_timer = qemu_new_timer_ns(vm_clock, kvm_kick_env, cenv);
 
+/* Some targets support access to KVM's guest TLB. */
+switch (cenv->mmu_model) {
+case POWERPC_MMU_BOOKE206:
+ret = kvm_booke206_tlb_init(cenv);
+break;
+default:
+break;
+}
+
 return ret;
 }
 
@@ -123,6 +180,31 @@ void kvm_arch_reset_vcpu(CPUState *env)
 {
 }
 
+static void kvm_sw_tlb_put(CPUState *env)
+{
+struct kvm_dirty_tlb dirty_tlb;
+unsigned char *bitmap;
+int ret;
+
+if (!env->kvm_sw_tlb) {
+return;
+}
+
+bitmap = qemu_malloc((env->nb_tlb + 7) / 8);
+memset(bitmap, 0xFF, (env->nb_tlb + 7) / 8);
+
+dirty_tlb.bitmap = (uintptr_t)bitmap;
+dirty_tlb.num_dirty = env->nb_tlb;
+
+ret = kvm_vcpu_ioctl(env, KVM_DIRTY_TLB, &dirty_tlb);
+if (ret) {
+fprintf(stderr, "%s: KVM_DIRTY_TLB: %s\n",
+__func__, strerror(-ret));
+}
+
+qemu_free(bitmap);
+}
+
 int kvm_arch_put_registers(CPUState *env, int level)
 {
 struct kvm_regs regs;
@@ -160,6 +242,11 @@ int kvm_arch_put_registers(CPUState *env, int level)
 if (ret < 0)
 return ret;
 
+if (env->tlb_dirty) {
+kvm_sw_tlb_put(env);
+env->tlb_dirty = false;
+}
+
 return ret;
 }
 
-- 
1.7.6





[Qemu-devel] [PATCH v2 2/4] kvm: ppc: booke206: use MMU API

2011-07-07 Thread Scott Wood
Share the TLB array with KVM.  This allows us to set the initial TLB
both on initial boot and reset, is useful for debugging, and could
eventually be used to support migration.

Signed-off-by: Scott Wood 
---
v2:
 - rebase on top of current tree, remove now-unneeded ifdefs
 - add some asserts and comments as requested

 hw/ppce500_mpc8544ds.c |2 +
 target-ppc/cpu.h   |2 +
 target-ppc/kvm.c   |   83 
 3 files changed, 87 insertions(+), 0 deletions(-)

diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index b739ce2..3626e26 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -202,6 +202,8 @@ static void mmubooke_create_initial_mapping(CPUState *env,
 tlb->mas2 = va & TARGET_PAGE_MASK;
 tlb->mas7_3 = pa & TARGET_PAGE_MASK;
 tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX;
+
+env->tlb_dirty = true;
 }
 
 static void mpc8544ds_cpu_reset(void *opaque)
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 84f8ff6..f8bf2b1 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -921,6 +921,8 @@ struct CPUPPCState {
 ppc_tlb_t tlb;   /* TLB is optional. Allocate them only if needed*/
 /* 403 dedicated access protection registers */
 target_ulong pb[4];
+bool tlb_dirty;   /* Set to non-zero when modifying TLB  */
+bool kvm_sw_tlb;  /* non-zero if KVM SW TLB API is active*/
 #endif
 
 /* Other registers */
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 21f35af7..e18c931 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -105,6 +105,50 @@ static int kvm_arch_sync_sregs(CPUState *cenv)
 return kvm_vcpu_ioctl(cenv, KVM_SET_SREGS, &sregs);
 }
 
+/* Set up a shared TLB array with KVM */
+static int kvm_booke206_tlb_init(CPUState *env)
+{
+struct kvm_book3e_206_tlb_params params = {};
+struct kvm_config_tlb cfg = {};
+size_t array_len;
+unsigned int entries = 0;
+int ret, i;
+
+if (!kvm_enabled() ||
+!kvm_check_extension(env->kvm_state, KVM_CAP_SW_TLB)) {
+return 0;
+}
+
+assert(ARRAY_SIZE(params.tlb_sizes) == BOOKE206_MAX_TLBN);
+
+for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
+params.tlb_sizes[i] = booke206_tlb_size(env, i);
+params.tlb_ways[i] = booke206_tlb_ways(env, i);
+entries += params.tlb_sizes[i];
+}
+
+assert(entries == env->nb_tlb);
+assert(sizeof(struct kvm_book3e_206_tlb_entry) == sizeof(ppcmas_tlb_t));
+
+array_len = sizeof(ppcmas_tlb_t) * entries;
+env->tlb_dirty = true;
+
+cfg.array = (uintptr_t)env->tlb.tlbm;
+cfg.array_len = sizeof(ppcmas_tlb_t) * entries;
+cfg.params = (uintptr_t)¶ms;
+cfg.mmu_type = KVM_MMU_FSL_BOOKE_NOHV;
+
+ret = kvm_vcpu_ioctl(env, KVM_CONFIG_TLB, &cfg);
+if (ret < 0) {
+fprintf(stderr, "%s: couldn't KVM_CONFIG_TLB: %s\n",
+__func__, strerror(-ret));
+return ret;
+}
+
+env->kvm_sw_tlb = true;
+return 0;
+}
+
 int kvm_arch_init_vcpu(CPUState *cenv)
 {
 int ret;
@@ -116,6 +160,15 @@ int kvm_arch_init_vcpu(CPUState *cenv)
 
 idle_timer = qemu_new_timer_ns(vm_clock, kvm_kick_env, cenv);
 
+/* Some targets support access to KVM's guest TLB. */
+switch (cenv->mmu_model) {
+case POWERPC_MMU_BOOKE206:
+ret = kvm_booke206_tlb_init(cenv);
+break;
+default:
+break;
+}
+
 return ret;
 }
 
@@ -123,6 +176,31 @@ void kvm_arch_reset_vcpu(CPUState *env)
 {
 }
 
+static void kvm_sw_tlb_put(CPUState *env)
+{
+struct kvm_dirty_tlb dirty_tlb;
+unsigned char *bitmap;
+int ret;
+
+if (!env->kvm_sw_tlb) {
+return;
+}
+
+bitmap = qemu_malloc((env->nb_tlb + 7) / 8);
+memset(bitmap, 0xFF, (env->nb_tlb + 7) / 8);
+
+dirty_tlb.bitmap = (uintptr_t)bitmap;
+dirty_tlb.num_dirty = env->nb_tlb;
+
+ret = kvm_vcpu_ioctl(env, KVM_DIRTY_TLB, &dirty_tlb);
+if (ret) {
+fprintf(stderr, "%s: KVM_DIRTY_TLB: %s\n",
+__func__, strerror(-ret));
+}
+
+qemu_free(bitmap);
+}
+
 int kvm_arch_put_registers(CPUState *env, int level)
 {
 struct kvm_regs regs;
@@ -160,6 +238,11 @@ int kvm_arch_put_registers(CPUState *env, int level)
 if (ret < 0)
 return ret;
 
+if (env->tlb_dirty) {
+kvm_sw_tlb_put(env);
+env->tlb_dirty = false;
+}
+
 return ret;
 }
 
-- 
1.7.4.1