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
This commit is contained in:
Andriy Gapon 2012-10-14 10:13:50 +00:00
parent a01d461b70
commit 851dbc07af
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=241540
2 changed files with 39 additions and 12 deletions

View File

@ -295,6 +295,13 @@ pcie_cfgregopen(uint64_t base, uint8_t minbus, uint8_t maxbus)
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, 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;
}
@ -344,13 +354,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;
}
}

View File

@ -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;
}