svn commit: r338990 - in head/sys: compat/freebsd32 dev/pci

Brooks Davis brooks at FreeBSD.org
Thu Sep 27 21:08:34 UTC 2018


Author: brooks
Date: Thu Sep 27 21:08:32 2018
New Revision: 338990
URL: https://svnweb.freebsd.org/changeset/base/338990

Log:
  Centralize compat support for PCIOCGETCONF.
  
  The pre-7.x compat for both native and 32-bit code was already in
  pci_user.c. Use this infrastructure to add implement 32-bit support.
  This is more correct as ioctl(2) commands only have meaning in the
  context of a file descriptor.
  
  Reviewed by:	kib
  Approved by:	re (gjb)
  Obtained from:	CheriBSD
  Sponsored by:	DARPA, AFRL
  Differential revision:	https://reviews.freebsd.org/D17324

Modified:
  head/sys/compat/freebsd32/freebsd32_ioctl.c
  head/sys/compat/freebsd32/freebsd32_ioctl.h
  head/sys/dev/pci/pci_user.c

Modified: head/sys/compat/freebsd32/freebsd32_ioctl.c
==============================================================================
--- head/sys/compat/freebsd32/freebsd32_ioctl.c	Thu Sep 27 20:48:07 2018	(r338989)
+++ head/sys/compat/freebsd32/freebsd32_ioctl.c	Thu Sep 27 21:08:32 2018	(r338990)
@@ -58,9 +58,6 @@ __FBSDID("$FreeBSD$");
 
 CTASSERT(sizeof(struct ioc_read_toc_entry32) == 8);
 CTASSERT(sizeof(struct mem_range_op32) == 12);
