aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kvm/book3s_hv.c128
1 files changed, 3 insertions, 125 deletions
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index c4f8971c954d..3686471be32b 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -2103,66 +2103,6 @@ static void init_master_vcore(struct kvmppc_vcore *vc)
2103 vc->conferring_threads = 0; 2103 vc->conferring_threads = 0;
2104} 2104}
2105 2105
2106/*
2107 * See if the existing subcores can be split into 3 (or fewer) subcores
2108 * of at most two threads each, so we can fit in another vcore. This
2109 * assumes there are at most two subcores and at most 6 threads in total.
2110 */
2111static bool can_split_piggybacked_subcores(struct core_info *cip)
2112{
2113 int sub, new_sub;
2114 int large_sub = -1;
2115 int thr;
2116 int n_subcores = cip->n_subcores;
2117 struct kvmppc_vcore *vc, *vcnext;
2118 struct kvmppc_vcore *master_vc = NULL;
2119
2120 for (sub = 0; sub < cip->n_subcores; ++sub) {
2121 if (cip->subcore_threads[sub] <= 2)
2122 continue;
2123 if (large_sub >= 0)
2124 return false;
2125 large_sub = sub;
2126 vc = list_first_entry(&cip->vcs[sub], struct kvmppc_vcore,
2127 preempt_list);
2128 if (vc->num_threads > 2)
2129 return false;
2130 n_subcores += (cip->subcore_threads[sub] - 1) >> 1;
2131 }
2132 if (large_sub < 0 || !subcore_config_ok(n_subcores + 1, 2))
2133 return false;
2134
2135 /*
2136 * Seems feasible, so go through and move vcores to new subcores.
2137 * Note that when we have two or more vcores in one subcore,
2138 * all those vcores must have only one thread each.
2139 */
2140 new_sub = cip->n_subcores;
2141 thr = 0;
2142 sub = large_sub;
2143 list_for_each_entry_safe(vc, vcnext, &cip->vcs[sub], preempt_list) {
2144 if (thr >= 2) {
2145 list_del(&vc->preempt_list);
2146 list_add_tail(&vc->preempt_list, &cip->vcs[new_sub]);
2147 /* vc->num_threads must be 1 */
2148 if (++cip->subcore_threads[new_sub] == 1) {
2149 cip->subcore_vm[new_sub] = vc->kvm;
2150 init_master_vcore(vc);
2151 master_vc = vc;
2152 ++cip->n_subcores;
2153 } else {
2154 vc->master_vcore = master_vc;
2155 ++new_sub;
2156 }
2157 }
2158 thr += vc->num_threads;
2159 }
2160 cip->subcore_threads[large_sub] = 2;
2161 cip->max_subcore_threads = 2;
2162
2163 return true;
2164}
2165
2166static bool can_dynamic_split(struct kvmppc_vcore *vc, struct core_info *cip) 2106static bool can_dynamic_split(struct kvmppc_vcore *vc, struct core_info *cip)
2167{ 2107{
2168 int n_threads = vc->num_threads; 2108 int n_threads = vc->num_threads;
@@ -2173,23 +2113,9 @@ static bool can_dynamic_split(struct kvmppc_vcore *vc, struct core_info *cip)
2173 2113
2174 if (n_threads < cip->max_subcore_threads) 2114 if (n_threads < cip->max_subcore_threads)
2175 n_threads = cip->max_subcore_threads; 2115 n_threads = cip->max_subcore_threads;
2176 if (subcore_config_ok(cip->n_subcores + 1, n_threads)) { 2116 if (!subcore_config_ok(cip->n_subcores + 1, n_threads))
2177 cip->max_subcore_threads = n_threads;
2178 } else if (cip->n_subcores <= 2 && cip->total_threads <= 6 &&
2179 vc->num_threads <= 2) {
2180 /*
2181 * We may be able to fit another subcore in by
2182 * splitting an existing subcore with 3 or 4
2183 * threads into two 2-thread subcores, or one
2184 * with 5 or 6 threads into three subcores.
2185 * We can only do this if those subcores have
2186 * piggybacked virtual cores.
2187 */
2188 if (!can_split_piggybacked_subcores(cip))
2189 return false;
2190 } else {
2191 return false; 2117 return false;
2192 } 2118 cip->max_subcore_threads = n_threads;
2193 2119
2194 sub = cip->n_subcores; 2120 sub = cip->n_subcores;
2195 ++cip->n_subcores; 2121 ++cip->n_subcores;
@@ -2203,45 +2129,6 @@ static bool can_dynamic_split(struct kvmppc_vcore *vc, struct core_info *cip)
2203 return true; 2129 return true;
2204} 2130}
2205 2131
2206static bool can_piggyback_subcore(struct kvmppc_vcore *pvc,
2207 struct core_info *cip, int sub)
2208{
2209 struct kvmppc_vcore *vc;
2210 int n_thr;
2211
2212 vc = list_first_entry(&cip->vcs[sub], struct kvmppc_vcore,
2213 preempt_list);
2214
2215 /* require same VM and same per-core reg values */
2216 if (pvc->kvm != vc->kvm ||
2217 pvc->tb_offset != vc->tb_offset ||
2218 pvc->pcr != vc->pcr ||
2219 pvc->lpcr != vc->lpcr)
2220 return false;
2221
2222 /*
2223 * P8 guests can't do piggybacking, because then the
2224 * VTB would be shared between the vcpus.
2225 */
2226 if (cpu_has_feature(CPU_FTR_ARCH_207S))
2227 return false;
2228
2229 n_thr = cip->subcore_threads[sub] + pvc->num_threads;
2230 if (n_thr > cip->max_subcore_threads) {
2231 if (!subcore_config_ok(cip->n_subcores, n_thr))
2232 return false;
2233 cip->max_subcore_threads = n_thr;
2234 }
2235
2236 cip->total_threads += pvc->num_threads;
2237 cip->subcore_threads[sub] = n_thr;
2238 pvc->master_vcore = vc;
2239 list_del(&pvc->preempt_list);
2240 list_add_tail(&pvc->preempt_list, &cip->vcs[sub]);
2241
2242 return true;
2243}
2244
2245/* 2132/*
2246 * Work out whether it is possible to piggyback the execution of 2133 * Work out whether it is possible to piggyback the execution of
2247 * vcore *pvc onto the execution of the other vcores described in *cip. 2134 * vcore *pvc onto the execution of the other vcores described in *cip.
@@ -2249,19 +2136,10 @@ static bool can_piggyback_subcore(struct kvmppc_vcore *pvc,
2249static bool can_piggyback(struct kvmppc_vcore *pvc, struct core_info *cip, 2136static bool can_piggyback(struct kvmppc_vcore *pvc, struct core_info *cip,
2250 int target_threads) 2137 int target_threads)
2251{ 2138{
2252 int sub;
2253
2254 if (cip->total_threads + pvc->num_threads > target_threads) 2139 if (cip->total_threads + pvc->num_threads > target_threads)
2255 return false; 2140 return false;
2256 for (sub = 0; sub < cip->n_subcores; ++sub)
2257 if (cip->subcore_threads[sub] &&
2258 can_piggyback_subcore(pvc, cip, sub))
2259 return true;
2260 2141
2261 if (can_dynamic_split(pvc, cip)) 2142 return can_dynamic_split(pvc, cip);
2262 return true;
2263
2264 return false;
2265} 2143}
2266 2144
2267static void prepare_threads(struct kvmppc_vcore *vc) 2145static void prepare_threads(struct kvmppc_vcore *vc)