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
1 changed files with 14 additions and 3 deletions
|
@ -167,15 +167,26 @@ void __init paging_init(void)
|
|||
unsigned long *dtlb_vector = __va(0x900);
|
||||
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);
|
||||
*dtlb_vector = ((unsigned long)&dtlb_miss_handler -
|
||||
(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 */
|
||||
mtspr(SPR_ICBIR, 0x900);
|
||||
mtspr(SPR_ICBIR, 0xa00);
|
||||
|
|
Loading…
Reference in a new issue