From: Vijaya Kumar K <vijaya.ku...@caviumnetworks.com> Replace TARGET_PAGE_BITS with arm_target_page_size function in order to fetch page size at run-time.
Introduced MachineClass callback to compute target page size at the early boot before memory initialization. This callback is currently implemented for ARM platforms. Based on cpu_model, the page size is updated in target_page_bits which is defined as TARGET_PAGE_BITS. Signed-off-by: Vijaya Kumar K <vija...@cavium.com> --- hw/arm/virt.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ include/hw/boards.h | 1 + target-arm/cpu.h | 12 +++++++----- vl.c | 7 +++++++ 4 files changed, 63 insertions(+), 5 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 73113cf..37aab33 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -90,6 +90,12 @@ typedef struct { int32_t gic_version; } VirtMachineState; +/* + * Holds TARGET_AARCH_64_PAGE_BITS or TARGET_ARM_PAGE_BITS + * based on the the cpu type emulated at runtime. + */ +static uint32_t target_page_bits; + #define TYPE_VIRT_MACHINE MACHINE_TYPE_NAME("virt") #define VIRT_MACHINE(obj) \ OBJECT_CHECK(VirtMachineState, (obj), TYPE_VIRT_MACHINE) @@ -1099,6 +1105,47 @@ void virt_guest_info_machine_done(Notifier *notifier, void *data) virt_build_smbios(&guest_info_state->info); } +static void machvirt_update_target_page_size(const char *cpu_model) +{ + char **cpustr; + ObjectClass *oc, *parent; + const char *parent_type; + /* Set to default page size */ + uint32_t page_bits = TARGET_ARM_PAGE_BITS; + + cpustr = g_strsplit(cpu_model, ",", 2); + if (!strcmp(cpustr[0], "host")) { +#ifdef __aarch64__ + page_bits = TARGET_AARCH64_PAGE_BITS; +#else + page_bits = TARGET_ARM_PAGE_BITS; +#endif + goto out; + } + + oc = cpu_class_by_name(TYPE_ARM_CPU, cpustr[0]); + if (!oc) { + oc = cpu_class_by_name(TYPE_AARCH64_CPU, cpustr[0]); + if (!oc) + goto out; + } + + parent = object_class_get_parent(oc); + if (!parent) + goto out; + + parent_type = object_class_get_name(parent); + if (!strcmp(parent_type, TYPE_AARCH64_CPU)) + page_bits = TARGET_AARCH64_PAGE_BITS; +out: + target_page_bits = page_bits; +} + +uint32_t arm_get_target_page_bits(void) +{ + return target_page_bits; +} + static void machvirt_init(MachineState *machine) { VirtMachineState *vms = VIRT_MACHINE(machine); @@ -1376,6 +1423,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) mc->block_default_type = IF_VIRTIO; mc->no_cdrom = 1; mc->pci_allow_0_address = true; + mc->update_target_page_size = machvirt_update_target_page_size; } static const TypeInfo virt_machine_info = { diff --git a/include/hw/boards.h b/include/hw/boards.h index d268bd0..1e8abb6 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -124,6 +124,7 @@ struct MachineClass { DeviceState *dev); unsigned (*cpu_index_to_socket_id)(unsigned cpu_index); CPUArchIdList *(*possible_cpu_arch_ids)(MachineState *machine); + void (*update_target_page_size)(const char *cpu_model); }; /** diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 17d8051..f593620 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -1743,14 +1743,16 @@ bool write_cpustate_to_list(ARMCPU *cpu); #define ARM_CPUID_TI915T 0x54029152 #define ARM_CPUID_TI925T 0x54029252 -#if defined(CONFIG_USER_ONLY) -#define TARGET_PAGE_BITS 12 -#else +uint32_t arm_get_target_page_bits(void); +/* + * Minimum page size for aarch64 is 4K + */ +#define TARGET_AARCH64_PAGE_BITS 12 /* The ARM MMU allows 1k pages. */ /* ??? Linux doesn't actually use these, and they're deprecated in recent architecture revisions. Maybe a configure option to disable them. */ -#define TARGET_PAGE_BITS 10 -#endif +#define TARGET_ARM_PAGE_BITS 10 +#define TARGET_PAGE_BITS arm_get_target_page_bits() #if defined(TARGET_AARCH64) # define TARGET_PHYS_ADDR_SPACE_BITS 48 diff --git a/vl.c b/vl.c index b6da265..a317cf1 100644 --- a/vl.c +++ b/vl.c @@ -4045,6 +4045,13 @@ int main(int argc, char **argv, char **envp) object_property_add_child(object_get_root(), "machine", OBJECT(current_machine), &error_abort); + /* + * Compute target page size dynamically if arch supports + * multiple page sizes. Ex: ARM + */ + if (machine_class->update_target_page_size) + machine_class->update_target_page_size(cpu_model); + init_l1_page_table_param(); cpu_exec_init_all(); -- 1.7.9.5