Skip to content

Commit

Permalink
dev: loop over CPU nodes on disabling memory protection
Browse files Browse the repository at this point in the history
DEV is specific to a northbridge, so there are multiple of them on
systems with several CPU sockets. 0x18 is the device number of the
first one with the rest using successive numbers (0x19, 0x1A, etc.).

Signed-off-by: Sergii Dmytruk <[email protected]>
  • Loading branch information
SergiiDmytruk committed Apr 17, 2024
1 parent 97b94fc commit 18f5358
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 29 deletions.
76 changes: 49 additions & 27 deletions dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,67 +20,89 @@
#include <pci.h>
#include <dev.h>

u32 dev_locate(void)
/*
* There are only 5 bits (0x00..0x1f) for PCI slot number (see definition of
* PCI_DEVFN) and we start at 0x18 (DEV_PCI_DEVICE), so there is hard upper
* limit on how many nodes can exist.
*/
#define MAX_CPU_NODES 8

u32 dev_locate(u8 cpu_node)
{
return pci_locate(DEV_PCI_BUS,
PCI_DEVFN(DEV_PCI_DEVICE, DEV_PCI_FUNCTION));
PCI_DEVFN(DEV_PCI_DEVICE + cpu_node, DEV_PCI_FUNCTION));
}

u32 dev_read(u32 dev_cap, u32 function, u32 index)
u32 dev_read(u8 cpu_node, u32 dev_cap, u32 function, u32 index)
{
u32 value;

pci_write(0, DEV_PCI_BUS,
PCI_DEVFN(DEV_PCI_DEVICE, DEV_PCI_FUNCTION),
PCI_DEVFN(DEV_PCI_DEVICE + cpu_node, DEV_PCI_FUNCTION),
dev_cap + DEV_OP_OFFSET,
4,
(u32)(((function & 0xff) << 8) + (index & 0xff)));

pci_read(0, DEV_PCI_BUS,
PCI_DEVFN(DEV_PCI_DEVICE, DEV_PCI_FUNCTION),
PCI_DEVFN(DEV_PCI_DEVICE + cpu_node, DEV_PCI_FUNCTION),
dev_cap + DEV_DATA_OFFSET,
4, &value);

return value;
}

void dev_write(u32 dev, u32 function, u32 index, u32 value)
void dev_write(u8 cpu_node, u32 dev, u32 function, u32 index, u32 value)
{
pci_write(0, DEV_PCI_BUS,
PCI_DEVFN(DEV_PCI_DEVICE, DEV_PCI_FUNCTION),
PCI_DEVFN(DEV_PCI_DEVICE + cpu_node, DEV_PCI_FUNCTION),
dev + DEV_OP_OFFSET,
4,
(u32)(((function & 0xff) << 8) + (index & 0xff)) );

pci_write(0, DEV_PCI_BUS,
PCI_DEVFN(DEV_PCI_DEVICE, DEV_PCI_FUNCTION),
PCI_DEVFN(DEV_PCI_DEVICE + cpu_node, DEV_PCI_FUNCTION),
dev + DEV_DATA_OFFSET,
4, value);
}

void dev_disable_sl(u32 dev)
void dev_disable_sl(u8 cpu_node, u32 dev)
{
u32 dev_cr = dev_read(dev, DEV_CR, 0);
dev_write(dev, DEV_CR, 0, dev_cr & ~(DEV_CR_SL_DEV_EN_MASK));
u32 dev_cr = dev_read(cpu_node, dev, DEV_CR, 0);
dev_write(cpu_node, dev, DEV_CR, 0, dev_cr & ~(DEV_CR_SL_DEV_EN_MASK));
}

void disable_memory_protection(void)
{
u32 dev_cap, sldev;

dev_cap = dev_locate();
if (dev_cap) {
/* Older families with remains of DEV */
dev_disable_sl(dev_cap);
return;
}

/* Fam 17h uses different DMA protection control register */
pci_read(0, MCH_PCI_BUS,
PCI_DEVFN(MCH_PCI_DEVICE, MCH_PCI_FUNCTION),
MEMPROT_CR, 4, &sldev);
pci_write(0, MCH_PCI_BUS,
PCI_DEVFN(MCH_PCI_DEVICE, MCH_PCI_FUNCTION),
MEMPROT_CR, 4, sldev & ~(MEMPROT_EN));
u32 dev_cap, sldev, vid_did;
u8 cpu_node = 0;

dev_cap = dev_locate(cpu_node);
if (dev_cap) {
/* Older families with remains of DEV */
do {
dev_disable_sl(cpu_node, dev_cap);

cpu_node++;
if (cpu_node == MAX_CPU_NODES)
break;

dev_cap = dev_locate(cpu_node);
} while (dev_cap);
return;
}

/* Fam 17h uses different DMA protection control register */
while (cpu_node < MAX_CPU_NODES &&
pci_read(0, MCH_PCI_BUS,
PCI_DEVFN(MCH_PCI_DEVICE + cpu_node, MCH_PCI_FUNCTION),
VIDDID, 4, &vid_did) == 0 &&
vid_did != 0xffffffffU) {
u8 devfn = PCI_DEVFN(MCH_PCI_DEVICE + cpu_node, MCH_PCI_FUNCTION);

pci_read(0, MCH_PCI_BUS, devfn, MEMPROT_CR, 4, &sldev);
pci_write(0, MCH_PCI_BUS, devfn, MEMPROT_CR, 4, sldev & ~(MEMPROT_EN));

cpu_node++;
}
}

5 changes: 3 additions & 2 deletions include/dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,13 @@
#define MCH_PCI_DEVICE 0x18
#define MCH_PCI_FUNCTION 0x0

#define VIDDID 0
#define MEMPROT_CR 0x384

#define MEMPROT_EN (1<<0)

u32 dev_locate(void);
void dev_disable_sl(u32 dev);
u32 dev_locate(u8 cpu_node);
void dev_disable_sl(u8 cpu_node, u32 dev);
void disable_memory_protection(void);

#endif /* __DEV_H__ */

0 comments on commit 18f5358

Please sign in to comment.