On Tue, May 28, 2024 at 12:55:14PM +0300, Kirill A. Shutemov wrote: > +static void tdx_kexec_finish(void) > +{ > + unsigned long addr, end; > + long found = 0, shared; > + > + lockdep_assert_irqs_disabled(); > + > + addr = PAGE_OFFSET; > + end = PAGE_OFFSET + get_max_mapped(); > + > + while (addr < end) { > + unsigned long size; > + unsigned int level; > + pte_t *pte; > + > + pte = lookup_address(addr, &level); > + size = page_level_size(level); > + > + if (pte && pte_decrypted(*pte)) { > + int pages = size / PAGE_SIZE; > + > + /* > + * Touching memory with shared bit set triggers implicit > + * conversion to shared. > + * > + * Make sure nobody touches the shared range from > + * now on. > + */ > + set_pte(pte, __pte(0)); > + Format the below into a comment here: /* The only thing one can do at this point on failure is panic. It is reasonable to proceed, especially for the crash case because the kexec-ed kernel is using a different page table so there won't be a mismatch between shared/private marking of the page so it doesn't matter. Also, even if the failure is real and the page cannot be touched as private, the kdump kernel will boot fine as it uses pre-reserved memory. What happens next depends on what the dumping process does and there's a reasonable chance to produce useful dump on crash. Regardless, the print leaves a trace in the log to give a clue for debug. One possible reason for the failure is if kdump raced with memory conversion. In this case shared bit in page table got set (or not cleared form shared->private conversion), but the page is actually private. So this failure is not going to affect the kexec'ed kernel. */ <--- > + if (!tdx_enc_status_changed(addr, pages, true)) { > + pr_err("Failed to unshare range %#lx-%#lx\n", > + addr, addr + size); > + } > + > + found += pages; > + } > + > + addr += size; > + } > + > + __flush_tlb_all(); > + > + shared = atomic_long_read(&nr_shared); > + if (shared != found) { > + pr_err("shared page accounting is off\n"); > + pr_err("nr_shared = %ld, nr_found = %ld\n", shared, found); > + } > +} ... > static int __set_memory_enc_dec(unsigned long addr, int numpages, bool enc) > { > - if (cc_platform_has(CC_ATTR_MEM_ENCRYPT)) > - return __set_memory_enc_pgtable(addr, numpages, enc); > + int ret = 0; > > - return 0; > + if (cc_platform_has(CC_ATTR_MEM_ENCRYPT)) { > + if (!down_read_trylock(&mem_enc_lock)) > + return -EBUSY; > + > + ret = __set_memory_enc_pgtable(addr, numpages, enc); > + > + up_read(&mem_enc_lock); > + } So CC_ATTR_MEM_ENCRYPT is set for SEV* guests too. You need to change that code here to take the lock only on TDX, where you want it, not on the others. Thx. -- Regards/Gruss, Boris. https://people.kernel.org/tglx/notes-about-netiquette