2005-11-09 03:38:01 +01:00
|
|
|
#ifndef _ASM_POWERPC_ABS_ADDR_H
|
|
|
|
#define _ASM_POWERPC_ABS_ADDR_H
|
2005-12-16 22:43:46 +01:00
|
|
|
#ifdef __KERNEL__
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* c 2001 PPC 64 Team, IBM Corp
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version
|
|
|
|
* 2 of the License, or (at your option) any later version.
|
|
|
|
*/
|
|
|
|
|
2008-02-14 01:56:49 +01:00
|
|
|
#include <linux/lmb.h>
|
|
|
|
|
2005-04-17 00:20:36 +02:00
|
|
|
#include <asm/types.h>
|
|
|
|
#include <asm/page.h>
|
|
|
|
#include <asm/prom.h>
|
2005-08-03 12:21:26 +02:00
|
|
|
#include <asm/firmware.h>
|
2005-08-03 12:21:23 +02:00
|
|
|
|
|
|
|
struct mschunks_map {
|
2005-04-17 00:20:36 +02:00
|
|
|
unsigned long num_chunks;
|
|
|
|
unsigned long chunk_size;
|
|
|
|
unsigned long chunk_shift;
|
|
|
|
unsigned long chunk_mask;
|
2005-08-03 12:21:23 +02:00
|
|
|
u32 *mapping;
|
2005-04-17 00:20:36 +02:00
|
|
|
};
|
|
|
|
|
2005-08-03 12:21:23 +02:00
|
|
|
extern struct mschunks_map mschunks_map;
|
2005-04-17 00:20:36 +02:00
|
|
|
|
2005-08-03 12:21:23 +02:00
|
|
|
/* Chunks are 256 KB */
|
|
|
|
#define MSCHUNKS_CHUNK_SHIFT (18)
|
|
|
|
#define MSCHUNKS_CHUNK_SIZE (1UL << MSCHUNKS_CHUNK_SHIFT)
|
|
|
|
#define MSCHUNKS_OFFSET_MASK (MSCHUNKS_CHUNK_SIZE - 1)
|
|
|
|
|
2005-08-03 12:21:23 +02:00
|
|
|
static inline unsigned long chunk_to_addr(unsigned long chunk)
|
2005-04-17 00:20:36 +02:00
|
|
|
{
|
2005-08-03 12:21:23 +02:00
|
|
|
return chunk << MSCHUNKS_CHUNK_SHIFT;
|
2005-04-17 00:20:36 +02:00
|
|
|
}
|
|
|
|
|
2005-08-03 12:21:23 +02:00
|
|
|
static inline unsigned long addr_to_chunk(unsigned long addr)
|
2005-04-17 00:20:36 +02:00
|
|
|
{
|
2005-08-03 12:21:23 +02:00
|
|
|
return addr >> MSCHUNKS_CHUNK_SHIFT;
|
2005-04-17 00:20:36 +02:00
|
|
|
}
|
|
|
|
|
2005-08-03 12:21:23 +02:00
|
|
|
static inline unsigned long phys_to_abs(unsigned long pa)
|
2005-04-17 00:20:36 +02:00
|
|
|
{
|
2005-08-03 12:21:23 +02:00
|
|
|
unsigned long chunk;
|
2005-04-17 00:20:36 +02:00
|
|
|
|
2005-08-03 12:21:26 +02:00
|
|
|
/* This is a no-op on non-iSeries */
|
|
|
|
if (!firmware_has_feature(FW_FEATURE_ISERIES))
|
|
|
|
return pa;
|
|
|
|
|
2005-08-03 12:21:23 +02:00
|
|
|
chunk = addr_to_chunk(pa);
|
2005-08-03 12:21:23 +02:00
|
|
|
|
2005-08-03 12:21:23 +02:00
|
|
|
if (chunk < mschunks_map.num_chunks)
|
|
|
|
chunk = mschunks_map.mapping[chunk];
|
2005-04-17 00:20:36 +02:00
|
|
|
|
2005-08-03 12:21:23 +02:00
|
|
|
return chunk_to_addr(chunk) + (pa & MSCHUNKS_OFFSET_MASK);
|
|
|
|
}
|
2005-04-17 00:20:36 +02:00
|
|
|
|
|
|
|
/* Convenience macros */
|
|
|
|
#define virt_to_abs(va) phys_to_abs(__pa(va))
|
[PATCH] ppc64: Remove redundant abs_to_phys() macro
abs_to_phys() is a macro that turns out to do nothing, and also has the
unfortunate property that it's not the inverse of phys_to_abs() on iSeries.
The following is for my benefit as much as everyone else.
With CONFIG_MSCHUNKS enabled, the lmb code is changed such that it keeps
a physbase variable for each lmb region. This is used to take the possibly
discontiguous lmb regions and present them as a contiguous address space
beginning from zero.
In this context each lmb region's base address is its "absolute" base
address, and its physbase is it's "physical" address (from Linux's point of
view). The abs_to_phys() macro does the mapping from "absolute" to "physical".
Note: This is not related to the iSeries mapping of physical to absolute
(ie. Hypervisor) addresses which is maintained with the msChunks structure.
And the msChunks structure is not controlled via CONFIG_MSCHUNKS.
Once upon a time you could compile for non-iSeries with CONFIG_MSCHUNKS
enabled. But these days CONFIG_MSCHUNKS depends on CONFIG_PPC_ISERIES, so
for non-iSeries code abs_to_phys() is a no-op.
On iSeries we always have one lmb region which spans from 0 to
systemcfg->physicalMemorySize (arch/ppc64/kernel/iSeries_setup.c line 383).
This region has a base (ie. absolute) address of 0, and a physbase address
of 0 (as calculated in lmb_analyze() (arch/ppc64/kernel/lmb.c line 144)).
On iSeries, abs_to_phys(aa) is defined as lmb_abs_to_phys(aa), which finds
the lmb region containing aa (and there's only one, ie. 0), and then does:
return lmb.memory.region[0].physbase + (aa - lmb.memory.region[0].base)
physbase == base == 0, so you're left with "return aa".
So remove abs_to_phys(), and lmb_abs_to_phys() which is the implementation
of abs_to_phys() for iSeries.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Paul Mackerras <paulus@samba.org>
2005-08-03 12:21:25 +02:00
|
|
|
#define abs_to_virt(aa) __va(aa)
|
2005-04-17 00:20:36 +02:00
|
|
|
|
2005-10-14 06:51:42 +02:00
|
|
|
/*
|
|
|
|
* Converts Virtual Address to Real Address for
|
|
|
|
* Legacy iSeries Hypervisor calls
|
|
|
|
*/
|
|
|
|
#define iseries_hv_addr(virtaddr) \
|
|
|
|
(0x8000000000000000 | virt_to_abs(virtaddr))
|
|
|
|
|
2005-12-16 22:43:46 +01:00
|
|
|
#endif /* __KERNEL__ */
|
2005-11-09 03:38:01 +01:00
|
|
|
#endif /* _ASM_POWERPC_ABS_ADDR_H */
|