ia64/xen-unstable
changeset 10748:050de6b53961
[powerpc] Initial checkin of new powerpc files.
From: Hollis Blanchard et al (IBM)
Signed-off-by: Keir Fraser <keir@xensource.com>
From: Hollis Blanchard et al (IBM)
Signed-off-by: Keir Fraser <keir@xensource.com>
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/config/powerpc64.mk Fri Jul 14 10:47:50 2006 +0100 1.3 @@ -0,0 +1,4 @@ 1.4 +CONFIG_POWERPC := y 1.5 + 1.6 +CFLAGS += -DELFSIZE=64 1.7 +LIBDIR := lib
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/tools/libxc/xc_ppc_linux_build.c Fri Jul 14 10:47:50 2006 +0100 2.3 @@ -0,0 +1,408 @@ 2.4 +/* 2.5 + * This program is free software; you can redistribute it and/or modify 2.6 + * it under the terms of the GNU General Public License as published by 2.7 + * the Free Software Foundation; either version 2 of the License, or 2.8 + * (at your option) any later version. 2.9 + * 2.10 + * This program is distributed in the hope that it will be useful, 2.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 2.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 2.13 + * GNU General Public License for more details. 2.14 + * 2.15 + * You should have received a copy of the GNU General Public License 2.16 + * along with this program; if not, write to the Free Software 2.17 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 2.18 + * 2.19 + * Copyright (C) IBM Corporation 2006 2.20 + * 2.21 + * Authors: Hollis Blanchard <hollisb@us.ibm.com> 2.22 + */ 2.23 + 2.24 +#include <stdio.h> 2.25 +#include <stdint.h> 2.26 +#include <stdlib.h> 2.27 +#include <string.h> 2.28 +#include <unistd.h> 2.29 +#include <fcntl.h> 2.30 +#include <sys/types.h> 2.31 +#include <inttypes.h> 2.32 + 2.33 +#include <xen/dom0_ops.h> 2.34 +#include <xen/memory.h> 2.35 +#include <xc_private.h> 2.36 +#include <xg_private.h> 2.37 +#include <xenctrl.h> 2.38 + 2.39 +/* XXX 64M hack */ 2.40 +#define MEMSIZE (64UL << 20) 2.41 +#define INITRD_ADDR (24UL << 20) 2.42 + 2.43 +int verbose; 2.44 +#define VERBOSE(stuff, ...) \ 2.45 + if (verbose) \ 2.46 + stuff __VA_ARGS__; 2.47 + 2.48 +#define ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1))) 2.49 + 2.50 +#define max(x,y) ({ \ 2.51 + const typeof(x) _x = (x); \ 2.52 + const typeof(y) _y = (y); \ 2.53 + (void) (&_x == &_y); \ 2.54 + _x > _y ? _x : _y; }) 2.55 + 2.56 +static void *load_file(const char *path, unsigned long *filesize) 2.57 +{ 2.58 + void *img; 2.59 + ssize_t size; 2.60 + int fd; 2.61 + 2.62 + VERBOSE(printf("load_file(%s)\n", path)); 2.63 + 2.64 + fd = open(path, O_RDONLY); 2.65 + if (fd < 0) { 2.66 + perror(path); 2.67 + return NULL; 2.68 + } 2.69 + 2.70 + size = lseek(fd, 0, SEEK_END); 2.71 + if (size < 0) { 2.72 + perror(path); 2.73 + close(fd); 2.74 + return NULL; 2.75 + } 2.76 + lseek(fd, 0, SEEK_SET); 2.77 + 2.78 + img = malloc(size); 2.79 + if (img == NULL) { 2.80 + perror(path); 2.81 + close(fd); 2.82 + return NULL; 2.83 + } 2.84 + 2.85 + size = read(fd, img, size); 2.86 + if (size <= 0) { 2.87 + perror(path); 2.88 + close(fd); 2.89 + free(img); 2.90 + return NULL; 2.91 + } 2.92 + 2.93 + if (filesize) 2.94 + *filesize = size; 2.95 + close(fd); 2.96 + return img; 2.97 +} 2.98 + 2.99 +static int init_boot_vcpu( 2.100 + int xc_handle, 2.101 + int domid, 2.102 + struct domain_setup_info *dsi, 2.103 + unsigned long dtb, 2.104 + unsigned long kaddr) 2.105 +{ 2.106 + vcpu_guest_context_t ctxt; 2.107 + int rc; 2.108 + 2.109 + memset(&ctxt.user_regs, 0x55, sizeof(ctxt.user_regs)); 2.110 + ctxt.user_regs.pc = dsi->v_kernentry; 2.111 + ctxt.user_regs.msr = 0; 2.112 + ctxt.user_regs.gprs[1] = 32<<20; /* XXX arbitrary stack address */ 2.113 + ctxt.user_regs.gprs[3] = dtb; 2.114 + ctxt.user_regs.gprs[4] = kaddr; 2.115 + ctxt.user_regs.gprs[5] = 0; 2.116 + 2.117 + VERBOSE(printf("xc_vcpu_setvcpucontext:\n" 2.118 + " pc 0x%"PRIx64", msr 0x016%"PRIx64"\n" 2.119 + " r1-5 %016"PRIx64" %016"PRIx64" %016"PRIx64" %016"PRIx64 2.120 + " %016"PRIx64"\n", 2.121 + ctxt.user_regs.pc, ctxt.user_regs.msr, 2.122 + ctxt.user_regs.gprs[1], 2.123 + ctxt.user_regs.gprs[2], 2.124 + ctxt.user_regs.gprs[3], 2.125 + ctxt.user_regs.gprs[4], 2.126 + ctxt.user_regs.gprs[5])); 2.127 + rc = xc_vcpu_setcontext(xc_handle, domid, 0, &ctxt); 2.128 + if (rc < 0) 2.129 + perror("setdomaininfo"); 2.130 + 2.131 + return rc; 2.132 +} 2.133 + 2.134 +static int install_image( 2.135 + int xc_handle, 2.136 + int domid, 2.137 + xen_pfn_t *page_array, 2.138 + void *image, 2.139 + unsigned long paddr, 2.140 + unsigned long size) 2.141 +{ 2.142 + uint8_t *img = image; 2.143 + int i; 2.144 + int rc = 0; 2.145 + 2.146 + if (paddr & ~PAGE_MASK) { 2.147 + printf("*** unaligned address\n"); 2.148 + return -1; 2.149 + } 2.150 + 2.151 + for (i = 0; i < size; i += PAGE_SIZE) { 2.152 + void *page = img + i; 2.153 + xen_pfn_t pfn = (paddr + i) >> PAGE_SHIFT; 2.154 + xen_pfn_t mfn = page_array[pfn]; 2.155 + 2.156 + rc = xc_copy_to_domain_page(xc_handle, domid, mfn, page); 2.157 + if (rc < 0) { 2.158 + perror("xc_copy_to_domain_page"); 2.159 + break; 2.160 + } 2.161 + } 2.162 + return rc; 2.163 +} 2.164 + 2.165 +/* XXX be more flexible about placement in memory */ 2.166 +static int load_dtb( 2.167 + int xc_handle, 2.168 + int domid, 2.169 + const char *dtb_path, 2.170 + unsigned long dtb_addr, 2.171 + struct domain_setup_info *dsi, 2.172 + xen_pfn_t *page_array) 2.173 +{ 2.174 + uint8_t *img; 2.175 + unsigned long dtb_size; 2.176 + int rc = 0; 2.177 + 2.178 + img = load_file(dtb_path, &dtb_size); 2.179 + if (img == NULL) { 2.180 + rc = -1; 2.181 + goto out; 2.182 + } 2.183 + 2.184 + VERBOSE(printf("copying device tree to 0x%lx[0x%lx]\n", 2.185 + dtb_addr, dtb_size)); 2.186 + rc = install_image(xc_handle, domid, page_array, img, dtb_addr, dtb_size); 2.187 + 2.188 +out: 2.189 + free(img); 2.190 + return rc; 2.191 +} 2.192 + 2.193 +unsigned long spin_list[] = { 2.194 +#if 0 2.195 + 0x100, 2.196 + 0x200, 2.197 + 0x300, 2.198 + 0x380, 2.199 + 0x400, 2.200 + 0x480, 2.201 + 0x500, 2.202 + 0x700, 2.203 + 0x900, 2.204 + 0xc00, 2.205 +#endif 2.206 + 0 2.207 +}; 2.208 + 2.209 +/* XXX yes, this is a hack */ 2.210 +static void hack_kernel_img(char *img) 2.211 +{ 2.212 + const off_t file_offset = 0x10000; 2.213 + unsigned long *addr = spin_list; 2.214 + 2.215 + while (*addr) { 2.216 + uint32_t *instruction = (uint32_t *)(img + *addr + file_offset); 2.217 + printf("installing spin loop at %lx (%x)\n", *addr, *instruction); 2.218 + *instruction = 0x48000000; 2.219 + addr++; 2.220 + } 2.221 +} 2.222 + 2.223 +static int load_kernel( 2.224 + int xc_handle, 2.225 + int domid, 2.226 + const char *kernel_path, 2.227 + struct domain_setup_info *dsi, 2.228 + xen_pfn_t *page_array) 2.229 +{ 2.230 + struct load_funcs load_funcs; 2.231 + char *kernel_img; 2.232 + unsigned long kernel_size; 2.233 + int rc; 2.234 + 2.235 + /* load the kernel ELF file */ 2.236 + kernel_img = load_file(kernel_path, &kernel_size); 2.237 + if (kernel_img == NULL) { 2.238 + rc = -1; 2.239 + goto out; 2.240 + } 2.241 + 2.242 + hack_kernel_img(kernel_img); 2.243 + 2.244 + VERBOSE(printf("probe_elf\n")); 2.245 + rc = probe_elf(kernel_img, kernel_size, &load_funcs); 2.246 + if (rc < 0) { 2.247 + rc = -1; 2.248 + printf("%s is not an ELF file\n", kernel_path); 2.249 + goto out; 2.250 + } 2.251 + 2.252 + VERBOSE(printf("parseimage\n")); 2.253 + rc = (load_funcs.parseimage)(kernel_img, kernel_size, dsi); 2.254 + if (rc < 0) { 2.255 + rc = -1; 2.256 + goto out; 2.257 + } 2.258 + 2.259 + VERBOSE(printf("loadimage\n")); 2.260 + (load_funcs.loadimage)(kernel_img, kernel_size, xc_handle, domid, 2.261 + page_array, dsi); 2.262 + 2.263 + VERBOSE(printf(" v_start %016"PRIx64"\n", dsi->v_start)); 2.264 + VERBOSE(printf(" v_end %016"PRIx64"\n", dsi->v_end)); 2.265 + VERBOSE(printf(" v_kernstart %016"PRIx64"\n", dsi->v_kernstart)); 2.266 + VERBOSE(printf(" v_kernend %016"PRIx64"\n", dsi->v_kernend)); 2.267 + VERBOSE(printf(" v_kernentry %016"PRIx64"\n", dsi->v_kernentry)); 2.268 + 2.269 +out: 2.270 + free(kernel_img); 2.271 + return rc; 2.272 +} 2.273 + 2.274 +static int load_initrd( 2.275 + int xc_handle, 2.276 + int domid, 2.277 + xen_pfn_t *page_array, 2.278 + const char *initrd_path, 2.279 + unsigned long *base, 2.280 + unsigned long *len) 2.281 +{ 2.282 + uint8_t *initrd_img; 2.283 + int rc = -1; 2.284 + 2.285 + /* load the initrd file */ 2.286 + initrd_img = load_file(initrd_path, len); 2.287 + if (initrd_img == NULL) 2.288 + return -1; 2.289 + 2.290 + VERBOSE(printf("copying initrd to 0x%lx[0x%lx]\n", INITRD_ADDR, *len)); 2.291 + if (install_image(xc_handle, domid, page_array, initrd_img, INITRD_ADDR, 2.292 + *len)) 2.293 + goto out; 2.294 + 2.295 + *base = INITRD_ADDR; 2.296 + rc = 0; 2.297 + 2.298 +out: 2.299 + free(initrd_img); 2.300 + return rc; 2.301 +} 2.302 + 2.303 +static unsigned long create_start_info(start_info_t *si, 2.304 + unsigned int console_evtchn, unsigned int store_evtchn) 2.305 +{ 2.306 + unsigned long eomem; 2.307 + unsigned long si_addr; 2.308 + 2.309 + memset(si, 0, sizeof(*si)); 2.310 + snprintf(si->magic, sizeof(si->magic), "xen-%d.%d-powerpc64HV", 3, 0); 2.311 + 2.312 + eomem = MEMSIZE; 2.313 + si->nr_pages = eomem >> PAGE_SHIFT; 2.314 + si->shared_info = eomem - (PAGE_SIZE * 1); 2.315 + si->store_mfn = si->nr_pages - 2; 2.316 + si->store_evtchn = store_evtchn; 2.317 + si->console_mfn = si->nr_pages - 3; 2.318 + si->console_evtchn = console_evtchn; 2.319 + si_addr = eomem - (PAGE_SIZE * 4); 2.320 + 2.321 + return si_addr; 2.322 +} 2.323 + 2.324 +static int get_page_array(int xc_handle, int domid, xen_pfn_t **page_array) 2.325 +{ 2.326 + int nr_pages; 2.327 + int rc; 2.328 + 2.329 + VERBOSE(printf("xc_get_tot_pages\n")); 2.330 + nr_pages = xc_get_tot_pages(xc_handle, domid); 2.331 + VERBOSE(printf(" 0x%x\n", nr_pages)); 2.332 + 2.333 + *page_array = malloc(nr_pages * sizeof(xen_pfn_t)); 2.334 + if (*page_array == NULL) { 2.335 + perror("malloc"); 2.336 + return -1; 2.337 + } 2.338 + 2.339 + VERBOSE(printf("xc_get_pfn_list\n")); 2.340 + rc = xc_get_pfn_list(xc_handle, domid, *page_array, nr_pages); 2.341 + if (rc != nr_pages) { 2.342 + perror("Could not get the page frame list"); 2.343 + return -1; 2.344 + } 2.345 + 2.346 + return 0; 2.347 +} 2.348 + 2.349 +int xc_linux_build(int xc_handle, 2.350 + uint32_t domid, 2.351 + const char *image_name, 2.352 + const char *initrd_name, 2.353 + const char *cmdline, 2.354 + const char *features, 2.355 + unsigned long flags, 2.356 + unsigned int store_evtchn, 2.357 + unsigned long *store_mfn, 2.358 + unsigned int console_evtchn, 2.359 + unsigned long *console_mfn) 2.360 +{ 2.361 + struct domain_setup_info dsi; 2.362 + xen_pfn_t *page_array = NULL; 2.363 + unsigned long kern_addr; 2.364 + unsigned long dtb_addr; 2.365 + unsigned long si_addr; 2.366 + unsigned long initrd_base = 0; 2.367 + unsigned long initrd_len = 0; 2.368 + start_info_t si; 2.369 + int rc = 0; 2.370 + 2.371 + if (get_page_array(xc_handle, domid, &page_array)) { 2.372 + rc = -1; 2.373 + goto out; 2.374 + } 2.375 + 2.376 + if (load_kernel(xc_handle, domid, image_name, &dsi, page_array)) { 2.377 + rc = -1; 2.378 + goto out; 2.379 + } 2.380 + kern_addr = 0; 2.381 + 2.382 + if (initrd_name && initrd_name[0] != '\0' && 2.383 + load_initrd(xc_handle, domid, page_array, initrd_name, &initrd_base, 2.384 + &initrd_len)) { 2.385 + rc = -1; 2.386 + goto out; 2.387 + } 2.388 + /* XXX install initrd addr/len into device tree */ 2.389 + 2.390 + dtb_addr = (16 << 20); 2.391 + if (load_dtb(xc_handle, domid, "DomU.dtb", dtb_addr, &dsi, page_array)) { 2.392 + dtb_addr = 0; 2.393 + } 2.394 + 2.395 + si_addr = create_start_info(&si, store_evtchn, console_evtchn); 2.396 + *console_mfn = si.console_mfn; 2.397 + *store_mfn = si.store_mfn; 2.398 + if (install_image(xc_handle, domid, page_array, &si, si_addr, 2.399 + sizeof(start_info_t))) { 2.400 + rc = -1; 2.401 + goto out; 2.402 + } 2.403 + 2.404 + if (init_boot_vcpu(xc_handle, domid, &dsi, dtb_addr, kern_addr)) { 2.405 + rc = -1; 2.406 + goto out; 2.407 + } 2.408 + 2.409 +out: 2.410 + return rc; 2.411 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/xen/arch/powerpc/0opt.c Fri Jul 14 10:47:50 2006 +0100 3.3 @@ -0,0 +1,28 @@ 3.4 +/* 3.5 + * This program is free software; you can redistribute it and/or modify 3.6 + * it under the terms of the GNU General Public License as published by 3.7 + * the Free Software Foundation; either version 2 of the License, or 3.8 + * (at your option) any later version. 3.9 + * 3.10 + * This program is distributed in the hope that it will be useful, 3.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 3.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 3.13 + * GNU General Public License for more details. 3.14 + * 3.15 + * You should have received a copy of the GNU General Public License 3.16 + * along with this program; if not, write to the Free Software 3.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 3.18 + * 3.19 + * Copyright (C) IBM Corp. 2005 3.20 + * 3.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 3.22 + */ 3.23 + 3.24 +#include <xen/config.h> 3.25 +#include <asm/misc.h> 3.26 + 3.27 +extern void __cmpxchg_called_with_bad_pointer(void); 3.28 +void __cmpxchg_called_with_bad_pointer(void) 3.29 +{ 3.30 + trap(); 3.31 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/xen/arch/powerpc/Makefile Fri Jul 14 10:47:50 2006 +0100 4.3 @@ -0,0 +1,117 @@ 4.4 +ifneq ($(DOM0_IMAGE),) 4.5 +builtin_dom0 := y 4.6 +endif 4.7 + 4.8 +subdir-$(HAS_PPC64) += powerpc64 4.9 +subdir-y += papr 4.10 + 4.11 +obj-y += audit.o 4.12 +obj-y += bitops.o 4.13 +obj-y += boot_of.o 4.14 +obj-y += dart.o 4.15 +obj-y += dart_u3.o 4.16 +obj-y += dart_u4.o 4.17 +obj-y += delay.o 4.18 +obj-y += dom0_ops.o 4.19 +obj-y += domain_build.o 4.20 +obj-y += domain.o 4.21 +obj-y += exceptions.o 4.22 +obj-y += external.o 4.23 +obj-y += float.o 4.24 +obj-y += hcalls.o 4.25 +obj-y += htab.o 4.26 +obj-y += iommu.o 4.27 +obj-y += irq.o 4.28 +obj-y += mambo.o 4.29 +obj-y += mm.o 4.30 +obj-y += mpic.o 4.31 +obj-y += mpic_init.o 4.32 +obj-y += of-devtree.o 4.33 +obj-y += of-devwalk.o 4.34 +obj-y += ofd_fixup.o 4.35 +obj-y += physdev.o 4.36 +obj-y += rtas.o 4.37 +obj-y += setup.o 4.38 +obj-y += smp.o 4.39 +obj-y += time.o 4.40 +obj-y += usercopy.o 4.41 + 4.42 +obj-$(debug) += 0opt.o 4.43 +obj-$(crash_debug) += gdbstub.o 4.44 +obj-$(builtin_dom0) += dom0.o 4.45 + 4.46 +obj-y += firmware_image.o 4.47 + 4.48 +obj-y += elf32.o 4.49 + 4.50 +# These are extra warnings like for the arch/ppc directory but may not 4.51 +# allow the rest of the tree to build. 4.52 +PPC_C_WARNINGS += -Wundef -Wmissing-prototypes -Wmissing-declarations 4.53 +CFLAGS += $(PPC_C_WARNINGS) 4.54 + 4.55 +LINK=0x3000000 4.56 +boot32_link_base = $(LINK) 4.57 +xen_link_offset = 100 4.58 +xen_link_base = $(patsubst %000,%$(xen_link_offset),$(LINK)) 4.59 + 4.60 +# 4.61 +# The following flags are fed to gcc in order to link several 4.62 +# objects into a single ELF segment and to not link in any additional 4.63 +# objects that gcc would normally like to 4.64 +# 4.65 +OMAGIC = -N -nodefaultlibs -nostartfiles 4.66 + 4.67 +firmware: of_handler/built_in.o $(TARGET_SUBARCH)/memcpy.o of-devtree.o 4.68 + $(CC) $(CFLAGS) $(OMAGIC) -e __ofh_start -Wl,-Ttext,0x0 $^ -o $@ 4.69 + 4.70 +firmware_image: firmware 4.71 + $(CROSS_COMPILE)objcopy --output-target=binary $< $@ 4.72 + 4.73 +firmware_image.o: firmware_image 4.74 + $(CROSS_COMPILE)objcopy --input-target=binary \ 4.75 + --output-target=elf64-powerpc \ 4.76 + --binary-architecture=powerpc \ 4.77 + --redefine-sym _binary_$<_start=$(@:%.o=%)_start \ 4.78 + --redefine-sym _binary_$<_end=$(@:%.o=%)_end \ 4.79 + --redefine-sym _binary_$<_size=$(@:%.o=%)_size $< $@ 4.80 + 4.81 +# 4.82 +# Hacks for included C files 4.83 +# 4.84 +irq.o: ../x86/irq.c 4.85 +physdev.o: ../x86/physdev.c 4.86 + 4.87 +HDRS += $(wildcard *.h) 4.88 + 4.89 +start.o: boot/start.S 4.90 + $(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $@ 4.91 + 4.92 +$(TARGET)-syms: start.o $(ALL_OBJS) xen.lds 4.93 + $(CC) $(CFLAGS) $(OMAGIC) -Wl,-Ttext,$(xen_link_base),-T,xen.lds start.o $(ALL_OBJS) -o $@ 4.94 + 4.95 +$(TARGET).bin: $(TARGET)-syms 4.96 + $(CROSS_COMPILE)objcopy --output-target=binary $< $@ 4.97 + 4.98 +$(TARGET).bin.o: $(TARGET).bin 4.99 + $(CROSS_COMPILE)objcopy --input-target=binary \ 4.100 + --output-target=elf32-powerpc \ 4.101 + --binary-architecture=powerpc $< $@ 4.102 + 4.103 +boot32.o: boot/boot32.S 4.104 + $(CC) -m32 -Wa,-a32,-mppc64bridge \ 4.105 + -D__ASSEMBLY__ -D__BRIDGE64__ $(CFLAGS) -c $< -o $@ 4.106 + 4.107 +$(TARGET): boot32.o $(TARGET).bin.o 4.108 + $(CC) -m32 -N -Wl,-melf32ppclinux -static -nostdlib \ 4.109 + -Wl,-Ttext,$(boot32_link_base) -Wl,-Tdata,$(xen_link_base) \ 4.110 + $(CFLAGS) $^ -o $@ 4.111 + 4.112 +asm-offsets.s: $(TARGET_SUBARCH)/asm-offsets.c $(HDRS) 4.113 + $(CC) $(CFLAGS) -S -o $@ $< 4.114 + 4.115 +dom0.bin: $(DOM0_IMAGE) 4.116 + cp $< $@ 4.117 + 4.118 +clean:: 4.119 + $(MAKE) -f $(BASEDIR)/Rules.mk -C of_handler clean 4.120 + rm -f firmware firmware_image dom0.bin
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/xen/arch/powerpc/Rules.mk Fri Jul 14 10:47:50 2006 +0100 5.3 @@ -0,0 +1,51 @@ 5.4 +HAS_PPC64 := y 5.5 + 5.6 +CC := $(CROSS_COMPILE)gcc 5.7 +LD := $(CROSS_COMPILE)ld 5.8 + 5.9 +# These are goodess that applies to all source. 5.10 +C_WARNINGS := -Wpointer-arith -Wredundant-decls 5.11 + 5.12 +# _no_ common code can have packed data structures or we are in touble. 5.13 +C_WARNINGS += -Wpacked 5.14 + 5.15 +CFLAGS := -m64 -ffreestanding -fno-builtin -fno-common -fno-strict-aliasing 5.16 +CFLAGS += -iwithprefix include -Wall -Werror -pipe 5.17 +CFLAGS += -I$(BASEDIR)/include 5.18 +CFLAGS += -I$(BASEDIR)/include/asm-powerpc/mach-generic 5.19 +CFLAGS += -I$(BASEDIR)/include/asm-powerpc/mach-default 5.20 +CFLAGS += $(C_WARNINGS) 5.21 +CFLAGS += -msoft-float -O2 5.22 +CFLAGS-$(debug) += -O0 # last one wins 5.23 +CFLAGS-$(papr_vterm) += -DPAPR_VDEVICE -DPAPR_VTERM 5.24 + 5.25 +LDFLAGS += -m elf64ppc 5.26 + 5.27 +# 5.28 +# command to embed a binary inside a .o 5.29 +# 5.30 +%.o: %.bin 5.31 + $(CROSS_COMPILE)objcopy --input-target=binary \ 5.32 + --output-target=elf64-powerpc \ 5.33 + --binary-architecture=powerpc \ 5.34 + --redefine-sym _binary_$*_bin_start=$*_start \ 5.35 + --redefine-sym _binary_$*_bin_end=$*_end \ 5.36 + --redefine-sym _binary_$*_bin_size=$*_size \ 5.37 + $< $@ 5.38 + 5.39 +# Test for at least GCC v3.2.x. 5.40 +gcc-ver = $(shell $(CC) -dumpversion | sed -e 's/^\(.\)\.\(.\)\.\(.\)/\$(1)/') 5.41 +ifeq ($(call gcc-ver,1),1) 5.42 +$(error gcc-1.x.x unsupported - upgrade to at least gcc-3.2.x) 5.43 +endif 5.44 +ifeq ($(call gcc-ver,1),2) 5.45 +$(error gcc-2.x.x unsupported - upgrade to at least gcc-3.2.x) 5.46 +endif 5.47 +ifeq ($(call gcc-ver,1),3) 5.48 +ifeq ($(call gcc-ver,2),0) 5.49 +$(error gcc-3.0.x unsupported - upgrade to at least gcc-3.2.x) 5.50 +endif 5.51 +ifeq ($(call gcc-ver,2),1) 5.52 +$(error gcc-3.1.x unsupported - upgrade to at least gcc-3.2.x) 5.53 +endif 5.54 +endif
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/xen/arch/powerpc/audit.c Fri Jul 14 10:47:50 2006 +0100 6.3 @@ -0,0 +1,45 @@ 6.4 +/* 6.5 + * This program is free software; you can redistribute it and/or modify 6.6 + * it under the terms of the GNU General Public License as published by 6.7 + * the Free Software Foundation; either version 2 of the License, or 6.8 + * (at your option) any later version. 6.9 + * 6.10 + * This program is distributed in the hope that it will be useful, 6.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 6.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 6.13 + * GNU General Public License for more details. 6.14 + * 6.15 + * You should have received a copy of the GNU General Public License 6.16 + * along with this program; if not, write to the Free Software 6.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 6.18 + * 6.19 + * Copyright (C) IBM Corp. 2005 6.20 + * 6.21 + * Authors: Hollis Blanchard <hollisb@us.ibm.com> 6.22 + */ 6.23 + 6.24 +#ifndef NDEBUG 6.25 +#include <xen/lib.h> 6.26 +#include <xen/sched.h> 6.27 + 6.28 +extern void audit_domain(struct domain *d); 6.29 +extern void audit_domains(void); 6.30 +extern void audit_domains_key(unsigned char key); 6.31 + 6.32 +void audit_domain(struct domain *d) 6.33 +{ 6.34 + panic("%s unimplemented\n", __func__); 6.35 +} 6.36 + 6.37 +void audit_domains(void) 6.38 +{ 6.39 + struct domain *d; 6.40 + for_each_domain ( d ) 6.41 + audit_domain(d); 6.42 +} 6.43 + 6.44 +void audit_domains_key(unsigned char key) 6.45 +{ 6.46 + audit_domains(); 6.47 +} 6.48 +#endif
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/xen/arch/powerpc/bitops.c Fri Jul 14 10:47:50 2006 +0100 7.3 @@ -0,0 +1,94 @@ 7.4 +/* from linux/arch/powerpc/lib/bitops.c */ 7.5 + 7.6 +#include <asm/types.h> 7.7 +#include <asm/bitops.h> 7.8 + 7.9 +#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) 7.10 + 7.11 +/** 7.12 + * find_next_bit - find the next set bit in a memory region 7.13 + * @addr: The address to base the search on 7.14 + * @offset: The bitnumber to start searching at 7.15 + * @size: The maximum size to search 7.16 + */ 7.17 +unsigned long find_next_bit(const unsigned long *addr, unsigned long size, 7.18 + unsigned long offset) 7.19 +{ 7.20 + const unsigned long *p = addr + BITOP_WORD(offset); 7.21 + unsigned long result = offset & ~(BITS_PER_LONG-1); 7.22 + unsigned long tmp; 7.23 + 7.24 + if (offset >= size) 7.25 + return size; 7.26 + size -= result; 7.27 + offset %= BITS_PER_LONG; 7.28 + if (offset) { 7.29 + tmp = *(p++); 7.30 + tmp &= (~0UL << offset); 7.31 + if (size < BITS_PER_LONG) 7.32 + goto found_first; 7.33 + if (tmp) 7.34 + goto found_middle; 7.35 + size -= BITS_PER_LONG; 7.36 + result += BITS_PER_LONG; 7.37 + } 7.38 + while (size & ~(BITS_PER_LONG-1)) { 7.39 + if ((tmp = *(p++))) 7.40 + goto found_middle; 7.41 + result += BITS_PER_LONG; 7.42 + size -= BITS_PER_LONG; 7.43 + } 7.44 + if (!size) 7.45 + return result; 7.46 + tmp = *p; 7.47 + 7.48 +found_first: 7.49 + tmp &= (~0UL >> (BITS_PER_LONG - size)); 7.50 + if (tmp == 0UL) /* Are any bits set? */ 7.51 + return result + size; /* Nope. */ 7.52 +found_middle: 7.53 + return result + __ffs(tmp); 7.54 +} 7.55 + 7.56 +/* 7.57 + * This implementation of find_{first,next}_zero_bit was stolen from 7.58 + * Linus' asm-alpha/bitops.h. 7.59 + */ 7.60 +unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, 7.61 + unsigned long offset) 7.62 +{ 7.63 + const unsigned long *p = addr + BITOP_WORD(offset); 7.64 + unsigned long result = offset & ~(BITS_PER_LONG-1); 7.65 + unsigned long tmp; 7.66 + 7.67 + if (offset >= size) 7.68 + return size; 7.69 + size -= result; 7.70 + offset %= BITS_PER_LONG; 7.71 + if (offset) { 7.72 + tmp = *(p++); 7.73 + tmp |= ~0UL >> (BITS_PER_LONG - offset); 7.74 + if (size < BITS_PER_LONG) 7.75 + goto found_first; 7.76 + if (~tmp) 7.77 + goto found_middle; 7.78 + size -= BITS_PER_LONG; 7.79 + result += BITS_PER_LONG; 7.80 + } 7.81 + while (size & ~(BITS_PER_LONG-1)) { 7.82 + if (~(tmp = *(p++))) 7.83 + goto found_middle; 7.84 + result += BITS_PER_LONG; 7.85 + size -= BITS_PER_LONG; 7.86 + } 7.87 + if (!size) 7.88 + return result; 7.89 + tmp = *p; 7.90 + 7.91 +found_first: 7.92 + tmp |= ~0UL << size; 7.93 + if (tmp == ~0UL) /* Are any bits zero? */ 7.94 + return result + size; /* Nope. */ 7.95 +found_middle: 7.96 + return result + ffz(tmp); 7.97 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/xen/arch/powerpc/boot/boot32.S Fri Jul 14 10:47:50 2006 +0100 8.3 @@ -0,0 +1,75 @@ 8.4 +/* 8.5 + * Copyright (C) 2005 Jimi Xenidis <jimix@watson.ibm.com>, IBM Corporation 8.6 + * 8.7 + * This program is free software; you can redistribute it and/or modify 8.8 + * it under the terms of the GNU General Public License as published by 8.9 + * the Free Software Foundation; either version 2 of the License, or 8.10 + * (at your option) any later version. 8.11 + * 8.12 + * This program is distributed in the hope that it will be useful, 8.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 8.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 8.15 + * GNU General Public License for more details. 8.16 + * 8.17 + * You should have received a copy of the GNU General Public License 8.18 + * along with this program; if not, write to the Free Software 8.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 8.20 + * 8.21 + */ 8.22 + 8.23 +### 32 bit strapping code so Of will like us 8.24 + .section ".text" 8.25 + .align 3 8.26 + .globl _start 8.27 + 8.28 +_start: 8.29 + ## Double word align the MSR value below 8.30 + nop 8.31 + bl _real_start 8.32 + ## static value for MSR 8.33 + .llong 0x9000000000001000 8.34 + 8.35 + ## see also docs/reference/ppc/msr.txt 8.36 +##bit C Hex Name Desc 8.37 +## 0 63 80000000 00000000 SF 64-bit Mode 8.38 +## 3 60 10000000 00000000 HV Hypervisor State iff PR = 0 in hypervisor state. 8.39 +## 51 12 00000000 00001000 ME Machine Check Enable 8.40 + 8.41 +_real_start: 8.42 + # pass the original msr as argument to hype_init 8.43 + mfmsr 8 8.44 + 8.45 + ## Set PC 8.46 + li 21, 0 8.47 + oris 21, 21, _hype64@h 8.48 + ori 21, 21, _hype64@l 8.49 +#ifdef __BRIDGE64__ 8.50 + ## In 64bit we use rfid to switch from 32bit to 64 bit 8.51 + mtsrr0 21 8.52 + 8.53 + ## Set MSR 8.54 + mflr 21 8.55 + ld 22, 0(21) 8.56 + mtsrr1 22 8.57 + bl __leap 8.58 + /* should never return */ 8.59 + trap 8.60 +__leap: 8.61 + rfid 8.62 +#else 8.63 + mtctr 21 8.64 + bctrl 8.65 + /* should never return */ 8.66 + trap 8.67 +#endif 8.68 + 8.69 + 8.70 +_real_end: 8.71 + .data 8.72 + .align 3 8.73 + ## Hypervisor starts here, at the first data address 8.74 + ## linker magic positions _hype64 0x100 after _start 8.75 + ## hype/ppc64/Makefile.isa 8.76 +_hype64: 8.77 + 8.78 +
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/xen/arch/powerpc/boot/start.S Fri Jul 14 10:47:50 2006 +0100 9.3 @@ -0,0 +1,51 @@ 9.4 +/* 9.5 + * Copyright (C) 2005 Jimi Xenidis <jimix@watson.ibm.com>, IBM Corporation 9.6 + * 9.7 + * This program is free software; you can redistribute it and/or modify 9.8 + * it under the terms of the GNU General Public License as published by 9.9 + * the Free Software Foundation; either version 2 of the License, or 9.10 + * (at your option) any later version. 9.11 + * 9.12 + * This program is distributed in the hope that it will be useful, 9.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 9.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9.15 + * GNU General Public License for more details. 9.16 + * 9.17 + * You should have received a copy of the GNU General Public License 9.18 + * along with this program; if not, write to the Free Software 9.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 9.20 + * 9.21 + */ 9.22 + 9.23 +#include <asm/config.h> 9.24 +#include <asm/processor.h> 9.25 +#include <asm/page.h> 9.26 + 9.27 + .globl _start 9.28 +_start: 9.29 + /* load up the stack */ 9.30 + SET_REG_TO_LABEL(r1, cpu0_stack) 9.31 + 9.32 + /* call the init function */ 9.33 + LOADADDR(r21,__start_xen_ppc) 9.34 + 9.35 +#ifdef __PPC64__ 9.36 + ld r2, 8(r21) 9.37 + ld r21, 0(r21) 9.38 +#endif 9.39 + mtctr r21 9.40 + bctrl 9.41 + /* should never return */ 9.42 + trap 9.43 + 9.44 + /* Note! GDB 6.3 makes the very stupid assumption that PC > SP means we are 9.45 + * in a Linux signal trampoline, and it begins groping for a struct 9.46 + * rt_sigframe on the stack. Naturally, this fails miserably for our 9.47 + * backtrace. To work around this behavior, we must make certain that our 9.48 + * stack is always above our text, e.g. in the data section. */ 9.49 + .data /* DO NOT REMOVE; see GDB note above */ 9.50 + .align 4 9.51 +cpu0_stack_bottom: 9.52 + .space STACK_SIZE 9.53 +cpu0_stack: 9.54 + .space STACK_FRAME_OVERHEAD
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/xen/arch/powerpc/boot_of.c Fri Jul 14 10:47:50 2006 +0100 10.3 @@ -0,0 +1,1016 @@ 10.4 +/* 10.5 + * This program is free software; you can redistribute it and/or modify 10.6 + * it under the terms of the GNU General Public License as published by 10.7 + * the Free Software Foundation; either version 2 of the License, or 10.8 + * (at your option) any later version. 10.9 + * 10.10 + * This program is distributed in the hope that it will be useful, 10.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10.13 + * GNU General Public License for more details. 10.14 + * 10.15 + * You should have received a copy of the GNU General Public License 10.16 + * along with this program; if not, write to the Free Software 10.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 10.18 + * 10.19 + * Copyright (C) IBM Corp. 2005 10.20 + * 10.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 10.22 + */ 10.23 + 10.24 +#include <xen/config.h> 10.25 +#include <xen/init.h> 10.26 +#include <xen/lib.h> 10.27 +#include <xen/multiboot.h> 10.28 +#include <xen/compile.h> 10.29 +#include <xen/spinlock.h> 10.30 +#include <xen/serial.h> 10.31 +#include <xen/time.h> 10.32 +#include <asm/page.h> 10.33 +#include <asm/io.h> 10.34 +#include "exceptions.h" 10.35 +#include "of-devtree.h" 10.36 + 10.37 +static ulong of_vec; 10.38 +static ulong of_msr; 10.39 +static int of_out; 10.40 +static ofdn_t boot_cpu; 10.41 +static char bootargs[256]; 10.42 + 10.43 +extern struct ns16550_defaults ns16550; 10.44 + 10.45 +#undef OF_DEBUG 10.46 + 10.47 +#ifdef OF_DEBUG 10.48 +#define DBG(args...) of_printf(args) 10.49 +#else 10.50 +#define DBG(args...) 10.51 +#endif 10.52 + 10.53 +#define of_panic(MSG...) \ 10.54 + do { of_printf(MSG); of_printf("\nHANG\n"); for (;;); } while (0) 10.55 + 10.56 +struct of_service { 10.57 + u32 ofs_service; 10.58 + u32 ofs_nargs; 10.59 + u32 ofs_nrets; 10.60 + u32 ofs_args[10]; 10.61 +}; 10.62 + 10.63 +static int bof_chosen; 10.64 + 10.65 +static struct of_service s; 10.66 +extern s32 prom_call(void *arg, ulong rtas_base, ulong func, ulong msr); 10.67 + 10.68 +static int __init of_call( 10.69 + const char *service, u32 nargs, u32 nrets, s32 rets[], ...) 10.70 +{ 10.71 + int rc; 10.72 + 10.73 + if (of_vec != 0) { 10.74 + va_list args; 10.75 + int i; 10.76 + 10.77 + memset(&s, 0, sizeof (s)); 10.78 + s.ofs_service = (ulong)service; 10.79 + s.ofs_nargs = nargs; 10.80 + s.ofs_nrets = nrets; 10.81 + s.ofs_nargs = nargs; 10.82 + 10.83 + /* copy all the params into the args array */ 10.84 + va_start(args, rets); 10.85 + 10.86 + for (i = 0; i < nargs; i++) { 10.87 + s.ofs_args[i] = va_arg(args, u32); 10.88 + } 10.89 + 10.90 + va_end(args); 10.91 + 10.92 + rc = prom_call(&s, 0, of_vec, of_msr); 10.93 + 10.94 + /* yes always to the copy, just in case */ 10.95 + for (i = 0; i < nrets; i++) { 10.96 + rets[i] = s.ofs_args[i + nargs]; 10.97 + } 10.98 + } else { 10.99 + rc = OF_FAILURE; 10.100 + } 10.101 + return rc; 10.102 +} 10.103 + 10.104 +/* popular OF methods */ 10.105 +static int __init _of_write(int ih, const char *addr, u32 len) 10.106 +{ 10.107 + int rets[1] = { OF_FAILURE }; 10.108 + if (of_call("write", 3, 1, rets, ih, addr, len) == OF_FAILURE) { 10.109 + return OF_FAILURE; 10.110 + } 10.111 + return rets[0]; 10.112 +} 10.113 + 10.114 +/* popular OF methods */ 10.115 +static int __init of_write(int ih, const char *addr, u32 len) 10.116 +{ 10.117 + int rc; 10.118 + int i = 0; 10.119 + int sum = 0; 10.120 + 10.121 + while (i < len) { 10.122 + if (addr[i] == '\n') { 10.123 + if (i > 0) { 10.124 + rc = _of_write(ih, addr, i); 10.125 + if (rc == OF_FAILURE) 10.126 + return rc; 10.127 + sum += rc; 10.128 + } 10.129 + rc = _of_write(ih, "\r\n", 2); 10.130 + if (rc == OF_FAILURE) 10.131 + return rc; 10.132 + sum += rc; 10.133 + i++; 10.134 + addr += i; 10.135 + len -= i; 10.136 + i = 0; 10.137 + continue; 10.138 + } 10.139 + i++; 10.140 + } 10.141 + if (len > 0) { 10.142 + rc = _of_write(ih, addr, len); 10.143 + if (rc == OF_FAILURE) 10.144 + return rc; 10.145 + sum += rc; 10.146 + } 10.147 + 10.148 + return sum; 10.149 +} 10.150 + 10.151 +static int of_printf(const char *fmt, ...) 10.152 + __attribute__ ((format (printf, 1, 2))); 10.153 +static int __init of_printf(const char *fmt, ...) 10.154 +{ 10.155 + static char buf[1024]; 10.156 + va_list args; 10.157 + int sz; 10.158 + 10.159 + if (of_out == 0) { 10.160 + return OF_FAILURE; 10.161 + } 10.162 + 10.163 + va_start(args, fmt); 10.164 + 10.165 + sz = vsnprintf(buf, sizeof (buf), fmt, args); 10.166 + if (sz <= sizeof (buf)) { 10.167 + of_write(of_out, buf, sz); 10.168 + } else { 10.169 + static const char trunc[] = "\n(TRUNCATED)\n"; 10.170 + 10.171 + sz = sizeof (buf); 10.172 + of_write(of_out, buf, sz); 10.173 + of_write(of_out, trunc, sizeof (trunc)); 10.174 + } 10.175 + return sz; 10.176 +} 10.177 + 10.178 +static int __init of_finddevice(const char *devspec) 10.179 +{ 10.180 + int rets[1] = { OF_FAILURE }; 10.181 + 10.182 + of_call("finddevice", 1, 1, rets, devspec); 10.183 + if (rets[0] == OF_FAILURE) { 10.184 + DBG("finddevice %s -> FAILURE %d\n",devspec,rets[0]); 10.185 + return OF_FAILURE; 10.186 + } 10.187 + DBG("finddevice %s -> %d\n",devspec, rets[0]); 10.188 + return rets[0]; 10.189 +} 10.190 + 10.191 +static int __init of_getprop(int ph, const char *name, void *buf, u32 buflen) 10.192 +{ 10.193 + int rets[1] = { OF_FAILURE }; 10.194 + 10.195 + of_call("getprop", 4, 1, rets, ph, name, buf, buflen); 10.196 + 10.197 + if (rets[0] == OF_FAILURE) { 10.198 + DBG("getprop 0x%x %s -> FAILURE\n", ph, name); 10.199 + return OF_FAILURE; 10.200 + } 10.201 + 10.202 + DBG("getprop 0x%x %s -> 0x%x (%s)\n", ph, name, rets[0], (char *)buf); 10.203 + return rets[0]; 10.204 +} 10.205 + 10.206 +static int __init of_setprop( 10.207 + int ph, const char *name, const void *buf, u32 buflen) 10.208 +{ 10.209 + int rets[1] = { OF_FAILURE }; 10.210 + 10.211 + of_call("setprop", 4, 1, rets, ph, name, buf, buflen); 10.212 + 10.213 + if (rets[0] == OF_FAILURE) { 10.214 + DBG("setprop 0x%x %s -> FAILURE\n", ph, name); 10.215 + return OF_FAILURE; 10.216 + } 10.217 + 10.218 + DBG("setprop 0x%x %s -> %s\n", ph, name, (char *)buf); 10.219 + return rets[0]; 10.220 +} 10.221 + 10.222 +/* 10.223 + * returns 0 if there are no children (of spec) 10.224 + */ 10.225 +static int __init of_getchild(int ph) 10.226 +{ 10.227 + int rets[1] = { OF_FAILURE }; 10.228 + 10.229 + of_call("child", 1, 1, rets, ph); 10.230 + DBG("getchild 0x%x -> 0x%x\n", ph, rets[0]); 10.231 + 10.232 + return rets[0]; 10.233 +} 10.234 + 10.235 +/* 10.236 + * returns 0 is there are no peers 10.237 + */ 10.238 +static int __init of_getpeer(int ph) 10.239 +{ 10.240 + int rets[1] = { OF_FAILURE }; 10.241 + 10.242 + of_call("peer", 1, 1, rets, ph); 10.243 + DBG("getpeer 0x%x -> 0x%x\n", ph, rets[0]); 10.244 + 10.245 + return rets[0]; 10.246 +} 10.247 + 10.248 +static int __init of_getproplen(int ph, const char *name) 10.249 +{ 10.250 + int rets[1] = { OF_FAILURE }; 10.251 + 10.252 + of_call("getproplen", 2, 1, rets, ph, name); 10.253 + if (rets[0] == OF_FAILURE) { 10.254 + DBG("getproplen 0x%x %s -> FAILURE\n", ph, name); 10.255 + return OF_FAILURE; 10.256 + } 10.257 + DBG("getproplen 0x%x %s -> 0x%x\n", ph, name, rets[0]); 10.258 + return rets[0]; 10.259 +} 10.260 + 10.261 +static int __init of_package_to_path(int ph, char *buffer, u32 buflen) 10.262 +{ 10.263 + int rets[1] = { OF_FAILURE }; 10.264 + 10.265 + of_call("package-to-path", 3, 1, rets, ph, buffer, buflen); 10.266 + if (rets[0] == OF_FAILURE) { 10.267 + DBG("%s 0x%x -> FAILURE\n", __func__, ph); 10.268 + return OF_FAILURE; 10.269 + } 10.270 + DBG("%s 0x%x %s -> 0x%x\n", __func__, ph, buffer, rets[0]); 10.271 + if (rets[0] <= buflen) 10.272 + buffer[rets[0]] = '\0'; 10.273 + return rets[0]; 10.274 +} 10.275 + 10.276 +static int __init of_nextprop(int ph, const char *name, void *buf) 10.277 +{ 10.278 + int rets[1] = { OF_FAILURE }; 10.279 + 10.280 + of_call("nextprop", 3, 1, rets, ph, name, buf); 10.281 + 10.282 + if (rets[0] == OF_FAILURE) { 10.283 + DBG("nextprop 0x%x %s -> FAILURE\n", ph, name); 10.284 + return OF_FAILURE; 10.285 + } 10.286 + 10.287 + DBG("nextprop 0x%x %s -> %s\n", ph, name, (char *)buf); 10.288 + return rets[0]; 10.289 +} 10.290 + 10.291 +static int __init of_instance_to_path(int ih, char *buffer, u32 buflen) 10.292 +{ 10.293 + int rets[1] = { OF_FAILURE }; 10.294 + 10.295 + if (of_call("instance-to-path", 3, 1, rets, ih, buffer, buflen) 10.296 + == OF_FAILURE) 10.297 + return OF_FAILURE; 10.298 + 10.299 + if (rets[0] <= buflen) 10.300 + buffer[rets[0]] = '\0'; 10.301 + return rets[0]; 10.302 +} 10.303 + 10.304 +static int __init of_start_cpu(int cpu, u32 pc, u32 reg) 10.305 +{ 10.306 + int rets[1] = { OF_FAILURE }; 10.307 + 10.308 + if ( of_call("start-cpu", 3, 0, rets, cpu, pc, reg) == OF_FAILURE ) 10.309 + return OF_FAILURE; 10.310 + 10.311 + return rets[0]; 10.312 +} 10.313 + 10.314 +static void __init of_test(const char *of_method_name) 10.315 +{ 10.316 + int rets[1] = { OF_FAILURE }; 10.317 + 10.318 + of_call("test", 1, 1, rets, of_method_name); 10.319 + if (rets[0] == OF_FAILURE ) { 10.320 + of_printf("Warning: possibly no OF method %s.\n" 10.321 + "(Ignore this warning on PIBS.)\n", of_method_name); 10.322 + } 10.323 +} 10.324 + 10.325 +static int __init of_claim(void * virt, u32 size) 10.326 +{ 10.327 + int rets[1] = { OF_FAILURE }; 10.328 + 10.329 + of_call("claim", 3, 1, rets, virt, size, 0/*align*/); 10.330 + if (rets[0] == OF_FAILURE) { 10.331 + DBG("%s 0x%p 0x%08x -> FAIL\n", __func__, virt, size); 10.332 + return OF_FAILURE; 10.333 + } 10.334 + 10.335 + DBG("%s 0x%p 0x%08x -> 0x%x\n", __func__, virt, size, rets[0]); 10.336 + return rets[0]; 10.337 +} 10.338 + 10.339 +static int __init of_instance_to_package(int ih) 10.340 +{ 10.341 + int rets[1] = { OF_FAILURE }; 10.342 + 10.343 + of_call("instance-to-package", 1, 1, rets, ih); 10.344 + if (rets[0] == OF_FAILURE) 10.345 + return OF_FAILURE; 10.346 + 10.347 + return rets[0]; 10.348 +} 10.349 + 10.350 +static int __init of_getparent(int ph) 10.351 +{ 10.352 + int rets[1] = { OF_FAILURE }; 10.353 + 10.354 + of_call("parent", 1, 1, rets, ph); 10.355 + 10.356 + DBG("getparent 0x%x -> 0x%x\n", ph, rets[0]); 10.357 + return rets[0]; 10.358 +} 10.359 + 10.360 +static void boot_of_probemem(multiboot_info_t *mbi) 10.361 +{ 10.362 + int root; 10.363 + int p; 10.364 + u32 addr_cells = 1; 10.365 + u32 size_cells = 1; 10.366 + int rc; 10.367 + int mcount = 0; 10.368 + static memory_map_t mmap[16]; 10.369 + 10.370 + root = of_finddevice("/"); 10.371 + p = of_getchild(root); 10.372 + 10.373 + /* code is writen to assume sizes of 1 */ 10.374 + of_getprop(root, "#address-cells", &addr_cells, sizeof (addr_cells)); 10.375 + of_getprop(root, "#size-cells", &size_cells, sizeof (size_cells)); 10.376 + DBG("%s: address_cells=%d size_cells=%d\n", 10.377 + __func__, addr_cells, size_cells); 10.378 + 10.379 + do { 10.380 + const char memory[] = "memory"; 10.381 + char type[32]; 10.382 + 10.383 + type[0] = '\0'; 10.384 + 10.385 + of_getprop(p, "device_type", type, sizeof (type)); 10.386 + if (strncmp(type, memory, sizeof (memory)) == 0) { 10.387 + u32 reg[48]; 10.388 + u32 al, ah, ll, lh; 10.389 + int r; 10.390 + 10.391 + rc = of_getprop(p, "reg", reg, sizeof (reg)); 10.392 + if (rc == OF_FAILURE) { 10.393 + of_panic("no reg property for memory node: 0x%x.\n", p); 10.394 + } 10.395 + int l = rc/sizeof(u32); /* number reg element */ 10.396 + DBG("%s: number of bytes in property 'reg' %d\n", 10.397 + __func__, rc); 10.398 + 10.399 + r = 0; 10.400 + while (r < l) { 10.401 + al = ah = ll = lh = 0; 10.402 + if (addr_cells == 2) { 10.403 + ah = reg[r++]; 10.404 + if (r >= l) 10.405 + break; /* partial line. Skip */ 10.406 + al = reg[r++]; 10.407 + if (r >= l) 10.408 + break; /* partial line. Skip */ 10.409 + } else { 10.410 + al = reg[r++]; 10.411 + if (r >= l) 10.412 + break; /* partial line. Skip */ 10.413 + } 10.414 + if (size_cells == 2) { 10.415 + lh = reg[r++]; 10.416 + if (r >= l) 10.417 + break; /* partial line. Skip */ 10.418 + ll = reg[r++]; 10.419 + } else { 10.420 + ll = reg[r++]; 10.421 + } 10.422 + 10.423 + if ((ll != 0) || (lh != 0)) { 10.424 + mmap[mcount].size = 20; /* - size field */ 10.425 + mmap[mcount].type = 1; /* Regular ram */ 10.426 + mmap[mcount].length_high = lh; 10.427 + mmap[mcount].length_low = ll; 10.428 + mmap[mcount].base_addr_high = ah; 10.429 + mmap[mcount].base_addr_low = al; 10.430 + of_printf("%s: memory 0x%016lx[0x%08lx]\n", 10.431 + __func__, 10.432 + (u64)(((u64)mmap[mcount].base_addr_high << 32) 10.433 + | mmap[mcount].base_addr_low), 10.434 + (u64)(((u64)mmap[mcount].length_high << 32) 10.435 + | mmap[mcount].length_low)); 10.436 + ++mcount; 10.437 + } 10.438 + } 10.439 + } 10.440 + p = of_getpeer(p); 10.441 + } while (p != OF_FAILURE && p != 0); 10.442 + 10.443 + if (mcount > 0) { 10.444 + mbi->flags |= MBI_MEMMAP; 10.445 + mbi->mmap_length = sizeof (mmap[0]) * mcount; 10.446 + mbi->mmap_addr = (ulong)mmap; 10.447 + } 10.448 +} 10.449 + 10.450 +static void boot_of_bootargs(multiboot_info_t *mbi) 10.451 +{ 10.452 + int rc; 10.453 + 10.454 + rc = of_getprop(bof_chosen, "bootargs", &bootargs, sizeof (bootargs)); 10.455 + if (rc == OF_FAILURE) { 10.456 + strcpy(bootargs, "xen"); 10.457 + } 10.458 + 10.459 + mbi->flags |= MBI_CMDLINE; 10.460 + mbi->cmdline = (u32)bootargs; 10.461 + 10.462 + of_printf("bootargs = %s\n", bootargs); 10.463 +} 10.464 + 10.465 +static int save_props(void *m, ofdn_t n, int pkg) 10.466 +{ 10.467 + int ret; 10.468 + char name[128]; 10.469 + int result = 1; 10.470 + int found_name = 0; 10.471 + int found_device_type = 0; 10.472 + const char name_str[] = "name"; 10.473 + const char devtype_str[] = "device_type"; 10.474 + 10.475 + /* get first */ 10.476 + result = of_nextprop(pkg, 0, name); 10.477 + 10.478 + while (result > 0) { 10.479 + int sz; 10.480 + u64 obj[1024]; 10.481 + 10.482 + sz = of_getproplen(pkg, name); 10.483 + if (sz >= 0) { 10.484 + ret = OF_SUCCESS; 10.485 + } else { 10.486 + ret = OF_FAILURE; 10.487 + } 10.488 + 10.489 + if (ret == OF_SUCCESS) { 10.490 + int actual = 0; 10.491 + ofdn_t pos; 10.492 + 10.493 + if (sz > 0) { 10.494 + if (sz > sizeof (obj)) { 10.495 + of_panic("obj array not big enough for 0x%x\n", sz); 10.496 + } 10.497 + actual = of_getprop(pkg, name, obj, sz); 10.498 + if (actual > sz) of_panic("obj too small"); 10.499 + } 10.500 + 10.501 + if (strncmp(name, name_str, sizeof(name_str)) == 0) { 10.502 + found_name = 1; 10.503 + } 10.504 + 10.505 + if (strncmp(name, devtype_str, sizeof(devtype_str)) == 0) { 10.506 + found_device_type = 1; 10.507 + } 10.508 + 10.509 + pos = ofd_prop_add(m, n, name, obj, actual); 10.510 + if (pos == 0) of_panic("prop_create"); 10.511 + } 10.512 + 10.513 + result = of_nextprop(pkg, name, name); 10.514 + } 10.515 + 10.516 + return 1; 10.517 +} 10.518 + 10.519 + 10.520 +static void do_pkg(void *m, ofdn_t n, int p, char *path, size_t psz) 10.521 +{ 10.522 + int pnext; 10.523 + ofdn_t nnext; 10.524 + int sz; 10.525 + 10.526 +retry: 10.527 + save_props(m, n, p); 10.528 + 10.529 + /* do children first */ 10.530 + pnext = of_getchild(p); 10.531 + 10.532 + if (pnext != 0) { 10.533 + sz = of_package_to_path(pnext, path, psz); 10.534 + if (sz == OF_FAILURE) of_panic("bad path\n"); 10.535 + 10.536 + nnext = ofd_node_child_create(m, n, path, sz); 10.537 + if (nnext == 0) of_panic("out of mem\n"); 10.538 + 10.539 + do_pkg(m, nnext, pnext, path, psz); 10.540 + } 10.541 + 10.542 + /* do peer */ 10.543 + pnext = of_getpeer(p); 10.544 + 10.545 + if (pnext != 0) { 10.546 + sz = of_package_to_path(pnext, path, psz); 10.547 + 10.548 + nnext = ofd_node_peer_create(m, n, path, sz); 10.549 + if (nnext <= 0) of_panic("out of space in OFD tree.\n"); 10.550 + 10.551 + n = nnext; 10.552 + p = pnext; 10.553 + goto retry; 10.554 + } 10.555 +} 10.556 + 10.557 +static int pkg_save(void *mem) 10.558 +{ 10.559 + int root; 10.560 + char path[256]; 10.561 + int r; 10.562 + 10.563 + path[0]='/'; 10.564 + path[1]='\0'; 10.565 + 10.566 + /* get root */ 10.567 + root = of_getpeer(0); 10.568 + if (root == OF_FAILURE) of_panic("no root package\n"); 10.569 + 10.570 + do_pkg(mem, OFD_ROOT, root, path, sizeof(path)); 10.571 + 10.572 + r = (((ofdn_t *)mem)[1] + 1) * sizeof (u64); 10.573 + 10.574 + of_printf("%s: saved device tree in 0x%x bytes\n", __func__, r); 10.575 + 10.576 + return r; 10.577 +} 10.578 + 10.579 +static int boot_of_fixup_refs(void *mem) 10.580 +{ 10.581 + static const char *fixup_props[] = { 10.582 + "interrupt-parent", 10.583 + }; 10.584 + int i; 10.585 + int count = 0; 10.586 + 10.587 + for (i = 0; i < ARRAY_SIZE(fixup_props); i++) { 10.588 + ofdn_t c; 10.589 + const char *name = fixup_props[i]; 10.590 + 10.591 + c = ofd_node_find_by_prop(mem, OFD_ROOT, name, NULL, 0); 10.592 + while (c > 0) { 10.593 + const char *path; 10.594 + int rp; 10.595 + int ref; 10.596 + ofdn_t dp; 10.597 + int rc; 10.598 + ofdn_t upd; 10.599 + char ofpath[256]; 10.600 + 10.601 + path = ofd_node_path(mem, c); 10.602 + if (path == NULL) of_panic("no path to found prop: %s\n", name); 10.603 + 10.604 + rp = of_finddevice(path); 10.605 + if (rp == OF_FAILURE) 10.606 + of_panic("no real device for: name %s, path %s\n", 10.607 + name, path); 10.608 + /* Note: In theory 0 is a valid node handle but it is highly 10.609 + * unlikely. 10.610 + */ 10.611 + if (rp == 0) { 10.612 + of_panic("%s: of_finddevice returns 0 for path %s\n", 10.613 + __func__, path); 10.614 + } 10.615 + 10.616 + rc = of_getprop(rp, name, &ref, sizeof(ref)); 10.617 + if ((rc == OF_FAILURE) || (rc == 0)) 10.618 + of_panic("no prop: name %s, path %s, device 0x%x\n", 10.619 + name, path, rp); 10.620 + 10.621 + rc = of_package_to_path(ref, ofpath, sizeof (ofpath)); 10.622 + if (rc == OF_FAILURE) 10.623 + of_panic("no package: name %s, path %s, device 0x%x,\n" 10.624 + "ref 0x%x\n", name, path, rp, ref); 10.625 + 10.626 + dp = ofd_node_find(mem, ofpath); 10.627 + if (dp <= 0) of_panic("no ofd node for OF node[0x%x]: %s\n", 10.628 + ref, ofpath); 10.629 + 10.630 + ref = dp; 10.631 + 10.632 + upd = ofd_prop_add(mem, c, name, &ref, sizeof(ref)); 10.633 + if (upd <= 0) of_panic("update failed: %s\n", name); 10.634 + 10.635 +#ifdef DEBUG 10.636 + of_printf("%s: %s/%s -> %s\n", __func__, 10.637 + path, name, ofpath); 10.638 +#endif 10.639 + ++count; 10.640 + c = ofd_node_find_next(mem, c); 10.641 + } 10.642 + } 10.643 + return count; 10.644 +} 10.645 + 10.646 +static int boot_of_fixup_chosen(void *mem) 10.647 +{ 10.648 + int ch; 10.649 + ofdn_t dn; 10.650 + ofdn_t dc; 10.651 + int val; 10.652 + int rc; 10.653 + char ofpath[256]; 10.654 + 10.655 + ch = of_finddevice("/chosen"); 10.656 + if (ch == OF_FAILURE) of_panic("/chosen not found\n"); 10.657 + 10.658 + rc = of_getprop(ch, "cpu", &val, sizeof (val)); 10.659 + 10.660 + if (rc != OF_FAILURE) { 10.661 + rc = of_instance_to_path(val, ofpath, sizeof (ofpath)); 10.662 + 10.663 + if (rc > 0) { 10.664 + dn = ofd_node_find(mem, ofpath); 10.665 + if (dn <= 0) of_panic("no node for: %s\n", ofpath); 10.666 + 10.667 + boot_cpu = dn; 10.668 + val = dn; 10.669 + 10.670 + dn = ofd_node_find(mem, "/chosen"); 10.671 + if (dn <= 0) of_panic("no /chosen node\n"); 10.672 + 10.673 + dc = ofd_prop_add(mem, dn, "cpu", &val, sizeof (val)); 10.674 + if (dc <= 0) of_panic("could not fix /chosen/cpu\n"); 10.675 + rc = 1; 10.676 + } else { 10.677 + of_printf("*** can't find path to booting cpu, " 10.678 + "SMP is disabled\n"); 10.679 + boot_cpu = -1; 10.680 + } 10.681 + } 10.682 + return rc; 10.683 +} 10.684 + 10.685 +static ulong space_base; 10.686 +static ulong find_space(u32 size, ulong align, multiboot_info_t *mbi) 10.687 +{ 10.688 + memory_map_t *map = (memory_map_t *)((ulong)mbi->mmap_addr); 10.689 + ulong eomem = ((u64)map->length_high << 32) | (u64)map->length_low; 10.690 + ulong base; 10.691 + 10.692 + of_printf("%s base=0x%016lx eomem=0x%016lx size=0x%08x align=0x%lx\n", 10.693 + __func__, space_base, eomem, size, align); 10.694 + base = ALIGN_UP(space_base, PAGE_SIZE); 10.695 + if ((base + size) >= 0x4000000) return 0; 10.696 + if (base + size > eomem) of_panic("not enough RAM\n"); 10.697 + 10.698 + if (size == 0) return base; 10.699 + if (of_claim((void*)base, size) != OF_FAILURE) { 10.700 + space_base = base + size; 10.701 + return base; 10.702 + } else { 10.703 + for(base += 0x100000; (base+size) < 0x4000000; base += 0x100000) { 10.704 + of_printf("Trying 0x%016lx\n", base); 10.705 + if (of_claim((void*)base, size) != OF_FAILURE) { 10.706 + space_base = base + size; 10.707 + return base; 10.708 + } 10.709 + } 10.710 + return 0; 10.711 + } 10.712 +} 10.713 + 10.714 +/* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges 10.715 + * property. The values are bad, and it doesn't even have the 10.716 + * right number of cells. */ 10.717 + 10.718 +static void __init boot_of_fix_maple(void) 10.719 +{ 10.720 + int isa; 10.721 + const char *ranges = "ranges"; 10.722 + u32 isa_ranges[3]; 10.723 + const u32 isa_test[] = { 0x00000001, 0xf4000000, 0x00010000 }; 10.724 + const u32 isa_fixed[] = { 10.725 + 0x00000001, 10.726 + 0x00000000, 10.727 + 0x00000000, /* 0xf4000000, matt says this */ 10.728 + 0x00000000, 10.729 + 0x00000000, 10.730 + 0x00010000 10.731 + }; 10.732 + 10.733 + isa = of_finddevice("/ht@0/isa@4"); 10.734 + if (isa != OF_FAILURE) { 10.735 + if (of_getproplen(isa, ranges) == sizeof (isa_test)) { 10.736 + of_getprop(isa, ranges, isa_ranges, sizeof (isa_ranges)); 10.737 + if (memcmp(isa_ranges, isa_test, sizeof (isa_test)) == 0) { 10.738 + int rc; 10.739 + 10.740 + of_printf("OF: fixing bogus ISA range on maple\n"); 10.741 + rc = of_setprop(isa, ranges, isa_fixed, sizeof (isa_fixed)); 10.742 + if (rc == OF_FAILURE) { 10.743 + of_panic("of_setprop() failed\n"); 10.744 + } 10.745 + } 10.746 + } 10.747 + } 10.748 +} 10.749 + 10.750 +static int __init boot_of_serial(void *oftree) 10.751 +{ 10.752 + int n; 10.753 + int p; 10.754 + int rc; 10.755 + u32 val[3]; 10.756 + char buf[128]; 10.757 + 10.758 + n = of_instance_to_package(of_out); 10.759 + if (n == OF_FAILURE) { 10.760 + of_panic("instance-to-package of /chosen/stdout: failed\n"); 10.761 + } 10.762 + 10.763 + /* prune this from the oftree */ 10.764 + rc = of_package_to_path(n, buf, sizeof(buf)); 10.765 + if (rc == OF_FAILURE) { 10.766 + of_panic("package-to-path of /chosen/stdout: failed\n"); 10.767 + } 10.768 + of_printf("Pruning from devtree: %s\n" 10.769 + " since Xen will be using it for console\n", buf); 10.770 + rc = ofd_prune_path(oftree, buf); 10.771 + if (rc < 0) { 10.772 + of_panic("prune path \"%s\" failed\n", buf); 10.773 + } 10.774 + 10.775 + 10.776 + p = of_getparent(n); 10.777 + if (p == OF_FAILURE) { 10.778 + of_panic("no parent for: 0x%x\n", n); 10.779 + } 10.780 + 10.781 + buf[0] = '\0'; 10.782 + of_getprop(p, "device_type", buf, sizeof (buf)); 10.783 + if (strstr(buf, "isa") == NULL) { 10.784 + of_panic("only ISA UARTS supported\n"); 10.785 + } 10.786 + 10.787 + /* should get this from devtree */ 10.788 + isa_io_base = 0xf4000000; 10.789 + of_printf("%s: ISA base: 0x%lx\n", __func__, isa_io_base); 10.790 + 10.791 + buf[0] = '\0'; 10.792 + of_getprop(n, "device_type", buf, sizeof (buf)); 10.793 + if (strstr(buf, "serial") == NULL) { 10.794 + of_panic("only UARTS supported\n"); 10.795 + } 10.796 + 10.797 + rc = of_getprop(n, "reg", val, sizeof (val)); 10.798 + if (rc == OF_FAILURE) { 10.799 + of_panic("%s: no location for serial port\n", __func__); 10.800 + } 10.801 + ns16550.io_base = val[1]; 10.802 + 10.803 + ns16550.baud = BAUD_AUTO; 10.804 + ns16550.data_bits = 8; 10.805 + ns16550.parity = 'n'; 10.806 + ns16550.stop_bits = 1; 10.807 + 10.808 + rc = of_getprop(n, "interrupts", val, sizeof (val)); 10.809 + if (rc == OF_FAILURE) { 10.810 + of_printf("%s: no ISRC, forcing poll mode\n", __func__); 10.811 + ns16550.irq = 0; 10.812 + } else { 10.813 + ns16550.irq = val[0]; 10.814 + of_printf("%s: ISRC=0x%x, but forcing poll mode\n", 10.815 + __func__, ns16550.irq); 10.816 + ns16550.irq = 0; 10.817 + } 10.818 + 10.819 + return 1; 10.820 +} 10.821 + 10.822 +static void boot_of_module(ulong r3, ulong r4, multiboot_info_t *mbi) 10.823 +{ 10.824 + static module_t mods[3]; 10.825 + void *oftree; 10.826 + ulong oftree_sz = 48 * PAGE_SIZE; 10.827 + char *mod0_start; 10.828 + ulong mod0_size; 10.829 + ulong mod0; 10.830 + static const char sepr[] = " -- "; 10.831 + extern char dom0_start[] __attribute__ ((weak)); 10.832 + extern char dom0_size[] __attribute__ ((weak)); 10.833 + const char *p; 10.834 + 10.835 + if ((r3 > 0) && (r4 > 0)) { 10.836 + /* was it handed to us in registers ? */ 10.837 + mod0_start = (void *)r3; 10.838 + mod0_size = r4; 10.839 + } else { 10.840 + /* see if it is in the boot params */ 10.841 + p = strstr((char *)((ulong)mbi->cmdline), "dom0_start="); 10.842 + if ( p != NULL) { 10.843 + p += 11; 10.844 + mod0_start = (char *)simple_strtoul(p, NULL, 0); 10.845 + 10.846 + p = strstr((char *)((ulong)mbi->cmdline), "dom0_size="); 10.847 + p += 10; 10.848 + mod0_size = simple_strtoul(p, NULL, 0); 10.849 + 10.850 + of_printf("mod0: %o %c %c %c\n", 10.851 + mod0_start[0], 10.852 + mod0_start[1], 10.853 + mod0_start[2], 10.854 + mod0_start[3]); 10.855 + 10.856 + } else if ( ((ulong)dom0_start != 0) && ((ulong)dom0_size != 0) ) { 10.857 + /* was it linked in ? */ 10.858 + 10.859 + mod0_start = dom0_start; 10.860 + mod0_size = (ulong)dom0_size; 10.861 + of_printf("%s: linked in module copied after _end " 10.862 + "(start 0x%p size 0x%lx)\n", 10.863 + __func__, mod0_start, mod0_size); 10.864 + } else { 10.865 + mod0_start = _end; 10.866 + mod0_size = 0; 10.867 + } 10.868 + } 10.869 + 10.870 + space_base = (ulong)_end; 10.871 + mod0 = find_space(mod0_size, PAGE_SIZE, mbi); 10.872 + 10.873 + /* three cases 10.874 + * 1) mod0_size is not 0 and the image can be copied 10.875 + * 2) mod0_size is not 0 and the image cannot be copied 10.876 + * 3) mod0_size is 0 10.877 + */ 10.878 + if (mod0_size > 0) { 10.879 + if (mod0 != 0) { 10.880 + memcpy((void *)mod0, mod0_start, mod0_size); 10.881 + mods[0].mod_start = mod0; 10.882 + mods[0].mod_end = mod0 + mod0_size; 10.883 + } else { 10.884 + of_panic("No space to copy mod0\n"); 10.885 + } 10.886 + } else { 10.887 + mods[0].mod_start = mod0; 10.888 + mods[0].mod_end = mod0; 10.889 + } 10.890 + 10.891 + of_printf("%s: mod[0] @ 0x%016x[0x%x]\n", __func__, 10.892 + mods[0].mod_start, mods[0].mod_end); 10.893 + p = strstr((char *)(ulong)mbi->cmdline, sepr); 10.894 + if (p != NULL) { 10.895 + p += sizeof (sepr) - 1; 10.896 + mods[0].string = (u32)(ulong)p; 10.897 + of_printf("%s: mod[0].string: %s\n", __func__, p); 10.898 + } 10.899 + 10.900 + /* snapshot the tree */ 10.901 + oftree = (void*)find_space(oftree_sz, PAGE_SIZE, mbi); 10.902 + if (oftree == 0) of_panic("Could not allocate OFD tree\n"); 10.903 + 10.904 + of_printf("creating oftree\n"); 10.905 + of_test("package-to-path"); 10.906 + ofd_create(oftree, oftree_sz); 10.907 + pkg_save(oftree); 10.908 + 10.909 + boot_of_fixup_refs(oftree); 10.910 + boot_of_fixup_chosen(oftree); 10.911 + 10.912 + ofd_walk(oftree, OFD_ROOT, /* add_hype_props */ NULL, 2); 10.913 + 10.914 + mods[1].mod_start = (ulong)oftree; 10.915 + mods[1].mod_end = mods[1].mod_start + oftree_sz; 10.916 + of_printf("%s: mod[1] @ 0x%016x[0x%x]\n", __func__, 10.917 + mods[1].mod_start, mods[1].mod_end); 10.918 + 10.919 + 10.920 + mbi->flags |= MBI_MODULES; 10.921 + mbi->mods_count = 2; 10.922 + mbi->mods_addr = (u32)mods; 10.923 + 10.924 + boot_of_serial(oftree); 10.925 +} 10.926 + 10.927 +static int __init boot_of_cpus(void) 10.928 +{ 10.929 + int cpus; 10.930 + int cpu; 10.931 + int result; 10.932 + u32 cpu_clock[2]; 10.933 + 10.934 + cpus = of_finddevice("/cpus"); 10.935 + cpu = of_getchild(cpus); 10.936 + result = of_getprop(cpu, "timebase-frequency", &timebase_freq, 10.937 + sizeof(timebase_freq)); 10.938 + if (result == OF_FAILURE) { 10.939 + of_panic("Couldn't get timebase frequency!\n"); 10.940 + } 10.941 + of_printf("OF: timebase-frequency = %d Hz\n", timebase_freq); 10.942 + 10.943 + result = of_getprop(cpu, "clock-frequency", &cpu_clock, sizeof(cpu_clock)); 10.944 + if (result == OF_FAILURE || (result !=4 && result != 8)) { 10.945 + of_panic("Couldn't get clock frequency!\n"); 10.946 + } 10.947 + cpu_khz = cpu_clock[0]; 10.948 + if (result == 8) { 10.949 + cpu_khz <<= 32; 10.950 + cpu_khz |= cpu_clock[1]; 10.951 + } 10.952 + cpu_khz /= 1000; 10.953 + of_printf("OF: clock-frequency = %ld KHz\n", cpu_khz); 10.954 + 10.955 + /* FIXME: should not depend on the boot CPU bring the first child */ 10.956 + cpu = of_getpeer(cpu); 10.957 + while (cpu > 0) { 10.958 + of_start_cpu(cpu, (ulong)spin_start, 0); 10.959 + cpu = of_getpeer(cpu); 10.960 + } 10.961 + return 1; 10.962 +} 10.963 + 10.964 +static int __init boot_of_rtas(void) 10.965 +{ 10.966 + return 1; 10.967 +} 10.968 + 10.969 +multiboot_info_t __init *boot_of_init( 10.970 + ulong r3, ulong r4, ulong vec, ulong r6, ulong r7, ulong orig_msr) 10.971 +{ 10.972 + static multiboot_info_t mbi; 10.973 + 10.974 + of_vec = vec; 10.975 + of_msr = orig_msr; 10.976 + 10.977 + bof_chosen = of_finddevice("/chosen"); 10.978 + of_getprop(bof_chosen, "stdout", &of_out, sizeof (of_out)); 10.979 + 10.980 + of_printf("%s\n", "---------------------------------------------------"); 10.981 + of_printf("OF: Xen/PPC version %d.%d%s (%s@%s) (%s) %s\n", 10.982 + XEN_VERSION, XEN_SUBVERSION, XEN_EXTRAVERSION, 10.983 + XEN_COMPILE_BY, XEN_COMPILE_DOMAIN, 10.984 + XEN_COMPILER, XEN_COMPILE_DATE); 10.985 + 10.986 + of_printf("%s args: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n" 10.987 + "boot msr: 0x%lx\n", 10.988 + __func__, 10.989 + r3, r4, vec, r6, r7, orig_msr); 10.990 + 10.991 + if ((vec >= (ulong)_start) && (vec <= (ulong)_end)) { 10.992 + of_printf("Hmm.. OF[0x%lx] seems to have stepped on our image " 10.993 + "that ranges: %p .. %p.\n HANG!\n", 10.994 + vec, _start, _end); 10.995 + } 10.996 + of_printf("%s: _start %p _end %p 0x%lx\n", __func__, _start, _end, r6); 10.997 + 10.998 + boot_of_fix_maple(); 10.999 + boot_of_probemem(&mbi); 10.1000 + boot_of_bootargs(&mbi); 10.1001 + boot_of_module(r3, r4, &mbi); 10.1002 + boot_of_cpus(); 10.1003 + boot_of_rtas(); 10.1004 + 10.1005 + /* end of OF */ 10.1006 + of_call("quiesce", 0, 0, NULL); 10.1007 + 10.1008 + return &mbi; 10.1009 +} 10.1010 + 10.1011 +/* 10.1012 + * Local variables: 10.1013 + * mode: C 10.1014 + * c-set-style: "BSD" 10.1015 + * c-basic-offset: 4 10.1016 + * tab-width: 4 10.1017 + * indent-tabs-mode: nil 10.1018 + * End: 10.1019 + */
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/xen/arch/powerpc/dart.c Fri Jul 14 10:47:50 2006 +0100 11.3 @@ -0,0 +1,299 @@ 11.4 +/* 11.5 + * This program is free software; you can redistribute it and/or modify 11.6 + * it under the terms of the GNU General Public License as published by 11.7 + * the Free Software Foundation; either version 2 of the License, or 11.8 + * (at your option) any later version. 11.9 + * 11.10 + * This program is distributed in the hope that it will be useful, 11.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11.13 + * GNU General Public License for more details. 11.14 + * 11.15 + * You should have received a copy of the GNU General Public License 11.16 + * along with this program; if not, write to the Free Software 11.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 11.18 + * 11.19 + * Copyright (C) IBM Corp. 2005 11.20 + * 11.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 11.22 + */ 11.23 + 11.24 +#include <xen/config.h> 11.25 +#include <xen/types.h> 11.26 +#include <xen/mm.h> 11.27 +#include <asm/cache.h> 11.28 +#include <xen/init.h> 11.29 +#include "tce.h" 11.30 +#include "iommu.h" 11.31 +#include "dart.h" 11.32 +#include "oftree.h" 11.33 +#include "of-devtree.h" 11.34 + 11.35 +#undef DEBUG 11.36 +#ifdef DEBUG 11.37 +#define DBG(fmt...) printk(fmt) 11.38 +static int dbg_after; 11.39 +#define DBG_SET_AFTER dbg_after = 1; 11.40 +#define DBG_AFTER(fmt...) if (dbg_after) DBG(fmt) 11.41 +#else 11.42 +#define DBG(fmt...) 11.43 +#define DBG_SET_AFTER 11.44 +#define DBG_AFTER(fmt...) 11.45 +#endif 11.46 + 11.47 +/* Max size of 512 pages */ 11.48 +#define U3_LOG_MAX_PAGES 9 11.49 + 11.50 +#define DART_DEF_BASE 0xf8033000UL 11.51 +#define DART_NONE 0 11.52 +#define DART_U3 3 11.53 +#define DART_U4 4 11.54 +#define DART_WRITE 0x1 11.55 +#define DART_READ 0x2 11.56 + 11.57 +static ulong dummy_page; 11.58 +static ulong dart_entries; 11.59 +static struct dart_ops *dops; 11.60 +static u32 *dart_table; 11.61 + 11.62 +union dart_entry { 11.63 + u32 de_word; 11.64 + struct { 11.65 + u32 de_v:1; /* valid */ 11.66 + u32 de_rp:1; /* read protected*/ 11.67 + u32 de_wp:1; /* write protected*/ 11.68 + u32 _de_res:5; 11.69 + u32 de_ppn:24; /* 24 bit Physical Page Number 11.70 + * representing address [28:51] */ 11.71 + } de_bits; 11.72 +}; 11.73 + 11.74 +struct dma_window { 11.75 + u32 dw_liobn; 11.76 + u32 dw_base_hi; 11.77 + u64 dw_base; 11.78 + u64 dw_size; 11.79 +}; 11.80 + 11.81 +struct dart_info { 11.82 + struct dma_window di_window; 11.83 + ulong di_base; 11.84 + int di_model; 11.85 +}; 11.86 + 11.87 +static u32 dart_encode(int perm, ulong rpn) 11.88 +{ 11.89 + union dart_entry e; 11.90 + 11.91 + e.de_word = 0; 11.92 + e.de_bits.de_v = 1; 11.93 + e.de_bits.de_ppn = rpn; 11.94 + 11.95 + /* protect the page */ 11.96 + e.de_bits.de_rp = 1; 11.97 + e.de_bits.de_wp = 1; 11.98 + if (perm & DART_READ) { 11.99 + e.de_bits.de_rp = 0; 11.100 + } 11.101 + if (perm & DART_WRITE) { 11.102 + e.de_bits.de_wp = 0; 11.103 + } 11.104 + 11.105 + return e.de_word; 11.106 +} 11.107 + 11.108 +static void dart_fill(ulong index, int perm, ulong rpg, ulong num_pg) 11.109 +{ 11.110 + u32 volatile *entry = dart_table + index; 11.111 + ulong i = 0; 11.112 + ulong last_flush = 0; 11.113 + 11.114 + while (1) { 11.115 + entry[i] = dart_encode(perm, rpg); 11.116 + ++i; 11.117 + ++rpg; 11.118 + if (i == num_pg) break; 11.119 + 11.120 + if (((ulong)&entry[i]) % CACHE_LINE_SIZE == 0) { 11.121 + last_flush = (ulong)&entry[i - 1]; 11.122 + dcbst(last_flush); 11.123 + } 11.124 + } 11.125 + dcbst((ulong) &entry[i - 1]); 11.126 +} 11.127 + 11.128 +static void dart_clear(ulong index, ulong num_pg) 11.129 +{ 11.130 + u32 *entry = dart_table + index; 11.131 + ulong i = 0; 11.132 + ulong rpg = dummy_page; 11.133 + ulong last_flush = 0; 11.134 + 11.135 + while (1) { 11.136 + entry[i] = dart_encode(DART_READ | DART_WRITE, rpg); 11.137 + ++i; 11.138 + if (i == num_pg) break; 11.139 + 11.140 + if (((ulong)&entry[i]) % CACHE_LINE_SIZE == 0) { 11.141 + last_flush = (ulong)&entry[i - 1]; 11.142 + dcbst(last_flush); 11.143 + } 11.144 + } 11.145 + dcbst((ulong)&entry[i - 1]); 11.146 +} 11.147 + 11.148 +static int dart_put(ulong ioba, union tce tce) 11.149 +{ 11.150 + ulong index = ioba >> PAGE_SHIFT; 11.151 + 11.152 + if (index > dart_entries) { 11.153 + return -1; 11.154 + } 11.155 + 11.156 + if (tce.tce_bits.tce_vlps != 0 || tce.tce_bits.tce_lpx != 0) { 11.157 + panic("no support for large TCEs\n"); 11.158 + } 11.159 + 11.160 + if (tce.tce_bits.tce_read == 0 && 11.161 + tce.tce_bits.tce_write == 0) { 11.162 + /* the TCE table is inited by the domain by a bunch of 0 11.163 + * perminssion puts. We are only interesting in debugging the 11.164 + * ones after the first put */ 11.165 + DBG_AFTER(">DART[0x%lx] clear\n", index); 11.166 + dart_clear(index, 1); 11.167 + } else { 11.168 + unsigned perm = 0; 11.169 + 11.170 + if (tce.tce_bits.tce_read) 11.171 + perm |= DART_READ; 11.172 + if (tce.tce_bits.tce_write) 11.173 + perm |= DART_WRITE; 11.174 + 11.175 + DBG("<DART[0x%lx]: ioba: 0x%lx perm:%x[%c%c] rpn:0x%lx\n", 11.176 + index, ioba, perm, 11.177 + (perm & DART_READ) ? 'R' : '-', 11.178 + (perm & DART_WRITE) ? 'W' : '-', 11.179 + (ulong)tce.tce_bits.tce_rpn); 11.180 + DBG_SET_AFTER; 11.181 + 11.182 + dart_fill(index, perm, tce.tce_bits.tce_rpn, 1); 11.183 + } 11.184 + dops->do_inv_entry(tce.tce_bits.tce_rpn); 11.185 + 11.186 + return 0; 11.187 +} 11.188 + 11.189 +static int find_dart(struct dart_info *di) 11.190 +{ 11.191 + int rc; 11.192 + void *ofd_p; 11.193 + ofdn_t n; 11.194 + char compat[128]; 11.195 + 11.196 + 11.197 + if (on_mambo()) { 11.198 + /* mambo has no dart */ 11.199 + DBG("%s: Mambo does not support a dart\n", __func__); 11.200 + return -1; 11.201 + } 11.202 + 11.203 + ofd_p = (void *)oftree; 11.204 + n = ofd_node_find(ofd_p, "/ht"); 11.205 + if (n <= 0) 11.206 + return -1; 11.207 + 11.208 + /* get the defaults from the HT node model */ 11.209 + rc = ofd_getprop(ofd_p, n, "compatible", compat, sizeof (compat)); 11.210 + if (rc <= 0) 11.211 + return -1; 11.212 + 11.213 + di->di_base = DART_DEF_BASE; 11.214 + 11.215 + if (strstr(compat, "u3")) { 11.216 + di->di_model = DART_U3; 11.217 + } else if (strstr(compat, "u4")) { 11.218 + di->di_model = DART_U4; 11.219 + } else { 11.220 + DBG("%s: not a U3 or U4\n", __func__); 11.221 + return -1; 11.222 + } 11.223 + /* FIXME: this should actually be the HT reg value */ 11.224 + di->di_window.dw_liobn = 0; 11.225 + di->di_window.dw_base_hi = 0; 11.226 + di->di_window.dw_base = 0; 11.227 + 11.228 + /* lets see if the devtree has more info */ 11.229 + n = ofd_node_find(ofd_p, "/dart"); 11.230 + if (n > 0) { 11.231 + ulong base; 11.232 + 11.233 + rc = ofd_getprop(ofd_p, n, "compatible", compat, sizeof (compat)); 11.234 + if (rc > 0) { 11.235 + if (strstr(compat, "u4")) { 11.236 + di->di_model = DART_U4; 11.237 + } 11.238 + } 11.239 + 11.240 + rc = ofd_getprop(ofd_p, n, "reg", &base, sizeof (base)); 11.241 + if (rc > 0) { 11.242 + di->di_base = base; 11.243 + } 11.244 + } 11.245 + return 0; 11.246 +} 11.247 + 11.248 +static int init_dart(void) 11.249 +{ 11.250 + ulong log_pgs; 11.251 + void *ofd_p; 11.252 + ofdn_t n; 11.253 + struct dart_info di; 11.254 + 11.255 + if (find_dart(&di)) 11.256 + return 0; 11.257 + 11.258 + /* Max size of 512 pages == 2MB == 1<<21. That siz is good enough for U4 */ 11.259 + log_pgs = U3_LOG_MAX_PAGES; 11.260 + dart_table = alloc_xenheap_pages(log_pgs); 11.261 + BUG_ON(dart_table == NULL); 11.262 + 11.263 + dart_entries = (1UL << (log_pgs + PAGE_SHIFT)) / sizeof (union dart_entry); 11.264 + di.di_window.dw_size = dart_entries << PAGE_SHIFT; 11.265 + 11.266 + /* Linux uses a dummy page, filling "empty" DART entries with a 11.267 + reference to this page to capture stray DMA's */ 11.268 + dummy_page = (ulong)alloc_xenheap_pages(1); 11.269 + memset((void *)dummy_page, 0, PAGE_SIZE); 11.270 + dummy_page >>= PAGE_SHIFT; 11.271 + 11.272 + printk("Initializing DART 0x%lx: tbl: %p[0x%lx] entries: 0x%lx\n", 11.273 + di.di_base, dart_table, 1UL << log_pgs, dart_entries); 11.274 + 11.275 + /* register this iommu */ 11.276 + iommu_register(di.di_window.dw_liobn, dart_put); 11.277 + 11.278 + switch (di.di_model) { 11.279 + case DART_U3: 11.280 + dops = u3_init(di.di_base, (ulong)dart_table, 1UL << log_pgs); 11.281 + break; 11.282 + case DART_U4: 11.283 + dops = u4_init(di.di_base, (ulong)dart_table, 1UL << log_pgs); 11.284 + break; 11.285 + } 11.286 + 11.287 + dart_clear(0, dart_entries); 11.288 + dops->do_inv_all(); 11.289 + 11.290 + /* fix up the devtree */ 11.291 + ofd_p = (void *)oftree; 11.292 + n = ofd_node_find(ofd_p, "/ht"); 11.293 + if (n > 0) { 11.294 + di.di_window.dw_size = dart_entries << PAGE_SHIFT; 11.295 + ofd_prop_add(ofd_p, n, "ibm,dma-window", &di.di_window, 11.296 + sizeof (di.di_window)); 11.297 + } else { 11.298 + panic("%s: no /ht node\n", __func__); 11.299 + } 11.300 + return 0; 11.301 +} 11.302 +__initcall(init_dart);
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/xen/arch/powerpc/dart.h Fri Jul 14 10:47:50 2006 +0100 12.3 @@ -0,0 +1,36 @@ 12.4 +/* 12.5 + * This program is free software; you can redistribute it and/or modify 12.6 + * it under the terms of the GNU General Public License as published by 12.7 + * the Free Software Foundation; either version 2 of the License, or 12.8 + * (at your option) any later version. 12.9 + * 12.10 + * This program is distributed in the hope that it will be useful, 12.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12.13 + * GNU General Public License for more details. 12.14 + * 12.15 + * You should have received a copy of the GNU General Public License 12.16 + * along with this program; if not, write to the Free Software 12.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 12.18 + * 12.19 + * Copyright (C) IBM Corp. 2005 12.20 + * 12.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 12.22 + */ 12.23 + 12.24 +#ifndef _DART_H 12.25 +#define _DART_H 12.26 + 12.27 +#include <xen/config.h> 12.28 +#include <xen/types.h> 12.29 + 12.30 +struct dart_ops { 12.31 + void (*do_inv_all)(void); 12.32 + void (*do_inv_entry)(ulong pg); 12.33 +}; 12.34 + 12.35 +extern struct dart_ops *u3_init(ulong base, ulong table, ulong dart_pages); 12.36 +extern struct dart_ops *u4_init(ulong base, ulong table, ulong dart_pages); 12.37 + 12.38 +#endif /* _DART_H */ 12.39 +
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/xen/arch/powerpc/dart_u3.c Fri Jul 14 10:47:50 2006 +0100 13.3 @@ -0,0 +1,108 @@ 13.4 +/* 13.5 + * This program is free software; you can redistribute it and/or modify 13.6 + * it under the terms of the GNU General Public License as published by 13.7 + * the Free Software Foundation; either version 2 of the License, or 13.8 + * (at your option) any later version. 13.9 + * 13.10 + * This program is distributed in the hope that it will be useful, 13.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13.13 + * GNU General Public License for more details. 13.14 + * 13.15 + * You should have received a copy of the GNU General Public License 13.16 + * along with this program; if not, write to the Free Software 13.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 13.18 + * 13.19 + * Copyright (C) IBM Corp. 2005 13.20 + * 13.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 13.22 + */ 13.23 + 13.24 +#undef DEBUG 13.25 + 13.26 +#include <xen/config.h> 13.27 +#include <xen/types.h> 13.28 +#include <xen/sched.h> 13.29 +#include <xen/mm.h> 13.30 +#include <public/xen.h> 13.31 +#include <asm/io.h> 13.32 +#include <asm/current.h> 13.33 +#include "tce.h" 13.34 +#include "iommu.h" 13.35 +#include "dart.h" 13.36 + 13.37 +union dart_ctl { 13.38 + u32 dc_word; 13.39 + struct { 13.40 + u32 dc_base:20; 13.41 + u32 dc_stop_access:1; 13.42 + u32 dc_invtlb:1; 13.43 + u32 dc_enable:1; 13.44 + u32 dc_size:9; 13.45 + } reg; 13.46 +}; 13.47 + 13.48 +static u32 volatile *dart_ctl_reg; 13.49 + 13.50 +static void u3_inv_all(void) 13.51 +{ 13.52 + union dart_ctl dc; 13.53 + ulong r = 0; 13.54 + int l = 0; 13.55 + 13.56 + for (;;) { 13.57 + dc.dc_word = in_32(dart_ctl_reg); 13.58 + dc.reg.dc_invtlb = 1; 13.59 + out_32(dart_ctl_reg, dc.dc_word); 13.60 + 13.61 + do { 13.62 + dc.dc_word = in_32(dart_ctl_reg); 13.63 + r++; 13.64 + } while ((dc.reg.dc_invtlb == 1) && (r < (1 << l))); 13.65 + 13.66 + if (r == (1 << l)) { 13.67 + if (l < 4) { 13.68 + l++; 13.69 + dc.dc_word = in_32(dart_ctl_reg); 13.70 + dc.reg.dc_invtlb = 0; 13.71 + out_32(dart_ctl_reg, dc.dc_word); 13.72 + continue; 13.73 + } else { 13.74 + panic(" broken U3???\n"); 13.75 + } 13.76 + } 13.77 + return; 13.78 + } 13.79 +} 13.80 + 13.81 +static void u3_inv_entry(ulong pg) 13.82 +{ 13.83 + /* sadly single entry invalidation has been reported not to work */ 13.84 + u3_inv_all(); 13.85 +} 13.86 + 13.87 +static struct dart_ops u3_ops = { 13.88 + .do_inv_all = u3_inv_all, 13.89 + .do_inv_entry = u3_inv_entry, 13.90 +}; 13.91 + 13.92 +struct dart_ops *u3_init(ulong base, ulong table, ulong dart_pages) 13.93 +{ 13.94 + union dart_ctl dc; 13.95 + 13.96 + dart_ctl_reg = (u32 *)base; 13.97 + 13.98 + dc.dc_word = 0; 13.99 + 13.100 + dc.reg.dc_base = table >> PAGE_SHIFT; 13.101 + dc.reg.dc_size = dart_pages; 13.102 + dc.reg.dc_enable = 1; 13.103 + 13.104 + 13.105 + printk("Initializing DART Model U3: reg: %p word: %x\n", 13.106 + dart_ctl_reg, dc.dc_word); 13.107 + 13.108 + out_32(dart_ctl_reg, dc.dc_word); 13.109 + 13.110 + return &u3_ops; 13.111 +}
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/xen/arch/powerpc/dart_u4.c Fri Jul 14 10:47:50 2006 +0100 14.3 @@ -0,0 +1,177 @@ 14.4 +/* 14.5 + * This program is free software; you can redistribute it and/or modify 14.6 + * it under the terms of the GNU General Public License as published by 14.7 + * the Free Software Foundation; either version 2 of the License, or 14.8 + * (at your option) any later version. 14.9 + * 14.10 + * This program is distributed in the hope that it will be useful, 14.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 14.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14.13 + * GNU General Public License for more details. 14.14 + * 14.15 + * You should have received a copy of the GNU General Public License 14.16 + * along with this program; if not, write to the Free Software 14.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 14.18 + * 14.19 + * Copyright (C) IBM Corp. 2005 14.20 + * 14.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 14.22 + */ 14.23 + 14.24 +#undef DEBUG 14.25 + 14.26 +#include <xen/config.h> 14.27 +#include <xen/types.h> 14.28 +#include <xen/sched.h> 14.29 +#include <xen/init.h> 14.30 +#include <xen/mm.h> 14.31 +#include <public/xen.h> 14.32 +#include <asm/io.h> 14.33 +#include <asm/current.h> 14.34 +#include "tce.h" 14.35 +#include "iommu.h" 14.36 +#include "dart.h" 14.37 + 14.38 +#define TOO_MANY_RETRIES ~0 14.39 + 14.40 +union dart_ctl { 14.41 + u32 dc_word; 14.42 + struct { 14.43 + u32 dc_darten:1; /* DART Enable (0:disabled) */ 14.44 + u32 dc_ione:1; /* Invalidate one DART TLB entry (using ILPN) */ 14.45 + u32 dc_iall:1; /* Invalidate all DART TLB entries */ 14.46 + u32 dc_idle:1; /* DART is idle */ 14.47 + u32 dc_peen:1; /* Parity Checking is enabled */ 14.48 + u32 dc_ilpn:27; /* 27-bit Logical Page Address for 14.49 + * invalidating one TLB entry */ 14.50 + } dc_bits; 14.51 +}; 14.52 + 14.53 +union dart_base { 14.54 + u32 db_word; 14.55 + struct { 14.56 + u32 _db_resv:8; 14.57 + u32 db_dartbase:24; /* Base Address of DART (4K byte Alignment) */ 14.58 + } db_bits; 14.59 +}; 14.60 + 14.61 +union dart_size { 14.62 + u32 ds_word; 14.63 + struct { 14.64 + u32 _ds_resv:15; 14.65 + u32 ds_dartsize:17; /* Size of Dart in 4K-Byte Pages */ 14.66 + } ds_bits; 14.67 +}; 14.68 + 14.69 +union dart_excp { 14.70 + u32 de_word; 14.71 + struct { 14.72 + u32 de_rqsrc:1; /* Request Source. [0:PCIE, 1:HT] */ 14.73 + u32 de_lpn:27; /* 27Ðbit Logical Address of Exception [25:51] */ 14.74 + u32 de_rqop:1; /* Request operation. [0:Read, 1:Write] */ 14.75 + u32 de_xcd:3; /* Exception code */ 14.76 + } de_bits; 14.77 +}; 14.78 + 14.79 +struct dart { 14.80 + /* 0x00 */ 14.81 + union dart_ctl d_dartcntl; 14.82 + u32 _pad0x04_0x10[3]; 14.83 + /* 0x10 */ 14.84 + union dart_base d_dartbase; 14.85 + u32 _pad0x14_0x20[3]; 14.86 + /* 0x20 */ 14.87 + union dart_size d_dartsize; 14.88 + u32 _pad0x24_0x30[3]; 14.89 + /* 0x30 */ 14.90 + union dart_excp d_dartexcp; 14.91 + u32 _pad0x34_0x40[3]; 14.92 +}; 14.93 + 14.94 +static volatile struct dart *dart; 14.95 + 14.96 +static void u4_inv_all(void) 14.97 +{ 14.98 + union dart_ctl dc; 14.99 + ulong r = 0; 14.100 + int l = 0; 14.101 + 14.102 + for (;;) { 14.103 + dc.dc_word = in_32(&dart->d_dartcntl.dc_word); 14.104 + dc.dc_bits.dc_iall = 1; 14.105 + out_32(&dart->d_dartcntl.dc_word, dc.dc_word); 14.106 + 14.107 + do { 14.108 + dc.dc_word = in_32(&dart->d_dartcntl.dc_word); 14.109 + r++; 14.110 + } while ((dc.dc_bits.dc_iall == 1) && (r < (1 << l))); 14.111 + 14.112 + if (r == (1 << l)) { 14.113 + if (l < 4) { 14.114 + l++; 14.115 + dc.dc_word = in_32(&dart->d_dartcntl.dc_word); 14.116 + dc.dc_bits.dc_iall = 0; 14.117 + out_32(&dart->d_dartcntl.dc_word, dc.dc_word); 14.118 + continue; 14.119 + } else { 14.120 + panic(" broken U4???\n"); 14.121 + } 14.122 + } 14.123 + return; 14.124 + } 14.125 +} 14.126 + 14.127 +static void u4_inv_entry(ulong pgn) 14.128 +{ 14.129 + union dart_ctl dc; 14.130 + ulong retries = 0; 14.131 + 14.132 + dc.dc_word = in_32(&dart->d_dartcntl.dc_word); 14.133 + dc.dc_bits.dc_ilpn = pgn; 14.134 + dc.dc_bits.dc_ione = 1; 14.135 + out_32(&dart->d_dartcntl.dc_word, dc.dc_word); 14.136 + 14.137 + /* wait for completion */ 14.138 + /* FIXME: since we do this from the HV do we need to wait?! */ 14.139 + do { 14.140 + dc.dc_word = in_32(&dart->d_dartcntl.dc_word); 14.141 + retries++; 14.142 + if (retries > 1000000) 14.143 + panic("WAY! too long\n"); 14.144 + } while (dc.dc_bits.dc_ione != 0); 14.145 +} 14.146 + 14.147 +static struct dart_ops u4_ops = { 14.148 + .do_inv_all = u4_inv_all, 14.149 + .do_inv_entry = u4_inv_entry, 14.150 +}; 14.151 + 14.152 +struct dart_ops *u4_init(ulong base, ulong table, ulong dart_pages) 14.153 +{ 14.154 + union dart_base db; 14.155 + union dart_size ds; 14.156 + union dart_ctl dc; 14.157 + 14.158 + dart = (struct dart *)base; 14.159 + 14.160 + db.db_word = 0; 14.161 + db.db_bits.db_dartbase = table >> PAGE_SHIFT; 14.162 + 14.163 + ds.ds_word = 0; 14.164 + ds.ds_bits.ds_dartsize = dart_pages; 14.165 + 14.166 + dc.dc_word = in_32(&dart->d_dartcntl.dc_word); 14.167 + if (dc.dc_bits.dc_darten == 1) { 14.168 + panic("%s: dart is already enabled: 0x%x\n", __func__, dc.dc_word); 14.169 + } 14.170 + dc.dc_bits.dc_darten = 1; /* enable it */ 14.171 + 14.172 + printk("Initializing DART Model U4: ctl: 0x%x base: 0x%x size: 0x%x\n", 14.173 + dc.dc_word, db.db_word, ds.ds_word); 14.174 + 14.175 + out_32(&dart->d_dartbase.db_word, db.db_word); 14.176 + out_32(&dart->d_dartsize.ds_word, ds.ds_word); 14.177 + out_32(&dart->d_dartcntl.dc_word, dc.dc_word); 14.178 + 14.179 + return &u4_ops; 14.180 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/xen/arch/powerpc/delay.c Fri Jul 14 10:47:50 2006 +0100 15.3 @@ -0,0 +1,37 @@ 15.4 +/* 15.5 + * This program is free software; you can redistribute it and/or modify 15.6 + * it under the terms of the GNU General Public License as published by 15.7 + * the Free Software Foundation; either version 2 of the License, or 15.8 + * (at your option) any later version. 15.9 + * 15.10 + * This program is distributed in the hope that it will be useful, 15.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 15.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15.13 + * GNU General Public License for more details. 15.14 + * 15.15 + * You should have received a copy of the GNU General Public License 15.16 + * along with this program; if not, write to the Free Software 15.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 15.18 + * 15.19 + * Copyright (C) IBM Corp. 2005 15.20 + * 15.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 15.22 + */ 15.23 + 15.24 +#include <xen/config.h> 15.25 +#include <xen/delay.h> 15.26 +#include <xen/time.h> 15.27 +#include <asm/processor.h> 15.28 + 15.29 +void udelay(unsigned long usecs) 15.30 +{ 15.31 + ulong ticks = usecs * ticks_per_usec; 15.32 + ulong s; 15.33 + ulong e; 15.34 + 15.35 + s = get_timebase(); 15.36 + do { 15.37 + asm volatile("or 1,1,1"); /* also puts the thread to low priority */ 15.38 + e = get_timebase(); 15.39 + } while ((e-s) < ticks); 15.40 +}
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/xen/arch/powerpc/dom0_ops.c Fri Jul 14 10:47:50 2006 +0100 16.3 @@ -0,0 +1,87 @@ 16.4 +/* 16.5 + * This program is free software; you can redistribute it and/or modify 16.6 + * it under the terms of the GNU General Public License as published by 16.7 + * the Free Software Foundation; either version 2 of the License, or 16.8 + * (at your option) any later version. 16.9 + * 16.10 + * This program is distributed in the hope that it will be useful, 16.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 16.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16.13 + * GNU General Public License for more details. 16.14 + * 16.15 + * You should have received a copy of the GNU General Public License 16.16 + * along with this program; if not, write to the Free Software 16.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16.18 + * 16.19 + * Copyright (C) IBM Corp. 2005 16.20 + * 16.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 16.22 + */ 16.23 + 16.24 +#include <xen/config.h> 16.25 +#include <xen/types.h> 16.26 +#include <xen/lib.h> 16.27 +#include <xen/sched.h> 16.28 +#include <xen/guest_access.h> 16.29 +#include <public/xen.h> 16.30 +#include <public/dom0_ops.h> 16.31 + 16.32 +extern void arch_getdomaininfo_ctxt(struct vcpu *v, vcpu_guest_context_t *c); 16.33 +extern long arch_do_dom0_op(struct dom0_op *op, XEN_GUEST_HANDLE(dom0_op_t) u_dom0_op); 16.34 + 16.35 +void arch_getdomaininfo_ctxt(struct vcpu *v, vcpu_guest_context_t *c) 16.36 +{ 16.37 + memcpy(&c->user_regs, &v->arch.ctxt, sizeof(struct cpu_user_regs)); 16.38 + /* XXX fill in rest of vcpu_guest_context_t */ 16.39 +} 16.40 + 16.41 +long arch_do_dom0_op(struct dom0_op *op, XEN_GUEST_HANDLE(dom0_op_t) u_dom0_op) 16.42 +{ 16.43 + long ret = 0; 16.44 + 16.45 + switch (op->cmd) { 16.46 + case DOM0_GETMEMLIST: { 16.47 + /* XXX 64M hackage */ 16.48 + const int memsize = (64UL<<20); 16.49 + int domain_pfns = memsize>>12; 16.50 + int max_pfns = op->u.getmemlist.max_pfns; 16.51 + int domid = op->u.getmemlist.domain; 16.52 + int i; 16.53 + 16.54 + for (i = 0; (i < max_pfns) && (i < domain_pfns); i++) { 16.55 + xen_pfn_t mfn = (((domid + 1) * memsize) >> 12) + i; 16.56 + if (copy_to_guest_offset(op->u.getmemlist.buffer, i, &mfn, 1)) { 16.57 + ret = -EFAULT; 16.58 + break; 16.59 + } 16.60 + } 16.61 + op->u.getmemlist.num_pfns = i; 16.62 + copy_to_guest(u_dom0_op, op, 1); 16.63 + } 16.64 + break; 16.65 + 16.66 + case DOM0_PHYSINFO: 16.67 + { 16.68 + dom0_physinfo_t *pi = &op->u.physinfo; 16.69 + 16.70 + pi->threads_per_core = 1; 16.71 + pi->cores_per_socket = 1; 16.72 + pi->sockets_per_node = 1; 16.73 + pi->nr_nodes = 1; 16.74 + pi->total_pages = total_pages; 16.75 + pi->free_pages = avail_domheap_pages(); 16.76 + pi->cpu_khz = cpu_khz; 16.77 + memset(pi->hw_cap, 0, sizeof(pi->hw_cap)); 16.78 + ret = 0; 16.79 + if ( copy_to_guest(u_dom0_op, op, 1) ) 16.80 + ret = -EFAULT; 16.81 + } 16.82 + break; 16.83 + 16.84 + default: 16.85 + ret = -ENOSYS; 16.86 + break; 16.87 + } 16.88 + 16.89 + return ret; 16.90 +}
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/xen/arch/powerpc/domain.c Fri Jul 14 10:47:50 2006 +0100 17.3 @@ -0,0 +1,251 @@ 17.4 +/* 17.5 + * This program is free software; you can redistribute it and/or modify 17.6 + * it under the terms of the GNU General Public License as published by 17.7 + * the Free Software Foundation; either version 2 of the License, or 17.8 + * (at your option) any later version. 17.9 + * 17.10 + * This program is distributed in the hope that it will be useful, 17.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 17.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17.13 + * GNU General Public License for more details. 17.14 + * 17.15 + * You should have received a copy of the GNU General Public License 17.16 + * along with this program; if not, write to the Free Software 17.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17.18 + * 17.19 + * Copyright (C) IBM Corp. 2005, 2006 17.20 + * 17.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 17.22 + */ 17.23 + 17.24 +#include <stdarg.h> 17.25 +#include <xen/config.h> 17.26 +#include <xen/lib.h> 17.27 +#include <xen/sched.h> 17.28 +#include <xen/mm.h> 17.29 +#include <xen/serial.h> 17.30 +#include <xen/domain.h> 17.31 +#include <xen/console.h> 17.32 +#include <xen/reboot.h> 17.33 +#include <asm/htab.h> 17.34 +#include <asm/current.h> 17.35 +#include <asm/hcalls.h> 17.36 + 17.37 +extern void idle_loop(void); 17.38 + 17.39 +#define next_arg(fmt, args) ({ \ 17.40 + unsigned long __arg; \ 17.41 + switch ( *(fmt)++ ) \ 17.42 + { \ 17.43 + case 'i': __arg = (unsigned long)va_arg(args, unsigned int); break; \ 17.44 + case 'l': __arg = (unsigned long)va_arg(args, unsigned long); break; \ 17.45 + case 'p': __arg = (unsigned long)va_arg(args, void *); break; \ 17.46 + case 'h': __arg = (unsigned long)va_arg(args, void *); break; \ 17.47 + default: __arg = 0; BUG(); \ 17.48 + } \ 17.49 + __arg; \ 17.50 +}) 17.51 + 17.52 +unsigned long hypercall_create_continuation(unsigned int op, 17.53 + const char *format, ...) 17.54 +{ 17.55 + struct cpu_user_regs *regs = guest_cpu_user_regs(); 17.56 + const char *p = format; 17.57 + va_list args; 17.58 + int gprnum = 4; 17.59 + int i; 17.60 + 17.61 + va_start(args, format); 17.62 + 17.63 + regs->pc -= 4; /* re-execute 'sc' */ 17.64 + 17.65 + for (i = 0; *p != '\0'; i++) { 17.66 + regs->gprs[gprnum++] = next_arg(p, args); 17.67 + } 17.68 + 17.69 + va_end(args); 17.70 + 17.71 + /* As luck would have it, we use the same register for hcall opcodes and 17.72 + * for hcall return values. The return value from this function is placed 17.73 + * in r3 on return, so modifying regs->gprs[3] would have no effect. */ 17.74 + return XEN_MARK(op); 17.75 +} 17.76 + 17.77 +int arch_domain_create(struct domain *d) 17.78 +{ 17.79 + 17.80 + if (d->domain_id == IDLE_DOMAIN_ID) { 17.81 + d->shared_info = (void *)alloc_xenheap_page(); 17.82 + clear_page(d->shared_info); 17.83 + 17.84 + return 0; 17.85 + } 17.86 + 17.87 + /* XXX the hackage... hardcode 64M domains */ 17.88 + d->arch.rma_base = (64<<20) * (d->domain_id + 1); 17.89 + d->arch.rma_size = (64<<20); 17.90 + 17.91 + printk("clearing RMO: 0x%lx[0x%lx]\n", d->arch.rma_base, d->arch.rma_size); 17.92 + memset((void*)d->arch.rma_base, 0, d->arch.rma_size); 17.93 + 17.94 + htab_alloc(d, LOG_DEFAULT_HTAB_BYTES); 17.95 + 17.96 + d->shared_info = (shared_info_t *) 17.97 + (rma_addr(&d->arch, RMA_SHARED_INFO) + d->arch.rma_base); 17.98 + 17.99 + d->arch.large_page_sizes = 1; 17.100 + d->arch.large_page_shift[0] = 24; /* 16 M for 970s */ 17.101 + 17.102 + return 0; 17.103 +} 17.104 + 17.105 +void arch_domain_destroy(struct domain *d) 17.106 +{ 17.107 + unimplemented(); 17.108 +} 17.109 + 17.110 +void machine_halt(void) 17.111 +{ 17.112 + printf("machine_halt called: spinning....\n"); 17.113 + console_start_sync(); 17.114 + while(1); 17.115 +} 17.116 + 17.117 +void machine_restart(char * __unused) 17.118 +{ 17.119 + printf("machine_restart called: spinning....\n"); 17.120 + console_start_sync(); 17.121 + while(1); 17.122 +} 17.123 + 17.124 +struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id) 17.125 +{ 17.126 + struct vcpu *v; 17.127 + 17.128 + if ( (v = xmalloc(struct vcpu)) == NULL ) 17.129 + return NULL; 17.130 + 17.131 + memset(v, 0, sizeof(*v)); 17.132 + v->vcpu_id = vcpu_id; 17.133 + 17.134 + return v; 17.135 +} 17.136 + 17.137 +void free_vcpu_struct(struct vcpu *v) 17.138 +{ 17.139 + BUG_ON(v->next_in_list != NULL); 17.140 + if ( v->vcpu_id != 0 ) 17.141 + v->domain->vcpu[v->vcpu_id - 1]->next_in_list = NULL; 17.142 + xfree(v); 17.143 +} 17.144 + 17.145 +int arch_set_info_guest(struct vcpu *v, vcpu_guest_context_t *c) 17.146 +{ 17.147 + memcpy(&v->arch.ctxt, &c->user_regs, sizeof(c->user_regs)); 17.148 + 17.149 + set_bit(_VCPUF_initialised, &v->vcpu_flags); 17.150 + 17.151 + cpu_init_vcpu(v); 17.152 + 17.153 + return 0; 17.154 +} 17.155 + 17.156 +void dump_pageframe_info(struct domain *d) 17.157 +{ 17.158 + struct page_info *page; 17.159 + 17.160 + printk("Memory pages belonging to domain %u:\n", d->domain_id); 17.161 + 17.162 + if ( d->tot_pages >= 10 ) 17.163 + { 17.164 + printk(" DomPage list too long to display\n"); 17.165 + } 17.166 + else 17.167 + { 17.168 + list_for_each_entry ( page, &d->page_list, list ) 17.169 + { 17.170 + printk(" DomPage %p: mfn=%p, caf=%016lx, taf=%" PRtype_info "\n", 17.171 + _p(page_to_maddr(page)), _p(page_to_mfn(page)), 17.172 + page->count_info, page->u.inuse.type_info); 17.173 + } 17.174 + } 17.175 + 17.176 + list_for_each_entry ( page, &d->xenpage_list, list ) 17.177 + { 17.178 + printk(" XenPage %p: mfn=%p, caf=%016lx, taf=%" PRtype_info "\n", 17.179 + _p(page_to_maddr(page)), _p(page_to_mfn(page)), 17.180 + page->count_info, page->u.inuse.type_info); 17.181 + } 17.182 +} 17.183 + 17.184 + 17.185 +void context_switch(struct vcpu *prev, struct vcpu *next) 17.186 +{ 17.187 + struct cpu_user_regs *stack_regs = guest_cpu_user_regs(); 17.188 + cpumask_t dirty_mask = next->vcpu_dirty_cpumask; 17.189 + unsigned int cpu = smp_processor_id(); 17.190 + 17.191 +#if 0 17.192 + printf("%s: dom %x to dom %x\n", __func__, prev->domain->domain_id, 17.193 + next->domain->domain_id); 17.194 +#endif 17.195 + 17.196 + /* Allow at most one CPU at a time to be dirty. */ 17.197 + ASSERT(cpus_weight(dirty_mask) <= 1); 17.198 + if (unlikely(!cpu_isset(cpu, dirty_mask) && !cpus_empty(dirty_mask))) 17.199 + { 17.200 + /* Other cpus call __sync_lazy_execstate from flush ipi handler. */ 17.201 + if (!cpus_empty(next->vcpu_dirty_cpumask)) 17.202 + flush_tlb_mask(next->vcpu_dirty_cpumask); 17.203 + } 17.204 + 17.205 + /* copy prev guest state off the stack into its vcpu */ 17.206 + memcpy(&prev->arch.ctxt, stack_regs, sizeof(struct cpu_user_regs)); 17.207 + 17.208 + set_current(next); 17.209 + 17.210 + /* copy next guest state onto the stack */ 17.211 + memcpy(stack_regs, &next->arch.ctxt, sizeof(struct cpu_user_regs)); 17.212 + 17.213 + /* save old domain state */ 17.214 + save_sprs(prev); 17.215 + save_float(prev); 17.216 + save_segments(prev); 17.217 + 17.218 + context_saved(prev); 17.219 + 17.220 + /* load up new domain */ 17.221 + load_sprs(next); 17.222 + load_float(next); 17.223 + load_segments(next); 17.224 + 17.225 + mtsdr1(next->domain->arch.htab.sdr1); 17.226 + local_flush_tlb(); /* XXX maybe flush_tlb_mask? */ 17.227 + 17.228 + if (is_idle_vcpu(next)) { 17.229 + reset_stack_and_jump(idle_loop); 17.230 + } 17.231 + 17.232 + reset_stack_and_jump(full_resume); 17.233 + /* not reached */ 17.234 +} 17.235 + 17.236 +void continue_running(struct vcpu *same) 17.237 +{ 17.238 + /* nothing to do */ 17.239 +} 17.240 + 17.241 +void sync_vcpu_execstate(struct vcpu *v) 17.242 +{ 17.243 + /* XXX for now, for domain destruction, make this non-fatal */ 17.244 + printf("%s: called\n", __func__); 17.245 +} 17.246 + 17.247 +void domain_relinquish_resources(struct domain *d) 17.248 +{ 17.249 + /* nothing to do? */ 17.250 +} 17.251 + 17.252 +void arch_dump_domain_info(struct domain *d) 17.253 +{ 17.254 +}
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/xen/arch/powerpc/domain_build.c Fri Jul 14 10:47:50 2006 +0100 18.3 @@ -0,0 +1,285 @@ 18.4 +/* 18.5 + * This program is free software; you can redistribute it and/or modify 18.6 + * it under the terms of the GNU General Public License as published by 18.7 + * the Free Software Foundation; either version 2 of the License, or 18.8 + * (at your option) any later version. 18.9 + * 18.10 + * This program is distributed in the hope that it will be useful, 18.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 18.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18.13 + * GNU General Public License for more details. 18.14 + * 18.15 + * You should have received a copy of the GNU General Public License 18.16 + * along with this program; if not, write to the Free Software 18.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18.18 + * 18.19 + * Copyright (C) IBM Corp. 2005 18.20 + * 18.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 18.22 + */ 18.23 + 18.24 +#include <xen/config.h> 18.25 +#include <xen/lib.h> 18.26 +#include <xen/elf.h> 18.27 +#include <xen/sched.h> 18.28 +#include <xen/init.h> 18.29 +#include <xen/ctype.h> 18.30 +#include <xen/iocap.h> 18.31 +#include <xen/compile.h> 18.32 +#include <asm/processor.h> 18.33 +#include <asm/papr.h> 18.34 +#include "oftree.h" 18.35 + 18.36 +extern int parseelfimage_32(struct domain_setup_info *dsi); 18.37 +extern int loadelfimage_32(struct domain_setup_info *dsi); 18.38 + 18.39 +/* opt_dom0_mem: memory allocated to domain 0. */ 18.40 +static unsigned int opt_dom0_mem; 18.41 +static void parse_dom0_mem(char *s) 18.42 +{ 18.43 + unsigned long long bytes = parse_size_and_unit(s); 18.44 + /* If no unit is specified we default to kB units, not bytes. */ 18.45 + if (isdigit(s[strlen(s)-1])) 18.46 + opt_dom0_mem = (unsigned int)bytes; 18.47 + else 18.48 + opt_dom0_mem = (unsigned int)(bytes >> 10); 18.49 +} 18.50 +custom_param("dom0_mem", parse_dom0_mem); 18.51 + 18.52 +int elf_sanity_check(Elf_Ehdr *ehdr) 18.53 +{ 18.54 + if (IS_ELF(*ehdr)) 18.55 + /* we are happy with either */ 18.56 + if ((ehdr->e_ident[EI_CLASS] == ELFCLASS32 18.57 + && ehdr->e_machine == EM_PPC) 18.58 + || (ehdr->e_ident[EI_CLASS] == ELFCLASS64 18.59 + && ehdr->e_machine == EM_PPC64)) { 18.60 + if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB 18.61 + && ehdr->e_type == ET_EXEC) 18.62 + return 1; 18.63 + } 18.64 + printk("DOM0 image is not a Xen-compatible Elf image.\n"); 18.65 + return 0; 18.66 +} 18.67 + 18.68 +/* adapted from common/elf.c */ 18.69 +#define RM_MASK(a,l) ((a) & ((1UL << (l)) - 1)) 18.70 + 18.71 +static int rm_loadelfimage_64(struct domain_setup_info *dsi, ulong rma) 18.72 +{ 18.73 + char *elfbase = (char *)dsi->image_addr; 18.74 + Elf64_Ehdr *ehdr = (Elf64_Ehdr *)dsi->image_addr; 18.75 + Elf64_Phdr *phdr; 18.76 + int h; 18.77 + 18.78 + for (h = 0; h < ehdr->e_phnum; h++ ) 18.79 + { 18.80 + phdr = (Elf64_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize)); 18.81 + if (!((phdr->p_type == PT_LOAD) && 18.82 + ((phdr->p_flags & (PF_W|PF_X)) != 0))) 18.83 + continue; 18.84 + 18.85 + if (phdr->p_filesz != 0) 18.86 + memcpy((char *)(rma + RM_MASK(phdr->p_paddr, 42)), 18.87 + elfbase + phdr->p_offset, 18.88 + phdr->p_filesz); 18.89 + if (phdr->p_memsz > phdr->p_filesz) 18.90 + memset((char *)(rma + RM_MASK(phdr->p_paddr, 42) + phdr->p_filesz), 18.91 + 0, phdr->p_memsz - phdr->p_filesz); 18.92 + } 18.93 + 18.94 +#ifdef NOT_YET 18.95 + loadelfsymtab(dsi, 1); 18.96 +#endif 18.97 + 18.98 + return 0; 18.99 +} 18.100 + 18.101 +int construct_dom0(struct domain *d, 18.102 + unsigned long image_start, unsigned long image_len, 18.103 + unsigned long initrd_start, unsigned long initrd_len, 18.104 + char *cmdline) 18.105 +{ 18.106 + int rc; 18.107 + struct vcpu *v = d->vcpu[0]; 18.108 + struct domain_setup_info dsi; 18.109 + ulong dst; 18.110 + u64 *ofh_tree; 18.111 + ulong rma_sz = d->arch.rma_size; 18.112 + ulong rma = d->arch.rma_base; 18.113 + start_info_t *si; 18.114 + ulong eomem; 18.115 + int am64 = 1; 18.116 + ulong msr; 18.117 + ulong pc; 18.118 + ulong r2; 18.119 + 18.120 + /* Sanity! */ 18.121 + BUG_ON(d->domain_id != 0); 18.122 + BUG_ON(d->vcpu[0] == NULL); 18.123 + 18.124 + cpu_init_vcpu(v); 18.125 + 18.126 + memset(&dsi, 0, sizeof(struct domain_setup_info)); 18.127 + dsi.image_addr = image_start; 18.128 + dsi.image_len = image_len; 18.129 + 18.130 + if ((rc = parseelfimage(&dsi)) != 0) { 18.131 + if ((rc = parseelfimage_32(&dsi)) != 0) 18.132 + return rc; 18.133 + am64 = 0; 18.134 + } 18.135 + 18.136 + /* elf contains virtual addresses that can have the upper bits 18.137 + * masked while running in real mode, so we do the masking as well 18.138 + * as well */ 18.139 + dsi.v_kernstart = RM_MASK(dsi.v_kernstart, 42); 18.140 + dsi.v_kernend = RM_MASK(dsi.v_kernend, 42); 18.141 + dsi.v_kernentry = RM_MASK(dsi.v_kernentry, 42); 18.142 + 18.143 + if (dsi.xen_section_string == NULL) { 18.144 + printk("Not a Xen-ELF image: '__xen_guest' section not found.\n"); 18.145 + return -EINVAL; 18.146 + } 18.147 + printk("*** LOADING DOMAIN 0 ***\n"); 18.148 + 18.149 + /* By default DOM0 is allocated all available memory. */ 18.150 + d->max_pages = ~0U; 18.151 + d->tot_pages = (d->arch.rma_size >> PAGE_SHIFT); 18.152 + 18.153 + ASSERT( image_len < rma_sz ); 18.154 + 18.155 + si = (start_info_t *)(rma_addr(&d->arch, RMA_START_INFO) + rma); 18.156 + printk("xen_start_info: %p\n", si); 18.157 + 18.158 + sprintf(si->magic, "xen-%i.%i-powerpc%d%s", 18.159 + XEN_VERSION, XEN_SUBVERSION, BITS_PER_LONG, "HV"); 18.160 + si->flags = SIF_PRIVILEGED | SIF_INITDOMAIN; 18.161 + 18.162 + si->shared_info = ((ulong)d->shared_info) - rma; 18.163 + printk("shared_info: 0x%lx,%p\n", si->shared_info, d->shared_info); 18.164 + 18.165 + eomem = si->shared_info; 18.166 + 18.167 + /* allow dom0 to access all of system RAM */ 18.168 + d->arch.logical_base_pfn = 128 << (20 - PAGE_SHIFT); /* 128 MB */ 18.169 + d->arch.logical_end_pfn = max_page; 18.170 + 18.171 + /* number of pages accessible */ 18.172 + si->nr_pages = rma_sz >> PAGE_SHIFT; 18.173 + 18.174 + si->pt_base = 0; 18.175 + si->nr_pt_frames = 0; 18.176 + si->mfn_list = 0; 18.177 + 18.178 + /* OF usually sits here: 18.179 + * - Linux needs it to be loaded before the vmlinux or initrd 18.180 + * - AIX demands it to be @ 32M. 18.181 + */ 18.182 + dst = (32 << 20); 18.183 + 18.184 + /* put stack below everything */ 18.185 + v->arch.ctxt.gprs[1] = dst - STACK_FRAME_OVERHEAD; 18.186 + 18.187 + /* copy relative to Xen */ 18.188 + dst += rma; 18.189 + 18.190 + ASSERT((dst - rma) + (ulong)firmware_image_size < eomem); 18.191 + printk("loading OFH: 0x%lx, RMA: 0x%lx\n", dst, dst - rma); 18.192 + memcpy((void *)dst, firmware_image_start, (ulong)firmware_image_size); 18.193 + 18.194 + v->arch.ctxt.gprs[5] = (dst - rma); 18.195 + ofh_tree = (u64 *)(dst + 0x10); 18.196 + ASSERT(*ofh_tree == 0xdeadbeef00000000); 18.197 + 18.198 + /* accomodate for a modest bss section */ 18.199 + dst = ALIGN_UP(dst + (ulong)firmware_image_size + PAGE_SIZE, PAGE_SIZE); 18.200 + ASSERT((dst - rma) + oftree_len < eomem); 18.201 + 18.202 + *ofh_tree = dst - rma; 18.203 + printk("loading OFD: 0x%lx RMA: 0x%lx, 0x%lx\n", dst, dst - rma, 18.204 + oftree_len); 18.205 + memcpy((void *)dst, (void *)oftree, oftree_len); 18.206 + 18.207 + dst = ALIGN_UP(dst + oftree_len, PAGE_SIZE); 18.208 + 18.209 + if (am64) { 18.210 + ulong kbase; 18.211 + ulong *fdesc; 18.212 + 18.213 + printk("loading 64-bit Dom0: 0x%lx, in RMA:0x%lx\n", dst, dst - rma); 18.214 + rm_loadelfimage_64(&dsi, dst); 18.215 + 18.216 + kbase = dst; 18.217 + /* move dst to end of bss */ 18.218 + dst = ALIGN_UP(dsi.v_kernend + dst, PAGE_SIZE); 18.219 + 18.220 + if ( initrd_len > 0 ) { 18.221 + ASSERT( (dst - rma) + image_len < eomem ); 18.222 + 18.223 + printk("loading initrd: 0x%lx, 0x%lx\n", dst, initrd_len); 18.224 + memcpy((void *)dst, (void *)initrd_start, initrd_len); 18.225 + 18.226 + si->mod_start = dst - rma; 18.227 + si->mod_len = image_len; 18.228 + 18.229 + dst = ALIGN_UP(dst + initrd_len, PAGE_SIZE); 18.230 + } else { 18.231 + printk("no initrd\n"); 18.232 + si->mod_start = 0; 18.233 + si->mod_len = 0; 18.234 + } 18.235 + /* it may be a function descriptor */ 18.236 + fdesc = (ulong *)(dsi.v_kernstart + dsi.v_kernentry + kbase); 18.237 + 18.238 + if (fdesc[2] == 0 18.239 + && ((fdesc[0] >= dsi.v_kernstart) 18.240 + && (fdesc[0] < dsi.v_kernend)) /* text entry is in range */ 18.241 + && ((fdesc[1] >= dsi.v_kernstart) /* toc can be > image */ 18.242 + && (fdesc[1] < (dsi.v_kernend + (0x7fff * sizeof (ulong)))))) { 18.243 + /* it is almost certainly a function descriptor */ 18.244 + pc = RM_MASK(fdesc[0], 42) + kbase - rma; 18.245 + r2 = RM_MASK(fdesc[1], 42) + kbase - rma; 18.246 + } else { 18.247 + pc = ((ulong)fdesc) - rma; 18.248 + r2 = 0; 18.249 + } 18.250 + msr = MSR_SF; 18.251 + } else { 18.252 + printk("loading 32-bit Dom0: 0x%lx, in RMA:0x%lx\n", 18.253 + dsi.v_kernstart + rma, dsi.v_kernstart); 18.254 + dsi.v_start = rma; 18.255 + loadelfimage_32(&dsi); 18.256 + 18.257 + pc = dsi.v_kernentry; 18.258 + r2 = 0; 18.259 + msr = 0; 18.260 + } 18.261 + 18.262 + v->arch.ctxt.gprs[3] = si->mod_start; 18.263 + v->arch.ctxt.gprs[4] = si->mod_len; 18.264 + 18.265 + memset(si->cmd_line, 0, sizeof(si->cmd_line)); 18.266 + if ( cmdline != NULL ) 18.267 + strncpy((char *)si->cmd_line, cmdline, sizeof(si->cmd_line)-1); 18.268 + 18.269 + v->arch.ctxt.msr = msr; 18.270 + v->arch.ctxt.pc = pc; 18.271 + v->arch.ctxt.gprs[2] = r2; 18.272 + 18.273 + printk("DOM: pc = 0x%lx, r2 = 0x%lx\n", pc, r2); 18.274 + 18.275 + ofd_dom0_fixup(d, *ofh_tree + rma, si, dst - rma); 18.276 + 18.277 + set_bit(_VCPUF_initialised, &v->vcpu_flags); 18.278 + 18.279 + rc = 0; 18.280 + 18.281 + /* DOM0 is permitted full I/O capabilities. */ 18.282 + rc |= iomem_permit_access(dom0, 0UL, ~0UL); 18.283 + rc |= irqs_permit_access(dom0, 0, NR_IRQS-1); 18.284 + 18.285 + BUG_ON(rc != 0); 18.286 + 18.287 + return 0; 18.288 +}
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 19.2 +++ b/xen/arch/powerpc/elf32.c Fri Jul 14 10:47:50 2006 +0100 19.3 @@ -0,0 +1,5 @@ 19.4 +#define parseelfimage parseelfimage_32 19.5 +#define loadelfimage loadelfimage_32 19.6 +#define ELFSIZE 32 19.7 +#include "../../common/elf.c" 19.8 +
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 20.2 +++ b/xen/arch/powerpc/exceptions.c Fri Jul 14 10:47:50 2006 +0100 20.3 @@ -0,0 +1,87 @@ 20.4 +/* 20.5 + * This program is free software; you can redistribute it and/or modify 20.6 + * it under the terms of the GNU General Public License as published by 20.7 + * the Free Software Foundation; either version 2 of the License, or 20.8 + * (at your option) any later version. 20.9 + * 20.10 + * This program is distributed in the hope that it will be useful, 20.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 20.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20.13 + * GNU General Public License for more details. 20.14 + * 20.15 + * You should have received a copy of the GNU General Public License 20.16 + * along with this program; if not, write to the Free Software 20.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20.18 + * 20.19 + * Copyright (C) IBM Corp. 2005, 2006 20.20 + * 20.21 + * Authors: Hollis Blanchard <hollisb@us.ibm.com> 20.22 + */ 20.23 + 20.24 +#include <xen/config.h> 20.25 +#include <xen/softirq.h> 20.26 +#include <xen/sched.h> 20.27 +#include <xen/serial.h> 20.28 +#include <xen/gdbstub.h> 20.29 +#include <public/xen.h> 20.30 +#include <asm/time.h> 20.31 + 20.32 +#undef DEBUG 20.33 +#define HDEC_PREEMPT 20.34 + 20.35 +extern ulong ppc_do_softirq(ulong orig_msr); 20.36 +extern void do_timer(struct cpu_user_regs *regs); 20.37 +extern void do_dec(struct cpu_user_regs *regs); 20.38 +extern void program_exception(struct cpu_user_regs *regs, unsigned long cookie); 20.39 + 20.40 +int hdec_sample = 0; 20.41 + 20.42 +void do_timer(struct cpu_user_regs *regs) 20.43 +{ 20.44 + /* XXX this is just here to keep HDEC from firing until 20.45 + * reprogram_ac_timer() sets the proper next-tick time */ 20.46 + mthdec(timebase_freq); 20.47 + 20.48 +#ifdef HDEC_PREEMPT 20.49 + raise_softirq(TIMER_SOFTIRQ); 20.50 +#endif 20.51 +#ifdef DEBUG 20.52 + { 20.53 + int d; 20.54 + if (regs->msr & MSR_HV) { 20.55 + d = -1; 20.56 + } else { 20.57 + d = get_current()->domain->domain_id; 20.58 + } 20.59 + extern char serial_getc_nb(int handle); 20.60 + if (0 && serial_getc_nb(0) > 0) { 20.61 + printk("H: pc: 0x%lx lr: 0x%lx \n", regs->pc, regs->lr); 20.62 + } 20.63 + if (hdec_sample) { 20.64 + printk("H: pc: 0x%lx lr: 0x%lx \n", regs->pc, regs->lr); 20.65 + hdec_sample = 0; 20.66 + } 20.67 + } 20.68 +#endif 20.69 +} 20.70 + 20.71 +void do_dec(struct cpu_user_regs *regs) 20.72 +{ 20.73 + if (!(regs->msr & MSR_HV)) { 20.74 + panic("HV dec from domain\n"); 20.75 + } 20.76 + printk("DEC_HV: pc: 0x%lx lr: 0x%lx \n", regs->pc, regs->lr); 20.77 + mtdec(INT_MAX); 20.78 +} 20.79 + 20.80 +void program_exception(struct cpu_user_regs *regs, unsigned long cookie) 20.81 +{ 20.82 +#ifdef CRASH_DEBUG 20.83 + __trap_to_gdb(regs, cookie); 20.84 +#else /* CRASH_DEBUG */ 20.85 + show_registers(regs); 20.86 + printk("dar 0x%016lx, dsisr 0x%08x\n", mfdar(), mfdsisr()); 20.87 + printk("hid4 0x%016lx\n", regs->hid4); 20.88 + panic("%s: 0x%lx\n", __func__, cookie); 20.89 +#endif /* CRASH_DEBUG */ 20.90 +}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/xen/arch/powerpc/exceptions.h Fri Jul 14 10:47:50 2006 +0100 21.3 @@ -0,0 +1,57 @@ 21.4 +/* 21.5 + * This program is free software; you can redistribute it and/or modify 21.6 + * it under the terms of the GNU General Public License as published by 21.7 + * the Free Software Foundation; either version 2 of the License, or 21.8 + * (at your option) any later version. 21.9 + * 21.10 + * This program is distributed in the hope that it will be useful, 21.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 21.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21.13 + * GNU General Public License for more details. 21.14 + * 21.15 + * You should have received a copy of the GNU General Public License 21.16 + * along with this program; if not, write to the Free Software 21.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 21.18 + * 21.19 + * Copyright (C) IBM Corp. 2005 21.20 + * 21.21 + * Authors: Hollis Blanchard <hollisb@us.ibm.com> 21.22 + */ 21.23 + 21.24 +#ifndef _ARCH_PPC_EXCEPTIONS_H_ 21.25 +#define _ARCH_PPC_EXCEPTIONS_H_ 21.26 + 21.27 +#include <xen/types.h> 21.28 +#include <public/xen.h> 21.29 +#include <xen/multiboot.h> 21.30 + 21.31 +extern void do_hcall(struct cpu_user_regs *regs); 21.32 +extern void do_IRQ(struct cpu_user_regs *regs); 21.33 +extern void deliver_ee(struct cpu_user_regs *regs); 21.34 +extern void do_external(struct cpu_user_regs *regs); 21.35 +extern void init_IRQ(void); 21.36 +extern void ack_APIC_irq(void); 21.37 +extern int ioapic_guest_read(unsigned long physbase, unsigned int reg, u32 *pval); 21.38 +extern int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val); 21.39 +extern void __start_xen_ppc( 21.40 + ulong r3, ulong r4, ulong r5, ulong r6, ulong r7, ulong orig_msr); 21.41 +extern multiboot_info_t *boot_of_init(ulong r3, ulong r4, ulong vec, ulong r6, ulong r7, ulong orig_msr); 21.42 + 21.43 +extern void do_timer(struct cpu_user_regs *regs); 21.44 +extern void do_dec(struct cpu_user_regs *regs); 21.45 +extern void program_exception( 21.46 + struct cpu_user_regs *regs, unsigned long cookie); 21.47 + 21.48 +extern long xen_hvcall_jump(struct cpu_user_regs *regs, ulong address); 21.49 +extern void *mambo_memset(void *, int, ulong); 21.50 +extern void *mambo_memcpy(void *, const void *, ulong); 21.51 + 21.52 +extern ulong *__hypercall_table[]; 21.53 + 21.54 +extern char exception_vectors[]; 21.55 +extern char exception_vectors_end[]; 21.56 +extern int spin_start[]; 21.57 +extern int firmware_image_start[0]; 21.58 +extern int firmware_image_size[0]; 21.59 + 21.60 +#endif
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 22.2 +++ b/xen/arch/powerpc/external.c Fri Jul 14 10:47:50 2006 +0100 22.3 @@ -0,0 +1,247 @@ 22.4 +/* 22.5 + * This program is free software; you can redistribute it and/or modify 22.6 + * it under the terms of the GNU General Public License as published by 22.7 + * the Free Software Foundation; either version 2 of the License, or 22.8 + * (at your option) any later version. 22.9 + * 22.10 + * This program is distributed in the hope that it will be useful, 22.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 22.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22.13 + * GNU General Public License for more details. 22.14 + * 22.15 + * You should have received a copy of the GNU General Public License 22.16 + * along with this program; if not, write to the Free Software 22.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 22.18 + * 22.19 + * Copyright (C) IBM Corp. 2005, 2006 22.20 + * 22.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 22.22 + */ 22.23 + 22.24 +#include <xen/config.h> 22.25 +#include <xen/types.h> 22.26 +#include <xen/sched.h> 22.27 +#include <xen/lib.h> 22.28 +#include <xen/event.h> 22.29 +#include <xen/irq.h> 22.30 +#include <public/xen.h> 22.31 +#include <asm/current.h> 22.32 +#include <asm/hardirq.h> 22.33 +#include <asm/mpic.h> 22.34 +#include "mpic_init.h" 22.35 +#include "exceptions.h" 22.36 + 22.37 +#undef DEBUG 22.38 +#ifdef DEBUG 22.39 +#define DBG(fmt...) printk(fmt) 22.40 +#else 22.41 +#define DBG(fmt...) 22.42 +#endif 22.43 + 22.44 +int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1}; 22.45 + 22.46 +unsigned long io_apic_irqs; 22.47 +int ioapic_ack_new = 1; 22.48 + 22.49 +static struct hw_interrupt_type *hc_irq; 22.50 + 22.51 +/* deliver_ee: called with interrupts off when resuming every vcpu */ 22.52 +void deliver_ee(struct cpu_user_regs *regs) 22.53 +{ 22.54 + const ulong srr_mask = ~(MSR_IR | MSR_DR | MSR_FE0 | MSR_FE1 | MSR_EE | 22.55 + MSR_RI | 22.56 + MSR_BE | MSR_FP | MSR_PMM | MSR_PR | MSR_SE); 22.57 + 22.58 + BUG_ON(mfmsr() & MSR_EE); 22.59 + BUG_ON(regs->msr & MSR_HV); 22.60 + 22.61 + if (!local_events_need_delivery()) 22.62 + return; 22.63 + 22.64 + /* XXX OS error: EE was set but RI was not. We could trigger a machine 22.65 + * check, or kill the domain... for now just crash Xen so we notice. */ 22.66 + BUG_ON(!(regs->msr & MSR_RI)); 22.67 + 22.68 + regs->srr0 = regs->pc; 22.69 + /* zero SRR1[33:36] and SRR1[42:47] */ 22.70 + regs->srr1 = regs->msr & ~0x00000000783f0000; 22.71 + regs->pc = 0x500; 22.72 + regs->msr &= srr_mask; 22.73 + regs->msr |= MSR_SF | MSR_ME; 22.74 + 22.75 + DBG("<HV: pc=0x%lx, msr=0x%lx\n", regs->pc, regs->msr); 22.76 +} 22.77 + 22.78 +void do_external(struct cpu_user_regs *regs) 22.79 +{ 22.80 + int vec; 22.81 + 22.82 + BUG_ON(!(regs->msr & MSR_EE)); 22.83 + BUG_ON(mfmsr() & MSR_EE); 22.84 + 22.85 + vec = xen_mpic_get_irq(regs); 22.86 + 22.87 + if (vec != -1) { 22.88 + DBG("EE:0x%lx isrc: %d\n", regs->msr, vec); 22.89 + regs->entry_vector = vec; 22.90 + do_IRQ(regs); 22.91 + 22.92 + BUG_ON(mfmsr() & MSR_EE); 22.93 + } 22.94 +} 22.95 + 22.96 +static int xen_local_irq(unsigned int irq) 22.97 +{ 22.98 + irq_desc_t *desc; 22.99 + unsigned int vector; 22.100 + 22.101 + vector = irq_to_vector(irq); 22.102 + desc = &irq_desc[vector]; 22.103 + 22.104 + return !(desc->status & IRQ_GUEST); 22.105 +} 22.106 + 22.107 +static unsigned int xen_startup_irq(unsigned int irq) 22.108 +{ 22.109 + DBG("%s(%d)\n", __func__, irq); 22.110 + if (xen_local_irq(irq)) { 22.111 + return hc_irq->startup(irq); 22.112 + } 22.113 + return 0; 22.114 +} 22.115 + 22.116 +static void xen_shutdown_irq(unsigned int irq) 22.117 +{ 22.118 + DBG("%s(%d)\n", __func__, irq); 22.119 + if (xen_local_irq(irq)) { 22.120 + hc_irq->shutdown(irq); 22.121 + } 22.122 +} 22.123 + 22.124 +static void xen_enable_irq(unsigned int irq) 22.125 +{ 22.126 + DBG("%s(%d)\n", __func__, irq); 22.127 + if (xen_local_irq(irq)) { 22.128 + hc_irq->enable(irq); 22.129 + } 22.130 +} 22.131 + 22.132 +static void xen_disable_irq(unsigned int irq) 22.133 +{ 22.134 + DBG("%s(%d)\n", __func__, irq); 22.135 + if (xen_local_irq(irq)) { 22.136 + hc_irq->disable(irq); 22.137 + } 22.138 +} 22.139 + 22.140 +static void xen_ack_irq(unsigned int irq) 22.141 +{ 22.142 + DBG("%s(%d)\n", __func__, irq); 22.143 + if (xen_local_irq(irq)) { 22.144 + if (hc_irq->ack) hc_irq->ack(irq); 22.145 + } 22.146 +} 22.147 + 22.148 +static void xen_end_irq(unsigned int irq) 22.149 +{ 22.150 + DBG("%s(%d)\n", __func__, irq); 22.151 + if (xen_local_irq(irq)) { 22.152 + hc_irq->end(irq); 22.153 + } 22.154 +} 22.155 + 22.156 +static void xen_set_affinity(unsigned int irq, cpumask_t mask) 22.157 +{ 22.158 + DBG("%s(%d)\n", __func__, irq); 22.159 + if (xen_local_irq(irq)) { 22.160 + if (hc_irq->set_affinity) hc_irq->set_affinity(irq, mask); 22.161 + } 22.162 +} 22.163 + 22.164 +static struct hw_interrupt_type xen_irq = { 22.165 + .startup = xen_startup_irq, 22.166 + .enable = xen_enable_irq, 22.167 + .disable = xen_disable_irq, 22.168 + .shutdown = xen_shutdown_irq, 22.169 + .ack = xen_ack_irq, 22.170 + .end = xen_end_irq, 22.171 + .set_affinity = xen_set_affinity, 22.172 +}; 22.173 + 22.174 +void init_IRQ(void) 22.175 +{ 22.176 + hc_irq = xen_mpic_init(&xen_irq); 22.177 +} 22.178 + 22.179 +void ack_APIC_irq(void) 22.180 +{ 22.181 + printk("%s: EOI the whole MPIC?\n", __func__); 22.182 + for (;;); 22.183 +} 22.184 + 22.185 +void ack_bad_irq(unsigned int irq) 22.186 +{ 22.187 + printk("unexpected IRQ trap at vector %02x\n", irq); 22.188 + /* 22.189 + * Currently unexpected vectors happen only on SMP and APIC. 22.190 + * We _must_ ack these because every local APIC has only N 22.191 + * irq slots per priority level, and a 'hanging, unacked' IRQ 22.192 + * holds up an irq slot - in excessive cases (when multiple 22.193 + * unexpected vectors occur) that might lock up the APIC 22.194 + * completely. 22.195 + */ 22.196 + ack_APIC_irq(); 22.197 +} 22.198 + 22.199 +extern void dump_ioapic_irq_info(void); 22.200 +void dump_ioapic_irq_info(void) 22.201 +{ 22.202 + printk("%s: can't dump yet\n", __func__); 22.203 +} 22.204 + 22.205 +/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */ 22.206 +u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 }; 22.207 +int assign_irq_vector(int irq) 22.208 +{ 22.209 + static int current_vector = FIRST_DEVICE_VECTOR, offset = 0; 22.210 + 22.211 + BUG_ON(irq >= NR_IRQ_VECTORS); 22.212 + if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) 22.213 + return IO_APIC_VECTOR(irq); 22.214 +next: 22.215 + current_vector += 8; 22.216 + 22.217 + /* Skip the hypercall vector. */ 22.218 + if (current_vector == HYPERCALL_VECTOR) 22.219 + goto next; 22.220 + 22.221 + /* Skip the Linux/BSD fast-trap vector. */ 22.222 + if (current_vector == FAST_TRAP) 22.223 + goto next; 22.224 + 22.225 + if (current_vector >= FIRST_SYSTEM_VECTOR) { 22.226 + offset++; 22.227 + if (!(offset%8)) 22.228 + return -ENOSPC; 22.229 + current_vector = FIRST_DEVICE_VECTOR + offset; 22.230 + } 22.231 + 22.232 + vector_irq[current_vector] = irq; 22.233 + if (irq != AUTO_ASSIGN) 22.234 + IO_APIC_VECTOR(irq) = current_vector; 22.235 + 22.236 + return current_vector; 22.237 +} 22.238 + 22.239 +int ioapic_guest_read(unsigned long physbase, unsigned int reg, u32 *pval) 22.240 +{ 22.241 + BUG_ON(pval != pval); 22.242 + 22.243 + return 0; 22.244 +} 22.245 + 22.246 +int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val) 22.247 +{ 22.248 + BUG_ON(val != val); 22.249 + return 0; 22.250 +}
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 23.2 +++ b/xen/arch/powerpc/float.S Fri Jul 14 10:47:50 2006 +0100 23.3 @@ -0,0 +1,243 @@ 23.4 +/* 23.5 + * Copyright (C) 2005 Jimi Xenidis <jimix@watson.ibm.com>, IBM Corporation 23.6 + * 23.7 + * This program is free software; you can redistribute it and/or modify 23.8 + * it under the terms of the GNU General Public License as published by 23.9 + * the Free Software Foundation; either version 2 of the License, or 23.10 + * (at your option) any later version. 23.11 + * 23.12 + * This program is distributed in the hope that it will be useful, 23.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 23.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23.15 + * GNU General Public License for more details. 23.16 + * 23.17 + * You should have received a copy of the GNU General Public License 23.18 + * along with this program; if not, write to the Free Software 23.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23.20 + */ 23.21 + 23.22 +#include <asm/config.h> 23.23 +#include <asm/asm-offsets.h> 23.24 +#include <asm/reg_defs.h> 23.25 +#include <asm/msr.h> 23.26 +#include <asm/processor.h> 23.27 + 23.28 +#ifdef HAS_FLOAT 23.29 +save_fp: 23.30 + addi r4, r3, VCPU_fprs - FPR_WIDTH 23.31 + stfdu fr0,FPR_WIDTH(r4) 23.32 + stfdu fr1,FPR_WIDTH(r4) 23.33 + stfdu fr2,FPR_WIDTH(r4) 23.34 + stfdu fr3,FPR_WIDTH(r4) 23.35 + stfdu fr4,FPR_WIDTH(r4) 23.36 + stfdu fr5,FPR_WIDTH(r4) 23.37 + stfdu fr6,FPR_WIDTH(r4) 23.38 + stfdu fr7,FPR_WIDTH(r4) 23.39 + stfdu fr8,FPR_WIDTH(r4) 23.40 + stfdu fr9,FPR_WIDTH(r4) 23.41 + stfdu fr10,FPR_WIDTH(r4) 23.42 + stfdu fr11,FPR_WIDTH(r4) 23.43 + stfdu fr12,FPR_WIDTH(r4) 23.44 + stfdu fr13,FPR_WIDTH(r4) 23.45 + stfdu fr14,FPR_WIDTH(r4) 23.46 + stfdu fr15,FPR_WIDTH(r4) 23.47 + stfdu fr16,FPR_WIDTH(r4) 23.48 + stfdu fr17,FPR_WIDTH(r4) 23.49 + stfdu fr18,FPR_WIDTH(r4) 23.50 + stfdu fr19,FPR_WIDTH(r4) 23.51 + stfdu fr20,FPR_WIDTH(r4) 23.52 + stfdu fr21,FPR_WIDTH(r4) 23.53 + stfdu fr22,FPR_WIDTH(r4) 23.54 + stfdu fr23,FPR_WIDTH(r4) 23.55 + stfdu fr24,FPR_WIDTH(r4) 23.56 + stfdu fr25,FPR_WIDTH(r4) 23.57 + stfdu fr26,FPR_WIDTH(r4) 23.58 + stfdu fr27,FPR_WIDTH(r4) 23.59 + stfdu fr28,FPR_WIDTH(r4) 23.60 + stfdu fr29,FPR_WIDTH(r4) 23.61 + stfdu fr30,FPR_WIDTH(r4) 23.62 + stfdu fr31,FPR_WIDTH(r4) 23.63 + mffs fr0 23.64 + stfd fr0,VCPU_fpscr(r3) 23.65 + blr 23.66 + 23.67 +load_fp: 23.68 + lfd fr0,VCPU_fpscr(r3) 23.69 + mtfsf 0xff,fr0 23.70 + 23.71 + addi r4, r3, VCPU_fprs - FPR_WIDTH 23.72 + lfdu fr0,FPR_WIDTH(r4) 23.73 + lfdu fr1,FPR_WIDTH(r4) 23.74 + lfdu fr2,FPR_WIDTH(r4) 23.75 + lfdu fr3,FPR_WIDTH(r4) 23.76 + lfdu fr4,FPR_WIDTH(r4) 23.77 + lfdu fr5,FPR_WIDTH(r4) 23.78 + lfdu fr6,FPR_WIDTH(r4) 23.79 + lfdu fr7,FPR_WIDTH(r4) 23.80 + lfdu fr8,FPR_WIDTH(r4) 23.81 + lfdu fr9,FPR_WIDTH(r4) 23.82 + lfdu fr10,FPR_WIDTH(r4) 23.83 + lfdu fr11,FPR_WIDTH(r4) 23.84 + lfdu fr12,FPR_WIDTH(r4) 23.85 + lfdu fr13,FPR_WIDTH(r4) 23.86 + lfdu fr14,FPR_WIDTH(r4) 23.87 + lfdu fr15,FPR_WIDTH(r4) 23.88 + lfdu fr16,FPR_WIDTH(r4) 23.89 + lfdu fr17,FPR_WIDTH(r4) 23.90 + lfdu fr18,FPR_WIDTH(r4) 23.91 + lfdu fr19,FPR_WIDTH(r4) 23.92 + lfdu fr20,FPR_WIDTH(r4) 23.93 + lfdu fr21,FPR_WIDTH(r4) 23.94 + lfdu fr22,FPR_WIDTH(r4) 23.95 + lfdu fr23,FPR_WIDTH(r4) 23.96 + lfdu fr24,FPR_WIDTH(r4) 23.97 + lfdu fr25,FPR_WIDTH(r4) 23.98 + lfdu fr26,FPR_WIDTH(r4) 23.99 + lfdu fr27,FPR_WIDTH(r4) 23.100 + lfdu fr28,FPR_WIDTH(r4) 23.101 + lfdu fr29,FPR_WIDTH(r4) 23.102 + lfdu fr30,FPR_WIDTH(r4) 23.103 + lfdu fr31,FPR_WIDTH(r4) 23.104 + blr 23.105 +#endif /* HAS_FLOAT */ 23.106 + 23.107 +#ifdef HAS_VMX 23.108 + 23.109 +#define VCPU_vr(n) (VCPU_vrs + ((n) * 16)) 23.110 + 23.111 +/* 23.112 + * We cannot rely on the domain to correctly use VRSAVE 23.113 + * so it is required that all VMX registers are saved and restored. 23.114 + */ 23.115 +save_vmx: 23.116 + mfspr r0,SPRN_VRSAVE 23.117 + stw r0,VCPU_vrsave(r3) 23.118 + 23.119 + addi r0,r3,VCPU_vr(0); stvxl vr0,0,r0 23.120 + addi r0,r3,VCPU_vr(1); stvxl vr1,0,r0 23.121 + addi r0,r3,VCPU_vr(2); stvxl vr2,0,r0 23.122 + addi r0,r3,VCPU_vr(3); stvxl vr3,0,r0 23.123 + addi r0,r3,VCPU_vr(4); stvxl vr4,0,r0 23.124 + addi r0,r3,VCPU_vr(5); stvxl vr5,0,r0 23.125 + addi r0,r3,VCPU_vr(6); stvxl vr6,0,r0 23.126 + addi r0,r3,VCPU_vr(7); stvxl vr7,0,r0 23.127 + addi r0,r3,VCPU_vr(8); stvxl vr8,0,r0 23.128 + 23.129 + /* 23.130 + * By now vr0 should be pushed out so now is a good time to 23.131 + * get the VRSCR which can take a long time and has no dependcies 23.132 + * on the following operations. 23.133 + */ 23.134 + mfvscr vr0 23.135 + addi r0,r3,VCPU_vscr ; stvxl vr0,0,r0 23.136 + 23.137 + addi r0,r3,VCPU_vr(9); stvxl vr9,0,r0 23.138 + addi r0,r3,VCPU_vr(10); stvxl vr10,0,r0 23.139 + addi r0,r3,VCPU_vr(11); stvxl vr11,0,r0 23.140 + addi r0,r3,VCPU_vr(12); stvxl vr12,0,r0 23.141 + addi r0,r3,VCPU_vr(13); stvxl vr13,0,r0 23.142 + addi r0,r3,VCPU_vr(14); stvxl vr14,0,r0 23.143 + addi r0,r3,VCPU_vr(15); stvxl vr15,0,r0 23.144 + addi r0,r3,VCPU_vr(16); stvxl vr16,0,r0 23.145 + addi r0,r3,VCPU_vr(17); stvxl vr17,0,r0 23.146 + addi r0,r3,VCPU_vr(18); stvxl vr18,0,r0 23.147 + addi r0,r3,VCPU_vr(19); stvxl vr19,0,r0 23.148 + addi r0,r3,VCPU_vr(20); stvxl vr20,0,r0 23.149 + addi r0,r3,VCPU_vr(21); stvxl vr21,0,r0 23.150 + addi r0,r3,VCPU_vr(22); stvxl vr22,0,r0 23.151 + addi r0,r3,VCPU_vr(23); stvxl vr23,0,r0 23.152 + addi r0,r3,VCPU_vr(24); stvxl vr24,0,r0 23.153 + addi r0,r3,VCPU_vr(25); stvxl vr25,0,r0 23.154 + addi r0,r3,VCPU_vr(26); stvxl vr26,0,r0 23.155 + addi r0,r3,VCPU_vr(27); stvxl vr27,0,r0 23.156 + addi r0,r3,VCPU_vr(28); stvxl vr28,0,r0 23.157 + addi r0,r3,VCPU_vr(29); stvxl vr29,0,r0 23.158 + addi r0,r3,VCPU_vr(30); stvxl vr30,0,r0 23.159 + addi r0,r3,VCPU_vr(31); stvxl vr31,0,r0 23.160 + blr 23.161 + 23.162 +load_vmx: 23.163 + lwz r0,VCPU_vrsave(r3) 23.164 + mtspr SPRN_VRSAVE,r0 23.165 + 23.166 + /* 23.167 + * This operation can take a long time so we use vr31 to 23.168 + * eliminate the depency on r0 for the next load 23.169 + */ 23.170 + addi r0,r3,VCPU_vscr ; lvxl vr31,0,r0 23.171 + mtvscr vr31 23.172 + 23.173 + addi r0,r3,VCPU_vr(0); lvxl vr0,0,r0 23.174 + addi r0,r3,VCPU_vr(1); lvxl vr1,0,r0 23.175 + addi r0,r3,VCPU_vr(2); lvxl vr2,0,r0 23.176 + addi r0,r3,VCPU_vr(3); lvxl vr3,0,r0 23.177 + addi r0,r3,VCPU_vr(4); lvxl vr4,0,r0 23.178 + addi r0,r3,VCPU_vr(5); lvxl vr5,0,r0 23.179 + addi r0,r3,VCPU_vr(6); lvxl vr6,0,r0 23.180 + addi r0,r3,VCPU_vr(7); lvxl vr7,0,r0 23.181 + addi r0,r3,VCPU_vr(8); lvxl vr8,0,r0 23.182 + addi r0,r3,VCPU_vr(9); lvxl vr9,0,r0 23.183 + addi r0,r3,VCPU_vr(10); lvxl vr10,0,r0 23.184 + addi r0,r3,VCPU_vr(11); lvxl vr11,0,r0 23.185 + addi r0,r3,VCPU_vr(12); lvxl vr12,0,r0 23.186 + addi r0,r3,VCPU_vr(13); lvxl vr13,0,r0 23.187 + addi r0,r3,VCPU_vr(14); lvxl vr14,0,r0 23.188 + addi r0,r3,VCPU_vr(15); lvxl vr15,0,r0 23.189 + addi r0,r3,VCPU_vr(16); lvxl vr16,0,r0 23.190 + addi r0,r3,VCPU_vr(17); lvxl vr17,0,r0 23.191 + addi r0,r3,VCPU_vr(18); lvxl vr18,0,r0 23.192 + addi r0,r3,VCPU_vr(19); lvxl vr19,0,r0 23.193 + addi r0,r3,VCPU_vr(20); lvxl vr20,0,r0 23.194 + addi r0,r3,VCPU_vr(21); lvxl vr21,0,r0 23.195 + addi r0,r3,VCPU_vr(22); lvxl vr22,0,r0 23.196 + addi r0,r3,VCPU_vr(23); lvxl vr23,0,r0 23.197 + addi r0,r3,VCPU_vr(24); lvxl vr24,0,r0 23.198 + addi r0,r3,VCPU_vr(25); lvxl vr25,0,r0 23.199 + addi r0,r3,VCPU_vr(26); lvxl vr26,0,r0 23.200 + addi r0,r3,VCPU_vr(27); lvxl vr27,0,r0 23.201 + addi r0,r3,VCPU_vr(28); lvxl vr28,0,r0 23.202 + addi r0,r3,VCPU_vr(29); lvxl vr29,0,r0 23.203 + addi r0,r3,VCPU_vr(30); lvxl vr30,0,r0 23.204 + addi r0,r3,VCPU_vr(31); lvxl vr31,0,r0 23.205 + blr 23.206 +#endif /* HAS_VMX */ 23.207 + 23.208 +/* void save_float(struct exec_domain *ed) */ 23.209 +_GLOBAL(save_float) 23.210 + mflr r8 23.211 +#ifdef HAS_FLOAT 23.212 + mfmsr r9 # save msr 23.213 + ori r0,r9,MSR_FP # turn on FPU 23.214 + mtmsr r0 23.215 + bl save_fp # uses r3, r4 23.216 + mtmsr r9 # restore msr 23.217 +#endif /* HAS_FLOAT */ 23.218 +#ifdef HAS_VMX 23.219 + mfmsr r9 # save msr 23.220 + oris r0,r9,MSR_VMX@h # turn on VMX 23.221 + mtmsr r0 23.222 + bl save_vmx # uses r3 23.223 + mtmsr r9 # restore msr 23.224 +#endif /* HAS_VMX */ 23.225 + mtlr r8 23.226 + blr 23.227 + 23.228 +/* void load_float(struct exec_domain *ed) */ 23.229 +_GLOBAL(load_float) 23.230 + mflr r8 23.231 +#ifdef HAS_FLOAT 23.232 + mfmsr r9 # save msr 23.233 + ori r0,r9,MSR_FP # turn on FPU 23.234 + mtmsr r0 23.235 + bl load_fp # uses r3, r4 23.236 + mtmsr r9 # restore msr 23.237 +#endif /* HAS_FLOAT */ 23.238 +#ifdef HAS_VMX 23.239 + mfmsr r9 # save msr 23.240 + oris r0,r9,MSR_VMX@h # turn on VMX 23.241 + mtmsr r0 23.242 + bl load_vmx # uses r3 23.243 + mtmsr r9 # restore msr 23.244 +#endif /* HAS_VMX */ 23.245 + mtlr r8 23.246 + blr
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 24.2 +++ b/xen/arch/powerpc/gdbstub.c Fri Jul 14 10:47:50 2006 +0100 24.3 @@ -0,0 +1,207 @@ 24.4 +/* 24.5 + * This program is free software; you can redistribute it and/or modify 24.6 + * it under the terms of the GNU General Public License as published by 24.7 + * the Free Software Foundation; either version 2 of the License, or 24.8 + * (at your option) any later version. 24.9 + * 24.10 + * This program is distributed in the hope that it will be useful, 24.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 24.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24.13 + * GNU General Public License for more details. 24.14 + * 24.15 + * You should have received a copy of the GNU General Public License 24.16 + * along with this program; if not, write to the Free Software 24.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 24.18 + * 24.19 + * Copyright (C) IBM Corp. 2005 24.20 + * 24.21 + * Authors: Hollis Blanchard <hollisb@us.ibm.com> 24.22 + */ 24.23 + 24.24 +#include <xen/types.h> 24.25 +#include <xen/lib.h> 24.26 +#include <xen/gdbstub.h> 24.27 +#include <public/xen.h> 24.28 +#include <asm/msr.h> 24.29 +#include <asm/bitops.h> 24.30 +#include <asm/cache.h> 24.31 +#include <asm/processor.h> 24.32 + 24.33 +asm(".globl trap_instruction\n" 24.34 + "trap_instruction:\n" 24.35 + "trap\n"); 24.36 +extern u32 trap_instruction[]; 24.37 + 24.38 +static unsigned int dec_entry; 24.39 +static unsigned int hdec_entry; 24.40 + 24.41 +static inline ulong 24.42 +gdb_ppc_0x700(struct cpu_user_regs *state) 24.43 +{ 24.44 + ulong instr; 24.45 + 24.46 + switch (state->msr & MSR_TRAP_BITS) { 24.47 + case MSR_TRAP_FE: 24.48 + return SIGFPE; 24.49 + case MSR_TRAP_IOP: 24.50 + case MSR_TRAP_PRIV: 24.51 + return SIGILL; 24.52 + case MSR_TRAP: 24.53 + instr = *((u32 *)state->pc); 24.54 + 24.55 + /* if this was a hardcoded trap in the source, step past it */ 24.56 + if (instr == *trap_instruction) { 24.57 + state->pc += sizeof (u32); 24.58 + } 24.59 + return SIGTRAP; 24.60 + } 24.61 + return SIGBUS; 24.62 +} 24.63 + 24.64 +u16 gdb_arch_signal_num(struct cpu_user_regs *regs, unsigned long cookie) 24.65 +{ 24.66 + /* exception type identifies, trap or bad address */ 24.67 + switch (cookie) { 24.68 + case 0x200: /* Machine Check */ 24.69 + return SIGTERM; 24.70 + case 0x300: /* DSI */ 24.71 + case 0x380: /* Data SLB */ 24.72 + case 0x400: /* ISI */ 24.73 + case 0x480: /* Instruction SLB */ 24.74 + return SIGSEGV; 24.75 + case 0x600: /* Alignment SLB */ 24.76 + return SIGBUS; 24.77 + case 0x700: /* Program */ 24.78 + return gdb_ppc_0x700(regs); 24.79 + case 0x800: /* Float */ 24.80 + return SIGFPE; 24.81 + case 0x900: /* Decrementer */ 24.82 + return SIGALRM; /* is this right? */ 24.83 + case 0xd00: /* TRAP */ 24.84 + return SIGTRAP; 24.85 + case 0xe00: /* FP */ 24.86 + return SIGFPE; 24.87 + } 24.88 + return SIGBUS; 24.89 +} 24.90 + 24.91 +void 24.92 +gdb_arch_resume(struct cpu_user_regs *regs, 24.93 + unsigned long addr, unsigned long type, 24.94 + struct gdb_context *ctx) 24.95 +{ 24.96 + if (addr != ~((ulong)0)) { 24.97 + regs->pc = addr; 24.98 + } 24.99 + 24.100 + if (type == GDB_CONTINUE) { 24.101 + regs->msr &= ~MSR_SE; 24.102 + } else { 24.103 + regs->msr |= MSR_SE; 24.104 + } 24.105 +} 24.106 + 24.107 +void 24.108 +gdb_arch_read_reg(unsigned long regnum, struct cpu_user_regs *regs, 24.109 + struct gdb_context *ctx) 24.110 +{ 24.111 + unimplemented(); 24.112 + gdb_send_reply("", ctx); 24.113 +} 24.114 + 24.115 +void 24.116 +gdb_arch_read_reg_array(struct cpu_user_regs *state, struct gdb_context *ctx) 24.117 +{ 24.118 + ulong i = 0; 24.119 + 24.120 + for (i = 0; i < 32; ++i) { 24.121 + gdb_write_to_packet_hex(state->gprs[i], sizeof(state->gprs[i]), ctx); 24.122 + } 24.123 + /* Avoid floating point for now */ 24.124 + for (i = 0; i < 32; ++i) { 24.125 + gdb_write_to_packet_hex(0, sizeof(u64), ctx); 24.126 + } 24.127 + gdb_write_to_packet_hex(state->pc, sizeof (state->pc), ctx); 24.128 + gdb_write_to_packet_hex(state->msr, sizeof (state->msr), ctx); 24.129 + gdb_write_to_packet_hex(state->cr, sizeof (state->cr), ctx); 24.130 + gdb_write_to_packet_hex(state->lr, sizeof (state->lr), ctx); 24.131 + gdb_write_to_packet_hex(state->ctr, sizeof (state->ctr), ctx); 24.132 + gdb_write_to_packet_hex(state->xer, sizeof (u32), ctx); 24.133 + gdb_write_to_packet_hex(0, sizeof(u32), ctx); /* fpscr */ 24.134 + gdb_send_packet(ctx); 24.135 +} 24.136 + 24.137 +void 24.138 +gdb_arch_write_reg_array(struct cpu_user_regs *regs, const char *buf, 24.139 + struct gdb_context *ctx) 24.140 +{ 24.141 + ulong i; 24.142 + 24.143 + for (i = 0; i < 32; ++i) { 24.144 + regs->gprs[i] = str2ulong(buf, sizeof (ulong)); 24.145 + buf += sizeof (regs->gprs[0]) * 2; 24.146 + } 24.147 + /* Avoid floating point for now */ 24.148 + for (i = 0; i < 32; ++i) { 24.149 + buf += sizeof (u64) * 2; 24.150 + } 24.151 + 24.152 + regs->pc = str2ulong(buf, sizeof (regs->pc)); 24.153 + buf += sizeof (regs->pc) * 2; 24.154 + regs->msr = str2ulong(buf, sizeof (regs->msr)); 24.155 + buf += sizeof (regs->msr) * 2; 24.156 + regs->cr = str2ulong(buf, sizeof (regs->cr)); 24.157 + buf += sizeof (regs->cr) * 2; 24.158 + regs->lr = str2ulong(buf, sizeof (regs->lr)); 24.159 + buf += sizeof (regs->lr) * 2; 24.160 + regs->ctr = str2ulong(buf, sizeof (regs->ctr)); 24.161 + buf += sizeof (regs->ctr) * 2; 24.162 + regs->xer = str2ulong(buf, sizeof (u32)); 24.163 + buf += sizeof (u32) * 2; 24.164 +} 24.165 + 24.166 +unsigned int 24.167 +gdb_arch_copy_from_user(void *dest, const void *src, unsigned len) 24.168 +{ 24.169 + memcpy(dest, src, len); 24.170 + return 0; 24.171 +} 24.172 + 24.173 +unsigned int 24.174 +gdb_arch_copy_to_user(void *dest, const void *src, unsigned len) 24.175 +{ 24.176 + memcpy(dest, src, len); 24.177 + synchronize_caches((ulong)dest, len); 24.178 + return 0; 24.179 +} 24.180 + 24.181 +void 24.182 +gdb_arch_print_state(struct cpu_user_regs *state) 24.183 +{ 24.184 + int i = 0; 24.185 + printk("PC: 0x%016lx MSR: 0x%016lx\n", state->pc, state->msr); 24.186 + printk("LR: 0x%016lx CTR: 0x%016lx\n", state->lr, state->ctr); 24.187 + /* XXX 24.188 + printk("DAR: 0x%016lx DSISR: 0x%016lx\n", state->dar, state->dsisr); 24.189 + */ 24.190 + printk("CR: 0x%08x XER: 0x%016lx\n", state->cr, state->xer); 24.191 + for (; i < 32; i+=4) { 24.192 + printk("%02d: 0x%016lx 0x%016lx 0x%016lx 0x%016lx\n", 24.193 + i, state->gprs[i], state->gprs[i+1], 24.194 + state->gprs[i+2], state->gprs[i+3]); 24.195 + } 24.196 +} 24.197 + 24.198 +void 24.199 +gdb_arch_enter(struct cpu_user_regs *state) 24.200 +{ 24.201 + dec_entry = mfdec(); 24.202 + hdec_entry = mfhdec(); 24.203 +} 24.204 + 24.205 +void 24.206 +gdb_arch_exit(struct cpu_user_regs *state) 24.207 +{ 24.208 + mtdec(dec_entry); 24.209 + mthdec(hdec_entry); 24.210 +}
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 25.2 +++ b/xen/arch/powerpc/hcalls.c Fri Jul 14 10:47:50 2006 +0100 25.3 @@ -0,0 +1,172 @@ 25.4 +/* 25.5 + * This program is free software; you can redistribute it and/or modify 25.6 + * it under the terms of the GNU General Public License as published by 25.7 + * the Free Software Foundation; either version 2 of the License, or 25.8 + * (at your option) any later version. 25.9 + * 25.10 + * This program is distributed in the hope that it will be useful, 25.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 25.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25.13 + * GNU General Public License for more details. 25.14 + * 25.15 + * You should have received a copy of the GNU General Public License 25.16 + * along with this program; if not, write to the Free Software 25.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 25.18 + * 25.19 + * Copyright (C) IBM Corp. 2005 25.20 + * 25.21 + * Authors: Hollis Blanchard <hollisb@us.ibm.com> 25.22 + */ 25.23 + 25.24 +#include <xen/config.h> 25.25 +#include <xen/types.h> 25.26 +#include <xen/sched.h> 25.27 +#include <xen/lib.h> 25.28 +#include <xen/init.h> 25.29 +#include <xen/multicall.h> 25.30 +#include <public/xen.h> 25.31 +#include <asm/current.h> 25.32 +#include <asm/papr.h> 25.33 +#include <asm/hcalls.h> 25.34 +#include <asm/debugger.h> 25.35 +#include <asm/msr.h> 25.36 +#include "exceptions.h" 25.37 + 25.38 +u32 *papr_hcalls; /* PAPR Hypervisor Calls */ 25.39 +u32 *hypercall_table; /* Xen Hypervisor Calls */ 25.40 + 25.41 +static void hcall_papr(ulong num, struct cpu_user_regs *regs) 25.42 +{ 25.43 + u32 address; 25.44 + 25.45 + if (regs->msr & MSR_PR) { 25.46 + regs->gprs[3] = H_Privilege; 25.47 + return; 25.48 + } 25.49 + 25.50 + if ((num & 0x3) || (num > RPA_HCALL_END)) { 25.51 + regs->gprs[3] = H_Parameter; 25.52 + return; 25.53 + } 25.54 + 25.55 + address = papr_hcalls[num/4]; 25.56 + papr_hcall_jump(regs, address); 25.57 +} 25.58 + 25.59 +static void hcall_xen(ulong num, struct cpu_user_regs *regs) 25.60 +{ 25.61 + u32 address; 25.62 + 25.63 + if (regs->msr & MSR_PR) { 25.64 + regs->gprs[3] = -EPERM; 25.65 + return; 25.66 + } 25.67 + 25.68 + if ((num >= NR_hypercalls)) { 25.69 + regs->gprs[3] = -ENOSYS; 25.70 + return; 25.71 + } 25.72 + address = hypercall_table[num]; 25.73 + if (address == 0) { 25.74 + printk("unsupported Xen hypercall: 0x%lx\n", num); 25.75 + regs->gprs[3] = -ENOSYS; 25.76 + return; 25.77 + } 25.78 + 25.79 + regs->gprs[3] = xen_hvcall_jump(regs, address); 25.80 +} 25.81 + 25.82 +void do_multicall_call(multicall_entry_t *call) 25.83 +{ 25.84 + struct cpu_user_regs regs; 25.85 + 25.86 + regs.gprs[3] = call->args[0]; 25.87 + regs.gprs[4] = call->args[1]; 25.88 + regs.gprs[5] = call->args[2]; 25.89 + regs.gprs[6] = call->args[3]; 25.90 + regs.gprs[7] = call->args[4]; 25.91 + regs.gprs[8] = call->args[5]; 25.92 + 25.93 + hcall_xen(call->op, ®s); 25.94 + 25.95 + call->result = regs.gprs[3]; 25.96 +} 25.97 + 25.98 +void do_hcall(struct cpu_user_regs *regs) 25.99 +{ 25.100 + ulong num = regs->gprs[3]; 25.101 + 25.102 + local_irq_enable(); 25.103 + 25.104 + if ((num & XEN_MARK(0)) == XEN_MARK(0)) { 25.105 + /* it's a Xen call */ 25.106 + num &= ~XEN_MARK(0); 25.107 + hcall_xen(num, regs); 25.108 + } else { 25.109 + /* it's a PAPR call */ 25.110 + hcall_papr(num, regs); 25.111 + } 25.112 +} 25.113 + 25.114 +static void do_ni_papr_hypercall(struct cpu_user_regs *regs) 25.115 +{ 25.116 + struct vcpu *v = get_current(); 25.117 + 25.118 + printk("unsupported hcall 0x%lx was called by dom0x%x\n", 25.119 + regs->gprs[3], v->domain->domain_id); 25.120 + debugger_trap_immediate(); 25.121 + 25.122 + regs->gprs[3] = H_Parameter; 25.123 +} 25.124 + 25.125 +/* store low 32 bits of 64-bit address in hcall table (this is safe because we 25.126 + * know we will not link above 4GB). We don't need to preserve the TOC 25.127 + * because that only changes when calling dynamically linked objects. */ 25.128 +static void register_papr_hcall(ulong num, hcall_handler_t handler) 25.129 +{ 25.130 + int index = num/4; 25.131 + 25.132 + papr_hcalls[index] = (u32)(*(u64 *)handler); 25.133 +} 25.134 + 25.135 +static void init_papr_hcalls(void) 25.136 +{ 25.137 + inithcall_t *hcall; 25.138 + int i; 25.139 + 25.140 + /* initialize PAPR hcall table */ 25.141 + papr_hcalls = xmalloc_array(u32, RPA_HCALL_END/4); 25.142 + ASSERT(papr_hcalls != NULL); 25.143 + for (i = 0; i <= RPA_HCALL_END; i += 4) 25.144 + register_papr_hcall(i, do_ni_papr_hypercall); 25.145 + 25.146 + /* register the PAPR hcalls */ 25.147 + for (hcall = &__inithcall_start; hcall < &__inithcall_end; hcall++) { 25.148 + register_papr_hcall(hcall->number, hcall->handler); 25.149 + } 25.150 +} 25.151 + 25.152 +static void init_hypercall_table(void) 25.153 +{ 25.154 + int i; 25.155 + 25.156 + hypercall_table = xmalloc_array(u32, NR_hypercalls); 25.157 + ASSERT(hypercall_table != NULL); 25.158 + 25.159 + for (i = 0; i < NR_hypercalls; i++) { 25.160 + if (__hypercall_table[i] == NULL ) { 25.161 + hypercall_table[i] = 0; 25.162 + } else { 25.163 + hypercall_table[i] = (u32)(*__hypercall_table[i]); 25.164 + } 25.165 + } 25.166 +} 25.167 + 25.168 +static int init_hcalls(void) 25.169 +{ 25.170 + init_papr_hcalls(); 25.171 + init_hypercall_table(); 25.172 + 25.173 + return 0; 25.174 +} 25.175 +__initcall(init_hcalls);
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/xen/arch/powerpc/htab.c Fri Jul 14 10:47:50 2006 +0100 26.3 @@ -0,0 +1,69 @@ 26.4 +/* 26.5 + * This program is free software; you can redistribute it and/or modify 26.6 + * it under the terms of the GNU General Public License as published by 26.7 + * the Free Software Foundation; either version 2 of the License, or 26.8 + * (at your option) any later version. 26.9 + * 26.10 + * This program is distributed in the hope that it will be useful, 26.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 26.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26.13 + * GNU General Public License for more details. 26.14 + * 26.15 + * You should have received a copy of the GNU General Public License 26.16 + * along with this program; if not, write to the Free Software 26.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26.18 + * 26.19 + * Copyright (C) IBM Corp. 2005 26.20 + * 26.21 + * Authors: Hollis Blanchard <hollisb@us.ibm.com> 26.22 + */ 26.23 + 26.24 +#include <xen/config.h> 26.25 +#include <xen/sched.h> 26.26 + 26.27 +static ulong htab_calc_sdr1(ulong htab_addr, ulong log_htab_size) 26.28 +{ 26.29 + ulong sdr1_htabsize; 26.30 + 26.31 + ASSERT((htab_addr & ((1UL << log_htab_size) - 1)) == 0); 26.32 + ASSERT(log_htab_size <= SDR1_HTABSIZE_MAX); 26.33 + ASSERT(log_htab_size >= HTAB_MIN_LOG_SIZE); 26.34 + 26.35 + sdr1_htabsize = log_htab_size - LOG_PTEG_SIZE - SDR1_HTABSIZE_BASEBITS; 26.36 + 26.37 + return (htab_addr | (sdr1_htabsize & SDR1_HTABSIZE_MASK)); 26.38 +} 26.39 + 26.40 +void htab_alloc(struct domain *d, int log_htab_bytes) 26.41 +{ 26.42 + ulong htab_raddr; 26.43 + ulong htab_bytes = 1UL << log_htab_bytes; 26.44 + 26.45 + /* XXX use alloc_domheap_pages instead? */ 26.46 + htab_raddr = (ulong)alloc_xenheap_pages(log_htab_bytes - PAGE_SHIFT); 26.47 + ASSERT(htab_raddr != 0); 26.48 + /* XXX check alignment guarantees */ 26.49 + ASSERT((htab_raddr & (htab_bytes-1)) == 0); 26.50 + 26.51 + /* XXX slow. move memset out to service partition? */ 26.52 + memset((void *)htab_raddr, 0, htab_bytes); 26.53 + 26.54 + d->arch.htab.log_num_ptes = log_htab_bytes - LOG_PTE_SIZE; 26.55 + d->arch.htab.sdr1 = htab_calc_sdr1(htab_raddr, log_htab_bytes); 26.56 + d->arch.htab.map = (union pte *)htab_raddr; 26.57 + d->arch.htab.shadow = xmalloc_array(ulong, 26.58 + 1UL << d->arch.htab.log_num_ptes); 26.59 + ASSERT(d->arch.htab.shadow != NULL); 26.60 + 26.61 + printf("%s: dom%x sdr1: %lx\n", __func__, d->domain_id, d->arch.htab.sdr1); 26.62 +} 26.63 + 26.64 +void htab_free(struct domain *d) 26.65 +{ 26.66 + ulong htab_raddr = GET_HTAB(d); 26.67 + 26.68 + free_xenheap_pages((void *)htab_raddr, 26.69 + (1UL << d->arch.htab.log_num_ptes) << LOG_PTE_SIZE); 26.70 + xfree(d->arch.htab.shadow); 26.71 +} 26.72 +
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/xen/arch/powerpc/iommu.c Fri Jul 14 10:47:50 2006 +0100 27.3 @@ -0,0 +1,79 @@ 27.4 +/* 27.5 + * This program is free software; you can redistribute it and/or modify 27.6 + * it under the terms of the GNU General Public License as published by 27.7 + * the Free Software Foundation; either version 2 of the License, or 27.8 + * (at your option) any later version. 27.9 + * 27.10 + * This program is distributed in the hope that it will be useful, 27.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 27.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27.13 + * GNU General Public License for more details. 27.14 + * 27.15 + * You should have received a copy of the GNU General Public License 27.16 + * along with this program; if not, write to the Free Software 27.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 27.18 + * 27.19 + * Copyright (C) IBM Corp. 2005 27.20 + * 27.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 27.22 + */ 27.23 + 27.24 +#undef DEBUG 27.25 + 27.26 +#include <xen/config.h> 27.27 +#include <xen/types.h> 27.28 +#include <xen/sched.h> 27.29 +#include <xen/init.h> 27.30 +#include <xen/mm.h> 27.31 +#include <asm/current.h> 27.32 +#include <asm/papr.h> 27.33 +#include <asm/hcalls.h> 27.34 +#include <public/xen.h> 27.35 +#include "tce.h" 27.36 +#include "iommu.h" 27.37 + 27.38 +struct iommu_funcs { 27.39 + int (*iommu_put)(ulong, union tce); 27.40 +}; 27.41 + 27.42 +/* individual host bridges */ 27.43 +static struct iommu_funcs iommu_phbs[16]; 27.44 +static u32 iommu_phbs_num = ARRAY_SIZE(iommu_phbs); 27.45 + 27.46 +int iommu_put(u32 buid, ulong ioba, union tce tce) 27.47 +{ 27.48 + struct vcpu *v = get_current(); 27.49 + struct domain *d = v->domain; 27.50 + 27.51 + if (buid < iommu_phbs_num && iommu_phbs[buid].iommu_put != NULL) { 27.52 + ulong pfn; 27.53 + ulong mfn; 27.54 + int mtype; 27.55 + 27.56 + pfn = tce.tce_bits.tce_rpn; 27.57 + mfn = pfn2mfn(d, pfn, &mtype); 27.58 + if (mtype != 0) { 27.59 + panic("we don't do non-RMO memory yet\n"); 27.60 + } 27.61 + 27.62 +#ifdef DEBUG 27.63 + printk("%s: ioba=0x%lx pfn=0x%lx mfn=0x%lx\n", __func__, 27.64 + ioba, pfn, mfn); 27.65 +#endif 27.66 + tce.tce_bits.tce_rpn = mfn; 27.67 + 27.68 + return iommu_phbs[buid].iommu_put(ioba, tce); 27.69 + } 27.70 + return -1; 27.71 +} 27.72 + 27.73 +int iommu_register(u32 buid, int (*put)(ulong ioba, union tce ltce)) 27.74 +{ 27.75 + 27.76 + if (buid < iommu_phbs_num && iommu_phbs[buid].iommu_put == NULL) { 27.77 + iommu_phbs[0].iommu_put = put; 27.78 + return 0; 27.79 + } 27.80 + panic("bad IOMMU registration\n"); 27.81 + return -1; 27.82 +}
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 28.2 +++ b/xen/arch/powerpc/iommu.h Fri Jul 14 10:47:50 2006 +0100 28.3 @@ -0,0 +1,28 @@ 28.4 +/* 28.5 + * This program is free software; you can redistribute it and/or modify 28.6 + * it under the terms of the GNU General Public License as published by 28.7 + * the Free Software Foundation; either version 2 of the License, or 28.8 + * (at your option) any later version. 28.9 + * 28.10 + * This program is distributed in the hope that it will be useful, 28.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 28.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28.13 + * GNU General Public License for more details. 28.14 + * 28.15 + * You should have received a copy of the GNU General Public License 28.16 + * along with this program; if not, write to the Free Software 28.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 28.18 + * 28.19 + * Copyright (C) IBM Corp. 2005 28.20 + * 28.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 28.22 + */ 28.23 + 28.24 +#ifndef _IOMMU_H 28.25 +#define _IOMMU_H 28.26 + 28.27 +extern int iommu_put(u32 buid, ulong ioba, union tce tce); 28.28 +extern int iommu_register(u32 buid, int (*put)(ulong, union tce)); 28.29 + 28.30 +#endif /* _IOMMU_H */ 28.31 +
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 29.2 +++ b/xen/arch/powerpc/irq.c Fri Jul 14 10:47:50 2006 +0100 29.3 @@ -0,0 +1,22 @@ 29.4 +/* 29.5 + * This program is free software; you can redistribute it and/or modify 29.6 + * it under the terms of the GNU General Public License as published by 29.7 + * the Free Software Foundation; either version 2 of the License, or 29.8 + * (at your option) any later version. 29.9 + * 29.10 + * This program is distributed in the hope that it will be useful, 29.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 29.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 29.13 + * GNU General Public License for more details. 29.14 + * 29.15 + * You should have received a copy of the GNU General Public License 29.16 + * along with this program; if not, write to the Free Software 29.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 29.18 + * 29.19 + * Copyright (C) IBM Corp. 2005 29.20 + * 29.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 29.22 + */ 29.23 + 29.24 +#include "exceptions.h" 29.25 +#include "../x86/irq.c"
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 30.2 +++ b/xen/arch/powerpc/mambo.S Fri Jul 14 10:47:50 2006 +0100 30.3 @@ -0,0 +1,64 @@ 30.4 +/* 30.5 + * Copyright (C) 2005 Jimi Xenidis <jimix@watson.ibm.com>, IBM Corporation 30.6 + * 30.7 + * This program is free software; you can redistribute it and/or modify 30.8 + * it under the terms of the GNU General Public License as published by 30.9 + * the Free Software Foundation; either version 2 of the License, or 30.10 + * (at your option) any later version. 30.11 + * 30.12 + * This program is distributed in the hope that it will be useful, 30.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 30.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30.15 + * GNU General Public License for more details. 30.16 + * 30.17 + * You should have received a copy of the GNU General Public License 30.18 + * along with this program; if not, write to the Free Software 30.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 30.20 + * 30.21 + */ 30.22 + 30.23 +#include <asm/config.h> 30.24 +#include <asm/processor.h> 30.25 + 30.26 +_GLOBAL(mambo_callthru) 30.27 + .long 0x000eaeb0 30.28 + blr 30.29 + 30.30 +_GLOBAL(mambo_write) 30.31 + mr r5, r4 30.32 + mr r4, r3 30.33 + li r3, 0 # Write console code 30.34 + 30.35 + li r6, 0 30.36 + /* need to fix return value */ 30.37 + mflr r7 30.38 + bl _ENTRY(mambo_callthru) 30.39 + mtlr r7 30.40 + mr r3, r5 30.41 + blr 30.42 + 30.43 +_GLOBAL(mambo_memset) 30.44 + mr r6, r5 30.45 + mr r5, r4 30.46 + mr r4, r3 30.47 + li r3, 0x47 # memset 30.48 + /* need to fix return value */ 30.49 + mflr r7 30.50 + bl _ENTRY(mambo_callthru) 30.51 + mtlr r7 30.52 + mr r3, r4 30.53 + blr 30.54 + 30.55 +_GLOBAL(mambo_memcpy) 30.56 + mr r6, r5 30.57 + mr r5, r4 30.58 + mr r4, r3 30.59 + li r3, 0x45 # memcpy 30.60 + /* need to fix return value */ 30.61 + mflr r7 30.62 + bl _ENTRY(mambo_callthru) 30.63 + mtlr r7 30.64 + mr r3, r4 30.65 + blr 30.66 + 30.67 +
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 31.2 +++ b/xen/arch/powerpc/mm.c Fri Jul 14 10:47:50 2006 +0100 31.3 @@ -0,0 +1,141 @@ 31.4 +/* 31.5 + * This program is free software; you can redistribute it and/or modify 31.6 + * it under the terms of the GNU General Public License as published by 31.7 + * the Free Software Foundation; either version 2 of the License, or 31.8 + * (at your option) any later version. 31.9 + * 31.10 + * This program is distributed in the hope that it will be useful, 31.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 31.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 31.13 + * GNU General Public License for more details. 31.14 + * 31.15 + * You should have received a copy of the GNU General Public License 31.16 + * along with this program; if not, write to the Free Software 31.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 31.18 + * 31.19 + * Copyright (C) IBM Corp. 2005 31.20 + * 31.21 + * Authors: Hollis Blanchard <hollisb@us.ibm.com> 31.22 + */ 31.23 + 31.24 +#include <xen/config.h> 31.25 +#include <xen/mm.h> 31.26 +#include <xen/kernel.h> 31.27 +#include <xen/sched.h> 31.28 +#include <asm/misc.h> 31.29 +#include <asm/init.h> 31.30 +#include <asm/page.h> 31.31 + 31.32 +/* Frame table and its size in pages. */ 31.33 +struct page_info *frame_table; 31.34 +unsigned long frame_table_size; 31.35 +unsigned long max_page; 31.36 +unsigned long total_pages; 31.37 + 31.38 +int create_grant_host_mapping( 31.39 + unsigned long addr, unsigned long frame, unsigned int flags) 31.40 +{ 31.41 + panic("%s called\n", __func__); 31.42 + return 1; 31.43 +} 31.44 + 31.45 +int destroy_grant_host_mapping( 31.46 + unsigned long addr, unsigned long frame, unsigned int flags) 31.47 +{ 31.48 + panic("%s called\n", __func__); 31.49 + return 1; 31.50 +} 31.51 + 31.52 +int steal_page(struct domain *d, struct page_info *page, unsigned int memflags) 31.53 +{ 31.54 + panic("%s called\n", __func__); 31.55 + return 1; 31.56 +} 31.57 + 31.58 + 31.59 +int get_page_type(struct page_info *page, u32 type) 31.60 +{ 31.61 + panic("%s called\n", __func__); 31.62 + return 1; 31.63 +} 31.64 + 31.65 +void put_page_type(struct page_info *page) 31.66 +{ 31.67 + panic("%s called\n", __func__); 31.68 +} 31.69 + 31.70 +void __init init_frametable(void) 31.71 +{ 31.72 + unsigned long p; 31.73 + 31.74 + frame_table_size = PFN_UP(max_page * sizeof(struct page_info)); 31.75 + 31.76 + p = alloc_boot_pages(min(frame_table_size, 4UL << 20), 1); 31.77 + if (p == 0) 31.78 + panic("Not enough memory for frame table\n"); 31.79 + 31.80 + frame_table = (struct page_info *)(p << PAGE_SHIFT); 31.81 + frame_table_size = (frame_table_size + PAGE_SIZE - 1) & PAGE_MASK; 31.82 + 31.83 + memset(frame_table, 0, frame_table_size); 31.84 +} 31.85 + 31.86 +long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg) 31.87 +{ 31.88 + printk("%s: no PPC specific memory ops\n", __func__); 31.89 + return -ENOSYS; 31.90 +} 31.91 + 31.92 +void clear_page(void *page) 31.93 +{ 31.94 + if (on_mambo()) { 31.95 + extern void *mambo_memset(void *,int ,__kernel_size_t); 31.96 + mambo_memset(page, 0, PAGE_SIZE); 31.97 + } else { 31.98 + memset(page, 0, PAGE_SIZE); 31.99 + } 31.100 +} 31.101 + 31.102 +extern void copy_page(void *dp, void *sp) 31.103 +{ 31.104 + if (on_mambo()) { 31.105 + extern void *mambo_memcpy(void *,const void *,__kernel_size_t); 31.106 + mambo_memcpy(dp, sp, PAGE_SIZE); 31.107 + } else { 31.108 + memcpy(dp, sp, PAGE_SIZE); 31.109 + } 31.110 +} 31.111 + 31.112 +ulong pfn2mfn(struct domain *d, long pfn, int *type) 31.113 +{ 31.114 + ulong rma_base_mfn = d->arch.rma_base >> PAGE_SHIFT; 31.115 + ulong rma_size_mfn = d->arch.rma_size >> PAGE_SHIFT; 31.116 + ulong mfn; 31.117 + int t; 31.118 + 31.119 + if (pfn < rma_size_mfn) { 31.120 + mfn = pfn + rma_base_mfn; 31.121 + t = PFN_TYPE_RMA; 31.122 + } else if (pfn >= d->arch.logical_base_pfn && 31.123 + pfn < d->arch.logical_end_pfn) { 31.124 + if (test_bit(_DOMF_privileged, &d->domain_flags)) { 31.125 + /* This hack allows dom0 to map all memory, necessary to 31.126 + * initialize domU state. */ 31.127 + mfn = pfn; 31.128 + } else { 31.129 + panic("we do not handle the logical area yet\n"); 31.130 + mfn = 0; 31.131 + } 31.132 + 31.133 + t = PFN_TYPE_LOGICAL; 31.134 + } else { 31.135 + /* don't know */ 31.136 + mfn = pfn; 31.137 + t = PFN_TYPE_IO; 31.138 + } 31.139 + 31.140 + if (type != NULL) 31.141 + *type = t; 31.142 + 31.143 + return mfn; 31.144 +}
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 32.2 +++ b/xen/arch/powerpc/mpic.c Fri Jul 14 10:47:50 2006 +0100 32.3 @@ -0,0 +1,1109 @@ 32.4 +/* 32.5 + * arch/powerpc/kernel/mpic.c 32.6 + * 32.7 + * Driver for interrupt controllers following the OpenPIC standard, the 32.8 + * common implementation beeing IBM's MPIC. This driver also can deal 32.9 + * with various broken implementations of this HW. 32.10 + * 32.11 + * Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp. 32.12 + * 32.13 + * This file is subject to the terms and conditions of the GNU General Public 32.14 + * License. See the file COPYING in the main directory of this archive 32.15 + * for more details. 32.16 + */ 32.17 + 32.18 +/* XXX Xen hacks ... */ 32.19 +/* make this generic */ 32.20 + 32.21 +#define le32_to_cpu(x) \ 32.22 +({ \ 32.23 + __u32 __x = (x); \ 32.24 + ((__u32)( \ 32.25 + (((__u32)(__x) & (__u32)0x000000ffUL) << 24) | \ 32.26 + (((__u32)(__x) & (__u32)0x0000ff00UL) << 8) | \ 32.27 + (((__u32)(__x) & (__u32)0x00ff0000UL) >> 8) | \ 32.28 + (((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); \ 32.29 +}) 32.30 + 32.31 + 32.32 +#define alloc_bootmem(x) xmalloc_bytes(x) 32.33 +#define request_irq(irq, handler, f, devname, dev_id) \ 32.34 + panic("IPI requested: %d: %p: %s: %p\n", irq, handler, devname, dev_id) 32.35 + 32.36 +typedef int irqreturn_t; 32.37 + 32.38 +#define IRQ_NONE (0) 32.39 +#define IRQ_HANDLED (1) 32.40 +#define IRQ_RETVAL(x) ((x) != 0) 32.41 + 32.42 +#define IRQ_SENSE_MASK 0x1 32.43 +#define IRQ_SENSE_LEVEL 0x1 /* interrupt on active level */ 32.44 +#define IRQ_SENSE_EDGE 0x0 /* interrupt triggered by edge */ 32.45 + 32.46 +#define IRQ_POLARITY_MASK 0x2 32.47 +#define IRQ_POLARITY_POSITIVE 0x2 /* high level or low->high edge */ 32.48 +#define IRQ_POLARITY_NEGATIVE 0x0 /* low level or high->low edge */ 32.49 + 32.50 +#define CONFIG_IRQ_ALL_CPUS 0 32.51 +#define distribute_irqs CONFIG_IRQ_ALL_CPUS 32.52 +#define CONFIG_MPIC_BROKEN_U3 32.53 + 32.54 +#define PCI_DEVFN(slot,func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) 32.55 +#define PCI_FUNC(devfn) ((devfn) & 0x07) 32.56 +#define PCI_HEADER_TYPE 0x0e /* 8 bits */ 32.57 +#define PCI_VENDOR_ID 0x00 /* 16 bits */ 32.58 +#define PCI_VENDOR_ID_AMD 0x1022 32.59 +#define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */ 32.60 +#define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */ 32.61 +#define PCI_CAP_LIST_ID 0 /* Capability ID */ 32.62 +#define PCI_CAP_ID_HT_IRQCONF 0x08 /* HyperTransport IRQ Configuration */ 32.63 +#define PCI_STATUS 0x06 /* 16 bits */ 32.64 +#define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */ 32.65 +#define MSG_ALL 0x8001 32.66 +#define MSG_ALL_BUT_SELF 0x8000 32.67 + 32.68 +/* keeps file even closer to the original */ 32.69 +#define pt_regs cpu_user_regs 32.70 +/* XXX ... Xen hacks */ 32.71 + 32.72 +#undef DEBUG 32.73 +#undef DEBUG_IPI 32.74 +#undef DEBUG_IRQ 32.75 +#undef DEBUG_LOW 32.76 + 32.77 +#include <xen/config.h> 32.78 +#include <xen/types.h> 32.79 +#include <xen/kernel.h> 32.80 +#include <xen/init.h> 32.81 +#include <xen/irq.h> 32.82 +#include <xen/smp.h> 32.83 +#ifndef __XEN__ 32.84 +#include <linux/interrupt.h> 32.85 +#include <linux/bootmem.h> 32.86 +#endif 32.87 +#include <xen/spinlock.h> 32.88 +#ifndef __XEN__ 32.89 +#include <asm/pci.h> 32.90 + 32.91 +#include <asm/ptrace.h> 32.92 +#include <asm/signal.h> 32.93 +#endif 32.94 +#include <asm/io.h> 32.95 +#ifndef __XEN__ 32.96 +#include <asm/pgtable.h> 32.97 +#include <asm/irq.h> 32.98 +#include <asm/machdep.h> 32.99 +#endif 32.100 +#include <asm/mpic.h> 32.101 +#include <asm/smp.h> 32.102 + 32.103 +static inline void smp_message_recv(int msg, struct pt_regs *regs) 32.104 +{ 32.105 + return; 32.106 +} 32.107 + 32.108 +#ifdef DEBUG 32.109 +#define DBG(fmt...) printk(fmt) 32.110 +#else 32.111 +#define DBG(fmt...) 32.112 +#endif 32.113 + 32.114 +static struct mpic *mpics; 32.115 +static struct mpic *mpic_primary; 32.116 +static DEFINE_SPINLOCK(mpic_lock); 32.117 + 32.118 +#ifdef CONFIG_PPC32 /* XXX for now */ 32.119 +#ifdef CONFIG_IRQ_ALL_CPUS 32.120 +#define distribute_irqs (1) 32.121 +#else 32.122 +#define distribute_irqs (0) 32.123 +#endif 32.124 +#endif 32.125 + 32.126 +/* 32.127 + * Register accessor functions 32.128 + */ 32.129 + 32.130 + 32.131 +static inline u32 _mpic_read(unsigned int be, volatile u32 __iomem *base, 32.132 + unsigned int reg) 32.133 +{ 32.134 + if (be) 32.135 + return in_be32(base + (reg >> 2)); 32.136 + else 32.137 + return in_le32(base + (reg >> 2)); 32.138 +} 32.139 + 32.140 +static inline void _mpic_write(unsigned int be, volatile u32 __iomem *base, 32.141 + unsigned int reg, u32 value) 32.142 +{ 32.143 + if (be) 32.144 + out_be32(base + (reg >> 2), value); 32.145 + else 32.146 + out_le32(base + (reg >> 2), value); 32.147 +} 32.148 + 32.149 +static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi) 32.150 +{ 32.151 + unsigned int be = (mpic->flags & MPIC_BIG_ENDIAN) != 0; 32.152 + unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10); 32.153 + 32.154 + if (mpic->flags & MPIC_BROKEN_IPI) 32.155 + be = !be; 32.156 + return _mpic_read(be, mpic->gregs, offset); 32.157 +} 32.158 + 32.159 +static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value) 32.160 +{ 32.161 + unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10); 32.162 + 32.163 + _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->gregs, offset, value); 32.164 +} 32.165 + 32.166 +static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg) 32.167 +{ 32.168 + unsigned int cpu = 0; 32.169 + 32.170 + if (mpic->flags & MPIC_PRIMARY) 32.171 + cpu = hard_smp_processor_id(); 32.172 + 32.173 + return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg); 32.174 +} 32.175 + 32.176 +static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value) 32.177 +{ 32.178 + unsigned int cpu = 0; 32.179 + 32.180 + if (mpic->flags & MPIC_PRIMARY) 32.181 + cpu = hard_smp_processor_id(); 32.182 + 32.183 + _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg, value); 32.184 +} 32.185 + 32.186 +static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigned int reg) 32.187 +{ 32.188 + unsigned int isu = src_no >> mpic->isu_shift; 32.189 + unsigned int idx = src_no & mpic->isu_mask; 32.190 + 32.191 + return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu], 32.192 + reg + (idx * MPIC_IRQ_STRIDE)); 32.193 +} 32.194 + 32.195 +static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no, 32.196 + unsigned int reg, u32 value) 32.197 +{ 32.198 + unsigned int isu = src_no >> mpic->isu_shift; 32.199 + unsigned int idx = src_no & mpic->isu_mask; 32.200 + 32.201 + _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu], 32.202 + reg + (idx * MPIC_IRQ_STRIDE), value); 32.203 +} 32.204 + 32.205 +#define mpic_read(b,r) _mpic_read(mpic->flags & MPIC_BIG_ENDIAN,(b),(r)) 32.206 +#define mpic_write(b,r,v) _mpic_write(mpic->flags & MPIC_BIG_ENDIAN,(b),(r),(v)) 32.207 +#define mpic_ipi_read(i) _mpic_ipi_read(mpic,(i)) 32.208 +#define mpic_ipi_write(i,v) _mpic_ipi_write(mpic,(i),(v)) 32.209 +#define mpic_cpu_read(i) _mpic_cpu_read(mpic,(i)) 32.210 +#define mpic_cpu_write(i,v) _mpic_cpu_write(mpic,(i),(v)) 32.211 +#define mpic_irq_read(s,r) _mpic_irq_read(mpic,(s),(r)) 32.212 +#define mpic_irq_write(s,r,v) _mpic_irq_write(mpic,(s),(r),(v)) 32.213 + 32.214 + 32.215 +/* 32.216 + * Low level utility functions 32.217 + */ 32.218 + 32.219 + 32.220 + 32.221 +/* Check if we have one of those nice broken MPICs with a flipped endian on 32.222 + * reads from IPI registers 32.223 + */ 32.224 +static void __init mpic_test_broken_ipi(struct mpic *mpic) 32.225 +{ 32.226 + u32 r; 32.227 + 32.228 + mpic_write(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0, MPIC_VECPRI_MASK); 32.229 + r = mpic_read(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0); 32.230 + 32.231 + if (r == le32_to_cpu(MPIC_VECPRI_MASK)) { 32.232 + printk(KERN_INFO "mpic: Detected reversed IPI registers\n"); 32.233 + mpic->flags |= MPIC_BROKEN_IPI; 32.234 + } 32.235 +} 32.236 + 32.237 +#ifdef CONFIG_MPIC_BROKEN_U3 32.238 + 32.239 +/* Test if an interrupt is sourced from HyperTransport (used on broken U3s) 32.240 + * to force the edge setting on the MPIC and do the ack workaround. 32.241 + */ 32.242 +static inline int mpic_is_ht_interrupt(struct mpic *mpic, unsigned int source) 32.243 +{ 32.244 + if (source >= 128 || !mpic->fixups) 32.245 + return 0; 32.246 + return mpic->fixups[source].base != NULL; 32.247 +} 32.248 + 32.249 + 32.250 +static inline void mpic_ht_end_irq(struct mpic *mpic, unsigned int source) 32.251 +{ 32.252 + struct mpic_irq_fixup *fixup = &mpic->fixups[source]; 32.253 + 32.254 + if (fixup->applebase) { 32.255 + unsigned int soff = (fixup->index >> 3) & ~3; 32.256 + unsigned int mask = 1U << (fixup->index & 0x1f); 32.257 + writel(mask, fixup->applebase + soff); 32.258 + } else { 32.259 + spin_lock(&mpic->fixup_lock); 32.260 + writeb(0x11 + 2 * fixup->index, fixup->base + 2); 32.261 + writel(fixup->data, fixup->base + 4); 32.262 + spin_unlock(&mpic->fixup_lock); 32.263 + } 32.264 +} 32.265 + 32.266 +static void mpic_startup_ht_interrupt(struct mpic *mpic, unsigned int source, 32.267 + unsigned int irqflags) 32.268 +{ 32.269 + struct mpic_irq_fixup *fixup = &mpic->fixups[source]; 32.270 + unsigned long flags; 32.271 + u32 tmp; 32.272 + 32.273 + if (fixup->base == NULL) 32.274 + return; 32.275 + 32.276 + DBG("startup_ht_interrupt(%u, %u) index: %d\n", 32.277 + source, irqflags, fixup->index); 32.278 + spin_lock_irqsave(&mpic->fixup_lock, flags); 32.279 + /* Enable and configure */ 32.280 + writeb(0x10 + 2 * fixup->index, fixup->base + 2); 32.281 + tmp = readl(fixup->base + 4); 32.282 + tmp &= ~(0x23U); 32.283 + if (irqflags & IRQ_LEVEL) 32.284 + tmp |= 0x22; 32.285 + writel(tmp, fixup->base + 4); 32.286 + spin_unlock_irqrestore(&mpic->fixup_lock, flags); 32.287 +} 32.288 + 32.289 +static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source, 32.290 + unsigned int irqflags) 32.291 +{ 32.292 + struct mpic_irq_fixup *fixup = &mpic->fixups[source]; 32.293 + unsigned long flags; 32.294 + u32 tmp; 32.295 + 32.296 + if (fixup->base == NULL) 32.297 + return; 32.298 + 32.299 + DBG("shutdown_ht_interrupt(%u, %u)\n", source, irqflags); 32.300 + 32.301 + /* Disable */ 32.302 + spin_lock_irqsave(&mpic->fixup_lock, flags); 32.303 + writeb(0x10 + 2 * fixup->index, fixup->base + 2); 32.304 + tmp = readl(fixup->base + 4); 32.305 + tmp |= 1; 32.306 + writel(tmp, fixup->base + 4); 32.307 + spin_unlock_irqrestore(&mpic->fixup_lock, flags); 32.308 +} 32.309 + 32.310 +static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase, 32.311 + unsigned int devfn, u32 vdid) 32.312 +{ 32.313 + int i, irq, n; 32.314 + u8 __iomem *base; 32.315 + u32 tmp; 32.316 + u8 pos; 32.317 + 32.318 + for (pos = readb(devbase + PCI_CAPABILITY_LIST); pos != 0; 32.319 + pos = readb(devbase + pos + PCI_CAP_LIST_NEXT)) { 32.320 + u8 id = readb(devbase + pos + PCI_CAP_LIST_ID); 32.321 + if (id == PCI_CAP_ID_HT_IRQCONF) { 32.322 + id = readb(devbase + pos + 3); 32.323 + if (id == 0x80) 32.324 + break; 32.325 + } 32.326 + } 32.327 + if (pos == 0) 32.328 + return; 32.329 + 32.330 + base = devbase + pos; 32.331 + writeb(0x01, base + 2); 32.332 + n = (readl(base + 4) >> 16) & 0xff; 32.333 + 32.334 + printk(KERN_INFO "mpic: - HT:%02x.%x [0x%02x] vendor %04x device %04x" 32.335 + " has %d irqs\n", 32.336 + devfn >> 3, devfn & 0x7, pos, vdid & 0xffff, vdid >> 16, n + 1); 32.337 + 32.338 + for (i = 0; i <= n; i++) { 32.339 + writeb(0x10 + 2 * i, base + 2); 32.340 + tmp = readl(base + 4); 32.341 + irq = (tmp >> 16) & 0xff; 32.342 + DBG("HT PIC index 0x%x, irq 0x%x, tmp: %08x\n", i, irq, tmp); 32.343 + /* mask it , will be unmasked later */ 32.344 + tmp |= 0x1; 32.345 + writel(tmp, base + 4); 32.346 + mpic->fixups[irq].index = i; 32.347 + mpic->fixups[irq].base = base; 32.348 + /* Apple HT PIC has a non-standard way of doing EOIs */ 32.349 + if ((vdid & 0xffff) == 0x106b) 32.350 + mpic->fixups[irq].applebase = devbase + 0x60; 32.351 + else 32.352 + mpic->fixups[irq].applebase = NULL; 32.353 + writeb(0x11 + 2 * i, base + 2); 32.354 + mpic->fixups[irq].data = readl(base + 4) | 0x80000000; 32.355 + } 32.356 +} 32.357 + 32.358 + 32.359 +static void __init mpic_scan_ht_pics(struct mpic *mpic) 32.360 +{ 32.361 + unsigned int devfn; 32.362 + u8 __iomem *cfgspace; 32.363 + 32.364 + printk(KERN_INFO "mpic: Setting up HT PICs workarounds for U3/U4\n"); 32.365 + 32.366 + /* Allocate fixups array */ 32.367 + mpic->fixups = alloc_bootmem(128 * sizeof(struct mpic_irq_fixup)); 32.368 + BUG_ON(mpic->fixups == NULL); 32.369 + memset(mpic->fixups, 0, 128 * sizeof(struct mpic_irq_fixup)); 32.370 + 32.371 + /* Init spinlock */ 32.372 + spin_lock_init(&mpic->fixup_lock); 32.373 + 32.374 + /* Map U3 config space. We assume all IO-APICs are on the primary bus 32.375 + * so we only need to map 64kB. 32.376 + */ 32.377 + cfgspace = ioremap(0xf2000000, 0x10000); 32.378 + BUG_ON(cfgspace == NULL); 32.379 + 32.380 + /* Now we scan all slots. We do a very quick scan, we read the header 32.381 + * type, vendor ID and device ID only, that's plenty enough 32.382 + */ 32.383 + for (devfn = 0; devfn < 0x100; devfn++) { 32.384 + u8 __iomem *devbase = cfgspace + (devfn << 8); 32.385 + u8 hdr_type = readb(devbase + PCI_HEADER_TYPE); 32.386 + u32 l = readl(devbase + PCI_VENDOR_ID); 32.387 + u16 s; 32.388 + 32.389 + DBG("devfn %x, l: %x\n", devfn, l); 32.390 + 32.391 + /* If no device, skip */ 32.392 + if (l == 0xffffffff || l == 0x00000000 || 32.393 + l == 0x0000ffff || l == 0xffff0000) 32.394 + goto next; 32.395 + /* Check if is supports capability lists */ 32.396 + s = readw(devbase + PCI_STATUS); 32.397 + if (!(s & PCI_STATUS_CAP_LIST)) 32.398 + goto next; 32.399 + 32.400 + mpic_scan_ht_pic(mpic, devbase, devfn, l); 32.401 + 32.402 + next: 32.403 + /* next device, if function 0 */ 32.404 + if (PCI_FUNC(devfn) == 0 && (hdr_type & 0x80) == 0) 32.405 + devfn += 7; 32.406 + } 32.407 +} 32.408 + 32.409 +#endif /* CONFIG_MPIC_BROKEN_U3 */ 32.410 + 32.411 + 32.412 +/* Find an mpic associated with a given linux interrupt */ 32.413 +static struct mpic *mpic_find(unsigned int irq, unsigned int *is_ipi) 32.414 +{ 32.415 + struct mpic *mpic = mpics; 32.416 + 32.417 + while(mpic) { 32.418 + /* search IPIs first since they may override the main interrupts */ 32.419 + if (irq >= mpic->ipi_offset && irq < (mpic->ipi_offset + 4)) { 32.420 + if (is_ipi) 32.421 + *is_ipi = 1; 32.422 + return mpic; 32.423 + } 32.424 + if (irq >= mpic->irq_offset && 32.425 + irq < (mpic->irq_offset + mpic->irq_count)) { 32.426 + if (is_ipi) 32.427 + *is_ipi = 0; 32.428 + return mpic; 32.429 + } 32.430 + mpic = mpic -> next; 32.431 + } 32.432 + return NULL; 32.433 +} 32.434 + 32.435 +/* Convert a cpu mask from logical to physical cpu numbers. */ 32.436 +static inline u32 mpic_physmask(u32 cpumask) 32.437 +{ 32.438 + int i; 32.439 + u32 mask = 0; 32.440 + 32.441 + for (i = 0; i < NR_CPUS; ++i, cpumask >>= 1) 32.442 + mask |= (cpumask & 1) << get_hard_smp_processor_id(i); 32.443 + return mask; 32.444 +} 32.445 + 32.446 +#ifdef CONFIG_SMP 32.447 +/* Get the mpic structure from the IPI number */ 32.448 +static inline struct mpic * mpic_from_ipi(unsigned int ipi) 32.449 +{ 32.450 + return container_of(irq_desc[ipi].handler, struct mpic, hc_ipi); 32.451 +} 32.452 +#endif 32.453 + 32.454 +/* Get the mpic structure from the irq number */ 32.455 +static inline struct mpic * mpic_from_irq(unsigned int irq) 32.456 +{ 32.457 + return container_of(irq_desc[irq].handler, struct mpic, hc_irq); 32.458 +} 32.459 + 32.460 +/* Send an EOI */ 32.461 +static inline void mpic_eoi(struct mpic *mpic) 32.462 +{ 32.463 + mpic_cpu_write(MPIC_CPU_EOI, 0); 32.464 + (void)mpic_cpu_read(MPIC_CPU_WHOAMI); 32.465 +} 32.466 + 32.467 +#ifdef CONFIG_SMP 32.468 +static irqreturn_t mpic_ipi_action(int irq, void *dev_id, struct pt_regs *regs) 32.469 +{ 32.470 + struct mpic *mpic = dev_id; 32.471 + 32.472 + smp_message_recv(irq - mpic->ipi_offset, regs); 32.473 + return IRQ_HANDLED; 32.474 +} 32.475 +#endif /* CONFIG_SMP */ 32.476 + 32.477 +/* 32.478 + * Linux descriptor level callbacks 32.479 + */ 32.480 + 32.481 + 32.482 +static void mpic_enable_irq(unsigned int irq) 32.483 +{ 32.484 + unsigned int loops = 100000; 32.485 + struct mpic *mpic = mpic_from_irq(irq); 32.486 + unsigned int src = irq - mpic->irq_offset; 32.487 + 32.488 + DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src); 32.489 + 32.490 + mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, 32.491 + mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & 32.492 + ~MPIC_VECPRI_MASK); 32.493 + 32.494 + /* make sure mask gets to controller before we return to user */ 32.495 + do { 32.496 + if (!loops--) { 32.497 + printk(KERN_ERR "mpic_enable_irq timeout\n"); 32.498 + break; 32.499 + } 32.500 + } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK); 32.501 + 32.502 +#ifdef CONFIG_MPIC_BROKEN_U3 32.503 + if (mpic->flags & MPIC_BROKEN_U3) { 32.504 + unsigned int src = irq - mpic->irq_offset; 32.505 + if (mpic_is_ht_interrupt(mpic, src) && 32.506 + (irq_desc[irq].status & IRQ_LEVEL)) 32.507 + mpic_ht_end_irq(mpic, src); 32.508 + } 32.509 +#endif /* CONFIG_MPIC_BROKEN_U3 */ 32.510 +} 32.511 + 32.512 +static unsigned int mpic_startup_irq(unsigned int irq) 32.513 +{ 32.514 +#ifdef CONFIG_MPIC_BROKEN_U3 32.515 + struct mpic *mpic = mpic_from_irq(irq); 32.516 + unsigned int src = irq - mpic->irq_offset; 32.517 +#endif /* CONFIG_MPIC_BROKEN_U3 */ 32.518 + 32.519 + mpic_enable_irq(irq); 32.520 + 32.521 +#ifdef CONFIG_MPIC_BROKEN_U3 32.522 + if (mpic_is_ht_interrupt(mpic, src)) 32.523 + mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status); 32.524 +#endif /* CONFIG_MPIC_BROKEN_U3 */ 32.525 + 32.526 + return 0; 32.527 +} 32.528 + 32.529 +static void mpic_disable_irq(unsigned int irq) 32.530 +{ 32.531 + unsigned int loops = 100000; 32.532 + struct mpic *mpic = mpic_from_irq(irq); 32.533 + unsigned int src = irq - mpic->irq_offset; 32.534 + 32.535 + DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src); 32.536 + 32.537 + mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, 32.538 + mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) | 32.539 + MPIC_VECPRI_MASK); 32.540 + 32.541 + /* make sure mask gets to controller before we return to user */ 32.542 + do { 32.543 + if (!loops--) { 32.544 + printk(KERN_ERR "mpic_enable_irq timeout\n"); 32.545 + break; 32.546 + } 32.547 + } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK)); 32.548 +} 32.549 + 32.550 +static void mpic_shutdown_irq(unsigned int irq) 32.551 +{ 32.552 +#ifdef CONFIG_MPIC_BROKEN_U3 32.553 + struct mpic *mpic = mpic_from_irq(irq); 32.554 + unsigned int src = irq - mpic->irq_offset; 32.555 + 32.556 + if (mpic_is_ht_interrupt(mpic, src)) 32.557 + mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status); 32.558 + 32.559 +#endif /* CONFIG_MPIC_BROKEN_U3 */ 32.560 + 32.561 + mpic_disable_irq(irq); 32.562 +} 32.563 + 32.564 +static void mpic_end_irq(unsigned int irq) 32.565 +{ 32.566 + struct mpic *mpic = mpic_from_irq(irq); 32.567 + 32.568 +#ifdef DEBUG_IRQ 32.569 + DBG("%s: end_irq: %d\n", mpic->name, irq); 32.570 +#endif 32.571 + /* We always EOI on end_irq() even for edge interrupts since that 32.572 + * should only lower the priority, the MPIC should have properly 32.573 + * latched another edge interrupt coming in anyway 32.574 + */ 32.575 + 32.576 +#ifdef CONFIG_MPIC_BROKEN_U3 32.577 + if (mpic->flags & MPIC_BROKEN_U3) { 32.578 + unsigned int src = irq - mpic->irq_offset; 32.579 + if (mpic_is_ht_interrupt(mpic, src) && 32.580 + (irq_desc[irq].status & IRQ_LEVEL)) 32.581 + mpic_ht_end_irq(mpic, src); 32.582 + } 32.583 +#endif /* CONFIG_MPIC_BROKEN_U3 */ 32.584 + 32.585 + mpic_eoi(mpic); 32.586 +} 32.587 + 32.588 +#ifdef CONFIG_SMP 32.589 + 32.590 +static void mpic_enable_ipi(unsigned int irq) 32.591 +{ 32.592 + struct mpic *mpic = mpic_from_ipi(irq); 32.593 + unsigned int src = irq - mpic->ipi_offset; 32.594 + 32.595 + DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src); 32.596 + mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK); 32.597 +} 32.598 + 32.599 +static void mpic_disable_ipi(unsigned int irq) 32.600 +{ 32.601 + /* NEVER disable an IPI... that's just plain wrong! */ 32.602 +} 32.603 + 32.604 +static void mpic_end_ipi(unsigned int irq) 32.605 +{ 32.606 + struct mpic *mpic = mpic_from_ipi(irq); 32.607 + 32.608 + /* 32.609 + * IPIs are marked IRQ_PER_CPU. This has the side effect of 32.610 + * preventing the IRQ_PENDING/IRQ_INPROGRESS logic from 32.611 + * applying to them. We EOI them late to avoid re-entering. 32.612 + * We mark IPI's with SA_INTERRUPT as they must run with 32.613 + * irqs disabled. 32.614 + */ 32.615 + mpic_eoi(mpic); 32.616 +} 32.617 + 32.618 +#endif /* CONFIG_SMP */ 32.619 + 32.620 +static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask) 32.621 +{ 32.622 + struct mpic *mpic = mpic_from_irq(irq); 32.623 + 32.624 + cpumask_t tmp; 32.625 + 32.626 + cpus_and(tmp, cpumask, cpu_online_map); 32.627 + 32.628 + mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_DESTINATION, 32.629 + mpic_physmask(cpus_addr(tmp)[0])); 32.630 +} 32.631 + 32.632 + 32.633 +/* 32.634 + * Exported functions 32.635 + */ 32.636 + 32.637 + 32.638 +struct mpic * __init mpic_alloc(unsigned long phys_addr, 32.639 + unsigned int flags, 32.640 + unsigned int isu_size, 32.641 + unsigned int irq_offset, 32.642 + unsigned int irq_count, 32.643 + unsigned int ipi_offset, 32.644 + unsigned char *senses, 32.645 + unsigned int senses_count, 32.646 + const char *name) 32.647 +{ 32.648 + struct mpic *mpic; 32.649 + u32 reg; 32.650 + const char *vers; 32.651 + int i; 32.652 + 32.653 + mpic = alloc_bootmem(sizeof(struct mpic)); 32.654 + if (mpic == NULL) 32.655 + return NULL; 32.656 + 32.657 + 32.658 + memset(mpic, 0, sizeof(struct mpic)); 32.659 + mpic->name = name; 32.660 + 32.661 + mpic->hc_irq.typename = name; 32.662 + mpic->hc_irq.startup = mpic_startup_irq; 32.663 + mpic->hc_irq.shutdown = mpic_shutdown_irq; 32.664 + mpic->hc_irq.enable = mpic_enable_irq; 32.665 + mpic->hc_irq.disable = mpic_disable_irq; 32.666 + mpic->hc_irq.end = mpic_end_irq; 32.667 + if (flags & MPIC_PRIMARY) 32.668 + mpic->hc_irq.set_affinity = mpic_set_affinity; 32.669 +#ifdef CONFIG_SMP 32.670 + mpic->hc_ipi.typename = name; 32.671 + mpic->hc_ipi.enable = mpic_enable_ipi; 32.672 + mpic->hc_ipi.disable = mpic_disable_ipi; 32.673 + mpic->hc_ipi.end = mpic_end_ipi; 32.674 +#endif /* CONFIG_SMP */ 32.675 + 32.676 + mpic->flags = flags; 32.677 + mpic->isu_size = isu_size; 32.678 + mpic->irq_offset = irq_offset; 32.679 + mpic->irq_count = irq_count; 32.680 + mpic->ipi_offset = ipi_offset; 32.681 + mpic->num_sources = 0; /* so far */ 32.682 + mpic->senses = senses; 32.683 + mpic->senses_count = senses_count; 32.684 + 32.685 + /* Map the global registers */ 32.686 + mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000); 32.687 + mpic->tmregs = mpic->gregs + ((MPIC_TIMER_BASE - MPIC_GREG_BASE) >> 2); 32.688 + BUG_ON(mpic->gregs == NULL); 32.689 + 32.690 + /* Reset */ 32.691 + if (flags & MPIC_WANTS_RESET) { 32.692 + mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0, 32.693 + mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0) 32.694 + | MPIC_GREG_GCONF_RESET); 32.695 + while( mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0) 32.696 + & MPIC_GREG_GCONF_RESET) 32.697 + mb(); 32.698 + } 32.699 + 32.700 + /* Read feature register, calculate num CPUs and, for non-ISU 32.701 + * MPICs, num sources as well. On ISU MPICs, sources are counted 32.702 + * as ISUs are added 32.703 + */ 32.704 + reg = mpic_read(mpic->gregs, MPIC_GREG_FEATURE_0); 32.705 + mpic->num_cpus = ((reg & MPIC_GREG_FEATURE_LAST_CPU_MASK) 32.706 + >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1; 32.707 + if (isu_size == 0) 32.708 + mpic->num_sources = ((reg & MPIC_GREG_FEATURE_LAST_SRC_MASK) 32.709 + >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1; 32.710 + 32.711 + /* Map the per-CPU registers */ 32.712 + for (i = 0; i < mpic->num_cpus; i++) { 32.713 + mpic->cpuregs[i] = ioremap(phys_addr + MPIC_CPU_BASE + 32.714 + i * MPIC_CPU_STRIDE, 0x1000); 32.715 + BUG_ON(mpic->cpuregs[i] == NULL); 32.716 + } 32.717 + 32.718 + /* Initialize main ISU if none provided */ 32.719 + if (mpic->isu_size == 0) { 32.720 + mpic->isu_size = mpic->num_sources; 32.721 + mpic->isus[0] = ioremap(phys_addr + MPIC_IRQ_BASE, 32.722 + MPIC_IRQ_STRIDE * mpic->isu_size); 32.723 + BUG_ON(mpic->isus[0] == NULL); 32.724 + } 32.725 + mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); 32.726 + mpic->isu_mask = (1 << mpic->isu_shift) - 1; 32.727 + 32.728 + /* Display version */ 32.729 + switch (reg & MPIC_GREG_FEATURE_VERSION_MASK) { 32.730 + case 1: 32.731 + vers = "1.0"; 32.732 + break; 32.733 + case 2: 32.734 + vers = "1.2"; 32.735 + break; 32.736 + case 3: 32.737 + vers = "1.3"; 32.738 + break; 32.739 + default: 32.740 + vers = "<unknown>"; 32.741 + break; 32.742 + } 32.743 + printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %lx, max %d CPUs\n", 32.744 + name, vers, phys_addr, mpic->num_cpus); 32.745 + printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n", mpic->isu_size, 32.746 + mpic->isu_shift, mpic->isu_mask); 32.747 + 32.748 + mpic->next = mpics; 32.749 + mpics = mpic; 32.750 + 32.751 + if (flags & MPIC_PRIMARY) 32.752 + mpic_primary = mpic; 32.753 + 32.754 + return mpic; 32.755 +} 32.756 + 32.757 +void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, 32.758 + unsigned long phys_addr) 32.759 +{ 32.760 + unsigned int isu_first = isu_num * mpic->isu_size; 32.761 + 32.762 + BUG_ON(isu_num >= MPIC_MAX_ISU); 32.763 + 32.764 + mpic->isus[isu_num] = ioremap(phys_addr, MPIC_IRQ_STRIDE * mpic->isu_size); 32.765 + if ((isu_first + mpic->isu_size) > mpic->num_sources) 32.766 + mpic->num_sources = isu_first + mpic->isu_size; 32.767 +} 32.768 + 32.769 +void __init mpic_setup_cascade(unsigned int irq, mpic_cascade_t handler, 32.770 + void *data) 32.771 +{ 32.772 + struct mpic *mpic = mpic_find(irq, NULL); 32.773 + unsigned long flags; 32.774 + 32.775 + /* Synchronization here is a bit dodgy, so don't try to replace cascade 32.776 + * interrupts on the fly too often ... but normally it's set up at boot. 32.777 + */ 32.778 + spin_lock_irqsave(&mpic_lock, flags); 32.779 + if (mpic->cascade) 32.780 + mpic_disable_irq(mpic->cascade_vec + mpic->irq_offset); 32.781 + mpic->cascade = NULL; 32.782 + wmb(); 32.783 + mpic->cascade_vec = irq - mpic->irq_offset; 32.784 + mpic->cascade_data = data; 32.785 + wmb(); 32.786 + mpic->cascade = handler; 32.787 + mpic_enable_irq(irq); 32.788 + spin_unlock_irqrestore(&mpic_lock, flags); 32.789 +} 32.790 + 32.791 +void __init mpic_init(struct mpic *mpic) 32.792 +{ 32.793 + int i; 32.794 + 32.795 + BUG_ON(mpic->num_sources == 0); 32.796 + 32.797 + printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources); 32.798 + 32.799 + /* Set current processor priority to max */ 32.800 + mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf); 32.801 + 32.802 + /* Initialize timers: just disable them all */ 32.803 + for (i = 0; i < 4; i++) { 32.804 + mpic_write(mpic->tmregs, 32.805 + i * MPIC_TIMER_STRIDE + MPIC_TIMER_DESTINATION, 0); 32.806 + mpic_write(mpic->tmregs, 32.807 + i * MPIC_TIMER_STRIDE + MPIC_TIMER_VECTOR_PRI, 32.808 + MPIC_VECPRI_MASK | 32.809 + (MPIC_VEC_TIMER_0 + i)); 32.810 + } 32.811 + 32.812 + /* Initialize IPIs to our reserved vectors and mark them disabled for now */ 32.813 + mpic_test_broken_ipi(mpic); 32.814 + for (i = 0; i < 4; i++) { 32.815 + mpic_ipi_write(i, 32.816 + MPIC_VECPRI_MASK | 32.817 + (10 << MPIC_VECPRI_PRIORITY_SHIFT) | 32.818 + (MPIC_VEC_IPI_0 + i)); 32.819 +#ifdef CONFIG_SMP 32.820 + if (!(mpic->flags & MPIC_PRIMARY)) 32.821 + continue; 32.822 + irq_desc[mpic->ipi_offset+i].status |= IRQ_PER_CPU; 32.823 + irq_desc[mpic->ipi_offset+i].handler = &mpic->hc_ipi; 32.824 +#endif /* CONFIG_SMP */ 32.825 + } 32.826 + 32.827 + /* Initialize interrupt sources */ 32.828 + if (mpic->irq_count == 0) 32.829 + mpic->irq_count = mpic->num_sources; 32.830 + 32.831 +#ifdef CONFIG_MPIC_BROKEN_U3 32.832 + /* Do the HT PIC fixups on U3 broken mpic */ 32.833 + DBG("MPIC flags: %x\n", mpic->flags); 32.834 + if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY)) 32.835 + mpic_scan_ht_pics(mpic); 32.836 +#endif /* CONFIG_MPIC_BROKEN_U3 */ 32.837 + 32.838 + for (i = 0; i < mpic->num_sources; i++) { 32.839 + /* start with vector = source number, and masked */ 32.840 + u32 vecpri = MPIC_VECPRI_MASK | i | (8 << MPIC_VECPRI_PRIORITY_SHIFT); 32.841 + int level = 0; 32.842 + 32.843 + /* if it's an IPI, we skip it */ 32.844 + if ((mpic->irq_offset + i) >= (mpic->ipi_offset + i) && 32.845 + (mpic->irq_offset + i) < (mpic->ipi_offset + i + 4)) 32.846 + continue; 32.847 + 32.848 + /* do senses munging */ 32.849 + if (mpic->senses && i < mpic->senses_count) { 32.850 + if (mpic->senses[i] & IRQ_SENSE_LEVEL) 32.851 + vecpri |= MPIC_VECPRI_SENSE_LEVEL; 32.852 + if (mpic->senses[i] & IRQ_POLARITY_POSITIVE) 32.853 + vecpri |= MPIC_VECPRI_POLARITY_POSITIVE; 32.854 + } else 32.855 + vecpri |= MPIC_VECPRI_SENSE_LEVEL; 32.856 + 32.857 + /* remember if it was a level interrupts */ 32.858 + level = (vecpri & MPIC_VECPRI_SENSE_LEVEL); 32.859 + 32.860 + /* deal with broken U3 */ 32.861 + if (mpic->flags & MPIC_BROKEN_U3) { 32.862 +#ifdef CONFIG_MPIC_BROKEN_U3 32.863 + if (mpic_is_ht_interrupt(mpic, i)) { 32.864 + vecpri &= ~(MPIC_VECPRI_SENSE_MASK | 32.865 + MPIC_VECPRI_POLARITY_MASK); 32.866 + vecpri |= MPIC_VECPRI_POLARITY_POSITIVE; 32.867 + } 32.868 +#else 32.869 + printk(KERN_ERR "mpic: BROKEN_U3 set, but CONFIG doesn't match\n"); 32.870 +#endif 32.871 + } 32.872 + 32.873 + DBG("setup source %d, vecpri: %08x, level: %d\n", i, vecpri, 32.874 + (level != 0)); 32.875 + 32.876 + /* init hw */ 32.877 + mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri); 32.878 + mpic_irq_write(i, MPIC_IRQ_DESTINATION, 32.879 + 1 << hard_smp_processor_id()); 32.880 + 32.881 + /* init linux descriptors */ 32.882 + if (i < mpic->irq_count) { 32.883 + irq_desc[mpic->irq_offset+i].status = level ? IRQ_LEVEL : 0; 32.884 + irq_desc[mpic->irq_offset+i].handler = &mpic->hc_irq; 32.885 + } 32.886 + } 32.887 + 32.888 + /* Init spurrious vector */ 32.889 + mpic_write(mpic->gregs, MPIC_GREG_SPURIOUS, MPIC_VEC_SPURRIOUS); 32.890 + 32.891 + /* Disable 8259 passthrough */ 32.892 + mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0, 32.893 + mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0) 32.894 + | MPIC_GREG_GCONF_8259_PTHROU_DIS); 32.895 + 32.896 + /* Set current processor priority to 0 */ 32.897 + mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0); 32.898 +} 32.899 + 32.900 + 32.901 + 32.902 +void mpic_irq_set_priority(unsigned int irq, unsigned int pri) 32.903 +{ 32.904 + unsigned is_ipi; 32.905 + struct mpic *mpic = mpic_find(irq, &is_ipi); 32.906 + unsigned long flags; 32.907 + u32 reg; 32.908 + 32.909 + spin_lock_irqsave(&mpic_lock, flags); 32.910 + if (is_ipi) { 32.911 + reg = mpic_ipi_read(irq - mpic->ipi_offset) & 32.912 + ~MPIC_VECPRI_PRIORITY_MASK; 32.913 + mpic_ipi_write(irq - mpic->ipi_offset, 32.914 + reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); 32.915 + } else { 32.916 + reg = mpic_irq_read(irq - mpic->irq_offset,MPIC_IRQ_VECTOR_PRI) 32.917 + & ~MPIC_VECPRI_PRIORITY_MASK; 32.918 + mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI, 32.919 + reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); 32.920 + } 32.921 + spin_unlock_irqrestore(&mpic_lock, flags); 32.922 +} 32.923 + 32.924 +unsigned int mpic_irq_get_priority(unsigned int irq) 32.925 +{ 32.926 + unsigned is_ipi; 32.927 + struct mpic *mpic = mpic_find(irq, &is_ipi); 32.928 + unsigned long flags; 32.929 + u32 reg; 32.930 + 32.931 + spin_lock_irqsave(&mpic_lock, flags); 32.932 + if (is_ipi) 32.933 + reg = mpic_ipi_read(irq - mpic->ipi_offset); 32.934 + else 32.935 + reg = mpic_irq_read(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI); 32.936 + spin_unlock_irqrestore(&mpic_lock, flags); 32.937 + return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT; 32.938 +} 32.939 + 32.940 +void mpic_setup_this_cpu(void) 32.941 +{ 32.942 +#ifdef CONFIG_SMP 32.943 + struct mpic *mpic = mpic_primary; 32.944 + unsigned long flags; 32.945 + u32 msk = 1 << hard_smp_processor_id(); 32.946 + unsigned int i; 32.947 + 32.948 + BUG_ON(mpic == NULL); 32.949 + 32.950 + DBG("%s: setup_this_cpu(%d)\n", mpic->name, hard_smp_processor_id()); 32.951 + 32.952 + spin_lock_irqsave(&mpic_lock, flags); 32.953 + 32.954 + /* let the mpic know we want intrs. default affinity is 0xffffffff 32.955 + * until changed via /proc. That's how it's done on x86. If we want 32.956 + * it differently, then we should make sure we also change the default 32.957 + * values of irq_affinity in irq.c. 32.958 + */ 32.959 + if (distribute_irqs) { 32.960 + for (i = 0; i < mpic->num_sources ; i++) 32.961 + mpic_irq_write(i, MPIC_IRQ_DESTINATION, 32.962 + mpic_irq_read(i, MPIC_IRQ_DESTINATION) | msk); 32.963 + } 32.964 + 32.965 + /* Set current processor priority to 0 */ 32.966 + mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0); 32.967 + 32.968 + spin_unlock_irqrestore(&mpic_lock, flags); 32.969 +#endif /* CONFIG_SMP */ 32.970 +} 32.971 + 32.972 +int mpic_cpu_get_priority(void) 32.973 +{ 32.974 + struct mpic *mpic = mpic_primary; 32.975 + 32.976 + return mpic_cpu_read(MPIC_CPU_CURRENT_TASK_PRI); 32.977 +} 32.978 + 32.979 +void mpic_cpu_set_priority(int prio) 32.980 +{ 32.981 + struct mpic *mpic = mpic_primary; 32.982 + 32.983 + prio &= MPIC_CPU_TASKPRI_MASK; 32.984 + mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, prio); 32.985 +} 32.986 + 32.987 +/* 32.988 + * XXX: someone who knows mpic should check this. 32.989 + * do we need to eoi the ipi including for kexec cpu here (see xics comments)? 32.990 + * or can we reset the mpic in the new kernel? 32.991 + */ 32.992 +void mpic_teardown_this_cpu(int secondary) 32.993 +{ 32.994 + struct mpic *mpic = mpic_primary; 32.995 + unsigned long flags; 32.996 + u32 msk = 1 << hard_smp_processor_id(); 32.997 + unsigned int i; 32.998 + 32.999 + BUG_ON(mpic == NULL); 32.1000 + 32.1001 + DBG("%s: teardown_this_cpu(%d)\n", mpic->name, hard_smp_processor_id()); 32.1002 + spin_lock_irqsave(&mpic_lock, flags); 32.1003 + 32.1004 + /* let the mpic know we don't want intrs. */ 32.1005 + for (i = 0; i < mpic->num_sources ; i++) 32.1006 + mpic_irq_write(i, MPIC_IRQ_DESTINATION, 32.1007 + mpic_irq_read(i, MPIC_IRQ_DESTINATION) & ~msk); 32.1008 + 32.1009 + /* Set current processor priority to max */ 32.1010 + mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf); 32.1011 + 32.1012 + spin_unlock_irqrestore(&mpic_lock, flags); 32.1013 +} 32.1014 + 32.1015 + 32.1016 +void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask) 32.1017 +{ 32.1018 + struct mpic *mpic = mpic_primary; 32.1019 + 32.1020 + BUG_ON(mpic == NULL); 32.1021 + 32.1022 +#ifdef DEBUG_IPI 32.1023 + DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no); 32.1024 +#endif 32.1025 + 32.1026 + mpic_cpu_write(MPIC_CPU_IPI_DISPATCH_0 + ipi_no * 0x10, 32.1027 + mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0])); 32.1028 +} 32.1029 + 32.1030 +int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs) 32.1031 +{ 32.1032 + u32 irq; 32.1033 + 32.1034 + irq = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK; 32.1035 +#ifdef DEBUG_LOW 32.1036 + DBG("%s: get_one_irq(): %d\n", mpic->name, irq); 32.1037 +#endif 32.1038 + if (mpic->cascade && irq == mpic->cascade_vec) { 32.1039 +#ifdef DEBUG_LOW 32.1040 + DBG("%s: cascading ...\n", mpic->name); 32.1041 +#endif 32.1042 + irq = mpic->cascade(regs, mpic->cascade_data); 32.1043 + mpic_eoi(mpic); 32.1044 + return irq; 32.1045 + } 32.1046 + if (unlikely(irq == MPIC_VEC_SPURRIOUS)) 32.1047 + return -1; 32.1048 + if (irq < MPIC_VEC_IPI_0) { 32.1049 +#ifdef DEBUG_IRQ 32.1050 + DBG("%s: irq %d\n", mpic->name, irq + mpic->irq_offset); 32.1051 +#endif 32.1052 + return irq + mpic->irq_offset; 32.1053 + } 32.1054 +#ifdef DEBUG_IPI 32.1055 + DBG("%s: ipi %d !\n", mpic->name, irq - MPIC_VEC_IPI_0); 32.1056 +#endif 32.1057 + return irq - MPIC_VEC_IPI_0 + mpic->ipi_offset; 32.1058 +} 32.1059 + 32.1060 +int mpic_get_irq(struct pt_regs *regs) 32.1061 +{ 32.1062 + struct mpic *mpic = mpic_primary; 32.1063 + 32.1064 + BUG_ON(mpic == NULL); 32.1065 + 32.1066 + return mpic_get_one_irq(mpic, regs); 32.1067 +} 32.1068 + 32.1069 + 32.1070 +#ifdef CONFIG_SMP 32.1071 +void mpic_request_ipis(void) 32.1072 +{ 32.1073 + struct mpic *mpic = mpic_primary; 32.1074 + 32.1075 + BUG_ON(mpic == NULL); 32.1076 + 32.1077 + printk("requesting IPIs ... \n"); 32.1078 + 32.1079 + /* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */ 32.1080 + request_irq(mpic->ipi_offset+0, mpic_ipi_action, SA_INTERRUPT, 32.1081 + "IPI0 (call function)", mpic); 32.1082 + request_irq(mpic->ipi_offset+1, mpic_ipi_action, SA_INTERRUPT, 32.1083 + "IPI1 (reschedule)", mpic); 32.1084 + request_irq(mpic->ipi_offset+2, mpic_ipi_action, SA_INTERRUPT, 32.1085 + "IPI2 (unused)", mpic); 32.1086 + request_irq(mpic->ipi_offset+3, mpic_ipi_action, SA_INTERRUPT, 32.1087 + "IPI3 (debugger break)", mpic); 32.1088 + 32.1089 + printk("IPIs requested... \n"); 32.1090 +} 32.1091 + 32.1092 +void smp_mpic_message_pass(int target, int msg) 32.1093 +{ 32.1094 + /* make sure we're sending something that translates to an IPI */ 32.1095 + if ((unsigned int)msg > 3) { 32.1096 + printk("SMP %d: smp_message_pass: unknown msg %d\n", 32.1097 + smp_processor_id(), msg); 32.1098 + return; 32.1099 + } 32.1100 + switch (target) { 32.1101 + case MSG_ALL: 32.1102 + mpic_send_ipi(msg, 0xffffffff); 32.1103 + break; 32.1104 + case MSG_ALL_BUT_SELF: 32.1105 + mpic_send_ipi(msg, 0xffffffff & ~(1 << smp_processor_id())); 32.1106 + break; 32.1107 + default: 32.1108 + mpic_send_ipi(msg, 1 << target); 32.1109 + break; 32.1110 + } 32.1111 +} 32.1112 +#endif /* CONFIG_SMP */
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 33.2 +++ b/xen/arch/powerpc/mpic_init.c Fri Jul 14 10:47:50 2006 +0100 33.3 @@ -0,0 +1,390 @@ 33.4 +/* 33.5 + * This program is free software; you can redistribute it and/or modify 33.6 + * it under the terms of the GNU General Public License as published by 33.7 + * the Free Software Foundation; either version 2 of the License, or 33.8 + * (at your option) any later version. 33.9 + * 33.10 + * This program is distributed in the hope that it will be useful, 33.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 33.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 33.13 + * GNU General Public License for more details. 33.14 + * 33.15 + * You should have received a copy of the GNU General Public License 33.16 + * along with this program; if not, write to the Free Software 33.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 33.18 + * 33.19 + * Copyright (C) IBM Corp. 2005 33.20 + * 33.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 33.22 + */ 33.23 + 33.24 +#include <xen/config.h> 33.25 +#include <xen/init.h> 33.26 +#include <xen/lib.h> 33.27 +#include <xen/compile.h> 33.28 +#include <asm/mpic.h> 33.29 +#include "mpic_init.h" 33.30 +#include "oftree.h" 33.31 +#include "of-devtree.h" 33.32 + 33.33 +#undef DEBUG 33.34 +#ifdef DEBUG 33.35 +#define DBG(fmt...) printk(fmt) 33.36 +#else 33.37 +#define DBG(fmt...) 33.38 +#endif 33.39 + 33.40 +#define PANIC(fmt...) DBG(fmt) 33.41 + 33.42 +static struct mpic *mpic; 33.43 +static unsigned long opic_addr; 33.44 +static unsigned int opic_flags; 33.45 + 33.46 +/* 33.47 + * from OF_IEEE_1275 33.48 + * 33.49 + * pg 175, property "ranges" 33.50 + * 33.51 + * The number of integers in each size entry is determined by the 33.52 + * value of the #size-cells property of this node (the node in which 33.53 + * the ranges property appears) or 1 if the #size-cells property is 33.54 + * absent. 33.55 + * 33.56 + * 33.57 + * pg 177, property "reg" 33.58 + * 33.59 + * The number of integers in each size entry is determined by the 33.60 + * value of the "#size-cells" property in the parent node. If the 33.61 + * parent node has no such property, the value is one. 33.62 + */ 33.63 +static unsigned long reg2(void *oft_p, ofdn_t c) 33.64 +{ 33.65 + int rc; 33.66 + /* the struct isa_reg_property is for a value of 2 for 33.67 + * #address-cells and a value of 1 for #size-cells (of the 33.68 + * parent). 33.69 + */ 33.70 + struct isa_reg_property { 33.71 + u32 space; 33.72 + u32 address; 33.73 + u32 size; 33.74 + } isa_reg; 33.75 + 33.76 + rc = ofd_getprop(oft_p, c, "reg", &isa_reg, sizeof(isa_reg)); 33.77 + 33.78 + DBG("%s: reg property address=0x%08x size=0x%08x\n", __func__, 33.79 + isa_reg.address, isa_reg.size); 33.80 + return isa_reg.address; 33.81 +} 33.82 + 33.83 +static unsigned long reg1(void *oft_p, ofdn_t c) 33.84 +{ 33.85 + int rc; 33.86 + /* the struct reg_property32 is for a value of 1 for 33.87 + * #address-cells and a value of 1 for #size-cells. 33.88 + */ 33.89 + struct reg_property32 { 33.90 + u32 address; 33.91 + u32 size; 33.92 + } reg; 33.93 + 33.94 + rc = ofd_getprop(oft_p, c, "reg", ®, sizeof(reg)); 33.95 + 33.96 + DBG("%s: reg property address=0x%08x size=0x%08x\n", __func__, 33.97 + reg.address, reg.size); 33.98 + return reg.address; 33.99 +} 33.100 + 33.101 +static unsigned long find_reg_addr_from_node(void *oft_p, ofdn_t c) 33.102 +{ 33.103 + int p_len; 33.104 + unsigned long reg_addr = 0; 33.105 + u32 size_c = 1; 33.106 + u32 addr_c = 2; 33.107 + ofdn_t parent; 33.108 + 33.109 + if (c == OFD_ROOT) { 33.110 + parent = c; 33.111 + } else { 33.112 + parent = ofd_node_parent(oft_p, c); 33.113 + } 33.114 + 33.115 + p_len = ofd_getprop(oft_p, parent, "#size-cells", &size_c, sizeof(size_c)); 33.116 + DBG("%s size is %d\n", __func__, size_c); 33.117 + 33.118 + p_len = ofd_getprop(oft_p, parent, "#address-cells", &addr_c, 33.119 + sizeof(addr_c)); 33.120 + DBG("%s address is %d\n", __func__, addr_c); 33.121 + 33.122 + if ( 1 != size_c ) { 33.123 + PANIC("Unsupported size for reg property\n"); 33.124 + } 33.125 + 33.126 + if ( 1 == addr_c) { 33.127 + reg_addr = reg1(oft_p, c); 33.128 + } else if ( 2 == addr_c ) { 33.129 + reg_addr = reg2(oft_p, c); 33.130 + } else { 33.131 + PANIC("Unsupported address size for reg property\n"); 33.132 + } 33.133 + DBG("%s: address 0x%lx\n", __func__, reg_addr); 33.134 + return reg_addr; 33.135 +} 33.136 + 33.137 +/* 33.138 + * from OF_IEEE_1275 33.139 + * 33.140 + * pg 175, property "ranges" 33.141 + * 33.142 + * The ranges property value is a sequence of child-phys parent-phys 33.143 + * size specifications. Child-phys is an address, encoded as with 33.144 + * encode-phys, in the child address space. Parent-phys is an address 33.145 + * (likewise encoded as with encode-phys) in the parent address 33.146 + * space. Size is a list of integers, each encoded as with encode-int, 33.147 + * denoting the length of the child's address range. 33.148 + */ 33.149 +static unsigned long find_ranges_addr_from_node(void *oft_p, ofdn_t c) 33.150 +{ 33.151 + unsigned long ranges_addr = 0; 33.152 + int ranges_i; 33.153 + ofdn_t parent; 33.154 + u32 addr_c = 2; 33.155 + u32 ranges[64]; 33.156 + int p_len; 33.157 + 33.158 + parent = ofd_node_parent(oft_p, c); 33.159 + parent = ofd_node_parent(oft_p, parent); 33.160 + 33.161 + p_len = ofd_getprop(oft_p, parent, "ranges", &ranges, sizeof(ranges)); 33.162 + DBG("%s: ranges\n", __func__); 33.163 + int i; for (i=0; i<p_len; i++) {DBG("%08x ", ranges[i]);} 33.164 + DBG("\n"); 33.165 + 33.166 + p_len = ofd_getprop(oft_p, parent, "#address-cells", 33.167 + &addr_c, sizeof(addr_c)); 33.168 + DBG("%s address is %d\n", __func__, addr_c); 33.169 + ranges_i = addr_c; /* skip over the child address */ 33.170 + 33.171 + DBG("%s address is %d\n", __func__, addr_c); 33.172 + switch (addr_c) { 33.173 + case 1: 33.174 + ranges_addr = ranges[ranges_i]; 33.175 + break; 33.176 + case 2: 33.177 + ranges_addr = (((u64)ranges[ranges_i]) << 32) | 33.178 + ranges[ranges_i + 1]; 33.179 + break; 33.180 + case 3: /* the G5 case, how to squeeze 96 bits into 64 */ 33.181 + ranges_addr = (((u64)ranges[ranges_i+1]) << 32) | 33.182 + ranges[ranges_i + 2]; 33.183 + break; 33.184 + case 4: 33.185 + ranges_addr = (((u64)ranges[ranges_i+2]) << 32) | 33.186 + ranges[ranges_i + 4]; 33.187 + break; 33.188 + default: 33.189 + PANIC("#address-cells out of range\n"); 33.190 + break; 33.191 + } 33.192 + 33.193 + DBG("%s: address 0x%lx\n", __func__, ranges_addr); 33.194 + return ranges_addr; 33.195 +} 33.196 + 33.197 +static unsigned long find_pic_address_from_node(void *oft_p, ofdn_t c) 33.198 +{ 33.199 + unsigned long reg_addr, range_addr, addr; 33.200 + 33.201 + /* 33.202 + * The address is the sum of the address in the reg property of this node 33.203 + * and the ranges property of the granparent node. 33.204 + */ 33.205 + reg_addr = find_reg_addr_from_node(oft_p, c); 33.206 + range_addr = find_ranges_addr_from_node(oft_p, c); 33.207 + addr = reg_addr + range_addr; 33.208 + DBG("%s: address 0x%lx\n", __func__, addr); 33.209 + return addr; 33.210 +} 33.211 + 33.212 +static unsigned int find_pic_flags_from_node(void *oft_p, ofdn_t c) 33.213 +{ 33.214 + int be_len; 33.215 + unsigned int flags = 0; 33.216 + 33.217 + /* does it have the property big endian? */ 33.218 + be_len = ofd_getprop(oft_p, c, "big_endian", NULL, 0); 33.219 + if (be_len >= 0) { 33.220 + DBG("%s: Big Endian found\n", __func__); 33.221 + flags |= MPIC_BIG_ENDIAN; 33.222 + } 33.223 + DBG("%s: flags 0x%x\n", __func__, flags); 33.224 + return flags; 33.225 +} 33.226 + 33.227 +static int find_mpic_simple_probe(void *oft_p) 33.228 +{ 33.229 + u32 addr_cells; 33.230 + int rc; 33.231 + u32 addr[2]; 33.232 + 33.233 + rc = ofd_getprop(oft_p, OFD_ROOT, "#address-cells", 33.234 + &addr_cells, sizeof(addr_cells)); 33.235 + if ( rc < 0 ) { 33.236 + /* if the property does not exist use its default value, 2 */ 33.237 + addr_cells = 2; 33.238 + } 33.239 + 33.240 + rc = ofd_getprop(oft_p, OFD_ROOT, "platform-open-pic", addr, sizeof(addr)); 33.241 + if (rc < 0) { 33.242 + return rc; 33.243 + } 33.244 + 33.245 + opic_addr = addr[0]; 33.246 + if (addr_cells == 2) { 33.247 + opic_addr <<= 32; 33.248 + opic_addr |= addr[1]; 33.249 + } 33.250 + DBG("%s: found OpenPIC at: 0x%lx\n", __func__, opic_addr); 33.251 + /* we did not really find the pic device, only its address. 33.252 + * We use big endian and broken u3 by default. 33.253 + */ 33.254 + opic_flags |= MPIC_BIG_ENDIAN | MPIC_BROKEN_U3; 33.255 + return 0; 33.256 +} 33.257 + 33.258 +static int find_mpic_canonical_probe(void *oft_p) 33.259 +{ 33.260 + ofdn_t c; 33.261 + const char mpic_type[] = "open-pic"; 33.262 + /* some paths are special and we cannot find the address 33.263 + * by the usual method */ 33.264 + const char *excluded_paths[] = { "/interrupt-controller" }; 33.265 + 33.266 + /* 33.267 + * Search through the OFD tree for all devices of type 'open_pic'. 33.268 + * We select the one without an 'interrupt' property. 33.269 + */ 33.270 + c = ofd_node_find_by_prop(oft_p, OFD_ROOT, "device_type", mpic_type, 33.271 + sizeof(mpic_type)); 33.272 + while (c > 0) { 33.273 + int int_len; 33.274 + int good_mpic; 33.275 + const char * path = ofd_node_path(oft_p, c); 33.276 + 33.277 + good_mpic = 0; 33.278 + int_len = ofd_getprop(oft_p, c, "interrupts", NULL, 0); 33.279 + if (int_len < 0) { 33.280 + int i; 33.281 + 33.282 + /* there is no property interrupt. This could be the pic */ 33.283 + DBG("%s: potential OpenPIC in: %s\n", __func__, path); 33.284 + good_mpic = 1; 33.285 + 33.286 + for (i = 0; i < ARRAY_SIZE(excluded_paths) && good_mpic; i++) { 33.287 + const char *excluded_path = excluded_paths[i]; 33.288 + if (!strncmp(path, excluded_path, strlen(excluded_path))) 33.289 + good_mpic = 0; 33.290 + } 33.291 + } 33.292 + 33.293 + if (good_mpic) { 33.294 + DBG("%s: found OpenPIC in: %s\n", __func__, path); 33.295 + opic_addr = find_pic_address_from_node(oft_p, c); 33.296 + opic_flags = find_pic_flags_from_node(oft_p, c); 33.297 + return 0; 33.298 + } 33.299 + 33.300 + c = ofd_node_find_next(oft_p, c); 33.301 + } 33.302 + 33.303 + DBG("%s: Could not find a pic\n", __func__); 33.304 + return -1; 33.305 +} 33.306 + 33.307 +static int find_mpic(void) 33.308 +{ 33.309 + void *oft_p; 33.310 + int rc; 33.311 + 33.312 + opic_addr = (unsigned long)-1; 33.313 + opic_flags = 0; 33.314 + 33.315 + oft_p = (void *)oftree; 33.316 + rc = find_mpic_simple_probe(oft_p); 33.317 + 33.318 + if (rc < 0) { 33.319 + DBG("%s: Searching for pic ...\n", __func__); 33.320 + rc = find_mpic_canonical_probe(oft_p); 33.321 + } 33.322 + 33.323 + return rc; 33.324 +} 33.325 + 33.326 +static struct hw_interrupt_type hc_irq; 33.327 + 33.328 +struct hw_interrupt_type *xen_mpic_init(struct hw_interrupt_type *xen_irq) 33.329 +{ 33.330 + unsigned int isu_size; 33.331 + unsigned int irq_offset; 33.332 + unsigned int irq_count; 33.333 + unsigned int ipi_offset; 33.334 + unsigned char *senses; 33.335 + unsigned int senses_count; 33.336 + 33.337 + printk("%s: start\n", __func__); 33.338 + 33.339 + io_apic_irqs = ~0; /* all IRQs go through IOAPIC */ 33.340 + irq_vector[0] = FIRST_DEVICE_VECTOR; 33.341 + vector_irq[FIRST_DEVICE_VECTOR] = 0; 33.342 + 33.343 + isu_size = 0; 33.344 + irq_offset = 0; 33.345 + irq_count = 128; 33.346 + ipi_offset = 128; 33.347 + senses = NULL; 33.348 + senses_count = 0; 33.349 + 33.350 + if (find_mpic()) { 33.351 + printk("%s: ERROR: Could not find open pic.\n", __func__); 33.352 + return NULL; 33.353 + } 33.354 + 33.355 + mpic = mpic_alloc(opic_addr, 33.356 + opic_flags | MPIC_PRIMARY | MPIC_WANTS_RESET, 33.357 + isu_size, irq_offset, irq_count, 33.358 + ipi_offset, senses, senses_count, "Xen-U3-MPIC"); 33.359 + 33.360 + BUG_ON(mpic == NULL); 33.361 + mpic_init(mpic); 33.362 + 33.363 + hc_irq.startup = mpic->hc_irq.startup; 33.364 + mpic->hc_irq.startup = xen_irq->startup; 33.365 + 33.366 + hc_irq.enable = mpic->hc_irq.enable; 33.367 + mpic->hc_irq.enable = xen_irq->enable; 33.368 + 33.369 + hc_irq.disable = mpic->hc_irq.disable; 33.370 + mpic->hc_irq.disable = xen_irq->disable; 33.371 + 33.372 + hc_irq.shutdown = mpic->hc_irq.shutdown; 33.373 + mpic->hc_irq.shutdown = xen_irq->shutdown; 33.374 + 33.375 + hc_irq.ack = mpic->hc_irq.ack; 33.376 + mpic->hc_irq.ack = xen_irq->ack; 33.377 + 33.378 + hc_irq.end = mpic->hc_irq.end; 33.379 + mpic->hc_irq.end = xen_irq->end; 33.380 + 33.381 + hc_irq.set_affinity = mpic->hc_irq.set_affinity; 33.382 + mpic->hc_irq.set_affinity = xen_irq->set_affinity; 33.383 + 33.384 + printk("%s: success\n", __func__); 33.385 + return &hc_irq; 33.386 +} 33.387 + 33.388 +int xen_mpic_get_irq(struct cpu_user_regs *regs) 33.389 +{ 33.390 + BUG_ON(mpic == NULL); 33.391 + 33.392 + return mpic_get_one_irq(mpic, regs); 33.393 +}
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 34.2 +++ b/xen/arch/powerpc/mpic_init.h Fri Jul 14 10:47:50 2006 +0100 34.3 @@ -0,0 +1,29 @@ 34.4 +/* 34.5 + * This program is free software; you can redistribute it and/or modify 34.6 + * it under the terms of the GNU General Public License as published by 34.7 + * the Free Software Foundation; either version 2 of the License, or 34.8 + * (at your option) any later version. 34.9 + * 34.10 + * This program is distributed in the hope that it will be useful, 34.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 34.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 34.13 + * GNU General Public License for more details. 34.14 + * 34.15 + * You should have received a copy of the GNU General Public License 34.16 + * along with this program; if not, write to the Free Software 34.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 34.18 + * 34.19 + * Copyright (C) IBM Corp. 2005 34.20 + * 34.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 34.22 + */ 34.23 + 34.24 +#ifndef _MPIC_INIT_H 34.25 +#define _MPIC_INIT_H 34.26 + 34.27 +extern struct hw_interrupt_type *xen_mpic_init( 34.28 + struct hw_interrupt_type *xen_irq); 34.29 + 34.30 +extern int xen_mpic_get_irq(struct cpu_user_regs *regs); 34.31 + 34.32 +#endif /* #ifndef _MPIC_INIT_H */
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 35.2 +++ b/xen/arch/powerpc/of-devtree.c Fri Jul 14 10:47:50 2006 +0100 35.3 @@ -0,0 +1,1088 @@ 35.4 +/* 35.5 + * This program is free software; you can redistribute it and/or modify 35.6 + * it under the terms of the GNU General Public License as published by 35.7 + * the Free Software Foundation; either version 2 of the License, or 35.8 + * (at your option) any later version. 35.9 + * 35.10 + * This program is distributed in the hope that it will be useful, 35.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 35.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 35.13 + * GNU General Public License for more details. 35.14 + * 35.15 + * You should have received a copy of the GNU General Public License 35.16 + * along with this program; if not, write to the Free Software 35.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 35.18 + * 35.19 + * Copyright (C) IBM Corp. 2005 35.20 + * 35.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 35.22 + */ 35.23 + 35.24 +/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING 35.25 + * This code is intended to be used but relocatable routines So PLEASE 35.26 + * do not place any global data here including const integrals or 35.27 + * literals. 35.28 + * The local assert() is ok for string literal usage.. but thats it. 35.29 + */ 35.30 + 35.31 + 35.32 +#include <xen/config.h> 35.33 +#include <xen/init.h> 35.34 +#include <xen/lib.h> 35.35 +#include "of-devtree.h" 35.36 + 35.37 +static int (*ofd_write)(const char *, size_t len) = NULL; 35.38 + 35.39 +void ofd_init(int (*write)(const char *, size_t len)) 35.40 +{ 35.41 + ofd_write = write; 35.42 +} 35.43 + 35.44 + 35.45 +static void ofd_stop(void) 35.46 +{ 35.47 + for ( ; ; ) ; 35.48 +} 35.49 + 35.50 +/* this is so it can be called from anywhere */ 35.51 +static void ofd_assprint(int line) 35.52 +{ 35.53 + char a[13]; 35.54 + char num[20]; 35.55 + int i; 35.56 + 35.57 + a[0] = '\n'; 35.58 + a[1] = '\n'; 35.59 + a[2] = 'O'; 35.60 + a[3] = 'F'; 35.61 + a[4] = 'D'; 35.62 + a[5] = ':'; 35.63 + a[6] = 'A'; 35.64 + a[7] = 'S'; 35.65 + a[8] = 'S'; 35.66 + a[9] = 'E'; 35.67 + a[10] = 'R'; 35.68 + a[11] = 'T'; 35.69 + a[12] = ':'; 35.70 + 35.71 + 35.72 + ofd_write(a, sizeof (a) - 1); 35.73 + 35.74 + /* put the number in backwards */ 35.75 + i = 0; 35.76 + while ( line > 0 ) { 35.77 + num[i++] = '0' + (line % 10); 35.78 + line /= 10; 35.79 + } 35.80 + /* print it */ 35.81 + /* number */ 35.82 + while (i-- > 0) { 35.83 + ofd_write(&num[i], 1); 35.84 + } 35.85 + ofd_write("\n", 1); 35.86 + 35.87 + ofd_stop(); 35.88 +} 35.89 + 35.90 +#ifdef assert 35.91 +#undef assert 35.92 +#endif 35.93 + 35.94 +#define assert(EX) \ 35.95 + do { \ 35.96 + if ( !(EX) ) { \ 35.97 + ofd_assprint(__LINE__); \ 35.98 + } \ 35.99 + } while (0) 35.100 + 35.101 +/* 35.102 + * We treat memory like an array of u64. For the sake of 35.103 + * compactness we assume that a short is big enough as an index. 35.104 + */ 35.105 +struct ofd_node { 35.106 + ofdn_t on_ima; 35.107 + ofdn_t on_parent; 35.108 + ofdn_t on_child; 35.109 + ofdn_t on_peer; 35.110 + ofdn_t on_io; 35.111 + ofdn_t on_next; /* for search lists */ 35.112 + ofdn_t on_prev; 35.113 + ofdn_t on_prop; 35.114 + u32 on_pathlen; 35.115 + u32 on_last; 35.116 + char on_path[0]; 35.117 +}; 35.118 + 35.119 +struct ofd_prop { 35.120 + ofdn_t op_ima; 35.121 + ofdn_t op_next; 35.122 + u32 op_objsz; 35.123 + u32 op_namesz; 35.124 + /* must have 64bit alignment */ 35.125 + char op_data[0] __attribute__ ((aligned(8))); 35.126 +}; 35.127 + 35.128 +struct ofd_io { 35.129 + ofdn_t oi_ima; 35.130 + ofdn_t oi_node; 35.131 + u64 oi_open __attribute__ ((aligned(8))); 35.132 +}; 35.133 + 35.134 +struct ofd_free { 35.135 + ofdn_t of_cells; 35.136 + ofdn_t of_next; 35.137 +}; 35.138 + 35.139 +struct ofd_mem { 35.140 + ofdn_t om_num; 35.141 + ofdn_t om_next; 35.142 + ofdn_t om_free; /* Future site of a free list */ 35.143 + ofdn_t _om_pad; 35.144 + u64 om_mem[0] __attribute__((aligned(8))); 35.145 +}; 35.146 + 35.147 +#define NODE_PAT 0x0f01 35.148 +#define PROP_PAT 0x0f03 35.149 +#define IO_PAT 0x0f05 35.150 + 35.151 + 35.152 +size_t ofd_size(void *mem) 35.153 +{ 35.154 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.155 + size_t sz; 35.156 + 35.157 + sz = m->om_next * sizeof (u64) + sizeof(*m); 35.158 + return sz; 35.159 +} 35.160 + 35.161 +size_t ofd_space(void *mem) 35.162 +{ 35.163 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.164 + size_t sz; 35.165 + 35.166 + sz = m->om_num * sizeof (u64); 35.167 + return sz; 35.168 +} 35.169 + 35.170 + 35.171 +static int ofd_pathsplit_right(const char *s, int c, size_t max) 35.172 +{ 35.173 + int i = 0; 35.174 + 35.175 + if ( max == 0 ) { 35.176 + --max; 35.177 + } 35.178 + 35.179 + while ( *s != '\0' && *s != c && max != 0 ) { 35.180 + ++i; 35.181 + ++s; 35.182 + --max; 35.183 + } 35.184 + return i; 35.185 +} 35.186 + 35.187 +static int ofd_pathsplit_left(const char *p, int c, size_t len) 35.188 +{ 35.189 + const char *s; 35.190 + 35.191 + if ( len > 0 ) { 35.192 + /* move s to the end */ 35.193 + s = p + len - 1; 35.194 + 35.195 + /* len could include a null */ 35.196 + if ( *s == '\0' ) { 35.197 + --s; 35.198 + } 35.199 + while ( s >= p ) { 35.200 + if ( *s == c ) { 35.201 + ++s; 35.202 + break; 35.203 + } 35.204 + --s; 35.205 + } 35.206 + if ( s < p ) { 35.207 + return 0; 35.208 + } 35.209 + return (s - p); 35.210 + } 35.211 + return 0; 35.212 +} 35.213 + 35.214 +void *ofd_create(void *mem, size_t sz) 35.215 +{ 35.216 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.217 + struct ofd_node *n; 35.218 + size_t sum; 35.219 + ofdn_t cells; 35.220 + 35.221 + if ( sz < (sizeof (*n) * 4) ) { 35.222 + return NULL; 35.223 + } 35.224 + 35.225 + memset(mem, 0, sz); 35.226 + 35.227 + m->om_num = (sz - sizeof(*m)) / sizeof (u64); 35.228 + 35.229 + /* skip the first cell */ 35.230 + m->om_next = OFD_ROOT; 35.231 + n = (struct ofd_node *)&m->om_mem[m->om_next]; 35.232 + n->on_ima = NODE_PAT; 35.233 + n->on_pathlen = 2; 35.234 + n->on_last = 1; 35.235 + n->on_path[0] = '/'; 35.236 + n->on_path[1] = '\0'; 35.237 + 35.238 + sum = sizeof (*n) + 2; /* Don't forget the path */ 35.239 + cells = (sum + sizeof (m->om_mem[0]) - 1) / sizeof (m->om_mem[0]); 35.240 + m->om_next += cells; 35.241 + 35.242 + return m; 35.243 +} 35.244 + 35.245 +static struct ofd_node *ofd_node_get(struct ofd_mem *m, ofdn_t n) 35.246 +{ 35.247 + if ( n < m->om_next ) { 35.248 + struct ofd_node *r; 35.249 + 35.250 + r = (struct ofd_node *)&m->om_mem[n]; 35.251 + if ( r->on_ima == NODE_PAT ) { 35.252 + return r; 35.253 + } 35.254 + } 35.255 + return NULL; 35.256 +} 35.257 + 35.258 +ofdn_t ofd_node_parent(void *mem, ofdn_t n) 35.259 +{ 35.260 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.261 + struct ofd_node *r = ofd_node_get(m, n); 35.262 + 35.263 + if ( r == NULL) return 0; 35.264 + return r->on_parent; 35.265 +} 35.266 + 35.267 +ofdn_t ofd_node_peer(void *mem, ofdn_t n) 35.268 +{ 35.269 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.270 + struct ofd_node *r; 35.271 + 35.272 + if ( n == 0 ) { 35.273 + return OFD_ROOT; 35.274 + } 35.275 + 35.276 + r = ofd_node_get(m, n); 35.277 + if ( r == NULL) return 0; 35.278 + return r->on_peer; 35.279 +} 35.280 + 35.281 +const char *ofd_node_path(void *mem, ofdn_t n) 35.282 +{ 35.283 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.284 + struct ofd_node *r = ofd_node_get(m, n); 35.285 + 35.286 + if ( r == NULL) return NULL; 35.287 + return r->on_path; 35.288 +} 35.289 + 35.290 +static ofdn_t ofd_node_prop(void *mem, ofdn_t n) 35.291 +{ 35.292 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.293 + struct ofd_node *r = ofd_node_get(m, n); 35.294 + 35.295 + if ( r == NULL) return 0; 35.296 + return r->on_prop; 35.297 +} 35.298 + 35.299 +ofdn_t ofd_node_child(void *mem, ofdn_t p) 35.300 +{ 35.301 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.302 + struct ofd_node *r = ofd_node_get(m, p); 35.303 + 35.304 + if ( r == NULL) return 0; 35.305 + return r->on_child; 35.306 +} 35.307 + 35.308 +int ofd_node_to_path(void *mem, ofdn_t p, void *buf, size_t sz) 35.309 +{ 35.310 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.311 + struct ofd_node *r = ofd_node_get(m, p); 35.312 + 35.313 + if ( sz > r->on_pathlen ) { 35.314 + sz = r->on_pathlen; 35.315 + } 35.316 + 35.317 + memcpy(buf, r->on_path, sz); 35.318 + 35.319 + if ( r == NULL) return -1; 35.320 + return r->on_pathlen; 35.321 +} 35.322 + 35.323 +static int ofd_check(void *p, size_t l) 35.324 +{ 35.325 + int i; 35.326 + u64 *v = (u64 *)p; 35.327 + 35.328 + for ( i = 0; i < l; i++ ) { 35.329 + if ( v[i] != 0ULL ) { 35.330 + return 0; 35.331 + } 35.332 + } 35.333 + return 1; 35.334 +} 35.335 + 35.336 + 35.337 + 35.338 +static ofdn_t ofd_node_create( 35.339 + struct ofd_mem *m, const char *path, size_t pathlen) 35.340 +{ 35.341 + struct ofd_node *n; 35.342 + ofdn_t pos; 35.343 + size_t sum = pathlen + 1 + sizeof (*n); /* add trailing zero to path */ 35.344 + ofdn_t cells = (sum + sizeof(m->om_mem[0]) - 1) / sizeof(m->om_mem[0]); 35.345 + 35.346 + if ( m->om_next + cells >= m->om_num ) { 35.347 + return 0; 35.348 + } 35.349 + 35.350 + pos = m->om_next; 35.351 + 35.352 + assert(ofd_check(&m->om_mem[pos], cells)); /* non-zero */ 35.353 + m->om_next += cells; 35.354 + 35.355 + n = (struct ofd_node *)&m->om_mem[pos]; 35.356 + assert(n->on_ima == 0); /* new node not empty */ 35.357 + 35.358 + n->on_ima = NODE_PAT; 35.359 + n->on_peer = 0; 35.360 + n->on_child = 0; 35.361 + n->on_io = 0; 35.362 + n->on_pathlen = pathlen; 35.363 + n->on_last = ofd_pathsplit_left(path, '/', pathlen); 35.364 + strncpy(n->on_path, path, pathlen); 35.365 + n->on_path[n->on_pathlen] = 0; 35.366 + 35.367 + return pos; 35.368 +} 35.369 + 35.370 +/* prunes a node and all its children simply by wasting memory and 35.371 + * unlinking it from the tree */ 35.372 +int ofd_node_prune(void *mem, ofdn_t node) 35.373 +{ 35.374 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.375 + struct ofd_node *n; 35.376 + struct ofd_node *p; 35.377 + 35.378 + n = ofd_node_get(m, node); 35.379 + if (n == NULL) return -1; 35.380 + 35.381 + p = ofd_node_get(m, n->on_parent); 35.382 + assert(p != NULL); 35.383 + 35.384 + if ( p->on_child == node ) { 35.385 + /* easy case */ 35.386 + p->on_child = n->on_peer; 35.387 + } else { 35.388 + struct ofd_node *s; 35.389 + 35.390 + s = ofd_node_get(m, p->on_child); 35.391 + assert(s != NULL); 35.392 + while ( s->on_peer != node ) { 35.393 + s = ofd_node_get(m, s->on_peer); 35.394 + assert(s != NULL); 35.395 + } 35.396 + s->on_peer = n->on_peer; 35.397 + } 35.398 + return 1; 35.399 +} 35.400 + 35.401 +ofdn_t ofd_prune_path(void *m, const char *path) 35.402 +{ 35.403 + ofdn_t n; 35.404 + int rc = -1; 35.405 + while ((n = ofd_node_find(m, path)) > 0) { 35.406 + rc = ofd_node_prune(m, n); 35.407 + } 35.408 + 35.409 + return rc; 35.410 +} 35.411 + 35.412 +ofdn_t ofd_node_child_create( 35.413 + void *mem, ofdn_t parent, const char *path, size_t pathlen) 35.414 +{ 35.415 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.416 + struct ofd_node *p; 35.417 + struct ofd_node *n; 35.418 + ofdn_t pos; 35.419 + 35.420 + p = ofd_node_get(m, parent); 35.421 + if (p == NULL) return 0; 35.422 + 35.423 + pos = ofd_node_create(m, path, pathlen); 35.424 + n = ofd_node_get(m, pos); 35.425 + assert(n != NULL); 35.426 + 35.427 + assert(p->on_child == 0); /* child exists */ 35.428 + if ( p->on_child == 0 ) { 35.429 + p->on_child = pos; 35.430 + n->on_parent = parent; 35.431 + } else { 35.432 + pos = 0; 35.433 + } 35.434 + 35.435 + return pos; 35.436 +} 35.437 + 35.438 +ofdn_t ofd_node_peer_create( 35.439 + void *mem, ofdn_t sibling, const char *path, size_t pathlen) 35.440 +{ 35.441 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.442 + struct ofd_node *s; 35.443 + struct ofd_node *n; 35.444 + ofdn_t pos; 35.445 + 35.446 + s = ofd_node_get(m, sibling); 35.447 + if (s == NULL) return 0; 35.448 + 35.449 + pos = ofd_node_create(m, path, pathlen); 35.450 + n = ofd_node_get(m, pos); 35.451 + assert(n != NULL); 35.452 + 35.453 + if ( s->on_peer == 0 ) { 35.454 + s->on_peer = pos; 35.455 + n->on_parent = s->on_parent; 35.456 + } else { 35.457 + assert(0); /* peer exists */ 35.458 + pos = 0; 35.459 + } 35.460 + return pos; 35.461 +} 35.462 + 35.463 +static ofdn_t ofd_node_peer_last(void *mem, ofdn_t c) 35.464 +{ 35.465 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.466 + struct ofd_node *n; 35.467 + 35.468 + n = ofd_node_get(m, c); 35.469 + if (n == NULL) return 0; 35.470 + 35.471 + while ( n->on_peer > 0 ) { 35.472 + c = n->on_peer; 35.473 + n = ofd_node_get(m, c); 35.474 + assert(n != NULL); 35.475 + } 35.476 + 35.477 + return c; 35.478 +} 35.479 + 35.480 +static ofdn_t ofd_node_walk(struct ofd_mem *m, ofdn_t p, const char *s) 35.481 +{ 35.482 + struct ofd_node *np; 35.483 + ofdn_t n; 35.484 + ofdn_t r; 35.485 + 35.486 + if ( *s == '/' ) { 35.487 + ++s; 35.488 + if ( *s == '\0' ) { 35.489 + assert(0); /* ends in / */ 35.490 + return 0; 35.491 + } 35.492 + } 35.493 + 35.494 + np = ofd_node_get(m, p); 35.495 + if (np == NULL) return 0; 35.496 + 35.497 + r = p; 35.498 + do { 35.499 + int last = np->on_last; 35.500 + size_t lsz = np->on_pathlen - last; 35.501 + size_t sz; 35.502 + 35.503 + sz = ofd_pathsplit_right(s, '/', 0); 35.504 + 35.505 + if ( lsz > 0 && strncmp(s, &np->on_path[last], sz) == 0 ) { 35.506 + if ( s[sz] == '\0' ) { 35.507 + return r; 35.508 + } 35.509 + /* there is more to the path */ 35.510 + n = ofd_node_child(m, p); 35.511 + if ( n != 0 ) { 35.512 + r = ofd_node_walk(m, n, &s[sz]); 35.513 + return r; 35.514 + } 35.515 + /* there are no children */ 35.516 + return 0; 35.517 + } 35.518 + } while ( 0 ); 35.519 + 35.520 + /* 35.521 + * we know that usually we are only serching for top level peers 35.522 + * so we do peers first peer 35.523 + */ 35.524 + n = ofd_node_peer(m, p); 35.525 + if ( n > 0 ) { 35.526 + r = ofd_node_walk(m, n, s); 35.527 + } else { 35.528 + r = 0; 35.529 + } 35.530 + 35.531 + return r; 35.532 +} 35.533 + 35.534 + 35.535 +ofdn_t ofd_node_find(void *mem, const char *devspec) 35.536 +{ 35.537 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.538 + ofdn_t n = OFD_ROOT; 35.539 + const char *s = devspec; 35.540 + size_t sz; 35.541 + 35.542 + if ( s == NULL || s[0] == '\0' ) { 35.543 + return OFD_ROOT; 35.544 + } 35.545 + 35.546 + if ( s[0] != '/' ) { 35.547 + size_t asz; 35.548 + 35.549 + /* get the component length */ 35.550 + sz = ofd_pathsplit_right(s, '/', 0); 35.551 + 35.552 + /* check for an alias */ 35.553 + asz = ofd_pathsplit_right(s, ':', sz); 35.554 + 35.555 + if ( s[asz] == ':' ) { 35.556 + /* 35.557 + * s points to an alias and &s[sz] points to the alias 35.558 + * args. 35.559 + */ 35.560 + assert(0); /* aliases no supported */ 35.561 + return 0; 35.562 + } 35.563 + } else if ( s[1] == '\0' ) { 35.564 + return n; 35.565 + } 35.566 + 35.567 + n = ofd_node_child(m, n); 35.568 + if ( n == 0 ) { 35.569 + return 0; 35.570 + } 35.571 + 35.572 + return ofd_node_walk(m, n, s); 35.573 +} 35.574 + 35.575 + 35.576 +static struct ofd_prop *ofd_prop_get(struct ofd_mem *m, ofdn_t p) 35.577 +{ 35.578 + if ( p < m->om_next ) { 35.579 + struct ofd_prop *r; 35.580 + 35.581 + r = (struct ofd_prop *)&m->om_mem[p]; 35.582 + if ( r->op_ima == PROP_PAT ) { 35.583 + return r; 35.584 + } 35.585 + assert(r->op_ima == PROP_PAT); /* bad object */ 35.586 + } 35.587 + return NULL; 35.588 +} 35.589 + 35.590 +static ofdn_t ofd_prop_create( 35.591 + struct ofd_mem *m, 35.592 + ofdn_t node, 35.593 + const char *name, 35.594 + const void *src, 35.595 + size_t sz) 35.596 +{ 35.597 + struct ofd_node *n; 35.598 + struct ofd_prop *p; 35.599 + size_t len = strlen(name) + 1; 35.600 + size_t sum = sizeof (*p) + sz + len; 35.601 + ofdn_t cells; 35.602 + char *dst; 35.603 + ofdn_t pos; 35.604 + 35.605 + cells = (sum + sizeof (m->om_mem[0]) - 1) / sizeof (m->om_mem[0]); 35.606 + 35.607 + if ( m->om_next + cells >= m->om_num ) { 35.608 + return 0; 35.609 + } 35.610 + 35.611 + /* actual data structure */ 35.612 + pos = m->om_next; 35.613 + assert(ofd_check(&m->om_mem[pos], cells)); /* non-zero */ 35.614 + 35.615 + p = (struct ofd_prop *)&m->om_mem[pos]; 35.616 + m->om_next += cells; 35.617 + 35.618 + assert(p->op_ima == 0); /* new node not empty */ 35.619 + p->op_ima = PROP_PAT; 35.620 + p->op_next = 0; 35.621 + p->op_objsz = sz; 35.622 + p->op_namesz = len; 35.623 + 35.624 + /* the rest of the data */ 35.625 + dst = p->op_data; 35.626 + 35.627 + /* zero what will be the pad, cheap and cannot hurt */ 35.628 + m->om_mem[m->om_next - 1] = 0; 35.629 + 35.630 + if ( sz > 0 ) { 35.631 + /* some props have no data, just a name */ 35.632 + memcpy(dst, src, sz); 35.633 + dst += sz; 35.634 + } 35.635 + 35.636 + memcpy(dst, name, len); 35.637 + 35.638 + /* now place it in the tree */ 35.639 + n = ofd_node_get(m, node); 35.640 + assert(n != NULL); 35.641 + 35.642 + if ( n->on_prop == 0 ) { 35.643 + n->on_prop = pos; 35.644 + } else { 35.645 + ofdn_t pn = n->on_prop; 35.646 + struct ofd_prop *nxt; 35.647 + 35.648 + for (;;) { 35.649 + nxt = ofd_prop_get(m, pn); 35.650 + if (nxt->op_next == 0) { 35.651 + nxt->op_next = pos; 35.652 + break; 35.653 + } 35.654 + pn = nxt->op_next; 35.655 + } 35.656 + } 35.657 + 35.658 + return pos; 35.659 +} 35.660 + 35.661 +void ofd_prop_remove(void *mem, ofdn_t node, ofdn_t prop) 35.662 +{ 35.663 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.664 + struct ofd_node *n = ofd_node_get(m, node); 35.665 + struct ofd_prop *p = ofd_prop_get(m, prop); 35.666 + 35.667 + if (n == NULL) return; 35.668 + if (p == NULL) return; 35.669 + 35.670 + if ( n->on_prop == prop ) { 35.671 + n->on_prop = p->op_next; 35.672 + } else { 35.673 + ofdn_t pn = n->on_prop; 35.674 + struct ofd_prop *nxt; 35.675 + 35.676 + for ( ; ; ) { 35.677 + nxt = ofd_prop_get(m, pn); 35.678 + if ( nxt->op_next == prop ) { 35.679 + nxt->op_next = p->op_next; 35.680 + break; 35.681 + } 35.682 + pn = nxt->op_next; 35.683 + } 35.684 + } 35.685 + return; 35.686 +} 35.687 + 35.688 +ofdn_t ofd_prop_find(void *mem, ofdn_t n, const char *name) 35.689 +{ 35.690 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.691 + ofdn_t p = ofd_node_prop(m, n); 35.692 + struct ofd_prop *r; 35.693 + char *s; 35.694 + size_t len; 35.695 + 35.696 + if ( name == NULL || *name == '\0' ) { 35.697 + return OFD_ROOT; 35.698 + } 35.699 + 35.700 + len = strlen(name) + 1; 35.701 + 35.702 + while ( p != 0 ) { 35.703 + r = ofd_prop_get(m, p); 35.704 + s = &r->op_data[r->op_objsz]; 35.705 + if ( len == r->op_namesz ) { 35.706 + if ( strncmp(name, s, r->op_namesz) == 0 ) { 35.707 + break; 35.708 + } 35.709 + } 35.710 + p = r->op_next; 35.711 + } 35.712 + return p; 35.713 +} 35.714 + 35.715 +static ofdn_t ofd_prop_next(struct ofd_mem *m, ofdn_t n, const char *prev) 35.716 +{ 35.717 + ofdn_t p; 35.718 + 35.719 + if ( prev == NULL || *prev == '\0' ) { 35.720 + /* give the first */ 35.721 + p = ofd_node_prop(m, n); 35.722 + } else { 35.723 + struct ofd_prop *r; 35.724 + 35.725 + /* look for the name */ 35.726 + p = ofd_prop_find(m, n, prev); 35.727 + if ( p != 0 ) { 35.728 + /* get the data for prev */ 35.729 + r = ofd_prop_get(m, p); 35.730 + 35.731 + /* now get next */ 35.732 + p = r->op_next; 35.733 + } else { 35.734 + p = -1; 35.735 + } 35.736 + } 35.737 + 35.738 + return p; 35.739 +} 35.740 + 35.741 +ofdn_t ofd_nextprop(void *mem, ofdn_t n, const char *prev, char *name) 35.742 +{ 35.743 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.744 + ofdn_t p = ofd_prop_next(m, n, prev); 35.745 + struct ofd_prop *r; 35.746 + char *s; 35.747 + 35.748 + if ( p > 0 ) { 35.749 + r = ofd_prop_get(m, p); 35.750 + s = &r->op_data[r->op_objsz]; 35.751 + memcpy(name, s, r->op_namesz); 35.752 + } 35.753 + 35.754 + return p; 35.755 +} 35.756 + 35.757 +/* 35.758 + * It is valid to call with NULL pointers, in case you want only one 35.759 + * cell size. 35.760 + */ 35.761 +int ofd_getcells(void* mem, ofdn_t n, u32* addr_cells, u32* size_cells) 35.762 +{ 35.763 + if ( addr_cells != NULL ) *addr_cells = 0; 35.764 + if ( size_cells != NULL ) *size_cells = 0; 35.765 + 35.766 +retry: 35.767 + if ( addr_cells != NULL && *addr_cells == 0 ) { 35.768 + ofd_getprop(mem, n, "#address-cells", 35.769 + addr_cells, sizeof(u32)); 35.770 + } 35.771 + 35.772 + if ( size_cells != NULL && *size_cells == 0 ) { 35.773 + ofd_getprop(mem, n, "#size-cells", size_cells, sizeof(u32)); 35.774 + } 35.775 + 35.776 + if ( ( size_cells != NULL && *size_cells == 0 ) 35.777 + || ( addr_cells != NULL && *addr_cells == 0 ) ) { 35.778 + if ( n != OFD_ROOT ) { 35.779 + n = ofd_node_parent(mem, n); 35.780 + goto retry; 35.781 + } 35.782 + return -1; 35.783 + } 35.784 + 35.785 + return 1; 35.786 +} 35.787 + 35.788 +int ofd_getprop(void *mem, ofdn_t n, const char *name, void *buf, size_t sz) 35.789 +{ 35.790 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.791 + ofdn_t p = ofd_prop_find(m, n, name); 35.792 + struct ofd_prop *r; 35.793 + 35.794 + if ( p == 0 ) { 35.795 + return -1; 35.796 + } 35.797 + 35.798 + r = ofd_prop_get(m, p); 35.799 + 35.800 + if ( sz > r->op_objsz ) { 35.801 + sz = r->op_objsz; 35.802 + } 35.803 + memcpy(buf, r->op_data, sz); 35.804 + 35.805 + return r->op_objsz; 35.806 +} 35.807 + 35.808 +int ofd_getproplen(void *mem, ofdn_t n, const char *name) 35.809 +{ 35.810 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.811 + ofdn_t p = ofd_prop_find(m, n, name); 35.812 + struct ofd_prop *r; 35.813 + 35.814 + if ( p == 0 ) { 35.815 + return -1; 35.816 + } 35.817 + 35.818 + r = ofd_prop_get(m, p); 35.819 + 35.820 + return r->op_objsz; 35.821 +} 35.822 + 35.823 +static ofdn_t ofd_prop_set( 35.824 + void *mem, ofdn_t n, const char *name, const void *src, size_t sz) 35.825 +{ 35.826 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.827 + ofdn_t p = ofd_prop_find(m, n, name); 35.828 + struct ofd_prop *r; 35.829 + char *dst; 35.830 + 35.831 + r = ofd_prop_get(m, p); 35.832 + 35.833 + if ( sz <= r->op_objsz ) { 35.834 + /* we can reuse */ 35.835 + memcpy(r->op_data, src, sz); 35.836 + if ( sz < r->op_objsz ) { 35.837 + /* need to move name */ 35.838 + dst = r->op_data + sz; 35.839 + /* 35.840 + * use the name arg size we may have overlap with the 35.841 + * original 35.842 + */ 35.843 + memcpy(dst, name, r->op_namesz); 35.844 + r->op_objsz = sz; 35.845 + } 35.846 + } else { 35.847 + /* 35.848 + * Sadly, we remove from the list, wasting the space and then 35.849 + * we can creat a new one 35.850 + */ 35.851 + ofd_prop_remove(m, n, p); 35.852 + p = ofd_prop_create(mem, n, name, src, sz); 35.853 + } 35.854 + 35.855 + return p; 35.856 +} 35.857 + 35.858 +int ofd_setprop( 35.859 + void *mem, ofdn_t n, const char *name, const void *buf, size_t sz) 35.860 +{ 35.861 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.862 + ofdn_t r; 35.863 + 35.864 + r = ofd_prop_find(m, n, name); 35.865 + if ( r == 0 ) { 35.866 + r = ofd_prop_create(mem, n, name, buf, sz); 35.867 + } else { 35.868 + r = ofd_prop_set(mem, n, name, buf, sz); 35.869 + } 35.870 + 35.871 + if ( r > 0 ) { 35.872 + struct ofd_prop *pp = ofd_prop_get(m, r); 35.873 + return pp->op_objsz; 35.874 + } 35.875 + 35.876 + return OF_FAILURE; 35.877 +} 35.878 + 35.879 + 35.880 +static ofdn_t ofd_find_by_prop( 35.881 + struct ofd_mem *m, 35.882 + ofdn_t head, 35.883 + ofdn_t *prev_p, 35.884 + ofdn_t n, 35.885 + const char *name, 35.886 + const void *val, 35.887 + size_t sz) 35.888 +{ 35.889 + struct ofd_node *np; 35.890 + struct ofd_prop *pp; 35.891 + ofdn_t p; 35.892 + 35.893 +retry: 35.894 + p = ofd_prop_find(m, n, name); 35.895 + 35.896 + if ( p > 0 ) { 35.897 + int match = 0; 35.898 + 35.899 + /* a property exists by that name */ 35.900 + if ( val == NULL ) { 35.901 + match = 1; 35.902 + } else { 35.903 + /* need to compare values */ 35.904 + pp = ofd_prop_get(m, p); 35.905 + if ( sz == pp->op_objsz 35.906 + && memcmp(pp->op_data, val, sz) == 0 ) { 35.907 + match = 1; 35.908 + } 35.909 + } 35.910 + if ( match == 1 ) { 35.911 + if ( *prev_p >= 0 ) { 35.912 + np = ofd_node_get(m, *prev_p); 35.913 + np->on_next = n; 35.914 + } else { 35.915 + head = n; 35.916 + } 35.917 + np = ofd_node_get(m, n); 35.918 + np->on_prev = *prev_p; 35.919 + np->on_next = -1; 35.920 + *prev_p = n; 35.921 + } 35.922 + } 35.923 + 35.924 + p = ofd_node_child(m, n); 35.925 + if ( p > 0 ) { 35.926 + head = ofd_find_by_prop(m, head, prev_p, p, name, val, sz); 35.927 + } 35.928 + 35.929 + p = ofd_node_peer(m, n); 35.930 + if ( p > 0 ) { 35.931 + n = p; 35.932 + goto retry; 35.933 + } 35.934 + 35.935 + return head; 35.936 +} 35.937 + 35.938 +ofdn_t ofd_node_find_by_prop( 35.939 + void *mem, 35.940 + ofdn_t n, 35.941 + const char *name, 35.942 + const void *val, 35.943 + size_t sz) 35.944 +{ 35.945 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.946 + 35.947 + if ( n <= 0 ) { 35.948 + n = OFD_ROOT; 35.949 + } 35.950 + 35.951 + ofdn_t prev = -1; 35.952 + return ofd_find_by_prop(m, -1, &prev, n, name, val, sz); 35.953 +} 35.954 + 35.955 +ofdn_t ofd_node_find_next(void *mem, ofdn_t n) 35.956 +{ 35.957 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.958 + struct ofd_node *np; 35.959 + 35.960 + np = ofd_node_get(m, n); 35.961 + 35.962 + if (np == NULL) return 0; 35.963 + return np->on_next; 35.964 +} 35.965 + 35.966 +ofdn_t ofd_node_find_prev(void *mem, ofdn_t n) 35.967 +{ 35.968 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.969 + struct ofd_node *np; 35.970 + 35.971 + np = ofd_node_get(m, n); 35.972 + if (np == NULL) return 0; 35.973 + 35.974 + return np->on_prev; 35.975 +} 35.976 + 35.977 +ofdn_t ofd_io_create(void *mem, ofdn_t node, u64 open) 35.978 +{ 35.979 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.980 + struct ofd_node *n; 35.981 + struct ofd_io *i; 35.982 + ofdn_t pos; 35.983 + ofdn_t cells; 35.984 + 35.985 + cells = (sizeof (*i) + sizeof (m->om_mem[0]) - 1) / sizeof(m->om_mem[0]); 35.986 + 35.987 + n = ofd_node_get(m, node); 35.988 + if ( n == NULL ) return 0; 35.989 + 35.990 + if ( m->om_next + cells >= m->om_num ) { 35.991 + return 0; 35.992 + } 35.993 + 35.994 + pos = m->om_next; 35.995 + assert(ofd_check(&m->om_mem[pos], cells)); /* non-zero */ 35.996 + 35.997 + m->om_next += cells; 35.998 + 35.999 + i = (struct ofd_io *)&m->om_mem[pos]; 35.1000 + assert(i->oi_ima == 0); /* new node not empty */ 35.1001 + 35.1002 + i->oi_ima = IO_PAT; 35.1003 + i->oi_node = node; 35.1004 + i->oi_open = open; 35.1005 + 35.1006 + n->on_io = pos; 35.1007 + 35.1008 + return pos; 35.1009 +} 35.1010 + 35.1011 +static struct ofd_io *ofd_io_get(struct ofd_mem *m, ofdn_t i) 35.1012 +{ 35.1013 + if ( i < m->om_next ) { 35.1014 + struct ofd_io *r; 35.1015 + 35.1016 + r = (struct ofd_io *)&m->om_mem[i]; 35.1017 + if ( r->oi_ima == IO_PAT ) { 35.1018 + return r; 35.1019 + } 35.1020 + assert(r->oi_ima == IO_PAT); /* bad object */ 35.1021 + } 35.1022 + 35.1023 + return NULL; 35.1024 +} 35.1025 + 35.1026 +ofdn_t ofd_node_io(void *mem, ofdn_t n) 35.1027 +{ 35.1028 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.1029 + struct ofd_node *r = ofd_node_get(m, n); 35.1030 + 35.1031 + if (r == NULL) return 0; 35.1032 + return r->on_io; 35.1033 +} 35.1034 + 35.1035 +uint ofd_io_open(void *mem, ofdn_t n) 35.1036 +{ 35.1037 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.1038 + struct ofd_io *r = ofd_io_get(m, n); 35.1039 + 35.1040 + if (r == NULL) return 0; 35.1041 + return r->oi_open; 35.1042 +} 35.1043 + 35.1044 +void ofd_io_close(void *mem, ofdn_t n) 35.1045 +{ 35.1046 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.1047 + struct ofd_io *o = ofd_io_get(m, n); 35.1048 + struct ofd_node *r = ofd_node_get(m, o->oi_node); 35.1049 + 35.1050 + assert(o != NULL); 35.1051 + assert(r != NULL); 35.1052 + o->oi_open = 0; 35.1053 + r->on_io = 0; 35.1054 +} 35.1055 + 35.1056 +ofdn_t ofd_node_add(void *m, ofdn_t p, const char *path, size_t sz) 35.1057 +{ 35.1058 + ofdn_t n; 35.1059 + 35.1060 + n = ofd_node_child(m, p); 35.1061 + if ( n > 0 ) { 35.1062 + n = ofd_node_peer_last(m, n); 35.1063 + if ( n > 0 ) { 35.1064 + n = ofd_node_peer_create(m, n, path, sz); 35.1065 + } 35.1066 + } else { 35.1067 + n = ofd_node_child_create(m, p, path, sz); 35.1068 + } 35.1069 + 35.1070 + return n; 35.1071 +} 35.1072 + 35.1073 +ofdn_t ofd_prop_add( 35.1074 + void *mem, 35.1075 + ofdn_t n, 35.1076 + const char *name, 35.1077 + const void *buf, 35.1078 + size_t sz) 35.1079 +{ 35.1080 + struct ofd_mem *m = (struct ofd_mem *)mem; 35.1081 + ofdn_t r; 35.1082 + 35.1083 + r = ofd_prop_find(m, n, name); 35.1084 + if ( r == 0 ) { 35.1085 + r = ofd_prop_create(mem, n, name, buf, sz); 35.1086 + } else { 35.1087 + r = ofd_prop_set(mem, n, name, buf, sz); 35.1088 + } 35.1089 + 35.1090 + return r; 35.1091 +}
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 36.2 +++ b/xen/arch/powerpc/of-devtree.h Fri Jul 14 10:47:50 2006 +0100 36.3 @@ -0,0 +1,139 @@ 36.4 +/* 36.5 + * This program is free software; you can redistribute it and/or modify 36.6 + * it under the terms of the GNU General Public License as published by 36.7 + * the Free Software Foundation; either version 2 of the License, or 36.8 + * (at your option) any later version. 36.9 + * 36.10 + * This program is distributed in the hope that it will be useful, 36.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 36.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 36.13 + * GNU General Public License for more details. 36.14 + * 36.15 + * You should have received a copy of the GNU General Public License 36.16 + * along with this program; if not, write to the Free Software 36.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 36.18 + * 36.19 + * Copyright (C) IBM Corp. 2005 36.20 + * 36.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 36.22 + */ 36.23 + 36.24 +#ifndef _OF_DEVTREE_H 36.25 +#define _OF_DEVTREE_H 36.26 + 36.27 +#include <xen/types.h> 36.28 +#include <public/xen.h> 36.29 + 36.30 +enum { 36.31 + OF_FAILURE = -1, 36.32 + OF_SUCCESS = 0, 36.33 +}; 36.34 + 36.35 +union of_pci_hi { 36.36 + u32 word; 36.37 + struct { 36.38 + u32 opa_n: 1; /* relocatable */ 36.39 + u32 opa_p: 1; /* prefetchable */ 36.40 + u32 opa_t: 1; /* aliased */ 36.41 + u32 _opa_res: 3; 36.42 + u32 opa: 2; /* space code */ 36.43 + u32 opa_b: 8; /* bus number */ 36.44 + u32 opa_d: 5; /* device number */ 36.45 + u32 opa_f: 3; /* function number */ 36.46 + u32 opa_r: 8; /* register number */ 36.47 + } bits; 36.48 +}; 36.49 + 36.50 +struct of_pci_addr { 36.51 + union of_pci_hi opa_hi; 36.52 + u32 opa_mid; 36.53 + u32 opa_lo; 36.54 +}; 36.55 + 36.56 +struct of_pci_range32 { 36.57 + struct of_pci_addr opr_addr; 36.58 + u32 opr_phys; 36.59 + u32 opr_size; 36.60 +}; 36.61 + 36.62 +struct of_pci_range64 { 36.63 + struct of_pci_addr opr_addr; 36.64 + u32 opr_phys_hi; 36.65 + u32 opr_phys_lo; 36.66 + u32 opr_size_hi; 36.67 + u32 opr_size_lo; 36.68 +}; 36.69 + 36.70 +struct of_pci_addr_range64 { 36.71 + struct of_pci_addr opr_addr; 36.72 + u32 opr_size_hi; 36.73 + u32 opr_size_lo; 36.74 +}; 36.75 + 36.76 +struct reg_property32 { 36.77 + u32 address; 36.78 + u32 size; 36.79 +}; 36.80 + 36.81 +typedef s32 ofdn_t; 36.82 + 36.83 +#define OFD_ROOT 1 36.84 +#define OFD_DUMP_NAMES 0x1 36.85 +#define OFD_DUMP_VALUES 0x2 36.86 +#define OFD_DUMP_ALL (OFD_DUMP_VALUES|OFD_DUMP_NAMES) 36.87 + 36.88 +extern void *ofd_create(void *mem, size_t sz); 36.89 +extern ofdn_t ofd_node_parent(void *mem, ofdn_t n); 36.90 +extern ofdn_t ofd_node_peer(void *mem, ofdn_t n); 36.91 +extern ofdn_t ofd_node_child(void *mem, ofdn_t p); 36.92 +extern const char *ofd_node_path(void *mem, ofdn_t p); 36.93 +extern int ofd_node_to_path(void *mem, ofdn_t p, void *buf, size_t sz); 36.94 +extern ofdn_t ofd_node_child_create(void *mem, ofdn_t parent, 36.95 + const char *path, size_t pathlen); 36.96 +extern ofdn_t ofd_node_peer_create(void *mem, ofdn_t sibling, 36.97 + const char *path, size_t pathlen); 36.98 +extern ofdn_t ofd_node_find(void *mem, const char *devspec); 36.99 +extern ofdn_t ofd_node_add(void *m, ofdn_t n, const char *path, size_t sz); 36.100 +extern int ofd_node_prune(void *m, ofdn_t n); 36.101 +extern int ofd_prune_path(void *m, const char *path); 36.102 +extern ofdn_t ofd_node_io(void *mem, ofdn_t n); 36.103 + 36.104 +extern ofdn_t ofd_nextprop(void *mem, ofdn_t n, const char *prev, char *name); 36.105 +extern ofdn_t ofd_prop_find(void *mem, ofdn_t n, const char *name); 36.106 +extern int ofd_getprop(void *mem, ofdn_t n, const char *name, 36.107 + void *buf, size_t sz); 36.108 +extern int ofd_getproplen(void *mem, ofdn_t n, const char *name); 36.109 + 36.110 +extern int ofd_setprop(void *mem, ofdn_t n, const char *name, 36.111 + const void *buf, size_t sz); 36.112 +extern void ofd_prop_remove(void *mem, ofdn_t node, ofdn_t prop); 36.113 +extern ofdn_t ofd_prop_add(void *mem, ofdn_t n, const char *name, 36.114 + const void *buf, size_t sz); 36.115 +extern ofdn_t ofd_io_create(void *m, ofdn_t node, u64 open); 36.116 +extern u32 ofd_io_open(void *mem, ofdn_t n); 36.117 +extern void ofd_io_close(void *mem, ofdn_t n); 36.118 + 36.119 + 36.120 +typedef void (*walk_fn)(void *m, ofdn_t p, int arg); 36.121 +extern void ofd_dump_props(void *m, ofdn_t p, int dump); 36.122 + 36.123 +extern void ofd_walk(void *m, ofdn_t p, walk_fn fn, int arg); 36.124 + 36.125 + 36.126 +/* Recursively look up #address_cells and #size_cells properties */ 36.127 +extern int ofd_getcells(void *mem, ofdn_t n, 36.128 + u32 *addr_cells, u32 *size_cells); 36.129 + 36.130 +extern size_t ofd_size(void *mem); 36.131 +extern size_t ofd_space(void *mem); 36.132 + 36.133 +extern void ofd_prop_print(const char *head, const char *path, 36.134 + const char *name, const char *prop, size_t sz); 36.135 + 36.136 +extern ofdn_t ofd_node_find_by_prop(void *mem, ofdn_t n, const char *name, 36.137 + const void *val, size_t sz); 36.138 +extern ofdn_t ofd_node_find_next(void *mem, ofdn_t n); 36.139 +extern ofdn_t ofd_node_find_prev(void *mem, ofdn_t n); 36.140 +extern void ofd_init(int (*write)(const char *, size_t len)); 36.141 + 36.142 +#endif /* _OF_DEVTREE_H */
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 37.2 +++ b/xen/arch/powerpc/of-devwalk.c Fri Jul 14 10:47:50 2006 +0100 37.3 @@ -0,0 +1,135 @@ 37.4 +/* 37.5 + * This program is free software; you can redistribute it and/or modify 37.6 + * it under the terms of the GNU General Public License as published by 37.7 + * the Free Software Foundation; either version 2 of the License, or 37.8 + * (at your option) any later version. 37.9 + * 37.10 + * This program is distributed in the hope that it will be useful, 37.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 37.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 37.13 + * GNU General Public License for more details. 37.14 + * 37.15 + * You should have received a copy of the GNU General Public License 37.16 + * along with this program; if not, write to the Free Software 37.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 37.18 + * 37.19 + * Copyright (C) IBM Corp. 2005 37.20 + * 37.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 37.22 + */ 37.23 + 37.24 +#include <xen/config.h> 37.25 +#include <xen/init.h> 37.26 +#include <xen/lib.h> 37.27 +#include <xen/ctype.h> 37.28 +#include <xen/kernel.h> 37.29 +#include "of-devtree.h" 37.30 + 37.31 +void ofd_prop_print( 37.32 + const char *head, 37.33 + const char *path, 37.34 + const char *name, 37.35 + const char *prop, 37.36 + size_t sz) 37.37 +{ 37.38 + if ( path[0] == '/' && path[1] == '\0' ) { 37.39 + path = ""; 37.40 + } 37.41 + printf("%s: %s/%s: 0x%lx\n", head, path, name, sz); 37.42 + 37.43 +#define DEBUG_PROP 37.44 +#ifdef DEBUG_PROP 37.45 + int i; 37.46 + int isstr = sz; 37.47 + const char *b = prop; 37.48 + 37.49 + for ( i = 0; i < sz; i++ ) { 37.50 + /* see if there is any non printable characters */ 37.51 + if ( !isprint(b[i]) ) { 37.52 + /* not printable */ 37.53 + if (b[i] != '\0' || (i + 1) != sz) { 37.54 + /* not the end of string */ 37.55 + isstr = 0; 37.56 + break; 37.57 + } 37.58 + } 37.59 + } 37.60 + 37.61 + if ( isstr > 0 ) { 37.62 + printf("%s: \t%s\n", head, b); 37.63 + } else if ( sz != 0 ) { 37.64 + printf("%s: \t0x", head); 37.65 + 37.66 + for ( i = 0; i < sz; i++ ) { 37.67 + if ( (i % 4) == 0 && i != 0 ) { 37.68 + if ( (i % 16) == 0 && i != 0 ) { 37.69 + printf("\n%s: \t0x", head); 37.70 + } else { 37.71 + printf(" 0x"); 37.72 + } 37.73 + } 37.74 + if (b[i] < 0x10) { 37.75 + printf("0"); 37.76 + } 37.77 + printf("%x", b[i]); 37.78 + } 37.79 + printf("\n"); 37.80 + } 37.81 +#else 37.82 + (void)prop; 37.83 +#endif 37.84 +} 37.85 + 37.86 +void ofd_dump_props(void *mem, ofdn_t n, int dump) 37.87 +{ 37.88 + ofdn_t p; 37.89 + char name[128]; 37.90 + char prop[256] __attribute__ ((aligned (__alignof__ (u64)))); 37.91 + int sz; 37.92 + const char *path; 37.93 + 37.94 + if ( n == OFD_ROOT ) { 37.95 + path = ""; 37.96 + } else { 37.97 + path = ofd_node_path(mem, n); 37.98 + } 37.99 + 37.100 + if (dump & OFD_DUMP_NAMES) { 37.101 + printf("of_walk: %s: phandle 0x%x\n", path, n); 37.102 + } 37.103 + 37.104 + p = ofd_nextprop(mem, n, NULL, name); 37.105 + while ( p > 0 ) { 37.106 + sz = ofd_getprop(mem, n, name, prop, sizeof (prop)); 37.107 + if ( sz > 0 && sz > sizeof (prop) ) { 37.108 + sz = sizeof (prop); 37.109 + } 37.110 + 37.111 + if ( dump & OFD_DUMP_VALUES ) { 37.112 + ofd_prop_print("of_walk", path, name, prop, sz); 37.113 + } 37.114 + 37.115 + p = ofd_nextprop(mem, n, name, name); 37.116 + } 37.117 +} 37.118 + 37.119 +void ofd_walk(void *m, ofdn_t p, walk_fn fn, int arg) 37.120 +{ 37.121 + ofdn_t n; 37.122 + 37.123 + if ( fn != NULL ) { 37.124 + (*fn)(m, p, arg); 37.125 + } 37.126 + 37.127 + /* child */ 37.128 + n = ofd_node_child(m, p); 37.129 + if ( n != 0 ) { 37.130 + ofd_walk(m, n, fn, arg); 37.131 + } 37.132 + 37.133 + /* peer */ 37.134 + n = ofd_node_peer(m, p); 37.135 + if ( n != 0 ) { 37.136 + ofd_walk(m, n, fn, arg); 37.137 + } 37.138 +}
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 38.2 +++ b/xen/arch/powerpc/of_handler/Makefile Fri Jul 14 10:47:50 2006 +0100 38.3 @@ -0,0 +1,31 @@ 38.4 +# 38.5 +# Build the Open Firmware handler 38.6 +# 38.7 + 38.8 +CFLAGS += -I.. 38.9 + 38.10 +# head.o must be first 38.11 +obj-y = head.o 38.12 +obj-y += console.o 38.13 +obj-y += control.o 38.14 +obj-y += cpu.o 38.15 +obj-y += devtree.o 38.16 +obj-y += head.o 38.17 +obj-y += io.o 38.18 +obj-y += leap.o 38.19 +obj-y += memory.o 38.20 +obj-y += ofh.o 38.21 +obj-y += papr.o 38.22 +obj-y += services.o 38.23 +obj-y += vdevice.o 38.24 +obj-y += xencomm.o 38.25 +obj-y += xen_hvcall.o 38.26 + 38.27 +obj-y += memcmp.o 38.28 +obj-y += memset.o 38.29 +obj-y += snprintf.o 38.30 +obj-y += strcmp.o 38.31 +obj-y += strlen.o 38.32 +obj-y += strncmp.o 38.33 +obj-y += strncpy.o 38.34 +obj-y += strnlen.o
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 39.2 +++ b/xen/arch/powerpc/of_handler/console.c Fri Jul 14 10:47:50 2006 +0100 39.3 @@ -0,0 +1,233 @@ 39.4 +/* 39.5 + * This program is free software; you can redistribute it and/or modify 39.6 + * it under the terms of the GNU General Public License as published by 39.7 + * the Free Software Foundation; either version 2 of the License, or 39.8 + * (at your option) any later version. 39.9 + * 39.10 + * This program is distributed in the hope that it will be useful, 39.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 39.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 39.13 + * GNU General Public License for more details. 39.14 + * 39.15 + * You should have received a copy of the GNU General Public License 39.16 + * along with this program; if not, write to the Free Software 39.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 39.18 + * 39.19 + * Copyright (C) IBM Corp. 2005 39.20 + * 39.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 39.22 + */ 39.23 + 39.24 +#include "ofh.h" 39.25 +#include "papr.h" 39.26 +#include <xen/string.h> 39.27 +#include <asm/system.h> 39.28 + 39.29 +union chpack { 39.30 + u64 oct[2]; 39.31 + u32 quad[4]; 39.32 + char c[16]; 39.33 +}; 39.34 + 39.35 +/* used for internal printing */ 39.36 +static struct ofh_ihandle *ofh_ihp; 39.37 + 39.38 +static s32 ofh_papr_read(s32 chan, void *buf, u32 count, s32 *actual, ulong b) 39.39 +{ 39.40 + s32 rc; 39.41 + ulong ret[5]; 39.42 + ulong sz = 0; 39.43 + 39.44 + rc = papr_get_term_char(ret, chan); 39.45 + if (rc == H_Success && ret[0] > 0) { 39.46 + sz = MIN(count, ret[0]); 39.47 + memcpy(buf, &ret[1], sz); 39.48 + } 39.49 + *actual = sz; 39.50 + return OF_SUCCESS; 39.51 +} 39.52 + 39.53 +static s32 ofh_papr_write(s32 chan, const void *buf, u32 count, s32 *actual, 39.54 + ulong b) 39.55 +{ 39.56 + const char *str = (const char *)buf; 39.57 + u32 i; 39.58 + union chpack ch; 39.59 + s32 ret; 39.60 + 39.61 + for (i = 0; i < count; i++) { 39.62 + int m = i % sizeof(ch); 39.63 + ch.c[m] = str[i]; 39.64 + if (m == sizeof(ch) - 1 || i == count - 1) { 39.65 + for (;;) { 39.66 + if (sizeof (ulong) == sizeof (u64)) { 39.67 + ret = papr_put_term_char(NULL, 39.68 + chan, 39.69 + m + 1, 39.70 + ch.oct[0], 39.71 + ch.oct[1]); 39.72 + } else { 39.73 + ret = papr_put_term_char(NULL, 39.74 + chan, 39.75 + m + 1, 39.76 + ch.quad[0], 39.77 + ch.quad[1], 39.78 + ch.quad[2], 39.79 + ch.quad[3]); 39.80 + } 39.81 + if (ret != H_Busy) { 39.82 + break; 39.83 + } 39.84 + /* yielding here would be nice */ 39.85 + } 39.86 + if (ret != H_Success) { 39.87 + return -1; 39.88 + } 39.89 + } 39.90 + } 39.91 + *actual = count; 39.92 + if (*actual == -1) { 39.93 + return OF_FAILURE; 39.94 + } 39.95 + return OF_SUCCESS; 39.96 +} 39.97 + 39.98 +#define __HYPERVISOR_console_io 18 39.99 +#define CONSOLEIO_write 0 39.100 +#define CONSOLEIO_read 1 39.101 +#define XEN_MARK(a) ((a) | (~0UL << 16)) 39.102 +extern long xen_hvcall(ulong code, ...); 39.103 + 39.104 +#define XENCOMM_MINI_AREA (sizeof(struct xencomm_mini) * 2) 39.105 +static s32 ofh_xen_dom0_read(s32 chan, void *buf, u32 count, s32 *actual, 39.106 + ulong b) 39.107 +{ 39.108 + char __storage[XENCOMM_MINI_AREA]; 39.109 + struct xencomm_desc *desc; 39.110 + s32 rc; 39.111 + char *s = buf; 39.112 + s32 ret = 0; 39.113 + 39.114 + while (count > 0) { 39.115 + if (xencomm_create_mini(__storage, XENCOMM_MINI_AREA, s, count, &desc)) 39.116 + return ret; 39.117 + 39.118 + rc = xen_hvcall(XEN_MARK(__HYPERVISOR_console_io), CONSOLEIO_read, 39.119 + count, desc); 39.120 + if (rc <= 0) { 39.121 + return ret; 39.122 + } 39.123 + count -= rc; 39.124 + s += rc; 39.125 + ret += rc; 39.126 + } 39.127 + *actual = ret; 39.128 + return OF_SUCCESS; 39.129 +} 39.130 + 39.131 +static s32 ofh_xen_dom0_write(s32 chan, const void *buf, u32 count, 39.132 + s32 *actual, ulong b) 39.133 +{ 39.134 + char __storage[XENCOMM_MINI_AREA]; 39.135 + struct xencomm_desc *desc; 39.136 + s32 rc; 39.137 + char *s = (char *)buf; 39.138 + s32 ret = 0; 39.139 + 39.140 + while (count > 0) { 39.141 + if (xencomm_create_mini(__storage, XENCOMM_MINI_AREA, s, count, &desc)) 39.142 + return ret; 39.143 + 39.144 + rc = xen_hvcall(XEN_MARK(__HYPERVISOR_console_io), CONSOLEIO_write, 39.145 + count, desc); 39.146 + if (rc <= 0) { 39.147 + return ret; 39.148 + } 39.149 + count -= rc; 39.150 + s += rc; 39.151 + ret += rc; 39.152 + } 39.153 + *actual = ret; 39.154 + if (*actual == -1) { 39.155 + return OF_FAILURE; 39.156 + } 39.157 + return OF_SUCCESS; 39.158 +} 39.159 + 39.160 +static s32 ofh_xen_domu_read(s32 chan, void *buf, u32 count, s32 *actual, 39.161 + ulong b) 39.162 +{ 39.163 + struct xencons_interface *intf; 39.164 + XENCONS_RING_IDX cons, prod; 39.165 + s32 ret; 39.166 + 39.167 + intf = DRELA(ofh_ihp, b)->ofi_intf; 39.168 + cons = intf->in_cons; 39.169 + prod = intf->in_prod; 39.170 + mb(); 39.171 + 39.172 + ret = prod - cons; 39.173 + 39.174 + if (ret > 0) { 39.175 + ret = (ret < count) ? ret : count; 39.176 + memcpy(buf, intf->in+MASK_XENCONS_IDX(cons,intf->in), ret); 39.177 + } 39.178 + 39.179 + *actual = (ret < 0) ? 0 : ret; 39.180 + return OF_SUCCESS; 39.181 +} 39.182 + 39.183 +static s32 ofh_xen_domu_write(s32 chan, const void *buf, u32 count, 39.184 + s32 *actual, ulong b) 39.185 +{ 39.186 + struct xencons_interface *intf; 39.187 + XENCONS_RING_IDX cons, prod; 39.188 + s32 ret; 39.189 + 39.190 + intf = DRELA(ofh_ihp, b)->ofi_intf; 39.191 + cons = intf->in_cons; 39.192 + prod = intf->in_prod; 39.193 + mb(); 39.194 + 39.195 + ret = prod - cons; 39.196 + /* FIXME: Do we have to write the whole thing or are partial writes ok? */ 39.197 + if (ret > 0) { 39.198 + ret = (ret < count) ? ret : count; 39.199 + memcpy(intf->in+MASK_XENCONS_IDX(cons,intf->in), buf, ret); 39.200 + } 39.201 + 39.202 + *actual = (ret < 0) ? 0 : ret; 39.203 + return OF_SUCCESS; 39.204 +} 39.205 + 39.206 +/* for emergency printing in the OFH */ 39.207 +s32 ofh_cons_write(const void *buf, u32 count, s32 *actual) 39.208 +{ 39.209 + ulong b = get_base(); 39.210 + struct ofh_ihandle *ihp = DRELA(ofh_ihp, b); 39.211 + 39.212 + return ihp->ofi_write(ihp->ofi_chan, buf, count, actual, b); 39.213 +} 39.214 + 39.215 +s32 ofh_cons_close(void) 39.216 +{ 39.217 + return OF_SUCCESS; 39.218 +} 39.219 + 39.220 +void 39.221 +ofh_cons_init(struct ofh_ihandle *ihp, ulong b) 39.222 +{ 39.223 + if (ihp->ofi_chan == OFH_CONS_XEN) { 39.224 + if (ihp->ofi_intf == NULL) { 39.225 + ihp->ofi_write = ofh_xen_dom0_write; 39.226 + ihp->ofi_read = ofh_xen_dom0_read; 39.227 + } else { 39.228 + ihp->ofi_write = ofh_xen_domu_write; 39.229 + ihp->ofi_read = ofh_xen_domu_read; 39.230 + } 39.231 + } else { 39.232 + ihp->ofi_write = ofh_papr_write; 39.233 + ihp->ofi_read = ofh_papr_read; 39.234 + } 39.235 + *DRELA(&ofh_ihp, b) = ihp; 39.236 +}
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 40.2 +++ b/xen/arch/powerpc/of_handler/control.c Fri Jul 14 10:47:50 2006 +0100 40.3 @@ -0,0 +1,90 @@ 40.4 +/* 40.5 + * This program is free software; you can redistribute it and/or modify 40.6 + * it under the terms of the GNU General Public License as published by 40.7 + * the Free Software Foundation; either version 2 of the License, or 40.8 + * (at your option) any later version. 40.9 + * 40.10 + * This program is distributed in the hope that it will be useful, 40.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 40.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 40.13 + * GNU General Public License for more details. 40.14 + * 40.15 + * You should have received a copy of the GNU General Public License 40.16 + * along with this program; if not, write to the Free Software 40.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 40.18 + * 40.19 + * Copyright (C) IBM Corp. 2005 40.20 + * 40.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 40.22 + */ 40.23 + 40.24 +#include "ofh.h" 40.25 + 40.26 +s32 40.27 +ofh_boot(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 40.28 +{ 40.29 + b=b; 40.30 + nargs = nargs; 40.31 + nrets = nrets; 40.32 + argp = argp; 40.33 + retp = retp; 40.34 + return OF_FAILURE; 40.35 +} 40.36 + 40.37 +s32 40.38 +ofh_enter(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 40.39 +{ 40.40 + b=b; 40.41 + nargs = nargs; 40.42 + nrets = nrets; 40.43 + argp = argp; 40.44 + retp = retp; 40.45 + return OF_FAILURE; 40.46 +} 40.47 + 40.48 +s32 40.49 +ofh_exit(u32 nargs __attribute__ ((unused)), 40.50 + u32 nrets __attribute__ ((unused)), 40.51 + s32 argp[] __attribute__ ((unused)), 40.52 + s32 retp[] __attribute__ ((unused)), 40.53 + ulong b) 40.54 +{ 40.55 + static const char msg[] = "OFH: exit method called\n"; 40.56 + s32 dummy; 40.57 + 40.58 + ofh_cons_write(DRELA(&msg[0], b), sizeof (msg), &dummy); 40.59 + 40.60 + for (;;) { 40.61 + /* kill domain here */ 40.62 + } 40.63 + return OF_FAILURE; 40.64 +} 40.65 + 40.66 +s32 40.67 +ofh_chain(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 40.68 +{ 40.69 + b=b; 40.70 + nargs = nargs; 40.71 + nrets = nrets; 40.72 + argp = argp; 40.73 + retp = retp; 40.74 + return OF_FAILURE; 40.75 +} 40.76 + 40.77 +s32 40.78 +ofh_quiesce(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 40.79 +{ 40.80 + if (nargs == 0) { 40.81 + if (nrets == 0) { 40.82 + void *mem = ofd_mem(b); 40.83 + (void)nargs; 40.84 + (void)nrets; 40.85 + (void)argp; 40.86 + (void)retp; 40.87 + (void)mem; 40.88 + 40.89 + return OF_SUCCESS; 40.90 + } 40.91 + } 40.92 + return OF_FAILURE; 40.93 +}
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 41.2 +++ b/xen/arch/powerpc/of_handler/cpu.c Fri Jul 14 10:47:50 2006 +0100 41.3 @@ -0,0 +1,82 @@ 41.4 +/* 41.5 + * This program is free software; you can redistribute it and/or modify 41.6 + * it under the terms of the GNU General Public License as published by 41.7 + * the Free Software Foundation; either version 2 of the License, or 41.8 + * (at your option) any later version. 41.9 + * 41.10 + * This program is distributed in the hope that it will be useful, 41.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 41.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 41.13 + * GNU General Public License for more details. 41.14 + * 41.15 + * You should have received a copy of the GNU General Public License 41.16 + * along with this program; if not, write to the Free Software 41.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 41.18 + * 41.19 + * Copyright (C) IBM Corp. 2005 41.20 + * 41.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 41.22 + */ 41.23 + 41.24 +#include "ofh.h" 41.25 + 41.26 +s32 41.27 +ofh_start_cpu(u32 nargs, u32 nrets, s32 argp[], 41.28 + s32 retp[] __attribute__ ((unused)), 41.29 + ulong b __attribute__ ((unused))) 41.30 +{ 41.31 + if (nargs == 3) { 41.32 + if (nrets == 0) { 41.33 + ofdn_t ph = argp[0]; 41.34 + u32 pc = argp[1]; 41.35 + u32 arg = argp[2]; 41.36 + 41.37 + (void)ph; (void)pc; (void)arg; 41.38 + return OF_FAILURE; 41.39 + } 41.40 + } 41.41 + return OF_FAILURE; 41.42 +} 41.43 + 41.44 +s32 41.45 +ofh_stop_self(u32 nargs, u32 nrets, 41.46 + s32 argp[] __attribute__ ((unused)), 41.47 + s32 retp[] __attribute__ ((unused)), 41.48 + ulong b __attribute__ ((unused))) 41.49 +{ 41.50 + if (nargs == 0) { 41.51 + if (nrets == 0) { 41.52 + return OF_FAILURE; 41.53 + } 41.54 + } 41.55 + return OF_FAILURE; 41.56 +} 41.57 + 41.58 +s32 41.59 +ofh_idle_self(u32 nargs, u32 nrets, 41.60 + s32 argp[] __attribute__ ((unused)), 41.61 + s32 retp[] __attribute__ ((unused)), 41.62 + ulong b __attribute__ ((unused))) 41.63 +{ 41.64 + if (nargs == 0) { 41.65 + if (nrets == 0) { 41.66 + return OF_FAILURE; 41.67 + } 41.68 + } 41.69 + return OF_FAILURE; 41.70 +} 41.71 +s32 41.72 +ofh_resume_cpu(u32 nargs, u32 nrets, s32 argp[], 41.73 + s32 retp[] __attribute__ ((unused)), 41.74 + ulong b __attribute__ ((unused))) 41.75 +{ 41.76 + if (nargs == 1) { 41.77 + if (nrets == 0) { 41.78 + ofdn_t ph = argp[0]; 41.79 + 41.80 + (void)ph; 41.81 + return OF_FAILURE; 41.82 + } 41.83 + } 41.84 + return OF_FAILURE; 41.85 +}
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 42.2 +++ b/xen/arch/powerpc/of_handler/devtree.c Fri Jul 14 10:47:50 2006 +0100 42.3 @@ -0,0 +1,266 @@ 42.4 +/* 42.5 + * This program is free software; you can redistribute it and/or modify 42.6 + * it under the terms of the GNU General Public License as published by 42.7 + * the Free Software Foundation; either version 2 of the License, or 42.8 + * (at your option) any later version. 42.9 + * 42.10 + * This program is distributed in the hope that it will be useful, 42.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 42.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 42.13 + * GNU General Public License for more details. 42.14 + * 42.15 + * You should have received a copy of the GNU General Public License 42.16 + * along with this program; if not, write to the Free Software 42.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 42.18 + * 42.19 + * Copyright (C) IBM Corp. 2005 42.20 + * 42.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 42.22 + */ 42.23 + 42.24 +#include "ofh.h" 42.25 +#include <of-devtree.h> 42.26 + 42.27 +s32 42.28 +ofh_peer(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 42.29 +{ 42.30 + if (nargs == 1) { 42.31 + if (nrets == 1) { 42.32 + ofdn_t ph = argp[0]; 42.33 + s32 *sib_ph = &retp[0]; 42.34 + void *mem = ofd_mem(b); 42.35 + 42.36 + *sib_ph = ofd_node_peer(mem, ph); 42.37 + return OF_SUCCESS; 42.38 + } 42.39 + } 42.40 + return OF_FAILURE; 42.41 +} 42.42 + 42.43 +s32 42.44 +ofh_child(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 42.45 +{ 42.46 + if (nargs == 1) { 42.47 + if (nrets == 1) { 42.48 + ofdn_t ph = argp[0]; 42.49 + s32 *ch_ph = &retp[0]; 42.50 + void *mem = ofd_mem(b); 42.51 + 42.52 + *ch_ph = ofd_node_child(mem, ph); 42.53 + return OF_SUCCESS; 42.54 + } 42.55 + } 42.56 + return OF_FAILURE; 42.57 +} 42.58 + 42.59 +s32 42.60 +ofh_parent(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 42.61 +{ 42.62 + if (nargs == 1) { 42.63 + if (nrets == 1) { 42.64 + ofdn_t ph = argp[0]; 42.65 + s32 *parent_ph = &retp[0]; 42.66 + void *mem = ofd_mem(b); 42.67 + 42.68 + *parent_ph = ofd_node_parent(mem, ph); 42.69 + return OF_SUCCESS; 42.70 + } 42.71 + } 42.72 + return OF_FAILURE; 42.73 +} 42.74 + 42.75 +s32 42.76 +ofh_instance_to_package(u32 nargs, u32 nrets, s32 argp[], s32 retp[], 42.77 + ulong b __attribute__ ((unused))) 42.78 +{ 42.79 + if (nargs == 1) { 42.80 + if (nrets == 1) { 42.81 + struct ofh_ihandle *ih = 42.82 + (struct ofh_ihandle *)(ulong)argp[0]; 42.83 + s32 *p = &retp[0]; 42.84 + 42.85 + *p = (s32)ih->ofi_node; 42.86 + return OF_SUCCESS; 42.87 + } 42.88 + } 42.89 + return OF_FAILURE; 42.90 +} 42.91 + 42.92 +s32 42.93 +ofh_getproplen(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 42.94 +{ 42.95 + if (nargs == 2) { 42.96 + if (nrets == 1) { 42.97 + ofdn_t ph = argp[0]; 42.98 + const char *name = (const char *)(ulong)argp[1]; 42.99 + s32 *size = &retp[0]; 42.100 + void *mem = ofd_mem(b); 42.101 + 42.102 + *size = ofd_getproplen(mem, ph, name); 42.103 + if (*size >= 0) { 42.104 + return OF_SUCCESS; 42.105 + } 42.106 + } 42.107 + } 42.108 + return OF_FAILURE; 42.109 +} 42.110 + 42.111 +s32 42.112 +ofh_getprop(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 42.113 +{ 42.114 + if (nargs == 4) { 42.115 + if (nrets == 1) { 42.116 + ofdn_t ph = argp[0]; 42.117 + const char *name = (const char *)(ulong)argp[1]; 42.118 + void *buf = (void *)(ulong)argp[2]; 42.119 + ulong buflen = argp[3]; 42.120 + s32 *size = &retp[0]; 42.121 + void *mem = ofd_mem(b); 42.122 + 42.123 + *size = ofd_getprop(mem, ph, name, buf, buflen); 42.124 + if (*size > 0) { 42.125 + return OF_SUCCESS; 42.126 + } 42.127 + } 42.128 + } 42.129 + return OF_FAILURE; 42.130 +} 42.131 + 42.132 +s32 42.133 +ofh_nextprop(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 42.134 +{ 42.135 + if (nargs == 3) { 42.136 + if (nrets == 1) { 42.137 + ofdn_t ph = argp[0]; 42.138 + const char *prev = (const char *)(ulong)argp[1]; 42.139 + char *name = (char *)(ulong)argp[2]; 42.140 + s32 *flag = &retp[0]; 42.141 + void *mem = ofd_mem(b); 42.142 + 42.143 + *flag = ofd_nextprop(mem, ph, prev, name); 42.144 + if (*flag > 0) { 42.145 + *flag = 1; 42.146 + } 42.147 + return OF_SUCCESS; 42.148 + } 42.149 + } 42.150 + return OF_FAILURE; 42.151 +} 42.152 + 42.153 +s32 42.154 +ofh_setprop(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 42.155 +{ 42.156 + if (nargs == 4) { 42.157 + if (nrets == 1) { 42.158 + ofdn_t ph = argp[0]; 42.159 + const char *name = (const char *)(ulong)argp[1]; 42.160 + const void *buf = (void *)(ulong)argp[2]; 42.161 + ulong buflen = argp[3]; 42.162 + s32 *size = &retp[0]; 42.163 + void *mem = ofd_mem(b); 42.164 + 42.165 + *size = ofd_setprop(mem, ph, name, buf, buflen); 42.166 + return OF_SUCCESS; 42.167 + } 42.168 + } 42.169 + return OF_FAILURE; 42.170 +} 42.171 + 42.172 +s32 42.173 +ofh_canon(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 42.174 +{ 42.175 + if (nargs == 3) { 42.176 + if (nrets == 1) { 42.177 + const char *dev_spec = (const char *)(ulong)argp[0]; 42.178 + char *buf = (char *)(ulong)argp[1]; 42.179 + u32 sz = argp[2]; 42.180 + s32 *len = &retp[0]; 42.181 + void *mem = ofd_mem(b); 42.182 + ofdn_t ph; 42.183 + 42.184 + ph = ofd_node_find(mem, dev_spec); 42.185 + if (ph > 0) { 42.186 + *len = ofd_node_to_path(mem, ph, buf, sz); 42.187 + return OF_SUCCESS; 42.188 + } 42.189 + } 42.190 + } 42.191 + return OF_FAILURE; 42.192 +} 42.193 + 42.194 +s32 ofh_active_package = -1; 42.195 + 42.196 +s32 42.197 +ofh_finddevice(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 42.198 +{ 42.199 + if (nargs == 1) { 42.200 + if (nrets == 1) { 42.201 + s32 *ap = DRELA(&ofh_active_package, b); 42.202 + const char *devspec = (const char *)(ulong)argp[0]; 42.203 + s32 *ph = &retp[0]; 42.204 + void *mem = ofd_mem(b); 42.205 + 42.206 + /* good enuff */ 42.207 + if (devspec[0] == '\0') { 42.208 + if (*ap == -1) { 42.209 + return OF_FAILURE; 42.210 + } 42.211 + *ph = *ap; 42.212 + } else { 42.213 + *ph = ofd_node_find(mem, devspec); 42.214 + if (*ph <= 0) { 42.215 + return OF_FAILURE; 42.216 + } 42.217 + } 42.218 + *ap = *ph; 42.219 + return OF_SUCCESS; 42.220 + } 42.221 + } 42.222 + return OF_FAILURE; 42.223 +} 42.224 + 42.225 +s32 42.226 +ofh_instance_to_path(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 42.227 +{ 42.228 + if (nargs == 3) { 42.229 + if (nrets == 1) { 42.230 + struct ofh_ihandle *ih = 42.231 + (struct ofh_ihandle *)((ulong)argp[0]); 42.232 + char *buf = (char *)(ulong)argp[1]; 42.233 + u32 sz = argp[2]; 42.234 + s32 *len = &retp[0]; 42.235 + ofdn_t ph; 42.236 + void *mem = ofd_mem(b); 42.237 + 42.238 + ph = ih->ofi_node; 42.239 + if (ph > 0) { 42.240 + *len = ofd_node_to_path(mem, ph, buf, sz); 42.241 + return OF_SUCCESS; 42.242 + } 42.243 + } 42.244 + } 42.245 + return OF_FAILURE; 42.246 +} 42.247 + 42.248 +s32 42.249 +ofh_package_to_path(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 42.250 +{ 42.251 + if (nargs == 3) { 42.252 + if (nrets == 1) { 42.253 + ofdn_t ph = argp[0]; 42.254 + char *buf = (char *)(ulong)argp[1]; 42.255 + u32 sz = argp[2]; 42.256 + s32 *len = &retp[0]; 42.257 + void *mem = ofd_mem(b); 42.258 + 42.259 + if (ph > 0) { 42.260 + *len = ofd_node_to_path(mem, ph, buf, sz); 42.261 + return OF_SUCCESS; 42.262 + } 42.263 + } 42.264 + } 42.265 + return OF_FAILURE; 42.266 +} 42.267 + 42.268 + 42.269 +
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 43.2 +++ b/xen/arch/powerpc/of_handler/head.S Fri Jul 14 10:47:50 2006 +0100 43.3 @@ -0,0 +1,152 @@ 43.4 +/* 43.5 + * Copyright (C) 2005 Jimi Xenidis <jimix@watson.ibm.com>, IBM Corporation 43.6 + * 43.7 + * This program is free software; you can redistribute it and/or modify 43.8 + * it under the terms of the GNU General Public License as published by 43.9 + * the Free Software Foundation; either version 2 of the License, or 43.10 + * (at your option) any later version. 43.11 + * 43.12 + * This program is distributed in the hope that it will be useful, 43.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 43.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 43.15 + * GNU General Public License for more details. 43.16 + * 43.17 + * You should have received a copy of the GNU General Public License 43.18 + * along with this program; if not, write to the Free Software 43.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 43.20 + */ 43.21 +/* 43.22 + * Glue code for open-firmware client interface implementation. 43.23 + */ 43.24 + 43.25 +#define OF_STACK_SIZE (32*1024) 43.26 + 43.27 +#include <asm/config.h> 43.28 +#include <asm/processor.h> 43.29 + 43.30 +#define SAVE_STACK 0 43.31 +#define SAVE_SRR0 1 43.32 +#define SAVE_SRR1 2 43.33 +#define SAVE_MSR 3 43.34 +#define SAVE_LR 4 43.35 +#define SAVE_TOC 5 43.36 +#define SAVE_BASE 6 43.37 +#define SAVE_BCHAIN 7 /* MUST be last */ 43.38 + 43.39 +/* This code is NOT MP safe and does not need to be */ 43.40 + .p2align 3 43.41 + . = 0x0 43.42 +_GLOBAL(ofh_start) # make the linker happy 43.43 +_ofh_cih: 43.44 + ## r3 holds the parameter. All other volatiles are available. 43.45 + mflr r0 43.46 + # Obtain address of _ofh_work_space via a branch-and-link 43.47 + bl _ofh_cih_continue 43.48 +_ofh_work_space: 43.49 + nop 43.50 + 43.51 + . = 0x10 43.52 + .global _ofh_tree 43.53 +_ofh_tree: 43.54 + .long 0xdeadbeef 43.55 + .long 0x0 43.56 + 43.57 + . = 0x18 43.58 + .global _ofh_inited 43.59 +_ofh_inited: 43.60 + .long 0x0 43.61 + 43.62 + . = 0x20 43.63 + .global _ofh_lastarg 43.64 +_ofh_lastarg: 43.65 + .long 0x0 43.66 + .long 0x0 43.67 + 43.68 + . = 0x30 43.69 +_ofh_cih_stack_end: 43.70 + .space OF_STACK_SIZE 43.71 +_ofh_cih_stack: 43.72 + 43.73 +_ofh_cih_continue: 43.74 + mflr r12 # r12 = &_ofh_work_space 43.75 + mr r11, r1 # r11 = orig stk ptr 43.76 + 43.77 + /* load base address in r4 */ 43.78 + LOADADDR(r4, _ofh_work_space) 43.79 + sub r4, r12, r4 43.80 + 43.81 + 43.82 + # save srr0/1 43.83 + mfsrr0 r9 43.84 + mfsrr1 r8 43.85 + mfmsr r7 43.86 + LOADADDR(r5, _ofh_cih_64bit) 43.87 + add r5, r5, r4 # offset base 43.88 + mtsrr0 r5 43.89 + # r5 = MSR_SF 43.90 + li r5,-1 43.91 + rldicr r5,r5,0,0 43.92 + or r5,r5,r7 43.93 + mtsrr1 r5 43.94 + rfid 43.95 + trap 43.96 + 43.97 +_ofh_cih_64bit: 43.98 + # move to local stack 43.99 + lis r1, (_ofh_cih_stack - _ofh_cih_stack_end) >> 16 43.100 + ori r1, r1, (_ofh_cih_stack - _ofh_cih_stack_end) & 0xffff 43.101 + add r1, r12, r1 43.102 + # create an initial chain 43.103 + li r10, 0 43.104 + # frame with 3 slots 43.105 + stdu r10, -(STACK_FRAME_OVERHEAD + (SAVE_BCHAIN * 8))(r1) 43.106 + # preserve base 43.107 + std r4, (STACK_FRAME_OVERHEAD + (SAVE_BASE * 8))(r1) 43.108 + # preserve orig stk ptr 43.109 + std r11, (STACK_FRAME_OVERHEAD + (SAVE_STACK * 8))(r1) 43.110 + # preserve orig srr0 43.111 + std r9, (STACK_FRAME_OVERHEAD + (SAVE_SRR0 * 8))(r1) 43.112 + # preserve orig srr1 43.113 + std r8, (STACK_FRAME_OVERHEAD + (SAVE_SRR1 * 8))(r1) 43.114 + # preserve orig msr 43.115 + std r7, (STACK_FRAME_OVERHEAD + (SAVE_MSR * 8))(r1) 43.116 + # preserve orig lr 43.117 + std r0, (STACK_FRAME_OVERHEAD + (SAVE_LR * 8))(r1) 43.118 + # preserve orig toc 43.119 + std r2, (STACK_FRAME_OVERHEAD + (SAVE_TOC * 8))(r1) 43.120 + 43.121 + LOADADDR(r2, ofh_start) # get the address of any function 43.122 + add r2, r2, r4 # add the base 43.123 + ld r2, 8(r2) # get the TOC for that funtion 43.124 + add r2, r2, r4 # add the base 43.125 + 43.126 + bl _ENTRY(ofh_handler) # call handler 43.127 + 43.128 + ld r4, (STACK_FRAME_OVERHEAD + (SAVE_BASE * 8))(r1) 43.129 + ld r9, (STACK_FRAME_OVERHEAD + (SAVE_SRR0 * 8))(r1) 43.130 + ld r8, (STACK_FRAME_OVERHEAD + (SAVE_SRR1 * 8))(r1) 43.131 + ld r7, (STACK_FRAME_OVERHEAD + (SAVE_MSR * 8))(r1) 43.132 + ld r2, (STACK_FRAME_OVERHEAD + (SAVE_TOC * 8))(r1) 43.133 + ld r0, (STACK_FRAME_OVERHEAD + (SAVE_LR * 8))(r1) 43.134 + ld r1, (STACK_FRAME_OVERHEAD + (SAVE_STACK * 8))(r1) 43.135 + 43.136 + LOADADDR(r5, _ofh_cih_orig_msr) 43.137 + add r5, r5, r4 43.138 + mtsrr0 r5 43.139 + mtsrr1 r7 43.140 + rfid 43.141 + 43.142 +_ofh_cih_orig_msr: 43.143 + mtsrr0 r9 43.144 + mtsrr1 r8 43.145 + mtlr r0 43.146 + blr 43.147 + 43.148 +_GLOBAL(get_base) 43.149 + mflr r0 43.150 + bl 1f 43.151 +1: mflr r5 43.152 + LOADADDR(r4,1b) 43.153 + subf r3,r4,r5 43.154 + mtlr r0 43.155 + blr
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 44.2 +++ b/xen/arch/powerpc/of_handler/io.c Fri Jul 14 10:47:50 2006 +0100 44.3 @@ -0,0 +1,160 @@ 44.4 +/* 44.5 + * This program is free software; you can redistribute it and/or modify 44.6 + * it under the terms of the GNU General Public License as published by 44.7 + * the Free Software Foundation; either version 2 of the License, or 44.8 + * (at your option) any later version. 44.9 + * 44.10 + * This program is distributed in the hope that it will be useful, 44.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 44.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 44.13 + * GNU General Public License for more details. 44.14 + * 44.15 + * You should have received a copy of the GNU General Public License 44.16 + * along with this program; if not, write to the Free Software 44.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 44.18 + * 44.19 + * Copyright (C) IBM Corp. 2005 44.20 + * 44.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 44.22 + */ 44.23 + 44.24 +#include "ofh.h" 44.25 +#include "xen/lib.h" 44.26 + 44.27 +s32 44.28 +ofh_open(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 44.29 +{ 44.30 + if (nargs == 1) { 44.31 + if (nrets == 1) { 44.32 + const char *devspec = (const char *)(ulong)argp[0]; 44.33 + s32 *ih = &retp[0]; 44.34 + ofdn_t p; 44.35 + void *mem = ofd_mem(b); 44.36 + 44.37 + p = ofd_node_find(mem, devspec); 44.38 + if (p > 0) { 44.39 + ofdn_t io; 44.40 + io = ofd_node_io(mem, p); 44.41 + if (io > 0) { 44.42 + void *f = (void *)(ulong)ofd_io_open(mem, io); 44.43 + if (f != 0) { 44.44 + *ih = leap(b, 0, NULL, NULL, 44.45 + b, f); 44.46 + return OF_SUCCESS; 44.47 + } 44.48 + } 44.49 + } 44.50 + *ih = 0; 44.51 + } 44.52 + } 44.53 + return OF_FAILURE; 44.54 +} 44.55 + 44.56 +s32 44.57 +ofh_close(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 44.58 +{ 44.59 + if (nargs == 1) { 44.60 + if (nrets == 0) { 44.61 + argp = argp; 44.62 + retp = retp; 44.63 + b = b; 44.64 + return OF_FAILURE; 44.65 + } 44.66 + } 44.67 + return OF_FAILURE; 44.68 +} 44.69 +s32 44.70 +ofh_read(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 44.71 +{ 44.72 + if (nargs == 3) { 44.73 + if (nrets == 1) { 44.74 + struct ofh_ihandle *ih = 44.75 + (struct ofh_ihandle *)(ulong)argp[0]; 44.76 + 44.77 + if (ih->ofi_read != NULL) { 44.78 + void *addr = (void *)(ulong)argp[1]; 44.79 + u32 sz = argp[2]; 44.80 + s32 *actual = &retp[0]; 44.81 + void *f = ih->ofi_read; 44.82 + 44.83 + if (f != 0) { 44.84 + return io_leap(ih->ofi_chan, addr, sz, actual, 44.85 + b, f); 44.86 + } 44.87 + } 44.88 + } 44.89 + } 44.90 + return OF_FAILURE; 44.91 +} 44.92 + 44.93 +s32 44.94 +ofh_write(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 44.95 +{ 44.96 + if (nargs == 3) { 44.97 + if (nrets == 1) { 44.98 + struct ofh_ihandle *ih = 44.99 + (struct ofh_ihandle *)(ulong)argp[0]; 44.100 + 44.101 + if (ih->ofi_write != NULL) { 44.102 + void *addr = (void *)(ulong)argp[1]; 44.103 + u32 sz = argp[2]; 44.104 + s32 *actual = &retp[0]; 44.105 + void *f = ih->ofi_write; 44.106 + 44.107 + if (f != 0) { 44.108 + return io_leap(ih->ofi_chan, addr, sz, actual, 44.109 + b, f); 44.110 + } 44.111 + } 44.112 + } 44.113 + } 44.114 + return OF_FAILURE; 44.115 +} 44.116 + 44.117 +s32 44.118 +ofh_seek(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 44.119 +{ 44.120 + b=b; 44.121 + nargs = nargs; 44.122 + nrets = nrets; 44.123 + argp = argp; 44.124 + retp = retp; 44.125 + return OF_FAILURE; 44.126 +} 44.127 + 44.128 +static ofh_func_t * 44.129 +method_lookup(struct ofh_ihandle *ih, const char *name, ulong b) 44.130 +{ 44.131 + struct ofh_methods *m = DRELA(ih->ofi_methods, b); 44.132 + 44.133 + while (m != NULL && m->ofm_name != NULL ) { 44.134 + if (strcmp(name, DRELA(m->ofm_name, b)) == 0) { 44.135 + return m->ofm_method; 44.136 + } 44.137 + } 44.138 + return NULL; 44.139 +} 44.140 + 44.141 + 44.142 +s32 44.143 +ofh_call_method(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 44.144 +{ 44.145 + if (nargs > 2) { 44.146 + if (nrets > 1) { 44.147 + const char *method = (const char *)(ulong)argp[0]; 44.148 + struct ofh_ihandle *ih = 44.149 + (struct ofh_ihandle *)(ulong)argp[1]; 44.150 + ofh_func_t *f; 44.151 + 44.152 + f = method_lookup(ih, method, b); 44.153 + if (f != NULL) { 44.154 + /* set catch methods return 0 on success */ 44.155 + retp[0] = leap(nargs - 2, nrets - 1, 44.156 + &argp[2], &retp[1], b, f); 44.157 + return OF_SUCCESS; 44.158 + } 44.159 + } 44.160 + } 44.161 + return OF_FAILURE; 44.162 +} 44.163 +
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 45.2 +++ b/xen/arch/powerpc/of_handler/leap.S Fri Jul 14 10:47:50 2006 +0100 45.3 @@ -0,0 +1,38 @@ 45.4 +/* 45.5 + * Copyright (C) 2005 Jimi Xenidis <jimix@watson.ibm.com>, IBM Corporation 45.6 + * 45.7 + * This program is free software; you can redistribute it and/or modify 45.8 + * it under the terms of the GNU General Public License as published by 45.9 + * the Free Software Foundation; either version 2 of the License, or 45.10 + * (at your option) any later version. 45.11 + * 45.12 + * This program is distributed in the hope that it will be useful, 45.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 45.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 45.15 + * GNU General Public License for more details. 45.16 + * 45.17 + * You should have received a copy of the GNU General Public License 45.18 + * along with this program; if not, write to the Free Software 45.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 45.20 + */ 45.21 +#include <asm/config.h> 45.22 +#include <asm/processor.h> 45.23 + 45.24 +/* 45.25 + * sval 45.26 + * rh_leap(uval nargs, uval nrets, uval args[], uval rets[], uval ba, 45.27 + * rh_func_t f) 45.28 + * We need to deal with f actually bein a function descriptor, we can 45.29 + * assume that TOC is correct. 45.30 + */ 45.31 + 45.32 + 45.33 +_GLOBAL(io_leap) 45.34 +_GLOBAL(leap) 45.35 + ## r8 contains the base address for everyone 45.36 + add r8,r8,r7 # add 45.37 + ld r8, 0(r8) # get the entry point 45.38 + add r8,r8,r7 # add 45.39 + mtctr r8 # and 45.40 + bctr # leap 45.41 + /* never get here */
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 46.2 +++ b/xen/arch/powerpc/of_handler/memcmp.c Fri Jul 14 10:47:50 2006 +0100 46.3 @@ -0,0 +1,39 @@ 46.4 +/* 46.5 + * This program is free software; you can redistribute it and/or modify 46.6 + * it under the terms of the GNU General Public License as published by 46.7 + * the Free Software Foundation; either version 2 of the License, or 46.8 + * (at your option) any later version. 46.9 + * 46.10 + * This program is distributed in the hope that it will be useful, 46.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 46.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 46.13 + * GNU General Public License for more details. 46.14 + * 46.15 + * You should have received a copy of the GNU General Public License 46.16 + * along with this program; if not, write to the Free Software 46.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 46.18 + * 46.19 + * Copyright (C) IBM Corp. 2005 46.20 + * 46.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 46.22 + */ 46.23 + 46.24 +#include <xen/string.h> 46.25 + 46.26 +int 46.27 +memcmp(const void *v1, const void *v2, size_t n) 46.28 +{ 46.29 + const char *s1 = (const char *)v1; 46.30 + const char *s2 = (const char *)v2; 46.31 + 46.32 + while (n > 0) { 46.33 + if (*s1 != *s2) { 46.34 + return (*s1 - *s2); 46.35 + } 46.36 + /* advance pointers to next character */ 46.37 + ++s1; 46.38 + ++s2; 46.39 + --n; 46.40 + } 46.41 + return 0; 46.42 +}
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 47.2 +++ b/xen/arch/powerpc/of_handler/memory.c Fri Jul 14 10:47:50 2006 +0100 47.3 @@ -0,0 +1,129 @@ 47.4 +/* 47.5 + * This program is free software; you can redistribute it and/or modify 47.6 + * it under the terms of the GNU General Public License as published by 47.7 + * the Free Software Foundation; either version 2 of the License, or 47.8 + * (at your option) any later version. 47.9 + * 47.10 + * This program is distributed in the hope that it will be useful, 47.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 47.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 47.13 + * GNU General Public License for more details. 47.14 + * 47.15 + * You should have received a copy of the GNU General Public License 47.16 + * along with this program; if not, write to the Free Software 47.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 47.18 + * 47.19 + * Copyright (C) IBM Corp. 2005 47.20 + * 47.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 47.22 + */ 47.23 + 47.24 +#include "ofh.h" 47.25 + 47.26 +struct of_malloc_s { 47.27 + u32 ofm_start; 47.28 + u32 ofm_end; 47.29 +}; 47.30 +static struct of_malloc_s claimed[64]; 47.31 + 47.32 +static s32 47.33 +claim(ulong b, u32 virt, u32 size, u32 align, s32 *baseaddr) 47.34 +{ 47.35 + struct of_malloc_s *cp; 47.36 + u32 i; 47.37 + s32 e; 47.38 + u32 end; 47.39 + 47.40 + if (align != 0) { 47.41 + /* we don't do this now */ 47.42 + return OF_FAILURE; 47.43 + } 47.44 + 47.45 + end = virt + size; 47.46 + 47.47 + /* you cannot claim OF's own space */ 47.48 + if (virt >= (u32)ofh_start && end < (u32)_end) { 47.49 + return OF_FAILURE; 47.50 + } 47.51 + 47.52 + cp = DRELA(&claimed[0], b); 47.53 + /* don't care about speed at the moment */ 47.54 + e = -1; 47.55 + for (i = 0; i < sizeof (claimed)/sizeof (claimed[0]); i++) { 47.56 + if (cp[i].ofm_end == 0) { 47.57 + if (e == -1) { 47.58 + e = i; 47.59 + } 47.60 + continue; 47.61 + } 47.62 + if (virt >= cp[i].ofm_start && virt < cp[i].ofm_end) { 47.63 + return OF_FAILURE; 47.64 + } 47.65 + if (end >= cp[i].ofm_start && end < cp[i].ofm_end) { 47.66 + return OF_FAILURE; 47.67 + } 47.68 + } 47.69 + /* e points to the first empty */ 47.70 + cp[e].ofm_start = virt; 47.71 + cp[e].ofm_end = end; 47.72 + *baseaddr = virt; 47.73 + return OF_SUCCESS; 47.74 +} 47.75 + 47.76 +s32 47.77 +ofh_claim(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 47.78 +{ 47.79 + if (nargs == 3) { 47.80 + if (nrets == 1) { 47.81 + u32 virt = argp[0]; 47.82 + u32 size = argp[1]; 47.83 + u32 align = argp[2]; 47.84 + s32 *baseaddr = &retp[0]; 47.85 + 47.86 + return claim(b, virt, size, align, baseaddr); 47.87 + } 47.88 + } 47.89 + return OF_FAILURE; 47.90 +} 47.91 + 47.92 +static s32 47.93 +release(ulong b, u32 virt, u32 size) 47.94 +{ 47.95 + struct of_malloc_s *cp; 47.96 + u32 i; 47.97 + u32 end; 47.98 + 47.99 + end = virt + size; 47.100 + 47.101 + /* you cannot release OF's own space */ 47.102 + if (virt >= (u32)ofh_start && end < (u32)_end) { 47.103 + return OF_FAILURE; 47.104 + } 47.105 + 47.106 + cp = DRELA(&claimed[0], b); 47.107 + /* don't care about speed at the moment */ 47.108 + for (i = 0; i < sizeof (claimed)/sizeof (claimed[0]); i++) { 47.109 + if (virt == cp[i].ofm_start && end == cp[i].ofm_end) { 47.110 + cp[i].ofm_start = 0; 47.111 + cp[i].ofm_end = 0; 47.112 + return OF_SUCCESS; 47.113 + } 47.114 + } 47.115 + return OF_FAILURE; 47.116 +} 47.117 + 47.118 +s32 47.119 +ofh_release(u32 nargs, u32 nrets, s32 argp[], 47.120 + s32 retp[] __attribute__ ((unused)), 47.121 + ulong b) 47.122 +{ 47.123 + if (nargs == 2) { 47.124 + if (nrets == 0) { 47.125 + u32 virt = argp[0]; 47.126 + u32 size = argp[1]; 47.127 + 47.128 + return release(b, virt, size); 47.129 + } 47.130 + } 47.131 + return OF_FAILURE; 47.132 +}
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 48.2 +++ b/xen/arch/powerpc/of_handler/memset.c Fri Jul 14 10:47:50 2006 +0100 48.3 @@ -0,0 +1,67 @@ 48.4 +/* 48.5 + * This program is free software; you can redistribute it and/or modify 48.6 + * it under the terms of the GNU General Public License as published by 48.7 + * the Free Software Foundation; either version 2 of the License, or 48.8 + * (at your option) any later version. 48.9 + * 48.10 + * This program is distributed in the hope that it will be useful, 48.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 48.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 48.13 + * GNU General Public License for more details. 48.14 + * 48.15 + * You should have received a copy of the GNU General Public License 48.16 + * along with this program; if not, write to the Free Software 48.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 48.18 + * 48.19 + * Copyright (C) IBM Corp. 2005 48.20 + * 48.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 48.22 + */ 48.23 + 48.24 +#include <xen/string.h> 48.25 + 48.26 +void * 48.27 +memset(void *s, int c, size_t n) 48.28 +{ 48.29 + uint8_t *ss = (uint8_t *)s; 48.30 + 48.31 + if (n == 0) { 48.32 + return s; 48.33 + } 48.34 + 48.35 + /* yes, I pulled the 2 out of this air */ 48.36 + if (n >= (2 * sizeof (ulong))) { 48.37 + ulong val = 0; 48.38 + ulong i; 48.39 + 48.40 + /* construct val assignment from c */ 48.41 + if (c != 0) { 48.42 + for (i = 0; i < sizeof (ulong); i++) { 48.43 + val = (val << 8) | c; 48.44 + } 48.45 + } 48.46 + 48.47 + /* do by character until aligned */ 48.48 + while (((ulong)ss & (sizeof (ulong) - 1)) > 0) { 48.49 + *ss = c; 48.50 + ++ss; 48.51 + --n; 48.52 + } 48.53 + 48.54 + /* now do the aligned stores */ 48.55 + while (n >= sizeof (ulong)) { 48.56 + *(ulong *)ss = val; 48.57 + ss += sizeof (ulong); 48.58 + n -= sizeof (ulong); 48.59 + } 48.60 + } 48.61 + /* do that last unaligned bit */ 48.62 + while (n > 0) { 48.63 + *ss = c; 48.64 + ++ss; 48.65 + --n; 48.66 + 48.67 + } 48.68 + 48.69 + return s; 48.70 +}
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 49.2 +++ b/xen/arch/powerpc/of_handler/ofh.c Fri Jul 14 10:47:50 2006 +0100 49.3 @@ -0,0 +1,454 @@ 49.4 +/* 49.5 + * This program is free software; you can redistribute it and/or modify 49.6 + * it under the terms of the GNU General Public License as published by 49.7 + * the Free Software Foundation; either version 2 of the License, or 49.8 + * (at your option) any later version. 49.9 + * 49.10 + * This program is distributed in the hope that it will be useful, 49.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 49.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 49.13 + * GNU General Public License for more details. 49.14 + * 49.15 + * You should have received a copy of the GNU General Public License 49.16 + * along with this program; if not, write to the Free Software 49.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 49.18 + * 49.19 + * Copyright (C) IBM Corp. 2005 49.20 + * 49.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 49.22 + */ 49.23 + 49.24 +#include "ofh.h" 49.25 +#include <stdarg.h> 49.26 +#include <xen/lib.h> 49.27 + 49.28 +/* 49.29 + * 6.3.1 Access to the client interface functions 49.30 + * This is the spec'd maximum 49.31 + */ 49.32 +#define PFW_MAXSRVCLEN 31 49.33 + 49.34 +static u32 ofh_maxsrvclen; 49.35 + 49.36 +extern s32 debug(const char *fmt, ...); 49.37 + 49.38 +s32 debug(const char *fmt, ...) 49.39 +{ 49.40 + s32 sz; 49.41 + va_list ap; 49.42 + char buf[512]; 49.43 + va_start(ap, fmt); 49.44 + sz = vsnprintf(buf, 512, fmt, ap); 49.45 + va_end(ap); 49.46 + ofh_cons_write(buf, sz, &sz); 49.47 + 49.48 + return sz; 49.49 +} 49.50 + 49.51 + 49.52 + 49.53 +void 49.54 +assprint(const char *expr, const char *file, int line, const char *fmt, ...) 49.55 +{ 49.56 + char a[15]; 49.57 + 49.58 + a[0] = '\n'; 49.59 + a[1] = '\n'; 49.60 + a[2] = 'O'; 49.61 + a[3] = 'F'; 49.62 + a[4] = 'H'; 49.63 + a[5] = ':'; 49.64 + a[6] = 'A'; 49.65 + a[7] = 'S'; 49.66 + a[8] = 'S'; 49.67 + a[9] = 'E'; 49.68 + a[10] = 'R'; 49.69 + a[11] = 'T'; 49.70 + a[12] = '!'; 49.71 + a[13] = '\n'; 49.72 + a[14] = '\n'; 49.73 + 49.74 + s32 actual; 49.75 + u32 t = 1; 49.76 + volatile u32 *tp = &t; 49.77 + 49.78 + (void)expr; (void)file; (void)line; (void)fmt; 49.79 + 49.80 + ofh_cons_write(a, sizeof (a), &actual); 49.81 + 49.82 + /* maybe I can break out of this loop manually (like with a 49.83 + * debugger) */ 49.84 + while (*tp) { 49.85 + continue; 49.86 + } 49.87 +} 49.88 + 49.89 +/* 49.90 + * we use elf hash since it is pretty standard 49.91 + */ 49.92 +static u32 49.93 +of_hash(const char *s) 49.94 +{ 49.95 + u32 hash = 0; 49.96 + u32 hnib; 49.97 + 49.98 + if (s != NULL) { 49.99 + while (*s != '\0') { 49.100 + hash = (hash << 4) + *s++; 49.101 + hnib = hash & 0xf0000000UL; 49.102 + if (hnib != 0) { 49.103 + hash ^= hnib >> 24; 49.104 + } 49.105 + hash &= ~hnib; 49.106 + } 49.107 + } 49.108 + return hash; 49.109 +} 49.110 + 49.111 +static void 49.112 +ofh_service_init(ulong b) 49.113 +{ 49.114 + ulong sz; 49.115 + int i; 49.116 + int j = 0; 49.117 + struct ofh_srvc *o; 49.118 + struct ofh_srvc *ofs[] = { 49.119 + DRELA(&ofh_srvc[0], b), 49.120 + DRELA(&ofh_isa_srvc[0], b), 49.121 + NULL 49.122 + }; 49.123 + 49.124 + j = 0; 49.125 + while (ofs[j] != NULL) { 49.126 + /* find the maximum string length for services */ 49.127 + o = &ofs[j][0]; 49.128 + while (o->ofs_name != NULL) { 49.129 + const char *n; 49.130 + 49.131 + n = DRELA(&o->ofs_name[0], b); 49.132 + /* fix it up so we don't have to fix it anymore */ 49.133 + o->ofs_name = n; 49.134 + 49.135 + sz = strlen(n); 49.136 + if (sz > *DRELA(&ofh_maxsrvclen, b)) { 49.137 + *DRELA(&ofh_maxsrvclen, b) = sz; 49.138 + } 49.139 + o->ofs_hash = 49.140 + of_hash(n); 49.141 + ++i; 49.142 + ++o; 49.143 + } 49.144 + ++j; 49.145 + } 49.146 +} 49.147 + 49.148 + 49.149 +static void 49.150 +ofh_cpu_init(ofdn_t chosen, ulong b) 49.151 +{ 49.152 + static struct ofh_ihandle _ih_cpu_0; 49.153 + void *mem = ofd_mem(b); 49.154 + u32 ih = DRELA((ulong)&_ih_cpu_0, b); 49.155 + struct ofh_ihandle *ihp = (struct ofh_ihandle *)((ulong)ih); 49.156 + const char *cpu_type = DRELA((const char*)"cpu",b); 49.157 + 49.158 + ofdn_t cpu = ofd_node_find_by_prop(mem, OFD_ROOT, 49.159 + DRELA((const char*)"device_type",b), 49.160 + cpu_type, 4); 49.161 + ihp->ofi_node = cpu; 49.162 + ofd_prop_add(mem, chosen, DRELA((const char *)"cpu", b), 49.163 + &ih, sizeof (ih)); 49.164 +} 49.165 +static s32 49.166 +mmu_translate(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 49.167 +{ 49.168 + /* FIXME: need a little more here */ 49.169 + nargs = nargs; 49.170 + nrets = nrets; 49.171 + argp = argp; 49.172 + retp = retp; 49.173 + b = b; 49.174 + return OF_SUCCESS; 49.175 +} 49.176 + 49.177 +static void 49.178 +ofh_mmu_init(ofdn_t chosen, ulong b) 49.179 +{ 49.180 + static struct ofh_methods _mmu_methods[] = { 49.181 + { "translate", mmu_translate }, 49.182 + { NULL, NULL}, 49.183 + }; 49.184 + static struct ofh_ihandle _ih_mmu = { 49.185 + .ofi_methods = _mmu_methods, 49.186 + }; 49.187 + void *mem = ofd_mem(b); 49.188 + u32 ih = DRELA((ulong)&_ih_mmu, b); 49.189 + 49.190 + ofd_prop_add(mem, chosen, DRELA((const char *)"mmu", b), 49.191 + &ih, sizeof (ih)); 49.192 +} 49.193 + 49.194 +static void 49.195 +ofh_chosen_init(ulong b) 49.196 +{ 49.197 + ofdn_t ph; 49.198 + void *mem = ofd_mem(b); 49.199 + 49.200 + ph = ofd_node_find(mem, DRELA((const char *)"/chosen", b)); 49.201 + 49.202 + ofh_vty_init(ph, b); 49.203 + ofh_cpu_init(ph, b); 49.204 + ofh_mmu_init(ph, b); 49.205 +} 49.206 + 49.207 +static void 49.208 +ofh_options_init(ulong b) 49.209 +{ 49.210 + void *mem = ofd_mem(b); 49.211 + ofdn_t options; 49.212 + u32 size = 1 << 20; 49.213 + u32 base = b; 49.214 + char buf[20]; 49.215 + int i; 49.216 + 49.217 + 49.218 + /* fixup the ihandle */ 49.219 + options = ofd_node_find(mem, 49.220 + DRELA((const char *)"options", b)); 49.221 + 49.222 + i = snprintf(buf, sizeof (buf), "0x%x", base); 49.223 + ofd_prop_add(mem, options, DRELA((const char *)"real-base", b), 49.224 + buf, i); 49.225 + 49.226 + i = snprintf(buf,sizeof (buf), "0x%x", size); 49.227 + ofd_prop_add(mem, options, DRELA((const char *)"real-size", b), 49.228 + buf, i); 49.229 +} 49.230 + 49.231 +static void 49.232 +ofh_init(ulong b) 49.233 +{ 49.234 + ulong sz = (ulong)_end - (ulong)__bss_start; 49.235 + /* clear bss */ 49.236 + memset(__bss_start + b, 0, sz); 49.237 + 49.238 + ofh_service_init(b); 49.239 + ofh_chosen_init(b); 49.240 + ofh_options_init(b); 49.241 +} 49.242 + 49.243 +static ofh_func_t * 49.244 +ofh_lookup(const char *service, ulong b) 49.245 +{ 49.246 + int j; 49.247 + u32 hash; 49.248 + struct ofh_srvc *o; 49.249 + struct ofh_srvc *ofs[] = { 49.250 + DRELA(&ofh_srvc[0], b), 49.251 + DRELA(&ofh_isa_srvc[0], b), 49.252 + NULL 49.253 + }; 49.254 + u32 sz; 49.255 + 49.256 + sz = *DRELA(&ofh_maxsrvclen, b); 49.257 + 49.258 + if (strnlen(service, sz + 1) > sz) { 49.259 + return NULL; 49.260 + } 49.261 + 49.262 + hash = of_hash(service); 49.263 + 49.264 + j = 0; 49.265 + while (ofs[j] != NULL) { 49.266 + /* yes this could be quicker */ 49.267 + o = &ofs[j][0]; 49.268 + while (o->ofs_name != NULL) { 49.269 + if (o->ofs_hash == hash) { 49.270 + const char *n = o->ofs_name; 49.271 + if (strcmp(service, n) == 0) { 49.272 + return o->ofs_func; 49.273 + } 49.274 + } 49.275 + ++o; 49.276 + } 49.277 + ++j; 49.278 + } 49.279 + return NULL; 49.280 +} 49.281 + 49.282 +s32 49.283 +ofh_nosup(u32 nargs __attribute__ ((unused)), 49.284 + u32 nrets __attribute__ ((unused)), 49.285 + s32 argp[] __attribute__ ((unused)), 49.286 + s32 retp[] __attribute__ ((unused)), 49.287 + ulong b __attribute__ ((unused))) 49.288 +{ 49.289 + return OF_FAILURE; 49.290 +} 49.291 + 49.292 +s32 49.293 +ofh_test_method(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) 49.294 +{ 49.295 + if (nargs == 2) { 49.296 + if (nrets == 1) { 49.297 + s32 *ap = DRELA(&ofh_active_package, b); 49.298 + u32 service = (s32)argp[0]; 49.299 + const char *method = (const char *)(ulong)argp[1]; 49.300 + s32 *stat = &retp[0]; 49.301 + 49.302 + (void)ap; (void)service; (void)method; 49.303 + 49.304 + *stat = 0; 49.305 + /* we do not do this yet */ 49.306 + return OF_FAILURE; 49.307 + } 49.308 + } 49.309 + return OF_FAILURE; 49.310 +} 49.311 +extern u32 _ofh_inited[0]; 49.312 +extern u32 _ofh_lastarg[0]; 49.313 + 49.314 +s32 49.315 +ofh_handler(struct ofh_args *args, ulong b) 49.316 +{ 49.317 + u32 *inited = (u32 *)DRELA(&_ofh_inited[0],b); 49.318 + u32 *lastarg = (u32 *)DRELA(&_ofh_lastarg[0],b); 49.319 + ofh_func_t *f; 49.320 + 49.321 + if (*inited == 0) { 49.322 + ofh_init(b); 49.323 + 49.324 + if ((ulong)ofd_mem(b) < (ulong)_end + b) { 49.325 + static const char msg[] = "PANIC: OFD and BSS collide\n"; 49.326 + s32 dummy; 49.327 + 49.328 + ofh_cons_write(DRELA(&msg[0], b), sizeof (msg), &dummy); 49.329 + for (;;); 49.330 + } 49.331 + 49.332 + *inited = 1; 49.333 + } 49.334 + 49.335 + *lastarg = (ulong)args; 49.336 + 49.337 + f = ofh_lookup((char *)((ulong)args->ofa_service), b); 49.338 + 49.339 + if (f == ((ofh_func_t *)~0UL)) { 49.340 + /* do test */ 49.341 + if (args->ofa_nargs == 1) { 49.342 + if (args->ofa_nreturns == 1) { 49.343 + char *name = (char *)(ulong)args->ofa_args[0]; 49.344 + if (ofh_lookup(name, b) != NULL) { 49.345 + args->ofa_args[args->ofa_nargs] = 49.346 + OF_SUCCESS; 49.347 + return OF_SUCCESS; 49.348 + } 49.349 + } 49.350 + } 49.351 + return OF_FAILURE; 49.352 + 49.353 + } else if (f != NULL) { 49.354 + return leap(args->ofa_nargs, 49.355 + args->ofa_nreturns, 49.356 + args->ofa_args, 49.357 + &args->ofa_args[args->ofa_nargs], 49.358 + b, f); 49.359 + } 49.360 + return OF_FAILURE; 49.361 +} 49.362 + 49.363 +/* 49.364 + * The following code exists solely to run the handler code standalone 49.365 + */ 49.366 +void 49.367 +__ofh_start(void) 49.368 +{ 49.369 + s32 ret; 49.370 + u32 of_stdout; 49.371 + u32 ihandle; 49.372 + char buf[1024]; 49.373 + u32 args_buf[sizeof (struct ofh_args) + (sizeof (u32) * 10)]; 49.374 + struct ofh_args *args; 49.375 + 49.376 + args = (struct ofh_args *)args_buf; 49.377 + 49.378 + args->ofa_service = (u32)"finddevice"; 49.379 + args->ofa_nargs = 1; 49.380 + args->ofa_nreturns = 1; 49.381 + args->ofa_args[0] = (u32)"/"; 49.382 + args->ofa_args[1] = -1; 49.383 + ret = ofh_start(args); 49.384 + 49.385 + if (ret == OF_SUCCESS) { 49.386 + args->ofa_service = (u32)"finddevice"; 49.387 + args->ofa_nargs = 1; 49.388 + args->ofa_nreturns = 1; 49.389 + args->ofa_args[0] = (u32)"/chosen"; 49.390 + args->ofa_args[1] = -1; 49.391 + ret = ofh_start(args); 49.392 + } 49.393 + 49.394 + if (ret == OF_SUCCESS) { 49.395 + u32 phandle = args->ofa_args[1]; 49.396 + 49.397 + args->ofa_service = (u32)"getprop"; 49.398 + args->ofa_nargs = 4; 49.399 + args->ofa_nreturns = 1; 49.400 + args->ofa_args[0] = phandle; 49.401 + args->ofa_args[1] = (ulong)"stdout"; 49.402 + args->ofa_args[2] = (ulong)&of_stdout; 49.403 + args->ofa_args[3] = sizeof(of_stdout); 49.404 + args->ofa_args[4] = -1; 49.405 + ret = ofh_start(args); 49.406 + } 49.407 + 49.408 + ihandle = *(u32 *)((ulong)args->ofa_args[2]); 49.409 + 49.410 + if (ret == OF_SUCCESS) { 49.411 + /* instance to path */ 49.412 + args->ofa_service = (u32)"instance-to-path"; 49.413 + args->ofa_nargs = 3; 49.414 + args->ofa_nreturns = 1; 49.415 + args->ofa_args[0] = ihandle; 49.416 + args->ofa_args[1] = (ulong)buf; 49.417 + args->ofa_args[2] = sizeof (buf); 49.418 + args->ofa_args[3] = -1; 49.419 + ret = ofh_start(args); 49.420 + 49.421 + } 49.422 + 49.423 + if (ret == OF_SUCCESS) { 49.424 + /* open rtas */ 49.425 + args->ofa_service = (u32)"open"; 49.426 + args->ofa_nargs = 1; 49.427 + args->ofa_nreturns = 1; 49.428 + args->ofa_args[0] = (u32)"/rtas"; 49.429 + ret = ofh_start(args); 49.430 + if (ret == OF_SUCCESS) { 49.431 + u32 ir = args->ofa_args[1]; 49.432 + args->ofa_service = (u32)"call-method"; 49.433 + args->ofa_nargs = 3; 49.434 + args->ofa_nreturns = 2; 49.435 + args->ofa_args[0] = (ulong)"instantiate-rtas"; 49.436 + args->ofa_args[1] = ir; 49.437 + args->ofa_args[2] = (ulong)buf; 49.438 + 49.439 + ret = ofh_start(args); 49.440 + } 49.441 + } 49.442 + 49.443 + if (ret == OF_SUCCESS) { 49.444 + const char msg[] = "This is a test"; 49.445 + u32 msgsz = sizeof(msg) - 1; /* Includes \0 */ 49.446 + 49.447 + args->ofa_service = (u32)"write"; 49.448 + args->ofa_nargs = 3; 49.449 + args->ofa_nreturns = 1; 49.450 + args->ofa_args[0] = ihandle; 49.451 + args->ofa_args[1] = (ulong)msg; 49.452 + args->ofa_args[2] = msgsz; 49.453 + args->ofa_args[3] = -1; 49.454 + ret = ofh_start(args); 49.455 + } 49.456 + 49.457 +}
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 50.2 +++ b/xen/arch/powerpc/of_handler/ofh.h Fri Jul 14 10:47:50 2006 +0100 50.3 @@ -0,0 +1,164 @@ 50.4 +/* 50.5 + * This program is free software; you can redistribute it and/or modify 50.6 + * it under the terms of the GNU General Public License as published by 50.7 + * the Free Software Foundation; either version 2 of the License, or 50.8 + * (at your option) any later version. 50.9 + * 50.10 + * This program is distributed in the hope that it will be useful, 50.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 50.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 50.13 + * GNU General Public License for more details. 50.14 + * 50.15 + * You should have received a copy of the GNU General Public License 50.16 + * along with this program; if not, write to the Free Software 50.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 50.18 + * 50.19 + * Copyright (C) IBM Corp. 2005 50.20 + * 50.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 50.22 + */ 50.23 + 50.24 +#ifndef _PFW_H 50.25 +#define _PFW_H 50.26 + 50.27 +#include <xen/types.h> 50.28 +#include <public/xencomm.h> 50.29 +#include <public/io/console.h> 50.30 +#include <of-devtree.h> 50.31 + 50.32 +#define MIN(x,y) (((x)<(y))?(x):(y)) 50.33 + 50.34 +#define PAGE_SHIFT 12 50.35 +#define PAGE_SIZE (1UL<<PAGE_SHIFT) 50.36 + 50.37 +struct ofh_args { 50.38 + u32 ofa_service; 50.39 + u32 ofa_nargs; 50.40 + u32 ofa_nreturns; 50.41 + s32 ofa_args[0]; 50.42 +}; 50.43 + 50.44 +typedef s32 (ofh_func_t)(u32, u32, s32 [], s32 [], ulong b); 50.45 + 50.46 +struct ofh_srvc { 50.47 + const char *ofs_name; 50.48 + ofh_func_t *ofs_func; 50.49 + u32 ofs_hash; 50.50 +}; 50.51 + 50.52 +extern ofh_func_t ofh_test_method; 50.53 +extern ofh_func_t ofh_nosup; 50.54 + 50.55 +/* device tree */ 50.56 +extern ofh_func_t ofh_peer; 50.57 +extern ofh_func_t ofh_child; 50.58 +extern ofh_func_t ofh_parent; 50.59 +extern ofh_func_t ofh_instance_to_package; 50.60 +extern ofh_func_t ofh_getproplen; 50.61 +extern ofh_func_t ofh_getprop; 50.62 +extern ofh_func_t ofh_nextprop; 50.63 +extern ofh_func_t ofh_setprop; 50.64 +extern ofh_func_t ofh_canon; 50.65 +extern ofh_func_t ofh_finddevice; 50.66 +extern ofh_func_t ofh_instance_to_path; 50.67 +extern ofh_func_t ofh_package_to_path; 50.68 +extern ofh_func_t ofh_call_method; 50.69 + 50.70 +/* IO */ 50.71 +extern ofh_func_t ofh_open; 50.72 +extern ofh_func_t ofh_close; 50.73 +extern ofh_func_t ofh_read; 50.74 +extern ofh_func_t ofh_write; 50.75 +extern ofh_func_t ofh_seek; 50.76 + 50.77 +/* memory */ 50.78 +extern ofh_func_t ofh_claim; 50.79 +extern ofh_func_t ofh_release; 50.80 + 50.81 +/* control */ 50.82 +extern ofh_func_t ofh_boot; 50.83 +extern ofh_func_t ofh_enter; 50.84 +extern ofh_func_t ofh_exit; /* __attribute__ ((noreturn)); */ 50.85 +extern ofh_func_t ofh_chain; 50.86 +extern ofh_func_t ofh_quiesce; 50.87 + 50.88 +extern struct ofh_srvc ofh_srvc[]; 50.89 +extern struct ofh_srvc ofh_isa_srvc[]; 50.90 +extern s32 ofh_active_package; 50.91 + 50.92 +struct ofh_methods { 50.93 + const char *ofm_name; 50.94 + ofh_func_t *ofm_method; 50.95 +}; 50.96 + 50.97 +struct ofh_ihandle { 50.98 + s32 (*ofi_close)(void); 50.99 + s32 (*ofi_read)(s32 chan, void *buf, u32 count, s32 *actual, ulong b); 50.100 + s32 (*ofi_write)(s32 chan, const void *buf, u32 count, s32 *actual, 50.101 + ulong b); 50.102 + s32 (*ofi_seek)(u32 pos_hi, u32 pos_lo, u32 *status); 50.103 + struct ofh_methods *ofi_methods; 50.104 + struct xencons_interface *ofi_intf; 50.105 + s32 ofi_node; 50.106 + s32 ofi_chan; 50.107 +}; 50.108 + 50.109 +struct ofh_imem { 50.110 + s32 (*ofi_xlate)(void *addr, u32 ret[4]); 50.111 +}; 50.112 + 50.113 + 50.114 +enum prop_type { 50.115 + pt_byte_array, 50.116 + pt_value, 50.117 + pt_string, 50.118 + pt_composite, 50.119 + /* these are for our own use */ 50.120 + pt_func, 50.121 +}; 50.122 + 50.123 +extern s32 ofh_start(struct ofh_args *); 50.124 + 50.125 +#define OFH_CONS_XEN -1 50.126 +extern void ofh_cons_init(struct ofh_ihandle *ihp, ulong b); 50.127 +extern s32 ofh_cons_read(s32 chan, void *buf, u32 count, s32 *actual); 50.128 +extern s32 ofh_cons_write(const void *buf, u32 count, s32 *actual); 50.129 +extern s32 ofh_cons_close(void); 50.130 +extern s32 ofh_handler(struct ofh_args *args, ulong ifh_base); 50.131 +extern s32 leap(u32 nargs, u32 nrets, s32 args[], s32 rets[], 50.132 + ulong ba, void *f); 50.133 + 50.134 +extern s32 io_leap(s32 chan, void *buf, u32 sz, s32 *actual, 50.135 + ulong ba, void *f); 50.136 + 50.137 +extern void ofh_vty_init(ofdn_t chosen, ulong b); 50.138 +extern void ofh_rtas_init(ulong b); 50.139 + 50.140 +extern void *_ofh_tree; 50.141 + 50.142 +#if 1 50.143 +#define DRELA(p,b) ((__typeof__ (p))((((ulong)(p)) + (b)))) 50.144 +#else 50.145 +#define DRELA(p,b) (b == b ? p : 0) 50.146 +#endif 50.147 +extern ulong get_base(void); 50.148 + 50.149 +static inline void *ofd_mem(ulong base) { return *DRELA(&_ofh_tree, base); } 50.150 + 50.151 +extern ofh_func_t ofh_start_cpu; 50.152 +extern ofh_func_t ofh_stop_self; 50.153 +extern ofh_func_t ofh_idle_self; 50.154 +extern ofh_func_t ofh_resume_cpu; 50.155 + 50.156 +/* In Open Firmware, we only use xencomm for reading/writing console data. 50.157 + * Since that's always small, we can use this fixed-size structure. */ 50.158 +#define XENCOMM_MINI_ADDRS 3 50.159 +struct xencomm_mini { 50.160 + struct xencomm_desc _desc; 50.161 + u64 address[XENCOMM_MINI_ADDRS]; 50.162 +}; 50.163 + 50.164 +extern int xencomm_create_mini(void *area, int arealen, void *buffer, 50.165 + unsigned long bytes, struct xencomm_desc **ret); 50.166 + 50.167 +#endif
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 51.2 +++ b/xen/arch/powerpc/of_handler/papr.S Fri Jul 14 10:47:50 2006 +0100 51.3 @@ -0,0 +1,97 @@ 51.4 +/* 51.5 + * Copyright (C) 2005 Jimi Xenidis <jimix@watson.ibm.com>, IBM Corporation 51.6 + * 51.7 + * This program is free software; you can redistribute it and/or modify 51.8 + * it under the terms of the GNU General Public License as published by 51.9 + * the Free Software Foundation; either version 2 of the License, or 51.10 + * (at your option) any later version. 51.11 + * 51.12 + * This program is distributed in the hope that it will be useful, 51.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 51.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 51.15 + * GNU General Public License for more details. 51.16 + * 51.17 + * You should have received a copy of the GNU General Public License 51.18 + * along with this program; if not, write to the Free Software 51.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 51.20 + */ 51.21 + 51.22 +#include <asm/config.h> 51.23 +#include <asm/processor.h> 51.24 +#include <asm/papr.h> 51.25 +#include <asm/asm-offsets.h> 51.26 + 51.27 +#define HSC .long 0x44000022 51.28 + 51.29 + 51.30 +/* in is unsused */ 51.31 +#define PAPR(in, out, name, func_code) \ 51.32 + _GLOBAL(name); \ 51.33 + std r3,-GPR_WIDTH(r1); \ 51.34 + li r3,func_code; \ 51.35 + HSC; \ 51.36 + ld r12,-GPR_WIDTH(r1); \ 51.37 + cmpi 0,r12,0; \ 51.38 + bne ret ## out; /* only store regs if r12 != NULL */ \ 51.39 + b ret0 51.40 + 51.41 +ret8: std r11, 7 * GPR_WIDTH(r12) 51.42 +ret7: std r10, 6 * GPR_WIDTH(r12) 51.43 +ret6: std r9, 5 * GPR_WIDTH(r12) 51.44 +ret5: std r8, 4 * GPR_WIDTH(r12) 51.45 +ret4: std r7, 3 * GPR_WIDTH(r12) 51.46 +ret3: std r6, 2 * GPR_WIDTH(r12) 51.47 +ret2: std r5, 1 * GPR_WIDTH(r12) 51.48 +ret1: std r4, 0 * GPR_WIDTH(r12) 51.49 + nop 51.50 +ret0: blr 51.51 + 51.52 +PAPR(5, 2,papr_remove, H_REMOVE) 51.53 +PAPR(5, 1,papr_clear_mod, H_CLEAR_MOD) 51.54 +PAPR(5, 1,papr_clear_ref, H_CLEAR_REF) 51.55 +PAPR(5, 0,papr_protect, H_PROTECT) 51.56 +PAPR(1, 0,papr_eoi, H_EOI) 51.57 +PAPR(5, 1,papr_cppr, H_CPPR) 51.58 +PAPR(5, 2,papr_ipi, H_IPI) 51.59 +PAPR(5, 1,papr_ipoll, H_IPOLL) 51.60 +PAPR(5, 1,papr_xirr, H_XIRR) 51.61 +PAPR(2, 0,papr_interrupt, H_INTERRUPT) 51.62 +PAPR(5, 1,papr_logical_ci_load_64, H_LOGICAL_CI_LOAD) 51.63 +PAPR(5, 0,papr_logical_ci_store_64, H_LOGICAL_CI_STORE) 51.64 +PAPR(5, 1,papr_logical_cache_load_64, H_LOGICAL_CACHE_LOAD) 51.65 +PAPR(5, 0,papr_logical_cache_store_64, H_LOGICAL_CACHE_STORE) 51.66 +PAPR(5, 0,papr_logical_icbi, H_LOGICAL_ICBI) 51.67 +PAPR(5, 0,papr_logical_dcbf, H_LOGICAL_DCBF) 51.68 +PAPR(5, 1,papr_set_dabr, H_SET_DABR) 51.69 +PAPR(5, 1,papr_real_to_logical, H_REAL_TO_LOGICAL) 51.70 +PAPR(5, 1,papr_pci_config_read, H_PCI_CONFIG_READ) 51.71 +PAPR(5, 0,papr_pci_config_write, H_PCI_CONFIG_WRITE) 51.72 + 51.73 + PAPR(5, 1,papr_grant_logical, H_GRANT_LOGICAL) 51.74 +PAPR(1, 1,papr_accept_logical, H_ACCEPT_LOGICAL) 51.75 +PAPR(0, 2,papr_rescind_logical, H_RESCIND_LOGICAL) 51.76 +PAPR(3, 0,papr_register_vterm, H_REGISTER_VTERM) 51.77 +PAPR(4, 0,papr_vterm_partner_info, H_VTERM_PARTNER_INFO) 51.78 +PAPR(1, 0,papr_free_vterm, H_FREE_VTERM) 51.79 + 51.80 +/* Definitions for hypervisor functions. Note that we do not use the 51.81 + * first macro arg */ 51.82 + 51.83 +PAPR(x, 1,papr_enter, H_ENTER) 51.84 +PAPR(x, 8,papr_read, H_READ) 51.85 +PAPR(x, 1,papr_thread_control, H_THREAD_CONTROL) 51.86 +PAPR(x, 0,papr_cede, H_CEDE) 51.87 + 51.88 +PAPR(x, 0,papr_page_init, H_PAGE_INIT) 51.89 +PAPR(x, 1,papr_set_asr, H_SET_ASR) /* ISTAR only. */ 51.90 +PAPR(x, 0,papr_asr_on, H_ASR_ON) /* ISTAR only. */ 51.91 +PAPR(x, 0,papr_asr_off, H_ASR_OFF) /* ISTAR only. */ 51.92 + 51.93 +PAPR(x, 8,papr_hypervisor_data, H_HYPERVISOR_DATA) 51.94 + 51.95 +PAPR(x, 2,papr_get_xive, H_GET_XIVE) 51.96 +PAPR(x, 0,papr_set_xive, H_SET_XIVE) 51.97 + 51.98 + 51.99 +PAPR(x, 0,papr_put_term_char, H_PUT_TERM_CHAR) 51.100 +PAPR(x, 3,papr_get_term_char, H_GET_TERM_CHAR)
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 52.2 +++ b/xen/arch/powerpc/of_handler/papr.h Fri Jul 14 10:47:50 2006 +0100 52.3 @@ -0,0 +1,69 @@ 52.4 +/* 52.5 + * This program is free software; you can redistribute it and/or modify 52.6 + * it under the terms of the GNU General Public License as published by 52.7 + * the Free Software Foundation; either version 2 of the License, or 52.8 + * (at your option) any later version. 52.9 + * 52.10 + * This program is distributed in the hope that it will be useful, 52.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 52.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 52.13 + * GNU General Public License for more details. 52.14 + * 52.15 + * You should have received a copy of the GNU General Public License 52.16 + * along with this program; if not, write to the Free Software 52.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 52.18 + * 52.19 + * Copyright (C) IBM Corp. 2005 52.20 + * 52.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 52.22 + */ 52.23 + 52.24 +#ifndef _OFH_PAPR_H 52.25 +#define _OFH_PAPR_H 52.26 + 52.27 +#include <asm/papr.h> 52.28 + 52.29 +#ifndef __ASSEMBLY__ 52.30 + 52.31 +extern long papr_enter(ulong *retvals, ulong flags, ulong idx, ...); 52.32 +extern long papr_read(ulong *retvals, ulong flags, ulong idx); 52.33 +extern long papr_remove(ulong *retvals, ulong flags, ulong pte_index, 52.34 + ulong avpn); 52.35 +extern long papr_clear_mod(ulong *retvals, ulong flags, ulong pte_index); 52.36 +extern long papr_clear_ref(ulong *retvals, ulong flags, ulong pte_index); 52.37 +extern long papr_protect(ulong *retvals, ulong flags, ulong pte_index, 52.38 + ulong avpn); 52.39 +extern long papr_get_term_char(ulong *retvals, ulong idx); 52.40 +extern long papr_put_term_char(ulong *retvals, ulong idx, ulong count, ...); 52.41 +extern long papr_register_vterm(ulong *retvals, ulong ua, ulong plpid, ulong pua); 52.42 +extern long papr_vterm_partner_info(ulong *retvals, ulong ua, ulong plpid, 52.43 + ulong pua, ulong lpage); 52.44 +extern long papr_free_vterm(ulong *retvals, ulong uaddr); 52.45 + 52.46 +extern long papr_cede(ulong *retvals); 52.47 +extern long papr_page_init(ulong *retvals, ulong flags, 52.48 + ulong destination, ulong source); 52.49 +extern long papr_set_asr(ulong *retvals, ulong value); /* ISTAR only. */ 52.50 +extern long papr_asr_on(ulong *retvals); /* ISTAR only. */ 52.51 +extern long papr_asr_off(ulong *retvals); /* ISTAR only. */ 52.52 +extern long papr_eoi(ulong *retvals, ulong xirr); 52.53 +extern long papr_cppr(ulong *retvals, ulong cppr); 52.54 +extern long papr_ipi(ulong *retvals, ulong sn, ulong mfrr); 52.55 +extern long papr_ipoll(ulong *retvals, ulong sn); 52.56 +extern long papr_xirr(ulong *retvals); 52.57 +extern long papr_logical_ci_load_64(ulong *retvals, ulong size, 52.58 + ulong addrAndVal); 52.59 +extern long papr_logical_ci_store_64(ulong *retvals, ulong size, 52.60 + ulong addr, ulong value); 52.61 +extern long papr_logical_cache_load_64(ulong *retvals, ulong size, 52.62 + ulong addrAndVal); 52.63 +extern long papr_logical_cache_store_64(ulong *retvals, ulong size, 52.64 + ulong addr, ulong value); 52.65 +extern long papr_logical_icbi(ulong *retvals, ulong addr); 52.66 +extern long papr_logical_dcbf(ulong *retvals, ulong addr); 52.67 +extern long papr_set_dabr(ulong *retvals, ulong dabr); 52.68 +extern long papr_hypervisor_data(ulong *retvals, u64 control); 52.69 +extern long papr_real_to_logical(ulong *retvals, ulong raddr); 52.70 + 52.71 +#endif /* ! __ASSEMBLY__ */ 52.72 +#endif /* ! _OFH_PAPR_H */
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 53.2 +++ b/xen/arch/powerpc/of_handler/services.c Fri Jul 14 10:47:50 2006 +0100 53.3 @@ -0,0 +1,96 @@ 53.4 +/* 53.5 + * This program is free software; you can redistribute it and/or modify 53.6 + * it under the terms of the GNU General Public License as published by 53.7 + * the Free Software Foundation; either version 2 of the License, or 53.8 + * (at your option) any later version. 53.9 + * 53.10 + * This program is distributed in the hope that it will be useful, 53.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 53.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 53.13 + * GNU General Public License for more details. 53.14 + * 53.15 + * You should have received a copy of the GNU General Public License 53.16 + * along with this program; if not, write to the Free Software 53.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 53.18 + * 53.19 + * Copyright (C) IBM Corp. 2005 53.20 + * 53.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 53.22 + */ 53.23 + 53.24 +#include "ofh.h" 53.25 + 53.26 +/* 53.27 + * These are ISA independent OF services 53.28 + */ 53.29 + 53.30 +struct ofh_srvc ofh_srvc[] = { 53.31 + /* Document Section 6.3.2.1 Client Interface */ 53.32 + { .ofs_name = "test", .ofs_func = ((ofh_func_t *)~0UL) }, 53.33 + { .ofs_name = "test-method", .ofs_func = ofh_test_method }, 53.34 + 53.35 + /* Document Section 6.3.2.2 Device Tree */ 53.36 + { .ofs_name = "peer", .ofs_func = ofh_peer }, 53.37 + { .ofs_name = "child", .ofs_func = ofh_child }, 53.38 + { .ofs_name = "parent", .ofs_func = ofh_parent }, 53.39 + { .ofs_name = "instance-to-package", 53.40 + .ofs_func = ofh_instance_to_package }, 53.41 + { .ofs_name = "getproplen", .ofs_func = ofh_getproplen }, 53.42 + { .ofs_name = "getprop", .ofs_func = ofh_getprop }, 53.43 + { .ofs_name = "nextprop", .ofs_func = ofh_nextprop }, 53.44 + { .ofs_name = "setprop", .ofs_func = ofh_setprop }, 53.45 + { .ofs_name = "canon", .ofs_func = ofh_canon }, 53.46 + { .ofs_name = "finddevice", .ofs_func = ofh_finddevice }, 53.47 + { .ofs_name = "instance-to-path", .ofs_func = ofh_instance_to_path }, 53.48 + { .ofs_name = "package-to-path", .ofs_func = ofh_package_to_path }, 53.49 + { .ofs_name = "call-method", .ofs_func = ofh_call_method }, 53.50 + 53.51 + /* Document Section 6.3.2.3 Device I/O */ 53.52 + { .ofs_name = "open", .ofs_func = ofh_open }, 53.53 + { .ofs_name = "close", .ofs_func = ofh_close }, 53.54 + { .ofs_name = "read", .ofs_func = ofh_read }, 53.55 + { .ofs_name = "write", .ofs_func = ofh_write }, 53.56 + { .ofs_name = "seek", .ofs_func = ofh_seek }, 53.57 + 53.58 + /* Document Section 6.3.2.4 Memory */ 53.59 + { .ofs_name = "claim", .ofs_func = ofh_claim }, 53.60 + { .ofs_name = "release", .ofs_func = ofh_release }, 53.61 + 53.62 + /* Document Section 6.3.2.5 Control Transfer */ 53.63 + { .ofs_name = "boot", .ofs_func = ofh_boot }, 53.64 + { .ofs_name = "enter", .ofs_func = ofh_enter }, 53.65 + { .ofs_name = "exit", .ofs_func = ofh_exit }, 53.66 + { .ofs_name = "chain", .ofs_func = ofh_chain }, 53.67 + { .ofs_name = "quiesce", .ofs_func = ofh_quiesce }, 53.68 + 53.69 + /* Document Section 6.3.2.6 User Interface */ 53.70 + { .ofs_name = "interpret", .ofs_func = ofh_nosup }, 53.71 + { .ofs_name = "set-callback", .ofs_func = ofh_nosup }, 53.72 + { .ofs_name = "set-symbol-lookup", .ofs_func = ofh_nosup }, 53.73 + 53.74 + /* Document Section 6.3.2.7 Time */ 53.75 + { .ofs_name = "milliseconds", .ofs_func = ofh_nosup }, 53.76 + { .ofs_name = NULL, .ofs_func = NULL} 53.77 +}; 53.78 + 53.79 +/* 53.80 + * These are services particular to poweprc 32/64 53.81 + */ 53.82 + 53.83 +struct ofh_srvc ofh_isa_srvc[] = { 53.84 + /* Document Section 8.5.1 Real-Mode physical memory ... */ 53.85 + { .ofs_name = "alloc-real_mem", .ofs_func = ofh_nosup }, 53.86 + 53.87 + /* Document Section 8.5.2 Virtual address translation ... */ 53.88 + { .ofs_name = "map", .ofs_func = ofh_nosup }, 53.89 + { .ofs_name = "unmap", .ofs_func = ofh_nosup }, 53.90 + { .ofs_name = "translate", .ofs_func = ofh_nosup }, 53.91 + 53.92 + /* Document Section 11.3 Client Interface Services */ 53.93 + { .ofs_name = "start-cpu", .ofs_func = ofh_start_cpu }, 53.94 + { .ofs_name = "stop-self", .ofs_func = ofh_stop_self }, 53.95 + { .ofs_name = "idle-self", .ofs_func = ofh_idle_self }, 53.96 + { .ofs_name = "resume-cpu", .ofs_func = ofh_resume_cpu }, 53.97 + { .ofs_name = NULL, .ofs_func = NULL} 53.98 +}; 53.99 +
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 54.2 +++ b/xen/arch/powerpc/of_handler/snprintf.c Fri Jul 14 10:47:50 2006 +0100 54.3 @@ -0,0 +1,332 @@ 54.4 +/* 54.5 + * This program is free software; you can redistribute it and/or modify 54.6 + * it under the terms of the GNU General Public License as published by 54.7 + * the Free Software Foundation; either version 2 of the License, or 54.8 + * (at your option) any later version. 54.9 + * 54.10 + * This program is distributed in the hope that it will be useful, 54.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 54.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 54.13 + * GNU General Public License for more details. 54.14 + * 54.15 + * You should have received a copy of the GNU General Public License 54.16 + * along with this program; if not, write to the Free Software 54.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 54.18 + * 54.19 + * Copyright (C) IBM Corp. 2005 54.20 + * 54.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com> 54.22 + */ 54.23 + 54.24 +#include <xen/types.h> 54.25 +#include <stdarg.h> 54.26 + 54.27 +#define UPPER 0x00001 54.28 +#define SIGNED 0x00010 54.29 +#define ZERO 0x00100 54.30 +#define PTR 0x01000 54.31 + 54.32 +#define NUMBUFSZ 24 /* fits a 64bit value formatted in octal */ 54.33 + 54.34 +/* do we need to handle 128 bits? */ 54.35 +static ulong 54.36 +digits(char *buf, uint64_t val, ulong radix, ulong width, ulong flgs) 54.37 +{ 54.38 + const char hex[] = "0123456789abcdefx"; 54.39 + const char Hex[] = "0123456789ABCDEFX"; 54.40 + const char *dig; 54.41 + char *b = buf; 54.42 + char num[NUMBUFSZ]; 54.43 + ulong i; 54.44 + 54.45 + if (radix == 0 || radix > 16) { 54.46 + radix = 16; 54.47 + } 54.48 + 54.49 + if (flgs & UPPER) { 54.50 + dig = Hex; 54.51 + } else { 54.52 + dig = hex; 54.53 + } 54.54 + 54.55 + /* sign */ 54.56 + if (flgs & SIGNED && radix == 10) { 54.57 + /* there are corner cases here, for sure */ 54.58 + if ((int64_t)val < 0) { 54.59 + *b++ = '-'; 54.60 + val *= -1; 54.61 + } 54.62 + } 54.63 + 54.64 + /* ptr */ 54.65 + if (flgs & PTR && radix == 16) { 54.66 + *b++ = '0'; 54.67 + *b++ = dig[16]; 54.68 + } 54.69 + 54.70 + /* put it in t backwards */ 54.71 + i = 0; 54.72 + if (val == 0) { 54.73 + num[i++] = '0'; 54.74 + } else { 54.75 + while (val > 0) { 54.76 + num[i++] = dig[val % radix]; 54.77 + val /= radix; 54.78 + } 54.79 + } 54.80 + 54.81 + /* pad */ 54.82 + if (flgs & ZERO && width > i) { 54.83 + while (width-- > i) { 54.84 + *b++ = '0'; 54.85 + } 54.86 + } 54.87 + 54.88 + /* number */ 54.89 + while (i-- > 0) { 54.90 + *b++ = num[i]; 54.91 + } 54.92 + 54.93 + return (b - buf); 54.94 +} 54.95 + 54.96 +/* 54.97 + * yeah, I dislike goto's too, but ... 54.98 + */ 54.99 +int 54.100 +vsnprintf(char *buf, size_t size, const char *fmt, va_list ap) 54.101 +{ 54.102 + int c; 54.103 + int nullify; 54.104 + ulong used = 0; 54.105 + ulong sz; 54.106 + unsigned ells; 54.107 + ulong flgs; 54.108 + const char *str; 54.109 + uint64_t val = 0; 54.110 + ulong radix; 54.111 + ulong width; 54.112 + char num[NUMBUFSZ]; 54.113 + 54.114 + /* there must always be a trailing null */ 54.115 + if (size == 0) { 54.116 + /* but don't write anything is size is zero */ 54.117 + nullify = 0; 54.118 + } else { 54.119 + --size; 54.120 + nullify = 1; 54.121 + } 54.122 + 54.123 + while ((c = *fmt++) != '\0') { 54.124 + if (c != '%') { 54.125 + if (used++ < size) { 54.126 + *buf++ = c; 54.127 + } 54.128 + continue; 54.129 + } 54.130 + /* deal with format */ 54.131 + ells = 0; 54.132 + flgs = 0; 54.133 + 54.134 + /* check for a given width */ 54.135 + width = 0; 54.136 + 54.137 + c = *fmt; 54.138 + if (c >= '0' && c <= '9') { 54.139 + flgs |= ZERO; 54.140 + ++fmt; 54.141 + while (c >= '0' && c <= '9') { 54.142 + width = (width * 10) + (c - '0'); 54.143 + c = *fmt++; 54.144 + } 54.145 + --fmt; 54.146 + } 54.147 + 54.148 +loop: 54.149 + c = *fmt++; 54.150 + switch (c) { 54.151 + case 'l': 54.152 + ++ells; 54.153 + goto loop; 54.154 + /*NOTREACHED*/ 54.155 + break; 54.156 + 54.157 + case 'h': /* support linux kernel 'h' for short */ 54.158 + ells = 0; 54.159 + goto loop; 54.160 + /*NOTREACHED*/ 54.161 + break; 54.162 + 54.163 + case 'L': /* support linux kernel 'L' for long long */ 54.164 + ells = 2; 54.165 + goto loop; 54.166 + /*NOTREACHED*/ 54.167