ia64/xen-unstable
changeset 18500:4a381ddc764a
merge with xen-unstable.hg
author | Isaku Yamahata <yamahata@valinux.co.jp> |
---|---|
date | Tue Sep 16 21:25:30 2008 +0900 (2008-09-16) |
parents | ec8eaab557d8 3eb7a0cfffc2 |
children | 3d96f88fb220 d7be37824fe0 |
files |
line diff
1.1 --- a/Config.mk Fri Sep 12 14:47:40 2008 +0900 1.2 +++ b/Config.mk Tue Sep 16 21:25:30 2008 +0900 1.3 @@ -54,6 +54,22 @@ define cc-ver-check-closure 1.4 endif 1.5 endef 1.6 1.7 +define absolutify_xen_root 1.8 + case "$(XEN_ROOT)" in \ 1.9 + /*) XEN_ROOT=$(XEN_ROOT) ;; \ 1.10 + *) xen_root_lhs=`pwd`; \ 1.11 + xen_root_rhs=$(XEN_ROOT)/; \ 1.12 + while [ "x$${xen_root_rhs#../}" != "x$$xen_root_rhs" ]; do \ 1.13 + xen_root_rhs="$${xen_root_rhs#../}"; \ 1.14 + xen_root_rhs="$${xen_root_rhs#/}"; \ 1.15 + xen_root_rhs="$${xen_root_rhs#/}"; \ 1.16 + xen_root_lhs="$${xen_root_lhs%/*}"; \ 1.17 + done; \ 1.18 + XEN_ROOT="$$xen_root_lhs/$$xen_root_rhs" ;; \ 1.19 + esac; \ 1.20 + export XEN_ROOT 1.21 +endef 1.22 + 1.23 ifeq ($(debug),y) 1.24 CFLAGS += -g 1.25 endif
2.1 --- a/Makefile Fri Sep 12 14:47:40 2008 +0900 2.2 +++ b/Makefile Tue Sep 16 21:25:30 2008 +0900 2.3 @@ -64,7 +64,7 @@ install-xen: 2.4 $(MAKE) -C xen install 2.5 2.6 .PHONY: install-tools 2.7 -install-tools: 2.8 +install-tools: tools/ioemu-dir 2.9 $(MAKE) -C tools install 2.10 2.11 .PHONY: install-kernels 2.12 @@ -72,12 +72,15 @@ install-kernels: 2.13 for i in $(XKERNELS) ; do $(MAKE) $$i-install || exit 1; done 2.14 2.15 .PHONY: install-stubdom 2.16 -install-stubdom: 2.17 +install-stubdom: tools/ioemu-dir 2.18 $(MAKE) -C stubdom install 2.19 ifeq (x86_64,$(XEN_TARGET_ARCH)) 2.20 XEN_TARGET_ARCH=x86_32 $(MAKE) -C stubdom install-grub 2.21 endif 2.22 2.23 +tools/ioemu-dir: 2.24 + make -C tools ioemu-dir-find 2.25 + 2.26 .PHONY: install-docs 2.27 install-docs: 2.28 sh ./docs/check_pkgs && $(MAKE) -C docs install || true
3.1 --- a/stubdom/Makefile Fri Sep 12 14:47:40 2008 +0900 3.2 +++ b/stubdom/Makefile Tue Sep 16 21:25:30 2008 +0900 3.3 @@ -7,8 +7,6 @@ export stubdom=y 3.4 export debug=y 3.5 include $(XEN_ROOT)/Config.mk 3.6 3.7 -override CONFIG_QEMU=ioemu 3.8 - 3.9 IOEMU_OPTIONS=--disable-sdl --disable-opengl --disable-vnc-tls --disable-brlapi --disable-kqemu 3.10 ZLIB_URL?=http://www.zlib.net 3.11 ZLIB_VERSION=1.2.3 3.12 @@ -59,8 +57,8 @@ TARGET_CPPFLAGS += -nostdinc 3.13 TARGET_CPPFLAGS += -isystem $(CURDIR)/$(MINI_OS)/include/posix 3.14 TARGET_CPPFLAGS += -isystem $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/include 3.15 TARGET_CPPFLAGS += -isystem $(GCC_INSTALL)include 3.16 -TARGET_CPPFLAGS += -isystem $(CURDIR)/lwip/src/include 3.17 -TARGET_CPPFLAGS += -isystem $(CURDIR)/lwip/src/include/ipv4 3.18 +TARGET_CPPFLAGS += -isystem $(CURDIR)/lwip-$(XEN_TARGET_ARCH)/src/include 3.19 +TARGET_CPPFLAGS += -isystem $(CURDIR)/lwip-$(XEN_TARGET_ARCH)/src/include/ipv4 3.20 TARGET_CPPFLAGS += -I$(CURDIR)/include 3.21 3.22 TARGET_LDFLAGS += -nostdlib -L$(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/lib 3.23 @@ -164,7 +162,29 @@ lwip-$(XEN_TARGET_ARCH): lwip-$(LWIP_VER 3.24 .PHONY: $(CROSS_ROOT) 3.25 $(CROSS_ROOT): cross-newlib cross-zlib cross-libpci 3.26 3.27 -mk-headers-$(XEN_TARGET_ARCH): 3.28 +$(XEN_ROOT)/tools/ioemu-dir: 3.29 + make -C $(XEN_ROOT)/tools ioemu-dir-find 3.30 + 3.31 +ioemu/linkfarm.stamp: $(XEN_ROOT)/tools/ioemu-dir 3.32 + mkdir -p ioemu 3.33 +ifeq ($(CONFIG_QEMU),ioemu) 3.34 + [ -h ioemu/Makefile ] || ( cd ioemu && \ 3.35 + ln -sf ../$(XEN_ROOT)/tools/ioemu/* .) 3.36 +else 3.37 + set -e; \ 3.38 + $(absolutify_xen_root); \ 3.39 + cd ioemu; \ 3.40 + src="$$XEN_ROOT/tools/ioemu-dir"; export src; \ 3.41 + (cd $$src && find * -type d -print) | xargs mkdir -p; \ 3.42 + (cd $$src && find * ! -type l -type f $(addprefix ! -name , \ 3.43 + '*.[oda1]' 'config-*' config.mak qemu-dm qemu-img-xen \ 3.44 + '*.html' '*.pod' \ 3.45 + )) | \ 3.46 + while read f; do rm -f "$$f"; ln -s "$$src/$$f" "$$f"; done 3.47 +endif 3.48 + touch ioemu/linkfarm.stamp 3.49 + 3.50 +mk-headers-$(XEN_TARGET_ARCH): ioemu/linkfarm.stamp 3.51 mkdir -p include/xen && \ 3.52 ln -sf $(addprefix ../../,$(wildcard $(XEN_ROOT)/xen/include/public/*.h)) include/xen && \ 3.53 ln -sf $(addprefix ../../$(XEN_ROOT)/xen/include/public/,arch-ia64 arch-x86 hvm io xsm) include/xen && \ 3.54 @@ -183,22 +203,6 @@ mk-headers-$(XEN_TARGET_ARCH): 3.55 ln -sf ../$(XEN_ROOT)/tools/libxc/$(XEN_TARGET_ARCH)/*.c . && \ 3.56 ln -sf ../$(XEN_ROOT)/tools/libxc/$(XEN_TARGET_ARCH)/*.h . && \ 3.57 ln -sf ../$(XEN_ROOT)/tools/libxc/$(XEN_TARGET_ARCH)/Makefile . ) 3.58 - mkdir -p ioemu 3.59 -ifeq ($(CONFIG_QEMU),ioemu) 3.60 - [ -h ioemu/Makefile ] || ( cd ioemu && \ 3.61 - ln -sf ../$(XEN_ROOT)/tools/ioemu/* .) 3.62 -else 3.63 - [ -h ioemu/Makefile ] || ( cd ioemu && \ 3.64 - ln -sf $(CONFIG_QEMU)/* . && \ 3.65 - rm -fr i386-dm && \ 3.66 - rm -fr i386-stubdom && \ 3.67 - mkdir i386-dm && \ 3.68 - mkdir i386-stubdom && \ 3.69 - ln -sf $(CONFIG_QEMU)/i386-dm/* i386-dm/ && \ 3.70 - ln -sf $(CONFIG_QEMU)/i386-stubdom/* i386-stubdom/ ) 3.71 -endif 3.72 - [ ! -h ioemu/config-host.h ] || rm -f ioemu/config-host.h 3.73 - [ ! -h ioemu/config-host.mak ] || rm -f ioemu/config-host.mak 3.74 $(MAKE) -C $(MINI_OS) links 3.75 touch mk-headers-$(XEN_TARGET_ARCH) 3.76 3.77 @@ -231,8 +235,9 @@ ifeq ($(CONFIG_QEMU),ioemu) 3.78 CPPFLAGS="$(TARGET_CPPFLAGS)" $(MAKE) -C ioemu LWIPDIR=$(CURDIR)/lwip-$(XEN_TARGET_ARCH) TOOLS= 3.79 else 3.80 [ -f ioemu/config-host.mak ] || \ 3.81 - ( cd ioemu ; \ 3.82 - 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)) 3.83 + ( $(absolutify_xen_root); \ 3.84 + cd ioemu ; \ 3.85 + CONFIG_STUBDOM=yes XEN_TARGET_ARCH=$(XEN_TARGET_ARCH) CFLAGS="$(TARGET_CFLAGS)" sh ./xen-setup --cc=$(CC) --disable-gcc-check $(IOEMU_OPTIONS)) 3.86 CPPFLAGS= TARGET_CPPFLAGS="$(TARGET_CPPFLAGS)" $(MAKE) -C ioemu LWIPDIR=$(CURDIR)/lwip-$(XEN_TARGET_ARCH) TOOLS= CONFIG_STUBDOM=yes 3.87 endif 3.88 3.89 @@ -336,7 +341,7 @@ clean: 3.90 $(MAKE) -C c clean 3.91 rm -fr grub-$(XEN_TARGET_ARCH) 3.92 [ ! -d libxc-$(XEN_TARGET_ARCH) ] || $(MAKE) -C libxc-$(XEN_TARGET_ARCH) clean 3.93 - [ ! -d ioemu ] || $(MAKE) -C ioemu clean 3.94 + -[ ! -d ioemu ] || $(MAKE) -C ioemu clean 3.95 3.96 # clean the cross-compilation result 3.97 .PHONY: crossclean
4.1 --- a/tools/Makefile Fri Sep 12 14:47:40 2008 +0900 4.2 +++ b/tools/Makefile Tue Sep 16 21:25:30 2008 +0900 4.3 @@ -93,17 +93,14 @@ ioemu-dir-find: 4.4 ln -sf ioemu-remote ioemu-dir; \ 4.5 fi 4.6 set -e; \ 4.7 - case "$(XEN_ROOT)" in \ 4.8 - /*) XEN_ROOT=$(XEN_ROOT) ;; \ 4.9 - *) XEN_ROOT=`pwd`/$(XEN_ROOT) ;; \ 4.10 - esac; \ 4.11 - export XEN_ROOT; \ 4.12 + $(absolutify_xen_root); \ 4.13 cd ioemu-dir; \ 4.14 ./xen-setup $(IOEMU_CONFIGURE_CROSS) 4.15 4.16 subdir-all-ioemu-dir subdir-install-ioemu-dir: ioemu-dir-find 4.17 4.18 subdir-clean-ioemu-dir: 4.19 - if test -d ioemu-dir/.; then \ 4.20 + set -e; if test -d ioemu-dir/.; then \ 4.21 + $(absolutify_xen_root); \ 4.22 $(MAKE) -C ioemu-dir clean; \ 4.23 fi
5.1 --- a/tools/python/xen/util/xsm/dummy/dummy.py Fri Sep 12 14:47:40 2008 +0900 5.2 +++ b/tools/python/xen/util/xsm/dummy/dummy.py Tue Sep 16 21:25:30 2008 +0900 5.3 @@ -131,3 +131,6 @@ def dump_policy_file(): 5.4 5.5 def get_ssid(domain): 5.6 err("No ssid has been assigned to any domain under xsm dummy module.") 5.7 + 5.8 +def security_label_to_details(res_label): 5.9 + return ("","","")
6.1 --- a/xen/arch/x86/Makefile Fri Sep 12 14:47:40 2008 +0900 6.2 +++ b/xen/arch/x86/Makefile Tue Sep 16 21:25:30 2008 +0900 6.3 @@ -28,6 +28,8 @@ obj-y += msi.o 6.4 obj-y += ioport_emulate.o 6.5 obj-y += irq.o 6.6 obj-y += microcode.o 6.7 +obj-y += microcode_amd.o 6.8 +obj-y += microcode_intel.o 6.9 obj-y += mm.o 6.10 obj-y += mpparse.o 6.11 obj-y += nmi.o
7.1 --- a/xen/arch/x86/acpi/cpufreq/cpufreq.c Fri Sep 12 14:47:40 2008 +0900 7.2 +++ b/xen/arch/x86/acpi/cpufreq/cpufreq.c Tue Sep 16 21:25:30 2008 +0900 7.3 @@ -32,6 +32,7 @@ 7.4 #include <xen/errno.h> 7.5 #include <xen/delay.h> 7.6 #include <xen/cpumask.h> 7.7 +#include <xen/sched.h> 7.8 #include <xen/timer.h> 7.9 #include <xen/xmalloc.h> 7.10 #include <asm/bug.h> 7.11 @@ -44,12 +45,8 @@ 7.12 #include <acpi/acpi.h> 7.13 #include <acpi/cpufreq/cpufreq.h> 7.14 7.15 -struct processor_pminfo processor_pminfo[NR_CPUS]; 7.16 -struct cpufreq_policy xen_px_policy[NR_CPUS]; 7.17 - 7.18 -static cpumask_t *cpufreq_dom_pt; 7.19 -static unsigned long *cpufreq_dom_mask; 7.20 -static unsigned int cpufreq_dom_max; 7.21 +/* TODO: change to link list later as domain number may be sparse */ 7.22 +static cpumask_t cpufreq_dom_map[NR_CPUS]; 7.23 7.24 enum { 7.25 UNDEFINED_CAPABLE = 0, 7.26 @@ -335,7 +332,7 @@ static int acpi_cpufreq_target(struct cp 7.27 if (unlikely(result)) 7.28 return -ENODEV; 7.29 7.30 - online_policy_cpus = policy->cpus; 7.31 + cpus_and(online_policy_cpus, cpu_online_map, policy->cpus); 7.32 7.33 next_perf_state = data->freq_table[next_state].index; 7.34 if (perf->state == next_perf_state) { 7.35 @@ -390,6 +387,20 @@ static int acpi_cpufreq_target(struct cp 7.36 return result; 7.37 } 7.38 7.39 +static int acpi_cpufreq_verify(struct cpufreq_policy *policy) 7.40 +{ 7.41 + struct acpi_cpufreq_data *data = drv_data[policy->cpu]; 7.42 + struct processor_performance *perf = &processor_pminfo[policy->cpu].perf; 7.43 + 7.44 + if (!policy || !data) 7.45 + return -EINVAL; 7.46 + 7.47 + cpufreq_verify_within_limits(policy, 0, 7.48 + perf->states[perf->platform_limit].core_frequency * 1000); 7.49 + 7.50 + return cpufreq_frequency_table_verify(policy, data->freq_table); 7.51 +} 7.52 + 7.53 static unsigned long 7.54 acpi_cpufreq_guess_freq(struct acpi_cpufreq_data *data, unsigned int cpu) 7.55 { 7.56 @@ -441,14 +452,6 @@ acpi_cpufreq_cpu_init(struct cpufreq_pol 7.57 perf = data->acpi_data; 7.58 policy->shared_type = perf->shared_type; 7.59 7.60 - /* 7.61 - * Currently the latest linux (kernel version 2.6.26) 7.62 - * still has issue when handle the situation _psd HW_ALL coordination. 7.63 - * In Xen hypervisor, we handle _psd HW_ALL coordination in same way as 7.64 - * _psd SW_ALL coordination for the seek of safety. 7.65 - */ 7.66 - policy->cpus = perf->shared_cpu_map; 7.67 - 7.68 /* capability check */ 7.69 if (perf->state_count <= 1) { 7.70 printk("No P-States\n"); 7.71 @@ -496,6 +499,7 @@ acpi_cpufreq_cpu_init(struct cpufreq_pol 7.72 policy->cpuinfo.transition_latency = 7.73 perf->states[i].transition_latency * 1000; 7.74 } 7.75 + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; 7.76 7.77 data->max_freq = perf->states[0].core_frequency * 1000; 7.78 /* table init */ 7.79 @@ -554,114 +558,173 @@ err_unreg: 7.80 return result; 7.81 } 7.82 7.83 -static struct cpufreq_driver acpi_cpufreq_driver = { 7.84 - .target = acpi_cpufreq_target, 7.85 - .init = acpi_cpufreq_cpu_init, 7.86 -}; 7.87 - 7.88 -void cpufreq_dom_exit(void) 7.89 +static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy) 7.90 { 7.91 - cpufreq_dom_max = 0; 7.92 - if (cpufreq_dom_mask) 7.93 - xfree(cpufreq_dom_mask); 7.94 - if (cpufreq_dom_pt) 7.95 - xfree(cpufreq_dom_pt); 7.96 -} 7.97 - 7.98 -int cpufreq_dom_init(void) 7.99 -{ 7.100 - unsigned int i; 7.101 - 7.102 - cpufreq_dom_max = 0; 7.103 + struct acpi_cpufreq_data *data = drv_data[policy->cpu]; 7.104 7.105 - for_each_online_cpu(i) { 7.106 - if (cpufreq_dom_max < processor_pminfo[i].perf.domain_info.domain) 7.107 - cpufreq_dom_max = processor_pminfo[i].perf.domain_info.domain; 7.108 + if (data) { 7.109 + drv_data[policy->cpu] = NULL; 7.110 + xfree(data->freq_table); 7.111 + xfree(data); 7.112 } 7.113 - cpufreq_dom_max++; 7.114 - 7.115 - cpufreq_dom_mask = xmalloc_array(unsigned long, 7.116 - BITS_TO_LONGS(cpufreq_dom_max)); 7.117 - if (!cpufreq_dom_mask) 7.118 - return -ENOMEM; 7.119 - bitmap_zero(cpufreq_dom_mask, cpufreq_dom_max); 7.120 - 7.121 - cpufreq_dom_pt = xmalloc_array(cpumask_t, cpufreq_dom_max); 7.122 - if (!cpufreq_dom_pt) 7.123 - return -ENOMEM; 7.124 - memset(cpufreq_dom_pt, 0, cpufreq_dom_max * sizeof(cpumask_t)); 7.125 - 7.126 - for_each_online_cpu(i) { 7.127 - __set_bit(processor_pminfo[i].perf.domain_info.domain, cpufreq_dom_mask); 7.128 - cpu_set(i, cpufreq_dom_pt[processor_pminfo[i].perf.domain_info.domain]); 7.129 - } 7.130 - 7.131 - for_each_online_cpu(i) 7.132 - processor_pminfo[i].perf.shared_cpu_map = 7.133 - cpufreq_dom_pt[processor_pminfo[i].perf.domain_info.domain]; 7.134 7.135 return 0; 7.136 } 7.137 7.138 -static int cpufreq_cpu_init(void) 7.139 +static struct cpufreq_driver acpi_cpufreq_driver = { 7.140 + .verify = acpi_cpufreq_verify, 7.141 + .target = acpi_cpufreq_target, 7.142 + .init = acpi_cpufreq_cpu_init, 7.143 + .exit = acpi_cpufreq_cpu_exit, 7.144 +}; 7.145 + 7.146 +int cpufreq_limit_change(unsigned int cpu) 7.147 { 7.148 - int i, ret = 0; 7.149 + struct processor_performance *perf = &processor_pminfo[cpu].perf; 7.150 + struct cpufreq_policy *data = cpufreq_cpu_policy[cpu]; 7.151 + struct cpufreq_policy policy; 7.152 + 7.153 + if (!cpu_online(cpu) || !data) 7.154 + return -ENODEV; 7.155 + 7.156 + if ((perf->platform_limit < 0) || 7.157 + (perf->platform_limit >= perf->state_count)) 7.158 + return -EINVAL; 7.159 + 7.160 + memcpy(&policy, data, sizeof(struct cpufreq_policy)); 7.161 + 7.162 + policy.max = 7.163 + perf->states[perf->platform_limit].core_frequency * 1000; 7.164 + 7.165 + return __cpufreq_set_policy(data, &policy); 7.166 +} 7.167 7.168 - for_each_online_cpu(i) { 7.169 - xen_px_policy[i].cpu = i; 7.170 +int cpufreq_add_cpu(unsigned int cpu) 7.171 +{ 7.172 + int ret = 0; 7.173 + unsigned int firstcpu; 7.174 + unsigned int dom; 7.175 + unsigned int j; 7.176 + struct cpufreq_policy new_policy; 7.177 + struct cpufreq_policy *policy; 7.178 + struct processor_performance *perf = &processor_pminfo[cpu].perf; 7.179 + 7.180 + /* to protect the case when Px was not controlled by xen */ 7.181 + if (!(perf->init & XEN_PX_INIT)) 7.182 + return 0; 7.183 + 7.184 + if (cpu_is_offline(cpu) || cpufreq_cpu_policy[cpu]) 7.185 + return -EINVAL; 7.186 + 7.187 + ret = px_statistic_init(cpu); 7.188 + if (ret) 7.189 + return ret; 7.190 7.191 - ret = px_statistic_init(i); 7.192 - if (ret) 7.193 - return ret; 7.194 + dom = perf->domain_info.domain; 7.195 + if (cpus_weight(cpufreq_dom_map[dom])) { 7.196 + /* share policy with the first cpu since on same boat */ 7.197 + firstcpu = first_cpu(cpufreq_dom_map[dom]); 7.198 + policy = cpufreq_cpu_policy[firstcpu]; 7.199 + 7.200 + cpufreq_cpu_policy[cpu] = policy; 7.201 + cpu_set(cpu, cpufreq_dom_map[dom]); 7.202 + cpu_set(cpu, policy->cpus); 7.203 + 7.204 + printk(KERN_EMERG"adding CPU %u\n", cpu); 7.205 + } else { 7.206 + /* for the first cpu, setup policy and do init work */ 7.207 + policy = xmalloc(struct cpufreq_policy); 7.208 + if (!policy) { 7.209 + px_statistic_exit(cpu); 7.210 + return -ENOMEM; 7.211 + } 7.212 + memset(policy, 0, sizeof(struct cpufreq_policy)); 7.213 + 7.214 + cpufreq_cpu_policy[cpu] = policy; 7.215 + cpu_set(cpu, cpufreq_dom_map[dom]); 7.216 + cpu_set(cpu, policy->cpus); 7.217 7.218 - ret = acpi_cpufreq_cpu_init(&xen_px_policy[i]); 7.219 + policy->cpu = cpu; 7.220 + ret = cpufreq_driver->init(policy); 7.221 if (ret) 7.222 - return ret; 7.223 + goto err1; 7.224 + printk(KERN_EMERG"CPU %u initialization completed\n", cpu); 7.225 } 7.226 + 7.227 + /* 7.228 + * After get full cpumap of the coordination domain, 7.229 + * we can safely start gov here. 7.230 + */ 7.231 + if (cpus_weight(cpufreq_dom_map[dom]) == 7.232 + perf->domain_info.num_processors) { 7.233 + memcpy(&new_policy, policy, sizeof(struct cpufreq_policy)); 7.234 + policy->governor = NULL; 7.235 + ret = __cpufreq_set_policy(policy, &new_policy); 7.236 + if (ret) 7.237 + goto err2; 7.238 + } 7.239 + 7.240 + return 0; 7.241 + 7.242 +err2: 7.243 + cpufreq_driver->exit(policy); 7.244 +err1: 7.245 + for_each_cpu_mask(j, cpufreq_dom_map[dom]) { 7.246 + cpufreq_cpu_policy[j] = NULL; 7.247 + px_statistic_exit(j); 7.248 + } 7.249 + 7.250 + cpus_clear(cpufreq_dom_map[dom]); 7.251 + xfree(policy); 7.252 return ret; 7.253 } 7.254 7.255 -int cpufreq_dom_dbs(unsigned int event) 7.256 +int cpufreq_del_cpu(unsigned int cpu) 7.257 { 7.258 - unsigned int cpu, dom; 7.259 - int ret = 0; 7.260 + unsigned int dom; 7.261 + struct cpufreq_policy *policy; 7.262 + struct processor_performance *perf = &processor_pminfo[cpu].perf; 7.263 + 7.264 + /* to protect the case when Px was not controlled by xen */ 7.265 + if (!(perf->init & XEN_PX_INIT)) 7.266 + return 0; 7.267 + 7.268 + if (cpu_is_offline(cpu) || !cpufreq_cpu_policy[cpu]) 7.269 + return -EINVAL; 7.270 + 7.271 + dom = perf->domain_info.domain; 7.272 + policy = cpufreq_cpu_policy[cpu]; 7.273 + 7.274 + printk(KERN_EMERG"deleting CPU %u\n", cpu); 7.275 7.276 - for (dom = 0; dom < cpufreq_dom_max; dom++) { 7.277 - if (!test_bit(dom, cpufreq_dom_mask)) 7.278 - continue; 7.279 - cpu = first_cpu(cpufreq_dom_pt[dom]); 7.280 - ret = cpufreq_governor_dbs(&xen_px_policy[cpu], event); 7.281 - if (ret) 7.282 - return ret; 7.283 + /* for the first cpu of the domain, stop gov */ 7.284 + if (cpus_weight(cpufreq_dom_map[dom]) == 7.285 + perf->domain_info.num_processors) 7.286 + __cpufreq_governor(policy, CPUFREQ_GOV_STOP); 7.287 + 7.288 + cpufreq_cpu_policy[cpu] = NULL; 7.289 + cpu_clear(cpu, policy->cpus); 7.290 + cpu_clear(cpu, cpufreq_dom_map[dom]); 7.291 + px_statistic_exit(cpu); 7.292 + 7.293 + /* for the last cpu of the domain, clean room */ 7.294 + /* It's safe here to free freq_table, drv_data and policy */ 7.295 + if (!cpus_weight(cpufreq_dom_map[dom])) { 7.296 + cpufreq_driver->exit(policy); 7.297 + xfree(policy); 7.298 } 7.299 - return ret; 7.300 + 7.301 + return 0; 7.302 } 7.303 7.304 -int acpi_cpufreq_init(void) 7.305 +static int __init cpufreq_driver_init(void) 7.306 { 7.307 int ret = 0; 7.308 - 7.309 - /* setup cpumask of psd dom and shared cpu map of cpu */ 7.310 - ret = cpufreq_dom_init(); 7.311 - if (ret) 7.312 - goto err; 7.313 7.314 - /* setup cpufreq driver */ 7.315 - cpufreq_driver = &acpi_cpufreq_driver; 7.316 - 7.317 - /* setup cpufreq infrastructure */ 7.318 - ret = cpufreq_cpu_init(); 7.319 - if (ret) 7.320 - goto err; 7.321 - 7.322 - /* setup cpufreq dbs according to dom coordiation */ 7.323 - ret = cpufreq_dom_dbs(CPUFREQ_GOV_START); 7.324 - if (ret) 7.325 - goto err; 7.326 + if ((cpufreq_controller == FREQCTL_xen) && 7.327 + (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)) 7.328 + ret = cpufreq_register_driver(&acpi_cpufreq_driver); 7.329 7.330 return ret; 7.331 - 7.332 -err: 7.333 - cpufreq_dom_exit(); 7.334 - return ret; 7.335 } 7.336 +__initcall(cpufreq_driver_init);
8.1 --- a/xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c Fri Sep 12 14:47:40 2008 +0900 8.2 +++ b/xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c Tue Sep 16 21:25:30 2008 +0900 8.3 @@ -238,4 +238,9 @@ int cpufreq_governor_dbs(struct cpufreq_ 8.4 break; 8.5 } 8.6 return 0; 8.7 -} 8.8 +} 8.9 + 8.10 +struct cpufreq_governor cpufreq_gov_dbs = { 8.11 + .name = "ondemand", 8.12 + .governor = cpufreq_governor_dbs, 8.13 +};
9.1 --- a/xen/arch/x86/acpi/cpufreq/powernow.c Fri Sep 12 14:47:40 2008 +0900 9.2 +++ b/xen/arch/x86/acpi/cpufreq/powernow.c Tue Sep 16 21:25:30 2008 +0900 9.3 @@ -50,7 +50,7 @@ 9.4 #define MSR_PSTATE_CUR_LIMIT 0xc0010061 /* pstate current limit MSR */ 9.5 9.6 extern struct processor_pminfo processor_pminfo[NR_CPUS]; 9.7 -extern struct cpufreq_policy xen_px_policy[NR_CPUS]; 9.8 +extern struct cpufreq_policy *cpufreq_cpu_policy[NR_CPUS]; 9.9 9.10 struct powernow_cpufreq_data { 9.11 struct processor_performance *acpi_data; 9.12 @@ -281,9 +281,9 @@ int powernow_cpufreq_init(void) 9.13 9.14 /* setup cpufreq infrastructure */ 9.15 for_each_online_cpu(i) { 9.16 - xen_px_policy[i].cpu = i; 9.17 + cpufreq_cpu_policy[i]->cpu = i; 9.18 9.19 - ret = powernow_cpufreq_cpu_init(&xen_px_policy[i]); 9.20 + ret = powernow_cpufreq_cpu_init(cpufreq_cpu_policy[i]); 9.21 if (ret) 9.22 goto cpufreq_init_out; 9.23 } 9.24 @@ -293,7 +293,7 @@ int powernow_cpufreq_init(void) 9.25 if (!cpu_isset(dom, dom_mask)) 9.26 continue; 9.27 i = first_cpu(pt[dom]); 9.28 - ret = cpufreq_governor_dbs(&xen_px_policy[i], CPUFREQ_GOV_START); 9.29 + ret = cpufreq_governor_dbs(cpufreq_cpu_policy[i], CPUFREQ_GOV_START); 9.30 if (ret) 9.31 goto cpufreq_init_out; 9.32 }
10.1 --- a/xen/arch/x86/acpi/cpufreq/utility.c Fri Sep 12 14:47:40 2008 +0900 10.2 +++ b/xen/arch/x86/acpi/cpufreq/utility.c Tue Sep 16 21:25:30 2008 +0900 10.3 @@ -31,47 +31,14 @@ 10.4 #include <acpi/cpufreq/cpufreq.h> 10.5 #include <public/sysctl.h> 10.6 10.7 -struct cpufreq_driver *cpufreq_driver; 10.8 +struct cpufreq_driver *cpufreq_driver; 10.9 +struct processor_pminfo processor_pminfo[NR_CPUS]; 10.10 +struct cpufreq_policy *cpufreq_cpu_policy[NR_CPUS]; 10.11 10.12 /********************************************************************* 10.13 * Px STATISTIC INFO * 10.14 *********************************************************************/ 10.15 10.16 -void px_statistic_suspend(void) 10.17 -{ 10.18 - int cpu; 10.19 - uint64_t now; 10.20 - 10.21 - now = NOW(); 10.22 - 10.23 - for_each_online_cpu(cpu) { 10.24 - struct pm_px *pxpt = &px_statistic_data[cpu]; 10.25 - uint64_t total_idle_ns; 10.26 - uint64_t tmp_idle_ns; 10.27 - 10.28 - total_idle_ns = get_cpu_idle_time(cpu); 10.29 - tmp_idle_ns = total_idle_ns - pxpt->prev_idle_wall; 10.30 - 10.31 - pxpt->u.pt[pxpt->u.cur].residency += 10.32 - now - pxpt->prev_state_wall; 10.33 - pxpt->u.pt[pxpt->u.cur].residency -= tmp_idle_ns; 10.34 - } 10.35 -} 10.36 - 10.37 -void px_statistic_resume(void) 10.38 -{ 10.39 - int cpu; 10.40 - uint64_t now; 10.41 - 10.42 - now = NOW(); 10.43 - 10.44 - for_each_online_cpu(cpu) { 10.45 - struct pm_px *pxpt = &px_statistic_data[cpu]; 10.46 - pxpt->prev_state_wall = now; 10.47 - pxpt->prev_idle_wall = get_cpu_idle_time(cpu); 10.48 - } 10.49 -} 10.50 - 10.51 void px_statistic_update(cpumask_t cpumask, uint8_t from, uint8_t to) 10.52 { 10.53 uint32_t i; 10.54 @@ -101,7 +68,7 @@ void px_statistic_update(cpumask_t cpuma 10.55 } 10.56 } 10.57 10.58 -int px_statistic_init(int cpuid) 10.59 +int px_statistic_init(unsigned int cpuid) 10.60 { 10.61 uint32_t i, count; 10.62 struct pm_px *pxpt = &px_statistic_data[cpuid]; 10.63 @@ -123,7 +90,7 @@ int px_statistic_init(int cpuid) 10.64 memset(pxpt->u.pt, 0, count * (sizeof(struct pm_px_val))); 10.65 10.66 pxpt->u.total = pmpt->perf.state_count; 10.67 - pxpt->u.usable = pmpt->perf.state_count - pmpt->perf.ppc; 10.68 + pxpt->u.usable = pmpt->perf.state_count - pmpt->perf.platform_limit; 10.69 10.70 for (i=0; i < pmpt->perf.state_count; i++) 10.71 pxpt->u.pt[i].freq = pmpt->perf.states[i].core_frequency; 10.72 @@ -134,7 +101,16 @@ int px_statistic_init(int cpuid) 10.73 return 0; 10.74 } 10.75 10.76 -void px_statistic_reset(int cpuid) 10.77 +void px_statistic_exit(unsigned int cpuid) 10.78 +{ 10.79 + struct pm_px *pxpt = &px_statistic_data[cpuid]; 10.80 + 10.81 + xfree(pxpt->u.trans_pt); 10.82 + xfree(pxpt->u.pt); 10.83 + memset(pxpt, 0, sizeof(struct pm_px)); 10.84 +} 10.85 + 10.86 +void px_statistic_reset(unsigned int cpuid) 10.87 { 10.88 uint32_t i, j, count; 10.89 struct pm_px *pxpt = &px_statistic_data[cpuid]; 10.90 @@ -184,6 +160,38 @@ int cpufreq_frequency_table_cpuinfo(stru 10.91 return 0; 10.92 } 10.93 10.94 +int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, 10.95 + struct cpufreq_frequency_table *table) 10.96 +{ 10.97 + unsigned int next_larger = ~0; 10.98 + unsigned int i; 10.99 + unsigned int count = 0; 10.100 + 10.101 + if (!cpu_online(policy->cpu)) 10.102 + return -EINVAL; 10.103 + 10.104 + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, 10.105 + policy->cpuinfo.max_freq); 10.106 + 10.107 + for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { 10.108 + unsigned int freq = table[i].frequency; 10.109 + if (freq == CPUFREQ_ENTRY_INVALID) 10.110 + continue; 10.111 + if ((freq >= policy->min) && (freq <= policy->max)) 10.112 + count++; 10.113 + else if ((next_larger > freq) && (freq > policy->max)) 10.114 + next_larger = freq; 10.115 + } 10.116 + 10.117 + if (!count) 10.118 + policy->max = next_larger; 10.119 + 10.120 + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, 10.121 + policy->cpuinfo.max_freq); 10.122 + 10.123 + return 0; 10.124 +} 10.125 + 10.126 int cpufreq_frequency_table_target(struct cpufreq_policy *policy, 10.127 struct cpufreq_frequency_table *table, 10.128 unsigned int target_freq, 10.129 @@ -289,57 +297,51 @@ int __cpufreq_driver_getavg(struct cpufr 10.130 10.131 10.132 /********************************************************************* 10.133 - * CPUFREQ SUSPEND/RESUME * 10.134 + * POLICY * 10.135 *********************************************************************/ 10.136 10.137 -void cpufreq_suspend(void) 10.138 +/* 10.139 + * data : current policy. 10.140 + * policy : policy to be set. 10.141 + */ 10.142 +int __cpufreq_set_policy(struct cpufreq_policy *data, 10.143 + struct cpufreq_policy *policy) 10.144 { 10.145 - int cpu; 10.146 + int ret = 0; 10.147 + 10.148 + memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo)); 10.149 + 10.150 + if (policy->min > data->min && policy->min > policy->max) 10.151 + return -EINVAL; 10.152 + 10.153 + /* verify the cpu speed can be set within this limit */ 10.154 + ret = cpufreq_driver->verify(policy); 10.155 + if (ret) 10.156 + return ret; 10.157 10.158 - /* to protect the case when Px was not controlled by xen */ 10.159 - for_each_online_cpu(cpu) { 10.160 - struct processor_performance *perf = &processor_pminfo[cpu].perf; 10.161 + data->min = policy->min; 10.162 + data->max = policy->max; 10.163 + 10.164 + if (policy->governor != data->governor) { 10.165 + /* save old, working values */ 10.166 + struct cpufreq_governor *old_gov = data->governor; 10.167 + 10.168 + /* end old governor */ 10.169 + if (data->governor) 10.170 + __cpufreq_governor(data, CPUFREQ_GOV_STOP); 10.171 10.172 - if (!(perf->init & XEN_PX_INIT)) 10.173 - return; 10.174 + /* start new governor */ 10.175 + data->governor = policy->governor; 10.176 + if (__cpufreq_governor(data, CPUFREQ_GOV_START)) { 10.177 + /* new governor failed, so re-start old one */ 10.178 + if (old_gov) { 10.179 + data->governor = old_gov; 10.180 + __cpufreq_governor(data, CPUFREQ_GOV_START); 10.181 + } 10.182 + return -EINVAL; 10.183 + } 10.184 + /* might be a policy change, too, so fall through */ 10.185 } 10.186 10.187 - cpufreq_dom_dbs(CPUFREQ_GOV_STOP); 10.188 - 10.189 - cpufreq_dom_exit(); 10.190 - 10.191 - px_statistic_suspend(); 10.192 + return __cpufreq_governor(data, CPUFREQ_GOV_LIMITS); 10.193 } 10.194 - 10.195 -int cpufreq_resume(void) 10.196 -{ 10.197 - int cpu, ret = 0; 10.198 - 10.199 - /* 1. to protect the case when Px was not controlled by xen */ 10.200 - /* 2. set state and resume flag to sync cpu to right state and freq */ 10.201 - for_each_online_cpu(cpu) { 10.202 - struct processor_performance *perf = &processor_pminfo[cpu].perf; 10.203 - struct cpufreq_policy *policy = &xen_px_policy[cpu]; 10.204 - 10.205 - if (!(perf->init & XEN_PX_INIT)) 10.206 - goto err; 10.207 - perf->state = 0; 10.208 - policy->resume = 1; 10.209 - } 10.210 - 10.211 - px_statistic_resume(); 10.212 - 10.213 - ret = cpufreq_dom_init(); 10.214 - if (ret) 10.215 - goto err; 10.216 - 10.217 - ret = cpufreq_dom_dbs(CPUFREQ_GOV_START); 10.218 - if (ret) 10.219 - goto err; 10.220 - 10.221 - return ret; 10.222 - 10.223 -err: 10.224 - cpufreq_dom_exit(); 10.225 - return ret; 10.226 -}
11.1 --- a/xen/arch/x86/acpi/pmstat.c Fri Sep 12 14:47:40 2008 +0900 11.2 +++ b/xen/arch/x86/acpi/pmstat.c Tue Sep 16 21:25:30 2008 +0900 11.3 @@ -78,7 +78,7 @@ int do_get_pm_info(struct xen_sysctl_get 11.4 tmp_idle_ns = total_idle_ns - pxpt->prev_idle_wall; 11.5 11.6 now = NOW(); 11.7 - pxpt->u.usable = pmpt->perf.state_count - pmpt->perf.ppc; 11.8 + pxpt->u.usable = pmpt->perf.state_count - pmpt->perf.platform_limit; 11.9 pxpt->u.pt[pxpt->u.cur].residency += now - pxpt->prev_state_wall; 11.10 pxpt->u.pt[pxpt->u.cur].residency -= tmp_idle_ns; 11.11 pxpt->prev_state_wall = now;
12.1 --- a/xen/arch/x86/acpi/power.c Fri Sep 12 14:47:40 2008 +0900 12.2 +++ b/xen/arch/x86/acpi/power.c Tue Sep 16 21:25:30 2008 +0900 12.3 @@ -133,8 +133,6 @@ static int enter_state(u32 state) 12.4 12.5 freeze_domains(); 12.6 12.7 - cpufreq_suspend(); 12.8 - 12.9 disable_nonboot_cpus(); 12.10 if ( num_online_cpus() != 1 ) 12.11 { 12.12 @@ -142,6 +140,8 @@ static int enter_state(u32 state) 12.13 goto enable_cpu; 12.14 } 12.15 12.16 + cpufreq_del_cpu(0); 12.17 + 12.18 hvm_cpu_down(); 12.19 12.20 acpi_sleep_prepare(state); 12.21 @@ -189,8 +189,8 @@ static int enter_state(u32 state) 12.22 BUG(); 12.23 12.24 enable_cpu: 12.25 + cpufreq_add_cpu(0); 12.26 enable_nonboot_cpus(); 12.27 - cpufreq_resume(); 12.28 thaw_domains(); 12.29 spin_unlock(&pm_lock); 12.30 return error;
13.1 --- a/xen/arch/x86/domain.c Fri Sep 12 14:47:40 2008 +0900 13.2 +++ b/xen/arch/x86/domain.c Tue Sep 16 21:25:30 2008 +0900 13.3 @@ -86,6 +86,12 @@ static void default_idle(void) 13.4 13.5 static void play_dead(void) 13.6 { 13.7 + /* 13.8 + * Flush pending softirqs if any. They can be queued up before this CPU 13.9 + * was taken out of cpu_online_map in __cpu_disable(). 13.10 + */ 13.11 + do_softirq(); 13.12 + 13.13 /* This must be done before dead CPU ack */ 13.14 cpu_exit_clear(); 13.15 hvm_cpu_down();
14.1 --- a/xen/arch/x86/microcode.c Fri Sep 12 14:47:40 2008 +0900 14.2 +++ b/xen/arch/x86/microcode.c Tue Sep 16 21:25:30 2008 +0900 14.3 @@ -1,72 +1,24 @@ 14.4 /* 14.5 - * Intel CPU Microcode Update Driver for Linux 14.6 - * 14.7 - * Copyright (C) 2000-2004 Tigran Aivazian 14.8 - * 14.9 - * This driver allows to upgrade microcode on Intel processors 14.10 - * belonging to IA-32 family - PentiumPro, Pentium II, 14.11 - * Pentium III, Xeon, Pentium 4, etc. 14.12 + * Intel CPU Microcode Update Driver for Linux 14.13 * 14.14 - * Reference: Section 8.10 of Volume III, Intel Pentium 4 Manual, 14.15 - * Order Number 245472 or free download from: 14.16 - * 14.17 - * http://developer.intel.com/design/pentium4/manuals/245472.htm 14.18 - * 14.19 - * For more information, go to http://www.urbanmyth.org/microcode 14.20 - * 14.21 - * This program is free software; you can redistribute it and/or 14.22 - * modify it under the terms of the GNU General Public License 14.23 - * as published by the Free Software Foundation; either version 14.24 - * 2 of the License, or (at your option) any later version. 14.25 + * Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk> 14.26 + * 2006 Shaohua Li <shaohua.li@intel.com> * 14.27 + * This driver allows to upgrade microcode on Intel processors 14.28 + * belonging to IA-32 family - PentiumPro, Pentium II, 14.29 + * Pentium III, Xeon, Pentium 4, etc. 14.30 * 14.31 - * 1.0 16 Feb 2000, Tigran Aivazian <tigran@sco.com> 14.32 - * Initial release. 14.33 - * 1.01 18 Feb 2000, Tigran Aivazian <tigran@sco.com> 14.34 - * Added read() support + cleanups. 14.35 - * 1.02 21 Feb 2000, Tigran Aivazian <tigran@sco.com> 14.36 - * Added 'device trimming' support. open(O_WRONLY) zeroes 14.37 - * and frees the saved copy of applied microcode. 14.38 - * 1.03 29 Feb 2000, Tigran Aivazian <tigran@sco.com> 14.39 - * Made to use devfs (/dev/cpu/microcode) + cleanups. 14.40 - * 1.04 06 Jun 2000, Simon Trimmer <simon@veritas.com> 14.41 - * Added misc device support (now uses both devfs and misc). 14.42 - * Added MICROCODE_IOCFREE ioctl to clear memory. 14.43 - * 1.05 09 Jun 2000, Simon Trimmer <simon@veritas.com> 14.44 - * Messages for error cases (non Intel & no suitable microcode). 14.45 - * 1.06 03 Aug 2000, Tigran Aivazian <tigran@veritas.com> 14.46 - * Removed ->release(). Removed exclusive open and status bitmap. 14.47 - * Added microcode_rwsem to serialize read()/write()/ioctl(). 14.48 - * Removed global kernel lock usage. 14.49 - * 1.07 07 Sep 2000, Tigran Aivazian <tigran@veritas.com> 14.50 - * Write 0 to 0x8B msr and then cpuid before reading revision, 14.51 - * so that it works even if there were no update done by the 14.52 - * BIOS. Otherwise, reading from 0x8B gives junk (which happened 14.53 - * to be 0 on my machine which is why it worked even when I 14.54 - * disabled update by the BIOS) 14.55 - * Thanks to Eric W. Biederman <ebiederman@lnxi.com> for the fix. 14.56 - * 1.08 11 Dec 2000, Richard Schaal <richard.schaal@intel.com> and 14.57 - * Tigran Aivazian <tigran@veritas.com> 14.58 - * Intel Pentium 4 processor support and bugfixes. 14.59 - * 1.09 30 Oct 2001, Tigran Aivazian <tigran@veritas.com> 14.60 - * Bugfix for HT (Hyper-Threading) enabled processors 14.61 - * whereby processor resources are shared by all logical processors 14.62 - * in a single CPU package. 14.63 - * 1.10 28 Feb 2002 Asit K Mallick <asit.k.mallick@intel.com> and 14.64 - * Tigran Aivazian <tigran@veritas.com>, 14.65 - * Serialize updates as required on HT processors due to speculative 14.66 - * nature of implementation. 14.67 - * 1.11 22 Mar 2002 Tigran Aivazian <tigran@veritas.com> 14.68 - * Fix the panic when writing zero-length microcode chunk. 14.69 - * 1.12 29 Sep 2003 Nitin Kamble <nitin.a.kamble@intel.com>, 14.70 - * Jun Nakajima <jun.nakajima@intel.com> 14.71 - * Support for the microcode updates in the new format. 14.72 - * 1.13 10 Oct 2003 Tigran Aivazian <tigran@veritas.com> 14.73 - * Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl 14.74 - * because we no longer hold a copy of applied microcode 14.75 - * in kernel memory. 14.76 - * 1.14 25 Jun 2004 Tigran Aivazian <tigran@veritas.com> 14.77 - * Fix sigmatch() macro to handle old CPUs with pf == 0. 14.78 - * Thanks to Stuart Swales for pointing out this bug. 14.79 + * Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture 14.80 + * Software Developer's Manual 14.81 + * Order Number 253668 or free download from: 14.82 + * 14.83 + * http://developer.intel.com/design/pentium4/manuals/253668.htm 14.84 + * 14.85 + * For more information, go to http://www.urbanmyth.org/microcode 14.86 + * 14.87 + * This program is free software; you can redistribute it and/or 14.88 + * modify it under the terms of the GNU General Public License 14.89 + * as published by the Free Software Foundation; either version 14.90 + * 2 of the License, or (at your option) any later version. 14.91 */ 14.92 14.93 #include <xen/config.h> 14.94 @@ -76,402 +28,169 @@ 14.95 #include <xen/sched.h> 14.96 #include <xen/smp.h> 14.97 #include <xen/spinlock.h> 14.98 +#include <xen/guest_access.h> 14.99 14.100 #include <asm/current.h> 14.101 #include <asm/msr.h> 14.102 #include <asm/uaccess.h> 14.103 #include <asm/processor.h> 14.104 - 14.105 -#define pr_debug(x...) ((void)0) 14.106 -#define DEFINE_MUTEX(_m) DEFINE_SPINLOCK(_m) 14.107 -#define mutex_lock(_m) spin_lock(_m) 14.108 -#define mutex_unlock(_m) spin_unlock(_m) 14.109 -#define vmalloc(_s) xmalloc_bytes(_s) 14.110 -#define vfree(_p) xfree(_p) 14.111 +#include <asm/microcode.h> 14.112 14.113 -#if 0 14.114 -MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver"); 14.115 -MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>"); 14.116 -MODULE_LICENSE("GPL"); 14.117 -#endif 14.118 +const struct microcode_ops *microcode_ops; 14.119 14.120 -static int verbose; 14.121 -boolean_param("microcode.verbose", verbose); 14.122 - 14.123 -#define MICROCODE_VERSION "1.14a" 14.124 +static DEFINE_SPINLOCK(microcode_mutex); 14.125 14.126 -#define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ 14.127 -#define MC_HEADER_SIZE (sizeof (microcode_header_t)) /* 48 bytes */ 14.128 -#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */ 14.129 -#define EXT_HEADER_SIZE (sizeof (struct extended_sigtable)) /* 20 bytes */ 14.130 -#define EXT_SIGNATURE_SIZE (sizeof (struct extended_signature)) /* 12 bytes */ 14.131 -#define DWSIZE (sizeof (u32)) 14.132 -#define get_totalsize(mc) \ 14.133 - (((microcode_t *)mc)->hdr.totalsize ? \ 14.134 - ((microcode_t *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE) 14.135 -#define get_datasize(mc) \ 14.136 - (((microcode_t *)mc)->hdr.datasize ? \ 14.137 - ((microcode_t *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE) 14.138 +struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; 14.139 14.140 -#define sigmatch(s1, s2, p1, p2) \ 14.141 - (((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0)))) 14.142 - 14.143 -#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE) 14.144 - 14.145 -/* serialize access to the physical write to MSR 0x79 */ 14.146 -static DEFINE_SPINLOCK(microcode_update_lock); 14.147 - 14.148 -/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ 14.149 -static DEFINE_MUTEX(microcode_mutex); 14.150 - 14.151 -static const void __user *user_buffer; /* user area microcode data buffer */ 14.152 -static unsigned int user_buffer_size; /* it's size */ 14.153 +struct microcode_buffer { 14.154 + void *buf; 14.155 + size_t size; 14.156 +}; 14.157 14.158 -typedef enum mc_error_code { 14.159 - MC_SUCCESS = 0, 14.160 - MC_IGNORED = 1, 14.161 - MC_NOTFOUND = 2, 14.162 - MC_MARKED = 3, 14.163 - MC_ALLOCATED = 4, 14.164 -} mc_error_code_t; 14.165 - 14.166 -static struct ucode_cpu_info { 14.167 - unsigned int sig; 14.168 - unsigned int pf, orig_pf; 14.169 - unsigned int rev; 14.170 - unsigned int cksum; 14.171 - mc_error_code_t err; 14.172 - microcode_t *mc; 14.173 -} ucode_cpu_info[NR_CPUS]; 14.174 - 14.175 -static void collect_cpu_info (void *unused) 14.176 -{ 14.177 - int cpu_num = smp_processor_id(); 14.178 - struct cpuinfo_x86 *c = cpu_data + cpu_num; 14.179 - struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 14.180 - unsigned int val[2]; 14.181 +static struct microcode_buffer microcode_buffer; 14.182 +static bool_t microcode_error; 14.183 14.184 - uci->sig = uci->pf = uci->rev = uci->cksum = 0; 14.185 - uci->err = MC_NOTFOUND; 14.186 - uci->mc = NULL; 14.187 - 14.188 - if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || 14.189 - cpu_has(c, X86_FEATURE_IA64)) { 14.190 - printk(KERN_ERR "microcode: CPU%d not a capable Intel processor\n", cpu_num); 14.191 - return; 14.192 - } else { 14.193 - uci->sig = cpuid_eax(0x00000001); 14.194 +static void microcode_fini_cpu(int cpu) 14.195 +{ 14.196 + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 14.197 14.198 - if ((c->x86_model >= 5) || (c->x86 > 6)) { 14.199 - /* get processor flags from MSR 0x17 */ 14.200 - rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); 14.201 - uci->pf = 1 << ((val[1] >> 18) & 7); 14.202 - } 14.203 - uci->orig_pf = uci->pf; 14.204 - } 14.205 - 14.206 - wrmsr(MSR_IA32_UCODE_REV, 0, 0); 14.207 - /* see notes above for revision 1.07. Apparent chip bug */ 14.208 - sync_core(); 14.209 - /* get the current revision from MSR 0x8B */ 14.210 - rdmsr(MSR_IA32_UCODE_REV, val[0], uci->rev); 14.211 - pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n", 14.212 - uci->sig, uci->pf, uci->rev); 14.213 + spin_lock(µcode_mutex); 14.214 + xfree(uci->mc.valid_mc); 14.215 + uci->mc.valid_mc = NULL; 14.216 + uci->valid = 0; 14.217 + spin_unlock(µcode_mutex); 14.218 } 14.219 14.220 -static inline void mark_microcode_update (int cpu_num, microcode_header_t *mc_header, int sig, int pf, int cksum) 14.221 +static int collect_cpu_info(int cpu) 14.222 { 14.223 - struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 14.224 - 14.225 - pr_debug("Microcode Found.\n"); 14.226 - pr_debug(" Header Revision 0x%x\n", mc_header->hdrver); 14.227 - pr_debug(" Loader Revision 0x%x\n", mc_header->ldrver); 14.228 - pr_debug(" Revision 0x%x \n", mc_header->rev); 14.229 - pr_debug(" Date %x/%x/%x\n", 14.230 - ((mc_header->date >> 24 ) & 0xff), 14.231 - ((mc_header->date >> 16 ) & 0xff), 14.232 - (mc_header->date & 0xFFFF)); 14.233 - pr_debug(" Signature 0x%x\n", sig); 14.234 - pr_debug(" Type 0x%x Family 0x%x Model 0x%x Stepping 0x%x\n", 14.235 - ((sig >> 12) & 0x3), 14.236 - ((sig >> 8) & 0xf), 14.237 - ((sig >> 4) & 0xf), 14.238 - ((sig & 0xf))); 14.239 - pr_debug(" Processor Flags 0x%x\n", pf); 14.240 - pr_debug(" Checksum 0x%x\n", cksum); 14.241 + int err = 0; 14.242 + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 14.243 14.244 - if (mc_header->rev < uci->rev) { 14.245 - if (uci->err == MC_NOTFOUND) { 14.246 - uci->err = MC_IGNORED; 14.247 - uci->cksum = mc_header->rev; 14.248 - } else if (uci->err == MC_IGNORED && uci->cksum < mc_header->rev) 14.249 - uci->cksum = mc_header->rev; 14.250 - } else if (mc_header->rev == uci->rev) { 14.251 - if (uci->err < MC_MARKED) { 14.252 - /* notify the caller of success on this cpu */ 14.253 - uci->err = MC_SUCCESS; 14.254 - } 14.255 - } else if (uci->err != MC_ALLOCATED || mc_header->rev > uci->mc->hdr.rev) { 14.256 - pr_debug("microcode: CPU%d found a matching microcode update with " 14.257 - " revision 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev); 14.258 - uci->cksum = cksum; 14.259 - uci->pf = pf; /* keep the original mc pf for cksum calculation */ 14.260 - uci->err = MC_MARKED; /* found the match */ 14.261 - for_each_online_cpu(cpu_num) { 14.262 - if (ucode_cpu_info + cpu_num != uci 14.263 - && ucode_cpu_info[cpu_num].mc == uci->mc) { 14.264 - uci->mc = NULL; 14.265 - break; 14.266 - } 14.267 - } 14.268 - if (uci->mc != NULL) { 14.269 - vfree(uci->mc); 14.270 - uci->mc = NULL; 14.271 - } 14.272 - } 14.273 - return; 14.274 + memset(uci, 0, sizeof(*uci)); 14.275 + err = microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig); 14.276 + if ( !err ) 14.277 + uci->valid = 1; 14.278 + 14.279 + return err; 14.280 } 14.281 14.282 -static int find_matching_ucodes (void) 14.283 +static int microcode_resume_cpu(int cpu) 14.284 { 14.285 - int cursor = 0; 14.286 - int error = 0; 14.287 - 14.288 - while (cursor + MC_HEADER_SIZE < user_buffer_size) { 14.289 - microcode_header_t mc_header; 14.290 - void *newmc = NULL; 14.291 - int i, sum, cpu_num, allocated_flag, total_size, data_size, ext_table_size; 14.292 - 14.293 - if (copy_from_user(&mc_header, user_buffer + cursor, MC_HEADER_SIZE)) { 14.294 - printk(KERN_ERR "microcode: error! Can not read user data\n"); 14.295 - error = -EFAULT; 14.296 - goto out; 14.297 - } 14.298 - 14.299 - total_size = get_totalsize(&mc_header); 14.300 - if (cursor + total_size > user_buffer_size) { 14.301 - printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); 14.302 - error = -EINVAL; 14.303 - goto out; 14.304 - } 14.305 - 14.306 - data_size = get_datasize(&mc_header); 14.307 - if (data_size + MC_HEADER_SIZE > total_size) { 14.308 - printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); 14.309 - error = -EINVAL; 14.310 - goto out; 14.311 - } 14.312 + int err = 0; 14.313 + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 14.314 + struct cpu_signature nsig; 14.315 14.316 - if (mc_header.ldrver != 1 || mc_header.hdrver != 1) { 14.317 - printk(KERN_ERR "microcode: error! Unknown microcode update format\n"); 14.318 - error = -EINVAL; 14.319 - goto out; 14.320 - } 14.321 - 14.322 - for_each_online_cpu(cpu_num) { 14.323 - struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 14.324 - 14.325 - if (sigmatch(mc_header.sig, uci->sig, mc_header.pf, uci->orig_pf)) 14.326 - mark_microcode_update(cpu_num, &mc_header, mc_header.sig, mc_header.pf, mc_header.cksum); 14.327 - } 14.328 + gdprintk(XENLOG_INFO, "microcode: CPU%d resumed\n", cpu); 14.329 14.330 - ext_table_size = total_size - (MC_HEADER_SIZE + data_size); 14.331 - if (ext_table_size) { 14.332 - struct extended_sigtable ext_header; 14.333 - struct extended_signature ext_sig; 14.334 - int ext_sigcount; 14.335 - 14.336 - if ((ext_table_size < EXT_HEADER_SIZE) 14.337 - || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) { 14.338 - printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); 14.339 - error = -EINVAL; 14.340 - goto out; 14.341 - } 14.342 - if (copy_from_user(&ext_header, user_buffer + cursor 14.343 - + MC_HEADER_SIZE + data_size, EXT_HEADER_SIZE)) { 14.344 - printk(KERN_ERR "microcode: error! Can not read user data\n"); 14.345 - error = -EFAULT; 14.346 - goto out; 14.347 - } 14.348 - if (ext_table_size != exttable_size(&ext_header)) { 14.349 - printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); 14.350 - error = -EFAULT; 14.351 - goto out; 14.352 - } 14.353 + if ( !uci->mc.valid_mc ) 14.354 + return -EIO; 14.355 14.356 - ext_sigcount = ext_header.count; 14.357 - 14.358 - for (i = 0; i < ext_sigcount; i++) { 14.359 - if (copy_from_user(&ext_sig, user_buffer + cursor + MC_HEADER_SIZE + data_size + EXT_HEADER_SIZE 14.360 - + EXT_SIGNATURE_SIZE * i, EXT_SIGNATURE_SIZE)) { 14.361 - printk(KERN_ERR "microcode: error! Can not read user data\n"); 14.362 - error = -EFAULT; 14.363 - goto out; 14.364 - } 14.365 - for_each_online_cpu(cpu_num) { 14.366 - struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 14.367 + /* 14.368 + * Let's verify that the 'cached' ucode does belong 14.369 + * to this cpu (a bit of paranoia): 14.370 + */ 14.371 + err = microcode_ops->collect_cpu_info(cpu, &nsig); 14.372 + if ( err ) 14.373 + { 14.374 + microcode_fini_cpu(cpu); 14.375 + return err; 14.376 + } 14.377 14.378 - if (sigmatch(ext_sig.sig, uci->sig, ext_sig.pf, uci->orig_pf)) { 14.379 - mark_microcode_update(cpu_num, &mc_header, ext_sig.sig, ext_sig.pf, ext_sig.cksum); 14.380 - } 14.381 - } 14.382 - } 14.383 - } 14.384 - /* now check if any cpu has matched */ 14.385 - allocated_flag = 0; 14.386 - sum = 0; 14.387 - for_each_online_cpu(cpu_num) { 14.388 - if (ucode_cpu_info[cpu_num].err == MC_MARKED) { 14.389 - struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 14.390 - if (!allocated_flag) { 14.391 - allocated_flag = 1; 14.392 - newmc = vmalloc(total_size); 14.393 - if (!newmc) { 14.394 - printk(KERN_ERR "microcode: error! Can not allocate memory\n"); 14.395 - error = -ENOMEM; 14.396 - goto out; 14.397 - } 14.398 - if (copy_from_user(newmc + MC_HEADER_SIZE, 14.399 - user_buffer + cursor + MC_HEADER_SIZE, 14.400 - total_size - MC_HEADER_SIZE)) { 14.401 - printk(KERN_ERR "microcode: error! Can not read user data\n"); 14.402 - vfree(newmc); 14.403 - error = -EFAULT; 14.404 - goto out; 14.405 - } 14.406 - memcpy(newmc, &mc_header, MC_HEADER_SIZE); 14.407 - /* check extended table checksum */ 14.408 - if (ext_table_size) { 14.409 - int ext_table_sum = 0; 14.410 - int * ext_tablep = (((void *) newmc) + MC_HEADER_SIZE + data_size); 14.411 - i = ext_table_size / DWSIZE; 14.412 - while (i--) ext_table_sum += ext_tablep[i]; 14.413 - if (ext_table_sum) { 14.414 - printk(KERN_WARNING "microcode: aborting, bad extended signature table checksum\n"); 14.415 - vfree(newmc); 14.416 - error = -EINVAL; 14.417 - goto out; 14.418 - } 14.419 - } 14.420 + if ( memcmp(&nsig, &uci->cpu_sig, sizeof(nsig)) ) 14.421 + { 14.422 + microcode_fini_cpu(cpu); 14.423 + /* Should we look for a new ucode here? */ 14.424 + return -EIO; 14.425 + } 14.426 14.427 - /* calculate the checksum */ 14.428 - i = (MC_HEADER_SIZE + data_size) / DWSIZE; 14.429 - while (i--) sum += ((int *)newmc)[i]; 14.430 - sum -= (mc_header.sig + mc_header.pf + mc_header.cksum); 14.431 - } 14.432 - ucode_cpu_info[cpu_num].mc = newmc; 14.433 - ucode_cpu_info[cpu_num].err = MC_ALLOCATED; /* mc updated */ 14.434 - if (sum + uci->sig + uci->pf + uci->cksum != 0) { 14.435 - printk(KERN_ERR "microcode: CPU%d aborting, bad checksum\n", cpu_num); 14.436 - error = -EINVAL; 14.437 - goto out; 14.438 - } 14.439 - } 14.440 - } 14.441 - cursor += total_size; /* goto the next update patch */ 14.442 - } /* end of while */ 14.443 -out: 14.444 - return error; 14.445 + err = microcode_ops->apply_microcode(cpu); 14.446 + 14.447 + return err; 14.448 } 14.449 14.450 -static void do_update_one (void * unused) 14.451 +static int microcode_update_cpu(int cpu, const void *buf, size_t size) 14.452 { 14.453 - unsigned long flags; 14.454 - unsigned int val[2]; 14.455 - int cpu_num = smp_processor_id(); 14.456 - struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 14.457 + int err = 0; 14.458 + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 14.459 14.460 - if (uci->mc == NULL) { 14.461 - if (verbose) { 14.462 - if (uci->err == MC_SUCCESS) 14.463 - printk(KERN_INFO "microcode: CPU%d already at revision 0x%x\n", 14.464 - cpu_num, uci->rev); 14.465 - else 14.466 - printk(KERN_INFO "microcode: No new microcode data for CPU%d\n", cpu_num); 14.467 - } 14.468 - return; 14.469 - } 14.470 + /* We should bind the task to the CPU */ 14.471 + BUG_ON(raw_smp_processor_id() != cpu); 14.472 + 14.473 + spin_lock(µcode_mutex); 14.474 14.475 - /* serialize access to the physical write to MSR 0x79 */ 14.476 - spin_lock_irqsave(µcode_update_lock, flags); 14.477 - 14.478 - /* write microcode via MSR 0x79 */ 14.479 - wrmsr(MSR_IA32_UCODE_WRITE, 14.480 - (unsigned long) uci->mc->bits, 14.481 - (unsigned long) uci->mc->bits >> 16 >> 16); 14.482 - wrmsr(MSR_IA32_UCODE_REV, 0, 0); 14.483 + /* 14.484 + * Check if the system resume is in progress (uci->valid != NULL), 14.485 + * otherwise just request a firmware: 14.486 + */ 14.487 + if ( uci->valid ) 14.488 + { 14.489 + err = microcode_resume_cpu(cpu); 14.490 + } 14.491 + else 14.492 + { 14.493 + err = collect_cpu_info(cpu); 14.494 + if ( !err && uci->valid ) 14.495 + err = microcode_ops->cpu_request_microcode(cpu, buf, size); 14.496 + } 14.497 14.498 - /* see notes above for revision 1.07. Apparent chip bug */ 14.499 - sync_core(); 14.500 - 14.501 - /* get the current revision from MSR 0x8B */ 14.502 - rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); 14.503 + spin_unlock(µcode_mutex); 14.504 14.505 - /* notify the caller of success on this cpu */ 14.506 - uci->err = MC_SUCCESS; 14.507 - spin_unlock_irqrestore(µcode_update_lock, flags); 14.508 - printk(KERN_INFO "microcode: CPU%d updated from revision " 14.509 - "0x%x to 0x%x, date = %08x \n", 14.510 - cpu_num, uci->rev, val[1], uci->mc->hdr.date); 14.511 - return; 14.512 + return err; 14.513 } 14.514 14.515 -static int do_microcode_update (void) 14.516 +static void do_microcode_update_one(void *info) 14.517 { 14.518 - int i, error; 14.519 - 14.520 - if (on_each_cpu(collect_cpu_info, NULL, 1, 1) != 0) { 14.521 - printk(KERN_ERR "microcode: Error! Could not run on all processors\n"); 14.522 - error = -EIO; 14.523 - goto out; 14.524 - } 14.525 - 14.526 - if ((error = find_matching_ucodes())) { 14.527 - printk(KERN_ERR "microcode: Error in the microcode data\n"); 14.528 - goto out_free; 14.529 - } 14.530 + int error = microcode_update_cpu( 14.531 + smp_processor_id(), microcode_buffer.buf, microcode_buffer.size); 14.532 + if ( error ) 14.533 + microcode_error = error; 14.534 +} 14.535 14.536 - if (on_each_cpu(do_update_one, NULL, 1, 1) != 0) { 14.537 - printk(KERN_ERR "microcode: Error! Could not run on all processors\n"); 14.538 - error = -EIO; 14.539 - } 14.540 +static int do_microcode_update(void) 14.541 +{ 14.542 + microcode_error = 0; 14.543 14.544 -out_free: 14.545 - for_each_online_cpu(i) { 14.546 - if (ucode_cpu_info[i].mc) { 14.547 - int j; 14.548 - void *tmp = ucode_cpu_info[i].mc; 14.549 - vfree(tmp); 14.550 - for_each_online_cpu(j) { 14.551 - if (ucode_cpu_info[j].mc == tmp) 14.552 - ucode_cpu_info[j].mc = NULL; 14.553 - } 14.554 - } 14.555 - if (ucode_cpu_info[i].err == MC_IGNORED && verbose) 14.556 - printk(KERN_WARNING "microcode: CPU%d not 'upgrading' to earlier revision" 14.557 - " 0x%x (current=0x%x)\n", i, ucode_cpu_info[i].cksum, ucode_cpu_info[i].rev); 14.558 - } 14.559 -out: 14.560 - return error; 14.561 + if ( on_each_cpu(do_microcode_update_one, NULL, 1, 1) != 0 ) 14.562 + { 14.563 + printk(KERN_ERR "microcode: Error! Could not run on all processors\n"); 14.564 + return -EIO; 14.565 + } 14.566 + 14.567 + return microcode_error; 14.568 } 14.569 14.570 int microcode_update(XEN_GUEST_HANDLE(const_void) buf, unsigned long len) 14.571 { 14.572 - int ret; 14.573 + int ret; 14.574 + 14.575 + /* XXX FIXME: No allocations in interrupt context. */ 14.576 + return -EINVAL; 14.577 14.578 - if (len != (typeof(user_buffer_size))len) { 14.579 - printk(KERN_ERR "microcode: too much data\n"); 14.580 - return -E2BIG; 14.581 - } 14.582 + if ( len != (typeof(microcode_buffer.size))len ) 14.583 + { 14.584 + printk(KERN_ERR "microcode: too much data\n"); 14.585 + return -E2BIG; 14.586 + } 14.587 14.588 - mutex_lock(µcode_mutex); 14.589 + if ( microcode_ops == NULL ) 14.590 + return -EINVAL; 14.591 14.592 - user_buffer = buf.p; 14.593 - user_buffer_size = len; 14.594 + microcode_buffer.buf = xmalloc_array(uint8_t, len); 14.595 + if ( microcode_buffer.buf == NULL ) 14.596 + return -ENOMEM; 14.597 14.598 - ret = do_microcode_update(); 14.599 + ret = copy_from_guest(microcode_buffer.buf, buf, len); 14.600 + if ( ret != 0 ) 14.601 + return ret; 14.602 14.603 - mutex_unlock(µcode_mutex); 14.604 + microcode_buffer.size = len; 14.605 + wmb(); 14.606 + 14.607 + ret = do_microcode_update(); 14.608 14.609 - return ret; 14.610 + xfree(microcode_buffer.buf); 14.611 + microcode_buffer.buf = NULL; 14.612 + microcode_buffer.size = 0; 14.613 + 14.614 + return ret; 14.615 }
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/xen/arch/x86/microcode_amd.c Tue Sep 16 21:25:30 2008 +0900 15.3 @@ -0,0 +1,371 @@ 15.4 +/* 15.5 + * AMD CPU Microcode Update Driver for Linux 15.6 + * Copyright (C) 2008 Advanced Micro Devices Inc. 15.7 + * 15.8 + * Author: Peter Oruba <peter.oruba@amd.com> 15.9 + * 15.10 + * Based on work by: 15.11 + * Tigran Aivazian <tigran@aivazian.fsnet.co.uk> 15.12 + * 15.13 + * This driver allows to upgrade microcode on AMD 15.14 + * family 0x10 and 0x11 processors. 15.15 + * 15.16 + * Licensed unter the terms of the GNU General Public 15.17 + * License version 2. See file COPYING for details. 15.18 + */ 15.19 + 15.20 +#include <xen/config.h> 15.21 +#include <xen/lib.h> 15.22 +#include <xen/kernel.h> 15.23 +#include <xen/init.h> 15.24 +#include <xen/sched.h> 15.25 +#include <xen/smp.h> 15.26 +#include <xen/spinlock.h> 15.27 + 15.28 +#include <asm/msr.h> 15.29 +#include <asm/uaccess.h> 15.30 +#include <asm/processor.h> 15.31 +#include <asm/microcode.h> 15.32 + 15.33 +#define pr_debug(x...) ((void)0) 15.34 + 15.35 +#define UCODE_MAGIC 0x00414d44 15.36 +#define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000 15.37 +#define UCODE_UCODE_TYPE 0x00000001 15.38 + 15.39 +#define UCODE_MAX_SIZE (2048) 15.40 +#define DEFAULT_UCODE_DATASIZE (896) 15.41 +#define MC_HEADER_SIZE (sizeof(struct microcode_header_amd)) 15.42 +#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) 15.43 +#define DWSIZE (sizeof(uint32_t)) 15.44 +/* For now we support a fixed ucode total size only */ 15.45 +#define get_totalsize(mc) \ 15.46 + ((((struct microcode_amd *)mc)->hdr.mc_patch_data_len * 28) \ 15.47 + + MC_HEADER_SIZE) 15.48 + 15.49 +/* serialize access to the physical write */ 15.50 +static DEFINE_SPINLOCK(microcode_update_lock); 15.51 + 15.52 +struct equiv_cpu_entry *equiv_cpu_table; 15.53 + 15.54 +static long install_equiv_cpu_table(const void *, uint32_t, long); 15.55 + 15.56 +static int collect_cpu_info(int cpu, struct cpu_signature *csig) 15.57 +{ 15.58 + struct cpuinfo_x86 *c = &cpu_data[cpu]; 15.59 + 15.60 + memset(csig, 0, sizeof(*csig)); 15.61 + 15.62 + if ( (c->x86_vendor != X86_VENDOR_AMD) || (c->x86 < 0x10) ) 15.63 + { 15.64 + printk(KERN_ERR "microcode: CPU%d not a capable AMD processor\n", 15.65 + cpu); 15.66 + return -1; 15.67 + } 15.68 + 15.69 + asm volatile ( 15.70 + "movl %1, %%ecx; rdmsr" 15.71 + : "=a" (csig->rev) 15.72 + : "i" (MSR_AMD_PATCHLEVEL) : "ecx" ); 15.73 + 15.74 + printk(KERN_INFO "microcode: collect_cpu_info: patch_id=0x%x\n", 15.75 + csig->rev); 15.76 + 15.77 + return 0; 15.78 +} 15.79 + 15.80 +static int get_matching_microcode(void *mc, int cpu) 15.81 +{ 15.82 + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 15.83 + struct microcode_header_amd *mc_header = mc; 15.84 + unsigned long total_size = get_totalsize(mc_header); 15.85 + void *new_mc; 15.86 + unsigned int current_cpu_id; 15.87 + unsigned int equiv_cpu_id = 0x00; 15.88 + unsigned int i; 15.89 + 15.90 + /* We should bind the task to the CPU */ 15.91 + BUG_ON(cpu != raw_smp_processor_id()); 15.92 + 15.93 + /* This is a tricky part. We might be called from a write operation 15.94 + * to the device file instead of the usual process of firmware 15.95 + * loading. This routine needs to be able to distinguish both 15.96 + * cases. This is done by checking if there already is a equivalent 15.97 + * CPU table installed. If not, we're written through 15.98 + * /dev/cpu/microcode. 15.99 + * Since we ignore all checks. The error case in which going through 15.100 + * firmware loading and that table is not loaded has already been 15.101 + * checked earlier. 15.102 + */ 15.103 + if ( equiv_cpu_table == NULL ) 15.104 + { 15.105 + printk(KERN_INFO "microcode: CPU%d microcode update with " 15.106 + "version 0x%x (current=0x%x)\n", 15.107 + cpu, mc_header->patch_id, uci->cpu_sig.rev); 15.108 + goto out; 15.109 + } 15.110 + 15.111 + current_cpu_id = cpuid_eax(0x00000001); 15.112 + 15.113 + for ( i = 0; equiv_cpu_table[i].installed_cpu != 0; i++ ) 15.114 + { 15.115 + if ( current_cpu_id == equiv_cpu_table[i].installed_cpu ) 15.116 + { 15.117 + equiv_cpu_id = equiv_cpu_table[i].equiv_cpu; 15.118 + break; 15.119 + } 15.120 + } 15.121 + 15.122 + if ( !equiv_cpu_id ) 15.123 + { 15.124 + printk(KERN_ERR "microcode: CPU%d cpu_id " 15.125 + "not found in equivalent cpu table \n", cpu); 15.126 + return 0; 15.127 + } 15.128 + 15.129 + if ( (mc_header->processor_rev_id[0]) != (equiv_cpu_id & 0xff) ) 15.130 + { 15.131 + printk(KERN_INFO 15.132 + "microcode: CPU%d patch does not match " 15.133 + "(patch is %x, cpu extended is %x) \n", 15.134 + cpu, mc_header->processor_rev_id[0], 15.135 + (equiv_cpu_id & 0xff)); 15.136 + return 0; 15.137 + } 15.138 + 15.139 + if ( (mc_header->processor_rev_id[1]) != ((equiv_cpu_id >> 16) & 0xff) ) 15.140 + { 15.141 + printk(KERN_INFO "microcode: CPU%d patch does not match " 15.142 + "(patch is %x, cpu base id is %x) \n", 15.143 + cpu, mc_header->processor_rev_id[1], 15.144 + ((equiv_cpu_id >> 16) & 0xff)); 15.145 + return 0; 15.146 + } 15.147 + 15.148 + if ( mc_header->patch_id <= uci->cpu_sig.rev ) 15.149 + return 0; 15.150 + 15.151 + printk(KERN_INFO "microcode: CPU%d found a matching microcode " 15.152 + "update with version 0x%x (current=0x%x)\n", 15.153 + cpu, mc_header->patch_id, uci->cpu_sig.rev); 15.154 + 15.155 + out: 15.156 + new_mc = xmalloc_bytes(UCODE_MAX_SIZE); 15.157 + if ( new_mc == NULL ) 15.158 + { 15.159 + printk(KERN_ERR "microcode: error, can't allocate memory\n"); 15.160 + return -ENOMEM; 15.161 + } 15.162 + memset(new_mc, 0, UCODE_MAX_SIZE); 15.163 + 15.164 + /* free previous update file */ 15.165 + xfree(uci->mc.mc_amd); 15.166 + 15.167 + memcpy(new_mc, mc, total_size); 15.168 + 15.169 + uci->mc.mc_amd = new_mc; 15.170 + return 1; 15.171 +} 15.172 + 15.173 +static int apply_microcode(int cpu) 15.174 +{ 15.175 + unsigned long flags; 15.176 + uint32_t eax, edx, rev; 15.177 + int cpu_num = raw_smp_processor_id(); 15.178 + struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 15.179 + uint64_t addr; 15.180 + 15.181 + /* We should bind the task to the CPU */ 15.182 + BUG_ON(cpu_num != cpu); 15.183 + 15.184 + if ( uci->mc.mc_amd == NULL ) 15.185 + return -EINVAL; 15.186 + 15.187 + spin_lock_irqsave(µcode_update_lock, flags); 15.188 + 15.189 + addr = (unsigned long)&uci->mc.mc_amd->hdr.data_code; 15.190 + edx = (uint32_t)(addr >> 32); 15.191 + eax = (uint32_t)addr; 15.192 + 15.193 + asm volatile ( 15.194 + "movl %0, %%ecx; wrmsr" : 15.195 + : "i" (MSR_AMD_PATCHLOADER), "a" (eax), "d" (edx) : "ecx" ); 15.196 + 15.197 + /* get patch id after patching */ 15.198 + asm volatile ( 15.199 + "movl %1, %%ecx; rdmsr" 15.200 + : "=a" (rev) 15.201 + : "i" (MSR_AMD_PATCHLEVEL) : "ecx"); 15.202 + 15.203 + spin_unlock_irqrestore(µcode_update_lock, flags); 15.204 + 15.205 + /* check current patch id and patch's id for match */ 15.206 + if ( rev != uci->mc.mc_amd->hdr.patch_id ) 15.207 + { 15.208 + printk(KERN_ERR "microcode: CPU%d update from revision " 15.209 + "0x%x to 0x%x failed\n", cpu_num, 15.210 + uci->mc.mc_amd->hdr.patch_id, rev); 15.211 + return -EIO; 15.212 + } 15.213 + 15.214 + printk("microcode: CPU%d updated from revision " 15.215 + "0x%x to 0x%x \n", 15.216 + cpu_num, uci->cpu_sig.rev, uci->mc.mc_amd->hdr.patch_id); 15.217 + 15.218 + uci->cpu_sig.rev = rev; 15.219 + 15.220 + return 0; 15.221 +} 15.222 + 15.223 +static long get_next_ucode_from_buffer_amd(void **mc, const void *buf, 15.224 + unsigned long size, long offset) 15.225 +{ 15.226 + struct microcode_header_amd *mc_header; 15.227 + unsigned long total_size; 15.228 + const uint8_t *buf_pos = buf; 15.229 + 15.230 + /* No more data */ 15.231 + if ( offset >= size ) 15.232 + return 0; 15.233 + 15.234 + if ( buf_pos[offset] != UCODE_UCODE_TYPE ) 15.235 + { 15.236 + printk(KERN_ERR "microcode: error! " 15.237 + "Wrong microcode payload type field\n"); 15.238 + return -EINVAL; 15.239 + } 15.240 + 15.241 + mc_header = (struct microcode_header_amd *)(&buf_pos[offset+8]); 15.242 + 15.243 + total_size = (unsigned long) (buf_pos[offset+4] + 15.244 + (buf_pos[offset+5] << 8)); 15.245 + 15.246 + printk(KERN_INFO "microcode: size %lu, total_size %lu, offset %ld\n", 15.247 + size, total_size, offset); 15.248 + 15.249 + if ( (offset + total_size) > size ) 15.250 + { 15.251 + printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); 15.252 + return -EINVAL; 15.253 + } 15.254 + 15.255 + *mc = xmalloc_bytes(UCODE_MAX_SIZE); 15.256 + if ( *mc == NULL ) 15.257 + { 15.258 + printk(KERN_ERR "microcode: error! " 15.259 + "Can not allocate memory for microcode patch\n"); 15.260 + return -ENOMEM; 15.261 + } 15.262 + 15.263 + memset(*mc, 0, UCODE_MAX_SIZE); 15.264 + memcpy(*mc, (const void *)(buf + offset + 8), total_size); 15.265 + 15.266 + return offset + total_size + 8; 15.267 +} 15.268 + 15.269 +static long install_equiv_cpu_table(const void *buf, 15.270 + uint32_t size, long offset) 15.271 +{ 15.272 + const uint32_t *buf_pos = buf; 15.273 + 15.274 + /* No more data */ 15.275 + if ( offset >= size ) 15.276 + return 0; 15.277 + 15.278 + if ( buf_pos[1] != UCODE_EQUIV_CPU_TABLE_TYPE ) 15.279 + { 15.280 + printk(KERN_ERR "microcode: error! " 15.281 + "Wrong microcode equivalnet cpu table type field\n"); 15.282 + return 0; 15.283 + } 15.284 + 15.285 + if ( size == 0 ) 15.286 + { 15.287 + printk(KERN_ERR "microcode: error! " 15.288 + "Wrong microcode equivalnet cpu table length\n"); 15.289 + return 0; 15.290 + } 15.291 + 15.292 + equiv_cpu_table = xmalloc_bytes(size); 15.293 + if ( equiv_cpu_table == NULL ) 15.294 + { 15.295 + printk(KERN_ERR "microcode: error, can't allocate " 15.296 + "memory for equiv CPU table\n"); 15.297 + return 0; 15.298 + } 15.299 + 15.300 + memset(equiv_cpu_table, 0, size); 15.301 + memcpy(equiv_cpu_table, (const void *)&buf_pos[3], size); 15.302 + 15.303 + return size + 12; /* add header length */ 15.304 +} 15.305 + 15.306 +static int cpu_request_microcode(int cpu, const void *buf, size_t size) 15.307 +{ 15.308 + const uint32_t *buf_pos; 15.309 + long offset = 0; 15.310 + int error = 0; 15.311 + void *mc; 15.312 + 15.313 + /* We should bind the task to the CPU */ 15.314 + BUG_ON(cpu != raw_smp_processor_id()); 15.315 + 15.316 + buf_pos = (const uint32_t *)buf; 15.317 + 15.318 + if ( buf_pos[0] != UCODE_MAGIC ) 15.319 + { 15.320 + printk(KERN_ERR "microcode: error! Wrong " 15.321 + "microcode patch file magic\n"); 15.322 + return -EINVAL; 15.323 + } 15.324 + 15.325 + offset = install_equiv_cpu_table(buf, (uint32_t)(buf_pos[2]), offset); 15.326 + if ( !offset ) 15.327 + { 15.328 + printk(KERN_ERR "microcode: installing equivalent cpu table failed\n"); 15.329 + return -EINVAL; 15.330 + } 15.331 + 15.332 + while ( (offset = 15.333 + get_next_ucode_from_buffer_amd(&mc, buf, size, offset)) > 0 ) 15.334 + { 15.335 + error = get_matching_microcode(mc, cpu); 15.336 + if ( error < 0 ) 15.337 + break; 15.338 + /* 15.339 + * It's possible the data file has multiple matching ucode, 15.340 + * lets keep searching till the latest version 15.341 + */ 15.342 + if ( error == 1 ) 15.343 + { 15.344 + apply_microcode(cpu); 15.345 + error = 0; 15.346 + } 15.347 + xfree(mc); 15.348 + } 15.349 + if ( offset > 0 ) 15.350 + { 15.351 + xfree(mc); 15.352 + xfree(equiv_cpu_table); 15.353 + equiv_cpu_table = NULL; 15.354 + } 15.355 + if ( offset < 0 ) 15.356 + error = offset; 15.357 + 15.358 + return error; 15.359 +} 15.360 + 15.361 +static struct microcode_ops microcode_amd_ops = { 15.362 + .get_matching_microcode = get_matching_microcode, 15.363 + .cpu_request_microcode = cpu_request_microcode, 15.364 + .collect_cpu_info = collect_cpu_info, 15.365 + .apply_microcode = apply_microcode, 15.366 +}; 15.367 + 15.368 +static __init int microcode_init_amd(void) 15.369 +{ 15.370 + if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD ) 15.371 + microcode_ops = µcode_amd_ops; 15.372 + return 0; 15.373 +} 15.374 +__initcall(microcode_init_amd);
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/xen/arch/x86/microcode_intel.c Tue Sep 16 21:25:30 2008 +0900 16.3 @@ -0,0 +1,370 @@ 16.4 +/* 16.5 + * Intel CPU Microcode Update Driver for Linux 16.6 + * 16.7 + * Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk> 16.8 + * 2006 Shaohua Li <shaohua.li@intel.com> * 16.9 + * This driver allows to upgrade microcode on Intel processors 16.10 + * belonging to IA-32 family - PentiumPro, Pentium II, 16.11 + * Pentium III, Xeon, Pentium 4, etc. 16.12 + * 16.13 + * Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture 16.14 + * Software Developer's Manual 16.15 + * Order Number 253668 or free download from: 16.16 + * 16.17 + * http://developer.intel.com/design/pentium4/manuals/253668.htm 16.18 + * 16.19 + * For more information, go to http://www.urbanmyth.org/microcode 16.20 + * 16.21 + * This program is free software; you can redistribute it and/or 16.22 + * modify it under the terms of the GNU General Public License 16.23 + * as published by the Free Software Foundation; either version 16.24 + * 2 of the License, or (at your option) any later version. 16.25 + */ 16.26 + 16.27 +#include <xen/config.h> 16.28 +#include <xen/lib.h> 16.29 +#include <xen/kernel.h> 16.30 +#include <xen/init.h> 16.31 +#include <xen/sched.h> 16.32 +#include <xen/smp.h> 16.33 +#include <xen/spinlock.h> 16.34 + 16.35 +#include <asm/msr.h> 16.36 +#include <asm/uaccess.h> 16.37 +#include <asm/processor.h> 16.38 +#include <asm/microcode.h> 16.39 + 16.40 +#define pr_debug(x...) ((void)0) 16.41 + 16.42 +#define DEFAULT_UCODE_DATASIZE (2000) 16.43 +#define MC_HEADER_SIZE (sizeof(struct microcode_header_intel)) 16.44 +#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) 16.45 +#define EXT_HEADER_SIZE (sizeof(struct extended_sigtable)) 16.46 +#define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature)) 16.47 +#define DWSIZE (sizeof(u32)) 16.48 +#define get_totalsize(mc) \ 16.49 + (((struct microcode_intel *)mc)->hdr.totalsize ? \ 16.50 + ((struct microcode_intel *)mc)->hdr.totalsize : \ 16.51 + DEFAULT_UCODE_TOTALSIZE) 16.52 + 16.53 +#define get_datasize(mc) \ 16.54 + (((struct microcode_intel *)mc)->hdr.datasize ? \ 16.55 + ((struct microcode_intel *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE) 16.56 + 16.57 +#define sigmatch(s1, s2, p1, p2) \ 16.58 + (((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0)))) 16.59 + 16.60 +#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE) 16.61 + 16.62 +/* serialize access to the physical write to MSR 0x79 */ 16.63 +static DEFINE_SPINLOCK(microcode_update_lock); 16.64 + 16.65 +static int collect_cpu_info(int cpu_num, struct cpu_signature *csig) 16.66 +{ 16.67 + struct cpuinfo_x86 *c = &cpu_data[cpu_num]; 16.68 + unsigned int val[2]; 16.69 + 16.70 + memset(csig, 0, sizeof(*csig)); 16.71 + 16.72 + if ( (c->x86_vendor != X86_VENDOR_INTEL) || (c->x86 < 6) || 16.73 + cpu_has(c, X86_FEATURE_IA64) ) 16.74 + { 16.75 + printk(KERN_ERR "microcode: CPU%d not a capable Intel " 16.76 + "processor\n", cpu_num); 16.77 + return -1; 16.78 + } 16.79 + 16.80 + csig->sig = cpuid_eax(0x00000001); 16.81 + 16.82 + if ( (c->x86_model >= 5) || (c->x86 > 6) ) 16.83 + { 16.84 + /* get processor flags from MSR 0x17 */ 16.85 + rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); 16.86 + csig->pf = 1 << ((val[1] >> 18) & 7); 16.87 + } 16.88 + 16.89 + wrmsr(MSR_IA32_UCODE_REV, 0, 0); 16.90 + /* see notes above for revision 1.07. Apparent chip bug */ 16.91 + sync_core(); 16.92 + /* get the current revision from MSR 0x8B */ 16.93 + rdmsr(MSR_IA32_UCODE_REV, val[0], csig->rev); 16.94 + pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n", 16.95 + csig->sig, csig->pf, csig->rev); 16.96 + 16.97 + return 0; 16.98 +} 16.99 + 16.100 +static inline int microcode_update_match( 16.101 + int cpu_num, struct microcode_header_intel *mc_header, int sig, int pf) 16.102 +{ 16.103 + struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 16.104 + 16.105 + return (sigmatch(sig, uci->cpu_sig.sig, pf, uci->cpu_sig.pf) && 16.106 + (mc_header->rev > uci->cpu_sig.rev)); 16.107 +} 16.108 + 16.109 +static int microcode_sanity_check(void *mc) 16.110 +{ 16.111 + struct microcode_header_intel *mc_header = mc; 16.112 + struct extended_sigtable *ext_header = NULL; 16.113 + struct extended_signature *ext_sig; 16.114 + unsigned long total_size, data_size, ext_table_size; 16.115 + int sum, orig_sum, ext_sigcount = 0, i; 16.116 + 16.117 + total_size = get_totalsize(mc_header); 16.118 + data_size = get_datasize(mc_header); 16.119 + if ( (data_size + MC_HEADER_SIZE) > total_size ) 16.120 + { 16.121 + printk(KERN_ERR "microcode: error! " 16.122 + "Bad data size in microcode data file\n"); 16.123 + return -EINVAL; 16.124 + } 16.125 + 16.126 + if ( (mc_header->ldrver != 1) || (mc_header->hdrver != 1) ) 16.127 + { 16.128 + printk(KERN_ERR "microcode: error! " 16.129 + "Unknown microcode update format\n"); 16.130 + return -EINVAL; 16.131 + } 16.132 + ext_table_size = total_size - (MC_HEADER_SIZE + data_size); 16.133 + if ( ext_table_size ) 16.134 + { 16.135 + if ( (ext_table_size < EXT_HEADER_SIZE) || 16.136 + ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE) ) 16.137 + { 16.138 + printk(KERN_ERR "microcode: error! " 16.139 + "Small exttable size in microcode data file\n"); 16.140 + return -EINVAL; 16.141 + } 16.142 + ext_header = mc + MC_HEADER_SIZE + data_size; 16.143 + if ( ext_table_size != exttable_size(ext_header) ) 16.144 + { 16.145 + printk(KERN_ERR "microcode: error! " 16.146 + "Bad exttable size in microcode data file\n"); 16.147 + return -EFAULT; 16.148 + } 16.149 + ext_sigcount = ext_header->count; 16.150 + } 16.151 + 16.152 + /* check extended table checksum */ 16.153 + if ( ext_table_size ) 16.154 + { 16.155 + int ext_table_sum = 0; 16.156 + int *ext_tablep = (int *)ext_header; 16.157 + 16.158 + i = ext_table_size / DWSIZE; 16.159 + while ( i-- ) 16.160 + ext_table_sum += ext_tablep[i]; 16.161 + if ( ext_table_sum ) 16.162 + { 16.163 + printk(KERN_WARNING "microcode: aborting, " 16.164 + "bad extended signature table checksum\n"); 16.165 + return -EINVAL; 16.166 + } 16.167 + } 16.168 + 16.169 + /* calculate the checksum */ 16.170 + orig_sum = 0; 16.171 + i = (MC_HEADER_SIZE + data_size) / DWSIZE; 16.172 + while ( i-- ) 16.173 + orig_sum += ((int *)mc)[i]; 16.174 + if ( orig_sum ) 16.175 + { 16.176 + printk(KERN_ERR "microcode: aborting, bad checksum\n"); 16.177 + return -EINVAL; 16.178 + } 16.179 + if ( !ext_table_size ) 16.180 + return 0; 16.181 + /* check extended signature checksum */ 16.182 + for ( i = 0; i < ext_sigcount; i++ ) 16.183 + { 16.184 + ext_sig = (void *)ext_header + EXT_HEADER_SIZE + 16.185 + EXT_SIGNATURE_SIZE * i; 16.186 + sum = orig_sum 16.187 + - (mc_header->sig + mc_header->pf + mc_header->cksum) 16.188 + + (ext_sig->sig + ext_sig->pf + ext_sig->cksum); 16.189 + if ( sum ) 16.190 + { 16.191 + printk(KERN_ERR "microcode: aborting, bad checksum\n"); 16.192 + return -EINVAL; 16.193 + } 16.194 + } 16.195 + return 0; 16.196 +} 16.197 + 16.198 +/* 16.199 + * return 0 - no update found 16.200 + * return 1 - found update 16.201 + * return < 0 - error 16.202 + */ 16.203 +static int get_matching_microcode(void *mc, int cpu) 16.204 +{ 16.205 + struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 16.206 + struct microcode_header_intel *mc_header = mc; 16.207 + struct extended_sigtable *ext_header; 16.208 + unsigned long total_size = get_totalsize(mc_header); 16.209 + int ext_sigcount, i; 16.210 + struct extended_signature *ext_sig; 16.211 + void *new_mc; 16.212 + 16.213 + if ( microcode_update_match(cpu, mc_header, 16.214 + mc_header->sig, mc_header->pf) ) 16.215 + goto find; 16.216 + 16.217 + if ( total_size <= (get_datasize(mc_header) + MC_HEADER_SIZE) ) 16.218 + return 0; 16.219 + 16.220 + ext_header = mc + get_datasize(mc_header) + MC_HEADER_SIZE; 16.221 + ext_sigcount = ext_header->count; 16.222 + ext_sig = (void *)ext_header + EXT_HEADER_SIZE; 16.223 + for ( i = 0; i < ext_sigcount; i++ ) 16.224 + { 16.225 + if ( microcode_update_match(cpu, mc_header, 16.226 + ext_sig->sig, ext_sig->pf) ) 16.227 + goto find; 16.228 + ext_sig++; 16.229 + } 16.230 + return 0; 16.231 + find: 16.232 + pr_debug("microcode: CPU%d found a matching microcode update with" 16.233 + " version 0x%x (current=0x%x)\n", 16.234 + cpu, mc_header->rev, uci->cpu_sig.rev); 16.235 + new_mc = xmalloc_bytes(total_size); 16.236 + if ( new_mc == NULL ) 16.237 + { 16.238 + printk(KERN_ERR "microcode: error! Can not allocate memory\n"); 16.239 + return -ENOMEM; 16.240 + } 16.241 + 16.242 + /* free previous update file */ 16.243 + xfree(uci->mc.mc_intel); 16.244 + 16.245 + memcpy(new_mc, mc, total_size); 16.246 + uci->mc.mc_intel = new_mc; 16.247 + return 1; 16.248 +} 16.249 + 16.250 +static int apply_microcode(int cpu) 16.251 +{ 16.252 + unsigned long flags; 16.253 + unsigned int val[2]; 16.254 + int cpu_num = raw_smp_processor_id(); 16.255 + struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 16.256 + 16.257 + /* We should bind the task to the CPU */ 16.258 + BUG_ON(cpu_num != cpu); 16.259 + 16.260 + if ( uci->mc.mc_intel == NULL ) 16.261 + return -EINVAL; 16.262 + 16.263 + /* serialize access to the physical write to MSR 0x79 */ 16.264 + spin_lock_irqsave(µcode_update_lock, flags); 16.265 + 16.266 + /* write microcode via MSR 0x79 */ 16.267 + wrmsr(MSR_IA32_UCODE_WRITE, 16.268 + (unsigned long) uci->mc.mc_intel->bits, 16.269 + (unsigned long) uci->mc.mc_intel->bits >> 16 >> 16); 16.270 + wrmsr(MSR_IA32_UCODE_REV, 0, 0); 16.271 + 16.272 + /* see notes above for revision 1.07. Apparent chip bug */ 16.273 + sync_core(); 16.274 + 16.275 + /* get the current revision from MSR 0x8B */ 16.276 + rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); 16.277 + 16.278 + spin_unlock_irqrestore(µcode_update_lock, flags); 16.279 + if ( val[1] != uci->mc.mc_intel->hdr.rev ) 16.280 + { 16.281 + printk(KERN_ERR "microcode: CPU%d update from revision " 16.282 + "0x%x to 0x%x failed\n", cpu_num, uci->cpu_sig.rev, val[1]); 16.283 + return -EIO; 16.284 + } 16.285 + printk(KERN_INFO "microcode: CPU%d updated from revision " 16.286 + "0x%x to 0x%x, date = %04x-%02x-%02x \n", 16.287 + cpu_num, uci->cpu_sig.rev, val[1], 16.288 + uci->mc.mc_intel->hdr.date & 0xffff, 16.289 + uci->mc.mc_intel->hdr.date >> 24, 16.290 + (uci->mc.mc_intel->hdr.date >> 16) & 0xff); 16.291 + uci->cpu_sig.rev = val[1]; 16.292 + 16.293 + return 0; 16.294 +} 16.295 + 16.296 +static long get_next_ucode_from_buffer(void **mc, const u8 *buf, 16.297 + unsigned long size, long offset) 16.298 +{ 16.299 + struct microcode_header_intel *mc_header; 16.300 + unsigned long total_size; 16.301 + 16.302 + /* No more data */ 16.303 + if ( offset >= size ) 16.304 + return 0; 16.305 + mc_header = (struct microcode_header_intel *)(buf + offset); 16.306 + total_size = get_totalsize(mc_header); 16.307 + 16.308 + if ( (offset + total_size) > size ) 16.309 + { 16.310 + printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); 16.311 + return -EINVAL; 16.312 + } 16.313 + 16.314 + *mc = xmalloc_bytes(total_size); 16.315 + if ( *mc == NULL ) 16.316 + { 16.317 + printk(KERN_ERR "microcode: error! Can not allocate memory\n"); 16.318 + return -ENOMEM; 16.319 + } 16.320 + memcpy(*mc, (const void *)(buf + offset), total_size); 16.321 + return offset + total_size; 16.322 +} 16.323 + 16.324 +static int cpu_request_microcode(int cpu, const void *buf, size_t size) 16.325 +{ 16.326 + long offset = 0; 16.327 + int error = 0; 16.328 + void *mc; 16.329 + 16.330 + /* We should bind the task to the CPU */ 16.331 + BUG_ON(cpu != raw_smp_processor_id()); 16.332 + 16.333 + while ( (offset = get_next_ucode_from_buffer(&mc, buf, size, offset)) > 0 ) 16.334 + { 16.335 + error = microcode_sanity_check(mc); 16.336 + if ( error ) 16.337 + break; 16.338 + error = get_matching_microcode(mc, cpu); 16.339 + if ( error < 0 ) 16.340 + break; 16.341 + /* 16.342 + * It's possible the data file has multiple matching ucode, 16.343 + * lets keep searching till the latest version 16.344 + */ 16.345 + if ( error == 1 ) 16.346 + { 16.347 + apply_microcode(cpu); 16.348 + error = 0; 16.349 + } 16.350 + xfree(mc); 16.351 + } 16.352 + if ( offset > 0 ) 16.353 + xfree(mc); 16.354 + if ( offset < 0 ) 16.355 + error = offset; 16.356 + 16.357 + return error; 16.358 +} 16.359 + 16.360 +static struct microcode_ops microcode_intel_ops = { 16.361 + .get_matching_microcode = get_matching_microcode, 16.362 + .cpu_request_microcode = cpu_request_microcode, 16.363 + .collect_cpu_info = collect_cpu_info, 16.364 + .apply_microcode = apply_microcode, 16.365 +}; 16.366 + 16.367 +static __init int microcode_init_intel(void) 16.368 +{ 16.369 + if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL ) 16.370 + microcode_ops = µcode_intel_ops; 16.371 + return 0; 16.372 +} 16.373 +__initcall(microcode_init_intel);
17.1 --- a/xen/arch/x86/mm/shadow/common.c Fri Sep 12 14:47:40 2008 +0900 17.2 +++ b/xen/arch/x86/mm/shadow/common.c Tue Sep 16 21:25:30 2008 +0900 17.3 @@ -2385,11 +2385,13 @@ int sh_remove_write_access(struct vcpu * 17.4 + ((fault_addr & VADDR_MASK) >> 27), 3); break; 17.5 } 17.6 17.7 - /* 64bit Linux direct map at 0xffff810000000000; older kernels 17.8 - * had it at 0x0000010000000000UL */ 17.9 + /* 64bit Linux direct map at 0xffff880000000000; older kernels 17.10 + * had it at 0xffff810000000000, and older kernels yet had it 17.11 + * at 0x0000010000000000UL */ 17.12 gfn = mfn_to_gfn(v->domain, gmfn); 17.13 - GUESS(0xffff810000000000UL + (gfn << PAGE_SHIFT), 4); 17.14 - GUESS(0x0000010000000000UL + (gfn << PAGE_SHIFT), 4); 17.15 + GUESS(0xffff880000000000UL + (gfn << PAGE_SHIFT), 4); 17.16 + GUESS(0xffff810000000000UL + (gfn << PAGE_SHIFT), 4); 17.17 + GUESS(0x0000010000000000UL + (gfn << PAGE_SHIFT), 4); 17.18 /* 17.19 * 64bit Solaris kernel page map at 17.20 * kpm_vbase; 0xfffffe0000000000UL 17.21 @@ -2462,22 +2464,25 @@ int sh_remove_write_access_from_sl1p(str 17.22 ASSERT(mfn_valid(smfn)); 17.23 ASSERT(mfn_valid(gmfn)); 17.24 17.25 - if ( sp->type == SH_type_l1_32_shadow ) 17.26 + if ( sp->type == SH_type_l1_32_shadow 17.27 + || sp->type == SH_type_fl1_32_shadow ) 17.28 { 17.29 return SHADOW_INTERNAL_NAME(sh_rm_write_access_from_sl1p,2) 17.30 (v, gmfn, smfn, off); 17.31 } 17.32 #if CONFIG_PAGING_LEVELS >= 3 17.33 - else if ( sp->type == SH_type_l1_pae_shadow ) 17.34 + else if ( sp->type == SH_type_l1_pae_shadow 17.35 + || sp->type == SH_type_fl1_pae_shadow ) 17.36 return SHADOW_INTERNAL_NAME(sh_rm_write_access_from_sl1p,3) 17.37 (v, gmfn, smfn, off); 17.38 #if CONFIG_PAGING_LEVELS >= 4 17.39 - else if ( sp->type == SH_type_l1_64_shadow ) 17.40 + else if ( sp->type == SH_type_l1_64_shadow 17.41 + || sp->type == SH_type_fl1_64_shadow ) 17.42 return SHADOW_INTERNAL_NAME(sh_rm_write_access_from_sl1p,4) 17.43 (v, gmfn, smfn, off); 17.44 #endif 17.45 #endif 17.46 - 17.47 + 17.48 return 0; 17.49 } 17.50 #endif
18.1 --- a/xen/arch/x86/mm/shadow/multi.c Fri Sep 12 14:47:40 2008 +0900 18.2 +++ b/xen/arch/x86/mm/shadow/multi.c Tue Sep 16 21:25:30 2008 +0900 18.3 @@ -4539,7 +4539,8 @@ int sh_rm_write_access_from_sl1p(struct 18.4 sp = mfn_to_shadow_page(smfn); 18.5 18.6 if ( sp->mbz != 0 18.7 - || (sp->type != SH_type_l1_shadow) ) 18.8 + || (sp->type != SH_type_l1_shadow 18.9 + && sp->type != SH_type_fl1_shadow) ) 18.10 goto fail; 18.11 18.12 sl1p = sh_map_domain_page(smfn);
19.1 --- a/xen/arch/x86/platform_hypercall.c Fri Sep 12 14:47:40 2008 +0900 19.2 +++ b/xen/arch/x86/platform_hypercall.c Tue Sep 16 21:25:30 2008 +0900 19.3 @@ -393,7 +393,6 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe 19.4 memcpy ((void *)&pxpt->status_register, 19.5 (void *)&xenpxpt->status_register, 19.6 sizeof(struct xen_pct_register)); 19.7 - pxpt->init |= XEN_PX_PCT; 19.8 } 19.9 if ( xenpxpt->flags & XEN_PX_PSS ) 19.10 { 19.11 @@ -411,7 +410,6 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe 19.12 break; 19.13 } 19.14 pxpt->state_count = xenpxpt->state_count; 19.15 - pxpt->init |= XEN_PX_PSS; 19.16 } 19.17 if ( xenpxpt->flags & XEN_PX_PSD ) 19.18 { 19.19 @@ -419,27 +417,34 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe 19.20 memcpy ((void *)&pxpt->domain_info, 19.21 (void *)&xenpxpt->domain_info, 19.22 sizeof(struct xen_psd_package)); 19.23 - pxpt->init |= XEN_PX_PSD; 19.24 } 19.25 if ( xenpxpt->flags & XEN_PX_PPC ) 19.26 { 19.27 - pxpt->ppc = xenpxpt->ppc; 19.28 - pxpt->init |= XEN_PX_PPC; 19.29 + pxpt->platform_limit = xenpxpt->platform_limit; 19.30 + 19.31 + if ( pxpt->init == XEN_PX_INIT ) 19.32 + { 19.33 + ret = cpufreq_limit_change(cpuid); 19.34 + break; 19.35 + } 19.36 } 19.37 19.38 - if ( pxpt->init == ( XEN_PX_PCT | XEN_PX_PSS | 19.39 - XEN_PX_PSD | XEN_PX_PPC ) ) 19.40 + if ( xenpxpt->flags == ( XEN_PX_PCT | XEN_PX_PSS | 19.41 + XEN_PX_PSD | XEN_PX_PPC ) ) 19.42 { 19.43 - pxpt->init |= XEN_PX_INIT; 19.44 + pxpt->init = XEN_PX_INIT; 19.45 cpu_count++; 19.46 - } 19.47 - if ( cpu_count == num_online_cpus() ) 19.48 - { 19.49 - if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD ) 19.50 + 19.51 + /* Currently we only handle Intel and AMD processor */ 19.52 + if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL ) 19.53 + ret = cpufreq_add_cpu(cpuid); 19.54 + else if ( (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && 19.55 + (cpu_count == num_online_cpus()) ) 19.56 ret = powernow_cpufreq_init(); 19.57 else 19.58 - ret = acpi_cpufreq_init(); 19.59 + break; 19.60 } 19.61 + 19.62 break; 19.63 } 19.64
20.1 --- a/xen/arch/x86/smpboot.c Fri Sep 12 14:47:40 2008 +0900 20.2 +++ b/xen/arch/x86/smpboot.c Tue Sep 16 21:25:30 2008 +0900 20.3 @@ -55,6 +55,7 @@ 20.4 #include <mach_wakecpu.h> 20.5 #include <smpboot_hooks.h> 20.6 #include <xen/stop_machine.h> 20.7 +#include <acpi/cpufreq/processor_perf.h> 20.8 20.9 #define set_kernel_exec(x, y) (0) 20.10 #define setup_trampoline() (bootsym_phys(trampoline_realmode_entry)) 20.11 @@ -1232,6 +1233,8 @@ int __cpu_disable(void) 20.12 mdelay(1); 20.13 local_irq_disable(); 20.14 20.15 + cpufreq_del_cpu(cpu); 20.16 + 20.17 time_suspend(); 20.18 20.19 remove_siblinginfo(cpu); 20.20 @@ -1421,6 +1424,8 @@ int __devinit __cpu_up(unsigned int cpu) 20.21 mb(); 20.22 process_pending_timers(); 20.23 } 20.24 + 20.25 + cpufreq_add_cpu(cpu); 20.26 return 0; 20.27 } 20.28
21.1 --- a/xen/common/gdbstub.c Fri Sep 12 14:47:40 2008 +0900 21.2 +++ b/xen/common/gdbstub.c Tue Sep 16 21:25:30 2008 +0900 21.3 @@ -65,7 +65,7 @@ static atomic_t gdb_smp_paused_count; 21.4 static void gdb_smp_pause(void); 21.5 static void gdb_smp_resume(void); 21.6 21.7 -static char opt_gdb[30] = "none"; 21.8 +static char opt_gdb[30]; 21.9 string_param("gdb", opt_gdb); 21.10 21.11 static void gdbstub_console_puts(const char *str); 21.12 @@ -625,10 +625,19 @@ int 21.13 void __init 21.14 initialise_gdb(void) 21.15 { 21.16 + if ( *opt_gdb == '\0' ) 21.17 + return; 21.18 + 21.19 gdb_ctx->serhnd = serial_parse_handle(opt_gdb); 21.20 - if ( gdb_ctx->serhnd != -1 ) 21.21 - printk("GDB stub initialised.\n"); 21.22 + if ( gdb_ctx->serhnd == -1 ) 21.23 + { 21.24 + printk("Bad gdb= option '%s'\n", opt_gdb); 21.25 + return; 21.26 + } 21.27 + 21.28 serial_start_sync(gdb_ctx->serhnd); 21.29 + 21.30 + printk("GDB stub initialised.\n"); 21.31 } 21.32 21.33 static void gdb_pause_this_cpu(void *unused)
22.1 --- a/xen/drivers/char/console.c Fri Sep 12 14:47:40 2008 +0900 22.2 +++ b/xen/drivers/char/console.c Tue Sep 16 21:25:30 2008 +0900 22.3 @@ -543,10 +543,18 @@ void __init init_console(void) 22.4 { 22.5 if ( *p == ',' ) 22.6 p++; 22.7 - if ( strncmp(p, "com", 3) == 0 ) 22.8 - sercon_handle = serial_parse_handle(p); 22.9 - else if ( strncmp(p, "vga", 3) == 0 ) 22.10 + if ( !strncmp(p, "vga", 3) ) 22.11 vga_init(); 22.12 + else if ( strncmp(p, "com", 3) || 22.13 + (sercon_handle = serial_parse_handle(p)) == -1 ) 22.14 + { 22.15 + char *q = strchr(p, ','); 22.16 + if ( q != NULL ) 22.17 + *q = '\0'; 22.18 + printk("Bad console= option '%s'\n", p); 22.19 + if ( q != NULL ) 22.20 + *q = ','; 22.21 + } 22.22 } 22.23 22.24 serial_set_rx_handler(sercon_handle, serial_rx);
23.1 --- a/xen/drivers/char/ns16550.c Fri Sep 12 14:47:40 2008 +0900 23.2 +++ b/xen/drivers/char/ns16550.c Tue Sep 16 21:25:30 2008 +0900 23.3 @@ -82,6 +82,7 @@ static struct ns16550 { 23.4 #define MCR_DTR 0x01 /* Data Terminal Ready */ 23.5 #define MCR_RTS 0x02 /* Request to Send */ 23.6 #define MCR_OUT2 0x08 /* OUT2: interrupt mask */ 23.7 +#define MCR_LOOP 0x10 /* Enable loopback test mode */ 23.8 23.9 /* Line Status Register */ 23.10 #define LSR_DR 0x01 /* Data ready */ 23.11 @@ -295,6 +296,37 @@ static int __init parse_parity_char(int 23.12 return 0; 23.13 } 23.14 23.15 +static int check_existence(struct ns16550 *uart) 23.16 +{ 23.17 + unsigned char status, scratch, scratch2, scratch3; 23.18 + 23.19 + /* 23.20 + * Do a simple existence test first; if we fail this, 23.21 + * there's no point trying anything else. 23.22 + */ 23.23 + scratch = ns_read_reg(uart, IER); 23.24 + ns_write_reg(uart, IER, 0); 23.25 + 23.26 + /* 23.27 + * Mask out IER[7:4] bits for test as some UARTs (e.g. TL 23.28 + * 16C754B) allow only to modify them if an EFR bit is set. 23.29 + */ 23.30 + scratch2 = ns_read_reg(uart, IER) & 0x0f; 23.31 + ns_write_reg(uart, IER, 0x0F); 23.32 + scratch3 = ns_read_reg(uart, IER) & 0x0f; 23.33 + ns_write_reg(uart, IER, scratch); 23.34 + if ( (scratch2 != 0) || (scratch3 != 0x0F) ) 23.35 + return 0; 23.36 + 23.37 + /* 23.38 + * Check to see if a UART is really there. 23.39 + * Use loopback test mode. 23.40 + */ 23.41 + ns_write_reg(uart, MCR, MCR_LOOP | 0x0A); 23.42 + status = ns_read_reg(uart, MSR) & 0xF0; 23.43 + return (status == 0x90); 23.44 +} 23.45 + 23.46 #define PARSE_ERR(_f, _a...) \ 23.47 do { \ 23.48 printk( "ERROR: " _f "\n" , ## _a ); \ 23.49 @@ -357,6 +389,8 @@ static void __init ns16550_parse_port_co 23.50 PARSE_ERR("%d stop bits are unsupported.", uart->stop_bits); 23.51 if ( uart->io_base == 0 ) 23.52 PARSE_ERR("I/O base address must be specified."); 23.53 + if ( !check_existence(uart) ) 23.54 + PARSE_ERR("16550-compatible serial UART not present"); 23.55 23.56 /* Register with generic serial driver. */ 23.57 serial_register_uart(uart - ns16550_com, &ns16550_driver, uart);
24.1 --- a/xen/drivers/char/serial.c Fri Sep 12 14:47:40 2008 +0900 24.2 +++ b/xen/drivers/char/serial.c Tue Sep 16 21:25:30 2008 +0900 24.3 @@ -258,11 +258,7 @@ int serial_parse_handle(char *conf) 24.4 { 24.5 int handle; 24.6 24.7 - /* Silently fail if user has explicitly requested no serial I/O. */ 24.8 - if ( strcmp(conf, "none") == 0 ) 24.9 - return -1; 24.10 - 24.11 - if ( strncmp(conf, "com", 3) != 0 ) 24.12 + if ( strncmp(conf, "com", 3) ) 24.13 goto fail; 24.14 24.15 switch ( conf[3] ) 24.16 @@ -277,6 +273,9 @@ int serial_parse_handle(char *conf) 24.17 goto fail; 24.18 } 24.19 24.20 + if ( !com[handle].driver ) 24.21 + goto fail; 24.22 + 24.23 if ( conf[4] == 'H' ) 24.24 handle |= SERHND_HI; 24.25 else if ( conf[4] == 'L' ) 24.26 @@ -287,7 +286,6 @@ int serial_parse_handle(char *conf) 24.27 return handle; 24.28 24.29 fail: 24.30 - printk("ERROR: bad serial-interface specification '%s'\n", conf); 24.31 return -1; 24.32 } 24.33
25.1 --- a/xen/drivers/passthrough/vtd/iommu.c Fri Sep 12 14:47:40 2008 +0900 25.2 +++ b/xen/drivers/passthrough/vtd/iommu.c Tue Sep 16 21:25:30 2008 +0900 25.3 @@ -152,6 +152,7 @@ static u64 bus_to_context_maddr(struct i 25.4 maddr = alloc_pgtable_maddr(); 25.5 if ( maddr == 0 ) 25.6 { 25.7 + unmap_vtd_domain_page(root_entries); 25.8 spin_unlock_irqrestore(&iommu->lock, flags); 25.9 return 0; 25.10 }
26.1 --- a/xen/include/acpi/cpufreq/cpufreq.h Fri Sep 12 14:47:40 2008 +0900 26.2 +++ b/xen/include/acpi/cpufreq/cpufreq.h Tue Sep 16 21:25:30 2008 +0900 26.3 @@ -19,6 +19,8 @@ 26.4 26.5 #define CPUFREQ_NAME_LEN 16 26.6 26.7 +struct cpufreq_governor; 26.8 + 26.9 struct cpufreq_cpuinfo { 26.10 unsigned int max_freq; 26.11 unsigned int min_freq; 26.12 @@ -30,16 +32,21 @@ struct cpufreq_policy { 26.13 unsigned int shared_type; /* ANY or ALL affected CPUs 26.14 should set cpufreq */ 26.15 unsigned int cpu; /* cpu nr of registered CPU */ 26.16 - struct cpufreq_cpuinfo cpuinfo; /* see above */ 26.17 + struct cpufreq_cpuinfo cpuinfo; 26.18 26.19 unsigned int min; /* in kHz */ 26.20 unsigned int max; /* in kHz */ 26.21 unsigned int cur; /* in kHz, only needed if cpufreq 26.22 * governors are used */ 26.23 + struct cpufreq_governor *governor; 26.24 + 26.25 unsigned int resume; /* flag for cpufreq 1st run 26.26 * S3 wakeup, hotplug cpu, etc */ 26.27 }; 26.28 -extern struct cpufreq_policy xen_px_policy[NR_CPUS]; 26.29 +extern struct cpufreq_policy *cpufreq_cpu_policy[NR_CPUS]; 26.30 + 26.31 +extern int __cpufreq_set_policy(struct cpufreq_policy *data, 26.32 + struct cpufreq_policy *policy); 26.33 26.34 #define CPUFREQ_SHARED_TYPE_NONE (0) /* None */ 26.35 #define CPUFREQ_SHARED_TYPE_HW (1) /* HW does needed coordination */ 26.36 @@ -64,12 +71,27 @@ struct cpufreq_freqs { 26.37 #define CPUFREQ_GOV_STOP 2 26.38 #define CPUFREQ_GOV_LIMITS 3 26.39 26.40 +struct cpufreq_governor { 26.41 + char name[CPUFREQ_NAME_LEN]; 26.42 + int (*governor)(struct cpufreq_policy *policy, 26.43 + unsigned int event); 26.44 +}; 26.45 + 26.46 +extern struct cpufreq_governor cpufreq_gov_dbs; 26.47 +#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_dbs 26.48 + 26.49 /* pass a target to the cpufreq driver */ 26.50 extern int __cpufreq_driver_target(struct cpufreq_policy *policy, 26.51 unsigned int target_freq, 26.52 unsigned int relation); 26.53 extern int __cpufreq_driver_getavg(struct cpufreq_policy *policy); 26.54 26.55 +static __inline__ int 26.56 +__cpufreq_governor(struct cpufreq_policy *policy, unsigned int event) 26.57 +{ 26.58 + return policy->governor->governor(policy, event); 26.59 +} 26.60 + 26.61 26.62 /********************************************************************* 26.63 * CPUFREQ DRIVER INTERFACE * 26.64 @@ -91,7 +113,50 @@ struct cpufreq_driver { 26.65 26.66 extern struct cpufreq_driver *cpufreq_driver; 26.67 26.68 -void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state); 26.69 +static __inline__ 26.70 +int cpufreq_register_driver(struct cpufreq_driver *driver_data) 26.71 +{ 26.72 + if (!driver_data || 26.73 + !driver_data->init || 26.74 + !driver_data->exit || 26.75 + !driver_data->verify || 26.76 + !driver_data->target) 26.77 + return -EINVAL; 26.78 + 26.79 + if (cpufreq_driver) 26.80 + return -EBUSY; 26.81 + 26.82 + cpufreq_driver = driver_data; 26.83 + return 0; 26.84 +} 26.85 + 26.86 +static __inline__ 26.87 +int cpufreq_unregister_driver(struct cpufreq_driver *driver) 26.88 +{ 26.89 + if (!cpufreq_driver || (driver != cpufreq_driver)) 26.90 + return -EINVAL; 26.91 + 26.92 + cpufreq_driver = NULL; 26.93 + return 0; 26.94 +} 26.95 + 26.96 +static __inline__ 26.97 +void cpufreq_verify_within_limits(struct cpufreq_policy *policy, 26.98 + unsigned int min, unsigned int max) 26.99 +{ 26.100 + if (policy->min < min) 26.101 + policy->min = min; 26.102 + if (policy->max < min) 26.103 + policy->max = min; 26.104 + if (policy->min > max) 26.105 + policy->min = max; 26.106 + if (policy->max > max) 26.107 + policy->max = max; 26.108 + if (policy->min > policy->max) 26.109 + policy->min = policy->max; 26.110 + return; 26.111 +} 26.112 + 26.113 26.114 /********************************************************************* 26.115 * FREQUENCY TABLE HELPERS * 26.116 @@ -109,6 +174,9 @@ struct cpufreq_frequency_table { 26.117 int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, 26.118 struct cpufreq_frequency_table *table); 26.119 26.120 +int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, 26.121 + struct cpufreq_frequency_table *table); 26.122 + 26.123 int cpufreq_frequency_table_target(struct cpufreq_policy *policy, 26.124 struct cpufreq_frequency_table *table, 26.125 unsigned int target_freq,
27.1 --- a/xen/include/acpi/cpufreq/processor_perf.h Fri Sep 12 14:47:40 2008 +0900 27.2 +++ b/xen/include/acpi/cpufreq/processor_perf.h Tue Sep 16 21:25:30 2008 +0900 27.3 @@ -7,26 +7,23 @@ 27.4 #define XEN_PX_INIT 0x80000000 27.5 27.6 int get_cpu_id(u8); 27.7 -int acpi_cpufreq_init(void); 27.8 int powernow_cpufreq_init(void); 27.9 27.10 void px_statistic_update(cpumask_t, uint8_t, uint8_t); 27.11 -int px_statistic_init(int); 27.12 -void px_statistic_reset(int); 27.13 -void px_statistic_suspend(void); 27.14 -void px_statistic_resume(void); 27.15 +int px_statistic_init(unsigned int); 27.16 +void px_statistic_exit(unsigned int); 27.17 +void px_statistic_reset(unsigned int); 27.18 27.19 -void cpufreq_dom_exit(void); 27.20 -int cpufreq_dom_init(void); 27.21 -int cpufreq_dom_dbs(unsigned int); 27.22 -void cpufreq_suspend(void); 27.23 -int cpufreq_resume(void); 27.24 +int cpufreq_limit_change(unsigned int); 27.25 + 27.26 +int cpufreq_add_cpu(unsigned int); 27.27 +int cpufreq_del_cpu(unsigned int); 27.28 27.29 uint64_t get_cpu_idle_time(unsigned int); 27.30 27.31 struct processor_performance { 27.32 uint32_t state; 27.33 - uint32_t ppc; 27.34 + uint32_t platform_limit; 27.35 struct xen_pct_register control_register; 27.36 struct xen_pct_register status_register; 27.37 uint32_t state_count;
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 28.2 +++ b/xen/include/asm-x86/microcode.h Tue Sep 16 21:25:30 2008 +0900 28.3 @@ -0,0 +1,93 @@ 28.4 +#ifndef ASM_X86__MICROCODE_H 28.5 +#define ASM_X86__MICROCODE_H 28.6 + 28.7 +struct cpu_signature; 28.8 + 28.9 +struct microcode_ops { 28.10 + int (*get_matching_microcode)(void *mc, int cpu); 28.11 + int (*cpu_request_microcode)(int cpu, const void *buf, size_t size); 28.12 + int (*collect_cpu_info)(int cpu_num, struct cpu_signature *csig); 28.13 + int (*apply_microcode)(int cpu); 28.14 +}; 28.15 + 28.16 +struct microcode_header_intel { 28.17 + unsigned int hdrver; 28.18 + unsigned int rev; 28.19 + unsigned int date; 28.20 + unsigned int sig; 28.21 + unsigned int cksum; 28.22 + unsigned int ldrver; 28.23 + unsigned int pf; 28.24 + unsigned int datasize; 28.25 + unsigned int totalsize; 28.26 + unsigned int reserved[3]; 28.27 +}; 28.28 + 28.29 +struct microcode_intel { 28.30 + struct microcode_header_intel hdr; 28.31 + unsigned int bits[0]; 28.32 +}; 28.33 + 28.34 +/* microcode format is extended from prescott processors */ 28.35 +struct extended_signature { 28.36 + unsigned int sig; 28.37 + unsigned int pf; 28.38 + unsigned int cksum; 28.39 +}; 28.40 + 28.41 +struct extended_sigtable { 28.42 + unsigned int count; 28.43 + unsigned int cksum; 28.44 + unsigned int reserved[3]; 28.45 + struct extended_signature sigs[0]; 28.46 +}; 28.47 + 28.48 +struct equiv_cpu_entry { 28.49 + unsigned int installed_cpu; 28.50 + unsigned int fixed_errata_mask; 28.51 + unsigned int fixed_errata_compare; 28.52 + unsigned int equiv_cpu; 28.53 +}; 28.54 + 28.55 +struct microcode_header_amd { 28.56 + unsigned int data_code; 28.57 + unsigned int patch_id; 28.58 + unsigned char mc_patch_data_id[2]; 28.59 + unsigned char mc_patch_data_len; 28.60 + unsigned char init_flag; 28.61 + unsigned int mc_patch_data_checksum; 28.62 + unsigned int nb_dev_id; 28.63 + unsigned int sb_dev_id; 28.64 + unsigned char processor_rev_id[2]; 28.65 + unsigned char nb_rev_id; 28.66 + unsigned char sb_rev_id; 28.67 + unsigned char bios_api_rev; 28.68 + unsigned char reserved1[3]; 28.69 + unsigned int match_reg[8]; 28.70 +}; 28.71 + 28.72 +struct microcode_amd { 28.73 + struct microcode_header_amd hdr; 28.74 + unsigned int mpb[0]; 28.75 +}; 28.76 + 28.77 +struct cpu_signature { 28.78 + unsigned int sig; 28.79 + unsigned int pf; 28.80 + unsigned int rev; 28.81 +}; 28.82 + 28.83 +struct ucode_cpu_info { 28.84 + struct cpu_signature cpu_sig; 28.85 + int valid; 28.86 + union { 28.87 + struct microcode_intel *mc_intel; 28.88 + struct microcode_amd *mc_amd; 28.89 + void *valid_mc; 28.90 + } mc; 28.91 +}; 28.92 + 28.93 +extern struct ucode_cpu_info ucode_cpu_info[]; 28.94 +extern const struct microcode_ops *microcode_ops; 28.95 + 28.96 +#endif /* ASM_X86__MICROCODE_H */
29.1 --- a/xen/include/asm-x86/msr-index.h Fri Sep 12 14:47:40 2008 +0900 29.2 +++ b/xen/include/asm-x86/msr-index.h Tue Sep 16 21:25:30 2008 +0900 29.3 @@ -211,6 +211,10 @@ 29.4 #define FAM10H_MMIO_CONF_BASE_MASK 0xfffffff 29.5 #define FAM10H_MMIO_CONF_BASE_SHIFT 20 29.6 29.7 +/* AMD Microcode MSRs */ 29.8 +#define MSR_AMD_PATCHLEVEL 0x0000008b 29.9 +#define MSR_AMD_PATCHLOADER 0xc0010020 29.10 + 29.11 /* K6 MSRs */ 29.12 #define MSR_K6_EFER 0xc0000080 29.13 #define MSR_K6_STAR 0xc0000081
30.1 --- a/xen/include/asm-x86/processor.h Fri Sep 12 14:47:40 2008 +0900 30.2 +++ b/xen/include/asm-x86/processor.h Tue Sep 16 21:25:30 2008 +0900 30.3 @@ -486,41 +486,6 @@ long set_gdt(struct vcpu *d, 30.4 }) 30.5 long set_debugreg(struct vcpu *p, int reg, unsigned long value); 30.6 30.7 -struct microcode_header { 30.8 - unsigned int hdrver; 30.9 - unsigned int rev; 30.10 - unsigned int date; 30.11 - unsigned int sig; 30.12 - unsigned int cksum; 30.13 - unsigned int ldrver; 30.14 - unsigned int pf; 30.15 - unsigned int datasize; 30.16 - unsigned int totalsize; 30.17 - unsigned int reserved[3]; 30.18 -}; 30.19 - 30.20 -struct microcode { 30.21 - struct microcode_header hdr; 30.22 - unsigned int bits[0]; 30.23 -}; 30.24 - 30.25 -typedef struct microcode microcode_t; 30.26 -typedef struct microcode_header microcode_header_t; 30.27 - 30.28 -/* microcode format is extended from prescott processors */ 30.29 -struct extended_signature { 30.30 - unsigned int sig; 30.31 - unsigned int pf; 30.32 - unsigned int cksum; 30.33 -}; 30.34 - 30.35 -struct extended_sigtable { 30.36 - unsigned int count; 30.37 - unsigned int cksum; 30.38 - unsigned int reserved[3]; 30.39 - struct extended_signature sigs[0]; 30.40 -}; 30.41 - 30.42 /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ 30.43 static always_inline void rep_nop(void) 30.44 {
31.1 --- a/xen/include/public/platform.h Fri Sep 12 14:47:40 2008 +0900 31.2 +++ b/xen/include/public/platform.h Tue Sep 16 21:25:30 2008 +0900 31.3 @@ -289,7 +289,7 @@ struct xen_psd_package { 31.4 31.5 struct xen_processor_performance { 31.6 uint32_t flags; /* flag for Px sub info type */ 31.7 - uint32_t ppc; /* Platform limitation on freq usage */ 31.8 + uint32_t platform_limit; /* Platform limitation on freq usage */ 31.9 struct xen_pct_register control_register; 31.10 struct xen_pct_register status_register; 31.11 uint32_t state_count; /* total available performance states */