For a full task switch, the task structures are usually located in kernel memory, which is mapped into the address space of every task.
Threads of a task all share a common address space, so there is no need to reload CR3. The thread structures should be mapped into the address space also. Details depend on whether your threading implementation is in kernel space or user space.
Multitasking...
-
BI lazy
Re:Multitasking...
To avoid misunderstanding, use clear language *Mister* FlashBurn!
To solve your problem do as nullify recommends: map kernel space into each process adress space.
further - a process may own a *page directory*
stay safe
To solve your problem do as nullify recommends: map kernel space into each process adress space.
further - a process may own a *page directory*
stay safe
-
kaos
Re:Multitasking...
I think that the following method could be used to determine whether or not a hardware task switch that does not change the value of CR3 would cause a TLB flush:
1. Enable paging, etc.
2. Do a task switch via interrupt though a task gate in the IDT without changing the value of CR3.
3. Immediately do a TLB lookup on the address of the instruction that actually triggered the interrupt. The procedure for doing TLB lookups is described in 10.6.3 of the 80386 Programmer's Reference Manual.
4. If the TLB entry exists then the TLB has not been flushed. Otherwise, the TLB has been flushed.
This is only intended to apply to the 80386 processor.
Any thoughts?
1. Enable paging, etc.
2. Do a task switch via interrupt though a task gate in the IDT without changing the value of CR3.
3. Immediately do a TLB lookup on the address of the instruction that actually triggered the interrupt. The procedure for doing TLB lookups is described in 10.6.3 of the 80386 Programmer's Reference Manual.
4. If the TLB entry exists then the TLB has not been flushed. Otherwise, the TLB has been flushed.
This is only intended to apply to the 80386 processor.
Any thoughts?
- Pype.Clicker
- Member

- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Multitasking...
another trick would be to modify one of the page entries just after you switched to another task (for instance making it not present), and then try to reference it without having done the required pginvld command on that page.
1. if the task switch did not flush the TLB (and if the page has been referenced before the switch and not yet referenced in the new task), the old entry should still be there and your reference is correct.
2. if the task switch did flush the TLB, the MMU will reload the new entry and discover it is not a present page, so you'll get a page fault.
Afaik, this test should work on any processor.
1. if the task switch did not flush the TLB (and if the page has been referenced before the switch and not yet referenced in the new task), the old entry should still be there and your reference is correct.
2. if the task switch did flush the TLB, the MMU will reload the new entry and discover it is not a present page, so you'll get a page fault.
Afaik, this test should work on any processor.
-
kaos
Re:Multitasking...
Pype.Clicker: I thought your idea was a good one, so I wrote the following test:Pype.Clicker wrote: another trick would be to modify one of the page entries just after you switched to another task (for instance making it not present), and then try to reference it without having done the required pginvld command on that page.
1. if the task switch did not flush the TLB (and if the page has been referenced before the switch and not yet referenced in the new task), the old entry should still be there and your reference is correct.
2. if the task switch did flush the TLB, the MMU will reload the new entry and discover it is not a present page, so you'll get a page fault.
Afaik, this test should work on any processor.
Code: Select all
#define TLB_TEST_PAGE_VADDR ((void *) 0x10000000)
void tlb_test_interrupt(void)
{
char *p = TLB_TEST_PAGE_VADDR;
*p = 1;
kprintf("The test was successful!\n");
for(;;);
}
void tlb_test(void)
{
void *page = page_alloc();
thread_t *t;
char *stack = page_alloc();
char *p = TLB_TEST_PAGE_VADDR;
uint ptdi, ptei; /* pagetable directory and entry indexes */
machine_pagetable_t *pagetable;
/* install the interrupt */
t = systhread_new (stack + PAGE_SIZE - 4, tlb_test_interrupt);
I386_GATE_INIT_SYS (idt[0xff], t->tss_sel, 0);
/* map the page */
page_map(kernel_pdir, page, TLB_TEST_PAGE_VADDR, 1, 0);
__asm__ __volatile__ ("mov %cr3, %eax");
__asm__ __volatile__ ("mov %eax,%cr3");
/* access *p just to make sure that everything is cool */
*p = 1;
/* do the test */
kprintf("Time for the TLB flush test!\n");
/* unmap the page, accessing *p at the last possible moment */
ptdi = I386_VADDR_GET_PTDI (p);
ptei = I386_VADDR_GET_PTEI (p);
pagetable = I386_PTE_GET_PADDR (kernel_pdir[ptdi]);
*p = 0;
I386_PTE_CLEAR_PRESENT (pagetable[ptei]);
/* interrupt */
__asm__ __volatile__ ("int $0xff");
}
[attachment deleted by admin]
- Pype.Clicker
- Member

- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact: