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] merge with xen-unstable.hg

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] merge with xen-unstable.hg
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 17 Sep 2008 09:50:36 -0700
Delivery-date: Wed, 17 Sep 2008 09:52:48 -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 Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
# Date 1221567930 -32400
# Node ID 4a381ddc764a635e9242686ef8cefb5af363c873
# Parent  ec8eaab557d867dca3e8cbb3e0384d797929102a
# Parent  3eb7a0cfffc20146c1676b001acbd86b449dc58f
merge with xen-unstable.hg
---
 Config.mk                                    |   16 
 Makefile                                     |    7 
 stubdom/Makefile                             |   53 +-
 tools/Makefile                               |    9 
 tools/python/xen/util/xsm/dummy/dummy.py     |    3 
 xen/arch/x86/Makefile                        |    2 
 xen/arch/x86/acpi/cpufreq/cpufreq.c          |  287 ++++++++------
 xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c |    7 
 xen/arch/x86/acpi/cpufreq/powernow.c         |   10 
 xen/arch/x86/acpi/cpufreq/utility.c          |  186 ++++-----
 xen/arch/x86/acpi/pmstat.c                   |    2 
 xen/arch/x86/acpi/power.c                    |    6 
 xen/arch/x86/domain.c                        |    6 
 xen/arch/x86/microcode.c                     |  541 ++++++---------------------
 xen/arch/x86/microcode_amd.c                 |  371 ++++++++++++++++++
 xen/arch/x86/microcode_intel.c               |  370 ++++++++++++++++++
 xen/arch/x86/mm/shadow/common.c              |   21 -
 xen/arch/x86/mm/shadow/multi.c               |    3 
 xen/arch/x86/platform_hypercall.c            |   39 +
 xen/arch/x86/smpboot.c                       |    5 
 xen/common/gdbstub.c                         |   15 
 xen/drivers/char/console.c                   |   14 
 xen/drivers/char/ns16550.c                   |   34 +
 xen/drivers/char/serial.c                    |   10 
 xen/drivers/passthrough/vtd/iommu.c          |    1 
 xen/include/acpi/cpufreq/cpufreq.h           |   74 +++
 xen/include/acpi/cpufreq/processor_perf.h    |   19 
 xen/include/asm-x86/microcode.h              |   93 ++++
 xen/include/asm-x86/msr-index.h              |    4 
 xen/include/asm-x86/processor.h              |   35 -
 xen/include/public/platform.h                |    2 
 31 files changed, 1500 insertions(+), 745 deletions(-)

diff -r ec8eaab557d8 -r 4a381ddc764a Config.mk
--- a/Config.mk Fri Sep 12 14:47:40 2008 +0900
+++ b/Config.mk Tue Sep 16 21:25:30 2008 +0900
@@ -54,6 +54,22 @@ define cc-ver-check-closure
     endif
 endef
 
