diff options
| author | Dean Nelson <dcn@sgi.com> | 2005-09-01 15:01:37 -0400 |
|---|---|---|
| committer | Tony Luck <tony.luck@intel.com> | 2005-09-06 19:15:38 -0400 |
| commit | a607c38971fd078865fa9bef39e6c1d4435680c8 (patch) | |
| tree | cb7853f0d74ee6a9cd92ccc721096b57367d0390 | |
| parent | 4706df3d3c42af802597d82c8b1542c3d52eab23 (diff) | |
[IA64-SGI] get XPC to cleanly disengage from remote memory references
When XPC is being shutdown (i.e., rmmod, reboot) it doesn't ensure that
other partitions with whom it was connected have completely disengaged
from any attempt at cross-partition memory references. This can lead to
MCAs in any of these other partitions when the partition is reset.
Signed-off-by: Dean Nelson <dcn@sgi.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
| -rw-r--r-- | arch/ia64/sn/kernel/xpc.h | 288 | ||||
| -rw-r--r-- | arch/ia64/sn/kernel/xpc_channel.c | 216 | ||||
| -rw-r--r-- | arch/ia64/sn/kernel/xpc_main.c | 242 | ||||
| -rw-r--r-- | arch/ia64/sn/kernel/xpc_partition.c | 304 | ||||
| -rw-r--r-- | include/asm-ia64/sn/xp.h | 10 |
5 files changed, 822 insertions, 238 deletions
diff --git a/arch/ia64/sn/kernel/xpc.h b/arch/ia64/sn/kernel/xpc.h index d0ee635daf2e..565822ab3d08 100644 --- a/arch/ia64/sn/kernel/xpc.h +++ b/arch/ia64/sn/kernel/xpc.h | |||
| @@ -57,7 +57,7 @@ | |||
| 57 | #define XPC_NASID_FROM_W_B(_w, _b) (((_w) * 64 + (_b)) * 2) | 57 | #define XPC_NASID_FROM_W_B(_w, _b) (((_w) * 64 + (_b)) * 2) |
| 58 | 58 | ||
| 59 | #define XPC_HB_DEFAULT_INTERVAL 5 /* incr HB every x secs */ | 59 | #define XPC_HB_DEFAULT_INTERVAL 5 /* incr HB every x secs */ |
| 60 | #define XPC_HB_CHECK_DEFAULT_TIMEOUT 20 /* check HB every x secs */ | 60 | #define XPC_HB_CHECK_DEFAULT_INTERVAL 20 /* check HB every x secs */ |
| 61 | 61 | ||
| 62 | /* define the process name of HB checker and the CPU it is pinned to */ | 62 | /* define the process name of HB checker and the CPU it is pinned to */ |
| 63 | #define XPC_HB_CHECK_THREAD_NAME "xpc_hb" | 63 | #define XPC_HB_CHECK_THREAD_NAME "xpc_hb" |
| @@ -67,11 +67,6 @@ | |||
| 67 | #define XPC_DISCOVERY_THREAD_NAME "xpc_discovery" | 67 | #define XPC_DISCOVERY_THREAD_NAME "xpc_discovery" |
| 68 | 68 | ||
| 69 | 69 | ||
| 70 | #define XPC_HB_ALLOWED(_p, _v) ((_v)->heartbeating_to_mask & (1UL << (_p))) | ||
| 71 | #define XPC_ALLOW_HB(_p, _v) (_v)->heartbeating_to_mask |= (1UL << (_p)) | ||
| 72 | #define XPC_DISALLOW_HB(_p, _v) (_v)->heartbeating_to_mask &= (~(1UL << (_p))) | ||
| 73 | |||
| 74 | |||
| 75 | /* | 70 | /* |
| 76 | * Reserved Page provided by SAL. | 71 | * Reserved Page provided by SAL. |
| 77 | * | 72 | * |
| @@ -88,14 +83,38 @@ struct xpc_rsvd_page { | |||
| 88 | u8 version; | 83 | u8 version; |
| 89 | u8 pad[6]; /* pad to u64 align */ | 84 | u8 pad[6]; /* pad to u64 align */ |
| 90 | volatile u64 vars_pa; | 85 | volatile u64 vars_pa; |
| 86 | struct timespec stamp; /* time when reserved page was initialized */ | ||
| 91 | u64 part_nasids[XP_NASID_MASK_WORDS] ____cacheline_aligned; | 87 | u64 part_nasids[XP_NASID_MASK_WORDS] ____cacheline_aligned; |
| 92 | u64 mach_nasids[XP_NASID_MASK_WORDS] ____cacheline_aligned; | 88 | u64 mach_nasids[XP_NASID_MASK_WORDS] ____cacheline_aligned; |
| 93 | }; | 89 | }; |
| 94 | #define XPC_RP_VERSION _XPC_VERSION(1,0) /* version 1.0 of the reserved page */ | ||
| 95 | 90 | ||
| 96 | #define XPC_RSVD_PAGE_ALIGNED_SIZE \ | 91 | #define XPC_RSVD_PAGE_ALIGNED_SIZE \ |
| 97 | (L1_CACHE_ALIGN(sizeof(struct xpc_rsvd_page))) | 92 | (L1_CACHE_ALIGN(sizeof(struct xpc_rsvd_page))) |
| 98 | 93 | ||
| 94 | #define XPC_RP_VERSION _XPC_VERSION(1,1) /* version 1.1 of the reserved page */ | ||
| 95 | |||
| 96 | #define XPC_SUPPORTS_RP_STAMP(_version) \ | ||
| 97 | (_version >= _XPC_VERSION(1,1)) | ||
| 98 | |||
| 99 | /* | ||
| 100 | * compare stamps - the return value is: | ||
| 101 | * | ||
| 102 | * < 0, if stamp1 < stamp2 | ||
| 103 | * = 0, if stamp1 == stamp2 | ||
| 104 | * > 0, if stamp1 > stamp2 | ||
| 105 | */ | ||
| 106 | static inline int | ||
| 107 | xpc_compare_stamps(struct timespec *stamp1, struct timespec *stamp2) | ||
| 108 | { | ||
| 109 | int ret; | ||
| 110 | |||
| 111 | |||
| 112 | if ((ret = stamp1->tv_sec - stamp2->tv_sec) == 0) { | ||
| 113 | ret = stamp1->tv_nsec - stamp2->tv_nsec; | ||
| 114 | } | ||
| 115 | return ret; | ||
| 116 | } | ||
| 117 | |||
| 99 | 118 | ||
| 100 | /* | 119 | /* |
| 101 | * Define the structures by which XPC variables can be exported to other | 120 | * Define the structures by which XPC variables can be exported to other |
| @@ -121,12 +140,61 @@ struct xpc_vars { | |||
| 121 | u64 vars_part_pa; | 140 | u64 vars_part_pa; |
| 122 | u64 amos_page_pa; /* paddr of page of AMOs from MSPEC driver */ | 141 | u64 amos_page_pa; /* paddr of page of AMOs from MSPEC driver */ |
| 123 | AMO_t *amos_page; /* vaddr of page of AMOs from MSPEC driver */ | 142 | AMO_t *amos_page; /* vaddr of page of AMOs from MSPEC driver */ |
| 124 | AMO_t *act_amos; /* pointer to the first activation AMO */ | ||
| 125 | }; | 143 | }; |
| 126 | #define XPC_V_VERSION _XPC_VERSION(3,0) /* version 3.0 of the cross vars */ | ||
| 127 | 144 | ||
| 128 | #define XPC_VARS_ALIGNED_SIZE (L1_CACHE_ALIGN(sizeof(struct xpc_vars))) | 145 | #define XPC_VARS_ALIGNED_SIZE (L1_CACHE_ALIGN(sizeof(struct xpc_vars))) |
| 129 | 146 | ||
| 147 | #define XPC_V_VERSION _XPC_VERSION(3,1) /* version 3.1 of the cross vars */ | ||
| 148 | |||
| 149 | #define XPC_SUPPORTS_DISENGAGE_REQUEST(_version) \ | ||
| 150 | (_version >= _XPC_VERSION(3,1)) | ||
| 151 | |||
| 152 | |||
| 153 | static inline int | ||
| 154 | xpc_hb_allowed(partid_t partid, struct xpc_vars *vars) | ||
| 155 | { | ||
| 156 | return ((vars->heartbeating_to_mask & (1UL << partid)) != 0); | ||
| 157 | } | ||
| 158 | |||
| 159 | static inline void | ||
| 160 | xpc_allow_hb(partid_t partid, struct xpc_vars *vars) | ||
| 161 | { | ||
| 162 | u64 old_mask, new_mask; | ||
| 163 | |||
| 164 | do { | ||
| 165 | old_mask = vars->heartbeating_to_mask; | ||
| 166 | new_mask = (old_mask | (1UL << partid)); | ||
| 167 | } while (cmpxchg(&vars->heartbeating_to_mask, old_mask, new_mask) != | ||
| 168 | old_mask); | ||
| 169 | } | ||
| 170 | |||
| 171 | static inline void | ||
| 172 | xpc_disallow_hb(partid_t partid, struct xpc_vars *vars) | ||
| 173 | { | ||
| 174 | u64 old_mask, new_mask; | ||
| 175 | |||
| 176 | do { | ||
| 177 | old_mask = vars->heartbeating_to_mask; | ||
| 178 | new_mask = (old_mask & ~(1UL << partid)); | ||
| 179 | } while (cmpxchg(&vars->heartbeating_to_mask, old_mask, new_mask) != | ||
| 180 | old_mask); | ||
| 181 | } | ||
| 182 | |||
| 183 | |||
| 184 | /* | ||
| 185 | * The AMOs page consists of a number of AMO variables which are divided into | ||
| 186 | * four groups, The first two groups are used to identify an IRQ's sender. | ||
| 187 | * These two groups consist of 64 and 16 AMO variables respectively. The last | ||
| 188 | * two groups, consisting of just one AMO variable each, are used to identify | ||
| 189 | * the remote partitions that are currently engaged (from the viewpoint of | ||
| 190 | * the XPC running on the remote partition). | ||
| 191 | */ | ||
| 192 | #define XPC_NOTIFY_IRQ_AMOS 0 | ||
| 193 | #define XPC_ACTIVATE_IRQ_AMOS (XPC_NOTIFY_IRQ_AMOS + XP_MAX_PARTITIONS) | ||
| 194 | #define XPC_ENGAGED_PARTITIONS_AMO (XPC_ACTIVATE_IRQ_AMOS + XP_NASID_MASK_WORDS) | ||
| 195 | #define XPC_DISENGAGE_REQUEST_AMO (XPC_ENGAGED_PARTITIONS_AMO + 1) | ||
| 196 | |||
| 197 | |||
| 130 | /* | 198 | /* |
| 131 | * The following structure describes the per partition specific variables. | 199 | * The following structure describes the per partition specific variables. |
| 132 | * | 200 | * |
| @@ -358,7 +426,7 @@ struct xpc_channel { | |||
| 358 | void *key; /* pointer to user's key */ | 426 | void *key; /* pointer to user's key */ |
| 359 | 427 | ||
| 360 | struct semaphore msg_to_pull_sema; /* next msg to pull serialization */ | 428 | struct semaphore msg_to_pull_sema; /* next msg to pull serialization */ |
| 361 | struct semaphore teardown_sema; /* wait for teardown completion */ | 429 | struct semaphore wdisconnect_sema; /* wait for channel disconnect */ |
| 362 | 430 | ||
| 363 | struct xpc_openclose_args *local_openclose_args; /* args passed on */ | 431 | struct xpc_openclose_args *local_openclose_args; /* args passed on */ |
| 364 | /* opening or closing of channel */ | 432 | /* opening or closing of channel */ |
| @@ -410,6 +478,7 @@ struct xpc_channel { | |||
| 410 | 478 | ||
| 411 | #define XPC_C_DISCONNECTED 0x00002000 /* channel is disconnected */ | 479 | #define XPC_C_DISCONNECTED 0x00002000 /* channel is disconnected */ |
| 412 | #define XPC_C_DISCONNECTING 0x00004000 /* channel is being disconnected */ | 480 | #define XPC_C_DISCONNECTING 0x00004000 /* channel is being disconnected */ |
| 481 | #define XPC_C_WDISCONNECT 0x00008000 /* waiting for channel disconnect */ | ||
| 413 | 482 | ||
| 414 | 483 | ||
| 415 | 484 | ||
| @@ -422,6 +491,8 @@ struct xpc_partition { | |||
| 422 | 491 | ||
| 423 | /* XPC HB infrastructure */ | 492 | /* XPC HB infrastructure */ |
| 424 | 493 | ||
| 494 | u8 remote_rp_version; /* version# of partition's rsvd pg */ | ||
| 495 | struct timespec remote_rp_stamp;/* time when rsvd pg was initialized */ | ||
| 425 | u64 remote_rp_pa; /* phys addr of partition's rsvd pg */ | 496 | u64 remote_rp_pa; /* phys addr of partition's rsvd pg */ |
| 426 | u64 remote_vars_pa; /* phys addr of partition's vars */ | 497 | u64 remote_vars_pa; /* phys addr of partition's vars */ |
| 427 | u64 remote_vars_part_pa; /* phys addr of partition's vars part */ | 498 | u64 remote_vars_part_pa; /* phys addr of partition's vars part */ |
| @@ -432,10 +503,14 @@ struct xpc_partition { | |||
| 432 | u32 act_IRQ_rcvd; /* IRQs since activation */ | 503 | u32 act_IRQ_rcvd; /* IRQs since activation */ |
| 433 | spinlock_t act_lock; /* protect updating of act_state */ | 504 | spinlock_t act_lock; /* protect updating of act_state */ |
| 434 | u8 act_state; /* from XPC HB viewpoint */ | 505 | u8 act_state; /* from XPC HB viewpoint */ |
| 506 | u8 remote_vars_version; /* version# of partition's vars */ | ||
| 435 | enum xpc_retval reason; /* reason partition is deactivating */ | 507 | enum xpc_retval reason; /* reason partition is deactivating */ |
| 436 | int reason_line; /* line# deactivation initiated from */ | 508 | int reason_line; /* line# deactivation initiated from */ |
