diff options
| author | Dean Nelson <dcn@sgi.com> | 2008-07-30 01:34:13 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-30 12:41:50 -0400 |
| commit | ee6665e3b6e1283c30ae240732af1345bc02154e (patch) | |
| tree | 91fbfb2a4cab26e3979df44a9bdcd6851efc9c50 | |
| parent | a7b4d509205db5e9cd3ffc77b306d7b10fe6a34d (diff) | |
sgi-xp: isolate remote copy buffer to sn2 only
Make the remote copy buffer an sn2 only item.
Signed-off-by: Dean Nelson <dcn@sgi.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | drivers/misc/sgi-xp/xp.h | 10 | ||||
| -rw-r--r-- | drivers/misc/sgi-xp/xpc.h | 39 | ||||
| -rw-r--r-- | drivers/misc/sgi-xp/xpc_main.c | 31 | ||||
| -rw-r--r-- | drivers/misc/sgi-xp/xpc_partition.c | 31 | ||||
| -rw-r--r-- | drivers/misc/sgi-xp/xpc_sn2.c | 88 |
5 files changed, 97 insertions, 102 deletions
diff --git a/drivers/misc/sgi-xp/xp.h b/drivers/misc/sgi-xp/xp.h index 43bf2470850e..955b5b913235 100644 --- a/drivers/misc/sgi-xp/xp.h +++ b/drivers/misc/sgi-xp/xp.h | |||
| @@ -61,16 +61,6 @@ | |||
| 61 | #define XP_MAX_NPARTITIONS_UV 256 | 61 | #define XP_MAX_NPARTITIONS_UV 256 |
| 62 | 62 | ||
| 63 | /* | 63 | /* |
| 64 | * Define the number of u64s required to represent all the C-brick nasids | ||
| 65 | * as a bitmap. The cross-partition kernel modules deal only with | ||
| 66 | * C-brick nasids, thus the need for bitmaps which don't account for | ||
| 67 | * odd-numbered (non C-brick) nasids. | ||
| 68 | */ | ||
| 69 | #define XP_MAX_PHYSNODE_ID (MAX_NUMALINK_NODES / 2) | ||
| 70 | #define XP_NASID_MASK_BYTES ((XP_MAX_PHYSNODE_ID + 7) / 8) | ||
| 71 | #define XP_NASID_MASK_WORDS ((XP_MAX_PHYSNODE_ID + 63) / 64) | ||
| 72 | |||
| 73 | /* | ||
| 74 | * XPC establishes channel connections between the local partition and any | 64 | * XPC establishes channel connections between the local partition and any |
| 75 | * other partition that is currently up. Over these channels, kernel-level | 65 | * other partition that is currently up. Over these channels, kernel-level |
| 76 | * `users' can communicate with their counterparts on the other partitions. | 66 | * `users' can communicate with their counterparts on the other partitions. |
diff --git a/drivers/misc/sgi-xp/xpc.h b/drivers/misc/sgi-xp/xpc.h index defd08881184..2111723553bf 100644 --- a/drivers/misc/sgi-xp/xpc.h +++ b/drivers/misc/sgi-xp/xpc.h | |||
| @@ -151,26 +151,6 @@ struct xpc_vars_sn2 { | |||
| 151 | #define XPC_V_VERSION _XPC_VERSION(3, 1) /* version 3.1 of the cross vars */ | 151 | #define XPC_V_VERSION _XPC_VERSION(3, 1) /* version 3.1 of the cross vars */ |
| 152 | 152 | ||
| 153 | /* | 153 | /* |
| 154 | * The following pertains to ia64-sn2 only. | ||
| 155 | * | ||
| 156 | * Memory for XPC's amo variables is allocated by the MSPEC driver. These | ||
| 157 | * pages are located in the lowest granule. The lowest granule uses 4k pages | ||
| 158 | * for cached references and an alternate TLB handler to never provide a | ||
| 159 | * cacheable mapping for the entire region. This will prevent speculative | ||
| 160 | * reading of cached copies of our lines from being issued which will cause | ||
| 161 | * a PI FSB Protocol error to be generated by the SHUB. For XPC, we need 64 | ||
| 162 | * amo variables (based on XP_MAX_NPARTITIONS_SN2) to identify the senders of | ||
| 163 | * NOTIFY IRQs, 128 amo variables (based on XP_NASID_MASK_WORDS) to identify | ||
| 164 | * the senders of ACTIVATE IRQs, 1 amo variable to identify which remote | ||
| 165 | * partitions (i.e., XPCs) consider themselves currently engaged with the | ||
| 166 | * local XPC and 1 amo variable to request partition deactivation. | ||
| 167 | */ | ||
| 168 | #define XPC_NOTIFY_IRQ_AMOS 0 | ||
| 169 | #define XPC_ACTIVATE_IRQ_AMOS (XPC_NOTIFY_IRQ_AMOS + XP_MAX_NPARTITIONS_SN2) | ||
| 170 | #define XPC_ENGAGED_PARTITIONS_AMO (XPC_ACTIVATE_IRQ_AMOS + XP_NASID_MASK_WORDS) | ||
| 171 | #define XPC_DEACTIVATE_REQUEST_AMO (XPC_ENGAGED_PARTITIONS_AMO + 1) | ||
| 172 | |||
| 173 | /* | ||
| 174 | * The following structure describes the per partition specific variables. | 154 | * The following structure describes the per partition specific variables. |
| 175 | * | 155 | * |
| 176 | * An array of these structures, one per partition, will be defined. As a | 156 | * An array of these structures, one per partition, will be defined. As a |
| @@ -214,9 +194,10 @@ struct xpc_vars_part_sn2 { | |||
| 214 | #define XPC_RP_VARS_SIZE L1_CACHE_ALIGN(sizeof(struct xpc_vars_sn2)) | 194 | #define XPC_RP_VARS_SIZE L1_CACHE_ALIGN(sizeof(struct xpc_vars_sn2)) |
| 215 | 195 | ||
| 216 | #define XPC_RP_PART_NASIDS(_rp) ((u64 *)((u8 *)(_rp) + XPC_RP_HEADER_SIZE)) | 196 | #define XPC_RP_PART_NASIDS(_rp) ((u64 *)((u8 *)(_rp) + XPC_RP_HEADER_SIZE)) |
| 217 | #define XPC_RP_MACH_NASIDS(_rp) (XPC_RP_PART_NASIDS(_rp) + xp_nasid_mask_words) | 197 | #define XPC_RP_MACH_NASIDS(_rp) (XPC_RP_PART_NASIDS(_rp) + xpc_nasid_mask_words) |
| 218 | #define XPC_RP_VARS(_rp) ((struct xpc_vars_sn2 *)(XPC_RP_MACH_NASIDS(_rp) + \ | 198 | #define XPC_RP_VARS(_rp) ((struct xpc_vars_sn2 *) \ |
| 219 | xp_nasid_mask_words)) | 199 | (XPC_RP_MACH_NASIDS(_rp) + \ |
| 200 | xpc_nasid_mask_words)) | ||
| 220 | 201 | ||
| 221 | /* | 202 | /* |
| 222 | * Functions registered by add_timer() or called by kernel_thread() only | 203 | * Functions registered by add_timer() or called by kernel_thread() only |
| @@ -225,11 +206,11 @@ struct xpc_vars_part_sn2 { | |||
| 225 | * the passed argument. | 206 | * the passed argument. |
| 226 | */ | 207 | */ |
| 227 | #define XPC_PACK_ARGS(_arg1, _arg2) \ | 208 | #define XPC_PACK_ARGS(_arg1, _arg2) \ |
| 228 | ((((u64) _arg1) & 0xffffffff) | \ | 209 | ((((u64)_arg1) & 0xffffffff) | \ |
| 229 | ((((u64) _arg2) & 0xffffffff) << 32)) | 210 | ((((u64)_arg2) & 0xffffffff) << 32)) |
| 230 | 211 | ||
| 231 | #define XPC_UNPACK_ARG1(_args) (((u64) _args) & 0xffffffff) | 212 | #define XPC_UNPACK_ARG1(_args) (((u64)_args) & 0xffffffff) |
| 232 | #define XPC_UNPACK_ARG2(_args) ((((u64) _args) >> 32) & 0xffffffff) | 213 | #define XPC_UNPACK_ARG2(_args) ((((u64)_args) >> 32) & 0xffffffff) |
| 233 | 214 | ||
| 234 | /* | 215 | /* |
| 235 | * Define a Get/Put value pair (pointers) used with a message queue. | 216 | * Define a Get/Put value pair (pointers) used with a message queue. |
| @@ -710,12 +691,10 @@ extern void xpc_exit_uv(void); | |||
| 710 | 691 | ||
| 711 | /* found in xpc_partition.c */ | 692 | /* found in xpc_partition.c */ |
| 712 | extern int xpc_exiting; | 693 | extern int xpc_exiting; |
| 713 | extern int xp_nasid_mask_words; | 694 | extern int xpc_nasid_mask_words; |
| 714 | extern struct xpc_rsvd_page *xpc_rsvd_page; | 695 | extern struct xpc_rsvd_page *xpc_rsvd_page; |
| 715 | extern u64 *xpc_mach_nasids; | 696 | extern u64 *xpc_mach_nasids; |
| 716 | extern struct xpc_partition *xpc_partitions; | 697 | extern struct xpc_partition *xpc_partitions; |
| 717 | extern char *xpc_remote_copy_buffer; | ||
| 718 | extern void *xpc_remote_copy_buffer_base; | ||
| 719 | extern void *xpc_kmalloc_cacheline_aligned(size_t, gfp_t, void **); | 698 | extern void *xpc_kmalloc_cacheline_aligned(size_t, gfp_t, void **); |
| 720 | extern struct xpc_rsvd_page *xpc_setup_rsvd_page(void); | 699 | extern struct xpc_rsvd_page *xpc_setup_rsvd_page(void); |
| 721 | extern int xpc_identify_activate_IRQ_sender(void); | 700 | extern int xpc_identify_activate_IRQ_sender(void); |
diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c index b5f3c5e59db0..36dfccea5247 100644 --- a/drivers/misc/sgi-xp/xpc_main.c +++ b/drivers/misc/sgi-xp/xpc_main.c | |||
| @@ -877,7 +877,6 @@ xpc_do_exit(enum xp_retval reason) | |||
| 877 | unregister_sysctl_table(xpc_sysctl); | 877 | unregister_sysctl_table(xpc_sysctl); |
| 878 | 878 | ||
| 879 | kfree(xpc_partitions); | 879 | kfree(xpc_partitions); |
| 880 | kfree(xpc_remote_copy_buffer_base); | ||
| 881 | 880 | ||
| 882 | if (is_shub()) | 881 | if (is_shub()) |
| 883 | xpc_exit_sn2(); | 882 | xpc_exit_sn2(); |
| @@ -1031,7 +1030,9 @@ xpc_init(void) | |||
| 1031 | short partid; | 1030 | short partid; |
| 1032 | struct xpc_partition *part; | 1031 | struct xpc_partition *part; |
| 1033 | struct task_struct *kthread; | 1032 | struct task_struct *kthread; |
| 1034 | size_t buf_size; | 1033 | |
| 1034 | snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part"); | ||
| 1035 | snprintf(xpc_chan->bus_id, BUS_ID_SIZE, "chan"); | ||
| 1035 | 1036 | ||
| 1036 | if (is_shub()) { | 1037 | if (is_shub()) { |
| 1037 | /* | 1038 | /* |
| @@ -1054,26 +1055,12 @@ xpc_init(void) | |||
| 1054 | return -ENODEV; | 1055 | return -ENODEV; |
| 1055 | } | 1056 | } |
| 1056 | 1057 | ||
| 1057 | snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part"); | ||
| 1058 | snprintf(xpc_chan->bus_id, BUS_ID_SIZE, "chan"); | ||
| 1059 | |||
| 1060 | buf_size = max(XPC_RP_VARS_SIZE, | ||
| 1061 | XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES); | ||
| 1062 | xpc_remote_copy_buffer = xpc_kmalloc_cacheline_aligned(buf_size, | ||
| 1063 | GFP_KERNEL, | ||
| 1064 | &xpc_remote_copy_buffer_base); | ||
| 1065 | if (xpc_remote_copy_buffer == NULL) { | ||
| 1066 | dev_err(xpc_part, "can't get memory for remote copy buffer\n"); | ||
| 1067 | ret = -ENOMEM; | ||
| 1068 | goto out_1; | ||
| 1069 | } | ||
| 1070 | |||
| 1071 | xpc_partitions = kzalloc(sizeof(struct xpc_partition) * | 1058 | xpc_partitions = kzalloc(sizeof(struct xpc_partition) * |
| 1072 | xp_max_npartitions, GFP_KERNEL); | 1059 | xp_max_npartitions, GFP_KERNEL); |
| 1073 | if (xpc_partitions == NULL) { | 1060 | if (xpc_partitions == NULL) { |
| 1074 | dev_err(xpc_part, "can't get memory for partition structure\n"); | 1061 | dev_err(xpc_part, "can't get memory for partition structure\n"); |
| 1075 | ret = -ENOMEM; | 1062 | ret = -ENOMEM; |
| 1076 | goto out_2; | 1063 | goto out_1; |
| 1077 | } | 1064 | } |
| 1078 | 1065 | ||
| 1079 | /* | 1066 | /* |
| @@ -1115,7 +1102,7 @@ xpc_init(void) | |||
| 1115 | if (xpc_rsvd_page == NULL) { | 1102 | if (xpc_rsvd_page == NULL) { |
| 1116 | dev_err(xpc_part, "can't setup our reserved page\n"); | 1103 | dev_err(xpc_part, "can't setup our reserved page\n"); |
| 1117 | ret = -EBUSY; | 1104 | ret = -EBUSY; |
| 1118 | goto out_3; | 1105 | goto out_2; |
| 1119 | } | 1106 | } |
| 1120 | 1107 | ||
| 1121 | /* add ourselves to the reboot_notifier_list */ | 1108 | /* add ourselves to the reboot_notifier_list */ |
| @@ -1136,7 +1123,7 @@ xpc_init(void) | |||
| 1136 | if (IS_ERR(kthread)) { | 1123 | if (IS_ERR(kthread)) { |
| 1137 | dev_err(xpc_part, "failed while forking hb check thread\n"); | 1124 | dev_err(xpc_part, "failed while forking hb check thread\n"); |
| 1138 | ret = -EBUSY; | 1125 | ret = -EBUSY; |
| 1139 | goto out_4; | 1126 | goto out_3; |
| 1140 | } | 1127 | } |
| 1141 | 1128 | ||
| 1142 | /* | 1129 | /* |
| @@ -1164,18 +1151,16 @@ xpc_init(void) | |||
| 1164 | return 0; | 1151 | return 0; |
| 1165 | 1152 | ||
| 1166 | /* initialization was not successful */ | 1153 | /* initialization was not successful */ |
| 1167 | out_4: | 1154 | out_3: |
| 1168 | /* indicate to others that our reserved page is uninitialized */ | 1155 | /* indicate to others that our reserved page is uninitialized */ |
| 1169 | xpc_rsvd_page->stamp = 0; | 1156 | xpc_rsvd_page->stamp = 0; |
| 1170 | 1157 | ||
| 1171 | (void)unregister_die_notifier(&xpc_die_notifier); | 1158 | (void)unregister_die_notifier(&xpc_die_notifier); |
| 1172 | (void)unregister_reboot_notifier(&xpc_reboot_notifier); | 1159 | (void)unregister_reboot_notifier(&xpc_reboot_notifier); |
| 1173 | out_3: | 1160 | out_2: |
| 1174 | if (xpc_sysctl) | 1161 | if (xpc_sysctl) |
| 1175 | unregister_sysctl_table(xpc_sysctl); | 1162 | unregister_sysctl_table(xpc_sysctl); |
| 1176 | kfree(xpc_partitions); | 1163 | kfree(xpc_partitions); |
| 1177 | out_2: | ||
| 1178 | kfree(xpc_remote_copy_buffer_base); | ||
| 1179 | out_1: | 1164 | out_1: |
| 1180 | if (is_shub()) | 1165 | if (is_shub()) |
| 1181 | xpc_exit_sn2(); | 1166 | xpc_exit_sn2(); |
diff --git a/drivers/misc/sgi-xp/xpc_partition.c b/drivers/misc/sgi-xp/xpc_partition.c index c769ab8f74ef..9f104450478f 100644 --- a/drivers/misc/sgi-xp/xpc_partition.c +++ b/drivers/misc/sgi-xp/xpc_partition.c | |||
| @@ -34,21 +34,12 @@ struct xpc_rsvd_page *xpc_rsvd_page; | |||
| 34 | static u64 *xpc_part_nasids; | 34 | static u64 *xpc_part_nasids; |
| 35 | u64 *xpc_mach_nasids; | 35 | u64 *xpc_mach_nasids; |
| 36 | 36 | ||
| 37 | /* >>> next two variables should be 'xpc_' if they remain here */ | 37 | static int xpc_sizeof_nasid_mask; /* actual size in bytes of nasid mask */ |
| 38 | static int xp_sizeof_nasid_mask; /* actual size in bytes of nasid mask */ | 38 | int xpc_nasid_mask_words; /* actual size in words of nasid mask */ |
| 39 | int xp_nasid_mask_words; /* actual size in words of nasid mask */ | ||
| 40 | 39 | ||
| 41 | struct xpc_partition *xpc_partitions; | 40 | struct xpc_partition *xpc_partitions; |
| 42 | 41 | ||
| 43 | /* | 42 | /* |
| 44 | * Generic buffer used to store a local copy of portions of a remote | ||
| 45 | * partition's reserved page (either its header and part_nasids mask, | ||
| 46 | * or its vars). | ||
| 47 | */ | ||
| 48 | char *xpc_remote_copy_buffer; | ||
| 49 | void *xpc_remote_copy_buffer_base; | ||
| 50 | |||
| 51 | /* | ||
| 52 | * Guarantee that the kmalloc'd memory is cacheline aligned. | 43 | * Guarantee that the kmalloc'd memory is cacheline aligned. |
| 53 | */ | 44 | */ |
| 54 | void * | 45 | void * |
| @@ -176,9 +167,9 @@ xpc_setup_rsvd_page(void) | |||
| 176 | /* SAL_version 1 didn't set the nasids_size field */ | 167 | /* SAL_version 1 didn't set the nasids_size field */ |
| 177 | rp->SAL_nasids_size = 128; | 168 | rp->SAL_nasids_size = 128; |
| 178 | } | 169 | } |
| 179 | xp_sizeof_nasid_mask = rp->SAL_nasids_size; | 170 | xpc_sizeof_nasid_mask = rp->SAL_nasids_size; |
| 180 | xp_nasid_mask_words = DIV_ROUND_UP(xp_sizeof_nasid_mask, | 171 | xpc_nasid_mask_words = DIV_ROUND_UP(xpc_sizeof_nasid_mask, |
| 181 | BYTES_PER_WORD); | 172 | BYTES_PER_WORD); |
| 182 | 173 | ||
| 183 | /* setup the pointers to the various items in the reserved page */ | 174 | /* setup the pointers to the various items in the reserved page */ |
| 184 | xpc_part_nasids = XPC_RP_PART_NASIDS(rp); | 175 | xpc_part_nasids = XPC_RP_PART_NASIDS(rp); |
| @@ -222,14 +213,14 @@ xpc_get_remote_rp(int nasid, u64 *discovered_nasids, | |||
| 222 | 213 | ||
| 223 | /* pull over the reserved page header and part_nasids mask */ | 214 | /* pull over the reserved page header and part_nasids mask */ |
| 224 | ret = xp_remote_memcpy(remote_rp, (void *)*remote_rp_pa, | 215 | ret = xp_remote_memcpy(remote_rp, (void *)*remote_rp_pa, |
| 225 | XPC_RP_HEADER_SIZE + xp_sizeof_nasid_mask); | 216 | XPC_RP_HEADER_SIZE + xpc_sizeof_nasid_mask); |
| 226 | if (ret != xpSuccess) | 217 | if (ret != xpSuccess) |
| 227 | return ret; | 218 | return ret; |
| 228 | 219 | ||
| 229 | if (discovered_nasids != NULL) { | 220 | if (discovered_nasids != NULL) { |
| 230 | u64 *remote_part_nasids = XPC_RP_PART_NASIDS(remote_rp); | 221 | u64 *remote_part_nasids = XPC_RP_PART_NASIDS(remote_rp); |
| 231 | 222 | ||
| 232 | for (i = 0; i < xp_nasid_mask_words; i++) | 223 | for (i = 0; i < xpc_nasid_mask_words; i++) |
| 233 | discovered_nasids[i] |= remote_part_nasids[i]; | 224 | discovered_nasids[i] |= remote_part_nasids[i]; |
| 234 | } | 225 | } |
| 235 | 226 | ||
| @@ -414,12 +405,12 @@ xpc_discovery(void) | |||
| 414 | enum xp_retval ret; | 405 | enum xp_retval ret; |
| 415 | 406 | ||
| 416 | remote_rp = xpc_kmalloc_cacheline_aligned(XPC_RP_HEADER_SIZE + | 407 | remote_rp = xpc_kmalloc_cacheline_aligned(XPC_RP_HEADER_SIZE + |
| 417 | xp_sizeof_nasid_mask, | 408 | xpc_sizeof_nasid_mask, |
| 418 | GFP_KERNEL, &remote_rp_base); | 409 | GFP_KERNEL, &remote_rp_base); |
| 419 | if (remote_rp == NULL) | 410 | if (remote_rp == NULL) |
| 420 | return; | 411 | return; |
| 421 | 412 | ||
| 422 | discovered_nasids = kzalloc(sizeof(u64) * xp_nasid_mask_words, | 413 | discovered_nasids = kzalloc(sizeof(u64) * xpc_nasid_mask_words, |
| 423 | GFP_KERNEL); | 414 | GFP_KERNEL); |
| 424 | if (discovered_nasids == NULL) { | 415 | if (discovered_nasids == NULL) { |
| 425 | kfree(remote_rp_base); | 416 | kfree(remote_rp_base); |
| @@ -521,10 +512,10 @@ xpc_initiate_partid_to_nasids(short partid, void *nasid_mask) | |||
| 521 | if (part->remote_rp_pa == 0) | 512 | if (part->remote_rp_pa == 0) |
| 522 | return xpPartitionDown; | 513 | return xpPartitionDown; |
| 523 | 514 | ||
| 524 | memset(nasid_mask, 0, XP_NASID_MASK_BYTES); | 515 | memset(nasid_mask, 0, xpc_sizeof_nasid_mask); |
| 525 | 516 | ||
| 526 | part_nasid_pa = (u64)XPC_RP_PART_NASIDS(part->remote_rp_pa); | 517 | part_nasid_pa = (u64)XPC_RP_PART_NASIDS(part->remote_rp_pa); |
| 527 | 518 | ||
| 528 | return xp_remote_memcpy(nasid_mask, (void *)part_nasid_pa, | 519 | return xp_remote_memcpy(nasid_mask, (void *)part_nasid_pa, |
| 529 | xp_sizeof_nasid_mask); | 520 | xpc_sizeof_nasid_mask); |
| 530 | } | 521 | } |
diff --git a/drivers/misc/sgi-xp/xpc_sn2.c b/drivers/misc/sgi-xp/xpc_sn2.c index e5dc8c44c6fb..9c0c29a2ac86 100644 --- a/drivers/misc/sgi-xp/xpc_sn2.c +++ b/drivers/misc/sgi-xp/xpc_sn2.c | |||
| @@ -19,6 +19,43 @@ | |||
| 19 | #include <asm/sn/sn_sal.h> | 19 | #include <asm/sn/sn_sal.h> |
| 20 | #include "xpc.h" | 20 | #include "xpc.h" |
| 21 | 21 | ||
| 22 | /* | ||
| 23 | * Define the number of u64s required to represent all the C-brick nasids | ||
| 24 | * as a bitmap. The cross-partition kernel modules deal only with | ||
| 25 | * C-brick nasids, thus the need for bitmaps which don't account for | ||
| 26 | * odd-numbered (non C-brick) nasids. | ||
| 27 | */ | ||
| 28 | #define XPC_MAX_PHYSNODES_SN2 (MAX_NUMALINK_NODES / 2) | ||
| 29 | #define XP_NASID_MASK_BYTES_SN2 ((XPC_MAX_PHYSNODES_SN2 + 7) / 8) | ||
| 30 | #define XP_NASID_MASK_WORDS_SN2 ((XPC_MAX_PHYSNODES_SN2 + 63) / 64) | ||
| 31 | |||
| 32 | /* | ||
| 33 | * Memory for XPC's amo variables is allocated by the MSPEC driver. These | ||
| 34 | * pages are located in the lowest granule. The lowest granule uses 4k pages | ||
| 35 | * for cached references and an alternate TLB handler to never provide a | ||
| 36 | * cacheable mapping for the entire region. This will prevent speculative | ||
| 37 | * reading of cached copies of our lines from being issued which will cause | ||
| 38 | * a PI FSB Protocol error to be generated by the SHUB. For XPC, we need 64 | ||
| 39 | * amo variables (based on XP_MAX_NPARTITIONS_SN2) to identify the senders of | ||
| 40 | * NOTIFY IRQs, 128 amo variables (based on XP_NASID_MASK_WORDS_SN2) to identify | ||
| 41 | * the senders of ACTIVATE IRQs, 1 amo variable to identify which remote | ||
| 42 | * partitions (i.e., XPCs) consider themselves currently engaged with the | ||
| 43 | * local XPC and 1 amo variable to request partition deactivation. | ||
| 44 | */ | ||
| 45 | #define XPC_NOTIFY_IRQ_AMOS_SN2 0 | ||
| 46 | #define XPC_ACTIVATE_IRQ_AMOS_SN2 (XPC_NOTIFY_IRQ_AMOS_SN2 + \ | ||
| 47 | XP_MAX_NPARTITIONS_SN2) | ||
| 48 | #define XPC_ENGAGED_PARTITIONS_AMO_SN2 (XPC_ACTIVATE_IRQ_AMOS_SN2 + \ | ||
| 49 | XP_NASID_MASK_WORDS_SN2) | ||
| 50 | #define XPC_DEACTIVATE_REQUEST_AMO_SN2 (XPC_ENGAGED_PARTITIONS_AMO_SN2 + 1) | ||
| 51 | |||
| 52 | /* | ||
| 53 | * Buffer used to store a local copy of portions of a remote partition's | ||
| 54 | * reserved page (either its header and part_nasids mask, or its vars). | ||
| 55 | */ | ||
| 56 | static char *xpc_remote_copy_buffer_sn2; | ||
| 57 | static void *xpc_remote_copy_buffer_base_sn2; | ||
| 58 | |||
| 22 | static struct xpc_vars_sn2 *xpc_vars; /* >>> Add _sn2 suffix? */ | 59 | static struct xpc_vars_sn2 *xpc_vars; /* >>> Add _sn2 suffix? */ |
| 23 | static struct xpc_vars_part_sn2 *xpc_vars_part; /* >>> Add _sn2 suffix? */ | 60 | static struct xpc_vars_part_sn2 *xpc_vars_part; /* >>> Add _sn2 suffix? */ |
| 24 | 61 | ||
| @@ -176,7 +213,7 @@ xpc_send_activate_IRQ_sn2(u64 amos_page_pa, int from_nasid, int to_nasid, | |||
| 176 | int w_index = XPC_NASID_W_INDEX(from_nasid); | 213 | int w_index = XPC_NASID_W_INDEX(from_nasid); |
| 177 | int b_index = XPC_NASID_B_INDEX(from_nasid); | 214 | int b_index = XPC_NASID_B_INDEX(from_nasid); |
| 178 | struct amo *amos = (struct amo *)__va(amos_page_pa + | 215 | struct amo *amos = (struct amo *)__va(amos_page_pa + |
| 179 | (XPC_ACTIVATE_IRQ_AMOS * | 216 | (XPC_ACTIVATE_IRQ_AMOS_SN2 * |
| 180 | sizeof(struct amo))); | 217 | sizeof(struct amo))); |
| 181 | 218 | ||
| 182 | (void)xpc_send_IRQ_sn2(&amos[w_index], (1UL << b_index), to_nasid, | 219 | (void)xpc_send_IRQ_sn2(&amos[w_index], (1UL << b_index), to_nasid, |
| @@ -189,7 +226,7 @@ xpc_send_local_activate_IRQ_sn2(int from_nasid) | |||
| 189 | int w_index = XPC_NASID_W_INDEX(from_nasid); | 226 | int w_index = XPC_NASID_W_INDEX(from_nasid); |
| 190 | int b_index = XPC_NASID_B_INDEX(from_nasid); | 227 | int b_index = XPC_NASID_B_INDEX(from_nasid); |
| 191 | struct amo *amos = (struct amo *)__va(xpc_vars->amos_page_pa + | 228 | struct amo *amos = (struct amo *)__va(xpc_vars->amos_page_pa + |
| 192 | (XPC_ACTIVATE_IRQ_AMOS * | 229 | (XPC_ACTIVATE_IRQ_AMOS_SN2 * |
| 193 | sizeof(struct amo))); | 230 | sizeof(struct amo))); |
| 194 | 231 | ||
| 195 | /* fake the sending and receipt of an activate IRQ from remote nasid */ | 232 | /* fake the sending and receipt of an activate IRQ from remote nasid */ |
| @@ -395,7 +432,7 @@ xpc_indicate_partition_engaged_sn2(struct xpc_partition *part) | |||
| 395 | { | 432 | { |
| 396 | unsigned long irq_flags; | 433 | unsigned long irq_flags; |
| 397 | struct amo *amo = (struct amo *)__va(part->sn.sn2.remote_amos_page_pa + | 434 | struct amo *amo = (struct amo *)__va(part->sn.sn2.remote_amos_page_pa + |
| 398 | (XPC_ENGAGED_PARTITIONS_AMO * | 435 | (XPC_ENGAGED_PARTITIONS_AMO_SN2 * |
| 399 | sizeof(struct amo))); | 436 | sizeof(struct amo))); |
| 400 | 437 | ||
| 401 | local_irq_save(irq_flags); | 438 | local_irq_save(irq_flags); |
| @@ -422,7 +459,7 @@ xpc_indicate_partition_disengaged_sn2(struct xpc_partition *part) | |||
| 422 | struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2; | 459 | struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2; |
| 423 | unsigned long irq_flags; | 460 | unsigned long irq_flags; |
| 424 | struct amo *amo = (struct amo *)__va(part_sn2->remote_amos_page_pa + | 461 | struct amo *amo = (struct amo *)__va(part_sn2->remote_amos_page_pa + |
| 425 | (XPC_ENGAGED_PARTITIONS_AMO * | 462 | (XPC_ENGAGED_PARTITIONS_AMO_SN2 * |
| 426 | sizeof(struct amo))); | 463 | sizeof(struct amo))); |
| 427 | 464 | ||
| 428 | local_irq_save(irq_flags); | 465 | local_irq_save(irq_flags); |
| @@ -455,7 +492,7 @@ xpc_indicate_partition_disengaged_sn2(struct xpc_partition *part) | |||
| 455 | static int | 492 | static int |
| 456 | xpc_partition_engaged_sn2(short partid) | 493 | xpc_partition_engaged_sn2(short partid) |
| 457 | { | 494 | { |
| 458 | struct amo *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO; | 495 | struct amo *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO_SN2; |
| 459 | 496 | ||
| 460 | /* our partition's amo variable ANDed with partid mask */ | 497 | /* our partition's amo variable ANDed with partid mask */ |
| 461 | return (FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) & | 498 | return (FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) & |
| @@ -465,7 +502,7 @@ xpc_partition_engaged_sn2(short partid) | |||
| 465 | static int | 502 | static int |
| 466 | xpc_any_partition_engaged_sn2(void) | 503 | xpc_any_partition_engaged_sn2(void) |
| 467 | { | 504 | { |
| 468 | struct amo *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO; | 505 | struct amo *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO_SN2; |
| 469 | 506 | ||
| 470 | /* our partition's amo variable */ | 507 | /* our partition's amo variable */ |
| 471 | return FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) != 0; | 508 | return FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) != 0; |
| @@ -474,7 +511,7 @@ xpc_any_partition_engaged_sn2(void) | |||
| 474 | static void | 511 | static void |
| 475 | xpc_assume_partition_disengaged_sn2(short partid) | 512 | xpc_assume_partition_disengaged_sn2(short partid) |
| 476 | { | 513 | { |
| 477 | struct amo *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO; | 514 | struct amo *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO_SN2; |
| 478 | 515 | ||
| 479 | /* clear bit(s) based on partid mask in our partition's amo */ | 516 | /* clear bit(s) based on partid mask in our partition's amo */ |
| 480 | FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND, | 517 | FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND, |
| @@ -599,12 +636,12 @@ xpc_rsvd_page_init_sn2(struct xpc_rsvd_page *rp) | |||
| 599 | xp_max_npartitions); | 636 | xp_max_npartitions); |
| 600 | 637 | ||
| 601 | /* initialize the activate IRQ related amo variables */ | 638 | /* initialize the activate IRQ related amo variables */ |
| 602 | for (i = 0; i < xp_nasid_mask_words; i++) | 639 | for (i = 0; i < xpc_nasid_mask_words; i++) |
| 603 | (void)xpc_init_IRQ_amo_sn2(XPC_ACTIVATE_IRQ_AMOS + i); | 640 | (void)xpc_init_IRQ_amo_sn2(XPC_ACTIVATE_IRQ_AMOS_SN2 + i); |
| 604 | 641 | ||
| 605 | /* initialize the engaged remote partitions related amo variables */ | 642 | /* initialize the engaged remote partitions related amo variables */ |
| 606 | (void)xpc_init_IRQ_amo_sn2(XPC_ENGAGED_PARTITIONS_AMO); | 643 | (void)xpc_init_IRQ_amo_sn2(XPC_ENGAGED_PARTITIONS_AMO_SN2); |
| 607 | (void)xpc_init_IRQ_amo_sn2(XPC_DEACTIVATE_REQUEST_AMO); | 644 | (void)xpc_init_IRQ_amo_sn2(XPC_DEACTIVATE_REQUEST_AMO_SN2); |
| 608 | 645 | ||
| 609 | return xpSuccess; | 646 | return xpSuccess; |
| 610 | } | 647 | } |
| @@ -657,7 +694,7 @@ xpc_check_remote_hb_sn2(void) | |||
| 657 | short partid; | 694 | short partid; |
| 658 | enum xp_retval ret; | 695 | enum xp_retval ret; |
| 659 | 696 | ||
| 660 | remote_vars = (struct xpc_vars_sn2 *)xpc_remote_copy_buffer; | 697 | remote_vars = (struct xpc_vars_sn2 *)xpc_remote_copy_buffer_sn2; |
| 661 | 698 | ||
| 662 | for (partid = 0; partid < xp_max_npartitions; partid++) { | 699 | for (partid = 0; partid < xp_max_npartitions; partid++) { |
| 663 | 700 | ||
| @@ -749,7 +786,7 @@ xpc_request_partition_deactivation_sn2(struct xpc_partition *part) | |||
| 749 | struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2; | 786 | struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2; |
| 750 | unsigned long irq_flags; | 787 | unsigned long irq_flags; |
| 751 | struct amo *amo = (struct amo *)__va(part_sn2->remote_amos_page_pa + | 788 | struct amo *amo = (struct amo *)__va(part_sn2->remote_amos_page_pa + |
| 752 | (XPC_DEACTIVATE_REQUEST_AMO * | 789 | (XPC_DEACTIVATE_REQUEST_AMO_SN2 * |
| 753 | sizeof(struct amo))); | 790 | sizeof(struct amo))); |
| 754 | 791 | ||
| 755 | local_irq_save(irq_flags); | 792 | local_irq_save(irq_flags); |
| @@ -784,7 +821,7 @@ xpc_cancel_partition_deactivation_request_sn2(struct xpc_partition *part) | |||
| 784 | { | 821 | { |
| 785 | unsigned long irq_flags; | 822 | unsigned long irq_flags; |
| 786 | struct amo *amo = (struct amo *)__va(part->sn.sn2.remote_amos_page_pa + | 823 | struct amo *amo = (struct amo *)__va(part->sn.sn2.remote_amos_page_pa + |
| 787 | (XPC_DEACTIVATE_REQUEST_AMO * | 824 | (XPC_DEACTIVATE_REQUEST_AMO_SN2 * |
| 788 | sizeof(struct amo))); | 825 | sizeof(struct amo))); |
| 789 | 826 | ||
| 790 | local_irq_save(irq_flags); | 827 | local_irq_save(irq_flags); |
| @@ -808,7 +845,7 @@ xpc_cancel_partition_deactivation_request_sn2(struct xpc_partition *part) | |||
| 808 | static int | 845 | static int |
| 809 | xpc_partition_deactivation_requested_sn2(short partid) | 846 | xpc_partition_deactivation_requested_sn2(short partid) |
| 810 | { | 847 | { |
| 811 | struct amo *amo = xpc_vars->amos_page + XPC_DEACTIVATE_REQUEST_AMO; | 848 | struct amo *amo = xpc_vars->amos_page + XPC_DEACTIVATE_REQUEST_AMO_SN2; |
| 812 | 849 | ||
| 813 | /* our partition's amo variable ANDed with partid mask */ | 850 | /* our partition's amo variable ANDed with partid mask */ |
| 814 | return (FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) & | 851 | return (FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) & |
| @@ -898,7 +935,7 @@ xpc_identify_activate_IRQ_req_sn2(int nasid) | |||
| 898 | 935 | ||
| 899 | /* pull over the reserved page structure */ | 936 | /* pull over the reserved page structure */ |
| 900 | 937 | ||
| 901 | remote_rp = (struct xpc_rsvd_page *)xpc_remote_copy_buffer; | 938 | remote_rp = (struct xpc_rsvd_page *)xpc_remote_copy_buffer_sn2; |
| 902 | 939 | ||
| 903 | ret = xpc_get_remote_rp(nasid, NULL, remote_rp, &remote_rp_pa); | 940 | ret = xpc_get_remote_rp(nasid, NULL, remote_rp, &remote_rp_pa); |
| 904 | if (ret != xpSuccess) { | 941 | if (ret != xpSuccess) { |
| @@ -917,7 +954,7 @@ xpc_identify_activate_IRQ_req_sn2(int nasid) | |||
| 917 | 954 | ||
| 918 | /* pull over the cross partition variables */ | 955 | /* pull over the cross partition variables */ |
| 919 | 956 | ||
| 920 | remote_vars = (struct xpc_vars_sn2 *)xpc_remote_copy_buffer; | 957 | remote_vars = (struct xpc_vars_sn2 *)xpc_remote_copy_buffer_sn2; |
| 921 | 958 | ||
| 922 | ret = xpc_get_remote_vars_sn2(remote_vars_pa, remote_vars); | 959 | ret = xpc_get_remote_vars_sn2(remote_vars_pa, remote_vars); |
| 923 | if (ret != xpSuccess) { | 960 | if (ret != xpSuccess) { |
| @@ -996,10 +1033,10 @@ xpc_identify_activate_IRQ_sender_sn2(void) | |||
| 996 | int n_IRQs_detected = 0; | 1033 | int n_IRQs_detected = 0; |
| 997 | struct amo *act_amos; | 1034 | struct amo *act_amos; |
| 998 | 1035 | ||
| 999 | act_amos = xpc_vars->amos_page + XPC_ACTIVATE_IRQ_AMOS; | 1036 | act_amos = xpc_vars->amos_page + XPC_ACTIVATE_IRQ_AMOS_SN2; |
| 1000 | 1037 | ||
| 1001 | /* scan through act amo variable looking for non-zero entries */ | 1038 | /* scan through act amo variable looking for non-zero entries */ |
| 1002 | for (word = 0; word < xp_nasid_mask_words; word++) { | 1039 | for (word = 0; word < xpc_nasid_mask_words; word++) { |
| 1003 | 1040 | ||
| 1004 | if (xpc_exiting) | 1041 | if (xpc_exiting) |
| 1005 | break; | 1042 | break; |
| @@ -2334,6 +2371,7 @@ int | |||
| 2334 | xpc_init_sn2(void) | 2371 | xpc_init_sn2(void) |
| 2335 | { | 2372 | { |
| 2336 | int ret; | 2373 | int ret; |
| 2374 | size_t buf_size; | ||
| 2337 | 2375 | ||
| 2338 | xpc_rsvd_page_init = xpc_rsvd_page_init_sn2; | 2376 | xpc_rsvd_page_init = xpc_rsvd_page_init_sn2; |
| 2339 | xpc_increment_heartbeat = xpc_increment_heartbeat_sn2; | 2377 | xpc_increment_heartbeat = xpc_increment_heartbeat_sn2; |
| @@ -2378,6 +2416,16 @@ xpc_init_sn2(void) | |||
| 2378 | xpc_send_msg = xpc_send_msg_sn2; | 2416 | xpc_send_msg = xpc_send_msg_sn2; |
| 2379 | xpc_received_msg = xpc_received_msg_sn2; | 2417 | xpc_received_msg = xpc_received_msg_sn2; |
| 2380 | 2418 | ||
| 2419 | buf_size = max(XPC_RP_VARS_SIZE, | ||
| 2420 | XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES_SN2); | ||
| 2421 | xpc_remote_copy_buffer_sn2 = xpc_kmalloc_cacheline_aligned(buf_size, | ||
| 2422 | GFP_KERNEL, | ||
| 2423 | &xpc_remote_copy_buffer_base_sn2); | ||
| 2424 | if (xpc_remote_copy_buffer_sn2 == NULL) { | ||
| 2425 | dev_err(xpc_part, "can't get memory for remote copy buffer\n"); | ||
| 2426 | return -ENOMEM; | ||
| 2427 | } | ||
| 2428 | |||
| 2381 | /* open up protections for IPI and [potentially] amo operations */ | 2429 | /* open up protections for IPI and [potentially] amo operations */ |
| 2382 | xpc_allow_IPI_ops_sn2(); | 2430 | xpc_allow_IPI_ops_sn2(); |
| 2383 | xpc_allow_amo_ops_shub_wars_1_1_sn2(); | 2431 | xpc_allow_amo_ops_shub_wars_1_1_sn2(); |
| @@ -2394,6 +2442,7 @@ xpc_init_sn2(void) | |||
| 2394 | dev_err(xpc_part, "can't register ACTIVATE IRQ handler, " | 2442 | dev_err(xpc_part, "can't register ACTIVATE IRQ handler, " |
| 2395 | "errno=%d\n", -ret); | 2443 | "errno=%d\n", -ret); |
| 2396 | xpc_disallow_IPI_ops_sn2(); | 2444 | xpc_disallow_IPI_ops_sn2(); |
| 2445 | kfree(xpc_remote_copy_buffer_base_sn2); | ||
| 2397 | } | 2446 | } |
| 2398 | return ret; | 2447 | return ret; |
| 2399 | } | 2448 | } |
| @@ -2403,4 +2452,5 @@ xpc_exit_sn2(void) | |||
| 2403 | { | 2452 | { |
| 2404 | free_irq(SGI_XPC_ACTIVATE, NULL); | 2453 | free_irq(SGI_XPC_ACTIVATE, NULL); |
| 2405 | xpc_disallow_IPI_ops_sn2(); | 2454 | xpc_disallow_IPI_ops_sn2(); |
| 2455 | kfree(xpc_remote_copy_buffer_base_sn2); | ||
| 2406 | } | 2456 | } |