+define absolutify_xen_root
+    case "$(XEN_ROOT)" in                                          \
+    /*) XEN_ROOT=$(XEN_ROOT) ;;                                    \
+    *)  xen_root_lhs=`pwd`;                                        \
+        xen_root_rhs=$(XEN_ROOT)/;                                 \
+        while [ "x$${xen_root_rhs#../}" != "x$$xen_root_rhs" ]; do \
+            xen_root_rhs="$${xen_root_rhs#../}";                   \
+            xen_root_rhs="$${xen_root_rhs#/}";                     \
+            xen_root_rhs="$${xen_root_rhs#/}";                     \
+            xen_root_lhs="$${xen_root_lhs%/*}";                    \
+        done;                                                      \
+        XEN_ROOT="$$xen_root_lhs/$$xen_root_rhs" ;;                \
+    esac;                                                          \
+    export XEN_ROOT
+endef
+
 ifeq ($(debug),y)
 CFLAGS += -g
 endif
diff -r ec8eaab557d8 -r 4a381ddc764a Makefile
--- a/Makefile  Fri Sep 12 14:47:40 2008 +0900
+++ b/Makefile  Tue Sep 16 21:25:30 2008 +0900
@@ -64,7 +64,7 @@ install-xen:
        $(MAKE) -C xen install
 
 .PHONY: install-tools
-install-tools:
+install-tools: tools/ioemu-dir
        $(MAKE) -C tools install
 
 .PHONY: install-kernels
@@ -72,11 +72,14 @@ install-kernels:
        for i in $(XKERNELS) ; do $(MAKE) $$i-install || exit 1; done
 
 .PHONY: install-stubdom
-install-stubdom:
+install-stubdom: tools/ioemu-dir
        $(MAKE) -C stubdom install
 ifeq (x86_64,$(XEN_TARGET_ARCH))
        XEN_TARGET_ARCH=x86_32 $(MAKE) -C stubdom install-grub
 endif
+
+tools/ioemu-dir:
+       make -C tools ioemu-dir-find
 
 .PHONY: install-docs
 install-docs:
diff -r ec8eaab557d8 -r 4a381ddc764a stubdom/Makefile
--- a/stubdom/Makefile  Fri Sep 12 14:47:40 2008 +0900
+++ b/stubdom/Makefile  Tue Sep 16 21:25:30 2008 +0900
@@ -6,8 +6,6 @@ export stubdom=y
 export stubdom=y
 export debug=y
 include $(XEN_ROOT)/Config.mk
-
-override CONFIG_QEMU=ioemu
 
 IOEMU_OPTIONS=--disable-sdl --disable-opengl --disable-vnc-tls 
--disable-brlapi --disable-kqemu
 ZLIB_URL?=http://www.zlib.net
@@ -59,8 +57,8 @@ TARGET_CPPFLAGS += -isystem $(CURDIR)/$(
 TARGET_CPPFLAGS += -isystem $(CURDIR)/$(MINI_OS)/include/posix
 TARGET_CPPFLAGS += -isystem $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/include
 TARGET_CPPFLAGS += -isystem $(GCC_INSTALL)include
-TARGET_CPPFLAGS += -isystem $(CURDIR)/lwip/src/include
-TARGET_CPPFLAGS += -isystem $(CURDIR)/lwip/src/include/ipv4
+TARGET_CPPFLAGS += -isystem $(CURDIR)/lwip-$(XEN_TARGET_ARCH)/src/include
+TARGET_CPPFLAGS += -isystem $(CURDIR)/lwip-$(XEN_TARGET_ARCH)/src/include/ipv4
 TARGET_CPPFLAGS += -I$(CURDIR)/include
 
 TARGET_LDFLAGS += -nostdlib -L$(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/lib
@@ -164,7 +162,29 @@ lwip-$(XEN_TARGET_ARCH): lwip-$(LWIP_VER
 .PHONY: $(CROSS_ROOT)
 $(CROSS_ROOT): cross-newlib cross-zlib cross-libpci
 
-mk-headers-$(XEN_TARGET_ARCH):
+$(XEN_ROOT)/tools/ioemu-dir:
+       make -C $(XEN_ROOT)/tools ioemu-dir-find
+
+ioemu/linkfarm.stamp: $(XEN_ROOT)/tools/ioemu-dir
+       mkdir -p ioemu
+ifeq ($(CONFIG_QEMU),ioemu)
+       [ -h ioemu/Makefile ] || ( cd ioemu && \
+         ln -sf ../$(XEN_ROOT)/tools/ioemu/* .)
+else
+       set -e;                                                                 
\
+       $(absolutify_xen_root);                                                 
\
+       cd ioemu;                                                               
\
+       src="$$XEN_ROOT/tools/ioemu-dir"; export src;                           
\
+       (cd $$src && find * -type d -print) | xargs mkdir -p;                   
\
+       (cd $$src && find *     ! -type l  -type f  $(addprefix ! -name ,       
\
+                       '*.[oda1]' 'config-*' config.mak qemu-dm qemu-img-xen   
\
+                       '*.html' '*.pod'                                        
\
+                       )) |                                                    
\
+           while read f; do rm -f "$$f"; ln -s "$$src/$$f" "$$f"; done
+endif
+       touch ioemu/linkfarm.stamp
+
+mk-headers-$(XEN_TARGET_ARCH): ioemu/linkfarm.stamp
        mkdir -p include/xen && \
           ln -sf $(addprefix ../../,$(wildcard 
$(XEN_ROOT)/xen/include/public/*.h)) include/xen && \
           ln -sf $(addprefix ../../$(XEN_ROOT)/xen/include/public/,arch-ia64 
arch-x86 hvm io xsm) include/xen && \
@@ -183,22 +203,6 @@ mk-headers-$(XEN_TARGET_ARCH):
          ln -sf ../$(XEN_ROOT)/tools/libxc/$(XEN_TARGET_ARCH)/*.c . && \
          ln -sf ../$(XEN_ROOT)/tools/libxc/$(XEN_TARGET_ARCH)/*.h . && \
          ln -sf ../$(XEN_ROOT)/tools/libxc/$(XEN_TARGET_ARCH)/Makefile . )
-       mkdir -p ioemu
-ifeq ($(CONFIG_QEMU),ioemu)
-       [ -h ioemu/Makefile ] || ( cd ioemu && \
-         ln -sf ../$(XEN_ROOT)/tools/ioemu/* .)
-else
-       [ -h ioemu/Makefile ] || ( cd ioemu && \
-         ln -sf $(CONFIG_QEMU)/* . && \
-          rm -fr i386-dm && \
-          rm -fr i386-stubdom && \
-          mkdir i386-dm && \
-          mkdir i386-stubdom && \
-         ln -sf $(CONFIG_QEMU)/i386-dm/* i386-dm/ && \
-         ln -sf $(CONFIG_QEMU)/i386-stubdom/* i386-stubdom/ )
-endif
-       [ ! -h ioemu/config-host.h ] || rm -f ioemu/config-host.h
-       [ ! -h ioemu/config-host.mak ] || rm -f ioemu/config-host.mak
        $(MAKE) -C $(MINI_OS) links
        touch mk-headers-$(XEN_TARGET_ARCH)
 
@@ -231,8 +235,9 @@ ifeq ($(CONFIG_QEMU),ioemu)
        CPPFLAGS="$(TARGET_CPPFLAGS)" $(MAKE) -C ioemu 
LWIPDIR=$(CURDIR)/lwip-$(XEN_TARGET_ARCH) TOOLS=
 else
        [ -f ioemu/config-host.mak ] || \
-         ( cd ioemu ; \
-          CONFIG_STUBDOM=yes XEN_ROOT=$(abspath $(XEN_ROOT)) 
XEN_TARGET_ARCH=$(XEN_TARGET_ARCH) CFLAGS="$(TARGET_CFLAGS)" sh ./xen-setup 
--cc=$(CC) --disable-gcc-check $(IOEMU_OPTIONS))
+         ( $(absolutify_xen_root); \
+           cd ioemu ; \
+          CONFIG_STUBDOM=yes XEN_TARGET_ARCH=$(XEN_TARGET_ARCH) 
CFLAGS="$(TARGET_CFLAGS)" sh ./xen-setup --cc=$(CC) --disable-gcc-check 
$(IOEMU_OPTIONS))
        CPPFLAGS= TARGET_CPPFLAGS="$(TARGET_CPPFLAGS)" $(MAKE) -C ioemu 
LWIPDIR=$(CURDIR)/lwip-$(XEN_TARGET_ARCH) TOOLS= CONFIG_STUBDOM=yes
 endif
 
@@ -336,7 +341,7 @@ clean:
        $(MAKE) -C c clean
        rm -fr grub-$(XEN_TARGET_ARCH)
        [ ! -d libxc-$(XEN_TARGET_ARCH) ] || $(MAKE) -C 
libxc-$(XEN_TARGET_ARCH) clean
-       [ ! -d ioemu ] || $(MAKE) -C ioemu clean
+       -[ ! -d ioemu ] || $(MAKE) -C ioemu clean
 
 # clean the cross-compilation result
 .PHONY: crossclean
diff -r ec8eaab557d8 -r 4a381ddc764a tools/Makefile
--- a/tools/Makefile    Fri Sep 12 14:47:40 2008 +0900
+++ b/tools/Makefile    Tue Sep 16 21:25:30 2008 +0900
@@ -93,17 +93,14 @@ ioemu-dir-find:
                ln -sf ioemu-remote ioemu-dir; \
        fi
        set -e; \
-               case "$(XEN_ROOT)" in \
-               /*)     XEN_ROOT=$(XEN_ROOT) ;; \
-               *)      XEN_ROOT=`pwd`/$(XEN_ROOT) ;; \
-               esac; \
-               export XEN_ROOT; \
+               $(absolutify_xen_root); \
                cd ioemu-dir; \
                ./xen-setup $(IOEMU_CONFIGURE_CROSS)
 
 subdir-all-ioemu-dir subdir-install-ioemu-dir: ioemu-dir-find
 
 subdir-clean-ioemu-dir:
-       if test -d ioemu-dir/.; then \
+       set -e; if test -d ioemu-dir/.; then \
+               $(absolutify_xen_root); \
                $(MAKE) -C ioemu-dir clean; \
        fi
diff -r ec8eaab557d8 -r 4a381ddc764a tools/python/xen/util/xsm/dummy/dummy.py
--- a/tools/python/xen/util/xsm/dummy/dummy.py  Fri Sep 12 14:47:40 2008 +0900
+++ b/tools/python/xen/util/xsm/dummy/dummy.py  Tue Sep 16 21:25:30 2008 +0900
@@ -131,3 +131,6 @@ def dump_policy_file():
 
 def get_ssid(domain):
     err("No ssid has been assigned to any domain under xsm dummy module.")
+
+def security_label_to_details(res_label):
+    return ("","","")
diff -r ec8eaab557d8 -r 4a381ddc764a xen/arch/x86/Makefile
--- a/xen/arch/x86/Makefile     Fri Sep 12 14:47:40 2008 +0900
+++ b/xen/arch/x86/Makefile     Tue Sep 16 21:25:30 2008 +0900
@@ -28,6 +28,8 @@ obj-y += ioport_emulate.o
 obj-y += ioport_emulate.o
 obj-y += irq.o
 obj-y += microcode.o
+obj-y += microcode_amd.o
+obj-y += microcode_intel.o
 obj-y += mm.o
 obj-y += mpparse.o
 obj-y += nmi.o
diff -r ec8eaab557d8 -r 4a381ddc764a xen/arch/x86/acpi/cpufreq/cpufreq.c
--- a/xen/arch/x86/acpi/cpufreq/cpufreq.c       Fri Sep 12 14:47:40 2008 +0900
+++ b/xen/arch/x86/acpi/cpufreq/cpufreq.c       Tue Sep 16 21:25:30 2008 +0900
@@ -32,6 +32,7 @@
 #include <xen/errno.h>
 #include <xen/delay.h>
 #include <xen/cpumask.h>
+#include <xen/sched.h>
 #include <xen/timer.h>
 #include <xen/xmalloc.h>
 #include <asm/bug.h>
@@ -44,12 +45,8 @@
 #include <acpi/acpi.h>
 #include <acpi/cpufreq/cpufreq.h>
 
-struct processor_pminfo processor_pminfo[NR_CPUS];
-struct cpufreq_policy xen_px_policy[NR_CPUS];
-
-static cpumask_t *cpufreq_dom_pt;
-static unsigned long *cpufreq_dom_mask;
-static unsigned int cpufreq_dom_max;
+/* TODO: change to link list later as domain number may be sparse */
+static cpumask_t cpufreq_dom_map[NR_CPUS];
 
 enum {
     UNDEFINED_CAPABLE = 0,
@@ -335,7 +332,7 @@ static int acpi_cpufreq_target(struct cp
     if (unlikely(result))
         return -ENODEV;
 
-    online_policy_cpus = policy->cpus;
+    cpus_and(online_policy_cpus, cpu_online_map, policy->cpus);
 
     next_perf_state = data->freq_table[next_state].index;
     if (perf->state == next_perf_state) {
@@ -388,6 +385,20 @@ static int acpi_cpufreq_target(struct cp
     policy->cur = freqs.new;
 
     return result;
+}
+
+static int acpi_cpufreq_verify(struct cpufreq_policy *policy)
+{
+    struct acpi_cpufreq_data *data = drv_data[policy->cpu];
+    struct processor_performance *perf = &processor_pminfo[policy->cpu].perf;
+
+    if (!policy || !data)
+        return -EINVAL;
+
+    cpufreq_verify_within_limits(policy, 0, 
+        perf->states[perf->platform_limit].core_frequency * 1000);
+
+    return cpufreq_frequency_table_verify(policy, data->freq_table);
 }
 
 static unsigned long
@@ -441,14 +452,6 @@ acpi_cpufreq_cpu_init(struct cpufreq_pol
     perf = data->acpi_data;
     policy->shared_type = perf->shared_type;
 
-    /* 
-     * Currently the latest linux (kernel version 2.6.26) 
-     * still has issue when handle the situation _psd HW_ALL coordination.
-     * In Xen hypervisor, we handle _psd HW_ALL coordination in same way as
-     * _psd SW_ALL coordination for the seek of safety.
-     */
-    policy->cpus = perf->shared_cpu_map;
-
     /* capability check */
     if (perf->state_count <= 1) {
         printk("No P-States\n");
@@ -496,6 +499,7 @@ acpi_cpufreq_cpu_init(struct cpufreq_pol
             policy->cpuinfo.transition_latency =
                 perf->states[i].transition_latency * 1000;
     }
+    policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
 
     data->max_freq = perf->states[0].core_frequency * 1000;
     /* table init */
@@ -554,114 +558,173 @@ err_unreg:
     return result;
 }
 
+static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy)
+{
+    struct acpi_cpufreq_data *data = drv_data[policy->cpu];
+
+    if (data) {
+        drv_data[policy->cpu] = NULL;
+        xfree(data->freq_table);
+        xfree(data);
+    }
+
+    return 0;
+}
+
 static struct cpufreq_driver acpi_cpufreq_driver = {
+    .verify = acpi_cpufreq_verify,
     .target = acpi_cpufreq_target,
     .init   = acpi_cpufreq_cpu_init,
+    .exit   = acpi_cpufreq_cpu_exit,
 };
 
-void cpufreq_dom_exit(void)
-{
-    cpufreq_dom_max = 0;
-    if (cpufreq_dom_mask)
-        xfree(cpufreq_dom_mask);
-    if (cpufreq_dom_pt)
-        xfree(cpufreq_dom_pt);
-}
-
-int cpufreq_dom_init(void)
-{
-    unsigned int i;
-
-    cpufreq_dom_max = 0;
-
-    for_each_online_cpu(i) {
-        if (cpufreq_dom_max < processor_pminfo[i].perf.domain_info.domain)
-            cpufreq_dom_max = processor_pminfo[i].perf.domain_info.domain;
-    }
-    cpufreq_dom_max++;
-
-    cpufreq_dom_mask = xmalloc_array(unsigned long,
-                                     BITS_TO_LONGS(cpufreq_dom_max));
-    if (!cpufreq_dom_mask)
-        return -ENOMEM;
-    bitmap_zero(cpufreq_dom_mask, cpufreq_dom_max);
-
-    cpufreq_dom_pt = xmalloc_array(cpumask_t, cpufreq_dom_max);
-    if (!cpufreq_dom_pt)
-        return -ENOMEM;
-    memset(cpufreq_dom_pt, 0, cpufreq_dom_max * sizeof(cpumask_t));
-
-    for_each_online_cpu(i) {
-        __set_bit(processor_pminfo[i].perf.domain_info.domain, 
cpufreq_dom_mask);
-        cpu_set(i, 
cpufreq_dom_pt[processor_pminfo[i].perf.domain_info.domain]);
-    }
-
-    for_each_online_cpu(i)
-        processor_pminfo[i].perf.shared_cpu_map =
-            cpufreq_dom_pt[processor_pminfo[i].perf.domain_info.domain];
+int cpufreq_limit_change(unsigned int cpu)
+{
+    struct processor_performance *perf = &processor_pminfo[cpu].perf;
+    struct cpufreq_policy *data = cpufreq_cpu_policy[cpu];
+    struct cpufreq_policy policy;
+
+    if (!cpu_online(cpu) || !data)
+        return -ENODEV;
+
+    if ((perf->platform_limit < 0) || 
+        (perf->platform_limit >= perf->state_count))
+        return -EINVAL;
+
+    memcpy(&policy, data, sizeof(struct cpufreq_policy)); 
+
+    policy.max =
+        perf->states[perf->platform_limit].core_frequency * 1000;
+
+    return __cpufreq_set_policy(data, &policy);
+}
+
+int cpufreq_add_cpu(unsigned int cpu)
+{
+    int ret = 0;
+    unsigned int firstcpu;
+    unsigned int dom;
+    unsigned int j;
+    struct cpufreq_policy new_policy;
+    struct cpufreq_policy *policy;
+    struct processor_performance *perf = &processor_pminfo[cpu].perf;
+
+    /* to protect the case when Px was not controlled by xen */
+    if (!(perf->init & XEN_PX_INIT))
+        return 0;
+
+    if (cpu_is_offline(cpu) || cpufreq_cpu_policy[cpu])
+        return -EINVAL;
+
+    ret = px_statistic_init(cpu);
+    if (ret)
+        return ret;
+
+    dom = perf->domain_info.domain;
+    if (cpus_weight(cpufreq_dom_map[dom])) {
+        /* share policy with the first cpu since on same boat */
+        firstcpu = first_cpu(cpufreq_dom_map[dom]);
+        policy = cpufreq_cpu_policy[firstcpu];
+
+        cpufreq_cpu_policy[cpu] = policy;
+        cpu_set(cpu, cpufreq_dom_map[dom]);
+        cpu_set(cpu, policy->cpus);
+
+        printk(KERN_EMERG"adding CPU %u\n", cpu);
+    } else {
+        /* for the first cpu, setup policy and do init work */
+        policy = xmalloc(struct cpufreq_policy);
+        if (!policy) {
+            px_statistic_exit(cpu);
+            return -ENOMEM;
+        }
+        memset(policy, 0, sizeof(struct cpufreq_policy));
+
+        cpufreq_cpu_policy[cpu] = policy;
+        cpu_set(cpu, cpufreq_dom_map[dom]);
+        cpu_set(cpu, policy->cpus);
+
+        policy->cpu = cpu;
+        ret = cpufreq_driver->init(policy);
+        if (ret)
+            goto err1;
+        printk(KERN_EMERG"CPU %u initialization completed\n", cpu);
+    }
+
+    /*
+     * After get full cpumap of the coordination domain,
+     * we can safely start gov here.
+     */
+    if (cpus_weight(cpufreq_dom_map[dom]) ==
+        perf->domain_info.num_processors) {
+        memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
+        policy->governor = NULL;
+        ret = __cpufreq_set_policy(policy, &new_policy);
+        if (ret)
+            goto err2;
+    }
 
     return 0;
-}
-
-static int cpufreq_cpu_init(void)
-{
-    int i, ret = 0;
-
-    for_each_online_cpu(i) {
-        xen_px_policy[i].cpu = i;
-
-        ret = px_statistic_init(i);
-        if (ret)
-            return ret;
-
-        ret = acpi_cpufreq_cpu_init(&xen_px_policy[i]);
-        if (ret)
-            return ret;
-    }
+
+err2:
+    cpufreq_driver->exit(policy);
+err1:
+    for_each_cpu_mask(j, cpufreq_dom_map[dom]) {
+        cpufreq_cpu_policy[j] = NULL;
+        px_statistic_exit(j);
+    }
+
+    cpus_clear(cpufreq_dom_map[dom]);
+    xfree(policy);
     return ret;
 }
 
-int cpufreq_dom_dbs(unsigned int event)
-{
-    unsigned int cpu, dom;
+int cpufreq_del_cpu(unsigned int cpu)
+{
+    unsigned int dom;
+    struct cpufreq_policy *policy;
+    struct processor_performance *perf = &processor_pminfo[cpu].perf;
+
+    /* to protect the case when Px was not controlled by xen */
+    if (!(perf->init & XEN_PX_INIT))
+        return 0;
+
+    if (cpu_is_offline(cpu) || !cpufreq_cpu_policy[cpu])
+        return -EINVAL;
+
+    dom = perf->domain_info.domain;
+    policy = cpufreq_cpu_policy[cpu];
+
+    printk(KERN_EMERG"deleting CPU %u\n", cpu);
+
+    /* for the first cpu of the domain, stop gov */
+    if (cpus_weight(cpufreq_dom_map[dom]) ==
+        perf->domain_info.num_processors)
+        __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
+
+    cpufreq_cpu_policy[cpu] = NULL;
+    cpu_clear(cpu, policy->cpus);
+    cpu_clear(cpu, cpufreq_dom_map[dom]);
+    px_statistic_exit(cpu);
+
+    /* for the last cpu of the domain, clean room */
+    /* It's safe here to free freq_table, drv_data and policy */
+    if (!cpus_weight(cpufreq_dom_map[dom])) {
+        cpufreq_driver->exit(policy);
+        xfree(policy);
+    }
+
+    return 0;
+}
+
+static int __init cpufreq_driver_init(void)
+{
     int ret = 0;
 
-    for (dom = 0; dom < cpufreq_dom_max; dom++) {
-        if (!test_bit(dom, cpufreq_dom_mask))
-            continue;
-        cpu = first_cpu(cpufreq_dom_pt[dom]);
-        ret = cpufreq_governor_dbs(&xen_px_policy[cpu], event);
-        if (ret)
-            return ret;
-    }
+    if ((cpufreq_controller == FREQCTL_xen) &&
+        (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL))
+        ret = cpufreq_register_driver(&acpi_cpufreq_driver);
+
     return ret;
 }
-
-int acpi_cpufreq_init(void)
-{
-    int ret = 0;
-    
-    /* setup cpumask of psd dom and shared cpu map of cpu */
-    ret = cpufreq_dom_init();
-    if (ret)
-        goto err;
-
-    /* setup cpufreq driver */
-    cpufreq_driver = &acpi_cpufreq_driver;
-
-    /* setup cpufreq infrastructure */
-    ret = cpufreq_cpu_init();
-    if (ret)
-        goto err;
-
-    /* setup cpufreq dbs according to dom coordiation */
-    ret = cpufreq_dom_dbs(CPUFREQ_GOV_START);
-    if (ret)
-        goto err;
-
-    return ret;
-
-err:
-    cpufreq_dom_exit();
-    return ret;
-}
+__initcall(cpufreq_driver_init);
diff -r ec8eaab557d8 -r 4a381ddc764a 
xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c
--- a/xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c      Fri Sep 12 14:47:40 
2008 +0900
+++ b/xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c      Tue Sep 16 21:25:30 
2008 +0900
@@ -238,4 +238,9 @@ int cpufreq_governor_dbs(struct cpufreq_
         break;
     }
     return 0;
-} 
+}
+
+struct cpufreq_governor cpufreq_gov_dbs = {
+    .name = "ondemand",
+    .governor = cpufreq_governor_dbs,
+};
diff -r ec8eaab557d8 -r 4a381ddc764a xen/arch/x86/acpi/cpufreq/powernow.c
--- a/xen/arch/x86/acpi/cpufreq/powernow.c      Fri Sep 12 14:47:40 2008 +0900
+++ b/xen/arch/x86/acpi/cpufreq/powernow.c      Tue Sep 16 21:25:30 2008 +0900
@@ -50,7 +50,7 @@
 #define MSR_PSTATE_CUR_LIMIT    0xc0010061 /* pstate current limit MSR */
 
 extern struct processor_pminfo processor_pminfo[NR_CPUS];
-extern struct cpufreq_policy xen_px_policy[NR_CPUS];
+extern struct cpufreq_policy *cpufreq_cpu_policy[NR_CPUS];
 
 struct powernow_cpufreq_data {
     struct processor_performance *acpi_data;
@@ -281,9 +281,9 @@ int powernow_cpufreq_init(void)
 
     /* setup cpufreq infrastructure */
     for_each_online_cpu(i) {
-        xen_px_policy[i].cpu = i;
-
-        ret = powernow_cpufreq_cpu_init(&xen_px_policy[i]);
+        cpufreq_cpu_policy[i]->cpu = i;
+
+        ret = powernow_cpufreq_cpu_init(cpufreq_cpu_policy[i]);
         if (ret)
             goto cpufreq_init_out;
     }
@@ -293,7 +293,7 @@ int powernow_cpufreq_init(void)
         if (!cpu_isset(dom, dom_mask))
             continue;
         i = first_cpu(pt[dom]);
-        ret = cpufreq_governor_dbs(&xen_px_policy[i], CPUFREQ_GOV_START);
+        ret = cpufreq_governor_dbs(cpufreq_cpu_policy[i], CPUFREQ_GOV_START);
         if (ret)
             goto cpufreq_init_out;
     }
diff -r ec8eaab557d8 -r 4a381ddc764a xen/arch/x86/acpi/cpufreq/utility.c
--- a/xen/arch/x86/acpi/cpufreq/utility.c       Fri Sep 12 14:47:40 2008 +0900
+++ b/xen/arch/x86/acpi/cpufreq/utility.c       Tue Sep 16 21:25:30 2008 +0900
@@ -31,46 +31,13 @@
 #include <acpi/cpufreq/cpufreq.h>
 #include <public/sysctl.h>
 
-struct cpufreq_driver *cpufreq_driver;
+struct cpufreq_driver   *cpufreq_driver;
+struct processor_pminfo processor_pminfo[NR_CPUS];
+struct cpufreq_policy   *cpufreq_cpu_policy[NR_CPUS];
 
 /*********************************************************************
  *                    Px STATISTIC INFO                              *
  *********************************************************************/
-
-void px_statistic_suspend(void)
-{
-    int cpu;
-    uint64_t now;
-
-    now = NOW();
-
-    for_each_online_cpu(cpu) {
-        struct pm_px *pxpt = &px_statistic_data[cpu];
-        uint64_t total_idle_ns;
-        uint64_t tmp_idle_ns;
-
-        total_idle_ns = get_cpu_idle_time(cpu);
-        tmp_idle_ns = total_idle_ns - pxpt->prev_idle_wall;
-
-        pxpt->u.pt[pxpt->u.cur].residency +=
-                    now - pxpt->prev_state_wall;
-        pxpt->u.pt[pxpt->u.cur].residency -= tmp_idle_ns;
-    }
-}
-
-void px_statistic_resume(void)
-{
-    int cpu;
-    uint64_t now;
-
-    now = NOW();
-
-    for_each_online_cpu(cpu) {
-        struct pm_px *pxpt = &px_statistic_data[cpu];
-        pxpt->prev_state_wall = now;
-        pxpt->prev_idle_wall = get_cpu_idle_time(cpu);
-    }
-}
 
 void px_statistic_update(cpumask_t cpumask, uint8_t from, uint8_t to)
 {
@@ -101,7 +68,7 @@ void px_statistic_update(cpumask_t cpuma
     }
 }
 
-int px_statistic_init(int cpuid)
+int px_statistic_init(unsigned int cpuid)
 {
     uint32_t i, count;
     struct pm_px *pxpt = &px_statistic_data[cpuid];
@@ -123,7 +90,7 @@ int px_statistic_init(int cpuid)
     memset(pxpt->u.pt, 0, count * (sizeof(struct pm_px_val)));
 
     pxpt->u.total = pmpt->perf.state_count;
-    pxpt->u.usable = pmpt->perf.state_count - pmpt->perf.ppc;
+    pxpt->u.usable = pmpt->perf.state_count - pmpt->perf.platform_limit;
 
     for (i=0; i < pmpt->perf.state_count; i++)
         pxpt->u.pt[i].freq = pmpt->perf.states[i].core_frequency;
@@ -134,7 +101,16 @@ int px_statistic_init(int cpuid)
     return 0;
 }
 
-void px_statistic_reset(int cpuid)
+void px_statistic_exit(unsigned int cpuid)
+{
+    struct pm_px *pxpt = &px_statistic_data[cpuid];
+
+    xfree(pxpt->u.trans_pt);
+    xfree(pxpt->u.pt);
+    memset(pxpt, 0, sizeof(struct pm_px));
+}
+
+void px_statistic_reset(unsigned int cpuid)
 {
     uint32_t i, j, count;
     struct pm_px *pxpt = &px_statistic_data[cpuid];
@@ -182,6 +158,38 @@ int cpufreq_frequency_table_cpuinfo(stru
         return -EINVAL;
     else
         return 0;
+}
+
+int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
+                                   struct cpufreq_frequency_table *table)
+{
+    unsigned int next_larger = ~0;
+    unsigned int i;
+    unsigned int count = 0;
+
+    if (!cpu_online(policy->cpu))
+        return -EINVAL;
+
+    cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+                                 policy->cpuinfo.max_freq);
+
+    for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+        unsigned int freq = table[i].frequency;
+        if (freq == CPUFREQ_ENTRY_INVALID)
+            continue;
+        if ((freq >= policy->min) && (freq <= policy->max))
+            count++;
+        else if ((next_larger > freq) && (freq > policy->max))
+            next_larger = freq;
+    }
+
+    if (!count)
+        policy->max = next_larger;
+
+    cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+                                 policy->cpuinfo.max_freq);
+
+    return 0;
 }
 
 int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
