Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IOMMU cleanup #76

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 124 additions & 16 deletions include/iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,128 @@
#ifndef __IOMMU_H__
#define __IOMMU_H__

#define IOMMU_PCI_BUS 0x0
#define IOMMU_PCI_DEVICE 0x0
#define IOMMU_PCI_FUNCTION 0x2

/* fields of Device Table entry (incomplete list) */
#define IOMMU_DTE_Q0_V (1ULL << 0)
#define IOMMU_DTE_Q0_TV (1ULL << 1)
#define IOMMU_DTE_Q0_IR (1ULL << 61)
#define IOMMU_DTE_Q0_IW (1ULL << 62)

#define IOMMU_DTE_Q1_I (1ULL << (96 - 64))

#define IOMMU_DTE_Q2_IV (1ULL << (128 - 128))
#define IOMMU_DTE_Q2_IG (1ULL << (133 - 128))
#define IOMMU_DTE_Q2_INITPASS (1ULL << (184 - 128))
#define IOMMU_DTE_Q2_EINTPASS (1ULL << (185 - 128))
#define IOMMU_DTE_Q2_NMIPASS (1ULL << (186 - 128))

#define IOMMU_CAP_BA_LOW(c) (c + 4)
#define IOMMU_CAP_BA_LOW_ENABLE (1ULL << 0)

#define IOMMU_CAP_BA_HIGH(c) (c + 8)

/* indices into u64 table */
#define IOMMU_MMIO_DEVICE_TABLE_BA (0x00 >> 3)
#define IOMMU_MMIO_COMMAND_BUF_BA (0x08 >> 3)
#define IOMMU_MMIO_EVENT_LOG_BA (0x10 >> 3)
#define IOMMU_MMIO_CONTROL_REGISTER (0x18 >> 3)
#define IOMMU_MMIO_EXCLUSION_BASE (0x20 >> 3)
#define IOMMU_MMIO_EXCLUSION_LIMIT (0x28 >> 3)
#define IOMMU_MMIO_EXTENDED_FEATURE (0x30 >> 3)
#define IOMMU_MMIO_COMMAND_BUF_HEAD (0x2000 >> 3)
#define IOMMU_MMIO_COMMAND_BUF_TAIL (0x2008 >> 3)
#define IOMMU_MMIO_EVENT_LOG_HEAD (0x2010 >> 3)
#define IOMMU_MMIO_EVENT_LOG_TAIL (0x2018 >> 3)
#define IOMMU_MMIO_STATUS_REGISTER (0x2020 >> 3)

#define IOMMU_CR_IommuEn (1ULL << 0)
#define IOMMU_CR_HtTunEn (1ULL << 1)
#define IOMMU_CR_EventLogEn (1ULL << 2)
#define IOMMU_CR_EventIntEn (1ULL << 3)
#define IOMMU_CR_ComWaitIntEn (1ULL << 4)
#define IOMMU_CR_CmdBufEn (1ULL << 12)
#define IOMMU_CR_PPRLogEn (1ULL << 13)
#define IOMMU_CR_PprIntEn (1ULL << 14)
#define IOMMU_CR_PPREn (1ULL << 15)
#define IOMMU_CR_GTEn (1ULL << 16)
#define IOMMU_CR_GAEn (1ULL << 17)
#define IOMMU_CR_SmiFEn (1ULL << 22)
#define IOMMU_CR_SmiFLogEn (1ULL << 24)
#define IOMMU_CR_GALogEn (1ULL << 28)
#define IOMMU_CR_GAIntEn (1ULL << 29)
#define IOMMU_CR_DualPprLogEn (3ULL << 30)
#define IOMMU_CR_DualEventLogEn (3ULL << 32)
#define IOMMU_CR_DevTblSegEn (7ULL << 34)
#define IOMMU_CR_PrivAbrtEn (3ULL << 37)
#define IOMMU_CR_PprAutoRspEn (1ULL << 39)
#define IOMMU_CR_MarcEn (1ULL << 40)
#define IOMMU_CR_BlkStopMrkEn (1ULL << 41)
#define IOMMU_CR_PprAutoRspAon (1ULL << 42)

#define IOMMU_CR_ENABLE_ALL_MASK (IOMMU_CR_IommuEn | \
IOMMU_CR_HtTunEn | \
IOMMU_CR_EventLogEn | \
IOMMU_CR_EventIntEn | \
IOMMU_CR_ComWaitIntEn | \
IOMMU_CR_CmdBufEn | \
IOMMU_CR_PPRLogEn | \
IOMMU_CR_PprIntEn | \
IOMMU_CR_PPREn | \
IOMMU_CR_GTEn | \
IOMMU_CR_GAEn | \
IOMMU_CR_SmiFEn | \
IOMMU_CR_SmiFLogEn | \
IOMMU_CR_GALogEn | \
IOMMU_CR_GAIntEn | \
IOMMU_CR_DualPprLogEn | \
IOMMU_CR_DualEventLogEn | \
IOMMU_CR_DevTblSegEn | \
IOMMU_CR_PrivAbrtEn | \
IOMMU_CR_PprAutoRspEn | \
IOMMU_CR_MarcEn | \
IOMMU_CR_BlkStopMrkEn | \
IOMMU_CR_PprAutoRspAon)

