Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 14 Oct 2012 10:13:51 +0000 (UTC)
From:      Andriy Gapon <avg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r241540 - in head/sys: amd64/pci i386/pci
Message-ID:  <201210141013.q9EADp7c039401@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: avg
Date: Sun Oct 14 10:13:50 2012
New Revision: 241540
URL: http://svn.freebsd.org/changeset/base/241540

Log:
  pciereg_cfg*: use assembly to access the mem-mapped cfg space
  
  AMD BKDG for CPU families 10h and later requires that the memory
  mapped config is always read into or written from al/ax/eax register.
  
  Discussed with:	kib, alc
  Reviewed by:	kib (earlier version)
  MFC after:	25 days

Modified:
  head/sys/amd64/pci/pci_cfgreg.c
  head/sys/i386/pci/pci_cfgreg.c

Modified: head/sys/amd64/pci/pci_cfgreg.c
==============================================================================
--- head/sys/amd64/pci/pci_cfgreg.c	Sun Oct 14 10:12:32 2012	(r241539)
+++ head/sys/amd64/pci/pci_cfgreg.c	Sun Oct 14 10:13:50 2012	(r241540)
@@ -295,6 +295,13 @@ pcie_cfgregopen(uint64_t base, uint8_t m
 	return (1);
 }
 
+/*
+ * AMD BIOS And Kernel Developer's Guides for CPU families starting with 10h
+ * have a requirement that all accesses to the memory mapped PCI configuration
+ * space are done using AX class of registers.
+ * Since other vendors do not currently have any contradicting requirements
+ * the AMD access pattern is applied universally.
+ */
 #define PCIE_VADDR(base, reg, bus, slot, func)	\
 	((base)				+	\
 	((((bus) & 0xff) << 20)		|	\
@@ -317,13 +324,16 @@ pciereg_cfgread(int bus, unsigned slot, 
 
 	switch (bytes) {
 	case 4:
-		data = *(volatile uint32_t *)(va);
+		__asm __volatile("mov %1, %%eax" : "=a" (data)
+		    : "m" (*(uint32_t *)va));
 		break;
 	case 2:
-		data = *(volatile uint16_t *)(va);
+		__asm __volatile("movzwl %1, %%eax" : "=a" (data)
+		    : "m" (*(uint16_t *)va));
 		break;
 	case 1:
-		data = *(volatile uint8_t *)(va);
+		__asm __volatile("movzbl %1, %%eax" : "=a" (data)
+		    : "m" (*(uint8_t *)va));
 		break;
 	}
 
@@ -344,13 +354,16 @@ pciereg_cfgwrite(int bus, unsigned slot,
 
 	switch (bytes) {
 	case 4:
-		*(volatile uint32_t *)(va) = data;
+		__asm __volatile("mov %%eax, %0" : "=m" (*(uint32_t *)va)
+		    : "a" (data));
 		break;
 	case 2:
-		*(volatile uint16_t *)(va) = data;
+		__asm __volatile("mov %%ax, %0" : "=m" (*(uint16_t *)va)
+		    : "a" (data));
 		break;
 	case 1:
-		*(volatile uint8_t *)(va) = data;
+		__asm __volatile("mov %%al, %0" : "=m" (*(uint8_t *)va)
+		    : "a" (data));
 		break;
 	}
 }

Modified: head/sys/i386/pci/pci_cfgreg.c
==============================================================================
--- head/sys/i386/pci/pci_cfgreg.c	Sun Oct 14 10:12:32 2012	(r241539)
+++ head/sys/i386/pci/pci_cfgreg.c	Sun Oct 14 10:13:50 2012	(r241540)
@@ -652,6 +652,14 @@ pciereg_findelem(vm_paddr_t papage)
 	return (elem);
 }
 
+/*
+ * AMD BIOS And Kernel Developer's Guides for CPU families starting with 10h
+ * have a requirement that all accesses to the memory mapped PCI configuration
+ * space are done using AX class of registers.
+ * Since other vendors do not currently have any contradicting requirements
+ * the AMD access pattern is applied universally.
+ */
+
 static int
 pciereg_cfgread(int bus, unsigned slot, unsigned func, unsigned reg,
     unsigned bytes)
@@ -673,13 +681,16 @@ pciereg_cfgread(int bus, unsigned slot, 
 
 	switch (bytes) {
 	case 4:
-		data = *(volatile uint32_t *)(va);
+		__asm __volatile("mov %1, %%eax" : "=a" (data)
+		    : "m" (*(uint32_t *)va));
 		break;
 	case 2:
-		data = *(volatile uint16_t *)(va);
+		__asm __volatile("movzwl %1, %%eax" : "=a" (data)
+		    : "m" (*(uint16_t *)va));
 		break;
 	case 1:
-		data = *(volatile uint8_t *)(va);
+		__asm __volatile("movzbl %1, %%eax" : "=a" (data)
+		    : "m" (*(uint8_t *)va));
 		break;
 	}
 
@@ -707,13 +718,16 @@ pciereg_cfgwrite(int bus, unsigned slot,
 
 	switch (bytes) {
 	case 4:
-		*(volatile uint32_t *)(va) = data;
+		__asm __volatile("mov %%eax, %0" : "=m" (*(uint32_t *)va)
+		    : "a" (data));
 		break;
 	case 2:
-		*(volatile uint16_t *)(va) = data;
+		__asm __volatile("mov %%ax, %0" : "=m" (*(uint16_t *)va)
+		    : "a" (data));
 		break;
 	case 1:
-		*(volatile uint8_t *)(va) = data;
+		__asm __volatile("mov %%al, %0" : "=m" (*(uint8_t *)va)
+		    : "a" (data));
 		break;
 	}
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201210141013.q9EADp7c039401>