#include "seize6.h" int seize_major = SEIZE_MAJOR; int seize_irq = SEIZE_IRQ; int seize_quantum = SEIZE_QUANTUM; int seize_qset = SEIZE_QSET; MODULE_PARM(seize_major,"i"); int seize_open(struct inode *inode, struct file *filp) { outb(SetUp, i8255ctl); outb(HIGH, TR_ENB); printk("<1>seize: BYU Halting routine enabled\n"); outb(HIGH, 0x308); MOD_INC_USE_COUNT; return (0); } int seize_release(struct inode *inode, struct file *filp) { outb(HIGH, 0x310); outb(LOW, TR_ENB); printk("<1>seize: BYU Halting routine disabled\n"); MOD_DEC_USE_COUNT; return (0); } int seize_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { int err = 0, tmp, size = _IOC_SIZE(cmd); printk("seize: in ioctl handler, cmd == %d\n", cmd); if (_IOC_TYPE(cmd) != SEIZE_IOC_MAGIC) return -EINVAL; if (_IOC_NR(cmd) > SEIZE_IOC_MAXNR) return -EINVAL; if (_IOC_DIR(cmd) & _IOC_READ) err = verify_area(VERIFY_WRITE, (void *)arg, size); else if (_IOC_DIR(cmd) & _IOC_WRITE) err = verify_area(VERIFY_READ, (void *)arg, size); if (err) return err; switch (cmd) { case SEIZE_SET_CACHE: seize_quantum = arg; if (seize_quantum == 0) { __asm__("pushl %eax\n" "pushl %ecx\n" "pushl %edx\n" "cli\n" "movl %cr0,%eax\n" "orl $1073741824,%eax\n" "andl $-536870913,%eax\n" "movl %eax,%cr0\n" "wbinvd\n" "movl $767,%ecx\n" "rdmsr\n" "andl $-2049,%eax\n" "wrmsr\n" "sti\n" "popl %edx\n" "popl %ecx\n" "popl %eax\n"); printk("seize: disabled cache.\n"); } else if (seize_quantum == 1) { __asm__("pushl %eax\n" "pushl %ecx\n" "pushl %edx\n" "cli\n" "movl $767,%ecx\n" "rdmsr\n" "orl $2048,%eax\n" "wrmsr\n" "movl %cr0,%eax\n" "andl $-1073741825,%eax\n" "movl %eax,%cr0\n" "sti\n" "popl %edx\n" "popl %ecx\n" "popl %eax\n"); printk("seize: enabled cache.\n"); } break; default: return -EINVAL; } return 0; } struct file_operations seize_fops = { NULL, // lseek NULL, // read NULL, // write NULL, // readdir NULL, // poll seize_ioctl, // ioctl NULL, // mmap seize_open, // open NULL, // flush seize_release, // release NULL, // fsync NULL, // fasync // nothing more, fill with NULLs }; void seize_interrupt(int ivn, void *dev_id, struct pt_regs *regs) { unsigned long flags; unsigned char t; #ifdef SAFE_IRQ save_flags(flags); // #endif // printk(KERN_INFO "seize: interrupt received\n"); cli(); // disable interrupts if ((inb(TR_CONT)&0x02)) { // printk(KERN_INFO "seize: sending HIGH to SEIZED\n"); outb(HIGH, SEIZED); while((inb(TR_CONT)&0x02)); // wait for interrupt to go Low // printk(KERN_INFO "seize: entering seizure\n"); while(!(inb(TR_CONT)&0x02)); // wait for ENABLE // printk(KERN_INFO "seize: leaving seizure\n"); // printk(KERN_INFO "seize: sending LOW to SEIZED\n"); outb(LOW, SEIZED); } #ifdef SAFE_IRQ restore_flags(flags); #else sti(); #endif // printk(KERN_INFO "seize: leaving interrupt handler\n"); } int init_module(void) { int result; outb(SetUp, i8255ctl); outb(LOW, TR_ENB); outb(LOW, SEIZED); printk(KERN_INFO "seize: %x was sent %x\n",i8255ctl,SetUp); printk(KERN_INFO "seize: %x was sent %x\n",TR_ENB,LOW); printk(KERN_INFO "seize: %x was sent %x\n",SEIZED,LOW); // request IO port region request_region(BaseAddr,8,"seize"); // register the device result = register_chrdev(seize_major, "seize", &seize_fops); if (result < 0) { printk(KERN_WARNING "seize: can't get major %d\n",seize_major); return result; } seize_major = result; // request the irq result = request_irq(seize_irq, seize_interrupt, SA_INTERRUPT, "seize", NULL); if (result) { printk(KERN_INFO "seize: can't get assigned irq %i\n", seize_irq); seize_irq = -1; } //else { // enable interrupt // outb(0x10,BaseAddr+2); //} printk("<1>seize: BYU Halting module loaded, halting not enabled\n"); return 0; } void cleanup_module(void) { int result; if (seize_irq >= 0) free_irq(seize_irq, NULL); result = unregister_chrdev(seize_major, "seize"); release_region(BaseAddr,8); if (result < 0) printk("seize: Error unregistering device: %d\n",result); printk("<1>seize: BYU Halting module unloaded\n"); }