[Xen-devel] [v8][PATCH 07/16] hvmloader/e820: construct guest e820 table

2015-07-16 Thread Tiejun Chen
Now use the hypervisor-supplied memory map to build our final e820 table:
* Add regions for BIOS ranges and other special mappings not in the
  hypervisor map
* Add in the hypervisor regions
* Adjust the lowmem and highmem regions if we've had to relocate
  memory (adding a highmem region if necessary)
* Sort all the ranges so that they appear in memory order.

CC: Keir Fraser k...@xen.org
CC: Jan Beulich jbeul...@suse.com
CC: Andrew Cooper andrew.coop...@citrix.com
CC: Ian Jackson ian.jack...@eu.citrix.com
CC: Stefano Stabellini stefano.stabell...@eu.citrix.com
CC: Ian Campbell ian.campb...@citrix.com
CC: Wei Liu wei.l...@citrix.com
Signed-off-by: Tiejun Chen tiejun.c...@intel.com
---
v8:

* define low_mem_end as uint32_t

* Correct those two wrong loops, memory_map.nr_map - nr
  when we're trying to revise low/high memory e820 entries.

* Improve code comments and the patch head description

* Add one check if highmem is just populated by hvmloader itself

v5 ~ v7:

* Nothing is changed.

v4:

* Rename local variable, low_mem_pgend, to low_mem_end.

* Improve some code comments

* Adjust highmem after lowmem is changed.
 
 
 tools/firmware/hvmloader/e820.c | 92 +
 1 file changed, 83 insertions(+), 9 deletions(-)

