From cba2026a410328216f26db276a6ecf0e55a06e17 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sat, 19 May 2012 00:48:50 +0200 Subject: PPC: mpc8544ds: Span initial TLB entry over as much RAM as we need The initial TLB entry is supposed to help us run the guest -kernel payload. This means the guest needs to be able to access its own memory, the initrd memory and the device tree. So far we only statically reserved a TLB entry from [0;256M[. This patch fixes it to span from [0;dt_end[, allowing the guest payload to access everything initially. Reported-by: Stuart Yoder Signed-off-by: Alexander Graf --- hw/ppce500_mpc8544ds.c | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) (limited to 'hw') diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index 3eb8a23779..b1a0b8c542 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -31,6 +31,7 @@ #include "elf.h" #include "sysbus.h" #include "exec-memory.h" +#include "host-utils.h" #define BINARY_DEVICE_TREE_FILE "mpc8544ds.dtb" #define UIMAGE_LOAD_BASE 0 @@ -55,6 +56,7 @@ struct boot_info { uint32_t dt_base; + uint32_t dt_size; uint32_t entry; }; @@ -164,7 +166,11 @@ static int mpc8544_load_device_tree(CPUPPCState *env, } ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr); + if (ret < 0) { + goto out; + } g_free(fdt); + ret = fdt_size; out: #endif @@ -172,23 +178,27 @@ out: return ret; } -/* Create -kernel TLB entries for BookE, linearly spanning 256MB. */ +/* Create -kernel TLB entries for BookE. */ static inline target_phys_addr_t booke206_page_size_to_tlb(uint64_t size) { - return ffs(size >> 10) - 1; + return 63 - clz64(size >> 10); } -static void mmubooke_create_initial_mapping(CPUPPCState *env, - target_ulong va, - target_phys_addr_t pa) +static void mmubooke_create_initial_mapping(CPUPPCState *env) { + struct boot_info *bi = env->load_info; ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 0); - target_phys_addr_t size; - - size = (booke206_page_size_to_tlb(256 * 1024 * 1024) << MAS1_TSIZE_SHIFT); + target_phys_addr_t size, dt_end; + int ps; + + /* Our initial TLB entry needs to cover everything from 0 to + the device tree top */ + dt_end = bi->dt_base + bi->dt_size; + ps = booke206_page_size_to_tlb(dt_end) + 1; + size = (ps << MAS1_TSIZE_SHIFT); tlb->mas1 = MAS1_VALID | size; - tlb->mas2 = va & TARGET_PAGE_MASK; - tlb->mas7_3 = pa & TARGET_PAGE_MASK; + tlb->mas2 = 0; + tlb->mas7_3 = 0; tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX; env->tlb_dirty = true; @@ -220,7 +230,7 @@ static void mpc8544ds_cpu_reset(void *opaque) env->gpr[1] = (16<<20) - 8; env->gpr[3] = bi->dt_base; env->nip = bi->entry; - mmubooke_create_initial_mapping(env, 0, 0); + mmubooke_create_initial_mapping(env); } static void mpc8544ds_init(ram_addr_t ram_size, @@ -379,13 +389,15 @@ static void mpc8544ds_init(ram_addr_t ram_size, /* If we're loading a kernel directly, we must load the device tree too. */ if (kernel_filename) { struct boot_info *boot_info; + int dt_size; #ifndef CONFIG_FDT cpu_abort(env, "Compiled without FDT support - can't load kernel\n"); #endif - dt_base = (kernel_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK; - if (mpc8544_load_device_tree(env, dt_base, ram_size, - initrd_base, initrd_size, kernel_cmdline) < 0) { + dt_base = (loadaddr + kernel_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK; + dt_size = mpc8544_load_device_tree(env, dt_base, ram_size, initrd_base, + initrd_size, kernel_cmdline); + if (dt_size < 0) { fprintf(stderr, "couldn't load device tree\n"); exit(1); } @@ -393,6 +405,7 @@ static void mpc8544ds_init(ram_addr_t ram_size, boot_info = env->load_info; boot_info->entry = entry; boot_info->dt_base = dt_base; + boot_info->dt_size = dt_size; } if (kvm_enabled()) { -- cgit v1.2.3 From 5af9873d301cf5affec57e2f93650e8700f8251a Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 18 Jun 2012 19:56:30 +0000 Subject: pseries: Correctly create ibm,segment-page-sizes property The core tcg/kvm code for ppc64 now has at least the outline capability to support pagesizes beyond the standard 4k and 16MB. The CPUState is initialized with information advertising the available pagesizes and their correct encodings, and under the right KVM setup this will be populated with page sizes beyond the standard. Obviously guests can't use the extra page sizes unless they know they're present. For the pseries machine, at least, there is a defined method for conveying exactly this information, the "ibm-segment-page-sizes" property in the guest device tree. This patch generates this property using the supported page size information that's already in the CPUState. Signed-off-by: Nishanth Aravamudan Signed-off-by: David Gibson Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Alexander Graf --- hw/spapr.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'hw') diff --git a/hw/spapr.c b/hw/spapr.c index d0bddbce95..1b01d6475d 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -146,6 +146,40 @@ static int spapr_set_associativity(void *fdt, sPAPREnvironment *spapr) return ret; } + +static size_t create_page_sizes_prop(CPUPPCState *env, uint32_t *prop, + size_t maxsize) +{ + size_t maxcells = maxsize / sizeof(uint32_t); + int i, j, count; + uint32_t *p = prop; + + for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) { + struct ppc_one_seg_page_size *sps = &env->sps.sps[i]; + + if (!sps->page_shift) { + break; + } + for (count = 0; count < PPC_PAGE_SIZES_MAX_SZ; count++) { + if (sps->enc[count].page_shift == 0) { + break; + } + } + if ((p - prop) >= (maxcells - 3 - count * 2)) { + break; + } + *(p++) = cpu_to_be32(sps->page_shift); + *(p++) = cpu_to_be32(sps->slb_enc); + *(p++) = cpu_to_be32(count); + for (j = 0; j < count; j++) { + *(p++) = cpu_to_be32(sps->enc[j].page_shift); + *(p++) = cpu_to_be32(sps->enc[j].pte_enc); + } + } + + return (p - prop) * sizeof(uint32_t); +} + static void *spapr_create_fdt_skel(const char *cpu_model, target_phys_addr_t rma_size, target_phys_addr_t initrd_base, @@ -298,6 +332,8 @@ static void *spapr_create_fdt_skel(const char *cpu_model, 0xffffffff, 0xffffffff}; uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() : TIMEBASE_FREQ; uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000; + uint32_t page_sizes_prop[64]; + size_t page_sizes_prop_size; if ((index % smt) != 0) { continue; @@ -362,6 +398,13 @@ static void *spapr_create_fdt_skel(const char *cpu_model, _FDT((fdt_property_cell(fdt, "ibm,dfp", 1))); } + page_sizes_prop_size = create_page_sizes_prop(env, page_sizes_prop, + sizeof(page_sizes_prop)); + if (page_sizes_prop_size) { + _FDT((fdt_property(fdt, "ibm,segment-page-sizes", + page_sizes_prop, page_sizes_prop_size))); + } + _FDT((fdt_end_node(fdt))); } -- cgit v1.2.3 From a4d8e8daee324e230b0155915f562743f4fff5d8 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 18 Jun 2012 20:02:38 +0000 Subject: spapr_vscsi: Error handling fixes We were incorrectly g_free'ing an object that isn't allocated in one error path and failed to release it completely in another This fixes qemu crashes with some cases of IO errors. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Alexander Graf --- hw/spapr_vscsi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c index 037867ab4f..2f09616dd5 100644 --- a/hw/spapr_vscsi.c +++ b/hw/spapr_vscsi.c @@ -800,6 +800,7 @@ static void vscsi_got_payload(VSCSIState *s, vscsi_crq *crq) if (crq->s.IU_length > sizeof(union viosrp_iu)) { fprintf(stderr, "VSCSI: SRP IU too long (%d bytes) !\n", crq->s.IU_length); + vscsi_put_req(req); return; } @@ -807,7 +808,8 @@ static void vscsi_got_payload(VSCSIState *s, vscsi_crq *crq) if (spapr_tce_dma_read(&s->vdev, crq->s.IU_data_ptr, &req->iu, crq->s.IU_length)) { fprintf(stderr, "vscsi_got_payload: DMA read failure !\n"); - g_free(req); + vscsi_put_req(req); + return; } memcpy(&req->crq, crq, sizeof(vscsi_crq)); -- cgit v1.2.3 From c73e3771ea79ab3898da3ba51ff6fc5b05948d85 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 18 Jun 2012 20:21:37 +0000 Subject: spapr: Add "memop" hypercall This adds a qemu-specific hypervisor call to the pseries machine which allows to do what amounts to memmove, memcpy and xor over regions of physical memory such as the framebuffer. This is the simplest way to get usable framebuffer speed from SLOF since the framebuffer isn't mapped in the VRMA and so would otherwise require an hcall per 8 bytes access. The performance is still not great but usable, and can be improved with a more complex implementation of the hcall itself if needed. This also adds some documentation for the qemu-specific hypercalls that we add to PAPR along with a new qemu,hypertas-functions property that mirrors ibm,hypertas-functions and provides some discoverability for the new calls. Note: I chose note to advertise H_RTAS to the guest via that mechanism. This is done on purpose, the guest uses the normal RTAS interfaces provided by qemu (including SLOF) which internally calls H_RTAS. We might in the future implement part (or even all) of RTAS inside the guest like IBM's firmware does and replace H_RTAS with some finer grained set of private hypercalls. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Alexander Graf --- hw/spapr.c | 3 +++ hw/spapr.h | 3 ++- hw/spapr_hcall.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/spapr.c b/hw/spapr.c index 1b01d6475d..09a23ff092 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -197,6 +197,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model, uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)}; char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt" "\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk"; + char qemu_hypertas_prop[] = "hcall-memop1"; uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)}; int i; char *modelname; @@ -417,6 +418,8 @@ static void *spapr_create_fdt_skel(const char *cpu_model, _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas_prop, sizeof(hypertas_prop)))); + _FDT((fdt_property(fdt, "qemu,hypertas-functions", qemu_hypertas_prop, + sizeof(qemu_hypertas_prop)))); _FDT((fdt_property(fdt, "ibm,associativity-reference-points", refpoints, sizeof(refpoints)))); diff --git a/hw/spapr.h b/hw/spapr.h index 654a7a8a34..c75172e0c0 100644 --- a/hw/spapr.h +++ b/hw/spapr.h @@ -264,7 +264,8 @@ typedef struct sPAPREnvironment { */ #define KVMPPC_HCALL_BASE 0xf000 #define KVMPPC_H_RTAS (KVMPPC_HCALL_BASE + 0x0) -#define KVMPPC_HCALL_MAX KVMPPC_H_RTAS +#define KVMPPC_H_LOGICAL_MEMOP (KVMPPC_HCALL_BASE + 0x1) +#define KVMPPC_HCALL_MAX KVMPPC_H_LOGICAL_MEMOP extern sPAPREnvironment *spapr; diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c index 94bb504ca6..a5990a9617 100644 --- a/hw/spapr_hcall.c +++ b/hw/spapr_hcall.c @@ -608,6 +608,73 @@ static target_ulong h_logical_store(CPUPPCState *env, sPAPREnvironment *spapr, return H_PARAMETER; } +static target_ulong h_logical_memop(CPUPPCState *env, sPAPREnvironment *spapr, + target_ulong opcode, target_ulong *args) +{ + target_ulong dst = args[0]; /* Destination address */ + target_ulong src = args[1]; /* Source address */ + target_ulong esize = args[2]; /* Element size (0=1,1=2,2=4,3=8) */ + target_ulong count = args[3]; /* Element count */ + target_ulong op = args[4]; /* 0 = copy, 1 = invert */ + uint64_t tmp; + unsigned int mask = (1 << esize) - 1; + int step = 1 << esize; + + if (count > 0x80000000) { + return H_PARAMETER; + } + + if ((dst & mask) || (src & mask) || (op > 1)) { + return H_PARAMETER; + } + + if (dst >= src && dst < (src + (count << esize))) { + dst = dst + ((count - 1) << esize); + src = src + ((count - 1) << esize); + step = -step; + } + + while (count--) { + switch (esize) { + case 0: + tmp = ldub_phys(src); + break; + case 1: + tmp = lduw_phys(src); + break; + case 2: + tmp = ldl_phys(src); + break; + case 3: + tmp = ldq_phys(src); + break; + default: + return H_PARAMETER; + } + if (op == 1) { + tmp = ~tmp; + } + switch (esize) { + case 0: + stb_phys(dst, tmp); + break; + case 1: + stw_phys(dst, tmp); + break; + case 2: + stl_phys(dst, tmp); + break; + case 3: + stq_phys(dst, tmp); + break; + } + dst = dst + step; + src = src + step; + } + + return H_SUCCESS; +} + static target_ulong h_logical_icbi(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { @@ -700,6 +767,7 @@ static void hypercall_register_types(void) spapr_register_hypercall(H_LOGICAL_CACHE_STORE, h_logical_store); spapr_register_hypercall(H_LOGICAL_ICBI, h_logical_icbi); spapr_register_hypercall(H_LOGICAL_DCBF, h_logical_dcbf); + spapr_register_hypercall(KVMPPC_H_LOGICAL_MEMOP, h_logical_memop); /* qemu/KVM-PPC specific hcalls */ spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas); -- cgit v1.2.3 From 63397dd0be8d03d62393620e8192dafe0db72f8f Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 17 May 2012 12:23:41 +0200 Subject: PPC: e500: require libfdt Now that we're moving all of the device tree generation from an external pre-execution generated blob to runtime generation using libfdt, we absolutely must have libfdt around. This requirement was there before already, as the only way to not require libfdt with e500 was to not use -kernel, which was the only way to boot the mpc8544ds machine. This patch only manifests said requirement in the build system. Signed-off-by: Alexander Graf --- hw/ppc/Makefile.objs | 2 +- hw/ppce500_mpc8544ds.c | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'hw') diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index 44a1e8cdab..d18dbaf6cc 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -15,7 +15,7 @@ obj-$(CONFIG_PSERIES) += spapr_pci.o pci-hotplug.o obj-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o obj-y += ppc440_bamboo.o # PowerPC E500 boards -obj-y += ppce500_mpc8544ds.o mpc8544_guts.o ppce500_spin.o +obj-$(CONFIG_FDT) += ppce500_mpc8544ds.o mpc8544_guts.o ppce500_spin.o # PowerPC 440 Xilinx ML507 reference board. obj-y += virtex_ml507.o # PowerPC OpenPIC diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index b1a0b8c542..506ddf38b8 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -68,7 +68,6 @@ static int mpc8544_load_device_tree(CPUPPCState *env, const char *kernel_cmdline) { int ret = -1; -#ifdef CONFIG_FDT uint32_t mem_reg_property[] = {0, cpu_to_be32(ramsize)}; char *filename; int fdt_size; @@ -173,7 +172,6 @@ static int mpc8544_load_device_tree(CPUPPCState *env, ret = fdt_size; out: -#endif return ret; } @@ -391,9 +389,6 @@ static void mpc8544ds_init(ram_addr_t ram_size, struct boot_info *boot_info; int dt_size; -#ifndef CONFIG_FDT - cpu_abort(env, "Compiled without FDT support - can't load kernel\n"); -#endif dt_base = (loadaddr + kernel_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK; dt_size = mpc8544_load_device_tree(env, dt_base, ram_size, initrd_base, initrd_size, kernel_cmdline); -- cgit v1.2.3 From dd0bcfca64d12f557fae67a0ca318bf9b5579dd9 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 17 May 2012 11:34:50 +0200 Subject: PPC: e500: dt: create memory node dynamically Signed-off-by: Alexander Graf --- hw/ppce500_mpc8544ds.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'hw') diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index 506ddf38b8..3ec90133fd 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -88,10 +88,10 @@ static int mpc8544_load_device_tree(CPUPPCState *env, } /* Manipulate device tree in memory. */ - ret = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property, - sizeof(mem_reg_property)); - if (ret < 0) - fprintf(stderr, "couldn't set /memory/reg\n"); + qemu_devtree_add_subnode(fdt, "/memory"); + qemu_devtree_setprop_string(fdt, "/memory", "device_type", "memory"); + qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property, + sizeof(mem_reg_property)); if (initrd_size) { ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start", -- cgit v1.2.3 From 625e665b61184cabce0d556910de05cc8a70169c Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 17 May 2012 11:48:16 +0200 Subject: PPC: e500: dt: create /cpus node dynamically Signed-off-by: Alexander Graf --- hw/ppce500_mpc8544ds.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'hw') diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index 3ec90133fd..c046206e16 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -125,6 +125,11 @@ static int mpc8544_load_device_tree(CPUPPCState *env, hypercall, sizeof(hypercall)); } + /* Create CPU nodes */ + qemu_devtree_add_subnode(fdt, "/cpus"); + qemu_devtree_setprop_cell(fdt, "/cpus", "#address-cells", 1); + qemu_devtree_setprop_cell(fdt, "/cpus", "#size-cells", 0); + /* We need to generate the cpu nodes in reverse order, so Linux can pick the first node as boot node and be happy */ for (i = smp_cpus - 1; i >= 0; i--) { -- cgit v1.2.3 From d50f71a5fda5515021a33e8e391decb5602f6328 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 17 May 2012 11:50:05 +0200 Subject: PPC: e500: dt: create /hypervisor node dynamically Signed-off-by: Alexander Graf --- hw/ppce500_mpc8544ds.c | 1 + 1 file changed, 1 insertion(+) (limited to 'hw') diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index c046206e16..54e7ec7c20 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -118,6 +118,7 @@ static int mpc8544_load_device_tree(CPUPPCState *env, tb_freq = kvmppc_get_tbfreq(); /* indicate KVM hypercall interface */ + qemu_devtree_add_subnode(fdt, "/hypervisor"); qemu_devtree_setprop_string(fdt, "/hypervisor", "compatible", "linux,kvm"); kvmppc_get_hypercall(env, hypercall, sizeof(hypercall)); -- cgit v1.2.3 From 51b852b74c999f099338fba1b26bbbb4ab8a0bd4 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 17 May 2012 12:20:50 +0200 Subject: PPC: e500: dt: create / node dynamically Signed-off-by: Alexander Graf --- hw/ppce500_mpc8544ds.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'hw') diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index 54e7ec7c20..28c7c8c93d 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -76,6 +76,8 @@ static int mpc8544_load_device_tree(CPUPPCState *env, uint32_t clock_freq = 400000000; uint32_t tb_freq = 400000000; int i; + char compatible[] = "MPC8544DS\0MPC85xxDS"; + char model[] = "MPC8544DS"; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE); if (!filename) { @@ -88,6 +90,12 @@ static int mpc8544_load_device_tree(CPUPPCState *env, } /* Manipulate device tree in memory. */ + qemu_devtree_setprop_string(fdt, "/", "model", model); + qemu_devtree_setprop(fdt, "/", "compatible", compatible, + sizeof(compatible)); + qemu_devtree_setprop_cell(fdt, "/", "#address-cells", 1); + qemu_devtree_setprop_cell(fdt, "/", "#size-cells", 1); + qemu_devtree_add_subnode(fdt, "/memory"); qemu_devtree_setprop_string(fdt, "/memory", "device_type", "memory"); qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property, -- cgit v1.2.3 From f5231aafbfcbf4c43c7612785daa8f26e54ab5bb Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 17 May 2012 14:49:20 +0200 Subject: PPC: e500: dt: create /chosen node dynamically Signed-off-by: Alexander Graf --- hw/ppce500_mpc8544ds.c | 1 + 1 file changed, 1 insertion(+) (limited to 'hw') diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index 28c7c8c93d..a078e24103 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -101,6 +101,7 @@ static int mpc8544_load_device_tree(CPUPPCState *env, qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property, sizeof(mem_reg_property)); + qemu_devtree_add_subnode(fdt, "/chosen"); if (initrd_size) { ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start", initrd_base); -- cgit v1.2.3 From 5da96624391b27f9ead1e0639dbca416926cd660 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 17 May 2012 14:51:07 +0200 Subject: PPC: e500: dt: create /soc8544 node dynamically Signed-off-by: Alexander Graf --- hw/ppce500_mpc8544ds.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'hw') diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index a078e24103..c7c16c1267 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -43,6 +43,8 @@ #define RAM_SIZES_ALIGN (64UL << 20) #define MPC8544_CCSRBAR_BASE 0xE0000000 +#define MPC8544_CCSRBAR_REGSIZE 0x00001000 +#define MPC8544_CCSRBAR_SIZE 0x00100000 #define MPC8544_MPIC_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x40000) #define MPC8544_SERIAL0_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x4500) #define MPC8544_SERIAL1_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x4600) @@ -78,6 +80,7 @@ static int mpc8544_load_device_tree(CPUPPCState *env, int i; char compatible[] = "MPC8544DS\0MPC85xxDS"; char model[] = "MPC8544DS"; + char soc[128]; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE); if (!filename) { @@ -179,6 +182,20 @@ static int mpc8544_load_device_tree(CPUPPCState *env, } } + /* XXX These should go into their respective devices' code */ + snprintf(soc, sizeof(soc), "/soc8544@%x", MPC8544_CCSRBAR_BASE); + qemu_devtree_add_subnode(fdt, soc); + qemu_devtree_setprop_string(fdt, soc, "device_type", "soc"); + qemu_devtree_setprop_string(fdt, soc, "compatible", "simple-bus"); + qemu_devtree_setprop_cell(fdt, soc, "#address-cells", 1); + qemu_devtree_setprop_cell(fdt, soc, "#size-cells", 1); + qemu_devtree_setprop_cells(fdt, soc, "ranges", 0x0, MPC8544_CCSRBAR_BASE, + MPC8544_CCSRBAR_SIZE); + qemu_devtree_setprop_cells(fdt, soc, "reg", MPC8544_CCSRBAR_BASE, + MPC8544_CCSRBAR_REGSIZE); + /* XXX should contain a reasonable value */ + qemu_devtree_setprop_cell(fdt, soc, "bus-frequency", 0); + ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr); if (ret < 0) { goto out; -- cgit v1.2.3 From 0cfc6e8d9e18856b1db0cb5cd5624df7fb19b469 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 17 May 2012 14:51:34 +0200 Subject: PPC: e500: dt: create serial nodes dynamically Signed-off-by: Alexander Graf --- hw/ppce500_mpc8544ds.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'hw') diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index c7c16c1267..c68e9949b8 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -81,6 +81,8 @@ static int mpc8544_load_device_tree(CPUPPCState *env, char compatible[] = "MPC8544DS\0MPC85xxDS"; char model[] = "MPC8544DS"; char soc[128]; + char ser0[128]; + char ser1[128]; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE); if (!filename) { @@ -182,6 +184,7 @@ static int mpc8544_load_device_tree(CPUPPCState *env, } } + qemu_devtree_add_subnode(fdt, "/aliases"); /* XXX These should go into their respective devices' code */ snprintf(soc, sizeof(soc), "/soc8544@%x", MPC8544_CCSRBAR_BASE); qemu_devtree_add_subnode(fdt, soc); @@ -196,6 +199,38 @@ static int mpc8544_load_device_tree(CPUPPCState *env, /* XXX should contain a reasonable value */ qemu_devtree_setprop_cell(fdt, soc, "bus-frequency", 0); + /* + * We have to generate ser1 first, because Linux takes the first + * device it finds in the dt as serial output device. And we generate + * devices in reverse order to the dt. + */ + snprintf(ser1, sizeof(ser1), "%s/serial@%x", soc, + MPC8544_SERIAL1_REGS_BASE - MPC8544_CCSRBAR_BASE); + qemu_devtree_add_subnode(fdt, ser1); + qemu_devtree_setprop_string(fdt, ser1, "device_type", "serial"); + qemu_devtree_setprop_string(fdt, ser1, "compatible", "ns16550"); + qemu_devtree_setprop_cells(fdt, ser1, "reg", MPC8544_SERIAL1_REGS_BASE - + MPC8544_CCSRBAR_BASE, 0x100); + qemu_devtree_setprop_cell(fdt, ser1, "cell-index", 1); + qemu_devtree_setprop_cell(fdt, ser1, "clock-frequency", 0); + qemu_devtree_setprop_cells(fdt, ser1, "interrupts", 42, 2); + qemu_devtree_setprop_phandle(fdt, ser1, "interrupt-parent", mpic); + qemu_devtree_setprop_string(fdt, "/aliases", "serial1", ser1); + + snprintf(ser0, sizeof(ser0), "%s/serial@%x", soc, + MPC8544_SERIAL0_REGS_BASE - MPC8544_CCSRBAR_BASE); + qemu_devtree_add_subnode(fdt, ser0); + qemu_devtree_setprop_string(fdt, ser0, "device_type", "serial"); + qemu_devtree_setprop_string(fdt, ser0, "compatible", "ns16550"); + qemu_devtree_setprop_cells(fdt, ser0, "reg", MPC8544_SERIAL0_REGS_BASE - + MPC8544_CCSRBAR_BASE, 0x100); + qemu_devtree_setprop_cell(fdt, ser0, "cell-index", 0); + qemu_devtree_setprop_cell(fdt, ser0, "clock-frequency", 0); + qemu_devtree_setprop_cells(fdt, ser0, "interrupts", 42, 2); + qemu_devtree_setprop_phandle(fdt, ser0, "interrupt-parent", mpic); + qemu_devtree_setprop_string(fdt, "/aliases", "serial0", ser0); + qemu_devtree_setprop_string(fdt, "/chosen", "linux,stdout-path", ser0); + ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr); if (ret < 0) { goto out; -- cgit v1.2.3 From 19ac9deacbadf77532723950ce3e128e18c31573 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 17 May 2012 14:51:51 +0200 Subject: PPC: e500: dt: create mpic node dynamically Signed-off-by: Alexander Graf --- hw/ppce500_mpc8544ds.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'hw') diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index c68e9949b8..5c2b6ab79a 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -83,6 +83,8 @@ static int mpc8544_load_device_tree(CPUPPCState *env, char soc[128]; char ser0[128]; char ser1[128]; + char mpic[128]; + uint32_t mpic_ph; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE); if (!filename) { @@ -199,6 +201,20 @@ static int mpc8544_load_device_tree(CPUPPCState *env, /* XXX should contain a reasonable value */ qemu_devtree_setprop_cell(fdt, soc, "bus-frequency", 0); + snprintf(mpic, sizeof(mpic), "%s/pic@%x", soc, + MPC8544_MPIC_REGS_BASE - MPC8544_CCSRBAR_BASE); + qemu_devtree_add_subnode(fdt, mpic); + qemu_devtree_setprop_string(fdt, mpic, "device_type", "open-pic"); + qemu_devtree_setprop_string(fdt, mpic, "compatible", "chrp,open-pic"); + qemu_devtree_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_BASE - + MPC8544_CCSRBAR_BASE, 0x40000); + qemu_devtree_setprop_cell(fdt, mpic, "#address-cells", 0); + qemu_devtree_setprop_cell(fdt, mpic, "#interrupt-cells", 2); + mpic_ph = qemu_devtree_alloc_phandle(fdt); + qemu_devtree_setprop_cell(fdt, mpic, "phandle", mpic_ph); + qemu_devtree_setprop_cell(fdt, mpic, "linux,phandle", mpic_ph); + qemu_devtree_setprop(fdt, mpic, "interrupt-controller", NULL, 0); + /* * We have to generate ser1 first, because Linux takes the first * device it finds in the dt as serial output device. And we generate -- cgit v1.2.3 From f5038483e4e752b7b4f7053e90873b127bfe4064 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 17 May 2012 14:52:46 +0200 Subject: PPC: e500: dt: create global-utils node dynamically Signed-off-by: Alexander Graf --- hw/ppce500_mpc8544ds.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'hw') diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index 5c2b6ab79a..03938b2e3b 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -85,6 +85,7 @@ static int mpc8544_load_device_tree(CPUPPCState *env, char ser1[128]; char mpic[128]; uint32_t mpic_ph; + char gutil[128]; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE); if (!filename) { @@ -247,6 +248,14 @@ static int mpc8544_load_device_tree(CPUPPCState *env, qemu_devtree_setprop_string(fdt, "/aliases", "serial0", ser0); qemu_devtree_setprop_string(fdt, "/chosen", "linux,stdout-path", ser0); + snprintf(gutil, sizeof(gutil), "%s/global-utilities@%x", soc, + MPC8544_UTIL_BASE - MPC8544_CCSRBAR_BASE); + qemu_devtree_add_subnode(fdt, gutil); + qemu_devtree_setprop_string(fdt, gutil, "compatible", "fsl,mpc8544-guts"); + qemu_devtree_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_BASE - + MPC8544_CCSRBAR_BASE, 0x1000); + qemu_devtree_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0); + ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr); if (ret < 0) { goto out; -- cgit v1.2.3 From 0dbc07985b15940ff3f19529c1f6fd734d535971 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 17 May 2012 15:34:34 +0200 Subject: PPC: e500: dt: create pci node dynamically Signed-off-by: Alexander Graf --- hw/ppce500_mpc8544ds.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'hw') diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index 03938b2e3b..15df51571c 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -62,6 +62,27 @@ struct boot_info uint32_t entry; }; +static void pci_map_create(void *fdt, uint32_t *pci_map, uint32_t mpic) +{ + int i; + const uint32_t tmp[] = { + /* IDSEL 0x11 J17 Slot 1 */ + 0x8800, 0x0, 0x0, 0x1, mpic, 0x2, 0x1, + 0x8800, 0x0, 0x0, 0x2, mpic, 0x3, 0x1, + 0x8800, 0x0, 0x0, 0x3, mpic, 0x4, 0x1, + 0x8800, 0x0, 0x0, 0x4, mpic, 0x1, 0x1, + + /* IDSEL 0x12 J16 Slot 2 */ + 0x9000, 0x0, 0x0, 0x1, mpic, 0x3, 0x1, + 0x9000, 0x0, 0x0, 0x2, mpic, 0x4, 0x1, + 0x9000, 0x0, 0x0, 0x3, mpic, 0x2, 0x1, + 0x9000, 0x0, 0x0, 0x4, mpic, 0x1, 0x1, + }; + for (i = 0; i < (7 * 8); i++) { + pci_map[i] = cpu_to_be32(tmp[i]); + } +} + static int mpc8544_load_device_tree(CPUPPCState *env, target_phys_addr_t addr, uint32_t ramsize, @@ -86,6 +107,11 @@ static int mpc8544_load_device_tree(CPUPPCState *env, char mpic[128]; uint32_t mpic_ph; char gutil[128]; + char pci[128]; + uint32_t pci_map[7 * 8]; + uint32_t pci_ranges[12] = { 0x2000000, 0x0, 0xc0000000, 0xc0000000, 0x0, + 0x20000000, 0x1000000, 0x0, 0x0, 0xe1000000, + 0x0, 0x10000 }; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE); if (!filename) { @@ -256,6 +282,30 @@ static int mpc8544_load_device_tree(CPUPPCState *env, MPC8544_CCSRBAR_BASE, 0x1000); qemu_devtree_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0); + snprintf(pci, sizeof(pci), "/pci@%x", MPC8544_PCI_REGS_BASE); + qemu_devtree_add_subnode(fdt, pci); + qemu_devtree_setprop_cell(fdt, pci, "cell-index", 0); + qemu_devtree_setprop_string(fdt, pci, "compatible", "fsl,mpc8540-pci"); + qemu_devtree_setprop_string(fdt, pci, "device_type", "pci"); + qemu_devtree_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0, + 0x0, 0x7); + pci_map_create(fdt, pci_map, qemu_devtree_get_phandle(fdt, mpic)); + qemu_devtree_setprop(fdt, pci, "interrupt-map", pci_map, sizeof(pci_map)); + qemu_devtree_setprop_phandle(fdt, pci, "interrupt-parent", mpic); + qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2); + qemu_devtree_setprop_cells(fdt, pci, "bus-range", 0, 255); + for (i = 0; i < 12; i++) { + pci_ranges[i] = cpu_to_be32(pci_ranges[i]); + } + qemu_devtree_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges)); + qemu_devtree_setprop_cells(fdt, pci, "reg", MPC8544_PCI_REGS_BASE, + 0x1000); + qemu_devtree_setprop_cell(fdt, pci, "clock-frequency", 66666666); + qemu_devtree_setprop_cell(fdt, pci, "#interrupt-cells", 1); + qemu_devtree_setprop_cell(fdt, pci, "#size-cells", 2); + qemu_devtree_setprop_cell(fdt, pci, "#address-cells", 3); + qemu_devtree_setprop_string(fdt, "/aliases", "pci0", pci); + ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr); if (ret < 0) { goto out; -- cgit v1.2.3 From 2636fcb6532eafbb3f1fafba69a107664218e3c8 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 17 May 2012 15:50:14 +0200 Subject: PPC: e500: dt: start with empty device tree Now that all of the device tree bits are generated during runtime, we can get rid of the device tree blob and instead start from scratch with an empty device tree. Signed-off-by: Alexander Graf --- hw/ppce500_mpc8544ds.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'hw') diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index 15df51571c..880ed55fdb 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -92,7 +92,6 @@ static int mpc8544_load_device_tree(CPUPPCState *env, { int ret = -1; uint32_t mem_reg_property[] = {0, cpu_to_be32(ramsize)}; - char *filename; int fdt_size; void *fdt; uint8_t hypercall[16]; @@ -113,12 +112,7 @@ static int mpc8544_load_device_tree(CPUPPCState *env, 0x20000000, 0x1000000, 0x0, 0x0, 0xe1000000, 0x0, 0x10000 }; - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE); - if (!filename) { - goto out; - } - fdt = load_device_tree(filename, &fdt_size); - g_free(filename); + fdt = create_device_tree(&fdt_size); if (fdt == NULL) { goto out; } -- cgit v1.2.3 From 25b42708cd011e7d4b37313f7f83ac2551e5370f Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Fri, 18 May 2012 00:11:33 +0200 Subject: dt: Add -machine dumpdtb option to dump the current dtb Now that we are dynamically creating the dtb, it's really useful to be able to dump the created blob for debugging. This patch implements a -machine dumpdtb= option for e500 that dumps the dtb exactly in the form the guest would get it to disk. It can then be analyzed by dtc to get information about the guest configuration. Signed-off-by: Alexander Graf --- hw/ppce500_mpc8544ds.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'hw') diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index 880ed55fdb..7c6edc22e1 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -111,6 +111,8 @@ static int mpc8544_load_device_tree(CPUPPCState *env, uint32_t pci_ranges[12] = { 0x2000000, 0x0, 0xc0000000, 0xc0000000, 0x0, 0x20000000, 0x1000000, 0x0, 0x0, 0xe1000000, 0x0, 0x10000 }; + QemuOpts *machine_opts; + const char *dumpdtb = NULL; fdt = create_device_tree(&fdt_size); if (fdt == NULL) { @@ -300,6 +302,22 @@ static int mpc8544_load_device_tree(CPUPPCState *env, qemu_devtree_setprop_cell(fdt, pci, "#address-cells", 3); qemu_devtree_setprop_string(fdt, "/aliases", "pci0", pci); + machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); + if (machine_opts) { + dumpdtb = qemu_opt_get(machine_opts, "dumpdtb"); + } + if (dumpdtb) { + /* Dump the dtb to a file and quit */ + FILE *f = fopen(dumpdtb, "wb"); + size_t len; + len = fwrite(fdt, fdt_size, 1, f); + fclose(f); + if (len != fdt_size) { + exit(1); + } + exit(0); + } + ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr); if (ret < 0) { goto out; -- cgit v1.2.3 From 1d2e5c5235dc722bc9e12218d5f00c12f8bdc5bb Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Fri, 18 May 2012 01:56:46 +0200 Subject: PPC: e500: dt: use 64bit cell helper We have a nice 64bit helper to ease the device tree generation and make the code more readable when creating 64bit 2-cell parameters. Use it when generating the device tree. Signed-off-by: Alexander Graf --- hw/ppce500_mpc8544ds.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'hw') diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index 7c6edc22e1..5fa2089fb8 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -174,7 +174,7 @@ static int mpc8544_load_device_tree(CPUPPCState *env, the first node as boot node and be happy */ for (i = smp_cpus - 1; i >= 0; i--) { char cpu_name[128]; - uint64_t cpu_release_addr = cpu_to_be64(MPC8544_SPIN_BASE + (i * 0x20)); + uint64_t cpu_release_addr = MPC8544_SPIN_BASE + (i * 0x20); for (env = first_cpu; env != NULL; env = env->next_cpu) { if (env->cpu_index == i) { @@ -202,8 +202,8 @@ static int mpc8544_load_device_tree(CPUPPCState *env, if (env->cpu_index) { qemu_devtree_setprop_string(fdt, cpu_name, "status", "disabled"); qemu_devtree_setprop_string(fdt, cpu_name, "enable-method", "spin-table"); - qemu_devtree_setprop(fdt, cpu_name, "cpu-release-addr", - &cpu_release_addr, sizeof(cpu_release_addr)); + qemu_devtree_setprop_u64(fdt, cpu_name, "cpu-release-addr", + cpu_release_addr); } else { qemu_devtree_setprop_string(fdt, cpu_name, "status", "okay"); } -- cgit v1.2.3 From 7f47b41f3f36fd0618758580121ddeb0407069b7 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Fri, 18 May 2012 02:14:46 +0200 Subject: PPC: e500: dt: use target_phys_addr_t for ramsize We're passing the ram size as uint32_t, capping it to 32 bits atm. Change to target_phys_addr_t (uint64_t) to make sure we have all the bits. Signed-off-by: Alexander Graf --- hw/ppce500_mpc8544ds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index 5fa2089fb8..f8a3d9abcf 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -85,7 +85,7 @@ static void pci_map_create(void *fdt, uint32_t *pci_map, uint32_t mpic) static int mpc8544_load_device_tree(CPUPPCState *env, target_phys_addr_t addr, - uint32_t ramsize, + target_phys_addr_t ramsize, target_phys_addr_t initrd_base, target_phys_addr_t initrd_size, const char *kernel_cmdline) -- cgit v1.2.3 From d1b935659b77ff8e9d4cb84e3f75679f634401f3 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 22 May 2012 14:28:50 +0200 Subject: PPC: e500: enable manual loading of dtb blob We want to be able to override the automatically created device tree by using the -dtb option. Implement this for the mpc8544ds machine. Signed-off-by: Alexander Graf --- hw/ppce500_mpc8544ds.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'hw') diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index f8a3d9abcf..fa10df226f 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -113,6 +113,27 @@ static int mpc8544_load_device_tree(CPUPPCState *env, 0x0, 0x10000 }; QemuOpts *machine_opts; const char *dumpdtb = NULL; + const char *dtb_file = NULL; + + machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); + if (machine_opts) { + dumpdtb = qemu_opt_get(machine_opts, "dumpdtb"); + dtb_file = qemu_opt_get(machine_opts, "dtb"); + } + + if (dtb_file) { + char *filename; + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_file); + if (!filename) { + goto out; + } + + fdt = load_device_tree(filename, &fdt_size); + if (!fdt) { + goto out; + } + goto done; + } fdt = create_device_tree(&fdt_size); if (fdt == NULL) { @@ -302,10 +323,7 @@ static int mpc8544_load_device_tree(CPUPPCState *env, qemu_devtree_setprop_cell(fdt, pci, "#address-cells", 3); qemu_devtree_setprop_string(fdt, "/aliases", "pci0", pci); - machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); - if (machine_opts) { - dumpdtb = qemu_opt_get(machine_opts, "dumpdtb"); - } +done: if (dumpdtb) { /* Dump the dtb to a file and quit */ FILE *f = fopen(dumpdtb, "wb"); -- cgit v1.2.3 From 518c7fb44f2182cde943dc64f88cb2fd4e4ff6b5 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 6 Jun 2012 00:14:34 +0200 Subject: PPC: e500: Use new MPIC dt format Due to popular demand, we're updating the way we generate the MPIC node and interrupt lines based on what the current state of art is. Requested-by: Scott Wood Signed-off-by: Alexander Graf --- hw/ppce500_mpc8544ds.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'hw') diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index fa10df226f..e3e0659594 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -67,18 +67,18 @@ static void pci_map_create(void *fdt, uint32_t *pci_map, uint32_t mpic) int i; const uint32_t tmp[] = { /* IDSEL 0x11 J17 Slot 1 */ - 0x8800, 0x0, 0x0, 0x1, mpic, 0x2, 0x1, - 0x8800, 0x0, 0x0, 0x2, mpic, 0x3, 0x1, - 0x8800, 0x0, 0x0, 0x3, mpic, 0x4, 0x1, - 0x8800, 0x0, 0x0, 0x4, mpic, 0x1, 0x1, + 0x8800, 0x0, 0x0, 0x1, mpic, 0x2, 0x1, 0x0, 0x0, + 0x8800, 0x0, 0x0, 0x2, mpic, 0x3, 0x1, 0x0, 0x0, + 0x8800, 0x0, 0x0, 0x3, mpic, 0x4, 0x1, 0x0, 0x0, + 0x8800, 0x0, 0x0, 0x4, mpic, 0x1, 0x1, 0x0, 0x0, /* IDSEL 0x12 J16 Slot 2 */ - 0x9000, 0x0, 0x0, 0x1, mpic, 0x3, 0x1, - 0x9000, 0x0, 0x0, 0x2, mpic, 0x4, 0x1, - 0x9000, 0x0, 0x0, 0x3, mpic, 0x2, 0x1, - 0x9000, 0x0, 0x0, 0x4, mpic, 0x1, 0x1, + 0x9000, 0x0, 0x0, 0x1, mpic, 0x3, 0x1, 0x0, 0x0, + 0x9000, 0x0, 0x0, 0x2, mpic, 0x4, 0x1, 0x0, 0x0, + 0x9000, 0x0, 0x0, 0x3, mpic, 0x2, 0x1, 0x0, 0x0, + 0x9000, 0x0, 0x0, 0x4, mpic, 0x1, 0x1, 0x0, 0x0, }; - for (i = 0; i < (7 * 8); i++) { + for (i = 0; i < ARRAY_SIZE(tmp); i++) { pci_map[i] = cpu_to_be32(tmp[i]); } } @@ -107,7 +107,7 @@ static int mpc8544_load_device_tree(CPUPPCState *env, uint32_t mpic_ph; char gutil[128]; char pci[128]; - uint32_t pci_map[7 * 8]; + uint32_t pci_map[9 * 8]; uint32_t pci_ranges[12] = { 0x2000000, 0x0, 0xc0000000, 0xc0000000, 0x0, 0x20000000, 0x1000000, 0x0, 0x0, 0xe1000000, 0x0, 0x10000 }; @@ -249,15 +249,18 @@ static int mpc8544_load_device_tree(CPUPPCState *env, MPC8544_MPIC_REGS_BASE - MPC8544_CCSRBAR_BASE); qemu_devtree_add_subnode(fdt, mpic); qemu_devtree_setprop_string(fdt, mpic, "device_type", "open-pic"); - qemu_devtree_setprop_string(fdt, mpic, "compatible", "chrp,open-pic"); + qemu_devtree_setprop_string(fdt, mpic, "compatible", "fsl,mpic"); qemu_devtree_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_BASE - MPC8544_CCSRBAR_BASE, 0x40000); qemu_devtree_setprop_cell(fdt, mpic, "#address-cells", 0); - qemu_devtree_setprop_cell(fdt, mpic, "#interrupt-cells", 2); + qemu_devtree_setprop_cell(fdt, mpic, "#interrupt-cells", 4); mpic_ph = qemu_devtree_alloc_phandle(fdt); qemu_devtree_setprop_cell(fdt, mpic, "phandle", mpic_ph); qemu_devtree_setprop_cell(fdt, mpic, "linux,phandle", mpic_ph); qemu_devtree_setprop(fdt, mpic, "interrupt-controller", NULL, 0); + qemu_devtree_setprop(fdt, mpic, "big-endian", NULL, 0); + qemu_devtree_setprop(fdt, mpic, "single-cpu-affinity", NULL, 0); + qemu_devtree_setprop_cell(fdt, mpic, "last-interrupt-source", 255); /* * We have to generate ser1 first, because Linux takes the first @@ -273,7 +276,7 @@ static int mpc8544_load_device_tree(CPUPPCState *env, MPC8544_CCSRBAR_BASE, 0x100); qemu_devtree_setprop_cell(fdt, ser1, "cell-index", 1); qemu_devtree_setprop_cell(fdt, ser1, "clock-frequency", 0); - qemu_devtree_setprop_cells(fdt, ser1, "interrupts", 42, 2); + qemu_devtree_setprop_cells(fdt, ser1, "interrupts", 42, 2, 0, 0); qemu_devtree_setprop_phandle(fdt, ser1, "interrupt-parent", mpic); qemu_devtree_setprop_string(fdt, "/aliases", "serial1", ser1); @@ -286,7 +289,7 @@ static int mpc8544_load_device_tree(CPUPPCState *env, MPC8544_CCSRBAR_BASE, 0x100); qemu_devtree_setprop_cell(fdt, ser0, "cell-index", 0); qemu_devtree_setprop_cell(fdt, ser0, "clock-frequency", 0); - qemu_devtree_setprop_cells(fdt, ser0, "interrupts", 42, 2); + qemu_devtree_setprop_cells(fdt, ser0, "interrupts", 42, 2, 0, 0); qemu_devtree_setprop_phandle(fdt, ser0, "interrupt-parent", mpic); qemu_devtree_setprop_string(fdt, "/aliases", "serial0", ser0); qemu_devtree_setprop_string(fdt, "/chosen", "linux,stdout-path", ser0); @@ -309,7 +312,7 @@ static int mpc8544_load_device_tree(CPUPPCState *env, pci_map_create(fdt, pci_map, qemu_devtree_get_phandle(fdt, mpic)); qemu_devtree_setprop(fdt, pci, "interrupt-map", pci_map, sizeof(pci_map)); qemu_devtree_setprop_phandle(fdt, pci, "interrupt-parent", mpic); - qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2); + qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2, 0, 0); qemu_devtree_setprop_cells(fdt, pci, "bus-range", 0, 255); for (i = 0; i < 12; i++) { pci_ranges[i] = cpu_to_be32(pci_ranges[i]); -- cgit v1.2.3 From ebb9518aab7a6c8bb78636494fa60b2742d00251 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 6 Jun 2012 00:20:20 +0200 Subject: PPC: e500: Use new SOC dt format Due to popular demand, let's clean up the soc node a bit and use more recent dt notions. Requested-by: Scott Wood Signed-off-by: Alexander Graf --- hw/ppce500_mpc8544ds.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'hw') diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index e3e0659594..7dc3a07aec 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -43,7 +43,6 @@ #define RAM_SIZES_ALIGN (64UL << 20) #define MPC8544_CCSRBAR_BASE 0xE0000000 -#define MPC8544_CCSRBAR_REGSIZE 0x00001000 #define MPC8544_CCSRBAR_SIZE 0x00100000 #define MPC8544_MPIC_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x40000) #define MPC8544_SERIAL0_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x4500) @@ -99,6 +98,7 @@ static int mpc8544_load_device_tree(CPUPPCState *env, uint32_t tb_freq = 400000000; int i; char compatible[] = "MPC8544DS\0MPC85xxDS"; + char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus"; char model[] = "MPC8544DS"; char soc[128]; char ser0[128]; @@ -232,16 +232,15 @@ static int mpc8544_load_device_tree(CPUPPCState *env, qemu_devtree_add_subnode(fdt, "/aliases"); /* XXX These should go into their respective devices' code */ - snprintf(soc, sizeof(soc), "/soc8544@%x", MPC8544_CCSRBAR_BASE); + snprintf(soc, sizeof(soc), "/soc@%x", MPC8544_CCSRBAR_BASE); qemu_devtree_add_subnode(fdt, soc); qemu_devtree_setprop_string(fdt, soc, "device_type", "soc"); - qemu_devtree_setprop_string(fdt, soc, "compatible", "simple-bus"); + qemu_devtree_setprop(fdt, soc, "compatible", compatible_sb, + sizeof(compatible_sb)); qemu_devtree_setprop_cell(fdt, soc, "#address-cells", 1); qemu_devtree_setprop_cell(fdt, soc, "#size-cells", 1); qemu_devtree_setprop_cells(fdt, soc, "ranges", 0x0, MPC8544_CCSRBAR_BASE, MPC8544_CCSRBAR_SIZE); - qemu_devtree_setprop_cells(fdt, soc, "reg", MPC8544_CCSRBAR_BASE, - MPC8544_CCSRBAR_REGSIZE); /* XXX should contain a reasonable value */ qemu_devtree_setprop_cell(fdt, soc, "bus-frequency", 0); -- cgit v1.2.3 From ed2bc496eff0d78544d46c637cf11a29114666c5 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 6 Jun 2012 00:30:36 +0200 Subject: PPC: e500: Define addresses as always 64bit Every time we use an address constant, it needs to potentially fit into a 64bit physical address space. So let's define things accordingly. Signed-off-by: Alexander Graf --- hw/ppce500_mpc8544ds.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'hw') diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index 7dc3a07aec..c6a09bba3f 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -42,17 +42,17 @@ #define RAM_SIZES_ALIGN (64UL << 20) -#define MPC8544_CCSRBAR_BASE 0xE0000000 -#define MPC8544_CCSRBAR_SIZE 0x00100000 -#define MPC8544_MPIC_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x40000) -#define MPC8544_SERIAL0_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x4500) -#define MPC8544_SERIAL1_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x4600) -#define MPC8544_PCI_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x8000) -#define MPC8544_PCI_REGS_SIZE 0x1000 -#define MPC8544_PCI_IO 0xE1000000 -#define MPC8544_PCI_IOLEN 0x10000 -#define MPC8544_UTIL_BASE (MPC8544_CCSRBAR_BASE + 0xe0000) -#define MPC8544_SPIN_BASE 0xEF000000 +#define MPC8544_CCSRBAR_BASE 0xE0000000ULL +#define MPC8544_CCSRBAR_SIZE 0x00100000ULL +#define MPC8544_MPIC_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x40000ULL) +#define MPC8544_SERIAL0_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x4500ULL) +#define MPC8544_SERIAL1_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x4600ULL) +#define MPC8544_PCI_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x8000ULL) +#define MPC8544_PCI_REGS_SIZE 0x1000ULL +#define MPC8544_PCI_IO 0xE1000000ULL +#define MPC8544_PCI_IOLEN 0x10000ULL +#define MPC8544_UTIL_BASE (MPC8544_CCSRBAR_BASE + 0xe0000ULL) +#define MPC8544_SPIN_BASE 0xEF000000ULL struct boot_info { @@ -232,7 +232,7 @@ static int mpc8544_load_device_tree(CPUPPCState *env, qemu_devtree_add_subnode(fdt, "/aliases"); /* XXX These should go into their respective devices' code */ - snprintf(soc, sizeof(soc), "/soc@%x", MPC8544_CCSRBAR_BASE); + snprintf(soc, sizeof(soc), "/soc@%llx", MPC8544_CCSRBAR_BASE); qemu_devtree_add_subnode(fdt, soc); qemu_devtree_setprop_string(fdt, soc, "device_type", "soc"); qemu_devtree_setprop(fdt, soc, "compatible", compatible_sb, @@ -244,7 +244,7 @@ static int mpc8544_load_device_tree(CPUPPCState *env, /* XXX should contain a reasonable value */ qemu_devtree_setprop_cell(fdt, soc, "bus-frequency", 0); - snprintf(mpic, sizeof(mpic), "%s/pic@%x", soc, + snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc, MPC8544_MPIC_REGS_BASE - MPC8544_CCSRBAR_BASE); qemu_devtree_add_subnode(fdt, mpic); qemu_devtree_setprop_string(fdt, mpic, "device_type", "open-pic"); @@ -266,7 +266,7 @@ static int mpc8544_load_device_tree(CPUPPCState *env, * device it finds in the dt as serial output device. And we generate * devices in reverse order to the dt. */ - snprintf(ser1, sizeof(ser1), "%s/serial@%x", soc, + snprintf(ser1, sizeof(ser1), "%s/serial@%llx", soc, MPC8544_SERIAL1_REGS_BASE - MPC8544_CCSRBAR_BASE); qemu_devtree_add_subnode(fdt, ser1); qemu_devtree_setprop_string(fdt, ser1, "device_type", "serial"); @@ -279,7 +279,7 @@ static int mpc8544_load_device_tree(CPUPPCState *env, qemu_devtree_setprop_phandle(fdt, ser1, "interrupt-parent", mpic); qemu_devtree_setprop_string(fdt, "/aliases", "serial1", ser1); - snprintf(ser0, sizeof(ser0), "%s/serial@%x", soc, + snprintf(ser0, sizeof(ser0), "%s/serial@%llx", soc, MPC8544_SERIAL0_REGS_BASE - MPC8544_CCSRBAR_BASE); qemu_devtree_add_subnode(fdt, ser0); qemu_devtree_setprop_string(fdt, ser0, "device_type", "serial"); @@ -293,7 +293,7 @@ static int mpc8544_load_device_tree(CPUPPCState *env, qemu_devtree_setprop_string(fdt, "/aliases", "serial0", ser0); qemu_devtree_setprop_string(fdt, "/chosen", "linux,stdout-path", ser0); - snprintf(gutil, sizeof(gutil), "%s/global-utilities@%x", soc, + snprintf(gutil, sizeof(gutil), "%s/global-utilities@%llx", soc, MPC8544_UTIL_BASE - MPC8544_CCSRBAR_BASE); qemu_devtree_add_subnode(fdt, gutil); qemu_devtree_setprop_string(fdt, gutil, "compatible", "fsl,mpc8544-guts"); @@ -301,7 +301,7 @@ static int mpc8544_load_device_tree(CPUPPCState *env, MPC8544_CCSRBAR_BASE, 0x1000); qemu_devtree_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0); - snprintf(pci, sizeof(pci), "/pci@%x", MPC8544_PCI_REGS_BASE); + snprintf(pci, sizeof(pci), "/pci@%llx", MPC8544_PCI_REGS_BASE); qemu_devtree_add_subnode(fdt, pci); qemu_devtree_setprop_cell(fdt, pci, "cell-index", 0); qemu_devtree_setprop_string(fdt, pci, "compatible", "fsl,mpc8540-pci"); -- cgit v1.2.3 From 3627757e32e2c9fcee84e218746639aa2bfb1723 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 6 Jun 2012 00:25:06 +0200 Subject: PPC: e500: Extend address/size of / to 64bit We want to be able to support >= 4GB of RAM. To do so, we need to be able to tell the guest OS how much RAM it has. However, that information today is capped to 32bit. So let's extend the offset and size fields to 64bit, so we can fit in big addresses and even one day - if we wish to do so - map devices above 32bit. Signed-off-by: Alexander Graf --- hw/ppce500_mpc8544ds.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'hw') diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index c6a09bba3f..bf48bc7d75 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -90,7 +90,7 @@ static int mpc8544_load_device_tree(CPUPPCState *env, const char *kernel_cmdline) { int ret = -1; - uint32_t mem_reg_property[] = {0, cpu_to_be32(ramsize)}; + uint64_t mem_reg_property[] = { 0, cpu_to_be64(ramsize) }; int fdt_size; void *fdt; uint8_t hypercall[16]; @@ -108,9 +108,16 @@ static int mpc8544_load_device_tree(CPUPPCState *env, char gutil[128]; char pci[128]; uint32_t pci_map[9 * 8]; - uint32_t pci_ranges[12] = { 0x2000000, 0x0, 0xc0000000, 0xc0000000, 0x0, - 0x20000000, 0x1000000, 0x0, 0x0, 0xe1000000, - 0x0, 0x10000 }; + uint32_t pci_ranges[14] = + { + 0x2000000, 0x0, 0xc0000000, + 0x0, 0xc0000000, + 0x0, 0x20000000, + + 0x1000000, 0x0, 0x0, + 0x0, 0xe1000000, + 0x0, 0x10000, + }; QemuOpts *machine_opts; const char *dumpdtb = NULL; const char *dtb_file = NULL; @@ -144,8 +151,8 @@ static int mpc8544_load_device_tree(CPUPPCState *env, qemu_devtree_setprop_string(fdt, "/", "model", model); qemu_devtree_setprop(fdt, "/", "compatible", compatible, sizeof(compatible)); - qemu_devtree_setprop_cell(fdt, "/", "#address-cells", 1); - qemu_devtree_setprop_cell(fdt, "/", "#size-cells", 1); + qemu_devtree_setprop_cell(fdt, "/", "#address-cells", 2); + qemu_devtree_setprop_cell(fdt, "/", "#size-cells", 2); qemu_devtree_add_subnode(fdt, "/memory"); qemu_devtree_setprop_string(fdt, "/memory", "device_type", "memory"); @@ -239,7 +246,8 @@ static int mpc8544_load_device_tree(CPUPPCState *env, sizeof(compatible_sb)); qemu_devtree_setprop_cell(fdt, soc, "#address-cells", 1); qemu_devtree_setprop_cell(fdt, soc, "#size-cells", 1); - qemu_devtree_setprop_cells(fdt, soc, "ranges", 0x0, MPC8544_CCSRBAR_BASE, + qemu_devtree_setprop_cells(fdt, soc, "ranges", 0x0, + MPC8544_CCSRBAR_BASE >> 32, MPC8544_CCSRBAR_BASE, MPC8544_CCSRBAR_SIZE); /* XXX should contain a reasonable value */ qemu_devtree_setprop_cell(fdt, soc, "bus-frequency", 0); @@ -313,12 +321,12 @@ static int mpc8544_load_device_tree(CPUPPCState *env, qemu_devtree_setprop_phandle(fdt, pci, "interrupt-parent", mpic); qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2, 0, 0); qemu_devtree_setprop_cells(fdt, pci, "bus-range", 0, 255); - for (i = 0; i < 12; i++) { + for (i = 0; i < 14; i++) { pci_ranges[i] = cpu_to_be32(pci_ranges[i]); } qemu_devtree_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges)); - qemu_devtree_setprop_cells(fdt, pci, "reg", MPC8544_PCI_REGS_BASE, - 0x1000); + qemu_devtree_setprop_cells(fdt, pci, "reg", MPC8544_PCI_REGS_BASE >> 32, + MPC8544_PCI_REGS_BASE, 0, 0x1000); qemu_devtree_setprop_cell(fdt, pci, "clock-frequency", 66666666); qemu_devtree_setprop_cell(fdt, pci, "#interrupt-cells", 1); qemu_devtree_setprop_cell(fdt, pci, "#size-cells", 2); -- cgit v1.2.3 From a053a7cea61da679fe87ce491701f3874ae42371 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 6 Jun 2012 01:19:40 +0200 Subject: PPC: e500: Refactor serial dt generation When generating serial port device tree nodes, we duplicate quite a bit of code, because there are 2 of them in the mpc8544ds board we emulate. Shove the generating code into a function, so we duplicate less code. Signed-off-by: Alexander Graf --- hw/ppce500_mpc8544ds.c | 54 ++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 28 deletions(-) (limited to 'hw') diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index bf48bc7d75..f6da25bb65 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -82,6 +82,28 @@ static void pci_map_create(void *fdt, uint32_t *pci_map, uint32_t mpic) } } +static void dt_serial_create(void *fdt, unsigned long long offset, + const char *soc, const char *mpic, + const char *alias, int idx, bool defcon) +{ + char ser[128]; + + snprintf(ser, sizeof(ser), "%s/serial@%llx", soc, offset); + qemu_devtree_add_subnode(fdt, ser); + qemu_devtree_setprop_string(fdt, ser, "device_type", "serial"); + qemu_devtree_setprop_string(fdt, ser, "compatible", "ns16550"); + qemu_devtree_setprop_cells(fdt, ser, "reg", offset, 0x100); + qemu_devtree_setprop_cell(fdt, ser, "cell-index", idx); + qemu_devtree_setprop_cell(fdt, ser, "clock-frequency", 0); + qemu_devtree_setprop_cells(fdt, ser, "interrupts", 42, 2, 0, 0); + qemu_devtree_setprop_phandle(fdt, ser, "interrupt-parent", mpic); + qemu_devtree_setprop_string(fdt, "/aliases", alias, ser); + + if (defcon) { + qemu_devtree_setprop_string(fdt, "/chosen", "linux,stdout-path", ser); + } +} + static int mpc8544_load_device_tree(CPUPPCState *env, target_phys_addr_t addr, target_phys_addr_t ramsize, @@ -101,8 +123,6 @@ static int mpc8544_load_device_tree(CPUPPCState *env, char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus"; char model[] = "MPC8544DS"; char soc[128]; - char ser0[128]; - char ser1[128]; char mpic[128]; uint32_t mpic_ph; char gutil[128]; @@ -274,32 +294,10 @@ static int mpc8544_load_device_tree(CPUPPCState *env, * device it finds in the dt as serial output device. And we generate * devices in reverse order to the dt. */ - snprintf(ser1, sizeof(ser1), "%s/serial@%llx", soc, - MPC8544_SERIAL1_REGS_BASE - MPC8544_CCSRBAR_BASE); - qemu_devtree_add_subnode(fdt, ser1); - qemu_devtree_setprop_string(fdt, ser1, "device_type", "serial"); - qemu_devtree_setprop_string(fdt, ser1, "compatible", "ns16550"); - qemu_devtree_setprop_cells(fdt, ser1, "reg", MPC8544_SERIAL1_REGS_BASE - - MPC8544_CCSRBAR_BASE, 0x100); - qemu_devtree_setprop_cell(fdt, ser1, "cell-index", 1); - qemu_devtree_setprop_cell(fdt, ser1, "clock-frequency", 0); - qemu_devtree_setprop_cells(fdt, ser1, "interrupts", 42, 2, 0, 0); - qemu_devtree_setprop_phandle(fdt, ser1, "interrupt-parent", mpic); - qemu_devtree_setprop_string(fdt, "/aliases", "serial1", ser1); - - snprintf(ser0, sizeof(ser0), "%s/serial@%llx", soc, - MPC8544_SERIAL0_REGS_BASE - MPC8544_CCSRBAR_BASE); - qemu_devtree_add_subnode(fdt, ser0); - qemu_devtree_setprop_string(fdt, ser0, "device_type", "serial"); - qemu_devtree_setprop_string(fdt, ser0, "compatible", "ns16550"); - qemu_devtree_setprop_cells(fdt, ser0, "reg", MPC8544_SERIAL0_REGS_BASE - - MPC8544_CCSRBAR_BASE, 0x100); - qemu_devtree_setprop_cell(fdt, ser0, "cell-index", 0); - qemu_devtree_setprop_cell(fdt, ser0, "clock-frequency", 0); - qemu_devtree_setprop_cells(fdt, ser0, "interrupts", 42, 2, 0, 0); - qemu_devtree_setprop_phandle(fdt, ser0, "interrupt-parent", mpic); - qemu_devtree_setprop_string(fdt, "/aliases", "serial0", ser0); - qemu_devtree_setprop_string(fdt, "/chosen", "linux,stdout-path", ser0); + dt_serial_create(fdt, MPC8544_SERIAL1_REGS_BASE - MPC8544_CCSRBAR_BASE, + soc, mpic, "serial1", 1, false); + dt_serial_create(fdt, MPC8544_SERIAL0_REGS_BASE - MPC8544_CCSRBAR_BASE, + soc, mpic, "serial0", 0, true); snprintf(gutil, sizeof(gutil), "%s/global-utilities@%llx", soc, MPC8544_UTIL_BASE - MPC8544_CCSRBAR_BASE); -- cgit v1.2.3 From caedc737d27dd697641cb75ef6c5c27562c8044a Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 20 Jun 2012 20:46:22 +0200 Subject: PPC: e500: allow users to set the /compatible property via -machine Device trees usually have a node /compatible, which indicate which machine type we're looking at. For quick prototyping, it can be very useful to change the contents of that node via the command line. Thus, introduce a new option to -machine called dt_compatible, which when set changes the /compatible contents to its value. Signed-off-by: Alexander Graf --- hw/ppce500_mpc8544ds.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'hw') diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index f6da25bb65..d38ad99249 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -119,7 +119,8 @@ static int mpc8544_load_device_tree(CPUPPCState *env, uint32_t clock_freq = 400000000; uint32_t tb_freq = 400000000; int i; - char compatible[] = "MPC8544DS\0MPC85xxDS"; + const char *compatible = "MPC8544DS\0MPC85xxDS"; + int compatible_len = sizeof("MPC8544DS\0MPC85xxDS"); char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus"; char model[] = "MPC8544DS"; char soc[128]; @@ -144,8 +145,14 @@ static int mpc8544_load_device_tree(CPUPPCState *env, machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); if (machine_opts) { + const char *tmp; dumpdtb = qemu_opt_get(machine_opts, "dumpdtb"); dtb_file = qemu_opt_get(machine_opts, "dtb"); + tmp = qemu_opt_get(machine_opts, "dt_compatible"); + if (tmp) { + compatible = tmp; + compatible_len = strlen(compatible) + 1; + } } if (dtb_file) { @@ -169,8 +176,7 @@ static int mpc8544_load_device_tree(CPUPPCState *env, /* Manipulate device tree in memory. */ qemu_devtree_setprop_string(fdt, "/", "model", model); - qemu_devtree_setprop(fdt, "/", "compatible", compatible, - sizeof(compatible)); + qemu_devtree_setprop(fdt, "/", "compatible", compatible, compatible_len); qemu_devtree_setprop_cell(fdt, "/", "#address-cells", 2); qemu_devtree_setprop_cell(fdt, "/", "#size-cells", 2); -- cgit v1.2.3 From 5025d5421d3c6e705669f365192a7edf17b1aad8 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 20 Jun 2012 20:58:27 +0200 Subject: uImage: increase the gzip load size Recent u-boot has different defines for its gzip extract buffer, but the common ground seems to be 64MB. So let's bump it up to that, enabling me to load my test image again ;). Signed-off-by: Alexander Graf --- hw/loader.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/loader.c b/hw/loader.c index 7d64113e7f..33acc2fdab 100644 --- a/hw/loader.c +++ b/hw/loader.c @@ -377,9 +377,9 @@ static void zfree(void *x, void *addr) #define DEFLATED 8 -/* This is the maximum in uboot, so if a uImage overflows this, it would +/* This is the usual maximum in uboot, so if a uImage overflows this, it would * overflow on real hardware too. */ -#define UBOOT_MAX_GUNZIP_BYTES 0x800000 +#define UBOOT_MAX_GUNZIP_BYTES (64 << 20) static ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src, size_t srclen) -- cgit v1.2.3 From 2a7a47fc6c19703a849a34243701a09052cb1bc6 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 20 Jun 2012 21:27:02 +0200 Subject: PPC: BookE: Implement EPR SPR On the e500 series, accessing SPR_EPR magically turns into an access at that CPU's IACK register on the MPIC. Implement that logic to get kernels that make use of that feature work. Signed-off-by: Alexander Graf --- hw/ppce500_mpc8544ds.c | 1 + 1 file changed, 1 insertion(+) (limited to 'hw') diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index d38ad99249..8b9fd83ce1 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -469,6 +469,7 @@ static void mpc8544ds_init(ram_addr_t ram_size, irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT]; irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT]; env->spr[SPR_BOOKE_PIR] = env->cpu_index = i; + env->mpic_cpu_base = MPC8544_MPIC_REGS_BASE + 0x20000; ppc_booke_timers_init(env, 400000000, PPC_TIMER_E500); -- cgit v1.2.3