Browse Source

Merge branch 'monarch' into monarch_201407

Conflicts:
	Makefile.am
Luke Dashjr 11 years ago
parent
commit
0d0bb21d7a
6 changed files with 150 additions and 15 deletions
  1. 6 0
      Makefile.am
  2. 15 8
      README.ASIC
  3. 1 0
      configure.ac
  4. 1 1
      driver-bitforce.c
  5. 10 6
      lowl-pci.c
  6. 117 0
      setup-vfio

+ 6 - 0
Makefile.am

@@ -41,6 +41,8 @@ INCLUDES	= -fno-strict-aliasing
 
 bin_PROGRAMS	= bfgminer
 
+sbin_SCRIPTS =
+
 if HAVE_WINDOWS
 else
 bin_SCRIPTS = start-bfgminer.sh
@@ -354,6 +356,10 @@ endif
 
 if NEED_BFG_LOWL_PCI
 bfgminer_SOURCES += lowl-pci.c lowl-pci.h
+
+if USE_VFIO
+sbin_SCRIPTS += setup-vfio
+endif
 endif
 
 if NEED_BFG_LOWL_SPI

+ 15 - 8
README.ASIC

@@ -200,22 +200,29 @@ To enable uio on your cards, you may need to do:
     sudo modprobe uio_pci_generic
     echo 1cf9 0001 | sudo tee /sys/bus/pci/drivers/uio_pci_generic/new_id
 
-Enabling vfio is similar, but more complicated, but allows you to run BFGMiner
-without root privileges. First, load the kernel module and tell it to accept the
-Monarch:
+Enabling vfio is similar, but allows you to run BFGMiner without root
+privileges. Since setting this up is more complicated, BFGMiner includes a
+setup-vfio script (which must be run with root permissions). Simply run:
+    sudo setup-vfio --unsafe --user $(whoami) 1cf9 0001
+You will be asked about each Monarch found, and must answer 'yes' to each one.
+
+If you wish to manually setup VFIO, follow these steps:
+First, load the kernel module:
     sudo modprobe vfio-pci
-    echo 1cf9 0001 | sudo tee /sys/bus/pci/drivers/vfio-pci/new_id
 Next, identify what the device ids are for your card(s):
     lspci -D | grep 1cf9  # the first number of each line is the device id
 From that, you can identify its IOMMU group, and list all devices sharing that
 group:
-    readlink /sys/bus/pci/devices/<device_id>/iommu_group
-    ls /sys/kernel/iommu_groups/<iommu_group>/devices/
+    readlink "/sys/bus/pci/devices/$DEVICE_ID/iommu_group"
+    ls "/sys/kernel/iommu_groups/$IOMMU_GROUP_ID/devices/"
 All of the devices listed (other than the Monarch), if any, will need to be
 disabled and unbound! To do that, use:
-    echo <device_id> | sudo tee /sys/bus/pci/devices/<device_id>/driver/unbind
+    echo "$DEVICE_ID" | sudo tee "/sys/bus/pci/devices/$DEVICE_ID/driver/unbind"
+    echo "$DEVICE_CODE" | sudo tee /sys/bus/pci/drivers/vfio-pci/new_id
+Note that $DEVICE_ID should be something like "0000:01:00.0" and $DEVICE_CODE is
+something like "1cf9 0001" (this example is the Monarch itself).
 If you want to run BFGMiner as a normal user:
-    chown <username> /dev/vfio/<iommu_group>
+    chown "$USERNAME" "/dev/vfio/$IOMMU_GROUP_ID"
 Depending on your system, you may also need to do:
     echo 1 | sudo tee /sys/module/vfio_iommu_type1/parameters/allow_unsafe_interrupts
 

+ 1 - 0
configure.ac

@@ -1188,6 +1188,7 @@ if test x$need_lowl_pci = xyes; then
 		AC_DEFINE([USE_VFIO], [1], [Defined to 1 if lowlevel PCI drivers should support VFIO])
 	fi
 fi
+AM_CONDITIONAL([USE_VFIO], [test x$need_lowl_pci$vfio = xyesyes])
 
 lowllist="$lowllist usb/need_lowl_usb"
 if test x$need_lowl_usb = xyes; then

