diff options
author | Jan Beulich <jbeulich@novell.com> | 2011-07-23 08:49:15 +0100 |
---|---|---|
committer | Jan Beulich <jbeulich@novell.com> | 2011-07-23 08:49:15 +0100 |
commit | ec029aaa9a79965f83476808e32b8573891aa79c (patch) | |
tree | 8f7a0d56b7a3869f0bf7d42e165f8b7d72f3371e /xen/common/libelf | |
parent | 173b4afb894a248ade34bfd38850214f82d657c3 (diff) | |
download | xen-ec029aaa9a79965f83476808e32b8573891aa79c.tar.gz xen-ec029aaa9a79965f83476808e32b8573891aa79c.tar.bz2 xen-ec029aaa9a79965f83476808e32b8573891aa79c.zip |
add privileged (dom0) kernel feature indication
With our switching away from supporting 32-bit Dom0 operation, users
complained that attempts (perhaps due to lack of knowledge of that
change) to boot the no longer privileged kernel in Dom0 resulted in
apparently silent failure. To make the mismatch explicit and visible,
add dom0 feature flag that the kernel can set to indicate operation as
dom0 is supported.
Due to the way elf_xen_parse_features() worked up to now (getting
fixed here), adding features indications to the old, string based ELF
note would make the respective kernel unusable on older hypervisors.
For that reason, a new ELF Note is being introduced that allows
specifying supported features as a bit array instead (with features
unknown to the hypervisor simply ignored, as now also done by
elf_xen_parse_features(), whereas here unknown kernel-required
features still keep the kernel [and hence VM] from booting).
Introduce and use elf_note_numeric_array() to be forward
compatible (or else an old hypervisor wouldn't be able to parse kernel
specified features occupying more than 64 bits - thanks, Ian!).
Signed-off-by: Jan Beulich <jbeulich@novell.com>
Diffstat (limited to 'xen/common/libelf')
-rw-r--r-- | xen/common/libelf/libelf-dominfo.c | 13 | ||||
-rw-r--r-- | xen/common/libelf/libelf-tools.c | 21 |
2 files changed, 32 insertions, 2 deletions
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c index 57ca26088b..c569a4893a 100644 --- a/xen/common/libelf/libelf-dominfo.c +++ b/xen/common/libelf/libelf-dominfo.c @@ -26,7 +26,8 @@ static const char *const elf_xen_feature_names[] = { [XENFEAT_writable_descriptor_tables] = "writable_descriptor_tables", [XENFEAT_auto_translated_physmap] = "auto_translated_physmap", [XENFEAT_supervisor_mode_kernel] = "supervisor_mode_kernel", - [XENFEAT_pae_pgdir_above_4gb] = "pae_pgdir_above_4gb" + [XENFEAT_pae_pgdir_above_4gb] = "pae_pgdir_above_4gb", + [XENFEAT_dom0] = "dom0" }; static const int elf_xen_features = sizeof(elf_xen_feature_names) / sizeof(elf_xen_feature_names[0]); @@ -83,7 +84,7 @@ int elf_xen_parse_features(const char *features, } } } - if ( i == elf_xen_features ) + if ( i == elf_xen_features && required && feature[0] == '!' ) return -1; } @@ -114,6 +115,7 @@ int elf_xen_parse_note(struct elf_binary *elf, [XEN_ELFNOTE_LOADER] = { "LOADER", 1}, [XEN_ELFNOTE_PAE_MODE] = { "PAE_MODE", 1}, [XEN_ELFNOTE_FEATURES] = { "FEATURES", 1}, + [XEN_ELFNOTE_SUPPORTED_FEATURES] = { "SUPPORTED_FEATURES", 0}, [XEN_ELFNOTE_BSD_SYMTAB] = { "BSD_SYMTAB", 1}, [XEN_ELFNOTE_SUSPEND_CANCEL] = { "SUSPEND_CANCEL", 0 }, [XEN_ELFNOTE_MOD_START_PFN] = { "MOD_START_PFN", 0 }, @@ -122,6 +124,7 @@ int elf_xen_parse_note(struct elf_binary *elf, const char *str = NULL; uint64_t val = 0; + unsigned int i; int type = elf_uval(elf, note, type); if ( (type >= sizeof(note_desc) / sizeof(note_desc[0])) || @@ -200,6 +203,12 @@ int elf_xen_parse_note(struct elf_binary *elf, return -1; break; + case XEN_ELFNOTE_SUPPORTED_FEATURES: + for ( i = 0; i < XENFEAT_NR_SUBMAPS; ++i ) + parms->f_supported[i] |= elf_note_numeric_array( + elf, note, sizeof(*parms->f_supported), i); + break; + } return 0; } diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c index 885d5e8ad3..cb97908138 100644 --- a/xen/common/libelf/libelf-tools.c +++ b/xen/common/libelf/libelf-tools.c @@ -227,6 +227,27 @@ uint64_t elf_note_numeric(struct elf_binary *elf, const elf_note * note) return 0; } } + +uint64_t elf_note_numeric_array(struct elf_binary *elf, const elf_note *note, + unsigned int unitsz, unsigned int idx) +{ + const void *desc = elf_note_desc(elf, note); + int descsz = elf_uval(elf, note, descsz); + + if ( descsz % unitsz || idx >= descsz / unitsz ) + return 0; + switch (unitsz) + { + case 1: + case 2: + case 4: + case 8: + return elf_access_unsigned(elf, desc, idx * unitsz, unitsz); + default: + return 0; + } +} + const elf_note *elf_note_next(struct elf_binary *elf, const elf_note * note) { int namesz = (elf_uval(elf, note, namesz) + 3) & ~3; |