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
 bin_PROGRAMS	= bfgminer
 
 
+sbin_SCRIPTS =
+
 if HAVE_WINDOWS
 if HAVE_WINDOWS
 else
 else
 bin_SCRIPTS = start-bfgminer.sh
 bin_SCRIPTS = start-bfgminer.sh
@@ -354,6 +356,10 @@ endif
 
 
 if NEED_BFG_LOWL_PCI
 if NEED_BFG_LOWL_PCI
 bfgminer_SOURCES += lowl-pci.c lowl-pci.h
 bfgminer_SOURCES += lowl-pci.c lowl-pci.h
+
+if USE_VFIO
+sbin_SCRIPTS += setup-vfio
+endif
 endif
 endif
 
 
 if NEED_BFG_LOWL_SPI
 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
     sudo modprobe uio_pci_generic
     echo 1cf9 0001 | sudo tee /sys/bus/pci/drivers/uio_pci_generic/new_id
     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
     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):
 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
     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
 From that, you can identify its IOMMU group, and list all devices sharing that
 group:
 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
 All of the devices listed (other than the Monarch), if any, will need to be
 disabled and unbound! To do that, use:
 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:
 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:
 Depending on your system, you may also need to do:
     echo 1 | sudo tee /sys/module/vfio_iommu_type1/parameters/allow_unsafe_interrupts
     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])
 		AC_DEFINE([USE_VFIO], [1], [Defined to 1 if lowlevel PCI drivers should support VFIO])
 	fi
 	fi
 fi
 fi
+AM_CONDITIONAL([USE_VFIO], [test x$need_lowl_pci$vfio = xyesyes])
 
 
 lowllist="$lowllist usb/need_lowl_usb"
 lowllist="$lowllist usb/need_lowl_usb"
 if test x$need_lowl_usb = xyes; then
 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->sleep_ms = BITFORCE_SLEEP_MS;
 		bitforce->device_data = data = malloc(sizeof(*data));
 		bitforce->device_data = data = malloc(sizeof(*data));
 		*data = (struct bitforce_data){
 		*data = (struct bitforce_data){
-			.lowlif = &bfllif_vcom,
+			.lowlif = initdata->lowlif,
 			.xlink_id = xlink_id,
 			.xlink_id = xlink_id,
 			.next_work_ob = ">>>>>>>>|---------- MidState ----------||-DataTail-||Nonces|>>>>>>>>",
 			.next_work_ob = ">>>>>>>>|---------- MidState ----------||-DataTail-||Nonces|>>>>>>>>",
 			.proto = BFP_RANGE,
 			.proto = BFP_RANGE,

+ 10 - 6
lowl-pci.c

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