Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- dosent work atm
- dumps every other
- feel free to modify
- /*
- * SPP verifier direct
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published
- * by the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/proc_fs.h>
- #include <linux/workqueue.h>
- #include <linux/mmzone.h>
- #include <linux/io.h>
- #include <linux/mm.h>
- #include <linux/file.h>
- #include <linux/fs.h>
- #include <linux/fcntl.h>
- #include <linux/syscalls.h>
- #include <asm/uaccess.h>
- #include <asm/lv1call.h>
- #include "spu.h"
- #define PROC_ROOT "spp_verifier_direct"
- #define PROC_METLDR "metldr"
- #define PROC_ISOLDR "isoldr"
- #define PROC_RVKPRG "rvkprg"
- #define PROC_EID0 "eid0"
- #define PROC_SPU "spu"
- #define PROC_DEBUG "debug"
- #define PROC_RUN "run"
- #define PROC_PROFILE "profile"
- #define METLDR_PAGE_ORDER 4
- #define ISOLDR_PAGE_ORDER 5
- #define RVKPRG_PAGE_ORDER 0
- #define EID0_PAGE_ORDER 0
- #define SPU_PAGE_ORDER 5
- #define PROFILE_PAGE_ORDER 2
- #define LS_ARGS_PAGE_ORDER 0
- #define DEBUG_SIZE 4096
- #define EID0_LS_ADDR 0x3e400
- #define LDR_ARGS_LS_ADDR 0x3e800
- #define RVK_PRG_LS_ADDR 0x3f000
- /*
- * DPRINTF
- */
- #define DPRINTF(fmt, ...) \
- do { \
- if (debug_size >= (DEBUG_SIZE / 2)) \
- debug_size = 0; \
- \
- debug_size += sprintf(debug + debug_size, fmt, ## __VA_ARGS__); \
- } while (0)
- struct ldr_args {
- u64 prog_auth_id;
- u64 lpar_auth_id;
- void *spu_module;
- void *spu_module_arg1;
- u64 spu_module_arg1_size;
- void *spu_module_arg2;
- u64 spu_module_arg2_size;
- u8 res1[16];
- u64 field48;
- u8 res2[16];
- };
- static struct proc_dir_entry *proc_root;
- static struct proc_dir_entry *proc_metldr;
- static struct proc_dir_entry *proc_isoldr;
- static struct proc_dir_entry *proc_rvkprg;
- static struct proc_dir_entry *proc_eid0;
- static struct proc_dir_entry *proc_spu;
- static struct proc_dir_entry *proc_debug;
- static struct proc_dir_entry *proc_run;
- static struct proc_dir_entry *proc_profile;
- static unsigned char *metldr;
- static unsigned char *isoldr;
- static unsigned char *rvkprg;
- static unsigned char *eid0;
- static unsigned char *spu;
- static unsigned char *debug;
- static unsigned long debug_size;
- static unsigned char *profile;
- static unsigned char *ls_args;
- static struct workqueue_struct *workqueue;
- static struct work_struct work;
- static int force_exit;
- /*
- * proc_generic_open
- */
- static int proc_generic_open(struct inode *inode, struct file *file)
- {
- struct proc_dir_entry *proc = PDE(inode);
- file->private_data = proc;
- return 0;
- }
- /*
- * proc_generic_release
- */
- static int proc_generic_release(struct inode *inode, struct file *file)
- {
- return 0;
- }
- /*
- * proc_generic_read
- */
- static ssize_t proc_generic_read(struct file *file, char __user *buffer, size_t len, loff_t *off)
- {
- struct proc_dir_entry *proc = file->private_data;
- int pos;
- pos = *off;
- if ((pos >= proc->size) || !len)
- return 0;
- if ((pos + len) > proc->size)
- len = proc->size - pos;
- if (copy_to_user(buffer, (unsigned char *) proc->data + pos, len))
- return -EFAULT;
- *off += len;
- return len;
- }
- /*
- * proc_generic_write
- */
- static ssize_t proc_generic_write(struct file *file, const char __user *buffer, size_t len, loff_t *off)
- {
- struct proc_dir_entry *proc = file->private_data;
- int pos;
- pos = *off;
- if ((pos >= proc->size) || !len)
- return 0;
- if ((pos + len) > proc->size)
- len = proc->size - pos;
- if (copy_from_user((unsigned char *) proc->data + pos, buffer, len))
- return -EFAULT;
- *off += len;
- return len;
- }
- /*
- * work_function
- */
- static void work_function(struct work_struct *work)
- {
- u64 ppe_id, vas_id;
- u64 priv2_addr, problem_phys, local_store_phys, unused, shadow_addr, spe_id;
- struct spu_shadow *shadow = NULL;
- struct spu_problem *problem = NULL;
- struct spu_priv2 *priv2 = NULL;
- u64 esid, vsid;
- u64 intr_status;
- u32 out_mbox, size;
- int res;
- memset(debug, 0, DEBUG_SIZE);
- debug_size = 0;
- lv1_get_logical_ppe_id(&ppe_id);
- lv1_get_virtual_address_space_id_of_ppe(ppe_id, &vas_id);
- DPRINTF("PPE id (0x%016llx) VAS id (0x%016llx)\n", ppe_id, vas_id);
- res = lv1_construct_logical_spe(PAGE_SHIFT, PAGE_SHIFT, PAGE_SHIFT, PAGE_SHIFT, PAGE_SHIFT,
- vas_id, 0 /* type */, &priv2_addr, &problem_phys, &local_store_phys,
- &unused, &shadow_addr, &spe_id);
- DPRINTF("lv1_construct_logical_spe (0x%08x)\n", res);
- if (res)
- return;
- DPRINTF("SPE id (0x%016llx)\n", spe_id);
- res = lv1_enable_logical_spe(spe_id, 6);
- DPRINTF("lv1_enable_logical_spe (0x%08x)\n", res);
- if (res)
- goto bad;
- res = lv1_set_spe_interrupt_mask(spe_id, 0, 0x7);
- DPRINTF("lv1_set_spe_interrupt_mask(0) (0x%08x)\n", res);
- if (res)
- goto bad;
- res = lv1_set_spe_interrupt_mask(spe_id, 1, 0xf);
- DPRINTF("lv1_set_spe_interrupt_mask(1) (0x%08x)\n", res);
- if (res)
- goto bad;
- res = lv1_set_spe_interrupt_mask(spe_id, 2, 0xf);
- DPRINTF("lv1_set_spe_interrupt_mask(2) (0x%08x)\n", res);
- if (res)
- goto bad;
- res = lv1_set_spe_privilege_state_area_1_register(spe_id, MFC_SR1, 0x10);
- DPRINTF("lv1_set_spe_privilege_state_area_1_register (0x%08x)\n", res);
- if (res)
- goto bad;
- shadow = __ioremap(shadow_addr, sizeof(*shadow), _PAGE_NO_CACHE | 3);
- if (!shadow)
- goto bad;
- problem = ioremap(problem_phys, sizeof(*problem));
- if (!problem)
- goto bad;
- priv2 = ioremap(priv2_addr, sizeof(*priv2));
- if (!priv2)
- goto bad;
- esid = (GET_ESID((unsigned long) metldr) << SID_SHIFT) | SLB_ESID_V;
- vsid = (get_kernel_vsid((unsigned long) metldr, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
- SLB_VSID_KP | SLB_VSID_L;
- DPRINTF("ea (0x%016llx) esid (0x%016llx) vsid (0x%016llx)\n", (unsigned long long) metldr, esid, vsid);
- spu_slb_invalidate_all(priv2);
- spu_slb_set_entry(priv2, 0, esid, vsid);
- priv2->spu_cfg = 0;
- eieio();
- spu_in_mbox_write_64(problem, (u64) isoldr);
- spu_sig_notify_1_2_write_64(problem, (u64) metldr);
- spu_iso_load_req_enable(priv2);
- spu_iso_load_req(problem);
- while (1) {
- if (force_exit) {
- DPRINTF("exiting\n");
- goto bad;
- }
- res = lv1_get_spe_interrupt_status(spe_id, 0, &intr_status);
- DPRINTF("lv1_get_spe_interrupt_status(0) (0x%08x)\n", res);
- if (res)
- goto bad;
- if (intr_status) {
- res = lv1_clear_spe_interrupt_status(spe_id, 0, intr_status, 0);
- DPRINTF("lv1_clear_spe_interrupt_status(0) (0x%08x)\n", res);
- if (res)
- goto bad;
- }
- res = lv1_get_spe_interrupt_status(spe_id, 1, &intr_status);
- DPRINTF("lv1_get_spe_interrupt_status(1) (0x%08x)\n", res);
- if (res)
- goto bad;
- if (intr_status) {
- res = lv1_clear_spe_interrupt_status(spe_id, 1, intr_status, 0);
- DPRINTF("lv1_clear_spe_interrupt_status(1) (0x%08x)\n", res);
- if (res)
- goto bad;
- }
- res = lv1_get_spe_interrupt_status(spe_id, 2, &intr_status);
- DPRINTF("lv1_get_spe_interrupt_status(2) (0x%08x)\n", res);
- if (res)
- goto bad;
- if (intr_status & 0x1) {
- /* mailbox interrupt */
- struct file *f = filp_open("/ls.bin", O_RDWR | O_CREAT | O_APPEND | O_SYNC, 0);
- mm_segment_t oldfs;
- oldfs = get_fs();
- set_fs (KERNEL_DS);
- size = 0;
- while(size <= 0x40000)
- {
- eieio();
- //Wait for mbox value to be written.
- while(spu_mbox_stat_intr_out_mbox_count(problem) == 0);
- out_mbox = problem->spu_out_mbox;
- //eieio(); shit.
- f->f_op->write(f,(char *) &problem->spu_out_mbox, sizeof(problem->spu_out_mbox), &f->f_pos);
- DPRINTF("\rdumped 0x%08x of 0x40000", size);
- size += 4;
- }
- set_fs(oldfs);
- filp_close(f,NULL);
- fput(f);
- goto bad;
- res = lv1_clear_spe_interrupt_status(spe_id, 2, intr_status, 0);
- DPRINTF("lv1_clear_spe_interrupt_status(2) (0x%08x)\n", res);
- if (res)
- goto bad;
- }
- if (!(problem->spu_status & 0x1))
- break;
- DPRINTF("sleep\n");
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(100);
- }
- DPRINTF("problem status (0x%08x)\n", problem->spu_status);
- bad:
- if (shadow)
- iounmap(shadow);
- if (problem) {
- spu_stop_req(problem);
- iounmap(problem);
- }
- if (priv2)
- iounmap(priv2);
- res = lv1_destruct_logical_spe(spe_id);
- DPRINTF("lv1_destruct_logical_spe (0x%08x)\n", res);
- }
- /*
- * proc_run_write
- */
- static int proc_run_write(struct file *file, const char *page, unsigned long count, void *data)
- {
- queue_work(workqueue, &work);
- return count;
- }
- static struct file_operations proc_generic_fops = {
- .owner = THIS_MODULE,
- .open = proc_generic_open,
- .release = proc_generic_release,
- .read = proc_generic_read,
- .write = proc_generic_write,
- };
- /*
- * construct_proc
- */
- static int construct_proc(void)
- {
- proc_root = proc_mkdir(PROC_ROOT, NULL);
- if (!proc_root)
- return -ENOMEM;
- proc_metldr = create_proc_entry(PROC_METLDR, S_IFREG | S_IRUGO | S_IWUSR, proc_root);
- if (!proc_metldr)
- return -ENOMEM;
- proc_metldr->proc_fops = &proc_generic_fops;
- proc_metldr->mode = S_IFREG | S_IRUGO | S_IWUSR;
- proc_metldr->uid = 0;
- proc_metldr->gid = 0;
- proc_metldr->size = (1 << METLDR_PAGE_ORDER) << PAGE_SHIFT;
- proc_metldr->data = metldr;
- proc_isoldr = create_proc_entry(PROC_ISOLDR, S_IFREG | S_IRUGO | S_IWUSR, proc_root);
- if (!proc_isoldr)
- return -ENOMEM;
- proc_isoldr->proc_fops = &proc_generic_fops;
- proc_isoldr->mode = S_IFREG | S_IRUGO | S_IWUSR;
- proc_isoldr->uid = 0;
- proc_isoldr->gid = 0;
- proc_isoldr->size = (1 << ISOLDR_PAGE_ORDER) << PAGE_SHIFT;
- proc_isoldr->data = isoldr;
- proc_rvkprg = create_proc_entry(PROC_RVKPRG, S_IFREG | S_IRUGO | S_IWUSR, proc_root);
- if (!proc_rvkprg)
- return -ENOMEM;
- proc_rvkprg->proc_fops = &proc_generic_fops;
- proc_rvkprg->mode = S_IFREG | S_IRUGO | S_IWUSR;
- proc_rvkprg->uid = 0;
- proc_rvkprg->gid = 0;
- proc_rvkprg->size = (1 << RVKPRG_PAGE_ORDER) << PAGE_SHIFT;
- proc_rvkprg->data = rvkprg;
- proc_eid0 = create_proc_entry(PROC_EID0, S_IFREG | S_IRUGO | S_IWUSR, proc_root);
- if (!proc_eid0)
- return -ENOMEM;
- proc_eid0->proc_fops = &proc_generic_fops;
- proc_eid0->mode = S_IFREG | S_IRUGO | S_IWUSR;
- proc_eid0->uid = 0;
- proc_eid0->gid = 0;
- proc_eid0->size = (1 << EID0_PAGE_ORDER) << PAGE_SHIFT;
- proc_eid0->data = eid0;
- proc_spu = create_proc_entry(PROC_SPU, S_IFREG | S_IRUGO | S_IWUSR, proc_root);
- if (!proc_spu)
- return -ENOMEM;
- proc_spu->proc_fops = &proc_generic_fops;
- proc_spu->mode = S_IFREG | S_IRUGO | S_IWUSR;
- proc_spu->uid = 0;
- proc_spu->gid = 0;
- proc_spu->size = (1 << SPU_PAGE_ORDER) << PAGE_SHIFT;
- proc_spu->data = spu;
- proc_debug = create_proc_entry(PROC_DEBUG, S_IFREG | S_IRUGO | S_IWUSR, proc_root);
- if (!proc_debug)
- return -ENOMEM;
- proc_debug->proc_fops = &proc_generic_fops;
- proc_debug->mode = S_IFREG | S_IRUGO | S_IWUSR;
- proc_debug->uid = 0;
- proc_debug->gid = 0;
- proc_debug->size = DEBUG_SIZE;
- proc_debug->data = debug;
- proc_run = create_proc_entry(PROC_RUN, S_IFREG | S_IRUGO | S_IWUSR, proc_root);
- if (!proc_run)
- return -ENOMEM;
- proc_run->write_proc = proc_run_write;
- proc_profile = create_proc_entry(PROC_PROFILE, S_IFREG | S_IRUGO | S_IWUSR, proc_root);
- if (!proc_profile)
- return -ENOMEM;
- proc_profile->proc_fops = &proc_generic_fops;
- proc_profile->mode = S_IFREG | S_IRUGO | S_IWUSR;
- proc_profile->uid = 0;
- proc_profile->gid = 0;
- proc_profile->size = (1 << PROFILE_PAGE_ORDER) << PAGE_SHIFT;
- proc_profile->data = profile;
- return 0;
- }
- /*
- * destruct_proc
- */
- static void destruct_proc(void)
- {
- if (proc_profile)
- remove_proc_entry(PROC_PROFILE, proc_root);
- if (proc_run)
- remove_proc_entry(PROC_RUN, proc_root);
- if (proc_debug)
- remove_proc_entry(PROC_DEBUG, proc_root);
- if (proc_spu)
- remove_proc_entry(PROC_SPU, proc_root);
- if (proc_eid0)
- remove_proc_entry(PROC_EID0, proc_root);
- if (proc_rvkprg)
- remove_proc_entry(PROC_RVKPRG, proc_root);
- if (proc_isoldr)
- remove_proc_entry(PROC_ISOLDR, proc_root);
- if (proc_metldr)
- remove_proc_entry(PROC_METLDR, proc_root);
- remove_proc_entry(PROC_ROOT, NULL);
- }
- /*
- * spp_verifier_direct_init
- */
- static int __init spp_verifier_direct_init(void)
- {
- int res;
- metldr = (unsigned char *) __get_free_pages(GFP_KERNEL, METLDR_PAGE_ORDER);
- if (!metldr) {
- res = -ENOMEM;
- goto bad1;
- }
- memset(metldr, 0, (1 << METLDR_PAGE_ORDER) << PAGE_SHIFT);
- isoldr = (unsigned char *) __get_free_pages(GFP_KERNEL, ISOLDR_PAGE_ORDER);
- if (!isoldr) {
- res = -ENOMEM;
- goto bad2;
- }
- memset(isoldr, 0, (1 << ISOLDR_PAGE_ORDER) << PAGE_SHIFT);
- rvkprg = (unsigned char *) __get_free_pages(GFP_KERNEL, RVKPRG_PAGE_ORDER);
- if (!rvkprg) {
- res = -ENOMEM;
- goto bad3;
- }
- memset(rvkprg, 0, (1 << RVKPRG_PAGE_ORDER) << PAGE_SHIFT);
- eid0 = (unsigned char *) __get_free_pages(GFP_KERNEL, EID0_PAGE_ORDER);
- if (!eid0) {
- res = -ENOMEM;
- goto bad4;
- }
- memset(eid0, 0, (1 << EID0_PAGE_ORDER) << PAGE_SHIFT);
- spu = (unsigned char *) __get_free_pages(GFP_KERNEL, SPU_PAGE_ORDER);
- if (!spu) {
- res = -ENOMEM;
- goto bad5;
- }
- memset(spu, 0, (1 << SPU_PAGE_ORDER) << PAGE_SHIFT);
- debug = kzalloc(DEBUG_SIZE, GFP_KERNEL);
- if (!debug) {
- res = -ENOMEM;
- goto bad6;
- }
- profile = (unsigned char *) __get_free_pages(GFP_KERNEL, PROFILE_PAGE_ORDER);
- if (!profile) {
- res = -ENOMEM;
- goto bad7;
- }
- memset(profile, 0, (1 << PROFILE_PAGE_ORDER) << PAGE_SHIFT);
- ls_args = (unsigned char *) __get_free_pages(GFP_KERNEL, LS_ARGS_PAGE_ORDER);
- if (!ls_args) {
- res = -ENOMEM;
- goto bad8;
- }
- memset(ls_args, 0, (1 << LS_ARGS_PAGE_ORDER) << PAGE_SHIFT);
- res = construct_proc();
- if (res)
- goto bad9;
- INIT_WORK(&work, work_function);
- workqueue = create_singlethread_workqueue("spp_verifier_direct_wq");
- if (!workqueue) {
- res = -ENOMEM;
- goto bad9;
- }
- return 0;
- bad9:
- destruct_proc();
- free_pages((unsigned long) ls_args, LS_ARGS_PAGE_ORDER);
- bad8:
- free_pages((unsigned long) profile, PROFILE_PAGE_ORDER);
- bad7:
- kfree(debug);
- bad6:
- free_pages((unsigned long) spu, SPU_PAGE_ORDER);
- bad5:
- free_pages((unsigned long) eid0, EID0_PAGE_ORDER);
- bad4:
- free_pages((unsigned long) rvkprg, RVKPRG_PAGE_ORDER);
- bad3:
- free_pages((unsigned long) isoldr, ISOLDR_PAGE_ORDER);
- bad2:
- free_pages((unsigned long) metldr, METLDR_PAGE_ORDER);
- bad1:
- return res;
- }
- /*
- * spp_verifier_direct_exit
- */
- static void __exit spp_verifier_direct_exit(void)
- {
- force_exit = 1;
- destroy_workqueue(workqueue);
- destruct_proc();
- if (metldr)
- free_pages((unsigned long) metldr, METLDR_PAGE_ORDER);
- if (isoldr)
- free_pages((unsigned long) isoldr, ISOLDR_PAGE_ORDER);
- if (rvkprg)
- free_pages((unsigned long) rvkprg, RVKPRG_PAGE_ORDER);
- if (eid0)
- free_pages((unsigned long) eid0, EID0_PAGE_ORDER);
- if (spu)
- free_pages((unsigned long) spu, SPU_PAGE_ORDER);
- if (debug)
- kfree(debug);
- if (profile)
- free_pages((unsigned long) profile, PROFILE_PAGE_ORDER);
- if (ls_args)
- free_pages((unsigned long) ls_args, LS_ARGS_PAGE_ORDER);
- }
- module_init(spp_verifier_direct_init);
- module_exit(spp_verifier_direct_exit);
- MODULE_LICENSE("GPL");
- MODULE_DESCRIPTION("SPP verifier direct");
- MODULE_AUTHOR("glevand");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement