From: Rob Hoes Date: Wed, 17 Feb 2010 10:14:40 +0000 (+0000) Subject: CP-1635: Cpuid module to obtain CPU information X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=870867bd7efbed58843cf23bcab0f637d9dc202b;p=xcp%2Fxen-api-libs.git CP-1635: Cpuid module to obtain CPU information This module obtains the vendor/model/family/stepping as well as feature information from the CPU, and determines whether CPU feature masks can be applied. Signed-off-by: Rob Hoes --- diff --git a/.hgignore b/.hgignore index d42d65a..daa8cd2 100644 --- a/.hgignore +++ b/.hgignore @@ -14,3 +14,4 @@ autom4te\.cache/ ^config\.log$ ^config\.status$ ^configure$ +doc/* diff --git a/Makefile.in b/Makefile.in index a56c995..b810b72 100644 --- a/Makefile.in +++ b/Makefile.in @@ -31,6 +31,7 @@ ifeq ($(HAVE_DEVICE_MAPPER),1) endif $(MAKE) -C forking_executioner $(MAKE) -C mlvm + $(MAKE) -C cpuid .PHONY: allxen allxen: @@ -67,6 +68,7 @@ ifeq ($(HAVE_DEVICE_MAPPER),1) endif $(MAKE) -C forking_executioner install $(MAKE) -C mlvm install + $(MAKE) -C cpuid install installxen: ifeq ($(HAVE_XEN),1) @@ -102,6 +104,7 @@ ifeq ($(HAVE_DEVICE_MAPPER),1) endif $(MAKE) -C forking_executioner uninstall $(MAKE) -C mlvm uninstall + $(MAKE) -C cpuid uninstall uninstallxen: ifeq ($(HAVE_XEN),1) @@ -160,6 +163,7 @@ doc: $(MAKE) -C mmap doc $(MAKE) -C forking_executioner doc $(MAKE) -C mlvm doc + $(MAKE) -C cpuid doc .PHONY: clean clean: @@ -179,6 +183,7 @@ clean: make -C doc clean make -C forking_executioner clean make -C mlvm clean + make -C cpuid clean cleanxen: $(MAKE) -C mmap clean diff --git a/cpuid/META.in b/cpuid/META.in index 7a549ec..c5ced2f 100644 --- a/cpuid/META.in +++ b/cpuid/META.in @@ -1,5 +1,5 @@ version = "@VERSION@" description = "Cpuid extension" -requires = "stdext xc xen-utils" +requires = "" archive(byte) = "cpuid.cma" archive(native) = "cpuid.cmxa" diff --git a/cpuid/Makefile b/cpuid/Makefile index 8c47528..f62642f 100644 --- a/cpuid/Makefile +++ b/cpuid/Makefile @@ -1,8 +1,8 @@ CC = gcc -CFLAGS = -Wall -fPIC -O2 -I/usr/lib/ocaml -I$(XEN_ROOT)/usr/include +CFLAGS = -Wall -fPIC -O2 -I/opt/xensource/lib/ocaml -I$(XEN_ROOT)/usr/include OCAMLC = ocamlc -g OCAMLOPT = ocamlopt -INCLUDES = -I ../stdext -I ../xc -I ../xen-utils +INCLUDES = -I ../stdext LDFLAGS = -cclib -L./ @@ -65,8 +65,8 @@ uninstall: .PHONY: doc doc: $(INTF) - python ../doc/doc.py $(DOCDIR) "cpuid" "package" "$(OBJS)" "." "stdext xc xen-utils" "" + python ../doc/doc.py $(DOCDIR) "cpuid" "package" "$(OBJS)" "." "stdext" "" clean: - rm -f *.o *.so *.a *.cmo *.cmi *.cma *.cmx *.cmxa *.annot $(LIBS) $(PROGRAMS) *~ *.rej + rm -f *.o *.so *.a *.cmo *.cmi *.cma *.cmx *.cmxa *.annot $(LIBS) $(PROGRAMS) diff --git a/cpuid/cpuid.ml b/cpuid/cpuid.ml index ee692d9..fe69372 100644 --- a/cpuid/cpuid.ml +++ b/cpuid/cpuid.ml @@ -23,7 +23,6 @@ exception ManufacturersDiffer (* === Types and conversion === *) type manufacturer = AMD | Intel | Unknown -and maskability = No | Base | Full and features = { base_ecx: int32; @@ -39,7 +38,7 @@ and cpu_info = stepping: int32; features: features; physical_features: features; - maskable: maskability; + maskable: bool; } let features_to_string f = @@ -110,73 +109,39 @@ let read_features () = (* Does this Intel CPU support "FlexMigration"? * It's not sensibly documented, so check by model *) let has_flexmigration family model stepping = - if family <> 0x6l then - No - else if model = 0x1dl || (model = 0x17l && stepping >= 4l) then - Base - else if (model = 0x1al && stepping > 2l) || - model = 0x1el || model = 0x25l || model = 0x2cl || - model = 0x2el || model = 0x2fl then - Full - else - No + family > 0x6l || (model > 0x17l || (model = 0x17l && stepping >= 4l)) (* Does this AMD CPU have Extended Migration Technology? * Known good on Barcelona and better; did exist on some older CPUs * but not really documented which ones *) let has_emt family = - if family >= 0x10l then - Full - else - No + family >= 0x10l let is_maskable manufacturer family model stepping = match manufacturer with - | Unknown -> No - | Intel -> has_flexmigration family model stepping - | AMD -> has_emt family - -let get_features_from_xen () = - let features = - try Xc.with_intf (fun xc -> Xc.get_boot_cpufeatures xc) - with _ -> 0l, 0l, 0l, 0l, 0l, 0l, 0l, 0l - in - match features with - | base_ecx, base_edx, ext_ecx, ext_edx, - masked_base_ecx, masked_base_edx, masked_ext_ecx, masked_ext_edx -> - { - base_ecx = masked_base_ecx; - base_edx = masked_base_edx; - ext_ecx = masked_ext_ecx; - ext_edx = masked_ext_edx - }, - { - base_ecx = base_ecx; - base_edx = base_edx; - ext_ecx = ext_ecx; - ext_edx = ext_edx - } - -let get_current_mask () = - let masks = Xen_cmdline.list_cpuid_masks () in - let get_mask m = - if List.mem_assoc m masks = false then - 0xffffffffl - else - Int32.of_string (List.assoc m masks) - in - { - base_ecx = get_mask "cpuid_mask_ecx"; - base_edx = get_mask "cpuid_mask_edx"; - ext_ecx = get_mask "cpuid_mask_ext_ecx"; - ext_edx = get_mask "cpuid_mask_ext_edx" - } - + | Unknown -> false + | Intel -> + if has_flexmigration family model stepping then true + else false + | AMD -> + if has_emt family then true + else false + +let get_physical_features features = + let features_file = "/var/xapi/features" in + try + let data = Unixext.read_whole_file_to_string features_file in + string_to_features data + with _ -> + let data = features_to_string features in + Unixext.write_string_to_file features_file data; + features + let read_cpu_info () = let manufacturer = read_manufacturer () in let family = read_family () in let model = read_model () in - let features, phy_features = get_features_from_xen () in + let features = read_features () in let stepping = read_stepping () in { manufacturer = manufacturer; @@ -184,43 +149,39 @@ let read_cpu_info () = model = model; stepping = stepping; features = features; - physical_features = phy_features; + physical_features = get_physical_features features; maskable = is_maskable manufacturer family model stepping; } (* === Masking checks === *) -let mask_features features mask = - { - base_ecx = logand features.base_ecx mask.base_ecx; - base_edx = logand features.base_edx mask.base_edx; - ext_ecx = logand features.ext_ecx mask.ext_ecx; - ext_edx = logand features.ext_edx mask.ext_edx; - } - let assert_maskability cpu manufacturer features = (* Manufacturers need to be the same *) if manufacturer != cpu.manufacturer then raise ManufacturersDiffer; - (* Check whether the features can be obtained by masking the physical features *) - let base = (logand cpu.physical_features.base_ecx features.base_ecx) = features.base_ecx - && (logand cpu.physical_features.base_edx features.base_edx) = features.base_edx in - match cpu.maskable with - | No -> + (* Check whether masking is supported on the CPU *) + if not cpu.maskable then begin match cpu.manufacturer with | Unknown -> raise (MaskingNotSupported "Unknown CPU manufacturer") | Intel -> raise (MaskingNotSupported "CPU does not have FlexMigration") | AMD -> raise (MaskingNotSupported "CPU does not have Extended Migration Technology") + end; + (* Check whether the features can be obtained by masking the physical features *) + let possible = (logand cpu.physical_features.base_ecx features.base_ecx) = features.base_ecx + && (logand cpu.physical_features.base_edx features.base_edx) = features.base_edx + && begin match manufacturer with + | Intel -> + (* Intel can't mask extented features but doesn't (yet) need to *) + cpu.physical_features.ext_ecx = features.ext_ecx + && cpu.physical_features.ext_edx = features.ext_edx + | AMD -> + (logand cpu.physical_features.ext_ecx features.ext_ecx) = features.ext_ecx + && (logand cpu.physical_features.ext_edx features.ext_edx) = features.ext_edx + | _ -> false end - | Base -> - if not (base && cpu.physical_features.ext_ecx = features.ext_ecx - && cpu.physical_features.ext_edx = features.ext_edx) then - raise (InvalidFeatureString "CPU features cannot be masked to obtain \ - given features (only base features can be masked)") - | Full -> - if not (base && (logand cpu.physical_features.ext_ecx features.ext_ecx) = features.ext_ecx - && (logand cpu.physical_features.ext_edx features.ext_edx) = features.ext_edx) then - raise (InvalidFeatureString "CPU features cannot be masked to obtain given features") + in + if not possible then + raise (InvalidFeatureString "CPU features cannot be masked to obtain given features") let xen_masking_string cpu features = let rec stringify reglist = diff --git a/cpuid/cpuid.mli b/cpuid/cpuid.mli index 871ca11..7f9e800 100644 --- a/cpuid/cpuid.mli +++ b/cpuid/cpuid.mli @@ -21,12 +21,6 @@ type manufacturer = | Intel (** Intel *) | Unknown (** Other manufacturer *) -(** Indicates whether CPUID features can be masked. *) -and maskability = -| No (** No masking possible *) -| Base (** Only base features can be masked *) -| Full (** Both base and extended features can be masked *) - (** CPU feature bit vector. *) and features @@ -39,7 +33,7 @@ and cpu_info = stepping: int32; (** Stepping number of the CPU *) features: features; (** Feature bit vector of the CPU *) physical_features: features; (** Physical Feature bit vector of the CPU *) - maskable: maskability; (** Indicates whether the CPU supports + maskable: bool; (** Boolean indicating whether the CPU supports Intel FlexMigration or AMD Extended Migration, or cannot be masked *) } @@ -60,11 +54,8 @@ val read_cpu_info : unit -> cpu_info (** {2 Masking Checks} *) -(** Apply a mask to given features. *) -val mask_features : features -> features -> features - -(** Check that this CPU can be masked to fit the pool. Raises exception - * indicating the reason if this is not possible. *) +(** Check that this CPU can be masked to fit the pool. Raises {!CannotMaskCpu} + * including a reason string if this is not possible. *) val assert_maskability : cpu_info -> manufacturer -> features -> unit (** Return the CPU masking string to add to the Xen command-line,