attached a patch, it may be more clear to understand what I have done. To cause a page fault there is a need to compile the kernel with 8KB stack, and use the following module and application: the module is a char device "my_device", the application opens a fd to the module and call ioctl, the module respond in calling to an overloaded stack function which cause a page fault. the task gate is being set dynamically by the ioctl sys_call. #include #include #include #include #include #include #include #include #include #include #include int simple_open (struct inode *inode, struct file *filp); int simple_release(struct inode *inode, struct file *filp); int simple_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); static int simple_major = 0; //extern void my_set_task_gate(unsigned int n, unsigned int gdt); //extern void my_set_page_fault_intr_gate(); struct file_operations simple_nopage_ops = { open: simple_open, release: simple_release, ioctl: simple_ioctl }; struct file_operations *simple_fops = { &simple_nopage_ops, }; int simple_open (struct inode *inode, struct file *filp) { filp->f_op = simple_fops; filp->private_data = 0; return 0; } int simple_release(struct inode *inode, struct file *filp) { printk(KERN_INFO "Driver: simple release\n"); return 0; } /* declare a stack that is larger then a PAGE_SIZE */ static void call_overloaded_stack(void) { char buff[1420]; char buff1[1420]; char buff2[1500]; printk(KERN_INFO "overloaded stack called\n"); buff[1400] = 1; buff1[1400] = 1; buff2[1450] = 1; } /* cause a page fault by calling to call_overloaded_stack() method */ int simple_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { printk(KERN_INFO "Driver: Pre simple ioctl\n"); /* set task gate */ // my_set_task_gate(14, GDT_ENTRY_PAGE_FAULT_TSS); /* it is being set by the ioctl sys_call */ call_overloaded_stack(); /* return to interrupt gate */ // my_set_page_fault_intr_gate(); return 0; } static int __init mm_init(void) { int result; printk("Driver: initialized\n"); result = register_chrdev(simple_major, "my_device", &simple_nopage_ops); if (result < 0) { printk(KERN_WARNING "Driver: my_device: unable to get major %d\n", simple_major); return result; } if (simple_major == 0) simple_major = result; return 0; } static void __exit mm_exit(void) { printk("Driver: exited\n"); unregister_chrdev(simple_major, "my_device"); } MODULE_AUTHOR("Eliad Lubovsky"); MODULE_DESCRIPTION("Memory Test"); MODULE_LICENSE("GPL"); module_init(mm_init); module_exit(mm_exit); /***********************************************************/ Application: open device and implement ioctl to cause a page fault by an overloaded stack. #include #include #include #include #include #include #include int main(int argc, char ** argv) { int ret; unsigned int i=0; int fd = open("/dev/my_device", O_RDWR); if(fd<0) { printf("Failed to open my_device\n"); exit(1); } ret = ioctl(fd, 0, i); if(ret != 0) { printf("Ioctl failed\n"); exit(1); } close(fd); return 0; } On Thu, 2005-06-30 at 10:11, Ingo Molnar wrote: > * eliad lubovsky wrote: > > > How do I clear the 'busy' bit? > > I set my TSS descriptor with > > __set_tss_desc(cpu, GDT_ENTRY_PAGE_FAULT_TSS, &pagefault_tss); > > i suspect you have to clear the busy bit in the pagefault handler > itself. The CPU marks it as busy upon fault. I guess it would be OK to > just do the above __set_tss_desc() for _every_ pagefault, that too will > clear the busy bit, but you are probably better off just clearing that > bit manually: > > cpu_gdt_table[cpu][GDT_ENTRY_TSS].b &= 0xfffffdff; > > Ingo