162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 362306a36Sopenharmony_ci * License. See the file "COPYING" in the main directory of this archive 462306a36Sopenharmony_ci * for more details. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * (C) Copyright 2020 Hewlett Packard Enterprise Development LP 762306a36Sopenharmony_ci * Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved. 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci/* 1162306a36Sopenharmony_ci * Cross Partition (XP) uv-based functions. 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * Architecture specific implementation of common functions. 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <linux/device.h> 1862306a36Sopenharmony_ci#include <asm/uv/uv_hub.h> 1962306a36Sopenharmony_ci#if defined CONFIG_X86_64 2062306a36Sopenharmony_ci#include <asm/uv/bios.h> 2162306a36Sopenharmony_ci#elif defined CONFIG_IA64_SGI_UV 2262306a36Sopenharmony_ci#include <asm/sn/sn_sal.h> 2362306a36Sopenharmony_ci#endif 2462306a36Sopenharmony_ci#include "../sgi-gru/grukservices.h" 2562306a36Sopenharmony_ci#include "xp.h" 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci/* 2862306a36Sopenharmony_ci * Convert a virtual memory address to a physical memory address. 2962306a36Sopenharmony_ci */ 3062306a36Sopenharmony_cistatic unsigned long 3162306a36Sopenharmony_cixp_pa_uv(void *addr) 3262306a36Sopenharmony_ci{ 3362306a36Sopenharmony_ci return uv_gpa(addr); 3462306a36Sopenharmony_ci} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci/* 3762306a36Sopenharmony_ci * Convert a global physical to socket physical address. 3862306a36Sopenharmony_ci */ 3962306a36Sopenharmony_cistatic unsigned long 4062306a36Sopenharmony_cixp_socket_pa_uv(unsigned long gpa) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci return uv_gpa_to_soc_phys_ram(gpa); 4362306a36Sopenharmony_ci} 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistatic enum xp_retval 4662306a36Sopenharmony_cixp_remote_mmr_read(unsigned long dst_gpa, const unsigned long src_gpa, 4762306a36Sopenharmony_ci size_t len) 4862306a36Sopenharmony_ci{ 4962306a36Sopenharmony_ci int ret; 5062306a36Sopenharmony_ci unsigned long *dst_va = __va(uv_gpa_to_soc_phys_ram(dst_gpa)); 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci BUG_ON(!uv_gpa_in_mmr_space(src_gpa)); 5362306a36Sopenharmony_ci BUG_ON(len != 8); 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci ret = gru_read_gpa(dst_va, src_gpa); 5662306a36Sopenharmony_ci if (ret == 0) 5762306a36Sopenharmony_ci return xpSuccess; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci dev_err(xp, "gru_read_gpa() failed, dst_gpa=0x%016lx src_gpa=0x%016lx " 6062306a36Sopenharmony_ci "len=%ld\n", dst_gpa, src_gpa, len); 6162306a36Sopenharmony_ci return xpGruCopyError; 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic enum xp_retval 6662306a36Sopenharmony_cixp_remote_memcpy_uv(unsigned long dst_gpa, const unsigned long src_gpa, 6762306a36Sopenharmony_ci size_t len) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci int ret; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci if (uv_gpa_in_mmr_space(src_gpa)) 7262306a36Sopenharmony_ci return xp_remote_mmr_read(dst_gpa, src_gpa, len); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci ret = gru_copy_gpa(dst_gpa, src_gpa, len); 7562306a36Sopenharmony_ci if (ret == 0) 7662306a36Sopenharmony_ci return xpSuccess; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci dev_err(xp, "gru_copy_gpa() failed, dst_gpa=0x%016lx src_gpa=0x%016lx " 7962306a36Sopenharmony_ci "len=%ld\n", dst_gpa, src_gpa, len); 8062306a36Sopenharmony_ci return xpGruCopyError; 8162306a36Sopenharmony_ci} 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistatic int 8462306a36Sopenharmony_cixp_cpu_to_nasid_uv(int cpuid) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci /* ??? Is this same as sn2 nasid in mach/part bitmaps set up by SAL? */ 8762306a36Sopenharmony_ci return UV_PNODE_TO_NASID(uv_cpu_to_pnode(cpuid)); 8862306a36Sopenharmony_ci} 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_cistatic enum xp_retval 9162306a36Sopenharmony_cixp_expand_memprotect_uv(unsigned long phys_addr, unsigned long size) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci int ret; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci#if defined CONFIG_X86_64 9662306a36Sopenharmony_ci ret = uv_bios_change_memprotect(phys_addr, size, UV_MEMPROT_ALLOW_RW); 9762306a36Sopenharmony_ci if (ret != BIOS_STATUS_SUCCESS) { 9862306a36Sopenharmony_ci dev_err(xp, "uv_bios_change_memprotect(,, " 9962306a36Sopenharmony_ci "UV_MEMPROT_ALLOW_RW) failed, ret=%d\n", ret); 10062306a36Sopenharmony_ci return xpBiosError; 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci#elif defined CONFIG_IA64_SGI_UV 10462306a36Sopenharmony_ci u64 nasid_array; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci ret = sn_change_memprotect(phys_addr, size, SN_MEMPROT_ACCESS_CLASS_1, 10762306a36Sopenharmony_ci &nasid_array); 10862306a36Sopenharmony_ci if (ret != 0) { 10962306a36Sopenharmony_ci dev_err(xp, "sn_change_memprotect(,, " 11062306a36Sopenharmony_ci "SN_MEMPROT_ACCESS_CLASS_1,) failed ret=%d\n", ret); 11162306a36Sopenharmony_ci return xpSalError; 11262306a36Sopenharmony_ci } 11362306a36Sopenharmony_ci#else 11462306a36Sopenharmony_ci #error not a supported configuration 11562306a36Sopenharmony_ci#endif 11662306a36Sopenharmony_ci return xpSuccess; 11762306a36Sopenharmony_ci} 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cistatic enum xp_retval 12062306a36Sopenharmony_cixp_restrict_memprotect_uv(unsigned long phys_addr, unsigned long size) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci int ret; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci#if defined CONFIG_X86_64 12562306a36Sopenharmony_ci ret = uv_bios_change_memprotect(phys_addr, size, 12662306a36Sopenharmony_ci UV_MEMPROT_RESTRICT_ACCESS); 12762306a36Sopenharmony_ci if (ret != BIOS_STATUS_SUCCESS) { 12862306a36Sopenharmony_ci dev_err(xp, "uv_bios_change_memprotect(,, " 12962306a36Sopenharmony_ci "UV_MEMPROT_RESTRICT_ACCESS) failed, ret=%d\n", ret); 13062306a36Sopenharmony_ci return xpBiosError; 13162306a36Sopenharmony_ci } 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci#elif defined CONFIG_IA64_SGI_UV 13462306a36Sopenharmony_ci u64 nasid_array; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci ret = sn_change_memprotect(phys_addr, size, SN_MEMPROT_ACCESS_CLASS_0, 13762306a36Sopenharmony_ci &nasid_array); 13862306a36Sopenharmony_ci if (ret != 0) { 13962306a36Sopenharmony_ci dev_err(xp, "sn_change_memprotect(,, " 14062306a36Sopenharmony_ci "SN_MEMPROT_ACCESS_CLASS_0,) failed ret=%d\n", ret); 14162306a36Sopenharmony_ci return xpSalError; 14262306a36Sopenharmony_ci } 14362306a36Sopenharmony_ci#else 14462306a36Sopenharmony_ci #error not a supported configuration 14562306a36Sopenharmony_ci#endif 14662306a36Sopenharmony_ci return xpSuccess; 14762306a36Sopenharmony_ci} 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_cienum xp_retval 15062306a36Sopenharmony_cixp_init_uv(void) 15162306a36Sopenharmony_ci{ 15262306a36Sopenharmony_ci WARN_ON(!is_uv_system()); 15362306a36Sopenharmony_ci if (!is_uv_system()) 15462306a36Sopenharmony_ci return xpUnsupported; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci xp_max_npartitions = XP_MAX_NPARTITIONS_UV; 15762306a36Sopenharmony_ci#ifdef CONFIG_X86 15862306a36Sopenharmony_ci xp_partition_id = sn_partition_id; 15962306a36Sopenharmony_ci xp_region_size = sn_region_size; 16062306a36Sopenharmony_ci#endif 16162306a36Sopenharmony_ci xp_pa = xp_pa_uv; 16262306a36Sopenharmony_ci xp_socket_pa = xp_socket_pa_uv; 16362306a36Sopenharmony_ci xp_remote_memcpy = xp_remote_memcpy_uv; 16462306a36Sopenharmony_ci xp_cpu_to_nasid = xp_cpu_to_nasid_uv; 16562306a36Sopenharmony_ci xp_expand_memprotect = xp_expand_memprotect_uv; 16662306a36Sopenharmony_ci xp_restrict_memprotect = xp_restrict_memprotect_uv; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci return xpSuccess; 16962306a36Sopenharmony_ci} 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_civoid 17262306a36Sopenharmony_cixp_exit_uv(void) 17362306a36Sopenharmony_ci{ 17462306a36Sopenharmony_ci WARN_ON(!is_uv_system()); 17562306a36Sopenharmony_ci} 176