Merge refs/heads/devtree from rsync://oak/kernels/iseries/work/.git
This commit is contained in:
Коммит
51a0885ed7
|
@ -357,7 +357,6 @@ config HOTPLUG_CPU
|
|||
|
||||
config PROC_DEVICETREE
|
||||
bool "Support for Open Firmware device tree in /proc"
|
||||
depends on !PPC_ISERIES
|
||||
help
|
||||
This option adds a device-tree directory under /proc which contains
|
||||
an image of the device tree that the kernel copies from Open
|
||||
|
|
|
@ -11,7 +11,7 @@ obj-y := setup.o entry.o traps.o irq.o idle.o dma.o \
|
|||
udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \
|
||||
ptrace32.o signal32.o rtc.o init_task.o \
|
||||
lmb.o cputable.o cpu_setup_power4.o idle_power4.o \
|
||||
iommu.o sysfs.o vdso.o pmc.o firmware.o
|
||||
iommu.o sysfs.o vdso.o pmc.o firmware.o prom.o
|
||||
obj-y += vdso32/ vdso64/
|
||||
|
||||
obj-$(CONFIG_PPC_OF) += of_device.o
|
||||
|
@ -27,7 +27,7 @@ obj-$(CONFIG_PPC_ISERIES) += HvCall.o HvLpConfig.o LparData.o \
|
|||
mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \
|
||||
iSeries_iommu.o
|
||||
|
||||
obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o prom.o
|
||||
obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o
|
||||
|
||||
obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \
|
||||
pSeries_nvram.o rtasd.o ras.o pSeries_reconfig.o \
|
||||
|
|
|
@ -1364,6 +1364,7 @@ _STATIC(__start_initialization_iSeries)
|
|||
addi r2,r2,0x4000
|
||||
|
||||
bl .iSeries_early_setup
|
||||
bl .early_setup
|
||||
|
||||
/* relocation is on at this point */
|
||||
|
||||
|
@ -1970,20 +1971,22 @@ _GLOBAL(hmt_start_secondary)
|
|||
blr
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_KEXEC) || (defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES))
|
||||
#if defined(CONFIG_KEXEC) || defined(CONFIG_SMP)
|
||||
_GLOBAL(smp_release_cpus)
|
||||
/* All secondary cpus are spinning on a common
|
||||
* spinloop, release them all now so they can start
|
||||
* to spin on their individual paca spinloops.
|
||||
* For non SMP kernels, the secondary cpus never
|
||||
* get out of the common spinloop.
|
||||
* XXX This does nothing useful on iSeries, secondaries are
|
||||
* already waiting on their paca.
|
||||
*/
|
||||
li r3,1
|
||||
LOADADDR(r5,__secondary_hold_spinloop)
|
||||
std r3,0(r5)
|
||||
sync
|
||||
blr
|
||||
#endif /* CONFIG_SMP && !CONFIG_PPC_ISERIES */
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -84,6 +84,25 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
|
|||
return (secondary << 3) | (slot & 7);
|
||||
}
|
||||
|
||||
long iSeries_hpte_bolt_or_insert(unsigned long hpte_group,
|
||||
unsigned long va, unsigned long prpn, unsigned long vflags,
|
||||
unsigned long rflags)
|
||||
{
|
||||
long slot;
|
||||
hpte_t lhpte;
|
||||
|
||||
slot = HvCallHpt_findValid(&lhpte, va >> PAGE_SHIFT);
|
||||
|
||||
if (lhpte.v & HPTE_V_VALID) {
|
||||
/* Bolt the existing HPTE */
|
||||
HvCallHpt_setSwBits(slot, 0x10, 0);
|
||||
HvCallHpt_setPp(slot, PP_RWXX);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return iSeries_hpte_insert(hpte_group, va, prpn, vflags, rflags);
|
||||
}
|
||||
|
||||
static unsigned long iSeries_hpte_getword0(unsigned long slot)
|
||||
{
|
||||
hpte_t hpte;
|
||||
|
|
|
@ -351,3 +351,16 @@ int __init iSeries_allocate_IRQ(HvBusNumber busNumber,
|
|||
irq_desc[virtirq].handler = &iSeries_IRQ_handler;
|
||||
return virtirq;
|
||||
}
|
||||
|
||||
int virt_irq_create_mapping(unsigned int real_irq)
|
||||
{
|
||||
BUG(); /* Don't call this on iSeries, yet */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void virt_irq_init(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -74,8 +74,8 @@ extern void hvlog(char *fmt, ...);
|
|||
extern void ppcdbg_initialize(void);
|
||||
|
||||
static void build_iSeries_Memory_Map(void);
|
||||
static void setup_iSeries_cache_sizes(void);
|
||||
static void iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr);
|
||||
static int iseries_shared_idle(void);
|
||||
static int iseries_dedicated_idle(void);
|
||||
#ifdef CONFIG_PCI
|
||||
extern void iSeries_pci_final_fixup(void);
|
||||
#else
|
||||
|
@ -83,14 +83,6 @@ static void iSeries_pci_final_fixup(void) { }
|
|||
#endif
|
||||
|
||||
/* Global Variables */
|
||||
static unsigned long procFreqHz;
|
||||
static unsigned long procFreqMhz;
|
||||
static unsigned long procFreqMhzHundreths;
|
||||
|
||||
static unsigned long tbFreqHz;
|
||||
static unsigned long tbFreqMhz;
|
||||
static unsigned long tbFreqMhzHundreths;
|
||||
|
||||
int piranha_simulator;
|
||||
|
||||
extern int rd_size; /* Defined in drivers/block/rd.c */
|
||||
|
@ -319,6 +311,8 @@ static void __init iSeries_init_early(void)
|
|||
|
||||
ppcdbg_initialize();
|
||||
|
||||
ppc64_interrupt_controller = IC_ISERIES;
|
||||
|
||||
#if defined(CONFIG_BLK_DEV_INITRD)
|
||||
/*
|
||||
* If the init RAM disk has been configured and there is
|
||||
|
@ -340,12 +334,6 @@ static void __init iSeries_init_early(void)
|
|||
iSeries_recal_tb = get_tb();
|
||||
iSeries_recal_titan = HvCallXm_loadTod();
|
||||
|
||||
/*
|
||||
* Cache sizes must be initialized before hpte_init_iSeries is called
|
||||
* as the later need them for flush_icache_range()
|
||||
*/
|
||||
setup_iSeries_cache_sizes();
|
||||
|
||||
/*
|
||||
* Initialize the hash table management pointers
|
||||
*/
|
||||
|
@ -356,12 +344,6 @@ static void __init iSeries_init_early(void)
|
|||
*/
|
||||
iommu_init_early_iSeries();
|
||||
|
||||
/*
|
||||
* Initialize the table which translate Linux physical addresses to
|
||||
* AS/400 absolute addresses
|
||||
*/
|
||||
build_iSeries_Memory_Map();
|
||||
|
||||
iSeries_get_cmdline();
|
||||
|
||||
/* Save unparsed command line copy for /proc/cmdline */
|
||||
|
@ -379,14 +361,6 @@ static void __init iSeries_init_early(void)
|
|||
}
|
||||
}
|
||||
|
||||
/* Bolt kernel mappings for all of memory (or just a bit if we've got a limit) */
|
||||
iSeries_bolt_kernel(0, systemcfg->physicalMemorySize);
|
||||
|
||||
lmb_init();
|
||||
lmb_add(0, systemcfg->physicalMemorySize);
|
||||
lmb_analyze();
|
||||
lmb_reserve(0, __pa(klimit));
|
||||
|
||||
/* Initialize machine-dependency vectors */
|
||||
#ifdef CONFIG_SMP
|
||||
smp_init_iSeries();
|
||||
|
@ -591,103 +565,6 @@ static void __init build_iSeries_Memory_Map(void)
|
|||
systemcfg->physicalMemorySize = chunk_to_addr(nextPhysChunk);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the variables that describe the cache line sizes
|
||||
* for this machine.
|
||||
*/
|
||||
static void __init setup_iSeries_cache_sizes(void)
|
||||
{
|
||||
unsigned int i, n;
|
||||
unsigned int procIx = get_paca()->lppaca.dyn_hv_phys_proc_index;
|
||||
|
||||
systemcfg->icache_size =
|
||||
ppc64_caches.isize = xIoHriProcessorVpd[procIx].xInstCacheSize * 1024;
|
||||
systemcfg->icache_line_size =
|
||||
ppc64_caches.iline_size =
|
||||
xIoHriProcessorVpd[procIx].xInstCacheOperandSize;
|
||||
systemcfg->dcache_size =
|
||||
ppc64_caches.dsize =
|
||||
xIoHriProcessorVpd[procIx].xDataL1CacheSizeKB * 1024;
|
||||
systemcfg->dcache_line_size =
|
||||
ppc64_caches.dline_size =
|
||||
xIoHriProcessorVpd[procIx].xDataCacheOperandSize;
|
||||
ppc64_caches.ilines_per_page = PAGE_SIZE / ppc64_caches.iline_size;
|
||||
ppc64_caches.dlines_per_page = PAGE_SIZE / ppc64_caches.dline_size;
|
||||
|
||||
i = ppc64_caches.iline_size;
|
||||
n = 0;
|
||||
while ((i = (i / 2)))
|
||||
++n;
|
||||
ppc64_caches.log_iline_size = n;
|
||||
|
||||
i = ppc64_caches.dline_size;
|
||||
n = 0;
|
||||
while ((i = (i / 2)))
|
||||
++n;
|
||||
ppc64_caches.log_dline_size = n;
|
||||
|
||||
printk("D-cache line size = %d\n",
|
||||
(unsigned int)ppc64_caches.dline_size);
|
||||
printk("I-cache line size = %d\n",
|
||||
(unsigned int)ppc64_caches.iline_size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a pte. Used during initialization only.
|
||||
*/
|
||||
static void iSeries_make_pte(unsigned long va, unsigned long pa,
|
||||
int mode)
|
||||
{
|
||||
hpte_t local_hpte, rhpte;
|
||||
unsigned long hash, vpn;
|
||||
long slot;
|
||||
|
||||
vpn = va >> PAGE_SHIFT;
|
||||
hash = hpt_hash(vpn, 0);
|
||||
|
||||
local_hpte.r = pa | mode;
|
||||
local_hpte.v = ((va >> 23) << HPTE_V_AVPN_SHIFT)
|
||||
| HPTE_V_BOLTED | HPTE_V_VALID;
|
||||
|
||||
slot = HvCallHpt_findValid(&rhpte, vpn);
|
||||
if (slot < 0) {
|
||||
/* Must find space in primary group */
|
||||
panic("hash_page: hpte already exists\n");
|
||||
}
|
||||
HvCallHpt_addValidate(slot, 0, &local_hpte);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bolt the kernel addr space into the HPT
|
||||
*/
|
||||
static void __init iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr)
|
||||
{
|
||||
unsigned long pa;
|
||||
unsigned long mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX;
|
||||
hpte_t hpte;
|
||||
|
||||
for (pa = saddr; pa < eaddr ;pa += PAGE_SIZE) {
|
||||
unsigned long ea = (unsigned long)__va(pa);
|
||||
unsigned long vsid = get_kernel_vsid(ea);
|
||||
unsigned long va = (vsid << 28) | (pa & 0xfffffff);
|
||||
unsigned long vpn = va >> PAGE_SHIFT;
|
||||
unsigned long slot = HvCallHpt_findValid(&hpte, vpn);
|
||||
|
||||
/* Make non-kernel text non-executable */
|
||||
if (!in_kernel_text(ea))
|
||||
mode_rw |= HW_NO_EXEC;
|
||||
|
||||
if (hpte.v & HPTE_V_VALID) {
|
||||
/* HPTE exists, so just bolt it */
|
||||
HvCallHpt_setSwBits(slot, 0x10, 0);
|
||||
/* And make sure the pp bits are correct */
|
||||
HvCallHpt_setPp(slot, PP_RWXX);
|
||||
} else
|
||||
/* No HPTE exists, so create a new bolted one */
|
||||
iSeries_make_pte(va, phys_to_abs(pa), mode_rw);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Document me.
|
||||
*/
|
||||
|
@ -695,36 +572,22 @@ static void __init iSeries_setup_arch(void)
|
|||
{
|
||||
unsigned procIx = get_paca()->lppaca.dyn_hv_phys_proc_index;
|
||||
|
||||
/* Add an eye catcher and the systemcfg layout version number */
|
||||
strcpy(systemcfg->eye_catcher, "SYSTEMCFG:PPC64");
|
||||
systemcfg->version.major = SYSTEMCFG_MAJOR;
|
||||
systemcfg->version.minor = SYSTEMCFG_MINOR;
|
||||
if (get_paca()->lppaca.shared_proc) {
|
||||
ppc_md.idle_loop = iseries_shared_idle;
|
||||
printk(KERN_INFO "Using shared processor idle loop\n");
|
||||
} else {
|
||||
ppc_md.idle_loop = iseries_dedicated_idle;
|
||||
printk(KERN_INFO "Using dedicated idle loop\n");
|
||||
}
|
||||
|
||||
/* Setup the Lp Event Queue */
|
||||
setup_hvlpevent_queue();
|
||||
|
||||
/* Compute processor frequency */
|
||||
procFreqHz = ((1UL << 34) * 1000000) /
|
||||
xIoHriProcessorVpd[procIx].xProcFreq;
|
||||
procFreqMhz = procFreqHz / 1000000;
|
||||
procFreqMhzHundreths = (procFreqHz / 10000) - (procFreqMhz * 100);
|
||||
ppc_proc_freq = procFreqHz;
|
||||
|
||||
/* Compute time base frequency */
|
||||
tbFreqHz = ((1UL << 32) * 1000000) /
|
||||
xIoHriProcessorVpd[procIx].xTimeBaseFreq;
|
||||
tbFreqMhz = tbFreqHz / 1000000;
|
||||
tbFreqMhzHundreths = (tbFreqHz / 10000) - (tbFreqMhz * 100);
|
||||
ppc_tb_freq = tbFreqHz;
|
||||
|
||||
printk("Max logical processors = %d\n",
|
||||
itVpdAreas.xSlicMaxLogicalProcs);
|
||||
printk("Max physical processors = %d\n",
|
||||
itVpdAreas.xSlicMaxPhysicalProcs);
|
||||
printk("Processor frequency = %lu.%02lu\n", procFreqMhz,
|
||||
procFreqMhzHundreths);
|
||||
printk("Time base frequency = %lu.%02lu\n", tbFreqMhz,
|
||||
tbFreqMhzHundreths);
|
||||
|
||||
systemcfg->processor = xIoHriProcessorVpd[procIx].xPVR;
|
||||
printk("Processor version = %x\n", systemcfg->processor);
|
||||
}
|
||||
|
@ -768,49 +631,6 @@ static void iSeries_halt(void)
|
|||
mf_power_off();
|
||||
}
|
||||
|
||||
/*
|
||||
* void __init iSeries_calibrate_decr()
|
||||
*
|
||||
* Description:
|
||||
* This routine retrieves the internal processor frequency from the VPD,
|
||||
* and sets up the kernel timer decrementer based on that value.
|
||||
*
|
||||
*/
|
||||
static void __init iSeries_calibrate_decr(void)
|
||||
{
|
||||
unsigned long cyclesPerUsec;
|
||||
struct div_result divres;
|
||||
|
||||
/* Compute decrementer (and TB) frequency in cycles/sec */
|
||||
cyclesPerUsec = ppc_tb_freq / 1000000;
|
||||
|
||||
/*
|
||||
* Set the amount to refresh the decrementer by. This
|
||||
* is the number of decrementer ticks it takes for
|
||||
* 1/HZ seconds.
|
||||
*/
|
||||
tb_ticks_per_jiffy = ppc_tb_freq / HZ;
|
||||
|
||||
#if 0
|
||||
/* TEST CODE FOR ADJTIME */
|
||||
tb_ticks_per_jiffy += tb_ticks_per_jiffy / 5000;
|
||||
/* END OF TEST CODE */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* tb_ticks_per_sec = freq; would give better accuracy
|
||||
* but tb_ticks_per_sec = tb_ticks_per_jiffy*HZ; assures
|
||||
* that jiffies (and xtime) will match the time returned
|
||||
* by do_gettimeofday.
|
||||
*/
|
||||
tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
|
||||
tb_ticks_per_usec = cyclesPerUsec;
|
||||
tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
|
||||
div128_by_32(1024 * 1024, 0, tb_ticks_per_sec, &divres);
|
||||
tb_to_xs = divres.result_low;
|
||||
setup_default_decr();
|
||||
}
|
||||
|
||||
static void __init iSeries_progress(char * st, unsigned short code)
|
||||
{
|
||||
printk("Progress: [%04x] - %s\n", (unsigned)code, st);
|
||||
|
@ -942,36 +762,246 @@ static int iseries_dedicated_idle(void)
|
|||
void __init iSeries_init_IRQ(void) { }
|
||||
#endif
|
||||
|
||||
void __init iSeries_early_setup(void)
|
||||
static int __init iseries_probe(int platform)
|
||||
{
|
||||
iSeries_fixup_klimit();
|
||||
|
||||
ppc_md.setup_arch = iSeries_setup_arch;
|
||||
ppc_md.get_cpuinfo = iSeries_get_cpuinfo;
|
||||
ppc_md.init_IRQ = iSeries_init_IRQ;
|
||||
ppc_md.get_irq = iSeries_get_irq;
|
||||
ppc_md.init_early = iSeries_init_early,
|
||||
|
||||
ppc_md.pcibios_fixup = iSeries_pci_final_fixup;
|
||||
|
||||
ppc_md.restart = iSeries_restart;
|
||||
ppc_md.power_off = iSeries_power_off;
|
||||
ppc_md.halt = iSeries_halt;
|
||||
|
||||
ppc_md.get_boot_time = iSeries_get_boot_time;
|
||||
ppc_md.set_rtc_time = iSeries_set_rtc_time;
|
||||
ppc_md.get_rtc_time = iSeries_get_rtc_time;
|
||||
ppc_md.calibrate_decr = iSeries_calibrate_decr;
|
||||
ppc_md.progress = iSeries_progress;
|
||||
return PLATFORM_ISERIES_LPAR == platform;
|
||||
}
|
||||
|
||||
struct machdep_calls __initdata iseries_md = {
|
||||
.setup_arch = iSeries_setup_arch,
|
||||
.get_cpuinfo = iSeries_get_cpuinfo,
|
||||
.init_IRQ = iSeries_init_IRQ,
|
||||
.get_irq = iSeries_get_irq,
|
||||
.init_early = iSeries_init_early,
|
||||
.pcibios_fixup = iSeries_pci_final_fixup,
|
||||
.restart = iSeries_restart,
|
||||
.power_off = iSeries_power_off,
|
||||
.halt = iSeries_halt,
|
||||
.get_boot_time = iSeries_get_boot_time,
|
||||
.set_rtc_time = iSeries_set_rtc_time,
|
||||
.get_rtc_time = iSeries_get_rtc_time,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = iSeries_progress,
|
||||
.probe = iseries_probe,
|
||||
/* XXX Implement enable_pmcs for iSeries */
|
||||
};
|
||||
|
||||
if (get_paca()->lppaca.shared_proc) {
|
||||
ppc_md.idle_loop = iseries_shared_idle;
|
||||
printk(KERN_INFO "Using shared processor idle loop\n");
|
||||
} else {
|
||||
ppc_md.idle_loop = iseries_dedicated_idle;
|
||||
printk(KERN_INFO "Using dedicated idle loop\n");
|
||||
struct blob {
|
||||
unsigned char data[PAGE_SIZE];
|
||||
unsigned long next;
|
||||
};
|
||||
|
||||
struct iseries_flat_dt {
|
||||
struct boot_param_header header;
|
||||
u64 reserve_map[2];
|
||||
struct blob dt;
|
||||
struct blob strings;
|
||||
};
|
||||
|
||||
struct iseries_flat_dt iseries_dt;
|
||||
|
||||
void dt_init(struct iseries_flat_dt *dt)
|
||||
{
|
||||
dt->header.off_mem_rsvmap =
|
||||
offsetof(struct iseries_flat_dt, reserve_map);
|
||||
dt->header.off_dt_struct = offsetof(struct iseries_flat_dt, dt);
|
||||
dt->header.off_dt_strings = offsetof(struct iseries_flat_dt, strings);
|
||||
dt->header.totalsize = sizeof(struct iseries_flat_dt);
|
||||
dt->header.dt_strings_size = sizeof(struct blob);
|
||||
|
||||
/* There is no notion of hardware cpu id on iSeries */
|
||||
dt->header.boot_cpuid_phys = smp_processor_id();
|
||||
|
||||
dt->dt.next = (unsigned long)&dt->dt.data;
|
||||
dt->strings.next = (unsigned long)&dt->strings.data;
|
||||
|
||||
dt->header.magic = OF_DT_HEADER;
|
||||
dt->header.version = 0x10;
|
||||
dt->header.last_comp_version = 0x10;
|
||||
|
||||
dt->reserve_map[0] = 0;
|
||||
dt->reserve_map[1] = 0;
|
||||
}
|
||||
|
||||
void dt_check_blob(struct blob *b)
|
||||
{
|
||||
if (b->next >= (unsigned long)&b->next) {
|
||||
DBG("Ran out of space in flat device tree blob!\n");
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
void dt_push_u32(struct iseries_flat_dt *dt, u32 value)
|
||||
{
|
||||
*((u32*)dt->dt.next) = value;
|
||||
dt->dt.next += sizeof(u32);
|
||||
|
||||
dt_check_blob(&dt->dt);
|
||||
}
|
||||
|
||||
void dt_push_u64(struct iseries_flat_dt *dt, u64 value)
|
||||
{
|
||||
*((u64*)dt->dt.next) = value;
|
||||
dt->dt.next += sizeof(u64);
|
||||
|
||||
dt_check_blob(&dt->dt);
|
||||
}
|
||||
|
||||
unsigned long dt_push_bytes(struct blob *blob, char *data, int len)
|
||||
{
|
||||
unsigned long start = blob->next - (unsigned long)blob->data;
|
||||
|
||||
memcpy((char *)blob->next, data, len);
|
||||
blob->next = _ALIGN(blob->next + len, 4);
|
||||
|
||||
dt_check_blob(blob);
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
void dt_start_node(struct iseries_flat_dt *dt, char *name)
|
||||
{
|
||||
dt_push_u32(dt, OF_DT_BEGIN_NODE);
|
||||
dt_push_bytes(&dt->dt, name, strlen(name) + 1);
|
||||
}
|
||||
|
||||
#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
|
||||
|
||||
void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len)
|
||||
{
|
||||
unsigned long offset;
|
||||
|
||||
dt_push_u32(dt, OF_DT_PROP);
|
||||
|
||||
/* Length of the data */
|
||||
dt_push_u32(dt, len);
|
||||
|
||||
/* Put the property name in the string blob. */
|
||||
offset = dt_push_bytes(&dt->strings, name, strlen(name) + 1);
|
||||
|
||||
/* The offset of the properties name in the string blob. */
|
||||
dt_push_u32(dt, (u32)offset);
|
||||
|
||||
/* The actual data. */
|
||||
dt_push_bytes(&dt->dt, data, len);
|
||||
}
|
||||
|
||||
void dt_prop_str(struct iseries_flat_dt *dt, char *name, char *data)
|
||||
{
|
||||
dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */
|
||||
}
|
||||
|
||||
void dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data)
|
||||
{
|
||||
dt_prop(dt, name, (char *)&data, sizeof(u32));
|
||||
}
|
||||
|
||||
void dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data)
|
||||
{
|
||||
dt_prop(dt, name, (char *)&data, sizeof(u64));
|
||||
}
|
||||
|
||||
void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n)
|
||||
{
|
||||
dt_prop(dt, name, (char *)data, sizeof(u64) * n);
|
||||
}
|
||||
|
||||
void dt_prop_empty(struct iseries_flat_dt *dt, char *name)
|
||||
{
|
||||
dt_prop(dt, name, NULL, 0);
|
||||
}
|
||||
|
||||
void dt_cpus(struct iseries_flat_dt *dt)
|
||||
{
|
||||
unsigned char buf[32];
|
||||
unsigned char *p;
|
||||
unsigned int i, index;
|
||||
struct IoHriProcessorVpd *d;
|
||||
|
||||
/* yuck */
|
||||
snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name);
|
||||
p = strchr(buf, ' ');
|
||||
if (!p) p = buf + strlen(buf);
|
||||
|
||||
dt_start_node(dt, "cpus");
|
||||
dt_prop_u32(dt, "#address-cells", 1);
|
||||
dt_prop_u32(dt, "#size-cells", 0);
|
||||
|
||||
for (i = 0; i < NR_CPUS; i++) {
|
||||
if (paca[i].lppaca.dyn_proc_status >= 2)
|
||||
continue;
|
||||
|
||||
snprintf(p, 32 - (p - buf), "@%d", i);
|
||||
dt_start_node(dt, buf);
|
||||
|
||||
dt_prop_str(dt, "device_type", "cpu");
|
||||
|
||||
index = paca[i].lppaca.dyn_hv_phys_proc_index;
|
||||
d = &xIoHriProcessorVpd[index];
|
||||
|
||||
dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);
|
||||
dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize);
|
||||
|
||||
dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024);
|
||||
dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize);
|
||||
|
||||
/* magic conversions to Hz copied from old code */
|
||||
dt_prop_u32(dt, "clock-frequency",
|
||||
((1UL << 34) * 1000000) / d->xProcFreq);
|
||||
dt_prop_u32(dt, "timebase-frequency",
|
||||
((1UL << 32) * 1000000) / d->xTimeBaseFreq);
|
||||
|
||||
dt_prop_u32(dt, "reg", i);
|
||||
|
||||
dt_end_node(dt);
|
||||
}
|
||||
|
||||
dt_end_node(dt);
|
||||
}
|
||||
|
||||
void build_flat_dt(struct iseries_flat_dt *dt)
|
||||
{
|
||||
u64 tmp[2];
|
||||
|
||||
dt_init(dt);
|
||||
|
||||
dt_start_node(dt, "");
|
||||
|
||||
dt_prop_u32(dt, "#address-cells", 2);
|
||||
dt_prop_u32(dt, "#size-cells", 2);
|
||||
|
||||
/* /memory */
|
||||
dt_start_node(dt, "memory@0");
|
||||
dt_prop_str(dt, "name", "memory");
|
||||
dt_prop_str(dt, "device_type", "memory");
|
||||
tmp[0] = 0;
|
||||
tmp[1] = systemcfg->physicalMemorySize;
|
||||
dt_prop_u64_list(dt, "reg", tmp, 2);
|
||||
dt_end_node(dt);
|
||||
|
||||
/* /chosen */
|
||||
dt_start_node(dt, "chosen");
|
||||
dt_prop_u32(dt, "linux,platform", PLATFORM_ISERIES_LPAR);
|
||||
dt_end_node(dt);
|
||||
|
||||
dt_cpus(dt);
|
||||
|
||||
dt_end_node(dt);
|
||||
|
||||
dt_push_u32(dt, OF_DT_END);
|
||||
}
|
||||
|
||||
void * __init iSeries_early_setup(void)
|
||||
{
|
||||
iSeries_fixup_klimit();
|
||||
|
||||
/*
|
||||
* Initialize the table which translate Linux physical addresses to
|
||||
* AS/400 absolute addresses
|
||||
*/
|
||||
build_iSeries_Memory_Map();
|
||||
|
||||
build_flat_dt(&iseries_dt);
|
||||
|
||||
return (void *) __pa(&iseries_dt);
|
||||
}
|
||||
|
|
|
@ -82,35 +82,9 @@ static void smp_iSeries_message_pass(int target, int msg)
|
|||
}
|
||||
}
|
||||
|
||||
static int smp_iSeries_numProcs(void)
|
||||
{
|
||||
unsigned np, i;
|
||||
|
||||
np = 0;
|
||||
for (i=0; i < NR_CPUS; ++i) {
|
||||
if (paca[i].lppaca.dyn_proc_status < 2) {
|
||||
cpu_set(i, cpu_possible_map);
|
||||
cpu_set(i, cpu_present_map);
|
||||
cpu_set(i, cpu_sibling_map[i]);
|
||||
++np;
|
||||
}
|
||||
}
|
||||
return np;
|
||||
}
|
||||
|
||||
static int smp_iSeries_probe(void)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned np = 0;
|
||||
|
||||
for (i=0; i < NR_CPUS; ++i) {
|
||||
if (paca[i].lppaca.dyn_proc_status < 2) {
|
||||
/*paca[i].active = 1;*/
|
||||
++np;
|
||||
}
|
||||
}
|
||||
|
||||
return np;
|
||||
return cpus_weight(cpu_possible_map);
|
||||
}
|
||||
|
||||
static void smp_iSeries_kick_cpu(int nr)
|
||||
|
@ -144,6 +118,4 @@ static struct smp_ops_t iSeries_smp_ops = {
|
|||
void __init smp_init_iSeries(void)
|
||||
{
|
||||
smp_ops = &iSeries_smp_ops;
|
||||
systemcfg->processorCount = smp_iSeries_numProcs();
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#include <asm/mmu.h>
|
||||
#include <asm/lmb.h>
|
||||
#include <asm/iSeries/ItLpNaca.h>
|
||||
#include <asm/firmware.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(fmt...) udbg_printf(fmt)
|
||||
|
@ -153,7 +154,7 @@ struct screen_info screen_info = {
|
|||
.orig_video_points = 16
|
||||
};
|
||||
|
||||
#if defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_SMP)
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
static int smt_enabled_cmdline;
|
||||
|
||||
|
@ -306,15 +307,13 @@ static void __init setup_cpu_maps(void)
|
|||
|
||||
systemcfg->processorCount = num_present_cpus();
|
||||
}
|
||||
#endif /* defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_SMP) */
|
||||
|
||||
|
||||
#ifdef CONFIG_PPC_MULTIPLATFORM
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
extern struct machdep_calls pSeries_md;
|
||||
extern struct machdep_calls pmac_md;
|
||||
extern struct machdep_calls maple_md;
|
||||
extern struct machdep_calls bpa_md;
|
||||
extern struct machdep_calls iseries_md;
|
||||
|
||||
/* Ultimately, stuff them in an elf section like initcalls... */
|
||||
static struct machdep_calls __initdata *machines[] = {
|
||||
|
@ -329,6 +328,9 @@ static struct machdep_calls __initdata *machines[] = {
|
|||
#endif /* CONFIG_PPC_MAPLE */
|
||||
#ifdef CONFIG_PPC_BPA
|
||||
&bpa_md,
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
&iseries_md,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
@ -401,7 +403,8 @@ void __init early_setup(unsigned long dt_ptr)
|
|||
/*
|
||||
* Initialize stab / SLB management
|
||||
*/
|
||||
stab_initialize(lpaca->stab_real);
|
||||
if (!firmware_has_feature(FW_FEATURE_ISERIES))
|
||||
stab_initialize(lpaca->stab_real);
|
||||
|
||||
/*
|
||||
* Initialize the MMU Hash table and create the linear mapping
|
||||
|
@ -532,8 +535,6 @@ static void __init check_for_initrd(void)
|
|||
#endif /* CONFIG_BLK_DEV_INITRD */
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PPC_MULTIPLATFORM */
|
||||
|
||||
/*
|
||||
* Do some initial setup of the system. The parameters are those which
|
||||
* were passed in from the bootloader.
|
||||
|
@ -542,14 +543,6 @@ void __init setup_system(void)
|
|||
{
|
||||
DBG(" -> setup_system()\n");
|
||||
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
/* pSeries systems are identified in prom.c via OF. */
|
||||
if (itLpNaca.xLparInstalled == 1)
|
||||
systemcfg->platform = PLATFORM_ISERIES_LPAR;
|
||||
|
||||
ppc_md.init_early();
|
||||
#else /* CONFIG_PPC_ISERIES */
|
||||
|
||||
/*
|
||||
* Unflatten the device-tree passed by prom_init or kexec
|
||||
*/
|
||||
|
@ -607,9 +600,8 @@ void __init setup_system(void)
|
|||
strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
|
||||
|
||||
parse_early_param();
|
||||
#endif /* !CONFIG_PPC_ISERIES */
|
||||
|
||||
#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES)
|
||||
#ifdef CONFIG_SMP
|
||||
/*
|
||||
* iSeries has already initialized the cpu maps at this point.
|
||||
*/
|
||||
|
@ -619,7 +611,7 @@ void __init setup_system(void)
|
|||
* we can map physical -> logical CPU ids
|
||||
*/
|
||||
smp_release_cpus();
|
||||
#endif /* defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES) */
|
||||
#endif
|
||||
|
||||
printk("Starting Linux PPC64 %s\n", system_utsname.version);
|
||||
|
||||
|
|
|
@ -465,7 +465,7 @@ int do_settimeofday(struct timespec *tv)
|
|||
|
||||
EXPORT_SYMBOL(do_settimeofday);
|
||||
|
||||
#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_MAPLE) || defined(CONFIG_PPC_BPA)
|
||||
#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_MAPLE) || defined(CONFIG_PPC_BPA) || defined(CONFIG_PPC_ISERIES)
|
||||
void __init generic_calibrate_decr(void)
|
||||
{
|
||||
struct device_node *cpu;
|
||||
|
|
|
@ -90,7 +90,6 @@ static inline void loop_forever(void)
|
|||
;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC_MULTIPLATFORM
|
||||
static inline void create_pte_mapping(unsigned long start, unsigned long end,
|
||||
unsigned long mode, int large)
|
||||
{
|
||||
|
@ -111,7 +110,7 @@ static inline void create_pte_mapping(unsigned long start, unsigned long end,
|
|||
unsigned long vpn, hash, hpteg;
|
||||
unsigned long vsid = get_kernel_vsid(addr);
|
||||
unsigned long va = (vsid << 28) | (addr & 0xfffffff);
|
||||
int ret;
|
||||
int ret = -1;
|
||||
|
||||
if (large)
|
||||
vpn = va >> HPAGE_SHIFT;
|
||||
|
@ -129,16 +128,25 @@ static inline void create_pte_mapping(unsigned long start, unsigned long end,
|
|||
|
||||
hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
|
||||
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
if (systemcfg->platform & PLATFORM_ISERIES_LPAR)
|
||||
ret = iSeries_hpte_bolt_or_insert(hpteg, va,
|
||||
virt_to_abs(addr) >> PAGE_SHIFT,
|
||||
vflags, tmp_mode);
|
||||
else
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_PSERIES
|
||||
if (systemcfg->platform & PLATFORM_LPAR)
|
||||
ret = pSeries_lpar_hpte_insert(hpteg, va,
|
||||
virt_to_abs(addr) >> PAGE_SHIFT,
|
||||
vflags, tmp_mode);
|
||||
else
|
||||
#endif /* CONFIG_PPC_PSERIES */
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_MULTIPLATFORM
|
||||
ret = native_hpte_insert(hpteg, va,
|
||||
virt_to_abs(addr) >> PAGE_SHIFT,
|
||||
vflags, tmp_mode);
|
||||
#endif
|
||||
|
||||
if (ret == -1) {
|
||||
ppc64_terminate_msg(0x20, "create_pte_mapping");
|
||||
|
@ -261,7 +269,6 @@ void __init htab_initialize(void)
|
|||
}
|
||||
#undef KB
|
||||
#undef MB
|
||||
#endif /* CONFIG_PPC_MULTIPLATFORM */
|
||||
|
||||
/*
|
||||
* Called by asm hashtable.S for doing lazy icache flush
|
||||
|
|
|
@ -206,6 +206,10 @@ extern long native_hpte_insert(unsigned long hpte_group, unsigned long va,
|
|||
unsigned long prpn,
|
||||
unsigned long vflags, unsigned long rflags);
|
||||
|
||||
extern long iSeries_hpte_bolt_or_insert(unsigned long hpte_group,
|
||||
unsigned long va, unsigned long prpn,
|
||||
unsigned long vflags, unsigned long rflags);
|
||||
|
||||
extern void stabs_alloc(void);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
|
|
@ -291,6 +291,7 @@
|
|||
#define IC_OPEN_PIC 1
|
||||
#define IC_PPC_XIC 2
|
||||
#define IC_BPA_IIC 3
|
||||
#define IC_ISERIES 4
|
||||
|
||||
#define XGLUE(a,b) a##b
|
||||
#define GLUE(a,b) XGLUE(a,b)
|
||||
|
|
Загрузка…
Ссылка в новой задаче