openrisc: update DTLB-miss handler last
The self-modifying code that updates the TLB handler at start-up has a subtle ordering requirement: the DTLB handler must be the last thing changed. What I was seeing was the following: i) The DTLB handler was updated ii) The following printk caused a TLB miss and the look-up resulted in the page containing itlb_vector (0xc0000a00) being bounced from the TLB. iii) The subsequent access to itlb_vector caused a TLB miss and reload of the page containing itlb_vector from the page tables. iv) But this reload of the page in iii) was being done by the "new" DTLB-miss handler which resulted (correctly) in the page flags being set to read-only; the subsequent write-access to itlb_vector thus resulted in a page (access) fault. This is easily remedied if we ensure that the boot-time DTLB-miss handler continues running until the very last bit of self-modifying code has been executed. This patch should ensure that the very last thing updated is the DTLB-handler itself. Signed-off-by: Jonas Bonn <jonas@southpole.se> Acked-by: Julius Baxter <juliusbaxter@gmail.com> Tested-by: Sebastian Macke <sebastian@macke.de>
This commit is contained in:
parent
a81252d75e
commit
8668480eb7
|
@ -167,15 +167,26 @@ void __init paging_init(void)
|
||||||
unsigned long *dtlb_vector = __va(0x900);
|
unsigned long *dtlb_vector = __va(0x900);
|
||||||
unsigned long *itlb_vector = __va(0xa00);
|
unsigned long *itlb_vector = __va(0xa00);
|
||||||
|
|
||||||
|
printk(KERN_INFO "itlb_miss_handler %p\n", &itlb_miss_handler);
|
||||||
|
*itlb_vector = ((unsigned long)&itlb_miss_handler -
|
||||||
|
(unsigned long)itlb_vector) >> 2;
|
||||||
|
|
||||||
|
/* Soft ordering constraint to ensure that dtlb_vector is
|
||||||
|
* the last thing updated
|
||||||
|
*/
|
||||||
|
barrier();
|
||||||
|
|
||||||
printk(KERN_INFO "dtlb_miss_handler %p\n", &dtlb_miss_handler);
|
printk(KERN_INFO "dtlb_miss_handler %p\n", &dtlb_miss_handler);
|
||||||
*dtlb_vector = ((unsigned long)&dtlb_miss_handler -
|
*dtlb_vector = ((unsigned long)&dtlb_miss_handler -
|
||||||
(unsigned long)dtlb_vector) >> 2;
|
(unsigned long)dtlb_vector) >> 2;
|
||||||
|
|
||||||
printk(KERN_INFO "itlb_miss_handler %p\n", &itlb_miss_handler);
|
|
||||||
*itlb_vector = ((unsigned long)&itlb_miss_handler -
|
|
||||||
(unsigned long)itlb_vector) >> 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Soft ordering constraint to ensure that cache invalidation and
|
||||||
|
* TLB flush really happen _after_ code has been modified.
|
||||||
|
*/
|
||||||
|
barrier();
|
||||||
|
|
||||||
/* Invalidate instruction caches after code modification */
|
/* Invalidate instruction caches after code modification */
|
||||||
mtspr(SPR_ICBIR, 0x900);
|
mtspr(SPR_ICBIR, 0x900);
|
||||||
mtspr(SPR_ICBIR, 0xa00);
|
mtspr(SPR_ICBIR, 0xa00);
|
||||||
|
|
Loading…
Reference in New Issue