Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 24607
b: refs/heads/master
c: 6df10a8
h: refs/heads/master
i:
  24605: bff9ed6
  24603: 3c5e087
  24599: 5a835a8
  24591: 9ef0676
  24575: 9c716ca
v: v3
  • Loading branch information
Mark Nutter authored and Paul Mackerras committed Mar 27, 2006
1 parent a8e2fef commit ea489a4
Show file tree
Hide file tree
Showing 8 changed files with 257 additions and 13 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a33a7d7309d79656bc19a0e96fc4547a1633283e
refs/heads/master: 6df10a82f8de89c66eb91c371d62d76e87b2cbba
5 changes: 5 additions & 0 deletions trunk/arch/powerpc/platforms/cell/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,9 @@ config SPU_FS
Units on machines implementing the Broadband Processor
Architecture.

config SPUFS_MMAP
bool
depends on SPU_FS && SPARSEMEM && !PPC_64K_PAGES
default y

endmenu
5 changes: 5 additions & 0 deletions trunk/arch/powerpc/platforms/cell/spu_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,11 @@ static int __init spu_map_device(struct spu *spu, struct device_node *spe)
if (!spu->local_store)
goto out;

prop = get_property(spe, "problem", NULL);
if (!prop)
goto out_unmap;
spu->problem_phys = *(unsigned long *)prop;

spu->problem= map_spe_prop(spe, "problem");
if (!spu->problem)
goto out_unmap;
Expand Down
18 changes: 15 additions & 3 deletions trunk/arch/powerpc/platforms/cell/spufs/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#include <asm/spu_csa.h>
#include "spufs.h"

struct spu_context *alloc_spu_context(struct address_space *local_store)
struct spu_context *alloc_spu_context(void)
{
struct spu_context *ctx;
ctx = kmalloc(sizeof *ctx, GFP_KERNEL);
Expand All @@ -53,7 +53,10 @@ struct spu_context *alloc_spu_context(struct address_space *local_store)
ctx->mfc_fasync = NULL;
ctx->tagwait = 0;
ctx->state = SPU_STATE_SAVED;
ctx->local_store = local_store;
ctx->local_store = NULL;
ctx->cntl = NULL;
ctx->signal1 = NULL;
ctx->signal2 = NULL;
ctx->spu = NULL;
ctx->ops = &spu_backing_ops;
ctx->owner = get_task_mm(current);
Expand Down Expand Up @@ -110,7 +113,16 @@ void spu_release(struct spu_context *ctx)

void spu_unmap_mappings(struct spu_context *ctx)
{
unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1);
if (ctx->local_store)
unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1);
if (ctx->mfc)
unmap_mapping_range(ctx->mfc, 0, 0x4000, 1);
if (ctx->cntl)
unmap_mapping_range(ctx->cntl, 0, 0x4000, 1);
if (ctx->signal1)
unmap_mapping_range(ctx->signal1, 0, 0x4000, 1);
if (ctx->signal2)
unmap_mapping_range(ctx->signal2, 0, 0x4000, 1);
}

int spu_acquire_runnable(struct spu_context *ctx)
Expand Down
229 changes: 223 additions & 6 deletions trunk/arch/powerpc/platforms/cell/spufs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ static int
spufs_mem_open(struct inode *inode, struct file *file)
{
struct spufs_inode_info *i = SPUFS_I(inode);
file->private_data = i->i_ctx;
file->f_mapping = i->i_ctx->local_store;
struct spu_context *ctx = i->i_ctx;
file->private_data = ctx;
file->f_mapping = inode->i_mapping;
ctx->local_store = inode->i_mapping;
return 0;
}

Expand Down Expand Up @@ -86,7 +88,7 @@ spufs_mem_write(struct file *file, const char __user *buffer,
return ret;
}

#ifdef CONFIG_SPARSEMEM
#ifdef CONFIG_SPUFS_MMAP
static struct page *
spufs_mem_mmap_nopage(struct vm_area_struct *vma,
unsigned long address, int *type)
Expand Down Expand Up @@ -138,11 +140,113 @@ static struct file_operations spufs_mem_fops = {
.read = spufs_mem_read,
.write = spufs_mem_write,
.llseek = generic_file_llseek,
#ifdef CONFIG_SPARSEMEM
#ifdef CONFIG_SPUFS_MMAP
.mmap = spufs_mem_mmap,
#endif
};

