lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Wed, 8 Aug 2012 18:31:02 +0300
From:	Felipe Balbi <balbi@...com>
To:	Felipe Balbi <balbi@...com>
Cc:	Hiroshi Doyu <hdoyu@...dia.com>, iommu@...ts.linux-foundation.org,
	linux-tegra@...r.kernel.org, Al Viro <viro@...iv.linux.org.uk>,
	Joerg Roedel <joerg.roedel@....com>,
	Stephen Warren <swarren@...dotorg.org>,
	Chris Wright <chrisw@...s-sol.org>,
	Grant Likely <grant.likely@...retlab.ca>,
	linux-kernel@...r.kernel.org
Subject: Re: [PATCH 2/2] iommu/tegra: smmu: Use __debugfs_create_dir

Hi,

On Wed, Aug 08, 2012 at 06:11:29PM +0300, Felipe Balbi wrote:
> Hi,
> 
> On Wed, Aug 08, 2012 at 09:24:33AM +0300, Hiroshi Doyu wrote:
> > The commit c3b1a35 "debugfs: make sure that debugfs_create_file() gets
> > used only for regulars" doesn't allow to use debugfs_create_file() for
> > dir. Use the version with "data", __debugfs_create_dir().
> > 
> > Signed-off-by: Hiroshi Doyu <hdoyu@...dia.com>
> > Reported-by: Laxman Dewangan <ldewangan@...dia.com>
> > ---
> >  drivers/iommu/tegra-smmu.c |    4 +---
> >  1 files changed, 1 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
> > index 5e51fb7..41aff7a 100644
> > --- a/drivers/iommu/tegra-smmu.c
> > +++ b/drivers/iommu/tegra-smmu.c
> > @@ -1035,9 +1035,7 @@ static void smmu_debugfs_create(struct smmu_device *smmu)
> >  	int i;
> >  	struct dentry *root;
> >  
> > -	root = debugfs_create_file(dev_name(smmu->dev),
> > -				   S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
> > -				   NULL, smmu, NULL);
> > +	root = __debugfs_create_dir(dev_name(smmu->dev), NULL, smmu);
> 
> why would the directory need extra data ? Looking in mainline,
> tegra-smmu.c doesn't have any debugfs support, where can I see the
> patches adding debugfs to tegra-smmu ? It doesn't look correct that the
> directory will have a data field.

Looking at linux-next I found the commit which added it:

