diff options
author | avg <avg@FreeBSD.org> | 2012-10-14 10:13:50 +0000 |
---|---|---|
committer | avg <avg@FreeBSD.org> | 2012-10-14 10:13:50 +0000 |
commit | 5da136c22f8a7f4f67eaf03852226d20ddd2b568 (patch) | |
tree | 5b8fc33f5aeba462358dbac389a6838848b993e8 /sys/i386 | |
parent | 576f6682829894f83e9cae7e361f8865c033ab7f (diff) | |
download | FreeBSD-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.c | 26 |
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; } |