tree: https://git.kernel.org/pub/scm/virt/kvm/kvm.git tdp-mmu head: 1eb10c8be32298671cee78789ce32c3851f2e1f7 commit: 0fbfee5a26646c2c3e361ba1f7d6c3adee7d09a5 [41/57] kvm: mmu: Add functions to handle changed TDP SPTEs config: x86_64-rhel-7.6-kselftests (attached as .config) compiler: gcc-9 (Debian 9.3.0-15) 9.3.0 reproduce (this is a W=1 build): # https://git.kernel.org/pub/scm/virt/kvm/kvm.git/commit/?id=0fbfee5a26646c2c3e361ba1f7d6c3adee7d09a5 git remote add kvm https://git.kernel.org/pub/scm/virt/kvm/kvm.git git fetch --no-tags kvm tdp-mmu git checkout 0fbfee5a26646c2c3e361ba1f7d6c3adee7d09a5 # save the attached .config to linux build tree make W=1 ARCH=x86_64 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@xxxxxxxxx> Note: the kvm/tdp-mmu HEAD 1eb10c8be32298671cee78789ce32c3851f2e1f7 builds fine. It only hurts bisectibility. All error/warnings (new ones prefixed by >>): arch/x86/kvm/mmu/tdp_mmu.c: In function 'handle_changed_spte': >> arch/x86/kvm/mmu/tdp_mmu.c:281:8: error: implicit declaration of function 'spte_to_child_pt' [-Werror=implicit-function-declaration] 281 | pt = spte_to_child_pt(old_spte, level); | ^~~~~~~~~~~~~~~~ >> arch/x86/kvm/mmu/tdp_mmu.c:281:6: warning: assignment to 'u64 *' {aka 'long long unsigned int *'} from 'int' makes pointer from integer without a cast [-Wint-conversion] 281 | pt = spte_to_child_pt(old_spte, level); | ^ At top level: arch/x86/kvm/mmu/tdp_mmu.c:208:13: warning: 'handle_changed_spte' defined but not used [-Wunused-function] 208 | static void handle_changed_spte(struct kvm *kvm, int as_id, gfn_t gfn, | ^~~~~~~~~~~~~~~~~~~ cc1: some warnings being treated as errors vim +/spte_to_child_pt +281 arch/x86/kvm/mmu/tdp_mmu.c 192 193 static void handle_changed_spte(struct kvm *kvm, int as_id, gfn_t gfn, 194 u64 old_spte, u64 new_spte, int level); 195 196 /** 197 * handle_changed_spte - handle bookkeeping associated with an SPTE change 198 * @kvm: kvm instance 199 * @as_id: the address space of the paging structure the SPTE was a part of 200 * @gfn: the base GFN that was mapped by the SPTE 201 * @old_spte: The value of the SPTE before the change 202 * @new_spte: The value of the SPTE after the change 203 * @level: the level of the PT the SPTE is part of in the paging structure 204 * 205 * Handle bookkeeping that might result from the modification of a SPTE. 206 * This function must be called for all TDP SPTE modifications. 207 */ 208 static void handle_changed_spte(struct kvm *kvm, int as_id, gfn_t gfn, 209 u64 old_spte, u64 new_spte, int level) 210 { 211 bool was_present = is_shadow_present_pte(old_spte); 212 bool is_present = is_shadow_present_pte(new_spte); 213 bool was_leaf = was_present && is_last_spte(old_spte, level); 214 bool is_leaf = is_present && is_last_spte(new_spte, level); 215 bool pfn_changed = spte_to_pfn(old_spte) != spte_to_pfn(new_spte); 216 u64 *pt; 217 u64 old_child_spte; 218 int i; 219 220 WARN_ON(level > PT64_ROOT_MAX_LEVEL); 221 WARN_ON(level < PG_LEVEL_4K); 222 WARN_ON(gfn % KVM_PAGES_PER_HPAGE(level)); 223 224 /* 225 * If this warning were to trigger it would indicate that there was a 226 * missing MMU notifier or a race with some notifier handler. 227 * A present, leaf SPTE should never be directly replaced with another 228 * present leaf SPTE pointing to a differnt PFN. A notifier handler 229 * should be zapping the SPTE before the main MM's page table is 230 * changed, or the SPTE should be zeroed, and the TLBs flushed by the 231 * thread before replacement. 232 */ 233 if (was_leaf && is_leaf && pfn_changed) { 234 pr_err("Invalid SPTE change: cannot replace a present leaf\n" 235 "SPTE with another present leaf SPTE mapping a\n" 236 "different PFN!\n" 237 "as_id: %d gfn: %llx old_spte: %llx new_spte: %llx level: %d", 238 as_id, gfn, old_spte, new_spte, level); 239 240 /* 241 * Crash the host to prevent error propagation and guest data 242 * courruption. 243 */ 244 BUG(); 245 } 246 247 if (old_spte == new_spte) 248 return; 249 250 /* 251 * The only times a SPTE should be changed from a non-present to 252 * non-present state is when an MMIO entry is installed/modified/ 253 * removed. In that case, there is nothing to do here. 254 */ 255 if (!was_present && !is_present) { 256 /* 257 * If this change does not involve a MMIO SPTE, it is 258 * unexpected. Log the change, though it should not impact the 259 * guest since both the former and current SPTEs are nonpresent. 260 */ 261 if (WARN_ON(!is_mmio_spte(old_spte) && !is_mmio_spte(new_spte))) 262 pr_err("Unexpected SPTE change! Nonpresent SPTEs\n" 263 "should not be replaced with another,\n" 264 "different nonpresent SPTE, unless one or both\n" 265 "are MMIO SPTEs.\n" 266 "as_id: %d gfn: %llx old_spte: %llx new_spte: %llx level: %d", 267 as_id, gfn, old_spte, new_spte, level); 268 return; 269 } 270 271 272 if (was_leaf && is_dirty_spte(old_spte) && 273 (!is_dirty_spte(new_spte) || pfn_changed)) 274 kvm_set_pfn_dirty(spte_to_pfn(old_spte)); 275 276 /* 277 * Recursively handle child PTs if the change removed a subtree from 278 * the paging structure. 279 */ 280 if (was_present && !was_leaf && (pfn_changed || !is_present)) { > 281 pt = spte_to_child_pt(old_spte, level); --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@xxxxxxxxxxxx
Attachment:
.config.gz
Description: application/gzip