# HG changeset patch # User cegger # Date 1298892098 -3600 tools: Add nestedhvm guest config option Signed-off-by: Christoph Egger diff -r 207fdcef2c67 -r 879b3d37143a tools/libxc/xc_cpuid_x86.c --- a/tools/libxc/xc_cpuid_x86.c +++ b/tools/libxc/xc_cpuid_x86.c @@ -30,7 +30,8 @@ #define set_bit(idx, dst) ((dst) |= (1u << ((idx) & 31))) #define DEF_MAX_BASE 0x0000000du -#define DEF_MAX_EXT 0x80000008u +#define DEF_MAX_INTELEXT 0x80000008u +#define DEF_MAX_AMDEXT 0x8000000au static int hypervisor_is_64bit(xc_interface *xch) { @@ -78,7 +79,7 @@ static void xc_cpuid_brand_get(char *str static void amd_xc_cpuid_policy( xc_interface *xch, domid_t domid, const unsigned int *input, unsigned int *regs, - int is_pae) + int is_pae, int is_nestedhvm) { switch ( input[0] ) { @@ -87,6 +88,11 @@ static void amd_xc_cpuid_policy( regs[0] = regs[1] = regs[2] = 0; break; + case 0x80000000: + if ( regs[0] > DEF_MAX_AMDEXT ) + regs[0] = DEF_MAX_AMDEXT; + break; + case 0x80000001: { int is_64bit = hypervisor_is_64bit(xch) && is_pae; @@ -97,6 +103,7 @@ static void amd_xc_cpuid_policy( /* Filter all other features according to a whitelist. */ regs[2] &= ((is_64bit ? bitmaskof(X86_FEATURE_LAHF_LM) : 0) | bitmaskof(X86_FEATURE_CMP_LEGACY) | + (is_nestedhvm ? bitmaskof(X86_FEATURE_SVM) : 0) | bitmaskof(X86_FEATURE_CR8_LEGACY) | bitmaskof(X86_FEATURE_ABM) | bitmaskof(X86_FEATURE_SSE4A) | @@ -124,16 +131,50 @@ static void amd_xc_cpuid_policy( */ regs[2] = ((regs[2] & 0xf000u) + 1) | ((regs[2] & 0xffu) << 1) | 1u; break; + + case 0x8000000a: { + if (!is_nestedhvm) { + regs[0] = regs[1] = regs[2] = regs[3] = 0; + break; + } + +#define SVM_FEATURE_NPT 0x00000001 /* Nested page table support */ +#define SVM_FEATURE_LBRV 0x00000002 /* LBR virtualization support */ +#define SVM_FEATURE_SVML 0x00000004 /* SVM locking MSR support */ +#define SVM_FEATURE_NRIPS 0x00000008 /* Next RIP save on VMEXIT */ +#define SVM_FEATURE_TSCRATEMSR 0x00000010 /* TSC ratio MSR support */ +#define SVM_FEATURE_VMCBCLEAN 0x00000020 /* VMCB clean bits support */ +#define SVM_FEATURE_FLUSHBYASID 0x00000040 /* TLB flush by ASID support */ +#define SVM_FEATURE_DECODEASSISTS 0x00000080 /* Decode assists support */ +#define SVM_FEATURE_PAUSEFILTER 0x00000400 /* Pause intercept filter */ + + /* Pass 1: Only passthrough SVM features which are + * available in hw and which are implemented + */ + regs[3] &= (SVM_FEATURE_NPT | SVM_FEATURE_LBRV | \ + SVM_FEATURE_NRIPS | SVM_FEATURE_PAUSEFILTER); + + /* Pass 2: Always enable SVM features which are emulated */ + regs[3] |= SVM_FEATURE_VMCBCLEAN; + break; + } + } } static void intel_xc_cpuid_policy( xc_interface *xch, domid_t domid, const unsigned int *input, unsigned int *regs, - int is_pae) + int is_pae, int is_nestedhvm) { switch ( input[0] ) { + case 0x00000001: + /* ECX[5] is availability of VMX */ + if (is_nestedhvm) + set_bit(X86_FEATURE_VMXE, regs[2]); + break; + case 0x00000004: /* * EAX[31:26] is Maximum Cores Per Package (minus one). @@ -144,6 +185,11 @@ static void intel_xc_cpuid_policy( regs[3] &= 0x3ffu; break; + case 0x80000000: + if ( regs[0] > DEF_MAX_INTELEXT ) + regs[0] = DEF_MAX_INTELEXT; + break; + case 0x80000001: { int is_64bit = hypervisor_is_64bit(xch) && is_pae; @@ -225,8 +271,9 @@ static void xc_cpuid_hvm_policy( { DECLARE_DOMCTL; char brand[13]; + unsigned long nestedhvm; unsigned long pae; - int is_pae; + int is_pae, is_nestedhvm; uint64_t xfeature_mask; xc_get_hvm_param(xch, domid, HVM_PARAM_PAE_ENABLED, &pae); @@ -239,6 +286,9 @@ static void xc_cpuid_hvm_policy( do_domctl(xch, &domctl); xfeature_mask = domctl.u.vcpuextstate.xfeature_mask; + xc_get_hvm_param(xch, domid, HVM_PARAM_NESTEDHVM, &nestedhvm); + is_nestedhvm = !!nestedhvm; + switch ( input[0] ) { case 0x00000000: @@ -305,8 +355,7 @@ static void xc_cpuid_hvm_policy( break; case 0x80000000: - if ( regs[0] > DEF_MAX_EXT ) - regs[0] = DEF_MAX_EXT; + /* Passthrough to cpu vendor specific functions */ break; case 0x80000001: @@ -335,6 +384,7 @@ static void xc_cpuid_hvm_policy( case 0x80000004: /* ... continued */ case 0x80000005: /* AMD L1 cache/TLB info (dumped by Intel policy) */ case 0x80000006: /* AMD L2/3 cache/TLB info ; Intel L2 cache features */ + case 0x8000000a: /* AMD SVM feature bits */ break; default: @@ -344,9 +394,9 @@ static void xc_cpuid_hvm_policy( xc_cpuid_brand_get(brand); if ( strstr(brand, "AMD") ) - amd_xc_cpuid_policy(xch, domid, input, regs, is_pae); + amd_xc_cpuid_policy(xch, domid, input, regs, is_pae, is_nestedhvm); else - intel_xc_cpuid_policy(xch, domid, input, regs, is_pae); + intel_xc_cpuid_policy(xch, domid, input, regs, is_pae, is_nestedhvm); } @@ -507,13 +557,20 @@ int xc_cpuid_apply_policy(xc_interface * { unsigned int input[2] = { 0, 0 }, regs[4]; unsigned int base_max, ext_max; + char brand[13]; int rc; + cpuid(input, regs); base_max = (regs[0] <= DEF_MAX_BASE) ? regs[0] : DEF_MAX_BASE; input[0] = 0x80000000; cpuid(input, regs); - ext_max = (regs[0] <= DEF_MAX_EXT) ? regs[0] : DEF_MAX_EXT; + + xc_cpuid_brand_get(brand); + if ( strstr(brand, "AMD") ) + ext_max = (regs[0] <= DEF_MAX_AMDEXT) ? regs[0] : DEF_MAX_AMDEXT; + else + ext_max = (regs[0] <= DEF_MAX_INTELEXT) ? regs[0] : DEF_MAX_INTELEXT; input[0] = 0; input[1] = XEN_CPUID_INPUT_UNUSED; diff -r 207fdcef2c67 -r 879b3d37143a tools/libxl/libxl.idl --- a/tools/libxl/libxl.idl +++ b/tools/libxl/libxl.idl @@ -109,6 +109,7 @@ libxl_domain_build_info = Struct("domain ("hpet", bool), ("vpt_align", bool), ("timer_mode", integer), + ("nested_hvm", bool), ])), ("pv", "!%s", Struct(None, [("slack_memkb", uint32), diff -r 207fdcef2c67 -r 879b3d37143a tools/libxl/libxl_create.c --- a/tools/libxl/libxl_create.c +++ b/tools/libxl/libxl_create.c @@ -98,6 +98,7 @@ void libxl_init_build_info(libxl_domain_ b_info->u.hvm.hpet = 1; b_info->u.hvm.vpt_align = 1; b_info->u.hvm.timer_mode = 1; + b_info->u.hvm.nested_hvm = 0; } else { b_info->u.pv.slack_memkb = 8 * 1024; } diff -r 207fdcef2c67 -r 879b3d37143a tools/libxl/libxl_dom.c --- a/tools/libxl/libxl_dom.c +++ b/tools/libxl/libxl_dom.c @@ -256,6 +256,7 @@ static int hvm_build_set_params(xc_inter #endif xc_set_hvm_param(handle, domid, HVM_PARAM_TIMER_MODE, (unsigned long) info->u.hvm.timer_mode); xc_set_hvm_param(handle, domid, HVM_PARAM_VPT_ALIGN, (unsigned long) info->u.hvm.vpt_align); + xc_set_hvm_param(handle, domid, HVM_PARAM_NESTEDHVM, info->u.hvm.nested_hvm); xc_set_hvm_param(handle, domid, HVM_PARAM_STORE_EVTCHN, store_evtchn); xc_set_hvm_param(handle, domid, HVM_PARAM_CONSOLE_EVTCHN, console_evtchn); return 0; diff -r 207fdcef2c67 -r 879b3d37143a tools/libxl/xl_cmdimpl.c --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -327,6 +327,7 @@ static void printf_info(int domid, printf("\t\t\t(hpet %d)\n", b_info->u.hvm.hpet); printf("\t\t\t(vpt_align %d)\n", b_info->u.hvm.vpt_align); printf("\t\t\t(timer_mode %d)\n", b_info->u.hvm.timer_mode); + printf("\t\t\t(nestedhvm %d)\n", b_info->u.hvm.nested_hvm); printf("\t\t\t(device_model %s)\n", dm_info->device_model); printf("\t\t\t(videoram %d)\n", dm_info->videoram); @@ -740,6 +741,8 @@ static void parse_config_data(const char b_info->u.hvm.vpt_align = l; if (!xlu_cfg_get_long (config, "timer_mode", &l)) b_info->u.hvm.timer_mode = l; + if (!xlu_cfg_get_long (config, "nestedhvm", &l)) + b_info->u.hvm.nested_hvm = l; } else { char *cmdline = NULL; const char *root = NULL, *extra = ""; diff -r 207fdcef2c67 -r 879b3d37143a tools/python/xen/xend/XendConfig.py --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -185,6 +185,7 @@ XENAPI_PLATFORM_CFG_TYPES = { 'vhpt': int, 'guest_os_type': str, 'hap': int, + 'nestedhvm' : int, 'xen_extended_power_mgmt': int, 'pci_msitranslate': int, 'pci_power_mgmt': int, diff -r 207fdcef2c67 -r 879b3d37143a tools/python/xen/xend/XendConstants.py --- a/tools/python/xen/xend/XendConstants.py +++ b/tools/python/xen/xend/XendConstants.py @@ -52,6 +52,7 @@ HVM_PARAM_TIMER_MODE = 10 HVM_PARAM_HPET_ENABLED = 11 HVM_PARAM_ACPI_S_STATE = 14 HVM_PARAM_VPT_ALIGN = 16 +HVM_PARAM_NESTEDHVM = 24 # x86 restart_modes = [ "restart", diff -r 207fdcef2c67 -r 879b3d37143a tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -2585,10 +2585,15 @@ class XendDomainInfo: xc.hvm_set_param(self.domid, HVM_PARAM_TIMER_MODE, long(timer_mode)) - # Set Viridian interface configuration of domain - viridian = self.info["platform"].get("viridian") - if arch.type == "x86" and hvm and viridian is not None: - xc.hvm_set_param(self.domid, HVM_PARAM_VIRIDIAN, long(viridian)) + if arch.type == "x86" and hvm: + # Set Viridian interface configuration of domain + viridian = self.info["platform"].get("viridian") + if viridian is not None: + xc.hvm_set_param(self.domid, HVM_PARAM_VIRIDIAN, long(viridian)) + # Set nestedhvm of domain + nestedhvm = self.info["platform"].get("nestedhvm") + if nestedhvm is not None: + xc.hvm_set_param(self.domid, HVM_PARAM_NESTEDHVM, long(nestedhvm)) # If nomigrate is set, disable migration nomigrate = self.info["platform"].get("nomigrate") diff -r 207fdcef2c67 -r 879b3d37143a tools/python/xen/xm/create.py --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -633,6 +633,11 @@ gopts.var('hap', val='HAP', use="""Hap status (0=hap is disabled; 1=hap is enabled.""") +gopts.var('nestedhvm', val='NESTEDHVM', + fn=set_int, default=0, + use="""Nested HVM status (0=Nested HVM is disabled; + 1=Nested HVM is enabled.""") + gopts.var('s3_integrity', val='TBOOT_MEMORY_PROTECT', fn=set_int, default=1, use="""Should domain memory integrity be verified during S3? @@ -1083,7 +1088,7 @@ def configure_hvm(config_image, vals): 'isa', 'keymap', 'localtime', - 'nographic', + 'nestedhvm', 'nographic', 'opengl', 'oos', 'pae', 'pci', 'pci_msitranslate', 'pci_power_mgmt', 'rtc_timeoffset', diff -r 207fdcef2c67 -r 879b3d37143a xen/include/public/hvm/params.h --- a/xen/include/public/hvm/params.h +++ b/xen/include/public/hvm/params.h @@ -137,6 +137,9 @@ #define HVMPME_mode_sync 2 #define HVMPME_onchangeonly (1 << 2) -#define HVM_NR_PARAMS 24 +/* Boolean: Enable nestedhvm (hvm only) */ +#define HVM_PARAM_NESTEDHVM 24 + +#define HVM_NR_PARAMS 25 #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */