diff options
author | Michael Neuling <mikey@neuling.org> | 2012-09-06 21:24:56 +0000 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2012-09-10 09:59:10 +1000 |
commit | 4474ef055c5d8cb8eaf002d69e49af71e3aa3a88 (patch) | |
tree | e57b99bfa78d7c3faf4125ab4a08f17fed2c41d8 /arch/powerpc/platforms | |
parent | 3ab96a02e829131c19db8ed99239289acdb4e3dc (diff) | |
download | linux-4474ef055c5d8cb8eaf002d69e49af71e3aa3a88.tar.gz linux-4474ef055c5d8cb8eaf002d69e49af71e3aa3a88.tar.bz2 linux-4474ef055c5d8cb8eaf002d69e49af71e3aa3a88.zip |
powerpc: Rework set_dabr so it can take a DABRX value as well
Rework set_dabr to take a DABRX value as well.
Both the pseries and PS3 hypervisors do some checks on the DABRX
values that are passed in the hcall. This patch stops bogus values
from being passed to hypervisor. Also, in the case where we are
clearing the breakpoint, where DABR and DABRX are zero, we modify the
DABRX value to make it valid so that the hcall won't fail.
Signed-off-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r-- | arch/powerpc/platforms/cell/beat.c | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/beat.h | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/ps3/setup.c | 10 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/setup.c | 14 |
4 files changed, 19 insertions, 11 deletions
diff --git a/arch/powerpc/platforms/cell/beat.c b/arch/powerpc/platforms/cell/beat.c index 852592b2b712..affcf566d460 100644 --- a/arch/powerpc/platforms/cell/beat.c +++ b/arch/powerpc/platforms/cell/beat.c @@ -136,9 +136,9 @@ ssize_t beat_nvram_get_size(void) return BEAT_NVRAM_SIZE; } -int beat_set_xdabr(unsigned long dabr) +int beat_set_xdabr(unsigned long dabr, unsigned long dabrx) { - if (beat_set_dabr(dabr, DABRX_KERNEL | DABRX_USER)) + if (beat_set_dabr(dabr, dabrx)) return -1; return 0; } diff --git a/arch/powerpc/platforms/cell/beat.h b/arch/powerpc/platforms/cell/beat.h index 32c8efcedc80..bfcb8e351ae5 100644 --- a/arch/powerpc/platforms/cell/beat.h +++ b/arch/powerpc/platforms/cell/beat.h @@ -32,7 +32,7 @@ void beat_get_rtc_time(struct rtc_time *); ssize_t beat_nvram_get_size(void); ssize_t beat_nvram_read(char *, size_t, loff_t *); ssize_t beat_nvram_write(char *, size_t, loff_t *); -int beat_set_xdabr(unsigned long); +int beat_set_xdabr(unsigned long, unsigned long); void beat_power_save(void); void beat_kexec_cpu_down(int, int); diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c index 2d664c5a83b0..3f509f86432c 100644 --- a/arch/powerpc/platforms/ps3/setup.c +++ b/arch/powerpc/platforms/ps3/setup.c @@ -184,11 +184,15 @@ early_param("ps3flash", early_parse_ps3flash); #define prealloc_ps3flash_bounce_buffer() do { } while (0) #endif -static int ps3_set_dabr(unsigned long dabr) +static int ps3_set_dabr(unsigned long dabr, unsigned long dabrx) { - enum {DABR_USER = 1, DABR_KERNEL = 2,}; + /* Have to set at least one bit in the DABRX */ + if (dabrx == 0 && dabr == 0) + dabrx = DABRX_USER; + /* hypervisor only allows us to set BTI, Kernel and user */ + dabrx &= DABRX_BTI | DABRX_KERNEL | DABRX_USER; - return lv1_set_dabr(dabr, DABR_KERNEL | DABR_USER) ? -1 : 0; + return lv1_set_dabr(dabr, dabrx) ? -1 : 0; } static void __init ps3_setup_arch(void) diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 4a2cd48b21f6..a3a69658a6ec 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -414,16 +414,20 @@ static int __init pSeries_init_panel(void) } machine_arch_initcall(pseries, pSeries_init_panel); -static int pseries_set_dabr(unsigned long dabr) +static int pseries_set_dabr(unsigned long dabr, unsigned long dabrx) { return plpar_hcall_norets(H_SET_DABR, dabr); } -static int pseries_set_xdabr(unsigned long dabr) +static int pseries_set_xdabr(unsigned long dabr, unsigned long dabrx) { - /* We want to catch accesses from kernel and userspace */ - return plpar_hcall_norets(H_SET_XDABR, dabr, - H_DABRX_KERNEL | H_DABRX_USER); + /* Have to set at least one bit in the DABRX according to PAPR */ + if (dabrx == 0 && dabr == 0) + dabrx = DABRX_USER; + /* PAPR says we can only set kernel and user bits */ + dabrx &= H_DABRX_KERNEL | H_DABRX_USER; + + return plpar_hcall_norets(H_SET_XDABR, dabr, dabrx); } #define CMO_CHARACTERISTICS_TOKEN 44 |