WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] Xen power management daemon patch.

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] Xen power management daemon patch.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 23 Oct 2008 10:50:08 -0700
Delivery-date: Thu, 23 Oct 2008 10:50:07 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1224757045 -3600
# Node ID 635a9691a8a9e9793312dc61184624a6d2e6b285
# Parent  10d338e5f741f813ea5b3335c405e9a57d55f535
Xen power management daemon patch.

Signed-off-by: Kamala Narasimhan <kamala.narasimhan@xxxxxxxxxx>
---
 tools/Makefile        |    1 
 tools/xenpmd/Makefile |   15 +
 tools/xenpmd/xenpmd.c |  520 ++++++++++++++++++++++++++++++++++++++++++++++++++
 xenpmd/xenpmd         |    0 
 4 files changed, 536 insertions(+)

diff -r 10d338e5f741 -r 635a9691a8a9 tools/Makefile
--- a/tools/Makefile    Wed Oct 22 16:47:44 2008 +0100
+++ b/tools/Makefile    Thu Oct 23 11:17:25 2008 +0100
@@ -24,6 +24,7 @@ SUBDIRS-$(LIBXENAPI_BINDINGS) += libxen
 SUBDIRS-$(LIBXENAPI_BINDINGS) += libxen
 SUBDIRS-y += fs-back
 SUBDIRS-$(CONFIG_IOEMU) += ioemu-dir
+SUBDIRS-y += xenpmd
 
 # These don't cross-compile
 ifeq ($(XEN_COMPILE_ARCH),$(XEN_TARGET_ARCH))
