machdep.c revision 266003
1/*- 2 * Copyright (C) 2006-2012 Semihalf 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 17 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 19 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25/*- 26 * Copyright (C) 2001 Benno Rice 27 * All rights reserved. 28 * 29 * Redistribution and use in source and binary forms, with or without 30 * modification, are permitted provided that the following conditions 31 * are met: 32 * 1. Redistributions of source code must retain the above copyright 33 * notice, this list of conditions and the following disclaimer. 34 * 2. Redistributions in binary form must reproduce the above copyright 35 * notice, this list of conditions and the following disclaimer in the 36 * documentation and/or other materials provided with the distribution. 37 * 38 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR 39 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 40 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 41 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 43 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 44 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 45 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 46 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 47 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 48 * $NetBSD: machdep.c,v 1.74.2.1 2000/11/01 16:13:48 tv Exp $ 49 */ 50/*- 51 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 52 * Copyright (C) 1995, 1996 TooLs GmbH. 53 * All rights reserved. 54 * 55 * Redistribution and use in source and binary forms, with or without 56 * modification, are permitted provided that the following conditions 57 * are met: 58 * 1. Redistributions of source code must retain the above copyright 59 * notice, this list of conditions and the following disclaimer. 60 * 2. Redistributions in binary form must reproduce the above copyright 61 * notice, this list of conditions and the following disclaimer in the 62 * documentation and/or other materials provided with the distribution. 63 * 3. All advertising materials mentioning features or use of this software 64 * must display the following acknowledgement: 65 * This product includes software developed by TooLs GmbH. 66 * 4. The name of TooLs GmbH may not be used to endorse or promote products 67 * derived from this software without specific prior written permission. 68 * 69 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 70 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 71 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 72 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 73 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 74 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 75 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 76 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 77 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 78 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 79 */ 80 81#include <sys/cdefs.h> 82__FBSDID("$FreeBSD: stable/10/sys/powerpc/booke/machdep.c 266003 2014-05-14 04:14:58Z ian $"); 83 84#include "opt_compat.h" 85#include "opt_ddb.h" 86#include "opt_kstack_pages.h" 87#include "opt_platform.h" 88 89#include <sys/cdefs.h> 90#include <sys/types.h> 91#include <sys/param.h> 92#include <sys/proc.h> 93#include <sys/systm.h> 94#include <sys/time.h> 95#include <sys/bio.h> 96#include <sys/buf.h> 97#include <sys/bus.h> 98#include <sys/cons.h> 99#include <sys/cpu.h> 100#include <sys/kdb.h> 101#include <sys/kernel.h> 102#include <sys/lock.h> 103#include <sys/mutex.h> 104#include <sys/rwlock.h> 105#include <sys/sysctl.h> 106#include <sys/exec.h> 107#include <sys/ktr.h> 108#include <sys/syscallsubr.h> 109#include <sys/sysproto.h> 110#include <sys/signalvar.h> 111#include <sys/sysent.h> 112#include <sys/imgact.h> 113#include <sys/msgbuf.h> 114#include <sys/ptrace.h> 115 116#include <vm/vm.h> 117#include <vm/pmap.h> 118#include <vm/vm_page.h> 119#include <vm/vm_object.h> 120#include <vm/vm_pager.h> 121 122#include <machine/cpu.h> 123#include <machine/kdb.h> 124#include <machine/reg.h> 125#include <machine/vmparam.h> 126#include <machine/spr.h> 127#include <machine/hid.h> 128#include <machine/psl.h> 129#include <machine/trap.h> 130#include <machine/md_var.h> 131#include <machine/mmuvar.h> 132#include <machine/sigframe.h> 133#include <machine/machdep.h> 134#include <machine/metadata.h> 135#include <machine/platform.h> 136 137#include <sys/linker.h> 138#include <sys/reboot.h> 139 140#include <contrib/libfdt/libfdt.h> 141#include <dev/fdt/fdt_common.h> 142#include <dev/ofw/openfirm.h> 143 144#ifdef DDB 145extern vm_offset_t ksym_start, ksym_end; 146#endif 147 148#ifdef DEBUG 149#define debugf(fmt, args...) printf(fmt, ##args) 150#else 151#define debugf(fmt, args...) 152#endif 153 154extern unsigned char kernel_text[]; 155extern unsigned char _etext[]; 156extern unsigned char _edata[]; 157extern unsigned char __bss_start[]; 158extern unsigned char __sbss_start[]; 159extern unsigned char __sbss_end[]; 160extern unsigned char _end[]; 161 162/* 163 * Bootinfo is passed to us by legacy loaders. Save the address of the 164 * structure to handle backward compatibility. 165 */ 166uint32_t *bootinfo; 167 168struct kva_md_info kmi; 169struct pcpu __pcpu[MAXCPU]; 170struct trapframe frame0; 171int cold = 1; 172long realmem = 0; 173long Maxmem = 0; 174char machine[] = "powerpc"; 175SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); 176 177int cacheline_size = 32; 178 179SYSCTL_INT(_machdep, CPU_CACHELINE, cacheline_size, 180 CTLFLAG_RD, &cacheline_size, 0, ""); 181 182int hw_direct_map = 0; 183 184static void cpu_booke_startup(void *); 185SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_booke_startup, NULL); 186 187void print_kernel_section_addr(void); 188void print_kenv(void); 189u_int booke_init(uint32_t, uint32_t); 190 191extern int elf32_nxstack; 192 193static void 194cpu_booke_startup(void *dummy) 195{ 196 int indx; 197 unsigned long size; 198 199 /* Initialise the decrementer-based clock. */ 200 decr_init(); 201 202 /* Good {morning,afternoon,evening,night}. */ 203 cpu_setup(PCPU_GET(cpuid)); 204 205 printf("real memory = %lu (%ld MB)\n", ptoa(physmem), 206 ptoa(physmem) / 1048576); 207 realmem = physmem; 208 209 /* Display any holes after the first chunk of extended memory. */ 210 if (bootverbose) { 211 printf("Physical memory chunk(s):\n"); 212 for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) { 213 size = phys_avail[indx + 1] - phys_avail[indx]; 214 215 printf("0x%08x - 0x%08x, %lu bytes (%lu pages)\n", 216 phys_avail[indx], phys_avail[indx + 1] - 1, 217 size, size / PAGE_SIZE); 218 } 219 } 220 221 vm_ksubmap_init(&kmi); 222 223 printf("avail memory = %lu (%ld MB)\n", ptoa(cnt.v_free_count), 224 ptoa(cnt.v_free_count) / 1048576); 225 226 /* Set up buffers, so they can be used to read disk labels. */ 227 bufinit(); 228 vm_pager_bufferinit(); 229 230 /* Cpu supports execution permissions on the pages. */ 231 elf32_nxstack = 1; 232} 233 234static char * 235kenv_next(char *cp) 236{ 237 238 if (cp != NULL) { 239 while (*cp != 0) 240 cp++; 241 cp++; 242 if (*cp == 0) 243 cp = NULL; 244 } 245 return (cp); 246} 247 248void 249print_kenv(void) 250{ 251 int len; 252 char *cp; 253 254 debugf("loader passed (static) kenv:\n"); 255 if (kern_envp == NULL) { 256 debugf(" no env, null ptr\n"); 257 return; 258 } 259 debugf(" kern_envp = 0x%08x\n", (u_int32_t)kern_envp); 260 261 len = 0; 262 for (cp = kern_envp; cp != NULL; cp = kenv_next(cp)) 263 debugf(" %x %s\n", (u_int32_t)cp, cp); 264} 265 266void 267print_kernel_section_addr(void) 268{ 269 270 debugf("kernel image addresses:\n"); 271 debugf(" kernel_text = 0x%08x\n", (uint32_t)kernel_text); 272 debugf(" _etext (sdata) = 0x%08x\n", (uint32_t)_etext); 273 debugf(" _edata = 0x%08x\n", (uint32_t)_edata); 274 debugf(" __sbss_start = 0x%08x\n", (uint32_t)__sbss_start); 275 debugf(" __sbss_end = 0x%08x\n", (uint32_t)__sbss_end); 276 debugf(" __sbss_start = 0x%08x\n", (uint32_t)__bss_start); 277 debugf(" _end = 0x%08x\n", (uint32_t)_end); 278} 279 280static int 281booke_check_for_fdt(uint32_t arg1, vm_offset_t *dtbp) 282{ 283 void *ptr; 284 285 if (arg1 % 8 != 0) 286 return (-1); 287 288 ptr = (void *)pmap_early_io_map(arg1, PAGE_SIZE); 289 if (fdt_check_header(ptr) != 0) 290 return (-1); 291 292 *dtbp = (vm_offset_t)ptr; 293 294 return (0); 295} 296 297u_int 298booke_init(uint32_t arg1, uint32_t arg2) 299{ 300 struct pcpu *pc; 301 void *kmdp, *mdp; 302 vm_offset_t dtbp, end; 303 304 kmdp = NULL; 305 306 end = (uintptr_t)_end; 307 dtbp = (vm_offset_t)NULL; 308 309 /* Set up TLB initially */ 310 bootinfo = NULL; 311 tlb1_init(); 312 313 /* 314 * Handle the various ways we can get loaded and started: 315 * - FreeBSD's loader passes the pointer to the metadata 316 * in arg1, with arg2 undefined. arg1 has a value that's 317 * relative to the kernel's link address (i.e. larger 318 * than 0xc0000000). 319 * - Juniper's loader passes the metadata pointer in arg2 320 * and sets arg1 to zero. This is to signal that the 321 * loader maps the kernel and starts it at its link 322 * address (unlike the FreeBSD loader). 323 * - U-Boot passes the standard argc and argv parameters 324 * in arg1 and arg2 (resp). arg1 is between 1 and some 325 * relatively small number, such as 64K. arg2 is the 326 * physical address of the argv vector. 327 * - ePAPR loaders pass an FDT blob in r3 (arg1) and the magic hex 328 * string 0x45504150 ('ePAP') in r6 (which has been lost by now). 329 * r4 (arg2) is supposed to be set to zero, but is not always. 330 */ 331 332 if (arg1 == 0) /* Juniper loader */ 333 mdp = (void *)arg2; 334 else if (booke_check_for_fdt(arg1, &dtbp) == 0) { /* ePAPR */ 335 end = roundup(end, 8); 336 memmove((void *)end, (void *)dtbp, fdt_totalsize((void *)dtbp)); 337 dtbp = end; 338 end += fdt_totalsize((void *)dtbp); 339 mdp = NULL; 340 } else if (arg1 > (uintptr_t)kernel_text) /* FreeBSD loader */ 341 mdp = (void *)arg1; 342 else /* U-Boot */ 343 mdp = NULL; 344 345 /* 346 * Parse metadata and fetch parameters. 347 */ 348 if (mdp != NULL) { 349 preload_metadata = mdp; 350 kmdp = preload_search_by_type("elf kernel"); 351 if (kmdp != NULL) { 352 boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); 353 kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); 354 dtbp = MD_FETCH(kmdp, MODINFOMD_DTBP, vm_offset_t); 355 end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t); 356 357 bootinfo = (uint32_t *)preload_search_info(kmdp, 358 MODINFO_METADATA | MODINFOMD_BOOTINFO); 359 360#ifdef DDB 361 ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t); 362 ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t); 363#endif 364 } 365 } else { 366 bzero(__sbss_start, __sbss_end - __sbss_start); 367 bzero(__bss_start, _end - __bss_start); 368 } 369 370#if defined(FDT_DTB_STATIC) 371 /* 372 * In case the device tree blob was not retrieved (from metadata) try 373 * to use the statically embedded one. 374 */ 375 if (dtbp == (vm_offset_t)NULL) 376 dtbp = (vm_offset_t)&fdt_static_dtb; 377#endif 378 379 if (OF_install(OFW_FDT, 0) == FALSE) 380 while (1); 381 382 if (OF_init((void *)dtbp) != 0) 383 while (1); 384 385 OF_interpret("perform-fixup", 0); 386 387 /* Reset TLB1 to get rid of temporary mappings */ 388 tlb1_init(); 389 390 /* Reset Time Base */ 391 mttb(0); 392 393 /* Init params/tunables that can be overridden by the loader. */ 394 init_param1(); 395 396 /* Start initializing proc0 and thread0. */ 397 proc_linkup0(&proc0, &thread0); 398 thread0.td_frame = &frame0; 399 400 /* Set up per-cpu data and store the pointer in SPR general 0. */ 401 pc = &__pcpu[0]; 402 pcpu_init(pc, 0, sizeof(struct pcpu)); 403 pc->pc_curthread = &thread0; 404#ifdef __powerpc64__ 405 __asm __volatile("mr 13,%0" :: "r"(pc->pc_curthread)); 406#else 407 __asm __volatile("mr 2,%0" :: "r"(pc->pc_curthread)); 408#endif 409 __asm __volatile("mtsprg 0, %0" :: "r"(pc)); 410 411 /* Initialize system mutexes. */ 412 mutex_init(); 413 414 /* Initialize the console before printing anything. */ 415 cninit(); 416 417 /* Print out some debug info... */ 418 debugf("%s: console initialized\n", __func__); 419 debugf(" arg3 mdp = 0x%08x\n", (u_int32_t)mdp); 420 debugf(" end = 0x%08x\n", (u_int32_t)end); 421 debugf(" boothowto = 0x%08x\n", boothowto); 422 debugf(" kernel ccsrbar = 0x%08x\n", CCSRBAR_VA); 423 debugf(" MSR = 0x%08x\n", mfmsr()); 424#if defined(BOOKE_E500) 425 debugf(" HID0 = 0x%08x\n", mfspr(SPR_HID0)); 426 debugf(" HID1 = 0x%08x\n", mfspr(SPR_HID1)); 427 debugf(" BUCSR = 0x%08x\n", mfspr(SPR_BUCSR)); 428#endif 429 430 debugf(" dtbp = 0x%08x\n", (uint32_t)dtbp); 431 432 print_kernel_section_addr(); 433 print_kenv(); 434#if defined(BOOKE_E500) 435 //tlb1_print_entries(); 436 //tlb1_print_tlbentries(); 437#endif 438 439 kdb_init(); 440 441#ifdef KDB 442 if (boothowto & RB_KDB) 443 kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); 444#endif 445 446 /* Initialise platform module */ 447 platform_probe_and_attach(); 448 449 /* Initialise virtual memory. */ 450 pmap_mmu_install(MMU_TYPE_BOOKE, 0); 451 pmap_bootstrap((uintptr_t)kernel_text, end); 452 pmap_bootstrapped = 1; 453 debugf("MSR = 0x%08x\n", mfmsr()); 454#if defined(BOOKE_E500) 455 //tlb1_print_entries(); 456 //tlb1_print_tlbentries(); 457#endif 458 459 /* Initialize params/tunables that are derived from memsize. */ 460 init_param2(physmem); 461 462 /* Finish setting up thread0. */ 463 thread0.td_pcb = (struct pcb *) 464 ((thread0.td_kstack + thread0.td_kstack_pages * PAGE_SIZE - 465 sizeof(struct pcb)) & ~15); 466 bzero((void *)thread0.td_pcb, sizeof(struct pcb)); 467 pc->pc_curpcb = thread0.td_pcb; 468 469 /* Initialise the message buffer. */ 470 msgbufinit(msgbufp, msgbufsize); 471 472 /* Enable Machine Check interrupt. */ 473 mtmsr(mfmsr() | PSL_ME); 474 isync(); 475 476 /* Enable L1 caches */ 477 booke_enable_l1_cache(); 478 479 debugf("%s: SP = 0x%08x\n", __func__, 480 ((uintptr_t)thread0.td_pcb - 16) & ~15); 481 482 return (((uintptr_t)thread0.td_pcb - 16) & ~15); 483} 484 485#define RES_GRANULE 32 486extern uint32_t tlb0_miss_locks[]; 487 488/* Initialise a struct pcpu. */ 489void 490cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz) 491{ 492 493 pcpu->pc_tid_next = TID_MIN; 494 495#ifdef SMP 496 uint32_t *ptr; 497 int words_per_gran = RES_GRANULE / sizeof(uint32_t); 498 499 ptr = &tlb0_miss_locks[cpuid * words_per_gran]; 500 pcpu->pc_booke_tlb_lock = ptr; 501 *ptr = TLB_UNLOCKED; 502 *(ptr + 1) = 0; /* recurse counter */ 503#endif 504} 505 506/* 507 * Flush the D-cache for non-DMA I/O so that the I-cache can 508 * be made coherent later. 509 */ 510void 511cpu_flush_dcache(void *ptr, size_t len) 512{ 513 register_t addr, off; 514 515 /* 516 * Align the address to a cacheline and adjust the length 517 * accordingly. Then round the length to a multiple of the 518 * cacheline for easy looping. 519 */ 520 addr = (uintptr_t)ptr; 521 off = addr & (cacheline_size - 1); 522 addr -= off; 523 len = (len + off + cacheline_size - 1) & ~(cacheline_size - 1); 524 525 while (len > 0) { 526 __asm __volatile ("dcbf 0,%0" :: "r"(addr)); 527 __asm __volatile ("sync"); 528 addr += cacheline_size; 529 len -= cacheline_size; 530 } 531} 532 533void 534spinlock_enter(void) 535{ 536 struct thread *td; 537 register_t msr; 538 539 td = curthread; 540 if (td->td_md.md_spinlock_count == 0) { 541 msr = intr_disable(); 542 td->td_md.md_spinlock_count = 1; 543 td->td_md.md_saved_msr = msr; 544 } else 545 td->td_md.md_spinlock_count++; 546 critical_enter(); 547} 548 549void 550spinlock_exit(void) 551{ 552 struct thread *td; 553 register_t msr; 554 555 td = curthread; 556 critical_exit(); 557 msr = td->td_md.md_saved_msr; 558 td->td_md.md_spinlock_count--; 559 if (td->td_md.md_spinlock_count == 0) 560 intr_restore(msr); 561} 562 563/* Shutdown the CPU as much as possible. */ 564void 565cpu_halt(void) 566{ 567 568 mtmsr(mfmsr() & ~(PSL_CE | PSL_EE | PSL_ME | PSL_DE)); 569 while (1) 570 ; 571} 572 573int 574ptrace_set_pc(struct thread *td, unsigned long addr) 575{ 576 struct trapframe *tf; 577 578 tf = td->td_frame; 579 tf->srr0 = (register_t)addr; 580 581 return (0); 582} 583 584int 585ptrace_single_step(struct thread *td) 586{ 587 struct trapframe *tf; 588 589 tf = td->td_frame; 590 tf->srr1 |= PSL_DE; 591 tf->cpu.booke.dbcr0 |= (DBCR0_IDM | DBCR0_IC); 592 return (0); 593} 594 595int 596ptrace_clear_single_step(struct thread *td) 597{ 598 struct trapframe *tf; 599 600 tf = td->td_frame; 601 tf->srr1 &= ~PSL_DE; 602 tf->cpu.booke.dbcr0 &= ~(DBCR0_IDM | DBCR0_IC); 603 return (0); 604} 605 606void 607kdb_cpu_clear_singlestep(void) 608{ 609 register_t r; 610 611 r = mfspr(SPR_DBCR0); 612 mtspr(SPR_DBCR0, r & ~DBCR0_IC); 613 kdb_frame->srr1 &= ~PSL_DE; 614} 615 616void 617kdb_cpu_set_singlestep(void) 618{ 619 register_t r; 620 621 r = mfspr(SPR_DBCR0); 622 mtspr(SPR_DBCR0, r | DBCR0_IC | DBCR0_IDM); 623 kdb_frame->srr1 |= PSL_DE; 624} 625 626void 627bzero(void *buf, size_t len) 628{ 629 caddr_t p; 630 631 p = buf; 632 633 while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) { 634 *p++ = 0; 635 len--; 636 } 637 638 while (len >= sizeof(u_long) * 8) { 639 *(u_long*) p = 0; 640 *((u_long*) p + 1) = 0; 641 *((u_long*) p + 2) = 0; 642 *((u_long*) p + 3) = 0; 643 len -= sizeof(u_long) * 8; 644 *((u_long*) p + 4) = 0; 645 *((u_long*) p + 5) = 0; 646 *((u_long*) p + 6) = 0; 647 *((u_long*) p + 7) = 0; 648 p += sizeof(u_long) * 8; 649 } 650 651 while (len >= sizeof(u_long)) { 652 *(u_long*) p = 0; 653 len -= sizeof(u_long); 654 p += sizeof(u_long); 655 } 656 657 while (len) { 658 *p++ = 0; 659 len--; 660 } 661} 662 663