aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMatt Evans <matt@ozlabs.org>2012-01-30 15:25:31 -0500
committerAvi Kivity <avi@redhat.com>2012-04-08 05:55:31 -0400
commit3aaefef200f618dc455cdf18053a7aeb262b5a11 (patch)
tree600a14e49230fbb8182325481b6a599864628484 /arch
parent03660ba27020250eae0b5a2722e0c7bec4968c3c (diff)
KVM: PPC: Book3s: PR: Add SPAPR H_BULK_REMOVE support
SPAPR support includes various in-kernel hypercalls, improving performance by cutting out the exit to userspace. H_BULK_REMOVE is implemented in this patch. Signed-off-by: Matt Evans <matt@ozlabs.org> Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/kvm/book3s_pr_papr.c82
1 files changed, 78 insertions, 4 deletions
diff --git a/arch/powerpc/kvm/book3s_pr_papr.c b/arch/powerpc/kvm/book3s_pr_papr.c
index b9589324797..6d1bfe246f0 100644
--- a/arch/powerpc/kvm/book3s_pr_papr.c
+++ b/arch/powerpc/kvm/book3s_pr_papr.c
@@ -98,6 +98,83 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu)
98 return EMULATE_DONE; 98 return EMULATE_DONE;
99} 99}
100 100
101/* Request defs for kvmppc_h_pr_bulk_remove() */
102#define H_BULK_REMOVE_TYPE 0xc000000000000000ULL
103#define H_BULK_REMOVE_REQUEST 0x4000000000000000ULL
104#define H_BULK_REMOVE_RESPONSE 0x8000000000000000ULL
105#define H_BULK_REMOVE_END 0xc000000000000000ULL
106#define H_BULK_REMOVE_CODE 0x3000000000000000ULL
107#define H_BULK_REMOVE_SUCCESS 0x0000000000000000ULL
108#define H_BULK_REMOVE_NOT_FOUND 0x1000000000000000ULL
109#define H_BULK_REMOVE_PARM 0x2000000000000000ULL
110#define H_BULK_REMOVE_HW 0x3000000000000000ULL
111#define H_BULK_REMOVE_RC 0x0c00000000000000ULL
112#define H_BULK_REMOVE_FLAGS 0x0300000000000000ULL
113#define H_BULK_REMOVE_ABSOLUTE 0x0000000000000000ULL
114#define H_BULK_REMOVE_ANDCOND 0x0100000000000000ULL
115#define H_BULK_REMOVE_AVPN 0x0200000000000000ULL
116#define H_BULK_REMOVE_PTEX 0x00ffffffffffffffULL
117#define H_BULK_REMOVE_MAX_BATCH 4
118
119static int kvmppc_h_pr_bulk_remove(struct kvm_vcpu *vcpu)
120{
121 int i;
122 int paramnr = 4;
123 int ret = H_SUCCESS;
124
125 for (i = 0; i < H_BULK_REMOVE_MAX_BATCH; i++) {
126 unsigned long tsh = kvmppc_get_gpr(vcpu, paramnr+(2*i));
127 unsigned long tsl = kvmppc_get_gpr(vcpu, paramnr+(2*i)+1);
128 unsigned long pteg, rb, flags;
129 unsigned long pte[2];
130 unsigned long v = 0;
131
132 if ((tsh & H_BULK_REMOVE_TYPE) == H_BULK_REMOVE_END) {
133 break; /* Exit success */
134 } else if ((tsh & H_BULK_REMOVE_TYPE) !=
135 H_BULK_REMOVE_REQUEST) {
136 ret = H_PARAMETER;
137 break; /* Exit fail */
138 }
139
140 tsh &= H_BULK_REMOVE_PTEX | H_BULK_REMOVE_FLAGS;
141 tsh |= H_BULK_REMOVE_RESPONSE;
142
143 if ((tsh & H_BULK_REMOVE_ANDCOND) &&
144 (tsh & H_BULK_REMOVE_AVPN)) {
145 tsh |= H_BULK_REMOVE_PARM;
146 kvmppc_set_gpr(vcpu, paramnr+(2*i), tsh);
147 ret = H_PARAMETER;
148 break; /* Exit fail */
149 }
150
151 pteg = get_pteg_addr(vcpu, tsh & H_BULK_REMOVE_PTEX);
152 copy_from_user(pte, (void __user *)pteg, sizeof(pte));
153
154 /* tsl = AVPN */
155 flags = (tsh & H_BULK_REMOVE_FLAGS) >> 26;
156
157 if ((pte[0] & HPTE_V_VALID) == 0 ||
158 ((flags & H_AVPN) && (pte[0] & ~0x7fUL) != tsl) ||
159 ((flags & H_ANDCOND) && (pte[0] & tsl) != 0)) {
160 tsh |= H_BULK_REMOVE_NOT_FOUND;
161 } else {
162 /* Splat the pteg in (userland) hpt */
163 copy_to_user((void __user *)pteg, &v, sizeof(v));
164
165 rb = compute_tlbie_rb(pte[0], pte[1],
166 tsh & H_BULK_REMOVE_PTEX);
167 vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false);
168 tsh |= H_BULK_REMOVE_SUCCESS;
169 tsh |= (pte[1] & (HPTE_R_C | HPTE_R_R)) << 43;
170 }
171 kvmppc_set_gpr(vcpu, paramnr+(2*i), tsh);
172 }
173 kvmppc_set_gpr(vcpu, 3, ret);
174
175 return EMULATE_DONE;
176}
177
101static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu) 178static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
102{ 179{
103 unsigned long flags = kvmppc_get_gpr(vcpu, 4); 180 unsigned long flags = kvmppc_get_gpr(vcpu, 4);
@@ -144,10 +221,7 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
144 case H_PROTECT: 221 case H_PROTECT:
145 return kvmppc_h_pr_protect(vcpu); 222 return kvmppc_h_pr_protect(vcpu);
146 case H_BULK_REMOVE: 223 case H_BULK_REMOVE:
147 /* We just flush all PTEs, so user space can 224 return kvmppc_h_pr_bulk_remove(vcpu);
148 handle the HPT modifications */
149 kvmppc_mmu_pte_flush(vcpu, 0, 0);
150 break;
151 case H_CEDE: 225 case H_CEDE:
152 kvm_vcpu_block(vcpu); 226 kvm_vcpu_block(vcpu);
153 vcpu->stat.halt_wakeup++; 227 vcpu->stat.halt_wakeup++;