#define IOMMU_EF_IASup (1ULL << 6)

#define COMPLETION_WAIT 1
#define INVALIDATE_DEVTAB_ENTRY 2
#define INVALIDATE_IOMMU_PAGES 3
#define INVALIDATE_IOTLB_PAGES 4
#define INVALIDATE_INTERRUPT_TABLE 5
#define PREFETCH_IOMMU_PAGES 6
#define COMPLETE_PPR_REQUEST 7
#define INVALIDATE_IOMMU_ALL 8

#define INVALID_CAP(c) ((c == 0) || (c == 0xFFFFFFFF) || (c == 0xFF))

/*
* Following are used to disable initial SLB protection only on
* platforms where DEV is present (Family 16h and older).
*/
#define DEV_PCI_BUS 0x0
#define DEV_PCI_DEVICE 0x18
#define DEV_PCI_FUNCTION 0x3

#define DEV_OP_OFFSET 4
#define DEV_DATA_OFFSET 8

#define DEV_CR 4

#define DEV_CR_SL_DEV_EN_MASK 1<<5

/* Family 17h and newer */
#define MCH_PCI_BUS 0x0
#define MCH_PCI_DEVICE 0x18
#define MCH_PCI_FUNCTION 0x0

#define MEMPROT_CR 0x384

#define MEMPROT_EN 1<<0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs brackets, otherwise ~MEMPROT_EN becomes (~1)<<0, same for DEV_CR_SL_DEV_EN_MASK above

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, I copied the problem to the new MEMPROT_EN define. So DEV_CR_SL_DEV_EN_MASK was already had the issue so how was this working? The disabling of DEV on the APU systems should have failed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was explicitly bracketed in the point it was used: https://github.com/TrenchBoot/landing-zone/pull/76/files#diff-06fe7dc01e61244778e4a79b20e826b83073d3dc18d726b5fa7a1ec5cf87a156R157

Doing it in the header file instead is safer, too many parentheses only hurt eyes but not the code.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes I see. I guess I should make everything consistent.


typedef struct dte {
u64 a, b, c, d;
} iommu_dte_t;
Expand All @@ -36,23 +158,9 @@ typedef struct __packed {
extern char event_log[PAGE_SIZE];
extern iommu_command_t command_buf[2];

void disable_memory_protection(void);

u32 iommu_locate(void);
u32 iommu_load_device_table(u32 cap, volatile u64 *completed);

/* Following are used to disable initial SLB protection only */

#define DEV_PCI_BUS 0x0
#define DEV_PCI_DEVICE 0x18
#define DEV_PCI_FUNCTION 0x3

#define DEV_OP_OFFSET 4
#define DEV_DATA_OFFSET 8

#define DEV_CR 4

#define DEV_CR_SL_DEV_EN_MASK 1<<5

u32 dev_locate(void);
void dev_disable_sl(u32 dev);

#endif /* __IOMMU_H__ */
118 changes: 0 additions & 118 deletions include/iommu_defs.h

This file was deleted.

41 changes: 30 additions & 11 deletions iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#include <types.h>
#include <pci.h>
#include <iommu.h>
#include <iommu_defs.h>

iommu_dte_t device_table[2 * PAGE_SIZE / sizeof(iommu_dte_t)] __page_data = {
[0 ... ARRAY_SIZE(device_table) - 1 ] = {
Expand Down Expand Up @@ -114,48 +113,68 @@ u32 iommu_locate(void)
PCI_DEVFN(IOMMU_PCI_DEVICE, IOMMU_PCI_FUNCTION));
}

u32 dev_locate(void)
static u32 dev_locate(void)
{
return _locate(DEV_PCI_BUS,
PCI_DEVFN(DEV_PCI_DEVICE, DEV_PCI_FUNCTION));
}

static inline u32 dev_read(u32 dev, u32 function, u32 index)
static inline u32 dev_read(u32 dev_cap, u32 function, u32 index)
{
u32 value;

pci_write(0, DEV_PCI_BUS,
PCI_DEVFN(DEV_PCI_DEVICE,DEV_PCI_FUNCTION),
dev + DEV_OP_OFFSET,
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),
dev + DEV_DATA_OFFSET,
dev_cap + DEV_DATA_OFFSET,
4, &value);

return value;
}

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

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

void dev_disable_sl(u32 dev)
static void dev_disable_sl(u32 dev_cap)
{
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(dev_cap, DEV_CR, 0);
dev_write(dev_cap, 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);
}

static void send_command(u64 *mmio_base, iommu_command_t cmd)
Expand Down
Loading