#ifdef CONFIG_SPUFS_MMAP
static struct page *spufs_ps_nopage(struct vm_area_struct *vma,
unsigned long address,
int *type, unsigned long ps_offs)
{
struct page *page = NOPAGE_SIGBUS;
int fault_type = VM_FAULT_SIGBUS;
struct spu_context *ctx = vma->vm_file->private_data;
unsigned long offset = address - vma->vm_start;
unsigned long area;
int ret;

offset += vma->vm_pgoff << PAGE_SHIFT;
if (offset >= 0x4000)
goto out;

ret = spu_acquire_runnable(ctx);
if (ret)
goto out;

area = ctx->spu->problem_phys + ps_offs;
page = pfn_to_page((area + offset) >> PAGE_SHIFT);
fault_type = VM_FAULT_MINOR;
page_cache_get(page);

spu_release(ctx);

out:
if (type)
*type = fault_type;

return page;
}

static struct page *spufs_cntl_mmap_nopage(struct vm_area_struct *vma,
unsigned long address, int *type)
{
return spufs_ps_nopage(vma, address, type, 0x4000);
}

static struct vm_operations_struct spufs_cntl_mmap_vmops = {
.nopage = spufs_cntl_mmap_nopage,
};

/*
* mmap support for problem state control area [0x4000 - 0x4fff].
* Mapping this area requires that the application have CAP_SYS_RAWIO,
* as these registers require special care when read/writing.
*/
static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma)
{
if (!(vma->vm_flags & VM_SHARED))
return -EINVAL;

if (!capable(CAP_SYS_RAWIO))
return -EPERM;

vma->vm_flags |= VM_RESERVED;
vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
| _PAGE_NO_CACHE);

vma->vm_ops = &spufs_cntl_mmap_vmops;
return 0;
}
#endif

static int spufs_cntl_open(struct inode *inode, struct file *file)
{
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;

file->private_data = ctx;
file->f_mapping = inode->i_mapping;
ctx->cntl = inode->i_mapping;
return 0;
}

static ssize_t
spufs_cntl_read(struct file *file, char __user *buffer,
size_t size, loff_t *pos)
{
/* FIXME: read from spu status */
return -EINVAL;
}

static ssize_t
spufs_cntl_write(struct file *file, const char __user *buffer,
size_t size, loff_t *pos)
{
/* FIXME: write to runctl bit */
return -EINVAL;
}

static struct file_operations spufs_cntl_fops = {
.open = spufs_cntl_open,
.read = spufs_cntl_read,
.write = spufs_cntl_write,
#ifdef CONFIG_SPUFS_MMAP
.mmap = spufs_cntl_mmap,
#endif
};

static int
spufs_regs_open(struct inode *inode, struct file *file)
{
Expand Down Expand Up @@ -503,6 +607,16 @@ static struct file_operations spufs_wbox_stat_fops = {
.read = spufs_wbox_stat_read,
};

static int spufs_signal1_open(struct inode *inode, struct file *file)
{
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;
file->private_data = ctx;
file->f_mapping = inode->i_mapping;
ctx->signal1 = inode->i_mapping;
return nonseekable_open(inode, file);
}

static ssize_t spufs_signal1_read(struct file *file, char __user *buf,
size_t len, loff_t *pos)
{
Expand Down Expand Up @@ -543,12 +657,50 @@ static ssize_t spufs_signal1_write(struct file *file, const char __user *buf,
return 4;
}

#ifdef CONFIG_SPUFS_MMAP
static struct page *spufs_signal1_mmap_nopage(struct vm_area_struct *vma,
unsigned long address, int *type)
{
return spufs_ps_nopage(vma, address, type, 0x14000);
}

static struct vm_operations_struct spufs_signal1_mmap_vmops = {
.nopage = spufs_signal1_mmap_nopage,
};

static int spufs_signal1_mmap(struct file *file, struct vm_area_struct *vma)
{
if (!(vma->vm_flags & VM_SHARED))
return -EINVAL;

vma->vm_flags |= VM_RESERVED;
vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
| _PAGE_NO_CACHE);

vma->vm_ops = &spufs_signal1_mmap_vmops;
return 0;
}
#endif

static struct file_operations spufs_signal1_fops = {
.open = spufs_pipe_open,
.open = spufs_signal1_open,
.read = spufs_signal1_read,
.write = spufs_signal1_write,
#ifdef CONFIG_SPUFS_MMAP
.mmap = spufs_signal1_mmap,
#endif
};

static int spufs_signal2_open(struct inode *inode, struct file *file)
{
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;
file->private_data = ctx;
file->f_mapping = inode->i_mapping;
ctx->signal2 = inode->i_mapping;
return nonseekable_open(inode, file);
}

static ssize_t spufs_signal2_read(struct file *file, char __user *buf,
size_t len, loff_t *pos)
{
Expand Down Expand Up @@ -591,10 +743,39 @@ static ssize_t spufs_signal2_write(struct file *file, const char __user *buf,
return 4;
}

#ifdef CONFIG_SPUFS_MMAP
static struct page *spufs_signal2_mmap_nopage(struct vm_area_struct *vma,
unsigned long address, int *type)
{
return spufs_ps_nopage(vma, address, type, 0x1c000);
}

static struct vm_operations_struct spufs_signal2_mmap_vmops = {
.nopage = spufs_signal2_mmap_nopage,
};

static int spufs_signal2_mmap(struct file *file, struct vm_area_struct *vma)
{
if (!(vma->vm_flags & VM_SHARED))
return -EINVAL;

/* FIXME: */
vma->vm_flags |= VM_RESERVED;
vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
| _PAGE_NO_CACHE);

vma->vm_ops = &spufs_signal2_mmap_vmops;
return 0;
}
#endif

static struct file_operations spufs_signal2_fops = {
.open = spufs_pipe_open,
.open = spufs_signal2_open,
.read = spufs_signal2_read,
.write = spufs_signal2_write,
#ifdef CONFIG_SPUFS_MMAP
.mmap = spufs_signal2_mmap,
#endif
};

static void spufs_signal1_type_set(void *data, u64 val)
Expand Down Expand Up @@ -643,6 +824,38 @@ static u64 spufs_signal2_type_get(void *data)
DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get,
spufs_signal2_type_set, "%llu");

