From 5042c3fab58810c46fc1f0f4c464e86e8b0084b4 Mon Sep 17 00:00:00 2001 From: glevand Date: Mon, 7 Oct 2013 22:13:25 +0200 Subject: [PATCH] implement a function which converts SPE EA to PPU EA --- spuisofs.c | 81 ++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 44 insertions(+), 37 deletions(-) diff --git a/spuisofs.c b/spuisofs.c index ed8d599..a509b8c 100644 --- a/spuisofs.c +++ b/spuisofs.c @@ -100,7 +100,7 @@ static unsigned int spuisofs_spe_virq[4]; static void *spuisofs_spe_app; static void *spuisofs_spe_arg1; static void *spuisofs_spe_arg2; -static void *spuisofs_buf; +static void *spuisofs_spe_buf; static unsigned int spuisofs_spe_slb_index; @@ -113,8 +113,8 @@ module_param(spuisofs_spe_arg1_size, ulong, 0); static unsigned long spuisofs_spe_arg2_size = 1024 * 1024; module_param(spuisofs_spe_arg2_size, ulong, 0); -static unsigned long spuisofs_buf_size = 1024 * 1024; -module_param(spuisofs_buf_size, ulong, 0); +static unsigned long spuisofs_spe_buf_size = 1024 * 1024; +module_param(spuisofs_spe_buf_size, ulong, 0); static unsigned long spuisofs_spe_trans_notify_mask = 0xf; module_param(spuisofs_spe_trans_notify_mask, ulong, 0); @@ -122,8 +122,8 @@ module_param(spuisofs_spe_trans_notify_mask, ulong, 0); static unsigned long spuisofs_spe_resource_id = 6; module_param(spuisofs_spe_resource_id, ulong, 0); -static int spuisofs_buf_addr_32bit = 0; -module_param(spuisofs_buf_addr_32bit, int, 0); +static int spuisofs_spe_buf_addr_32bit = 0; +module_param(spuisofs_spe_buf_addr_32bit, int, 0); /* * spuisofs_spe_regs_read @@ -302,15 +302,16 @@ static ssize_t spuisofs_info_read(struct file *file, char __user *buffer, { char buf[256]; size_t len; - unsigned long buf_addr; + unsigned long spe_buf_addr; - buf_addr = (unsigned long) spuisofs_buf; - if (spuisofs_buf_addr_32bit) - buf_addr &= 0xfffffffful; + spe_buf_addr = (unsigned long) spuisofs_spe_buf; + + if (spuisofs_spe_buf_addr_32bit) + spe_buf_addr &= 0xfffffffful; len = sprintf(buf, "arg1 %lx\narg2 %lx\nbuf %lx\n", (unsigned long) spuisofs_spe_arg1, (unsigned long) spuisofs_spe_arg2, - buf_addr); + spe_buf_addr); return simple_read_from_buffer(buffer, size, pos, buf, len); } @@ -558,7 +559,7 @@ static int spuisofs_fill_super(struct super_block *sb, void *data, int silent) { "app", &spuisofs_mem_fops, 0666, spuisofs_spe_app_size, 0, spuisofs_spe_app, }, { "arg1", &spuisofs_mem_fops, 0666, spuisofs_spe_arg1_size, 0, spuisofs_spe_arg1, }, { "arg2", &spuisofs_mem_fops, 0666, spuisofs_spe_arg2_size, 0, spuisofs_spe_arg2, }, - { "buf", &spuisofs_mem_fops, 0666, spuisofs_buf_size, 0, spuisofs_buf, }, + { "buf", &spuisofs_mem_fops, 0666, spuisofs_spe_buf_size, 0, spuisofs_spe_buf, }, { "info", &spuisofs_info_fops, 0444, 0, 0, NULL, }, { "run", &spuisofs_run_fops, 0222, sizeof(struct spuisofs_run_args), 0, NULL, }, { "cont", &spuisofs_cont_fops, 0222, 0, 0, NULL, }, @@ -596,12 +597,32 @@ static int spuisofs_fill_super(struct super_block *sb, void *data, int silent) } /* + * spuisofs_spe_ea_to_kernel_ea + */ +static unsigned long spuisofs_spe_ea_to_kernel_ea(unsigned long spe_ea) +{ + unsigned long kernel_ea, spe_buf_addr; + + kernel_ea = spe_ea; + + if (!spuisofs_spe_buf_addr_32bit) + return (kernel_ea); + + spe_buf_addr = (unsigned long) spuisofs_spe_buf & 0xfffffffful; + + if ((spe_ea >= spe_buf_addr) && (spe_ea < (spe_buf_addr + spuisofs_spe_buf_size))) + kernel_ea = (unsigned long) spuisofs_spe_buf + (spe_buf_addr - spe_ea); + + return (kernel_ea); +} + +/* * spuisofs_spe_interrupt */ static irqreturn_t spuisofs_spe_interrupt(int irq, void *data) { u64 status; - u64 ea, ea_full, dsisr, esid, vsid, buf_addr; + u64 ea, kernel_ea, dsisr, esid, vsid; u64 puint_mb_R; u32 spu_status_R; u64 spe_execution_status; @@ -636,19 +657,12 @@ static irqreturn_t spuisofs_spe_interrupt(int irq, void *data) if (status & CLASS1_SEGMENT_FAULT_INTR) { ea = in_be64(&spuisofs_spe_shadow->mfc_dar_RW); - ea_full = ea; - - buf_addr = (u64) spuisofs_buf; - if (spuisofs_buf_addr_32bit) - buf_addr &= 0xfffffffful; - - if ((ea >= buf_addr) && (ea < (buf_addr + spuisofs_buf_size))) - ea_full = (u64) spuisofs_buf + (buf_addr - ea); + kernel_ea = spuisofs_spe_ea_to_kernel_ea(ea); esid = (ea & ESID_MASK) | SLB_ESID_V; - vsid = (get_kernel_vsid(ea_full, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) | SLB_VSID_KERNEL | MMU_PAGE_4K; + vsid = (get_kernel_vsid(kernel_ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) | SLB_VSID_KERNEL | MMU_PAGE_4K; - printk(KERN_INFO"spuisofs: data segment fault at %llx (%llx)\n", ea, ea_full); + printk(KERN_INFO"spuisofs: data segment fault at %llx (%llx)\n", ea, kernel_ea); err = lv1_undocumented_function_62(spuisofs_spe_id, 0, spuisofs_spe_slb_index, esid, vsid); if (err) { @@ -663,20 +677,13 @@ static irqreturn_t spuisofs_spe_interrupt(int irq, void *data) if (status & CLASS1_STORAGE_FAULT_INTR) { ea = in_be64(&spuisofs_spe_shadow->mfc_dar_RW); - ea_full = ea; + kernel_ea = spuisofs_spe_ea_to_kernel_ea(ea); dsisr = in_be64(&spuisofs_spe_shadow->mfc_dsisr_RW); - buf_addr = (u64) spuisofs_buf; - if (spuisofs_buf_addr_32bit) - buf_addr &= 0xfffffffful; - - if ((ea >= buf_addr) && (ea < (buf_addr + spuisofs_buf_size))) - ea_full = (u64) spuisofs_buf + (buf_addr - ea); - - printk(KERN_INFO"spuisofs: data storage fault at %llx (%llx)\n", ea, ea_full); + printk(KERN_INFO"spuisofs: data storage fault at %llx (%llx)\n", ea, kernel_ea); if (dsisr & MFC_DSISR_PTE_NOT_FOUND) { - err = hash_page(ea_full, _PAGE_PRESENT, 0x300); + err = hash_page(kernel_ea, _PAGE_PRESENT, 0x300); if (err) { printk(KERN_INFO"spuisofs: hash_page failed with %d\n", err); goto out; @@ -958,13 +965,13 @@ static struct dentry *spuisofs_mount(struct file_system_type *fs_type, memset(spuisofs_spe_arg2, 0, spuisofs_spe_arg2_size); - spuisofs_buf = vmalloc_user(spuisofs_buf_size); - if (!spuisofs_buf) { + spuisofs_spe_buf = vmalloc_user(spuisofs_spe_buf_size); + if (!spuisofs_spe_buf) { err = -ENOMEM; goto fail_free_spe_arg2; } - memset(spuisofs_buf, 0, spuisofs_buf_size); + memset(spuisofs_spe_buf, 0, spuisofs_spe_buf_size); root = mount_single(fs_type, flags, data, spuisofs_fill_super); if (IS_ERR(root)) { @@ -976,7 +983,7 @@ static struct dentry *spuisofs_mount(struct file_system_type *fs_type, fail_free_buf: - vfree(spuisofs_buf); + vfree(spuisofs_spe_buf); fail_free_spe_arg2: @@ -1007,7 +1014,7 @@ static void spuisofs_kill_sb(struct super_block *sb) vfree(spuisofs_spe_app); vfree(spuisofs_spe_arg1); vfree(spuisofs_spe_arg2); - vfree(spuisofs_buf); + vfree(spuisofs_spe_buf); spuisofs_destruct_spe(); } -- 2.11.4.GIT