From a678e26cbe89f7a27cbce794c2c2784571ee9d21 Mon Sep 17 00:00:00 2001 From: Michael Roth Date: Sun, 26 May 2013 22:20:58 -0500 Subject: qapi: pad GenericList value fields to 64 bits With the introduction of native list types, we now have types such as int64List where the 'value' field is not a pointer, but the actual 64-bit value. On 32-bit architectures, this can lead to situations where 'next' field offset in GenericList does not correspond to the 'next' field in the types that we cast to GenericList when using the visit_next_list() interface, causing issues when we attempt to traverse linked list structures of these types. To fix this, pad the 'value' field of GenericList and other schema-defined/native *List types out to 64-bits. This is less memory-efficient for 32-bit architectures, but allows us to continue to rely on list-handling interfaces that target GenericList to simply visitor implementations. In the future we can improve efficiency by defaulting to using native C array backends to handle list of non-pointer types, which would be more memory efficient in itself and allow us to roll back this change. Signed-off-by: Michael Roth Signed-off-by: Luiz Capitulino --- include/qapi/visitor.h | 5 ++++- scripts/qapi-types.py | 10 ++++++++-- tests/test-qmp-output-visitor.c | 5 ++++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h index 1fef18c08f..28c21d8338 100644 --- a/include/qapi/visitor.h +++ b/include/qapi/visitor.h @@ -18,7 +18,10 @@ typedef struct GenericList { - void *value; + union { + void *value; + uint64_t padding; + }; struct GenericList *next; } GenericList; diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index fd42d71da1..ddcfed9f4b 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -22,7 +22,10 @@ def generate_fwd_struct(name, members, builtin_type=False): typedef struct %(name)sList { - %(type)s value; + union { + %(type)s value; + uint64_t padding; + }; struct %(name)sList *next; } %(name)sList; ''', @@ -35,7 +38,10 @@ typedef struct %(name)s %(name)s; typedef struct %(name)sList { - %(name)s *value; + union { + %(name)s *value; + uint64_t padding; + }; struct %(name)sList *next; } %(name)sList; ''', diff --git a/tests/test-qmp-output-visitor.c b/tests/test-qmp-output-visitor.c index 0942a41875..b2fa9a74f6 100644 --- a/tests/test-qmp-output-visitor.c +++ b/tests/test-qmp-output-visitor.c @@ -295,7 +295,10 @@ static void test_visitor_out_struct_errors(TestOutputVisitorData *data, typedef struct TestStructList { - TestStruct *value; + union { + TestStruct *value; + uint64_t padding; + }; struct TestStructList *next; } TestStructList; -- cgit v1.2.1 From fbc2ed9518efcdcdcbf0adb9539c17a65addd20a Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Tue, 28 May 2013 14:19:22 -0400 Subject: target-i386: fix abort on bad PML4E/PDPTE/PDE/PTE addresses The code used to walk IA-32e page-tables, and possibly PAE page-tables, uses the bit mask ~0xfff to get the next PML4E/PDPTE/PDE/PTE address. However, as we use a uint64_t to store the resulting address, that mask gets expanded to 0xfffffffffffff000 which not only ends up selecting reserved bits but also selects the XD bit (execute-disable) which happens to be enabled by Windows 8, causing qemu_get_ram_ptr() to abort. This commit fixes that problem by replacing ~0xfff by a correct mask that only selects the address bit range (ie. bits 51:12). Signed-off-by: Luiz Capitulino Reviewed-by: Laszlo Ersek --- target-i386/arch_memory_mapping.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/target-i386/arch_memory_mapping.c b/target-i386/arch_memory_mapping.c index 844893f44d..24884bd482 100644 --- a/target-i386/arch_memory_mapping.c +++ b/target-i386/arch_memory_mapping.c @@ -75,6 +75,8 @@ static void walk_pte2(MemoryMappingList *list, } /* PAE Paging or IA-32e Paging */ +#define PLM4_ADDR_MASK 0xffffffffff000 /* selects bits 51:12 */ + static void walk_pde(MemoryMappingList *list, hwaddr pde_start_addr, int32_t a20_mask, target_ulong start_line_addr) { @@ -105,7 +107,7 @@ static void walk_pde(MemoryMappingList *list, hwaddr pde_start_addr, continue; } - pte_start_addr = (pde & ~0xfff) & a20_mask; + pte_start_addr = (pde & PLM4_ADDR_MASK) & a20_mask; walk_pte(list, pte_start_addr, a20_mask, line_addr); } } @@ -208,7 +210,7 @@ static void walk_pdpe(MemoryMappingList *list, continue; } - pde_start_addr = (pdpe & ~0xfff) & a20_mask; + pde_start_addr = (pdpe & PLM4_ADDR_MASK) & a20_mask; walk_pde(list, pde_start_addr, a20_mask, line_addr); } } @@ -231,7 +233,7 @@ static void walk_pml4e(MemoryMappingList *list, } line_addr = ((i & 0x1ffULL) << 39) | (0xffffULL << 48); - pdpe_start_addr = (pml4e & ~0xfff) & a20_mask; + pdpe_start_addr = (pml4e & PLM4_ADDR_MASK) & a20_mask; walk_pdpe(list, pdpe_start_addr, a20_mask, line_addr); } } @@ -249,7 +251,7 @@ int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env) if (env->hflags & HF_LMA_MASK) { hwaddr pml4e_addr; - pml4e_addr = (env->cr[3] & ~0xfff) & env->a20_mask; + pml4e_addr = (env->cr[3] & PLM4_ADDR_MASK) & env->a20_mask; walk_pml4e(list, pml4e_addr, env->a20_mask); } else #endif -- cgit v1.2.1 From bff63471ced94e3a6de76b1a7375a875178d6cdc Mon Sep 17 00:00:00 2001 From: Qiao Nuohan Date: Thu, 30 May 2013 17:07:54 +0200 Subject: target-i386: Fix mask of pte index in memory mapping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Function walk_pte() needs pte index to calculate virtual address. However, pte index of PAE paging or IA-32e paging is 9 bit, so the mask should be 0x1ff. Signed-off-by: Qiao Nuohan Reviewed-by: Jesse Larrew Signed-off-by: Andreas Färber Signed-off-by: Luiz Capitulino --- target-i386/arch_memory_mapping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-i386/arch_memory_mapping.c b/target-i386/arch_memory_mapping.c index 24884bd482..5096fbdf44 100644 --- a/target-i386/arch_memory_mapping.c +++ b/target-i386/arch_memory_mapping.c @@ -38,7 +38,7 @@ static void walk_pte(MemoryMappingList *list, hwaddr pte_start_addr, continue; } - start_vaddr = start_line_addr | ((i & 0x1fff) << 12); + start_vaddr = start_line_addr | ((i & 0x1ff) << 12); memory_mapping_list_add_merge_sorted(list, start_paddr, start_vaddr, 1 << 12); } -- cgit v1.2.1