#ifdef CONFIG_SPUFS_MMAP
static struct page *spufs_mfc_mmap_nopage(struct vm_area_struct *vma,
unsigned long address, int *type)
{
return spufs_ps_nopage(vma, address, type, 0x3000);
}

static struct vm_operations_struct spufs_mfc_mmap_vmops = {
.nopage = spufs_mfc_mmap_nopage,
};

/*
* mmap support for problem state MFC DMA area [0x0000 - 0x0fff].
* Mapping this area requires that the application have CAP_SYS_RAWIO,
* as these registers require special care when read/writing.
*/
static int spufs_mfc_mmap(struct file *file, struct vm_area_struct *vma)
{
if (!(vma->vm_flags & VM_SHARED))
return -EINVAL;

if (!capable(CAP_SYS_RAWIO))
return -EPERM;

vma->vm_flags |= VM_RESERVED;
vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
| _PAGE_NO_CACHE);

vma->vm_ops = &spufs_mfc_mmap_vmops;
return 0;
}
#endif

static int spufs_mfc_open(struct inode *inode, struct file *file)
{
Expand Down Expand Up @@ -932,6 +1145,9 @@ static struct file_operations spufs_mfc_fops = {
.flush = spufs_mfc_flush,
.fsync = spufs_mfc_fsync,
.fasync = spufs_mfc_fasync,
#ifdef CONFIG_SPUFS_MMAP
.mmap = spufs_mfc_mmap,
#endif
};

static void spufs_npc_set(void *data, u64 val)
Expand Down Expand Up @@ -1077,6 +1293,7 @@ struct tree_descr spufs_dir_contents[] = {
{ "signal1_type", &spufs_signal1_type, 0666, },
{ "signal2_type", &spufs_signal2_type, 0666, },
{ "mfc", &spufs_mfc_fops, 0666, },
{ "cntl", &spufs_cntl_fops, 0666, },
{ "npc", &spufs_npc_ops, 0666, },
{ "fpcr", &spufs_fpcr_fops, 0666, },
{ "decr", &spufs_decr_ops, 0666, },
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/powerpc/platforms/cell/spufs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
inode->i_gid = dir->i_gid;
inode->i_mode &= S_ISGID;
}
ctx = alloc_spu_context(inode->i_mapping);
ctx = alloc_spu_context();
SPUFS_I(inode)->i_ctx = ctx;
if (!ctx)
goto out_iput;
Expand Down
8 changes: 6 additions & 2 deletions trunk/arch/powerpc/platforms/cell/spufs/spufs.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ struct spu_context {
struct spu *spu; /* pointer to a physical SPU */
struct spu_state csa; /* SPU context save area. */
spinlock_t mmio_lock; /* protects mmio access */
struct address_space *local_store;/* local store backing store */
struct address_space *local_store; /* local store mapping. */
struct address_space *mfc; /* 'mfc' area mappings. */
struct address_space *cntl; /* 'control' area mappings. */
struct address_space *signal1; /* 'signal1' area mappings. */
struct address_space *signal2; /* 'signal2' area mappings. */

enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state;
struct rw_semaphore state_sema;
Expand Down Expand Up @@ -125,7 +129,7 @@ long spufs_create_thread(struct nameidata *nd,
extern struct file_operations spufs_context_fops;

/* context management */
struct spu_context * alloc_spu_context(struct address_space *local_store);
struct spu_context * alloc_spu_context(void);
void destroy_spu_context(struct kref *kref);
struct spu_context * get_spu_context(struct spu_context *ctx);
int put_spu_context(struct spu_context *ctx);
Expand Down
Loading

0 comments on commit ea489a4

Please sign in to comment.