xref: /titanic_53/usr/src/cmd/drd/drd.c (revision 8fea755a86ff6c596183a4366bfbd59f1bfdfe55)
11d4b38e0Srsmaeda /*
21d4b38e0Srsmaeda  * CDDL HEADER START
31d4b38e0Srsmaeda  *
41d4b38e0Srsmaeda  * The contents of this file are subject to the terms of the
51d4b38e0Srsmaeda  * Common Development and Distribution License (the "License").
61d4b38e0Srsmaeda  * You may not use this file except in compliance with the License.
71d4b38e0Srsmaeda  *
81d4b38e0Srsmaeda  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91d4b38e0Srsmaeda  * or http://www.opensolaris.org/os/licensing.
101d4b38e0Srsmaeda  * See the License for the specific language governing permissions
111d4b38e0Srsmaeda  * and limitations under the License.
121d4b38e0Srsmaeda  *
131d4b38e0Srsmaeda  * When distributing Covered Code, include this CDDL HEADER in each
141d4b38e0Srsmaeda  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151d4b38e0Srsmaeda  * If applicable, add the following below this CDDL HEADER, with the
161d4b38e0Srsmaeda  * fields enclosed by brackets "[]" replaced with your own identifying
171d4b38e0Srsmaeda  * information: Portions Copyright [yyyy] [name of copyright owner]
181d4b38e0Srsmaeda  *
191d4b38e0Srsmaeda  * CDDL HEADER END
201d4b38e0Srsmaeda  */
211d4b38e0Srsmaeda 
221d4b38e0Srsmaeda /*
23*8fea755aSjm22469  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
241d4b38e0Srsmaeda  * Use is subject to license terms.
251d4b38e0Srsmaeda  */
261d4b38e0Srsmaeda 
271d4b38e0Srsmaeda #pragma ident	"%Z%%M%	%I%	%E% SMI"
281d4b38e0Srsmaeda 
291d4b38e0Srsmaeda /*
301d4b38e0Srsmaeda  * sun4v DR daemon
311d4b38e0Srsmaeda  */
321d4b38e0Srsmaeda 
331d4b38e0Srsmaeda #include <stdio.h>
341d4b38e0Srsmaeda #include <stdlib.h>
351d4b38e0Srsmaeda #include <unistd.h>
361d4b38e0Srsmaeda #include <string.h>
371d4b38e0Srsmaeda #include <strings.h>
381d4b38e0Srsmaeda #include <fcntl.h>
391d4b38e0Srsmaeda #include <errno.h>
401d4b38e0Srsmaeda #include <libgen.h>
411d4b38e0Srsmaeda #include <syslog.h>
421d4b38e0Srsmaeda #include <door.h>
431d4b38e0Srsmaeda #include <assert.h>
441d4b38e0Srsmaeda #include <sys/types.h>
451d4b38e0Srsmaeda #include <sys/stat.h>
461d4b38e0Srsmaeda 
471d4b38e0Srsmaeda #include <sys/drctl_impl.h>
481d4b38e0Srsmaeda #include <sys/drctl.h>
491d4b38e0Srsmaeda #include "drd.h"
501d4b38e0Srsmaeda 
511d4b38e0Srsmaeda boolean_t drd_debug = B_FALSE;
521d4b38e0Srsmaeda boolean_t drd_daemonized = B_FALSE;
531d4b38e0Srsmaeda 
541d4b38e0Srsmaeda #define	DRD_DOOR_FILE		"/tmp/drd_door"
551d4b38e0Srsmaeda #define	DRD_DOOR_RETURN_ERR()	(void) door_return(NULL, 0, NULL, 0)
561d4b38e0Srsmaeda 
571d4b38e0Srsmaeda static char *cmdname;
581d4b38e0Srsmaeda static int drctl_fd;
591d4b38e0Srsmaeda static drctl_rsrc_t *drd_result = NULL;
601d4b38e0Srsmaeda 
611d4b38e0Srsmaeda /*
621d4b38e0Srsmaeda  * Currently, the only supported backend is for the Reconfiguration
631d4b38e0Srsmaeda  * Coordination Manager (RCM). When there are other backends, this
641d4b38e0Srsmaeda  * variable should be set dynamically.
651d4b38e0Srsmaeda  */
661d4b38e0Srsmaeda static drd_backend_t *drd_backend = &drd_rcm_backend;
671d4b38e0Srsmaeda 
681d4b38e0Srsmaeda static void drd_daemonize(void);
691d4b38e0Srsmaeda static int drd_init_drctl_dev(boolean_t standalone);
701d4b38e0Srsmaeda static int drd_init_door_server(boolean_t standalone);
711d4b38e0Srsmaeda static void drd_door_server(void *, char *, size_t, door_desc_t *, uint_t);
721d4b38e0Srsmaeda 
731d4b38e0Srsmaeda int
741d4b38e0Srsmaeda main(int argc, char **argv)
751d4b38e0Srsmaeda {
761d4b38e0Srsmaeda 	int		opt;
7720046e4cSjm22469 	boolean_t	standalone = B_FALSE;
781d4b38e0Srsmaeda 
791d4b38e0Srsmaeda 	cmdname = basename(argv[0]);
801d4b38e0Srsmaeda 
811d4b38e0Srsmaeda 	/*
821d4b38e0Srsmaeda 	 * Process command line arguments
831d4b38e0Srsmaeda 	 */
841d4b38e0Srsmaeda 	opterr = 0;	/* disable getopt error messages */
851d4b38e0Srsmaeda 	while ((opt = getopt(argc, argv, "ds")) != EOF) {
861d4b38e0Srsmaeda 
871d4b38e0Srsmaeda 		switch (opt) {
881d4b38e0Srsmaeda 		case 'd':
891d4b38e0Srsmaeda 			drd_debug = B_TRUE;
901d4b38e0Srsmaeda 			break;
911d4b38e0Srsmaeda 		case 's':
921d4b38e0Srsmaeda 			standalone = B_TRUE;
931d4b38e0Srsmaeda 			break;
941d4b38e0Srsmaeda 		default:
951d4b38e0Srsmaeda 			drd_err("unkown option: -%c", optopt);
961d4b38e0Srsmaeda 			exit(1);
971d4b38e0Srsmaeda 		}
981d4b38e0Srsmaeda 	}
991d4b38e0Srsmaeda 
1001d4b38e0Srsmaeda 	drd_dbg("initializing %s...", cmdname);
1011d4b38e0Srsmaeda 
1021d4b38e0Srsmaeda 	/* must be root */
1031d4b38e0Srsmaeda 	if (geteuid() != 0) {
1041d4b38e0Srsmaeda 		drd_err("permission denied: must run as root");
1051d4b38e0Srsmaeda 		exit(1);
1061d4b38e0Srsmaeda 	}
1071d4b38e0Srsmaeda 
1081d4b38e0Srsmaeda 	/* open the drctl device */
1091d4b38e0Srsmaeda 	if (drd_init_drctl_dev(standalone) != 0) {
1101d4b38e0Srsmaeda 		drd_err("unable to initialize drctl device");
1111d4b38e0Srsmaeda 		exit(1);
1121d4b38e0Srsmaeda 	}
1131d4b38e0Srsmaeda 
1141d4b38e0Srsmaeda 	/* daemonize */
1151d4b38e0Srsmaeda 	if (!standalone) {
1161d4b38e0Srsmaeda 		drd_daemonize();
1171d4b38e0Srsmaeda 	}
1181d4b38e0Srsmaeda 
1191d4b38e0Srsmaeda 	/* initialize door server */
1201d4b38e0Srsmaeda 	if (drd_init_door_server(standalone) != 0) {
1211d4b38e0Srsmaeda 		drd_err("unable to initialize door server");
1221d4b38e0Srsmaeda 		exit(1);
1231d4b38e0Srsmaeda 	}
1241d4b38e0Srsmaeda 
1251d4b38e0Srsmaeda 	/* initialize the backend */
1261d4b38e0Srsmaeda 	if ((*drd_backend->init)() != 0) {
1271d4b38e0Srsmaeda 		drd_err("unable to initialize backend processor");
1281d4b38e0Srsmaeda 		exit(1);
1291d4b38e0Srsmaeda 	}
1301d4b38e0Srsmaeda 
1311d4b38e0Srsmaeda 	/* loop forever */
1321d4b38e0Srsmaeda 	for (;;) {
1331d4b38e0Srsmaeda 		pause();
1341d4b38e0Srsmaeda 	}
1351d4b38e0Srsmaeda 
1361d4b38e0Srsmaeda 	/*NOTREACHED*/
1371d4b38e0Srsmaeda 	return (0);
1381d4b38e0Srsmaeda }
1391d4b38e0Srsmaeda 
1401d4b38e0Srsmaeda static void
1411d4b38e0Srsmaeda drd_daemonize(void)
1421d4b38e0Srsmaeda {
1431d4b38e0Srsmaeda 	pid_t	pid;
1441d4b38e0Srsmaeda 
1451d4b38e0Srsmaeda 	if ((pid = fork()) == -1) {
1461d4b38e0Srsmaeda 		drd_err("failed to fork: %s", strerror(errno));
1471d4b38e0Srsmaeda 		exit(1);
1481d4b38e0Srsmaeda 	}
1491d4b38e0Srsmaeda 
1501d4b38e0Srsmaeda 	if (pid != 0) {
1511d4b38e0Srsmaeda 		/* parent */
1521d4b38e0Srsmaeda 		exit(0);
1531d4b38e0Srsmaeda 	}
1541d4b38e0Srsmaeda 
1551d4b38e0Srsmaeda 	/*
1561d4b38e0Srsmaeda 	 * Initialize child process
1571d4b38e0Srsmaeda 	 */
1581d4b38e0Srsmaeda 	(void) setsid();
1591d4b38e0Srsmaeda 	(void) chdir("/");
1601d4b38e0Srsmaeda 	(void) umask(0);
1611d4b38e0Srsmaeda 
1621d4b38e0Srsmaeda 	/*
16320046e4cSjm22469 	 * Initialize file descriptors. Do not touch stderr
16420046e4cSjm22469 	 * which is initialized by SMF to point to the drd
16520046e4cSjm22469 	 * specific log file.
1661d4b38e0Srsmaeda 	 */
1671d4b38e0Srsmaeda 	assert(drctl_fd == (STDERR_FILENO + 1));
1681d4b38e0Srsmaeda 
1691d4b38e0Srsmaeda 	(void) close(STDIN_FILENO);
1701d4b38e0Srsmaeda 	(void) open("/dev/null", O_RDWR);
1711d4b38e0Srsmaeda 	(void) dup2(STDIN_FILENO, STDOUT_FILENO);
1721d4b38e0Srsmaeda 
1731d4b38e0Srsmaeda 	closefrom(drctl_fd + 1);
1741d4b38e0Srsmaeda 
1751d4b38e0Srsmaeda 	/* initialize logging */
1761d4b38e0Srsmaeda 	openlog(cmdname, LOG_CONS | LOG_NDELAY, LOG_DAEMON);
1771d4b38e0Srsmaeda 
1781d4b38e0Srsmaeda 	drd_daemonized = B_TRUE;
1791d4b38e0Srsmaeda }
1801d4b38e0Srsmaeda 
1811d4b38e0Srsmaeda static int
1821d4b38e0Srsmaeda drd_init_drctl_dev(boolean_t standalone)
1831d4b38e0Srsmaeda {
1841d4b38e0Srsmaeda 	void (*drd_output)(char *, ...);
1851d4b38e0Srsmaeda 
1861d4b38e0Srsmaeda 	drd_output = (standalone) ? drd_info : drd_err;
1871d4b38e0Srsmaeda 
1881d4b38e0Srsmaeda 	/* open the drctl device */
1891d4b38e0Srsmaeda 	if ((drctl_fd = open(DRCTL_DEV, O_RDWR)) == -1) {
1901d4b38e0Srsmaeda 		drd_output("open %s failed: %s", DRCTL_DEV, strerror(errno));
1911d4b38e0Srsmaeda 		return ((standalone) ? 0 : -1);
1921d4b38e0Srsmaeda 	}
1931d4b38e0Srsmaeda 
1941d4b38e0Srsmaeda 	return (0);
1951d4b38e0Srsmaeda }
1961d4b38e0Srsmaeda 
1971d4b38e0Srsmaeda static int
1981d4b38e0Srsmaeda drd_init_door_server(boolean_t standalone)
1991d4b38e0Srsmaeda {
2001d4b38e0Srsmaeda 	int		door_fd;
2011d4b38e0Srsmaeda 	int		dbg_fd;
2021d4b38e0Srsmaeda 	drctl_setup_t	setup;
2031d4b38e0Srsmaeda 
2041d4b38e0Srsmaeda 	assert((drctl_fd != -1) || standalone);
2051d4b38e0Srsmaeda 
2061d4b38e0Srsmaeda 	/* create the door */
2071d4b38e0Srsmaeda 	if ((door_fd = door_create(drd_door_server, NULL, 0)) == -1) {
2081d4b38e0Srsmaeda 		drd_err("door_create failed: %s", strerror(errno));
2091d4b38e0Srsmaeda 		return (-1);
2101d4b38e0Srsmaeda 	}
2111d4b38e0Srsmaeda 
2121d4b38e0Srsmaeda 	if (drctl_fd != -1) {
2131d4b38e0Srsmaeda 
2141d4b38e0Srsmaeda 		setup.did = door_fd;
2151d4b38e0Srsmaeda 
2161d4b38e0Srsmaeda 		/* send the door descriptor to drctl */
2171d4b38e0Srsmaeda 		if (ioctl(drctl_fd, DRCTL_IOCTL_CONNECT_SERVER, &setup) == -1) {
2181d4b38e0Srsmaeda 			drd_err("drctl ioctl failed: %s", strerror(errno));
2191d4b38e0Srsmaeda 			(void) door_revoke(door_fd);
2201d4b38e0Srsmaeda 			return (-1);
2211d4b38e0Srsmaeda 		}
2221d4b38e0Srsmaeda 
2231d4b38e0Srsmaeda 		drd_dbg("connection to drctl established");
2241d4b38e0Srsmaeda 
2251d4b38e0Srsmaeda 		/* setup is complete in daemon mode */
2261d4b38e0Srsmaeda 		if (!standalone) {
2271d4b38e0Srsmaeda 			return (0);
2281d4b38e0Srsmaeda 		}
2291d4b38e0Srsmaeda 	}
2301d4b38e0Srsmaeda 
2311d4b38e0Srsmaeda 	/*
2321d4b38e0Srsmaeda 	 * At this point, the daemon is running in standalone
2331d4b38e0Srsmaeda 	 * mode for testing purposes. This allows the daemon
2341d4b38e0Srsmaeda 	 * to be controlled directly through a door exported
2351d4b38e0Srsmaeda 	 * to the filesystem. No drctl device is required in
2361d4b38e0Srsmaeda 	 * this mode.
2371d4b38e0Srsmaeda 	 */
2381d4b38e0Srsmaeda 
2391d4b38e0Srsmaeda 	/* create the door file */
2401d4b38e0Srsmaeda 	unlink(DRD_DOOR_FILE);
2411d4b38e0Srsmaeda 	if ((dbg_fd = creat(DRD_DOOR_FILE, 0644)) == -1) {
2421d4b38e0Srsmaeda 		drd_err("failed to create door file '%s': %s",
2431d4b38e0Srsmaeda 		    DRD_DOOR_FILE, strerror(errno));
2441d4b38e0Srsmaeda 		(void) door_revoke(door_fd);
2451d4b38e0Srsmaeda 		return (-1);
2461d4b38e0Srsmaeda 	}
2471d4b38e0Srsmaeda 	close(dbg_fd);
2481d4b38e0Srsmaeda 
2491d4b38e0Srsmaeda 	/* attach the door file to the door descriptor */
2501d4b38e0Srsmaeda 	if (fattach(door_fd, DRD_DOOR_FILE) == -1) {
2511d4b38e0Srsmaeda 		drd_err("failed to fattach door file '%s': %s",
2521d4b38e0Srsmaeda 		    DRD_DOOR_FILE, strerror(errno));
2531d4b38e0Srsmaeda 		unlink(DRD_DOOR_FILE);
2541d4b38e0Srsmaeda 		(void) door_revoke(door_fd);
2551d4b38e0Srsmaeda 		return (-1);
2561d4b38e0Srsmaeda 	}
2571d4b38e0Srsmaeda 
2581d4b38e0Srsmaeda 	drd_dbg("door server attached to '%s'", DRD_DOOR_FILE);
2591d4b38e0Srsmaeda 
2601d4b38e0Srsmaeda 	return (0);
2611d4b38e0Srsmaeda }
2621d4b38e0Srsmaeda 
2631d4b38e0Srsmaeda static size_t
2641d4b38e0Srsmaeda drd_pack_response(drctl_rsrc_t *rsrcs, int nrsrc)
2651d4b38e0Srsmaeda {
2661d4b38e0Srsmaeda 	drctl_rsrc_t	*orsrcsp;
2671d4b38e0Srsmaeda 	void		*resizep;
2681d4b38e0Srsmaeda 	size_t		osize;
2691d4b38e0Srsmaeda 	char		*str;
2701d4b38e0Srsmaeda 	size_t		offset;
2711d4b38e0Srsmaeda 	char		*off;
2721d4b38e0Srsmaeda 	int		idx;
2731d4b38e0Srsmaeda 	size_t		len;
2741d4b38e0Srsmaeda 
2751d4b38e0Srsmaeda 	drd_dbg("drd_pack_response...");
2761d4b38e0Srsmaeda 
2771d4b38e0Srsmaeda 	/*
2781d4b38e0Srsmaeda 	 * Deallocate the global response buffer if it is
2791d4b38e0Srsmaeda 	 * in use. This assumes that there will only ever
2801d4b38e0Srsmaeda 	 * be one pending operation in the daemon. This is
2811d4b38e0Srsmaeda 	 * enforced by the kernel.
2821d4b38e0Srsmaeda 	 */
2831d4b38e0Srsmaeda 	s_free(drd_result);
2841d4b38e0Srsmaeda 
2851d4b38e0Srsmaeda 	orsrcsp = calloc(sizeof (*orsrcsp), nrsrc);
2861d4b38e0Srsmaeda 	osize = sizeof (*orsrcsp) * nrsrc;
2871d4b38e0Srsmaeda 	bcopy(rsrcs, orsrcsp, osize);
2881d4b38e0Srsmaeda 
2891d4b38e0Srsmaeda 	offset = osize;
2901d4b38e0Srsmaeda 
2911d4b38e0Srsmaeda 	/*
2921d4b38e0Srsmaeda 	 * Loop through all the resources and concatenate
2931d4b38e0Srsmaeda 	 * all the error strings to the end of the resource
2941d4b38e0Srsmaeda 	 * array. Also, update the offset field of each
2951d4b38e0Srsmaeda 	 * resource.
2961d4b38e0Srsmaeda 	 */
2971d4b38e0Srsmaeda 	for (idx = 0; idx < nrsrc; idx++) {
2981d4b38e0Srsmaeda 
2991d4b38e0Srsmaeda 		str = (char *)(uintptr_t)rsrcs[idx].offset;
3001d4b38e0Srsmaeda 
3011d4b38e0Srsmaeda 		/* skip if no error string */
3021d4b38e0Srsmaeda 		if (str == NULL)
3031d4b38e0Srsmaeda 			continue;
3041d4b38e0Srsmaeda 
3051d4b38e0Srsmaeda 		len = strlen(str) + 1;
3061d4b38e0Srsmaeda 
3071d4b38e0Srsmaeda 		/* increase the size of the buffer */
3081d4b38e0Srsmaeda 		resizep = realloc(orsrcsp, osize + len);
3091d4b38e0Srsmaeda 		if (resizep == NULL) {
3101d4b38e0Srsmaeda 			drd_err("realloc failed: %s", strerror(errno));
3111d4b38e0Srsmaeda 			s_free(orsrcsp);
3121d4b38e0Srsmaeda 
3131d4b38e0Srsmaeda 			/* clean up any remaining strings */
3141d4b38e0Srsmaeda 			while (idx < nrsrc) {
3151d4b38e0Srsmaeda 				str = (char *)(uintptr_t)rsrcs[idx++].offset;
3161d4b38e0Srsmaeda 				s_free(str);
3171d4b38e0Srsmaeda 			}
3181d4b38e0Srsmaeda 			return (0);
3191d4b38e0Srsmaeda 		}
3201d4b38e0Srsmaeda 
3211d4b38e0Srsmaeda 		orsrcsp = resizep;
3221d4b38e0Srsmaeda 
3231d4b38e0Srsmaeda 		/* copy the error string into the response */
3241d4b38e0Srsmaeda 		off = (char *)orsrcsp + offset;
3251d4b38e0Srsmaeda 		bcopy(str, off, len);
3261d4b38e0Srsmaeda 		orsrcsp[idx].offset = offset;
3271d4b38e0Srsmaeda 
3281d4b38e0Srsmaeda 		/*
3291d4b38e0Srsmaeda 		 * Now that the error string has been copied
3301d4b38e0Srsmaeda 		 * into the response message, the memory that
3311d4b38e0Srsmaeda 		 * was allocated for it is no longer needed.
3321d4b38e0Srsmaeda 		 */
3331d4b38e0Srsmaeda 		s_free(str);
3341d4b38e0Srsmaeda 		rsrcs[idx].offset = 0;
3351d4b38e0Srsmaeda 
3361d4b38e0Srsmaeda 		/* update size and offset */
3371d4b38e0Srsmaeda 		offset += len;
3381d4b38e0Srsmaeda 		osize += len;
3391d4b38e0Srsmaeda 	}
3401d4b38e0Srsmaeda 
3411d4b38e0Srsmaeda 	drd_result = orsrcsp;
3421d4b38e0Srsmaeda 	return (osize);
3431d4b38e0Srsmaeda }
3441d4b38e0Srsmaeda 
3451d4b38e0Srsmaeda /*ARGSUSED*/
3461d4b38e0Srsmaeda static void
3471d4b38e0Srsmaeda drd_door_server(void *cookie, char *argp, size_t arg_sz, door_desc_t *dp,
3481d4b38e0Srsmaeda     uint_t n_desc)
3491d4b38e0Srsmaeda {
3501d4b38e0Srsmaeda 	drd_msg_t	*msg = (drd_msg_t *)(uintptr_t)argp;
3511d4b38e0Srsmaeda 	drctl_rsrc_t	*rsrcs;
3521d4b38e0Srsmaeda 	size_t		osize;
3531d4b38e0Srsmaeda 	int		nrsrc;
3541d4b38e0Srsmaeda 
3551d4b38e0Srsmaeda 	drd_dbg("drd_door_server...");
3561d4b38e0Srsmaeda 	drd_dbg("message received: %d bytes", arg_sz);
3571d4b38e0Srsmaeda 
3581d4b38e0Srsmaeda 	/* sanity check incoming arg */
3591d4b38e0Srsmaeda 	if ((argp == NULL) || (arg_sz == 0))
3601d4b38e0Srsmaeda 		DRD_DOOR_RETURN_ERR();
3611d4b38e0Srsmaeda 
3621d4b38e0Srsmaeda 	drd_dbg("  cmd=%d, count=%d, flags=%d", msg->cmd,
3631d4b38e0Srsmaeda 	    msg->count, msg->flags);
3641d4b38e0Srsmaeda 
3651d4b38e0Srsmaeda 	rsrcs = (drctl_rsrc_t *)(uintptr_t)msg->data;
3661d4b38e0Srsmaeda 	nrsrc = msg->count;
3671d4b38e0Srsmaeda 
3681d4b38e0Srsmaeda 	/* pass off to backend for processing */
3691d4b38e0Srsmaeda 	switch (msg->cmd) {
3701d4b38e0Srsmaeda 	case DRCTL_CPU_CONFIG_REQUEST:
3711d4b38e0Srsmaeda 		(*drd_backend->cpu_config_request)(rsrcs, nrsrc);
3721d4b38e0Srsmaeda 		break;
3731d4b38e0Srsmaeda 
3741d4b38e0Srsmaeda 	case DRCTL_CPU_CONFIG_NOTIFY:
3751d4b38e0Srsmaeda 		(*drd_backend->cpu_config_notify)(rsrcs, nrsrc);
3761d4b38e0Srsmaeda 		break;
3771d4b38e0Srsmaeda 
3781d4b38e0Srsmaeda 	case DRCTL_CPU_UNCONFIG_REQUEST:
3791d4b38e0Srsmaeda 		(*drd_backend->cpu_unconfig_request)(rsrcs, nrsrc);
3801d4b38e0Srsmaeda 		break;
3811d4b38e0Srsmaeda 
3821d4b38e0Srsmaeda 	case DRCTL_CPU_UNCONFIG_NOTIFY:
3831d4b38e0Srsmaeda 		(*drd_backend->cpu_unconfig_notify)(rsrcs, nrsrc);
3841d4b38e0Srsmaeda 		break;
3851d4b38e0Srsmaeda 
3861d4b38e0Srsmaeda 	case DRCTL_MEM_CONFIG_REQUEST:
3871d4b38e0Srsmaeda 	case DRCTL_MEM_CONFIG_NOTIFY:
3881d4b38e0Srsmaeda 	case DRCTL_MEM_UNCONFIG_REQUEST:
3891d4b38e0Srsmaeda 	case DRCTL_MEM_UNCONFIG_NOTIFY:
3901d4b38e0Srsmaeda 		drd_err("memory DR operations not supported yet");
3911d4b38e0Srsmaeda 		DRD_DOOR_RETURN_ERR();
3921d4b38e0Srsmaeda 		break;
3931d4b38e0Srsmaeda 
3941d4b38e0Srsmaeda 	case DRCTL_IO_CONFIG_REQUEST:
395*8fea755aSjm22469 		(*drd_backend->io_config_request)(rsrcs, nrsrc);
396*8fea755aSjm22469 		break;
397*8fea755aSjm22469 
3981d4b38e0Srsmaeda 	case DRCTL_IO_CONFIG_NOTIFY:
399*8fea755aSjm22469 		(*drd_backend->io_config_notify)(rsrcs, nrsrc);
400*8fea755aSjm22469 		break;
401*8fea755aSjm22469 
4021d4b38e0Srsmaeda 	case DRCTL_IO_UNCONFIG_REQUEST:
403*8fea755aSjm22469 		(*drd_backend->io_unconfig_request)(rsrcs, nrsrc);
404*8fea755aSjm22469 		break;
405*8fea755aSjm22469 
4061d4b38e0Srsmaeda 	case DRCTL_IO_UNCONFIG_NOTIFY:
407*8fea755aSjm22469 		(*drd_backend->io_unconfig_notify)(rsrcs, nrsrc);
4081d4b38e0Srsmaeda 		break;
4091d4b38e0Srsmaeda 
4101d4b38e0Srsmaeda 	default:
4111d4b38e0Srsmaeda 		drd_err("unknown command: %d", msg->cmd);
4121d4b38e0Srsmaeda 		DRD_DOOR_RETURN_ERR();
4131d4b38e0Srsmaeda 		break;
4141d4b38e0Srsmaeda 	}
4151d4b38e0Srsmaeda 
4161d4b38e0Srsmaeda 	osize = drd_pack_response(rsrcs, nrsrc);
4171d4b38e0Srsmaeda 	if (osize == 0)
4181d4b38e0Srsmaeda 		DRD_DOOR_RETURN_ERR();
4191d4b38e0Srsmaeda 
4201d4b38e0Srsmaeda 	(void) door_return((char *)drd_result, osize, NULL, 0);
4211d4b38e0Srsmaeda }
422