ia64/xen-unstable

changeset 11425:65a41e3206ac

Fix the memory reservation calculations. Introduce a new architecture-specific
call to determine the initial reservation separately from the amount of
memory to be freed up by ballooning -- when using QEMU, we lose 8 MiB to video
RAM, which must be accounted for when ballooning, but _not_ accounted for
within the domain's memory allocation.

Tidy this code up using the new architecture-specific interface arrangement.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Tue Sep 05 14:17:50 2006 +0100 (2006-09-05)
parents 536c25a9654d
children 45746c770018
files tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/image.py
line diff
     1.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Tue Sep 05 14:17:49 2006 +0100
     1.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Tue Sep 05 14:17:50 2006 +0100
     1.3 @@ -1285,28 +1285,37 @@ class XendDomainInfo:
     1.4                  for v in range(0, self.info['max_vcpu_id']+1):
     1.5                      xc.vcpu_setaffinity(self.domid, v, self.info['cpus'])
     1.6  
     1.7 +            # Use architecture- and image-specific calculations to determine
     1.8 +            # the various headrooms necessary, given the raw configured
     1.9 +            # values.
    1.10 +            # reservation, maxmem, memory, and shadow are all in KiB.
    1.11 +            reservation = self.image.getRequiredInitialReservation(
    1.12 +                self.info['memory'] * 1024)
    1.13 +            maxmem = self.image.getRequiredAvailableMemory(
    1.14 +                self.info['maxmem'] * 1024)
    1.15 +            memory = self.image.getRequiredAvailableMemory(
    1.16 +                self.info['memory'] * 1024)
    1.17 +            shadow = self.image.getRequiredShadowMemory(
    1.18 +                self.info['shadow_memory'] * 1024,
    1.19 +                self.info['maxmem'] * 1024)
    1.20 +
    1.21 +            # Round shadow up to a multiple of a MiB, as shadow_mem_control
    1.22 +            # takes MiB and we must not round down and end up under-providing.
    1.23 +            shadow = ((shadow + 1023) / 1024) * 1024
    1.24 +
    1.25              # set memory limit
    1.26 -            maxmem = self.image.getRequiredMemory(self.info['maxmem'] * 1024)
    1.27              xc.domain_setmaxmem(self.domid, maxmem)
    1.28  
    1.29 -            mem_kb = self.image.getRequiredMemory(self.info['memory'] * 1024)
    1.30 -
    1.31 -            # get the domain's shadow memory requirement
    1.32 -            shadow_kb = self.image.getRequiredShadowMemory(mem_kb)
    1.33 -            shadow_kb_req = self.info['shadow_memory'] * 1024
    1.34 -            if shadow_kb_req > shadow_kb:
    1.35 -                shadow_kb = shadow_kb_req
    1.36 -            shadow_mb = (shadow_kb + 1023) / 1024
    1.37 -
    1.38              # Make sure there's enough RAM available for the domain
    1.39 -            balloon.free(mem_kb + shadow_mb * 1024)
    1.40 +            balloon.free(memory + shadow)
    1.41  
    1.42              # Set up the shadow memory
    1.43 -            shadow_cur = xc.shadow_mem_control(self.domid, shadow_mb)
    1.44 +            shadow_cur = xc.shadow_mem_control(self.domid, shadow / 1024)
    1.45              self.info['shadow_memory'] = shadow_cur
    1.46  
    1.47 -            # initial memory allocation
    1.48 -            xc.domain_memory_increase_reservation(self.domid, mem_kb, 0, 0)
    1.49 +            # initial memory reservation
    1.50 +            xc.domain_memory_increase_reservation(self.domid, reservation, 0,
    1.51 +                                                  0)
    1.52  
    1.53              self.createChannels()
    1.54  
     2.1 --- a/tools/python/xen/xend/image.py	Tue Sep 05 14:17:49 2006 +0100
     2.2 +++ b/tools/python/xen/xend/image.py	Tue Sep 05 14:17:50 2006 +0100
     2.3 @@ -143,12 +143,27 @@ class ImageHandler:
     2.4              raise VmError('Building domain failed: ostype=%s dom=%d err=%s'
     2.5                            % (self.ostype, self.vm.getDomid(), str(result)))
     2.6  
     2.7 -    def getRequiredMemory(self, mem_kb):
     2.8 +    def getRequiredAvailableMemory(self, mem_kb):
     2.9 +        """@param mem_kb The configured maxmem or memory, in KiB.
    2.10 +        @return The corresponding required amount of memory for the domain,
    2.11 +        also in KiB.  This is normally the given mem_kb, but architecture- or
    2.12 +        image-specific code may override this to add headroom where
    2.13 +        necessary."""
    2.14          return mem_kb
    2.15  
    2.16 -    def getRequiredShadowMemory(self, mem_kb):
    2.17 -        """@return The minimum shadow memory required, in KiB, for a domain 
    2.18 -        with mem_kb KiB of RAM."""
    2.19 +    def getRequiredInitialReservation(self, mem_kb):
    2.20 +        """@param mem_kb The configured memory, in KiB.
    2.21 +        @return The corresponding required amount of memory to be free, also
    2.22 +        in KiB. This is normally the same as getRequiredAvailableMemory, but
    2.23 +        architecture- or image-specific code may override this to
    2.24 +        add headroom where necessary."""
    2.25 +        return self.getRequiredAvailableMemory(mem_kb)
    2.26 +
    2.27 +    def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb):
    2.28 +        """@param shadow_mem_kb The configured shadow memory, in KiB.
    2.29 +        @param maxmem_kb The configured maxmem, in KiB.
    2.30 +        @return The corresponding required amount of shadow memory, also in
    2.31 +        KiB."""
    2.32          # PV domains don't need any shadow memory
    2.33          return 0
    2.34  
    2.35 @@ -418,7 +433,7 @@ class IA64_HVM_ImageHandler(HVMImageHand
    2.36  
    2.37      ostype = "hvm"
    2.38  
    2.39 -    def getRequiredMemory(self, mem_kb):
    2.40 +    def getRequiredAvailableMemory(self, mem_kb):
    2.41          page_kb = 16
    2.42          # ROM size for guest firmware, ioreq page and xenstore page
    2.43          extra_pages = 1024 + 2
    2.44 @@ -432,19 +447,29 @@ class X86_HVM_ImageHandler(HVMImageHandl
    2.45  
    2.46      ostype = "hvm"
    2.47  
    2.48 -    def getRequiredMemory(self, mem_kb):
    2.49 +    def getRequiredAvailableMemory(self, mem_kb):
    2.50          page_kb = 4
    2.51          # This was derived emperically:
    2.52 -        #   2.4 MB overhead per 1024 MB RAM + 8 MB constant
    2.53 +        #   2.4 MB overhead per 1024 MB RAM
    2.54          #   + 4 to avoid low-memory condition
    2.55 -        extra_mb = (2.4/1024) * (mem_kb/1024.0) + 12;
    2.56 +        extra_mb = (2.4/1024) * (mem_kb/1024.0) + 4;
    2.57          extra_pages = int( math.ceil( extra_mb*1024 / page_kb ))
    2.58          return mem_kb + extra_pages * page_kb
    2.59  
    2.60 -    def getRequiredShadowMemory(self, mem_kb):
    2.61 +    def getRequiredInitialReservation(self, mem_kb):
    2.62 +        # Add 8 MiB overhead for QEMU's video RAM.
    2.63 +        return self.getRequiredAvailableMemory(mem_kb) + 8192
    2.64 +
    2.65 +    def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb):
    2.66 +        # The given value is the configured value -- we need to include the
    2.67 +        # overhead due to getRequiredMemory.
    2.68 +        maxmem_kb = self.getRequiredMemory(maxmem_kb)
    2.69 +
    2.70          # 1MB per vcpu plus 4Kib/Mib of RAM.  This is higher than 
    2.71          # the minimum that Xen would allocate if no value were given.
    2.72 -        return 1024 * self.vm.getVCpuCount() + mem_kb / 256
    2.73 +        return max(1024 * self.vm.getVCpuCount() + maxmem_kb / 256,
    2.74 +                   shadow_mem_kb)
    2.75 +
    2.76  
    2.77  _handlers = {
    2.78      "powerpc": {