1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Copyright 2023 Oxide Computer Company 28 */ 29 30 #ifndef _SYS_DR_H 31 #define _SYS_DR_H 32 33 #ifdef __cplusplus 34 extern "C" { 35 #endif 36 37 #include <sys/types.h> 38 #include <sys/processor.h> 39 #include <sys/obpdefs.h> 40 #include <sys/memlist.h> 41 #include <sys/sbd_ioctl.h> 42 #include <sys/mem_config.h> 43 #include <sys/dr_util.h> 44 #include <sys/drmach.h> 45 #include <sys/param.h> /* for MAXPATHLEN */ 46 #include <sys/varargs.h> 47 #include <sys/note.h> 48 49 #define DR_MAXNUM_NT 3 50 51 /* used to map sbd_comp_type_t to array index */ 52 #define NIX(t) \ 53 (((t) == SBD_COMP_CPU) ? 0 : \ 54 ((t) == SBD_COMP_MEM) ? 1 : \ 55 ((t) == SBD_COMP_IO) ? 2 : \ 56 ((t) == SBD_COMP_CMP) ? 0 : DR_MAXNUM_NT) 57 58 #define BIX(t) \ 59 (((t) == SBD_COMP_CPU) ? 0 : \ 60 ((t) == SBD_COMP_MEM) ? 32 : \ 61 ((t) == SBD_COMP_IO) ? 40 : \ 62 ((t) == SBD_COMP_CMP) ? 0 : 0) 63 64 #define NMASK(t) \ 65 (((t) == SBD_COMP_CPU) ? ((dr_devset_t)0xffffffff) : \ 66 ((t) == SBD_COMP_MEM) ? ((dr_devset_t)0x1) : \ 67 ((t) == SBD_COMP_IO) ? ((dr_devset_t)0x1ff) : \ 68 ((t) == SBD_COMP_CMP) ? ((dr_devset_t)0xffffffff) : 0) 69 70 /* 71 * helper macros for constructing and reporting internal error messages. 72 * NOTE: each module which uses one or more this these macros is expected 73 * to supply a char *dr_ie_fmt string containing the SCCS filename 74 * expansion macro (percent M percent) and a sprintf %d to render the 75 * line number argument. 76 */ 77 #define DR_INTERNAL_ERROR(hp) \ 78 drerr_new(1, ESBD_INTERNAL, dr_ie_fmt, __LINE__) 79 80 #define DR_OP_INTERNAL_ERROR(hp) \ 81 drerr_set_c(CE_WARN, &(hp)->h_err, \ 82 ESBD_INTERNAL, dr_ie_fmt, __LINE__) 83 84 #define DR_DEV_INTERNAL_ERROR(cp) \ 85 drerr_set_c(CE_WARN, &(cp)->sbdev_error, \ 86 ESBD_INTERNAL, dr_ie_fmt, __LINE__) 87 88 /* 89 * TODO: Simplify or get rid of this. 90 * Macros for keeping an error code and an associated list of integers. 91 */ 92 #define DR_MAX_ERR_INT (32) 93 #define DR_GET_E_CODE(sep) ((sep)->e_code) 94 #define DR_SET_E_CODE(sep, en) ((sep)->e_code = (en)) 95 #define DR_GET_E_RSC(sep) ((sep)->e_rsc) 96 97 /* 98 * Format of dr_devset_t bit masks: 99 * 100 * 64 48 40 32 24 16 8 0 101 * |....|...I|IIII|IIII|....|...M|CCCC|CCCC|CCCC|CCCC|CCCC|CCCC|CCCC|CCCC| 102 * 103 * 1 = indicates respective component present/attached. 104 * I = I/O, M = Memory, C = CPU. 105 */ 106 #define _NT2DEVPOS(t, u) (BIX(t) + (u)) 107 #define _DEVSET_MASK ((dr_devset_t)0x1ff01ffffffff) 108 #define _CMP_DEVSET_MASK ((dr_devset_t)0x11111111) 109 #define DEVSET_ONEUNIT ((dr_devset_t)1) 110 #define DEVSET_ANYUNIT (dr_devset_t)(-1) 111 #define DEVSET(t, u) \ 112 (((u) == DEVSET_ANYUNIT) ? \ 113 ((NMASK(t) << _NT2DEVPOS((t), 0)) & _DEVSET_MASK) : \ 114 ((t) == SBD_COMP_CMP) ? \ 115 (_CMP_DEVSET_MASK << _NT2DEVPOS((t), (u))) : \ 116 (DEVSET_ONEUNIT << _NT2DEVPOS((t), (u)))) 117 118 #define DEVSET_IN_SET(ds, t, u) (((ds) & DEVSET((t), (u))) != 0) 119 #define DEVSET_ADD(ds, t, u) ((ds) |= DEVSET((t), (u))) 120 #define DEVSET_DEL(ds, t, u) ((ds) &= ~DEVSET((t), (u))) 121 #define DEVSET_GET_UNITSET(ds, t) \ 122 (((ds) & DEVSET((t), DEVSET_ANYUNIT)) >> _NT2DEVPOS((t), 0)) 123 124 /* 125 * Ops for dr_board_t.b_dev_* 126 */ 127 #define DR_DEV_IS(ds, cp) DEVSET_IN_SET( \ 128 (cp)->sbdev_bp->b_dev_##ds, \ 129 (cp)->sbdev_type, \ 130 (cp)->sbdev_unum) 131 132 #define DR_DEV_ADD(ds, cp) DEVSET_ADD( \ 133 (cp)->sbdev_bp->b_dev_##ds, \ 134 (cp)->sbdev_type, \ 135 (cp)->sbdev_unum) 136 137 #define DR_DEV_DEL(ds, cp) DEVSET_DEL( \ 138 (cp)->sbdev_bp->b_dev_##ds, \ 139 (cp)->sbdev_type, \ 140 (cp)->sbdev_unum) 141 142 /* 143 * Ops for dr_board_t.b_dev_present 144 */ 145 #define DR_DEV_IS_PRESENT(cp) DR_DEV_IS(present, cp) 146 #define DR_DEV_SET_PRESENT(cp) DR_DEV_ADD(present, cp) 147 #define DR_DEV_CLR_PRESENT(cp) DR_DEV_DEL(present, cp) 148 149 /* 150 * Ops for dr_board_t.b_dev_attached 151 */ 152 #define DR_DEV_IS_ATTACHED(cp) DR_DEV_IS(attached, cp) 153 #define DR_DEV_SET_ATTACHED(cp) DR_DEV_ADD(attached, cp) 154 #define DR_DEV_CLR_ATTACHED(cp) DR_DEV_DEL(attached, cp) 155 156 /* 157 * Ops for dr_board_t.b_dev_released 158 */ 159 #define DR_DEV_IS_RELEASED(cp) DR_DEV_IS(released, cp) 160 #define DR_DEV_SET_RELEASED(cp) DR_DEV_ADD(released, cp) 161 #define DR_DEV_CLR_RELEASED(cp) DR_DEV_DEL(released, cp) 162 163 /* 164 * Ops for dr_board_t.b_dev_unreferenced 165 */ 166 #define DR_DEV_IS_UNREFERENCED(cp) DR_DEV_IS(unreferenced, cp) 167 #define DR_DEV_SET_UNREFERENCED(cp) DR_DEV_ADD(unreferenced, cp) 168 #define DR_DEV_CLR_UNREFERENCED(cp) DR_DEV_DEL(unreferenced, cp) 169 170 #define DR_DEVS_PRESENT(bp) \ 171 ((bp)->b_dev_present) 172 #define DR_DEVS_ATTACHED(bp) \ 173 ((bp)->b_dev_attached) 174 #define DR_DEVS_RELEASED(bp) \ 175 ((bp)->b_dev_released) 176 #define DR_DEVS_UNREFERENCED(bp) \ 177 ((bp)->b_dev_unreferenced) 178 #define DR_DEVS_UNATTACHED(bp) \ 179 ((bp)->b_dev_present & ~(bp)->b_dev_attached) 180 #define DR_DEVS_CONFIGURE(bp, devs) \ 181 ((bp)->b_dev_attached = (devs)) 182 #define DR_DEVS_DISCONNECT(bp, devs) \ 183 ((bp)->b_dev_present &= ~(devs)) 184 #define DR_DEVS_CANCEL(bp, devs) \ 185 ((bp)->b_dev_released &= ~(devs), \ 186 (bp)->b_dev_unreferenced &= ~(devs)) 187 188 /* 189 * CMP Specific Helpers 190 */ 191 #define DR_CMP_CORE_UNUM(cmp, core) (cmp + (core * 4)) 192 /* 193 * DR_UNUM2SBD_UNUM should be set to (unum & (max #of CMP on board - 1)) 194 * for all the platforms. So far, all sun4u platforms supported have 195 * the same limit so 0x3 works. One day we might have to make this 196 * a platform specific macro. 197 */ 198 199 #define DR_UNUM2SBD_UNUM(n, d) ((d == SBD_COMP_IO) ? (n & 0xf) : \ 200 (d == SBD_COMP_CPU) ? (n & 0x3) : \ 201 (d == SBD_COMP_CMP) ? (n & 0x3) : \ 202 (n)) 203 204 /* 205 * Some stuff to assist in debug. 206 */ 207 #ifdef DEBUG 208 #define DRDBG_STATE 0x00000001 209 #define DRDBG_QR 0x00000002 210 #define DRDBG_CPU 0x00000004 211 #define DRDBG_MEM 0x00000008 212 #define DRDBG_IO 0x00000010 213 214 #define PR_ALL if (dr_debug) printf 215 #define PR_STATE if (dr_debug & DRDBG_STATE) printf 216 #define PR_QR if (dr_debug & DRDBG_QR) prom_printf 217 #define PR_CPU if (dr_debug & DRDBG_CPU) printf 218 #define PR_MEM if (dr_debug & DRDBG_MEM) printf 219 #define PR_IO if (dr_debug & DRDBG_IO) printf 220 #define PR_MEMLIST_DUMP if (dr_debug & DRDBG_MEM) MEMLIST_DUMP 221 222 extern uint_t dr_debug; 223 #else /* DEBUG */ 224 #define PR_ALL _NOTE(CONSTANTCONDITION) if (0) printf 225 #define PR_STATE PR_ALL 226 #define PR_QR PR_ALL 227 #define PR_CPU PR_ALL 228 #define PR_MEM PR_ALL 229 #define PR_IO PR_ALL 230 #define PR_MEMLIST_DUMP _NOTE(CONSTANTCONDITION) if (0) MEMLIST_DUMP 231 232 #endif /* DEBUG */ 233 234 /* 235 * dr_board_t b_sflags. 236 */ 237 #define DR_BSLOCK 0x01 /* for blocking status (protected by b_slock) */ 238 239 typedef const char *fn_t; 240 typedef uint64_t dr_devset_t; /* TODO: fix limitation */ 241 242 /* 243 * Unsafe devices based on dr.conf prop "unsupported-io-drivers" 244 */ 245 typedef struct { 246 char **devnames; 247 uint_t ndevs; 248 } dr_unsafe_devs_t; 249 250 /* 251 * Device states. 252 * PARTIAL state is really only relevant for board state. 253 */ 254 typedef enum { 255 DR_STATE_EMPTY = 0, 256 DR_STATE_OCCUPIED, 257 DR_STATE_CONNECTED, 258 DR_STATE_UNCONFIGURED, 259 DR_STATE_PARTIAL, /* part connected, part configured */ 260 DR_STATE_CONFIGURED, 261 DR_STATE_RELEASE, 262 DR_STATE_UNREFERENCED, 263 DR_STATE_FATAL, 264 DR_STATE_MAX 265 } dr_state_t; 266 267 typedef struct dr_handle { 268 struct dr_board *h_bd; 269 sbd_error_t *h_err; 270 int h_op_intr; /* nz if op interrupted */ 271 dev_t h_dev; /* dev_t of opened device */ 272 int h_cmd; /* PIM ioctl argument */ 273 int h_mode; /* device open mode */ 274 sbd_cmd_t h_sbdcmd; /* copied-in ioctl cmd struct */ 275 sbd_ioctl_arg_t *h_iap; /* ptr to caller-space cmd struct */ 276 dr_devset_t h_devset; /* based on h_dev */ 277 drmach_opts_t h_opts; /* command-line platform options */ 278 } dr_handle_t; 279 280 typedef struct dr_common_unit { 281 dr_state_t sbdev_state; 282 sbd_state_t sbdev_ostate; 283 sbd_cond_t sbdev_cond; 284 time_t sbdev_time; 285 int sbdev_busy; 286 struct dr_board *sbdev_bp; 287 int sbdev_unum; 288 sbd_comp_type_t sbdev_type; 289 drmachid_t sbdev_id; 290 char sbdev_path[MAXNAMELEN]; 291 sbd_error_t *sbdev_error; 292 } dr_common_unit_t; 293 294 typedef struct dr_mem_unit { 295 dr_common_unit_t sbm_cm; /* mem-unit state */ 296 uint_t sbm_flags; 297 pfn_t sbm_basepfn; 298 pgcnt_t sbm_npages; 299 pgcnt_t sbm_pageslost; 300 struct memlist *sbm_dyn_segs; /* kphysm_add_dynamic segs */ 301 /* 302 * The following fields are used during 303 * the memory detach process only. sbm_mlist 304 * will be used to store the board memlist 305 * following a detach. The memlist will be 306 * used to re-attach the board when configuring 307 * the unit directly after an unconfigure. 308 */ 309 struct dr_mem_unit *sbm_peer; 310 struct memlist *sbm_mlist; 311 struct memlist *sbm_del_mlist; 312 memhandle_t sbm_memhandle; 313 pfn_t sbm_alignment_mask; 314 pfn_t sbm_slice_offset; 315 uint64_t sbm_slice_size; 316 } dr_mem_unit_t; 317 318 /* 319 * Currently only maintain state information for individual 320 * components. 321 */ 322 typedef struct dr_cpu_unit { 323 dr_common_unit_t sbc_cm; /* cpu-unit state */ 324 processorid_t sbc_cpu_id; 325 cpu_flag_t sbc_cpu_flags; /* snapshot of CPU flags */ 326 ushort_t sbc_pad1; /* padded for compatibility */ 327 int sbc_speed; 328 int sbc_ecache; 329 int sbc_cpu_impl; 330 } dr_cpu_unit_t; 331 332 typedef struct dr_io_unit { 333 dr_common_unit_t sbi_cm; /* io-unit state */ 334 } dr_io_unit_t; 335 336 typedef union { 337 dr_common_unit_t du_common; 338 dr_mem_unit_t du_mem; 339 dr_cpu_unit_t du_cpu; 340 dr_io_unit_t du_io; 341 } dr_dev_unit_t; 342 343 typedef struct dr_board { 344 kmutex_t b_lock; /* lock for this board struct */ 345 kmutex_t b_slock; /* lock for status on the board */ 346 kcondvar_t b_scv; /* condvar for status on the board */ 347 int b_sflags; /* for serializing status */ 348 sbd_state_t b_rstate; /* board's cfgadm receptacle state */ 349 sbd_state_t b_ostate; /* board's cfgadm occupant state */ 350 sbd_cond_t b_cond; /* cfgadm condition */ 351 int b_busy; 352 int b_assigned; 353 time_t b_time; /* time of last board operation */ 354 char b_type[MAXNAMELEN]; 355 drmachid_t b_id; 356 int b_num; /* board number */ 357 int b_ndev; /* # of devices on board */ 358 dev_info_t *b_dip; /* dip for make-nodes */ 359 dr_state_t b_state; /* board DR state */ 360 dr_devset_t b_dev_present; /* present mask */ 361 dr_devset_t b_dev_attached; /* attached mask */ 362 dr_devset_t b_dev_released; /* released mask */ 363 dr_devset_t b_dev_unreferenced; /* unreferenced mask */ 364 char b_path[MAXNAMELEN]; 365 dr_dev_unit_t *b_dev[DR_MAXNUM_NT]; 366 } dr_board_t; 367 368 /* 369 * dr_quiesce.c interfaces 370 */ 371 struct dr_sr_handle; 372 typedef struct dr_sr_handle dr_sr_handle_t; 373 374 extern dr_sr_handle_t *dr_get_sr_handle(dr_handle_t *handle); 375 extern void dr_release_sr_handle(dr_sr_handle_t *srh); 376 extern int dr_suspend(dr_sr_handle_t *srh); 377 extern void dr_resume(dr_sr_handle_t *srh); 378 extern void dr_check_devices(dev_info_t *dip, int *refcount, 379 dr_handle_t *handle, uint64_t *arr, int *idx, 380 int len, int *refcount_non_gldv3); 381 extern int dr_pt_test_suspend(dr_handle_t *hp); 382 383 /* 384 * dr_cpu.c interface 385 */ 386 extern void dr_init_cpu_unit(dr_cpu_unit_t *cp); 387 extern int dr_pre_attach_cpu(dr_handle_t *hp, 388 dr_common_unit_t **devlist, int devnum); 389 extern void dr_attach_cpu(dr_handle_t *hp, dr_common_unit_t *cp); 390 extern int dr_post_attach_cpu(dr_handle_t *hp, 391 dr_common_unit_t **devlist, int devnum); 392 extern int dr_pre_release_cpu(dr_handle_t *hp, 393 dr_common_unit_t **devlist, int devnum); 394 extern int dr_pre_detach_cpu(dr_handle_t *hp, 395 dr_common_unit_t **devlist, int devnum); 396 extern void dr_detach_cpu(dr_handle_t *hp, dr_common_unit_t *cp); 397 extern int dr_post_detach_cpu(dr_handle_t *hp, 398 dr_common_unit_t **devlist, int devnum); 399 extern int dr_cpu_status(dr_handle_t *hp, dr_devset_t devset, 400 sbd_dev_stat_t *dsp); 401 extern int dr_cancel_cpu(dr_cpu_unit_t *cp); 402 extern int dr_disconnect_cpu(dr_cpu_unit_t *cp); 403 404 405 /* 406 * dr_mem.c interface 407 */ 408 extern void dr_init_mem_unit(dr_mem_unit_t *mp); 409 extern int dr_pre_attach_mem(dr_handle_t *hp, 410 dr_common_unit_t **devlist, int devnum); 411 extern void dr_attach_mem(dr_handle_t *hp, dr_common_unit_t *cp); 412 extern int dr_post_attach_mem(dr_handle_t *hp, 413 dr_common_unit_t **devlist, int devnum); 414 extern int dr_pre_release_mem(dr_handle_t *hp, 415 dr_common_unit_t **devlist, int devnum); 416 extern void dr_release_mem(dr_common_unit_t *cp); 417 extern void dr_release_mem_done(dr_common_unit_t *cp); 418 extern int dr_pre_detach_mem(dr_handle_t *hp, 419 dr_common_unit_t **devlist, int devnum); 420 extern void dr_detach_mem(dr_handle_t *, dr_common_unit_t *); 421 extern int dr_post_detach_mem(dr_handle_t *hp, 422 dr_common_unit_t **devlist, int devnum); 423 extern int dr_mem_status(dr_handle_t *hp, dr_devset_t devset, 424 sbd_dev_stat_t *dsp); 425 extern int dr_cancel_mem(dr_mem_unit_t *mp); 426 extern int dr_disconnect_mem(dr_mem_unit_t *mp); 427 428 /* 429 * dr_io.c interface 430 */ 431 extern void dr_init_io_unit(dr_io_unit_t *io); 432 extern int dr_disconnect_io(dr_io_unit_t *ip); 433 extern int dr_pre_attach_io(dr_handle_t *hp, 434 dr_common_unit_t **devlist, int devnum); 435 extern void dr_attach_io(dr_handle_t *hp, dr_common_unit_t *cp); 436 extern int dr_post_attach_io(dr_handle_t *hp, 437 dr_common_unit_t **devlist, int devnum); 438 extern int dr_pre_release_io(dr_handle_t *hp, 439 dr_common_unit_t **devlist, int devnum); 440 extern int dr_pre_detach_io(dr_handle_t *hp, 441 dr_common_unit_t **devlist, int devnum); 442 extern void dr_detach_io(dr_handle_t *hp, dr_common_unit_t *cp); 443 extern int dr_post_detach_io(dr_handle_t *hp, 444 dr_common_unit_t **devlist, int devnum); 445 extern int dr_io_status(dr_handle_t *hp, dr_devset_t devset, 446 sbd_dev_stat_t *dsp); 447 448 449 /* 450 * dr.c interface 451 */ 452 extern void dr_op_err(int ce, dr_handle_t *hp, int code, char *fmt, ...); 453 extern void dr_dev_err(int ce, dr_common_unit_t *cp, int code); 454 455 extern dr_cpu_unit_t *dr_get_cpu_unit(dr_board_t *bp, int unit_num); 456 extern dr_mem_unit_t *dr_get_mem_unit(dr_board_t *bp, int unit_num); 457 extern dr_io_unit_t *dr_get_io_unit(dr_board_t *bp, int unit_num); 458 459 extern dr_board_t *dr_lookup_board(int board_num); 460 extern int dr_release_dev_done(dr_common_unit_t *cp); 461 extern char *dr_nt_to_dev_type(int type); 462 extern void dr_device_transition(dr_common_unit_t *cp, 463 dr_state_t new_state); 464 extern void dr_lock_status(dr_board_t *bp); 465 extern void dr_unlock_status(dr_board_t *bp); 466 extern int dr_cmd_flags(dr_handle_t *hp); 467 468 #ifdef __cplusplus 469 } 470 #endif 471 472 #endif /* _SYS_DR_H */ 473