summaryrefslogtreecommitdiffstats
path: root/sys/i386
diff options
context:
space:
mode:
authoravg <avg@FreeBSD.org>2012-10-14 10:13:50 +0000
committeravg <avg@FreeBSD.org>2012-10-14 10:13:50 +0000
commit5da136c22f8a7f4f67eaf03852226d20ddd2b568 (patch)
tree5b8fc33f5aeba462358dbac389a6838848b993e8 /sys/i386
parent576f6682829894f83e9cae7e361f8865c033ab7f (diff)
downloadFreeBSD-src-5da136c22f8a7f4f67eaf03852226d20ddd2b568.zip
FreeBSD-src-5da136c22f8a7f4f67eaf03852226d20ddd2b568.tar.gz
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
Diffstat (limited to 'sys/i386')
-rw-r--r--sys/i386/pci/pci_cfgreg.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/sys/i386/pci/pci_cfgreg.c b/sys/i386/pci/pci_cfgreg.c
index ac641a8..651a36c 100644
--- a/sys/i386/pci/pci_cfgreg.c
+++ b/sys/i386/pci/pci_cfgreg.c
@@ -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, unsigned func, unsigned reg,
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, unsigned func, unsigned reg, int data,
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;
}
OpenPOWER on IntegriCloud