Date: Fri, 17 Apr 2026 13:00:42 +0000 From: bugzilla-noreply@freebsd.org To: bugs@FreeBSD.org Subject: [Bug 293382] Dead lock and kernel crash around closefp_impl Message-ID: <bug-293382-227-l3OVsBg2EE@https.bugs.freebsd.org/bugzilla/> In-Reply-To: <bug-293382-227@https.bugs.freebsd.org/bugzilla/>
index | next in thread | previous in thread | raw e-mail
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=293382 --- Comment #94 from Kristofer Peterson <kris@tranception.com> --- The description of INVLPGB in Volume 3 of the AMD64 Architecture Programmer's Manual is not terribly clear; it would have been nice had they included a pseudo-code description similar to what you find in the Intel documentation. I was curious how other operating systems chose to use and implement INVLPGB given presumably the same information; I include a short extract below from the Linux kernel. Bit 31 of ECX is represented by a stride enum which suggests their interpretation of INVLPGB is inline with what Kyle outlined yesterday. Obviously this is no substitute for clear authoritative documentation or guidance from AMD but hopefully a useful data point. Excerpt from Linux source file: arch/x86/include/asm/tlb.h repo: https://github.com/torvalds/linux.git ----------------------------------------------------------------------------- 31:enum addr_stride { 32: PTE_STRIDE = 0, 33: PMD_STRIDE = 1 34:}; 35: 36:/* 37: * INVLPGB can be targeted by virtual address, PCID, ASID, or any combination 38: * of the three. For example: 39: * - FLAG_VA | FLAG_INCLUDE_GLOBAL: invalidate all TLB entries at the address 40: * - FLAG_PCID: invalidate all TLB entries matching the PCID 41: * 42: * The first is used to invalidate (kernel) mappings at a particular 43: * address across all processes. 44: * 45: * The latter invalidates all TLB entries matching a PCID. 46: */ 47:#define INVLPGB_FLAG_VA BIT(0) 48:#define INVLPGB_FLAG_PCID BIT(1) 49:#define INVLPGB_FLAG_ASID BIT(2) 50:#define INVLPGB_FLAG_INCLUDE_GLOBAL BIT(3) 51:#define INVLPGB_FLAG_FINAL_ONLY BIT(4) 52:#define INVLPGB_FLAG_INCLUDE_NESTED BIT(5) 53: 54:/* The implied mode when all bits are clear: */ 55:#define INVLPGB_MODE_ALL_NONGLOBALS 0UL 56: 57:#ifdef CONFIG_BROADCAST_TLB_FLUSH 58:/* 59: * INVLPGB does broadcast TLB invalidation across all the CPUs in the system. 60: * 61: * The INVLPGB instruction is weakly ordered, and a batch of invalidations can 62: * be done in a parallel fashion. 63: * 64: * The instruction takes the number of extra pages to invalidate, beyond the 65: * first page, while __invlpgb gets the more human readable number of pages to 66: * invalidate. 67: * 68: * The bits in rax[0:2] determine respectively which components of the address 69: * (VA, PCID, ASID) get compared when flushing. If neither bits are set, *any* 70: * address in the specified range matches. 71: * 72: * Since it is desired to only flush TLB entries for the ASID that is executing 73: * the instruction (a host/hypervisor or a guest), the ASID valid bit should 74: * always be set. On a host/hypervisor, the hardware will use the ASID value 75: * specified in EDX[15:0] (which should be 0). On a guest, the hardware will 76: * use the actual ASID value of the guest. 77: * 78: * TLBSYNC is used to ensure that pending INVLPGB invalidations initiated from 79: * this CPU have completed. 80: */ 81:static inline void __invlpgb(unsigned long asid, unsigned long pcid, 82: unsigned long addr, u16 nr_pages, 83: enum addr_stride stride, u8 flags) 84:{ 85: u64 rax = addr | flags | INVLPGB_FLAG_ASID; 86: u32 ecx = (stride << 31) | (nr_pages - 1); 87: u32 edx = (pcid << 16) | asid; 88: 89: /* The low bits in rax are for flags. Verify addr is clean. */ 90: VM_WARN_ON_ONCE(addr & ~PAGE_MASK); 91: 92: /* INVLPGB; supported in binutils >= 2.36. */ 93: asm volatile(".byte 0x0f, 0x01, 0xfe" :: "a" (rax), "c" (ecx), "d" (edx)); 94:} -- You are receiving this mail because: You are the assignee for the bug.home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-293382-227-l3OVsBg2EE>
