diff --git a/tools/examples/xmexample.vti b/tools/examples/xmexample.vti index f38d363918..92e29c76c9 100644 --- a/tools/examples/xmexample.vti +++ b/tools/examples/xmexample.vti @@ -147,3 +147,16 @@ serial='pty' #----------------------------------------------------------------------------- # Set keyboard layout, default is en-us keyboard. #keymap='ja' + +#----------------------------------------------------------------------------- +# Enable optimization features for the specified OS type. (Specific to the +# OS running in the guest domain. Other OSes may not run correctly +# if the wrong OS type is specified.) +# +# Default is "default", which should work for all supported guest OSes. +# +# Known values: +# 'linux' - All Linux variants +# 'windows' - All Windows variants (Windows Server 2003/2008) +# +#guest_os_type='default' diff --git a/tools/libxc/ia64/xc_ia64_hvm_build.c b/tools/libxc/ia64/xc_ia64_hvm_build.c index 5fc0d58fa9..3a9c0e16ba 100644 --- a/tools/libxc/ia64/xc_ia64_hvm_build.c +++ b/tools/libxc/ia64/xc_ia64_hvm_build.c @@ -1093,6 +1093,78 @@ error_out: return -1; } +/* + * From asm/pgtable.h + */ +#define _PAGE_P_BIT 0 +#define _PAGE_A_BIT 5 +#define _PAGE_D_BIT 6 + +#define _PAGE_P (1 << _PAGE_P_BIT) /* page present bit */ +#define _PAGE_A (1 << _PAGE_A_BIT) /* page accessed bit */ +#define _PAGE_D (1 << _PAGE_D_BIT) /* page dirty bit */ + +#define _PAGE_MA_WB (0x0 << 2) /* write back memory attribute */ +#define _PAGE_MA_UC (0x4 << 2) /* uncacheable memory attribute */ +#define _PAGE_AR_RW (2 << 9) /* read & write */ + +int +xc_ia64_set_os_type(int xc_handle, char *guest_os_type, uint32_t dom) +{ + DECLARE_DOMCTL; + + domctl.cmd = XEN_DOMCTL_set_opt_feature; + domctl.domain = (domid_t)dom; + + if (!guest_os_type || !strlen(guest_os_type) || + !strcmp("default", guest_os_type)) { + + /* Nothing */ + return 0; + + } else if (!strcmp("windows", guest_os_type)) { + DPRINTF("Enabling Windows guest OS optimizations\n"); + + /* Windows identity maps regions 4 & 5 */ + domctl.u.set_opt_feature.optf.cmd = XEN_IA64_OPTF_IDENT_MAP_REG4; + domctl.u.set_opt_feature.optf.on = XEN_IA64_OPTF_ON; + domctl.u.set_opt_feature.optf.pgprot = (_PAGE_P | _PAGE_A | _PAGE_D | + _PAGE_MA_WB | _PAGE_AR_RW); + domctl.u.set_opt_feature.optf.key = 0; + if (xc_domctl(xc_handle, &domctl)) + PERROR("Failed to set region 4 identity mapping for Windows " + "guest OS type.\n"); + + domctl.u.set_opt_feature.optf.cmd = XEN_IA64_OPTF_IDENT_MAP_REG5; + domctl.u.set_opt_feature.optf.on = XEN_IA64_OPTF_ON; + domctl.u.set_opt_feature.optf.pgprot = (_PAGE_P | _PAGE_A | _PAGE_D | + _PAGE_MA_UC | _PAGE_AR_RW); + domctl.u.set_opt_feature.optf.key = 0; + if (xc_domctl(xc_handle, &domctl)) + PERROR("Failed to set region 5 identity mapping for Windows " + "guest OS type.\n"); + return 0; + + } else if (!strcmp("linux", guest_os_type)) { + DPRINTF("Enabling Linux guest OS optimizations\n"); + + /* Linux identity maps regions 7 */ + domctl.u.set_opt_feature.optf.cmd = XEN_IA64_OPTF_IDENT_MAP_REG7; + domctl.u.set_opt_feature.optf.on = XEN_IA64_OPTF_ON; + domctl.u.set_opt_feature.optf.pgprot = (_PAGE_P | _PAGE_A | _PAGE_D | + _PAGE_MA_WB | _PAGE_AR_RW); + domctl.u.set_opt_feature.optf.key = 0; + if (xc_domctl(xc_handle, &domctl)) + PERROR("Failed to set region 7 identity mapping for Linux " + "guest OS type.\n"); + return 0; + } + + DPRINTF("Unknown guest_os_type (%s), using defaults\n", guest_os_type); + + return 0; +} + /* * Local variables: * mode: C diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index 0e82a5fbd3..61f7fc558f 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -906,6 +906,9 @@ int xc_ia64_save_to_nvram(int xc_handle, uint32_t dom); /* IA64 specific, nvram init */ int xc_ia64_nvram_init(int xc_handle, char *dom_name, uint32_t dom); +/* IA64 specific, set guest OS type optimizations */ +int xc_ia64_set_os_type(int xc_handle, char *guest_os_type, uint32_t dom); + /* HVM guest pass-through */ int xc_assign_device(int xc_handle, uint32_t domid, diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index 2a09947be3..f899edceeb 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -604,6 +604,21 @@ static PyObject *pyxc_nvram_init(XcObject *self, Py_INCREF(zero); return zero; } + +static PyObject *pyxc_set_os_type(XcObject *self, + PyObject *args) +{ + char *os_type; + uint32_t dom; + + if ( !PyArg_ParseTuple(args, "si", &os_type, &dom) ) + return NULL; + + xc_ia64_set_os_type(self->xc_handle, os_type, dom); + + Py_INCREF(zero); + return zero; +} #endif /* __ia64__ */ static PyObject *pyxc_hvm_build(XcObject *self, @@ -1558,6 +1573,11 @@ static PyMethodDef pyxc_methods[] = { METH_VARARGS, "\n" "Init nvram in IA64 platform\n" "Returns: [int] 0 on success; -1 on error.\n" }, + { "set_os_type", + (PyCFunction)pyxc_set_os_type, + METH_VARARGS, "\n" + "Set guest OS type on IA64 platform\n" + "Returns: [int] 0 on success; -1 on error.\n" }, #endif /* __ia64__ */ { "domain_ioport_permission", (PyCFunction)pyxc_domain_ioport_permission, diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py index a660e9faec..85e7e4fa08 100644 --- a/tools/python/xen/xend/image.py +++ b/tools/python/xen/xend/image.py @@ -541,6 +541,8 @@ class IA64_HVM_ImageHandler(HVMImageHandler): def buildDomain(self): xc.nvram_init(self.vm.getName(), self.vm.getDomid()) xc.hvm_set_param(self.vm.getDomid(), HVM_PARAM_VHPT_SIZE, self.vhpt) + if self.guest_os_type is not None: + xc.set_os_type(self.guest_os_type.lower(), self.vm.getDomid()) return HVMImageHandler.buildDomain(self) def getRequiredAvailableMemory(self, mem_kb): diff --git a/xen/arch/ia64/vmx/mmio.c b/xen/arch/ia64/vmx/mmio.c index bf5223ce9a..bbdad1bdf5 100644 --- a/xen/arch/ia64/vmx/mmio.c +++ b/xen/arch/ia64/vmx/mmio.c @@ -234,35 +234,6 @@ static int vmx_ide_pio_intercept(ioreq_t *p, u64 *val) #define TO_LEGACY_IO(pa) (((pa)>>12<<2)|((pa)&0x3)) -static const char * const guest_os_name[] = { - "Unknown", - "Windows 2003 server", - "Linux", -}; - -static inline void set_os_type(VCPU *v, u64 type) -{ - if (type > OS_BASE && type < OS_END) { - v->domain->arch.vmx_platform.gos_type = type; - gdprintk(XENLOG_INFO, "Guest OS : %s\n", guest_os_name[type - OS_BASE]); - - if (GOS_WINDOWS(v)) { - struct xen_ia64_opt_feature optf; - - /* Windows identity maps regions 4 & 5 */ - optf.cmd = XEN_IA64_OPTF_IDENT_MAP_REG4; - optf.on = XEN_IA64_OPTF_ON; - optf.pgprot = (_PAGE_P|_PAGE_A|_PAGE_D|_PAGE_MA_WB|_PAGE_AR_RW); - optf.key = 0; - domain_opt_feature(v->domain, &optf); - - optf.cmd = XEN_IA64_OPTF_IDENT_MAP_REG5; - optf.pgprot = (_PAGE_P|_PAGE_A|_PAGE_D|_PAGE_MA_UC|_PAGE_AR_RW); - domain_opt_feature(v->domain, &optf); - } - } -} - static void __vmx_identity_mapping_save(int on, const struct identity_mapping* im, struct hvm_hw_ia64_identity_mapping *im_save) @@ -359,11 +330,6 @@ static void legacy_io_access(VCPU *vcpu, u64 pa, u64 *val, size_t s, int dir) p->io_count++; - if (dir == IOREQ_WRITE && p->addr == OS_TYPE_PORT) { - set_os_type(v, *val); - return; - } - if (vmx_ide_pio_intercept(p, val)) return; diff --git a/xen/arch/ia64/vmx/vmx_init.c b/xen/arch/ia64/vmx/vmx_init.c index 84ed961e76..38d293f711 100644 --- a/xen/arch/ia64/vmx/vmx_init.c +++ b/xen/arch/ia64/vmx/vmx_init.c @@ -396,7 +396,6 @@ vmx_final_setup_guest(struct vcpu *v) v->arch.privregs = (mapped_regs_t *)vpd; vpd->vpd_low.virt_env_vaddr = vm_buffer; - v->domain->arch.vmx_platform.gos_type = OS_UNKNOWN; /* Per-domain vTLB and vhpt implementation. Now vmx domain will stick * to this solution. Maybe it can be deferred until we know created * one as vmx domain */ diff --git a/xen/include/asm-ia64/domain.h b/xen/include/asm-ia64/domain.h index 1cdb8404ed..97f6c8f821 100644 --- a/xen/include/asm-ia64/domain.h +++ b/xen/include/asm-ia64/domain.h @@ -75,11 +75,11 @@ struct xen_sal_data { }; /* - * Optimization features - * are used by the hypervisor to do some optimizations for guests. - * By default the optimizations are switched off and the guest has to activate - * the feature. On PV the guest must do this via the hypercall - * __HYPERVISOR_opt_feature, on HVM it's done within xen in set_os_type(). + * Optimization features are used by the hypervisor to do some optimizations + * for guests. By default the optimizations are switched off and the guest + * may activate the feature. The guest may do this via the hypercall + * __HYPERVISOR_opt_feature. Domain builder code can also enable these + * via XEN_DOMCTL_set_opt_feature. */ /* @@ -101,20 +101,6 @@ struct opt_feature { struct identity_mapping im_reg7; /* Region 7 identity mapping */ }; -/* - * The base XEN_IA64_OPTF_IDENT_MAP_REG7 is defined in public/arch-ia64.h. - * Identity mapping of region 4 addresses in HVM. - */ -#define XEN_IA64_OPTF_IDENT_MAP_REG4_BIT \ - (XEN_IA64_OPTF_IDENT_MAP_REG7_BIT + 1) -#define XEN_IA64_OPTF_IDENT_MAP_REG4 \ - (1UL << XEN_IA64_OPTF_IDENT_MAP_REG4_BIT) -/* Identity mapping of region 5 addresses in HVM. */ -#define XEN_IA64_OPTF_IDENT_MAP_REG5_BIT \ - (XEN_IA64_OPTF_IDENT_MAP_REG7_BIT + 2) -#define XEN_IA64_OPTF_IDENT_MAP_REG5 \ - (1UL << XEN_IA64_OPTF_IDENT_MAP_REG5_BIT) - /* Set an optimization feature in the struct arch_domain. */ extern int domain_opt_feature(struct domain *, struct xen_ia64_opt_feature*); diff --git a/xen/include/asm-ia64/vmx_platform.h b/xen/include/asm-ia64/vmx_platform.h index f8eadd6a41..deff5c29cf 100644 --- a/xen/include/asm-ia64/vmx_platform.h +++ b/xen/include/asm-ia64/vmx_platform.h @@ -24,25 +24,6 @@ #include #include - -/* Value of guest os type */ -#define OS_BASE 0xB0 -#define OS_UNKNOWN 0xB0 -#define OS_WINDOWS 0xB1 -#define OS_LINUX 0xB2 -#define OS_END 0xB3 - -#define GOS_WINDOWS(_v) \ - ((_v)->domain->arch.vmx_platform.gos_type == OS_WINDOWS) - -#define GOS_LINUX(_v) \ - ((_v)->domain->arch.vmx_platform.gos_type == OS_LINUX) - -/* port guest Firmware use to indicate os type - * this port is used to trigger SMI on x86, - * it is not used on ia64 */ -#define OS_TYPE_PORT 0xB2 - struct vmx_ioreq_page { spinlock_t lock; struct page_info *page; @@ -52,7 +33,6 @@ int vmx_set_ioreq_page(struct domain *d, struct vmx_ioreq_page *iorp, unsigned long gmfn); typedef struct virtual_platform_def { - unsigned long gos_type; struct vmx_ioreq_page ioreq; struct vmx_ioreq_page buf_ioreq; struct vmx_ioreq_page buf_pioreq; diff --git a/xen/include/public/arch-ia64.h b/xen/include/public/arch-ia64.h index 9fd63b1787..4d31153208 100644 --- a/xen/include/public/arch-ia64.h +++ b/xen/include/public/arch-ia64.h @@ -606,6 +606,20 @@ struct xen_ia64_boot_param { #define XEN_IA64_OPTF_IDENT_MAP_REG7 \ (1UL << XEN_IA64_OPTF_IDENT_MAP_REG7_BIT) +/* Identity mapping of region 4 addresses in HVM. */ +#define XEN_IA64_OPTF_IDENT_MAP_REG4_BIT \ + (XEN_IA64_OPTF_IDENT_MAP_REG7_BIT + 1) +#define XEN_IA64_OPTF_IDENT_MAP_REG4 \ + (1UL << XEN_IA64_OPTF_IDENT_MAP_REG4_BIT) + +/* Identity mapping of region 5 addresses in HVM. */ +#define XEN_IA64_OPTF_IDENT_MAP_REG5_BIT \ + (XEN_IA64_OPTF_IDENT_MAP_REG7_BIT + 2) +#define XEN_IA64_OPTF_IDENT_MAP_REG5 \ + (1UL << XEN_IA64_OPTF_IDENT_MAP_REG5_BIT) + +#define XEN_IA64_OPTF_IDENT_MAP_NOT_SET (0) + struct xen_ia64_opt_feature { unsigned long cmd; /* Which feature */ unsigned char on; /* Switch feature on/off */