Merge branch 'ppc-next' of git://repo.or.cz/qemu/agraf
* 'ppc-next' of git://repo.or.cz/qemu/agraf: PPC: Add description for the Freescale e500mc core. pseries: Check for duplicate addresses on the spapr-vio bus pseries: Populate "/chosen/linux,stdout-path" in the FDT pseries: Add a routine to find a stable "default" vty and use it pseries: Emit device tree nodes in reg order pseries: FDT NUMA extensions to support multi-node guests pseries: Remove hcalls callback kvm-ppc: halt secondary cpus when guest reset console: Fix segfault on screendump without VGA adapter PPC: monitor: add ability to dump SLB entries
This commit is contained in:
		
						commit
						15f43ccda1
					
				@ -186,7 +186,9 @@ void vga_hw_screen_dump(const char *filename)
 | 
				
			|||||||
        consoles[0]->hw_screen_dump(consoles[0]->hw, filename);
 | 
					        consoles[0]->hw_screen_dump(consoles[0]->hw, filename);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (previous_active_console) {
 | 
				
			||||||
        console_select(previous_active_console->index);
 | 
					        console_select(previous_active_console->index);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void vga_hw_text_update(console_ch_t *chardata)
 | 
					void vga_hw_text_update(console_ch_t *chardata)
 | 
				
			||||||
 | 
				
			|||||||
@ -112,6 +112,7 @@ static void spin_kick(void *data)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    env->halted = 0;
 | 
					    env->halted = 0;
 | 
				
			||||||
    env->exception_index = -1;
 | 
					    env->exception_index = -1;
 | 
				
			||||||
 | 
					    env->stopped = 0;
 | 
				
			||||||
    qemu_cpu_kick(env);
 | 
					    qemu_cpu_kick(env);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										114
									
								
								hw/spapr.c
									
									
									
									
									
								
							
							
						
						
									
										114
									
								
								hw/spapr.c
									
									
									
									
									
								
							@ -97,6 +97,44 @@ qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num)
 | 
				
			|||||||
    return qirq;
 | 
					    return qirq;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int spapr_set_associativity(void *fdt, sPAPREnvironment *spapr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int ret = 0, offset;
 | 
				
			||||||
 | 
					    CPUState *env;
 | 
				
			||||||
 | 
					    char cpu_model[32];
 | 
				
			||||||
 | 
					    int smt = kvmppc_smt_threads();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert(spapr->cpu_model);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (env = first_cpu; env != NULL; env = env->next_cpu) {
 | 
				
			||||||
 | 
					        uint32_t associativity[] = {cpu_to_be32(0x5),
 | 
				
			||||||
 | 
					                                    cpu_to_be32(0x0),
 | 
				
			||||||
 | 
					                                    cpu_to_be32(0x0),
 | 
				
			||||||
 | 
					                                    cpu_to_be32(0x0),
 | 
				
			||||||
 | 
					                                    cpu_to_be32(env->numa_node),
 | 
				
			||||||
 | 
					                                    cpu_to_be32(env->cpu_index)};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ((env->cpu_index % smt) != 0) {
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        snprintf(cpu_model, 32, "/cpus/%s@%x", spapr->cpu_model,
 | 
				
			||||||
 | 
					                 env->cpu_index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        offset = fdt_path_offset(fdt, cpu_model);
 | 
				
			||||||
 | 
					        if (offset < 0) {
 | 
				
			||||||
 | 
					            return offset;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ret = fdt_setprop(fdt, offset, "ibm,associativity", associativity,
 | 
				
			||||||
 | 
					                          sizeof(associativity));
 | 
				
			||||||
 | 
					        if (ret < 0) {
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void *spapr_create_fdt_skel(const char *cpu_model,
 | 
					static void *spapr_create_fdt_skel(const char *cpu_model,
 | 
				
			||||||
                                   target_phys_addr_t rma_size,
 | 
					                                   target_phys_addr_t rma_size,
 | 
				
			||||||
                                   target_phys_addr_t initrd_base,
 | 
					                                   target_phys_addr_t initrd_base,
 | 
				
			||||||
@ -107,9 +145,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    void *fdt;
 | 
					    void *fdt;
 | 
				
			||||||
    CPUState *env;
 | 
					    CPUState *env;
 | 
				
			||||||
    uint64_t mem_reg_property_rma[] = { 0, cpu_to_be64(rma_size) };
 | 
					    uint64_t mem_reg_property[2];
 | 
				
			||||||
    uint64_t mem_reg_property_nonrma[] = { cpu_to_be64(rma_size),
 | 
					 | 
				
			||||||
                                           cpu_to_be64(ram_size - rma_size) };
 | 
					 | 
				
			||||||
    uint32_t start_prop = cpu_to_be32(initrd_base);
 | 
					    uint32_t start_prop = cpu_to_be32(initrd_base);
 | 
				
			||||||
    uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
 | 
					    uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
 | 
				
			||||||
    uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)};
 | 
					    uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)};
 | 
				
			||||||
@ -119,6 +155,13 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
 | 
				
			|||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
    char *modelname;
 | 
					    char *modelname;
 | 
				
			||||||
    int smt = kvmppc_smt_threads();
 | 
					    int smt = kvmppc_smt_threads();
 | 
				
			||||||
 | 
					    unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80};
 | 
				
			||||||
 | 
					    uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
 | 
				
			||||||
 | 
					    uint32_t associativity[] = {cpu_to_be32(0x4), cpu_to_be32(0x0),
 | 
				
			||||||
 | 
					                                cpu_to_be32(0x0), cpu_to_be32(0x0),
 | 
				
			||||||
 | 
					                                cpu_to_be32(0x0)};
 | 
				
			||||||
 | 
					    char mem_name[32];
 | 
				
			||||||
 | 
					    target_phys_addr_t node0_size, mem_start;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define _FDT(exp) \
 | 
					#define _FDT(exp) \
 | 
				
			||||||
    do { \
 | 
					    do { \
 | 
				
			||||||
@ -146,6 +189,9 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
 | 
				
			|||||||
    /* /chosen */
 | 
					    /* /chosen */
 | 
				
			||||||
    _FDT((fdt_begin_node(fdt, "chosen")));
 | 
					    _FDT((fdt_begin_node(fdt, "chosen")));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Set Form1_affinity */
 | 
				
			||||||
 | 
					    _FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5))));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _FDT((fdt_property_string(fdt, "bootargs", kernel_cmdline)));
 | 
					    _FDT((fdt_property_string(fdt, "bootargs", kernel_cmdline)));
 | 
				
			||||||
    _FDT((fdt_property(fdt, "linux,initrd-start",
 | 
					    _FDT((fdt_property(fdt, "linux,initrd-start",
 | 
				
			||||||
                       &start_prop, sizeof(start_prop))));
 | 
					                       &start_prop, sizeof(start_prop))));
 | 
				
			||||||
@ -164,24 +210,54 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
 | 
				
			|||||||
    _FDT((fdt_end_node(fdt)));
 | 
					    _FDT((fdt_end_node(fdt)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* memory node(s) */
 | 
					    /* memory node(s) */
 | 
				
			||||||
    _FDT((fdt_begin_node(fdt, "memory@0")));
 | 
					    node0_size = (nb_numa_nodes > 1) ? node_mem[0] : ram_size;
 | 
				
			||||||
 | 
					    if (rma_size > node0_size) {
 | 
				
			||||||
 | 
					        rma_size = node0_size;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* RMA */
 | 
				
			||||||
 | 
					    mem_reg_property[0] = 0;
 | 
				
			||||||
 | 
					    mem_reg_property[1] = cpu_to_be64(rma_size);
 | 
				
			||||||
 | 
					    _FDT((fdt_begin_node(fdt, "memory@0")));
 | 
				
			||||||
    _FDT((fdt_property_string(fdt, "device_type", "memory")));
 | 
					    _FDT((fdt_property_string(fdt, "device_type", "memory")));
 | 
				
			||||||
    _FDT((fdt_property(fdt, "reg", mem_reg_property_rma,
 | 
					    _FDT((fdt_property(fdt, "reg", mem_reg_property,
 | 
				
			||||||
                       sizeof(mem_reg_property_rma))));
 | 
					        sizeof(mem_reg_property))));
 | 
				
			||||||
 | 
					    _FDT((fdt_property(fdt, "ibm,associativity", associativity,
 | 
				
			||||||
 | 
					        sizeof(associativity))));
 | 
				
			||||||
    _FDT((fdt_end_node(fdt)));
 | 
					    _FDT((fdt_end_node(fdt)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (ram_size > rma_size) {
 | 
					    /* RAM: Node 0 */
 | 
				
			||||||
        char mem_name[32];
 | 
					    if (node0_size > rma_size) {
 | 
				
			||||||
 | 
					        mem_reg_property[0] = cpu_to_be64(rma_size);
 | 
				
			||||||
 | 
					        mem_reg_property[1] = cpu_to_be64(node0_size - rma_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        sprintf(mem_name, "memory@%" PRIx64, (uint64_t)rma_size);
 | 
					        sprintf(mem_name, "memory@" TARGET_FMT_lx, rma_size);
 | 
				
			||||||
        _FDT((fdt_begin_node(fdt, mem_name)));
 | 
					        _FDT((fdt_begin_node(fdt, mem_name)));
 | 
				
			||||||
        _FDT((fdt_property_string(fdt, "device_type", "memory")));
 | 
					        _FDT((fdt_property_string(fdt, "device_type", "memory")));
 | 
				
			||||||
        _FDT((fdt_property(fdt, "reg", mem_reg_property_nonrma,
 | 
					        _FDT((fdt_property(fdt, "reg", mem_reg_property,
 | 
				
			||||||
                           sizeof(mem_reg_property_nonrma))));
 | 
					                           sizeof(mem_reg_property))));
 | 
				
			||||||
 | 
					        _FDT((fdt_property(fdt, "ibm,associativity", associativity,
 | 
				
			||||||
 | 
					                           sizeof(associativity))));
 | 
				
			||||||
        _FDT((fdt_end_node(fdt)));
 | 
					        _FDT((fdt_end_node(fdt)));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* RAM: Node 1 and beyond */
 | 
				
			||||||
 | 
					    mem_start = node0_size;
 | 
				
			||||||
 | 
					    for (i = 1; i < nb_numa_nodes; i++) {
 | 
				
			||||||
 | 
					        mem_reg_property[0] = cpu_to_be64(mem_start);
 | 
				
			||||||
 | 
					        mem_reg_property[1] = cpu_to_be64(node_mem[i]);
 | 
				
			||||||
 | 
					        associativity[3] = associativity[4] = cpu_to_be32(i);
 | 
				
			||||||
 | 
					        sprintf(mem_name, "memory@" TARGET_FMT_lx, mem_start);
 | 
				
			||||||
 | 
					        _FDT((fdt_begin_node(fdt, mem_name)));
 | 
				
			||||||
 | 
					        _FDT((fdt_property_string(fdt, "device_type", "memory")));
 | 
				
			||||||
 | 
					        _FDT((fdt_property(fdt, "reg", mem_reg_property,
 | 
				
			||||||
 | 
					            sizeof(mem_reg_property))));
 | 
				
			||||||
 | 
					        _FDT((fdt_property(fdt, "ibm,associativity", associativity,
 | 
				
			||||||
 | 
					            sizeof(associativity))));
 | 
				
			||||||
 | 
					        _FDT((fdt_end_node(fdt)));
 | 
				
			||||||
 | 
					        mem_start += node_mem[i];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* cpus */
 | 
					    /* cpus */
 | 
				
			||||||
    _FDT((fdt_begin_node(fdt, "cpus")));
 | 
					    _FDT((fdt_begin_node(fdt, "cpus")));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -194,6 +270,9 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
 | 
				
			|||||||
        modelname[i] = toupper(modelname[i]);
 | 
					        modelname[i] = toupper(modelname[i]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* This is needed during FDT finalization */
 | 
				
			||||||
 | 
					    spapr->cpu_model = g_strdup(modelname);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (env = first_cpu; env != NULL; env = env->next_cpu) {
 | 
					    for (env = first_cpu; env != NULL; env = env->next_cpu) {
 | 
				
			||||||
        int index = env->cpu_index;
 | 
					        int index = env->cpu_index;
 | 
				
			||||||
        uint32_t servers_prop[smp_threads];
 | 
					        uint32_t servers_prop[smp_threads];
 | 
				
			||||||
@ -280,6 +359,9 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
 | 
				
			|||||||
    _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas_prop,
 | 
					    _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas_prop,
 | 
				
			||||||
                       sizeof(hypertas_prop))));
 | 
					                       sizeof(hypertas_prop))));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _FDT((fdt_property(fdt, "ibm,associativity-reference-points",
 | 
				
			||||||
 | 
					        refpoints, sizeof(refpoints))));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _FDT((fdt_end_node(fdt)));
 | 
					    _FDT((fdt_end_node(fdt)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* interrupt controller */
 | 
					    /* interrupt controller */
 | 
				
			||||||
@ -351,6 +433,16 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr,
 | 
				
			|||||||
        fprintf(stderr, "Couldn't set up RTAS device tree properties\n");
 | 
					        fprintf(stderr, "Couldn't set up RTAS device tree properties\n");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Advertise NUMA via ibm,associativity */
 | 
				
			||||||
 | 
					    if (nb_numa_nodes > 1) {
 | 
				
			||||||
 | 
					        ret = spapr_set_associativity(fdt, spapr);
 | 
				
			||||||
 | 
					        if (ret < 0) {
 | 
				
			||||||
 | 
					            fprintf(stderr, "Couldn't set up NUMA device tree properties\n");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    spapr_populate_chosen_stdout(fdt, spapr->vio_bus);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _FDT((fdt_pack(fdt)));
 | 
					    _FDT((fdt_pack(fdt)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
 | 
					    cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
 | 
				
			||||||
 | 
				
			|||||||
@ -21,6 +21,7 @@ typedef struct sPAPREnvironment {
 | 
				
			|||||||
    target_ulong entry_point;
 | 
					    target_ulong entry_point;
 | 
				
			||||||
    int next_irq;
 | 
					    int next_irq;
 | 
				
			||||||
    int rtc_offset;
 | 
					    int rtc_offset;
 | 
				
			||||||
 | 
					    char *cpu_model;
 | 
				
			||||||
} sPAPREnvironment;
 | 
					} sPAPREnvironment;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define H_SUCCESS         0
 | 
					#define H_SUCCESS         0
 | 
				
			||||||
 | 
				
			|||||||
@ -474,16 +474,6 @@ static target_ulong h_multicast_ctrl(CPUState *env, sPAPREnvironment *spapr,
 | 
				
			|||||||
    return H_SUCCESS;
 | 
					    return H_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void vlan_hcalls(VIOsPAPRBus *bus)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    spapr_register_hypercall(H_REGISTER_LOGICAL_LAN, h_register_logical_lan);
 | 
					 | 
				
			||||||
    spapr_register_hypercall(H_FREE_LOGICAL_LAN, h_free_logical_lan);
 | 
					 | 
				
			||||||
    spapr_register_hypercall(H_SEND_LOGICAL_LAN, h_send_logical_lan);
 | 
					 | 
				
			||||||
    spapr_register_hypercall(H_ADD_LOGICAL_LAN_BUFFER,
 | 
					 | 
				
			||||||
                             h_add_logical_lan_buffer);
 | 
					 | 
				
			||||||
    spapr_register_hypercall(H_MULTICAST_CTRL, h_multicast_ctrl);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static VIOsPAPRDeviceInfo spapr_vlan = {
 | 
					static VIOsPAPRDeviceInfo spapr_vlan = {
 | 
				
			||||||
    .init = spapr_vlan_init,
 | 
					    .init = spapr_vlan_init,
 | 
				
			||||||
    .devnode = spapr_vlan_devnode,
 | 
					    .devnode = spapr_vlan_devnode,
 | 
				
			||||||
@ -491,7 +481,6 @@ static VIOsPAPRDeviceInfo spapr_vlan = {
 | 
				
			|||||||
    .dt_type = "network",
 | 
					    .dt_type = "network",
 | 
				
			||||||
    .dt_compatible = "IBM,l-lan",
 | 
					    .dt_compatible = "IBM,l-lan",
 | 
				
			||||||
    .signal_mask = 0x1,
 | 
					    .signal_mask = 0x1,
 | 
				
			||||||
    .hcalls = vlan_hcalls,
 | 
					 | 
				
			||||||
    .qdev.name = "spapr-vlan",
 | 
					    .qdev.name = "spapr-vlan",
 | 
				
			||||||
    .qdev.size = sizeof(VIOsPAPRVLANDevice),
 | 
					    .qdev.size = sizeof(VIOsPAPRVLANDevice),
 | 
				
			||||||
    .qdev.props = (Property[]) {
 | 
					    .qdev.props = (Property[]) {
 | 
				
			||||||
@ -504,5 +493,11 @@ static VIOsPAPRDeviceInfo spapr_vlan = {
 | 
				
			|||||||
static void spapr_vlan_register(void)
 | 
					static void spapr_vlan_register(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    spapr_vio_bus_register_withprop(&spapr_vlan);
 | 
					    spapr_vio_bus_register_withprop(&spapr_vlan);
 | 
				
			||||||
 | 
					    spapr_register_hypercall(H_REGISTER_LOGICAL_LAN, h_register_logical_lan);
 | 
				
			||||||
 | 
					    spapr_register_hypercall(H_FREE_LOGICAL_LAN, h_free_logical_lan);
 | 
				
			||||||
 | 
					    spapr_register_hypercall(H_SEND_LOGICAL_LAN, h_send_logical_lan);
 | 
				
			||||||
 | 
					    spapr_register_hypercall(H_ADD_LOGICAL_LAN_BUFFER,
 | 
				
			||||||
 | 
					                             h_add_logical_lan_buffer);
 | 
				
			||||||
 | 
					    spapr_register_hypercall(H_MULTICAST_CTRL, h_multicast_ctrl);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
device_init(spapr_vlan_register);
 | 
					device_init(spapr_vlan_register);
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										127
									
								
								hw/spapr_vio.c
									
									
									
									
									
								
							
							
						
						
									
										127
									
								
								hw/spapr_vio.c
									
									
									
									
									
								
							@ -621,11 +621,43 @@ static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token,
 | 
				
			|||||||
    rtas_st(rets, 0, 0);
 | 
					    rtas_st(rets, 0, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int spapr_vio_check_reg(VIOsPAPRDevice *sdev, VIOsPAPRDeviceInfo *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VIOsPAPRDevice *other_sdev;
 | 
				
			||||||
 | 
					    DeviceState *qdev;
 | 
				
			||||||
 | 
					    VIOsPAPRBus *sbus;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sbus = DO_UPCAST(VIOsPAPRBus, bus, sdev->qdev.parent_bus);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * Check two device aren't given clashing addresses by the user (or some
 | 
				
			||||||
 | 
					     * other mechanism). We have to open code this because we have to check
 | 
				
			||||||
 | 
					     * for matches with devices other than us.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    QTAILQ_FOREACH(qdev, &sbus->bus.children, sibling) {
 | 
				
			||||||
 | 
					        other_sdev = DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (other_sdev != sdev && other_sdev->reg == sdev->reg) {
 | 
				
			||||||
 | 
					            fprintf(stderr, "vio: %s and %s devices conflict at address %#x\n",
 | 
				
			||||||
 | 
					                    info->qdev.name, other_sdev->qdev.info->name, sdev->reg);
 | 
				
			||||||
 | 
					            return -EEXIST;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int spapr_vio_busdev_init(DeviceState *qdev, DeviceInfo *qinfo)
 | 
					static int spapr_vio_busdev_init(DeviceState *qdev, DeviceInfo *qinfo)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo;
 | 
					    VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo;
 | 
				
			||||||
    VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
 | 
					    VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
 | 
				
			||||||
    char *id;
 | 
					    char *id;
 | 
				
			||||||
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ret = spapr_vio_check_reg(dev, info);
 | 
				
			||||||
 | 
					    if (ret) {
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Don't overwrite ids assigned on the command line */
 | 
					    /* Don't overwrite ids assigned on the command line */
 | 
				
			||||||
    if (!dev->qdev.id) {
 | 
					    if (!dev->qdev.id) {
 | 
				
			||||||
@ -684,7 +716,6 @@ VIOsPAPRBus *spapr_vio_bus_init(void)
 | 
				
			|||||||
    VIOsPAPRBus *bus;
 | 
					    VIOsPAPRBus *bus;
 | 
				
			||||||
    BusState *qbus;
 | 
					    BusState *qbus;
 | 
				
			||||||
    DeviceState *dev;
 | 
					    DeviceState *dev;
 | 
				
			||||||
    DeviceInfo *qinfo;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Create bridge device */
 | 
					    /* Create bridge device */
 | 
				
			||||||
    dev = qdev_create(NULL, "spapr-vio-bridge");
 | 
					    dev = qdev_create(NULL, "spapr-vio-bridge");
 | 
				
			||||||
@ -711,18 +742,6 @@ VIOsPAPRBus *spapr_vio_bus_init(void)
 | 
				
			|||||||
    spapr_rtas_register("ibm,set-tce-bypass", rtas_set_tce_bypass);
 | 
					    spapr_rtas_register("ibm,set-tce-bypass", rtas_set_tce_bypass);
 | 
				
			||||||
    spapr_rtas_register("quiesce", rtas_quiesce);
 | 
					    spapr_rtas_register("quiesce", rtas_quiesce);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (qinfo = device_info_list; qinfo; qinfo = qinfo->next) {
 | 
					 | 
				
			||||||
        VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (qinfo->bus_info != &spapr_vio_bus_info) {
 | 
					 | 
				
			||||||
            continue;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (info->hcalls) {
 | 
					 | 
				
			||||||
            info->hcalls(bus);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return bus;
 | 
					    return bus;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -749,21 +768,95 @@ static void spapr_vio_register_devices(void)
 | 
				
			|||||||
device_init(spapr_vio_register_devices)
 | 
					device_init(spapr_vio_register_devices)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_FDT
 | 
					#ifdef CONFIG_FDT
 | 
				
			||||||
 | 
					static int compare_reg(const void *p1, const void *p2)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VIOsPAPRDevice const *dev1, *dev2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dev1 = (VIOsPAPRDevice *)*(DeviceState **)p1;
 | 
				
			||||||
 | 
					    dev2 = (VIOsPAPRDevice *)*(DeviceState **)p2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (dev1->reg < dev2->reg) {
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (dev1->reg == dev2->reg) {
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* dev1->reg > dev2->reg */
 | 
				
			||||||
 | 
					    return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt)
 | 
					int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    DeviceState *qdev;
 | 
					    DeviceState *qdev, **qdevs;
 | 
				
			||||||
    int ret = 0;
 | 
					    int i, num, ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Count qdevs on the bus list */
 | 
				
			||||||
 | 
					    num = 0;
 | 
				
			||||||
    QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
 | 
					    QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
 | 
				
			||||||
        VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
 | 
					        num++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Copy out into an array of pointers */
 | 
				
			||||||
 | 
					    qdevs = g_malloc(sizeof(qdev) * num);
 | 
				
			||||||
 | 
					    num = 0;
 | 
				
			||||||
 | 
					    QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
 | 
				
			||||||
 | 
					        qdevs[num++] = qdev;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Sort the array */
 | 
				
			||||||
 | 
					    qsort(qdevs, num, sizeof(qdev), compare_reg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Hack alert. Give the devices to libfdt in reverse order, we happen
 | 
				
			||||||
 | 
					     * to know that will mean they are in forward order in the tree. */
 | 
				
			||||||
 | 
					    for (i = num - 1; i >= 0; i--) {
 | 
				
			||||||
 | 
					        VIOsPAPRDevice *dev = (VIOsPAPRDevice *)(qdevs[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ret = vio_make_devnode(dev, fdt);
 | 
					        ret = vio_make_devnode(dev, fdt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (ret < 0) {
 | 
					        if (ret < 0) {
 | 
				
			||||||
            return ret;
 | 
					            goto out;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ret = 0;
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
					    free(qdevs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VIOsPAPRDevice *dev;
 | 
				
			||||||
 | 
					    char *name, *path;
 | 
				
			||||||
 | 
					    int ret, offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dev = spapr_vty_get_default(bus);
 | 
				
			||||||
 | 
					    if (!dev)
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    offset = fdt_path_offset(fdt, "/chosen");
 | 
				
			||||||
 | 
					    if (offset < 0) {
 | 
				
			||||||
 | 
					        return offset;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    name = vio_format_dev_name(dev);
 | 
				
			||||||
 | 
					    if (!name) {
 | 
				
			||||||
 | 
					        return -ENOMEM;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (asprintf(&path, "/vdevice/%s", name) < 0) {
 | 
				
			||||||
 | 
					        path = NULL;
 | 
				
			||||||
 | 
					        ret = -ENOMEM;
 | 
				
			||||||
 | 
					        goto out;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ret = fdt_setprop_string(fdt, offset, "linux,stdout-path", path);
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
					    free(name);
 | 
				
			||||||
 | 
					    free(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif /* CONFIG_FDT */
 | 
					#endif /* CONFIG_FDT */
 | 
				
			||||||
 | 
				
			|||||||
@ -75,7 +75,6 @@ typedef struct {
 | 
				
			|||||||
    const char *dt_name, *dt_type, *dt_compatible;
 | 
					    const char *dt_name, *dt_type, *dt_compatible;
 | 
				
			||||||
    target_ulong signal_mask;
 | 
					    target_ulong signal_mask;
 | 
				
			||||||
    int (*init)(VIOsPAPRDevice *dev);
 | 
					    int (*init)(VIOsPAPRDevice *dev);
 | 
				
			||||||
    void (*hcalls)(VIOsPAPRBus *bus);
 | 
					 | 
				
			||||||
    int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off);
 | 
					    int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off);
 | 
				
			||||||
} VIOsPAPRDeviceInfo;
 | 
					} VIOsPAPRDeviceInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -83,6 +82,7 @@ extern VIOsPAPRBus *spapr_vio_bus_init(void);
 | 
				
			|||||||
extern VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg);
 | 
					extern VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg);
 | 
				
			||||||
extern void spapr_vio_bus_register_withprop(VIOsPAPRDeviceInfo *info);
 | 
					extern void spapr_vio_bus_register_withprop(VIOsPAPRDeviceInfo *info);
 | 
				
			||||||
extern int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt);
 | 
					extern int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt);
 | 
				
			||||||
 | 
					extern int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int spapr_vio_signal(VIOsPAPRDevice *dev, target_ulong mode);
 | 
					extern int spapr_vio_signal(VIOsPAPRDevice *dev, target_ulong mode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -108,6 +108,8 @@ void spapr_vty_create(VIOsPAPRBus *bus, uint32_t reg, CharDriverState *chardev);
 | 
				
			|||||||
void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd);
 | 
					void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd);
 | 
				
			||||||
void spapr_vscsi_create(VIOsPAPRBus *bus, uint32_t reg);
 | 
					void spapr_vscsi_create(VIOsPAPRBus *bus, uint32_t reg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int spapr_tce_set_bypass(uint32_t unit, uint32_t enable);
 | 
					int spapr_tce_set_bypass(uint32_t unit, uint32_t enable);
 | 
				
			||||||
void spapr_vio_quiesce(void);
 | 
					void spapr_vio_quiesce(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -135,18 +135,11 @@ void spapr_vty_create(VIOsPAPRBus *bus, uint32_t reg, CharDriverState *chardev)
 | 
				
			|||||||
    qdev_init_nofail(dev);
 | 
					    qdev_init_nofail(dev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void vty_hcalls(VIOsPAPRBus *bus)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    spapr_register_hypercall(H_PUT_TERM_CHAR, h_put_term_char);
 | 
					 | 
				
			||||||
    spapr_register_hypercall(H_GET_TERM_CHAR, h_get_term_char);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static VIOsPAPRDeviceInfo spapr_vty = {
 | 
					static VIOsPAPRDeviceInfo spapr_vty = {
 | 
				
			||||||
    .init = spapr_vty_init,
 | 
					    .init = spapr_vty_init,
 | 
				
			||||||
    .dt_name = "vty",
 | 
					    .dt_name = "vty",
 | 
				
			||||||
    .dt_type = "serial",
 | 
					    .dt_type = "serial",
 | 
				
			||||||
    .dt_compatible = "hvterm1",
 | 
					    .dt_compatible = "hvterm1",
 | 
				
			||||||
    .hcalls = vty_hcalls,
 | 
					 | 
				
			||||||
    .qdev.name = "spapr-vty",
 | 
					    .qdev.name = "spapr-vty",
 | 
				
			||||||
    .qdev.size = sizeof(VIOsPAPRVTYDevice),
 | 
					    .qdev.size = sizeof(VIOsPAPRVTYDevice),
 | 
				
			||||||
    .qdev.props = (Property[]) {
 | 
					    .qdev.props = (Property[]) {
 | 
				
			||||||
@ -156,24 +149,53 @@ static VIOsPAPRDeviceInfo spapr_vty = {
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VIOsPAPRDevice *sdev, *selected;
 | 
				
			||||||
 | 
					    DeviceState *iter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * To avoid the console bouncing around we want one VTY to be
 | 
				
			||||||
 | 
					     * the "default". We haven't really got anything to go on, so
 | 
				
			||||||
 | 
					     * arbitrarily choose the one with the lowest reg value.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    selected = NULL;
 | 
				
			||||||
 | 
					    QTAILQ_FOREACH(iter, &bus->bus.children, sibling) {
 | 
				
			||||||
 | 
					        /* Only look at VTY devices */
 | 
				
			||||||
 | 
					        if (iter->info != &spapr_vty.qdev) {
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        sdev = DO_UPCAST(VIOsPAPRDevice, qdev, iter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* First VTY we've found, so it is selected for now */
 | 
				
			||||||
 | 
					        if (!selected) {
 | 
				
			||||||
 | 
					            selected = sdev;
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Choose VTY with lowest reg value */
 | 
				
			||||||
 | 
					        if (sdev->reg < selected->reg) {
 | 
				
			||||||
 | 
					            selected = sdev;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return selected;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg)
 | 
					static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    VIOsPAPRDevice *sdev;
 | 
					    VIOsPAPRDevice *sdev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
 | 
					    sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
 | 
				
			||||||
    if (!sdev && reg == 0) {
 | 
					    if (!sdev && reg == 0) {
 | 
				
			||||||
        DeviceState *qdev;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* Hack for kernel early debug, which always specifies reg==0.
 | 
					        /* Hack for kernel early debug, which always specifies reg==0.
 | 
				
			||||||
         * We search all VIO devices, and grab the first available vty
 | 
					         * We search all VIO devices, and grab the vty with the lowest
 | 
				
			||||||
         * device.  This attempts to mimic existing PowerVM behaviour
 | 
					         * reg.  This attempts to mimic existing PowerVM behaviour
 | 
				
			||||||
         * (early debug does work there, despite having no vty with
 | 
					         * (early debug does work there, despite having no vty with
 | 
				
			||||||
         * reg==0. */
 | 
					         * reg==0. */
 | 
				
			||||||
        QTAILQ_FOREACH(qdev, &spapr->vio_bus->bus.children, sibling) {
 | 
					        return spapr_vty_get_default(spapr->vio_bus);
 | 
				
			||||||
            if (qdev->info == &spapr_vty.qdev) {
 | 
					 | 
				
			||||||
                return DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return sdev;
 | 
					    return sdev;
 | 
				
			||||||
@ -182,5 +204,7 @@ static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg)
 | 
				
			|||||||
static void spapr_vty_register(void)
 | 
					static void spapr_vty_register(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    spapr_vio_bus_register_withprop(&spapr_vty);
 | 
					    spapr_vio_bus_register_withprop(&spapr_vty);
 | 
				
			||||||
 | 
					    spapr_register_hypercall(H_PUT_TERM_CHAR, h_put_term_char);
 | 
				
			||||||
 | 
					    spapr_register_hypercall(H_GET_TERM_CHAR, h_get_term_char);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
device_init(spapr_vty_register);
 | 
					device_init(spapr_vty_register);
 | 
				
			||||||
 | 
				
			|||||||
@ -1545,12 +1545,40 @@ static void mmubooke206_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(TARGET_PPC64)
 | 
				
			||||||
 | 
					static void mmubooks_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
 | 
				
			||||||
 | 
					                              CPUState *env)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					    uint64_t slbe, slbv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cpu_synchronize_state(env);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cpu_fprintf(f, "SLB\tESID\t\t\tVSID\n");
 | 
				
			||||||
 | 
					    for (i = 0; i < env->slb_nr; i++) {
 | 
				
			||||||
 | 
					        slbe = env->slb[i].esid;
 | 
				
			||||||
 | 
					        slbv = env->slb[i].vsid;
 | 
				
			||||||
 | 
					        if (slbe == 0 && slbv == 0) {
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        cpu_fprintf(f, "%d\t0x%016" PRIx64 "\t0x%016" PRIx64 "\n",
 | 
				
			||||||
 | 
					                    i, slbe, slbv);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
 | 
					void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    switch (env->mmu_model) {
 | 
					    switch (env->mmu_model) {
 | 
				
			||||||
    case POWERPC_MMU_BOOKE206:
 | 
					    case POWERPC_MMU_BOOKE206:
 | 
				
			||||||
        mmubooke206_dump_mmu(f, cpu_fprintf, env);
 | 
					        mmubooke206_dump_mmu(f, cpu_fprintf, env);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					#if defined(TARGET_PPC64)
 | 
				
			||||||
 | 
					    case POWERPC_MMU_64B:
 | 
				
			||||||
 | 
					    case POWERPC_MMU_2_06:
 | 
				
			||||||
 | 
					        mmubooks_dump_mmu(f, cpu_fprintf, env);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        cpu_fprintf(f, "%s: unimplemented\n", __func__);
 | 
					        cpu_fprintf(f, "%s: unimplemented\n", __func__);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -504,7 +504,7 @@ void kvm_arch_post_run(CPUState *env, struct kvm_run *run)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
int kvm_arch_process_async_events(CPUState *env)
 | 
					int kvm_arch_process_async_events(CPUState *env)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return 0;
 | 
					    return env->halted;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int kvmppc_handle_halt(CPUState *env)
 | 
					static int kvmppc_handle_halt(CPUState *env)
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@
 | 
				
			|||||||
 *  PowerPC CPU initialization for qemu.
 | 
					 *  PowerPC CPU initialization for qemu.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *  Copyright (c) 2003-2007 Jocelyn Mayer
 | 
					 *  Copyright (c) 2003-2007 Jocelyn Mayer
 | 
				
			||||||
 | 
					 *  Copyright 2011 Freescale Semiconductor, Inc.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * This library is free software; you can redistribute it and/or
 | 
					 * This library is free software; you can redistribute it and/or
 | 
				
			||||||
 * modify it under the terms of the GNU Lesser General Public
 | 
					 * modify it under the terms of the GNU Lesser General Public
 | 
				
			||||||
@ -4399,6 +4400,33 @@ static void init_proc_e300 (CPUPPCState *env)
 | 
				
			|||||||
#define check_pow_e500v2       check_pow_hid0
 | 
					#define check_pow_e500v2       check_pow_hid0
 | 
				
			||||||
#define init_proc_e500v2       init_proc_e500v2
 | 
					#define init_proc_e500v2       init_proc_e500v2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* e500mc core                                                               */
 | 
				
			||||||
 | 
					#define POWERPC_INSNS_e500mc   (PPC_INSNS_BASE | PPC_ISEL |                 \
 | 
				
			||||||
 | 
					                                PPC_WRTEE | PPC_RFDI | PPC_RFMCI |          \
 | 
				
			||||||
 | 
					                                PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI | \
 | 
				
			||||||
 | 
					                                PPC_CACHE_DCBZ | PPC_CACHE_DCBA |           \
 | 
				
			||||||
 | 
					                                PPC_FLOAT | PPC_FLOAT_FRES |                \
 | 
				
			||||||
 | 
					                                PPC_FLOAT_FRSQRTE | PPC_FLOAT_FSEL |        \
 | 
				
			||||||
 | 
					                                PPC_FLOAT_STFIWX | PPC_WAIT |               \
 | 
				
			||||||
 | 
					                                PPC_MEM_TLBSYNC | PPC_TLBIVAX)
 | 
				
			||||||
 | 
					#define POWERPC_INSNS2_e500mc  (PPC2_BOOKE206)
 | 
				
			||||||
 | 
					#define POWERPC_MSRM_e500mc    (0x000000001402FB36ULL)
 | 
				
			||||||
 | 
					#define POWERPC_MMU_e500mc     (POWERPC_MMU_BOOKE206)
 | 
				
			||||||
 | 
					#define POWERPC_EXCP_e500mc    (POWERPC_EXCP_BOOKE)
 | 
				
			||||||
 | 
					#define POWERPC_INPUT_e500mc   (PPC_FLAGS_INPUT_BookE)
 | 
				
			||||||
 | 
					/* Fixme: figure out the correct flag for e500mc */
 | 
				
			||||||
 | 
					#define POWERPC_BFDM_e500mc    (bfd_mach_ppc_e500)
 | 
				
			||||||
 | 
					#define POWERPC_FLAG_e500mc    (POWERPC_FLAG_CE | POWERPC_FLAG_DE | \
 | 
				
			||||||
 | 
					                                POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
 | 
				
			||||||
 | 
					#define check_pow_e500mc       check_pow_none
 | 
				
			||||||
 | 
					#define init_proc_e500mc       init_proc_e500mc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum fsl_e500_version {
 | 
				
			||||||
 | 
					    fsl_e500v1,
 | 
				
			||||||
 | 
					    fsl_e500v2,
 | 
				
			||||||
 | 
					    fsl_e500mc,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void init_proc_e500 (CPUPPCState *env, int version)
 | 
					static void init_proc_e500 (CPUPPCState *env, int version)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint32_t tlbncfg[2];
 | 
					    uint32_t tlbncfg[2];
 | 
				
			||||||
@ -4430,15 +4458,26 @@ static void init_proc_e500 (CPUPPCState *env, int version)
 | 
				
			|||||||
    env->nb_ways = 2;
 | 
					    env->nb_ways = 2;
 | 
				
			||||||
    env->id_tlbs = 0;
 | 
					    env->id_tlbs = 0;
 | 
				
			||||||
    switch (version) {
 | 
					    switch (version) {
 | 
				
			||||||
    case 1:
 | 
					    case fsl_e500v1:
 | 
				
			||||||
        /* e500v1 */
 | 
					        /* e500v1 */
 | 
				
			||||||
        tlbncfg[0] = gen_tlbncfg(2, 1, 1, 0, 256);
 | 
					        tlbncfg[0] = gen_tlbncfg(2, 1, 1, 0, 256);
 | 
				
			||||||
        tlbncfg[1] = gen_tlbncfg(16, 1, 9, TLBnCFG_AVAIL | TLBnCFG_IPROT, 16);
 | 
					        tlbncfg[1] = gen_tlbncfg(16, 1, 9, TLBnCFG_AVAIL | TLBnCFG_IPROT, 16);
 | 
				
			||||||
 | 
					        env->dcache_line_size = 32;
 | 
				
			||||||
 | 
					        env->icache_line_size = 32;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 2:
 | 
					    case fsl_e500v2:
 | 
				
			||||||
        /* e500v2 */
 | 
					        /* e500v2 */
 | 
				
			||||||
        tlbncfg[0] = gen_tlbncfg(4, 1, 1, 0, 512);
 | 
					        tlbncfg[0] = gen_tlbncfg(4, 1, 1, 0, 512);
 | 
				
			||||||
        tlbncfg[1] = gen_tlbncfg(16, 1, 12, TLBnCFG_AVAIL | TLBnCFG_IPROT, 16);
 | 
					        tlbncfg[1] = gen_tlbncfg(16, 1, 12, TLBnCFG_AVAIL | TLBnCFG_IPROT, 16);
 | 
				
			||||||
 | 
					        env->dcache_line_size = 32;
 | 
				
			||||||
 | 
					        env->icache_line_size = 32;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case fsl_e500mc:
 | 
				
			||||||
 | 
					        /* e500mc */
 | 
				
			||||||
 | 
					        tlbncfg[0] = gen_tlbncfg(4, 1, 1, 0, 512);
 | 
				
			||||||
 | 
					        tlbncfg[1] = gen_tlbncfg(64, 1, 12, TLBnCFG_AVAIL | TLBnCFG_IPROT, 64);
 | 
				
			||||||
 | 
					        env->dcache_line_size = 64;
 | 
				
			||||||
 | 
					        env->icache_line_size = 64;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        cpu_abort(env, "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]);
 | 
					        cpu_abort(env, "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]);
 | 
				
			||||||
@ -4522,20 +4561,23 @@ static void init_proc_e500 (CPUPPCState *env, int version)
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    init_excp_e200(env);
 | 
					    init_excp_e200(env);
 | 
				
			||||||
    env->dcache_line_size = 32;
 | 
					 | 
				
			||||||
    env->icache_line_size = 32;
 | 
					 | 
				
			||||||
    /* Allocate hardware IRQ controller */
 | 
					    /* Allocate hardware IRQ controller */
 | 
				
			||||||
    ppce500_irq_init(env);
 | 
					    ppce500_irq_init(env);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void init_proc_e500v1(CPUPPCState *env)
 | 
					static void init_proc_e500v1(CPUPPCState *env)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    init_proc_e500(env, 1);
 | 
					    init_proc_e500(env, fsl_e500v1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void init_proc_e500v2(CPUPPCState *env)
 | 
					static void init_proc_e500v2(CPUPPCState *env)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    init_proc_e500(env, 2);
 | 
					    init_proc_e500(env, fsl_e500v2);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void init_proc_e500mc(CPUPPCState *env)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    init_proc_e500(env, fsl_e500mc);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Non-embedded PowerPC                                                      */
 | 
					/* Non-embedded PowerPC                                                      */
 | 
				
			||||||
@ -7070,6 +7112,7 @@ enum {
 | 
				
			|||||||
    CPU_POWERPC_e500v2_v21         = 0x80210021,
 | 
					    CPU_POWERPC_e500v2_v21         = 0x80210021,
 | 
				
			||||||
    CPU_POWERPC_e500v2_v22         = 0x80210022,
 | 
					    CPU_POWERPC_e500v2_v22         = 0x80210022,
 | 
				
			||||||
    CPU_POWERPC_e500v2_v30         = 0x80210030,
 | 
					    CPU_POWERPC_e500v2_v30         = 0x80210030,
 | 
				
			||||||
 | 
					    CPU_POWERPC_e500mc             = 0x80230020,
 | 
				
			||||||
    /* MPC85xx microcontrollers */
 | 
					    /* MPC85xx microcontrollers */
 | 
				
			||||||
#define CPU_POWERPC_MPC8533          CPU_POWERPC_MPC8533_v11
 | 
					#define CPU_POWERPC_MPC8533          CPU_POWERPC_MPC8533_v11
 | 
				
			||||||
#define CPU_POWERPC_MPC8533_v10      CPU_POWERPC_e500v2_v21
 | 
					#define CPU_POWERPC_MPC8533_v10      CPU_POWERPC_e500v2_v21
 | 
				
			||||||
@ -8471,6 +8514,7 @@ static const ppc_def_t ppc_defs[] = {
 | 
				
			|||||||
    POWERPC_DEF("e500v2_v22",    CPU_POWERPC_e500v2_v22,             e500v2),
 | 
					    POWERPC_DEF("e500v2_v22",    CPU_POWERPC_e500v2_v22,             e500v2),
 | 
				
			||||||
    /* PowerPC e500v2 v3.0 core                                              */
 | 
					    /* PowerPC e500v2 v3.0 core                                              */
 | 
				
			||||||
    POWERPC_DEF("e500v2_v30",    CPU_POWERPC_e500v2_v30,             e500v2),
 | 
					    POWERPC_DEF("e500v2_v30",    CPU_POWERPC_e500v2_v30,             e500v2),
 | 
				
			||||||
 | 
					    POWERPC_DEF("e500mc",        CPU_POWERPC_e500mc,                 e500mc),
 | 
				
			||||||
    /* PowerPC e500 microcontrollers                                         */
 | 
					    /* PowerPC e500 microcontrollers                                         */
 | 
				
			||||||
    /* MPC8533                                                               */
 | 
					    /* MPC8533                                                               */
 | 
				
			||||||
    POWERPC_DEF_SVR("MPC8533",
 | 
					    POWERPC_DEF_SVR("MPC8533",
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user