]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
Merge branch 'x86/urgent' into x86/setup
authorH. Peter Anvin <hpa@zytor.com>
Sat, 23 May 2009 23:42:19 +0000 (16:42 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Sat, 23 May 2009 23:42:19 +0000 (16:42 -0700)
Resolved conflicts:
arch/x86/boot/memory.c

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
1  2 
arch/x86/boot/memory.c

diff --combined arch/x86/boot/memory.c
index d989de810cacc7141ed8b28253e30ee3bd1ab0ba,74b3d2ba84e90a39bb29f166278ce47bcf56437c..cae3feb1035e3da73826b518de4d47c15ad4e58d
  
  #define SMAP  0x534d4150      /* ASCII "SMAP" */
  
- struct e820_ext_entry {
-       struct e820entry std;
-       u32 ext_flags;
- } __attribute__((packed));
  static int detect_memory_e820(void)
  {
        int count = 0;
 -      u32 next = 0;
 -      u32 size, id, edi;
 -      u8 err;
 +      struct biosregs ireg, oreg;
        struct e820entry *desc = boot_params.e820_map;
-       static struct e820_ext_entry buf; /* static so it is zeroed */
+       static struct e820entry buf; /* static so it is zeroed */
  
 +      initregs(&ireg);
 +      ireg.ax  = 0xe820;
 +      ireg.cx  = sizeof buf;
 +      ireg.edx = SMAP;
 +      ireg.di  = (size_t)&buf;
 +
        /*
-        * Set this here so that if the BIOS doesn't change this field
-        * but still doesn't change %ecx, we're still okay...
+        * Note: at least one BIOS is known which assumes that the
+        * buffer pointed to by one e820 call is the same one as
+        * the previous call, and only changes modified fields.  Therefore,
+        * we use a temporary buffer and copy the results entry by entry.
+        *
+        * This routine deliberately does not try to account for
+        * ACPI 3+ extended attributes.  This is because there are
+        * BIOSes in the field which report zero for the valid bit for
+        * all ranges, and we don't currently make any use of the
+        * other attribute bits.  Revisit this if we see the extended
+        * attribute bits deployed in a meaningful way in the future.
         */
-       buf.ext_flags = 1;
  
        do {
 -              size = sizeof buf;
 -
 -              /* Important: %edx and %esi are clobbered by some BIOSes,
 -                 so they must be either used for the error output
 -                 or explicitly marked clobbered.  Given that, assume there
 -                 is something out there clobbering %ebp and %edi, too. */
 -              asm("pushl %%ebp; int $0x15; popl %%ebp; setc %0"
 -                  : "=d" (err), "+b" (next), "=a" (id), "+c" (size),
 -                    "=D" (edi), "+m" (buf)
 -                  : "D" (&buf), "d" (SMAP), "a" (0xe820)
 -                  : "esi");
 +              intcall(0x15, &ireg, &oreg);
 +              ireg.ebx = oreg.ebx; /* for next iteration... */
  
                /* BIOSes which terminate the chain with CF = 1 as opposed
                   to %ebx = 0 don't always report the SMAP signature on
                   the final, failing, probe. */
 -              if (err)
 +              if (oreg.eflags & X86_EFLAGS_CF)
                        break;
  
                /* Some BIOSes stop returning SMAP in the middle of
                   screwed up the map at that point, we might have a
                   partial map, the full map, or complete garbage, so
                   just return failure. */
 -              if (id != SMAP) {
 +              if (oreg.eax != SMAP) {
                        count = 0;
                        break;
                }
  
-               /* ACPI 3.0 added the extended flags support.  If bit 0
-                  in the extended flags is zero, we're supposed to simply
-                  ignore the entry -- a backwards incompatible change! */
-               if (oreg.cx > 20 && !(buf.ext_flags & 1))
-                       continue;
-               *desc++ = buf.std;
+               *desc++ = buf;
                count++;
 -      } while (next && count < ARRAY_SIZE(boot_params.e820_map));
 +      } while (ireg.ebx && count < ARRAY_SIZE(boot_params.e820_map));
  
        return boot_params.e820_entries = count;
  }
  
  static int detect_memory_e801(void)
  {
 -      u16 ax, bx, cx, dx;
 -      u8 err;
 +      struct biosregs ireg, oreg;
  
 -      bx = cx = dx = 0;
 -      ax = 0xe801;
 -      asm("stc; int $0x15; setc %0"
 -          : "=m" (err), "+a" (ax), "+b" (bx), "+c" (cx), "+d" (dx));
 +      initregs(&ireg);
 +      ireg.ax = 0xe801;
 +      intcall(0x15, &ireg, &oreg);
  
 -      if (err)
 +      if (oreg.eflags & X86_EFLAGS_CF)
                return -1;
  
        /* Do we really need to do this? */
 -      if (cx || dx) {
 -              ax = cx;
 -              bx = dx;
 +      if (oreg.cx || oreg.dx) {
 +              oreg.ax = oreg.cx;
 +              oreg.bx = oreg.dx;
        }
  
 -      if (ax > 15*1024)
 +      if (oreg.ax > 15*1024) {
                return -1;      /* Bogus! */
 -
 -      /* This ignores memory above 16MB if we have a memory hole
 -         there.  If someone actually finds a machine with a memory
 -         hole at 16MB and no support for 0E820h they should probably
 -         generate a fake e820 map. */
 -      boot_params.alt_mem_k = (ax == 15*1024) ? (dx << 6)+ax : ax;
 +      } else if (oreg.ax == 15*1024) {
 +              boot_params.alt_mem_k = (oreg.dx << 6) + oreg.ax;
 +      } else {
 +              /*
 +               * This ignores memory above 16MB if we have a memory
 +               * hole there.  If someone actually finds a machine
 +               * with a memory hole at 16MB and no support for
 +               * 0E820h they should probably generate a fake e820
 +               * map.
 +               */
 +              boot_params.alt_mem_k = oreg.ax;
 +      }
  
        return 0;
  }
  
  static int detect_memory_88(void)
  {
 -      u16 ax;
 -      u8 err;
 +      struct biosregs ireg, oreg;
  
 -      ax = 0x8800;
 -      asm("stc; int $0x15; setc %0" : "=bcdm" (err), "+a" (ax));
 +      initregs(&ireg);
 +      ireg.ah = 0x88;
 +      intcall(0x15, &ireg, &oreg);
  
 -      boot_params.screen_info.ext_mem_k = ax;
 +      boot_params.screen_info.ext_mem_k = oreg.ax;
  
 -      return -err;
 +      return -(oreg.eflags & X86_EFLAGS_CF); /* 0 or -1 */
  }
  
  int detect_memory(void)