-CTASSERT(sizeof(struct pci_conf_io32) == 36);
-CTASSERT(sizeof(struct pci_match_conf32) == 44);
-CTASSERT(sizeof(struct pci_conf32) == 44);
 
 static int
 freebsd32_ioctl_ioc_read_toc(struct thread *td,
@@ -148,108 +145,6 @@ freebsd32_ioctl_memrange(struct thread *td,
 }
 
 static int
-freebsd32_ioctl_pciocgetconf(struct thread *td,
-    struct freebsd32_ioctl_args *uap, struct file *fp)
-{
-	struct pci_conf_io pci;
-	struct pci_conf_io32 pci32;
-	struct pci_match_conf32 pmc32;
-	struct pci_match_conf32 *pmc32p;
-	struct pci_match_conf pmc;
-	struct pci_match_conf *pmcp;
-	struct pci_conf32 pc32;
-	struct pci_conf32 *pc32p;
-	struct pci_conf pc;
-	struct pci_conf *pcp;
-	u_int32_t i;
-	u_int32_t npat_to_convert;
-	u_int32_t nmatch_to_convert;
-	vm_offset_t addr;
-	int error;
-
-	if ((error = copyin(uap->data, &pci32, sizeof(pci32))) != 0)
-		return (error);
-
-	CP(pci32, pci, num_patterns);
-	CP(pci32, pci, offset);
-	CP(pci32, pci, generation);
-
-	npat_to_convert = pci32.pat_buf_len / sizeof(struct pci_match_conf32);
-	pci.pat_buf_len = npat_to_convert * sizeof(struct pci_match_conf);
-	pci.patterns = NULL;
-	nmatch_to_convert = pci32.match_buf_len / sizeof(struct pci_conf32);
-	pci.match_buf_len = nmatch_to_convert * sizeof(struct pci_conf);
-	pci.matches = NULL;
-
-	if ((error = copyout_map(td, &addr, pci.pat_buf_len)) != 0)
-		goto cleanup;
-	pci.patterns = (struct pci_match_conf *)addr;
-	if ((error = copyout_map(td, &addr, pci.match_buf_len)) != 0)
-		goto cleanup;
-	pci.matches = (struct pci_conf *)addr;
-
-	npat_to_convert = min(npat_to_convert, pci.num_patterns);
-
-	for (i = 0, pmc32p = (struct pci_match_conf32 *)PTRIN(pci32.patterns),
-	     pmcp = pci.patterns;
-	     i < npat_to_convert; i++, pmc32p++, pmcp++) {
-		if ((error = copyin(pmc32p, &pmc32, sizeof(pmc32))) != 0)
-			goto cleanup;
-		CP(pmc32,pmc,pc_sel);
-		strlcpy(pmc.pd_name, pmc32.pd_name, sizeof(pmc.pd_name));
-		CP(pmc32,pmc,pd_unit);
-		CP(pmc32,pmc,pc_vendor);
-		CP(pmc32,pmc,pc_device);
-		CP(pmc32,pmc,pc_class);
-		CP(pmc32,pmc,flags);
-		if ((error = copyout(&pmc, pmcp, sizeof(pmc))) != 0)
-			goto cleanup;
-	}
-
-	if ((error = fo_ioctl(fp, PCIOCGETCONF, (caddr_t)&pci,
-			      td->td_ucred, td)) != 0)
-		goto cleanup;
-
-	nmatch_to_convert = min(nmatch_to_convert, pci.num_matches);
-
-	for (i = 0, pcp = pci.matches,
-	     pc32p = (struct pci_conf32 *)PTRIN(pci32.matches);
-	     i < nmatch_to_convert; i++, pcp++, pc32p++) {
-		if ((error = copyin(pcp, &pc, sizeof(pc))) != 0)
-			goto cleanup;
-		CP(pc,pc32,pc_sel);
-		CP(pc,pc32,pc_hdr);
-		CP(pc,pc32,pc_subvendor);
-		CP(pc,pc32,pc_subdevice);
-		CP(pc,pc32,pc_vendor);
-		CP(pc,pc32,pc_device);
-		CP(pc,pc32,pc_class);
-		CP(pc,pc32,pc_subclass);
-		CP(pc,pc32,pc_progif);
-		CP(pc,pc32,pc_revid);
-		strlcpy(pc32.pd_name, pc.pd_name, sizeof(pc32.pd_name));
-		CP(pc,pc32,pd_unit);
-		if ((error = copyout(&pc32, pc32p, sizeof(pc32))) != 0)
-			goto cleanup;
-	}
-
-	CP(pci, pci32, num_matches);
-	CP(pci, pci32, offset);
-	CP(pci, pci32, generation);
-	CP(pci, pci32, status);
-
-	error = copyout(&pci32, uap->data, sizeof(pci32));
-
-cleanup:
-	if (pci.patterns)
-		copyout_unmap(td, (vm_offset_t)pci.patterns, pci.pat_buf_len);
-	if (pci.matches)
-		copyout_unmap(td, (vm_offset_t)pci.matches, pci.match_buf_len);
-
-	return (error);
-}
-
-static int
 freebsd32_ioctl_barmmap(struct thread *td,
     struct freebsd32_ioctl_args *uap, struct file *fp)
 {
@@ -380,10 +275,6 @@ freebsd32_ioctl(struct thread *td, struct freebsd32_io
 	case MEMRANGE_GET32:	/* FALLTHROUGH */
 	case MEMRANGE_SET32:
 		error = freebsd32_ioctl_memrange(td, uap, fp);
-		break;
-
-	case PCIOCGETCONF_32:
-		error = freebsd32_ioctl_pciocgetconf(td, uap, fp);
 		break;
 
 	case SG_IO_32:

Modified: head/sys/compat/freebsd32/freebsd32_ioctl.h
==============================================================================
--- head/sys/compat/freebsd32/freebsd32_ioctl.h	Thu Sep 27 20:48:07 2018	(r338989)
+++ head/sys/compat/freebsd32/freebsd32_ioctl.h	Thu Sep 27 21:08:32 2018	(r338990)
@@ -56,45 +56,6 @@ struct mem_range_op32
 	int		mo_arg[2];
 };
 
-struct pci_conf32 {
-	struct pcisel	pc_sel;		/* domain+bus+slot+function */
-	u_int8_t	pc_hdr;		/* PCI header type */
-	u_int16_t	pc_subvendor;	/* card vendor ID */
-	u_int16_t	pc_subdevice;	/* card device ID, assigned by
-					   card vendor */
-	u_int16_t	pc_vendor;	/* chip vendor ID */
-	u_int16_t	pc_device;	/* chip device ID, assigned by
-					   chip vendor */
-	u_int8_t	pc_class;	/* chip PCI class */
-	u_int8_t	pc_subclass;	/* chip PCI subclass */
-	u_int8_t	pc_progif;	/* chip PCI programming interface */
-	u_int8_t	pc_revid;	/* chip revision ID */
-	char		pd_name[PCI_MAXNAMELEN + 1];  /* device name */
-	u_int32_t	pd_unit;	/* device unit number */
-};
-
-struct pci_match_conf32 {
-	struct pcisel		pc_sel;		/* domain+bus+slot+function */
-	char			pd_name[PCI_MAXNAMELEN + 1];  /* device name */
-	u_int32_t		pd_unit;	/* Unit number */
-	u_int16_t		pc_vendor;	/* PCI Vendor ID */
-	u_int16_t		pc_device;	/* PCI Device ID */
-	u_int8_t		pc_class;	/* PCI class */
-	u_int32_t		flags;		/* Matching expression */
-};
-
-struct pci_conf_io32 {
-	u_int32_t		pat_buf_len;	/* pattern buffer length */
-	u_int32_t		num_patterns;	/* number of patterns */
-	caddr_t32		patterns;	/* struct pci_match_conf ptr */
-	u_int32_t		match_buf_len;	/* match buffer length */
-	u_int32_t		num_matches;	/* number of matches returned */
-	caddr_t32		matches;	/* struct pci_conf ptr */
-	u_int32_t		offset;		/* offset into device list */
-	u_int32_t		generation;	/* device list generation */
-	u_int32_t		status;		/* request status */
-};
-
 struct pci_bar_mmap32 {
 	uint32_t	pbm_map_base;
 	uint32_t	pbm_map_length;
@@ -110,7 +71,6 @@ struct pci_bar_mmap32 {
 #define	FIODGNAME_32	_IOW('f', 120, struct fiodgname_arg32)
 #define	MEMRANGE_GET32	_IOWR('m', 50, struct mem_range_op32)
 #define	MEMRANGE_SET32	_IOW('m', 51, struct mem_range_op32)
-#define	PCIOCGETCONF_32	_IOWR('p', 5, struct pci_conf_io32)
 #define	SG_IO_32	_IOWR(SGIOC, 0x85, struct sg_io_hdr32)
 #define	PCIOCBARMMAP_32	_IOWR('p', 8, struct pci_bar_mmap32)
 

Modified: head/sys/dev/pci/pci_user.c
==============================================================================
--- head/sys/dev/pci/pci_user.c	Thu Sep 27 20:48:07 2018	(r338989)
+++ head/sys/dev/pci/pci_user.c	Thu Sep 27 21:08:32 2018	(r338990)
@@ -66,6 +66,49 @@ __FBSDID("$FreeBSD$");
 #include "pcib_if.h"
 #include "pci_if.h"
 
+#ifdef COMPAT_FREEBSD32
+struct pci_conf32 {
+	struct pcisel	pc_sel;		/* domain+bus+slot+function */
+	u_int8_t	pc_hdr;		/* PCI header type */
+	u_int16_t	pc_subvendor;	/* card vendor ID */
+	u_int16_t	pc_subdevice;	/* card device ID, assigned by
+					   card vendor */
+	u_int16_t	pc_vendor;	/* chip vendor ID */
+	u_int16_t	pc_device;	/* chip device ID, assigned by
+					   chip vendor */
+	u_int8_t	pc_class;	/* chip PCI class */
+	u_int8_t	pc_subclass;	/* chip PCI subclass */
+	u_int8_t	pc_progif;	/* chip PCI programming interface */
+	u_int8_t	pc_revid;	/* chip revision ID */
+	char		pd_name[PCI_MAXNAMELEN + 1];  /* device name */
+	u_int32_t	pd_unit;	/* device unit number */
+};
+
+struct pci_match_conf32 {
+	struct pcisel		pc_sel;		/* domain+bus+slot+function */
+	char			pd_name[PCI_MAXNAMELEN + 1];  /* device name */
+	u_int32_t		pd_unit;	/* Unit number */
+	u_int16_t		pc_vendor;	/* PCI Vendor ID */
+	u_int16_t		pc_device;	/* PCI Device ID */
+	u_int8_t		pc_class;	/* PCI class */
+	u_int32_t		flags;		/* Matching expression */
+};
+
+struct pci_conf_io32 {
+	u_int32_t		pat_buf_len;	/* pattern buffer length */
+	u_int32_t		num_patterns;	/* number of patterns */
+	u_int32_t		patterns;	/* struct pci_match_conf ptr */
+	u_int32_t		match_buf_len;	/* match buffer length */
+	u_int32_t		num_matches;	/* number of matches returned */
+	u_int32_t		matches;	/* struct pci_conf ptr */
+	u_int32_t		offset;		/* offset into device list */
+	u_int32_t		generation;	/* device list generation */
+	u_int32_t		status;		/* request status */
+};
+
+#define	PCIOCGETCONF32	_IOC_NEWTYPE(PCIOCGETCONF, struct pci_conf_io32)
+#endif
+
 /*
  * This is the user interface to PCI configuration space.
  */
@@ -175,6 +218,73 @@ pci_conf_match_native(struct pci_match_conf *matches, 
 	return(1);
 }
 
+#ifdef COMPAT_FREEBSD32
+static int
+pci_conf_match32(struct pci_match_conf32 *matches, int num_matches,
+	       struct pci_conf *match_buf)
+{
+	int i;
+
+	if ((matches == NULL) || (match_buf == NULL) || (num_matches <= 0))
+		return(1);
+
+	for (i = 0; i < num_matches; i++) {
+		/*
+		 * I'm not sure why someone would do this...but...
+		 */
+		if (matches[i].flags == PCI_GETCONF_NO_MATCH)
+			continue;
+
+		/*
+		 * Look at each of the match flags.  If it's set, do the
+		 * comparison.  If the comparison fails, we don't have a
+		 * match, go on to the next item if there is one.
+		 */
+		if (((matches[i].flags & PCI_GETCONF_MATCH_DOMAIN) != 0)
+		 && (match_buf->pc_sel.pc_domain !=
+		 matches[i].pc_sel.pc_domain))
+			continue;
+
+		if (((matches[i].flags & PCI_GETCONF_MATCH_BUS) != 0)
+		 && (match_buf->pc_sel.pc_bus != matches[i].pc_sel.pc_bus))
+			continue;
+
+		if (((matches[i].flags & PCI_GETCONF_MATCH_DEV) != 0)
+		 && (match_buf->pc_sel.pc_dev != matches[i].pc_sel.pc_dev))
+			continue;
+
+		if (((matches[i].flags & PCI_GETCONF_MATCH_FUNC) != 0)
+		 && (match_buf->pc_sel.pc_func != matches[i].pc_sel.pc_func))
+			continue;
+
+		if (((matches[i].flags & PCI_GETCONF_MATCH_VENDOR) != 0)
+		 && (match_buf->pc_vendor != matches[i].pc_vendor))
+			continue;
+
+		if (((matches[i].flags & PCI_GETCONF_MATCH_DEVICE) != 0)
+		 && (match_buf->pc_device != matches[i].pc_device))
+			continue;
+
+		if (((matches[i].flags & PCI_GETCONF_MATCH_CLASS) != 0)
+		 && (match_buf->pc_class != matches[i].pc_class))
+			continue;
+
+		if (((matches[i].flags & PCI_GETCONF_MATCH_UNIT) != 0)
+		 && (match_buf->pd_unit != matches[i].pd_unit))
+			continue;
+
+		if (((matches[i].flags & PCI_GETCONF_MATCH_NAME) != 0)
+		 && (strncmp(matches[i].pd_name, match_buf->pd_name,
+			     sizeof(match_buf->pd_name)) != 0))
+			continue;
+
+		return(0);
+	}
+
+	return(1);
+}
+#endif	/* COMPAT_FREEBSD32 */
+
 #if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
     defined(COMPAT_FREEBSD6)
 #define PRE7_COMPAT
@@ -259,20 +369,6 @@ struct pci_match_conf_old32 {
 	pci_getconf_flags_old flags;	/* Matching expression */
 };
 
-struct pci_conf_io32 {
-	uint32_t	pat_buf_len;	/* pattern buffer length */
-	uint32_t	num_patterns;	/* number of patterns */
-	uint32_t	patterns;	/* pattern buffer
-					   (struct pci_match_conf_old32 *) */
-	uint32_t	match_buf_len;	/* match buffer length */
-	uint32_t	num_matches;	/* number of matches returned */
-	uint32_t	matches;	/* match buffer
-					   (struct pci_conf_old32 *) */
-	uint32_t	offset;		/* offset into device list */
-	uint32_t	generation;	/* device list generation */
-	pci_getconf_status status;	/* request status */
-};
-
 #define	PCIOCGETCONF_OLD32	_IOWR('p', 1, struct pci_conf_io32)
 #endif	/* COMPAT_FREEBSD32 */
 
@@ -411,6 +507,9 @@ pci_conf_match_old32(struct pci_match_conf_old32 *matc
 
 union pci_conf_union {
 	struct pci_conf		pc;
+#ifdef COMPAT_FREEBSD32
+	struct pci_conf32	pc32;
+#endif
 #ifdef PRE7_COMPAT
 	struct pci_conf_old	pco;
 #ifdef COMPAT_FREEBSD32
@@ -428,6 +527,11 @@ pci_conf_match(u_long cmd, struct pci_match_conf *matc
 	case PCIOCGETCONF:
 		return (pci_conf_match_native(
 		    (struct pci_match_conf *)matches, num_matches, match_buf));
+#ifdef COMPAT_FREEBSD32
+	case PCIOCGETCONF32:
+		return (pci_conf_match32((struct pci_match_conf32 *)matches,
+		    num_matches, match_buf));
+#endif
 #ifdef PRE7_COMPAT
 	case PCIOCGETCONF_OLD:
 		return (pci_conf_match_old(
@@ -544,6 +648,10 @@ pci_match_conf_size(u_long cmd)
 	switch (cmd) {
 	case PCIOCGETCONF:
 		return (sizeof(struct pci_match_conf));
+#ifdef COMPAT_FREEBSD32
+	case PCIOCGETCONF32:
+		return (sizeof(struct pci_match_conf32));
+#endif
 #ifdef PRE7_COMPAT
 	case PCIOCGETCONF_OLD:
 		return (sizeof(struct pci_match_conf_old));
@@ -565,6 +673,10 @@ pci_conf_size(u_long cmd)
 	switch (cmd) {
 	case PCIOCGETCONF:
 		return (sizeof(struct pci_conf));
+#ifdef COMPAT_FREEBSD32
+	case PCIOCGETCONF32:
+		return (sizeof(struct pci_conf32));
+#endif
 #ifdef PRE7_COMPAT
 	case PCIOCGETCONF_OLD:
 		return (sizeof(struct pci_conf_old));
@@ -582,7 +694,7 @@ pci_conf_size(u_long cmd)
 static void
 pci_conf_io_init(struct pci_conf_io *cio, caddr_t data, u_long cmd)
 {
-#if defined(PRE7_COMPAT) && defined(COMPAT_FREEBSD32)
+#if defined(COMPAT_FREEBSD32)
 	struct pci_conf_io32 *cio32;
 #endif
 
@@ -594,8 +706,11 @@ pci_conf_io_init(struct pci_conf_io *cio, caddr_t data
 		*cio = *(struct pci_conf_io *)data;
 		return;
 
-#if defined(PRE7_COMPAT) && defined(COMPAT_FREEBSD32)
+#ifdef COMPAT_FREEBSD32
+	case PCIOCGETCONF32:
+#ifdef PRE7_COMPAT
 	case PCIOCGETCONF_OLD32:
+#endif
                cio32 = (struct pci_conf_io32 *)data;
                cio->pat_buf_len = cio32->pat_buf_len;
                cio->num_patterns = cio32->num_patterns;
@@ -620,7 +735,7 @@ pci_conf_io_update_data(const struct pci_conf_io *cio,
     u_long cmd)
 {
 	struct pci_conf_io *d_cio;
-#if defined(PRE7_COMPAT) && defined(COMPAT_FREEBSD32)
+#if defined(COMPAT_FREEBSD32)
 	struct pci_conf_io32 *cio32;
 #endif
 
@@ -636,8 +751,11 @@ pci_conf_io_update_data(const struct pci_conf_io *cio,
 		d_cio->num_matches = cio->num_matches;
 		return;
 
-#if defined(PRE7_COMPAT) && defined(COMPAT_FREEBSD32)
+#ifdef COMPAT_FREEBSD32
+	case PCIOCGETCONF32:
+#ifdef PRE7_COMPAT
 	case PCIOCGETCONF_OLD32:
+#endif
 		cio32 = (struct pci_conf_io32 *)data;
 
 		cio32->status = cio->status;
@@ -664,6 +782,24 @@ pci_conf_for_copyout(const struct pci_conf *pcp, union
 	case PCIOCGETCONF:
 		pcup->pc = *pcp;
 		return;
+
+#ifdef COMPAT_FREEBSD32
+	case PCIOCGETCONF32:
+		pcup->pc32.pc_sel = pcp->pc_sel;
+		pcup->pc32.pc_hdr = pcp->pc_hdr;
+		pcup->pc32.pc_subvendor = pcp->pc_subvendor;
+		pcup->pc32.pc_subdevice = pcp->pc_subdevice;
+		pcup->pc32.pc_vendor = pcp->pc_vendor;
+		pcup->pc32.pc_device = pcp->pc_device;
+		pcup->pc32.pc_class = pcp->pc_class;
+		pcup->pc32.pc_subclass = pcp->pc_subclass;
+		pcup->pc32.pc_progif = pcp->pc_progif;
+		pcup->pc32.pc_revid = pcp->pc_revid;
+		strlcpy(pcup->pc32.pd_name, pcp->pd_name,
+		    sizeof(pcup->pc32.pd_name));
+		pcup->pc32.pd_unit = (uint32_t)pcp->pd_unit;
+		return;
+#endif
 
 #ifdef PRE7_COMPAT
 #ifdef COMPAT_FREEBSD32


More information about the svn-src-all mailing list