diff -r 10d338e5f741 -r 635a9691a8a9 tools/xenpmd/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/xenpmd/Makefile     Thu Oct 23 11:17:25 2008 +0100
@@ -0,0 +1,15 @@
+XEN_ROOT=../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+CFLAGS  += -Werror
+CFLAGS  += $(CFLAGS_libxenstore)
+LDFLAGS += $(LDFLAGS_libxenstore)
+
+BIN      = xenpmd
+
+.PHONY: all
+all: $(BIN)
+
+.PHONY: clean
+clean:
+       $(RM) -f $(BIN)
diff -r 10d338e5f741 -r 635a9691a8a9 tools/xenpmd/xenpmd
Binary file tools/xenpmd/xenpmd has changed
diff -r 10d338e5f741 -r 635a9691a8a9 tools/xenpmd/xenpmd.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/xenpmd/xenpmd.c     Thu Oct 23 11:17:25 2008 +0100
@@ -0,0 +1,520 @@
+/*
+ * xenpmd.c
+ *
+ * xen power management daemon - Facilitates power management 
+ * functionality within xen guests.
+ *
+ * Copyright (c) 2008  Kamala Narasimhan 
+ * Copyright (c) 2008  Citrix Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* Xen extended power management support provides HVM guest power management
+ * features beyond S3, S4, S5.  For example, it helps expose system level 
+ * battery status and battery meter information and in future will be extended
+ * to include more power management support.  This extended power management 
+ * support is enabled by setting xen_extended_power_mgmt to 1 or 2 in the HVM
+ * config file.  When set to 2, non-pass through mode is enabled which heavily
+ * relies on this power management daemon to glean battery information from 
+ * dom0 and store it xenstore which would then be queries and used by qemu and 
+ * passed to the guest when appropriate battery ports are read/written to.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <xs.h>
+
+/* #define RUN_STANDALONE */
+#define RUN_IN_SIMULATE_MODE
+
+enum BATTERY_INFO_TYPE {
+    BIF, 
+    BST 
+};
+
+enum BATTERY_PRESENT {
+    NO, 
+    YES 
+};
+
+enum BATTERY_TECHNOLOGY {
+    NON_RECHARGEABLE, 
+    RECHARGEABLE 
+};
+
+struct battery_info {
+    enum BATTERY_PRESENT    present;
+    unsigned long           design_capacity;
+    unsigned long           last_full_capacity;
+    enum BATTERY_TECHNOLOGY battery_technology;
+    unsigned long           design_voltage;
+    unsigned long           design_capacity_warning;
+    unsigned long           design_capacity_low;
+    unsigned long           capacity_granularity_1;
+    unsigned long           capacity_granularity_2;
+    char                    model_number[32];
+    char                    serial_number[32];
+    char                    battery_type[32];
+    char                    oem_info[32];
+};
+
+struct battery_status {
+    enum BATTERY_PRESENT    present;
+    unsigned long           state;
+    unsigned long           present_rate;
+    unsigned long           remaining_capacity;
+    unsigned long           present_voltage;
+};
+
+static struct xs_handle *xs;
+
+#ifdef RUN_IN_SIMULATE_MODE
+    #define BATTERY_DIR_PATH "/tmp/battery"
+    #define BATTERY_INFO_FILE_PATH "/tmp/battery/%s/info" 
+    #define BATTERY_STATE_FILE_PATH "/tmp/battery/%s/state"
+#else
+    #define BATTERY_DIR_PATH "/proc/acpi/battery"
+    #define BATTERY_INFO_FILE_PATH "/proc/acpi/battery/%s/info"
+    #define BATTERY_STATE_FILE_PATH "/proc/acpi/battery/%s/state"
+#endif
+
+FILE *get_next_battery_file(DIR *battery_dir, 
+                            enum BATTERY_INFO_TYPE battery_info_type)
+{
+    FILE *file = 0;
+    struct dirent *dir_entries;
+    char file_name[32];
+    
+    do 
+    {
+        dir_entries = readdir(battery_dir);
+        if ( !dir_entries ) 
+            return 0;
+        if ( strlen(dir_entries->d_name) < 4 )
+            continue;
+        if ( battery_info_type == BIF ) 
+            snprintf(file_name, 32, BATTERY_INFO_FILE_PATH,
+                     dir_entries->d_name);
+        else 
+            snprintf(file_name, 32, BATTERY_STATE_FILE_PATH,
+                     dir_entries->d_name);
+        file = fopen(file_name, "r");
+    } while ( !file );
+
+    return file;
+}
+
+void set_attribute_battery_info(char *attrib_name,
+                                char *attrib_value,
+                                struct battery_info *info)
+{
+    if ( strstr(attrib_name, "present") ) 
+    {
+        if ( strstr(attrib_value, "yes") ) 
+            info->present = YES;
+        return;
+    }
+
+    if ( strstr(attrib_name, "design capacity warning") ) 
+    {
+        info->design_capacity_warning = strtoull(attrib_value, NULL, 10);
+        return;
+    }
+
+    if ( strstr(attrib_name, "design capacity low") ) 
+    {
+        info->design_capacity_low = strtoull(attrib_value, NULL, 10);
+        return;
+    }
+
+    if ( strstr(attrib_name, "design capacity") ) 
+    { 
+        info->design_capacity = strtoull(attrib_value, NULL, 10);
+        return;
+    }
+
+    if ( strstr(attrib_name, "last full capacity") ) 
+    {
+        info->last_full_capacity = strtoull(attrib_value, NULL, 10);
+        return;
+    }
+
+    if ( strstr(attrib_name, "design voltage") ) 
+    {
+        info->design_voltage = strtoull(attrib_value, NULL, 10);
+        return;
+    }
+
+    if ( strstr(attrib_name, "capacity granularity 1") ) 
+    {
+        info->capacity_granularity_1 = strtoull(attrib_value, NULL, 10);
+        return;
+    }
+
+    if ( strstr(attrib_name, "capacity granularity 2") ) 
+    {
+        info->capacity_granularity_2 = strtoull(attrib_value, NULL, 10);
+        return;
+    }
+
+    if ( strstr(attrib_name, "battery technology") ) 
+    {
+        if ( strncmp(attrib_value, "rechargeable",
+                     strlen("rechargeable")) == 0 ) 
+            info->battery_technology = RECHARGEABLE;
+        else 
+            info->battery_technology = NON_RECHARGEABLE;
+        return;
+    }
+
+    if ( strstr(attrib_name, "model number") ) 
+    {
+        strncpy(info->model_number, attrib_value, 32);
+        return;
+    }
+
+    if ( strstr(attrib_name, "serial number") ) 
+    {
+        strncpy(info->serial_number, attrib_value, 32);
+        return;
+    }
+
+    if ( strstr(attrib_name, "battery type") ) 
+    {
+        strncpy(info->battery_type, attrib_value, 32);
+        return;
+    }
+
+    if ( strstr(attrib_name, "OEM info") ) 
+    {
+        strncpy(info->oem_info, attrib_value, 32);
+        return;
+    }
+
+    return;
+}
+
+void set_attribute_battery_status(char *attrib_name, 
+                                  char *attrib_value,
+                                  struct battery_status *status)
+{
+    if ( strstr(attrib_name, "charging state") ) 
+    {
+        /* Check this, below is half baked */
+        if ( strstr(attrib_value, "charged") ) 
+            status->state = 0;
+        else 
+            status->state = 1;
+        return;
+    }
+
+    if ( strstr(attrib_name, "present rate") ) 
+    {
+        status->present_rate = strtoull(attrib_value, NULL, 10);
+        return;
+    }
+
+    if ( strstr(attrib_name, "remaining capacity") ) 
+    {
+        status->remaining_capacity = strtoull(attrib_value, NULL, 10);
+        return;
+    }
+
+    if ( strstr(attrib_name, "present voltage") ) 
+    {
+        status->present_voltage = strtoull(attrib_value, NULL, 10);
+        return;
+    }
+
+    if ( strstr(attrib_name, "present") ) 
+    {
+        if ( strstr(attrib_value, "yes") ) 
+            status->present = YES;
+        return;
+    }
+}
+
+void parse_battery_info_or_status(char *line_info,
+                                  enum BATTERY_INFO_TYPE type,
+                                  void *info_or_status)
+{
+    char attrib_name[128];
+    char attrib_value[64];
+    char *delimiter;
+    unsigned long length;
+
+    length = strlen(line_info);
+    delimiter = (char *) strchr( line_info, ':');
+    if ( (!delimiter) || (delimiter == line_info) ||
+         (delimiter == line_info + length) ) 
+        return;
+
+    strncpy(attrib_name, line_info, delimiter-line_info);
+    while ( *(delimiter+1) == ' ' ) 
+    {
+        delimiter++;
+        if ( delimiter+1 == line_info + length)
+            return;
+    }
+    strncpy(attrib_value, delimiter+1, 
+            (unsigned long)line_info + length -(unsigned long)delimiter); 
+    
+    if ( type == BIF ) 
+        set_attribute_battery_info(attrib_name, attrib_value,
+                                   (struct battery_info *)info_or_status);
+    else 
+        set_attribute_battery_status(attrib_name, attrib_value,
+                                     (struct battery_status *)info_or_status);
+
+    return;
+}
+
+int get_next_battery_info_or_status(DIR *battery_dir,
+                                    enum BATTERY_INFO_TYPE type,
+                                    void *info_or_status)
+{
+    FILE *file;
+    char line_info[256];
+
+    if  ( !info_or_status )
+        return 0;
+
+    memset(line_info, 0, 256);
+    if (type == BIF) 
+        memset(info_or_status, 0, sizeof(struct battery_info));
+    else 
+        memset(info_or_status, 0, sizeof(struct battery_status));
+
+    file = get_next_battery_file(battery_dir, type);
+    if ( !file )
+        return 0;
+
+    while ( fgets(line_info, 1024, file) != NULL ) 
+    {
+        parse_battery_info_or_status(line_info, type, info_or_status);
+        memset(line_info, 0, 256);
+    }
+
+    fclose(file);
+    return 1;
+}
+
+#ifdef RUN_STANDALONE
+void print_battery_info(struct battery_info *info)
+{
+    printf("present:                %d\n", info->present);
+    printf("design capacity:        %d\n", info->design_capacity);
+    printf("last full capacity:     %d\n", info->last_full_capacity);
+    printf("battery technology:     %d\n", info->battery_technology);
+    printf("design voltage:         %d\n", info->design_voltage);
+    printf("design capacity warning:%d\n", info->design_capacity_warning);
+    printf("design capacity low:    %d\n", info->design_capacity_low);
+    printf("capacity granularity 1: %d\n", info->capacity_granularity_1);
+    printf("capacity granularity 2: %d\n", info->capacity_granularity_2);
+    printf("model number:           %s\n", info->model_number);
+    printf("serial number:          %s\n", info->serial_number);
+    printf("battery type:           %s\n", info->battery_type);
+    printf("OEM info:               %s\n", info->oem_info);
+}
+#endif /*RUN_STANDALONE*/
+
+void write_ulong_lsb_first(char *temp_val, unsigned long val)
+{
+    snprintf(temp_val, 9, "%02x%02x%02x%02x", (unsigned int)val & 0xff, 
+    (unsigned int)(val & 0xff00) >> 8, (unsigned int)(val & 0xff0000) >> 16, 
+    (unsigned int)(val & 0xff000000) >> 24);
+}
+
+void write_battery_info_to_xenstore(struct battery_info *info)
+{
+    char val[1024], string_info[256];
+
+    xs_mkdir(xs, XBT_NULL, "/pm");
+   
+    memset(val, 0, 1024);
+    memset(string_info, 0, 256);
+    /* write 9 dwords (so 9*4) + length of 4 strings + 4 null terminators */
+    snprintf(val, 3, "%02x", 
+             (unsigned int)(9*4 +
+                            strlen(info->model_number) +
+                            strlen(info->serial_number) +
+                            strlen(info->battery_type) +
+                            strlen(info->oem_info) + 4));
+    write_ulong_lsb_first(val+2, info->present);
+    write_ulong_lsb_first(val+10, info->design_capacity);
+    write_ulong_lsb_first(val+18, info->last_full_capacity);
+    write_ulong_lsb_first(val+26, info->battery_technology);
+    write_ulong_lsb_first(val+34, info->design_voltage);
+    write_ulong_lsb_first(val+42, info->design_capacity_warning);
+    write_ulong_lsb_first(val+50, info->design_capacity_low);
+    write_ulong_lsb_first(val+58, info->capacity_granularity_1);
+    write_ulong_lsb_first(val+66, info->capacity_granularity_2);
+
+    snprintf(string_info, 256, "%02x%s%02x%s%02x%s%02x%s", 
+             (unsigned int)strlen(info->model_number), info->model_number,
+             (unsigned int)strlen(info->serial_number), info->serial_number,
+             (unsigned int)strlen(info->battery_type), info->battery_type,
+             (unsigned int)strlen(info->oem_info), info->oem_info);
+    strncat(val+73, string_info, 1024);
+    xs_write(xs, XBT_NULL, "/pm/bif", 
+             val, 73+8+strlen(info->model_number)+strlen(info->serial_number)+
+             strlen(info->battery_type)+strlen(info->oem_info)+1);
+}
+
+int write_one_time_battery_info(void)
+{
+    DIR *dir;
+    int ret = 0;
+    struct battery_info info;
+    
+    dir = opendir(BATTERY_DIR_PATH);
+    if ( !dir )
+        return 0;
+
+    while ( get_next_battery_info_or_status(dir, BIF, (void *)&info) ) 
+    {
+#ifdef RUN_STANDALONE
+        print_battery_info(&info);
+#endif
+        if ( info.present == YES ) 
+        {
+            write_battery_info_to_xenstore(&info);
+            ret = 1;
+            break; /* rethink this... */
+        }
+    }
+
+    closedir(dir);
+    return ret;
+}
+
+#ifdef RUN_STANDALONE
+void print_battery_status(struct battery_status *status)
+{
+    printf("present:                     %d\n", status->present);
+    printf("Battery state                %d\n", status->state);
+    printf("Battery present rate         %d\n", status->present_rate);
+    printf("Battery remining capacity    %d\n", status->remaining_capacity);
+    printf("Battery present voltage      %d\n", status->present_voltage);
+}
+#endif /*RUN_STANDALONE*/
+
+void write_battery_status_to_xenstore(struct battery_status *status)
+{
+    char val[35];
+
+    xs_mkdir(xs, XBT_NULL, "/pm");
+
+    memset(val, 0, 35);
+    snprintf(val, 3, "%02x", 16);
+    write_ulong_lsb_first(val+2, status->state);
+    write_ulong_lsb_first(val+10, status->present_rate);
+    write_ulong_lsb_first(val+18, status->remaining_capacity);
+    write_ulong_lsb_first(val+26, status->present_voltage);
+
+    xs_write(xs, XBT_NULL, "/pm/bst", val, 35);
+}
+
+int wait_for_and_update_battery_status_request(void)
+{
+    DIR *dir;
+    int ret = 0;
+    unsigned int count;
+    struct battery_status status;
+
+    while ( true )
+    {
+        /* KN:@TODO - It is rather inefficient to not cache the file handle.
+         *  Switch to caching file handle. 
+         */
+        dir = opendir(BATTERY_DIR_PATH);
+        if ( !dir )
+            return 0;
+
+        while ( get_next_battery_info_or_status(dir, BST, (void *)&status) ) 
+        {
+#ifdef RUN_STANDALONE
+            print_battery_status(&status);
+#endif
+            if ( status.present == YES ) 
+            {
+                write_battery_status_to_xenstore(&status);
+                ret = 1;
+                /* rethink this; though I have never seen, there might be
+                 * systems out there with more than one battery device 
+                 * present
+                 */
+                break;
+            }
+        }
+        closedir(dir);
+        xs_watch(xs, "/pm/events", "refreshbatterystatus");
+        xs_read_watch(xs, &count); 
+    }
+
+    return ret;
+}
+
+/* Borrowed daemonize from xenstored - Initially written by Stevens. */
+static void daemonize(void)
+{
+    pid_t pid;
+
+    if ( (pid = fork()) < 0 )
+        exit(1);
+
+    if ( pid != 0 )
+        exit(0);
+
+    setsid();
+
+    if ( (pid = fork()) < 0 )
+        exit(1);
+
+    if ( pid != 0 )
+        exit(0);
+
+    if ( chdir("/") == -1 )
+        exit(1);
+
+    umask(0);
+}
+
+int main(int argc, char *argv[])
+{
+#ifndef RUN_STANDALONE
+    daemonize();
+#endif
+    xs = (struct xs_handle *)xs_daemon_open();
+    if ( xs == NULL ) 
+        return -1;
+
+    if ( write_one_time_battery_info() == 0 ) 
+    {
+        xs_daemon_close(xs);
+        return -1;
+    }
+
+    wait_for_and_update_battery_status_request();
+    xs_daemon_close(xs);
+    return 0;
+}
+

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] Xen power management daemon patch., Xen patchbot-unstable <=