MODULE_32 := i386/$(MODULE)
MODULE_64 := amd64/$(MODULE)
-PROG := vmware-memctld
-PROG_32 := i386/$(PROG)
-PROG_64 := amd64/$(PROG)
-
CFLAGS :=
KFLAGS :=
LDFLAGS :=
VMMCTL_64_OBJS := $(addprefix amd64/, $(VMMCTL_OBJS))
VMMCTL_64_OBJS += amd64/backdoorGcc64.o
-##
-## Objects needed to build the vmware-memctld program
-##
-VMMCTLD_OBJS := vmmemctld.o
-
-VMMCTLD_32_OBJS := $(addprefix i386/, $(VMMCTLD_OBJS))
-VMMCTLD_64_OBJS := $(addprefix amd64/, $(VMMCTLD_OBJS))
-
-
ifeq ($(shell echo "$(VM_UNAME)" | cut -c-4),5.9)
# Solaris 9
SUPPORTED := 1
MODULES := $(MODULE_32)
-PROGS := $(PROG_32)
INSTALL := install32
CFLAGS += -D__STDC__=0 -DSOL9
# Solaris 10
SUPPORTED := 1
MODULES := $(MODULE_32) $(MODULE_64)
-PROGS := $(PROG_32) $(PROG_64)
INSTALL := install32 install64
CFLAGS += -DSOL10
KFLAGS += -ffreestanding
# Solaris 11
SUPPORTED := 1
MODULES := $(MODULE_32) $(MODULE_64)
-PROGS := $(PROG_32) $(PROG_64)
INSTALL := install32 install64
CFLAGS += -DSOL11
KFLAGS += -ffreestanding
LDFLAGS_64 += -64
endif
-all: prepare_dirs $(MODULES) $(PROGS)
+all: prepare_dirs $(MODULES)
prepare_dirs:
@echo "Creating build directories"
@echo "Compiling $(<F)"
$(CC) $(CFLAGS_64) $(KFLAGS_64) -c $< -o $@
-$(PROG_32): $(VMMCTLD_32_OBJS)
- @echo "Linking $@"
- $(CC) -m32 $(VMMCTLD_32_OBJS) -o $@
-
-$(VMMCTLD_32_OBJS): i386/%.o: %.c
- @echo "Compiling $(<F)"
- $(CC) $(CFLAGS_32) -c $< -o $@
-
-$(PROG_64): $(VMMCTLD_64_OBJS)
- @echo "Linking $@"
- $(CC) -m64 $(VMMCTLD_64_OBJS) $< -o $@
-
-$(VMMCTLD_64_OBJS): amd64/%.o: %.c
- @echo "Compiling $(<F)"
- $(CC) $(CFLAGS_64) -c $< -o $@
-
clean:
@echo "Cleaning directories"
- @rm -rf $(MODULE_32) $(PROG_32) $(VMMCTL_32_OBJS) $(VMMCTLD_32_OBJS) i386
- @rm -rf $(MODULE_64) $(PROG_64) $(VMMCTL_64_OBJS) $(VMMCTLD_64_OBJS) amd64
+ @rm -rf $(MODULE_32) $(VMMCTL_32_OBJS) i386
+ @rm -rf $(MODULE_64) $(VMMCTL_64_OBJS) amd64
install32:
cp $(MODULE_32) /kernel/drv/
chmod 755 /kernel/drv/$(MODULE)
- mkdir -p /usr/sbin/i86
- cp $(PROG_32) /usr/sbin/i86/$(PROG)
- chmod 755 /usr/sbin/i86/$(PROG)
- ln -f /usr/lib/isaexec /usr/sbin/$(PROG)
install64:
chmod 755 /kernel/drv/$(MODULE)
cp $(MODULE_64) /kernel/drv/amd64
- mkdir -p /usr/sbin/amd64
- cp $(PROG_64) /usr/sbin/amd64/$(PROG)
- chmod 755 /usr/sbin/amd64/$(PROG)
install: $(INSTALL)
- cp vmmemctl.conf /kernel/drv/
- chmod 755 /kernel/drv/vmmemctl.conf
- grep $(MODULE) /etc/name_to_major > /dev/null 2>&1; \
- if [ ! $$? = 0 ]; then \
- /usr/sbin/add_drv $(MODULE); \
- fi
#include <sys/kstat.h>
#include <sys/id_space.h>
#include <sys/vnode.h>
-#include <sys/taskq.h>
+#include <sys/proc.h>
#include <sys/disp.h>
#include <sys/ksynch.h>
#include "vmballoon.h"
#include "balloon_def.h"
#include "vmballoon_kstats.h"
-#include "vmmemctl.h"
#include "buildNumber.h"
#if defined(SOL9)
typedef struct {
timeout_id_t id;
+ /* Worker thread ID */
+ kt_did_t thread_id;
+
/* termination flag */
volatile int stop;
*/
static os_state global_state;
-static dev_info_t *vmmemctl_dip; /* only one instance */
/*
*-----------------------------------------------------------------------------
*/
-static int
-os_worker(void)
+static void
+os_worker(os_timer *t) // IN
{
- os_timer *t = &global_state.timer;
clock_t timeout;
mutex_enter(&t->lock);
+
while (!t->stop) {
- /* invoke registered handler */
mutex_exit(&t->lock);
+
+ /* invoke registered handler */
(void) (*(t->handler))(t->data);
- mutex_enter(&t->lock);
+ mutex_enter(&t->lock);
/* check again whether we should stop */
if (t->stop)
- break;
+ break;
/* wait for timeout */
(void) drv_getparm(LBOLT, &timeout);
timeout += t->period;
- if (cv_timedwait_sig(&t->cv, &t->lock, timeout) == 0) {
- mutex_exit(&t->lock);
- return EINTR; /* took a signal, return to user level */
- }
+ cv_timedwait_sig(&t->cv, &t->lock, timeout);
}
+
mutex_exit(&t->lock);
- ASSERT(t->stop);
- return 0; /* normal termination */
+
+ thread_exit();
}
void *clientData) // IN
{
os_timer *t = &global_state.timer;
+ kthread_t *tp;
/* setup the timer structure */
t->id = 0;
/* start the timer */
t->stop = 0;
+ /*
+ * All Solaris drivers that I checked assume that thread_create() will
+ * succeed, let's follow the suit.
+ */
+ tp = thread_create(NULL, 0, os_worker, (void *)t, 0, &p0, TS_RUN, minclsyspri);
+ t->thread_id = tp->t_did;
+
return TRUE;
}
mutex_enter(&t->lock);
- /* set termination flag */
+ /* Set termination flag. */
t->stop = 1;
- /* wake up worker thread so it can exit */
+ /* Wake up worker thread so it can exit. */
cv_signal(&t->cv);
mutex_exit(&t->lock);
+
+ /* Wait for the worker thread to complete. */
+ if (t->thread_id != 0) {
+ thread_join(t->thread_id);
+ t->thread_id = 0;
+ }
}
}
-/*
- * Device configuration entry points
- */
-
-
-static int
-vmmemctl_attach(dev_info_t *dip, // IN
- ddi_attach_cmd_t cmd) // IN
-{
- switch (cmd) {
- case DDI_ATTACH:
- vmmemctl_dip = dip;
- if (ddi_create_minor_node(dip, "0", S_IFCHR, ddi_get_instance(dip),
- DDI_PSEUDO,0) != DDI_SUCCESS) {
- return DDI_FAILURE;
- } else {
- return DDI_SUCCESS;
- }
- default:
- return DDI_FAILURE;
- }
-}
-
-
-static int
-vmmemctl_detach(dev_info_t *dip, // IN
- ddi_detach_cmd_t cmd) // IN
-{
- switch (cmd) {
- case DDI_DETACH:
- vmmemctl_dip = 0;
- ddi_remove_minor_node(dip, NULL);
- return DDI_SUCCESS;
- default:
- return DDI_FAILURE;
- }
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * vmmemctl_ioctl --
- *
- * Commands used by the user level daemon to control the driver.
- * Since the daemon is single threaded, we use a simple monitor to
- * make sure that only one thread is executing here at a time.
- *
- * Results:
- * On success: 0
- * On failure: error code
- *
- * Side effects:
- * None
- *
- *-----------------------------------------------------------------------------
- */
-
-static int
-vmmemctl_ioctl(dev_t dev, // IN: Unused
- int cmd, // IN
- intptr_t arg, // IN: Unused
- int mode, // IN: Unused
- cred_t *cred, // IN
- int *rvalp) // IN: Unused
-{
- int error = 0;
- static int busy = 0; /* set when a thread is in this function */
- static kmutex_t lock; /* lock to protect busy count */
-
- if (drv_priv(cred) != 0)
- return EPERM;
-
- mutex_enter(&lock);
- if (busy) {
- /*
- * Only one thread at a time.
- */
- mutex_exit(&lock);
- return EBUSY;
- }
- busy = 1;
- mutex_exit(&lock);
-
- switch (cmd) {
- case VMMIOCWORK:
- error = os_worker();
- break;
-
- default:
- error = ENXIO;
- break;
- }
-
- mutex_enter(&lock);
- ASSERT(busy);
- busy = 0;
- mutex_exit(&lock);
-
- return error;
-}
-
/*
* Module linkage
*/
-static struct cb_ops vmmemctl_cb_ops = {
- nulldev, /* open */
- nulldev, /* close */
- nodev, /* strategy */
- nodev, /* print */
- nodev, /* dump */
- nodev, /* read */
- nodev, /* write */
- vmmemctl_ioctl,
- nodev, /* devmap */
- nodev, /* mmap */
- nodev, /* segmap */
- nochpoll, /* poll */
- ddi_prop_op, /* prop_op */
- 0, /* streamtab */
- D_NEW | D_MP
-};
-
-static struct dev_ops vmmemctl_dev_ops = {
- DEVO_REV,
- 0,
- ddi_no_info, /* getinfo */
- nulldev, /* identify */
- nulldev, /* probe */
- vmmemctl_attach,
- vmmemctl_detach,
- nodev, /* reset */
- &vmmemctl_cb_ops, /* cb_ops */
- NULL, /* bus_ops */
- nodev /* power */
-};
-
static struct modldrv vmmodldrv = {
- &mod_driverops,
+ &mod_miscops,
"VMware Memory Control b" BUILD_NUMBER_NUMERIC_STRING,
- &vmmemctl_dev_ops
};
static struct modlinkage vmmodlinkage = {
MODREV_1,
- {&vmmodldrv, NULL}
+ { &vmmodldrv, NULL }
};
+++ /dev/null
-#
-# Copyright 2005-2008 VMware, Inc. All rights reserved.
-#
-
-name="vmmemctl" parent="pseudo" instance=0;
+++ /dev/null
-/*********************************************************
- * Copyright (C) 2005 VMware, Inc. All rights reserved.
- *
- * The contents of this file are subject to the terms of the Common
- * Development and Distribution License (the "License") version 1.0
- * and no later version. You may not use this file except in
- * compliance with the License.
- *
- * You can obtain a copy of the License at
- * http://www.opensource.org/licenses/cddl1.php
- *
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- *********************************************************/
-
-/*
- * vmmemctl.h --
- *
- * Definitions for the interface between vmmemctl daemon (vmmemctld)
- * and driver.
- */
-
-#ifndef _VMMEMCTL_H
-#define _VMMEMCTL_H
-
-#define VMMIOC (0xba << 8) /* prefix */
-#define VMMIOCWORK (VMMIOC | 0x01)
-
-#endif /* _VMMEMCTL_H */
+++ /dev/null
-/*********************************************************
- * Copyright (C) 2005 VMware, Inc. All rights reserved.
- *
- * The contents of this file are subject to the terms of the Common
- * Development and Distribution License (the "License") version 1.0
- * and no later version. You may not use this file except in
- * compliance with the License.
- *
- * You can obtain a copy of the License at
- * http://www.opensource.org/licenses/cddl1.php
- *
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- *********************************************************/
-
-/*
- * vmmemctld.c --
- *
- * Simple daemon that provides a worker thread for the vmmemctl
- * driver. Note that opening the device node causes the driver
- * to load, and the driver can't be unloaded as long as we're
- * running inside it.
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include "vm_basic_types.h"
-#include "vmmemctl.h"
-
-static const char *pname;
-static const char dpath[] = "/devices/pseudo/vmmemctl@0:0";
-
-static void myperror(const char *str)
-{
- fprintf(stderr, "%s: ", pname);
- perror(str);
-}
-
-int main(int argc, char **argv)
-{
- int err;
- pid_t pid;
- int fd;
-
- pname = argv[0];
-
- /*
- * Basic sanity checks
- */
- if (chdir("/") < 0) {
- myperror("chdir");
- return 1;
- }
-
- /*
- * Run in background
- */
- pid = fork();
- if (pid < 0) {
- myperror("fork");
- return 1;
- }
- if (pid != 0) {
- /*
- * Parent writes pidfile if specified.
- */
- if (argc >= 3 && strcmp(argv[1], "--background") == 0) {
- int fd;
- int len;
- char buf[64];
-
- (void) unlink(argv[2]);
-
- fd = open(argv[2], O_CREAT | O_EXCL | O_WRONLY);
- if (fd < 0) {
- myperror("open");
- return 1;
- }
-
- len = snprintf(buf, sizeof buf, "%"FMTPID"\n", pid);
- if (len >= sizeof buf) {
- /* String was truncated */
- myperror("snprintf");
- close(fd);
- return 1;
- }
-
- if (write(fd, buf, len) != len) {
- myperror("write");
- close(fd);
- return 1;
- }
-
- if (close(fd) != 0) {
- myperror("close");
- return 1;
- }
- }
-
- return 0;
- }
-
- /*
- * Clean up file descriptors and detach from controlling tty.
- */
- closefrom(0);
- (void) open("/dev/null", O_RDONLY);
- (void) open("/dev/null", O_WRONLY);
- (void) dup(1);
- (void) setsid();
-
- /*
- * Call into the driver to do work.
- */
- if ((fd = open(dpath, O_RDWR)) == -1) {
- myperror("open");
- return 1;
- }
-
- /*
- * If ioctl returns EINTR, we were interrupted by a non-fatal signal.
- * Call back into the driver to continue working.
- */
- while ((err = ioctl(fd, VMMIOCWORK, 0)) == EINTR)
- ;
-
- if (err != 0) {
- myperror("ioctl");
- return 1;
- }
-
- /*
- * We've been told to exit cleanly.
- */
- (void) close(fd);
- return 0;
-}