> @@ -892,6 +909,164 @@ static struct iommu_ops smmu_iommu_ops = {
>  	.pgsize_bitmap	= SMMU_IOMMU_PGSIZES,
>  };
>  
> +/* Should be in the order of enum */
> +static const char * const smmu_debugfs_mc[] = { "mc", };
> +static const char * const smmu_debugfs_cache[] = {  "tlb", "ptc", };
> +
> +static ssize_t smmu_debugfs_stats_write(struct file *file,
> +					const char __user *buffer,
> +					size_t count, loff_t *pos)
> +{
> +	struct smmu_device *smmu;
> +	struct dentry *dent;
> +	int i, cache, mc;
> +	enum {
> +		_OFF = 0,
> +		_ON,
> +		_RESET,
> +	};
> +	const char * const command[] = {
> +		[_OFF]		= "off",
> +		[_ON]		= "on",
> +		[_RESET]	= "reset",
> +	};
> +	char str[] = "reset";
> +	u32 val;
> +	size_t offs;
> +
> +	count = min_t(size_t, count, sizeof(str));
> +	if (copy_from_user(str, buffer, count))
> +		return -EINVAL;
> +
> +	for (i = 0; i < ARRAY_SIZE(command); i++)
> +		if (strncmp(str, command[i],
> +			    strlen(command[i])) == 0)
> +			break;
> +
> +	if (i == ARRAY_SIZE(command))
> +		return -EINVAL;
> +
> +	dent = file->f_dentry;
> +	cache = (int)dent->d_inode->i_private;

cache you can figure out by the filename. In fact, it would be much
better to have tlc and ptc directories with a "status" filename which
you write ON/OFF/RESET or enable/disable/reset to trigger what you need.

For that to work, you should probably hold tlb and ptc on an array of
some sort, and pass those as data to their respective "status" files as
the data field. If tlb and ptc are properly defined structures which can
point back to smmu, then you have everything you need.

I mean something like:

struct smmu;

struct mc {
	const char *name;
	void __iomem *regs;

	struct smmu *smmu;
};

struct smmu {
	struct mc mc[2]; /*what does mc stand for ? memory controller ? */

	...
};

debugfs_create_dir(smmu);
debugfs_create_dir(mc);
debugfs_create_dir(smmu->mc[1].name);
debugfs_create_dir(smmu->mc[2].name);
debugfs_create_file(&smmu->mc[1], status);
debugfs_create_file(&smmu->mc[2], status);

or something similar. You will avoid all the trickery you did here to
achieve what you need.

> +	mc = (int)dent->d_parent->d_inode->i_private;
> +	smmu = dent->d_parent->d_parent->d_inode->i_private;
> +
> +	offs = SMMU_CACHE_CONFIG(cache);
> +	val = smmu_read(smmu, offs);
> +	switch (i) {
> +	case _OFF:
> +		val &= ~SMMU_CACHE_CONFIG_STATS_ENABLE;
> +		val &= ~SMMU_CACHE_CONFIG_STATS_TEST;
> +		smmu_write(smmu, val, offs);
> +		break;
> +	case _ON:
> +		val |= SMMU_CACHE_CONFIG_STATS_ENABLE;
> +		val &= ~SMMU_CACHE_CONFIG_STATS_TEST;
> +		smmu_write(smmu, val, offs);
> +		break;
> +	case _RESET:
> +		val |= SMMU_CACHE_CONFIG_STATS_TEST;
> +		smmu_write(smmu, val, offs);
> +		val &= ~SMMU_CACHE_CONFIG_STATS_TEST;
> +		smmu_write(smmu, val, offs);
> +		break;
> +	default:
> +		BUG();
> +		break;
> +	}
> +
> +	dev_dbg(smmu->dev, "%s() %08x, %08x @%08x\n", __func__,
> +		val, smmu_read(smmu, offs), offs);
> +
> +	return count;
> +}
> +
> +static int smmu_debugfs_stats_show(struct seq_file *s, void *v)
> +{
> +	struct smmu_device *smmu;
> +	struct dentry *dent;
> +	int i, cache, mc;
> +	const char * const stats[] = { "hit", "miss", };
> +
> +	dent = d_find_alias(s->private);
> +	cache = (int)dent->d_inode->i_private;
> +	mc = (int)dent->d_parent->d_inode->i_private;
> +	smmu = dent->d_parent->d_parent->d_inode->i_private;
> +
> +	for (i = 0; i < ARRAY_SIZE(stats); i++) {
> +		u32 val;
> +		size_t offs;
> +
> +		offs = SMMU_STATS_CACHE_COUNT(mc, cache, i);
> +		val = smmu_read(smmu, offs);
> +		seq_printf(s, "%s:%08x ", stats[i], val);
> +
> +		dev_dbg(smmu->dev, "%s() %s %08x @%08x\n", __func__,
> +			stats[i], val, offs);
> +	}
> +	seq_printf(s, "\n");
> +
> +	return 0;
> +}
> +
> +static int smmu_debugfs_stats_open(struct inode *inode, struct file *file)
> +{
> +	return single_open(file, smmu_debugfs_stats_show, inode);
> +}
> +
> +static const struct file_operations smmu_debugfs_stats_fops = {
> +	.open		= smmu_debugfs_stats_open,
> +	.read		= seq_read,
> +	.llseek		= seq_lseek,
> +	.release	= single_release,
> +	.write		= smmu_debugfs_stats_write,
> +};
> +
> +static void smmu_debugfs_delete(struct smmu_device *smmu)
> +{
> +	debugfs_remove_recursive(smmu->debugfs_root);
> +}
> +
> +static void smmu_debugfs_create(struct smmu_device *smmu)
> +{
> +	int i;
> +	struct dentry *root;
> +
> +	root = debugfs_create_file(dev_name(smmu->dev),
> +				   S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
> +				   NULL, smmu, NULL);

directories don't need data. You don't even have a file_operations
structure so when exactly are you going to access the data ? What you
did above is actually wrong. You need to either patch this ASAP or drop
the patch you wrote and rewrite the whole debugfs support.

> +	if (!root)
> +		goto err_out;
> +	smmu->debugfs_root = root;
> +
> +	for (i = 0; i < ARRAY_SIZE(smmu_debugfs_mc); i++) {
> +		int j;
> +		struct dentry *mc;
> +
> +		mc = debugfs_create_file(smmu_debugfs_mc[i],
> +					 S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
> +					 root, (void *)i, NULL);

likewise here. What would you use that index for ? Even if you were to
access it, how would you use it ? Not to mention that you never, ever
access the private_data of the directory :-)

Just convert these two to the proper debugfs_create_dir()

> +		if (!mc)
> +			goto err_out;
> +
> +		for (j = 0; j < ARRAY_SIZE(smmu_debugfs_cache); j++) {
> +			struct dentry *cache;
> +
> +			cache = debugfs_create_file(smmu_debugfs_cache[j],
> +						    S_IWUGO | S_IRUGO, mc,
> +						    (void *)j,
> +						    &smmu_debugfs_stats_fops);

it would be far better to pass a structure which you actually need. In
this case 'smmu'. That will be a lot more useful for your code.

-- 
balbi

Download attachment "signature.asc" of type "application/pgp-signature" (837 bytes)

Powered by blists - more mailing lists