1/*- 2 * Copyright (c) 2001, John Baldwin <jhb@FreeBSD.org>. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 19 unchanged lines hidden (view full) --- 28 */ 29 30/* 31 * This module holds the global variables and machine independent functions 32 * used for the kernel SMP support. 33 */ 34 35#include <sys/cdefs.h> |
36__FBSDID("$FreeBSD: head/sys/kern/subr_smp.c 255726 2013-09-20 05:06:03Z gibbs $"); |
37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <sys/kernel.h> 41#include <sys/ktr.h> 42#include <sys/proc.h> 43#include <sys/bus.h> 44#include <sys/lock.h> --- 175 unchanged lines hidden (view full) --- 220 ("%s: invalid stop type", __func__)); 221 222 if (!smp_started) 223 return (0); 224 225 CTR2(KTR_SMP, "stop_cpus(%s) with %u type", 226 cpusetobj_strprint(cpusetbuf, &map), type); 227 |
228#ifdef XENHVM 229 /* 230 * When migrating a PVHVM domain we need to make sure there are 231 * no IPIs in progress. IPIs that have been issued, but not 232 * yet delivered (not pending on a vCPU) will be lost in the 233 * IPI rebinding process, violating FreeBSD's assumption of 234 * reliable IPI delivery. 235 */ 236 if (type == IPI_SUSPEND) 237 mtx_lock_spin(&smp_ipi_mtx); 238#endif 239 |
240 if (stopping_cpu != PCPU_GET(cpuid)) 241 while (atomic_cmpset_int(&stopping_cpu, NOCPU, 242 PCPU_GET(cpuid)) == 0) 243 while (stopping_cpu != NOCPU) 244 cpu_spinwait(); /* spin */ 245 246 /* send the stop IPI to all CPUs in map */ 247 ipi_selected(map, type); --- 11 unchanged lines hidden (view full) --- 259 cpu_spinwait(); 260 i++; 261 if (i == 100000000) { 262 printf("timeout stopping cpus\n"); 263 break; 264 } 265 } 266 |
267#ifdef XENHVM 268 if (type == IPI_SUSPEND) 269 mtx_unlock_spin(&smp_ipi_mtx); 270#endif 271 |
272 stopping_cpu = NOCPU; 273 return (1); 274} 275 276int 277stop_cpus(cpuset_t map) 278{ 279 --- 24 unchanged lines hidden (view full) --- 304 * - Signals all CPUs in map to restart. 305 * - Waits for each to restart. 306 * 307 * Returns: 308 * -1: error 309 * 0: NA 310 * 1: ok 311 */ |
312static int 313generic_restart_cpus(cpuset_t map, u_int type) |
314{ 315#ifdef KTR 316 char cpusetbuf[CPUSETBUFSIZ]; 317#endif |
318 volatile cpuset_t *cpus; |
319 |
320 KASSERT( 321#if defined(__amd64__) || defined(__i386__) 322 type == IPI_STOP || type == IPI_STOP_HARD || type == IPI_SUSPEND, 323#else 324 type == IPI_STOP || type == IPI_STOP_HARD, 325#endif 326 ("%s: invalid stop type", __func__)); 327 |
328 if (!smp_started) 329 return 0; 330 331 CTR1(KTR_SMP, "restart_cpus(%s)", cpusetobj_strprint(cpusetbuf, &map)); 332 |
333#if defined(__amd64__) || defined(__i386__) 334 if (type == IPI_SUSPEND) 335 cpus = &suspended_cpus; 336 else 337#endif 338 cpus = &stopped_cpus; 339 |
340 /* signal other cpus to restart */ 341 CPU_COPY_STORE_REL(&map, &started_cpus); 342 343 /* wait for each to clear its bit */ |
344 while (CPU_OVERLAP(cpus, &map)) |
345 cpu_spinwait(); 346 347 return 1; 348} 349 |
350int 351restart_cpus(cpuset_t map) 352{ 353 354 return (generic_restart_cpus(map, IPI_STOP)); 355} 356 357#if defined(__amd64__) || defined(__i386__) 358int 359resume_cpus(cpuset_t map) 360{ 361 362 return (generic_restart_cpus(map, IPI_SUSPEND)); 363} 364#endif 365 |
366/* 367 * All-CPU rendezvous. CPUs are signalled, all execute the setup function 368 * (if specified), rendezvous, execute the action function (if specified), 369 * rendezvous again, execute the teardown function (if specified), and then 370 * resume. 371 * 372 * Note that the supplied external functions _must_ be reentrant and aware 373 * that they are running in parallel and in an unknown lock context. --- 463 unchanged lines hidden --- |