static void ipu_add_wired_entry(unsigned long pid, unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask) { unsigned long flags; unsigned long wired; unsigned long old_pagemask; unsigned long old_ctx; struct task_struct *g, *p; /* We will lock an 4MB page size entry to map the 4MB reserved IPU memory */ wired = read_c0_wired(); if (wired) return; do_each_thread(g, p) { if (p->pid == pid ) g_asid = p->mm->context[0]; } while_each_thread(g, p); local_irq_save(flags); entrylo0 = entrylo0 >> 6; /* PFN */ entrylo0 |= 0x6 | (0 << 3); /* Write-through cacheable, dirty, valid */ /* Save old context and create impossible VPN2 value */ old_ctx = read_c0_entryhi() & 0xff; old_pagemask = read_c0_pagemask(); wired = read_c0_wired(); write_c0_wired(wired + 1); write_c0_index(wired); BARRIER; entryhi &= ~0xff; /* new add, 20070906 */ entryhi |= g_asid; /* new add, 20070906 */ // entryhi |= old_ctx; /* new add, 20070906 */ write_c0_pagemask(pagemask); write_c0_entryhi(entryhi); write_c0_entrylo0(entrylo0); write_c0_entrylo1(entrylo1); BARRIER; tlb_write_indexed(); BARRIER; write_c0_entryhi(old_ctx); BARRIER; write_c0_pagemask(old_pagemask); local_flush_tlb_all(); local_irq_restore(flags); #if defined(DEBUG) printk("\nold_ctx=%03d\n", old_ctx); show_tlb(); #endif }
static void ipu_add_wired_entry(unsigned long pid, unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask) { unsigned long flags; unsigned long wired; unsigned long old_pagemask; unsigned long old_ctx; struct task_struct *g, *p; do_each_thread(g, p) { if (p->pid == pid ) g_asid = p->mm->context[0]; } while_each_thread(g, p); local_irq_save(flags); /* Save old context and create impossible VPN2 value */ old_ctx = read_c0_entryhi() & 0xff; old_pagemask = read_c0_pagemask(); wired = read_c0_wired(); write_c0_wired(wired + 1); write_c0_index(wired); BARRIER; entryhi &= ~0xff; /* new add, 20070906 */ entryhi |= g_asid; /* new add, 20070906 */ // entryhi |= old_ctx; /* new add, 20070906 */ write_c0_pagemask(pagemask); write_c0_entryhi(entryhi); write_c0_entrylo0(entrylo0); write_c0_entrylo1(entrylo1); BARRIER; tlb_write_indexed(); BARRIER; write_c0_entryhi(old_ctx); BARRIER; write_c0_pagemask(old_pagemask); local_flush_tlb_all(); local_irq_restore(flags); #if defined(DEBUG) printk("\nold_ctx=%03d\n", old_ctx); show_tlb(); #endif }
static int ipu_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { int len = 0; /* read as binary */ unsigned int * pint; pint = (unsigned int *) (page+len); if ( ipu_buf_cnt >= IPU_BUF_MAX ) { /* failed alloc mem, rturn 0 */ printk("no free buffer.\n"); *pint = 0; } else *pint = (unsigned int )ipu_buf[ipu_buf_cnt].addr; /* phys addr */ len += sizeof(unsigned int); #if defined(DEBUG) show_tlb(); #endif return len; }
static int ipu_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) { unsigned int val ; int cnt,i; char buf[12]; unsigned long pid, entrylo0, entrylo1, entryhi, pagemask; #if defined(DEBUG) printk("ipu write count=%u\n", count); #endif if (count == 41) { for (i=0;i<12;i++) buf[i]=0; strncpy(buf, buffer+8*0, 8); pid = simple_strtoul(buf, 0, 16); for (i=0;i<12;i++) buf[i]=0; strncpy(buf, buffer+8*1, 8); entrylo0 = simple_strtoul(buf, 0, 16); for (i=0;i<12;i++) buf[i]=0; strncpy(buf, buffer+8*2, 8); entrylo1 = simple_strtoul(buf, 0, 16); for (i=0;i<12;i++) buf[i]=0; strncpy(buf, buffer+8*3, 8); entryhi = simple_strtoul(buf, 0, 16); for (i=0;i<12;i++) buf[i]=0; strncpy(buf, buffer+8*4, 8); pagemask = simple_strtoul(buf, 0, 16); #if defined(DEBUG) printk("pid=0x%08x, entrylo0=0x%08x, entrylo1=0x%08x, entryhi=0x%08x, pagemask=0x%08x\n", pid, entrylo0, entrylo1, entryhi, pagemask); #endif ipu_add_wired_entry( pid, entrylo0, entrylo1, entryhi, pagemask); return 41; } else if ( count <= 9 ) { for (i=0;i<12;i++) buf[i]=0; strncpy(buf, buffer, 8); val = simple_strtoul(buf, 0, 16); } else if (count == 44) { for (i = 0; i < 12; i++) buf[i] = 0; strncpy(buf, buffer, 10); pid = simple_strtoul(buf, 0, 16); for (i = 0; i < 12; i++) buf[i] = 0; strncpy(buf, buffer + 11, 10); entryhi = simple_strtoul(buf, 0, 16);//vaddr for (i = 0; i < 12; i++) buf[i] = 0; strncpy(buf, buffer + 22, 10); entrylo0 = simple_strtoul(buf, 0, 16);//paddr for (i = 0; i < 12; i++) buf[i] = 0; strncpy(buf, buffer + 33, 10); pagemask = simple_strtoul(buf, 0, 16); pagemask = 0x3ff << 13; /* Fixed to 4MB page size */ //pagemask = 0xfff << 13; /* Fixed to 16MB page size */ ipu_add_wired_entry(pid, entrylo0, 0, entryhi, pagemask); return 44; } else if (count == 12) { printk("\necho release tlb > /proc/jz/ipu\n"); ipu_del_wired_entry(); return 12; } else { printk("ipu write count error, count=%d\n.", (unsigned int)count); return -1; } /* val: 1-9, page_shift, val>= 10: ipu_buf.addr */ if ( val == 0 ) { /* debug, print ipu_buf info */ for ( cnt=0; cnt<IPU_BUF_MAX; ++cnt) printk("ipu_buf[%d]: addr=0x%08x, page_shift=%d\n", cnt, ipu_buf[cnt].addr, ipu_buf[cnt].page_shift ); #if defined(DEBUG) show_tlb(); #endif } else if ( 0< val && val < 10 ) { ipu_buf_get(val); } else if ( val == 0xff ) { /* 255: free all ipu_buf */ for ( cnt=0; cnt<IPU_BUF_MAX; ++cnt ) { ipu_buf_free(ipu_buf[cnt].addr); } } else { ipu_buf_free(val); } return count; }
static int tlb_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { show_tlb(); return 0; }