ia64 SGI-SN2: fix silent data corruption caused by XPC
Jack Steiner identified a problem where XPC can cause a silent data corruption. On module load, the placement may cause the xpc_remote_copy_buffer to span two physical pages. DMA transfers are done to the start virtual address translated to physical. This patch changes the buffer from a statically allocated buffer to a kmalloc'd buffer. Dean Nelson reviewed this before posting. I have tested it in the configuration that was showing the memory corruption and verified it works. I also added a BUG_ON statement to help catch this if a similar situation is encountered. Signed-off-by: Robin Holt <holt@sgi.com> Signed-off-by: Dean Nelson <dcn@sgi.com> Signed-off-by: Jack Steiner <steiner@sgi.com> Signed-off-by: Tony Luck <tony.luck@intel.com> Signed-off-by: Adrian Bunk <bunk@stusta.de>
This commit is contained in:
@@ -60,23 +60,37 @@
|
||||
* the bte_copy() once in the hope that the failure was due to a temporary
|
||||
* aberration (i.e., the link going down temporarily).
|
||||
*
|
||||
* See bte_copy for definition of the input parameters.
|
||||
* src - physical address of the source of the transfer.
|
||||
* vdst - virtual address of the destination of the transfer.
|
||||
* len - number of bytes to transfer from source to destination.
|
||||
* mode - see bte_copy() for definition.
|
||||
* notification - see bte_copy() for definition.
|
||||
*
|
||||
* Note: xp_bte_copy() should never be called while holding a spinlock.
|
||||
*/
|
||||
static inline bte_result_t
|
||||
xp_bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification)
|
||||
xp_bte_copy(u64 src, u64 vdst, u64 len, u64 mode, void *notification)
|
||||
{
|
||||
bte_result_t ret;
|
||||
u64 pdst = ia64_tpa(vdst);
|
||||
|
||||
|
||||
ret = bte_copy(src, dest, len, mode, notification);
|
||||
/*
|
||||
* Ensure that the physically mapped memory is contiguous.
|
||||
*
|
||||
* We do this by ensuring that the memory is from region 7 only.
|
||||
* If the need should arise to use memory from one of the other
|
||||
* regions, then modify the BUG_ON() statement to ensure that the
|
||||
* memory from that region is always physically contiguous.
|
||||
*/
|
||||
BUG_ON(REGION_NUMBER(vdst) != RGN_KERNEL);
|
||||
|
||||
ret = bte_copy(src, pdst, len, mode, notification);
|
||||
if (ret != BTE_SUCCESS) {
|
||||
if (!in_interrupt()) {
|
||||
cond_resched();
|
||||
}
|
||||
ret = bte_copy(src, dest, len, mode, notification);
|
||||
ret = bte_copy(src, pdst, len, mode, notification);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -684,7 +684,8 @@ extern struct xpc_vars *xpc_vars;
|
||||
extern struct xpc_rsvd_page *xpc_rsvd_page;
|
||||
extern struct xpc_vars_part *xpc_vars_part;
|
||||
extern struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1];
|
||||
extern char xpc_remote_copy_buffer[];
|
||||
extern char *xpc_remote_copy_buffer;
|
||||
extern void *xpc_remote_copy_buffer_base;
|
||||
extern struct xpc_rsvd_page *xpc_rsvd_page_init(void);
|
||||
extern void xpc_allow_IPI_ops(void);
|
||||
extern void xpc_restrict_IPI_ops(void);
|
||||
|
||||
Reference in New Issue
Block a user