diff --git a/tools/firmware/hvmloader/e820.c b/tools/firmware/hvmloader/e820.c
index b72baa5..aa678a7 100644
--- a/tools/firmware/hvmloader/e820.c
+++ b/tools/firmware/hvmloader/e820.c
@@ -108,7 +108,9 @@ int build_e820_table(struct e820entry *e820,
  unsigned int lowmem_reserved_base,
  unsigned int bios_image_base)
 {
-unsigned int nr = 0;
+unsigned int nr = 0, i, j;
+uint64_t add_high_mem = 0;
+uint32_t low_mem_end = hvm_info-low_mem_pgend  PAGE_SHIFT;
 
 if ( !lowmem_reserved_base )
 lowmem_reserved_base = 0xA;
@@ -152,13 +154,6 @@ int build_e820_table(struct e820entry *e820,
 e820[nr].type = E820_RESERVED;
 nr++;
 
-/* Low RAM goes here. Reserve space for special pages. */
-BUG_ON((hvm_info-low_mem_pgend  PAGE_SHIFT)  (2u  20));
-e820[nr].addr = 0x10;
-e820[nr].size = (hvm_info-low_mem_pgend  PAGE_SHIFT) - e820[nr].addr;
-e820[nr].type = E820_RAM;
-nr++;
-
 /*
  * Explicitly reserve space for special pages.
  * This space starts at RESERVED_MEMBASE an extends to cover various
@@ -194,9 +189,73 @@ int build_e820_table(struct e820entry *e820,
 nr++;
 }
 
+/*
+ * Construct E820 table according to recorded memory map.
+ *
+ * The memory map created by toolstack may include,
+ *
+ * #1. Low memory region
+ *
+ * Low RAM starts at least from 1M to make sure all standard regions
+ * of the PC memory map, like BIOS, VGA memory-mapped I/O and vgabios,
+ * have enough space.
+ *
+ * #2. Reserved regions if they exist
+ *
+ * #3. High memory region if it exists
+ */
+for ( i = 0; i  memory_map.nr_map; i++ )
+{
+e820[nr] = memory_map.map[i];
+nr++;
+}
+
+/* Low RAM goes here. Reserve space for special pages. */
+BUG_ON(low_mem_end  (2u  20));
 
-if ( hvm_info-high_mem_pgend )
+/*
+ * Its possible to relocate RAM to allocate sufficient MMIO previously
+ * so low_mem_pgend would be changed over there. And here memory_map[]
+ * records the original low/high memory, so if low_mem_end is less than
+ * the original we need to revise low/high memory range in e820.
+ */
+for ( i = 0; i  nr; i++ )
 {
+uint64_t end = e820[i].addr + e820[i].size;
+if ( e820[i].type == E820_RAM 
+ low_mem_end  e820[i].addr  low_mem_end  end )
+{
+add_high_mem = end - low_mem_end;
+e820[i].size = low_mem_end - e820[i].addr;
+}
+}
+
+/*
+ * And then we also need to adjust highmem.
+ */
+if ( add_high_mem )
+{
+for ( i = 0; i  nr; i++ )
+{
+if ( e820[i].type == E820_RAM 
+ e820[i].addr == (1ull  32))
+{
+e820[i].size += add_high_mem;
+add_high_mem = 0;
+break;
+}
+}
+}
+
+/* Or this is just populated by hvmloader itself. */
+if ( add_high_mem )
+{
+/*
+ * hvmloader should always update hvm_info-high_mem_pgend
+ * when it relocates RAM anywhere.
+ */
+BUG_ON( !hvm_info-high_mem_pgend );
+
 e820[nr].addr = ((uint64_t)1  32);
 e820[nr].size =
 ((uint64_t)hvm_info-high_mem_pgend  PAGE_SHIFT) - e820[nr].addr;
@@ -204,6 +263,21 @@ int build_e820_table(struct e820entry *e820,
 nr++;
 }
 
+/* Finally we need to sort all e820 entries. */
+for ( j = 0; j  nr-1; j++ )
+{
+for ( i = j+1; i  nr; i++ )
+{
+if ( e820[j].addr  e820[i].addr )
+{
+struct e820entry tmp;
+  

Re: [Xen-devel] [v8][PATCH 07/16] hvmloader/e820: construct guest e820 table

2015-07-16 Thread Chen, Tiejun

+/*
+ * And then we also need to adjust highmem.
+ */
+if ( add_high_mem )
+{
+for ( i = 0; i  nr; i++ )
+{
+if ( e820[i].type == E820_RAM 
+ e820[i].addr == (1ull  32))
+{
+e820[i].size += add_high_mem;
+add_high_mem = 0;
+break;
+}
+}
+}
+
+/* Or this is just populated by hvmloader itself. */


This should probably say something like:

If there was no highmem region, we need to create one.


Okay, If there was no highmem entry, we need to create one.




+if ( add_high_mem )
+{
+/*
+ * hvmloader should always update hvm_info-high_mem_pgend
+ * when it relocates RAM anywhere.
+ */
+BUG_ON( !hvm_info-high_mem_pgend );
+
  e820[nr].addr = ((uint64_t)1  32);
  e820[nr].size =
  ((uint64_t)hvm_info-high_mem_pgend  PAGE_SHIFT) - 
e820[nr].addr;


In theory add_high_mem and hvm_info-high_mem_pgend  PAGE_SHIFT -
4GiB is the same, but it seems like asking for trouble to assume so


No, its not true in the first if( add_high_mem ) conditional.

Before we enter hvmloader, there are two cases:

#1. hvm_info-high_mem_pgend == 0

So we wouldn't have a highmem entry in e820. But hvmloader may relocate 
RAM upward highmem (add_high_mem) to get sufficient mmio, so 
hvm_info-high_mem_pgend is expanded somewhere (4GiB + add_high_mem).


Then we would fall into the second if( add_high_mem ) conditional.

#2. hvm_info-high_mem_pgend != 0

We always walk into the first if( add_high_mem ) conditional. But here 
add_high_mem just represents that highmem section expanded by 
hvmloader, its really not the whole higmem:(hvm_info-high_mem_pgend  
PAGE_SHIFT - 4GiB).


Thanks
Tiejun


without checking.

Perhaps in the first if( add_high_mem ) conditional, you can
BUG_ON(add_high_mem != ((hvm_info-high_mem_pgend  PAGE_SHIFT) -
(ull1  32))) ?

Other than that, this looks good, thanks.

  -George



___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [v8][PATCH 07/16] hvmloader/e820: construct guest e820 table

2015-07-16 Thread George Dunlap
On Thu, Jul 16, 2015 at 2:12 PM, Chen, Tiejun tiejun.c...@intel.com wrote:
 +if ( add_high_mem )
 +{
 +/*
 + * hvmloader should always update hvm_info-high_mem_pgend
 + * when it relocates RAM anywhere.
 + */
 +BUG_ON( !hvm_info-high_mem_pgend );
 +
   e820[nr].addr = ((uint64_t)1  32);
   e820[nr].size =
   ((uint64_t)hvm_info-high_mem_pgend  PAGE_SHIFT) -
 e820[nr].addr;


 In theory add_high_mem and hvm_info-high_mem_pgend  PAGE_SHIFT -
 4GiB is the same, but it seems like asking for trouble to assume so


 No, its not true in the first if( add_high_mem ) conditional.

 Before we enter hvmloader, there are two cases:

 #1. hvm_info-high_mem_pgend == 0

 So we wouldn't have a highmem entry in e820. But hvmloader may relocate RAM
 upward highmem (add_high_mem) to get sufficient mmio, so
 hvm_info-high_mem_pgend is expanded somewhere (4GiB + add_high_mem).

 Then we would fall into the second if( add_high_mem ) conditional.

 #2. hvm_info-high_mem_pgend != 0

 We always walk into the first if( add_high_mem ) conditional. But here
 add_high_mem just represents that highmem section expanded by hvmloader,
 its really not the whole higmem:(hvm_info-high_mem_pgend  PAGE_SHIFT -
 4GiB).

Yes, sorry, add_high_mem will be the size of memory *relocated*, not
the actual end of it (unless, as you say, the original highmem region
didn't exist).

What I really meant was that either way, after adjusting the highmem
region in the e820, the end of that region should correspond to
hvm_info-high_mem_pgend.

What about something like this?
---
/*
 * And then we also need to adjust highmem.
 */
if ( add_high_mem )
{
/*
 * Modify the existing highmem region if it exists
 */
for ( i = 0; i  nr; i++ )
{
if ( e820[i].type == E820_RAM 
 e820[i].addr == (1ull  32))
{
e820[i].size += add_high_mem;
break;
}
}

/*
 * If we didn't find a highmem region, make one
 */
if ( i == nr )
{
e820[nr].addr = ((uint64_t)1  32);
e820[nr].size = e820[nr].addr + add_high_mem;
e820[nr].type = E820_RAM;
nr++;
}

/*
 * Either way, at this point i points to the entry containing
 * highmem.  Compare it to what's in hvm_info as a sanity
 * check.
 */
BUG_ON(e820[i].addr+e820[i].size !=
   ((uint64_t)hvm_info-high_mem_pgend  PAGE_SHIFT));
}

--

 -George

___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [v8][PATCH 07/16] hvmloader/e820: construct guest e820 table

2015-07-16 Thread Chen, Tiejun

Yes, sorry, add_high_mem will be the size of memory *relocated*, not
the actual end of it (unless, as you say, the original highmem region
didn't exist).

What I really meant was that either way, after adjusting the highmem
region in the e820, the end of that region should correspond to
hvm_info-high_mem_pgend.

What about something like this?
---
 /*
  * And then we also need to adjust highmem.
  */
 if ( add_high_mem )
 {
 /*
  * Modify the existing highmem region if it exists
  */
 for ( i = 0; i  nr; i++ )
 {
 if ( e820[i].type == E820_RAM 
  e820[i].addr == (1ull  32))
 {
 e820[i].size += add_high_mem;
 break;
 }
 }

 /*
  * If we didn't find a highmem region, make one
  */
 if ( i == nr )
 {
 e820[nr].addr = ((uint64_t)1  32);
 e820[nr].size = e820[nr].addr + add_high_mem;
 e820[nr].type = E820_RAM;
 nr++;
 }

 /*
  * Either way, at this point i points to the entry containing
  * highmem.  Compare it to what's in hvm_info as a sanity
  * check.
  */
 BUG_ON(e820[i].addr+e820[i].size !=
((uint64_t)hvm_info-high_mem_pgend  PAGE_SHIFT));
 }



Looks really better.

I just introduce a little change based on yours, and I post this as a whole,

diff --git a/tools/firmware/hvmloader/e820.c 
b/tools/firmware/hvmloader/e820.c

index 7a414ab..8c9b01f 100644
--- a/tools/firmware/hvmloader/e820.c
+++ b/tools/firmware/hvmloader/e820.c
@@ -105,7 +105,10 @@ int build_e820_table(struct e820entry *e820,
  unsigned int lowmem_reserved_base,
  unsigned int bios_image_base)
 {
-unsigned int nr = 0;
+unsigned int nr = 0, i, j;
+uint32_t low_mem_end = hvm_info-low_mem_pgend  PAGE_SHIFT;
+uint64_t high_mem_end = (uint64_t)hvm_info-high_mem_pgend  
PAGE_SHIFT;

+uint64_t add_high_mem = 0;

 if ( !lowmem_reserved_base )
 lowmem_reserved_base = 0xA;
@@ -149,13 +152,6 @@ int build_e820_table(struct e820entry *e820,
 e820[nr].type = E820_RESERVED;
 nr++;

-/* Low RAM goes here. Reserve space for special pages. */
-BUG_ON((hvm_info-low_mem_pgend  PAGE_SHIFT)  (2u  20));
-e820[nr].addr = 0x10;
-e820[nr].size = (hvm_info-low_mem_pgend  PAGE_SHIFT) - 
e820[nr].addr;

-e820[nr].type = E820_RAM;
-nr++;
-
 /*
  * Explicitly reserve space for special pages.
  * This space starts at RESERVED_MEMBASE an extends to cover various
@@ -191,16 +187,91 @@ int build_e820_table(struct e820entry *e820,
 nr++;
 }

-
-if ( hvm_info-high_mem_pgend )
+/*
+ * Construct E820 table according to recorded memory map.
+ *
+ * The memory map created by toolstack may include,
+ *
+ * #1. Low memory region
+ *
+ * Low RAM starts at least from 1M to make sure all standard regions
+ * of the PC memory map, like BIOS, VGA memory-mapped I/O and vgabios,
+ * have enough space.
+ *
+ * #2. Reserved regions if they exist
+ *
+ * #3. High memory region if it exists
+ */
+for ( i = 0; i  memory_map.nr_map; i++ )
 {
-e820[nr].addr = ((uint64_t)1  32);
-e820[nr].size =
-((uint64_t)hvm_info-high_mem_pgend  PAGE_SHIFT) - 
e820[nr].addr;

-e820[nr].type = E820_RAM;
+e820[nr] = memory_map.map[i];
 nr++;
 }

+/* Low RAM goes here. Reserve space for special pages. */
+BUG_ON(low_mem_end  (2u  20));
+
+/*
+ * Its possible to relocate RAM to allocate sufficient MMIO previously
+ * so low_mem_pgend would be changed over there. And here memory_map[]
+ * records the original low/high memory, so if low_mem_end is less than
+ * the original we need to revise low/high memory range in e820.
+ */
+for ( i = 0; i  nr; i++ )
+{
+uint64_t end = e820[i].addr + e820[i].size;
+if ( e820[i].type == E820_RAM 
+ low_mem_end  e820[i].addr  low_mem_end  end )
+{
+add_high_mem = end - low_mem_end;
+e820[i].size = low_mem_end - e820[i].addr;
+}
+}
+
+/*
+ * And then we also need to adjust highmem.
+ */
+if ( add_high_mem )
+{
+/* Modify the existing highmem region if it exists. */
+for ( i = 0; i  nr; i++ )
+{
+if ( e820[i].type == E820_RAM 
+ e820[i].addr == ((uint64_t)1  32))
+{
+e820[i].size += add_high_mem;
+break;
+}
+}
+
+/* If there was no highmem region, just create one. */
+if ( i == nr )
+{
+e820[nr].addr = ((uint64_t)1  32);
+e820[nr].size = high_mem_end  - e820[nr].addr;
+e820[nr].type = E820_RAM;
+

Re: [Xen-devel] [v8][PATCH 07/16] hvmloader/e820: construct guest e820 table

2015-07-16 Thread Chen, Tiejun



On 2015/7/16 23:16, George Dunlap wrote:

On 07/16/2015 04:04 PM, Chen, Tiejun wrote:

Yes, sorry, add_high_mem will be the size of memory *relocated*, not
the actual end of it (unless, as you say, the original highmem region
didn't exist).

What I really meant was that either way, after adjusting the highmem
region in the e820, the end of that region should correspond to
hvm_info-high_mem_pgend.

What about something like this?
---
  /*
   * And then we also need to adjust highmem.
   */
  if ( add_high_mem )
  {
  /*
   * Modify the existing highmem region if it exists
   */
  for ( i = 0; i  nr; i++ )
  {
  if ( e820[i].type == E820_RAM 
   e820[i].addr == (1ull  32))
  {
  e820[i].size += add_high_mem;
  break;
  }
  }

  /*
   * If we didn't find a highmem region, make one
   */
  if ( i == nr )
  {
  e820[nr].addr = ((uint64_t)1  32);
  e820[nr].size = e820[nr].addr + add_high_mem;
  e820[nr].type = E820_RAM;
  nr++;
  }

  /*
   * Either way, at this point i points to the entry containing
   * highmem.  Compare it to what's in hvm_info as a sanity
   * check.
   */
  BUG_ON(e820[i].addr+e820[i].size !=
 ((uint64_t)hvm_info-high_mem_pgend  PAGE_SHIFT));
  }



Looks really better.

I just introduce a little change based on yours, and I post this as a
whole,

diff --git a/tools/firmware/hvmloader/e820.c
b/tools/firmware/hvmloader/e820.c
index 7a414ab..8c9b01f 100644
--- a/tools/firmware/hvmloader/e820.c
+++ b/tools/firmware/hvmloader/e820.c
@@ -105,7 +105,10 @@ int build_e820_table(struct e820entry *e820,
   unsigned int lowmem_reserved_base,
   unsigned int bios_image_base)
  {
-unsigned int nr = 0;
+unsigned int nr = 0, i, j;
+uint32_t low_mem_end = hvm_info-low_mem_pgend  PAGE_SHIFT;
+uint64_t high_mem_end = (uint64_t)hvm_info-high_mem_pgend 
PAGE_SHIFT;
+uint64_t add_high_mem = 0;

  if ( !lowmem_reserved_base )
  lowmem_reserved_base = 0xA;
@@ -149,13 +152,6 @@ int build_e820_table(struct e820entry *e820,
  e820[nr].type = E820_RESERVED;
  nr++;

-/* Low RAM goes here. Reserve space for special pages. */
-BUG_ON((hvm_info-low_mem_pgend  PAGE_SHIFT)  (2u  20));
-e820[nr].addr = 0x10;
-e820[nr].size = (hvm_info-low_mem_pgend  PAGE_SHIFT) -
e820[nr].addr;
-e820[nr].type = E820_RAM;
-nr++;
-
  /*
   * Explicitly reserve space for special pages.
   * This space starts at RESERVED_MEMBASE an extends to cover various
@@ -191,16 +187,91 @@ int build_e820_table(struct e820entry *e820,
  nr++;
  }

-
-if ( hvm_info-high_mem_pgend )
+/*
+ * Construct E820 table according to recorded memory map.
+ *
+ * The memory map created by toolstack may include,
+ *
+ * #1. Low memory region
+ *
+ * Low RAM starts at least from 1M to make sure all standard regions
+ * of the PC memory map, like BIOS, VGA memory-mapped I/O and vgabios,
+ * have enough space.
+ *
+ * #2. Reserved regions if they exist
+ *
+ * #3. High memory region if it exists
+ */
+for ( i = 0; i  memory_map.nr_map; i++ )
  {
-e820[nr].addr = ((uint64_t)1  32);
-e820[nr].size =
-((uint64_t)hvm_info-high_mem_pgend  PAGE_SHIFT) -
e820[nr].addr;
-e820[nr].type = E820_RAM;
+e820[nr] = memory_map.map[i];
  nr++;
  }

+/* Low RAM goes here. Reserve space for special pages. */
+BUG_ON(low_mem_end  (2u  20));
+
+/*
+ * Its possible to relocate RAM to allocate sufficient MMIO previously
+ * so low_mem_pgend would be changed over there. And here memory_map[]
+ * records the original low/high memory, so if low_mem_end is less
than
+ * the original we need to revise low/high memory range in e820.
+ */
+for ( i = 0; i  nr; i++ )
+{
+uint64_t end = e820[i].addr + e820[i].size;
+if ( e820[i].type == E820_RAM 
+ low_mem_end  e820[i].addr  low_mem_end  end )
+{
+add_high_mem = end - low_mem_end;
+e820[i].size = low_mem_end - e820[i].addr;
+}
+}
+
+/*
+ * And then we also need to adjust highmem.
+ */
+if ( add_high_mem )
+{
+/* Modify the existing highmem region if it exists. */
+for ( i = 0; i  nr; i++ )
+{
+if ( e820[i].type == E820_RAM 
+ e820[i].addr == ((uint64_t)1  32))
+{
+e820[i].size += add_high_mem;
+break;
+}
+}
+
+/* If there was no highmem region, just create one. */
+if ( i == nr )
+{
+e820[nr].addr = 

Re: [Xen-devel] [v8][PATCH 07/16] hvmloader/e820: construct guest e820 table

2015-07-16 Thread George Dunlap
On 07/16/2015 04:04 PM, Chen, Tiejun wrote:
 Yes, sorry, add_high_mem will be the size of memory *relocated*, not
 the actual end of it (unless, as you say, the original highmem region
 didn't exist).

 What I really meant was that either way, after adjusting the highmem
 region in the e820, the end of that region should correspond to
 hvm_info-high_mem_pgend.

 What about something like this?
 ---
  /*
   * And then we also need to adjust highmem.
   */
  if ( add_high_mem )
  {
  /*
   * Modify the existing highmem region if it exists
   */
  for ( i = 0; i  nr; i++ )
  {
  if ( e820[i].type == E820_RAM 
   e820[i].addr == (1ull  32))
  {
  e820[i].size += add_high_mem;
  break;
  }
  }

  /*
   * If we didn't find a highmem region, make one
   */
  if ( i == nr )
  {
  e820[nr].addr = ((uint64_t)1  32);
  e820[nr].size = e820[nr].addr + add_high_mem;
  e820[nr].type = E820_RAM;
  nr++;
  }

  /*
   * Either way, at this point i points to the entry containing
   * highmem.  Compare it to what's in hvm_info as a sanity
   * check.
   */
  BUG_ON(e820[i].addr+e820[i].size !=
 ((uint64_t)hvm_info-high_mem_pgend  PAGE_SHIFT));
  }

 
 Looks really better.
 
 I just introduce a little change based on yours, and I post this as a
 whole,
 
 diff --git a/tools/firmware/hvmloader/e820.c
 b/tools/firmware/hvmloader/e820.c
 index 7a414ab..8c9b01f 100644
 --- a/tools/firmware/hvmloader/e820.c
 +++ b/tools/firmware/hvmloader/e820.c
 @@ -105,7 +105,10 @@ int build_e820_table(struct e820entry *e820,
   unsigned int lowmem_reserved_base,
   unsigned int bios_image_base)
  {
 -unsigned int nr = 0;
 +unsigned int nr = 0, i, j;
 +uint32_t low_mem_end = hvm_info-low_mem_pgend  PAGE_SHIFT;
 +uint64_t high_mem_end = (uint64_t)hvm_info-high_mem_pgend 
 PAGE_SHIFT;
 +uint64_t add_high_mem = 0;
 
  if ( !lowmem_reserved_base )
  lowmem_reserved_base = 0xA;
 @@ -149,13 +152,6 @@ int build_e820_table(struct e820entry *e820,
  e820[nr].type = E820_RESERVED;
  nr++;
 
 -/* Low RAM goes here. Reserve space for special pages. */
 -BUG_ON((hvm_info-low_mem_pgend  PAGE_SHIFT)  (2u  20));
 -e820[nr].addr = 0x10;
 -e820[nr].size = (hvm_info-low_mem_pgend  PAGE_SHIFT) -
 e820[nr].addr;
 -e820[nr].type = E820_RAM;
 -nr++;
 -
  /*
   * Explicitly reserve space for special pages.
   * This space starts at RESERVED_MEMBASE an extends to cover various
 @@ -191,16 +187,91 @@ int build_e820_table(struct e820entry *e820,
  nr++;
  }
 
 -
 -if ( hvm_info-high_mem_pgend )
 +/*
 + * Construct E820 table according to recorded memory map.
 + *
 + * The memory map created by toolstack may include,
 + *
 + * #1. Low memory region
 + *
 + * Low RAM starts at least from 1M to make sure all standard regions
 + * of the PC memory map, like BIOS, VGA memory-mapped I/O and vgabios,
 + * have enough space.
 + *
 + * #2. Reserved regions if they exist
 + *
 + * #3. High memory region if it exists
 + */
 +for ( i = 0; i  memory_map.nr_map; i++ )
  {
 -e820[nr].addr = ((uint64_t)1  32);
 -e820[nr].size =
 -((uint64_t)hvm_info-high_mem_pgend  PAGE_SHIFT) -
 e820[nr].addr;
 -e820[nr].type = E820_RAM;
 +e820[nr] = memory_map.map[i];
  nr++;
  }
 
 +/* Low RAM goes here. Reserve space for special pages. */
 +BUG_ON(low_mem_end  (2u  20));
 +
 +/*
 + * Its possible to relocate RAM to allocate sufficient MMIO previously
 + * so low_mem_pgend would be changed over there. And here memory_map[]
 + * records the original low/high memory, so if low_mem_end is less
 than
 + * the original we need to revise low/high memory range in e820.
 + */
 +for ( i = 0; i  nr; i++ )
 +{
 +uint64_t end = e820[i].addr + e820[i].size;
 +if ( e820[i].type == E820_RAM 
 + low_mem_end  e820[i].addr  low_mem_end  end )
 +{
 +add_high_mem = end - low_mem_end;
 +e820[i].size = low_mem_end - e820[i].addr;
 +}
 +}
 +
 +/*
 + * And then we also need to adjust highmem.
 + */
 +if ( add_high_mem )
 +{
 +/* Modify the existing highmem region if it exists. */
 +for ( i = 0; i  nr; i++ )
 +{
 +if ( e820[i].type == E820_RAM 
 + e820[i].addr == ((uint64_t)1  32))
 +{
 +e820[i].size += add_high_mem;
 +break;
 +}
 +}
 +
 +/* If there was no highmem region, just create one. */
 +   

Re: [Xen-devel] [v8][PATCH 07/16] hvmloader/e820: construct guest e820 table

2015-07-16 Thread George Dunlap
On 07/16/2015 04:29 PM, Chen, Tiejun wrote:
 
 
 On 2015/7/16 23:16, George Dunlap wrote:
 On 07/16/2015 04:04 PM, Chen, Tiejun wrote:
 Yes, sorry, add_high_mem will be the size of memory *relocated*, not
 the actual end of it (unless, as you say, the original highmem region
 didn't exist).

 What I really meant was that either way, after adjusting the highmem
 region in the e820, the end of that region should correspond to
 hvm_info-high_mem_pgend.

 What about something like this?
 ---
   /*
* And then we also need to adjust highmem.
*/
   if ( add_high_mem )
   {
   /*
* Modify the existing highmem region if it exists
*/
   for ( i = 0; i  nr; i++ )
   {
   if ( e820[i].type == E820_RAM 
e820[i].addr == (1ull  32))
   {
   e820[i].size += add_high_mem;
   break;
   }
   }

   /*
* If we didn't find a highmem region, make one
*/
   if ( i == nr )
   {
   e820[nr].addr = ((uint64_t)1  32);
   e820[nr].size = e820[nr].addr + add_high_mem;
   e820[nr].type = E820_RAM;
   nr++;
   }

   /*
* Either way, at this point i points to the entry containing
* highmem.  Compare it to what's in hvm_info as a sanity
* check.
*/
   BUG_ON(e820[i].addr+e820[i].size !=
  ((uint64_t)hvm_info-high_mem_pgend  PAGE_SHIFT));
   }


 Looks really better.

 I just introduce a little change based on yours, and I post this as a
 whole,

 diff --git a/tools/firmware/hvmloader/e820.c
 b/tools/firmware/hvmloader/e820.c
 index 7a414ab..8c9b01f 100644
 --- a/tools/firmware/hvmloader/e820.c
 +++ b/tools/firmware/hvmloader/e820.c
 @@ -105,7 +105,10 @@ int build_e820_table(struct e820entry *e820,
unsigned int lowmem_reserved_base,
unsigned int bios_image_base)
   {
 -unsigned int nr = 0;
 +unsigned int nr = 0, i, j;
 +uint32_t low_mem_end = hvm_info-low_mem_pgend  PAGE_SHIFT;
 +uint64_t high_mem_end = (uint64_t)hvm_info-high_mem_pgend 
 PAGE_SHIFT;
 +uint64_t add_high_mem = 0;

   if ( !lowmem_reserved_base )
   lowmem_reserved_base = 0xA;
 @@ -149,13 +152,6 @@ int build_e820_table(struct e820entry *e820,
   e820[nr].type = E820_RESERVED;
   nr++;

 -/* Low RAM goes here. Reserve space for special pages. */
 -BUG_ON((hvm_info-low_mem_pgend  PAGE_SHIFT)  (2u  20));
 -e820[nr].addr = 0x10;
 -e820[nr].size = (hvm_info-low_mem_pgend  PAGE_SHIFT) -
 e820[nr].addr;
 -e820[nr].type = E820_RAM;
 -nr++;
 -
   /*
* Explicitly reserve space for special pages.
* This space starts at RESERVED_MEMBASE an extends to cover
 various
 @@ -191,16 +187,91 @@ int build_e820_table(struct e820entry *e820,
   nr++;
   }

 -
 -if ( hvm_info-high_mem_pgend )
 +/*
 + * Construct E820 table according to recorded memory map.
 + *
 + * The memory map created by toolstack may include,
 + *
 + * #1. Low memory region
 + *
 + * Low RAM starts at least from 1M to make sure all standard
 regions
 + * of the PC memory map, like BIOS, VGA memory-mapped I/O and
 vgabios,
 + * have enough space.
 + *
 + * #2. Reserved regions if they exist
 + *
 + * #3. High memory region if it exists
 + */
 +for ( i = 0; i  memory_map.nr_map; i++ )
   {
 -e820[nr].addr = ((uint64_t)1  32);
 -e820[nr].size =
 -((uint64_t)hvm_info-high_mem_pgend  PAGE_SHIFT) -
 e820[nr].addr;
 -e820[nr].type = E820_RAM;
 +e820[nr] = memory_map.map[i];
   nr++;
   }

 +/* Low RAM goes here. Reserve space for special pages. */
 +BUG_ON(low_mem_end  (2u  20));
 +
 +/*
 + * Its possible to relocate RAM to allocate sufficient MMIO
 previously
 + * so low_mem_pgend would be changed over there. And here
 memory_map[]
 + * records the original low/high memory, so if low_mem_end is less
 than
 + * the original we need to revise low/high memory range in e820.
 + */
 +for ( i = 0; i  nr; i++ )
 +{
 +uint64_t end = e820[i].addr + e820[i].size;
 +if ( e820[i].type == E820_RAM 
 + low_mem_end  e820[i].addr  low_mem_end  end )
 +{
 +add_high_mem = end - low_mem_end;
 +e820[i].size = low_mem_end - e820[i].addr;
 +}
 +}
 +
 +/*
 + * And then we also need to adjust highmem.
 + */
 +if ( add_high_mem )
 +{
 +/* Modify the existing highmem region if it exists. */
 +for ( i = 0; i  nr; i++ )
 +{
 +if ( e820[i].type == E820_RAM 
 + e820[i].addr == ((uint64_t)1  32))
 +{
 +e820[i].size += 

Re: [Xen-devel] [v8][PATCH 07/16] hvmloader/e820: construct guest e820 table

2015-07-16 Thread Chen, Tiejun

Honestly I didn't try to change that point but maybe I'm missing something?


Yes, you are missing something. :-)  I told you exactly what I wanted
changed and what I said could remain the same:


By all means, calculate high_mem_end so it's easier to read.  But then,
when creating a new region, set e820[nr].size = add_high_mem, so that
the BUG_ON() that follows actually checks something useful.


Just to be clear, I want the second if() statement to look like this:


+if ( i == nr )
+{
+e820[nr].addr = ((uint64_t)1  32);
+e820[nr].size = add_high_mem;


Ahh, when you're replying this, I also see this difference and realize 
what you meant. Sorry to this inconvenience and I'll sync this line into 
my tree :)


Thanks
Tiejun


+e820[nr].type = E820_RAM;
+nr++;
+}


Think about why and maybe that will help you understand what I'm talking
about.

  -George



___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [v8][PATCH 07/16] hvmloader/e820: construct guest e820 table

2015-07-16 Thread George Dunlap
On Thu, Jul 16, 2015 at 7:52 AM, Tiejun Chen tiejun.c...@intel.com wrote:
 Now use the hypervisor-supplied memory map to build our final e820 table:
 * Add regions for BIOS ranges and other special mappings not in the
   hypervisor map
 * Add in the hypervisor regions
 * Adjust the lowmem and highmem regions if we've had to relocate
   memory (adding a highmem region if necessary)
 * Sort all the ranges so that they appear in memory order.

 CC: Keir Fraser k...@xen.org
 CC: Jan Beulich jbeul...@suse.com
 CC: Andrew Cooper andrew.coop...@citrix.com
 CC: Ian Jackson ian.jack...@eu.citrix.com
 CC: Stefano Stabellini stefano.stabell...@eu.citrix.com
 CC: Ian Campbell ian.campb...@citrix.com
 CC: Wei Liu wei.l...@citrix.com
 Signed-off-by: Tiejun Chen tiejun.c...@intel.com
 ---
 v8:

 * define low_mem_end as uint32_t

 * Correct those two wrong loops, memory_map.nr_map - nr
   when we're trying to revise low/high memory e820 entries.

 * Improve code comments and the patch head description

 * Add one check if highmem is just populated by hvmloader itself

 v5 ~ v7:

 * Nothing is changed.

 v4:

 * Rename local variable, low_mem_pgend, to low_mem_end.

 * Improve some code comments

 * Adjust highmem after lowmem is changed.


  tools/firmware/hvmloader/e820.c | 92 
 +
  1 file changed, 83 insertions(+), 9 deletions(-)

 diff --git a/tools/firmware/hvmloader/e820.c b/tools/firmware/hvmloader/e820.c
 index b72baa5..aa678a7 100644
 --- a/tools/firmware/hvmloader/e820.c
 +++ b/tools/firmware/hvmloader/e820.c
 @@ -108,7 +108,9 @@ int build_e820_table(struct e820entry *e820,
   unsigned int lowmem_reserved_base,
   unsigned int bios_image_base)
  {
 -unsigned int nr = 0;
 +unsigned int nr = 0, i, j;
 +uint64_t add_high_mem = 0;
 +uint32_t low_mem_end = hvm_info-low_mem_pgend  PAGE_SHIFT;

  if ( !lowmem_reserved_base )
  lowmem_reserved_base = 0xA;
 @@ -152,13 +154,6 @@ int build_e820_table(struct e820entry *e820,
  e820[nr].type = E820_RESERVED;
  nr++;

 -/* Low RAM goes here. Reserve space for special pages. */
 -BUG_ON((hvm_info-low_mem_pgend  PAGE_SHIFT)  (2u  20));
 -e820[nr].addr = 0x10;
 -e820[nr].size = (hvm_info-low_mem_pgend  PAGE_SHIFT) - e820[nr].addr;
 -e820[nr].type = E820_RAM;
 -nr++;
 -
  /*
   * Explicitly reserve space for special pages.
   * This space starts at RESERVED_MEMBASE an extends to cover various
 @@ -194,9 +189,73 @@ int build_e820_table(struct e820entry *e820,
  nr++;
  }

 +/*
 + * Construct E820 table according to recorded memory map.
 + *
 + * The memory map created by toolstack may include,
 + *
 + * #1. Low memory region
 + *
 + * Low RAM starts at least from 1M to make sure all standard regions
 + * of the PC memory map, like BIOS, VGA memory-mapped I/O and vgabios,
 + * have enough space.
 + *
 + * #2. Reserved regions if they exist
 + *
 + * #3. High memory region if it exists
 + */
 +for ( i = 0; i  memory_map.nr_map; i++ )
 +{
 +e820[nr] = memory_map.map[i];
 +nr++;
 +}
 +
 +/* Low RAM goes here. Reserve space for special pages. */
 +BUG_ON(low_mem_end  (2u  20));

 -if ( hvm_info-high_mem_pgend )
 +/*
 + * Its possible to relocate RAM to allocate sufficient MMIO previously
 + * so low_mem_pgend would be changed over there. And here memory_map[]
 + * records the original low/high memory, so if low_mem_end is less than
 + * the original we need to revise low/high memory range in e820.
 + */
 +for ( i = 0; i  nr; i++ )
  {
 +uint64_t end = e820[i].addr + e820[i].size;
 +if ( e820[i].type == E820_RAM 
 + low_mem_end  e820[i].addr  low_mem_end  end )
 +{
 +add_high_mem = end - low_mem_end;
 +e820[i].size = low_mem_end - e820[i].addr;
 +}
 +}
 +
 +/*
 + * And then we also need to adjust highmem.
 + */
 +if ( add_high_mem )
 +{
 +for ( i = 0; i  nr; i++ )
 +{
 +if ( e820[i].type == E820_RAM 
 + e820[i].addr == (1ull  32))
 +{
 +e820[i].size += add_high_mem;
 +add_high_mem = 0;
 +break;
 +}
 +}
 +}
 +
 +/* Or this is just populated by hvmloader itself. */

This should probably say something like:

If there was no highmem region, we need to create one.

 +if ( add_high_mem )
 +{
 +/*
 + * hvmloader should always update hvm_info-high_mem_pgend
 + * when it relocates RAM anywhere.
 + */
 +BUG_ON( !hvm_info-high_mem_pgend );
 +
  e820[nr].addr = ((uint64_t)1  32);
  e820[nr].size =
  ((uint64_t)hvm_info-high_mem_pgend  PAGE_SHIFT) - 
 e820[nr].addr;

In theory add_high_mem and