···1-/*2- * Copyright (C) Cort Dougan 1999.3- *4- * This program is free software; you can redistribute it and/or5- * modify it under the terms of the GNU General Public License6- * as published by the Free Software Foundation; either version7- * 2 of the License, or (at your option) any later version.8- *9- * Generate a note section as per the CHRP specification.10- *11- */12-13-#include <stdio.h>14-15-#define PL(x) printf("%c%c%c%c", ((x)>>24)&0xff, ((x)>>16)&0xff, ((x)>>8)&0xff, (x)&0xff );16-17-int main(void)18-{19-/* header */20- /* namesz */21- PL(strlen("PowerPC")+1);22- /* descrsz */23- PL(6*4);24- /* type */25- PL(0x1275);26- /* name */27- printf("PowerPC"); printf("%c", 0);28-29-/* descriptor */30- /* real-mode */31- PL(0xffffffff);32- /* real-base */33- PL(0x00c00000);34- /* real-size */35- PL(0xffffffff);36- /* virt-base */37- PL(0xffffffff);38- /* virt-size */39- PL(0xffffffff);40- /* load-base */41- PL(0x4000);42- return 0;43-}
···0000000000000000000000000000000000000000000
-83
arch/ppc64/boot/piggyback.c
···1-/*2- * Copyright 2001 IBM Corp 3- *4- * This program is free software; you can redistribute it and/or5- * modify it under the terms of the GNU General Public License6- * as published by the Free Software Foundation; either version7- * 2 of the License, or (at your option) any later version.8- */9-#include <stdio.h>10-#include <unistd.h>11-#include <string.h>12-13-extern long ce_exec_config[];14-15-int main(int argc, char *argv[])16-{17- int i, cnt, pos, len;18- unsigned int cksum, val;19- unsigned char *lp;20- unsigned char buf[8192];21- char *varname;22- if (argc != 2)23- {24- fprintf(stderr, "usage: %s name <in-file >out-file\n",25- argv[0]);26- exit(1);27- }28-29- varname = strrchr(argv[1], '/');30- if (varname)31- varname++;32- else33- varname = argv[1];34-35- fprintf(stdout, "#\n");36- fprintf(stdout, "# Miscellaneous data structures:\n");37- fprintf(stdout, "# WARNING - this file is automatically generated!\n");38- fprintf(stdout, "#\n");39- fprintf(stdout, "\n");40- fprintf(stdout, "\t.data\n");41- fprintf(stdout, "\t.globl %s_data\n", varname);42- fprintf(stdout, "%s_data:\n", varname);43- pos = 0;44- cksum = 0;45- while ((len = read(0, buf, sizeof(buf))) > 0)46- {47- cnt = 0;48- lp = (unsigned char *)buf;49- len = (len + 3) & ~3; /* Round up to longwords */50- for (i = 0; i < len; i += 4)51- {52- if (cnt == 0)53- {54- fprintf(stdout, "\t.long\t");55- }56- fprintf(stdout, "0x%02X%02X%02X%02X", lp[0], lp[1], lp[2], lp[3]);57- val = *(unsigned long *)lp;58- cksum ^= val;59- lp += 4;60- if (++cnt == 4)61- {62- cnt = 0;63- fprintf(stdout, " # %x \n", pos+i-12);64- fflush(stdout);65- } else66- {67- fprintf(stdout, ",");68- }69- }70- if (cnt)71- {72- fprintf(stdout, "0\n");73- }74- pos += len;75- }76- fprintf(stdout, "\t.globl %s_len\n", varname);77- fprintf(stdout, "%s_len:\t.long\t0x%x\n", varname, pos);78- fflush(stdout);79- fclose(stdout);80- fprintf(stderr, "cksum = %x\n", cksum);81- exit(0);82-}83-
···40int getprop(void *phandle, const char *name, void *buf, int buflen);41void chrpboot(int a1, int a2, void *prom); /* in main.c */4243-void printk(char *fmt, ...);4445/* there is no convenient header to get this from... -- paulus */46extern unsigned long strlen(const char *);···220 case 1:221 return ch;222 case -1:223- printk("read(stdin) returned -1\r\n");224 return -1;225 }226 }···626}627628static char sprint_buf[1024];629-630-void631-printk(char *fmt, ...)632-{633- va_list args;634- int n;635-636- va_start(args, fmt);637- n = vsprintf(sprint_buf, fmt, args);638- va_end(args);639- write(stdout, sprint_buf, n);640-}641642int643printf(char *fmt, ...)
···40int getprop(void *phandle, const char *name, void *buf, int buflen);41void chrpboot(int a1, int a2, void *prom); /* in main.c */4243+int printf(char *fmt, ...);4445/* there is no convenient header to get this from... -- paulus */46extern unsigned long strlen(const char *);···220 case 1:221 return ch;222 case -1:223+ printf("read(stdin) returned -1\r\n");224 return -1;225 }226 }···626}627628static char sprint_buf[1024];000000000000629630int631printf(char *fmt, ...)
+196-100
arch/ppc64/kernel/ItLpQueue.c
···1/*2 * ItLpQueue.c3 * Copyright (C) 2001 Mike Corrigan IBM Corporation4- * 5 * This program is free software; you can redistribute it and/or modify6 * it under the terms of the GNU General Public License as published by7 * the Free Software Foundation; either version 2 of the License, or···11#include <linux/stddef.h>12#include <linux/kernel.h>13#include <linux/sched.h>00014#include <asm/system.h>15#include <asm/paca.h>16#include <asm/iSeries/ItLpQueue.h>17#include <asm/iSeries/HvLpEvent.h>18#include <asm/iSeries/HvCallEvent.h>1920-static __inline__ int set_inUse( struct ItLpQueue * lpQueue )21-{22- int t;23- u32 * inUseP = &(lpQueue->xInUseWord);0002425- __asm__ __volatile__("\n\26-1: lwarx %0,0,%2 \n\27- cmpwi 0,%0,0 \n\28- li %0,0 \n\29- bne- 2f \n\30- addi %0,%0,1 \n\31- stwcx. %0,0,%2 \n\32- bne- 1b \n\33-2: eieio"34- : "=&r" (t), "=m" (lpQueue->xInUseWord)35- : "r" (inUseP), "m" (lpQueue->xInUseWord)36- : "cc");3738- return t;39-}40-41-static __inline__ void clear_inUse( struct ItLpQueue * lpQueue )42-{43- lpQueue->xInUseWord = 0;44-}00004546/* Array of LpEvent handler functions */47extern LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes];48-unsigned long ItLpQueueInProcess = 0;4950-struct HvLpEvent * ItLpQueue_getNextLpEvent( struct ItLpQueue * lpQueue )51{52- struct HvLpEvent * nextLpEvent = 53- (struct HvLpEvent *)lpQueue->xSlicCurEventPtr;54- if ( nextLpEvent->xFlags.xValid ) {055 /* rmb() needed only for weakly consistent machines (regatta) */56 rmb();57 /* Set pointer to next potential event */58- lpQueue->xSlicCurEventPtr += ((nextLpEvent->xSizeMinus1 +59- LpEventAlign ) /60- LpEventAlign ) *61- LpEventAlign;62 /* Wrap to beginning if no room at end */63- if (lpQueue->xSlicCurEventPtr > lpQueue->xSlicLastValidEventPtr)64- lpQueue->xSlicCurEventPtr = lpQueue->xSlicEventStackPtr;0000065 }66- else 67- nextLpEvent = NULL;6869- return nextLpEvent;70}7172-int ItLpQueue_isLpIntPending( struct ItLpQueue * lpQueue )0073{74- int retval = 0;75- struct HvLpEvent * nextLpEvent;76- if ( lpQueue ) {77- nextLpEvent = (struct HvLpEvent *)lpQueue->xSlicCurEventPtr;78- retval = nextLpEvent->xFlags.xValid | lpQueue->xPlicOverflowIntPending;79- }80- return retval;0081}8283-void ItLpQueue_clearValid( struct HvLpEvent * event )84{85- /* Clear the valid bit of the event86- * Also clear bits within this event that might87- * look like valid bits (on 64-byte boundaries)88- */89- unsigned extra = (( event->xSizeMinus1 + LpEventAlign ) /90- LpEventAlign ) - 1;91- switch ( extra ) {92- case 3:93- ((struct HvLpEvent*)((char*)event+3*LpEventAlign))->xFlags.xValid=0;94- case 2:95- ((struct HvLpEvent*)((char*)event+2*LpEventAlign))->xFlags.xValid=0;96- case 1:97- ((struct HvLpEvent*)((char*)event+1*LpEventAlign))->xFlags.xValid=0;98- case 0:99- ; 000100 }0101 mb();0102 event->xFlags.xValid = 0;103}104105-unsigned ItLpQueue_process( struct ItLpQueue * lpQueue, struct pt_regs *regs )106{107- unsigned numIntsProcessed = 0;108- struct HvLpEvent * nextLpEvent;109110 /* If we have recursed, just return */111- if ( !set_inUse( lpQueue ) )112- return 0;113-114- if (ItLpQueueInProcess == 0)115- ItLpQueueInProcess = 1;116- else117- BUG();118119 for (;;) {120- nextLpEvent = ItLpQueue_getNextLpEvent( lpQueue );121- if ( nextLpEvent ) {122- /* Count events to return to caller123- * and count processed events in lpQueue124- */125- ++numIntsProcessed;126- lpQueue->xLpIntCount++; 127- /* Call appropriate handler here, passing 128 * a pointer to the LpEvent. The handler129 * must make a copy of the LpEvent if it130 * needs it in a bottom half. (perhaps for131 * an ACK)132- * 133- * Handlers are responsible for ACK processing 134 *135 * The Hypervisor guarantees that LpEvents will136 * only be delivered with types that we have137 * registered for, so no type check is necessary138 * here!139- */140- if ( nextLpEvent->xType < HvLpEvent_Type_NumTypes )141- lpQueue->xLpIntCountByType[nextLpEvent->xType]++;142- if ( nextLpEvent->xType < HvLpEvent_Type_NumTypes &&143- lpEventHandler[nextLpEvent->xType] ) 144- lpEventHandler[nextLpEvent->xType](nextLpEvent, regs);145 else146- printk(KERN_INFO "Unexpected Lp Event type=%d\n", nextLpEvent->xType );147-148- ItLpQueue_clearValid( nextLpEvent );149- } else if ( lpQueue->xPlicOverflowIntPending )150 /*151 * No more valid events. If overflow events are152 * pending process them153 */154- HvCallEvent_getOverflowLpEvents( lpQueue->xIndex);155 else156 break;157 }158159- ItLpQueueInProcess = 0;160- mb();161- clear_inUse( lpQueue );162-163- get_paca()->lpevent_count += numIntsProcessed;164-165- return numIntsProcessed;166}0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
···1/*2 * ItLpQueue.c3 * Copyright (C) 2001 Mike Corrigan IBM Corporation4+ *5 * This program is free software; you can redistribute it and/or modify6 * it under the terms of the GNU General Public License as published by7 * the Free Software Foundation; either version 2 of the License, or···11#include <linux/stddef.h>12#include <linux/kernel.h>13#include <linux/sched.h>14+#include <linux/bootmem.h>15+#include <linux/seq_file.h>16+#include <linux/proc_fs.h>17#include <asm/system.h>18#include <asm/paca.h>19#include <asm/iSeries/ItLpQueue.h>20#include <asm/iSeries/HvLpEvent.h>21#include <asm/iSeries/HvCallEvent.h>2223+/*24+ * The LpQueue is used to pass event data from the hypervisor to25+ * the partition. This is where I/O interrupt events are communicated.26+ *27+ * It is written to by the hypervisor so cannot end up in the BSS.28+ */29+struct hvlpevent_queue hvlpevent_queue __attribute__((__section__(".data")));3031+DEFINE_PER_CPU(unsigned long[HvLpEvent_Type_NumTypes], hvlpevent_counts);000000000003233+static char *event_types[HvLpEvent_Type_NumTypes] = {34+ "Hypervisor",35+ "Machine Facilities",36+ "Session Manager",37+ "SPD I/O",38+ "Virtual Bus",39+ "PCI I/O",40+ "RIO I/O",41+ "Virtual Lan",42+ "Virtual I/O"43+};4445/* Array of LpEvent handler functions */46extern LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes];04748+static struct HvLpEvent * get_next_hvlpevent(void)49{50+ struct HvLpEvent * event;51+ event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr;52+53+ if (event->xFlags.xValid) {54 /* rmb() needed only for weakly consistent machines (regatta) */55 rmb();56 /* Set pointer to next potential event */57+ hvlpevent_queue.xSlicCurEventPtr += ((event->xSizeMinus1 +58+ LpEventAlign) / LpEventAlign) * LpEventAlign;59+060 /* Wrap to beginning if no room at end */61+ if (hvlpevent_queue.xSlicCurEventPtr >62+ hvlpevent_queue.xSlicLastValidEventPtr) {63+ hvlpevent_queue.xSlicCurEventPtr =64+ hvlpevent_queue.xSlicEventStackPtr;65+ }66+ } else {67+ event = NULL;68 }006970+ return event;71}7273+static unsigned long spread_lpevents = NR_CPUS;74+75+int hvlpevent_is_pending(void)76{77+ struct HvLpEvent *next_event;78+79+ if (smp_processor_id() >= spread_lpevents)80+ return 0;81+82+ next_event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr;83+84+ return next_event->xFlags.xValid |85+ hvlpevent_queue.xPlicOverflowIntPending;86}8788+static void hvlpevent_clear_valid(struct HvLpEvent * event)89{90+ /* Tell the Hypervisor that we're done with this event.91+ * Also clear bits within this event that might look like valid bits.92+ * ie. on 64-byte boundaries.93+ */94+ struct HvLpEvent *tmp;95+ unsigned extra = ((event->xSizeMinus1 + LpEventAlign) /96+ LpEventAlign) - 1;97+98+ switch (extra) {99+ case 3:100+ tmp = (struct HvLpEvent*)((char*)event + 3 * LpEventAlign);101+ tmp->xFlags.xValid = 0;102+ case 2:103+ tmp = (struct HvLpEvent*)((char*)event + 2 * LpEventAlign);104+ tmp->xFlags.xValid = 0;105+ case 1:106+ tmp = (struct HvLpEvent*)((char*)event + 1 * LpEventAlign);107+ tmp->xFlags.xValid = 0;108 }109+110 mb();111+112 event->xFlags.xValid = 0;113}114115+void process_hvlpevents(struct pt_regs *regs)116{117+ struct HvLpEvent * event;0118119 /* If we have recursed, just return */120+ if (!spin_trylock(&hvlpevent_queue.lock))121+ return;00000122123 for (;;) {124+ event = get_next_hvlpevent();125+ if (event) {126+ /* Call appropriate handler here, passing00000127 * a pointer to the LpEvent. The handler128 * must make a copy of the LpEvent if it129 * needs it in a bottom half. (perhaps for130 * an ACK)131+ *132+ * Handlers are responsible for ACK processing133 *134 * The Hypervisor guarantees that LpEvents will135 * only be delivered with types that we have136 * registered for, so no type check is necessary137 * here!138+ */139+ if (event->xType < HvLpEvent_Type_NumTypes)140+ __get_cpu_var(hvlpevent_counts)[event->xType]++;141+ if (event->xType < HvLpEvent_Type_NumTypes &&142+ lpEventHandler[event->xType])143+ lpEventHandler[event->xType](event, regs);144 else145+ printk(KERN_INFO "Unexpected Lp Event type=%d\n", event->xType );146+147+ hvlpevent_clear_valid(event);148+ } else if (hvlpevent_queue.xPlicOverflowIntPending)149 /*150 * No more valid events. If overflow events are151 * pending process them152 */153+ HvCallEvent_getOverflowLpEvents(hvlpevent_queue.xIndex);154 else155 break;156 }157158+ spin_unlock(&hvlpevent_queue.lock);000000159}160+161+static int set_spread_lpevents(char *str)162+{163+ unsigned long val = simple_strtoul(str, NULL, 0);164+165+ /*166+ * The parameter is the number of processors to share in processing167+ * lp events.168+ */169+ if (( val > 0) && (val <= NR_CPUS)) {170+ spread_lpevents = val;171+ printk("lpevent processing spread over %ld processors\n", val);172+ } else {173+ printk("invalid spread_lpevents %ld\n", val);174+ }175+176+ return 1;177+}178+__setup("spread_lpevents=", set_spread_lpevents);179+180+void setup_hvlpevent_queue(void)181+{182+ void *eventStack;183+184+ /*185+ * Allocate a page for the Event Stack. The Hypervisor needs the186+ * absolute real address, so we subtract out the KERNELBASE and add187+ * in the absolute real address of the kernel load area.188+ */189+ eventStack = alloc_bootmem_pages(LpEventStackSize);190+ memset(eventStack, 0, LpEventStackSize);191+192+ /* Invoke the hypervisor to initialize the event stack */193+ HvCallEvent_setLpEventStack(0, eventStack, LpEventStackSize);194+195+ hvlpevent_queue.xSlicEventStackPtr = (char *)eventStack;196+ hvlpevent_queue.xSlicCurEventPtr = (char *)eventStack;197+ hvlpevent_queue.xSlicLastValidEventPtr = (char *)eventStack +198+ (LpEventStackSize - LpEventMaxSize);199+ hvlpevent_queue.xIndex = 0;200+}201+202+static int proc_lpevents_show(struct seq_file *m, void *v)203+{204+ int cpu, i;205+ unsigned long sum;206+ static unsigned long cpu_totals[NR_CPUS];207+208+ /* FIXME: do we care that there's no locking here? */209+ sum = 0;210+ for_each_online_cpu(cpu) {211+ cpu_totals[cpu] = 0;212+ for (i = 0; i < HvLpEvent_Type_NumTypes; i++) {213+ cpu_totals[cpu] += per_cpu(hvlpevent_counts, cpu)[i];214+ }215+ sum += cpu_totals[cpu];216+ }217+218+ seq_printf(m, "LpEventQueue 0\n");219+ seq_printf(m, " events processed:\t%lu\n", sum);220+221+ for (i = 0; i < HvLpEvent_Type_NumTypes; ++i) {222+ sum = 0;223+ for_each_online_cpu(cpu) {224+ sum += per_cpu(hvlpevent_counts, cpu)[i];225+ }226+227+ seq_printf(m, " %-20s %10lu\n", event_types[i], sum);228+ }229+230+ seq_printf(m, "\n events processed by processor:\n");231+232+ for_each_online_cpu(cpu) {233+ seq_printf(m, " CPU%02d %10lu\n", cpu, cpu_totals[cpu]);234+ }235+236+ return 0;237+}238+239+static int proc_lpevents_open(struct inode *inode, struct file *file)240+{241+ return single_open(file, proc_lpevents_show, NULL);242+}243+244+static struct file_operations proc_lpevents_operations = {245+ .open = proc_lpevents_open,246+ .read = seq_read,247+ .llseek = seq_lseek,248+ .release = single_release,249+};250+251+static int __init proc_lpevents_init(void)252+{253+ struct proc_dir_entry *e;254+255+ e = create_proc_entry("iSeries/lpevents", S_IFREG|S_IRUGO, NULL);256+ if (e)257+ e->proc_fops = &proc_lpevents_operations;258+259+ return 0;260+}261+__initcall(proc_lpevents_init);262+
+2-9
arch/ppc64/kernel/LparData.c
···28#include <asm/iSeries/IoHriProcessorVpd.h>29#include <asm/iSeries/ItSpCommArea.h>3031-/* The LpQueue is used to pass event data from the hypervisor to32- * the partition. This is where I/O interrupt events are communicated.33- */34-35-/* May be filled in by the hypervisor so cannot end up in the BSS */36-struct ItLpQueue xItLpQueue __attribute__((__section__(".data")));37-3839/* The HvReleaseData is the root of the information shared between 40 * the hypervisor and Linux. ···193 0,0,0, /* 13 - 15 */194 sizeof(struct IoHriProcessorVpd),/* 16 length of Proc Vpd */195 0,0,0,0,0,0, /* 17 - 22 */196- sizeof(struct ItLpQueue),/* 23 length of Lp Queue */197 0,0 /* 24 - 25 */198 },199 .xSlicVpdAdrs = { /* VPD addresses */···211 0,0,0, /* 13 - 15 */212 &xIoHriProcessorVpd, /* 16 Proc Vpd */213 0,0,0,0,0,0, /* 17 - 22 */214- &xItLpQueue, /* 23 Lp Queue */215 0,0216 }217};
···28#include <asm/iSeries/IoHriProcessorVpd.h>29#include <asm/iSeries/ItSpCommArea.h>3000000003132/* The HvReleaseData is the root of the information shared between 33 * the hypervisor and Linux. ···200 0,0,0, /* 13 - 15 */201 sizeof(struct IoHriProcessorVpd),/* 16 length of Proc Vpd */202 0,0,0,0,0,0, /* 17 - 22 */203+ sizeof(struct hvlpevent_queue), /* 23 length of Lp Queue */204 0,0 /* 24 - 25 */205 },206 .xSlicVpdAdrs = { /* VPD addresses */···218 0,0,0, /* 13 - 15 */219 &xIoHriProcessorVpd, /* 16 Proc Vpd */220 0,0,0,0,0,0, /* 17 - 22 */221+ &hvlpevent_queue, /* 23 Lp Queue */222 0,0223 }224};
-48
arch/ppc64/kernel/iSeries_proc.c
···40}41core_initcall(iseries_proc_create);4243-static char *event_types[9] = {44- "Hypervisor\t\t",45- "Machine Facilities\t",46- "Session Manager\t",47- "SPD I/O\t\t",48- "Virtual Bus\t\t",49- "PCI I/O\t\t",50- "RIO I/O\t\t",51- "Virtual Lan\t\t",52- "Virtual I/O\t\t"53-};54-55-static int proc_lpevents_show(struct seq_file *m, void *v)56-{57- unsigned int i;58-59- seq_printf(m, "LpEventQueue 0\n");60- seq_printf(m, " events processed:\t%lu\n",61- (unsigned long)xItLpQueue.xLpIntCount);62-63- for (i = 0; i < 9; ++i)64- seq_printf(m, " %s %10lu\n", event_types[i],65- (unsigned long)xItLpQueue.xLpIntCountByType[i]);66-67- seq_printf(m, "\n events processed by processor:\n");68-69- for_each_online_cpu(i)70- seq_printf(m, " CPU%02d %10u\n", i, paca[i].lpevent_count);71-72- return 0;73-}74-75-static int proc_lpevents_open(struct inode *inode, struct file *file)76-{77- return single_open(file, proc_lpevents_show, NULL);78-}79-80-static struct file_operations proc_lpevents_operations = {81- .open = proc_lpevents_open,82- .read = seq_read,83- .llseek = seq_lseek,84- .release = single_release,85-};86-87static unsigned long startTitan = 0;88static unsigned long startTb = 0;89···103static int __init iseries_proc_init(void)104{105 struct proc_dir_entry *e;106-107- e = create_proc_entry("iSeries/lpevents", S_IFREG|S_IRUGO, NULL);108- if (e)109- e->proc_fops = &proc_lpevents_operations;110111 e = create_proc_entry("iSeries/titanTod", S_IFREG|S_IRUGO, NULL);112 if (e)
···40}41core_initcall(iseries_proc_create);420000000000000000000000000000000000000000000043static unsigned long startTitan = 0;44static unsigned long startTb = 0;45···147static int __init iseries_proc_init(void)148{149 struct proc_dir_entry *e;0000150151 e = create_proc_entry("iSeries/titanTod", S_IFREG|S_IRUGO, NULL);152 if (e)
+1-42
arch/ppc64/kernel/iSeries_setup.c
···24#include <linux/smp.h>25#include <linux/param.h>26#include <linux/string.h>27-#include <linux/bootmem.h>28#include <linux/initrd.h>29#include <linux/seq_file.h>30#include <linux/kdev_t.h>···675 */676static void __init iSeries_setup_arch(void)677{678- void *eventStack;679 unsigned procIx = get_paca()->lppaca.dyn_hv_phys_proc_index;680681 /* Add an eye catcher and the systemcfg layout version number */···683 systemcfg->version.minor = SYSTEMCFG_MINOR;684685 /* Setup the Lp Event Queue */686-687- /* Allocate a page for the Event Stack688- * The hypervisor wants the absolute real address, so689- * we subtract out the KERNELBASE and add in the690- * absolute real address of the kernel load area691- */692- eventStack = alloc_bootmem_pages(LpEventStackSize);693- memset(eventStack, 0, LpEventStackSize);694-695- /* Invoke the hypervisor to initialize the event stack */696- HvCallEvent_setLpEventStack(0, eventStack, LpEventStackSize);697-698- /* Initialize fields in our Lp Event Queue */699- xItLpQueue.xSlicEventStackPtr = (char *)eventStack;700- xItLpQueue.xSlicCurEventPtr = (char *)eventStack;701- xItLpQueue.xSlicLastValidEventPtr = (char *)eventStack +702- (LpEventStackSize - LpEventMaxSize);703- xItLpQueue.xIndex = 0;704705 /* Compute processor frequency */706 procFreqHz = ((1UL << 34) * 1000000) /···833}834835late_initcall(iSeries_src_init);836-837-static int set_spread_lpevents(char *str)838-{839- unsigned long i;840- unsigned long val = simple_strtoul(str, NULL, 0);841-842- /*843- * The parameter is the number of processors to share in processing844- * lp events.845- */846- if (( val > 0) && (val <= NR_CPUS)) {847- for (i = 1; i < val; ++i)848- paca[i].lpqueue_ptr = paca[0].lpqueue_ptr;849-850- printk("lpevent processing spread over %ld processors\n", val);851- } else {852- printk("invalid spread_lpevents %ld\n", val);853- }854-855- return 1;856-}857-__setup("spread_lpevents=", set_spread_lpevents);858859#ifndef CONFIG_PCI860void __init iSeries_init_IRQ(void) { }
···24#include <linux/smp.h>25#include <linux/param.h>26#include <linux/string.h>027#include <linux/initrd.h>28#include <linux/seq_file.h>29#include <linux/kdev_t.h>···676 */677static void __init iSeries_setup_arch(void)678{0679 unsigned procIx = get_paca()->lppaca.dyn_hv_phys_proc_index;680681 /* Add an eye catcher and the systemcfg layout version number */···685 systemcfg->version.minor = SYSTEMCFG_MINOR;686687 /* Setup the Lp Event Queue */688+ setup_hvlpevent_queue();00000000000000000689690 /* Compute processor frequency */691 procFreqHz = ((1UL << 34) * 1000000) /···852}853854late_initcall(iSeries_src_init);0000000000000000000000855856#ifndef CONFIG_PCI857void __init iSeries_init_IRQ(void) { }
+2-2
arch/ppc64/kernel/idle.c
···8889 while (1) {90 if (lpaca->lppaca.shared_proc) {91- if (ItLpQueue_isLpIntPending(lpaca->lpqueue_ptr))92 process_iSeries_events();93 if (!need_resched())94 yield_shared_processor();···100101 while (!need_resched()) {102 HMT_medium();103- if (ItLpQueue_isLpIntPending(lpaca->lpqueue_ptr))104 process_iSeries_events();105 HMT_low();106 }
···8889 while (1) {90 if (lpaca->lppaca.shared_proc) {91+ if (hvlpevent_is_pending())92 process_iSeries_events();93 if (!need_resched())94 yield_shared_processor();···100101 while (!need_resched()) {102 HMT_medium();103+ if (hvlpevent_is_pending())104 process_iSeries_events();105 HMT_low();106 }
···801 return rc;802 /* We need to poll here as we are not yet taking interrupts */803 while (rtc_data.busy) {804- extern unsigned long lpevent_count;805- struct ItLpQueue *lpq = get_paca()->lpqueue_ptr;806- if (lpq && ItLpQueue_isLpIntPending(lpq))807- lpevent_count += ItLpQueue_process(lpq, NULL);808 }809 return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);810}
···801 return rc;802 /* We need to poll here as we are not yet taking interrupts */803 while (rtc_data.busy) {804+ if (hvlpevent_is_pending())805+ process_hvlpevents(NULL);00806 }807 return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);808}
+3-5
arch/ppc64/kernel/nvram.c
···338 */339static int nvram_create_os_partition(void)340{341- struct list_head * p;342- struct nvram_partition *part = NULL;343- struct nvram_partition *new_part = NULL;344 struct nvram_partition *free_part = NULL;345 int seq_init[2] = { 0, 0 };346 loff_t tmp_index;···348349 /* Find a free partition that will give us the maximum needed size 350 If can't find one that will give us the minimum size needed */351- list_for_each(p, &nvram_part->partition) {352- part = list_entry(p, struct nvram_partition, partition);353 if (part->header.signature != NVRAM_SIG_FREE)354 continue;355
···338 */339static int nvram_create_os_partition(void)340{341+ struct nvram_partition *part;342+ struct nvram_partition *new_part;0343 struct nvram_partition *free_part = NULL;344 int seq_init[2] = { 0, 0 };345 loff_t tmp_index;···349350 /* Find a free partition that will give us the maximum needed size 351 If can't find one that will give us the minimum size needed */352+ list_for_each_entry(part, &nvram_part->partition, partition) {0353 if (part->header.signature != NVRAM_SIG_FREE)354 continue;355
···400 struct cpu *c = &per_cpu(cpu_devices, cpu);401402#ifdef CONFIG_NUMA403- parent = &node_devices[cpu_to_node(cpu)];00000404#endif405 /*406 * For now, we just see if the system supports making
···400 struct cpu *c = &per_cpu(cpu_devices, cpu);401402#ifdef CONFIG_NUMA403+ /* The node to which a cpu belongs can't be known404+ * until the cpu is made present.405+ */406+ parent = NULL;407+ if (cpu_present(cpu))408+ parent = &node_devices[cpu_to_node(cpu)];409#endif410 /*411 * For now, we just see if the system supports making
+2-6
arch/ppc64/kernel/time.c
···99struct gettimeofday_struct do_gtod;100101extern unsigned long wall_jiffies;102-extern unsigned long lpevent_count;103extern int smp_tb_synchronized;104105extern struct timezone sys_tz;···366 set_dec(next_dec);367368#ifdef CONFIG_PPC_ISERIES369- {370- struct ItLpQueue *lpq = lpaca->lpqueue_ptr;371- if (lpq && ItLpQueue_isLpIntPending(lpq))372- lpevent_count += ItLpQueue_process(lpq, regs);373- }374#endif375376/* collect purr register values often, for accurate calculations */
···99struct gettimeofday_struct do_gtod;100101extern unsigned long wall_jiffies;0102extern int smp_tb_synchronized;103104extern struct timezone sys_tz;···367 set_dec(next_dec);368369#ifdef CONFIG_PPC_ISERIES370+ if (hvlpevent_is_pending())371+ process_hvlpevents(regs);000372#endif373374/* collect purr register values often, for accurate calculations */
+6-9
include/asm-ppc64/iSeries/ItLpQueue.h
···41#define LpEventMaxSize 25642#define LpEventAlign 644344-struct ItLpQueue {45/*46 * The xSlicCurEventPtr is the pointer to the next event stack entry47 * that will become valid. The OS must peek at this entry to determine···69 char *xSlicEventStackPtr; // 0x2070 u8 xIndex; // 0x28 unique sequential index.71 u8 xSlicRsvd[3]; // 0x29-2b72- u32 xInUseWord; // 0x2C73- u64 xLpIntCount; // 0x30 Total Lp Int msgs processed74- u64 xLpIntCountByType[9]; // 0x38-0x7F Event counts by type75};7677-extern struct ItLpQueue xItLpQueue;7879-extern struct HvLpEvent *ItLpQueue_getNextLpEvent(struct ItLpQueue *);80-extern int ItLpQueue_isLpIntPending(struct ItLpQueue *);81-extern unsigned ItLpQueue_process(struct ItLpQueue *, struct pt_regs *);82-extern void ItLpQueue_clearValid(struct HvLpEvent *);8384#endif /* _ITLPQUEUE_H */
···41#define LpEventMaxSize 25642#define LpEventAlign 644344+struct hvlpevent_queue {45/*46 * The xSlicCurEventPtr is the pointer to the next event stack entry47 * that will become valid. The OS must peek at this entry to determine···69 char *xSlicEventStackPtr; // 0x2070 u8 xIndex; // 0x28 unique sequential index.71 u8 xSlicRsvd[3]; // 0x29-2b72+ spinlock_t lock;0073};7475+extern struct hvlpevent_queue hvlpevent_queue;7677+extern int hvlpevent_is_pending(void);78+extern void process_hvlpevents(struct pt_regs *);79+extern void setup_hvlpevent_queue(void);08081#endif /* _ITLPQUEUE_H */
-3
include/asm-ppc64/paca.h
···20#include <asm/types.h>21#include <asm/lppaca.h>22#include <asm/iSeries/ItLpRegSave.h>23-#include <asm/iSeries/ItLpQueue.h>24#include <asm/mmu.h>2526register struct paca_struct *local_paca asm("r13");···61 u16 paca_index; /* Logical processor number */6263 u32 default_decr; /* Default decrementer value */64- struct ItLpQueue *lpqueue_ptr; /* LpQueue handled by this CPU */65 u64 kernel_toc; /* Kernel TOC address */66 u64 stab_real; /* Absolute address of segment table */67 u64 stab_addr; /* Virtual address of segment table */···89 u64 next_jiffy_update_tb; /* TB value for next jiffy update */90 u64 saved_r1; /* r1 save for RTAS calls */91 u64 saved_msr; /* MSR saved here by enter_rtas */92- u32 lpevent_count; /* lpevents processed */93 u8 proc_enabled; /* irq soft-enable flag */9495 /* not yet used */
···20#include <asm/types.h>21#include <asm/lppaca.h>22#include <asm/iSeries/ItLpRegSave.h>023#include <asm/mmu.h>2425register struct paca_struct *local_paca asm("r13");···62 u16 paca_index; /* Logical processor number */6364 u32 default_decr; /* Default decrementer value */065 u64 kernel_toc; /* Kernel TOC address */66 u64 stab_real; /* Absolute address of segment table */67 u64 stab_addr; /* Virtual address of segment table */···91 u64 next_jiffy_update_tb; /* TB value for next jiffy update */92 u64 saved_r1; /* r1 save for RTAS calls */93 u64 saved_msr; /* MSR saved here by enter_rtas */094 u8 proc_enabled; /* irq soft-enable flag */9596 /* not yet used */