[Intel-gfx] [PATCH 07/10] intel-gpu-tools: register range handling for forcewake hooks

Chris Wilson chris at chris-wilson.co.uk
Wed Jul 13 23:15:42 CEST 2011


On Wed, 13 Jul 2011 13:51:49 -0700, Ben Widawsky <ben at bwidawsk.net> wrote:
Non-text part: multipart/mixed
> We can deprecate the old code by using the non-safe flag in the new API.
> The safe flag should allow the previous behavior to continue.
> 
> The code also adds some range checking on register access. This code is
> gives hooks to prevent tools from doing bad things.
> 
> Signed-off-by: Ben Widawsky <ben at bwidawsk.net>
> ---
>  lib/Makefile.am       |    1 +
>  lib/intel_chipset.h   |    8 ++
>  lib/intel_gpu_tools.h |   27 ++++++++
>  lib/intel_mmio.c      |  178 +++++++++++++++++++++++++++++++++++++++++++++++++
>  lib/intel_reg_map.c   |  174 +++++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 388 insertions(+), 0 deletions(-)
> 
> diff --git a/lib/Makefile.am b/lib/Makefile.am
> index 0c9380d..4612cd5 100644
> --- a/lib/Makefile.am
> +++ b/lib/Makefile.am
> @@ -8,6 +8,7 @@ libintel_tools_la_SOURCES = \
>  	intel_mmio.c \
>  	intel_pci.c \
>  	intel_reg.h \
> +	intel_reg_map.c \
>  	instdone.c \
>  	instdone.h \
>  	drmtest.h
> diff --git a/lib/intel_chipset.h b/lib/intel_chipset.h
> index c3db3ab..a38f661 100755
> --- a/lib/intel_chipset.h
> +++ b/lib/intel_chipset.h
> @@ -168,3 +168,11 @@
>  
>  #define HAS_BLT_RING(devid)	(IS_GEN6(devid) || \
>  				 IS_GEN7(devid))
> +
> +#define IS_BROADWATER(devid)	(devid == PCI_CHIP_I946_GZ || \
> +				 devid == PCI_CHIP_I965_G_1 || \
> +				 devid == PCI_CHIP_I965_Q || \
> +				 devid == PCI_CHIP_I965_G)
> +
> +#define IS_CRESTLINE(devid)	(devid == PCI_CHIP_I965_GM || \
> +				 devid == PCI_CHIP_I965_GME)
> diff --git a/lib/intel_gpu_tools.h b/lib/intel_gpu_tools.h
> index acee657..a145fb9 100644
> --- a/lib/intel_gpu_tools.h
> +++ b/lib/intel_gpu_tools.h
> @@ -37,6 +37,33 @@
>  extern void *mmio;
>  void intel_get_mmio(struct pci_device *pci_dev);
>  
> +/* New style register access API */
> +int intel_register_access_init(struct pci_device *pci_dev, int safe);
> +void intel_register_access_fini(void);
> +uint32_t intel_register_read(uint32_t reg);
> +void intel_register_write(uint32_t reg, uint32_t val);
> +
> +#define INTEL_RANGE_RSVD	(0<<0) /*  Shouldn't be read or written */
> +#define INTEL_RANGE_READ	(1<<0)
> +#define INTEL_RANGE_WRITE	(1<<1)
> +#define INTEL_RANGE_RW		(INTEL_RANGE_READ | INTEL_RANGE_WRITE)
> +#define INTEL_RANGE_END		(1<<31)
> +
> +struct intel_register_range {
> +	uint32_t base;
> +	uint32_t size;
> +	uint32_t flags;
> +};
> +
> +struct intel_register_map {
> +	struct intel_register_range *map;
> +	uint32_t top;
> +	uint32_t alignment_mask;
> +};
> +struct intel_register_map intel_get_register_map(uint32_t devid);
> +struct intel_register_range *intel_get_register_range(struct intel_register_map map, uint32_t offset, int mode);
> +
> +
>  static inline uint32_t
>  INREG(uint32_t reg)
>  {
> diff --git a/lib/intel_mmio.c b/lib/intel_mmio.c
> index 0228a87..05cde4f 100644
> --- a/lib/intel_mmio.c
> +++ b/lib/intel_mmio.c
> @@ -22,12 +22,15 @@
>   *
>   * Authors:
>   *    Eric Anholt <eric at anholt.net>
> + *    Ben Widawsky <ben at bwidawsk.net>
>   *
>   */
>  
>  #include <unistd.h>
>  #include <stdlib.h>
>  #include <stdio.h>
> +#include <stdint.h>
> +#include <stdbool.h>
>  #include <string.h>
>  #include <errno.h>
>  #include <err.h>
> @@ -41,6 +44,16 @@
>  
>  void *mmio;
>  
> +static struct _mmio_data {
> +	int inited;
> +	bool safe;
> +	char debugfs_path[FILENAME_MAX];
> +	char debugfs_forcewake_path[FILENAME_MAX];
> +	uint32_t i915_devid;
> +	struct intel_register_map map;
> +	int key;
> +} mmio_data;
> +
>  void
>  intel_map_file(char *file)
>  {
> @@ -89,3 +102,168 @@ intel_get_mmio(struct pci_device *pci_dev)
>  	}
>  }
>  
> +/*
> + * If successful, i915_debugfs_path and i915_debugfs_forcewake_path are both
> + * updated with the correct path.
> + */
> +static int
> +find_debugfs_path(char *dri_base)
> +{
> +	int i;
> +	char buf[FILENAME_MAX];
> +	char name[256];
> +	char pciid[256];
> +	FILE *file;
> +
> +	for (i = 0; i < 16; i++) {
> +		int n;
> +		snprintf(buf, FILENAME_MAX, "%s/%i/name", dri_base, i);
> +
> +		file = fopen(buf, "r");
> +		if (file == NULL)
> +			continue;
> +
> +		/*
> +		 *if (master->unique) {
> +		 *	seq_printf(m, "%s %s %s\n",
> +		 *		   bus_name,
> +		 *		   dev_name(dev->dev), master->unique);
> +		 *} else {
> +		 *	seq_printf(m, "%s %s\n",
> +		 *	bus_name, dev_name(dev->dev));
> +		 *}
> +		 */
> +		n = fscanf(file, "%s %s ", name, pciid);
> +		fclose (file);
> +
> +		if (n != 2)
> +			continue;
> +
> +		if (strncmp("0000:00:02.0", pciid, strlen("0000:00:02.0")))
> +			continue;

We'd like to maintain the option of someday handling more than one
adaptor. We have the pciid, that should be enough to identify it as a
supported Intel gfx chipset?

> +		snprintf(mmio_data.debugfs_path, FILENAME_MAX,
> +			 "%s/%i/", dri_base, i);
> +		snprintf(mmio_data.debugfs_forcewake_path, FILENAME_MAX,
> +			 "%s/%i/i915_forcewake_user", dri_base, i);
> +
And this file won't even exist otherwise... You need a stat here to
confirm that it does.

> +		return 0;
> +	}
> +
> +	return -1;
> +}
> +
> +/* force wake locking is stubbed out until accepted upstream */
> +static int
> +get_forcewake_lock(void)
> +{
> +	return open(mmio_data.debugfs_forcewake_path, 0);
> +}
> +
> +static void
> +release_forcewake_lock(int fd)
> +{
> +	close(fd);
> +}
> +
> +/*
> + * Initialize register access library.
> + *
> + * @pci_dev: pci device we're mucking with
> + * @safe: use safe register access tables
> + */
> +int
> +intel_register_access_init(struct pci_device *pci_dev, int safe)
> +{
> +	int ret;
> +
> +	/* after old API is deprecated, remove this */
> +	if (mmio == NULL)
> +		intel_get_mmio(pci_dev);
> +
> +	assert(mmio != NULL);
> +
> +	if (mmio_data.inited)
> +		return -1;
> +
> +	mmio_data.safe = safe != 0 ? true : false;
> +
> +	/* Find where the forcewake lock is */
> +	ret = find_debugfs_path("/sys/kernel/debug/dri");
Need to try /debug afterwards, just because that's the other convention.

> +	if (ret) {
> +		fprintf(stderr, "Couldn't find path to dri/debugfs entry\n");
> +		return ret;
> +	}
> +
> +	mmio_data.i915_devid = pci_dev->device_id;
> +	if (mmio_data.safe)
> +		mmio_data.map = intel_get_register_map(mmio_data.i915_devid);
> +
> +	mmio_data.key = get_forcewake_lock();
> +	mmio_data.inited++;
> +	return 0;
> +}
> +
> +void
> +intel_register_access_fini(void)
> +{
> +	release_forcewake_lock(mmio_data.key);
> +	mmio_data.inited--;
> +}
> +
> +uint32_t
> +intel_register_read(uint32_t reg)
> +{
> +	struct intel_register_range *range;
> +	uint32_t ret;
> +
> +	assert(mmio_data.inited);
> +
> +	if (IS_GEN6(mmio_data.i915_devid))
> +		assert(mmio_data.key != -1);
> +
> +	if (!mmio_data.safe)
> +		goto read_out;
> +
> +	range = intel_get_register_range(mmio_data.map,
> +					 reg,
> +					 INTEL_RANGE_READ);
> +
> +	if(!range) {
        if (!range) {


> +struct intel_register_map
> +intel_get_register_map(uint32_t devid)
> +{
> +	struct intel_register_map map;
> +
> +	if (IS_GEN6(devid)) {
> +		map.map = gen6_gt_register_map;
> +		map.top = 0x180000;
> +	} else if (IS_BROADWATER(devid) || IS_CRESTLINE(devid)) {
> +		map.map = gen_bwcl_register_map;
> +		map.top = 0x80000;
> +	} else if (IS_GEN4(devid) || IS_GEN5(devid)) {
> +		map.map = gen4_register_map;
> +		map.top = 0x80000;
> +	} else {
> +		abort();
Give us some warning that this function will die horribly on gen2/3!
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre



More information about the Intel-gfx mailing list