AMD IOMMU: Allocate I/O pagetable from domheap instead of xenheap

Signed-off-by: Wei Wang <wei.wang2@amd.com>
This commit is contained in:
Keir Fraser committed 2009-01-09 15:57:57 +00:00
1 parent 0d1fa649fe
commit 49e486455b
6 files changed
+177 -144

No files matched your search

+14 -10
View File
@@ -535,10 +535,11 @@ void __init enable_iommu(struct amd_iommu *iommu)
static void __init deallocate_iommu_table_struct(
struct table_struct *table)
{
int order = 0;
if ( table->buffer )
{
free_xenheap_pages(table->buffer,
get_order_from_bytes(table->alloc_size));
order = get_order_from_bytes(table->alloc_size);
__free_amd_iommu_tables(table->buffer, order);
table->buffer = NULL;
}
}
@@ -552,16 +553,19 @@ static void __init deallocate_iommu_tables(struct amd_iommu *iommu)
static int __init allocate_iommu_table_struct(struct table_struct *table,
const char *name)
{
table->buffer = (void *) alloc_xenheap_pages(
get_order_from_bytes(table->alloc_size));
if ( !table->buffer )
int order = 0;
if ( table->buffer == NULL )
{
amd_iov_error("Error allocating %s\n", name);
return -ENOMEM;
}
order = get_order_from_bytes(table->alloc_size);
table->buffer = __alloc_amd_iommu_tables(order);
memset(table->buffer, 0, table->alloc_size);
if ( table->buffer == NULL )
{
amd_iov_error("Error allocating %s\n", name);
return -ENOMEM;
}
memset(table->buffer, 0, PAGE_SIZE * (1UL << order));
}
return 0;
}
+10 -6
View File
@@ -22,6 +22,7 @@
#include <asm/amd-iommu.h>
#include <asm/hvm/svm/amd-iommu-proto.h>
#define INTREMAP_TABLE_ORDER 1
DEFINE_SPINLOCK(int_remap_table_lock);
void *int_remap_table = NULL;
@@ -112,14 +113,17 @@ int __init amd_iommu_setup_intremap_table(void)
unsigned long flags;
spin_lock_irqsave(&int_remap_table_lock, flags);
if ( int_remap_table == NULL )
int_remap_table = (void *)alloc_xenheap_pages(1);
if ( !int_remap_table )
{
spin_unlock_irqrestore(&int_remap_table_lock, flags);
return -ENOMEM;
int_remap_table = __alloc_amd_iommu_tables(INTREMAP_TABLE_ORDER);
if ( int_remap_table == NULL )
{
spin_unlock_irqrestore(&int_remap_table_lock, flags);
return -ENOMEM;
}
memset(int_remap_table, 0, PAGE_SIZE * (1UL << INTREMAP_TABLE_ORDER));
}
memset((u8*)int_remap_table, 0, PAGE_SIZE*2);
spin_unlock_irqrestore(&int_remap_table_lock, flags);
return 0;
@@ -211,7 +215,7 @@ int __init deallocate_intremap_table(void)
spin_lock_irqsave(&int_remap_table_lock, flags);
if ( int_remap_table )
{
free_xenheap_pages(int_remap_table, 1);
__free_amd_iommu_tables(int_remap_table, INTREMAP_TABLE_ORDER);
int_remap_table = NULL;
}
spin_unlock_irqrestore(&int_remap_table_lock, flags);
+77 -61
View File
@@ -159,21 +159,39 @@ void flush_command_buffer(struct amd_iommu *iommu)
}
}
static void clear_page_table_entry_present(u32 *pte)
static void clear_iommu_l1e_present(u64 l2e, unsigned long gfn)
{
set_field_in_reg_u32(IOMMU_CONTROL_DISABLED, pte[0],
IOMMU_PTE_PRESENT_MASK,
IOMMU_PTE_PRESENT_SHIFT, &pte[0]);
u32 *l1e;
int offset;
void *l1_table;
l1_table = map_domain_page(l2e >> PAGE_SHIFT);
offset = gfn & (~PTE_PER_TABLE_MASK);
l1e = (u32*)(l1_table + (offset * IOMMU_PAGE_TABLE_ENTRY_SIZE));
/* clear l1 entry */
l1e[0] = l1e[1] = 0;
unmap_domain_page(l1_table);
}
static void set_page_table_entry_present(u32 *pte, u64 page_addr,
int iw, int ir)
static void set_iommu_l1e_present(u64 l2e, unsigned long gfn,
u64 maddr, int iw, int ir)
{
u64 addr_lo, addr_hi;
u32 entry;
void *l1_table;
int offset;
u32 *l1e;
addr_lo = page_addr & DMA_32BIT_MASK;
addr_hi = page_addr >> 32;
l1_table = map_domain_page(l2e >> PAGE_SHIFT);
offset = gfn & (~PTE_PER_TABLE_MASK);
l1e = (u32*)((u8*)l1_table + (offset * IOMMU_PAGE_TABLE_ENTRY_SIZE));
addr_lo = maddr & DMA_32BIT_MASK;
addr_hi = maddr >> 32;
set_field_in_reg_u32((u32)addr_hi, 0,
IOMMU_PTE_ADDR_HIGH_MASK,
@@ -186,7 +204,7 @@ static void set_page_table_entry_present(u32 *pte, u64 page_addr,
IOMMU_CONTROL_DISABLED, entry,
IOMMU_PTE_IO_READ_PERMISSION_MASK,
IOMMU_PTE_IO_READ_PERMISSION_SHIFT, &entry);
pte[1] = entry;
l1e[1] = entry;
set_field_in_reg_u32((u32)addr_lo >> PAGE_SHIFT, 0,
IOMMU_PTE_ADDR_LOW_MASK,
@@ -197,9 +215,10 @@ static void set_page_table_entry_present(u32 *pte, u64 page_addr,
set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
IOMMU_PTE_PRESENT_MASK,
IOMMU_PTE_PRESENT_SHIFT, &entry);
pte[0] = entry;
}
l1e[0] = entry;
unmap_domain_page(l1_table);
}
static void amd_iommu_set_page_directory_entry(u32 *pde,
u64 next_ptr, u8 next_level)
@@ -327,7 +346,7 @@ void amd_iommu_set_dev_table_entry(u32 *dte, u64 root_ptr, u64 intremap_ptr,
dte[0] = entry;
}
void *amd_iommu_get_vptr_from_page_table_entry(u32 *entry)
u64 amd_iommu_get_next_table_from_pte(u32 *entry)
{
u64 addr_lo, addr_hi, ptr;
@@ -342,7 +361,7 @@ void *amd_iommu_get_vptr_from_page_table_entry(u32 *entry)
IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_SHIFT);
ptr = (addr_hi << 32) | (addr_lo << PAGE_SHIFT);
return ptr ? maddr_to_virt((unsigned long)ptr) : NULL;
return ptr;
}
static int amd_iommu_is_pte_present(u32 *entry)
@@ -381,54 +400,53 @@ int amd_iommu_is_dte_page_translation_valid(u32 *entry)
IOMMU_DEV_TABLE_TRANSLATION_VALID_SHIFT));
}
static void *get_pte_from_page_tables(void *table, int level,
unsigned long io_pfn)
static u64 iommu_l2e_from_pfn(struct page_info *table, int level,
unsigned long io_pfn)
{
unsigned long offset;
void *pde = NULL;
void *table_vaddr;
u64 next_table_maddr = 0;
BUG_ON(table == NULL);
BUG_ON( table == NULL || level == 0 );
while ( level > 0 )
while ( level > 1 )
{
offset = io_pfn >> ((PTE_PER_TABLE_SHIFT *
(level - IOMMU_PAGING_MODE_LEVEL_1)));
offset &= ~PTE_PER_TABLE_MASK;
pde = table + (offset * IOMMU_PAGE_TABLE_ENTRY_SIZE);
if ( level == 1 )
break;
if ( !pde )
return NULL;
table_vaddr = map_domain_page(page_to_mfn(table));
pde = table_vaddr + (offset * IOMMU_PAGE_TABLE_ENTRY_SIZE);
next_table_maddr = amd_iommu_get_next_table_from_pte(pde);
if ( !amd_iommu_is_pte_present(pde) )
{
void *next_table = alloc_xenheap_page();
if ( next_table == NULL )
return NULL;
memset(next_table, 0, PAGE_SIZE);
if ( *(u64 *)pde == 0 )
if ( next_table_maddr == 0 )
{
unsigned long next_ptr = (u64)virt_to_maddr(next_table);
table = alloc_amd_iommu_pgtable();
if ( table == NULL )
return 0;
next_table_maddr = page_to_maddr(table);
amd_iommu_set_page_directory_entry(
(u32 *)pde, next_ptr, level - 1);
}
else
{
free_xenheap_page(next_table);
(u32 *)pde, next_table_maddr, level - 1);
}
else /* should never reach here */
return 0;
}
table = amd_iommu_get_vptr_from_page_table_entry(pde);
unmap_domain_page(table_vaddr);
table = maddr_to_page(next_table_maddr);
level--;
}
return pde;
return next_table_maddr;
}
int amd_iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn)
{
void *pte;
u64 iommu_l2e;
unsigned long flags;
u64 maddr;
struct hvm_iommu *hd = domain_hvm_iommu(d);
int iw = IOMMU_IO_WRITE_ENABLED;
int ir = IOMMU_IO_READ_ENABLED;
@@ -440,16 +458,15 @@ int amd_iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn)
if ( is_hvm_domain(d) && !hd->p2m_synchronized )
goto out;
maddr = (u64)mfn << PAGE_SHIFT;
pte = get_pte_from_page_tables(hd->root_table, hd->paging_mode, gfn);
if ( pte == NULL )
iommu_l2e = iommu_l2e_from_pfn(hd->root_table, hd->paging_mode, gfn);
if ( iommu_l2e == 0 )
{
amd_iov_error("Invalid IO pagetable entry gfn = %lx\n", gfn);
spin_unlock_irqrestore(&hd->mapping_lock, flags);
return -EFAULT;
}
set_iommu_l1e_present(iommu_l2e, gfn, (u64)mfn << PAGE_SHIFT, iw, ir);
set_page_table_entry_present((u32 *)pte, maddr, iw, ir);
out:
spin_unlock_irqrestore(&hd->mapping_lock, flags);
return 0;
@@ -457,10 +474,8 @@ out:
int amd_iommu_unmap_page(struct domain *d, unsigned long gfn)
{
void *pte;
u64 iommu_l2e;
unsigned long flags;
u64 io_addr = gfn;
int requestor_id;
struct amd_iommu *iommu;
struct hvm_iommu *hd = domain_hvm_iommu(d);
@@ -474,11 +489,9 @@ int amd_iommu_unmap_page(struct domain *d, unsigned long gfn)
return 0;
}
requestor_id = hd->domain_id;
io_addr = (u64)gfn << PAGE_SHIFT;
iommu_l2e = iommu_l2e_from_pfn(hd->root_table, hd->paging_mode, gfn);
pte = get_pte_from_page_tables(hd->root_table, hd->paging_mode, gfn);
if ( pte == NULL )
if ( iommu_l2e == 0 )
{
amd_iov_error("Invalid IO pagetable entry gfn = %lx\n", gfn);
spin_unlock_irqrestore(&hd->mapping_lock, flags);
@@ -486,14 +499,14 @@ int amd_iommu_unmap_page(struct domain *d, unsigned long gfn)
}
/* mark PTE as 'page not present' */
clear_page_table_entry_present((u32 *)pte);
clear_iommu_l1e_present(iommu_l2e, gfn);
spin_unlock_irqrestore(&hd->mapping_lock, flags);
/* send INVALIDATE_IOMMU_PAGES command */
for_each_amd_iommu ( iommu )
{
spin_lock_irqsave(&iommu->lock, flags);
invalidate_iommu_page(iommu, io_addr, requestor_id);
invalidate_iommu_page(iommu, (u64)gfn << PAGE_SHIFT, hd->domain_id);
flush_command_buffer(iommu);
spin_unlock_irqrestore(&iommu->lock, flags);
}
@@ -506,8 +519,8 @@ int amd_iommu_reserve_domain_unity_map(
unsigned long phys_addr,
unsigned long size, int iw, int ir)
{
u64 iommu_l2e;
unsigned long flags, npages, i;
void *pte;
struct hvm_iommu *hd = domain_hvm_iommu(domain);
npages = region_to_pages(phys_addr, size);
@@ -515,17 +528,20 @@ int amd_iommu_reserve_domain_unity_map(
spin_lock_irqsave(&hd->mapping_lock, flags);
for ( i = 0; i < npages; ++i )
{
pte = get_pte_from_page_tables(
iommu_l2e = iommu_l2e_from_pfn(
hd->root_table, hd->paging_mode, phys_addr >> PAGE_SHIFT);
if ( pte == NULL )
if ( iommu_l2e == 0 )
{
amd_iov_error(
"Invalid IO pagetable entry phys_addr = %lx\n", phys_addr);
spin_unlock_irqrestore(&hd->mapping_lock, flags);
return -EFAULT;
}
set_page_table_entry_present((u32 *)pte,
phys_addr, iw, ir);
set_iommu_l1e_present(iommu_l2e,
(phys_addr >> PAGE_SHIFT), phys_addr, iw, ir);
phys_addr += PAGE_SIZE;
}
spin_unlock_irqrestore(&hd->mapping_lock, flags);
@@ -535,8 +551,7 @@ int amd_iommu_reserve_domain_unity_map(
int amd_iommu_sync_p2m(struct domain *d)
{
unsigned long mfn, gfn, flags;
void *pte;
u64 maddr;
u64 iommu_l2e;
struct list_head *entry;
struct page_info *page;
struct hvm_iommu *hd;
@@ -563,15 +578,16 @@ int amd_iommu_sync_p2m(struct domain *d)
if ( gfn == INVALID_M2P_ENTRY )
continue;
maddr = (u64)mfn << PAGE_SHIFT;
pte = get_pte_from_page_tables(hd->root_table, hd->paging_mode, gfn);
if ( pte == NULL )
iommu_l2e = iommu_l2e_from_pfn(hd->root_table, hd->paging_mode, gfn);
if ( iommu_l2e == 0 )
{
amd_iov_error("Invalid IO pagetable entry gfn = %lx\n", gfn);
spin_unlock_irqrestore(&hd->mapping_lock, flags);
return -EFAULT;
}
set_page_table_entry_present((u32 *)pte, maddr, iw, ir);
set_iommu_l1e_present(iommu_l2e, gfn, (u64)mfn << PAGE_SHIFT, iw, ir);
}
hd->p2m_synchronized = 1;
+40 -63
View File
@@ -29,17 +29,6 @@ extern unsigned short ivrs_bdf_entries;
extern struct ivrs_mappings *ivrs_mappings;
extern void *int_remap_table;
static void deallocate_domain_page_tables(struct hvm_iommu *hd)
{
if ( hd->root_table )
free_xenheap_page(hd->root_table);
}
static void deallocate_domain_resources(struct hvm_iommu *hd)
{
deallocate_domain_page_tables(hd);
}
int __init amd_iommu_init(void)
{
struct amd_iommu *iommu;
@@ -79,8 +68,6 @@ static void amd_iommu_setup_domain_device(
struct domain *domain, struct amd_iommu *iommu, int bdf)
{
void *dte;
u64 root_ptr;
u64 intremap_ptr;
unsigned long flags;
int req_id;
u8 sys_mgt, dev_ex;
@@ -88,22 +75,21 @@ static void amd_iommu_setup_domain_device(
BUG_ON( !hd->root_table || !hd->paging_mode || !int_remap_table );
root_ptr = (u64)virt_to_maddr(hd->root_table);
/* get device-table entry */
req_id = ivrs_mappings[bdf].dte_requestor_id;
dte = iommu->dev_table.buffer +
(req_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
dte = iommu->dev_table.buffer + (req_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
intremap_ptr = (u64)virt_to_maddr(int_remap_table);
spin_lock_irqsave(&iommu->lock, flags);
if ( !amd_iommu_is_dte_page_translation_valid((u32 *)dte) )
{
spin_lock_irqsave(&iommu->lock, flags);
/* bind DTE to domain page-tables */
sys_mgt = ivrs_mappings[req_id].dte_sys_mgt_enable;
dev_ex = ivrs_mappings[req_id].dte_allow_exclusion;
amd_iommu_set_dev_table_entry((u32 *)dte, root_ptr, intremap_ptr,
amd_iommu_set_dev_table_entry((u32 *)dte,
page_to_maddr(hd->root_table),
virt_to_maddr(int_remap_table),
hd->domain_id, sys_mgt, dev_ex,
hd->paging_mode);
@@ -111,11 +97,15 @@ static void amd_iommu_setup_domain_device(
invalidate_interrupt_table(iommu, req_id);
flush_command_buffer(iommu);
amd_iov_info("Enable DTE:0x%x, "
"root_ptr:%"PRIx64", domain_id:%d, paging_mode:%d\n",
req_id, root_ptr, hd->domain_id, hd->paging_mode);
spin_unlock_irqrestore(&iommu->lock, flags);
"root_table:%"PRIx64", interrupt_table:%"PRIx64", "
"domain_id:%d, paging_mode:%d\n",
req_id, (u64)page_to_maddr(hd->root_table),
(u64)virt_to_maddr(int_remap_table), hd->domain_id,
hd->paging_mode);
}
spin_unlock_irqrestore(&iommu->lock, flags);
}
static void amd_iommu_setup_dom0_devices(struct domain *d)
@@ -188,10 +178,9 @@ static int allocate_domain_resources(struct hvm_iommu *hd)
spin_lock_irqsave(&hd->mapping_lock, flags);
if ( !hd->root_table )
{
hd->root_table = (void *)alloc_xenheap_page();
hd->root_table = alloc_amd_iommu_pgtable();
if ( !hd->root_table )
goto error_out;
memset((u8*)hd->root_table, 0, PAGE_SIZE);
}
spin_unlock_irqrestore(&hd->mapping_lock, flags);
@@ -228,7 +217,8 @@ static int amd_iommu_domain_init(struct domain *domain)
/* allocate page directroy */
if ( allocate_domain_resources(hd) != 0 )
{
deallocate_domain_resources(hd);
if ( hd->root_table )
free_domheap_page(hd->root_table);
return -ENOMEM;
}
@@ -258,12 +248,11 @@ static void amd_iommu_disable_domain_device(
int req_id;
req_id = ivrs_mappings[bdf].dte_requestor_id;
dte = iommu->dev_table.buffer +
(req_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
dte = iommu->dev_table.buffer + (req_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
spin_lock_irqsave(&iommu->lock, flags);
if ( amd_iommu_is_dte_page_translation_valid((u32 *)dte) )
{
spin_lock_irqsave(&iommu->lock, flags);
memset (dte, 0, IOMMU_DEV_TABLE_ENTRY_SIZE);
invalidate_dev_table_entry(iommu, req_id);
flush_command_buffer(iommu);
@@ -271,8 +260,8 @@ static void amd_iommu_disable_domain_device(
" domain_id:%d, paging_mode:%d\n",
req_id, domain_hvm_iommu(domain)->domain_id,
domain_hvm_iommu(domain)->paging_mode);
spin_unlock_irqrestore(&iommu->lock, flags);
}
spin_unlock_irqrestore(&iommu->lock, flags);
}
static int reassign_device( struct domain *source, struct domain *target,
@@ -338,56 +327,44 @@ static int amd_iommu_assign_device(struct domain *d, u8 bus, u8 devfn)
return reassign_device(dom0, d, bus, devfn);
}
static void deallocate_next_page_table(void *table, unsigned long index,
int level)
static void deallocate_next_page_table(struct page_info* pg, int level)
{
unsigned long next_index;
void *next_table, *pde;
int next_level;
void *table_vaddr, *pde;
u64 next_table_maddr;
int index;
pde = table + (index * IOMMU_PAGE_TABLE_ENTRY_SIZE);
next_table = amd_iommu_get_vptr_from_page_table_entry((u32 *)pde);
table_vaddr = map_domain_page(page_to_mfn(pg));
if ( next_table )
if ( level > 1 )
{
next_level = level - 1;
if ( next_level > 1 )
for ( index = 0; index < PTE_PER_TABLE_SIZE; index++ )
{
next_index = 0;
do
pde = table_vaddr + (index * IOMMU_PAGE_TABLE_ENTRY_SIZE);
next_table_maddr = amd_iommu_get_next_table_from_pte(pde);
if ( next_table_maddr != 0 )
{
deallocate_next_page_table(next_table,
next_index, next_level);
next_index++;
} while (next_index < PTE_PER_TABLE_SIZE);
deallocate_next_page_table(
maddr_to_page(next_table_maddr), level - 1);
}
}
free_xenheap_page(next_table);
}
unmap_domain_page(table_vaddr);
free_amd_iommu_pgtable(pg);
}
static void deallocate_iommu_page_tables(struct domain *d)
{
unsigned long index;
struct hvm_iommu *hd = domain_hvm_iommu(d);
if ( hd ->root_table )
if ( hd->root_table )
{
index = 0;
do
{
deallocate_next_page_table(hd->root_table,
index, hd->paging_mode);
index++;
} while ( index < PTE_PER_TABLE_SIZE );
free_xenheap_page(hd ->root_table);
deallocate_next_page_table(hd->root_table, hd->paging_mode);
hd->root_table = NULL;
}
hd ->root_table = NULL;
}
static void amd_iommu_domain_destroy(struct domain *d)
{
deallocate_iommu_page_tables(d);
+35 -3
View File
@@ -23,6 +23,7 @@
#include <xen/sched.h>
#include <asm/amd-iommu.h>
#include <xen/domain_page.h>
#define for_each_amd_iommu(amd_iommu) \
list_for_each_entry(amd_iommu, \
@@ -59,7 +60,7 @@ int __init amd_iommu_setup_shared_tables(void);
/* mapping functions */
int amd_iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn);
int amd_iommu_unmap_page(struct domain *d, unsigned long gfn);
void *amd_iommu_get_vptr_from_page_table_entry(u32 *entry);
u64 amd_iommu_get_next_table_from_pte(u32 *entry);
int amd_iommu_reserve_domain_unity_map(struct domain *domain,
unsigned long phys_addr, unsigned long size, int iw, int ir);
int amd_iommu_sync_p2m(struct domain *d);
@@ -69,8 +70,7 @@ void invalidate_all_iommu_pages(struct domain *d);
void amd_iommu_set_dev_table_entry(u32 *dte, u64 root_ptr, u64 intremap_ptr,
u16 domain_id, u8 sys_mgt, u8 dev_ex, u8 paging_mode);
int amd_iommu_is_dte_page_translation_valid(u32 *entry);
void invalidate_dev_table_entry(struct amd_iommu *iommu,
u16 devic_id);
void invalidate_dev_table_entry(struct amd_iommu *iommu, u16 devic_id);
/* send cmd to iommu */
int send_iommu_command(struct amd_iommu *iommu, u32 cmd[]);
@@ -117,4 +117,36 @@ static inline unsigned long region_to_pages(unsigned long addr, unsigned long si
return (PAGE_ALIGN(addr + size) - (addr & PAGE_MASK)) >> PAGE_SHIFT;
}
static inline struct page_info* alloc_amd_iommu_pgtable(void)
{
struct page_info *pg;
void *vaddr;
pg = alloc_domheap_page(NULL, 0);
vaddr = map_domain_page(page_to_mfn(pg));
if ( !vaddr )
return 0;
memset(vaddr, 0, PAGE_SIZE);
unmap_domain_page(vaddr);
return pg;
}
static inline void free_amd_iommu_pgtable(struct page_info *pg)
{
if ( pg != 0 )
free_domheap_page(pg);
}
static inline void* __alloc_amd_iommu_tables(int order)
{
void *buf;
buf = alloc_xenheap_pages(order);
return buf;
}
static inline void __free_amd_iommu_tables(void *table, int order)
{
free_xenheap_pages(table, order);
}
#endif /* _ASM_X86_64_AMD_IOMMU_PROTO_H */
+1 -1
View File
@@ -40,7 +40,7 @@ struct hvm_iommu {
/* amd iommu support */
int domain_id;
int paging_mode;
void *root_table;
struct page_info *root_table;
bool_t p2m_synchronized;
/* iommu_ops */
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.