From mboxrd@z Thu Jan 1 00:00:00 1970 From: erik quanstrom Date: Thu, 23 Jun 2011 21:04:28 -0400 To: 9fans@9fans.net Message-ID: <38d47085b6f6ddb3af96fb1cc0670ee4@ladd.quanstro.net> MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit Subject: [9fans] vunmap() bug Topicbox-Message-UUID: f5366abc-ead6-11e9-9d60-3106f5b1d025 today i spent a little while chasing a crash that happened after a driver i'm working on gave up during initialization and decided to free its vmaps. it crashed in vunmap. since this hardware does some crazy things, it took a while to rule out the hardware. after all, vunmap can't possibly be broken, right? as it turns out, there was an off by one error in pdbunmap(). in the case that (va&(4*MB-1)) == 0 and a 4mb pde were used, the code would stick on the same address and attempt to double-free the same va. the code was va = (va+4*MB-1) & ~(4*MB-1); this lead to a panic, since the second time through the va was not mapped. the reason for this is that a round-up algorithm was used, and this is off by one. i changed the code slightly to eliminate the rounding in the case of a 4mb mapping. we're assurred that (va&(4*MB-1)) == 0 in this case. (cf. pdbmap()) - erik ---- static void pdbunmap(ulong *pdb, ulong va, int size) { ulong vae; ulong *table; vae = va+size; while(va < vae){ table = &pdb[PDX(va)]; if(!(*table & PTEVALID)){ panic("vunmap: not mapped pde"); /* va = (va+4*MB) & ~(4*MB-1); continue; */ } if(*table & PTESIZE){ if(va & 4*MB-1) panic("vunmap: misaligned: %#p\n", va); *table = 0; va += 4*MB; continue; } table = KADDR(PPN(*table)); if(!(table[PTX(va)] & PTEVALID)) panic("vunmap: not mapped"); table[PTX(va)] = 0; va += BY2PG; } }