+ 1 - 1
driver-bitforce.c

@@ -1635,7 +1635,7 @@ static bool bitforce_thread_init(struct thr_info *thr)
 		bitforce->sleep_ms = BITFORCE_SLEEP_MS;
 		bitforce->device_data = data = malloc(sizeof(*data));
 		*data = (struct bitforce_data){
-			.lowlif = &bfllif_vcom,
+			.lowlif = initdata->lowlif,
 			.xlink_id = xlink_id,
 			.next_work_ob = ">>>>>>>>|---------- MidState ----------||-DataTail-||Nonces|>>>>>>>>",
 			.proto = BFP_RANGE,

+ 10 - 6
lowl-pci.c

@@ -102,7 +102,7 @@ struct lowl_pci_handle {
 	off_t baroff[6];
 #endif
 #ifdef USE_LOWL_PCI_MMAP
-	uint32_t *bar[6];
+	volatile uint32_t *bar[6];
 	size_t barsz[6];
 #endif
 };
@@ -113,20 +113,24 @@ void lowl_pci_close_mmap(struct lowl_pci_handle * const lph)
 {
 	for (int i = 0; i < 6; ++i)
 		if (lph->bar[i])
-			munmap(lph->bar[i], lph->barsz[i]);
+			munmap((void*)lph->bar[i], lph->barsz[i]);
 	free(lph);
 }
 
 static
 const uint32_t *lowl_pci_get_words_mmap(struct lowl_pci_handle * const lph, void * const buf, const size_t words, const int bar, const off_t offset)
 {
-	return &lph->bar[bar][offset];
+	volatile uint32_t *src = &lph->bar[bar][offset];
+	uint32_t *dest = buf;
+	for (int i = 0; i < words; ++i)
+		*(dest++) = *(src++);
+	return buf;
 }
 
 static
 bool lowl_pci_set_words_mmap(struct lowl_pci_handle * const lph, const uint32_t *buf, const size_t words, const int bar, const off_t offset)
 {
-	uint32_t *dest = &lph->bar[bar][offset];
+	volatile uint32_t *dest = &lph->bar[bar][offset];
 	for (int i = 0; i < words; ++i)
 		*(dest++) = *(buf++);
 	return true;
@@ -242,7 +246,7 @@ struct lowl_pci_handle *lowl_pci_open_uio(const char * const path, const struct
 err:
 	for (int i = 0; i < 6; ++i)
 		if (lph->bar[i])
-			munmap(lph->bar[i], lph->barsz[i]);
+			munmap((void*)lph->bar[i], lph->barsz[i]);
 	free(lph);
 	return NULL;
 }
@@ -396,7 +400,7 @@ struct lowl_pci_handle *lowl_pci_open_vfio(const char * const path, const struct
 err:
 	for (int i = 0; i < 6; ++i)
 		if (lph->bar[i])
-			munmap(lph->bar[i], lph->barsz[i]);
+			munmap((void*)lph->bar[i], lph->barsz[i]);
 	if (device != -1)
 		close(device);
 	if (group != -1)

+ 117 - 0
setup-vfio

@@ -0,0 +1,117 @@
+#!/bin/bash
+
+DEVICES_PATH=/sys/bus/pci/devices
+VFIO_MODULE="vfio-pci"
+VFIO_PCI_NEW_ID=/sys/bus/pci/drivers/${VFIO_MODULE}/new_id
+Interactive=true
+UnsafeInts=false
+CHOWN_USER=
+
+die() {
+	echo "$@" >&2
+	exit 1
+}
+
+dieusage() {
+	die "Usage: $0 [--unsafe] [--user <username>] [--yes] <vendor> <device>"
+}
+
+yesno() {
+	if ! $Interactive; then
+		$2
+		return
+	fi
+	while true; do
+		echo -n "$1 "
+		read answer
+		case "$answer" in
+		yes|y|ye)
+			return 0
+			;;
+		no|n)
+			return 1
+			;;
+		*)
+			echo "Please enter 'yes' or 'no'."
+		esac
+	done
+}
+
+while [ "$#" -gt 0 ]; do
+	case "$1" in
+	--help|-h)
+		dieusage
+		;;
+	--unsafe)
+		UnsafeInts=true
+		;;
+	--user|-u)
+		shift
+		CHOWN_USER="$1"
+		;;
+	--yes|-y)
+		Interactive=false
+		;;
+	*)
+		if [ -n "$WANT_VENDOR" ]; then
+			WANT_DEVICE="$1"
+		else
+			WANT_VENDOR="$1"
+		fi
+		;;
+	esac
+	shift
+done
+
+[ -n "$WANT_DEVICE" ] || dieusage
+
+modprobe ${VFIO_MODULE} || die 'Failed to load ${VFIO_MODULE} module'
+for TARGET_DEVICE_ID in $(ls $DEVICES_PATH); do
+	{ grep -q '^0x'"${WANT_VENDOR}" "${DEVICES_PATH}/${TARGET_DEVICE_ID}/vendor" && grep -q '^0x'"${WANT_DEVICE}" "${DEVICES_PATH}/${TARGET_DEVICE_ID}/device"; } || continue
+	
+	echo "Found $(lspci -s "$TARGET_DEVICE_ID")"
+	extradevs=
+	extradevsn=0
+	extradevsq=
+	for RELATED_DEVICE_ID in $(ls "${DEVICES_PATH}/${TARGET_DEVICE_ID}/iommu_group/devices/"); do
+		if [ "$RELATED_DEVICE_ID" = "$TARGET_DEVICE_ID" ] ||
+		 {
+		  { ! [ -e "${DEVICES_PATH}/${RELATED_DEVICE_ID}/driver" ]; } ||
+		  [ "$(basename "$(readlink "${DEVICES_PATH}/${RELATED_DEVICE_ID}/driver")")" = "${VFIO_MODULE}" ]
+		 } ||
+		 grep -q '^0x060400$' "${DEVICES_PATH}/${RELATED_DEVICE_ID}/class"; then
+			extradevsq="$extradevsq $RELATED_DEVICE_ID"
+		else
+			extradevs="$extradevs $RELATED_DEVICE_ID"
+			let ++extradevsn
+		fi
+	done
+	if [ "$extradevsn" -gt 0 ]; then
+		if [ $extradevsn -gt 1 ]; then
+			echo "Enabling VFIO for this device will also disable the following $extradevsn devices:"
+		else
+			echo "Enabling VFIO for this device will also disable this device:"
+		fi
+		for RELATED_DEVICE_ID in ${extradevs}; do
+			echo "- $(lspci -s "$RELATED_DEVICE_ID")"
+		done
+	fi
+	yesno 'Enable VFIO?' true || continue
+	
+	if $UnsafeInts; then
+		echo 1 >/sys/module/vfio_iommu_type1/parameters/allow_unsafe_interrupts || die 'Failed to enable unsafe interrupts'
+	fi
+	for RELATED_DEVICE_ID in ${extradevsq} ${extradevs}; do
+		if [ -e "${DEVICES_PATH}/${RELATED_DEVICE_ID}/driver" ]; then
+			echo "$RELATED_DEVICE_ID" >"${DEVICES_PATH}/${RELATED_DEVICE_ID}/driver/unbind" || die "Failed to unbind $RELATED_DEVICE_ID"
+		fi
+		echo "$(<"${DEVICES_PATH}/${RELATED_DEVICE_ID}/vendor") $(<"${DEVICES_PATH}/${RELATED_DEVICE_ID}/device")" >"${VFIO_PCI_NEW_ID}" || die "Failed to associate device id with ${VFIO_MODULE} module"
+	done
+	IOMMU_GROUP="$(basename "$(readlink "${DEVICES_PATH}/${TARGET_DEVICE_ID}/iommu_group")")"
+	VFIO_DEVICE="/dev/vfio/$IOMMU_GROUP"
+	[ -e "$VFIO_DEVICE" ] || die "$VFIO_DEVICE does not exist"
+	if [ -n "${CHOWN_USER}" ]; then
+		chown "${CHOWN_USER}" "$VFIO_DEVICE" || die "Failed to chown $VFIO_DEVICE to $CHOWN_USER"
+	fi
+	echo "VFIO enabled on $VFIO_DEVICE"
+done