@@ -289,57 +297,51 @@ int __cpufreq_driver_getavg(struct cpufr
 
 
 /*********************************************************************
- *               CPUFREQ SUSPEND/RESUME                              *
- *********************************************************************/
-
-void cpufreq_suspend(void)
-{
-    int cpu;
-
-    /* to protect the case when Px was not controlled by xen */
-    for_each_online_cpu(cpu) {
-        struct processor_performance *perf = &processor_pminfo[cpu].perf;
-
-        if (!(perf->init & XEN_PX_INIT))
-            return;
-    }
-
-    cpufreq_dom_dbs(CPUFREQ_GOV_STOP);
-
-    cpufreq_dom_exit();
-
-    px_statistic_suspend();
-}
-
-int cpufreq_resume(void)
-{
-    int cpu, ret = 0;
-
-    /* 1. to protect the case when Px was not controlled by xen */
-    /* 2. set state and resume flag to sync cpu to right state and freq */
-    for_each_online_cpu(cpu) {
-        struct processor_performance *perf = &processor_pminfo[cpu].perf;
-        struct cpufreq_policy *policy = &xen_px_policy[cpu];
-
-        if (!(perf->init & XEN_PX_INIT))
-            goto err;
-        perf->state = 0;
-        policy->resume = 1;
-    }
-
-    px_statistic_resume();
-
-    ret = cpufreq_dom_init();
+ *                 POLICY                                            *
+ *********************************************************************/
+
+/*
+ * data   : current policy.
+ * policy : policy to be set.
+ */
+int __cpufreq_set_policy(struct cpufreq_policy *data,
+                                struct cpufreq_policy *policy)
+{
+    int ret = 0;
+
+    memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo));
+
+    if (policy->min > data->min && policy->min > policy->max)
+        return -EINVAL;
+
+    /* verify the cpu speed can be set within this limit */
+    ret = cpufreq_driver->verify(policy);
     if (ret)
-        goto err;
-
-    ret = cpufreq_dom_dbs(CPUFREQ_GOV_START);
-    if (ret)
-        goto err;
-
-    return ret;
-
-err:
-    cpufreq_dom_exit();
-    return ret;
-}
+        return ret;
+
+    data->min = policy->min;
+    data->max = policy->max;
+
+    if (policy->governor != data->governor) {
+        /* save old, working values */
+        struct cpufreq_governor *old_gov = data->governor;
+
+        /* end old governor */
+        if (data->governor)
+            __cpufreq_governor(data, CPUFREQ_GOV_STOP);
+
+        /* start new governor */
+        data->governor = policy->governor;
+        if (__cpufreq_governor(data, CPUFREQ_GOV_START)) {
+            /* new governor failed, so re-start old one */
+            if (old_gov) {
+                data->governor = old_gov;
+                __cpufreq_governor(data, CPUFREQ_GOV_START);
+            }
+            return -EINVAL;
+        }
+        /* might be a policy change, too, so fall through */
+    }
+
+    return __cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
+}
diff -r ec8eaab557d8 -r 4a381ddc764a xen/arch/x86/acpi/pmstat.c
--- a/xen/arch/x86/acpi/pmstat.c        Fri Sep 12 14:47:40 2008 +0900
+++ b/xen/arch/x86/acpi/pmstat.c        Tue Sep 16 21:25:30 2008 +0900
@@ -78,7 +78,7 @@ int do_get_pm_info(struct xen_sysctl_get
         tmp_idle_ns = total_idle_ns - pxpt->prev_idle_wall;
 
         now = NOW();
-        pxpt->u.usable = pmpt->perf.state_count - pmpt->perf.ppc;
+        pxpt->u.usable = pmpt->perf.state_count - pmpt->perf.platform_limit;
         pxpt->u.pt[pxpt->u.cur].residency += now - pxpt->prev_state_wall;
         pxpt->u.pt[pxpt->u.cur].residency -= tmp_idle_ns;
         pxpt->prev_state_wall = now;
diff -r ec8eaab557d8 -r 4a381ddc764a xen/arch/x86/acpi/power.c
--- a/xen/arch/x86/acpi/power.c Fri Sep 12 14:47:40 2008 +0900
+++ b/xen/arch/x86/acpi/power.c Tue Sep 16 21:25:30 2008 +0900
@@ -133,14 +133,14 @@ static int enter_state(u32 state)
 
     freeze_domains();
 
-    cpufreq_suspend();
-
     disable_nonboot_cpus();
     if ( num_online_cpus() != 1 )
     {
         error = -EBUSY;
         goto enable_cpu;
     }
+
+    cpufreq_del_cpu(0);
 
     hvm_cpu_down();
 
@@ -189,8 +189,8 @@ static int enter_state(u32 state)
         BUG();
 
  enable_cpu:
+    cpufreq_add_cpu(0);
     enable_nonboot_cpus();
-    cpufreq_resume();
     thaw_domains();
     spin_unlock(&pm_lock);
     return error;
diff -r ec8eaab557d8 -r 4a381ddc764a xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Fri Sep 12 14:47:40 2008 +0900
+++ b/xen/arch/x86/domain.c     Tue Sep 16 21:25:30 2008 +0900
@@ -86,6 +86,12 @@ static void default_idle(void)
 
 static void play_dead(void)
 {
+    /*
+     * Flush pending softirqs if any. They can be queued up before this CPU
+     * was taken out of cpu_online_map in __cpu_disable().
+     */
+    do_softirq();
+
     /* This must be done before dead CPU ack */
     cpu_exit_clear();
     hvm_cpu_down();
diff -r ec8eaab557d8 -r 4a381ddc764a xen/arch/x86/microcode.c
--- a/xen/arch/x86/microcode.c  Fri Sep 12 14:47:40 2008 +0900
+++ b/xen/arch/x86/microcode.c  Tue Sep 16 21:25:30 2008 +0900
@@ -1,72 +1,24 @@
 /*
- *     Intel CPU Microcode Update Driver for Linux
+ * Intel CPU Microcode Update Driver for Linux
  *
- *     Copyright (C) 2000-2004 Tigran Aivazian
+ * Copyright (C) 2000-2006 Tigran Aivazian <tigran@xxxxxxxxxxxxxxxxxxxx>
+ *               2006      Shaohua Li <shaohua.li@xxxxxxxxx> *
+ * This driver allows to upgrade microcode on Intel processors
+ * belonging to IA-32 family - PentiumPro, Pentium II,
+ * Pentium III, Xeon, Pentium 4, etc.
  *
- *     This driver allows to upgrade microcode on Intel processors
- *     belonging to IA-32 family - PentiumPro, Pentium II, 
- *     Pentium III, Xeon, Pentium 4, etc.
+ * Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture
+ * Software Developer's Manual
+ * Order Number 253668 or free download from:
  *
- *     Reference: Section 8.10 of Volume III, Intel Pentium 4 Manual, 
- *     Order Number 245472 or free download from:
- *             
- *     http://developer.intel.com/design/pentium4/manuals/245472.htm
+ * http://developer.intel.com/design/pentium4/manuals/253668.htm
  *
- *     For more information, go to http://www.urbanmyth.org/microcode
+ * For more information, go to http://www.urbanmyth.org/microcode
  *
- *     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.
- *
- *     1.0     16 Feb 2000, Tigran Aivazian <tigran@xxxxxxx>
- *             Initial release.
- *     1.01    18 Feb 2000, Tigran Aivazian <tigran@xxxxxxx>
- *             Added read() support + cleanups.
- *     1.02    21 Feb 2000, Tigran Aivazian <tigran@xxxxxxx>
- *             Added 'device trimming' support. open(O_WRONLY) zeroes
- *             and frees the saved copy of applied microcode.
- *     1.03    29 Feb 2000, Tigran Aivazian <tigran@xxxxxxx>
- *             Made to use devfs (/dev/cpu/microcode) + cleanups.
- *     1.04    06 Jun 2000, Simon Trimmer <simon@xxxxxxxxxxx>
- *             Added misc device support (now uses both devfs and misc).
- *             Added MICROCODE_IOCFREE ioctl to clear memory.
- *     1.05    09 Jun 2000, Simon Trimmer <simon@xxxxxxxxxxx>
- *             Messages for error cases (non Intel & no suitable microcode).
- *     1.06    03 Aug 2000, Tigran Aivazian <tigran@xxxxxxxxxxx>
- *             Removed ->release(). Removed exclusive open and status bitmap.
- *             Added microcode_rwsem to serialize read()/write()/ioctl().
- *             Removed global kernel lock usage.
- *     1.07    07 Sep 2000, Tigran Aivazian <tigran@xxxxxxxxxxx>
- *             Write 0 to 0x8B msr and then cpuid before reading revision,
- *             so that it works even if there were no update done by the
- *             BIOS. Otherwise, reading from 0x8B gives junk (which happened
- *             to be 0 on my machine which is why it worked even when I
- *             disabled update by the BIOS)
- *             Thanks to Eric W. Biederman <ebiederman@xxxxxxxx> for the fix.
- *     1.08    11 Dec 2000, Richard Schaal <richard.schaal@xxxxxxxxx> and
- *                          Tigran Aivazian <tigran@xxxxxxxxxxx>
- *             Intel Pentium 4 processor support and bugfixes.
- *     1.09    30 Oct 2001, Tigran Aivazian <tigran@xxxxxxxxxxx>
- *             Bugfix for HT (Hyper-Threading) enabled processors
- *             whereby processor resources are shared by all logical processors
- *             in a single CPU package.
- *     1.10    28 Feb 2002 Asit K Mallick <asit.k.mallick@xxxxxxxxx> and
- *             Tigran Aivazian <tigran@xxxxxxxxxxx>,
- *             Serialize updates as required on HT processors due to 
speculative
- *             nature of implementation.
- *     1.11    22 Mar 2002 Tigran Aivazian <tigran@xxxxxxxxxxx>
- *             Fix the panic when writing zero-length microcode chunk.
- *     1.12    29 Sep 2003 Nitin Kamble <nitin.a.kamble@xxxxxxxxx>, 
- *             Jun Nakajima <jun.nakajima@xxxxxxxxx>
- *             Support for the microcode updates in the new format.
- *     1.13    10 Oct 2003 Tigran Aivazian <tigran@xxxxxxxxxxx>
- *             Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl
- *             because we no longer hold a copy of applied microcode 
- *             in kernel memory.
- *     1.14    25 Jun 2004 Tigran Aivazian <tigran@xxxxxxxxxxx>
- *             Fix sigmatch() macro to handle old CPUs with pf == 0.
- *             Thanks to Stuart Swales for pointing out this bug.
+ * 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.
  */
 
 #include <xen/config.h>
@@ -76,402 +28,169 @@
 #include <xen/sched.h>
 #include <xen/smp.h>
 #include <xen/spinlock.h>
+#include <xen/guest_access.h>
 
 #include <asm/current.h>
 #include <asm/msr.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>
+#include <asm/microcode.h>
 
-#define pr_debug(x...) ((void)0)
-#define DEFINE_MUTEX(_m) DEFINE_SPINLOCK(_m)
-#define mutex_lock(_m) spin_lock(_m)
-#define mutex_unlock(_m) spin_unlock(_m)
-#define vmalloc(_s) xmalloc_bytes(_s)
-#define vfree(_p) xfree(_p)
+const struct microcode_ops *microcode_ops;
 
-#if 0
-MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver");
-MODULE_AUTHOR("Tigran Aivazian <tigran@xxxxxxxxxxx>");
-MODULE_LICENSE("GPL");
-#endif
+static DEFINE_SPINLOCK(microcode_mutex);
 
-static int verbose;
-boolean_param("microcode.verbose", verbose);
+struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
 
-#define MICROCODE_VERSION      "1.14a"
+struct microcode_buffer {
+    void *buf;
+    size_t size;
+};
 
-#define DEFAULT_UCODE_DATASIZE         (2000)    /* 2000 bytes */
-#define MC_HEADER_SIZE         (sizeof (microcode_header_t))     /* 48 bytes */
-#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 
2048 bytes */
-#define EXT_HEADER_SIZE                (sizeof (struct extended_sigtable)) /* 
20 bytes */
-#define EXT_SIGNATURE_SIZE     (sizeof (struct extended_signature)) /* 12 
bytes */
-#define DWSIZE                 (sizeof (u32))
-#define get_totalsize(mc) \
-       (((microcode_t *)mc)->hdr.totalsize ? \
-        ((microcode_t *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE)
-#define get_datasize(mc) \
-       (((microcode_t *)mc)->hdr.datasize ? \
-        ((microcode_t *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE)
+static struct microcode_buffer microcode_buffer;
+static bool_t microcode_error;
 
-#define sigmatch(s1, s2, p1, p2) \
-       (((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0))))
+static void microcode_fini_cpu(int cpu)
+{
+    struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 
-#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)
-
-/* serialize access to the physical write to MSR 0x79 */
-static DEFINE_SPINLOCK(microcode_update_lock);
-
-/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
-static DEFINE_MUTEX(microcode_mutex);
-
-static const void __user *user_buffer; /* user area microcode data buffer */
-static unsigned int user_buffer_size;  /* it's size */
-
-typedef enum mc_error_code {
-       MC_SUCCESS      = 0,
-       MC_IGNORED      = 1,
-       MC_NOTFOUND     = 2,
-       MC_MARKED       = 3,
-       MC_ALLOCATED    = 4,
-} mc_error_code_t;
-
-static struct ucode_cpu_info {
-       unsigned int sig;
-       unsigned int pf, orig_pf;
-       unsigned int rev;
-       unsigned int cksum;
-       mc_error_code_t err;
-       microcode_t *mc;
-} ucode_cpu_info[NR_CPUS];
-                               
-static void collect_cpu_info (void *unused)
-{
-       int cpu_num = smp_processor_id();
-       struct cpuinfo_x86 *c = cpu_data + cpu_num;
-       struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
-       unsigned int val[2];
-
-       uci->sig = uci->pf = uci->rev = uci->cksum = 0;
-       uci->err = MC_NOTFOUND;
-       uci->mc = NULL;
-
-       if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
-               cpu_has(c, X86_FEATURE_IA64)) {
-               printk(KERN_ERR "microcode: CPU%d not a capable Intel 
processor\n", cpu_num);
-               return;
-       } else {
-               uci->sig = cpuid_eax(0x00000001);
-
-               if ((c->x86_model >= 5) || (c->x86 > 6)) {
-                       /* get processor flags from MSR 0x17 */
-                       rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
-                       uci->pf = 1 << ((val[1] >> 18) & 7);
-               }
-               uci->orig_pf = uci->pf;
-       }
-
-       wrmsr(MSR_IA32_UCODE_REV, 0, 0);
-       /* see notes above for revision 1.07.  Apparent chip bug */
-       sync_core();
-       /* get the current revision from MSR 0x8B */
-       rdmsr(MSR_IA32_UCODE_REV, val[0], uci->rev);
-       pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n",
-                       uci->sig, uci->pf, uci->rev);
+    spin_lock(&microcode_mutex);
+    xfree(uci->mc.valid_mc);
+    uci->mc.valid_mc = NULL;
+    uci->valid = 0;
+    spin_unlock(&microcode_mutex);
 }
 
-static inline void mark_microcode_update (int cpu_num, microcode_header_t 
*mc_header, int sig, int pf, int cksum)
+static int collect_cpu_info(int cpu)
 {
-       struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
+    int err = 0;
+    struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 
-       pr_debug("Microcode Found.\n");
-       pr_debug("   Header Revision 0x%x\n", mc_header->hdrver);
-       pr_debug("   Loader Revision 0x%x\n", mc_header->ldrver);
-       pr_debug("   Revision 0x%x \n", mc_header->rev);
-       pr_debug("   Date %x/%x/%x\n",
-               ((mc_header->date >> 24 ) & 0xff),
-               ((mc_header->date >> 16 ) & 0xff),
-               (mc_header->date & 0xFFFF));
-       pr_debug("   Signature 0x%x\n", sig);
-       pr_debug("   Type 0x%x Family 0x%x Model 0x%x Stepping 0x%x\n",
-               ((sig >> 12) & 0x3),
-               ((sig >> 8) & 0xf),
-               ((sig >> 4) & 0xf),
-               ((sig & 0xf)));
-       pr_debug("   Processor Flags 0x%x\n", pf);
-       pr_debug("   Checksum 0x%x\n", cksum);
+    memset(uci, 0, sizeof(*uci));
+    err = microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig);
+    if ( !err )
+        uci->valid = 1;
 
-       if (mc_header->rev < uci->rev) {
-               if (uci->err == MC_NOTFOUND) {
-                       uci->err = MC_IGNORED;
-                       uci->cksum = mc_header->rev;
-               } else if (uci->err == MC_IGNORED && uci->cksum < 
mc_header->rev)
-                       uci->cksum = mc_header->rev;
-       } else if (mc_header->rev == uci->rev) {
-               if (uci->err < MC_MARKED) {
-                       /* notify the caller of success on this cpu */
-                       uci->err = MC_SUCCESS;
-               }
-       } else if (uci->err != MC_ALLOCATED || mc_header->rev > 
uci->mc->hdr.rev) {
-               pr_debug("microcode: CPU%d found a matching microcode update 
with "
-                       " revision 0x%x (current=0x%x)\n", cpu_num, 
mc_header->rev, uci->rev);
-               uci->cksum = cksum;
-               uci->pf = pf; /* keep the original mc pf for cksum calculation 
*/
-               uci->err = MC_MARKED; /* found the match */
-               for_each_online_cpu(cpu_num) {
-                       if (ucode_cpu_info + cpu_num != uci
-                           && ucode_cpu_info[cpu_num].mc == uci->mc) {
-                               uci->mc = NULL;
-                               break;
-                       }
-               }
-               if (uci->mc != NULL) {
-                       vfree(uci->mc);
-                       uci->mc = NULL;
-               }
-       }
-       return;
+    return err;
 }
 
-static int find_matching_ucodes (void) 
+static int microcode_resume_cpu(int cpu)
 {
-       int cursor = 0;
-       int error = 0;
+    int err = 0;
+    struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+    struct cpu_signature nsig;
 
-       while (cursor + MC_HEADER_SIZE < user_buffer_size) {
-               microcode_header_t mc_header;
-               void *newmc = NULL;
-               int i, sum, cpu_num, allocated_flag, total_size, data_size, 
ext_table_size;
+    gdprintk(XENLOG_INFO, "microcode: CPU%d resumed\n", cpu);
 
-               if (copy_from_user(&mc_header, user_buffer + cursor, 
MC_HEADER_SIZE)) {
-                       printk(KERN_ERR "microcode: error! Can not read user 
data\n");
-                       error = -EFAULT;
-                       goto out;
-               }
+    if ( !uci->mc.valid_mc )
+        return -EIO;
 
-               total_size = get_totalsize(&mc_header);
-               if (cursor + total_size > user_buffer_size) {
-                       printk(KERN_ERR "microcode: error! Bad data in 
microcode data file\n");
-                       error = -EINVAL;
-                       goto out;
-               }
+    /*
+     * Let's verify that the 'cached' ucode does belong
+     * to this cpu (a bit of paranoia):
+     */
+    err = microcode_ops->collect_cpu_info(cpu, &nsig);
+    if ( err )
+    {
+        microcode_fini_cpu(cpu);
+        return err;
+    }
 
-               data_size = get_datasize(&mc_header);
-               if (data_size + MC_HEADER_SIZE > total_size) {
-                       printk(KERN_ERR "microcode: error! Bad data in 
microcode data file\n");
-                       error = -EINVAL;
-                       goto out;
-               }
+    if ( memcmp(&nsig, &uci->cpu_sig, sizeof(nsig)) )
+    {
+        microcode_fini_cpu(cpu);
+        /* Should we look for a new ucode here? */
+        return -EIO;
+    }
 
-               if (mc_header.ldrver != 1 || mc_header.hdrver != 1) {
-                       printk(KERN_ERR "microcode: error! Unknown microcode 
update format\n");
-                       error = -EINVAL;
-                       goto out;
-               }
+    err = microcode_ops->apply_microcode(cpu);
 
-               for_each_online_cpu(cpu_num) {
-                       struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
-
-                       if (sigmatch(mc_header.sig, uci->sig, mc_header.pf, 
uci->orig_pf))
-                               mark_microcode_update(cpu_num, &mc_header, 
mc_header.sig, mc_header.pf, mc_header.cksum);
-               }
-
-               ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
-               if (ext_table_size) {
-                       struct extended_sigtable ext_header;
-                       struct extended_signature ext_sig;
-                       int ext_sigcount;
-
-                       if ((ext_table_size < EXT_HEADER_SIZE) 
-                                       || ((ext_table_size - EXT_HEADER_SIZE) 
% EXT_SIGNATURE_SIZE)) {
-                               printk(KERN_ERR "microcode: error! Bad data in 
microcode data file\n");
-                               error = -EINVAL;
-                               goto out;
-                       }
-                       if (copy_from_user(&ext_header, user_buffer + cursor 
-                                       + MC_HEADER_SIZE + data_size, 
EXT_HEADER_SIZE)) {
-                               printk(KERN_ERR "microcode: error! Can not read 
user data\n");
-                               error = -EFAULT;
-                               goto out;
-                       }
-                       if (ext_table_size != exttable_size(&ext_header)) {
-                               printk(KERN_ERR "microcode: error! Bad data in 
microcode data file\n");
-                               error = -EFAULT;
-                               goto out;
-                       }
-
-                       ext_sigcount = ext_header.count;
-                       
-                       for (i = 0; i < ext_sigcount; i++) {
-                               if (copy_from_user(&ext_sig, user_buffer + 
cursor + MC_HEADER_SIZE + data_size + EXT_HEADER_SIZE 
-                                               + EXT_SIGNATURE_SIZE * i, 
EXT_SIGNATURE_SIZE)) {
-                                       printk(KERN_ERR "microcode: error! Can 
not read user data\n");
-                                       error = -EFAULT;
-                                       goto out;
-                               }
-                               for_each_online_cpu(cpu_num) {
-                                       struct ucode_cpu_info *uci = 
ucode_cpu_info + cpu_num;
-
-                                       if (sigmatch(ext_sig.sig, uci->sig, 
ext_sig.pf, uci->orig_pf)) {
-                                               mark_microcode_update(cpu_num, 
&mc_header, ext_sig.sig, ext_sig.pf, ext_sig.cksum);
-                                       }
-                               }
-                       }
-               }
-               /* now check if any cpu has matched */
-               allocated_flag = 0;
-               sum = 0;
-               for_each_online_cpu(cpu_num) {
-                       if (ucode_cpu_info[cpu_num].err == MC_MARKED) { 
-                               struct ucode_cpu_info *uci = ucode_cpu_info + 
cpu_num;
-                               if (!allocated_flag) {
-                                       allocated_flag = 1;
-                                       newmc = vmalloc(total_size);
-                                       if (!newmc) {
-                                               printk(KERN_ERR "microcode: 
error! Can not allocate memory\n");
-                                               error = -ENOMEM;
-                                               goto out;
-                                       }
-                                       if (copy_from_user(newmc + 
MC_HEADER_SIZE, 
-                                                               user_buffer + 
cursor + MC_HEADER_SIZE, 
-                                                               total_size - 
MC_HEADER_SIZE)) {
-                                               printk(KERN_ERR "microcode: 
error! Can not read user data\n");
-                                               vfree(newmc);
-                                               error = -EFAULT;
-                                               goto out;
-                                       }
-                                       memcpy(newmc, &mc_header, 
MC_HEADER_SIZE);
-                                       /* check extended table checksum */
-                                       if (ext_table_size) {
-                                               int ext_table_sum = 0;
-                                               int * ext_tablep = (((void *) 
newmc) + MC_HEADER_SIZE + data_size);
-                                               i = ext_table_size / DWSIZE;
-                                               while (i--) ext_table_sum += 
ext_tablep[i];
-                                               if (ext_table_sum) {
-                                                       printk(KERN_WARNING 
"microcode: aborting, bad extended signature table checksum\n");
-                                                       vfree(newmc);
-                                                       error = -EINVAL;
-                                                       goto out;
-                                               }
-                                       }
-
-                                       /* calculate the checksum */
-                                       i = (MC_HEADER_SIZE + data_size) / 
DWSIZE;
-                                       while (i--) sum += ((int *)newmc)[i];
-                                       sum -= (mc_header.sig + mc_header.pf + 
mc_header.cksum);
-                               }
-                               ucode_cpu_info[cpu_num].mc = newmc;
-                               ucode_cpu_info[cpu_num].err = MC_ALLOCATED; /* 
mc updated */
-                               if (sum + uci->sig + uci->pf + uci->cksum != 0) 
{
-                                       printk(KERN_ERR "microcode: CPU%d 
aborting, bad checksum\n", cpu_num);
-                                       error = -EINVAL;
-                                       goto out;
-                               }
-                       }
-               }
-               cursor += total_size; /* goto the next update patch */
-       } /* end of while */
-out:
-       return error;
+    return err;
 }
 
-static void do_update_one (void * unused)
+static int microcode_update_cpu(int cpu, const void *buf, size_t size)
 {
-       unsigned long flags;
-       unsigned int val[2];
-       int cpu_num = smp_processor_id();
-       struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
+    int err = 0;
+    struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 
-       if (uci->mc == NULL) {
-               if (verbose) {
-                       if (uci->err == MC_SUCCESS)
-                               printk(KERN_INFO "microcode: CPU%d already at 
revision 0x%x\n",
-                                       cpu_num, uci->rev);
-                       else
-                               printk(KERN_INFO "microcode: No new microcode 
data for CPU%d\n", cpu_num);
-               }
-               return;
-       }
+    /* We should bind the task to the CPU */
+    BUG_ON(raw_smp_processor_id() != cpu);
 
-       /* serialize access to the physical write to MSR 0x79 */
-       spin_lock_irqsave(&microcode_update_lock, flags);          
+    spin_lock(&microcode_mutex);
 
-       /* write microcode via MSR 0x79 */
-       wrmsr(MSR_IA32_UCODE_WRITE,
-               (unsigned long) uci->mc->bits, 
-               (unsigned long) uci->mc->bits >> 16 >> 16);
-       wrmsr(MSR_IA32_UCODE_REV, 0, 0);
+    /*
+     * Check if the system resume is in progress (uci->valid != NULL),
+     * otherwise just request a firmware:
+     */
+    if ( uci->valid )
+    {
+        err = microcode_resume_cpu(cpu);
+    }
+    else
+    {
+        err = collect_cpu_info(cpu);
+        if ( !err && uci->valid )
+            err = microcode_ops->cpu_request_microcode(cpu, buf, size);
+    }
 
-       /* see notes above for revision 1.07.  Apparent chip bug */
-       sync_core();
+    spin_unlock(&microcode_mutex);
 
-       /* get the current revision from MSR 0x8B */
-       rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
-
-       /* notify the caller of success on this cpu */
-       uci->err = MC_SUCCESS;
-       spin_unlock_irqrestore(&microcode_update_lock, flags);
-       printk(KERN_INFO "microcode: CPU%d updated from revision "
-              "0x%x to 0x%x, date = %08x \n", 
-              cpu_num, uci->rev, val[1], uci->mc->hdr.date);
-       return;
+    return err;
 }
 
-static int do_microcode_update (void)
+static void do_microcode_update_one(void *info)
 {
-       int i, error;
+    int error = microcode_update_cpu(
+        smp_processor_id(), microcode_buffer.buf, microcode_buffer.size);
+    if ( error )
+        microcode_error = error;
+}
 
-       if (on_each_cpu(collect_cpu_info, NULL, 1, 1) != 0) {
-               printk(KERN_ERR "microcode: Error! Could not run on all 
processors\n");
-               error = -EIO;
-               goto out;
-       }
+static int do_microcode_update(void)
+{
+    microcode_error = 0;
 
-       if ((error = find_matching_ucodes())) {
-               printk(KERN_ERR "microcode: Error in the microcode data\n");
-               goto out_free;
-       }
+    if ( on_each_cpu(do_microcode_update_one, NULL, 1, 1) != 0 )
+    {
+        printk(KERN_ERR "microcode: Error! Could not run on all processors\n");
+        return -EIO;
+    }
 
-       if (on_each_cpu(do_update_one, NULL, 1, 1) != 0) {
-               printk(KERN_ERR "microcode: Error! Could not run on all 
processors\n");
-               error = -EIO;
-       }
-
-out_free:
-       for_each_online_cpu(i) {
-               if (ucode_cpu_info[i].mc) {
-                       int j;
-                       void *tmp = ucode_cpu_info[i].mc;
-                       vfree(tmp);
-                       for_each_online_cpu(j) {
-                               if (ucode_cpu_info[j].mc == tmp)
-                                       ucode_cpu_info[j].mc = NULL;
-                       }
-               }
-               if (ucode_cpu_info[i].err == MC_IGNORED && verbose)
-                       printk(KERN_WARNING "microcode: CPU%d not 'upgrading' 
to earlier revision"
-                              " 0x%x (current=0x%x)\n", i, 
ucode_cpu_info[i].cksum, ucode_cpu_info[i].rev);
-       }
-out:
-       return error;
+    return microcode_error;
 }
 
 int microcode_update(XEN_GUEST_HANDLE(const_void) buf, unsigned long len)
 {
-       int ret;
+    int ret;
 
-       if (len != (typeof(user_buffer_size))len) {
-               printk(KERN_ERR "microcode: too much data\n");
-               return -E2BIG;
-       }
+    /* XXX FIXME: No allocations in interrupt context. */
+    return -EINVAL;
 
-       mutex_lock(&microcode_mutex);
+    if ( len != (typeof(microcode_buffer.size))len )
+    {
+        printk(KERN_ERR "microcode: too much data\n");
+        return -E2BIG;
+    }
 
-       user_buffer = buf.p;
-       user_buffer_size = len;
+    if ( microcode_ops == NULL )
+        return -EINVAL;
 
-       ret = do_microcode_update();
+    microcode_buffer.buf = xmalloc_array(uint8_t, len);
+    if ( microcode_buffer.buf == NULL )
+        return -ENOMEM;
 
-       mutex_unlock(&microcode_mutex);
+    ret = copy_from_guest(microcode_buffer.buf, buf, len);
+    if ( ret != 0 )
+        return ret;
 
-       return ret;
+    microcode_buffer.size = len;
+    wmb();
+
+    ret = do_microcode_update();
+
+    xfree(microcode_buffer.buf);
+    microcode_buffer.buf = NULL;
+    microcode_buffer.size = 0;
+
+    return ret;
 }
diff -r ec8eaab557d8 -r 4a381ddc764a xen/arch/x86/microcode_amd.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/microcode_amd.c      Tue Sep 16 21:25:30 2008 +0900
@@ -0,0 +1,371 @@
+/*
+ *  AMD CPU Microcode Update Driver for Linux
+ *  Copyright (C) 2008 Advanced Micro Devices Inc.
+ *
+ *  Author: Peter Oruba <peter.oruba@xxxxxxx>
+ *
+ *  Based on work by:
+ *  Tigran Aivazian <tigran@xxxxxxxxxxxxxxxxxxxx>
+ *
+ *  This driver allows to upgrade microcode on AMD
+ *  family 0x10 and 0x11 processors.
+ *
+ *  Licensed unter the terms of the GNU General Public
+ *  License version 2. See file COPYING for details.
+ */
+
+#include <xen/config.h>
+#include <xen/lib.h>
+#include <xen/kernel.h>
+#include <xen/init.h>
+#include <xen/sched.h>
+#include <xen/smp.h>
+#include <xen/spinlock.h>
+
+#include <asm/msr.h>
+#include <asm/uaccess.h>
+#include <asm/processor.h>
+#include <asm/microcode.h>
+
+#define pr_debug(x...) ((void)0)
+
+#define UCODE_MAGIC                0x00414d44
+#define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000
+#define UCODE_UCODE_TYPE           0x00000001
+
+#define UCODE_MAX_SIZE          (2048)
+#define DEFAULT_UCODE_DATASIZE  (896)
+#define MC_HEADER_SIZE          (sizeof(struct microcode_header_amd))
+#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE)
+#define DWSIZE                  (sizeof(uint32_t))
+/* For now we support a fixed ucode total size only */
+#define get_totalsize(mc) \
+        ((((struct microcode_amd *)mc)->hdr.mc_patch_data_len * 28) \
+         + MC_HEADER_SIZE)
+
+/* serialize access to the physical write */
+static DEFINE_SPINLOCK(microcode_update_lock);
+
+struct equiv_cpu_entry *equiv_cpu_table;
+
+static long install_equiv_cpu_table(const void *, uint32_t, long);
+
+static int collect_cpu_info(int cpu, struct cpu_signature *csig)
+{
+    struct cpuinfo_x86 *c = &cpu_data[cpu];
+
+    memset(csig, 0, sizeof(*csig));
+
+    if ( (c->x86_vendor != X86_VENDOR_AMD) || (c->x86 < 0x10) )
+    {
+        printk(KERN_ERR "microcode: CPU%d not a capable AMD processor\n",
+               cpu);
+        return -1;
+    }
+
+    asm volatile (
+        "movl %1, %%ecx; rdmsr"
+        : "=a" (csig->rev)
+        : "i" (MSR_AMD_PATCHLEVEL) : "ecx" );
+
+    printk(KERN_INFO "microcode: collect_cpu_info: patch_id=0x%x\n",
+           csig->rev);
+
+    return 0;
+}
+
+static int get_matching_microcode(void *mc, int cpu)
+{
+    struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+    struct microcode_header_amd *mc_header = mc;
+    unsigned long total_size = get_totalsize(mc_header);
+    void *new_mc;
+    unsigned int current_cpu_id;
+    unsigned int equiv_cpu_id = 0x00;
+    unsigned int i;
+
+    /* We should bind the task to the CPU */
+    BUG_ON(cpu != raw_smp_processor_id());
+
+    /* This is a tricky part. We might be called from a write operation
+     * to the device file instead of the usual process of firmware
+     * loading. This routine needs to be able to distinguish both
+     * cases. This is done by checking if there already is a equivalent
+     * CPU table installed. If not, we're written through
+     * /dev/cpu/microcode.
+     * Since we ignore all checks. The error case in which going through
+     * firmware loading and that table is not loaded has already been
+     * checked earlier.
+     */
+    if ( equiv_cpu_table == NULL )
+    {
+        printk(KERN_INFO "microcode: CPU%d microcode update with "
+               "version 0x%x (current=0x%x)\n",
+               cpu, mc_header->patch_id, uci->cpu_sig.rev);
+        goto out;
+    }
+
+    current_cpu_id = cpuid_eax(0x00000001);
+
+    for ( i = 0; equiv_cpu_table[i].installed_cpu != 0; i++ )
+    {
+        if ( current_cpu_id == equiv_cpu_table[i].installed_cpu )
+        {
+            equiv_cpu_id = equiv_cpu_table[i].equiv_cpu;
+            break;
+        }
+    }
+
+    if ( !equiv_cpu_id )
+    {
+        printk(KERN_ERR "microcode: CPU%d cpu_id "
+               "not found in equivalent cpu table \n", cpu);
+        return 0;
+    }
+
+    if ( (mc_header->processor_rev_id[0]) != (equiv_cpu_id & 0xff) )
+    {
+        printk(KERN_INFO
+               "microcode: CPU%d patch does not match "
+               "(patch is %x, cpu extended is %x) \n",
+               cpu, mc_header->processor_rev_id[0],
+               (equiv_cpu_id & 0xff));
+        return 0;
+    }
+
+    if ( (mc_header->processor_rev_id[1]) != ((equiv_cpu_id >> 16) & 0xff) )
+    {
+        printk(KERN_INFO "microcode: CPU%d patch does not match "
+               "(patch is %x, cpu base id is %x) \n",
+               cpu, mc_header->processor_rev_id[1],
+               ((equiv_cpu_id >> 16) & 0xff));
+        return 0;
+    }
+
+    if ( mc_header->patch_id <= uci->cpu_sig.rev )
+        return 0;
+
+    printk(KERN_INFO "microcode: CPU%d found a matching microcode "
+           "update with version 0x%x (current=0x%x)\n",
+           cpu, mc_header->patch_id, uci->cpu_sig.rev);
+
+ out:
+    new_mc = xmalloc_bytes(UCODE_MAX_SIZE);
+    if ( new_mc == NULL )
+    {
+        printk(KERN_ERR "microcode: error, can't allocate memory\n");
+        return -ENOMEM;
+    }
+    memset(new_mc, 0, UCODE_MAX_SIZE);
+
+    /* free previous update file */
+    xfree(uci->mc.mc_amd);
+
+    memcpy(new_mc, mc, total_size);
+
+    uci->mc.mc_amd = new_mc;
+    return 1;
+}
+
+static int apply_microcode(int cpu)
+{
+    unsigned long flags;
+    uint32_t eax, edx, rev;
+    int cpu_num = raw_smp_processor_id();
+    struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
+    uint64_t addr;
+
+    /* We should bind the task to the CPU */
+    BUG_ON(cpu_num != cpu);
+
+    if ( uci->mc.mc_amd == NULL )
+        return -EINVAL;
+
+    spin_lock_irqsave(&microcode_update_lock, flags);
+
+    addr = (unsigned long)&uci->mc.mc_amd->hdr.data_code;
+    edx = (uint32_t)(addr >> 32);
+    eax = (uint32_t)addr;
+
+    asm volatile (
+        "movl %0, %%ecx; wrmsr" :
+        : "i" (MSR_AMD_PATCHLOADER), "a" (eax), "d" (edx) : "ecx" );
+
+    /* get patch id after patching */
+    asm volatile (
+        "movl %1, %%ecx; rdmsr"
+        : "=a" (rev)
+        : "i" (MSR_AMD_PATCHLEVEL) : "ecx");
+
+    spin_unlock_irqrestore(&microcode_update_lock, flags);
+
+    /* check current patch id and patch's id for match */
+    if ( rev != uci->mc.mc_amd->hdr.patch_id )
+    {
+        printk(KERN_ERR "microcode: CPU%d update from revision "
+               "0x%x to 0x%x failed\n", cpu_num,
+               uci->mc.mc_amd->hdr.patch_id, rev);
+        return -EIO;
+    }
+
+    printk("microcode: CPU%d updated from revision "
+           "0x%x to 0x%x \n",
+           cpu_num, uci->cpu_sig.rev, uci->mc.mc_amd->hdr.patch_id);
+
+    uci->cpu_sig.rev = rev;
+
+    return 0;
+}
+
+static long get_next_ucode_from_buffer_amd(void **mc, const void *buf,
+                                           unsigned long size, long offset)
+{
+    struct microcode_header_amd *mc_header;
+    unsigned long total_size;
+    const uint8_t *buf_pos = buf;
+
+    /* No more data */
+    if ( offset >= size )
+        return 0;
+
+    if ( buf_pos[offset] != UCODE_UCODE_TYPE )
+    {
+        printk(KERN_ERR "microcode: error! "
+               "Wrong microcode payload type field\n");
+        return -EINVAL;
+    }
+
+    mc_header = (struct microcode_header_amd *)(&buf_pos[offset+8]);
+
+    total_size = (unsigned long) (buf_pos[offset+4] +
+                                  (buf_pos[offset+5] << 8));
+
+    printk(KERN_INFO "microcode: size %lu, total_size %lu, offset %ld\n",
+           size, total_size, offset);
+
+    if ( (offset + total_size) > size )
+    {
+        printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
+        return -EINVAL;
+    }
+
+    *mc = xmalloc_bytes(UCODE_MAX_SIZE);
+    if ( *mc == NULL )
+    {
+        printk(KERN_ERR "microcode: error! "
+               "Can not allocate memory for microcode patch\n");
+        return -ENOMEM;
+    }
+
+    memset(*mc, 0, UCODE_MAX_SIZE);
+    memcpy(*mc, (const void *)(buf + offset + 8), total_size);
+
+    return offset + total_size + 8;
+}
+
+static long install_equiv_cpu_table(const void *buf,
+                                    uint32_t size, long offset)
+{
+    const uint32_t *buf_pos = buf;
+
+    /* No more data */
+    if ( offset >= size )
+        return 0;
+
+    if ( buf_pos[1] != UCODE_EQUIV_CPU_TABLE_TYPE )
+    {
+        printk(KERN_ERR "microcode: error! "
+               "Wrong microcode equivalnet cpu table type field\n");
+        return 0;
+    }
+
+    if ( size == 0 )
+    {
+        printk(KERN_ERR "microcode: error! "
+               "Wrong microcode equivalnet cpu table length\n");
+        return 0;
+    }
+
+    equiv_cpu_table = xmalloc_bytes(size);
+    if ( equiv_cpu_table == NULL )
+    {
+        printk(KERN_ERR "microcode: error, can't allocate "
+               "memory for equiv CPU table\n");
+        return 0;
+    }
+
+    memset(equiv_cpu_table, 0, size);
+    memcpy(equiv_cpu_table, (const void *)&buf_pos[3], size);
+
+    return size + 12; /* add header length */
+}
+
+static int cpu_request_microcode(int cpu, const void *buf, size_t size)
+{
+    const uint32_t *buf_pos;
+    long offset = 0;
+    int error = 0;
+    void *mc;
+
+    /* We should bind the task to the CPU */
+    BUG_ON(cpu != raw_smp_processor_id());
+
+    buf_pos = (const uint32_t *)buf;
+
+    if ( buf_pos[0] != UCODE_MAGIC )
+    {
+        printk(KERN_ERR "microcode: error! Wrong "
+               "microcode patch file magic\n");
+        return -EINVAL;
+    }
+
+    offset = install_equiv_cpu_table(buf, (uint32_t)(buf_pos[2]), offset);
+    if ( !offset )
+    {
+        printk(KERN_ERR "microcode: installing equivalent cpu table failed\n");
+        return -EINVAL;
+    }
+
+    while ( (offset =
+             get_next_ucode_from_buffer_amd(&mc, buf, size, offset)) > 0 )
+    {
+        error = get_matching_microcode(mc, cpu);
+        if ( error < 0 )
+            break;
+        /*
+         * It's possible the data file has multiple matching ucode,
+         * lets keep searching till the latest version
+         */
+        if ( error == 1 )
+        {
+            apply_microcode(cpu);
+            error = 0;
+        }
+        xfree(mc);
+    }
+    if ( offset > 0 )
+    {
+        xfree(mc);
+        xfree(equiv_cpu_table);
+        equiv_cpu_table = NULL;
+    }
+    if ( offset < 0 )
+        error = offset;
+
+    return error;
+}
+
+static struct microcode_ops microcode_amd_ops = {
+    .get_matching_microcode           = get_matching_microcode,
+    .cpu_request_microcode            = cpu_request_microcode,
+    .collect_cpu_info                 = collect_cpu_info,
+    .apply_microcode                  = apply_microcode,
+};
+
+static __init int microcode_init_amd(void)
+{
+    if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD )
+        microcode_ops = &microcode_amd_ops;
+    return 0;
+}
+__initcall(microcode_init_amd);
diff -r ec8eaab557d8 -r 4a381ddc764a xen/arch/x86/microcode_intel.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/microcode_intel.c    Tue Sep 16 21:25:30 2008 +0900
@@ -0,0 +1,370 @@
+/*
+ * Intel CPU Microcode Update Driver for Linux
+ *
+ * Copyright (C) 2000-2006 Tigran Aivazian <tigran@xxxxxxxxxxxxxxxxxxxx>
+ *               2006 Shaohua Li <shaohua.li@xxxxxxxxx> *
+ * This driver allows to upgrade microcode on Intel processors
+ * belonging to IA-32 family - PentiumPro, Pentium II,
+ * Pentium III, Xeon, Pentium 4, etc.
+ *
+ * Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture
+ * Software Developer's Manual
+ * Order Number 253668 or free download from:
+ *
+ * http://developer.intel.com/design/pentium4/manuals/253668.htm
+ *
+ * For more information, go to http://www.urbanmyth.org/microcode
+ *
+ * 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.
+ */
+
+#include <xen/config.h>
+#include <xen/lib.h>
+#include <xen/kernel.h>
+#include <xen/init.h>
+#include <xen/sched.h>
+#include <xen/smp.h>
+#include <xen/spinlock.h>
+
+#include <asm/msr.h>
+#include <asm/uaccess.h>
+#include <asm/processor.h>
+#include <asm/microcode.h>
+
+#define pr_debug(x...) ((void)0)
+
+#define DEFAULT_UCODE_DATASIZE  (2000)
+#define MC_HEADER_SIZE          (sizeof(struct microcode_header_intel))
+#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE)
+#define EXT_HEADER_SIZE         (sizeof(struct extended_sigtable))
+#define EXT_SIGNATURE_SIZE      (sizeof(struct extended_signature))
+#define DWSIZE                  (sizeof(u32))
+#define get_totalsize(mc) \
+        (((struct microcode_intel *)mc)->hdr.totalsize ? \
+         ((struct microcode_intel *)mc)->hdr.totalsize : \
+         DEFAULT_UCODE_TOTALSIZE)
+
+#define get_datasize(mc) \
+        (((struct microcode_intel *)mc)->hdr.datasize ? \
+         ((struct microcode_intel *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE)
+
+#define sigmatch(s1, s2, p1, p2) \
+        (((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0))))
+
+#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)
+
+/* serialize access to the physical write to MSR 0x79 */
+static DEFINE_SPINLOCK(microcode_update_lock);
+
+static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
+{
+    struct cpuinfo_x86 *c = &cpu_data[cpu_num];
+    unsigned int val[2];
+
+    memset(csig, 0, sizeof(*csig));
+
+    if ( (c->x86_vendor != X86_VENDOR_INTEL) || (c->x86 < 6) ||
+         cpu_has(c, X86_FEATURE_IA64) )
+    {
+        printk(KERN_ERR "microcode: CPU%d not a capable Intel "
+               "processor\n", cpu_num);
+        return -1;
+    }
+
+    csig->sig = cpuid_eax(0x00000001);
+
+    if ( (c->x86_model >= 5) || (c->x86 > 6) )
+    {
+        /* get processor flags from MSR 0x17 */
+        rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
+        csig->pf = 1 << ((val[1] >> 18) & 7);
+    }
+
+    wrmsr(MSR_IA32_UCODE_REV, 0, 0);
+    /* see notes above for revision 1.07.  Apparent chip bug */
+    sync_core();
+    /* get the current revision from MSR 0x8B */
+    rdmsr(MSR_IA32_UCODE_REV, val[0], csig->rev);
+    pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n",
+             csig->sig, csig->pf, csig->rev);
+
+    return 0;
+}
+
+static inline int microcode_update_match(
+    int cpu_num, struct microcode_header_intel *mc_header, int sig, int pf)
+{
+    struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
+
+    return (sigmatch(sig, uci->cpu_sig.sig, pf, uci->cpu_sig.pf) &&
+            (mc_header->rev > uci->cpu_sig.rev));
+}
+
+static int microcode_sanity_check(void *mc)
+{
+    struct microcode_header_intel *mc_header = mc;
+    struct extended_sigtable *ext_header = NULL;
+    struct extended_signature *ext_sig;
+    unsigned long total_size, data_size, ext_table_size;
+    int sum, orig_sum, ext_sigcount = 0, i;
+
+    total_size = get_totalsize(mc_header);
+    data_size = get_datasize(mc_header);
+    if ( (data_size + MC_HEADER_SIZE) > total_size )
+    {
+        printk(KERN_ERR "microcode: error! "
+               "Bad data size in microcode data file\n");
+        return -EINVAL;
+    }
+
+    if ( (mc_header->ldrver != 1) || (mc_header->hdrver != 1) )
+    {
+        printk(KERN_ERR "microcode: error! "
+               "Unknown microcode update format\n");
+        return -EINVAL;
+    }
+    ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
+    if ( ext_table_size )
+    {
+        if ( (ext_table_size < EXT_HEADER_SIZE) ||
+             ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE) )
+        {
+            printk(KERN_ERR "microcode: error! "
+                   "Small exttable size in microcode data file\n");
+            return -EINVAL;
+        }
+        ext_header = mc + MC_HEADER_SIZE + data_size;
+        if ( ext_table_size != exttable_size(ext_header) )
+        {
+            printk(KERN_ERR "microcode: error! "
+                   "Bad exttable size in microcode data file\n");
+            return -EFAULT;
+        }
+        ext_sigcount = ext_header->count;
+    }
+
+    /* check extended table checksum */
+    if ( ext_table_size )
+    {
+        int ext_table_sum = 0;
+        int *ext_tablep = (int *)ext_header;
+
+        i = ext_table_size / DWSIZE;
+        while ( i-- )
+            ext_table_sum += ext_tablep[i];
+        if ( ext_table_sum )
+        {
+            printk(KERN_WARNING "microcode: aborting, "
+                   "bad extended signature table checksum\n");
+            return -EINVAL;
+        }
+    }
+
+    /* calculate the checksum */
+    orig_sum = 0;
+    i = (MC_HEADER_SIZE + data_size) / DWSIZE;
+    while ( i-- )
+        orig_sum += ((int *)mc)[i];
+    if ( orig_sum )
+    {
+        printk(KERN_ERR "microcode: aborting, bad checksum\n");
+        return -EINVAL;
+    }
+    if ( !ext_table_size )
+        return 0;
+    /* check extended signature checksum */
+    for ( i = 0; i < ext_sigcount; i++ )
+    {
+        ext_sig = (void *)ext_header + EXT_HEADER_SIZE +
+            EXT_SIGNATURE_SIZE * i;
+        sum = orig_sum
+            - (mc_header->sig + mc_header->pf + mc_header->cksum)
+            + (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
+        if ( sum )
+        {
+            printk(KERN_ERR "microcode: aborting, bad checksum\n");
+            return -EINVAL;
+        }
+    }
+    return 0;
+}
+
+/*
+ * return 0 - no update found
+ * return 1 - found update
+ * return < 0 - error
+ */
+static int get_matching_microcode(void *mc, int cpu)
+{
+    struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+    struct microcode_header_intel *mc_header = mc;
+    struct extended_sigtable *ext_header;
+    unsigned long total_size = get_totalsize(mc_header);
+    int ext_sigcount, i;
+    struct extended_signature *ext_sig;
+    void *new_mc;
+
+    if ( microcode_update_match(cpu, mc_header,
+                                mc_header->sig, mc_header->pf) )
+        goto find;
+
+    if ( total_size <= (get_datasize(mc_header) + MC_HEADER_SIZE) )
+        return 0;
+
+    ext_header = mc + get_datasize(mc_header) + MC_HEADER_SIZE;
+    ext_sigcount = ext_header->count;
+    ext_sig = (void *)ext_header + EXT_HEADER_SIZE;
+    for ( i = 0; i < ext_sigcount; i++ )
+    {
+        if ( microcode_update_match(cpu, mc_header,
+                                    ext_sig->sig, ext_sig->pf) )
+            goto find;
+        ext_sig++;
+    }
+    return 0;
+ find:
+    pr_debug("microcode: CPU%d found a matching microcode update with"
+             " version 0x%x (current=0x%x)\n",
+             cpu, mc_header->rev, uci->cpu_sig.rev);
+    new_mc = xmalloc_bytes(total_size);
+    if ( new_mc == NULL )
+    {
+        printk(KERN_ERR "microcode: error! Can not allocate memory\n");
+        return -ENOMEM;
+    }
+
+    /* free previous update file */
+    xfree(uci->mc.mc_intel);
+
+    memcpy(new_mc, mc, total_size);
+    uci->mc.mc_intel = new_mc;
+    return 1;
+}
+
+static int apply_microcode(int cpu)
+{
+    unsigned long flags;
+    unsigned int val[2];
+    int cpu_num = raw_smp_processor_id();
+    struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
+
+    /* We should bind the task to the CPU */
+    BUG_ON(cpu_num != cpu);
+
+    if ( uci->mc.mc_intel == NULL )
+        return -EINVAL;
+
+    /* serialize access to the physical write to MSR 0x79 */
+    spin_lock_irqsave(&microcode_update_lock, flags);
+
+    /* write microcode via MSR 0x79 */
+    wrmsr(MSR_IA32_UCODE_WRITE,
+          (unsigned long) uci->mc.mc_intel->bits,
+          (unsigned long) uci->mc.mc_intel->bits >> 16 >> 16);
+    wrmsr(MSR_IA32_UCODE_REV, 0, 0);
+
+    /* see notes above for revision 1.07.  Apparent chip bug */
+    sync_core();
+
+    /* get the current revision from MSR 0x8B */
+    rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
+
+    spin_unlock_irqrestore(&microcode_update_lock, flags);
+    if ( val[1] != uci->mc.mc_intel->hdr.rev )
+    {
+        printk(KERN_ERR "microcode: CPU%d update from revision "
+               "0x%x to 0x%x failed\n", cpu_num, uci->cpu_sig.rev, val[1]);
+        return -EIO;
+    }
+    printk(KERN_INFO "microcode: CPU%d updated from revision "
+           "0x%x to 0x%x, date = %04x-%02x-%02x \n",
+           cpu_num, uci->cpu_sig.rev, val[1],
+           uci->mc.mc_intel->hdr.date & 0xffff,
+           uci->mc.mc_intel->hdr.date >> 24,
+           (uci->mc.mc_intel->hdr.date >> 16) & 0xff);
+    uci->cpu_sig.rev = val[1];
+
+    return 0;
+}
+
+static long get_next_ucode_from_buffer(void **mc, const u8 *buf,
+                                       unsigned long size, long offset)
+{
+    struct microcode_header_intel *mc_header;
+    unsigned long total_size;
+
+    /* No more data */
+    if ( offset >= size )
+        return 0;
+    mc_header = (struct microcode_header_intel *)(buf + offset);
+    total_size = get_totalsize(mc_header);
+
+    if ( (offset + total_size) > size )
+    {
+        printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
+        return -EINVAL;
+    }
+
+    *mc = xmalloc_bytes(total_size);
+    if ( *mc == NULL )
+    {
+        printk(KERN_ERR "microcode: error! Can not allocate memory\n");
+        return -ENOMEM;
+    }
+    memcpy(*mc, (const void *)(buf + offset), total_size);
+    return offset + total_size;
+}
+
+static int cpu_request_microcode(int cpu, const void *buf, size_t size)
+{
+    long offset = 0;
+    int error = 0;
+    void *mc;
+
+    /* We should bind the task to the CPU */
+    BUG_ON(cpu != raw_smp_processor_id());
+
+    while ( (offset = get_next_ucode_from_buffer(&mc, buf, size, offset)) > 0 )
+    {
+        error = microcode_sanity_check(mc);
+        if ( error )
+            break;
+        error = get_matching_microcode(mc, cpu);
+        if ( error < 0 )
+            break;
+        /*
+         * It's possible the data file has multiple matching ucode,
+         * lets keep searching till the latest version
+         */
+        if ( error == 1 )
+        {
+            apply_microcode(cpu);
+            error = 0;
+        }
+        xfree(mc);
+    }
+    if ( offset > 0 )
+        xfree(mc);
+    if ( offset < 0 )
+        error = offset;
+
+    return error;
+}
+
+static struct microcode_ops microcode_intel_ops = {
+    .get_matching_microcode           = get_matching_microcode,
+    .cpu_request_microcode            = cpu_request_microcode,
+    .collect_cpu_info                 = collect_cpu_info,
+    .apply_microcode                  = apply_microcode,
+};
+
+static __init int microcode_init_intel(void)
+{
+    if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
+        microcode_ops = &microcode_intel_ops;
+    return 0;
+}
+__initcall(microcode_init_intel);
diff -r ec8eaab557d8 -r 4a381ddc764a xen/arch/x86/mm/shadow/common.c
--- a/xen/arch/x86/mm/shadow/common.c   Fri Sep 12 14:47:40 2008 +0900
+++ b/xen/arch/x86/mm/shadow/common.c   Tue Sep 16 21:25:30 2008 +0900
@@ -2385,11 +2385,13 @@ int sh_remove_write_access(struct vcpu *
                           + ((fault_addr & VADDR_MASK) >> 27), 3); break;
             }
 
-            /* 64bit Linux direct map at 0xffff810000000000; older kernels 
-             * had it at 0x0000010000000000UL */
+            /* 64bit Linux direct map at 0xffff880000000000; older kernels
+             * had it at 0xffff810000000000, and older kernels yet had it
+             * at 0x0000010000000000UL */
             gfn = mfn_to_gfn(v->domain, gmfn); 
-            GUESS(0xffff810000000000UL + (gfn << PAGE_SHIFT), 4); 
-            GUESS(0x0000010000000000UL + (gfn << PAGE_SHIFT), 4); 
+            GUESS(0xffff880000000000UL + (gfn << PAGE_SHIFT), 4);
+            GUESS(0xffff810000000000UL + (gfn << PAGE_SHIFT), 4);
+            GUESS(0x0000010000000000UL + (gfn << PAGE_SHIFT), 4);
             /*
              * 64bit Solaris kernel page map at
              * kpm_vbase; 0xfffffe0000000000UL
@@ -2462,22 +2464,25 @@ int sh_remove_write_access_from_sl1p(str
     ASSERT(mfn_valid(smfn));
     ASSERT(mfn_valid(gmfn));
     
-    if ( sp->type == SH_type_l1_32_shadow )
+    if ( sp->type == SH_type_l1_32_shadow
+         || sp->type == SH_type_fl1_32_shadow )
     {
         return SHADOW_INTERNAL_NAME(sh_rm_write_access_from_sl1p,2)
             (v, gmfn, smfn, off);
     }
 #if CONFIG_PAGING_LEVELS >= 3
-    else if ( sp->type == SH_type_l1_pae_shadow )
+    else if ( sp->type == SH_type_l1_pae_shadow
+              || sp->type == SH_type_fl1_pae_shadow )
         return SHADOW_INTERNAL_NAME(sh_rm_write_access_from_sl1p,3)
             (v, gmfn, smfn, off);
 #if CONFIG_PAGING_LEVELS >= 4
-    else if ( sp->type == SH_type_l1_64_shadow )
+    else if ( sp->type == SH_type_l1_64_shadow
+              || sp->type == SH_type_fl1_64_shadow )
         return SHADOW_INTERNAL_NAME(sh_rm_write_access_from_sl1p,4)
             (v, gmfn, smfn, off);
 #endif
 #endif
-    
+
     return 0;
 }
 #endif 
diff -r ec8eaab557d8 -r 4a381ddc764a xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c    Fri Sep 12 14:47:40 2008 +0900
+++ b/xen/arch/x86/mm/shadow/multi.c    Tue Sep 16 21:25:30 2008 +0900
@@ -4539,7 +4539,8 @@ int sh_rm_write_access_from_sl1p(struct 
     sp = mfn_to_shadow_page(smfn);
 
     if ( sp->mbz != 0
-         || (sp->type != SH_type_l1_shadow) )
+         || (sp->type != SH_type_l1_shadow
+             && sp->type != SH_type_fl1_shadow) )
         goto fail;
 
     sl1p = sh_map_domain_page(smfn);
diff -r ec8eaab557d8 -r 4a381ddc764a xen/arch/x86/platform_hypercall.c
--- a/xen/arch/x86/platform_hypercall.c Fri Sep 12 14:47:40 2008 +0900
+++ b/xen/arch/x86/platform_hypercall.c Tue Sep 16 21:25:30 2008 +0900
@@ -393,7 +393,6 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe
                 memcpy ((void *)&pxpt->status_register,
                     (void *)&xenpxpt->status_register,
                     sizeof(struct xen_pct_register));
-                pxpt->init |= XEN_PX_PCT;
             }
             if ( xenpxpt->flags & XEN_PX_PSS ) 
             {
@@ -411,7 +410,6 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe
                     break;
                 }
                 pxpt->state_count = xenpxpt->state_count;
-                pxpt->init |= XEN_PX_PSS;
             }
             if ( xenpxpt->flags & XEN_PX_PSD )
             {
@@ -419,27 +417,34 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe
                 memcpy ((void *)&pxpt->domain_info,
                     (void *)&xenpxpt->domain_info,
                     sizeof(struct xen_psd_package));
-                pxpt->init |= XEN_PX_PSD;
             }
             if ( xenpxpt->flags & XEN_PX_PPC )
             {
-                pxpt->ppc = xenpxpt->ppc;
-                pxpt->init |= XEN_PX_PPC;
-            }
-
-            if ( pxpt->init == ( XEN_PX_PCT | XEN_PX_PSS |
-                                 XEN_PX_PSD | XEN_PX_PPC ) )
-            {
-                pxpt->init |= XEN_PX_INIT;
+                pxpt->platform_limit = xenpxpt->platform_limit;
+
+                if ( pxpt->init == XEN_PX_INIT )
+                {
+                    ret = cpufreq_limit_change(cpuid);
+                    break;
+                }
+            }
+
+            if ( xenpxpt->flags == ( XEN_PX_PCT | XEN_PX_PSS |
+                                     XEN_PX_PSD | XEN_PX_PPC ) )
+            {
+                pxpt->init = XEN_PX_INIT;
                 cpu_count++;
-            }
-            if ( cpu_count == num_online_cpus() )
-            {
-                if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD )
+
+                /* Currently we only handle Intel and AMD processor */
+                if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
+                    ret = cpufreq_add_cpu(cpuid);
+                else if ( (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) &&
+                    (cpu_count == num_online_cpus()) )
                     ret = powernow_cpufreq_init();
                 else
-                    ret = acpi_cpufreq_init();
-            }
+                    break;
+            }
+
             break;
         }
  
diff -r ec8eaab557d8 -r 4a381ddc764a xen/arch/x86/smpboot.c
--- a/xen/arch/x86/smpboot.c    Fri Sep 12 14:47:40 2008 +0900
+++ b/xen/arch/x86/smpboot.c    Tue Sep 16 21:25:30 2008 +0900
@@ -55,6 +55,7 @@
 #include <mach_wakecpu.h>
 #include <smpboot_hooks.h>
 #include <xen/stop_machine.h>
+#include <acpi/cpufreq/processor_perf.h>
 
 #define set_kernel_exec(x, y) (0)
 #define setup_trampoline()    (bootsym_phys(trampoline_realmode_entry))
@@ -1232,6 +1233,8 @@ int __cpu_disable(void)
        mdelay(1);
        local_irq_disable();
 
+       cpufreq_del_cpu(cpu);
+
        time_suspend();
 
        remove_siblinginfo(cpu);
@@ -1421,6 +1424,8 @@ int __devinit __cpu_up(unsigned int cpu)
                mb();
                process_pending_timers();
        }
+
+       cpufreq_add_cpu(cpu);
        return 0;
 }
 
diff -r ec8eaab557d8 -r 4a381ddc764a xen/common/gdbstub.c
--- a/xen/common/gdbstub.c      Fri Sep 12 14:47:40 2008 +0900
+++ b/xen/common/gdbstub.c      Tue Sep 16 21:25:30 2008 +0900
@@ -65,7 +65,7 @@ static void gdb_smp_pause(void);
 static void gdb_smp_pause(void);
 static void gdb_smp_resume(void);
 
-static char opt_gdb[30] = "none";
+static char opt_gdb[30];
 string_param("gdb", opt_gdb);
 
 static void gdbstub_console_puts(const char *str);
@@ -625,10 +625,19 @@ void __init
 void __init
 initialise_gdb(void)
 {
+    if ( *opt_gdb == '\0' )
+        return;
+
     gdb_ctx->serhnd = serial_parse_handle(opt_gdb);
-    if ( gdb_ctx->serhnd != -1 )
-        printk("GDB stub initialised.\n");
+    if ( gdb_ctx->serhnd == -1 )
+    {
+        printk("Bad gdb= option '%s'\n", opt_gdb);
+        return;
+    }
+
     serial_start_sync(gdb_ctx->serhnd);
+
+    printk("GDB stub initialised.\n");
 }
 
 static void gdb_pause_this_cpu(void *unused)
diff -r ec8eaab557d8 -r 4a381ddc764a xen/drivers/char/console.c
--- a/xen/drivers/char/console.c        Fri Sep 12 14:47:40 2008 +0900
+++ b/xen/drivers/char/console.c        Tue Sep 16 21:25:30 2008 +0900
@@ -543,10 +543,18 @@ void __init init_console(void)
     {
         if ( *p == ',' )
             p++;
-        if ( strncmp(p, "com", 3) == 0 )
-            sercon_handle = serial_parse_handle(p);
-        else if ( strncmp(p, "vga", 3) == 0 )
+        if ( !strncmp(p, "vga", 3) )
             vga_init();
+        else if ( strncmp(p, "com", 3) ||
+                  (sercon_handle = serial_parse_handle(p)) == -1 )
+        {
+            char *q = strchr(p, ',');
+            if ( q != NULL )
+                *q = '\0';
+            printk("Bad console= option '%s'\n", p);
+            if ( q != NULL )
+                *q = ',';
+        }
     }
 
     serial_set_rx_handler(sercon_handle, serial_rx);
diff -r ec8eaab557d8 -r 4a381ddc764a xen/drivers/char/ns16550.c
--- a/xen/drivers/char/ns16550.c        Fri Sep 12 14:47:40 2008 +0900
+++ b/xen/drivers/char/ns16550.c        Tue Sep 16 21:25:30 2008 +0900
@@ -82,6 +82,7 @@ static struct ns16550 {
 #define MCR_DTR         0x01    /* Data Terminal Ready  */
 #define MCR_RTS         0x02    /* Request to Send      */
 #define MCR_OUT2        0x08    /* OUT2: interrupt mask */
+#define MCR_LOOP        0x10    /* Enable loopback test mode */
 
 /* Line Status Register */
 #define LSR_DR          0x01    /* Data ready           */
@@ -293,6 +294,37 @@ static int __init parse_parity_char(int 
         return PARITY_SPACE;
     }
     return 0;
+}
+
+static int check_existence(struct ns16550 *uart)
+{
+    unsigned char status, scratch, scratch2, scratch3;
+
+    /*
+     * Do a simple existence test first; if we fail this,
+     * there's no point trying anything else.
+     */
+    scratch = ns_read_reg(uart, IER);
+    ns_write_reg(uart, IER, 0);
+
+    /*
+     * Mask out IER[7:4] bits for test as some UARTs (e.g. TL
+     * 16C754B) allow only to modify them if an EFR bit is set.
+     */
+    scratch2 = ns_read_reg(uart, IER) & 0x0f;
+    ns_write_reg(uart, IER, 0x0F);
+    scratch3 = ns_read_reg(uart, IER) & 0x0f;
+    ns_write_reg(uart, IER, scratch);
+    if ( (scratch2 != 0) || (scratch3 != 0x0F) )
+        return 0;
+
+    /*
+     * Check to see if a UART is really there.
+     * Use loopback test mode.
+     */
+    ns_write_reg(uart, MCR, MCR_LOOP | 0x0A);
+    status = ns_read_reg(uart, MSR) & 0xF0;
+    return (status == 0x90);
 }
 
 #define PARSE_ERR(_f, _a...)                 \
@@ -357,6 +389,8 @@ static void __init ns16550_parse_port_co
         PARSE_ERR("%d stop bits are unsupported.", uart->stop_bits);
     if ( uart->io_base == 0 )
         PARSE_ERR("I/O base address must be specified.");
+    if ( !check_existence(uart) )
+        PARSE_ERR("16550-compatible serial UART not present");
 
     /* Register with generic serial driver. */
     serial_register_uart(uart - ns16550_com, &ns16550_driver, uart);
diff -r ec8eaab557d8 -r 4a381ddc764a xen/drivers/char/serial.c
--- a/xen/drivers/char/serial.c Fri Sep 12 14:47:40 2008 +0900
+++ b/xen/drivers/char/serial.c Tue Sep 16 21:25:30 2008 +0900
@@ -258,11 +258,7 @@ int serial_parse_handle(char *conf)
 {
     int handle;
 
-    /* Silently fail if user has explicitly requested no serial I/O. */
-    if ( strcmp(conf, "none") == 0 )
-        return -1;
-
-    if ( strncmp(conf, "com", 3) != 0 )
+    if ( strncmp(conf, "com", 3) )
         goto fail;
 
     switch ( conf[3] )
@@ -277,6 +273,9 @@ int serial_parse_handle(char *conf)
         goto fail;
     }
 
+    if ( !com[handle].driver )
+        goto fail;
+
     if ( conf[4] == 'H' )
         handle |= SERHND_HI;
     else if ( conf[4] == 'L' )
@@ -287,7 +286,6 @@ int serial_parse_handle(char *conf)
     return handle;
 
  fail:
-    printk("ERROR: bad serial-interface specification '%s'\n", conf);
     return -1;
 }
 
diff -r ec8eaab557d8 -r 4a381ddc764a xen/drivers/passthrough/vtd/iommu.c
--- a/xen/drivers/passthrough/vtd/iommu.c       Fri Sep 12 14:47:40 2008 +0900
+++ b/xen/drivers/passthrough/vtd/iommu.c       Tue Sep 16 21:25:30 2008 +0900
@@ -152,6 +152,7 @@ static u64 bus_to_context_maddr(struct i
         maddr = alloc_pgtable_maddr();
         if ( maddr == 0 )
         {
+            unmap_vtd_domain_page(root_entries);
             spin_unlock_irqrestore(&iommu->lock, flags);
             return 0;
         }
diff -r ec8eaab557d8 -r 4a381ddc764a xen/include/acpi/cpufreq/cpufreq.h
--- a/xen/include/acpi/cpufreq/cpufreq.h        Fri Sep 12 14:47:40 2008 +0900
+++ b/xen/include/acpi/cpufreq/cpufreq.h        Tue Sep 16 21:25:30 2008 +0900
@@ -18,6 +18,8 @@
 #include "processor_perf.h"
 
 #define CPUFREQ_NAME_LEN 16
+
+struct cpufreq_governor;
 
 struct cpufreq_cpuinfo {
     unsigned int        max_freq;
@@ -30,16 +32,21 @@ struct cpufreq_policy {
     unsigned int        shared_type;   /* ANY or ALL affected CPUs
                                           should set cpufreq */
     unsigned int        cpu;           /* cpu nr of registered CPU */
-    struct cpufreq_cpuinfo    cpuinfo; /* see above */
+    struct cpufreq_cpuinfo    cpuinfo;
 
     unsigned int        min;    /* in kHz */
     unsigned int        max;    /* in kHz */
     unsigned int        cur;    /* in kHz, only needed if cpufreq
                                  * governors are used */
+    struct cpufreq_governor     *governor;
+
     unsigned int        resume; /* flag for cpufreq 1st run
                                  * S3 wakeup, hotplug cpu, etc */
 };
-extern struct cpufreq_policy xen_px_policy[NR_CPUS];
+extern struct cpufreq_policy *cpufreq_cpu_policy[NR_CPUS];
+
+extern int __cpufreq_set_policy(struct cpufreq_policy *data,
+                                struct cpufreq_policy *policy);
 
 #define CPUFREQ_SHARED_TYPE_NONE (0) /* None */
 #define CPUFREQ_SHARED_TYPE_HW   (1) /* HW does needed coordination */
@@ -64,11 +71,26 @@ struct cpufreq_freqs {
 #define CPUFREQ_GOV_STOP   2
 #define CPUFREQ_GOV_LIMITS 3
 
+struct cpufreq_governor {
+    char    name[CPUFREQ_NAME_LEN];
+    int     (*governor)(struct cpufreq_policy *policy,
+                        unsigned int event);
+};
+
+extern struct cpufreq_governor cpufreq_gov_dbs;
+#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_dbs
+
 /* pass a target to the cpufreq driver */
 extern int __cpufreq_driver_target(struct cpufreq_policy *policy,
                                    unsigned int target_freq,
                                    unsigned int relation);
 extern int __cpufreq_driver_getavg(struct cpufreq_policy *policy);
+
+static __inline__ int 
+__cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
+{
+    return policy->governor->governor(policy, event);
+}
 
 
 /*********************************************************************
@@ -91,7 +113,50 @@ struct cpufreq_driver {
 
 extern struct cpufreq_driver *cpufreq_driver;
 
-void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int 
state);
+static __inline__ 
+int cpufreq_register_driver(struct cpufreq_driver *driver_data)
+{
+    if (!driver_data         || 
+        !driver_data->init   || 
+        !driver_data->exit   || 
+        !driver_data->verify || 
+        !driver_data->target)
+        return -EINVAL;
+
+    if (cpufreq_driver)
+        return -EBUSY;
+
+    cpufreq_driver = driver_data;
+    return 0;
+}
+
+static __inline__ 
+int cpufreq_unregister_driver(struct cpufreq_driver *driver)
+{
+    if (!cpufreq_driver || (driver != cpufreq_driver))
+        return -EINVAL;
+
+    cpufreq_driver = NULL;
+    return 0;
+}
+
+static __inline__
+void cpufreq_verify_within_limits(struct cpufreq_policy *policy,
+                                  unsigned int min, unsigned int max)
+{
+    if (policy->min < min)
+        policy->min = min;
+    if (policy->max < min)
+        policy->max = min;
+    if (policy->min > max)
+        policy->min = max;
+    if (policy->max > max)
+        policy->max = max;
+    if (policy->min > policy->max)
+        policy->min = policy->max;
+    return;
+}
+
 
 /*********************************************************************
  *                     FREQUENCY TABLE HELPERS                       *
@@ -107,6 +172,9 @@ struct cpufreq_frequency_table {
 };
 
 int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
+                   struct cpufreq_frequency_table *table);
+
+int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
                    struct cpufreq_frequency_table *table);
 
 int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
diff -r ec8eaab557d8 -r 4a381ddc764a xen/include/acpi/cpufreq/processor_perf.h
--- a/xen/include/acpi/cpufreq/processor_perf.h Fri Sep 12 14:47:40 2008 +0900
+++ b/xen/include/acpi/cpufreq/processor_perf.h Tue Sep 16 21:25:30 2008 +0900
@@ -7,26 +7,23 @@
 #define XEN_PX_INIT 0x80000000
 
 int get_cpu_id(u8);
-int acpi_cpufreq_init(void);
 int powernow_cpufreq_init(void);
 
 void px_statistic_update(cpumask_t, uint8_t, uint8_t);
-int  px_statistic_init(int);
-void px_statistic_reset(int);
-void px_statistic_suspend(void);
-void px_statistic_resume(void);
+int  px_statistic_init(unsigned int);
+void px_statistic_exit(unsigned int);
+void px_statistic_reset(unsigned int);
 
-void cpufreq_dom_exit(void);
-int  cpufreq_dom_init(void);
-int  cpufreq_dom_dbs(unsigned int);
-void cpufreq_suspend(void);
-int  cpufreq_resume(void);
+int  cpufreq_limit_change(unsigned int);
+
+int  cpufreq_add_cpu(unsigned int);
+int  cpufreq_del_cpu(unsigned int);
 
 uint64_t get_cpu_idle_time(unsigned int);
 
 struct processor_performance {
     uint32_t state;
-    uint32_t ppc;
+    uint32_t platform_limit;
     struct xen_pct_register control_register;
     struct xen_pct_register status_register;
     uint32_t state_count;
diff -r ec8eaab557d8 -r 4a381ddc764a xen/include/asm-x86/microcode.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-x86/microcode.h   Tue Sep 16 21:25:30 2008 +0900
@@ -0,0 +1,93 @@
+#ifndef ASM_X86__MICROCODE_H
+#define ASM_X86__MICROCODE_H
+
+struct cpu_signature;
+
+struct microcode_ops {
+    int (*get_matching_microcode)(void *mc, int cpu);
+    int (*cpu_request_microcode)(int cpu, const void *buf, size_t size);
+    int (*collect_cpu_info)(int cpu_num, struct cpu_signature *csig);
+    int (*apply_microcode)(int cpu);
+};
+
+struct microcode_header_intel {
+    unsigned int hdrver;
+    unsigned int rev;
+    unsigned int date;
+    unsigned int sig;
+    unsigned int cksum;
+    unsigned int ldrver;
+    unsigned int pf;
+    unsigned int datasize;
+    unsigned int totalsize;
+    unsigned int reserved[3];
+};
+
+struct microcode_intel {
+    struct microcode_header_intel hdr;
+    unsigned int bits[0];
+};
+
+/* microcode format is extended from prescott processors */
+struct extended_signature {
+    unsigned int sig;
+    unsigned int pf;
+    unsigned int cksum;
+};
+
+struct extended_sigtable {
+    unsigned int count;
+    unsigned int cksum;
+    unsigned int reserved[3];
+    struct extended_signature sigs[0];
+};
+
+struct equiv_cpu_entry {
+    unsigned int installed_cpu;
+    unsigned int fixed_errata_mask;
+    unsigned int fixed_errata_compare;
+    unsigned int equiv_cpu;
+};
+
+struct microcode_header_amd {
+    unsigned int  data_code;
+    unsigned int  patch_id;
+    unsigned char mc_patch_data_id[2];
+    unsigned char mc_patch_data_len;
+    unsigned char init_flag;
+    unsigned int  mc_patch_data_checksum;
+    unsigned int  nb_dev_id;
+    unsigned int  sb_dev_id;
+    unsigned char processor_rev_id[2];
+    unsigned char nb_rev_id;
+    unsigned char sb_rev_id;
+    unsigned char bios_api_rev;
+    unsigned char reserved1[3];
+    unsigned int  match_reg[8];
+};
+
+struct microcode_amd {
+    struct microcode_header_amd hdr;
+    unsigned int mpb[0];
+};
+
+struct cpu_signature {
+    unsigned int sig;
+    unsigned int pf;
+    unsigned int rev;
+};
+
+struct ucode_cpu_info {
+    struct cpu_signature cpu_sig;
+    int valid;
+    union {
+        struct microcode_intel *mc_intel;
+        struct microcode_amd *mc_amd;
+        void *valid_mc;
+    } mc;
+};
+
+extern struct ucode_cpu_info ucode_cpu_info[];
+extern const struct microcode_ops *microcode_ops;
+
+#endif /* ASM_X86__MICROCODE_H */
diff -r ec8eaab557d8 -r 4a381ddc764a xen/include/asm-x86/msr-index.h
--- a/xen/include/asm-x86/msr-index.h   Fri Sep 12 14:47:40 2008 +0900
+++ b/xen/include/asm-x86/msr-index.h   Tue Sep 16 21:25:30 2008 +0900
@@ -210,6 +210,10 @@
 #define FAM10H_MMIO_CONF_BUSRANGE_SHIFT 2
 #define FAM10H_MMIO_CONF_BASE_MASK     0xfffffff
 #define FAM10H_MMIO_CONF_BASE_SHIFT    20
+
+/* AMD Microcode MSRs */
+#define MSR_AMD_PATCHLEVEL             0x0000008b
+#define MSR_AMD_PATCHLOADER            0xc0010020
 
 /* K6 MSRs */
 #define MSR_K6_EFER                    0xc0000080
diff -r ec8eaab557d8 -r 4a381ddc764a xen/include/asm-x86/processor.h
--- a/xen/include/asm-x86/processor.h   Fri Sep 12 14:47:40 2008 +0900
+++ b/xen/include/asm-x86/processor.h   Tue Sep 16 21:25:30 2008 +0900
@@ -486,41 +486,6 @@ long set_gdt(struct vcpu *d,
 })
 long set_debugreg(struct vcpu *p, int reg, unsigned long value);
 
-struct microcode_header {
-    unsigned int hdrver;
-    unsigned int rev;
-    unsigned int date;
-    unsigned int sig;
-    unsigned int cksum;
-    unsigned int ldrver;
-    unsigned int pf;
-    unsigned int datasize;
-    unsigned int totalsize;
-    unsigned int reserved[3];
-};
-
-struct microcode {
-    struct microcode_header hdr;
-    unsigned int bits[0];
-};
-
-typedef struct microcode microcode_t;
-typedef struct microcode_header microcode_header_t;
-
-/* microcode format is extended from prescott processors */
-struct extended_signature {
-    unsigned int sig;
-    unsigned int pf;
-    unsigned int cksum;
-};
-
-struct extended_sigtable {
-    unsigned int count;
-    unsigned int cksum;
-    unsigned int reserved[3];
-    struct extended_signature sigs[0];
-};
-
 /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
 static always_inline void rep_nop(void)
 {
diff -r ec8eaab557d8 -r 4a381ddc764a xen/include/public/platform.h
--- a/xen/include/public/platform.h     Fri Sep 12 14:47:40 2008 +0900
+++ b/xen/include/public/platform.h     Tue Sep 16 21:25:30 2008 +0900
@@ -289,7 +289,7 @@ struct xen_psd_package {
 
 struct xen_processor_performance {
     uint32_t flags;     /* flag for Px sub info type */
-    uint32_t ppc;       /* Platform limitation on freq usage */
+    uint32_t platform_limit;  /* Platform limitation on freq usage */
     struct xen_pct_register control_register;
     struct xen_pct_register status_register;
     uint32_t state_count;     /* total available performance states */

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

<Prev in Thread] Current Thread [Next in Thread>