From b6f27b2db2df395d65b02a758861c7fc54edbec1 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Fri, 30 Sep 2016 14:10:11 +0300 Subject: clk: ti: add clkdm_lookup to the exported functions This will be needed to move some additional clockdomain functionality under clock driver. Signed-off-by: Tero Kristo Acked-by: Tony Lindgren --- arch/arm/mach-omap2/clock.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 1270afdcacdf..6fac82609c96 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -57,6 +57,7 @@ u16 cpu_mask; static struct ti_clk_ll_ops omap_clk_ll_ops = { .clkdm_clk_enable = clkdm_clk_enable, .clkdm_clk_disable = clkdm_clk_disable, + .clkdm_lookup = clkdm_lookup, .cm_wait_module_ready = omap_cm_wait_module_ready, .cm_split_idlest_reg = cm_split_idlest_reg, }; -- cgit v1.2.3-59-g8ed1b From 2e1a294c0f2273a6d3537c91965ca46a6483bd8c Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Fri, 30 Sep 2016 14:13:38 +0300 Subject: clk: ti: move omap2_init_clk_clkdm under TI clock driver This is not needed outside the driver, so move it inside it and remove the prototype from the public header also. Signed-off-by: Tero Kristo Acked-by: Tony Lindgren --- arch/arm/mach-omap2/clock.c | 32 -------------------------------- drivers/clk/ti/clock.h | 1 + drivers/clk/ti/clockdomain.c | 30 ++++++++++++++++++++++++++++++ include/linux/clk/ti.h | 1 - 4 files changed, 31 insertions(+), 33 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 6fac82609c96..ae5b23c19b83 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -79,38 +79,6 @@ int __init omap2_clk_setup_ll_ops(void) * OMAP2+ specific clock functions */ -/* Public functions */ - -/** - * omap2_init_clk_clkdm - look up a clockdomain name, store pointer in clk - * @clk: OMAP clock struct ptr to use - * - * Convert a clockdomain name stored in a struct clk 'clk' into a - * clockdomain pointer, and save it into the struct clk. Intended to be - * called during clk_register(). No return value. - */ -void omap2_init_clk_clkdm(struct clk_hw *hw) -{ - struct clk_hw_omap *clk = to_clk_hw_omap(hw); - struct clockdomain *clkdm; - const char *clk_name; - - if (!clk->clkdm_name) - return; - - clk_name = __clk_get_name(hw->clk); - - clkdm = clkdm_lookup(clk->clkdm_name); - if (clkdm) { - pr_debug("clock: associated clk %s to clkdm %s\n", - clk_name, clk->clkdm_name); - clk->clkdm = clkdm; - } else { - pr_debug("clock: could not associate clk %s to clkdm %s\n", - clk_name, clk->clkdm_name); - } -} - /** * ti_clk_init_features - init clock features struct for the SoC * diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h index ee6d22507a3d..ecf82d86118c 100644 --- a/drivers/clk/ti/clock.h +++ b/drivers/clk/ti/clock.h @@ -228,6 +228,7 @@ extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait; extern const struct clk_ops ti_clk_divider_ops; extern const struct clk_ops ti_clk_mux_ops; +void omap2_init_clk_clkdm(struct clk_hw *hw); int omap2_clkops_enable_clkdm(struct clk_hw *hw); void omap2_clkops_disable_clkdm(struct clk_hw *hw); diff --git a/drivers/clk/ti/clockdomain.c b/drivers/clk/ti/clockdomain.c index 6cf9dd189a92..704157d8c0b7 100644 --- a/drivers/clk/ti/clockdomain.c +++ b/drivers/clk/ti/clockdomain.c @@ -103,6 +103,36 @@ void omap2_clkops_disable_clkdm(struct clk_hw *hw) ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk); } +/** + * omap2_init_clk_clkdm - look up a clockdomain name, store pointer in clk + * @clk: OMAP clock struct ptr to use + * + * Convert a clockdomain name stored in a struct clk 'clk' into a + * clockdomain pointer, and save it into the struct clk. Intended to be + * called during clk_register(). No return value. + */ +void omap2_init_clk_clkdm(struct clk_hw *hw) +{ + struct clk_hw_omap *clk = to_clk_hw_omap(hw); + struct clockdomain *clkdm; + const char *clk_name; + + if (!clk->clkdm_name) + return; + + clk_name = __clk_get_name(hw->clk); + + clkdm = ti_clk_ll_ops->clkdm_lookup(clk->clkdm_name); + if (clkdm) { + pr_debug("clock: associated clk %s to clkdm %s\n", + clk_name, clk->clkdm_name); + clk->clkdm = clkdm; + } else { + pr_debug("clock: could not associate clk %s to clkdm %s\n", + clk_name, clk->clkdm_name); + } +} + static void __init of_ti_clockdomain_setup(struct device_node *node) { struct clk *clk; diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h index bc7fd8f0fb5d..626ae94b7444 100644 --- a/include/linux/clk/ti.h +++ b/include/linux/clk/ti.h @@ -238,7 +238,6 @@ struct ti_clk_ll_ops { #define to_clk_hw_omap(_hw) container_of(_hw, struct clk_hw_omap, hw) -void omap2_init_clk_clkdm(struct clk_hw *clk); int omap2_clk_disable_autoidle_all(void); int omap2_clk_enable_autoidle_all(void); int omap2_clk_allow_idle(struct clk *clk); -- cgit v1.2.3-59-g8ed1b From 6c0afb503937a12a8d20a805fcf263e31afa9871 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Thu, 9 Feb 2017 11:24:37 +0200 Subject: clk: ti: convert to use proper register definition for all accesses Currently, TI clock driver uses an encapsulated struct that is cast into a void pointer to store all register addresses. This can be considered as rather nasty hackery, and prevents from expanding the register address field also. Instead, replace all the code to use proper struct in place for this, which contains all the previously used data. This patch is rather large as it is touching multiple files, but this can't be split up as we need to avoid any boot breakage. Signed-off-by: Tero Kristo Acked-by: Tony Lindgren --- arch/arm/mach-omap2/clkt2xxx_dpllcore.c | 3 +- arch/arm/mach-omap2/clock.c | 2 +- arch/arm/mach-omap2/clock.h | 2 ++ arch/arm/mach-omap2/cm.h | 5 +-- arch/arm/mach-omap2/cm2xxx.c | 9 ++--- arch/arm/mach-omap2/cm3xxx.c | 10 ++---- arch/arm/mach-omap2/cm_common.c | 2 +- drivers/clk/ti/apll.c | 47 ++++++++++++------------- drivers/clk/ti/autoidle.c | 18 +++++----- drivers/clk/ti/clk-3xxx.c | 55 +++++++++++++++-------------- drivers/clk/ti/clk.c | 47 ++++++++++++------------- drivers/clk/ti/clkt_dflt.c | 61 ++++++++++++--------------------- drivers/clk/ti/clkt_dpll.c | 6 ++-- drivers/clk/ti/clkt_iclk.c | 29 ++++++++-------- drivers/clk/ti/clock.h | 11 +++--- drivers/clk/ti/clockdomain.c | 8 ----- drivers/clk/ti/divider.c | 24 +++++++------ drivers/clk/ti/dpll.c | 48 ++++++++++---------------- drivers/clk/ti/dpll3xxx.c | 38 ++++++++++---------- drivers/clk/ti/dpll44xx.c | 14 ++++---- drivers/clk/ti/gate.c | 32 ++++++++--------- drivers/clk/ti/interface.c | 22 ++++++------ drivers/clk/ti/mux.c | 41 +++++++++------------- include/linux/clk/ti.h | 46 +++++++++++++------------ 24 files changed, 264 insertions(+), 316 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/clkt2xxx_dpllcore.c b/arch/arm/mach-omap2/clkt2xxx_dpllcore.c index 59cf310bc1e9..e8d417309f33 100644 --- a/arch/arm/mach-omap2/clkt2xxx_dpllcore.c +++ b/arch/arm/mach-omap2/clkt2xxx_dpllcore.c @@ -138,7 +138,8 @@ int omap2_reprogram_dpllcore(struct clk_hw *hw, unsigned long rate, if (!dd) return -EINVAL; - tmpset.cm_clksel1_pll = readl_relaxed(dd->mult_div1_reg); + tmpset.cm_clksel1_pll = + omap_clk_ll_ops.clk_readl(&dd->mult_div1_reg); tmpset.cm_clksel1_pll &= ~(dd->mult_mask | dd->div1_mask); div = ((curr_prcm_set->xtal_speed / 1000000) - 1); diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index ae5b23c19b83..42881f21cede 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -54,7 +54,7 @@ u16 cpu_mask; #define OMAP3PLUS_DPLL_FINT_MIN 32000 #define OMAP3PLUS_DPLL_FINT_MAX 52000000 -static struct ti_clk_ll_ops omap_clk_ll_ops = { +struct ti_clk_ll_ops omap_clk_ll_ops = { .clkdm_clk_enable = clkdm_clk_enable, .clkdm_clk_disable = clkdm_clk_disable, .clkdm_lookup = clkdm_lookup, diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 4e66295dca25..cf45550197e6 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -64,6 +64,8 @@ #define OMAP4XXX_EN_DPLL_FRBYPASS 0x6 #define OMAP4XXX_EN_DPLL_LOCKED 0x7 +extern struct ti_clk_ll_ops omap_clk_ll_ops; + extern u16 cpu_mask; extern const struct clkops clkops_omap2_dflt_wait; diff --git a/arch/arm/mach-omap2/cm.h b/arch/arm/mach-omap2/cm.h index 1fe3e6b833d2..de75cbcdc9d1 100644 --- a/arch/arm/mach-omap2/cm.h +++ b/arch/arm/mach-omap2/cm.h @@ -23,6 +23,7 @@ #define MAX_MODULE_READY_TIME 2000 # ifndef __ASSEMBLER__ +#include extern void __iomem *cm_base; extern void __iomem *cm2_base; extern void omap2_set_globals_cm(void __iomem *cm, void __iomem *cm2); @@ -50,7 +51,7 @@ extern void omap2_set_globals_cm(void __iomem *cm, void __iomem *cm2); * @module_disable: ptr to the SoC CM-specific module_disable impl */ struct cm_ll_data { - int (*split_idlest_reg)(void __iomem *idlest_reg, s16 *prcm_inst, + int (*split_idlest_reg)(struct clk_omap_reg *idlest_reg, s16 *prcm_inst, u8 *idlest_reg_id); int (*wait_module_ready)(u8 part, s16 prcm_mod, u16 idlest_reg, u8 idlest_shift); @@ -60,7 +61,7 @@ struct cm_ll_data { void (*module_disable)(u8 part, u16 inst, u16 clkctrl_offs); }; -extern int cm_split_idlest_reg(void __iomem *idlest_reg, s16 *prcm_inst, +extern int cm_split_idlest_reg(struct clk_omap_reg *idlest_reg, s16 *prcm_inst, u8 *idlest_reg_id); int omap_cm_wait_module_ready(u8 part, s16 prcm_mod, u16 idlest_reg, u8 idlest_shift); diff --git a/arch/arm/mach-omap2/cm2xxx.c b/arch/arm/mach-omap2/cm2xxx.c index 3e5fd3587eb1..cd90b4c6a06b 100644 --- a/arch/arm/mach-omap2/cm2xxx.c +++ b/arch/arm/mach-omap2/cm2xxx.c @@ -204,7 +204,7 @@ void omap2xxx_cm_apll96_disable(void) * XXX This function is only needed until absolute register addresses are * removed from the OMAP struct clk records. */ -static int omap2xxx_cm_split_idlest_reg(void __iomem *idlest_reg, +static int omap2xxx_cm_split_idlest_reg(struct clk_omap_reg *idlest_reg, s16 *prcm_inst, u8 *idlest_reg_id) { @@ -212,10 +212,7 @@ static int omap2xxx_cm_split_idlest_reg(void __iomem *idlest_reg, u8 idlest_offs; int i; - if (idlest_reg < cm_base || idlest_reg > (cm_base + 0x0fff)) - return -EINVAL; - - idlest_offs = (unsigned long)idlest_reg & 0xff; + idlest_offs = idlest_reg->offset & 0xff; for (i = 0; i < ARRAY_SIZE(omap2xxx_cm_idlest_offs); i++) { if (idlest_offs == omap2xxx_cm_idlest_offs[i]) { *idlest_reg_id = i + 1; @@ -226,7 +223,7 @@ static int omap2xxx_cm_split_idlest_reg(void __iomem *idlest_reg, if (i == ARRAY_SIZE(omap2xxx_cm_idlest_offs)) return -EINVAL; - offs = idlest_reg - cm_base; + offs = idlest_reg->offset; offs &= 0xff00; *prcm_inst = offs; diff --git a/arch/arm/mach-omap2/cm3xxx.c b/arch/arm/mach-omap2/cm3xxx.c index d91ae8206d1e..55b046a719dc 100644 --- a/arch/arm/mach-omap2/cm3xxx.c +++ b/arch/arm/mach-omap2/cm3xxx.c @@ -118,7 +118,7 @@ static int omap3xxx_cm_wait_module_ready(u8 part, s16 prcm_mod, u16 idlest_id, * XXX This function is only needed until absolute register addresses are * removed from the OMAP struct clk records. */ -static int omap3xxx_cm_split_idlest_reg(void __iomem *idlest_reg, +static int omap3xxx_cm_split_idlest_reg(struct clk_omap_reg *idlest_reg, s16 *prcm_inst, u8 *idlest_reg_id) { @@ -126,11 +126,7 @@ static int omap3xxx_cm_split_idlest_reg(void __iomem *idlest_reg, u8 idlest_offs; int i; - if (idlest_reg < (cm_base + OMAP3430_IVA2_MOD) || - idlest_reg > (cm_base + 0x1ffff)) - return -EINVAL; - - idlest_offs = (unsigned long)idlest_reg & 0xff; + idlest_offs = idlest_reg->offset & 0xff; for (i = 0; i < ARRAY_SIZE(omap3xxx_cm_idlest_offs); i++) { if (idlest_offs == omap3xxx_cm_idlest_offs[i]) { *idlest_reg_id = i + 1; @@ -141,7 +137,7 @@ static int omap3xxx_cm_split_idlest_reg(void __iomem *idlest_reg, if (i == ARRAY_SIZE(omap3xxx_cm_idlest_offs)) return -EINVAL; - offs = idlest_reg - cm_base; + offs = idlest_reg->offset; offs &= 0xff00; *prcm_inst = offs; diff --git a/arch/arm/mach-omap2/cm_common.c b/arch/arm/mach-omap2/cm_common.c index 23e8bcec34e3..bbe41f4c9dc8 100644 --- a/arch/arm/mach-omap2/cm_common.c +++ b/arch/arm/mach-omap2/cm_common.c @@ -65,7 +65,7 @@ void __init omap2_set_globals_cm(void __iomem *cm, void __iomem *cm2) * or 0 upon success. XXX This function is only needed until absolute * register addresses are removed from the OMAP struct clk records. */ -int cm_split_idlest_reg(void __iomem *idlest_reg, s16 *prcm_inst, +int cm_split_idlest_reg(struct clk_omap_reg *idlest_reg, s16 *prcm_inst, u8 *idlest_reg_id) { if (!cm_ll_data->split_idlest_reg) { diff --git a/drivers/clk/ti/apll.c b/drivers/clk/ti/apll.c index 5cba28c6ab35..06f486b3488c 100644 --- a/drivers/clk/ti/apll.c +++ b/drivers/clk/ti/apll.c @@ -55,20 +55,20 @@ static int dra7_apll_enable(struct clk_hw *hw) state <<= __ffs(ad->idlest_mask); /* Check is already locked */ - v = ti_clk_ll_ops->clk_readl(ad->idlest_reg); + v = ti_clk_ll_ops->clk_readl(&ad->idlest_reg); if ((v & ad->idlest_mask) == state) return r; - v = ti_clk_ll_ops->clk_readl(ad->control_reg); + v = ti_clk_ll_ops->clk_readl(&ad->control_reg); v &= ~ad->enable_mask; v |= APLL_FORCE_LOCK << __ffs(ad->enable_mask); - ti_clk_ll_ops->clk_writel(v, ad->control_reg); + ti_clk_ll_ops->clk_writel(v, &ad->control_reg); state <<= __ffs(ad->idlest_mask); while (1) { - v = ti_clk_ll_ops->clk_readl(ad->idlest_reg); + v = ti_clk_ll_ops->clk_readl(&ad->idlest_reg); if ((v & ad->idlest_mask) == state) break; if (i > MAX_APLL_WAIT_TRIES) @@ -99,10 +99,10 @@ static void dra7_apll_disable(struct clk_hw *hw) state <<= __ffs(ad->idlest_mask); - v = ti_clk_ll_ops->clk_readl(ad->control_reg); + v = ti_clk_ll_ops->clk_readl(&ad->control_reg); v &= ~ad->enable_mask; v |= APLL_AUTO_IDLE << __ffs(ad->enable_mask); - ti_clk_ll_ops->clk_writel(v, ad->control_reg); + ti_clk_ll_ops->clk_writel(v, &ad->control_reg); } static int dra7_apll_is_enabled(struct clk_hw *hw) @@ -113,7 +113,7 @@ static int dra7_apll_is_enabled(struct clk_hw *hw) ad = clk->dpll_data; - v = ti_clk_ll_ops->clk_readl(ad->control_reg); + v = ti_clk_ll_ops->clk_readl(&ad->control_reg); v &= ad->enable_mask; v >>= __ffs(ad->enable_mask); @@ -185,6 +185,7 @@ static void __init of_dra7_apll_setup(struct device_node *node) struct clk_hw_omap *clk_hw = NULL; struct clk_init_data *init = NULL; const char **parent_names = NULL; + int ret; ad = kzalloc(sizeof(*ad), GFP_KERNEL); clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL); @@ -212,10 +213,10 @@ static void __init of_dra7_apll_setup(struct device_node *node) init->parent_names = parent_names; - ad->control_reg = ti_clk_get_reg_addr(node, 0); - ad->idlest_reg = ti_clk_get_reg_addr(node, 1); + ret = ti_clk_get_reg_addr(node, 0, &ad->control_reg); + ret |= ti_clk_get_reg_addr(node, 1, &ad->idlest_reg); - if (IS_ERR(ad->control_reg) || IS_ERR(ad->idlest_reg)) + if (ret) goto cleanup; ad->idlest_mask = 0x1; @@ -241,7 +242,7 @@ static int omap2_apll_is_enabled(struct clk_hw *hw) struct dpll_data *ad = clk->dpll_data; u32 v; - v = ti_clk_ll_ops->clk_readl(ad->control_reg); + v = ti_clk_ll_ops->clk_readl(&ad->control_reg); v &= ad->enable_mask; v >>= __ffs(ad->enable_mask); @@ -267,13 +268,13 @@ static int omap2_apll_enable(struct clk_hw *hw) u32 v; int i = 0; - v = ti_clk_ll_ops->clk_readl(ad->control_reg); + v = ti_clk_ll_ops->clk_readl(&ad->control_reg); v &= ~ad->enable_mask; v |= OMAP2_EN_APLL_LOCKED << __ffs(ad->enable_mask); - ti_clk_ll_ops->clk_writel(v, ad->control_reg); + ti_clk_ll_ops->clk_writel(v, &ad->control_reg); while (1) { - v = ti_clk_ll_ops->clk_readl(ad->idlest_reg); + v = ti_clk_ll_ops->clk_readl(&ad->idlest_reg); if (v & ad->idlest_mask) break; if (i > MAX_APLL_WAIT_TRIES) @@ -297,10 +298,10 @@ static void omap2_apll_disable(struct clk_hw *hw) struct dpll_data *ad = clk->dpll_data; u32 v; - v = ti_clk_ll_ops->clk_readl(ad->control_reg); + v = ti_clk_ll_ops->clk_readl(&ad->control_reg); v &= ~ad->enable_mask; v |= OMAP2_EN_APLL_STOPPED << __ffs(ad->enable_mask); - ti_clk_ll_ops->clk_writel(v, ad->control_reg); + ti_clk_ll_ops->clk_writel(v, &ad->control_reg); } static struct clk_ops omap2_apll_ops = { @@ -315,10 +316,10 @@ static void omap2_apll_set_autoidle(struct clk_hw_omap *clk, u32 val) struct dpll_data *ad = clk->dpll_data; u32 v; - v = ti_clk_ll_ops->clk_readl(ad->autoidle_reg); + v = ti_clk_ll_ops->clk_readl(&ad->autoidle_reg); v &= ~ad->autoidle_mask; v |= val << __ffs(ad->autoidle_mask); - ti_clk_ll_ops->clk_writel(v, ad->control_reg); + ti_clk_ll_ops->clk_writel(v, &ad->control_reg); } #define OMAP2_APLL_AUTOIDLE_LOW_POWER_STOP 0x3 @@ -347,6 +348,7 @@ static void __init of_omap2_apll_setup(struct device_node *node) struct clk *clk; const char *parent_name; u32 val; + int ret; ad = kzalloc(sizeof(*ad), GFP_KERNEL); clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL); @@ -392,12 +394,11 @@ static void __init of_omap2_apll_setup(struct device_node *node) ad->idlest_mask = 1 << val; - ad->control_reg = ti_clk_get_reg_addr(node, 0); - ad->autoidle_reg = ti_clk_get_reg_addr(node, 1); - ad->idlest_reg = ti_clk_get_reg_addr(node, 2); + ret = ti_clk_get_reg_addr(node, 0, &ad->control_reg); + ret |= ti_clk_get_reg_addr(node, 1, &ad->autoidle_reg); + ret |= ti_clk_get_reg_addr(node, 2, &ad->idlest_reg); - if (IS_ERR(ad->control_reg) || IS_ERR(ad->autoidle_reg) || - IS_ERR(ad->idlest_reg)) + if (ret) goto cleanup; clk = clk_register(NULL, &clk_hw->hw); diff --git a/drivers/clk/ti/autoidle.c b/drivers/clk/ti/autoidle.c index 345af43465f0..7bb9afbe4058 100644 --- a/drivers/clk/ti/autoidle.c +++ b/drivers/clk/ti/autoidle.c @@ -25,7 +25,7 @@ #include "clock.h" struct clk_ti_autoidle { - void __iomem *reg; + struct clk_omap_reg reg; u8 shift; u8 flags; const char *name; @@ -73,28 +73,28 @@ static void _allow_autoidle(struct clk_ti_autoidle *clk) { u32 val; - val = ti_clk_ll_ops->clk_readl(clk->reg); + val = ti_clk_ll_ops->clk_readl(&clk->reg); if (clk->flags & AUTOIDLE_LOW) val &= ~(1 << clk->shift); else val |= (1 << clk->shift); - ti_clk_ll_ops->clk_writel(val, clk->reg); + ti_clk_ll_ops->clk_writel(val, &clk->reg); } static void _deny_autoidle(struct clk_ti_autoidle *clk) { u32 val; - val = ti_clk_ll_ops->clk_readl(clk->reg); + val = ti_clk_ll_ops->clk_readl(&clk->reg); if (clk->flags & AUTOIDLE_LOW) val |= (1 << clk->shift); else val &= ~(1 << clk->shift); - ti_clk_ll_ops->clk_writel(val, clk->reg); + ti_clk_ll_ops->clk_writel(val, &clk->reg); } /** @@ -140,6 +140,7 @@ int __init of_ti_clk_autoidle_setup(struct device_node *node) { u32 shift; struct clk_ti_autoidle *clk; + int ret; /* Check if this clock has autoidle support or not */ if (of_property_read_u32(node, "ti,autoidle-shift", &shift)) @@ -152,11 +153,10 @@ int __init of_ti_clk_autoidle_setup(struct device_node *node) clk->shift = shift; clk->name = node->name; - clk->reg = ti_clk_get_reg_addr(node, 0); - - if (IS_ERR(clk->reg)) { + ret = ti_clk_get_reg_addr(node, 0, &clk->reg); + if (ret) { kfree(clk); - return -EINVAL; + return ret; } if (of_property_read_bool(node, "ti,invert-autoidle-bit")) diff --git a/drivers/clk/ti/clk-3xxx.c b/drivers/clk/ti/clk-3xxx.c index 11d8aa3ec186..b1251cae98b8 100644 --- a/drivers/clk/ti/clk-3xxx.c +++ b/drivers/clk/ti/clk-3xxx.c @@ -52,14 +52,13 @@ * @idlest_reg and @idlest_bit. No return value. */ static void omap3430es2_clk_ssi_find_idlest(struct clk_hw_omap *clk, - void __iomem **idlest_reg, + struct clk_omap_reg *idlest_reg, u8 *idlest_bit, u8 *idlest_val) { - u32 r; - - r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20); - *idlest_reg = (__force void __iomem *)r; + memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg)); + idlest_reg->offset &= ~0xf0; + idlest_reg->offset |= 0x20; *idlest_bit = OMAP3430ES2_ST_SSI_IDLE_SHIFT; *idlest_val = OMAP34XX_CM_IDLEST_VAL; } @@ -85,15 +84,15 @@ const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait = { * default find_idlest code assumes that they are at the same * position.) No return value. */ -static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk_hw_omap *clk, - void __iomem **idlest_reg, - u8 *idlest_bit, - u8 *idlest_val) +static void +omap3430es2_clk_dss_usbhost_find_idlest(struct clk_hw_omap *clk, + struct clk_omap_reg *idlest_reg, + u8 *idlest_bit, u8 *idlest_val) { - u32 r; + memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg)); - r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20); - *idlest_reg = (__force void __iomem *)r; + idlest_reg->offset &= ~0xf0; + idlest_reg->offset |= 0x20; /* USBHOST_IDLE has same shift */ *idlest_bit = OMAP3430ES2_ST_DSS_IDLE_SHIFT; *idlest_val = OMAP34XX_CM_IDLEST_VAL; @@ -122,15 +121,15 @@ const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait = { * shift from the CM_{I,F}CLKEN bit. Pass back the correct info via * @idlest_reg and @idlest_bit. No return value. */ -static void omap3430es2_clk_hsotgusb_find_idlest(struct clk_hw_omap *clk, - void __iomem **idlest_reg, - u8 *idlest_bit, - u8 *idlest_val) +static void +omap3430es2_clk_hsotgusb_find_idlest(struct clk_hw_omap *clk, + struct clk_omap_reg *idlest_reg, + u8 *idlest_bit, + u8 *idlest_val) { - u32 r; - - r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20); - *idlest_reg = (__force void __iomem *)r; + memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg)); + idlest_reg->offset &= ~0xf0; + idlest_reg->offset |= 0x20; *idlest_bit = OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT; *idlest_val = OMAP34XX_CM_IDLEST_VAL; } @@ -154,11 +153,11 @@ const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait = { * bit. A value of 1 indicates that clock is enabled. */ static void am35xx_clk_find_idlest(struct clk_hw_omap *clk, - void __iomem **idlest_reg, + struct clk_omap_reg *idlest_reg, u8 *idlest_bit, u8 *idlest_val) { - *idlest_reg = (__force void __iomem *)(clk->enable_reg); + memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg)); *idlest_bit = clk->enable_bit + AM35XX_IPSS_ICK_EN_ACK_OFFSET; *idlest_val = AM35XX_IPSS_CLK_IDLEST_VAL; } @@ -178,10 +177,10 @@ static void am35xx_clk_find_idlest(struct clk_hw_omap *clk, * avoid this issue, and remove the casts. No return value. */ static void am35xx_clk_find_companion(struct clk_hw_omap *clk, - void __iomem **other_reg, + struct clk_omap_reg *other_reg, u8 *other_bit) { - *other_reg = (__force void __iomem *)(clk->enable_reg); + memcpy(other_reg, &clk->enable_reg, sizeof(*other_reg)); if (clk->enable_bit & AM35XX_IPSS_ICK_MASK) *other_bit = clk->enable_bit + AM35XX_IPSS_ICK_FCK_OFFSET; else @@ -205,14 +204,14 @@ const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait = { * and @idlest_bit. No return value. */ static void am35xx_clk_ipss_find_idlest(struct clk_hw_omap *clk, - void __iomem **idlest_reg, + struct clk_omap_reg *idlest_reg, u8 *idlest_bit, u8 *idlest_val) { - u32 r; + memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg)); - r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20); - *idlest_reg = (__force void __iomem *)r; + idlest_reg->offset &= ~0xf0; + idlest_reg->offset |= 0x20; *idlest_bit = AM35XX_ST_IPSS_SHIFT; *idlest_val = OMAP34XX_CM_IDLEST_VAL; } diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c index 024123f421d6..ddbad7e8d7c9 100644 --- a/drivers/clk/ti/clk.c +++ b/drivers/clk/ti/clk.c @@ -43,27 +43,29 @@ struct clk_iomap { static struct clk_iomap *clk_memmaps[CLK_MAX_MEMMAPS]; -static void clk_memmap_writel(u32 val, void __iomem *reg) +static void clk_memmap_writel(u32 val, const struct clk_omap_reg *reg) { - struct clk_omap_reg *r = (struct clk_omap_reg *)® - struct clk_iomap *io = clk_memmaps[r->index]; + struct clk_iomap *io = clk_memmaps[reg->index]; - if (io->regmap) - regmap_write(io->regmap, r->offset, val); + if (reg->ptr) + writel_relaxed(val, reg->ptr); + else if (io->regmap) + regmap_write(io->regmap, reg->offset, val); else - writel_relaxed(val, io->mem + r->offset); + writel_relaxed(val, io->mem + reg->offset); } -static u32 clk_memmap_readl(void __iomem *reg) +static u32 clk_memmap_readl(const struct clk_omap_reg *reg) { u32 val; - struct clk_omap_reg *r = (struct clk_omap_reg *)® - struct clk_iomap *io = clk_memmaps[r->index]; + struct clk_iomap *io = clk_memmaps[reg->index]; - if (io->regmap) - regmap_read(io->regmap, r->offset, &val); + if (reg->ptr) + val = readl_relaxed(reg->ptr); + else if (io->regmap) + regmap_read(io->regmap, reg->offset, &val); else - val = readl_relaxed(io->mem + r->offset); + val = readl_relaxed(io->mem + reg->offset); return val; } @@ -162,20 +164,18 @@ int __init ti_clk_retry_init(struct device_node *node, struct clk_hw *hw, * ti_clk_get_reg_addr - get register address for a clock register * @node: device node for the clock * @index: register index from the clock node + * @reg: pointer to target register struct * - * Builds clock register address from device tree information. This - * is a struct of type clk_omap_reg. Returns a pointer to the register - * address, or a pointer error value in failure. + * Builds clock register address from device tree information, and returns + * the data via the provided output pointer @reg. Returns 0 on success, + * negative error value on failure. */ -void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index) +int ti_clk_get_reg_addr(struct device_node *node, int index, + struct clk_omap_reg *reg) { - struct clk_omap_reg *reg; u32 val; - u32 tmp; int i; - reg = (struct clk_omap_reg *)&tmp; - for (i = 0; i < CLK_MAX_MEMMAPS; i++) { if (clocks_node_ptr[i] == node->parent) break; @@ -183,19 +183,20 @@ void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index) if (i == CLK_MAX_MEMMAPS) { pr_err("clk-provider not found for %s!\n", node->name); - return IOMEM_ERR_PTR(-ENOENT); + return -ENOENT; } reg->index = i; if (of_property_read_u32_index(node, "reg", index, &val)) { pr_err("%s must have reg[%d]!\n", node->name, index); - return IOMEM_ERR_PTR(-EINVAL); + return -EINVAL; } reg->offset = val; + reg->ptr = NULL; - return (__force void __iomem *)tmp; + return 0; } /** diff --git a/drivers/clk/ti/clkt_dflt.c b/drivers/clk/ti/clkt_dflt.c index c6ae563801d7..91751dd26b16 100644 --- a/drivers/clk/ti/clkt_dflt.c +++ b/drivers/clk/ti/clkt_dflt.c @@ -55,7 +55,8 @@ * elapsed. XXX Deprecated - should be moved into drivers for the * individual IP block that the IDLEST register exists in. */ -static int _wait_idlest_generic(struct clk_hw_omap *clk, void __iomem *reg, +static int _wait_idlest_generic(struct clk_hw_omap *clk, + struct clk_omap_reg *reg, u32 mask, u8 idlest, const char *name) { int i = 0, ena = 0; @@ -91,7 +92,7 @@ static int _wait_idlest_generic(struct clk_hw_omap *clk, void __iomem *reg, */ static void _omap2_module_wait_ready(struct clk_hw_omap *clk) { - void __iomem *companion_reg, *idlest_reg; + struct clk_omap_reg companion_reg, idlest_reg; u8 other_bit, idlest_bit, idlest_val, idlest_reg_id; s16 prcm_mod; int r; @@ -99,17 +100,17 @@ static void _omap2_module_wait_ready(struct clk_hw_omap *clk) /* Not all modules have multiple clocks that their IDLEST depends on */ if (clk->ops->find_companion) { clk->ops->find_companion(clk, &companion_reg, &other_bit); - if (!(ti_clk_ll_ops->clk_readl(companion_reg) & + if (!(ti_clk_ll_ops->clk_readl(&companion_reg) & (1 << other_bit))) return; } clk->ops->find_idlest(clk, &idlest_reg, &idlest_bit, &idlest_val); - r = ti_clk_ll_ops->cm_split_idlest_reg(idlest_reg, &prcm_mod, + r = ti_clk_ll_ops->cm_split_idlest_reg(&idlest_reg, &prcm_mod, &idlest_reg_id); if (r) { /* IDLEST register not in the CM module */ - _wait_idlest_generic(clk, idlest_reg, (1 << idlest_bit), + _wait_idlest_generic(clk, &idlest_reg, (1 << idlest_bit), idlest_val, clk_hw_get_name(&clk->hw)); } else { ti_clk_ll_ops->cm_wait_module_ready(0, prcm_mod, idlest_reg_id, @@ -139,17 +140,17 @@ static void _omap2_module_wait_ready(struct clk_hw_omap *clk) * avoid this issue, and remove the casts. No return value. */ void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk, - void __iomem **other_reg, u8 *other_bit) + struct clk_omap_reg *other_reg, + u8 *other_bit) { - u32 r; + memcpy(other_reg, &clk->enable_reg, sizeof(*other_reg)); /* * Convert CM_ICLKEN* <-> CM_FCLKEN*. This conversion assumes * it's just a matter of XORing the bits. */ - r = ((__force u32)clk->enable_reg ^ (CM_FCLKEN ^ CM_ICLKEN)); + other_reg->offset ^= (CM_FCLKEN ^ CM_ICLKEN); - *other_reg = (__force void __iomem *)r; *other_bit = clk->enable_bit; } @@ -168,13 +169,14 @@ void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk, * CM_IDLEST2). This is not true for all modules. No return value. */ void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk, - void __iomem **idlest_reg, u8 *idlest_bit, + struct clk_omap_reg *idlest_reg, u8 *idlest_bit, u8 *idlest_val) { - u32 r; + memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg)); + + idlest_reg->offset &= ~0xf0; + idlest_reg->offset |= 0x20; - r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20); - *idlest_reg = (__force void __iomem *)r; *idlest_bit = clk->enable_bit; /* @@ -222,31 +224,19 @@ int omap2_dflt_clk_enable(struct clk_hw *hw) } } - if (IS_ERR(clk->enable_reg)) { - pr_err("%s: %s missing enable_reg\n", __func__, - clk_hw_get_name(hw)); - ret = -EINVAL; - goto err; - } - /* FIXME should not have INVERT_ENABLE bit here */ - v = ti_clk_ll_ops->clk_readl(clk->enable_reg); + v = ti_clk_ll_ops->clk_readl(&clk->enable_reg); if (clk->flags & INVERT_ENABLE) v &= ~(1 << clk->enable_bit); else v |= (1 << clk->enable_bit); - ti_clk_ll_ops->clk_writel(v, clk->enable_reg); - v = ti_clk_ll_ops->clk_readl(clk->enable_reg); /* OCP barrier */ + ti_clk_ll_ops->clk_writel(v, &clk->enable_reg); + v = ti_clk_ll_ops->clk_readl(&clk->enable_reg); /* OCP barrier */ if (clk->ops && clk->ops->find_idlest) _omap2_module_wait_ready(clk); return 0; - -err: - if (clkdm_control && clk->clkdm) - ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk); - return ret; } /** @@ -264,22 +254,13 @@ void omap2_dflt_clk_disable(struct clk_hw *hw) u32 v; clk = to_clk_hw_omap(hw); - if (IS_ERR(clk->enable_reg)) { - /* - * 'independent' here refers to a clock which is not - * controlled by its parent. - */ - pr_err("%s: independent clock %s has no enable_reg\n", - __func__, clk_hw_get_name(hw)); - return; - } - v = ti_clk_ll_ops->clk_readl(clk->enable_reg); + v = ti_clk_ll_ops->clk_readl(&clk->enable_reg); if (clk->flags & INVERT_ENABLE) v |= (1 << clk->enable_bit); else v &= ~(1 << clk->enable_bit); - ti_clk_ll_ops->clk_writel(v, clk->enable_reg); + ti_clk_ll_ops->clk_writel(v, &clk->enable_reg); /* No OCP barrier needed here since it is a disable operation */ if (!(ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL) && @@ -300,7 +281,7 @@ int omap2_dflt_clk_is_enabled(struct clk_hw *hw) struct clk_hw_omap *clk = to_clk_hw_omap(hw); u32 v; - v = ti_clk_ll_ops->clk_readl(clk->enable_reg); + v = ti_clk_ll_ops->clk_readl(&clk->enable_reg); if (clk->flags & INVERT_ENABLE) v ^= BIT(clk->enable_bit); diff --git a/drivers/clk/ti/clkt_dpll.c b/drivers/clk/ti/clkt_dpll.c index b919fdfe8256..ce98da2c10be 100644 --- a/drivers/clk/ti/clkt_dpll.c +++ b/drivers/clk/ti/clkt_dpll.c @@ -213,7 +213,7 @@ u8 omap2_init_dpll_parent(struct clk_hw *hw) if (!dd) return -EINVAL; - v = ti_clk_ll_ops->clk_readl(dd->control_reg); + v = ti_clk_ll_ops->clk_readl(&dd->control_reg); v &= dd->enable_mask; v >>= __ffs(dd->enable_mask); @@ -249,14 +249,14 @@ unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk) return 0; /* Return bypass rate if DPLL is bypassed */ - v = ti_clk_ll_ops->clk_readl(dd->control_reg); + v = ti_clk_ll_ops->clk_readl(&dd->control_reg); v &= dd->enable_mask; v >>= __ffs(dd->enable_mask); if (_omap2_dpll_is_in_bypass(v)) return clk_hw_get_rate(dd->clk_bypass); - v = ti_clk_ll_ops->clk_readl(dd->mult_div1_reg); + v = ti_clk_ll_ops->clk_readl(&dd->mult_div1_reg); dpll_mult = v & dd->mult_mask; dpll_mult >>= __ffs(dd->mult_mask); dpll_div = v & dd->div1_mask; diff --git a/drivers/clk/ti/clkt_iclk.c b/drivers/clk/ti/clkt_iclk.c index 38c36908cf88..60b583d7db33 100644 --- a/drivers/clk/ti/clkt_iclk.c +++ b/drivers/clk/ti/clkt_iclk.c @@ -31,28 +31,29 @@ void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk) { u32 v; - void __iomem *r; + struct clk_omap_reg r; - r = (__force void __iomem *) - ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN)); + memcpy(&r, &clk->enable_reg, sizeof(r)); + r.offset ^= (CM_AUTOIDLE ^ CM_ICLKEN); - v = ti_clk_ll_ops->clk_readl(r); + v = ti_clk_ll_ops->clk_readl(&r); v |= (1 << clk->enable_bit); - ti_clk_ll_ops->clk_writel(v, r); + ti_clk_ll_ops->clk_writel(v, &r); } /* XXX */ void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk) { u32 v; - void __iomem *r; + struct clk_omap_reg r; - r = (__force void __iomem *) - ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN)); + memcpy(&r, &clk->enable_reg, sizeof(r)); - v = ti_clk_ll_ops->clk_readl(r); + r.offset ^= (CM_AUTOIDLE ^ CM_ICLKEN); + + v = ti_clk_ll_ops->clk_readl(&r); v &= ~(1 << clk->enable_bit); - ti_clk_ll_ops->clk_writel(v, r); + ti_clk_ll_ops->clk_writel(v, &r); } /** @@ -68,14 +69,12 @@ void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk) * modules. No return value. */ static void omap2430_clk_i2chs_find_idlest(struct clk_hw_omap *clk, - void __iomem **idlest_reg, + struct clk_omap_reg *idlest_reg, u8 *idlest_bit, u8 *idlest_val) { - u32 r; - - r = ((__force u32)clk->enable_reg ^ (OMAP24XX_CM_FCLKEN2 ^ CM_IDLEST)); - *idlest_reg = (__force void __iomem *)r; + memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg)); + idlest_reg->offset ^= (OMAP24XX_CM_FCLKEN2 ^ CM_IDLEST); *idlest_bit = clk->enable_bit; *idlest_val = OMAP24XX_CM_IDLEST_VAL; } diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h index 437ea768f837..3f7b26540be8 100644 --- a/drivers/clk/ti/clock.h +++ b/drivers/clk/ti/clock.h @@ -18,7 +18,7 @@ struct clk_omap_divider { struct clk_hw hw; - void __iomem *reg; + struct clk_omap_reg reg; u8 shift; u8 width; u8 flags; @@ -29,7 +29,7 @@ struct clk_omap_divider { struct clk_omap_mux { struct clk_hw hw; - void __iomem *reg; + struct clk_omap_reg reg; u32 *table; u32 mask; u8 shift; @@ -228,7 +228,8 @@ void ti_clk_patch_legacy_clks(struct ti_clk **patch); struct clk *ti_clk_register_clk(struct ti_clk *setup); int ti_clk_register_legacy_clks(struct ti_clk_alias *clks); -void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index); +int ti_clk_get_reg_addr(struct device_node *node, int index, + struct clk_omap_reg *reg); void ti_dt_clocks_register(struct ti_dt_clk *oclks); int ti_clk_retry_init(struct device_node *node, struct clk_hw *hw, ti_of_clk_init_cb_t func); @@ -263,10 +264,10 @@ int omap2_dflt_clk_enable(struct clk_hw *hw); void omap2_dflt_clk_disable(struct clk_hw *hw); int omap2_dflt_clk_is_enabled(struct clk_hw *hw); void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk, - void __iomem **other_reg, + struct clk_omap_reg *other_reg, u8 *other_bit); void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk, - void __iomem **idlest_reg, + struct clk_omap_reg *idlest_reg, u8 *idlest_bit, u8 *idlest_val); void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk); diff --git a/drivers/clk/ti/clockdomain.c b/drivers/clk/ti/clockdomain.c index 704157d8c0b7..fbedc6a9fed0 100644 --- a/drivers/clk/ti/clockdomain.c +++ b/drivers/clk/ti/clockdomain.c @@ -52,10 +52,6 @@ int omap2_clkops_enable_clkdm(struct clk_hw *hw) return -EINVAL; } - if (unlikely(clk->enable_reg)) - pr_err("%s: %s: should use dflt_clk_enable ?!\n", __func__, - clk_hw_get_name(hw)); - if (ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL) { pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n", __func__, clk_hw_get_name(hw)); @@ -90,10 +86,6 @@ void omap2_clkops_disable_clkdm(struct clk_hw *hw) return; } - if (unlikely(clk->enable_reg)) - pr_err("%s: %s: should use dflt_clk_disable ?!\n", __func__, - clk_hw_get_name(hw)); - if (ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL) { pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n", __func__, clk_hw_get_name(hw)); diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c index 1cc0242d823f..d6dcb283b72b 100644 --- a/drivers/clk/ti/divider.c +++ b/drivers/clk/ti/divider.c @@ -100,7 +100,7 @@ static unsigned long ti_clk_divider_recalc_rate(struct clk_hw *hw, struct clk_omap_divider *divider = to_clk_omap_divider(hw); unsigned int div, val; - val = ti_clk_ll_ops->clk_readl(divider->reg) >> divider->shift; + val = ti_clk_ll_ops->clk_readl(÷r->reg) >> divider->shift; val &= div_mask(divider); div = _get_div(divider, val); @@ -257,11 +257,11 @@ static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, if (divider->flags & CLK_DIVIDER_HIWORD_MASK) { val = div_mask(divider) << (divider->shift + 16); } else { - val = ti_clk_ll_ops->clk_readl(divider->reg); + val = ti_clk_ll_ops->clk_readl(÷r->reg); val &= ~(div_mask(divider) << divider->shift); } val |= value << divider->shift; - ti_clk_ll_ops->clk_writel(val, divider->reg); + ti_clk_ll_ops->clk_writel(val, ÷r->reg); return 0; } @@ -274,7 +274,8 @@ const struct clk_ops ti_clk_divider_ops = { static struct clk *_register_divider(struct device *dev, const char *name, const char *parent_name, - unsigned long flags, void __iomem *reg, + unsigned long flags, + struct clk_omap_reg *reg, u8 shift, u8 width, u8 clk_divider_flags, const struct clk_div_table *table) { @@ -303,7 +304,7 @@ static struct clk *_register_divider(struct device *dev, const char *name, init.num_parents = (parent_name ? 1 : 0); /* struct clk_divider assignments */ - div->reg = reg; + memcpy(&div->reg, reg, sizeof(*reg)); div->shift = shift; div->width = width; div->flags = clk_divider_flags; @@ -561,14 +562,15 @@ static int _get_divider_width(struct device_node *node, } static int __init ti_clk_divider_populate(struct device_node *node, - void __iomem **reg, const struct clk_div_table **table, + struct clk_omap_reg *reg, const struct clk_div_table **table, u32 *flags, u8 *div_flags, u8 *width, u8 *shift) { u32 val; + int ret; - *reg = ti_clk_get_reg_addr(node, 0); - if (IS_ERR(*reg)) - return PTR_ERR(*reg); + ret = ti_clk_get_reg_addr(node, 0, reg); + if (ret) + return ret; if (!of_property_read_u32(node, "ti,bit-shift", &val)) *shift = val; @@ -607,7 +609,7 @@ static void __init of_ti_divider_clk_setup(struct device_node *node) { struct clk *clk; const char *parent_name; - void __iomem *reg; + struct clk_omap_reg reg; u8 clk_divider_flags = 0; u8 width = 0; u8 shift = 0; @@ -620,7 +622,7 @@ static void __init of_ti_divider_clk_setup(struct device_node *node) &clk_divider_flags, &width, &shift)) goto cleanup; - clk = _register_divider(NULL, node->name, parent_name, flags, reg, + clk = _register_divider(NULL, node->name, parent_name, flags, ®, shift, width, clk_divider_flags, table); if (!IS_ERR(clk)) { diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c index 778bc90955b9..96d84888c6c5 100644 --- a/drivers/clk/ti/dpll.c +++ b/drivers/clk/ti/dpll.c @@ -203,17 +203,10 @@ cleanup: } #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_ATAGS) -static void __iomem *_get_reg(u8 module, u16 offset) +void _get_reg(u8 module, u16 offset, struct clk_omap_reg *reg) { - u32 reg; - struct clk_omap_reg *reg_setup; - - reg_setup = (struct clk_omap_reg *)® - - reg_setup->index = module; - reg_setup->offset = offset; - - return (void __iomem *)reg; + reg->index = module; + reg->offset = offset; } struct clk *ti_clk_register_dpll(struct ti_clk *setup) @@ -255,10 +248,10 @@ struct clk *ti_clk_register_dpll(struct ti_clk *setup) init.num_parents = dpll->num_parents; init.parent_names = dpll->parents; - dd->control_reg = _get_reg(dpll->module, dpll->control_reg); - dd->idlest_reg = _get_reg(dpll->module, dpll->idlest_reg); - dd->mult_div1_reg = _get_reg(dpll->module, dpll->mult_div1_reg); - dd->autoidle_reg = _get_reg(dpll->module, dpll->autoidle_reg); + _get_reg(dpll->module, dpll->control_reg, &dd->control_reg); + _get_reg(dpll->module, dpll->idlest_reg, &dd->idlest_reg); + _get_reg(dpll->module, dpll->mult_div1_reg, &dd->mult_div1_reg); + _get_reg(dpll->module, dpll->autoidle_reg, &dd->autoidle_reg); dd->modes = dpll->modes; dd->div1_mask = dpll->div1_mask; @@ -344,12 +337,9 @@ static void _register_dpll_x2(struct device_node *node, ret = of_property_count_elems_of_size(node, "reg", 1); if (ret <= 0) { hw_ops = NULL; - } else { - clk_hw->clksel_reg = ti_clk_get_reg_addr(node, 0); - if (IS_ERR(clk_hw->clksel_reg)) { - kfree(clk_hw); - return; - } + } else if (ti_clk_get_reg_addr(node, 0, &clk_hw->clksel_reg)) { + kfree(clk_hw); + return; } } @@ -412,7 +402,8 @@ static void __init of_ti_dpll_setup(struct device_node *node, init->parent_names = parent_names; - dd->control_reg = ti_clk_get_reg_addr(node, 0); + if (ti_clk_get_reg_addr(node, 0, &dd->control_reg)) + goto cleanup; /* * Special case for OMAP2 DPLL, register order is different due to @@ -420,25 +411,22 @@ static void __init of_ti_dpll_setup(struct device_node *node, * missing idlest_mask. */ if (!dd->idlest_mask) { - dd->mult_div1_reg = ti_clk_get_reg_addr(node, 1); + if (ti_clk_get_reg_addr(node, 1, &dd->mult_div1_reg)) + goto cleanup; #ifdef CONFIG_ARCH_OMAP2 clk_hw->ops = &clkhwops_omap2xxx_dpll; omap2xxx_clkt_dpllcore_init(&clk_hw->hw); #endif } else { - dd->idlest_reg = ti_clk_get_reg_addr(node, 1); - if (IS_ERR(dd->idlest_reg)) + if (ti_clk_get_reg_addr(node, 1, &dd->idlest_reg)) goto cleanup; - dd->mult_div1_reg = ti_clk_get_reg_addr(node, 2); + if (ti_clk_get_reg_addr(node, 2, &dd->mult_div1_reg)) + goto cleanup; } - if (IS_ERR(dd->control_reg) || IS_ERR(dd->mult_div1_reg)) - goto cleanup; - if (dd->autoidle_mask) { - dd->autoidle_reg = ti_clk_get_reg_addr(node, 3); - if (IS_ERR(dd->autoidle_reg)) + if (ti_clk_get_reg_addr(node, 3, &dd->autoidle_reg)) goto cleanup; } diff --git a/drivers/clk/ti/dpll3xxx.c b/drivers/clk/ti/dpll3xxx.c index 4cdd28a25584..4534de2ef455 100644 --- a/drivers/clk/ti/dpll3xxx.c +++ b/drivers/clk/ti/dpll3xxx.c @@ -54,10 +54,10 @@ static void _omap3_dpll_write_clken(struct clk_hw_omap *clk, u8 clken_bits) dd = clk->dpll_data; - v = ti_clk_ll_ops->clk_readl(dd->control_reg); + v = ti_clk_ll_ops->clk_readl(&dd->control_reg); v &= ~dd->enable_mask; v |= clken_bits << __ffs(dd->enable_mask); - ti_clk_ll_ops->clk_writel(v, dd->control_reg); + ti_clk_ll_ops->clk_writel(v, &dd->control_reg); } /* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */ @@ -73,7 +73,7 @@ static int _omap3_wait_dpll_status(struct clk_hw_omap *clk, u8 state) state <<= __ffs(dd->idlest_mask); - while (((ti_clk_ll_ops->clk_readl(dd->idlest_reg) & dd->idlest_mask) + while (((ti_clk_ll_ops->clk_readl(&dd->idlest_reg) & dd->idlest_mask) != state) && i < MAX_DPLL_WAIT_TRIES) { i++; udelay(1); @@ -151,7 +151,7 @@ static int _omap3_noncore_dpll_lock(struct clk_hw_omap *clk) state <<= __ffs(dd->idlest_mask); /* Check if already locked */ - if ((ti_clk_ll_ops->clk_readl(dd->idlest_reg) & dd->idlest_mask) == + if ((ti_clk_ll_ops->clk_readl(&dd->idlest_reg) & dd->idlest_mask) == state) goto done; @@ -317,14 +317,14 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel) * only since freqsel field is no longer present on other devices. */ if (ti_clk_get_features()->flags & TI_CLK_DPLL_HAS_FREQSEL) { - v = ti_clk_ll_ops->clk_readl(dd->control_reg); + v = ti_clk_ll_ops->clk_readl(&dd->control_reg); v &= ~dd->freqsel_mask; v |= freqsel << __ffs(dd->freqsel_mask); - ti_clk_ll_ops->clk_writel(v, dd->control_reg); + ti_clk_ll_ops->clk_writel(v, &dd->control_reg); } /* Set DPLL multiplier, divider */ - v = ti_clk_ll_ops->clk_readl(dd->mult_div1_reg); + v = ti_clk_ll_ops->clk_readl(&dd->mult_div1_reg); /* Handle Duty Cycle Correction */ if (dd->dcc_mask) { @@ -370,11 +370,11 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel) } } - ti_clk_ll_ops->clk_writel(v, dd->mult_div1_reg); + ti_clk_ll_ops->clk_writel(v, &dd->mult_div1_reg); /* Set 4X multiplier and low-power mode */ if (dd->m4xen_mask || dd->lpmode_mask) { - v = ti_clk_ll_ops->clk_readl(dd->control_reg); + v = ti_clk_ll_ops->clk_readl(&dd->control_reg); if (dd->m4xen_mask) { if (dd->last_rounded_m4xen) @@ -390,7 +390,7 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel) v &= ~dd->lpmode_mask; } - ti_clk_ll_ops->clk_writel(v, dd->control_reg); + ti_clk_ll_ops->clk_writel(v, &dd->control_reg); } /* We let the clock framework set the other output dividers later */ @@ -652,10 +652,10 @@ static u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk) dd = clk->dpll_data; - if (!dd->autoidle_reg) + if (!dd->autoidle_mask) return -EINVAL; - v = ti_clk_ll_ops->clk_readl(dd->autoidle_reg); + v = ti_clk_ll_ops->clk_readl(&dd->autoidle_reg); v &= dd->autoidle_mask; v >>= __ffs(dd->autoidle_mask); @@ -681,7 +681,7 @@ static void omap3_dpll_allow_idle(struct clk_hw_omap *clk) dd = clk->dpll_data; - if (!dd->autoidle_reg) + if (!dd->autoidle_mask) return; /* @@ -689,10 +689,10 @@ static void omap3_dpll_allow_idle(struct clk_hw_omap *clk) * by writing 0x5 instead of 0x1. Add some mechanism to * optionally enter this mode. */ - v = ti_clk_ll_ops->clk_readl(dd->autoidle_reg); + v = ti_clk_ll_ops->clk_readl(&dd->autoidle_reg); v &= ~dd->autoidle_mask; v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask); - ti_clk_ll_ops->clk_writel(v, dd->autoidle_reg); + ti_clk_ll_ops->clk_writel(v, &dd->autoidle_reg); } /** @@ -711,13 +711,13 @@ static void omap3_dpll_deny_idle(struct clk_hw_omap *clk) dd = clk->dpll_data; - if (!dd->autoidle_reg) + if (!dd->autoidle_mask) return; - v = ti_clk_ll_ops->clk_readl(dd->autoidle_reg); + v = ti_clk_ll_ops->clk_readl(&dd->autoidle_reg); v &= ~dd->autoidle_mask; v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask); - ti_clk_ll_ops->clk_writel(v, dd->autoidle_reg); + ti_clk_ll_ops->clk_writel(v, &dd->autoidle_reg); } /* Clock control for DPLL outputs */ @@ -773,7 +773,7 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw, WARN_ON(!dd->enable_mask); - v = ti_clk_ll_ops->clk_readl(dd->control_reg) & dd->enable_mask; + v = ti_clk_ll_ops->clk_readl(&dd->control_reg) & dd->enable_mask; v >>= __ffs(dd->enable_mask); if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE)) rate = parent_rate; diff --git a/drivers/clk/ti/dpll44xx.c b/drivers/clk/ti/dpll44xx.c index 82c05b55a7be..d7a3f7ec8d77 100644 --- a/drivers/clk/ti/dpll44xx.c +++ b/drivers/clk/ti/dpll44xx.c @@ -42,17 +42,17 @@ static void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk) u32 v; u32 mask; - if (!clk || !clk->clksel_reg) + if (!clk) return; mask = clk->flags & CLOCK_CLKOUTX2 ? OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK : OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK; - v = ti_clk_ll_ops->clk_readl(clk->clksel_reg); + v = ti_clk_ll_ops->clk_readl(&clk->clksel_reg); /* Clear the bit to allow gatectrl */ v &= ~mask; - ti_clk_ll_ops->clk_writel(v, clk->clksel_reg); + ti_clk_ll_ops->clk_writel(v, &clk->clksel_reg); } static void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk) @@ -60,17 +60,17 @@ static void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk) u32 v; u32 mask; - if (!clk || !clk->clksel_reg) + if (!clk) return; mask = clk->flags & CLOCK_CLKOUTX2 ? OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK : OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK; - v = ti_clk_ll_ops->clk_readl(clk->clksel_reg); + v = ti_clk_ll_ops->clk_readl(&clk->clksel_reg); /* Set the bit to deny gatectrl */ v |= mask; - ti_clk_ll_ops->clk_writel(v, clk->clksel_reg); + ti_clk_ll_ops->clk_writel(v, &clk->clksel_reg); } const struct clk_hw_omap_ops clkhwops_omap4_dpllmx = { @@ -128,7 +128,7 @@ unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw, rate = omap2_get_dpll_rate(clk); /* regm4xen adds a multiplier of 4 to DPLL calculations */ - v = ti_clk_ll_ops->clk_readl(dd->control_reg); + v = ti_clk_ll_ops->clk_readl(&dd->control_reg); if (v & OMAP4430_DPLL_REGM4XEN_MASK) rate *= OMAP4430_REGM4XEN_MULT; diff --git a/drivers/clk/ti/gate.c b/drivers/clk/ti/gate.c index 77f0920e12f1..7151ec3a1b07 100644 --- a/drivers/clk/ti/gate.c +++ b/drivers/clk/ti/gate.c @@ -76,15 +76,15 @@ static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *hw) /* Restore the dividers */ if (!ret) { - orig_v = ti_clk_ll_ops->clk_readl(parent->reg); + orig_v = ti_clk_ll_ops->clk_readl(&parent->reg); dummy_v = orig_v; /* Write any other value different from the Read value */ dummy_v ^= (1 << parent->shift); - ti_clk_ll_ops->clk_writel(dummy_v, parent->reg); + ti_clk_ll_ops->clk_writel(dummy_v, &parent->reg); /* Write the original divider */ - ti_clk_ll_ops->clk_writel(orig_v, parent->reg); + ti_clk_ll_ops->clk_writel(orig_v, &parent->reg); } return ret; @@ -92,7 +92,7 @@ static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *hw) static struct clk *_register_gate(struct device *dev, const char *name, const char *parent_name, unsigned long flags, - void __iomem *reg, u8 bit_idx, + struct clk_omap_reg *reg, u8 bit_idx, u8 clk_gate_flags, const struct clk_ops *ops, const struct clk_hw_omap_ops *hw_ops) { @@ -109,7 +109,7 @@ static struct clk *_register_gate(struct device *dev, const char *name, init.name = name; init.ops = ops; - clk_hw->enable_reg = reg; + memcpy(&clk_hw->enable_reg, reg, sizeof(*reg)); clk_hw->enable_bit = bit_idx; clk_hw->ops = hw_ops; @@ -133,8 +133,7 @@ struct clk *ti_clk_register_gate(struct ti_clk *setup) { const struct clk_ops *ops = &omap_gate_clk_ops; const struct clk_hw_omap_ops *hw_ops = NULL; - u32 reg; - struct clk_omap_reg *reg_setup; + struct clk_omap_reg reg; u32 flags = 0; u8 clk_gate_flags = 0; struct ti_clk_gate *gate; @@ -144,8 +143,6 @@ struct clk *ti_clk_register_gate(struct ti_clk *setup) if (gate->flags & CLKF_INTERFACE) return ti_clk_register_interface(setup); - reg_setup = (struct clk_omap_reg *)® - if (gate->flags & CLKF_SET_RATE_PARENT) flags |= CLK_SET_RATE_PARENT; @@ -169,11 +166,12 @@ struct clk *ti_clk_register_gate(struct ti_clk *setup) if (gate->flags & CLKF_AM35XX) hw_ops = &clkhwops_am35xx_ipss_module_wait; - reg_setup->index = gate->module; - reg_setup->offset = gate->reg; + reg.index = gate->module; + reg.offset = gate->reg; + reg.ptr = NULL; return _register_gate(NULL, setup->name, gate->parent, flags, - (void __iomem *)reg, gate->bit_shift, + ®, gate->bit_shift, clk_gate_flags, ops, hw_ops); } @@ -214,15 +212,14 @@ static void __init _of_ti_gate_clk_setup(struct device_node *node, { struct clk *clk; const char *parent_name; - void __iomem *reg = NULL; + struct clk_omap_reg reg; u8 enable_bit = 0; u32 val; u32 flags = 0; u8 clk_gate_flags = 0; if (ops != &omap_gate_clkdm_clk_ops) { - reg = ti_clk_get_reg_addr(node, 0); - if (IS_ERR(reg)) + if (ti_clk_get_reg_addr(node, 0, ®)) return; if (!of_property_read_u32(node, "ti,bit-shift", &val)) @@ -242,7 +239,7 @@ static void __init _of_ti_gate_clk_setup(struct device_node *node, if (of_property_read_bool(node, "ti,set-bit-to-disable")) clk_gate_flags |= INVERT_ENABLE; - clk = _register_gate(NULL, node->name, parent_name, flags, reg, + clk = _register_gate(NULL, node->name, parent_name, flags, ®, enable_bit, clk_gate_flags, ops, hw_ops); if (!IS_ERR(clk)) @@ -260,8 +257,7 @@ _of_ti_composite_gate_clk_setup(struct device_node *node, if (!gate) return; - gate->enable_reg = ti_clk_get_reg_addr(node, 0); - if (IS_ERR(gate->enable_reg)) + if (ti_clk_get_reg_addr(node, 0, &gate->enable_reg)) goto cleanup; of_property_read_u32(node, "ti,bit-shift", &val); diff --git a/drivers/clk/ti/interface.c b/drivers/clk/ti/interface.c index 42d9fd4f5f6a..62cf50c1e1e3 100644 --- a/drivers/clk/ti/interface.c +++ b/drivers/clk/ti/interface.c @@ -34,7 +34,7 @@ static const struct clk_ops ti_interface_clk_ops = { static struct clk *_register_interface(struct device *dev, const char *name, const char *parent_name, - void __iomem *reg, u8 bit_idx, + struct clk_omap_reg *reg, u8 bit_idx, const struct clk_hw_omap_ops *ops) { struct clk_init_data init = { NULL }; @@ -47,7 +47,7 @@ static struct clk *_register_interface(struct device *dev, const char *name, clk_hw->hw.init = &init; clk_hw->ops = ops; - clk_hw->enable_reg = reg; + memcpy(&clk_hw->enable_reg, reg, sizeof(*reg)); clk_hw->enable_bit = bit_idx; init.name = name; @@ -71,14 +71,13 @@ static struct clk *_register_interface(struct device *dev, const char *name, struct clk *ti_clk_register_interface(struct ti_clk *setup) { const struct clk_hw_omap_ops *ops = &clkhwops_iclk_wait; - u32 reg; - struct clk_omap_reg *reg_setup; + struct clk_omap_reg reg; struct ti_clk_gate *gate; gate = setup->data; - reg_setup = (struct clk_omap_reg *)® - reg_setup->index = gate->module; - reg_setup->offset = gate->reg; + reg.index = gate->module; + reg.offset = gate->reg; + reg.ptr = NULL; if (gate->flags & CLKF_NO_WAIT) ops = &clkhwops_iclk; @@ -96,7 +95,7 @@ struct clk *ti_clk_register_interface(struct ti_clk *setup) ops = &clkhwops_am35xx_ipss_wait; return _register_interface(NULL, setup->name, gate->parent, - (void __iomem *)reg, gate->bit_shift, ops); + ®, gate->bit_shift, ops); } #endif @@ -105,12 +104,11 @@ static void __init _of_ti_interface_clk_setup(struct device_node *node, { struct clk *clk; const char *parent_name; - void __iomem *reg; + struct clk_omap_reg reg; u8 enable_bit = 0; u32 val; - reg = ti_clk_get_reg_addr(node, 0); - if (IS_ERR(reg)) + if (ti_clk_get_reg_addr(node, 0, ®)) return; if (!of_property_read_u32(node, "ti,bit-shift", &val)) @@ -122,7 +120,7 @@ static void __init _of_ti_interface_clk_setup(struct device_node *node, return; } - clk = _register_interface(NULL, node->name, parent_name, reg, + clk = _register_interface(NULL, node->name, parent_name, ®, enable_bit, ops); if (!IS_ERR(clk)) diff --git a/drivers/clk/ti/mux.c b/drivers/clk/ti/mux.c index daa2dee6bafe..18c267b38461 100644 --- a/drivers/clk/ti/mux.c +++ b/drivers/clk/ti/mux.c @@ -39,7 +39,7 @@ static u8 ti_clk_mux_get_parent(struct clk_hw *hw) * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so * val = 0x4 really means "bit 2, index starts at bit 0" */ - val = ti_clk_ll_ops->clk_readl(mux->reg) >> mux->shift; + val = ti_clk_ll_ops->clk_readl(&mux->reg) >> mux->shift; val &= mux->mask; if (mux->table) { @@ -81,11 +81,11 @@ static int ti_clk_mux_set_parent(struct clk_hw *hw, u8 index) if (mux->flags & CLK_MUX_HIWORD_MASK) { val = mux->mask << (mux->shift + 16); } else { - val = ti_clk_ll_ops->clk_readl(mux->reg); + val = ti_clk_ll_ops->clk_readl(&mux->reg); val &= ~(mux->mask << mux->shift); } val |= index << mux->shift; - ti_clk_ll_ops->clk_writel(val, mux->reg); + ti_clk_ll_ops->clk_writel(val, &mux->reg); return 0; } @@ -99,7 +99,7 @@ const struct clk_ops ti_clk_mux_ops = { static struct clk *_register_mux(struct device *dev, const char *name, const char * const *parent_names, u8 num_parents, unsigned long flags, - void __iomem *reg, u8 shift, u32 mask, + struct clk_omap_reg *reg, u8 shift, u32 mask, u8 clk_mux_flags, u32 *table) { struct clk_omap_mux *mux; @@ -120,7 +120,7 @@ static struct clk *_register_mux(struct device *dev, const char *name, init.num_parents = num_parents; /* struct clk_mux assignments */ - mux->reg = reg; + memcpy(&mux->reg, reg, sizeof(*reg)); mux->shift = shift; mux->mask = mask; mux->flags = clk_mux_flags; @@ -140,12 +140,9 @@ struct clk *ti_clk_register_mux(struct ti_clk *setup) struct ti_clk_mux *mux; u32 flags; u8 mux_flags = 0; - struct clk_omap_reg *reg_setup; - u32 reg; + struct clk_omap_reg reg; u32 mask; - reg_setup = (struct clk_omap_reg *)® - mux = setup->data; flags = CLK_SET_RATE_NO_REPARENT; @@ -154,8 +151,9 @@ struct clk *ti_clk_register_mux(struct ti_clk *setup) mask--; mask = (1 << fls(mask)) - 1; - reg_setup->index = mux->module; - reg_setup->offset = mux->reg; + reg.index = mux->module; + reg.offset = mux->reg; + reg.ptr = NULL; if (mux->flags & CLKF_INDEX_STARTS_AT_ONE) mux_flags |= CLK_MUX_INDEX_ONE; @@ -164,7 +162,7 @@ struct clk *ti_clk_register_mux(struct ti_clk *setup) flags |= CLK_SET_RATE_PARENT; return _register_mux(NULL, setup->name, mux->parents, mux->num_parents, - flags, (void __iomem *)reg, mux->bit_shift, mask, + flags, ®, mux->bit_shift, mask, mux_flags, NULL); } @@ -177,7 +175,7 @@ struct clk *ti_clk_register_mux(struct ti_clk *setup) static void of_mux_clk_setup(struct device_node *node) { struct clk *clk; - void __iomem *reg; + struct clk_omap_reg reg; unsigned int num_parents; const char **parent_names; u8 clk_mux_flags = 0; @@ -196,9 +194,7 @@ static void of_mux_clk_setup(struct device_node *node) of_clk_parent_fill(node, parent_names, num_parents); - reg = ti_clk_get_reg_addr(node, 0); - - if (IS_ERR(reg)) + if (ti_clk_get_reg_addr(node, 0, ®)) goto cleanup; of_property_read_u32(node, "ti,bit-shift", &shift); @@ -217,7 +213,7 @@ static void of_mux_clk_setup(struct device_node *node) mask = (1 << fls(mask)) - 1; clk = _register_mux(NULL, node->name, parent_names, num_parents, - flags, reg, shift, mask, clk_mux_flags, NULL); + flags, ®, shift, mask, clk_mux_flags, NULL); if (!IS_ERR(clk)) of_clk_add_provider(node, of_clk_src_simple_get, clk); @@ -230,7 +226,6 @@ CLK_OF_DECLARE(mux_clk, "ti,mux-clock", of_mux_clk_setup); struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup) { struct clk_omap_mux *mux; - struct clk_omap_reg *reg; int num_parents; if (!setup) @@ -240,12 +235,10 @@ struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup) if (!mux) return ERR_PTR(-ENOMEM); - reg = (struct clk_omap_reg *)&mux->reg; - mux->shift = setup->bit_shift; - reg->index = setup->module; - reg->offset = setup->reg; + mux->reg.index = setup->module; + mux->reg.offset = setup->reg; if (setup->flags & CLKF_INDEX_STARTS_AT_ONE) mux->flags |= CLK_MUX_INDEX_ONE; @@ -268,9 +261,7 @@ static void __init of_ti_composite_mux_clk_setup(struct device_node *node) if (!mux) return; - mux->reg = ti_clk_get_reg_addr(node, 0); - - if (IS_ERR(mux->reg)) + if (ti_clk_get_reg_addr(node, 0, &mux->reg)) goto cleanup; if (!of_property_read_u32(node, "ti,bit-shift", &val)) diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h index affdabd0b6a1..d18da839b810 100644 --- a/include/linux/clk/ti.h +++ b/include/linux/clk/ti.h @@ -18,6 +18,18 @@ #include #include +/** + * struct clk_omap_reg - OMAP register declaration + * @offset: offset from the master IP module base address + * @index: index of the master IP module + */ +struct clk_omap_reg { + void __iomem *ptr; + u16 offset; + u8 index; + u8 flags; +}; + /** * struct dpll_data - DPLL registers and integration data * @mult_div1_reg: register containing the DPLL M and N bitfields @@ -67,12 +79,12 @@ * can be placed into read-only space. */ struct dpll_data { - void __iomem *mult_div1_reg; + struct clk_omap_reg mult_div1_reg; u32 mult_mask; u32 div1_mask; struct clk_hw *clk_bypass; struct clk_hw *clk_ref; - void __iomem *control_reg; + struct clk_omap_reg control_reg; u32 enable_mask; unsigned long last_rounded_rate; u16 last_rounded_m; @@ -84,8 +96,8 @@ struct dpll_data { u16 max_divider; unsigned long max_rate; u8 modes; - void __iomem *autoidle_reg; - void __iomem *idlest_reg; + struct clk_omap_reg autoidle_reg; + struct clk_omap_reg idlest_reg; u32 autoidle_mask; u32 freqsel_mask; u32 idlest_mask; @@ -113,10 +125,10 @@ struct clk_hw_omap; */ struct clk_hw_omap_ops { void (*find_idlest)(struct clk_hw_omap *oclk, - void __iomem **idlest_reg, + struct clk_omap_reg *idlest_reg, u8 *idlest_bit, u8 *idlest_val); void (*find_companion)(struct clk_hw_omap *oclk, - void __iomem **other_reg, + struct clk_omap_reg *other_reg, u8 *other_bit); void (*allow_idle)(struct clk_hw_omap *oclk); void (*deny_idle)(struct clk_hw_omap *oclk); @@ -139,10 +151,10 @@ struct clk_hw_omap { struct list_head node; unsigned long fixed_rate; u8 fixed_div; - void __iomem *enable_reg; + struct clk_omap_reg enable_reg; u8 enable_bit; u8 flags; - void __iomem *clksel_reg; + struct clk_omap_reg clksel_reg; struct dpll_data *dpll_data; const char *clkdm_name; struct clockdomain *clkdm; @@ -195,16 +207,6 @@ enum { CLK_MAX_MEMMAPS }; -/** - * struct clk_omap_reg - OMAP register declaration - * @offset: offset from the master IP module base address - * @index: index of the master IP module - */ -struct clk_omap_reg { - u16 offset; - u16 index; -}; - /** * struct ti_clk_ll_ops - low-level ops for clocks * @clk_readl: pointer to register read function @@ -222,16 +224,16 @@ struct clk_omap_reg { * operations not provided directly by clock drivers. */ struct ti_clk_ll_ops { - u32 (*clk_readl)(void __iomem *reg); - void (*clk_writel)(u32 val, void __iomem *reg); + u32 (*clk_readl)(const struct clk_omap_reg *reg); + void (*clk_writel)(u32 val, const struct clk_omap_reg *reg); int (*clkdm_clk_enable)(struct clockdomain *clkdm, struct clk *clk); int (*clkdm_clk_disable)(struct clockdomain *clkdm, struct clk *clk); struct clockdomain * (*clkdm_lookup)(const char *name); int (*cm_wait_module_ready)(u8 part, s16 prcm_mod, u16 idlest_reg, u8 idlest_shift); - int (*cm_split_idlest_reg)(void __iomem *idlest_reg, s16 *prcm_inst, - u8 *idlest_reg_id); + int (*cm_split_idlest_reg)(struct clk_omap_reg *idlest_reg, + s16 *prcm_inst, u8 *idlest_reg_id); }; #define to_clk_hw_omap(_hw) container_of(_hw, struct clk_hw_omap, hw) -- cgit v1.2.3-59-g8ed1b From f16bd7ca045729e1104a9353dfd792ea98931b80 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 24 May 2016 23:07:46 +0200 Subject: mtd: nand: Kill the MTD_NAND_IDS Kconfig option MTD_NAND_IDS is selected by MTD_NAND, which makes it useless. Remove the Kconfig option and link nand_ids.o into the nand.o object file. Doing that also prevents creating an extra nand_ids.ko module when MTD_NAND is activated as a module. Since nand_ids.c is no longer compiled as a standalone module and the nand_manuf_ids/nand_flash_ids symbols are only used in nand_base.c, we can get rid of the MODULE_XXX() and EXPORT_SYMBOL() definitions. Signed-off-by: Boris Brezillon --- arch/cris/arch-v32/drivers/Kconfig | 1 - drivers/mtd/nand/Kconfig | 4 ---- drivers/mtd/nand/Makefile | 3 +-- drivers/mtd/nand/nand_ids.c | 7 ------- 4 files changed, 1 insertion(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig index 2735eb7671a5..b7cd6b9209a9 100644 --- a/arch/cris/arch-v32/drivers/Kconfig +++ b/arch/cris/arch-v32/drivers/Kconfig @@ -136,7 +136,6 @@ config ETRAX_NANDFLASH bool "NAND flash support" depends on ETRAX_ARCH_V32 select MTD_NAND - select MTD_NAND_IDS help This option enables MTD mapping of NAND flash devices. Needed to use NAND flash memories. If unsure, say Y. diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 6d4d5672d1d8..1ac7f321203e 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -13,7 +13,6 @@ config MTD_NAND_ECC_SMC menuconfig MTD_NAND tristate "NAND Device Support" depends on MTD - select MTD_NAND_IDS select MTD_NAND_ECC help This enables support for accessing all type of NAND flash @@ -109,9 +108,6 @@ config MTD_NAND_OMAP_BCH config MTD_NAND_OMAP_BCH_BUILD def_tristate MTD_NAND_OMAP2 && MTD_NAND_OMAP_BCH -config MTD_NAND_IDS - tristate - config MTD_NAND_RICOH tristate "Ricoh xD card reader" default n diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 19a66e404d5b..bfd5d12b9ade 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -5,7 +5,6 @@ obj-$(CONFIG_MTD_NAND) += nand.o obj-$(CONFIG_MTD_NAND_ECC) += nand_ecc.o obj-$(CONFIG_MTD_NAND_BCH) += nand_bch.o -obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o obj-$(CONFIG_MTD_SM_COMMON) += sm_common.o obj-$(CONFIG_MTD_NAND_CAFE) += cafe_nand.o @@ -61,4 +60,4 @@ obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand/ obj-$(CONFIG_MTD_NAND_QCOM) += qcom_nandc.o obj-$(CONFIG_MTD_NAND_MTK) += mtk_nand.o mtk_ecc.o -nand-objs := nand_base.o nand_bbt.o nand_timings.o +nand-objs := nand_base.o nand_bbt.o nand_timings.o nand_ids.o diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index 3f80cfcb5e37..bd267ade0742 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c @@ -188,10 +188,3 @@ struct nand_manufacturer nand_manuf_ids[] = { {NAND_MFR_WINBOND, "Winbond"}, {0x0, "Unknown"} }; - -EXPORT_SYMBOL(nand_manuf_ids); -EXPORT_SYMBOL(nand_flash_ids); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Thomas Gleixner "); -MODULE_DESCRIPTION("Nand device & manufacturer IDs"); -- cgit v1.2.3-59-g8ed1b From cf8178f78645148dc38b28263b9d3f604148e3a8 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 15 Mar 2017 17:10:10 +0000 Subject: x86/microcode/AMD: Remove redundant NULL check on mc mc is a pointer to the static u8 array amd_ucode_patch and therefore can never be null, so the check is redundant. Remove it. Detected by CoverityScan, CID#1372871 ("Logically Dead Code") Signed-off-by: Colin Ian King Cc: kernel-janitors@vger.kernel.org Cc: x86-ml Link: http://lkml.kernel.org/r/20170315171010.17536-1-colin.king@canonical.com Signed-off-by: Borislav Petkov Signed-off-by: Thomas Gleixner --- arch/x86/kernel/cpu/microcode/amd.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index 7889ae492af0..1d38e53c2d5c 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -352,8 +352,6 @@ void reload_ucode_amd(void) u32 rev, dummy; mc = (struct microcode_amd *)amd_ucode_patch; - if (!mc) - return; rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); -- cgit v1.2.3-59-g8ed1b From 06995804b5762f016c7a80503406da853a8f3785 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Tue, 22 Nov 2016 22:34:29 +0100 Subject: arm64: Use full path in KBUILD_IMAGE definition The KBUILD_IMAGE variable is used by the rpm and deb-pkg targets, which expect it to point to the image file in the build directory. The builddeb script has a workaround for architectures which only provide the basename, but let's provide a clean interface for packaging tools. Cc: Catalin Marinas Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Michal Marek Acked-by: Will Deacon Signed-off-by: Masahiro Yamada --- arch/arm64/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index b9a4a934ca05..adf977fd39f1 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -100,12 +100,12 @@ libs-y := arch/arm64/lib/ $(libs-y) core-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a # Default target when executing plain make -KBUILD_IMAGE := Image.gz +boot := arch/arm64/boot +KBUILD_IMAGE := $(boot)/Image.gz KBUILD_DTBS := dtbs -all: $(KBUILD_IMAGE) $(KBUILD_DTBS) +all: Image.gz $(KBUILD_DTBS) -boot := arch/arm64/boot Image: vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ -- cgit v1.2.3-59-g8ed1b From 152e6744ebfc8fa6cc9fff4ba36271f5f1ba2821 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Tue, 22 Nov 2016 22:34:30 +0100 Subject: arm: Use full path in KBUILD_IMAGE definition The KBUILD_IMAGE variable is used by the rpm and deb-pkg targets, which expect it to point to the image file in the build directory. The builddeb script has a workaround for architectures which only provide the basename, but let's provide a clean interface for packaging tools. Cc: Russell King Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Michal Marek Signed-off-by: Masahiro Yamada --- arch/arm/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/Makefile b/arch/arm/Makefile index ab30cc634d02..65f4e2a4eb94 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -297,10 +297,11 @@ drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/ libs-y := arch/arm/lib/ $(libs-y) # Default target when executing plain make +boot := arch/arm/boot ifeq ($(CONFIG_XIP_KERNEL),y) -KBUILD_IMAGE := xipImage +KBUILD_IMAGE := $(boot)/xipImage else -KBUILD_IMAGE := zImage +KBUILD_IMAGE := $(boot)/zImage endif # Build the DT binary blobs if we have OF configured @@ -308,9 +309,8 @@ ifeq ($(CONFIG_USE_OF),y) KBUILD_DTBS := dtbs endif -all: $(KBUILD_IMAGE) $(KBUILD_DTBS) +all: $(notdir $(KBUILD_IMAGE)) $(KBUILD_DTBS) -boot := arch/arm/boot archheaders: $(Q)$(MAKE) $(build)=arch/arm/tools uapi -- cgit v1.2.3-59-g8ed1b From 5e40f0fd234f36564881b03d28deaa69653ae9f2 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Tue, 22 Nov 2016 22:34:31 +0100 Subject: arc: Use full path in KBUILD_IMAGE definition The KBUILD_IMAGE variable is used by the rpm and deb-pkg targets, which expect it to point to the image file in the build directory. The builddeb script has a workaround for architectures which only provide the basename, but let's provide a clean interface for packaging tools. Cc: Vineet Gupta Cc: linux-snps-arc@lists.infradead.org Signed-off-by: Michal Marek Signed-off-by: Masahiro Yamada --- arch/arc/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arc/Makefile b/arch/arc/Makefile index 19cce226d1a8..44ef35d33956 100644 --- a/arch/arc/Makefile +++ b/arch/arc/Makefile @@ -123,9 +123,9 @@ libs-y += arch/arc/lib/ $(LIBGCC) boot := arch/arc/boot #default target for make without any arguments. -KBUILD_IMAGE := bootpImage +KBUILD_IMAGE := $(boot)/bootpImage -all: $(KBUILD_IMAGE) +all: bootpImage bootpImage: vmlinux boot_targets += uImage uImage.bin uImage.gz -- cgit v1.2.3-59-g8ed1b From e62c527efb07fa62a549cb03109a4d0265cedce2 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Tue, 22 Nov 2016 22:34:32 +0100 Subject: sh: Use full path in KBUILD_IMAGE definition The KBUILD_IMAGE variable is used by the rpm and deb-pkg targets, which expect it to point to the image file in the build directory. The builddeb script has a workaround for architectures which only provide the basename, but let's provide a clean interface for packaging tools. Cc: Yoshinori Sato Cc: Rich Felker Cc: linux-sh@vger.kernel.org Signed-off-by: Michal Marek Signed-off-by: Masahiro Yamada --- arch/sh/Makefile | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 336f33a419d9..280bbff12102 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -94,7 +94,8 @@ defaultimage-$(CONFIG_SH_7206_SOLUTION_ENGINE) := vmlinux defaultimage-$(CONFIG_SH_7619_SOLUTION_ENGINE) := vmlinux # Set some sensible Kbuild defaults -KBUILD_IMAGE := $(defaultimage-y) +boot := arch/sh/boot +KBUILD_IMAGE := $(boot)/$(defaultimage-y) # # Choosing incompatible machines durings configuration will result in @@ -186,8 +187,6 @@ cpuincdir-y += cpu-common # Must be last drivers-y += arch/sh/drivers/ drivers-$(CONFIG_OPROFILE) += arch/sh/oprofile/ -boot := arch/sh/boot - cflags-y += $(foreach d, $(cpuincdir-y), -Iarch/sh/include/$(d)) \ $(foreach d, $(machdir-y), -Iarch/sh/include/$(d)) @@ -211,7 +210,7 @@ BOOT_TARGETS = uImage uImage.bz2 uImage.gz uImage.lzma uImage.xz uImage.lzo \ romImage PHONY += $(BOOT_TARGETS) -all: $(KBUILD_IMAGE) +all: $(notdir $(KBUILD_IMAGE)) $(BOOT_TARGETS): vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ -- cgit v1.2.3-59-g8ed1b From 41f5b8db796fdea5d5265798add260e66d44276b Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Tue, 22 Nov 2016 22:34:33 +0100 Subject: unicore32: Use full path in KBUILD_IMAGE definition The KBUILD_IMAGE variable is used by the rpm and deb-pkg targets, which expect it to point to the image file in the build directory. The builddeb script has a workaround for architectures which only provide the basename, but let's provide a clean interface for packaging tools. Cc: Guan Xuetao Signed-off-by: Michal Marek Signed-off-by: Masahiro Yamada --- arch/unicore32/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/unicore32/Makefile b/arch/unicore32/Makefile index b6f5c4c1eaf9..98a5ca43ae87 100644 --- a/arch/unicore32/Makefile +++ b/arch/unicore32/Makefile @@ -43,9 +43,9 @@ boot := arch/unicore32/boot # Default defconfig and target when executing plain make KBUILD_DEFCONFIG := $(ARCH)_defconfig -KBUILD_IMAGE := zImage +KBUILD_IMAGE := $(boot)/zImage -all: $(KBUILD_IMAGE) +all: zImage zImage Image uImage: vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ -- cgit v1.2.3-59-g8ed1b From 7e2a9035c1dbc4632f1897a8fe580fc90f33c013 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Fri, 17 Mar 2017 18:18:38 +0100 Subject: clk: rockchip: rename RK1108 to RV1108 Rockchip finally named the SOC as RV1108, so change it. Signed-off-by: Andy Yan [include rename in rk1108.dtsi to prevent compile errors] Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk1108.dtsi | 2 +- drivers/clk/rockchip/Makefile | 2 +- drivers/clk/rockchip/clk-rk1108.c | 531 --------------------------------- drivers/clk/rockchip/clk-rv1108.c | 531 +++++++++++++++++++++++++++++++++ drivers/clk/rockchip/clk.h | 28 +- include/dt-bindings/clock/rk1108-cru.h | 269 ----------------- include/dt-bindings/clock/rv1108-cru.h | 269 +++++++++++++++++ 7 files changed, 816 insertions(+), 816 deletions(-) delete mode 100644 drivers/clk/rockchip/clk-rk1108.c create mode 100644 drivers/clk/rockchip/clk-rv1108.c delete mode 100644 include/dt-bindings/clock/rk1108-cru.h create mode 100644 include/dt-bindings/clock/rv1108-cru.h (limited to 'arch') diff --git a/arch/arm/boot/dts/rk1108.dtsi b/arch/arm/boot/dts/rk1108.dtsi index d6194bff7afe..4867342b88d4 100644 --- a/arch/arm/boot/dts/rk1108.dtsi +++ b/arch/arm/boot/dts/rk1108.dtsi @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include / { #address-cells = <1>; diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile index 141971488f40..26b220c988b2 100644 --- a/drivers/clk/rockchip/Makefile +++ b/drivers/clk/rockchip/Makefile @@ -12,7 +12,7 @@ obj-y += clk-muxgrf.o obj-y += clk-ddr.o obj-$(CONFIG_RESET_CONTROLLER) += softrst.o -obj-y += clk-rk1108.o +obj-y += clk-rv1108.o obj-y += clk-rk3036.o obj-y += clk-rk3188.o obj-y += clk-rk3228.o diff --git a/drivers/clk/rockchip/clk-rk1108.c b/drivers/clk/rockchip/clk-rk1108.c deleted file mode 100644 index 92750d798e5d..000000000000 --- a/drivers/clk/rockchip/clk-rk1108.c +++ /dev/null @@ -1,531 +0,0 @@ -/* - * Copyright (c) 2016 Rockchip Electronics Co. Ltd. - * Author: Shawn Lin - * Andy Yan - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include "clk.h" - -#define RK1108_GRF_SOC_STATUS0 0x480 - -enum rk1108_plls { - apll, dpll, gpll, -}; - -static struct rockchip_pll_rate_table rk1108_pll_rates[] = { - /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */ - RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0), - RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0), - RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0), - RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0), - RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0), - RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0), - RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0), - RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0), - RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0), - RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0), - RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0), - RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0), - RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0), - RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0), - RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0), - RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0), - RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0), - RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0), - RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0), - RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0), - RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0), - RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0), - RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0), - RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0), - RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0), - RK3036_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0), - RK3036_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0), - RK3036_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0), - RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0), - RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0), - RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0), - RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0), - RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0), - RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0), - RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0), - RK3036_PLL_RATE( 594000000, 2, 99, 2, 1, 1, 0), - RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0), - RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0), - RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0), - RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0), - RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0), - RK3036_PLL_RATE( 96000000, 1, 64, 4, 4, 1, 0), - { /* sentinel */ }, -}; - -#define RK1108_DIV_CORE_MASK 0xf -#define RK1108_DIV_CORE_SHIFT 4 - -#define RK1108_CLKSEL0(_core_peri_div) \ - { \ - .reg = RK1108_CLKSEL_CON(1), \ - .val = HIWORD_UPDATE(_core_peri_div, RK1108_DIV_CORE_MASK,\ - RK1108_DIV_CORE_SHIFT) \ - } - -#define RK1108_CPUCLK_RATE(_prate, _core_peri_div) \ - { \ - .prate = _prate, \ - .divs = { \ - RK1108_CLKSEL0(_core_peri_div), \ - }, \ - } - -static struct rockchip_cpuclk_rate_table rk1108_cpuclk_rates[] __initdata = { - RK1108_CPUCLK_RATE(816000000, 4), - RK1108_CPUCLK_RATE(600000000, 4), - RK1108_CPUCLK_RATE(312000000, 4), -}; - -static const struct rockchip_cpuclk_reg_data rk1108_cpuclk_data = { - .core_reg = RK1108_CLKSEL_CON(0), - .div_core_shift = 0, - .div_core_mask = 0x1f, - .mux_core_alt = 1, - .mux_core_main = 0, - .mux_core_shift = 8, - .mux_core_mask = 0x1, -}; - -PNAME(mux_pll_p) = { "xin24m", "xin24m"}; -PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr", "apll_ddr" }; -PNAME(mux_armclk_p) = { "apll_core", "gpll_core", "dpll_core" }; -PNAME(mux_usb480m_pre_p) = { "usbphy", "xin24m" }; -PNAME(mux_hdmiphy_phy_p) = { "hdmiphy", "xin24m" }; -PNAME(mux_dclk_hdmiphy_pre_p) = { "dclk_hdmiphy_src_gpll", "dclk_hdmiphy_src_dpll" }; -PNAME(mux_pll_src_4plls_p) = { "dpll", "hdmiphy", "gpll", "usb480m" }; -PNAME(mux_pll_src_3plls_p) = { "apll", "gpll", "dpll" }; -PNAME(mux_pll_src_2plls_p) = { "dpll", "gpll" }; -PNAME(mux_pll_src_apll_gpll_p) = { "apll", "gpll" }; -PNAME(mux_aclk_peri_src_p) = { "aclk_peri_src_dpll", "aclk_peri_src_gpll" }; -PNAME(mux_aclk_bus_src_p) = { "aclk_bus_src_gpll", "aclk_bus_src_apll", "aclk_bus_src_dpll" }; -PNAME(mux_mmc_src_p) = { "dpll", "gpll", "xin24m", "usb480m" }; -PNAME(mux_pll_src_dpll_gpll_usb480m_p) = { "dpll", "gpll", "usb480m" }; -PNAME(mux_uart0_p) = { "uart0_src", "uart0_frac", "xin24m" }; -PNAME(mux_uart1_p) = { "uart1_src", "uart1_frac", "xin24m" }; -PNAME(mux_uart2_p) = { "uart2_src", "uart2_frac", "xin24m" }; -PNAME(mux_sclk_macphy_p) = { "sclk_macphy_pre", "ext_gmac" }; -PNAME(mux_i2s0_pre_p) = { "i2s0_src", "i2s0_frac", "ext_i2s", "xin12m" }; -PNAME(mux_i2s_out_p) = { "i2s0_pre", "xin12m" }; -PNAME(mux_i2s1_p) = { "i2s1_src", "i2s1_frac", "xin12m" }; -PNAME(mux_i2s2_p) = { "i2s2_src", "i2s2_frac", "xin12m" }; - -static struct rockchip_pll_clock rk1108_pll_clks[] __initdata = { - [apll] = PLL(pll_rk3399, PLL_APLL, "apll", mux_pll_p, 0, RK1108_PLL_CON(0), - RK1108_PLL_CON(3), 8, 31, 0, rk1108_pll_rates), - [dpll] = PLL(pll_rk3399, PLL_DPLL, "dpll", mux_pll_p, 0, RK1108_PLL_CON(8), - RK1108_PLL_CON(11), 8, 31, 0, NULL), - [gpll] = PLL(pll_rk3399, PLL_GPLL, "gpll", mux_pll_p, 0, RK1108_PLL_CON(16), - RK1108_PLL_CON(19), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk1108_pll_rates), -}; - -#define MFLAGS CLK_MUX_HIWORD_MASK -#define DFLAGS CLK_DIVIDER_HIWORD_MASK -#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE) -#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK - -static struct rockchip_clk_branch rk1108_uart0_fracmux __initdata = - MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(13), 8, 2, MFLAGS); - -static struct rockchip_clk_branch rk1108_uart1_fracmux __initdata = - MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(14), 8, 2, MFLAGS); - -static struct rockchip_clk_branch rk1108_uart2_fracmux __initdata = - MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(15), 8, 2, MFLAGS); - -static struct rockchip_clk_branch rk1108_i2s0_fracmux __initdata = - MUX(0, "i2s0_pre", mux_i2s0_pre_p, CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(5), 12, 2, MFLAGS); - -static struct rockchip_clk_branch rk1108_i2s1_fracmux __initdata = - MUX(0, "i2s1_pre", mux_i2s1_p, CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(6), 12, 2, MFLAGS); - -static struct rockchip_clk_branch rk1108_i2s2_fracmux __initdata = - MUX(0, "i2s2_pre", mux_i2s2_p, CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(7), 12, 2, MFLAGS); - -static struct rockchip_clk_branch rk1108_clk_branches[] __initdata = { - MUX(0, "hdmi_phy", mux_hdmiphy_phy_p, CLK_SET_RATE_PARENT, - RK1108_MISC_CON, 13, 2, MFLAGS), - MUX(0, "usb480m", mux_usb480m_pre_p, CLK_SET_RATE_PARENT, - RK1108_MISC_CON, 15, 2, MFLAGS), - /* - * Clock-Architecture Diagram 2 - */ - - /* PD_CORE */ - GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(0), 1, GFLAGS), - GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(0), 0, GFLAGS), - GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(0), 2, GFLAGS), - COMPOSITE_NOMUX(0, "pclken_dbg", "armclk", CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(1), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, - RK1108_CLKGATE_CON(0), 5, GFLAGS), - COMPOSITE_NOMUX(ACLK_ENMCORE, "aclkenm_core", "armclk", CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, - RK1108_CLKGATE_CON(0), 4, GFLAGS), - GATE(ACLK_CORE, "aclk_core", "aclkenm_core", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(11), 0, GFLAGS), - GATE(0, "pclk_dbg", "pclken_dbg", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(11), 1, GFLAGS), - - /* PD_RKVENC */ - - /* PD_RKVDEC */ - - /* PD_PMU_wrapper */ - COMPOSITE_NOMUX(0, "pmu_24m_ena", "gpll", CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(38), 0, 5, DFLAGS, - RK1108_CLKGATE_CON(8), 12, GFLAGS), - GATE(0, "pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(10), 0, GFLAGS), - GATE(0, "intmem1", "pmu_24m_ena", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(10), 1, GFLAGS), - GATE(0, "gpio0_pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(10), 2, GFLAGS), - GATE(0, "pmugrf", "pmu_24m_ena", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(10), 3, GFLAGS), - GATE(0, "pmu_noc", "pmu_24m_ena", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(10), 4, GFLAGS), - GATE(0, "i2c0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(10), 5, GFLAGS), - GATE(0, "pwm0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(10), 6, GFLAGS), - COMPOSITE(0, "pwm0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(12), 7, 1, MFLAGS, 0, 7, DFLAGS, - RK1108_CLKGATE_CON(8), 15, GFLAGS), - COMPOSITE(0, "i2c0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(19), 7, 1, MFLAGS, 0, 7, DFLAGS, - RK1108_CLKGATE_CON(8), 14, GFLAGS), - GATE(0, "pvtm_pmu", "xin24m", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(8), 13, GFLAGS), - - /* - * Clock-Architecture Diagram 4 - */ - COMPOSITE(0, "aclk_vio0_2wrap_occ", mux_pll_src_4plls_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS, - RK1108_CLKGATE_CON(6), 0, GFLAGS), - GATE(0, "aclk_vio0_pre", "aclk_vio0_2wrap_occ", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(17), 0, GFLAGS), - COMPOSITE_NOMUX(0, "hclk_vio_pre", "aclk_vio0_pre", 0, - RK1108_CLKSEL_CON(29), 0, 5, DFLAGS, - RK1108_CLKGATE_CON(7), 2, GFLAGS), - COMPOSITE_NOMUX(0, "pclk_vio_pre", "aclk_vio0_pre", 0, - RK1108_CLKSEL_CON(29), 8, 5, DFLAGS, - RK1108_CLKGATE_CON(7), 3, GFLAGS), - - INVERTER(0, "pclk_vip", "ext_vip", - RK1108_CLKSEL_CON(31), 8, IFLAGS), - GATE(0, "pclk_isp_pre", "pclk_vip", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(7), 6, GFLAGS), - GATE(0, "pclk_isp", "pclk_isp_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(18), 10, GFLAGS), - GATE(0, "dclk_hdmiphy_src_gpll", "gpll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(6), 5, GFLAGS), - GATE(0, "dclk_hdmiphy_src_dpll", "dpll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(6), 4, GFLAGS), - COMPOSITE_NOGATE(0, "dclk_hdmiphy", mux_dclk_hdmiphy_pre_p, 0, - RK1108_CLKSEL_CON(32), 6, 2, MFLAGS, 8, 6, DFLAGS), - - /* - * Clock-Architecture Diagram 5 - */ - - FACTOR(0, "xin12m", "xin24m", 0, 1, 2), - - COMPOSITE(0, "i2s0_src", mux_pll_src_2plls_p, 0, - RK1108_CLKSEL_CON(5), 8, 1, MFLAGS, 0, 7, DFLAGS, - RK1108_CLKGATE_CON(2), 0, GFLAGS), - COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(8), 0, - RK1108_CLKGATE_CON(2), 1, GFLAGS, - &rk1108_i2s0_fracmux), - GATE(SCLK_I2S0, "sclk_i2s0", "i2s0_pre", CLK_SET_RATE_PARENT, - RK1108_CLKGATE_CON(2), 2, GFLAGS), - COMPOSITE_NODIV(0, "i2s_out", mux_i2s_out_p, 0, - RK1108_CLKSEL_CON(5), 15, 1, MFLAGS, - RK1108_CLKGATE_CON(2), 3, GFLAGS), - - COMPOSITE(0, "i2s1_src", mux_pll_src_2plls_p, 0, - RK1108_CLKSEL_CON(6), 8, 1, MFLAGS, 0, 7, DFLAGS, - RK1108_CLKGATE_CON(2), 4, GFLAGS), - COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT, - RK2928_CLKSEL_CON(9), 0, - RK2928_CLKGATE_CON(2), 5, GFLAGS, - &rk1108_i2s1_fracmux), - GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", CLK_SET_RATE_PARENT, - RK1108_CLKGATE_CON(2), 6, GFLAGS), - - COMPOSITE(0, "i2s2_src", mux_pll_src_2plls_p, 0, - RK1108_CLKSEL_CON(7), 8, 1, MFLAGS, 0, 7, DFLAGS, - RK1108_CLKGATE_CON(3), 8, GFLAGS), - COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(10), 0, - RK1108_CLKGATE_CON(2), 9, GFLAGS, - &rk1108_i2s2_fracmux), - GATE(SCLK_I2S2, "sclk_i2s2", "i2s2_pre", CLK_SET_RATE_PARENT, - RK1108_CLKGATE_CON(2), 10, GFLAGS), - - /* PD_BUS */ - GATE(0, "aclk_bus_src_gpll", "gpll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(1), 0, GFLAGS), - GATE(0, "aclk_bus_src_apll", "apll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(1), 1, GFLAGS), - GATE(0, "aclk_bus_src_dpll", "dpll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(1), 2, GFLAGS), - COMPOSITE_NOGATE(ACLK_PRE, "aclk_bus_pre", mux_aclk_bus_src_p, 0, - RK1108_CLKSEL_CON(2), 8, 2, MFLAGS, 0, 5, DFLAGS), - COMPOSITE_NOMUX(0, "hclk_bus_pre", "aclk_bus_2wrap_occ", 0, - RK1108_CLKSEL_CON(3), 0, 5, DFLAGS, - RK1108_CLKGATE_CON(1), 4, GFLAGS), - COMPOSITE_NOMUX(0, "pclken_bus", "aclk_bus_2wrap_occ", 0, - RK1108_CLKSEL_CON(3), 8, 5, DFLAGS, - RK1108_CLKGATE_CON(1), 5, GFLAGS), - GATE(0, "pclk_bus_pre", "pclken_bus", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(1), 6, GFLAGS), - GATE(0, "pclk_top_pre", "pclken_bus", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(1), 7, GFLAGS), - GATE(0, "pclk_ddr_pre", "pclken_bus", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(1), 8, GFLAGS), - GATE(0, "clk_timer0", "mux_pll_p", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(1), 9, GFLAGS), - GATE(0, "clk_timer1", "mux_pll_p", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(1), 10, GFLAGS), - GATE(0, "pclk_timer", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 4, GFLAGS), - - COMPOSITE(0, "uart0_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(13), 12, 2, MFLAGS, 0, 7, DFLAGS, - RK1108_CLKGATE_CON(3), 1, GFLAGS), - COMPOSITE(0, "uart1_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(14), 12, 2, MFLAGS, 0, 7, DFLAGS, - RK1108_CLKGATE_CON(3), 3, GFLAGS), - COMPOSITE(0, "uart21_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(15), 12, 2, MFLAGS, 0, 7, DFLAGS, - RK1108_CLKGATE_CON(3), 5, GFLAGS), - - COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(16), 0, - RK1108_CLKGATE_CON(3), 2, GFLAGS, - &rk1108_uart0_fracmux), - COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(17), 0, - RK1108_CLKGATE_CON(3), 4, GFLAGS, - &rk1108_uart1_fracmux), - COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(18), 0, - RK1108_CLKGATE_CON(3), 6, GFLAGS, - &rk1108_uart2_fracmux), - GATE(PCLK_UART0, "pclk_uart0", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 10, GFLAGS), - GATE(PCLK_UART1, "pclk_uart1", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 11, GFLAGS), - GATE(PCLK_UART2, "pclk_uart2", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 12, GFLAGS), - - COMPOSITE(0, "clk_i2c1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(19), 15, 2, MFLAGS, 8, 7, DFLAGS, - RK1108_CLKGATE_CON(3), 7, GFLAGS), - COMPOSITE(0, "clk_i2c2", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(20), 7, 2, MFLAGS, 0, 7, DFLAGS, - RK1108_CLKGATE_CON(3), 8, GFLAGS), - COMPOSITE(0, "clk_i2c3", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(20), 15, 2, MFLAGS, 8, 7, DFLAGS, - RK1108_CLKGATE_CON(3), 9, GFLAGS), - GATE(0, "pclk_i2c1", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 0, GFLAGS), - GATE(0, "pclk_i2c2", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 1, GFLAGS), - GATE(0, "pclk_i2c3", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 2, GFLAGS), - COMPOSITE(0, "clk_pwm1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(12), 15, 2, MFLAGS, 8, 7, DFLAGS, - RK1108_CLKGATE_CON(3), 10, GFLAGS), - GATE(0, "pclk_pwm1", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 6, GFLAGS), - GATE(0, "pclk_wdt", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 3, GFLAGS), - GATE(0, "pclk_gpio1", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 7, GFLAGS), - GATE(0, "pclk_gpio2", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 8, GFLAGS), - GATE(0, "pclk_gpio3", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 9, GFLAGS), - - GATE(0, "pclk_grf", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(14), 0, GFLAGS), - - GATE(ACLK_DMAC, "aclk_dmac", "aclk_bus_pre", 0, - RK1108_CLKGATE_CON(12), 2, GFLAGS), - GATE(0, "hclk_rom", "hclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(12), 3, GFLAGS), - GATE(0, "aclk_intmem", "aclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(12), 1, GFLAGS), - - /* PD_DDR */ - GATE(0, "apll_ddr", "apll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(0), 8, GFLAGS), - GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(0), 9, GFLAGS), - GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(0), 10, GFLAGS), - COMPOSITE(0, "ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(4), 8, 2, MFLAGS, 0, 3, - DFLAGS | CLK_DIVIDER_POWER_OF_TWO, - RK1108_CLKGATE_CON(10), 9, GFLAGS), - GATE(0, "ddrupctl", "ddrphy_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(12), 4, GFLAGS), - GATE(0, "ddrc", "ddrphy", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(12), 5, GFLAGS), - GATE(0, "ddrmon", "ddrphy_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(12), 6, GFLAGS), - GATE(0, "timer_clk", "xin24m", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(0), 11, GFLAGS), - - /* - * Clock-Architecture Diagram 6 - */ - - /* PD_PERI */ - COMPOSITE_NOMUX(0, "pclk_periph_pre", "gpll", 0, - RK1108_CLKSEL_CON(23), 10, 5, DFLAGS, - RK1108_CLKGATE_CON(4), 5, GFLAGS), - GATE(0, "pclk_periph", "pclk_periph_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(15), 13, GFLAGS), - COMPOSITE_NOMUX(0, "hclk_periph_pre", "gpll", 0, - RK1108_CLKSEL_CON(23), 5, 5, DFLAGS, - RK1108_CLKGATE_CON(4), 4, GFLAGS), - GATE(0, "hclk_periph", "hclk_periph_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(15), 12, GFLAGS), - - GATE(0, "aclk_peri_src_dpll", "dpll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(4), 1, GFLAGS), - GATE(0, "aclk_peri_src_gpll", "gpll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(4), 2, GFLAGS), - COMPOSITE(0, "aclk_periph", mux_aclk_peri_src_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(23), 15, 2, MFLAGS, 0, 5, DFLAGS, - RK1108_CLKGATE_CON(15), 11, GFLAGS), - - COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0, - RK1108_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 8, DFLAGS, - RK1108_CLKGATE_CON(5), 0, GFLAGS), - - COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0, - RK1108_CLKSEL_CON(25), 10, 2, MFLAGS, - RK1108_CLKGATE_CON(5), 2, GFLAGS), - DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0, - RK1108_CLKSEL_CON(26), 0, 8, DFLAGS), - - COMPOSITE_NODIV(0, "sclk_emmc_src", mux_mmc_src_p, 0, - RK1108_CLKSEL_CON(25), 12, 2, MFLAGS, - RK1108_CLKGATE_CON(5), 1, GFLAGS), - DIV(SCLK_EMMC, "sclk_emmc", "sclk_emmc_src", 0, - RK2928_CLKSEL_CON(26), 8, 8, DFLAGS), - GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 0, GFLAGS), - GATE(HCLK_SDIO, "hclk_sdio", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 1, GFLAGS), - GATE(HCLK_EMMC, "hclk_emmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 2, GFLAGS), - - COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_2plls_p, 0, - RK1108_CLKSEL_CON(27), 14, 2, MFLAGS, 8, 5, DFLAGS, - RK1108_CLKGATE_CON(5), 3, GFLAGS), - GATE(HCLK_NANDC, "hclk_nandc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 3, GFLAGS), - - COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_2plls_p, 0, - RK1108_CLKSEL_CON(27), 7, 2, MFLAGS, 0, 7, DFLAGS, - RK1108_CLKGATE_CON(5), 4, GFLAGS), - GATE(HCLK_SFC, "hclk_sfc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 10, GFLAGS), - - COMPOSITE(0, "sclk_macphy_pre", mux_pll_src_apll_gpll_p, 0, - RK1108_CLKSEL_CON(24), 12, 2, MFLAGS, 0, 5, DFLAGS, - RK1108_CLKGATE_CON(4), 10, GFLAGS), - MUX(0, "sclk_macphy", mux_sclk_macphy_p, CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(24), 8, 2, MFLAGS), - GATE(0, "sclk_macphy_rx", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 8, GFLAGS), - GATE(0, "sclk_mac_ref", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 6, GFLAGS), - GATE(0, "sclk_mac_refout", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 7, GFLAGS), - - MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RK1108_SDMMC_CON0, 1), - MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK1108_SDMMC_CON1, 1), - - MMC(SCLK_SDIO_DRV, "sdio_drv", "sclk_sdio", RK1108_SDIO_CON0, 1), - MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK1108_SDIO_CON1, 1), - - MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RK1108_EMMC_CON0, 1), - MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK1108_EMMC_CON1, 1), -}; - -static const char *const rk1108_critical_clocks[] __initconst = { - "aclk_core", - "aclk_bus_src_gpll", - "aclk_periph", - "hclk_periph", - "pclk_periph", -}; - -static void __init rk1108_clk_init(struct device_node *np) -{ - struct rockchip_clk_provider *ctx; - void __iomem *reg_base; - - reg_base = of_iomap(np, 0); - if (!reg_base) { - pr_err("%s: could not map cru region\n", __func__); - return; - } - - ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); - if (IS_ERR(ctx)) { - pr_err("%s: rockchip clk init failed\n", __func__); - iounmap(reg_base); - return; - } - - rockchip_clk_register_plls(ctx, rk1108_pll_clks, - ARRAY_SIZE(rk1108_pll_clks), - RK1108_GRF_SOC_STATUS0); - rockchip_clk_register_branches(ctx, rk1108_clk_branches, - ARRAY_SIZE(rk1108_clk_branches)); - rockchip_clk_protect_critical(rk1108_critical_clocks, - ARRAY_SIZE(rk1108_critical_clocks)); - - rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", - mux_armclk_p, ARRAY_SIZE(mux_armclk_p), - &rk1108_cpuclk_data, rk1108_cpuclk_rates, - ARRAY_SIZE(rk1108_cpuclk_rates)); - - rockchip_register_softrst(np, 13, reg_base + RK1108_SOFTRST_CON(0), - ROCKCHIP_SOFTRST_HIWORD_MASK); - - rockchip_register_restart_notifier(ctx, RK1108_GLB_SRST_FST, NULL); - - rockchip_clk_of_add_provider(np, ctx); -} -CLK_OF_DECLARE(rk1108_cru, "rockchip,rk1108-cru", rk1108_clk_init); diff --git a/drivers/clk/rockchip/clk-rv1108.c b/drivers/clk/rockchip/clk-rv1108.c new file mode 100644 index 000000000000..7c05ab366348 --- /dev/null +++ b/drivers/clk/rockchip/clk-rv1108.c @@ -0,0 +1,531 @@ +/* + * Copyright (c) 2016 Rockchip Electronics Co. Ltd. + * Author: Shawn Lin + * Andy Yan + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include "clk.h" + +#define RV1108_GRF_SOC_STATUS0 0x480 + +enum rv1108_plls { + apll, dpll, gpll, +}; + +static struct rockchip_pll_rate_table rv1108_pll_rates[] = { + /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */ + RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0), + RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0), + RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0), + RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0), + RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0), + RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0), + RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0), + RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0), + RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0), + RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0), + RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0), + RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0), + RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0), + RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0), + RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0), + RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0), + RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0), + RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0), + RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0), + RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0), + RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0), + RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0), + RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0), + RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0), + RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0), + RK3036_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0), + RK3036_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0), + RK3036_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0), + RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0), + RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0), + RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0), + RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0), + RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0), + RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0), + RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0), + RK3036_PLL_RATE( 594000000, 2, 99, 2, 1, 1, 0), + RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0), + RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0), + RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0), + RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0), + RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0), + RK3036_PLL_RATE( 96000000, 1, 64, 4, 4, 1, 0), + { /* sentinel */ }, +}; + +#define RV1108_DIV_CORE_MASK 0xf +#define RV1108_DIV_CORE_SHIFT 4 + +#define RV1108_CLKSEL0(_core_peri_div) \ + { \ + .reg = RV1108_CLKSEL_CON(1), \ + .val = HIWORD_UPDATE(_core_peri_div, RV1108_DIV_CORE_MASK,\ + RV1108_DIV_CORE_SHIFT) \ + } + +#define RV1108_CPUCLK_RATE(_prate, _core_peri_div) \ + { \ + .prate = _prate, \ + .divs = { \ + RV1108_CLKSEL0(_core_peri_div), \ + }, \ + } + +static struct rockchip_cpuclk_rate_table rv1108_cpuclk_rates[] __initdata = { + RV1108_CPUCLK_RATE(816000000, 4), + RV1108_CPUCLK_RATE(600000000, 4), + RV1108_CPUCLK_RATE(312000000, 4), +}; + +static const struct rockchip_cpuclk_reg_data rv1108_cpuclk_data = { + .core_reg = RV1108_CLKSEL_CON(0), + .div_core_shift = 0, + .div_core_mask = 0x1f, + .mux_core_alt = 1, + .mux_core_main = 0, + .mux_core_shift = 8, + .mux_core_mask = 0x1, +}; + +PNAME(mux_pll_p) = { "xin24m", "xin24m"}; +PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr", "apll_ddr" }; +PNAME(mux_armclk_p) = { "apll_core", "gpll_core", "dpll_core" }; +PNAME(mux_usb480m_pre_p) = { "usbphy", "xin24m" }; +PNAME(mux_hdmiphy_phy_p) = { "hdmiphy", "xin24m" }; +PNAME(mux_dclk_hdmiphy_pre_p) = { "dclk_hdmiphy_src_gpll", "dclk_hdmiphy_src_dpll" }; +PNAME(mux_pll_src_4plls_p) = { "dpll", "hdmiphy", "gpll", "usb480m" }; +PNAME(mux_pll_src_3plls_p) = { "apll", "gpll", "dpll" }; +PNAME(mux_pll_src_2plls_p) = { "dpll", "gpll" }; +PNAME(mux_pll_src_apll_gpll_p) = { "apll", "gpll" }; +PNAME(mux_aclk_peri_src_p) = { "aclk_peri_src_dpll", "aclk_peri_src_gpll" }; +PNAME(mux_aclk_bus_src_p) = { "aclk_bus_src_gpll", "aclk_bus_src_apll", "aclk_bus_src_dpll" }; +PNAME(mux_mmc_src_p) = { "dpll", "gpll", "xin24m", "usb480m" }; +PNAME(mux_pll_src_dpll_gpll_usb480m_p) = { "dpll", "gpll", "usb480m" }; +PNAME(mux_uart0_p) = { "uart0_src", "uart0_frac", "xin24m" }; +PNAME(mux_uart1_p) = { "uart1_src", "uart1_frac", "xin24m" }; +PNAME(mux_uart2_p) = { "uart2_src", "uart2_frac", "xin24m" }; +PNAME(mux_sclk_macphy_p) = { "sclk_macphy_pre", "ext_gmac" }; +PNAME(mux_i2s0_pre_p) = { "i2s0_src", "i2s0_frac", "ext_i2s", "xin12m" }; +PNAME(mux_i2s_out_p) = { "i2s0_pre", "xin12m" }; +PNAME(mux_i2s1_p) = { "i2s1_src", "i2s1_frac", "xin12m" }; +PNAME(mux_i2s2_p) = { "i2s2_src", "i2s2_frac", "xin12m" }; + +static struct rockchip_pll_clock rv1108_pll_clks[] __initdata = { + [apll] = PLL(pll_rk3399, PLL_APLL, "apll", mux_pll_p, 0, RV1108_PLL_CON(0), + RV1108_PLL_CON(3), 8, 31, 0, rv1108_pll_rates), + [dpll] = PLL(pll_rk3399, PLL_DPLL, "dpll", mux_pll_p, 0, RV1108_PLL_CON(8), + RV1108_PLL_CON(11), 8, 31, 0, NULL), + [gpll] = PLL(pll_rk3399, PLL_GPLL, "gpll", mux_pll_p, 0, RV1108_PLL_CON(16), + RV1108_PLL_CON(19), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rv1108_pll_rates), +}; + +#define MFLAGS CLK_MUX_HIWORD_MASK +#define DFLAGS CLK_DIVIDER_HIWORD_MASK +#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE) +#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK + +static struct rockchip_clk_branch rv1108_uart0_fracmux __initdata = + MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT, + RV1108_CLKSEL_CON(13), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rv1108_uart1_fracmux __initdata = + MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT, + RV1108_CLKSEL_CON(14), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rv1108_uart2_fracmux __initdata = + MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT, + RV1108_CLKSEL_CON(15), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rv1108_i2s0_fracmux __initdata = + MUX(0, "i2s0_pre", mux_i2s0_pre_p, CLK_SET_RATE_PARENT, + RV1108_CLKSEL_CON(5), 12, 2, MFLAGS); + +static struct rockchip_clk_branch rv1108_i2s1_fracmux __initdata = + MUX(0, "i2s1_pre", mux_i2s1_p, CLK_SET_RATE_PARENT, + RV1108_CLKSEL_CON(6), 12, 2, MFLAGS); + +static struct rockchip_clk_branch rv1108_i2s2_fracmux __initdata = + MUX(0, "i2s2_pre", mux_i2s2_p, CLK_SET_RATE_PARENT, + RV1108_CLKSEL_CON(7), 12, 2, MFLAGS); + +static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { + MUX(0, "hdmi_phy", mux_hdmiphy_phy_p, CLK_SET_RATE_PARENT, + RV1108_MISC_CON, 13, 2, MFLAGS), + MUX(0, "usb480m", mux_usb480m_pre_p, CLK_SET_RATE_PARENT, + RV1108_MISC_CON, 15, 2, MFLAGS), + /* + * Clock-Architecture Diagram 2 + */ + + /* PD_CORE */ + GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(0), 1, GFLAGS), + GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(0), 0, GFLAGS), + GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(0), 2, GFLAGS), + COMPOSITE_NOMUX(0, "pclken_dbg", "armclk", CLK_IGNORE_UNUSED, + RV1108_CLKSEL_CON(1), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, + RV1108_CLKGATE_CON(0), 5, GFLAGS), + COMPOSITE_NOMUX(ACLK_ENMCORE, "aclkenm_core", "armclk", CLK_IGNORE_UNUSED, + RV1108_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, + RV1108_CLKGATE_CON(0), 4, GFLAGS), + GATE(ACLK_CORE, "aclk_core", "aclkenm_core", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(11), 0, GFLAGS), + GATE(0, "pclk_dbg", "pclken_dbg", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(11), 1, GFLAGS), + + /* PD_RKVENC */ + + /* PD_RKVDEC */ + + /* PD_PMU_wrapper */ + COMPOSITE_NOMUX(0, "pmu_24m_ena", "gpll", CLK_IGNORE_UNUSED, + RV1108_CLKSEL_CON(38), 0, 5, DFLAGS, + RV1108_CLKGATE_CON(8), 12, GFLAGS), + GATE(0, "pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(10), 0, GFLAGS), + GATE(0, "intmem1", "pmu_24m_ena", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(10), 1, GFLAGS), + GATE(0, "gpio0_pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(10), 2, GFLAGS), + GATE(0, "pmugrf", "pmu_24m_ena", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(10), 3, GFLAGS), + GATE(0, "pmu_noc", "pmu_24m_ena", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(10), 4, GFLAGS), + GATE(0, "i2c0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(10), 5, GFLAGS), + GATE(0, "pwm0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(10), 6, GFLAGS), + COMPOSITE(0, "pwm0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, + RV1108_CLKSEL_CON(12), 7, 1, MFLAGS, 0, 7, DFLAGS, + RV1108_CLKGATE_CON(8), 15, GFLAGS), + COMPOSITE(0, "i2c0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, + RV1108_CLKSEL_CON(19), 7, 1, MFLAGS, 0, 7, DFLAGS, + RV1108_CLKGATE_CON(8), 14, GFLAGS), + GATE(0, "pvtm_pmu", "xin24m", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(8), 13, GFLAGS), + + /* + * Clock-Architecture Diagram 4 + */ + COMPOSITE(0, "aclk_vio0_2wrap_occ", mux_pll_src_4plls_p, CLK_IGNORE_UNUSED, + RV1108_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS, + RV1108_CLKGATE_CON(6), 0, GFLAGS), + GATE(0, "aclk_vio0_pre", "aclk_vio0_2wrap_occ", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(17), 0, GFLAGS), + COMPOSITE_NOMUX(0, "hclk_vio_pre", "aclk_vio0_pre", 0, + RV1108_CLKSEL_CON(29), 0, 5, DFLAGS, + RV1108_CLKGATE_CON(7), 2, GFLAGS), + COMPOSITE_NOMUX(0, "pclk_vio_pre", "aclk_vio0_pre", 0, + RV1108_CLKSEL_CON(29), 8, 5, DFLAGS, + RV1108_CLKGATE_CON(7), 3, GFLAGS), + + INVERTER(0, "pclk_vip", "ext_vip", + RV1108_CLKSEL_CON(31), 8, IFLAGS), + GATE(0, "pclk_isp_pre", "pclk_vip", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(7), 6, GFLAGS), + GATE(0, "pclk_isp", "pclk_isp_pre", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(18), 10, GFLAGS), + GATE(0, "dclk_hdmiphy_src_gpll", "gpll", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(6), 5, GFLAGS), + GATE(0, "dclk_hdmiphy_src_dpll", "dpll", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(6), 4, GFLAGS), + COMPOSITE_NOGATE(0, "dclk_hdmiphy", mux_dclk_hdmiphy_pre_p, 0, + RV1108_CLKSEL_CON(32), 6, 2, MFLAGS, 8, 6, DFLAGS), + + /* + * Clock-Architecture Diagram 5 + */ + + FACTOR(0, "xin12m", "xin24m", 0, 1, 2), + + COMPOSITE(0, "i2s0_src", mux_pll_src_2plls_p, 0, + RV1108_CLKSEL_CON(5), 8, 1, MFLAGS, 0, 7, DFLAGS, + RV1108_CLKGATE_CON(2), 0, GFLAGS), + COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT, + RV1108_CLKSEL_CON(8), 0, + RV1108_CLKGATE_CON(2), 1, GFLAGS, + &rv1108_i2s0_fracmux), + GATE(SCLK_I2S0, "sclk_i2s0", "i2s0_pre", CLK_SET_RATE_PARENT, + RV1108_CLKGATE_CON(2), 2, GFLAGS), + COMPOSITE_NODIV(0, "i2s_out", mux_i2s_out_p, 0, + RV1108_CLKSEL_CON(5), 15, 1, MFLAGS, + RV1108_CLKGATE_CON(2), 3, GFLAGS), + + COMPOSITE(0, "i2s1_src", mux_pll_src_2plls_p, 0, + RV1108_CLKSEL_CON(6), 8, 1, MFLAGS, 0, 7, DFLAGS, + RV1108_CLKGATE_CON(2), 4, GFLAGS), + COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(9), 0, + RK2928_CLKGATE_CON(2), 5, GFLAGS, + &rv1108_i2s1_fracmux), + GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", CLK_SET_RATE_PARENT, + RV1108_CLKGATE_CON(2), 6, GFLAGS), + + COMPOSITE(0, "i2s2_src", mux_pll_src_2plls_p, 0, + RV1108_CLKSEL_CON(7), 8, 1, MFLAGS, 0, 7, DFLAGS, + RV1108_CLKGATE_CON(3), 8, GFLAGS), + COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT, + RV1108_CLKSEL_CON(10), 0, + RV1108_CLKGATE_CON(2), 9, GFLAGS, + &rv1108_i2s2_fracmux), + GATE(SCLK_I2S2, "sclk_i2s2", "i2s2_pre", CLK_SET_RATE_PARENT, + RV1108_CLKGATE_CON(2), 10, GFLAGS), + + /* PD_BUS */ + GATE(0, "aclk_bus_src_gpll", "gpll", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(1), 0, GFLAGS), + GATE(0, "aclk_bus_src_apll", "apll", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(1), 1, GFLAGS), + GATE(0, "aclk_bus_src_dpll", "dpll", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(1), 2, GFLAGS), + COMPOSITE_NOGATE(ACLK_PRE, "aclk_bus_pre", mux_aclk_bus_src_p, 0, + RV1108_CLKSEL_CON(2), 8, 2, MFLAGS, 0, 5, DFLAGS), + COMPOSITE_NOMUX(0, "hclk_bus_pre", "aclk_bus_2wrap_occ", 0, + RV1108_CLKSEL_CON(3), 0, 5, DFLAGS, + RV1108_CLKGATE_CON(1), 4, GFLAGS), + COMPOSITE_NOMUX(0, "pclken_bus", "aclk_bus_2wrap_occ", 0, + RV1108_CLKSEL_CON(3), 8, 5, DFLAGS, + RV1108_CLKGATE_CON(1), 5, GFLAGS), + GATE(0, "pclk_bus_pre", "pclken_bus", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(1), 6, GFLAGS), + GATE(0, "pclk_top_pre", "pclken_bus", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(1), 7, GFLAGS), + GATE(0, "pclk_ddr_pre", "pclken_bus", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(1), 8, GFLAGS), + GATE(0, "clk_timer0", "mux_pll_p", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(1), 9, GFLAGS), + GATE(0, "clk_timer1", "mux_pll_p", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(1), 10, GFLAGS), + GATE(0, "pclk_timer", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(13), 4, GFLAGS), + + COMPOSITE(0, "uart0_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, + RV1108_CLKSEL_CON(13), 12, 2, MFLAGS, 0, 7, DFLAGS, + RV1108_CLKGATE_CON(3), 1, GFLAGS), + COMPOSITE(0, "uart1_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, + RV1108_CLKSEL_CON(14), 12, 2, MFLAGS, 0, 7, DFLAGS, + RV1108_CLKGATE_CON(3), 3, GFLAGS), + COMPOSITE(0, "uart21_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, + RV1108_CLKSEL_CON(15), 12, 2, MFLAGS, 0, 7, DFLAGS, + RV1108_CLKGATE_CON(3), 5, GFLAGS), + + COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT, + RV1108_CLKSEL_CON(16), 0, + RV1108_CLKGATE_CON(3), 2, GFLAGS, + &rv1108_uart0_fracmux), + COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT, + RV1108_CLKSEL_CON(17), 0, + RV1108_CLKGATE_CON(3), 4, GFLAGS, + &rv1108_uart1_fracmux), + COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT, + RV1108_CLKSEL_CON(18), 0, + RV1108_CLKGATE_CON(3), 6, GFLAGS, + &rv1108_uart2_fracmux), + GATE(PCLK_UART0, "pclk_uart0", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(13), 10, GFLAGS), + GATE(PCLK_UART1, "pclk_uart1", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(13), 11, GFLAGS), + GATE(PCLK_UART2, "pclk_uart2", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(13), 12, GFLAGS), + + COMPOSITE(0, "clk_i2c1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, + RV1108_CLKSEL_CON(19), 15, 2, MFLAGS, 8, 7, DFLAGS, + RV1108_CLKGATE_CON(3), 7, GFLAGS), + COMPOSITE(0, "clk_i2c2", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, + RV1108_CLKSEL_CON(20), 7, 2, MFLAGS, 0, 7, DFLAGS, + RV1108_CLKGATE_CON(3), 8, GFLAGS), + COMPOSITE(0, "clk_i2c3", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, + RV1108_CLKSEL_CON(20), 15, 2, MFLAGS, 8, 7, DFLAGS, + RV1108_CLKGATE_CON(3), 9, GFLAGS), + GATE(0, "pclk_i2c1", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(13), 0, GFLAGS), + GATE(0, "pclk_i2c2", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(13), 1, GFLAGS), + GATE(0, "pclk_i2c3", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(13), 2, GFLAGS), + COMPOSITE(0, "clk_pwm1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, + RV1108_CLKSEL_CON(12), 15, 2, MFLAGS, 8, 7, DFLAGS, + RV1108_CLKGATE_CON(3), 10, GFLAGS), + GATE(0, "pclk_pwm1", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(13), 6, GFLAGS), + GATE(0, "pclk_wdt", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(13), 3, GFLAGS), + GATE(0, "pclk_gpio1", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(13), 7, GFLAGS), + GATE(0, "pclk_gpio2", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(13), 8, GFLAGS), + GATE(0, "pclk_gpio3", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(13), 9, GFLAGS), + + GATE(0, "pclk_grf", "pclk_bus_pre", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(14), 0, GFLAGS), + + GATE(ACLK_DMAC, "aclk_dmac", "aclk_bus_pre", 0, + RV1108_CLKGATE_CON(12), 2, GFLAGS), + GATE(0, "hclk_rom", "hclk_bus_pre", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(12), 3, GFLAGS), + GATE(0, "aclk_intmem", "aclk_bus_pre", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(12), 1, GFLAGS), + + /* PD_DDR */ + GATE(0, "apll_ddr", "apll", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(0), 8, GFLAGS), + GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(0), 9, GFLAGS), + GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(0), 10, GFLAGS), + COMPOSITE(0, "ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED, + RV1108_CLKSEL_CON(4), 8, 2, MFLAGS, 0, 3, + DFLAGS | CLK_DIVIDER_POWER_OF_TWO, + RV1108_CLKGATE_CON(10), 9, GFLAGS), + GATE(0, "ddrupctl", "ddrphy_pre", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(12), 4, GFLAGS), + GATE(0, "ddrc", "ddrphy", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(12), 5, GFLAGS), + GATE(0, "ddrmon", "ddrphy_pre", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(12), 6, GFLAGS), + GATE(0, "timer_clk", "xin24m", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(0), 11, GFLAGS), + + /* + * Clock-Architecture Diagram 6 + */ + + /* PD_PERI */ + COMPOSITE_NOMUX(0, "pclk_periph_pre", "gpll", 0, + RV1108_CLKSEL_CON(23), 10, 5, DFLAGS, + RV1108_CLKGATE_CON(4), 5, GFLAGS), + GATE(0, "pclk_periph", "pclk_periph_pre", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(15), 13, GFLAGS), + COMPOSITE_NOMUX(0, "hclk_periph_pre", "gpll", 0, + RV1108_CLKSEL_CON(23), 5, 5, DFLAGS, + RV1108_CLKGATE_CON(4), 4, GFLAGS), + GATE(0, "hclk_periph", "hclk_periph_pre", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(15), 12, GFLAGS), + + GATE(0, "aclk_peri_src_dpll", "dpll", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(4), 1, GFLAGS), + GATE(0, "aclk_peri_src_gpll", "gpll", CLK_IGNORE_UNUSED, + RV1108_CLKGATE_CON(4), 2, GFLAGS), + COMPOSITE(0, "aclk_periph", mux_aclk_peri_src_p, CLK_IGNORE_UNUSED, + RV1108_CLKSEL_CON(23), 15, 2, MFLAGS, 0, 5, DFLAGS, + RV1108_CLKGATE_CON(15), 11, GFLAGS), + + COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0, + RV1108_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 8, DFLAGS, + RV1108_CLKGATE_CON(5), 0, GFLAGS), + + COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0, + RV1108_CLKSEL_CON(25), 10, 2, MFLAGS, + RV1108_CLKGATE_CON(5), 2, GFLAGS), + DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0, + RV1108_CLKSEL_CON(26), 0, 8, DFLAGS), + + COMPOSITE_NODIV(0, "sclk_emmc_src", mux_mmc_src_p, 0, + RV1108_CLKSEL_CON(25), 12, 2, MFLAGS, + RV1108_CLKGATE_CON(5), 1, GFLAGS), + DIV(SCLK_EMMC, "sclk_emmc", "sclk_emmc_src", 0, + RK2928_CLKSEL_CON(26), 8, 8, DFLAGS), + GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 0, GFLAGS), + GATE(HCLK_SDIO, "hclk_sdio", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 1, GFLAGS), + GATE(HCLK_EMMC, "hclk_emmc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 2, GFLAGS), + + COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_2plls_p, 0, + RV1108_CLKSEL_CON(27), 14, 2, MFLAGS, 8, 5, DFLAGS, + RV1108_CLKGATE_CON(5), 3, GFLAGS), + GATE(HCLK_NANDC, "hclk_nandc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 3, GFLAGS), + + COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_2plls_p, 0, + RV1108_CLKSEL_CON(27), 7, 2, MFLAGS, 0, 7, DFLAGS, + RV1108_CLKGATE_CON(5), 4, GFLAGS), + GATE(HCLK_SFC, "hclk_sfc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 10, GFLAGS), + + COMPOSITE(0, "sclk_macphy_pre", mux_pll_src_apll_gpll_p, 0, + RV1108_CLKSEL_CON(24), 12, 2, MFLAGS, 0, 5, DFLAGS, + RV1108_CLKGATE_CON(4), 10, GFLAGS), + MUX(0, "sclk_macphy", mux_sclk_macphy_p, CLK_SET_RATE_PARENT, + RV1108_CLKSEL_CON(24), 8, 2, MFLAGS), + GATE(0, "sclk_macphy_rx", "sclk_macphy", 0, RV1108_CLKGATE_CON(4), 8, GFLAGS), + GATE(0, "sclk_mac_ref", "sclk_macphy", 0, RV1108_CLKGATE_CON(4), 6, GFLAGS), + GATE(0, "sclk_mac_refout", "sclk_macphy", 0, RV1108_CLKGATE_CON(4), 7, GFLAGS), + + MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RV1108_SDMMC_CON0, 1), + MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RV1108_SDMMC_CON1, 1), + + MMC(SCLK_SDIO_DRV, "sdio_drv", "sclk_sdio", RV1108_SDIO_CON0, 1), + MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RV1108_SDIO_CON1, 1), + + MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RV1108_EMMC_CON0, 1), + MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RV1108_EMMC_CON1, 1), +}; + +static const char *const rv1108_critical_clocks[] __initconst = { + "aclk_core", + "aclk_bus_src_gpll", + "aclk_periph", + "hclk_periph", + "pclk_periph", +}; + +static void __init rv1108_clk_init(struct device_node *np) +{ + struct rockchip_clk_provider *ctx; + void __iomem *reg_base; + + reg_base = of_iomap(np, 0); + if (!reg_base) { + pr_err("%s: could not map cru region\n", __func__); + return; + } + + ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); + if (IS_ERR(ctx)) { + pr_err("%s: rockchip clk init failed\n", __func__); + iounmap(reg_base); + return; + } + + rockchip_clk_register_plls(ctx, rv1108_pll_clks, + ARRAY_SIZE(rv1108_pll_clks), + RV1108_GRF_SOC_STATUS0); + rockchip_clk_register_branches(ctx, rv1108_clk_branches, + ARRAY_SIZE(rv1108_clk_branches)); + rockchip_clk_protect_critical(rv1108_critical_clocks, + ARRAY_SIZE(rv1108_critical_clocks)); + + rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", + mux_armclk_p, ARRAY_SIZE(mux_armclk_p), + &rv1108_cpuclk_data, rv1108_cpuclk_rates, + ARRAY_SIZE(rv1108_cpuclk_rates)); + + rockchip_register_softrst(np, 13, reg_base + RV1108_SOFTRST_CON(0), + ROCKCHIP_SOFTRST_HIWORD_MASK); + + rockchip_register_restart_notifier(ctx, RV1108_GLB_SRST_FST, NULL); + + rockchip_clk_of_add_provider(np, ctx); +} +CLK_OF_DECLARE(rv1108_cru, "rockchip,rv1108-cru", rv1108_clk_init); diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 7c15473ea72b..ef601dded32c 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -34,20 +34,20 @@ struct clk; #define HIWORD_UPDATE(val, mask, shift) \ ((val) << (shift) | (mask) << ((shift) + 16)) -/* register positions shared by RK1108, RK2928, RK3036, RK3066, RK3188 and RK3228 */ -#define RK1108_PLL_CON(x) ((x) * 0x4) -#define RK1108_CLKSEL_CON(x) ((x) * 0x4 + 0x60) -#define RK1108_CLKGATE_CON(x) ((x) * 0x4 + 0x120) -#define RK1108_SOFTRST_CON(x) ((x) * 0x4 + 0x180) -#define RK1108_GLB_SRST_FST 0x1c0 -#define RK1108_GLB_SRST_SND 0x1c4 -#define RK1108_MISC_CON 0x1cc -#define RK1108_SDMMC_CON0 0x1d8 -#define RK1108_SDMMC_CON1 0x1dc -#define RK1108_SDIO_CON0 0x1e0 -#define RK1108_SDIO_CON1 0x1e4 -#define RK1108_EMMC_CON0 0x1e8 -#define RK1108_EMMC_CON1 0x1ec +/* register positions shared by RV1108, RK2928, RK3036, RK3066, RK3188 and RK3228 */ +#define RV1108_PLL_CON(x) ((x) * 0x4) +#define RV1108_CLKSEL_CON(x) ((x) * 0x4 + 0x60) +#define RV1108_CLKGATE_CON(x) ((x) * 0x4 + 0x120) +#define RV1108_SOFTRST_CON(x) ((x) * 0x4 + 0x180) +#define RV1108_GLB_SRST_FST 0x1c0 +#define RV1108_GLB_SRST_SND 0x1c4 +#define RV1108_MISC_CON 0x1cc +#define RV1108_SDMMC_CON0 0x1d8 +#define RV1108_SDMMC_CON1 0x1dc +#define RV1108_SDIO_CON0 0x1e0 +#define RV1108_SDIO_CON1 0x1e4 +#define RV1108_EMMC_CON0 0x1e8 +#define RV1108_EMMC_CON1 0x1ec #define RK2928_PLL_CON(x) ((x) * 0x4) #define RK2928_MODE_CON 0x40 diff --git a/include/dt-bindings/clock/rk1108-cru.h b/include/dt-bindings/clock/rk1108-cru.h deleted file mode 100644 index 9350a5527a36..000000000000 --- a/include/dt-bindings/clock/rk1108-cru.h +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright (c) 2016 Rockchip Electronics Co. Ltd. - * Author: Shawn Lin - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK1108_H -#define _DT_BINDINGS_CLK_ROCKCHIP_RK1108_H - -/* pll id */ -#define PLL_APLL 0 -#define PLL_DPLL 1 -#define PLL_GPLL 2 -#define ARMCLK 3 - -/* sclk gates (special clocks) */ -#define SCLK_SPI0 65 -#define SCLK_NANDC 67 -#define SCLK_SDMMC 68 -#define SCLK_SDIO 69 -#define SCLK_EMMC 71 -#define SCLK_UART0 72 -#define SCLK_UART1 73 -#define SCLK_UART2 74 -#define SCLK_I2S0 75 -#define SCLK_I2S1 76 -#define SCLK_I2S2 77 -#define SCLK_TIMER0 78 -#define SCLK_TIMER1 79 -#define SCLK_SFC 80 -#define SCLK_SDMMC_DRV 81 -#define SCLK_SDIO_DRV 82 -#define SCLK_EMMC_DRV 83 -#define SCLK_SDMMC_SAMPLE 84 -#define SCLK_SDIO_SAMPLE 85 -#define SCLK_EMMC_SAMPLE 86 - -/* aclk gates */ -#define ACLK_DMAC 192 -#define ACLK_PRE 193 -#define ACLK_CORE 194 -#define ACLK_ENMCORE 195 - -/* pclk gates */ -#define PCLK_GPIO1 256 -#define PCLK_GPIO2 257 -#define PCLK_GPIO3 258 -#define PCLK_GRF 259 -#define PCLK_I2C1 260 -#define PCLK_I2C2 261 -#define PCLK_I2C3 262 -#define PCLK_SPI 263 -#define PCLK_SFC 264 -#define PCLK_UART0 265 -#define PCLK_UART1 266 -#define PCLK_UART2 267 -#define PCLK_TSADC 268 -#define PCLK_PWM 269 -#define PCLK_TIMER 270 -#define PCLK_PERI 271 - -/* hclk gates */ -#define HCLK_I2S0_8CH 320 -#define HCLK_I2S1_8CH 321 -#define HCLK_I2S2_2CH 322 -#define HCLK_NANDC 323 -#define HCLK_SDMMC 324 -#define HCLK_SDIO 325 -#define HCLK_EMMC 326 -#define HCLK_PERI 327 -#define HCLK_SFC 328 - -#define CLK_NR_CLKS (HCLK_SFC + 1) - -/* reset id */ -#define SRST_CORE_PO_AD 0 -#define SRST_CORE_AD 1 -#define SRST_L2_AD 2 -#define SRST_CPU_NIU_AD 3 -#define SRST_CORE_PO 4 -#define SRST_CORE 5 -#define SRST_L2 6 -#define SRST_CORE_DBG 8 -#define PRST_DBG 9 -#define RST_DAP 10 -#define PRST_DBG_NIU 11 -#define ARST_STRC_SYS_AD 15 - -#define SRST_DDRPHY_CLKDIV 16 -#define SRST_DDRPHY 17 -#define PRST_DDRPHY 18 -#define PRST_HDMIPHY 19 -#define PRST_VDACPHY 20 -#define PRST_VADCPHY 21 -#define PRST_MIPI_CSI_PHY 22 -#define PRST_MIPI_DSI_PHY 23 -#define PRST_ACODEC 24 -#define ARST_BUS_NIU 25 -#define PRST_TOP_NIU 26 -#define ARST_INTMEM 27 -#define HRST_ROM 28 -#define ARST_DMAC 29 -#define SRST_MSCH_NIU 30 -#define PRST_MSCH_NIU 31 - -#define PRST_DDRUPCTL 32 -#define NRST_DDRUPCTL 33 -#define PRST_DDRMON 34 -#define HRST_I2S0_8CH 35 -#define MRST_I2S0_8CH 36 -#define HRST_I2S1_2CH 37 -#define MRST_IS21_2CH 38 -#define HRST_I2S2_2CH 39 -#define MRST_I2S2_2CH 40 -#define HRST_CRYPTO 41 -#define SRST_CRYPTO 42 -#define PRST_SPI 43 -#define SRST_SPI 44 -#define PRST_UART0 45 -#define PRST_UART1 46 -#define PRST_UART2 47 - -#define SRST_UART0 48 -#define SRST_UART1 49 -#define SRST_UART2 50 -#define PRST_I2C1 51 -#define PRST_I2C2 52 -#define PRST_I2C3 53 -#define SRST_I2C1 54 -#define SRST_I2C2 55 -#define SRST_I2C3 56 -#define PRST_PWM1 58 -#define SRST_PWM1 60 -#define PRST_WDT 61 -#define PRST_GPIO1 62 -#define PRST_GPIO2 63 - -#define PRST_GPIO3 64 -#define PRST_GRF 65 -#define PRST_EFUSE 66 -#define PRST_EFUSE512 67 -#define PRST_TIMER0 68 -#define SRST_TIMER0 69 -#define SRST_TIMER1 70 -#define PRST_TSADC 71 -#define SRST_TSADC 72 -#define PRST_SARADC 73 -#define SRST_SARADC 74 -#define HRST_SYSBUS 75 -#define PRST_USBGRF 76 - -#define ARST_PERIPH_NIU 80 -#define HRST_PERIPH_NIU 81 -#define PRST_PERIPH_NIU 82 -#define HRST_PERIPH 83 -#define HRST_SDMMC 84 -#define HRST_SDIO 85 -#define HRST_EMMC 86 -#define HRST_NANDC 87 -#define NRST_NANDC 88 -#define HRST_SFC 89 -#define SRST_SFC 90 -#define ARST_GMAC 91 -#define HRST_OTG 92 -#define SRST_OTG 93 -#define SRST_OTG_ADP 94 -#define HRST_HOST0 95 - -#define HRST_HOST0_AUX 96 -#define HRST_HOST0_ARB 97 -#define SRST_HOST0_EHCIPHY 98 -#define SRST_HOST0_UTMI 99 -#define SRST_USBPOR 100 -#define SRST_UTMI0 101 -#define SRST_UTMI1 102 - -#define ARST_VIO0_NIU 102 -#define ARST_VIO1_NIU 103 -#define HRST_VIO_NIU 104 -#define PRST_VIO_NIU 105 -#define ARST_VOP 106 -#define HRST_VOP 107 -#define DRST_VOP 108 -#define ARST_IEP 109 -#define HRST_IEP 110 -#define ARST_RGA 111 -#define HRST_RGA 112 -#define SRST_RGA 113 -#define PRST_CVBS 114 -#define PRST_HDMI 115 -#define SRST_HDMI 116 -#define PRST_MIPI_DSI 117 - -#define ARST_ISP_NIU 118 -#define HRST_ISP_NIU 119 -#define HRST_ISP 120 -#define SRST_ISP 121 -#define ARST_VIP0 122 -#define HRST_VIP0 123 -#define PRST_VIP0 124 -#define ARST_VIP1 125 -#define HRST_VIP1 126 -#define PRST_VIP1 127 -#define ARST_VIP2 128 -#define HRST_VIP2 129 -#define PRST_VIP2 120 -#define ARST_VIP3 121 -#define HRST_VIP3 122 -#define PRST_VIP4 123 - -#define PRST_CIF1TO4 124 -#define SRST_CVBS_CLK 125 -#define HRST_CVBS 126 - -#define ARST_VPU_NIU 140 -#define HRST_VPU_NIU 141 -#define ARST_VPU 142 -#define HRST_VPU 143 -#define ARST_RKVDEC_NIU 144 -#define HRST_RKVDEC_NIU 145 -#define ARST_RKVDEC 146 -#define HRST_RKVDEC 147 -#define SRST_RKVDEC_CABAC 148 -#define SRST_RKVDEC_CORE 149 -#define ARST_RKVENC_NIU 150 -#define HRST_RKVENC_NIU 151 -#define ARST_RKVENC 152 -#define HRST_RKVENC 153 -#define SRST_RKVENC_CORE 154 - -#define SRST_DSP_CORE 156 -#define SRST_DSP_SYS 157 -#define SRST_DSP_GLOBAL 158 -#define SRST_DSP_OECM 159 -#define PRST_DSP_IOP_NIU 160 -#define ARST_DSP_EPP_NIU 161 -#define ARST_DSP_EDP_NIU 162 -#define PRST_DSP_DBG_NIU 163 -#define PRST_DSP_CFG_NIU 164 -#define PRST_DSP_GRF 165 -#define PRST_DSP_MAILBOX 166 -#define PRST_DSP_INTC 167 -#define PRST_DSP_PFM_MON 169 -#define SRST_DSP_PFM_MON 170 -#define ARST_DSP_EDAP_NIU 171 - -#define SRST_PMU 172 -#define SRST_PMU_I2C0 173 -#define PRST_PMU_I2C0 174 -#define PRST_PMU_GPIO0 175 -#define PRST_PMU_INTMEM 176 -#define PRST_PMU_PWM0 177 -#define SRST_PMU_PWM0 178 -#define PRST_PMU_GRF 179 -#define SRST_PMU_NIU 180 -#define SRST_PMU_PVTM 181 -#define ARST_DSP_EDP_PERF 184 -#define ARST_DSP_EPP_PERF 185 - -#endif /* _DT_BINDINGS_CLK_ROCKCHIP_RK1108_H */ diff --git a/include/dt-bindings/clock/rv1108-cru.h b/include/dt-bindings/clock/rv1108-cru.h new file mode 100644 index 000000000000..ae26f8105914 --- /dev/null +++ b/include/dt-bindings/clock/rv1108-cru.h @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2016 Rockchip Electronics Co. Ltd. + * Author: Shawn Lin + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RV1108_H +#define _DT_BINDINGS_CLK_ROCKCHIP_RV1108_H + +/* pll id */ +#define PLL_APLL 0 +#define PLL_DPLL 1 +#define PLL_GPLL 2 +#define ARMCLK 3 + +/* sclk gates (special clocks) */ +#define SCLK_SPI0 65 +#define SCLK_NANDC 67 +#define SCLK_SDMMC 68 +#define SCLK_SDIO 69 +#define SCLK_EMMC 71 +#define SCLK_UART0 72 +#define SCLK_UART1 73 +#define SCLK_UART2 74 +#define SCLK_I2S0 75 +#define SCLK_I2S1 76 +#define SCLK_I2S2 77 +#define SCLK_TIMER0 78 +#define SCLK_TIMER1 79 +#define SCLK_SFC 80 +#define SCLK_SDMMC_DRV 81 +#define SCLK_SDIO_DRV 82 +#define SCLK_EMMC_DRV 83 +#define SCLK_SDMMC_SAMPLE 84 +#define SCLK_SDIO_SAMPLE 85 +#define SCLK_EMMC_SAMPLE 86 + +/* aclk gates */ +#define ACLK_DMAC 192 +#define ACLK_PRE 193 +#define ACLK_CORE 194 +#define ACLK_ENMCORE 195 + +/* pclk gates */ +#define PCLK_GPIO1 256 +#define PCLK_GPIO2 257 +#define PCLK_GPIO3 258 +#define PCLK_GRF 259 +#define PCLK_I2C1 260 +#define PCLK_I2C2 261 +#define PCLK_I2C3 262 +#define PCLK_SPI 263 +#define PCLK_SFC 264 +#define PCLK_UART0 265 +#define PCLK_UART1 266 +#define PCLK_UART2 267 +#define PCLK_TSADC 268 +#define PCLK_PWM 269 +#define PCLK_TIMER 270 +#define PCLK_PERI 271 + +/* hclk gates */ +#define HCLK_I2S0_8CH 320 +#define HCLK_I2S1_8CH 321 +#define HCLK_I2S2_2CH 322 +#define HCLK_NANDC 323 +#define HCLK_SDMMC 324 +#define HCLK_SDIO 325 +#define HCLK_EMMC 326 +#define HCLK_PERI 327 +#define HCLK_SFC 328 + +#define CLK_NR_CLKS (HCLK_SFC + 1) + +/* reset id */ +#define SRST_CORE_PO_AD 0 +#define SRST_CORE_AD 1 +#define SRST_L2_AD 2 +#define SRST_CPU_NIU_AD 3 +#define SRST_CORE_PO 4 +#define SRST_CORE 5 +#define SRST_L2 6 +#define SRST_CORE_DBG 8 +#define PRST_DBG 9 +#define RST_DAP 10 +#define PRST_DBG_NIU 11 +#define ARST_STRC_SYS_AD 15 + +#define SRST_DDRPHY_CLKDIV 16 +#define SRST_DDRPHY 17 +#define PRST_DDRPHY 18 +#define PRST_HDMIPHY 19 +#define PRST_VDACPHY 20 +#define PRST_VADCPHY 21 +#define PRST_MIPI_CSI_PHY 22 +#define PRST_MIPI_DSI_PHY 23 +#define PRST_ACODEC 24 +#define ARST_BUS_NIU 25 +#define PRST_TOP_NIU 26 +#define ARST_INTMEM 27 +#define HRST_ROM 28 +#define ARST_DMAC 29 +#define SRST_MSCH_NIU 30 +#define PRST_MSCH_NIU 31 + +#define PRST_DDRUPCTL 32 +#define NRST_DDRUPCTL 33 +#define PRST_DDRMON 34 +#define HRST_I2S0_8CH 35 +#define MRST_I2S0_8CH 36 +#define HRST_I2S1_2CH 37 +#define MRST_IS21_2CH 38 +#define HRST_I2S2_2CH 39 +#define MRST_I2S2_2CH 40 +#define HRST_CRYPTO 41 +#define SRST_CRYPTO 42 +#define PRST_SPI 43 +#define SRST_SPI 44 +#define PRST_UART0 45 +#define PRST_UART1 46 +#define PRST_UART2 47 + +#define SRST_UART0 48 +#define SRST_UART1 49 +#define SRST_UART2 50 +#define PRST_I2C1 51 +#define PRST_I2C2 52 +#define PRST_I2C3 53 +#define SRST_I2C1 54 +#define SRST_I2C2 55 +#define SRST_I2C3 56 +#define PRST_PWM1 58 +#define SRST_PWM1 60 +#define PRST_WDT 61 +#define PRST_GPIO1 62 +#define PRST_GPIO2 63 + +#define PRST_GPIO3 64 +#define PRST_GRF 65 +#define PRST_EFUSE 66 +#define PRST_EFUSE512 67 +#define PRST_TIMER0 68 +#define SRST_TIMER0 69 +#define SRST_TIMER1 70 +#define PRST_TSADC 71 +#define SRST_TSADC 72 +#define PRST_SARADC 73 +#define SRST_SARADC 74 +#define HRST_SYSBUS 75 +#define PRST_USBGRF 76 + +#define ARST_PERIPH_NIU 80 +#define HRST_PERIPH_NIU 81 +#define PRST_PERIPH_NIU 82 +#define HRST_PERIPH 83 +#define HRST_SDMMC 84 +#define HRST_SDIO 85 +#define HRST_EMMC 86 +#define HRST_NANDC 87 +#define NRST_NANDC 88 +#define HRST_SFC 89 +#define SRST_SFC 90 +#define ARST_GMAC 91 +#define HRST_OTG 92 +#define SRST_OTG 93 +#define SRST_OTG_ADP 94 +#define HRST_HOST0 95 + +#define HRST_HOST0_AUX 96 +#define HRST_HOST0_ARB 97 +#define SRST_HOST0_EHCIPHY 98 +#define SRST_HOST0_UTMI 99 +#define SRST_USBPOR 100 +#define SRST_UTMI0 101 +#define SRST_UTMI1 102 + +#define ARST_VIO0_NIU 102 +#define ARST_VIO1_NIU 103 +#define HRST_VIO_NIU 104 +#define PRST_VIO_NIU 105 +#define ARST_VOP 106 +#define HRST_VOP 107 +#define DRST_VOP 108 +#define ARST_IEP 109 +#define HRST_IEP 110 +#define ARST_RGA 111 +#define HRST_RGA 112 +#define SRST_RGA 113 +#define PRST_CVBS 114 +#define PRST_HDMI 115 +#define SRST_HDMI 116 +#define PRST_MIPI_DSI 117 + +#define ARST_ISP_NIU 118 +#define HRST_ISP_NIU 119 +#define HRST_ISP 120 +#define SRST_ISP 121 +#define ARST_VIP0 122 +#define HRST_VIP0 123 +#define PRST_VIP0 124 +#define ARST_VIP1 125 +#define HRST_VIP1 126 +#define PRST_VIP1 127 +#define ARST_VIP2 128 +#define HRST_VIP2 129 +#define PRST_VIP2 120 +#define ARST_VIP3 121 +#define HRST_VIP3 122 +#define PRST_VIP4 123 + +#define PRST_CIF1TO4 124 +#define SRST_CVBS_CLK 125 +#define HRST_CVBS 126 + +#define ARST_VPU_NIU 140 +#define HRST_VPU_NIU 141 +#define ARST_VPU 142 +#define HRST_VPU 143 +#define ARST_RKVDEC_NIU 144 +#define HRST_RKVDEC_NIU 145 +#define ARST_RKVDEC 146 +#define HRST_RKVDEC 147 +#define SRST_RKVDEC_CABAC 148 +#define SRST_RKVDEC_CORE 149 +#define ARST_RKVENC_NIU 150 +#define HRST_RKVENC_NIU 151 +#define ARST_RKVENC 152 +#define HRST_RKVENC 153 +#define SRST_RKVENC_CORE 154 + +#define SRST_DSP_CORE 156 +#define SRST_DSP_SYS 157 +#define SRST_DSP_GLOBAL 158 +#define SRST_DSP_OECM 159 +#define PRST_DSP_IOP_NIU 160 +#define ARST_DSP_EPP_NIU 161 +#define ARST_DSP_EDP_NIU 162 +#define PRST_DSP_DBG_NIU 163 +#define PRST_DSP_CFG_NIU 164 +#define PRST_DSP_GRF 165 +#define PRST_DSP_MAILBOX 166 +#define PRST_DSP_INTC 167 +#define PRST_DSP_PFM_MON 169 +#define SRST_DSP_PFM_MON 170 +#define ARST_DSP_EDAP_NIU 171 + +#define SRST_PMU 172 +#define SRST_PMU_I2C0 173 +#define PRST_PMU_I2C0 174 +#define PRST_PMU_GPIO0 175 +#define PRST_PMU_INTMEM 176 +#define PRST_PMU_PWM0 177 +#define SRST_PMU_PWM0 178 +#define PRST_PMU_GRF 179 +#define SRST_PMU_NIU 180 +#define SRST_PMU_PVTM 181 +#define ARST_DSP_EDP_PERF 184 +#define ARST_DSP_EPP_PERF 185 + +#endif /* _DT_BINDINGS_CLK_ROCKCHIP_RV1108_H */ -- cgit v1.2.3-59-g8ed1b From e8bb4673596ea28fab287dbc417e8100d798cd40 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 27 Mar 2017 07:31:03 +0200 Subject: dmaengine: pl330: remove pdata based initialization This driver is now used only on platforms which support device tree, so it is safe to remove legacy platform data based initialization code. Signed-off-by: Marek Szyprowski Reviewed-by: Ulf Hansson Acked-by: Arnd Bergmann For plat-samsung: Acked-by: Krzysztof Kozlowski Signed-off-by: Vinod Koul --- arch/arm/plat-samsung/devs.c | 1 - drivers/dma/pl330.c | 42 ++++++++---------------------------------- include/linux/amba/pl330.h | 35 ----------------------------------- 3 files changed, 8 insertions(+), 70 deletions(-) delete mode 100644 include/linux/amba/pl330.h (limited to 'arch') diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c index 03fac123676d..dc269d9143bc 100644 --- a/arch/arm/plat-samsung/devs.c +++ b/arch/arm/plat-samsung/devs.c @@ -10,7 +10,6 @@ * published by the Free Software Foundation. */ -#include #include #include #include diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index f37f4978dabb..8b0da7fa520d 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -2077,18 +2076,6 @@ static void pl330_tasklet(unsigned long data) } } -bool pl330_filter(struct dma_chan *chan, void *param) -{ - u8 *peri_id; - - if (chan->device->dev->driver != &pl330_driver.drv) - return false; - - peri_id = chan->private; - return *peri_id == (unsigned long)param; -} -EXPORT_SYMBOL(pl330_filter); - static struct dma_chan *of_dma_pl330_xlate(struct of_phandle_args *dma_spec, struct of_dma *ofdma) { @@ -2833,7 +2820,6 @@ static SIMPLE_DEV_PM_OPS(pl330_pm, pl330_suspend, pl330_resume); static int pl330_probe(struct amba_device *adev, const struct amba_id *id) { - struct dma_pl330_platdata *pdat; struct pl330_config *pcfg; struct pl330_dmac *pl330; struct dma_pl330_chan *pch, *_p; @@ -2843,8 +2829,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) int num_chan; struct device_node *np = adev->dev.of_node; - pdat = dev_get_platdata(&adev->dev); - ret = dma_set_mask_and_coherent(&adev->dev, DMA_BIT_MASK(32)); if (ret) return ret; @@ -2857,7 +2841,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) pd = &pl330->ddma; pd->dev = &adev->dev; - pl330->mcbufsz = pdat ? pdat->mcbuf_sz : 0; + pl330->mcbufsz = 0; /* get quirk */ for (i = 0; i < ARRAY_SIZE(of_quirks); i++) @@ -2901,10 +2885,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) INIT_LIST_HEAD(&pd->channels); /* Initialize channel parameters */ - if (pdat) - num_chan = max_t(int, pdat->nr_valid_peri, pcfg->num_chan); - else - num_chan = max_t(int, pcfg->num_peri, pcfg->num_chan); + num_chan = max_t(int, pcfg->num_peri, pcfg->num_chan); pl330->num_peripherals = num_chan; @@ -2916,11 +2897,8 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) for (i = 0; i < num_chan; i++) { pch = &pl330->peripherals[i]; - if (!adev->dev.of_node) - pch->chan.private = pdat ? &pdat->peri_id[i] : NULL; - else - pch->chan.private = adev->dev.of_node; + pch->chan.private = adev->dev.of_node; INIT_LIST_HEAD(&pch->submitted_list); INIT_LIST_HEAD(&pch->work_list); INIT_LIST_HEAD(&pch->completed_list); @@ -2933,15 +2911,11 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) list_add_tail(&pch->chan.device_node, &pd->channels); } - if (pdat) { - pd->cap_mask = pdat->cap_mask; - } else { - dma_cap_set(DMA_MEMCPY, pd->cap_mask); - if (pcfg->num_peri) { - dma_cap_set(DMA_SLAVE, pd->cap_mask); - dma_cap_set(DMA_CYCLIC, pd->cap_mask); - dma_cap_set(DMA_PRIVATE, pd->cap_mask); - } + dma_cap_set(DMA_MEMCPY, pd->cap_mask); + if (pcfg->num_peri) { + dma_cap_set(DMA_SLAVE, pd->cap_mask); + dma_cap_set(DMA_CYCLIC, pd->cap_mask); + dma_cap_set(DMA_PRIVATE, pd->cap_mask); } pd->device_alloc_chan_resources = pl330_alloc_chan_resources; diff --git a/include/linux/amba/pl330.h b/include/linux/amba/pl330.h deleted file mode 100644 index fe93758e8403..000000000000 --- a/include/linux/amba/pl330.h +++ /dev/null @@ -1,35 +0,0 @@ -/* linux/include/linux/amba/pl330.h - * - * Copyright (C) 2010 Samsung Electronics Co. Ltd. - * Jaswinder Singh - * - * 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. - */ - -#ifndef __AMBA_PL330_H_ -#define __AMBA_PL330_H_ - -#include - -struct dma_pl330_platdata { - /* - * Number of valid peripherals connected to DMAC. - * This may be different from the value read from - * CR0, as the PL330 implementation might have 'holes' - * in the peri list or the peri could also be reached - * from another DMAC which the platform prefers. - */ - u8 nr_valid_peri; - /* Array of valid peripherals */ - u8 *peri_id; - /* Operational capabilities */ - dma_cap_mask_t cap_mask; - /* Bytes to allocate for MC buffer */ - unsigned mcbuf_sz; -}; - -extern bool pl330_filter(struct dma_chan *chan, void *param); -#endif /* __AMBA_PL330_H_ */ -- cgit v1.2.3-59-g8ed1b From 3c2e2e6816930e25c755f2e4fc298a0d05d223cf Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 4 Apr 2017 16:54:21 +0100 Subject: Annotate hardware config module parameters in arch/x86/mm/ When the kernel is running in secure boot mode, we lock down the kernel to prevent userspace from modifying the running kernel image. Whilst this includes prohibiting access to things like /dev/mem, it must also prevent access by means of configuring driver modules in such a way as to cause a device to access or modify the kernel image. To this end, annotate module_param* statements that refer to hardware configuration and indicate for future reference what type of parameter they specify. The parameter parser in the core sees this information and can skip such parameters with an error message if the kernel is locked down. The module initialisation then runs as normal, but just sees whatever the default values for those parameters is. Note that we do still need to do the module initialisation because some drivers have viable defaults set in case parameters aren't specified and some drivers support automatic configuration (e.g. PNP or PCI) in addition to manually coded parameters. This patch annotates drivers in arch/x86/mm/. [Note: With respect to testmmiotrace, an additional patch will be added separately that makes the module refuse to load if the kernel is locked down.] Suggested-by: Alan Cox Signed-off-by: David Howells Acked-by: Steven Rostedt cc: Ingo Molnar cc: Thomas Gleixner cc: "H. Peter Anvin" cc: x86@kernel.org cc: linux-kernel@vger.kernel.org cc: nouveau@lists.freedesktop.org --- arch/x86/mm/testmmiotrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/mm/testmmiotrace.c b/arch/x86/mm/testmmiotrace.c index 38868adf07ea..f6ae6830b341 100644 --- a/arch/x86/mm/testmmiotrace.c +++ b/arch/x86/mm/testmmiotrace.c @@ -9,7 +9,7 @@ #include static unsigned long mmio_address; -module_param(mmio_address, ulong, 0); +module_param_hw(mmio_address, ulong, iomem, 0); MODULE_PARM_DESC(mmio_address, " Start address of the mapping of 16 kB " "(or 8 MB if read_far is non-zero)."); -- cgit v1.2.3-59-g8ed1b From 049520dcb3966ee0471f2757ca3f5f5e317f33cd Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 4 Apr 2017 07:53:38 +0100 Subject: metag/usercopy: Reformat rapf loop inline asm Reformat rapf loop inline assembly to make it more readable and easier to modify in future. Signed-off-by: James Hogan Cc: linux-metag@vger.kernel.org --- arch/metag/lib/usercopy.c | 214 ++++++++++++++++++---------------------------- 1 file changed, 85 insertions(+), 129 deletions(-) (limited to 'arch') diff --git a/arch/metag/lib/usercopy.c b/arch/metag/lib/usercopy.c index 2792fc621088..7abed2f45c83 100644 --- a/arch/metag/lib/usercopy.c +++ b/arch/metag/lib/usercopy.c @@ -246,65 +246,49 @@ #define __asm_copy_user_64bit_rapf_loop( \ to, from, ret, n, id, FIXUP) \ asm volatile ( \ - ".balign 8\n" \ - "MOV RAPF, %1\n" \ - "MSETL [A0StP++], D0Ar6, D0FrT, D0.5, D0.6, D0.7\n" \ - "MOV D0Ar6, #0\n" \ - "LSR D1Ar5, %3, #6\n" \ - "SUB TXRPT, D1Ar5, #2\n" \ - "MOV RAPF, %1\n" \ + ".balign 8\n" \ + " MOV RAPF, %1\n" \ + " MSETL [A0StP++], D0Ar6, D0FrT, D0.5, D0.6, D0.7\n" \ + " MOV D0Ar6, #0\n" \ + " LSR D1Ar5, %3, #6\n" \ + " SUB TXRPT, D1Ar5, #2\n" \ + " MOV RAPF, %1\n" \ "$Lloop"id":\n" \ - "ADD RAPF, %1, #64\n" \ - "21:\n" \ - "MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ - "22:\n" \ - "MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ - "23:\n" \ - "SUB %3, %3, #32\n" \ - "24:\n" \ - "MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ - "25:\n" \ - "MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ - "26:\n" \ - "SUB %3, %3, #32\n" \ - "DCACHE [%1+#-64], D0Ar6\n" \ - "BR $Lloop"id"\n" \ + " ADD RAPF, %1, #64\n" \ + "21: MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ + "22: MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ + "23: SUB %3, %3, #32\n" \ + "24: MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ + "25: MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ + "26: SUB %3, %3, #32\n" \ + " DCACHE [%1+#-64], D0Ar6\n" \ + " BR $Lloop"id"\n" \ \ - "MOV RAPF, %1\n" \ - "27:\n" \ - "MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ - "28:\n" \ - "MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ - "29:\n" \ - "SUB %3, %3, #32\n" \ - "30:\n" \ - "MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ - "31:\n" \ - "MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ - "32:\n" \ - "SUB %0, %0, #8\n" \ - "33:\n" \ - "SETL [%0++], D0.7, D1.7\n" \ - "SUB %3, %3, #32\n" \ - "1:" \ - "DCACHE [%1+#-64], D0Ar6\n" \ - "GETL D0Ar6, D1Ar5, [A0StP+#-40]\n" \ - "GETL D0FrT, D1RtP, [A0StP+#-32]\n" \ - "GETL D0.5, D1.5, [A0StP+#-24]\n" \ - "GETL D0.6, D1.6, [A0StP+#-16]\n" \ - "GETL D0.7, D1.7, [A0StP+#-8]\n" \ - "SUB A0StP, A0StP, #40\n" \ + " MOV RAPF, %1\n" \ + "27: MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ + "28: MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ + "29: SUB %3, %3, #32\n" \ + "30: MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ + "31: MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ + "32: SUB %0, %0, #8\n" \ + "33: SETL [%0++], D0.7, D1.7\n" \ + " SUB %3, %3, #32\n" \ + "1: DCACHE [%1+#-64], D0Ar6\n" \ + " GETL D0Ar6, D1Ar5, [A0StP+#-40]\n" \ + " GETL D0FrT, D1RtP, [A0StP+#-32]\n" \ + " GETL D0.5, D1.5, [A0StP+#-24]\n" \ + " GETL D0.6, D1.6, [A0StP+#-16]\n" \ + " GETL D0.7, D1.7, [A0StP+#-8]\n" \ + " SUB A0StP, A0StP, #40\n" \ " .section .fixup,\"ax\"\n" \ - "4:\n" \ - " ADD %0, %0, #8\n" \ - "3:\n" \ - " MOV D0Ar2, TXSTATUS\n" \ + "4: ADD %0, %0, #8\n" \ + "3: MOV D0Ar2, TXSTATUS\n" \ " MOV D1Ar1, TXSTATUS\n" \ " AND D1Ar1, D1Ar1, #0xFFFFF8FF\n" \ " MOV TXSTATUS, D1Ar1\n" \ FIXUP \ - " MOVT D0Ar2,#HI(1b)\n" \ - " JUMP D0Ar2,#LO(1b)\n" \ + " MOVT D0Ar2, #HI(1b)\n" \ + " JUMP D0Ar2, #LO(1b)\n" \ " .previous\n" \ " .section __ex_table,\"a\"\n" \ " .long 21b,3b\n" \ @@ -397,89 +381,61 @@ #define __asm_copy_user_32bit_rapf_loop( \ to, from, ret, n, id, FIXUP) \ asm volatile ( \ - ".balign 8\n" \ - "MOV RAPF, %1\n" \ - "MSETL [A0StP++], D0Ar6, D0FrT, D0.5, D0.6, D0.7\n" \ - "MOV D0Ar6, #0\n" \ - "LSR D1Ar5, %3, #6\n" \ - "SUB TXRPT, D1Ar5, #2\n" \ - "MOV RAPF, %1\n" \ - "$Lloop"id":\n" \ - "ADD RAPF, %1, #64\n" \ - "21:\n" \ - "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ - "22:\n" \ - "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ - "23:\n" \ - "SUB %3, %3, #16\n" \ - "24:\n" \ - "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ - "25:\n" \ - "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ - "26:\n" \ - "SUB %3, %3, #16\n" \ - "27:\n" \ - "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ - "28:\n" \ - "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ - "29:\n" \ - "SUB %3, %3, #16\n" \ - "30:\n" \ - "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ - "31:\n" \ - "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ - "32:\n" \ - "SUB %3, %3, #16\n" \ - "DCACHE [%1+#-64], D0Ar6\n" \ - "BR $Lloop"id"\n" \ + ".balign 8\n" \ + " MOV RAPF, %1\n" \ + " MSETL [A0StP++], D0Ar6, D0FrT, D0.5, D0.6, D0.7\n" \ + " MOV D0Ar6, #0\n" \ + " LSR D1Ar5, %3, #6\n" \ + " SUB TXRPT, D1Ar5, #2\n" \ + " MOV RAPF, %1\n" \ + "$Lloop"id":\n" \ + " ADD RAPF, %1, #64\n" \ + "21: MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ + "22: MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ + "23: SUB %3, %3, #16\n" \ + "24: MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ + "25: MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ + "26: SUB %3, %3, #16\n" \ + "27: MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ + "28: MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ + "29: SUB %3, %3, #16\n" \ + "30: MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ + "31: MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ + "32: SUB %3, %3, #16\n" \ + " DCACHE [%1+#-64], D0Ar6\n" \ + " BR $Lloop"id"\n" \ \ - "MOV RAPF, %1\n" \ - "33:\n" \ - "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ - "34:\n" \ - "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ - "35:\n" \ - "SUB %3, %3, #16\n" \ - "36:\n" \ - "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ - "37:\n" \ - "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ - "38:\n" \ - "SUB %3, %3, #16\n" \ - "39:\n" \ - "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ - "40:\n" \ - "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ - "41:\n" \ - "SUB %3, %3, #16\n" \ - "42:\n" \ - "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ - "43:\n" \ - "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ - "44:\n" \ - "SUB %0, %0, #4\n" \ - "45:\n" \ - "SETD [%0++], D0.7\n" \ - "SUB %3, %3, #16\n" \ - "1:" \ - "DCACHE [%1+#-64], D0Ar6\n" \ - "GETL D0Ar6, D1Ar5, [A0StP+#-40]\n" \ - "GETL D0FrT, D1RtP, [A0StP+#-32]\n" \ - "GETL D0.5, D1.5, [A0StP+#-24]\n" \ - "GETL D0.6, D1.6, [A0StP+#-16]\n" \ - "GETL D0.7, D1.7, [A0StP+#-8]\n" \ - "SUB A0StP, A0StP, #40\n" \ + " MOV RAPF, %1\n" \ + "33: MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ + "34: MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ + "35: SUB %3, %3, #16\n" \ + "36: MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ + "37: MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ + "38: SUB %3, %3, #16\n" \ + "39: MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ + "40: MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ + "41: SUB %3, %3, #16\n" \ + "42: MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ + "43: MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ + "44: SUB %0, %0, #4\n" \ + "45: SETD [%0++], D0.7\n" \ + " SUB %3, %3, #16\n" \ + "1: DCACHE [%1+#-64], D0Ar6\n" \ + " GETL D0Ar6, D1Ar5, [A0StP+#-40]\n" \ + " GETL D0FrT, D1RtP, [A0StP+#-32]\n" \ + " GETL D0.5, D1.5, [A0StP+#-24]\n" \ + " GETL D0.6, D1.6, [A0StP+#-16]\n" \ + " GETL D0.7, D1.7, [A0StP+#-8]\n" \ + " SUB A0StP, A0StP, #40\n" \ " .section .fixup,\"ax\"\n" \ - "4:\n" \ - " ADD %0, %0, #4\n" \ - "3:\n" \ - " MOV D0Ar2, TXSTATUS\n" \ + "4: ADD %0, %0, #4\n" \ + "3: MOV D0Ar2, TXSTATUS\n" \ " MOV D1Ar1, TXSTATUS\n" \ " AND D1Ar1, D1Ar1, #0xFFFFF8FF\n" \ " MOV TXSTATUS, D1Ar1\n" \ FIXUP \ - " MOVT D0Ar2,#HI(1b)\n" \ - " JUMP D0Ar2,#LO(1b)\n" \ + " MOVT D0Ar2, #HI(1b)\n" \ + " JUMP D0Ar2, #LO(1b)\n" \ " .previous\n" \ " .section __ex_table,\"a\"\n" \ " .long 21b,3b\n" \ -- cgit v1.2.3-59-g8ed1b From fc1b759ae4e0f636c56ca8410207a8a36630a96e Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 4 Apr 2017 11:42:35 +0100 Subject: metag/usercopy: Simplify rapf loop fixup corner case The final fixup in the rapf loops must handle a corner case due to the intermediate decrementing of the destination pointer before writing the last element to it again and re-incrementing it. This decrement (and the associated increment in the fixup code) can be easily avoided by using SETL/SETD with an offset of -8/-4. Signed-off-by: James Hogan Cc: linux-metag@vger.kernel.org --- arch/metag/lib/usercopy.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/metag/lib/usercopy.c b/arch/metag/lib/usercopy.c index 7abed2f45c83..ceb4590fbca5 100644 --- a/arch/metag/lib/usercopy.c +++ b/arch/metag/lib/usercopy.c @@ -270,8 +270,7 @@ "29: SUB %3, %3, #32\n" \ "30: MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ "31: MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ - "32: SUB %0, %0, #8\n" \ - "33: SETL [%0++], D0.7, D1.7\n" \ + "32: SETL [%0+#-8], D0.7, D1.7\n" \ " SUB %3, %3, #32\n" \ "1: DCACHE [%1+#-64], D0Ar6\n" \ " GETL D0Ar6, D1Ar5, [A0StP+#-40]\n" \ @@ -281,7 +280,6 @@ " GETL D0.7, D1.7, [A0StP+#-8]\n" \ " SUB A0StP, A0StP, #40\n" \ " .section .fixup,\"ax\"\n" \ - "4: ADD %0, %0, #8\n" \ "3: MOV D0Ar2, TXSTATUS\n" \ " MOV D1Ar1, TXSTATUS\n" \ " AND D1Ar1, D1Ar1, #0xFFFFF8FF\n" \ @@ -303,7 +301,6 @@ " .long 30b,3b\n" \ " .long 31b,3b\n" \ " .long 32b,3b\n" \ - " .long 33b,4b\n" \ " .previous\n" \ : "=r" (to), "=r" (from), "=r" (ret), "=d" (n) \ : "0" (to), "1" (from), "2" (ret), "3" (n) \ @@ -417,8 +414,7 @@ "41: SUB %3, %3, #16\n" \ "42: MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ "43: MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ - "44: SUB %0, %0, #4\n" \ - "45: SETD [%0++], D0.7\n" \ + "44: SETD [%0+#-4], D0.7\n" \ " SUB %3, %3, #16\n" \ "1: DCACHE [%1+#-64], D0Ar6\n" \ " GETL D0Ar6, D1Ar5, [A0StP+#-40]\n" \ @@ -428,7 +424,6 @@ " GETL D0.7, D1.7, [A0StP+#-8]\n" \ " SUB A0StP, A0StP, #40\n" \ " .section .fixup,\"ax\"\n" \ - "4: ADD %0, %0, #4\n" \ "3: MOV D0Ar2, TXSTATUS\n" \ " MOV D1Ar1, TXSTATUS\n" \ " AND D1Ar1, D1Ar1, #0xFFFFF8FF\n" \ @@ -462,7 +457,6 @@ " .long 42b,3b\n" \ " .long 43b,3b\n" \ " .long 44b,3b\n" \ - " .long 45b,4b\n" \ " .previous\n" \ : "=r" (to), "=r" (from), "=r" (ret), "=d" (n) \ : "0" (to), "1" (from), "2" (ret), "3" (n) \ -- cgit v1.2.3-59-g8ed1b From d3ba2e922d4d1d61806fcb6e09512d2bee734d06 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 31 Mar 2017 15:40:52 +0100 Subject: metag/usercopy: Add 64-bit get_user support Metag already supports 64-bit put_user, so add support for 64-bit get_user too so that the test_user_copy module can test both. Signed-off-by: James Hogan Cc: linux-metag@vger.kernel.org --- arch/metag/include/asm/uaccess.h | 9 +++++++-- arch/metag/lib/usercopy.c | 24 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/metag/include/asm/uaccess.h b/arch/metag/include/asm/uaccess.h index 07238b39638c..469a2f1393d3 100644 --- a/arch/metag/include/asm/uaccess.h +++ b/arch/metag/include/asm/uaccess.h @@ -138,7 +138,8 @@ extern long __get_user_bad(void); #define __get_user_nocheck(x, ptr, size) \ ({ \ - long __gu_err, __gu_val; \ + long __gu_err; \ + long long __gu_val; \ __get_user_size(__gu_val, (ptr), (size), __gu_err); \ (x) = (__force __typeof__(*(ptr)))__gu_val; \ __gu_err; \ @@ -146,7 +147,8 @@ extern long __get_user_bad(void); #define __get_user_check(x, ptr, size) \ ({ \ - long __gu_err = -EFAULT, __gu_val = 0; \ + long __gu_err = -EFAULT; \ + long long __gu_val = 0; \ const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ if (access_ok(VERIFY_READ, __gu_addr, size)) \ __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ @@ -157,6 +159,7 @@ extern long __get_user_bad(void); extern unsigned char __get_user_asm_b(const void __user *addr, long *err); extern unsigned short __get_user_asm_w(const void __user *addr, long *err); extern unsigned int __get_user_asm_d(const void __user *addr, long *err); +extern unsigned long long __get_user_asm_l(const void __user *addr, long *err); #define __get_user_size(x, ptr, size, retval) \ do { \ @@ -168,6 +171,8 @@ do { \ x = __get_user_asm_w(ptr, &retval); break; \ case 4: \ x = __get_user_asm_d(ptr, &retval); break; \ + case 8: \ + x = __get_user_asm_l(ptr, &retval); break; \ default: \ (x) = __get_user_bad(); \ } \ diff --git a/arch/metag/lib/usercopy.c b/arch/metag/lib/usercopy.c index ceb4590fbca5..45e7b79eca19 100644 --- a/arch/metag/lib/usercopy.c +++ b/arch/metag/lib/usercopy.c @@ -1044,6 +1044,30 @@ unsigned int __get_user_asm_d(const void __user *addr, long *err) } EXPORT_SYMBOL(__get_user_asm_d); +unsigned long long __get_user_asm_l(const void __user *addr, long *err) +{ + register unsigned long long x asm ("D0Re0") = 0; + asm volatile ( + " GETL %0,%t0,[%2]\n" + "1:\n" + " GETL %0,%t0,[%2]\n" + "2:\n" + " .section .fixup,\"ax\"\n" + "3: MOV D0FrT,%3\n" + " SETD [%1],D0FrT\n" + " MOVT D0FrT,#HI(2b)\n" + " JUMP D0FrT,#LO(2b)\n" + " .previous\n" + " .section __ex_table,\"a\"\n" + " .long 1b,3b\n" + " .previous\n" + : "=r" (x) + : "r" (err), "r" (addr), "P" (-EFAULT) + : "D0FrT"); + return x; +} +EXPORT_SYMBOL(__get_user_asm_l); + long __put_user_asm_b(unsigned int x, void __user *addr) { register unsigned int err asm ("D0Re0") = 0; -- cgit v1.2.3-59-g8ed1b From 05510f2b4819398a25ef432d72efa9e95419768a Mon Sep 17 00:00:00 2001 From: Marcin Nowakowski Date: Tue, 7 Mar 2017 14:19:56 +0100 Subject: MIPS: Enable GENERIC_CPU_AUTOPROBE Add missing macros and methods that are required by CONFIG_GENERIC_CPU_AUTOPROBE: MAX_CPU_FEATURES, cpu_have_feature(), cpu_feature(). Also set a default elf platform as currently it is not set for most MIPS platforms resulting in incorrectly specified modalias values in cpu autoprobe ("cpu:type:(null):feature:..."). Export 'elf_hwcap' symbol so that it can be accessed from modules that use module_cpu_feature_match() Signed-off-by: Marcin Nowakowski Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/15395/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 + arch/mips/include/asm/cpufeature.h | 26 ++++++++++++++++++++++++++ arch/mips/kernel/cpu-probe.c | 7 +++++++ 3 files changed, 34 insertions(+) create mode 100644 arch/mips/include/asm/cpufeature.h (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index e0bb576410bb..68af16b72e9c 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -46,6 +46,7 @@ config MIPS select ARCH_DISCARD_MEMBLOCK select GENERIC_SMP_IDLE_THREAD select BUILDTIME_EXTABLE_SORT + select GENERIC_CPU_AUTOPROBE select GENERIC_CLOCKEVENTS select GENERIC_SCHED_CLOCK if !CAVIUM_OCTEON_SOC select GENERIC_CMOS_UPDATE diff --git a/arch/mips/include/asm/cpufeature.h b/arch/mips/include/asm/cpufeature.h new file mode 100644 index 000000000000..c63ec05313c1 --- /dev/null +++ b/arch/mips/include/asm/cpufeature.h @@ -0,0 +1,26 @@ +/* + * CPU feature definitions for module loading, used by + * module_cpu_feature_match(), see uapi/asm/hwcap.h for MIPS CPU features. + * + * 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. + */ + +#ifndef __ASM_CPUFEATURE_H +#define __ASM_CPUFEATURE_H + +#include +#include + +#define MAX_CPU_FEATURES (8 * sizeof(elf_hwcap)) + +#define cpu_feature(x) ilog2(HWCAP_ ## x) + +static inline bool cpu_have_feature(unsigned int num) +{ + return elf_hwcap & (1UL << num); +} + +#endif /* __ASM_CPUFEATURE_H */ diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 12422fd4af23..e57e6850f4dd 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -34,6 +34,7 @@ /* Hardware capabilities */ unsigned int elf_hwcap __read_mostly; +EXPORT_SYMBOL_GPL(elf_hwcap); /* * Get the FPU Implementation/Revision. @@ -1946,6 +1947,12 @@ void cpu_probe(void) struct cpuinfo_mips *c = ¤t_cpu_data; unsigned int cpu = smp_processor_id(); + /* + * Set a default elf platform, cpu probe may later + * overwrite it with a more precise value + */ + set_elf_platform(cpu, "mips"); + c->processor_id = PRID_IMP_UNKNOWN; c->fpu_id = FPIR_IMP_NONE; c->cputype = CPU_UNKNOWN; -- cgit v1.2.3-59-g8ed1b From bfbfa9d61cf29f3579107892c7347c02d891dfec Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 14 Mar 2017 14:21:40 -0700 Subject: MIPS: uasm: Add support for LHU. The follow-on BPF JIT patches use the LHU instruction, so add it. Signed-off-by: David Daney Cc: James Hogan Cc: Alexei Starovoitov Cc: Steven J. Hill Cc: linux-mips@linux-mips.org Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/15743/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/uasm.h | 1 + arch/mips/mm/uasm-mips.c | 1 + arch/mips/mm/uasm.c | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index e9a9e2ade1d2..d91ed5b506ed 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -138,6 +138,7 @@ Ip_u2s3u1(_lb); Ip_u2s3u1(_ld); Ip_u3u1u2(_ldx); Ip_u2s3u1(_lh); +Ip_u2s3u1(_lhu); Ip_u2s3u1(_ll); Ip_u2s3u1(_lld); Ip_u1s2(_lui); diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c index 763d3f1edb8a..2277499fe6ae 100644 --- a/arch/mips/mm/uasm-mips.c +++ b/arch/mips/mm/uasm-mips.c @@ -103,6 +103,7 @@ static struct insn insn_table[] = { { insn_ld, M(ld_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD }, { insn_lh, M(lh_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, + { insn_lhu, M(lhu_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, #ifndef CONFIG_CPU_MIPSR6 { insn_lld, M(lld_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_ll, M(ll_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index a82970442b8a..7f400c8d4645 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -61,7 +61,7 @@ enum opcode { insn_sllv, insn_slt, insn_sltiu, insn_sltu, insn_sra, insn_srl, insn_srlv, insn_subu, insn_sw, insn_sync, insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_wait, insn_wsbh, insn_xor, - insn_xori, insn_yield, insn_lddir, insn_ldpte, + insn_xori, insn_yield, insn_lddir, insn_ldpte, insn_lhu, }; struct insn { @@ -297,6 +297,7 @@ I_u1(_jr) I_u2s3u1(_lb) I_u2s3u1(_ld) I_u2s3u1(_lh) +I_u2s3u1(_lhu) I_u2s3u1(_ll) I_u2s3u1(_lld) I_u1s2(_lui) -- cgit v1.2.3-59-g8ed1b From 4ad701532a758202a422a8588f4d09c058c9a5dc Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 14 Mar 2017 14:21:41 -0700 Subject: MIPS: BPF: Add JIT support for SKF_AD_HATYPE. This let's us pass some additional "modprobe test-bpf" tests with JIT enabled. Reuse the code for SKF_AD_IFINDEX, but substitute the offset and size of the "type" field. Signed-off-by: David Daney Cc: James Hogan Cc: Alexei Starovoitov Cc: Steven J. Hill Cc: linux-mips@linux-mips.org Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/15744/ Signed-off-by: Ralf Baechle --- arch/mips/net/bpf_jit.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/mips/net/bpf_jit.c b/arch/mips/net/bpf_jit.c index 49a2e2226fee..880e329310ee 100644 --- a/arch/mips/net/bpf_jit.c +++ b/arch/mips/net/bpf_jit.c @@ -365,6 +365,12 @@ static inline void emit_half_load(unsigned int reg, unsigned int base, emit_instr(ctx, lh, reg, offset, base); } +static inline void emit_half_load_unsigned(unsigned int reg, unsigned int base, + unsigned int offset, struct jit_ctx *ctx) +{ + emit_instr(ctx, lhu, reg, offset, base); +} + static inline void emit_mul(unsigned int dst, unsigned int src1, unsigned int src2, struct jit_ctx *ctx) { @@ -1112,6 +1118,8 @@ jmp_cmp: break; case BPF_ANC | SKF_AD_IFINDEX: /* A = skb->dev->ifindex */ + case BPF_ANC | SKF_AD_HATYPE: + /* A = skb->dev->type */ ctx->flags |= SEEN_SKB | SEEN_A; off = offsetof(struct sk_buff, dev); /* Load *dev pointer */ @@ -1120,10 +1128,15 @@ jmp_cmp: emit_bcond(MIPS_COND_EQ, r_s0, r_zero, b_imm(prog->len, ctx), ctx); emit_reg_move(r_ret, r_zero, ctx); - BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, - ifindex) != 4); - off = offsetof(struct net_device, ifindex); - emit_load(r_A, r_s0, off, ctx); + if (code == (BPF_ANC | SKF_AD_IFINDEX)) { + BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, ifindex) != 4); + off = offsetof(struct net_device, ifindex); + emit_load(r_A, r_s0, off, ctx); + } else { /* (code == (BPF_ANC | SKF_AD_HATYPE) */ + BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, type) != 2); + off = offsetof(struct net_device, type); + emit_half_load_unsigned(r_A, r_s0, off, ctx); + } break; case BPF_ANC | SKF_AD_MARK: ctx->flags |= SEEN_SKB | SEEN_A; -- cgit v1.2.3-59-g8ed1b From 64b2dd3a8be3ec4e08fd5a3dab0620d9c6c398fe Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 14 Mar 2017 14:21:42 -0700 Subject: MIPS: BPF: Use unsigned access for unsigned SKB fields. The SKB vlan_tci and queue_mapping fields are unsigned, don't sign extend these in the BPF JIT. In the vlan_tci case, the value gets masked so the change is not needed for correctness, but do it anyway for agreement with the types defined in struct sk_buff. Signed-off-by: David Daney Cc: James Hogan Cc: Alexei Starovoitov Cc: Steven J. Hill Cc: linux-mips@linux-mips.org Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/15746/ Signed-off-by: Ralf Baechle --- arch/mips/net/bpf_jit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/net/bpf_jit.c b/arch/mips/net/bpf_jit.c index 880e329310ee..a68cd36a892f 100644 --- a/arch/mips/net/bpf_jit.c +++ b/arch/mips/net/bpf_jit.c @@ -1156,7 +1156,7 @@ jmp_cmp: BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2); off = offsetof(struct sk_buff, vlan_tci); - emit_half_load(r_s0, r_skb, off, ctx); + emit_half_load_unsigned(r_s0, r_skb, off, ctx); if (code == (BPF_ANC | SKF_AD_VLAN_TAG)) { emit_andi(r_A, r_s0, (u16)~VLAN_TAG_PRESENT, ctx); } else { @@ -1183,7 +1183,7 @@ jmp_cmp: BUILD_BUG_ON(offsetof(struct sk_buff, queue_mapping) > 0xff); off = offsetof(struct sk_buff, queue_mapping); - emit_half_load(r_A, r_skb, off, ctx); + emit_half_load_unsigned(r_A, r_skb, off, ctx); break; default: pr_debug("%s: Unhandled opcode: 0x%02x\n", __FILE__, -- cgit v1.2.3-59-g8ed1b From 1ef0910cfd681f0bd0b81f8809935b2006e9cfb9 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 14 Mar 2017 14:21:43 -0700 Subject: MIPS: BPF: Quit clobbering callee saved registers in JIT code. If bpf_needs_clear_a() returns true, only actually clear it if it is ever used. If it is not used, we don't save and restore it, so the clearing has the nasty side effect of clobbering caller state. Also, don't emit stack pointer adjustment instructions if the adjustment amount is zero. Signed-off-by: David Daney Cc: James Hogan Cc: Alexei Starovoitov Cc: Steven J. Hill Cc: linux-mips@linux-mips.org Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/15745/ Signed-off-by: Ralf Baechle --- arch/mips/net/bpf_jit.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/mips/net/bpf_jit.c b/arch/mips/net/bpf_jit.c index a68cd36a892f..44b925005dd3 100644 --- a/arch/mips/net/bpf_jit.c +++ b/arch/mips/net/bpf_jit.c @@ -532,7 +532,8 @@ static void save_bpf_jit_regs(struct jit_ctx *ctx, unsigned offset) u32 sflags, tmp_flags; /* Adjust the stack pointer */ - emit_stack_offset(-align_sp(offset), ctx); + if (offset) + emit_stack_offset(-align_sp(offset), ctx); tmp_flags = sflags = ctx->flags >> SEEN_SREG_SFT; /* sflags is essentially a bitmap */ @@ -584,7 +585,8 @@ static void restore_bpf_jit_regs(struct jit_ctx *ctx, emit_load_stack_reg(r_ra, r_sp, real_off, ctx); /* Restore the sp and discard the scrach memory */ - emit_stack_offset(align_sp(offset), ctx); + if (offset) + emit_stack_offset(align_sp(offset), ctx); } static unsigned int get_stack_depth(struct jit_ctx *ctx) @@ -631,8 +633,14 @@ static void build_prologue(struct jit_ctx *ctx) if (ctx->flags & SEEN_X) emit_jit_reg_move(r_X, r_zero, ctx); - /* Do not leak kernel data to userspace */ - if (bpf_needs_clear_a(&ctx->skf->insns[0])) + /* + * Do not leak kernel data to userspace, we only need to clear + * r_A if it is ever used. In fact if it is never used, we + * will not save/restore it, so clearing it in this case would + * corrupt the state of the caller. + */ + if (bpf_needs_clear_a(&ctx->skf->insns[0]) && + (ctx->flags & SEEN_A)) emit_jit_reg_move(r_A, r_zero, ctx); } -- cgit v1.2.3-59-g8ed1b From a81507c79f4ae9a0f9fb1054b59b62a090620dd9 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 14 Mar 2017 14:21:44 -0700 Subject: MIPS: BPF: Fix multiple problems in JIT skb access helpers. o Socket data is unsigned, so use unsigned accessors instructions. o Fix path result pointer generation arithmetic. o Fix half-word byte swapping code for unsigned semantics. Signed-off-by: David Daney Cc: James Hogan Cc: Alexei Starovoitov Cc: Steven J. Hill Cc: linux-mips@linux-mips.org Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/15747/ Signed-off-by: Ralf Baechle --- arch/mips/net/bpf_jit_asm.S | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/mips/net/bpf_jit_asm.S b/arch/mips/net/bpf_jit_asm.S index 5d2e0c8d29c0..88a2075305d1 100644 --- a/arch/mips/net/bpf_jit_asm.S +++ b/arch/mips/net/bpf_jit_asm.S @@ -90,18 +90,14 @@ FEXPORT(sk_load_half_positive) is_offset_in_header(2, half) /* Offset within header boundaries */ PTR_ADDU t1, $r_skb_data, offset - .set reorder - lh $r_A, 0(t1) - .set noreorder + lhu $r_A, 0(t1) #ifdef CONFIG_CPU_LITTLE_ENDIAN # if defined(__mips_isa_rev) && (__mips_isa_rev >= 2) - wsbh t0, $r_A - seh $r_A, t0 + wsbh $r_A, $r_A # else - sll t0, $r_A, 24 - andi t1, $r_A, 0xff00 - sra t0, t0, 16 - srl t1, t1, 8 + sll t0, $r_A, 8 + srl t1, $r_A, 8 + andi t0, t0, 0xff00 or $r_A, t0, t1 # endif #endif @@ -115,7 +111,7 @@ FEXPORT(sk_load_byte_positive) is_offset_in_header(1, byte) /* Offset within header boundaries */ PTR_ADDU t1, $r_skb_data, offset - lb $r_A, 0(t1) + lbu $r_A, 0(t1) jr $r_ra move $r_ret, zero END(sk_load_byte) @@ -139,6 +135,11 @@ FEXPORT(sk_load_byte_positive) * (void *to) is returned in r_s0 * */ +#ifdef CONFIG_CPU_LITTLE_ENDIAN +#define DS_OFFSET(SIZE) (4 * SZREG) +#else +#define DS_OFFSET(SIZE) ((4 * SZREG) + (4 - SIZE)) +#endif #define bpf_slow_path_common(SIZE) \ /* Quick check. Are we within reasonable boundaries? */ \ LONG_ADDIU $r_s1, $r_skb_len, -SIZE; \ @@ -150,7 +151,7 @@ FEXPORT(sk_load_byte_positive) PTR_LA t0, skb_copy_bits; \ PTR_S $r_ra, (5 * SZREG)($r_sp); \ /* Assign low slot to a2 */ \ - move a2, $r_sp; \ + PTR_ADDIU a2, $r_sp, DS_OFFSET(SIZE); \ jalr t0; \ /* Reset our destination slot (DS but it's ok) */ \ INT_S zero, (4 * SZREG)($r_sp); \ -- cgit v1.2.3-59-g8ed1b From dfa32261fa0ed1821c7d5dbb9e93eddfe311a0d9 Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 17 Feb 2017 11:45:55 -0800 Subject: MIPS: Octeon: Remove vestiges of CONFIG_CAVIUM_OCTEON_2ND_KERNEL This config option never really worked, and has bit-rotted to the point of being completely useless. Remove it completely. Signed-off-by: David Daney Cc: James Hogan Cc: Steven J. Hill Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/15314/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/Kconfig | 9 --------- arch/mips/cavium-octeon/Platform | 4 ---- arch/mips/cavium-octeon/setup.c | 12 +----------- 3 files changed, 1 insertion(+), 24 deletions(-) (limited to 'arch') diff --git a/arch/mips/cavium-octeon/Kconfig b/arch/mips/cavium-octeon/Kconfig index c370426a7322..5c0b56203bae 100644 --- a/arch/mips/cavium-octeon/Kconfig +++ b/arch/mips/cavium-octeon/Kconfig @@ -25,15 +25,6 @@ endif # CPU_CAVIUM_OCTEON if CAVIUM_OCTEON_SOC -config CAVIUM_OCTEON_2ND_KERNEL - bool "Build the kernel to be used as a 2nd kernel on the same chip" - default "n" - help - This option configures this kernel to be linked at a different - address and use the 2nd uart for output. This allows a kernel built - with this option to be run at the same time as one built without this - option. - config CAVIUM_OCTEON_LOCK_L2 bool "Lock often used kernel code in the L2" default "y" diff --git a/arch/mips/cavium-octeon/Platform b/arch/mips/cavium-octeon/Platform index 8a301cb12d68..45be853700e6 100644 --- a/arch/mips/cavium-octeon/Platform +++ b/arch/mips/cavium-octeon/Platform @@ -4,8 +4,4 @@ platform-$(CONFIG_CAVIUM_OCTEON_SOC) += cavium-octeon/ cflags-$(CONFIG_CAVIUM_OCTEON_SOC) += \ -I$(srctree)/arch/mips/include/asm/mach-cavium-octeon -ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL -load-$(CONFIG_CAVIUM_OCTEON_SOC) += 0xffffffff84100000 -else load-$(CONFIG_CAVIUM_OCTEON_SOC) += 0xffffffff81100000 -endif diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index d9dbeb0b165b..a8034d0dcade 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -374,14 +374,8 @@ void octeon_write_lcd(const char *s) */ int octeon_get_boot_uart(void) { - int uart; -#ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL - uart = 1; -#else - uart = (octeon_boot_desc_ptr->flags & OCTEON_BL_FLAG_CONSOLE_UART1) ? + return (octeon_boot_desc_ptr->flags & OCTEON_BL_FLAG_CONSOLE_UART1) ? 1 : 0; -#endif - return uart; } /** @@ -901,14 +895,10 @@ void __init prom_init(void) } if (strstr(arcs_cmdline, "console=") == NULL) { -#ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL - strcat(arcs_cmdline, " console=ttyS0,115200"); -#else if (octeon_uart == 1) strcat(arcs_cmdline, " console=ttyS1,115200"); else strcat(arcs_cmdline, " console=ttyS0,115200"); -#endif } mips_hpt_frequency = octeon_get_clock_rate(); -- cgit v1.2.3-59-g8ed1b From 3377e227af441aff710726437adc20efc359fd9c Mon Sep 17 00:00:00 2001 From: Alex Belits Date: Thu, 16 Feb 2017 17:27:34 -0800 Subject: MIPS: Add 48-bit VA space (and 4-level page tables) for 4K pages. Some users must have 4K pages while needing a 48-bit VA space size. The cleanest way do do this is to go to a 4-level page table for this case. Each page table level using order-0 pages adds 9 bits to the VA size (at 4K pages, so for four levels we get 9 * 4 + 12 == 48-bits. For the 4K page size case only we add support functions for the PUD level of the page table tree, also the TLB exception handlers get an extra level of tree walk. [david.daney@cavium.com: Forward port to v4.10.] [david.daney@cavium.com: Forward port to v4.11.] Signed-off-by: Alex Belits Signed-off-by: David Daney Cc: James Hogan Cc: Alex Belits Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/15312/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 13 +++--- arch/mips/include/asm/pgalloc.h | 26 +++++++++++ arch/mips/include/asm/pgtable-64.h | 88 +++++++++++++++++++++++++++++++++++--- arch/mips/mm/init.c | 3 ++ arch/mips/mm/pgtable-64.c | 33 ++++++++++++-- arch/mips/mm/tlbex.c | 22 ++++++++++ 6 files changed, 172 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 68af16b72e9c..f4dd2c322d4b 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2121,10 +2121,13 @@ config MIPS_VA_BITS_48 bool "48 bits virtual memory" depends on 64BIT help - Support a maximum at least 48 bits of application virtual memory. - Default is 40 bits or less, depending on the CPU. - This option result in a small memory overhead for page tables. - This option is only supported with 16k and 64k page sizes. + Support a maximum at least 48 bits of application virtual + memory. Default is 40 bits or less, depending on the CPU. + For page sizes 16k and above, this option results in a small + memory overhead for page tables. For 4k page size, a fourth + level of page tables is added which imposes both a memory + overhead as well as slower TLB fault handling. + If unsure, say N. choice @@ -2134,7 +2137,6 @@ choice config PAGE_SIZE_4KB bool "4kB" depends on !CPU_LOONGSON2 && !CPU_LOONGSON3 - depends on !MIPS_VA_BITS_48 help This option select the standard 4kB Linux page size. On some R3000-family processors this is the only available page size. Using @@ -2983,6 +2985,7 @@ config HAVE_LATENCYTOP_SUPPORT config PGTABLE_LEVELS int + default 4 if PAGE_SIZE_4KB && MIPS_VA_BITS_48 default 3 if 64BIT && !PAGE_SIZE_64KB default 2 diff --git a/arch/mips/include/asm/pgalloc.h b/arch/mips/include/asm/pgalloc.h index a8705f6c8180..a1bdb1ea5234 100644 --- a/arch/mips/include/asm/pgalloc.h +++ b/arch/mips/include/asm/pgalloc.h @@ -110,6 +110,32 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) #endif +#ifndef __PAGETABLE_PUD_FOLDED + +static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address) +{ + pud_t *pud; + + pud = (pud_t *) __get_free_pages(GFP_KERNEL|__GFP_REPEAT, PUD_ORDER); + if (pud) + pud_init((unsigned long)pud, (unsigned long)invalid_pmd_table); + return pud; +} + +static inline void pud_free(struct mm_struct *mm, pud_t *pud) +{ + free_pages((unsigned long)pud, PUD_ORDER); +} + +static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud) +{ + set_pgd(pgd, __pgd((unsigned long)pud)); +} + +#define __pud_free_tlb(tlb, x, addr) pud_free((tlb)->mm, x) + +#endif /* __PAGETABLE_PUD_FOLDED */ + #define check_pgt_cache() do { } while (0) extern void pagetable_init(void); diff --git a/arch/mips/include/asm/pgtable-64.h b/arch/mips/include/asm/pgtable-64.h index 130a2a6c1531..67fe6dc5211c 100644 --- a/arch/mips/include/asm/pgtable-64.h +++ b/arch/mips/include/asm/pgtable-64.h @@ -20,7 +20,7 @@ #define __ARCH_USE_5LEVEL_HACK #if defined(CONFIG_PAGE_SIZE_64KB) && !defined(CONFIG_MIPS_VA_BITS_48) #include -#else +#elif !(defined(CONFIG_PAGE_SIZE_4KB) && defined(CONFIG_MIPS_VA_BITS_48)) #include #endif @@ -54,9 +54,18 @@ #define PMD_SIZE (1UL << PMD_SHIFT) #define PMD_MASK (~(PMD_SIZE-1)) +# ifdef __PAGETABLE_PUD_FOLDED +# define PGDIR_SHIFT (PMD_SHIFT + (PAGE_SHIFT + PMD_ORDER - 3)) +# endif +#endif -#define PGDIR_SHIFT (PMD_SHIFT + (PAGE_SHIFT + PMD_ORDER - 3)) +#ifndef __PAGETABLE_PUD_FOLDED +#define PUD_SHIFT (PMD_SHIFT + (PAGE_SHIFT + PMD_ORDER - 3)) +#define PUD_SIZE (1UL << PUD_SHIFT) +#define PUD_MASK (~(PUD_SIZE-1)) +#define PGDIR_SHIFT (PUD_SHIFT + (PAGE_SHIFT + PUD_ORDER - 3)) #endif + #define PGDIR_SIZE (1UL << PGDIR_SHIFT) #define PGDIR_MASK (~(PGDIR_SIZE-1)) @@ -79,8 +88,13 @@ * of virtual address space. */ #ifdef CONFIG_PAGE_SIZE_4KB -#define PGD_ORDER 1 -#define PUD_ORDER aieeee_attempt_to_allocate_pud +# ifdef CONFIG_MIPS_VA_BITS_48 +# define PGD_ORDER 0 +# define PUD_ORDER 0 +# else +# define PGD_ORDER 1 +# define PUD_ORDER aieeee_attempt_to_allocate_pud +# endif #define PMD_ORDER 0 #define PTE_ORDER 0 #endif @@ -118,6 +132,9 @@ #endif #define PTRS_PER_PGD ((PAGE_SIZE << PGD_ORDER) / sizeof(pgd_t)) +#ifndef __PAGETABLE_PUD_FOLDED +#define PTRS_PER_PUD ((PAGE_SIZE << PUD_ORDER) / sizeof(pud_t)) +#endif #ifndef __PAGETABLE_PMD_FOLDED #define PTRS_PER_PMD ((PAGE_SIZE << PMD_ORDER) / sizeof(pmd_t)) #endif @@ -134,7 +151,7 @@ #define VMALLOC_START (MAP_BASE + (2 * PAGE_SIZE)) #define VMALLOC_END \ (MAP_BASE + \ - min(PTRS_PER_PGD * PTRS_PER_PMD * PTRS_PER_PTE * PAGE_SIZE, \ + min(PTRS_PER_PGD * PTRS_PER_PUD * PTRS_PER_PMD * PTRS_PER_PTE * PAGE_SIZE, \ (1UL << cpu_vmbits)) - (1UL << 32)) #if defined(CONFIG_MODULES) && defined(KBUILD_64BIT_SYM32) && \ @@ -150,12 +167,72 @@ #define pmd_ERROR(e) \ printk("%s:%d: bad pmd %016lx.\n", __FILE__, __LINE__, pmd_val(e)) #endif +#ifndef __PAGETABLE_PUD_FOLDED +#define pud_ERROR(e) \ + printk("%s:%d: bad pud %016lx.\n", __FILE__, __LINE__, pud_val(e)) +#endif #define pgd_ERROR(e) \ printk("%s:%d: bad pgd %016lx.\n", __FILE__, __LINE__, pgd_val(e)) extern pte_t invalid_pte_table[PTRS_PER_PTE]; extern pte_t empty_bad_page_table[PTRS_PER_PTE]; +#ifndef __PAGETABLE_PUD_FOLDED +/* + * For 4-level pagetables we defines these ourselves, for 3-level the + * definitions are below, for 2-level the + * definitions are supplied by . + */ +typedef struct { unsigned long pud; } pud_t; +#define pud_val(x) ((x).pud) +#define __pud(x) ((pud_t) { (x) }) + +extern pud_t invalid_pud_table[PTRS_PER_PUD]; + +/* + * Empty pgd entries point to the invalid_pud_table. + */ +static inline int pgd_none(pgd_t pgd) +{ + return pgd_val(pgd) == (unsigned long)invalid_pud_table; +} + +static inline int pgd_bad(pgd_t pgd) +{ + if (unlikely(pgd_val(pgd) & ~PAGE_MASK)) + return 1; + + return 0; +} + +static inline int pgd_present(pgd_t pgd) +{ + return pgd_val(pgd) != (unsigned long)invalid_pud_table; +} + +static inline void pgd_clear(pgd_t *pgdp) +{ + pgd_val(*pgdp) = (unsigned long)invalid_pud_table; +} + +#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)) + +static inline unsigned long pgd_page_vaddr(pgd_t pgd) +{ + return pgd_val(pgd); +} + +static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address) +{ + return (pud_t *)pgd_page_vaddr(*pgd) + pud_index(address); +} + +static inline void set_pgd(pgd_t *pgd, pgd_t pgdval) +{ + *pgd = pgdval; +} + +#endif #ifndef __PAGETABLE_PMD_FOLDED /* @@ -281,6 +358,7 @@ static inline pmd_t *pmd_offset(pud_t * pud, unsigned long address) * Initialize a new pgd / pmd table with invalid pointers. */ extern void pgd_init(unsigned long page); +extern void pud_init(unsigned long page, unsigned long pagetable); extern void pmd_init(unsigned long page, unsigned long pagetable); /* diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index aa75849c36bc..37aa931501bf 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -537,6 +537,9 @@ unsigned long pgd_current[NR_CPUS]; * it in the linker script. */ pgd_t swapper_pg_dir[_PTRS_PER_PGD] __section(.bss..swapper_pg_dir); +#ifndef __PAGETABLE_PUD_FOLDED +pud_t invalid_pud_table[PTRS_PER_PUD] __page_aligned_bss; +#endif #ifndef __PAGETABLE_PMD_FOLDED pmd_t invalid_pmd_table[PTRS_PER_PMD] __page_aligned_bss; EXPORT_SYMBOL_GPL(invalid_pmd_table); diff --git a/arch/mips/mm/pgtable-64.c b/arch/mips/mm/pgtable-64.c index 0ae7b28b4db5..6fd6e96fdebb 100644 --- a/arch/mips/mm/pgtable-64.c +++ b/arch/mips/mm/pgtable-64.c @@ -19,10 +19,12 @@ void pgd_init(unsigned long page) unsigned long *p, *end; unsigned long entry; -#ifdef __PAGETABLE_PMD_FOLDED - entry = (unsigned long)invalid_pte_table; -#else +#if !defined(__PAGETABLE_PUD_FOLDED) + entry = (unsigned long)invalid_pud_table; +#elif !defined(__PAGETABLE_PMD_FOLDED) entry = (unsigned long)invalid_pmd_table; +#else + entry = (unsigned long)invalid_pte_table; #endif p = (unsigned long *) page; @@ -64,6 +66,28 @@ void pmd_init(unsigned long addr, unsigned long pagetable) EXPORT_SYMBOL_GPL(pmd_init); #endif +#ifndef __PAGETABLE_PUD_FOLDED +void pud_init(unsigned long addr, unsigned long pagetable) +{ + unsigned long *p, *end; + + p = (unsigned long *)addr; + end = p + PTRS_PER_PUD; + + do { + p[0] = pagetable; + p[1] = pagetable; + p[2] = pagetable; + p[3] = pagetable; + p[4] = pagetable; + p += 8; + p[-3] = pagetable; + p[-2] = pagetable; + p[-1] = pagetable; + } while (p != end); +} +#endif + pmd_t mk_pmd(struct page *page, pgprot_t prot) { pmd_t pmd; @@ -87,6 +111,9 @@ void __init pagetable_init(void) /* Initialize the entire pgd. */ pgd_init((unsigned long)swapper_pg_dir); +#ifndef __PAGETABLE_PUD_FOLDED + pud_init((unsigned long)invalid_pud_table, (unsigned long)invalid_pmd_table); +#endif #ifndef __PAGETABLE_PMD_FOLDED pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table); #endif diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 4f642e07c2b1..ed1c5297547a 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -865,6 +865,13 @@ void build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, uasm_i_andi(p, tmp, tmp, (PTRS_PER_PGD - 1)<<3); uasm_i_daddu(p, ptr, ptr, tmp); /* add in pgd offset */ +#ifndef __PAGETABLE_PUD_FOLDED + uasm_i_dmfc0(p, tmp, C0_BADVADDR); /* get faulting address */ + uasm_i_ld(p, ptr, 0, ptr); /* get pud pointer */ + uasm_i_dsrl_safe(p, tmp, tmp, PUD_SHIFT - 3); /* get pud offset in bytes */ + uasm_i_andi(p, tmp, tmp, (PTRS_PER_PUD - 1) << 3); + uasm_i_daddu(p, ptr, ptr, tmp); /* add in pud offset */ +#endif #ifndef __PAGETABLE_PMD_FOLDED uasm_i_dmfc0(p, tmp, C0_BADVADDR); /* get faulting address */ uasm_i_ld(p, ptr, 0, ptr); /* get pmd pointer */ @@ -1184,6 +1191,21 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, uasm_i_ld(p, LOC_PTEP, 0, ptr); /* get pmd pointer */ } +#ifndef __PAGETABLE_PUD_FOLDED + /* get pud offset in bytes */ + uasm_i_dsrl_safe(p, scratch, tmp, PUD_SHIFT - 3); + uasm_i_andi(p, scratch, scratch, (PTRS_PER_PUD - 1) << 3); + + if (use_lwx_insns()) { + UASM_i_LWX(p, ptr, scratch, ptr); + } else { + uasm_i_daddu(p, ptr, ptr, scratch); /* add in pmd offset */ + UASM_i_LW(p, ptr, 0, ptr); + } + /* ptr contains a pointer to PMD entry */ + /* tmp contains the address */ +#endif + #ifndef __PAGETABLE_PMD_FOLDED /* get pmd offset in bytes */ uasm_i_dsrl_safe(p, scratch, tmp, PMD_SHIFT - 3); -- cgit v1.2.3-59-g8ed1b From 15f6847923a87040ebe962e34eea48711c5d0582 Mon Sep 17 00:00:00 2001 From: "Steven J. Hill" Date: Thu, 9 Mar 2017 08:14:15 -0600 Subject: MIPS: Octeon: Remove unused L2C types and macros. Remove all unused bitfields and macros. Convert the remaining bitfields to use __BITFIELD_FIELD instead of #ifdef. [ralf@linux-mips.org: Add inclusions of as necessary.] Signed-off-by: Steven J. Hill Acked-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/15403/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/executive/cvmx-l2c.c | 139 +- arch/mips/cavium-octeon/executive/octeon-model.c | 21 +- arch/mips/include/asm/octeon/cvmx-l2c-defs.h | 3193 +--------------------- arch/mips/include/asm/octeon/cvmx-l2c.h | 59 +- arch/mips/include/asm/octeon/cvmx-l2d-defs.h | 526 ---- arch/mips/include/asm/octeon/cvmx-l2t-defs.h | 286 +- arch/mips/include/asm/octeon/cvmx.h | 3 +- 7 files changed, 305 insertions(+), 3922 deletions(-) delete mode 100644 arch/mips/include/asm/octeon/cvmx-l2d-defs.h (limited to 'arch') diff --git a/arch/mips/cavium-octeon/executive/cvmx-l2c.c b/arch/mips/cavium-octeon/executive/cvmx-l2c.c index 89b5273299ab..f091c9b70603 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-l2c.c +++ b/arch/mips/cavium-octeon/executive/cvmx-l2c.c @@ -4,7 +4,7 @@ * Contact: support@caviumnetworks.com * This file is part of the OCTEON SDK * - * Copyright (c) 2003-2010 Cavium Networks + * Copyright (c) 2003-2017 Cavium, Inc. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as @@ -239,6 +239,7 @@ uint64_t cvmx_l2c_read_perf(uint32_t counter) else { uint64_t counter = 0; int tad; + for (tad = 0; tad < CVMX_L2C_TADS; tad++) counter += cvmx_read_csr(CVMX_L2C_TADX_PFC0(tad)); return counter; @@ -249,6 +250,7 @@ uint64_t cvmx_l2c_read_perf(uint32_t counter) else { uint64_t counter = 0; int tad; + for (tad = 0; tad < CVMX_L2C_TADS; tad++) counter += cvmx_read_csr(CVMX_L2C_TADX_PFC1(tad)); return counter; @@ -259,6 +261,7 @@ uint64_t cvmx_l2c_read_perf(uint32_t counter) else { uint64_t counter = 0; int tad; + for (tad = 0; tad < CVMX_L2C_TADS; tad++) counter += cvmx_read_csr(CVMX_L2C_TADX_PFC2(tad)); return counter; @@ -270,6 +273,7 @@ uint64_t cvmx_l2c_read_perf(uint32_t counter) else { uint64_t counter = 0; int tad; + for (tad = 0; tad < CVMX_L2C_TADS; tad++) counter += cvmx_read_csr(CVMX_L2C_TADX_PFC3(tad)); return counter; @@ -301,7 +305,7 @@ static void fault_in(uint64_t addr, int len) */ CVMX_DCACHE_INVALIDATE; while (len > 0) { - ACCESS_ONCE(*ptr); + READ_ONCE(*ptr); len -= CVMX_CACHE_LINE_SIZE; ptr += CVMX_CACHE_LINE_SIZE; } @@ -375,7 +379,9 @@ int cvmx_l2c_lock_line(uint64_t addr) if (((union cvmx_l2c_cfg)(cvmx_read_csr(CVMX_L2C_CFG))).s.idxalias) { int alias_shift = CVMX_L2C_IDX_ADDR_SHIFT + 2 * CVMX_L2_SET_BITS - 1; uint64_t addr_tmp = addr ^ (addr & ((1 << alias_shift) - 1)) >> CVMX_L2_SET_BITS; + lckbase.s.lck_base = addr_tmp >> 7; + } else { lckbase.s.lck_base = addr >> 7; } @@ -435,6 +441,7 @@ void cvmx_l2c_flush(void) /* These may look like constants, but they aren't... */ int assoc_shift = CVMX_L2C_TAG_ADDR_ALIAS_SHIFT; int set_shift = CVMX_L2C_IDX_ADDR_SHIFT; + for (set = 0; set < n_set; set++) { for (assoc = 0; assoc < n_assoc; assoc++) { address = CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, @@ -519,89 +526,49 @@ int cvmx_l2c_unlock_mem_region(uint64_t start, uint64_t len) union __cvmx_l2c_tag { uint64_t u64; struct cvmx_l2c_tag_cn50xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved:40; - uint64_t V:1; /* Line valid */ - uint64_t D:1; /* Line dirty */ - uint64_t L:1; /* Line locked */ - uint64_t U:1; /* Use, LRU eviction */ - uint64_t addr:20; /* Phys mem addr (33..14) */ -#else - uint64_t addr:20; /* Phys mem addr (33..14) */ - uint64_t U:1; /* Use, LRU eviction */ - uint64_t L:1; /* Line locked */ - uint64_t D:1; /* Line dirty */ - uint64_t V:1; /* Line valid */ - uint64_t reserved:40; -#endif + __BITFIELD_FIELD(uint64_t reserved:40, + __BITFIELD_FIELD(uint64_t V:1, /* Line valid */ + __BITFIELD_FIELD(uint64_t D:1, /* Line dirty */ + __BITFIELD_FIELD(uint64_t L:1, /* Line locked */ + __BITFIELD_FIELD(uint64_t U:1, /* Use, LRU eviction */ + __BITFIELD_FIELD(uint64_t addr:20, /* Phys addr (33..14) */ + ;)))))) } cn50xx; struct cvmx_l2c_tag_cn30xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved:41; - uint64_t V:1; /* Line valid */ - uint64_t D:1; /* Line dirty */ - uint64_t L:1; /* Line locked */ - uint64_t U:1; /* Use, LRU eviction */ - uint64_t addr:19; /* Phys mem addr (33..15) */ -#else - uint64_t addr:19; /* Phys mem addr (33..15) */ - uint64_t U:1; /* Use, LRU eviction */ - uint64_t L:1; /* Line locked */ - uint64_t D:1; /* Line dirty */ - uint64_t V:1; /* Line valid */ - uint64_t reserved:41; -#endif + __BITFIELD_FIELD(uint64_t reserved:41, + __BITFIELD_FIELD(uint64_t V:1, /* Line valid */ + __BITFIELD_FIELD(uint64_t D:1, /* Line dirty */ + __BITFIELD_FIELD(uint64_t L:1, /* Line locked */ + __BITFIELD_FIELD(uint64_t U:1, /* Use, LRU eviction */ + __BITFIELD_FIELD(uint64_t addr:19, /* Phys addr (33..15) */ + ;)))))) } cn30xx; struct cvmx_l2c_tag_cn31xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved:42; - uint64_t V:1; /* Line valid */ - uint64_t D:1; /* Line dirty */ - uint64_t L:1; /* Line locked */ - uint64_t U:1; /* Use, LRU eviction */ - uint64_t addr:18; /* Phys mem addr (33..16) */ -#else - uint64_t addr:18; /* Phys mem addr (33..16) */ - uint64_t U:1; /* Use, LRU eviction */ - uint64_t L:1; /* Line locked */ - uint64_t D:1; /* Line dirty */ - uint64_t V:1; /* Line valid */ - uint64_t reserved:42; -#endif + __BITFIELD_FIELD(uint64_t reserved:42, + __BITFIELD_FIELD(uint64_t V:1, /* Line valid */ + __BITFIELD_FIELD(uint64_t D:1, /* Line dirty */ + __BITFIELD_FIELD(uint64_t L:1, /* Line locked */ + __BITFIELD_FIELD(uint64_t U:1, /* Use, LRU eviction */ + __BITFIELD_FIELD(uint64_t addr:18, /* Phys addr (33..16) */ + ;)))))) } cn31xx; struct cvmx_l2c_tag_cn38xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved:43; - uint64_t V:1; /* Line valid */ - uint64_t D:1; /* Line dirty */ - uint64_t L:1; /* Line locked */ - uint64_t U:1; /* Use, LRU eviction */ - uint64_t addr:17; /* Phys mem addr (33..17) */ -#else - uint64_t addr:17; /* Phys mem addr (33..17) */ - uint64_t U:1; /* Use, LRU eviction */ - uint64_t L:1; /* Line locked */ - uint64_t D:1; /* Line dirty */ - uint64_t V:1; /* Line valid */ - uint64_t reserved:43; -#endif + __BITFIELD_FIELD(uint64_t reserved:43, + __BITFIELD_FIELD(uint64_t V:1, /* Line valid */ + __BITFIELD_FIELD(uint64_t D:1, /* Line dirty */ + __BITFIELD_FIELD(uint64_t L:1, /* Line locked */ + __BITFIELD_FIELD(uint64_t U:1, /* Use, LRU eviction */ + __BITFIELD_FIELD(uint64_t addr:17, /* Phys addr (33..17) */ + ;)))))) } cn38xx; struct cvmx_l2c_tag_cn58xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved:44; - uint64_t V:1; /* Line valid */ - uint64_t D:1; /* Line dirty */ - uint64_t L:1; /* Line locked */ - uint64_t U:1; /* Use, LRU eviction */ - uint64_t addr:16; /* Phys mem addr (33..18) */ -#else - uint64_t addr:16; /* Phys mem addr (33..18) */ - uint64_t U:1; /* Use, LRU eviction */ - uint64_t L:1; /* Line locked */ - uint64_t D:1; /* Line dirty */ - uint64_t V:1; /* Line valid */ - uint64_t reserved:44; -#endif + __BITFIELD_FIELD(uint64_t reserved:44, + __BITFIELD_FIELD(uint64_t V:1, /* Line valid */ + __BITFIELD_FIELD(uint64_t D:1, /* Line dirty */ + __BITFIELD_FIELD(uint64_t L:1, /* Line locked */ + __BITFIELD_FIELD(uint64_t U:1, /* Use, LRU eviction */ + __BITFIELD_FIELD(uint64_t addr:16, /* Phys addr (33..18) */ + ;)))))) } cn58xx; struct cvmx_l2c_tag_cn58xx cn56xx; /* 2048 sets */ struct cvmx_l2c_tag_cn31xx cn52xx; /* 512 sets */ @@ -629,8 +596,8 @@ static union __cvmx_l2c_tag __read_l2_tag(uint64_t assoc, uint64_t index) union __cvmx_l2c_tag tag_val; uint64_t dbg_addr = CVMX_L2C_DBG; unsigned long flags; - union cvmx_l2c_dbg debug_val; + debug_val.u64 = 0; /* * For low core count parts, the core number is always small @@ -683,8 +650,8 @@ static union __cvmx_l2c_tag __read_l2_tag(uint64_t assoc, uint64_t index) union cvmx_l2c_tag cvmx_l2c_get_tag(uint32_t association, uint32_t index) { union cvmx_l2c_tag tag; - tag.u64 = 0; + tag.u64 = 0; if ((int)association >= cvmx_l2c_get_num_assoc()) { cvmx_dprintf("ERROR: cvmx_l2c_get_tag association out of range\n"); return tag; @@ -767,10 +734,12 @@ uint32_t cvmx_l2c_address_to_index(uint64_t addr) if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) { union cvmx_l2c_ctl l2c_ctl; + l2c_ctl.u64 = cvmx_read_csr(CVMX_L2C_CTL); indxalias = !l2c_ctl.s.disidxalias; } else { union cvmx_l2c_cfg l2c_cfg; + l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG); indxalias = l2c_cfg.s.idxalias; } @@ -778,6 +747,7 @@ uint32_t cvmx_l2c_address_to_index(uint64_t addr) if (indxalias) { if (OCTEON_IS_MODEL(OCTEON_CN63XX)) { uint32_t a_14_12 = (idx / (CVMX_L2C_MEMBANK_SELECT_SIZE/(1<> 35) & 0x1) + if ((l2d_fus3 >> 35) & 0x1) l2_assoc = l2_assoc >> 2; - else if ((val.u64 >> 34) & 0x1) + else if ((l2d_fus3 >> 34) & 0x1) l2_assoc = l2_assoc >> 1; } return l2_assoc; diff --git a/arch/mips/cavium-octeon/executive/octeon-model.c b/arch/mips/cavium-octeon/executive/octeon-model.c index d08a2bce653c..341052387b49 100644 --- a/arch/mips/cavium-octeon/executive/octeon-model.c +++ b/arch/mips/cavium-octeon/executive/octeon-model.c @@ -4,7 +4,7 @@ * Contact: support@caviumnetworks.com * This file is part of the OCTEON SDK * - * Copyright (c) 2003-2010 Cavium Networks + * Copyright (c) 2003-2017 Cavium, Inc. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as @@ -63,16 +63,15 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id, char pass[4]; int clock_mhz; const char *suffix; - union cvmx_l2d_fus3 fus3; int num_cores; union cvmx_mio_fus_dat2 fus_dat2; union cvmx_mio_fus_dat3 fus_dat3; char fuse_model[10]; uint32_t fuse_data = 0; + uint64_t l2d_fus3 = 0; - fus3.u64 = 0; if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX)) - fus3.u64 = cvmx_read_csr(CVMX_L2D_FUS3); + l2d_fus3 = (cvmx_read_csr(CVMX_L2D_FUS3) >> 34) & 0x3; fus_dat2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2); fus_dat3.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT3); num_cores = cvmx_octeon_num_cores(); @@ -192,7 +191,7 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id, /* Now figure out the family, the first two digits */ switch ((chip_id >> 8) & 0xff) { case 0: /* CN38XX, CN37XX or CN36XX */ - if (fus3.cn38xx.crip_512k) { + if (l2d_fus3) { /* * For some unknown reason, the 16 core one is * called 37 instead of 36. @@ -223,7 +222,7 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id, } break; case 1: /* CN31XX or CN3020 */ - if ((chip_id & 0x10) || fus3.cn31xx.crip_128k) + if ((chip_id & 0x10) || l2d_fus3) family = "30"; else family = "31"; @@ -246,7 +245,7 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id, case 2: /* CN3010 or CN3005 */ family = "30"; /* A chip with half cache is an 05 */ - if (fus3.cn30xx.crip_64k) + if (l2d_fus3) core_model = "05"; /* * This series of chips didn't follow the standard @@ -267,7 +266,7 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id, case 3: /* CN58XX */ family = "58"; /* Special case. 4 core, half cache (CP with half cache) */ - if ((num_cores == 4) && fus3.cn58xx.crip_1024k && !strncmp(suffix, "CP", 2)) + if ((num_cores == 4) && l2d_fus3 && !strncmp(suffix, "CP", 2)) core_model = "29"; /* Pass 1 uses different encodings for pass numbers */ @@ -290,7 +289,7 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id, break; case 4: /* CN57XX, CN56XX, CN55XX, CN54XX */ if (fus_dat2.cn56xx.raid_en) { - if (fus3.cn56xx.crip_1024k) + if (l2d_fus3) family = "55"; else family = "57"; @@ -309,7 +308,7 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id, if (fus_dat3.cn56xx.bar2_en) suffix = "NSPB2"; } - if (fus3.cn56xx.crip_1024k) + if (l2d_fus3) family = "54"; else family = "56"; @@ -319,7 +318,7 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id, family = "50"; break; case 7: /* CN52XX */ - if (fus3.cn52xx.crip_256k) + if (l2d_fus3) family = "51"; else family = "52"; diff --git a/arch/mips/include/asm/octeon/cvmx-l2c-defs.h b/arch/mips/include/asm/octeon/cvmx-l2c-defs.h index 10262cb6ff50..d045973ddb33 100644 --- a/arch/mips/include/asm/octeon/cvmx-l2c-defs.h +++ b/arch/mips/include/asm/octeon/cvmx-l2c-defs.h @@ -4,7 +4,7 @@ * Contact: support@caviumnetworks.com * This file is part of the OCTEON SDK * - * Copyright (c) 2003-2012 Cavium Networks + * Copyright (c) 2003-2017 Cavium, Inc. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as @@ -28,3140 +28,177 @@ #ifndef __CVMX_L2C_DEFS_H__ #define __CVMX_L2C_DEFS_H__ -#define CVMX_L2C_BIG_CTL (CVMX_ADD_IO_SEG(0x0001180080800030ull)) -#define CVMX_L2C_BST (CVMX_ADD_IO_SEG(0x00011800808007F8ull)) -#define CVMX_L2C_BST0 (CVMX_ADD_IO_SEG(0x00011800800007F8ull)) -#define CVMX_L2C_BST1 (CVMX_ADD_IO_SEG(0x00011800800007F0ull)) -#define CVMX_L2C_BST2 (CVMX_ADD_IO_SEG(0x00011800800007E8ull)) -#define CVMX_L2C_BST_MEMX(block_id) (CVMX_ADD_IO_SEG(0x0001180080C007F8ull) + ((block_id) & 3) * 0x40000ull) -#define CVMX_L2C_BST_TDTX(block_id) (CVMX_ADD_IO_SEG(0x0001180080A007F0ull) + ((block_id) & 3) * 0x40000ull) -#define CVMX_L2C_BST_TTGX(block_id) (CVMX_ADD_IO_SEG(0x0001180080A007F8ull) + ((block_id) & 3) * 0x40000ull) +#include + +#define CVMX_L2C_DBG (CVMX_ADD_IO_SEG(0x0001180080000030ull)) #define CVMX_L2C_CFG (CVMX_ADD_IO_SEG(0x0001180080000000ull)) -#define CVMX_L2C_COP0_MAPX(offset) (CVMX_ADD_IO_SEG(0x0001180080940000ull) + ((offset) & 16383) * 8) #define CVMX_L2C_CTL (CVMX_ADD_IO_SEG(0x0001180080800000ull)) -#define CVMX_L2C_DBG (CVMX_ADD_IO_SEG(0x0001180080000030ull)) -#define CVMX_L2C_DUT (CVMX_ADD_IO_SEG(0x0001180080000050ull)) -#define CVMX_L2C_DUT_MAPX(offset) (CVMX_ADD_IO_SEG(0x0001180080E00000ull) + ((offset) & 8191) * 8) -#define CVMX_L2C_ERR_TDTX(block_id) (CVMX_ADD_IO_SEG(0x0001180080A007E0ull) + ((block_id) & 3) * 0x40000ull) -#define CVMX_L2C_ERR_TTGX(block_id) (CVMX_ADD_IO_SEG(0x0001180080A007E8ull) + ((block_id) & 3) * 0x40000ull) -#define CVMX_L2C_ERR_VBFX(block_id) (CVMX_ADD_IO_SEG(0x0001180080C007F0ull) + ((block_id) & 3) * 0x40000ull) -#define CVMX_L2C_ERR_XMC (CVMX_ADD_IO_SEG(0x00011800808007D8ull)) -#define CVMX_L2C_GRPWRR0 (CVMX_ADD_IO_SEG(0x00011800800000C8ull)) -#define CVMX_L2C_GRPWRR1 (CVMX_ADD_IO_SEG(0x00011800800000D0ull)) -#define CVMX_L2C_INT_EN (CVMX_ADD_IO_SEG(0x0001180080000100ull)) -#define CVMX_L2C_INT_ENA (CVMX_ADD_IO_SEG(0x0001180080800020ull)) -#define CVMX_L2C_INT_REG (CVMX_ADD_IO_SEG(0x0001180080800018ull)) -#define CVMX_L2C_INT_STAT (CVMX_ADD_IO_SEG(0x00011800800000F8ull)) -#define CVMX_L2C_IOCX_PFC(block_id) (CVMX_ADD_IO_SEG(0x0001180080800420ull)) -#define CVMX_L2C_IORX_PFC(block_id) (CVMX_ADD_IO_SEG(0x0001180080800428ull)) #define CVMX_L2C_LCKBASE (CVMX_ADD_IO_SEG(0x0001180080000058ull)) #define CVMX_L2C_LCKOFF (CVMX_ADD_IO_SEG(0x0001180080000060ull)) -#define CVMX_L2C_LFB0 (CVMX_ADD_IO_SEG(0x0001180080000038ull)) -#define CVMX_L2C_LFB1 (CVMX_ADD_IO_SEG(0x0001180080000040ull)) -#define CVMX_L2C_LFB2 (CVMX_ADD_IO_SEG(0x0001180080000048ull)) -#define CVMX_L2C_LFB3 (CVMX_ADD_IO_SEG(0x00011800800000B8ull)) -#define CVMX_L2C_OOB (CVMX_ADD_IO_SEG(0x00011800800000D8ull)) -#define CVMX_L2C_OOB1 (CVMX_ADD_IO_SEG(0x00011800800000E0ull)) -#define CVMX_L2C_OOB2 (CVMX_ADD_IO_SEG(0x00011800800000E8ull)) -#define CVMX_L2C_OOB3 (CVMX_ADD_IO_SEG(0x00011800800000F0ull)) +#define CVMX_L2C_PFCTL (CVMX_ADD_IO_SEG(0x0001180080000090ull)) +#define CVMX_L2C_PFCX(offset) (CVMX_ADD_IO_SEG(0x0001180080000098ull) + \ + ((offset) & 3) * 8) #define CVMX_L2C_PFC0 CVMX_L2C_PFCX(0) #define CVMX_L2C_PFC1 CVMX_L2C_PFCX(1) #define CVMX_L2C_PFC2 CVMX_L2C_PFCX(2) #define CVMX_L2C_PFC3 CVMX_L2C_PFCX(3) -#define CVMX_L2C_PFCTL (CVMX_ADD_IO_SEG(0x0001180080000090ull)) -#define CVMX_L2C_PFCX(offset) (CVMX_ADD_IO_SEG(0x0001180080000098ull) + ((offset) & 3) * 8) -#define CVMX_L2C_PPGRP (CVMX_ADD_IO_SEG(0x00011800800000C0ull)) -#define CVMX_L2C_QOS_IOBX(offset) (CVMX_ADD_IO_SEG(0x0001180080880200ull) + ((offset) & 1) * 8) -#define CVMX_L2C_QOS_PPX(offset) (CVMX_ADD_IO_SEG(0x0001180080880000ull) + ((offset) & 31) * 8) -#define CVMX_L2C_QOS_WGT (CVMX_ADD_IO_SEG(0x0001180080800008ull)) -#define CVMX_L2C_RSCX_PFC(offset) (CVMX_ADD_IO_SEG(0x0001180080800410ull) + ((offset) & 3) * 64) -#define CVMX_L2C_RSDX_PFC(offset) (CVMX_ADD_IO_SEG(0x0001180080800418ull) + ((offset) & 3) * 64) #define CVMX_L2C_SPAR0 (CVMX_ADD_IO_SEG(0x0001180080000068ull)) #define CVMX_L2C_SPAR1 (CVMX_ADD_IO_SEG(0x0001180080000070ull)) #define CVMX_L2C_SPAR2 (CVMX_ADD_IO_SEG(0x0001180080000078ull)) #define CVMX_L2C_SPAR3 (CVMX_ADD_IO_SEG(0x0001180080000080ull)) #define CVMX_L2C_SPAR4 (CVMX_ADD_IO_SEG(0x0001180080000088ull)) -#define CVMX_L2C_TADX_ECC0(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00018ull) + ((block_id) & 3) * 0x40000ull) -#define CVMX_L2C_TADX_ECC1(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00020ull) + ((block_id) & 3) * 0x40000ull) -#define CVMX_L2C_TADX_IEN(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00000ull) + ((block_id) & 3) * 0x40000ull) -#define CVMX_L2C_TADX_INT(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00028ull) + ((block_id) & 3) * 0x40000ull) -#define CVMX_L2C_TADX_PFC0(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00400ull) + ((block_id) & 3) * 0x40000ull) -#define CVMX_L2C_TADX_PFC1(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00408ull) + ((block_id) & 3) * 0x40000ull) -#define CVMX_L2C_TADX_PFC2(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00410ull) + ((block_id) & 3) * 0x40000ull) -#define CVMX_L2C_TADX_PFC3(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00418ull) + ((block_id) & 3) * 0x40000ull) -#define CVMX_L2C_TADX_PRF(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00008ull) + ((block_id) & 3) * 0x40000ull) -#define CVMX_L2C_TADX_TAG(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00010ull) + ((block_id) & 3) * 0x40000ull) -#define CVMX_L2C_VER_ID (CVMX_ADD_IO_SEG(0x00011800808007E0ull)) -#define CVMX_L2C_VER_IOB (CVMX_ADD_IO_SEG(0x00011800808007F0ull)) -#define CVMX_L2C_VER_MSC (CVMX_ADD_IO_SEG(0x00011800808007D0ull)) -#define CVMX_L2C_VER_PP (CVMX_ADD_IO_SEG(0x00011800808007E8ull)) -#define CVMX_L2C_VIRTID_IOBX(offset) (CVMX_ADD_IO_SEG(0x00011800808C0200ull) + ((offset) & 1) * 8) -#define CVMX_L2C_VIRTID_PPX(offset) (CVMX_ADD_IO_SEG(0x00011800808C0000ull) + ((offset) & 31) * 8) -#define CVMX_L2C_VRT_CTL (CVMX_ADD_IO_SEG(0x0001180080800010ull)) -#define CVMX_L2C_VRT_MEMX(offset) (CVMX_ADD_IO_SEG(0x0001180080900000ull) + ((offset) & 1023) * 8) -#define CVMX_L2C_WPAR_IOBX(offset) (CVMX_ADD_IO_SEG(0x0001180080840200ull) + ((offset) & 1) * 8) -#define CVMX_L2C_WPAR_PPX(offset) (CVMX_ADD_IO_SEG(0x0001180080840000ull) + ((offset) & 31) * 8) -#define CVMX_L2C_XMCX_PFC(offset) (CVMX_ADD_IO_SEG(0x0001180080800400ull) + ((offset) & 3) * 64) -#define CVMX_L2C_XMC_CMD (CVMX_ADD_IO_SEG(0x0001180080800028ull)) -#define CVMX_L2C_XMDX_PFC(offset) (CVMX_ADD_IO_SEG(0x0001180080800408ull) + ((offset) & 3) * 64) - -union cvmx_l2c_big_ctl { - uint64_t u64; - struct cvmx_l2c_big_ctl_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_8_63:56; - uint64_t maxdram:4; - uint64_t reserved_1_3:3; - uint64_t disable:1; -#else - uint64_t disable:1; - uint64_t reserved_1_3:3; - uint64_t maxdram:4; - uint64_t reserved_8_63:56; -#endif - } s; - struct cvmx_l2c_big_ctl_s cn61xx; - struct cvmx_l2c_big_ctl_s cn63xx; - struct cvmx_l2c_big_ctl_s cn66xx; - struct cvmx_l2c_big_ctl_s cn68xx; - struct cvmx_l2c_big_ctl_s cn68xxp1; - struct cvmx_l2c_big_ctl_s cnf71xx; -}; - -union cvmx_l2c_bst { - uint64_t u64; - struct cvmx_l2c_bst_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t dutfl:32; - uint64_t rbffl:4; - uint64_t xbffl:4; - uint64_t tdpfl:4; - uint64_t ioccmdfl:4; - uint64_t iocdatfl:4; - uint64_t dutresfl:4; - uint64_t vrtfl:4; - uint64_t tdffl:4; -#else - uint64_t tdffl:4; - uint64_t vrtfl:4; - uint64_t dutresfl:4; - uint64_t iocdatfl:4; - uint64_t ioccmdfl:4; - uint64_t tdpfl:4; - uint64_t xbffl:4; - uint64_t rbffl:4; - uint64_t dutfl:32; -#endif - } s; - struct cvmx_l2c_bst_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_36_63:28; - uint64_t dutfl:4; - uint64_t reserved_17_31:15; - uint64_t ioccmdfl:1; - uint64_t reserved_13_15:3; - uint64_t iocdatfl:1; - uint64_t reserved_9_11:3; - uint64_t dutresfl:1; - uint64_t reserved_5_7:3; - uint64_t vrtfl:1; - uint64_t reserved_1_3:3; - uint64_t tdffl:1; -#else - uint64_t tdffl:1; - uint64_t reserved_1_3:3; - uint64_t vrtfl:1; - uint64_t reserved_5_7:3; - uint64_t dutresfl:1; - uint64_t reserved_9_11:3; - uint64_t iocdatfl:1; - uint64_t reserved_13_15:3; - uint64_t ioccmdfl:1; - uint64_t reserved_17_31:15; - uint64_t dutfl:4; - uint64_t reserved_36_63:28; -#endif - } cn61xx; - struct cvmx_l2c_bst_cn63xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_38_63:26; - uint64_t dutfl:6; - uint64_t reserved_17_31:15; - uint64_t ioccmdfl:1; - uint64_t reserved_13_15:3; - uint64_t iocdatfl:1; - uint64_t reserved_9_11:3; - uint64_t dutresfl:1; - uint64_t reserved_5_7:3; - uint64_t vrtfl:1; - uint64_t reserved_1_3:3; - uint64_t tdffl:1; -#else - uint64_t tdffl:1; - uint64_t reserved_1_3:3; - uint64_t vrtfl:1; - uint64_t reserved_5_7:3; - uint64_t dutresfl:1; - uint64_t reserved_9_11:3; - uint64_t iocdatfl:1; - uint64_t reserved_13_15:3; - uint64_t ioccmdfl:1; - uint64_t reserved_17_31:15; - uint64_t dutfl:6; - uint64_t reserved_38_63:26; -#endif - } cn63xx; - struct cvmx_l2c_bst_cn63xx cn63xxp1; - struct cvmx_l2c_bst_cn66xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_42_63:22; - uint64_t dutfl:10; - uint64_t reserved_17_31:15; - uint64_t ioccmdfl:1; - uint64_t reserved_13_15:3; - uint64_t iocdatfl:1; - uint64_t reserved_9_11:3; - uint64_t dutresfl:1; - uint64_t reserved_5_7:3; - uint64_t vrtfl:1; - uint64_t reserved_1_3:3; - uint64_t tdffl:1; -#else - uint64_t tdffl:1; - uint64_t reserved_1_3:3; - uint64_t vrtfl:1; - uint64_t reserved_5_7:3; - uint64_t dutresfl:1; - uint64_t reserved_9_11:3; - uint64_t iocdatfl:1; - uint64_t reserved_13_15:3; - uint64_t ioccmdfl:1; - uint64_t reserved_17_31:15; - uint64_t dutfl:10; - uint64_t reserved_42_63:22; -#endif - } cn66xx; - struct cvmx_l2c_bst_s cn68xx; - struct cvmx_l2c_bst_s cn68xxp1; - struct cvmx_l2c_bst_cn61xx cnf71xx; -}; - -union cvmx_l2c_bst0 { - uint64_t u64; - struct cvmx_l2c_bst0_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_24_63:40; - uint64_t dtbnk:1; - uint64_t wlb_msk:4; - uint64_t dtcnt:13; - uint64_t dt:1; - uint64_t stin_msk:1; - uint64_t wlb_dat:4; -#else - uint64_t wlb_dat:4; - uint64_t stin_msk:1; - uint64_t dt:1; - uint64_t dtcnt:13; - uint64_t wlb_msk:4; - uint64_t dtbnk:1; - uint64_t reserved_24_63:40; -#endif - } s; - struct cvmx_l2c_bst0_cn30xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_23_63:41; - uint64_t wlb_msk:4; - uint64_t reserved_15_18:4; - uint64_t dtcnt:9; - uint64_t dt:1; - uint64_t reserved_4_4:1; - uint64_t wlb_dat:4; -#else - uint64_t wlb_dat:4; - uint64_t reserved_4_4:1; - uint64_t dt:1; - uint64_t dtcnt:9; - uint64_t reserved_15_18:4; - uint64_t wlb_msk:4; - uint64_t reserved_23_63:41; -#endif - } cn30xx; - struct cvmx_l2c_bst0_cn31xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_23_63:41; - uint64_t wlb_msk:4; - uint64_t reserved_16_18:3; - uint64_t dtcnt:10; - uint64_t dt:1; - uint64_t stin_msk:1; - uint64_t wlb_dat:4; -#else - uint64_t wlb_dat:4; - uint64_t stin_msk:1; - uint64_t dt:1; - uint64_t dtcnt:10; - uint64_t reserved_16_18:3; - uint64_t wlb_msk:4; - uint64_t reserved_23_63:41; -#endif - } cn31xx; - struct cvmx_l2c_bst0_cn38xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_19_63:45; - uint64_t dtcnt:13; - uint64_t dt:1; - uint64_t stin_msk:1; - uint64_t wlb_dat:4; -#else - uint64_t wlb_dat:4; - uint64_t stin_msk:1; - uint64_t dt:1; - uint64_t dtcnt:13; - uint64_t reserved_19_63:45; -#endif - } cn38xx; - struct cvmx_l2c_bst0_cn38xx cn38xxp2; - struct cvmx_l2c_bst0_cn50xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_24_63:40; - uint64_t dtbnk:1; - uint64_t wlb_msk:4; - uint64_t reserved_16_18:3; - uint64_t dtcnt:10; - uint64_t dt:1; - uint64_t stin_msk:1; - uint64_t wlb_dat:4; -#else - uint64_t wlb_dat:4; - uint64_t stin_msk:1; - uint64_t dt:1; - uint64_t dtcnt:10; - uint64_t reserved_16_18:3; - uint64_t wlb_msk:4; - uint64_t dtbnk:1; - uint64_t reserved_24_63:40; -#endif - } cn50xx; - struct cvmx_l2c_bst0_cn50xx cn52xx; - struct cvmx_l2c_bst0_cn50xx cn52xxp1; - struct cvmx_l2c_bst0_s cn56xx; - struct cvmx_l2c_bst0_s cn56xxp1; - struct cvmx_l2c_bst0_s cn58xx; - struct cvmx_l2c_bst0_s cn58xxp1; -}; - -union cvmx_l2c_bst1 { - uint64_t u64; - struct cvmx_l2c_bst1_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_9_63:55; - uint64_t l2t:9; -#else - uint64_t l2t:9; - uint64_t reserved_9_63:55; -#endif - } s; - struct cvmx_l2c_bst1_cn30xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_16_63:48; - uint64_t vwdf:4; - uint64_t lrf:2; - uint64_t vab_vwcf:1; - uint64_t reserved_5_8:4; - uint64_t l2t:5; -#else - uint64_t l2t:5; - uint64_t reserved_5_8:4; - uint64_t vab_vwcf:1; - uint64_t lrf:2; - uint64_t vwdf:4; - uint64_t reserved_16_63:48; -#endif - } cn30xx; - struct cvmx_l2c_bst1_cn30xx cn31xx; - struct cvmx_l2c_bst1_cn38xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_16_63:48; - uint64_t vwdf:4; - uint64_t lrf:2; - uint64_t vab_vwcf:1; - uint64_t l2t:9; -#else - uint64_t l2t:9; - uint64_t vab_vwcf:1; - uint64_t lrf:2; - uint64_t vwdf:4; - uint64_t reserved_16_63:48; -#endif - } cn38xx; - struct cvmx_l2c_bst1_cn38xx cn38xxp2; - struct cvmx_l2c_bst1_cn38xx cn50xx; - struct cvmx_l2c_bst1_cn52xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_19_63:45; - uint64_t plc2:1; - uint64_t plc1:1; - uint64_t plc0:1; - uint64_t vwdf:4; - uint64_t reserved_11_11:1; - uint64_t ilc:1; - uint64_t vab_vwcf:1; - uint64_t l2t:9; -#else - uint64_t l2t:9; - uint64_t vab_vwcf:1; - uint64_t ilc:1; - uint64_t reserved_11_11:1; - uint64_t vwdf:4; - uint64_t plc0:1; - uint64_t plc1:1; - uint64_t plc2:1; - uint64_t reserved_19_63:45; -#endif - } cn52xx; - struct cvmx_l2c_bst1_cn52xx cn52xxp1; - struct cvmx_l2c_bst1_cn56xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_24_63:40; - uint64_t plc2:1; - uint64_t plc1:1; - uint64_t plc0:1; - uint64_t ilc:1; - uint64_t vwdf1:4; - uint64_t vwdf0:4; - uint64_t vab_vwcf1:1; - uint64_t reserved_10_10:1; - uint64_t vab_vwcf0:1; - uint64_t l2t:9; -#else - uint64_t l2t:9; - uint64_t vab_vwcf0:1; - uint64_t reserved_10_10:1; - uint64_t vab_vwcf1:1; - uint64_t vwdf0:4; - uint64_t vwdf1:4; - uint64_t ilc:1; - uint64_t plc0:1; - uint64_t plc1:1; - uint64_t plc2:1; - uint64_t reserved_24_63:40; -#endif - } cn56xx; - struct cvmx_l2c_bst1_cn56xx cn56xxp1; - struct cvmx_l2c_bst1_cn38xx cn58xx; - struct cvmx_l2c_bst1_cn38xx cn58xxp1; -}; - -union cvmx_l2c_bst2 { - uint64_t u64; - struct cvmx_l2c_bst2_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_16_63:48; - uint64_t mrb:4; - uint64_t reserved_4_11:8; - uint64_t ipcbst:1; - uint64_t picbst:1; - uint64_t xrdmsk:1; - uint64_t xrddat:1; -#else - uint64_t xrddat:1; - uint64_t xrdmsk:1; - uint64_t picbst:1; - uint64_t ipcbst:1; - uint64_t reserved_4_11:8; - uint64_t mrb:4; - uint64_t reserved_16_63:48; -#endif - } s; - struct cvmx_l2c_bst2_cn30xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_16_63:48; - uint64_t mrb:4; - uint64_t rmdf:4; - uint64_t reserved_4_7:4; - uint64_t ipcbst:1; - uint64_t reserved_2_2:1; - uint64_t xrdmsk:1; - uint64_t xrddat:1; -#else - uint64_t xrddat:1; - uint64_t xrdmsk:1; - uint64_t reserved_2_2:1; - uint64_t ipcbst:1; - uint64_t reserved_4_7:4; - uint64_t rmdf:4; - uint64_t mrb:4; - uint64_t reserved_16_63:48; -#endif - } cn30xx; - struct cvmx_l2c_bst2_cn30xx cn31xx; - struct cvmx_l2c_bst2_cn38xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_16_63:48; - uint64_t mrb:4; - uint64_t rmdf:4; - uint64_t rhdf:4; - uint64_t ipcbst:1; - uint64_t picbst:1; - uint64_t xrdmsk:1; - uint64_t xrddat:1; -#else - uint64_t xrddat:1; - uint64_t xrdmsk:1; - uint64_t picbst:1; - uint64_t ipcbst:1; - uint64_t rhdf:4; - uint64_t rmdf:4; - uint64_t mrb:4; - uint64_t reserved_16_63:48; -#endif - } cn38xx; - struct cvmx_l2c_bst2_cn38xx cn38xxp2; - struct cvmx_l2c_bst2_cn30xx cn50xx; - struct cvmx_l2c_bst2_cn30xx cn52xx; - struct cvmx_l2c_bst2_cn30xx cn52xxp1; - struct cvmx_l2c_bst2_cn56xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_16_63:48; - uint64_t mrb:4; - uint64_t rmdb:4; - uint64_t rhdb:4; - uint64_t ipcbst:1; - uint64_t picbst:1; - uint64_t xrdmsk:1; - uint64_t xrddat:1; -#else - uint64_t xrddat:1; - uint64_t xrdmsk:1; - uint64_t picbst:1; - uint64_t ipcbst:1; - uint64_t rhdb:4; - uint64_t rmdb:4; - uint64_t mrb:4; - uint64_t reserved_16_63:48; -#endif - } cn56xx; - struct cvmx_l2c_bst2_cn56xx cn56xxp1; - struct cvmx_l2c_bst2_cn56xx cn58xx; - struct cvmx_l2c_bst2_cn56xx cn58xxp1; -}; - -union cvmx_l2c_bst_memx { - uint64_t u64; - struct cvmx_l2c_bst_memx_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t start_bist:1; - uint64_t clear_bist:1; - uint64_t reserved_5_61:57; - uint64_t rdffl:1; - uint64_t vbffl:4; -#else - uint64_t vbffl:4; - uint64_t rdffl:1; - uint64_t reserved_5_61:57; - uint64_t clear_bist:1; - uint64_t start_bist:1; -#endif - } s; - struct cvmx_l2c_bst_memx_s cn61xx; - struct cvmx_l2c_bst_memx_s cn63xx; - struct cvmx_l2c_bst_memx_s cn63xxp1; - struct cvmx_l2c_bst_memx_s cn66xx; - struct cvmx_l2c_bst_memx_s cn68xx; - struct cvmx_l2c_bst_memx_s cn68xxp1; - struct cvmx_l2c_bst_memx_s cnf71xx; -}; - -union cvmx_l2c_bst_tdtx { - uint64_t u64; - struct cvmx_l2c_bst_tdtx_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t fbfrspfl:8; - uint64_t sbffl:8; - uint64_t fbffl:8; - uint64_t l2dfl:8; -#else - uint64_t l2dfl:8; - uint64_t fbffl:8; - uint64_t sbffl:8; - uint64_t fbfrspfl:8; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_l2c_bst_tdtx_s cn61xx; - struct cvmx_l2c_bst_tdtx_s cn63xx; - struct cvmx_l2c_bst_tdtx_cn63xxp1 { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_24_63:40; - uint64_t sbffl:8; - uint64_t fbffl:8; - uint64_t l2dfl:8; -#else - uint64_t l2dfl:8; - uint64_t fbffl:8; - uint64_t sbffl:8; - uint64_t reserved_24_63:40; -#endif - } cn63xxp1; - struct cvmx_l2c_bst_tdtx_s cn66xx; - struct cvmx_l2c_bst_tdtx_s cn68xx; - struct cvmx_l2c_bst_tdtx_s cn68xxp1; - struct cvmx_l2c_bst_tdtx_s cnf71xx; -}; +#define CVMX_L2C_TADX_PFCX(offset, block_id) \ + (CVMX_ADD_IO_SEG(0x0001180080A00400ull) + (((offset) & 3) + \ + ((block_id) & 7) * 0x8000ull) * 8) +#define CVMX_L2C_TADX_PFC0(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00400ull) + \ + ((block_id) & 3) * 0x40000ull) +#define CVMX_L2C_TADX_PFC1(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00408ull) + \ + ((block_id) & 3) * 0x40000ull) +#define CVMX_L2C_TADX_PFC2(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00410ull) + \ + ((block_id) & 3) * 0x40000ull) +#define CVMX_L2C_TADX_PFC3(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00418ull) + \ + ((block_id) & 3) * 0x40000ull) +#define CVMX_L2C_TADX_PRF(offset) (CVMX_ADD_IO_SEG(0x0001180080A00008ull) + \ + ((offset) & 7) * 0x40000ull) +#define CVMX_L2C_TADX_TAG(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00010ull) + \ + ((block_id) & 3) * 0x40000ull) +#define CVMX_L2C_WPAR_IOBX(offset) (CVMX_ADD_IO_SEG(0x0001180080840200ull) + \ + ((offset) & 1) * 8) +#define CVMX_L2C_WPAR_PPX(offset) (CVMX_ADD_IO_SEG(0x0001180080840000ull) + \ + ((offset) & 31) * 8) +#define CVMX_L2D_FUS3 (CVMX_ADD_IO_SEG(0x00011800800007B8ull)) -union cvmx_l2c_bst_ttgx { - uint64_t u64; - struct cvmx_l2c_bst_ttgx_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_17_63:47; - uint64_t lrufl:1; - uint64_t tagfl:16; -#else - uint64_t tagfl:16; - uint64_t lrufl:1; - uint64_t reserved_17_63:47; -#endif - } s; - struct cvmx_l2c_bst_ttgx_s cn61xx; - struct cvmx_l2c_bst_ttgx_s cn63xx; - struct cvmx_l2c_bst_ttgx_s cn63xxp1; - struct cvmx_l2c_bst_ttgx_s cn66xx; - struct cvmx_l2c_bst_ttgx_s cn68xx; - struct cvmx_l2c_bst_ttgx_s cn68xxp1; - struct cvmx_l2c_bst_ttgx_s cnf71xx; -}; union cvmx_l2c_cfg { uint64_t u64; struct cvmx_l2c_cfg_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_20_63:44; - uint64_t bstrun:1; - uint64_t lbist:1; - uint64_t xor_bank:1; - uint64_t dpres1:1; - uint64_t dpres0:1; - uint64_t dfill_dis:1; - uint64_t fpexp:4; - uint64_t fpempty:1; - uint64_t fpen:1; - uint64_t idxalias:1; - uint64_t mwf_crd:4; - uint64_t rsp_arb_mode:1; - uint64_t rfb_arb_mode:1; - uint64_t lrf_arb_mode:1; -#else - uint64_t lrf_arb_mode:1; - uint64_t rfb_arb_mode:1; - uint64_t rsp_arb_mode:1; - uint64_t mwf_crd:4; - uint64_t idxalias:1; - uint64_t fpen:1; - uint64_t fpempty:1; - uint64_t fpexp:4; - uint64_t dfill_dis:1; - uint64_t dpres0:1; - uint64_t dpres1:1; - uint64_t xor_bank:1; - uint64_t lbist:1; - uint64_t bstrun:1; - uint64_t reserved_20_63:44; -#endif + __BITFIELD_FIELD(uint64_t reserved_20_63:44, + __BITFIELD_FIELD(uint64_t bstrun:1, + __BITFIELD_FIELD(uint64_t lbist:1, + __BITFIELD_FIELD(uint64_t xor_bank:1, + __BITFIELD_FIELD(uint64_t dpres1:1, + __BITFIELD_FIELD(uint64_t dpres0:1, + __BITFIELD_FIELD(uint64_t dfill_dis:1, + __BITFIELD_FIELD(uint64_t fpexp:4, + __BITFIELD_FIELD(uint64_t fpempty:1, + __BITFIELD_FIELD(uint64_t fpen:1, + __BITFIELD_FIELD(uint64_t idxalias:1, + __BITFIELD_FIELD(uint64_t mwf_crd:4, + __BITFIELD_FIELD(uint64_t rsp_arb_mode:1, + __BITFIELD_FIELD(uint64_t rfb_arb_mode:1, + __BITFIELD_FIELD(uint64_t lrf_arb_mode:1, + ;))))))))))))))) } s; - struct cvmx_l2c_cfg_cn30xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_14_63:50; - uint64_t fpexp:4; - uint64_t fpempty:1; - uint64_t fpen:1; - uint64_t idxalias:1; - uint64_t mwf_crd:4; - uint64_t rsp_arb_mode:1; - uint64_t rfb_arb_mode:1; - uint64_t lrf_arb_mode:1; -#else - uint64_t lrf_arb_mode:1; - uint64_t rfb_arb_mode:1; - uint64_t rsp_arb_mode:1; - uint64_t mwf_crd:4; - uint64_t idxalias:1; - uint64_t fpen:1; - uint64_t fpempty:1; - uint64_t fpexp:4; - uint64_t reserved_14_63:50; -#endif - } cn30xx; - struct cvmx_l2c_cfg_cn30xx cn31xx; - struct cvmx_l2c_cfg_cn30xx cn38xx; - struct cvmx_l2c_cfg_cn30xx cn38xxp2; - struct cvmx_l2c_cfg_cn50xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_20_63:44; - uint64_t bstrun:1; - uint64_t lbist:1; - uint64_t reserved_14_17:4; - uint64_t fpexp:4; - uint64_t fpempty:1; - uint64_t fpen:1; - uint64_t idxalias:1; - uint64_t mwf_crd:4; - uint64_t rsp_arb_mode:1; - uint64_t rfb_arb_mode:1; - uint64_t lrf_arb_mode:1; -#else - uint64_t lrf_arb_mode:1; - uint64_t rfb_arb_mode:1; - uint64_t rsp_arb_mode:1; - uint64_t mwf_crd:4; - uint64_t idxalias:1; - uint64_t fpen:1; - uint64_t fpempty:1; - uint64_t fpexp:4; - uint64_t reserved_14_17:4; - uint64_t lbist:1; - uint64_t bstrun:1; - uint64_t reserved_20_63:44; -#endif - } cn50xx; - struct cvmx_l2c_cfg_cn50xx cn52xx; - struct cvmx_l2c_cfg_cn50xx cn52xxp1; - struct cvmx_l2c_cfg_s cn56xx; - struct cvmx_l2c_cfg_s cn56xxp1; - struct cvmx_l2c_cfg_cn58xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_20_63:44; - uint64_t bstrun:1; - uint64_t lbist:1; - uint64_t reserved_15_17:3; - uint64_t dfill_dis:1; - uint64_t fpexp:4; - uint64_t fpempty:1; - uint64_t fpen:1; - uint64_t idxalias:1; - uint64_t mwf_crd:4; - uint64_t rsp_arb_mode:1; - uint64_t rfb_arb_mode:1; - uint64_t lrf_arb_mode:1; -#else - uint64_t lrf_arb_mode:1; - uint64_t rfb_arb_mode:1; - uint64_t rsp_arb_mode:1; - uint64_t mwf_crd:4; - uint64_t idxalias:1; - uint64_t fpen:1; - uint64_t fpempty:1; - uint64_t fpexp:4; - uint64_t dfill_dis:1; - uint64_t reserved_15_17:3; - uint64_t lbist:1; - uint64_t bstrun:1; - uint64_t reserved_20_63:44; -#endif - } cn58xx; - struct cvmx_l2c_cfg_cn58xxp1 { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_15_63:49; - uint64_t dfill_dis:1; - uint64_t fpexp:4; - uint64_t fpempty:1; - uint64_t fpen:1; - uint64_t idxalias:1; - uint64_t mwf_crd:4; - uint64_t rsp_arb_mode:1; - uint64_t rfb_arb_mode:1; - uint64_t lrf_arb_mode:1; -#else - uint64_t lrf_arb_mode:1; - uint64_t rfb_arb_mode:1; - uint64_t rsp_arb_mode:1; - uint64_t mwf_crd:4; - uint64_t idxalias:1; - uint64_t fpen:1; - uint64_t fpempty:1; - uint64_t fpexp:4; - uint64_t dfill_dis:1; - uint64_t reserved_15_63:49; -#endif - } cn58xxp1; -}; - -union cvmx_l2c_cop0_mapx { - uint64_t u64; - struct cvmx_l2c_cop0_mapx_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t data:64; -#else - uint64_t data:64; -#endif - } s; - struct cvmx_l2c_cop0_mapx_s cn61xx; - struct cvmx_l2c_cop0_mapx_s cn63xx; - struct cvmx_l2c_cop0_mapx_s cn63xxp1; - struct cvmx_l2c_cop0_mapx_s cn66xx; - struct cvmx_l2c_cop0_mapx_s cn68xx; - struct cvmx_l2c_cop0_mapx_s cn68xxp1; - struct cvmx_l2c_cop0_mapx_s cnf71xx; }; union cvmx_l2c_ctl { uint64_t u64; struct cvmx_l2c_ctl_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_30_63:34; - uint64_t sepcmt:1; - uint64_t rdf_fast:1; - uint64_t disstgl2i:1; - uint64_t l2dfsbe:1; - uint64_t l2dfdbe:1; - uint64_t discclk:1; - uint64_t maxvab:4; - uint64_t maxlfb:4; - uint64_t rsp_arb_mode:1; - uint64_t xmc_arb_mode:1; - uint64_t ef_ena:1; - uint64_t ef_cnt:7; - uint64_t vab_thresh:4; - uint64_t disecc:1; - uint64_t disidxalias:1; -#else - uint64_t disidxalias:1; - uint64_t disecc:1; - uint64_t vab_thresh:4; - uint64_t ef_cnt:7; - uint64_t ef_ena:1; - uint64_t xmc_arb_mode:1; - uint64_t rsp_arb_mode:1; - uint64_t maxlfb:4; - uint64_t maxvab:4; - uint64_t discclk:1; - uint64_t l2dfdbe:1; - uint64_t l2dfsbe:1; - uint64_t disstgl2i:1; - uint64_t rdf_fast:1; - uint64_t sepcmt:1; - uint64_t reserved_30_63:34; -#endif + __BITFIELD_FIELD(uint64_t reserved_30_63:34, + __BITFIELD_FIELD(uint64_t sepcmt:1, + __BITFIELD_FIELD(uint64_t rdf_fast:1, + __BITFIELD_FIELD(uint64_t disstgl2i:1, + __BITFIELD_FIELD(uint64_t l2dfsbe:1, + __BITFIELD_FIELD(uint64_t l2dfdbe:1, + __BITFIELD_FIELD(uint64_t discclk:1, + __BITFIELD_FIELD(uint64_t maxvab:4, + __BITFIELD_FIELD(uint64_t maxlfb:4, + __BITFIELD_FIELD(uint64_t rsp_arb_mode:1, + __BITFIELD_FIELD(uint64_t xmc_arb_mode:1, + __BITFIELD_FIELD(uint64_t ef_ena:1, + __BITFIELD_FIELD(uint64_t ef_cnt:7, + __BITFIELD_FIELD(uint64_t vab_thresh:4, + __BITFIELD_FIELD(uint64_t disecc:1, + __BITFIELD_FIELD(uint64_t disidxalias:1, + ;)))))))))))))))) } s; - struct cvmx_l2c_ctl_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_29_63:35; - uint64_t rdf_fast:1; - uint64_t disstgl2i:1; - uint64_t l2dfsbe:1; - uint64_t l2dfdbe:1; - uint64_t discclk:1; - uint64_t maxvab:4; - uint64_t maxlfb:4; - uint64_t rsp_arb_mode:1; - uint64_t xmc_arb_mode:1; - uint64_t ef_ena:1; - uint64_t ef_cnt:7; - uint64_t vab_thresh:4; - uint64_t disecc:1; - uint64_t disidxalias:1; -#else - uint64_t disidxalias:1; - uint64_t disecc:1; - uint64_t vab_thresh:4; - uint64_t ef_cnt:7; - uint64_t ef_ena:1; - uint64_t xmc_arb_mode:1; - uint64_t rsp_arb_mode:1; - uint64_t maxlfb:4; - uint64_t maxvab:4; - uint64_t discclk:1; - uint64_t l2dfdbe:1; - uint64_t l2dfsbe:1; - uint64_t disstgl2i:1; - uint64_t rdf_fast:1; - uint64_t reserved_29_63:35; -#endif - } cn61xx; - struct cvmx_l2c_ctl_cn63xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_28_63:36; - uint64_t disstgl2i:1; - uint64_t l2dfsbe:1; - uint64_t l2dfdbe:1; - uint64_t discclk:1; - uint64_t maxvab:4; - uint64_t maxlfb:4; - uint64_t rsp_arb_mode:1; - uint64_t xmc_arb_mode:1; - uint64_t ef_ena:1; - uint64_t ef_cnt:7; - uint64_t vab_thresh:4; - uint64_t disecc:1; - uint64_t disidxalias:1; -#else - uint64_t disidxalias:1; - uint64_t disecc:1; - uint64_t vab_thresh:4; - uint64_t ef_cnt:7; - uint64_t ef_ena:1; - uint64_t xmc_arb_mode:1; - uint64_t rsp_arb_mode:1; - uint64_t maxlfb:4; - uint64_t maxvab:4; - uint64_t discclk:1; - uint64_t l2dfdbe:1; - uint64_t l2dfsbe:1; - uint64_t disstgl2i:1; - uint64_t reserved_28_63:36; -#endif - } cn63xx; - struct cvmx_l2c_ctl_cn63xxp1 { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_25_63:39; - uint64_t discclk:1; - uint64_t maxvab:4; - uint64_t maxlfb:4; - uint64_t rsp_arb_mode:1; - uint64_t xmc_arb_mode:1; - uint64_t ef_ena:1; - uint64_t ef_cnt:7; - uint64_t vab_thresh:4; - uint64_t disecc:1; - uint64_t disidxalias:1; -#else - uint64_t disidxalias:1; - uint64_t disecc:1; - uint64_t vab_thresh:4; - uint64_t ef_cnt:7; - uint64_t ef_ena:1; - uint64_t xmc_arb_mode:1; - uint64_t rsp_arb_mode:1; - uint64_t maxlfb:4; - uint64_t maxvab:4; - uint64_t discclk:1; - uint64_t reserved_25_63:39; -#endif - } cn63xxp1; - struct cvmx_l2c_ctl_cn61xx cn66xx; - struct cvmx_l2c_ctl_s cn68xx; - struct cvmx_l2c_ctl_cn63xx cn68xxp1; - struct cvmx_l2c_ctl_cn61xx cnf71xx; }; union cvmx_l2c_dbg { uint64_t u64; struct cvmx_l2c_dbg_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_15_63:49; - uint64_t lfb_enum:4; - uint64_t lfb_dmp:1; - uint64_t ppnum:4; - uint64_t set:3; - uint64_t finv:1; - uint64_t l2d:1; - uint64_t l2t:1; -#else - uint64_t l2t:1; - uint64_t l2d:1; - uint64_t finv:1; - uint64_t set:3; - uint64_t ppnum:4; - uint64_t lfb_dmp:1; - uint64_t lfb_enum:4; - uint64_t reserved_15_63:49; -#endif - } s; - struct cvmx_l2c_dbg_cn30xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_13_63:51; - uint64_t lfb_enum:2; - uint64_t lfb_dmp:1; - uint64_t reserved_7_9:3; - uint64_t ppnum:1; - uint64_t reserved_5_5:1; - uint64_t set:2; - uint64_t finv:1; - uint64_t l2d:1; - uint64_t l2t:1; -#else - uint64_t l2t:1; - uint64_t l2d:1; - uint64_t finv:1; - uint64_t set:2; - uint64_t reserved_5_5:1; - uint64_t ppnum:1; - uint64_t reserved_7_9:3; - uint64_t lfb_dmp:1; - uint64_t lfb_enum:2; - uint64_t reserved_13_63:51; -#endif - } cn30xx; - struct cvmx_l2c_dbg_cn31xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_14_63:50; - uint64_t lfb_enum:3; - uint64_t lfb_dmp:1; - uint64_t reserved_7_9:3; - uint64_t ppnum:1; - uint64_t reserved_5_5:1; - uint64_t set:2; - uint64_t finv:1; - uint64_t l2d:1; - uint64_t l2t:1; -#else - uint64_t l2t:1; - uint64_t l2d:1; - uint64_t finv:1; - uint64_t set:2; - uint64_t reserved_5_5:1; - uint64_t ppnum:1; - uint64_t reserved_7_9:3; - uint64_t lfb_dmp:1; - uint64_t lfb_enum:3; - uint64_t reserved_14_63:50; -#endif - } cn31xx; - struct cvmx_l2c_dbg_s cn38xx; - struct cvmx_l2c_dbg_s cn38xxp2; - struct cvmx_l2c_dbg_cn50xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_14_63:50; - uint64_t lfb_enum:3; - uint64_t lfb_dmp:1; - uint64_t reserved_7_9:3; - uint64_t ppnum:1; - uint64_t set:3; - uint64_t finv:1; - uint64_t l2d:1; - uint64_t l2t:1; -#else - uint64_t l2t:1; - uint64_t l2d:1; - uint64_t finv:1; - uint64_t set:3; - uint64_t ppnum:1; - uint64_t reserved_7_9:3; - uint64_t lfb_dmp:1; - uint64_t lfb_enum:3; - uint64_t reserved_14_63:50; -#endif - } cn50xx; - struct cvmx_l2c_dbg_cn52xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_14_63:50; - uint64_t lfb_enum:3; - uint64_t lfb_dmp:1; - uint64_t reserved_8_9:2; - uint64_t ppnum:2; - uint64_t set:3; - uint64_t finv:1; - uint64_t l2d:1; - uint64_t l2t:1; -#else - uint64_t l2t:1; - uint64_t l2d:1; - uint64_t finv:1; - uint64_t set:3; - uint64_t ppnum:2; - uint64_t reserved_8_9:2; - uint64_t lfb_dmp:1; - uint64_t lfb_enum:3; - uint64_t reserved_14_63:50; -#endif - } cn52xx; - struct cvmx_l2c_dbg_cn52xx cn52xxp1; - struct cvmx_l2c_dbg_s cn56xx; - struct cvmx_l2c_dbg_s cn56xxp1; - struct cvmx_l2c_dbg_s cn58xx; - struct cvmx_l2c_dbg_s cn58xxp1; -}; - -union cvmx_l2c_dut { - uint64_t u64; - struct cvmx_l2c_dut_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t dtena:1; - uint64_t reserved_30_30:1; - uint64_t dt_vld:1; - uint64_t dt_tag:29; -#else - uint64_t dt_tag:29; - uint64_t dt_vld:1; - uint64_t reserved_30_30:1; - uint64_t dtena:1; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_l2c_dut_s cn30xx; - struct cvmx_l2c_dut_s cn31xx; - struct cvmx_l2c_dut_s cn38xx; - struct cvmx_l2c_dut_s cn38xxp2; - struct cvmx_l2c_dut_s cn50xx; - struct cvmx_l2c_dut_s cn52xx; - struct cvmx_l2c_dut_s cn52xxp1; - struct cvmx_l2c_dut_s cn56xx; - struct cvmx_l2c_dut_s cn56xxp1; - struct cvmx_l2c_dut_s cn58xx; - struct cvmx_l2c_dut_s cn58xxp1; -}; - -union cvmx_l2c_dut_mapx { - uint64_t u64; - struct cvmx_l2c_dut_mapx_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_38_63:26; - uint64_t tag:28; - uint64_t reserved_1_9:9; - uint64_t valid:1; -#else - uint64_t valid:1; - uint64_t reserved_1_9:9; - uint64_t tag:28; - uint64_t reserved_38_63:26; -#endif - } s; - struct cvmx_l2c_dut_mapx_s cn61xx; - struct cvmx_l2c_dut_mapx_s cn63xx; - struct cvmx_l2c_dut_mapx_s cn63xxp1; - struct cvmx_l2c_dut_mapx_s cn66xx; - struct cvmx_l2c_dut_mapx_s cn68xx; - struct cvmx_l2c_dut_mapx_s cn68xxp1; - struct cvmx_l2c_dut_mapx_s cnf71xx; -}; - -union cvmx_l2c_err_tdtx { - uint64_t u64; - struct cvmx_l2c_err_tdtx_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t dbe:1; - uint64_t sbe:1; - uint64_t vdbe:1; - uint64_t vsbe:1; - uint64_t syn:10; - uint64_t reserved_22_49:28; - uint64_t wayidx:18; - uint64_t reserved_2_3:2; - uint64_t type:2; -#else - uint64_t type:2; - uint64_t reserved_2_3:2; - uint64_t wayidx:18; - uint64_t reserved_22_49:28; - uint64_t syn:10; - uint64_t vsbe:1; - uint64_t vdbe:1; - uint64_t sbe:1; - uint64_t dbe:1; -#endif - } s; - struct cvmx_l2c_err_tdtx_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t dbe:1; - uint64_t sbe:1; - uint64_t vdbe:1; - uint64_t vsbe:1; - uint64_t syn:10; - uint64_t reserved_20_49:30; - uint64_t wayidx:16; - uint64_t reserved_2_3:2; - uint64_t type:2; -#else - uint64_t type:2; - uint64_t reserved_2_3:2; - uint64_t wayidx:16; - uint64_t reserved_20_49:30; - uint64_t syn:10; - uint64_t vsbe:1; - uint64_t vdbe:1; - uint64_t sbe:1; - uint64_t dbe:1; -#endif - } cn61xx; - struct cvmx_l2c_err_tdtx_cn63xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t dbe:1; - uint64_t sbe:1; - uint64_t vdbe:1; - uint64_t vsbe:1; - uint64_t syn:10; - uint64_t reserved_21_49:29; - uint64_t wayidx:17; - uint64_t reserved_2_3:2; - uint64_t type:2; -#else - uint64_t type:2; - uint64_t reserved_2_3:2; - uint64_t wayidx:17; - uint64_t reserved_21_49:29; - uint64_t syn:10; - uint64_t vsbe:1; - uint64_t vdbe:1; - uint64_t sbe:1; - uint64_t dbe:1; -#endif - } cn63xx; - struct cvmx_l2c_err_tdtx_cn63xx cn63xxp1; - struct cvmx_l2c_err_tdtx_cn63xx cn66xx; - struct cvmx_l2c_err_tdtx_s cn68xx; - struct cvmx_l2c_err_tdtx_s cn68xxp1; - struct cvmx_l2c_err_tdtx_cn61xx cnf71xx; -}; - -union cvmx_l2c_err_ttgx { - uint64_t u64; - struct cvmx_l2c_err_ttgx_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t dbe:1; - uint64_t sbe:1; - uint64_t noway:1; - uint64_t reserved_56_60:5; - uint64_t syn:6; - uint64_t reserved_22_49:28; - uint64_t wayidx:15; - uint64_t reserved_2_6:5; - uint64_t type:2; -#else - uint64_t type:2; - uint64_t reserved_2_6:5; - uint64_t wayidx:15; - uint64_t reserved_22_49:28; - uint64_t syn:6; - uint64_t reserved_56_60:5; - uint64_t noway:1; - uint64_t sbe:1; - uint64_t dbe:1; -#endif - } s; - struct cvmx_l2c_err_ttgx_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t dbe:1; - uint64_t sbe:1; - uint64_t noway:1; - uint64_t reserved_56_60:5; - uint64_t syn:6; - uint64_t reserved_20_49:30; - uint64_t wayidx:13; - uint64_t reserved_2_6:5; - uint64_t type:2; -#else - uint64_t type:2; - uint64_t reserved_2_6:5; - uint64_t wayidx:13; - uint64_t reserved_20_49:30; - uint64_t syn:6; - uint64_t reserved_56_60:5; - uint64_t noway:1; - uint64_t sbe:1; - uint64_t dbe:1; -#endif - } cn61xx; - struct cvmx_l2c_err_ttgx_cn63xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t dbe:1; - uint64_t sbe:1; - uint64_t noway:1; - uint64_t reserved_56_60:5; - uint64_t syn:6; - uint64_t reserved_21_49:29; - uint64_t wayidx:14; - uint64_t reserved_2_6:5; - uint64_t type:2; -#else - uint64_t type:2; - uint64_t reserved_2_6:5; - uint64_t wayidx:14; - uint64_t reserved_21_49:29; - uint64_t syn:6; - uint64_t reserved_56_60:5; - uint64_t noway:1; - uint64_t sbe:1; - uint64_t dbe:1; -#endif - } cn63xx; - struct cvmx_l2c_err_ttgx_cn63xx cn63xxp1; - struct cvmx_l2c_err_ttgx_cn63xx cn66xx; - struct cvmx_l2c_err_ttgx_s cn68xx; - struct cvmx_l2c_err_ttgx_s cn68xxp1; - struct cvmx_l2c_err_ttgx_cn61xx cnf71xx; -}; - -union cvmx_l2c_err_vbfx { - uint64_t u64; - struct cvmx_l2c_err_vbfx_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_62_63:2; - uint64_t vdbe:1; - uint64_t vsbe:1; - uint64_t vsyn:10; - uint64_t reserved_2_49:48; - uint64_t type:2; -#else - uint64_t type:2; - uint64_t reserved_2_49:48; - uint64_t vsyn:10; - uint64_t vsbe:1; - uint64_t vdbe:1; - uint64_t reserved_62_63:2; -#endif - } s; - struct cvmx_l2c_err_vbfx_s cn61xx; - struct cvmx_l2c_err_vbfx_s cn63xx; - struct cvmx_l2c_err_vbfx_s cn63xxp1; - struct cvmx_l2c_err_vbfx_s cn66xx; - struct cvmx_l2c_err_vbfx_s cn68xx; - struct cvmx_l2c_err_vbfx_s cn68xxp1; - struct cvmx_l2c_err_vbfx_s cnf71xx; -}; - -union cvmx_l2c_err_xmc { - uint64_t u64; - struct cvmx_l2c_err_xmc_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t cmd:6; - uint64_t reserved_54_57:4; - uint64_t sid:6; - uint64_t reserved_38_47:10; - uint64_t addr:38; -#else - uint64_t addr:38; - uint64_t reserved_38_47:10; - uint64_t sid:6; - uint64_t reserved_54_57:4; - uint64_t cmd:6; -#endif - } s; - struct cvmx_l2c_err_xmc_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t cmd:6; - uint64_t reserved_52_57:6; - uint64_t sid:4; - uint64_t reserved_38_47:10; - uint64_t addr:38; -#else - uint64_t addr:38; - uint64_t reserved_38_47:10; - uint64_t sid:4; - uint64_t reserved_52_57:6; - uint64_t cmd:6; -#endif - } cn61xx; - struct cvmx_l2c_err_xmc_cn61xx cn63xx; - struct cvmx_l2c_err_xmc_cn61xx cn63xxp1; - struct cvmx_l2c_err_xmc_cn66xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t cmd:6; - uint64_t reserved_53_57:5; - uint64_t sid:5; - uint64_t reserved_38_47:10; - uint64_t addr:38; -#else - uint64_t addr:38; - uint64_t reserved_38_47:10; - uint64_t sid:5; - uint64_t reserved_53_57:5; - uint64_t cmd:6; -#endif - } cn66xx; - struct cvmx_l2c_err_xmc_s cn68xx; - struct cvmx_l2c_err_xmc_s cn68xxp1; - struct cvmx_l2c_err_xmc_cn61xx cnf71xx; -}; - -union cvmx_l2c_grpwrr0 { - uint64_t u64; - struct cvmx_l2c_grpwrr0_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t plc1rmsk:32; - uint64_t plc0rmsk:32; -#else - uint64_t plc0rmsk:32; - uint64_t plc1rmsk:32; -#endif - } s; - struct cvmx_l2c_grpwrr0_s cn52xx; - struct cvmx_l2c_grpwrr0_s cn52xxp1; - struct cvmx_l2c_grpwrr0_s cn56xx; - struct cvmx_l2c_grpwrr0_s cn56xxp1; -}; - -union cvmx_l2c_grpwrr1 { - uint64_t u64; - struct cvmx_l2c_grpwrr1_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t ilcrmsk:32; - uint64_t plc2rmsk:32; -#else - uint64_t plc2rmsk:32; - uint64_t ilcrmsk:32; -#endif - } s; - struct cvmx_l2c_grpwrr1_s cn52xx; - struct cvmx_l2c_grpwrr1_s cn52xxp1; - struct cvmx_l2c_grpwrr1_s cn56xx; - struct cvmx_l2c_grpwrr1_s cn56xxp1; -}; - -union cvmx_l2c_int_en { - uint64_t u64; - struct cvmx_l2c_int_en_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_9_63:55; - uint64_t lck2ena:1; - uint64_t lckena:1; - uint64_t l2ddeden:1; - uint64_t l2dsecen:1; - uint64_t l2tdeden:1; - uint64_t l2tsecen:1; - uint64_t oob3en:1; - uint64_t oob2en:1; - uint64_t oob1en:1; -#else - uint64_t oob1en:1; - uint64_t oob2en:1; - uint64_t oob3en:1; - uint64_t l2tsecen:1; - uint64_t l2tdeden:1; - uint64_t l2dsecen:1; - uint64_t l2ddeden:1; - uint64_t lckena:1; - uint64_t lck2ena:1; - uint64_t reserved_9_63:55; -#endif - } s; - struct cvmx_l2c_int_en_s cn52xx; - struct cvmx_l2c_int_en_s cn52xxp1; - struct cvmx_l2c_int_en_s cn56xx; - struct cvmx_l2c_int_en_s cn56xxp1; -}; - -union cvmx_l2c_int_ena { - uint64_t u64; - struct cvmx_l2c_int_ena_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_8_63:56; - uint64_t bigrd:1; - uint64_t bigwr:1; - uint64_t vrtpe:1; - uint64_t vrtadrng:1; - uint64_t vrtidrng:1; - uint64_t vrtwr:1; - uint64_t holewr:1; - uint64_t holerd:1; -#else - uint64_t holerd:1; - uint64_t holewr:1; - uint64_t vrtwr:1; - uint64_t vrtidrng:1; - uint64_t vrtadrng:1; - uint64_t vrtpe:1; - uint64_t bigwr:1; - uint64_t bigrd:1; - uint64_t reserved_8_63:56; -#endif - } s; - struct cvmx_l2c_int_ena_s cn61xx; - struct cvmx_l2c_int_ena_s cn63xx; - struct cvmx_l2c_int_ena_cn63xxp1 { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_6_63:58; - uint64_t vrtpe:1; - uint64_t vrtadrng:1; - uint64_t vrtidrng:1; - uint64_t vrtwr:1; - uint64_t holewr:1; - uint64_t holerd:1; -#else - uint64_t holerd:1; - uint64_t holewr:1; - uint64_t vrtwr:1; - uint64_t vrtidrng:1; - uint64_t vrtadrng:1; - uint64_t vrtpe:1; - uint64_t reserved_6_63:58; -#endif - } cn63xxp1; - struct cvmx_l2c_int_ena_s cn66xx; - struct cvmx_l2c_int_ena_s cn68xx; - struct cvmx_l2c_int_ena_s cn68xxp1; - struct cvmx_l2c_int_ena_s cnf71xx; -}; - -union cvmx_l2c_int_reg { - uint64_t u64; - struct cvmx_l2c_int_reg_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_20_63:44; - uint64_t tad3:1; - uint64_t tad2:1; - uint64_t tad1:1; - uint64_t tad0:1; - uint64_t reserved_8_15:8; - uint64_t bigrd:1; - uint64_t bigwr:1; - uint64_t vrtpe:1; - uint64_t vrtadrng:1; - uint64_t vrtidrng:1; - uint64_t vrtwr:1; - uint64_t holewr:1; - uint64_t holerd:1; -#else - uint64_t holerd:1; - uint64_t holewr:1; - uint64_t vrtwr:1; - uint64_t vrtidrng:1; - uint64_t vrtadrng:1; - uint64_t vrtpe:1; - uint64_t bigwr:1; - uint64_t bigrd:1; - uint64_t reserved_8_15:8; - uint64_t tad0:1; - uint64_t tad1:1; - uint64_t tad2:1; - uint64_t tad3:1; - uint64_t reserved_20_63:44; -#endif - } s; - struct cvmx_l2c_int_reg_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_17_63:47; - uint64_t tad0:1; - uint64_t reserved_8_15:8; - uint64_t bigrd:1; - uint64_t bigwr:1; - uint64_t vrtpe:1; - uint64_t vrtadrng:1; - uint64_t vrtidrng:1; - uint64_t vrtwr:1; - uint64_t holewr:1; - uint64_t holerd:1; -#else - uint64_t holerd:1; - uint64_t holewr:1; - uint64_t vrtwr:1; - uint64_t vrtidrng:1; - uint64_t vrtadrng:1; - uint64_t vrtpe:1; - uint64_t bigwr:1; - uint64_t bigrd:1; - uint64_t reserved_8_15:8; - uint64_t tad0:1; - uint64_t reserved_17_63:47; -#endif - } cn61xx; - struct cvmx_l2c_int_reg_cn61xx cn63xx; - struct cvmx_l2c_int_reg_cn63xxp1 { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_17_63:47; - uint64_t tad0:1; - uint64_t reserved_6_15:10; - uint64_t vrtpe:1; - uint64_t vrtadrng:1; - uint64_t vrtidrng:1; - uint64_t vrtwr:1; - uint64_t holewr:1; - uint64_t holerd:1; -#else - uint64_t holerd:1; - uint64_t holewr:1; - uint64_t vrtwr:1; - uint64_t vrtidrng:1; - uint64_t vrtadrng:1; - uint64_t vrtpe:1; - uint64_t reserved_6_15:10; - uint64_t tad0:1; - uint64_t reserved_17_63:47; -#endif - } cn63xxp1; - struct cvmx_l2c_int_reg_cn61xx cn66xx; - struct cvmx_l2c_int_reg_s cn68xx; - struct cvmx_l2c_int_reg_s cn68xxp1; - struct cvmx_l2c_int_reg_cn61xx cnf71xx; -}; - -union cvmx_l2c_int_stat { - uint64_t u64; - struct cvmx_l2c_int_stat_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_9_63:55; - uint64_t lck2:1; - uint64_t lck:1; - uint64_t l2dded:1; - uint64_t l2dsec:1; - uint64_t l2tded:1; - uint64_t l2tsec:1; - uint64_t oob3:1; - uint64_t oob2:1; - uint64_t oob1:1; -#else - uint64_t oob1:1; - uint64_t oob2:1; - uint64_t oob3:1; - uint64_t l2tsec:1; - uint64_t l2tded:1; - uint64_t l2dsec:1; - uint64_t l2dded:1; - uint64_t lck:1; - uint64_t lck2:1; - uint64_t reserved_9_63:55; -#endif - } s; - struct cvmx_l2c_int_stat_s cn52xx; - struct cvmx_l2c_int_stat_s cn52xxp1; - struct cvmx_l2c_int_stat_s cn56xx; - struct cvmx_l2c_int_stat_s cn56xxp1; -}; - -union cvmx_l2c_iocx_pfc { - uint64_t u64; - struct cvmx_l2c_iocx_pfc_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t count:64; -#else - uint64_t count:64; -#endif - } s; - struct cvmx_l2c_iocx_pfc_s cn61xx; - struct cvmx_l2c_iocx_pfc_s cn63xx; - struct cvmx_l2c_iocx_pfc_s cn63xxp1; - struct cvmx_l2c_iocx_pfc_s cn66xx; - struct cvmx_l2c_iocx_pfc_s cn68xx; - struct cvmx_l2c_iocx_pfc_s cn68xxp1; - struct cvmx_l2c_iocx_pfc_s cnf71xx; -}; - -union cvmx_l2c_iorx_pfc { - uint64_t u64; - struct cvmx_l2c_iorx_pfc_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t count:64; -#else - uint64_t count:64; -#endif - } s; - struct cvmx_l2c_iorx_pfc_s cn61xx; - struct cvmx_l2c_iorx_pfc_s cn63xx; - struct cvmx_l2c_iorx_pfc_s cn63xxp1; - struct cvmx_l2c_iorx_pfc_s cn66xx; - struct cvmx_l2c_iorx_pfc_s cn68xx; - struct cvmx_l2c_iorx_pfc_s cn68xxp1; - struct cvmx_l2c_iorx_pfc_s cnf71xx; -}; - -union cvmx_l2c_lckbase { - uint64_t u64; - struct cvmx_l2c_lckbase_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_31_63:33; - uint64_t lck_base:27; - uint64_t reserved_1_3:3; - uint64_t lck_ena:1; -#else - uint64_t lck_ena:1; - uint64_t reserved_1_3:3; - uint64_t lck_base:27; - uint64_t reserved_31_63:33; -#endif - } s; - struct cvmx_l2c_lckbase_s cn30xx; - struct cvmx_l2c_lckbase_s cn31xx; - struct cvmx_l2c_lckbase_s cn38xx; - struct cvmx_l2c_lckbase_s cn38xxp2; - struct cvmx_l2c_lckbase_s cn50xx; - struct cvmx_l2c_lckbase_s cn52xx; - struct cvmx_l2c_lckbase_s cn52xxp1; - struct cvmx_l2c_lckbase_s cn56xx; - struct cvmx_l2c_lckbase_s cn56xxp1; - struct cvmx_l2c_lckbase_s cn58xx; - struct cvmx_l2c_lckbase_s cn58xxp1; -}; - -union cvmx_l2c_lckoff { - uint64_t u64; - struct cvmx_l2c_lckoff_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_10_63:54; - uint64_t lck_offset:10; -#else - uint64_t lck_offset:10; - uint64_t reserved_10_63:54; -#endif - } s; - struct cvmx_l2c_lckoff_s cn30xx; - struct cvmx_l2c_lckoff_s cn31xx; - struct cvmx_l2c_lckoff_s cn38xx; - struct cvmx_l2c_lckoff_s cn38xxp2; - struct cvmx_l2c_lckoff_s cn50xx; - struct cvmx_l2c_lckoff_s cn52xx; - struct cvmx_l2c_lckoff_s cn52xxp1; - struct cvmx_l2c_lckoff_s cn56xx; - struct cvmx_l2c_lckoff_s cn56xxp1; - struct cvmx_l2c_lckoff_s cn58xx; - struct cvmx_l2c_lckoff_s cn58xxp1; -}; - -union cvmx_l2c_lfb0 { - uint64_t u64; - struct cvmx_l2c_lfb0_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t stcpnd:1; - uint64_t stpnd:1; - uint64_t stinv:1; - uint64_t stcfl:1; - uint64_t vam:1; - uint64_t inxt:4; - uint64_t itl:1; - uint64_t ihd:1; - uint64_t set:3; - uint64_t vabnum:4; - uint64_t sid:9; - uint64_t cmd:4; - uint64_t vld:1; -#else - uint64_t vld:1; - uint64_t cmd:4; - uint64_t sid:9; - uint64_t vabnum:4; - uint64_t set:3; - uint64_t ihd:1; - uint64_t itl:1; - uint64_t inxt:4; - uint64_t vam:1; - uint64_t stcfl:1; - uint64_t stinv:1; - uint64_t stpnd:1; - uint64_t stcpnd:1; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_l2c_lfb0_cn30xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t stcpnd:1; - uint64_t stpnd:1; - uint64_t stinv:1; - uint64_t stcfl:1; - uint64_t vam:1; - uint64_t reserved_25_26:2; - uint64_t inxt:2; - uint64_t itl:1; - uint64_t ihd:1; - uint64_t reserved_20_20:1; - uint64_t set:2; - uint64_t reserved_16_17:2; - uint64_t vabnum:2; - uint64_t sid:9; - uint64_t cmd:4; - uint64_t vld:1; -#else - uint64_t vld:1; - uint64_t cmd:4; - uint64_t sid:9; - uint64_t vabnum:2; - uint64_t reserved_16_17:2; - uint64_t set:2; - uint64_t reserved_20_20:1; - uint64_t ihd:1; - uint64_t itl:1; - uint64_t inxt:2; - uint64_t reserved_25_26:2; - uint64_t vam:1; - uint64_t stcfl:1; - uint64_t stinv:1; - uint64_t stpnd:1; - uint64_t stcpnd:1; - uint64_t reserved_32_63:32; -#endif - } cn30xx; - struct cvmx_l2c_lfb0_cn31xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t stcpnd:1; - uint64_t stpnd:1; - uint64_t stinv:1; - uint64_t stcfl:1; - uint64_t vam:1; - uint64_t reserved_26_26:1; - uint64_t inxt:3; - uint64_t itl:1; - uint64_t ihd:1; - uint64_t reserved_20_20:1; - uint64_t set:2; - uint64_t reserved_17_17:1; - uint64_t vabnum:3; - uint64_t sid:9; - uint64_t cmd:4; - uint64_t vld:1; -#else - uint64_t vld:1; - uint64_t cmd:4; - uint64_t sid:9; - uint64_t vabnum:3; - uint64_t reserved_17_17:1; - uint64_t set:2; - uint64_t reserved_20_20:1; - uint64_t ihd:1; - uint64_t itl:1; - uint64_t inxt:3; - uint64_t reserved_26_26:1; - uint64_t vam:1; - uint64_t stcfl:1; - uint64_t stinv:1; - uint64_t stpnd:1; - uint64_t stcpnd:1; - uint64_t reserved_32_63:32; -#endif - } cn31xx; - struct cvmx_l2c_lfb0_s cn38xx; - struct cvmx_l2c_lfb0_s cn38xxp2; - struct cvmx_l2c_lfb0_cn50xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t stcpnd:1; - uint64_t stpnd:1; - uint64_t stinv:1; - uint64_t stcfl:1; - uint64_t vam:1; - uint64_t reserved_26_26:1; - uint64_t inxt:3; - uint64_t itl:1; - uint64_t ihd:1; - uint64_t set:3; - uint64_t reserved_17_17:1; - uint64_t vabnum:3; - uint64_t sid:9; - uint64_t cmd:4; - uint64_t vld:1; -#else - uint64_t vld:1; - uint64_t cmd:4; - uint64_t sid:9; - uint64_t vabnum:3; - uint64_t reserved_17_17:1; - uint64_t set:3; - uint64_t ihd:1; - uint64_t itl:1; - uint64_t inxt:3; - uint64_t reserved_26_26:1; - uint64_t vam:1; - uint64_t stcfl:1; - uint64_t stinv:1; - uint64_t stpnd:1; - uint64_t stcpnd:1; - uint64_t reserved_32_63:32; -#endif - } cn50xx; - struct cvmx_l2c_lfb0_cn50xx cn52xx; - struct cvmx_l2c_lfb0_cn50xx cn52xxp1; - struct cvmx_l2c_lfb0_s cn56xx; - struct cvmx_l2c_lfb0_s cn56xxp1; - struct cvmx_l2c_lfb0_s cn58xx; - struct cvmx_l2c_lfb0_s cn58xxp1; -}; - -union cvmx_l2c_lfb1 { - uint64_t u64; - struct cvmx_l2c_lfb1_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_19_63:45; - uint64_t dsgoing:1; - uint64_t bid:2; - uint64_t wtrsp:1; - uint64_t wtdw:1; - uint64_t wtdq:1; - uint64_t wtwhp:1; - uint64_t wtwhf:1; - uint64_t wtwrm:1; - uint64_t wtstm:1; - uint64_t wtrda:1; - uint64_t wtstdt:1; - uint64_t wtstrsp:1; - uint64_t wtstrsc:1; - uint64_t wtvtm:1; - uint64_t wtmfl:1; - uint64_t prbrty:1; - uint64_t wtprb:1; - uint64_t vld:1; -#else - uint64_t vld:1; - uint64_t wtprb:1; - uint64_t prbrty:1; - uint64_t wtmfl:1; - uint64_t wtvtm:1; - uint64_t wtstrsc:1; - uint64_t wtstrsp:1; - uint64_t wtstdt:1; - uint64_t wtrda:1; - uint64_t wtstm:1; - uint64_t wtwrm:1; - uint64_t wtwhf:1; - uint64_t wtwhp:1; - uint64_t wtdq:1; - uint64_t wtdw:1; - uint64_t wtrsp:1; - uint64_t bid:2; - uint64_t dsgoing:1; - uint64_t reserved_19_63:45; -#endif - } s; - struct cvmx_l2c_lfb1_s cn30xx; - struct cvmx_l2c_lfb1_s cn31xx; - struct cvmx_l2c_lfb1_s cn38xx; - struct cvmx_l2c_lfb1_s cn38xxp2; - struct cvmx_l2c_lfb1_s cn50xx; - struct cvmx_l2c_lfb1_s cn52xx; - struct cvmx_l2c_lfb1_s cn52xxp1; - struct cvmx_l2c_lfb1_s cn56xx; - struct cvmx_l2c_lfb1_s cn56xxp1; - struct cvmx_l2c_lfb1_s cn58xx; - struct cvmx_l2c_lfb1_s cn58xxp1; -}; - -union cvmx_l2c_lfb2 { - uint64_t u64; - struct cvmx_l2c_lfb2_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_0_63:64; -#else - uint64_t reserved_0_63:64; -#endif - } s; - struct cvmx_l2c_lfb2_cn30xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_27_63:37; - uint64_t lfb_tag:19; - uint64_t lfb_idx:8; -#else - uint64_t lfb_idx:8; - uint64_t lfb_tag:19; - uint64_t reserved_27_63:37; -#endif - } cn30xx; - struct cvmx_l2c_lfb2_cn31xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_27_63:37; - uint64_t lfb_tag:17; - uint64_t lfb_idx:10; -#else - uint64_t lfb_idx:10; - uint64_t lfb_tag:17; - uint64_t reserved_27_63:37; -#endif - } cn31xx; - struct cvmx_l2c_lfb2_cn31xx cn38xx; - struct cvmx_l2c_lfb2_cn31xx cn38xxp2; - struct cvmx_l2c_lfb2_cn50xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_27_63:37; - uint64_t lfb_tag:20; - uint64_t lfb_idx:7; -#else - uint64_t lfb_idx:7; - uint64_t lfb_tag:20; - uint64_t reserved_27_63:37; -#endif - } cn50xx; - struct cvmx_l2c_lfb2_cn52xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_27_63:37; - uint64_t lfb_tag:18; - uint64_t lfb_idx:9; -#else - uint64_t lfb_idx:9; - uint64_t lfb_tag:18; - uint64_t reserved_27_63:37; -#endif - } cn52xx; - struct cvmx_l2c_lfb2_cn52xx cn52xxp1; - struct cvmx_l2c_lfb2_cn56xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_27_63:37; - uint64_t lfb_tag:16; - uint64_t lfb_idx:11; -#else - uint64_t lfb_idx:11; - uint64_t lfb_tag:16; - uint64_t reserved_27_63:37; -#endif - } cn56xx; - struct cvmx_l2c_lfb2_cn56xx cn56xxp1; - struct cvmx_l2c_lfb2_cn56xx cn58xx; - struct cvmx_l2c_lfb2_cn56xx cn58xxp1; -}; - -union cvmx_l2c_lfb3 { - uint64_t u64; - struct cvmx_l2c_lfb3_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_5_63:59; - uint64_t stpartdis:1; - uint64_t lfb_hwm:4; -#else - uint64_t lfb_hwm:4; - uint64_t stpartdis:1; - uint64_t reserved_5_63:59; -#endif + __BITFIELD_FIELD(uint64_t reserved_15_63:49, + __BITFIELD_FIELD(uint64_t lfb_enum:4, + __BITFIELD_FIELD(uint64_t lfb_dmp:1, + __BITFIELD_FIELD(uint64_t ppnum:4, + __BITFIELD_FIELD(uint64_t set:3, + __BITFIELD_FIELD(uint64_t finv:1, + __BITFIELD_FIELD(uint64_t l2d:1, + __BITFIELD_FIELD(uint64_t l2t:1, + ;)))))))) } s; - struct cvmx_l2c_lfb3_cn30xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_5_63:59; - uint64_t stpartdis:1; - uint64_t reserved_2_3:2; - uint64_t lfb_hwm:2; -#else - uint64_t lfb_hwm:2; - uint64_t reserved_2_3:2; - uint64_t stpartdis:1; - uint64_t reserved_5_63:59; -#endif - } cn30xx; - struct cvmx_l2c_lfb3_cn31xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_5_63:59; - uint64_t stpartdis:1; - uint64_t reserved_3_3:1; - uint64_t lfb_hwm:3; -#else - uint64_t lfb_hwm:3; - uint64_t reserved_3_3:1; - uint64_t stpartdis:1; - uint64_t reserved_5_63:59; -#endif - } cn31xx; - struct cvmx_l2c_lfb3_s cn38xx; - struct cvmx_l2c_lfb3_s cn38xxp2; - struct cvmx_l2c_lfb3_cn31xx cn50xx; - struct cvmx_l2c_lfb3_cn31xx cn52xx; - struct cvmx_l2c_lfb3_cn31xx cn52xxp1; - struct cvmx_l2c_lfb3_s cn56xx; - struct cvmx_l2c_lfb3_s cn56xxp1; - struct cvmx_l2c_lfb3_s cn58xx; - struct cvmx_l2c_lfb3_s cn58xxp1; -}; - -union cvmx_l2c_oob { - uint64_t u64; - struct cvmx_l2c_oob_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_2_63:62; - uint64_t dwbena:1; - uint64_t stena:1; -#else - uint64_t stena:1; - uint64_t dwbena:1; - uint64_t reserved_2_63:62; -#endif - } s; - struct cvmx_l2c_oob_s cn52xx; - struct cvmx_l2c_oob_s cn52xxp1; - struct cvmx_l2c_oob_s cn56xx; - struct cvmx_l2c_oob_s cn56xxp1; -}; - -union cvmx_l2c_oob1 { - uint64_t u64; - struct cvmx_l2c_oob1_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t fadr:27; - uint64_t fsrc:1; - uint64_t reserved_34_35:2; - uint64_t sadr:14; - uint64_t reserved_14_19:6; - uint64_t size:14; -#else - uint64_t size:14; - uint64_t reserved_14_19:6; - uint64_t sadr:14; - uint64_t reserved_34_35:2; - uint64_t fsrc:1; - uint64_t fadr:27; -#endif - } s; - struct cvmx_l2c_oob1_s cn52xx; - struct cvmx_l2c_oob1_s cn52xxp1; - struct cvmx_l2c_oob1_s cn56xx; - struct cvmx_l2c_oob1_s cn56xxp1; -}; - -union cvmx_l2c_oob2 { - uint64_t u64; - struct cvmx_l2c_oob2_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t fadr:27; - uint64_t fsrc:1; - uint64_t reserved_34_35:2; - uint64_t sadr:14; - uint64_t reserved_14_19:6; - uint64_t size:14; -#else - uint64_t size:14; - uint64_t reserved_14_19:6; - uint64_t sadr:14; - uint64_t reserved_34_35:2; - uint64_t fsrc:1; - uint64_t fadr:27; -#endif - } s; - struct cvmx_l2c_oob2_s cn52xx; - struct cvmx_l2c_oob2_s cn52xxp1; - struct cvmx_l2c_oob2_s cn56xx; - struct cvmx_l2c_oob2_s cn56xxp1; -}; - -union cvmx_l2c_oob3 { - uint64_t u64; - struct cvmx_l2c_oob3_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t fadr:27; - uint64_t fsrc:1; - uint64_t reserved_34_35:2; - uint64_t sadr:14; - uint64_t reserved_14_19:6; - uint64_t size:14; -#else - uint64_t size:14; - uint64_t reserved_14_19:6; - uint64_t sadr:14; - uint64_t reserved_34_35:2; - uint64_t fsrc:1; - uint64_t fadr:27; -#endif - } s; - struct cvmx_l2c_oob3_s cn52xx; - struct cvmx_l2c_oob3_s cn52xxp1; - struct cvmx_l2c_oob3_s cn56xx; - struct cvmx_l2c_oob3_s cn56xxp1; -}; - -union cvmx_l2c_pfcx { - uint64_t u64; - struct cvmx_l2c_pfcx_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_36_63:28; - uint64_t pfcnt0:36; -#else - uint64_t pfcnt0:36; - uint64_t reserved_36_63:28; -#endif - } s; - struct cvmx_l2c_pfcx_s cn30xx; - struct cvmx_l2c_pfcx_s cn31xx; - struct cvmx_l2c_pfcx_s cn38xx; - struct cvmx_l2c_pfcx_s cn38xxp2; - struct cvmx_l2c_pfcx_s cn50xx; - struct cvmx_l2c_pfcx_s cn52xx; - struct cvmx_l2c_pfcx_s cn52xxp1; - struct cvmx_l2c_pfcx_s cn56xx; - struct cvmx_l2c_pfcx_s cn56xxp1; - struct cvmx_l2c_pfcx_s cn58xx; - struct cvmx_l2c_pfcx_s cn58xxp1; }; union cvmx_l2c_pfctl { uint64_t u64; struct cvmx_l2c_pfctl_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_36_63:28; - uint64_t cnt3rdclr:1; - uint64_t cnt2rdclr:1; - uint64_t cnt1rdclr:1; - uint64_t cnt0rdclr:1; - uint64_t cnt3ena:1; - uint64_t cnt3clr:1; - uint64_t cnt3sel:6; - uint64_t cnt2ena:1; - uint64_t cnt2clr:1; - uint64_t cnt2sel:6; - uint64_t cnt1ena:1; - uint64_t cnt1clr:1; - uint64_t cnt1sel:6; - uint64_t cnt0ena:1; - uint64_t cnt0clr:1; - uint64_t cnt0sel:6; -#else - uint64_t cnt0sel:6; - uint64_t cnt0clr:1; - uint64_t cnt0ena:1; - uint64_t cnt1sel:6; - uint64_t cnt1clr:1; - uint64_t cnt1ena:1; - uint64_t cnt2sel:6; - uint64_t cnt2clr:1; - uint64_t cnt2ena:1; - uint64_t cnt3sel:6; - uint64_t cnt3clr:1; - uint64_t cnt3ena:1; - uint64_t cnt0rdclr:1; - uint64_t cnt1rdclr:1; - uint64_t cnt2rdclr:1; - uint64_t cnt3rdclr:1; - uint64_t reserved_36_63:28; -#endif - } s; - struct cvmx_l2c_pfctl_s cn30xx; - struct cvmx_l2c_pfctl_s cn31xx; - struct cvmx_l2c_pfctl_s cn38xx; - struct cvmx_l2c_pfctl_s cn38xxp2; - struct cvmx_l2c_pfctl_s cn50xx; - struct cvmx_l2c_pfctl_s cn52xx; - struct cvmx_l2c_pfctl_s cn52xxp1; - struct cvmx_l2c_pfctl_s cn56xx; - struct cvmx_l2c_pfctl_s cn56xxp1; - struct cvmx_l2c_pfctl_s cn58xx; - struct cvmx_l2c_pfctl_s cn58xxp1; -}; - -union cvmx_l2c_ppgrp { - uint64_t u64; - struct cvmx_l2c_ppgrp_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_24_63:40; - uint64_t pp11grp:2; - uint64_t pp10grp:2; - uint64_t pp9grp:2; - uint64_t pp8grp:2; - uint64_t pp7grp:2; - uint64_t pp6grp:2; - uint64_t pp5grp:2; - uint64_t pp4grp:2; - uint64_t pp3grp:2; - uint64_t pp2grp:2; - uint64_t pp1grp:2; - uint64_t pp0grp:2; -#else - uint64_t pp0grp:2; - uint64_t pp1grp:2; - uint64_t pp2grp:2; - uint64_t pp3grp:2; - uint64_t pp4grp:2; - uint64_t pp5grp:2; - uint64_t pp6grp:2; - uint64_t pp7grp:2; - uint64_t pp8grp:2; - uint64_t pp9grp:2; - uint64_t pp10grp:2; - uint64_t pp11grp:2; - uint64_t reserved_24_63:40; -#endif - } s; - struct cvmx_l2c_ppgrp_cn52xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_8_63:56; - uint64_t pp3grp:2; - uint64_t pp2grp:2; - uint64_t pp1grp:2; - uint64_t pp0grp:2; -#else - uint64_t pp0grp:2; - uint64_t pp1grp:2; - uint64_t pp2grp:2; - uint64_t pp3grp:2; - uint64_t reserved_8_63:56; -#endif - } cn52xx; - struct cvmx_l2c_ppgrp_cn52xx cn52xxp1; - struct cvmx_l2c_ppgrp_s cn56xx; - struct cvmx_l2c_ppgrp_s cn56xxp1; -}; - -union cvmx_l2c_qos_iobx { - uint64_t u64; - struct cvmx_l2c_qos_iobx_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_7_63:57; - uint64_t dwblvl:3; - uint64_t reserved_3_3:1; - uint64_t lvl:3; -#else - uint64_t lvl:3; - uint64_t reserved_3_3:1; - uint64_t dwblvl:3; - uint64_t reserved_7_63:57; -#endif - } s; - struct cvmx_l2c_qos_iobx_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_6_63:58; - uint64_t dwblvl:2; - uint64_t reserved_2_3:2; - uint64_t lvl:2; -#else - uint64_t lvl:2; - uint64_t reserved_2_3:2; - uint64_t dwblvl:2; - uint64_t reserved_6_63:58; -#endif - } cn61xx; - struct cvmx_l2c_qos_iobx_cn61xx cn63xx; - struct cvmx_l2c_qos_iobx_cn61xx cn63xxp1; - struct cvmx_l2c_qos_iobx_cn61xx cn66xx; - struct cvmx_l2c_qos_iobx_s cn68xx; - struct cvmx_l2c_qos_iobx_s cn68xxp1; - struct cvmx_l2c_qos_iobx_cn61xx cnf71xx; -}; - -union cvmx_l2c_qos_ppx { - uint64_t u64; - struct cvmx_l2c_qos_ppx_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_3_63:61; - uint64_t lvl:3; -#else - uint64_t lvl:3; - uint64_t reserved_3_63:61; -#endif - } s; - struct cvmx_l2c_qos_ppx_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_2_63:62; - uint64_t lvl:2; -#else - uint64_t lvl:2; - uint64_t reserved_2_63:62; -#endif - } cn61xx; - struct cvmx_l2c_qos_ppx_cn61xx cn63xx; - struct cvmx_l2c_qos_ppx_cn61xx cn63xxp1; - struct cvmx_l2c_qos_ppx_cn61xx cn66xx; - struct cvmx_l2c_qos_ppx_s cn68xx; - struct cvmx_l2c_qos_ppx_s cn68xxp1; - struct cvmx_l2c_qos_ppx_cn61xx cnf71xx; -}; - -union cvmx_l2c_qos_wgt { - uint64_t u64; - struct cvmx_l2c_qos_wgt_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t wgt7:8; - uint64_t wgt6:8; - uint64_t wgt5:8; - uint64_t wgt4:8; - uint64_t wgt3:8; - uint64_t wgt2:8; - uint64_t wgt1:8; - uint64_t wgt0:8; -#else - uint64_t wgt0:8; - uint64_t wgt1:8; - uint64_t wgt2:8; - uint64_t wgt3:8; - uint64_t wgt4:8; - uint64_t wgt5:8; - uint64_t wgt6:8; - uint64_t wgt7:8; -#endif - } s; - struct cvmx_l2c_qos_wgt_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t wgt3:8; - uint64_t wgt2:8; - uint64_t wgt1:8; - uint64_t wgt0:8; -#else - uint64_t wgt0:8; - uint64_t wgt1:8; - uint64_t wgt2:8; - uint64_t wgt3:8; - uint64_t reserved_32_63:32; -#endif - } cn61xx; - struct cvmx_l2c_qos_wgt_cn61xx cn63xx; - struct cvmx_l2c_qos_wgt_cn61xx cn63xxp1; - struct cvmx_l2c_qos_wgt_cn61xx cn66xx; - struct cvmx_l2c_qos_wgt_s cn68xx; - struct cvmx_l2c_qos_wgt_s cn68xxp1; - struct cvmx_l2c_qos_wgt_cn61xx cnf71xx; -}; - -union cvmx_l2c_rscx_pfc { - uint64_t u64; - struct cvmx_l2c_rscx_pfc_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t count:64; -#else - uint64_t count:64; -#endif - } s; - struct cvmx_l2c_rscx_pfc_s cn61xx; - struct cvmx_l2c_rscx_pfc_s cn63xx; - struct cvmx_l2c_rscx_pfc_s cn63xxp1; - struct cvmx_l2c_rscx_pfc_s cn66xx; - struct cvmx_l2c_rscx_pfc_s cn68xx; - struct cvmx_l2c_rscx_pfc_s cn68xxp1; - struct cvmx_l2c_rscx_pfc_s cnf71xx; -}; - -union cvmx_l2c_rsdx_pfc { - uint64_t u64; - struct cvmx_l2c_rsdx_pfc_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t count:64; -#else - uint64_t count:64; -#endif - } s; - struct cvmx_l2c_rsdx_pfc_s cn61xx; - struct cvmx_l2c_rsdx_pfc_s cn63xx; - struct cvmx_l2c_rsdx_pfc_s cn63xxp1; - struct cvmx_l2c_rsdx_pfc_s cn66xx; - struct cvmx_l2c_rsdx_pfc_s cn68xx; - struct cvmx_l2c_rsdx_pfc_s cn68xxp1; - struct cvmx_l2c_rsdx_pfc_s cnf71xx; -}; - -union cvmx_l2c_spar0 { - uint64_t u64; - struct cvmx_l2c_spar0_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t umsk3:8; - uint64_t umsk2:8; - uint64_t umsk1:8; - uint64_t umsk0:8; -#else - uint64_t umsk0:8; - uint64_t umsk1:8; - uint64_t umsk2:8; - uint64_t umsk3:8; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_l2c_spar0_cn30xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_4_63:60; - uint64_t umsk0:4; -#else - uint64_t umsk0:4; - uint64_t reserved_4_63:60; -#endif - } cn30xx; - struct cvmx_l2c_spar0_cn31xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_12_63:52; - uint64_t umsk1:4; - uint64_t reserved_4_7:4; - uint64_t umsk0:4; -#else - uint64_t umsk0:4; - uint64_t reserved_4_7:4; - uint64_t umsk1:4; - uint64_t reserved_12_63:52; -#endif - } cn31xx; - struct cvmx_l2c_spar0_s cn38xx; - struct cvmx_l2c_spar0_s cn38xxp2; - struct cvmx_l2c_spar0_cn50xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_16_63:48; - uint64_t umsk1:8; - uint64_t umsk0:8; -#else - uint64_t umsk0:8; - uint64_t umsk1:8; - uint64_t reserved_16_63:48; -#endif - } cn50xx; - struct cvmx_l2c_spar0_s cn52xx; - struct cvmx_l2c_spar0_s cn52xxp1; - struct cvmx_l2c_spar0_s cn56xx; - struct cvmx_l2c_spar0_s cn56xxp1; - struct cvmx_l2c_spar0_s cn58xx; - struct cvmx_l2c_spar0_s cn58xxp1; -}; - -union cvmx_l2c_spar1 { - uint64_t u64; - struct cvmx_l2c_spar1_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t umsk7:8; - uint64_t umsk6:8; - uint64_t umsk5:8; - uint64_t umsk4:8; -#else - uint64_t umsk4:8; - uint64_t umsk5:8; - uint64_t umsk6:8; - uint64_t umsk7:8; - uint64_t reserved_32_63:32; -#endif + __BITFIELD_FIELD(uint64_t reserved_36_63:28, + __BITFIELD_FIELD(uint64_t cnt3rdclr:1, + __BITFIELD_FIELD(uint64_t cnt2rdclr:1, + __BITFIELD_FIELD(uint64_t cnt1rdclr:1, + __BITFIELD_FIELD(uint64_t cnt0rdclr:1, + __BITFIELD_FIELD(uint64_t cnt3ena:1, + __BITFIELD_FIELD(uint64_t cnt3clr:1, + __BITFIELD_FIELD(uint64_t cnt3sel:6, + __BITFIELD_FIELD(uint64_t cnt2ena:1, + __BITFIELD_FIELD(uint64_t cnt2clr:1, + __BITFIELD_FIELD(uint64_t cnt2sel:6, + __BITFIELD_FIELD(uint64_t cnt1ena:1, + __BITFIELD_FIELD(uint64_t cnt1clr:1, + __BITFIELD_FIELD(uint64_t cnt1sel:6, + __BITFIELD_FIELD(uint64_t cnt0ena:1, + __BITFIELD_FIELD(uint64_t cnt0clr:1, + __BITFIELD_FIELD(uint64_t cnt0sel:6, + ;))))))))))))))))) } s; - struct cvmx_l2c_spar1_s cn38xx; - struct cvmx_l2c_spar1_s cn38xxp2; - struct cvmx_l2c_spar1_s cn56xx; - struct cvmx_l2c_spar1_s cn56xxp1; - struct cvmx_l2c_spar1_s cn58xx; - struct cvmx_l2c_spar1_s cn58xxp1; -}; - -union cvmx_l2c_spar2 { - uint64_t u64; - struct cvmx_l2c_spar2_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t umsk11:8; - uint64_t umsk10:8; - uint64_t umsk9:8; - uint64_t umsk8:8; -#else - uint64_t umsk8:8; - uint64_t umsk9:8; - uint64_t umsk10:8; - uint64_t umsk11:8; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_l2c_spar2_s cn38xx; - struct cvmx_l2c_spar2_s cn38xxp2; - struct cvmx_l2c_spar2_s cn56xx; - struct cvmx_l2c_spar2_s cn56xxp1; - struct cvmx_l2c_spar2_s cn58xx; - struct cvmx_l2c_spar2_s cn58xxp1; -}; - -union cvmx_l2c_spar3 { - uint64_t u64; - struct cvmx_l2c_spar3_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t umsk15:8; - uint64_t umsk14:8; - uint64_t umsk13:8; - uint64_t umsk12:8; -#else - uint64_t umsk12:8; - uint64_t umsk13:8; - uint64_t umsk14:8; - uint64_t umsk15:8; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_l2c_spar3_s cn38xx; - struct cvmx_l2c_spar3_s cn38xxp2; - struct cvmx_l2c_spar3_s cn58xx; - struct cvmx_l2c_spar3_s cn58xxp1; -}; - -union cvmx_l2c_spar4 { - uint64_t u64; - struct cvmx_l2c_spar4_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_8_63:56; - uint64_t umskiob:8; -#else - uint64_t umskiob:8; - uint64_t reserved_8_63:56; -#endif - } s; - struct cvmx_l2c_spar4_cn30xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_4_63:60; - uint64_t umskiob:4; -#else - uint64_t umskiob:4; - uint64_t reserved_4_63:60; -#endif - } cn30xx; - struct cvmx_l2c_spar4_cn30xx cn31xx; - struct cvmx_l2c_spar4_s cn38xx; - struct cvmx_l2c_spar4_s cn38xxp2; - struct cvmx_l2c_spar4_s cn50xx; - struct cvmx_l2c_spar4_s cn52xx; - struct cvmx_l2c_spar4_s cn52xxp1; - struct cvmx_l2c_spar4_s cn56xx; - struct cvmx_l2c_spar4_s cn56xxp1; - struct cvmx_l2c_spar4_s cn58xx; - struct cvmx_l2c_spar4_s cn58xxp1; -}; - -union cvmx_l2c_tadx_ecc0 { - uint64_t u64; - struct cvmx_l2c_tadx_ecc0_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_58_63:6; - uint64_t ow3ecc:10; - uint64_t reserved_42_47:6; - uint64_t ow2ecc:10; - uint64_t reserved_26_31:6; - uint64_t ow1ecc:10; - uint64_t reserved_10_15:6; - uint64_t ow0ecc:10; -#else - uint64_t ow0ecc:10; - uint64_t reserved_10_15:6; - uint64_t ow1ecc:10; - uint64_t reserved_26_31:6; - uint64_t ow2ecc:10; - uint64_t reserved_42_47:6; - uint64_t ow3ecc:10; - uint64_t reserved_58_63:6; -#endif - } s; - struct cvmx_l2c_tadx_ecc0_s cn61xx; - struct cvmx_l2c_tadx_ecc0_s cn63xx; - struct cvmx_l2c_tadx_ecc0_s cn63xxp1; - struct cvmx_l2c_tadx_ecc0_s cn66xx; - struct cvmx_l2c_tadx_ecc0_s cn68xx; - struct cvmx_l2c_tadx_ecc0_s cn68xxp1; - struct cvmx_l2c_tadx_ecc0_s cnf71xx; -}; - -union cvmx_l2c_tadx_ecc1 { - uint64_t u64; - struct cvmx_l2c_tadx_ecc1_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_58_63:6; - uint64_t ow7ecc:10; - uint64_t reserved_42_47:6; - uint64_t ow6ecc:10; - uint64_t reserved_26_31:6; - uint64_t ow5ecc:10; - uint64_t reserved_10_15:6; - uint64_t ow4ecc:10; -#else - uint64_t ow4ecc:10; - uint64_t reserved_10_15:6; - uint64_t ow5ecc:10; - uint64_t reserved_26_31:6; - uint64_t ow6ecc:10; - uint64_t reserved_42_47:6; - uint64_t ow7ecc:10; - uint64_t reserved_58_63:6; -#endif - } s; - struct cvmx_l2c_tadx_ecc1_s cn61xx; - struct cvmx_l2c_tadx_ecc1_s cn63xx; - struct cvmx_l2c_tadx_ecc1_s cn63xxp1; - struct cvmx_l2c_tadx_ecc1_s cn66xx; - struct cvmx_l2c_tadx_ecc1_s cn68xx; - struct cvmx_l2c_tadx_ecc1_s cn68xxp1; - struct cvmx_l2c_tadx_ecc1_s cnf71xx; -}; - -union cvmx_l2c_tadx_ien { - uint64_t u64; - struct cvmx_l2c_tadx_ien_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_9_63:55; - uint64_t wrdislmc:1; - uint64_t rddislmc:1; - uint64_t noway:1; - uint64_t vbfdbe:1; - uint64_t vbfsbe:1; - uint64_t tagdbe:1; - uint64_t tagsbe:1; - uint64_t l2ddbe:1; - uint64_t l2dsbe:1; -#else - uint64_t l2dsbe:1; - uint64_t l2ddbe:1; - uint64_t tagsbe:1; - uint64_t tagdbe:1; - uint64_t vbfsbe:1; - uint64_t vbfdbe:1; - uint64_t noway:1; - uint64_t rddislmc:1; - uint64_t wrdislmc:1; - uint64_t reserved_9_63:55; -#endif - } s; - struct cvmx_l2c_tadx_ien_s cn61xx; - struct cvmx_l2c_tadx_ien_s cn63xx; - struct cvmx_l2c_tadx_ien_cn63xxp1 { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_7_63:57; - uint64_t noway:1; - uint64_t vbfdbe:1; - uint64_t vbfsbe:1; - uint64_t tagdbe:1; - uint64_t tagsbe:1; - uint64_t l2ddbe:1; - uint64_t l2dsbe:1; -#else - uint64_t l2dsbe:1; - uint64_t l2ddbe:1; - uint64_t tagsbe:1; - uint64_t tagdbe:1; - uint64_t vbfsbe:1; - uint64_t vbfdbe:1; - uint64_t noway:1; - uint64_t reserved_7_63:57; -#endif - } cn63xxp1; - struct cvmx_l2c_tadx_ien_s cn66xx; - struct cvmx_l2c_tadx_ien_s cn68xx; - struct cvmx_l2c_tadx_ien_s cn68xxp1; - struct cvmx_l2c_tadx_ien_s cnf71xx; -}; - -union cvmx_l2c_tadx_int { - uint64_t u64; - struct cvmx_l2c_tadx_int_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_9_63:55; - uint64_t wrdislmc:1; - uint64_t rddislmc:1; - uint64_t noway:1; - uint64_t vbfdbe:1; - uint64_t vbfsbe:1; - uint64_t tagdbe:1; - uint64_t tagsbe:1; - uint64_t l2ddbe:1; - uint64_t l2dsbe:1; -#else - uint64_t l2dsbe:1; - uint64_t l2ddbe:1; - uint64_t tagsbe:1; - uint64_t tagdbe:1; - uint64_t vbfsbe:1; - uint64_t vbfdbe:1; - uint64_t noway:1; - uint64_t rddislmc:1; - uint64_t wrdislmc:1; - uint64_t reserved_9_63:55; -#endif - } s; - struct cvmx_l2c_tadx_int_s cn61xx; - struct cvmx_l2c_tadx_int_s cn63xx; - struct cvmx_l2c_tadx_int_s cn66xx; - struct cvmx_l2c_tadx_int_s cn68xx; - struct cvmx_l2c_tadx_int_s cn68xxp1; - struct cvmx_l2c_tadx_int_s cnf71xx; -}; - -union cvmx_l2c_tadx_pfc0 { - uint64_t u64; - struct cvmx_l2c_tadx_pfc0_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t count:64; -#else - uint64_t count:64; -#endif - } s; - struct cvmx_l2c_tadx_pfc0_s cn61xx; - struct cvmx_l2c_tadx_pfc0_s cn63xx; - struct cvmx_l2c_tadx_pfc0_s cn63xxp1; - struct cvmx_l2c_tadx_pfc0_s cn66xx; - struct cvmx_l2c_tadx_pfc0_s cn68xx; - struct cvmx_l2c_tadx_pfc0_s cn68xxp1; - struct cvmx_l2c_tadx_pfc0_s cnf71xx; -}; - -union cvmx_l2c_tadx_pfc1 { - uint64_t u64; - struct cvmx_l2c_tadx_pfc1_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t count:64; -#else - uint64_t count:64; -#endif - } s; - struct cvmx_l2c_tadx_pfc1_s cn61xx; - struct cvmx_l2c_tadx_pfc1_s cn63xx; - struct cvmx_l2c_tadx_pfc1_s cn63xxp1; - struct cvmx_l2c_tadx_pfc1_s cn66xx; - struct cvmx_l2c_tadx_pfc1_s cn68xx; - struct cvmx_l2c_tadx_pfc1_s cn68xxp1; - struct cvmx_l2c_tadx_pfc1_s cnf71xx; -}; - -union cvmx_l2c_tadx_pfc2 { - uint64_t u64; - struct cvmx_l2c_tadx_pfc2_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t count:64; -#else - uint64_t count:64; -#endif - } s; - struct cvmx_l2c_tadx_pfc2_s cn61xx; - struct cvmx_l2c_tadx_pfc2_s cn63xx; - struct cvmx_l2c_tadx_pfc2_s cn63xxp1; - struct cvmx_l2c_tadx_pfc2_s cn66xx; - struct cvmx_l2c_tadx_pfc2_s cn68xx; - struct cvmx_l2c_tadx_pfc2_s cn68xxp1; - struct cvmx_l2c_tadx_pfc2_s cnf71xx; -}; - -union cvmx_l2c_tadx_pfc3 { - uint64_t u64; - struct cvmx_l2c_tadx_pfc3_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t count:64; -#else - uint64_t count:64; -#endif - } s; - struct cvmx_l2c_tadx_pfc3_s cn61xx; - struct cvmx_l2c_tadx_pfc3_s cn63xx; - struct cvmx_l2c_tadx_pfc3_s cn63xxp1; - struct cvmx_l2c_tadx_pfc3_s cn66xx; - struct cvmx_l2c_tadx_pfc3_s cn68xx; - struct cvmx_l2c_tadx_pfc3_s cn68xxp1; - struct cvmx_l2c_tadx_pfc3_s cnf71xx; }; union cvmx_l2c_tadx_prf { uint64_t u64; struct cvmx_l2c_tadx_prf_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t cnt3sel:8; - uint64_t cnt2sel:8; - uint64_t cnt1sel:8; - uint64_t cnt0sel:8; -#else - uint64_t cnt0sel:8; - uint64_t cnt1sel:8; - uint64_t cnt2sel:8; - uint64_t cnt3sel:8; - uint64_t reserved_32_63:32; -#endif + __BITFIELD_FIELD(uint64_t reserved_32_63:32, + __BITFIELD_FIELD(uint64_t cnt3sel:8, + __BITFIELD_FIELD(uint64_t cnt2sel:8, + __BITFIELD_FIELD(uint64_t cnt1sel:8, + __BITFIELD_FIELD(uint64_t cnt0sel:8, + ;))))) } s; - struct cvmx_l2c_tadx_prf_s cn61xx; - struct cvmx_l2c_tadx_prf_s cn63xx; - struct cvmx_l2c_tadx_prf_s cn63xxp1; - struct cvmx_l2c_tadx_prf_s cn66xx; - struct cvmx_l2c_tadx_prf_s cn68xx; - struct cvmx_l2c_tadx_prf_s cn68xxp1; - struct cvmx_l2c_tadx_prf_s cnf71xx; }; union cvmx_l2c_tadx_tag { uint64_t u64; struct cvmx_l2c_tadx_tag_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_46_63:18; - uint64_t ecc:6; - uint64_t reserved_36_39:4; - uint64_t tag:19; - uint64_t reserved_4_16:13; - uint64_t use:1; - uint64_t valid:1; - uint64_t dirty:1; - uint64_t lock:1; -#else - uint64_t lock:1; - uint64_t dirty:1; - uint64_t valid:1; - uint64_t use:1; - uint64_t reserved_4_16:13; - uint64_t tag:19; - uint64_t reserved_36_39:4; - uint64_t ecc:6; - uint64_t reserved_46_63:18; -#endif - } s; - struct cvmx_l2c_tadx_tag_s cn61xx; - struct cvmx_l2c_tadx_tag_s cn63xx; - struct cvmx_l2c_tadx_tag_s cn63xxp1; - struct cvmx_l2c_tadx_tag_s cn66xx; - struct cvmx_l2c_tadx_tag_s cn68xx; - struct cvmx_l2c_tadx_tag_s cn68xxp1; - struct cvmx_l2c_tadx_tag_s cnf71xx; -}; - -union cvmx_l2c_ver_id { - uint64_t u64; - struct cvmx_l2c_ver_id_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t mask:64; -#else - uint64_t mask:64; -#endif - } s; - struct cvmx_l2c_ver_id_s cn61xx; - struct cvmx_l2c_ver_id_s cn63xx; - struct cvmx_l2c_ver_id_s cn63xxp1; - struct cvmx_l2c_ver_id_s cn66xx; - struct cvmx_l2c_ver_id_s cn68xx; - struct cvmx_l2c_ver_id_s cn68xxp1; - struct cvmx_l2c_ver_id_s cnf71xx; -}; - -union cvmx_l2c_ver_iob { - uint64_t u64; - struct cvmx_l2c_ver_iob_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_2_63:62; - uint64_t mask:2; -#else - uint64_t mask:2; - uint64_t reserved_2_63:62; -#endif - } s; - struct cvmx_l2c_ver_iob_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_1_63:63; - uint64_t mask:1; -#else - uint64_t mask:1; - uint64_t reserved_1_63:63; -#endif - } cn61xx; - struct cvmx_l2c_ver_iob_cn61xx cn63xx; - struct cvmx_l2c_ver_iob_cn61xx cn63xxp1; - struct cvmx_l2c_ver_iob_cn61xx cn66xx; - struct cvmx_l2c_ver_iob_s cn68xx; - struct cvmx_l2c_ver_iob_s cn68xxp1; - struct cvmx_l2c_ver_iob_cn61xx cnf71xx; -}; - -union cvmx_l2c_ver_msc { - uint64_t u64; - struct cvmx_l2c_ver_msc_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_2_63:62; - uint64_t invl2:1; - uint64_t dwb:1; -#else - uint64_t dwb:1; - uint64_t invl2:1; - uint64_t reserved_2_63:62; -#endif + __BITFIELD_FIELD(uint64_t reserved_46_63:18, + __BITFIELD_FIELD(uint64_t ecc:6, + __BITFIELD_FIELD(uint64_t reserved_36_39:4, + __BITFIELD_FIELD(uint64_t tag:19, + __BITFIELD_FIELD(uint64_t reserved_4_16:13, + __BITFIELD_FIELD(uint64_t use:1, + __BITFIELD_FIELD(uint64_t valid:1, + __BITFIELD_FIELD(uint64_t dirty:1, + __BITFIELD_FIELD(uint64_t lock:1, + ;))))))))) } s; - struct cvmx_l2c_ver_msc_s cn61xx; - struct cvmx_l2c_ver_msc_s cn63xx; - struct cvmx_l2c_ver_msc_s cn66xx; - struct cvmx_l2c_ver_msc_s cn68xx; - struct cvmx_l2c_ver_msc_s cn68xxp1; - struct cvmx_l2c_ver_msc_s cnf71xx; }; -union cvmx_l2c_ver_pp { - uint64_t u64; - struct cvmx_l2c_ver_pp_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t mask:32; -#else - uint64_t mask:32; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_l2c_ver_pp_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_4_63:60; - uint64_t mask:4; -#else - uint64_t mask:4; - uint64_t reserved_4_63:60; -#endif - } cn61xx; - struct cvmx_l2c_ver_pp_cn63xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_6_63:58; - uint64_t mask:6; -#else - uint64_t mask:6; - uint64_t reserved_6_63:58; -#endif - } cn63xx; - struct cvmx_l2c_ver_pp_cn63xx cn63xxp1; - struct cvmx_l2c_ver_pp_cn66xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_10_63:54; - uint64_t mask:10; -#else - uint64_t mask:10; - uint64_t reserved_10_63:54; -#endif - } cn66xx; - struct cvmx_l2c_ver_pp_s cn68xx; - struct cvmx_l2c_ver_pp_s cn68xxp1; - struct cvmx_l2c_ver_pp_cn61xx cnf71xx; -}; - -union cvmx_l2c_virtid_iobx { - uint64_t u64; - struct cvmx_l2c_virtid_iobx_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_14_63:50; - uint64_t dwbid:6; - uint64_t reserved_6_7:2; - uint64_t id:6; -#else - uint64_t id:6; - uint64_t reserved_6_7:2; - uint64_t dwbid:6; - uint64_t reserved_14_63:50; -#endif - } s; - struct cvmx_l2c_virtid_iobx_s cn61xx; - struct cvmx_l2c_virtid_iobx_s cn63xx; - struct cvmx_l2c_virtid_iobx_s cn63xxp1; - struct cvmx_l2c_virtid_iobx_s cn66xx; - struct cvmx_l2c_virtid_iobx_s cn68xx; - struct cvmx_l2c_virtid_iobx_s cn68xxp1; - struct cvmx_l2c_virtid_iobx_s cnf71xx; -}; - -union cvmx_l2c_virtid_ppx { - uint64_t u64; - struct cvmx_l2c_virtid_ppx_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_6_63:58; - uint64_t id:6; -#else - uint64_t id:6; - uint64_t reserved_6_63:58; -#endif - } s; - struct cvmx_l2c_virtid_ppx_s cn61xx; - struct cvmx_l2c_virtid_ppx_s cn63xx; - struct cvmx_l2c_virtid_ppx_s cn63xxp1; - struct cvmx_l2c_virtid_ppx_s cn66xx; - struct cvmx_l2c_virtid_ppx_s cn68xx; - struct cvmx_l2c_virtid_ppx_s cn68xxp1; - struct cvmx_l2c_virtid_ppx_s cnf71xx; -}; - -union cvmx_l2c_vrt_ctl { - uint64_t u64; - struct cvmx_l2c_vrt_ctl_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_9_63:55; - uint64_t ooberr:1; - uint64_t reserved_7_7:1; - uint64_t memsz:3; - uint64_t numid:3; - uint64_t enable:1; -#else - uint64_t enable:1; - uint64_t numid:3; - uint64_t memsz:3; - uint64_t reserved_7_7:1; - uint64_t ooberr:1; - uint64_t reserved_9_63:55; -#endif - } s; - struct cvmx_l2c_vrt_ctl_s cn61xx; - struct cvmx_l2c_vrt_ctl_s cn63xx; - struct cvmx_l2c_vrt_ctl_s cn63xxp1; - struct cvmx_l2c_vrt_ctl_s cn66xx; - struct cvmx_l2c_vrt_ctl_s cn68xx; - struct cvmx_l2c_vrt_ctl_s cn68xxp1; - struct cvmx_l2c_vrt_ctl_s cnf71xx; -}; - -union cvmx_l2c_vrt_memx { - uint64_t u64; - struct cvmx_l2c_vrt_memx_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_36_63:28; - uint64_t parity:4; - uint64_t data:32; -#else - uint64_t data:32; - uint64_t parity:4; - uint64_t reserved_36_63:28; -#endif - } s; - struct cvmx_l2c_vrt_memx_s cn61xx; - struct cvmx_l2c_vrt_memx_s cn63xx; - struct cvmx_l2c_vrt_memx_s cn63xxp1; - struct cvmx_l2c_vrt_memx_s cn66xx; - struct cvmx_l2c_vrt_memx_s cn68xx; - struct cvmx_l2c_vrt_memx_s cn68xxp1; - struct cvmx_l2c_vrt_memx_s cnf71xx; -}; - -union cvmx_l2c_wpar_iobx { - uint64_t u64; - struct cvmx_l2c_wpar_iobx_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_16_63:48; - uint64_t mask:16; -#else - uint64_t mask:16; - uint64_t reserved_16_63:48; -#endif - } s; - struct cvmx_l2c_wpar_iobx_s cn61xx; - struct cvmx_l2c_wpar_iobx_s cn63xx; - struct cvmx_l2c_wpar_iobx_s cn63xxp1; - struct cvmx_l2c_wpar_iobx_s cn66xx; - struct cvmx_l2c_wpar_iobx_s cn68xx; - struct cvmx_l2c_wpar_iobx_s cn68xxp1; - struct cvmx_l2c_wpar_iobx_s cnf71xx; -}; - -union cvmx_l2c_wpar_ppx { - uint64_t u64; - struct cvmx_l2c_wpar_ppx_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_16_63:48; - uint64_t mask:16; -#else - uint64_t mask:16; - uint64_t reserved_16_63:48; -#endif - } s; - struct cvmx_l2c_wpar_ppx_s cn61xx; - struct cvmx_l2c_wpar_ppx_s cn63xx; - struct cvmx_l2c_wpar_ppx_s cn63xxp1; - struct cvmx_l2c_wpar_ppx_s cn66xx; - struct cvmx_l2c_wpar_ppx_s cn68xx; - struct cvmx_l2c_wpar_ppx_s cn68xxp1; - struct cvmx_l2c_wpar_ppx_s cnf71xx; -}; - -union cvmx_l2c_xmcx_pfc { - uint64_t u64; - struct cvmx_l2c_xmcx_pfc_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t count:64; -#else - uint64_t count:64; -#endif - } s; - struct cvmx_l2c_xmcx_pfc_s cn61xx; - struct cvmx_l2c_xmcx_pfc_s cn63xx; - struct cvmx_l2c_xmcx_pfc_s cn63xxp1; - struct cvmx_l2c_xmcx_pfc_s cn66xx; - struct cvmx_l2c_xmcx_pfc_s cn68xx; - struct cvmx_l2c_xmcx_pfc_s cn68xxp1; - struct cvmx_l2c_xmcx_pfc_s cnf71xx; -}; - -union cvmx_l2c_xmc_cmd { +union cvmx_l2c_lckbase { uint64_t u64; - struct cvmx_l2c_xmc_cmd_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t inuse:1; - uint64_t cmd:6; - uint64_t reserved_38_56:19; - uint64_t addr:38; -#else - uint64_t addr:38; - uint64_t reserved_38_56:19; - uint64_t cmd:6; - uint64_t inuse:1; -#endif + struct cvmx_l2c_lckbase_s { + __BITFIELD_FIELD(uint64_t reserved_31_63:33, + __BITFIELD_FIELD(uint64_t lck_base:27, + __BITFIELD_FIELD(uint64_t reserved_1_3:3, + __BITFIELD_FIELD(uint64_t lck_ena:1, + ;)))) } s; - struct cvmx_l2c_xmc_cmd_s cn61xx; - struct cvmx_l2c_xmc_cmd_s cn63xx; - struct cvmx_l2c_xmc_cmd_s cn63xxp1; - struct cvmx_l2c_xmc_cmd_s cn66xx; - struct cvmx_l2c_xmc_cmd_s cn68xx; - struct cvmx_l2c_xmc_cmd_s cn68xxp1; - struct cvmx_l2c_xmc_cmd_s cnf71xx; }; -union cvmx_l2c_xmdx_pfc { +union cvmx_l2c_lckoff { uint64_t u64; - struct cvmx_l2c_xmdx_pfc_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t count:64; -#else - uint64_t count:64; -#endif + struct cvmx_l2c_lckoff_s { + __BITFIELD_FIELD(uint64_t reserved_10_63:54, + __BITFIELD_FIELD(uint64_t lck_offset:10, + ;)) } s; - struct cvmx_l2c_xmdx_pfc_s cn61xx; - struct cvmx_l2c_xmdx_pfc_s cn63xx; - struct cvmx_l2c_xmdx_pfc_s cn63xxp1; - struct cvmx_l2c_xmdx_pfc_s cn66xx; - struct cvmx_l2c_xmdx_pfc_s cn68xx; - struct cvmx_l2c_xmdx_pfc_s cn68xxp1; - struct cvmx_l2c_xmdx_pfc_s cnf71xx; }; #endif diff --git a/arch/mips/include/asm/octeon/cvmx-l2c.h b/arch/mips/include/asm/octeon/cvmx-l2c.h index ddb429210a0e..02c4479a90c8 100644 --- a/arch/mips/include/asm/octeon/cvmx-l2c.h +++ b/arch/mips/include/asm/octeon/cvmx-l2c.h @@ -4,7 +4,7 @@ * Contact: support@caviumnetworks.com * This file is part of the OCTEON SDK * - * Copyright (c) 2003-2010 Cavium Networks + * Copyright (c) 2003-2017 Cavium, Inc. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as @@ -33,48 +33,39 @@ #ifndef __CVMX_L2C_H__ #define __CVMX_L2C_H__ -#define CVMX_L2_ASSOC cvmx_l2c_get_num_assoc() /* Deprecated macro, use function */ -#define CVMX_L2_SET_BITS cvmx_l2c_get_set_bits() /* Deprecated macro, use function */ -#define CVMX_L2_SETS cvmx_l2c_get_num_sets() /* Deprecated macro, use function */ +#include +#define CVMX_L2_ASSOC cvmx_l2c_get_num_assoc() /* Deprecated macro */ +#define CVMX_L2_SET_BITS cvmx_l2c_get_set_bits() /* Deprecated macro */ +#define CVMX_L2_SETS cvmx_l2c_get_num_sets() /* Deprecated macro */ -#define CVMX_L2C_IDX_ADDR_SHIFT 7 /* based on 128 byte cache line size */ +/* Based on 128 byte cache line size */ +#define CVMX_L2C_IDX_ADDR_SHIFT 7 #define CVMX_L2C_IDX_MASK (cvmx_l2c_get_num_sets() - 1) /* Defines for index aliasing computations */ -#define CVMX_L2C_TAG_ADDR_ALIAS_SHIFT (CVMX_L2C_IDX_ADDR_SHIFT + cvmx_l2c_get_set_bits()) +#define CVMX_L2C_TAG_ADDR_ALIAS_SHIFT (CVMX_L2C_IDX_ADDR_SHIFT + \ + cvmx_l2c_get_set_bits()) #define CVMX_L2C_ALIAS_MASK (CVMX_L2C_IDX_MASK << CVMX_L2C_TAG_ADDR_ALIAS_SHIFT) -#define CVMX_L2C_MEMBANK_SELECT_SIZE 4096 +#define CVMX_L2C_MEMBANK_SELECT_SIZE 4096 -/* Defines for Virtualizations, valid only from Octeon II onwards. */ -#define CVMX_L2C_VRT_MAX_VIRTID_ALLOWED ((OCTEON_IS_MODEL(OCTEON_CN63XX)) ? 64 : 0) -#define CVMX_L2C_VRT_MAX_MEMSZ_ALLOWED ((OCTEON_IS_MODEL(OCTEON_CN63XX)) ? 32 : 0) +/* Number of L2C Tag-and-data sections (TADs) that are connected to LMC. */ +#define CVMX_L2C_TADS 1 union cvmx_l2c_tag { uint64_t u64; struct { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved:28; - uint64_t V:1; /* Line valid */ - uint64_t D:1; /* Line dirty */ - uint64_t L:1; /* Line locked */ - uint64_t U:1; /* Use, LRU eviction */ - uint64_t addr:32; /* Phys mem (not all bits valid) */ -#else - uint64_t addr:32; /* Phys mem (not all bits valid) */ - uint64_t U:1; /* Use, LRU eviction */ - uint64_t L:1; /* Line locked */ - uint64_t D:1; /* Line dirty */ - uint64_t V:1; /* Line valid */ - uint64_t reserved:28; -#endif + __BITFIELD_FIELD(uint64_t reserved:28, + __BITFIELD_FIELD(uint64_t V:1, + __BITFIELD_FIELD(uint64_t D:1, + __BITFIELD_FIELD(uint64_t L:1, + __BITFIELD_FIELD(uint64_t U:1, + __BITFIELD_FIELD(uint64_t addr:32, + ;)))))) } s; }; -/* Number of L2C Tag-and-data sections (TADs) that are connected to LMC. */ -#define CVMX_L2C_TADS 1 - - /* L2C Performance Counter events. */ +/* L2C Performance Counter events. */ enum cvmx_l2c_event { CVMX_L2C_EVENT_CYCLES = 0, CVMX_L2C_EVENT_INSTRUCTION_MISS = 1, @@ -175,7 +166,8 @@ enum cvmx_l2c_tad_event { * * @note The routine does not clear the counter. */ -void cvmx_l2c_config_perf(uint32_t counter, enum cvmx_l2c_event event, uint32_t clear_on_read); +void cvmx_l2c_config_perf(uint32_t counter, enum cvmx_l2c_event event, + uint32_t clear_on_read); /** * Read the given L2 Cache performance counter. The counter must be configured @@ -307,8 +299,11 @@ int cvmx_l2c_unlock_mem_region(uint64_t start, uint64_t len); union cvmx_l2c_tag cvmx_l2c_get_tag(uint32_t association, uint32_t index); /* Wrapper providing a deprecated old function name */ -static inline union cvmx_l2c_tag cvmx_get_l2c_tag(uint32_t association, uint32_t index) __attribute__((deprecated)); -static inline union cvmx_l2c_tag cvmx_get_l2c_tag(uint32_t association, uint32_t index) +static inline union cvmx_l2c_tag cvmx_get_l2c_tag(uint32_t association, + uint32_t index) + __attribute__((deprecated)); +static inline union cvmx_l2c_tag cvmx_get_l2c_tag(uint32_t association, + uint32_t index) { return cvmx_l2c_get_tag(association, index); } diff --git a/arch/mips/include/asm/octeon/cvmx-l2d-defs.h b/arch/mips/include/asm/octeon/cvmx-l2d-defs.h deleted file mode 100644 index 11a456215638..000000000000 --- a/arch/mips/include/asm/octeon/cvmx-l2d-defs.h +++ /dev/null @@ -1,526 +0,0 @@ -/***********************license start*************** - * Author: Cavium Networks - * - * Contact: support@caviumnetworks.com - * This file is part of the OCTEON SDK - * - * Copyright (c) 2003-2012 Cavium Networks - * - * This file is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, Version 2, as - * published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, but - * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or - * NONINFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * or visit http://www.gnu.org/licenses/. - * - * This file may also be available under a different license from Cavium. - * Contact Cavium Networks for more information - ***********************license end**************************************/ - -#ifndef __CVMX_L2D_DEFS_H__ -#define __CVMX_L2D_DEFS_H__ - -#define CVMX_L2D_BST0 (CVMX_ADD_IO_SEG(0x0001180080000780ull)) -#define CVMX_L2D_BST1 (CVMX_ADD_IO_SEG(0x0001180080000788ull)) -#define CVMX_L2D_BST2 (CVMX_ADD_IO_SEG(0x0001180080000790ull)) -#define CVMX_L2D_BST3 (CVMX_ADD_IO_SEG(0x0001180080000798ull)) -#define CVMX_L2D_ERR (CVMX_ADD_IO_SEG(0x0001180080000010ull)) -#define CVMX_L2D_FADR (CVMX_ADD_IO_SEG(0x0001180080000018ull)) -#define CVMX_L2D_FSYN0 (CVMX_ADD_IO_SEG(0x0001180080000020ull)) -#define CVMX_L2D_FSYN1 (CVMX_ADD_IO_SEG(0x0001180080000028ull)) -#define CVMX_L2D_FUS0 (CVMX_ADD_IO_SEG(0x00011800800007A0ull)) -#define CVMX_L2D_FUS1 (CVMX_ADD_IO_SEG(0x00011800800007A8ull)) -#define CVMX_L2D_FUS2 (CVMX_ADD_IO_SEG(0x00011800800007B0ull)) -#define CVMX_L2D_FUS3 (CVMX_ADD_IO_SEG(0x00011800800007B8ull)) - -union cvmx_l2d_bst0 { - uint64_t u64; - struct cvmx_l2d_bst0_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_35_63:29; - uint64_t ftl:1; - uint64_t q0stat:34; -#else - uint64_t q0stat:34; - uint64_t ftl:1; - uint64_t reserved_35_63:29; -#endif - } s; - struct cvmx_l2d_bst0_s cn30xx; - struct cvmx_l2d_bst0_s cn31xx; - struct cvmx_l2d_bst0_s cn38xx; - struct cvmx_l2d_bst0_s cn38xxp2; - struct cvmx_l2d_bst0_s cn50xx; - struct cvmx_l2d_bst0_s cn52xx; - struct cvmx_l2d_bst0_s cn52xxp1; - struct cvmx_l2d_bst0_s cn56xx; - struct cvmx_l2d_bst0_s cn56xxp1; - struct cvmx_l2d_bst0_s cn58xx; - struct cvmx_l2d_bst0_s cn58xxp1; -}; - -union cvmx_l2d_bst1 { - uint64_t u64; - struct cvmx_l2d_bst1_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_34_63:30; - uint64_t q1stat:34; -#else - uint64_t q1stat:34; - uint64_t reserved_34_63:30; -#endif - } s; - struct cvmx_l2d_bst1_s cn30xx; - struct cvmx_l2d_bst1_s cn31xx; - struct cvmx_l2d_bst1_s cn38xx; - struct cvmx_l2d_bst1_s cn38xxp2; - struct cvmx_l2d_bst1_s cn50xx; - struct cvmx_l2d_bst1_s cn52xx; - struct cvmx_l2d_bst1_s cn52xxp1; - struct cvmx_l2d_bst1_s cn56xx; - struct cvmx_l2d_bst1_s cn56xxp1; - struct cvmx_l2d_bst1_s cn58xx; - struct cvmx_l2d_bst1_s cn58xxp1; -}; - -union cvmx_l2d_bst2 { - uint64_t u64; - struct cvmx_l2d_bst2_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_34_63:30; - uint64_t q2stat:34; -#else - uint64_t q2stat:34; - uint64_t reserved_34_63:30; -#endif - } s; - struct cvmx_l2d_bst2_s cn30xx; - struct cvmx_l2d_bst2_s cn31xx; - struct cvmx_l2d_bst2_s cn38xx; - struct cvmx_l2d_bst2_s cn38xxp2; - struct cvmx_l2d_bst2_s cn50xx; - struct cvmx_l2d_bst2_s cn52xx; - struct cvmx_l2d_bst2_s cn52xxp1; - struct cvmx_l2d_bst2_s cn56xx; - struct cvmx_l2d_bst2_s cn56xxp1; - struct cvmx_l2d_bst2_s cn58xx; - struct cvmx_l2d_bst2_s cn58xxp1; -}; - -union cvmx_l2d_bst3 { - uint64_t u64; - struct cvmx_l2d_bst3_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_34_63:30; - uint64_t q3stat:34; -#else - uint64_t q3stat:34; - uint64_t reserved_34_63:30; -#endif - } s; - struct cvmx_l2d_bst3_s cn30xx; - struct cvmx_l2d_bst3_s cn31xx; - struct cvmx_l2d_bst3_s cn38xx; - struct cvmx_l2d_bst3_s cn38xxp2; - struct cvmx_l2d_bst3_s cn50xx; - struct cvmx_l2d_bst3_s cn52xx; - struct cvmx_l2d_bst3_s cn52xxp1; - struct cvmx_l2d_bst3_s cn56xx; - struct cvmx_l2d_bst3_s cn56xxp1; - struct cvmx_l2d_bst3_s cn58xx; - struct cvmx_l2d_bst3_s cn58xxp1; -}; - -union cvmx_l2d_err { - uint64_t u64; - struct cvmx_l2d_err_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_6_63:58; - uint64_t bmhclsel:1; - uint64_t ded_err:1; - uint64_t sec_err:1; - uint64_t ded_intena:1; - uint64_t sec_intena:1; - uint64_t ecc_ena:1; -#else - uint64_t ecc_ena:1; - uint64_t sec_intena:1; - uint64_t ded_intena:1; - uint64_t sec_err:1; - uint64_t ded_err:1; - uint64_t bmhclsel:1; - uint64_t reserved_6_63:58; -#endif - } s; - struct cvmx_l2d_err_s cn30xx; - struct cvmx_l2d_err_s cn31xx; - struct cvmx_l2d_err_s cn38xx; - struct cvmx_l2d_err_s cn38xxp2; - struct cvmx_l2d_err_s cn50xx; - struct cvmx_l2d_err_s cn52xx; - struct cvmx_l2d_err_s cn52xxp1; - struct cvmx_l2d_err_s cn56xx; - struct cvmx_l2d_err_s cn56xxp1; - struct cvmx_l2d_err_s cn58xx; - struct cvmx_l2d_err_s cn58xxp1; -}; - -union cvmx_l2d_fadr { - uint64_t u64; - struct cvmx_l2d_fadr_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_19_63:45; - uint64_t fadru:1; - uint64_t fowmsk:4; - uint64_t fset:3; - uint64_t fadr:11; -#else - uint64_t fadr:11; - uint64_t fset:3; - uint64_t fowmsk:4; - uint64_t fadru:1; - uint64_t reserved_19_63:45; -#endif - } s; - struct cvmx_l2d_fadr_cn30xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_18_63:46; - uint64_t fowmsk:4; - uint64_t reserved_13_13:1; - uint64_t fset:2; - uint64_t reserved_9_10:2; - uint64_t fadr:9; -#else - uint64_t fadr:9; - uint64_t reserved_9_10:2; - uint64_t fset:2; - uint64_t reserved_13_13:1; - uint64_t fowmsk:4; - uint64_t reserved_18_63:46; -#endif - } cn30xx; - struct cvmx_l2d_fadr_cn31xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_18_63:46; - uint64_t fowmsk:4; - uint64_t reserved_13_13:1; - uint64_t fset:2; - uint64_t reserved_10_10:1; - uint64_t fadr:10; -#else - uint64_t fadr:10; - uint64_t reserved_10_10:1; - uint64_t fset:2; - uint64_t reserved_13_13:1; - uint64_t fowmsk:4; - uint64_t reserved_18_63:46; -#endif - } cn31xx; - struct cvmx_l2d_fadr_cn38xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_18_63:46; - uint64_t fowmsk:4; - uint64_t fset:3; - uint64_t fadr:11; -#else - uint64_t fadr:11; - uint64_t fset:3; - uint64_t fowmsk:4; - uint64_t reserved_18_63:46; -#endif - } cn38xx; - struct cvmx_l2d_fadr_cn38xx cn38xxp2; - struct cvmx_l2d_fadr_cn50xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_18_63:46; - uint64_t fowmsk:4; - uint64_t fset:3; - uint64_t reserved_8_10:3; - uint64_t fadr:8; -#else - uint64_t fadr:8; - uint64_t reserved_8_10:3; - uint64_t fset:3; - uint64_t fowmsk:4; - uint64_t reserved_18_63:46; -#endif - } cn50xx; - struct cvmx_l2d_fadr_cn52xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_18_63:46; - uint64_t fowmsk:4; - uint64_t fset:3; - uint64_t reserved_10_10:1; - uint64_t fadr:10; -#else - uint64_t fadr:10; - uint64_t reserved_10_10:1; - uint64_t fset:3; - uint64_t fowmsk:4; - uint64_t reserved_18_63:46; -#endif - } cn52xx; - struct cvmx_l2d_fadr_cn52xx cn52xxp1; - struct cvmx_l2d_fadr_s cn56xx; - struct cvmx_l2d_fadr_s cn56xxp1; - struct cvmx_l2d_fadr_s cn58xx; - struct cvmx_l2d_fadr_s cn58xxp1; -}; - -union cvmx_l2d_fsyn0 { - uint64_t u64; - struct cvmx_l2d_fsyn0_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_20_63:44; - uint64_t fsyn_ow1:10; - uint64_t fsyn_ow0:10; -#else - uint64_t fsyn_ow0:10; - uint64_t fsyn_ow1:10; - uint64_t reserved_20_63:44; -#endif - } s; - struct cvmx_l2d_fsyn0_s cn30xx; - struct cvmx_l2d_fsyn0_s cn31xx; - struct cvmx_l2d_fsyn0_s cn38xx; - struct cvmx_l2d_fsyn0_s cn38xxp2; - struct cvmx_l2d_fsyn0_s cn50xx; - struct cvmx_l2d_fsyn0_s cn52xx; - struct cvmx_l2d_fsyn0_s cn52xxp1; - struct cvmx_l2d_fsyn0_s cn56xx; - struct cvmx_l2d_fsyn0_s cn56xxp1; - struct cvmx_l2d_fsyn0_s cn58xx; - struct cvmx_l2d_fsyn0_s cn58xxp1; -}; - -union cvmx_l2d_fsyn1 { - uint64_t u64; - struct cvmx_l2d_fsyn1_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_20_63:44; - uint64_t fsyn_ow3:10; - uint64_t fsyn_ow2:10; -#else - uint64_t fsyn_ow2:10; - uint64_t fsyn_ow3:10; - uint64_t reserved_20_63:44; -#endif - } s; - struct cvmx_l2d_fsyn1_s cn30xx; - struct cvmx_l2d_fsyn1_s cn31xx; - struct cvmx_l2d_fsyn1_s cn38xx; - struct cvmx_l2d_fsyn1_s cn38xxp2; - struct cvmx_l2d_fsyn1_s cn50xx; - struct cvmx_l2d_fsyn1_s cn52xx; - struct cvmx_l2d_fsyn1_s cn52xxp1; - struct cvmx_l2d_fsyn1_s cn56xx; - struct cvmx_l2d_fsyn1_s cn56xxp1; - struct cvmx_l2d_fsyn1_s cn58xx; - struct cvmx_l2d_fsyn1_s cn58xxp1; -}; - -union cvmx_l2d_fus0 { - uint64_t u64; - struct cvmx_l2d_fus0_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_34_63:30; - uint64_t q0fus:34; -#else - uint64_t q0fus:34; - uint64_t reserved_34_63:30; -#endif - } s; - struct cvmx_l2d_fus0_s cn30xx; - struct cvmx_l2d_fus0_s cn31xx; - struct cvmx_l2d_fus0_s cn38xx; - struct cvmx_l2d_fus0_s cn38xxp2; - struct cvmx_l2d_fus0_s cn50xx; - struct cvmx_l2d_fus0_s cn52xx; - struct cvmx_l2d_fus0_s cn52xxp1; - struct cvmx_l2d_fus0_s cn56xx; - struct cvmx_l2d_fus0_s cn56xxp1; - struct cvmx_l2d_fus0_s cn58xx; - struct cvmx_l2d_fus0_s cn58xxp1; -}; - -union cvmx_l2d_fus1 { - uint64_t u64; - struct cvmx_l2d_fus1_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_34_63:30; - uint64_t q1fus:34; -#else - uint64_t q1fus:34; - uint64_t reserved_34_63:30; -#endif - } s; - struct cvmx_l2d_fus1_s cn30xx; - struct cvmx_l2d_fus1_s cn31xx; - struct cvmx_l2d_fus1_s cn38xx; - struct cvmx_l2d_fus1_s cn38xxp2; - struct cvmx_l2d_fus1_s cn50xx; - struct cvmx_l2d_fus1_s cn52xx; - struct cvmx_l2d_fus1_s cn52xxp1; - struct cvmx_l2d_fus1_s cn56xx; - struct cvmx_l2d_fus1_s cn56xxp1; - struct cvmx_l2d_fus1_s cn58xx; - struct cvmx_l2d_fus1_s cn58xxp1; -}; - -union cvmx_l2d_fus2 { - uint64_t u64; - struct cvmx_l2d_fus2_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_34_63:30; - uint64_t q2fus:34; -#else - uint64_t q2fus:34; - uint64_t reserved_34_63:30; -#endif - } s; - struct cvmx_l2d_fus2_s cn30xx; - struct cvmx_l2d_fus2_s cn31xx; - struct cvmx_l2d_fus2_s cn38xx; - struct cvmx_l2d_fus2_s cn38xxp2; - struct cvmx_l2d_fus2_s cn50xx; - struct cvmx_l2d_fus2_s cn52xx; - struct cvmx_l2d_fus2_s cn52xxp1; - struct cvmx_l2d_fus2_s cn56xx; - struct cvmx_l2d_fus2_s cn56xxp1; - struct cvmx_l2d_fus2_s cn58xx; - struct cvmx_l2d_fus2_s cn58xxp1; -}; - -union cvmx_l2d_fus3 { - uint64_t u64; - struct cvmx_l2d_fus3_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_40_63:24; - uint64_t ema_ctl:3; - uint64_t reserved_34_36:3; - uint64_t q3fus:34; -#else - uint64_t q3fus:34; - uint64_t reserved_34_36:3; - uint64_t ema_ctl:3; - uint64_t reserved_40_63:24; -#endif - } s; - struct cvmx_l2d_fus3_cn30xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_35_63:29; - uint64_t crip_64k:1; - uint64_t q3fus:34; -#else - uint64_t q3fus:34; - uint64_t crip_64k:1; - uint64_t reserved_35_63:29; -#endif - } cn30xx; - struct cvmx_l2d_fus3_cn31xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_35_63:29; - uint64_t crip_128k:1; - uint64_t q3fus:34; -#else - uint64_t q3fus:34; - uint64_t crip_128k:1; - uint64_t reserved_35_63:29; -#endif - } cn31xx; - struct cvmx_l2d_fus3_cn38xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_36_63:28; - uint64_t crip_256k:1; - uint64_t crip_512k:1; - uint64_t q3fus:34; -#else - uint64_t q3fus:34; - uint64_t crip_512k:1; - uint64_t crip_256k:1; - uint64_t reserved_36_63:28; -#endif - } cn38xx; - struct cvmx_l2d_fus3_cn38xx cn38xxp2; - struct cvmx_l2d_fus3_cn50xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_40_63:24; - uint64_t ema_ctl:3; - uint64_t reserved_36_36:1; - uint64_t crip_32k:1; - uint64_t crip_64k:1; - uint64_t q3fus:34; -#else - uint64_t q3fus:34; - uint64_t crip_64k:1; - uint64_t crip_32k:1; - uint64_t reserved_36_36:1; - uint64_t ema_ctl:3; - uint64_t reserved_40_63:24; -#endif - } cn50xx; - struct cvmx_l2d_fus3_cn52xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_40_63:24; - uint64_t ema_ctl:3; - uint64_t reserved_36_36:1; - uint64_t crip_128k:1; - uint64_t crip_256k:1; - uint64_t q3fus:34; -#else - uint64_t q3fus:34; - uint64_t crip_256k:1; - uint64_t crip_128k:1; - uint64_t reserved_36_36:1; - uint64_t ema_ctl:3; - uint64_t reserved_40_63:24; -#endif - } cn52xx; - struct cvmx_l2d_fus3_cn52xx cn52xxp1; - struct cvmx_l2d_fus3_cn56xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_40_63:24; - uint64_t ema_ctl:3; - uint64_t reserved_36_36:1; - uint64_t crip_512k:1; - uint64_t crip_1024k:1; - uint64_t q3fus:34; -#else - uint64_t q3fus:34; - uint64_t crip_1024k:1; - uint64_t crip_512k:1; - uint64_t reserved_36_36:1; - uint64_t ema_ctl:3; - uint64_t reserved_40_63:24; -#endif - } cn56xx; - struct cvmx_l2d_fus3_cn56xx cn56xxp1; - struct cvmx_l2d_fus3_cn58xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_39_63:25; - uint64_t ema_ctl:2; - uint64_t reserved_36_36:1; - uint64_t crip_512k:1; - uint64_t crip_1024k:1; - uint64_t q3fus:34; -#else - uint64_t q3fus:34; - uint64_t crip_1024k:1; - uint64_t crip_512k:1; - uint64_t reserved_36_36:1; - uint64_t ema_ctl:2; - uint64_t reserved_39_63:25; -#endif - } cn58xx; - struct cvmx_l2d_fus3_cn58xx cn58xxp1; -}; - -#endif diff --git a/arch/mips/include/asm/octeon/cvmx-l2t-defs.h b/arch/mips/include/asm/octeon/cvmx-l2t-defs.h index 83ce22c080e6..fe50671fd1bb 100644 --- a/arch/mips/include/asm/octeon/cvmx-l2t-defs.h +++ b/arch/mips/include/asm/octeon/cvmx-l2t-defs.h @@ -4,7 +4,7 @@ * Contact: support@caviumnetworks.com * This file is part of the OCTEON SDK * - * Copyright (c) 2003-2012 Cavium Networks + * Copyright (c) 2003-2017 Cavium, Inc. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as @@ -28,210 +28,116 @@ #ifndef __CVMX_L2T_DEFS_H__ #define __CVMX_L2T_DEFS_H__ -#define CVMX_L2T_ERR (CVMX_ADD_IO_SEG(0x0001180080000008ull)) +#include + +#define CVMX_L2T_ERR (CVMX_ADD_IO_SEG(0x0001180080000008ull)) + union cvmx_l2t_err { uint64_t u64; struct cvmx_l2t_err_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_29_63:35; - uint64_t fadru:1; - uint64_t lck_intena2:1; - uint64_t lckerr2:1; - uint64_t lck_intena:1; - uint64_t lckerr:1; - uint64_t fset:3; - uint64_t fadr:10; - uint64_t fsyn:6; - uint64_t ded_err:1; - uint64_t sec_err:1; - uint64_t ded_intena:1; - uint64_t sec_intena:1; - uint64_t ecc_ena:1; -#else - uint64_t ecc_ena:1; - uint64_t sec_intena:1; - uint64_t ded_intena:1; - uint64_t sec_err:1; - uint64_t ded_err:1; - uint64_t fsyn:6; - uint64_t fadr:10; - uint64_t fset:3; - uint64_t lckerr:1; - uint64_t lck_intena:1; - uint64_t lckerr2:1; - uint64_t lck_intena2:1; - uint64_t fadru:1; - uint64_t reserved_29_63:35; -#endif + __BITFIELD_FIELD(uint64_t reserved_29_63:35, + __BITFIELD_FIELD(uint64_t fadru:1, + __BITFIELD_FIELD(uint64_t lck_intena2:1, + __BITFIELD_FIELD(uint64_t lckerr2:1, + __BITFIELD_FIELD(uint64_t lck_intena:1, + __BITFIELD_FIELD(uint64_t lckerr:1, + __BITFIELD_FIELD(uint64_t fset:3, + __BITFIELD_FIELD(uint64_t fadr:10, + __BITFIELD_FIELD(uint64_t fsyn:6, + __BITFIELD_FIELD(uint64_t ded_err:1, + __BITFIELD_FIELD(uint64_t sec_err:1, + __BITFIELD_FIELD(uint64_t ded_intena:1, + __BITFIELD_FIELD(uint64_t sec_intena:1, + __BITFIELD_FIELD(uint64_t ecc_ena:1, + ;)))))))))))))) } s; struct cvmx_l2t_err_cn30xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_28_63:36; - uint64_t lck_intena2:1; - uint64_t lckerr2:1; - uint64_t lck_intena:1; - uint64_t lckerr:1; - uint64_t reserved_23_23:1; - uint64_t fset:2; - uint64_t reserved_19_20:2; - uint64_t fadr:8; - uint64_t fsyn:6; - uint64_t ded_err:1; - uint64_t sec_err:1; - uint64_t ded_intena:1; - uint64_t sec_intena:1; - uint64_t ecc_ena:1; -#else - uint64_t ecc_ena:1; - uint64_t sec_intena:1; - uint64_t ded_intena:1; - uint64_t sec_err:1; - uint64_t ded_err:1; - uint64_t fsyn:6; - uint64_t fadr:8; - uint64_t reserved_19_20:2; - uint64_t fset:2; - uint64_t reserved_23_23:1; - uint64_t lckerr:1; - uint64_t lck_intena:1; - uint64_t lckerr2:1; - uint64_t lck_intena2:1; - uint64_t reserved_28_63:36; -#endif + __BITFIELD_FIELD(uint64_t reserved_28_63:36, + __BITFIELD_FIELD(uint64_t lck_intena2:1, + __BITFIELD_FIELD(uint64_t lckerr2:1, + __BITFIELD_FIELD(uint64_t lck_intena:1, + __BITFIELD_FIELD(uint64_t lckerr:1, + __BITFIELD_FIELD(uint64_t reserved_23_23:1, + __BITFIELD_FIELD(uint64_t fset:2, + __BITFIELD_FIELD(uint64_t reserved_19_20:2, + __BITFIELD_FIELD(uint64_t fadr:8, + __BITFIELD_FIELD(uint64_t fsyn:6, + __BITFIELD_FIELD(uint64_t ded_err:1, + __BITFIELD_FIELD(uint64_t sec_err:1, + __BITFIELD_FIELD(uint64_t ded_intena:1, + __BITFIELD_FIELD(uint64_t sec_intena:1, + __BITFIELD_FIELD(uint64_t ecc_ena:1, + ;))))))))))))))) } cn30xx; struct cvmx_l2t_err_cn31xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_28_63:36; - uint64_t lck_intena2:1; - uint64_t lckerr2:1; - uint64_t lck_intena:1; - uint64_t lckerr:1; - uint64_t reserved_23_23:1; - uint64_t fset:2; - uint64_t reserved_20_20:1; - uint64_t fadr:9; - uint64_t fsyn:6; - uint64_t ded_err:1; - uint64_t sec_err:1; - uint64_t ded_intena:1; - uint64_t sec_intena:1; - uint64_t ecc_ena:1; -#else - uint64_t ecc_ena:1; - uint64_t sec_intena:1; - uint64_t ded_intena:1; - uint64_t sec_err:1; - uint64_t ded_err:1; - uint64_t fsyn:6; - uint64_t fadr:9; - uint64_t reserved_20_20:1; - uint64_t fset:2; - uint64_t reserved_23_23:1; - uint64_t lckerr:1; - uint64_t lck_intena:1; - uint64_t lckerr2:1; - uint64_t lck_intena2:1; - uint64_t reserved_28_63:36; -#endif + __BITFIELD_FIELD(uint64_t reserved_28_63:36, + __BITFIELD_FIELD(uint64_t lck_intena2:1, + __BITFIELD_FIELD(uint64_t lckerr2:1, + __BITFIELD_FIELD(uint64_t lck_intena:1, + __BITFIELD_FIELD(uint64_t lckerr:1, + __BITFIELD_FIELD(uint64_t reserved_23_23:1, + __BITFIELD_FIELD(uint64_t fset:2, + __BITFIELD_FIELD(uint64_t reserved_20_20:1, + __BITFIELD_FIELD(uint64_t fadr:9, + __BITFIELD_FIELD(uint64_t fsyn:6, + __BITFIELD_FIELD(uint64_t ded_err:1, + __BITFIELD_FIELD(uint64_t sec_err:1, + __BITFIELD_FIELD(uint64_t ded_intena:1, + __BITFIELD_FIELD(uint64_t sec_intena:1, + __BITFIELD_FIELD(uint64_t ecc_ena:1, + ;))))))))))))))) } cn31xx; struct cvmx_l2t_err_cn38xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_28_63:36; - uint64_t lck_intena2:1; - uint64_t lckerr2:1; - uint64_t lck_intena:1; - uint64_t lckerr:1; - uint64_t fset:3; - uint64_t fadr:10; - uint64_t fsyn:6; - uint64_t ded_err:1; - uint64_t sec_err:1; - uint64_t ded_intena:1; - uint64_t sec_intena:1; - uint64_t ecc_ena:1; -#else - uint64_t ecc_ena:1; - uint64_t sec_intena:1; - uint64_t ded_intena:1; - uint64_t sec_err:1; - uint64_t ded_err:1; - uint64_t fsyn:6; - uint64_t fadr:10; - uint64_t fset:3; - uint64_t lckerr:1; - uint64_t lck_intena:1; - uint64_t lckerr2:1; - uint64_t lck_intena2:1; - uint64_t reserved_28_63:36; -#endif + __BITFIELD_FIELD(uint64_t reserved_28_63:36, + __BITFIELD_FIELD(uint64_t lck_intena2:1, + __BITFIELD_FIELD(uint64_t lckerr2:1, + __BITFIELD_FIELD(uint64_t lck_intena:1, + __BITFIELD_FIELD(uint64_t lckerr:1, + __BITFIELD_FIELD(uint64_t fset:3, + __BITFIELD_FIELD(uint64_t fadr:10, + __BITFIELD_FIELD(uint64_t fsyn:6, + __BITFIELD_FIELD(uint64_t ded_err:1, + __BITFIELD_FIELD(uint64_t sec_err:1, + __BITFIELD_FIELD(uint64_t ded_intena:1, + __BITFIELD_FIELD(uint64_t sec_intena:1, + __BITFIELD_FIELD(uint64_t ecc_ena:1, + ;))))))))))))) } cn38xx; struct cvmx_l2t_err_cn38xx cn38xxp2; struct cvmx_l2t_err_cn50xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_28_63:36; - uint64_t lck_intena2:1; - uint64_t lckerr2:1; - uint64_t lck_intena:1; - uint64_t lckerr:1; - uint64_t fset:3; - uint64_t reserved_18_20:3; - uint64_t fadr:7; - uint64_t fsyn:6; - uint64_t ded_err:1; - uint64_t sec_err:1; - uint64_t ded_intena:1; - uint64_t sec_intena:1; - uint64_t ecc_ena:1; -#else - uint64_t ecc_ena:1; - uint64_t sec_intena:1; - uint64_t ded_intena:1; - uint64_t sec_err:1; - uint64_t ded_err:1; - uint64_t fsyn:6; - uint64_t fadr:7; - uint64_t reserved_18_20:3; - uint64_t fset:3; - uint64_t lckerr:1; - uint64_t lck_intena:1; - uint64_t lckerr2:1; - uint64_t lck_intena2:1; - uint64_t reserved_28_63:36; -#endif + __BITFIELD_FIELD(uint64_t reserved_28_63:36, + __BITFIELD_FIELD(uint64_t lck_intena2:1, + __BITFIELD_FIELD(uint64_t lckerr2:1, + __BITFIELD_FIELD(uint64_t lck_intena:1, + __BITFIELD_FIELD(uint64_t lckerr:1, + __BITFIELD_FIELD(uint64_t fset:3, + __BITFIELD_FIELD(uint64_t reserved_18_20:3, + __BITFIELD_FIELD(uint64_t fadr:7, + __BITFIELD_FIELD(uint64_t fsyn:6, + __BITFIELD_FIELD(uint64_t ded_err:1, + __BITFIELD_FIELD(uint64_t sec_err:1, + __BITFIELD_FIELD(uint64_t ded_intena:1, + __BITFIELD_FIELD(uint64_t sec_intena:1, + __BITFIELD_FIELD(uint64_t ecc_ena:1, + ;)))))))))))))) } cn50xx; struct cvmx_l2t_err_cn52xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_28_63:36; - uint64_t lck_intena2:1; - uint64_t lckerr2:1; - uint64_t lck_intena:1; - uint64_t lckerr:1; - uint64_t fset:3; - uint64_t reserved_20_20:1; - uint64_t fadr:9; - uint64_t fsyn:6; - uint64_t ded_err:1; - uint64_t sec_err:1; - uint64_t ded_intena:1; - uint64_t sec_intena:1; - uint64_t ecc_ena:1; -#else - uint64_t ecc_ena:1; - uint64_t sec_intena:1; - uint64_t ded_intena:1; - uint64_t sec_err:1; - uint64_t ded_err:1; - uint64_t fsyn:6; - uint64_t fadr:9; - uint64_t reserved_20_20:1; - uint64_t fset:3; - uint64_t lckerr:1; - uint64_t lck_intena:1; - uint64_t lckerr2:1; - uint64_t lck_intena2:1; - uint64_t reserved_28_63:36; -#endif + __BITFIELD_FIELD(uint64_t reserved_28_63:36, + __BITFIELD_FIELD(uint64_t lck_intena2:1, + __BITFIELD_FIELD(uint64_t lckerr2:1, + __BITFIELD_FIELD(uint64_t lck_intena:1, + __BITFIELD_FIELD(uint64_t lckerr:1, + __BITFIELD_FIELD(uint64_t fset:3, + __BITFIELD_FIELD(uint64_t reserved_20_20:1, + __BITFIELD_FIELD(uint64_t fadr:9, + __BITFIELD_FIELD(uint64_t fsyn:6, + __BITFIELD_FIELD(uint64_t ded_err:1, + __BITFIELD_FIELD(uint64_t sec_err:1, + __BITFIELD_FIELD(uint64_t ded_intena:1, + __BITFIELD_FIELD(uint64_t sec_intena:1, + __BITFIELD_FIELD(uint64_t ecc_ena:1, + ;)))))))))))))) } cn52xx; struct cvmx_l2t_err_cn52xx cn52xxp1; struct cvmx_l2t_err_s cn56xx; diff --git a/arch/mips/include/asm/octeon/cvmx.h b/arch/mips/include/asm/octeon/cvmx.h index 2530e8731c8a..9742202f2a32 100644 --- a/arch/mips/include/asm/octeon/cvmx.h +++ b/arch/mips/include/asm/octeon/cvmx.h @@ -4,7 +4,7 @@ * Contact: support@caviumnetworks.com * This file is part of the OCTEON SDK * - * Copyright (c) 2003-2008 Cavium Networks + * Copyright (c) 2003-2017 Cavium, Inc. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as @@ -62,7 +62,6 @@ enum cvmx_mips_space { #include #include #include -#include #include #include #include -- cgit v1.2.3-59-g8ed1b From 930cbb73ee7d0e396987efccc24112c4469c03dc Mon Sep 17 00:00:00 2001 From: "Steven J. Hill" Date: Thu, 9 Mar 2017 08:15:16 -0600 Subject: MIPS: Octeon: Remove unused SLI types and macros. Remove all unused bitfields and macros. Convert the remaining bitfields to use __BITFIELD_FIELD instead of #ifdef. [ralf@linux-mips.org: Add inclusions of as necessary.] Signed-off-by: Steven J. Hill Acked-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/15405/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/octeon/cvmx-sli-defs.h | 3541 +------------------------- arch/mips/pci/pcie-octeon.c | 4 +- 2 files changed, 76 insertions(+), 3469 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/octeon/cvmx-sli-defs.h b/arch/mips/include/asm/octeon/cvmx-sli-defs.h index e697c2f52a62..52cf96ea43e5 100644 --- a/arch/mips/include/asm/octeon/cvmx-sli-defs.h +++ b/arch/mips/include/asm/octeon/cvmx-sli-defs.h @@ -4,7 +4,7 @@ * Contact: support@caviumnetworks.com * This file is part of the OCTEON SDK * - * Copyright (c) 2003-2012 Cavium Networks + * Copyright (c) 2003-2017 Cavium, Inc. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as @@ -28,3494 +28,101 @@ #ifndef __CVMX_SLI_DEFS_H__ #define __CVMX_SLI_DEFS_H__ -#define CVMX_SLI_BIST_STATUS (0x0000000000000580ull) -#define CVMX_SLI_CTL_PORTX(offset) (0x0000000000000050ull + ((offset) & 3) * 16) -#define CVMX_SLI_CTL_STATUS (0x0000000000000570ull) -#define CVMX_SLI_DATA_OUT_CNT (0x00000000000005F0ull) -#define CVMX_SLI_DBG_DATA (0x0000000000000310ull) -#define CVMX_SLI_DBG_SELECT (0x0000000000000300ull) -#define CVMX_SLI_DMAX_CNT(offset) (0x0000000000000400ull + ((offset) & 1) * 16) -#define CVMX_SLI_DMAX_INT_LEVEL(offset) (0x00000000000003E0ull + ((offset) & 1) * 16) -#define CVMX_SLI_DMAX_TIM(offset) (0x0000000000000420ull + ((offset) & 1) * 16) -#define CVMX_SLI_INT_ENB_CIU (0x0000000000003CD0ull) -#define CVMX_SLI_INT_ENB_PORTX(offset) (0x0000000000000340ull + ((offset) & 1) * 16) -#define CVMX_SLI_INT_SUM (0x0000000000000330ull) -#define CVMX_SLI_LAST_WIN_RDATA0 (0x0000000000000600ull) -#define CVMX_SLI_LAST_WIN_RDATA1 (0x0000000000000610ull) -#define CVMX_SLI_LAST_WIN_RDATA2 (0x00000000000006C0ull) -#define CVMX_SLI_LAST_WIN_RDATA3 (0x00000000000006D0ull) -#define CVMX_SLI_MAC_CREDIT_CNT (0x0000000000003D70ull) -#define CVMX_SLI_MAC_CREDIT_CNT2 (0x0000000000003E10ull) -#define CVMX_SLI_MAC_NUMBER (0x0000000000003E00ull) -#define CVMX_SLI_MEM_ACCESS_CTL (0x00000000000002F0ull) -#define CVMX_SLI_MEM_ACCESS_SUBIDX(offset) (0x00000000000000E0ull + ((offset) & 31) * 16 - 16*12) -#define CVMX_SLI_MSI_ENB0 (0x0000000000003C50ull) -#define CVMX_SLI_MSI_ENB1 (0x0000000000003C60ull) -#define CVMX_SLI_MSI_ENB2 (0x0000000000003C70ull) -#define CVMX_SLI_MSI_ENB3 (0x0000000000003C80ull) -#define CVMX_SLI_MSI_RCV0 (0x0000000000003C10ull) -#define CVMX_SLI_MSI_RCV1 (0x0000000000003C20ull) -#define CVMX_SLI_MSI_RCV2 (0x0000000000003C30ull) -#define CVMX_SLI_MSI_RCV3 (0x0000000000003C40ull) -#define CVMX_SLI_MSI_RD_MAP (0x0000000000003CA0ull) -#define CVMX_SLI_MSI_W1C_ENB0 (0x0000000000003CF0ull) -#define CVMX_SLI_MSI_W1C_ENB1 (0x0000000000003D00ull) -#define CVMX_SLI_MSI_W1C_ENB2 (0x0000000000003D10ull) -#define CVMX_SLI_MSI_W1C_ENB3 (0x0000000000003D20ull) -#define CVMX_SLI_MSI_W1S_ENB0 (0x0000000000003D30ull) -#define CVMX_SLI_MSI_W1S_ENB1 (0x0000000000003D40ull) -#define CVMX_SLI_MSI_W1S_ENB2 (0x0000000000003D50ull) -#define CVMX_SLI_MSI_W1S_ENB3 (0x0000000000003D60ull) -#define CVMX_SLI_MSI_WR_MAP (0x0000000000003C90ull) -#define CVMX_SLI_PCIE_MSI_RCV (0x0000000000003CB0ull) -#define CVMX_SLI_PCIE_MSI_RCV_B1 (0x0000000000000650ull) -#define CVMX_SLI_PCIE_MSI_RCV_B2 (0x0000000000000660ull) -#define CVMX_SLI_PCIE_MSI_RCV_B3 (0x0000000000000670ull) -#define CVMX_SLI_PKTX_CNTS(offset) (0x0000000000002400ull + ((offset) & 31) * 16) -#define CVMX_SLI_PKTX_INSTR_BADDR(offset) (0x0000000000002800ull + ((offset) & 31) * 16) -#define CVMX_SLI_PKTX_INSTR_BAOFF_DBELL(offset) (0x0000000000002C00ull + ((offset) & 31) * 16) -#define CVMX_SLI_PKTX_INSTR_FIFO_RSIZE(offset) (0x0000000000003000ull + ((offset) & 31) * 16) -#define CVMX_SLI_PKTX_INSTR_HEADER(offset) (0x0000000000003400ull + ((offset) & 31) * 16) -#define CVMX_SLI_PKTX_IN_BP(offset) (0x0000000000003800ull + ((offset) & 31) * 16) -#define CVMX_SLI_PKTX_OUT_SIZE(offset) (0x0000000000000C00ull + ((offset) & 31) * 16) -#define CVMX_SLI_PKTX_SLIST_BADDR(offset) (0x0000000000001400ull + ((offset) & 31) * 16) -#define CVMX_SLI_PKTX_SLIST_BAOFF_DBELL(offset) (0x0000000000001800ull + ((offset) & 31) * 16) -#define CVMX_SLI_PKTX_SLIST_FIFO_RSIZE(offset) (0x0000000000001C00ull + ((offset) & 31) * 16) -#define CVMX_SLI_PKT_CNT_INT (0x0000000000001130ull) -#define CVMX_SLI_PKT_CNT_INT_ENB (0x0000000000001150ull) -#define CVMX_SLI_PKT_CTL (0x0000000000001220ull) -#define CVMX_SLI_PKT_DATA_OUT_ES (0x00000000000010B0ull) -#define CVMX_SLI_PKT_DATA_OUT_NS (0x00000000000010A0ull) -#define CVMX_SLI_PKT_DATA_OUT_ROR (0x0000000000001090ull) -#define CVMX_SLI_PKT_DPADDR (0x0000000000001080ull) -#define CVMX_SLI_PKT_INPUT_CONTROL (0x0000000000001170ull) -#define CVMX_SLI_PKT_INSTR_ENB (0x0000000000001000ull) -#define CVMX_SLI_PKT_INSTR_RD_SIZE (0x00000000000011A0ull) -#define CVMX_SLI_PKT_INSTR_SIZE (0x0000000000001020ull) -#define CVMX_SLI_PKT_INT_LEVELS (0x0000000000001120ull) -#define CVMX_SLI_PKT_IN_BP (0x0000000000001210ull) -#define CVMX_SLI_PKT_IN_DONEX_CNTS(offset) (0x0000000000002000ull + ((offset) & 31) * 16) -#define CVMX_SLI_PKT_IN_INSTR_COUNTS (0x0000000000001200ull) -#define CVMX_SLI_PKT_IN_PCIE_PORT (0x00000000000011B0ull) -#define CVMX_SLI_PKT_IPTR (0x0000000000001070ull) -#define CVMX_SLI_PKT_OUTPUT_WMARK (0x0000000000001180ull) -#define CVMX_SLI_PKT_OUT_BMODE (0x00000000000010D0ull) -#define CVMX_SLI_PKT_OUT_BP_EN (0x0000000000001240ull) -#define CVMX_SLI_PKT_OUT_ENB (0x0000000000001010ull) -#define CVMX_SLI_PKT_PCIE_PORT (0x00000000000010E0ull) -#define CVMX_SLI_PKT_PORT_IN_RST (0x00000000000011F0ull) -#define CVMX_SLI_PKT_SLIST_ES (0x0000000000001050ull) -#define CVMX_SLI_PKT_SLIST_NS (0x0000000000001040ull) -#define CVMX_SLI_PKT_SLIST_ROR (0x0000000000001030ull) -#define CVMX_SLI_PKT_TIME_INT (0x0000000000001140ull) -#define CVMX_SLI_PKT_TIME_INT_ENB (0x0000000000001160ull) -#define CVMX_SLI_PORTX_PKIND(offset) (0x0000000000000800ull + ((offset) & 31) * 16) -#define CVMX_SLI_S2M_PORTX_CTL(offset) (0x0000000000003D80ull + ((offset) & 3) * 16) -#define CVMX_SLI_SCRATCH_1 (0x00000000000003C0ull) -#define CVMX_SLI_SCRATCH_2 (0x00000000000003D0ull) -#define CVMX_SLI_STATE1 (0x0000000000000620ull) -#define CVMX_SLI_STATE2 (0x0000000000000630ull) -#define CVMX_SLI_STATE3 (0x0000000000000640ull) -#define CVMX_SLI_TX_PIPE (0x0000000000001230ull) -#define CVMX_SLI_WINDOW_CTL (0x00000000000002E0ull) -#define CVMX_SLI_WIN_RD_ADDR (0x0000000000000010ull) -#define CVMX_SLI_WIN_RD_DATA (0x0000000000000040ull) -#define CVMX_SLI_WIN_WR_ADDR (0x0000000000000000ull) -#define CVMX_SLI_WIN_WR_DATA (0x0000000000000020ull) -#define CVMX_SLI_WIN_WR_MASK (0x0000000000000030ull) +#include + +#define CVMX_SLI_PCIE_MSI_RCV CVMX_SLI_PCIE_MSI_RCV_FUNC() +static inline uint64_t CVMX_SLI_PCIE_MSI_RCV_FUNC(void) +{ + switch (cvmx_get_octeon_family()) { + case OCTEON_CNF71XX & OCTEON_FAMILY_MASK: + case OCTEON_CN61XX & OCTEON_FAMILY_MASK: + case OCTEON_CN63XX & OCTEON_FAMILY_MASK: + case OCTEON_CN66XX & OCTEON_FAMILY_MASK: + case OCTEON_CN68XX & OCTEON_FAMILY_MASK: + case OCTEON_CN70XX & OCTEON_FAMILY_MASK: + return 0x0000000000003CB0ull; + case OCTEON_CNF75XX & OCTEON_FAMILY_MASK: + case OCTEON_CN73XX & OCTEON_FAMILY_MASK: + case OCTEON_CN78XX & OCTEON_FAMILY_MASK: + if (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_X)) + return 0x0000000000003CB0ull; + default: + return 0x0000000000023CB0ull; + } +} -union cvmx_sli_bist_status { - uint64_t u64; - struct cvmx_sli_bist_status_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t ncb_req:1; - uint64_t n2p0_c:1; - uint64_t n2p0_o:1; - uint64_t n2p1_c:1; - uint64_t n2p1_o:1; - uint64_t cpl_p0:1; - uint64_t cpl_p1:1; - uint64_t reserved_19_24:6; - uint64_t p2n0_c0:1; - uint64_t p2n0_c1:1; - uint64_t p2n0_n:1; - uint64_t p2n0_p0:1; - uint64_t p2n0_p1:1; - uint64_t p2n1_c0:1; - uint64_t p2n1_c1:1; - uint64_t p2n1_n:1; - uint64_t p2n1_p0:1; - uint64_t p2n1_p1:1; - uint64_t reserved_6_8:3; - uint64_t dsi1_1:1; - uint64_t dsi1_0:1; - uint64_t dsi0_1:1; - uint64_t dsi0_0:1; - uint64_t msi:1; - uint64_t ncb_cmd:1; -#else - uint64_t ncb_cmd:1; - uint64_t msi:1; - uint64_t dsi0_0:1; - uint64_t dsi0_1:1; - uint64_t dsi1_0:1; - uint64_t dsi1_1:1; - uint64_t reserved_6_8:3; - uint64_t p2n1_p1:1; - uint64_t p2n1_p0:1; - uint64_t p2n1_n:1; - uint64_t p2n1_c1:1; - uint64_t p2n1_c0:1; - uint64_t p2n0_p1:1; - uint64_t p2n0_p0:1; - uint64_t p2n0_n:1; - uint64_t p2n0_c1:1; - uint64_t p2n0_c0:1; - uint64_t reserved_19_24:6; - uint64_t cpl_p1:1; - uint64_t cpl_p0:1; - uint64_t n2p1_o:1; - uint64_t n2p1_c:1; - uint64_t n2p0_o:1; - uint64_t n2p0_c:1; - uint64_t ncb_req:1; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_sli_bist_status_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_31_63:33; - uint64_t n2p0_c:1; - uint64_t n2p0_o:1; - uint64_t reserved_27_28:2; - uint64_t cpl_p0:1; - uint64_t cpl_p1:1; - uint64_t reserved_19_24:6; - uint64_t p2n0_c0:1; - uint64_t p2n0_c1:1; - uint64_t p2n0_n:1; - uint64_t p2n0_p0:1; - uint64_t p2n0_p1:1; - uint64_t p2n1_c0:1; - uint64_t p2n1_c1:1; - uint64_t p2n1_n:1; - uint64_t p2n1_p0:1; - uint64_t p2n1_p1:1; - uint64_t reserved_6_8:3; - uint64_t dsi1_1:1; - uint64_t dsi1_0:1; - uint64_t dsi0_1:1; - uint64_t dsi0_0:1; - uint64_t msi:1; - uint64_t ncb_cmd:1; -#else - uint64_t ncb_cmd:1; - uint64_t msi:1; - uint64_t dsi0_0:1; - uint64_t dsi0_1:1; - uint64_t dsi1_0:1; - uint64_t dsi1_1:1; - uint64_t reserved_6_8:3; - uint64_t p2n1_p1:1; - uint64_t p2n1_p0:1; - uint64_t p2n1_n:1; - uint64_t p2n1_c1:1; - uint64_t p2n1_c0:1; - uint64_t p2n0_p1:1; - uint64_t p2n0_p0:1; - uint64_t p2n0_n:1; - uint64_t p2n0_c1:1; - uint64_t p2n0_c0:1; - uint64_t reserved_19_24:6; - uint64_t cpl_p1:1; - uint64_t cpl_p0:1; - uint64_t reserved_27_28:2; - uint64_t n2p0_o:1; - uint64_t n2p0_c:1; - uint64_t reserved_31_63:33; -#endif - } cn61xx; - struct cvmx_sli_bist_status_cn63xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_31_63:33; - uint64_t n2p0_c:1; - uint64_t n2p0_o:1; - uint64_t n2p1_c:1; - uint64_t n2p1_o:1; - uint64_t cpl_p0:1; - uint64_t cpl_p1:1; - uint64_t reserved_19_24:6; - uint64_t p2n0_c0:1; - uint64_t p2n0_c1:1; - uint64_t p2n0_n:1; - uint64_t p2n0_p0:1; - uint64_t p2n0_p1:1; - uint64_t p2n1_c0:1; - uint64_t p2n1_c1:1; - uint64_t p2n1_n:1; - uint64_t p2n1_p0:1; - uint64_t p2n1_p1:1; - uint64_t reserved_6_8:3; - uint64_t dsi1_1:1; - uint64_t dsi1_0:1; - uint64_t dsi0_1:1; - uint64_t dsi0_0:1; - uint64_t msi:1; - uint64_t ncb_cmd:1; -#else - uint64_t ncb_cmd:1; - uint64_t msi:1; - uint64_t dsi0_0:1; - uint64_t dsi0_1:1; - uint64_t dsi1_0:1; - uint64_t dsi1_1:1; - uint64_t reserved_6_8:3; - uint64_t p2n1_p1:1; - uint64_t p2n1_p0:1; - uint64_t p2n1_n:1; - uint64_t p2n1_c1:1; - uint64_t p2n1_c0:1; - uint64_t p2n0_p1:1; - uint64_t p2n0_p0:1; - uint64_t p2n0_n:1; - uint64_t p2n0_c1:1; - uint64_t p2n0_c0:1; - uint64_t reserved_19_24:6; - uint64_t cpl_p1:1; - uint64_t cpl_p0:1; - uint64_t n2p1_o:1; - uint64_t n2p1_c:1; - uint64_t n2p0_o:1; - uint64_t n2p0_c:1; - uint64_t reserved_31_63:33; -#endif - } cn63xx; - struct cvmx_sli_bist_status_cn63xx cn63xxp1; - struct cvmx_sli_bist_status_cn61xx cn66xx; - struct cvmx_sli_bist_status_s cn68xx; - struct cvmx_sli_bist_status_s cn68xxp1; - struct cvmx_sli_bist_status_cn61xx cnf71xx; -}; union cvmx_sli_ctl_portx { uint64_t u64; struct cvmx_sli_ctl_portx_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_22_63:42; - uint64_t intd:1; - uint64_t intc:1; - uint64_t intb:1; - uint64_t inta:1; - uint64_t dis_port:1; - uint64_t waitl_com:1; - uint64_t intd_map:2; - uint64_t intc_map:2; - uint64_t intb_map:2; - uint64_t inta_map:2; - uint64_t ctlp_ro:1; - uint64_t reserved_6_6:1; - uint64_t ptlp_ro:1; - uint64_t reserved_1_4:4; - uint64_t wait_com:1; -#else - uint64_t wait_com:1; - uint64_t reserved_1_4:4; - uint64_t ptlp_ro:1; - uint64_t reserved_6_6:1; - uint64_t ctlp_ro:1; - uint64_t inta_map:2; - uint64_t intb_map:2; - uint64_t intc_map:2; - uint64_t intd_map:2; - uint64_t waitl_com:1; - uint64_t dis_port:1; - uint64_t inta:1; - uint64_t intb:1; - uint64_t intc:1; - uint64_t intd:1; - uint64_t reserved_22_63:42; -#endif - } s; - struct cvmx_sli_ctl_portx_s cn61xx; - struct cvmx_sli_ctl_portx_s cn63xx; - struct cvmx_sli_ctl_portx_s cn63xxp1; - struct cvmx_sli_ctl_portx_s cn66xx; - struct cvmx_sli_ctl_portx_s cn68xx; - struct cvmx_sli_ctl_portx_s cn68xxp1; - struct cvmx_sli_ctl_portx_s cnf71xx; -}; - -union cvmx_sli_ctl_status { - uint64_t u64; - struct cvmx_sli_ctl_status_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_20_63:44; - uint64_t p1_ntags:6; - uint64_t p0_ntags:6; - uint64_t chip_rev:8; -#else - uint64_t chip_rev:8; - uint64_t p0_ntags:6; - uint64_t p1_ntags:6; - uint64_t reserved_20_63:44; -#endif - } s; - struct cvmx_sli_ctl_status_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_14_63:50; - uint64_t p0_ntags:6; - uint64_t chip_rev:8; -#else - uint64_t chip_rev:8; - uint64_t p0_ntags:6; - uint64_t reserved_14_63:50; -#endif - } cn61xx; - struct cvmx_sli_ctl_status_s cn63xx; - struct cvmx_sli_ctl_status_s cn63xxp1; - struct cvmx_sli_ctl_status_cn61xx cn66xx; - struct cvmx_sli_ctl_status_s cn68xx; - struct cvmx_sli_ctl_status_s cn68xxp1; - struct cvmx_sli_ctl_status_cn61xx cnf71xx; -}; - -union cvmx_sli_data_out_cnt { - uint64_t u64; - struct cvmx_sli_data_out_cnt_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_44_63:20; - uint64_t p1_ucnt:16; - uint64_t p1_fcnt:6; - uint64_t p0_ucnt:16; - uint64_t p0_fcnt:6; -#else - uint64_t p0_fcnt:6; - uint64_t p0_ucnt:16; - uint64_t p1_fcnt:6; - uint64_t p1_ucnt:16; - uint64_t reserved_44_63:20; -#endif - } s; - struct cvmx_sli_data_out_cnt_s cn61xx; - struct cvmx_sli_data_out_cnt_s cn63xx; - struct cvmx_sli_data_out_cnt_s cn63xxp1; - struct cvmx_sli_data_out_cnt_s cn66xx; - struct cvmx_sli_data_out_cnt_s cn68xx; - struct cvmx_sli_data_out_cnt_s cn68xxp1; - struct cvmx_sli_data_out_cnt_s cnf71xx; -}; - -union cvmx_sli_dbg_data { - uint64_t u64; - struct cvmx_sli_dbg_data_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_18_63:46; - uint64_t dsel_ext:1; - uint64_t data:17; -#else - uint64_t data:17; - uint64_t dsel_ext:1; - uint64_t reserved_18_63:46; -#endif - } s; - struct cvmx_sli_dbg_data_s cn61xx; - struct cvmx_sli_dbg_data_s cn63xx; - struct cvmx_sli_dbg_data_s cn63xxp1; - struct cvmx_sli_dbg_data_s cn66xx; - struct cvmx_sli_dbg_data_s cn68xx; - struct cvmx_sli_dbg_data_s cn68xxp1; - struct cvmx_sli_dbg_data_s cnf71xx; -}; - -union cvmx_sli_dbg_select { - uint64_t u64; - struct cvmx_sli_dbg_select_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_33_63:31; - uint64_t adbg_sel:1; - uint64_t dbg_sel:32; -#else - uint64_t dbg_sel:32; - uint64_t adbg_sel:1; - uint64_t reserved_33_63:31; -#endif - } s; - struct cvmx_sli_dbg_select_s cn61xx; - struct cvmx_sli_dbg_select_s cn63xx; - struct cvmx_sli_dbg_select_s cn63xxp1; - struct cvmx_sli_dbg_select_s cn66xx; - struct cvmx_sli_dbg_select_s cn68xx; - struct cvmx_sli_dbg_select_s cn68xxp1; - struct cvmx_sli_dbg_select_s cnf71xx; -}; - -union cvmx_sli_dmax_cnt { - uint64_t u64; - struct cvmx_sli_dmax_cnt_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t cnt:32; -#else - uint64_t cnt:32; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_sli_dmax_cnt_s cn61xx; - struct cvmx_sli_dmax_cnt_s cn63xx; - struct cvmx_sli_dmax_cnt_s cn63xxp1; - struct cvmx_sli_dmax_cnt_s cn66xx; - struct cvmx_sli_dmax_cnt_s cn68xx; - struct cvmx_sli_dmax_cnt_s cn68xxp1; - struct cvmx_sli_dmax_cnt_s cnf71xx; -}; - -union cvmx_sli_dmax_int_level { - uint64_t u64; - struct cvmx_sli_dmax_int_level_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t time:32; - uint64_t cnt:32; -#else - uint64_t cnt:32; - uint64_t time:32; -#endif - } s; - struct cvmx_sli_dmax_int_level_s cn61xx; - struct cvmx_sli_dmax_int_level_s cn63xx; - struct cvmx_sli_dmax_int_level_s cn63xxp1; - struct cvmx_sli_dmax_int_level_s cn66xx; - struct cvmx_sli_dmax_int_level_s cn68xx; - struct cvmx_sli_dmax_int_level_s cn68xxp1; - struct cvmx_sli_dmax_int_level_s cnf71xx; -}; - -union cvmx_sli_dmax_tim { - uint64_t u64; - struct cvmx_sli_dmax_tim_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t tim:32; -#else - uint64_t tim:32; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_sli_dmax_tim_s cn61xx; - struct cvmx_sli_dmax_tim_s cn63xx; - struct cvmx_sli_dmax_tim_s cn63xxp1; - struct cvmx_sli_dmax_tim_s cn66xx; - struct cvmx_sli_dmax_tim_s cn68xx; - struct cvmx_sli_dmax_tim_s cn68xxp1; - struct cvmx_sli_dmax_tim_s cnf71xx; -}; - -union cvmx_sli_int_enb_ciu { - uint64_t u64; - struct cvmx_sli_int_enb_ciu_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_62_63:2; - uint64_t pipe_err:1; - uint64_t ill_pad:1; - uint64_t sprt3_err:1; - uint64_t sprt2_err:1; - uint64_t sprt1_err:1; - uint64_t sprt0_err:1; - uint64_t pins_err:1; - uint64_t pop_err:1; - uint64_t pdi_err:1; - uint64_t pgl_err:1; - uint64_t pin_bp:1; - uint64_t pout_err:1; - uint64_t psldbof:1; - uint64_t pidbof:1; - uint64_t reserved_38_47:10; - uint64_t dtime:2; - uint64_t dcnt:2; - uint64_t dmafi:2; - uint64_t reserved_28_31:4; - uint64_t m3_un_wi:1; - uint64_t m3_un_b0:1; - uint64_t m3_up_wi:1; - uint64_t m3_up_b0:1; - uint64_t m2_un_wi:1; - uint64_t m2_un_b0:1; - uint64_t m2_up_wi:1; - uint64_t m2_up_b0:1; - uint64_t reserved_18_19:2; - uint64_t mio_int1:1; - uint64_t mio_int0:1; - uint64_t m1_un_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_up_b0:1; - uint64_t m0_un_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_up_b0:1; - uint64_t reserved_6_7:2; - uint64_t ptime:1; - uint64_t pcnt:1; - uint64_t iob2big:1; - uint64_t bar0_to:1; - uint64_t reserved_1_1:1; - uint64_t rml_to:1; -#else - uint64_t rml_to:1; - uint64_t reserved_1_1:1; - uint64_t bar0_to:1; - uint64_t iob2big:1; - uint64_t pcnt:1; - uint64_t ptime:1; - uint64_t reserved_6_7:2; - uint64_t m0_up_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_un_wi:1; - uint64_t m1_up_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_un_wi:1; - uint64_t mio_int0:1; - uint64_t mio_int1:1; - uint64_t reserved_18_19:2; - uint64_t m2_up_b0:1; - uint64_t m2_up_wi:1; - uint64_t m2_un_b0:1; - uint64_t m2_un_wi:1; - uint64_t m3_up_b0:1; - uint64_t m3_up_wi:1; - uint64_t m3_un_b0:1; - uint64_t m3_un_wi:1; - uint64_t reserved_28_31:4; - uint64_t dmafi:2; - uint64_t dcnt:2; - uint64_t dtime:2; - uint64_t reserved_38_47:10; - uint64_t pidbof:1; - uint64_t psldbof:1; - uint64_t pout_err:1; - uint64_t pin_bp:1; - uint64_t pgl_err:1; - uint64_t pdi_err:1; - uint64_t pop_err:1; - uint64_t pins_err:1; - uint64_t sprt0_err:1; - uint64_t sprt1_err:1; - uint64_t sprt2_err:1; - uint64_t sprt3_err:1; - uint64_t ill_pad:1; - uint64_t pipe_err:1; - uint64_t reserved_62_63:2; -#endif - } s; - struct cvmx_sli_int_enb_ciu_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_61_63:3; - uint64_t ill_pad:1; - uint64_t sprt3_err:1; - uint64_t sprt2_err:1; - uint64_t sprt1_err:1; - uint64_t sprt0_err:1; - uint64_t pins_err:1; - uint64_t pop_err:1; - uint64_t pdi_err:1; - uint64_t pgl_err:1; - uint64_t pin_bp:1; - uint64_t pout_err:1; - uint64_t psldbof:1; - uint64_t pidbof:1; - uint64_t reserved_38_47:10; - uint64_t dtime:2; - uint64_t dcnt:2; - uint64_t dmafi:2; - uint64_t reserved_28_31:4; - uint64_t m3_un_wi:1; - uint64_t m3_un_b0:1; - uint64_t m3_up_wi:1; - uint64_t m3_up_b0:1; - uint64_t m2_un_wi:1; - uint64_t m2_un_b0:1; - uint64_t m2_up_wi:1; - uint64_t m2_up_b0:1; - uint64_t reserved_18_19:2; - uint64_t mio_int1:1; - uint64_t mio_int0:1; - uint64_t m1_un_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_up_b0:1; - uint64_t m0_un_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_up_b0:1; - uint64_t reserved_6_7:2; - uint64_t ptime:1; - uint64_t pcnt:1; - uint64_t iob2big:1; - uint64_t bar0_to:1; - uint64_t reserved_1_1:1; - uint64_t rml_to:1; -#else - uint64_t rml_to:1; - uint64_t reserved_1_1:1; - uint64_t bar0_to:1; - uint64_t iob2big:1; - uint64_t pcnt:1; - uint64_t ptime:1; - uint64_t reserved_6_7:2; - uint64_t m0_up_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_un_wi:1; - uint64_t m1_up_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_un_wi:1; - uint64_t mio_int0:1; - uint64_t mio_int1:1; - uint64_t reserved_18_19:2; - uint64_t m2_up_b0:1; - uint64_t m2_up_wi:1; - uint64_t m2_un_b0:1; - uint64_t m2_un_wi:1; - uint64_t m3_up_b0:1; - uint64_t m3_up_wi:1; - uint64_t m3_un_b0:1; - uint64_t m3_un_wi:1; - uint64_t reserved_28_31:4; - uint64_t dmafi:2; - uint64_t dcnt:2; - uint64_t dtime:2; - uint64_t reserved_38_47:10; - uint64_t pidbof:1; - uint64_t psldbof:1; - uint64_t pout_err:1; - uint64_t pin_bp:1; - uint64_t pgl_err:1; - uint64_t pdi_err:1; - uint64_t pop_err:1; - uint64_t pins_err:1; - uint64_t sprt0_err:1; - uint64_t sprt1_err:1; - uint64_t sprt2_err:1; - uint64_t sprt3_err:1; - uint64_t ill_pad:1; - uint64_t reserved_61_63:3; -#endif - } cn61xx; - struct cvmx_sli_int_enb_ciu_cn63xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_61_63:3; - uint64_t ill_pad:1; - uint64_t reserved_58_59:2; - uint64_t sprt1_err:1; - uint64_t sprt0_err:1; - uint64_t pins_err:1; - uint64_t pop_err:1; - uint64_t pdi_err:1; - uint64_t pgl_err:1; - uint64_t pin_bp:1; - uint64_t pout_err:1; - uint64_t psldbof:1; - uint64_t pidbof:1; - uint64_t reserved_38_47:10; - uint64_t dtime:2; - uint64_t dcnt:2; - uint64_t dmafi:2; - uint64_t reserved_18_31:14; - uint64_t mio_int1:1; - uint64_t mio_int0:1; - uint64_t m1_un_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_up_b0:1; - uint64_t m0_un_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_up_b0:1; - uint64_t reserved_6_7:2; - uint64_t ptime:1; - uint64_t pcnt:1; - uint64_t iob2big:1; - uint64_t bar0_to:1; - uint64_t reserved_1_1:1; - uint64_t rml_to:1; -#else - uint64_t rml_to:1; - uint64_t reserved_1_1:1; - uint64_t bar0_to:1; - uint64_t iob2big:1; - uint64_t pcnt:1; - uint64_t ptime:1; - uint64_t reserved_6_7:2; - uint64_t m0_up_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_un_wi:1; - uint64_t m1_up_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_un_wi:1; - uint64_t mio_int0:1; - uint64_t mio_int1:1; - uint64_t reserved_18_31:14; - uint64_t dmafi:2; - uint64_t dcnt:2; - uint64_t dtime:2; - uint64_t reserved_38_47:10; - uint64_t pidbof:1; - uint64_t psldbof:1; - uint64_t pout_err:1; - uint64_t pin_bp:1; - uint64_t pgl_err:1; - uint64_t pdi_err:1; - uint64_t pop_err:1; - uint64_t pins_err:1; - uint64_t sprt0_err:1; - uint64_t sprt1_err:1; - uint64_t reserved_58_59:2; - uint64_t ill_pad:1; - uint64_t reserved_61_63:3; -#endif - } cn63xx; - struct cvmx_sli_int_enb_ciu_cn63xx cn63xxp1; - struct cvmx_sli_int_enb_ciu_cn61xx cn66xx; - struct cvmx_sli_int_enb_ciu_cn68xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_62_63:2; - uint64_t pipe_err:1; - uint64_t ill_pad:1; - uint64_t reserved_58_59:2; - uint64_t sprt1_err:1; - uint64_t sprt0_err:1; - uint64_t pins_err:1; - uint64_t pop_err:1; - uint64_t pdi_err:1; - uint64_t pgl_err:1; - uint64_t reserved_51_51:1; - uint64_t pout_err:1; - uint64_t psldbof:1; - uint64_t pidbof:1; - uint64_t reserved_38_47:10; - uint64_t dtime:2; - uint64_t dcnt:2; - uint64_t dmafi:2; - uint64_t reserved_18_31:14; - uint64_t mio_int1:1; - uint64_t mio_int0:1; - uint64_t m1_un_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_up_b0:1; - uint64_t m0_un_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_up_b0:1; - uint64_t reserved_6_7:2; - uint64_t ptime:1; - uint64_t pcnt:1; - uint64_t iob2big:1; - uint64_t bar0_to:1; - uint64_t reserved_1_1:1; - uint64_t rml_to:1; -#else - uint64_t rml_to:1; - uint64_t reserved_1_1:1; - uint64_t bar0_to:1; - uint64_t iob2big:1; - uint64_t pcnt:1; - uint64_t ptime:1; - uint64_t reserved_6_7:2; - uint64_t m0_up_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_un_wi:1; - uint64_t m1_up_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_un_wi:1; - uint64_t mio_int0:1; - uint64_t mio_int1:1; - uint64_t reserved_18_31:14; - uint64_t dmafi:2; - uint64_t dcnt:2; - uint64_t dtime:2; - uint64_t reserved_38_47:10; - uint64_t pidbof:1; - uint64_t psldbof:1; - uint64_t pout_err:1; - uint64_t reserved_51_51:1; - uint64_t pgl_err:1; - uint64_t pdi_err:1; - uint64_t pop_err:1; - uint64_t pins_err:1; - uint64_t sprt0_err:1; - uint64_t sprt1_err:1; - uint64_t reserved_58_59:2; - uint64_t ill_pad:1; - uint64_t pipe_err:1; - uint64_t reserved_62_63:2; -#endif - } cn68xx; - struct cvmx_sli_int_enb_ciu_cn68xx cn68xxp1; - struct cvmx_sli_int_enb_ciu_cn61xx cnf71xx; -}; - -union cvmx_sli_int_enb_portx { - uint64_t u64; - struct cvmx_sli_int_enb_portx_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_62_63:2; - uint64_t pipe_err:1; - uint64_t ill_pad:1; - uint64_t sprt3_err:1; - uint64_t sprt2_err:1; - uint64_t sprt1_err:1; - uint64_t sprt0_err:1; - uint64_t pins_err:1; - uint64_t pop_err:1; - uint64_t pdi_err:1; - uint64_t pgl_err:1; - uint64_t pin_bp:1; - uint64_t pout_err:1; - uint64_t psldbof:1; - uint64_t pidbof:1; - uint64_t reserved_38_47:10; - uint64_t dtime:2; - uint64_t dcnt:2; - uint64_t dmafi:2; - uint64_t reserved_28_31:4; - uint64_t m3_un_wi:1; - uint64_t m3_un_b0:1; - uint64_t m3_up_wi:1; - uint64_t m3_up_b0:1; - uint64_t m2_un_wi:1; - uint64_t m2_un_b0:1; - uint64_t m2_up_wi:1; - uint64_t m2_up_b0:1; - uint64_t mac1_int:1; - uint64_t mac0_int:1; - uint64_t mio_int1:1; - uint64_t mio_int0:1; - uint64_t m1_un_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_up_b0:1; - uint64_t m0_un_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_up_b0:1; - uint64_t reserved_6_7:2; - uint64_t ptime:1; - uint64_t pcnt:1; - uint64_t iob2big:1; - uint64_t bar0_to:1; - uint64_t reserved_1_1:1; - uint64_t rml_to:1; -#else - uint64_t rml_to:1; - uint64_t reserved_1_1:1; - uint64_t bar0_to:1; - uint64_t iob2big:1; - uint64_t pcnt:1; - uint64_t ptime:1; - uint64_t reserved_6_7:2; - uint64_t m0_up_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_un_wi:1; - uint64_t m1_up_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_un_wi:1; - uint64_t mio_int0:1; - uint64_t mio_int1:1; - uint64_t mac0_int:1; - uint64_t mac1_int:1; - uint64_t m2_up_b0:1; - uint64_t m2_up_wi:1; - uint64_t m2_un_b0:1; - uint64_t m2_un_wi:1; - uint64_t m3_up_b0:1; - uint64_t m3_up_wi:1; - uint64_t m3_un_b0:1; - uint64_t m3_un_wi:1; - uint64_t reserved_28_31:4; - uint64_t dmafi:2; - uint64_t dcnt:2; - uint64_t dtime:2; - uint64_t reserved_38_47:10; - uint64_t pidbof:1; - uint64_t psldbof:1; - uint64_t pout_err:1; - uint64_t pin_bp:1; - uint64_t pgl_err:1; - uint64_t pdi_err:1; - uint64_t pop_err:1; - uint64_t pins_err:1; - uint64_t sprt0_err:1; - uint64_t sprt1_err:1; - uint64_t sprt2_err:1; - uint64_t sprt3_err:1; - uint64_t ill_pad:1; - uint64_t pipe_err:1; - uint64_t reserved_62_63:2; -#endif - } s; - struct cvmx_sli_int_enb_portx_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_61_63:3; - uint64_t ill_pad:1; - uint64_t sprt3_err:1; - uint64_t sprt2_err:1; - uint64_t sprt1_err:1; - uint64_t sprt0_err:1; - uint64_t pins_err:1; - uint64_t pop_err:1; - uint64_t pdi_err:1; - uint64_t pgl_err:1; - uint64_t pin_bp:1; - uint64_t pout_err:1; - uint64_t psldbof:1; - uint64_t pidbof:1; - uint64_t reserved_38_47:10; - uint64_t dtime:2; - uint64_t dcnt:2; - uint64_t dmafi:2; - uint64_t reserved_28_31:4; - uint64_t m3_un_wi:1; - uint64_t m3_un_b0:1; - uint64_t m3_up_wi:1; - uint64_t m3_up_b0:1; - uint64_t m2_un_wi:1; - uint64_t m2_un_b0:1; - uint64_t m2_up_wi:1; - uint64_t m2_up_b0:1; - uint64_t mac1_int:1; - uint64_t mac0_int:1; - uint64_t mio_int1:1; - uint64_t mio_int0:1; - uint64_t m1_un_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_up_b0:1; - uint64_t m0_un_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_up_b0:1; - uint64_t reserved_6_7:2; - uint64_t ptime:1; - uint64_t pcnt:1; - uint64_t iob2big:1; - uint64_t bar0_to:1; - uint64_t reserved_1_1:1; - uint64_t rml_to:1; -#else - uint64_t rml_to:1; - uint64_t reserved_1_1:1; - uint64_t bar0_to:1; - uint64_t iob2big:1; - uint64_t pcnt:1; - uint64_t ptime:1; - uint64_t reserved_6_7:2; - uint64_t m0_up_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_un_wi:1; - uint64_t m1_up_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_un_wi:1; - uint64_t mio_int0:1; - uint64_t mio_int1:1; - uint64_t mac0_int:1; - uint64_t mac1_int:1; - uint64_t m2_up_b0:1; - uint64_t m2_up_wi:1; - uint64_t m2_un_b0:1; - uint64_t m2_un_wi:1; - uint64_t m3_up_b0:1; - uint64_t m3_up_wi:1; - uint64_t m3_un_b0:1; - uint64_t m3_un_wi:1; - uint64_t reserved_28_31:4; - uint64_t dmafi:2; - uint64_t dcnt:2; - uint64_t dtime:2; - uint64_t reserved_38_47:10; - uint64_t pidbof:1; - uint64_t psldbof:1; - uint64_t pout_err:1; - uint64_t pin_bp:1; - uint64_t pgl_err:1; - uint64_t pdi_err:1; - uint64_t pop_err:1; - uint64_t pins_err:1; - uint64_t sprt0_err:1; - uint64_t sprt1_err:1; - uint64_t sprt2_err:1; - uint64_t sprt3_err:1; - uint64_t ill_pad:1; - uint64_t reserved_61_63:3; -#endif - } cn61xx; - struct cvmx_sli_int_enb_portx_cn63xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_61_63:3; - uint64_t ill_pad:1; - uint64_t reserved_58_59:2; - uint64_t sprt1_err:1; - uint64_t sprt0_err:1; - uint64_t pins_err:1; - uint64_t pop_err:1; - uint64_t pdi_err:1; - uint64_t pgl_err:1; - uint64_t pin_bp:1; - uint64_t pout_err:1; - uint64_t psldbof:1; - uint64_t pidbof:1; - uint64_t reserved_38_47:10; - uint64_t dtime:2; - uint64_t dcnt:2; - uint64_t dmafi:2; - uint64_t reserved_20_31:12; - uint64_t mac1_int:1; - uint64_t mac0_int:1; - uint64_t mio_int1:1; - uint64_t mio_int0:1; - uint64_t m1_un_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_up_b0:1; - uint64_t m0_un_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_up_b0:1; - uint64_t reserved_6_7:2; - uint64_t ptime:1; - uint64_t pcnt:1; - uint64_t iob2big:1; - uint64_t bar0_to:1; - uint64_t reserved_1_1:1; - uint64_t rml_to:1; -#else - uint64_t rml_to:1; - uint64_t reserved_1_1:1; - uint64_t bar0_to:1; - uint64_t iob2big:1; - uint64_t pcnt:1; - uint64_t ptime:1; - uint64_t reserved_6_7:2; - uint64_t m0_up_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_un_wi:1; - uint64_t m1_up_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_un_wi:1; - uint64_t mio_int0:1; - uint64_t mio_int1:1; - uint64_t mac0_int:1; - uint64_t mac1_int:1; - uint64_t reserved_20_31:12; - uint64_t dmafi:2; - uint64_t dcnt:2; - uint64_t dtime:2; - uint64_t reserved_38_47:10; - uint64_t pidbof:1; - uint64_t psldbof:1; - uint64_t pout_err:1; - uint64_t pin_bp:1; - uint64_t pgl_err:1; - uint64_t pdi_err:1; - uint64_t pop_err:1; - uint64_t pins_err:1; - uint64_t sprt0_err:1; - uint64_t sprt1_err:1; - uint64_t reserved_58_59:2; - uint64_t ill_pad:1; - uint64_t reserved_61_63:3; -#endif - } cn63xx; - struct cvmx_sli_int_enb_portx_cn63xx cn63xxp1; - struct cvmx_sli_int_enb_portx_cn61xx cn66xx; - struct cvmx_sli_int_enb_portx_cn68xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_62_63:2; - uint64_t pipe_err:1; - uint64_t ill_pad:1; - uint64_t reserved_58_59:2; - uint64_t sprt1_err:1; - uint64_t sprt0_err:1; - uint64_t pins_err:1; - uint64_t pop_err:1; - uint64_t pdi_err:1; - uint64_t pgl_err:1; - uint64_t reserved_51_51:1; - uint64_t pout_err:1; - uint64_t psldbof:1; - uint64_t pidbof:1; - uint64_t reserved_38_47:10; - uint64_t dtime:2; - uint64_t dcnt:2; - uint64_t dmafi:2; - uint64_t reserved_20_31:12; - uint64_t mac1_int:1; - uint64_t mac0_int:1; - uint64_t mio_int1:1; - uint64_t mio_int0:1; - uint64_t m1_un_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_up_b0:1; - uint64_t m0_un_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_up_b0:1; - uint64_t reserved_6_7:2; - uint64_t ptime:1; - uint64_t pcnt:1; - uint64_t iob2big:1; - uint64_t bar0_to:1; - uint64_t reserved_1_1:1; - uint64_t rml_to:1; -#else - uint64_t rml_to:1; - uint64_t reserved_1_1:1; - uint64_t bar0_to:1; - uint64_t iob2big:1; - uint64_t pcnt:1; - uint64_t ptime:1; - uint64_t reserved_6_7:2; - uint64_t m0_up_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_un_wi:1; - uint64_t m1_up_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_un_wi:1; - uint64_t mio_int0:1; - uint64_t mio_int1:1; - uint64_t mac0_int:1; - uint64_t mac1_int:1; - uint64_t reserved_20_31:12; - uint64_t dmafi:2; - uint64_t dcnt:2; - uint64_t dtime:2; - uint64_t reserved_38_47:10; - uint64_t pidbof:1; - uint64_t psldbof:1; - uint64_t pout_err:1; - uint64_t reserved_51_51:1; - uint64_t pgl_err:1; - uint64_t pdi_err:1; - uint64_t pop_err:1; - uint64_t pins_err:1; - uint64_t sprt0_err:1; - uint64_t sprt1_err:1; - uint64_t reserved_58_59:2; - uint64_t ill_pad:1; - uint64_t pipe_err:1; - uint64_t reserved_62_63:2; -#endif - } cn68xx; - struct cvmx_sli_int_enb_portx_cn68xx cn68xxp1; - struct cvmx_sli_int_enb_portx_cn61xx cnf71xx; -}; - -union cvmx_sli_int_sum { - uint64_t u64; - struct cvmx_sli_int_sum_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_62_63:2; - uint64_t pipe_err:1; - uint64_t ill_pad:1; - uint64_t sprt3_err:1; - uint64_t sprt2_err:1; - uint64_t sprt1_err:1; - uint64_t sprt0_err:1; - uint64_t pins_err:1; - uint64_t pop_err:1; - uint64_t pdi_err:1; - uint64_t pgl_err:1; - uint64_t pin_bp:1; - uint64_t pout_err:1; - uint64_t psldbof:1; - uint64_t pidbof:1; - uint64_t reserved_38_47:10; - uint64_t dtime:2; - uint64_t dcnt:2; - uint64_t dmafi:2; - uint64_t reserved_28_31:4; - uint64_t m3_un_wi:1; - uint64_t m3_un_b0:1; - uint64_t m3_up_wi:1; - uint64_t m3_up_b0:1; - uint64_t m2_un_wi:1; - uint64_t m2_un_b0:1; - uint64_t m2_up_wi:1; - uint64_t m2_up_b0:1; - uint64_t mac1_int:1; - uint64_t mac0_int:1; - uint64_t mio_int1:1; - uint64_t mio_int0:1; - uint64_t m1_un_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_up_b0:1; - uint64_t m0_un_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_up_b0:1; - uint64_t reserved_6_7:2; - uint64_t ptime:1; - uint64_t pcnt:1; - uint64_t iob2big:1; - uint64_t bar0_to:1; - uint64_t reserved_1_1:1; - uint64_t rml_to:1; -#else - uint64_t rml_to:1; - uint64_t reserved_1_1:1; - uint64_t bar0_to:1; - uint64_t iob2big:1; - uint64_t pcnt:1; - uint64_t ptime:1; - uint64_t reserved_6_7:2; - uint64_t m0_up_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_un_wi:1; - uint64_t m1_up_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_un_wi:1; - uint64_t mio_int0:1; - uint64_t mio_int1:1; - uint64_t mac0_int:1; - uint64_t mac1_int:1; - uint64_t m2_up_b0:1; - uint64_t m2_up_wi:1; - uint64_t m2_un_b0:1; - uint64_t m2_un_wi:1; - uint64_t m3_up_b0:1; - uint64_t m3_up_wi:1; - uint64_t m3_un_b0:1; - uint64_t m3_un_wi:1; - uint64_t reserved_28_31:4; - uint64_t dmafi:2; - uint64_t dcnt:2; - uint64_t dtime:2; - uint64_t reserved_38_47:10; - uint64_t pidbof:1; - uint64_t psldbof:1; - uint64_t pout_err:1; - uint64_t pin_bp:1; - uint64_t pgl_err:1; - uint64_t pdi_err:1; - uint64_t pop_err:1; - uint64_t pins_err:1; - uint64_t sprt0_err:1; - uint64_t sprt1_err:1; - uint64_t sprt2_err:1; - uint64_t sprt3_err:1; - uint64_t ill_pad:1; - uint64_t pipe_err:1; - uint64_t reserved_62_63:2; -#endif - } s; - struct cvmx_sli_int_sum_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_61_63:3; - uint64_t ill_pad:1; - uint64_t sprt3_err:1; - uint64_t sprt2_err:1; - uint64_t sprt1_err:1; - uint64_t sprt0_err:1; - uint64_t pins_err:1; - uint64_t pop_err:1; - uint64_t pdi_err:1; - uint64_t pgl_err:1; - uint64_t pin_bp:1; - uint64_t pout_err:1; - uint64_t psldbof:1; - uint64_t pidbof:1; - uint64_t reserved_38_47:10; - uint64_t dtime:2; - uint64_t dcnt:2; - uint64_t dmafi:2; - uint64_t reserved_28_31:4; - uint64_t m3_un_wi:1; - uint64_t m3_un_b0:1; - uint64_t m3_up_wi:1; - uint64_t m3_up_b0:1; - uint64_t m2_un_wi:1; - uint64_t m2_un_b0:1; - uint64_t m2_up_wi:1; - uint64_t m2_up_b0:1; - uint64_t mac1_int:1; - uint64_t mac0_int:1; - uint64_t mio_int1:1; - uint64_t mio_int0:1; - uint64_t m1_un_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_up_b0:1; - uint64_t m0_un_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_up_b0:1; - uint64_t reserved_6_7:2; - uint64_t ptime:1; - uint64_t pcnt:1; - uint64_t iob2big:1; - uint64_t bar0_to:1; - uint64_t reserved_1_1:1; - uint64_t rml_to:1; -#else - uint64_t rml_to:1; - uint64_t reserved_1_1:1; - uint64_t bar0_to:1; - uint64_t iob2big:1; - uint64_t pcnt:1; - uint64_t ptime:1; - uint64_t reserved_6_7:2; - uint64_t m0_up_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_un_wi:1; - uint64_t m1_up_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_un_wi:1; - uint64_t mio_int0:1; - uint64_t mio_int1:1; - uint64_t mac0_int:1; - uint64_t mac1_int:1; - uint64_t m2_up_b0:1; - uint64_t m2_up_wi:1; - uint64_t m2_un_b0:1; - uint64_t m2_un_wi:1; - uint64_t m3_up_b0:1; - uint64_t m3_up_wi:1; - uint64_t m3_un_b0:1; - uint64_t m3_un_wi:1; - uint64_t reserved_28_31:4; - uint64_t dmafi:2; - uint64_t dcnt:2; - uint64_t dtime:2; - uint64_t reserved_38_47:10; - uint64_t pidbof:1; - uint64_t psldbof:1; - uint64_t pout_err:1; - uint64_t pin_bp:1; - uint64_t pgl_err:1; - uint64_t pdi_err:1; - uint64_t pop_err:1; - uint64_t pins_err:1; - uint64_t sprt0_err:1; - uint64_t sprt1_err:1; - uint64_t sprt2_err:1; - uint64_t sprt3_err:1; - uint64_t ill_pad:1; - uint64_t reserved_61_63:3; -#endif - } cn61xx; - struct cvmx_sli_int_sum_cn63xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_61_63:3; - uint64_t ill_pad:1; - uint64_t reserved_58_59:2; - uint64_t sprt1_err:1; - uint64_t sprt0_err:1; - uint64_t pins_err:1; - uint64_t pop_err:1; - uint64_t pdi_err:1; - uint64_t pgl_err:1; - uint64_t pin_bp:1; - uint64_t pout_err:1; - uint64_t psldbof:1; - uint64_t pidbof:1; - uint64_t reserved_38_47:10; - uint64_t dtime:2; - uint64_t dcnt:2; - uint64_t dmafi:2; - uint64_t reserved_20_31:12; - uint64_t mac1_int:1; - uint64_t mac0_int:1; - uint64_t mio_int1:1; - uint64_t mio_int0:1; - uint64_t m1_un_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_up_b0:1; - uint64_t m0_un_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_up_b0:1; - uint64_t reserved_6_7:2; - uint64_t ptime:1; - uint64_t pcnt:1; - uint64_t iob2big:1; - uint64_t bar0_to:1; - uint64_t reserved_1_1:1; - uint64_t rml_to:1; -#else - uint64_t rml_to:1; - uint64_t reserved_1_1:1; - uint64_t bar0_to:1; - uint64_t iob2big:1; - uint64_t pcnt:1; - uint64_t ptime:1; - uint64_t reserved_6_7:2; - uint64_t m0_up_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_un_wi:1; - uint64_t m1_up_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_un_wi:1; - uint64_t mio_int0:1; - uint64_t mio_int1:1; - uint64_t mac0_int:1; - uint64_t mac1_int:1; - uint64_t reserved_20_31:12; - uint64_t dmafi:2; - uint64_t dcnt:2; - uint64_t dtime:2; - uint64_t reserved_38_47:10; - uint64_t pidbof:1; - uint64_t psldbof:1; - uint64_t pout_err:1; - uint64_t pin_bp:1; - uint64_t pgl_err:1; - uint64_t pdi_err:1; - uint64_t pop_err:1; - uint64_t pins_err:1; - uint64_t sprt0_err:1; - uint64_t sprt1_err:1; - uint64_t reserved_58_59:2; - uint64_t ill_pad:1; - uint64_t reserved_61_63:3; -#endif - } cn63xx; - struct cvmx_sli_int_sum_cn63xx cn63xxp1; - struct cvmx_sli_int_sum_cn61xx cn66xx; - struct cvmx_sli_int_sum_cn68xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_62_63:2; - uint64_t pipe_err:1; - uint64_t ill_pad:1; - uint64_t reserved_58_59:2; - uint64_t sprt1_err:1; - uint64_t sprt0_err:1; - uint64_t pins_err:1; - uint64_t pop_err:1; - uint64_t pdi_err:1; - uint64_t pgl_err:1; - uint64_t reserved_51_51:1; - uint64_t pout_err:1; - uint64_t psldbof:1; - uint64_t pidbof:1; - uint64_t reserved_38_47:10; - uint64_t dtime:2; - uint64_t dcnt:2; - uint64_t dmafi:2; - uint64_t reserved_20_31:12; - uint64_t mac1_int:1; - uint64_t mac0_int:1; - uint64_t mio_int1:1; - uint64_t mio_int0:1; - uint64_t m1_un_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_up_b0:1; - uint64_t m0_un_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_up_b0:1; - uint64_t reserved_6_7:2; - uint64_t ptime:1; - uint64_t pcnt:1; - uint64_t iob2big:1; - uint64_t bar0_to:1; - uint64_t reserved_1_1:1; - uint64_t rml_to:1; -#else - uint64_t rml_to:1; - uint64_t reserved_1_1:1; - uint64_t bar0_to:1; - uint64_t iob2big:1; - uint64_t pcnt:1; - uint64_t ptime:1; - uint64_t reserved_6_7:2; - uint64_t m0_up_b0:1; - uint64_t m0_up_wi:1; - uint64_t m0_un_b0:1; - uint64_t m0_un_wi:1; - uint64_t m1_up_b0:1; - uint64_t m1_up_wi:1; - uint64_t m1_un_b0:1; - uint64_t m1_un_wi:1; - uint64_t mio_int0:1; - uint64_t mio_int1:1; - uint64_t mac0_int:1; - uint64_t mac1_int:1; - uint64_t reserved_20_31:12; - uint64_t dmafi:2; - uint64_t dcnt:2; - uint64_t dtime:2; - uint64_t reserved_38_47:10; - uint64_t pidbof:1; - uint64_t psldbof:1; - uint64_t pout_err:1; - uint64_t reserved_51_51:1; - uint64_t pgl_err:1; - uint64_t pdi_err:1; - uint64_t pop_err:1; - uint64_t pins_err:1; - uint64_t sprt0_err:1; - uint64_t sprt1_err:1; - uint64_t reserved_58_59:2; - uint64_t ill_pad:1; - uint64_t pipe_err:1; - uint64_t reserved_62_63:2; -#endif - } cn68xx; - struct cvmx_sli_int_sum_cn68xx cn68xxp1; - struct cvmx_sli_int_sum_cn61xx cnf71xx; -}; - -union cvmx_sli_last_win_rdata0 { - uint64_t u64; - struct cvmx_sli_last_win_rdata0_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t data:64; -#else - uint64_t data:64; -#endif + __BITFIELD_FIELD(uint64_t reserved_22_63:42, + __BITFIELD_FIELD(uint64_t intd:1, + __BITFIELD_FIELD(uint64_t intc:1, + __BITFIELD_FIELD(uint64_t intb:1, + __BITFIELD_FIELD(uint64_t inta:1, + __BITFIELD_FIELD(uint64_t dis_port:1, + __BITFIELD_FIELD(uint64_t waitl_com:1, + __BITFIELD_FIELD(uint64_t intd_map:2, + __BITFIELD_FIELD(uint64_t intc_map:2, + __BITFIELD_FIELD(uint64_t intb_map:2, + __BITFIELD_FIELD(uint64_t inta_map:2, + __BITFIELD_FIELD(uint64_t ctlp_ro:1, + __BITFIELD_FIELD(uint64_t reserved_6_6:1, + __BITFIELD_FIELD(uint64_t ptlp_ro:1, + __BITFIELD_FIELD(uint64_t reserved_1_4:4, + __BITFIELD_FIELD(uint64_t wait_com:1, + ;)))))))))))))))) } s; - struct cvmx_sli_last_win_rdata0_s cn61xx; - struct cvmx_sli_last_win_rdata0_s cn63xx; - struct cvmx_sli_last_win_rdata0_s cn63xxp1; - struct cvmx_sli_last_win_rdata0_s cn66xx; - struct cvmx_sli_last_win_rdata0_s cn68xx; - struct cvmx_sli_last_win_rdata0_s cn68xxp1; - struct cvmx_sli_last_win_rdata0_s cnf71xx; -}; - -union cvmx_sli_last_win_rdata1 { - uint64_t u64; - struct cvmx_sli_last_win_rdata1_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t data:64; -#else - uint64_t data:64; -#endif - } s; - struct cvmx_sli_last_win_rdata1_s cn61xx; - struct cvmx_sli_last_win_rdata1_s cn63xx; - struct cvmx_sli_last_win_rdata1_s cn63xxp1; - struct cvmx_sli_last_win_rdata1_s cn66xx; - struct cvmx_sli_last_win_rdata1_s cn68xx; - struct cvmx_sli_last_win_rdata1_s cn68xxp1; - struct cvmx_sli_last_win_rdata1_s cnf71xx; -}; - -union cvmx_sli_last_win_rdata2 { - uint64_t u64; - struct cvmx_sli_last_win_rdata2_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t data:64; -#else - uint64_t data:64; -#endif - } s; - struct cvmx_sli_last_win_rdata2_s cn61xx; - struct cvmx_sli_last_win_rdata2_s cn66xx; - struct cvmx_sli_last_win_rdata2_s cnf71xx; -}; - -union cvmx_sli_last_win_rdata3 { - uint64_t u64; - struct cvmx_sli_last_win_rdata3_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t data:64; -#else - uint64_t data:64; -#endif - } s; - struct cvmx_sli_last_win_rdata3_s cn61xx; - struct cvmx_sli_last_win_rdata3_s cn66xx; - struct cvmx_sli_last_win_rdata3_s cnf71xx; -}; - -union cvmx_sli_mac_credit_cnt { - uint64_t u64; - struct cvmx_sli_mac_credit_cnt_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_54_63:10; - uint64_t p1_c_d:1; - uint64_t p1_n_d:1; - uint64_t p1_p_d:1; - uint64_t p0_c_d:1; - uint64_t p0_n_d:1; - uint64_t p0_p_d:1; - uint64_t p1_ccnt:8; - uint64_t p1_ncnt:8; - uint64_t p1_pcnt:8; - uint64_t p0_ccnt:8; - uint64_t p0_ncnt:8; - uint64_t p0_pcnt:8; -#else - uint64_t p0_pcnt:8; - uint64_t p0_ncnt:8; - uint64_t p0_ccnt:8; - uint64_t p1_pcnt:8; - uint64_t p1_ncnt:8; - uint64_t p1_ccnt:8; - uint64_t p0_p_d:1; - uint64_t p0_n_d:1; - uint64_t p0_c_d:1; - uint64_t p1_p_d:1; - uint64_t p1_n_d:1; - uint64_t p1_c_d:1; - uint64_t reserved_54_63:10; -#endif - } s; - struct cvmx_sli_mac_credit_cnt_s cn61xx; - struct cvmx_sli_mac_credit_cnt_s cn63xx; - struct cvmx_sli_mac_credit_cnt_cn63xxp1 { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_48_63:16; - uint64_t p1_ccnt:8; - uint64_t p1_ncnt:8; - uint64_t p1_pcnt:8; - uint64_t p0_ccnt:8; - uint64_t p0_ncnt:8; - uint64_t p0_pcnt:8; -#else - uint64_t p0_pcnt:8; - uint64_t p0_ncnt:8; - uint64_t p0_ccnt:8; - uint64_t p1_pcnt:8; - uint64_t p1_ncnt:8; - uint64_t p1_ccnt:8; - uint64_t reserved_48_63:16; -#endif - } cn63xxp1; - struct cvmx_sli_mac_credit_cnt_s cn66xx; - struct cvmx_sli_mac_credit_cnt_s cn68xx; - struct cvmx_sli_mac_credit_cnt_s cn68xxp1; - struct cvmx_sli_mac_credit_cnt_s cnf71xx; -}; - -union cvmx_sli_mac_credit_cnt2 { - uint64_t u64; - struct cvmx_sli_mac_credit_cnt2_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_54_63:10; - uint64_t p3_c_d:1; - uint64_t p3_n_d:1; - uint64_t p3_p_d:1; - uint64_t p2_c_d:1; - uint64_t p2_n_d:1; - uint64_t p2_p_d:1; - uint64_t p3_ccnt:8; - uint64_t p3_ncnt:8; - uint64_t p3_pcnt:8; - uint64_t p2_ccnt:8; - uint64_t p2_ncnt:8; - uint64_t p2_pcnt:8; -#else - uint64_t p2_pcnt:8; - uint64_t p2_ncnt:8; - uint64_t p2_ccnt:8; - uint64_t p3_pcnt:8; - uint64_t p3_ncnt:8; - uint64_t p3_ccnt:8; - uint64_t p2_p_d:1; - uint64_t p2_n_d:1; - uint64_t p2_c_d:1; - uint64_t p3_p_d:1; - uint64_t p3_n_d:1; - uint64_t p3_c_d:1; - uint64_t reserved_54_63:10; -#endif - } s; - struct cvmx_sli_mac_credit_cnt2_s cn61xx; - struct cvmx_sli_mac_credit_cnt2_s cn66xx; - struct cvmx_sli_mac_credit_cnt2_s cnf71xx; -}; - -union cvmx_sli_mac_number { - uint64_t u64; - struct cvmx_sli_mac_number_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_9_63:55; - uint64_t a_mode:1; - uint64_t num:8; -#else - uint64_t num:8; - uint64_t a_mode:1; - uint64_t reserved_9_63:55; -#endif - } s; - struct cvmx_sli_mac_number_s cn61xx; - struct cvmx_sli_mac_number_cn63xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_8_63:56; - uint64_t num:8; -#else - uint64_t num:8; - uint64_t reserved_8_63:56; -#endif - } cn63xx; - struct cvmx_sli_mac_number_s cn66xx; - struct cvmx_sli_mac_number_cn63xx cn68xx; - struct cvmx_sli_mac_number_cn63xx cn68xxp1; - struct cvmx_sli_mac_number_s cnf71xx; }; union cvmx_sli_mem_access_ctl { uint64_t u64; struct cvmx_sli_mem_access_ctl_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_14_63:50; - uint64_t max_word:4; - uint64_t timer:10; -#else - uint64_t timer:10; - uint64_t max_word:4; - uint64_t reserved_14_63:50; -#endif - } s; - struct cvmx_sli_mem_access_ctl_s cn61xx; - struct cvmx_sli_mem_access_ctl_s cn63xx; - struct cvmx_sli_mem_access_ctl_s cn63xxp1; - struct cvmx_sli_mem_access_ctl_s cn66xx; - struct cvmx_sli_mem_access_ctl_s cn68xx; - struct cvmx_sli_mem_access_ctl_s cn68xxp1; - struct cvmx_sli_mem_access_ctl_s cnf71xx; -}; - -union cvmx_sli_mem_access_subidx { - uint64_t u64; - struct cvmx_sli_mem_access_subidx_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_43_63:21; - uint64_t zero:1; - uint64_t port:3; - uint64_t nmerge:1; - uint64_t esr:2; - uint64_t esw:2; - uint64_t wtype:2; - uint64_t rtype:2; - uint64_t reserved_0_29:30; -#else - uint64_t reserved_0_29:30; - uint64_t rtype:2; - uint64_t wtype:2; - uint64_t esw:2; - uint64_t esr:2; - uint64_t nmerge:1; - uint64_t port:3; - uint64_t zero:1; - uint64_t reserved_43_63:21; -#endif - } s; - struct cvmx_sli_mem_access_subidx_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_43_63:21; - uint64_t zero:1; - uint64_t port:3; - uint64_t nmerge:1; - uint64_t esr:2; - uint64_t esw:2; - uint64_t wtype:2; - uint64_t rtype:2; - uint64_t ba:30; -#else - uint64_t ba:30; - uint64_t rtype:2; - uint64_t wtype:2; - uint64_t esw:2; - uint64_t esr:2; - uint64_t nmerge:1; - uint64_t port:3; - uint64_t zero:1; - uint64_t reserved_43_63:21; -#endif - } cn61xx; - struct cvmx_sli_mem_access_subidx_cn61xx cn63xx; - struct cvmx_sli_mem_access_subidx_cn61xx cn63xxp1; - struct cvmx_sli_mem_access_subidx_cn61xx cn66xx; - struct cvmx_sli_mem_access_subidx_cn68xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_43_63:21; - uint64_t zero:1; - uint64_t port:3; - uint64_t nmerge:1; - uint64_t esr:2; - uint64_t esw:2; - uint64_t wtype:2; - uint64_t rtype:2; - uint64_t ba:28; - uint64_t reserved_0_1:2; -#else - uint64_t reserved_0_1:2; - uint64_t ba:28; - uint64_t rtype:2; - uint64_t wtype:2; - uint64_t esw:2; - uint64_t esr:2; - uint64_t nmerge:1; - uint64_t port:3; - uint64_t zero:1; - uint64_t reserved_43_63:21; -#endif - } cn68xx; - struct cvmx_sli_mem_access_subidx_cn68xx cn68xxp1; - struct cvmx_sli_mem_access_subidx_cn61xx cnf71xx; -}; - -union cvmx_sli_msi_enb0 { - uint64_t u64; - struct cvmx_sli_msi_enb0_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t enb:64; -#else - uint64_t enb:64; -#endif - } s; - struct cvmx_sli_msi_enb0_s cn61xx; - struct cvmx_sli_msi_enb0_s cn63xx; - struct cvmx_sli_msi_enb0_s cn63xxp1; - struct cvmx_sli_msi_enb0_s cn66xx; - struct cvmx_sli_msi_enb0_s cn68xx; - struct cvmx_sli_msi_enb0_s cn68xxp1; - struct cvmx_sli_msi_enb0_s cnf71xx; -}; - -union cvmx_sli_msi_enb1 { - uint64_t u64; - struct cvmx_sli_msi_enb1_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t enb:64; -#else - uint64_t enb:64; -#endif - } s; - struct cvmx_sli_msi_enb1_s cn61xx; - struct cvmx_sli_msi_enb1_s cn63xx; - struct cvmx_sli_msi_enb1_s cn63xxp1; - struct cvmx_sli_msi_enb1_s cn66xx; - struct cvmx_sli_msi_enb1_s cn68xx; - struct cvmx_sli_msi_enb1_s cn68xxp1; - struct cvmx_sli_msi_enb1_s cnf71xx; -}; - -union cvmx_sli_msi_enb2 { - uint64_t u64; - struct cvmx_sli_msi_enb2_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t enb:64; -#else - uint64_t enb:64; -#endif - } s; - struct cvmx_sli_msi_enb2_s cn61xx; - struct cvmx_sli_msi_enb2_s cn63xx; - struct cvmx_sli_msi_enb2_s cn63xxp1; - struct cvmx_sli_msi_enb2_s cn66xx; - struct cvmx_sli_msi_enb2_s cn68xx; - struct cvmx_sli_msi_enb2_s cn68xxp1; - struct cvmx_sli_msi_enb2_s cnf71xx; -}; - -union cvmx_sli_msi_enb3 { - uint64_t u64; - struct cvmx_sli_msi_enb3_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t enb:64; -#else - uint64_t enb:64; -#endif - } s; - struct cvmx_sli_msi_enb3_s cn61xx; - struct cvmx_sli_msi_enb3_s cn63xx; - struct cvmx_sli_msi_enb3_s cn63xxp1; - struct cvmx_sli_msi_enb3_s cn66xx; - struct cvmx_sli_msi_enb3_s cn68xx; - struct cvmx_sli_msi_enb3_s cn68xxp1; - struct cvmx_sli_msi_enb3_s cnf71xx; -}; - -union cvmx_sli_msi_rcv0 { - uint64_t u64; - struct cvmx_sli_msi_rcv0_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t intr:64; -#else - uint64_t intr:64; -#endif - } s; - struct cvmx_sli_msi_rcv0_s cn61xx; - struct cvmx_sli_msi_rcv0_s cn63xx; - struct cvmx_sli_msi_rcv0_s cn63xxp1; - struct cvmx_sli_msi_rcv0_s cn66xx; - struct cvmx_sli_msi_rcv0_s cn68xx; - struct cvmx_sli_msi_rcv0_s cn68xxp1; - struct cvmx_sli_msi_rcv0_s cnf71xx; -}; - -union cvmx_sli_msi_rcv1 { - uint64_t u64; - struct cvmx_sli_msi_rcv1_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t intr:64; -#else - uint64_t intr:64; -#endif - } s; - struct cvmx_sli_msi_rcv1_s cn61xx; - struct cvmx_sli_msi_rcv1_s cn63xx; - struct cvmx_sli_msi_rcv1_s cn63xxp1; - struct cvmx_sli_msi_rcv1_s cn66xx; - struct cvmx_sli_msi_rcv1_s cn68xx; - struct cvmx_sli_msi_rcv1_s cn68xxp1; - struct cvmx_sli_msi_rcv1_s cnf71xx; -}; - -union cvmx_sli_msi_rcv2 { - uint64_t u64; - struct cvmx_sli_msi_rcv2_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t intr:64; -#else - uint64_t intr:64; -#endif - } s; - struct cvmx_sli_msi_rcv2_s cn61xx; - struct cvmx_sli_msi_rcv2_s cn63xx; - struct cvmx_sli_msi_rcv2_s cn63xxp1; - struct cvmx_sli_msi_rcv2_s cn66xx; - struct cvmx_sli_msi_rcv2_s cn68xx; - struct cvmx_sli_msi_rcv2_s cn68xxp1; - struct cvmx_sli_msi_rcv2_s cnf71xx; -}; - -union cvmx_sli_msi_rcv3 { - uint64_t u64; - struct cvmx_sli_msi_rcv3_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t intr:64; -#else - uint64_t intr:64; -#endif - } s; - struct cvmx_sli_msi_rcv3_s cn61xx; - struct cvmx_sli_msi_rcv3_s cn63xx; - struct cvmx_sli_msi_rcv3_s cn63xxp1; - struct cvmx_sli_msi_rcv3_s cn66xx; - struct cvmx_sli_msi_rcv3_s cn68xx; - struct cvmx_sli_msi_rcv3_s cn68xxp1; - struct cvmx_sli_msi_rcv3_s cnf71xx; -}; - -union cvmx_sli_msi_rd_map { - uint64_t u64; - struct cvmx_sli_msi_rd_map_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_16_63:48; - uint64_t rd_int:8; - uint64_t msi_int:8; -#else - uint64_t msi_int:8; - uint64_t rd_int:8; - uint64_t reserved_16_63:48; -#endif - } s; - struct cvmx_sli_msi_rd_map_s cn61xx; - struct cvmx_sli_msi_rd_map_s cn63xx; - struct cvmx_sli_msi_rd_map_s cn63xxp1; - struct cvmx_sli_msi_rd_map_s cn66xx; - struct cvmx_sli_msi_rd_map_s cn68xx; - struct cvmx_sli_msi_rd_map_s cn68xxp1; - struct cvmx_sli_msi_rd_map_s cnf71xx; -}; - -union cvmx_sli_msi_w1c_enb0 { - uint64_t u64; - struct cvmx_sli_msi_w1c_enb0_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t clr:64; -#else - uint64_t clr:64; -#endif - } s; - struct cvmx_sli_msi_w1c_enb0_s cn61xx; - struct cvmx_sli_msi_w1c_enb0_s cn63xx; - struct cvmx_sli_msi_w1c_enb0_s cn63xxp1; - struct cvmx_sli_msi_w1c_enb0_s cn66xx; - struct cvmx_sli_msi_w1c_enb0_s cn68xx; - struct cvmx_sli_msi_w1c_enb0_s cn68xxp1; - struct cvmx_sli_msi_w1c_enb0_s cnf71xx; -}; - -union cvmx_sli_msi_w1c_enb1 { - uint64_t u64; - struct cvmx_sli_msi_w1c_enb1_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t clr:64; -#else - uint64_t clr:64; -#endif - } s; - struct cvmx_sli_msi_w1c_enb1_s cn61xx; - struct cvmx_sli_msi_w1c_enb1_s cn63xx; - struct cvmx_sli_msi_w1c_enb1_s cn63xxp1; - struct cvmx_sli_msi_w1c_enb1_s cn66xx; - struct cvmx_sli_msi_w1c_enb1_s cn68xx; - struct cvmx_sli_msi_w1c_enb1_s cn68xxp1; - struct cvmx_sli_msi_w1c_enb1_s cnf71xx; -}; - -union cvmx_sli_msi_w1c_enb2 { - uint64_t u64; - struct cvmx_sli_msi_w1c_enb2_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t clr:64; -#else - uint64_t clr:64; -#endif - } s; - struct cvmx_sli_msi_w1c_enb2_s cn61xx; - struct cvmx_sli_msi_w1c_enb2_s cn63xx; - struct cvmx_sli_msi_w1c_enb2_s cn63xxp1; - struct cvmx_sli_msi_w1c_enb2_s cn66xx; - struct cvmx_sli_msi_w1c_enb2_s cn68xx; - struct cvmx_sli_msi_w1c_enb2_s cn68xxp1; - struct cvmx_sli_msi_w1c_enb2_s cnf71xx; -}; - -union cvmx_sli_msi_w1c_enb3 { - uint64_t u64; - struct cvmx_sli_msi_w1c_enb3_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t clr:64; -#else - uint64_t clr:64; -#endif - } s; - struct cvmx_sli_msi_w1c_enb3_s cn61xx; - struct cvmx_sli_msi_w1c_enb3_s cn63xx; - struct cvmx_sli_msi_w1c_enb3_s cn63xxp1; - struct cvmx_sli_msi_w1c_enb3_s cn66xx; - struct cvmx_sli_msi_w1c_enb3_s cn68xx; - struct cvmx_sli_msi_w1c_enb3_s cn68xxp1; - struct cvmx_sli_msi_w1c_enb3_s cnf71xx; -}; - -union cvmx_sli_msi_w1s_enb0 { - uint64_t u64; - struct cvmx_sli_msi_w1s_enb0_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t set:64; -#else - uint64_t set:64; -#endif - } s; - struct cvmx_sli_msi_w1s_enb0_s cn61xx; - struct cvmx_sli_msi_w1s_enb0_s cn63xx; - struct cvmx_sli_msi_w1s_enb0_s cn63xxp1; - struct cvmx_sli_msi_w1s_enb0_s cn66xx; - struct cvmx_sli_msi_w1s_enb0_s cn68xx; - struct cvmx_sli_msi_w1s_enb0_s cn68xxp1; - struct cvmx_sli_msi_w1s_enb0_s cnf71xx; -}; - -union cvmx_sli_msi_w1s_enb1 { - uint64_t u64; - struct cvmx_sli_msi_w1s_enb1_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t set:64; -#else - uint64_t set:64; -#endif - } s; - struct cvmx_sli_msi_w1s_enb1_s cn61xx; - struct cvmx_sli_msi_w1s_enb1_s cn63xx; - struct cvmx_sli_msi_w1s_enb1_s cn63xxp1; - struct cvmx_sli_msi_w1s_enb1_s cn66xx; - struct cvmx_sli_msi_w1s_enb1_s cn68xx; - struct cvmx_sli_msi_w1s_enb1_s cn68xxp1; - struct cvmx_sli_msi_w1s_enb1_s cnf71xx; -}; - -union cvmx_sli_msi_w1s_enb2 { - uint64_t u64; - struct cvmx_sli_msi_w1s_enb2_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t set:64; -#else - uint64_t set:64; -#endif - } s; - struct cvmx_sli_msi_w1s_enb2_s cn61xx; - struct cvmx_sli_msi_w1s_enb2_s cn63xx; - struct cvmx_sli_msi_w1s_enb2_s cn63xxp1; - struct cvmx_sli_msi_w1s_enb2_s cn66xx; - struct cvmx_sli_msi_w1s_enb2_s cn68xx; - struct cvmx_sli_msi_w1s_enb2_s cn68xxp1; - struct cvmx_sli_msi_w1s_enb2_s cnf71xx; -}; - -union cvmx_sli_msi_w1s_enb3 { - uint64_t u64; - struct cvmx_sli_msi_w1s_enb3_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t set:64; -#else - uint64_t set:64; -#endif - } s; - struct cvmx_sli_msi_w1s_enb3_s cn61xx; - struct cvmx_sli_msi_w1s_enb3_s cn63xx; - struct cvmx_sli_msi_w1s_enb3_s cn63xxp1; - struct cvmx_sli_msi_w1s_enb3_s cn66xx; - struct cvmx_sli_msi_w1s_enb3_s cn68xx; - struct cvmx_sli_msi_w1s_enb3_s cn68xxp1; - struct cvmx_sli_msi_w1s_enb3_s cnf71xx; -}; - -union cvmx_sli_msi_wr_map { - uint64_t u64; - struct cvmx_sli_msi_wr_map_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_16_63:48; - uint64_t ciu_int:8; - uint64_t msi_int:8; -#else - uint64_t msi_int:8; - uint64_t ciu_int:8; - uint64_t reserved_16_63:48; -#endif - } s; - struct cvmx_sli_msi_wr_map_s cn61xx; - struct cvmx_sli_msi_wr_map_s cn63xx; - struct cvmx_sli_msi_wr_map_s cn63xxp1; - struct cvmx_sli_msi_wr_map_s cn66xx; - struct cvmx_sli_msi_wr_map_s cn68xx; - struct cvmx_sli_msi_wr_map_s cn68xxp1; - struct cvmx_sli_msi_wr_map_s cnf71xx; -}; - -union cvmx_sli_pcie_msi_rcv { - uint64_t u64; - struct cvmx_sli_pcie_msi_rcv_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_8_63:56; - uint64_t intr:8; -#else - uint64_t intr:8; - uint64_t reserved_8_63:56; -#endif - } s; - struct cvmx_sli_pcie_msi_rcv_s cn61xx; - struct cvmx_sli_pcie_msi_rcv_s cn63xx; - struct cvmx_sli_pcie_msi_rcv_s cn63xxp1; - struct cvmx_sli_pcie_msi_rcv_s cn66xx; - struct cvmx_sli_pcie_msi_rcv_s cn68xx; - struct cvmx_sli_pcie_msi_rcv_s cn68xxp1; - struct cvmx_sli_pcie_msi_rcv_s cnf71xx; -}; - -union cvmx_sli_pcie_msi_rcv_b1 { - uint64_t u64; - struct cvmx_sli_pcie_msi_rcv_b1_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_16_63:48; - uint64_t intr:8; - uint64_t reserved_0_7:8; -#else - uint64_t reserved_0_7:8; - uint64_t intr:8; - uint64_t reserved_16_63:48; -#endif - } s; - struct cvmx_sli_pcie_msi_rcv_b1_s cn61xx; - struct cvmx_sli_pcie_msi_rcv_b1_s cn63xx; - struct cvmx_sli_pcie_msi_rcv_b1_s cn63xxp1; - struct cvmx_sli_pcie_msi_rcv_b1_s cn66xx; - struct cvmx_sli_pcie_msi_rcv_b1_s cn68xx; - struct cvmx_sli_pcie_msi_rcv_b1_s cn68xxp1; - struct cvmx_sli_pcie_msi_rcv_b1_s cnf71xx; -}; - -union cvmx_sli_pcie_msi_rcv_b2 { - uint64_t u64; - struct cvmx_sli_pcie_msi_rcv_b2_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_24_63:40; - uint64_t intr:8; - uint64_t reserved_0_15:16; -#else - uint64_t reserved_0_15:16; - uint64_t intr:8; - uint64_t reserved_24_63:40; -#endif - } s; - struct cvmx_sli_pcie_msi_rcv_b2_s cn61xx; - struct cvmx_sli_pcie_msi_rcv_b2_s cn63xx; - struct cvmx_sli_pcie_msi_rcv_b2_s cn63xxp1; - struct cvmx_sli_pcie_msi_rcv_b2_s cn66xx; - struct cvmx_sli_pcie_msi_rcv_b2_s cn68xx; - struct cvmx_sli_pcie_msi_rcv_b2_s cn68xxp1; - struct cvmx_sli_pcie_msi_rcv_b2_s cnf71xx; -}; - -union cvmx_sli_pcie_msi_rcv_b3 { - uint64_t u64; - struct cvmx_sli_pcie_msi_rcv_b3_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t intr:8; - uint64_t reserved_0_23:24; -#else - uint64_t reserved_0_23:24; - uint64_t intr:8; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_sli_pcie_msi_rcv_b3_s cn61xx; - struct cvmx_sli_pcie_msi_rcv_b3_s cn63xx; - struct cvmx_sli_pcie_msi_rcv_b3_s cn63xxp1; - struct cvmx_sli_pcie_msi_rcv_b3_s cn66xx; - struct cvmx_sli_pcie_msi_rcv_b3_s cn68xx; - struct cvmx_sli_pcie_msi_rcv_b3_s cn68xxp1; - struct cvmx_sli_pcie_msi_rcv_b3_s cnf71xx; -}; - -union cvmx_sli_pktx_cnts { - uint64_t u64; - struct cvmx_sli_pktx_cnts_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_54_63:10; - uint64_t timer:22; - uint64_t cnt:32; -#else - uint64_t cnt:32; - uint64_t timer:22; - uint64_t reserved_54_63:10; -#endif - } s; - struct cvmx_sli_pktx_cnts_s cn61xx; - struct cvmx_sli_pktx_cnts_s cn63xx; - struct cvmx_sli_pktx_cnts_s cn63xxp1; - struct cvmx_sli_pktx_cnts_s cn66xx; - struct cvmx_sli_pktx_cnts_s cn68xx; - struct cvmx_sli_pktx_cnts_s cn68xxp1; - struct cvmx_sli_pktx_cnts_s cnf71xx; -}; - -union cvmx_sli_pktx_in_bp { - uint64_t u64; - struct cvmx_sli_pktx_in_bp_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t wmark:32; - uint64_t cnt:32; -#else - uint64_t cnt:32; - uint64_t wmark:32; -#endif - } s; - struct cvmx_sli_pktx_in_bp_s cn61xx; - struct cvmx_sli_pktx_in_bp_s cn63xx; - struct cvmx_sli_pktx_in_bp_s cn63xxp1; - struct cvmx_sli_pktx_in_bp_s cn66xx; - struct cvmx_sli_pktx_in_bp_s cnf71xx; -}; - -union cvmx_sli_pktx_instr_baddr { - uint64_t u64; - struct cvmx_sli_pktx_instr_baddr_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t addr:61; - uint64_t reserved_0_2:3; -#else - uint64_t reserved_0_2:3; - uint64_t addr:61; -#endif + __BITFIELD_FIELD(uint64_t reserved_14_63:50, + __BITFIELD_FIELD(uint64_t max_word:4, + __BITFIELD_FIELD(uint64_t timer:10, + ;))) } s; - struct cvmx_sli_pktx_instr_baddr_s cn61xx; - struct cvmx_sli_pktx_instr_baddr_s cn63xx; - struct cvmx_sli_pktx_instr_baddr_s cn63xxp1; - struct cvmx_sli_pktx_instr_baddr_s cn66xx; - struct cvmx_sli_pktx_instr_baddr_s cn68xx; - struct cvmx_sli_pktx_instr_baddr_s cn68xxp1; - struct cvmx_sli_pktx_instr_baddr_s cnf71xx; -}; - -union cvmx_sli_pktx_instr_baoff_dbell { - uint64_t u64; - struct cvmx_sli_pktx_instr_baoff_dbell_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t aoff:32; - uint64_t dbell:32; -#else - uint64_t dbell:32; - uint64_t aoff:32; -#endif - } s; - struct cvmx_sli_pktx_instr_baoff_dbell_s cn61xx; - struct cvmx_sli_pktx_instr_baoff_dbell_s cn63xx; - struct cvmx_sli_pktx_instr_baoff_dbell_s cn63xxp1; - struct cvmx_sli_pktx_instr_baoff_dbell_s cn66xx; - struct cvmx_sli_pktx_instr_baoff_dbell_s cn68xx; - struct cvmx_sli_pktx_instr_baoff_dbell_s cn68xxp1; - struct cvmx_sli_pktx_instr_baoff_dbell_s cnf71xx; -}; - -union cvmx_sli_pktx_instr_fifo_rsize { - uint64_t u64; - struct cvmx_sli_pktx_instr_fifo_rsize_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t max:9; - uint64_t rrp:9; - uint64_t wrp:9; - uint64_t fcnt:5; - uint64_t rsize:32; -#else - uint64_t rsize:32; - uint64_t fcnt:5; - uint64_t wrp:9; - uint64_t rrp:9; - uint64_t max:9; -#endif - } s; - struct cvmx_sli_pktx_instr_fifo_rsize_s cn61xx; - struct cvmx_sli_pktx_instr_fifo_rsize_s cn63xx; - struct cvmx_sli_pktx_instr_fifo_rsize_s cn63xxp1; - struct cvmx_sli_pktx_instr_fifo_rsize_s cn66xx; - struct cvmx_sli_pktx_instr_fifo_rsize_s cn68xx; - struct cvmx_sli_pktx_instr_fifo_rsize_s cn68xxp1; - struct cvmx_sli_pktx_instr_fifo_rsize_s cnf71xx; -}; - -union cvmx_sli_pktx_instr_header { - uint64_t u64; - struct cvmx_sli_pktx_instr_header_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_44_63:20; - uint64_t pbp:1; - uint64_t reserved_38_42:5; - uint64_t rparmode:2; - uint64_t reserved_35_35:1; - uint64_t rskp_len:7; - uint64_t rngrpext:2; - uint64_t rnqos:1; - uint64_t rngrp:1; - uint64_t rntt:1; - uint64_t rntag:1; - uint64_t use_ihdr:1; - uint64_t reserved_16_20:5; - uint64_t par_mode:2; - uint64_t reserved_13_13:1; - uint64_t skp_len:7; - uint64_t ngrpext:2; - uint64_t nqos:1; - uint64_t ngrp:1; - uint64_t ntt:1; - uint64_t ntag:1; -#else - uint64_t ntag:1; - uint64_t ntt:1; - uint64_t ngrp:1; - uint64_t nqos:1; - uint64_t ngrpext:2; - uint64_t skp_len:7; - uint64_t reserved_13_13:1; - uint64_t par_mode:2; - uint64_t reserved_16_20:5; - uint64_t use_ihdr:1; - uint64_t rntag:1; - uint64_t rntt:1; - uint64_t rngrp:1; - uint64_t rnqos:1; - uint64_t rngrpext:2; - uint64_t rskp_len:7; - uint64_t reserved_35_35:1; - uint64_t rparmode:2; - uint64_t reserved_38_42:5; - uint64_t pbp:1; - uint64_t reserved_44_63:20; -#endif - } s; - struct cvmx_sli_pktx_instr_header_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_44_63:20; - uint64_t pbp:1; - uint64_t reserved_38_42:5; - uint64_t rparmode:2; - uint64_t reserved_35_35:1; - uint64_t rskp_len:7; - uint64_t reserved_26_27:2; - uint64_t rnqos:1; - uint64_t rngrp:1; - uint64_t rntt:1; - uint64_t rntag:1; - uint64_t use_ihdr:1; - uint64_t reserved_16_20:5; - uint64_t par_mode:2; - uint64_t reserved_13_13:1; - uint64_t skp_len:7; - uint64_t reserved_4_5:2; - uint64_t nqos:1; - uint64_t ngrp:1; - uint64_t ntt:1; - uint64_t ntag:1; -#else - uint64_t ntag:1; - uint64_t ntt:1; - uint64_t ngrp:1; - uint64_t nqos:1; - uint64_t reserved_4_5:2; - uint64_t skp_len:7; - uint64_t reserved_13_13:1; - uint64_t par_mode:2; - uint64_t reserved_16_20:5; - uint64_t use_ihdr:1; - uint64_t rntag:1; - uint64_t rntt:1; - uint64_t rngrp:1; - uint64_t rnqos:1; - uint64_t reserved_26_27:2; - uint64_t rskp_len:7; - uint64_t reserved_35_35:1; - uint64_t rparmode:2; - uint64_t reserved_38_42:5; - uint64_t pbp:1; - uint64_t reserved_44_63:20; -#endif - } cn61xx; - struct cvmx_sli_pktx_instr_header_cn61xx cn63xx; - struct cvmx_sli_pktx_instr_header_cn61xx cn63xxp1; - struct cvmx_sli_pktx_instr_header_cn61xx cn66xx; - struct cvmx_sli_pktx_instr_header_s cn68xx; - struct cvmx_sli_pktx_instr_header_cn61xx cn68xxp1; - struct cvmx_sli_pktx_instr_header_cn61xx cnf71xx; -}; - -union cvmx_sli_pktx_out_size { - uint64_t u64; - struct cvmx_sli_pktx_out_size_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_23_63:41; - uint64_t isize:7; - uint64_t bsize:16; -#else - uint64_t bsize:16; - uint64_t isize:7; - uint64_t reserved_23_63:41; -#endif - } s; - struct cvmx_sli_pktx_out_size_s cn61xx; - struct cvmx_sli_pktx_out_size_s cn63xx; - struct cvmx_sli_pktx_out_size_s cn63xxp1; - struct cvmx_sli_pktx_out_size_s cn66xx; - struct cvmx_sli_pktx_out_size_s cn68xx; - struct cvmx_sli_pktx_out_size_s cn68xxp1; - struct cvmx_sli_pktx_out_size_s cnf71xx; -}; - -union cvmx_sli_pktx_slist_baddr { - uint64_t u64; - struct cvmx_sli_pktx_slist_baddr_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t addr:60; - uint64_t reserved_0_3:4; -#else - uint64_t reserved_0_3:4; - uint64_t addr:60; -#endif - } s; - struct cvmx_sli_pktx_slist_baddr_s cn61xx; - struct cvmx_sli_pktx_slist_baddr_s cn63xx; - struct cvmx_sli_pktx_slist_baddr_s cn63xxp1; - struct cvmx_sli_pktx_slist_baddr_s cn66xx; - struct cvmx_sli_pktx_slist_baddr_s cn68xx; - struct cvmx_sli_pktx_slist_baddr_s cn68xxp1; - struct cvmx_sli_pktx_slist_baddr_s cnf71xx; -}; - -union cvmx_sli_pktx_slist_baoff_dbell { - uint64_t u64; - struct cvmx_sli_pktx_slist_baoff_dbell_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t aoff:32; - uint64_t dbell:32; -#else - uint64_t dbell:32; - uint64_t aoff:32; -#endif - } s; - struct cvmx_sli_pktx_slist_baoff_dbell_s cn61xx; - struct cvmx_sli_pktx_slist_baoff_dbell_s cn63xx; - struct cvmx_sli_pktx_slist_baoff_dbell_s cn63xxp1; - struct cvmx_sli_pktx_slist_baoff_dbell_s cn66xx; - struct cvmx_sli_pktx_slist_baoff_dbell_s cn68xx; - struct cvmx_sli_pktx_slist_baoff_dbell_s cn68xxp1; - struct cvmx_sli_pktx_slist_baoff_dbell_s cnf71xx; -}; - -union cvmx_sli_pktx_slist_fifo_rsize { - uint64_t u64; - struct cvmx_sli_pktx_slist_fifo_rsize_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t rsize:32; -#else - uint64_t rsize:32; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_sli_pktx_slist_fifo_rsize_s cn61xx; - struct cvmx_sli_pktx_slist_fifo_rsize_s cn63xx; - struct cvmx_sli_pktx_slist_fifo_rsize_s cn63xxp1; - struct cvmx_sli_pktx_slist_fifo_rsize_s cn66xx; - struct cvmx_sli_pktx_slist_fifo_rsize_s cn68xx; - struct cvmx_sli_pktx_slist_fifo_rsize_s cn68xxp1; - struct cvmx_sli_pktx_slist_fifo_rsize_s cnf71xx; -}; - -union cvmx_sli_pkt_cnt_int { - uint64_t u64; - struct cvmx_sli_pkt_cnt_int_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t port:32; -#else - uint64_t port:32; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_sli_pkt_cnt_int_s cn61xx; - struct cvmx_sli_pkt_cnt_int_s cn63xx; - struct cvmx_sli_pkt_cnt_int_s cn63xxp1; - struct cvmx_sli_pkt_cnt_int_s cn66xx; - struct cvmx_sli_pkt_cnt_int_s cn68xx; - struct cvmx_sli_pkt_cnt_int_s cn68xxp1; - struct cvmx_sli_pkt_cnt_int_s cnf71xx; -}; - -union cvmx_sli_pkt_cnt_int_enb { - uint64_t u64; - struct cvmx_sli_pkt_cnt_int_enb_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t port:32; -#else - uint64_t port:32; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_sli_pkt_cnt_int_enb_s cn61xx; - struct cvmx_sli_pkt_cnt_int_enb_s cn63xx; - struct cvmx_sli_pkt_cnt_int_enb_s cn63xxp1; - struct cvmx_sli_pkt_cnt_int_enb_s cn66xx; - struct cvmx_sli_pkt_cnt_int_enb_s cn68xx; - struct cvmx_sli_pkt_cnt_int_enb_s cn68xxp1; - struct cvmx_sli_pkt_cnt_int_enb_s cnf71xx; -}; - -union cvmx_sli_pkt_ctl { - uint64_t u64; - struct cvmx_sli_pkt_ctl_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_5_63:59; - uint64_t ring_en:1; - uint64_t pkt_bp:4; -#else - uint64_t pkt_bp:4; - uint64_t ring_en:1; - uint64_t reserved_5_63:59; -#endif - } s; - struct cvmx_sli_pkt_ctl_s cn61xx; - struct cvmx_sli_pkt_ctl_s cn63xx; - struct cvmx_sli_pkt_ctl_s cn63xxp1; - struct cvmx_sli_pkt_ctl_s cn66xx; - struct cvmx_sli_pkt_ctl_s cn68xx; - struct cvmx_sli_pkt_ctl_s cn68xxp1; - struct cvmx_sli_pkt_ctl_s cnf71xx; -}; - -union cvmx_sli_pkt_data_out_es { - uint64_t u64; - struct cvmx_sli_pkt_data_out_es_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t es:64; -#else - uint64_t es:64; -#endif - } s; - struct cvmx_sli_pkt_data_out_es_s cn61xx; - struct cvmx_sli_pkt_data_out_es_s cn63xx; - struct cvmx_sli_pkt_data_out_es_s cn63xxp1; - struct cvmx_sli_pkt_data_out_es_s cn66xx; - struct cvmx_sli_pkt_data_out_es_s cn68xx; - struct cvmx_sli_pkt_data_out_es_s cn68xxp1; - struct cvmx_sli_pkt_data_out_es_s cnf71xx; -}; - -union cvmx_sli_pkt_data_out_ns { - uint64_t u64; - struct cvmx_sli_pkt_data_out_ns_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t nsr:32; -#else - uint64_t nsr:32; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_sli_pkt_data_out_ns_s cn61xx; - struct cvmx_sli_pkt_data_out_ns_s cn63xx; - struct cvmx_sli_pkt_data_out_ns_s cn63xxp1; - struct cvmx_sli_pkt_data_out_ns_s cn66xx; - struct cvmx_sli_pkt_data_out_ns_s cn68xx; - struct cvmx_sli_pkt_data_out_ns_s cn68xxp1; - struct cvmx_sli_pkt_data_out_ns_s cnf71xx; -}; - -union cvmx_sli_pkt_data_out_ror { - uint64_t u64; - struct cvmx_sli_pkt_data_out_ror_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t ror:32; -#else - uint64_t ror:32; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_sli_pkt_data_out_ror_s cn61xx; - struct cvmx_sli_pkt_data_out_ror_s cn63xx; - struct cvmx_sli_pkt_data_out_ror_s cn63xxp1; - struct cvmx_sli_pkt_data_out_ror_s cn66xx; - struct cvmx_sli_pkt_data_out_ror_s cn68xx; - struct cvmx_sli_pkt_data_out_ror_s cn68xxp1; - struct cvmx_sli_pkt_data_out_ror_s cnf71xx; -}; - -union cvmx_sli_pkt_dpaddr { - uint64_t u64; - struct cvmx_sli_pkt_dpaddr_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t dptr:32; -#else - uint64_t dptr:32; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_sli_pkt_dpaddr_s cn61xx; - struct cvmx_sli_pkt_dpaddr_s cn63xx; - struct cvmx_sli_pkt_dpaddr_s cn63xxp1; - struct cvmx_sli_pkt_dpaddr_s cn66xx; - struct cvmx_sli_pkt_dpaddr_s cn68xx; - struct cvmx_sli_pkt_dpaddr_s cn68xxp1; - struct cvmx_sli_pkt_dpaddr_s cnf71xx; -}; - -union cvmx_sli_pkt_in_bp { - uint64_t u64; - struct cvmx_sli_pkt_in_bp_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t bp:32; -#else - uint64_t bp:32; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_sli_pkt_in_bp_s cn61xx; - struct cvmx_sli_pkt_in_bp_s cn63xx; - struct cvmx_sli_pkt_in_bp_s cn63xxp1; - struct cvmx_sli_pkt_in_bp_s cn66xx; - struct cvmx_sli_pkt_in_bp_s cnf71xx; -}; - -union cvmx_sli_pkt_in_donex_cnts { - uint64_t u64; - struct cvmx_sli_pkt_in_donex_cnts_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t cnt:32; -#else - uint64_t cnt:32; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_sli_pkt_in_donex_cnts_s cn61xx; - struct cvmx_sli_pkt_in_donex_cnts_s cn63xx; - struct cvmx_sli_pkt_in_donex_cnts_s cn63xxp1; - struct cvmx_sli_pkt_in_donex_cnts_s cn66xx; - struct cvmx_sli_pkt_in_donex_cnts_s cn68xx; - struct cvmx_sli_pkt_in_donex_cnts_s cn68xxp1; - struct cvmx_sli_pkt_in_donex_cnts_s cnf71xx; -}; - -union cvmx_sli_pkt_in_instr_counts { - uint64_t u64; - struct cvmx_sli_pkt_in_instr_counts_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t wr_cnt:32; - uint64_t rd_cnt:32; -#else - uint64_t rd_cnt:32; - uint64_t wr_cnt:32; -#endif - } s; - struct cvmx_sli_pkt_in_instr_counts_s cn61xx; - struct cvmx_sli_pkt_in_instr_counts_s cn63xx; - struct cvmx_sli_pkt_in_instr_counts_s cn63xxp1; - struct cvmx_sli_pkt_in_instr_counts_s cn66xx; - struct cvmx_sli_pkt_in_instr_counts_s cn68xx; - struct cvmx_sli_pkt_in_instr_counts_s cn68xxp1; - struct cvmx_sli_pkt_in_instr_counts_s cnf71xx; -}; - -union cvmx_sli_pkt_in_pcie_port { - uint64_t u64; - struct cvmx_sli_pkt_in_pcie_port_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t pp:64; -#else - uint64_t pp:64; -#endif - } s; - struct cvmx_sli_pkt_in_pcie_port_s cn61xx; - struct cvmx_sli_pkt_in_pcie_port_s cn63xx; - struct cvmx_sli_pkt_in_pcie_port_s cn63xxp1; - struct cvmx_sli_pkt_in_pcie_port_s cn66xx; - struct cvmx_sli_pkt_in_pcie_port_s cn68xx; - struct cvmx_sli_pkt_in_pcie_port_s cn68xxp1; - struct cvmx_sli_pkt_in_pcie_port_s cnf71xx; -}; - -union cvmx_sli_pkt_input_control { - uint64_t u64; - struct cvmx_sli_pkt_input_control_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t prd_erst:1; - uint64_t prd_rds:7; - uint64_t gii_erst:1; - uint64_t gii_rds:7; - uint64_t reserved_41_47:7; - uint64_t prc_idle:1; - uint64_t reserved_24_39:16; - uint64_t pin_rst:1; - uint64_t pkt_rr:1; - uint64_t pbp_dhi:13; - uint64_t d_nsr:1; - uint64_t d_esr:2; - uint64_t d_ror:1; - uint64_t use_csr:1; - uint64_t nsr:1; - uint64_t esr:2; - uint64_t ror:1; -#else - uint64_t ror:1; - uint64_t esr:2; - uint64_t nsr:1; - uint64_t use_csr:1; - uint64_t d_ror:1; - uint64_t d_esr:2; - uint64_t d_nsr:1; - uint64_t pbp_dhi:13; - uint64_t pkt_rr:1; - uint64_t pin_rst:1; - uint64_t reserved_24_39:16; - uint64_t prc_idle:1; - uint64_t reserved_41_47:7; - uint64_t gii_rds:7; - uint64_t gii_erst:1; - uint64_t prd_rds:7; - uint64_t prd_erst:1; -#endif - } s; - struct cvmx_sli_pkt_input_control_s cn61xx; - struct cvmx_sli_pkt_input_control_cn63xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_23_63:41; - uint64_t pkt_rr:1; - uint64_t pbp_dhi:13; - uint64_t d_nsr:1; - uint64_t d_esr:2; - uint64_t d_ror:1; - uint64_t use_csr:1; - uint64_t nsr:1; - uint64_t esr:2; - uint64_t ror:1; -#else - uint64_t ror:1; - uint64_t esr:2; - uint64_t nsr:1; - uint64_t use_csr:1; - uint64_t d_ror:1; - uint64_t d_esr:2; - uint64_t d_nsr:1; - uint64_t pbp_dhi:13; - uint64_t pkt_rr:1; - uint64_t reserved_23_63:41; -#endif - } cn63xx; - struct cvmx_sli_pkt_input_control_cn63xx cn63xxp1; - struct cvmx_sli_pkt_input_control_s cn66xx; - struct cvmx_sli_pkt_input_control_s cn68xx; - struct cvmx_sli_pkt_input_control_s cn68xxp1; - struct cvmx_sli_pkt_input_control_s cnf71xx; -}; - -union cvmx_sli_pkt_instr_enb { - uint64_t u64; - struct cvmx_sli_pkt_instr_enb_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t enb:32; -#else - uint64_t enb:32; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_sli_pkt_instr_enb_s cn61xx; - struct cvmx_sli_pkt_instr_enb_s cn63xx; - struct cvmx_sli_pkt_instr_enb_s cn63xxp1; - struct cvmx_sli_pkt_instr_enb_s cn66xx; - struct cvmx_sli_pkt_instr_enb_s cn68xx; - struct cvmx_sli_pkt_instr_enb_s cn68xxp1; - struct cvmx_sli_pkt_instr_enb_s cnf71xx; -}; - -union cvmx_sli_pkt_instr_rd_size { - uint64_t u64; - struct cvmx_sli_pkt_instr_rd_size_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t rdsize:64; -#else - uint64_t rdsize:64; -#endif - } s; - struct cvmx_sli_pkt_instr_rd_size_s cn61xx; - struct cvmx_sli_pkt_instr_rd_size_s cn63xx; - struct cvmx_sli_pkt_instr_rd_size_s cn63xxp1; - struct cvmx_sli_pkt_instr_rd_size_s cn66xx; - struct cvmx_sli_pkt_instr_rd_size_s cn68xx; - struct cvmx_sli_pkt_instr_rd_size_s cn68xxp1; - struct cvmx_sli_pkt_instr_rd_size_s cnf71xx; -}; - -union cvmx_sli_pkt_instr_size { - uint64_t u64; - struct cvmx_sli_pkt_instr_size_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t is_64b:32; -#else - uint64_t is_64b:32; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_sli_pkt_instr_size_s cn61xx; - struct cvmx_sli_pkt_instr_size_s cn63xx; - struct cvmx_sli_pkt_instr_size_s cn63xxp1; - struct cvmx_sli_pkt_instr_size_s cn66xx; - struct cvmx_sli_pkt_instr_size_s cn68xx; - struct cvmx_sli_pkt_instr_size_s cn68xxp1; - struct cvmx_sli_pkt_instr_size_s cnf71xx; -}; - -union cvmx_sli_pkt_int_levels { - uint64_t u64; - struct cvmx_sli_pkt_int_levels_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_54_63:10; - uint64_t time:22; - uint64_t cnt:32; -#else - uint64_t cnt:32; - uint64_t time:22; - uint64_t reserved_54_63:10; -#endif - } s; - struct cvmx_sli_pkt_int_levels_s cn61xx; - struct cvmx_sli_pkt_int_levels_s cn63xx; - struct cvmx_sli_pkt_int_levels_s cn63xxp1; - struct cvmx_sli_pkt_int_levels_s cn66xx; - struct cvmx_sli_pkt_int_levels_s cn68xx; - struct cvmx_sli_pkt_int_levels_s cn68xxp1; - struct cvmx_sli_pkt_int_levels_s cnf71xx; -}; - -union cvmx_sli_pkt_iptr { - uint64_t u64; - struct cvmx_sli_pkt_iptr_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t iptr:32; -#else - uint64_t iptr:32; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_sli_pkt_iptr_s cn61xx; - struct cvmx_sli_pkt_iptr_s cn63xx; - struct cvmx_sli_pkt_iptr_s cn63xxp1; - struct cvmx_sli_pkt_iptr_s cn66xx; - struct cvmx_sli_pkt_iptr_s cn68xx; - struct cvmx_sli_pkt_iptr_s cn68xxp1; - struct cvmx_sli_pkt_iptr_s cnf71xx; -}; - -union cvmx_sli_pkt_out_bmode { - uint64_t u64; - struct cvmx_sli_pkt_out_bmode_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t bmode:32; -#else - uint64_t bmode:32; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_sli_pkt_out_bmode_s cn61xx; - struct cvmx_sli_pkt_out_bmode_s cn63xx; - struct cvmx_sli_pkt_out_bmode_s cn63xxp1; - struct cvmx_sli_pkt_out_bmode_s cn66xx; - struct cvmx_sli_pkt_out_bmode_s cn68xx; - struct cvmx_sli_pkt_out_bmode_s cn68xxp1; - struct cvmx_sli_pkt_out_bmode_s cnf71xx; -}; - -union cvmx_sli_pkt_out_bp_en { - uint64_t u64; - struct cvmx_sli_pkt_out_bp_en_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t bp_en:32; -#else - uint64_t bp_en:32; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_sli_pkt_out_bp_en_s cn68xx; - struct cvmx_sli_pkt_out_bp_en_s cn68xxp1; -}; - -union cvmx_sli_pkt_out_enb { - uint64_t u64; - struct cvmx_sli_pkt_out_enb_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t enb:32; -#else - uint64_t enb:32; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_sli_pkt_out_enb_s cn61xx; - struct cvmx_sli_pkt_out_enb_s cn63xx; - struct cvmx_sli_pkt_out_enb_s cn63xxp1; - struct cvmx_sli_pkt_out_enb_s cn66xx; - struct cvmx_sli_pkt_out_enb_s cn68xx; - struct cvmx_sli_pkt_out_enb_s cn68xxp1; - struct cvmx_sli_pkt_out_enb_s cnf71xx; -}; - -union cvmx_sli_pkt_output_wmark { - uint64_t u64; - struct cvmx_sli_pkt_output_wmark_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t wmark:32; -#else - uint64_t wmark:32; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_sli_pkt_output_wmark_s cn61xx; - struct cvmx_sli_pkt_output_wmark_s cn63xx; - struct cvmx_sli_pkt_output_wmark_s cn63xxp1; - struct cvmx_sli_pkt_output_wmark_s cn66xx; - struct cvmx_sli_pkt_output_wmark_s cn68xx; - struct cvmx_sli_pkt_output_wmark_s cn68xxp1; - struct cvmx_sli_pkt_output_wmark_s cnf71xx; -}; - -union cvmx_sli_pkt_pcie_port { - uint64_t u64; - struct cvmx_sli_pkt_pcie_port_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t pp:64; -#else - uint64_t pp:64; -#endif - } s; - struct cvmx_sli_pkt_pcie_port_s cn61xx; - struct cvmx_sli_pkt_pcie_port_s cn63xx; - struct cvmx_sli_pkt_pcie_port_s cn63xxp1; - struct cvmx_sli_pkt_pcie_port_s cn66xx; - struct cvmx_sli_pkt_pcie_port_s cn68xx; - struct cvmx_sli_pkt_pcie_port_s cn68xxp1; - struct cvmx_sli_pkt_pcie_port_s cnf71xx; -}; - -union cvmx_sli_pkt_port_in_rst { - uint64_t u64; - struct cvmx_sli_pkt_port_in_rst_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t in_rst:32; - uint64_t out_rst:32; -#else - uint64_t out_rst:32; - uint64_t in_rst:32; -#endif - } s; - struct cvmx_sli_pkt_port_in_rst_s cn61xx; - struct cvmx_sli_pkt_port_in_rst_s cn63xx; - struct cvmx_sli_pkt_port_in_rst_s cn63xxp1; - struct cvmx_sli_pkt_port_in_rst_s cn66xx; - struct cvmx_sli_pkt_port_in_rst_s cn68xx; - struct cvmx_sli_pkt_port_in_rst_s cn68xxp1; - struct cvmx_sli_pkt_port_in_rst_s cnf71xx; -}; - -union cvmx_sli_pkt_slist_es { - uint64_t u64; - struct cvmx_sli_pkt_slist_es_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t es:64; -#else - uint64_t es:64; -#endif - } s; - struct cvmx_sli_pkt_slist_es_s cn61xx; - struct cvmx_sli_pkt_slist_es_s cn63xx; - struct cvmx_sli_pkt_slist_es_s cn63xxp1; - struct cvmx_sli_pkt_slist_es_s cn66xx; - struct cvmx_sli_pkt_slist_es_s cn68xx; - struct cvmx_sli_pkt_slist_es_s cn68xxp1; - struct cvmx_sli_pkt_slist_es_s cnf71xx; -}; - -union cvmx_sli_pkt_slist_ns { - uint64_t u64; - struct cvmx_sli_pkt_slist_ns_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t nsr:32; -#else - uint64_t nsr:32; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_sli_pkt_slist_ns_s cn61xx; - struct cvmx_sli_pkt_slist_ns_s cn63xx; - struct cvmx_sli_pkt_slist_ns_s cn63xxp1; - struct cvmx_sli_pkt_slist_ns_s cn66xx; - struct cvmx_sli_pkt_slist_ns_s cn68xx; - struct cvmx_sli_pkt_slist_ns_s cn68xxp1; - struct cvmx_sli_pkt_slist_ns_s cnf71xx; -}; - -union cvmx_sli_pkt_slist_ror { - uint64_t u64; - struct cvmx_sli_pkt_slist_ror_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t ror:32; -#else - uint64_t ror:32; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_sli_pkt_slist_ror_s cn61xx; - struct cvmx_sli_pkt_slist_ror_s cn63xx; - struct cvmx_sli_pkt_slist_ror_s cn63xxp1; - struct cvmx_sli_pkt_slist_ror_s cn66xx; - struct cvmx_sli_pkt_slist_ror_s cn68xx; - struct cvmx_sli_pkt_slist_ror_s cn68xxp1; - struct cvmx_sli_pkt_slist_ror_s cnf71xx; -}; - -union cvmx_sli_pkt_time_int { - uint64_t u64; - struct cvmx_sli_pkt_time_int_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t port:32; -#else - uint64_t port:32; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_sli_pkt_time_int_s cn61xx; - struct cvmx_sli_pkt_time_int_s cn63xx; - struct cvmx_sli_pkt_time_int_s cn63xxp1; - struct cvmx_sli_pkt_time_int_s cn66xx; - struct cvmx_sli_pkt_time_int_s cn68xx; - struct cvmx_sli_pkt_time_int_s cn68xxp1; - struct cvmx_sli_pkt_time_int_s cnf71xx; -}; - -union cvmx_sli_pkt_time_int_enb { - uint64_t u64; - struct cvmx_sli_pkt_time_int_enb_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t port:32; -#else - uint64_t port:32; - uint64_t reserved_32_63:32; -#endif - } s; - struct cvmx_sli_pkt_time_int_enb_s cn61xx; - struct cvmx_sli_pkt_time_int_enb_s cn63xx; - struct cvmx_sli_pkt_time_int_enb_s cn63xxp1; - struct cvmx_sli_pkt_time_int_enb_s cn66xx; - struct cvmx_sli_pkt_time_int_enb_s cn68xx; - struct cvmx_sli_pkt_time_int_enb_s cn68xxp1; - struct cvmx_sli_pkt_time_int_enb_s cnf71xx; -}; - -union cvmx_sli_portx_pkind { - uint64_t u64; - struct cvmx_sli_portx_pkind_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_25_63:39; - uint64_t rpk_enb:1; - uint64_t reserved_22_23:2; - uint64_t pkindr:6; - uint64_t reserved_14_15:2; - uint64_t bpkind:6; - uint64_t reserved_6_7:2; - uint64_t pkind:6; -#else - uint64_t pkind:6; - uint64_t reserved_6_7:2; - uint64_t bpkind:6; - uint64_t reserved_14_15:2; - uint64_t pkindr:6; - uint64_t reserved_22_23:2; - uint64_t rpk_enb:1; - uint64_t reserved_25_63:39; -#endif - } s; - struct cvmx_sli_portx_pkind_s cn68xx; - struct cvmx_sli_portx_pkind_cn68xxp1 { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_14_63:50; - uint64_t bpkind:6; - uint64_t reserved_6_7:2; - uint64_t pkind:6; -#else - uint64_t pkind:6; - uint64_t reserved_6_7:2; - uint64_t bpkind:6; - uint64_t reserved_14_63:50; -#endif - } cn68xxp1; }; union cvmx_sli_s2m_portx_ctl { uint64_t u64; struct cvmx_sli_s2m_portx_ctl_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_5_63:59; - uint64_t wind_d:1; - uint64_t bar0_d:1; - uint64_t mrrs:3; -#else - uint64_t mrrs:3; - uint64_t bar0_d:1; - uint64_t wind_d:1; - uint64_t reserved_5_63:59; -#endif - } s; - struct cvmx_sli_s2m_portx_ctl_s cn61xx; - struct cvmx_sli_s2m_portx_ctl_s cn63xx; - struct cvmx_sli_s2m_portx_ctl_s cn63xxp1; - struct cvmx_sli_s2m_portx_ctl_s cn66xx; - struct cvmx_sli_s2m_portx_ctl_s cn68xx; - struct cvmx_sli_s2m_portx_ctl_s cn68xxp1; - struct cvmx_sli_s2m_portx_ctl_s cnf71xx; -}; - -union cvmx_sli_scratch_1 { - uint64_t u64; - struct cvmx_sli_scratch_1_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t data:64; -#else - uint64_t data:64; -#endif - } s; - struct cvmx_sli_scratch_1_s cn61xx; - struct cvmx_sli_scratch_1_s cn63xx; - struct cvmx_sli_scratch_1_s cn63xxp1; - struct cvmx_sli_scratch_1_s cn66xx; - struct cvmx_sli_scratch_1_s cn68xx; - struct cvmx_sli_scratch_1_s cn68xxp1; - struct cvmx_sli_scratch_1_s cnf71xx; -}; - -union cvmx_sli_scratch_2 { - uint64_t u64; - struct cvmx_sli_scratch_2_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t data:64; -#else - uint64_t data:64; -#endif - } s; - struct cvmx_sli_scratch_2_s cn61xx; - struct cvmx_sli_scratch_2_s cn63xx; - struct cvmx_sli_scratch_2_s cn63xxp1; - struct cvmx_sli_scratch_2_s cn66xx; - struct cvmx_sli_scratch_2_s cn68xx; - struct cvmx_sli_scratch_2_s cn68xxp1; - struct cvmx_sli_scratch_2_s cnf71xx; -}; - -union cvmx_sli_state1 { - uint64_t u64; - struct cvmx_sli_state1_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t cpl1:12; - uint64_t cpl0:12; - uint64_t arb:1; - uint64_t csr:39; -#else - uint64_t csr:39; - uint64_t arb:1; - uint64_t cpl0:12; - uint64_t cpl1:12; -#endif - } s; - struct cvmx_sli_state1_s cn61xx; - struct cvmx_sli_state1_s cn63xx; - struct cvmx_sli_state1_s cn63xxp1; - struct cvmx_sli_state1_s cn66xx; - struct cvmx_sli_state1_s cn68xx; - struct cvmx_sli_state1_s cn68xxp1; - struct cvmx_sli_state1_s cnf71xx; -}; - -union cvmx_sli_state2 { - uint64_t u64; - struct cvmx_sli_state2_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_56_63:8; - uint64_t nnp1:8; - uint64_t reserved_47_47:1; - uint64_t rac:1; - uint64_t csm1:15; - uint64_t csm0:15; - uint64_t nnp0:8; - uint64_t nnd:8; -#else - uint64_t nnd:8; - uint64_t nnp0:8; - uint64_t csm0:15; - uint64_t csm1:15; - uint64_t rac:1; - uint64_t reserved_47_47:1; - uint64_t nnp1:8; - uint64_t reserved_56_63:8; -#endif - } s; - struct cvmx_sli_state2_s cn61xx; - struct cvmx_sli_state2_s cn63xx; - struct cvmx_sli_state2_s cn63xxp1; - struct cvmx_sli_state2_s cn66xx; - struct cvmx_sli_state2_s cn68xx; - struct cvmx_sli_state2_s cn68xxp1; - struct cvmx_sli_state2_s cnf71xx; -}; - -union cvmx_sli_state3 { - uint64_t u64; - struct cvmx_sli_state3_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_56_63:8; - uint64_t psm1:15; - uint64_t psm0:15; - uint64_t nsm1:13; - uint64_t nsm0:13; -#else - uint64_t nsm0:13; - uint64_t nsm1:13; - uint64_t psm0:15; - uint64_t psm1:15; - uint64_t reserved_56_63:8; -#endif - } s; - struct cvmx_sli_state3_s cn61xx; - struct cvmx_sli_state3_s cn63xx; - struct cvmx_sli_state3_s cn63xxp1; - struct cvmx_sli_state3_s cn66xx; - struct cvmx_sli_state3_s cn68xx; - struct cvmx_sli_state3_s cn68xxp1; - struct cvmx_sli_state3_s cnf71xx; -}; - -union cvmx_sli_tx_pipe { - uint64_t u64; - struct cvmx_sli_tx_pipe_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_24_63:40; - uint64_t nump:8; - uint64_t reserved_7_15:9; - uint64_t base:7; -#else - uint64_t base:7; - uint64_t reserved_7_15:9; - uint64_t nump:8; - uint64_t reserved_24_63:40; -#endif + __BITFIELD_FIELD(uint64_t reserved_5_63:59, + __BITFIELD_FIELD(uint64_t wind_d:1, + __BITFIELD_FIELD(uint64_t bar0_d:1, + __BITFIELD_FIELD(uint64_t mrrs:3, + ;)))) } s; - struct cvmx_sli_tx_pipe_s cn68xx; - struct cvmx_sli_tx_pipe_s cn68xxp1; }; -union cvmx_sli_win_rd_addr { - uint64_t u64; - struct cvmx_sli_win_rd_addr_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_51_63:13; - uint64_t ld_cmd:2; - uint64_t iobit:1; - uint64_t rd_addr:48; -#else - uint64_t rd_addr:48; - uint64_t iobit:1; - uint64_t ld_cmd:2; - uint64_t reserved_51_63:13; -#endif - } s; - struct cvmx_sli_win_rd_addr_s cn61xx; - struct cvmx_sli_win_rd_addr_s cn63xx; - struct cvmx_sli_win_rd_addr_s cn63xxp1; - struct cvmx_sli_win_rd_addr_s cn66xx; - struct cvmx_sli_win_rd_addr_s cn68xx; - struct cvmx_sli_win_rd_addr_s cn68xxp1; - struct cvmx_sli_win_rd_addr_s cnf71xx; -}; - -union cvmx_sli_win_rd_data { - uint64_t u64; - struct cvmx_sli_win_rd_data_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t rd_data:64; -#else - uint64_t rd_data:64; -#endif - } s; - struct cvmx_sli_win_rd_data_s cn61xx; - struct cvmx_sli_win_rd_data_s cn63xx; - struct cvmx_sli_win_rd_data_s cn63xxp1; - struct cvmx_sli_win_rd_data_s cn66xx; - struct cvmx_sli_win_rd_data_s cn68xx; - struct cvmx_sli_win_rd_data_s cn68xxp1; - struct cvmx_sli_win_rd_data_s cnf71xx; -}; - -union cvmx_sli_win_wr_addr { - uint64_t u64; - struct cvmx_sli_win_wr_addr_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_49_63:15; - uint64_t iobit:1; - uint64_t wr_addr:45; - uint64_t reserved_0_2:3; -#else - uint64_t reserved_0_2:3; - uint64_t wr_addr:45; - uint64_t iobit:1; - uint64_t reserved_49_63:15; -#endif - } s; - struct cvmx_sli_win_wr_addr_s cn61xx; - struct cvmx_sli_win_wr_addr_s cn63xx; - struct cvmx_sli_win_wr_addr_s cn63xxp1; - struct cvmx_sli_win_wr_addr_s cn66xx; - struct cvmx_sli_win_wr_addr_s cn68xx; - struct cvmx_sli_win_wr_addr_s cn68xxp1; - struct cvmx_sli_win_wr_addr_s cnf71xx; -}; - -union cvmx_sli_win_wr_data { - uint64_t u64; - struct cvmx_sli_win_wr_data_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t wr_data:64; -#else - uint64_t wr_data:64; -#endif - } s; - struct cvmx_sli_win_wr_data_s cn61xx; - struct cvmx_sli_win_wr_data_s cn63xx; - struct cvmx_sli_win_wr_data_s cn63xxp1; - struct cvmx_sli_win_wr_data_s cn66xx; - struct cvmx_sli_win_wr_data_s cn68xx; - struct cvmx_sli_win_wr_data_s cn68xxp1; - struct cvmx_sli_win_wr_data_s cnf71xx; -}; - -union cvmx_sli_win_wr_mask { - uint64_t u64; - struct cvmx_sli_win_wr_mask_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_8_63:56; - uint64_t wr_mask:8; -#else - uint64_t wr_mask:8; - uint64_t reserved_8_63:56; -#endif - } s; - struct cvmx_sli_win_wr_mask_s cn61xx; - struct cvmx_sli_win_wr_mask_s cn63xx; - struct cvmx_sli_win_wr_mask_s cn63xxp1; - struct cvmx_sli_win_wr_mask_s cn66xx; - struct cvmx_sli_win_wr_mask_s cn68xx; - struct cvmx_sli_win_wr_mask_s cn68xxp1; - struct cvmx_sli_win_wr_mask_s cnf71xx; -}; - -union cvmx_sli_window_ctl { +union cvmx_sli_mem_access_subidx { uint64_t u64; - struct cvmx_sli_window_ctl_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint64_t reserved_32_63:32; - uint64_t time:32; -#else - uint64_t time:32; - uint64_t reserved_32_63:32; -#endif + struct cvmx_sli_mem_access_subidx_s { + __BITFIELD_FIELD(uint64_t reserved_43_63:21, + __BITFIELD_FIELD(uint64_t zero:1, + __BITFIELD_FIELD(uint64_t port:3, + __BITFIELD_FIELD(uint64_t nmerge:1, + __BITFIELD_FIELD(uint64_t esr:2, + __BITFIELD_FIELD(uint64_t esw:2, + __BITFIELD_FIELD(uint64_t wtype:2, + __BITFIELD_FIELD(uint64_t rtype:2, + __BITFIELD_FIELD(uint64_t ba:30, + ;))))))))) } s; - struct cvmx_sli_window_ctl_s cn61xx; - struct cvmx_sli_window_ctl_s cn63xx; - struct cvmx_sli_window_ctl_s cn63xxp1; - struct cvmx_sli_window_ctl_s cn66xx; - struct cvmx_sli_window_ctl_s cn68xx; - struct cvmx_sli_window_ctl_s cn68xxp1; - struct cvmx_sli_window_ctl_s cnf71xx; + struct cvmx_sli_mem_access_subidx_cn68xx { + __BITFIELD_FIELD(uint64_t reserved_43_63:21, + __BITFIELD_FIELD(uint64_t zero:1, + __BITFIELD_FIELD(uint64_t port:3, + __BITFIELD_FIELD(uint64_t nmerge:1, + __BITFIELD_FIELD(uint64_t esr:2, + __BITFIELD_FIELD(uint64_t esw:2, + __BITFIELD_FIELD(uint64_t wtype:2, + __BITFIELD_FIELD(uint64_t rtype:2, + __BITFIELD_FIELD(uint64_t ba:28, + __BITFIELD_FIELD(uint64_t reserved_0_1:2, + ;)))))))))) + } cn68xx; }; #endif diff --git a/arch/mips/pci/pcie-octeon.c b/arch/mips/pci/pcie-octeon.c index 9f672ceb089b..ad3584dbc9d7 100644 --- a/arch/mips/pci/pcie-octeon.c +++ b/arch/mips/pci/pcie-octeon.c @@ -679,7 +679,7 @@ static void __cvmx_increment_ba(union cvmx_sli_mem_access_subidx *pmas) if (OCTEON_IS_MODEL(OCTEON_CN68XX)) pmas->cn68xx.ba++; else - pmas->cn63xx.ba++; + pmas->s.ba++; } /** @@ -1351,7 +1351,7 @@ static int __cvmx_pcie_rc_initialize_gen2(int pcie_port) if (OCTEON_IS_MODEL(OCTEON_CN68XX)) mem_access_subid.cn68xx.ba = 0; else - mem_access_subid.cn63xx.ba = 0; + mem_access_subid.s.ba = 0; /* * Setup mem access 12-15 for port 0, 16-19 for port 1, -- cgit v1.2.3-59-g8ed1b From 7fd57ab9d9cff7ef0181c1e5db0ebd63cd514d6a Mon Sep 17 00:00:00 2001 From: "Steven J. Hill" Date: Thu, 9 Mar 2017 08:15:38 -0600 Subject: MIPS: Octeon: Fix compile error when USB is not enabled. Move all USB platform code to one place within the file. Signed-off-by: Steven J. Hill Acked-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/15406/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/octeon-platform.c | 97 ++++++++++++++++--------------- 1 file changed, 49 insertions(+), 48 deletions(-) (limited to 'arch') diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c index 3375e61daa19..e3c77d8a0d56 100644 --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2004-2016 Cavium Networks + * Copyright (C) 2004-2017 Cavium, Inc. * Copyright (C) 2008 Wind River Systems */ @@ -13,61 +13,19 @@ #include #include #include -#include -#include -#include #include #include + +#ifdef CONFIG_USB +#include +#include +#include #include #define CVMX_UAHCX_EHCI_USBCMD (CVMX_ADD_IO_SEG(0x00016F0000000010ull)) #define CVMX_UAHCX_OHCI_USBCMD (CVMX_ADD_IO_SEG(0x00016F0000000408ull)) -/* Octeon Random Number Generator. */ -static int __init octeon_rng_device_init(void) -{ - struct platform_device *pd; - int ret = 0; - - struct resource rng_resources[] = { - { - .flags = IORESOURCE_MEM, - .start = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS), - .end = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS) + 0xf - }, { - .flags = IORESOURCE_MEM, - .start = cvmx_build_io_address(8, 0), - .end = cvmx_build_io_address(8, 0) + 0x7 - } - }; - - pd = platform_device_alloc("octeon_rng", -1); - if (!pd) { - ret = -ENOMEM; - goto out; - } - - ret = platform_device_add_resources(pd, rng_resources, - ARRAY_SIZE(rng_resources)); - if (ret) - goto fail; - - ret = platform_device_add(pd); - if (ret) - goto fail; - - return ret; -fail: - platform_device_put(pd); - -out: - return ret; -} -device_initcall(octeon_rng_device_init); - -#ifdef CONFIG_USB - static DEFINE_MUTEX(octeon2_usb_clocks_mutex); static int octeon2_usb_clock_start_cnt; @@ -440,6 +398,47 @@ device_initcall(octeon_ohci_device_init); #endif /* CONFIG_USB */ +/* Octeon Random Number Generator. */ +static int __init octeon_rng_device_init(void) +{ + struct platform_device *pd; + int ret = 0; + + struct resource rng_resources[] = { + { + .flags = IORESOURCE_MEM, + .start = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS), + .end = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS) + 0xf + }, { + .flags = IORESOURCE_MEM, + .start = cvmx_build_io_address(8, 0), + .end = cvmx_build_io_address(8, 0) + 0x7 + } + }; + + pd = platform_device_alloc("octeon_rng", -1); + if (!pd) { + ret = -ENOMEM; + goto out; + } + + ret = platform_device_add_resources(pd, rng_resources, + ARRAY_SIZE(rng_resources)); + if (ret) + goto fail; + + ret = platform_device_add(pd); + if (ret) + goto fail; + + return ret; +fail: + platform_device_put(pd); + +out: + return ret; +} +device_initcall(octeon_rng_device_init); static struct of_device_id __initdata octeon_ids[] = { { .compatible = "simple-bus", }, @@ -1004,6 +1003,7 @@ end_led: ; } +#ifdef CONFIG_USB /* OHCI/UHCI USB */ alias_prop = fdt_getprop(initial_boot_params, aliases, "uctl", NULL); @@ -1052,6 +1052,7 @@ end_led: } } } +#endif return 0; } -- cgit v1.2.3-59-g8ed1b From 97b702981da0aa042007cd5b23a0f3904d470ec3 Mon Sep 17 00:00:00 2001 From: "Steven J. Hill" Date: Thu, 9 Mar 2017 08:31:30 -0600 Subject: MIPS: Octeon: Remove unused PCIERCX types and macros. Remove all unused bitfields and macros. Convert the remaining bitfields to use __BITFIELD_FIELD instead of #ifdef. [ralf@linux-mips.org: Add inclusions of as necessary.] Signed-off-by: Steven J. Hill Acked-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/15408/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/octeon/cvmx-pciercx-defs.h | 3225 ++-------------------- 1 file changed, 209 insertions(+), 3016 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/octeon/cvmx-pciercx-defs.h b/arch/mips/include/asm/octeon/cvmx-pciercx-defs.h index 4bce393391e2..e2dce1acf029 100644 --- a/arch/mips/include/asm/octeon/cvmx-pciercx-defs.h +++ b/arch/mips/include/asm/octeon/cvmx-pciercx-defs.h @@ -4,7 +4,7 @@ * Contact: support@caviumnetworks.com * This file is part of the OCTEON SDK * - * Copyright (c) 2003-2012 Cavium Networks + * Copyright (c) 2003-2017 Cavium, Inc. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as @@ -28,3148 +28,341 @@ #ifndef __CVMX_PCIERCX_DEFS_H__ #define __CVMX_PCIERCX_DEFS_H__ -#define CVMX_PCIERCX_CFG000(block_id) (0x0000000000000000ull) +#include + #define CVMX_PCIERCX_CFG001(block_id) (0x0000000000000004ull) -#define CVMX_PCIERCX_CFG002(block_id) (0x0000000000000008ull) -#define CVMX_PCIERCX_CFG003(block_id) (0x000000000000000Cull) -#define CVMX_PCIERCX_CFG004(block_id) (0x0000000000000010ull) -#define CVMX_PCIERCX_CFG005(block_id) (0x0000000000000014ull) #define CVMX_PCIERCX_CFG006(block_id) (0x0000000000000018ull) -#define CVMX_PCIERCX_CFG007(block_id) (0x000000000000001Cull) #define CVMX_PCIERCX_CFG008(block_id) (0x0000000000000020ull) #define CVMX_PCIERCX_CFG009(block_id) (0x0000000000000024ull) #define CVMX_PCIERCX_CFG010(block_id) (0x0000000000000028ull) #define CVMX_PCIERCX_CFG011(block_id) (0x000000000000002Cull) -#define CVMX_PCIERCX_CFG012(block_id) (0x0000000000000030ull) -#define CVMX_PCIERCX_CFG013(block_id) (0x0000000000000034ull) -#define CVMX_PCIERCX_CFG014(block_id) (0x0000000000000038ull) -#define CVMX_PCIERCX_CFG015(block_id) (0x000000000000003Cull) -#define CVMX_PCIERCX_CFG016(block_id) (0x0000000000000040ull) -#define CVMX_PCIERCX_CFG017(block_id) (0x0000000000000044ull) -#define CVMX_PCIERCX_CFG020(block_id) (0x0000000000000050ull) -#define CVMX_PCIERCX_CFG021(block_id) (0x0000000000000054ull) -#define CVMX_PCIERCX_CFG022(block_id) (0x0000000000000058ull) -#define CVMX_PCIERCX_CFG023(block_id) (0x000000000000005Cull) -#define CVMX_PCIERCX_CFG028(block_id) (0x0000000000000070ull) -#define CVMX_PCIERCX_CFG029(block_id) (0x0000000000000074ull) #define CVMX_PCIERCX_CFG030(block_id) (0x0000000000000078ull) #define CVMX_PCIERCX_CFG031(block_id) (0x000000000000007Cull) #define CVMX_PCIERCX_CFG032(block_id) (0x0000000000000080ull) -#define CVMX_PCIERCX_CFG033(block_id) (0x0000000000000084ull) #define CVMX_PCIERCX_CFG034(block_id) (0x0000000000000088ull) #define CVMX_PCIERCX_CFG035(block_id) (0x000000000000008Cull) -#define CVMX_PCIERCX_CFG036(block_id) (0x0000000000000090ull) -#define CVMX_PCIERCX_CFG037(block_id) (0x0000000000000094ull) -#define CVMX_PCIERCX_CFG038(block_id) (0x0000000000000098ull) -#define CVMX_PCIERCX_CFG039(block_id) (0x000000000000009Cull) #define CVMX_PCIERCX_CFG040(block_id) (0x00000000000000A0ull) -#define CVMX_PCIERCX_CFG041(block_id) (0x00000000000000A4ull) -#define CVMX_PCIERCX_CFG042(block_id) (0x00000000000000A8ull) -#define CVMX_PCIERCX_CFG064(block_id) (0x0000000000000100ull) -#define CVMX_PCIERCX_CFG065(block_id) (0x0000000000000104ull) #define CVMX_PCIERCX_CFG066(block_id) (0x0000000000000108ull) -#define CVMX_PCIERCX_CFG067(block_id) (0x000000000000010Cull) -#define CVMX_PCIERCX_CFG068(block_id) (0x0000000000000110ull) #define CVMX_PCIERCX_CFG069(block_id) (0x0000000000000114ull) #define CVMX_PCIERCX_CFG070(block_id) (0x0000000000000118ull) -#define CVMX_PCIERCX_CFG071(block_id) (0x000000000000011Cull) -#define CVMX_PCIERCX_CFG072(block_id) (0x0000000000000120ull) -#define CVMX_PCIERCX_CFG073(block_id) (0x0000000000000124ull) -#define CVMX_PCIERCX_CFG074(block_id) (0x0000000000000128ull) #define CVMX_PCIERCX_CFG075(block_id) (0x000000000000012Cull) -#define CVMX_PCIERCX_CFG076(block_id) (0x0000000000000130ull) -#define CVMX_PCIERCX_CFG077(block_id) (0x0000000000000134ull) #define CVMX_PCIERCX_CFG448(block_id) (0x0000000000000700ull) -#define CVMX_PCIERCX_CFG449(block_id) (0x0000000000000704ull) -#define CVMX_PCIERCX_CFG450(block_id) (0x0000000000000708ull) -#define CVMX_PCIERCX_CFG451(block_id) (0x000000000000070Cull) #define CVMX_PCIERCX_CFG452(block_id) (0x0000000000000710ull) -#define CVMX_PCIERCX_CFG453(block_id) (0x0000000000000714ull) -#define CVMX_PCIERCX_CFG454(block_id) (0x0000000000000718ull) #define CVMX_PCIERCX_CFG455(block_id) (0x000000000000071Cull) -#define CVMX_PCIERCX_CFG456(block_id) (0x0000000000000720ull) -#define CVMX_PCIERCX_CFG458(block_id) (0x0000000000000728ull) -#define CVMX_PCIERCX_CFG459(block_id) (0x000000000000072Cull) -#define CVMX_PCIERCX_CFG460(block_id) (0x0000000000000730ull) -#define CVMX_PCIERCX_CFG461(block_id) (0x0000000000000734ull) -#define CVMX_PCIERCX_CFG462(block_id) (0x0000000000000738ull) -#define CVMX_PCIERCX_CFG463(block_id) (0x000000000000073Cull) -#define CVMX_PCIERCX_CFG464(block_id) (0x0000000000000740ull) -#define CVMX_PCIERCX_CFG465(block_id) (0x0000000000000744ull) -#define CVMX_PCIERCX_CFG466(block_id) (0x0000000000000748ull) -#define CVMX_PCIERCX_CFG467(block_id) (0x000000000000074Cull) -#define CVMX_PCIERCX_CFG468(block_id) (0x0000000000000750ull) -#define CVMX_PCIERCX_CFG490(block_id) (0x00000000000007A8ull) -#define CVMX_PCIERCX_CFG491(block_id) (0x00000000000007ACull) -#define CVMX_PCIERCX_CFG492(block_id) (0x00000000000007B0ull) #define CVMX_PCIERCX_CFG515(block_id) (0x000000000000080Cull) -#define CVMX_PCIERCX_CFG516(block_id) (0x0000000000000810ull) -#define CVMX_PCIERCX_CFG517(block_id) (0x0000000000000814ull) - -union cvmx_pciercx_cfg000 { - uint32_t u32; - struct cvmx_pciercx_cfg000_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t devid:16; - uint32_t vendid:16; -#else - uint32_t vendid:16; - uint32_t devid:16; -#endif - } s; - struct cvmx_pciercx_cfg000_s cn52xx; - struct cvmx_pciercx_cfg000_s cn52xxp1; - struct cvmx_pciercx_cfg000_s cn56xx; - struct cvmx_pciercx_cfg000_s cn56xxp1; - struct cvmx_pciercx_cfg000_s cn61xx; - struct cvmx_pciercx_cfg000_s cn63xx; - struct cvmx_pciercx_cfg000_s cn63xxp1; - struct cvmx_pciercx_cfg000_s cn66xx; - struct cvmx_pciercx_cfg000_s cn68xx; - struct cvmx_pciercx_cfg000_s cn68xxp1; - struct cvmx_pciercx_cfg000_s cnf71xx; -}; union cvmx_pciercx_cfg001 { uint32_t u32; struct cvmx_pciercx_cfg001_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t dpe:1; - uint32_t sse:1; - uint32_t rma:1; - uint32_t rta:1; - uint32_t sta:1; - uint32_t devt:2; - uint32_t mdpe:1; - uint32_t fbb:1; - uint32_t reserved_22_22:1; - uint32_t m66:1; - uint32_t cl:1; - uint32_t i_stat:1; - uint32_t reserved_11_18:8; - uint32_t i_dis:1; - uint32_t fbbe:1; - uint32_t see:1; - uint32_t ids_wcc:1; - uint32_t per:1; - uint32_t vps:1; - uint32_t mwice:1; - uint32_t scse:1; - uint32_t me:1; - uint32_t msae:1; - uint32_t isae:1; -#else - uint32_t isae:1; - uint32_t msae:1; - uint32_t me:1; - uint32_t scse:1; - uint32_t mwice:1; - uint32_t vps:1; - uint32_t per:1; - uint32_t ids_wcc:1; - uint32_t see:1; - uint32_t fbbe:1; - uint32_t i_dis:1; - uint32_t reserved_11_18:8; - uint32_t i_stat:1; - uint32_t cl:1; - uint32_t m66:1; - uint32_t reserved_22_22:1; - uint32_t fbb:1; - uint32_t mdpe:1; - uint32_t devt:2; - uint32_t sta:1; - uint32_t rta:1; - uint32_t rma:1; - uint32_t sse:1; - uint32_t dpe:1; -#endif - } s; - struct cvmx_pciercx_cfg001_s cn52xx; - struct cvmx_pciercx_cfg001_s cn52xxp1; - struct cvmx_pciercx_cfg001_s cn56xx; - struct cvmx_pciercx_cfg001_s cn56xxp1; - struct cvmx_pciercx_cfg001_s cn61xx; - struct cvmx_pciercx_cfg001_s cn63xx; - struct cvmx_pciercx_cfg001_s cn63xxp1; - struct cvmx_pciercx_cfg001_s cn66xx; - struct cvmx_pciercx_cfg001_s cn68xx; - struct cvmx_pciercx_cfg001_s cn68xxp1; - struct cvmx_pciercx_cfg001_s cnf71xx; -}; - -union cvmx_pciercx_cfg002 { - uint32_t u32; - struct cvmx_pciercx_cfg002_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t bcc:8; - uint32_t sc:8; - uint32_t pi:8; - uint32_t rid:8; -#else - uint32_t rid:8; - uint32_t pi:8; - uint32_t sc:8; - uint32_t bcc:8; -#endif - } s; - struct cvmx_pciercx_cfg002_s cn52xx; - struct cvmx_pciercx_cfg002_s cn52xxp1; - struct cvmx_pciercx_cfg002_s cn56xx; - struct cvmx_pciercx_cfg002_s cn56xxp1; - struct cvmx_pciercx_cfg002_s cn61xx; - struct cvmx_pciercx_cfg002_s cn63xx; - struct cvmx_pciercx_cfg002_s cn63xxp1; - struct cvmx_pciercx_cfg002_s cn66xx; - struct cvmx_pciercx_cfg002_s cn68xx; - struct cvmx_pciercx_cfg002_s cn68xxp1; - struct cvmx_pciercx_cfg002_s cnf71xx; -}; - -union cvmx_pciercx_cfg003 { - uint32_t u32; - struct cvmx_pciercx_cfg003_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t bist:8; - uint32_t mfd:1; - uint32_t chf:7; - uint32_t lt:8; - uint32_t cls:8; -#else - uint32_t cls:8; - uint32_t lt:8; - uint32_t chf:7; - uint32_t mfd:1; - uint32_t bist:8; -#endif - } s; - struct cvmx_pciercx_cfg003_s cn52xx; - struct cvmx_pciercx_cfg003_s cn52xxp1; - struct cvmx_pciercx_cfg003_s cn56xx; - struct cvmx_pciercx_cfg003_s cn56xxp1; - struct cvmx_pciercx_cfg003_s cn61xx; - struct cvmx_pciercx_cfg003_s cn63xx; - struct cvmx_pciercx_cfg003_s cn63xxp1; - struct cvmx_pciercx_cfg003_s cn66xx; - struct cvmx_pciercx_cfg003_s cn68xx; - struct cvmx_pciercx_cfg003_s cn68xxp1; - struct cvmx_pciercx_cfg003_s cnf71xx; -}; - -union cvmx_pciercx_cfg004 { - uint32_t u32; - struct cvmx_pciercx_cfg004_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_0_31:32; -#else - uint32_t reserved_0_31:32; -#endif + __BITFIELD_FIELD(uint32_t dpe:1, + __BITFIELD_FIELD(uint32_t sse:1, + __BITFIELD_FIELD(uint32_t rma:1, + __BITFIELD_FIELD(uint32_t rta:1, + __BITFIELD_FIELD(uint32_t sta:1, + __BITFIELD_FIELD(uint32_t devt:2, + __BITFIELD_FIELD(uint32_t mdpe:1, + __BITFIELD_FIELD(uint32_t fbb:1, + __BITFIELD_FIELD(uint32_t reserved_22_22:1, + __BITFIELD_FIELD(uint32_t m66:1, + __BITFIELD_FIELD(uint32_t cl:1, + __BITFIELD_FIELD(uint32_t i_stat:1, + __BITFIELD_FIELD(uint32_t reserved_11_18:8, + __BITFIELD_FIELD(uint32_t i_dis:1, + __BITFIELD_FIELD(uint32_t fbbe:1, + __BITFIELD_FIELD(uint32_t see:1, + __BITFIELD_FIELD(uint32_t ids_wcc:1, + __BITFIELD_FIELD(uint32_t per:1, + __BITFIELD_FIELD(uint32_t vps:1, + __BITFIELD_FIELD(uint32_t mwice:1, + __BITFIELD_FIELD(uint32_t scse:1, + __BITFIELD_FIELD(uint32_t me:1, + __BITFIELD_FIELD(uint32_t msae:1, + __BITFIELD_FIELD(uint32_t isae:1, + ;)))))))))))))))))))))))) } s; - struct cvmx_pciercx_cfg004_s cn52xx; - struct cvmx_pciercx_cfg004_s cn52xxp1; - struct cvmx_pciercx_cfg004_s cn56xx; - struct cvmx_pciercx_cfg004_s cn56xxp1; - struct cvmx_pciercx_cfg004_s cn61xx; - struct cvmx_pciercx_cfg004_s cn63xx; - struct cvmx_pciercx_cfg004_s cn63xxp1; - struct cvmx_pciercx_cfg004_s cn66xx; - struct cvmx_pciercx_cfg004_s cn68xx; - struct cvmx_pciercx_cfg004_s cn68xxp1; - struct cvmx_pciercx_cfg004_s cnf71xx; -}; - -union cvmx_pciercx_cfg005 { - uint32_t u32; - struct cvmx_pciercx_cfg005_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_0_31:32; -#else - uint32_t reserved_0_31:32; -#endif - } s; - struct cvmx_pciercx_cfg005_s cn52xx; - struct cvmx_pciercx_cfg005_s cn52xxp1; - struct cvmx_pciercx_cfg005_s cn56xx; - struct cvmx_pciercx_cfg005_s cn56xxp1; - struct cvmx_pciercx_cfg005_s cn61xx; - struct cvmx_pciercx_cfg005_s cn63xx; - struct cvmx_pciercx_cfg005_s cn63xxp1; - struct cvmx_pciercx_cfg005_s cn66xx; - struct cvmx_pciercx_cfg005_s cn68xx; - struct cvmx_pciercx_cfg005_s cn68xxp1; - struct cvmx_pciercx_cfg005_s cnf71xx; }; union cvmx_pciercx_cfg006 { uint32_t u32; struct cvmx_pciercx_cfg006_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t slt:8; - uint32_t subbnum:8; - uint32_t sbnum:8; - uint32_t pbnum:8; -#else - uint32_t pbnum:8; - uint32_t sbnum:8; - uint32_t subbnum:8; - uint32_t slt:8; -#endif - } s; - struct cvmx_pciercx_cfg006_s cn52xx; - struct cvmx_pciercx_cfg006_s cn52xxp1; - struct cvmx_pciercx_cfg006_s cn56xx; - struct cvmx_pciercx_cfg006_s cn56xxp1; - struct cvmx_pciercx_cfg006_s cn61xx; - struct cvmx_pciercx_cfg006_s cn63xx; - struct cvmx_pciercx_cfg006_s cn63xxp1; - struct cvmx_pciercx_cfg006_s cn66xx; - struct cvmx_pciercx_cfg006_s cn68xx; - struct cvmx_pciercx_cfg006_s cn68xxp1; - struct cvmx_pciercx_cfg006_s cnf71xx; -}; - -union cvmx_pciercx_cfg007 { - uint32_t u32; - struct cvmx_pciercx_cfg007_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t dpe:1; - uint32_t sse:1; - uint32_t rma:1; - uint32_t rta:1; - uint32_t sta:1; - uint32_t devt:2; - uint32_t mdpe:1; - uint32_t fbb:1; - uint32_t reserved_22_22:1; - uint32_t m66:1; - uint32_t reserved_16_20:5; - uint32_t lio_limi:4; - uint32_t reserved_9_11:3; - uint32_t io32b:1; - uint32_t lio_base:4; - uint32_t reserved_1_3:3; - uint32_t io32a:1; -#else - uint32_t io32a:1; - uint32_t reserved_1_3:3; - uint32_t lio_base:4; - uint32_t io32b:1; - uint32_t reserved_9_11:3; - uint32_t lio_limi:4; - uint32_t reserved_16_20:5; - uint32_t m66:1; - uint32_t reserved_22_22:1; - uint32_t fbb:1; - uint32_t mdpe:1; - uint32_t devt:2; - uint32_t sta:1; - uint32_t rta:1; - uint32_t rma:1; - uint32_t sse:1; - uint32_t dpe:1; -#endif + __BITFIELD_FIELD(uint32_t slt:8, + __BITFIELD_FIELD(uint32_t subbnum:8, + __BITFIELD_FIELD(uint32_t sbnum:8, + __BITFIELD_FIELD(uint32_t pbnum:8, + ;)))) } s; - struct cvmx_pciercx_cfg007_s cn52xx; - struct cvmx_pciercx_cfg007_s cn52xxp1; - struct cvmx_pciercx_cfg007_s cn56xx; - struct cvmx_pciercx_cfg007_s cn56xxp1; - struct cvmx_pciercx_cfg007_s cn61xx; - struct cvmx_pciercx_cfg007_s cn63xx; - struct cvmx_pciercx_cfg007_s cn63xxp1; - struct cvmx_pciercx_cfg007_s cn66xx; - struct cvmx_pciercx_cfg007_s cn68xx; - struct cvmx_pciercx_cfg007_s cn68xxp1; - struct cvmx_pciercx_cfg007_s cnf71xx; }; union cvmx_pciercx_cfg008 { uint32_t u32; struct cvmx_pciercx_cfg008_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t ml_addr:12; - uint32_t reserved_16_19:4; - uint32_t mb_addr:12; - uint32_t reserved_0_3:4; -#else - uint32_t reserved_0_3:4; - uint32_t mb_addr:12; - uint32_t reserved_16_19:4; - uint32_t ml_addr:12; -#endif + __BITFIELD_FIELD(uint32_t ml_addr:12, + __BITFIELD_FIELD(uint32_t reserved_16_19:4, + __BITFIELD_FIELD(uint32_t mb_addr:12, + __BITFIELD_FIELD(uint32_t reserved_0_3:4, + ;)))) } s; - struct cvmx_pciercx_cfg008_s cn52xx; - struct cvmx_pciercx_cfg008_s cn52xxp1; - struct cvmx_pciercx_cfg008_s cn56xx; - struct cvmx_pciercx_cfg008_s cn56xxp1; - struct cvmx_pciercx_cfg008_s cn61xx; - struct cvmx_pciercx_cfg008_s cn63xx; - struct cvmx_pciercx_cfg008_s cn63xxp1; - struct cvmx_pciercx_cfg008_s cn66xx; - struct cvmx_pciercx_cfg008_s cn68xx; - struct cvmx_pciercx_cfg008_s cn68xxp1; - struct cvmx_pciercx_cfg008_s cnf71xx; }; union cvmx_pciercx_cfg009 { uint32_t u32; struct cvmx_pciercx_cfg009_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t lmem_limit:12; - uint32_t reserved_17_19:3; - uint32_t mem64b:1; - uint32_t lmem_base:12; - uint32_t reserved_1_3:3; - uint32_t mem64a:1; -#else - uint32_t mem64a:1; - uint32_t reserved_1_3:3; - uint32_t lmem_base:12; - uint32_t mem64b:1; - uint32_t reserved_17_19:3; - uint32_t lmem_limit:12; -#endif + __BITFIELD_FIELD(uint32_t lmem_limit:12, + __BITFIELD_FIELD(uint32_t reserved_17_19:3, + __BITFIELD_FIELD(uint32_t mem64b:1, + __BITFIELD_FIELD(uint32_t lmem_base:12, + __BITFIELD_FIELD(uint32_t reserved_1_3:3, + __BITFIELD_FIELD(uint32_t mem64a:1, + ;)))))) } s; - struct cvmx_pciercx_cfg009_s cn52xx; - struct cvmx_pciercx_cfg009_s cn52xxp1; - struct cvmx_pciercx_cfg009_s cn56xx; - struct cvmx_pciercx_cfg009_s cn56xxp1; - struct cvmx_pciercx_cfg009_s cn61xx; - struct cvmx_pciercx_cfg009_s cn63xx; - struct cvmx_pciercx_cfg009_s cn63xxp1; - struct cvmx_pciercx_cfg009_s cn66xx; - struct cvmx_pciercx_cfg009_s cn68xx; - struct cvmx_pciercx_cfg009_s cn68xxp1; - struct cvmx_pciercx_cfg009_s cnf71xx; }; union cvmx_pciercx_cfg010 { uint32_t u32; struct cvmx_pciercx_cfg010_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t umem_base:32; -#else - uint32_t umem_base:32; -#endif + uint32_t umem_base; } s; - struct cvmx_pciercx_cfg010_s cn52xx; - struct cvmx_pciercx_cfg010_s cn52xxp1; - struct cvmx_pciercx_cfg010_s cn56xx; - struct cvmx_pciercx_cfg010_s cn56xxp1; - struct cvmx_pciercx_cfg010_s cn61xx; - struct cvmx_pciercx_cfg010_s cn63xx; - struct cvmx_pciercx_cfg010_s cn63xxp1; - struct cvmx_pciercx_cfg010_s cn66xx; - struct cvmx_pciercx_cfg010_s cn68xx; - struct cvmx_pciercx_cfg010_s cn68xxp1; - struct cvmx_pciercx_cfg010_s cnf71xx; }; union cvmx_pciercx_cfg011 { uint32_t u32; struct cvmx_pciercx_cfg011_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t umem_limit:32; -#else - uint32_t umem_limit:32; -#endif - } s; - struct cvmx_pciercx_cfg011_s cn52xx; - struct cvmx_pciercx_cfg011_s cn52xxp1; - struct cvmx_pciercx_cfg011_s cn56xx; - struct cvmx_pciercx_cfg011_s cn56xxp1; - struct cvmx_pciercx_cfg011_s cn61xx; - struct cvmx_pciercx_cfg011_s cn63xx; - struct cvmx_pciercx_cfg011_s cn63xxp1; - struct cvmx_pciercx_cfg011_s cn66xx; - struct cvmx_pciercx_cfg011_s cn68xx; - struct cvmx_pciercx_cfg011_s cn68xxp1; - struct cvmx_pciercx_cfg011_s cnf71xx; -}; - -union cvmx_pciercx_cfg012 { - uint32_t u32; - struct cvmx_pciercx_cfg012_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t uio_limit:16; - uint32_t uio_base:16; -#else - uint32_t uio_base:16; - uint32_t uio_limit:16; -#endif + uint32_t umem_limit; } s; - struct cvmx_pciercx_cfg012_s cn52xx; - struct cvmx_pciercx_cfg012_s cn52xxp1; - struct cvmx_pciercx_cfg012_s cn56xx; - struct cvmx_pciercx_cfg012_s cn56xxp1; - struct cvmx_pciercx_cfg012_s cn61xx; - struct cvmx_pciercx_cfg012_s cn63xx; - struct cvmx_pciercx_cfg012_s cn63xxp1; - struct cvmx_pciercx_cfg012_s cn66xx; - struct cvmx_pciercx_cfg012_s cn68xx; - struct cvmx_pciercx_cfg012_s cn68xxp1; - struct cvmx_pciercx_cfg012_s cnf71xx; -}; - -union cvmx_pciercx_cfg013 { - uint32_t u32; - struct cvmx_pciercx_cfg013_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_8_31:24; - uint32_t cp:8; -#else - uint32_t cp:8; - uint32_t reserved_8_31:24; -#endif - } s; - struct cvmx_pciercx_cfg013_s cn52xx; - struct cvmx_pciercx_cfg013_s cn52xxp1; - struct cvmx_pciercx_cfg013_s cn56xx; - struct cvmx_pciercx_cfg013_s cn56xxp1; - struct cvmx_pciercx_cfg013_s cn61xx; - struct cvmx_pciercx_cfg013_s cn63xx; - struct cvmx_pciercx_cfg013_s cn63xxp1; - struct cvmx_pciercx_cfg013_s cn66xx; - struct cvmx_pciercx_cfg013_s cn68xx; - struct cvmx_pciercx_cfg013_s cn68xxp1; - struct cvmx_pciercx_cfg013_s cnf71xx; -}; - -union cvmx_pciercx_cfg014 { - uint32_t u32; - struct cvmx_pciercx_cfg014_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_0_31:32; -#else - uint32_t reserved_0_31:32; -#endif - } s; - struct cvmx_pciercx_cfg014_s cn52xx; - struct cvmx_pciercx_cfg014_s cn52xxp1; - struct cvmx_pciercx_cfg014_s cn56xx; - struct cvmx_pciercx_cfg014_s cn56xxp1; - struct cvmx_pciercx_cfg014_s cn61xx; - struct cvmx_pciercx_cfg014_s cn63xx; - struct cvmx_pciercx_cfg014_s cn63xxp1; - struct cvmx_pciercx_cfg014_s cn66xx; - struct cvmx_pciercx_cfg014_s cn68xx; - struct cvmx_pciercx_cfg014_s cn68xxp1; - struct cvmx_pciercx_cfg014_s cnf71xx; -}; - -union cvmx_pciercx_cfg015 { - uint32_t u32; - struct cvmx_pciercx_cfg015_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_28_31:4; - uint32_t dtsees:1; - uint32_t dts:1; - uint32_t sdt:1; - uint32_t pdt:1; - uint32_t fbbe:1; - uint32_t sbrst:1; - uint32_t mam:1; - uint32_t vga16d:1; - uint32_t vgae:1; - uint32_t isae:1; - uint32_t see:1; - uint32_t pere:1; - uint32_t inta:8; - uint32_t il:8; -#else - uint32_t il:8; - uint32_t inta:8; - uint32_t pere:1; - uint32_t see:1; - uint32_t isae:1; - uint32_t vgae:1; - uint32_t vga16d:1; - uint32_t mam:1; - uint32_t sbrst:1; - uint32_t fbbe:1; - uint32_t pdt:1; - uint32_t sdt:1; - uint32_t dts:1; - uint32_t dtsees:1; - uint32_t reserved_28_31:4; -#endif - } s; - struct cvmx_pciercx_cfg015_s cn52xx; - struct cvmx_pciercx_cfg015_s cn52xxp1; - struct cvmx_pciercx_cfg015_s cn56xx; - struct cvmx_pciercx_cfg015_s cn56xxp1; - struct cvmx_pciercx_cfg015_s cn61xx; - struct cvmx_pciercx_cfg015_s cn63xx; - struct cvmx_pciercx_cfg015_s cn63xxp1; - struct cvmx_pciercx_cfg015_s cn66xx; - struct cvmx_pciercx_cfg015_s cn68xx; - struct cvmx_pciercx_cfg015_s cn68xxp1; - struct cvmx_pciercx_cfg015_s cnf71xx; -}; - -union cvmx_pciercx_cfg016 { - uint32_t u32; - struct cvmx_pciercx_cfg016_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t pmes:5; - uint32_t d2s:1; - uint32_t d1s:1; - uint32_t auxc:3; - uint32_t dsi:1; - uint32_t reserved_20_20:1; - uint32_t pme_clock:1; - uint32_t pmsv:3; - uint32_t ncp:8; - uint32_t pmcid:8; -#else - uint32_t pmcid:8; - uint32_t ncp:8; - uint32_t pmsv:3; - uint32_t pme_clock:1; - uint32_t reserved_20_20:1; - uint32_t dsi:1; - uint32_t auxc:3; - uint32_t d1s:1; - uint32_t d2s:1; - uint32_t pmes:5; -#endif - } s; - struct cvmx_pciercx_cfg016_s cn52xx; - struct cvmx_pciercx_cfg016_s cn52xxp1; - struct cvmx_pciercx_cfg016_s cn56xx; - struct cvmx_pciercx_cfg016_s cn56xxp1; - struct cvmx_pciercx_cfg016_s cn61xx; - struct cvmx_pciercx_cfg016_s cn63xx; - struct cvmx_pciercx_cfg016_s cn63xxp1; - struct cvmx_pciercx_cfg016_s cn66xx; - struct cvmx_pciercx_cfg016_s cn68xx; - struct cvmx_pciercx_cfg016_s cn68xxp1; - struct cvmx_pciercx_cfg016_s cnf71xx; -}; - -union cvmx_pciercx_cfg017 { - uint32_t u32; - struct cvmx_pciercx_cfg017_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t pmdia:8; - uint32_t bpccee:1; - uint32_t bd3h:1; - uint32_t reserved_16_21:6; - uint32_t pmess:1; - uint32_t pmedsia:2; - uint32_t pmds:4; - uint32_t pmeens:1; - uint32_t reserved_4_7:4; - uint32_t nsr:1; - uint32_t reserved_2_2:1; - uint32_t ps:2; -#else - uint32_t ps:2; - uint32_t reserved_2_2:1; - uint32_t nsr:1; - uint32_t reserved_4_7:4; - uint32_t pmeens:1; - uint32_t pmds:4; - uint32_t pmedsia:2; - uint32_t pmess:1; - uint32_t reserved_16_21:6; - uint32_t bd3h:1; - uint32_t bpccee:1; - uint32_t pmdia:8; -#endif - } s; - struct cvmx_pciercx_cfg017_s cn52xx; - struct cvmx_pciercx_cfg017_s cn52xxp1; - struct cvmx_pciercx_cfg017_s cn56xx; - struct cvmx_pciercx_cfg017_s cn56xxp1; - struct cvmx_pciercx_cfg017_s cn61xx; - struct cvmx_pciercx_cfg017_s cn63xx; - struct cvmx_pciercx_cfg017_s cn63xxp1; - struct cvmx_pciercx_cfg017_s cn66xx; - struct cvmx_pciercx_cfg017_s cn68xx; - struct cvmx_pciercx_cfg017_s cn68xxp1; - struct cvmx_pciercx_cfg017_s cnf71xx; -}; - -union cvmx_pciercx_cfg020 { - uint32_t u32; - struct cvmx_pciercx_cfg020_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_25_31:7; - uint32_t pvm:1; - uint32_t m64:1; - uint32_t mme:3; - uint32_t mmc:3; - uint32_t msien:1; - uint32_t ncp:8; - uint32_t msicid:8; -#else - uint32_t msicid:8; - uint32_t ncp:8; - uint32_t msien:1; - uint32_t mmc:3; - uint32_t mme:3; - uint32_t m64:1; - uint32_t pvm:1; - uint32_t reserved_25_31:7; -#endif - } s; - struct cvmx_pciercx_cfg020_cn52xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_24_31:8; - uint32_t m64:1; - uint32_t mme:3; - uint32_t mmc:3; - uint32_t msien:1; - uint32_t ncp:8; - uint32_t msicid:8; -#else - uint32_t msicid:8; - uint32_t ncp:8; - uint32_t msien:1; - uint32_t mmc:3; - uint32_t mme:3; - uint32_t m64:1; - uint32_t reserved_24_31:8; -#endif - } cn52xx; - struct cvmx_pciercx_cfg020_cn52xx cn52xxp1; - struct cvmx_pciercx_cfg020_cn52xx cn56xx; - struct cvmx_pciercx_cfg020_cn52xx cn56xxp1; - struct cvmx_pciercx_cfg020_s cn61xx; - struct cvmx_pciercx_cfg020_cn52xx cn63xx; - struct cvmx_pciercx_cfg020_cn52xx cn63xxp1; - struct cvmx_pciercx_cfg020_cn52xx cn66xx; - struct cvmx_pciercx_cfg020_cn52xx cn68xx; - struct cvmx_pciercx_cfg020_cn52xx cn68xxp1; - struct cvmx_pciercx_cfg020_s cnf71xx; -}; - -union cvmx_pciercx_cfg021 { - uint32_t u32; - struct cvmx_pciercx_cfg021_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t lmsi:30; - uint32_t reserved_0_1:2; -#else - uint32_t reserved_0_1:2; - uint32_t lmsi:30; -#endif - } s; - struct cvmx_pciercx_cfg021_s cn52xx; - struct cvmx_pciercx_cfg021_s cn52xxp1; - struct cvmx_pciercx_cfg021_s cn56xx; - struct cvmx_pciercx_cfg021_s cn56xxp1; - struct cvmx_pciercx_cfg021_s cn61xx; - struct cvmx_pciercx_cfg021_s cn63xx; - struct cvmx_pciercx_cfg021_s cn63xxp1; - struct cvmx_pciercx_cfg021_s cn66xx; - struct cvmx_pciercx_cfg021_s cn68xx; - struct cvmx_pciercx_cfg021_s cn68xxp1; - struct cvmx_pciercx_cfg021_s cnf71xx; -}; - -union cvmx_pciercx_cfg022 { - uint32_t u32; - struct cvmx_pciercx_cfg022_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t umsi:32; -#else - uint32_t umsi:32; -#endif - } s; - struct cvmx_pciercx_cfg022_s cn52xx; - struct cvmx_pciercx_cfg022_s cn52xxp1; - struct cvmx_pciercx_cfg022_s cn56xx; - struct cvmx_pciercx_cfg022_s cn56xxp1; - struct cvmx_pciercx_cfg022_s cn61xx; - struct cvmx_pciercx_cfg022_s cn63xx; - struct cvmx_pciercx_cfg022_s cn63xxp1; - struct cvmx_pciercx_cfg022_s cn66xx; - struct cvmx_pciercx_cfg022_s cn68xx; - struct cvmx_pciercx_cfg022_s cn68xxp1; - struct cvmx_pciercx_cfg022_s cnf71xx; -}; - -union cvmx_pciercx_cfg023 { - uint32_t u32; - struct cvmx_pciercx_cfg023_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_16_31:16; - uint32_t msimd:16; -#else - uint32_t msimd:16; - uint32_t reserved_16_31:16; -#endif - } s; - struct cvmx_pciercx_cfg023_s cn52xx; - struct cvmx_pciercx_cfg023_s cn52xxp1; - struct cvmx_pciercx_cfg023_s cn56xx; - struct cvmx_pciercx_cfg023_s cn56xxp1; - struct cvmx_pciercx_cfg023_s cn61xx; - struct cvmx_pciercx_cfg023_s cn63xx; - struct cvmx_pciercx_cfg023_s cn63xxp1; - struct cvmx_pciercx_cfg023_s cn66xx; - struct cvmx_pciercx_cfg023_s cn68xx; - struct cvmx_pciercx_cfg023_s cn68xxp1; - struct cvmx_pciercx_cfg023_s cnf71xx; -}; - -union cvmx_pciercx_cfg028 { - uint32_t u32; - struct cvmx_pciercx_cfg028_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_30_31:2; - uint32_t imn:5; - uint32_t si:1; - uint32_t dpt:4; - uint32_t pciecv:4; - uint32_t ncp:8; - uint32_t pcieid:8; -#else - uint32_t pcieid:8; - uint32_t ncp:8; - uint32_t pciecv:4; - uint32_t dpt:4; - uint32_t si:1; - uint32_t imn:5; - uint32_t reserved_30_31:2; -#endif - } s; - struct cvmx_pciercx_cfg028_s cn52xx; - struct cvmx_pciercx_cfg028_s cn52xxp1; - struct cvmx_pciercx_cfg028_s cn56xx; - struct cvmx_pciercx_cfg028_s cn56xxp1; - struct cvmx_pciercx_cfg028_s cn61xx; - struct cvmx_pciercx_cfg028_s cn63xx; - struct cvmx_pciercx_cfg028_s cn63xxp1; - struct cvmx_pciercx_cfg028_s cn66xx; - struct cvmx_pciercx_cfg028_s cn68xx; - struct cvmx_pciercx_cfg028_s cn68xxp1; - struct cvmx_pciercx_cfg028_s cnf71xx; -}; - -union cvmx_pciercx_cfg029 { - uint32_t u32; - struct cvmx_pciercx_cfg029_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_28_31:4; - uint32_t cspls:2; - uint32_t csplv:8; - uint32_t reserved_16_17:2; - uint32_t rber:1; - uint32_t reserved_12_14:3; - uint32_t el1al:3; - uint32_t el0al:3; - uint32_t etfs:1; - uint32_t pfs:2; - uint32_t mpss:3; -#else - uint32_t mpss:3; - uint32_t pfs:2; - uint32_t etfs:1; - uint32_t el0al:3; - uint32_t el1al:3; - uint32_t reserved_12_14:3; - uint32_t rber:1; - uint32_t reserved_16_17:2; - uint32_t csplv:8; - uint32_t cspls:2; - uint32_t reserved_28_31:4; -#endif - } s; - struct cvmx_pciercx_cfg029_s cn52xx; - struct cvmx_pciercx_cfg029_s cn52xxp1; - struct cvmx_pciercx_cfg029_s cn56xx; - struct cvmx_pciercx_cfg029_s cn56xxp1; - struct cvmx_pciercx_cfg029_s cn61xx; - struct cvmx_pciercx_cfg029_s cn63xx; - struct cvmx_pciercx_cfg029_s cn63xxp1; - struct cvmx_pciercx_cfg029_s cn66xx; - struct cvmx_pciercx_cfg029_s cn68xx; - struct cvmx_pciercx_cfg029_s cn68xxp1; - struct cvmx_pciercx_cfg029_s cnf71xx; }; union cvmx_pciercx_cfg030 { uint32_t u32; struct cvmx_pciercx_cfg030_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_22_31:10; - uint32_t tp:1; - uint32_t ap_d:1; - uint32_t ur_d:1; - uint32_t fe_d:1; - uint32_t nfe_d:1; - uint32_t ce_d:1; - uint32_t reserved_15_15:1; - uint32_t mrrs:3; - uint32_t ns_en:1; - uint32_t ap_en:1; - uint32_t pf_en:1; - uint32_t etf_en:1; - uint32_t mps:3; - uint32_t ro_en:1; - uint32_t ur_en:1; - uint32_t fe_en:1; - uint32_t nfe_en:1; - uint32_t ce_en:1; -#else - uint32_t ce_en:1; - uint32_t nfe_en:1; - uint32_t fe_en:1; - uint32_t ur_en:1; - uint32_t ro_en:1; - uint32_t mps:3; - uint32_t etf_en:1; - uint32_t pf_en:1; - uint32_t ap_en:1; - uint32_t ns_en:1; - uint32_t mrrs:3; - uint32_t reserved_15_15:1; - uint32_t ce_d:1; - uint32_t nfe_d:1; - uint32_t fe_d:1; - uint32_t ur_d:1; - uint32_t ap_d:1; - uint32_t tp:1; - uint32_t reserved_22_31:10; -#endif + __BITFIELD_FIELD(uint32_t reserved_22_31:10, + __BITFIELD_FIELD(uint32_t tp:1, + __BITFIELD_FIELD(uint32_t ap_d:1, + __BITFIELD_FIELD(uint32_t ur_d:1, + __BITFIELD_FIELD(uint32_t fe_d:1, + __BITFIELD_FIELD(uint32_t nfe_d:1, + __BITFIELD_FIELD(uint32_t ce_d:1, + __BITFIELD_FIELD(uint32_t reserved_15_15:1, + __BITFIELD_FIELD(uint32_t mrrs:3, + __BITFIELD_FIELD(uint32_t ns_en:1, + __BITFIELD_FIELD(uint32_t ap_en:1, + __BITFIELD_FIELD(uint32_t pf_en:1, + __BITFIELD_FIELD(uint32_t etf_en:1, + __BITFIELD_FIELD(uint32_t mps:3, + __BITFIELD_FIELD(uint32_t ro_en:1, + __BITFIELD_FIELD(uint32_t ur_en:1, + __BITFIELD_FIELD(uint32_t fe_en:1, + __BITFIELD_FIELD(uint32_t nfe_en:1, + __BITFIELD_FIELD(uint32_t ce_en:1, + ;))))))))))))))))))) } s; - struct cvmx_pciercx_cfg030_s cn52xx; - struct cvmx_pciercx_cfg030_s cn52xxp1; - struct cvmx_pciercx_cfg030_s cn56xx; - struct cvmx_pciercx_cfg030_s cn56xxp1; - struct cvmx_pciercx_cfg030_s cn61xx; - struct cvmx_pciercx_cfg030_s cn63xx; - struct cvmx_pciercx_cfg030_s cn63xxp1; - struct cvmx_pciercx_cfg030_s cn66xx; - struct cvmx_pciercx_cfg030_s cn68xx; - struct cvmx_pciercx_cfg030_s cn68xxp1; - struct cvmx_pciercx_cfg030_s cnf71xx; }; union cvmx_pciercx_cfg031 { uint32_t u32; struct cvmx_pciercx_cfg031_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t pnum:8; - uint32_t reserved_23_23:1; - uint32_t aspm:1; - uint32_t lbnc:1; - uint32_t dllarc:1; - uint32_t sderc:1; - uint32_t cpm:1; - uint32_t l1el:3; - uint32_t l0el:3; - uint32_t aslpms:2; - uint32_t mlw:6; - uint32_t mls:4; -#else - uint32_t mls:4; - uint32_t mlw:6; - uint32_t aslpms:2; - uint32_t l0el:3; - uint32_t l1el:3; - uint32_t cpm:1; - uint32_t sderc:1; - uint32_t dllarc:1; - uint32_t lbnc:1; - uint32_t aspm:1; - uint32_t reserved_23_23:1; - uint32_t pnum:8; -#endif + __BITFIELD_FIELD(uint32_t pnum:8, + __BITFIELD_FIELD(uint32_t reserved_23_23:1, + __BITFIELD_FIELD(uint32_t aspm:1, + __BITFIELD_FIELD(uint32_t lbnc:1, + __BITFIELD_FIELD(uint32_t dllarc:1, + __BITFIELD_FIELD(uint32_t sderc:1, + __BITFIELD_FIELD(uint32_t cpm:1, + __BITFIELD_FIELD(uint32_t l1el:3, + __BITFIELD_FIELD(uint32_t l0el:3, + __BITFIELD_FIELD(uint32_t aslpms:2, + __BITFIELD_FIELD(uint32_t mlw:6, + __BITFIELD_FIELD(uint32_t mls:4, + ;)))))))))))) } s; - struct cvmx_pciercx_cfg031_cn52xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t pnum:8; - uint32_t reserved_22_23:2; - uint32_t lbnc:1; - uint32_t dllarc:1; - uint32_t sderc:1; - uint32_t cpm:1; - uint32_t l1el:3; - uint32_t l0el:3; - uint32_t aslpms:2; - uint32_t mlw:6; - uint32_t mls:4; -#else - uint32_t mls:4; - uint32_t mlw:6; - uint32_t aslpms:2; - uint32_t l0el:3; - uint32_t l1el:3; - uint32_t cpm:1; - uint32_t sderc:1; - uint32_t dllarc:1; - uint32_t lbnc:1; - uint32_t reserved_22_23:2; - uint32_t pnum:8; -#endif - } cn52xx; - struct cvmx_pciercx_cfg031_cn52xx cn52xxp1; - struct cvmx_pciercx_cfg031_cn52xx cn56xx; - struct cvmx_pciercx_cfg031_cn52xx cn56xxp1; - struct cvmx_pciercx_cfg031_s cn61xx; - struct cvmx_pciercx_cfg031_cn52xx cn63xx; - struct cvmx_pciercx_cfg031_cn52xx cn63xxp1; - struct cvmx_pciercx_cfg031_s cn66xx; - struct cvmx_pciercx_cfg031_s cn68xx; - struct cvmx_pciercx_cfg031_cn52xx cn68xxp1; - struct cvmx_pciercx_cfg031_s cnf71xx; }; union cvmx_pciercx_cfg032 { uint32_t u32; struct cvmx_pciercx_cfg032_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t lab:1; - uint32_t lbm:1; - uint32_t dlla:1; - uint32_t scc:1; - uint32_t lt:1; - uint32_t reserved_26_26:1; - uint32_t nlw:6; - uint32_t ls:4; - uint32_t reserved_12_15:4; - uint32_t lab_int_enb:1; - uint32_t lbm_int_enb:1; - uint32_t hawd:1; - uint32_t ecpm:1; - uint32_t es:1; - uint32_t ccc:1; - uint32_t rl:1; - uint32_t ld:1; - uint32_t rcb:1; - uint32_t reserved_2_2:1; - uint32_t aslpc:2; -#else - uint32_t aslpc:2; - uint32_t reserved_2_2:1; - uint32_t rcb:1; - uint32_t ld:1; - uint32_t rl:1; - uint32_t ccc:1; - uint32_t es:1; - uint32_t ecpm:1; - uint32_t hawd:1; - uint32_t lbm_int_enb:1; - uint32_t lab_int_enb:1; - uint32_t reserved_12_15:4; - uint32_t ls:4; - uint32_t nlw:6; - uint32_t reserved_26_26:1; - uint32_t lt:1; - uint32_t scc:1; - uint32_t dlla:1; - uint32_t lbm:1; - uint32_t lab:1; -#endif - } s; - struct cvmx_pciercx_cfg032_s cn52xx; - struct cvmx_pciercx_cfg032_s cn52xxp1; - struct cvmx_pciercx_cfg032_s cn56xx; - struct cvmx_pciercx_cfg032_s cn56xxp1; - struct cvmx_pciercx_cfg032_s cn61xx; - struct cvmx_pciercx_cfg032_s cn63xx; - struct cvmx_pciercx_cfg032_s cn63xxp1; - struct cvmx_pciercx_cfg032_s cn66xx; - struct cvmx_pciercx_cfg032_s cn68xx; - struct cvmx_pciercx_cfg032_s cn68xxp1; - struct cvmx_pciercx_cfg032_s cnf71xx; -}; - -union cvmx_pciercx_cfg033 { - uint32_t u32; - struct cvmx_pciercx_cfg033_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t ps_num:13; - uint32_t nccs:1; - uint32_t emip:1; - uint32_t sp_ls:2; - uint32_t sp_lv:8; - uint32_t hp_c:1; - uint32_t hp_s:1; - uint32_t pip:1; - uint32_t aip:1; - uint32_t mrlsp:1; - uint32_t pcp:1; - uint32_t abp:1; -#else - uint32_t abp:1; - uint32_t pcp:1; - uint32_t mrlsp:1; - uint32_t aip:1; - uint32_t pip:1; - uint32_t hp_s:1; - uint32_t hp_c:1; - uint32_t sp_lv:8; - uint32_t sp_ls:2; - uint32_t emip:1; - uint32_t nccs:1; - uint32_t ps_num:13; -#endif + __BITFIELD_FIELD(uint32_t lab:1, + __BITFIELD_FIELD(uint32_t lbm:1, + __BITFIELD_FIELD(uint32_t dlla:1, + __BITFIELD_FIELD(uint32_t scc:1, + __BITFIELD_FIELD(uint32_t lt:1, + __BITFIELD_FIELD(uint32_t reserved_26_26:1, + __BITFIELD_FIELD(uint32_t nlw:6, + __BITFIELD_FIELD(uint32_t ls:4, + __BITFIELD_FIELD(uint32_t reserved_12_15:4, + __BITFIELD_FIELD(uint32_t lab_int_enb:1, + __BITFIELD_FIELD(uint32_t lbm_int_enb:1, + __BITFIELD_FIELD(uint32_t hawd:1, + __BITFIELD_FIELD(uint32_t ecpm:1, + __BITFIELD_FIELD(uint32_t es:1, + __BITFIELD_FIELD(uint32_t ccc:1, + __BITFIELD_FIELD(uint32_t rl:1, + __BITFIELD_FIELD(uint32_t ld:1, + __BITFIELD_FIELD(uint32_t rcb:1, + __BITFIELD_FIELD(uint32_t reserved_2_2:1, + __BITFIELD_FIELD(uint32_t aslpc:2, + ;)))))))))))))))))))) } s; - struct cvmx_pciercx_cfg033_s cn52xx; - struct cvmx_pciercx_cfg033_s cn52xxp1; - struct cvmx_pciercx_cfg033_s cn56xx; - struct cvmx_pciercx_cfg033_s cn56xxp1; - struct cvmx_pciercx_cfg033_s cn61xx; - struct cvmx_pciercx_cfg033_s cn63xx; - struct cvmx_pciercx_cfg033_s cn63xxp1; - struct cvmx_pciercx_cfg033_s cn66xx; - struct cvmx_pciercx_cfg033_s cn68xx; - struct cvmx_pciercx_cfg033_s cn68xxp1; - struct cvmx_pciercx_cfg033_s cnf71xx; }; union cvmx_pciercx_cfg034 { uint32_t u32; struct cvmx_pciercx_cfg034_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_25_31:7; - uint32_t dlls_c:1; - uint32_t emis:1; - uint32_t pds:1; - uint32_t mrlss:1; - uint32_t ccint_d:1; - uint32_t pd_c:1; - uint32_t mrls_c:1; - uint32_t pf_d:1; - uint32_t abp_d:1; - uint32_t reserved_13_15:3; - uint32_t dlls_en:1; - uint32_t emic:1; - uint32_t pcc:1; - uint32_t pic:2; - uint32_t aic:2; - uint32_t hpint_en:1; - uint32_t ccint_en:1; - uint32_t pd_en:1; - uint32_t mrls_en:1; - uint32_t pf_en:1; - uint32_t abp_en:1; -#else - uint32_t abp_en:1; - uint32_t pf_en:1; - uint32_t mrls_en:1; - uint32_t pd_en:1; - uint32_t ccint_en:1; - uint32_t hpint_en:1; - uint32_t aic:2; - uint32_t pic:2; - uint32_t pcc:1; - uint32_t emic:1; - uint32_t dlls_en:1; - uint32_t reserved_13_15:3; - uint32_t abp_d:1; - uint32_t pf_d:1; - uint32_t mrls_c:1; - uint32_t pd_c:1; - uint32_t ccint_d:1; - uint32_t mrlss:1; - uint32_t pds:1; - uint32_t emis:1; - uint32_t dlls_c:1; - uint32_t reserved_25_31:7; -#endif + __BITFIELD_FIELD(uint32_t reserved_25_31:7, + __BITFIELD_FIELD(uint32_t dlls_c:1, + __BITFIELD_FIELD(uint32_t emis:1, + __BITFIELD_FIELD(uint32_t pds:1, + __BITFIELD_FIELD(uint32_t mrlss:1, + __BITFIELD_FIELD(uint32_t ccint_d:1, + __BITFIELD_FIELD(uint32_t pd_c:1, + __BITFIELD_FIELD(uint32_t mrls_c:1, + __BITFIELD_FIELD(uint32_t pf_d:1, + __BITFIELD_FIELD(uint32_t abp_d:1, + __BITFIELD_FIELD(uint32_t reserved_13_15:3, + __BITFIELD_FIELD(uint32_t dlls_en:1, + __BITFIELD_FIELD(uint32_t emic:1, + __BITFIELD_FIELD(uint32_t pcc:1, + __BITFIELD_FIELD(uint32_t pic:1, + __BITFIELD_FIELD(uint32_t aic:1, + __BITFIELD_FIELD(uint32_t hpint_en:1, + __BITFIELD_FIELD(uint32_t ccint_en:1, + __BITFIELD_FIELD(uint32_t pd_en:1, + __BITFIELD_FIELD(uint32_t mrls_en:1, + __BITFIELD_FIELD(uint32_t pf_en:1, + __BITFIELD_FIELD(uint32_t abp_en:1, + ;)))))))))))))))))))))) } s; - struct cvmx_pciercx_cfg034_s cn52xx; - struct cvmx_pciercx_cfg034_s cn52xxp1; - struct cvmx_pciercx_cfg034_s cn56xx; - struct cvmx_pciercx_cfg034_s cn56xxp1; - struct cvmx_pciercx_cfg034_s cn61xx; - struct cvmx_pciercx_cfg034_s cn63xx; - struct cvmx_pciercx_cfg034_s cn63xxp1; - struct cvmx_pciercx_cfg034_s cn66xx; - struct cvmx_pciercx_cfg034_s cn68xx; - struct cvmx_pciercx_cfg034_s cn68xxp1; - struct cvmx_pciercx_cfg034_s cnf71xx; }; union cvmx_pciercx_cfg035 { uint32_t u32; struct cvmx_pciercx_cfg035_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_17_31:15; - uint32_t crssv:1; - uint32_t reserved_5_15:11; - uint32_t crssve:1; - uint32_t pmeie:1; - uint32_t sefee:1; - uint32_t senfee:1; - uint32_t secee:1; -#else - uint32_t secee:1; - uint32_t senfee:1; - uint32_t sefee:1; - uint32_t pmeie:1; - uint32_t crssve:1; - uint32_t reserved_5_15:11; - uint32_t crssv:1; - uint32_t reserved_17_31:15; -#endif - } s; - struct cvmx_pciercx_cfg035_s cn52xx; - struct cvmx_pciercx_cfg035_s cn52xxp1; - struct cvmx_pciercx_cfg035_s cn56xx; - struct cvmx_pciercx_cfg035_s cn56xxp1; - struct cvmx_pciercx_cfg035_s cn61xx; - struct cvmx_pciercx_cfg035_s cn63xx; - struct cvmx_pciercx_cfg035_s cn63xxp1; - struct cvmx_pciercx_cfg035_s cn66xx; - struct cvmx_pciercx_cfg035_s cn68xx; - struct cvmx_pciercx_cfg035_s cn68xxp1; - struct cvmx_pciercx_cfg035_s cnf71xx; -}; - -union cvmx_pciercx_cfg036 { - uint32_t u32; - struct cvmx_pciercx_cfg036_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_18_31:14; - uint32_t pme_pend:1; - uint32_t pme_stat:1; - uint32_t pme_rid:16; -#else - uint32_t pme_rid:16; - uint32_t pme_stat:1; - uint32_t pme_pend:1; - uint32_t reserved_18_31:14; -#endif - } s; - struct cvmx_pciercx_cfg036_s cn52xx; - struct cvmx_pciercx_cfg036_s cn52xxp1; - struct cvmx_pciercx_cfg036_s cn56xx; - struct cvmx_pciercx_cfg036_s cn56xxp1; - struct cvmx_pciercx_cfg036_s cn61xx; - struct cvmx_pciercx_cfg036_s cn63xx; - struct cvmx_pciercx_cfg036_s cn63xxp1; - struct cvmx_pciercx_cfg036_s cn66xx; - struct cvmx_pciercx_cfg036_s cn68xx; - struct cvmx_pciercx_cfg036_s cn68xxp1; - struct cvmx_pciercx_cfg036_s cnf71xx; -}; - -union cvmx_pciercx_cfg037 { - uint32_t u32; - struct cvmx_pciercx_cfg037_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_20_31:12; - uint32_t obffs:2; - uint32_t reserved_12_17:6; - uint32_t ltrs:1; - uint32_t noroprpr:1; - uint32_t atom128s:1; - uint32_t atom64s:1; - uint32_t atom32s:1; - uint32_t atom_ops:1; - uint32_t reserved_5_5:1; - uint32_t ctds:1; - uint32_t ctrs:4; -#else - uint32_t ctrs:4; - uint32_t ctds:1; - uint32_t reserved_5_5:1; - uint32_t atom_ops:1; - uint32_t atom32s:1; - uint32_t atom64s:1; - uint32_t atom128s:1; - uint32_t noroprpr:1; - uint32_t ltrs:1; - uint32_t reserved_12_17:6; - uint32_t obffs:2; - uint32_t reserved_20_31:12; -#endif - } s; - struct cvmx_pciercx_cfg037_cn52xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_5_31:27; - uint32_t ctds:1; - uint32_t ctrs:4; -#else - uint32_t ctrs:4; - uint32_t ctds:1; - uint32_t reserved_5_31:27; -#endif - } cn52xx; - struct cvmx_pciercx_cfg037_cn52xx cn52xxp1; - struct cvmx_pciercx_cfg037_cn52xx cn56xx; - struct cvmx_pciercx_cfg037_cn52xx cn56xxp1; - struct cvmx_pciercx_cfg037_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_14_31:18; - uint32_t tph:2; - uint32_t reserved_11_11:1; - uint32_t noroprpr:1; - uint32_t atom128s:1; - uint32_t atom64s:1; - uint32_t atom32s:1; - uint32_t atom_ops:1; - uint32_t ari_fw:1; - uint32_t ctds:1; - uint32_t ctrs:4; -#else - uint32_t ctrs:4; - uint32_t ctds:1; - uint32_t ari_fw:1; - uint32_t atom_ops:1; - uint32_t atom32s:1; - uint32_t atom64s:1; - uint32_t atom128s:1; - uint32_t noroprpr:1; - uint32_t reserved_11_11:1; - uint32_t tph:2; - uint32_t reserved_14_31:18; -#endif - } cn61xx; - struct cvmx_pciercx_cfg037_cn52xx cn63xx; - struct cvmx_pciercx_cfg037_cn52xx cn63xxp1; - struct cvmx_pciercx_cfg037_cn66xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_14_31:18; - uint32_t tph:2; - uint32_t reserved_11_11:1; - uint32_t noroprpr:1; - uint32_t atom128s:1; - uint32_t atom64s:1; - uint32_t atom32s:1; - uint32_t atom_ops:1; - uint32_t ari:1; - uint32_t ctds:1; - uint32_t ctrs:4; -#else - uint32_t ctrs:4; - uint32_t ctds:1; - uint32_t ari:1; - uint32_t atom_ops:1; - uint32_t atom32s:1; - uint32_t atom64s:1; - uint32_t atom128s:1; - uint32_t noroprpr:1; - uint32_t reserved_11_11:1; - uint32_t tph:2; - uint32_t reserved_14_31:18; -#endif - } cn66xx; - struct cvmx_pciercx_cfg037_cn66xx cn68xx; - struct cvmx_pciercx_cfg037_cn66xx cn68xxp1; - struct cvmx_pciercx_cfg037_cnf71xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_20_31:12; - uint32_t obffs:2; - uint32_t reserved_14_17:4; - uint32_t tphs:2; - uint32_t ltrs:1; - uint32_t noroprpr:1; - uint32_t atom128s:1; - uint32_t atom64s:1; - uint32_t atom32s:1; - uint32_t atom_ops:1; - uint32_t ari_fw:1; - uint32_t ctds:1; - uint32_t ctrs:4; -#else - uint32_t ctrs:4; - uint32_t ctds:1; - uint32_t ari_fw:1; - uint32_t atom_ops:1; - uint32_t atom32s:1; - uint32_t atom64s:1; - uint32_t atom128s:1; - uint32_t noroprpr:1; - uint32_t ltrs:1; - uint32_t tphs:2; - uint32_t reserved_14_17:4; - uint32_t obffs:2; - uint32_t reserved_20_31:12; -#endif - } cnf71xx; -}; - -union cvmx_pciercx_cfg038 { - uint32_t u32; - struct cvmx_pciercx_cfg038_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_15_31:17; - uint32_t obffe:2; - uint32_t reserved_11_12:2; - uint32_t ltre:1; - uint32_t id0_cp:1; - uint32_t id0_rq:1; - uint32_t atom_op_eb:1; - uint32_t atom_op:1; - uint32_t ari:1; - uint32_t ctd:1; - uint32_t ctv:4; -#else - uint32_t ctv:4; - uint32_t ctd:1; - uint32_t ari:1; - uint32_t atom_op:1; - uint32_t atom_op_eb:1; - uint32_t id0_rq:1; - uint32_t id0_cp:1; - uint32_t ltre:1; - uint32_t reserved_11_12:2; - uint32_t obffe:2; - uint32_t reserved_15_31:17; -#endif + __BITFIELD_FIELD(uint32_t reserved_17_31:15, + __BITFIELD_FIELD(uint32_t crssv:1, + __BITFIELD_FIELD(uint32_t reserved_5_15:11, + __BITFIELD_FIELD(uint32_t crssve:1, + __BITFIELD_FIELD(uint32_t pmeie:1, + __BITFIELD_FIELD(uint32_t sefee:1, + __BITFIELD_FIELD(uint32_t senfee:1, + __BITFIELD_FIELD(uint32_t secee:1, + ;)))))))) } s; - struct cvmx_pciercx_cfg038_cn52xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_5_31:27; - uint32_t ctd:1; - uint32_t ctv:4; -#else - uint32_t ctv:4; - uint32_t ctd:1; - uint32_t reserved_5_31:27; -#endif - } cn52xx; - struct cvmx_pciercx_cfg038_cn52xx cn52xxp1; - struct cvmx_pciercx_cfg038_cn52xx cn56xx; - struct cvmx_pciercx_cfg038_cn52xx cn56xxp1; - struct cvmx_pciercx_cfg038_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_10_31:22; - uint32_t id0_cp:1; - uint32_t id0_rq:1; - uint32_t atom_op_eb:1; - uint32_t atom_op:1; - uint32_t ari:1; - uint32_t ctd:1; - uint32_t ctv:4; -#else - uint32_t ctv:4; - uint32_t ctd:1; - uint32_t ari:1; - uint32_t atom_op:1; - uint32_t atom_op_eb:1; - uint32_t id0_rq:1; - uint32_t id0_cp:1; - uint32_t reserved_10_31:22; -#endif - } cn61xx; - struct cvmx_pciercx_cfg038_cn52xx cn63xx; - struct cvmx_pciercx_cfg038_cn52xx cn63xxp1; - struct cvmx_pciercx_cfg038_cn61xx cn66xx; - struct cvmx_pciercx_cfg038_cn61xx cn68xx; - struct cvmx_pciercx_cfg038_cn61xx cn68xxp1; - struct cvmx_pciercx_cfg038_s cnf71xx; -}; - -union cvmx_pciercx_cfg039 { - uint32_t u32; - struct cvmx_pciercx_cfg039_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_9_31:23; - uint32_t cls:1; - uint32_t slsv:7; - uint32_t reserved_0_0:1; -#else - uint32_t reserved_0_0:1; - uint32_t slsv:7; - uint32_t cls:1; - uint32_t reserved_9_31:23; -#endif - } s; - struct cvmx_pciercx_cfg039_cn52xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_0_31:32; -#else - uint32_t reserved_0_31:32; -#endif - } cn52xx; - struct cvmx_pciercx_cfg039_cn52xx cn52xxp1; - struct cvmx_pciercx_cfg039_cn52xx cn56xx; - struct cvmx_pciercx_cfg039_cn52xx cn56xxp1; - struct cvmx_pciercx_cfg039_s cn61xx; - struct cvmx_pciercx_cfg039_s cn63xx; - struct cvmx_pciercx_cfg039_cn52xx cn63xxp1; - struct cvmx_pciercx_cfg039_s cn66xx; - struct cvmx_pciercx_cfg039_s cn68xx; - struct cvmx_pciercx_cfg039_s cn68xxp1; - struct cvmx_pciercx_cfg039_s cnf71xx; }; union cvmx_pciercx_cfg040 { uint32_t u32; struct cvmx_pciercx_cfg040_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_17_31:15; - uint32_t cdl:1; - uint32_t reserved_13_15:3; - uint32_t cde:1; - uint32_t csos:1; - uint32_t emc:1; - uint32_t tm:3; - uint32_t sde:1; - uint32_t hasd:1; - uint32_t ec:1; - uint32_t tls:4; -#else - uint32_t tls:4; - uint32_t ec:1; - uint32_t hasd:1; - uint32_t sde:1; - uint32_t tm:3; - uint32_t emc:1; - uint32_t csos:1; - uint32_t cde:1; - uint32_t reserved_13_15:3; - uint32_t cdl:1; - uint32_t reserved_17_31:15; -#endif - } s; - struct cvmx_pciercx_cfg040_cn52xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_0_31:32; -#else - uint32_t reserved_0_31:32; -#endif - } cn52xx; - struct cvmx_pciercx_cfg040_cn52xx cn52xxp1; - struct cvmx_pciercx_cfg040_cn52xx cn56xx; - struct cvmx_pciercx_cfg040_cn52xx cn56xxp1; - struct cvmx_pciercx_cfg040_s cn61xx; - struct cvmx_pciercx_cfg040_s cn63xx; - struct cvmx_pciercx_cfg040_s cn63xxp1; - struct cvmx_pciercx_cfg040_s cn66xx; - struct cvmx_pciercx_cfg040_s cn68xx; - struct cvmx_pciercx_cfg040_s cn68xxp1; - struct cvmx_pciercx_cfg040_s cnf71xx; -}; - -union cvmx_pciercx_cfg041 { - uint32_t u32; - struct cvmx_pciercx_cfg041_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_0_31:32; -#else - uint32_t reserved_0_31:32; -#endif - } s; - struct cvmx_pciercx_cfg041_s cn52xx; - struct cvmx_pciercx_cfg041_s cn52xxp1; - struct cvmx_pciercx_cfg041_s cn56xx; - struct cvmx_pciercx_cfg041_s cn56xxp1; - struct cvmx_pciercx_cfg041_s cn61xx; - struct cvmx_pciercx_cfg041_s cn63xx; - struct cvmx_pciercx_cfg041_s cn63xxp1; - struct cvmx_pciercx_cfg041_s cn66xx; - struct cvmx_pciercx_cfg041_s cn68xx; - struct cvmx_pciercx_cfg041_s cn68xxp1; - struct cvmx_pciercx_cfg041_s cnf71xx; -}; - -union cvmx_pciercx_cfg042 { - uint32_t u32; - struct cvmx_pciercx_cfg042_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_0_31:32; -#else - uint32_t reserved_0_31:32; -#endif + __BITFIELD_FIELD(uint32_t reserved_22_31:10, + __BITFIELD_FIELD(uint32_t ler:1, + __BITFIELD_FIELD(uint32_t ep3s:1, + __BITFIELD_FIELD(uint32_t ep2s:1, + __BITFIELD_FIELD(uint32_t ep1s:1, + __BITFIELD_FIELD(uint32_t eqc:1, + __BITFIELD_FIELD(uint32_t cdl:1, + __BITFIELD_FIELD(uint32_t cde:4, + __BITFIELD_FIELD(uint32_t csos:1, + __BITFIELD_FIELD(uint32_t emc:1, + __BITFIELD_FIELD(uint32_t tm:3, + __BITFIELD_FIELD(uint32_t sde:1, + __BITFIELD_FIELD(uint32_t hasd:1, + __BITFIELD_FIELD(uint32_t ec:1, + __BITFIELD_FIELD(uint32_t tls:4, + ;))))))))))))))) } s; - struct cvmx_pciercx_cfg042_s cn52xx; - struct cvmx_pciercx_cfg042_s cn52xxp1; - struct cvmx_pciercx_cfg042_s cn56xx; - struct cvmx_pciercx_cfg042_s cn56xxp1; - struct cvmx_pciercx_cfg042_s cn61xx; - struct cvmx_pciercx_cfg042_s cn63xx; - struct cvmx_pciercx_cfg042_s cn63xxp1; - struct cvmx_pciercx_cfg042_s cn66xx; - struct cvmx_pciercx_cfg042_s cn68xx; - struct cvmx_pciercx_cfg042_s cn68xxp1; - struct cvmx_pciercx_cfg042_s cnf71xx; -}; - -union cvmx_pciercx_cfg064 { - uint32_t u32; - struct cvmx_pciercx_cfg064_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t nco:12; - uint32_t cv:4; - uint32_t pcieec:16; -#else - uint32_t pcieec:16; - uint32_t cv:4; - uint32_t nco:12; -#endif - } s; - struct cvmx_pciercx_cfg064_s cn52xx; - struct cvmx_pciercx_cfg064_s cn52xxp1; - struct cvmx_pciercx_cfg064_s cn56xx; - struct cvmx_pciercx_cfg064_s cn56xxp1; - struct cvmx_pciercx_cfg064_s cn61xx; - struct cvmx_pciercx_cfg064_s cn63xx; - struct cvmx_pciercx_cfg064_s cn63xxp1; - struct cvmx_pciercx_cfg064_s cn66xx; - struct cvmx_pciercx_cfg064_s cn68xx; - struct cvmx_pciercx_cfg064_s cn68xxp1; - struct cvmx_pciercx_cfg064_s cnf71xx; -}; - -union cvmx_pciercx_cfg065 { - uint32_t u32; - struct cvmx_pciercx_cfg065_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_25_31:7; - uint32_t uatombs:1; - uint32_t reserved_23_23:1; - uint32_t ucies:1; - uint32_t reserved_21_21:1; - uint32_t ures:1; - uint32_t ecrces:1; - uint32_t mtlps:1; - uint32_t ros:1; - uint32_t ucs:1; - uint32_t cas:1; - uint32_t cts:1; - uint32_t fcpes:1; - uint32_t ptlps:1; - uint32_t reserved_6_11:6; - uint32_t sdes:1; - uint32_t dlpes:1; - uint32_t reserved_0_3:4; -#else - uint32_t reserved_0_3:4; - uint32_t dlpes:1; - uint32_t sdes:1; - uint32_t reserved_6_11:6; - uint32_t ptlps:1; - uint32_t fcpes:1; - uint32_t cts:1; - uint32_t cas:1; - uint32_t ucs:1; - uint32_t ros:1; - uint32_t mtlps:1; - uint32_t ecrces:1; - uint32_t ures:1; - uint32_t reserved_21_21:1; - uint32_t ucies:1; - uint32_t reserved_23_23:1; - uint32_t uatombs:1; - uint32_t reserved_25_31:7; -#endif - } s; - struct cvmx_pciercx_cfg065_cn52xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_21_31:11; - uint32_t ures:1; - uint32_t ecrces:1; - uint32_t mtlps:1; - uint32_t ros:1; - uint32_t ucs:1; - uint32_t cas:1; - uint32_t cts:1; - uint32_t fcpes:1; - uint32_t ptlps:1; - uint32_t reserved_6_11:6; - uint32_t sdes:1; - uint32_t dlpes:1; - uint32_t reserved_0_3:4; -#else - uint32_t reserved_0_3:4; - uint32_t dlpes:1; - uint32_t sdes:1; - uint32_t reserved_6_11:6; - uint32_t ptlps:1; - uint32_t fcpes:1; - uint32_t cts:1; - uint32_t cas:1; - uint32_t ucs:1; - uint32_t ros:1; - uint32_t mtlps:1; - uint32_t ecrces:1; - uint32_t ures:1; - uint32_t reserved_21_31:11; -#endif - } cn52xx; - struct cvmx_pciercx_cfg065_cn52xx cn52xxp1; - struct cvmx_pciercx_cfg065_cn52xx cn56xx; - struct cvmx_pciercx_cfg065_cn52xx cn56xxp1; - struct cvmx_pciercx_cfg065_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_25_31:7; - uint32_t uatombs:1; - uint32_t reserved_21_23:3; - uint32_t ures:1; - uint32_t ecrces:1; - uint32_t mtlps:1; - uint32_t ros:1; - uint32_t ucs:1; - uint32_t cas:1; - uint32_t cts:1; - uint32_t fcpes:1; - uint32_t ptlps:1; - uint32_t reserved_6_11:6; - uint32_t sdes:1; - uint32_t dlpes:1; - uint32_t reserved_0_3:4; -#else - uint32_t reserved_0_3:4; - uint32_t dlpes:1; - uint32_t sdes:1; - uint32_t reserved_6_11:6; - uint32_t ptlps:1; - uint32_t fcpes:1; - uint32_t cts:1; - uint32_t cas:1; - uint32_t ucs:1; - uint32_t ros:1; - uint32_t mtlps:1; - uint32_t ecrces:1; - uint32_t ures:1; - uint32_t reserved_21_23:3; - uint32_t uatombs:1; - uint32_t reserved_25_31:7; -#endif - } cn61xx; - struct cvmx_pciercx_cfg065_cn52xx cn63xx; - struct cvmx_pciercx_cfg065_cn52xx cn63xxp1; - struct cvmx_pciercx_cfg065_cn61xx cn66xx; - struct cvmx_pciercx_cfg065_cn61xx cn68xx; - struct cvmx_pciercx_cfg065_cn52xx cn68xxp1; - struct cvmx_pciercx_cfg065_s cnf71xx; -}; - -union cvmx_pciercx_cfg066 { - uint32_t u32; - struct cvmx_pciercx_cfg066_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_25_31:7; - uint32_t uatombm:1; - uint32_t reserved_23_23:1; - uint32_t uciem:1; - uint32_t reserved_21_21:1; - uint32_t urem:1; - uint32_t ecrcem:1; - uint32_t mtlpm:1; - uint32_t rom:1; - uint32_t ucm:1; - uint32_t cam:1; - uint32_t ctm:1; - uint32_t fcpem:1; - uint32_t ptlpm:1; - uint32_t reserved_6_11:6; - uint32_t sdem:1; - uint32_t dlpem:1; - uint32_t reserved_0_3:4; -#else - uint32_t reserved_0_3:4; - uint32_t dlpem:1; - uint32_t sdem:1; - uint32_t reserved_6_11:6; - uint32_t ptlpm:1; - uint32_t fcpem:1; - uint32_t ctm:1; - uint32_t cam:1; - uint32_t ucm:1; - uint32_t rom:1; - uint32_t mtlpm:1; - uint32_t ecrcem:1; - uint32_t urem:1; - uint32_t reserved_21_21:1; - uint32_t uciem:1; - uint32_t reserved_23_23:1; - uint32_t uatombm:1; - uint32_t reserved_25_31:7; -#endif - } s; - struct cvmx_pciercx_cfg066_cn52xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_21_31:11; - uint32_t urem:1; - uint32_t ecrcem:1; - uint32_t mtlpm:1; - uint32_t rom:1; - uint32_t ucm:1; - uint32_t cam:1; - uint32_t ctm:1; - uint32_t fcpem:1; - uint32_t ptlpm:1; - uint32_t reserved_6_11:6; - uint32_t sdem:1; - uint32_t dlpem:1; - uint32_t reserved_0_3:4; -#else - uint32_t reserved_0_3:4; - uint32_t dlpem:1; - uint32_t sdem:1; - uint32_t reserved_6_11:6; - uint32_t ptlpm:1; - uint32_t fcpem:1; - uint32_t ctm:1; - uint32_t cam:1; - uint32_t ucm:1; - uint32_t rom:1; - uint32_t mtlpm:1; - uint32_t ecrcem:1; - uint32_t urem:1; - uint32_t reserved_21_31:11; -#endif - } cn52xx; - struct cvmx_pciercx_cfg066_cn52xx cn52xxp1; - struct cvmx_pciercx_cfg066_cn52xx cn56xx; - struct cvmx_pciercx_cfg066_cn52xx cn56xxp1; - struct cvmx_pciercx_cfg066_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_25_31:7; - uint32_t uatombm:1; - uint32_t reserved_21_23:3; - uint32_t urem:1; - uint32_t ecrcem:1; - uint32_t mtlpm:1; - uint32_t rom:1; - uint32_t ucm:1; - uint32_t cam:1; - uint32_t ctm:1; - uint32_t fcpem:1; - uint32_t ptlpm:1; - uint32_t reserved_6_11:6; - uint32_t sdem:1; - uint32_t dlpem:1; - uint32_t reserved_0_3:4; -#else - uint32_t reserved_0_3:4; - uint32_t dlpem:1; - uint32_t sdem:1; - uint32_t reserved_6_11:6; - uint32_t ptlpm:1; - uint32_t fcpem:1; - uint32_t ctm:1; - uint32_t cam:1; - uint32_t ucm:1; - uint32_t rom:1; - uint32_t mtlpm:1; - uint32_t ecrcem:1; - uint32_t urem:1; - uint32_t reserved_21_23:3; - uint32_t uatombm:1; - uint32_t reserved_25_31:7; -#endif - } cn61xx; - struct cvmx_pciercx_cfg066_cn52xx cn63xx; - struct cvmx_pciercx_cfg066_cn52xx cn63xxp1; - struct cvmx_pciercx_cfg066_cn61xx cn66xx; - struct cvmx_pciercx_cfg066_cn61xx cn68xx; - struct cvmx_pciercx_cfg066_cn52xx cn68xxp1; - struct cvmx_pciercx_cfg066_s cnf71xx; -}; - -union cvmx_pciercx_cfg067 { - uint32_t u32; - struct cvmx_pciercx_cfg067_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_25_31:7; - uint32_t uatombs:1; - uint32_t reserved_23_23:1; - uint32_t ucies:1; - uint32_t reserved_21_21:1; - uint32_t ures:1; - uint32_t ecrces:1; - uint32_t mtlps:1; - uint32_t ros:1; - uint32_t ucs:1; - uint32_t cas:1; - uint32_t cts:1; - uint32_t fcpes:1; - uint32_t ptlps:1; - uint32_t reserved_6_11:6; - uint32_t sdes:1; - uint32_t dlpes:1; - uint32_t reserved_0_3:4; -#else - uint32_t reserved_0_3:4; - uint32_t dlpes:1; - uint32_t sdes:1; - uint32_t reserved_6_11:6; - uint32_t ptlps:1; - uint32_t fcpes:1; - uint32_t cts:1; - uint32_t cas:1; - uint32_t ucs:1; - uint32_t ros:1; - uint32_t mtlps:1; - uint32_t ecrces:1; - uint32_t ures:1; - uint32_t reserved_21_21:1; - uint32_t ucies:1; - uint32_t reserved_23_23:1; - uint32_t uatombs:1; - uint32_t reserved_25_31:7; -#endif - } s; - struct cvmx_pciercx_cfg067_cn52xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_21_31:11; - uint32_t ures:1; - uint32_t ecrces:1; - uint32_t mtlps:1; - uint32_t ros:1; - uint32_t ucs:1; - uint32_t cas:1; - uint32_t cts:1; - uint32_t fcpes:1; - uint32_t ptlps:1; - uint32_t reserved_6_11:6; - uint32_t sdes:1; - uint32_t dlpes:1; - uint32_t reserved_0_3:4; -#else - uint32_t reserved_0_3:4; - uint32_t dlpes:1; - uint32_t sdes:1; - uint32_t reserved_6_11:6; - uint32_t ptlps:1; - uint32_t fcpes:1; - uint32_t cts:1; - uint32_t cas:1; - uint32_t ucs:1; - uint32_t ros:1; - uint32_t mtlps:1; - uint32_t ecrces:1; - uint32_t ures:1; - uint32_t reserved_21_31:11; -#endif - } cn52xx; - struct cvmx_pciercx_cfg067_cn52xx cn52xxp1; - struct cvmx_pciercx_cfg067_cn52xx cn56xx; - struct cvmx_pciercx_cfg067_cn52xx cn56xxp1; - struct cvmx_pciercx_cfg067_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_25_31:7; - uint32_t uatombs:1; - uint32_t reserved_21_23:3; - uint32_t ures:1; - uint32_t ecrces:1; - uint32_t mtlps:1; - uint32_t ros:1; - uint32_t ucs:1; - uint32_t cas:1; - uint32_t cts:1; - uint32_t fcpes:1; - uint32_t ptlps:1; - uint32_t reserved_6_11:6; - uint32_t sdes:1; - uint32_t dlpes:1; - uint32_t reserved_0_3:4; -#else - uint32_t reserved_0_3:4; - uint32_t dlpes:1; - uint32_t sdes:1; - uint32_t reserved_6_11:6; - uint32_t ptlps:1; - uint32_t fcpes:1; - uint32_t cts:1; - uint32_t cas:1; - uint32_t ucs:1; - uint32_t ros:1; - uint32_t mtlps:1; - uint32_t ecrces:1; - uint32_t ures:1; - uint32_t reserved_21_23:3; - uint32_t uatombs:1; - uint32_t reserved_25_31:7; -#endif - } cn61xx; - struct cvmx_pciercx_cfg067_cn52xx cn63xx; - struct cvmx_pciercx_cfg067_cn52xx cn63xxp1; - struct cvmx_pciercx_cfg067_cn61xx cn66xx; - struct cvmx_pciercx_cfg067_cn61xx cn68xx; - struct cvmx_pciercx_cfg067_cn52xx cn68xxp1; - struct cvmx_pciercx_cfg067_s cnf71xx; -}; - -union cvmx_pciercx_cfg068 { - uint32_t u32; - struct cvmx_pciercx_cfg068_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_15_31:17; - uint32_t cies:1; - uint32_t anfes:1; - uint32_t rtts:1; - uint32_t reserved_9_11:3; - uint32_t rnrs:1; - uint32_t bdllps:1; - uint32_t btlps:1; - uint32_t reserved_1_5:5; - uint32_t res:1; -#else - uint32_t res:1; - uint32_t reserved_1_5:5; - uint32_t btlps:1; - uint32_t bdllps:1; - uint32_t rnrs:1; - uint32_t reserved_9_11:3; - uint32_t rtts:1; - uint32_t anfes:1; - uint32_t cies:1; - uint32_t reserved_15_31:17; -#endif - } s; - struct cvmx_pciercx_cfg068_cn52xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_14_31:18; - uint32_t anfes:1; - uint32_t rtts:1; - uint32_t reserved_9_11:3; - uint32_t rnrs:1; - uint32_t bdllps:1; - uint32_t btlps:1; - uint32_t reserved_1_5:5; - uint32_t res:1; -#else - uint32_t res:1; - uint32_t reserved_1_5:5; - uint32_t btlps:1; - uint32_t bdllps:1; - uint32_t rnrs:1; - uint32_t reserved_9_11:3; - uint32_t rtts:1; - uint32_t anfes:1; - uint32_t reserved_14_31:18; -#endif - } cn52xx; - struct cvmx_pciercx_cfg068_cn52xx cn52xxp1; - struct cvmx_pciercx_cfg068_cn52xx cn56xx; - struct cvmx_pciercx_cfg068_cn52xx cn56xxp1; - struct cvmx_pciercx_cfg068_cn52xx cn61xx; - struct cvmx_pciercx_cfg068_cn52xx cn63xx; - struct cvmx_pciercx_cfg068_cn52xx cn63xxp1; - struct cvmx_pciercx_cfg068_cn52xx cn66xx; - struct cvmx_pciercx_cfg068_cn52xx cn68xx; - struct cvmx_pciercx_cfg068_cn52xx cn68xxp1; - struct cvmx_pciercx_cfg068_s cnf71xx; -}; - -union cvmx_pciercx_cfg069 { - uint32_t u32; - struct cvmx_pciercx_cfg069_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_15_31:17; - uint32_t ciem:1; - uint32_t anfem:1; - uint32_t rttm:1; - uint32_t reserved_9_11:3; - uint32_t rnrm:1; - uint32_t bdllpm:1; - uint32_t btlpm:1; - uint32_t reserved_1_5:5; - uint32_t rem:1; -#else - uint32_t rem:1; - uint32_t reserved_1_5:5; - uint32_t btlpm:1; - uint32_t bdllpm:1; - uint32_t rnrm:1; - uint32_t reserved_9_11:3; - uint32_t rttm:1; - uint32_t anfem:1; - uint32_t ciem:1; - uint32_t reserved_15_31:17; -#endif - } s; - struct cvmx_pciercx_cfg069_cn52xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_14_31:18; - uint32_t anfem:1; - uint32_t rttm:1; - uint32_t reserved_9_11:3; - uint32_t rnrm:1; - uint32_t bdllpm:1; - uint32_t btlpm:1; - uint32_t reserved_1_5:5; - uint32_t rem:1; -#else - uint32_t rem:1; - uint32_t reserved_1_5:5; - uint32_t btlpm:1; - uint32_t bdllpm:1; - uint32_t rnrm:1; - uint32_t reserved_9_11:3; - uint32_t rttm:1; - uint32_t anfem:1; - uint32_t reserved_14_31:18; -#endif - } cn52xx; - struct cvmx_pciercx_cfg069_cn52xx cn52xxp1; - struct cvmx_pciercx_cfg069_cn52xx cn56xx; - struct cvmx_pciercx_cfg069_cn52xx cn56xxp1; - struct cvmx_pciercx_cfg069_cn52xx cn61xx; - struct cvmx_pciercx_cfg069_cn52xx cn63xx; - struct cvmx_pciercx_cfg069_cn52xx cn63xxp1; - struct cvmx_pciercx_cfg069_cn52xx cn66xx; - struct cvmx_pciercx_cfg069_cn52xx cn68xx; - struct cvmx_pciercx_cfg069_cn52xx cn68xxp1; - struct cvmx_pciercx_cfg069_s cnf71xx; }; union cvmx_pciercx_cfg070 { uint32_t u32; struct cvmx_pciercx_cfg070_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_9_31:23; - uint32_t ce:1; - uint32_t cc:1; - uint32_t ge:1; - uint32_t gc:1; - uint32_t fep:5; -#else - uint32_t fep:5; - uint32_t gc:1; - uint32_t ge:1; - uint32_t cc:1; - uint32_t ce:1; - uint32_t reserved_9_31:23; -#endif - } s; - struct cvmx_pciercx_cfg070_s cn52xx; - struct cvmx_pciercx_cfg070_s cn52xxp1; - struct cvmx_pciercx_cfg070_s cn56xx; - struct cvmx_pciercx_cfg070_s cn56xxp1; - struct cvmx_pciercx_cfg070_s cn61xx; - struct cvmx_pciercx_cfg070_s cn63xx; - struct cvmx_pciercx_cfg070_s cn63xxp1; - struct cvmx_pciercx_cfg070_s cn66xx; - struct cvmx_pciercx_cfg070_s cn68xx; - struct cvmx_pciercx_cfg070_s cn68xxp1; - struct cvmx_pciercx_cfg070_s cnf71xx; -}; - -union cvmx_pciercx_cfg071 { - uint32_t u32; - struct cvmx_pciercx_cfg071_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t dword1:32; -#else - uint32_t dword1:32; -#endif + __BITFIELD_FIELD(uint32_t reserved_12_31:20, + __BITFIELD_FIELD(uint32_t tplp:1, + __BITFIELD_FIELD(uint32_t reserved_9_10:2, + __BITFIELD_FIELD(uint32_t ce:1, + __BITFIELD_FIELD(uint32_t cc:1, + __BITFIELD_FIELD(uint32_t ge:1, + __BITFIELD_FIELD(uint32_t gc:1, + __BITFIELD_FIELD(uint32_t fep:5, + ;)))))))) } s; - struct cvmx_pciercx_cfg071_s cn52xx; - struct cvmx_pciercx_cfg071_s cn52xxp1; - struct cvmx_pciercx_cfg071_s cn56xx; - struct cvmx_pciercx_cfg071_s cn56xxp1; - struct cvmx_pciercx_cfg071_s cn61xx; - struct cvmx_pciercx_cfg071_s cn63xx; - struct cvmx_pciercx_cfg071_s cn63xxp1; - struct cvmx_pciercx_cfg071_s cn66xx; - struct cvmx_pciercx_cfg071_s cn68xx; - struct cvmx_pciercx_cfg071_s cn68xxp1; - struct cvmx_pciercx_cfg071_s cnf71xx; -}; - -union cvmx_pciercx_cfg072 { - uint32_t u32; - struct cvmx_pciercx_cfg072_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t dword2:32; -#else - uint32_t dword2:32; -#endif - } s; - struct cvmx_pciercx_cfg072_s cn52xx; - struct cvmx_pciercx_cfg072_s cn52xxp1; - struct cvmx_pciercx_cfg072_s cn56xx; - struct cvmx_pciercx_cfg072_s cn56xxp1; - struct cvmx_pciercx_cfg072_s cn61xx; - struct cvmx_pciercx_cfg072_s cn63xx; - struct cvmx_pciercx_cfg072_s cn63xxp1; - struct cvmx_pciercx_cfg072_s cn66xx; - struct cvmx_pciercx_cfg072_s cn68xx; - struct cvmx_pciercx_cfg072_s cn68xxp1; - struct cvmx_pciercx_cfg072_s cnf71xx; -}; - -union cvmx_pciercx_cfg073 { - uint32_t u32; - struct cvmx_pciercx_cfg073_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t dword3:32; -#else - uint32_t dword3:32; -#endif - } s; - struct cvmx_pciercx_cfg073_s cn52xx; - struct cvmx_pciercx_cfg073_s cn52xxp1; - struct cvmx_pciercx_cfg073_s cn56xx; - struct cvmx_pciercx_cfg073_s cn56xxp1; - struct cvmx_pciercx_cfg073_s cn61xx; - struct cvmx_pciercx_cfg073_s cn63xx; - struct cvmx_pciercx_cfg073_s cn63xxp1; - struct cvmx_pciercx_cfg073_s cn66xx; - struct cvmx_pciercx_cfg073_s cn68xx; - struct cvmx_pciercx_cfg073_s cn68xxp1; - struct cvmx_pciercx_cfg073_s cnf71xx; -}; - -union cvmx_pciercx_cfg074 { - uint32_t u32; - struct cvmx_pciercx_cfg074_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t dword4:32; -#else - uint32_t dword4:32; -#endif - } s; - struct cvmx_pciercx_cfg074_s cn52xx; - struct cvmx_pciercx_cfg074_s cn52xxp1; - struct cvmx_pciercx_cfg074_s cn56xx; - struct cvmx_pciercx_cfg074_s cn56xxp1; - struct cvmx_pciercx_cfg074_s cn61xx; - struct cvmx_pciercx_cfg074_s cn63xx; - struct cvmx_pciercx_cfg074_s cn63xxp1; - struct cvmx_pciercx_cfg074_s cn66xx; - struct cvmx_pciercx_cfg074_s cn68xx; - struct cvmx_pciercx_cfg074_s cn68xxp1; - struct cvmx_pciercx_cfg074_s cnf71xx; }; union cvmx_pciercx_cfg075 { uint32_t u32; struct cvmx_pciercx_cfg075_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_3_31:29; - uint32_t fere:1; - uint32_t nfere:1; - uint32_t cere:1; -#else - uint32_t cere:1; - uint32_t nfere:1; - uint32_t fere:1; - uint32_t reserved_3_31:29; -#endif - } s; - struct cvmx_pciercx_cfg075_s cn52xx; - struct cvmx_pciercx_cfg075_s cn52xxp1; - struct cvmx_pciercx_cfg075_s cn56xx; - struct cvmx_pciercx_cfg075_s cn56xxp1; - struct cvmx_pciercx_cfg075_s cn61xx; - struct cvmx_pciercx_cfg075_s cn63xx; - struct cvmx_pciercx_cfg075_s cn63xxp1; - struct cvmx_pciercx_cfg075_s cn66xx; - struct cvmx_pciercx_cfg075_s cn68xx; - struct cvmx_pciercx_cfg075_s cn68xxp1; - struct cvmx_pciercx_cfg075_s cnf71xx; -}; - -union cvmx_pciercx_cfg076 { - uint32_t u32; - struct cvmx_pciercx_cfg076_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t aeimn:5; - uint32_t reserved_7_26:20; - uint32_t femr:1; - uint32_t nfemr:1; - uint32_t fuf:1; - uint32_t multi_efnfr:1; - uint32_t efnfr:1; - uint32_t multi_ecr:1; - uint32_t ecr:1; -#else - uint32_t ecr:1; - uint32_t multi_ecr:1; - uint32_t efnfr:1; - uint32_t multi_efnfr:1; - uint32_t fuf:1; - uint32_t nfemr:1; - uint32_t femr:1; - uint32_t reserved_7_26:20; - uint32_t aeimn:5; -#endif + __BITFIELD_FIELD(uint32_t reserved_3_31:29, + __BITFIELD_FIELD(uint32_t fere:1, + __BITFIELD_FIELD(uint32_t nfere:1, + __BITFIELD_FIELD(uint32_t cere:1, + ;)))) } s; - struct cvmx_pciercx_cfg076_s cn52xx; - struct cvmx_pciercx_cfg076_s cn52xxp1; - struct cvmx_pciercx_cfg076_s cn56xx; - struct cvmx_pciercx_cfg076_s cn56xxp1; - struct cvmx_pciercx_cfg076_s cn61xx; - struct cvmx_pciercx_cfg076_s cn63xx; - struct cvmx_pciercx_cfg076_s cn63xxp1; - struct cvmx_pciercx_cfg076_s cn66xx; - struct cvmx_pciercx_cfg076_s cn68xx; - struct cvmx_pciercx_cfg076_s cn68xxp1; - struct cvmx_pciercx_cfg076_s cnf71xx; -}; - -union cvmx_pciercx_cfg077 { - uint32_t u32; - struct cvmx_pciercx_cfg077_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t efnfsi:16; - uint32_t ecsi:16; -#else - uint32_t ecsi:16; - uint32_t efnfsi:16; -#endif - } s; - struct cvmx_pciercx_cfg077_s cn52xx; - struct cvmx_pciercx_cfg077_s cn52xxp1; - struct cvmx_pciercx_cfg077_s cn56xx; - struct cvmx_pciercx_cfg077_s cn56xxp1; - struct cvmx_pciercx_cfg077_s cn61xx; - struct cvmx_pciercx_cfg077_s cn63xx; - struct cvmx_pciercx_cfg077_s cn63xxp1; - struct cvmx_pciercx_cfg077_s cn66xx; - struct cvmx_pciercx_cfg077_s cn68xx; - struct cvmx_pciercx_cfg077_s cn68xxp1; - struct cvmx_pciercx_cfg077_s cnf71xx; }; union cvmx_pciercx_cfg448 { uint32_t u32; struct cvmx_pciercx_cfg448_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t rtl:16; - uint32_t rtltl:16; -#else - uint32_t rtltl:16; - uint32_t rtl:16; -#endif - } s; - struct cvmx_pciercx_cfg448_s cn52xx; - struct cvmx_pciercx_cfg448_s cn52xxp1; - struct cvmx_pciercx_cfg448_s cn56xx; - struct cvmx_pciercx_cfg448_s cn56xxp1; - struct cvmx_pciercx_cfg448_s cn61xx; - struct cvmx_pciercx_cfg448_s cn63xx; - struct cvmx_pciercx_cfg448_s cn63xxp1; - struct cvmx_pciercx_cfg448_s cn66xx; - struct cvmx_pciercx_cfg448_s cn68xx; - struct cvmx_pciercx_cfg448_s cn68xxp1; - struct cvmx_pciercx_cfg448_s cnf71xx; -}; - -union cvmx_pciercx_cfg449 { - uint32_t u32; - struct cvmx_pciercx_cfg449_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t omr:32; -#else - uint32_t omr:32; -#endif - } s; - struct cvmx_pciercx_cfg449_s cn52xx; - struct cvmx_pciercx_cfg449_s cn52xxp1; - struct cvmx_pciercx_cfg449_s cn56xx; - struct cvmx_pciercx_cfg449_s cn56xxp1; - struct cvmx_pciercx_cfg449_s cn61xx; - struct cvmx_pciercx_cfg449_s cn63xx; - struct cvmx_pciercx_cfg449_s cn63xxp1; - struct cvmx_pciercx_cfg449_s cn66xx; - struct cvmx_pciercx_cfg449_s cn68xx; - struct cvmx_pciercx_cfg449_s cn68xxp1; - struct cvmx_pciercx_cfg449_s cnf71xx; -}; - -union cvmx_pciercx_cfg450 { - uint32_t u32; - struct cvmx_pciercx_cfg450_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t lpec:8; - uint32_t reserved_22_23:2; - uint32_t link_state:6; - uint32_t force_link:1; - uint32_t reserved_8_14:7; - uint32_t link_num:8; -#else - uint32_t link_num:8; - uint32_t reserved_8_14:7; - uint32_t force_link:1; - uint32_t link_state:6; - uint32_t reserved_22_23:2; - uint32_t lpec:8; -#endif - } s; - struct cvmx_pciercx_cfg450_s cn52xx; - struct cvmx_pciercx_cfg450_s cn52xxp1; - struct cvmx_pciercx_cfg450_s cn56xx; - struct cvmx_pciercx_cfg450_s cn56xxp1; - struct cvmx_pciercx_cfg450_s cn61xx; - struct cvmx_pciercx_cfg450_s cn63xx; - struct cvmx_pciercx_cfg450_s cn63xxp1; - struct cvmx_pciercx_cfg450_s cn66xx; - struct cvmx_pciercx_cfg450_s cn68xx; - struct cvmx_pciercx_cfg450_s cn68xxp1; - struct cvmx_pciercx_cfg450_s cnf71xx; -}; - -union cvmx_pciercx_cfg451 { - uint32_t u32; - struct cvmx_pciercx_cfg451_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_31_31:1; - uint32_t easpml1:1; - uint32_t l1el:3; - uint32_t l0el:3; - uint32_t n_fts_cc:8; - uint32_t n_fts:8; - uint32_t ack_freq:8; -#else - uint32_t ack_freq:8; - uint32_t n_fts:8; - uint32_t n_fts_cc:8; - uint32_t l0el:3; - uint32_t l1el:3; - uint32_t easpml1:1; - uint32_t reserved_31_31:1; -#endif + __BITFIELD_FIELD(uint32_t rtl:16, + __BITFIELD_FIELD(uint32_t rtltl:16, + ;)) } s; - struct cvmx_pciercx_cfg451_cn52xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_30_31:2; - uint32_t l1el:3; - uint32_t l0el:3; - uint32_t n_fts_cc:8; - uint32_t n_fts:8; - uint32_t ack_freq:8; -#else - uint32_t ack_freq:8; - uint32_t n_fts:8; - uint32_t n_fts_cc:8; - uint32_t l0el:3; - uint32_t l1el:3; - uint32_t reserved_30_31:2; -#endif - } cn52xx; - struct cvmx_pciercx_cfg451_cn52xx cn52xxp1; - struct cvmx_pciercx_cfg451_cn52xx cn56xx; - struct cvmx_pciercx_cfg451_cn52xx cn56xxp1; - struct cvmx_pciercx_cfg451_s cn61xx; - struct cvmx_pciercx_cfg451_cn52xx cn63xx; - struct cvmx_pciercx_cfg451_cn52xx cn63xxp1; - struct cvmx_pciercx_cfg451_s cn66xx; - struct cvmx_pciercx_cfg451_s cn68xx; - struct cvmx_pciercx_cfg451_s cn68xxp1; - struct cvmx_pciercx_cfg451_s cnf71xx; }; union cvmx_pciercx_cfg452 { uint32_t u32; struct cvmx_pciercx_cfg452_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_26_31:6; - uint32_t eccrc:1; - uint32_t reserved_22_24:3; - uint32_t lme:6; - uint32_t reserved_8_15:8; - uint32_t flm:1; - uint32_t reserved_6_6:1; - uint32_t dllle:1; - uint32_t reserved_4_4:1; - uint32_t ra:1; - uint32_t le:1; - uint32_t sd:1; - uint32_t omr:1; -#else - uint32_t omr:1; - uint32_t sd:1; - uint32_t le:1; - uint32_t ra:1; - uint32_t reserved_4_4:1; - uint32_t dllle:1; - uint32_t reserved_6_6:1; - uint32_t flm:1; - uint32_t reserved_8_15:8; - uint32_t lme:6; - uint32_t reserved_22_24:3; - uint32_t eccrc:1; - uint32_t reserved_26_31:6; -#endif + __BITFIELD_FIELD(uint32_t reserved_26_31:6, + __BITFIELD_FIELD(uint32_t eccrc:1, + __BITFIELD_FIELD(uint32_t reserved_22_24:3, + __BITFIELD_FIELD(uint32_t lme:6, + __BITFIELD_FIELD(uint32_t reserved_12_15:4, + __BITFIELD_FIELD(uint32_t link_rate:4, + __BITFIELD_FIELD(uint32_t flm:1, + __BITFIELD_FIELD(uint32_t reserved_6_6:1, + __BITFIELD_FIELD(uint32_t dllle:1, + __BITFIELD_FIELD(uint32_t reserved_4_4:1, + __BITFIELD_FIELD(uint32_t ra:1, + __BITFIELD_FIELD(uint32_t le:1, + __BITFIELD_FIELD(uint32_t sd:1, + __BITFIELD_FIELD(uint32_t omr:1, + ;)))))))))))))) } s; - struct cvmx_pciercx_cfg452_s cn52xx; - struct cvmx_pciercx_cfg452_s cn52xxp1; - struct cvmx_pciercx_cfg452_s cn56xx; - struct cvmx_pciercx_cfg452_s cn56xxp1; - struct cvmx_pciercx_cfg452_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_22_31:10; - uint32_t lme:6; - uint32_t reserved_8_15:8; - uint32_t flm:1; - uint32_t reserved_6_6:1; - uint32_t dllle:1; - uint32_t reserved_4_4:1; - uint32_t ra:1; - uint32_t le:1; - uint32_t sd:1; - uint32_t omr:1; -#else - uint32_t omr:1; - uint32_t sd:1; - uint32_t le:1; - uint32_t ra:1; - uint32_t reserved_4_4:1; - uint32_t dllle:1; - uint32_t reserved_6_6:1; - uint32_t flm:1; - uint32_t reserved_8_15:8; - uint32_t lme:6; - uint32_t reserved_22_31:10; -#endif - } cn61xx; - struct cvmx_pciercx_cfg452_s cn63xx; - struct cvmx_pciercx_cfg452_s cn63xxp1; - struct cvmx_pciercx_cfg452_cn61xx cn66xx; - struct cvmx_pciercx_cfg452_cn61xx cn68xx; - struct cvmx_pciercx_cfg452_cn61xx cn68xxp1; - struct cvmx_pciercx_cfg452_cn61xx cnf71xx; -}; - -union cvmx_pciercx_cfg453 { - uint32_t u32; - struct cvmx_pciercx_cfg453_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t dlld:1; - uint32_t reserved_26_30:5; - uint32_t ack_nak:1; - uint32_t fcd:1; - uint32_t ilst:24; -#else - uint32_t ilst:24; - uint32_t fcd:1; - uint32_t ack_nak:1; - uint32_t reserved_26_30:5; - uint32_t dlld:1; -#endif - } s; - struct cvmx_pciercx_cfg453_s cn52xx; - struct cvmx_pciercx_cfg453_s cn52xxp1; - struct cvmx_pciercx_cfg453_s cn56xx; - struct cvmx_pciercx_cfg453_s cn56xxp1; - struct cvmx_pciercx_cfg453_s cn61xx; - struct cvmx_pciercx_cfg453_s cn63xx; - struct cvmx_pciercx_cfg453_s cn63xxp1; - struct cvmx_pciercx_cfg453_s cn66xx; - struct cvmx_pciercx_cfg453_s cn68xx; - struct cvmx_pciercx_cfg453_s cn68xxp1; - struct cvmx_pciercx_cfg453_s cnf71xx; -}; - -union cvmx_pciercx_cfg454 { - uint32_t u32; - struct cvmx_pciercx_cfg454_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t cx_nfunc:3; - uint32_t tmfcwt:5; - uint32_t tmanlt:5; - uint32_t tmrt:5; - uint32_t reserved_11_13:3; - uint32_t nskps:3; - uint32_t reserved_0_7:8; -#else - uint32_t reserved_0_7:8; - uint32_t nskps:3; - uint32_t reserved_11_13:3; - uint32_t tmrt:5; - uint32_t tmanlt:5; - uint32_t tmfcwt:5; - uint32_t cx_nfunc:3; -#endif - } s; - struct cvmx_pciercx_cfg454_cn52xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_29_31:3; - uint32_t tmfcwt:5; - uint32_t tmanlt:5; - uint32_t tmrt:5; - uint32_t reserved_11_13:3; - uint32_t nskps:3; - uint32_t reserved_4_7:4; - uint32_t ntss:4; -#else - uint32_t ntss:4; - uint32_t reserved_4_7:4; - uint32_t nskps:3; - uint32_t reserved_11_13:3; - uint32_t tmrt:5; - uint32_t tmanlt:5; - uint32_t tmfcwt:5; - uint32_t reserved_29_31:3; -#endif - } cn52xx; - struct cvmx_pciercx_cfg454_cn52xx cn52xxp1; - struct cvmx_pciercx_cfg454_cn52xx cn56xx; - struct cvmx_pciercx_cfg454_cn52xx cn56xxp1; - struct cvmx_pciercx_cfg454_cn61xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t cx_nfunc:3; - uint32_t tmfcwt:5; - uint32_t tmanlt:5; - uint32_t tmrt:5; - uint32_t reserved_8_13:6; - uint32_t mfuncn:8; -#else - uint32_t mfuncn:8; - uint32_t reserved_8_13:6; - uint32_t tmrt:5; - uint32_t tmanlt:5; - uint32_t tmfcwt:5; - uint32_t cx_nfunc:3; -#endif - } cn61xx; - struct cvmx_pciercx_cfg454_cn52xx cn63xx; - struct cvmx_pciercx_cfg454_cn52xx cn63xxp1; - struct cvmx_pciercx_cfg454_cn61xx cn66xx; - struct cvmx_pciercx_cfg454_cn61xx cn68xx; - struct cvmx_pciercx_cfg454_cn52xx cn68xxp1; - struct cvmx_pciercx_cfg454_cn61xx cnf71xx; }; union cvmx_pciercx_cfg455 { uint32_t u32; struct cvmx_pciercx_cfg455_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t m_cfg0_filt:1; - uint32_t m_io_filt:1; - uint32_t msg_ctrl:1; - uint32_t m_cpl_ecrc_filt:1; - uint32_t m_ecrc_filt:1; - uint32_t m_cpl_len_err:1; - uint32_t m_cpl_attr_err:1; - uint32_t m_cpl_tc_err:1; - uint32_t m_cpl_fun_err:1; - uint32_t m_cpl_rid_err:1; - uint32_t m_cpl_tag_err:1; - uint32_t m_lk_filt:1; - uint32_t m_cfg1_filt:1; - uint32_t m_bar_match:1; - uint32_t m_pois_filt:1; - uint32_t m_fun:1; - uint32_t dfcwt:1; - uint32_t reserved_11_14:4; - uint32_t skpiv:11; -#else - uint32_t skpiv:11; - uint32_t reserved_11_14:4; - uint32_t dfcwt:1; - uint32_t m_fun:1; - uint32_t m_pois_filt:1; - uint32_t m_bar_match:1; - uint32_t m_cfg1_filt:1; - uint32_t m_lk_filt:1; - uint32_t m_cpl_tag_err:1; - uint32_t m_cpl_rid_err:1; - uint32_t m_cpl_fun_err:1; - uint32_t m_cpl_tc_err:1; - uint32_t m_cpl_attr_err:1; - uint32_t m_cpl_len_err:1; - uint32_t m_ecrc_filt:1; - uint32_t m_cpl_ecrc_filt:1; - uint32_t msg_ctrl:1; - uint32_t m_io_filt:1; - uint32_t m_cfg0_filt:1; -#endif - } s; - struct cvmx_pciercx_cfg455_s cn52xx; - struct cvmx_pciercx_cfg455_s cn52xxp1; - struct cvmx_pciercx_cfg455_s cn56xx; - struct cvmx_pciercx_cfg455_s cn56xxp1; - struct cvmx_pciercx_cfg455_s cn61xx; - struct cvmx_pciercx_cfg455_s cn63xx; - struct cvmx_pciercx_cfg455_s cn63xxp1; - struct cvmx_pciercx_cfg455_s cn66xx; - struct cvmx_pciercx_cfg455_s cn68xx; - struct cvmx_pciercx_cfg455_s cn68xxp1; - struct cvmx_pciercx_cfg455_s cnf71xx; -}; - -union cvmx_pciercx_cfg456 { - uint32_t u32; - struct cvmx_pciercx_cfg456_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_4_31:28; - uint32_t m_handle_flush:1; - uint32_t m_dabort_4ucpl:1; - uint32_t m_vend1_drp:1; - uint32_t m_vend0_drp:1; -#else - uint32_t m_vend0_drp:1; - uint32_t m_vend1_drp:1; - uint32_t m_dabort_4ucpl:1; - uint32_t m_handle_flush:1; - uint32_t reserved_4_31:28; -#endif - } s; - struct cvmx_pciercx_cfg456_cn52xx { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_2_31:30; - uint32_t m_vend1_drp:1; - uint32_t m_vend0_drp:1; -#else - uint32_t m_vend0_drp:1; - uint32_t m_vend1_drp:1; - uint32_t reserved_2_31:30; -#endif - } cn52xx; - struct cvmx_pciercx_cfg456_cn52xx cn52xxp1; - struct cvmx_pciercx_cfg456_cn52xx cn56xx; - struct cvmx_pciercx_cfg456_cn52xx cn56xxp1; - struct cvmx_pciercx_cfg456_s cn61xx; - struct cvmx_pciercx_cfg456_cn52xx cn63xx; - struct cvmx_pciercx_cfg456_cn52xx cn63xxp1; - struct cvmx_pciercx_cfg456_s cn66xx; - struct cvmx_pciercx_cfg456_s cn68xx; - struct cvmx_pciercx_cfg456_cn52xx cn68xxp1; - struct cvmx_pciercx_cfg456_s cnf71xx; -}; - -union cvmx_pciercx_cfg458 { - uint32_t u32; - struct cvmx_pciercx_cfg458_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t dbg_info_l32:32; -#else - uint32_t dbg_info_l32:32; -#endif - } s; - struct cvmx_pciercx_cfg458_s cn52xx; - struct cvmx_pciercx_cfg458_s cn52xxp1; - struct cvmx_pciercx_cfg458_s cn56xx; - struct cvmx_pciercx_cfg458_s cn56xxp1; - struct cvmx_pciercx_cfg458_s cn61xx; - struct cvmx_pciercx_cfg458_s cn63xx; - struct cvmx_pciercx_cfg458_s cn63xxp1; - struct cvmx_pciercx_cfg458_s cn66xx; - struct cvmx_pciercx_cfg458_s cn68xx; - struct cvmx_pciercx_cfg458_s cn68xxp1; - struct cvmx_pciercx_cfg458_s cnf71xx; -}; - -union cvmx_pciercx_cfg459 { - uint32_t u32; - struct cvmx_pciercx_cfg459_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t dbg_info_u32:32; -#else - uint32_t dbg_info_u32:32; -#endif - } s; - struct cvmx_pciercx_cfg459_s cn52xx; - struct cvmx_pciercx_cfg459_s cn52xxp1; - struct cvmx_pciercx_cfg459_s cn56xx; - struct cvmx_pciercx_cfg459_s cn56xxp1; - struct cvmx_pciercx_cfg459_s cn61xx; - struct cvmx_pciercx_cfg459_s cn63xx; - struct cvmx_pciercx_cfg459_s cn63xxp1; - struct cvmx_pciercx_cfg459_s cn66xx; - struct cvmx_pciercx_cfg459_s cn68xx; - struct cvmx_pciercx_cfg459_s cn68xxp1; - struct cvmx_pciercx_cfg459_s cnf71xx; -}; - -union cvmx_pciercx_cfg460 { - uint32_t u32; - struct cvmx_pciercx_cfg460_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_20_31:12; - uint32_t tphfcc:8; - uint32_t tpdfcc:12; -#else - uint32_t tpdfcc:12; - uint32_t tphfcc:8; - uint32_t reserved_20_31:12; -#endif - } s; - struct cvmx_pciercx_cfg460_s cn52xx; - struct cvmx_pciercx_cfg460_s cn52xxp1; - struct cvmx_pciercx_cfg460_s cn56xx; - struct cvmx_pciercx_cfg460_s cn56xxp1; - struct cvmx_pciercx_cfg460_s cn61xx; - struct cvmx_pciercx_cfg460_s cn63xx; - struct cvmx_pciercx_cfg460_s cn63xxp1; - struct cvmx_pciercx_cfg460_s cn66xx; - struct cvmx_pciercx_cfg460_s cn68xx; - struct cvmx_pciercx_cfg460_s cn68xxp1; - struct cvmx_pciercx_cfg460_s cnf71xx; -}; - -union cvmx_pciercx_cfg461 { - uint32_t u32; - struct cvmx_pciercx_cfg461_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_20_31:12; - uint32_t tchfcc:8; - uint32_t tcdfcc:12; -#else - uint32_t tcdfcc:12; - uint32_t tchfcc:8; - uint32_t reserved_20_31:12; -#endif - } s; - struct cvmx_pciercx_cfg461_s cn52xx; - struct cvmx_pciercx_cfg461_s cn52xxp1; - struct cvmx_pciercx_cfg461_s cn56xx; - struct cvmx_pciercx_cfg461_s cn56xxp1; - struct cvmx_pciercx_cfg461_s cn61xx; - struct cvmx_pciercx_cfg461_s cn63xx; - struct cvmx_pciercx_cfg461_s cn63xxp1; - struct cvmx_pciercx_cfg461_s cn66xx; - struct cvmx_pciercx_cfg461_s cn68xx; - struct cvmx_pciercx_cfg461_s cn68xxp1; - struct cvmx_pciercx_cfg461_s cnf71xx; -}; - -union cvmx_pciercx_cfg462 { - uint32_t u32; - struct cvmx_pciercx_cfg462_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_20_31:12; - uint32_t tchfcc:8; - uint32_t tcdfcc:12; -#else - uint32_t tcdfcc:12; - uint32_t tchfcc:8; - uint32_t reserved_20_31:12; -#endif - } s; - struct cvmx_pciercx_cfg462_s cn52xx; - struct cvmx_pciercx_cfg462_s cn52xxp1; - struct cvmx_pciercx_cfg462_s cn56xx; - struct cvmx_pciercx_cfg462_s cn56xxp1; - struct cvmx_pciercx_cfg462_s cn61xx; - struct cvmx_pciercx_cfg462_s cn63xx; - struct cvmx_pciercx_cfg462_s cn63xxp1; - struct cvmx_pciercx_cfg462_s cn66xx; - struct cvmx_pciercx_cfg462_s cn68xx; - struct cvmx_pciercx_cfg462_s cn68xxp1; - struct cvmx_pciercx_cfg462_s cnf71xx; -}; - -union cvmx_pciercx_cfg463 { - uint32_t u32; - struct cvmx_pciercx_cfg463_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_3_31:29; - uint32_t rqne:1; - uint32_t trbne:1; - uint32_t rtlpfccnr:1; -#else - uint32_t rtlpfccnr:1; - uint32_t trbne:1; - uint32_t rqne:1; - uint32_t reserved_3_31:29; -#endif - } s; - struct cvmx_pciercx_cfg463_s cn52xx; - struct cvmx_pciercx_cfg463_s cn52xxp1; - struct cvmx_pciercx_cfg463_s cn56xx; - struct cvmx_pciercx_cfg463_s cn56xxp1; - struct cvmx_pciercx_cfg463_s cn61xx; - struct cvmx_pciercx_cfg463_s cn63xx; - struct cvmx_pciercx_cfg463_s cn63xxp1; - struct cvmx_pciercx_cfg463_s cn66xx; - struct cvmx_pciercx_cfg463_s cn68xx; - struct cvmx_pciercx_cfg463_s cn68xxp1; - struct cvmx_pciercx_cfg463_s cnf71xx; -}; - -union cvmx_pciercx_cfg464 { - uint32_t u32; - struct cvmx_pciercx_cfg464_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t wrr_vc3:8; - uint32_t wrr_vc2:8; - uint32_t wrr_vc1:8; - uint32_t wrr_vc0:8; -#else - uint32_t wrr_vc0:8; - uint32_t wrr_vc1:8; - uint32_t wrr_vc2:8; - uint32_t wrr_vc3:8; -#endif - } s; - struct cvmx_pciercx_cfg464_s cn52xx; - struct cvmx_pciercx_cfg464_s cn52xxp1; - struct cvmx_pciercx_cfg464_s cn56xx; - struct cvmx_pciercx_cfg464_s cn56xxp1; - struct cvmx_pciercx_cfg464_s cn61xx; - struct cvmx_pciercx_cfg464_s cn63xx; - struct cvmx_pciercx_cfg464_s cn63xxp1; - struct cvmx_pciercx_cfg464_s cn66xx; - struct cvmx_pciercx_cfg464_s cn68xx; - struct cvmx_pciercx_cfg464_s cn68xxp1; - struct cvmx_pciercx_cfg464_s cnf71xx; -}; - -union cvmx_pciercx_cfg465 { - uint32_t u32; - struct cvmx_pciercx_cfg465_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t wrr_vc7:8; - uint32_t wrr_vc6:8; - uint32_t wrr_vc5:8; - uint32_t wrr_vc4:8; -#else - uint32_t wrr_vc4:8; - uint32_t wrr_vc5:8; - uint32_t wrr_vc6:8; - uint32_t wrr_vc7:8; -#endif - } s; - struct cvmx_pciercx_cfg465_s cn52xx; - struct cvmx_pciercx_cfg465_s cn52xxp1; - struct cvmx_pciercx_cfg465_s cn56xx; - struct cvmx_pciercx_cfg465_s cn56xxp1; - struct cvmx_pciercx_cfg465_s cn61xx; - struct cvmx_pciercx_cfg465_s cn63xx; - struct cvmx_pciercx_cfg465_s cn63xxp1; - struct cvmx_pciercx_cfg465_s cn66xx; - struct cvmx_pciercx_cfg465_s cn68xx; - struct cvmx_pciercx_cfg465_s cn68xxp1; - struct cvmx_pciercx_cfg465_s cnf71xx; -}; - -union cvmx_pciercx_cfg466 { - uint32_t u32; - struct cvmx_pciercx_cfg466_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t rx_queue_order:1; - uint32_t type_ordering:1; - uint32_t reserved_24_29:6; - uint32_t queue_mode:3; - uint32_t reserved_20_20:1; - uint32_t header_credits:8; - uint32_t data_credits:12; -#else - uint32_t data_credits:12; - uint32_t header_credits:8; - uint32_t reserved_20_20:1; - uint32_t queue_mode:3; - uint32_t reserved_24_29:6; - uint32_t type_ordering:1; - uint32_t rx_queue_order:1; -#endif - } s; - struct cvmx_pciercx_cfg466_s cn52xx; - struct cvmx_pciercx_cfg466_s cn52xxp1; - struct cvmx_pciercx_cfg466_s cn56xx; - struct cvmx_pciercx_cfg466_s cn56xxp1; - struct cvmx_pciercx_cfg466_s cn61xx; - struct cvmx_pciercx_cfg466_s cn63xx; - struct cvmx_pciercx_cfg466_s cn63xxp1; - struct cvmx_pciercx_cfg466_s cn66xx; - struct cvmx_pciercx_cfg466_s cn68xx; - struct cvmx_pciercx_cfg466_s cn68xxp1; - struct cvmx_pciercx_cfg466_s cnf71xx; -}; - -union cvmx_pciercx_cfg467 { - uint32_t u32; - struct cvmx_pciercx_cfg467_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_24_31:8; - uint32_t queue_mode:3; - uint32_t reserved_20_20:1; - uint32_t header_credits:8; - uint32_t data_credits:12; -#else - uint32_t data_credits:12; - uint32_t header_credits:8; - uint32_t reserved_20_20:1; - uint32_t queue_mode:3; - uint32_t reserved_24_31:8; -#endif - } s; - struct cvmx_pciercx_cfg467_s cn52xx; - struct cvmx_pciercx_cfg467_s cn52xxp1; - struct cvmx_pciercx_cfg467_s cn56xx; - struct cvmx_pciercx_cfg467_s cn56xxp1; - struct cvmx_pciercx_cfg467_s cn61xx; - struct cvmx_pciercx_cfg467_s cn63xx; - struct cvmx_pciercx_cfg467_s cn63xxp1; - struct cvmx_pciercx_cfg467_s cn66xx; - struct cvmx_pciercx_cfg467_s cn68xx; - struct cvmx_pciercx_cfg467_s cn68xxp1; - struct cvmx_pciercx_cfg467_s cnf71xx; -}; - -union cvmx_pciercx_cfg468 { - uint32_t u32; - struct cvmx_pciercx_cfg468_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_24_31:8; - uint32_t queue_mode:3; - uint32_t reserved_20_20:1; - uint32_t header_credits:8; - uint32_t data_credits:12; -#else - uint32_t data_credits:12; - uint32_t header_credits:8; - uint32_t reserved_20_20:1; - uint32_t queue_mode:3; - uint32_t reserved_24_31:8; -#endif - } s; - struct cvmx_pciercx_cfg468_s cn52xx; - struct cvmx_pciercx_cfg468_s cn52xxp1; - struct cvmx_pciercx_cfg468_s cn56xx; - struct cvmx_pciercx_cfg468_s cn56xxp1; - struct cvmx_pciercx_cfg468_s cn61xx; - struct cvmx_pciercx_cfg468_s cn63xx; - struct cvmx_pciercx_cfg468_s cn63xxp1; - struct cvmx_pciercx_cfg468_s cn66xx; - struct cvmx_pciercx_cfg468_s cn68xx; - struct cvmx_pciercx_cfg468_s cn68xxp1; - struct cvmx_pciercx_cfg468_s cnf71xx; -}; - -union cvmx_pciercx_cfg490 { - uint32_t u32; - struct cvmx_pciercx_cfg490_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_26_31:6; - uint32_t header_depth:10; - uint32_t reserved_14_15:2; - uint32_t data_depth:14; -#else - uint32_t data_depth:14; - uint32_t reserved_14_15:2; - uint32_t header_depth:10; - uint32_t reserved_26_31:6; -#endif + __BITFIELD_FIELD(uint32_t m_cfg0_filt:1, + __BITFIELD_FIELD(uint32_t m_io_filt:1, + __BITFIELD_FIELD(uint32_t msg_ctrl:1, + __BITFIELD_FIELD(uint32_t m_cpl_ecrc_filt:1, + __BITFIELD_FIELD(uint32_t m_ecrc_filt:1, + __BITFIELD_FIELD(uint32_t m_cpl_len_err:1, + __BITFIELD_FIELD(uint32_t m_cpl_attr_err:1, + __BITFIELD_FIELD(uint32_t m_cpl_tc_err:1, + __BITFIELD_FIELD(uint32_t m_cpl_fun_err:1, + __BITFIELD_FIELD(uint32_t m_cpl_rid_err:1, + __BITFIELD_FIELD(uint32_t m_cpl_tag_err:1, + __BITFIELD_FIELD(uint32_t m_lk_filt:1, + __BITFIELD_FIELD(uint32_t m_cfg1_filt:1, + __BITFIELD_FIELD(uint32_t m_bar_match:1, + __BITFIELD_FIELD(uint32_t m_pois_filt:1, + __BITFIELD_FIELD(uint32_t m_fun:1, + __BITFIELD_FIELD(uint32_t dfcwt:1, + __BITFIELD_FIELD(uint32_t reserved_11_14:4, + __BITFIELD_FIELD(uint32_t skpiv:11, + ;))))))))))))))))))) } s; - struct cvmx_pciercx_cfg490_s cn52xx; - struct cvmx_pciercx_cfg490_s cn52xxp1; - struct cvmx_pciercx_cfg490_s cn56xx; - struct cvmx_pciercx_cfg490_s cn56xxp1; - struct cvmx_pciercx_cfg490_s cn61xx; - struct cvmx_pciercx_cfg490_s cn63xx; - struct cvmx_pciercx_cfg490_s cn63xxp1; - struct cvmx_pciercx_cfg490_s cn66xx; - struct cvmx_pciercx_cfg490_s cn68xx; - struct cvmx_pciercx_cfg490_s cn68xxp1; - struct cvmx_pciercx_cfg490_s cnf71xx; -}; - -union cvmx_pciercx_cfg491 { - uint32_t u32; - struct cvmx_pciercx_cfg491_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_26_31:6; - uint32_t header_depth:10; - uint32_t reserved_14_15:2; - uint32_t data_depth:14; -#else - uint32_t data_depth:14; - uint32_t reserved_14_15:2; - uint32_t header_depth:10; - uint32_t reserved_26_31:6; -#endif - } s; - struct cvmx_pciercx_cfg491_s cn52xx; - struct cvmx_pciercx_cfg491_s cn52xxp1; - struct cvmx_pciercx_cfg491_s cn56xx; - struct cvmx_pciercx_cfg491_s cn56xxp1; - struct cvmx_pciercx_cfg491_s cn61xx; - struct cvmx_pciercx_cfg491_s cn63xx; - struct cvmx_pciercx_cfg491_s cn63xxp1; - struct cvmx_pciercx_cfg491_s cn66xx; - struct cvmx_pciercx_cfg491_s cn68xx; - struct cvmx_pciercx_cfg491_s cn68xxp1; - struct cvmx_pciercx_cfg491_s cnf71xx; -}; - -union cvmx_pciercx_cfg492 { - uint32_t u32; - struct cvmx_pciercx_cfg492_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_26_31:6; - uint32_t header_depth:10; - uint32_t reserved_14_15:2; - uint32_t data_depth:14; -#else - uint32_t data_depth:14; - uint32_t reserved_14_15:2; - uint32_t header_depth:10; - uint32_t reserved_26_31:6; -#endif - } s; - struct cvmx_pciercx_cfg492_s cn52xx; - struct cvmx_pciercx_cfg492_s cn52xxp1; - struct cvmx_pciercx_cfg492_s cn56xx; - struct cvmx_pciercx_cfg492_s cn56xxp1; - struct cvmx_pciercx_cfg492_s cn61xx; - struct cvmx_pciercx_cfg492_s cn63xx; - struct cvmx_pciercx_cfg492_s cn63xxp1; - struct cvmx_pciercx_cfg492_s cn66xx; - struct cvmx_pciercx_cfg492_s cn68xx; - struct cvmx_pciercx_cfg492_s cn68xxp1; - struct cvmx_pciercx_cfg492_s cnf71xx; }; union cvmx_pciercx_cfg515 { uint32_t u32; struct cvmx_pciercx_cfg515_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t reserved_21_31:11; - uint32_t s_d_e:1; - uint32_t ctcrb:1; - uint32_t cpyts:1; - uint32_t dsc:1; - uint32_t le:9; - uint32_t n_fts:8; -#else - uint32_t n_fts:8; - uint32_t le:9; - uint32_t dsc:1; - uint32_t cpyts:1; - uint32_t ctcrb:1; - uint32_t s_d_e:1; - uint32_t reserved_21_31:11; -#endif - } s; - struct cvmx_pciercx_cfg515_s cn61xx; - struct cvmx_pciercx_cfg515_s cn63xx; - struct cvmx_pciercx_cfg515_s cn63xxp1; - struct cvmx_pciercx_cfg515_s cn66xx; - struct cvmx_pciercx_cfg515_s cn68xx; - struct cvmx_pciercx_cfg515_s cn68xxp1; - struct cvmx_pciercx_cfg515_s cnf71xx; -}; - -union cvmx_pciercx_cfg516 { - uint32_t u32; - struct cvmx_pciercx_cfg516_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t phy_stat:32; -#else - uint32_t phy_stat:32; -#endif - } s; - struct cvmx_pciercx_cfg516_s cn52xx; - struct cvmx_pciercx_cfg516_s cn52xxp1; - struct cvmx_pciercx_cfg516_s cn56xx; - struct cvmx_pciercx_cfg516_s cn56xxp1; - struct cvmx_pciercx_cfg516_s cn61xx; - struct cvmx_pciercx_cfg516_s cn63xx; - struct cvmx_pciercx_cfg516_s cn63xxp1; - struct cvmx_pciercx_cfg516_s cn66xx; - struct cvmx_pciercx_cfg516_s cn68xx; - struct cvmx_pciercx_cfg516_s cn68xxp1; - struct cvmx_pciercx_cfg516_s cnf71xx; -}; - -union cvmx_pciercx_cfg517 { - uint32_t u32; - struct cvmx_pciercx_cfg517_s { -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t phy_ctrl:32; -#else - uint32_t phy_ctrl:32; -#endif + __BITFIELD_FIELD(uint32_t reserved_21_31:11, + __BITFIELD_FIELD(uint32_t s_d_e:1, + __BITFIELD_FIELD(uint32_t ctcrb:1, + __BITFIELD_FIELD(uint32_t cpyts:1, + __BITFIELD_FIELD(uint32_t dsc:1, + __BITFIELD_FIELD(uint32_t le:9, + __BITFIELD_FIELD(uint32_t n_fts:8, + ;))))))) } s; - struct cvmx_pciercx_cfg517_s cn52xx; - struct cvmx_pciercx_cfg517_s cn52xxp1; - struct cvmx_pciercx_cfg517_s cn56xx; - struct cvmx_pciercx_cfg517_s cn56xxp1; - struct cvmx_pciercx_cfg517_s cn61xx; - struct cvmx_pciercx_cfg517_s cn63xx; - struct cvmx_pciercx_cfg517_s cn63xxp1; - struct cvmx_pciercx_cfg517_s cn66xx; - struct cvmx_pciercx_cfg517_s cn68xx; - struct cvmx_pciercx_cfg517_s cn68xxp1; - struct cvmx_pciercx_cfg517_s cnf71xx; }; #endif -- cgit v1.2.3-59-g8ed1b From e96b1b0648adf7d80606a99e9596177186fd90ab Mon Sep 17 00:00:00 2001 From: "Steven J. Hill" Date: Thu, 9 Mar 2017 08:16:03 -0600 Subject: MIPS: Octeon: Clean up platform code. Remove unused headers and fix warnings from checkpatch. Signed-off-by: Steven J. Hill Acked-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/15407/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/octeon-platform.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c index e3c77d8a0d56..8505db478904 100644 --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c @@ -7,8 +7,6 @@ * Copyright (C) 2008 Wind River Systems */ -#include -#include #include #include #include @@ -440,7 +438,7 @@ out: } device_initcall(octeon_rng_device_init); -static struct of_device_id __initdata octeon_ids[] = { +const struct of_device_id octeon_ids[] __initconst = { { .compatible = "simple-bus", }, { .compatible = "cavium,octeon-6335-uctl", }, { .compatible = "cavium,octeon-5750-usbn", }, @@ -480,6 +478,7 @@ static void __init octeon_fdt_set_phy(int eth, int phy_addr) alt_phy_handle = fdt_getprop(initial_boot_params, eth, "cavium,alt-phy-handle", NULL); if (alt_phy_handle) { u32 alt_phandle = be32_to_cpup(alt_phy_handle); + alt_phy = fdt_node_offset_by_phandle(initial_boot_params, alt_phandle); } else { alt_phy = -1; @@ -578,6 +577,7 @@ static void __init octeon_fdt_rm_ethernet(int node) if (phy_handle) { u32 ph = be32_to_cpup(phy_handle); int p = fdt_node_offset_by_phandle(initial_boot_params, ph); + if (p >= 0) fdt_nop_node(initial_boot_params, p); } @@ -727,6 +727,7 @@ int __init octeon_prune_device_tree(void) for (i = 0; i < 2; i++) { int mgmt; + snprintf(name_buffer, sizeof(name_buffer), "mix%d", i); alias_prop = fdt_getprop(initial_boot_params, aliases, @@ -742,6 +743,7 @@ int __init octeon_prune_device_tree(void) name_buffer); } else { int phy_addr = cvmx_helper_board_get_mii_address(CVMX_HELPER_BOARD_MGMT_IPD_PORT + i); + octeon_fdt_set_phy(mgmt, phy_addr); } } @@ -750,6 +752,7 @@ int __init octeon_prune_device_tree(void) pip_path = fdt_getprop(initial_boot_params, aliases, "pip", NULL); if (pip_path) { int pip = fdt_path_offset(initial_boot_params, pip_path); + if (pip >= 0) for (i = 0; i <= 4; i++) octeon_fdt_pip_iface(pip, i); @@ -766,6 +769,7 @@ int __init octeon_prune_device_tree(void) for (i = 0; i < 2; i++) { int i2c; + snprintf(name_buffer, sizeof(name_buffer), "twsi%d", i); alias_prop = fdt_getprop(initial_boot_params, aliases, @@ -796,11 +800,11 @@ int __init octeon_prune_device_tree(void) for (i = 0; i < 2; i++) { int i2c; + snprintf(name_buffer, sizeof(name_buffer), "smi%d", i); alias_prop = fdt_getprop(initial_boot_params, aliases, name_buffer, NULL); - if (alias_prop) { i2c = fdt_path_offset(initial_boot_params, alias_prop); if (i2c < 0) @@ -823,6 +827,7 @@ int __init octeon_prune_device_tree(void) for (i = 0; i < 3; i++) { int uart; + snprintf(name_buffer, sizeof(name_buffer), "uart%d", i); alias_prop = fdt_getprop(initial_boot_params, aliases, @@ -862,6 +867,7 @@ int __init octeon_prune_device_tree(void) int len; int cf = fdt_path_offset(initial_boot_params, alias_prop); + base_ptr = 0; if (octeon_bootinfo->major_version == 1 && octeon_bootinfo->minor_version >= 1) { @@ -911,6 +917,7 @@ int __init octeon_prune_device_tree(void) fdt_nop_property(initial_boot_params, cf, "cavium,dma-engine-handle"); if (!is_16bit) { __be32 width = cpu_to_be32(8); + fdt_setprop_inplace(initial_boot_params, cf, "cavium,bus-width", &width, sizeof(width)); } @@ -1036,6 +1043,7 @@ end_led: } else { __be32 new_f[1]; enum cvmx_helper_board_usb_clock_types c; + c = __cvmx_helper_board_usb_get_clock_type(); switch (c) { case USB_CLOCK_TYPE_REF_48: -- cgit v1.2.3-59-g8ed1b From 5373633cc9253ba82547473e899cab141c54133e Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 16 Mar 2017 18:06:12 -0700 Subject: MIPS: Disable Werror when W= is set Using any value for W= will lead to a ton of warnings which are turned into fatal errors because MIPS adds -Werror to arch/mips/*. Signed-off-by: Florian Fainelli Cc: linux-mips@linux-mips.org Cc: james.hogan@imgtec.com Patchwork: https://patchwork.linux-mips.org/patch/15785/ Signed-off-by: Ralf Baechle --- arch/mips/Kbuild | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/mips/Kbuild b/arch/mips/Kbuild index 5c3f688a5232..5cef58651db0 100644 --- a/arch/mips/Kbuild +++ b/arch/mips/Kbuild @@ -1,7 +1,9 @@ # Fail on warnings - also for files referenced in subdirs # -Werror can be disabled for specific files using: # CFLAGS_ := -Wno-error +ifeq ($(W),) subdir-ccflags-y := -Werror +endif # platform specific definitions include arch/mips/Kbuild.platforms -- cgit v1.2.3-59-g8ed1b From 296e46db00731b05c796e4f1db4bfe2e0efd80c1 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 21 Mar 2017 22:13:06 +0100 Subject: MIPS: Don't unnecessarily include kmalloc.h into . Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cache.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/cache.h b/arch/mips/include/asm/cache.h index b4db69fbc40c..99d6632c5047 100644 --- a/arch/mips/include/asm/cache.h +++ b/arch/mips/include/asm/cache.h @@ -9,8 +9,6 @@ #ifndef _ASM_CACHE_H #define _ASM_CACHE_H -#include - #define L1_CACHE_SHIFT CONFIG_MIPS_L1_CACHE_SHIFT #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) -- cgit v1.2.3-59-g8ed1b From 4437637c3277fa9aba4e443329b5db3b6d34eedf Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 21 Mar 2017 22:14:30 +0100 Subject: MIPS: Delete unused definition of SMP_CACHE_SHIFT. Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cache.h | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/include/asm/cache.h b/arch/mips/include/asm/cache.h index 99d6632c5047..d7e314b6be09 100644 --- a/arch/mips/include/asm/cache.h +++ b/arch/mips/include/asm/cache.h @@ -12,7 +12,6 @@ #define L1_CACHE_SHIFT CONFIG_MIPS_L1_CACHE_SHIFT #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) -#define SMP_CACHE_SHIFT L1_CACHE_SHIFT #define SMP_CACHE_BYTES L1_CACHE_BYTES #define __read_mostly __attribute__((__section__(".data..read_mostly"))) -- cgit v1.2.3-59-g8ed1b From 294d62743754f1fefefccccb09f8deec48f00969 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 21 Mar 2017 22:40:43 +0100 Subject: MIPS: Delete redundant definition of SMP_CACHE_BYTES. already defines SMP_CACHE_BYTES as L1_CACHE_BYTES. This change results in a build error in which directly includes . Fix this by including instead. Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cache.h | 2 -- arch/mips/include/asm/cpu-info.h | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/cache.h b/arch/mips/include/asm/cache.h index d7e314b6be09..fc67947ed658 100644 --- a/arch/mips/include/asm/cache.h +++ b/arch/mips/include/asm/cache.h @@ -12,8 +12,6 @@ #define L1_CACHE_SHIFT CONFIG_MIPS_L1_CACHE_SHIFT #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) -#define SMP_CACHE_BYTES L1_CACHE_BYTES - #define __read_mostly __attribute__((__section__(".data..read_mostly"))) #endif /* _ASM_CACHE_H */ diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h index edbe2734a1bf..d43b3045109e 100644 --- a/arch/mips/include/asm/cpu-info.h +++ b/arch/mips/include/asm/cpu-info.h @@ -12,10 +12,9 @@ #ifndef __ASM_CPU_INFO_H #define __ASM_CPU_INFO_H +#include #include -#include - /* * Descriptor for a cache */ -- cgit v1.2.3-59-g8ed1b From 17c99d9421695a0e0de18bf1e7091d859e20ec1d Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Thu, 16 Mar 2017 21:00:28 +0800 Subject: MIPS: Loongson-3: Select MIPS_L1_CACHE_SHIFT_6 Some newer Loongson-3 have 64 bytes cache lines, so select MIPS_L1_CACHE_SHIFT_6. Signed-off-by: Huacai Chen Cc: John Crispin Cc: Steven J . Hill Cc: Fuxin Zhang Cc: Zhangjin Wu Cc: linux-mips@linux-mips.org Cc: stable@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/15755/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index f4dd2c322d4b..2afb41c52ba0 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1374,6 +1374,7 @@ config CPU_LOONGSON3 select WEAK_ORDERING select WEAK_REORDERING_BEYOND_LLSC select MIPS_PGD_C0_CONTEXT + select MIPS_L1_CACHE_SHIFT_6 select GPIOLIB help The Loongson 3 processor implements the MIPS64R2 instruction -- cgit v1.2.3-59-g8ed1b From 5bba7aa4958e271c3ffceb70d47d3206524cf489 Mon Sep 17 00:00:00 2001 From: Leonid Yegoshin Date: Mon, 13 Mar 2017 16:36:35 +0100 Subject: MIPS: r2-on-r6-emu: Fix BLEZL and BGTZL identification Fix the problem of inaccurate identification of instructions BLEZL and BGTZL in R2 emulation code by making sure all necessary encoding specifications are met. Previously, certain R6 instructions could be identified as BLEZL or BGTZL. R2 emulation routine didn't take into account that both BLEZL and BGTZL instructions require their rt field (bits 20 to 16 of instruction encoding) to be 0, and that, at same time, if the value in that field is not 0, the encoding may represent a legitimate MIPS R6 instruction. This means that a problem could occur after emulation optimization, when emulation routine tried to pipeline emulation, picked up a next candidate, and subsequently misrecognized an R6 instruction as BLEZL or BGTZL. It should be said that for single pass strategy, the problem does not happen because CPU doesn't trap on branch-compacts which share opcode space with BLEZL/BGTZL (but have rt field != 0, of course). Signed-off-by: Leonid Yegoshin Signed-off-by: Miodrag Dinic Signed-off-by: Aleksandar Markovic Reported-by: Douglas Leung Reviewed-by: Paul Burton Cc: james.hogan@imgtec.com Cc: petar.jovanovic@imgtec.com Cc: goran.ferenc@imgtec.com Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/15456/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/mips-r2-to-r6-emul.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/mips-r2-to-r6-emul.c b/arch/mips/kernel/mips-r2-to-r6-emul.c index d8f1cf1ec370..50558b30a809 100644 --- a/arch/mips/kernel/mips-r2-to-r6-emul.c +++ b/arch/mips/kernel/mips-r2-to-r6-emul.c @@ -1096,10 +1096,20 @@ repeat: } break; - case beql_op: - case bnel_op: case blezl_op: case bgtzl_op: + /* + * For BLEZL and BGTZL, rt field must be set to 0. If this + * is not the case, this may be an encoding of a MIPS R6 + * instruction, so return to CPU execution if this occurs + */ + if (MIPSInst_RT(inst)) { + err = SIGILL; + break; + } + /* fall through */ + case beql_op: + case bnel_op: if (delay_slot(regs)) { err = SIGILL; break; -- cgit v1.2.3-59-g8ed1b From 411dac79cc2ed80f7e348ccc23eb4d8b0ba9f6d5 Mon Sep 17 00:00:00 2001 From: Aleksandar Markovic Date: Mon, 13 Mar 2017 16:36:36 +0100 Subject: MIPS: r2-on-r6-emu: Clear BLTZALL and BGEZALL debugfs counters Add missing clearing of BLTZALL and BGEZALL emulation counters in function mipsr2_stats_clear_show(). Previously, it was not possible to reset BLTZALL and BGEZALL emulation counters - their value remained the same even after explicit request via debugfs. As far as other related counters are concerned, they all seem to be properly cleared. This change affects debugfs operation only, core R2 emulation functionality is not affected. Signed-off-by: Aleksandar Markovic Reviewed-by: Paul Burton Cc: james.hogan@imgtec.com Cc: leonid.yegoshin@imgtec.com Cc: douglas.leung@imgtec.com Cc: petar.jovanovic@imgtec.com Cc: miodrag.dinic@imgtec.com Cc: goran.ferenc@imgtec.com Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/15517/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/mips-r2-to-r6-emul.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/mips/kernel/mips-r2-to-r6-emul.c b/arch/mips/kernel/mips-r2-to-r6-emul.c index 50558b30a809..e1416f1d2477 100644 --- a/arch/mips/kernel/mips-r2-to-r6-emul.c +++ b/arch/mips/kernel/mips-r2-to-r6-emul.c @@ -2339,6 +2339,8 @@ static int mipsr2_stats_clear_show(struct seq_file *s, void *unused) __this_cpu_write((mipsr2bremustats).bgezl, 0); __this_cpu_write((mipsr2bremustats).bltzll, 0); __this_cpu_write((mipsr2bremustats).bgezll, 0); + __this_cpu_write((mipsr2bremustats).bltzall, 0); + __this_cpu_write((mipsr2bremustats).bgezall, 0); __this_cpu_write((mipsr2bremustats).bltzal, 0); __this_cpu_write((mipsr2bremustats).bgezal, 0); __this_cpu_write((mipsr2bremustats).beql, 0); -- cgit v1.2.3-59-g8ed1b From 8bcd84a4a37c88d8304ca3a64f0461a51487e239 Mon Sep 17 00:00:00 2001 From: Douglas Leung Date: Mon, 13 Mar 2017 16:36:37 +0100 Subject: MIPS: math-emu: Fix BC1EQZ and BC1NEZ condition handling Correct the treatment of branching conditions for BC1EQZ and BC1NEZ instructions in function isBranchInstr(). Previously, corresponding conditions were swapped, which in turn meant that, for these two instructions, function isBranchInstr() returned wrong value in its output parameter contpc. This change is actually an extension of the fix done by the commit 93583e178ebf ("MIPS: math-emu: Fix BC1{EQ,NE}Z emulation"). That commit dealt with a similar problem in function cop1Emulate(), while this commit deals with condition handling in function isBranchInstr(). The code styles of changes in these two commits are kept as consistent as possible. Signed-off-by: Douglas Leung Signed-off-by: Miodrag Dinic Signed-off-by: Aleksandar Markovic Reviewed-by: Paul Burton Cc: james.hogan@imgtec.com Cc: leonid.yegoshin@imgtec.com Cc: petar.jovanovic@imgtec.com Cc: goran.ferenc@imgtec.com Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/15489/ Signed-off-by: Ralf Baechle --- arch/mips/math-emu/cp1emu.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index a298ac93edcc..f12fde10c8ad 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -439,6 +439,8 @@ int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, union mips_instruction insn = (union mips_instruction)dec_insn.insn; unsigned int fcr31; unsigned int bit = 0; + unsigned int bit0; + union fpureg *fpr; switch (insn.i_format.opcode) { case spec_op: @@ -706,14 +708,14 @@ int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, ((insn.i_format.rs == bc1eqz_op) || (insn.i_format.rs == bc1nez_op))) { bit = 0; + fpr = ¤t->thread.fpu.fpr[insn.i_format.rt]; + bit0 = get_fpr32(fpr, 0) & 0x1; switch (insn.i_format.rs) { case bc1eqz_op: - if (get_fpr32(¤t->thread.fpu.fpr[insn.i_format.rt], 0) & 0x1) - bit = 1; + bit = bit0 == 0; break; case bc1nez_op: - if (!(get_fpr32(¤t->thread.fpu.fpr[insn.i_format.rt], 0) & 0x1)) - bit = 1; + bit = bit0 != 0; break; } if (bit) -- cgit v1.2.3-59-g8ed1b From 1f83f5e42b5b17f844955b49e986c3f1f187dd54 Mon Sep 17 00:00:00 2001 From: Marcin Nowakowski Date: Fri, 7 Apr 2017 13:40:28 +0200 Subject: MIPS: Use common outgoing-CPU-notification code Replace the open-coded CPU-offline notification with common code. In particular avoid calling scheduler code using RCU from an offline CPU that RCU is ignoring. Signed-off-by: Marcin Nowakowski Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/15921/ Patchwork: https://patchwork.linux-mips.org/patch/15953/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/smp-cps.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 6d45f05538c8..306b4a64cb8f 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -8,6 +8,7 @@ * option) any later version. */ +#include #include #include #include @@ -408,7 +409,6 @@ static int cps_cpu_disable(void) return 0; } -static DECLARE_COMPLETION(cpu_death_chosen); static unsigned cpu_death_sibling; static enum { CPU_DEATH_HALT, @@ -444,7 +444,7 @@ void play_dead(void) } /* This CPU has chosen its way out */ - complete(&cpu_death_chosen); + (void)cpu_report_death(); if (cpu_death == CPU_DEATH_HALT) { vpe_id = cpu_vpe_id(&cpu_data[cpu]); @@ -493,8 +493,7 @@ static void cps_cpu_die(unsigned int cpu) int err; /* Wait for the cpu to choose its way out */ - if (!wait_for_completion_timeout(&cpu_death_chosen, - msecs_to_jiffies(5000))) { + if (!cpu_wait_death(cpu, 5)) { pr_err("CPU%u: didn't offline\n", cpu); return; } -- cgit v1.2.3-59-g8ed1b From 828d1e4e98654e2284496e2fd7f9605ba04ef02a Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Thu, 6 Apr 2017 11:29:06 +0100 Subject: MIPS: Remove dead define of ST_OFF Commit 1a3d59579b9f ("MIPS: Tidy up FPU context switching") removed the last usage of the macro ST_OFF. Remove the dead code. Signed-off-by: Matt Redfearn Cc: James Hogan Cc: Paul Burton Cc: trivial@kernel.org Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/15898/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/r4k_switch.S | 6 ------ 1 file changed, 6 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S index 758577861523..7b386d54fd65 100644 --- a/arch/mips/kernel/r4k_switch.S +++ b/arch/mips/kernel/r4k_switch.S @@ -25,12 +25,6 @@ /* preprocessor replaces the fp in ".set fp=64" with $30 otherwise */ #undef fp -/* - * Offset to the current process status flags, the first 32 bytes of the - * stack are not used. - */ -#define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS) - #ifndef USE_ALTERNATE_RESUME_IMPL /* * task_struct *resume(task_struct *prev, task_struct *next, -- cgit v1.2.3-59-g8ed1b From 33679a50370db9aa1a3f0cdf5f70c1c07236a4b2 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 30 Mar 2017 14:52:15 -0700 Subject: MIPS: uasm: Remove needless ISA abstraction We always either target MIPS32/MIPS64 or microMIPS, and always include one & only one of uasm-mips.c or uasm-micromips.c. Therefore the abstraction of the ISA in asm/uasm.h declaring functions for either ISA is redundant & needless. Remove it to simplify the code. This is largely the result of the following: :%s/ISAOPC(\(.\{-}\))/uasm_i##\1/ :%s/ISAFUNC(\(.\{-}\))/\1/ Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Paul Burton Patchwork: https://patchwork.linux-mips.org/patch/15844/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/uasm.h | 87 ++++++++---------------- arch/mips/mm/uasm.c | 156 +++++++++++++++++++++---------------------- 2 files changed, 106 insertions(+), 137 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index d91ed5b506ed..3748f4d120a5 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -21,77 +21,46 @@ #define UASM_EXPORT_SYMBOL(sym) #endif -#define _UASM_ISA_CLASSIC 0 -#define _UASM_ISA_MICROMIPS 1 - -#ifndef UASM_ISA -#ifdef CONFIG_CPU_MICROMIPS -#define UASM_ISA _UASM_ISA_MICROMIPS -#else -#define UASM_ISA _UASM_ISA_CLASSIC -#endif -#endif - -#if (UASM_ISA == _UASM_ISA_CLASSIC) -#ifdef CONFIG_CPU_MICROMIPS -#define ISAOPC(op) CL_uasm_i##op -#define ISAFUNC(x) CL_##x -#else -#define ISAOPC(op) uasm_i##op -#define ISAFUNC(x) x -#endif -#elif (UASM_ISA == _UASM_ISA_MICROMIPS) -#ifdef CONFIG_CPU_MICROMIPS -#define ISAOPC(op) uasm_i##op -#define ISAFUNC(x) x -#else -#define ISAOPC(op) MM_uasm_i##op -#define ISAFUNC(x) MM_##x -#endif -#else -#error Unsupported micro-assembler ISA!!! -#endif - #define Ip_u1u2u3(op) \ -void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c) +void uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c) #define Ip_u2u1u3(op) \ -void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c) +void uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c) #define Ip_u3u2u1(op) \ -void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c) +void uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c) #define Ip_u3u1u2(op) \ -void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c) +void uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c) #define Ip_u1u2s3(op) \ -void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, signed int c) +void uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c) #define Ip_u2s3u1(op) \ -void ISAOPC(op)(u32 **buf, unsigned int a, signed int b, unsigned int c) +void uasm_i##op(u32 **buf, unsigned int a, signed int b, unsigned int c) #define Ip_s3s1s2(op) \ -void ISAOPC(op)(u32 **buf, int a, int b, int c) +void uasm_i##op(u32 **buf, int a, int b, int c) #define Ip_u2u1s3(op) \ -void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, signed int c) +void uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c) #define Ip_u2u1msbu3(op) \ -void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c, \ +void uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c, \ unsigned int d) #define Ip_u1u2(op) \ -void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b) +void uasm_i##op(u32 **buf, unsigned int a, unsigned int b) #define Ip_u2u1(op) \ -void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b) +void uasm_i##op(u32 **buf, unsigned int a, unsigned int b) #define Ip_u1s2(op) \ -void ISAOPC(op)(u32 **buf, unsigned int a, signed int b) +void uasm_i##op(u32 **buf, unsigned int a, signed int b) -#define Ip_u1(op) void ISAOPC(op)(u32 **buf, unsigned int a) +#define Ip_u1(op) void uasm_i##op(u32 **buf, unsigned int a) -#define Ip_0(op) void ISAOPC(op)(u32 **buf) +#define Ip_0(op) void uasm_i##op(u32 **buf) Ip_u2u1s3(_addiu); Ip_u3u1u2(_addu); @@ -191,20 +160,20 @@ struct uasm_label { int lab; }; -void ISAFUNC(uasm_build_label)(struct uasm_label **lab, u32 *addr, +void uasm_build_label(struct uasm_label **lab, u32 *addr, int lid); #ifdef CONFIG_64BIT -int ISAFUNC(uasm_in_compat_space_p)(long addr); +int uasm_in_compat_space_p(long addr); #endif -int ISAFUNC(uasm_rel_hi)(long val); -int ISAFUNC(uasm_rel_lo)(long val); -void ISAFUNC(UASM_i_LA_mostly)(u32 **buf, unsigned int rs, long addr); -void ISAFUNC(UASM_i_LA)(u32 **buf, unsigned int rs, long addr); +int uasm_rel_hi(long val); +int uasm_rel_lo(long val); +void UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr); +void UASM_i_LA(u32 **buf, unsigned int rs, long addr); #define UASM_L_LA(lb) \ -static inline void ISAFUNC(uasm_l##lb)(struct uasm_label **lab, u32 *addr) \ +static inline void uasm_l##lb(struct uasm_label **lab, u32 *addr) \ { \ - ISAFUNC(uasm_build_label)(lab, addr, label##lb); \ + uasm_build_label(lab, addr, label##lb); \ } /* convenience macros for instructions */ @@ -256,27 +225,27 @@ static inline void uasm_i_drotr_safe(u32 **p, unsigned int a1, unsigned int a2, unsigned int a3) { if (a3 < 32) - ISAOPC(_drotr)(p, a1, a2, a3); + uasm_i_drotr(p, a1, a2, a3); else - ISAOPC(_drotr32)(p, a1, a2, a3 - 32); + uasm_i_drotr32(p, a1, a2, a3 - 32); } static inline void uasm_i_dsll_safe(u32 **p, unsigned int a1, unsigned int a2, unsigned int a3) { if (a3 < 32) - ISAOPC(_dsll)(p, a1, a2, a3); + uasm_i_dsll(p, a1, a2, a3); else - ISAOPC(_dsll32)(p, a1, a2, a3 - 32); + uasm_i_dsll32(p, a1, a2, a3 - 32); } static inline void uasm_i_dsrl_safe(u32 **p, unsigned int a1, unsigned int a2, unsigned int a3) { if (a3 < 32) - ISAOPC(_dsrl)(p, a1, a2, a3); + uasm_i_dsrl(p, a1, a2, a3); else - ISAOPC(_dsrl32)(p, a1, a2, a3 - 32); + uasm_i_dsrl32(p, a1, a2, a3 - 32); } /* Handle relocations. */ diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 7f400c8d4645..730363b59bac 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -350,7 +350,7 @@ I_u2u1u3(_lddir) #ifdef CONFIG_CPU_CAVIUM_OCTEON #include -void ISAFUNC(uasm_i_pref)(u32 **buf, unsigned int a, signed int b, +void uasm_i_pref(u32 **buf, unsigned int a, signed int b, unsigned int c) { if (CAVIUM_OCTEON_DCACHE_PREFETCH_WAR && a <= 24 && a != 5) @@ -362,26 +362,26 @@ void ISAFUNC(uasm_i_pref)(u32 **buf, unsigned int a, signed int b, else build_insn(buf, insn_pref, c, a, b); } -UASM_EXPORT_SYMBOL(ISAFUNC(uasm_i_pref)); +UASM_EXPORT_SYMBOL(uasm_i_pref); #else I_u2s3u1(_pref) #endif /* Handle labels. */ -void ISAFUNC(uasm_build_label)(struct uasm_label **lab, u32 *addr, int lid) +void uasm_build_label(struct uasm_label **lab, u32 *addr, int lid) { (*lab)->addr = addr; (*lab)->lab = lid; (*lab)++; } -UASM_EXPORT_SYMBOL(ISAFUNC(uasm_build_label)); +UASM_EXPORT_SYMBOL(uasm_build_label); -int ISAFUNC(uasm_in_compat_space_p)(long addr) +int uasm_in_compat_space_p(long addr) { /* Is this address in 32bit compat space? */ return addr == (int)addr; } -UASM_EXPORT_SYMBOL(ISAFUNC(uasm_in_compat_space_p)); +UASM_EXPORT_SYMBOL(uasm_in_compat_space_p); static int uasm_rel_highest(long val) { @@ -401,64 +401,64 @@ static int uasm_rel_higher(long val) #endif } -int ISAFUNC(uasm_rel_hi)(long val) +int uasm_rel_hi(long val) { return ((((val + 0x8000L) >> 16) & 0xffff) ^ 0x8000) - 0x8000; } -UASM_EXPORT_SYMBOL(ISAFUNC(uasm_rel_hi)); +UASM_EXPORT_SYMBOL(uasm_rel_hi); -int ISAFUNC(uasm_rel_lo)(long val) +int uasm_rel_lo(long val) { return ((val & 0xffff) ^ 0x8000) - 0x8000; } -UASM_EXPORT_SYMBOL(ISAFUNC(uasm_rel_lo)); +UASM_EXPORT_SYMBOL(uasm_rel_lo); -void ISAFUNC(UASM_i_LA_mostly)(u32 **buf, unsigned int rs, long addr) +void UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr) { - if (!ISAFUNC(uasm_in_compat_space_p)(addr)) { - ISAFUNC(uasm_i_lui)(buf, rs, uasm_rel_highest(addr)); + if (!uasm_in_compat_space_p(addr)) { + uasm_i_lui(buf, rs, uasm_rel_highest(addr)); if (uasm_rel_higher(addr)) - ISAFUNC(uasm_i_daddiu)(buf, rs, rs, uasm_rel_higher(addr)); - if (ISAFUNC(uasm_rel_hi(addr))) { - ISAFUNC(uasm_i_dsll)(buf, rs, rs, 16); - ISAFUNC(uasm_i_daddiu)(buf, rs, rs, - ISAFUNC(uasm_rel_hi)(addr)); - ISAFUNC(uasm_i_dsll)(buf, rs, rs, 16); + uasm_i_daddiu(buf, rs, rs, uasm_rel_higher(addr)); + if (uasm_rel_hi(addr)) { + uasm_i_dsll(buf, rs, rs, 16); + uasm_i_daddiu(buf, rs, rs, + uasm_rel_hi(addr)); + uasm_i_dsll(buf, rs, rs, 16); } else - ISAFUNC(uasm_i_dsll32)(buf, rs, rs, 0); + uasm_i_dsll32(buf, rs, rs, 0); } else - ISAFUNC(uasm_i_lui)(buf, rs, ISAFUNC(uasm_rel_hi(addr))); + uasm_i_lui(buf, rs, uasm_rel_hi(addr)); } -UASM_EXPORT_SYMBOL(ISAFUNC(UASM_i_LA_mostly)); +UASM_EXPORT_SYMBOL(UASM_i_LA_mostly); -void ISAFUNC(UASM_i_LA)(u32 **buf, unsigned int rs, long addr) +void UASM_i_LA(u32 **buf, unsigned int rs, long addr) { - ISAFUNC(UASM_i_LA_mostly)(buf, rs, addr); - if (ISAFUNC(uasm_rel_lo(addr))) { - if (!ISAFUNC(uasm_in_compat_space_p)(addr)) - ISAFUNC(uasm_i_daddiu)(buf, rs, rs, - ISAFUNC(uasm_rel_lo(addr))); + UASM_i_LA_mostly(buf, rs, addr); + if (uasm_rel_lo(addr)) { + if (!uasm_in_compat_space_p(addr)) + uasm_i_daddiu(buf, rs, rs, + uasm_rel_lo(addr)); else - ISAFUNC(uasm_i_addiu)(buf, rs, rs, - ISAFUNC(uasm_rel_lo(addr))); + uasm_i_addiu(buf, rs, rs, + uasm_rel_lo(addr)); } } -UASM_EXPORT_SYMBOL(ISAFUNC(UASM_i_LA)); +UASM_EXPORT_SYMBOL(UASM_i_LA); /* Handle relocations. */ -void ISAFUNC(uasm_r_mips_pc16)(struct uasm_reloc **rel, u32 *addr, int lid) +void uasm_r_mips_pc16(struct uasm_reloc **rel, u32 *addr, int lid) { (*rel)->addr = addr; (*rel)->type = R_MIPS_PC16; (*rel)->lab = lid; (*rel)++; } -UASM_EXPORT_SYMBOL(ISAFUNC(uasm_r_mips_pc16)); +UASM_EXPORT_SYMBOL(uasm_r_mips_pc16); static inline void __resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab); -void ISAFUNC(uasm_resolve_relocs)(struct uasm_reloc *rel, +void uasm_resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab) { struct uasm_label *l; @@ -468,39 +468,39 @@ void ISAFUNC(uasm_resolve_relocs)(struct uasm_reloc *rel, if (rel->lab == l->lab) __resolve_relocs(rel, l); } -UASM_EXPORT_SYMBOL(ISAFUNC(uasm_resolve_relocs)); +UASM_EXPORT_SYMBOL(uasm_resolve_relocs); -void ISAFUNC(uasm_move_relocs)(struct uasm_reloc *rel, u32 *first, u32 *end, +void uasm_move_relocs(struct uasm_reloc *rel, u32 *first, u32 *end, long off) { for (; rel->lab != UASM_LABEL_INVALID; rel++) if (rel->addr >= first && rel->addr < end) rel->addr += off; } -UASM_EXPORT_SYMBOL(ISAFUNC(uasm_move_relocs)); +UASM_EXPORT_SYMBOL(uasm_move_relocs); -void ISAFUNC(uasm_move_labels)(struct uasm_label *lab, u32 *first, u32 *end, +void uasm_move_labels(struct uasm_label *lab, u32 *first, u32 *end, long off) { for (; lab->lab != UASM_LABEL_INVALID; lab++) if (lab->addr >= first && lab->addr < end) lab->addr += off; } -UASM_EXPORT_SYMBOL(ISAFUNC(uasm_move_labels)); +UASM_EXPORT_SYMBOL(uasm_move_labels); -void ISAFUNC(uasm_copy_handler)(struct uasm_reloc *rel, struct uasm_label *lab, +void uasm_copy_handler(struct uasm_reloc *rel, struct uasm_label *lab, u32 *first, u32 *end, u32 *target) { long off = (long)(target - first); memcpy(target, first, (end - first) * sizeof(u32)); - ISAFUNC(uasm_move_relocs(rel, first, end, off)); - ISAFUNC(uasm_move_labels(lab, first, end, off)); + uasm_move_relocs(rel, first, end, off); + uasm_move_labels(lab, first, end, off); } -UASM_EXPORT_SYMBOL(ISAFUNC(uasm_copy_handler)); +UASM_EXPORT_SYMBOL(uasm_copy_handler); -int ISAFUNC(uasm_insn_has_bdelay)(struct uasm_reloc *rel, u32 *addr) +int uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr) { for (; rel->lab != UASM_LABEL_INVALID; rel++) { if (rel->addr == addr @@ -511,92 +511,92 @@ int ISAFUNC(uasm_insn_has_bdelay)(struct uasm_reloc *rel, u32 *addr) return 0; } -UASM_EXPORT_SYMBOL(ISAFUNC(uasm_insn_has_bdelay)); +UASM_EXPORT_SYMBOL(uasm_insn_has_bdelay); /* Convenience functions for labeled branches. */ -void ISAFUNC(uasm_il_bltz)(u32 **p, struct uasm_reloc **r, unsigned int reg, +void uasm_il_bltz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); - ISAFUNC(uasm_i_bltz)(p, reg, 0); + uasm_i_bltz(p, reg, 0); } -UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bltz)); +UASM_EXPORT_SYMBOL(uasm_il_bltz); -void ISAFUNC(uasm_il_b)(u32 **p, struct uasm_reloc **r, int lid) +void uasm_il_b(u32 **p, struct uasm_reloc **r, int lid) { uasm_r_mips_pc16(r, *p, lid); - ISAFUNC(uasm_i_b)(p, 0); + uasm_i_b(p, 0); } -UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_b)); +UASM_EXPORT_SYMBOL(uasm_il_b); -void ISAFUNC(uasm_il_beq)(u32 **p, struct uasm_reloc **r, unsigned int r1, +void uasm_il_beq(u32 **p, struct uasm_reloc **r, unsigned int r1, unsigned int r2, int lid) { uasm_r_mips_pc16(r, *p, lid); - ISAFUNC(uasm_i_beq)(p, r1, r2, 0); + uasm_i_beq(p, r1, r2, 0); } -UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beq)); +UASM_EXPORT_SYMBOL(uasm_il_beq); -void ISAFUNC(uasm_il_beqz)(u32 **p, struct uasm_reloc **r, unsigned int reg, +void uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); - ISAFUNC(uasm_i_beqz)(p, reg, 0); + uasm_i_beqz(p, reg, 0); } -UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beqz)); +UASM_EXPORT_SYMBOL(uasm_il_beqz); -void ISAFUNC(uasm_il_beqzl)(u32 **p, struct uasm_reloc **r, unsigned int reg, +void uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); - ISAFUNC(uasm_i_beqzl)(p, reg, 0); + uasm_i_beqzl(p, reg, 0); } -UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beqzl)); +UASM_EXPORT_SYMBOL(uasm_il_beqzl); -void ISAFUNC(uasm_il_bne)(u32 **p, struct uasm_reloc **r, unsigned int reg1, +void uasm_il_bne(u32 **p, struct uasm_reloc **r, unsigned int reg1, unsigned int reg2, int lid) { uasm_r_mips_pc16(r, *p, lid); - ISAFUNC(uasm_i_bne)(p, reg1, reg2, 0); + uasm_i_bne(p, reg1, reg2, 0); } -UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bne)); +UASM_EXPORT_SYMBOL(uasm_il_bne); -void ISAFUNC(uasm_il_bnez)(u32 **p, struct uasm_reloc **r, unsigned int reg, +void uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); - ISAFUNC(uasm_i_bnez)(p, reg, 0); + uasm_i_bnez(p, reg, 0); } -UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bnez)); +UASM_EXPORT_SYMBOL(uasm_il_bnez); -void ISAFUNC(uasm_il_bgezl)(u32 **p, struct uasm_reloc **r, unsigned int reg, +void uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); - ISAFUNC(uasm_i_bgezl)(p, reg, 0); + uasm_i_bgezl(p, reg, 0); } -UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bgezl)); +UASM_EXPORT_SYMBOL(uasm_il_bgezl); -void ISAFUNC(uasm_il_bgez)(u32 **p, struct uasm_reloc **r, unsigned int reg, +void uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); - ISAFUNC(uasm_i_bgez)(p, reg, 0); + uasm_i_bgez(p, reg, 0); } -UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bgez)); +UASM_EXPORT_SYMBOL(uasm_il_bgez); -void ISAFUNC(uasm_il_bbit0)(u32 **p, struct uasm_reloc **r, unsigned int reg, +void uasm_il_bbit0(u32 **p, struct uasm_reloc **r, unsigned int reg, unsigned int bit, int lid) { uasm_r_mips_pc16(r, *p, lid); - ISAFUNC(uasm_i_bbit0)(p, reg, bit, 0); + uasm_i_bbit0(p, reg, bit, 0); } -UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bbit0)); +UASM_EXPORT_SYMBOL(uasm_il_bbit0); -void ISAFUNC(uasm_il_bbit1)(u32 **p, struct uasm_reloc **r, unsigned int reg, +void uasm_il_bbit1(u32 **p, struct uasm_reloc **r, unsigned int reg, unsigned int bit, int lid) { uasm_r_mips_pc16(r, *p, lid); - ISAFUNC(uasm_i_bbit1)(p, reg, bit, 0); + uasm_i_bbit1(p, reg, bit, 0); } -UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bbit1)); +UASM_EXPORT_SYMBOL(uasm_il_bbit1); -- cgit v1.2.3-59-g8ed1b From f9c4e3a6dae1a3a15055ea478438cdc0352e1af2 Mon Sep 17 00:00:00 2001 From: James Cowgill Date: Fri, 31 Mar 2017 17:09:58 +0100 Subject: MIPS: Opt into HAVE_COPY_THREAD_TLS This the mips version of commit c1bd55f922a2d ("x86: opt into HAVE_COPY_THREAD_TLS, for both 32-bit and 64-bit"). Simply use the tls system call argument instead of extracting the tls argument by magic from the pt_regs structure. See commit 3033f14ab78c3 ("clone: support passing tls argument via C rather than pt_regs magic") for more background. Signed-off-by: James Cowgill Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/15855/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 + arch/mips/kernel/process.c | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 2afb41c52ba0..52d81ca6f74e 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -70,6 +70,7 @@ config MIPS select HAVE_EXIT_THREAD select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_ARCH_HARDENED_USERCOPY + select HAVE_COPY_THREAD_TLS menu "Machine selection" diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index b68e10fc453d..918d4c73e951 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -114,8 +114,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) /* * Copy architecture-specific thread state */ -int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long kthread_arg, struct task_struct *p) +int copy_thread_tls(unsigned long clone_flags, unsigned long usp, + unsigned long kthread_arg, struct task_struct *p, unsigned long tls) { struct thread_info *ti = task_thread_info(p); struct pt_regs *childregs, *regs = current_pt_regs(); @@ -176,7 +176,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, atomic_set(&p->thread.bd_emu_frame, BD_EMUFRAME_NONE); if (clone_flags & CLONE_SETTLS) - ti->tp_value = regs->regs[7]; + ti->tp_value = tls; return 0; } -- cgit v1.2.3-59-g8ed1b From 1e548da5cef1f7148ce625f0bb0272ae2657cb1f Mon Sep 17 00:00:00 2001 From: Marcin Nowakowski Date: Mon, 13 Mar 2017 14:33:37 +0100 Subject: MIPS: mach-rm: Remove recursive include of cpu-feature-overrides.h cpu-feautre-overrides.h in mach-rm unnecessarily includes itself, so drop the pointless include Signed-off-by: Marcin Nowakowski Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/15462/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mach-rm/cpu-feature-overrides.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/mach-rm/cpu-feature-overrides.h b/arch/mips/include/asm/mach-rm/cpu-feature-overrides.h index 98cf40417c5d..d38be668e338 100644 --- a/arch/mips/include/asm/mach-rm/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-rm/cpu-feature-overrides.h @@ -10,8 +10,6 @@ #ifndef __ASM_MACH_RM200_CPU_FEATURE_OVERRIDES_H #define __ASM_MACH_RM200_CPU_FEATURE_OVERRIDES_H -#include - #define cpu_has_tlb 1 #define cpu_has_4kex 1 #define cpu_has_4k_cache 1 -- cgit v1.2.3-59-g8ed1b From f110cc4f9b2b456501c839d02412544c9656c2cc Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Fri, 31 Mar 2017 16:21:24 +0100 Subject: MIPS: generic: Enable Root FS on NFS in generic_defconfig The generic_defconfig is used for platforms like SEAD3 which do not usually have fixed storage available, therefore NFS is the preferred location of the RFS. When the upstream kernel defconfig is built & tested on platforms such as SEAD3 this leads to essentially false failures when the RFS fails to mount. There is little harm in having this feature enabled by default, so enable it in the defconfig. Kernel autoconfiguration & DHCP must also be selected to allow RFS on NFS. Signed-off-by: Matt Redfearn Cc: James Hogan Cc: Paul Burton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/15853/ Signed-off-by: Ralf Baechle --- arch/mips/configs/generic_defconfig | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/mips/configs/generic_defconfig b/arch/mips/configs/generic_defconfig index c95d94c7838b..91aacf2ef26d 100644 --- a/arch/mips/configs/generic_defconfig +++ b/arch/mips/configs/generic_defconfig @@ -36,6 +36,8 @@ CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y CONFIG_NETFILTER=y # CONFIG_WIRELESS is not set CONFIG_DEVTMPFS=y @@ -80,6 +82,7 @@ CONFIG_NFS_V3_ACL=y CONFIG_NFS_V4=y CONFIG_NFS_V4_1=y CONFIG_NFS_V4_2=y +CONFIG_ROOT_NFS=y CONFIG_PRINTK_TIME=y CONFIG_DEBUG_INFO=y CONFIG_DEBUG_INFO_REDUCED=y -- cgit v1.2.3-59-g8ed1b From ca452b95e3be1cbd86ee60165de640d27ddca8b7 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 30 Mar 2017 13:51:59 -0700 Subject: MIPS: Remove CONFIG_ARCH_HAS_ILOG2_U{32,64} We declare CONFIG_ARCH_HAS_ILOG2_U32 & CONFIG_ARCH_HAS_ILOG2_U64 in Kconfig, but they are always false since nothing ever selects them. The generic fls-based implementation is efficient for MIPS anyway. Remove the redundant Kconfig entries. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: trivial@kernel.org Patchwork: https://patchwork.linux-mips.org/patch/15840/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 8 -------- 1 file changed, 8 deletions(-) (limited to 'arch') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 52d81ca6f74e..1f8ebdf75734 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1042,14 +1042,6 @@ config RWSEM_GENERIC_SPINLOCK config RWSEM_XCHGADD_ALGORITHM bool -config ARCH_HAS_ILOG2_U32 - bool - default n - -config ARCH_HAS_ILOG2_U64 - bool - default n - config GENERIC_HWEIGHT bool default y -- cgit v1.2.3-59-g8ed1b From ebf003f0cfb3705e60d40dedc3ec949176c741af Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Wed, 12 Apr 2017 12:43:52 -0700 Subject: kbuild: Consolidate header generation from ASM offset information Largely redundant code is used in different places to generate C headers from offset information extracted from assembly language output. Consolidate the code in Makefile.lib and use this instead. Signed-off-by: Matthias Kaehlcke Signed-off-by: Masahiro Yamada --- Kbuild | 25 ------------------------- arch/ia64/kernel/Makefile | 26 ++------------------------ scripts/Makefile.lib | 28 ++++++++++++++++++++++++++++ scripts/mod/Makefile | 28 ++-------------------------- 4 files changed, 32 insertions(+), 75 deletions(-) (limited to 'arch') diff --git a/Kbuild b/Kbuild index 3d0ae152af7c..94c752762bc2 100644 --- a/Kbuild +++ b/Kbuild @@ -7,31 +7,6 @@ # 4) Check for missing system calls # 5) Generate constants.py (may need bounds.h) -# Default sed regexp - multiline due to syntax constraints -define sed-y - "/^->/{s:->#\(.*\):/* \1 */:; \ - s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \ - s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \ - s:->::; p;}" -endef - -# Use filechk to avoid rebuilds when a header changes, but the resulting file -# does not -define filechk_offsets - (set -e; \ - echo "#ifndef $2"; \ - echo "#define $2"; \ - echo "/*"; \ - echo " * DO NOT MODIFY."; \ - echo " *"; \ - echo " * This file was generated by Kbuild"; \ - echo " */"; \ - echo ""; \ - sed -ne $(sed-y); \ - echo ""; \ - echo "#endif" ) -endef - ##### # 1) Generate bounds.h diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index 3686d6abafde..9edda5466020 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -50,32 +50,10 @@ CFLAGS_traps.o += -mfixed-range=f2-f5,f16-f31 # The gate DSO image is built using a special linker script. include $(src)/Makefile.gate -# Calculate NR_IRQ = max(IA64_NATIVE_NR_IRQS, XEN_NR_IRQS, ...) based on config -define sed-y - "/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}" -endef -quiet_cmd_nr_irqs = GEN $@ -define cmd_nr_irqs - (set -e; \ - echo "#ifndef __ASM_NR_IRQS_H__"; \ - echo "#define __ASM_NR_IRQS_H__"; \ - echo "/*"; \ - echo " * DO NOT MODIFY."; \ - echo " *"; \ - echo " * This file was generated by Kbuild"; \ - echo " *"; \ - echo " */"; \ - echo ""; \ - sed -ne $(sed-y) $<; \ - echo ""; \ - echo "#endif" ) > $@ -endef - # We use internal kbuild rules to avoid the "is up to date" message from make arch/$(SRCARCH)/kernel/nr-irqs.s: arch/$(SRCARCH)/kernel/nr-irqs.c $(Q)mkdir -p $(dir $@) $(call if_changed_dep,cc_s_c) -include/generated/nr-irqs.h: arch/$(SRCARCH)/kernel/nr-irqs.s - $(Q)mkdir -p $(dir $@) - $(call cmd,nr_irqs) +include/generated/nr-irqs.h: arch/$(SRCARCH)/kernel/nr-irqs.s FORCE + $(call filechk,offsets,__ASM_NR_IRQS_H__) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 0a07f9014944..dd567e5d59e0 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -408,3 +408,31 @@ quiet_cmd_xzmisc = XZMISC $@ cmd_xzmisc = (cat $(filter-out FORCE,$^) | \ xz --check=crc32 --lzma2=dict=1MiB) > $@ || \ (rm -f $@ ; false) + +# ASM offsets +# --------------------------------------------------------------------------- + +# Default sed regexp - multiline due to syntax constraints +define sed-offsets + "/^->/{s:->#\(.*\):/* \1 */:; \ + s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \ + s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \ + s:->::; p;}" +endef + +# Use filechk to avoid rebuilds when a header changes, but the resulting file +# does not +define filechk_offsets + (set -e; \ + echo "#ifndef $2"; \ + echo "#define $2"; \ + echo "/*"; \ + echo " * DO NOT MODIFY."; \ + echo " *"; \ + echo " * This file was generated by Kbuild"; \ + echo " */"; \ + echo ""; \ + sed -ne $(sed-offsets); \ + echo ""; \ + echo "#endif" ) +endef diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile index 19d9bcadc0cc..b497d9764dcf 100644 --- a/scripts/mod/Makefile +++ b/scripts/mod/Makefile @@ -7,32 +7,8 @@ modpost-objs := modpost.o file2alias.o sumversion.o devicetable-offsets-file := devicetable-offsets.h -define sed-y - "/^->/{s:->#\(.*\):/* \1 */:; \ - s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \ - s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \ - s:->::; p;}" -endef - -quiet_cmd_offsets = GEN $@ -define cmd_offsets - (set -e; \ - echo "#ifndef __DEVICETABLE_OFFSETS_H__"; \ - echo "#define __DEVICETABLE_OFFSETS_H__"; \ - echo "/*"; \ - echo " * DO NOT MODIFY."; \ - echo " *"; \ - echo " * This file was generated by Kbuild"; \ - echo " *"; \ - echo " */"; \ - echo ""; \ - sed -ne $(sed-y) $<; \ - echo ""; \ - echo "#endif" ) > $@ -endef - -$(obj)/$(devicetable-offsets-file): $(obj)/devicetable-offsets.s - $(call if_changed,offsets) +$(obj)/$(devicetable-offsets-file): $(obj)/devicetable-offsets.s FORCE + $(call filechk,offsets,__DEVICETABLE_OFFSETS_H__) targets += $(devicetable-offsets-file) devicetable-offsets.s -- cgit v1.2.3-59-g8ed1b From 1eed40043579608e16509c43eeeb3a53a8a42378 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 30 Mar 2017 12:06:12 -0700 Subject: MIPS: smp-mt: Use CPU interrupt controller IPI IRQ domain support Remove the smp-mt IPI code that supported single-core multithreaded systems and instead make use of the IPI IRQ domain support provided by the MIPS CPU interrupt controller driver. This removes some less than nice code, the horrible split between arch & board code and the duplication that led to within board code. The lantiq portion of this patch has only been compile tested. Malta has been tested & is functional. Signed-off-by: Paul Burton Cc: Thomas Gleixner Cc: Jason Cooper Cc: Marc Zyngier Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/15837/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/smp-mt.c | 49 ++---------------------- arch/mips/lantiq/irq.c | 52 -------------------------- arch/mips/mti-malta/malta-int.c | 83 ++--------------------------------------- 3 files changed, 8 insertions(+), 176 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index e398cbc3d776..ed6b4df583ea 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -83,6 +83,8 @@ static unsigned int __init smvp_vpe_init(unsigned int tc, unsigned int mvpconf0, if (tc != 0) smvp_copy_vpe_config(); + cpu_data[ncpu].vpe_id = tc; + return ncpu; } @@ -114,49 +116,6 @@ static void __init smvp_tc_init(unsigned int tc, unsigned int mvpconf0) write_tc_c0_tchalt(TCHALT_H); } -static void vsmp_send_ipi_single(int cpu, unsigned int action) -{ - int i; - unsigned long flags; - int vpflags; - -#ifdef CONFIG_MIPS_GIC - if (gic_present) { - mips_smp_send_ipi_single(cpu, action); - return; - } -#endif - local_irq_save(flags); - - vpflags = dvpe(); /* can't access the other CPU's registers whilst MVPE enabled */ - - switch (action) { - case SMP_CALL_FUNCTION: - i = C_SW1; - break; - - case SMP_RESCHEDULE_YOURSELF: - default: - i = C_SW0; - break; - } - - /* 1:1 mapping of vpe and tc... */ - settc(cpu); - write_vpe_c0_cause(read_vpe_c0_cause() | i); - evpe(vpflags); - - local_irq_restore(flags); -} - -static void vsmp_send_ipi_mask(const struct cpumask *mask, unsigned int action) -{ - unsigned int i; - - for_each_cpu(i, mask) - vsmp_send_ipi_single(i, action); -} - static void vsmp_init_secondary(void) { #ifdef CONFIG_MIPS_GIC @@ -281,8 +240,8 @@ static void __init vsmp_prepare_cpus(unsigned int max_cpus) } struct plat_smp_ops vsmp_smp_ops = { - .send_ipi_single = vsmp_send_ipi_single, - .send_ipi_mask = vsmp_send_ipi_mask, + .send_ipi_single = mips_smp_send_ipi_single, + .send_ipi_mask = mips_smp_send_ipi_mask, .init_secondary = vsmp_init_secondary, .smp_finish = vsmp_smp_finish, .boot_secondary = vsmp_boot_secondary, diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c index 0ddf3698b85d..33728b7af426 100644 --- a/arch/mips/lantiq/irq.c +++ b/arch/mips/lantiq/irq.c @@ -274,47 +274,6 @@ static void ltq_hw_irq_handler(struct irq_desc *desc) ltq_hw_irqdispatch(irq_desc_get_irq(desc) - 2); } -#ifdef CONFIG_MIPS_MT_SMP -void __init arch_init_ipiirq(int irq, struct irqaction *action) -{ - setup_irq(irq, action); - irq_set_handler(irq, handle_percpu_irq); -} - -static void ltq_sw0_irqdispatch(void) -{ - do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ); -} - -static void ltq_sw1_irqdispatch(void) -{ - do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ); -} -static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id) -{ - scheduler_ipi(); - return IRQ_HANDLED; -} - -static irqreturn_t ipi_call_interrupt(int irq, void *dev_id) -{ - generic_smp_call_function_interrupt(); - return IRQ_HANDLED; -} - -static struct irqaction irq_resched = { - .handler = ipi_resched_interrupt, - .flags = IRQF_PERCPU, - .name = "IPI_resched" -}; - -static struct irqaction irq_call = { - .handler = ipi_call_interrupt, - .flags = IRQF_PERCPU, - .name = "IPI_call" -}; -#endif - asmlinkage void plat_irq_dispatch(void) { unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; @@ -402,17 +361,6 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent) (MAX_IM * INT_NUM_IM_OFFSET) + MIPS_CPU_IRQ_CASCADE, &irq_domain_ops, 0); -#if defined(CONFIG_MIPS_MT_SMP) - if (cpu_has_vint) { - pr_info("Setting up IPI vectored interrupts\n"); - set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ltq_sw0_irqdispatch); - set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ltq_sw1_irqdispatch); - } - arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ, - &irq_resched); - arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ, &irq_call); -#endif - #ifndef CONFIG_MIPS_MT_SMP set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5); diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index cb675ec6f283..fe9bb479f2a0 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c @@ -145,56 +145,6 @@ static irqreturn_t corehi_handler(int irq, void *dev_id) return IRQ_HANDLED; } -#ifdef CONFIG_MIPS_MT_SMP - -#define MIPS_CPU_IPI_RESCHED_IRQ 0 /* SW int 0 for resched */ -#define C_RESCHED C_SW0 -#define MIPS_CPU_IPI_CALL_IRQ 1 /* SW int 1 for resched */ -#define C_CALL C_SW1 -static int cpu_ipi_resched_irq, cpu_ipi_call_irq; - -static void ipi_resched_dispatch(void) -{ - do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ); -} - -static void ipi_call_dispatch(void) -{ - do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ); -} - -static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id) -{ -#ifdef CONFIG_MIPS_VPE_APSP_API_CMP - if (aprp_hook) - aprp_hook(); -#endif - - scheduler_ipi(); - - return IRQ_HANDLED; -} - -static irqreturn_t ipi_call_interrupt(int irq, void *dev_id) -{ - generic_smp_call_function_interrupt(); - - return IRQ_HANDLED; -} - -static struct irqaction irq_resched = { - .handler = ipi_resched_interrupt, - .flags = IRQF_PERCPU, - .name = "IPI_resched" -}; - -static struct irqaction irq_call = { - .handler = ipi_call_interrupt, - .flags = IRQF_PERCPU, - .name = "IPI_call" -}; -#endif /* CONFIG_MIPS_MT_SMP */ - static struct irqaction corehi_irqaction = { .handler = corehi_handler, .name = "CoreHi", @@ -222,12 +172,6 @@ static msc_irqmap_t msc_eicirqmap[] __initdata = { static int msc_nr_eicirqs __initdata = ARRAY_SIZE(msc_eicirqmap); -void __init arch_init_ipiirq(int irq, struct irqaction *action) -{ - setup_irq(irq, action); - irq_set_handler(irq, handle_percpu_irq); -} - void __init arch_init_irq(void) { int corehi_irq; @@ -262,30 +206,11 @@ void __init arch_init_irq(void) if (gic_present) { corehi_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_COREHI; + } else if (cpu_has_veic) { + set_vi_handler(MSC01E_INT_COREHI, corehi_irqdispatch); + corehi_irq = MSC01E_INT_BASE + MSC01E_INT_COREHI; } else { -#if defined(CONFIG_MIPS_MT_SMP) - /* set up ipi interrupts */ - if (cpu_has_veic) { - set_vi_handler (MSC01E_INT_SW0, ipi_resched_dispatch); - set_vi_handler (MSC01E_INT_SW1, ipi_call_dispatch); - cpu_ipi_resched_irq = MSC01E_INT_SW0; - cpu_ipi_call_irq = MSC01E_INT_SW1; - } else { - cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + - MIPS_CPU_IPI_RESCHED_IRQ; - cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + - MIPS_CPU_IPI_CALL_IRQ; - } - arch_init_ipiirq(cpu_ipi_resched_irq, &irq_resched); - arch_init_ipiirq(cpu_ipi_call_irq, &irq_call); -#endif - if (cpu_has_veic) { - set_vi_handler(MSC01E_INT_COREHI, - corehi_irqdispatch); - corehi_irq = MSC01E_INT_BASE + MSC01E_INT_COREHI; - } else { - corehi_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_COREHI; - } + corehi_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_COREHI; } setup_irq(corehi_irq, &corehi_irqaction); -- cgit v1.2.3-59-g8ed1b From e64889823d58305a5ddb2828ae0a988c59e87d7e Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 30 Mar 2017 12:06:13 -0700 Subject: MIPS: Stengthen IPI IRQ domain sanity check Commit fbde2d7d8290 ("MIPS: Add generic SMP IPI support") introduced a sanity check that an IPI IRQ domain can be found during boot, in order to ensure that IPIs are able to be set up in systems using such domains. However it was added at a point where systems may have used an IPI IRQ domain in some situations but not others, and we could not know which were the case until runtime, so commit 578bffc82ec5 ("MIPS: Don't BUG_ON when no IPI domain is found") made that check simply skip IPI init if no domain were found in order to fix the boot for systems such as QEMU Malta. We now use IPI IRQ domains for the MIPS CPU interrupt controller, which means systems which make use of IPI IRQ domains will always do so when running on multiple CPUs. As a result we now strengthen the sanity check to ensure that an IPI IRQ domain is found when multiple CPUs are present in the system. Signed-off-by: Paul Burton Cc: Thomas Gleixner Cc: Jason Cooper Cc: Marc Zyngier Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/15838/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/smp.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 6e71130549ea..aba1afb64b62 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -261,16 +261,20 @@ int mips_smp_ipi_allocate(const struct cpumask *mask) ipidomain = irq_find_matching_host(NULL, DOMAIN_BUS_IPI); /* - * There are systems which only use IPI domains some of the time, - * depending upon configuration we don't know until runtime. An - * example is Malta where we may compile in support for GIC & the - * MT ASE, but run on a system which has multiple VPEs in a single - * core and doesn't include a GIC. Until all IPI implementations - * have been converted to use IPI domains the best we can do here - * is to return & hope some other code sets up the IPIs. + * There are systems which use IPI IRQ domains, but only have one + * registered when some runtime condition is met. For example a Malta + * kernel may include support for GIC & CPU interrupt controller IPI + * IRQ domains, but if run on a system with no GIC & no MT ASE then + * neither will be supported or registered. + * + * We only have a problem if we're actually using multiple CPUs so fail + * loudly if that is the case. Otherwise simply return, skipping IPI + * setup, if we're running with only a single CPU. */ - if (!ipidomain) + if (!ipidomain) { + BUG_ON(num_present_cpus() > 1); return 0; + } virq = irq_reserve_ipi(ipidomain, mask); BUG_ON(!virq); -- cgit v1.2.3-59-g8ed1b From 72f941af88a543e6a038c75b8467903b7812239c Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 30 Mar 2017 14:27:02 -0700 Subject: MIPS: Remove confusing else statement in __do_page_fault() Commit 41c594ab65fc ("[MIPS] MT: Improved multithreading support.") added an else case to an if statement in do_page_fault() (which has since gained 2 leading underscores) for some unclear reason. If the condition in the if statement evaluates true then we execute a goto & branch elsewhere anyway, so the else has no effect. Combined with an #if 0 block with misleading indentation introduced in the same commit it makes the code less clear than it could be. Remove the unnecessary else statement & de-indent the printk within the #if 0 block in order to make the code easier for humans to parse. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: trivial@kernel.org Patchwork: https://patchwork.linux-mips.org/patch/15842/ Signed-off-by: Ralf Baechle --- arch/mips/mm/fault.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c index 3bef306cdfdb..4f8f5bf46977 100644 --- a/arch/mips/mm/fault.c +++ b/arch/mips/mm/fault.c @@ -267,19 +267,19 @@ do_sigbus: /* Kernel mode? Handle exceptions or die */ if (!user_mode(regs)) goto no_context; - else + /* * Send a sigbus, regardless of whether we were in kernel * or user mode. */ #if 0 - printk("do_page_fault() #3: sending SIGBUS to %s for " - "invalid %s\n%0*lx (epc == %0*lx, ra == %0*lx)\n", - tsk->comm, - write ? "write access to" : "read access from", - field, address, - field, (unsigned long) regs->cp0_epc, - field, (unsigned long) regs->regs[31]); + printk("do_page_fault() #3: sending SIGBUS to %s for " + "invalid %s\n%0*lx (epc == %0*lx, ra == %0*lx)\n", + tsk->comm, + write ? "write access to" : "read access from", + field, address, + field, (unsigned long) regs->cp0_epc, + field, (unsigned long) regs->regs[31]); #endif current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f; tsk->thread.cp0_badvaddr = address; -- cgit v1.2.3-59-g8ed1b From 7ee06cb2f840a96be46233181ed4557901a74385 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 8 Apr 2017 19:54:20 +0200 Subject: x86: i8259: export legacy_pic symbol The classic PC rtc-coms driver has a workaround for broken ACPI device nodes for it which lack an irq resource. This workaround used to unconditionally hardcode the irq to 8 in these cases. This was causing irq conflict problems on systems without a legacy-pic so a recent patch added an if (nr_legacy_irqs()) guard to the workaround to avoid this irq conflict. nr_legacy_irqs() uses the legacy_pic symbol under the hood causing an undefined symbol error if the rtc-cmos code is build as a module. This commit exports the legacy_pic symbol to fix this. Cc: rtc-linux@googlegroups.com Cc: alexandre.belloni@free-electrons.com Signed-off-by: Hans de Goede Signed-off-by: Alexandre Belloni --- arch/x86/kernel/i8259.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c index be22f5a2192e..4e3b8a587c88 100644 --- a/arch/x86/kernel/i8259.c +++ b/arch/x86/kernel/i8259.c @@ -418,6 +418,7 @@ struct legacy_pic default_legacy_pic = { }; struct legacy_pic *legacy_pic = &default_legacy_pic; +EXPORT_SYMBOL(legacy_pic); static int __init i8259A_init_ops(void) { -- cgit v1.2.3-59-g8ed1b From 20c994e4d806e0c656b5fe0d14b17896b73a086c Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Mon, 3 Apr 2017 12:46:36 -0700 Subject: frv: Use OFFSET macro in DEF_*REG() Avoid code duplication by using OFFSET() in DEF_*REG() instead of replicating the macro. Signed-off-by: Matthias Kaehlcke Reviewed-by: David Howells Signed-off-by: Masahiro Yamada --- arch/frv/kernel/asm-offsets.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/frv/kernel/asm-offsets.c b/arch/frv/kernel/asm-offsets.c index 8414293f213a..20c5b79b55f9 100644 --- a/arch/frv/kernel/asm-offsets.c +++ b/arch/frv/kernel/asm-offsets.c @@ -14,21 +14,10 @@ #include #include -#define DEF_PTREG(sym, reg) \ - asm volatile("\n->" #sym " %0 offsetof(struct pt_regs, " #reg ")" \ - : : "i" (offsetof(struct pt_regs, reg))) - -#define DEF_IREG(sym, reg) \ - asm volatile("\n->" #sym " %0 offsetof(struct user_context, " #reg ")" \ - : : "i" (offsetof(struct user_context, reg))) - -#define DEF_FREG(sym, reg) \ - asm volatile("\n->" #sym " %0 offsetof(struct user_context, " #reg ")" \ - : : "i" (offsetof(struct user_context, reg))) - -#define DEF_0REG(sym, reg) \ - asm volatile("\n->" #sym " %0 offsetof(struct frv_frame0, " #reg ")" \ - : : "i" (offsetof(struct frv_frame0, reg))) +#define DEF_PTREG(sym, reg) OFFSET(sym, pt_regs, reg) +#define DEF_IREG(sym, reg) OFFSET(sym, user_context, reg) +#define DEF_FREG(sym, reg) OFFSET(sym, user_context, reg) +#define DEF_0REG(sym, reg) OFFSET(sym, frv_frame0, reg) void foo(void) { -- cgit v1.2.3-59-g8ed1b From 77e5849688670280b173bb9e0544e9da7b2acc36 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sat, 14 Jan 2017 13:32:50 -0800 Subject: rcu: Make arch select smp_mb__after_unlock_lock() strength The definition of smp_mb__after_unlock_lock() is currently smp_mb() for CONFIG_PPC and a no-op otherwise. It would be better to instead provide an architecture-selectable Kconfig option, and select the strength of smp_mb__after_unlock_lock() based on that option. This commit therefore creates ARCH_WEAK_RELEASE_ACQUIRE, has PPC select it, and bases the definition of smp_mb__after_unlock_lock() on this new ARCH_WEAK_RELEASE_ACQUIRE Kconfig option. Reported-by: Ingo Molnar Signed-off-by: Paul E. McKenney Cc: Peter Zijlstra Cc: Will Deacon Cc: Boqun Feng Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Acked-by: Michael Ellerman Cc: Reviewed-by: Josh Triplett --- arch/Kconfig | 3 +++ arch/powerpc/Kconfig | 1 + include/linux/rcupdate.h | 6 +++--- 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/Kconfig b/arch/Kconfig index cd211a14a88f..adefaf344239 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -320,6 +320,9 @@ config HAVE_CMPXCHG_LOCAL config HAVE_CMPXCHG_DOUBLE bool +config ARCH_WEAK_RELEASE_ACQUIRE + bool + config ARCH_WANT_IPC_PARSE_VERSION bool diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 97a8bc8a095c..7a5c9b764cd2 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -99,6 +99,7 @@ config PPC select ARCH_USE_BUILTIN_BSWAP select ARCH_USE_CMPXCHG_LOCKREF if PPC64 select ARCH_WANT_IPC_PARSE_VERSION + select ARCH_WEAK_RELEASE_ACQUIRE select BINFMT_ELF select BUILDTIME_EXTABLE_SORT select CLONE_BACKWARDS diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index de88b33c0974..e6146d0074f8 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -1127,11 +1127,11 @@ do { \ * if the UNLOCK and LOCK are executed by the same CPU or if the * UNLOCK and LOCK operate on the same lock variable. */ -#ifdef CONFIG_PPC +#ifdef CONFIG_ARCH_WEAK_RELEASE_ACQUIRE #define smp_mb__after_unlock_lock() smp_mb() /* Full ordering for lock. */ -#else /* #ifdef CONFIG_PPC */ +#else /* #ifdef CONFIG_ARCH_WEAK_RELEASE_ACQUIRE */ #define smp_mb__after_unlock_lock() do { } while (0) -#endif /* #else #ifdef CONFIG_PPC */ +#endif /* #else #ifdef CONFIG_ARCH_WEAK_RELEASE_ACQUIRE */ #endif /* __LINUX_RCUPDATE_H */ -- cgit v1.2.3-59-g8ed1b From b913efe78a7ce1b2e64af7e5dc3a03748b997c61 Mon Sep 17 00:00:00 2001 From: Sricharan R Date: Mon, 10 Apr 2017 16:51:04 +0530 Subject: arm64: dma-mapping: Remove the notifier trick to handle early setting of dma_ops With arch_setup_dma_ops now being called late during device's probe after the device's iommu is probed, the notifier trick required to handle the early setup of dma_ops before the iommu group gets created is not required. So removing the notifier's here. Tested-by: Marek Szyprowski Tested-by: Hanjun Guo Acked-by: Will Deacon Signed-off-by: Sricharan R [rm: clean up even more] Signed-off-by: Robin Murphy Signed-off-by: Joerg Roedel --- arch/arm64/mm/dma-mapping.c | 142 ++++++-------------------------------------- 1 file changed, 18 insertions(+), 124 deletions(-) (limited to 'arch') diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c index 81cdb2e844ed..b46575954032 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c @@ -813,34 +813,26 @@ static const struct dma_map_ops iommu_dma_ops = { .mapping_error = iommu_dma_mapping_error, }; -/* - * TODO: Right now __iommu_setup_dma_ops() gets called too early to do - * everything it needs to - the device is only partially created and the - * IOMMU driver hasn't seen it yet, so it can't have a group. Thus we - * need this delayed attachment dance. Once IOMMU probe ordering is sorted - * to move the arch_setup_dma_ops() call later, all the notifier bits below - * become unnecessary, and will go away. - */ -struct iommu_dma_notifier_data { - struct list_head list; - struct device *dev; - const struct iommu_ops *ops; - u64 dma_base; - u64 size; -}; -static LIST_HEAD(iommu_dma_masters); -static DEFINE_MUTEX(iommu_dma_notifier_lock); +static int __init __iommu_dma_init(void) +{ + return iommu_dma_init(); +} +arch_initcall(__iommu_dma_init); -static bool do_iommu_attach(struct device *dev, const struct iommu_ops *ops, - u64 dma_base, u64 size) +static void __iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, + const struct iommu_ops *ops) { - struct iommu_domain *domain = iommu_get_domain_for_dev(dev); + struct iommu_domain *domain; + + if (!ops) + return; /* - * If the IOMMU driver has the DMA domain support that we require, - * then the IOMMU core will have already configured a group for this - * device, and allocated the default domain for that group. + * The IOMMU core code allocates the default DMA domain, which the + * underlying IOMMU driver needs to support via the dma-iommu layer. */ + domain = iommu_get_domain_for_dev(dev); + if (!domain) goto out_err; @@ -851,109 +843,11 @@ static bool do_iommu_attach(struct device *dev, const struct iommu_ops *ops, dev->dma_ops = &iommu_dma_ops; } - return true; + return; + out_err: - pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n", + pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n", dev_name(dev)); - return false; -} - -static void queue_iommu_attach(struct device *dev, const struct iommu_ops *ops, - u64 dma_base, u64 size) -{ - struct iommu_dma_notifier_data *iommudata; - - iommudata = kzalloc(sizeof(*iommudata), GFP_KERNEL); - if (!iommudata) - return; - - iommudata->dev = dev; - iommudata->ops = ops; - iommudata->dma_base = dma_base; - iommudata->size = size; - - mutex_lock(&iommu_dma_notifier_lock); - list_add(&iommudata->list, &iommu_dma_masters); - mutex_unlock(&iommu_dma_notifier_lock); -} - -static int __iommu_attach_notifier(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct iommu_dma_notifier_data *master, *tmp; - - if (action != BUS_NOTIFY_BIND_DRIVER) - return 0; - - mutex_lock(&iommu_dma_notifier_lock); - list_for_each_entry_safe(master, tmp, &iommu_dma_masters, list) { - if (data == master->dev && do_iommu_attach(master->dev, - master->ops, master->dma_base, master->size)) { - list_del(&master->list); - kfree(master); - break; - } - } - mutex_unlock(&iommu_dma_notifier_lock); - return 0; -} - -static int __init register_iommu_dma_ops_notifier(struct bus_type *bus) -{ - struct notifier_block *nb = kzalloc(sizeof(*nb), GFP_KERNEL); - int ret; - - if (!nb) - return -ENOMEM; - - nb->notifier_call = __iommu_attach_notifier; - - ret = bus_register_notifier(bus, nb); - if (ret) { - pr_warn("Failed to register DMA domain notifier; IOMMU DMA ops unavailable on bus '%s'\n", - bus->name); - kfree(nb); - } - return ret; -} - -static int __init __iommu_dma_init(void) -{ - int ret; - - ret = iommu_dma_init(); - if (!ret) - ret = register_iommu_dma_ops_notifier(&platform_bus_type); - if (!ret) - ret = register_iommu_dma_ops_notifier(&amba_bustype); -#ifdef CONFIG_PCI - if (!ret) - ret = register_iommu_dma_ops_notifier(&pci_bus_type); -#endif - return ret; -} -arch_initcall(__iommu_dma_init); - -static void __iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, - const struct iommu_ops *ops) -{ - struct iommu_group *group; - - if (!ops) - return; - /* - * TODO: As a concession to the future, we're ready to handle being - * called both early and late (i.e. after bus_add_device). Once all - * the platform bus code is reworked to call us late and the notifier - * junk above goes away, move the body of do_iommu_attach here. - */ - group = iommu_group_get(dev); - if (group) { - do_iommu_attach(dev, ops, dma_base, size); - iommu_group_put(group); - } else { - queue_iommu_attach(dev, ops, dma_base, size); - } } void arch_teardown_dma_ops(struct device *dev) -- cgit v1.2.3-59-g8ed1b From c1d590081e3f77b364e8563d3edf83ca245a51d9 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 21 Apr 2017 03:14:51 +0200 Subject: MIPS: Sibyte: Export symbol periph_rev to sb1250-mac network driver. This fixes the following modpost error: ERROR: "periph_rev" [drivers/net/ethernet/broadcom/sb1250-mac.ko] undefined! Signed-off-by: Ralf Baechle --- arch/mips/sibyte/bcm1480/setup.c | 1 + arch/mips/sibyte/sb1250/setup.c | 1 + 2 files changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/mips/sibyte/bcm1480/setup.c b/arch/mips/sibyte/bcm1480/setup.c index a05246cbf54c..2035aaec8514 100644 --- a/arch/mips/sibyte/bcm1480/setup.c +++ b/arch/mips/sibyte/bcm1480/setup.c @@ -36,6 +36,7 @@ unsigned int soc_pass; unsigned int soc_type; EXPORT_SYMBOL(soc_type); unsigned int periph_rev; +EXPORT_SYMBOL_GPL(periph_rev); unsigned int zbbus_mhz; EXPORT_SYMBOL(zbbus_mhz); diff --git a/arch/mips/sibyte/sb1250/setup.c b/arch/mips/sibyte/sb1250/setup.c index 90e43782342b..aa7713adfa58 100644 --- a/arch/mips/sibyte/sb1250/setup.c +++ b/arch/mips/sibyte/sb1250/setup.c @@ -34,6 +34,7 @@ unsigned int soc_pass; unsigned int soc_type; EXPORT_SYMBOL(soc_type); unsigned int periph_rev; +EXPORT_SYMBOL_GPL(periph_rev); unsigned int zbbus_mhz; EXPORT_SYMBOL(zbbus_mhz); -- cgit v1.2.3-59-g8ed1b From 3e441845caf1c9591b5b961f34ff1a37d023c9e2 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 21 Apr 2017 03:28:18 +0200 Subject: MIPS: Sibyte: Fix Kconfig warning. warning: (SB1XXX_CORELIS) selects DEBUG_INFO which has unmet direct dependencies (DEBUG_KERNEL && !COMPILE_TEST) Signed-off-by: Ralf Baechle --- arch/mips/Kconfig.debug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug index 7f975b20b20c..42a97c59200f 100644 --- a/arch/mips/Kconfig.debug +++ b/arch/mips/Kconfig.debug @@ -82,7 +82,7 @@ config CMDLINE_OVERRIDE config SB1XXX_CORELIS bool "Corelis Debugger" depends on SIBYTE_SB1xxx_SOC - select DEBUG_INFO + select DEBUG_INFO if !COMPILE_TEST help Select compile flags that produce code that can be processed by the Corelis mksym utility and UDB Emulator. -- cgit v1.2.3-59-g8ed1b From 8bf8f2e8c786f37991bd27332c75edcc524d2232 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Wed, 19 Apr 2017 05:12:16 +1000 Subject: powerpc/64s: Revert setting of LPCR[LPES] on POWER9 The XIVE enablement patches included a change to set the LPES (Logical Partitioning Environment Selector) bit (bit # 3) in LPCR (Logical Partitioning Control Register) on POWER9 hosts. This bit sets external interrupts to guest delivery mode, which uses SRR0/1. The host's EE interrupt handler is written to expect HSRR0/1 (for earlier CPUs). This should be fine because XIVE is configured not to deliver EEs to the host (Hypervisor Virtulization Interrupt is used instead) so the EE handler should never be executed. However a bug in interrupt controller code, hardware, or odd configuration of a simulator could result in the host getting an EE incorrectly. Keeping the EE delivery mode matching the host EE handler prevents strange crashes due to using the wrong exception registers. KVM will configure the LPCR to set LPES prior to running a guest so that EEs are delivered to the guest using SRR0/1. Fixes: 08a1e650cc ("powerpc: Fixup LPCR:PECE and HEIC setting on POWER9") Signed-off-by: Nicholas Piggin [mpe: Massage change log to avoid referring to LPES0 which is now renamed LPES] Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/cpu_setup_power.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S index 7013ae3d1675..1fce4ddd2e6c 100644 --- a/arch/powerpc/kernel/cpu_setup_power.S +++ b/arch/powerpc/kernel/cpu_setup_power.S @@ -107,7 +107,7 @@ _GLOBAL(__setup_cpu_power9) or r3, r3, r4 LOAD_REG_IMMEDIATE(r4, LPCR_UPRT | LPCR_HR) andc r3, r3, r4 - li r4,(LPCR_LPES0 >> LPCR_LPES_SH) + li r4,0 /* LPES = 0 */ bl __init_LPCR bl __init_HFSCR bl __init_tlb_power9 @@ -131,7 +131,7 @@ _GLOBAL(__restore_cpu_power9) or r3, r3, r4 LOAD_REG_IMMEDIATE(r4, LPCR_UPRT | LPCR_HR) andc r3, r3, r4 - li r4,(LPCR_LPES0 >> LPCR_LPES_SH) + li r4,0 /* LPES = 0 */ bl __init_LPCR bl __init_HFSCR bl __init_tlb_power9 -- cgit v1.2.3-59-g8ed1b From bfd20f1cc85010d2f2d77e544da05cd8c149ba9b Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Wed, 26 Apr 2017 09:18:35 -0700 Subject: x86, iommu/vt-d: Add an option to disable Intel IOMMU force on IOMMU harms performance signficantly when we run very fast networking workloads. It's 40GB networking doing XDP test. Software overhead is almost unaware, but it's the IOTLB miss (based on our analysis) which kills the performance. We observed the same performance issue even with software passthrough (identity mapping), only the hardware passthrough survives. The pps with iommu (with software passthrough) is only about ~30% of that without it. This is a limitation in hardware based on our observation, so we'd like to disable the IOMMU force on, but we do want to use TBOOT and we can sacrifice the DMA security bought by IOMMU. I must admit I know nothing about TBOOT, but TBOOT guys (cc-ed) think not eabling IOMMU is totally ok. So introduce a new boot option to disable the force on. It's kind of silly we need to run into intel_iommu_init even without force on, but we need to disable TBOOT PMR registers. For system without the boot option, nothing is changed. Signed-off-by: Shaohua Li Signed-off-by: Joerg Roedel --- Documentation/admin-guide/kernel-parameters.txt | 9 +++++++++ arch/x86/kernel/tboot.c | 3 +++ drivers/iommu/intel-iommu.c | 18 ++++++++++++++++++ include/linux/dma_remapping.h | 1 + 4 files changed, 31 insertions(+) (limited to 'arch') diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 2ba45caabada..17135bfade6a 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -1578,6 +1578,15 @@ extended tables themselves, and also PASID support. With this option set, extended tables will not be used even on hardware which claims to support them. + tboot_noforce [Default Off] + Do not force the Intel IOMMU enabled under tboot. + By default, tboot will force Intel IOMMU on, which + could harm performance of some high-throughput + devices like 40GBit network cards, even if identity + mapping is enabled. + Note that using this option lowers the security + provided by tboot because it makes the system + vulnerable to DMA attacks. intel_idle.max_cstate= [KNL,HW,ACPI,X86] 0 disables intel_idle and fall back on acpi_idle. diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c index b868fa1b812b..edbdfe6ab60a 100644 --- a/arch/x86/kernel/tboot.c +++ b/arch/x86/kernel/tboot.c @@ -510,6 +510,9 @@ int tboot_force_iommu(void) if (!tboot_enabled()) return 0; + if (!intel_iommu_tboot_noforce) + return 1; + if (no_iommu || swiotlb || dmar_disabled) pr_warning("Forcing Intel-IOMMU to enabled\n"); diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 5f08ba13972b..b0ced1c13713 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -183,6 +183,7 @@ static int rwbf_quirk; * (used when kernel is launched w/ TXT) */ static int force_on = 0; +int intel_iommu_tboot_noforce; /* * 0: Present @@ -607,6 +608,10 @@ static int __init intel_iommu_setup(char *str) "Intel-IOMMU: enable pre-production PASID support\n"); intel_iommu_pasid28 = 1; iommu_identity_mapping |= IDENTMAP_GFX; + } else if (!strncmp(str, "tboot_noforce", 13)) { + printk(KERN_INFO + "Intel-IOMMU: not forcing on after tboot. This could expose security risk for tboot\n"); + intel_iommu_tboot_noforce = 1; } str += strcspn(str, ","); @@ -4850,6 +4855,19 @@ int __init intel_iommu_init(void) } if (no_iommu || dmar_disabled) { + /* + * We exit the function here to ensure IOMMU's remapping and + * mempool aren't setup, which means that the IOMMU's PMRs + * won't be disabled via the call to init_dmars(). So disable + * it explicitly here. The PMRs were setup by tboot prior to + * calling SENTER, but the kernel is expected to reset/tear + * down the PMRs. + */ + if (intel_iommu_tboot_noforce) { + for_each_iommu(iommu, drhd) + iommu_disable_protect_mem_regions(iommu); + } + /* * Make sure the IOMMUs are switched off, even when we * boot into a kexec kernel and the previous kernel left diff --git a/include/linux/dma_remapping.h b/include/linux/dma_remapping.h index 187c10299722..90884072fa73 100644 --- a/include/linux/dma_remapping.h +++ b/include/linux/dma_remapping.h @@ -39,6 +39,7 @@ extern int iommu_calculate_agaw(struct intel_iommu *iommu); extern int iommu_calculate_max_sagaw(struct intel_iommu *iommu); extern int dmar_disabled; extern int intel_iommu_enabled; +extern int intel_iommu_tboot_noforce; #else static inline int iommu_calculate_agaw(struct intel_iommu *iommu) { -- cgit v1.2.3-59-g8ed1b From 5af50993850a48ba749b122173d789ea90976c72 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 5 Apr 2017 17:54:56 +1000 Subject: KVM: PPC: Book3S HV: Native usage of the XIVE interrupt controller This patch makes KVM capable of using the XIVE interrupt controller to provide the standard PAPR "XICS" style hypercalls. It is necessary for proper operations when the host uses XIVE natively. This has been lightly tested on an actual system, including PCI pass-through with a TG3 device. Signed-off-by: Benjamin Herrenschmidt [mpe: Cleanup pr_xxx(), unsplit pr_xxx() strings, etc., fix build failures by adding KVM_XIVE which depends on KVM_XICS and XIVE, and adding empty stubs for the kvm_xive_xxx() routines, fixup subject, integrate fixes from Paul for building PR=y HV=n] Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/kvm_book3s_asm.h | 2 + arch/powerpc/include/asm/kvm_host.h | 28 +- arch/powerpc/include/asm/kvm_ppc.h | 74 ++ arch/powerpc/include/asm/xive.h | 9 +- arch/powerpc/kernel/asm-offsets.c | 10 + arch/powerpc/kvm/Kconfig | 5 + arch/powerpc/kvm/Makefile | 4 +- arch/powerpc/kvm/book3s.c | 75 +- arch/powerpc/kvm/book3s_hv.c | 51 +- arch/powerpc/kvm/book3s_hv_builtin.c | 103 ++ arch/powerpc/kvm/book3s_hv_rm_xics.c | 10 +- arch/powerpc/kvm/book3s_hv_rm_xive.c | 47 + arch/powerpc/kvm/book3s_hv_rmhandlers.S | 62 +- arch/powerpc/kvm/book3s_rtas.c | 21 +- arch/powerpc/kvm/book3s_xics.c | 35 +- arch/powerpc/kvm/book3s_xics.h | 7 + arch/powerpc/kvm/book3s_xive.c | 1893 +++++++++++++++++++++++++++++ arch/powerpc/kvm/book3s_xive.h | 256 ++++ arch/powerpc/kvm/book3s_xive_template.c | 503 ++++++++ arch/powerpc/kvm/irq.h | 1 + arch/powerpc/kvm/powerpc.c | 17 +- arch/powerpc/platforms/powernv/opal.c | 1 + arch/powerpc/sysdev/xive/common.c | 142 ++- arch/powerpc/sysdev/xive/native.c | 86 +- include/linux/kvm_host.h | 1 - virt/kvm/kvm_main.c | 4 - 26 files changed, 3358 insertions(+), 89 deletions(-) create mode 100644 arch/powerpc/kvm/book3s_hv_rm_xive.c create mode 100644 arch/powerpc/kvm/book3s_xive.c create mode 100644 arch/powerpc/kvm/book3s_xive.h create mode 100644 arch/powerpc/kvm/book3s_xive_template.c (limited to 'arch') diff --git a/arch/powerpc/include/asm/kvm_book3s_asm.h b/arch/powerpc/include/asm/kvm_book3s_asm.h index 0593d9479f74..b148496ffe36 100644 --- a/arch/powerpc/include/asm/kvm_book3s_asm.h +++ b/arch/powerpc/include/asm/kvm_book3s_asm.h @@ -111,6 +111,8 @@ struct kvmppc_host_state { struct kvm_vcpu *kvm_vcpu; struct kvmppc_vcore *kvm_vcore; void __iomem *xics_phys; + void __iomem *xive_tima_phys; + void __iomem *xive_tima_virt; u32 saved_xirr; u64 dabr; u64 host_mmcr[7]; /* MMCR 0,1,A, SIAR, SDAR, MMCR2, SIER */ diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 7bba8f415627..5a8ab4a758f1 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -205,6 +205,12 @@ struct kvmppc_spapr_tce_table { /* XICS components, defined in book3s_xics.c */ struct kvmppc_xics; struct kvmppc_icp; +extern struct kvm_device_ops kvm_xics_ops; + +/* XIVE components, defined in book3s_xive.c */ +struct kvmppc_xive; +struct kvmppc_xive_vcpu; +extern struct kvm_device_ops kvm_xive_ops; struct kvmppc_passthru_irqmap; @@ -293,6 +299,7 @@ struct kvm_arch { #endif #ifdef CONFIG_KVM_XICS struct kvmppc_xics *xics; + struct kvmppc_xive *xive; struct kvmppc_passthru_irqmap *pimap; #endif struct kvmppc_ops *kvm_ops; @@ -421,7 +428,7 @@ struct kvmppc_passthru_irqmap { #define KVMPPC_IRQ_DEFAULT 0 #define KVMPPC_IRQ_MPIC 1 -#define KVMPPC_IRQ_XICS 2 +#define KVMPPC_IRQ_XICS 2 /* Includes a XIVE option */ #define MMIO_HPTE_CACHE_SIZE 4 @@ -443,6 +450,21 @@ struct mmio_hpte_cache { struct openpic; +/* W0 and W1 of a XIVE thread management context */ +union xive_tma_w01 { + struct { + u8 nsr; + u8 cppr; + u8 ipb; + u8 lsmfb; + u8 ack; + u8 inc; + u8 age; + u8 pipr; + }; + __be64 w01; +}; + struct kvm_vcpu_arch { ulong host_stack; u32 host_pid; @@ -688,6 +710,10 @@ struct kvm_vcpu_arch { struct openpic *mpic; /* KVM_IRQ_MPIC */ #ifdef CONFIG_KVM_XICS struct kvmppc_icp *icp; /* XICS presentation controller */ + struct kvmppc_xive_vcpu *xive_vcpu; /* XIVE virtual CPU data */ + __be32 xive_cam_word; /* Cooked W2 in proper endian with valid bit */ + u32 xive_pushed; /* Is the VP pushed on the physical CPU ? */ + union xive_tma_w01 xive_saved_state; /* W0..1 of XIVE thread state */ #endif #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index c3877992eff9..ed52b13d9ffb 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h @@ -225,6 +225,7 @@ int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq); extern int kvm_vm_ioctl_rtas_define_token(struct kvm *kvm, void __user *argp); extern int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu); extern void kvmppc_rtas_tokens_free(struct kvm *kvm); + extern int kvmppc_xics_set_xive(struct kvm *kvm, u32 irq, u32 server, u32 priority); extern int kvmppc_xics_get_xive(struct kvm *kvm, u32 irq, u32 *server, @@ -412,6 +413,14 @@ static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr) paca[cpu].kvm_hstate.xics_phys = (void __iomem *)addr; } +static inline void kvmppc_set_xive_tima(int cpu, + unsigned long phys_addr, + void __iomem *virt_addr) +{ + paca[cpu].kvm_hstate.xive_tima_phys = (void __iomem *)phys_addr; + paca[cpu].kvm_hstate.xive_tima_virt = virt_addr; +} + static inline u32 kvmppc_get_xics_latch(void) { u32 xirr; @@ -442,6 +451,11 @@ static inline void __init kvm_cma_reserve(void) static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr) {} +static inline void kvmppc_set_xive_tima(int cpu, + unsigned long phys_addr, + void __iomem *virt_addr) +{} + static inline u32 kvmppc_get_xics_latch(void) { return 0; @@ -492,6 +506,10 @@ extern long kvmppc_deliver_irq_passthru(struct kvm_vcpu *vcpu, __be32 xirr, struct kvmppc_irq_map *irq_map, struct kvmppc_passthru_irqmap *pimap, bool *again); + +extern int kvmppc_xics_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, + int level, bool line_status); + extern int h_ipi_redirect; #else static inline struct kvmppc_passthru_irqmap *kvmppc_get_passthru_irqmap( @@ -509,6 +527,60 @@ static inline int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd) { return 0; } #endif +#ifdef CONFIG_KVM_XIVE +/* + * Below the first "xive" is the "eXternal Interrupt Virtualization Engine" + * ie. P9 new interrupt controller, while the second "xive" is the legacy + * "eXternal Interrupt Vector Entry" which is the configuration of an + * interrupt on the "xics" interrupt controller on P8 and earlier. Those + * two function consume or produce a legacy "XIVE" state from the + * new "XIVE" interrupt controller. + */ +extern int kvmppc_xive_set_xive(struct kvm *kvm, u32 irq, u32 server, + u32 priority); +extern int kvmppc_xive_get_xive(struct kvm *kvm, u32 irq, u32 *server, + u32 *priority); +extern int kvmppc_xive_int_on(struct kvm *kvm, u32 irq); +extern int kvmppc_xive_int_off(struct kvm *kvm, u32 irq); +extern void kvmppc_xive_init_module(void); +extern void kvmppc_xive_exit_module(void); + +extern int kvmppc_xive_connect_vcpu(struct kvm_device *dev, + struct kvm_vcpu *vcpu, u32 cpu); +extern void kvmppc_xive_cleanup_vcpu(struct kvm_vcpu *vcpu); +extern int kvmppc_xive_set_mapped(struct kvm *kvm, unsigned long guest_irq, + struct irq_desc *host_desc); +extern int kvmppc_xive_clr_mapped(struct kvm *kvm, unsigned long guest_irq, + struct irq_desc *host_desc); +extern u64 kvmppc_xive_get_icp(struct kvm_vcpu *vcpu); +extern int kvmppc_xive_set_icp(struct kvm_vcpu *vcpu, u64 icpval); + +extern int kvmppc_xive_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, + int level, bool line_status); +#else +static inline int kvmppc_xive_set_xive(struct kvm *kvm, u32 irq, u32 server, + u32 priority) { return -1; } +static inline int kvmppc_xive_get_xive(struct kvm *kvm, u32 irq, u32 *server, + u32 *priority) { return -1; } +static inline int kvmppc_xive_int_on(struct kvm *kvm, u32 irq) { return -1; } +static inline int kvmppc_xive_int_off(struct kvm *kvm, u32 irq) { return -1; } +static inline void kvmppc_xive_init_module(void) { } +static inline void kvmppc_xive_exit_module(void) { } + +static inline int kvmppc_xive_connect_vcpu(struct kvm_device *dev, + struct kvm_vcpu *vcpu, u32 cpu) { return -EBUSY; } +static inline void kvmppc_xive_cleanup_vcpu(struct kvm_vcpu *vcpu) { } +static inline int kvmppc_xive_set_mapped(struct kvm *kvm, unsigned long guest_irq, + struct irq_desc *host_desc) { return -ENODEV; } +static inline int kvmppc_xive_clr_mapped(struct kvm *kvm, unsigned long guest_irq, + struct irq_desc *host_desc) { return -ENODEV; } +static inline u64 kvmppc_xive_get_icp(struct kvm_vcpu *vcpu) { return 0; } +static inline int kvmppc_xive_set_icp(struct kvm_vcpu *vcpu, u64 icpval) { return -ENOENT; } + +static inline int kvmppc_xive_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, + int level, bool line_status) { return -ENODEV; } +#endif /* CONFIG_KVM_XIVE */ + /* * Prototypes for functions called only from assembler code. * Having prototypes reduces sparse errors. @@ -546,6 +618,8 @@ long kvmppc_h_clear_mod(struct kvm_vcpu *vcpu, unsigned long flags, long kvmppc_hpte_hv_fault(struct kvm_vcpu *vcpu, unsigned long addr, unsigned long slb_v, unsigned int status, bool data); unsigned long kvmppc_rm_h_xirr(struct kvm_vcpu *vcpu); +unsigned long kvmppc_rm_h_xirr_x(struct kvm_vcpu *vcpu); +unsigned long kvmppc_rm_h_ipoll(struct kvm_vcpu *vcpu, unsigned long server); int kvmppc_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server, unsigned long mfrr); int kvmppc_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr); diff --git a/arch/powerpc/include/asm/xive.h b/arch/powerpc/include/asm/xive.h index 3cdbeaeac397..c8a822acf962 100644 --- a/arch/powerpc/include/asm/xive.h +++ b/arch/powerpc/include/asm/xive.h @@ -99,7 +99,6 @@ struct xive_q { #define XIVE_ESB_SET_PQ_01 0xd00 #define XIVE_ESB_SET_PQ_10 0xe00 #define XIVE_ESB_SET_PQ_11 0xf00 -#define XIVE_ESB_MASK XIVE_ESB_SET_PQ_01 #define XIVE_ESB_VAL_P 0x2 #define XIVE_ESB_VAL_Q 0x1 @@ -136,11 +135,11 @@ extern int xive_native_configure_queue(u32 vp_id, struct xive_q *q, u8 prio, __be32 *qpage, u32 order, bool can_escalate); extern void xive_native_disable_queue(u32 vp_id, struct xive_q *q, u8 prio); -extern bool __xive_irq_trigger(struct xive_irq_data *xd); -extern bool __xive_irq_retrigger(struct xive_irq_data *xd); -extern void xive_do_source_eoi(u32 hw_irq, struct xive_irq_data *xd); - +extern void xive_native_sync_source(u32 hw_irq); extern bool is_xive_irq(struct irq_chip *chip); +extern int xive_native_enable_vp(u32 vp_id); +extern int xive_native_disable_vp(u32 vp_id); +extern int xive_native_get_vp_info(u32 vp_id, u32 *out_cam_id, u32 *out_chip_id); #else diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 4367e7df51a1..1822187813dc 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -630,6 +630,8 @@ int main(void) HSTATE_FIELD(HSTATE_KVM_VCPU, kvm_vcpu); HSTATE_FIELD(HSTATE_KVM_VCORE, kvm_vcore); HSTATE_FIELD(HSTATE_XICS_PHYS, xics_phys); + HSTATE_FIELD(HSTATE_XIVE_TIMA_PHYS, xive_tima_phys); + HSTATE_FIELD(HSTATE_XIVE_TIMA_VIRT, xive_tima_virt); HSTATE_FIELD(HSTATE_SAVED_XIRR, saved_xirr); HSTATE_FIELD(HSTATE_HOST_IPI, host_ipi); HSTATE_FIELD(HSTATE_PTID, ptid); @@ -715,6 +717,14 @@ int main(void) OFFSET(VCPU_HOST_MAS6, kvm_vcpu, arch.host_mas6); #endif +#ifdef CONFIG_KVM_XICS + DEFINE(VCPU_XIVE_SAVED_STATE, offsetof(struct kvm_vcpu, + arch.xive_saved_state)); + DEFINE(VCPU_XIVE_CAM_WORD, offsetof(struct kvm_vcpu, + arch.xive_cam_word)); + DEFINE(VCPU_XIVE_PUSHED, offsetof(struct kvm_vcpu, arch.xive_pushed)); +#endif + #ifdef CONFIG_KVM_EXIT_TIMING OFFSET(VCPU_TIMING_EXIT_TBU, kvm_vcpu, arch.timing_exit.tv32.tbu); OFFSET(VCPU_TIMING_EXIT_TBL, kvm_vcpu, arch.timing_exit.tv32.tbl); diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig index 029be26b5a17..b9d66e53b773 100644 --- a/arch/powerpc/kvm/Kconfig +++ b/arch/powerpc/kvm/Kconfig @@ -196,6 +196,11 @@ config KVM_XICS Specification) interrupt controller architecture used on IBM POWER (pSeries) servers. +config KVM_XIVE + bool + default y + depends on KVM_XICS && PPC_XIVE_NATIVE && KVM_BOOK3S_HV_POSSIBLE + source drivers/vhost/Kconfig endif # VIRTUALIZATION diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile index b87ccde2137a..d91a2604c496 100644 --- a/arch/powerpc/kvm/Makefile +++ b/arch/powerpc/kvm/Makefile @@ -74,7 +74,7 @@ kvm-hv-y += \ book3s_64_mmu_radix.o kvm-book3s_64-builtin-xics-objs-$(CONFIG_KVM_XICS) := \ - book3s_hv_rm_xics.o + book3s_hv_rm_xics.o book3s_hv_rm_xive.o ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) += \ @@ -89,6 +89,8 @@ endif kvm-book3s_64-objs-$(CONFIG_KVM_XICS) += \ book3s_xics.o +kvm-book3s_64-objs-$(CONFIG_KVM_XIVE) += book3s_xive.o + kvm-book3s_64-module-objs := \ $(common-objs-y) \ book3s.o \ diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index aedacefd961d..cb8009cd688d 100644 --- a/arch/powerpc/kvm/book3s.c +++ b/arch/powerpc/kvm/book3s.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "book3s.h" #include "trace.h" @@ -578,11 +579,14 @@ int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, break; #ifdef CONFIG_KVM_XICS case KVM_REG_PPC_ICP_STATE: - if (!vcpu->arch.icp) { + if (!vcpu->arch.icp && !vcpu->arch.xive_vcpu) { r = -ENXIO; break; } - *val = get_reg_val(id, kvmppc_xics_get_icp(vcpu)); + if (xive_enabled()) + *val = get_reg_val(id, kvmppc_xive_get_icp(vcpu)); + else + *val = get_reg_val(id, kvmppc_xics_get_icp(vcpu)); break; #endif /* CONFIG_KVM_XICS */ case KVM_REG_PPC_FSCR: @@ -648,12 +652,14 @@ int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, #endif /* CONFIG_VSX */ #ifdef CONFIG_KVM_XICS case KVM_REG_PPC_ICP_STATE: - if (!vcpu->arch.icp) { + if (!vcpu->arch.icp && !vcpu->arch.xive_vcpu) { r = -ENXIO; break; } - r = kvmppc_xics_set_icp(vcpu, - set_reg_val(id, *val)); + if (xive_enabled()) + r = kvmppc_xive_set_icp(vcpu, set_reg_val(id, *val)); + else + r = kvmppc_xics_set_icp(vcpu, set_reg_val(id, *val)); break; #endif /* CONFIG_KVM_XICS */ case KVM_REG_PPC_FSCR: @@ -924,6 +930,50 @@ int kvmppc_book3s_hcall_implemented(struct kvm *kvm, unsigned long hcall) return kvm->arch.kvm_ops->hcall_implemented(hcall); } +#ifdef CONFIG_KVM_XICS +int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, + bool line_status) +{ + if (xive_enabled()) + return kvmppc_xive_set_irq(kvm, irq_source_id, irq, level, + line_status); + else + return kvmppc_xics_set_irq(kvm, irq_source_id, irq, level, + line_status); +} + +int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *irq_entry, + struct kvm *kvm, int irq_source_id, + int level, bool line_status) +{ + return kvm_set_irq(kvm, irq_source_id, irq_entry->gsi, + level, line_status); +} +static int kvmppc_book3s_set_irq(struct kvm_kernel_irq_routing_entry *e, + struct kvm *kvm, int irq_source_id, int level, + bool line_status) +{ + return kvm_set_irq(kvm, irq_source_id, e->gsi, level, line_status); +} + +int kvm_irq_map_gsi(struct kvm *kvm, + struct kvm_kernel_irq_routing_entry *entries, int gsi) +{ + entries->gsi = gsi; + entries->type = KVM_IRQ_ROUTING_IRQCHIP; + entries->set = kvmppc_book3s_set_irq; + entries->irqchip.irqchip = 0; + entries->irqchip.pin = gsi; + return 1; +} + +int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned irqchip, unsigned pin) +{ + return pin; +} + +#endif /* CONFIG_KVM_XICS */ + static int kvmppc_book3s_init(void) { int r; @@ -934,12 +984,25 @@ static int kvmppc_book3s_init(void) #ifdef CONFIG_KVM_BOOK3S_32_HANDLER r = kvmppc_book3s_init_pr(); #endif - return r; +#ifdef CONFIG_KVM_XICS +#ifdef CONFIG_KVM_XIVE + if (xive_enabled()) { + kvmppc_xive_init_module(); + kvm_register_device_ops(&kvm_xive_ops, KVM_DEV_TYPE_XICS); + } else +#endif + kvm_register_device_ops(&kvm_xics_ops, KVM_DEV_TYPE_XICS); +#endif + return r; } static void kvmppc_book3s_exit(void) { +#ifdef CONFIG_KVM_XICS + if (xive_enabled()) + kvmppc_xive_exit_module(); +#endif #ifdef CONFIG_KVM_BOOK3S_32_HANDLER kvmppc_book3s_exit_pr(); #endif diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index fadb75abfe37..128efb42ec4e 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -67,6 +67,7 @@ #include #include #include +#include #include "book3s.h" @@ -837,6 +838,10 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) case H_IPOLL: case H_XIRR_X: if (kvmppc_xics_enabled(vcpu)) { + if (xive_enabled()) { + ret = H_NOT_AVAILABLE; + return RESUME_GUEST; + } ret = kvmppc_xics_hcall(vcpu, req); break; } @@ -2947,8 +2952,12 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu) r = kvmppc_book3s_hv_page_fault(run, vcpu, vcpu->arch.fault_dar, vcpu->arch.fault_dsisr); srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx); - } else if (r == RESUME_PASSTHROUGH) - r = kvmppc_xics_rm_complete(vcpu, 0); + } else if (r == RESUME_PASSTHROUGH) { + if (WARN_ON(xive_enabled())) + r = H_SUCCESS; + else + r = kvmppc_xics_rm_complete(vcpu, 0); + } } while (is_kvmppc_resume_guest(r)); out: @@ -3400,10 +3409,20 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm) /* * On POWER9, VPM0 bit is reserved (VPM0=1 behaviour is assumed) * Set HVICE bit to enable hypervisor virtualization interrupts. + * Set HEIC to prevent OS interrupts to go to hypervisor (should + * be unnecessary but better safe than sorry in case we re-enable + * EE in HV mode with this LPCR still set) */ if (cpu_has_feature(CPU_FTR_ARCH_300)) { lpcr &= ~LPCR_VPM0; - lpcr |= LPCR_HVICE; + lpcr |= LPCR_HVICE | LPCR_HEIC; + + /* + * If xive is enabled, we route 0x500 interrupts directly + * to the guest. + */ + if (xive_enabled()) + lpcr |= LPCR_LPES; } /* @@ -3533,7 +3552,7 @@ static int kvmppc_set_passthru_irq(struct kvm *kvm, int host_irq, int guest_gsi) struct kvmppc_irq_map *irq_map; struct kvmppc_passthru_irqmap *pimap; struct irq_chip *chip; - int i; + int i, rc = 0; if (!kvm_irq_bypass) return 1; @@ -3558,10 +3577,10 @@ static int kvmppc_set_passthru_irq(struct kvm *kvm, int host_irq, int guest_gsi) /* * For now, we only support interrupts for which the EOI operation * is an OPAL call followed by a write to XIRR, since that's - * what our real-mode EOI code does. + * what our real-mode EOI code does, or a XIVE interrupt */ chip = irq_data_get_irq_chip(&desc->irq_data); - if (!chip || !is_pnv_opal_msi(chip)) { + if (!chip || !(is_pnv_opal_msi(chip) || is_xive_irq(chip))) { pr_warn("kvmppc_set_passthru_irq_hv: Could not assign IRQ map for (%d,%d)\n", host_irq, guest_gsi); mutex_unlock(&kvm->lock); @@ -3603,7 +3622,12 @@ static int kvmppc_set_passthru_irq(struct kvm *kvm, int host_irq, int guest_gsi) if (i == pimap->n_mapped) pimap->n_mapped++; - kvmppc_xics_set_mapped(kvm, guest_gsi, desc->irq_data.hwirq); + if (xive_enabled()) + rc = kvmppc_xive_set_mapped(kvm, guest_gsi, desc); + else + kvmppc_xics_set_mapped(kvm, guest_gsi, desc->irq_data.hwirq); + if (rc) + irq_map->r_hwirq = 0; mutex_unlock(&kvm->lock); @@ -3614,7 +3638,7 @@ static int kvmppc_clr_passthru_irq(struct kvm *kvm, int host_irq, int guest_gsi) { struct irq_desc *desc; struct kvmppc_passthru_irqmap *pimap; - int i; + int i, rc = 0; if (!kvm_irq_bypass) return 0; @@ -3641,9 +3665,12 @@ static int kvmppc_clr_passthru_irq(struct kvm *kvm, int host_irq, int guest_gsi) return -ENODEV; } - kvmppc_xics_clr_mapped(kvm, guest_gsi, pimap->mapped[i].r_hwirq); + if (xive_enabled()) + rc = kvmppc_xive_clr_mapped(kvm, guest_gsi, pimap->mapped[i].desc); + else + kvmppc_xics_clr_mapped(kvm, guest_gsi, pimap->mapped[i].r_hwirq); - /* invalidate the entry */ + /* invalidate the entry (what do do on error from the above ?) */ pimap->mapped[i].r_hwirq = 0; /* @@ -3652,7 +3679,7 @@ static int kvmppc_clr_passthru_irq(struct kvm *kvm, int host_irq, int guest_gsi) */ mutex_unlock(&kvm->lock); - return 0; + return rc; } static int kvmppc_irq_bypass_add_producer_hv(struct irq_bypass_consumer *cons, @@ -3930,7 +3957,7 @@ static int kvmppc_book3s_init_hv(void) * indirectly, via OPAL. */ #ifdef CONFIG_SMP - if (!get_paca()->kvm_hstate.xics_phys) { + if (!xive_enabled() && !get_paca()->kvm_hstate.xics_phys) { struct device_node *np; np = of_find_compatible_node(NULL, NULL, "ibm,opal-intc"); diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c index a752e29977e0..846b40cb3a62 100644 --- a/arch/powerpc/kvm/book3s_hv_builtin.c +++ b/arch/powerpc/kvm/book3s_hv_builtin.c @@ -32,6 +32,24 @@ #define KVM_CMA_CHUNK_ORDER 18 +#include "book3s_xics.h" +#include "book3s_xive.h" + +/* + * The XIVE module will populate these when it loads + */ +unsigned long (*__xive_vm_h_xirr)(struct kvm_vcpu *vcpu); +unsigned long (*__xive_vm_h_ipoll)(struct kvm_vcpu *vcpu, unsigned long server); +int (*__xive_vm_h_ipi)(struct kvm_vcpu *vcpu, unsigned long server, + unsigned long mfrr); +int (*__xive_vm_h_cppr)(struct kvm_vcpu *vcpu, unsigned long cppr); +int (*__xive_vm_h_eoi)(struct kvm_vcpu *vcpu, unsigned long xirr); +EXPORT_SYMBOL_GPL(__xive_vm_h_xirr); +EXPORT_SYMBOL_GPL(__xive_vm_h_ipoll); +EXPORT_SYMBOL_GPL(__xive_vm_h_ipi); +EXPORT_SYMBOL_GPL(__xive_vm_h_cppr); +EXPORT_SYMBOL_GPL(__xive_vm_h_eoi); + /* * Hash page table alignment on newer cpus(CPU_FTR_ARCH_206) * should be power of 2. @@ -210,6 +228,7 @@ void kvmhv_rm_send_ipi(int cpu) __asm__ __volatile__ (PPC_MSGSND(%0) : : "r" (msg)); return; } + /* On POWER8 for IPIs to threads in the same core, use msgsnd. */ if (cpu_has_feature(CPU_FTR_ARCH_207S) && cpu_first_thread_sibling(cpu) == @@ -406,6 +425,9 @@ static long kvmppc_read_one_intr(bool *again) u8 host_ipi; int64_t rc; + if (xive_enabled()) + return 1; + /* see if a host IPI is pending */ host_ipi = local_paca->kvm_hstate.host_ipi; if (host_ipi) @@ -490,3 +512,84 @@ static long kvmppc_read_one_intr(bool *again) return kvmppc_check_passthru(xisr, xirr, again); } + +#ifdef CONFIG_KVM_XICS +static inline bool is_rm(void) +{ + return !(mfmsr() & MSR_DR); +} + +unsigned long kvmppc_rm_h_xirr(struct kvm_vcpu *vcpu) +{ + if (xive_enabled()) { + if (is_rm()) + return xive_rm_h_xirr(vcpu); + if (unlikely(!__xive_vm_h_xirr)) + return H_NOT_AVAILABLE; + return __xive_vm_h_xirr(vcpu); + } else + return xics_rm_h_xirr(vcpu); +} + +unsigned long kvmppc_rm_h_xirr_x(struct kvm_vcpu *vcpu) +{ + vcpu->arch.gpr[5] = get_tb(); + if (xive_enabled()) { + if (is_rm()) + return xive_rm_h_xirr(vcpu); + if (unlikely(!__xive_vm_h_xirr)) + return H_NOT_AVAILABLE; + return __xive_vm_h_xirr(vcpu); + } else + return xics_rm_h_xirr(vcpu); +} + +unsigned long kvmppc_rm_h_ipoll(struct kvm_vcpu *vcpu, unsigned long server) +{ + if (xive_enabled()) { + if (is_rm()) + return xive_rm_h_ipoll(vcpu, server); + if (unlikely(!__xive_vm_h_ipoll)) + return H_NOT_AVAILABLE; + return __xive_vm_h_ipoll(vcpu, server); + } else + return H_TOO_HARD; +} + +int kvmppc_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server, + unsigned long mfrr) +{ + if (xive_enabled()) { + if (is_rm()) + return xive_rm_h_ipi(vcpu, server, mfrr); + if (unlikely(!__xive_vm_h_ipi)) + return H_NOT_AVAILABLE; + return __xive_vm_h_ipi(vcpu, server, mfrr); + } else + return xics_rm_h_ipi(vcpu, server, mfrr); +} + +int kvmppc_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr) +{ + if (xive_enabled()) { + if (is_rm()) + return xive_rm_h_cppr(vcpu, cppr); + if (unlikely(!__xive_vm_h_cppr)) + return H_NOT_AVAILABLE; + return __xive_vm_h_cppr(vcpu, cppr); + } else + return xics_rm_h_cppr(vcpu, cppr); +} + +int kvmppc_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr) +{ + if (xive_enabled()) { + if (is_rm()) + return xive_rm_h_eoi(vcpu, xirr); + if (unlikely(!__xive_vm_h_eoi)) + return H_NOT_AVAILABLE; + return __xive_vm_h_eoi(vcpu, xirr); + } else + return xics_rm_h_eoi(vcpu, xirr); +} +#endif /* CONFIG_KVM_XICS */ diff --git a/arch/powerpc/kvm/book3s_hv_rm_xics.c b/arch/powerpc/kvm/book3s_hv_rm_xics.c index 3a1a463a039a..f8068801ac36 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_xics.c +++ b/arch/powerpc/kvm/book3s_hv_rm_xics.c @@ -485,7 +485,7 @@ static void icp_rm_down_cppr(struct kvmppc_xics *xics, struct kvmppc_icp *icp, } -unsigned long kvmppc_rm_h_xirr(struct kvm_vcpu *vcpu) +unsigned long xics_rm_h_xirr(struct kvm_vcpu *vcpu) { union kvmppc_icp_state old_state, new_state; struct kvmppc_xics *xics = vcpu->kvm->arch.xics; @@ -523,8 +523,8 @@ unsigned long kvmppc_rm_h_xirr(struct kvm_vcpu *vcpu) return check_too_hard(xics, icp); } -int kvmppc_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server, - unsigned long mfrr) +int xics_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server, + unsigned long mfrr) { union kvmppc_icp_state old_state, new_state; struct kvmppc_xics *xics = vcpu->kvm->arch.xics; @@ -610,7 +610,7 @@ int kvmppc_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server, return check_too_hard(xics, this_icp); } -int kvmppc_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr) +int xics_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr) { union kvmppc_icp_state old_state, new_state; struct kvmppc_xics *xics = vcpu->kvm->arch.xics; @@ -730,7 +730,7 @@ static int ics_rm_eoi(struct kvm_vcpu *vcpu, u32 irq) return check_too_hard(xics, icp); } -int kvmppc_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr) +int xics_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr) { struct kvmppc_xics *xics = vcpu->kvm->arch.xics; struct kvmppc_icp *icp = vcpu->arch.icp; diff --git a/arch/powerpc/kvm/book3s_hv_rm_xive.c b/arch/powerpc/kvm/book3s_hv_rm_xive.c new file mode 100644 index 000000000000..abf5f01b6eb1 --- /dev/null +++ b/arch/powerpc/kvm/book3s_hv_rm_xive.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "book3s_xive.h" + +/* XXX */ +#include +//#define DBG(fmt...) udbg_printf(fmt) +#define DBG(fmt...) do { } while(0) + +static inline void __iomem *get_tima_phys(void) +{ + return local_paca->kvm_hstate.xive_tima_phys; +} + +#undef XIVE_RUNTIME_CHECKS +#define X_PFX xive_rm_ +#define X_STATIC +#define X_STAT_PFX stat_rm_ +#define __x_tima get_tima_phys() +#define __x_eoi_page(xd) ((void __iomem *)((xd)->eoi_page)) +#define __x_trig_page(xd) ((void __iomem *)((xd)->trig_page)) +#define __x_readb __raw_rm_readb +#define __x_writeb __raw_rm_writeb +#define __x_readw __raw_rm_readw +#define __x_readq __raw_rm_readq +#define __x_writeq __raw_rm_writeq + +#include "book3s_xive_template.c" diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index 7c6477d1840a..bdb3f76ceb6b 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S @@ -30,6 +30,7 @@ #include #include #include +#include #define VCPU_GPRS_TM(reg) (((reg) * ULONG_SIZE) + VCPU_GPR_TM) @@ -970,6 +971,23 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300) cmpwi r3, 512 /* 1 microsecond */ blt hdec_soon +#ifdef CONFIG_KVM_XICS + /* We are entering the guest on that thread, push VCPU to XIVE */ + ld r10, HSTATE_XIVE_TIMA_PHYS(r13) + cmpldi cr0, r10, r0 + beq no_xive + ld r11, VCPU_XIVE_SAVED_STATE(r4) + li r9, TM_QW1_OS + stdcix r11,r9,r10 + eieio + lwz r11, VCPU_XIVE_CAM_WORD(r4) + li r9, TM_QW1_OS + TM_WORD2 + stwcix r11,r9,r10 + li r9, 1 + stw r9, VCPU_XIVE_PUSHED(r4) +no_xive: +#endif /* CONFIG_KVM_XICS */ + deliver_guest_interrupt: ld r6, VCPU_CTR(r4) ld r7, VCPU_XER(r4) @@ -1307,6 +1325,42 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) blt deliver_guest_interrupt guest_exit_cont: /* r9 = vcpu, r12 = trap, r13 = paca */ +#ifdef CONFIG_KVM_XICS + /* We are exiting, pull the VP from the XIVE */ + lwz r0, VCPU_XIVE_PUSHED(r9) + cmpwi cr0, r0, 0 + beq 1f + li r7, TM_SPC_PULL_OS_CTX + li r6, TM_QW1_OS + mfmsr r0 + andi. r0, r0, MSR_IR /* in real mode? */ + beq 2f + ld r10, HSTATE_XIVE_TIMA_VIRT(r13) + cmpldi cr0, r10, 0 + beq 1f + /* First load to pull the context, we ignore the value */ + lwzx r11, r7, r10 + eieio + /* Second load to recover the context state (Words 0 and 1) */ + ldx r11, r6, r10 + b 3f +2: ld r10, HSTATE_XIVE_TIMA_PHYS(r13) + cmpldi cr0, r10, 0 + beq 1f + /* First load to pull the context, we ignore the value */ + lwzcix r11, r7, r10 + eieio + /* Second load to recover the context state (Words 0 and 1) */ + ldcix r11, r6, r10 +3: std r11, VCPU_XIVE_SAVED_STATE(r9) + /* Fixup some of the state for the next load */ + li r10, 0 + li r0, 0xff + stw r10, VCPU_XIVE_PUSHED(r9) + stb r10, (VCPU_XIVE_SAVED_STATE+3)(r9) + stb r0, (VCPU_XIVE_SAVED_STATE+4)(r9) +1: +#endif /* CONFIG_KVM_XICS */ /* Save more register state */ mfdar r6 mfdsisr r7 @@ -2011,7 +2065,7 @@ hcall_real_table: .long DOTSYM(kvmppc_rm_h_eoi) - hcall_real_table .long DOTSYM(kvmppc_rm_h_cppr) - hcall_real_table .long DOTSYM(kvmppc_rm_h_ipi) - hcall_real_table - .long 0 /* 0x70 - H_IPOLL */ + .long DOTSYM(kvmppc_rm_h_ipoll) - hcall_real_table .long DOTSYM(kvmppc_rm_h_xirr) - hcall_real_table #else .long 0 /* 0x64 - H_EOI */ @@ -2181,7 +2235,11 @@ hcall_real_table: .long 0 /* 0x2f0 */ .long 0 /* 0x2f4 */ .long 0 /* 0x2f8 */ - .long 0 /* 0x2fc */ +#ifdef CONFIG_KVM_XICS + .long DOTSYM(kvmppc_rm_h_xirr_x) - hcall_real_table +#else + .long 0 /* 0x2fc - H_XIRR_X*/ +#endif .long DOTSYM(kvmppc_h_random) - hcall_real_table .globl hcall_real_table_end hcall_real_table_end: diff --git a/arch/powerpc/kvm/book3s_rtas.c b/arch/powerpc/kvm/book3s_rtas.c index 20528701835b..2d3b2b1cc272 100644 --- a/arch/powerpc/kvm/book3s_rtas.c +++ b/arch/powerpc/kvm/book3s_rtas.c @@ -16,6 +16,7 @@ #include #include #include +#include #ifdef CONFIG_KVM_XICS static void kvm_rtas_set_xive(struct kvm_vcpu *vcpu, struct rtas_args *args) @@ -32,7 +33,10 @@ static void kvm_rtas_set_xive(struct kvm_vcpu *vcpu, struct rtas_args *args) server = be32_to_cpu(args->args[1]); priority = be32_to_cpu(args->args[2]); - rc = kvmppc_xics_set_xive(vcpu->kvm, irq, server, priority); + if (xive_enabled()) + rc = kvmppc_xive_set_xive(vcpu->kvm, irq, server, priority); + else + rc = kvmppc_xics_set_xive(vcpu->kvm, irq, server, priority); if (rc) rc = -3; out: @@ -52,7 +56,10 @@ static void kvm_rtas_get_xive(struct kvm_vcpu *vcpu, struct rtas_args *args) irq = be32_to_cpu(args->args[0]); server = priority = 0; - rc = kvmppc_xics_get_xive(vcpu->kvm, irq, &server, &priority); + if (xive_enabled()) + rc = kvmppc_xive_get_xive(vcpu->kvm, irq, &server, &priority); + else + rc = kvmppc_xics_get_xive(vcpu->kvm, irq, &server, &priority); if (rc) { rc = -3; goto out; @@ -76,7 +83,10 @@ static void kvm_rtas_int_off(struct kvm_vcpu *vcpu, struct rtas_args *args) irq = be32_to_cpu(args->args[0]); - rc = kvmppc_xics_int_off(vcpu->kvm, irq); + if (xive_enabled()) + rc = kvmppc_xive_int_off(vcpu->kvm, irq); + else + rc = kvmppc_xics_int_off(vcpu->kvm, irq); if (rc) rc = -3; out: @@ -95,7 +105,10 @@ static void kvm_rtas_int_on(struct kvm_vcpu *vcpu, struct rtas_args *args) irq = be32_to_cpu(args->args[0]); - rc = kvmppc_xics_int_on(vcpu->kvm, irq); + if (xive_enabled()) + rc = kvmppc_xive_int_on(vcpu->kvm, irq); + else + rc = kvmppc_xics_int_on(vcpu->kvm, irq); if (rc) rc = -3; out: diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c index ef4fd528c193..e6829c415bc8 100644 --- a/arch/powerpc/kvm/book3s_xics.c +++ b/arch/powerpc/kvm/book3s_xics.c @@ -1307,8 +1307,8 @@ static int xics_set_source(struct kvmppc_xics *xics, long irq, u64 addr) return 0; } -int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, - bool line_status) +int kvmppc_xics_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, + bool line_status) { struct kvmppc_xics *xics = kvm->arch.xics; @@ -1317,14 +1317,6 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, return ics_deliver_irq(xics, irq, level); } -int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *irq_entry, - struct kvm *kvm, int irq_source_id, - int level, bool line_status) -{ - return kvm_set_irq(kvm, irq_source_id, irq_entry->gsi, - level, line_status); -} - static int xics_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) { struct kvmppc_xics *xics = dev->private; @@ -1458,29 +1450,6 @@ void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu) vcpu->arch.irq_type = KVMPPC_IRQ_DEFAULT; } -static int xics_set_irq(struct kvm_kernel_irq_routing_entry *e, - struct kvm *kvm, int irq_source_id, int level, - bool line_status) -{ - return kvm_set_irq(kvm, irq_source_id, e->gsi, level, line_status); -} - -int kvm_irq_map_gsi(struct kvm *kvm, - struct kvm_kernel_irq_routing_entry *entries, int gsi) -{ - entries->gsi = gsi; - entries->type = KVM_IRQ_ROUTING_IRQCHIP; - entries->set = xics_set_irq; - entries->irqchip.irqchip = 0; - entries->irqchip.pin = gsi; - return 1; -} - -int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned irqchip, unsigned pin) -{ - return pin; -} - void kvmppc_xics_set_mapped(struct kvm *kvm, unsigned long irq, unsigned long host_irq) { diff --git a/arch/powerpc/kvm/book3s_xics.h b/arch/powerpc/kvm/book3s_xics.h index ec5474cf70c6..453c9e518c19 100644 --- a/arch/powerpc/kvm/book3s_xics.h +++ b/arch/powerpc/kvm/book3s_xics.h @@ -10,6 +10,7 @@ #ifndef _KVM_PPC_BOOK3S_XICS_H #define _KVM_PPC_BOOK3S_XICS_H +#ifdef CONFIG_KVM_XICS /* * We use a two-level tree to store interrupt source information. * There are up to 1024 ICS nodes, each of which can represent @@ -144,5 +145,11 @@ static inline struct kvmppc_ics *kvmppc_xics_find_ics(struct kvmppc_xics *xics, return ics; } +extern unsigned long xics_rm_h_xirr(struct kvm_vcpu *vcpu); +extern int xics_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server, + unsigned long mfrr); +extern int xics_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr); +extern int xics_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr); +#endif /* CONFIG_KVM_XICS */ #endif /* _KVM_PPC_BOOK3S_XICS_H */ diff --git a/arch/powerpc/kvm/book3s_xive.c b/arch/powerpc/kvm/book3s_xive.c new file mode 100644 index 000000000000..7807ee17af4b --- /dev/null +++ b/arch/powerpc/kvm/book3s_xive.c @@ -0,0 +1,1893 @@ +/* + * Copyright 2017 Benjamin Herrenschmidt, IBM Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + */ + +#define pr_fmt(fmt) "xive-kvm: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "book3s_xive.h" + + +/* + * Virtual mode variants of the hcalls for use on radix/radix + * with AIL. They require the VCPU's VP to be "pushed" + * + * We still instanciate them here because we use some of the + * generated utility functions as well in this file. + */ +#define XIVE_RUNTIME_CHECKS +#define X_PFX xive_vm_ +#define X_STATIC static +#define X_STAT_PFX stat_vm_ +#define __x_tima xive_tima +#define __x_eoi_page(xd) ((void __iomem *)((xd)->eoi_mmio)) +#define __x_trig_page(xd) ((void __iomem *)((xd)->trig_mmio)) +#define __x_readb __raw_readb +#define __x_writeb __raw_writeb +#define __x_readw __raw_readw +#define __x_readq __raw_readq +#define __x_writeq __raw_writeq + +#include "book3s_xive_template.c" + +/* + * We leave a gap of a couple of interrupts in the queue to + * account for the IPI and additional safety guard. + */ +#define XIVE_Q_GAP 2 + +/* + * This is a simple trigger for a generic XIVE IRQ. This must + * only be called for interrupts that support a trigger page + */ +static bool xive_irq_trigger(struct xive_irq_data *xd) +{ + /* This should be only for MSIs */ + if (WARN_ON(xd->flags & XIVE_IRQ_FLAG_LSI)) + return false; + + /* Those interrupts should always have a trigger page */ + if (WARN_ON(!xd->trig_mmio)) + return false; + + out_be64(xd->trig_mmio, 0); + + return true; +} + +static irqreturn_t xive_esc_irq(int irq, void *data) +{ + struct kvm_vcpu *vcpu = data; + + /* We use the existing H_PROD mechanism to wake up the target */ + vcpu->arch.prodded = 1; + smp_mb(); + if (vcpu->arch.ceded) + kvmppc_fast_vcpu_kick(vcpu); + + return IRQ_HANDLED; +} + +static int xive_attach_escalation(struct kvm_vcpu *vcpu, u8 prio) +{ + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + struct xive_q *q = &xc->queues[prio]; + char *name = NULL; + int rc; + + /* Already there ? */ + if (xc->esc_virq[prio]) + return 0; + + /* Hook up the escalation interrupt */ + xc->esc_virq[prio] = irq_create_mapping(NULL, q->esc_irq); + if (!xc->esc_virq[prio]) { + pr_err("Failed to map escalation interrupt for queue %d of VCPU %d\n", + prio, xc->server_num); + return -EIO; + } + + /* + * Future improvement: start with them disabled + * and handle DD2 and later scheme of merged escalation + * interrupts + */ + name = kasprintf(GFP_KERNEL, "kvm-%d-%d-%d", + vcpu->kvm->arch.lpid, xc->server_num, prio); + if (!name) { + pr_err("Failed to allocate escalation irq name for queue %d of VCPU %d\n", + prio, xc->server_num); + rc = -ENOMEM; + goto error; + } + rc = request_irq(xc->esc_virq[prio], xive_esc_irq, + IRQF_NO_THREAD, name, vcpu); + if (rc) { + pr_err("Failed to request escalation interrupt for queue %d of VCPU %d\n", + prio, xc->server_num); + goto error; + } + xc->esc_virq_names[prio] = name; + return 0; +error: + irq_dispose_mapping(xc->esc_virq[prio]); + xc->esc_virq[prio] = 0; + kfree(name); + return rc; +} + +static int xive_provision_queue(struct kvm_vcpu *vcpu, u8 prio) +{ + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + struct kvmppc_xive *xive = xc->xive; + struct xive_q *q = &xc->queues[prio]; + void *qpage; + int rc; + + if (WARN_ON(q->qpage)) + return 0; + + /* Allocate the queue and retrieve infos on current node for now */ + qpage = (__be32 *)__get_free_pages(GFP_KERNEL, xive->q_page_order); + if (!qpage) { + pr_err("Failed to allocate queue %d for VCPU %d\n", + prio, xc->server_num); + return -ENOMEM;; + } + memset(qpage, 0, 1 << xive->q_order); + + /* + * Reconfigure the queue. This will set q->qpage only once the + * queue is fully configured. This is a requirement for prio 0 + * as we will stop doing EOIs for every IPI as soon as we observe + * qpage being non-NULL, and instead will only EOI when we receive + * corresponding queue 0 entries + */ + rc = xive_native_configure_queue(xc->vp_id, q, prio, qpage, + xive->q_order, true); + if (rc) + pr_err("Failed to configure queue %d for VCPU %d\n", + prio, xc->server_num); + return rc; +} + +/* Called with kvm_lock held */ +static int xive_check_provisioning(struct kvm *kvm, u8 prio) +{ + struct kvmppc_xive *xive = kvm->arch.xive; + struct kvm_vcpu *vcpu; + int i, rc; + + lockdep_assert_held(&kvm->lock); + + /* Already provisioned ? */ + if (xive->qmap & (1 << prio)) + return 0; + + pr_devel("Provisioning prio... %d\n", prio); + + /* Provision each VCPU and enable escalations */ + kvm_for_each_vcpu(i, vcpu, kvm) { + if (!vcpu->arch.xive_vcpu) + continue; + rc = xive_provision_queue(vcpu, prio); + if (rc == 0) + xive_attach_escalation(vcpu, prio); + if (rc) + return rc; + } + + /* Order previous stores and mark it as provisioned */ + mb(); + xive->qmap |= (1 << prio); + return 0; +} + +static void xive_inc_q_pending(struct kvm *kvm, u32 server, u8 prio) +{ + struct kvm_vcpu *vcpu; + struct kvmppc_xive_vcpu *xc; + struct xive_q *q; + + /* Locate target server */ + vcpu = kvmppc_xive_find_server(kvm, server); + if (!vcpu) { + pr_warn("%s: Can't find server %d\n", __func__, server); + return; + } + xc = vcpu->arch.xive_vcpu; + if (WARN_ON(!xc)) + return; + + q = &xc->queues[prio]; + atomic_inc(&q->pending_count); +} + +static int xive_try_pick_queue(struct kvm_vcpu *vcpu, u8 prio) +{ + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + struct xive_q *q; + u32 max; + + if (WARN_ON(!xc)) + return -ENXIO; + if (!xc->valid) + return -ENXIO; + + q = &xc->queues[prio]; + if (WARN_ON(!q->qpage)) + return -ENXIO; + + /* Calculate max number of interrupts in that queue. */ + max = (q->msk + 1) - XIVE_Q_GAP; + return atomic_add_unless(&q->count, 1, max) ? 0 : -EBUSY; +} + +static int xive_select_target(struct kvm *kvm, u32 *server, u8 prio) +{ + struct kvm_vcpu *vcpu; + int i, rc; + + /* Locate target server */ + vcpu = kvmppc_xive_find_server(kvm, *server); + if (!vcpu) { + pr_devel("Can't find server %d\n", *server); + return -EINVAL; + } + + pr_devel("Finding irq target on 0x%x/%d...\n", *server, prio); + + /* Try pick it */ + rc = xive_try_pick_queue(vcpu, prio); + if (rc == 0) + return rc; + + pr_devel(" .. failed, looking up candidate...\n"); + + /* Failed, pick another VCPU */ + kvm_for_each_vcpu(i, vcpu, kvm) { + if (!vcpu->arch.xive_vcpu) + continue; + rc = xive_try_pick_queue(vcpu, prio); + if (rc == 0) { + *server = vcpu->arch.xive_vcpu->server_num; + pr_devel(" found on 0x%x/%d\n", *server, prio); + return rc; + } + } + pr_devel(" no available target !\n"); + + /* No available target ! */ + return -EBUSY; +} + +static u8 xive_lock_and_mask(struct kvmppc_xive *xive, + struct kvmppc_xive_src_block *sb, + struct kvmppc_xive_irq_state *state) +{ + struct xive_irq_data *xd; + u32 hw_num; + u8 old_prio; + u64 val; + + /* + * Take the lock, set masked, try again if racing + * with H_EOI + */ + for (;;) { + arch_spin_lock(&sb->lock); + old_prio = state->guest_priority; + state->guest_priority = MASKED; + mb(); + if (!state->in_eoi) + break; + state->guest_priority = old_prio; + arch_spin_unlock(&sb->lock); + } + + /* No change ? Bail */ + if (old_prio == MASKED) + return old_prio; + + /* Get the right irq */ + kvmppc_xive_select_irq(state, &hw_num, &xd); + + /* + * If the interrupt is marked as needing masking via + * firmware, we do it here. Firmware masking however + * is "lossy", it won't return the old p and q bits + * and won't set the interrupt to a state where it will + * record queued ones. If this is an issue we should do + * lazy masking instead. + * + * For now, we work around this in unmask by forcing + * an interrupt whenever we unmask a non-LSI via FW + * (if ever). + */ + if (xd->flags & OPAL_XIVE_IRQ_MASK_VIA_FW) { + xive_native_configure_irq(hw_num, + xive->vp_base + state->act_server, + MASKED, state->number); + /* set old_p so we can track if an H_EOI was done */ + state->old_p = true; + state->old_q = false; + } else { + /* Set PQ to 10, return old P and old Q and remember them */ + val = xive_vm_esb_load(xd, XIVE_ESB_SET_PQ_10); + state->old_p = !!(val & 2); + state->old_q = !!(val & 1); + + /* + * Synchronize hardware to sensure the queues are updated + * when masking + */ + xive_native_sync_source(hw_num); + } + + return old_prio; +} + +static void xive_lock_for_unmask(struct kvmppc_xive_src_block *sb, + struct kvmppc_xive_irq_state *state) +{ + /* + * Take the lock try again if racing with H_EOI + */ + for (;;) { + arch_spin_lock(&sb->lock); + if (!state->in_eoi) + break; + arch_spin_unlock(&sb->lock); + } +} + +static void xive_finish_unmask(struct kvmppc_xive *xive, + struct kvmppc_xive_src_block *sb, + struct kvmppc_xive_irq_state *state, + u8 prio) +{ + struct xive_irq_data *xd; + u32 hw_num; + + /* If we aren't changing a thing, move on */ + if (state->guest_priority != MASKED) + goto bail; + + /* Get the right irq */ + kvmppc_xive_select_irq(state, &hw_num, &xd); + + /* + * See command in xive_lock_and_mask() concerning masking + * via firmware. + */ + if (xd->flags & OPAL_XIVE_IRQ_MASK_VIA_FW) { + xive_native_configure_irq(hw_num, + xive->vp_base + state->act_server, + state->act_priority, state->number); + /* If an EOI is needed, do it here */ + if (!state->old_p) + xive_vm_source_eoi(hw_num, xd); + /* If this is not an LSI, force a trigger */ + if (!(xd->flags & OPAL_XIVE_IRQ_LSI)) + xive_irq_trigger(xd); + goto bail; + } + + /* Old Q set, set PQ to 11 */ + if (state->old_q) + xive_vm_esb_load(xd, XIVE_ESB_SET_PQ_11); + + /* + * If not old P, then perform an "effective" EOI, + * on the source. This will handle the cases where + * FW EOI is needed. + */ + if (!state->old_p) + xive_vm_source_eoi(hw_num, xd); + + /* Synchronize ordering and mark unmasked */ + mb(); +bail: + state->guest_priority = prio; +} + +/* + * Target an interrupt to a given server/prio, this will fallback + * to another server if necessary and perform the HW targetting + * updates as needed + * + * NOTE: Must be called with the state lock held + */ +static int xive_target_interrupt(struct kvm *kvm, + struct kvmppc_xive_irq_state *state, + u32 server, u8 prio) +{ + struct kvmppc_xive *xive = kvm->arch.xive; + u32 hw_num; + int rc; + + /* + * This will return a tentative server and actual + * priority. The count for that new target will have + * already been incremented. + */ + rc = xive_select_target(kvm, &server, prio); + + /* + * We failed to find a target ? Not much we can do + * at least until we support the GIQ. + */ + if (rc) + return rc; + + /* + * Increment the old queue pending count if there + * was one so that the old queue count gets adjusted later + * when observed to be empty. + */ + if (state->act_priority != MASKED) + xive_inc_q_pending(kvm, + state->act_server, + state->act_priority); + /* + * Update state and HW + */ + state->act_priority = prio; + state->act_server = server; + + /* Get the right irq */ + kvmppc_xive_select_irq(state, &hw_num, NULL); + + return xive_native_configure_irq(hw_num, + xive->vp_base + server, + prio, state->number); +} + +/* + * Targetting rules: In order to avoid losing track of + * pending interrupts accross mask and unmask, which would + * allow queue overflows, we implement the following rules: + * + * - Unless it was never enabled (or we run out of capacity) + * an interrupt is always targetted at a valid server/queue + * pair even when "masked" by the guest. This pair tends to + * be the last one used but it can be changed under some + * circumstances. That allows us to separate targetting + * from masking, we only handle accounting during (re)targetting, + * this also allows us to let an interrupt drain into its target + * queue after masking, avoiding complex schemes to remove + * interrupts out of remote processor queues. + * + * - When masking, we set PQ to 10 and save the previous value + * of P and Q. + * + * - When unmasking, if saved Q was set, we set PQ to 11 + * otherwise we leave PQ to the HW state which will be either + * 10 if nothing happened or 11 if the interrupt fired while + * masked. Effectively we are OR'ing the previous Q into the + * HW Q. + * + * Then if saved P is clear, we do an effective EOI (Q->P->Trigger) + * which will unmask the interrupt and shoot a new one if Q was + * set. + * + * Otherwise (saved P is set) we leave PQ unchanged (so 10 or 11, + * effectively meaning an H_EOI from the guest is still expected + * for that interrupt). + * + * - If H_EOI occurs while masked, we clear the saved P. + * + * - When changing target, we account on the new target and + * increment a separate "pending" counter on the old one. + * This pending counter will be used to decrement the old + * target's count when its queue has been observed empty. + */ + +int kvmppc_xive_set_xive(struct kvm *kvm, u32 irq, u32 server, + u32 priority) +{ + struct kvmppc_xive *xive = kvm->arch.xive; + struct kvmppc_xive_src_block *sb; + struct kvmppc_xive_irq_state *state; + u8 new_act_prio; + int rc = 0; + u16 idx; + + if (!xive) + return -ENODEV; + + pr_devel("set_xive ! irq 0x%x server 0x%x prio %d\n", + irq, server, priority); + + /* First, check provisioning of queues */ + if (priority != MASKED) + rc = xive_check_provisioning(xive->kvm, + xive_prio_from_guest(priority)); + if (rc) { + pr_devel(" provisioning failure %d !\n", rc); + return rc; + } + + sb = kvmppc_xive_find_source(xive, irq, &idx); + if (!sb) + return -EINVAL; + state = &sb->irq_state[idx]; + + /* + * We first handle masking/unmasking since the locking + * might need to be retried due to EOIs, we'll handle + * targetting changes later. These functions will return + * with the SB lock held. + * + * xive_lock_and_mask() will also set state->guest_priority + * but won't otherwise change other fields of the state. + * + * xive_lock_for_unmask will not actually unmask, this will + * be done later by xive_finish_unmask() once the targetting + * has been done, so we don't try to unmask an interrupt + * that hasn't yet been targetted. + */ + if (priority == MASKED) + xive_lock_and_mask(xive, sb, state); + else + xive_lock_for_unmask(sb, state); + + + /* + * Then we handle targetting. + * + * First calculate a new "actual priority" + */ + new_act_prio = state->act_priority; + if (priority != MASKED) + new_act_prio = xive_prio_from_guest(priority); + + pr_devel(" new_act_prio=%x act_server=%x act_prio=%x\n", + new_act_prio, state->act_server, state->act_priority); + + /* + * Then check if we actually need to change anything, + * + * The condition for re-targetting the interrupt is that + * we have a valid new priority (new_act_prio is not 0xff) + * and either the server or the priority changed. + * + * Note: If act_priority was ff and the new priority is + * also ff, we don't do anything and leave the interrupt + * untargetted. An attempt of doing an int_on on an + * untargetted interrupt will fail. If that is a problem + * we could initialize interrupts with valid default + */ + + if (new_act_prio != MASKED && + (state->act_server != server || + state->act_priority != new_act_prio)) + rc = xive_target_interrupt(kvm, state, server, new_act_prio); + + /* + * Perform the final unmasking of the interrupt source + * if necessary + */ + if (priority != MASKED) + xive_finish_unmask(xive, sb, state, priority); + + /* + * Finally Update saved_priority to match. Only int_on/off + * set this field to a different value. + */ + state->saved_priority = priority; + + arch_spin_unlock(&sb->lock); + return rc; +} + +int kvmppc_xive_get_xive(struct kvm *kvm, u32 irq, u32 *server, + u32 *priority) +{ + struct kvmppc_xive *xive = kvm->arch.xive; + struct kvmppc_xive_src_block *sb; + struct kvmppc_xive_irq_state *state; + u16 idx; + + if (!xive) + return -ENODEV; + + sb = kvmppc_xive_find_source(xive, irq, &idx); + if (!sb) + return -EINVAL; + state = &sb->irq_state[idx]; + arch_spin_lock(&sb->lock); + *server = state->guest_server; + *priority = state->guest_priority; + arch_spin_unlock(&sb->lock); + + return 0; +} + +int kvmppc_xive_int_on(struct kvm *kvm, u32 irq) +{ + struct kvmppc_xive *xive = kvm->arch.xive; + struct kvmppc_xive_src_block *sb; + struct kvmppc_xive_irq_state *state; + u16 idx; + + if (!xive) + return -ENODEV; + + sb = kvmppc_xive_find_source(xive, irq, &idx); + if (!sb) + return -EINVAL; + state = &sb->irq_state[idx]; + + pr_devel("int_on(irq=0x%x)\n", irq); + + /* + * Check if interrupt was not targetted + */ + if (state->act_priority == MASKED) { + pr_devel("int_on on untargetted interrupt\n"); + return -EINVAL; + } + + /* If saved_priority is 0xff, do nothing */ + if (state->saved_priority == MASKED) + return 0; + + /* + * Lock and unmask it. + */ + xive_lock_for_unmask(sb, state); + xive_finish_unmask(xive, sb, state, state->saved_priority); + arch_spin_unlock(&sb->lock); + + return 0; +} + +int kvmppc_xive_int_off(struct kvm *kvm, u32 irq) +{ + struct kvmppc_xive *xive = kvm->arch.xive; + struct kvmppc_xive_src_block *sb; + struct kvmppc_xive_irq_state *state; + u16 idx; + + if (!xive) + return -ENODEV; + + sb = kvmppc_xive_find_source(xive, irq, &idx); + if (!sb) + return -EINVAL; + state = &sb->irq_state[idx]; + + pr_devel("int_off(irq=0x%x)\n", irq); + + /* + * Lock and mask + */ + state->saved_priority = xive_lock_and_mask(xive, sb, state); + arch_spin_unlock(&sb->lock); + + return 0; +} + +static bool xive_restore_pending_irq(struct kvmppc_xive *xive, u32 irq) +{ + struct kvmppc_xive_src_block *sb; + struct kvmppc_xive_irq_state *state; + u16 idx; + + sb = kvmppc_xive_find_source(xive, irq, &idx); + if (!sb) + return false; + state = &sb->irq_state[idx]; + if (!state->valid) + return false; + + /* + * Trigger the IPI. This assumes we never restore a pass-through + * interrupt which should be safe enough + */ + xive_irq_trigger(&state->ipi_data); + + return true; +} + +u64 kvmppc_xive_get_icp(struct kvm_vcpu *vcpu) +{ + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + + if (!xc) + return 0; + + /* Return the per-cpu state for state saving/migration */ + return (u64)xc->cppr << KVM_REG_PPC_ICP_CPPR_SHIFT | + (u64)xc->mfrr << KVM_REG_PPC_ICP_MFRR_SHIFT; +} + +int kvmppc_xive_set_icp(struct kvm_vcpu *vcpu, u64 icpval) +{ + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + struct kvmppc_xive *xive = vcpu->kvm->arch.xive; + u8 cppr, mfrr; + u32 xisr; + + if (!xc || !xive) + return -ENOENT; + + /* Grab individual state fields. We don't use pending_pri */ + cppr = icpval >> KVM_REG_PPC_ICP_CPPR_SHIFT; + xisr = (icpval >> KVM_REG_PPC_ICP_XISR_SHIFT) & + KVM_REG_PPC_ICP_XISR_MASK; + mfrr = icpval >> KVM_REG_PPC_ICP_MFRR_SHIFT; + + pr_devel("set_icp vcpu %d cppr=0x%x mfrr=0x%x xisr=0x%x\n", + xc->server_num, cppr, mfrr, xisr); + + /* + * We can't update the state of a "pushed" VCPU, but that + * shouldn't happen. + */ + if (WARN_ON(vcpu->arch.xive_pushed)) + return -EIO; + + /* Update VCPU HW saved state */ + vcpu->arch.xive_saved_state.cppr = cppr; + xc->hw_cppr = xc->cppr = cppr; + + /* + * Update MFRR state. If it's not 0xff, we mark the VCPU as + * having a pending MFRR change, which will re-evaluate the + * target. The VCPU will thus potentially get a spurious + * interrupt but that's not a big deal. + */ + xc->mfrr = mfrr; + if (mfrr < cppr) + xive_irq_trigger(&xc->vp_ipi_data); + + /* + * Now saved XIRR is "interesting". It means there's something in + * the legacy "1 element" queue... for an IPI we simply ignore it, + * as the MFRR restore will handle that. For anything else we need + * to force a resend of the source. + * However the source may not have been setup yet. If that's the + * case, we keep that info and increment a counter in the xive to + * tell subsequent xive_set_source() to go look. + */ + if (xisr > XICS_IPI && !xive_restore_pending_irq(xive, xisr)) { + xc->delayed_irq = xisr; + xive->delayed_irqs++; + pr_devel(" xisr restore delayed\n"); + } + + return 0; +} + +int kvmppc_xive_set_mapped(struct kvm *kvm, unsigned long guest_irq, + struct irq_desc *host_desc) +{ + struct kvmppc_xive *xive = kvm->arch.xive; + struct kvmppc_xive_src_block *sb; + struct kvmppc_xive_irq_state *state; + struct irq_data *host_data = irq_desc_get_irq_data(host_desc); + unsigned int host_irq = irq_desc_get_irq(host_desc); + unsigned int hw_irq = (unsigned int)irqd_to_hwirq(host_data); + u16 idx; + u8 prio; + int rc; + + if (!xive) + return -ENODEV; + + pr_devel("set_mapped girq 0x%lx host HW irq 0x%x...\n",guest_irq, hw_irq); + + sb = kvmppc_xive_find_source(xive, guest_irq, &idx); + if (!sb) + return -EINVAL; + state = &sb->irq_state[idx]; + + /* + * Mark the passed-through interrupt as going to a VCPU, + * this will prevent further EOIs and similar operations + * from the XIVE code. It will also mask the interrupt + * to either PQ=10 or 11 state, the latter if the interrupt + * is pending. This will allow us to unmask or retrigger it + * after routing it to the guest with a simple EOI. + * + * The "state" argument is a "token", all it needs is to be + * non-NULL to switch to passed-through or NULL for the + * other way around. We may not yet have an actual VCPU + * target here and we don't really care. + */ + rc = irq_set_vcpu_affinity(host_irq, state); + if (rc) { + pr_err("Failed to set VCPU affinity for irq %d\n", host_irq); + return rc; + } + + /* + * Mask and read state of IPI. We need to know if its P bit + * is set as that means it's potentially already using a + * queue entry in the target + */ + prio = xive_lock_and_mask(xive, sb, state); + pr_devel(" old IPI prio %02x P:%d Q:%d\n", prio, + state->old_p, state->old_q); + + /* Turn the IPI hard off */ + xive_vm_esb_load(&state->ipi_data, XIVE_ESB_SET_PQ_01); + + /* Grab info about irq */ + state->pt_number = hw_irq; + state->pt_data = irq_data_get_irq_handler_data(host_data); + + /* + * Configure the IRQ to match the existing configuration of + * the IPI if it was already targetted. Otherwise this will + * mask the interrupt in a lossy way (act_priority is 0xff) + * which is fine for a never started interrupt. + */ + xive_native_configure_irq(hw_irq, + xive->vp_base + state->act_server, + state->act_priority, state->number); + + /* + * We do an EOI to enable the interrupt (and retrigger if needed) + * if the guest has the interrupt unmasked and the P bit was *not* + * set in the IPI. If it was set, we know a slot may still be in + * use in the target queue thus we have to wait for a guest + * originated EOI + */ + if (prio != MASKED && !state->old_p) + xive_vm_source_eoi(hw_irq, state->pt_data); + + /* Clear old_p/old_q as they are no longer relevant */ + state->old_p = state->old_q = false; + + /* Restore guest prio (unlocks EOI) */ + mb(); + state->guest_priority = prio; + arch_spin_unlock(&sb->lock); + + return 0; +} +EXPORT_SYMBOL_GPL(kvmppc_xive_set_mapped); + +int kvmppc_xive_clr_mapped(struct kvm *kvm, unsigned long guest_irq, + struct irq_desc *host_desc) +{ + struct kvmppc_xive *xive = kvm->arch.xive; + struct kvmppc_xive_src_block *sb; + struct kvmppc_xive_irq_state *state; + unsigned int host_irq = irq_desc_get_irq(host_desc); + u16 idx; + u8 prio; + int rc; + + if (!xive) + return -ENODEV; + + pr_devel("clr_mapped girq 0x%lx...\n", guest_irq); + + sb = kvmppc_xive_find_source(xive, guest_irq, &idx); + if (!sb) + return -EINVAL; + state = &sb->irq_state[idx]; + + /* + * Mask and read state of IRQ. We need to know if its P bit + * is set as that means it's potentially already using a + * queue entry in the target + */ + prio = xive_lock_and_mask(xive, sb, state); + pr_devel(" old IRQ prio %02x P:%d Q:%d\n", prio, + state->old_p, state->old_q); + + /* + * If old_p is set, the interrupt is pending, we switch it to + * PQ=11. This will force a resend in the host so the interrupt + * isn't lost to whatver host driver may pick it up + */ + if (state->old_p) + xive_vm_esb_load(state->pt_data, XIVE_ESB_SET_PQ_11); + + /* Release the passed-through interrupt to the host */ + rc = irq_set_vcpu_affinity(host_irq, NULL); + if (rc) { + pr_err("Failed to clr VCPU affinity for irq %d\n", host_irq); + return rc; + } + + /* Forget about the IRQ */ + state->pt_number = 0; + state->pt_data = NULL; + + /* Reconfigure the IPI */ + xive_native_configure_irq(state->ipi_number, + xive->vp_base + state->act_server, + state->act_priority, state->number); + + /* + * If old_p is set (we have a queue entry potentially + * occupied) or the interrupt is masked, we set the IPI + * to PQ=10 state. Otherwise we just re-enable it (PQ=00). + */ + if (prio == MASKED || state->old_p) + xive_vm_esb_load(&state->ipi_data, XIVE_ESB_SET_PQ_10); + else + xive_vm_esb_load(&state->ipi_data, XIVE_ESB_SET_PQ_00); + + /* Restore guest prio (unlocks EOI) */ + mb(); + state->guest_priority = prio; + arch_spin_unlock(&sb->lock); + + return 0; +} +EXPORT_SYMBOL_GPL(kvmppc_xive_clr_mapped); + +static void kvmppc_xive_disable_vcpu_interrupts(struct kvm_vcpu *vcpu) +{ + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + struct kvm *kvm = vcpu->kvm; + struct kvmppc_xive *xive = kvm->arch.xive; + int i, j; + + for (i = 0; i <= xive->max_sbid; i++) { + struct kvmppc_xive_src_block *sb = xive->src_blocks[i]; + + if (!sb) + continue; + for (j = 0; j < KVMPPC_XICS_IRQ_PER_ICS; j++) { + struct kvmppc_xive_irq_state *state = &sb->irq_state[j]; + + if (!state->valid) + continue; + if (state->act_priority == MASKED) + continue; + if (state->act_server != xc->server_num) + continue; + + /* Clean it up */ + arch_spin_lock(&sb->lock); + state->act_priority = MASKED; + xive_vm_esb_load(&state->ipi_data, XIVE_ESB_SET_PQ_01); + xive_native_configure_irq(state->ipi_number, 0, MASKED, 0); + if (state->pt_number) { + xive_vm_esb_load(state->pt_data, XIVE_ESB_SET_PQ_01); + xive_native_configure_irq(state->pt_number, 0, MASKED, 0); + } + arch_spin_unlock(&sb->lock); + } + } +} + +void kvmppc_xive_cleanup_vcpu(struct kvm_vcpu *vcpu) +{ + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + struct kvmppc_xive *xive = xc->xive; + int i; + + pr_devel("cleanup_vcpu(cpu=%d)\n", xc->server_num); + + /* Ensure no interrupt is still routed to that VP */ + xc->valid = false; + kvmppc_xive_disable_vcpu_interrupts(vcpu); + + /* Mask the VP IPI */ + xive_vm_esb_load(&xc->vp_ipi_data, XIVE_ESB_SET_PQ_01); + + /* Disable the VP */ + xive_native_disable_vp(xc->vp_id); + + /* Free the queues & associated interrupts */ + for (i = 0; i < KVMPPC_XIVE_Q_COUNT; i++) { + struct xive_q *q = &xc->queues[i]; + + /* Free the escalation irq */ + if (xc->esc_virq[i]) { + free_irq(xc->esc_virq[i], vcpu); + irq_dispose_mapping(xc->esc_virq[i]); + kfree(xc->esc_virq_names[i]); + } + /* Free the queue */ + xive_native_disable_queue(xc->vp_id, q, i); + if (q->qpage) { + free_pages((unsigned long)q->qpage, + xive->q_page_order); + q->qpage = NULL; + } + } + + /* Free the IPI */ + if (xc->vp_ipi) { + xive_cleanup_irq_data(&xc->vp_ipi_data); + xive_native_free_irq(xc->vp_ipi); + } + /* Free the VP */ + kfree(xc); +} + +int kvmppc_xive_connect_vcpu(struct kvm_device *dev, + struct kvm_vcpu *vcpu, u32 cpu) +{ + struct kvmppc_xive *xive = dev->private; + struct kvmppc_xive_vcpu *xc; + int i, r = -EBUSY; + + pr_devel("connect_vcpu(cpu=%d)\n", cpu); + + if (dev->ops != &kvm_xive_ops) { + pr_devel("Wrong ops !\n"); + return -EPERM; + } + if (xive->kvm != vcpu->kvm) + return -EPERM; + if (vcpu->arch.irq_type) + return -EBUSY; + if (kvmppc_xive_find_server(vcpu->kvm, cpu)) { + pr_devel("Duplicate !\n"); + return -EEXIST; + } + if (cpu >= KVM_MAX_VCPUS) { + pr_devel("Out of bounds !\n"); + return -EINVAL; + } + xc = kzalloc(sizeof(*xc), GFP_KERNEL); + if (!xc) + return -ENOMEM; + + /* We need to synchronize with queue provisioning */ + mutex_lock(&vcpu->kvm->lock); + vcpu->arch.xive_vcpu = xc; + xc->xive = xive; + xc->vcpu = vcpu; + xc->server_num = cpu; + xc->vp_id = xive->vp_base + cpu; + xc->mfrr = 0xff; + xc->valid = true; + + r = xive_native_get_vp_info(xc->vp_id, &xc->vp_cam, &xc->vp_chip_id); + if (r) + goto bail; + + /* Configure VCPU fields for use by assembly push/pull */ + vcpu->arch.xive_saved_state.w01 = cpu_to_be64(0xff000000); + vcpu->arch.xive_cam_word = cpu_to_be32(xc->vp_cam | TM_QW1W2_VO); + + /* Allocate IPI */ + xc->vp_ipi = xive_native_alloc_irq(); + if (!xc->vp_ipi) { + r = -EIO; + goto bail; + } + pr_devel(" IPI=0x%x\n", xc->vp_ipi); + + r = xive_native_populate_irq_data(xc->vp_ipi, &xc->vp_ipi_data); + if (r) + goto bail; + + /* + * Initialize queues. Initially we set them all for no queueing + * and we enable escalation for queue 0 only which we'll use for + * our mfrr change notifications. If the VCPU is hot-plugged, we + * do handle provisioning however. + */ + for (i = 0; i < KVMPPC_XIVE_Q_COUNT; i++) { + struct xive_q *q = &xc->queues[i]; + + /* Is queue already enabled ? Provision it */ + if (xive->qmap & (1 << i)) { + r = xive_provision_queue(vcpu, i); + if (r == 0) + xive_attach_escalation(vcpu, i); + if (r) + goto bail; + } else { + r = xive_native_configure_queue(xc->vp_id, + q, i, NULL, 0, true); + if (r) { + pr_err("Failed to configure queue %d for VCPU %d\n", + i, cpu); + goto bail; + } + } + } + + /* If not done above, attach priority 0 escalation */ + r = xive_attach_escalation(vcpu, 0); + if (r) + goto bail; + + /* Enable the VP */ + r = xive_native_enable_vp(xc->vp_id); + if (r) + goto bail; + + /* Route the IPI */ + r = xive_native_configure_irq(xc->vp_ipi, xc->vp_id, 0, XICS_IPI); + if (!r) + xive_vm_esb_load(&xc->vp_ipi_data, XIVE_ESB_SET_PQ_00); + +bail: + mutex_unlock(&vcpu->kvm->lock); + if (r) { + kvmppc_xive_cleanup_vcpu(vcpu); + return r; + } + + vcpu->arch.irq_type = KVMPPC_IRQ_XICS; + return 0; +} + +/* + * Scanning of queues before/after migration save + */ +static void xive_pre_save_set_queued(struct kvmppc_xive *xive, u32 irq) +{ + struct kvmppc_xive_src_block *sb; + struct kvmppc_xive_irq_state *state; + u16 idx; + + sb = kvmppc_xive_find_source(xive, irq, &idx); + if (!sb) + return; + + state = &sb->irq_state[idx]; + + /* Some sanity checking */ + if (!state->valid) { + pr_err("invalid irq 0x%x in cpu queue!\n", irq); + return; + } + + /* + * If the interrupt is in a queue it should have P set. + * We warn so that gets reported. A backtrace isn't useful + * so no need to use a WARN_ON. + */ + if (!state->saved_p) + pr_err("Interrupt 0x%x is marked in a queue but P not set !\n", irq); + + /* Set flag */ + state->in_queue = true; +} + +static void xive_pre_save_mask_irq(struct kvmppc_xive *xive, + struct kvmppc_xive_src_block *sb, + u32 irq) +{ + struct kvmppc_xive_irq_state *state = &sb->irq_state[irq]; + + if (!state->valid) + return; + + /* Mask and save state, this will also sync HW queues */ + state->saved_scan_prio = xive_lock_and_mask(xive, sb, state); + + /* Transfer P and Q */ + state->saved_p = state->old_p; + state->saved_q = state->old_q; + + /* Unlock */ + arch_spin_unlock(&sb->lock); +} + +static void xive_pre_save_unmask_irq(struct kvmppc_xive *xive, + struct kvmppc_xive_src_block *sb, + u32 irq) +{ + struct kvmppc_xive_irq_state *state = &sb->irq_state[irq]; + + if (!state->valid) + return; + + /* + * Lock / exclude EOI (not technically necessary if the + * guest isn't running concurrently. If this becomes a + * performance issue we can probably remove the lock. + */ + xive_lock_for_unmask(sb, state); + + /* Restore mask/prio if it wasn't masked */ + if (state->saved_scan_prio != MASKED) + xive_finish_unmask(xive, sb, state, state->saved_scan_prio); + + /* Unlock */ + arch_spin_unlock(&sb->lock); +} + +static void xive_pre_save_queue(struct kvmppc_xive *xive, struct xive_q *q) +{ + u32 idx = q->idx; + u32 toggle = q->toggle; + u32 irq; + + do { + irq = __xive_read_eq(q->qpage, q->msk, &idx, &toggle); + if (irq > XICS_IPI) + xive_pre_save_set_queued(xive, irq); + } while(irq); +} + +static void xive_pre_save_scan(struct kvmppc_xive *xive) +{ + struct kvm_vcpu *vcpu = NULL; + int i, j; + + /* + * See comment in xive_get_source() about how this + * work. Collect a stable state for all interrupts + */ + for (i = 0; i <= xive->max_sbid; i++) { + struct kvmppc_xive_src_block *sb = xive->src_blocks[i]; + if (!sb) + continue; + for (j = 0; j < KVMPPC_XICS_IRQ_PER_ICS; j++) + xive_pre_save_mask_irq(xive, sb, j); + } + + /* Then scan the queues and update the "in_queue" flag */ + kvm_for_each_vcpu(i, vcpu, xive->kvm) { + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + if (!xc) + continue; + for (j = 0; j < KVMPPC_XIVE_Q_COUNT; j++) { + if (xc->queues[i].qpage) + xive_pre_save_queue(xive, &xc->queues[i]); + } + } + + /* Finally restore interrupt states */ + for (i = 0; i <= xive->max_sbid; i++) { + struct kvmppc_xive_src_block *sb = xive->src_blocks[i]; + if (!sb) + continue; + for (j = 0; j < KVMPPC_XICS_IRQ_PER_ICS; j++) + xive_pre_save_unmask_irq(xive, sb, j); + } +} + +static void xive_post_save_scan(struct kvmppc_xive *xive) +{ + u32 i, j; + + /* Clear all the in_queue flags */ + for (i = 0; i <= xive->max_sbid; i++) { + struct kvmppc_xive_src_block *sb = xive->src_blocks[i]; + if (!sb) + continue; + for (j = 0; j < KVMPPC_XICS_IRQ_PER_ICS; j++) + sb->irq_state[j].in_queue = false; + } + + /* Next get_source() will do a new scan */ + xive->saved_src_count = 0; +} + +/* + * This returns the source configuration and state to user space. + */ +static int xive_get_source(struct kvmppc_xive *xive, long irq, u64 addr) +{ + struct kvmppc_xive_src_block *sb; + struct kvmppc_xive_irq_state *state; + u64 __user *ubufp = (u64 __user *) addr; + u64 val, prio; + u16 idx; + + sb = kvmppc_xive_find_source(xive, irq, &idx); + if (!sb) + return -ENOENT; + + state = &sb->irq_state[idx]; + + if (!state->valid) + return -ENOENT; + + pr_devel("get_source(%ld)...\n", irq); + + /* + * So to properly save the state into something that looks like a + * XICS migration stream we cannot treat interrupts individually. + * + * We need, instead, mask them all (& save their previous PQ state) + * to get a stable state in the HW, then sync them to ensure that + * any interrupt that had already fired hits its queue, and finally + * scan all the queues to collect which interrupts are still present + * in the queues, so we can set the "pending" flag on them and + * they can be resent on restore. + * + * So we do it all when the "first" interrupt gets saved, all the + * state is collected at that point, the rest of xive_get_source() + * will merely collect and convert that state to the expected + * userspace bit mask. + */ + if (xive->saved_src_count == 0) + xive_pre_save_scan(xive); + xive->saved_src_count++; + + /* Convert saved state into something compatible with xics */ + val = state->guest_server; + prio = state->saved_scan_prio; + + if (prio == MASKED) { + val |= KVM_XICS_MASKED; + prio = state->saved_priority; + } + val |= prio << KVM_XICS_PRIORITY_SHIFT; + if (state->lsi) { + val |= KVM_XICS_LEVEL_SENSITIVE; + if (state->saved_p) + val |= KVM_XICS_PENDING; + } else { + if (state->saved_p) + val |= KVM_XICS_PRESENTED; + + if (state->saved_q) + val |= KVM_XICS_QUEUED; + + /* + * We mark it pending (which will attempt a re-delivery) + * if we are in a queue *or* we were masked and had + * Q set which is equivalent to the XICS "masked pending" + * state + */ + if (state->in_queue || (prio == MASKED && state->saved_q)) + val |= KVM_XICS_PENDING; + } + + /* + * If that was the last interrupt saved, reset the + * in_queue flags + */ + if (xive->saved_src_count == xive->src_count) + xive_post_save_scan(xive); + + /* Copy the result to userspace */ + if (put_user(val, ubufp)) + return -EFAULT; + + return 0; +} + +static struct kvmppc_xive_src_block *xive_create_src_block(struct kvmppc_xive *xive, + int irq) +{ + struct kvm *kvm = xive->kvm; + struct kvmppc_xive_src_block *sb; + int i, bid; + + bid = irq >> KVMPPC_XICS_ICS_SHIFT; + + mutex_lock(&kvm->lock); + + /* block already exists - somebody else got here first */ + if (xive->src_blocks[bid]) + goto out; + + /* Create the ICS */ + sb = kzalloc(sizeof(*sb), GFP_KERNEL); + if (!sb) + goto out; + + sb->id = bid; + + for (i = 0; i < KVMPPC_XICS_IRQ_PER_ICS; i++) { + sb->irq_state[i].number = (bid << KVMPPC_XICS_ICS_SHIFT) | i; + sb->irq_state[i].guest_priority = MASKED; + sb->irq_state[i].saved_priority = MASKED; + sb->irq_state[i].act_priority = MASKED; + } + smp_wmb(); + xive->src_blocks[bid] = sb; + + if (bid > xive->max_sbid) + xive->max_sbid = bid; + +out: + mutex_unlock(&kvm->lock); + return xive->src_blocks[bid]; +} + +static bool xive_check_delayed_irq(struct kvmppc_xive *xive, u32 irq) +{ + struct kvm *kvm = xive->kvm; + struct kvm_vcpu *vcpu = NULL; + int i; + + kvm_for_each_vcpu(i, vcpu, kvm) { + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + + if (!xc) + continue; + + if (xc->delayed_irq == irq) { + xc->delayed_irq = 0; + xive->delayed_irqs--; + return true; + } + } + return false; +} + +static int xive_set_source(struct kvmppc_xive *xive, long irq, u64 addr) +{ + struct kvmppc_xive_src_block *sb; + struct kvmppc_xive_irq_state *state; + u64 __user *ubufp = (u64 __user *) addr; + u16 idx; + u64 val; + u8 act_prio, guest_prio; + u32 server; + int rc = 0; + + if (irq < KVMPPC_XICS_FIRST_IRQ || irq >= KVMPPC_XICS_NR_IRQS) + return -ENOENT; + + pr_devel("set_source(irq=0x%lx)\n", irq); + + /* Find the source */ + sb = kvmppc_xive_find_source(xive, irq, &idx); + if (!sb) { + pr_devel("No source, creating source block...\n"); + sb = xive_create_src_block(xive, irq); + if (!sb) { + pr_devel("Failed to create block...\n"); + return -ENOMEM; + } + } + state = &sb->irq_state[idx]; + + /* Read user passed data */ + if (get_user(val, ubufp)) { + pr_devel("fault getting user info !\n"); + return -EFAULT; + } + + server = val & KVM_XICS_DESTINATION_MASK; + guest_prio = val >> KVM_XICS_PRIORITY_SHIFT; + + pr_devel(" val=0x016%llx (server=0x%x, guest_prio=%d)\n", + val, server, guest_prio); + /* + * If the source doesn't already have an IPI, allocate + * one and get the corresponding data + */ + if (!state->ipi_number) { + state->ipi_number = xive_native_alloc_irq(); + if (state->ipi_number == 0) { + pr_devel("Failed to allocate IPI !\n"); + return -ENOMEM; + } + xive_native_populate_irq_data(state->ipi_number, &state->ipi_data); + pr_devel(" src_ipi=0x%x\n", state->ipi_number); + } + + /* + * We use lock_and_mask() to set us in the right masked + * state. We will override that state from the saved state + * further down, but this will handle the cases of interrupts + * that need FW masking. We set the initial guest_priority to + * 0 before calling it to ensure it actually performs the masking. + */ + state->guest_priority = 0; + xive_lock_and_mask(xive, sb, state); + + /* + * Now, we select a target if we have one. If we don't we + * leave the interrupt untargetted. It means that an interrupt + * can become "untargetted" accross migration if it was masked + * by set_xive() but there is little we can do about it. + */ + + /* First convert prio and mark interrupt as untargetted */ + act_prio = xive_prio_from_guest(guest_prio); + state->act_priority = MASKED; + state->guest_server = server; + + /* + * We need to drop the lock due to the mutex below. Hopefully + * nothing is touching that interrupt yet since it hasn't been + * advertized to a running guest yet + */ + arch_spin_unlock(&sb->lock); + + /* If we have a priority target the interrupt */ + if (act_prio != MASKED) { + /* First, check provisioning of queues */ + mutex_lock(&xive->kvm->lock); + rc = xive_check_provisioning(xive->kvm, act_prio); + mutex_unlock(&xive->kvm->lock); + + /* Target interrupt */ + if (rc == 0) + rc = xive_target_interrupt(xive->kvm, state, + server, act_prio); + /* + * If provisioning or targetting failed, leave it + * alone and masked. It will remain disabled until + * the guest re-targets it. + */ + } + + /* + * Find out if this was a delayed irq stashed in an ICP, + * in which case, treat it as pending + */ + if (xive->delayed_irqs && xive_check_delayed_irq(xive, irq)) { + val |= KVM_XICS_PENDING; + pr_devel(" Found delayed ! forcing PENDING !\n"); + } + + /* Cleanup the SW state */ + state->old_p = false; + state->old_q = false; + state->lsi = false; + state->asserted = false; + + /* Restore LSI state */ + if (val & KVM_XICS_LEVEL_SENSITIVE) { + state->lsi = true; + if (val & KVM_XICS_PENDING) + state->asserted = true; + pr_devel(" LSI ! Asserted=%d\n", state->asserted); + } + + /* + * Restore P and Q. If the interrupt was pending, we + * force both P and Q, which will trigger a resend. + * + * That means that a guest that had both an interrupt + * pending (queued) and Q set will restore with only + * one instance of that interrupt instead of 2, but that + * is perfectly fine as coalescing interrupts that haven't + * been presented yet is always allowed. + */ + if (val & KVM_XICS_PRESENTED || val & KVM_XICS_PENDING) + state->old_p = true; + if (val & KVM_XICS_QUEUED || val & KVM_XICS_PENDING) + state->old_q = true; + + pr_devel(" P=%d, Q=%d\n", state->old_p, state->old_q); + + /* + * If the interrupt was unmasked, update guest priority and + * perform the appropriate state transition and do a + * re-trigger if necessary. + */ + if (val & KVM_XICS_MASKED) { + pr_devel(" masked, saving prio\n"); + state->guest_priority = MASKED; + state->saved_priority = guest_prio; + } else { + pr_devel(" unmasked, restoring to prio %d\n", guest_prio); + xive_finish_unmask(xive, sb, state, guest_prio); + state->saved_priority = guest_prio; + } + + /* Increment the number of valid sources and mark this one valid */ + if (!state->valid) + xive->src_count++; + state->valid = true; + + return 0; +} + +int kvmppc_xive_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, + bool line_status) +{ + struct kvmppc_xive *xive = kvm->arch.xive; + struct kvmppc_xive_src_block *sb; + struct kvmppc_xive_irq_state *state; + u16 idx; + + if (!xive) + return -ENODEV; + + sb = kvmppc_xive_find_source(xive, irq, &idx); + if (!sb) + return -EINVAL; + + /* Perform locklessly .... (we need to do some RCUisms here...) */ + state = &sb->irq_state[idx]; + if (!state->valid) + return -EINVAL; + + /* We don't allow a trigger on a passed-through interrupt */ + if (state->pt_number) + return -EINVAL; + + if ((level == 1 && state->lsi) || level == KVM_INTERRUPT_SET_LEVEL) + state->asserted = 1; + else if (level == 0 || level == KVM_INTERRUPT_UNSET) { + state->asserted = 0; + return 0; + } + + /* Trigger the IPI */ + xive_irq_trigger(&state->ipi_data); + + return 0; +} + +static int xive_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) +{ + struct kvmppc_xive *xive = dev->private; + + /* We honor the existing XICS ioctl */ + switch (attr->group) { + case KVM_DEV_XICS_GRP_SOURCES: + return xive_set_source(xive, attr->attr, attr->addr); + } + return -ENXIO; +} + +static int xive_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr) +{ + struct kvmppc_xive *xive = dev->private; + + /* We honor the existing XICS ioctl */ + switch (attr->group) { + case KVM_DEV_XICS_GRP_SOURCES: + return xive_get_source(xive, attr->attr, attr->addr); + } + return -ENXIO; +} + +static int xive_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr) +{ + /* We honor the same limits as XICS, at least for now */ + switch (attr->group) { + case KVM_DEV_XICS_GRP_SOURCES: + if (attr->attr >= KVMPPC_XICS_FIRST_IRQ && + attr->attr < KVMPPC_XICS_NR_IRQS) + return 0; + break; + } + return -ENXIO; +} + +static void kvmppc_xive_cleanup_irq(u32 hw_num, struct xive_irq_data *xd) +{ + xive_vm_esb_load(xd, XIVE_ESB_SET_PQ_01); + xive_native_configure_irq(hw_num, 0, MASKED, 0); + xive_cleanup_irq_data(xd); +} + +static void kvmppc_xive_free_sources(struct kvmppc_xive_src_block *sb) +{ + int i; + + for (i = 0; i < KVMPPC_XICS_IRQ_PER_ICS; i++) { + struct kvmppc_xive_irq_state *state = &sb->irq_state[i]; + + if (!state->valid) + continue; + + kvmppc_xive_cleanup_irq(state->ipi_number, &state->ipi_data); + xive_native_free_irq(state->ipi_number); + + /* Pass-through, cleanup too */ + if (state->pt_number) + kvmppc_xive_cleanup_irq(state->pt_number, state->pt_data); + + state->valid = false; + } +} + +static void kvmppc_xive_free(struct kvm_device *dev) +{ + struct kvmppc_xive *xive = dev->private; + struct kvm *kvm = xive->kvm; + int i; + + debugfs_remove(xive->dentry); + + if (kvm) + kvm->arch.xive = NULL; + + /* Mask and free interrupts */ + for (i = 0; i <= xive->max_sbid; i++) { + if (xive->src_blocks[i]) + kvmppc_xive_free_sources(xive->src_blocks[i]); + kfree(xive->src_blocks[i]); + xive->src_blocks[i] = NULL; + } + + if (xive->vp_base != XIVE_INVALID_VP) + xive_native_free_vp_block(xive->vp_base); + + + kfree(xive); + kfree(dev); +} + +static int kvmppc_xive_create(struct kvm_device *dev, u32 type) +{ + struct kvmppc_xive *xive; + struct kvm *kvm = dev->kvm; + int ret = 0; + + pr_devel("Creating xive for partition\n"); + + xive = kzalloc(sizeof(*xive), GFP_KERNEL); + if (!xive) + return -ENOMEM; + + dev->private = xive; + xive->dev = dev; + xive->kvm = kvm; + + /* Already there ? */ + if (kvm->arch.xive) + ret = -EEXIST; + else + kvm->arch.xive = xive; + + /* We use the default queue size set by the host */ + xive->q_order = xive_native_default_eq_shift(); + if (xive->q_order < PAGE_SHIFT) + xive->q_page_order = 0; + else + xive->q_page_order = xive->q_order - PAGE_SHIFT; + + /* Allocate a bunch of VPs */ + xive->vp_base = xive_native_alloc_vp_block(KVM_MAX_VCPUS); + pr_devel("VP_Base=%x\n", xive->vp_base); + + if (xive->vp_base == XIVE_INVALID_VP) + ret = -ENOMEM; + + if (ret) { + kfree(xive); + return ret; + } + + return 0; +} + + +static int xive_debug_show(struct seq_file *m, void *private) +{ + struct kvmppc_xive *xive = m->private; + struct kvm *kvm = xive->kvm; + struct kvm_vcpu *vcpu; + u64 t_rm_h_xirr = 0; + u64 t_rm_h_ipoll = 0; + u64 t_rm_h_cppr = 0; + u64 t_rm_h_eoi = 0; + u64 t_rm_h_ipi = 0; + u64 t_vm_h_xirr = 0; + u64 t_vm_h_ipoll = 0; + u64 t_vm_h_cppr = 0; + u64 t_vm_h_eoi = 0; + u64 t_vm_h_ipi = 0; + unsigned int i; + + if (!kvm) + return 0; + + seq_printf(m, "=========\nVCPU state\n=========\n"); + + kvm_for_each_vcpu(i, vcpu, kvm) { + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + + if (!xc) + continue; + + seq_printf(m, "cpu server %#x CPPR:%#x HWCPPR:%#x" + " MFRR:%#x PEND:%#x h_xirr: R=%lld V=%lld\n", + xc->server_num, xc->cppr, xc->hw_cppr, + xc->mfrr, xc->pending, + xc->stat_rm_h_xirr, xc->stat_vm_h_xirr); + + t_rm_h_xirr += xc->stat_rm_h_xirr; + t_rm_h_ipoll += xc->stat_rm_h_ipoll; + t_rm_h_cppr += xc->stat_rm_h_cppr; + t_rm_h_eoi += xc->stat_rm_h_eoi; + t_rm_h_ipi += xc->stat_rm_h_ipi; + t_vm_h_xirr += xc->stat_vm_h_xirr; + t_vm_h_ipoll += xc->stat_vm_h_ipoll; + t_vm_h_cppr += xc->stat_vm_h_cppr; + t_vm_h_eoi += xc->stat_vm_h_eoi; + t_vm_h_ipi += xc->stat_vm_h_ipi; + } + + seq_printf(m, "Hcalls totals\n"); + seq_printf(m, " H_XIRR R=%10lld V=%10lld\n", t_rm_h_xirr, t_vm_h_xirr); + seq_printf(m, " H_IPOLL R=%10lld V=%10lld\n", t_rm_h_ipoll, t_vm_h_ipoll); + seq_printf(m, " H_CPPR R=%10lld V=%10lld\n", t_rm_h_cppr, t_vm_h_cppr); + seq_printf(m, " H_EOI R=%10lld V=%10lld\n", t_rm_h_eoi, t_vm_h_eoi); + seq_printf(m, " H_IPI R=%10lld V=%10lld\n", t_rm_h_ipi, t_vm_h_ipi); + + return 0; +} + +static int xive_debug_open(struct inode *inode, struct file *file) +{ + return single_open(file, xive_debug_show, inode->i_private); +} + +static const struct file_operations xive_debug_fops = { + .open = xive_debug_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void xive_debugfs_init(struct kvmppc_xive *xive) +{ + char *name; + + name = kasprintf(GFP_KERNEL, "kvm-xive-%p", xive); + if (!name) { + pr_err("%s: no memory for name\n", __func__); + return; + } + + xive->dentry = debugfs_create_file(name, S_IRUGO, powerpc_debugfs_root, + xive, &xive_debug_fops); + + pr_debug("%s: created %s\n", __func__, name); + kfree(name); +} + +static void kvmppc_xive_init(struct kvm_device *dev) +{ + struct kvmppc_xive *xive = (struct kvmppc_xive *)dev->private; + + /* Register some debug interfaces */ + xive_debugfs_init(xive); +} + +struct kvm_device_ops kvm_xive_ops = { + .name = "kvm-xive", + .create = kvmppc_xive_create, + .init = kvmppc_xive_init, + .destroy = kvmppc_xive_free, + .set_attr = xive_set_attr, + .get_attr = xive_get_attr, + .has_attr = xive_has_attr, +}; + +void kvmppc_xive_init_module(void) +{ + __xive_vm_h_xirr = xive_vm_h_xirr; + __xive_vm_h_ipoll = xive_vm_h_ipoll; + __xive_vm_h_ipi = xive_vm_h_ipi; + __xive_vm_h_cppr = xive_vm_h_cppr; + __xive_vm_h_eoi = xive_vm_h_eoi; +} + +void kvmppc_xive_exit_module(void) +{ + __xive_vm_h_xirr = NULL; + __xive_vm_h_ipoll = NULL; + __xive_vm_h_ipi = NULL; + __xive_vm_h_cppr = NULL; + __xive_vm_h_eoi = NULL; +} diff --git a/arch/powerpc/kvm/book3s_xive.h b/arch/powerpc/kvm/book3s_xive.h new file mode 100644 index 000000000000..5938f7644dc1 --- /dev/null +++ b/arch/powerpc/kvm/book3s_xive.h @@ -0,0 +1,256 @@ +/* + * Copyright 2017 Benjamin Herrenschmidt, IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + */ + +#ifndef _KVM_PPC_BOOK3S_XIVE_H +#define _KVM_PPC_BOOK3S_XIVE_H + +#ifdef CONFIG_KVM_XICS +#include "book3s_xics.h" + +/* + * State for one guest irq source. + * + * For each guest source we allocate a HW interrupt in the XIVE + * which we use for all SW triggers. It will be unused for + * pass-through but it's easier to keep around as the same + * guest interrupt can alternatively be emulated or pass-through + * if a physical device is hot unplugged and replaced with an + * emulated one. + * + * This state structure is very similar to the XICS one with + * additional XIVE specific tracking. + */ +struct kvmppc_xive_irq_state { + bool valid; /* Interrupt entry is valid */ + + u32 number; /* Guest IRQ number */ + u32 ipi_number; /* XIVE IPI HW number */ + struct xive_irq_data ipi_data; /* XIVE IPI associated data */ + u32 pt_number; /* XIVE Pass-through number if any */ + struct xive_irq_data *pt_data; /* XIVE Pass-through associated data */ + + /* Targetting as set by guest */ + u32 guest_server; /* Current guest selected target */ + u8 guest_priority; /* Guest set priority */ + u8 saved_priority; /* Saved priority when masking */ + + /* Actual targetting */ + u32 act_server; /* Actual server */ + u8 act_priority; /* Actual priority */ + + /* Various state bits */ + bool in_eoi; /* Synchronize with H_EOI */ + bool old_p; /* P bit state when masking */ + bool old_q; /* Q bit state when masking */ + bool lsi; /* level-sensitive interrupt */ + bool asserted; /* Only for emulated LSI: current state */ + + /* Saved for migration state */ + bool in_queue; + bool saved_p; + bool saved_q; + u8 saved_scan_prio; +}; + +/* Select the "right" interrupt (IPI vs. passthrough) */ +static inline void kvmppc_xive_select_irq(struct kvmppc_xive_irq_state *state, + u32 *out_hw_irq, + struct xive_irq_data **out_xd) +{ + if (state->pt_number) { + if (out_hw_irq) + *out_hw_irq = state->pt_number; + if (out_xd) + *out_xd = state->pt_data; + } else { + if (out_hw_irq) + *out_hw_irq = state->ipi_number; + if (out_xd) + *out_xd = &state->ipi_data; + } +} + +/* + * This corresponds to an "ICS" in XICS terminology, we use it + * as a mean to break up source information into multiple structures. + */ +struct kvmppc_xive_src_block { + arch_spinlock_t lock; + u16 id; + struct kvmppc_xive_irq_state irq_state[KVMPPC_XICS_IRQ_PER_ICS]; +}; + + +struct kvmppc_xive { + struct kvm *kvm; + struct kvm_device *dev; + struct dentry *dentry; + + /* VP block associated with the VM */ + u32 vp_base; + + /* Blocks of sources */ + struct kvmppc_xive_src_block *src_blocks[KVMPPC_XICS_MAX_ICS_ID + 1]; + u32 max_sbid; + + /* + * For state save, we lazily scan the queues on the first interrupt + * being migrated. We don't have a clean way to reset that flags + * so we keep track of the number of valid sources and how many of + * them were migrated so we can reset when all of them have been + * processed. + */ + u32 src_count; + u32 saved_src_count; + + /* + * Some irqs are delayed on restore until the source is created, + * keep track here of how many of them + */ + u32 delayed_irqs; + + /* Which queues (priorities) are in use by the guest */ + u8 qmap; + + /* Queue orders */ + u32 q_order; + u32 q_page_order; + +}; + +#define KVMPPC_XIVE_Q_COUNT 8 + +struct kvmppc_xive_vcpu { + struct kvmppc_xive *xive; + struct kvm_vcpu *vcpu; + bool valid; + + /* Server number. This is the HW CPU ID from a guest perspective */ + u32 server_num; + + /* + * HW VP corresponding to this VCPU. This is the base of the VP + * block plus the server number. + */ + u32 vp_id; + u32 vp_chip_id; + u32 vp_cam; + + /* IPI used for sending ... IPIs */ + u32 vp_ipi; + struct xive_irq_data vp_ipi_data; + + /* Local emulation state */ + uint8_t cppr; /* guest CPPR */ + uint8_t hw_cppr;/* Hardware CPPR */ + uint8_t mfrr; + uint8_t pending; + + /* Each VP has 8 queues though we only provision some */ + struct xive_q queues[KVMPPC_XIVE_Q_COUNT]; + u32 esc_virq[KVMPPC_XIVE_Q_COUNT]; + char *esc_virq_names[KVMPPC_XIVE_Q_COUNT]; + + /* Stash a delayed irq on restore from migration (see set_icp) */ + u32 delayed_irq; + + /* Stats */ + u64 stat_rm_h_xirr; + u64 stat_rm_h_ipoll; + u64 stat_rm_h_cppr; + u64 stat_rm_h_eoi; + u64 stat_rm_h_ipi; + u64 stat_vm_h_xirr; + u64 stat_vm_h_ipoll; + u64 stat_vm_h_cppr; + u64 stat_vm_h_eoi; + u64 stat_vm_h_ipi; +}; + +static inline struct kvm_vcpu *kvmppc_xive_find_server(struct kvm *kvm, u32 nr) +{ + struct kvm_vcpu *vcpu = NULL; + int i; + + kvm_for_each_vcpu(i, vcpu, kvm) { + if (vcpu->arch.xive_vcpu && nr == vcpu->arch.xive_vcpu->server_num) + return vcpu; + } + return NULL; +} + +static inline struct kvmppc_xive_src_block *kvmppc_xive_find_source(struct kvmppc_xive *xive, + u32 irq, u16 *source) +{ + u32 bid = irq >> KVMPPC_XICS_ICS_SHIFT; + u16 src = irq & KVMPPC_XICS_SRC_MASK; + + if (source) + *source = src; + if (bid > KVMPPC_XICS_MAX_ICS_ID) + return NULL; + return xive->src_blocks[bid]; +} + +/* + * Mapping between guest priorities and host priorities + * is as follow. + * + * Guest request for 0...6 are honored. Guest request for anything + * higher results in a priority of 7 being applied. + * + * However, when XIRR is returned via H_XIRR, 7 is translated to 0xb + * in order to match AIX expectations + * + * Similar mapping is done for CPPR values + */ +static inline u8 xive_prio_from_guest(u8 prio) +{ + if (prio == 0xff || prio < 8) + return prio; + return 7; +} + +static inline u8 xive_prio_to_guest(u8 prio) +{ + if (prio == 0xff || prio < 7) + return prio; + return 0xb; +} + +static inline u32 __xive_read_eq(__be32 *qpage, u32 msk, u32 *idx, u32 *toggle) +{ + u32 cur; + + if (!qpage) + return 0; + cur = be32_to_cpup(qpage + *idx); + if ((cur >> 31) == *toggle) + return 0; + *idx = (*idx + 1) & msk; + if (*idx == 0) + (*toggle) ^= 1; + return cur & 0x7fffffff; +} + +extern unsigned long xive_rm_h_xirr(struct kvm_vcpu *vcpu); +extern unsigned long xive_rm_h_ipoll(struct kvm_vcpu *vcpu, unsigned long server); +extern int xive_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server, + unsigned long mfrr); +extern int xive_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr); +extern int xive_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr); + +extern unsigned long (*__xive_vm_h_xirr)(struct kvm_vcpu *vcpu); +extern unsigned long (*__xive_vm_h_ipoll)(struct kvm_vcpu *vcpu, unsigned long server); +extern int (*__xive_vm_h_ipi)(struct kvm_vcpu *vcpu, unsigned long server, + unsigned long mfrr); +extern int (*__xive_vm_h_cppr)(struct kvm_vcpu *vcpu, unsigned long cppr); +extern int (*__xive_vm_h_eoi)(struct kvm_vcpu *vcpu, unsigned long xirr); + +#endif /* CONFIG_KVM_XICS */ +#endif /* _KVM_PPC_BOOK3S_XICS_H */ diff --git a/arch/powerpc/kvm/book3s_xive_template.c b/arch/powerpc/kvm/book3s_xive_template.c new file mode 100644 index 000000000000..023a31133c37 --- /dev/null +++ b/arch/powerpc/kvm/book3s_xive_template.c @@ -0,0 +1,503 @@ +/* + * Copyright 2017 Benjamin Herrenschmidt, IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + */ + +/* File to be included by other .c files */ + +#define XGLUE(a,b) a##b +#define GLUE(a,b) XGLUE(a,b) + +static void GLUE(X_PFX,ack_pending)(struct kvmppc_xive_vcpu *xc) +{ + u8 cppr; + u16 ack; + + /* XXX DD1 bug workaround: Check PIPR vs. CPPR first ! */ + + /* Perform the acknowledge OS to register cycle. */ + ack = be16_to_cpu(__x_readw(__x_tima + TM_SPC_ACK_OS_REG)); + + /* Synchronize subsequent queue accesses */ + mb(); + + /* XXX Check grouping level */ + + /* Anything ? */ + if (!((ack >> 8) & TM_QW1_NSR_EO)) + return; + + /* Grab CPPR of the most favored pending interrupt */ + cppr = ack & 0xff; + if (cppr < 8) + xc->pending |= 1 << cppr; + +#ifdef XIVE_RUNTIME_CHECKS + /* Check consistency */ + if (cppr >= xc->hw_cppr) + pr_warn("KVM-XIVE: CPU %d odd ack CPPR, got %d at %d\n", + smp_processor_id(), cppr, xc->hw_cppr); +#endif + + /* + * Update our image of the HW CPPR. We don't yet modify + * xc->cppr, this will be done as we scan for interrupts + * in the queues. + */ + xc->hw_cppr = cppr; +} + +static u8 GLUE(X_PFX,esb_load)(struct xive_irq_data *xd, u32 offset) +{ + u64 val; + + if (xd->flags & XIVE_IRQ_FLAG_SHIFT_BUG) + offset |= offset << 4; + + val =__x_readq(__x_eoi_page(xd) + offset); +#ifdef __LITTLE_ENDIAN__ + val >>= 64-8; +#endif + return (u8)val; +} + + +static void GLUE(X_PFX,source_eoi)(u32 hw_irq, struct xive_irq_data *xd) +{ + /* If the XIVE supports the new "store EOI facility, use it */ + if (xd->flags & XIVE_IRQ_FLAG_STORE_EOI) + __x_writeq(0, __x_eoi_page(xd)); + else if (hw_irq && xd->flags & XIVE_IRQ_FLAG_EOI_FW) { + opal_int_eoi(hw_irq); + } else { + uint64_t eoi_val; + + /* + * Otherwise for EOI, we use the special MMIO that does + * a clear of both P and Q and returns the old Q, + * except for LSIs where we use the "EOI cycle" special + * load. + * + * This allows us to then do a re-trigger if Q was set + * rather than synthetizing an interrupt in software + * + * For LSIs, using the HW EOI cycle works around a problem + * on P9 DD1 PHBs where the other ESB accesses don't work + * properly. + */ + if (xd->flags & XIVE_IRQ_FLAG_LSI) + __x_readq(__x_eoi_page(xd)); + else { + eoi_val = GLUE(X_PFX,esb_load)(xd, XIVE_ESB_SET_PQ_00); + + /* Re-trigger if needed */ + if ((eoi_val & 1) && __x_trig_page(xd)) + __x_writeq(0, __x_trig_page(xd)); + } + } +} + +enum { + scan_fetch, + scan_poll, + scan_eoi, +}; + +static u32 GLUE(X_PFX,scan_interrupts)(struct kvmppc_xive_vcpu *xc, + u8 pending, int scan_type) +{ + u32 hirq = 0; + u8 prio = 0xff; + + /* Find highest pending priority */ + while ((xc->mfrr != 0xff || pending != 0) && hirq == 0) { + struct xive_q *q; + u32 idx, toggle; + __be32 *qpage; + + /* + * If pending is 0 this will return 0xff which is what + * we want + */ + prio = ffs(pending) - 1; + + /* + * If the most favoured prio we found pending is less + * favored (or equal) than a pending IPI, we return + * the IPI instead. + * + * Note: If pending was 0 and mfrr is 0xff, we will + * not spurriously take an IPI because mfrr cannot + * then be smaller than cppr. + */ + if (prio >= xc->mfrr && xc->mfrr < xc->cppr) { + prio = xc->mfrr; + hirq = XICS_IPI; + break; + } + + /* Don't scan past the guest cppr */ + if (prio >= xc->cppr || prio > 7) + break; + + /* Grab queue and pointers */ + q = &xc->queues[prio]; + idx = q->idx; + toggle = q->toggle; + + /* + * Snapshot the queue page. The test further down for EOI + * must use the same "copy" that was used by __xive_read_eq + * since qpage can be set concurrently and we don't want + * to miss an EOI. + */ + qpage = READ_ONCE(q->qpage); + +skip_ipi: + /* + * Try to fetch from the queue. Will return 0 for a + * non-queueing priority (ie, qpage = 0). + */ + hirq = __xive_read_eq(qpage, q->msk, &idx, &toggle); + + /* + * If this was a signal for an MFFR change done by + * H_IPI we skip it. Additionally, if we were fetching + * we EOI it now, thus re-enabling reception of a new + * such signal. + * + * We also need to do that if prio is 0 and we had no + * page for the queue. In this case, we have non-queued + * IPI that needs to be EOId. + * + * This is safe because if we have another pending MFRR + * change that wasn't observed above, the Q bit will have + * been set and another occurrence of the IPI will trigger. + */ + if (hirq == XICS_IPI || (prio == 0 && !qpage)) { + if (scan_type == scan_fetch) + GLUE(X_PFX,source_eoi)(xc->vp_ipi, + &xc->vp_ipi_data); + /* Loop back on same queue with updated idx/toggle */ +#ifdef XIVE_RUNTIME_CHECKS + WARN_ON(hirq && hirq != XICS_IPI); +#endif + if (hirq) + goto skip_ipi; + } + + /* If fetching, update queue pointers */ + if (scan_type == scan_fetch) { + q->idx = idx; + q->toggle = toggle; + } + + /* Something found, stop searching */ + if (hirq) + break; + + /* Clear the pending bit on the now empty queue */ + pending &= ~(1 << prio); + + /* + * Check if the queue count needs adjusting due to + * interrupts being moved away. + */ + if (atomic_read(&q->pending_count)) { + int p = atomic_xchg(&q->pending_count, 0); + if (p) { +#ifdef XIVE_RUNTIME_CHECKS + WARN_ON(p > atomic_read(&q->count)); +#endif + atomic_sub(p, &q->count); + } + } + } + + /* If we are just taking a "peek", do nothing else */ + if (scan_type == scan_poll) + return hirq; + + /* Update the pending bits */ + xc->pending = pending; + + /* + * If this is an EOI that's it, no CPPR adjustment done here, + * all we needed was cleanup the stale pending bits and check + * if there's anything left. + */ + if (scan_type == scan_eoi) + return hirq; + + /* + * If we found an interrupt, adjust what the guest CPPR should + * be as if we had just fetched that interrupt from HW. + */ + if (hirq) + xc->cppr = prio; + /* + * If it was an IPI the HW CPPR might have been lowered too much + * as the HW interrupt we use for IPIs is routed to priority 0. + * + * We re-sync it here. + */ + if (xc->cppr != xc->hw_cppr) { + xc->hw_cppr = xc->cppr; + __x_writeb(xc->cppr, __x_tima + TM_QW1_OS + TM_CPPR); + } + + return hirq; +} + +X_STATIC unsigned long GLUE(X_PFX,h_xirr)(struct kvm_vcpu *vcpu) +{ + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + u8 old_cppr; + u32 hirq; + + pr_devel("H_XIRR\n"); + + xc->GLUE(X_STAT_PFX,h_xirr)++; + + /* First collect pending bits from HW */ + GLUE(X_PFX,ack_pending)(xc); + + /* + * Cleanup the old-style bits if needed (they may have been + * set by pull or an escalation interrupts). + */ + if (test_bit(BOOK3S_IRQPRIO_EXTERNAL, &vcpu->arch.pending_exceptions)) + clear_bit(BOOK3S_IRQPRIO_EXTERNAL_LEVEL, + &vcpu->arch.pending_exceptions); + + pr_devel(" new pending=0x%02x hw_cppr=%d cppr=%d\n", + xc->pending, xc->hw_cppr, xc->cppr); + + /* Grab previous CPPR and reverse map it */ + old_cppr = xive_prio_to_guest(xc->cppr); + + /* Scan for actual interrupts */ + hirq = GLUE(X_PFX,scan_interrupts)(xc, xc->pending, scan_fetch); + + pr_devel(" got hirq=0x%x hw_cppr=%d cppr=%d\n", + hirq, xc->hw_cppr, xc->cppr); + +#ifdef XIVE_RUNTIME_CHECKS + /* That should never hit */ + if (hirq & 0xff000000) + pr_warn("XIVE: Weird guest interrupt number 0x%08x\n", hirq); +#endif + + /* + * XXX We could check if the interrupt is masked here and + * filter it. If we chose to do so, we would need to do: + * + * if (masked) { + * lock(); + * if (masked) { + * old_Q = true; + * hirq = 0; + * } + * unlock(); + * } + */ + + /* Return interrupt and old CPPR in GPR4 */ + vcpu->arch.gpr[4] = hirq | (old_cppr << 24); + + return H_SUCCESS; +} + +X_STATIC unsigned long GLUE(X_PFX,h_ipoll)(struct kvm_vcpu *vcpu, unsigned long server) +{ + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + u8 pending = xc->pending; + u32 hirq; + u8 pipr; + + pr_devel("H_IPOLL(server=%ld)\n", server); + + xc->GLUE(X_STAT_PFX,h_ipoll)++; + + /* Grab the target VCPU if not the current one */ + if (xc->server_num != server) { + vcpu = kvmppc_xive_find_server(vcpu->kvm, server); + if (!vcpu) + return H_PARAMETER; + xc = vcpu->arch.xive_vcpu; + + /* Scan all priorities */ + pending = 0xff; + } else { + /* Grab pending interrupt if any */ + pipr = __x_readb(__x_tima + TM_QW1_OS + TM_PIPR); + if (pipr < 8) + pending |= 1 << pipr; + } + + hirq = GLUE(X_PFX,scan_interrupts)(xc, pending, scan_poll); + + /* Return interrupt and old CPPR in GPR4 */ + vcpu->arch.gpr[4] = hirq | (xc->cppr << 24); + + return H_SUCCESS; +} + +static void GLUE(X_PFX,push_pending_to_hw)(struct kvmppc_xive_vcpu *xc) +{ + u8 pending, prio; + + pending = xc->pending; + if (xc->mfrr != 0xff) { + if (xc->mfrr < 8) + pending |= 1 << xc->mfrr; + else + pending |= 0x80; + } + if (!pending) + return; + prio = ffs(pending) - 1; + + __x_writeb(prio, __x_tima + TM_SPC_SET_OS_PENDING); +} + +X_STATIC int GLUE(X_PFX,h_cppr)(struct kvm_vcpu *vcpu, unsigned long cppr) +{ + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + u8 old_cppr; + + pr_devel("H_CPPR(cppr=%ld)\n", cppr); + + xc->GLUE(X_STAT_PFX,h_cppr)++; + + /* Map CPPR */ + cppr = xive_prio_from_guest(cppr); + + /* Remember old and update SW state */ + old_cppr = xc->cppr; + xc->cppr = cppr; + + /* + * We are masking less, we need to look for pending things + * to deliver and set VP pending bits accordingly to trigger + * a new interrupt otherwise we might miss MFRR changes for + * which we have optimized out sending an IPI signal. + */ + if (cppr > old_cppr) + GLUE(X_PFX,push_pending_to_hw)(xc); + + /* Apply new CPPR */ + xc->hw_cppr = cppr; + __x_writeb(cppr, __x_tima + TM_QW1_OS + TM_CPPR); + + return H_SUCCESS; +} + +X_STATIC int GLUE(X_PFX,h_eoi)(struct kvm_vcpu *vcpu, unsigned long xirr) +{ + struct kvmppc_xive *xive = vcpu->kvm->arch.xive; + struct kvmppc_xive_src_block *sb; + struct kvmppc_xive_irq_state *state; + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + struct xive_irq_data *xd; + u8 new_cppr = xirr >> 24; + u32 irq = xirr & 0x00ffffff, hw_num; + u16 src; + int rc = 0; + + pr_devel("H_EOI(xirr=%08lx)\n", xirr); + + xc->GLUE(X_STAT_PFX,h_eoi)++; + + xc->cppr = xive_prio_from_guest(new_cppr); + + /* + * IPIs are synthetized from MFRR and thus don't need + * any special EOI handling. The underlying interrupt + * used to signal MFRR changes is EOId when fetched from + * the queue. + */ + if (irq == XICS_IPI || irq == 0) + goto bail; + + /* Find interrupt source */ + sb = kvmppc_xive_find_source(xive, irq, &src); + if (!sb) { + pr_devel(" source not found !\n"); + rc = H_PARAMETER; + goto bail; + } + state = &sb->irq_state[src]; + kvmppc_xive_select_irq(state, &hw_num, &xd); + + state->in_eoi = true; + mb(); + +again: + if (state->guest_priority == MASKED) { + arch_spin_lock(&sb->lock); + if (state->guest_priority != MASKED) { + arch_spin_unlock(&sb->lock); + goto again; + } + pr_devel(" EOI on saved P...\n"); + + /* Clear old_p, that will cause unmask to perform an EOI */ + state->old_p = false; + + arch_spin_unlock(&sb->lock); + } else { + pr_devel(" EOI on source...\n"); + + /* Perform EOI on the source */ + GLUE(X_PFX,source_eoi)(hw_num, xd); + + /* If it's an emulated LSI, check level and resend */ + if (state->lsi && state->asserted) + __x_writeq(0, __x_trig_page(xd)); + + } + + mb(); + state->in_eoi = false; +bail: + + /* Re-evaluate pending IRQs and update HW */ + GLUE(X_PFX,scan_interrupts)(xc, xc->pending, scan_eoi); + GLUE(X_PFX,push_pending_to_hw)(xc); + pr_devel(" after scan pending=%02x\n", xc->pending); + + /* Apply new CPPR */ + xc->hw_cppr = xc->cppr; + __x_writeb(xc->cppr, __x_tima + TM_QW1_OS + TM_CPPR); + + return rc; +} + +X_STATIC int GLUE(X_PFX,h_ipi)(struct kvm_vcpu *vcpu, unsigned long server, + unsigned long mfrr) +{ + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + + pr_devel("H_IPI(server=%08lx,mfrr=%ld)\n", server, mfrr); + + xc->GLUE(X_STAT_PFX,h_ipi)++; + + /* Find target */ + vcpu = kvmppc_xive_find_server(vcpu->kvm, server); + if (!vcpu) + return H_PARAMETER; + xc = vcpu->arch.xive_vcpu; + + /* Locklessly write over MFRR */ + xc->mfrr = mfrr; + + /* Shoot the IPI if most favored than target cppr */ + if (mfrr < xc->cppr) + __x_writeq(0, __x_trig_page(&xc->vp_ipi_data)); + + return H_SUCCESS; +} diff --git a/arch/powerpc/kvm/irq.h b/arch/powerpc/kvm/irq.h index 5a9a10b90762..3f1be85a83bc 100644 --- a/arch/powerpc/kvm/irq.h +++ b/arch/powerpc/kvm/irq.h @@ -12,6 +12,7 @@ static inline int irqchip_in_kernel(struct kvm *kvm) #endif #ifdef CONFIG_KVM_XICS ret = ret || (kvm->arch.xics != NULL); + ret = ret || (kvm->arch.xive != NULL); #endif smp_rmb(); return ret; diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 95c91a9de351..de79bd721ec7 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -37,6 +37,8 @@ #include #include #include +#include + #include "timing.h" #include "irq.h" #include "../mm/mmu_decl.h" @@ -699,7 +701,10 @@ void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu) kvmppc_mpic_disconnect_vcpu(vcpu->arch.mpic, vcpu); break; case KVMPPC_IRQ_XICS: - kvmppc_xics_free_icp(vcpu); + if (xive_enabled()) + kvmppc_xive_cleanup_vcpu(vcpu); + else + kvmppc_xics_free_icp(vcpu); break; } @@ -1219,8 +1224,12 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, r = -EPERM; dev = kvm_device_from_filp(f.file); - if (dev) - r = kvmppc_xics_connect_vcpu(dev, vcpu, cap->args[1]); + if (dev) { + if (xive_enabled()) + r = kvmppc_xive_connect_vcpu(dev, vcpu, cap->args[1]); + else + r = kvmppc_xics_connect_vcpu(dev, vcpu, cap->args[1]); + } fdput(f); break; @@ -1244,7 +1253,7 @@ bool kvm_arch_intc_initialized(struct kvm *kvm) return true; #endif #ifdef CONFIG_KVM_XICS - if (kvm->arch.xics) + if (kvm->arch.xics || kvm->arch.xive) return true; #endif return false; diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index e0f856bfbfe8..d71cd773d870 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c @@ -890,3 +890,4 @@ EXPORT_SYMBOL_GPL(opal_leds_set_ind); EXPORT_SYMBOL_GPL(opal_write_oppanel_async); /* Export this for KVM */ EXPORT_SYMBOL_GPL(opal_int_set_mfrr); +EXPORT_SYMBOL_GPL(opal_int_eoi); diff --git a/arch/powerpc/sysdev/xive/common.c b/arch/powerpc/sysdev/xive/common.c index d9cd7f705f21..496036c93531 100644 --- a/arch/powerpc/sysdev/xive/common.c +++ b/arch/powerpc/sysdev/xive/common.c @@ -46,13 +46,15 @@ #endif bool __xive_enabled; +EXPORT_SYMBOL_GPL(__xive_enabled); bool xive_cmdline_disabled; /* We use only one priority for now */ static u8 xive_irq_priority; -/* TIMA */ +/* TIMA exported to KVM */ void __iomem *xive_tima; +EXPORT_SYMBOL_GPL(xive_tima); u32 xive_tima_offset; /* Backend ops */ @@ -345,8 +347,11 @@ static void xive_irq_eoi(struct irq_data *d) DBG_VERBOSE("eoi_irq: irq=%d [0x%lx] pending=%02x\n", d->irq, irqd_to_hwirq(d), xc->pending_prio); - /* EOI the source if it hasn't been disabled */ - if (!irqd_irq_disabled(d)) + /* + * EOI the source if it hasn't been disabled and hasn't + * been passed-through to a KVM guest + */ + if (!irqd_irq_disabled(d) && !irqd_is_forwarded_to_vcpu(d)) xive_do_source_eoi(irqd_to_hwirq(d), xd); /* @@ -689,9 +694,14 @@ static int xive_irq_set_affinity(struct irq_data *d, old_target = xd->target; - rc = xive_ops->configure_irq(hw_irq, - get_hard_smp_processor_id(target), - xive_irq_priority, d->irq); + /* + * Only configure the irq if it's not currently passed-through to + * a KVM guest + */ + if (!irqd_is_forwarded_to_vcpu(d)) + rc = xive_ops->configure_irq(hw_irq, + get_hard_smp_processor_id(target), + xive_irq_priority, d->irq); if (rc < 0) { pr_err("Error %d reconfiguring irq %d\n", rc, d->irq); return rc; @@ -771,6 +781,123 @@ static int xive_irq_retrigger(struct irq_data *d) return 1; } +static int xive_irq_set_vcpu_affinity(struct irq_data *d, void *state) +{ + struct xive_irq_data *xd = irq_data_get_irq_handler_data(d); + unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d); + int rc; + u8 pq; + + /* + * We only support this on interrupts that do not require + * firmware calls for masking and unmasking + */ + if (xd->flags & XIVE_IRQ_FLAG_MASK_FW) + return -EIO; + + /* + * This is called by KVM with state non-NULL for enabling + * pass-through or NULL for disabling it + */ + if (state) { + irqd_set_forwarded_to_vcpu(d); + + /* Set it to PQ=10 state to prevent further sends */ + pq = xive_poke_esb(xd, XIVE_ESB_SET_PQ_10); + + /* No target ? nothing to do */ + if (xd->target == XIVE_INVALID_TARGET) { + /* + * An untargetted interrupt should have been + * also masked at the source + */ + WARN_ON(pq & 2); + + return 0; + } + + /* + * If P was set, adjust state to PQ=11 to indicate + * that a resend is needed for the interrupt to reach + * the guest. Also remember the value of P. + * + * This also tells us that it's in flight to a host queue + * or has already been fetched but hasn't been EOIed yet + * by the host. This it's potentially using up a host + * queue slot. This is important to know because as long + * as this is the case, we must not hard-unmask it when + * "returning" that interrupt to the host. + * + * This saved_p is cleared by the host EOI, when we know + * for sure the queue slot is no longer in use. + */ + if (pq & 2) { + pq = xive_poke_esb(xd, XIVE_ESB_SET_PQ_11); + xd->saved_p = true; + + /* + * Sync the XIVE source HW to ensure the interrupt + * has gone through the EAS before we change its + * target to the guest. That should guarantee us + * that we *will* eventually get an EOI for it on + * the host. Otherwise there would be a small window + * for P to be seen here but the interrupt going + * to the guest queue. + */ + if (xive_ops->sync_source) + xive_ops->sync_source(hw_irq); + } else + xd->saved_p = false; + } else { + irqd_clr_forwarded_to_vcpu(d); + + /* No host target ? hard mask and return */ + if (xd->target == XIVE_INVALID_TARGET) { + xive_do_source_set_mask(xd, true); + return 0; + } + + /* + * Sync the XIVE source HW to ensure the interrupt + * has gone through the EAS before we change its + * target to the host. + */ + if (xive_ops->sync_source) + xive_ops->sync_source(hw_irq); + + /* + * By convention we are called with the interrupt in + * a PQ=10 or PQ=11 state, ie, it won't fire and will + * have latched in Q whether there's a pending HW + * interrupt or not. + * + * First reconfigure the target. + */ + rc = xive_ops->configure_irq(hw_irq, + get_hard_smp_processor_id(xd->target), + xive_irq_priority, d->irq); + if (rc) + return rc; + + /* + * Then if saved_p is not set, effectively re-enable the + * interrupt with an EOI. If it is set, we know there is + * still a message in a host queue somewhere that will be + * EOId eventually. + * + * Note: We don't check irqd_irq_disabled(). Effectively, + * we *will* let the irq get through even if masked if the + * HW is still firing it in order to deal with the whole + * saved_p business properly. If the interrupt triggers + * while masked, the generic code will re-mask it anyway. + */ + if (!xd->saved_p) + xive_do_source_eoi(hw_irq, xd); + + } + return 0; +} + static struct irq_chip xive_irq_chip = { .name = "XIVE-IRQ", .irq_startup = xive_irq_startup, @@ -781,12 +908,14 @@ static struct irq_chip xive_irq_chip = { .irq_set_affinity = xive_irq_set_affinity, .irq_set_type = xive_irq_set_type, .irq_retrigger = xive_irq_retrigger, + .irq_set_vcpu_affinity = xive_irq_set_vcpu_affinity, }; bool is_xive_irq(struct irq_chip *chip) { return chip == &xive_irq_chip; } +EXPORT_SYMBOL_GPL(is_xive_irq); void xive_cleanup_irq_data(struct xive_irq_data *xd) { @@ -801,6 +930,7 @@ void xive_cleanup_irq_data(struct xive_irq_data *xd) xd->trig_mmio = NULL; } } +EXPORT_SYMBOL_GPL(xive_cleanup_irq_data); static int xive_irq_alloc_data(unsigned int virq, irq_hw_number_t hw) { diff --git a/arch/powerpc/sysdev/xive/native.c b/arch/powerpc/sysdev/xive/native.c index 5fae59186cb2..6feac0a758e1 100644 --- a/arch/powerpc/sysdev/xive/native.c +++ b/arch/powerpc/sysdev/xive/native.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "xive-internal.h" @@ -95,6 +96,7 @@ int xive_native_populate_irq_data(u32 hw_irq, struct xive_irq_data *data) } return 0; } +EXPORT_SYMBOL_GPL(xive_native_populate_irq_data); int xive_native_configure_irq(u32 hw_irq, u32 target, u8 prio, u32 sw_irq) { @@ -108,6 +110,8 @@ int xive_native_configure_irq(u32 hw_irq, u32 target, u8 prio, u32 sw_irq) } return rc == 0 ? 0 : -ENXIO; } +EXPORT_SYMBOL_GPL(xive_native_configure_irq); + /* This can be called multiple time to change a queue configuration */ int xive_native_configure_queue(u32 vp_id, struct xive_q *q, u8 prio, @@ -172,6 +176,7 @@ int xive_native_configure_queue(u32 vp_id, struct xive_q *q, u8 prio, fail: return rc; } +EXPORT_SYMBOL_GPL(xive_native_configure_queue); static void __xive_native_disable_queue(u32 vp_id, struct xive_q *q, u8 prio) { @@ -191,6 +196,7 @@ void xive_native_disable_queue(u32 vp_id, struct xive_q *q, u8 prio) { __xive_native_disable_queue(vp_id, q, prio); } +EXPORT_SYMBOL_GPL(xive_native_disable_queue); static int xive_native_setup_queue(unsigned int cpu, struct xive_cpu *xc, u8 prio) { @@ -261,6 +267,7 @@ static int xive_native_get_ipi(unsigned int cpu, struct xive_cpu *xc) } return 0; } +#endif /* CONFIG_SMP */ u32 xive_native_alloc_irq(void) { @@ -276,6 +283,7 @@ u32 xive_native_alloc_irq(void) return 0; return rc; } +EXPORT_SYMBOL_GPL(xive_native_alloc_irq); void xive_native_free_irq(u32 irq) { @@ -286,7 +294,9 @@ void xive_native_free_irq(u32 irq) msleep(1); } } +EXPORT_SYMBOL_GPL(xive_native_free_irq); +#ifdef CONFIG_SMP static void xive_native_put_ipi(unsigned int cpu, struct xive_cpu *xc) { s64 rc; @@ -382,7 +392,7 @@ static void xive_native_setup_cpu(unsigned int cpu, struct xive_cpu *xc) return; /* Enable the pool VP */ - vp = xive_pool_vps + get_hard_smp_processor_id(cpu); + vp = xive_pool_vps + cpu; pr_debug("CPU %d setting up pool VP 0x%x\n", cpu, vp); for (;;) { rc = opal_xive_set_vp_info(vp, OPAL_XIVE_VP_ENABLED, 0); @@ -427,7 +437,7 @@ static void xive_native_teardown_cpu(unsigned int cpu, struct xive_cpu *xc) in_be64(xive_tima + TM_SPC_PULL_POOL_CTX); /* Disable it */ - vp = xive_pool_vps + get_hard_smp_processor_id(cpu); + vp = xive_pool_vps + cpu; for (;;) { rc = opal_xive_set_vp_info(vp, 0, 0); if (rc != OPAL_BUSY) @@ -436,10 +446,11 @@ static void xive_native_teardown_cpu(unsigned int cpu, struct xive_cpu *xc) } } -static void xive_native_sync_source(u32 hw_irq) +void xive_native_sync_source(u32 hw_irq) { opal_xive_sync(XIVE_SYNC_EAS, hw_irq); } +EXPORT_SYMBOL_GPL(xive_native_sync_source); static const struct xive_ops xive_native_ops = { .populate_irq_data = xive_native_populate_irq_data, @@ -500,10 +511,24 @@ static bool xive_parse_provisioning(struct device_node *np) return true; } +static void xive_native_setup_pools(void) +{ + /* Allocate a pool big enough */ + pr_debug("XIVE: Allocating VP block for pool size %d\n", nr_cpu_ids); + + xive_pool_vps = xive_native_alloc_vp_block(nr_cpu_ids); + if (WARN_ON(xive_pool_vps == XIVE_INVALID_VP)) + pr_err("XIVE: Failed to allocate pool VP, KVM might not function\n"); + + pr_debug("XIVE: Pool VPs allocated at 0x%x for %d max CPUs\n", + xive_pool_vps, nr_cpu_ids); +} + u32 xive_native_default_eq_shift(void) { return xive_queue_shift; } +EXPORT_SYMBOL_GPL(xive_native_default_eq_shift); bool xive_native_init(void) { @@ -513,7 +538,7 @@ bool xive_native_init(void) struct property *prop; u8 max_prio = 7; const __be32 *p; - u32 val; + u32 val, cpu; s64 rc; if (xive_cmdline_disabled) @@ -549,7 +574,11 @@ bool xive_native_init(void) break; } - /* Grab size of provisioning pages */ + /* Configure Thread Management areas for KVM */ + for_each_possible_cpu(cpu) + kvmppc_set_xive_tima(cpu, r.start, tima); + + /* Grab size of provisionning pages */ xive_parse_provisioning(np); /* Switch the XIVE to exploitation mode */ @@ -559,6 +588,9 @@ bool xive_native_init(void) return false; } + /* Setup some dummy HV pool VPs */ + xive_native_setup_pools(); + /* Initialize XIVE core with our backend */ if (!xive_core_init(&xive_native_ops, tima, TM_QW3_HV_PHYS, max_prio)) { @@ -637,3 +669,47 @@ void xive_native_free_vp_block(u32 vp_base) pr_warn("OPAL error %lld freeing VP block\n", rc); } EXPORT_SYMBOL_GPL(xive_native_free_vp_block); + +int xive_native_enable_vp(u32 vp_id) +{ + s64 rc; + + for (;;) { + rc = opal_xive_set_vp_info(vp_id, OPAL_XIVE_VP_ENABLED, 0); + if (rc != OPAL_BUSY) + break; + msleep(1); + } + return rc ? -EIO : 0; +} +EXPORT_SYMBOL_GPL(xive_native_enable_vp); + +int xive_native_disable_vp(u32 vp_id) +{ + s64 rc; + + for (;;) { + rc = opal_xive_set_vp_info(vp_id, 0, 0); + if (rc != OPAL_BUSY) + break; + msleep(1); + } + return rc ? -EIO : 0; +} +EXPORT_SYMBOL_GPL(xive_native_disable_vp); + +int xive_native_get_vp_info(u32 vp_id, u32 *out_cam_id, u32 *out_chip_id) +{ + __be64 vp_cam_be; + __be32 vp_chip_id_be; + s64 rc; + + rc = opal_xive_get_vp_info(vp_id, NULL, &vp_cam_be, NULL, &vp_chip_id_be); + if (rc) + return -EIO; + *out_cam_id = be64_to_cpu(vp_cam_be) & 0xffffffffu; + *out_chip_id = be32_to_cpu(vp_chip_id_be); + + return 0; +} +EXPORT_SYMBOL_GPL(xive_native_get_vp_info); diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 2c14ad9809da..d1a6e554ee68 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -1165,7 +1165,6 @@ int kvm_register_device_ops(struct kvm_device_ops *ops, u32 type); void kvm_unregister_device_ops(u32 type); extern struct kvm_device_ops kvm_mpic_ops; -extern struct kvm_device_ops kvm_xics_ops; extern struct kvm_device_ops kvm_arm_vgic_v2_ops; extern struct kvm_device_ops kvm_arm_vgic_v3_ops; diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index a17d78759727..1b0da5771f71 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -2839,10 +2839,6 @@ static struct kvm_device_ops *kvm_device_ops_table[KVM_DEV_TYPE_MAX] = { [KVM_DEV_TYPE_FSL_MPIC_20] = &kvm_mpic_ops, [KVM_DEV_TYPE_FSL_MPIC_42] = &kvm_mpic_ops, #endif - -#ifdef CONFIG_KVM_XICS - [KVM_DEV_TYPE_XICS] = &kvm_xics_ops, -#endif }; int kvm_register_device_ops(struct kvm_device_ops *ops, u32 type) -- cgit v1.2.3-59-g8ed1b From c8581984ffd917736ab3630c0f07bb5b218411e3 Mon Sep 17 00:00:00 2001 From: Jose Abreu Date: Wed, 22 Feb 2017 18:19:34 +0000 Subject: arc: axs10x: Add DT bindings for I2S audio playback This patch adds the necessary DT bindings to get HDMI audio output in ARC AXS10x SDP. The bindings for I2S controller were added as well as the bindings for simple audio card. Signed-off-by: Jose Abreu Cc: Carlos Palminha Cc: Alexey Brodkin Cc: Rob Herring Cc: Vineet Gupta Cc: devicetree@vger.kernel.org Cc: linux-snps-arc@lists.infradead.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Vineet Gupta --- arch/arc/boot/dts/axs10x_mb.dtsi | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi index d6c1bbc98ac3..9d882b1a3e1c 100644 --- a/arch/arc/boot/dts/axs10x_mb.dtsi +++ b/arch/arc/boot/dts/axs10x_mb.dtsi @@ -149,12 +149,13 @@ interrupts = <14>; }; - i2c@0x1e000 { - compatible = "snps,designware-i2c"; + i2s: i2s@1e000 { + compatible = "snps,designware-i2s"; reg = <0x1e000 0x100>; - clock-frequency = <400000>; - clocks = <&i2cclk>; + clocks = <&i2sclk 0>; + clock-names = "i2sclk"; interrupts = <15>; + #sound-dai-cells = <0>; }; i2c@0x1f000 { @@ -174,6 +175,7 @@ adi,input-colorspace = "rgb"; adi,input-clock = "1x"; adi,clock-delay = <0x03>; + #sound-dai-cells = <0>; ports { #address-cells = <1>; @@ -295,5 +297,17 @@ }; }; }; + + sound_playback { + compatible = "simple-audio-card"; + simple-audio-card,name = "AXS10x HDMI Audio"; + simple-audio-card,format = "i2s"; + simple-audio-card,cpu { + sound-dai = <&i2s>; + }; + simple-audio-card,codec { + sound-dai = <&adv7511>; + }; + }; }; }; -- cgit v1.2.3-59-g8ed1b From 36b5a5152119cd08760067ca31d8577de993c490 Mon Sep 17 00:00:00 2001 From: Jose Abreu Date: Wed, 22 Feb 2017 18:19:35 +0000 Subject: arc: axs10x: Fix ARC PGU default clock frequency Default clock frequency for ARC PGU does not match any existing HDMI mode, instead the default value matches a DVI mode. Change the clock frequency to 74.25MHz so that it matches HDMI mode 1280x720@60Hz Signed-off-by: Jose Abreu Cc: Carlos Palminha Cc: Alexey Brodkin Cc: Rob Herring Cc: Vineet Gupta Cc: devicetree@vger.kernel.org Cc: linux-snps-arc@lists.infradead.org Cc: linux-kernel@vger.kernel.org Acked-by: Alexey Brodkin Signed-off-by: Vineet Gupta --- arch/arc/boot/dts/axs10x_mb.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi index 9d882b1a3e1c..41cfb29b62c1 100644 --- a/arch/arc/boot/dts/axs10x_mb.dtsi +++ b/arch/arc/boot/dts/axs10x_mb.dtsi @@ -51,7 +51,7 @@ pguclk: pguclk { #clock-cells = <0>; compatible = "fixed-clock"; - clock-frequency = <74440000>; + clock-frequency = <74250000>; }; }; -- cgit v1.2.3-59-g8ed1b From db4b0dfab7b016f5514442046d86a9727ee87f12 Mon Sep 17 00:00:00 2001 From: Denis Kirjanov Date: Wed, 29 Mar 2017 06:55:37 -0400 Subject: KVM: PPC: Book3S HV: Avoid preemptibility warning in module initialization With CONFIG_DEBUG_PREEMPT, get_paca() produces the following warning in kvmppc_book3s_init_hv() since it calls debug_smp_processor_id(). There is no real issue with the xics_phys field. If paca->kvm_hstate.xics_phys is non-zero on one cpu, it will be non-zero on them all. Therefore this is not fixing any actual problem, just the warning. [ 138.521188] BUG: using smp_processor_id() in preemptible [00000000] code: modprobe/5596 [ 138.521308] caller is .kvmppc_book3s_init_hv+0x184/0x350 [kvm_hv] [ 138.521404] CPU: 5 PID: 5596 Comm: modprobe Not tainted 4.11.0-rc3-00022-gc7e790c #1 [ 138.521509] Call Trace: [ 138.521563] [c0000007d018b810] [c0000000023eef10] .dump_stack+0xe4/0x150 (unreliable) [ 138.521694] [c0000007d018b8a0] [c000000001f6ec04] .check_preemption_disabled+0x134/0x150 [ 138.521829] [c0000007d018b940] [d00000000a010274] .kvmppc_book3s_init_hv+0x184/0x350 [kvm_hv] [ 138.521963] [c0000007d018ba00] [c00000000191d5cc] .do_one_initcall+0x5c/0x1c0 [ 138.522082] [c0000007d018bad0] [c0000000023e9494] .do_init_module+0x84/0x240 [ 138.522201] [c0000007d018bb70] [c000000001aade18] .load_module+0x1f68/0x2a10 [ 138.522319] [c0000007d018bd20] [c000000001aaeb30] .SyS_finit_module+0xc0/0xf0 [ 138.522439] [c0000007d018be30] [c00000000191baec] system_call+0x38/0xfc Signed-off-by: Denis Kirjanov Signed-off-by: Paul Mackerras --- arch/powerpc/kvm/book3s_hv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 06b7d8ae27e5..d42182eb0c26 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -3928,7 +3928,7 @@ static int kvmppc_book3s_init_hv(void) * indirectly, via OPAL. */ #ifdef CONFIG_SMP - if (!get_paca()->kvm_hstate.xics_phys) { + if (!local_paca->kvm_hstate.xics_phys) { struct device_node *np; np = of_find_compatible_node(NULL, NULL, "ibm,opal-intc"); -- cgit v1.2.3-59-g8ed1b From 26b37b946a5c2658dbc37dd5d6df40aaa9685d70 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 15 May 2015 02:00:02 +0300 Subject: arm: dma-mapping: Don't override dma_ops in arch_setup_dma_ops() The arch_setup_dma_ops() function is in charge of setting dma_ops with a call to set_dma_ops(). set_dma_ops() is also called from - highbank and mvebu bus notifiers - dmabounce (to be replaced with swiotlb) - arm_iommu_attach_device (arm_iommu_attach_device is itself called from IOMMU and bus master device drivers) To allow the arch_setup_dma_ops() call to be moved from device add time to device probe time we must ensure that dma_ops already setup by any of the above callers will not be overriden. Aftering replacing dmabounce with swiotlb, converting IOMMU drivers to of_xlate and taking care of highbank and mvebu, the workaround should be removed. Signed-off-by: Sricharan R Signed-off-by: Laurent Pinchart Tested-by: Ralph Sennhauser Signed-off-by: Joerg Roedel --- arch/arm/mm/dma-mapping.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'arch') diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 63eabb06f9f1..ff131928be50 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -2390,6 +2390,15 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, const struct dma_map_ops *dma_ops; dev->archdata.dma_coherent = coherent; + + /* + * Don't override the dma_ops if they have already been set. Ideally + * this should be the only location where dma_ops are set, remove this + * check when all other callers of set_dma_ops will have disappeared. + */ + if (dev->dma_ops) + return; + if (arm_setup_iommu_dma_ops(dev, dma_base, size, iommu)) dma_ops = arm_get_iommu_dma_map_ops(coherent); else -- cgit v1.2.3-59-g8ed1b From 461a6946b1f93f6720577fb06aa78e8cbd9291c9 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 26 Apr 2017 15:46:20 +0200 Subject: iommu: Remove pci.h include from trace/events/iommu.h The include file does not need any PCI specifics, so remove that include. Also fix the places that relied on it. Signed-off-by: Joerg Roedel --- arch/arm64/mm/dma-mapping.c | 1 + drivers/infiniband/hw/qedr/main.c | 1 + drivers/iommu/fsl_pamu.h | 1 + drivers/iommu/rockchip-iommu.c | 1 + drivers/iommu/tegra-smmu.c | 1 + include/linux/dma-iommu.h | 1 + include/trace/events/iommu.h | 1 - 7 files changed, 6 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c index 81cdb2e844ed..982f85b81624 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c @@ -28,6 +28,7 @@ #include #include #include +#include #include diff --git a/drivers/infiniband/hw/qedr/main.c b/drivers/infiniband/hw/qedr/main.c index b9b47e5cc8b3..33033624cd9b 100644 --- a/drivers/infiniband/hw/qedr/main.c +++ b/drivers/infiniband/hw/qedr/main.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/iommu/fsl_pamu.h b/drivers/iommu/fsl_pamu.h index aab723f91f12..c3434f29c967 100644 --- a/drivers/iommu/fsl_pamu.h +++ b/drivers/iommu/fsl_pamu.h @@ -20,6 +20,7 @@ #define __FSL_PAMU_H #include +#include #include diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index 9afcbf79f0b0..0ba303a184dd 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 9305964250ac..eeb19f560a05 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h index 5725c94b1f12..abd946569515 100644 --- a/include/linux/dma-iommu.h +++ b/include/linux/dma-iommu.h @@ -20,6 +20,7 @@ #include #ifdef CONFIG_IOMMU_DMA +#include #include #include diff --git a/include/trace/events/iommu.h b/include/trace/events/iommu.h index 2c7befb10f13..99254ed89212 100644 --- a/include/trace/events/iommu.h +++ b/include/trace/events/iommu.h @@ -11,7 +11,6 @@ #define _TRACE_IOMMU_H #include -#include struct device; -- cgit v1.2.3-59-g8ed1b From fd615f69a18a9d4aa5ef02a1dc83f319f75da8e7 Mon Sep 17 00:00:00 2001 From: LiuHailong Date: Tue, 7 Feb 2017 10:35:52 +0800 Subject: powerpc/64e: Fix hang when debugging programs with relocated kernel Debug interrupts can be taken during interrupt entry, since interrupt entry does not automatically turn them off. The kernel will check whether the faulting instruction is between [interrupt_base_book3e, __end_interrupts], and if so clear MSR[DE] and return. However, when the kernel is built with CONFIG_RELOCATABLE, it can't use LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e) and LOAD_REG_IMMEDIATE(r15,__end_interrupts), as they ignore relocation. Thus, if the kernel is actually running at a different address than it was built at, the address comparison will fail, and the exception entry code will hang at kernel_dbg_exc. r2(toc) is also not usable here, as r2 still holds data from the interrupted context, so LOAD_REG_ADDR() doesn't work either. So we use the *name@got* to get the EV of two labels directly. Test programs test.c shows as follows: int main(int argc, char *argv[]) { if (access("/proc/sys/kernel/perf_event_paranoid", F_OK) == -1) printf("Kernel doesn't have perf_event support\n"); } Steps to reproduce the bug, for example: 1) ./gdb ./test 2) (gdb) b access 3) (gdb) r 4) (gdb) s Signed-off-by: Liu Hailong Signed-off-by: Jiang Xuexin Reviewed-by: Jiang Biao Reviewed-by: Liu Song Reviewed-by: Huang Jian [scottwood: cleaned up commit message, and specified bad behavior as a hang rather than an oops to correspond to mainline kernel behavior] Fixes: 1cb6e0649248 ("powerpc/book3e: support CONFIG_RELOCATABLE") Cc: # 4.4.x- Signed-off-by: Scott Wood --- arch/powerpc/kernel/exceptions-64e.S | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'arch') diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S index 45b453e4d0c8..acd8ca76233e 100644 --- a/arch/powerpc/kernel/exceptions-64e.S +++ b/arch/powerpc/kernel/exceptions-64e.S @@ -735,8 +735,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) andis. r15,r14,(DBSR_IC|DBSR_BT)@h beq+ 1f +#ifdef CONFIG_RELOCATABLE + ld r15,PACATOC(r13) + ld r14,interrupt_base_book3e@got(r15) + ld r15,__end_interrupts@got(r15) +#else LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e) LOAD_REG_IMMEDIATE(r15,__end_interrupts) +#endif cmpld cr0,r10,r14 cmpld cr1,r10,r15 blt+ cr0,1f @@ -799,8 +805,14 @@ kernel_dbg_exc: andis. r15,r14,(DBSR_IC|DBSR_BT)@h beq+ 1f +#ifdef CONFIG_RELOCATABLE + ld r15,PACATOC(r13) + ld r14,interrupt_base_book3e@got(r15) + ld r15,__end_interrupts@got(r15) +#else LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e) LOAD_REG_IMMEDIATE(r15,__end_interrupts) +#endif cmpld cr0,r10,r14 cmpld cr1,r10,r15 blt+ cr0,1f -- cgit v1.2.3-59-g8ed1b From c667186f1c01ca8970c785888868b7ffd74e51ee Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Thu, 27 Apr 2017 19:06:48 +0100 Subject: arm64: KVM: Fix decoding of Rt/Rt2 when trapping AArch32 CP accesses Our 32bit CP14/15 handling inherited some of the ARMv7 code for handling the trapped system registers, completely missing the fact that the fields for Rt and Rt2 are now 5 bit wide, and not 4... Let's fix it, and provide an accessor for the most common Rt case. Cc: stable@vger.kernel.org Reviewed-by: Christoffer Dall Signed-off-by: Marc Zyngier Signed-off-by: Christoffer Dall --- arch/arm64/include/asm/kvm_emulate.h | 6 ++++++ arch/arm64/kvm/sys_regs.c | 8 ++++---- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index f5ea0ba70f07..fe39e6841326 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -240,6 +240,12 @@ static inline u8 kvm_vcpu_trap_get_fault_type(const struct kvm_vcpu *vcpu) return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_FSC_TYPE; } +static inline int kvm_vcpu_sys_get_rt(struct kvm_vcpu *vcpu) +{ + u32 esr = kvm_vcpu_get_hsr(vcpu); + return (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT; +} + static inline unsigned long kvm_vcpu_get_mpidr_aff(struct kvm_vcpu *vcpu) { return vcpu_sys_reg(vcpu, MPIDR_EL1) & MPIDR_HWID_BITMASK; diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 8ddcee6e4702..ea9fbb5c17d0 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -1529,8 +1529,8 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu, { struct sys_reg_params params; u32 hsr = kvm_vcpu_get_hsr(vcpu); - int Rt = (hsr >> 5) & 0xf; - int Rt2 = (hsr >> 10) & 0xf; + int Rt = kvm_vcpu_sys_get_rt(vcpu); + int Rt2 = (hsr >> 10) & 0x1f; params.is_aarch32 = true; params.is_32bit = false; @@ -1586,7 +1586,7 @@ static int kvm_handle_cp_32(struct kvm_vcpu *vcpu, { struct sys_reg_params params; u32 hsr = kvm_vcpu_get_hsr(vcpu); - int Rt = (hsr >> 5) & 0xf; + int Rt = kvm_vcpu_sys_get_rt(vcpu); params.is_aarch32 = true; params.is_32bit = true; @@ -1688,7 +1688,7 @@ int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run) { struct sys_reg_params params; unsigned long esr = kvm_vcpu_get_hsr(vcpu); - int Rt = (esr >> 5) & 0x1f; + int Rt = kvm_vcpu_sys_get_rt(vcpu); int ret; trace_kvm_handle_sys_reg(esr); -- cgit v1.2.3-59-g8ed1b From 8a8b56638bcac4e64cccc88bf95a0f9f4b19a2fb Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 28 Apr 2017 10:50:26 +0100 Subject: metag/uaccess: Fix access_ok() The __user_bad() macro used by access_ok() has a few corner cases noticed by Al Viro where it doesn't behave correctly: - The kernel range check has off by 1 errors which permit access to the first and last byte of the kernel mapped range. - The kernel range check ends at LINCORE_BASE rather than META_MEMORY_LIMIT, which is ineffective when the kernel is in global space (an extremely uncommon configuration). There are a couple of other shortcomings here too: - Access to the whole of the other address space is permitted (i.e. the global half of the address space when the kernel is in local space). This isn't ideal as it could theoretically still contain privileged mappings set up by the bootloader. - The size argument is unused, permitting user copies which start on valid pages at the end of the user address range and cross the boundary into the kernel address space (e.g. addr = 0x3ffffff0, size > 0x10). It isn't very convenient to add size checks when disallowing certain regions, and it seems far safer to be sure and explicit about what userland is able to access, so invert the logic to allow certain regions instead, and fix the off by 1 errors and missing size checks. This also allows the get_fs() == KERNEL_DS check to be more easily optimised into the user address range case. We now have 3 such allowed regions: - The user address range (incorporating the get_fs() == KERNEL_DS check). - NULL (some kernel code expects this to work, and we'll always catch the fault anyway). - The core code memory region. Fixes: 373cd784d0fc ("metag: Memory handling") Reported-by: Al Viro Signed-off-by: James Hogan Cc: linux-metag@vger.kernel.org Cc: stable@vger.kernel.org --- arch/metag/include/asm/uaccess.h | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/metag/include/asm/uaccess.h b/arch/metag/include/asm/uaccess.h index 469a2f1393d3..1e5f26d2dce8 100644 --- a/arch/metag/include/asm/uaccess.h +++ b/arch/metag/include/asm/uaccess.h @@ -28,24 +28,32 @@ #define segment_eq(a, b) ((a).seg == (b).seg) -#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS)) -/* - * Explicitly allow NULL pointers here. Parts of the kernel such - * as readv/writev use access_ok to validate pointers, but want - * to allow NULL pointers for various reasons. NULL pointers are - * safe to allow through because the first page is not mappable on - * Meta. - * - * We also wish to avoid letting user code access the system area - * and the kernel half of the address space. - */ -#define __user_bad(addr, size) (((addr) > 0 && (addr) < META_MEMORY_BASE) || \ - ((addr) > PAGE_OFFSET && \ - (addr) < LINCORE_BASE)) - static inline int __access_ok(unsigned long addr, unsigned long size) { - return __kernel_ok || !__user_bad(addr, size); + /* + * Allow access to the user mapped memory area, but not the system area + * before it. The check extends to the top of the address space when + * kernel access is allowed (there's no real reason to user copy to the + * system area in any case). + */ + if (likely(addr >= META_MEMORY_BASE && addr < get_fs().seg && + size <= get_fs().seg - addr)) + return true; + /* + * Explicitly allow NULL pointers here. Parts of the kernel such + * as readv/writev use access_ok to validate pointers, but want + * to allow NULL pointers for various reasons. NULL pointers are + * safe to allow through because the first page is not mappable on + * Meta. + */ + if (!addr) + return true; + /* Allow access to core code memory area... */ + if (addr >= LINCORE_CODE_BASE && addr <= LINCORE_CODE_LIMIT && + size <= LINCORE_CODE_LIMIT + 1 - addr) + return true; + /* ... but no other areas. */ + return false; } #define access_ok(type, addr, size) __access_ok((unsigned long)(addr), \ -- cgit v1.2.3-59-g8ed1b From 3a158a62da0673db918b53ac1440845a5b64fd90 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 2 May 2017 19:41:06 +0100 Subject: metag/uaccess: Check access_ok in strncpy_from_user The metag implementation of strncpy_from_user() doesn't validate the src pointer, which could allow reading of arbitrary kernel memory. Add a short access_ok() check to prevent that. Its still possible for it to read across the user/kernel boundary, but it will invariably reach a NUL character after only 9 bytes, leaking only a static kernel address being loaded into D0Re0 at the beginning of __start, which is acceptable for the immediate fix. Reported-by: Al Viro Signed-off-by: James Hogan Cc: linux-metag@vger.kernel.org Cc: stable@vger.kernel.org --- arch/metag/include/asm/uaccess.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/metag/include/asm/uaccess.h b/arch/metag/include/asm/uaccess.h index 1e5f26d2dce8..500f1be6e0fe 100644 --- a/arch/metag/include/asm/uaccess.h +++ b/arch/metag/include/asm/uaccess.h @@ -199,8 +199,13 @@ do { \ extern long __must_check __strncpy_from_user(char *dst, const char __user *src, long count); -#define strncpy_from_user(dst, src, count) __strncpy_from_user(dst, src, count) - +static inline long +strncpy_from_user(char *dst, const char __user *src, long count) +{ + if (!access_ok(VERIFY_READ, src, 1)) + return -EFAULT; + return __strncpy_from_user(dst, src, count); +} /* * Return the size of a string (including the ending 0) * -- cgit v1.2.3-59-g8ed1b From 7d3d162bbd515070dfa4f422778276aa28f114d4 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Mon, 23 Jan 2017 19:32:23 -0800 Subject: ARC: mm: Move full_page computation into cache version agnostic wrapper This reduces code duplication in each of cache version specific handlers Signed-off-by: Vineet Gupta --- arch/arc/mm/cache.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/arc/mm/cache.c b/arch/arc/mm/cache.c index 928562967f3c..18132eb56150 100644 --- a/arch/arc/mm/cache.c +++ b/arch/arc/mm/cache.c @@ -28,7 +28,7 @@ unsigned long perip_base = ARC_UNCACHED_ADDR_SPACE; /* legacy value for boot */ unsigned long perip_end = 0xFFFFFFFF; /* legacy value */ void (*_cache_line_loop_ic_fn)(phys_addr_t paddr, unsigned long vaddr, - unsigned long sz, const int cacheop); + unsigned long sz, const int op, const int full_page); void (*__dma_cache_wback_inv)(phys_addr_t start, unsigned long sz); void (*__dma_cache_inv)(phys_addr_t start, unsigned long sz); @@ -233,11 +233,10 @@ slc_chk: static inline void __cache_line_loop_v2(phys_addr_t paddr, unsigned long vaddr, - unsigned long sz, const int op) + unsigned long sz, const int op, const int full_page) { unsigned int aux_cmd; int num_lines; - const int full_page = __builtin_constant_p(sz) && sz == PAGE_SIZE; if (op == OP_INV_IC) { aux_cmd = ARC_REG_IC_IVIL; @@ -279,11 +278,10 @@ void __cache_line_loop_v2(phys_addr_t paddr, unsigned long vaddr, */ static inline void __cache_line_loop_v3(phys_addr_t paddr, unsigned long vaddr, - unsigned long sz, const int op) + unsigned long sz, const int op, const int full_page) { unsigned int aux_cmd, aux_tag; int num_lines; - const int full_page = __builtin_constant_p(sz) && sz == PAGE_SIZE; if (op == OP_INV_IC) { aux_cmd = ARC_REG_IC_IVIL; @@ -349,17 +347,16 @@ void __cache_line_loop_v3(phys_addr_t paddr, unsigned long vaddr, */ static inline void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr, - unsigned long sz, const int cacheop) + unsigned long sz, const int op, const int full_page) { unsigned int aux_cmd; int num_lines; - const int full_page_op = __builtin_constant_p(sz) && sz == PAGE_SIZE; - if (cacheop == OP_INV_IC) { + if (op == OP_INV_IC) { aux_cmd = ARC_REG_IC_IVIL; } else { /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */ - aux_cmd = cacheop & OP_INV ? ARC_REG_DC_IVDL : ARC_REG_DC_FLDL; + aux_cmd = op & OP_INV ? ARC_REG_DC_IVDL : ARC_REG_DC_FLDL; } /* Ensure we properly floor/ceil the non-line aligned/sized requests @@ -368,7 +365,7 @@ void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr, * -@paddr will be cache-line aligned already (being page aligned) * -@sz will be integral multiple of line size (being page sized). */ - if (!full_page_op) { + if (!full_page) { sz += paddr & ~CACHE_LINE_MASK; paddr &= CACHE_LINE_MASK; } @@ -381,7 +378,7 @@ void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr, * - (and needs to be written before the lower 32 bits) */ if (is_pae40_enabled()) { - if (cacheop == OP_INV_IC) + if (op == OP_INV_IC) /* * Non aliasing I-cache in HS38, * aliasing I-cache handled in __cache_line_loop_v3() @@ -486,13 +483,14 @@ static void __dc_enable(void) static inline void __dc_line_op(phys_addr_t paddr, unsigned long vaddr, unsigned long sz, const int op) { + const int full_page = __builtin_constant_p(sz) && sz == PAGE_SIZE; unsigned long flags; local_irq_save(flags); __before_dc_op(op); - __cache_line_loop(paddr, vaddr, sz, op); + __cache_line_loop(paddr, vaddr, sz, op, full_page); __after_dc_op(op); @@ -521,10 +519,11 @@ static inline void __ic_line_inv_vaddr_local(phys_addr_t paddr, unsigned long vaddr, unsigned long sz) { + const int full_page = __builtin_constant_p(sz) && sz == PAGE_SIZE; unsigned long flags; local_irq_save(flags); - (*_cache_line_loop_ic_fn)(paddr, vaddr, sz, OP_INV_IC); + (*_cache_line_loop_ic_fn)(paddr, vaddr, sz, OP_INV_IC, full_page); local_irq_restore(flags); } -- cgit v1.2.3-59-g8ed1b From 0d77117fc5c0333d024a183d6790167bb90c3b62 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Fri, 29 Aug 2014 10:55:15 +0530 Subject: ARCv2: mm: Implement cache region flush operations These are more efficient than the per-line ops Signed-off-by: Vineet Gupta --- arch/arc/include/asm/cache.h | 6 ++++ arch/arc/mm/cache.c | 68 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) (limited to 'arch') diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index 5008021fba98..16e457706129 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h @@ -62,6 +62,8 @@ extern unsigned long perip_base, perip_end; #define ARC_REG_IC_BCR 0x77 /* Build Config reg */ #define ARC_REG_IC_IVIC 0x10 #define ARC_REG_IC_CTRL 0x11 +#define ARC_REG_IC_IVIR 0x16 +#define ARC_REG_IC_ENDR 0x17 #define ARC_REG_IC_IVIL 0x19 #define ARC_REG_IC_PTAG 0x1E #define ARC_REG_IC_PTAG_HI 0x1F @@ -76,6 +78,8 @@ extern unsigned long perip_base, perip_end; #define ARC_REG_DC_IVDL 0x4A #define ARC_REG_DC_FLSH 0x4B #define ARC_REG_DC_FLDL 0x4C +#define ARC_REG_DC_STARTR 0x4D +#define ARC_REG_DC_ENDR 0x4E #define ARC_REG_DC_PTAG 0x5C #define ARC_REG_DC_PTAG_HI 0x5F @@ -83,6 +87,8 @@ extern unsigned long perip_base, perip_end; #define DC_CTRL_DIS 0x001 #define DC_CTRL_INV_MODE_FLUSH 0x040 #define DC_CTRL_FLUSH_STATUS 0x100 +#define DC_CTRL_RGN_OP_INV 0x200 +#define DC_CTRL_RGN_OP_MSK 0xE00 /*System-level cache (L2 cache) related Auxiliary registers */ #define ARC_REG_SLC_CFG 0x901 diff --git a/arch/arc/mm/cache.c b/arch/arc/mm/cache.c index 18132eb56150..8401fcb75d19 100644 --- a/arch/arc/mm/cache.c +++ b/arch/arc/mm/cache.c @@ -21,6 +21,10 @@ #include #include +#ifdef CONFIG_ISA_ARCV2 +#define USE_RGN_FLSH 1 +#endif + static int l2_line_sz; static int ioc_exists; int slc_enable = 1, ioc_enable = 1; @@ -332,6 +336,8 @@ void __cache_line_loop_v3(phys_addr_t paddr, unsigned long vaddr, } } +#ifndef USE_RGN_FLSH + /* * In HS38x (MMU v4), I-cache is VIPT (can alias), D-cache is PIPT * Here's how cache ops are implemented @@ -394,6 +400,68 @@ void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr, } } +#else + +/* + * optimized flush operation which takes a region as opposed to iterating per line + */ +static inline +void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr, + unsigned long sz, const int op, const int full_page) +{ + const unsigned int ctl = ARC_REG_DC_CTRL; + unsigned int s, e, val; + + /* Only for Non aliasing I-cache in HS38 */ + if (op == OP_INV_IC) { + s = ARC_REG_IC_IVIR; + e = ARC_REG_IC_ENDR; + } else { + s = ARC_REG_DC_STARTR; + e = ARC_REG_DC_ENDR; + } + + if (!full_page) { + /* for any leading gap between @paddr and start of cache line */ + sz += paddr & ~CACHE_LINE_MASK; + paddr &= CACHE_LINE_MASK; + + /* + * account for any trailing gap to end of cache line + * this is equivalent to DIV_ROUND_UP() in line ops above + */ + sz += L1_CACHE_BYTES - 1; + } + + if (is_pae40_enabled()) { + /* TBD: check if crossing 4TB boundary */ + if (op == OP_INV_IC) + write_aux_reg(ARC_REG_IC_PTAG_HI, (u64)paddr >> 32); + else + write_aux_reg(ARC_REG_DC_PTAG_HI, (u64)paddr >> 32); + } + + /* + * Flush / Invalidate is provided by DC_CTRL.RNG_OP 0 or 1 + * Flush-n-invalidate additionally uses setting DC_CTRL.IM = 1 + * just as for line ops which is handled in __before_dc_op() + */ + val = read_aux_reg(ctl) & ~DC_CTRL_RGN_OP_MSK; + + if (op & OP_INV) + val |= DC_CTRL_RGN_OP_INV; + + write_aux_reg(ctl, val); + + /* ENDR needs to be set ahead of START */ + write_aux_reg(e, paddr + sz); /* ENDR is exclusive */ + write_aux_reg(s, paddr); + + /* caller waits on DC_CTRL.FS */ +} + +#endif + #if (CONFIG_ARC_MMU_VER < 3) #define __cache_line_loop __cache_line_loop_v2 #elif (CONFIG_ARC_MMU_VER == 3) -- cgit v1.2.3-59-g8ed1b From ee40bd1e0c3fb83d810f258952692ffdebc14726 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Tue, 2 May 2017 15:28:12 -0700 Subject: ARCv2: mm: Merge 2 updates to DC_CTRL for region flush Region Flush has a weird programming model. 1. Flush or Invalidate is selected by DC_CTRL.RGN_OP 2 Flush-n-Invalidate is done by DC_CTRL.IM Given the code structuring before, case #2 above was generating two seperate updates to DC_CTRL which was pointless. | 80a342b0 <__dma_cache_wback_inv_l1>: | 80a342b0: clri r4 | 80a342b4: lr r2,[dc_ctrl] | 80a342b8: bset_s r2,r2,0x6 | 80a342ba: sr r2,[dc_ctrl] <-- FIRST | | 80a342be: bmskn r3,r0,0x5 | | 80a342c2: lr r2,[dc_ctrl] | 80a342c6: and r2,r2,0xfffff1ff | 80a342ce: bset_s r2,r2,0x9 | 80a342d0: sr r2,[dc_ctrl] <-- SECOND | | 80a342d4: add_s r1,r1,0x3f | 80a342d6: bmsk_s r0,r0,0x5 | 80a342d8: add_s r0,r0,r1 | 80a342da: add_s r0,r0,r3 | 80a342dc: sr r0,[78] | 80a342e0: sr r3,[77] |... |... So move setting of DC_CTRL.RGN_OP into __before_dc_op() and combine with any other update. | 80b63324 <__dma_cache_wback_inv_l1>: | 80b63324: clri r3 | 80b63328: lr r2,[dc_ctrl] | 80b6332c: and r2,r2,0xfffff1ff | 80b63334: or r2,r2,576 | 80b63338: sr r2,[dc_ctrl] | | 80b6333c: add_s r1,r1,0x3f | 80b6333e: bmskn r2,r0,0x5 | 80b63342: add_s r0,r0,r1 | 80b63344: sr r0,[78] | 80b63348: sr r2,[77] Signed-off-by: Vineet Gupta --- arch/arc/mm/cache.c | 46 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/arc/mm/cache.c b/arch/arc/mm/cache.c index 8401fcb75d19..a867575a758b 100644 --- a/arch/arc/mm/cache.c +++ b/arch/arc/mm/cache.c @@ -409,8 +409,7 @@ static inline void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr, unsigned long sz, const int op, const int full_page) { - const unsigned int ctl = ARC_REG_DC_CTRL; - unsigned int s, e, val; + unsigned int s, e; /* Only for Non aliasing I-cache in HS38 */ if (op == OP_INV_IC) { @@ -441,18 +440,6 @@ void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr, write_aux_reg(ARC_REG_DC_PTAG_HI, (u64)paddr >> 32); } - /* - * Flush / Invalidate is provided by DC_CTRL.RNG_OP 0 or 1 - * Flush-n-invalidate additionally uses setting DC_CTRL.IM = 1 - * just as for line ops which is handled in __before_dc_op() - */ - val = read_aux_reg(ctl) & ~DC_CTRL_RGN_OP_MSK; - - if (op & OP_INV) - val |= DC_CTRL_RGN_OP_INV; - - write_aux_reg(ctl, val); - /* ENDR needs to be set ahead of START */ write_aux_reg(e, paddr + sz); /* ENDR is exclusive */ write_aux_reg(s, paddr); @@ -476,6 +463,11 @@ void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr, * Machine specific helpers for Entire D-Cache or Per Line ops */ +#ifndef USE_RGN_FLSH +/* + * this version avoids extra read/write of DC_CTRL for flush or invalid ops + * in the non region flush regime (such as for ARCompact) + */ static inline void __before_dc_op(const int op) { if (op == OP_FLUSH_N_INV) { @@ -489,6 +481,32 @@ static inline void __before_dc_op(const int op) } } +#else + +static inline void __before_dc_op(const int op) +{ + const unsigned int ctl = ARC_REG_DC_CTRL; + unsigned int val = read_aux_reg(ctl); + + if (op == OP_FLUSH_N_INV) { + val |= DC_CTRL_INV_MODE_FLUSH; + } + + if (op != OP_INV_IC) { + /* + * Flush / Invalidate is provided by DC_CTRL.RNG_OP 0 or 1 + * combined Flush-n-invalidate uses DC_CTRL.IM = 1 set above + */ + val &= ~DC_CTRL_RGN_OP_MSK; + if (op & OP_INV) + val |= DC_CTRL_RGN_OP_INV; + } + write_aux_reg(ctl, val); +} + +#endif + + static inline void __after_dc_op(const int op) { if (op & OP_FLUSH) { -- cgit v1.2.3-59-g8ed1b From f734a31083324b8f4f24b2c5cba178c7459db309 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Tue, 2 May 2017 16:23:57 -0700 Subject: ARCv2: mm: micro-optimize region flush generated code DC_CTRL.RGN_OP is 3 bits wide, however only 1 bit is used in current programming model (0: flush, 1: invalidate) The current code targetting 3 bits leads to additional 8 byte AND operation which can be elided given that only 1 bit is ever set by software and/or looked at by hardware before ------ | 80b63324 <__dma_cache_wback_inv_l1>: | 80b63324: clri r3 | 80b63328: lr r2,[dc_ctrl] | 80b6332c: and r2,r2,0xfffff1ff <--- 8 bytes insn | 80b63334: or r2,r2,576 | 80b63338: sr r2,[dc_ctrl] | ... | ... | 80b63360 <__dma_cache_inv_l1>: | 80b63360: clri r3 | 80b63364: lr r2,[dc_ctrl] | 80b63368: and r2,r2,0xfffff1ff <--- 8 bytes insn | 80b63370: bset_s r2,r2,0x9 | 80b63372: sr r2,[dc_ctrl] | ... | ... | 80b6338c <__dma_cache_wback_l1>: | 80b6338c: clri r3 | 80b63390: lr r2,[dc_ctrl] | 80b63394: and r2,r2,0xfffff1ff <--- 8 bytes insn | 80b6339c: sr r2,[dc_ctrl] after (AND elided totally in 2 cases, replaced with 2 byte BCLR in 3rd) ----- | 80b63324 <__dma_cache_wback_inv_l1>: | 80b63324: clri r3 | 80b63328: lr r2,[dc_ctrl] | 80b6332c: or r2,r2,576 | 80b63330: sr r2,[dc_ctrl] | ... | ... | 80b63358 <__dma_cache_inv_l1>: | 80b63358: clri r3 | 80b6335c: lr r2,[dc_ctrl] | 80b63360: bset_s r2,r2,0x9 | 80b63362: sr r2,[dc_ctrl] | ... | ... | 80b6337c <__dma_cache_wback_l1>: | 80b6337c: clri r3 | 80b63380: lr r2,[dc_ctrl] | 80b63384: bclr_s r2,r2,0x9 | 80b63386: sr r2,[dc_ctrl] Signed-off-by: Vineet Gupta --- arch/arc/include/asm/cache.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index 16e457706129..19ebddffb279 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h @@ -88,7 +88,7 @@ extern unsigned long perip_base, perip_end; #define DC_CTRL_INV_MODE_FLUSH 0x040 #define DC_CTRL_FLUSH_STATUS 0x100 #define DC_CTRL_RGN_OP_INV 0x200 -#define DC_CTRL_RGN_OP_MSK 0xE00 +#define DC_CTRL_RGN_OP_MSK 0x200 /*System-level cache (L2 cache) related Auxiliary registers */ #define ARC_REG_SLC_CFG 0x901 -- cgit v1.2.3-59-g8ed1b From 726bd223105c04f7bf5eacdc2540819c301061f7 Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Mon, 1 May 2017 09:38:13 +0200 Subject: powerpc/8xx: Adding support of IRQ in MPC8xx GPIO This patch allows the use of IRQ to notify the change of GPIO status on MPC8xx CPM IO ports. This then allows to associate IRQs to GPIOs in the Device Tree. Ex: CPM1_PIO_C: gpio-controller@960 { #gpio-cells = <2>; compatible = "fsl,cpm1-pario-bank-c"; reg = <0x960 0x10>; fsl,cpm1-gpio-irq-mask = <0x0fff>; interrupts = <1 2 6 9 10 11 14 15 23 24 26 31>; interrupt-parent = <&CPM_PIC>; gpio-controller; }; The property 'fsl,cpm1-gpio-irq-mask' defines which of the 16 GPIOs have the associated interrupts defined in the 'interrupts' property. Signed-off-by: Christophe Leroy Signed-off-by: Scott Wood --- .../devicetree/bindings/soc/fsl/cpm_qe/gpio.txt | 21 +++++++++++++++++- arch/powerpc/include/asm/cpm1.h | 2 ++ arch/powerpc/sysdev/cpm1.c | 25 ++++++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/Documentation/devicetree/bindings/soc/fsl/cpm_qe/gpio.txt b/Documentation/devicetree/bindings/soc/fsl/cpm_qe/gpio.txt index 349f79fd7076..626e1afa64a6 100644 --- a/Documentation/devicetree/bindings/soc/fsl/cpm_qe/gpio.txt +++ b/Documentation/devicetree/bindings/soc/fsl/cpm_qe/gpio.txt @@ -13,8 +13,17 @@ Required properties: - #gpio-cells : Should be two. The first cell is the pin number and the second cell is used to specify optional parameters (currently unused). - gpio-controller : Marks the port as GPIO controller. +Optional properties: +- fsl,cpm1-gpio-irq-mask : For banks having interrupt capability (like port C + on CPM1), this item tells which ports have an associated interrupt (ports are + listed in the same order as in PCINT register) +- interrupts : This property provides the list of interrupt for each GPIO having + one as described by the fsl,cpm1-gpio-irq-mask property. There should be as + many interrupts as number of ones in the mask property. The first interrupt in + the list corresponds to the most significant bit of the mask. +- interrupt-parent : Parent for the above interrupt property. -Example of three SOC GPIO banks defined as gpio-controller nodes: +Example of four SOC GPIO banks defined as gpio-controller nodes: CPM1_PIO_A: gpio-controller@950 { #gpio-cells = <2>; @@ -30,6 +39,16 @@ Example of three SOC GPIO banks defined as gpio-controller nodes: gpio-controller; }; + CPM1_PIO_C: gpio-controller@960 { + #gpio-cells = <2>; + compatible = "fsl,cpm1-pario-bank-c"; + reg = <0x960 0x10>; + fsl,cpm1-gpio-irq-mask = <0x0fff>; + interrupts = <1 2 6 9 10 11 14 15 23 24 26 31>; + interrupt-parent = <&CPM_PIC>; + gpio-controller; + }; + CPM1_PIO_E: gpio-controller@ac8 { #gpio-cells = <2>; compatible = "fsl,cpm1-pario-bank-e"; diff --git a/arch/powerpc/include/asm/cpm1.h b/arch/powerpc/include/asm/cpm1.h index 8ee4211ca0c6..14ad37865000 100644 --- a/arch/powerpc/include/asm/cpm1.h +++ b/arch/powerpc/include/asm/cpm1.h @@ -560,6 +560,8 @@ typedef struct risc_timer_pram { #define CPM_PIN_SECONDARY 2 #define CPM_PIN_GPIO 4 #define CPM_PIN_OPENDRAIN 8 +#define CPM_PIN_FALLEDGE 16 +#define CPM_PIN_ANYEDGE 0 enum cpm_port { CPM_PORTA, diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c index 986cd111d4df..c651e668996b 100644 --- a/arch/powerpc/sysdev/cpm1.c +++ b/arch/powerpc/sysdev/cpm1.c @@ -377,6 +377,10 @@ static void cpm1_set_pin16(int port, int pin, int flags) setbits16(&iop->odr_sor, pin); else clrbits16(&iop->odr_sor, pin); + if (flags & CPM_PIN_FALLEDGE) + setbits16(&iop->intr, pin); + else + clrbits16(&iop->intr, pin); } } @@ -528,6 +532,9 @@ struct cpm1_gpio16_chip { /* shadowed data register to clear/set bits safely */ u16 cpdata; + + /* IRQ associated with Pins when relevant */ + int irq[16]; }; static void cpm1_gpio16_save_regs(struct of_mm_gpio_chip *mm_gc) @@ -578,6 +585,14 @@ static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value) spin_unlock_irqrestore(&cpm1_gc->lock, flags); } +static int cpm1_gpio16_to_irq(struct gpio_chip *gc, unsigned int gpio) +{ + struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); + struct cpm1_gpio16_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc); + + return cpm1_gc->irq[gpio] ? : -ENXIO; +} + static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); @@ -618,6 +633,7 @@ int cpm1_gpiochip_add16(struct device_node *np) struct cpm1_gpio16_chip *cpm1_gc; struct of_mm_gpio_chip *mm_gc; struct gpio_chip *gc; + u16 mask; cpm1_gc = kzalloc(sizeof(*cpm1_gc), GFP_KERNEL); if (!cpm1_gc) @@ -625,6 +641,14 @@ int cpm1_gpiochip_add16(struct device_node *np) spin_lock_init(&cpm1_gc->lock); + if (!of_property_read_u16(np, "fsl,cpm1-gpio-irq-mask", &mask)) { + int i, j; + + for (i = 0, j = 0; i < 16; i++) + if (mask & (1 << (15 - i))) + cpm1_gc->irq[i] = irq_of_parse_and_map(np, j++); + } + mm_gc = &cpm1_gc->mm_gc; gc = &mm_gc->gc; @@ -634,6 +658,7 @@ int cpm1_gpiochip_add16(struct device_node *np) gc->direction_output = cpm1_gpio16_dir_out; gc->get = cpm1_gpio16_get; gc->set = cpm1_gpio16_set; + gc->to_irq = cpm1_gpio16_to_irq; return of_mm_gpiochip_add_data(np, mm_gc, cpm1_gc); } -- cgit v1.2.3-59-g8ed1b From 5ed78e5523fd9ba77b8444d380d54da1f88c53fc Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 11 Sep 2016 16:42:14 +0900 Subject: alpha: add $(src)/ rather than $(obj)/ to make source file path $(ev6-y)divide.S is a source file, not a build-time generated file. So, it should be prefixed with $(src)/ rather than $(obj)/. Signed-off-by: Masahiro Yamada --- arch/alpha/lib/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile index 59660743237c..7b694fed382c 100644 --- a/arch/alpha/lib/Makefile +++ b/arch/alpha/lib/Makefile @@ -46,11 +46,11 @@ AFLAGS___remqu.o = -DREM AFLAGS___divlu.o = -DDIV -DINTSIZE AFLAGS___remlu.o = -DREM -DINTSIZE -$(obj)/__divqu.o: $(obj)/$(ev6-y)divide.S +$(obj)/__divqu.o: $(src)/$(ev6-y)divide.S $(cmd_as_o_S) -$(obj)/__remqu.o: $(obj)/$(ev6-y)divide.S +$(obj)/__remqu.o: $(src)/$(ev6-y)divide.S $(cmd_as_o_S) -$(obj)/__divlu.o: $(obj)/$(ev6-y)divide.S +$(obj)/__divlu.o: $(src)/$(ev6-y)divide.S $(cmd_as_o_S) -$(obj)/__remlu.o: $(obj)/$(ev6-y)divide.S +$(obj)/__remlu.o: $(src)/$(ev6-y)divide.S $(cmd_as_o_S) -- cgit v1.2.3-59-g8ed1b From e19a4e3f1bffe45b8e2ea67fcfb0c9c88278c4cc Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 11 Sep 2016 16:42:15 +0900 Subject: alpha: merge build rules of division routines These four objects are generated by the same build rule, with different compile options. The build rules can be merged. Signed-off-by: Masahiro Yamada --- arch/alpha/lib/Makefile | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile index 7b694fed382c..5f12e9dcd623 100644 --- a/arch/alpha/lib/Makefile +++ b/arch/alpha/lib/Makefile @@ -46,11 +46,6 @@ AFLAGS___remqu.o = -DREM AFLAGS___divlu.o = -DDIV -DINTSIZE AFLAGS___remlu.o = -DREM -DINTSIZE -$(obj)/__divqu.o: $(src)/$(ev6-y)divide.S - $(cmd_as_o_S) -$(obj)/__remqu.o: $(src)/$(ev6-y)divide.S - $(cmd_as_o_S) -$(obj)/__divlu.o: $(src)/$(ev6-y)divide.S - $(cmd_as_o_S) -$(obj)/__remlu.o: $(src)/$(ev6-y)divide.S +$(addprefix $(obj)/,__divqu.o __remqu.o __divlu.o __remlu.o): \ + $(src)/$(ev6-y)divide.S $(cmd_as_o_S) -- cgit v1.2.3-59-g8ed1b From 3eec0291830e4c28d09f73bab247f3b59172022b Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 11 Sep 2016 16:42:16 +0900 Subject: alpha: make short build log available for division routines This enables the Kbuild standard log style as follows: AS arch/alpha/lib/__divlu.o AS arch/alpha/lib/__divqu.o AS arch/alpha/lib/__remlu.o AS arch/alpha/lib/__remqu.o Signed-off-by: Masahiro Yamada --- arch/alpha/lib/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile index 5f12e9dcd623..7083434dd241 100644 --- a/arch/alpha/lib/Makefile +++ b/arch/alpha/lib/Makefile @@ -47,5 +47,5 @@ AFLAGS___divlu.o = -DDIV -DINTSIZE AFLAGS___remlu.o = -DREM -DINTSIZE $(addprefix $(obj)/,__divqu.o __remqu.o __divlu.o __remlu.o): \ - $(src)/$(ev6-y)divide.S - $(cmd_as_o_S) + $(src)/$(ev6-y)divide.S FORCE + $(call if_changed_rule,as_o_S) -- cgit v1.2.3-59-g8ed1b From 028d5bf161d11b6cab9f2d0ad076cccd1d8495bc Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 12 Apr 2017 08:36:32 +0900 Subject: ia64: beatify build log for gate.so and gate-syms.o Currently, the object path is not aligned in the build log: LDS arch/ia64/kernel/gate.lds AS arch/ia64/kernel/gate.o GATE arch/ia64/kernel/gate.so AS arch/ia64/kernel/gate-data.o Signed-off-by: Masahiro Yamada --- arch/ia64/kernel/Makefile.gate | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/ia64/kernel/Makefile.gate b/arch/ia64/kernel/Makefile.gate index ceeffc509764..a32903ada016 100644 --- a/arch/ia64/kernel/Makefile.gate +++ b/arch/ia64/kernel/Makefile.gate @@ -6,7 +6,7 @@ extra-y += gate.so gate-syms.o gate.lds gate.o CPPFLAGS_gate.lds := -P -C -U$(ARCH) -quiet_cmd_gate = GATE $@ +quiet_cmd_gate = GATE $@ cmd_gate = $(CC) -nostdlib $(GATECFLAGS_$(@F)) -Wl,-T,$(filter-out FORCE,$^) -o $@ GATECFLAGS_gate.so = -shared -s -Wl,-soname=linux-gate.so.1 \ -- cgit v1.2.3-59-g8ed1b From e3cd7f013bac3105d44b8bd5a90359989d45b5a5 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 3 May 2017 09:54:20 +0100 Subject: metag/mm: Drop pointless increment The increment of entry in the loop in mmu_init for meta1 is redundant as it isn't used again, so drop it. Reported-by: David Binderman Signed-off-by: James Hogan --- arch/metag/mm/mmu-meta1.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/metag/mm/mmu-meta1.c b/arch/metag/mm/mmu-meta1.c index 91f4255bcb5c..62ebab90924d 100644 --- a/arch/metag/mm/mmu-meta1.c +++ b/arch/metag/mm/mmu-meta1.c @@ -152,6 +152,5 @@ void __init mmu_init(unsigned long mem_end) p_swapper_pg_dir++; addr += PGDIR_SIZE; - entry++; } } -- cgit v1.2.3-59-g8ed1b From 33b88e708e7dfa58dc896da2a98f5719d2eb315c Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Tue, 2 May 2017 14:08:50 -0400 Subject: perf/x86: Fix Broadwell-EP DRAM RAPL events It appears as though the Broadwell-EP DRAM units share the special units quirk with Haswell-EP/KNL. Without this patch, you get really high results (a single DRAM using 20W of power). The powercap driver in drivers/powercap/intel_rapl.c already has this change. Signed-off-by: Vince Weaver Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Kan Liang Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Stephane Eranian Cc: Thomas Gleixner Cc: linux-kernel@vger.kernel.org Cc: Signed-off-by: Ingo Molnar --- arch/x86/events/intel/rapl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c index 9d05c7e67f60..a45e2114a846 100644 --- a/arch/x86/events/intel/rapl.c +++ b/arch/x86/events/intel/rapl.c @@ -761,7 +761,7 @@ static const struct x86_cpu_id rapl_cpu_match[] __initconst = { X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_CORE, hsw_rapl_init), X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_GT3E, hsw_rapl_init), - X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_X, hsw_rapl_init), + X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_X, hsx_rapl_init), X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_XEON_D, hsw_rapl_init), X86_RAPL_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNL, knl_rapl_init), -- cgit v1.2.3-59-g8ed1b From 8c64415cc1f5794c02b95dee10084fa8a4ee3cfe Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 3 May 2017 08:28:48 -0700 Subject: sparc: Remove redundant tests in boot_flags_init(). The test: *commands && *commands == ' ' is equivalent to: *commands == ' ' Reported-by: David Binderman Signed-off-by: David S. Miller --- arch/sparc/kernel/setup_32.c | 2 +- arch/sparc/kernel/setup_64.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c index 6f06058c5ae7..6722308d1a98 100644 --- a/arch/sparc/kernel/setup_32.c +++ b/arch/sparc/kernel/setup_32.c @@ -148,7 +148,7 @@ static void __init boot_flags_init(char *commands) { while (*commands) { /* Move to the start of the next "argument". */ - while (*commands && *commands == ' ') + while (*commands == ' ') commands++; /* Process any command switches, otherwise skip it. */ diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c index 6b7331d198e9..422b17880955 100644 --- a/arch/sparc/kernel/setup_64.c +++ b/arch/sparc/kernel/setup_64.c @@ -133,7 +133,7 @@ static void __init boot_flags_init(char *commands) { while (*commands) { /* Move to the start of the next "argument". */ - while (*commands && *commands == ' ') + while (*commands == ' ') commands++; /* Process any command switches, otherwise skip it. */ -- cgit v1.2.3-59-g8ed1b From 65c02a556bc4f374e9002ded1ea11a0263da7b63 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Wed, 3 May 2017 11:21:31 -0700 Subject: ARCv2: ptrace: provide regset for accumulator/r30 regs Signed-off-by: Vineet Gupta --- arch/arc/include/uapi/asm/elf.h | 1 + arch/arc/include/uapi/asm/ptrace.h | 5 +++ arch/arc/kernel/ptrace.c | 62 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 65 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arc/include/uapi/asm/elf.h b/arch/arc/include/uapi/asm/elf.h index 0037a587320d..06d95e611616 100644 --- a/arch/arc/include/uapi/asm/elf.h +++ b/arch/arc/include/uapi/asm/elf.h @@ -27,6 +27,7 @@ typedef unsigned long elf_greg_t; typedef unsigned long elf_fpregset_t; #define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t)) +#define ELF_ARCV2REG (sizeof(struct user_regs_arcv2) / sizeof(elf_greg_t)) typedef elf_greg_t elf_gregset_t[ELF_NGREG]; diff --git a/arch/arc/include/uapi/asm/ptrace.h b/arch/arc/include/uapi/asm/ptrace.h index 0b3ef63d4a03..dd206e6b482c 100644 --- a/arch/arc/include/uapi/asm/ptrace.h +++ b/arch/arc/include/uapi/asm/ptrace.h @@ -47,6 +47,11 @@ struct user_regs_struct { unsigned long efa; /* break pt addr, for break points in delay slots */ unsigned long stop_pc; /* give dbg stop_pc after ensuring brkpt trap */ }; + +struct user_regs_arcv2 { + unsigned long r30, r58, r59; +}; + #endif /* !__ASSEMBLY__ */ #endif /* _UAPI__ASM_ARC_PTRACE_H */ diff --git a/arch/arc/kernel/ptrace.c b/arch/arc/kernel/ptrace.c index 31150060d38b..5ee4676f135d 100644 --- a/arch/arc/kernel/ptrace.c +++ b/arch/arc/kernel/ptrace.c @@ -184,19 +184,75 @@ static int genregs_set(struct task_struct *target, return ret; } +#ifdef CONFIG_ISA_ARCV2 +static int arcv2regs_get(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + void *kbuf, void __user *ubuf) +{ + const struct pt_regs *regs = task_pt_regs(target); + int ret, copy_sz; + + if (IS_ENABLED(CONFIG_ARC_HAS_ACCL_REGS)) + copy_sz = sizeof(struct user_regs_arcv2); + else + copy_sz = 4; /* r30 only */ + + /* + * itemized copy not needed like above as layout of regs (r30,r58,r59) + * is exactly same in kernel (pt_regs) and userspace (user_regs_arcv2) + */ + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, ®s->r30, + 0, copy_sz); + + return ret; +} + +static int arcv2regs_set(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) +{ + const struct pt_regs *regs = task_pt_regs(target); + int ret, copy_sz; + + if (IS_ENABLED(CONFIG_ARC_HAS_ACCL_REGS)) + copy_sz = sizeof(struct user_regs_arcv2); + else + copy_sz = 4; /* r30 only */ + + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, (void *)®s->r30, + 0, copy_sz); + + return ret; +} + +#endif + enum arc_getset { - REGSET_GENERAL, + REGSET_CMN, + REGSET_ARCV2, }; static const struct user_regset arc_regsets[] = { - [REGSET_GENERAL] = { + [REGSET_CMN] = { .core_note_type = NT_PRSTATUS, .n = ELF_NGREG, .size = sizeof(unsigned long), .align = sizeof(unsigned long), .get = genregs_get, .set = genregs_set, - } + }, +#ifdef CONFIG_ISA_ARCV2 + [REGSET_ARCV2] = { + .core_note_type = NT_ARC_V2, + .n = ELF_ARCV2REG, + .size = sizeof(unsigned long), + .align = sizeof(unsigned long), + .get = arcv2regs_get, + .set = arcv2regs_set, + }, +#endif }; static const struct user_regset_view user_arc_view = { -- cgit v1.2.3-59-g8ed1b From ecb6c7435f25d6a11fa9d14f407d00286f9642b9 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sun, 25 Dec 2016 23:11:05 +0100 Subject: um: Fix _print_addr() Recent changes to printk() broke UML's stack trace output. Kill the root of the problem by using a single printk() statement. Signed-off-by: Richard Weinberger --- arch/um/kernel/sysrq.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c index a76295f7ede9..6b995e870d55 100644 --- a/arch/um/kernel/sysrq.c +++ b/arch/um/kernel/sysrq.c @@ -20,10 +20,8 @@ static void _print_addr(void *data, unsigned long address, int reliable) { - pr_info(" [<%08lx>]", address); - pr_cont(" %s", reliable ? "" : "? "); - print_symbol("%s", address); - pr_cont("\n"); + pr_info(" [<%08lx>] %s%pF\n", address, reliable ? "" : "? ", + (void *)address); } static const struct stacktrace_ops stackops = { -- cgit v1.2.3-59-g8ed1b From 8bba077066d6d0a135b7be1970691522075bf905 Mon Sep 17 00:00:00 2001 From: Nikola Kotur Date: Thu, 2 Mar 2017 14:16:40 +0100 Subject: um: Set number of CPUs Define NR_CPUS required by the timer subsystem. Fixes this make warning: scripts/kconfig/conf --oldconfig arch/x86/um/Kconfig kernel/time/Kconfig:155:warning: range is invalid Signed-off-by: Nikola Kotur Signed-off-by: Richard Weinberger --- arch/um/Kconfig.common | 5 +++++ arch/um/os-Linux/skas/process.c | 3 --- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/um/Kconfig.common b/arch/um/Kconfig.common index fd443852103c..347bcd444c99 100644 --- a/arch/um/Kconfig.common +++ b/arch/um/Kconfig.common @@ -62,3 +62,8 @@ config HZ config SUBARCH string option env="SUBARCH" + +config NR_CPUS + int + range 1 1 + default 1 diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 23025d645160..92f7ee14b10e 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -233,9 +233,6 @@ static int userspace_tramp(void *stack) return 0; } -/* Each element set once, and only accessed by a single processor anyway */ -#undef NR_CPUS -#define NR_CPUS 1 int userspace_pid[NR_CPUS]; int start_userspace(unsigned long stub_stack) -- cgit v1.2.3-59-g8ed1b From 9abc74a22d85ab29cef9896a2582a530da7e79bf Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sat, 1 Apr 2017 00:41:57 +0200 Subject: um: Fix PTRACE_POKEUSER on x86_64 This is broken since ever but sadly nobody noticed. Recent versions of GDB set DR_CONTROL unconditionally and UML dies due to a heap corruption. It turns out that the PTRACE_POKEUSER was copy&pasted from i386 and assumes that addresses are 4 bytes long. Fix that by using 8 as address size in the calculation. Cc: Reported-by: jie cao Signed-off-by: Richard Weinberger --- arch/x86/um/ptrace_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/um/ptrace_64.c b/arch/x86/um/ptrace_64.c index a5c9910d234f..09a085bde0d4 100644 --- a/arch/x86/um/ptrace_64.c +++ b/arch/x86/um/ptrace_64.c @@ -125,7 +125,7 @@ int poke_user(struct task_struct *child, long addr, long data) else if ((addr >= offsetof(struct user, u_debugreg[0])) && (addr <= offsetof(struct user, u_debugreg[7]))) { addr -= offsetof(struct user, u_debugreg[0]); - addr = addr >> 2; + addr = addr >> 3; if ((addr == 4) || (addr == 5)) return -EIO; child->thread.arch.debugregs[addr] = data; -- cgit v1.2.3-59-g8ed1b From 601b7b9147455a4d8d80d04f0e5a1eb222301bbe Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Mon, 3 Apr 2017 12:54:58 -0700 Subject: um: Include kbuild.h instead of duplicating its macros Signed-off-by: Matthias Kaehlcke Reviewed-by: Masahiro Yamada Signed-off-by: Richard Weinberger --- arch/x86/um/shared/sysdep/kernel-offsets.h | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/um/shared/sysdep/kernel-offsets.h b/arch/x86/um/shared/sysdep/kernel-offsets.h index 46a9df99f3c5..7e1d35b6ad5c 100644 --- a/arch/x86/um/shared/sysdep/kernel-offsets.h +++ b/arch/x86/um/shared/sysdep/kernel-offsets.h @@ -2,16 +2,9 @@ #include #include #include +#include #include -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define BLANK() asm volatile("\n->" : : ) - -#define OFFSET(sym, str, mem) \ - DEFINE(sym, offsetof(struct str, mem)); - void foo(void) { #include -- cgit v1.2.3-59-g8ed1b From 5b4236e17cc1bd9fa14b2b0c7a4ae632d41f2e20 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 27 Apr 2017 12:15:10 +0900 Subject: um: Fix to call read_initrd after init_bootmem Since read_initrd() invokes alloc_bootmem() for allocating memory to load initrd image, it must be called after init_bootmem. This makes read_initrd() called directly from setup_arch() after init_bootmem() and mem_total_pages(). Cc: Fixes: b63236972e1 ("um: Setup physical memory in setup_arch()") Signed-off-by: Masami Hiramatsu Signed-off-by: Richard Weinberger --- arch/um/kernel/initrd.c | 4 +--- arch/um/kernel/um_arch.c | 6 ++++++ 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c index 48bae81f8dca..6f6e7896e53f 100644 --- a/arch/um/kernel/initrd.c +++ b/arch/um/kernel/initrd.c @@ -14,7 +14,7 @@ static char *initrd __initdata = NULL; static int load_initrd(char *filename, void *buf, int size); -static int __init read_initrd(void) +int __init read_initrd(void) { void *area; long long size; @@ -46,8 +46,6 @@ static int __init read_initrd(void) return 0; } -__uml_postsetup(read_initrd); - static int __init uml_initrd_setup(char *line, int *add) { initrd = line; diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 4b85acd4020c..64a1fd06f3fd 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -338,11 +338,17 @@ int __init linux_main(int argc, char **argv) return start_uml(); } +int __init __weak read_initrd(void) +{ + return 0; +} + void __init setup_arch(char **cmdline_p) { stack_protections((unsigned long) &init_thread_info); setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem); mem_total_pages(physmem_size, iomem_size, highmem); + read_initrd(); paging_init(); strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); -- cgit v1.2.3-59-g8ed1b From c374ed27c93698c794f99c5d41d9ad3062c4c207 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Wed, 19 Apr 2017 14:46:24 +1000 Subject: powerpc/powernv: Block PCI config access on BCM5718 during EEH recovery Similar to what is done in commit b6541db13952 ("powerpc/eeh: Block PCI config access upon frozen PE"), we need block PCI config access for BCM5719 when recovering frozen error on them. Otherwise, an unexpected recursive fenced PHB error is observed. 0001:06:00.0 Ethernet controller: Broadcom Corporation \ NetXtreme BCM5718 Gigabit Ethernet PCIe (rev 10) 0001:06:00.1 Ethernet controller: Broadcom Corporation \ NetXtreme BCM5718 Gigabit Ethernet PCIe (rev 10) Signed-off-by: Gavin Shan Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/powernv/eeh-powernv.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index d2f19821d71d..d12ea7b9fd47 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c @@ -412,11 +412,14 @@ static void *pnv_eeh_probe(struct pci_dn *pdn, void *data) * been set for the PE, we will set EEH_PE_CFG_BLOCKED for * that PE to block its config space. * + * Broadcom BCM5718 2-ports NICs (14e4:1656) * Broadcom Austin 4-ports NICs (14e4:1657) * Broadcom Shiner 4-ports 1G NICs (14e4:168a) * Broadcom Shiner 2-ports 10G NICs (14e4:168e) */ if ((pdn->vendor_id == PCI_VENDOR_ID_BROADCOM && + pdn->device_id == 0x1656) || + (pdn->vendor_id == PCI_VENDOR_ID_BROADCOM && pdn->device_id == 0x1657) || (pdn->vendor_id == PCI_VENDOR_ID_BROADCOM && pdn->device_id == 0x168a) || -- cgit v1.2.3-59-g8ed1b From ce4586063f1af780b1c6b7e344907e6f9c1ba59a Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Thu, 4 May 2017 08:15:10 +0200 Subject: um: Add missing NR_CPUS include We need linux/threads.h for that variable. Fixes: 8bba077066d6d0 ("um: Set number of CPUs") Signed-off-by: Richard Weinberger --- arch/um/os-Linux/skas/process.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 92f7ee14b10e..03b3c4cc7735 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -21,6 +21,7 @@ #include #include #include +#include int is_skas_winch(int pid, int fd, void *data) { -- cgit v1.2.3-59-g8ed1b From 35d2d5d490e2dc98ec07f899577b2a5451f413e8 Mon Sep 17 00:00:00 2001 From: Christoffer Dall Date: Thu, 4 May 2017 13:54:17 +0200 Subject: KVM: arm/arm64: Move shared files to virt/kvm/arm For some time now we have been having a lot of shared functionality between the arm and arm64 KVM support in arch/arm, which not only required a horrible inter-arch reference from the Makefile in arch/arm64/kvm, but also created confusion for newcomers to the code base, as was recently seen on the mailing list. Further, it causes confusion for things like cscope, which needs special attention to index specific shared files for arm64 from the arm tree. Move the shared files into virt/kvm/arm and move the trace points along with it. When moving the tracepoints we have to modify the way the vgic creates definitions of the trace points, so we take the chance to include the VGIC tracepoints in its very own special vgic trace.h file. Signed-off-by: Christoffer Dall --- arch/arm/kvm/Makefile | 7 +- arch/arm/kvm/arm.c | 1480 ---------------------------------- arch/arm/kvm/mmio.c | 217 ----- arch/arm/kvm/mmu.c | 1958 --------------------------------------------- arch/arm/kvm/perf.c | 68 -- arch/arm/kvm/psci.c | 332 -------- arch/arm/kvm/trace.h | 247 ------ arch/arm64/kvm/Makefile | 5 +- virt/kvm/arm/arm.c | 1480 ++++++++++++++++++++++++++++++++++ virt/kvm/arm/mmio.c | 217 +++++ virt/kvm/arm/mmu.c | 1958 +++++++++++++++++++++++++++++++++++++++++++++ virt/kvm/arm/perf.c | 68 ++ virt/kvm/arm/psci.c | 332 ++++++++ virt/kvm/arm/trace.h | 246 +++++- virt/kvm/arm/vgic/trace.h | 37 + virt/kvm/arm/vgic/vgic.c | 2 +- 16 files changed, 4335 insertions(+), 4319 deletions(-) delete mode 100644 arch/arm/kvm/arm.c delete mode 100644 arch/arm/kvm/mmio.c delete mode 100644 arch/arm/kvm/mmu.c delete mode 100644 arch/arm/kvm/perf.c delete mode 100644 arch/arm/kvm/psci.c create mode 100644 virt/kvm/arm/arm.c create mode 100644 virt/kvm/arm/mmio.c create mode 100644 virt/kvm/arm/mmu.c create mode 100644 virt/kvm/arm/perf.c create mode 100644 virt/kvm/arm/psci.c create mode 100644 virt/kvm/arm/vgic/trace.h (limited to 'arch') diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile index 7b3670c2ae7b..d9beee652d36 100644 --- a/arch/arm/kvm/Makefile +++ b/arch/arm/kvm/Makefile @@ -18,9 +18,12 @@ KVM := ../../../virt/kvm kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o $(KVM)/vfio.o obj-$(CONFIG_KVM_ARM_HOST) += hyp/ + obj-y += kvm-arm.o init.o interrupts.o -obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o -obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o vgic-v3-coproc.o +obj-y += handle_exit.o guest.o emulate.o reset.o +obj-y += coproc.o coproc_a15.o coproc_a7.o vgic-v3-coproc.o +obj-y += $(KVM)/arm/arm.o $(KVM)/arm/mmu.o $(KVM)/arm/mmio.o +obj-y += $(KVM)/arm/psci.o $(KVM)/arm/perf.o obj-y += $(KVM)/arm/aarch32.o obj-y += $(KVM)/arm/vgic/vgic.o diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c deleted file mode 100644 index 7941699a766d..000000000000 --- a/arch/arm/kvm/arm.c +++ /dev/null @@ -1,1480 +0,0 @@ -/* - * Copyright (C) 2012 - Virtual Open Systems and Columbia University - * Author: Christoffer Dall - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2, as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define CREATE_TRACE_POINTS -#include "trace.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef REQUIRES_VIRT -__asm__(".arch_extension virt"); -#endif - -static DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page); -static kvm_cpu_context_t __percpu *kvm_host_cpu_state; - -/* Per-CPU variable containing the currently running vcpu. */ -static DEFINE_PER_CPU(struct kvm_vcpu *, kvm_arm_running_vcpu); - -/* The VMID used in the VTTBR */ -static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1); -static u32 kvm_next_vmid; -static unsigned int kvm_vmid_bits __read_mostly; -static DEFINE_SPINLOCK(kvm_vmid_lock); - -static bool vgic_present; - -static DEFINE_PER_CPU(unsigned char, kvm_arm_hardware_enabled); - -static void kvm_arm_set_running_vcpu(struct kvm_vcpu *vcpu) -{ - BUG_ON(preemptible()); - __this_cpu_write(kvm_arm_running_vcpu, vcpu); -} - -/** - * kvm_arm_get_running_vcpu - get the vcpu running on the current CPU. - * Must be called from non-preemptible context - */ -struct kvm_vcpu *kvm_arm_get_running_vcpu(void) -{ - BUG_ON(preemptible()); - return __this_cpu_read(kvm_arm_running_vcpu); -} - -/** - * kvm_arm_get_running_vcpus - get the per-CPU array of currently running vcpus. - */ -struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void) -{ - return &kvm_arm_running_vcpu; -} - -int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu) -{ - return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE; -} - -int kvm_arch_hardware_setup(void) -{ - return 0; -} - -void kvm_arch_check_processor_compat(void *rtn) -{ - *(int *)rtn = 0; -} - - -/** - * kvm_arch_init_vm - initializes a VM data structure - * @kvm: pointer to the KVM struct - */ -int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) -{ - int ret, cpu; - - if (type) - return -EINVAL; - - kvm->arch.last_vcpu_ran = alloc_percpu(typeof(*kvm->arch.last_vcpu_ran)); - if (!kvm->arch.last_vcpu_ran) - return -ENOMEM; - - for_each_possible_cpu(cpu) - *per_cpu_ptr(kvm->arch.last_vcpu_ran, cpu) = -1; - - ret = kvm_alloc_stage2_pgd(kvm); - if (ret) - goto out_fail_alloc; - - ret = create_hyp_mappings(kvm, kvm + 1, PAGE_HYP); - if (ret) - goto out_free_stage2_pgd; - - kvm_vgic_early_init(kvm); - - /* Mark the initial VMID generation invalid */ - kvm->arch.vmid_gen = 0; - - /* The maximum number of VCPUs is limited by the host's GIC model */ - kvm->arch.max_vcpus = vgic_present ? - kvm_vgic_get_max_vcpus() : KVM_MAX_VCPUS; - - return ret; -out_free_stage2_pgd: - kvm_free_stage2_pgd(kvm); -out_fail_alloc: - free_percpu(kvm->arch.last_vcpu_ran); - kvm->arch.last_vcpu_ran = NULL; - return ret; -} - -bool kvm_arch_has_vcpu_debugfs(void) -{ - return false; -} - -int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu) -{ - return 0; -} - -int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf) -{ - return VM_FAULT_SIGBUS; -} - - -/** - * kvm_arch_destroy_vm - destroy the VM data structure - * @kvm: pointer to the KVM struct - */ -void kvm_arch_destroy_vm(struct kvm *kvm) -{ - int i; - - free_percpu(kvm->arch.last_vcpu_ran); - kvm->arch.last_vcpu_ran = NULL; - - for (i = 0; i < KVM_MAX_VCPUS; ++i) { - if (kvm->vcpus[i]) { - kvm_arch_vcpu_free(kvm->vcpus[i]); - kvm->vcpus[i] = NULL; - } - } - - kvm_vgic_destroy(kvm); -} - -int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) -{ - int r; - switch (ext) { - case KVM_CAP_IRQCHIP: - r = vgic_present; - break; - case KVM_CAP_IOEVENTFD: - case KVM_CAP_DEVICE_CTRL: - case KVM_CAP_USER_MEMORY: - case KVM_CAP_SYNC_MMU: - case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: - case KVM_CAP_ONE_REG: - case KVM_CAP_ARM_PSCI: - case KVM_CAP_ARM_PSCI_0_2: - case KVM_CAP_READONLY_MEM: - case KVM_CAP_MP_STATE: - case KVM_CAP_IMMEDIATE_EXIT: - r = 1; - break; - case KVM_CAP_COALESCED_MMIO: - r = KVM_COALESCED_MMIO_PAGE_OFFSET; - break; - case KVM_CAP_ARM_SET_DEVICE_ADDR: - r = 1; - break; - case KVM_CAP_NR_VCPUS: - r = num_online_cpus(); - break; - case KVM_CAP_MAX_VCPUS: - r = KVM_MAX_VCPUS; - break; - case KVM_CAP_NR_MEMSLOTS: - r = KVM_USER_MEM_SLOTS; - break; - case KVM_CAP_MSI_DEVID: - if (!kvm) - r = -EINVAL; - else - r = kvm->arch.vgic.msis_require_devid; - break; - case KVM_CAP_ARM_USER_IRQ: - /* - * 1: EL1_VTIMER, EL1_PTIMER, and PMU. - * (bump this number if adding more devices) - */ - r = 1; - break; - default: - r = kvm_arch_dev_ioctl_check_extension(kvm, ext); - break; - } - return r; -} - -long kvm_arch_dev_ioctl(struct file *filp, - unsigned int ioctl, unsigned long arg) -{ - return -EINVAL; -} - - -struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id) -{ - int err; - struct kvm_vcpu *vcpu; - - if (irqchip_in_kernel(kvm) && vgic_initialized(kvm)) { - err = -EBUSY; - goto out; - } - - if (id >= kvm->arch.max_vcpus) { - err = -EINVAL; - goto out; - } - - vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); - if (!vcpu) { - err = -ENOMEM; - goto out; - } - - err = kvm_vcpu_init(vcpu, kvm, id); - if (err) - goto free_vcpu; - - err = create_hyp_mappings(vcpu, vcpu + 1, PAGE_HYP); - if (err) - goto vcpu_uninit; - - return vcpu; -vcpu_uninit: - kvm_vcpu_uninit(vcpu); -free_vcpu: - kmem_cache_free(kvm_vcpu_cache, vcpu); -out: - return ERR_PTR(err); -} - -void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) -{ - kvm_vgic_vcpu_early_init(vcpu); -} - -void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu) -{ - kvm_mmu_free_memory_caches(vcpu); - kvm_timer_vcpu_terminate(vcpu); - kvm_vgic_vcpu_destroy(vcpu); - kvm_pmu_vcpu_destroy(vcpu); - kvm_vcpu_uninit(vcpu); - kmem_cache_free(kvm_vcpu_cache, vcpu); -} - -void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) -{ - kvm_arch_vcpu_free(vcpu); -} - -int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu) -{ - return kvm_timer_should_fire(vcpu_vtimer(vcpu)) || - kvm_timer_should_fire(vcpu_ptimer(vcpu)); -} - -void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu) -{ - kvm_timer_schedule(vcpu); -} - -void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) -{ - kvm_timer_unschedule(vcpu); -} - -int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) -{ - /* Force users to call KVM_ARM_VCPU_INIT */ - vcpu->arch.target = -1; - bitmap_zero(vcpu->arch.features, KVM_VCPU_MAX_FEATURES); - - /* Set up the timer */ - kvm_timer_vcpu_init(vcpu); - - kvm_arm_reset_debug_ptr(vcpu); - - return 0; -} - -void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) -{ - int *last_ran; - - last_ran = this_cpu_ptr(vcpu->kvm->arch.last_vcpu_ran); - - /* - * We might get preempted before the vCPU actually runs, but - * over-invalidation doesn't affect correctness. - */ - if (*last_ran != vcpu->vcpu_id) { - kvm_call_hyp(__kvm_tlb_flush_local_vmid, vcpu); - *last_ran = vcpu->vcpu_id; - } - - vcpu->cpu = cpu; - vcpu->arch.host_cpu_context = this_cpu_ptr(kvm_host_cpu_state); - - kvm_arm_set_running_vcpu(vcpu); - - kvm_vgic_load(vcpu); -} - -void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) -{ - kvm_vgic_put(vcpu); - - vcpu->cpu = -1; - - kvm_arm_set_running_vcpu(NULL); - kvm_timer_vcpu_put(vcpu); -} - -int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu, - struct kvm_mp_state *mp_state) -{ - if (vcpu->arch.power_off) - mp_state->mp_state = KVM_MP_STATE_STOPPED; - else - mp_state->mp_state = KVM_MP_STATE_RUNNABLE; - - return 0; -} - -int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, - struct kvm_mp_state *mp_state) -{ - switch (mp_state->mp_state) { - case KVM_MP_STATE_RUNNABLE: - vcpu->arch.power_off = false; - break; - case KVM_MP_STATE_STOPPED: - vcpu->arch.power_off = true; - break; - default: - return -EINVAL; - } - - return 0; -} - -/** - * kvm_arch_vcpu_runnable - determine if the vcpu can be scheduled - * @v: The VCPU pointer - * - * If the guest CPU is not waiting for interrupts or an interrupt line is - * asserted, the CPU is by definition runnable. - */ -int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) -{ - return ((!!v->arch.irq_lines || kvm_vgic_vcpu_pending_irq(v)) - && !v->arch.power_off && !v->arch.pause); -} - -/* Just ensure a guest exit from a particular CPU */ -static void exit_vm_noop(void *info) -{ -} - -void force_vm_exit(const cpumask_t *mask) -{ - preempt_disable(); - smp_call_function_many(mask, exit_vm_noop, NULL, true); - preempt_enable(); -} - -/** - * need_new_vmid_gen - check that the VMID is still valid - * @kvm: The VM's VMID to check - * - * return true if there is a new generation of VMIDs being used - * - * The hardware supports only 256 values with the value zero reserved for the - * host, so we check if an assigned value belongs to a previous generation, - * which which requires us to assign a new value. If we're the first to use a - * VMID for the new generation, we must flush necessary caches and TLBs on all - * CPUs. - */ -static bool need_new_vmid_gen(struct kvm *kvm) -{ - return unlikely(kvm->arch.vmid_gen != atomic64_read(&kvm_vmid_gen)); -} - -/** - * update_vttbr - Update the VTTBR with a valid VMID before the guest runs - * @kvm The guest that we are about to run - * - * Called from kvm_arch_vcpu_ioctl_run before entering the guest to ensure the - * VM has a valid VMID, otherwise assigns a new one and flushes corresponding - * caches and TLBs. - */ -static void update_vttbr(struct kvm *kvm) -{ - phys_addr_t pgd_phys; - u64 vmid; - - if (!need_new_vmid_gen(kvm)) - return; - - spin_lock(&kvm_vmid_lock); - - /* - * We need to re-check the vmid_gen here to ensure that if another vcpu - * already allocated a valid vmid for this vm, then this vcpu should - * use the same vmid. - */ - if (!need_new_vmid_gen(kvm)) { - spin_unlock(&kvm_vmid_lock); - return; - } - - /* First user of a new VMID generation? */ - if (unlikely(kvm_next_vmid == 0)) { - atomic64_inc(&kvm_vmid_gen); - kvm_next_vmid = 1; - - /* - * On SMP we know no other CPUs can use this CPU's or each - * other's VMID after force_vm_exit returns since the - * kvm_vmid_lock blocks them from reentry to the guest. - */ - force_vm_exit(cpu_all_mask); - /* - * Now broadcast TLB + ICACHE invalidation over the inner - * shareable domain to make sure all data structures are - * clean. - */ - kvm_call_hyp(__kvm_flush_vm_context); - } - - kvm->arch.vmid_gen = atomic64_read(&kvm_vmid_gen); - kvm->arch.vmid = kvm_next_vmid; - kvm_next_vmid++; - kvm_next_vmid &= (1 << kvm_vmid_bits) - 1; - - /* update vttbr to be used with the new vmid */ - pgd_phys = virt_to_phys(kvm->arch.pgd); - BUG_ON(pgd_phys & ~VTTBR_BADDR_MASK); - vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK(kvm_vmid_bits); - kvm->arch.vttbr = pgd_phys | vmid; - - spin_unlock(&kvm_vmid_lock); -} - -static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) -{ - struct kvm *kvm = vcpu->kvm; - int ret = 0; - - if (likely(vcpu->arch.has_run_once)) - return 0; - - vcpu->arch.has_run_once = true; - - /* - * Map the VGIC hardware resources before running a vcpu the first - * time on this VM. - */ - if (unlikely(irqchip_in_kernel(kvm) && !vgic_ready(kvm))) { - ret = kvm_vgic_map_resources(kvm); - if (ret) - return ret; - } - - ret = kvm_timer_enable(vcpu); - - return ret; -} - -bool kvm_arch_intc_initialized(struct kvm *kvm) -{ - return vgic_initialized(kvm); -} - -void kvm_arm_halt_guest(struct kvm *kvm) -{ - int i; - struct kvm_vcpu *vcpu; - - kvm_for_each_vcpu(i, vcpu, kvm) - vcpu->arch.pause = true; - kvm_make_all_cpus_request(kvm, KVM_REQ_VCPU_EXIT); -} - -void kvm_arm_halt_vcpu(struct kvm_vcpu *vcpu) -{ - vcpu->arch.pause = true; - kvm_vcpu_kick(vcpu); -} - -void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu) -{ - struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu); - - vcpu->arch.pause = false; - swake_up(wq); -} - -void kvm_arm_resume_guest(struct kvm *kvm) -{ - int i; - struct kvm_vcpu *vcpu; - - kvm_for_each_vcpu(i, vcpu, kvm) - kvm_arm_resume_vcpu(vcpu); -} - -static void vcpu_sleep(struct kvm_vcpu *vcpu) -{ - struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu); - - swait_event_interruptible(*wq, ((!vcpu->arch.power_off) && - (!vcpu->arch.pause))); -} - -static int kvm_vcpu_initialized(struct kvm_vcpu *vcpu) -{ - return vcpu->arch.target >= 0; -} - -/** - * kvm_arch_vcpu_ioctl_run - the main VCPU run function to execute guest code - * @vcpu: The VCPU pointer - * @run: The kvm_run structure pointer used for userspace state exchange - * - * This function is called through the VCPU_RUN ioctl called from user space. It - * will execute VM code in a loop until the time slice for the process is used - * or some emulation is needed from user space in which case the function will - * return with return value 0 and with the kvm_run structure filled in with the - * required data for the requested emulation. - */ -int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) -{ - int ret; - sigset_t sigsaved; - - if (unlikely(!kvm_vcpu_initialized(vcpu))) - return -ENOEXEC; - - ret = kvm_vcpu_first_run_init(vcpu); - if (ret) - return ret; - - if (run->exit_reason == KVM_EXIT_MMIO) { - ret = kvm_handle_mmio_return(vcpu, vcpu->run); - if (ret) - return ret; - } - - if (run->immediate_exit) - return -EINTR; - - if (vcpu->sigset_active) - sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved); - - ret = 1; - run->exit_reason = KVM_EXIT_UNKNOWN; - while (ret > 0) { - /* - * Check conditions before entering the guest - */ - cond_resched(); - - update_vttbr(vcpu->kvm); - - if (vcpu->arch.power_off || vcpu->arch.pause) - vcpu_sleep(vcpu); - - /* - * Preparing the interrupts to be injected also - * involves poking the GIC, which must be done in a - * non-preemptible context. - */ - preempt_disable(); - - kvm_pmu_flush_hwstate(vcpu); - - kvm_timer_flush_hwstate(vcpu); - kvm_vgic_flush_hwstate(vcpu); - - local_irq_disable(); - - /* - * If we have a singal pending, or need to notify a userspace - * irqchip about timer or PMU level changes, then we exit (and - * update the timer level state in kvm_timer_update_run - * below). - */ - if (signal_pending(current) || - kvm_timer_should_notify_user(vcpu) || - kvm_pmu_should_notify_user(vcpu)) { - ret = -EINTR; - run->exit_reason = KVM_EXIT_INTR; - } - - if (ret <= 0 || need_new_vmid_gen(vcpu->kvm) || - vcpu->arch.power_off || vcpu->arch.pause) { - local_irq_enable(); - kvm_pmu_sync_hwstate(vcpu); - kvm_timer_sync_hwstate(vcpu); - kvm_vgic_sync_hwstate(vcpu); - preempt_enable(); - continue; - } - - kvm_arm_setup_debug(vcpu); - - /************************************************************** - * Enter the guest - */ - trace_kvm_entry(*vcpu_pc(vcpu)); - guest_enter_irqoff(); - vcpu->mode = IN_GUEST_MODE; - - ret = kvm_call_hyp(__kvm_vcpu_run, vcpu); - - vcpu->mode = OUTSIDE_GUEST_MODE; - vcpu->stat.exits++; - /* - * Back from guest - *************************************************************/ - - kvm_arm_clear_debug(vcpu); - - /* - * We may have taken a host interrupt in HYP mode (ie - * while executing the guest). This interrupt is still - * pending, as we haven't serviced it yet! - * - * We're now back in SVC mode, with interrupts - * disabled. Enabling the interrupts now will have - * the effect of taking the interrupt again, in SVC - * mode this time. - */ - local_irq_enable(); - - /* - * We do local_irq_enable() before calling guest_exit() so - * that if a timer interrupt hits while running the guest we - * account that tick as being spent in the guest. We enable - * preemption after calling guest_exit() so that if we get - * preempted we make sure ticks after that is not counted as - * guest time. - */ - guest_exit(); - trace_kvm_exit(ret, kvm_vcpu_trap_get_class(vcpu), *vcpu_pc(vcpu)); - - /* - * We must sync the PMU and timer state before the vgic state so - * that the vgic can properly sample the updated state of the - * interrupt line. - */ - kvm_pmu_sync_hwstate(vcpu); - kvm_timer_sync_hwstate(vcpu); - - kvm_vgic_sync_hwstate(vcpu); - - preempt_enable(); - - ret = handle_exit(vcpu, run, ret); - } - - /* Tell userspace about in-kernel device output levels */ - if (unlikely(!irqchip_in_kernel(vcpu->kvm))) { - kvm_timer_update_run(vcpu); - kvm_pmu_update_run(vcpu); - } - - if (vcpu->sigset_active) - sigprocmask(SIG_SETMASK, &sigsaved, NULL); - return ret; -} - -static int vcpu_interrupt_line(struct kvm_vcpu *vcpu, int number, bool level) -{ - int bit_index; - bool set; - unsigned long *ptr; - - if (number == KVM_ARM_IRQ_CPU_IRQ) - bit_index = __ffs(HCR_VI); - else /* KVM_ARM_IRQ_CPU_FIQ */ - bit_index = __ffs(HCR_VF); - - ptr = (unsigned long *)&vcpu->arch.irq_lines; - if (level) - set = test_and_set_bit(bit_index, ptr); - else - set = test_and_clear_bit(bit_index, ptr); - - /* - * If we didn't change anything, no need to wake up or kick other CPUs - */ - if (set == level) - return 0; - - /* - * The vcpu irq_lines field was updated, wake up sleeping VCPUs and - * trigger a world-switch round on the running physical CPU to set the - * virtual IRQ/FIQ fields in the HCR appropriately. - */ - kvm_vcpu_kick(vcpu); - - return 0; -} - -int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level, - bool line_status) -{ - u32 irq = irq_level->irq; - unsigned int irq_type, vcpu_idx, irq_num; - int nrcpus = atomic_read(&kvm->online_vcpus); - struct kvm_vcpu *vcpu = NULL; - bool level = irq_level->level; - - irq_type = (irq >> KVM_ARM_IRQ_TYPE_SHIFT) & KVM_ARM_IRQ_TYPE_MASK; - vcpu_idx = (irq >> KVM_ARM_IRQ_VCPU_SHIFT) & KVM_ARM_IRQ_VCPU_MASK; - irq_num = (irq >> KVM_ARM_IRQ_NUM_SHIFT) & KVM_ARM_IRQ_NUM_MASK; - - trace_kvm_irq_line(irq_type, vcpu_idx, irq_num, irq_level->level); - - switch (irq_type) { - case KVM_ARM_IRQ_TYPE_CPU: - if (irqchip_in_kernel(kvm)) - return -ENXIO; - - if (vcpu_idx >= nrcpus) - return -EINVAL; - - vcpu = kvm_get_vcpu(kvm, vcpu_idx); - if (!vcpu) - return -EINVAL; - - if (irq_num > KVM_ARM_IRQ_CPU_FIQ) - return -EINVAL; - - return vcpu_interrupt_line(vcpu, irq_num, level); - case KVM_ARM_IRQ_TYPE_PPI: - if (!irqchip_in_kernel(kvm)) - return -ENXIO; - - if (vcpu_idx >= nrcpus) - return -EINVAL; - - vcpu = kvm_get_vcpu(kvm, vcpu_idx); - if (!vcpu) - return -EINVAL; - - if (irq_num < VGIC_NR_SGIS || irq_num >= VGIC_NR_PRIVATE_IRQS) - return -EINVAL; - - return kvm_vgic_inject_irq(kvm, vcpu->vcpu_id, irq_num, level); - case KVM_ARM_IRQ_TYPE_SPI: - if (!irqchip_in_kernel(kvm)) - return -ENXIO; - - if (irq_num < VGIC_NR_PRIVATE_IRQS) - return -EINVAL; - - return kvm_vgic_inject_irq(kvm, 0, irq_num, level); - } - - return -EINVAL; -} - -static int kvm_vcpu_set_target(struct kvm_vcpu *vcpu, - const struct kvm_vcpu_init *init) -{ - unsigned int i; - int phys_target = kvm_target_cpu(); - - if (init->target != phys_target) - return -EINVAL; - - /* - * Secondary and subsequent calls to KVM_ARM_VCPU_INIT must - * use the same target. - */ - if (vcpu->arch.target != -1 && vcpu->arch.target != init->target) - return -EINVAL; - - /* -ENOENT for unknown features, -EINVAL for invalid combinations. */ - for (i = 0; i < sizeof(init->features) * 8; i++) { - bool set = (init->features[i / 32] & (1 << (i % 32))); - - if (set && i >= KVM_VCPU_MAX_FEATURES) - return -ENOENT; - - /* - * Secondary and subsequent calls to KVM_ARM_VCPU_INIT must - * use the same feature set. - */ - if (vcpu->arch.target != -1 && i < KVM_VCPU_MAX_FEATURES && - test_bit(i, vcpu->arch.features) != set) - return -EINVAL; - - if (set) - set_bit(i, vcpu->arch.features); - } - - vcpu->arch.target = phys_target; - - /* Now we know what it is, we can reset it. */ - return kvm_reset_vcpu(vcpu); -} - - -static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu, - struct kvm_vcpu_init *init) -{ - int ret; - - ret = kvm_vcpu_set_target(vcpu, init); - if (ret) - return ret; - - /* - * Ensure a rebooted VM will fault in RAM pages and detect if the - * guest MMU is turned off and flush the caches as needed. - */ - if (vcpu->arch.has_run_once) - stage2_unmap_vm(vcpu->kvm); - - vcpu_reset_hcr(vcpu); - - /* - * Handle the "start in power-off" case. - */ - if (test_bit(KVM_ARM_VCPU_POWER_OFF, vcpu->arch.features)) - vcpu->arch.power_off = true; - else - vcpu->arch.power_off = false; - - return 0; -} - -static int kvm_arm_vcpu_set_attr(struct kvm_vcpu *vcpu, - struct kvm_device_attr *attr) -{ - int ret = -ENXIO; - - switch (attr->group) { - default: - ret = kvm_arm_vcpu_arch_set_attr(vcpu, attr); - break; - } - - return ret; -} - -static int kvm_arm_vcpu_get_attr(struct kvm_vcpu *vcpu, - struct kvm_device_attr *attr) -{ - int ret = -ENXIO; - - switch (attr->group) { - default: - ret = kvm_arm_vcpu_arch_get_attr(vcpu, attr); - break; - } - - return ret; -} - -static int kvm_arm_vcpu_has_attr(struct kvm_vcpu *vcpu, - struct kvm_device_attr *attr) -{ - int ret = -ENXIO; - - switch (attr->group) { - default: - ret = kvm_arm_vcpu_arch_has_attr(vcpu, attr); - break; - } - - return ret; -} - -long kvm_arch_vcpu_ioctl(struct file *filp, - unsigned int ioctl, unsigned long arg) -{ - struct kvm_vcpu *vcpu = filp->private_data; - void __user *argp = (void __user *)arg; - struct kvm_device_attr attr; - - switch (ioctl) { - case KVM_ARM_VCPU_INIT: { - struct kvm_vcpu_init init; - - if (copy_from_user(&init, argp, sizeof(init))) - return -EFAULT; - - return kvm_arch_vcpu_ioctl_vcpu_init(vcpu, &init); - } - case KVM_SET_ONE_REG: - case KVM_GET_ONE_REG: { - struct kvm_one_reg reg; - - if (unlikely(!kvm_vcpu_initialized(vcpu))) - return -ENOEXEC; - - if (copy_from_user(®, argp, sizeof(reg))) - return -EFAULT; - if (ioctl == KVM_SET_ONE_REG) - return kvm_arm_set_reg(vcpu, ®); - else - return kvm_arm_get_reg(vcpu, ®); - } - case KVM_GET_REG_LIST: { - struct kvm_reg_list __user *user_list = argp; - struct kvm_reg_list reg_list; - unsigned n; - - if (unlikely(!kvm_vcpu_initialized(vcpu))) - return -ENOEXEC; - - if (copy_from_user(®_list, user_list, sizeof(reg_list))) - return -EFAULT; - n = reg_list.n; - reg_list.n = kvm_arm_num_regs(vcpu); - if (copy_to_user(user_list, ®_list, sizeof(reg_list))) - return -EFAULT; - if (n < reg_list.n) - return -E2BIG; - return kvm_arm_copy_reg_indices(vcpu, user_list->reg); - } - case KVM_SET_DEVICE_ATTR: { - if (copy_from_user(&attr, argp, sizeof(attr))) - return -EFAULT; - return kvm_arm_vcpu_set_attr(vcpu, &attr); - } - case KVM_GET_DEVICE_ATTR: { - if (copy_from_user(&attr, argp, sizeof(attr))) - return -EFAULT; - return kvm_arm_vcpu_get_attr(vcpu, &attr); - } - case KVM_HAS_DEVICE_ATTR: { - if (copy_from_user(&attr, argp, sizeof(attr))) - return -EFAULT; - return kvm_arm_vcpu_has_attr(vcpu, &attr); - } - default: - return -EINVAL; - } -} - -/** - * kvm_vm_ioctl_get_dirty_log - get and clear the log of dirty pages in a slot - * @kvm: kvm instance - * @log: slot id and address to which we copy the log - * - * Steps 1-4 below provide general overview of dirty page logging. See - * kvm_get_dirty_log_protect() function description for additional details. - * - * We call kvm_get_dirty_log_protect() to handle steps 1-3, upon return we - * always flush the TLB (step 4) even if previous step failed and the dirty - * bitmap may be corrupt. Regardless of previous outcome the KVM logging API - * does not preclude user space subsequent dirty log read. Flushing TLB ensures - * writes will be marked dirty for next log read. - * - * 1. Take a snapshot of the bit and clear it if needed. - * 2. Write protect the corresponding page. - * 3. Copy the snapshot to the userspace. - * 4. Flush TLB's if needed. - */ -int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log) -{ - bool is_dirty = false; - int r; - - mutex_lock(&kvm->slots_lock); - - r = kvm_get_dirty_log_protect(kvm, log, &is_dirty); - - if (is_dirty) - kvm_flush_remote_tlbs(kvm); - - mutex_unlock(&kvm->slots_lock); - return r; -} - -static int kvm_vm_ioctl_set_device_addr(struct kvm *kvm, - struct kvm_arm_device_addr *dev_addr) -{ - unsigned long dev_id, type; - - dev_id = (dev_addr->id & KVM_ARM_DEVICE_ID_MASK) >> - KVM_ARM_DEVICE_ID_SHIFT; - type = (dev_addr->id & KVM_ARM_DEVICE_TYPE_MASK) >> - KVM_ARM_DEVICE_TYPE_SHIFT; - - switch (dev_id) { - case KVM_ARM_DEVICE_VGIC_V2: - if (!vgic_present) - return -ENXIO; - return kvm_vgic_addr(kvm, type, &dev_addr->addr, true); - default: - return -ENODEV; - } -} - -long kvm_arch_vm_ioctl(struct file *filp, - unsigned int ioctl, unsigned long arg) -{ - struct kvm *kvm = filp->private_data; - void __user *argp = (void __user *)arg; - - switch (ioctl) { - case KVM_CREATE_IRQCHIP: { - int ret; - if (!vgic_present) - return -ENXIO; - mutex_lock(&kvm->lock); - ret = kvm_vgic_create(kvm, KVM_DEV_TYPE_ARM_VGIC_V2); - mutex_unlock(&kvm->lock); - return ret; - } - case KVM_ARM_SET_DEVICE_ADDR: { - struct kvm_arm_device_addr dev_addr; - - if (copy_from_user(&dev_addr, argp, sizeof(dev_addr))) - return -EFAULT; - return kvm_vm_ioctl_set_device_addr(kvm, &dev_addr); - } - case KVM_ARM_PREFERRED_TARGET: { - int err; - struct kvm_vcpu_init init; - - err = kvm_vcpu_preferred_target(&init); - if (err) - return err; - - if (copy_to_user(argp, &init, sizeof(init))) - return -EFAULT; - - return 0; - } - default: - return -EINVAL; - } -} - -static void cpu_init_hyp_mode(void *dummy) -{ - phys_addr_t pgd_ptr; - unsigned long hyp_stack_ptr; - unsigned long stack_page; - unsigned long vector_ptr; - - /* Switch from the HYP stub to our own HYP init vector */ - __hyp_set_vectors(kvm_get_idmap_vector()); - - pgd_ptr = kvm_mmu_get_httbr(); - stack_page = __this_cpu_read(kvm_arm_hyp_stack_page); - hyp_stack_ptr = stack_page + PAGE_SIZE; - vector_ptr = (unsigned long)kvm_ksym_ref(__kvm_hyp_vector); - - __cpu_init_hyp_mode(pgd_ptr, hyp_stack_ptr, vector_ptr); - __cpu_init_stage2(); - - if (is_kernel_in_hyp_mode()) - kvm_timer_init_vhe(); - - kvm_arm_init_debug(); -} - -static void cpu_hyp_reset(void) -{ - if (!is_kernel_in_hyp_mode()) - __hyp_reset_vectors(); -} - -static void cpu_hyp_reinit(void) -{ - cpu_hyp_reset(); - - if (is_kernel_in_hyp_mode()) { - /* - * __cpu_init_stage2() is safe to call even if the PM - * event was cancelled before the CPU was reset. - */ - __cpu_init_stage2(); - } else { - cpu_init_hyp_mode(NULL); - } -} - -static void _kvm_arch_hardware_enable(void *discard) -{ - if (!__this_cpu_read(kvm_arm_hardware_enabled)) { - cpu_hyp_reinit(); - __this_cpu_write(kvm_arm_hardware_enabled, 1); - } -} - -int kvm_arch_hardware_enable(void) -{ - _kvm_arch_hardware_enable(NULL); - return 0; -} - -static void _kvm_arch_hardware_disable(void *discard) -{ - if (__this_cpu_read(kvm_arm_hardware_enabled)) { - cpu_hyp_reset(); - __this_cpu_write(kvm_arm_hardware_enabled, 0); - } -} - -void kvm_arch_hardware_disable(void) -{ - _kvm_arch_hardware_disable(NULL); -} - -#ifdef CONFIG_CPU_PM -static int hyp_init_cpu_pm_notifier(struct notifier_block *self, - unsigned long cmd, - void *v) -{ - /* - * kvm_arm_hardware_enabled is left with its old value over - * PM_ENTER->PM_EXIT. It is used to indicate PM_EXIT should - * re-enable hyp. - */ - switch (cmd) { - case CPU_PM_ENTER: - if (__this_cpu_read(kvm_arm_hardware_enabled)) - /* - * don't update kvm_arm_hardware_enabled here - * so that the hardware will be re-enabled - * when we resume. See below. - */ - cpu_hyp_reset(); - - return NOTIFY_OK; - case CPU_PM_EXIT: - if (__this_cpu_read(kvm_arm_hardware_enabled)) - /* The hardware was enabled before suspend. */ - cpu_hyp_reinit(); - - return NOTIFY_OK; - - default: - return NOTIFY_DONE; - } -} - -static struct notifier_block hyp_init_cpu_pm_nb = { - .notifier_call = hyp_init_cpu_pm_notifier, -}; - -static void __init hyp_cpu_pm_init(void) -{ - cpu_pm_register_notifier(&hyp_init_cpu_pm_nb); -} -static void __init hyp_cpu_pm_exit(void) -{ - cpu_pm_unregister_notifier(&hyp_init_cpu_pm_nb); -} -#else -static inline void hyp_cpu_pm_init(void) -{ -} -static inline void hyp_cpu_pm_exit(void) -{ -} -#endif - -static void teardown_common_resources(void) -{ - free_percpu(kvm_host_cpu_state); -} - -static int init_common_resources(void) -{ - kvm_host_cpu_state = alloc_percpu(kvm_cpu_context_t); - if (!kvm_host_cpu_state) { - kvm_err("Cannot allocate host CPU state\n"); - return -ENOMEM; - } - - /* set size of VMID supported by CPU */ - kvm_vmid_bits = kvm_get_vmid_bits(); - kvm_info("%d-bit VMID\n", kvm_vmid_bits); - - return 0; -} - -static int init_subsystems(void) -{ - int err = 0; - - /* - * Enable hardware so that subsystem initialisation can access EL2. - */ - on_each_cpu(_kvm_arch_hardware_enable, NULL, 1); - - /* - * Register CPU lower-power notifier - */ - hyp_cpu_pm_init(); - - /* - * Init HYP view of VGIC - */ - err = kvm_vgic_hyp_init(); - switch (err) { - case 0: - vgic_present = true; - break; - case -ENODEV: - case -ENXIO: - vgic_present = false; - err = 0; - break; - default: - goto out; - } - - /* - * Init HYP architected timer support - */ - err = kvm_timer_hyp_init(); - if (err) - goto out; - - kvm_perf_init(); - kvm_coproc_table_init(); - -out: - on_each_cpu(_kvm_arch_hardware_disable, NULL, 1); - - return err; -} - -static void teardown_hyp_mode(void) -{ - int cpu; - - if (is_kernel_in_hyp_mode()) - return; - - free_hyp_pgds(); - for_each_possible_cpu(cpu) - free_page(per_cpu(kvm_arm_hyp_stack_page, cpu)); - hyp_cpu_pm_exit(); -} - -static int init_vhe_mode(void) -{ - kvm_info("VHE mode initialized successfully\n"); - return 0; -} - -/** - * Inits Hyp-mode on all online CPUs - */ -static int init_hyp_mode(void) -{ - int cpu; - int err = 0; - - /* - * Allocate Hyp PGD and setup Hyp identity mapping - */ - err = kvm_mmu_init(); - if (err) - goto out_err; - - /* - * Allocate stack pages for Hypervisor-mode - */ - for_each_possible_cpu(cpu) { - unsigned long stack_page; - - stack_page = __get_free_page(GFP_KERNEL); - if (!stack_page) { - err = -ENOMEM; - goto out_err; - } - - per_cpu(kvm_arm_hyp_stack_page, cpu) = stack_page; - } - - /* - * Map the Hyp-code called directly from the host - */ - err = create_hyp_mappings(kvm_ksym_ref(__hyp_text_start), - kvm_ksym_ref(__hyp_text_end), PAGE_HYP_EXEC); - if (err) { - kvm_err("Cannot map world-switch code\n"); - goto out_err; - } - - err = create_hyp_mappings(kvm_ksym_ref(__start_rodata), - kvm_ksym_ref(__end_rodata), PAGE_HYP_RO); - if (err) { - kvm_err("Cannot map rodata section\n"); - goto out_err; - } - - err = create_hyp_mappings(kvm_ksym_ref(__bss_start), - kvm_ksym_ref(__bss_stop), PAGE_HYP_RO); - if (err) { - kvm_err("Cannot map bss section\n"); - goto out_err; - } - - /* - * Map the Hyp stack pages - */ - for_each_possible_cpu(cpu) { - char *stack_page = (char *)per_cpu(kvm_arm_hyp_stack_page, cpu); - err = create_hyp_mappings(stack_page, stack_page + PAGE_SIZE, - PAGE_HYP); - - if (err) { - kvm_err("Cannot map hyp stack\n"); - goto out_err; - } - } - - for_each_possible_cpu(cpu) { - kvm_cpu_context_t *cpu_ctxt; - - cpu_ctxt = per_cpu_ptr(kvm_host_cpu_state, cpu); - err = create_hyp_mappings(cpu_ctxt, cpu_ctxt + 1, PAGE_HYP); - - if (err) { - kvm_err("Cannot map host CPU state: %d\n", err); - goto out_err; - } - } - - kvm_info("Hyp mode initialized successfully\n"); - - return 0; - -out_err: - teardown_hyp_mode(); - kvm_err("error initializing Hyp mode: %d\n", err); - return err; -} - -static void check_kvm_target_cpu(void *ret) -{ - *(int *)ret = kvm_target_cpu(); -} - -struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr) -{ - struct kvm_vcpu *vcpu; - int i; - - mpidr &= MPIDR_HWID_BITMASK; - kvm_for_each_vcpu(i, vcpu, kvm) { - if (mpidr == kvm_vcpu_get_mpidr_aff(vcpu)) - return vcpu; - } - return NULL; -} - -/** - * Initialize Hyp-mode and memory mappings on all CPUs. - */ -int kvm_arch_init(void *opaque) -{ - int err; - int ret, cpu; - - if (!is_hyp_mode_available()) { - kvm_err("HYP mode not available\n"); - return -ENODEV; - } - - for_each_online_cpu(cpu) { - smp_call_function_single(cpu, check_kvm_target_cpu, &ret, 1); - if (ret < 0) { - kvm_err("Error, CPU %d not supported!\n", cpu); - return -ENODEV; - } - } - - err = init_common_resources(); - if (err) - return err; - - if (is_kernel_in_hyp_mode()) - err = init_vhe_mode(); - else - err = init_hyp_mode(); - if (err) - goto out_err; - - err = init_subsystems(); - if (err) - goto out_hyp; - - return 0; - -out_hyp: - teardown_hyp_mode(); -out_err: - teardown_common_resources(); - return err; -} - -/* NOP: Compiling as a module not supported */ -void kvm_arch_exit(void) -{ - kvm_perf_teardown(); -} - -static int arm_init(void) -{ - int rc = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE); - return rc; -} - -module_init(arm_init); diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c deleted file mode 100644 index b6e715fd3c90..000000000000 --- a/arch/arm/kvm/mmio.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (C) 2012 - Virtual Open Systems and Columbia University - * Author: Christoffer Dall - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2, as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include -#include -#include -#include - -#include "trace.h" - -void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data) -{ - void *datap = NULL; - union { - u8 byte; - u16 hword; - u32 word; - u64 dword; - } tmp; - - switch (len) { - case 1: - tmp.byte = data; - datap = &tmp.byte; - break; - case 2: - tmp.hword = data; - datap = &tmp.hword; - break; - case 4: - tmp.word = data; - datap = &tmp.word; - break; - case 8: - tmp.dword = data; - datap = &tmp.dword; - break; - } - - memcpy(buf, datap, len); -} - -unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len) -{ - unsigned long data = 0; - union { - u16 hword; - u32 word; - u64 dword; - } tmp; - - switch (len) { - case 1: - data = *(u8 *)buf; - break; - case 2: - memcpy(&tmp.hword, buf, len); - data = tmp.hword; - break; - case 4: - memcpy(&tmp.word, buf, len); - data = tmp.word; - break; - case 8: - memcpy(&tmp.dword, buf, len); - data = tmp.dword; - break; - } - - return data; -} - -/** - * kvm_handle_mmio_return -- Handle MMIO loads after user space emulation - * or in-kernel IO emulation - * - * @vcpu: The VCPU pointer - * @run: The VCPU run struct containing the mmio data - */ -int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run) -{ - unsigned long data; - unsigned int len; - int mask; - - if (!run->mmio.is_write) { - len = run->mmio.len; - if (len > sizeof(unsigned long)) - return -EINVAL; - - data = kvm_mmio_read_buf(run->mmio.data, len); - - if (vcpu->arch.mmio_decode.sign_extend && - len < sizeof(unsigned long)) { - mask = 1U << ((len * 8) - 1); - data = (data ^ mask) - mask; - } - - trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr, - data); - data = vcpu_data_host_to_guest(vcpu, data, len); - vcpu_set_reg(vcpu, vcpu->arch.mmio_decode.rt, data); - } - - return 0; -} - -static int decode_hsr(struct kvm_vcpu *vcpu, bool *is_write, int *len) -{ - unsigned long rt; - int access_size; - bool sign_extend; - - if (kvm_vcpu_dabt_iss1tw(vcpu)) { - /* page table accesses IO mem: tell guest to fix its TTBR */ - kvm_inject_dabt(vcpu, kvm_vcpu_get_hfar(vcpu)); - return 1; - } - - access_size = kvm_vcpu_dabt_get_as(vcpu); - if (unlikely(access_size < 0)) - return access_size; - - *is_write = kvm_vcpu_dabt_iswrite(vcpu); - sign_extend = kvm_vcpu_dabt_issext(vcpu); - rt = kvm_vcpu_dabt_get_rd(vcpu); - - *len = access_size; - vcpu->arch.mmio_decode.sign_extend = sign_extend; - vcpu->arch.mmio_decode.rt = rt; - - /* - * The MMIO instruction is emulated and should not be re-executed - * in the guest. - */ - kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu)); - return 0; -} - -int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, - phys_addr_t fault_ipa) -{ - unsigned long data; - unsigned long rt; - int ret; - bool is_write; - int len; - u8 data_buf[8]; - - /* - * Prepare MMIO operation. First decode the syndrome data we get - * from the CPU. Then try if some in-kernel emulation feels - * responsible, otherwise let user space do its magic. - */ - if (kvm_vcpu_dabt_isvalid(vcpu)) { - ret = decode_hsr(vcpu, &is_write, &len); - if (ret) - return ret; - } else { - kvm_err("load/store instruction decoding not implemented\n"); - return -ENOSYS; - } - - rt = vcpu->arch.mmio_decode.rt; - - if (is_write) { - data = vcpu_data_guest_to_host(vcpu, vcpu_get_reg(vcpu, rt), - len); - - trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, len, fault_ipa, data); - kvm_mmio_write_buf(data_buf, len, data); - - ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, fault_ipa, len, - data_buf); - } else { - trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, len, - fault_ipa, 0); - - ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, fault_ipa, len, - data_buf); - } - - /* Now prepare kvm_run for the potential return to userland. */ - run->mmio.is_write = is_write; - run->mmio.phys_addr = fault_ipa; - run->mmio.len = len; - - if (!ret) { - /* We handled the access successfully in the kernel. */ - if (!is_write) - memcpy(run->mmio.data, data_buf, len); - vcpu->stat.mmio_exit_kernel++; - kvm_handle_mmio_return(vcpu, run); - return 1; - } - - if (is_write) - memcpy(run->mmio.data, data_buf, len); - vcpu->stat.mmio_exit_user++; - run->exit_reason = KVM_EXIT_MMIO; - return 0; -} diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c deleted file mode 100644 index efb4335aa5c4..000000000000 --- a/arch/arm/kvm/mmu.c +++ /dev/null @@ -1,1958 +0,0 @@ -/* - * Copyright (C) 2012 - Virtual Open Systems and Columbia University - * Author: Christoffer Dall - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2, as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "trace.h" - -static pgd_t *boot_hyp_pgd; -static pgd_t *hyp_pgd; -static pgd_t *merged_hyp_pgd; -static DEFINE_MUTEX(kvm_hyp_pgd_mutex); - -static unsigned long hyp_idmap_start; -static unsigned long hyp_idmap_end; -static phys_addr_t hyp_idmap_vector; - -#define S2_PGD_SIZE (PTRS_PER_S2_PGD * sizeof(pgd_t)) -#define hyp_pgd_order get_order(PTRS_PER_PGD * sizeof(pgd_t)) - -#define KVM_S2PTE_FLAG_IS_IOMAP (1UL << 0) -#define KVM_S2_FLAG_LOGGING_ACTIVE (1UL << 1) - -static bool memslot_is_logging(struct kvm_memory_slot *memslot) -{ - return memslot->dirty_bitmap && !(memslot->flags & KVM_MEM_READONLY); -} - -/** - * kvm_flush_remote_tlbs() - flush all VM TLB entries for v7/8 - * @kvm: pointer to kvm structure. - * - * Interface to HYP function to flush all VM TLB entries - */ -void kvm_flush_remote_tlbs(struct kvm *kvm) -{ - kvm_call_hyp(__kvm_tlb_flush_vmid, kvm); -} - -static void kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa) -{ - kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, kvm, ipa); -} - -/* - * D-Cache management functions. They take the page table entries by - * value, as they are flushing the cache using the kernel mapping (or - * kmap on 32bit). - */ -static void kvm_flush_dcache_pte(pte_t pte) -{ - __kvm_flush_dcache_pte(pte); -} - -static void kvm_flush_dcache_pmd(pmd_t pmd) -{ - __kvm_flush_dcache_pmd(pmd); -} - -static void kvm_flush_dcache_pud(pud_t pud) -{ - __kvm_flush_dcache_pud(pud); -} - -static bool kvm_is_device_pfn(unsigned long pfn) -{ - return !pfn_valid(pfn); -} - -/** - * stage2_dissolve_pmd() - clear and flush huge PMD entry - * @kvm: pointer to kvm structure. - * @addr: IPA - * @pmd: pmd pointer for IPA - * - * Function clears a PMD entry, flushes addr 1st and 2nd stage TLBs. Marks all - * pages in the range dirty. - */ -static void stage2_dissolve_pmd(struct kvm *kvm, phys_addr_t addr, pmd_t *pmd) -{ - if (!pmd_thp_or_huge(*pmd)) - return; - - pmd_clear(pmd); - kvm_tlb_flush_vmid_ipa(kvm, addr); - put_page(virt_to_page(pmd)); -} - -static int mmu_topup_memory_cache(struct kvm_mmu_memory_cache *cache, - int min, int max) -{ - void *page; - - BUG_ON(max > KVM_NR_MEM_OBJS); - if (cache->nobjs >= min) - return 0; - while (cache->nobjs < max) { - page = (void *)__get_free_page(PGALLOC_GFP); - if (!page) - return -ENOMEM; - cache->objects[cache->nobjs++] = page; - } - return 0; -} - -static void mmu_free_memory_cache(struct kvm_mmu_memory_cache *mc) -{ - while (mc->nobjs) - free_page((unsigned long)mc->objects[--mc->nobjs]); -} - -static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc) -{ - void *p; - - BUG_ON(!mc || !mc->nobjs); - p = mc->objects[--mc->nobjs]; - return p; -} - -static void clear_stage2_pgd_entry(struct kvm *kvm, pgd_t *pgd, phys_addr_t addr) -{ - pud_t *pud_table __maybe_unused = stage2_pud_offset(pgd, 0UL); - stage2_pgd_clear(pgd); - kvm_tlb_flush_vmid_ipa(kvm, addr); - stage2_pud_free(pud_table); - put_page(virt_to_page(pgd)); -} - -static void clear_stage2_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr) -{ - pmd_t *pmd_table __maybe_unused = stage2_pmd_offset(pud, 0); - VM_BUG_ON(stage2_pud_huge(*pud)); - stage2_pud_clear(pud); - kvm_tlb_flush_vmid_ipa(kvm, addr); - stage2_pmd_free(pmd_table); - put_page(virt_to_page(pud)); -} - -static void clear_stage2_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr) -{ - pte_t *pte_table = pte_offset_kernel(pmd, 0); - VM_BUG_ON(pmd_thp_or_huge(*pmd)); - pmd_clear(pmd); - kvm_tlb_flush_vmid_ipa(kvm, addr); - pte_free_kernel(NULL, pte_table); - put_page(virt_to_page(pmd)); -} - -/* - * Unmapping vs dcache management: - * - * If a guest maps certain memory pages as uncached, all writes will - * bypass the data cache and go directly to RAM. However, the CPUs - * can still speculate reads (not writes) and fill cache lines with - * data. - * - * Those cache lines will be *clean* cache lines though, so a - * clean+invalidate operation is equivalent to an invalidate - * operation, because no cache lines are marked dirty. - * - * Those clean cache lines could be filled prior to an uncached write - * by the guest, and the cache coherent IO subsystem would therefore - * end up writing old data to disk. - * - * This is why right after unmapping a page/section and invalidating - * the corresponding TLBs, we call kvm_flush_dcache_p*() to make sure - * the IO subsystem will never hit in the cache. - */ -static void unmap_stage2_ptes(struct kvm *kvm, pmd_t *pmd, - phys_addr_t addr, phys_addr_t end) -{ - phys_addr_t start_addr = addr; - pte_t *pte, *start_pte; - - start_pte = pte = pte_offset_kernel(pmd, addr); - do { - if (!pte_none(*pte)) { - pte_t old_pte = *pte; - - kvm_set_pte(pte, __pte(0)); - kvm_tlb_flush_vmid_ipa(kvm, addr); - - /* No need to invalidate the cache for device mappings */ - if (!kvm_is_device_pfn(pte_pfn(old_pte))) - kvm_flush_dcache_pte(old_pte); - - put_page(virt_to_page(pte)); - } - } while (pte++, addr += PAGE_SIZE, addr != end); - - if (stage2_pte_table_empty(start_pte)) - clear_stage2_pmd_entry(kvm, pmd, start_addr); -} - -static void unmap_stage2_pmds(struct kvm *kvm, pud_t *pud, - phys_addr_t addr, phys_addr_t end) -{ - phys_addr_t next, start_addr = addr; - pmd_t *pmd, *start_pmd; - - start_pmd = pmd = stage2_pmd_offset(pud, addr); - do { - next = stage2_pmd_addr_end(addr, end); - if (!pmd_none(*pmd)) { - if (pmd_thp_or_huge(*pmd)) { - pmd_t old_pmd = *pmd; - - pmd_clear(pmd); - kvm_tlb_flush_vmid_ipa(kvm, addr); - - kvm_flush_dcache_pmd(old_pmd); - - put_page(virt_to_page(pmd)); - } else { - unmap_stage2_ptes(kvm, pmd, addr, next); - } - } - } while (pmd++, addr = next, addr != end); - - if (stage2_pmd_table_empty(start_pmd)) - clear_stage2_pud_entry(kvm, pud, start_addr); -} - -static void unmap_stage2_puds(struct kvm *kvm, pgd_t *pgd, - phys_addr_t addr, phys_addr_t end) -{ - phys_addr_t next, start_addr = addr; - pud_t *pud, *start_pud; - - start_pud = pud = stage2_pud_offset(pgd, addr); - do { - next = stage2_pud_addr_end(addr, end); - if (!stage2_pud_none(*pud)) { - if (stage2_pud_huge(*pud)) { - pud_t old_pud = *pud; - - stage2_pud_clear(pud); - kvm_tlb_flush_vmid_ipa(kvm, addr); - kvm_flush_dcache_pud(old_pud); - put_page(virt_to_page(pud)); - } else { - unmap_stage2_pmds(kvm, pud, addr, next); - } - } - } while (pud++, addr = next, addr != end); - - if (stage2_pud_table_empty(start_pud)) - clear_stage2_pgd_entry(kvm, pgd, start_addr); -} - -/** - * unmap_stage2_range -- Clear stage2 page table entries to unmap a range - * @kvm: The VM pointer - * @start: The intermediate physical base address of the range to unmap - * @size: The size of the area to unmap - * - * Clear a range of stage-2 mappings, lowering the various ref-counts. Must - * be called while holding mmu_lock (unless for freeing the stage2 pgd before - * destroying the VM), otherwise another faulting VCPU may come in and mess - * with things behind our backs. - */ -static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size) -{ - pgd_t *pgd; - phys_addr_t addr = start, end = start + size; - phys_addr_t next; - - pgd = kvm->arch.pgd + stage2_pgd_index(addr); - do { - next = stage2_pgd_addr_end(addr, end); - if (!stage2_pgd_none(*pgd)) - unmap_stage2_puds(kvm, pgd, addr, next); - } while (pgd++, addr = next, addr != end); -} - -static void stage2_flush_ptes(struct kvm *kvm, pmd_t *pmd, - phys_addr_t addr, phys_addr_t end) -{ - pte_t *pte; - - pte = pte_offset_kernel(pmd, addr); - do { - if (!pte_none(*pte) && !kvm_is_device_pfn(pte_pfn(*pte))) - kvm_flush_dcache_pte(*pte); - } while (pte++, addr += PAGE_SIZE, addr != end); -} - -static void stage2_flush_pmds(struct kvm *kvm, pud_t *pud, - phys_addr_t addr, phys_addr_t end) -{ - pmd_t *pmd; - phys_addr_t next; - - pmd = stage2_pmd_offset(pud, addr); - do { - next = stage2_pmd_addr_end(addr, end); - if (!pmd_none(*pmd)) { - if (pmd_thp_or_huge(*pmd)) - kvm_flush_dcache_pmd(*pmd); - else - stage2_flush_ptes(kvm, pmd, addr, next); - } - } while (pmd++, addr = next, addr != end); -} - -static void stage2_flush_puds(struct kvm *kvm, pgd_t *pgd, - phys_addr_t addr, phys_addr_t end) -{ - pud_t *pud; - phys_addr_t next; - - pud = stage2_pud_offset(pgd, addr); - do { - next = stage2_pud_addr_end(addr, end); - if (!stage2_pud_none(*pud)) { - if (stage2_pud_huge(*pud)) - kvm_flush_dcache_pud(*pud); - else - stage2_flush_pmds(kvm, pud, addr, next); - } - } while (pud++, addr = next, addr != end); -} - -static void stage2_flush_memslot(struct kvm *kvm, - struct kvm_memory_slot *memslot) -{ - phys_addr_t addr = memslot->base_gfn << PAGE_SHIFT; - phys_addr_t end = addr + PAGE_SIZE * memslot->npages; - phys_addr_t next; - pgd_t *pgd; - - pgd = kvm->arch.pgd + stage2_pgd_index(addr); - do { - next = stage2_pgd_addr_end(addr, end); - stage2_flush_puds(kvm, pgd, addr, next); - } while (pgd++, addr = next, addr != end); -} - -/** - * stage2_flush_vm - Invalidate cache for pages mapped in stage 2 - * @kvm: The struct kvm pointer - * - * Go through the stage 2 page tables and invalidate any cache lines - * backing memory already mapped to the VM. - */ -static void stage2_flush_vm(struct kvm *kvm) -{ - struct kvm_memslots *slots; - struct kvm_memory_slot *memslot; - int idx; - - idx = srcu_read_lock(&kvm->srcu); - spin_lock(&kvm->mmu_lock); - - slots = kvm_memslots(kvm); - kvm_for_each_memslot(memslot, slots) - stage2_flush_memslot(kvm, memslot); - - spin_unlock(&kvm->mmu_lock); - srcu_read_unlock(&kvm->srcu, idx); -} - -static void clear_hyp_pgd_entry(pgd_t *pgd) -{ - pud_t *pud_table __maybe_unused = pud_offset(pgd, 0UL); - pgd_clear(pgd); - pud_free(NULL, pud_table); - put_page(virt_to_page(pgd)); -} - -static void clear_hyp_pud_entry(pud_t *pud) -{ - pmd_t *pmd_table __maybe_unused = pmd_offset(pud, 0); - VM_BUG_ON(pud_huge(*pud)); - pud_clear(pud); - pmd_free(NULL, pmd_table); - put_page(virt_to_page(pud)); -} - -static void clear_hyp_pmd_entry(pmd_t *pmd) -{ - pte_t *pte_table = pte_offset_kernel(pmd, 0); - VM_BUG_ON(pmd_thp_or_huge(*pmd)); - pmd_clear(pmd); - pte_free_kernel(NULL, pte_table); - put_page(virt_to_page(pmd)); -} - -static void unmap_hyp_ptes(pmd_t *pmd, phys_addr_t addr, phys_addr_t end) -{ - pte_t *pte, *start_pte; - - start_pte = pte = pte_offset_kernel(pmd, addr); - do { - if (!pte_none(*pte)) { - kvm_set_pte(pte, __pte(0)); - put_page(virt_to_page(pte)); - } - } while (pte++, addr += PAGE_SIZE, addr != end); - - if (hyp_pte_table_empty(start_pte)) - clear_hyp_pmd_entry(pmd); -} - -static void unmap_hyp_pmds(pud_t *pud, phys_addr_t addr, phys_addr_t end) -{ - phys_addr_t next; - pmd_t *pmd, *start_pmd; - - start_pmd = pmd = pmd_offset(pud, addr); - do { - next = pmd_addr_end(addr, end); - /* Hyp doesn't use huge pmds */ - if (!pmd_none(*pmd)) - unmap_hyp_ptes(pmd, addr, next); - } while (pmd++, addr = next, addr != end); - - if (hyp_pmd_table_empty(start_pmd)) - clear_hyp_pud_entry(pud); -} - -static void unmap_hyp_puds(pgd_t *pgd, phys_addr_t addr, phys_addr_t end) -{ - phys_addr_t next; - pud_t *pud, *start_pud; - - start_pud = pud = pud_offset(pgd, addr); - do { - next = pud_addr_end(addr, end); - /* Hyp doesn't use huge puds */ - if (!pud_none(*pud)) - unmap_hyp_pmds(pud, addr, next); - } while (pud++, addr = next, addr != end); - - if (hyp_pud_table_empty(start_pud)) - clear_hyp_pgd_entry(pgd); -} - -static void unmap_hyp_range(pgd_t *pgdp, phys_addr_t start, u64 size) -{ - pgd_t *pgd; - phys_addr_t addr = start, end = start + size; - phys_addr_t next; - - /* - * We don't unmap anything from HYP, except at the hyp tear down. - * Hence, we don't have to invalidate the TLBs here. - */ - pgd = pgdp + pgd_index(addr); - do { - next = pgd_addr_end(addr, end); - if (!pgd_none(*pgd)) - unmap_hyp_puds(pgd, addr, next); - } while (pgd++, addr = next, addr != end); -} - -/** - * free_hyp_pgds - free Hyp-mode page tables - * - * Assumes hyp_pgd is a page table used strictly in Hyp-mode and - * therefore contains either mappings in the kernel memory area (above - * PAGE_OFFSET), or device mappings in the vmalloc range (from - * VMALLOC_START to VMALLOC_END). - * - * boot_hyp_pgd should only map two pages for the init code. - */ -void free_hyp_pgds(void) -{ - unsigned long addr; - - mutex_lock(&kvm_hyp_pgd_mutex); - - if (boot_hyp_pgd) { - unmap_hyp_range(boot_hyp_pgd, hyp_idmap_start, PAGE_SIZE); - free_pages((unsigned long)boot_hyp_pgd, hyp_pgd_order); - boot_hyp_pgd = NULL; - } - - if (hyp_pgd) { - unmap_hyp_range(hyp_pgd, hyp_idmap_start, PAGE_SIZE); - for (addr = PAGE_OFFSET; virt_addr_valid(addr); addr += PGDIR_SIZE) - unmap_hyp_range(hyp_pgd, kern_hyp_va(addr), PGDIR_SIZE); - for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr += PGDIR_SIZE) - unmap_hyp_range(hyp_pgd, kern_hyp_va(addr), PGDIR_SIZE); - - free_pages((unsigned long)hyp_pgd, hyp_pgd_order); - hyp_pgd = NULL; - } - if (merged_hyp_pgd) { - clear_page(merged_hyp_pgd); - free_page((unsigned long)merged_hyp_pgd); - merged_hyp_pgd = NULL; - } - - mutex_unlock(&kvm_hyp_pgd_mutex); -} - -static void create_hyp_pte_mappings(pmd_t *pmd, unsigned long start, - unsigned long end, unsigned long pfn, - pgprot_t prot) -{ - pte_t *pte; - unsigned long addr; - - addr = start; - do { - pte = pte_offset_kernel(pmd, addr); - kvm_set_pte(pte, pfn_pte(pfn, prot)); - get_page(virt_to_page(pte)); - kvm_flush_dcache_to_poc(pte, sizeof(*pte)); - pfn++; - } while (addr += PAGE_SIZE, addr != end); -} - -static int create_hyp_pmd_mappings(pud_t *pud, unsigned long start, - unsigned long end, unsigned long pfn, - pgprot_t prot) -{ - pmd_t *pmd; - pte_t *pte; - unsigned long addr, next; - - addr = start; - do { - pmd = pmd_offset(pud, addr); - - BUG_ON(pmd_sect(*pmd)); - - if (pmd_none(*pmd)) { - pte = pte_alloc_one_kernel(NULL, addr); - if (!pte) { - kvm_err("Cannot allocate Hyp pte\n"); - return -ENOMEM; - } - pmd_populate_kernel(NULL, pmd, pte); - get_page(virt_to_page(pmd)); - kvm_flush_dcache_to_poc(pmd, sizeof(*pmd)); - } - - next = pmd_addr_end(addr, end); - - create_hyp_pte_mappings(pmd, addr, next, pfn, prot); - pfn += (next - addr) >> PAGE_SHIFT; - } while (addr = next, addr != end); - - return 0; -} - -static int create_hyp_pud_mappings(pgd_t *pgd, unsigned long start, - unsigned long end, unsigned long pfn, - pgprot_t prot) -{ - pud_t *pud; - pmd_t *pmd; - unsigned long addr, next; - int ret; - - addr = start; - do { - pud = pud_offset(pgd, addr); - - if (pud_none_or_clear_bad(pud)) { - pmd = pmd_alloc_one(NULL, addr); - if (!pmd) { - kvm_err("Cannot allocate Hyp pmd\n"); - return -ENOMEM; - } - pud_populate(NULL, pud, pmd); - get_page(virt_to_page(pud)); - kvm_flush_dcache_to_poc(pud, sizeof(*pud)); - } - - next = pud_addr_end(addr, end); - ret = create_hyp_pmd_mappings(pud, addr, next, pfn, prot); - if (ret) - return ret; - pfn += (next - addr) >> PAGE_SHIFT; - } while (addr = next, addr != end); - - return 0; -} - -static int __create_hyp_mappings(pgd_t *pgdp, - unsigned long start, unsigned long end, - unsigned long pfn, pgprot_t prot) -{ - pgd_t *pgd; - pud_t *pud; - unsigned long addr, next; - int err = 0; - - mutex_lock(&kvm_hyp_pgd_mutex); - addr = start & PAGE_MASK; - end = PAGE_ALIGN(end); - do { - pgd = pgdp + pgd_index(addr); - - if (pgd_none(*pgd)) { - pud = pud_alloc_one(NULL, addr); - if (!pud) { - kvm_err("Cannot allocate Hyp pud\n"); - err = -ENOMEM; - goto out; - } - pgd_populate(NULL, pgd, pud); - get_page(virt_to_page(pgd)); - kvm_flush_dcache_to_poc(pgd, sizeof(*pgd)); - } - - next = pgd_addr_end(addr, end); - err = create_hyp_pud_mappings(pgd, addr, next, pfn, prot); - if (err) - goto out; - pfn += (next - addr) >> PAGE_SHIFT; - } while (addr = next, addr != end); -out: - mutex_unlock(&kvm_hyp_pgd_mutex); - return err; -} - -static phys_addr_t kvm_kaddr_to_phys(void *kaddr) -{ - if (!is_vmalloc_addr(kaddr)) { - BUG_ON(!virt_addr_valid(kaddr)); - return __pa(kaddr); - } else { - return page_to_phys(vmalloc_to_page(kaddr)) + - offset_in_page(kaddr); - } -} - -/** - * create_hyp_mappings - duplicate a kernel virtual address range in Hyp mode - * @from: The virtual kernel start address of the range - * @to: The virtual kernel end address of the range (exclusive) - * @prot: The protection to be applied to this range - * - * The same virtual address as the kernel virtual address is also used - * in Hyp-mode mapping (modulo HYP_PAGE_OFFSET) to the same underlying - * physical pages. - */ -int create_hyp_mappings(void *from, void *to, pgprot_t prot) -{ - phys_addr_t phys_addr; - unsigned long virt_addr; - unsigned long start = kern_hyp_va((unsigned long)from); - unsigned long end = kern_hyp_va((unsigned long)to); - - if (is_kernel_in_hyp_mode()) - return 0; - - start = start & PAGE_MASK; - end = PAGE_ALIGN(end); - - for (virt_addr = start; virt_addr < end; virt_addr += PAGE_SIZE) { - int err; - - phys_addr = kvm_kaddr_to_phys(from + virt_addr - start); - err = __create_hyp_mappings(hyp_pgd, virt_addr, - virt_addr + PAGE_SIZE, - __phys_to_pfn(phys_addr), - prot); - if (err) - return err; - } - - return 0; -} - -/** - * create_hyp_io_mappings - duplicate a kernel IO mapping into Hyp mode - * @from: The kernel start VA of the range - * @to: The kernel end VA of the range (exclusive) - * @phys_addr: The physical start address which gets mapped - * - * The resulting HYP VA is the same as the kernel VA, modulo - * HYP_PAGE_OFFSET. - */ -int create_hyp_io_mappings(void *from, void *to, phys_addr_t phys_addr) -{ - unsigned long start = kern_hyp_va((unsigned long)from); - unsigned long end = kern_hyp_va((unsigned long)to); - - if (is_kernel_in_hyp_mode()) - return 0; - - /* Check for a valid kernel IO mapping */ - if (!is_vmalloc_addr(from) || !is_vmalloc_addr(to - 1)) - return -EINVAL; - - return __create_hyp_mappings(hyp_pgd, start, end, - __phys_to_pfn(phys_addr), PAGE_HYP_DEVICE); -} - -/** - * kvm_alloc_stage2_pgd - allocate level-1 table for stage-2 translation. - * @kvm: The KVM struct pointer for the VM. - * - * Allocates only the stage-2 HW PGD level table(s) (can support either full - * 40-bit input addresses or limited to 32-bit input addresses). Clears the - * allocated pages. - * - * Note we don't need locking here as this is only called when the VM is - * created, which can only be done once. - */ -int kvm_alloc_stage2_pgd(struct kvm *kvm) -{ - pgd_t *pgd; - - if (kvm->arch.pgd != NULL) { - kvm_err("kvm_arch already initialized?\n"); - return -EINVAL; - } - - /* Allocate the HW PGD, making sure that each page gets its own refcount */ - pgd = alloc_pages_exact(S2_PGD_SIZE, GFP_KERNEL | __GFP_ZERO); - if (!pgd) - return -ENOMEM; - - kvm->arch.pgd = pgd; - return 0; -} - -static void stage2_unmap_memslot(struct kvm *kvm, - struct kvm_memory_slot *memslot) -{ - hva_t hva = memslot->userspace_addr; - phys_addr_t addr = memslot->base_gfn << PAGE_SHIFT; - phys_addr_t size = PAGE_SIZE * memslot->npages; - hva_t reg_end = hva + size; - - /* - * A memory region could potentially cover multiple VMAs, and any holes - * between them, so iterate over all of them to find out if we should - * unmap any of them. - * - * +--------------------------------------------+ - * +---------------+----------------+ +----------------+ - * | : VMA 1 | VMA 2 | | VMA 3 : | - * +---------------+----------------+ +----------------+ - * | memory region | - * +--------------------------------------------+ - */ - do { - struct vm_area_struct *vma = find_vma(current->mm, hva); - hva_t vm_start, vm_end; - - if (!vma || vma->vm_start >= reg_end) - break; - - /* - * Take the intersection of this VMA with the memory region - */ - vm_start = max(hva, vma->vm_start); - vm_end = min(reg_end, vma->vm_end); - - if (!(vma->vm_flags & VM_PFNMAP)) { - gpa_t gpa = addr + (vm_start - memslot->userspace_addr); - unmap_stage2_range(kvm, gpa, vm_end - vm_start); - } - hva = vm_end; - } while (hva < reg_end); -} - -/** - * stage2_unmap_vm - Unmap Stage-2 RAM mappings - * @kvm: The struct kvm pointer - * - * Go through the memregions and unmap any reguler RAM - * backing memory already mapped to the VM. - */ -void stage2_unmap_vm(struct kvm *kvm) -{ - struct kvm_memslots *slots; - struct kvm_memory_slot *memslot; - int idx; - - idx = srcu_read_lock(&kvm->srcu); - spin_lock(&kvm->mmu_lock); - - slots = kvm_memslots(kvm); - kvm_for_each_memslot(memslot, slots) - stage2_unmap_memslot(kvm, memslot); - - spin_unlock(&kvm->mmu_lock); - srcu_read_unlock(&kvm->srcu, idx); -} - -/** - * kvm_free_stage2_pgd - free all stage-2 tables - * @kvm: The KVM struct pointer for the VM. - * - * Walks the level-1 page table pointed to by kvm->arch.pgd and frees all - * underlying level-2 and level-3 tables before freeing the actual level-1 table - * and setting the struct pointer to NULL. - * - * Note we don't need locking here as this is only called when the VM is - * destroyed, which can only be done once. - */ -void kvm_free_stage2_pgd(struct kvm *kvm) -{ - if (kvm->arch.pgd == NULL) - return; - - unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE); - /* Free the HW pgd, one page at a time */ - free_pages_exact(kvm->arch.pgd, S2_PGD_SIZE); - kvm->arch.pgd = NULL; -} - -static pud_t *stage2_get_pud(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, - phys_addr_t addr) -{ - pgd_t *pgd; - pud_t *pud; - - pgd = kvm->arch.pgd + stage2_pgd_index(addr); - if (WARN_ON(stage2_pgd_none(*pgd))) { - if (!cache) - return NULL; - pud = mmu_memory_cache_alloc(cache); - stage2_pgd_populate(pgd, pud); - get_page(virt_to_page(pgd)); - } - - return stage2_pud_offset(pgd, addr); -} - -static pmd_t *stage2_get_pmd(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, - phys_addr_t addr) -{ - pud_t *pud; - pmd_t *pmd; - - pud = stage2_get_pud(kvm, cache, addr); - if (stage2_pud_none(*pud)) { - if (!cache) - return NULL; - pmd = mmu_memory_cache_alloc(cache); - stage2_pud_populate(pud, pmd); - get_page(virt_to_page(pud)); - } - - return stage2_pmd_offset(pud, addr); -} - -static int stage2_set_pmd_huge(struct kvm *kvm, struct kvm_mmu_memory_cache - *cache, phys_addr_t addr, const pmd_t *new_pmd) -{ - pmd_t *pmd, old_pmd; - - pmd = stage2_get_pmd(kvm, cache, addr); - VM_BUG_ON(!pmd); - - /* - * Mapping in huge pages should only happen through a fault. If a - * page is merged into a transparent huge page, the individual - * subpages of that huge page should be unmapped through MMU - * notifiers before we get here. - * - * Merging of CompoundPages is not supported; they should become - * splitting first, unmapped, merged, and mapped back in on-demand. - */ - VM_BUG_ON(pmd_present(*pmd) && pmd_pfn(*pmd) != pmd_pfn(*new_pmd)); - - old_pmd = *pmd; - if (pmd_present(old_pmd)) { - pmd_clear(pmd); - kvm_tlb_flush_vmid_ipa(kvm, addr); - } else { - get_page(virt_to_page(pmd)); - } - - kvm_set_pmd(pmd, *new_pmd); - return 0; -} - -static int stage2_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, - phys_addr_t addr, const pte_t *new_pte, - unsigned long flags) -{ - pmd_t *pmd; - pte_t *pte, old_pte; - bool iomap = flags & KVM_S2PTE_FLAG_IS_IOMAP; - bool logging_active = flags & KVM_S2_FLAG_LOGGING_ACTIVE; - - VM_BUG_ON(logging_active && !cache); - - /* Create stage-2 page table mapping - Levels 0 and 1 */ - pmd = stage2_get_pmd(kvm, cache, addr); - if (!pmd) { - /* - * Ignore calls from kvm_set_spte_hva for unallocated - * address ranges. - */ - return 0; - } - - /* - * While dirty page logging - dissolve huge PMD, then continue on to - * allocate page. - */ - if (logging_active) - stage2_dissolve_pmd(kvm, addr, pmd); - - /* Create stage-2 page mappings - Level 2 */ - if (pmd_none(*pmd)) { - if (!cache) - return 0; /* ignore calls from kvm_set_spte_hva */ - pte = mmu_memory_cache_alloc(cache); - pmd_populate_kernel(NULL, pmd, pte); - get_page(virt_to_page(pmd)); - } - - pte = pte_offset_kernel(pmd, addr); - - if (iomap && pte_present(*pte)) - return -EFAULT; - - /* Create 2nd stage page table mapping - Level 3 */ - old_pte = *pte; - if (pte_present(old_pte)) { - kvm_set_pte(pte, __pte(0)); - kvm_tlb_flush_vmid_ipa(kvm, addr); - } else { - get_page(virt_to_page(pte)); - } - - kvm_set_pte(pte, *new_pte); - return 0; -} - -#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG -static int stage2_ptep_test_and_clear_young(pte_t *pte) -{ - if (pte_young(*pte)) { - *pte = pte_mkold(*pte); - return 1; - } - return 0; -} -#else -static int stage2_ptep_test_and_clear_young(pte_t *pte) -{ - return __ptep_test_and_clear_young(pte); -} -#endif - -static int stage2_pmdp_test_and_clear_young(pmd_t *pmd) -{ - return stage2_ptep_test_and_clear_young((pte_t *)pmd); -} - -/** - * kvm_phys_addr_ioremap - map a device range to guest IPA - * - * @kvm: The KVM pointer - * @guest_ipa: The IPA at which to insert the mapping - * @pa: The physical address of the device - * @size: The size of the mapping - */ -int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa, - phys_addr_t pa, unsigned long size, bool writable) -{ - phys_addr_t addr, end; - int ret = 0; - unsigned long pfn; - struct kvm_mmu_memory_cache cache = { 0, }; - - end = (guest_ipa + size + PAGE_SIZE - 1) & PAGE_MASK; - pfn = __phys_to_pfn(pa); - - for (addr = guest_ipa; addr < end; addr += PAGE_SIZE) { - pte_t pte = pfn_pte(pfn, PAGE_S2_DEVICE); - - if (writable) - pte = kvm_s2pte_mkwrite(pte); - - ret = mmu_topup_memory_cache(&cache, KVM_MMU_CACHE_MIN_PAGES, - KVM_NR_MEM_OBJS); - if (ret) - goto out; - spin_lock(&kvm->mmu_lock); - ret = stage2_set_pte(kvm, &cache, addr, &pte, - KVM_S2PTE_FLAG_IS_IOMAP); - spin_unlock(&kvm->mmu_lock); - if (ret) - goto out; - - pfn++; - } - -out: - mmu_free_memory_cache(&cache); - return ret; -} - -static bool transparent_hugepage_adjust(kvm_pfn_t *pfnp, phys_addr_t *ipap) -{ - kvm_pfn_t pfn = *pfnp; - gfn_t gfn = *ipap >> PAGE_SHIFT; - - if (PageTransCompoundMap(pfn_to_page(pfn))) { - unsigned long mask; - /* - * The address we faulted on is backed by a transparent huge - * page. However, because we map the compound huge page and - * not the individual tail page, we need to transfer the - * refcount to the head page. We have to be careful that the - * THP doesn't start to split while we are adjusting the - * refcounts. - * - * We are sure this doesn't happen, because mmu_notifier_retry - * was successful and we are holding the mmu_lock, so if this - * THP is trying to split, it will be blocked in the mmu - * notifier before touching any of the pages, specifically - * before being able to call __split_huge_page_refcount(). - * - * We can therefore safely transfer the refcount from PG_tail - * to PG_head and switch the pfn from a tail page to the head - * page accordingly. - */ - mask = PTRS_PER_PMD - 1; - VM_BUG_ON((gfn & mask) != (pfn & mask)); - if (pfn & mask) { - *ipap &= PMD_MASK; - kvm_release_pfn_clean(pfn); - pfn &= ~mask; - kvm_get_pfn(pfn); - *pfnp = pfn; - } - - return true; - } - - return false; -} - -static bool kvm_is_write_fault(struct kvm_vcpu *vcpu) -{ - if (kvm_vcpu_trap_is_iabt(vcpu)) - return false; - - return kvm_vcpu_dabt_iswrite(vcpu); -} - -/** - * stage2_wp_ptes - write protect PMD range - * @pmd: pointer to pmd entry - * @addr: range start address - * @end: range end address - */ -static void stage2_wp_ptes(pmd_t *pmd, phys_addr_t addr, phys_addr_t end) -{ - pte_t *pte; - - pte = pte_offset_kernel(pmd, addr); - do { - if (!pte_none(*pte)) { - if (!kvm_s2pte_readonly(pte)) - kvm_set_s2pte_readonly(pte); - } - } while (pte++, addr += PAGE_SIZE, addr != end); -} - -/** - * stage2_wp_pmds - write protect PUD range - * @pud: pointer to pud entry - * @addr: range start address - * @end: range end address - */ -static void stage2_wp_pmds(pud_t *pud, phys_addr_t addr, phys_addr_t end) -{ - pmd_t *pmd; - phys_addr_t next; - - pmd = stage2_pmd_offset(pud, addr); - - do { - next = stage2_pmd_addr_end(addr, end); - if (!pmd_none(*pmd)) { - if (pmd_thp_or_huge(*pmd)) { - if (!kvm_s2pmd_readonly(pmd)) - kvm_set_s2pmd_readonly(pmd); - } else { - stage2_wp_ptes(pmd, addr, next); - } - } - } while (pmd++, addr = next, addr != end); -} - -/** - * stage2_wp_puds - write protect PGD range - * @pgd: pointer to pgd entry - * @addr: range start address - * @end: range end address - * - * Process PUD entries, for a huge PUD we cause a panic. - */ -static void stage2_wp_puds(pgd_t *pgd, phys_addr_t addr, phys_addr_t end) -{ - pud_t *pud; - phys_addr_t next; - - pud = stage2_pud_offset(pgd, addr); - do { - next = stage2_pud_addr_end(addr, end); - if (!stage2_pud_none(*pud)) { - /* TODO:PUD not supported, revisit later if supported */ - BUG_ON(stage2_pud_huge(*pud)); - stage2_wp_pmds(pud, addr, next); - } - } while (pud++, addr = next, addr != end); -} - -/** - * stage2_wp_range() - write protect stage2 memory region range - * @kvm: The KVM pointer - * @addr: Start address of range - * @end: End address of range - */ -static void stage2_wp_range(struct kvm *kvm, phys_addr_t addr, phys_addr_t end) -{ - pgd_t *pgd; - phys_addr_t next; - - pgd = kvm->arch.pgd + stage2_pgd_index(addr); - do { - /* - * Release kvm_mmu_lock periodically if the memory region is - * large. Otherwise, we may see kernel panics with - * CONFIG_DETECT_HUNG_TASK, CONFIG_LOCKUP_DETECTOR, - * CONFIG_LOCKDEP. Additionally, holding the lock too long - * will also starve other vCPUs. - */ - if (need_resched() || spin_needbreak(&kvm->mmu_lock)) - cond_resched_lock(&kvm->mmu_lock); - - next = stage2_pgd_addr_end(addr, end); - if (stage2_pgd_present(*pgd)) - stage2_wp_puds(pgd, addr, next); - } while (pgd++, addr = next, addr != end); -} - -/** - * kvm_mmu_wp_memory_region() - write protect stage 2 entries for memory slot - * @kvm: The KVM pointer - * @slot: The memory slot to write protect - * - * Called to start logging dirty pages after memory region - * KVM_MEM_LOG_DIRTY_PAGES operation is called. After this function returns - * all present PMD and PTEs are write protected in the memory region. - * Afterwards read of dirty page log can be called. - * - * Acquires kvm_mmu_lock. Called with kvm->slots_lock mutex acquired, - * serializing operations for VM memory regions. - */ -void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot) -{ - struct kvm_memslots *slots = kvm_memslots(kvm); - struct kvm_memory_slot *memslot = id_to_memslot(slots, slot); - phys_addr_t start = memslot->base_gfn << PAGE_SHIFT; - phys_addr_t end = (memslot->base_gfn + memslot->npages) << PAGE_SHIFT; - - spin_lock(&kvm->mmu_lock); - stage2_wp_range(kvm, start, end); - spin_unlock(&kvm->mmu_lock); - kvm_flush_remote_tlbs(kvm); -} - -/** - * kvm_mmu_write_protect_pt_masked() - write protect dirty pages - * @kvm: The KVM pointer - * @slot: The memory slot associated with mask - * @gfn_offset: The gfn offset in memory slot - * @mask: The mask of dirty pages at offset 'gfn_offset' in this memory - * slot to be write protected - * - * Walks bits set in mask write protects the associated pte's. Caller must - * acquire kvm_mmu_lock. - */ -static void kvm_mmu_write_protect_pt_masked(struct kvm *kvm, - struct kvm_memory_slot *slot, - gfn_t gfn_offset, unsigned long mask) -{ - phys_addr_t base_gfn = slot->base_gfn + gfn_offset; - phys_addr_t start = (base_gfn + __ffs(mask)) << PAGE_SHIFT; - phys_addr_t end = (base_gfn + __fls(mask) + 1) << PAGE_SHIFT; - - stage2_wp_range(kvm, start, end); -} - -/* - * kvm_arch_mmu_enable_log_dirty_pt_masked - enable dirty logging for selected - * dirty pages. - * - * It calls kvm_mmu_write_protect_pt_masked to write protect selected pages to - * enable dirty logging for them. - */ -void kvm_arch_mmu_enable_log_dirty_pt_masked(struct kvm *kvm, - struct kvm_memory_slot *slot, - gfn_t gfn_offset, unsigned long mask) -{ - kvm_mmu_write_protect_pt_masked(kvm, slot, gfn_offset, mask); -} - -static void coherent_cache_guest_page(struct kvm_vcpu *vcpu, kvm_pfn_t pfn, - unsigned long size) -{ - __coherent_cache_guest_page(vcpu, pfn, size); -} - -static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, - struct kvm_memory_slot *memslot, unsigned long hva, - unsigned long fault_status) -{ - int ret; - bool write_fault, writable, hugetlb = false, force_pte = false; - unsigned long mmu_seq; - gfn_t gfn = fault_ipa >> PAGE_SHIFT; - struct kvm *kvm = vcpu->kvm; - struct kvm_mmu_memory_cache *memcache = &vcpu->arch.mmu_page_cache; - struct vm_area_struct *vma; - kvm_pfn_t pfn; - pgprot_t mem_type = PAGE_S2; - bool logging_active = memslot_is_logging(memslot); - unsigned long flags = 0; - - write_fault = kvm_is_write_fault(vcpu); - if (fault_status == FSC_PERM && !write_fault) { - kvm_err("Unexpected L2 read permission error\n"); - return -EFAULT; - } - - /* Let's check if we will get back a huge page backed by hugetlbfs */ - down_read(¤t->mm->mmap_sem); - vma = find_vma_intersection(current->mm, hva, hva + 1); - if (unlikely(!vma)) { - kvm_err("Failed to find VMA for hva 0x%lx\n", hva); - up_read(¤t->mm->mmap_sem); - return -EFAULT; - } - - if (is_vm_hugetlb_page(vma) && !logging_active) { - hugetlb = true; - gfn = (fault_ipa & PMD_MASK) >> PAGE_SHIFT; - } else { - /* - * Pages belonging to memslots that don't have the same - * alignment for userspace and IPA cannot be mapped using - * block descriptors even if the pages belong to a THP for - * the process, because the stage-2 block descriptor will - * cover more than a single THP and we loose atomicity for - * unmapping, updates, and splits of the THP or other pages - * in the stage-2 block range. - */ - if ((memslot->userspace_addr & ~PMD_MASK) != - ((memslot->base_gfn << PAGE_SHIFT) & ~PMD_MASK)) - force_pte = true; - } - up_read(¤t->mm->mmap_sem); - - /* We need minimum second+third level pages */ - ret = mmu_topup_memory_cache(memcache, KVM_MMU_CACHE_MIN_PAGES, - KVM_NR_MEM_OBJS); - if (ret) - return ret; - - mmu_seq = vcpu->kvm->mmu_notifier_seq; - /* - * Ensure the read of mmu_notifier_seq happens before we call - * gfn_to_pfn_prot (which calls get_user_pages), so that we don't risk - * the page we just got a reference to gets unmapped before we have a - * chance to grab the mmu_lock, which ensure that if the page gets - * unmapped afterwards, the call to kvm_unmap_hva will take it away - * from us again properly. This smp_rmb() interacts with the smp_wmb() - * in kvm_mmu_notifier_invalidate_. - */ - smp_rmb(); - - pfn = gfn_to_pfn_prot(kvm, gfn, write_fault, &writable); - if (is_error_noslot_pfn(pfn)) - return -EFAULT; - - if (kvm_is_device_pfn(pfn)) { - mem_type = PAGE_S2_DEVICE; - flags |= KVM_S2PTE_FLAG_IS_IOMAP; - } else if (logging_active) { - /* - * Faults on pages in a memslot with logging enabled - * should not be mapped with huge pages (it introduces churn - * and performance degradation), so force a pte mapping. - */ - force_pte = true; - flags |= KVM_S2_FLAG_LOGGING_ACTIVE; - - /* - * Only actually map the page as writable if this was a write - * fault. - */ - if (!write_fault) - writable = false; - } - - spin_lock(&kvm->mmu_lock); - if (mmu_notifier_retry(kvm, mmu_seq)) - goto out_unlock; - - if (!hugetlb && !force_pte) - hugetlb = transparent_hugepage_adjust(&pfn, &fault_ipa); - - if (hugetlb) { - pmd_t new_pmd = pfn_pmd(pfn, mem_type); - new_pmd = pmd_mkhuge(new_pmd); - if (writable) { - new_pmd = kvm_s2pmd_mkwrite(new_pmd); - kvm_set_pfn_dirty(pfn); - } - coherent_cache_guest_page(vcpu, pfn, PMD_SIZE); - ret = stage2_set_pmd_huge(kvm, memcache, fault_ipa, &new_pmd); - } else { - pte_t new_pte = pfn_pte(pfn, mem_type); - - if (writable) { - new_pte = kvm_s2pte_mkwrite(new_pte); - kvm_set_pfn_dirty(pfn); - mark_page_dirty(kvm, gfn); - } - coherent_cache_guest_page(vcpu, pfn, PAGE_SIZE); - ret = stage2_set_pte(kvm, memcache, fault_ipa, &new_pte, flags); - } - -out_unlock: - spin_unlock(&kvm->mmu_lock); - kvm_set_pfn_accessed(pfn); - kvm_release_pfn_clean(pfn); - return ret; -} - -/* - * Resolve the access fault by making the page young again. - * Note that because the faulting entry is guaranteed not to be - * cached in the TLB, we don't need to invalidate anything. - * Only the HW Access Flag updates are supported for Stage 2 (no DBM), - * so there is no need for atomic (pte|pmd)_mkyoung operations. - */ -static void handle_access_fault(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa) -{ - pmd_t *pmd; - pte_t *pte; - kvm_pfn_t pfn; - bool pfn_valid = false; - - trace_kvm_access_fault(fault_ipa); - - spin_lock(&vcpu->kvm->mmu_lock); - - pmd = stage2_get_pmd(vcpu->kvm, NULL, fault_ipa); - if (!pmd || pmd_none(*pmd)) /* Nothing there */ - goto out; - - if (pmd_thp_or_huge(*pmd)) { /* THP, HugeTLB */ - *pmd = pmd_mkyoung(*pmd); - pfn = pmd_pfn(*pmd); - pfn_valid = true; - goto out; - } - - pte = pte_offset_kernel(pmd, fault_ipa); - if (pte_none(*pte)) /* Nothing there either */ - goto out; - - *pte = pte_mkyoung(*pte); /* Just a page... */ - pfn = pte_pfn(*pte); - pfn_valid = true; -out: - spin_unlock(&vcpu->kvm->mmu_lock); - if (pfn_valid) - kvm_set_pfn_accessed(pfn); -} - -/** - * kvm_handle_guest_abort - handles all 2nd stage aborts - * @vcpu: the VCPU pointer - * @run: the kvm_run structure - * - * Any abort that gets to the host is almost guaranteed to be caused by a - * missing second stage translation table entry, which can mean that either the - * guest simply needs more memory and we must allocate an appropriate page or it - * can mean that the guest tried to access I/O memory, which is emulated by user - * space. The distinction is based on the IPA causing the fault and whether this - * memory region has been registered as standard RAM by user space. - */ -int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run) -{ - unsigned long fault_status; - phys_addr_t fault_ipa; - struct kvm_memory_slot *memslot; - unsigned long hva; - bool is_iabt, write_fault, writable; - gfn_t gfn; - int ret, idx; - - is_iabt = kvm_vcpu_trap_is_iabt(vcpu); - if (unlikely(!is_iabt && kvm_vcpu_dabt_isextabt(vcpu))) { - kvm_inject_vabt(vcpu); - return 1; - } - - fault_ipa = kvm_vcpu_get_fault_ipa(vcpu); - - trace_kvm_guest_fault(*vcpu_pc(vcpu), kvm_vcpu_get_hsr(vcpu), - kvm_vcpu_get_hfar(vcpu), fault_ipa); - - /* Check the stage-2 fault is trans. fault or write fault */ - fault_status = kvm_vcpu_trap_get_fault_type(vcpu); - if (fault_status != FSC_FAULT && fault_status != FSC_PERM && - fault_status != FSC_ACCESS) { - kvm_err("Unsupported FSC: EC=%#x xFSC=%#lx ESR_EL2=%#lx\n", - kvm_vcpu_trap_get_class(vcpu), - (unsigned long)kvm_vcpu_trap_get_fault(vcpu), - (unsigned long)kvm_vcpu_get_hsr(vcpu)); - return -EFAULT; - } - - idx = srcu_read_lock(&vcpu->kvm->srcu); - - gfn = fault_ipa >> PAGE_SHIFT; - memslot = gfn_to_memslot(vcpu->kvm, gfn); - hva = gfn_to_hva_memslot_prot(memslot, gfn, &writable); - write_fault = kvm_is_write_fault(vcpu); - if (kvm_is_error_hva(hva) || (write_fault && !writable)) { - if (is_iabt) { - /* Prefetch Abort on I/O address */ - kvm_inject_pabt(vcpu, kvm_vcpu_get_hfar(vcpu)); - ret = 1; - goto out_unlock; - } - - /* - * Check for a cache maintenance operation. Since we - * ended-up here, we know it is outside of any memory - * slot. But we can't find out if that is for a device, - * or if the guest is just being stupid. The only thing - * we know for sure is that this range cannot be cached. - * - * So let's assume that the guest is just being - * cautious, and skip the instruction. - */ - if (kvm_vcpu_dabt_is_cm(vcpu)) { - kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu)); - ret = 1; - goto out_unlock; - } - - /* - * The IPA is reported as [MAX:12], so we need to - * complement it with the bottom 12 bits from the - * faulting VA. This is always 12 bits, irrespective - * of the page size. - */ - fault_ipa |= kvm_vcpu_get_hfar(vcpu) & ((1 << 12) - 1); - ret = io_mem_abort(vcpu, run, fault_ipa); - goto out_unlock; - } - - /* Userspace should not be able to register out-of-bounds IPAs */ - VM_BUG_ON(fault_ipa >= KVM_PHYS_SIZE); - - if (fault_status == FSC_ACCESS) { - handle_access_fault(vcpu, fault_ipa); - ret = 1; - goto out_unlock; - } - - ret = user_mem_abort(vcpu, fault_ipa, memslot, hva, fault_status); - if (ret == 0) - ret = 1; -out_unlock: - srcu_read_unlock(&vcpu->kvm->srcu, idx); - return ret; -} - -static int handle_hva_to_gpa(struct kvm *kvm, - unsigned long start, - unsigned long end, - int (*handler)(struct kvm *kvm, - gpa_t gpa, u64 size, - void *data), - void *data) -{ - struct kvm_memslots *slots; - struct kvm_memory_slot *memslot; - int ret = 0; - - slots = kvm_memslots(kvm); - - /* we only care about the pages that the guest sees */ - kvm_for_each_memslot(memslot, slots) { - unsigned long hva_start, hva_end; - gfn_t gpa; - - hva_start = max(start, memslot->userspace_addr); - hva_end = min(end, memslot->userspace_addr + - (memslot->npages << PAGE_SHIFT)); - if (hva_start >= hva_end) - continue; - - gpa = hva_to_gfn_memslot(hva_start, memslot) << PAGE_SHIFT; - ret |= handler(kvm, gpa, (u64)(hva_end - hva_start), data); - } - - return ret; -} - -static int kvm_unmap_hva_handler(struct kvm *kvm, gpa_t gpa, u64 size, void *data) -{ - unmap_stage2_range(kvm, gpa, size); - return 0; -} - -int kvm_unmap_hva(struct kvm *kvm, unsigned long hva) -{ - unsigned long end = hva + PAGE_SIZE; - - if (!kvm->arch.pgd) - return 0; - - trace_kvm_unmap_hva(hva); - handle_hva_to_gpa(kvm, hva, end, &kvm_unmap_hva_handler, NULL); - return 0; -} - -int kvm_unmap_hva_range(struct kvm *kvm, - unsigned long start, unsigned long end) -{ - if (!kvm->arch.pgd) - return 0; - - trace_kvm_unmap_hva_range(start, end); - handle_hva_to_gpa(kvm, start, end, &kvm_unmap_hva_handler, NULL); - return 0; -} - -static int kvm_set_spte_handler(struct kvm *kvm, gpa_t gpa, u64 size, void *data) -{ - pte_t *pte = (pte_t *)data; - - WARN_ON(size != PAGE_SIZE); - /* - * We can always call stage2_set_pte with KVM_S2PTE_FLAG_LOGGING_ACTIVE - * flag clear because MMU notifiers will have unmapped a huge PMD before - * calling ->change_pte() (which in turn calls kvm_set_spte_hva()) and - * therefore stage2_set_pte() never needs to clear out a huge PMD - * through this calling path. - */ - stage2_set_pte(kvm, NULL, gpa, pte, 0); - return 0; -} - - -void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte) -{ - unsigned long end = hva + PAGE_SIZE; - pte_t stage2_pte; - - if (!kvm->arch.pgd) - return; - - trace_kvm_set_spte_hva(hva); - stage2_pte = pfn_pte(pte_pfn(pte), PAGE_S2); - handle_hva_to_gpa(kvm, hva, end, &kvm_set_spte_handler, &stage2_pte); -} - -static int kvm_age_hva_handler(struct kvm *kvm, gpa_t gpa, u64 size, void *data) -{ - pmd_t *pmd; - pte_t *pte; - - WARN_ON(size != PAGE_SIZE && size != PMD_SIZE); - pmd = stage2_get_pmd(kvm, NULL, gpa); - if (!pmd || pmd_none(*pmd)) /* Nothing there */ - return 0; - - if (pmd_thp_or_huge(*pmd)) /* THP, HugeTLB */ - return stage2_pmdp_test_and_clear_young(pmd); - - pte = pte_offset_kernel(pmd, gpa); - if (pte_none(*pte)) - return 0; - - return stage2_ptep_test_and_clear_young(pte); -} - -static int kvm_test_age_hva_handler(struct kvm *kvm, gpa_t gpa, u64 size, void *data) -{ - pmd_t *pmd; - pte_t *pte; - - WARN_ON(size != PAGE_SIZE && size != PMD_SIZE); - pmd = stage2_get_pmd(kvm, NULL, gpa); - if (!pmd || pmd_none(*pmd)) /* Nothing there */ - return 0; - - if (pmd_thp_or_huge(*pmd)) /* THP, HugeTLB */ - return pmd_young(*pmd); - - pte = pte_offset_kernel(pmd, gpa); - if (!pte_none(*pte)) /* Just a page... */ - return pte_young(*pte); - - return 0; -} - -int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end) -{ - trace_kvm_age_hva(start, end); - return handle_hva_to_gpa(kvm, start, end, kvm_age_hva_handler, NULL); -} - -int kvm_test_age_hva(struct kvm *kvm, unsigned long hva) -{ - trace_kvm_test_age_hva(hva); - return handle_hva_to_gpa(kvm, hva, hva, kvm_test_age_hva_handler, NULL); -} - -void kvm_mmu_free_memory_caches(struct kvm_vcpu *vcpu) -{ - mmu_free_memory_cache(&vcpu->arch.mmu_page_cache); -} - -phys_addr_t kvm_mmu_get_httbr(void) -{ - if (__kvm_cpu_uses_extended_idmap()) - return virt_to_phys(merged_hyp_pgd); - else - return virt_to_phys(hyp_pgd); -} - -phys_addr_t kvm_get_idmap_vector(void) -{ - return hyp_idmap_vector; -} - -static int kvm_map_idmap_text(pgd_t *pgd) -{ - int err; - - /* Create the idmap in the boot page tables */ - err = __create_hyp_mappings(pgd, - hyp_idmap_start, hyp_idmap_end, - __phys_to_pfn(hyp_idmap_start), - PAGE_HYP_EXEC); - if (err) - kvm_err("Failed to idmap %lx-%lx\n", - hyp_idmap_start, hyp_idmap_end); - - return err; -} - -int kvm_mmu_init(void) -{ - int err; - - hyp_idmap_start = kvm_virt_to_phys(__hyp_idmap_text_start); - hyp_idmap_end = kvm_virt_to_phys(__hyp_idmap_text_end); - hyp_idmap_vector = kvm_virt_to_phys(__kvm_hyp_init); - - /* - * We rely on the linker script to ensure at build time that the HYP - * init code does not cross a page boundary. - */ - BUG_ON((hyp_idmap_start ^ (hyp_idmap_end - 1)) & PAGE_MASK); - - kvm_info("IDMAP page: %lx\n", hyp_idmap_start); - kvm_info("HYP VA range: %lx:%lx\n", - kern_hyp_va(PAGE_OFFSET), kern_hyp_va(~0UL)); - - if (hyp_idmap_start >= kern_hyp_va(PAGE_OFFSET) && - hyp_idmap_start < kern_hyp_va(~0UL) && - hyp_idmap_start != (unsigned long)__hyp_idmap_text_start) { - /* - * The idmap page is intersecting with the VA space, - * it is not safe to continue further. - */ - kvm_err("IDMAP intersecting with HYP VA, unable to continue\n"); - err = -EINVAL; - goto out; - } - - hyp_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, hyp_pgd_order); - if (!hyp_pgd) { - kvm_err("Hyp mode PGD not allocated\n"); - err = -ENOMEM; - goto out; - } - - if (__kvm_cpu_uses_extended_idmap()) { - boot_hyp_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, - hyp_pgd_order); - if (!boot_hyp_pgd) { - kvm_err("Hyp boot PGD not allocated\n"); - err = -ENOMEM; - goto out; - } - - err = kvm_map_idmap_text(boot_hyp_pgd); - if (err) - goto out; - - merged_hyp_pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO); - if (!merged_hyp_pgd) { - kvm_err("Failed to allocate extra HYP pgd\n"); - goto out; - } - __kvm_extend_hypmap(boot_hyp_pgd, hyp_pgd, merged_hyp_pgd, - hyp_idmap_start); - } else { - err = kvm_map_idmap_text(hyp_pgd); - if (err) - goto out; - } - - return 0; -out: - free_hyp_pgds(); - return err; -} - -void kvm_arch_commit_memory_region(struct kvm *kvm, - const struct kvm_userspace_memory_region *mem, - const struct kvm_memory_slot *old, - const struct kvm_memory_slot *new, - enum kvm_mr_change change) -{ - /* - * At this point memslot has been committed and there is an - * allocated dirty_bitmap[], dirty pages will be be tracked while the - * memory slot is write protected. - */ - if (change != KVM_MR_DELETE && mem->flags & KVM_MEM_LOG_DIRTY_PAGES) - kvm_mmu_wp_memory_region(kvm, mem->slot); -} - -int kvm_arch_prepare_memory_region(struct kvm *kvm, - struct kvm_memory_slot *memslot, - const struct kvm_userspace_memory_region *mem, - enum kvm_mr_change change) -{ - hva_t hva = mem->userspace_addr; - hva_t reg_end = hva + mem->memory_size; - bool writable = !(mem->flags & KVM_MEM_READONLY); - int ret = 0; - - if (change != KVM_MR_CREATE && change != KVM_MR_MOVE && - change != KVM_MR_FLAGS_ONLY) - return 0; - - /* - * Prevent userspace from creating a memory region outside of the IPA - * space addressable by the KVM guest IPA space. - */ - if (memslot->base_gfn + memslot->npages >= - (KVM_PHYS_SIZE >> PAGE_SHIFT)) - return -EFAULT; - - /* - * A memory region could potentially cover multiple VMAs, and any holes - * between them, so iterate over all of them to find out if we can map - * any of them right now. - * - * +--------------------------------------------+ - * +---------------+----------------+ +----------------+ - * | : VMA 1 | VMA 2 | | VMA 3 : | - * +---------------+----------------+ +----------------+ - * | memory region | - * +--------------------------------------------+ - */ - do { - struct vm_area_struct *vma = find_vma(current->mm, hva); - hva_t vm_start, vm_end; - - if (!vma || vma->vm_start >= reg_end) - break; - - /* - * Mapping a read-only VMA is only allowed if the - * memory region is configured as read-only. - */ - if (writable && !(vma->vm_flags & VM_WRITE)) { - ret = -EPERM; - break; - } - - /* - * Take the intersection of this VMA with the memory region - */ - vm_start = max(hva, vma->vm_start); - vm_end = min(reg_end, vma->vm_end); - - if (vma->vm_flags & VM_PFNMAP) { - gpa_t gpa = mem->guest_phys_addr + - (vm_start - mem->userspace_addr); - phys_addr_t pa; - - pa = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT; - pa += vm_start - vma->vm_start; - - /* IO region dirty page logging not allowed */ - if (memslot->flags & KVM_MEM_LOG_DIRTY_PAGES) - return -EINVAL; - - ret = kvm_phys_addr_ioremap(kvm, gpa, pa, - vm_end - vm_start, - writable); - if (ret) - break; - } - hva = vm_end; - } while (hva < reg_end); - - if (change == KVM_MR_FLAGS_ONLY) - return ret; - - spin_lock(&kvm->mmu_lock); - if (ret) - unmap_stage2_range(kvm, mem->guest_phys_addr, mem->memory_size); - else - stage2_flush_memslot(kvm, memslot); - spin_unlock(&kvm->mmu_lock); - return ret; -} - -void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free, - struct kvm_memory_slot *dont) -{ -} - -int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot, - unsigned long npages) -{ - return 0; -} - -void kvm_arch_memslots_updated(struct kvm *kvm, struct kvm_memslots *slots) -{ -} - -void kvm_arch_flush_shadow_all(struct kvm *kvm) -{ - kvm_free_stage2_pgd(kvm); -} - -void kvm_arch_flush_shadow_memslot(struct kvm *kvm, - struct kvm_memory_slot *slot) -{ - gpa_t gpa = slot->base_gfn << PAGE_SHIFT; - phys_addr_t size = slot->npages << PAGE_SHIFT; - - spin_lock(&kvm->mmu_lock); - unmap_stage2_range(kvm, gpa, size); - spin_unlock(&kvm->mmu_lock); -} - -/* - * See note at ARMv7 ARM B1.14.4 (TL;DR: S/W ops are not easily virtualized). - * - * Main problems: - * - S/W ops are local to a CPU (not broadcast) - * - We have line migration behind our back (speculation) - * - System caches don't support S/W at all (damn!) - * - * In the face of the above, the best we can do is to try and convert - * S/W ops to VA ops. Because the guest is not allowed to infer the - * S/W to PA mapping, it can only use S/W to nuke the whole cache, - * which is a rather good thing for us. - * - * Also, it is only used when turning caches on/off ("The expected - * usage of the cache maintenance instructions that operate by set/way - * is associated with the cache maintenance instructions associated - * with the powerdown and powerup of caches, if this is required by - * the implementation."). - * - * We use the following policy: - * - * - If we trap a S/W operation, we enable VM trapping to detect - * caches being turned on/off, and do a full clean. - * - * - We flush the caches on both caches being turned on and off. - * - * - Once the caches are enabled, we stop trapping VM ops. - */ -void kvm_set_way_flush(struct kvm_vcpu *vcpu) -{ - unsigned long hcr = vcpu_get_hcr(vcpu); - - /* - * If this is the first time we do a S/W operation - * (i.e. HCR_TVM not set) flush the whole memory, and set the - * VM trapping. - * - * Otherwise, rely on the VM trapping to wait for the MMU + - * Caches to be turned off. At that point, we'll be able to - * clean the caches again. - */ - if (!(hcr & HCR_TVM)) { - trace_kvm_set_way_flush(*vcpu_pc(vcpu), - vcpu_has_cache_enabled(vcpu)); - stage2_flush_vm(vcpu->kvm); - vcpu_set_hcr(vcpu, hcr | HCR_TVM); - } -} - -void kvm_toggle_cache(struct kvm_vcpu *vcpu, bool was_enabled) -{ - bool now_enabled = vcpu_has_cache_enabled(vcpu); - - /* - * If switching the MMU+caches on, need to invalidate the caches. - * If switching it off, need to clean the caches. - * Clean + invalidate does the trick always. - */ - if (now_enabled != was_enabled) - stage2_flush_vm(vcpu->kvm); - - /* Caches are now on, stop trapping VM ops (until a S/W op) */ - if (now_enabled) - vcpu_set_hcr(vcpu, vcpu_get_hcr(vcpu) & ~HCR_TVM); - - trace_kvm_toggle_cache(*vcpu_pc(vcpu), was_enabled, now_enabled); -} diff --git a/arch/arm/kvm/perf.c b/arch/arm/kvm/perf.c deleted file mode 100644 index 1a3849da0b4b..000000000000 --- a/arch/arm/kvm/perf.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Based on the x86 implementation. - * - * Copyright (C) 2012 ARM Ltd. - * Author: Marc Zyngier - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include - -#include - -static int kvm_is_in_guest(void) -{ - return kvm_arm_get_running_vcpu() != NULL; -} - -static int kvm_is_user_mode(void) -{ - struct kvm_vcpu *vcpu; - - vcpu = kvm_arm_get_running_vcpu(); - - if (vcpu) - return !vcpu_mode_priv(vcpu); - - return 0; -} - -static unsigned long kvm_get_guest_ip(void) -{ - struct kvm_vcpu *vcpu; - - vcpu = kvm_arm_get_running_vcpu(); - - if (vcpu) - return *vcpu_pc(vcpu); - - return 0; -} - -static struct perf_guest_info_callbacks kvm_guest_cbs = { - .is_in_guest = kvm_is_in_guest, - .is_user_mode = kvm_is_user_mode, - .get_guest_ip = kvm_get_guest_ip, -}; - -int kvm_perf_init(void) -{ - return perf_register_guest_info_callbacks(&kvm_guest_cbs); -} - -int kvm_perf_teardown(void) -{ - return perf_unregister_guest_info_callbacks(&kvm_guest_cbs); -} diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c deleted file mode 100644 index a08d7a93aebb..000000000000 --- a/arch/arm/kvm/psci.c +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (C) 2012 - ARM Ltd - * Author: Marc Zyngier - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include - -#include -#include -#include -#include - -#include - -/* - * This is an implementation of the Power State Coordination Interface - * as described in ARM document number ARM DEN 0022A. - */ - -#define AFFINITY_MASK(level) ~((0x1UL << ((level) * MPIDR_LEVEL_BITS)) - 1) - -static unsigned long psci_affinity_mask(unsigned long affinity_level) -{ - if (affinity_level <= 3) - return MPIDR_HWID_BITMASK & AFFINITY_MASK(affinity_level); - - return 0; -} - -static unsigned long kvm_psci_vcpu_suspend(struct kvm_vcpu *vcpu) -{ - /* - * NOTE: For simplicity, we make VCPU suspend emulation to be - * same-as WFI (Wait-for-interrupt) emulation. - * - * This means for KVM the wakeup events are interrupts and - * this is consistent with intended use of StateID as described - * in section 5.4.1 of PSCI v0.2 specification (ARM DEN 0022A). - * - * Further, we also treat power-down request to be same as - * stand-by request as-per section 5.4.2 clause 3 of PSCI v0.2 - * specification (ARM DEN 0022A). This means all suspend states - * for KVM will preserve the register state. - */ - kvm_vcpu_block(vcpu); - - return PSCI_RET_SUCCESS; -} - -static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu) -{ - vcpu->arch.power_off = true; -} - -static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) -{ - struct kvm *kvm = source_vcpu->kvm; - struct kvm_vcpu *vcpu = NULL; - struct swait_queue_head *wq; - unsigned long cpu_id; - unsigned long context_id; - phys_addr_t target_pc; - - cpu_id = vcpu_get_reg(source_vcpu, 1) & MPIDR_HWID_BITMASK; - if (vcpu_mode_is_32bit(source_vcpu)) - cpu_id &= ~((u32) 0); - - vcpu = kvm_mpidr_to_vcpu(kvm, cpu_id); - - /* - * Make sure the caller requested a valid CPU and that the CPU is - * turned off. - */ - if (!vcpu) - return PSCI_RET_INVALID_PARAMS; - if (!vcpu->arch.power_off) { - if (kvm_psci_version(source_vcpu) != KVM_ARM_PSCI_0_1) - return PSCI_RET_ALREADY_ON; - else - return PSCI_RET_INVALID_PARAMS; - } - - target_pc = vcpu_get_reg(source_vcpu, 2); - context_id = vcpu_get_reg(source_vcpu, 3); - - kvm_reset_vcpu(vcpu); - - /* Gracefully handle Thumb2 entry point */ - if (vcpu_mode_is_32bit(vcpu) && (target_pc & 1)) { - target_pc &= ~((phys_addr_t) 1); - vcpu_set_thumb(vcpu); - } - - /* Propagate caller endianness */ - if (kvm_vcpu_is_be(source_vcpu)) - kvm_vcpu_set_be(vcpu); - - *vcpu_pc(vcpu) = target_pc; - /* - * NOTE: We always update r0 (or x0) because for PSCI v0.1 - * the general puspose registers are undefined upon CPU_ON. - */ - vcpu_set_reg(vcpu, 0, context_id); - vcpu->arch.power_off = false; - smp_mb(); /* Make sure the above is visible */ - - wq = kvm_arch_vcpu_wq(vcpu); - swake_up(wq); - - return PSCI_RET_SUCCESS; -} - -static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu) -{ - int i, matching_cpus = 0; - unsigned long mpidr; - unsigned long target_affinity; - unsigned long target_affinity_mask; - unsigned long lowest_affinity_level; - struct kvm *kvm = vcpu->kvm; - struct kvm_vcpu *tmp; - - target_affinity = vcpu_get_reg(vcpu, 1); - lowest_affinity_level = vcpu_get_reg(vcpu, 2); - - /* Determine target affinity mask */ - target_affinity_mask = psci_affinity_mask(lowest_affinity_level); - if (!target_affinity_mask) - return PSCI_RET_INVALID_PARAMS; - - /* Ignore other bits of target affinity */ - target_affinity &= target_affinity_mask; - - /* - * If one or more VCPU matching target affinity are running - * then ON else OFF - */ - kvm_for_each_vcpu(i, tmp, kvm) { - mpidr = kvm_vcpu_get_mpidr_aff(tmp); - if ((mpidr & target_affinity_mask) == target_affinity) { - matching_cpus++; - if (!tmp->arch.power_off) - return PSCI_0_2_AFFINITY_LEVEL_ON; - } - } - - if (!matching_cpus) - return PSCI_RET_INVALID_PARAMS; - - return PSCI_0_2_AFFINITY_LEVEL_OFF; -} - -static void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type) -{ - int i; - struct kvm_vcpu *tmp; - - /* - * The KVM ABI specifies that a system event exit may call KVM_RUN - * again and may perform shutdown/reboot at a later time that when the - * actual request is made. Since we are implementing PSCI and a - * caller of PSCI reboot and shutdown expects that the system shuts - * down or reboots immediately, let's make sure that VCPUs are not run - * after this call is handled and before the VCPUs have been - * re-initialized. - */ - kvm_for_each_vcpu(i, tmp, vcpu->kvm) { - tmp->arch.power_off = true; - kvm_vcpu_kick(tmp); - } - - memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event)); - vcpu->run->system_event.type = type; - vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT; -} - -static void kvm_psci_system_off(struct kvm_vcpu *vcpu) -{ - kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_SHUTDOWN); -} - -static void kvm_psci_system_reset(struct kvm_vcpu *vcpu) -{ - kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_RESET); -} - -int kvm_psci_version(struct kvm_vcpu *vcpu) -{ - if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) - return KVM_ARM_PSCI_0_2; - - return KVM_ARM_PSCI_0_1; -} - -static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) -{ - struct kvm *kvm = vcpu->kvm; - unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0); - unsigned long val; - int ret = 1; - - switch (psci_fn) { - case PSCI_0_2_FN_PSCI_VERSION: - /* - * Bits[31:16] = Major Version = 0 - * Bits[15:0] = Minor Version = 2 - */ - val = 2; - break; - case PSCI_0_2_FN_CPU_SUSPEND: - case PSCI_0_2_FN64_CPU_SUSPEND: - val = kvm_psci_vcpu_suspend(vcpu); - break; - case PSCI_0_2_FN_CPU_OFF: - kvm_psci_vcpu_off(vcpu); - val = PSCI_RET_SUCCESS; - break; - case PSCI_0_2_FN_CPU_ON: - case PSCI_0_2_FN64_CPU_ON: - mutex_lock(&kvm->lock); - val = kvm_psci_vcpu_on(vcpu); - mutex_unlock(&kvm->lock); - break; - case PSCI_0_2_FN_AFFINITY_INFO: - case PSCI_0_2_FN64_AFFINITY_INFO: - val = kvm_psci_vcpu_affinity_info(vcpu); - break; - case PSCI_0_2_FN_MIGRATE_INFO_TYPE: - /* - * Trusted OS is MP hence does not require migration - * or - * Trusted OS is not present - */ - val = PSCI_0_2_TOS_MP; - break; - case PSCI_0_2_FN_SYSTEM_OFF: - kvm_psci_system_off(vcpu); - /* - * We should'nt be going back to guest VCPU after - * receiving SYSTEM_OFF request. - * - * If user space accidently/deliberately resumes - * guest VCPU after SYSTEM_OFF request then guest - * VCPU should see internal failure from PSCI return - * value. To achieve this, we preload r0 (or x0) with - * PSCI return value INTERNAL_FAILURE. - */ - val = PSCI_RET_INTERNAL_FAILURE; - ret = 0; - break; - case PSCI_0_2_FN_SYSTEM_RESET: - kvm_psci_system_reset(vcpu); - /* - * Same reason as SYSTEM_OFF for preloading r0 (or x0) - * with PSCI return value INTERNAL_FAILURE. - */ - val = PSCI_RET_INTERNAL_FAILURE; - ret = 0; - break; - default: - val = PSCI_RET_NOT_SUPPORTED; - break; - } - - vcpu_set_reg(vcpu, 0, val); - return ret; -} - -static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) -{ - struct kvm *kvm = vcpu->kvm; - unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0); - unsigned long val; - - switch (psci_fn) { - case KVM_PSCI_FN_CPU_OFF: - kvm_psci_vcpu_off(vcpu); - val = PSCI_RET_SUCCESS; - break; - case KVM_PSCI_FN_CPU_ON: - mutex_lock(&kvm->lock); - val = kvm_psci_vcpu_on(vcpu); - mutex_unlock(&kvm->lock); - break; - default: - val = PSCI_RET_NOT_SUPPORTED; - break; - } - - vcpu_set_reg(vcpu, 0, val); - return 1; -} - -/** - * kvm_psci_call - handle PSCI call if r0 value is in range - * @vcpu: Pointer to the VCPU struct - * - * Handle PSCI calls from guests through traps from HVC instructions. - * The calling convention is similar to SMC calls to the secure world - * where the function number is placed in r0. - * - * This function returns: > 0 (success), 0 (success but exit to user - * space), and < 0 (errors) - * - * Errors: - * -EINVAL: Unrecognized PSCI function - */ -int kvm_psci_call(struct kvm_vcpu *vcpu) -{ - switch (kvm_psci_version(vcpu)) { - case KVM_ARM_PSCI_0_2: - return kvm_psci_0_2_call(vcpu); - case KVM_ARM_PSCI_0_1: - return kvm_psci_0_1_call(vcpu); - default: - return -EINVAL; - }; -} diff --git a/arch/arm/kvm/trace.h b/arch/arm/kvm/trace.h index c25a88598eb0..fc0943776db2 100644 --- a/arch/arm/kvm/trace.h +++ b/arch/arm/kvm/trace.h @@ -6,133 +6,6 @@ #undef TRACE_SYSTEM #define TRACE_SYSTEM kvm -/* - * Tracepoints for entry/exit to guest - */ -TRACE_EVENT(kvm_entry, - TP_PROTO(unsigned long vcpu_pc), - TP_ARGS(vcpu_pc), - - TP_STRUCT__entry( - __field( unsigned long, vcpu_pc ) - ), - - TP_fast_assign( - __entry->vcpu_pc = vcpu_pc; - ), - - TP_printk("PC: 0x%08lx", __entry->vcpu_pc) -); - -TRACE_EVENT(kvm_exit, - TP_PROTO(int idx, unsigned int exit_reason, unsigned long vcpu_pc), - TP_ARGS(idx, exit_reason, vcpu_pc), - - TP_STRUCT__entry( - __field( int, idx ) - __field( unsigned int, exit_reason ) - __field( unsigned long, vcpu_pc ) - ), - - TP_fast_assign( - __entry->idx = idx; - __entry->exit_reason = exit_reason; - __entry->vcpu_pc = vcpu_pc; - ), - - TP_printk("%s: HSR_EC: 0x%04x (%s), PC: 0x%08lx", - __print_symbolic(__entry->idx, kvm_arm_exception_type), - __entry->exit_reason, - __print_symbolic(__entry->exit_reason, kvm_arm_exception_class), - __entry->vcpu_pc) -); - -TRACE_EVENT(kvm_guest_fault, - TP_PROTO(unsigned long vcpu_pc, unsigned long hsr, - unsigned long hxfar, - unsigned long long ipa), - TP_ARGS(vcpu_pc, hsr, hxfar, ipa), - - TP_STRUCT__entry( - __field( unsigned long, vcpu_pc ) - __field( unsigned long, hsr ) - __field( unsigned long, hxfar ) - __field( unsigned long long, ipa ) - ), - - TP_fast_assign( - __entry->vcpu_pc = vcpu_pc; - __entry->hsr = hsr; - __entry->hxfar = hxfar; - __entry->ipa = ipa; - ), - - TP_printk("ipa %#llx, hsr %#08lx, hxfar %#08lx, pc %#08lx", - __entry->ipa, __entry->hsr, - __entry->hxfar, __entry->vcpu_pc) -); - -TRACE_EVENT(kvm_access_fault, - TP_PROTO(unsigned long ipa), - TP_ARGS(ipa), - - TP_STRUCT__entry( - __field( unsigned long, ipa ) - ), - - TP_fast_assign( - __entry->ipa = ipa; - ), - - TP_printk("IPA: %lx", __entry->ipa) -); - -TRACE_EVENT(kvm_irq_line, - TP_PROTO(unsigned int type, int vcpu_idx, int irq_num, int level), - TP_ARGS(type, vcpu_idx, irq_num, level), - - TP_STRUCT__entry( - __field( unsigned int, type ) - __field( int, vcpu_idx ) - __field( int, irq_num ) - __field( int, level ) - ), - - TP_fast_assign( - __entry->type = type; - __entry->vcpu_idx = vcpu_idx; - __entry->irq_num = irq_num; - __entry->level = level; - ), - - TP_printk("Inject %s interrupt (%d), vcpu->idx: %d, num: %d, level: %d", - (__entry->type == KVM_ARM_IRQ_TYPE_CPU) ? "CPU" : - (__entry->type == KVM_ARM_IRQ_TYPE_PPI) ? "VGIC PPI" : - (__entry->type == KVM_ARM_IRQ_TYPE_SPI) ? "VGIC SPI" : "UNKNOWN", - __entry->type, __entry->vcpu_idx, __entry->irq_num, __entry->level) -); - -TRACE_EVENT(kvm_mmio_emulate, - TP_PROTO(unsigned long vcpu_pc, unsigned long instr, - unsigned long cpsr), - TP_ARGS(vcpu_pc, instr, cpsr), - - TP_STRUCT__entry( - __field( unsigned long, vcpu_pc ) - __field( unsigned long, instr ) - __field( unsigned long, cpsr ) - ), - - TP_fast_assign( - __entry->vcpu_pc = vcpu_pc; - __entry->instr = instr; - __entry->cpsr = cpsr; - ), - - TP_printk("Emulate MMIO at: 0x%08lx (instr: %08lx, cpsr: %08lx)", - __entry->vcpu_pc, __entry->instr, __entry->cpsr) -); - /* Architecturally implementation defined CP15 register access */ TRACE_EVENT(kvm_emulate_cp15_imp, TP_PROTO(unsigned long Op1, unsigned long Rt1, unsigned long CRn, @@ -181,87 +54,6 @@ TRACE_EVENT(kvm_wfx, __entry->is_wfe ? 'e' : 'i', __entry->vcpu_pc) ); -TRACE_EVENT(kvm_unmap_hva, - TP_PROTO(unsigned long hva), - TP_ARGS(hva), - - TP_STRUCT__entry( - __field( unsigned long, hva ) - ), - - TP_fast_assign( - __entry->hva = hva; - ), - - TP_printk("mmu notifier unmap hva: %#08lx", __entry->hva) -); - -TRACE_EVENT(kvm_unmap_hva_range, - TP_PROTO(unsigned long start, unsigned long end), - TP_ARGS(start, end), - - TP_STRUCT__entry( - __field( unsigned long, start ) - __field( unsigned long, end ) - ), - - TP_fast_assign( - __entry->start = start; - __entry->end = end; - ), - - TP_printk("mmu notifier unmap range: %#08lx -- %#08lx", - __entry->start, __entry->end) -); - -TRACE_EVENT(kvm_set_spte_hva, - TP_PROTO(unsigned long hva), - TP_ARGS(hva), - - TP_STRUCT__entry( - __field( unsigned long, hva ) - ), - - TP_fast_assign( - __entry->hva = hva; - ), - - TP_printk("mmu notifier set pte hva: %#08lx", __entry->hva) -); - -TRACE_EVENT(kvm_age_hva, - TP_PROTO(unsigned long start, unsigned long end), - TP_ARGS(start, end), - - TP_STRUCT__entry( - __field( unsigned long, start ) - __field( unsigned long, end ) - ), - - TP_fast_assign( - __entry->start = start; - __entry->end = end; - ), - - TP_printk("mmu notifier age hva: %#08lx -- %#08lx", - __entry->start, __entry->end) -); - -TRACE_EVENT(kvm_test_age_hva, - TP_PROTO(unsigned long hva), - TP_ARGS(hva), - - TP_STRUCT__entry( - __field( unsigned long, hva ) - ), - - TP_fast_assign( - __entry->hva = hva; - ), - - TP_printk("mmu notifier test age hva: %#08lx", __entry->hva) -); - TRACE_EVENT(kvm_hvc, TP_PROTO(unsigned long vcpu_pc, unsigned long r0, unsigned long imm), TP_ARGS(vcpu_pc, r0, imm), @@ -282,45 +74,6 @@ TRACE_EVENT(kvm_hvc, __entry->vcpu_pc, __entry->r0, __entry->imm) ); -TRACE_EVENT(kvm_set_way_flush, - TP_PROTO(unsigned long vcpu_pc, bool cache), - TP_ARGS(vcpu_pc, cache), - - TP_STRUCT__entry( - __field( unsigned long, vcpu_pc ) - __field( bool, cache ) - ), - - TP_fast_assign( - __entry->vcpu_pc = vcpu_pc; - __entry->cache = cache; - ), - - TP_printk("S/W flush at 0x%016lx (cache %s)", - __entry->vcpu_pc, __entry->cache ? "on" : "off") -); - -TRACE_EVENT(kvm_toggle_cache, - TP_PROTO(unsigned long vcpu_pc, bool was, bool now), - TP_ARGS(vcpu_pc, was, now), - - TP_STRUCT__entry( - __field( unsigned long, vcpu_pc ) - __field( bool, was ) - __field( bool, now ) - ), - - TP_fast_assign( - __entry->vcpu_pc = vcpu_pc; - __entry->was = was; - __entry->now = now; - ), - - TP_printk("VM op at 0x%016lx (cache was %s, now %s)", - __entry->vcpu_pc, __entry->was ? "on" : "off", - __entry->now ? "on" : "off") -); - #endif /* _TRACE_KVM_H */ #undef TRACE_INCLUDE_PATH diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile index afd51bebb9c5..5d9810086c25 100644 --- a/arch/arm64/kvm/Makefile +++ b/arch/arm64/kvm/Makefile @@ -7,14 +7,13 @@ CFLAGS_arm.o := -I. CFLAGS_mmu.o := -I. KVM=../../../virt/kvm -ARM=../../../arch/arm/kvm obj-$(CONFIG_KVM_ARM_HOST) += kvm.o obj-$(CONFIG_KVM_ARM_HOST) += hyp/ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o $(KVM)/vfio.o -kvm-$(CONFIG_KVM_ARM_HOST) += $(ARM)/arm.o $(ARM)/mmu.o $(ARM)/mmio.o -kvm-$(CONFIG_KVM_ARM_HOST) += $(ARM)/psci.o $(ARM)/perf.o +kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arm.o $(KVM)/arm/mmu.o $(KVM)/arm/mmio.o +kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/psci.o $(KVM)/arm/perf.o kvm-$(CONFIG_KVM_ARM_HOST) += inject_fault.o regmap.o kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c new file mode 100644 index 000000000000..7941699a766d --- /dev/null +++ b/virt/kvm/arm/arm.c @@ -0,0 +1,1480 @@ +/* + * Copyright (C) 2012 - Virtual Open Systems and Columbia University + * Author: Christoffer Dall + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CREATE_TRACE_POINTS +#include "trace.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef REQUIRES_VIRT +__asm__(".arch_extension virt"); +#endif + +static DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page); +static kvm_cpu_context_t __percpu *kvm_host_cpu_state; + +/* Per-CPU variable containing the currently running vcpu. */ +static DEFINE_PER_CPU(struct kvm_vcpu *, kvm_arm_running_vcpu); + +/* The VMID used in the VTTBR */ +static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1); +static u32 kvm_next_vmid; +static unsigned int kvm_vmid_bits __read_mostly; +static DEFINE_SPINLOCK(kvm_vmid_lock); + +static bool vgic_present; + +static DEFINE_PER_CPU(unsigned char, kvm_arm_hardware_enabled); + +static void kvm_arm_set_running_vcpu(struct kvm_vcpu *vcpu) +{ + BUG_ON(preemptible()); + __this_cpu_write(kvm_arm_running_vcpu, vcpu); +} + +/** + * kvm_arm_get_running_vcpu - get the vcpu running on the current CPU. + * Must be called from non-preemptible context + */ +struct kvm_vcpu *kvm_arm_get_running_vcpu(void) +{ + BUG_ON(preemptible()); + return __this_cpu_read(kvm_arm_running_vcpu); +} + +/** + * kvm_arm_get_running_vcpus - get the per-CPU array of currently running vcpus. + */ +struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void) +{ + return &kvm_arm_running_vcpu; +} + +int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu) +{ + return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE; +} + +int kvm_arch_hardware_setup(void) +{ + return 0; +} + +void kvm_arch_check_processor_compat(void *rtn) +{ + *(int *)rtn = 0; +} + + +/** + * kvm_arch_init_vm - initializes a VM data structure + * @kvm: pointer to the KVM struct + */ +int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) +{ + int ret, cpu; + + if (type) + return -EINVAL; + + kvm->arch.last_vcpu_ran = alloc_percpu(typeof(*kvm->arch.last_vcpu_ran)); + if (!kvm->arch.last_vcpu_ran) + return -ENOMEM; + + for_each_possible_cpu(cpu) + *per_cpu_ptr(kvm->arch.last_vcpu_ran, cpu) = -1; + + ret = kvm_alloc_stage2_pgd(kvm); + if (ret) + goto out_fail_alloc; + + ret = create_hyp_mappings(kvm, kvm + 1, PAGE_HYP); + if (ret) + goto out_free_stage2_pgd; + + kvm_vgic_early_init(kvm); + + /* Mark the initial VMID generation invalid */ + kvm->arch.vmid_gen = 0; + + /* The maximum number of VCPUs is limited by the host's GIC model */ + kvm->arch.max_vcpus = vgic_present ? + kvm_vgic_get_max_vcpus() : KVM_MAX_VCPUS; + + return ret; +out_free_stage2_pgd: + kvm_free_stage2_pgd(kvm); +out_fail_alloc: + free_percpu(kvm->arch.last_vcpu_ran); + kvm->arch.last_vcpu_ran = NULL; + return ret; +} + +bool kvm_arch_has_vcpu_debugfs(void) +{ + return false; +} + +int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu) +{ + return 0; +} + +int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf) +{ + return VM_FAULT_SIGBUS; +} + + +/** + * kvm_arch_destroy_vm - destroy the VM data structure + * @kvm: pointer to the KVM struct + */ +void kvm_arch_destroy_vm(struct kvm *kvm) +{ + int i; + + free_percpu(kvm->arch.last_vcpu_ran); + kvm->arch.last_vcpu_ran = NULL; + + for (i = 0; i < KVM_MAX_VCPUS; ++i) { + if (kvm->vcpus[i]) { + kvm_arch_vcpu_free(kvm->vcpus[i]); + kvm->vcpus[i] = NULL; + } + } + + kvm_vgic_destroy(kvm); +} + +int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) +{ + int r; + switch (ext) { + case KVM_CAP_IRQCHIP: + r = vgic_present; + break; + case KVM_CAP_IOEVENTFD: + case KVM_CAP_DEVICE_CTRL: + case KVM_CAP_USER_MEMORY: + case KVM_CAP_SYNC_MMU: + case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: + case KVM_CAP_ONE_REG: + case KVM_CAP_ARM_PSCI: + case KVM_CAP_ARM_PSCI_0_2: + case KVM_CAP_READONLY_MEM: + case KVM_CAP_MP_STATE: + case KVM_CAP_IMMEDIATE_EXIT: + r = 1; + break; + case KVM_CAP_COALESCED_MMIO: + r = KVM_COALESCED_MMIO_PAGE_OFFSET; + break; + case KVM_CAP_ARM_SET_DEVICE_ADDR: + r = 1; + break; + case KVM_CAP_NR_VCPUS: + r = num_online_cpus(); + break; + case KVM_CAP_MAX_VCPUS: + r = KVM_MAX_VCPUS; + break; + case KVM_CAP_NR_MEMSLOTS: + r = KVM_USER_MEM_SLOTS; + break; + case KVM_CAP_MSI_DEVID: + if (!kvm) + r = -EINVAL; + else + r = kvm->arch.vgic.msis_require_devid; + break; + case KVM_CAP_ARM_USER_IRQ: + /* + * 1: EL1_VTIMER, EL1_PTIMER, and PMU. + * (bump this number if adding more devices) + */ + r = 1; + break; + default: + r = kvm_arch_dev_ioctl_check_extension(kvm, ext); + break; + } + return r; +} + +long kvm_arch_dev_ioctl(struct file *filp, + unsigned int ioctl, unsigned long arg) +{ + return -EINVAL; +} + + +struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id) +{ + int err; + struct kvm_vcpu *vcpu; + + if (irqchip_in_kernel(kvm) && vgic_initialized(kvm)) { + err = -EBUSY; + goto out; + } + + if (id >= kvm->arch.max_vcpus) { + err = -EINVAL; + goto out; + } + + vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); + if (!vcpu) { + err = -ENOMEM; + goto out; + } + + err = kvm_vcpu_init(vcpu, kvm, id); + if (err) + goto free_vcpu; + + err = create_hyp_mappings(vcpu, vcpu + 1, PAGE_HYP); + if (err) + goto vcpu_uninit; + + return vcpu; +vcpu_uninit: + kvm_vcpu_uninit(vcpu); +free_vcpu: + kmem_cache_free(kvm_vcpu_cache, vcpu); +out: + return ERR_PTR(err); +} + +void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) +{ + kvm_vgic_vcpu_early_init(vcpu); +} + +void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu) +{ + kvm_mmu_free_memory_caches(vcpu); + kvm_timer_vcpu_terminate(vcpu); + kvm_vgic_vcpu_destroy(vcpu); + kvm_pmu_vcpu_destroy(vcpu); + kvm_vcpu_uninit(vcpu); + kmem_cache_free(kvm_vcpu_cache, vcpu); +} + +void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) +{ + kvm_arch_vcpu_free(vcpu); +} + +int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu) +{ + return kvm_timer_should_fire(vcpu_vtimer(vcpu)) || + kvm_timer_should_fire(vcpu_ptimer(vcpu)); +} + +void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu) +{ + kvm_timer_schedule(vcpu); +} + +void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) +{ + kvm_timer_unschedule(vcpu); +} + +int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) +{ + /* Force users to call KVM_ARM_VCPU_INIT */ + vcpu->arch.target = -1; + bitmap_zero(vcpu->arch.features, KVM_VCPU_MAX_FEATURES); + + /* Set up the timer */ + kvm_timer_vcpu_init(vcpu); + + kvm_arm_reset_debug_ptr(vcpu); + + return 0; +} + +void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) +{ + int *last_ran; + + last_ran = this_cpu_ptr(vcpu->kvm->arch.last_vcpu_ran); + + /* + * We might get preempted before the vCPU actually runs, but + * over-invalidation doesn't affect correctness. + */ + if (*last_ran != vcpu->vcpu_id) { + kvm_call_hyp(__kvm_tlb_flush_local_vmid, vcpu); + *last_ran = vcpu->vcpu_id; + } + + vcpu->cpu = cpu; + vcpu->arch.host_cpu_context = this_cpu_ptr(kvm_host_cpu_state); + + kvm_arm_set_running_vcpu(vcpu); + + kvm_vgic_load(vcpu); +} + +void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) +{ + kvm_vgic_put(vcpu); + + vcpu->cpu = -1; + + kvm_arm_set_running_vcpu(NULL); + kvm_timer_vcpu_put(vcpu); +} + +int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu, + struct kvm_mp_state *mp_state) +{ + if (vcpu->arch.power_off) + mp_state->mp_state = KVM_MP_STATE_STOPPED; + else + mp_state->mp_state = KVM_MP_STATE_RUNNABLE; + + return 0; +} + +int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, + struct kvm_mp_state *mp_state) +{ + switch (mp_state->mp_state) { + case KVM_MP_STATE_RUNNABLE: + vcpu->arch.power_off = false; + break; + case KVM_MP_STATE_STOPPED: + vcpu->arch.power_off = true; + break; + default: + return -EINVAL; + } + + return 0; +} + +/** + * kvm_arch_vcpu_runnable - determine if the vcpu can be scheduled + * @v: The VCPU pointer + * + * If the guest CPU is not waiting for interrupts or an interrupt line is + * asserted, the CPU is by definition runnable. + */ +int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) +{ + return ((!!v->arch.irq_lines || kvm_vgic_vcpu_pending_irq(v)) + && !v->arch.power_off && !v->arch.pause); +} + +/* Just ensure a guest exit from a particular CPU */ +static void exit_vm_noop(void *info) +{ +} + +void force_vm_exit(const cpumask_t *mask) +{ + preempt_disable(); + smp_call_function_many(mask, exit_vm_noop, NULL, true); + preempt_enable(); +} + +/** + * need_new_vmid_gen - check that the VMID is still valid + * @kvm: The VM's VMID to check + * + * return true if there is a new generation of VMIDs being used + * + * The hardware supports only 256 values with the value zero reserved for the + * host, so we check if an assigned value belongs to a previous generation, + * which which requires us to assign a new value. If we're the first to use a + * VMID for the new generation, we must flush necessary caches and TLBs on all + * CPUs. + */ +static bool need_new_vmid_gen(struct kvm *kvm) +{ + return unlikely(kvm->arch.vmid_gen != atomic64_read(&kvm_vmid_gen)); +} + +/** + * update_vttbr - Update the VTTBR with a valid VMID before the guest runs + * @kvm The guest that we are about to run + * + * Called from kvm_arch_vcpu_ioctl_run before entering the guest to ensure the + * VM has a valid VMID, otherwise assigns a new one and flushes corresponding + * caches and TLBs. + */ +static void update_vttbr(struct kvm *kvm) +{ + phys_addr_t pgd_phys; + u64 vmid; + + if (!need_new_vmid_gen(kvm)) + return; + + spin_lock(&kvm_vmid_lock); + + /* + * We need to re-check the vmid_gen here to ensure that if another vcpu + * already allocated a valid vmid for this vm, then this vcpu should + * use the same vmid. + */ + if (!need_new_vmid_gen(kvm)) { + spin_unlock(&kvm_vmid_lock); + return; + } + + /* First user of a new VMID generation? */ + if (unlikely(kvm_next_vmid == 0)) { + atomic64_inc(&kvm_vmid_gen); + kvm_next_vmid = 1; + + /* + * On SMP we know no other CPUs can use this CPU's or each + * other's VMID after force_vm_exit returns since the + * kvm_vmid_lock blocks them from reentry to the guest. + */ + force_vm_exit(cpu_all_mask); + /* + * Now broadcast TLB + ICACHE invalidation over the inner + * shareable domain to make sure all data structures are + * clean. + */ + kvm_call_hyp(__kvm_flush_vm_context); + } + + kvm->arch.vmid_gen = atomic64_read(&kvm_vmid_gen); + kvm->arch.vmid = kvm_next_vmid; + kvm_next_vmid++; + kvm_next_vmid &= (1 << kvm_vmid_bits) - 1; + + /* update vttbr to be used with the new vmid */ + pgd_phys = virt_to_phys(kvm->arch.pgd); + BUG_ON(pgd_phys & ~VTTBR_BADDR_MASK); + vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK(kvm_vmid_bits); + kvm->arch.vttbr = pgd_phys | vmid; + + spin_unlock(&kvm_vmid_lock); +} + +static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) +{ + struct kvm *kvm = vcpu->kvm; + int ret = 0; + + if (likely(vcpu->arch.has_run_once)) + return 0; + + vcpu->arch.has_run_once = true; + + /* + * Map the VGIC hardware resources before running a vcpu the first + * time on this VM. + */ + if (unlikely(irqchip_in_kernel(kvm) && !vgic_ready(kvm))) { + ret = kvm_vgic_map_resources(kvm); + if (ret) + return ret; + } + + ret = kvm_timer_enable(vcpu); + + return ret; +} + +bool kvm_arch_intc_initialized(struct kvm *kvm) +{ + return vgic_initialized(kvm); +} + +void kvm_arm_halt_guest(struct kvm *kvm) +{ + int i; + struct kvm_vcpu *vcpu; + + kvm_for_each_vcpu(i, vcpu, kvm) + vcpu->arch.pause = true; + kvm_make_all_cpus_request(kvm, KVM_REQ_VCPU_EXIT); +} + +void kvm_arm_halt_vcpu(struct kvm_vcpu *vcpu) +{ + vcpu->arch.pause = true; + kvm_vcpu_kick(vcpu); +} + +void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu) +{ + struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu); + + vcpu->arch.pause = false; + swake_up(wq); +} + +void kvm_arm_resume_guest(struct kvm *kvm) +{ + int i; + struct kvm_vcpu *vcpu; + + kvm_for_each_vcpu(i, vcpu, kvm) + kvm_arm_resume_vcpu(vcpu); +} + +static void vcpu_sleep(struct kvm_vcpu *vcpu) +{ + struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu); + + swait_event_interruptible(*wq, ((!vcpu->arch.power_off) && + (!vcpu->arch.pause))); +} + +static int kvm_vcpu_initialized(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.target >= 0; +} + +/** + * kvm_arch_vcpu_ioctl_run - the main VCPU run function to execute guest code + * @vcpu: The VCPU pointer + * @run: The kvm_run structure pointer used for userspace state exchange + * + * This function is called through the VCPU_RUN ioctl called from user space. It + * will execute VM code in a loop until the time slice for the process is used + * or some emulation is needed from user space in which case the function will + * return with return value 0 and with the kvm_run structure filled in with the + * required data for the requested emulation. + */ +int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + int ret; + sigset_t sigsaved; + + if (unlikely(!kvm_vcpu_initialized(vcpu))) + return -ENOEXEC; + + ret = kvm_vcpu_first_run_init(vcpu); + if (ret) + return ret; + + if (run->exit_reason == KVM_EXIT_MMIO) { + ret = kvm_handle_mmio_return(vcpu, vcpu->run); + if (ret) + return ret; + } + + if (run->immediate_exit) + return -EINTR; + + if (vcpu->sigset_active) + sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved); + + ret = 1; + run->exit_reason = KVM_EXIT_UNKNOWN; + while (ret > 0) { + /* + * Check conditions before entering the guest + */ + cond_resched(); + + update_vttbr(vcpu->kvm); + + if (vcpu->arch.power_off || vcpu->arch.pause) + vcpu_sleep(vcpu); + + /* + * Preparing the interrupts to be injected also + * involves poking the GIC, which must be done in a + * non-preemptible context. + */ + preempt_disable(); + + kvm_pmu_flush_hwstate(vcpu); + + kvm_timer_flush_hwstate(vcpu); + kvm_vgic_flush_hwstate(vcpu); + + local_irq_disable(); + + /* + * If we have a singal pending, or need to notify a userspace + * irqchip about timer or PMU level changes, then we exit (and + * update the timer level state in kvm_timer_update_run + * below). + */ + if (signal_pending(current) || + kvm_timer_should_notify_user(vcpu) || + kvm_pmu_should_notify_user(vcpu)) { + ret = -EINTR; + run->exit_reason = KVM_EXIT_INTR; + } + + if (ret <= 0 || need_new_vmid_gen(vcpu->kvm) || + vcpu->arch.power_off || vcpu->arch.pause) { + local_irq_enable(); + kvm_pmu_sync_hwstate(vcpu); + kvm_timer_sync_hwstate(vcpu); + kvm_vgic_sync_hwstate(vcpu); + preempt_enable(); + continue; + } + + kvm_arm_setup_debug(vcpu); + + /************************************************************** + * Enter the guest + */ + trace_kvm_entry(*vcpu_pc(vcpu)); + guest_enter_irqoff(); + vcpu->mode = IN_GUEST_MODE; + + ret = kvm_call_hyp(__kvm_vcpu_run, vcpu); + + vcpu->mode = OUTSIDE_GUEST_MODE; + vcpu->stat.exits++; + /* + * Back from guest + *************************************************************/ + + kvm_arm_clear_debug(vcpu); + + /* + * We may have taken a host interrupt in HYP mode (ie + * while executing the guest). This interrupt is still + * pending, as we haven't serviced it yet! + * + * We're now back in SVC mode, with interrupts + * disabled. Enabling the interrupts now will have + * the effect of taking the interrupt again, in SVC + * mode this time. + */ + local_irq_enable(); + + /* + * We do local_irq_enable() before calling guest_exit() so + * that if a timer interrupt hits while running the guest we + * account that tick as being spent in the guest. We enable + * preemption after calling guest_exit() so that if we get + * preempted we make sure ticks after that is not counted as + * guest time. + */ + guest_exit(); + trace_kvm_exit(ret, kvm_vcpu_trap_get_class(vcpu), *vcpu_pc(vcpu)); + + /* + * We must sync the PMU and timer state before the vgic state so + * that the vgic can properly sample the updated state of the + * interrupt line. + */ + kvm_pmu_sync_hwstate(vcpu); + kvm_timer_sync_hwstate(vcpu); + + kvm_vgic_sync_hwstate(vcpu); + + preempt_enable(); + + ret = handle_exit(vcpu, run, ret); + } + + /* Tell userspace about in-kernel device output levels */ + if (unlikely(!irqchip_in_kernel(vcpu->kvm))) { + kvm_timer_update_run(vcpu); + kvm_pmu_update_run(vcpu); + } + + if (vcpu->sigset_active) + sigprocmask(SIG_SETMASK, &sigsaved, NULL); + return ret; +} + +static int vcpu_interrupt_line(struct kvm_vcpu *vcpu, int number, bool level) +{ + int bit_index; + bool set; + unsigned long *ptr; + + if (number == KVM_ARM_IRQ_CPU_IRQ) + bit_index = __ffs(HCR_VI); + else /* KVM_ARM_IRQ_CPU_FIQ */ + bit_index = __ffs(HCR_VF); + + ptr = (unsigned long *)&vcpu->arch.irq_lines; + if (level) + set = test_and_set_bit(bit_index, ptr); + else + set = test_and_clear_bit(bit_index, ptr); + + /* + * If we didn't change anything, no need to wake up or kick other CPUs + */ + if (set == level) + return 0; + + /* + * The vcpu irq_lines field was updated, wake up sleeping VCPUs and + * trigger a world-switch round on the running physical CPU to set the + * virtual IRQ/FIQ fields in the HCR appropriately. + */ + kvm_vcpu_kick(vcpu); + + return 0; +} + +int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level, + bool line_status) +{ + u32 irq = irq_level->irq; + unsigned int irq_type, vcpu_idx, irq_num; + int nrcpus = atomic_read(&kvm->online_vcpus); + struct kvm_vcpu *vcpu = NULL; + bool level = irq_level->level; + + irq_type = (irq >> KVM_ARM_IRQ_TYPE_SHIFT) & KVM_ARM_IRQ_TYPE_MASK; + vcpu_idx = (irq >> KVM_ARM_IRQ_VCPU_SHIFT) & KVM_ARM_IRQ_VCPU_MASK; + irq_num = (irq >> KVM_ARM_IRQ_NUM_SHIFT) & KVM_ARM_IRQ_NUM_MASK; + + trace_kvm_irq_line(irq_type, vcpu_idx, irq_num, irq_level->level); + + switch (irq_type) { + case KVM_ARM_IRQ_TYPE_CPU: + if (irqchip_in_kernel(kvm)) + return -ENXIO; + + if (vcpu_idx >= nrcpus) + return -EINVAL; + + vcpu = kvm_get_vcpu(kvm, vcpu_idx); + if (!vcpu) + return -EINVAL; + + if (irq_num > KVM_ARM_IRQ_CPU_FIQ) + return -EINVAL; + + return vcpu_interrupt_line(vcpu, irq_num, level); + case KVM_ARM_IRQ_TYPE_PPI: + if (!irqchip_in_kernel(kvm)) + return -ENXIO; + + if (vcpu_idx >= nrcpus) + return -EINVAL; + + vcpu = kvm_get_vcpu(kvm, vcpu_idx); + if (!vcpu) + return -EINVAL; + + if (irq_num < VGIC_NR_SGIS || irq_num >= VGIC_NR_PRIVATE_IRQS) + return -EINVAL; + + return kvm_vgic_inject_irq(kvm, vcpu->vcpu_id, irq_num, level); + case KVM_ARM_IRQ_TYPE_SPI: + if (!irqchip_in_kernel(kvm)) + return -ENXIO; + + if (irq_num < VGIC_NR_PRIVATE_IRQS) + return -EINVAL; + + return kvm_vgic_inject_irq(kvm, 0, irq_num, level); + } + + return -EINVAL; +} + +static int kvm_vcpu_set_target(struct kvm_vcpu *vcpu, + const struct kvm_vcpu_init *init) +{ + unsigned int i; + int phys_target = kvm_target_cpu(); + + if (init->target != phys_target) + return -EINVAL; + + /* + * Secondary and subsequent calls to KVM_ARM_VCPU_INIT must + * use the same target. + */ + if (vcpu->arch.target != -1 && vcpu->arch.target != init->target) + return -EINVAL; + + /* -ENOENT for unknown features, -EINVAL for invalid combinations. */ + for (i = 0; i < sizeof(init->features) * 8; i++) { + bool set = (init->features[i / 32] & (1 << (i % 32))); + + if (set && i >= KVM_VCPU_MAX_FEATURES) + return -ENOENT; + + /* + * Secondary and subsequent calls to KVM_ARM_VCPU_INIT must + * use the same feature set. + */ + if (vcpu->arch.target != -1 && i < KVM_VCPU_MAX_FEATURES && + test_bit(i, vcpu->arch.features) != set) + return -EINVAL; + + if (set) + set_bit(i, vcpu->arch.features); + } + + vcpu->arch.target = phys_target; + + /* Now we know what it is, we can reset it. */ + return kvm_reset_vcpu(vcpu); +} + + +static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu, + struct kvm_vcpu_init *init) +{ + int ret; + + ret = kvm_vcpu_set_target(vcpu, init); + if (ret) + return ret; + + /* + * Ensure a rebooted VM will fault in RAM pages and detect if the + * guest MMU is turned off and flush the caches as needed. + */ + if (vcpu->arch.has_run_once) + stage2_unmap_vm(vcpu->kvm); + + vcpu_reset_hcr(vcpu); + + /* + * Handle the "start in power-off" case. + */ + if (test_bit(KVM_ARM_VCPU_POWER_OFF, vcpu->arch.features)) + vcpu->arch.power_off = true; + else + vcpu->arch.power_off = false; + + return 0; +} + +static int kvm_arm_vcpu_set_attr(struct kvm_vcpu *vcpu, + struct kvm_device_attr *attr) +{ + int ret = -ENXIO; + + switch (attr->group) { + default: + ret = kvm_arm_vcpu_arch_set_attr(vcpu, attr); + break; + } + + return ret; +} + +static int kvm_arm_vcpu_get_attr(struct kvm_vcpu *vcpu, + struct kvm_device_attr *attr) +{ + int ret = -ENXIO; + + switch (attr->group) { + default: + ret = kvm_arm_vcpu_arch_get_attr(vcpu, attr); + break; + } + + return ret; +} + +static int kvm_arm_vcpu_has_attr(struct kvm_vcpu *vcpu, + struct kvm_device_attr *attr) +{ + int ret = -ENXIO; + + switch (attr->group) { + default: + ret = kvm_arm_vcpu_arch_has_attr(vcpu, attr); + break; + } + + return ret; +} + +long kvm_arch_vcpu_ioctl(struct file *filp, + unsigned int ioctl, unsigned long arg) +{ + struct kvm_vcpu *vcpu = filp->private_data; + void __user *argp = (void __user *)arg; + struct kvm_device_attr attr; + + switch (ioctl) { + case KVM_ARM_VCPU_INIT: { + struct kvm_vcpu_init init; + + if (copy_from_user(&init, argp, sizeof(init))) + return -EFAULT; + + return kvm_arch_vcpu_ioctl_vcpu_init(vcpu, &init); + } + case KVM_SET_ONE_REG: + case KVM_GET_ONE_REG: { + struct kvm_one_reg reg; + + if (unlikely(!kvm_vcpu_initialized(vcpu))) + return -ENOEXEC; + + if (copy_from_user(®, argp, sizeof(reg))) + return -EFAULT; + if (ioctl == KVM_SET_ONE_REG) + return kvm_arm_set_reg(vcpu, ®); + else + return kvm_arm_get_reg(vcpu, ®); + } + case KVM_GET_REG_LIST: { + struct kvm_reg_list __user *user_list = argp; + struct kvm_reg_list reg_list; + unsigned n; + + if (unlikely(!kvm_vcpu_initialized(vcpu))) + return -ENOEXEC; + + if (copy_from_user(®_list, user_list, sizeof(reg_list))) + return -EFAULT; + n = reg_list.n; + reg_list.n = kvm_arm_num_regs(vcpu); + if (copy_to_user(user_list, ®_list, sizeof(reg_list))) + return -EFAULT; + if (n < reg_list.n) + return -E2BIG; + return kvm_arm_copy_reg_indices(vcpu, user_list->reg); + } + case KVM_SET_DEVICE_ATTR: { + if (copy_from_user(&attr, argp, sizeof(attr))) + return -EFAULT; + return kvm_arm_vcpu_set_attr(vcpu, &attr); + } + case KVM_GET_DEVICE_ATTR: { + if (copy_from_user(&attr, argp, sizeof(attr))) + return -EFAULT; + return kvm_arm_vcpu_get_attr(vcpu, &attr); + } + case KVM_HAS_DEVICE_ATTR: { + if (copy_from_user(&attr, argp, sizeof(attr))) + return -EFAULT; + return kvm_arm_vcpu_has_attr(vcpu, &attr); + } + default: + return -EINVAL; + } +} + +/** + * kvm_vm_ioctl_get_dirty_log - get and clear the log of dirty pages in a slot + * @kvm: kvm instance + * @log: slot id and address to which we copy the log + * + * Steps 1-4 below provide general overview of dirty page logging. See + * kvm_get_dirty_log_protect() function description for additional details. + * + * We call kvm_get_dirty_log_protect() to handle steps 1-3, upon return we + * always flush the TLB (step 4) even if previous step failed and the dirty + * bitmap may be corrupt. Regardless of previous outcome the KVM logging API + * does not preclude user space subsequent dirty log read. Flushing TLB ensures + * writes will be marked dirty for next log read. + * + * 1. Take a snapshot of the bit and clear it if needed. + * 2. Write protect the corresponding page. + * 3. Copy the snapshot to the userspace. + * 4. Flush TLB's if needed. + */ +int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log) +{ + bool is_dirty = false; + int r; + + mutex_lock(&kvm->slots_lock); + + r = kvm_get_dirty_log_protect(kvm, log, &is_dirty); + + if (is_dirty) + kvm_flush_remote_tlbs(kvm); + + mutex_unlock(&kvm->slots_lock); + return r; +} + +static int kvm_vm_ioctl_set_device_addr(struct kvm *kvm, + struct kvm_arm_device_addr *dev_addr) +{ + unsigned long dev_id, type; + + dev_id = (dev_addr->id & KVM_ARM_DEVICE_ID_MASK) >> + KVM_ARM_DEVICE_ID_SHIFT; + type = (dev_addr->id & KVM_ARM_DEVICE_TYPE_MASK) >> + KVM_ARM_DEVICE_TYPE_SHIFT; + + switch (dev_id) { + case KVM_ARM_DEVICE_VGIC_V2: + if (!vgic_present) + return -ENXIO; + return kvm_vgic_addr(kvm, type, &dev_addr->addr, true); + default: + return -ENODEV; + } +} + +long kvm_arch_vm_ioctl(struct file *filp, + unsigned int ioctl, unsigned long arg) +{ + struct kvm *kvm = filp->private_data; + void __user *argp = (void __user *)arg; + + switch (ioctl) { + case KVM_CREATE_IRQCHIP: { + int ret; + if (!vgic_present) + return -ENXIO; + mutex_lock(&kvm->lock); + ret = kvm_vgic_create(kvm, KVM_DEV_TYPE_ARM_VGIC_V2); + mutex_unlock(&kvm->lock); + return ret; + } + case KVM_ARM_SET_DEVICE_ADDR: { + struct kvm_arm_device_addr dev_addr; + + if (copy_from_user(&dev_addr, argp, sizeof(dev_addr))) + return -EFAULT; + return kvm_vm_ioctl_set_device_addr(kvm, &dev_addr); + } + case KVM_ARM_PREFERRED_TARGET: { + int err; + struct kvm_vcpu_init init; + + err = kvm_vcpu_preferred_target(&init); + if (err) + return err; + + if (copy_to_user(argp, &init, sizeof(init))) + return -EFAULT; + + return 0; + } + default: + return -EINVAL; + } +} + +static void cpu_init_hyp_mode(void *dummy) +{ + phys_addr_t pgd_ptr; + unsigned long hyp_stack_ptr; + unsigned long stack_page; + unsigned long vector_ptr; + + /* Switch from the HYP stub to our own HYP init vector */ + __hyp_set_vectors(kvm_get_idmap_vector()); + + pgd_ptr = kvm_mmu_get_httbr(); + stack_page = __this_cpu_read(kvm_arm_hyp_stack_page); + hyp_stack_ptr = stack_page + PAGE_SIZE; + vector_ptr = (unsigned long)kvm_ksym_ref(__kvm_hyp_vector); + + __cpu_init_hyp_mode(pgd_ptr, hyp_stack_ptr, vector_ptr); + __cpu_init_stage2(); + + if (is_kernel_in_hyp_mode()) + kvm_timer_init_vhe(); + + kvm_arm_init_debug(); +} + +static void cpu_hyp_reset(void) +{ + if (!is_kernel_in_hyp_mode()) + __hyp_reset_vectors(); +} + +static void cpu_hyp_reinit(void) +{ + cpu_hyp_reset(); + + if (is_kernel_in_hyp_mode()) { + /* + * __cpu_init_stage2() is safe to call even if the PM + * event was cancelled before the CPU was reset. + */ + __cpu_init_stage2(); + } else { + cpu_init_hyp_mode(NULL); + } +} + +static void _kvm_arch_hardware_enable(void *discard) +{ + if (!__this_cpu_read(kvm_arm_hardware_enabled)) { + cpu_hyp_reinit(); + __this_cpu_write(kvm_arm_hardware_enabled, 1); + } +} + +int kvm_arch_hardware_enable(void) +{ + _kvm_arch_hardware_enable(NULL); + return 0; +} + +static void _kvm_arch_hardware_disable(void *discard) +{ + if (__this_cpu_read(kvm_arm_hardware_enabled)) { + cpu_hyp_reset(); + __this_cpu_write(kvm_arm_hardware_enabled, 0); + } +} + +void kvm_arch_hardware_disable(void) +{ + _kvm_arch_hardware_disable(NULL); +} + +#ifdef CONFIG_CPU_PM +static int hyp_init_cpu_pm_notifier(struct notifier_block *self, + unsigned long cmd, + void *v) +{ + /* + * kvm_arm_hardware_enabled is left with its old value over + * PM_ENTER->PM_EXIT. It is used to indicate PM_EXIT should + * re-enable hyp. + */ + switch (cmd) { + case CPU_PM_ENTER: + if (__this_cpu_read(kvm_arm_hardware_enabled)) + /* + * don't update kvm_arm_hardware_enabled here + * so that the hardware will be re-enabled + * when we resume. See below. + */ + cpu_hyp_reset(); + + return NOTIFY_OK; + case CPU_PM_EXIT: + if (__this_cpu_read(kvm_arm_hardware_enabled)) + /* The hardware was enabled before suspend. */ + cpu_hyp_reinit(); + + return NOTIFY_OK; + + default: + return NOTIFY_DONE; + } +} + +static struct notifier_block hyp_init_cpu_pm_nb = { + .notifier_call = hyp_init_cpu_pm_notifier, +}; + +static void __init hyp_cpu_pm_init(void) +{ + cpu_pm_register_notifier(&hyp_init_cpu_pm_nb); +} +static void __init hyp_cpu_pm_exit(void) +{ + cpu_pm_unregister_notifier(&hyp_init_cpu_pm_nb); +} +#else +static inline void hyp_cpu_pm_init(void) +{ +} +static inline void hyp_cpu_pm_exit(void) +{ +} +#endif + +static void teardown_common_resources(void) +{ + free_percpu(kvm_host_cpu_state); +} + +static int init_common_resources(void) +{ + kvm_host_cpu_state = alloc_percpu(kvm_cpu_context_t); + if (!kvm_host_cpu_state) { + kvm_err("Cannot allocate host CPU state\n"); + return -ENOMEM; + } + + /* set size of VMID supported by CPU */ + kvm_vmid_bits = kvm_get_vmid_bits(); + kvm_info("%d-bit VMID\n", kvm_vmid_bits); + + return 0; +} + +static int init_subsystems(void) +{ + int err = 0; + + /* + * Enable hardware so that subsystem initialisation can access EL2. + */ + on_each_cpu(_kvm_arch_hardware_enable, NULL, 1); + + /* + * Register CPU lower-power notifier + */ + hyp_cpu_pm_init(); + + /* + * Init HYP view of VGIC + */ + err = kvm_vgic_hyp_init(); + switch (err) { + case 0: + vgic_present = true; + break; + case -ENODEV: + case -ENXIO: + vgic_present = false; + err = 0; + break; + default: + goto out; + } + + /* + * Init HYP architected timer support + */ + err = kvm_timer_hyp_init(); + if (err) + goto out; + + kvm_perf_init(); + kvm_coproc_table_init(); + +out: + on_each_cpu(_kvm_arch_hardware_disable, NULL, 1); + + return err; +} + +static void teardown_hyp_mode(void) +{ + int cpu; + + if (is_kernel_in_hyp_mode()) + return; + + free_hyp_pgds(); + for_each_possible_cpu(cpu) + free_page(per_cpu(kvm_arm_hyp_stack_page, cpu)); + hyp_cpu_pm_exit(); +} + +static int init_vhe_mode(void) +{ + kvm_info("VHE mode initialized successfully\n"); + return 0; +} + +/** + * Inits Hyp-mode on all online CPUs + */ +static int init_hyp_mode(void) +{ + int cpu; + int err = 0; + + /* + * Allocate Hyp PGD and setup Hyp identity mapping + */ + err = kvm_mmu_init(); + if (err) + goto out_err; + + /* + * Allocate stack pages for Hypervisor-mode + */ + for_each_possible_cpu(cpu) { + unsigned long stack_page; + + stack_page = __get_free_page(GFP_KERNEL); + if (!stack_page) { + err = -ENOMEM; + goto out_err; + } + + per_cpu(kvm_arm_hyp_stack_page, cpu) = stack_page; + } + + /* + * Map the Hyp-code called directly from the host + */ + err = create_hyp_mappings(kvm_ksym_ref(__hyp_text_start), + kvm_ksym_ref(__hyp_text_end), PAGE_HYP_EXEC); + if (err) { + kvm_err("Cannot map world-switch code\n"); + goto out_err; + } + + err = create_hyp_mappings(kvm_ksym_ref(__start_rodata), + kvm_ksym_ref(__end_rodata), PAGE_HYP_RO); + if (err) { + kvm_err("Cannot map rodata section\n"); + goto out_err; + } + + err = create_hyp_mappings(kvm_ksym_ref(__bss_start), + kvm_ksym_ref(__bss_stop), PAGE_HYP_RO); + if (err) { + kvm_err("Cannot map bss section\n"); + goto out_err; + } + + /* + * Map the Hyp stack pages + */ + for_each_possible_cpu(cpu) { + char *stack_page = (char *)per_cpu(kvm_arm_hyp_stack_page, cpu); + err = create_hyp_mappings(stack_page, stack_page + PAGE_SIZE, + PAGE_HYP); + + if (err) { + kvm_err("Cannot map hyp stack\n"); + goto out_err; + } + } + + for_each_possible_cpu(cpu) { + kvm_cpu_context_t *cpu_ctxt; + + cpu_ctxt = per_cpu_ptr(kvm_host_cpu_state, cpu); + err = create_hyp_mappings(cpu_ctxt, cpu_ctxt + 1, PAGE_HYP); + + if (err) { + kvm_err("Cannot map host CPU state: %d\n", err); + goto out_err; + } + } + + kvm_info("Hyp mode initialized successfully\n"); + + return 0; + +out_err: + teardown_hyp_mode(); + kvm_err("error initializing Hyp mode: %d\n", err); + return err; +} + +static void check_kvm_target_cpu(void *ret) +{ + *(int *)ret = kvm_target_cpu(); +} + +struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr) +{ + struct kvm_vcpu *vcpu; + int i; + + mpidr &= MPIDR_HWID_BITMASK; + kvm_for_each_vcpu(i, vcpu, kvm) { + if (mpidr == kvm_vcpu_get_mpidr_aff(vcpu)) + return vcpu; + } + return NULL; +} + +/** + * Initialize Hyp-mode and memory mappings on all CPUs. + */ +int kvm_arch_init(void *opaque) +{ + int err; + int ret, cpu; + + if (!is_hyp_mode_available()) { + kvm_err("HYP mode not available\n"); + return -ENODEV; + } + + for_each_online_cpu(cpu) { + smp_call_function_single(cpu, check_kvm_target_cpu, &ret, 1); + if (ret < 0) { + kvm_err("Error, CPU %d not supported!\n", cpu); + return -ENODEV; + } + } + + err = init_common_resources(); + if (err) + return err; + + if (is_kernel_in_hyp_mode()) + err = init_vhe_mode(); + else + err = init_hyp_mode(); + if (err) + goto out_err; + + err = init_subsystems(); + if (err) + goto out_hyp; + + return 0; + +out_hyp: + teardown_hyp_mode(); +out_err: + teardown_common_resources(); + return err; +} + +/* NOP: Compiling as a module not supported */ +void kvm_arch_exit(void) +{ + kvm_perf_teardown(); +} + +static int arm_init(void) +{ + int rc = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE); + return rc; +} + +module_init(arm_init); diff --git a/virt/kvm/arm/mmio.c b/virt/kvm/arm/mmio.c new file mode 100644 index 000000000000..b6e715fd3c90 --- /dev/null +++ b/virt/kvm/arm/mmio.c @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2012 - Virtual Open Systems and Columbia University + * Author: Christoffer Dall + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include + +#include "trace.h" + +void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data) +{ + void *datap = NULL; + union { + u8 byte; + u16 hword; + u32 word; + u64 dword; + } tmp; + + switch (len) { + case 1: + tmp.byte = data; + datap = &tmp.byte; + break; + case 2: + tmp.hword = data; + datap = &tmp.hword; + break; + case 4: + tmp.word = data; + datap = &tmp.word; + break; + case 8: + tmp.dword = data; + datap = &tmp.dword; + break; + } + + memcpy(buf, datap, len); +} + +unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len) +{ + unsigned long data = 0; + union { + u16 hword; + u32 word; + u64 dword; + } tmp; + + switch (len) { + case 1: + data = *(u8 *)buf; + break; + case 2: + memcpy(&tmp.hword, buf, len); + data = tmp.hword; + break; + case 4: + memcpy(&tmp.word, buf, len); + data = tmp.word; + break; + case 8: + memcpy(&tmp.dword, buf, len); + data = tmp.dword; + break; + } + + return data; +} + +/** + * kvm_handle_mmio_return -- Handle MMIO loads after user space emulation + * or in-kernel IO emulation + * + * @vcpu: The VCPU pointer + * @run: The VCPU run struct containing the mmio data + */ +int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + unsigned long data; + unsigned int len; + int mask; + + if (!run->mmio.is_write) { + len = run->mmio.len; + if (len > sizeof(unsigned long)) + return -EINVAL; + + data = kvm_mmio_read_buf(run->mmio.data, len); + + if (vcpu->arch.mmio_decode.sign_extend && + len < sizeof(unsigned long)) { + mask = 1U << ((len * 8) - 1); + data = (data ^ mask) - mask; + } + + trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr, + data); + data = vcpu_data_host_to_guest(vcpu, data, len); + vcpu_set_reg(vcpu, vcpu->arch.mmio_decode.rt, data); + } + + return 0; +} + +static int decode_hsr(struct kvm_vcpu *vcpu, bool *is_write, int *len) +{ + unsigned long rt; + int access_size; + bool sign_extend; + + if (kvm_vcpu_dabt_iss1tw(vcpu)) { + /* page table accesses IO mem: tell guest to fix its TTBR */ + kvm_inject_dabt(vcpu, kvm_vcpu_get_hfar(vcpu)); + return 1; + } + + access_size = kvm_vcpu_dabt_get_as(vcpu); + if (unlikely(access_size < 0)) + return access_size; + + *is_write = kvm_vcpu_dabt_iswrite(vcpu); + sign_extend = kvm_vcpu_dabt_issext(vcpu); + rt = kvm_vcpu_dabt_get_rd(vcpu); + + *len = access_size; + vcpu->arch.mmio_decode.sign_extend = sign_extend; + vcpu->arch.mmio_decode.rt = rt; + + /* + * The MMIO instruction is emulated and should not be re-executed + * in the guest. + */ + kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu)); + return 0; +} + +int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, + phys_addr_t fault_ipa) +{ + unsigned long data; + unsigned long rt; + int ret; + bool is_write; + int len; + u8 data_buf[8]; + + /* + * Prepare MMIO operation. First decode the syndrome data we get + * from the CPU. Then try if some in-kernel emulation feels + * responsible, otherwise let user space do its magic. + */ + if (kvm_vcpu_dabt_isvalid(vcpu)) { + ret = decode_hsr(vcpu, &is_write, &len); + if (ret) + return ret; + } else { + kvm_err("load/store instruction decoding not implemented\n"); + return -ENOSYS; + } + + rt = vcpu->arch.mmio_decode.rt; + + if (is_write) { + data = vcpu_data_guest_to_host(vcpu, vcpu_get_reg(vcpu, rt), + len); + + trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, len, fault_ipa, data); + kvm_mmio_write_buf(data_buf, len, data); + + ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, fault_ipa, len, + data_buf); + } else { + trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, len, + fault_ipa, 0); + + ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, fault_ipa, len, + data_buf); + } + + /* Now prepare kvm_run for the potential return to userland. */ + run->mmio.is_write = is_write; + run->mmio.phys_addr = fault_ipa; + run->mmio.len = len; + + if (!ret) { + /* We handled the access successfully in the kernel. */ + if (!is_write) + memcpy(run->mmio.data, data_buf, len); + vcpu->stat.mmio_exit_kernel++; + kvm_handle_mmio_return(vcpu, run); + return 1; + } + + if (is_write) + memcpy(run->mmio.data, data_buf, len); + vcpu->stat.mmio_exit_user++; + run->exit_reason = KVM_EXIT_MMIO; + return 0; +} diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c new file mode 100644 index 000000000000..efb4335aa5c4 --- /dev/null +++ b/virt/kvm/arm/mmu.c @@ -0,0 +1,1958 @@ +/* + * Copyright (C) 2012 - Virtual Open Systems and Columbia University + * Author: Christoffer Dall + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "trace.h" + +static pgd_t *boot_hyp_pgd; +static pgd_t *hyp_pgd; +static pgd_t *merged_hyp_pgd; +static DEFINE_MUTEX(kvm_hyp_pgd_mutex); + +static unsigned long hyp_idmap_start; +static unsigned long hyp_idmap_end; +static phys_addr_t hyp_idmap_vector; + +#define S2_PGD_SIZE (PTRS_PER_S2_PGD * sizeof(pgd_t)) +#define hyp_pgd_order get_order(PTRS_PER_PGD * sizeof(pgd_t)) + +#define KVM_S2PTE_FLAG_IS_IOMAP (1UL << 0) +#define KVM_S2_FLAG_LOGGING_ACTIVE (1UL << 1) + +static bool memslot_is_logging(struct kvm_memory_slot *memslot) +{ + return memslot->dirty_bitmap && !(memslot->flags & KVM_MEM_READONLY); +} + +/** + * kvm_flush_remote_tlbs() - flush all VM TLB entries for v7/8 + * @kvm: pointer to kvm structure. + * + * Interface to HYP function to flush all VM TLB entries + */ +void kvm_flush_remote_tlbs(struct kvm *kvm) +{ + kvm_call_hyp(__kvm_tlb_flush_vmid, kvm); +} + +static void kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa) +{ + kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, kvm, ipa); +} + +/* + * D-Cache management functions. They take the page table entries by + * value, as they are flushing the cache using the kernel mapping (or + * kmap on 32bit). + */ +static void kvm_flush_dcache_pte(pte_t pte) +{ + __kvm_flush_dcache_pte(pte); +} + +static void kvm_flush_dcache_pmd(pmd_t pmd) +{ + __kvm_flush_dcache_pmd(pmd); +} + +static void kvm_flush_dcache_pud(pud_t pud) +{ + __kvm_flush_dcache_pud(pud); +} + +static bool kvm_is_device_pfn(unsigned long pfn) +{ + return !pfn_valid(pfn); +} + +/** + * stage2_dissolve_pmd() - clear and flush huge PMD entry + * @kvm: pointer to kvm structure. + * @addr: IPA + * @pmd: pmd pointer for IPA + * + * Function clears a PMD entry, flushes addr 1st and 2nd stage TLBs. Marks all + * pages in the range dirty. + */ +static void stage2_dissolve_pmd(struct kvm *kvm, phys_addr_t addr, pmd_t *pmd) +{ + if (!pmd_thp_or_huge(*pmd)) + return; + + pmd_clear(pmd); + kvm_tlb_flush_vmid_ipa(kvm, addr); + put_page(virt_to_page(pmd)); +} + +static int mmu_topup_memory_cache(struct kvm_mmu_memory_cache *cache, + int min, int max) +{ + void *page; + + BUG_ON(max > KVM_NR_MEM_OBJS); + if (cache->nobjs >= min) + return 0; + while (cache->nobjs < max) { + page = (void *)__get_free_page(PGALLOC_GFP); + if (!page) + return -ENOMEM; + cache->objects[cache->nobjs++] = page; + } + return 0; +} + +static void mmu_free_memory_cache(struct kvm_mmu_memory_cache *mc) +{ + while (mc->nobjs) + free_page((unsigned long)mc->objects[--mc->nobjs]); +} + +static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc) +{ + void *p; + + BUG_ON(!mc || !mc->nobjs); + p = mc->objects[--mc->nobjs]; + return p; +} + +static void clear_stage2_pgd_entry(struct kvm *kvm, pgd_t *pgd, phys_addr_t addr) +{ + pud_t *pud_table __maybe_unused = stage2_pud_offset(pgd, 0UL); + stage2_pgd_clear(pgd); + kvm_tlb_flush_vmid_ipa(kvm, addr); + stage2_pud_free(pud_table); + put_page(virt_to_page(pgd)); +} + +static void clear_stage2_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr) +{ + pmd_t *pmd_table __maybe_unused = stage2_pmd_offset(pud, 0); + VM_BUG_ON(stage2_pud_huge(*pud)); + stage2_pud_clear(pud); + kvm_tlb_flush_vmid_ipa(kvm, addr); + stage2_pmd_free(pmd_table); + put_page(virt_to_page(pud)); +} + +static void clear_stage2_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr) +{ + pte_t *pte_table = pte_offset_kernel(pmd, 0); + VM_BUG_ON(pmd_thp_or_huge(*pmd)); + pmd_clear(pmd); + kvm_tlb_flush_vmid_ipa(kvm, addr); + pte_free_kernel(NULL, pte_table); + put_page(virt_to_page(pmd)); +} + +/* + * Unmapping vs dcache management: + * + * If a guest maps certain memory pages as uncached, all writes will + * bypass the data cache and go directly to RAM. However, the CPUs + * can still speculate reads (not writes) and fill cache lines with + * data. + * + * Those cache lines will be *clean* cache lines though, so a + * clean+invalidate operation is equivalent to an invalidate + * operation, because no cache lines are marked dirty. + * + * Those clean cache lines could be filled prior to an uncached write + * by the guest, and the cache coherent IO subsystem would therefore + * end up writing old data to disk. + * + * This is why right after unmapping a page/section and invalidating + * the corresponding TLBs, we call kvm_flush_dcache_p*() to make sure + * the IO subsystem will never hit in the cache. + */ +static void unmap_stage2_ptes(struct kvm *kvm, pmd_t *pmd, + phys_addr_t addr, phys_addr_t end) +{ + phys_addr_t start_addr = addr; + pte_t *pte, *start_pte; + + start_pte = pte = pte_offset_kernel(pmd, addr); + do { + if (!pte_none(*pte)) { + pte_t old_pte = *pte; + + kvm_set_pte(pte, __pte(0)); + kvm_tlb_flush_vmid_ipa(kvm, addr); + + /* No need to invalidate the cache for device mappings */ + if (!kvm_is_device_pfn(pte_pfn(old_pte))) + kvm_flush_dcache_pte(old_pte); + + put_page(virt_to_page(pte)); + } + } while (pte++, addr += PAGE_SIZE, addr != end); + + if (stage2_pte_table_empty(start_pte)) + clear_stage2_pmd_entry(kvm, pmd, start_addr); +} + +static void unmap_stage2_pmds(struct kvm *kvm, pud_t *pud, + phys_addr_t addr, phys_addr_t end) +{ + phys_addr_t next, start_addr = addr; + pmd_t *pmd, *start_pmd; + + start_pmd = pmd = stage2_pmd_offset(pud, addr); + do { + next = stage2_pmd_addr_end(addr, end); + if (!pmd_none(*pmd)) { + if (pmd_thp_or_huge(*pmd)) { + pmd_t old_pmd = *pmd; + + pmd_clear(pmd); + kvm_tlb_flush_vmid_ipa(kvm, addr); + + kvm_flush_dcache_pmd(old_pmd); + + put_page(virt_to_page(pmd)); + } else { + unmap_stage2_ptes(kvm, pmd, addr, next); + } + } + } while (pmd++, addr = next, addr != end); + + if (stage2_pmd_table_empty(start_pmd)) + clear_stage2_pud_entry(kvm, pud, start_addr); +} + +static void unmap_stage2_puds(struct kvm *kvm, pgd_t *pgd, + phys_addr_t addr, phys_addr_t end) +{ + phys_addr_t next, start_addr = addr; + pud_t *pud, *start_pud; + + start_pud = pud = stage2_pud_offset(pgd, addr); + do { + next = stage2_pud_addr_end(addr, end); + if (!stage2_pud_none(*pud)) { + if (stage2_pud_huge(*pud)) { + pud_t old_pud = *pud; + + stage2_pud_clear(pud); + kvm_tlb_flush_vmid_ipa(kvm, addr); + kvm_flush_dcache_pud(old_pud); + put_page(virt_to_page(pud)); + } else { + unmap_stage2_pmds(kvm, pud, addr, next); + } + } + } while (pud++, addr = next, addr != end); + + if (stage2_pud_table_empty(start_pud)) + clear_stage2_pgd_entry(kvm, pgd, start_addr); +} + +/** + * unmap_stage2_range -- Clear stage2 page table entries to unmap a range + * @kvm: The VM pointer + * @start: The intermediate physical base address of the range to unmap + * @size: The size of the area to unmap + * + * Clear a range of stage-2 mappings, lowering the various ref-counts. Must + * be called while holding mmu_lock (unless for freeing the stage2 pgd before + * destroying the VM), otherwise another faulting VCPU may come in and mess + * with things behind our backs. + */ +static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size) +{ + pgd_t *pgd; + phys_addr_t addr = start, end = start + size; + phys_addr_t next; + + pgd = kvm->arch.pgd + stage2_pgd_index(addr); + do { + next = stage2_pgd_addr_end(addr, end); + if (!stage2_pgd_none(*pgd)) + unmap_stage2_puds(kvm, pgd, addr, next); + } while (pgd++, addr = next, addr != end); +} + +static void stage2_flush_ptes(struct kvm *kvm, pmd_t *pmd, + phys_addr_t addr, phys_addr_t end) +{ + pte_t *pte; + + pte = pte_offset_kernel(pmd, addr); + do { + if (!pte_none(*pte) && !kvm_is_device_pfn(pte_pfn(*pte))) + kvm_flush_dcache_pte(*pte); + } while (pte++, addr += PAGE_SIZE, addr != end); +} + +static void stage2_flush_pmds(struct kvm *kvm, pud_t *pud, + phys_addr_t addr, phys_addr_t end) +{ + pmd_t *pmd; + phys_addr_t next; + + pmd = stage2_pmd_offset(pud, addr); + do { + next = stage2_pmd_addr_end(addr, end); + if (!pmd_none(*pmd)) { + if (pmd_thp_or_huge(*pmd)) + kvm_flush_dcache_pmd(*pmd); + else + stage2_flush_ptes(kvm, pmd, addr, next); + } + } while (pmd++, addr = next, addr != end); +} + +static void stage2_flush_puds(struct kvm *kvm, pgd_t *pgd, + phys_addr_t addr, phys_addr_t end) +{ + pud_t *pud; + phys_addr_t next; + + pud = stage2_pud_offset(pgd, addr); + do { + next = stage2_pud_addr_end(addr, end); + if (!stage2_pud_none(*pud)) { + if (stage2_pud_huge(*pud)) + kvm_flush_dcache_pud(*pud); + else + stage2_flush_pmds(kvm, pud, addr, next); + } + } while (pud++, addr = next, addr != end); +} + +static void stage2_flush_memslot(struct kvm *kvm, + struct kvm_memory_slot *memslot) +{ + phys_addr_t addr = memslot->base_gfn << PAGE_SHIFT; + phys_addr_t end = addr + PAGE_SIZE * memslot->npages; + phys_addr_t next; + pgd_t *pgd; + + pgd = kvm->arch.pgd + stage2_pgd_index(addr); + do { + next = stage2_pgd_addr_end(addr, end); + stage2_flush_puds(kvm, pgd, addr, next); + } while (pgd++, addr = next, addr != end); +} + +/** + * stage2_flush_vm - Invalidate cache for pages mapped in stage 2 + * @kvm: The struct kvm pointer + * + * Go through the stage 2 page tables and invalidate any cache lines + * backing memory already mapped to the VM. + */ +static void stage2_flush_vm(struct kvm *kvm) +{ + struct kvm_memslots *slots; + struct kvm_memory_slot *memslot; + int idx; + + idx = srcu_read_lock(&kvm->srcu); + spin_lock(&kvm->mmu_lock); + + slots = kvm_memslots(kvm); + kvm_for_each_memslot(memslot, slots) + stage2_flush_memslot(kvm, memslot); + + spin_unlock(&kvm->mmu_lock); + srcu_read_unlock(&kvm->srcu, idx); +} + +static void clear_hyp_pgd_entry(pgd_t *pgd) +{ + pud_t *pud_table __maybe_unused = pud_offset(pgd, 0UL); + pgd_clear(pgd); + pud_free(NULL, pud_table); + put_page(virt_to_page(pgd)); +} + +static void clear_hyp_pud_entry(pud_t *pud) +{ + pmd_t *pmd_table __maybe_unused = pmd_offset(pud, 0); + VM_BUG_ON(pud_huge(*pud)); + pud_clear(pud); + pmd_free(NULL, pmd_table); + put_page(virt_to_page(pud)); +} + +static void clear_hyp_pmd_entry(pmd_t *pmd) +{ + pte_t *pte_table = pte_offset_kernel(pmd, 0); + VM_BUG_ON(pmd_thp_or_huge(*pmd)); + pmd_clear(pmd); + pte_free_kernel(NULL, pte_table); + put_page(virt_to_page(pmd)); +} + +static void unmap_hyp_ptes(pmd_t *pmd, phys_addr_t addr, phys_addr_t end) +{ + pte_t *pte, *start_pte; + + start_pte = pte = pte_offset_kernel(pmd, addr); + do { + if (!pte_none(*pte)) { + kvm_set_pte(pte, __pte(0)); + put_page(virt_to_page(pte)); + } + } while (pte++, addr += PAGE_SIZE, addr != end); + + if (hyp_pte_table_empty(start_pte)) + clear_hyp_pmd_entry(pmd); +} + +static void unmap_hyp_pmds(pud_t *pud, phys_addr_t addr, phys_addr_t end) +{ + phys_addr_t next; + pmd_t *pmd, *start_pmd; + + start_pmd = pmd = pmd_offset(pud, addr); + do { + next = pmd_addr_end(addr, end); + /* Hyp doesn't use huge pmds */ + if (!pmd_none(*pmd)) + unmap_hyp_ptes(pmd, addr, next); + } while (pmd++, addr = next, addr != end); + + if (hyp_pmd_table_empty(start_pmd)) + clear_hyp_pud_entry(pud); +} + +static void unmap_hyp_puds(pgd_t *pgd, phys_addr_t addr, phys_addr_t end) +{ + phys_addr_t next; + pud_t *pud, *start_pud; + + start_pud = pud = pud_offset(pgd, addr); + do { + next = pud_addr_end(addr, end); + /* Hyp doesn't use huge puds */ + if (!pud_none(*pud)) + unmap_hyp_pmds(pud, addr, next); + } while (pud++, addr = next, addr != end); + + if (hyp_pud_table_empty(start_pud)) + clear_hyp_pgd_entry(pgd); +} + +static void unmap_hyp_range(pgd_t *pgdp, phys_addr_t start, u64 size) +{ + pgd_t *pgd; + phys_addr_t addr = start, end = start + size; + phys_addr_t next; + + /* + * We don't unmap anything from HYP, except at the hyp tear down. + * Hence, we don't have to invalidate the TLBs here. + */ + pgd = pgdp + pgd_index(addr); + do { + next = pgd_addr_end(addr, end); + if (!pgd_none(*pgd)) + unmap_hyp_puds(pgd, addr, next); + } while (pgd++, addr = next, addr != end); +} + +/** + * free_hyp_pgds - free Hyp-mode page tables + * + * Assumes hyp_pgd is a page table used strictly in Hyp-mode and + * therefore contains either mappings in the kernel memory area (above + * PAGE_OFFSET), or device mappings in the vmalloc range (from + * VMALLOC_START to VMALLOC_END). + * + * boot_hyp_pgd should only map two pages for the init code. + */ +void free_hyp_pgds(void) +{ + unsigned long addr; + + mutex_lock(&kvm_hyp_pgd_mutex); + + if (boot_hyp_pgd) { + unmap_hyp_range(boot_hyp_pgd, hyp_idmap_start, PAGE_SIZE); + free_pages((unsigned long)boot_hyp_pgd, hyp_pgd_order); + boot_hyp_pgd = NULL; + } + + if (hyp_pgd) { + unmap_hyp_range(hyp_pgd, hyp_idmap_start, PAGE_SIZE); + for (addr = PAGE_OFFSET; virt_addr_valid(addr); addr += PGDIR_SIZE) + unmap_hyp_range(hyp_pgd, kern_hyp_va(addr), PGDIR_SIZE); + for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr += PGDIR_SIZE) + unmap_hyp_range(hyp_pgd, kern_hyp_va(addr), PGDIR_SIZE); + + free_pages((unsigned long)hyp_pgd, hyp_pgd_order); + hyp_pgd = NULL; + } + if (merged_hyp_pgd) { + clear_page(merged_hyp_pgd); + free_page((unsigned long)merged_hyp_pgd); + merged_hyp_pgd = NULL; + } + + mutex_unlock(&kvm_hyp_pgd_mutex); +} + +static void create_hyp_pte_mappings(pmd_t *pmd, unsigned long start, + unsigned long end, unsigned long pfn, + pgprot_t prot) +{ + pte_t *pte; + unsigned long addr; + + addr = start; + do { + pte = pte_offset_kernel(pmd, addr); + kvm_set_pte(pte, pfn_pte(pfn, prot)); + get_page(virt_to_page(pte)); + kvm_flush_dcache_to_poc(pte, sizeof(*pte)); + pfn++; + } while (addr += PAGE_SIZE, addr != end); +} + +static int create_hyp_pmd_mappings(pud_t *pud, unsigned long start, + unsigned long end, unsigned long pfn, + pgprot_t prot) +{ + pmd_t *pmd; + pte_t *pte; + unsigned long addr, next; + + addr = start; + do { + pmd = pmd_offset(pud, addr); + + BUG_ON(pmd_sect(*pmd)); + + if (pmd_none(*pmd)) { + pte = pte_alloc_one_kernel(NULL, addr); + if (!pte) { + kvm_err("Cannot allocate Hyp pte\n"); + return -ENOMEM; + } + pmd_populate_kernel(NULL, pmd, pte); + get_page(virt_to_page(pmd)); + kvm_flush_dcache_to_poc(pmd, sizeof(*pmd)); + } + + next = pmd_addr_end(addr, end); + + create_hyp_pte_mappings(pmd, addr, next, pfn, prot); + pfn += (next - addr) >> PAGE_SHIFT; + } while (addr = next, addr != end); + + return 0; +} + +static int create_hyp_pud_mappings(pgd_t *pgd, unsigned long start, + unsigned long end, unsigned long pfn, + pgprot_t prot) +{ + pud_t *pud; + pmd_t *pmd; + unsigned long addr, next; + int ret; + + addr = start; + do { + pud = pud_offset(pgd, addr); + + if (pud_none_or_clear_bad(pud)) { + pmd = pmd_alloc_one(NULL, addr); + if (!pmd) { + kvm_err("Cannot allocate Hyp pmd\n"); + return -ENOMEM; + } + pud_populate(NULL, pud, pmd); + get_page(virt_to_page(pud)); + kvm_flush_dcache_to_poc(pud, sizeof(*pud)); + } + + next = pud_addr_end(addr, end); + ret = create_hyp_pmd_mappings(pud, addr, next, pfn, prot); + if (ret) + return ret; + pfn += (next - addr) >> PAGE_SHIFT; + } while (addr = next, addr != end); + + return 0; +} + +static int __create_hyp_mappings(pgd_t *pgdp, + unsigned long start, unsigned long end, + unsigned long pfn, pgprot_t prot) +{ + pgd_t *pgd; + pud_t *pud; + unsigned long addr, next; + int err = 0; + + mutex_lock(&kvm_hyp_pgd_mutex); + addr = start & PAGE_MASK; + end = PAGE_ALIGN(end); + do { + pgd = pgdp + pgd_index(addr); + + if (pgd_none(*pgd)) { + pud = pud_alloc_one(NULL, addr); + if (!pud) { + kvm_err("Cannot allocate Hyp pud\n"); + err = -ENOMEM; + goto out; + } + pgd_populate(NULL, pgd, pud); + get_page(virt_to_page(pgd)); + kvm_flush_dcache_to_poc(pgd, sizeof(*pgd)); + } + + next = pgd_addr_end(addr, end); + err = create_hyp_pud_mappings(pgd, addr, next, pfn, prot); + if (err) + goto out; + pfn += (next - addr) >> PAGE_SHIFT; + } while (addr = next, addr != end); +out: + mutex_unlock(&kvm_hyp_pgd_mutex); + return err; +} + +static phys_addr_t kvm_kaddr_to_phys(void *kaddr) +{ + if (!is_vmalloc_addr(kaddr)) { + BUG_ON(!virt_addr_valid(kaddr)); + return __pa(kaddr); + } else { + return page_to_phys(vmalloc_to_page(kaddr)) + + offset_in_page(kaddr); + } +} + +/** + * create_hyp_mappings - duplicate a kernel virtual address range in Hyp mode + * @from: The virtual kernel start address of the range + * @to: The virtual kernel end address of the range (exclusive) + * @prot: The protection to be applied to this range + * + * The same virtual address as the kernel virtual address is also used + * in Hyp-mode mapping (modulo HYP_PAGE_OFFSET) to the same underlying + * physical pages. + */ +int create_hyp_mappings(void *from, void *to, pgprot_t prot) +{ + phys_addr_t phys_addr; + unsigned long virt_addr; + unsigned long start = kern_hyp_va((unsigned long)from); + unsigned long end = kern_hyp_va((unsigned long)to); + + if (is_kernel_in_hyp_mode()) + return 0; + + start = start & PAGE_MASK; + end = PAGE_ALIGN(end); + + for (virt_addr = start; virt_addr < end; virt_addr += PAGE_SIZE) { + int err; + + phys_addr = kvm_kaddr_to_phys(from + virt_addr - start); + err = __create_hyp_mappings(hyp_pgd, virt_addr, + virt_addr + PAGE_SIZE, + __phys_to_pfn(phys_addr), + prot); + if (err) + return err; + } + + return 0; +} + +/** + * create_hyp_io_mappings - duplicate a kernel IO mapping into Hyp mode + * @from: The kernel start VA of the range + * @to: The kernel end VA of the range (exclusive) + * @phys_addr: The physical start address which gets mapped + * + * The resulting HYP VA is the same as the kernel VA, modulo + * HYP_PAGE_OFFSET. + */ +int create_hyp_io_mappings(void *from, void *to, phys_addr_t phys_addr) +{ + unsigned long start = kern_hyp_va((unsigned long)from); + unsigned long end = kern_hyp_va((unsigned long)to); + + if (is_kernel_in_hyp_mode()) + return 0; + + /* Check for a valid kernel IO mapping */ + if (!is_vmalloc_addr(from) || !is_vmalloc_addr(to - 1)) + return -EINVAL; + + return __create_hyp_mappings(hyp_pgd, start, end, + __phys_to_pfn(phys_addr), PAGE_HYP_DEVICE); +} + +/** + * kvm_alloc_stage2_pgd - allocate level-1 table for stage-2 translation. + * @kvm: The KVM struct pointer for the VM. + * + * Allocates only the stage-2 HW PGD level table(s) (can support either full + * 40-bit input addresses or limited to 32-bit input addresses). Clears the + * allocated pages. + * + * Note we don't need locking here as this is only called when the VM is + * created, which can only be done once. + */ +int kvm_alloc_stage2_pgd(struct kvm *kvm) +{ + pgd_t *pgd; + + if (kvm->arch.pgd != NULL) { + kvm_err("kvm_arch already initialized?\n"); + return -EINVAL; + } + + /* Allocate the HW PGD, making sure that each page gets its own refcount */ + pgd = alloc_pages_exact(S2_PGD_SIZE, GFP_KERNEL | __GFP_ZERO); + if (!pgd) + return -ENOMEM; + + kvm->arch.pgd = pgd; + return 0; +} + +static void stage2_unmap_memslot(struct kvm *kvm, + struct kvm_memory_slot *memslot) +{ + hva_t hva = memslot->userspace_addr; + phys_addr_t addr = memslot->base_gfn << PAGE_SHIFT; + phys_addr_t size = PAGE_SIZE * memslot->npages; + hva_t reg_end = hva + size; + + /* + * A memory region could potentially cover multiple VMAs, and any holes + * between them, so iterate over all of them to find out if we should + * unmap any of them. + * + * +--------------------------------------------+ + * +---------------+----------------+ +----------------+ + * | : VMA 1 | VMA 2 | | VMA 3 : | + * +---------------+----------------+ +----------------+ + * | memory region | + * +--------------------------------------------+ + */ + do { + struct vm_area_struct *vma = find_vma(current->mm, hva); + hva_t vm_start, vm_end; + + if (!vma || vma->vm_start >= reg_end) + break; + + /* + * Take the intersection of this VMA with the memory region + */ + vm_start = max(hva, vma->vm_start); + vm_end = min(reg_end, vma->vm_end); + + if (!(vma->vm_flags & VM_PFNMAP)) { + gpa_t gpa = addr + (vm_start - memslot->userspace_addr); + unmap_stage2_range(kvm, gpa, vm_end - vm_start); + } + hva = vm_end; + } while (hva < reg_end); +} + +/** + * stage2_unmap_vm - Unmap Stage-2 RAM mappings + * @kvm: The struct kvm pointer + * + * Go through the memregions and unmap any reguler RAM + * backing memory already mapped to the VM. + */ +void stage2_unmap_vm(struct kvm *kvm) +{ + struct kvm_memslots *slots; + struct kvm_memory_slot *memslot; + int idx; + + idx = srcu_read_lock(&kvm->srcu); + spin_lock(&kvm->mmu_lock); + + slots = kvm_memslots(kvm); + kvm_for_each_memslot(memslot, slots) + stage2_unmap_memslot(kvm, memslot); + + spin_unlock(&kvm->mmu_lock); + srcu_read_unlock(&kvm->srcu, idx); +} + +/** + * kvm_free_stage2_pgd - free all stage-2 tables + * @kvm: The KVM struct pointer for the VM. + * + * Walks the level-1 page table pointed to by kvm->arch.pgd and frees all + * underlying level-2 and level-3 tables before freeing the actual level-1 table + * and setting the struct pointer to NULL. + * + * Note we don't need locking here as this is only called when the VM is + * destroyed, which can only be done once. + */ +void kvm_free_stage2_pgd(struct kvm *kvm) +{ + if (kvm->arch.pgd == NULL) + return; + + unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE); + /* Free the HW pgd, one page at a time */ + free_pages_exact(kvm->arch.pgd, S2_PGD_SIZE); + kvm->arch.pgd = NULL; +} + +static pud_t *stage2_get_pud(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, + phys_addr_t addr) +{ + pgd_t *pgd; + pud_t *pud; + + pgd = kvm->arch.pgd + stage2_pgd_index(addr); + if (WARN_ON(stage2_pgd_none(*pgd))) { + if (!cache) + return NULL; + pud = mmu_memory_cache_alloc(cache); + stage2_pgd_populate(pgd, pud); + get_page(virt_to_page(pgd)); + } + + return stage2_pud_offset(pgd, addr); +} + +static pmd_t *stage2_get_pmd(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, + phys_addr_t addr) +{ + pud_t *pud; + pmd_t *pmd; + + pud = stage2_get_pud(kvm, cache, addr); + if (stage2_pud_none(*pud)) { + if (!cache) + return NULL; + pmd = mmu_memory_cache_alloc(cache); + stage2_pud_populate(pud, pmd); + get_page(virt_to_page(pud)); + } + + return stage2_pmd_offset(pud, addr); +} + +static int stage2_set_pmd_huge(struct kvm *kvm, struct kvm_mmu_memory_cache + *cache, phys_addr_t addr, const pmd_t *new_pmd) +{ + pmd_t *pmd, old_pmd; + + pmd = stage2_get_pmd(kvm, cache, addr); + VM_BUG_ON(!pmd); + + /* + * Mapping in huge pages should only happen through a fault. If a + * page is merged into a transparent huge page, the individual + * subpages of that huge page should be unmapped through MMU + * notifiers before we get here. + * + * Merging of CompoundPages is not supported; they should become + * splitting first, unmapped, merged, and mapped back in on-demand. + */ + VM_BUG_ON(pmd_present(*pmd) && pmd_pfn(*pmd) != pmd_pfn(*new_pmd)); + + old_pmd = *pmd; + if (pmd_present(old_pmd)) { + pmd_clear(pmd); + kvm_tlb_flush_vmid_ipa(kvm, addr); + } else { + get_page(virt_to_page(pmd)); + } + + kvm_set_pmd(pmd, *new_pmd); + return 0; +} + +static int stage2_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, + phys_addr_t addr, const pte_t *new_pte, + unsigned long flags) +{ + pmd_t *pmd; + pte_t *pte, old_pte; + bool iomap = flags & KVM_S2PTE_FLAG_IS_IOMAP; + bool logging_active = flags & KVM_S2_FLAG_LOGGING_ACTIVE; + + VM_BUG_ON(logging_active && !cache); + + /* Create stage-2 page table mapping - Levels 0 and 1 */ + pmd = stage2_get_pmd(kvm, cache, addr); + if (!pmd) { + /* + * Ignore calls from kvm_set_spte_hva for unallocated + * address ranges. + */ + return 0; + } + + /* + * While dirty page logging - dissolve huge PMD, then continue on to + * allocate page. + */ + if (logging_active) + stage2_dissolve_pmd(kvm, addr, pmd); + + /* Create stage-2 page mappings - Level 2 */ + if (pmd_none(*pmd)) { + if (!cache) + return 0; /* ignore calls from kvm_set_spte_hva */ + pte = mmu_memory_cache_alloc(cache); + pmd_populate_kernel(NULL, pmd, pte); + get_page(virt_to_page(pmd)); + } + + pte = pte_offset_kernel(pmd, addr); + + if (iomap && pte_present(*pte)) + return -EFAULT; + + /* Create 2nd stage page table mapping - Level 3 */ + old_pte = *pte; + if (pte_present(old_pte)) { + kvm_set_pte(pte, __pte(0)); + kvm_tlb_flush_vmid_ipa(kvm, addr); + } else { + get_page(virt_to_page(pte)); + } + + kvm_set_pte(pte, *new_pte); + return 0; +} + +#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG +static int stage2_ptep_test_and_clear_young(pte_t *pte) +{ + if (pte_young(*pte)) { + *pte = pte_mkold(*pte); + return 1; + } + return 0; +} +#else +static int stage2_ptep_test_and_clear_young(pte_t *pte) +{ + return __ptep_test_and_clear_young(pte); +} +#endif + +static int stage2_pmdp_test_and_clear_young(pmd_t *pmd) +{ + return stage2_ptep_test_and_clear_young((pte_t *)pmd); +} + +/** + * kvm_phys_addr_ioremap - map a device range to guest IPA + * + * @kvm: The KVM pointer + * @guest_ipa: The IPA at which to insert the mapping + * @pa: The physical address of the device + * @size: The size of the mapping + */ +int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa, + phys_addr_t pa, unsigned long size, bool writable) +{ + phys_addr_t addr, end; + int ret = 0; + unsigned long pfn; + struct kvm_mmu_memory_cache cache = { 0, }; + + end = (guest_ipa + size + PAGE_SIZE - 1) & PAGE_MASK; + pfn = __phys_to_pfn(pa); + + for (addr = guest_ipa; addr < end; addr += PAGE_SIZE) { + pte_t pte = pfn_pte(pfn, PAGE_S2_DEVICE); + + if (writable) + pte = kvm_s2pte_mkwrite(pte); + + ret = mmu_topup_memory_cache(&cache, KVM_MMU_CACHE_MIN_PAGES, + KVM_NR_MEM_OBJS); + if (ret) + goto out; + spin_lock(&kvm->mmu_lock); + ret = stage2_set_pte(kvm, &cache, addr, &pte, + KVM_S2PTE_FLAG_IS_IOMAP); + spin_unlock(&kvm->mmu_lock); + if (ret) + goto out; + + pfn++; + } + +out: + mmu_free_memory_cache(&cache); + return ret; +} + +static bool transparent_hugepage_adjust(kvm_pfn_t *pfnp, phys_addr_t *ipap) +{ + kvm_pfn_t pfn = *pfnp; + gfn_t gfn = *ipap >> PAGE_SHIFT; + + if (PageTransCompoundMap(pfn_to_page(pfn))) { + unsigned long mask; + /* + * The address we faulted on is backed by a transparent huge + * page. However, because we map the compound huge page and + * not the individual tail page, we need to transfer the + * refcount to the head page. We have to be careful that the + * THP doesn't start to split while we are adjusting the + * refcounts. + * + * We are sure this doesn't happen, because mmu_notifier_retry + * was successful and we are holding the mmu_lock, so if this + * THP is trying to split, it will be blocked in the mmu + * notifier before touching any of the pages, specifically + * before being able to call __split_huge_page_refcount(). + * + * We can therefore safely transfer the refcount from PG_tail + * to PG_head and switch the pfn from a tail page to the head + * page accordingly. + */ + mask = PTRS_PER_PMD - 1; + VM_BUG_ON((gfn & mask) != (pfn & mask)); + if (pfn & mask) { + *ipap &= PMD_MASK; + kvm_release_pfn_clean(pfn); + pfn &= ~mask; + kvm_get_pfn(pfn); + *pfnp = pfn; + } + + return true; + } + + return false; +} + +static bool kvm_is_write_fault(struct kvm_vcpu *vcpu) +{ + if (kvm_vcpu_trap_is_iabt(vcpu)) + return false; + + return kvm_vcpu_dabt_iswrite(vcpu); +} + +/** + * stage2_wp_ptes - write protect PMD range + * @pmd: pointer to pmd entry + * @addr: range start address + * @end: range end address + */ +static void stage2_wp_ptes(pmd_t *pmd, phys_addr_t addr, phys_addr_t end) +{ + pte_t *pte; + + pte = pte_offset_kernel(pmd, addr); + do { + if (!pte_none(*pte)) { + if (!kvm_s2pte_readonly(pte)) + kvm_set_s2pte_readonly(pte); + } + } while (pte++, addr += PAGE_SIZE, addr != end); +} + +/** + * stage2_wp_pmds - write protect PUD range + * @pud: pointer to pud entry + * @addr: range start address + * @end: range end address + */ +static void stage2_wp_pmds(pud_t *pud, phys_addr_t addr, phys_addr_t end) +{ + pmd_t *pmd; + phys_addr_t next; + + pmd = stage2_pmd_offset(pud, addr); + + do { + next = stage2_pmd_addr_end(addr, end); + if (!pmd_none(*pmd)) { + if (pmd_thp_or_huge(*pmd)) { + if (!kvm_s2pmd_readonly(pmd)) + kvm_set_s2pmd_readonly(pmd); + } else { + stage2_wp_ptes(pmd, addr, next); + } + } + } while (pmd++, addr = next, addr != end); +} + +/** + * stage2_wp_puds - write protect PGD range + * @pgd: pointer to pgd entry + * @addr: range start address + * @end: range end address + * + * Process PUD entries, for a huge PUD we cause a panic. + */ +static void stage2_wp_puds(pgd_t *pgd, phys_addr_t addr, phys_addr_t end) +{ + pud_t *pud; + phys_addr_t next; + + pud = stage2_pud_offset(pgd, addr); + do { + next = stage2_pud_addr_end(addr, end); + if (!stage2_pud_none(*pud)) { + /* TODO:PUD not supported, revisit later if supported */ + BUG_ON(stage2_pud_huge(*pud)); + stage2_wp_pmds(pud, addr, next); + } + } while (pud++, addr = next, addr != end); +} + +/** + * stage2_wp_range() - write protect stage2 memory region range + * @kvm: The KVM pointer + * @addr: Start address of range + * @end: End address of range + */ +static void stage2_wp_range(struct kvm *kvm, phys_addr_t addr, phys_addr_t end) +{ + pgd_t *pgd; + phys_addr_t next; + + pgd = kvm->arch.pgd + stage2_pgd_index(addr); + do { + /* + * Release kvm_mmu_lock periodically if the memory region is + * large. Otherwise, we may see kernel panics with + * CONFIG_DETECT_HUNG_TASK, CONFIG_LOCKUP_DETECTOR, + * CONFIG_LOCKDEP. Additionally, holding the lock too long + * will also starve other vCPUs. + */ + if (need_resched() || spin_needbreak(&kvm->mmu_lock)) + cond_resched_lock(&kvm->mmu_lock); + + next = stage2_pgd_addr_end(addr, end); + if (stage2_pgd_present(*pgd)) + stage2_wp_puds(pgd, addr, next); + } while (pgd++, addr = next, addr != end); +} + +/** + * kvm_mmu_wp_memory_region() - write protect stage 2 entries for memory slot + * @kvm: The KVM pointer + * @slot: The memory slot to write protect + * + * Called to start logging dirty pages after memory region + * KVM_MEM_LOG_DIRTY_PAGES operation is called. After this function returns + * all present PMD and PTEs are write protected in the memory region. + * Afterwards read of dirty page log can be called. + * + * Acquires kvm_mmu_lock. Called with kvm->slots_lock mutex acquired, + * serializing operations for VM memory regions. + */ +void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot) +{ + struct kvm_memslots *slots = kvm_memslots(kvm); + struct kvm_memory_slot *memslot = id_to_memslot(slots, slot); + phys_addr_t start = memslot->base_gfn << PAGE_SHIFT; + phys_addr_t end = (memslot->base_gfn + memslot->npages) << PAGE_SHIFT; + + spin_lock(&kvm->mmu_lock); + stage2_wp_range(kvm, start, end); + spin_unlock(&kvm->mmu_lock); + kvm_flush_remote_tlbs(kvm); +} + +/** + * kvm_mmu_write_protect_pt_masked() - write protect dirty pages + * @kvm: The KVM pointer + * @slot: The memory slot associated with mask + * @gfn_offset: The gfn offset in memory slot + * @mask: The mask of dirty pages at offset 'gfn_offset' in this memory + * slot to be write protected + * + * Walks bits set in mask write protects the associated pte's. Caller must + * acquire kvm_mmu_lock. + */ +static void kvm_mmu_write_protect_pt_masked(struct kvm *kvm, + struct kvm_memory_slot *slot, + gfn_t gfn_offset, unsigned long mask) +{ + phys_addr_t base_gfn = slot->base_gfn + gfn_offset; + phys_addr_t start = (base_gfn + __ffs(mask)) << PAGE_SHIFT; + phys_addr_t end = (base_gfn + __fls(mask) + 1) << PAGE_SHIFT; + + stage2_wp_range(kvm, start, end); +} + +/* + * kvm_arch_mmu_enable_log_dirty_pt_masked - enable dirty logging for selected + * dirty pages. + * + * It calls kvm_mmu_write_protect_pt_masked to write protect selected pages to + * enable dirty logging for them. + */ +void kvm_arch_mmu_enable_log_dirty_pt_masked(struct kvm *kvm, + struct kvm_memory_slot *slot, + gfn_t gfn_offset, unsigned long mask) +{ + kvm_mmu_write_protect_pt_masked(kvm, slot, gfn_offset, mask); +} + +static void coherent_cache_guest_page(struct kvm_vcpu *vcpu, kvm_pfn_t pfn, + unsigned long size) +{ + __coherent_cache_guest_page(vcpu, pfn, size); +} + +static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, + struct kvm_memory_slot *memslot, unsigned long hva, + unsigned long fault_status) +{ + int ret; + bool write_fault, writable, hugetlb = false, force_pte = false; + unsigned long mmu_seq; + gfn_t gfn = fault_ipa >> PAGE_SHIFT; + struct kvm *kvm = vcpu->kvm; + struct kvm_mmu_memory_cache *memcache = &vcpu->arch.mmu_page_cache; + struct vm_area_struct *vma; + kvm_pfn_t pfn; + pgprot_t mem_type = PAGE_S2; + bool logging_active = memslot_is_logging(memslot); + unsigned long flags = 0; + + write_fault = kvm_is_write_fault(vcpu); + if (fault_status == FSC_PERM && !write_fault) { + kvm_err("Unexpected L2 read permission error\n"); + return -EFAULT; + } + + /* Let's check if we will get back a huge page backed by hugetlbfs */ + down_read(¤t->mm->mmap_sem); + vma = find_vma_intersection(current->mm, hva, hva + 1); + if (unlikely(!vma)) { + kvm_err("Failed to find VMA for hva 0x%lx\n", hva); + up_read(¤t->mm->mmap_sem); + return -EFAULT; + } + + if (is_vm_hugetlb_page(vma) && !logging_active) { + hugetlb = true; + gfn = (fault_ipa & PMD_MASK) >> PAGE_SHIFT; + } else { + /* + * Pages belonging to memslots that don't have the same + * alignment for userspace and IPA cannot be mapped using + * block descriptors even if the pages belong to a THP for + * the process, because the stage-2 block descriptor will + * cover more than a single THP and we loose atomicity for + * unmapping, updates, and splits of the THP or other pages + * in the stage-2 block range. + */ + if ((memslot->userspace_addr & ~PMD_MASK) != + ((memslot->base_gfn << PAGE_SHIFT) & ~PMD_MASK)) + force_pte = true; + } + up_read(¤t->mm->mmap_sem); + + /* We need minimum second+third level pages */ + ret = mmu_topup_memory_cache(memcache, KVM_MMU_CACHE_MIN_PAGES, + KVM_NR_MEM_OBJS); + if (ret) + return ret; + + mmu_seq = vcpu->kvm->mmu_notifier_seq; + /* + * Ensure the read of mmu_notifier_seq happens before we call + * gfn_to_pfn_prot (which calls get_user_pages), so that we don't risk + * the page we just got a reference to gets unmapped before we have a + * chance to grab the mmu_lock, which ensure that if the page gets + * unmapped afterwards, the call to kvm_unmap_hva will take it away + * from us again properly. This smp_rmb() interacts with the smp_wmb() + * in kvm_mmu_notifier_invalidate_. + */ + smp_rmb(); + + pfn = gfn_to_pfn_prot(kvm, gfn, write_fault, &writable); + if (is_error_noslot_pfn(pfn)) + return -EFAULT; + + if (kvm_is_device_pfn(pfn)) { + mem_type = PAGE_S2_DEVICE; + flags |= KVM_S2PTE_FLAG_IS_IOMAP; + } else if (logging_active) { + /* + * Faults on pages in a memslot with logging enabled + * should not be mapped with huge pages (it introduces churn + * and performance degradation), so force a pte mapping. + */ + force_pte = true; + flags |= KVM_S2_FLAG_LOGGING_ACTIVE; + + /* + * Only actually map the page as writable if this was a write + * fault. + */ + if (!write_fault) + writable = false; + } + + spin_lock(&kvm->mmu_lock); + if (mmu_notifier_retry(kvm, mmu_seq)) + goto out_unlock; + + if (!hugetlb && !force_pte) + hugetlb = transparent_hugepage_adjust(&pfn, &fault_ipa); + + if (hugetlb) { + pmd_t new_pmd = pfn_pmd(pfn, mem_type); + new_pmd = pmd_mkhuge(new_pmd); + if (writable) { + new_pmd = kvm_s2pmd_mkwrite(new_pmd); + kvm_set_pfn_dirty(pfn); + } + coherent_cache_guest_page(vcpu, pfn, PMD_SIZE); + ret = stage2_set_pmd_huge(kvm, memcache, fault_ipa, &new_pmd); + } else { + pte_t new_pte = pfn_pte(pfn, mem_type); + + if (writable) { + new_pte = kvm_s2pte_mkwrite(new_pte); + kvm_set_pfn_dirty(pfn); + mark_page_dirty(kvm, gfn); + } + coherent_cache_guest_page(vcpu, pfn, PAGE_SIZE); + ret = stage2_set_pte(kvm, memcache, fault_ipa, &new_pte, flags); + } + +out_unlock: + spin_unlock(&kvm->mmu_lock); + kvm_set_pfn_accessed(pfn); + kvm_release_pfn_clean(pfn); + return ret; +} + +/* + * Resolve the access fault by making the page young again. + * Note that because the faulting entry is guaranteed not to be + * cached in the TLB, we don't need to invalidate anything. + * Only the HW Access Flag updates are supported for Stage 2 (no DBM), + * so there is no need for atomic (pte|pmd)_mkyoung operations. + */ +static void handle_access_fault(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa) +{ + pmd_t *pmd; + pte_t *pte; + kvm_pfn_t pfn; + bool pfn_valid = false; + + trace_kvm_access_fault(fault_ipa); + + spin_lock(&vcpu->kvm->mmu_lock); + + pmd = stage2_get_pmd(vcpu->kvm, NULL, fault_ipa); + if (!pmd || pmd_none(*pmd)) /* Nothing there */ + goto out; + + if (pmd_thp_or_huge(*pmd)) { /* THP, HugeTLB */ + *pmd = pmd_mkyoung(*pmd); + pfn = pmd_pfn(*pmd); + pfn_valid = true; + goto out; + } + + pte = pte_offset_kernel(pmd, fault_ipa); + if (pte_none(*pte)) /* Nothing there either */ + goto out; + + *pte = pte_mkyoung(*pte); /* Just a page... */ + pfn = pte_pfn(*pte); + pfn_valid = true; +out: + spin_unlock(&vcpu->kvm->mmu_lock); + if (pfn_valid) + kvm_set_pfn_accessed(pfn); +} + +/** + * kvm_handle_guest_abort - handles all 2nd stage aborts + * @vcpu: the VCPU pointer + * @run: the kvm_run structure + * + * Any abort that gets to the host is almost guaranteed to be caused by a + * missing second stage translation table entry, which can mean that either the + * guest simply needs more memory and we must allocate an appropriate page or it + * can mean that the guest tried to access I/O memory, which is emulated by user + * space. The distinction is based on the IPA causing the fault and whether this + * memory region has been registered as standard RAM by user space. + */ +int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + unsigned long fault_status; + phys_addr_t fault_ipa; + struct kvm_memory_slot *memslot; + unsigned long hva; + bool is_iabt, write_fault, writable; + gfn_t gfn; + int ret, idx; + + is_iabt = kvm_vcpu_trap_is_iabt(vcpu); + if (unlikely(!is_iabt && kvm_vcpu_dabt_isextabt(vcpu))) { + kvm_inject_vabt(vcpu); + return 1; + } + + fault_ipa = kvm_vcpu_get_fault_ipa(vcpu); + + trace_kvm_guest_fault(*vcpu_pc(vcpu), kvm_vcpu_get_hsr(vcpu), + kvm_vcpu_get_hfar(vcpu), fault_ipa); + + /* Check the stage-2 fault is trans. fault or write fault */ + fault_status = kvm_vcpu_trap_get_fault_type(vcpu); + if (fault_status != FSC_FAULT && fault_status != FSC_PERM && + fault_status != FSC_ACCESS) { + kvm_err("Unsupported FSC: EC=%#x xFSC=%#lx ESR_EL2=%#lx\n", + kvm_vcpu_trap_get_class(vcpu), + (unsigned long)kvm_vcpu_trap_get_fault(vcpu), + (unsigned long)kvm_vcpu_get_hsr(vcpu)); + return -EFAULT; + } + + idx = srcu_read_lock(&vcpu->kvm->srcu); + + gfn = fault_ipa >> PAGE_SHIFT; + memslot = gfn_to_memslot(vcpu->kvm, gfn); + hva = gfn_to_hva_memslot_prot(memslot, gfn, &writable); + write_fault = kvm_is_write_fault(vcpu); + if (kvm_is_error_hva(hva) || (write_fault && !writable)) { + if (is_iabt) { + /* Prefetch Abort on I/O address */ + kvm_inject_pabt(vcpu, kvm_vcpu_get_hfar(vcpu)); + ret = 1; + goto out_unlock; + } + + /* + * Check for a cache maintenance operation. Since we + * ended-up here, we know it is outside of any memory + * slot. But we can't find out if that is for a device, + * or if the guest is just being stupid. The only thing + * we know for sure is that this range cannot be cached. + * + * So let's assume that the guest is just being + * cautious, and skip the instruction. + */ + if (kvm_vcpu_dabt_is_cm(vcpu)) { + kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu)); + ret = 1; + goto out_unlock; + } + + /* + * The IPA is reported as [MAX:12], so we need to + * complement it with the bottom 12 bits from the + * faulting VA. This is always 12 bits, irrespective + * of the page size. + */ + fault_ipa |= kvm_vcpu_get_hfar(vcpu) & ((1 << 12) - 1); + ret = io_mem_abort(vcpu, run, fault_ipa); + goto out_unlock; + } + + /* Userspace should not be able to register out-of-bounds IPAs */ + VM_BUG_ON(fault_ipa >= KVM_PHYS_SIZE); + + if (fault_status == FSC_ACCESS) { + handle_access_fault(vcpu, fault_ipa); + ret = 1; + goto out_unlock; + } + + ret = user_mem_abort(vcpu, fault_ipa, memslot, hva, fault_status); + if (ret == 0) + ret = 1; +out_unlock: + srcu_read_unlock(&vcpu->kvm->srcu, idx); + return ret; +} + +static int handle_hva_to_gpa(struct kvm *kvm, + unsigned long start, + unsigned long end, + int (*handler)(struct kvm *kvm, + gpa_t gpa, u64 size, + void *data), + void *data) +{ + struct kvm_memslots *slots; + struct kvm_memory_slot *memslot; + int ret = 0; + + slots = kvm_memslots(kvm); + + /* we only care about the pages that the guest sees */ + kvm_for_each_memslot(memslot, slots) { + unsigned long hva_start, hva_end; + gfn_t gpa; + + hva_start = max(start, memslot->userspace_addr); + hva_end = min(end, memslot->userspace_addr + + (memslot->npages << PAGE_SHIFT)); + if (hva_start >= hva_end) + continue; + + gpa = hva_to_gfn_memslot(hva_start, memslot) << PAGE_SHIFT; + ret |= handler(kvm, gpa, (u64)(hva_end - hva_start), data); + } + + return ret; +} + +static int kvm_unmap_hva_handler(struct kvm *kvm, gpa_t gpa, u64 size, void *data) +{ + unmap_stage2_range(kvm, gpa, size); + return 0; +} + +int kvm_unmap_hva(struct kvm *kvm, unsigned long hva) +{ + unsigned long end = hva + PAGE_SIZE; + + if (!kvm->arch.pgd) + return 0; + + trace_kvm_unmap_hva(hva); + handle_hva_to_gpa(kvm, hva, end, &kvm_unmap_hva_handler, NULL); + return 0; +} + +int kvm_unmap_hva_range(struct kvm *kvm, + unsigned long start, unsigned long end) +{ + if (!kvm->arch.pgd) + return 0; + + trace_kvm_unmap_hva_range(start, end); + handle_hva_to_gpa(kvm, start, end, &kvm_unmap_hva_handler, NULL); + return 0; +} + +static int kvm_set_spte_handler(struct kvm *kvm, gpa_t gpa, u64 size, void *data) +{ + pte_t *pte = (pte_t *)data; + + WARN_ON(size != PAGE_SIZE); + /* + * We can always call stage2_set_pte with KVM_S2PTE_FLAG_LOGGING_ACTIVE + * flag clear because MMU notifiers will have unmapped a huge PMD before + * calling ->change_pte() (which in turn calls kvm_set_spte_hva()) and + * therefore stage2_set_pte() never needs to clear out a huge PMD + * through this calling path. + */ + stage2_set_pte(kvm, NULL, gpa, pte, 0); + return 0; +} + + +void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte) +{ + unsigned long end = hva + PAGE_SIZE; + pte_t stage2_pte; + + if (!kvm->arch.pgd) + return; + + trace_kvm_set_spte_hva(hva); + stage2_pte = pfn_pte(pte_pfn(pte), PAGE_S2); + handle_hva_to_gpa(kvm, hva, end, &kvm_set_spte_handler, &stage2_pte); +} + +static int kvm_age_hva_handler(struct kvm *kvm, gpa_t gpa, u64 size, void *data) +{ + pmd_t *pmd; + pte_t *pte; + + WARN_ON(size != PAGE_SIZE && size != PMD_SIZE); + pmd = stage2_get_pmd(kvm, NULL, gpa); + if (!pmd || pmd_none(*pmd)) /* Nothing there */ + return 0; + + if (pmd_thp_or_huge(*pmd)) /* THP, HugeTLB */ + return stage2_pmdp_test_and_clear_young(pmd); + + pte = pte_offset_kernel(pmd, gpa); + if (pte_none(*pte)) + return 0; + + return stage2_ptep_test_and_clear_young(pte); +} + +static int kvm_test_age_hva_handler(struct kvm *kvm, gpa_t gpa, u64 size, void *data) +{ + pmd_t *pmd; + pte_t *pte; + + WARN_ON(size != PAGE_SIZE && size != PMD_SIZE); + pmd = stage2_get_pmd(kvm, NULL, gpa); + if (!pmd || pmd_none(*pmd)) /* Nothing there */ + return 0; + + if (pmd_thp_or_huge(*pmd)) /* THP, HugeTLB */ + return pmd_young(*pmd); + + pte = pte_offset_kernel(pmd, gpa); + if (!pte_none(*pte)) /* Just a page... */ + return pte_young(*pte); + + return 0; +} + +int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end) +{ + trace_kvm_age_hva(start, end); + return handle_hva_to_gpa(kvm, start, end, kvm_age_hva_handler, NULL); +} + +int kvm_test_age_hva(struct kvm *kvm, unsigned long hva) +{ + trace_kvm_test_age_hva(hva); + return handle_hva_to_gpa(kvm, hva, hva, kvm_test_age_hva_handler, NULL); +} + +void kvm_mmu_free_memory_caches(struct kvm_vcpu *vcpu) +{ + mmu_free_memory_cache(&vcpu->arch.mmu_page_cache); +} + +phys_addr_t kvm_mmu_get_httbr(void) +{ + if (__kvm_cpu_uses_extended_idmap()) + return virt_to_phys(merged_hyp_pgd); + else + return virt_to_phys(hyp_pgd); +} + +phys_addr_t kvm_get_idmap_vector(void) +{ + return hyp_idmap_vector; +} + +static int kvm_map_idmap_text(pgd_t *pgd) +{ + int err; + + /* Create the idmap in the boot page tables */ + err = __create_hyp_mappings(pgd, + hyp_idmap_start, hyp_idmap_end, + __phys_to_pfn(hyp_idmap_start), + PAGE_HYP_EXEC); + if (err) + kvm_err("Failed to idmap %lx-%lx\n", + hyp_idmap_start, hyp_idmap_end); + + return err; +} + +int kvm_mmu_init(void) +{ + int err; + + hyp_idmap_start = kvm_virt_to_phys(__hyp_idmap_text_start); + hyp_idmap_end = kvm_virt_to_phys(__hyp_idmap_text_end); + hyp_idmap_vector = kvm_virt_to_phys(__kvm_hyp_init); + + /* + * We rely on the linker script to ensure at build time that the HYP + * init code does not cross a page boundary. + */ + BUG_ON((hyp_idmap_start ^ (hyp_idmap_end - 1)) & PAGE_MASK); + + kvm_info("IDMAP page: %lx\n", hyp_idmap_start); + kvm_info("HYP VA range: %lx:%lx\n", + kern_hyp_va(PAGE_OFFSET), kern_hyp_va(~0UL)); + + if (hyp_idmap_start >= kern_hyp_va(PAGE_OFFSET) && + hyp_idmap_start < kern_hyp_va(~0UL) && + hyp_idmap_start != (unsigned long)__hyp_idmap_text_start) { + /* + * The idmap page is intersecting with the VA space, + * it is not safe to continue further. + */ + kvm_err("IDMAP intersecting with HYP VA, unable to continue\n"); + err = -EINVAL; + goto out; + } + + hyp_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, hyp_pgd_order); + if (!hyp_pgd) { + kvm_err("Hyp mode PGD not allocated\n"); + err = -ENOMEM; + goto out; + } + + if (__kvm_cpu_uses_extended_idmap()) { + boot_hyp_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, + hyp_pgd_order); + if (!boot_hyp_pgd) { + kvm_err("Hyp boot PGD not allocated\n"); + err = -ENOMEM; + goto out; + } + + err = kvm_map_idmap_text(boot_hyp_pgd); + if (err) + goto out; + + merged_hyp_pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO); + if (!merged_hyp_pgd) { + kvm_err("Failed to allocate extra HYP pgd\n"); + goto out; + } + __kvm_extend_hypmap(boot_hyp_pgd, hyp_pgd, merged_hyp_pgd, + hyp_idmap_start); + } else { + err = kvm_map_idmap_text(hyp_pgd); + if (err) + goto out; + } + + return 0; +out: + free_hyp_pgds(); + return err; +} + +void kvm_arch_commit_memory_region(struct kvm *kvm, + const struct kvm_userspace_memory_region *mem, + const struct kvm_memory_slot *old, + const struct kvm_memory_slot *new, + enum kvm_mr_change change) +{ + /* + * At this point memslot has been committed and there is an + * allocated dirty_bitmap[], dirty pages will be be tracked while the + * memory slot is write protected. + */ + if (change != KVM_MR_DELETE && mem->flags & KVM_MEM_LOG_DIRTY_PAGES) + kvm_mmu_wp_memory_region(kvm, mem->slot); +} + +int kvm_arch_prepare_memory_region(struct kvm *kvm, + struct kvm_memory_slot *memslot, + const struct kvm_userspace_memory_region *mem, + enum kvm_mr_change change) +{ + hva_t hva = mem->userspace_addr; + hva_t reg_end = hva + mem->memory_size; + bool writable = !(mem->flags & KVM_MEM_READONLY); + int ret = 0; + + if (change != KVM_MR_CREATE && change != KVM_MR_MOVE && + change != KVM_MR_FLAGS_ONLY) + return 0; + + /* + * Prevent userspace from creating a memory region outside of the IPA + * space addressable by the KVM guest IPA space. + */ + if (memslot->base_gfn + memslot->npages >= + (KVM_PHYS_SIZE >> PAGE_SHIFT)) + return -EFAULT; + + /* + * A memory region could potentially cover multiple VMAs, and any holes + * between them, so iterate over all of them to find out if we can map + * any of them right now. + * + * +--------------------------------------------+ + * +---------------+----------------+ +----------------+ + * | : VMA 1 | VMA 2 | | VMA 3 : | + * +---------------+----------------+ +----------------+ + * | memory region | + * +--------------------------------------------+ + */ + do { + struct vm_area_struct *vma = find_vma(current->mm, hva); + hva_t vm_start, vm_end; + + if (!vma || vma->vm_start >= reg_end) + break; + + /* + * Mapping a read-only VMA is only allowed if the + * memory region is configured as read-only. + */ + if (writable && !(vma->vm_flags & VM_WRITE)) { + ret = -EPERM; + break; + } + + /* + * Take the intersection of this VMA with the memory region + */ + vm_start = max(hva, vma->vm_start); + vm_end = min(reg_end, vma->vm_end); + + if (vma->vm_flags & VM_PFNMAP) { + gpa_t gpa = mem->guest_phys_addr + + (vm_start - mem->userspace_addr); + phys_addr_t pa; + + pa = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT; + pa += vm_start - vma->vm_start; + + /* IO region dirty page logging not allowed */ + if (memslot->flags & KVM_MEM_LOG_DIRTY_PAGES) + return -EINVAL; + + ret = kvm_phys_addr_ioremap(kvm, gpa, pa, + vm_end - vm_start, + writable); + if (ret) + break; + } + hva = vm_end; + } while (hva < reg_end); + + if (change == KVM_MR_FLAGS_ONLY) + return ret; + + spin_lock(&kvm->mmu_lock); + if (ret) + unmap_stage2_range(kvm, mem->guest_phys_addr, mem->memory_size); + else + stage2_flush_memslot(kvm, memslot); + spin_unlock(&kvm->mmu_lock); + return ret; +} + +void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free, + struct kvm_memory_slot *dont) +{ +} + +int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot, + unsigned long npages) +{ + return 0; +} + +void kvm_arch_memslots_updated(struct kvm *kvm, struct kvm_memslots *slots) +{ +} + +void kvm_arch_flush_shadow_all(struct kvm *kvm) +{ + kvm_free_stage2_pgd(kvm); +} + +void kvm_arch_flush_shadow_memslot(struct kvm *kvm, + struct kvm_memory_slot *slot) +{ + gpa_t gpa = slot->base_gfn << PAGE_SHIFT; + phys_addr_t size = slot->npages << PAGE_SHIFT; + + spin_lock(&kvm->mmu_lock); + unmap_stage2_range(kvm, gpa, size); + spin_unlock(&kvm->mmu_lock); +} + +/* + * See note at ARMv7 ARM B1.14.4 (TL;DR: S/W ops are not easily virtualized). + * + * Main problems: + * - S/W ops are local to a CPU (not broadcast) + * - We have line migration behind our back (speculation) + * - System caches don't support S/W at all (damn!) + * + * In the face of the above, the best we can do is to try and convert + * S/W ops to VA ops. Because the guest is not allowed to infer the + * S/W to PA mapping, it can only use S/W to nuke the whole cache, + * which is a rather good thing for us. + * + * Also, it is only used when turning caches on/off ("The expected + * usage of the cache maintenance instructions that operate by set/way + * is associated with the cache maintenance instructions associated + * with the powerdown and powerup of caches, if this is required by + * the implementation."). + * + * We use the following policy: + * + * - If we trap a S/W operation, we enable VM trapping to detect + * caches being turned on/off, and do a full clean. + * + * - We flush the caches on both caches being turned on and off. + * + * - Once the caches are enabled, we stop trapping VM ops. + */ +void kvm_set_way_flush(struct kvm_vcpu *vcpu) +{ + unsigned long hcr = vcpu_get_hcr(vcpu); + + /* + * If this is the first time we do a S/W operation + * (i.e. HCR_TVM not set) flush the whole memory, and set the + * VM trapping. + * + * Otherwise, rely on the VM trapping to wait for the MMU + + * Caches to be turned off. At that point, we'll be able to + * clean the caches again. + */ + if (!(hcr & HCR_TVM)) { + trace_kvm_set_way_flush(*vcpu_pc(vcpu), + vcpu_has_cache_enabled(vcpu)); + stage2_flush_vm(vcpu->kvm); + vcpu_set_hcr(vcpu, hcr | HCR_TVM); + } +} + +void kvm_toggle_cache(struct kvm_vcpu *vcpu, bool was_enabled) +{ + bool now_enabled = vcpu_has_cache_enabled(vcpu); + + /* + * If switching the MMU+caches on, need to invalidate the caches. + * If switching it off, need to clean the caches. + * Clean + invalidate does the trick always. + */ + if (now_enabled != was_enabled) + stage2_flush_vm(vcpu->kvm); + + /* Caches are now on, stop trapping VM ops (until a S/W op) */ + if (now_enabled) + vcpu_set_hcr(vcpu, vcpu_get_hcr(vcpu) & ~HCR_TVM); + + trace_kvm_toggle_cache(*vcpu_pc(vcpu), was_enabled, now_enabled); +} diff --git a/virt/kvm/arm/perf.c b/virt/kvm/arm/perf.c new file mode 100644 index 000000000000..1a3849da0b4b --- /dev/null +++ b/virt/kvm/arm/perf.c @@ -0,0 +1,68 @@ +/* + * Based on the x86 implementation. + * + * Copyright (C) 2012 ARM Ltd. + * Author: Marc Zyngier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include + +static int kvm_is_in_guest(void) +{ + return kvm_arm_get_running_vcpu() != NULL; +} + +static int kvm_is_user_mode(void) +{ + struct kvm_vcpu *vcpu; + + vcpu = kvm_arm_get_running_vcpu(); + + if (vcpu) + return !vcpu_mode_priv(vcpu); + + return 0; +} + +static unsigned long kvm_get_guest_ip(void) +{ + struct kvm_vcpu *vcpu; + + vcpu = kvm_arm_get_running_vcpu(); + + if (vcpu) + return *vcpu_pc(vcpu); + + return 0; +} + +static struct perf_guest_info_callbacks kvm_guest_cbs = { + .is_in_guest = kvm_is_in_guest, + .is_user_mode = kvm_is_user_mode, + .get_guest_ip = kvm_get_guest_ip, +}; + +int kvm_perf_init(void) +{ + return perf_register_guest_info_callbacks(&kvm_guest_cbs); +} + +int kvm_perf_teardown(void) +{ + return perf_unregister_guest_info_callbacks(&kvm_guest_cbs); +} diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c new file mode 100644 index 000000000000..a08d7a93aebb --- /dev/null +++ b/virt/kvm/arm/psci.c @@ -0,0 +1,332 @@ +/* + * Copyright (C) 2012 - ARM Ltd + * Author: Marc Zyngier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include + +/* + * This is an implementation of the Power State Coordination Interface + * as described in ARM document number ARM DEN 0022A. + */ + +#define AFFINITY_MASK(level) ~((0x1UL << ((level) * MPIDR_LEVEL_BITS)) - 1) + +static unsigned long psci_affinity_mask(unsigned long affinity_level) +{ + if (affinity_level <= 3) + return MPIDR_HWID_BITMASK & AFFINITY_MASK(affinity_level); + + return 0; +} + +static unsigned long kvm_psci_vcpu_suspend(struct kvm_vcpu *vcpu) +{ + /* + * NOTE: For simplicity, we make VCPU suspend emulation to be + * same-as WFI (Wait-for-interrupt) emulation. + * + * This means for KVM the wakeup events are interrupts and + * this is consistent with intended use of StateID as described + * in section 5.4.1 of PSCI v0.2 specification (ARM DEN 0022A). + * + * Further, we also treat power-down request to be same as + * stand-by request as-per section 5.4.2 clause 3 of PSCI v0.2 + * specification (ARM DEN 0022A). This means all suspend states + * for KVM will preserve the register state. + */ + kvm_vcpu_block(vcpu); + + return PSCI_RET_SUCCESS; +} + +static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu) +{ + vcpu->arch.power_off = true; +} + +static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) +{ + struct kvm *kvm = source_vcpu->kvm; + struct kvm_vcpu *vcpu = NULL; + struct swait_queue_head *wq; + unsigned long cpu_id; + unsigned long context_id; + phys_addr_t target_pc; + + cpu_id = vcpu_get_reg(source_vcpu, 1) & MPIDR_HWID_BITMASK; + if (vcpu_mode_is_32bit(source_vcpu)) + cpu_id &= ~((u32) 0); + + vcpu = kvm_mpidr_to_vcpu(kvm, cpu_id); + + /* + * Make sure the caller requested a valid CPU and that the CPU is + * turned off. + */ + if (!vcpu) + return PSCI_RET_INVALID_PARAMS; + if (!vcpu->arch.power_off) { + if (kvm_psci_version(source_vcpu) != KVM_ARM_PSCI_0_1) + return PSCI_RET_ALREADY_ON; + else + return PSCI_RET_INVALID_PARAMS; + } + + target_pc = vcpu_get_reg(source_vcpu, 2); + context_id = vcpu_get_reg(source_vcpu, 3); + + kvm_reset_vcpu(vcpu); + + /* Gracefully handle Thumb2 entry point */ + if (vcpu_mode_is_32bit(vcpu) && (target_pc & 1)) { + target_pc &= ~((phys_addr_t) 1); + vcpu_set_thumb(vcpu); + } + + /* Propagate caller endianness */ + if (kvm_vcpu_is_be(source_vcpu)) + kvm_vcpu_set_be(vcpu); + + *vcpu_pc(vcpu) = target_pc; + /* + * NOTE: We always update r0 (or x0) because for PSCI v0.1 + * the general puspose registers are undefined upon CPU_ON. + */ + vcpu_set_reg(vcpu, 0, context_id); + vcpu->arch.power_off = false; + smp_mb(); /* Make sure the above is visible */ + + wq = kvm_arch_vcpu_wq(vcpu); + swake_up(wq); + + return PSCI_RET_SUCCESS; +} + +static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu) +{ + int i, matching_cpus = 0; + unsigned long mpidr; + unsigned long target_affinity; + unsigned long target_affinity_mask; + unsigned long lowest_affinity_level; + struct kvm *kvm = vcpu->kvm; + struct kvm_vcpu *tmp; + + target_affinity = vcpu_get_reg(vcpu, 1); + lowest_affinity_level = vcpu_get_reg(vcpu, 2); + + /* Determine target affinity mask */ + target_affinity_mask = psci_affinity_mask(lowest_affinity_level); + if (!target_affinity_mask) + return PSCI_RET_INVALID_PARAMS; + + /* Ignore other bits of target affinity */ + target_affinity &= target_affinity_mask; + + /* + * If one or more VCPU matching target affinity are running + * then ON else OFF + */ + kvm_for_each_vcpu(i, tmp, kvm) { + mpidr = kvm_vcpu_get_mpidr_aff(tmp); + if ((mpidr & target_affinity_mask) == target_affinity) { + matching_cpus++; + if (!tmp->arch.power_off) + return PSCI_0_2_AFFINITY_LEVEL_ON; + } + } + + if (!matching_cpus) + return PSCI_RET_INVALID_PARAMS; + + return PSCI_0_2_AFFINITY_LEVEL_OFF; +} + +static void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type) +{ + int i; + struct kvm_vcpu *tmp; + + /* + * The KVM ABI specifies that a system event exit may call KVM_RUN + * again and may perform shutdown/reboot at a later time that when the + * actual request is made. Since we are implementing PSCI and a + * caller of PSCI reboot and shutdown expects that the system shuts + * down or reboots immediately, let's make sure that VCPUs are not run + * after this call is handled and before the VCPUs have been + * re-initialized. + */ + kvm_for_each_vcpu(i, tmp, vcpu->kvm) { + tmp->arch.power_off = true; + kvm_vcpu_kick(tmp); + } + + memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event)); + vcpu->run->system_event.type = type; + vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT; +} + +static void kvm_psci_system_off(struct kvm_vcpu *vcpu) +{ + kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_SHUTDOWN); +} + +static void kvm_psci_system_reset(struct kvm_vcpu *vcpu) +{ + kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_RESET); +} + +int kvm_psci_version(struct kvm_vcpu *vcpu) +{ + if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) + return KVM_ARM_PSCI_0_2; + + return KVM_ARM_PSCI_0_1; +} + +static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) +{ + struct kvm *kvm = vcpu->kvm; + unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0); + unsigned long val; + int ret = 1; + + switch (psci_fn) { + case PSCI_0_2_FN_PSCI_VERSION: + /* + * Bits[31:16] = Major Version = 0 + * Bits[15:0] = Minor Version = 2 + */ + val = 2; + break; + case PSCI_0_2_FN_CPU_SUSPEND: + case PSCI_0_2_FN64_CPU_SUSPEND: + val = kvm_psci_vcpu_suspend(vcpu); + break; + case PSCI_0_2_FN_CPU_OFF: + kvm_psci_vcpu_off(vcpu); + val = PSCI_RET_SUCCESS; + break; + case PSCI_0_2_FN_CPU_ON: + case PSCI_0_2_FN64_CPU_ON: + mutex_lock(&kvm->lock); + val = kvm_psci_vcpu_on(vcpu); + mutex_unlock(&kvm->lock); + break; + case PSCI_0_2_FN_AFFINITY_INFO: + case PSCI_0_2_FN64_AFFINITY_INFO: + val = kvm_psci_vcpu_affinity_info(vcpu); + break; + case PSCI_0_2_FN_MIGRATE_INFO_TYPE: + /* + * Trusted OS is MP hence does not require migration + * or + * Trusted OS is not present + */ + val = PSCI_0_2_TOS_MP; + break; + case PSCI_0_2_FN_SYSTEM_OFF: + kvm_psci_system_off(vcpu); + /* + * We should'nt be going back to guest VCPU after + * receiving SYSTEM_OFF request. + * + * If user space accidently/deliberately resumes + * guest VCPU after SYSTEM_OFF request then guest + * VCPU should see internal failure from PSCI return + * value. To achieve this, we preload r0 (or x0) with + * PSCI return value INTERNAL_FAILURE. + */ + val = PSCI_RET_INTERNAL_FAILURE; + ret = 0; + break; + case PSCI_0_2_FN_SYSTEM_RESET: + kvm_psci_system_reset(vcpu); + /* + * Same reason as SYSTEM_OFF for preloading r0 (or x0) + * with PSCI return value INTERNAL_FAILURE. + */ + val = PSCI_RET_INTERNAL_FAILURE; + ret = 0; + break; + default: + val = PSCI_RET_NOT_SUPPORTED; + break; + } + + vcpu_set_reg(vcpu, 0, val); + return ret; +} + +static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) +{ + struct kvm *kvm = vcpu->kvm; + unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0); + unsigned long val; + + switch (psci_fn) { + case KVM_PSCI_FN_CPU_OFF: + kvm_psci_vcpu_off(vcpu); + val = PSCI_RET_SUCCESS; + break; + case KVM_PSCI_FN_CPU_ON: + mutex_lock(&kvm->lock); + val = kvm_psci_vcpu_on(vcpu); + mutex_unlock(&kvm->lock); + break; + default: + val = PSCI_RET_NOT_SUPPORTED; + break; + } + + vcpu_set_reg(vcpu, 0, val); + return 1; +} + +/** + * kvm_psci_call - handle PSCI call if r0 value is in range + * @vcpu: Pointer to the VCPU struct + * + * Handle PSCI calls from guests through traps from HVC instructions. + * The calling convention is similar to SMC calls to the secure world + * where the function number is placed in r0. + * + * This function returns: > 0 (success), 0 (success but exit to user + * space), and < 0 (errors) + * + * Errors: + * -EINVAL: Unrecognized PSCI function + */ +int kvm_psci_call(struct kvm_vcpu *vcpu) +{ + switch (kvm_psci_version(vcpu)) { + case KVM_ARM_PSCI_0_2: + return kvm_psci_0_2_call(vcpu); + case KVM_ARM_PSCI_0_1: + return kvm_psci_0_1_call(vcpu); + default: + return -EINVAL; + }; +} diff --git a/virt/kvm/arm/trace.h b/virt/kvm/arm/trace.h index 37d8b98867d5..f7dc5ddd6847 100644 --- a/virt/kvm/arm/trace.h +++ b/virt/kvm/arm/trace.h @@ -7,26 +7,250 @@ #define TRACE_SYSTEM kvm /* - * Tracepoints for vgic + * Tracepoints for entry/exit to guest */ -TRACE_EVENT(vgic_update_irq_pending, - TP_PROTO(unsigned long vcpu_id, __u32 irq, bool level), - TP_ARGS(vcpu_id, irq, level), +TRACE_EVENT(kvm_entry, + TP_PROTO(unsigned long vcpu_pc), + TP_ARGS(vcpu_pc), TP_STRUCT__entry( - __field( unsigned long, vcpu_id ) - __field( __u32, irq ) - __field( bool, level ) + __field( unsigned long, vcpu_pc ) ), TP_fast_assign( - __entry->vcpu_id = vcpu_id; - __entry->irq = irq; + __entry->vcpu_pc = vcpu_pc; + ), + + TP_printk("PC: 0x%08lx", __entry->vcpu_pc) +); + +TRACE_EVENT(kvm_exit, + TP_PROTO(int idx, unsigned int exit_reason, unsigned long vcpu_pc), + TP_ARGS(idx, exit_reason, vcpu_pc), + + TP_STRUCT__entry( + __field( int, idx ) + __field( unsigned int, exit_reason ) + __field( unsigned long, vcpu_pc ) + ), + + TP_fast_assign( + __entry->idx = idx; + __entry->exit_reason = exit_reason; + __entry->vcpu_pc = vcpu_pc; + ), + + TP_printk("%s: HSR_EC: 0x%04x (%s), PC: 0x%08lx", + __print_symbolic(__entry->idx, kvm_arm_exception_type), + __entry->exit_reason, + __print_symbolic(__entry->exit_reason, kvm_arm_exception_class), + __entry->vcpu_pc) +); + +TRACE_EVENT(kvm_guest_fault, + TP_PROTO(unsigned long vcpu_pc, unsigned long hsr, + unsigned long hxfar, + unsigned long long ipa), + TP_ARGS(vcpu_pc, hsr, hxfar, ipa), + + TP_STRUCT__entry( + __field( unsigned long, vcpu_pc ) + __field( unsigned long, hsr ) + __field( unsigned long, hxfar ) + __field( unsigned long long, ipa ) + ), + + TP_fast_assign( + __entry->vcpu_pc = vcpu_pc; + __entry->hsr = hsr; + __entry->hxfar = hxfar; + __entry->ipa = ipa; + ), + + TP_printk("ipa %#llx, hsr %#08lx, hxfar %#08lx, pc %#08lx", + __entry->ipa, __entry->hsr, + __entry->hxfar, __entry->vcpu_pc) +); + +TRACE_EVENT(kvm_access_fault, + TP_PROTO(unsigned long ipa), + TP_ARGS(ipa), + + TP_STRUCT__entry( + __field( unsigned long, ipa ) + ), + + TP_fast_assign( + __entry->ipa = ipa; + ), + + TP_printk("IPA: %lx", __entry->ipa) +); + +TRACE_EVENT(kvm_irq_line, + TP_PROTO(unsigned int type, int vcpu_idx, int irq_num, int level), + TP_ARGS(type, vcpu_idx, irq_num, level), + + TP_STRUCT__entry( + __field( unsigned int, type ) + __field( int, vcpu_idx ) + __field( int, irq_num ) + __field( int, level ) + ), + + TP_fast_assign( + __entry->type = type; + __entry->vcpu_idx = vcpu_idx; + __entry->irq_num = irq_num; __entry->level = level; ), - TP_printk("VCPU: %ld, IRQ %d, level: %d", - __entry->vcpu_id, __entry->irq, __entry->level) + TP_printk("Inject %s interrupt (%d), vcpu->idx: %d, num: %d, level: %d", + (__entry->type == KVM_ARM_IRQ_TYPE_CPU) ? "CPU" : + (__entry->type == KVM_ARM_IRQ_TYPE_PPI) ? "VGIC PPI" : + (__entry->type == KVM_ARM_IRQ_TYPE_SPI) ? "VGIC SPI" : "UNKNOWN", + __entry->type, __entry->vcpu_idx, __entry->irq_num, __entry->level) +); + +TRACE_EVENT(kvm_mmio_emulate, + TP_PROTO(unsigned long vcpu_pc, unsigned long instr, + unsigned long cpsr), + TP_ARGS(vcpu_pc, instr, cpsr), + + TP_STRUCT__entry( + __field( unsigned long, vcpu_pc ) + __field( unsigned long, instr ) + __field( unsigned long, cpsr ) + ), + + TP_fast_assign( + __entry->vcpu_pc = vcpu_pc; + __entry->instr = instr; + __entry->cpsr = cpsr; + ), + + TP_printk("Emulate MMIO at: 0x%08lx (instr: %08lx, cpsr: %08lx)", + __entry->vcpu_pc, __entry->instr, __entry->cpsr) +); + +TRACE_EVENT(kvm_unmap_hva, + TP_PROTO(unsigned long hva), + TP_ARGS(hva), + + TP_STRUCT__entry( + __field( unsigned long, hva ) + ), + + TP_fast_assign( + __entry->hva = hva; + ), + + TP_printk("mmu notifier unmap hva: %#08lx", __entry->hva) +); + +TRACE_EVENT(kvm_unmap_hva_range, + TP_PROTO(unsigned long start, unsigned long end), + TP_ARGS(start, end), + + TP_STRUCT__entry( + __field( unsigned long, start ) + __field( unsigned long, end ) + ), + + TP_fast_assign( + __entry->start = start; + __entry->end = end; + ), + + TP_printk("mmu notifier unmap range: %#08lx -- %#08lx", + __entry->start, __entry->end) +); + +TRACE_EVENT(kvm_set_spte_hva, + TP_PROTO(unsigned long hva), + TP_ARGS(hva), + + TP_STRUCT__entry( + __field( unsigned long, hva ) + ), + + TP_fast_assign( + __entry->hva = hva; + ), + + TP_printk("mmu notifier set pte hva: %#08lx", __entry->hva) +); + +TRACE_EVENT(kvm_age_hva, + TP_PROTO(unsigned long start, unsigned long end), + TP_ARGS(start, end), + + TP_STRUCT__entry( + __field( unsigned long, start ) + __field( unsigned long, end ) + ), + + TP_fast_assign( + __entry->start = start; + __entry->end = end; + ), + + TP_printk("mmu notifier age hva: %#08lx -- %#08lx", + __entry->start, __entry->end) +); + +TRACE_EVENT(kvm_test_age_hva, + TP_PROTO(unsigned long hva), + TP_ARGS(hva), + + TP_STRUCT__entry( + __field( unsigned long, hva ) + ), + + TP_fast_assign( + __entry->hva = hva; + ), + + TP_printk("mmu notifier test age hva: %#08lx", __entry->hva) +); + +TRACE_EVENT(kvm_set_way_flush, + TP_PROTO(unsigned long vcpu_pc, bool cache), + TP_ARGS(vcpu_pc, cache), + + TP_STRUCT__entry( + __field( unsigned long, vcpu_pc ) + __field( bool, cache ) + ), + + TP_fast_assign( + __entry->vcpu_pc = vcpu_pc; + __entry->cache = cache; + ), + + TP_printk("S/W flush at 0x%016lx (cache %s)", + __entry->vcpu_pc, __entry->cache ? "on" : "off") +); + +TRACE_EVENT(kvm_toggle_cache, + TP_PROTO(unsigned long vcpu_pc, bool was, bool now), + TP_ARGS(vcpu_pc, was, now), + + TP_STRUCT__entry( + __field( unsigned long, vcpu_pc ) + __field( bool, was ) + __field( bool, now ) + ), + + TP_fast_assign( + __entry->vcpu_pc = vcpu_pc; + __entry->was = was; + __entry->now = now; + ), + + TP_printk("VM op at 0x%016lx (cache was %s, now %s)", + __entry->vcpu_pc, __entry->was ? "on" : "off", + __entry->now ? "on" : "off") ); /* diff --git a/virt/kvm/arm/vgic/trace.h b/virt/kvm/arm/vgic/trace.h new file mode 100644 index 000000000000..ed3229282888 --- /dev/null +++ b/virt/kvm/arm/vgic/trace.h @@ -0,0 +1,37 @@ +#if !defined(_TRACE_VGIC_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_VGIC_H + +#include + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM kvm + +TRACE_EVENT(vgic_update_irq_pending, + TP_PROTO(unsigned long vcpu_id, __u32 irq, bool level), + TP_ARGS(vcpu_id, irq, level), + + TP_STRUCT__entry( + __field( unsigned long, vcpu_id ) + __field( __u32, irq ) + __field( bool, level ) + ), + + TP_fast_assign( + __entry->vcpu_id = vcpu_id; + __entry->irq = irq; + __entry->level = level; + ), + + TP_printk("VCPU: %ld, IRQ %d, level: %d", + __entry->vcpu_id, __entry->irq, __entry->level) +); + +#endif /* _TRACE_VGIC_H */ + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH ../../../virt/kvm/arm/vgic +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE trace + +/* This part must be outside protection */ +#include diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c index 3d0979c30721..d40210ae9474 100644 --- a/virt/kvm/arm/vgic/vgic.c +++ b/virt/kvm/arm/vgic/vgic.c @@ -21,7 +21,7 @@ #include "vgic.h" #define CREATE_TRACE_POINTS -#include "../trace.h" +#include "trace.h" #ifdef CONFIG_DEBUG_SPINLOCK #define DEBUG_SPINLOCK_BUG_ON(p) BUG_ON(p) -- cgit v1.2.3-59-g8ed1b From 42fc6c6cb1662ba2fa727dd01c9473c63be4e3b6 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Thu, 4 May 2017 09:51:40 -0500 Subject: x86/asm: Don't use RBP as a temporary register in csum_partial_copy_generic() Andrey Konovalov reported the following warning while fuzzing the kernel with syzkaller: WARNING: kernel stack regs at ffff8800686869f8 in a.out:4933 has bad 'bp' value c3fc855a10167ec0 The unwinder dump revealed that RBP had a bad value when an interrupt occurred in csum_partial_copy_generic(). That function saves RBP on the stack and then overwrites it, using it as a scratch register. That's problematic because it breaks stack traces if an interrupt occurs in the middle of the function. Replace the usage of RBP with another callee-saved register (R15) so stack traces are no longer affected. Reported-by: Andrey Konovalov Tested-by: Andrey Konovalov Signed-off-by: Josh Poimboeuf Cc: Cong Wang Cc: David S . Miller Cc: Dmitry Vyukov Cc: Eric Dumazet Cc: Kostya Serebryany Cc: Linus Torvalds Cc: Marcelo Ricardo Leitner Cc: Neil Horman Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Vlad Yasevich Cc: linux-sctp@vger.kernel.org Cc: netdev Cc: syzkaller Link: http://lkml.kernel.org/r/4b03a961efda5ec9bfe46b7b9c9ad72d1efad343.1493909486.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar --- arch/x86/lib/csum-copy_64.S | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/lib/csum-copy_64.S b/arch/x86/lib/csum-copy_64.S index 7e48807b2fa1..45a53dfe1859 100644 --- a/arch/x86/lib/csum-copy_64.S +++ b/arch/x86/lib/csum-copy_64.S @@ -55,7 +55,7 @@ ENTRY(csum_partial_copy_generic) movq %r12, 3*8(%rsp) movq %r14, 4*8(%rsp) movq %r13, 5*8(%rsp) - movq %rbp, 6*8(%rsp) + movq %r15, 6*8(%rsp) movq %r8, (%rsp) movq %r9, 1*8(%rsp) @@ -74,7 +74,7 @@ ENTRY(csum_partial_copy_generic) /* main loop. clear in 64 byte blocks */ /* r9: zero, r8: temp2, rbx: temp1, rax: sum, rcx: saved length */ /* r11: temp3, rdx: temp4, r12 loopcnt */ - /* r10: temp5, rbp: temp6, r14 temp7, r13 temp8 */ + /* r10: temp5, r15: temp6, r14 temp7, r13 temp8 */ .p2align 4 .Lloop: source @@ -89,7 +89,7 @@ ENTRY(csum_partial_copy_generic) source movq 32(%rdi), %r10 source - movq 40(%rdi), %rbp + movq 40(%rdi), %r15 source movq 48(%rdi), %r14 source @@ -103,7 +103,7 @@ ENTRY(csum_partial_copy_generic) adcq %r11, %rax adcq %rdx, %rax adcq %r10, %rax - adcq %rbp, %rax + adcq %r15, %rax adcq %r14, %rax adcq %r13, %rax @@ -121,7 +121,7 @@ ENTRY(csum_partial_copy_generic) dest movq %r10, 32(%rsi) dest - movq %rbp, 40(%rsi) + movq %r15, 40(%rsi) dest movq %r14, 48(%rsi) dest @@ -203,7 +203,7 @@ ENTRY(csum_partial_copy_generic) movq 3*8(%rsp), %r12 movq 4*8(%rsp), %r14 movq 5*8(%rsp), %r13 - movq 6*8(%rsp), %rbp + movq 6*8(%rsp), %r15 addq $7*8, %rsp ret -- cgit v1.2.3-59-g8ed1b From fc5f9d5f151c9fff21d3d1d2907b888a5aec3ff7 Mon Sep 17 00:00:00 2001 From: Baoquan He Date: Thu, 4 May 2017 10:25:47 +0800 Subject: x86/mm: Fix boot crash caused by incorrect loop count calculation in sync_global_pgds() Jeff Moyer reported that on his system with two memory regions 0~64G and 1T~1T+192G, and kernel option "memmap=192G!1024G" added, enabling KASLR will make the system hang intermittently during boot. While adding 'nokaslr' won't. The back trace is: Oops: 0000 [#1] SMP RIP: memcpy_erms() [ .... ] Call Trace: pmem_rw_page() bdev_read_page() do_mpage_readpage() mpage_readpages() blkdev_readpages() __do_page_cache_readahead() force_page_cache_readahead() page_cache_sync_readahead() generic_file_read_iter() blkdev_read_iter() __vfs_read() vfs_read() SyS_read() entry_SYSCALL_64_fastpath() This crash happens because the for loop count calculation in sync_global_pgds() is not correct. When a mapping area crosses PGD entries, we should calculate the starting address of region which next PGD covers and assign it to next for loop count, but not add PGDIR_SIZE directly. The old code works right only if the mapping area is an exact multiple of PGDIR_SIZE, otherwize the end region could be skipped so that it can't be synchronized to all other processes from kernel PGD init_mm.pgd. In Jeff's system, emulated pmem area [1024G, 1216G) is smaller than PGDIR_SIZE. While 'nokaslr' works because PAGE_OFFSET is 1T aligned, it makes this area be mapped inside one PGD entry. With KASLR enabled, this area could cross two PGD entries, then the next PGD entry won't be synced to all other processes. That is why we saw empty PGD. Fix it. Reported-by: Jeff Moyer Signed-off-by: Baoquan He Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Dan Williams Cc: Dave Hansen Cc: Dave Young Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Jinbum Park Cc: Josh Poimboeuf Cc: Kees Cook Cc: Kirill A. Shutemov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Garnier Cc: Thomas Gleixner Cc: Yasuaki Ishimatsu Cc: Yinghai Lu Link: http://lkml.kernel.org/r/1493864747-8506-1-git-send-email-bhe@redhat.com Signed-off-by: Ingo Molnar --- arch/x86/mm/init_64.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 745e5e183169..97fe88749e18 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -94,10 +94,10 @@ __setup("noexec32=", nonx32_setup); */ void sync_global_pgds(unsigned long start, unsigned long end) { - unsigned long address; + unsigned long addr; - for (address = start; address <= end; address += PGDIR_SIZE) { - pgd_t *pgd_ref = pgd_offset_k(address); + for (addr = start; addr <= end; addr = ALIGN(addr + 1, PGDIR_SIZE)) { + pgd_t *pgd_ref = pgd_offset_k(addr); const p4d_t *p4d_ref; struct page *page; @@ -106,7 +106,7 @@ void sync_global_pgds(unsigned long start, unsigned long end) * handle synchonization on p4d level. */ BUILD_BUG_ON(pgd_none(*pgd_ref)); - p4d_ref = p4d_offset(pgd_ref, address); + p4d_ref = p4d_offset(pgd_ref, addr); if (p4d_none(*p4d_ref)) continue; @@ -117,8 +117,8 @@ void sync_global_pgds(unsigned long start, unsigned long end) p4d_t *p4d; spinlock_t *pgt_lock; - pgd = (pgd_t *)page_address(page) + pgd_index(address); - p4d = p4d_offset(pgd, address); + pgd = (pgd_t *)page_address(page) + pgd_index(addr); + p4d = p4d_offset(pgd, addr); /* the pgt_lock only for Xen */ pgt_lock = &pgd_page_get_mm(page)->page_table_lock; spin_lock(pgt_lock); -- cgit v1.2.3-59-g8ed1b From 61baf15555129f69720334f232b153890895ef71 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Fri, 5 May 2017 01:22:06 -0500 Subject: powerpc/64e: Don't place the stack beyond TASK_SIZE Commit f4ea6dcb08ea ("powerpc/mm: Enable mappings above 128TB") increased the task size on book3s, and introduced a mechanism to dynamically control whether a task uses these larger addresses. While the change to the task size itself was ifdef-protected to only apply on book3s, the change to STACK_TOP_USER64 was not. On book3e, this had the effect of trying to use addresses up to 128TiB for the stack despite a 64TiB task size limit -- which broke 64-bit userspace producing the following errors: Starting init: /sbin/init exists but couldn't execute it (error -14) Starting init: /bin/sh exists but couldn't execute it (error -14) Kernel panic - not syncing: No working init found. Try passing init= option to kernel. See Linux Documentation/admin-guide/init.rst for guidance. Fixes: f4ea6dcb08ea ("powerpc/mm: Enable mappings above 128TB") Cc: Aneesh Kumar K.V Signed-off-by: Scott Wood --- arch/powerpc/include/asm/processor.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch') diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index a4b1d8d6b793..a2123f291ab0 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h @@ -151,8 +151,13 @@ void release_thread(struct task_struct *); #ifdef __powerpc64__ +#ifdef CONFIG_PPC_BOOK3S_64 /* Limit stack to 128TB */ #define STACK_TOP_USER64 TASK_SIZE_128TB +#else +#define STACK_TOP_USER64 TASK_SIZE_USER64 +#endif + #define STACK_TOP_USER32 TASK_SIZE_USER32 #define STACK_TOP (is_32bit_task() ? \ -- cgit v1.2.3-59-g8ed1b From 121843eb02a6e2fa30aefab64bfe183c97230c75 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Mon, 1 May 2017 15:47:41 -0700 Subject: x86/mm/kaslr: Use the _ASM_MUL macro for multiplication to work around Clang incompatibility The constraint "rm" allows the compiler to put mix_const into memory. When the input operand is a memory location then MUL needs an operand size suffix, since Clang can't infer the multiplication width from the operand. Add and use the _ASM_MUL macro which determines the operand size and resolves to the NUL instruction with the corresponding suffix. This fixes the following error when building with clang: CC arch/x86/lib/kaslr.o /tmp/kaslr-dfe1ad.s: Assembler messages: /tmp/kaslr-dfe1ad.s:182: Error: no instruction mnemonic suffix given and no register operands; can't size instruction Signed-off-by: Matthias Kaehlcke Cc: Grant Grundler Cc: Greg Hackmann Cc: Kees Cook Cc: Linus Torvalds Cc: Michael Davidson Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20170501224741.133938-1-mka@chromium.org Signed-off-by: Ingo Molnar --- arch/x86/include/asm/asm.h | 1 + arch/x86/lib/kaslr.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h index 7acb51c49fec..7a9df3beb89b 100644 --- a/arch/x86/include/asm/asm.h +++ b/arch/x86/include/asm/asm.h @@ -32,6 +32,7 @@ #define _ASM_ADD __ASM_SIZE(add) #define _ASM_SUB __ASM_SIZE(sub) #define _ASM_XADD __ASM_SIZE(xadd) +#define _ASM_MUL __ASM_SIZE(mul) #define _ASM_AX __ASM_REG(ax) #define _ASM_BX __ASM_REG(bx) diff --git a/arch/x86/lib/kaslr.c b/arch/x86/lib/kaslr.c index 5761a4f19455..ab2d1d73e9e7 100644 --- a/arch/x86/lib/kaslr.c +++ b/arch/x86/lib/kaslr.c @@ -5,6 +5,7 @@ * kernel starts. This file is included in the compressed kernel and * normally linked in the regular. */ +#include #include #include #include @@ -79,7 +80,7 @@ unsigned long kaslr_get_random_long(const char *purpose) } /* Circular multiply for better bit diffusion */ - asm("mul %3" + asm(_ASM_MUL "%3" : "=a" (random), "=d" (raw) : "a" (random), "rm" (mix_const)); random += raw; -- cgit v1.2.3-59-g8ed1b From 40f4ac0b510dbf9f00668ded5474290940616d09 Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Tue, 25 Apr 2017 08:47:40 +0200 Subject: x86/xen: fix xsave capability setting Commit 690b7f10b4f9f ("x86/xen: use capabilities instead of fake cpuid values for xsave") introduced a regression as it tried to make use of the fixup feature before it being available. Fall back to the old variant testing via cpuid(). Signed-off-by: Juergen Gross Reviewed-by: Boris Ostrovsky Signed-off-by: Juergen Gross --- arch/x86/xen/enlighten_pv.c | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c index a732bc2b9dfc..a1af4f68278f 100644 --- a/arch/x86/xen/enlighten_pv.c +++ b/arch/x86/xen/enlighten_pv.c @@ -277,26 +277,15 @@ static bool __init xen_check_mwait(void) static bool __init xen_check_xsave(void) { - unsigned int err, eax, edx; + unsigned int cx, xsave_mask; - /* - * Xen 4.0 and older accidentally leaked the host XSAVE flag into guest - * view, despite not being able to support guests using the - * functionality. Probe for the actual availability of XSAVE by seeing - * whether xgetbv executes successfully or raises #UD. - */ - asm volatile("1: .byte 0x0f,0x01,0xd0\n\t" /* xgetbv */ - "xor %[err], %[err]\n" - "2:\n\t" - ".pushsection .fixup,\"ax\"\n\t" - "3: movl $1,%[err]\n\t" - "jmp 2b\n\t" - ".popsection\n\t" - _ASM_EXTABLE(1b, 3b) - : [err] "=r" (err), "=a" (eax), "=d" (edx) - : "c" (0)); - - return err == 0; + cx = cpuid_ecx(1); + + xsave_mask = (1 << (X86_FEATURE_XSAVE % 32)) | + (1 << (X86_FEATURE_OSXSAVE % 32)); + + /* Xen will set CR4.OSXSAVE if supported and not disabled by force */ + return (cx & xsave_mask) == xsave_mask; } static void __init xen_init_capabilities(void) @@ -317,10 +306,7 @@ static void __init xen_init_capabilities(void) else setup_clear_cpu_cap(X86_FEATURE_MWAIT); - if (xen_check_xsave()) { - setup_force_cpu_cap(X86_FEATURE_XSAVE); - setup_force_cpu_cap(X86_FEATURE_OSXSAVE); - } else { + if (!xen_check_xsave()) { setup_clear_cpu_cap(X86_FEATURE_XSAVE); setup_clear_cpu_cap(X86_FEATURE_OSXSAVE); } -- cgit v1.2.3-59-g8ed1b From d162809f85b4f54ef075517ffa2f3d02e55d5a53 Mon Sep 17 00:00:00 2001 From: Boris Ostrovsky Date: Wed, 3 May 2017 16:20:51 -0400 Subject: xen/x86: Do not call xen_init_time_ops() until shared_info is initialized Routines that are set by xen_init_time_ops() use shared_info's pvclock_vcpu_time_info area. This area is not properly available until shared_info is mapped in xen_setup_shared_info(). This became especially problematic due to commit dd759d93f4dd ("x86/timers: Add simple udelay calibration") where we end up reading tsc_to_system_mul from xen_dummy_shared_info (i.e. getting zero value) and then trying to divide by it in pvclock_tsc_khz(). Signed-off-by: Boris Ostrovsky Reviewed-by: Juergen Gross Signed-off-by: Juergen Gross --- arch/x86/xen/enlighten_pv.c | 9 +++++++-- arch/x86/xen/time.c | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c index a1af4f68278f..b5c54ab0e195 100644 --- a/arch/x86/xen/enlighten_pv.c +++ b/arch/x86/xen/enlighten_pv.c @@ -974,6 +974,13 @@ void xen_setup_shared_info(void) #endif xen_setup_mfn_list_list(); + + /* + * Now that shared info is set up we can start using routines that + * point to pvclock area. + */ + if (system_state == SYSTEM_BOOTING) + xen_init_time_ops(); } /* This is called once we have the cpu_possible_mask */ @@ -1272,8 +1279,6 @@ asmlinkage __visible void __init xen_start_kernel(void) x86_init.oem.arch_setup = xen_arch_setup; x86_init.oem.banner = xen_banner; - xen_init_time_ops(); - /* * Set up some pagetable state before starting to set any ptes. */ diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 090c7eb4dca9..a1895a8e85c1 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -406,7 +406,7 @@ static void __init xen_time_init(void) pvclock_gtod_register_notifier(&xen_pvclock_gtod_notifier); } -void __init xen_init_time_ops(void) +void __ref xen_init_time_ops(void) { pv_time_ops = xen_time_ops; -- cgit v1.2.3-59-g8ed1b From 868a65307d3015064db2a6fb2d6e451293e3047f Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Fri, 5 May 2017 11:59:41 -0700 Subject: ARC: mm: fix build failure in linux-next for UP builds kisskb build service reported ARC defconfig build failures in linux-next | arch/arc/include/asm/mmu.h:75:21: error: 'NR_CPUS' undeclared here (not in a function) | make[3]: *** [arch/arc/mm/ioremap.o] Error 1 | make[2]: *** [arch/arc/mm] Error 2 | make[1]: *** [arch/arc] Error 2 which I bisected to a subtle side-effect of a totally benign mm patch ("mm, vmalloc: properly track vmalloc users") which caused a header include chain deviation - asm/mmu.h using NR_CPUS before including linux/threads.h Fix that by adding the dependnet header and while it at fix a related header to include linux headers aheads of asm headers as sometimes that slso triggers such issues ! Reported-by: noreply@ellerman.id.au Signed-off-by: Vineet Gupta --- arch/arc/include/asm/mmu.h | 4 ++++ arch/arc/include/asm/pgtable.h | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arc/include/asm/mmu.h b/arch/arc/include/asm/mmu.h index b144d7ca7d20..db7319e9b506 100644 --- a/arch/arc/include/asm/mmu.h +++ b/arch/arc/include/asm/mmu.h @@ -9,6 +9,10 @@ #ifndef _ASM_ARC_MMU_H #define _ASM_ARC_MMU_H +#ifndef __ASSEMBLY__ +#include /* NR_CPUS */ +#endif + #if defined(CONFIG_ARC_MMU_V1) #define CONFIG_ARC_MMU_VER 1 #elif defined(CONFIG_ARC_MMU_V2) diff --git a/arch/arc/include/asm/pgtable.h b/arch/arc/include/asm/pgtable.h index ee22d40afef4..08fe33830d4b 100644 --- a/arch/arc/include/asm/pgtable.h +++ b/arch/arc/include/asm/pgtable.h @@ -35,11 +35,11 @@ #ifndef _ASM_ARC_PGTABLE_H #define _ASM_ARC_PGTABLE_H -#include -#include +#include #define __ARCH_USE_5LEVEL_HACK #include -#include +#include +#include /* to propagate CONFIG_ARC_MMU_VER */ /************************************************************************** * Page Table Flags -- cgit v1.2.3-59-g8ed1b From cf4100d1cddcd243f80ac2af2e4c4273919ff225 Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Fri, 5 May 2017 23:20:29 +0300 Subject: Revert "ARCv2: Allow enabling PAE40 w/o HIGHMEM" This reverts commit 7cab91b87dd8eeee5911ec34be8bb0288ebba18b. Now when we have a real hardware platform with PAE40 enabled (here I mean axs103 with firmware v1.2) and 1 Gb of DDR mapped to 0x1_a000_0000-0x1_ffff_ffff we're really targeting memory above 4Gb when PAE40 is enabled. This in its turn requires HIGHMEM to be enabled otherwise user won't see any difference with enabling PAE in kernel configuration as only lowmem will be used anyways. Signed-off-by: Alexey Brodkin Signed-off-by: Vineet Gupta --- arch/arc/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 5d7fb3e7cb97..a5459698f0ee 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -444,6 +444,7 @@ config ARC_HAS_PAE40 bool "Support for the 40-bit Physical Address Extension" default n depends on ISA_ARCV2 + select HIGHMEM help Enable access to physical memory beyond 4G, only supported on ARC cores with 40 bit Physical Addressing support -- cgit v1.2.3-59-g8ed1b From 60854a12d281e2fa25662fa32ac8022bbff17432 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 5 May 2017 21:51:16 -0700 Subject: x86/boot: Declare error() as noreturn MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The compressed boot function error() is used to halt execution, but it wasn't marked with "noreturn". This fixes that in preparation for supporting kernel FORTIFY_SOURCE, which uses the noreturn annotation on panic, and calls error(). GCC would warn about a noreturn function calling a non-noreturn function: arch/x86/boot/compressed/misc.c: In function ‘fortify_panic’: arch/x86/boot/compressed/misc.c:416:1: warning: ‘noreturn’ function does return } ^ Signed-off-by: Kees Cook Cc: Daniel Micay Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: H. Peter Anvin Link: http://lkml.kernel.org/r/20170506045116.GA2879@beast Signed-off-by: Ingo Molnar --- arch/x86/boot/compressed/error.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/boot/compressed/error.h b/arch/x86/boot/compressed/error.h index 2e59dac07f9e..d732e608e3af 100644 --- a/arch/x86/boot/compressed/error.h +++ b/arch/x86/boot/compressed/error.h @@ -1,7 +1,9 @@ #ifndef BOOT_COMPRESSED_ERROR_H #define BOOT_COMPRESSED_ERROR_H +#include + void warn(char *m); -void error(char *m); +void error(char *m) __noreturn; #endif /* BOOT_COMPRESSED_ERROR_H */ -- cgit v1.2.3-59-g8ed1b From 66aad4fdf2bf0af29c7decb4433dc5ec6c7c5451 Mon Sep 17 00:00:00 2001 From: Xunlei Pang Date: Thu, 4 May 2017 09:42:50 +0800 Subject: x86/mm: Add support for gbpages to kernel_ident_mapping_init() Kernel identity mappings on x86-64 kernels are created in two ways: by the early x86 boot code, or by kernel_ident_mapping_init(). Native kernels (which is the dominant usecase) use the former, but the kexec and the hibernation code uses kernel_ident_mapping_init(). There's a subtle difference between these two ways of how identity mappings are created, the current kernel_ident_mapping_init() code creates identity mappings always using 2MB page(PMD level) - while the native kernel boot path also utilizes gbpages where available. This difference is suboptimal both for performance and for memory usage: kernel_ident_mapping_init() needs to allocate pages for the page tables when creating the new identity mappings. This patch adds 1GB page(PUD level) support to kernel_ident_mapping_init() to address these concerns. The primary advantage would be better TLB coverage/performance, because we'd utilize 1GB TLBs instead of 2MB ones. It is also useful for machines with large number of memory to save paging structure allocations(around 4MB/TB using 2MB page) when setting identity mappings for all the memory, after using 1GB page it will consume only 8KB/TB. ( Note that this change alone does not activate gbpages in kexec, we are doing that in a separate patch. ) Signed-off-by: Xunlei Pang Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Dave Young Cc: Denys Vlasenko Cc: Eric Biederman Cc: H. Peter Anvin Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Yinghai Lu Cc: akpm@linux-foundation.org Cc: kexec@lists.infradead.org Link: http://lkml.kernel.org/r/1493862171-8799-1-git-send-email-xlpang@redhat.com Signed-off-by: Ingo Molnar --- arch/x86/boot/compressed/pagetable.c | 2 +- arch/x86/include/asm/init.h | 3 ++- arch/x86/kernel/machine_kexec_64.c | 2 +- arch/x86/mm/ident_map.c | 14 +++++++++++++- arch/x86/power/hibernate_64.c | 2 +- 5 files changed, 18 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/boot/compressed/pagetable.c b/arch/x86/boot/compressed/pagetable.c index 56589d0a804b..1d78f1739087 100644 --- a/arch/x86/boot/compressed/pagetable.c +++ b/arch/x86/boot/compressed/pagetable.c @@ -70,7 +70,7 @@ static unsigned long level4p; * Due to relocation, pointers must be assigned at run time not build time. */ static struct x86_mapping_info mapping_info = { - .pmd_flag = __PAGE_KERNEL_LARGE_EXEC, + .page_flag = __PAGE_KERNEL_LARGE_EXEC, }; /* Locates and clears a region for a new top level page table. */ diff --git a/arch/x86/include/asm/init.h b/arch/x86/include/asm/init.h index 737da62bfeb0..474eb8c66fee 100644 --- a/arch/x86/include/asm/init.h +++ b/arch/x86/include/asm/init.h @@ -4,8 +4,9 @@ struct x86_mapping_info { void *(*alloc_pgt_page)(void *); /* allocate buf for page table */ void *context; /* context for alloc_pgt_page */ - unsigned long pmd_flag; /* page flag for PMD entry */ + unsigned long page_flag; /* page flag for PMD or PUD entry */ unsigned long offset; /* ident mapping offset */ + bool direct_gbpages; /* PUD level 1GB page support */ }; int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page, diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c index 085c3b300d32..1d4f2b076545 100644 --- a/arch/x86/kernel/machine_kexec_64.c +++ b/arch/x86/kernel/machine_kexec_64.c @@ -113,7 +113,7 @@ static int init_pgtable(struct kimage *image, unsigned long start_pgtable) struct x86_mapping_info info = { .alloc_pgt_page = alloc_pgt_page, .context = image, - .pmd_flag = __PAGE_KERNEL_LARGE_EXEC, + .page_flag = __PAGE_KERNEL_LARGE_EXEC, }; unsigned long mstart, mend; pgd_t *level4p; diff --git a/arch/x86/mm/ident_map.c b/arch/x86/mm/ident_map.c index 04210a29dd60..adab1595f4bd 100644 --- a/arch/x86/mm/ident_map.c +++ b/arch/x86/mm/ident_map.c @@ -13,7 +13,7 @@ static void ident_pmd_init(struct x86_mapping_info *info, pmd_t *pmd_page, if (pmd_present(*pmd)) continue; - set_pmd(pmd, __pmd((addr - info->offset) | info->pmd_flag)); + set_pmd(pmd, __pmd((addr - info->offset) | info->page_flag)); } } @@ -30,6 +30,18 @@ static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page, if (next > end) next = end; + if (info->direct_gbpages) { + pud_t pudval; + + if (pud_present(*pud)) + continue; + + addr &= PUD_MASK; + pudval = __pud((addr - info->offset) | info->page_flag); + set_pud(pud, pudval); + continue; + } + if (pud_present(*pud)) { pmd = pmd_offset(pud, 0); ident_pmd_init(info, pmd, addr, next); diff --git a/arch/x86/power/hibernate_64.c b/arch/x86/power/hibernate_64.c index 6a61194ffd58..a6e21fee22ea 100644 --- a/arch/x86/power/hibernate_64.c +++ b/arch/x86/power/hibernate_64.c @@ -104,7 +104,7 @@ static int set_up_temporary_mappings(void) { struct x86_mapping_info info = { .alloc_pgt_page = alloc_pgt_page, - .pmd_flag = __PAGE_KERNEL_LARGE_EXEC, + .page_flag = __PAGE_KERNEL_LARGE_EXEC, .offset = __PAGE_OFFSET, }; unsigned long mstart, mend; -- cgit v1.2.3-59-g8ed1b From 8638100c52bb7782462b14aad102a4aaf0c7094c Mon Sep 17 00:00:00 2001 From: Xunlei Pang Date: Thu, 4 May 2017 09:42:51 +0800 Subject: x86/kexec/64: Use gbpages for identity mappings if available Kexec sets up all identity mappings before booting into the new kernel, and this will cause extra memory consumption for paging structures which is quite considerable on modern machines with huge memory sizes. E.g. on a 32TB machine that is kdumping, it could waste around 128MB (around 4MB/TB) from the reserved memory after kexec sets all the identity mappings using the current 2MB page. Add to that the memory needed for the loaded kdump kernel, initramfs, etc., and it causes a kexec syscall -NOMEM failure. As a result, we had to enlarge reserved memory via "crashkernel=X" to work around this problem. This causes some trouble for distributions that use policies to evaluate the proper "crashkernel=X" value for users. So enable gbpages for kexec mappings. Signed-off-by: Xunlei Pang Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Dave Young Cc: Denys Vlasenko Cc: Eric Biederman Cc: H. Peter Anvin Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Yinghai Lu Cc: akpm@linux-foundation.org Cc: kexec@lists.infradead.org Link: http://lkml.kernel.org/r/1493862171-8799-2-git-send-email-xlpang@redhat.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/machine_kexec_64.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c index 1d4f2b076545..c25d277d7d7e 100644 --- a/arch/x86/kernel/machine_kexec_64.c +++ b/arch/x86/kernel/machine_kexec_64.c @@ -122,6 +122,10 @@ static int init_pgtable(struct kimage *image, unsigned long start_pgtable) level4p = (pgd_t *)__va(start_pgtable); clear_page(level4p); + + if (direct_gbpages) + info.direct_gbpages = true; + for (i = 0; i < nr_pfn_mapped; i++) { mstart = pfn_mapped[i].start << PAGE_SHIFT; mend = pfn_mapped[i].end << PAGE_SHIFT; -- cgit v1.2.3-59-g8ed1b From 6852aa0263cdc4d43ab8e23735e6e0973cadeb63 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Sun, 2 Apr 2017 20:08:29 -0700 Subject: nios2: add .gitignore entries for auto-generated files Add .gitignore entries for nios2 specific files generated during the build process. Signed-off-by: Tobias Klauser Acked-by: Ley Foon Tan --- arch/nios2/boot/.gitignore | 2 ++ arch/nios2/kernel/.gitignore | 1 + 2 files changed, 3 insertions(+) create mode 100644 arch/nios2/boot/.gitignore create mode 100644 arch/nios2/kernel/.gitignore (limited to 'arch') diff --git a/arch/nios2/boot/.gitignore b/arch/nios2/boot/.gitignore new file mode 100644 index 000000000000..109279ca5a4d --- /dev/null +++ b/arch/nios2/boot/.gitignore @@ -0,0 +1,2 @@ +*.dtb +vmImage diff --git a/arch/nios2/kernel/.gitignore b/arch/nios2/kernel/.gitignore new file mode 100644 index 000000000000..c5f676c3c224 --- /dev/null +++ b/arch/nios2/kernel/.gitignore @@ -0,0 +1 @@ +vmlinux.lds -- cgit v1.2.3-59-g8ed1b From f679b311f0683be352cb73b28d7108eed79ef795 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Sun, 2 Apr 2017 20:08:40 -0700 Subject: nios2: remove wrapper header for cmpxchg.h Since commit 713e9b802e21 ("nios2: Switch to generic __xchg()") asm/cmpxchg.h for nios2 is merely including asm-generic/cmpxchg.h. Thus, the wrapper can be omitted and the generic header can be used directly. Signed-off-by: Tobias Klauser Acked-by: Ley Foon Tan --- arch/nios2/include/asm/Kbuild | 1 + arch/nios2/include/asm/cmpxchg.h | 14 -------------- 2 files changed, 1 insertion(+), 14 deletions(-) delete mode 100644 arch/nios2/include/asm/cmpxchg.h (limited to 'arch') diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild index 87e70f2b463f..727dbb333f60 100644 --- a/arch/nios2/include/asm/Kbuild +++ b/arch/nios2/include/asm/Kbuild @@ -6,6 +6,7 @@ generic-y += bitsperlong.h generic-y += bug.h generic-y += bugs.h generic-y += clkdev.h +generic-y += cmpxchg.h generic-y += current.h generic-y += device.h generic-y += div64.h diff --git a/arch/nios2/include/asm/cmpxchg.h b/arch/nios2/include/asm/cmpxchg.h deleted file mode 100644 index a7978f14d157..000000000000 --- a/arch/nios2/include/asm/cmpxchg.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (C) 2004 Microtronix Datacom Ltd. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_NIOS2_CMPXCHG_H -#define _ASM_NIOS2_CMPXCHG_H - -#include - -#endif /* _ASM_NIOS2_CMPXCHG_H */ -- cgit v1.2.3-59-g8ed1b From 57ac76ed6c0daf02c520e09e0af421f02ee2de8b Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Sun, 2 Apr 2017 20:08:52 -0700 Subject: nios2: constify irq_domain_ops struct irq_domain_ops is not modified, so it can be made const. Signed-off-by: Tobias Klauser Acked-by: Ley Foon Tan --- arch/nios2/kernel/irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/nios2/kernel/irq.c b/arch/nios2/kernel/irq.c index f5b74ae69b5b..6c833a9d4eab 100644 --- a/arch/nios2/kernel/irq.c +++ b/arch/nios2/kernel/irq.c @@ -67,7 +67,7 @@ static int irq_map(struct irq_domain *h, unsigned int virq, return 0; } -static struct irq_domain_ops irq_ops = { +static const struct irq_domain_ops irq_ops = { .map = irq_map, .xlate = irq_domain_xlate_onecell, }; -- cgit v1.2.3-59-g8ed1b From 44a4ed42576da5f3387005a1667cb3e7aedfd687 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Sun, 2 Apr 2017 20:09:04 -0700 Subject: nios2: enable earlycon support Enable generic earlycon support for nios2. This e.g. allows to use a 8250/16650 UART as earlycon. In order to get the earlycon, we just need to call parse_early_param() in early_init_devtree() as soon as the device tree is initially scanned. By adding an stdout-path property to the dts (done in this patch for 10m50_devboard), the earlycon can be used. In order to provide early printk support, we need to provide a dummy implementation of early_console_write(), so that arch/nios2/kernel/early_printk.c can still be compiled if neither SERIAL_ALTERA_JTAGUART_CONSOLE nor SERIAL_ALTERA_UART_CONSOLE is selected. As soon as the altera_uart and altera_jtaguart support earlycon, the entire file can be removed. Tested-by: Guenter Roeck Signed-off-by: Tobias Klauser Acked-by: Ley Foon Tan --- arch/nios2/Kconfig.debug | 1 - arch/nios2/boot/dts/10m50_devboard.dts | 3 ++- arch/nios2/kernel/early_printk.c | 7 +++++-- arch/nios2/kernel/setup.c | 2 ++ 4 files changed, 9 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/nios2/Kconfig.debug b/arch/nios2/Kconfig.debug index 2fd08cbfdddb..55105220370c 100644 --- a/arch/nios2/Kconfig.debug +++ b/arch/nios2/Kconfig.debug @@ -18,7 +18,6 @@ config EARLY_PRINTK bool "Activate early kernel debugging" default y select SERIAL_CORE_CONSOLE - depends on SERIAL_ALTERA_JTAGUART_CONSOLE || SERIAL_ALTERA_UART_CONSOLE help Enable early printk on console This is useful for kernel debugging when your machine crashes very diff --git a/arch/nios2/boot/dts/10m50_devboard.dts b/arch/nios2/boot/dts/10m50_devboard.dts index f362b2224ee7..4bb4dc1b52e9 100644 --- a/arch/nios2/boot/dts/10m50_devboard.dts +++ b/arch/nios2/boot/dts/10m50_devboard.dts @@ -244,6 +244,7 @@ }; chosen { - bootargs = "debug console=ttyS0,115200"; + bootargs = "debug earlycon console=ttyS0,115200"; + stdout-path = &a_16550_uart_0; }; }; diff --git a/arch/nios2/kernel/early_printk.c b/arch/nios2/kernel/early_printk.c index c08e4c1486fc..4a7bb98f744c 100644 --- a/arch/nios2/kernel/early_printk.c +++ b/arch/nios2/kernel/early_printk.c @@ -81,8 +81,11 @@ static void early_console_write(struct console *con, const char *s, unsigned n) } #else -# error Neither SERIAL_ALTERA_JTAGUART_CONSOLE nor SERIAL_ALTERA_UART_CONSOLE \ -selected + +static void early_console_write(struct console *con, const char *s, unsigned n) +{ +} + #endif static struct console early_console_prom = { diff --git a/arch/nios2/kernel/setup.c b/arch/nios2/kernel/setup.c index 6044d9be28b4..8b5146082e3e 100644 --- a/arch/nios2/kernel/setup.c +++ b/arch/nios2/kernel/setup.c @@ -137,6 +137,8 @@ asmlinkage void __init nios2_boot_init(unsigned r4, unsigned r5, unsigned r6, strncpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); #endif #endif + + parse_early_param(); } void __init setup_arch(char **cmdline_p) -- cgit v1.2.3-59-g8ed1b From 4b40c1c092a932b5b5ab8154235080f02ae19a34 Mon Sep 17 00:00:00 2001 From: Julien Beraud Date: Wed, 5 Apr 2017 15:03:44 +0800 Subject: nios2: implement flush_dcache_mmap_lock/unlock Use spin_lock/unlock_irq instead of doing nothing. This fixes corruptions of the vma_interval_tree causing the kernel to be stuck in an infinite loop in vma_interval_tree_foreach. Signed-off-by: Julien Beraud Acked-by: Ley Foon Tan --- arch/nios2/include/asm/cacheflush.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/nios2/include/asm/cacheflush.h b/arch/nios2/include/asm/cacheflush.h index 52abba973dc2..55e383c173f7 100644 --- a/arch/nios2/include/asm/cacheflush.h +++ b/arch/nios2/include/asm/cacheflush.h @@ -46,7 +46,9 @@ extern void copy_from_user_page(struct vm_area_struct *vma, struct page *page, extern void flush_dcache_range(unsigned long start, unsigned long end); extern void invalidate_dcache_range(unsigned long start, unsigned long end); -#define flush_dcache_mmap_lock(mapping) do { } while (0) -#define flush_dcache_mmap_unlock(mapping) do { } while (0) +#define flush_dcache_mmap_lock(mapping) \ + spin_lock_irq(&(mapping)->tree_lock) +#define flush_dcache_mmap_unlock(mapping) \ + spin_unlock_irq(&(mapping)->tree_lock) #endif /* _ASM_NIOS2_CACHEFLUSH_H */ -- cgit v1.2.3-59-g8ed1b From a89988a6e00c5a099ee23619cd91dc8dc7ec9328 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 19 Apr 2017 13:19:00 +0200 Subject: nios2: Add NIOS2_ARCH_REVISION to select between R1 and R2 Allow user to select between Nios2 R1 and R2. Since R1 and R2 are not binary compatible, we cannot have a single kernel binary and there is no point in having DT property for discerning these two. Signed-off-by: Marek Vasut Cc: Ley Foon Tan --- arch/nios2/Makefile | 3 +++ arch/nios2/kernel/cpuinfo.c | 2 ++ arch/nios2/platform/Kconfig.platform | 8 ++++++++ 3 files changed, 13 insertions(+) (limited to 'arch') diff --git a/arch/nios2/Makefile b/arch/nios2/Makefile index e74afc12d516..38da17e4c908 100644 --- a/arch/nios2/Makefile +++ b/arch/nios2/Makefile @@ -22,7 +22,10 @@ export MMU LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) $(KCFLAGS) -print-libgcc-file-name) +KBUILD_AFLAGS += -march=r$(CONFIG_NIOS2_ARCH_REVISION) + KBUILD_CFLAGS += -pipe -D__linux__ -D__ELF__ +KBUILD_CFLAGS += -march=r$(CONFIG_NIOS2_ARCH_REVISION) KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_HW_MUL_SUPPORT),-mhw-mul,-mno-hw-mul) KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_HW_MULX_SUPPORT),-mhw-mulx,-mno-hw-mulx) KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_HW_DIV_SUPPORT),-mhw-div,-mno-hw-div) diff --git a/arch/nios2/kernel/cpuinfo.c b/arch/nios2/kernel/cpuinfo.c index 1cccc36877bc..b4a6242b0f1c 100644 --- a/arch/nios2/kernel/cpuinfo.c +++ b/arch/nios2/kernel/cpuinfo.c @@ -125,12 +125,14 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "CPU:\t\tNios II/%s\n" + "REV:\t\t%i\n" "MMU:\t\t%s\n" "FPU:\t\tnone\n" "Clocking:\t%u.%02u MHz\n" "BogoMips:\t%lu.%02lu\n" "Calibration:\t%lu loops\n", cpuinfo.cpu_impl, + CONFIG_NIOS2_ARCH_REVISION, cpuinfo.mmu ? "present" : "none", clockfreq / 1000000, (clockfreq / 100000) % 10, (loops_per_jiffy * HZ) / 500000, diff --git a/arch/nios2/platform/Kconfig.platform b/arch/nios2/platform/Kconfig.platform index d3e5df9fb36b..b7ac5b90c399 100644 --- a/arch/nios2/platform/Kconfig.platform +++ b/arch/nios2/platform/Kconfig.platform @@ -52,6 +52,14 @@ config NIOS2_DTB_SOURCE comment "Nios II instructions" +config NIOS2_ARCH_REVISION + int "Select Nios II architecture revision" + range 1 2 + default 1 + help + Select between Nios II R1 and Nios II R2 . The architectures + are binary incompatible. Default is R1 . + config NIOS2_HW_MUL_SUPPORT bool "Enable MUL instruction" default n -- cgit v1.2.3-59-g8ed1b From 23460839b983d5d8d47fe90f341599f66523dd81 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 19 Apr 2017 13:19:01 +0200 Subject: nios2: Add BMX support Add support for the BMX Bit Manipulation Extensions present in Nios II R2 . This introduces three new instructions, EXTRACT, INSERT and MERGE. Signed-off-by: Marek Vasut Cc: Ley Foon Tan --- arch/nios2/Makefile | 1 + arch/nios2/include/asm/cpuinfo.h | 1 + arch/nios2/kernel/cpuinfo.c | 10 ++++++++-- arch/nios2/platform/Kconfig.platform | 9 +++++++++ 4 files changed, 19 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/nios2/Makefile b/arch/nios2/Makefile index 38da17e4c908..74109c01eaea 100644 --- a/arch/nios2/Makefile +++ b/arch/nios2/Makefile @@ -29,6 +29,7 @@ KBUILD_CFLAGS += -march=r$(CONFIG_NIOS2_ARCH_REVISION) KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_HW_MUL_SUPPORT),-mhw-mul,-mno-hw-mul) KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_HW_MULX_SUPPORT),-mhw-mulx,-mno-hw-mulx) KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_HW_DIV_SUPPORT),-mhw-div,-mno-hw-div) +KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_BMX_SUPPORT),-mbmx,-mno-bmx) KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_FPU_SUPPORT),-mcustom-fpu-cfg=60-1,) KBUILD_CFLAGS += -fno-optimize-sibling-calls diff --git a/arch/nios2/include/asm/cpuinfo.h b/arch/nios2/include/asm/cpuinfo.h index 348bb228fec9..79d376435d7d 100644 --- a/arch/nios2/include/asm/cpuinfo.h +++ b/arch/nios2/include/asm/cpuinfo.h @@ -29,6 +29,7 @@ struct cpuinfo { bool has_div; bool has_mul; bool has_mulx; + bool has_bmx; /* CPU caches */ u32 icache_line_size; diff --git a/arch/nios2/kernel/cpuinfo.c b/arch/nios2/kernel/cpuinfo.c index b4a6242b0f1c..4c84fec34882 100644 --- a/arch/nios2/kernel/cpuinfo.c +++ b/arch/nios2/kernel/cpuinfo.c @@ -67,6 +67,7 @@ void __init setup_cpuinfo(void) cpuinfo.has_div = of_property_read_bool(cpu, "altr,has-div"); cpuinfo.has_mul = of_property_read_bool(cpu, "altr,has-mul"); cpuinfo.has_mulx = of_property_read_bool(cpu, "altr,has-mulx"); + cpuinfo.has_bmx = of_property_read_bool(cpu, "altr,has-bmx"); cpuinfo.mmu = of_property_read_bool(cpu, "altr,has-mmu"); if (IS_ENABLED(CONFIG_NIOS2_HW_DIV_SUPPORT) && !cpuinfo.has_div) @@ -78,6 +79,9 @@ void __init setup_cpuinfo(void) if (IS_ENABLED(CONFIG_NIOS2_HW_MULX_SUPPORT) && !cpuinfo.has_mulx) err_cpu("MULX"); + if (IS_ENABLED(CONFIG_NIOS2_BMX_SUPPORT) && !cpuinfo.has_bmx) + err_cpu("BMX"); + cpuinfo.tlb_num_ways = fcpu(cpu, "altr,tlb-num-ways"); if (!cpuinfo.tlb_num_ways) panic("altr,tlb-num-ways can't be 0. Please check your hardware " @@ -143,10 +147,12 @@ static int show_cpuinfo(struct seq_file *m, void *v) "HW:\n" " MUL:\t\t%s\n" " MULX:\t\t%s\n" - " DIV:\t\t%s\n", + " DIV:\t\t%s\n" + " BMX:\t\t%s\n", cpuinfo.has_mul ? "yes" : "no", cpuinfo.has_mulx ? "yes" : "no", - cpuinfo.has_div ? "yes" : "no"); + cpuinfo.has_div ? "yes" : "no", + cpuinfo.has_bmx ? "yes" : "no"); seq_printf(m, "Icache:\t\t%ukB, line length: %u\n", diff --git a/arch/nios2/platform/Kconfig.platform b/arch/nios2/platform/Kconfig.platform index b7ac5b90c399..b6a8bfd59491 100644 --- a/arch/nios2/platform/Kconfig.platform +++ b/arch/nios2/platform/Kconfig.platform @@ -81,6 +81,15 @@ config NIOS2_HW_DIV_SUPPORT Set to true if you configured the Nios II to include the DIV instruction. Enables the -mhw-div compiler flag. +config NIOS2_BMX_SUPPORT + bool "Enable BMX instructions" + depends on NIOS2_ARCH_REVISION = 2 + default n + help + Set to true if you configured the Nios II R2 to include + the BMX Bit Manipulation Extension instructions. Enables + the -mbmx compiler flag. + config NIOS2_FPU_SUPPORT bool "Custom floating point instr support" default n -- cgit v1.2.3-59-g8ed1b From edebea98777d7090ea14bdce2e38e6798557729d Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 19 Apr 2017 13:19:02 +0200 Subject: nios2: Add CDX support Add support for the CDX Code Density Extensions present in Nios II R2 . This introduces new 16bit instruction set to improve code density while retaining support for the 32bit Nios II R2 instructions. Signed-off-by: Marek Vasut Cc: Ley Foon Tan --- arch/nios2/Makefile | 1 + arch/nios2/include/asm/cpuinfo.h | 1 + arch/nios2/kernel/cpuinfo.c | 10 ++++++++-- arch/nios2/platform/Kconfig.platform | 9 +++++++++ 4 files changed, 19 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/nios2/Makefile b/arch/nios2/Makefile index 74109c01eaea..8673a79dca9c 100644 --- a/arch/nios2/Makefile +++ b/arch/nios2/Makefile @@ -30,6 +30,7 @@ KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_HW_MUL_SUPPORT),-mhw-mul,-mno-hw-mul) KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_HW_MULX_SUPPORT),-mhw-mulx,-mno-hw-mulx) KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_HW_DIV_SUPPORT),-mhw-div,-mno-hw-div) KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_BMX_SUPPORT),-mbmx,-mno-bmx) +KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_CDX_SUPPORT),-mcdx,-mno-cdx) KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_FPU_SUPPORT),-mcustom-fpu-cfg=60-1,) KBUILD_CFLAGS += -fno-optimize-sibling-calls diff --git a/arch/nios2/include/asm/cpuinfo.h b/arch/nios2/include/asm/cpuinfo.h index 79d376435d7d..dbdaf96f28d4 100644 --- a/arch/nios2/include/asm/cpuinfo.h +++ b/arch/nios2/include/asm/cpuinfo.h @@ -30,6 +30,7 @@ struct cpuinfo { bool has_mul; bool has_mulx; bool has_bmx; + bool has_cdx; /* CPU caches */ u32 icache_line_size; diff --git a/arch/nios2/kernel/cpuinfo.c b/arch/nios2/kernel/cpuinfo.c index 4c84fec34882..93207718bb22 100644 --- a/arch/nios2/kernel/cpuinfo.c +++ b/arch/nios2/kernel/cpuinfo.c @@ -68,6 +68,7 @@ void __init setup_cpuinfo(void) cpuinfo.has_mul = of_property_read_bool(cpu, "altr,has-mul"); cpuinfo.has_mulx = of_property_read_bool(cpu, "altr,has-mulx"); cpuinfo.has_bmx = of_property_read_bool(cpu, "altr,has-bmx"); + cpuinfo.has_cdx = of_property_read_bool(cpu, "altr,has-cdx"); cpuinfo.mmu = of_property_read_bool(cpu, "altr,has-mmu"); if (IS_ENABLED(CONFIG_NIOS2_HW_DIV_SUPPORT) && !cpuinfo.has_div) @@ -82,6 +83,9 @@ void __init setup_cpuinfo(void) if (IS_ENABLED(CONFIG_NIOS2_BMX_SUPPORT) && !cpuinfo.has_bmx) err_cpu("BMX"); + if (IS_ENABLED(CONFIG_NIOS2_CDX_SUPPORT) && !cpuinfo.has_cdx) + err_cpu("CDX"); + cpuinfo.tlb_num_ways = fcpu(cpu, "altr,tlb-num-ways"); if (!cpuinfo.tlb_num_ways) panic("altr,tlb-num-ways can't be 0. Please check your hardware " @@ -148,11 +152,13 @@ static int show_cpuinfo(struct seq_file *m, void *v) " MUL:\t\t%s\n" " MULX:\t\t%s\n" " DIV:\t\t%s\n" - " BMX:\t\t%s\n", + " BMX:\t\t%s\n" + " CDX:\t\t%s\n", cpuinfo.has_mul ? "yes" : "no", cpuinfo.has_mulx ? "yes" : "no", cpuinfo.has_div ? "yes" : "no", - cpuinfo.has_bmx ? "yes" : "no"); + cpuinfo.has_bmx ? "yes" : "no", + cpuinfo.has_cdx ? "yes" : "no"); seq_printf(m, "Icache:\t\t%ukB, line length: %u\n", diff --git a/arch/nios2/platform/Kconfig.platform b/arch/nios2/platform/Kconfig.platform index b6a8bfd59491..74c1aaf588b8 100644 --- a/arch/nios2/platform/Kconfig.platform +++ b/arch/nios2/platform/Kconfig.platform @@ -90,6 +90,15 @@ config NIOS2_BMX_SUPPORT the BMX Bit Manipulation Extension instructions. Enables the -mbmx compiler flag. +config NIOS2_CDX_SUPPORT + bool "Enable CDX instructions" + depends on NIOS2_ARCH_REVISION = 2 + default n + help + Set to true if you configured the Nios II R2 to include + the CDX Bit Manipulation Extension instructions. Enables + the -mcdx compiler flag. + config NIOS2_FPU_SUPPORT bool "Custom floating point instr support" default n -- cgit v1.2.3-59-g8ed1b From 7f1e614113ffe75f5ea7c99f641bf1b56f85be03 Mon Sep 17 00:00:00 2001 From: Ley Foon Tan Date: Mon, 8 May 2017 17:14:14 +0800 Subject: nios2: use generic strncpy_from_user() and strnlen_user() This change enables the generic strncpy_from_user() and strnlen_user() Signed-off-by: Ley Foon Tan --- arch/nios2/Kconfig | 2 ++ arch/nios2/include/asm/uaccess.h | 7 +++++-- arch/nios2/mm/uaccess.c | 33 --------------------------------- 3 files changed, 7 insertions(+), 35 deletions(-) (limited to 'arch') diff --git a/arch/nios2/Kconfig b/arch/nios2/Kconfig index 51a56c8b04b4..a72d5f0de692 100644 --- a/arch/nios2/Kconfig +++ b/arch/nios2/Kconfig @@ -6,6 +6,8 @@ config NIOS2 select GENERIC_CPU_DEVICES select GENERIC_IRQ_PROBE select GENERIC_IRQ_SHOW + select GENERIC_STRNCPY_FROM_USER + select GENERIC_STRNLEN_USER select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_KGDB select IRQ_DOMAIN diff --git a/arch/nios2/include/asm/uaccess.h b/arch/nios2/include/asm/uaccess.h index 727bd9504899..dfa3c7cb30b4 100644 --- a/arch/nios2/include/asm/uaccess.h +++ b/arch/nios2/include/asm/uaccess.h @@ -42,6 +42,8 @@ # define __EX_TABLE_SECTION ".section __ex_table,\"a\"\n" +#define user_addr_max() (uaccess_kernel() ? ~0UL : TASK_SIZE) + /* * Zero Userspace */ @@ -81,8 +83,9 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n); #define INLINE_COPY_TO_USER extern long strncpy_from_user(char *__to, const char __user *__from, - long __len); -extern long strnlen_user(const char __user *s, long n); + long __len); +extern __must_check long strlen_user(const char __user *str); +extern __must_check long strnlen_user(const char __user *s, long n); /* Optimized macros */ #define __get_user_asm(val, insn, addr, err) \ diff --git a/arch/nios2/mm/uaccess.c b/arch/nios2/mm/uaccess.c index 804983317766..34f10af8ea40 100644 --- a/arch/nios2/mm/uaccess.c +++ b/arch/nios2/mm/uaccess.c @@ -128,36 +128,3 @@ asm( ".word 12b,13b\n" ".previous\n"); EXPORT_SYMBOL(raw_copy_to_user); - -long strncpy_from_user(char *__to, const char __user *__from, long __len) -{ - int l = strnlen_user(__from, __len); - int is_zt = 1; - - if (l > __len) { - is_zt = 0; - l = __len; - } - - if (l == 0 || copy_from_user(__to, __from, l)) - return -EFAULT; - - if (is_zt) - l--; - return l; -} - -long strnlen_user(const char __user *s, long n) -{ - long i; - - for (i = 0; i < n; i++) { - char c; - - if (get_user(c, s + i) == -EFAULT) - return 0; - if (c == 0) - return i + 1; - } - return n + 1; -} -- cgit v1.2.3-59-g8ed1b From 876ae234cb5e908c12c60562295cd633eac687bb Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Tue, 20 Dec 2016 01:36:35 -0500 Subject: KVM: arm64: vgic-its: KVM_DEV_ARM_VGIC_GRP_ITS_REGS group The ITS KVM device exposes a new KVM_DEV_ARM_VGIC_GRP_ITS_REGS group which allows the userspace to save/restore ITS registers. At this stage the get/set/has operations are not yet implemented. Signed-off-by: Eric Auger Reviewed-by: Andre Przywara Reviewed-by: Christoffer Dall Acked-by: Marc Zyngier --- arch/arm/include/uapi/asm/kvm.h | 1 + arch/arm64/include/uapi/asm/kvm.h | 1 + virt/kvm/arm/vgic/vgic-its.c | 36 +++++++++++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h index a5838d605e7b..ee183fcd1c82 100644 --- a/arch/arm/include/uapi/asm/kvm.h +++ b/arch/arm/include/uapi/asm/kvm.h @@ -194,6 +194,7 @@ struct kvm_arch_memory_slot { #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5 #define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6 #define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7 +#define KVM_DEV_ARM_VGIC_GRP_ITS_REGS 8 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \ (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT) diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index cd6bea495e63..ee4a0ad44359 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -214,6 +214,7 @@ struct kvm_arch_memory_slot { #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5 #define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6 #define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7 +#define KVM_DEV_ARM_VGIC_GRP_ITS_REGS 8 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \ (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT) diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c index 3ffcbbe97523..f687e91741f0 100644 --- a/virt/kvm/arm/vgic/vgic-its.c +++ b/virt/kvm/arm/vgic/vgic-its.c @@ -1466,6 +1466,19 @@ static void vgic_its_destroy(struct kvm_device *kvm_dev) kfree(its); } +int vgic_its_has_attr_regs(struct kvm_device *dev, + struct kvm_device_attr *attr) +{ + return -ENXIO; +} + +int vgic_its_attr_regs_access(struct kvm_device *dev, + struct kvm_device_attr *attr, + u64 *reg, bool is_write) +{ + return -ENXIO; +} + static int vgic_its_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr) { @@ -1482,6 +1495,8 @@ static int vgic_its_has_attr(struct kvm_device *dev, return 0; } break; + case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: + return vgic_its_has_attr_regs(dev, attr); } return -ENXIO; } @@ -1521,6 +1536,15 @@ static int vgic_its_set_attr(struct kvm_device *dev, return 0; } break; + case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: { + u64 __user *uaddr = (u64 __user *)(long)attr->addr; + u64 reg; + + if (get_user(reg, uaddr)) + return -EFAULT; + + return vgic_its_attr_regs_access(dev, attr, ®, true); + } } return -ENXIO; } @@ -1541,10 +1565,20 @@ static int vgic_its_get_attr(struct kvm_device *dev, if (copy_to_user(uaddr, &addr, sizeof(addr))) return -EFAULT; break; + } + case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: { + u64 __user *uaddr = (u64 __user *)(long)attr->addr; + u64 reg; + int ret; + + ret = vgic_its_attr_regs_access(dev, attr, ®, false); + if (ret) + return ret; + return put_user(reg, uaddr); + } default: return -ENXIO; } - } return 0; } -- cgit v1.2.3-59-g8ed1b From 3b65808f4b2914db175a048097956d59ec609e04 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Sat, 24 Dec 2016 18:48:04 +0100 Subject: KVM: arm64: vgic-its: KVM_DEV_ARM_ITS_SAVE/RESTORE_TABLES Introduce new attributes in KVM_DEV_ARM_VGIC_GRP_CTRL group: - KVM_DEV_ARM_ITS_SAVE_TABLES: saves the ITS tables into guest RAM - KVM_DEV_ARM_ITS_RESTORE_TABLES: restores them into VGIC internal structures. We hold the vcpus lock during the save and restore to make sure no vcpu is running. At this stage the functionality is not yet implemented. Only the skeleton is put in place. Signed-off-by: Eric Auger [Given we will move the iodev register until setting the base addr] Reviewed-by: Christoffer Dall --- arch/arm/include/uapi/asm/kvm.h | 4 +- arch/arm64/include/uapi/asm/kvm.h | 4 +- virt/kvm/arm/vgic/vgic-its.c | 107 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 109 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h index ee183fcd1c82..0f7ee15f9fcf 100644 --- a/arch/arm/include/uapi/asm/kvm.h +++ b/arch/arm/include/uapi/asm/kvm.h @@ -201,7 +201,9 @@ struct kvm_arch_memory_slot { #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff #define VGIC_LEVEL_INFO_LINE_LEVEL 0 -#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 +#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 +#define KVM_DEV_ARM_ITS_SAVE_TABLES 1 +#define KVM_DEV_ARM_ITS_RESTORE_TABLES 2 /* KVM_IRQ_LINE irq field index values */ #define KVM_ARM_IRQ_TYPE_SHIFT 24 diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index ee4a0ad44359..5dd7be049934 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -221,7 +221,9 @@ struct kvm_arch_memory_slot { #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff #define VGIC_LEVEL_INFO_LINE_LEVEL 0 -#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 +#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 +#define KVM_DEV_ARM_ITS_SAVE_TABLES 1 +#define KVM_DEV_ARM_ITS_RESTORE_TABLES 2 /* Device Control API on vcpu fd */ #define KVM_ARM_VCPU_PMU_V3_CTRL 0 diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c index ffd0a801aeb5..cb7ae4c53ad9 100644 --- a/virt/kvm/arm/vgic/vgic-its.c +++ b/virt/kvm/arm/vgic/vgic-its.c @@ -1702,13 +1702,72 @@ out: return ret; } +/** + * vgic_its_save_device_tables - Save the device table and all ITT + * into guest RAM + */ +static int vgic_its_save_device_tables(struct vgic_its *its) +{ + return -ENXIO; +} + +/** + * vgic_its_restore_device_tables - Restore the device table and all ITT + * from guest RAM to internal data structs + */ +static int vgic_its_restore_device_tables(struct vgic_its *its) +{ + return -ENXIO; +} + +/** + * vgic_its_save_collection_table - Save the collection table into + * guest RAM + */ +static int vgic_its_save_collection_table(struct vgic_its *its) +{ + return -ENXIO; +} + +/** + * vgic_its_restore_collection_table - reads the collection table + * in guest memory and restores the ITS internal state. Requires the + * BASER registers to be restored before. + */ +static int vgic_its_restore_collection_table(struct vgic_its *its) +{ + return -ENXIO; +} + /** * vgic_its_save_tables_v0 - Save the ITS tables into guest ARM * according to v0 ABI */ static int vgic_its_save_tables_v0(struct vgic_its *its) { - return -ENXIO; + struct kvm *kvm = its->dev->kvm; + int ret; + + mutex_lock(&kvm->lock); + mutex_lock(&its->its_lock); + + if (!lock_all_vcpus(kvm)) { + mutex_unlock(&its->its_lock); + mutex_unlock(&kvm->lock); + return -EBUSY; + } + + ret = vgic_its_save_device_tables(its); + if (ret) + goto out; + + ret = vgic_its_save_collection_table(its); + +out: + unlock_all_vcpus(kvm); + mutex_unlock(&its->its_lock); + mutex_unlock(&kvm->lock); + return ret; } /** @@ -1718,7 +1777,37 @@ static int vgic_its_save_tables_v0(struct vgic_its *its) */ static int vgic_its_restore_tables_v0(struct vgic_its *its) { - return -ENXIO; + struct kvm *kvm = its->dev->kvm; + int ret; + + mutex_lock(&kvm->lock); + mutex_lock(&its->its_lock); + + if (!lock_all_vcpus(kvm)) { + mutex_unlock(&its->its_lock); + mutex_unlock(&kvm->lock); + return -EBUSY; + } + + ret = vgic_its_restore_collection_table(its); + if (ret) + goto out; + + ret = vgic_its_restore_device_tables(its); + +out: + unlock_all_vcpus(kvm); + mutex_unlock(&its->its_lock); + mutex_unlock(&kvm->lock); + + if (ret) + return ret; + + /* + * On restore path, MSI injections can happen before the + * first VCPU run so let's complete the GIC init here. + */ + return kvm_vgic_map_resources(its->dev->kvm); } static int vgic_its_commit_v0(struct vgic_its *its) @@ -1751,6 +1840,10 @@ static int vgic_its_has_attr(struct kvm_device *dev, switch (attr->attr) { case KVM_DEV_ARM_VGIC_CTRL_INIT: return 0; + case KVM_DEV_ARM_ITS_SAVE_TABLES: + return 0; + case KVM_DEV_ARM_ITS_RESTORE_TABLES: + return 0; } break; case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: @@ -1786,14 +1879,20 @@ static int vgic_its_set_attr(struct kvm_device *dev, return 0; } - case KVM_DEV_ARM_VGIC_GRP_CTRL: + case KVM_DEV_ARM_VGIC_GRP_CTRL: { + const struct vgic_its_abi *abi = vgic_its_get_abi(its); + switch (attr->attr) { case KVM_DEV_ARM_VGIC_CTRL_INIT: its->initialized = true; return 0; + case KVM_DEV_ARM_ITS_SAVE_TABLES: + return abi->save_tables(its); + case KVM_DEV_ARM_ITS_RESTORE_TABLES: + return abi->restore_tables(its); } - break; + } case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: { u64 __user *uaddr = (u64 __user *)(long)attr->addr; u64 reg; -- cgit v1.2.3-59-g8ed1b From 280771252c1bae0947215c59fb9ea6a8d9f8399d Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Mon, 9 Jan 2017 16:28:27 +0100 Subject: KVM: arm64: vgic-v3: KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES This patch adds a new attribute to GICV3 KVM device KVM_DEV_ARM_VGIC_GRP_CTRL group. This allows userspace to flush all GICR pending tables into guest RAM. Signed-off-by: Eric Auger Reviewed-by: Christoffer Dall Acked-by: Marc Zyngier --- arch/arm/include/uapi/asm/kvm.h | 1 + arch/arm64/include/uapi/asm/kvm.h | 1 + virt/kvm/arm/vgic/vgic-kvm-device.c | 20 +++++++++++++++ virt/kvm/arm/vgic/vgic-v3.c | 51 +++++++++++++++++++++++++++++++++++++ virt/kvm/arm/vgic/vgic.h | 1 + 5 files changed, 74 insertions(+) (limited to 'arch') diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h index 0f7ee15f9fcf..a3fbab56d4a8 100644 --- a/arch/arm/include/uapi/asm/kvm.h +++ b/arch/arm/include/uapi/asm/kvm.h @@ -204,6 +204,7 @@ struct kvm_arch_memory_slot { #define KVM_DEV_ARM_VGIC_CTRL_INIT 0 #define KVM_DEV_ARM_ITS_SAVE_TABLES 1 #define KVM_DEV_ARM_ITS_RESTORE_TABLES 2 +#define KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES 3 /* KVM_IRQ_LINE irq field index values */ #define KVM_ARM_IRQ_TYPE_SHIFT 24 diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index 5dd7be049934..d46a99d999ec 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -224,6 +224,7 @@ struct kvm_arch_memory_slot { #define KVM_DEV_ARM_VGIC_CTRL_INIT 0 #define KVM_DEV_ARM_ITS_SAVE_TABLES 1 #define KVM_DEV_ARM_ITS_RESTORE_TABLES 2 +#define KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES 3 /* Device Control API on vcpu fd */ #define KVM_ARM_VCPU_PMU_V3_CTRL 0 diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c index 859bfa871b30..d48743cafedc 100644 --- a/virt/kvm/arm/vgic/vgic-kvm-device.c +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c @@ -580,6 +580,24 @@ static int vgic_v3_set_attr(struct kvm_device *dev, reg = tmp32; return vgic_v3_attr_regs_access(dev, attr, ®, true); } + case KVM_DEV_ARM_VGIC_GRP_CTRL: { + int ret; + + switch (attr->attr) { + case KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES: + mutex_lock(&dev->kvm->lock); + + if (!lock_all_vcpus(dev->kvm)) { + mutex_unlock(&dev->kvm->lock); + return -EBUSY; + } + ret = vgic_v3_save_pending_tables(dev->kvm); + unlock_all_vcpus(dev->kvm); + mutex_unlock(&dev->kvm->lock); + return ret; + } + break; + } } return -ENXIO; } @@ -658,6 +676,8 @@ static int vgic_v3_has_attr(struct kvm_device *dev, switch (attr->attr) { case KVM_DEV_ARM_VGIC_CTRL_INIT: return 0; + case KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES: + return 0; } } return -ENXIO; diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c index 9ae8adddff69..54dee725da18 100644 --- a/virt/kvm/arm/vgic/vgic-v3.c +++ b/virt/kvm/arm/vgic/vgic-v3.c @@ -278,6 +278,57 @@ retry: return 0; } +/** + * vgic_its_save_pending_tables - Save the pending tables into guest RAM + * kvm lock and all vcpu lock must be held + */ +int vgic_v3_save_pending_tables(struct kvm *kvm) +{ + struct vgic_dist *dist = &kvm->arch.vgic; + int last_byte_offset = -1; + struct vgic_irq *irq; + int ret; + + list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) { + int byte_offset, bit_nr; + struct kvm_vcpu *vcpu; + gpa_t pendbase, ptr; + bool stored; + u8 val; + + vcpu = irq->target_vcpu; + if (!vcpu) + continue; + + pendbase = GICR_PENDBASER_ADDRESS(vcpu->arch.vgic_cpu.pendbaser); + + byte_offset = irq->intid / BITS_PER_BYTE; + bit_nr = irq->intid % BITS_PER_BYTE; + ptr = pendbase + byte_offset; + + if (byte_offset != last_byte_offset) { + ret = kvm_read_guest(kvm, ptr, &val, 1); + if (ret) + return ret; + last_byte_offset = byte_offset; + } + + stored = val & (1U << bit_nr); + if (stored == irq->pending_latch) + continue; + + if (irq->pending_latch) + val |= 1 << bit_nr; + else + val &= ~(1 << bit_nr); + + ret = kvm_write_guest(kvm, ptr, &val, 1); + if (ret) + return ret; + } + return 0; +} + /* check for overlapping regions and for regions crossing the end of memory */ static bool vgic_v3_check_base(struct kvm *kvm) { diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h index 433449b25c78..8259f0a859ab 100644 --- a/virt/kvm/arm/vgic/vgic.h +++ b/virt/kvm/arm/vgic/vgic.h @@ -173,6 +173,7 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu); int vgic_v3_probe(const struct gic_kvm_info *info); int vgic_v3_map_resources(struct kvm *kvm); int vgic_v3_lpi_sync_pending_status(struct kvm *kvm, struct vgic_irq *irq); +int vgic_v3_save_pending_tables(struct kvm *kvm); int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address); void vgic_v3_load(struct kvm_vcpu *vcpu); -- cgit v1.2.3-59-g8ed1b From 861ce4a3244c21b0af64f880d5bfe5e6e2fb9e4a Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Mon, 8 May 2017 14:23:16 -0700 Subject: x86/mm/32: Set the '__vmalloc_start_set' flag in initmem_init() '__vmalloc_start_set' currently only gets set in initmem_init() when !CONFIG_NEED_MULTIPLE_NODES. This breaks detection of vmalloc address with virt_addr_valid() with CONFIG_NEED_MULTIPLE_NODES=y, causing a kernel crash: [mm/usercopy] 517e1fbeb6: kernel BUG at arch/x86/mm/physaddr.c:78! Set '__vmalloc_start_set' appropriately for that case as well. Reported-by: kbuild test robot Signed-off-by: Laura Abbott Reviewed-by: Kees Cook Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Fixes: dc16ecf7fd1f ("x86-32: use specific __vmalloc_start_set flag in __virt_addr_valid") Link: http://lkml.kernel.org/r/1494278596-30373-1-git-send-email-labbott@redhat.com Signed-off-by: Ingo Molnar --- arch/x86/mm/numa_32.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c index 6b7ce6279133..aca6295350f3 100644 --- a/arch/x86/mm/numa_32.c +++ b/arch/x86/mm/numa_32.c @@ -100,5 +100,6 @@ void __init initmem_init(void) printk(KERN_DEBUG "High memory starts at vaddr %08lx\n", (ulong) pfn_to_kaddr(highstart_pfn)); + __vmalloc_start_set = true; setup_bootmem_allocator(); } -- cgit v1.2.3-59-g8ed1b From d2b6dc61a8dd3c429609b993778cb54e75a5c5f0 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Mon, 8 May 2017 17:09:10 -0700 Subject: x86/boot/32: Fix UP boot on Quark and possibly other platforms This partially reverts commit: 23b2a4ddebdd17f ("x86/boot/32: Defer resyncing initial_page_table until per-cpu is set up") That commit had one definite bug and one potential bug. The definite bug is that setup_per_cpu_areas() uses a differnet generic implementation on UP kernels, so initial_page_table never got resynced. This was fine for access to percpu data (it's in the identity map on UP), but it breaks other users of initial_page_table. The potential bug is that helpers like efi_init() would be called before the tables were synced. Avoid both problems by just syncing the page tables in setup_arch() *and* setup_per_cpu_areas(). Reported-by: Jan Kiszka Signed-off-by: Andy Lutomirski Cc: Andy Shevchenko Cc: Ard Biesheuvel Cc: Boris Ostrovsky Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Josh Poimboeuf Cc: Juergen Gross Cc: Linus Torvalds Cc: Matt Fleming Cc: Peter Zijlstra Cc: Thomas Garnier Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/setup.c | 15 +++++++++++++++ arch/x86/kernel/setup_percpu.c | 10 +++++----- 2 files changed, 20 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 603a1669a2ec..0b4d3c686b1e 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -1225,6 +1225,21 @@ void __init setup_arch(char **cmdline_p) kasan_init(); +#ifdef CONFIG_X86_32 + /* sync back kernel address range */ + clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY, + swapper_pg_dir + KERNEL_PGD_BOUNDARY, + KERNEL_PGD_PTRS); + + /* + * sync back low identity map too. It is used for example + * in the 32-bit EFI stub. + */ + clone_pgd_range(initial_page_table, + swapper_pg_dir + KERNEL_PGD_BOUNDARY, + min(KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY)); +#endif + tboot_probe(); map_vsyscall(); diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index bb1e8cc0bc84..10edd1e69a68 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -291,11 +291,11 @@ void __init setup_per_cpu_areas(void) #ifdef CONFIG_X86_32 /* - * Sync back kernel address range. We want to make sure that - * all kernel mappings, including percpu mappings, are available - * in the smpboot asm. We can't reliably pick up percpu - * mappings using vmalloc_fault(), because exception dispatch - * needs percpu data. + * Sync back kernel address range again. We already did this in + * setup_arch(), but percpu data also needs to be available in + * the smpboot asm. We can't reliably pick up percpu mappings + * using vmalloc_fault(), because exception dispatch needs + * percpu data. */ clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY, swapper_pg_dir + KERNEL_PGD_BOUNDARY, -- cgit v1.2.3-59-g8ed1b From 4a1bec4605838fd7872ec41677585e241e256785 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Mon, 8 May 2017 20:29:46 -0700 Subject: x86/build: Don't add -maccumulate-outgoing-args w/o compiler support Clang does not support this machine dependent option. Older versions of GCC (pre 3.0) may not support this option, added in 2000, but it's unlikely they can still compile a working kernel. Signed-off-by: Nick Desaulniers Reviewed-by: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20170509032946.20444-1-nick.desaulniers@gmail.com Signed-off-by: Ingo Molnar --- arch/x86/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 4430dd489620..5851411e60fb 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -179,7 +179,8 @@ ifdef CONFIG_JUMP_LABEL endif ifeq ($(ACCUMULATE_OUTGOING_ARGS), 1) - KBUILD_CFLAGS += -maccumulate-outgoing-args + # This compiler flag is not supported by Clang: + KBUILD_CFLAGS += $(call cc-option,-maccumulate-outgoing-args,) endif # Stackpointer is addressed different for 32 bit and 64 bit x86 -- cgit v1.2.3-59-g8ed1b From 24e0bfbf63bac18495b0ad76115269f2158e9234 Mon Sep 17 00:00:00 2001 From: Horia Geantă Date: Mon, 8 May 2017 11:50:16 +0300 Subject: powerpc: Fix distclean with Makefile.postlink MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Makefile.postlink always includes include/config/auto.conf, however this file is not present in a clean kernel tree, causing make to fail: $ git clone linuxppc.git $ cd linuxppc.git $ make distclean arch/powerpc/Makefile.postlink:10: include/config/auto.conf: No such file or directory make[1]: *** No rule to make target `include/config/auto.conf'. Stop. make: *** [vmlinuxclean] Error 2 Equally running 'make distclean; make distclean' will trip the error case. Change the inclusion such that file not being found does not trigger an error. Fixes: f188d0524d7e ("powerpc: Use the new post-link pass to check relocations") Reported-by: Mircea Pop Signed-off-by: Horia Geantă Tested-by: Justin M. Forbes Signed-off-by: Michael Ellerman --- arch/powerpc/Makefile.postlink | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/powerpc/Makefile.postlink b/arch/powerpc/Makefile.postlink index 3c22d64b2de9..eccfcc88afae 100644 --- a/arch/powerpc/Makefile.postlink +++ b/arch/powerpc/Makefile.postlink @@ -7,7 +7,7 @@ PHONY := __archpost __archpost: -include include/config/auto.conf +-include include/config/auto.conf include scripts/Kbuild.include quiet_cmd_relocs_check = CHKREL $@ -- cgit v1.2.3-59-g8ed1b From ba95b5d0359609b4ec8010f77c40ab3c595a6ac6 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 9 May 2017 15:39:04 +1000 Subject: powerpc/mm/book3s/64: Rework page table geometry for lower memory usage Recently in commit f6eedbba7a26 ("powerpc/mm/hash: Increase VA range to 128TB") we increased the virtual address space for user processes to 128TB by default, and up to 512TB if user space opts in. This obviously required expanding the range of the Linux page tables. For Book3s 64-bit using hash and with PAGE_SIZE=64K, we increased the PGD to 2^15 entries. This meant we could cover the full address range, while still being able to insert a 16G hugepage at the PGD level and a 16M hugepage in the PMD. The downside of that geometry is that it uses a lot of memory for the PGD, and in particular makes the PGD a 4-page allocation, which means it's much more likely to fail under memory pressure. Instead we can make the PMD larger, so that a single PUD entry maps 16G, allowing the 16G hugepages to sit at that level in the tree. We're then able to split the remaining bits between the PUG and PGD. We make the PGD slightly larger as that results in lower memory usage for typical programs. When THP is enabled the PMD actually doubles in size, to 2^11 entries, or 2^14 bytes, which is large but still < PAGE_SIZE. Signed-off-by: Michael Ellerman Reviewed-by: Balbir Singh Reviewed-by: Aneesh Kumar K.V --- arch/powerpc/include/asm/book3s/64/hash-64k.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/include/asm/book3s/64/hash-64k.h b/arch/powerpc/include/asm/book3s/64/hash-64k.h index 214219dff87c..9732837aaae8 100644 --- a/arch/powerpc/include/asm/book3s/64/hash-64k.h +++ b/arch/powerpc/include/asm/book3s/64/hash-64k.h @@ -2,9 +2,9 @@ #define _ASM_POWERPC_BOOK3S_64_HASH_64K_H #define H_PTE_INDEX_SIZE 8 -#define H_PMD_INDEX_SIZE 5 -#define H_PUD_INDEX_SIZE 5 -#define H_PGD_INDEX_SIZE 15 +#define H_PMD_INDEX_SIZE 10 +#define H_PUD_INDEX_SIZE 7 +#define H_PGD_INDEX_SIZE 8 /* * 64k aligned address free up few of the lower bits of RPN for us -- cgit v1.2.3-59-g8ed1b From 6102c005a71b4a7a6433d43b887662fb0780746d Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Thu, 4 May 2017 20:41:12 +1000 Subject: powerpc/64s: Fix unnecessary machine check handler relocation branch Similarly to commit 2563a70c3b ("powerpc/64s: Remove unnecessary relocation branch from idle handler"), the machine check handler has a BRANCH_TO from relocated to relocated code, which is unnecessary. It has also caused build errors with some toolchains: arch/powerpc/kernel/exceptions-64s.S: Assembler messages: arch/powerpc/kernel/exceptions-64s.S:395: Error: operand out of range (0xffffffffffff8280 is not between 0x0000000000000000 and 0x000000000000ffff) Fixes: 1945bc4549e5 ("powerpc/64s: Fix POWER9 machine check handler from stop state") Signed-off-by: Nicholas Piggin Reported-and-tested-by : Abdul Haleem Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/exceptions-64s.S | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 3840a7700285..ef72065f684c 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S @@ -391,9 +391,7 @@ EXC_COMMON_BEGIN(machine_check_handle_early) */ BEGIN_FTR_SECTION rlwinm. r11,r12,47-31,30,31 - beq- 4f - BRANCH_TO_COMMON(r10, machine_check_idle_common) -4: + bne machine_check_idle_common END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206) #endif -- cgit v1.2.3-59-g8ed1b From c7c2c709b60ed2d7e6e6871496f0e963cfad121f Mon Sep 17 00:00:00 2001 From: Jim Mattson Date: Fri, 5 May 2017 11:28:09 -0700 Subject: kvm: nVMX: Validate CR3 target count on nested VM-entry According to the SDM, the CR3-target count must not be greater than 4. Future processors may support a different number of CR3-target values. Software should read the VMX capability MSR IA32_VMX_MISC to determine the number of values supported. Signed-off-by: Jim Mattson Signed-off-by: Paolo Bonzini --- arch/x86/kvm/vmx.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch') diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index c5fd459c4043..44508522a1c7 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -1314,6 +1314,11 @@ static inline bool report_flexpriority(void) return flexpriority_enabled; } +static inline unsigned nested_cpu_vmx_misc_cr3_count(struct kvm_vcpu *vcpu) +{ + return vmx_misc_cr3_count(to_vmx(vcpu)->nested.nested_vmx_misc_low); +} + static inline bool nested_cpu_has(struct vmcs12 *vmcs12, u32 bit) { return vmcs12->cpu_based_vm_exec_control & bit; @@ -10266,6 +10271,9 @@ static int check_vmentry_prereqs(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12) vmx->nested.nested_vmx_entry_ctls_high)) return VMXERR_ENTRY_INVALID_CONTROL_FIELD; + if (vmcs12->cr3_target_count > nested_cpu_vmx_misc_cr3_count(vcpu)) + return VMXERR_ENTRY_INVALID_CONTROL_FIELD; + if (!nested_host_cr0_valid(vcpu, vmcs12->host_cr0) || !nested_host_cr4_valid(vcpu, vmcs12->host_cr4) || !nested_cr3_valid(vcpu, vmcs12->host_cr3)) -- cgit v1.2.3-59-g8ed1b From bab4165e2f031905bd0a2bb8b6ad65c5c8cfa870 Mon Sep 17 00:00:00 2001 From: Bandan Das Date: Fri, 5 May 2017 15:25:13 -0400 Subject: kvm: x86: Add a hook for arch specific dirty logging emulation When KVM updates accessed/dirty bits, this hook can be used to invoke an arch specific function that implements/emulates dirty logging such as PML. Signed-off-by: Bandan Das Signed-off-by: Paolo Bonzini --- arch/x86/include/asm/kvm_host.h | 2 ++ arch/x86/kvm/mmu.c | 15 +++++++++++++++ arch/x86/kvm/mmu.h | 1 + arch/x86/kvm/paging_tmpl.h | 4 ++++ 4 files changed, 22 insertions(+) (limited to 'arch') diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index f5bddf92faba..9c761fea0c98 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1020,6 +1020,8 @@ struct kvm_x86_ops { void (*enable_log_dirty_pt_masked)(struct kvm *kvm, struct kvm_memory_slot *slot, gfn_t offset, unsigned long mask); + int (*write_log_dirty)(struct kvm_vcpu *vcpu); + /* pmu operations of sub-arch */ const struct kvm_pmu_ops *pmu_ops; diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 558676538fca..5d3376f67794 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -1498,6 +1498,21 @@ void kvm_arch_mmu_enable_log_dirty_pt_masked(struct kvm *kvm, kvm_mmu_write_protect_pt_masked(kvm, slot, gfn_offset, mask); } +/** + * kvm_arch_write_log_dirty - emulate dirty page logging + * @vcpu: Guest mode vcpu + * + * Emulate arch specific page modification logging for the + * nested hypervisor + */ +int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu) +{ + if (kvm_x86_ops->write_log_dirty) + return kvm_x86_ops->write_log_dirty(vcpu); + + return 0; +} + bool kvm_mmu_slot_gfn_write_protect(struct kvm *kvm, struct kvm_memory_slot *slot, u64 gfn) { diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h index d8ccb32f7308..27975807cc64 100644 --- a/arch/x86/kvm/mmu.h +++ b/arch/x86/kvm/mmu.h @@ -202,4 +202,5 @@ void kvm_mmu_gfn_disallow_lpage(struct kvm_memory_slot *slot, gfn_t gfn); void kvm_mmu_gfn_allow_lpage(struct kvm_memory_slot *slot, gfn_t gfn); bool kvm_mmu_slot_gfn_write_protect(struct kvm *kvm, struct kvm_memory_slot *slot, u64 gfn); +int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu); #endif diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index 314d2071b337..56241746abbd 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h @@ -226,6 +226,10 @@ static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu, if (level == walker->level && write_fault && !(pte & PT_GUEST_DIRTY_MASK)) { trace_kvm_mmu_set_dirty_bit(table_gfn, index, sizeof(pte)); +#if PTTYPE == PTTYPE_EPT + if (kvm_arch_write_log_dirty(vcpu)) + return -EINVAL; +#endif pte |= PT_GUEST_DIRTY_MASK; } if (pte == orig_pte) -- cgit v1.2.3-59-g8ed1b From c5f983f6e8455bbff8b6b39f3ad470317fcd808e Mon Sep 17 00:00:00 2001 From: Bandan Das Date: Fri, 5 May 2017 15:25:14 -0400 Subject: nVMX: Implement emulated Page Modification Logging With EPT A/D enabled, processor access to L2 guest paging structures will result in a write violation. When this happens, write the GUEST_PHYSICAL_ADDRESS to the pml buffer provided by L1 if the access is write and the dirty bit is being set. This patch also adds necessary checks during VMEntry if L1 has enabled PML. If the PML index overflows, we change the exit reason and run L1 to simulate a PML full event. Signed-off-by: Bandan Das Signed-off-by: Paolo Bonzini --- arch/x86/kvm/vmx.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 44508522a1c7..7d056f5385e7 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -248,6 +248,7 @@ struct __packed vmcs12 { u64 xss_exit_bitmap; u64 guest_physical_address; u64 vmcs_link_pointer; + u64 pml_address; u64 guest_ia32_debugctl; u64 guest_ia32_pat; u64 guest_ia32_efer; @@ -369,6 +370,7 @@ struct __packed vmcs12 { u16 guest_ldtr_selector; u16 guest_tr_selector; u16 guest_intr_status; + u16 guest_pml_index; u16 host_es_selector; u16 host_cs_selector; u16 host_ss_selector; @@ -407,6 +409,7 @@ struct nested_vmx { /* Has the level1 guest done vmxon? */ bool vmxon; gpa_t vmxon_ptr; + bool pml_full; /* The guest-physical address of the current VMCS L1 keeps for L2 */ gpa_t current_vmptr; @@ -742,6 +745,7 @@ static const unsigned short vmcs_field_to_offset_table[] = { FIELD(GUEST_LDTR_SELECTOR, guest_ldtr_selector), FIELD(GUEST_TR_SELECTOR, guest_tr_selector), FIELD(GUEST_INTR_STATUS, guest_intr_status), + FIELD(GUEST_PML_INDEX, guest_pml_index), FIELD(HOST_ES_SELECTOR, host_es_selector), FIELD(HOST_CS_SELECTOR, host_cs_selector), FIELD(HOST_SS_SELECTOR, host_ss_selector), @@ -767,6 +771,7 @@ static const unsigned short vmcs_field_to_offset_table[] = { FIELD64(XSS_EXIT_BITMAP, xss_exit_bitmap), FIELD64(GUEST_PHYSICAL_ADDRESS, guest_physical_address), FIELD64(VMCS_LINK_POINTER, vmcs_link_pointer), + FIELD64(PML_ADDRESS, pml_address), FIELD64(GUEST_IA32_DEBUGCTL, guest_ia32_debugctl), FIELD64(GUEST_IA32_PAT, guest_ia32_pat), FIELD64(GUEST_IA32_EFER, guest_ia32_efer), @@ -1353,6 +1358,11 @@ static inline bool nested_cpu_has_xsaves(struct vmcs12 *vmcs12) vmx_xsaves_supported(); } +static inline bool nested_cpu_has_pml(struct vmcs12 *vmcs12) +{ + return nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_PML); +} + static inline bool nested_cpu_has_virt_x2apic_mode(struct vmcs12 *vmcs12) { return nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE); @@ -9369,13 +9379,20 @@ static void nested_ept_inject_page_fault(struct kvm_vcpu *vcpu, struct x86_exception *fault) { struct vmcs12 *vmcs12 = get_vmcs12(vcpu); + struct vcpu_vmx *vmx = to_vmx(vcpu); u32 exit_reason; + unsigned long exit_qualification = vcpu->arch.exit_qualification; - if (fault->error_code & PFERR_RSVD_MASK) + if (vmx->nested.pml_full) { + exit_reason = EXIT_REASON_PML_FULL; + vmx->nested.pml_full = false; + exit_qualification &= INTR_INFO_UNBLOCK_NMI; + } else if (fault->error_code & PFERR_RSVD_MASK) exit_reason = EXIT_REASON_EPT_MISCONFIG; else exit_reason = EXIT_REASON_EPT_VIOLATION; - nested_vmx_vmexit(vcpu, exit_reason, 0, vcpu->arch.exit_qualification); + + nested_vmx_vmexit(vcpu, exit_reason, 0, exit_qualification); vmcs12->guest_physical_address = fault->address; } @@ -9718,6 +9735,22 @@ static int nested_vmx_check_msr_switch_controls(struct kvm_vcpu *vcpu, return 0; } +static int nested_vmx_check_pml_controls(struct kvm_vcpu *vcpu, + struct vmcs12 *vmcs12) +{ + u64 address = vmcs12->pml_address; + int maxphyaddr = cpuid_maxphyaddr(vcpu); + + if (nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_PML)) { + if (!nested_cpu_has_ept(vmcs12) || + !IS_ALIGNED(address, 4096) || + address >> maxphyaddr) + return -EINVAL; + } + + return 0; +} + static int nested_vmx_msr_check_common(struct kvm_vcpu *vcpu, struct vmx_msr_entry *e) { @@ -10253,6 +10286,9 @@ static int check_vmentry_prereqs(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12) if (nested_vmx_check_msr_switch_controls(vcpu, vmcs12)) return VMXERR_ENTRY_INVALID_CONTROL_FIELD; + if (nested_vmx_check_pml_controls(vcpu, vmcs12)) + return VMXERR_ENTRY_INVALID_CONTROL_FIELD; + if (!vmx_control_verify(vmcs12->cpu_based_vm_exec_control, vmx->nested.nested_vmx_procbased_ctls_low, vmx->nested.nested_vmx_procbased_ctls_high) || @@ -11151,6 +11187,46 @@ static void vmx_flush_log_dirty(struct kvm *kvm) kvm_flush_pml_buffers(kvm); } +static int vmx_write_pml_buffer(struct kvm_vcpu *vcpu) +{ + struct vmcs12 *vmcs12; + struct vcpu_vmx *vmx = to_vmx(vcpu); + gpa_t gpa; + struct page *page = NULL; + u64 *pml_address; + + if (is_guest_mode(vcpu)) { + WARN_ON_ONCE(vmx->nested.pml_full); + + /* + * Check if PML is enabled for the nested guest. + * Whether eptp bit 6 is set is already checked + * as part of A/D emulation. + */ + vmcs12 = get_vmcs12(vcpu); + if (!nested_cpu_has_pml(vmcs12)) + return 0; + + if (vmcs12->guest_pml_index > PML_ENTITY_NUM) { + vmx->nested.pml_full = true; + return 1; + } + + gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS) & ~0xFFFull; + + page = nested_get_page(vcpu, vmcs12->pml_address); + if (!page) + return 0; + + pml_address = kmap(page); + pml_address[vmcs12->guest_pml_index--] = gpa; + kunmap(page); + nested_release_page_clean(page); + } + + return 0; +} + static void vmx_enable_log_dirty_pt_masked(struct kvm *kvm, struct kvm_memory_slot *memslot, gfn_t offset, unsigned long mask) @@ -11510,6 +11586,7 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = { .slot_disable_log_dirty = vmx_slot_disable_log_dirty, .flush_log_dirty = vmx_flush_log_dirty, .enable_log_dirty_pt_masked = vmx_enable_log_dirty_pt_masked, + .write_log_dirty = vmx_write_pml_buffer, .pre_block = vmx_pre_block, .post_block = vmx_post_block, -- cgit v1.2.3-59-g8ed1b From 03efce6f935f89f90a98997ceea514aeff47b6dc Mon Sep 17 00:00:00 2001 From: Bandan Das Date: Fri, 5 May 2017 15:25:15 -0400 Subject: nVMX: Advertise PML to L1 hypervisor Advertise the PML bit in vmcs12 but don't try to enable it in hardware when running L2 since L0 is emulating it. Also, preserve L0's settings for PML since it may still want to log writes. Signed-off-by: Bandan Das Signed-off-by: Paolo Bonzini --- arch/x86/kvm/vmx.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 7d056f5385e7..c6f4ad44aa95 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -2766,8 +2766,11 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx) vmx->nested.nested_vmx_ept_caps |= VMX_EPT_EXTENT_GLOBAL_BIT | VMX_EPT_EXTENT_CONTEXT_BIT | VMX_EPT_2MB_PAGE_BIT | VMX_EPT_1GB_PAGE_BIT; - if (enable_ept_ad_bits) + if (enable_ept_ad_bits) { + vmx->nested.nested_vmx_secondary_ctls_high |= + SECONDARY_EXEC_ENABLE_PML; vmx->nested.nested_vmx_ept_caps |= VMX_EPT_AD_BIT; + } } else vmx->nested.nested_vmx_ept_caps = 0; @@ -8129,7 +8132,7 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu) case EXIT_REASON_PREEMPTION_TIMER: return false; case EXIT_REASON_PML_FULL: - /* We don't expose PML support to L1. */ + /* We emulate PML support to L1. */ return false; default: return true; @@ -9924,7 +9927,7 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, bool from_vmentry, u32 *entry_failure_code) { struct vcpu_vmx *vmx = to_vmx(vcpu); - u32 exec_control; + u32 exec_control, vmcs12_exec_ctrl; vmcs_write16(GUEST_ES_SELECTOR, vmcs12->guest_es_selector); vmcs_write16(GUEST_CS_SELECTOR, vmcs12->guest_cs_selector); @@ -10055,8 +10058,11 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | SECONDARY_EXEC_APIC_REGISTER_VIRT); if (nested_cpu_has(vmcs12, - CPU_BASED_ACTIVATE_SECONDARY_CONTROLS)) - exec_control |= vmcs12->secondary_vm_exec_control; + CPU_BASED_ACTIVATE_SECONDARY_CONTROLS)) { + vmcs12_exec_ctrl = vmcs12->secondary_vm_exec_control & + ~SECONDARY_EXEC_ENABLE_PML; + exec_control |= vmcs12_exec_ctrl; + } if (exec_control & SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY) { vmcs_write64(EOI_EXIT_BITMAP0, -- cgit v1.2.3-59-g8ed1b From 75bda95048a4d2c5ff04036bd0181bc84085d8b2 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Tue, 9 May 2017 13:17:08 +1000 Subject: powerpc: Don't print cpu_spec->cpu_name if it's NULL Currently we assume that if the cpu_spec has a pvr_mask then it must also have a cpu_name. But that will change in a subsequent commit when we do CPU feature discovery via the device tree, so check explicitly if cpu_name is NULL. Signed-off-by: Nicholas Piggin Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/setup-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 5c10b5925ac2..b57df7fc9e5f 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -256,7 +256,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "processor\t: %lu\n", cpu_id); seq_printf(m, "cpu\t\t: "); - if (cur_cpu_spec->pvr_mask) + if (cur_cpu_spec->pvr_mask && cur_cpu_spec->cpu_name) seq_printf(m, "%s", cur_cpu_spec->cpu_name); else seq_printf(m, "unknown (%08x)", pvr); -- cgit v1.2.3-59-g8ed1b From 5a61ef74f269f2573f48fa53607a8911216c3326 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Tue, 9 May 2017 13:16:52 +1000 Subject: powerpc/64s: Support new device tree binding for discovering CPU features The ibm,powerpc-cpu-features device tree binding describes CPU features with ASCII names and extensible compatibility, privilege, and enablement metadata that allows improved flexibility and compatibility with new hardware. The interface is described in detail in ibm,powerpc-cpu-features.txt in this patch. Currently this code is not enabled by default, and there are no released firmwares that provide the binding. Signed-off-by: Nicholas Piggin Signed-off-by: Michael Ellerman --- .../bindings/powerpc/ibm,powerpc-cpu-features.txt | 248 +++++ arch/powerpc/Kconfig | 16 + arch/powerpc/include/asm/cpu_has_feature.h | 6 +- arch/powerpc/include/asm/cputable.h | 2 + arch/powerpc/include/asm/dt_cpu_ftrs.h | 26 + arch/powerpc/include/asm/reg.h | 1 + arch/powerpc/include/uapi/asm/cputable.h | 7 + arch/powerpc/kernel/Makefile | 1 + arch/powerpc/kernel/cputable.c | 37 +- arch/powerpc/kernel/dt_cpu_ftrs.c | 1031 ++++++++++++++++++++ arch/powerpc/kernel/prom.c | 29 +- arch/powerpc/kernel/setup_64.c | 10 +- 12 files changed, 1398 insertions(+), 16 deletions(-) create mode 100644 Documentation/devicetree/bindings/powerpc/ibm,powerpc-cpu-features.txt create mode 100644 arch/powerpc/include/asm/dt_cpu_ftrs.h create mode 100644 arch/powerpc/kernel/dt_cpu_ftrs.c (limited to 'arch') diff --git a/Documentation/devicetree/bindings/powerpc/ibm,powerpc-cpu-features.txt b/Documentation/devicetree/bindings/powerpc/ibm,powerpc-cpu-features.txt new file mode 100644 index 000000000000..5af426e13334 --- /dev/null +++ b/Documentation/devicetree/bindings/powerpc/ibm,powerpc-cpu-features.txt @@ -0,0 +1,248 @@ +*** NOTE *** +This document is copied from OPAL firmware +(skiboot/doc/device-tree/ibm,powerpc-cpu-features/binding.txt) + +There is more complete overview and documentation of features in that +source tree. All patches and modifications should go there. +************ + +ibm,powerpc-cpu-features binding +================================ + +This device tree binding describes CPU features available to software, with +enablement, privilege, and compatibility metadata. + +More general description of design and implementation of this binding is +found in design.txt, which also points to documentation of specific features. + + +/cpus/ibm,powerpc-cpu-features node binding +------------------------------------------- + +Node: ibm,powerpc-cpu-features + +Description: Container of CPU feature nodes. + +The node name must be "ibm,powerpc-cpu-features". + +It is implemented as a child of the node "/cpus", but this must not be +assumed by parsers. + +The node is optional but should be provided by new OPAL firmware. + +Properties: + +- compatible + Usage: required + Value type: string + Definition: "ibm,powerpc-cpu-features" + + This compatibility refers to backwards compatibility of the overall + design with parsers that behave according to these guidelines. This can + be extended in a backward compatible manner which would not warrant a + revision of the compatible property. + +- isa + Usage: required + Value type: + Definition: + + isa that the CPU is currently running in. This provides instruction set + compatibility, less the individual feature nodes. For example, an ISA v3.0 + implementation that lacks the "transactional-memory" cpufeature node + should not use transactional memory facilities. + + Value corresponds to the "Power ISA Version" multiplied by 1000. + For example, <3000> corresponds to Version 3.0, <2070> to Version 2.07. + The minor digit is available for revisions. + +- display-name + Usage: optional + Value type: string + Definition: + + A human readable name for the CPU. + +/cpus/ibm,powerpc-cpu-features/example-feature node bindings +---------------------------------------------------------------- + +Each child node of cpu-features represents a CPU feature / capability. + +Node: A string describing an architected CPU feature, e.g., "floating-point". + +Description: A feature or capability supported by the CPUs. + +The name of the node is a human readable string that forms the interface +used to describe features to software. Features are currently documented +in the code where they are implemented in skiboot/core/cpufeatures.c + +Presence of the node indicates the feature is available. + +Properties: + +- isa + Usage: required + Value type: + Definition: + + First level of the Power ISA that the feature appears in. + Software should filter out features when constraining the + environment to a particular ISA version. + + Value is defined similarly to /cpus/features/isa + +- usable-privilege + Usage: required + Value type: bit mask + Definition: + Bit numbers are LSB0 + bit 0 - PR (problem state / user mode) + bit 1 - OS (privileged state) + bit 2 - HV (hypervisor state) + All other bits reserved and should be zero. + + This property describes the privilege levels and/or software components + that can use the feature. + + If bit 0 is set, then the hwcap-bit-nr property will exist. + + +- hv-support + Usage: optional + Value type: bit mask + Definition: + Bit numbers are LSB0 + bit 0 - HFSCR + All other bits reserved and should be zero. + + This property describes the HV privilege support required to enable the + feature to lesser privilege levels. If the property does not exist then no + support is required. + + If no bits are set, the hypervisor must have explicit/custom support for + this feature. + + If the HFSCR bit is set, then the hfscr-bit-nr property will exist and + the feature may be enabled by setting this bit in the HFSCR register. + + +- os-support + Usage: optional + Value type: bit mask + Definition: + Bit numbers are LSB0 + bit 0 - FSCR + All other bits reserved and should be zero. + + This property describes the OS privilege support required to enable the + feature to lesser privilege levels. If the property does not exist then no + support is required. + + If no bits are set, the operating system must have explicit/custom support + for this feature. + + If the FSCR bit is set, then the fscr-bit-nr property will exist and + the feature may be enabled by setting this bit in the FSCR register. + + +- hfscr-bit-nr + Usage: optional + Value type: + Definition: HFSCR bit position (LSB0) + + This property exists when the hv-support property HFSCR bit is set. This + property describes the bit number in the HFSCR register that the + hypervisor must set in order to enable this feature. + + This property also exists if an HFSCR bit corresponds with this feature. + This makes CPU feature parsing slightly simpler. + + +- fscr-bit-nr + Usage: optional + Value type: + Definition: FSCR bit position (LSB0) + + This property exists when the os-support property FSCR bit is set. This + property describes the bit number in the FSCR register that the + operating system must set in order to enable this feature. + + This property also exists if an FSCR bit corresponds with this feature. + This makes CPU feature parsing slightly simpler. + + +- hwcap-bit-nr + Usage: optional + Value type: + Definition: Linux ELF AUX vector bit position (LSB0) + + This property may exist when the usable-privilege property value has PR bit set. + This property describes the bit number that should be set in the ELF AUX + hardware capability vectors in order to advertise this feature to userspace. + Bits 0-31 correspond to bits 0-31 in AT_HWCAP vector. Bits 32-63 correspond + to 0-31 in AT_HWCAP2 vector, and so on. Missing AT_HWCAPx vectors implies + that the feature is not enabled or can not be advertised. Operating systems + may provide a number of unassigned hardware capability bits to allow for new + features to be advertised. + + Some properties representing features created before this binding are + advertised to userspace without a one-to-one hwcap bit number may not specify + this bit. Operating system will handle those bits specifically. All new + features usable by userspace will have a hwcap-bit-nr property. + + +- dependencies + Usage: optional + Value type: + Definition: + + If this property exists then it is a list of phandles to cpu feature + nodes that must be enabled for this feature to be enabled. + + +Example +------- + + /cpus/ibm,powerpc-cpu-features { + compatible = "ibm,powerpc-cpu-features"; + + isa = <3020>; + + darn { + isa = <3000>; + usable-privilege = <1 | 2 | 4>; + hwcap-bit-nr = ; + }; + + scv { + isa = <3000>; + usable-privilege = <1 | 2>; + os-support = <0>; + hwcap-bit-nr = ; + }; + + stop { + isa = <3000>; + usable-privilege = <2 | 4>; + hv-support = <0>; + os-support = <0>; + }; + + vsx2 (hypothetical) { + isa = <3010>; + usable-privilege = <1 | 2 | 4>; + hv-support = <0>; + os-support = <0>; + hwcap-bit-nr = ; + }; + + vsx2-newinsns { + isa = <3020>; + usable-privilege = <1 | 2 | 4>; + os-support = <1>; + fscr-bit-nr = ; + hwcap-bit-nr = ; + dependencies = <&vsx2>; + }; + + }; diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 67ee6731f4e9..5bd868f2e813 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -380,6 +380,22 @@ source "arch/powerpc/platforms/Kconfig" menu "Kernel options" +config PPC_DT_CPU_FTRS + bool "Device-tree based CPU feature discovery & setup" + depends on PPC_BOOK3S_64 + default n + help + This enables code to use a new device tree binding for describing CPU + compatibility and features. Saying Y here will attempt to use the new + binding if the firmware provides it. Currently only the skiboot + firmware provides this binding. + If you're not sure say Y. + +config PPC_CPUFEATURES_ENABLE_UNKNOWN + bool "cpufeatures pass through unknown features to guest/userspace" + depends on PPC_DT_CPU_FTRS + default y + config HIGHMEM bool "High memory support" depends on PPC32 diff --git a/arch/powerpc/include/asm/cpu_has_feature.h b/arch/powerpc/include/asm/cpu_has_feature.h index 6e834caa3720..0d1df02bf99d 100644 --- a/arch/powerpc/include/asm/cpu_has_feature.h +++ b/arch/powerpc/include/asm/cpu_has_feature.h @@ -1,5 +1,5 @@ -#ifndef __ASM_POWERPC_CPUFEATURES_H -#define __ASM_POWERPC_CPUFEATURES_H +#ifndef __ASM_POWERPC_CPU_HAS_FEATURE_H +#define __ASM_POWERPC_CPU_HAS_FEATURE_H #ifndef __ASSEMBLY__ @@ -52,4 +52,4 @@ static inline bool cpu_has_feature(unsigned long feature) #endif #endif /* __ASSEMBLY__ */ -#endif /* __ASM_POWERPC_CPUFEATURE_H */ +#endif /* __ASM_POWERPC_CPU_HAS_FEATURE_H */ diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index 1f6847b107e4..c2d509584a98 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h @@ -118,7 +118,9 @@ extern struct cpu_spec *cur_cpu_spec; extern unsigned int __start___ftr_fixup, __stop___ftr_fixup; +extern void set_cur_cpu_spec(struct cpu_spec *s); extern struct cpu_spec *identify_cpu(unsigned long offset, unsigned int pvr); +extern void identify_cpu_name(unsigned int pvr); extern void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end); diff --git a/arch/powerpc/include/asm/dt_cpu_ftrs.h b/arch/powerpc/include/asm/dt_cpu_ftrs.h new file mode 100644 index 000000000000..7a34fc11bf63 --- /dev/null +++ b/arch/powerpc/include/asm/dt_cpu_ftrs.h @@ -0,0 +1,26 @@ +#ifndef __ASM_POWERPC_DT_CPU_FTRS_H +#define __ASM_POWERPC_DT_CPU_FTRS_H + +/* + * Copyright 2017, IBM Corporation + * cpufeatures is the new way to discover CPU features with /cpus/features + * devicetree. This supersedes PVR based discovery ("cputable"), and older + * device tree feature advertisement. + */ + +#include +#include +#include +#include + +#ifdef CONFIG_PPC_DT_CPU_FTRS +bool dt_cpu_ftrs_init(void *fdt); +void dt_cpu_ftrs_scan(void); +bool dt_cpu_ftrs_in_use(void); +#else +static inline bool dt_cpu_ftrs_init(void *fdt) { return false; } +static inline void dt_cpu_ftrs_scan(void) { } +static inline bool dt_cpu_ftrs_in_use(void) { return false; } +#endif + +#endif /* __ASM_POWERPC_DT_CPU_FTRS_H */ diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index d4f653c9259a..7e50e47375d6 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -1229,6 +1229,7 @@ #define PVR_POWER8E 0x004B #define PVR_POWER8NVL 0x004C #define PVR_POWER8 0x004D +#define PVR_POWER9 0x004E #define PVR_BE 0x0070 #define PVR_PA6T 0x0090 diff --git a/arch/powerpc/include/uapi/asm/cputable.h b/arch/powerpc/include/uapi/asm/cputable.h index f63c96cd3608..3e7ce86d5c13 100644 --- a/arch/powerpc/include/uapi/asm/cputable.h +++ b/arch/powerpc/include/uapi/asm/cputable.h @@ -47,4 +47,11 @@ #define PPC_FEATURE2_ARCH_3_00 0x00800000 /* ISA 3.00 */ #define PPC_FEATURE2_HAS_IEEE128 0x00400000 /* VSX IEEE Binary Float 128-bit */ +/* + * IMPORTANT! + * All future PPC_FEATURE definitions should be allocated in cooperation with + * OPAL / skiboot firmware, in accordance with the ibm,powerpc-cpu-features + * device tree binding. + */ + #endif /* _UAPI__ASM_POWERPC_CPUTABLE_H */ diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index b9db46ae545b..e132902e1f14 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -56,6 +56,7 @@ obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y-y) obj-$(CONFIG_PPC_RTAS_DAEMON) += rtasd.o obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o obj-$(CONFIG_RTAS_PROC) += rtas-proc.o +obj-$(CONFIG_PPC_DT_CPU_FTRS) += dt_cpu_ftrs.o obj-$(CONFIG_EEH) += eeh.o eeh_pe.o eeh_dev.o eeh_cache.o \ eeh_driver.o eeh_event.o eeh_sysfs.o obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index e79b9daa873c..9b3e88b1a9c8 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -23,7 +23,9 @@ #include #include -struct cpu_spec* cur_cpu_spec = NULL; +static struct cpu_spec the_cpu_spec __read_mostly; + +struct cpu_spec* cur_cpu_spec __read_mostly = NULL; EXPORT_SYMBOL(cur_cpu_spec); /* The platform string corresponding to the real PVR */ @@ -2179,7 +2181,15 @@ static struct cpu_spec __initdata cpu_specs[] = { #endif /* CONFIG_E500 */ }; -static struct cpu_spec the_cpu_spec; +void __init set_cur_cpu_spec(struct cpu_spec *s) +{ + struct cpu_spec *t = &the_cpu_spec; + + t = PTRRELOC(t); + *t = *s; + + *PTRRELOC(&cur_cpu_spec) = &the_cpu_spec; +} static struct cpu_spec * __init setup_cpu_spec(unsigned long offset, struct cpu_spec *s) @@ -2266,6 +2276,29 @@ struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr) return NULL; } +/* + * Used by cpufeatures to get the name for CPUs with a PVR table. + * If they don't hae a PVR table, cpufeatures gets the name from + * cpu device-tree node. + */ +void __init identify_cpu_name(unsigned int pvr) +{ + struct cpu_spec *s = cpu_specs; + struct cpu_spec *t = &the_cpu_spec; + int i; + + s = PTRRELOC(s); + t = PTRRELOC(t); + + for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++) { + if ((pvr & s->pvr_mask) == s->pvr_value) { + t->cpu_name = s->cpu_name; + return; + } + } +} + + #ifdef CONFIG_JUMP_LABEL_FEATURE_CHECKS struct static_key_true cpu_feature_keys[NUM_CPU_FTR_KEYS] = { [0 ... NUM_CPU_FTR_KEYS - 1] = STATIC_KEY_TRUE_INIT diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c new file mode 100644 index 000000000000..fcc7588a96d6 --- /dev/null +++ b/arch/powerpc/kernel/dt_cpu_ftrs.c @@ -0,0 +1,1031 @@ +/* + * Copyright 2017, Nicholas Piggin, IBM Corporation + * Licensed under GPLv2. + */ + +#define pr_fmt(fmt) "dt-cpu-ftrs: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +/* Device-tree visible constants follow */ +#define ISA_V2_07B 2070 +#define ISA_V3_0B 3000 + +#define USABLE_PR (1U << 0) +#define USABLE_OS (1U << 1) +#define USABLE_HV (1U << 2) + +#define HV_SUPPORT_HFSCR (1U << 0) +#define OS_SUPPORT_FSCR (1U << 0) + +/* For parsing, we define all bits set as "NONE" case */ +#define HV_SUPPORT_NONE 0xffffffffU +#define OS_SUPPORT_NONE 0xffffffffU + +struct dt_cpu_feature { + const char *name; + uint32_t isa; + uint32_t usable_privilege; + uint32_t hv_support; + uint32_t os_support; + uint32_t hfscr_bit_nr; + uint32_t fscr_bit_nr; + uint32_t hwcap_bit_nr; + /* fdt parsing */ + unsigned long node; + int enabled; + int disabled; +}; + +#define CPU_FTRS_BASE \ + (CPU_FTR_USE_TB | \ + CPU_FTR_LWSYNC | \ + CPU_FTR_FPU_UNAVAILABLE |\ + CPU_FTR_NODSISRALIGN |\ + CPU_FTR_NOEXECUTE |\ + CPU_FTR_COHERENT_ICACHE | \ + CPU_FTR_STCX_CHECKS_ADDRESS |\ + CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ + CPU_FTR_DAWR | \ + CPU_FTR_ARCH_206 |\ + CPU_FTR_ARCH_207S) + +#define MMU_FTRS_HASH_BASE (MMU_FTRS_POWER8) + +#define COMMON_USER_BASE (PPC_FEATURE_32 | PPC_FEATURE_64 | \ + PPC_FEATURE_ARCH_2_06 |\ + PPC_FEATURE_ICACHE_SNOOP) +#define COMMON_USER2_BASE (PPC_FEATURE2_ARCH_2_07 | \ + PPC_FEATURE2_ISEL) +/* + * Set up the base CPU + */ + +extern void __flush_tlb_power8(unsigned int action); +extern void __flush_tlb_power9(unsigned int action); +extern long __machine_check_early_realmode_p8(struct pt_regs *regs); +extern long __machine_check_early_realmode_p9(struct pt_regs *regs); + +static int hv_mode; + +static struct { + u64 lpcr; + u64 hfscr; + u64 fscr; +} system_registers; + +static void (*init_pmu_registers)(void); + +static void cpufeatures_flush_tlb(void) +{ + unsigned long rb; + unsigned int i, num_sets; + + /* + * This is a temporary measure to keep equivalent TLB flush as the + * cputable based setup code. + */ + switch (PVR_VER(mfspr(SPRN_PVR))) { + case PVR_POWER8: + case PVR_POWER8E: + case PVR_POWER8NVL: + num_sets = POWER8_TLB_SETS; + break; + case PVR_POWER9: + num_sets = POWER9_TLB_SETS_HASH; + break; + default: + num_sets = 1; + pr_err("unknown CPU version for boot TLB flush\n"); + break; + } + + asm volatile("ptesync" : : : "memory"); + rb = TLBIEL_INVAL_SET; + for (i = 0; i < num_sets; i++) { + asm volatile("tlbiel %0" : : "r" (rb)); + rb += 1 << TLBIEL_INVAL_SET_SHIFT; + } + asm volatile("ptesync" : : : "memory"); +} + +static void __restore_cpu_cpufeatures(void) +{ + /* + * LPCR is restored by the power on engine already. It can be changed + * after early init e.g., by radix enable, and we have no unified API + * for saving and restoring such SPRs. + * + * This ->restore hook should really be removed from idle and register + * restore moved directly into the idle restore code, because this code + * doesn't know how idle is implemented or what it needs restored here. + * + * The best we can do to accommodate secondary boot and idle restore + * for now is "or" LPCR with existing. + */ + + mtspr(SPRN_LPCR, system_registers.lpcr | mfspr(SPRN_LPCR)); + if (hv_mode) { + mtspr(SPRN_LPID, 0); + mtspr(SPRN_HFSCR, system_registers.hfscr); + } + mtspr(SPRN_FSCR, system_registers.fscr); + + if (init_pmu_registers) + init_pmu_registers(); + + cpufeatures_flush_tlb(); +} + +static char dt_cpu_name[64]; + +static struct cpu_spec __initdata base_cpu_spec = { + .cpu_name = NULL, + .cpu_features = CPU_FTRS_BASE, + .cpu_user_features = COMMON_USER_BASE, + .cpu_user_features2 = COMMON_USER2_BASE, + .mmu_features = 0, + .icache_bsize = 32, /* minimum block size, fixed by */ + .dcache_bsize = 32, /* cache info init. */ + .num_pmcs = 0, + .pmc_type = PPC_PMC_DEFAULT, + .oprofile_cpu_type = NULL, + .oprofile_type = PPC_OPROFILE_INVALID, + .cpu_setup = NULL, + .cpu_restore = __restore_cpu_cpufeatures, + .flush_tlb = NULL, + .machine_check_early = NULL, + .platform = NULL, +}; + +static void __init cpufeatures_setup_cpu(void) +{ + set_cur_cpu_spec(&base_cpu_spec); + + cur_cpu_spec->pvr_mask = -1; + cur_cpu_spec->pvr_value = mfspr(SPRN_PVR); + + /* Initialize the base environment -- clear FSCR/HFSCR. */ + hv_mode = !!(mfmsr() & MSR_HV); + if (hv_mode) { + /* CPU_FTR_HVMODE is used early in PACA setup */ + cur_cpu_spec->cpu_features |= CPU_FTR_HVMODE; + mtspr(SPRN_HFSCR, 0); + } + mtspr(SPRN_FSCR, 0); + + /* + * LPCR does not get cleared, to match behaviour with secondaries + * in __restore_cpu_cpufeatures. Once the idle code is fixed, this + * could clear LPCR too. + */ +} + +static int __init feat_try_enable_unknown(struct dt_cpu_feature *f) +{ + if (f->hv_support == HV_SUPPORT_NONE) { + } else if (f->hv_support & HV_SUPPORT_HFSCR) { + u64 hfscr = mfspr(SPRN_HFSCR); + hfscr |= 1UL << f->hfscr_bit_nr; + mtspr(SPRN_HFSCR, hfscr); + } else { + /* Does not have a known recipe */ + return 0; + } + + if (f->os_support == OS_SUPPORT_NONE) { + } else if (f->os_support & OS_SUPPORT_FSCR) { + u64 fscr = mfspr(SPRN_FSCR); + fscr |= 1UL << f->fscr_bit_nr; + mtspr(SPRN_FSCR, fscr); + } else { + /* Does not have a known recipe */ + return 0; + } + + if ((f->usable_privilege & USABLE_PR) && (f->hwcap_bit_nr != -1)) { + uint32_t word = f->hwcap_bit_nr / 32; + uint32_t bit = f->hwcap_bit_nr % 32; + + if (word == 0) + cur_cpu_spec->cpu_user_features |= 1U << bit; + else if (word == 1) + cur_cpu_spec->cpu_user_features2 |= 1U << bit; + else + pr_err("%s could not advertise to user (no hwcap bits)\n", f->name); + } + + return 1; +} + +static int __init feat_enable(struct dt_cpu_feature *f) +{ + if (f->hv_support != HV_SUPPORT_NONE) { + if (f->hfscr_bit_nr != -1) { + u64 hfscr = mfspr(SPRN_HFSCR); + hfscr |= 1UL << f->hfscr_bit_nr; + mtspr(SPRN_HFSCR, hfscr); + } + } + + if (f->os_support != OS_SUPPORT_NONE) { + if (f->fscr_bit_nr != -1) { + u64 fscr = mfspr(SPRN_FSCR); + fscr |= 1UL << f->fscr_bit_nr; + mtspr(SPRN_FSCR, fscr); + } + } + + if ((f->usable_privilege & USABLE_PR) && (f->hwcap_bit_nr != -1)) { + uint32_t word = f->hwcap_bit_nr / 32; + uint32_t bit = f->hwcap_bit_nr % 32; + + if (word == 0) + cur_cpu_spec->cpu_user_features |= 1U << bit; + else if (word == 1) + cur_cpu_spec->cpu_user_features2 |= 1U << bit; + else + pr_err("CPU feature: %s could not advertise to user (no hwcap bits)\n", f->name); + } + + return 1; +} + +static int __init feat_disable(struct dt_cpu_feature *f) +{ + return 0; +} + +static int __init feat_enable_hv(struct dt_cpu_feature *f) +{ + u64 lpcr; + + if (!hv_mode) { + pr_err("CPU feature hypervisor present in device tree but HV mode not enabled in the CPU. Ignoring.\n"); + return 0; + } + + mtspr(SPRN_LPID, 0); + + lpcr = mfspr(SPRN_LPCR); + lpcr &= ~LPCR_LPES0; /* HV external interrupts */ + mtspr(SPRN_LPCR, lpcr); + + cur_cpu_spec->cpu_features |= CPU_FTR_HVMODE; + + return 1; +} + +static int __init feat_enable_le(struct dt_cpu_feature *f) +{ + cur_cpu_spec->cpu_user_features |= PPC_FEATURE_TRUE_LE; + return 1; +} + +static int __init feat_enable_smt(struct dt_cpu_feature *f) +{ + cur_cpu_spec->cpu_features |= CPU_FTR_SMT; + cur_cpu_spec->cpu_user_features |= PPC_FEATURE_SMT; + return 1; +} + +static int __init feat_enable_idle_nap(struct dt_cpu_feature *f) +{ + u64 lpcr; + + /* Set PECE wakeup modes for ISA 207 */ + lpcr = mfspr(SPRN_LPCR); + lpcr |= LPCR_PECE0; + lpcr |= LPCR_PECE1; + lpcr |= LPCR_PECE2; + mtspr(SPRN_LPCR, lpcr); + + return 1; +} + +static int __init feat_enable_align_dsisr(struct dt_cpu_feature *f) +{ + cur_cpu_spec->cpu_features &= ~CPU_FTR_NODSISRALIGN; + + return 1; +} + +static int __init feat_enable_idle_stop(struct dt_cpu_feature *f) +{ + u64 lpcr; + + /* Set PECE wakeup modes for ISAv3.0B */ + lpcr = mfspr(SPRN_LPCR); + lpcr |= LPCR_PECE0; + lpcr |= LPCR_PECE1; + lpcr |= LPCR_PECE2; + mtspr(SPRN_LPCR, lpcr); + + return 1; +} + +static int __init feat_enable_mmu_hash(struct dt_cpu_feature *f) +{ + u64 lpcr; + + lpcr = mfspr(SPRN_LPCR); + lpcr &= ~LPCR_ISL; + + /* VRMASD */ + lpcr |= LPCR_VPM0; + lpcr &= ~LPCR_VPM1; + lpcr |= 0x10UL << LPCR_VRMASD_SH; /* L=1 LP=00 */ + mtspr(SPRN_LPCR, lpcr); + + cur_cpu_spec->mmu_features |= MMU_FTRS_HASH_BASE; + cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_MMU; + + return 1; +} + +static int __init feat_enable_mmu_hash_v3(struct dt_cpu_feature *f) +{ + u64 lpcr; + + lpcr = mfspr(SPRN_LPCR); + lpcr &= ~LPCR_ISL; + mtspr(SPRN_LPCR, lpcr); + + cur_cpu_spec->mmu_features |= MMU_FTRS_HASH_BASE; + cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_MMU; + + return 1; +} + + +static int __init feat_enable_mmu_radix(struct dt_cpu_feature *f) +{ +#ifdef CONFIG_PPC_RADIX_MMU + cur_cpu_spec->mmu_features |= MMU_FTR_TYPE_RADIX; + cur_cpu_spec->mmu_features |= MMU_FTRS_HASH_BASE; + cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_MMU; + + return 1; +#endif + return 0; +} + +static int __init feat_enable_dscr(struct dt_cpu_feature *f) +{ + u64 lpcr; + + feat_enable(f); + + lpcr = mfspr(SPRN_LPCR); + lpcr &= ~LPCR_DPFD; + lpcr |= (4UL << LPCR_DPFD_SH); + mtspr(SPRN_LPCR, lpcr); + + return 1; +} + +static void hfscr_pmu_enable(void) +{ + u64 hfscr = mfspr(SPRN_HFSCR); + hfscr |= PPC_BIT(60); + mtspr(SPRN_HFSCR, hfscr); +} + +static void init_pmu_power8(void) +{ + if (hv_mode) { + mtspr(SPRN_MMCRC, 0); + mtspr(SPRN_MMCRH, 0); + } + + mtspr(SPRN_MMCRA, 0); + mtspr(SPRN_MMCR0, 0); + mtspr(SPRN_MMCR1, 0); + mtspr(SPRN_MMCR2, 0); + mtspr(SPRN_MMCRS, 0); +} + +static int __init feat_enable_mce_power8(struct dt_cpu_feature *f) +{ + cur_cpu_spec->platform = "power8"; + cur_cpu_spec->flush_tlb = __flush_tlb_power8; + cur_cpu_spec->machine_check_early = __machine_check_early_realmode_p8; + + return 1; +} + +static int __init feat_enable_pmu_power8(struct dt_cpu_feature *f) +{ + hfscr_pmu_enable(); + + init_pmu_power8(); + init_pmu_registers = init_pmu_power8; + + cur_cpu_spec->cpu_features |= CPU_FTR_MMCRA; + cur_cpu_spec->cpu_user_features |= PPC_FEATURE_PSERIES_PERFMON_COMPAT; + if (pvr_version_is(PVR_POWER8E)) + cur_cpu_spec->cpu_features |= CPU_FTR_PMAO_BUG; + + cur_cpu_spec->num_pmcs = 6; + cur_cpu_spec->pmc_type = PPC_PMC_IBM; + cur_cpu_spec->oprofile_cpu_type = "ppc64/power8"; + + return 1; +} + +static void init_pmu_power9(void) +{ + if (hv_mode) + mtspr(SPRN_MMCRC, 0); + + mtspr(SPRN_MMCRA, 0); + mtspr(SPRN_MMCR0, 0); + mtspr(SPRN_MMCR1, 0); + mtspr(SPRN_MMCR2, 0); +} + +static int __init feat_enable_mce_power9(struct dt_cpu_feature *f) +{ + cur_cpu_spec->platform = "power9"; + cur_cpu_spec->flush_tlb = __flush_tlb_power9; + cur_cpu_spec->machine_check_early = __machine_check_early_realmode_p9; + + return 1; +} + +static int __init feat_enable_pmu_power9(struct dt_cpu_feature *f) +{ + hfscr_pmu_enable(); + + init_pmu_power9(); + init_pmu_registers = init_pmu_power9; + + cur_cpu_spec->cpu_features |= CPU_FTR_MMCRA; + cur_cpu_spec->cpu_user_features |= PPC_FEATURE_PSERIES_PERFMON_COMPAT; + + cur_cpu_spec->num_pmcs = 6; + cur_cpu_spec->pmc_type = PPC_PMC_IBM; + cur_cpu_spec->oprofile_cpu_type = "ppc64/power9"; + + return 1; +} + +static int __init feat_enable_tm(struct dt_cpu_feature *f) +{ +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM + feat_enable(f); + cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_HTM_NOSC; + return 1; +#endif + return 0; +} + +static int __init feat_enable_fp(struct dt_cpu_feature *f) +{ + feat_enable(f); + cur_cpu_spec->cpu_features &= ~CPU_FTR_FPU_UNAVAILABLE; + + return 1; +} + +static int __init feat_enable_vector(struct dt_cpu_feature *f) +{ +#ifdef CONFIG_ALTIVEC + feat_enable(f); + cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; + cur_cpu_spec->cpu_features |= CPU_FTR_VMX_COPY; + cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; + + return 1; +#endif + return 0; +} + +static int __init feat_enable_vsx(struct dt_cpu_feature *f) +{ +#ifdef CONFIG_VSX + feat_enable(f); + cur_cpu_spec->cpu_features |= CPU_FTR_VSX; + cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_VSX; + + return 1; +#endif + return 0; +} + +static int __init feat_enable_purr(struct dt_cpu_feature *f) +{ + cur_cpu_spec->cpu_features |= CPU_FTR_PURR | CPU_FTR_SPURR; + + return 1; +} + +static int __init feat_enable_ebb(struct dt_cpu_feature *f) +{ + /* + * PPC_FEATURE2_EBB is enabled in PMU init code because it has + * historically been related to the PMU facility. This may have + * to be decoupled if EBB becomes more generic. For now, follow + * existing convention. + */ + f->hwcap_bit_nr = -1; + feat_enable(f); + + return 1; +} + +static int __init feat_enable_dbell(struct dt_cpu_feature *f) +{ + u64 lpcr; + + /* P9 has an HFSCR for privileged state */ + feat_enable(f); + + cur_cpu_spec->cpu_features |= CPU_FTR_DBELL; + + lpcr = mfspr(SPRN_LPCR); + lpcr |= LPCR_PECEDH; /* hyp doorbell wakeup */ + mtspr(SPRN_LPCR, lpcr); + + return 1; +} + +static int __init feat_enable_hvi(struct dt_cpu_feature *f) +{ + u64 lpcr; + + /* + * POWER9 XIVE interrupts including in OPAL XICS compatibility + * are always delivered as hypervisor virtualization interrupts (HVI) + * rather than EE. + * + * However LPES0 is not set here, in the chance that an EE does get + * delivered to the host somehow, the EE handler would not expect it + * to be delivered in LPES0 mode (e.g., using SRR[01]). This could + * happen if there is a bug in interrupt controller code, or IC is + * misconfigured in systemsim. + */ + + lpcr = mfspr(SPRN_LPCR); + lpcr |= LPCR_HVICE; /* enable hvi interrupts */ + lpcr |= LPCR_HEIC; /* disable ee interrupts when MSR_HV */ + lpcr |= LPCR_PECE_HVEE; /* hvi can wake from stop */ + mtspr(SPRN_LPCR, lpcr); + + return 1; +} + +static int __init feat_enable_large_ci(struct dt_cpu_feature *f) +{ + cur_cpu_spec->mmu_features |= MMU_FTR_CI_LARGE_PAGE; + + return 1; +} + +struct dt_cpu_feature_match { + const char *name; + int (*enable)(struct dt_cpu_feature *f); + u64 cpu_ftr_bit_mask; +}; + +static struct dt_cpu_feature_match __initdata + dt_cpu_feature_match_table[] = { + {"hypervisor", feat_enable_hv, 0}, + {"big-endian", feat_enable, 0}, + {"little-endian", feat_enable_le, CPU_FTR_REAL_LE}, + {"smt", feat_enable_smt, 0}, + {"interrupt-facilities", feat_enable, 0}, + {"timer-facilities", feat_enable, 0}, + {"timer-facilities-v3", feat_enable, 0}, + {"debug-facilities", feat_enable, 0}, + {"come-from-address-register", feat_enable, CPU_FTR_CFAR}, + {"branch-tracing", feat_enable, 0}, + {"floating-point", feat_enable_fp, 0}, + {"vector", feat_enable_vector, 0}, + {"vector-scalar", feat_enable_vsx, 0}, + {"vector-scalar-v3", feat_enable, 0}, + {"decimal-floating-point", feat_enable, 0}, + {"decimal-integer", feat_enable, 0}, + {"quadword-load-store", feat_enable, 0}, + {"vector-crypto", feat_enable, 0}, + {"mmu-hash", feat_enable_mmu_hash, 0}, + {"mmu-radix", feat_enable_mmu_radix, 0}, + {"mmu-hash-v3", feat_enable_mmu_hash_v3, 0}, + {"virtual-page-class-key-protection", feat_enable, 0}, + {"transactional-memory", feat_enable_tm, CPU_FTR_TM}, + {"transactional-memory-v3", feat_enable_tm, 0}, + {"idle-nap", feat_enable_idle_nap, 0}, + {"alignment-interrupt-dsisr", feat_enable_align_dsisr, 0}, + {"idle-stop", feat_enable_idle_stop, 0}, + {"machine-check-power8", feat_enable_mce_power8, 0}, + {"performance-monitor-power8", feat_enable_pmu_power8, 0}, + {"data-stream-control-register", feat_enable_dscr, CPU_FTR_DSCR}, + {"event-based-branch", feat_enable_ebb, 0}, + {"target-address-register", feat_enable, 0}, + {"branch-history-rolling-buffer", feat_enable, 0}, + {"control-register", feat_enable, CPU_FTR_CTRL}, + {"processor-control-facility", feat_enable_dbell, CPU_FTR_DBELL}, + {"processor-control-facility-v3", feat_enable_dbell, CPU_FTR_DBELL}, + {"processor-utilization-of-resources-register", feat_enable_purr, 0}, + {"subcore", feat_enable, CPU_FTR_SUBCORE}, + {"no-execute", feat_enable, 0}, + {"strong-access-ordering", feat_enable, CPU_FTR_SAO}, + {"cache-inhibited-large-page", feat_enable_large_ci, 0}, + {"coprocessor-icswx", feat_enable, CPU_FTR_ICSWX}, + {"hypervisor-virtualization-interrupt", feat_enable_hvi, 0}, + {"program-priority-register", feat_enable, CPU_FTR_HAS_PPR}, + {"wait", feat_enable, 0}, + {"atomic-memory-operations", feat_enable, 0}, + {"branch-v3", feat_enable, 0}, + {"copy-paste", feat_enable, 0}, + {"decimal-floating-point-v3", feat_enable, 0}, + {"decimal-integer-v3", feat_enable, 0}, + {"fixed-point-v3", feat_enable, 0}, + {"floating-point-v3", feat_enable, 0}, + {"group-start-register", feat_enable, 0}, + {"pc-relative-addressing", feat_enable, 0}, + {"machine-check-power9", feat_enable_mce_power9, 0}, + {"performance-monitor-power9", feat_enable_pmu_power9, 0}, + {"event-based-branch-v3", feat_enable, 0}, + {"random-number-generator", feat_enable, 0}, + {"system-call-vectored", feat_disable, 0}, + {"trace-interrupt-v3", feat_enable, 0}, + {"vector-v3", feat_enable, 0}, + {"vector-binary128", feat_enable, 0}, + {"vector-binary16", feat_enable, 0}, + {"wait-v3", feat_enable, 0}, +}; + +/* XXX: how to configure this? Default + boot time? */ +#ifdef CONFIG_PPC_CPUFEATURES_ENABLE_UNKNOWN +#define CPU_FEATURE_ENABLE_UNKNOWN 1 +#else +#define CPU_FEATURE_ENABLE_UNKNOWN 0 +#endif + +static void __init cpufeatures_setup_start(u32 isa) +{ + pr_info("setup for ISA %d\n", isa); + + if (isa >= 3000) { + cur_cpu_spec->cpu_features |= CPU_FTR_ARCH_300; + cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_ARCH_3_00; + } +} + +static bool __init cpufeatures_process_feature(struct dt_cpu_feature *f) +{ + const struct dt_cpu_feature_match *m; + bool known = false; + int i; + + for (i = 0; i < ARRAY_SIZE(dt_cpu_feature_match_table); i++) { + m = &dt_cpu_feature_match_table[i]; + if (!strcmp(f->name, m->name)) { + known = true; + if (m->enable(f)) + break; + + pr_info("not enabling: %s (disabled or unsupported by kernel)\n", + f->name); + return false; + } + } + + if (!known && CPU_FEATURE_ENABLE_UNKNOWN) { + if (!feat_try_enable_unknown(f)) { + pr_info("not enabling: %s (unknown and unsupported by kernel)\n", + f->name); + return false; + } + } + + if (m->cpu_ftr_bit_mask) + cur_cpu_spec->cpu_features |= m->cpu_ftr_bit_mask; + + if (known) + pr_debug("enabling: %s\n", f->name); + else + pr_debug("enabling: %s (unknown)\n", f->name); + + return true; +} + +static __init void cpufeatures_cpu_quirks(void) +{ + int version = mfspr(SPRN_PVR); + + /* + * Not all quirks can be derived from the cpufeatures device tree. + */ + if ((version & 0xffffff00) == 0x004e0100) + cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD1; +} + +static void __init cpufeatures_setup_finished(void) +{ + cpufeatures_cpu_quirks(); + + if (hv_mode && !(cur_cpu_spec->cpu_features & CPU_FTR_HVMODE)) { + pr_err("hypervisor not present in device tree but HV mode is enabled in the CPU. Enabling.\n"); + cur_cpu_spec->cpu_features |= CPU_FTR_HVMODE; + } + + system_registers.lpcr = mfspr(SPRN_LPCR); + system_registers.hfscr = mfspr(SPRN_HFSCR); + system_registers.fscr = mfspr(SPRN_FSCR); + + cpufeatures_flush_tlb(); + + pr_info("final cpu/mmu features = 0x%016lx 0x%08x\n", + cur_cpu_spec->cpu_features, cur_cpu_spec->mmu_features); +} + +static int __init fdt_find_cpu_features(unsigned long node, const char *uname, + int depth, void *data) +{ + if (of_flat_dt_is_compatible(node, "ibm,powerpc-cpu-features") + && of_get_flat_dt_prop(node, "isa", NULL)) + return 1; + + return 0; +} + +static bool __initdata using_dt_cpu_ftrs = false; + +bool __init dt_cpu_ftrs_in_use(void) +{ + return using_dt_cpu_ftrs; +} + +bool __init dt_cpu_ftrs_init(void *fdt) +{ + /* Setup and verify the FDT, if it fails we just bail */ + if (!early_init_dt_verify(fdt)) + return false; + + if (!of_scan_flat_dt(fdt_find_cpu_features, NULL)) + return false; + + cpufeatures_setup_cpu(); + + using_dt_cpu_ftrs = true; + return true; +} + +static int nr_dt_cpu_features; +static struct dt_cpu_feature *dt_cpu_features; + +static int __init process_cpufeatures_node(unsigned long node, + const char *uname, int i) +{ + const __be32 *prop; + struct dt_cpu_feature *f; + int len; + + f = &dt_cpu_features[i]; + memset(f, 0, sizeof(struct dt_cpu_feature)); + + f->node = node; + + f->name = uname; + + prop = of_get_flat_dt_prop(node, "isa", &len); + if (!prop) { + pr_warn("%s: missing isa property\n", uname); + return 0; + } + f->isa = be32_to_cpup(prop); + + prop = of_get_flat_dt_prop(node, "usable-privilege", &len); + if (!prop) { + pr_warn("%s: missing usable-privilege property", uname); + return 0; + } + f->usable_privilege = be32_to_cpup(prop); + + prop = of_get_flat_dt_prop(node, "hv-support", &len); + if (prop) + f->hv_support = be32_to_cpup(prop); + else + f->hv_support = HV_SUPPORT_NONE; + + prop = of_get_flat_dt_prop(node, "os-support", &len); + if (prop) + f->os_support = be32_to_cpup(prop); + else + f->os_support = OS_SUPPORT_NONE; + + prop = of_get_flat_dt_prop(node, "hfscr-bit-nr", &len); + if (prop) + f->hfscr_bit_nr = be32_to_cpup(prop); + else + f->hfscr_bit_nr = -1; + prop = of_get_flat_dt_prop(node, "fscr-bit-nr", &len); + if (prop) + f->fscr_bit_nr = be32_to_cpup(prop); + else + f->fscr_bit_nr = -1; + prop = of_get_flat_dt_prop(node, "hwcap-bit-nr", &len); + if (prop) + f->hwcap_bit_nr = be32_to_cpup(prop); + else + f->hwcap_bit_nr = -1; + + if (f->usable_privilege & USABLE_HV) { + if (!(mfmsr() & MSR_HV)) { + pr_warn("%s: HV feature passed to guest\n", uname); + return 0; + } + + if (f->hv_support == HV_SUPPORT_NONE && f->hfscr_bit_nr != -1) { + pr_warn("%s: unwanted hfscr_bit_nr\n", uname); + return 0; + } + + if (f->hv_support == HV_SUPPORT_HFSCR) { + if (f->hfscr_bit_nr == -1) { + pr_warn("%s: missing hfscr_bit_nr\n", uname); + return 0; + } + } + } else { + if (f->hv_support != HV_SUPPORT_NONE || f->hfscr_bit_nr != -1) { + pr_warn("%s: unwanted hv_support/hfscr_bit_nr\n", uname); + return 0; + } + } + + if (f->usable_privilege & USABLE_OS) { + if (f->os_support == OS_SUPPORT_NONE && f->fscr_bit_nr != -1) { + pr_warn("%s: unwanted fscr_bit_nr\n", uname); + return 0; + } + + if (f->os_support == OS_SUPPORT_FSCR) { + if (f->fscr_bit_nr == -1) { + pr_warn("%s: missing fscr_bit_nr\n", uname); + return 0; + } + } + } else { + if (f->os_support != OS_SUPPORT_NONE || f->fscr_bit_nr != -1) { + pr_warn("%s: unwanted os_support/fscr_bit_nr\n", uname); + return 0; + } + } + + if (!(f->usable_privilege & USABLE_PR)) { + if (f->hwcap_bit_nr != -1) { + pr_warn("%s: unwanted hwcap_bit_nr\n", uname); + return 0; + } + } + + /* Do all the independent features in the first pass */ + if (!of_get_flat_dt_prop(node, "dependencies", &len)) { + if (cpufeatures_process_feature(f)) + f->enabled = 1; + else + f->disabled = 1; + } + + return 0; +} + +static void __init cpufeatures_deps_enable(struct dt_cpu_feature *f) +{ + const __be32 *prop; + int len; + int nr_deps; + int i; + + if (f->enabled || f->disabled) + return; + + prop = of_get_flat_dt_prop(f->node, "dependencies", &len); + if (!prop) { + pr_warn("%s: missing dependencies property", f->name); + return; + } + + nr_deps = len / sizeof(int); + + for (i = 0; i < nr_deps; i++) { + unsigned long phandle = be32_to_cpu(prop[i]); + int j; + + for (j = 0; j < nr_dt_cpu_features; j++) { + struct dt_cpu_feature *d = &dt_cpu_features[j]; + + if (of_get_flat_dt_phandle(d->node) == phandle) { + cpufeatures_deps_enable(d); + if (d->disabled) { + f->disabled = 1; + return; + } + } + } + } + + if (cpufeatures_process_feature(f)) + f->enabled = 1; + else + f->disabled = 1; +} + +static int __init scan_cpufeatures_subnodes(unsigned long node, + const char *uname, + void *data) +{ + int *count = data; + + process_cpufeatures_node(node, uname, *count); + + (*count)++; + + return 0; +} + +static int __init count_cpufeatures_subnodes(unsigned long node, + const char *uname, + void *data) +{ + int *count = data; + + (*count)++; + + return 0; +} + +static int __init dt_cpu_ftrs_scan_callback(unsigned long node, const char + *uname, int depth, void *data) +{ + const __be32 *prop; + int count, i; + u32 isa; + + /* We are scanning "ibm,powerpc-cpu-features" nodes only */ + if (!of_flat_dt_is_compatible(node, "ibm,powerpc-cpu-features")) + return 0; + + prop = of_get_flat_dt_prop(node, "isa", NULL); + if (!prop) + /* We checked before, "can't happen" */ + return 0; + + isa = be32_to_cpup(prop); + + /* Count and allocate space for cpu features */ + of_scan_flat_dt_subnodes(node, count_cpufeatures_subnodes, + &nr_dt_cpu_features); + dt_cpu_features = __va( + memblock_alloc(sizeof(struct dt_cpu_feature)* + nr_dt_cpu_features, PAGE_SIZE)); + + cpufeatures_setup_start(isa); + + /* Scan nodes into dt_cpu_features and enable those without deps */ + count = 0; + of_scan_flat_dt_subnodes(node, scan_cpufeatures_subnodes, &count); + + /* Recursive enable remaining features with dependencies */ + for (i = 0; i < nr_dt_cpu_features; i++) { + struct dt_cpu_feature *f = &dt_cpu_features[i]; + + cpufeatures_deps_enable(f); + } + + prop = of_get_flat_dt_prop(node, "display-name", NULL); + if (prop && strlen((char *)prop) != 0) { + strlcpy(dt_cpu_name, (char *)prop, sizeof(dt_cpu_name)); + cur_cpu_spec->cpu_name = dt_cpu_name; + } + + cpufeatures_setup_finished(); + + memblock_free(__pa(dt_cpu_features), + sizeof(struct dt_cpu_feature)*nr_dt_cpu_features); + + return 0; +} + +void __init dt_cpu_ftrs_scan(void) +{ + of_scan_flat_dt(dt_cpu_ftrs_scan_callback, NULL); +} diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index d2f0afeae5a0..40c4887c27b6 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -57,6 +57,7 @@ #include #include #include +#include #include @@ -375,23 +376,31 @@ static int __init early_init_dt_scan_cpus(unsigned long node, * A POWER6 partition in "POWER6 architected" mode * uses the 0x0f000002 PVR value; in POWER5+ mode * it uses 0x0f000001. + * + * If we're using device tree CPU feature discovery then we don't + * support the cpu-version property, and it's the responsibility of the + * firmware/hypervisor to provide the correct feature set for the + * architecture level via the ibm,powerpc-cpu-features binding. */ - prop = of_get_flat_dt_prop(node, "cpu-version", NULL); - if (prop && (be32_to_cpup(prop) & 0xff000000) == 0x0f000000) - identify_cpu(0, be32_to_cpup(prop)); + if (!dt_cpu_ftrs_in_use()) { + prop = of_get_flat_dt_prop(node, "cpu-version", NULL); + if (prop && (be32_to_cpup(prop) & 0xff000000) == 0x0f000000) + identify_cpu(0, be32_to_cpup(prop)); - identical_pvr_fixup(node); + check_cpu_feature_properties(node); + check_cpu_pa_features(node); + } - check_cpu_feature_properties(node); - check_cpu_pa_features(node); + identical_pvr_fixup(node); init_mmu_slb_size(node); #ifdef CONFIG_PPC64 - if (nthreads > 1) - cur_cpu_spec->cpu_features |= CPU_FTR_SMT; - else + if (nthreads == 1) cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT; + else if (!dt_cpu_ftrs_in_use()) + cur_cpu_spec->cpu_features |= CPU_FTR_SMT; #endif + return 0; } @@ -721,6 +730,8 @@ void __init early_init_devtree(void *params) DBG("Scanning CPUs ...\n"); + dt_cpu_ftrs_scan(); + /* Retrieve CPU related informations from the flat tree * (altivec support, boot CPU ID, ...) */ diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 0f7b15860a06..1bf8978ec8da 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -265,8 +266,10 @@ void __init early_setup(unsigned long dt_ptr) /* -------- printk is _NOT_ safe to use here ! ------- */ - /* Identify CPU type */ - identify_cpu(0, mfspr(SPRN_PVR)); + /* Try new device tree based feature discovery ... */ + if (!dt_cpu_ftrs_init(__va(dt_ptr))) + /* Otherwise use the old style CPU table */ + identify_cpu(0, mfspr(SPRN_PVR)); /* Assume we're on cpu 0 for now. Don't write to the paca yet! */ initialise_paca(&boot_paca, 0); @@ -532,6 +535,9 @@ void __init initialize_cache_info(void) dcache_bsize = ppc64_caches.l1d.block_size; icache_bsize = ppc64_caches.l1i.block_size; + cur_cpu_spec->dcache_bsize = dcache_bsize; + cur_cpu_spec->icache_bsize = icache_bsize; + DBG(" <- initialize_cache_info()\n"); } -- cgit v1.2.3-59-g8ed1b From 81cddd65b5c82758ea5571a25e31ff6f1f89ff02 Mon Sep 17 00:00:00 2001 From: Kristina Martsenko Date: Wed, 3 May 2017 16:37:45 +0100 Subject: arm64: traps: fix userspace cache maintenance emulation on a tagged pointer When we emulate userspace cache maintenance in the kernel, we can currently send the task a SIGSEGV even though the maintenance was done on a valid address. This happens if the address has a non-zero address tag, and happens to not be mapped in. When we get the address from a user register, we don't currently remove the address tag before performing cache maintenance on it. If the maintenance faults, we end up in either __do_page_fault, where find_vma can't find the VMA if the address has a tag, or in do_translation_fault, where the tagged address will appear to be above TASK_SIZE. In both cases, the address is not mapped in, and the task is sent a SIGSEGV. This patch removes the tag from the address before using it. With this patch, the fault is handled correctly, the address gets mapped in, and the cache maintenance succeeds. As a second bug, if cache maintenance (correctly) fails on an invalid tagged address, the address gets passed into arm64_notify_segfault, where find_vma fails to find the VMA due to the tag, and the wrong si_code may be sent as part of the siginfo_t of the segfault. With this patch, the correct si_code is sent. Fixes: 7dd01aef0557 ("arm64: trap userspace "dc cvau" cache operation on errata-affected core") Cc: # 4.8.x- Acked-by: Will Deacon Signed-off-by: Kristina Martsenko Signed-off-by: Catalin Marinas --- arch/arm64/kernel/traps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index d4d6ae02cd55..0805b44f986a 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -443,7 +443,7 @@ int cpu_enable_cache_maint_trap(void *__unused) } #define __user_cache_maint(insn, address, res) \ - if (untagged_addr(address) >= user_addr_max()) { \ + if (address >= user_addr_max()) { \ res = -EFAULT; \ } else { \ uaccess_ttbr0_enable(); \ @@ -469,7 +469,7 @@ static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs) int crm = (esr & ESR_ELx_SYS64_ISS_CRM_MASK) >> ESR_ELx_SYS64_ISS_CRM_SHIFT; int ret = 0; - address = pt_regs_read_reg(regs, rt); + address = untagged_addr(pt_regs_read_reg(regs, rt)); switch (crm) { case ESR_ELx_SYS64_ISS_CRM_DC_CVAU: /* DC CVAU, gets promoted */ -- cgit v1.2.3-59-g8ed1b From 7dcd9dd8cebe9fa626af7e2358d03a37041a70fb Mon Sep 17 00:00:00 2001 From: Kristina Martsenko Date: Wed, 3 May 2017 16:37:46 +0100 Subject: arm64: hw_breakpoint: fix watchpoint matching for tagged pointers When we take a watchpoint exception, the address that triggered the watchpoint is found in FAR_EL1. We compare it to the address of each configured watchpoint to see which one was hit. The configured watchpoint addresses are untagged, while the address in FAR_EL1 will have an address tag if the data access was done using a tagged address. The tag needs to be removed to compare the address to the watchpoints. Currently we don't remove it, and as a result can report the wrong watchpoint as being hit (specifically, always either the highest TTBR0 watchpoint or lowest TTBR1 watchpoint). This patch removes the tag. Fixes: d50240a5f6ce ("arm64: mm: permit use of tagged pointers at EL0") Cc: # 3.12.x- Acked-by: Mark Rutland Acked-by: Will Deacon Signed-off-by: Kristina Martsenko Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/uaccess.h | 6 +++--- arch/arm64/kernel/hw_breakpoint.c | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index 5308d696311b..0221029e27ff 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -106,9 +106,9 @@ static inline void set_fs(mm_segment_t fs) }) /* - * When dealing with data aborts or instruction traps we may end up with - * a tagged userland pointer. Clear the tag to get a sane pointer to pass - * on to access_ok(), for instance. + * When dealing with data aborts, watchpoints, or instruction traps we may end + * up with a tagged userland pointer. Clear the tag to get a sane pointer to + * pass on to access_ok(), for instance. */ #define untagged_addr(addr) sign_extend64(addr, 55) diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c index 0296e7924240..749f81779420 100644 --- a/arch/arm64/kernel/hw_breakpoint.c +++ b/arch/arm64/kernel/hw_breakpoint.c @@ -36,6 +36,7 @@ #include #include #include +#include /* Breakpoint currently in use for each BRP. */ static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]); @@ -721,6 +722,8 @@ static u64 get_distance_from_watchpoint(unsigned long addr, u64 val, u64 wp_low, wp_high; u32 lens, lene; + addr = untagged_addr(addr); + lens = __ffs(ctrl->len); lene = __fls(ctrl->len); -- cgit v1.2.3-59-g8ed1b From 276e93279a630657fff4b086ba14c95955912dfa Mon Sep 17 00:00:00 2001 From: Kristina Martsenko Date: Wed, 3 May 2017 16:37:47 +0100 Subject: arm64: entry: improve data abort handling of tagged pointers When handling a data abort from EL0, we currently zero the top byte of the faulting address, as we assume the address is a TTBR0 address, which may contain a non-zero address tag. However, the address may be a TTBR1 address, in which case we should not zero the top byte. This patch fixes that. The effect is that the full TTBR1 address is passed to the task's signal handler (or printed out in the kernel log). When handling a data abort from EL1, we leave the faulting address intact, as we assume it's either a TTBR1 address or a TTBR0 address with tag 0x00. This is true as far as I'm aware, we don't seem to access a tagged TTBR0 address anywhere in the kernel. Regardless, it's easy to forget about address tags, and code added in the future may not always remember to remove tags from addresses before accessing them. So add tag handling to the EL1 data abort handler as well. This also makes it consistent with the EL0 data abort handler. Fixes: d50240a5f6ce ("arm64: mm: permit use of tagged pointers at EL0") Cc: # 3.12.x- Reviewed-by: Dave Martin Acked-by: Will Deacon Signed-off-by: Kristina Martsenko Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/asm-uaccess.h | 9 +++++++++ arch/arm64/kernel/entry.S | 5 +++-- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm64/include/asm/asm-uaccess.h b/arch/arm64/include/asm/asm-uaccess.h index df411f3e083c..ecd9788cd298 100644 --- a/arch/arm64/include/asm/asm-uaccess.h +++ b/arch/arm64/include/asm/asm-uaccess.h @@ -62,4 +62,13 @@ alternative_if ARM64_ALT_PAN_NOT_UAO alternative_else_nop_endif .endm +/* + * Remove the address tag from a virtual address, if present. + */ + .macro clear_address_tag, dst, addr + tst \addr, #(1 << 55) + bic \dst, \addr, #(0xff << 56) + csel \dst, \dst, \addr, eq + .endm + #endif diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 43512d4d7df2..b738880350f9 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -428,12 +428,13 @@ el1_da: /* * Data abort handling */ - mrs x0, far_el1 + mrs x3, far_el1 enable_dbg // re-enable interrupts if they were enabled in the aborted context tbnz x23, #7, 1f // PSR_I_BIT enable_irq 1: + clear_address_tag x0, x3 mov x2, sp // struct pt_regs bl do_mem_abort @@ -594,7 +595,7 @@ el0_da: // enable interrupts before calling the main handler enable_dbg_and_irq ct_user_exit - bic x0, x26, #(0xff << 56) + clear_address_tag x0, x26 mov x1, x25 mov x2, sp bl do_mem_abort -- cgit v1.2.3-59-g8ed1b From fee960bed5e857eb126c4e56dd9ff85938356579 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Wed, 3 May 2017 16:09:33 +0100 Subject: arm64: xchg: hazard against entire exchange variable The inline assembly in __XCHG_CASE() uses a +Q constraint to hazard against other accesses to the memory location being exchanged. However, the pointer passed to the constraint is a u8 pointer, and thus the hazard only applies to the first byte of the location. GCC can take advantage of this, assuming that other portions of the location are unchanged, as demonstrated with the following test case: union u { unsigned long l; unsigned int i[2]; }; unsigned long update_char_hazard(union u *u) { unsigned int a, b; a = u->i[1]; asm ("str %1, %0" : "+Q" (*(char *)&u->l) : "r" (0UL)); b = u->i[1]; return a ^ b; } unsigned long update_long_hazard(union u *u) { unsigned int a, b; a = u->i[1]; asm ("str %1, %0" : "+Q" (*(long *)&u->l) : "r" (0UL)); b = u->i[1]; return a ^ b; } The linaro 15.08 GCC 5.1.1 toolchain compiles the above as follows when using -O2 or above: 0000000000000000 : 0: d2800001 mov x1, #0x0 // #0 4: f9000001 str x1, [x0] 8: d2800000 mov x0, #0x0 // #0 c: d65f03c0 ret 0000000000000010 : 10: b9400401 ldr w1, [x0,#4] 14: d2800002 mov x2, #0x0 // #0 18: f9000002 str x2, [x0] 1c: b9400400 ldr w0, [x0,#4] 20: 4a000020 eor w0, w1, w0 24: d65f03c0 ret This patch fixes the issue by passing an unsigned long pointer into the +Q constraint, as we do for our cmpxchg code. This may hazard against more than is necessary, but this is better than missing a necessary hazard. Fixes: 305d454aaa29 ("arm64: atomics: implement native {relaxed, acquire, release} atomics") Cc: # 4.4.x- Acked-by: Will Deacon Signed-off-by: Mark Rutland Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/cmpxchg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm64/include/asm/cmpxchg.h b/arch/arm64/include/asm/cmpxchg.h index 91b26d26af8a..ae852add053d 100644 --- a/arch/arm64/include/asm/cmpxchg.h +++ b/arch/arm64/include/asm/cmpxchg.h @@ -46,7 +46,7 @@ static inline unsigned long __xchg_case_##name(unsigned long x, \ " swp" #acq_lse #rel #sz "\t%" #w "3, %" #w "0, %2\n" \ __nops(3) \ " " #nop_lse) \ - : "=&r" (ret), "=&r" (tmp), "+Q" (*(u8 *)ptr) \ + : "=&r" (ret), "=&r" (tmp), "+Q" (*(unsigned long *)ptr) \ : "r" (x) \ : cl); \ \ -- cgit v1.2.3-59-g8ed1b From 994870bead4ab19087a79492400a5478e2906196 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Wed, 3 May 2017 16:09:34 +0100 Subject: arm64: ensure extension of smp_store_release value When an inline assembly operand's type is narrower than the register it is allocated to, the least significant bits of the register (up to the operand type's width) are valid, and any other bits are permitted to contain any arbitrary value. This aligns with the AAPCS64 parameter passing rules. Our __smp_store_release() implementation does not account for this, and implicitly assumes that operands have been zero-extended to the width of the type being stored to. Thus, we may store unknown values to memory when the value type is narrower than the pointer type (e.g. when storing a char to a long). This patch fixes the issue by casting the value operand to the same width as the pointer operand in all cases, which ensures that the value is zero-extended as we expect. We use the same union trickery as __smp_load_acquire and {READ,WRITE}_ONCE() to avoid GCC complaining that pointers are potentially cast to narrower width integers in unreachable paths. A whitespace issue at the top of __smp_store_release() is also corrected. No changes are necessary for __smp_load_acquire(). Load instructions implicitly clear any upper bits of the register, and the compiler will only consider the least significant bits of the register as valid regardless. Fixes: 47933ad41a86 ("arch: Introduce smp_load_acquire(), smp_store_release()") Fixes: 878a84d5a8a1 ("arm64: add missing data types in smp_load_acquire/smp_store_release") Cc: # 3.14.x- Acked-by: Will Deacon Signed-off-by: Mark Rutland Cc: Matthias Kaehlcke Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/barrier.h | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h index 4e0497f581a0..0fe7e43b7fbc 100644 --- a/arch/arm64/include/asm/barrier.h +++ b/arch/arm64/include/asm/barrier.h @@ -42,25 +42,35 @@ #define __smp_rmb() dmb(ishld) #define __smp_wmb() dmb(ishst) -#define __smp_store_release(p, v) \ +#define __smp_store_release(p, v) \ do { \ + union { typeof(*p) __val; char __c[1]; } __u = \ + { .__val = (__force typeof(*p)) (v) }; \ compiletime_assert_atomic_type(*p); \ switch (sizeof(*p)) { \ case 1: \ asm volatile ("stlrb %w1, %0" \ - : "=Q" (*p) : "r" (v) : "memory"); \ + : "=Q" (*p) \ + : "r" (*(__u8 *)__u.__c) \ + : "memory"); \ break; \ case 2: \ asm volatile ("stlrh %w1, %0" \ - : "=Q" (*p) : "r" (v) : "memory"); \ + : "=Q" (*p) \ + : "r" (*(__u16 *)__u.__c) \ + : "memory"); \ break; \ case 4: \ asm volatile ("stlr %w1, %0" \ - : "=Q" (*p) : "r" (v) : "memory"); \ + : "=Q" (*p) \ + : "r" (*(__u32 *)__u.__c) \ + : "memory"); \ break; \ case 8: \ asm volatile ("stlr %1, %0" \ - : "=Q" (*p) : "r" (v) : "memory"); \ + : "=Q" (*p) \ + : "r" (*(__u64 *)__u.__c) \ + : "memory"); \ break; \ } \ } while (0) -- cgit v1.2.3-59-g8ed1b From a06040d7a791a9177581dcf7293941bd92400856 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Wed, 3 May 2017 16:09:35 +0100 Subject: arm64: uaccess: ensure extension of access_ok() addr Our access_ok() simply hands its arguments over to __range_ok(), which implicitly assummes that the addr parameter is 64 bits wide. This isn't necessarily true for compat code, which might pass down a 32-bit address parameter. In these cases, we don't have a guarantee that the address has been zero extended to 64 bits, and the upper bits of the register may contain unknown values, potentially resulting in a suprious failure. Avoid this by explicitly casting the addr parameter to an unsigned long (as is done on other architectures), ensuring that the parameter is widened appropriately. Fixes: 0aea86a2176c ("arm64: User access library functions") Cc: # 3.7.x- Acked-by: Will Deacon Signed-off-by: Mark Rutland Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/uaccess.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index 0221029e27ff..e6540471dcda 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -95,11 +95,12 @@ static inline void set_fs(mm_segment_t fs) */ #define __range_ok(addr, size) \ ({ \ + unsigned long __addr = (unsigned long __force)(addr); \ unsigned long flag, roksum; \ __chk_user_ptr(addr); \ asm("adds %1, %1, %3; ccmp %1, %4, #2, cc; cset %0, ls" \ : "=&r" (flag), "=&r" (roksum) \ - : "1" (addr), "Ir" (size), \ + : "1" (__addr), "Ir" (size), \ "r" (current_thread_info()->addr_limit) \ : "cc"); \ flag; \ -- cgit v1.2.3-59-g8ed1b From 55de49f9aa17b0b2b144dd2af587177b9aadf429 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Wed, 3 May 2017 16:09:36 +0100 Subject: arm64: armv8_deprecated: ensure extension of addr Our compat swp emulation holds the compat user address in an unsigned int, which it passes to __user_swpX_asm(). When a 32-bit value is passed in a register, the upper 32 bits of the register are unknown, and we must extend the value to 64 bits before we can use it as a base address. This patch casts the address to unsigned long to ensure it has been suitably extended, avoiding the potential issue, and silencing a related warning from clang. Fixes: bd35a4adc413 ("arm64: Port SWP/SWPB emulation support from arm") Cc: # 3.19.x- Acked-by: Will Deacon Signed-off-by: Mark Rutland Signed-off-by: Catalin Marinas --- arch/arm64/kernel/armv8_deprecated.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c index 657977e77ec8..f0e6d717885b 100644 --- a/arch/arm64/kernel/armv8_deprecated.c +++ b/arch/arm64/kernel/armv8_deprecated.c @@ -306,7 +306,8 @@ do { \ _ASM_EXTABLE(0b, 4b) \ _ASM_EXTABLE(1b, 4b) \ : "=&r" (res), "+r" (data), "=&r" (temp), "=&r" (temp2) \ - : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT), \ + : "r" ((unsigned long)addr), "i" (-EAGAIN), \ + "i" (-EFAULT), \ "i" (__SWP_LL_SC_LOOPS) \ : "memory"); \ uaccess_disable(); \ -- cgit v1.2.3-59-g8ed1b From 8997c93452d16aac11d3b0cc53940c94330273a4 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Wed, 3 May 2017 16:09:37 +0100 Subject: arm64: atomic_lse: match asm register sizes The LSE atomic code uses asm register variables to ensure that parameters are allocated in specific registers. In the majority of cases we specifically ask for an x register when using 64-bit values, but in a couple of cases we use a w regsiter for a 64-bit value. For asm register variables, the compiler only cares about the register index, with wN and xN having the same meaning. The compiler determines the register size to use based on the type of the variable. Thus, this inconsistency is merely confusing, and not harmful to code generation. For consistency, this patch updates those cases to use the x register alias. There should be no functional change as a result of this patch. Acked-by: Will Deacon Signed-off-by: Mark Rutland Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/atomic_lse.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm64/include/asm/atomic_lse.h b/arch/arm64/include/asm/atomic_lse.h index 7457ce082b5f..99fa69c9c3cf 100644 --- a/arch/arm64/include/asm/atomic_lse.h +++ b/arch/arm64/include/asm/atomic_lse.h @@ -322,7 +322,7 @@ static inline void atomic64_and(long i, atomic64_t *v) #define ATOMIC64_FETCH_OP_AND(name, mb, cl...) \ static inline long atomic64_fetch_and##name(long i, atomic64_t *v) \ { \ - register long x0 asm ("w0") = i; \ + register long x0 asm ("x0") = i; \ register atomic64_t *x1 asm ("x1") = v; \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ @@ -394,7 +394,7 @@ ATOMIC64_OP_SUB_RETURN( , al, "memory") #define ATOMIC64_FETCH_OP_SUB(name, mb, cl...) \ static inline long atomic64_fetch_sub##name(long i, atomic64_t *v) \ { \ - register long x0 asm ("w0") = i; \ + register long x0 asm ("x0") = i; \ register atomic64_t *x1 asm ("x1") = v; \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ -- cgit v1.2.3-59-g8ed1b From d135b8b5060ea91dd751ff172d179eb4eab1e966 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Wed, 3 May 2017 16:09:38 +0100 Subject: arm64: uaccess: suppress spurious clang warning Clang tries to warn when there's a mismatch between an operand's size, and the size of the register it is held in, as this may indicate a bug. Specifically, clang warns when the operand's type is less than 64 bits wide, and the register is used unqualified (i.e. %N rather than %xN or %wN). Unfortunately clang can generate these warnings for unreachable code. For example, for code like: do { \ typeof(*(ptr)) __v = (v); \ switch(sizeof(*(ptr))) { \ case 1: \ // assume __v is 1 byte wide \ asm ("{op}b %w0" : : "r" (v)); \ break; \ case 8: \ // assume __v is 8 bytes wide \ asm ("{op} %0" : : "r" (v)); \ break; \ } while (0) ... if op() were passed a char value and pointer to char, clang may produce a warning for the unreachable case where sizeof(*(ptr)) is 8. For the same reasons, clang produces warnings when __put_user_err() is used for types that are less than 64 bits wide. We could avoid this with a cast to a fixed-width type in each of the cases. However, GCC will then warn that pointer types are being cast to mismatched integer sizes (in unreachable paths). Another option would be to use the same union trickery as we do for __smp_store_release() and __smp_load_acquire(), but this is fairly invasive. Instead, this patch suppresses the clang warning by using an x modifier in the assembly for the 8 byte case of __put_user_err(). No additional work is necessary as the value has been cast to typeof(*(ptr)), so the compiler will have performed any necessary extension for the reachable case. For consistency, __get_user_err() is also updated to use the x modifier for its 8 byte case. Acked-by: Will Deacon Signed-off-by: Mark Rutland Reported-by: Matthias Kaehlcke Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/uaccess.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index e6540471dcda..90b5755c5003 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -257,7 +257,7 @@ do { \ (err), ARM64_HAS_UAO); \ break; \ case 8: \ - __get_user_asm("ldr", "ldtr", "%", __gu_val, (ptr), \ + __get_user_asm("ldr", "ldtr", "%x", __gu_val, (ptr), \ (err), ARM64_HAS_UAO); \ break; \ default: \ @@ -324,7 +324,7 @@ do { \ (err), ARM64_HAS_UAO); \ break; \ case 8: \ - __put_user_asm("str", "sttr", "%", __pu_val, (ptr), \ + __put_user_asm("str", "sttr", "%x", __pu_val, (ptr), \ (err), ARM64_HAS_UAO); \ break; \ default: \ -- cgit v1.2.3-59-g8ed1b From 8376efd31d3d7c44bd05be337adde023cc531fa1 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 9 May 2017 18:00:43 +0100 Subject: x86, pmem: Fix cache flushing for iovec write < 8 bytes Commit 11e63f6d920d added cache flushing for unaligned writes from an iovec, covering the first and last cache line of a >= 8 byte write and the first cache line of a < 8 byte write. But an unaligned write of 2-7 bytes can still cover two cache lines, so make sure we flush both in that case. Cc: Fixes: 11e63f6d920d ("x86, pmem: fix broken __copy_user_nocache ...") Signed-off-by: Ben Hutchings Signed-off-by: Dan Williams --- arch/x86/include/asm/pmem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/include/asm/pmem.h b/arch/x86/include/asm/pmem.h index d5a22bac9988..0ff8fe71b255 100644 --- a/arch/x86/include/asm/pmem.h +++ b/arch/x86/include/asm/pmem.h @@ -98,7 +98,7 @@ static inline size_t arch_copy_from_iter_pmem(void *addr, size_t bytes, if (bytes < 8) { if (!IS_ALIGNED(dest, 4) || (bytes != 4)) - arch_wb_cache_pmem(addr, 1); + arch_wb_cache_pmem(addr, bytes); } else { if (!IS_ALIGNED(dest, 8)) { dest = ALIGN(dest, boot_cpu_data.x86_clflush_size); -- cgit v1.2.3-59-g8ed1b From aed74ea0a09d2e60e4b3fe45caf30f6365b6c9f3 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Sat, 6 May 2017 23:40:20 +0800 Subject: sparc: use memdup_user_nul in sun4m LED driver Use memdup_user_nul() helper instead of open-coding to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: David S. Miller --- arch/sparc/kernel/led.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/led.c b/arch/sparc/kernel/led.c index 44a3ed93c214..e278bf52963b 100644 --- a/arch/sparc/kernel/led.c +++ b/arch/sparc/kernel/led.c @@ -70,16 +70,9 @@ static ssize_t led_proc_write(struct file *file, const char __user *buffer, if (count > LED_MAX_LENGTH) count = LED_MAX_LENGTH; - buf = kmalloc(sizeof(char) * (count + 1), GFP_KERNEL); - if (!buf) - return -ENOMEM; - - if (copy_from_user(buf, buffer, count)) { - kfree(buf); - return -EFAULT; - } - - buf[count] = '\0'; + buf = memdup_user_nul(buffer, count); + if (IS_ERR(buf)) + return PTR_ERR(buf); /* work around \n when echo'ing into proc */ if (buf[count - 1] == '\n') -- cgit v1.2.3-59-g8ed1b From 3c7f62212018b904ae17f5636ead18a4dca3a88f Mon Sep 17 00:00:00 2001 From: Dave Aldridge Date: Tue, 9 May 2017 02:57:35 -0600 Subject: sparc64: fix fault handling in NGbzero.S and GENbzero.S When any of the functions contained in NGbzero.S and GENbzero.S vector through *bzero_from_clear_user, we may end up taking a fault when executing one of the store alternate address space instructions. If this happens, the exception handler does not restore the %asi register. This commit fixes the issue by introducing a new exception handler that ensures the %asi register is restored when a fault is handled. Orabug: 25577560 Signed-off-by: Dave Aldridge Reviewed-by: Rob Gardner Reviewed-by: Babu Moger Signed-off-by: David S. Miller --- arch/sparc/kernel/head_64.S | 6 ++++++ arch/sparc/lib/GENbzero.S | 2 +- arch/sparc/lib/NGbzero.S | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S index 44101196d02b..41a407328667 100644 --- a/arch/sparc/kernel/head_64.S +++ b/arch/sparc/kernel/head_64.S @@ -939,3 +939,9 @@ ENTRY(__retl_o1) retl mov %o1, %o0 ENDPROC(__retl_o1) + +ENTRY(__retl_o1_asi) + wr %o5, 0x0, %asi + retl + mov %o1, %o0 +ENDPROC(__retl_o1_asi) diff --git a/arch/sparc/lib/GENbzero.S b/arch/sparc/lib/GENbzero.S index 8e7a843ddd88..2fbf6297d57c 100644 --- a/arch/sparc/lib/GENbzero.S +++ b/arch/sparc/lib/GENbzero.S @@ -8,7 +8,7 @@ 98: x,y; \ .section __ex_table,"a";\ .align 4; \ - .word 98b, __retl_o1; \ + .word 98b, __retl_o1_asi;\ .text; \ .align 4; diff --git a/arch/sparc/lib/NGbzero.S b/arch/sparc/lib/NGbzero.S index beab29bf419b..33053bdf3766 100644 --- a/arch/sparc/lib/NGbzero.S +++ b/arch/sparc/lib/NGbzero.S @@ -8,7 +8,7 @@ 98: x,y; \ .section __ex_table,"a";\ .align 4; \ - .word 98b, __retl_o1; \ + .word 98b, __retl_o1_asi;\ .text; \ .align 4; -- cgit v1.2.3-59-g8ed1b From 37835671c43b82bdfed628a6a37284a117bda17d Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Mon, 27 Mar 2017 14:20:06 +0200 Subject: h8300: put bitsperlong.h in uapi This header file is exported, thus move it to uapi. Signed-off-by: Nicolas Dichtel Signed-off-by: Masahiro Yamada --- arch/h8300/include/asm/bitsperlong.h | 14 -------------- arch/h8300/include/uapi/asm/bitsperlong.h | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 14 deletions(-) delete mode 100644 arch/h8300/include/asm/bitsperlong.h create mode 100644 arch/h8300/include/uapi/asm/bitsperlong.h (limited to 'arch') diff --git a/arch/h8300/include/asm/bitsperlong.h b/arch/h8300/include/asm/bitsperlong.h deleted file mode 100644 index e140e46729ac..000000000000 --- a/arch/h8300/include/asm/bitsperlong.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __ASM_H8300_BITS_PER_LONG -#define __ASM_H8300_BITS_PER_LONG - -#include - -#if !defined(__ASSEMBLY__) -/* h8300-unknown-linux required long */ -#define __kernel_size_t __kernel_size_t -typedef unsigned long __kernel_size_t; -typedef long __kernel_ssize_t; -typedef long __kernel_ptrdiff_t; -#endif - -#endif /* __ASM_H8300_BITS_PER_LONG */ diff --git a/arch/h8300/include/uapi/asm/bitsperlong.h b/arch/h8300/include/uapi/asm/bitsperlong.h new file mode 100644 index 000000000000..34212608371e --- /dev/null +++ b/arch/h8300/include/uapi/asm/bitsperlong.h @@ -0,0 +1,14 @@ +#ifndef _UAPI__ASM_H8300_BITS_PER_LONG +#define _UAPI__ASM_H8300_BITS_PER_LONG + +#include + +#if !defined(__ASSEMBLY__) +/* h8300-unknown-linux required long */ +#define __kernel_size_t __kernel_size_t +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +#endif + +#endif /* _UAPI__ASM_H8300_BITS_PER_LONG */ -- cgit v1.2.3-59-g8ed1b From 4f4ddad395b04c051fcf76687dd558228e605b6f Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Mon, 27 Mar 2017 14:20:07 +0200 Subject: nios2: put setup.h in uapi This header file is exported, but from a userland pov, it's just a wrapper to asm-generic/setup.h. Signed-off-by: Nicolas Dichtel Reviewed-by: Tobias Klauser Signed-off-by: Masahiro Yamada --- arch/nios2/include/uapi/asm/Kbuild | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/nios2/include/uapi/asm/Kbuild b/arch/nios2/include/uapi/asm/Kbuild index e0bb972a50d7..69c965304146 100644 --- a/arch/nios2/include/uapi/asm/Kbuild +++ b/arch/nios2/include/uapi/asm/Kbuild @@ -2,4 +2,5 @@ include include/uapi/asm-generic/Kbuild.asm header-y += elf.h +generic-y += setup.h generic-y += ucontext.h -- cgit v1.2.3-59-g8ed1b From 25dc1d6cc3082aab293e5dad47623b550f7ddd2a Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Mon, 27 Mar 2017 14:20:08 +0200 Subject: x86: stop exporting msr-index.h to userland Even if this file was not in an uapi directory, it was exported because it was listed in the Kbuild file. Fixes: b72e7464e4cf ("x86/uapi: Do not export as part of the user API headers") Suggested-by: Borislav Petkov Signed-off-by: Nicolas Dichtel Acked-by: Ingo Molnar Acked-by: Thomas Gleixner Signed-off-by: Masahiro Yamada --- arch/x86/include/uapi/asm/Kbuild | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/include/uapi/asm/Kbuild b/arch/x86/include/uapi/asm/Kbuild index 3dec769cadf7..1c532b3f18ea 100644 --- a/arch/x86/include/uapi/asm/Kbuild +++ b/arch/x86/include/uapi/asm/Kbuild @@ -27,7 +27,6 @@ header-y += ldt.h header-y += mce.h header-y += mman.h header-y += msgbuf.h -header-y += msr-index.h header-y += msr.h header-y += mtrr.h header-y += param.h -- cgit v1.2.3-59-g8ed1b From fcc8487d477a3452a1d0ccbdd4c5e0e1e3cb8bed Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Mon, 27 Mar 2017 14:20:15 +0200 Subject: uapi: export all headers under uapi directories Regularly, when a new header is created in include/uapi/, the developer forgets to add it in the corresponding Kbuild file. This error is usually detected after the release is out. In fact, all headers under uapi directories should be exported, thus it's useless to have an exhaustive list. After this patch, the following files, which were not exported, are now exported (with make headers_install_all): asm-arc/kvm_para.h asm-arc/ucontext.h asm-blackfin/shmparam.h asm-blackfin/ucontext.h asm-c6x/shmparam.h asm-c6x/ucontext.h asm-cris/kvm_para.h asm-h8300/shmparam.h asm-h8300/ucontext.h asm-hexagon/shmparam.h asm-m32r/kvm_para.h asm-m68k/kvm_para.h asm-m68k/shmparam.h asm-metag/kvm_para.h asm-metag/shmparam.h asm-metag/ucontext.h asm-mips/hwcap.h asm-mips/reg.h asm-mips/ucontext.h asm-nios2/kvm_para.h asm-nios2/ucontext.h asm-openrisc/shmparam.h asm-parisc/kvm_para.h asm-powerpc/perf_regs.h asm-sh/kvm_para.h asm-sh/ucontext.h asm-tile/shmparam.h asm-unicore32/shmparam.h asm-unicore32/ucontext.h asm-x86/hwcap2.h asm-xtensa/kvm_para.h drm/armada_drm.h drm/etnaviv_drm.h drm/vgem_drm.h linux/aspeed-lpc-ctrl.h linux/auto_dev-ioctl.h linux/bcache.h linux/btrfs_tree.h linux/can/vxcan.h linux/cifs/cifs_mount.h linux/coresight-stm.h linux/cryptouser.h linux/fsmap.h linux/genwqe/genwqe_card.h linux/hash_info.h linux/kcm.h linux/kcov.h linux/kfd_ioctl.h linux/lightnvm.h linux/module.h linux/nbd-netlink.h linux/nilfs2_api.h linux/nilfs2_ondisk.h linux/nsfs.h linux/pr.h linux/qrtr.h linux/rpmsg.h linux/sched/types.h linux/sed-opal.h linux/smc.h linux/smc_diag.h linux/stm.h linux/switchtec_ioctl.h linux/vfio_ccw.h linux/wil6210_uapi.h rdma/bnxt_re-abi.h Note that I have removed from this list the files which are generated in every exported directories (like .install or .install.cmd). Thanks to Julien Floret for the tip to get all subdirs with a pure makefile command. For the record, note that exported files for asm directories are a mix of files listed by: - include/uapi/asm-generic/Kbuild.asm; - arch//include/uapi/asm/Kbuild; - arch//include/asm/Kbuild. Signed-off-by: Nicolas Dichtel Acked-by: Daniel Vetter Acked-by: Russell King Acked-by: Mark Salter Acked-by: Michael Ellerman (powerpc) Signed-off-by: Masahiro Yamada --- Documentation/kbuild/makefiles.txt | 66 ++-- arch/alpha/include/uapi/asm/Kbuild | 41 --- arch/arc/include/uapi/asm/Kbuild | 3 - arch/arm/include/uapi/asm/Kbuild | 17 - arch/arm64/include/uapi/asm/Kbuild | 18 - arch/blackfin/include/uapi/asm/Kbuild | 17 - arch/c6x/include/uapi/asm/Kbuild | 8 - arch/cris/include/uapi/arch-v10/arch/Kbuild | 5 - arch/cris/include/uapi/arch-v32/arch/Kbuild | 3 - arch/cris/include/uapi/asm/Kbuild | 43 +-- arch/frv/include/uapi/asm/Kbuild | 33 -- arch/h8300/include/uapi/asm/Kbuild | 28 -- arch/hexagon/include/asm/Kbuild | 3 - arch/hexagon/include/uapi/asm/Kbuild | 13 - arch/ia64/include/uapi/asm/Kbuild | 45 --- arch/m32r/include/uapi/asm/Kbuild | 31 -- arch/m68k/include/uapi/asm/Kbuild | 24 -- arch/metag/include/uapi/asm/Kbuild | 8 - arch/microblaze/include/uapi/asm/Kbuild | 32 -- arch/mips/include/uapi/asm/Kbuild | 37 --- arch/mn10300/include/uapi/asm/Kbuild | 32 -- arch/nios2/include/uapi/asm/Kbuild | 3 +- arch/openrisc/include/asm/Kbuild | 3 - arch/openrisc/include/uapi/asm/Kbuild | 8 - arch/parisc/include/uapi/asm/Kbuild | 28 -- arch/powerpc/include/uapi/asm/Kbuild | 45 --- arch/s390/include/uapi/asm/Kbuild | 46 --- arch/score/include/asm/Kbuild | 3 - arch/score/include/uapi/asm/Kbuild | 32 -- arch/sh/include/uapi/asm/Kbuild | 23 -- arch/sparc/include/uapi/asm/Kbuild | 48 --- arch/tile/include/asm/Kbuild | 3 - arch/tile/include/uapi/arch/Kbuild | 17 - arch/tile/include/uapi/asm/Kbuild | 19 +- arch/unicore32/include/uapi/asm/Kbuild | 6 - arch/x86/include/uapi/asm/Kbuild | 58 ---- arch/xtensa/include/uapi/asm/Kbuild | 23 -- include/Kbuild | 2 - include/asm-generic/Kbuild.asm | 1 - include/scsi/fc/Kbuild | 0 include/uapi/Kbuild | 15 - include/uapi/asm-generic/Kbuild | 36 -- include/uapi/asm-generic/Kbuild.asm | 76 ++--- include/uapi/drm/Kbuild | 23 -- include/uapi/linux/Kbuild | 494 +--------------------------- include/uapi/linux/android/Kbuild | 2 - include/uapi/linux/byteorder/Kbuild | 3 - include/uapi/linux/caif/Kbuild | 3 - include/uapi/linux/can/Kbuild | 6 - include/uapi/linux/dvb/Kbuild | 9 - include/uapi/linux/hdlc/Kbuild | 2 - include/uapi/linux/hsi/Kbuild | 2 - include/uapi/linux/iio/Kbuild | 3 - include/uapi/linux/isdn/Kbuild | 2 - include/uapi/linux/mmc/Kbuild | 2 - include/uapi/linux/netfilter/Kbuild | 89 ----- include/uapi/linux/netfilter/ipset/Kbuild | 5 - include/uapi/linux/netfilter_arp/Kbuild | 3 - include/uapi/linux/netfilter_bridge/Kbuild | 18 - include/uapi/linux/netfilter_ipv4/Kbuild | 10 - include/uapi/linux/netfilter_ipv6/Kbuild | 13 - include/uapi/linux/nfsd/Kbuild | 6 - include/uapi/linux/raid/Kbuild | 3 - include/uapi/linux/spi/Kbuild | 2 - include/uapi/linux/sunrpc/Kbuild | 2 - include/uapi/linux/tc_act/Kbuild | 16 - include/uapi/linux/tc_ematch/Kbuild | 5 - include/uapi/linux/usb/Kbuild | 12 - include/uapi/linux/wimax/Kbuild | 2 - include/uapi/misc/Kbuild | 2 - include/uapi/mtd/Kbuild | 6 - include/uapi/rdma/Kbuild | 20 -- include/uapi/rdma/hfi/Kbuild | 3 - include/uapi/scsi/Kbuild | 6 - include/uapi/scsi/fc/Kbuild | 5 - include/uapi/sound/Kbuild | 16 - include/uapi/video/Kbuild | 4 - include/uapi/xen/Kbuild | 5 - include/video/Kbuild | 0 scripts/Makefile.headersinst | 55 ++-- 80 files changed, 111 insertions(+), 1750 deletions(-) delete mode 100644 arch/cris/include/uapi/arch-v10/arch/Kbuild delete mode 100644 arch/cris/include/uapi/arch-v32/arch/Kbuild delete mode 100644 arch/tile/include/uapi/arch/Kbuild delete mode 100644 include/Kbuild delete mode 100644 include/asm-generic/Kbuild.asm delete mode 100644 include/scsi/fc/Kbuild delete mode 100644 include/uapi/Kbuild delete mode 100644 include/uapi/asm-generic/Kbuild delete mode 100644 include/uapi/drm/Kbuild delete mode 100644 include/uapi/linux/android/Kbuild delete mode 100644 include/uapi/linux/byteorder/Kbuild delete mode 100644 include/uapi/linux/caif/Kbuild delete mode 100644 include/uapi/linux/can/Kbuild delete mode 100644 include/uapi/linux/dvb/Kbuild delete mode 100644 include/uapi/linux/hdlc/Kbuild delete mode 100644 include/uapi/linux/hsi/Kbuild delete mode 100644 include/uapi/linux/iio/Kbuild delete mode 100644 include/uapi/linux/isdn/Kbuild delete mode 100644 include/uapi/linux/mmc/Kbuild delete mode 100644 include/uapi/linux/netfilter/Kbuild delete mode 100644 include/uapi/linux/netfilter/ipset/Kbuild delete mode 100644 include/uapi/linux/netfilter_arp/Kbuild delete mode 100644 include/uapi/linux/netfilter_bridge/Kbuild delete mode 100644 include/uapi/linux/netfilter_ipv4/Kbuild delete mode 100644 include/uapi/linux/netfilter_ipv6/Kbuild delete mode 100644 include/uapi/linux/nfsd/Kbuild delete mode 100644 include/uapi/linux/raid/Kbuild delete mode 100644 include/uapi/linux/spi/Kbuild delete mode 100644 include/uapi/linux/sunrpc/Kbuild delete mode 100644 include/uapi/linux/tc_act/Kbuild delete mode 100644 include/uapi/linux/tc_ematch/Kbuild delete mode 100644 include/uapi/linux/usb/Kbuild delete mode 100644 include/uapi/linux/wimax/Kbuild delete mode 100644 include/uapi/misc/Kbuild delete mode 100644 include/uapi/mtd/Kbuild delete mode 100644 include/uapi/rdma/Kbuild delete mode 100644 include/uapi/rdma/hfi/Kbuild delete mode 100644 include/uapi/scsi/Kbuild delete mode 100644 include/uapi/scsi/fc/Kbuild delete mode 100644 include/uapi/sound/Kbuild delete mode 100644 include/uapi/video/Kbuild delete mode 100644 include/uapi/xen/Kbuild delete mode 100644 include/video/Kbuild (limited to 'arch') diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt index 37b525d329ae..b9f7ca4e62ae 100644 --- a/Documentation/kbuild/makefiles.txt +++ b/Documentation/kbuild/makefiles.txt @@ -44,10 +44,12 @@ This document describes the Linux kernel Makefiles. --- 6.11 Post-link pass === 7 Kbuild syntax for exported headers - --- 7.1 header-y + --- 7.1 no-export-headers --- 7.2 genhdr-y --- 7.3 generic-y --- 7.4 generated-y + --- 7.5 mandatory-y + --- 7.6 subdir-y === 8 Kbuild Variables === 9 Makefile language @@ -1235,7 +1237,7 @@ When kbuild executes, the following steps are followed (roughly): that may be shared between individual architectures. The recommended approach how to use a generic header file is to list the file in the Kbuild file. - See "7.4 generic-y" for further info on syntax etc. + See "7.3 generic-y" for further info on syntax etc. --- 6.11 Post-link pass @@ -1262,37 +1264,30 @@ The pre-processing does: - drop include of compiler.h - drop all sections that are kernel internal (guarded by ifdef __KERNEL__) -Each relevant directory contains a file name "Kbuild" which specifies the -headers to be exported. -See subsequent chapter for the syntax of the Kbuild file. - - --- 7.1 header-y - - header-y specifies header files to be exported. - - Example: - #include/linux/Kbuild - header-y += usb/ - header-y += aio_abi.h +All headers under include/uapi/, include/generated/uapi/, +arch//include/uapi/asm/ and arch//include/generated/uapi/asm/ +are exported. - The convention is to list one file per line and - preferably in alphabetic order. +A Kbuild file may be defined under arch//include/uapi/asm/ and +arch//include/asm/ to list asm files coming from asm-generic. +See subsequent chapter for the syntax of the Kbuild file. - header-y also specifies which subdirectories to visit. - A subdirectory is identified by a trailing '/' which - can be seen in the example above for the usb subdirectory. + --- 7.1 no-export-headers - Subdirectories are visited before their parent directories. + no-export-headers is essentially used by include/uapi/linux/Kbuild to + avoid exporting specific headers (e.g. kvm.h) on architectures that do + not support it. It should be avoided as much as possible. --- 7.2 genhdr-y - genhdr-y specifies generated files to be exported. - Generated files are special as they need to be looked - up in another directory when doing 'make O=...' builds. + genhdr-y specifies asm files to be generated. Example: - #include/linux/Kbuild - genhdr-y += version.h + #arch/x86/include/uapi/asm/Kbuild + genhdr-y += unistd_32.h + genhdr-y += unistd_64.h + genhdr-y += unistd_x32.h + --- 7.3 generic-y @@ -1334,6 +1329,27 @@ See subsequent chapter for the syntax of the Kbuild file. #arch/x86/include/asm/Kbuild generated-y += syscalls_32.h + --- 7.5 mandatory-y + + mandatory-y is essentially used by include/uapi/asm-generic/Kbuild.asm + to define the minimun set of headers that must be exported in + include/asm. + + The convention is to list one subdir per line and + preferably in alphabetic order. + + --- 7.6 subdir-y + + subdir-y may be used to specify a subdirectory to be exported. + + Example: + #arch/cris/include/uapi/asm/Kbuild + subdir-y += ../arch-v10/arch/ + subdir-y += ../arch-v32/arch/ + + The convention is to list one subdir per line and + preferably in alphabetic order. + === 8 Kbuild Variables The top Makefile exports the following variables: diff --git a/arch/alpha/include/uapi/asm/Kbuild b/arch/alpha/include/uapi/asm/Kbuild index d96f2ef5b639..b15bf6bc0e94 100644 --- a/arch/alpha/include/uapi/asm/Kbuild +++ b/arch/alpha/include/uapi/asm/Kbuild @@ -1,43 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += a.out.h -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += compiler.h -header-y += console.h -header-y += errno.h -header-y += fcntl.h -header-y += fpu.h -header-y += gentrap.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += kvm_para.h -header-y += mman.h -header-y += msgbuf.h -header-y += pal.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += reg.h -header-y += regdef.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += sysinfo.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += unistd.h diff --git a/arch/arc/include/uapi/asm/Kbuild b/arch/arc/include/uapi/asm/Kbuild index f50d02df78d5..b15bf6bc0e94 100644 --- a/arch/arc/include/uapi/asm/Kbuild +++ b/arch/arc/include/uapi/asm/Kbuild @@ -1,5 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm -header-y += elf.h -header-y += page.h -header-y += cachectl.h diff --git a/arch/arm/include/uapi/asm/Kbuild b/arch/arm/include/uapi/asm/Kbuild index 46a76cd6acb6..607f702c2d62 100644 --- a/arch/arm/include/uapi/asm/Kbuild +++ b/arch/arm/include/uapi/asm/Kbuild @@ -1,23 +1,6 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm -header-y += auxvec.h -header-y += byteorder.h -header-y += fcntl.h -header-y += hwcap.h -header-y += ioctls.h -header-y += kvm_para.h -header-y += mman.h -header-y += perf_regs.h -header-y += posix_types.h -header-y += ptrace.h -header-y += setup.h -header-y += sigcontext.h -header-y += signal.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += unistd.h genhdr-y += unistd-common.h genhdr-y += unistd-oabi.h genhdr-y += unistd-eabi.h diff --git a/arch/arm64/include/uapi/asm/Kbuild b/arch/arm64/include/uapi/asm/Kbuild index 825b0fe51c2b..13a97aa2285f 100644 --- a/arch/arm64/include/uapi/asm/Kbuild +++ b/arch/arm64/include/uapi/asm/Kbuild @@ -2,21 +2,3 @@ include include/uapi/asm-generic/Kbuild.asm generic-y += kvm_para.h - -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += fcntl.h -header-y += hwcap.h -header-y += kvm_para.h -header-y += perf_regs.h -header-y += param.h -header-y += ptrace.h -header-y += setup.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += stat.h -header-y += statfs.h -header-y += ucontext.h -header-y += unistd.h diff --git a/arch/blackfin/include/uapi/asm/Kbuild b/arch/blackfin/include/uapi/asm/Kbuild index 0bd28f77abc3..b15bf6bc0e94 100644 --- a/arch/blackfin/include/uapi/asm/Kbuild +++ b/arch/blackfin/include/uapi/asm/Kbuild @@ -1,19 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += bfin_sport.h -header-y += byteorder.h -header-y += cachectl.h -header-y += fcntl.h -header-y += fixed_code.h -header-y += ioctls.h -header-y += kvm_para.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += stat.h -header-y += swab.h -header-y += unistd.h diff --git a/arch/c6x/include/uapi/asm/Kbuild b/arch/c6x/include/uapi/asm/Kbuild index e9bc2b2b8147..13a97aa2285f 100644 --- a/arch/c6x/include/uapi/asm/Kbuild +++ b/arch/c6x/include/uapi/asm/Kbuild @@ -2,11 +2,3 @@ include include/uapi/asm-generic/Kbuild.asm generic-y += kvm_para.h - -header-y += byteorder.h -header-y += kvm_para.h -header-y += ptrace.h -header-y += setup.h -header-y += sigcontext.h -header-y += swab.h -header-y += unistd.h diff --git a/arch/cris/include/uapi/arch-v10/arch/Kbuild b/arch/cris/include/uapi/arch-v10/arch/Kbuild deleted file mode 100644 index 9048c87a782b..000000000000 --- a/arch/cris/include/uapi/arch-v10/arch/Kbuild +++ /dev/null @@ -1,5 +0,0 @@ -# UAPI Header export list -header-y += sv_addr.agh -header-y += sv_addr_ag.h -header-y += svinto.h -header-y += user.h diff --git a/arch/cris/include/uapi/arch-v32/arch/Kbuild b/arch/cris/include/uapi/arch-v32/arch/Kbuild deleted file mode 100644 index 59efffd16b61..000000000000 --- a/arch/cris/include/uapi/arch-v32/arch/Kbuild +++ /dev/null @@ -1,3 +0,0 @@ -# UAPI Header export list -header-y += cryptocop.h -header-y += user.h diff --git a/arch/cris/include/uapi/asm/Kbuild b/arch/cris/include/uapi/asm/Kbuild index d5564a0ae66a..d0c5471856e0 100644 --- a/arch/cris/include/uapi/asm/Kbuild +++ b/arch/cris/include/uapi/asm/Kbuild @@ -1,44 +1,5 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm -header-y += ../arch-v10/arch/ -header-y += ../arch-v32/arch/ -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += elf.h -header-y += elf_v10.h -header-y += elf_v32.h -header-y += errno.h -header-y += ethernet.h -header-y += etraxgpio.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += ptrace_v10.h -header-y += ptrace_v32.h -header-y += resource.h -header-y += rs485.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += sync_serial.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += unistd.h +subdir-y += ../arch-v10/arch/ +subdir-y += ../arch-v32/arch/ diff --git a/arch/frv/include/uapi/asm/Kbuild b/arch/frv/include/uapi/asm/Kbuild index 42a2b33461c0..b15bf6bc0e94 100644 --- a/arch/frv/include/uapi/asm/Kbuild +++ b/arch/frv/include/uapi/asm/Kbuild @@ -1,35 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += errno.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += kvm_para.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += registers.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += unistd.h diff --git a/arch/h8300/include/uapi/asm/Kbuild b/arch/h8300/include/uapi/asm/Kbuild index fb6101a5d4f1..b15bf6bc0e94 100644 --- a/arch/h8300/include/uapi/asm/Kbuild +++ b/arch/h8300/include/uapi/asm/Kbuild @@ -1,30 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += auxvec.h -header-y += bitsperlong.h -header-y += errno.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += kvm_para.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += siginfo.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += unistd.h diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild index a2036bfda8af..6b45ef79eb8f 100644 --- a/arch/hexagon/include/asm/Kbuild +++ b/arch/hexagon/include/asm/Kbuild @@ -1,6 +1,3 @@ - -header-y += ucontext.h - generic-y += auxvec.h generic-y += barrier.h generic-y += bug.h diff --git a/arch/hexagon/include/uapi/asm/Kbuild b/arch/hexagon/include/uapi/asm/Kbuild index c31706c38631..b15bf6bc0e94 100644 --- a/arch/hexagon/include/uapi/asm/Kbuild +++ b/arch/hexagon/include/uapi/asm/Kbuild @@ -1,15 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += bitsperlong.h -header-y += byteorder.h -header-y += kvm_para.h -header-y += param.h -header-y += ptrace.h -header-y += registers.h -header-y += setup.h -header-y += sigcontext.h -header-y += signal.h -header-y += swab.h -header-y += unistd.h -header-y += user.h diff --git a/arch/ia64/include/uapi/asm/Kbuild b/arch/ia64/include/uapi/asm/Kbuild index 891002bbb995..13a97aa2285f 100644 --- a/arch/ia64/include/uapi/asm/Kbuild +++ b/arch/ia64/include/uapi/asm/Kbuild @@ -2,48 +2,3 @@ include include/uapi/asm-generic/Kbuild.asm generic-y += kvm_para.h - -header-y += auxvec.h -header-y += bitsperlong.h -header-y += break.h -header-y += byteorder.h -header-y += cmpxchg.h -header-y += errno.h -header-y += fcntl.h -header-y += fpu.h -header-y += gcc_intrin.h -header-y += ia64regs.h -header-y += intel_intrin.h -header-y += intrinsics.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += kvm_para.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += perfmon.h -header-y += perfmon_default_smpl.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += ptrace_offsets.h -header-y += resource.h -header-y += rse.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += ucontext.h -header-y += unistd.h -header-y += ustack.h diff --git a/arch/m32r/include/uapi/asm/Kbuild b/arch/m32r/include/uapi/asm/Kbuild index 43937a61d6cf..b15bf6bc0e94 100644 --- a/arch/m32r/include/uapi/asm/Kbuild +++ b/arch/m32r/include/uapi/asm/Kbuild @@ -1,33 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += errno.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += unistd.h diff --git a/arch/m68k/include/uapi/asm/Kbuild b/arch/m68k/include/uapi/asm/Kbuild index 6a2d257bdfb2..64368077235a 100644 --- a/arch/m68k/include/uapi/asm/Kbuild +++ b/arch/m68k/include/uapi/asm/Kbuild @@ -9,27 +9,3 @@ generic-y += socket.h generic-y += sockios.h generic-y += termbits.h generic-y += termios.h - -header-y += a.out.h -header-y += bootinfo.h -header-y += bootinfo-amiga.h -header-y += bootinfo-apollo.h -header-y += bootinfo-atari.h -header-y += bootinfo-hp300.h -header-y += bootinfo-mac.h -header-y += bootinfo-q40.h -header-y += bootinfo-vme.h -header-y += byteorder.h -header-y += cachectl.h -header-y += fcntl.h -header-y += ioctls.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += setup.h -header-y += sigcontext.h -header-y += signal.h -header-y += stat.h -header-y += swab.h -header-y += unistd.h diff --git a/arch/metag/include/uapi/asm/Kbuild b/arch/metag/include/uapi/asm/Kbuild index ab78be2b6eb0..b29731ebd7a9 100644 --- a/arch/metag/include/uapi/asm/Kbuild +++ b/arch/metag/include/uapi/asm/Kbuild @@ -1,14 +1,6 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm -header-y += byteorder.h -header-y += ech.h -header-y += ptrace.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += swab.h -header-y += unistd.h - generic-y += mman.h generic-y += resource.h generic-y += setup.h diff --git a/arch/microblaze/include/uapi/asm/Kbuild b/arch/microblaze/include/uapi/asm/Kbuild index 1aac99f87df1..2178c78c7c1a 100644 --- a/arch/microblaze/include/uapi/asm/Kbuild +++ b/arch/microblaze/include/uapi/asm/Kbuild @@ -2,35 +2,3 @@ include include/uapi/asm-generic/Kbuild.asm generic-y += types.h - -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += elf.h -header-y += errno.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += kvm_para.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += unistd.h diff --git a/arch/mips/include/uapi/asm/Kbuild b/arch/mips/include/uapi/asm/Kbuild index f2cf41461146..a0266feba9e6 100644 --- a/arch/mips/include/uapi/asm/Kbuild +++ b/arch/mips/include/uapi/asm/Kbuild @@ -2,40 +2,3 @@ include include/uapi/asm-generic/Kbuild.asm generic-y += ipcbuf.h - -header-y += auxvec.h -header-y += bitfield.h -header-y += bitsperlong.h -header-y += break.h -header-y += byteorder.h -header-y += cachectl.h -header-y += errno.h -header-y += fcntl.h -header-y += inst.h -header-y += ioctl.h -header-y += ioctls.h -header-y += kvm_para.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += sgidefs.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += sysmips.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += unistd.h diff --git a/arch/mn10300/include/uapi/asm/Kbuild b/arch/mn10300/include/uapi/asm/Kbuild index 040178cdb3eb..b15bf6bc0e94 100644 --- a/arch/mn10300/include/uapi/asm/Kbuild +++ b/arch/mn10300/include/uapi/asm/Kbuild @@ -1,34 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += errno.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += kvm_para.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += unistd.h diff --git a/arch/nios2/include/uapi/asm/Kbuild b/arch/nios2/include/uapi/asm/Kbuild index 69c965304146..374bd123329f 100644 --- a/arch/nios2/include/uapi/asm/Kbuild +++ b/arch/nios2/include/uapi/asm/Kbuild @@ -1,6 +1,5 @@ +# UAPI Header export list include include/uapi/asm-generic/Kbuild.asm -header-y += elf.h - generic-y += setup.h generic-y += ucontext.h diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild index df8e2f7bc7dd..fdbcf0bf44a4 100644 --- a/arch/openrisc/include/asm/Kbuild +++ b/arch/openrisc/include/asm/Kbuild @@ -1,6 +1,3 @@ - -header-y += ucontext.h - generic-y += auxvec.h generic-y += barrier.h generic-y += bitsperlong.h diff --git a/arch/openrisc/include/uapi/asm/Kbuild b/arch/openrisc/include/uapi/asm/Kbuild index 80761eb82b5f..b15bf6bc0e94 100644 --- a/arch/openrisc/include/uapi/asm/Kbuild +++ b/arch/openrisc/include/uapi/asm/Kbuild @@ -1,10 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += byteorder.h -header-y += elf.h -header-y += kvm_para.h -header-y += param.h -header-y += ptrace.h -header-y += sigcontext.h -header-y += unistd.h diff --git a/arch/parisc/include/uapi/asm/Kbuild b/arch/parisc/include/uapi/asm/Kbuild index 348356c99514..3971c60a7e7f 100644 --- a/arch/parisc/include/uapi/asm/Kbuild +++ b/arch/parisc/include/uapi/asm/Kbuild @@ -2,31 +2,3 @@ include include/uapi/asm-generic/Kbuild.asm generic-y += resource.h - -header-y += bitsperlong.h -header-y += byteorder.h -header-y += errno.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += mman.h -header-y += msgbuf.h -header-y += pdc.h -header-y += posix_types.h -header-y += ptrace.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += unistd.h diff --git a/arch/powerpc/include/uapi/asm/Kbuild b/arch/powerpc/include/uapi/asm/Kbuild index dab3717e3ea0..b15bf6bc0e94 100644 --- a/arch/powerpc/include/uapi/asm/Kbuild +++ b/arch/powerpc/include/uapi/asm/Kbuild @@ -1,47 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += auxvec.h -header-y += bitsperlong.h -header-y += bootx.h -header-y += byteorder.h -header-y += cputable.h -header-y += eeh.h -header-y += elf.h -header-y += epapr_hcalls.h -header-y += errno.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += kvm.h -header-y += kvm_para.h -header-y += mman.h -header-y += msgbuf.h -header-y += nvram.h -header-y += opal-prd.h -header-y += param.h -header-y += perf_event.h -header-y += poll.h -header-y += posix_types.h -header-y += ps3fb.h -header-y += ptrace.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += spu_info.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += tm.h -header-y += types.h -header-y += ucontext.h -header-y += unistd.h diff --git a/arch/s390/include/uapi/asm/Kbuild b/arch/s390/include/uapi/asm/Kbuild index addb09cee0f5..ca62066895e0 100644 --- a/arch/s390/include/uapi/asm/Kbuild +++ b/arch/s390/include/uapi/asm/Kbuild @@ -10,49 +10,3 @@ generic-y += poll.h generic-y += resource.h generic-y += sockios.h generic-y += termbits.h - -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += chpid.h -header-y += chsc.h -header-y += clp.h -header-y += cmb.h -header-y += dasd.h -header-y += debug.h -header-y += errno.h -header-y += guarded_storage.h -header-y += hypfs.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += kvm.h -header-y += kvm_para.h -header-y += kvm_perf.h -header-y += kvm_virtio.h -header-y += monwriter.h -header-y += msgbuf.h -header-y += pkey.h -header-y += posix_types.h -header-y += ptrace.h -header-y += qeth.h -header-y += schid.h -header-y += sclp_ctl.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sie.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += tape390.h -header-y += termios.h -header-y += types.h -header-y += ucontext.h -header-y += unistd.h -header-y += virtio-ccw.h -header-y += vtoc.h -header-y += zcrypt.h diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild index e3a8d0f96652..54b3b2039af1 100644 --- a/arch/score/include/asm/Kbuild +++ b/arch/score/include/asm/Kbuild @@ -1,6 +1,3 @@ - -header-y += - generic-y += barrier.h generic-y += clkdev.h generic-y += current.h diff --git a/arch/score/include/uapi/asm/Kbuild b/arch/score/include/uapi/asm/Kbuild index 040178cdb3eb..b15bf6bc0e94 100644 --- a/arch/score/include/uapi/asm/Kbuild +++ b/arch/score/include/uapi/asm/Kbuild @@ -1,34 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += errno.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += kvm_para.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += unistd.h diff --git a/arch/sh/include/uapi/asm/Kbuild b/arch/sh/include/uapi/asm/Kbuild index 60613ae78513..b15bf6bc0e94 100644 --- a/arch/sh/include/uapi/asm/Kbuild +++ b/arch/sh/include/uapi/asm/Kbuild @@ -1,25 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += auxvec.h -header-y += byteorder.h -header-y += cachectl.h -header-y += cpu-features.h -header-y += hw_breakpoint.h -header-y += ioctls.h -header-y += posix_types.h -header-y += posix_types_32.h -header-y += posix_types_64.h -header-y += ptrace.h -header-y += ptrace_32.h -header-y += ptrace_64.h -header-y += setup.h -header-y += sigcontext.h -header-y += signal.h -header-y += sockios.h -header-y += stat.h -header-y += swab.h -header-y += types.h -header-y += unistd.h -header-y += unistd_32.h -header-y += unistd_64.h diff --git a/arch/sparc/include/uapi/asm/Kbuild b/arch/sparc/include/uapi/asm/Kbuild index b5843ee09fb5..b15bf6bc0e94 100644 --- a/arch/sparc/include/uapi/asm/Kbuild +++ b/arch/sparc/include/uapi/asm/Kbuild @@ -1,50 +1,2 @@ # UAPI Header export list -# User exported sparc header files - include include/uapi/asm-generic/Kbuild.asm - -header-y += apc.h -header-y += asi.h -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += display7seg.h -header-y += envctrl.h -header-y += errno.h -header-y += fbio.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += jsflash.h -header-y += kvm_para.h -header-y += mman.h -header-y += msgbuf.h -header-y += openpromio.h -header-y += param.h -header-y += perfctr.h -header-y += poll.h -header-y += posix_types.h -header-y += psr.h -header-y += psrcompat.h -header-y += pstate.h -header-y += ptrace.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += traps.h -header-y += uctx.h -header-y += unistd.h -header-y += utrap.h -header-y += watchdog.h diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild index 24c44e93804d..16f0b08c8ce9 100644 --- a/arch/tile/include/asm/Kbuild +++ b/arch/tile/include/asm/Kbuild @@ -1,6 +1,3 @@ - -header-y += ../arch/ - generic-y += bug.h generic-y += bugs.h generic-y += clkdev.h diff --git a/arch/tile/include/uapi/arch/Kbuild b/arch/tile/include/uapi/arch/Kbuild deleted file mode 100644 index 97dfbecec6b6..000000000000 --- a/arch/tile/include/uapi/arch/Kbuild +++ /dev/null @@ -1,17 +0,0 @@ -# UAPI Header export list -header-y += abi.h -header-y += chip.h -header-y += chip_tilegx.h -header-y += chip_tilepro.h -header-y += icache.h -header-y += interrupts.h -header-y += interrupts_32.h -header-y += interrupts_64.h -header-y += opcode.h -header-y += opcode_tilegx.h -header-y += opcode_tilepro.h -header-y += sim.h -header-y += sim_def.h -header-y += spr_def.h -header-y += spr_def_32.h -header-y += spr_def_64.h diff --git a/arch/tile/include/uapi/asm/Kbuild b/arch/tile/include/uapi/asm/Kbuild index c20db8e428bf..e0a50111e07f 100644 --- a/arch/tile/include/uapi/asm/Kbuild +++ b/arch/tile/include/uapi/asm/Kbuild @@ -1,21 +1,6 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += cachectl.h -header-y += hardwall.h -header-y += kvm_para.h -header-y += mman.h -header-y += ptrace.h -header-y += setup.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += stat.h -header-y += swab.h -header-y += ucontext.h -header-y += unistd.h - generic-y += ucontext.h + +subdir-y += ../arch diff --git a/arch/unicore32/include/uapi/asm/Kbuild b/arch/unicore32/include/uapi/asm/Kbuild index 0514d7ad6855..13a97aa2285f 100644 --- a/arch/unicore32/include/uapi/asm/Kbuild +++ b/arch/unicore32/include/uapi/asm/Kbuild @@ -1,10 +1,4 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm -header-y += byteorder.h -header-y += kvm_para.h -header-y += ptrace.h -header-y += sigcontext.h -header-y += unistd.h - generic-y += kvm_para.h diff --git a/arch/x86/include/uapi/asm/Kbuild b/arch/x86/include/uapi/asm/Kbuild index 1c532b3f18ea..83b6e9a0dce4 100644 --- a/arch/x86/include/uapi/asm/Kbuild +++ b/arch/x86/include/uapi/asm/Kbuild @@ -4,61 +4,3 @@ include include/uapi/asm-generic/Kbuild.asm genhdr-y += unistd_32.h genhdr-y += unistd_64.h genhdr-y += unistd_x32.h -header-y += a.out.h -header-y += auxvec.h -header-y += bitsperlong.h -header-y += boot.h -header-y += bootparam.h -header-y += byteorder.h -header-y += debugreg.h -header-y += e820.h -header-y += errno.h -header-y += fcntl.h -header-y += hw_breakpoint.h -header-y += hyperv.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += ist.h -header-y += kvm.h -header-y += kvm_para.h -header-y += kvm_perf.h -header-y += ldt.h -header-y += mce.h -header-y += mman.h -header-y += msgbuf.h -header-y += msr.h -header-y += mtrr.h -header-y += param.h -header-y += perf_regs.h -header-y += poll.h -header-y += posix_types.h -header-y += posix_types_32.h -header-y += posix_types_64.h -header-y += posix_types_x32.h -header-y += prctl.h -header-y += processor-flags.h -header-y += ptrace-abi.h -header-y += ptrace.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += sigcontext32.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += svm.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += ucontext.h -header-y += unistd.h -header-y += vm86.h -header-y += vmx.h -header-y += vsyscall.h diff --git a/arch/xtensa/include/uapi/asm/Kbuild b/arch/xtensa/include/uapi/asm/Kbuild index 56aad54e7fb7..b15bf6bc0e94 100644 --- a/arch/xtensa/include/uapi/asm/Kbuild +++ b/arch/xtensa/include/uapi/asm/Kbuild @@ -1,25 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += auxvec.h -header-y += byteorder.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += swab.h -header-y += termbits.h -header-y += types.h -header-y += unistd.h diff --git a/include/Kbuild b/include/Kbuild deleted file mode 100644 index bab1145bc7a7..000000000000 --- a/include/Kbuild +++ /dev/null @@ -1,2 +0,0 @@ -# Top-level Makefile calls into asm-$(ARCH) -# List only non-arch directories below diff --git a/include/asm-generic/Kbuild.asm b/include/asm-generic/Kbuild.asm deleted file mode 100644 index d2ee86b4c091..000000000000 --- a/include/asm-generic/Kbuild.asm +++ /dev/null @@ -1 +0,0 @@ -include include/uapi/asm-generic/Kbuild.asm diff --git a/include/scsi/fc/Kbuild b/include/scsi/fc/Kbuild deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/include/uapi/Kbuild b/include/uapi/Kbuild deleted file mode 100644 index 245aa6e05e6a..000000000000 --- a/include/uapi/Kbuild +++ /dev/null @@ -1,15 +0,0 @@ -# UAPI Header export list -# Top-level Makefile calls into asm-$(ARCH) -# List only non-arch directories below - - -header-y += asm-generic/ -header-y += linux/ -header-y += sound/ -header-y += mtd/ -header-y += rdma/ -header-y += video/ -header-y += drm/ -header-y += xen/ -header-y += scsi/ -header-y += misc/ diff --git a/include/uapi/asm-generic/Kbuild b/include/uapi/asm-generic/Kbuild deleted file mode 100644 index b73de7bb7a62..000000000000 --- a/include/uapi/asm-generic/Kbuild +++ /dev/null @@ -1,36 +0,0 @@ -# UAPI Header export list -header-y += auxvec.h -header-y += bitsperlong.h -header-y += errno-base.h -header-y += errno.h -header-y += fcntl.h -header-y += int-l64.h -header-y += int-ll64.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += kvm_para.h -header-y += mman-common.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += shmparam.h -header-y += siginfo.h -header-y += signal-defs.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += ucontext.h -header-y += unistd.h diff --git a/include/uapi/asm-generic/Kbuild.asm b/include/uapi/asm-generic/Kbuild.asm index fcd50b759217..21381449d98a 100644 --- a/include/uapi/asm-generic/Kbuild.asm +++ b/include/uapi/asm-generic/Kbuild.asm @@ -1,49 +1,33 @@ -# -# Headers that are optional in usr/include/asm/ -# -opt-header += kvm.h -opt-header += kvm_para.h -opt-header += a.out.h - # # Headers that are mandatory in usr/include/asm/ # -header-y += auxvec.h -header-y += bitsperlong.h -header-y += byteorder.h -header-y += errno.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += resource.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += siginfo.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += statfs.h -header-y += swab.h -header-y += termbits.h -header-y += termios.h -header-y += types.h -header-y += unistd.h - -header-y += $(foreach hdr,$(opt-header), \ - $(if \ - $(wildcard \ - $(srctree)/arch/$(SRCARCH)/include/uapi/asm/$(hdr) \ - $(srctree)/arch/$(SRCARCH)/include/asm/$(hdr) \ - ), \ - $(hdr) \ - )) +mandatory-y += auxvec.h +mandatory-y += bitsperlong.h +mandatory-y += byteorder.h +mandatory-y += errno.h +mandatory-y += fcntl.h +mandatory-y += ioctl.h +mandatory-y += ioctls.h +mandatory-y += ipcbuf.h +mandatory-y += mman.h +mandatory-y += msgbuf.h +mandatory-y += param.h +mandatory-y += poll.h +mandatory-y += posix_types.h +mandatory-y += ptrace.h +mandatory-y += resource.h +mandatory-y += sembuf.h +mandatory-y += setup.h +mandatory-y += shmbuf.h +mandatory-y += sigcontext.h +mandatory-y += siginfo.h +mandatory-y += signal.h +mandatory-y += socket.h +mandatory-y += sockios.h +mandatory-y += stat.h +mandatory-y += statfs.h +mandatory-y += swab.h +mandatory-y += termbits.h +mandatory-y += termios.h +mandatory-y += types.h +mandatory-y += unistd.h diff --git a/include/uapi/drm/Kbuild b/include/uapi/drm/Kbuild deleted file mode 100644 index c97addd08f8c..000000000000 --- a/include/uapi/drm/Kbuild +++ /dev/null @@ -1,23 +0,0 @@ -# UAPI Header export list -header-y += drm.h -header-y += drm_fourcc.h -header-y += drm_mode.h -header-y += drm_sarea.h -header-y += amdgpu_drm.h -header-y += exynos_drm.h -header-y += i810_drm.h -header-y += i915_drm.h -header-y += mga_drm.h -header-y += nouveau_drm.h -header-y += omap_drm.h -header-y += qxl_drm.h -header-y += r128_drm.h -header-y += radeon_drm.h -header-y += savage_drm.h -header-y += sis_drm.h -header-y += tegra_drm.h -header-y += via_drm.h -header-y += vmwgfx_drm.h -header-y += msm_drm.h -header-y += vc4_drm.h -header-y += virtgpu_drm.h diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild index 662c592b74dd..ca2787d9bf0f 100644 --- a/include/uapi/linux/Kbuild +++ b/include/uapi/linux/Kbuild @@ -1,495 +1,13 @@ # UAPI Header export list -header-y += android/ -header-y += byteorder/ -header-y += can/ -header-y += caif/ -header-y += dvb/ -header-y += hdlc/ -header-y += hsi/ -header-y += iio/ -header-y += isdn/ -header-y += mmc/ -header-y += nfsd/ -header-y += raid/ -header-y += spi/ -header-y += sunrpc/ -header-y += tc_act/ -header-y += tc_ematch/ -header-y += netfilter/ -header-y += netfilter_arp/ -header-y += netfilter_bridge/ -header-y += netfilter_ipv4/ -header-y += netfilter_ipv6/ -header-y += usb/ -header-y += wimax/ -genhdr-y += version.h - -ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/uapi/asm/a.out.h \ - $(srctree)/arch/$(SRCARCH)/include/asm/a.out.h),) -header-y += a.out.h +ifeq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/uapi/asm/a.out.h),) +no-export-headers += a.out.h endif -header-y += acct.h -header-y += adb.h -header-y += adfs_fs.h -header-y += affs_hardblocks.h -header-y += agpgart.h -header-y += aio_abi.h -header-y += am437x-vpfe.h -header-y += apm_bios.h -header-y += arcfb.h -header-y += atalk.h -header-y += atmapi.h -header-y += atmarp.h -header-y += atmbr2684.h -header-y += atmclip.h -header-y += atmdev.h -header-y += atm_eni.h -header-y += atm.h -header-y += atm_he.h -header-y += atm_idt77105.h -header-y += atmioc.h -header-y += atmlec.h -header-y += atmmpc.h -header-y += atm_nicstar.h -header-y += atmppp.h -header-y += atmsap.h -header-y += atmsvc.h -header-y += atm_tcp.h -header-y += atm_zatm.h -header-y += audit.h -header-y += auto_fs4.h -header-y += auto_fs.h -header-y += auxvec.h -header-y += ax25.h -header-y += b1lli.h -header-y += batman_adv.h -header-y += baycom.h -header-y += bcm933xx_hcs.h -header-y += bfs_fs.h -header-y += binfmts.h -header-y += blkpg.h -header-y += blktrace_api.h -header-y += blkzoned.h -header-y += bpf_common.h -header-y += bpf_perf_event.h -header-y += bpf.h -header-y += bpqether.h -header-y += bsg.h -header-y += bt-bmc.h -header-y += btrfs.h -header-y += can.h -header-y += capability.h -header-y += capi.h -header-y += cciss_defs.h -header-y += cciss_ioctl.h -header-y += cdrom.h -header-y += cec.h -header-y += cec-funcs.h -header-y += cgroupstats.h -header-y += chio.h -header-y += cm4000_cs.h -header-y += cn_proc.h -header-y += coda.h -header-y += coda_psdev.h -header-y += coff.h -header-y += connector.h -header-y += const.h -header-y += cramfs_fs.h -header-y += cuda.h -header-y += cyclades.h -header-y += cycx_cfm.h -header-y += dcbnl.h -header-y += dccp.h -header-y += devlink.h -header-y += dlmconstants.h -header-y += dlm_device.h -header-y += dlm.h -header-y += dlm_netlink.h -header-y += dlm_plock.h -header-y += dm-ioctl.h -header-y += dm-log-userspace.h -header-y += dma-buf.h -header-y += dn.h -header-y += dqblk_xfs.h -header-y += edd.h -header-y += efs_fs_sb.h -header-y += elfcore.h -header-y += elf-em.h -header-y += elf-fdpic.h -header-y += elf.h -header-y += errno.h -header-y += errqueue.h -header-y += ethtool.h -header-y += eventpoll.h -header-y += fadvise.h -header-y += falloc.h -header-y += fanotify.h -header-y += fb.h -header-y += fcntl.h -header-y += fd.h -header-y += fdreg.h -header-y += fib_rules.h -header-y += fiemap.h -header-y += filter.h -header-y += firewire-cdev.h -header-y += firewire-constants.h -header-y += flat.h -header-y += fou.h -header-y += fs.h -header-y += fsl_hypervisor.h -header-y += fuse.h -header-y += futex.h -header-y += gameport.h -header-y += genetlink.h -header-y += gen_stats.h -header-y += gfs2_ondisk.h -header-y += gigaset_dev.h -header-y += gpio.h -header-y += gsmmux.h -header-y += gtp.h -header-y += hdlcdrv.h -header-y += hdlc.h -header-y += hdreg.h -header-y += hiddev.h -header-y += hid.h -header-y += hidraw.h -header-y += hpet.h -header-y += hsr_netlink.h -header-y += hyperv.h -header-y += hysdn_if.h -header-y += i2c-dev.h -header-y += i2c.h -header-y += i2o-dev.h -header-y += i8k.h -header-y += icmp.h -header-y += icmpv6.h -header-y += if_addr.h -header-y += if_addrlabel.h -header-y += if_alg.h -header-y += if_arcnet.h -header-y += if_arp.h -header-y += if_bonding.h -header-y += if_bridge.h -header-y += if_cablemodem.h -header-y += if_eql.h -header-y += if_ether.h -header-y += if_fc.h -header-y += if_fddi.h -header-y += if_frad.h -header-y += if.h -header-y += if_hippi.h -header-y += if_infiniband.h -header-y += if_link.h -header-y += if_ltalk.h -header-y += if_macsec.h -header-y += if_packet.h -header-y += if_phonet.h -header-y += if_plip.h -header-y += if_ppp.h -header-y += if_pppol2tp.h -header-y += if_pppox.h -header-y += if_slip.h -header-y += if_team.h -header-y += if_tun.h -header-y += if_tunnel.h -header-y += if_vlan.h -header-y += if_x25.h -header-y += ife.h -header-y += igmp.h -header-y += ila.h -header-y += in6.h -header-y += inet_diag.h -header-y += in.h -header-y += inotify.h -header-y += input.h -header-y += input-event-codes.h -header-y += in_route.h -header-y += ioctl.h -header-y += ip6_tunnel.h -header-y += ipc.h -header-y += ip.h -header-y += ipmi.h -header-y += ipmi_msgdefs.h -header-y += ipsec.h -header-y += ipv6.h -header-y += ipv6_route.h -header-y += ip_vs.h -header-y += ipx.h -header-y += irda.h -header-y += irqnr.h -header-y += isdn_divertif.h -header-y += isdn.h -header-y += isdnif.h -header-y += isdn_ppp.h -header-y += iso_fs.h -header-y += ivtvfb.h -header-y += ivtv.h -header-y += ixjuser.h -header-y += jffs2.h -header-y += joystick.h -header-y += kcmp.h -header-y += kdev_t.h -header-y += kd.h -header-y += kernelcapi.h -header-y += kernel.h -header-y += kernel-page-flags.h -header-y += kexec.h -header-y += keyboard.h -header-y += keyctl.h - -ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/uapi/asm/kvm.h \ - $(srctree)/arch/$(SRCARCH)/include/asm/kvm.h),) -header-y += kvm.h +ifeq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/uapi/asm/kvm.h),) +no-export-headers += kvm.h endif - -ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/uapi/asm/kvm_para.h \ - $(srctree)/arch/$(SRCARCH)/include/asm/kvm_para.h),) -header-y += kvm_para.h +ifeq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/uapi/asm/kvm_para.h),) +no-export-headers += kvm_para.h endif - -header-y += hw_breakpoint.h -header-y += l2tp.h -header-y += libc-compat.h -header-y += lirc.h -header-y += limits.h -header-y += llc.h -header-y += loop.h -header-y += lp.h -header-y += lwtunnel.h -header-y += magic.h -header-y += major.h -header-y += map_to_7segment.h -header-y += matroxfb.h -header-y += mdio.h -header-y += media.h -header-y += media-bus-format.h -header-y += mei.h -header-y += membarrier.h -header-y += memfd.h -header-y += mempolicy.h -header-y += meye.h -header-y += mic_common.h -header-y += mic_ioctl.h -header-y += mii.h -header-y += minix_fs.h -header-y += mman.h -header-y += mmtimer.h -header-y += mpls.h -header-y += mpls_iptunnel.h -header-y += mqueue.h -header-y += mroute6.h -header-y += mroute.h -header-y += msdos_fs.h -header-y += msg.h -header-y += mtio.h -header-y += nbd.h -header-y += ncp_fs.h -header-y += ncp.h -header-y += ncp_mount.h -header-y += ncp_no.h -header-y += ndctl.h -header-y += neighbour.h -header-y += netconf.h -header-y += netdevice.h -header-y += net_dropmon.h -header-y += netfilter_arp.h -header-y += netfilter_bridge.h -header-y += netfilter_decnet.h -header-y += netfilter.h -header-y += netfilter_ipv4.h -header-y += netfilter_ipv6.h -header-y += net.h -header-y += netlink_diag.h -header-y += netlink.h -header-y += netrom.h -header-y += net_namespace.h -header-y += net_tstamp.h -header-y += nfc.h -header-y += psample.h -header-y += nfs2.h -header-y += nfs3.h -header-y += nfs4.h -header-y += nfs4_mount.h -header-y += nfsacl.h -header-y += nfs_fs.h -header-y += nfs.h -header-y += nfs_idmap.h -header-y += nfs_mount.h -header-y += nl80211.h -header-y += n_r3964.h -header-y += nubus.h -header-y += nvme_ioctl.h -header-y += nvram.h -header-y += omap3isp.h -header-y += omapfb.h -header-y += oom.h -header-y += openvswitch.h -header-y += packet_diag.h -header-y += param.h -header-y += parport.h -header-y += patchkey.h -header-y += pci.h -header-y += pci_regs.h -header-y += pcitest.h -header-y += perf_event.h -header-y += personality.h -header-y += pfkeyv2.h -header-y += pg.h -header-y += phantom.h -header-y += phonet.h -header-y += pktcdvd.h -header-y += pkt_cls.h -header-y += pkt_sched.h -header-y += pmu.h -header-y += poll.h -header-y += posix_acl.h -header-y += posix_acl_xattr.h -header-y += posix_types.h -header-y += ppdev.h -header-y += ppp-comp.h -header-y += ppp_defs.h -header-y += ppp-ioctl.h -header-y += pps.h -header-y += prctl.h -header-y += psci.h -header-y += ptp_clock.h -header-y += ptrace.h -header-y += qnx4_fs.h -header-y += qnxtypes.h -header-y += quota.h -header-y += radeonfb.h -header-y += random.h -header-y += raw.h -header-y += rds.h -header-y += reboot.h -header-y += reiserfs_fs.h -header-y += reiserfs_xattr.h -header-y += resource.h -header-y += rfkill.h -header-y += rio_cm_cdev.h -header-y += rio_mport_cdev.h -header-y += romfs_fs.h -header-y += rose.h -header-y += route.h -header-y += rtc.h -header-y += rtnetlink.h -header-y += scc.h -header-y += sched.h -header-y += scif_ioctl.h -header-y += screen_info.h -header-y += sctp.h -header-y += sdla.h -header-y += seccomp.h -header-y += securebits.h -header-y += seg6_genl.h -header-y += seg6.h -header-y += seg6_hmac.h -header-y += seg6_iptunnel.h -header-y += selinux_netlink.h -header-y += sem.h -header-y += serial_core.h -header-y += serial.h -header-y += serial_reg.h -header-y += serio.h -header-y += shm.h -header-y += signalfd.h -header-y += signal.h -header-y += smiapp.h -header-y += snmp.h -header-y += sock_diag.h -header-y += socket.h -header-y += sockios.h -header-y += sonet.h -header-y += sonypi.h -header-y += soundcard.h -header-y += sound.h -header-y += stat.h -header-y += stddef.h -header-y += string.h -header-y += suspend_ioctls.h -header-y += swab.h -header-y += synclink.h -header-y += sync_file.h -header-y += sysctl.h -header-y += sysinfo.h -header-y += target_core_user.h -header-y += taskstats.h -header-y += tcp.h -header-y += tcp_metrics.h -header-y += telephony.h -header-y += termios.h -header-y += thermal.h -header-y += time.h -header-y += timerfd.h -header-y += times.h -header-y += timex.h -header-y += tiocl.h -header-y += tipc_config.h -header-y += tipc_netlink.h -header-y += tipc.h -header-y += toshiba.h -header-y += tty_flags.h -header-y += tty.h -header-y += types.h -header-y += udf_fs_i.h -header-y += udp.h -header-y += uhid.h -header-y += uinput.h -header-y += uio.h -header-y += uleds.h -header-y += ultrasound.h -header-y += un.h -header-y += unistd.h -header-y += unix_diag.h -header-y += usbdevice_fs.h -header-y += usbip.h -header-y += userio.h -header-y += utime.h -header-y += utsname.h -header-y += uuid.h -header-y += uvcvideo.h -header-y += v4l2-common.h -header-y += v4l2-controls.h -header-y += v4l2-dv-timings.h -header-y += v4l2-mediabus.h -header-y += v4l2-subdev.h -header-y += veth.h -header-y += vfio.h -header-y += vhost.h -header-y += videodev2.h -header-y += virtio_9p.h -header-y += virtio_balloon.h -header-y += virtio_blk.h -header-y += virtio_config.h -header-y += virtio_console.h -header-y += virtio_gpu.h -header-y += virtio_ids.h -header-y += virtio_input.h -header-y += virtio_mmio.h -header-y += virtio_net.h -header-y += virtio_pci.h -header-y += virtio_ring.h -header-y += virtio_rng.h -header-y += virtio_scsi.h -header-y += virtio_types.h -header-y += virtio_vsock.h -header-y += virtio_crypto.h -header-y += vm_sockets.h -header-y += vsockmon.h -header-y += vt.h -header-y += vtpm_proxy.h -header-y += wait.h -header-y += wanrouter.h -header-y += watchdog.h -header-y += wimax.h -header-y += wireless.h -header-y += x25.h -header-y += xattr.h -header-y += xfrm.h -header-y += xilinx-v4l2-controls.h -header-y += zorro.h -header-y += zorro_ids.h -header-y += userfaultfd.h diff --git a/include/uapi/linux/android/Kbuild b/include/uapi/linux/android/Kbuild deleted file mode 100644 index ca011eec252a..000000000000 --- a/include/uapi/linux/android/Kbuild +++ /dev/null @@ -1,2 +0,0 @@ -# UAPI Header export list -header-y += binder.h diff --git a/include/uapi/linux/byteorder/Kbuild b/include/uapi/linux/byteorder/Kbuild deleted file mode 100644 index 619225b9ff2e..000000000000 --- a/include/uapi/linux/byteorder/Kbuild +++ /dev/null @@ -1,3 +0,0 @@ -# UAPI Header export list -header-y += big_endian.h -header-y += little_endian.h diff --git a/include/uapi/linux/caif/Kbuild b/include/uapi/linux/caif/Kbuild deleted file mode 100644 index 43396612d3a3..000000000000 --- a/include/uapi/linux/caif/Kbuild +++ /dev/null @@ -1,3 +0,0 @@ -# UAPI Header export list -header-y += caif_socket.h -header-y += if_caif.h diff --git a/include/uapi/linux/can/Kbuild b/include/uapi/linux/can/Kbuild deleted file mode 100644 index 21c91bf25a29..000000000000 --- a/include/uapi/linux/can/Kbuild +++ /dev/null @@ -1,6 +0,0 @@ -# UAPI Header export list -header-y += bcm.h -header-y += error.h -header-y += gw.h -header-y += netlink.h -header-y += raw.h diff --git a/include/uapi/linux/dvb/Kbuild b/include/uapi/linux/dvb/Kbuild deleted file mode 100644 index d40942cfc627..000000000000 --- a/include/uapi/linux/dvb/Kbuild +++ /dev/null @@ -1,9 +0,0 @@ -# UAPI Header export list -header-y += audio.h -header-y += ca.h -header-y += dmx.h -header-y += frontend.h -header-y += net.h -header-y += osd.h -header-y += version.h -header-y += video.h diff --git a/include/uapi/linux/hdlc/Kbuild b/include/uapi/linux/hdlc/Kbuild deleted file mode 100644 index 8c1d2cb75e33..000000000000 --- a/include/uapi/linux/hdlc/Kbuild +++ /dev/null @@ -1,2 +0,0 @@ -# UAPI Header export list -header-y += ioctl.h diff --git a/include/uapi/linux/hsi/Kbuild b/include/uapi/linux/hsi/Kbuild deleted file mode 100644 index a16a00544258..000000000000 --- a/include/uapi/linux/hsi/Kbuild +++ /dev/null @@ -1,2 +0,0 @@ -# UAPI Header export list -header-y += hsi_char.h cs-protocol.h diff --git a/include/uapi/linux/iio/Kbuild b/include/uapi/linux/iio/Kbuild deleted file mode 100644 index 86f76d84c44f..000000000000 --- a/include/uapi/linux/iio/Kbuild +++ /dev/null @@ -1,3 +0,0 @@ -# UAPI Header export list -header-y += events.h -header-y += types.h diff --git a/include/uapi/linux/isdn/Kbuild b/include/uapi/linux/isdn/Kbuild deleted file mode 100644 index 89e52850bf29..000000000000 --- a/include/uapi/linux/isdn/Kbuild +++ /dev/null @@ -1,2 +0,0 @@ -# UAPI Header export list -header-y += capicmd.h diff --git a/include/uapi/linux/mmc/Kbuild b/include/uapi/linux/mmc/Kbuild deleted file mode 100644 index 8c1d2cb75e33..000000000000 --- a/include/uapi/linux/mmc/Kbuild +++ /dev/null @@ -1,2 +0,0 @@ -# UAPI Header export list -header-y += ioctl.h diff --git a/include/uapi/linux/netfilter/Kbuild b/include/uapi/linux/netfilter/Kbuild deleted file mode 100644 index 03f194aeadc5..000000000000 --- a/include/uapi/linux/netfilter/Kbuild +++ /dev/null @@ -1,89 +0,0 @@ -# UAPI Header export list -header-y += ipset/ -header-y += nf_conntrack_common.h -header-y += nf_conntrack_ftp.h -header-y += nf_conntrack_sctp.h -header-y += nf_conntrack_tcp.h -header-y += nf_conntrack_tuple_common.h -header-y += nf_log.h -header-y += nf_tables.h -header-y += nf_tables_compat.h -header-y += nf_nat.h -header-y += nfnetlink.h -header-y += nfnetlink_acct.h -header-y += nfnetlink_compat.h -header-y += nfnetlink_conntrack.h -header-y += nfnetlink_cthelper.h -header-y += nfnetlink_cttimeout.h -header-y += nfnetlink_log.h -header-y += nfnetlink_queue.h -header-y += x_tables.h -header-y += xt_AUDIT.h -header-y += xt_CHECKSUM.h -header-y += xt_CLASSIFY.h -header-y += xt_CONNMARK.h -header-y += xt_CONNSECMARK.h -header-y += xt_CT.h -header-y += xt_DSCP.h -header-y += xt_HMARK.h -header-y += xt_IDLETIMER.h -header-y += xt_LED.h -header-y += xt_LOG.h -header-y += xt_MARK.h -header-y += xt_NFLOG.h -header-y += xt_NFQUEUE.h -header-y += xt_RATEEST.h -header-y += xt_SECMARK.h -header-y += xt_SYNPROXY.h -header-y += xt_TCPMSS.h -header-y += xt_TCPOPTSTRIP.h -header-y += xt_TEE.h -header-y += xt_TPROXY.h -header-y += xt_addrtype.h -header-y += xt_bpf.h -header-y += xt_cgroup.h -header-y += xt_cluster.h -header-y += xt_comment.h -header-y += xt_connbytes.h -header-y += xt_connlabel.h -header-y += xt_connlimit.h -header-y += xt_connmark.h -header-y += xt_conntrack.h -header-y += xt_cpu.h -header-y += xt_dccp.h -header-y += xt_devgroup.h -header-y += xt_dscp.h -header-y += xt_ecn.h -header-y += xt_esp.h -header-y += xt_hashlimit.h -header-y += xt_helper.h -header-y += xt_ipcomp.h -header-y += xt_iprange.h -header-y += xt_ipvs.h -header-y += xt_l2tp.h -header-y += xt_length.h -header-y += xt_limit.h -header-y += xt_mac.h -header-y += xt_mark.h -header-y += xt_multiport.h -header-y += xt_nfacct.h -header-y += xt_osf.h -header-y += xt_owner.h -header-y += xt_physdev.h -header-y += xt_pkttype.h -header-y += xt_policy.h -header-y += xt_quota.h -header-y += xt_rateest.h -header-y += xt_realm.h -header-y += xt_recent.h -header-y += xt_rpfilter.h -header-y += xt_sctp.h -header-y += xt_set.h -header-y += xt_socket.h -header-y += xt_state.h -header-y += xt_statistic.h -header-y += xt_string.h -header-y += xt_tcpmss.h -header-y += xt_tcpudp.h -header-y += xt_time.h -header-y += xt_u32.h diff --git a/include/uapi/linux/netfilter/ipset/Kbuild b/include/uapi/linux/netfilter/ipset/Kbuild deleted file mode 100644 index d2680423d9ab..000000000000 --- a/include/uapi/linux/netfilter/ipset/Kbuild +++ /dev/null @@ -1,5 +0,0 @@ -# UAPI Header export list -header-y += ip_set.h -header-y += ip_set_bitmap.h -header-y += ip_set_hash.h -header-y += ip_set_list.h diff --git a/include/uapi/linux/netfilter_arp/Kbuild b/include/uapi/linux/netfilter_arp/Kbuild deleted file mode 100644 index 62d5637cc0ac..000000000000 --- a/include/uapi/linux/netfilter_arp/Kbuild +++ /dev/null @@ -1,3 +0,0 @@ -# UAPI Header export list -header-y += arp_tables.h -header-y += arpt_mangle.h diff --git a/include/uapi/linux/netfilter_bridge/Kbuild b/include/uapi/linux/netfilter_bridge/Kbuild deleted file mode 100644 index 0fbad8ef96de..000000000000 --- a/include/uapi/linux/netfilter_bridge/Kbuild +++ /dev/null @@ -1,18 +0,0 @@ -# UAPI Header export list -header-y += ebt_802_3.h -header-y += ebt_among.h -header-y += ebt_arp.h -header-y += ebt_arpreply.h -header-y += ebt_ip.h -header-y += ebt_ip6.h -header-y += ebt_limit.h -header-y += ebt_log.h -header-y += ebt_mark_m.h -header-y += ebt_mark_t.h -header-y += ebt_nat.h -header-y += ebt_nflog.h -header-y += ebt_pkttype.h -header-y += ebt_redirect.h -header-y += ebt_stp.h -header-y += ebt_vlan.h -header-y += ebtables.h diff --git a/include/uapi/linux/netfilter_ipv4/Kbuild b/include/uapi/linux/netfilter_ipv4/Kbuild deleted file mode 100644 index ecb291df390e..000000000000 --- a/include/uapi/linux/netfilter_ipv4/Kbuild +++ /dev/null @@ -1,10 +0,0 @@ -# UAPI Header export list -header-y += ip_tables.h -header-y += ipt_CLUSTERIP.h -header-y += ipt_ECN.h -header-y += ipt_LOG.h -header-y += ipt_REJECT.h -header-y += ipt_TTL.h -header-y += ipt_ah.h -header-y += ipt_ecn.h -header-y += ipt_ttl.h diff --git a/include/uapi/linux/netfilter_ipv6/Kbuild b/include/uapi/linux/netfilter_ipv6/Kbuild deleted file mode 100644 index 75a668ca2353..000000000000 --- a/include/uapi/linux/netfilter_ipv6/Kbuild +++ /dev/null @@ -1,13 +0,0 @@ -# UAPI Header export list -header-y += ip6_tables.h -header-y += ip6t_HL.h -header-y += ip6t_LOG.h -header-y += ip6t_NPT.h -header-y += ip6t_REJECT.h -header-y += ip6t_ah.h -header-y += ip6t_frag.h -header-y += ip6t_hl.h -header-y += ip6t_ipv6header.h -header-y += ip6t_mh.h -header-y += ip6t_opts.h -header-y += ip6t_rt.h diff --git a/include/uapi/linux/nfsd/Kbuild b/include/uapi/linux/nfsd/Kbuild deleted file mode 100644 index c11bc404053c..000000000000 --- a/include/uapi/linux/nfsd/Kbuild +++ /dev/null @@ -1,6 +0,0 @@ -# UAPI Header export list -header-y += cld.h -header-y += debug.h -header-y += export.h -header-y += nfsfh.h -header-y += stats.h diff --git a/include/uapi/linux/raid/Kbuild b/include/uapi/linux/raid/Kbuild deleted file mode 100644 index e2c3d25405d7..000000000000 --- a/include/uapi/linux/raid/Kbuild +++ /dev/null @@ -1,3 +0,0 @@ -# UAPI Header export list -header-y += md_p.h -header-y += md_u.h diff --git a/include/uapi/linux/spi/Kbuild b/include/uapi/linux/spi/Kbuild deleted file mode 100644 index 0cc747eff165..000000000000 --- a/include/uapi/linux/spi/Kbuild +++ /dev/null @@ -1,2 +0,0 @@ -# UAPI Header export list -header-y += spidev.h diff --git a/include/uapi/linux/sunrpc/Kbuild b/include/uapi/linux/sunrpc/Kbuild deleted file mode 100644 index 8e02e47c20fb..000000000000 --- a/include/uapi/linux/sunrpc/Kbuild +++ /dev/null @@ -1,2 +0,0 @@ -# UAPI Header export list -header-y += debug.h diff --git a/include/uapi/linux/tc_act/Kbuild b/include/uapi/linux/tc_act/Kbuild deleted file mode 100644 index ba62ddf0e58a..000000000000 --- a/include/uapi/linux/tc_act/Kbuild +++ /dev/null @@ -1,16 +0,0 @@ -# UAPI Header export list -header-y += tc_csum.h -header-y += tc_defact.h -header-y += tc_gact.h -header-y += tc_ipt.h -header-y += tc_mirred.h -header-y += tc_sample.h -header-y += tc_nat.h -header-y += tc_pedit.h -header-y += tc_skbedit.h -header-y += tc_vlan.h -header-y += tc_bpf.h -header-y += tc_connmark.h -header-y += tc_ife.h -header-y += tc_tunnel_key.h -header-y += tc_skbmod.h diff --git a/include/uapi/linux/tc_ematch/Kbuild b/include/uapi/linux/tc_ematch/Kbuild deleted file mode 100644 index 53fca3925535..000000000000 --- a/include/uapi/linux/tc_ematch/Kbuild +++ /dev/null @@ -1,5 +0,0 @@ -# UAPI Header export list -header-y += tc_em_cmp.h -header-y += tc_em_meta.h -header-y += tc_em_nbyte.h -header-y += tc_em_text.h diff --git a/include/uapi/linux/usb/Kbuild b/include/uapi/linux/usb/Kbuild deleted file mode 100644 index 4cc4d6e7e523..000000000000 --- a/include/uapi/linux/usb/Kbuild +++ /dev/null @@ -1,12 +0,0 @@ -# UAPI Header export list -header-y += audio.h -header-y += cdc.h -header-y += cdc-wdm.h -header-y += ch11.h -header-y += ch9.h -header-y += functionfs.h -header-y += g_printer.h -header-y += gadgetfs.h -header-y += midi.h -header-y += tmc.h -header-y += video.h diff --git a/include/uapi/linux/wimax/Kbuild b/include/uapi/linux/wimax/Kbuild deleted file mode 100644 index 1c97be49971f..000000000000 --- a/include/uapi/linux/wimax/Kbuild +++ /dev/null @@ -1,2 +0,0 @@ -# UAPI Header export list -header-y += i2400m.h diff --git a/include/uapi/misc/Kbuild b/include/uapi/misc/Kbuild deleted file mode 100644 index e96cae7d58c9..000000000000 --- a/include/uapi/misc/Kbuild +++ /dev/null @@ -1,2 +0,0 @@ -# misc Header export list -header-y += cxl.h diff --git a/include/uapi/mtd/Kbuild b/include/uapi/mtd/Kbuild deleted file mode 100644 index 5a691e10cd0e..000000000000 --- a/include/uapi/mtd/Kbuild +++ /dev/null @@ -1,6 +0,0 @@ -# UAPI Header export list -header-y += inftl-user.h -header-y += mtd-abi.h -header-y += mtd-user.h -header-y += nftl-user.h -header-y += ubi-user.h diff --git a/include/uapi/rdma/Kbuild b/include/uapi/rdma/Kbuild deleted file mode 100644 index 1e0af1ff75c3..000000000000 --- a/include/uapi/rdma/Kbuild +++ /dev/null @@ -1,20 +0,0 @@ -# UAPI Header export list -header-y += ib_user_cm.h -header-y += rdma_user_ioctl.h -header-y += ib_user_mad.h -header-y += ib_user_sa.h -header-y += ib_user_verbs.h -header-y += rdma_netlink.h -header-y += rdma_user_cm.h -header-y += hfi/ -header-y += rdma_user_rxe.h -header-y += cxgb3-abi.h -header-y += cxgb4-abi.h -header-y += mlx4-abi.h -header-y += mlx5-abi.h -header-y += mthca-abi.h -header-y += nes-abi.h -header-y += ocrdma-abi.h -header-y += hns-abi.h -header-y += vmw_pvrdma-abi.h -header-y += qedr-abi.h diff --git a/include/uapi/rdma/hfi/Kbuild b/include/uapi/rdma/hfi/Kbuild deleted file mode 100644 index b65b0b3a5f63..000000000000 --- a/include/uapi/rdma/hfi/Kbuild +++ /dev/null @@ -1,3 +0,0 @@ -# UAPI Header export list -header-y += hfi1_user.h -header-y += hfi1_ioctl.h diff --git a/include/uapi/scsi/Kbuild b/include/uapi/scsi/Kbuild deleted file mode 100644 index d791e0ad509d..000000000000 --- a/include/uapi/scsi/Kbuild +++ /dev/null @@ -1,6 +0,0 @@ -# UAPI Header export list -header-y += fc/ -header-y += scsi_bsg_fc.h -header-y += scsi_netlink.h -header-y += scsi_netlink_fc.h -header-y += cxlflash_ioctl.h diff --git a/include/uapi/scsi/fc/Kbuild b/include/uapi/scsi/fc/Kbuild deleted file mode 100644 index 5ead9fac265c..000000000000 --- a/include/uapi/scsi/fc/Kbuild +++ /dev/null @@ -1,5 +0,0 @@ -# UAPI Header export list -header-y += fc_els.h -header-y += fc_fs.h -header-y += fc_gs.h -header-y += fc_ns.h diff --git a/include/uapi/sound/Kbuild b/include/uapi/sound/Kbuild deleted file mode 100644 index 9578d8bdbf31..000000000000 --- a/include/uapi/sound/Kbuild +++ /dev/null @@ -1,16 +0,0 @@ -# UAPI Header export list -header-y += asequencer.h -header-y += asoc.h -header-y += asound.h -header-y += asound_fm.h -header-y += compress_offload.h -header-y += compress_params.h -header-y += emu10k1.h -header-y += firewire.h -header-y += hdsp.h -header-y += hdspm.h -header-y += sb16_csp.h -header-y += sfnt_info.h -header-y += tlv.h -header-y += usb_stream.h -header-y += snd_sst_tokens.h diff --git a/include/uapi/video/Kbuild b/include/uapi/video/Kbuild deleted file mode 100644 index ac7203bb32cc..000000000000 --- a/include/uapi/video/Kbuild +++ /dev/null @@ -1,4 +0,0 @@ -# UAPI Header export list -header-y += edid.h -header-y += sisfb.h -header-y += uvesafb.h diff --git a/include/uapi/xen/Kbuild b/include/uapi/xen/Kbuild deleted file mode 100644 index 5c459628e8c7..000000000000 --- a/include/uapi/xen/Kbuild +++ /dev/null @@ -1,5 +0,0 @@ -# UAPI Header export list -header-y += evtchn.h -header-y += gntalloc.h -header-y += gntdev.h -header-y += privcmd.h diff --git a/include/video/Kbuild b/include/video/Kbuild deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst index ca5d439c9abf..20be1fbc19cc 100644 --- a/scripts/Makefile.headersinst +++ b/scripts/Makefile.headersinst @@ -1,17 +1,19 @@ # ========================================================================== # Installing headers # -# header-y - list files to be installed. They are preprocessed -# to remove __KERNEL__ section of the file -# genhdr-y - Same as header-y but in a generated/ directory +# All headers under include/uapi, include/generated/uapi, +# arch//include/uapi/asm and arch//include/generated/uapi/asm are +# exported. +# They are preprocessed to remove __KERNEL__ section of the file. # # ========================================================================== # generated header directory gen := $(if $(gen),$(gen),$(subst include/,include/generated/,$(obj))) +# Kbuild file is optional kbuild-file := $(srctree)/$(obj)/Kbuild -include $(kbuild-file) +-include $(kbuild-file) # called may set destination dir (when installing to asm/) _dst := $(if $(dst),$(dst),$(obj)) @@ -25,9 +27,15 @@ include scripts/Kbuild.include installdir := $(INSTALL_HDR_PATH)/$(subst uapi/,,$(_dst)) -header-y := $(sort $(header-y)) -subdirs := $(patsubst %/,%,$(filter %/, $(header-y))) -header-y := $(filter-out %/, $(header-y)) +srcdir := $(srctree)/$(obj) +gendir := $(objtree)/$(gen) +subdirs := $(patsubst $(srcdir)/%/.,%,$(wildcard $(srcdir)/*/.)) +subdirs += $(subdir-y) +header-files := $(notdir $(wildcard $(srcdir)/*.h)) +header-files += $(notdir $(wildcard $(srcdir)/*.agh)) +header-files := $(filter-out $(no-export-headers), $(header-files)) +genhdr-files := $(notdir $(wildcard $(gendir)/*.h)) +genhdr-files := $(filter-out $(header-files), $(genhdr-files)) # files used to track state of install/check install-file := $(installdir)/.install @@ -35,25 +43,20 @@ check-file := $(installdir)/.check # generic-y list all files an architecture uses from asm-generic # Use this to build a list of headers which require a wrapper -wrapper-files := $(filter $(header-y), $(generic-y)) - -srcdir := $(srctree)/$(obj) -gendir := $(objtree)/$(gen) +generic-files := $(notdir $(wildcard $(srctree)/include/uapi/asm-generic/*.h)) +wrapper-files := $(filter $(generic-files), $(generic-y)) +wrapper-files := $(filter-out $(header-files), $(wrapper-files)) # all headers files for this dir -header-y := $(filter-out $(generic-y), $(header-y)) -all-files := $(header-y) $(genhdr-y) $(wrapper-files) +all-files := $(header-files) $(genhdr-files) $(wrapper-files) output-files := $(addprefix $(installdir)/, $(all-files)) -# Check that all expected files exist -$(foreach hdr, $(header-y), \ - $(if $(wildcard $(srcdir)/$(hdr)),, \ - $(error Missing UAPI file $(srcdir)/$(hdr)) \ - )) -$(foreach hdr, $(genhdr-y), \ - $(if $(wildcard $(gendir)/$(hdr)),, \ - $(error Missing generated UAPI file $(gendir)/$(hdr)) \ - )) +ifneq ($(mandatory-y),) +missing := $(filter-out $(all-files),$(mandatory-y)) +ifneq ($(missing),) +$(error Some mandatory headers ($(missing)) are missing in $(obj)) +endif +endif # Work out what needs to be removed oldheaders := $(patsubst $(installdir)/%,%,$(wildcard $(installdir)/*.h)) @@ -67,8 +70,8 @@ printdir = $(patsubst $(INSTALL_HDR_PATH)/%/,%,$(dir $@)) quiet_cmd_install = INSTALL $(printdir) ($(words $(all-files))\ file$(if $(word 2, $(all-files)),s)) cmd_install = \ - $(CONFIG_SHELL) $< $(installdir) $(srcdir) $(header-y); \ - $(CONFIG_SHELL) $< $(installdir) $(gendir) $(genhdr-y); \ + $(CONFIG_SHELL) $< $(installdir) $(srcdir) $(header-files); \ + $(CONFIG_SHELL) $< $(installdir) $(gendir) $(genhdr-files); \ for F in $(wrapper-files); do \ echo "\#include " > $(installdir)/$$F; \ done; \ @@ -95,8 +98,8 @@ __headersinst: $(subdirs) $(install-file) targets += $(install-file) $(install-file): scripts/headers_install.sh \ - $(addprefix $(srcdir)/,$(header-y)) \ - $(addprefix $(gendir)/,$(genhdr-y)) FORCE + $(addprefix $(srcdir)/,$(header-files)) \ + $(addprefix $(gendir)/,$(genhdr-files)) FORCE $(if $(unwanted),$(call cmd,remove),) $(if $(wildcard $(dir $@)),,$(shell mkdir -p $(dir $@))) $(call if_changed,install) -- cgit v1.2.3-59-g8ed1b From 61562f981e9284ff7dfb2769d89c750986a5f677 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Mon, 27 Mar 2017 14:20:16 +0200 Subject: uapi: export all arch specifics directories This patch removes the need of subdir-y. Now all files/directories under arch//include/uapi/ are exported. The only change for userland is the layout of the command 'make headers_install_all': directories asm- are replaced by arch-/. Those new directories contains all files/directories of the specified arch. Note that only cris and tile have more directories than only asm: - arch-v[10|32] for cris; - arch for tile. Signed-off-by: Nicolas Dichtel Signed-off-by: Masahiro Yamada --- Documentation/kbuild/makefiles.txt | 15 +-------------- Makefile | 6 +++--- arch/cris/include/uapi/asm/Kbuild | 3 --- arch/tile/include/uapi/asm/Kbuild | 2 -- scripts/Makefile.headersinst | 3 +-- 5 files changed, 5 insertions(+), 24 deletions(-) (limited to 'arch') diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt index b9f7ca4e62ae..e18daca65ccd 100644 --- a/Documentation/kbuild/makefiles.txt +++ b/Documentation/kbuild/makefiles.txt @@ -49,7 +49,6 @@ This document describes the Linux kernel Makefiles. --- 7.3 generic-y --- 7.4 generated-y --- 7.5 mandatory-y - --- 7.6 subdir-y === 8 Kbuild Variables === 9 Makefile language @@ -1265,7 +1264,7 @@ The pre-processing does: - drop all sections that are kernel internal (guarded by ifdef __KERNEL__) All headers under include/uapi/, include/generated/uapi/, -arch//include/uapi/asm/ and arch//include/generated/uapi/asm/ +arch//include/uapi/ and arch//include/generated/uapi/ are exported. A Kbuild file may be defined under arch//include/uapi/asm/ and @@ -1338,18 +1337,6 @@ See subsequent chapter for the syntax of the Kbuild file. The convention is to list one subdir per line and preferably in alphabetic order. - --- 7.6 subdir-y - - subdir-y may be used to specify a subdirectory to be exported. - - Example: - #arch/cris/include/uapi/asm/Kbuild - subdir-y += ../arch-v10/arch/ - subdir-y += ../arch-v32/arch/ - - The convention is to list one subdir per line and - preferably in alphabetic order. - === 8 Kbuild Variables The top Makefile exports the following variables: diff --git a/Makefile b/Makefile index 220121fdca4d..4c5a02d30118 100644 --- a/Makefile +++ b/Makefile @@ -1128,7 +1128,7 @@ firmware_install: export INSTALL_HDR_PATH = $(objtree)/usr # If we do an all arch process set dst to asm-$(hdr-arch) -hdr-dst = $(if $(KBUILD_HEADERS), dst=include/asm-$(hdr-arch), dst=include/asm) +hdr-dst = $(if $(KBUILD_HEADERS), dst=include/arch-$(hdr-arch), dst=include) PHONY += archheaders archheaders: @@ -1149,7 +1149,7 @@ headers_install: __headers $(if $(wildcard $(srctree)/arch/$(hdr-arch)/include/uapi/asm/Kbuild),, \ $(error Headers not exportable for the $(SRCARCH) architecture)) $(Q)$(MAKE) $(hdr-inst)=include/uapi - $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi/asm $(hdr-dst) + $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi $(hdr-dst) PHONY += headers_check_all headers_check_all: headers_install_all @@ -1158,7 +1158,7 @@ headers_check_all: headers_install_all PHONY += headers_check headers_check: headers_install $(Q)$(MAKE) $(hdr-inst)=include/uapi HDRCHECK=1 - $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi/asm $(hdr-dst) HDRCHECK=1 + $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi/ $(hdr-dst) HDRCHECK=1 # --------------------------------------------------------------------------- # Kernel selftest diff --git a/arch/cris/include/uapi/asm/Kbuild b/arch/cris/include/uapi/asm/Kbuild index d0c5471856e0..b15bf6bc0e94 100644 --- a/arch/cris/include/uapi/asm/Kbuild +++ b/arch/cris/include/uapi/asm/Kbuild @@ -1,5 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -subdir-y += ../arch-v10/arch/ -subdir-y += ../arch-v32/arch/ diff --git a/arch/tile/include/uapi/asm/Kbuild b/arch/tile/include/uapi/asm/Kbuild index e0a50111e07f..0c74c3c5ebfa 100644 --- a/arch/tile/include/uapi/asm/Kbuild +++ b/arch/tile/include/uapi/asm/Kbuild @@ -2,5 +2,3 @@ include include/uapi/asm-generic/Kbuild.asm generic-y += ucontext.h - -subdir-y += ../arch diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst index 20be1fbc19cc..6ba97a1f9c5a 100644 --- a/scripts/Makefile.headersinst +++ b/scripts/Makefile.headersinst @@ -2,7 +2,7 @@ # Installing headers # # All headers under include/uapi, include/generated/uapi, -# arch//include/uapi/asm and arch//include/generated/uapi/asm are +# arch//include/uapi and arch//include/generated/uapi are # exported. # They are preprocessed to remove __KERNEL__ section of the file. # @@ -30,7 +30,6 @@ installdir := $(INSTALL_HDR_PATH)/$(subst uapi/,,$(_dst)) srcdir := $(srctree)/$(obj) gendir := $(objtree)/$(gen) subdirs := $(patsubst $(srcdir)/%/.,%,$(wildcard $(srcdir)/*/.)) -subdirs += $(subdir-y) header-files := $(notdir $(wildcard $(srcdir)/*.h)) header-files += $(notdir $(wildcard $(srcdir)/*.agh)) header-files := $(filter-out $(no-export-headers), $(header-files)) -- cgit v1.2.3-59-g8ed1b From 3e18c637fa3e2f6836a4034c80ca0a86be968efc Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Mon, 27 Mar 2017 14:20:17 +0200 Subject: arch/include: remove empty Kbuild files Signed-off-by: Nicolas Dichtel Signed-off-by: Masahiro Yamada --- arch/cris/include/arch-v10/arch/Kbuild | 1 - arch/cris/include/arch-v32/arch/Kbuild | 1 - arch/tile/include/arch/Kbuild | 1 - 3 files changed, 3 deletions(-) delete mode 100644 arch/cris/include/arch-v10/arch/Kbuild delete mode 100644 arch/cris/include/arch-v32/arch/Kbuild delete mode 100644 arch/tile/include/arch/Kbuild (limited to 'arch') diff --git a/arch/cris/include/arch-v10/arch/Kbuild b/arch/cris/include/arch-v10/arch/Kbuild deleted file mode 100644 index 1f0fc7a66f5f..000000000000 --- a/arch/cris/include/arch-v10/arch/Kbuild +++ /dev/null @@ -1 +0,0 @@ -# CRISv10 arch diff --git a/arch/cris/include/arch-v32/arch/Kbuild b/arch/cris/include/arch-v32/arch/Kbuild deleted file mode 100644 index 2fd65c7e15c9..000000000000 --- a/arch/cris/include/arch-v32/arch/Kbuild +++ /dev/null @@ -1 +0,0 @@ -# CRISv32 arch diff --git a/arch/tile/include/arch/Kbuild b/arch/tile/include/arch/Kbuild deleted file mode 100644 index 3751c9fabcf2..000000000000 --- a/arch/tile/include/arch/Kbuild +++ /dev/null @@ -1 +0,0 @@ -# Tile arch headers -- cgit v1.2.3-59-g8ed1b From e118c3fec9c0d8d2a96462c4c035305dc952e402 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Thu, 11 May 2017 11:40:16 +0200 Subject: nios2: remove custom early console implementation As of commits d8f347ba35cf ("nios2: enable earlycon support"), 0dcc0542a006 ("serial: altera_jtaguart: add earlycon support") and 4d9d7d896d77 ("serial: altera_uart: add earlycon support"), the nios2 architecture and the altera_uart/altera_jtaguart drivers support earlycon. Thus, the custom early console implementation for nios2 is no longer necessary to get early boot messages. Remove it and rely fully on earlycon support. Signed-off-by: Tobias Klauser --- arch/nios2/include/asm/prom.h | 22 ------- arch/nios2/include/asm/setup.h | 2 - arch/nios2/kernel/Makefile | 1 - arch/nios2/kernel/early_printk.c | 121 --------------------------------------- arch/nios2/kernel/prom.c | 49 ---------------- arch/nios2/kernel/setup.c | 4 -- 6 files changed, 199 deletions(-) delete mode 100644 arch/nios2/include/asm/prom.h delete mode 100644 arch/nios2/kernel/early_printk.c (limited to 'arch') diff --git a/arch/nios2/include/asm/prom.h b/arch/nios2/include/asm/prom.h deleted file mode 100644 index 75fffb42cfa5..000000000000 --- a/arch/nios2/include/asm/prom.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright Altera Corporation (C) <2015>. All rights reserved - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#ifndef __ASM_NIOS2_PROM_H__ -#define __ASM_NIOS2_PROM_H__ - -extern unsigned long __init of_early_console(void); - -#endif diff --git a/arch/nios2/include/asm/setup.h b/arch/nios2/include/asm/setup.h index dcbf8cf1a344..ac9bff248e6d 100644 --- a/arch/nios2/include/asm/setup.h +++ b/arch/nios2/include/asm/setup.h @@ -30,8 +30,6 @@ extern char fast_handler_end[]; extern void pagetable_init(void); -extern void setup_early_printk(void); - #endif/* __KERNEL__ */ #endif /* __ASSEMBLY__ */ diff --git a/arch/nios2/kernel/Makefile b/arch/nios2/kernel/Makefile index 1aae25703657..06d07432b38d 100644 --- a/arch/nios2/kernel/Makefile +++ b/arch/nios2/kernel/Makefile @@ -20,7 +20,6 @@ obj-y += syscall_table.o obj-y += time.o obj-y += traps.o -obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_KGDB) += kgdb.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_NIOS2_ALIGNMENT_TRAP) += misaligned.o diff --git a/arch/nios2/kernel/early_printk.c b/arch/nios2/kernel/early_printk.c deleted file mode 100644 index 4a7bb98f744c..000000000000 --- a/arch/nios2/kernel/early_printk.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Early printk for Nios2. - * - * Copyright (C) 2015, Altera Corporation - * Copyright (C) 2010, Tobias Klauser - * Copyright (C) 2009, Wind River Systems Inc - * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#include -#include -#include -#include - -#include - -static unsigned long base_addr; - -#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) - -#define ALTERA_JTAGUART_DATA_REG 0 -#define ALTERA_JTAGUART_CONTROL_REG 4 -#define ALTERA_JTAGUART_CONTROL_WSPACE_MSK 0xFFFF0000 -#define ALTERA_JTAGUART_CONTROL_AC_MSK 0x00000400 - -#define JUART_GET_CR() \ - __builtin_ldwio((void *)(base_addr + ALTERA_JTAGUART_CONTROL_REG)) -#define JUART_SET_CR(v) \ - __builtin_stwio((void *)(base_addr + ALTERA_JTAGUART_CONTROL_REG), v) -#define JUART_SET_TX(v) \ - __builtin_stwio((void *)(base_addr + ALTERA_JTAGUART_DATA_REG), v) - -static void early_console_write(struct console *con, const char *s, unsigned n) -{ - unsigned long status; - - while (n-- && *s) { - while (((status = JUART_GET_CR()) - & ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) { -#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS) - if ((status & ALTERA_JTAGUART_CONTROL_AC_MSK) == 0) - return; /* no connection activity */ -#endif - } - JUART_SET_TX(*s); - s++; - } -} - -#elif defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) - -#define ALTERA_UART_TXDATA_REG 4 -#define ALTERA_UART_STATUS_REG 8 -#define ALTERA_UART_STATUS_TRDY 0x0040 - -#define UART_GET_SR() \ - __builtin_ldwio((void *)(base_addr + ALTERA_UART_STATUS_REG)) -#define UART_SET_TX(v) \ - __builtin_stwio((void *)(base_addr + ALTERA_UART_TXDATA_REG), v) - -static void early_console_putc(char c) -{ - while (!(UART_GET_SR() & ALTERA_UART_STATUS_TRDY)) - ; - - UART_SET_TX(c); -} - -static void early_console_write(struct console *con, const char *s, unsigned n) -{ - while (n-- && *s) { - early_console_putc(*s); - if (*s == '\n') - early_console_putc('\r'); - s++; - } -} - -#else - -static void early_console_write(struct console *con, const char *s, unsigned n) -{ -} - -#endif - -static struct console early_console_prom = { - .name = "early", - .write = early_console_write, - .flags = CON_PRINTBUFFER | CON_BOOT, - .index = -1 -}; - -void __init setup_early_printk(void) -{ -#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) || \ - defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) - base_addr = of_early_console(); -#else - base_addr = 0; -#endif - - if (!base_addr) - return; - -#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS) - /* Clear activity bit so BYPASS doesn't stall if we've used JTAG for - * downloading the kernel. This might cause early data to be lost even - * if the JTAG terminal is running. - */ - JUART_SET_CR(JUART_GET_CR() | ALTERA_JTAGUART_CONTROL_AC_MSK); -#endif - - early_console = &early_console_prom; - register_console(early_console); - pr_info("early_console initialized at 0x%08lx\n", base_addr); -} diff --git a/arch/nios2/kernel/prom.c b/arch/nios2/kernel/prom.c index 3901b80d4420..6688576b3a47 100644 --- a/arch/nios2/kernel/prom.c +++ b/arch/nios2/kernel/prom.c @@ -30,7 +30,6 @@ #include #include -#include #include void __init early_init_dt_add_memory_arch(u64 base, u64 size) @@ -71,51 +70,3 @@ void __init early_init_devtree(void *params) early_init_dt_scan(params); } - -#ifdef CONFIG_EARLY_PRINTK -static int __init early_init_dt_scan_serial(unsigned long node, - const char *uname, int depth, void *data) -{ - u64 *addr64 = (u64 *) data; - const char *p; - - /* only consider serial nodes */ - if (strncmp(uname, "serial", 6) != 0) - return 0; - - p = of_get_flat_dt_prop(node, "compatible", NULL); - if (!p) - return 0; - - /* - * We found an altera_jtaguart but it wasn't configured for console, so - * skip it. - */ -#ifndef CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE - if (strncmp(p, "altr,juart", 10) == 0) - return 0; -#endif - - /* - * Same for altera_uart. - */ -#ifndef CONFIG_SERIAL_ALTERA_UART_CONSOLE - if (strncmp(p, "altr,uart", 9) == 0) - return 0; -#endif - - *addr64 = of_flat_dt_translate_address(node); - - return *addr64 == OF_BAD_ADDR ? 0 : 1; -} - -unsigned long __init of_early_console(void) -{ - u64 base = 0; - - if (of_scan_flat_dt(early_init_dt_scan_serial, &base)) - return (u32)ioremap(base, 32); - else - return 0; -} -#endif /* CONFIG_EARLY_PRINTK */ diff --git a/arch/nios2/kernel/setup.c b/arch/nios2/kernel/setup.c index 8b5146082e3e..926a02b17b31 100644 --- a/arch/nios2/kernel/setup.c +++ b/arch/nios2/kernel/setup.c @@ -147,10 +147,6 @@ void __init setup_arch(char **cmdline_p) console_verbose(); -#ifdef CONFIG_EARLY_PRINTK - setup_early_printk(); -#endif - memory_start = PAGE_ALIGN((unsigned long)__pa(_end)); memory_end = (unsigned long) CONFIG_NIOS2_MEM_BASE + memory_size; -- cgit v1.2.3-59-g8ed1b From 75d24d968af8913f641c612930c96acc5399e427 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 27 Apr 2017 11:19:01 -0700 Subject: ARM: Silence first allocation with CONFIG_ARM_MODULE_PLTS=y When CONFIG_ARM_MODULE_PLTS is enabled, the first allocation using the module space fails, because the module is too big, and then the module allocation is attempted from vmalloc space. Silence the first allocation failure in that case by setting __GFP_NOWARN. Acked-by: Russell King Signed-off-by: Florian Fainelli Signed-off-by: Catalin Marinas --- arch/arm/kernel/module.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index 80254b47dc34..3ff571c2c71c 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -40,8 +40,15 @@ #ifdef CONFIG_MMU void *module_alloc(unsigned long size) { - void *p = __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, - GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE, + gfp_t gfp_mask = GFP_KERNEL; + void *p; + + /* Silence the initial allocation */ + if (IS_ENABLED(CONFIG_ARM_MODULE_PLTS)) + gfp_mask |= __GFP_NOWARN; + + p = __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, + gfp_mask, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE, __builtin_return_address(0)); if (!IS_ENABLED(CONFIG_ARM_MODULE_PLTS) || p) return p; -- cgit v1.2.3-59-g8ed1b From 0c2cf6d9487cb90be6ad7fac66044dfa8e8e5243 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 27 Apr 2017 11:19:02 -0700 Subject: arm64: Silence first allocation with CONFIG_ARM64_MODULE_PLTS=y When CONFIG_ARM64_MODULE_PLTS is enabled, the first allocation using the module space fails, because the module is too big, and then the module allocation is attempted from vmalloc space. Silence the first allocation failure in that case by setting __GFP_NOWARN. Reviewed-by: Ard Biesheuvel Acked-by: Will Deacon Signed-off-by: Florian Fainelli Signed-off-by: Catalin Marinas --- arch/arm64/kernel/module.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c index c9a2ab446dc6..f035ff6fb223 100644 --- a/arch/arm64/kernel/module.c +++ b/arch/arm64/kernel/module.c @@ -32,11 +32,16 @@ void *module_alloc(unsigned long size) { + gfp_t gfp_mask = GFP_KERNEL; void *p; + /* Silence the initial allocation */ + if (IS_ENABLED(CONFIG_ARM64_MODULE_PLTS)) + gfp_mask |= __GFP_NOWARN; + p = __vmalloc_node_range(size, MODULE_ALIGN, module_alloc_base, module_alloc_base + MODULES_VSIZE, - GFP_KERNEL, PAGE_KERNEL_EXEC, 0, + gfp_mask, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE, __builtin_return_address(0)); if (!p && IS_ENABLED(CONFIG_ARM64_MODULE_PLTS) && -- cgit v1.2.3-59-g8ed1b From def9331a12977770cc6132d79f8e6565871e8e38 Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Thu, 27 Apr 2017 07:01:20 +0200 Subject: x86/amd: don't set X86_BUG_SYSRET_SS_ATTRS when running under Xen When running as Xen pv guest X86_BUG_SYSRET_SS_ATTRS must not be set on AMD cpus. This bug/feature bit is kind of special as it will be used very early when switching threads. Setting the bit and clearing it a little bit later leaves a critical window where things can go wrong. This time window has enlarged a little bit by using setup_clear_cpu_cap() instead of the hypervisor's set_cpu_features callback. It seems this larger window now makes it rather easy to hit the problem. The proper solution is to never set the bit in case of Xen. Signed-off-by: Juergen Gross Reviewed-by: Boris Ostrovsky Acked-by: Thomas Gleixner Signed-off-by: Juergen Gross --- arch/x86/kernel/cpu/amd.c | 5 +++-- arch/x86/xen/enlighten_pv.c | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index c36140d788fe..b6da6e75e3a8 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -799,8 +799,9 @@ static void init_amd(struct cpuinfo_x86 *c) if (cpu_has(c, X86_FEATURE_3DNOW) || cpu_has(c, X86_FEATURE_LM)) set_cpu_cap(c, X86_FEATURE_3DNOWPREFETCH); - /* AMD CPUs don't reset SS attributes on SYSRET */ - set_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS); + /* AMD CPUs don't reset SS attributes on SYSRET, Xen does. */ + if (!cpu_has(c, X86_FEATURE_XENPV)) + set_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS); } #ifdef CONFIG_X86_32 diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c index b5c54ab0e195..7cd442690f9d 100644 --- a/arch/x86/xen/enlighten_pv.c +++ b/arch/x86/xen/enlighten_pv.c @@ -290,7 +290,6 @@ static bool __init xen_check_xsave(void) static void __init xen_init_capabilities(void) { - setup_clear_cpu_cap(X86_BUG_SYSRET_SS_ATTRS); setup_force_cpu_cap(X86_FEATURE_XENPV); setup_clear_cpu_cap(X86_FEATURE_DCA); setup_clear_cpu_cap(X86_FEATURE_APERFMPERF); -- cgit v1.2.3-59-g8ed1b From 69861e0a52f8733355ce246f0db15e1b240ad667 Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Wed, 10 May 2017 06:08:44 +0200 Subject: xen: adjust early dom0 p2m handling to xen hypervisor behavior When booted as pv-guest the p2m list presented by the Xen is already mapped to virtual addresses. In dom0 case the hypervisor might make use of 2M- or 1G-pages for this mapping. Unfortunately while being properly aligned in virtual and machine address space, those pages might not be aligned properly in guest physical address space. So when trying to obtain the guest physical address of such a page pud_pfn() and pmd_pfn() must be avoided as those will mask away guest physical address bits not being zero in this special case. Signed-off-by: Juergen Gross Reviewed-by: Jan Beulich Signed-off-by: Juergen Gross --- arch/x86/xen/mmu_pv.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c index 9d9ae6650aa1..7397d8b8459d 100644 --- a/arch/x86/xen/mmu_pv.c +++ b/arch/x86/xen/mmu_pv.c @@ -2025,7 +2025,8 @@ static unsigned long __init xen_read_phys_ulong(phys_addr_t addr) /* * Translate a virtual address to a physical one without relying on mapped - * page tables. + * page tables. Don't rely on big pages being aligned in (guest) physical + * space! */ static phys_addr_t __init xen_early_virt_to_phys(unsigned long vaddr) { @@ -2046,7 +2047,7 @@ static phys_addr_t __init xen_early_virt_to_phys(unsigned long vaddr) sizeof(pud))); if (!pud_present(pud)) return 0; - pa = pud_pfn(pud) << PAGE_SHIFT; + pa = pud_val(pud) & PTE_PFN_MASK; if (pud_large(pud)) return pa + (vaddr & ~PUD_MASK); @@ -2054,7 +2055,7 @@ static phys_addr_t __init xen_early_virt_to_phys(unsigned long vaddr) sizeof(pmd))); if (!pmd_present(pmd)) return 0; - pa = pmd_pfn(pmd) << PAGE_SHIFT; + pa = pmd_val(pmd) & PTE_PFN_MASK; if (pmd_large(pmd)) return pa + (vaddr & ~PMD_MASK); -- cgit v1.2.3-59-g8ed1b From cea582247a0aea78b4674c32833c10b8820fcdbe Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 12 May 2017 15:46:44 -0700 Subject: Tigran has moved Cc: Tigran Aivazian Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/filesystems/bfs.txt | 2 +- MAINTAINERS | 2 +- arch/x86/kernel/cpu/microcode/amd.c | 2 +- arch/x86/kernel/cpu/microcode/core.c | 2 +- arch/x86/kernel/cpu/microcode/intel.c | 2 +- fs/bfs/inode.c | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/Documentation/filesystems/bfs.txt b/Documentation/filesystems/bfs.txt index 78043d5a8fc3..843ce91a2e40 100644 --- a/Documentation/filesystems/bfs.txt +++ b/Documentation/filesystems/bfs.txt @@ -54,4 +54,4 @@ The first 4 bytes should be 0x1badface. If you have any patches, questions or suggestions regarding this BFS implementation please contact the author: -Tigran Aivazian +Tigran Aivazian diff --git a/MAINTAINERS b/MAINTAINERS index 6b36037cbe8f..f7d568b8f133 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2483,7 +2483,7 @@ S: Maintained F: drivers/net/ethernet/ec_bhf.c BFS FILE SYSTEM -M: "Tigran A. Aivazian" +M: "Tigran A. Aivazian" S: Maintained F: Documentation/filesystems/bfs.txt F: fs/bfs/ diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index 1d38e53c2d5c..45db4d2ebd01 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -10,7 +10,7 @@ * Author: Peter Oruba * * Based on work by: - * Tigran Aivazian + * Tigran Aivazian * * early loader: * Copyright (C) 2013 Advanced Micro Devices, Inc. diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index b4a4cd39b358..e53d3c909840 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c @@ -1,7 +1,7 @@ /* * CPU Microcode Update Driver for Linux * - * Copyright (C) 2000-2006 Tigran Aivazian + * Copyright (C) 2000-2006 Tigran Aivazian * 2006 Shaohua Li * 2013-2016 Borislav Petkov * diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c index 8325d8a09ab0..afdfd237b59f 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -1,7 +1,7 @@ /* * Intel CPU Microcode Update Driver for Linux * - * Copyright (C) 2000-2006 Tigran Aivazian + * Copyright (C) 2000-2006 Tigran Aivazian * 2006 Shaohua Li * * Intel CPU microcode early update for Linux diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index f2deec0a62f0..25e312cb6071 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -1,7 +1,7 @@ /* * fs/bfs/inode.c * BFS superblock and inode operations. - * Copyright (C) 1999-2006 Tigran Aivazian + * Copyright (C) 1999-2006 Tigran Aivazian * From fs/minix, Copyright (C) 1991, 1992 Linus Torvalds. * * Made endianness-clean by Andrew Stribblehill , 2005. @@ -19,7 +19,7 @@ #include #include "bfs.h" -MODULE_AUTHOR("Tigran Aivazian "); +MODULE_AUTHOR("Tigran Aivazian "); MODULE_DESCRIPTION("SCO UnixWare BFS filesystem for Linux"); MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b