···11-#include <stdio.h>22-#include <stdlib.h>33-#include <netinet/in.h>44-#include <unistd.h>55-#include <sys/types.h>66-#include <sys/stat.h>77-#include <string.h>88-99-#define ElfHeaderSize (64 * 1024)1010-#define ElfPages (ElfHeaderSize / 4096)1111-#define KERNELBASE (0xc0000000)1212-1313-void get4k(FILE *file, char *buf )1414-{1515- unsigned j;1616- unsigned num = fread(buf, 1, 4096, file);1717- for ( j=num; j<4096; ++j )1818- buf[j] = 0;1919-}2020-2121-void put4k(FILE *file, char *buf )2222-{2323- fwrite(buf, 1, 4096, file);2424-}2525-2626-void death(const char *msg, FILE *fdesc, const char *fname)2727-{2828- printf(msg);2929- fclose(fdesc);3030- unlink(fname);3131- exit(1);3232-}3333-3434-int main(int argc, char **argv)3535-{3636- char inbuf[4096];3737- FILE *ramDisk = NULL;3838- FILE *inputVmlinux = NULL;3939- FILE *outputVmlinux = NULL;4040- unsigned i = 0;4141- u_int32_t ramFileLen = 0;4242- u_int32_t ramLen = 0;4343- u_int32_t roundR = 0;4444- u_int32_t kernelLen = 0;4545- u_int32_t actualKernelLen = 0;4646- u_int32_t round = 0;4747- u_int32_t roundedKernelLen = 0;4848- u_int32_t ramStartOffs = 0;4949- u_int32_t ramPages = 0;5050- u_int32_t roundedKernelPages = 0;5151- u_int32_t hvReleaseData = 0;5252- u_int32_t eyeCatcher = 0xc8a5d9c4;5353- u_int32_t naca = 0;5454- u_int32_t xRamDisk = 0;5555- u_int32_t xRamDiskSize = 0;5656- if ( argc < 2 ) {5757- printf("Name of RAM disk file missing.\n");5858- exit(1);5959- }6060-6161- if ( argc < 3 ) {6262- printf("Name of vmlinux file missing.\n");6363- exit(1);6464- }6565-6666- if ( argc < 4 ) {6767- printf("Name of vmlinux output file missing.\n");6868- exit(1);6969- }7070-7171- ramDisk = fopen(argv[1], "r");7272- if ( ! ramDisk ) {7373- printf("RAM disk file \"%s\" failed to open.\n", argv[1]);7474- exit(1);7575- }7676- inputVmlinux = fopen(argv[2], "r");7777- if ( ! inputVmlinux ) {7878- printf("vmlinux file \"%s\" failed to open.\n", argv[2]);7979- exit(1);8080- }8181- outputVmlinux = fopen(argv[3], "w+");8282- if ( ! outputVmlinux ) {8383- printf("output vmlinux file \"%s\" failed to open.\n", argv[3]);8484- exit(1);8585- }8686- fseek(ramDisk, 0, SEEK_END);8787- ramFileLen = ftell(ramDisk);8888- fseek(ramDisk, 0, SEEK_SET);8989- printf("%s file size = %d\n", argv[1], ramFileLen);9090-9191- ramLen = ramFileLen;9292-9393- roundR = 4096 - (ramLen % 4096);9494- if ( roundR ) {9595- printf("Rounding RAM disk file up to a multiple of 4096, adding %d\n", roundR);9696- ramLen += roundR;9797- }9898-9999- printf("Rounded RAM disk size is %d\n", ramLen);100100- fseek(inputVmlinux, 0, SEEK_END);101101- kernelLen = ftell(inputVmlinux);102102- fseek(inputVmlinux, 0, SEEK_SET);103103- printf("kernel file size = %d\n", kernelLen);104104- if ( kernelLen == 0 ) {105105- printf("You must have a linux kernel specified as argv[2]\n");106106- exit(1);107107- }108108-109109- actualKernelLen = kernelLen - ElfHeaderSize;110110-111111- printf("actual kernel length (minus ELF header) = %d\n", actualKernelLen);112112-113113- round = actualKernelLen % 4096;114114- roundedKernelLen = actualKernelLen;115115- if ( round )116116- roundedKernelLen += (4096 - round);117117-118118- printf("actual kernel length rounded up to a 4k multiple = %d\n", roundedKernelLen);119119-120120- ramStartOffs = roundedKernelLen;121121- ramPages = ramLen / 4096;122122-123123- printf("RAM disk pages to copy = %d\n", ramPages);124124-125125- // Copy 64K ELF header126126- for (i=0; i<(ElfPages); ++i) {127127- get4k( inputVmlinux, inbuf );128128- put4k( outputVmlinux, inbuf );129129- }130130-131131- roundedKernelPages = roundedKernelLen / 4096;132132-133133- fseek(inputVmlinux, ElfHeaderSize, SEEK_SET);134134-135135- for ( i=0; i<roundedKernelPages; ++i ) {136136- get4k( inputVmlinux, inbuf );137137- put4k( outputVmlinux, inbuf );138138- }139139-140140- for ( i=0; i<ramPages; ++i ) {141141- get4k( ramDisk, inbuf );142142- put4k( outputVmlinux, inbuf );143143- }144144-145145- /* Close the input files */146146- fclose(ramDisk);147147- fclose(inputVmlinux);148148- /* And flush the written output file */149149- fflush(outputVmlinux);150150-151151- /* fseek to the hvReleaseData pointer */152152- fseek(outputVmlinux, ElfHeaderSize + 0x24, SEEK_SET);153153- if (fread(&hvReleaseData, 4, 1, outputVmlinux) != 1) {154154- death("Could not read hvReleaseData pointer\n", outputVmlinux, argv[3]);155155- }156156- hvReleaseData = ntohl(hvReleaseData); /* Convert to native int */157157- printf("hvReleaseData is at %08x\n", hvReleaseData);158158-159159- /* fseek to the hvReleaseData */160160- fseek(outputVmlinux, ElfHeaderSize + hvReleaseData, SEEK_SET);161161- if (fread(inbuf, 0x40, 1, outputVmlinux) != 1) {162162- death("Could not read hvReleaseData\n", outputVmlinux, argv[3]);163163- }164164- /* Check hvReleaseData sanity */165165- if (memcmp(inbuf, &eyeCatcher, 4) != 0) {166166- death("hvReleaseData is invalid\n", outputVmlinux, argv[3]);167167- }168168- /* Get the naca pointer */169169- naca = ntohl(*((u_int32_t *) &inbuf[0x0c])) - KERNELBASE;170170- printf("naca is at %08x\n", naca);171171-172172- /* fseek to the naca */173173- fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET);174174- if (fread(inbuf, 0x18, 1, outputVmlinux) != 1) {175175- death("Could not read naca\n", outputVmlinux, argv[3]);176176- }177177- xRamDisk = ntohl(*((u_int32_t *) &inbuf[0x0c]));178178- xRamDiskSize = ntohl(*((u_int32_t *) &inbuf[0x14]));179179- /* Make sure a RAM disk isn't already present */180180- if ((xRamDisk != 0) || (xRamDiskSize != 0)) {181181- death("RAM disk is already attached to this kernel\n", outputVmlinux, argv[3]);182182- }183183- /* Fill in the values */184184- *((u_int32_t *) &inbuf[0x0c]) = htonl(ramStartOffs);185185- *((u_int32_t *) &inbuf[0x14]) = htonl(ramPages);186186-187187- /* Write out the new naca */188188- fflush(outputVmlinux);189189- fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET);190190- if (fwrite(inbuf, 0x18, 1, outputVmlinux) != 1) {191191- death("Could not write naca\n", outputVmlinux, argv[3]);192192- }193193- printf("RAM Disk of 0x%x pages size is attached to the kernel at offset 0x%08x\n",194194- ramPages, ramStartOffs);195195-196196- /* Done */197197- fclose(outputVmlinux);198198- /* Set permission to executable */199199- chmod(argv[3], S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);200200-201201- return 0;202202-}203203-
+34-40
arch/ppc64/Kconfig
···302302 bool303303 default y304304305305-config MSCHUNKS306306- bool307307- depends on PPC_ISERIES308308- default y309309-310310-311305config PPC_RTAS312306 bool313307 depends on PPC_PSERIES || PPC_BPA···344350345351 If unsure, say Y. Only embedded should say N here.346352353353+source "fs/Kconfig.binfmt"354354+355355+config HOTPLUG_CPU356356+ bool "Support for hot-pluggable CPUs"357357+ depends on SMP && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)358358+ select HOTPLUG359359+ ---help---360360+ Say Y here to be able to turn CPUs off and on.361361+362362+ Say N if you are unsure.363363+364364+config PROC_DEVICETREE365365+ bool "Support for Open Firmware device tree in /proc"366366+ depends on !PPC_ISERIES367367+ help368368+ This option adds a device-tree directory under /proc which contains369369+ an image of the device tree that the kernel copies from Open370370+ Firmware. If unsure, say Y here.371371+372372+config CMDLINE_BOOL373373+ bool "Default bootloader kernel arguments"374374+ depends on !PPC_ISERIES375375+376376+config CMDLINE377377+ string "Initial kernel command string"378378+ depends on CMDLINE_BOOL379379+ default "console=ttyS0,9600 console=tty0 root=/dev/sda2"380380+ help381381+ On some platforms, there is currently no way for the boot loader to382382+ pass arguments to the kernel. For these platforms, you can supply383383+ some command-line options at build time by entering them here. In384384+ most cases you will need to specify the root device here.385385+347386endmenu348387349388config ISA_DMA_API350389 bool351390 default y352391353353-menu "General setup"392392+menu "Bus Options"354393355394config ISA356395 bool···416389 bool417390 default PCI418391419419-source "fs/Kconfig.binfmt"420420-421392source "drivers/pci/Kconfig"422422-423423-config HOTPLUG_CPU424424- bool "Support for hot-pluggable CPUs"425425- depends on SMP && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)426426- select HOTPLUG427427- ---help---428428- Say Y here to be able to turn CPUs off and on.429429-430430- Say N if you are unsure.431393432394source "drivers/pcmcia/Kconfig"433395434396source "drivers/pci/hotplug/Kconfig"435435-436436-config PROC_DEVICETREE437437- bool "Support for Open Firmware device tree in /proc"438438- depends on !PPC_ISERIES439439- help440440- This option adds a device-tree directory under /proc which contains441441- an image of the device tree that the kernel copies from Open442442- Firmware. If unsure, say Y here.443443-444444-config CMDLINE_BOOL445445- bool "Default bootloader kernel arguments"446446- depends on !PPC_ISERIES447447-448448-config CMDLINE449449- string "Initial kernel command string"450450- depends on CMDLINE_BOOL451451- default "console=ttyS0,9600 console=tty0 root=/dev/sda2"452452- help453453- On some platforms, there is currently no way for the boot loader to454454- pass arguments to the kernel. For these platforms, you can supply455455- some command-line options at build time by entering them here. In456456- most cases you will need to specify the root device here.457397458398endmenu459399
···99 * NOTE: this code runs in 32 bit mode and is packaged as ELF32.1010 */11111212-#include <asm/ppc_asm.h>1212+#include "ppc_asm.h"13131414 .text1515 .globl _start
+1-1
arch/ppc64/boot/div64.S
···1313 * as published by the Free Software Foundation; either version1414 * 2 of the License, or (at your option) any later version.1515 */1616-#include <asm/ppc_asm.h>1616+#include "ppc_asm.h"17171818 .globl __div64_321919__div64_32:
+149
arch/ppc64/boot/elf.h
···11+#ifndef _PPC_BOOT_ELF_H_22+#define _PPC_BOOT_ELF_H_33+44+/* 32-bit ELF base types. */55+typedef unsigned int Elf32_Addr;66+typedef unsigned short Elf32_Half;77+typedef unsigned int Elf32_Off;88+typedef signed int Elf32_Sword;99+typedef unsigned int Elf32_Word;1010+1111+/* 64-bit ELF base types. */1212+typedef unsigned long long Elf64_Addr;1313+typedef unsigned short Elf64_Half;1414+typedef signed short Elf64_SHalf;1515+typedef unsigned long long Elf64_Off;1616+typedef signed int Elf64_Sword;1717+typedef unsigned int Elf64_Word;1818+typedef unsigned long long Elf64_Xword;1919+typedef signed long long Elf64_Sxword;2020+2121+/* These constants are for the segment types stored in the image headers */2222+#define PT_NULL 02323+#define PT_LOAD 12424+#define PT_DYNAMIC 22525+#define PT_INTERP 32626+#define PT_NOTE 42727+#define PT_SHLIB 52828+#define PT_PHDR 62929+#define PT_TLS 7 /* Thread local storage segment */3030+#define PT_LOOS 0x60000000 /* OS-specific */3131+#define PT_HIOS 0x6fffffff /* OS-specific */3232+#define PT_LOPROC 0x700000003333+#define PT_HIPROC 0x7fffffff3434+#define PT_GNU_EH_FRAME 0x6474e5503535+3636+#define PT_GNU_STACK (PT_LOOS + 0x474e551)3737+3838+/* These constants define the different elf file types */3939+#define ET_NONE 04040+#define ET_REL 14141+#define ET_EXEC 24242+#define ET_DYN 34343+#define ET_CORE 44444+#define ET_LOPROC 0xff004545+#define ET_HIPROC 0xffff4646+4747+/* These constants define the various ELF target machines */4848+#define EM_NONE 04949+#define EM_PPC 20 /* PowerPC */5050+#define EM_PPC64 21 /* PowerPC64 */5151+5252+#define EI_NIDENT 165353+5454+typedef struct elf32_hdr {5555+ unsigned char e_ident[EI_NIDENT];5656+ Elf32_Half e_type;5757+ Elf32_Half e_machine;5858+ Elf32_Word e_version;5959+ Elf32_Addr e_entry; /* Entry point */6060+ Elf32_Off e_phoff;6161+ Elf32_Off e_shoff;6262+ Elf32_Word e_flags;6363+ Elf32_Half e_ehsize;6464+ Elf32_Half e_phentsize;6565+ Elf32_Half e_phnum;6666+ Elf32_Half e_shentsize;6767+ Elf32_Half e_shnum;6868+ Elf32_Half e_shstrndx;6969+} Elf32_Ehdr;7070+7171+typedef struct elf64_hdr {7272+ unsigned char e_ident[16]; /* ELF "magic number" */7373+ Elf64_Half e_type;7474+ Elf64_Half e_machine;7575+ Elf64_Word e_version;7676+ Elf64_Addr e_entry; /* Entry point virtual address */7777+ Elf64_Off e_phoff; /* Program header table file offset */7878+ Elf64_Off e_shoff; /* Section header table file offset */7979+ Elf64_Word e_flags;8080+ Elf64_Half e_ehsize;8181+ Elf64_Half e_phentsize;8282+ Elf64_Half e_phnum;8383+ Elf64_Half e_shentsize;8484+ Elf64_Half e_shnum;8585+ Elf64_Half e_shstrndx;8686+} Elf64_Ehdr;8787+8888+/* These constants define the permissions on sections in the program8989+ header, p_flags. */9090+#define PF_R 0x49191+#define PF_W 0x29292+#define PF_X 0x19393+9494+typedef struct elf32_phdr {9595+ Elf32_Word p_type;9696+ Elf32_Off p_offset;9797+ Elf32_Addr p_vaddr;9898+ Elf32_Addr p_paddr;9999+ Elf32_Word p_filesz;100100+ Elf32_Word p_memsz;101101+ Elf32_Word p_flags;102102+ Elf32_Word p_align;103103+} Elf32_Phdr;104104+105105+typedef struct elf64_phdr {106106+ Elf64_Word p_type;107107+ Elf64_Word p_flags;108108+ Elf64_Off p_offset; /* Segment file offset */109109+ Elf64_Addr p_vaddr; /* Segment virtual address */110110+ Elf64_Addr p_paddr; /* Segment physical address */111111+ Elf64_Xword p_filesz; /* Segment size in file */112112+ Elf64_Xword p_memsz; /* Segment size in memory */113113+ Elf64_Xword p_align; /* Segment alignment, file & memory */114114+} Elf64_Phdr;115115+116116+#define EI_MAG0 0 /* e_ident[] indexes */117117+#define EI_MAG1 1118118+#define EI_MAG2 2119119+#define EI_MAG3 3120120+#define EI_CLASS 4121121+#define EI_DATA 5122122+#define EI_VERSION 6123123+#define EI_OSABI 7124124+#define EI_PAD 8125125+126126+#define ELFMAG0 0x7f /* EI_MAG */127127+#define ELFMAG1 'E'128128+#define ELFMAG2 'L'129129+#define ELFMAG3 'F'130130+#define ELFMAG "\177ELF"131131+#define SELFMAG 4132132+133133+#define ELFCLASSNONE 0 /* EI_CLASS */134134+#define ELFCLASS32 1135135+#define ELFCLASS64 2136136+#define ELFCLASSNUM 3137137+138138+#define ELFDATANONE 0 /* e_ident[EI_DATA] */139139+#define ELFDATA2LSB 1140140+#define ELFDATA2MSB 2141141+142142+#define EV_NONE 0 /* e_version, EI_VERSION */143143+#define EV_CURRENT 1144144+#define EV_NUM 2145145+146146+#define ELFOSABI_NONE 0147147+#define ELFOSABI_LINUX 3148148+149149+#endif /* _PPC_BOOT_ELF_H_ */
+18-33
arch/ppc64/boot/main.c
···88 * as published by the Free Software Foundation; either version99 * 2 of the License, or (at your option) any later version.1010 */1111-#include "ppc32-types.h"1111+#include <stdarg.h>1212+#include <stddef.h>1313+#include "elf.h"1414+#include "page.h"1515+#include "string.h"1616+#include "stdio.h"1717+#include "prom.h"1218#include "zlib.h"1313-#include <linux/elf.h>1414-#include <linux/string.h>1515-#include <asm/processor.h>1616-#include <asm/page.h>17191818-extern void *finddevice(const char *);1919-extern int getprop(void *, const char *, void *, int);2020-extern void printf(const char *fmt, ...);2121-extern int sprintf(char *buf, const char *fmt, ...);2222-void gunzip(void *, int, unsigned char *, int *);2323-void *claim(unsigned int, unsigned int, unsigned int);2424-void flush_cache(void *, unsigned long);2525-void pause(void);2626-extern void exit(void);2020+static void gunzip(void *, int, unsigned char *, int *);2121+extern void flush_cache(void *, unsigned long);27222828-unsigned long strlen(const char *s);2929-void *memmove(void *dest, const void *src, unsigned long n);3030-void *memcpy(void *dest, const void *src, unsigned long n);31233224/* Value picked to match that used by yaboot */3325#define PROG_START 0x014000003426#define RAM_END (256<<20) // Fixme: use OF */35273636-char *avail_ram;3737-char *begin_avail, *end_avail;3838-char *avail_high;3939-unsigned int heap_use;4040-unsigned int heap_max;2828+static char *avail_ram;2929+static char *begin_avail, *end_avail;3030+static char *avail_high;3131+static unsigned int heap_use;3232+static unsigned int heap_max;41334234extern char _start[];4335extern char _vmlinux_start[];···4452 unsigned long size;4553 unsigned long memsize;4654};4747-struct addr_range vmlinux = {0, 0, 0};4848-struct addr_range vmlinuz = {0, 0, 0};4949-struct addr_range initrd = {0, 0, 0};5555+static struct addr_range vmlinux = {0, 0, 0};5656+static struct addr_range vmlinuz = {0, 0, 0};5757+static struct addr_range initrd = {0, 0, 0};50585159static char scratch[128<<10]; /* 128kB of scratch space for gunzip */5260···5563 void *,5664 void *);57655858-5959-int (*prom)(void *);6060-6161-void *chosen_handle;6262-void *stdin;6363-void *stdout;6464-void *stderr;65666667#undef DEBUG6768···262277263278#define DEFLATED 8264279265265-void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)280280+static void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)266281{267282 z_stream s;268283 int r, i, flags;
+34
arch/ppc64/boot/page.h
···11+#ifndef _PPC_BOOT_PAGE_H22+#define _PPC_BOOT_PAGE_H33+/*44+ * Copyright (C) 2001 PPC64 Team, IBM Corp55+ *66+ * This program is free software; you can redistribute it and/or77+ * modify it under the terms of the GNU General Public License88+ * as published by the Free Software Foundation; either version99+ * 2 of the License, or (at your option) any later version.1010+ */1111+1212+#ifdef __ASSEMBLY__1313+#define ASM_CONST(x) x1414+#else1515+#define __ASM_CONST(x) x##UL1616+#define ASM_CONST(x) __ASM_CONST(x)1717+#endif1818+1919+/* PAGE_SHIFT determines the page size */2020+#define PAGE_SHIFT 122121+#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT)2222+#define PAGE_MASK (~(PAGE_SIZE-1))2323+2424+/* align addr on a size boundary - adjust address up/down if needed */2525+#define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1)))2626+#define _ALIGN_DOWN(addr,size) ((addr)&(~((size)-1)))2727+2828+/* align addr on a size boundary - adjust address up if needed */2929+#define _ALIGN(addr,size) _ALIGN_UP(addr,size)3030+3131+/* to align the pointer to the (next) page boundary */3232+#define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE)3333+3434+#endif /* _PPC_BOOT_PAGE_H */
-36
arch/ppc64/boot/ppc32-types.h
···11-#ifndef _PPC64_TYPES_H22-#define _PPC64_TYPES_H33-44-typedef __signed__ char __s8;55-typedef unsigned char __u8;66-77-typedef __signed__ short __s16;88-typedef unsigned short __u16;99-1010-typedef __signed__ int __s32;1111-typedef unsigned int __u32;1212-1313-typedef __signed__ long long __s64;1414-typedef unsigned long long __u64;1515-1616-typedef signed char s8;1717-typedef unsigned char u8;1818-1919-typedef signed short s16;2020-typedef unsigned short u16;2121-2222-typedef signed int s32;2323-typedef unsigned int u32;2424-2525-typedef signed long long s64;2626-typedef unsigned long long u64;2727-2828-typedef struct {2929- __u32 u[4];3030-} __attribute((aligned(16))) __vector128;3131-3232-#define BITS_PER_LONG 323333-3434-typedef __vector128 vector128;3535-3636-#endif /* _PPC64_TYPES_H */
+62
arch/ppc64/boot/ppc_asm.h
···11+#ifndef _PPC64_PPC_ASM_H22+#define _PPC64_PPC_ASM_H33+/*44+ *55+ * Definitions used by various bits of low-level assembly code on PowerPC.66+ *77+ * Copyright (C) 1995-1999 Gary Thomas, Paul Mackerras, Cort Dougan.88+ *99+ * This program is free software; you can redistribute it and/or1010+ * modify it under the terms of the GNU General Public License1111+ * as published by the Free Software Foundation; either version1212+ * 2 of the License, or (at your option) any later version.1313+ */1414+1515+/* Condition Register Bit Fields */1616+1717+#define cr0 01818+#define cr1 11919+#define cr2 22020+#define cr3 32121+#define cr4 42222+#define cr5 52323+#define cr6 62424+#define cr7 72525+2626+2727+/* General Purpose Registers (GPRs) */2828+2929+#define r0 03030+#define r1 13131+#define r2 23232+#define r3 33333+#define r4 43434+#define r5 53535+#define r6 63636+#define r7 73737+#define r8 83838+#define r9 93939+#define r10 104040+#define r11 114141+#define r12 124242+#define r13 134343+#define r14 144444+#define r15 154545+#define r16 164646+#define r17 174747+#define r18 184848+#define r19 194949+#define r20 205050+#define r21 215151+#define r22 225252+#define r23 235353+#define r24 245454+#define r25 255555+#define r26 265656+#define r27 275757+#define r28 285858+#define r29 295959+#define r30 306060+#define r31 316161+6262+#endif /* _PPC64_PPC_ASM_H */
+27-169
arch/ppc64/boot/prom.c
···77 * 2 of the License, or (at your option) any later version.88 */99#include <stdarg.h>1010-#include <linux/types.h>1111-#include <linux/string.h>1212-#include <linux/ctype.h>1313-1414-extern __u32 __div64_32(unsigned long long *dividend, __u32 divisor);1515-1616-/* The unnecessary pointer compare is there1717- * to check for type safety (n must be 64bit)1818- */1919-# define do_div(n,base) ({ \2020- __u32 __base = (base); \2121- __u32 __rem; \2222- (void)(((typeof((n)) *)0) == ((unsigned long long *)0)); \2323- if (((n) >> 32) == 0) { \2424- __rem = (__u32)(n) % __base; \2525- (n) = (__u32)(n) / __base; \2626- } else \2727- __rem = __div64_32(&(n), __base); \2828- __rem; \2929- })1010+#include <stddef.h>1111+#include "string.h"1212+#include "stdio.h"1313+#include "prom.h"30143115int (*prom)(void *);32163317void *chosen_handle;1818+3419void *stdin;3520void *stdout;3621void *stderr;37223838-void exit(void);3939-void *finddevice(const char *name);4040-int getprop(void *phandle, const char *name, void *buf, int buflen);4141-void chrpboot(int a1, int a2, void *prom); /* in main.c */4242-4343-int printf(char *fmt, ...);4444-4545-/* there is no convenient header to get this from... -- paulus */4646-extern unsigned long strlen(const char *);47234824int4925write(void *handle, void *ptr, int nb)···186210 return write(f, str, n) == n? 0: -1;187211}188212189189-int190190-readchar(void)191191-{192192- char ch;193193-194194- for (;;) {195195- switch (read(stdin, &ch, 1)) {196196- case 1:197197- return ch;198198- case -1:199199- printf("read(stdin) returned -1\r\n");200200- return -1;201201- }202202- }203203-}204204-205205-static char line[256];206206-static char *lineptr;207207-static int lineleft;208208-209209-int210210-getchar(void)211211-{212212- int c;213213-214214- if (lineleft == 0) {215215- lineptr = line;216216- for (;;) {217217- c = readchar();218218- if (c == -1 || c == 4)219219- break;220220- if (c == '\r' || c == '\n') {221221- *lineptr++ = '\n';222222- putchar('\n');223223- break;224224- }225225- switch (c) {226226- case 0177:227227- case '\b':228228- if (lineptr > line) {229229- putchar('\b');230230- putchar(' ');231231- putchar('\b');232232- --lineptr;233233- }234234- break;235235- case 'U' & 0x1F:236236- while (lineptr > line) {237237- putchar('\b');238238- putchar(' ');239239- putchar('\b');240240- --lineptr;241241- }242242- break;243243- default:244244- if (lineptr >= &line[sizeof(line) - 1])245245- putchar('\a');246246- else {247247- putchar(c);248248- *lineptr++ = c;249249- }250250- }251251- }252252- lineleft = lineptr - line;253253- lineptr = line;254254- }255255- if (lineleft == 0)256256- return -1;257257- --lineleft;258258- return *lineptr++;259259-}260260-261261-262262-263263-/* String functions lifted from lib/vsprintf.c and lib/ctype.c */264264-unsigned char _ctype[] = {265265-_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */266266-_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */267267-_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */268268-_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */269269-_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */270270-_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */271271-_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */272272-_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */273273-_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */274274-_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */275275-_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */276276-_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */277277-_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */278278-_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */279279-_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */280280-_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */281281-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */282282-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */283283-_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */284284-_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */285285-_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */286286-_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */287287-_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */288288-_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */289289-290213size_t strnlen(const char * s, size_t count)291214{292215 const char *sc;···195320 return sc - s;196321}197322198198-unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)199199-{200200- unsigned long result = 0,value;323323+extern unsigned int __div64_32(unsigned long long *dividend,324324+ unsigned int divisor);201325202202- if (!base) {203203- base = 10;204204- if (*cp == '0') {205205- base = 8;206206- cp++;207207- if ((*cp == 'x') && isxdigit(cp[1])) {208208- cp++;209209- base = 16;210210- }211211- }212212- }213213- while (isxdigit(*cp) &&214214- (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {215215- result = result*base + value;216216- cp++;217217- }218218- if (endp)219219- *endp = (char *)cp;220220- return result;221221-}222222-223223-long simple_strtol(const char *cp,char **endp,unsigned int base)224224-{225225- if(*cp=='-')226226- return -simple_strtoul(cp+1,endp,base);227227- return simple_strtoul(cp,endp,base);228228-}326326+/* The unnecessary pointer compare is there327327+ * to check for type safety (n must be 64bit)328328+ */329329+# define do_div(n,base) ({ \330330+ unsigned int __base = (base); \331331+ unsigned int __rem; \332332+ (void)(((typeof((n)) *)0) == ((unsigned long long *)0)); \333333+ if (((n) >> 32) == 0) { \334334+ __rem = (unsigned int)(n) % __base; \335335+ (n) = (unsigned int)(n) / __base; \336336+ } else \337337+ __rem = __div64_32(&(n), __base); \338338+ __rem; \339339+ })229340230341static int skip_atoi(const char **s)231342{232232- int i=0;343343+ int i, c;233344234234- while (isdigit(**s))235235- i = i*10 + *((*s)++) - '0';345345+ for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s)346346+ i = i*10 + c - '0';236347 return i;237348}238349···297436 return str;298437}299438300300-/* Forward decl. needed for IP address printing stuff... */301301-int sprintf(char * buf, const char *fmt, ...);302302-303439int vsprintf(char *buf, const char *fmt, va_list args)304440{305441 int len;···335477336478 /* get field width */337479 field_width = -1;338338- if (isdigit(*fmt))480480+ if ('0' <= *fmt && *fmt <= '9')339481 field_width = skip_atoi(&fmt);340482 else if (*fmt == '*') {341483 ++fmt;···351493 precision = -1;352494 if (*fmt == '.') {353495 ++fmt; 354354- if (isdigit(*fmt))496496+ if ('0' <= *fmt && *fmt <= '9')355497 precision = skip_atoi(&fmt);356498 else if (*fmt == '*') {357499 ++fmt;···486628static char sprint_buf[1024];487629488630int489489-printf(char *fmt, ...)631631+printf(const char *fmt, ...)490632{491633 va_list args;492634 int n;
+18
arch/ppc64/boot/prom.h
···11+#ifndef _PPC_BOOT_PROM_H_22+#define _PPC_BOOT_PROM_H_33+44+extern int (*prom) (void *);55+extern void *chosen_handle;66+77+extern void *stdin;88+extern void *stdout;99+extern void *stderr;1010+1111+extern int write(void *handle, void *ptr, int nb);1212+extern int read(void *handle, void *ptr, int nb);1313+extern void exit(void);1414+extern void pause(void);1515+extern void *finddevice(const char *);1616+extern void *claim(unsigned long virt, unsigned long size, unsigned long align);1717+extern int getprop(void *phandle, const char *name, void *buf, int buflen);1818+#endif /* _PPC_BOOT_PROM_H_ */
+16
arch/ppc64/boot/stdio.h
···11+#ifndef _PPC_BOOT_STDIO_H_22+#define _PPC_BOOT_STDIO_H_33+44+extern int printf(const char *fmt, ...);55+66+extern int sprintf(char *buf, const char *fmt, ...);77+88+extern int vsprintf(char *buf, const char *fmt, va_list args);99+1010+extern int putc(int c, void *f);1111+extern int putchar(int c);1212+extern int getchar(void);1313+1414+extern int fputs(char *str, void *f);1515+1616+#endif /* _PPC_BOOT_STDIO_H_ */
+1-1
arch/ppc64/boot/string.S
···99 * NOTE: this code runs in 32 bit mode and is packaged as ELF32.1010 */11111212-#include <asm/ppc_asm.h>1212+#include "ppc_asm.h"13131414 .text1515 .globl strcpy
···107107108108/* Diagnostic functions */109109#ifdef DEBUG_ZLIB110110-# include <stdio.h>110110+# include "stdio.h"111111# ifndef verbose112112# define verbose 0113113# endif
-1
arch/ppc64/configs/iSeries_defconfig
···9999# CONFIG_HZ_1000 is not set100100CONFIG_HZ=100101101CONFIG_GENERIC_HARDIRQS=y102102-CONFIG_MSCHUNKS=y103102CONFIG_LPARCFG=y104103CONFIG_SECCOMP=y105104CONFIG_ISA_DMA_API=y
+11-26
arch/ppc64/kernel/LparData.c
···5151 0xf4, 0x4b, 0xf6, 0xf4 },5252};53535454+/*5555+ * The NACA. The first dword of the naca is required by the iSeries5656+ * hypervisor to point to itVpdAreas. The hypervisor finds the NACA5757+ * through the pointer in hvReleaseData.5858+ */5959+struct naca_struct naca = {6060+ .xItVpdAreas = &itVpdAreas,6161+ .xRamDisk = 0,6262+ .xRamDiskSize = 0,6363+};6464+5465extern void system_reset_iSeries(void);5566extern void machine_check_iSeries(void);5667extern void data_access_iSeries(void);···225214 0,0226215 }227216};228228-229229-struct msChunks msChunks;230230-EXPORT_SYMBOL(msChunks);231231-232232-/* Depending on whether this is called from iSeries or pSeries setup233233- * code, the location of the msChunks struct may or may not have234234- * to be reloc'd, so we force the caller to do that for us by passing235235- * in a pointer to the structure.236236- */237237-unsigned long238238-msChunks_alloc(unsigned long mem, unsigned long num_chunks, unsigned long chunk_size)239239-{240240- unsigned long offset = reloc_offset();241241- struct msChunks *_msChunks = PTRRELOC(&msChunks);242242-243243- _msChunks->num_chunks = num_chunks;244244- _msChunks->chunk_size = chunk_size;245245- _msChunks->chunk_shift = __ilog2(chunk_size);246246- _msChunks->chunk_mask = (1UL<<_msChunks->chunk_shift)-1;247247-248248- mem = _ALIGN(mem, sizeof(msChunks_entry));249249- _msChunks->abs = (msChunks_entry *)(mem + offset);250250- mem += num_chunks * sizeof(msChunks_entry);251251-252252- return mem;253253-}
···11+/*22+ * arch/ppc64/kernel/firmware.c33+ *44+ * Extracted from cputable.c55+ *66+ * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org)77+ *88+ * Modifications for ppc64:99+ * Copyright (C) 2003 Dave Engebretsen <engebret@us.ibm.com>1010+ * Copyright (C) 2005 Stephen Rothwell, IBM Corporation1111+ *1212+ * This program is free software; you can redistribute it and/or1313+ * modify it under the terms of the GNU General Public License1414+ * as published by the Free Software Foundation; either version1515+ * 2 of the License, or (at your option) any later version.1616+ */1717+1818+#include <linux/config.h>1919+2020+#include <asm/firmware.h>2121+2222+unsigned long ppc64_firmware_features;2323+2424+#ifdef CONFIG_PPC_PSERIES2525+firmware_feature_t firmware_features_table[FIRMWARE_MAX_FEATURES] = {2626+ {FW_FEATURE_PFT, "hcall-pft"},2727+ {FW_FEATURE_TCE, "hcall-tce"},2828+ {FW_FEATURE_SPRG0, "hcall-sprg0"},2929+ {FW_FEATURE_DABR, "hcall-dabr"},3030+ {FW_FEATURE_COPY, "hcall-copy"},3131+ {FW_FEATURE_ASR, "hcall-asr"},3232+ {FW_FEATURE_DEBUG, "hcall-debug"},3333+ {FW_FEATURE_PERF, "hcall-perf"},3434+ {FW_FEATURE_DUMP, "hcall-dump"},3535+ {FW_FEATURE_INTERRUPT, "hcall-interrupt"},3636+ {FW_FEATURE_MIGRATE, "hcall-migrate"},3737+ {FW_FEATURE_PERFMON, "hcall-perfmon"},3838+ {FW_FEATURE_CRQ, "hcall-crq"},3939+ {FW_FEATURE_VIO, "hcall-vio"},4040+ {FW_FEATURE_RDMA, "hcall-rdma"},4141+ {FW_FEATURE_LLAN, "hcall-lLAN"},4242+ {FW_FEATURE_BULK, "hcall-bulk"},4343+ {FW_FEATURE_XDABR, "hcall-xdabr"},4444+ {FW_FEATURE_MULTITCE, "hcall-multi-tce"},4545+ {FW_FEATURE_SPLPAR, "hcall-splpar"},4646+};4747+#endif
+194-319
arch/ppc64/kernel/head.S
···2323 * 2 of the License, or (at your option) any later version.2424 */25252626-#define SECONDARY_PROCESSORS2727-2826#include <linux/config.h>2927#include <linux/threads.h>3028#include <asm/processor.h>3129#include <asm/page.h>3230#include <asm/mmu.h>3333-#include <asm/naca.h>3431#include <asm/systemcfg.h>3532#include <asm/ppc_asm.h>3633#include <asm/offsets.h>···4245#endif43464447/*4545- * hcall interface to pSeries LPAR4646- */4747-#define H_SET_ASR 0x304848-4949-/*5048 * We layout physical memory as follows:5149 * 0x0000 - 0x00ff : Secondary processor spin code5250 * 0x0100 - 0x2fff : pSeries Interrupt prologs5353- * 0x3000 - 0x3fff : Interrupt support5454- * 0x4000 - 0x4fff : NACA5555- * 0x6000 : iSeries and common interrupt prologs5656- * 0x9000 - 0x9fff : Initial segment table5151+ * 0x3000 - 0x5fff : interrupt support, iSeries and common interrupt prologs5252+ * 0x6000 - 0x6fff : Initial (CPU0) segment table5353+ * 0x7000 - 0x7fff : FWNMI data area5454+ * 0x8000 - : Early init and support code5755 */58565957/*···86948795 /* Catch branch to 0 in real mode */8896 trap9797+8998#ifdef CONFIG_PPC_ISERIES9099 /*91100 * At offset 0x20, there is a pointer to iSeries LPAR data.···96103 .llong hvReleaseData-KERNELBASE9710498105 /*9999- * At offset 0x28 and 0x30 are offsets to the msChunks106106+ * At offset 0x28 and 0x30 are offsets to the mschunks_map100107 * array (used by the iSeries LPAR debugger to do translation101108 * between physical addresses and absolute addresses) and102109 * to the pidhash table (also used by the debugger)103110 */104104- .llong msChunks-KERNELBASE111111+ .llong mschunks_map-KERNELBASE105112 .llong 0 /* pidhash-KERNELBASE SFRXXX */106113107114 /* Offset 0x38 - Pointer to start of embedded System.map */···113120embedded_sysmap_end:114121 .llong 0115122116116-#else /* CONFIG_PPC_ISERIES */123123+#endif /* CONFIG_PPC_ISERIES */117124118125 /* Secondary processors spin on this value until it goes to 1. */119126 .globl __secondary_hold_spinloop···148155 std r24,__secondary_hold_acknowledge@l(0)149156 sync150157151151- /* All secondary cpu's wait here until told to start. */158158+ /* All secondary cpus wait here until told to start. */152159100: ld r4,__secondary_hold_spinloop@l(0)153160 cmpdi 0,r4,1154161 bne 100b···161168 b .pSeries_secondary_smp_init162169#else163170 BUG_OPCODE164164-#endif165171#endif166172#endif167173···494502 STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint)495503 STD_EXCEPTION_PSERIES(0x1700, altivec_assist)496504497497- /* moved from 0xf00 */498498- STD_EXCEPTION_PSERIES(0x3000, performance_monitor)505505+ . = 0x3000499506500500- . = 0x3100507507+/*** pSeries interrupt support ***/508508+509509+ /* moved from 0xf00 */510510+ STD_EXCEPTION_PSERIES(., performance_monitor)511511+512512+ .align 7501513_GLOBAL(do_stab_bolted_pSeries)502514 mtcrf 0x80,r12503515 mfspr r12,SPRG2504516 EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted)505517506506-507507- /* Space for the naca. Architected to be located at real address508508- * NACA_PHYS_ADDR. Various tools rely on this location being fixed.509509- * The first dword of the naca is required by iSeries LPAR to510510- * point to itVpdAreas. On pSeries native, this value is not used.511511- */512512- . = NACA_PHYS_ADDR513513- .globl __end_interrupts514514-__end_interrupts:518518+/*519519+ * Vectors for the FWNMI option. Share common code.520520+ */521521+ .globl system_reset_fwnmi522522+system_reset_fwnmi:523523+ HMT_MEDIUM524524+ mtspr SPRG1,r13 /* save r13 */525525+ RUNLATCH_ON(r13)526526+ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)527527+528528+ .globl machine_check_fwnmi529529+machine_check_fwnmi:530530+ HMT_MEDIUM531531+ mtspr SPRG1,r13 /* save r13 */532532+ RUNLATCH_ON(r13)533533+ EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)534534+515535#ifdef CONFIG_PPC_ISERIES516516- .globl naca517517-naca:518518- .llong itVpdAreas519519- .llong 0 /* xRamDisk */520520- .llong 0 /* xRamDiskSize */521521-522522- . = 0x6100523523-524536/*** ISeries-LPAR interrupt handlers ***/525537526538 STD_EXCEPTION_ISERIES(0x200, machine_check, PACA_EXMC)···622626623627 cmpwi 0,r23,0624628 beq iSeries_secondary_smp_loop /* Loop until told to go */625625-#ifdef SECONDARY_PROCESSORS626629 bne .__secondary_start /* Loop until told to go */627627-#endif628630iSeries_secondary_smp_loop:629631 /* Let the Hypervisor know we are alive */630632 /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */···665671 ld r13,PACA_EXGEN+EX_R13(r13)666672 rfid667673 b . /* prevent speculative execution */668668-#endif669669-670670-/*671671- * Data area reserved for FWNMI option.672672- */673673- .= 0x7000674674- .globl fwnmi_data_area675675-fwnmi_data_area:676676-677677-#ifdef CONFIG_PPC_ISERIES678678- . = LPARMAP_PHYS679679-#include "lparmap.s"680674#endif /* CONFIG_PPC_ISERIES */681681-682682-/*683683- * Vectors for the FWNMI option. Share common code.684684- */685685- . = 0x8000686686- .globl system_reset_fwnmi687687-system_reset_fwnmi:688688- HMT_MEDIUM689689- mtspr SPRG1,r13 /* save r13 */690690- RUNLATCH_ON(r13)691691- EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)692692- .globl machine_check_fwnmi693693-machine_check_fwnmi:694694- HMT_MEDIUM695695- mtspr SPRG1,r13 /* save r13 */696696- RUNLATCH_ON(r13)697697- EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)698698-699699- /*700700- * Space for the initial segment table701701- * For LPAR, the hypervisor must fill in at least one entry702702- * before we get control (with relocate on)703703- */704704- . = STAB0_PHYS_ADDR705705- .globl __start_stab706706-__start_stab:707707-708708- . = (STAB0_PHYS_ADDR + PAGE_SIZE)709709- .globl __end_stab710710-__end_stab:711711-712675713676/*** Common interrupt handlers ***/714677···703752 * R9 contains the saved CR, r13 points to the paca,704753 * r10 contains the (bad) kernel stack pointer,705754 * r11 and r12 contain the saved SRR0 and SRR1.706706- * We switch to using the paca guard page as an emergency stack,707707- * save the registers there, and call kernel_bad_stack(), which panics.755755+ * We switch to using an emergency stack, save the registers there,756756+ * and call kernel_bad_stack(), which panics.708757 */709758bad_stack:710759 ld r1,PACAEMERGSP(r13)···857906 bl .kernel_fp_unavailable_exception858907 BUG_OPCODE859908909909+/*910910+ * load_up_fpu(unused, unused, tsk)911911+ * Disable FP for the task which had the FPU previously,912912+ * and save its floating-point registers in its thread_struct.913913+ * Enables the FPU for use in the kernel on return.914914+ * On SMP we know the fpu is free, since we give it up every915915+ * switch (ie, no lazy save of the FP registers).916916+ * On entry: r13 == 'current' && last_task_used_math != 'current'917917+ */918918+_STATIC(load_up_fpu)919919+ mfmsr r5 /* grab the current MSR */920920+ ori r5,r5,MSR_FP921921+ mtmsrd r5 /* enable use of fpu now */922922+ isync923923+/*924924+ * For SMP, we don't do lazy FPU switching because it just gets too925925+ * horrendously complex, especially when a task switches from one CPU926926+ * to another. Instead we call giveup_fpu in switch_to.927927+ *928928+ */929929+#ifndef CONFIG_SMP930930+ ld r3,last_task_used_math@got(r2)931931+ ld r4,0(r3)932932+ cmpdi 0,r4,0933933+ beq 1f934934+ /* Save FP state to last_task_used_math's THREAD struct */935935+ addi r4,r4,THREAD936936+ SAVE_32FPRS(0, r4)937937+ mffs fr0938938+ stfd fr0,THREAD_FPSCR(r4)939939+ /* Disable FP for last_task_used_math */940940+ ld r5,PT_REGS(r4)941941+ ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)942942+ li r6,MSR_FP|MSR_FE0|MSR_FE1943943+ andc r4,r4,r6944944+ std r4,_MSR-STACK_FRAME_OVERHEAD(r5)945945+1:946946+#endif /* CONFIG_SMP */947947+ /* enable use of FP after return */948948+ ld r4,PACACURRENT(r13)949949+ addi r5,r4,THREAD /* Get THREAD */950950+ ld r4,THREAD_FPEXC_MODE(r5)951951+ ori r12,r12,MSR_FP952952+ or r12,r12,r4953953+ std r12,_MSR(r1)954954+ lfd fr0,THREAD_FPSCR(r5)955955+ mtfsf 0xff,fr0956956+ REST_32FPRS(0, r5)957957+#ifndef CONFIG_SMP958958+ /* Update last_task_used_math to 'current' */959959+ subi r4,r5,THREAD /* Back to 'current' */960960+ std r4,0(r3)961961+#endif /* CONFIG_SMP */962962+ /* restore registers and return */963963+ b fast_exception_return964964+860965 .align 7861966 .globl altivec_unavailable_common862967altivec_unavailable_common:···927920 ENABLE_INTS928921 bl .altivec_unavailable_exception929922 b .ret_from_except923923+924924+#ifdef CONFIG_ALTIVEC925925+/*926926+ * load_up_altivec(unused, unused, tsk)927927+ * Disable VMX for the task which had it previously,928928+ * and save its vector registers in its thread_struct.929929+ * Enables the VMX for use in the kernel on return.930930+ * On SMP we know the VMX is free, since we give it up every931931+ * switch (ie, no lazy save of the vector registers).932932+ * On entry: r13 == 'current' && last_task_used_altivec != 'current'933933+ */934934+_STATIC(load_up_altivec)935935+ mfmsr r5 /* grab the current MSR */936936+ oris r5,r5,MSR_VEC@h937937+ mtmsrd r5 /* enable use of VMX now */938938+ isync939939+940940+/*941941+ * For SMP, we don't do lazy VMX switching because it just gets too942942+ * horrendously complex, especially when a task switches from one CPU943943+ * to another. Instead we call giveup_altvec in switch_to.944944+ * VRSAVE isn't dealt with here, that is done in the normal context945945+ * switch code. Note that we could rely on vrsave value to eventually946946+ * avoid saving all of the VREGs here...947947+ */948948+#ifndef CONFIG_SMP949949+ ld r3,last_task_used_altivec@got(r2)950950+ ld r4,0(r3)951951+ cmpdi 0,r4,0952952+ beq 1f953953+ /* Save VMX state to last_task_used_altivec's THREAD struct */954954+ addi r4,r4,THREAD955955+ SAVE_32VRS(0,r5,r4)956956+ mfvscr vr0957957+ li r10,THREAD_VSCR958958+ stvx vr0,r10,r4959959+ /* Disable VMX for last_task_used_altivec */960960+ ld r5,PT_REGS(r4)961961+ ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)962962+ lis r6,MSR_VEC@h963963+ andc r4,r4,r6964964+ std r4,_MSR-STACK_FRAME_OVERHEAD(r5)965965+1:966966+#endif /* CONFIG_SMP */967967+ /* Hack: if we get an altivec unavailable trap with VRSAVE968968+ * set to all zeros, we assume this is a broken application969969+ * that fails to set it properly, and thus we switch it to970970+ * all 1's971971+ */972972+ mfspr r4,SPRN_VRSAVE973973+ cmpdi 0,r4,0974974+ bne+ 1f975975+ li r4,-1976976+ mtspr SPRN_VRSAVE,r4977977+1:978978+ /* enable use of VMX after return */979979+ ld r4,PACACURRENT(r13)980980+ addi r5,r4,THREAD /* Get THREAD */981981+ oris r12,r12,MSR_VEC@h982982+ std r12,_MSR(r1)983983+ li r4,1984984+ li r10,THREAD_VSCR985985+ stw r4,THREAD_USED_VR(r5)986986+ lvx vr0,r10,r5987987+ mtvscr vr0988988+ REST_32VRS(0,r4,r5)989989+#ifndef CONFIG_SMP990990+ /* Update last_task_used_math to 'current' */991991+ subi r4,r5,THREAD /* Back to 'current' */992992+ std r4,0(r3)993993+#endif /* CONFIG_SMP */994994+ /* restore registers and return */995995+ b fast_exception_return996996+#endif /* CONFIG_ALTIVEC */930997931998/*932999 * Hash table stuff···12481167 bl .unrecoverable_exception12491168 b 1b1250116911701170+/*11711171+ * Space for CPU0's segment table.11721172+ *11731173+ * On iSeries, the hypervisor must fill in at least one entry before11741174+ * we get control (with relocate on). The address is give to the hv11751175+ * as a page number (see xLparMap in LparData.c), so this must be at a11761176+ * fixed address (the linker can't compute (u64)&initial_stab >>11771177+ * PAGE_SHIFT).11781178+ */11791179+ . = STAB0_PHYS_ADDR /* 0x6000 */11801180+ .globl initial_stab11811181+initial_stab:11821182+ .space 409611831183+11841184+/*11851185+ * Data area reserved for FWNMI option.11861186+ * This address (0x7000) is fixed by the RPA.11871187+ */11881188+ .= 0x700011891189+ .globl fwnmi_data_area11901190+fwnmi_data_area:11911191+ .space PAGE_SIZE1251119212521193/*12531194 * On pSeries, secondary processors spin in the following code.···13031200 b .kexec_wait /* next kernel might do better */13041201130512022: mtspr SPRG3,r13 /* Save vaddr of paca in SPRG3 */13061306- /* From now on, r24 is expected to be logica cpuid */12031203+ /* From now on, r24 is expected to be logical cpuid */13071204 mr r24,r5130812053: HMT_LOW13091206 lbz r23,PACAPROCSTART(r13) /* Test if this processor should */···1316121313171214 cmpwi 0,r23,013181215#ifdef CONFIG_SMP13191319-#ifdef SECONDARY_PROCESSORS13201216 bne .__secondary_start13211321-#endif13221217#endif13231218 b 3b /* Loop until told to go */13241219···1530142915311430.align 815321431copy_to_here:15331533-15341534-/*15351535- * load_up_fpu(unused, unused, tsk)15361536- * Disable FP for the task which had the FPU previously,15371537- * and save its floating-point registers in its thread_struct.15381538- * Enables the FPU for use in the kernel on return.15391539- * On SMP we know the fpu is free, since we give it up every15401540- * switch (ie, no lazy save of the FP registers).15411541- * On entry: r13 == 'current' && last_task_used_math != 'current'15421542- */15431543-_STATIC(load_up_fpu)15441544- mfmsr r5 /* grab the current MSR */15451545- ori r5,r5,MSR_FP15461546- mtmsrd r5 /* enable use of fpu now */15471547- isync15481548-/*15491549- * For SMP, we don't do lazy FPU switching because it just gets too15501550- * horrendously complex, especially when a task switches from one CPU15511551- * to another. Instead we call giveup_fpu in switch_to.15521552- *15531553- */15541554-#ifndef CONFIG_SMP15551555- ld r3,last_task_used_math@got(r2)15561556- ld r4,0(r3)15571557- cmpdi 0,r4,015581558- beq 1f15591559- /* Save FP state to last_task_used_math's THREAD struct */15601560- addi r4,r4,THREAD15611561- SAVE_32FPRS(0, r4)15621562- mffs fr015631563- stfd fr0,THREAD_FPSCR(r4)15641564- /* Disable FP for last_task_used_math */15651565- ld r5,PT_REGS(r4)15661566- ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)15671567- li r6,MSR_FP|MSR_FE0|MSR_FE115681568- andc r4,r4,r615691569- std r4,_MSR-STACK_FRAME_OVERHEAD(r5)15701570-1:15711571-#endif /* CONFIG_SMP */15721572- /* enable use of FP after return */15731573- ld r4,PACACURRENT(r13)15741574- addi r5,r4,THREAD /* Get THREAD */15751575- ld r4,THREAD_FPEXC_MODE(r5)15761576- ori r12,r12,MSR_FP15771577- or r12,r12,r415781578- std r12,_MSR(r1)15791579- lfd fr0,THREAD_FPSCR(r5)15801580- mtfsf 0xff,fr015811581- REST_32FPRS(0, r5)15821582-#ifndef CONFIG_SMP15831583- /* Update last_task_used_math to 'current' */15841584- subi r4,r5,THREAD /* Back to 'current' */15851585- std r4,0(r3)15861586-#endif /* CONFIG_SMP */15871587- /* restore registers and return */15881588- b fast_exception_return15891589-15901590-/*15911591- * disable_kernel_fp()15921592- * Disable the FPU.15931593- */15941594-_GLOBAL(disable_kernel_fp)15951595- mfmsr r315961596- rldicl r0,r3,(63-MSR_FP_LG),115971597- rldicl r3,r0,(MSR_FP_LG+1),015981598- mtmsrd r3 /* disable use of fpu now */15991599- isync16001600- blr16011601-16021602-/*16031603- * giveup_fpu(tsk)16041604- * Disable FP for the task given as the argument,16051605- * and save the floating-point registers in its thread_struct.16061606- * Enables the FPU for use in the kernel on return.16071607- */16081608-_GLOBAL(giveup_fpu)16091609- mfmsr r516101610- ori r5,r5,MSR_FP16111611- mtmsrd r5 /* enable use of fpu now */16121612- isync16131613- cmpdi 0,r3,016141614- beqlr- /* if no previous owner, done */16151615- addi r3,r3,THREAD /* want THREAD of task */16161616- ld r5,PT_REGS(r3)16171617- cmpdi 0,r5,016181618- SAVE_32FPRS(0, r3)16191619- mffs fr016201620- stfd fr0,THREAD_FPSCR(r3)16211621- beq 1f16221622- ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)16231623- li r3,MSR_FP|MSR_FE0|MSR_FE116241624- andc r4,r4,r3 /* disable FP for previous task */16251625- std r4,_MSR-STACK_FRAME_OVERHEAD(r5)16261626-1:16271627-#ifndef CONFIG_SMP16281628- li r5,016291629- ld r4,last_task_used_math@got(r2)16301630- std r5,0(r4)16311631-#endif /* CONFIG_SMP */16321632- blr16331633-16341634-16351635-#ifdef CONFIG_ALTIVEC16361636-16371637-/*16381638- * load_up_altivec(unused, unused, tsk)16391639- * Disable VMX for the task which had it previously,16401640- * and save its vector registers in its thread_struct.16411641- * Enables the VMX for use in the kernel on return.16421642- * On SMP we know the VMX is free, since we give it up every16431643- * switch (ie, no lazy save of the vector registers).16441644- * On entry: r13 == 'current' && last_task_used_altivec != 'current'16451645- */16461646-_STATIC(load_up_altivec)16471647- mfmsr r5 /* grab the current MSR */16481648- oris r5,r5,MSR_VEC@h16491649- mtmsrd r5 /* enable use of VMX now */16501650- isync16511651-16521652-/*16531653- * For SMP, we don't do lazy VMX switching because it just gets too16541654- * horrendously complex, especially when a task switches from one CPU16551655- * to another. Instead we call giveup_altvec in switch_to.16561656- * VRSAVE isn't dealt with here, that is done in the normal context16571657- * switch code. Note that we could rely on vrsave value to eventually16581658- * avoid saving all of the VREGs here...16591659- */16601660-#ifndef CONFIG_SMP16611661- ld r3,last_task_used_altivec@got(r2)16621662- ld r4,0(r3)16631663- cmpdi 0,r4,016641664- beq 1f16651665- /* Save VMX state to last_task_used_altivec's THREAD struct */16661666- addi r4,r4,THREAD16671667- SAVE_32VRS(0,r5,r4)16681668- mfvscr vr016691669- li r10,THREAD_VSCR16701670- stvx vr0,r10,r416711671- /* Disable VMX for last_task_used_altivec */16721672- ld r5,PT_REGS(r4)16731673- ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)16741674- lis r6,MSR_VEC@h16751675- andc r4,r4,r616761676- std r4,_MSR-STACK_FRAME_OVERHEAD(r5)16771677-1:16781678-#endif /* CONFIG_SMP */16791679- /* Hack: if we get an altivec unavailable trap with VRSAVE16801680- * set to all zeros, we assume this is a broken application16811681- * that fails to set it properly, and thus we switch it to16821682- * all 1's16831683- */16841684- mfspr r4,SPRN_VRSAVE16851685- cmpdi 0,r4,016861686- bne+ 1f16871687- li r4,-116881688- mtspr SPRN_VRSAVE,r416891689-1:16901690- /* enable use of VMX after return */16911691- ld r4,PACACURRENT(r13)16921692- addi r5,r4,THREAD /* Get THREAD */16931693- oris r12,r12,MSR_VEC@h16941694- std r12,_MSR(r1)16951695- li r4,116961696- li r10,THREAD_VSCR16971697- stw r4,THREAD_USED_VR(r5)16981698- lvx vr0,r10,r516991699- mtvscr vr017001700- REST_32VRS(0,r4,r5)17011701-#ifndef CONFIG_SMP17021702- /* Update last_task_used_math to 'current' */17031703- subi r4,r5,THREAD /* Back to 'current' */17041704- std r4,0(r3)17051705-#endif /* CONFIG_SMP */17061706- /* restore registers and return */17071707- b fast_exception_return17081708-17091709-/*17101710- * disable_kernel_altivec()17111711- * Disable the VMX.17121712- */17131713-_GLOBAL(disable_kernel_altivec)17141714- mfmsr r317151715- rldicl r0,r3,(63-MSR_VEC_LG),117161716- rldicl r3,r0,(MSR_VEC_LG+1),017171717- mtmsrd r3 /* disable use of VMX now */17181718- isync17191719- blr17201720-17211721-/*17221722- * giveup_altivec(tsk)17231723- * Disable VMX for the task given as the argument,17241724- * and save the vector registers in its thread_struct.17251725- * Enables the VMX for use in the kernel on return.17261726- */17271727-_GLOBAL(giveup_altivec)17281728- mfmsr r517291729- oris r5,r5,MSR_VEC@h17301730- mtmsrd r5 /* enable use of VMX now */17311731- isync17321732- cmpdi 0,r3,017331733- beqlr- /* if no previous owner, done */17341734- addi r3,r3,THREAD /* want THREAD of task */17351735- ld r5,PT_REGS(r3)17361736- cmpdi 0,r5,017371737- SAVE_32VRS(0,r4,r3)17381738- mfvscr vr017391739- li r4,THREAD_VSCR17401740- stvx vr0,r4,r317411741- beq 1f17421742- ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)17431743- lis r3,MSR_VEC@h17441744- andc r4,r4,r3 /* disable FP for previous task */17451745- std r4,_MSR-STACK_FRAME_OVERHEAD(r5)17461746-1:17471747-#ifndef CONFIG_SMP17481748- li r5,017491749- ld r4,last_task_used_altivec@got(r2)17501750- std r5,0(r4)17511751-#endif /* CONFIG_SMP */17521752- blr17531753-17541754-#endif /* CONFIG_ALTIVEC */1755143217561433#ifdef CONFIG_SMP17571434#ifdef CONFIG_PPC_PMAC···1881200218822003 bl .start_kernel1883200418841884-_GLOBAL(__setup_cpu_power3)18851885- blr18861886-18872005_GLOBAL(hmt_init)18882006#ifdef CONFIG_HMT18892007 LOADADDR(r5, hmt_thread_data)···1971209519722096/*19732097 * We put a few things here that have to be page-aligned.19741974- * This stuff goes at the beginning of the data segment,19751975- * which is page-aligned.20982098+ * This stuff goes at the beginning of the bss, which is page-aligned.19762099 */19771977- .data21002100+ .section ".bss"21012101+19782102 .align 1219791979- .globl sdata19801980-sdata:21032103+19812104 .globl empty_zero_page19822105empty_zero_page:19831983- .space 409621062106+ .space PAGE_SIZE1984210719852108 .globl swapper_pg_dir19862109swapper_pg_dir:19871987- .space 409621102110+ .space PAGE_SIZE1988211119892112/*19902113 * This space gets a copy of optional info passed to us by the bootstrap
+4-1
arch/ppc64/kernel/iSeries_htab.c
···4141 unsigned long prpn, unsigned long vflags,4242 unsigned long rflags)4343{4444+ unsigned long arpn;4445 long slot;4546 hpte_t lhpte;4647 int secondary = 0;···7170 slot &= 0x7fffffffffffffff;7271 }73727373+ arpn = phys_to_abs(prpn << PAGE_SHIFT) >> PAGE_SHIFT;7474+7475 lhpte.v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID;7575- lhpte.r = (physRpn_to_absRpn(prpn) << HPTE_R_RPN_SHIFT) | rflags;7676+ lhpte.r = (arpn << HPTE_R_RPN_SHIFT) | rflags;76777778 /* Now fill in the actual HPTE */7879 HvCallHpt_addValidate(slot, secondary, &lhpte);
+26-4
arch/ppc64/kernel/iSeries_setup.c
···3939#include <asm/cputable.h>4040#include <asm/sections.h>4141#include <asm/iommu.h>4242+#include <asm/firmware.h>42434344#include <asm/time.h>4445#include "iSeries_setup.h"···315314316315 DBG(" -> iSeries_init_early()\n");317316317317+ ppc64_firmware_features = FW_FEATURE_ISERIES;318318+318319 ppcdbg_initialize();319320320321#if defined(CONFIG_BLK_DEV_INITRD)···415412 DBG(" <- iSeries_init_early()\n");416413}417414415415+struct mschunks_map mschunks_map = {416416+ /* XXX We don't use these, but Piranha might need them. */417417+ .chunk_size = MSCHUNKS_CHUNK_SIZE,418418+ .chunk_shift = MSCHUNKS_CHUNK_SHIFT,419419+ .chunk_mask = MSCHUNKS_OFFSET_MASK,420420+};421421+EXPORT_SYMBOL(mschunks_map);422422+423423+void mschunks_alloc(unsigned long num_chunks)424424+{425425+ klimit = _ALIGN(klimit, sizeof(u32));426426+ mschunks_map.mapping = (u32 *)klimit;427427+ klimit += num_chunks * sizeof(u32);428428+ mschunks_map.num_chunks = num_chunks;429429+}430430+418431/*419432 * The iSeries may have very large memories ( > 128 GB ) and a partition420433 * may get memory in "chunks" that may be anywhere in the 2**52 real···468449469450 /* Chunk size on iSeries is 256K bytes */470451 totalChunks = (u32)HvLpConfig_getMsChunks();471471- klimit = msChunks_alloc(klimit, totalChunks, 1UL << 18);452452+ mschunks_alloc(totalChunks);472453473454 /*474455 * Get absolute address of our load area···505486 printk("Load area size %dK\n", loadAreaSize * 256);506487507488 for (nextPhysChunk = 0; nextPhysChunk < loadAreaSize; ++nextPhysChunk)508508- msChunks.abs[nextPhysChunk] =489489+ mschunks_map.mapping[nextPhysChunk] =509490 loadAreaFirstChunk + nextPhysChunk;510491511492 /*···514495 */515496 hptFirstChunk = (u32)addr_to_chunk(HvCallHpt_getHptAddress());516497 hptSizePages = (u32)HvCallHpt_getHptPages();517517- hptSizeChunks = hptSizePages >> (msChunks.chunk_shift - PAGE_SHIFT);498498+ hptSizeChunks = hptSizePages >> (MSCHUNKS_CHUNK_SHIFT - PAGE_SHIFT);518499 hptLastChunk = hptFirstChunk + hptSizeChunks - 1;519500520501 printk("HPT absolute addr = %016lx, size = %dK\n",···571552 (absChunk > hptLastChunk)) &&572553 ((absChunk < loadAreaFirstChunk) ||573554 (absChunk > loadAreaLastChunk))) {574574- msChunks.abs[nextPhysChunk] = absChunk;555555+ mschunks_map.mapping[nextPhysChunk] =556556+ absChunk;575557 ++nextPhysChunk;576558 }577559 }···963943 ppc_md.get_rtc_time = iSeries_get_rtc_time;964944 ppc_md.calibrate_decr = iSeries_calibrate_decr;965945 ppc_md.progress = iSeries_progress;946946+947947+ /* XXX Implement enable_pmcs for iSeries */966948967949 if (get_paca()->lppaca.shared_proc) {968950 ppc_md.idle_loop = iseries_shared_idle;
+144
arch/ppc64/kernel/iSeries_vio.c
···11+/*22+ * IBM PowerPC iSeries Virtual I/O Infrastructure Support.33+ *44+ * Copyright (c) 2005 Stephen Rothwell, IBM Corp.55+ *66+ * This program is free software; you can redistribute it and/or77+ * modify it under the terms of the GNU General Public License88+ * as published by the Free Software Foundation; either version99+ * 2 of the License, or (at your option) any later version.1010+ */1111+#include <linux/types.h>1212+#include <linux/device.h>1313+#include <linux/init.h>1414+1515+#include <asm/vio.h>1616+#include <asm/iommu.h>1717+#include <asm/abs_addr.h>1818+#include <asm/page.h>1919+#include <asm/iSeries/vio.h>2020+#include <asm/iSeries/HvTypes.h>2121+#include <asm/iSeries/HvLpConfig.h>2222+#include <asm/iSeries/HvCallXm.h>2323+2424+struct device *iSeries_vio_dev = &vio_bus_device.dev;2525+EXPORT_SYMBOL(iSeries_vio_dev);2626+2727+static struct iommu_table veth_iommu_table;2828+static struct iommu_table vio_iommu_table;2929+3030+static void __init iommu_vio_init(void)3131+{3232+ struct iommu_table *t;3333+ struct iommu_table_cb cb;3434+ unsigned long cbp;3535+ unsigned long itc_entries;3636+3737+ cb.itc_busno = 255; /* Bus 255 is the virtual bus */3838+ cb.itc_virtbus = 0xff; /* Ask for virtual bus */3939+4040+ cbp = virt_to_abs(&cb);4141+ HvCallXm_getTceTableParms(cbp);4242+4343+ itc_entries = cb.itc_size * PAGE_SIZE / sizeof(union tce_entry);4444+ veth_iommu_table.it_size = itc_entries / 2;4545+ veth_iommu_table.it_busno = cb.itc_busno;4646+ veth_iommu_table.it_offset = cb.itc_offset;4747+ veth_iommu_table.it_index = cb.itc_index;4848+ veth_iommu_table.it_type = TCE_VB;4949+ veth_iommu_table.it_blocksize = 1;5050+5151+ t = iommu_init_table(&veth_iommu_table);5252+5353+ if (!t)5454+ printk("Virtual Bus VETH TCE table failed.\n");5555+5656+ vio_iommu_table.it_size = itc_entries - veth_iommu_table.it_size;5757+ vio_iommu_table.it_busno = cb.itc_busno;5858+ vio_iommu_table.it_offset = cb.itc_offset +5959+ veth_iommu_table.it_size;6060+ vio_iommu_table.it_index = cb.itc_index;6161+ vio_iommu_table.it_type = TCE_VB;6262+ vio_iommu_table.it_blocksize = 1;6363+6464+ t = iommu_init_table(&vio_iommu_table);6565+6666+ if (!t)6767+ printk("Virtual Bus VIO TCE table failed.\n");6868+}6969+7070+/**7171+ * vio_register_device: - Register a new vio device.7272+ * @voidev: The device to register.7373+ */7474+static struct vio_dev *__init vio_register_device_iseries(char *type,7575+ uint32_t unit_num)7676+{7777+ struct vio_dev *viodev;7878+7979+ /* allocate a vio_dev for this node */8080+ viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);8181+ if (!viodev)8282+ return NULL;8383+ memset(viodev, 0, sizeof(struct vio_dev));8484+8585+ snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%s%d", type, unit_num);8686+8787+ return vio_register_device_common(viodev, viodev->dev.bus_id, type,8888+ unit_num, &vio_iommu_table);8989+}9090+9191+void __init probe_bus_iseries(void)9292+{9393+ HvLpIndexMap vlan_map;9494+ struct vio_dev *viodev;9595+ int i;9696+9797+ /* there is only one of each of these */9898+ vio_register_device_iseries("viocons", 0);9999+ vio_register_device_iseries("vscsi", 0);100100+101101+ vlan_map = HvLpConfig_getVirtualLanIndexMap();102102+ for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {103103+ if ((vlan_map & (0x8000 >> i)) == 0)104104+ continue;105105+ viodev = vio_register_device_iseries("vlan", i);106106+ /* veth is special and has it own iommu_table */107107+ viodev->iommu_table = &veth_iommu_table;108108+ }109109+ for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)110110+ vio_register_device_iseries("viodasd", i);111111+ for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)112112+ vio_register_device_iseries("viocd", i);113113+ for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)114114+ vio_register_device_iseries("viotape", i);115115+}116116+117117+/**118118+ * vio_match_device_iseries: - Tell if a iSeries VIO device matches a119119+ * vio_device_id120120+ */121121+static int vio_match_device_iseries(const struct vio_device_id *id,122122+ const struct vio_dev *dev)123123+{124124+ return strncmp(dev->type, id->type, strlen(id->type)) == 0;125125+}126126+127127+/**128128+ * vio_bus_init_iseries: - Initialize the iSeries virtual IO bus129129+ */130130+static int __init vio_bus_init_iseries(void)131131+{132132+ int err;133133+134134+ err = vio_bus_init(vio_match_device_iseries, NULL, NULL);135135+ if (err == 0) {136136+ iommu_vio_init();137137+ vio_bus_device.iommu_table = &vio_iommu_table;138138+ iSeries_vio_dev = &vio_bus_device.dev;139139+ probe_bus_iseries();140140+ }141141+ return err;142142+}143143+144144+__initcall(vio_bus_init_iseries);
+38-111
arch/ppc64/kernel/lmb.c
···2828{2929#ifdef DEBUG3030 unsigned long i;3131- struct lmb *_lmb = &lmb;32313332 udbg_printf("lmb_dump_all:\n");3433 udbg_printf(" memory.cnt = 0x%lx\n",3535- _lmb->memory.cnt);3434+ lmb.memory.cnt);3635 udbg_printf(" memory.size = 0x%lx\n",3737- _lmb->memory.size);3838- for (i=0; i < _lmb->memory.cnt ;i++) {3636+ lmb.memory.size);3737+ for (i=0; i < lmb.memory.cnt ;i++) {3938 udbg_printf(" memory.region[0x%x].base = 0x%lx\n",4040- i, _lmb->memory.region[i].base);4141- udbg_printf(" .physbase = 0x%lx\n",4242- _lmb->memory.region[i].physbase);3939+ i, lmb.memory.region[i].base);4340 udbg_printf(" .size = 0x%lx\n",4444- _lmb->memory.region[i].size);4141+ lmb.memory.region[i].size);4542 }46434744 udbg_printf("\n reserved.cnt = 0x%lx\n",4848- _lmb->reserved.cnt);4545+ lmb.reserved.cnt);4946 udbg_printf(" reserved.size = 0x%lx\n",5050- _lmb->reserved.size);5151- for (i=0; i < _lmb->reserved.cnt ;i++) {4747+ lmb.reserved.size);4848+ for (i=0; i < lmb.reserved.cnt ;i++) {5249 udbg_printf(" reserved.region[0x%x].base = 0x%lx\n",5353- i, _lmb->reserved.region[i].base);5454- udbg_printf(" .physbase = 0x%lx\n",5555- _lmb->reserved.region[i].physbase);5050+ i, lmb.reserved.region[i].base);5651 udbg_printf(" .size = 0x%lx\n",5757- _lmb->reserved.region[i].size);5252+ lmb.reserved.region[i].size);5853 }5954#endif /* DEBUG */6055}···9398 rgn->region[r1].size += rgn->region[r2].size;9499 for (i=r2; i < rgn->cnt-1; i++) {95100 rgn->region[i].base = rgn->region[i+1].base;9696- rgn->region[i].physbase = rgn->region[i+1].physbase;97101 rgn->region[i].size = rgn->region[i+1].size;98102 }99103 rgn->cnt--;···102108void __init103109lmb_init(void)104110{105105- struct lmb *_lmb = &lmb;106106-107111 /* Create a dummy zero size LMB which will get coalesced away later.108112 * This simplifies the lmb_add() code below...109113 */110110- _lmb->memory.region[0].base = 0;111111- _lmb->memory.region[0].size = 0;112112- _lmb->memory.cnt = 1;114114+ lmb.memory.region[0].base = 0;115115+ lmb.memory.region[0].size = 0;116116+ lmb.memory.cnt = 1;113117114118 /* Ditto. */115115- _lmb->reserved.region[0].base = 0;116116- _lmb->reserved.region[0].size = 0;117117- _lmb->reserved.cnt = 1;119119+ lmb.reserved.region[0].base = 0;120120+ lmb.reserved.region[0].size = 0;121121+ lmb.reserved.cnt = 1;118122}119123120124/* This routine called with relocation disabled. */121125void __init122126lmb_analyze(void)123127{124124- unsigned long i;125125- unsigned long mem_size = 0;126126- unsigned long size_mask = 0;127127- struct lmb *_lmb = &lmb;128128-#ifdef CONFIG_MSCHUNKS129129- unsigned long physbase = 0;130130-#endif128128+ int i;131129132132- for (i=0; i < _lmb->memory.cnt; i++) {133133- unsigned long lmb_size;130130+ lmb.memory.size = 0;134131135135- lmb_size = _lmb->memory.region[i].size;136136-137137-#ifdef CONFIG_MSCHUNKS138138- _lmb->memory.region[i].physbase = physbase;139139- physbase += lmb_size;140140-#else141141- _lmb->memory.region[i].physbase = _lmb->memory.region[i].base;142142-#endif143143- mem_size += lmb_size;144144- size_mask |= lmb_size;145145- }146146-147147- _lmb->memory.size = mem_size;132132+ for (i = 0; i < lmb.memory.cnt; i++)133133+ lmb.memory.size += lmb.memory.region[i].size;148134}149135150136/* This routine called with relocation disabled. */···142168 adjacent = lmb_addrs_adjacent(base,size,rgnbase,rgnsize);143169 if ( adjacent > 0 ) {144170 rgn->region[i].base -= size;145145- rgn->region[i].physbase -= size;146171 rgn->region[i].size += size;147172 coalesced++;148173 break;···168195 for (i=rgn->cnt-1; i >= 0; i--) {169196 if (base < rgn->region[i].base) {170197 rgn->region[i+1].base = rgn->region[i].base;171171- rgn->region[i+1].physbase = rgn->region[i].physbase;172198 rgn->region[i+1].size = rgn->region[i].size;173199 } else {174200 rgn->region[i+1].base = base;175175- rgn->region[i+1].physbase = lmb_abs_to_phys(base);176201 rgn->region[i+1].size = size;177202 break;178203 }···184213long __init185214lmb_add(unsigned long base, unsigned long size)186215{187187- struct lmb *_lmb = &lmb;188188- struct lmb_region *_rgn = &(_lmb->memory);216216+ struct lmb_region *_rgn = &(lmb.memory);189217190218 /* On pSeries LPAR systems, the first LMB is our RMO region. */191219 if ( base == 0 )192192- _lmb->rmo_size = size;220220+ lmb.rmo_size = size;193221194222 return lmb_add_region(_rgn, base, size);195223···197227long __init198228lmb_reserve(unsigned long base, unsigned long size)199229{200200- struct lmb *_lmb = &lmb;201201- struct lmb_region *_rgn = &(_lmb->reserved);230230+ struct lmb_region *_rgn = &(lmb.reserved);202231203232 return lmb_add_region(_rgn, base, size);204233}···229260{230261 long i, j;231262 unsigned long base = 0;232232- struct lmb *_lmb = &lmb;233233- struct lmb_region *_mem = &(_lmb->memory);234234- struct lmb_region *_rsv = &(_lmb->reserved);235263236236- for (i=_mem->cnt-1; i >= 0; i--) {237237- unsigned long lmbbase = _mem->region[i].base;238238- unsigned long lmbsize = _mem->region[i].size;264264+ for (i=lmb.memory.cnt-1; i >= 0; i--) {265265+ unsigned long lmbbase = lmb.memory.region[i].base;266266+ unsigned long lmbsize = lmb.memory.region[i].size;239267240268 if ( max_addr == LMB_ALLOC_ANYWHERE )241269 base = _ALIGN_DOWN(lmbbase+lmbsize-size, align);···242276 continue;243277244278 while ( (lmbbase <= base) &&245245- ((j = lmb_overlaps_region(_rsv,base,size)) >= 0) ) {246246- base = _ALIGN_DOWN(_rsv->region[j].base-size, align);279279+ ((j = lmb_overlaps_region(&lmb.reserved,base,size)) >= 0) ) {280280+ base = _ALIGN_DOWN(lmb.reserved.region[j].base-size, align);247281 }248282249283 if ( (base != 0) && (lmbbase <= base) )···253287 if ( i < 0 )254288 return 0;255289256256- lmb_add_region(_rsv, base, size);290290+ lmb_add_region(&lmb.reserved, base, size);257291258292 return base;259293}260294295295+/* You must call lmb_analyze() before this. */261296unsigned long __init262297lmb_phys_mem_size(void)263298{264264- struct lmb *_lmb = &lmb;265265-#ifdef CONFIG_MSCHUNKS266266- return _lmb->memory.size;267267-#else268268- struct lmb_region *_mem = &(_lmb->memory);269269- unsigned long total = 0;270270- int i;271271-272272- /* add all physical memory to the bootmem map */273273- for (i=0; i < _mem->cnt; i++)274274- total += _mem->region[i].size;275275- return total;276276-#endif /* CONFIG_MSCHUNKS */299299+ return lmb.memory.size;277300}278301279302unsigned long __init280303lmb_end_of_DRAM(void)281304{282282- struct lmb *_lmb = &lmb;283283- struct lmb_region *_mem = &(_lmb->memory);284284- int idx = _mem->cnt - 1;305305+ int idx = lmb.memory.cnt - 1;285306286286-#ifdef CONFIG_MSCHUNKS287287- return (_mem->region[idx].physbase + _mem->region[idx].size);288288-#else289289- return (_mem->region[idx].base + _mem->region[idx].size);290290-#endif /* CONFIG_MSCHUNKS */291291-292292- return 0;293293-}294294-295295-unsigned long __init296296-lmb_abs_to_phys(unsigned long aa)297297-{298298- unsigned long i, pa = aa;299299- struct lmb *_lmb = &lmb;300300- struct lmb_region *_mem = &(_lmb->memory);301301-302302- for (i=0; i < _mem->cnt; i++) {303303- unsigned long lmbbase = _mem->region[i].base;304304- unsigned long lmbsize = _mem->region[i].size;305305- if ( lmb_addrs_overlap(aa,1,lmbbase,lmbsize) ) {306306- pa = _mem->region[i].physbase + (aa - lmbbase);307307- break;308308- }309309- }310310-311311- return pa;307307+ return (lmb.memory.region[idx].base + lmb.memory.region[idx].size);312308}313309314310/*···281353{282354 extern unsigned long memory_limit;283355 unsigned long i, limit;284284- struct lmb_region *mem = &(lmb.memory);285356286357 if (! memory_limit)287358 return;288359289360 limit = memory_limit;290290- for (i = 0; i < mem->cnt; i++) {291291- if (limit > mem->region[i].size) {292292- limit -= mem->region[i].size;361361+ for (i = 0; i < lmb.memory.cnt; i++) {362362+ if (limit > lmb.memory.region[i].size) {363363+ limit -= lmb.memory.region[i].size;293364 continue;294365 }295366296296- mem->region[i].size = limit;297297- mem->cnt = i + 1;367367+ lmb.memory.region[i].size = limit;368368+ lmb.memory.cnt = i + 1;298369 break;299370 }300371}
+3-3
arch/ppc64/kernel/lparcfg.c
···2929#include <asm/iSeries/HvLpConfig.h>3030#include <asm/lppaca.h>3131#include <asm/hvcall.h>3232-#include <asm/cputable.h>3232+#include <asm/firmware.h>3333#include <asm/rtas.h>3434#include <asm/system.h>3535#include <asm/time.h>···377377378378 partition_active_processors = lparcfg_count_active_processors();379379380380- if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {380380+ if (firmware_has_feature(FW_FEATURE_SPLPAR)) {381381 unsigned long h_entitled, h_unallocated;382382 unsigned long h_aggregation, h_resource;383383 unsigned long pool_idle_time, pool_procs;···571571 mode_t mode = S_IRUSR;572572573573 /* Allow writing if we have FW_FEATURE_SPLPAR */574574- if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {574574+ if (firmware_has_feature(FW_FEATURE_SPLPAR)) {575575 lparcfg_fops.write = lparcfg_write;576576 mode |= S_IWUSR;577577 }
+98
arch/ppc64/kernel/misc.S
···680680 ld r30,-16(r1)681681 blr682682683683+/*684684+ * disable_kernel_fp()685685+ * Disable the FPU.686686+ */687687+_GLOBAL(disable_kernel_fp)688688+ mfmsr r3689689+ rldicl r0,r3,(63-MSR_FP_LG),1690690+ rldicl r3,r0,(MSR_FP_LG+1),0691691+ mtmsrd r3 /* disable use of fpu now */692692+ isync693693+ blr694694+695695+/*696696+ * giveup_fpu(tsk)697697+ * Disable FP for the task given as the argument,698698+ * and save the floating-point registers in its thread_struct.699699+ * Enables the FPU for use in the kernel on return.700700+ */701701+_GLOBAL(giveup_fpu)702702+ mfmsr r5703703+ ori r5,r5,MSR_FP704704+ mtmsrd r5 /* enable use of fpu now */705705+ isync706706+ cmpdi 0,r3,0707707+ beqlr- /* if no previous owner, done */708708+ addi r3,r3,THREAD /* want THREAD of task */709709+ ld r5,PT_REGS(r3)710710+ cmpdi 0,r5,0711711+ SAVE_32FPRS(0, r3)712712+ mffs fr0713713+ stfd fr0,THREAD_FPSCR(r3)714714+ beq 1f715715+ ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)716716+ li r3,MSR_FP|MSR_FE0|MSR_FE1717717+ andc r4,r4,r3 /* disable FP for previous task */718718+ std r4,_MSR-STACK_FRAME_OVERHEAD(r5)719719+1:720720+#ifndef CONFIG_SMP721721+ li r5,0722722+ ld r4,last_task_used_math@got(r2)723723+ std r5,0(r4)724724+#endif /* CONFIG_SMP */725725+ blr726726+727727+#ifdef CONFIG_ALTIVEC728728+729729+#if 0 /* this has no callers for now */730730+/*731731+ * disable_kernel_altivec()732732+ * Disable the VMX.733733+ */734734+_GLOBAL(disable_kernel_altivec)735735+ mfmsr r3736736+ rldicl r0,r3,(63-MSR_VEC_LG),1737737+ rldicl r3,r0,(MSR_VEC_LG+1),0738738+ mtmsrd r3 /* disable use of VMX now */739739+ isync740740+ blr741741+#endif /* 0 */742742+743743+/*744744+ * giveup_altivec(tsk)745745+ * Disable VMX for the task given as the argument,746746+ * and save the vector registers in its thread_struct.747747+ * Enables the VMX for use in the kernel on return.748748+ */749749+_GLOBAL(giveup_altivec)750750+ mfmsr r5751751+ oris r5,r5,MSR_VEC@h752752+ mtmsrd r5 /* enable use of VMX now */753753+ isync754754+ cmpdi 0,r3,0755755+ beqlr- /* if no previous owner, done */756756+ addi r3,r3,THREAD /* want THREAD of task */757757+ ld r5,PT_REGS(r3)758758+ cmpdi 0,r5,0759759+ SAVE_32VRS(0,r4,r3)760760+ mfvscr vr0761761+ li r4,THREAD_VSCR762762+ stvx vr0,r4,r3763763+ beq 1f764764+ ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)765765+ lis r3,MSR_VEC@h766766+ andc r4,r4,r3 /* disable FP for previous task */767767+ std r4,_MSR-STACK_FRAME_OVERHEAD(r5)768768+1:769769+#ifndef CONFIG_SMP770770+ li r5,0771771+ ld r4,last_task_used_altivec@got(r2)772772+ std r5,0(r4)773773+#endif /* CONFIG_SMP */774774+ blr775775+776776+#endif /* CONFIG_ALTIVEC */777777+778778+_GLOBAL(__setup_cpu_power3)779779+ blr780780+683781/* kexec_wait(phys_cpu)684782 *685783 * wait for the flag to change, indicating this kernel is going away but
+2-1
arch/ppc64/kernel/pSeries_iommu.c
···4545#include <asm/plpar_wrappers.h>4646#include <asm/pSeries_reconfig.h>4747#include <asm/systemcfg.h>4848+#include <asm/firmware.h>4849#include "pci.h"49505051#define DBG(fmt...)···547546 }548547549548 if (systemcfg->platform & PLATFORM_LPAR) {550550- if (cur_cpu_spec->firmware_features & FW_FEATURE_MULTITCE) {549549+ if (firmware_has_feature(FW_FEATURE_MULTITCE)) {551550 ppc_md.tce_build = tce_buildmulti_pSeriesLP;552551 ppc_md.tce_free = tce_freemulti_pSeriesLP;553552 } else {
+1-3
arch/ppc64/kernel/pSeries_lpar.c
···5252EXPORT_SYMBOL(plpar_hcall_norets);5353EXPORT_SYMBOL(plpar_hcall_8arg_2ret);54545555-extern void fw_feature_init(void);5655extern void pSeries_find_serial_port(void);57565857···278279 unsigned long va, unsigned long prpn,279280 unsigned long vflags, unsigned long rflags)280281{281281- unsigned long arpn = physRpn_to_absRpn(prpn);282282 unsigned long lpar_rc;283283 unsigned long flags;284284 unsigned long slot;···288290 if (vflags & HPTE_V_LARGE)289291 hpte_v &= ~(1UL << HPTE_V_AVPN_SHIFT);290292291291- hpte_r = (arpn << HPTE_R_RPN_SHIFT) | rflags;293293+ hpte_r = (prpn << HPTE_R_RPN_SHIFT) | rflags;292294293295 /* Now fill in the actual HPTE */294296 /* Set CEC cookie to 0 */
+29-10
arch/ppc64/kernel/pSeries_setup.c
···6060#include <asm/nvram.h>6161#include <asm/plpar_wrappers.h>6262#include <asm/xics.h>6363-#include <asm/cputable.h>6363+#include <asm/firmware.h>6464+#include <asm/pmc.h>64656566#include "i8259.h"6667#include "mpic.h"···188187 " MPIC ");189188}190189190190+static void pseries_lpar_enable_pmcs(void)191191+{192192+ unsigned long set, reset;193193+194194+ power4_enable_pmcs();195195+196196+ set = 1UL << 63;197197+ reset = 0;198198+ plpar_hcall_norets(H_PERFMON, set, reset);199199+200200+ /* instruct hypervisor to maintain PMCs */201201+ if (firmware_has_feature(FW_FEATURE_SPLPAR))202202+ get_paca()->lppaca.pmcregs_in_use = 1;203203+}204204+191205static void __init pSeries_setup_arch(void)192206{193207 /* Fixup ppc_md depending on the type of interrupt controller */···247231248232 pSeries_nvram_init();249233250250- if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)251251- vpa_init(boot_cpuid);252252-253234 /* Choose an idle loop */254254- if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {235235+ if (firmware_has_feature(FW_FEATURE_SPLPAR)) {236236+ vpa_init(boot_cpuid);255237 if (get_paca()->lppaca.shared_proc) {256238 printk(KERN_INFO "Using shared processor idle loop\n");257239 ppc_md.idle_loop = pseries_shared_idle;···261247 printk(KERN_INFO "Using default idle loop\n");262248 ppc_md.idle_loop = default_idle;263249 }250250+251251+ if (systemcfg->platform & PLATFORM_LPAR)252252+ ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;253253+ else254254+ ppc_md.enable_pmcs = power4_enable_pmcs;264255}265256266257static int __init pSeries_init_panel(void)···279260arch_initcall(pSeries_init_panel);280261281262282282-/* Build up the firmware_features bitmask field263263+/* Build up the ppc64_firmware_features bitmask field283264 * using contents of device-tree/ibm,hypertas-functions.284265 * Ultimately this functionality may be moved into prom.c prom_init().285266 */286286-void __init fw_feature_init(void)267267+static void __init fw_feature_init(void)287268{288269 struct device_node * dn;289270 char * hypertas;···291272292273 DBG(" -> fw_feature_init()\n");293274294294- cur_cpu_spec->firmware_features = 0;275275+ ppc64_firmware_features = 0;295276 dn = of_find_node_by_path("/rtas");296277 if (dn == NULL) {297278 printk(KERN_ERR "WARNING ! Cannot find RTAS in device-tree !\n");···307288 if ((firmware_features_table[i].name) &&308289 (strcmp(firmware_features_table[i].name,hypertas))==0) {309290 /* we have a match */310310- cur_cpu_spec->firmware_features |= 291291+ ppc64_firmware_features |= 311292 (firmware_features_table[i].val);312293 break;313294 } ···321302 of_node_put(dn);322303 no_rtas:323304 printk(KERN_INFO "firmware_features = 0x%lx\n", 324324- cur_cpu_spec->firmware_features);305305+ ppc64_firmware_features);325306326307 DBG(" <- fw_feature_init()\n");327308}
+2-1
arch/ppc64/kernel/pSeries_smp.c
···4141#include <asm/machdep.h>4242#include <asm/xics.h>4343#include <asm/cputable.h>4444+#include <asm/firmware.h>4445#include <asm/system.h>4546#include <asm/rtas.h>4647#include <asm/plpar_wrappers.h>···327326 if (cpu != boot_cpuid)328327 xics_setup_cpu();329328330330- if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)329329+ if (firmware_has_feature(FW_FEATURE_SPLPAR))331330 vpa_init(cpu);332331333332 cpu_clear(cpu, of_spin_map);
+266
arch/ppc64/kernel/pSeries_vio.c
···11+/*22+ * IBM PowerPC pSeries Virtual I/O Infrastructure Support.33+ *44+ * Copyright (c) 2003-2005 IBM Corp.55+ * Dave Engebretsen engebret@us.ibm.com66+ * Santiago Leon santil@us.ibm.com77+ * Hollis Blanchard <hollisb@us.ibm.com>88+ * Stephen Rothwell99+ *1010+ * This program is free software; you can redistribute it and/or1111+ * modify it under the terms of the GNU General Public License1212+ * as published by the Free Software Foundation; either version1313+ * 2 of the License, or (at your option) any later version.1414+ */1515+1616+#include <linux/init.h>1717+#include <linux/module.h>1818+#include <linux/mm.h>1919+#include <linux/kobject.h>2020+#include <asm/iommu.h>2121+#include <asm/dma.h>2222+#include <asm/vio.h>2323+#include <asm/hvcall.h>2424+2525+extern struct subsystem devices_subsys; /* needed for vio_find_name() */2626+2727+static void probe_bus_pseries(void)2828+{2929+ struct device_node *node_vroot, *of_node;3030+3131+ node_vroot = find_devices("vdevice");3232+ if ((node_vroot == NULL) || (node_vroot->child == NULL))3333+ /* this machine doesn't do virtual IO, and that's ok */3434+ return;3535+3636+ /*3737+ * Create struct vio_devices for each virtual device in the device tree.3838+ * Drivers will associate with them later.3939+ */4040+ for (of_node = node_vroot->child; of_node != NULL;4141+ of_node = of_node->sibling) {4242+ printk(KERN_DEBUG "%s: processing %p\n", __FUNCTION__, of_node);4343+ vio_register_device_node(of_node);4444+ }4545+}4646+4747+/**4848+ * vio_match_device_pseries: - Tell if a pSeries VIO device matches a4949+ * vio_device_id5050+ */5151+static int vio_match_device_pseries(const struct vio_device_id *id,5252+ const struct vio_dev *dev)5353+{5454+ return (strncmp(dev->type, id->type, strlen(id->type)) == 0) &&5555+ device_is_compatible(dev->dev.platform_data, id->compat);5656+}5757+5858+static void vio_release_device_pseries(struct device *dev)5959+{6060+ /* XXX free TCE table */6161+ of_node_put(dev->platform_data);6262+}6363+6464+static ssize_t viodev_show_devspec(struct device *dev,6565+ struct device_attribute *attr, char *buf)6666+{6767+ struct device_node *of_node = dev->platform_data;6868+6969+ return sprintf(buf, "%s\n", of_node->full_name);7070+}7171+DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL);7272+7373+static void vio_unregister_device_pseries(struct vio_dev *viodev)7474+{7575+ device_remove_file(&viodev->dev, &dev_attr_devspec);7676+}7777+7878+/**7979+ * vio_bus_init_pseries: - Initialize the pSeries virtual IO bus8080+ */8181+static int __init vio_bus_init_pseries(void)8282+{8383+ int err;8484+8585+ err = vio_bus_init(vio_match_device_pseries,8686+ vio_unregister_device_pseries,8787+ vio_release_device_pseries);8888+ if (err == 0)8989+ probe_bus_pseries();9090+ return err;9191+}9292+9393+__initcall(vio_bus_init_pseries);9494+9595+/**9696+ * vio_build_iommu_table: - gets the dma information from OF and9797+ * builds the TCE tree.9898+ * @dev: the virtual device.9999+ *100100+ * Returns a pointer to the built tce tree, or NULL if it can't101101+ * find property.102102+*/103103+static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)104104+{105105+ unsigned int *dma_window;106106+ struct iommu_table *newTceTable;107107+ unsigned long offset;108108+ int dma_window_property_size;109109+110110+ dma_window = (unsigned int *) get_property(dev->dev.platform_data, "ibm,my-dma-window", &dma_window_property_size);111111+ if(!dma_window) {112112+ return NULL;113113+ }114114+115115+ newTceTable = (struct iommu_table *) kmalloc(sizeof(struct iommu_table), GFP_KERNEL);116116+117117+ /* There should be some code to extract the phys-encoded offset118118+ using prom_n_addr_cells(). However, according to a comment119119+ on earlier versions, it's always zero, so we don't bother */120120+ offset = dma_window[1] >> PAGE_SHIFT;121121+122122+ /* TCE table size - measured in tce entries */123123+ newTceTable->it_size = dma_window[4] >> PAGE_SHIFT;124124+ /* offset for VIO should always be 0 */125125+ newTceTable->it_offset = offset;126126+ newTceTable->it_busno = 0;127127+ newTceTable->it_index = (unsigned long)dma_window[0];128128+ newTceTable->it_type = TCE_VB;129129+130130+ return iommu_init_table(newTceTable);131131+}132132+133133+/**134134+ * vio_register_device_node: - Register a new vio device.135135+ * @of_node: The OF node for this device.136136+ *137137+ * Creates and initializes a vio_dev structure from the data in138138+ * of_node (dev.platform_data) and adds it to the list of virtual devices.139139+ * Returns a pointer to the created vio_dev or NULL if node has140140+ * NULL device_type or compatible fields.141141+ */142142+struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)143143+{144144+ struct vio_dev *viodev;145145+ unsigned int *unit_address;146146+ unsigned int *irq_p;147147+148148+ /* we need the 'device_type' property, in order to match with drivers */149149+ if ((NULL == of_node->type)) {150150+ printk(KERN_WARNING151151+ "%s: node %s missing 'device_type'\n", __FUNCTION__,152152+ of_node->name ? of_node->name : "<unknown>");153153+ return NULL;154154+ }155155+156156+ unit_address = (unsigned int *)get_property(of_node, "reg", NULL);157157+ if (!unit_address) {158158+ printk(KERN_WARNING "%s: node %s missing 'reg'\n", __FUNCTION__,159159+ of_node->name ? of_node->name : "<unknown>");160160+ return NULL;161161+ }162162+163163+ /* allocate a vio_dev for this node */164164+ viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);165165+ if (!viodev) {166166+ return NULL;167167+ }168168+ memset(viodev, 0, sizeof(struct vio_dev));169169+170170+ viodev->dev.platform_data = of_node_get(of_node);171171+172172+ viodev->irq = NO_IRQ;173173+ irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL);174174+ if (irq_p) {175175+ int virq = virt_irq_create_mapping(*irq_p);176176+ if (virq == NO_IRQ) {177177+ printk(KERN_ERR "Unable to allocate interrupt "178178+ "number for %s\n", of_node->full_name);179179+ } else180180+ viodev->irq = irq_offset_up(virq);181181+ }182182+183183+ snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address);184184+185185+ /* register with generic device framework */186186+ if (vio_register_device_common(viodev, of_node->name, of_node->type,187187+ *unit_address, vio_build_iommu_table(viodev))188188+ == NULL) {189189+ /* XXX free TCE table */190190+ kfree(viodev);191191+ return NULL;192192+ }193193+ device_create_file(&viodev->dev, &dev_attr_devspec);194194+195195+ return viodev;196196+}197197+EXPORT_SYMBOL(vio_register_device_node);198198+199199+/**200200+ * vio_get_attribute: - get attribute for virtual device201201+ * @vdev: The vio device to get property.202202+ * @which: The property/attribute to be extracted.203203+ * @length: Pointer to length of returned data size (unused if NULL).204204+ *205205+ * Calls prom.c's get_property() to return the value of the206206+ * attribute specified by the preprocessor constant @which207207+*/208208+const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length)209209+{210210+ return get_property(vdev->dev.platform_data, (char*)which, length);211211+}212212+EXPORT_SYMBOL(vio_get_attribute);213213+214214+/* vio_find_name() - internal because only vio.c knows how we formatted the215215+ * kobject name216216+ * XXX once vio_bus_type.devices is actually used as a kset in217217+ * drivers/base/bus.c, this function should be removed in favor of218218+ * "device_find(kobj_name, &vio_bus_type)"219219+ */220220+static struct vio_dev *vio_find_name(const char *kobj_name)221221+{222222+ struct kobject *found;223223+224224+ found = kset_find_obj(&devices_subsys.kset, kobj_name);225225+ if (!found)226226+ return NULL;227227+228228+ return to_vio_dev(container_of(found, struct device, kobj));229229+}230230+231231+/**232232+ * vio_find_node - find an already-registered vio_dev233233+ * @vnode: device_node of the virtual device we're looking for234234+ */235235+struct vio_dev *vio_find_node(struct device_node *vnode)236236+{237237+ uint32_t *unit_address;238238+ char kobj_name[BUS_ID_SIZE];239239+240240+ /* construct the kobject name from the device node */241241+ unit_address = (uint32_t *)get_property(vnode, "reg", NULL);242242+ if (!unit_address)243243+ return NULL;244244+ snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address);245245+246246+ return vio_find_name(kobj_name);247247+}248248+EXPORT_SYMBOL(vio_find_node);249249+250250+int vio_enable_interrupts(struct vio_dev *dev)251251+{252252+ int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE);253253+ if (rc != H_Success)254254+ printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc);255255+ return rc;256256+}257257+EXPORT_SYMBOL(vio_enable_interrupts);258258+259259+int vio_disable_interrupts(struct vio_dev *dev)260260+{261261+ int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE);262262+ if (rc != H_Success)263263+ printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc);264264+ return rc;265265+}266266+EXPORT_SYMBOL(vio_disable_interrupts);
···5050#include <asm/machdep.h>5151#include <asm/iSeries/HvCallHpt.h>5252#include <asm/cputable.h>5353+#include <asm/firmware.h>5354#include <asm/sections.h>5455#include <asm/tlbflush.h>5556#include <asm/time.h>···203202 new_thread = &new->thread;204203 old_thread = ¤t->thread;205204206206-/* Collect purr utilization data per process and per processor wise */207207-/* purr is nothing but processor time base */208208-209209-#if defined(CONFIG_PPC_PSERIES)210210- if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {205205+ /* Collect purr utilization data per process and per processor206206+ * wise purr is nothing but processor time base207207+ */208208+ if (firmware_has_feature(FW_FEATURE_SPLPAR)) {211209 struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array);212210 long unsigned start_tb, current_tb;213211 start_tb = old_thread->start_tb;···214214 old_thread->accum_tb += (current_tb - start_tb);215215 new_thread->start_tb = current_tb;216216 }217217-#endif218218-219217220218 local_irq_save(flags);221219 last = _switch(old_thread, new_thread);
+152-32
arch/ppc64/kernel/prom.c
···625625626626static inline char *find_flat_dt_string(u32 offset)627627{628628- return ((char *)initial_boot_params) + initial_boot_params->off_dt_strings629629- + offset;628628+ return ((char *)initial_boot_params) +629629+ initial_boot_params->off_dt_strings + offset;630630}631631632632/**···635635 * unflatten the tree636636 */637637static int __init scan_flat_dt(int (*it)(unsigned long node,638638- const char *full_path, void *data),638638+ const char *uname, int depth,639639+ void *data),639640 void *data)640641{641642 unsigned long p = ((unsigned long)initial_boot_params) +642643 initial_boot_params->off_dt_struct;643644 int rc = 0;645645+ int depth = -1;644646645647 do {646648 u32 tag = *((u32 *)p);647649 char *pathp;648650649651 p += 4;650650- if (tag == OF_DT_END_NODE)652652+ if (tag == OF_DT_END_NODE) {653653+ depth --;654654+ continue;655655+ }656656+ if (tag == OF_DT_NOP)651657 continue;652658 if (tag == OF_DT_END)653659 break;654660 if (tag == OF_DT_PROP) {655661 u32 sz = *((u32 *)p);656662 p += 8;657657- p = _ALIGN(p, sz >= 8 ? 8 : 4);663663+ if (initial_boot_params->version < 0x10)664664+ p = _ALIGN(p, sz >= 8 ? 8 : 4);658665 p += sz;659666 p = _ALIGN(p, 4);660667 continue;···671664 " device tree !\n", tag);672665 return -EINVAL;673666 }667667+ depth++;674668 pathp = (char *)p;675669 p = _ALIGN(p + strlen(pathp) + 1, 4);676676- rc = it(p, pathp, data);670670+ if ((*pathp) == '/') {671671+ char *lp, *np;672672+ for (lp = NULL, np = pathp; *np; np++)673673+ if ((*np) == '/')674674+ lp = np+1;675675+ if (lp != NULL)676676+ pathp = lp;677677+ }678678+ rc = it(p, pathp, depth, data);677679 if (rc != 0)678680 break; 679681 } while(1);···705689 const char *nstr;706690707691 p += 4;692692+ if (tag == OF_DT_NOP)693693+ continue;708694 if (tag != OF_DT_PROP)709695 return NULL;710696711697 sz = *((u32 *)p);712698 noff = *((u32 *)(p + 4));713699 p += 8;714714- p = _ALIGN(p, sz >= 8 ? 8 : 4);700700+ if (initial_boot_params->version < 0x10)701701+ p = _ALIGN(p, sz >= 8 ? 8 : 4);715702716703 nstr = find_flat_dt_string(noff);717704 if (nstr == NULL) {718718- printk(KERN_WARNING "Can't find property index name !\n");705705+ printk(KERN_WARNING "Can't find property index"706706+ " name !\n");719707 return NULL;720708 }721709 if (strcmp(name, nstr) == 0) {···733713}734714735715static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,736736- unsigned long align)716716+ unsigned long align)737717{738718 void *res;739719···747727static unsigned long __init unflatten_dt_node(unsigned long mem,748728 unsigned long *p,749729 struct device_node *dad,750750- struct device_node ***allnextpp)730730+ struct device_node ***allnextpp,731731+ unsigned long fpsize)751732{752733 struct device_node *np;753734 struct property *pp, **prev_pp = NULL;754735 char *pathp;755736 u32 tag;756756- unsigned int l;737737+ unsigned int l, allocl;738738+ int has_name = 0;739739+ int new_format = 0;757740758741 tag = *((u32 *)(*p));759742 if (tag != OF_DT_BEGIN_NODE) {···765742 }766743 *p += 4;767744 pathp = (char *)*p;768768- l = strlen(pathp) + 1;745745+ l = allocl = strlen(pathp) + 1;769746 *p = _ALIGN(*p + l, 4);770747771771- np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + l,748748+ /* version 0x10 has a more compact unit name here instead of the full749749+ * path. we accumulate the full path size using "fpsize", we'll rebuild750750+ * it later. We detect this because the first character of the name is751751+ * not '/'.752752+ */753753+ if ((*pathp) != '/') {754754+ new_format = 1;755755+ if (fpsize == 0) {756756+ /* root node: special case. fpsize accounts for path757757+ * plus terminating zero. root node only has '/', so758758+ * fpsize should be 2, but we want to avoid the first759759+ * level nodes to have two '/' so we use fpsize 1 here760760+ */761761+ fpsize = 1;762762+ allocl = 2;763763+ } else {764764+ /* account for '/' and path size minus terminal 0765765+ * already in 'l'766766+ */767767+ fpsize += l;768768+ allocl = fpsize;769769+ }770770+ }771771+772772+773773+ np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,772774 __alignof__(struct device_node));773775 if (allnextpp) {774776 memset(np, 0, sizeof(*np));775777 np->full_name = ((char*)np) + sizeof(struct device_node);776776- memcpy(np->full_name, pathp, l);778778+ if (new_format) {779779+ char *p = np->full_name;780780+ /* rebuild full path for new format */781781+ if (dad && dad->parent) {782782+ strcpy(p, dad->full_name);783783+#ifdef DEBUG784784+ if ((strlen(p) + l + 1) != allocl) {785785+ DBG("%s: p: %d, l: %d, a: %d\n",786786+ pathp, strlen(p), l, allocl);787787+ }788788+#endif789789+ p += strlen(p);790790+ }791791+ *(p++) = '/';792792+ memcpy(p, pathp, l);793793+ } else794794+ memcpy(np->full_name, pathp, l);777795 prev_pp = &np->properties;778796 **allnextpp = np;779797 *allnextpp = &np->allnext;780798 if (dad != NULL) {781799 np->parent = dad;782782- /* we temporarily use the `next' field as `last_child'. */800800+ /* we temporarily use the next field as `last_child'*/783801 if (dad->next == 0)784802 dad->child = np;785803 else···834770 char *pname;835771836772 tag = *((u32 *)(*p));773773+ if (tag == OF_DT_NOP) {774774+ *p += 4;775775+ continue;776776+ }837777 if (tag != OF_DT_PROP)838778 break;839779 *p += 4;840780 sz = *((u32 *)(*p));841781 noff = *((u32 *)((*p) + 4));842842- *p = _ALIGN((*p) + 8, sz >= 8 ? 8 : 4);782782+ *p += 8;783783+ if (initial_boot_params->version < 0x10)784784+ *p = _ALIGN(*p, sz >= 8 ? 8 : 4);843785844786 pname = find_flat_dt_string(noff);845787 if (pname == NULL) {846788 printk("Can't find property name in list !\n");847789 break;848790 }791791+ if (strcmp(pname, "name") == 0)792792+ has_name = 1;849793 l = strlen(pname) + 1;850794 pp = unflatten_dt_alloc(&mem, sizeof(struct property),851795 __alignof__(struct property));···873801 }874802 *p = _ALIGN((*p) + sz, 4);875803 }804804+ /* with version 0x10 we may not have the name property, recreate805805+ * it here from the unit name if absent806806+ */807807+ if (!has_name) {808808+ char *p = pathp, *ps = pathp, *pa = NULL;809809+ int sz;810810+811811+ while (*p) {812812+ if ((*p) == '@')813813+ pa = p;814814+ if ((*p) == '/')815815+ ps = p + 1;816816+ p++;817817+ }818818+ if (pa < ps)819819+ pa = p;820820+ sz = (pa - ps) + 1;821821+ pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz,822822+ __alignof__(struct property));823823+ if (allnextpp) {824824+ pp->name = "name";825825+ pp->length = sz;826826+ pp->value = (unsigned char *)(pp + 1);827827+ *prev_pp = pp;828828+ prev_pp = &pp->next;829829+ memcpy(pp->value, ps, sz - 1);830830+ ((char *)pp->value)[sz - 1] = 0;831831+ DBG("fixed up name for %s -> %s\n", pathp, pp->value);832832+ }833833+ }876834 if (allnextpp) {877835 *prev_pp = NULL;878836 np->name = get_property(np, "name", NULL);···914812 np->type = "<NULL>";915813 }916814 while (tag == OF_DT_BEGIN_NODE) {917917- mem = unflatten_dt_node(mem, p, np, allnextpp);815815+ mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize);918816 tag = *((u32 *)(*p));919817 }920818 if (tag != OF_DT_END_NODE) {921921- printk("Weird tag at start of node: %x\n", tag);819819+ printk("Weird tag at end of node: %x\n", tag);922820 return mem;923821 }924822 *p += 4;···944842 /* First pass, scan for size */945843 start = ((unsigned long)initial_boot_params) +946844 initial_boot_params->off_dt_struct;947947- size = unflatten_dt_node(0, &start, NULL, NULL);845845+ size = unflatten_dt_node(0, &start, NULL, NULL, 0);846846+ size = (size | 3) + 1;948847949848 DBG(" size is %lx, allocating...\n", size);950849951850 /* Allocate memory for the expanded device tree */952952- mem = (unsigned long)abs_to_virt(lmb_alloc(size,953953- __alignof__(struct device_node)));851851+ mem = lmb_alloc(size + 4, __alignof__(struct device_node));852852+ if (!mem) {853853+ DBG("Couldn't allocate memory with lmb_alloc()!\n");854854+ panic("Couldn't allocate memory with lmb_alloc()!\n");855855+ }856856+ mem = (unsigned long)abs_to_virt(mem);857857+858858+ ((u32 *)mem)[size / 4] = 0xdeadbeef;859859+954860 DBG(" unflattening...\n", mem);955861956862 /* Second pass, do actual unflattening */957863 start = ((unsigned long)initial_boot_params) +958864 initial_boot_params->off_dt_struct;959959- unflatten_dt_node(mem, &start, NULL, &allnextp);865865+ unflatten_dt_node(mem, &start, NULL, &allnextp, 0);960866 if (*((u32 *)start) != OF_DT_END)961961- printk(KERN_WARNING "Weird tag at end of tree: %x\n", *((u32 *)start));867867+ printk(KERN_WARNING "Weird tag at end of tree: %08x\n", *((u32 *)start));868868+ if (((u32 *)mem)[size / 4] != 0xdeadbeef)869869+ printk(KERN_WARNING "End of tree marker overwritten: %08x\n",870870+ ((u32 *)mem)[size / 4] );962871 *allnextp = NULL;963872964873 /* Get pointer to OF "/chosen" node for use everywhere */···993880994881995882static int __init early_init_dt_scan_cpus(unsigned long node,996996- const char *full_path, void *data)883883+ const char *uname, int depth, void *data)997884{998885 char *type = get_flat_dt_prop(node, "device_type", NULL);999886 u32 *prop;···1060947}10619481062949static int __init early_init_dt_scan_chosen(unsigned long node,10631063- const char *full_path, void *data)950950+ const char *uname, int depth, void *data)1064951{1065952 u32 *prop;1066953 u64 *prop64;1067954 extern unsigned long memory_limit, tce_alloc_start, tce_alloc_end;106895510691069- if (strcmp(full_path, "/chosen") != 0)956956+ DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname);957957+958958+ if (depth != 1 || strcmp(uname, "chosen") != 0)1070959 return 0;10719601072961 /* get platform type */···11181003}1119100411201005static int __init early_init_dt_scan_root(unsigned long node,11211121- const char *full_path, void *data)10061006+ const char *uname, int depth, void *data)11221007{11231008 u32 *prop;1124100911251125- if (strcmp(full_path, "/") != 0)10101010+ if (depth != 0)11261011 return 0;1127101211281013 prop = (u32 *)get_flat_dt_prop(node, "#size-cells", NULL);11291014 dt_root_size_cells = (prop == NULL) ? 1 : *prop;11301130-10151015+ DBG("dt_root_size_cells = %x\n", dt_root_size_cells);10161016+11311017 prop = (u32 *)get_flat_dt_prop(node, "#address-cells", NULL);11321018 dt_root_addr_cells = (prop == NULL) ? 2 : *prop;10191019+ DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells);1133102011341021 /* break now */11351022 return 1;···115910421160104311611044static int __init early_init_dt_scan_memory(unsigned long node,11621162- const char *full_path, void *data)10451045+ const char *uname, int depth, void *data)11631046{11641047 char *type = get_flat_dt_prop(node, "device_type", NULL);11651048 cell_t *reg, *endp;···1175105811761059 endp = reg + (l / sizeof(cell_t));1177106011781178- DBG("memory scan node %s ...\n", full_path);10611061+ DBG("memory scan node %s ..., reg size %ld, data: %x %x %x %x, ...\n",10621062+ uname, l, reg[0], reg[1], reg[2], reg[3]);10631063+11791064 while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {11801065 unsigned long base, size;11811066···15881469 struct device_node *np = allnodes;1589147015901471 read_lock(&devtree_lock);15911591- for (; np != 0; np = np->allnext)14721472+ for (; np != 0; np = np->allnext) {15921473 if (np->full_name != 0 && strcasecmp(np->full_name, path) == 015931474 && of_node_get(np))15941475 break;14761476+ }15951477 read_unlock(&devtree_lock);15961478 return np;15971479}
+55-33
arch/ppc64/kernel/prom_init.c
···15341534 */15351535#define MAX_PROPERTY_NAME 641536153615371537-static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,15371537+static void __init scan_dt_build_strings(phandle node,15381538+ unsigned long *mem_start,15381539 unsigned long *mem_end)15391540{15401541 unsigned long offset = reloc_offset();···15481547 /* get and store all property names */15491548 prev_name = RELOC("");15501549 for (;;) {15511551- int rc;15521552-15531550 /* 64 is max len of name including nul. */15541551 namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);15551555- rc = call_prom("nextprop", 3, 1, node, prev_name, namep);15561556- if (rc != 1) {15521552+ if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) {15571553 /* No more nodes: unwind alloc */15581554 *mem_start = (unsigned long)namep;15591555 break;15601556 }15571557+15581558+ /* skip "name" */15591559+ if (strcmp(namep, RELOC("name")) == 0) {15601560+ *mem_start = (unsigned long)namep;15611561+ prev_name = RELOC("name");15621562+ continue;15631563+ }15641564+ /* get/create string entry */15611565 soff = dt_find_string(namep);15621566 if (soff != 0) {15631567 *mem_start = (unsigned long)namep;···1577157115781572 /* do all our children */15791573 child = call_prom("child", 1, 1, node);15801580- while (child != (phandle)0) {15741574+ while (child != 0) {15811575 scan_dt_build_strings(child, mem_start, mem_end);15821576 child = call_prom("peer", 1, 1, child);15831577 }···15861580static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,15871581 unsigned long *mem_end)15881582{15891589- int l, align;15901583 phandle child;15911591- char *namep, *prev_name, *sstart, *p, *ep;15841584+ char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;15921585 unsigned long soff;15931586 unsigned char *valp;15941587 unsigned long offset = reloc_offset();15951595- char pname[MAX_PROPERTY_NAME];15961596- char *path;15971597-15981598- path = RELOC(prom_scratch);15881588+ static char pname[MAX_PROPERTY_NAME];15891589+ int l;1599159016001591 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);16011592···16021599 namep, *mem_end - *mem_start);16031600 if (l >= 0) {16041601 /* Didn't fit? Get more room. */16051605- if (l+1 > *mem_end - *mem_start) {16021602+ if ((l+1) > (*mem_end - *mem_start)) {16061603 namep = make_room(mem_start, mem_end, l+1, 1);16071604 call_prom("package-to-path", 3, 1, node, namep, l);16081605 }16091606 namep[l] = '\0';16071607+16101608 /* Fixup an Apple bug where they have bogus \0 chars in the16111609 * middle of the path in some properties16121610 */16131611 for (p = namep, ep = namep + l; p < ep; p++)16141612 if (*p == '\0') {16151613 memmove(p, p+1, ep - p);16161616- ep--; l--;16141614+ ep--; l--; p--;16171615 }16181618- *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4);16161616+16171617+ /* now try to extract the unit name in that mess */16181618+ for (p = namep, lp = NULL; *p; p++)16191619+ if (*p == '/')16201620+ lp = p + 1;16211621+ if (lp != NULL)16221622+ memmove(namep, lp, strlen(lp) + 1);16231623+ *mem_start = _ALIGN(((unsigned long) namep) +16241624+ strlen(namep) + 1, 4);16191625 }1620162616211627 /* get it again for debugging */16281628+ path = RELOC(prom_scratch);16221629 memset(path, 0, PROM_SCRATCH_SIZE);16231630 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);16241631···16361623 prev_name = RELOC("");16371624 sstart = (char *)RELOC(dt_string_start);16381625 for (;;) {16391639- int rc;16401640-16411641- rc = call_prom("nextprop", 3, 1, node, prev_name, pname);16421642- if (rc != 1)16261626+ if (call_prom("nextprop", 3, 1, node, prev_name,16271627+ RELOC(pname)) != 1)16431628 break;1644162916301630+ /* skip "name" */16311631+ if (strcmp(RELOC(pname), RELOC("name")) == 0) {16321632+ prev_name = RELOC("name");16331633+ continue;16341634+ }16351635+16451636 /* find string offset */16461646- soff = dt_find_string(pname);16371637+ soff = dt_find_string(RELOC(pname));16471638 if (soff == 0) {16481648- prom_printf("WARNING: Can't find string index for <%s>, node %s\n",16491649- pname, path);16391639+ prom_printf("WARNING: Can't find string index for"16401640+ " <%s>, node %s\n", RELOC(pname), path);16501641 break;16511642 }16521643 prev_name = sstart + soff;1653164416541645 /* get length */16551655- l = call_prom("getproplen", 2, 1, node, pname);16461646+ l = call_prom("getproplen", 2, 1, node, RELOC(pname));1656164716571648 /* sanity checks */16581649 if (l == PROM_ERROR)···16651648 prom_printf("WARNING: ignoring large property ");16661649 /* It seems OF doesn't null-terminate the path :-( */16671650 prom_printf("[%s] ", path);16681668- prom_printf("%s length 0x%x\n", pname, l);16511651+ prom_printf("%s length 0x%x\n", RELOC(pname), l);16691652 continue;16701653 }16711654···16751658 dt_push_token(soff, mem_start, mem_end);1676165916771660 /* push property content */16781678- align = (l >= 8) ? 8 : 4;16791679- valp = make_room(mem_start, mem_end, l, align);16801680- call_prom("getprop", 4, 1, node, pname, valp, l);16611661+ valp = make_room(mem_start, mem_end, l, 4);16621662+ call_prom("getprop", 4, 1, node, RELOC(pname), valp, l);16811663 *mem_start = _ALIGN(*mem_start, 4);16821664 }1683166516841666 /* Add a "linux,phandle" property. */16851667 soff = dt_find_string(RELOC("linux,phandle"));16861668 if (soff == 0)16871687- prom_printf("WARNING: Can't find string index for <linux-phandle>"16881688- " node %s\n", path);16691669+ prom_printf("WARNING: Can't find string index for"16701670+ " <linux-phandle> node %s\n", path);16891671 else {16901672 dt_push_token(OF_DT_PROP, mem_start, mem_end);16911673 dt_push_token(4, mem_start, mem_end);···1695167916961680 /* do all our children */16971681 child = call_prom("child", 1, 1, node);16981698- while (child != (phandle)0) {16821682+ while (child != 0) {16991683 scan_dt_build_struct(child, mem_start, mem_end);17001684 child = call_prom("peer", 1, 1, child);17011685 }···1734171817351719 /* Build header and make room for mem rsv map */ 17361720 mem_start = _ALIGN(mem_start, 4);17371737- hdr = make_room(&mem_start, &mem_end, sizeof(struct boot_param_header), 4);17211721+ hdr = make_room(&mem_start, &mem_end,17221722+ sizeof(struct boot_param_header), 4);17381723 RELOC(dt_header_start) = (unsigned long)hdr;17391724 rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);17401725···17481731 namep = make_room(&mem_start, &mem_end, 16, 1);17491732 strcpy(namep, RELOC("linux,phandle"));17501733 mem_start = (unsigned long)namep + strlen(namep) + 1;17511751- RELOC(dt_string_end) = mem_start;1752173417531735 /* Build string array */17541736 prom_printf("Building dt strings...\n"); 17551737 scan_dt_build_strings(root, &mem_start, &mem_end);17381738+ RELOC(dt_string_end) = mem_start;1756173917571740 /* Build structure */17581741 mem_start = PAGE_ALIGN(mem_start);···17671750 hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start);17681751 hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start);17691752 hdr->off_dt_strings = RELOC(dt_string_start) - RELOC(dt_header_start);17531753+ hdr->dt_strings_size = RELOC(dt_string_end) - RELOC(dt_string_start);17701754 hdr->off_mem_rsvmap = ((unsigned long)rsvmap) - RELOC(dt_header_start);17711755 hdr->version = OF_DT_VERSION;17721772- hdr->last_comp_version = 1;17561756+ /* Version 16 is not backward compatible */17571757+ hdr->last_comp_version = 0x10;1773175817741759 /* Reserve the whole thing and copy the reserve map in, we17751760 * also bump mem_reserve_cnt to cause further reservations to···18271808 /* does it need fixup ? */18281809 if (prom_getproplen(i2c, "interrupts") > 0)18291810 return;18111811+18121812+ prom_printf("fixing up bogus interrupts for u3 i2c...\n");18131813+18301814 /* interrupt on this revision of u3 is number 0 and level */18311815 interrupts[0] = 0;18321816 interrupts[1] = 1;
+17-2
arch/ppc64/kernel/rtas_pci.c
···5858 return 0;5959}60606161+static int of_device_available(struct device_node * dn)6262+{6363+ char * status;6464+6565+ status = get_property(dn, "status", NULL);6666+6767+ if (!status)6868+ return 1;6969+7070+ if (!strcmp(status, "okay"))7171+ return 1;7272+7373+ return 0;7474+}7575+6176static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val)6277{6378 int returnval = -1;···118103119104 /* Search only direct children of the bus */120105 for (dn = busdn->child; dn; dn = dn->sibling)121121- if (dn->devfn == devfn)106106+ if (dn->devfn == devfn && of_device_available(dn))122107 return rtas_read_config(dn, where, size, val);123108 return PCIBIOS_DEVICE_NOT_FOUND;124109}···161146162147 /* Search only direct children of the bus */163148 for (dn = busdn->child; dn; dn = dn->sibling)164164- if (dn->devfn == devfn)149149+ if (dn->devfn == devfn && of_device_available(dn))165150 return rtas_write_config(dn, where, size, val);166151 return PCIBIOS_DEVICE_NOT_FOUND;167152}
+17-11
arch/ppc64/kernel/setup.c
···536536537537 DBG(" -> check_for_initrd()\n");538538539539- prop = (u64 *)get_property(of_chosen, "linux,initrd-start", NULL);540540- if (prop != NULL) {541541- initrd_start = (unsigned long)__va(*prop);542542- prop = (u64 *)get_property(of_chosen, "linux,initrd-end", NULL);539539+ if (of_chosen) {540540+ prop = (u64 *)get_property(of_chosen,541541+ "linux,initrd-start", NULL);543542 if (prop != NULL) {544544- initrd_end = (unsigned long)__va(*prop);545545- initrd_below_start_ok = 1;546546- } else547547- initrd_start = 0;543543+ initrd_start = (unsigned long)__va(*prop);544544+ prop = (u64 *)get_property(of_chosen,545545+ "linux,initrd-end", NULL);546546+ if (prop != NULL) {547547+ initrd_end = (unsigned long)__va(*prop);548548+ initrd_below_start_ok = 1;549549+ } else550550+ initrd_start = 0;551551+ }548552 }549553550554 /* If we were passed an initrd, set the ROOT_DEV properly if the values···631627 * Initialize xmon632628 */633629#ifdef CONFIG_XMON_DEFAULT634634- xmon_init();630630+ xmon_init(1);635631#endif636632 /*637633 * Register early console···13471343 /* ensure xmon is enabled */13481344 if (p) {13491345 if (strncmp(p, "on", 2) == 0)13501350- xmon_init();13461346+ xmon_init(1);13471347+ if (strncmp(p, "off", 3) == 0)13481348+ xmon_init(0);13511349 if (strncmp(p, "early", 5) != 0)13521350 return 0;13531351 }13541354- xmon_init();13521352+ xmon_init(1);13551353 debugger(NULL);1356135413571355 return 0;
+5-52
arch/ppc64/kernel/sysfs.c
···1313#include <asm/current.h>1414#include <asm/processor.h>1515#include <asm/cputable.h>1616+#include <asm/firmware.h>1617#include <asm/hvcall.h>1718#include <asm/prom.h>1819#include <asm/systemcfg.h>···101100}102101__setup("smt-snooze-delay=", setup_smt_snooze_delay);103102103103+#endif /* CONFIG_PPC_MULTIPLATFORM */104104+104105/*105106 * Enabling PMCs will slow partition context switch times so we only do106107 * it the first time we write to the PMCs.···112109113110void ppc64_enable_pmcs(void)114111{115115- unsigned long hid0;116116-#ifdef CONFIG_PPC_PSERIES117117- unsigned long set, reset;118118-#endif /* CONFIG_PPC_PSERIES */119119-120112 /* Only need to enable them once */121113 if (__get_cpu_var(pmcs_enabled))122114 return;123115124116 __get_cpu_var(pmcs_enabled) = 1;125117126126- switch (systemcfg->platform) {127127- case PLATFORM_PSERIES:128128- case PLATFORM_POWERMAC:129129- hid0 = mfspr(HID0);130130- hid0 |= 1UL << (63 - 20);131131-132132- /* POWER4 requires the following sequence */133133- asm volatile(134134- "sync\n"135135- "mtspr %1, %0\n"136136- "mfspr %0, %1\n"137137- "mfspr %0, %1\n"138138- "mfspr %0, %1\n"139139- "mfspr %0, %1\n"140140- "mfspr %0, %1\n"141141- "mfspr %0, %1\n"142142- "isync" : "=&r" (hid0) : "i" (HID0), "0" (hid0):143143- "memory");144144- break;145145-146146-#ifdef CONFIG_PPC_PSERIES147147- case PLATFORM_PSERIES_LPAR:148148- set = 1UL << 63;149149- reset = 0;150150- plpar_hcall_norets(H_PERFMON, set, reset);151151- break;152152-#endif /* CONFIG_PPC_PSERIES */153153-154154- default:155155- break;156156- }157157-158158-#ifdef CONFIG_PPC_PSERIES159159- /* instruct hypervisor to maintain PMCs */160160- if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)161161- get_paca()->lppaca.pmcregs_in_use = 1;162162-#endif /* CONFIG_PPC_PSERIES */118118+ if (ppc_md.enable_pmcs)119119+ ppc_md.enable_pmcs();163120}164164-165165-#else166166-167167-/* PMC stuff */168168-void ppc64_enable_pmcs(void)169169-{170170- /* XXX Implement for iseries */171171-}172172-#endif /* CONFIG_PPC_MULTIPLATFORM */173173-174121EXPORT_SYMBOL(ppc64_enable_pmcs);175122176123/* XXX convert to rusty's on_one_cpu */
+3-4
arch/ppc64/kernel/time.c
···6767#include <asm/prom.h>6868#include <asm/sections.h>6969#include <asm/systemcfg.h>7070+#include <asm/firmware.h>70717172u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES;7273···371370 process_hvlpevents(regs);372371#endif373372374374-/* collect purr register values often, for accurate calculations */375375-#if defined(CONFIG_PPC_PSERIES)376376- if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {373373+ /* collect purr register values often, for accurate calculations */374374+ if (firmware_has_feature(FW_FEATURE_SPLPAR)) {377375 struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array);378376 cu->current_tb = mfspr(SPRN_PURR);379377 }380380-#endif381378382379 irq_exit();383380
+26-381
arch/ppc64/kernel/vio.c
···11/*22 * IBM PowerPC Virtual I/O Infrastructure Support.33 *44- * Copyright (c) 2003 IBM Corp.44+ * Copyright (c) 2003-2005 IBM Corp.55 * Dave Engebretsen engebret@us.ibm.com66 * Santiago Leon santil@us.ibm.com77 * Hollis Blanchard <hollisb@us.ibm.com>88+ * Stephen Rothwell89 *910 * This program is free software; you can redistribute it and/or1011 * modify it under the terms of the GNU General Public License···15141615#include <linux/init.h>1716#include <linux/console.h>1818-#include <linux/version.h>1917#include <linux/module.h>2020-#include <linux/kobject.h>2118#include <linux/mm.h>2219#include <linux/dma-mapping.h>2323-#include <asm/rtas.h>2420#include <asm/iommu.h>2521#include <asm/dma.h>2626-#include <asm/ppcdebug.h>2722#include <asm/vio.h>2828-#include <asm/hvcall.h>2929-#include <asm/iSeries/vio.h>3030-#include <asm/iSeries/HvTypes.h>3131-#include <asm/iSeries/HvCallXm.h>3232-#include <asm/iSeries/HvLpConfig.h>3333-3434-#define DBGENTER() pr_debug("%s entered\n", __FUNCTION__)3535-3636-extern struct subsystem devices_subsys; /* needed for vio_find_name() */37233824static const struct vio_device_id *vio_match_device(3925 const struct vio_device_id *, const struct vio_dev *);40264141-#ifdef CONFIG_PPC_PSERIES4242-static struct iommu_table *vio_build_iommu_table(struct vio_dev *);4343-static int vio_num_address_cells;4444-#endif4545-#ifdef CONFIG_PPC_ISERIES4646-static struct iommu_table veth_iommu_table;4747-static struct iommu_table vio_iommu_table;4848-#endif4949-static struct vio_dev vio_bus_device = { /* fake "parent" device */2727+struct vio_dev vio_bus_device = { /* fake "parent" device */5028 .name = vio_bus_device.dev.bus_id,5129 .type = "",5252-#ifdef CONFIG_PPC_ISERIES5353- .iommu_table = &vio_iommu_table,5454-#endif5530 .dev.bus_id = "vio",5631 .dev.bus = &vio_bus_type,5732};58335959-#ifdef CONFIG_PPC_ISERIES6060-static struct vio_dev *__init vio_register_device_iseries(char *type,6161- uint32_t unit_num);6262-6363-struct device *iSeries_vio_dev = &vio_bus_device.dev;6464-EXPORT_SYMBOL(iSeries_vio_dev);6565-6666-#define device_is_compatible(a, b) 16767-6868-#endif3434+static int (*is_match)(const struct vio_device_id *id,3535+ const struct vio_dev *dev);3636+static void (*unregister_device_callback)(struct vio_dev *dev);3737+static void (*release_device_callback)(struct device *dev);69387039/* convert from struct device to struct vio_dev and pass to driver.7140 * dev->driver has already been set by generic code because vio_bus_match···4675 struct vio_driver *viodrv = to_vio_driver(dev->driver);4776 const struct vio_device_id *id;4877 int error = -ENODEV;4949-5050- DBGENTER();51785279 if (!viodrv->probe)5380 return error;···6394{6495 struct vio_dev *viodev = to_vio_dev(dev);6596 struct vio_driver *viodrv = to_vio_driver(dev->driver);6666-6767- DBGENTER();68976998 if (viodrv->remove) {7099 return viodrv->remove(viodev);···113146static const struct vio_device_id * vio_match_device(const struct vio_device_id *ids,114147 const struct vio_dev *dev)115148{116116- DBGENTER();117117-118149 while (ids->type) {119119- if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) &&120120- device_is_compatible(dev->dev.platform_data, ids->compat))150150+ if (is_match(ids, dev))121151 return ids;122152 ids++;123153 }124154 return NULL;125155}126156127127-#ifdef CONFIG_PPC_ISERIES128128-void __init iommu_vio_init(void)129129-{130130- struct iommu_table *t;131131- struct iommu_table_cb cb;132132- unsigned long cbp;133133- unsigned long itc_entries;134134-135135- cb.itc_busno = 255; /* Bus 255 is the virtual bus */136136- cb.itc_virtbus = 0xff; /* Ask for virtual bus */137137-138138- cbp = virt_to_abs(&cb);139139- HvCallXm_getTceTableParms(cbp);140140-141141- itc_entries = cb.itc_size * PAGE_SIZE / sizeof(union tce_entry);142142- veth_iommu_table.it_size = itc_entries / 2;143143- veth_iommu_table.it_busno = cb.itc_busno;144144- veth_iommu_table.it_offset = cb.itc_offset;145145- veth_iommu_table.it_index = cb.itc_index;146146- veth_iommu_table.it_type = TCE_VB;147147- veth_iommu_table.it_blocksize = 1;148148-149149- t = iommu_init_table(&veth_iommu_table);150150-151151- if (!t)152152- printk("Virtual Bus VETH TCE table failed.\n");153153-154154- vio_iommu_table.it_size = itc_entries - veth_iommu_table.it_size;155155- vio_iommu_table.it_busno = cb.itc_busno;156156- vio_iommu_table.it_offset = cb.itc_offset +157157- veth_iommu_table.it_size;158158- vio_iommu_table.it_index = cb.itc_index;159159- vio_iommu_table.it_type = TCE_VB;160160- vio_iommu_table.it_blocksize = 1;161161-162162- t = iommu_init_table(&vio_iommu_table);163163-164164- if (!t)165165- printk("Virtual Bus VIO TCE table failed.\n");166166-}167167-#endif168168-169169-#ifdef CONFIG_PPC_PSERIES170170-static void probe_bus_pseries(void)171171-{172172- struct device_node *node_vroot, *of_node;173173-174174- node_vroot = find_devices("vdevice");175175- if ((node_vroot == NULL) || (node_vroot->child == NULL))176176- /* this machine doesn't do virtual IO, and that's ok */177177- return;178178-179179- vio_num_address_cells = prom_n_addr_cells(node_vroot->child);180180-181181- /*182182- * Create struct vio_devices for each virtual device in the device tree.183183- * Drivers will associate with them later.184184- */185185- for (of_node = node_vroot->child; of_node != NULL;186186- of_node = of_node->sibling) {187187- printk(KERN_DEBUG "%s: processing %p\n", __FUNCTION__, of_node);188188- vio_register_device_node(of_node);189189- }190190-}191191-#endif192192-193193-#ifdef CONFIG_PPC_ISERIES194194-static void probe_bus_iseries(void)195195-{196196- HvLpIndexMap vlan_map = HvLpConfig_getVirtualLanIndexMap();197197- struct vio_dev *viodev;198198- int i;199199-200200- /* there is only one of each of these */201201- vio_register_device_iseries("viocons", 0);202202- vio_register_device_iseries("vscsi", 0);203203-204204- vlan_map = HvLpConfig_getVirtualLanIndexMap();205205- for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {206206- if ((vlan_map & (0x8000 >> i)) == 0)207207- continue;208208- viodev = vio_register_device_iseries("vlan", i);209209- /* veth is special and has it own iommu_table */210210- viodev->iommu_table = &veth_iommu_table;211211- }212212- for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)213213- vio_register_device_iseries("viodasd", i);214214- for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)215215- vio_register_device_iseries("viocd", i);216216- for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)217217- vio_register_device_iseries("viotape", i);218218-}219219-#endif220220-221157/**222158 * vio_bus_init: - Initialize the virtual IO bus223159 */224224-static int __init vio_bus_init(void)160160+int __init vio_bus_init(int (*match_func)(const struct vio_device_id *id,161161+ const struct vio_dev *dev),162162+ void (*unregister_dev)(struct vio_dev *),163163+ void (*release_dev)(struct device *))225164{226165 int err;166166+167167+ is_match = match_func;168168+ unregister_device_callback = unregister_dev;169169+ release_device_callback = release_dev;227170228171 err = bus_register(&vio_bus_type);229172 if (err) {···141264 return err;142265 }143266144144- /* the fake parent of all vio devices, just to give us a nice directory */267267+ /* the fake parent of all vio devices, just to give us268268+ * a nice directory269269+ */145270 err = device_register(&vio_bus_device.dev);146271 if (err) {147147- printk(KERN_WARNING "%s: device_register returned %i\n", __FUNCTION__,148148- err);272272+ printk(KERN_WARNING "%s: device_register returned %i\n",273273+ __FUNCTION__, err);149274 return err;150275 }151151-152152-#ifdef CONFIG_PPC_PSERIES153153- probe_bus_pseries();154154-#endif155155-#ifdef CONFIG_PPC_ISERIES156156- probe_bus_iseries();157157-#endif158276159277 return 0;160278}161279162162-__initcall(vio_bus_init);163163-164280/* vio_dev refcount hit 0 */165281static void __devinit vio_dev_release(struct device *dev)166282{167167- DBGENTER();168168-169169-#ifdef CONFIG_PPC_PSERIES170170- /* XXX free TCE table */171171- of_node_put(dev->platform_data);172172-#endif283283+ if (release_device_callback)284284+ release_device_callback(dev);173285 kfree(to_vio_dev(dev));174286}175175-176176-#ifdef CONFIG_PPC_PSERIES177177-static ssize_t viodev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)178178-{179179- struct device_node *of_node = dev->platform_data;180180-181181- return sprintf(buf, "%s\n", of_node->full_name);182182-}183183-DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL);184184-#endif185287186288static ssize_t viodev_show_name(struct device *dev, struct device_attribute *attr, char *buf)187289{···168312}169313DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_name, NULL);170314171171-static struct vio_dev * __devinit vio_register_device_common(315315+struct vio_dev * __devinit vio_register_device_common(172316 struct vio_dev *viodev, char *name, char *type,173317 uint32_t unit_address, struct iommu_table *iommu_table)174318{175175- DBGENTER();176176-177319 viodev->name = name;178320 viodev->type = type;179321 viodev->unit_address = unit_address;···192338 return viodev;193339}194340195195-#ifdef CONFIG_PPC_PSERIES196196-/**197197- * vio_register_device_node: - Register a new vio device.198198- * @of_node: The OF node for this device.199199- *200200- * Creates and initializes a vio_dev structure from the data in201201- * of_node (dev.platform_data) and adds it to the list of virtual devices.202202- * Returns a pointer to the created vio_dev or NULL if node has203203- * NULL device_type or compatible fields.204204- */205205-struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)206206-{207207- struct vio_dev *viodev;208208- unsigned int *unit_address;209209- unsigned int *irq_p;210210-211211- DBGENTER();212212-213213- /* we need the 'device_type' property, in order to match with drivers */214214- if ((NULL == of_node->type)) {215215- printk(KERN_WARNING216216- "%s: node %s missing 'device_type'\n", __FUNCTION__,217217- of_node->name ? of_node->name : "<unknown>");218218- return NULL;219219- }220220-221221- unit_address = (unsigned int *)get_property(of_node, "reg", NULL);222222- if (!unit_address) {223223- printk(KERN_WARNING "%s: node %s missing 'reg'\n", __FUNCTION__,224224- of_node->name ? of_node->name : "<unknown>");225225- return NULL;226226- }227227-228228- /* allocate a vio_dev for this node */229229- viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);230230- if (!viodev) {231231- return NULL;232232- }233233- memset(viodev, 0, sizeof(struct vio_dev));234234-235235- viodev->dev.platform_data = of_node_get(of_node);236236-237237- viodev->irq = NO_IRQ;238238- irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL);239239- if (irq_p) {240240- int virq = virt_irq_create_mapping(*irq_p);241241- if (virq == NO_IRQ) {242242- printk(KERN_ERR "Unable to allocate interrupt "243243- "number for %s\n", of_node->full_name);244244- } else245245- viodev->irq = irq_offset_up(virq);246246- }247247-248248- snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address);249249-250250- /* register with generic device framework */251251- if (vio_register_device_common(viodev, of_node->name, of_node->type,252252- *unit_address, vio_build_iommu_table(viodev))253253- == NULL) {254254- /* XXX free TCE table */255255- kfree(viodev);256256- return NULL;257257- }258258- device_create_file(&viodev->dev, &dev_attr_devspec);259259-260260- return viodev;261261-}262262-EXPORT_SYMBOL(vio_register_device_node);263263-#endif264264-265265-#ifdef CONFIG_PPC_ISERIES266266-/**267267- * vio_register_device: - Register a new vio device.268268- * @voidev: The device to register.269269- */270270-static struct vio_dev *__init vio_register_device_iseries(char *type,271271- uint32_t unit_num)272272-{273273- struct vio_dev *viodev;274274-275275- DBGENTER();276276-277277- /* allocate a vio_dev for this node */278278- viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);279279- if (!viodev)280280- return NULL;281281- memset(viodev, 0, sizeof(struct vio_dev));282282-283283- snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%s%d", type, unit_num);284284-285285- return vio_register_device_common(viodev, viodev->dev.bus_id, type,286286- unit_num, &vio_iommu_table);287287-}288288-#endif289289-290341void __devinit vio_unregister_device(struct vio_dev *viodev)291342{292292- DBGENTER();293293-#ifdef CONFIG_PPC_PSERIES294294- device_remove_file(&viodev->dev, &dev_attr_devspec);295295-#endif343343+ if (unregister_device_callback)344344+ unregister_device_callback(viodev);296345 device_remove_file(&viodev->dev, &dev_attr_name);297346 device_unregister(&viodev->dev);298347}299348EXPORT_SYMBOL(vio_unregister_device);300300-301301-#ifdef CONFIG_PPC_PSERIES302302-/**303303- * vio_get_attribute: - get attribute for virtual device304304- * @vdev: The vio device to get property.305305- * @which: The property/attribute to be extracted.306306- * @length: Pointer to length of returned data size (unused if NULL).307307- *308308- * Calls prom.c's get_property() to return the value of the309309- * attribute specified by the preprocessor constant @which310310-*/311311-const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length)312312-{313313- return get_property(vdev->dev.platform_data, (char*)which, length);314314-}315315-EXPORT_SYMBOL(vio_get_attribute);316316-317317-/* vio_find_name() - internal because only vio.c knows how we formatted the318318- * kobject name319319- * XXX once vio_bus_type.devices is actually used as a kset in320320- * drivers/base/bus.c, this function should be removed in favor of321321- * "device_find(kobj_name, &vio_bus_type)"322322- */323323-static struct vio_dev *vio_find_name(const char *kobj_name)324324-{325325- struct kobject *found;326326-327327- found = kset_find_obj(&devices_subsys.kset, kobj_name);328328- if (!found)329329- return NULL;330330-331331- return to_vio_dev(container_of(found, struct device, kobj));332332-}333333-334334-/**335335- * vio_find_node - find an already-registered vio_dev336336- * @vnode: device_node of the virtual device we're looking for337337- */338338-struct vio_dev *vio_find_node(struct device_node *vnode)339339-{340340- uint32_t *unit_address;341341- char kobj_name[BUS_ID_SIZE];342342-343343- /* construct the kobject name from the device node */344344- unit_address = (uint32_t *)get_property(vnode, "reg", NULL);345345- if (!unit_address)346346- return NULL;347347- snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address);348348-349349- return vio_find_name(kobj_name);350350-}351351-EXPORT_SYMBOL(vio_find_node);352352-353353-/**354354- * vio_build_iommu_table: - gets the dma information from OF and builds the TCE tree.355355- * @dev: the virtual device.356356- *357357- * Returns a pointer to the built tce tree, or NULL if it can't358358- * find property.359359-*/360360-static struct iommu_table * vio_build_iommu_table(struct vio_dev *dev)361361-{362362- unsigned int *dma_window;363363- struct iommu_table *newTceTable;364364- unsigned long offset;365365- int dma_window_property_size;366366-367367- dma_window = (unsigned int *) get_property(dev->dev.platform_data, "ibm,my-dma-window", &dma_window_property_size);368368- if(!dma_window) {369369- return NULL;370370- }371371-372372- newTceTable = (struct iommu_table *) kmalloc(sizeof(struct iommu_table), GFP_KERNEL);373373-374374- /* There should be some code to extract the phys-encoded offset375375- using prom_n_addr_cells(). However, according to a comment376376- on earlier versions, it's always zero, so we don't bother */377377- offset = dma_window[1] >> PAGE_SHIFT;378378-379379- /* TCE table size - measured in tce entries */380380- newTceTable->it_size = dma_window[4] >> PAGE_SHIFT;381381- /* offset for VIO should always be 0 */382382- newTceTable->it_offset = offset;383383- newTceTable->it_busno = 0;384384- newTceTable->it_index = (unsigned long)dma_window[0];385385- newTceTable->it_type = TCE_VB;386386-387387- return iommu_init_table(newTceTable);388388-}389389-390390-int vio_enable_interrupts(struct vio_dev *dev)391391-{392392- int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE);393393- if (rc != H_Success) {394394- printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc);395395- }396396- return rc;397397-}398398-EXPORT_SYMBOL(vio_enable_interrupts);399399-400400-int vio_disable_interrupts(struct vio_dev *dev)401401-{402402- int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE);403403- if (rc != H_Success) {404404- printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc);405405- }406406- return rc;407407-}408408-EXPORT_SYMBOL(vio_disable_interrupts);409409-#endif410349411350static dma_addr_t vio_map_single(struct device *dev, void *vaddr,412351 size_t size, enum dma_data_direction direction)···263616 struct vio_driver *vio_drv = to_vio_driver(drv);264617 const struct vio_device_id *ids = vio_drv->id_table;265618 const struct vio_device_id *found_id;266266-267267- DBGENTER();268619269620 if (!ids)270621 return 0;
+1-2
arch/ppc64/mm/hash_native.c
···5151 unsigned long prpn, unsigned long vflags,5252 unsigned long rflags)5353{5454- unsigned long arpn = physRpn_to_absRpn(prpn);5554 hpte_t *hptep = htab_address + hpte_group;5655 unsigned long hpte_v, hpte_r;5756 int i;···7374 hpte_v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID;7475 if (vflags & HPTE_V_LARGE)7576 va &= ~(1UL << HPTE_V_AVPN_SHIFT);7676- hpte_r = (arpn << HPTE_R_RPN_SHIFT) | rflags;7777+ hpte_r = (prpn << HPTE_R_RPN_SHIFT) | rflags;77787879 hptep->r = hpte_r;7980 /* Guarantee the second dword is visible before the valid bit */
+2-2
arch/ppc64/mm/hash_utils.c
···210210211211 /* create bolted the linear mapping in the hash table */212212 for (i=0; i < lmb.memory.cnt; i++) {213213- base = lmb.memory.region[i].physbase + KERNELBASE;213213+ base = lmb.memory.region[i].base + KERNELBASE;214214 size = lmb.memory.region[i].size;215215216216 DBG("creating mapping for region: %lx : %lx\n", base, size);···302302 int local = 0;303303 cpumask_t tmp;304304305305- if ((ea & ~REGION_MASK) > EADDR_MASK)305305+ if ((ea & ~REGION_MASK) >= PGTABLE_RANGE)306306 return 1;307307308308 switch (REGION_ID(ea)) {
+222-186
arch/ppc64/mm/hugetlbpage.c
···27272828#include <linux/sysctl.h>29293030-#define HUGEPGDIR_SHIFT (HPAGE_SHIFT + PAGE_SHIFT - 3)3131-#define HUGEPGDIR_SIZE (1UL << HUGEPGDIR_SHIFT)3232-#define HUGEPGDIR_MASK (~(HUGEPGDIR_SIZE-1))3030+#define NUM_LOW_AREAS (0x100000000UL >> SID_SHIFT)3131+#define NUM_HIGH_AREAS (PGTABLE_RANGE >> HTLB_AREA_SHIFT)33323434-#define HUGEPTE_INDEX_SIZE 93535-#define HUGEPGD_INDEX_SIZE 103636-3737-#define PTRS_PER_HUGEPTE (1 << HUGEPTE_INDEX_SIZE)3838-#define PTRS_PER_HUGEPGD (1 << HUGEPGD_INDEX_SIZE)3939-4040-static inline int hugepgd_index(unsigned long addr)3333+/* Modelled after find_linux_pte() */3434+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)4135{4242- return (addr & ~REGION_MASK) >> HUGEPGDIR_SHIFT;4343-}3636+ pgd_t *pg;3737+ pud_t *pu;3838+ pmd_t *pm;3939+ pte_t *pt;44404545-static pud_t *hugepgd_offset(struct mm_struct *mm, unsigned long addr)4646-{4747- int index;4848-4949- if (! mm->context.huge_pgdir)5050- return NULL;5151-5252-5353- index = hugepgd_index(addr);5454- BUG_ON(index >= PTRS_PER_HUGEPGD);5555- return (pud_t *)(mm->context.huge_pgdir + index);5656-}5757-5858-static inline pte_t *hugepte_offset(pud_t *dir, unsigned long addr)5959-{6060- int index;6161-6262- if (pud_none(*dir))6363- return NULL;6464-6565- index = (addr >> HPAGE_SHIFT) % PTRS_PER_HUGEPTE;6666- return (pte_t *)pud_page(*dir) + index;6767-}6868-6969-static pud_t *hugepgd_alloc(struct mm_struct *mm, unsigned long addr)7070-{7141 BUG_ON(! in_hugepage_area(mm->context, addr));72427373- if (! mm->context.huge_pgdir) {7474- pgd_t *new;7575- spin_unlock(&mm->page_table_lock);7676- /* Don't use pgd_alloc(), because we want __GFP_REPEAT */7777- new = kmem_cache_alloc(zero_cache, GFP_KERNEL | __GFP_REPEAT);7878- BUG_ON(memcmp(new, empty_zero_page, PAGE_SIZE));7979- spin_lock(&mm->page_table_lock);4343+ addr &= HPAGE_MASK;80448181- /*8282- * Because we dropped the lock, we should re-check the8383- * entry, as somebody else could have populated it..8484- */8585- if (mm->context.huge_pgdir)8686- pgd_free(new);8787- else8888- mm->context.huge_pgdir = new;8989- }9090- return hugepgd_offset(mm, addr);9191-}9292-9393-static pte_t *hugepte_alloc(struct mm_struct *mm, pud_t *dir, unsigned long addr)9494-{9595- if (! pud_present(*dir)) {9696- pte_t *new;9797-9898- spin_unlock(&mm->page_table_lock);9999- new = kmem_cache_alloc(zero_cache, GFP_KERNEL | __GFP_REPEAT);100100- BUG_ON(memcmp(new, empty_zero_page, PAGE_SIZE));101101- spin_lock(&mm->page_table_lock);102102- /*103103- * Because we dropped the lock, we should re-check the104104- * entry, as somebody else could have populated it..105105- */106106- if (pud_present(*dir)) {107107- if (new)108108- kmem_cache_free(zero_cache, new);109109- } else {110110- struct page *ptepage;111111-112112- if (! new)113113- return NULL;114114- ptepage = virt_to_page(new);115115- ptepage->mapping = (void *) mm;116116- ptepage->index = addr & HUGEPGDIR_MASK;117117- pud_populate(mm, dir, new);4545+ pg = pgd_offset(mm, addr);4646+ if (!pgd_none(*pg)) {4747+ pu = pud_offset(pg, addr);4848+ if (!pud_none(*pu)) {4949+ pm = pmd_offset(pu, addr);5050+ pt = (pte_t *)pm;5151+ BUG_ON(!pmd_none(*pm)5252+ && !(pte_present(*pt) && pte_huge(*pt)));5353+ return pt;11854 }11955 }12056121121- return hugepte_offset(dir, addr);122122-}123123-124124-pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)125125-{126126- pud_t *pud;127127-128128- BUG_ON(! in_hugepage_area(mm->context, addr));129129-130130- pud = hugepgd_offset(mm, addr);131131- if (! pud)132132- return NULL;133133-134134- return hugepte_offset(pud, addr);5757+ return NULL;13558}1365913760pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)13861{139139- pud_t *pud;6262+ pgd_t *pg;6363+ pud_t *pu;6464+ pmd_t *pm;6565+ pte_t *pt;1406614167 BUG_ON(! in_hugepage_area(mm->context, addr));14268143143- pud = hugepgd_alloc(mm, addr);144144- if (! pud)145145- return NULL;6969+ addr &= HPAGE_MASK;14670147147- return hugepte_alloc(mm, pud, addr);7171+ pg = pgd_offset(mm, addr);7272+ pu = pud_alloc(mm, pg, addr);7373+7474+ if (pu) {7575+ pm = pmd_alloc(mm, pu, addr);7676+ if (pm) {7777+ pt = (pte_t *)pm;7878+ BUG_ON(!pmd_none(*pm)7979+ && !(pte_present(*pt) && pte_huge(*pt)));8080+ return pt;8181+ }8282+ }8383+8484+ return NULL;8585+}8686+8787+#define HUGEPTE_BATCH_SIZE (HPAGE_SIZE / PMD_SIZE)8888+8989+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,9090+ pte_t *ptep, pte_t pte)9191+{9292+ int i;9393+9494+ if (pte_present(*ptep)) {9595+ pte_clear(mm, addr, ptep);9696+ flush_tlb_pending();9797+ }9898+9999+ for (i = 0; i < HUGEPTE_BATCH_SIZE; i++) {100100+ *ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);101101+ ptep++;102102+ }103103+}104104+105105+pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,106106+ pte_t *ptep)107107+{108108+ unsigned long old = pte_update(ptep, ~0UL);109109+ int i;110110+111111+ if (old & _PAGE_HASHPTE)112112+ hpte_update(mm, addr, old, 0);113113+114114+ for (i = 1; i < HUGEPTE_BATCH_SIZE; i++)115115+ ptep[i] = __pte(0);116116+117117+ return __pte(old);148118}149119150120/*···132162 return 0;133163}134164135135-static void flush_segments(void *parm)165165+static void flush_low_segments(void *parm)136166{137137- u16 segs = (unsigned long) parm;167167+ u16 areas = (unsigned long) parm;138168 unsigned long i;139169140170 asm volatile("isync" : : : "memory");141171142142- for (i = 0; i < 16; i++) {143143- if (! (segs & (1U << i)))172172+ BUILD_BUG_ON((sizeof(areas)*8) != NUM_LOW_AREAS);173173+174174+ for (i = 0; i < NUM_LOW_AREAS; i++) {175175+ if (! (areas & (1U << i)))144176 continue;145177 asm volatile("slbie %0" : : "r" (i << SID_SHIFT));146178 }···150178 asm volatile("isync" : : : "memory");151179}152180153153-static int prepare_low_seg_for_htlb(struct mm_struct *mm, unsigned long seg)181181+static void flush_high_segments(void *parm)154182{155155- unsigned long start = seg << SID_SHIFT;156156- unsigned long end = (seg+1) << SID_SHIFT;183183+ u16 areas = (unsigned long) parm;184184+ unsigned long i, j;185185+186186+ asm volatile("isync" : : : "memory");187187+188188+ BUILD_BUG_ON((sizeof(areas)*8) != NUM_HIGH_AREAS);189189+190190+ for (i = 0; i < NUM_HIGH_AREAS; i++) {191191+ if (! (areas & (1U << i)))192192+ continue;193193+ for (j = 0; j < (1UL << (HTLB_AREA_SHIFT-SID_SHIFT)); j++)194194+ asm volatile("slbie %0"195195+ :: "r" ((i << HTLB_AREA_SHIFT) + (j << SID_SHIFT)));196196+ }197197+198198+ asm volatile("isync" : : : "memory");199199+}200200+201201+static int prepare_low_area_for_htlb(struct mm_struct *mm, unsigned long area)202202+{203203+ unsigned long start = area << SID_SHIFT;204204+ unsigned long end = (area+1) << SID_SHIFT;157205 struct vm_area_struct *vma;158206159159- BUG_ON(seg >= 16);207207+ BUG_ON(area >= NUM_LOW_AREAS);160208161209 /* Check no VMAs are in the region */162210 vma = find_vma(mm, start);···186194 return 0;187195}188196189189-static int open_low_hpage_segs(struct mm_struct *mm, u16 newsegs)197197+static int prepare_high_area_for_htlb(struct mm_struct *mm, unsigned long area)198198+{199199+ unsigned long start = area << HTLB_AREA_SHIFT;200200+ unsigned long end = (area+1) << HTLB_AREA_SHIFT;201201+ struct vm_area_struct *vma;202202+203203+ BUG_ON(area >= NUM_HIGH_AREAS);204204+205205+ /* Check no VMAs are in the region */206206+ vma = find_vma(mm, start);207207+ if (vma && (vma->vm_start < end))208208+ return -EBUSY;209209+210210+ return 0;211211+}212212+213213+static int open_low_hpage_areas(struct mm_struct *mm, u16 newareas)190214{191215 unsigned long i;192216193193- newsegs &= ~(mm->context.htlb_segs);194194- if (! newsegs)217217+ BUILD_BUG_ON((sizeof(newareas)*8) != NUM_LOW_AREAS);218218+ BUILD_BUG_ON((sizeof(mm->context.low_htlb_areas)*8) != NUM_LOW_AREAS);219219+220220+ newareas &= ~(mm->context.low_htlb_areas);221221+ if (! newareas)195222 return 0; /* The segments we want are already open */196223197197- for (i = 0; i < 16; i++)198198- if ((1 << i) & newsegs)199199- if (prepare_low_seg_for_htlb(mm, i) != 0)224224+ for (i = 0; i < NUM_LOW_AREAS; i++)225225+ if ((1 << i) & newareas)226226+ if (prepare_low_area_for_htlb(mm, i) != 0)200227 return -EBUSY;201228202202- mm->context.htlb_segs |= newsegs;229229+ mm->context.low_htlb_areas |= newareas;203230204231 /* update the paca copy of the context struct */205232 get_paca()->context = mm->context;···226215 /* the context change must make it to memory before the flush,227216 * so that further SLB misses do the right thing. */228217 mb();229229- on_each_cpu(flush_segments, (void *)(unsigned long)newsegs, 0, 1);218218+ on_each_cpu(flush_low_segments, (void *)(unsigned long)newareas, 0, 1);219219+220220+ return 0;221221+}222222+223223+static int open_high_hpage_areas(struct mm_struct *mm, u16 newareas)224224+{225225+ unsigned long i;226226+227227+ BUILD_BUG_ON((sizeof(newareas)*8) != NUM_HIGH_AREAS);228228+ BUILD_BUG_ON((sizeof(mm->context.high_htlb_areas)*8)229229+ != NUM_HIGH_AREAS);230230+231231+ newareas &= ~(mm->context.high_htlb_areas);232232+ if (! newareas)233233+ return 0; /* The areas we want are already open */234234+235235+ for (i = 0; i < NUM_HIGH_AREAS; i++)236236+ if ((1 << i) & newareas)237237+ if (prepare_high_area_for_htlb(mm, i) != 0)238238+ return -EBUSY;239239+240240+ mm->context.high_htlb_areas |= newareas;241241+242242+ /* update the paca copy of the context struct */243243+ get_paca()->context = mm->context;244244+245245+ /* the context change must make it to memory before the flush,246246+ * so that further SLB misses do the right thing. */247247+ mb();248248+ on_each_cpu(flush_high_segments, (void *)(unsigned long)newareas, 0, 1);230249231250 return 0;232251}233252234253int prepare_hugepage_range(unsigned long addr, unsigned long len)235254{236236- if (within_hugepage_high_range(addr, len))237237- return 0;238238- else if ((addr < 0x100000000UL) && ((addr+len) < 0x100000000UL)) {239239- int err;240240- /* Yes, we need both tests, in case addr+len overflows241241- * 64-bit arithmetic */242242- err = open_low_hpage_segs(current->mm,255255+ int err;256256+257257+ if ( (addr+len) < addr )258258+ return -EINVAL;259259+260260+ if ((addr + len) < 0x100000000UL)261261+ err = open_low_hpage_areas(current->mm,243262 LOW_ESID_MASK(addr, len));244244- if (err)245245- printk(KERN_DEBUG "prepare_hugepage_range(%lx, %lx)"246246- " failed (segs: 0x%04hx)\n", addr, len,247247- LOW_ESID_MASK(addr, len));263263+ else264264+ err = open_high_hpage_areas(current->mm,265265+ HTLB_AREA_MASK(addr, len));266266+ if (err) {267267+ printk(KERN_DEBUG "prepare_hugepage_range(%lx, %lx)"268268+ " failed (lowmask: 0x%04hx, highmask: 0x%04hx)\n",269269+ addr, len,270270+ LOW_ESID_MASK(addr, len), HTLB_AREA_MASK(addr, len));248271 return err;249272 }250273251251- return -EINVAL;274274+ return 0;252275}253276254277struct page *···354309 vma = find_vma(mm, addr);355310 continue;356311 }357357- if (touches_hugepage_high_range(addr, len)) {358358- addr = TASK_HPAGE_END;312312+ if (touches_hugepage_high_range(mm, addr, len)) {313313+ addr = ALIGN(addr+1, 1UL<<HTLB_AREA_SHIFT);359314 vma = find_vma(mm, addr);360315 continue;361316 }···434389 if (touches_hugepage_low_range(mm, addr, len)) {435390 addr = (addr & ((~0) << SID_SHIFT)) - len;436391 goto hugepage_recheck;437437- } else if (touches_hugepage_high_range(addr, len)) {438438- addr = TASK_HPAGE_BASE - len;392392+ } else if (touches_hugepage_high_range(mm, addr, len)) {393393+ addr = (addr & ((~0UL) << HTLB_AREA_SHIFT)) - len;394394+ goto hugepage_recheck;439395 }440396441397 /*···527481 return -ENOMEM;528482}529483530530-static unsigned long htlb_get_high_area(unsigned long len)484484+static unsigned long htlb_get_high_area(unsigned long len, u16 areamask)531485{532532- unsigned long addr = TASK_HPAGE_BASE;486486+ unsigned long addr = 0x100000000UL;533487 struct vm_area_struct *vma;534488535489 vma = find_vma(current->mm, addr);536536- for (vma = find_vma(current->mm, addr);537537- addr + len <= TASK_HPAGE_END;538538- vma = vma->vm_next) {490490+ while (addr + len <= TASK_SIZE_USER64) {539491 BUG_ON(vma && (addr >= vma->vm_end)); /* invariant */540540- BUG_ON(! within_hugepage_high_range(addr, len));492492+493493+ if (! __within_hugepage_high_range(addr, len, areamask)) {494494+ addr = ALIGN(addr+1, 1UL<<HTLB_AREA_SHIFT);495495+ vma = find_vma(current->mm, addr);496496+ continue;497497+ }541498542499 if (!vma || (addr + len) <= vma->vm_start)543500 return addr;544501 addr = ALIGN(vma->vm_end, HPAGE_SIZE);545545- /* Because we're in a hugepage region, this alignment546546- * should not skip us over any VMAs */502502+ /* Depending on segmask this might not be a confirmed503503+ * hugepage region, so the ALIGN could have skipped504504+ * some VMAs */505505+ vma = find_vma(current->mm, addr);547506 }548507549508 return -ENOMEM;···558507 unsigned long len, unsigned long pgoff,559508 unsigned long flags)560509{510510+ int lastshift;511511+ u16 areamask, curareas;512512+561513 if (len & ~HPAGE_MASK)562514 return -EINVAL;563515···568514 return -EINVAL;569515570516 if (test_thread_flag(TIF_32BIT)) {571571- int lastshift = 0;572572- u16 segmask, cursegs = current->mm->context.htlb_segs;517517+ curareas = current->mm->context.low_htlb_areas;573518574519 /* First see if we can do the mapping in the existing575575- * low hpage segments */576576- addr = htlb_get_low_area(len, cursegs);520520+ * low areas */521521+ addr = htlb_get_low_area(len, curareas);577522 if (addr != -ENOMEM)578523 return addr;579524580580- for (segmask = LOW_ESID_MASK(0x100000000UL-len, len);581581- ! lastshift; segmask >>=1) {582582- if (segmask & 1)525525+ lastshift = 0;526526+ for (areamask = LOW_ESID_MASK(0x100000000UL-len, len);527527+ ! lastshift; areamask >>=1) {528528+ if (areamask & 1)583529 lastshift = 1;584530585585- addr = htlb_get_low_area(len, cursegs | segmask);531531+ addr = htlb_get_low_area(len, curareas | areamask);586532 if ((addr != -ENOMEM)587587- && open_low_hpage_segs(current->mm, segmask) == 0)533533+ && open_low_hpage_areas(current->mm, areamask) == 0)588534 return addr;589535 }590590- printk(KERN_DEBUG "hugetlb_get_unmapped_area() unable to open"591591- " enough segments\n");592592- return -ENOMEM;593536 } else {594594- return htlb_get_high_area(len);595595- }596596-}537537+ curareas = current->mm->context.high_htlb_areas;597538598598-void hugetlb_mm_free_pgd(struct mm_struct *mm)599599-{600600- int i;601601- pgd_t *pgdir;539539+ /* First see if we can do the mapping in the existing540540+ * high areas */541541+ addr = htlb_get_high_area(len, curareas);542542+ if (addr != -ENOMEM)543543+ return addr;602544603603- spin_lock(&mm->page_table_lock);545545+ lastshift = 0;546546+ for (areamask = HTLB_AREA_MASK(TASK_SIZE_USER64-len, len);547547+ ! lastshift; areamask >>=1) {548548+ if (areamask & 1)549549+ lastshift = 1;604550605605- pgdir = mm->context.huge_pgdir;606606- if (! pgdir)607607- goto out;608608-609609- mm->context.huge_pgdir = NULL;610610-611611- /* cleanup any hugepte pages leftover */612612- for (i = 0; i < PTRS_PER_HUGEPGD; i++) {613613- pud_t *pud = (pud_t *)(pgdir + i);614614-615615- if (! pud_none(*pud)) {616616- pte_t *pte = (pte_t *)pud_page(*pud);617617- struct page *ptepage = virt_to_page(pte);618618-619619- ptepage->mapping = NULL;620620-621621- BUG_ON(memcmp(pte, empty_zero_page, PAGE_SIZE));622622- kmem_cache_free(zero_cache, pte);551551+ addr = htlb_get_high_area(len, curareas | areamask);552552+ if ((addr != -ENOMEM)553553+ && open_high_hpage_areas(current->mm, areamask) == 0)554554+ return addr;623555 }624624- pud_clear(pud);625556 }626626-627627- BUG_ON(memcmp(pgdir, empty_zero_page, PAGE_SIZE));628628- kmem_cache_free(zero_cache, pgdir);629629-630630- out:631631- spin_unlock(&mm->page_table_lock);557557+ printk(KERN_DEBUG "hugetlb_get_unmapped_area() unable to open"558558+ " enough areas\n");559559+ return -ENOMEM;632560}633561634562int hash_huge_page(struct mm_struct *mm, unsigned long access,
+1-1
arch/ppc64/mm/imalloc.c
···3131 break;3232 if ((unsigned long)tmp->addr >= ioremap_bot)3333 addr = tmp->size + (unsigned long) tmp->addr;3434- if (addr > IMALLOC_END-size) 3434+ if (addr >= IMALLOC_END-size)3535 return 1;3636 }3737 *im_addr = addr;
+54-42
arch/ppc64/mm/init.c
···42424343#include <asm/pgalloc.h>4444#include <asm/page.h>4545-#include <asm/abs_addr.h>4645#include <asm/prom.h>4746#include <asm/lmb.h>4847#include <asm/rtas.h>···6465#include <asm/abs_addr.h>6566#include <asm/vdso.h>6667#include <asm/imalloc.h>6868+6969+#if PGTABLE_RANGE > USER_VSID_RANGE7070+#warning Limited user VSID range means pagetable space is wasted7171+#endif7272+7373+#if (TASK_SIZE_USER64 < PGTABLE_RANGE) && (TASK_SIZE_USER64 < USER_VSID_RANGE)7474+#warning TASK_SIZE is smaller than it needs to be.7575+#endif67766877int mem_init_done;6978unsigned long ioremap_bot = IMALLOC_BASE;···166159 ptep = pte_alloc_kernel(&init_mm, pmdp, ea);167160 if (!ptep)168161 return -ENOMEM;169169- pa = abs_to_phys(pa);170162 set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,171163 __pgprot(flags)));172164 spin_unlock(&init_mm.page_table_lock);···232226 * Before that, we map using addresses going233227 * up from ioremap_bot. imalloc will use234228 * the addresses from ioremap_bot through235235- * IMALLOC_END (0xE000001fffffffff)229229+ * IMALLOC_END236230 * 237231 */238232 pa = addr & PAGE_MASK;···423417 int index;424418 int err;425419426426-#ifdef CONFIG_HUGETLB_PAGE427427- /* We leave htlb_segs as it was, but for a fork, we need to428428- * clear the huge_pgdir. */429429- mm->context.huge_pgdir = NULL;430430-#endif431431-432420again:433421 if (!idr_pre_get(&mmu_context_idr, GFP_KERNEL))434422 return -ENOMEM;···453453 spin_unlock(&mmu_context_lock);454454455455 mm->context.id = NO_CONTEXT;456456-457457- hugetlb_mm_free_pgd(mm);458456}459457460458/*···482484 for (i = 1; i < lmb.memory.cnt; i++) {483485 unsigned long base, prevbase, prevsize;484486485485- prevbase = lmb.memory.region[i-1].physbase;487487+ prevbase = lmb.memory.region[i-1].base;486488 prevsize = lmb.memory.region[i-1].size;487487- base = lmb.memory.region[i].physbase;489489+ base = lmb.memory.region[i].base;488490 if (base > (prevbase + prevsize)) {489491 io_hole_start = prevbase + prevsize;490492 io_hole_size = base - (prevbase + prevsize);···511513 for (i=0; i < lmb.memory.cnt; i++) {512514 unsigned long base;513515514514-#ifdef CONFIG_MSCHUNKS515515- base = lmb.memory.region[i].physbase;516516-#else517516 base = lmb.memory.region[i].base;518518-#endif517517+519518 if ((paddr >= base) &&520519 (paddr < (base + lmb.memory.region[i].size))) {521520 return 1;···542547 */543548 bootmap_pages = bootmem_bootmap_pages(total_pages);544549545545- start = abs_to_phys(lmb_alloc(bootmap_pages<<PAGE_SHIFT, PAGE_SIZE));550550+ start = lmb_alloc(bootmap_pages<<PAGE_SHIFT, PAGE_SIZE);546551 BUG_ON(!start);547552548553 boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages);···553558 * present.554559 */555560 for (i=0; i < lmb.memory.cnt; i++) {556556- unsigned long physbase, size;561561+ unsigned long base, size;557562 unsigned long start_pfn, end_pfn;558563559559- physbase = lmb.memory.region[i].physbase;564564+ base = lmb.memory.region[i].base;560565 size = lmb.memory.region[i].size;561566562562- start_pfn = physbase >> PAGE_SHIFT;567567+ start_pfn = base >> PAGE_SHIFT;563568 end_pfn = start_pfn + (size >> PAGE_SHIFT);564569 memory_present(0, start_pfn, end_pfn);565570566566- free_bootmem(physbase, size);571571+ free_bootmem(base, size);567572 }568573569574 /* reserve the sections we're already using */570575 for (i=0; i < lmb.reserved.cnt; i++) {571571- unsigned long physbase = lmb.reserved.region[i].physbase;576576+ unsigned long base = lmb.reserved.region[i].base;572577 unsigned long size = lmb.reserved.region[i].size;573578574574- reserve_bootmem(physbase, size);579579+ reserve_bootmem(base, size);575580 }576581}577582···610615 int i;611616612617 for (i=0; i < lmb.memory.cnt; i++) {613613- unsigned long physbase, size;618618+ unsigned long base, size;614619 struct kcore_list *kcore_mem;615620616616- physbase = lmb.memory.region[i].physbase;621621+ base = lmb.memory.region[i].base;617622 size = lmb.memory.region[i].size;618623619624 /* GFP_ATOMIC to avoid might_sleep warnings during boot */···621626 if (!kcore_mem)622627 panic("mem_init: kmalloc failed\n");623628624624- kclist_add(kcore_mem, __va(physbase), size);629629+ kclist_add(kcore_mem, __va(base), size);625630 }626631627632 kclist_add(&kcore_vmem, (void *)VMALLOC_START, VMALLOC_END-VMALLOC_START);···681686682687 mem_init_done = 1;683688684684-#ifdef CONFIG_PPC_ISERIES685685- iommu_vio_init();686686-#endif687689 /* Initialize the vDSO */688690 vdso_init();689691}···825833 return virt_addr;826834}827835828828-kmem_cache_t *zero_cache;829829-830830-static void zero_ctor(void *pte, kmem_cache_t *cache, unsigned long flags)836836+static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags)831837{832832- memset(pte, 0, PAGE_SIZE);838838+ memset(addr, 0, kmem_cache_size(cache));833839}840840+841841+static const int pgtable_cache_size[2] = {842842+ PTE_TABLE_SIZE, PMD_TABLE_SIZE843843+};844844+static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = {845845+ "pgd_pte_cache", "pud_pmd_cache",846846+};847847+848848+kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)];834849835850void pgtable_cache_init(void)836851{837837- zero_cache = kmem_cache_create("zero",838838- PAGE_SIZE,839839- 0,840840- SLAB_HWCACHE_ALIGN | SLAB_MUST_HWCACHE_ALIGN,841841- zero_ctor,842842- NULL);843843- if (!zero_cache)844844- panic("pgtable_cache_init(): could not create zero_cache!\n");852852+ int i;853853+854854+ BUILD_BUG_ON(PTE_TABLE_SIZE != pgtable_cache_size[PTE_CACHE_NUM]);855855+ BUILD_BUG_ON(PMD_TABLE_SIZE != pgtable_cache_size[PMD_CACHE_NUM]);856856+ BUILD_BUG_ON(PUD_TABLE_SIZE != pgtable_cache_size[PUD_CACHE_NUM]);857857+ BUILD_BUG_ON(PGD_TABLE_SIZE != pgtable_cache_size[PGD_CACHE_NUM]);858858+859859+ for (i = 0; i < ARRAY_SIZE(pgtable_cache_size); i++) {860860+ int size = pgtable_cache_size[i];861861+ const char *name = pgtable_cache_name[i];862862+863863+ pgtable_cache[i] = kmem_cache_create(name,864864+ size, size,865865+ SLAB_HWCACHE_ALIGN866866+ | SLAB_MUST_HWCACHE_ALIGN,867867+ zero_ctor,868868+ NULL);869869+ if (! pgtable_cache[i])870870+ panic("pgtable_cache_init(): could not create %s!\n",871871+ name);872872+ }845873}846874847875pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr,
+1-1
arch/ppc64/mm/numa.c
···671671 * Mark reserved regions on this node672672 */673673 for (i = 0; i < lmb.reserved.cnt; i++) {674674- unsigned long physbase = lmb.reserved.region[i].physbase;674674+ unsigned long physbase = lmb.reserved.region[i].base;675675 unsigned long size = lmb.reserved.region[i].size;676676677677 if (pa_to_nid(physbase) != nid &&
+14-13
arch/ppc64/mm/slb_low.S
···8989 b 9f909091910: /* user address: proto-VSID = context<<15 | ESID */9292- li r11,SLB_VSID_USER9393-9494- srdi. r9,r3,139292+ srdi. r9,r3,USER_ESID_BITS9593 bne- 8f /* invalid ea bits set */96949795#ifdef CONFIG_HUGETLB_PAGE9896BEGIN_FTR_SECTION9999- /* check against the hugepage ranges */100100- cmpldi r3,(TASK_HPAGE_END>>SID_SHIFT)101101- bge 6f /* >= TASK_HPAGE_END */102102- cmpldi r3,(TASK_HPAGE_BASE>>SID_SHIFT)103103- bge 5f /* TASK_HPAGE_BASE..TASK_HPAGE_END */104104- cmpldi r3,16105105- bge 6f /* 4GB..TASK_HPAGE_BASE */9797+ lhz r9,PACAHIGHHTLBAREAS(r13)9898+ srdi r11,r3,(HTLB_AREA_SHIFT-SID_SHIFT)9999+ srd r9,r9,r11100100+ andi. r9,r9,1101101+ bne 5f106102107107- lhz r9,PACAHTLBSEGS(r13)103103+ li r11,SLB_VSID_USER104104+105105+ cmpldi r3,16106106+ bge 6f107107+108108+ lhz r9,PACALOWHTLBAREAS(r13)108109 srd r9,r9,r3109110 andi. r9,r9,1111111+110112 beq 6f111113112112-5: /* this is a hugepage user address */113113- li r11,(SLB_VSID_USER|SLB_VSID_L)114114+5: li r11,SLB_VSID_USER|SLB_VSID_L114115END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)115116#endif /* CONFIG_HUGETLB_PAGE */116117
+55-40
arch/ppc64/mm/tlb.c
···4141DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);4242unsigned long pte_freelist_forced_free;43434444-void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage)4444+struct pte_freelist_batch4545+{4646+ struct rcu_head rcu;4747+ unsigned int index;4848+ pgtable_free_t tables[0];4949+};5050+5151+DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);5252+unsigned long pte_freelist_forced_free;5353+5454+#define PTE_FREELIST_SIZE \5555+ ((PAGE_SIZE - sizeof(struct pte_freelist_batch)) \5656+ / sizeof(pgtable_free_t))5757+5858+#ifdef CONFIG_SMP5959+static void pte_free_smp_sync(void *arg)6060+{6161+ /* Do nothing, just ensure we sync with all CPUs */6262+}6363+#endif6464+6565+/* This is only called when we are critically out of memory6666+ * (and fail to get a page in pte_free_tlb).6767+ */6868+static void pgtable_free_now(pgtable_free_t pgf)6969+{7070+ pte_freelist_forced_free++;7171+7272+ smp_call_function(pte_free_smp_sync, NULL, 0, 1);7373+7474+ pgtable_free(pgf);7575+}7676+7777+static void pte_free_rcu_callback(struct rcu_head *head)7878+{7979+ struct pte_freelist_batch *batch =8080+ container_of(head, struct pte_freelist_batch, rcu);8181+ unsigned int i;8282+8383+ for (i = 0; i < batch->index; i++)8484+ pgtable_free(batch->tables[i]);8585+8686+ free_page((unsigned long)batch);8787+}8888+8989+static void pte_free_submit(struct pte_freelist_batch *batch)9090+{9191+ INIT_RCU_HEAD(&batch->rcu);9292+ call_rcu(&batch->rcu, pte_free_rcu_callback);9393+}9494+9595+void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf)4596{4697 /* This is safe as we are holding page_table_lock */4798 cpumask_t local_cpumask = cpumask_of_cpu(smp_processor_id());···1004910150 if (atomic_read(&tlb->mm->mm_users) < 2 ||10251 cpus_equal(tlb->mm->cpu_vm_mask, local_cpumask)) {103103- pte_free(ptepage);5252+ pgtable_free(pgf);10453 return;10554 }1065510756 if (*batchp == NULL) {10857 *batchp = (struct pte_freelist_batch *)__get_free_page(GFP_ATOMIC);10958 if (*batchp == NULL) {110110- pte_free_now(ptepage);5959+ pgtable_free_now(pgf);11160 return;11261 }11362 (*batchp)->index = 0;11463 }115115- (*batchp)->pages[(*batchp)->index++] = ptepage;6464+ (*batchp)->tables[(*batchp)->index++] = pgf;11665 if ((*batchp)->index == PTE_FREELIST_SIZE) {11766 pte_free_submit(*batchp);11867 *batchp = NULL;···181130 flush_hash_range(batch->context, i, local);182131 batch->index = 0;183132 put_cpu();184184-}185185-186186-#ifdef CONFIG_SMP187187-static void pte_free_smp_sync(void *arg)188188-{189189- /* Do nothing, just ensure we sync with all CPUs */190190-}191191-#endif192192-193193-/* This is only called when we are critically out of memory194194- * (and fail to get a page in pte_free_tlb).195195- */196196-void pte_free_now(struct page *ptepage)197197-{198198- pte_freelist_forced_free++;199199-200200- smp_call_function(pte_free_smp_sync, NULL, 0, 1);201201-202202- pte_free(ptepage);203203-}204204-205205-static void pte_free_rcu_callback(struct rcu_head *head)206206-{207207- struct pte_freelist_batch *batch =208208- container_of(head, struct pte_freelist_batch, rcu);209209- unsigned int i;210210-211211- for (i = 0; i < batch->index; i++)212212- pte_free(batch->pages[i]);213213- free_page((unsigned long)batch);214214-}215215-216216-void pte_free_submit(struct pte_freelist_batch *batch)217217-{218218- INIT_RCU_HEAD(&batch->rcu);219219- call_rcu(&batch->rcu, pte_free_rcu_callback);220133}221134222135void pte_free_finish(void)
···104104105105#ifdef CONFIG_PPC_ISERIES106106107107-/* Initializes tables for bio buses */108108-extern void __init iommu_vio_init(void);109109-110107struct iSeries_Device_Node;111108/* Creates table for an individual device node */112109extern void iommu_devnode_init_iSeries(struct iSeries_Device_Node *dn);
-1
include/asm-ppc64/lmb.h
···22222323struct lmb_property {2424 unsigned long base;2525- unsigned long physbase;2625 unsigned long size;2726};2827
+3
include/asm-ppc64/machdep.h
···140140141141 /* Idle loop for this platform, leave empty for default idle loop */142142 int (*idle_loop)(void);143143+144144+ /* Function to enable pmcs for this platform, called once per cpu. */145145+ void (*enable_pmcs)(void);143146};144147145148extern int default_idle(void);
···382382extern struct task_struct *last_task_used_math;383383extern struct task_struct *last_task_used_altivec;384384385385-/* 64-bit user address space is 41-bits (2TBs user VM) */386386-#define TASK_SIZE_USER64 (0x0000020000000000UL)385385+/* 64-bit user address space is 44-bits (16TB user VM) */386386+#define TASK_SIZE_USER64 (0x0000100000000000UL)387387388388/* 389389 * 32-bit user address space is 4GB - 1 page
+9-5
include/asm-ppc64/prom.h
···2222#define RELOC(x) (*PTRRELOC(&(x)))23232424/* Definitions used by the flattened device tree */2525-#define OF_DT_HEADER 0xd00dfeed /* 4: version, 4: total size */2626-#define OF_DT_BEGIN_NODE 0x1 /* Start node: full name */2525+#define OF_DT_HEADER 0xd00dfeed /* marker */2626+#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */2727#define OF_DT_END_NODE 0x2 /* End node */2828-#define OF_DT_PROP 0x3 /* Property: name off, size, content */2828+#define OF_DT_PROP 0x3 /* Property: name off, size,2929+ * content */3030+#define OF_DT_NOP 0x4 /* nop */2931#define OF_DT_END 0x930323131-#define OF_DT_VERSION 13333+#define OF_DT_VERSION 0x1032343335/*3436 * This is what gets passed to the kernel by prom_init or kexec···5654 u32 version; /* format version */5755 u32 last_comp_version; /* last compatible version */5856 /* version 2 fields below */5959- u32 boot_cpuid_phys; /* Which physical CPU id we're booting on */5757+ u32 boot_cpuid_phys; /* Physical CPU id we're booting on */5858+ /* version 3 fields below */5959+ u32 dt_strings_size; /* size of the DT strings block */6060};61616262