[IA64] Implement guest_os_type for ia64
authorAlex Williamson <alex.williamson@hp.com>
Thu, 29 Nov 2007 19:15:43 +0000 (12:15 -0700)
committerAlex Williamson <alex.williamson@hp.com>
Thu, 29 Nov 2007 19:15:43 +0000 (12:15 -0700)
This makes use of the domain config option guest_os_type for
ia64 and removes the backing for the previous ACPI based
mechanism used previously.  A user wanting optimal performance
for a specific type of OS guest running in an HVM domain should
make use of this new option.  See updated xmexmaple.vti for
available options.  All supported OSes should always work using
the default option or leaving the option unspecified.  Originally
based on patch from Zhang Xin.

Signed-off-by: Alex Williamson <alex.williamson@hp.com>
tools/examples/xmexample.vti
tools/libxc/ia64/xc_ia64_hvm_build.c
tools/libxc/xenctrl.h
tools/python/xen/lowlevel/xc/xc.c
tools/python/xen/xend/image.py
xen/arch/ia64/vmx/mmio.c
xen/arch/ia64/vmx/vmx_init.c
xen/include/asm-ia64/domain.h
xen/include/asm-ia64/vmx_platform.h
xen/include/public/arch-ia64.h

index f38d36391855275a95d7a0859b6c0a851a722c38..92e29c76c93e1119e4b047431c4c3e93155710ae 100644 (file)
@@ -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'
index 5fc0d58fa9d9833a7f7c9ec04d65cc002f56c6e8..3a9c0e16ba8f30c0934db654ffc0020e34c84cd1 100644 (file)
@@ -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
index 0e82a5fbd3dcf47ad673e5fcf922d2b3c77428f4..61f7fc558fadf8a204ffddb48ea8c277de8b4616 100644 (file)
@@ -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,
index 2a09947be30340a98d3d46d822f71a718d0ac93f..f899edceeb5a985e97ab9863187e5c0213b5b7c0 100644 (file)
@@ -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,
index a660e9faec2180c2812b3723f62c519efc5facde..85e7e4fa08edc7211c6dc5dd53cc0b5cf8d06c12 100644 (file)
@@ -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):
index bf5223ce9a9cfb746e572366fc6bd45e987d1cb6..bbdad1bdf55fd5c3f37f2241adb1b9b06236a5cc 100644 (file)
@@ -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;
 
index 84ed961e7603349d6f8ebc0190bd9e4f23a8b596..38d293f711b61b6595d12216b134f4c18812bb4f 100644 (file)
@@ -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 */
index 1cdb8404edac0ffc27400018c8ded070e5a83ca0..97f6c8f8212cd44ef6b404d055b61c8b2ad027b7 100644 (file)
@@ -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*);
 
index f8eadd6a416633482833d0d5844a629ee63ce2b8..deff5c29cfc45569faf02452cf52da7c8f8a6ad3 100644 (file)
 #include <asm/viosapic.h>
 #include <asm/hvm/vacpi.h>
 
-
-/* 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;
index 9fd63b1787d17b540997678e260e469810b23bbb..4d311532088c926cb988517f5cdda4b02509c76a 100644 (file)
@@ -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 */