2008-07-29 22:34:04 -07:00
/*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*
* Copyright ( c ) 2008 Silicon Graphics , Inc . All Rights Reserved .
*/
/*
* Cross Partition ( XP ) uv - based functions .
*
* Architecture specific implementation of common functions .
*
*/
2008-07-29 22:34:16 -07:00
# include <linux/device.h>
# include <asm/uv/uv_hub.h>
2008-11-05 17:27:22 -06:00
# if defined CONFIG_X86_64
# include <asm/uv/bios.h>
2019-08-13 09:25:12 +02:00
# elif defined CONFIG_IA64_SGI_UV
2008-11-05 17:27:22 -06:00
# include <asm/sn/sn_sal.h>
# endif
2008-07-29 22:34:16 -07:00
# include "../sgi-gru/grukservices.h"
2008-07-29 22:34:04 -07:00
# include "xp.h"
2008-07-29 22:34:16 -07:00
/*
* Convert a virtual memory address to a physical memory address .
*/
static unsigned long
xp_pa_uv ( void * addr )
{
return uv_gpa ( addr ) ;
}
2009-12-15 16:47:53 -08:00
/*
* Convert a global physical to socket physical address .
*/
static unsigned long
xp_socket_pa_uv ( unsigned long gpa )
{
return uv_gpa_to_soc_phys_ram ( gpa ) ;
}
2009-12-15 16:47:56 -08:00
static enum xp_retval
xp_remote_mmr_read ( unsigned long dst_gpa , const unsigned long src_gpa ,
size_t len )
{
int ret ;
unsigned long * dst_va = __va ( uv_gpa_to_soc_phys_ram ( dst_gpa ) ) ;
BUG_ON ( ! uv_gpa_in_mmr_space ( src_gpa ) ) ;
BUG_ON ( len ! = 8 ) ;
ret = gru_read_gpa ( dst_va , src_gpa ) ;
if ( ret = = 0 )
return xpSuccess ;
dev_err ( xp , " gru_read_gpa() failed, dst_gpa=0x%016lx src_gpa=0x%016lx "
" len=%ld \n " , dst_gpa , src_gpa , len ) ;
return xpGruCopyError ;
}
2008-07-29 22:34:05 -07:00
static enum xp_retval
2008-07-29 22:34:16 -07:00
xp_remote_memcpy_uv ( unsigned long dst_gpa , const unsigned long src_gpa ,
size_t len )
2008-07-29 22:34:05 -07:00
{
2008-07-29 22:34:16 -07:00
int ret ;
2009-12-15 16:47:56 -08:00
if ( uv_gpa_in_mmr_space ( src_gpa ) )
return xp_remote_mmr_read ( dst_gpa , src_gpa , len ) ;
2008-07-29 22:34:16 -07:00
ret = gru_copy_gpa ( dst_gpa , src_gpa , len ) ;
if ( ret = = 0 )
return xpSuccess ;
dev_err ( xp , " gru_copy_gpa() failed, dst_gpa=0x%016lx src_gpa=0x%016lx "
" len=%ld \n " , dst_gpa , src_gpa , len ) ;
return xpGruCopyError ;
2008-07-29 22:34:05 -07:00
}
2008-07-29 22:34:18 -07:00
static int
xp_cpu_to_nasid_uv ( int cpuid )
{
/* ??? Is this same as sn2 nasid in mach/part bitmaps set up by SAL? */
return UV_PNODE_TO_NASID ( uv_cpu_to_pnode ( cpuid ) ) ;
}
2008-11-05 17:27:22 -06:00
static enum xp_retval
xp_expand_memprotect_uv ( unsigned long phys_addr , unsigned long size )
{
int ret ;
# if defined CONFIG_X86_64
ret = uv_bios_change_memprotect ( phys_addr , size , UV_MEMPROT_ALLOW_RW ) ;
if ( ret ! = BIOS_STATUS_SUCCESS ) {
dev_err ( xp , " uv_bios_change_memprotect(,, "
" UV_MEMPROT_ALLOW_RW) failed, ret=%d \n " , ret ) ;
return xpBiosError ;
}
2019-08-13 09:25:12 +02:00
# elif defined CONFIG_IA64_SGI_UV
2008-11-05 17:27:22 -06:00
u64 nasid_array ;
ret = sn_change_memprotect ( phys_addr , size , SN_MEMPROT_ACCESS_CLASS_1 ,
& nasid_array ) ;
if ( ret ! = 0 ) {
dev_err ( xp , " sn_change_memprotect(,, "
" SN_MEMPROT_ACCESS_CLASS_1,) failed ret=%d \n " , ret ) ;
return xpSalError ;
}
# else
# error not a supported configuration
# endif
return xpSuccess ;
}
static enum xp_retval
xp_restrict_memprotect_uv ( unsigned long phys_addr , unsigned long size )
{
int ret ;
# if defined CONFIG_X86_64
ret = uv_bios_change_memprotect ( phys_addr , size ,
UV_MEMPROT_RESTRICT_ACCESS ) ;
if ( ret ! = BIOS_STATUS_SUCCESS ) {
dev_err ( xp , " uv_bios_change_memprotect(,, "
" UV_MEMPROT_RESTRICT_ACCESS) failed, ret=%d \n " , ret ) ;
return xpBiosError ;
}
2019-08-13 09:25:12 +02:00
# elif defined CONFIG_IA64_SGI_UV
2008-11-05 17:27:22 -06:00
u64 nasid_array ;
ret = sn_change_memprotect ( phys_addr , size , SN_MEMPROT_ACCESS_CLASS_0 ,
& nasid_array ) ;
if ( ret ! = 0 ) {
dev_err ( xp , " sn_change_memprotect(,, "
" SN_MEMPROT_ACCESS_CLASS_0,) failed ret=%d \n " , ret ) ;
return xpSalError ;
}
# else
# error not a supported configuration
# endif
return xpSuccess ;
}
2008-07-29 22:34:04 -07:00
enum xp_retval
xp_init_uv ( void )
{
2020-10-06 16:34:27 -05:00
WARN_ON ( ! is_uv_system ( ) ) ;
if ( ! is_uv_system ( ) )
return xpUnsupported ;
2008-07-29 22:34:04 -07:00
xp_max_npartitions = XP_MAX_NPARTITIONS_UV ;
2019-08-13 09:24:56 +02:00
# ifdef CONFIG_X86
2008-11-05 17:28:35 -06:00
xp_partition_id = sn_partition_id ;
xp_region_size = sn_region_size ;
2019-08-13 09:24:56 +02:00
# endif
2008-07-29 22:34:16 -07:00
xp_pa = xp_pa_uv ;
2009-12-15 16:47:53 -08:00
xp_socket_pa = xp_socket_pa_uv ;
2008-07-29 22:34:05 -07:00
xp_remote_memcpy = xp_remote_memcpy_uv ;
2008-07-29 22:34:18 -07:00
xp_cpu_to_nasid = xp_cpu_to_nasid_uv ;
2008-11-05 17:27:22 -06:00
xp_expand_memprotect = xp_expand_memprotect_uv ;
xp_restrict_memprotect = xp_restrict_memprotect_uv ;
2008-07-29 22:34:05 -07:00
return xpSuccess ;
2008-07-29 22:34:04 -07:00
}
void
xp_exit_uv ( void )
{
2020-10-06 16:34:27 -05:00
WARN_ON ( ! is_uv_system ( ) ) ;
2008-07-29 22:34:04 -07:00
}