From patchwork Tue Jan 13 14:25:11 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Grall X-Patchwork-Id: 42996 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wi0-f199.google.com (mail-wi0-f199.google.com [209.85.212.199]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id AD15220DE8 for ; Tue, 13 Jan 2015 14:27:52 +0000 (UTC) Received: by mail-wi0-f199.google.com with SMTP id bs8sf2098768wib.2 for ; Tue, 13 Jan 2015 06:27:52 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:date:message-id:in-reply-to :references:cc:subject:precedence:list-id:list-unsubscribe:list-post :list-help:list-subscribe:mime-version:content-type :content-transfer-encoding:sender:errors-to:x-original-sender :x-original-authentication-results:mailing-list:list-archive; bh=lIooZ4tQz7RArgNw8WP43K7J2CwZLLXKVDuHXdeLAxY=; b=KsHktVn/nivKH6btGUnzFwcNAiUnizGtxf7zhDFBgD7lF4SvgFyqU0q6iD1CbQxZJ9 wyoxGVbd8h24ZfUgLxEf1lKfmZogjr0odDfojLHM+QaKUWW1riNsMXIGTwrodhTi+rWt Wj0f/vxCg9oVEBhxZ1Z9NgyomBib0hMBuUehpRUpZcDob/OokQDYOO1nQ3AQ6OoDdguK LBrke6J68wCj+zMg6OKSFVHhcGfhfOSFgi/vXR+/Zl6wY1MYKFXEbp4uQfwaz/iK8cdd pJG9jLs6AHsop8uEJ8M0SfpWjviJhGkCKHIh/hK3BVaVuRci+o95pG3T/Qsptri6DkKZ aAPA== X-Gm-Message-State: ALoCoQkbomJxVQVknz1QX5hID/IZ8UO/Z7SPaM9ijgDmK8hXaqeJJin8aZpytzp4UtzBb4MGX0qp X-Received: by 10.180.228.38 with SMTP id sf6mr2899463wic.5.1421159271975; Tue, 13 Jan 2015 06:27:51 -0800 (PST) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.44.232 with SMTP id h8ls4012lam.3.gmail; Tue, 13 Jan 2015 06:27:51 -0800 (PST) X-Received: by 10.112.154.70 with SMTP id vm6mr42746143lbb.18.1421159271749; Tue, 13 Jan 2015 06:27:51 -0800 (PST) Received: from mail-la0-f53.google.com (mail-la0-f53.google.com. [209.85.215.53]) by mx.google.com with ESMTPS id la9si3049326lab.65.2015.01.13.06.27.51 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 13 Jan 2015 06:27:51 -0800 (PST) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.53 as permitted sender) client-ip=209.85.215.53; Received: by mail-la0-f53.google.com with SMTP id gm9so2864740lab.12 for ; Tue, 13 Jan 2015 06:27:51 -0800 (PST) X-Received: by 10.112.41.234 with SMTP id i10mr43241042lbl.25.1421159271655; Tue, 13 Jan 2015 06:27:51 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.9.200 with SMTP id c8csp1398757lbb; Tue, 13 Jan 2015 06:27:50 -0800 (PST) X-Received: by 10.53.13.204 with SMTP id fa12mr17981263vdd.16.1421159264993; Tue, 13 Jan 2015 06:27:44 -0800 (PST) Received: from lists.xen.org (lists.xen.org. [50.57.142.19]) by mx.google.com with ESMTPS id ri1si8083460vcb.43.2015.01.13.06.27.44 (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 13 Jan 2015 06:27:44 -0800 (PST) Received-SPF: none (google.com: xen-devel-bounces@lists.xen.org does not designate permitted sender hosts) client-ip=50.57.142.19; Received: from localhost ([127.0.0.1] helo=lists.xen.org) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1YB2QU-00017r-VC; Tue, 13 Jan 2015 14:26:34 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1YB2QT-00016d-L9 for xen-devel@lists.xenproject.org; Tue, 13 Jan 2015 14:26:33 +0000 Received: from [85.158.137.68] by server-5.bemta-3.messagelabs.com id 47/1E-26858-81B25B45; Tue, 13 Jan 2015 14:26:32 +0000 X-Env-Sender: julien.grall@linaro.org X-Msg-Ref: server-3.tower-31.messagelabs.com!1421159191!19301891!1 X-Originating-IP: [209.85.212.172] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 6.12.5; banners=-,-,- X-VirusChecked: Checked Received: (qmail 10418 invoked from network); 13 Jan 2015 14:26:31 -0000 Received: from mail-wi0-f172.google.com (HELO mail-wi0-f172.google.com) (209.85.212.172) by server-3.tower-31.messagelabs.com with RC4-SHA encrypted SMTP; 13 Jan 2015 14:26:31 -0000 Received: by mail-wi0-f172.google.com with SMTP id n3so21607149wiv.5 for ; Tue, 13 Jan 2015 06:26:31 -0800 (PST) X-Received: by 10.194.92.235 with SMTP id cp11mr36445075wjb.112.1421159185798; Tue, 13 Jan 2015 06:26:25 -0800 (PST) Received: from chilopoda.uk.xensource.com. ([185.25.64.249]) by mx.google.com with ESMTPSA id ni15sm14513482wic.18.2015.01.13.06.26.23 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 13 Jan 2015 06:26:24 -0800 (PST) From: Julien Grall To: xen-devel@lists.xenproject.org Date: Tue, 13 Jan 2015 14:25:11 +0000 Message-Id: <1421159133-31526-3-git-send-email-julien.grall@linaro.org> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1421159133-31526-1-git-send-email-julien.grall@linaro.org> References: <1421159133-31526-1-git-send-email-julien.grall@linaro.org> Cc: stefano.stabellini@citrix.com, Julien Grall , tim@xen.org, ian.campbell@citrix.com Subject: [Xen-devel] [PATCH v3 02/24] xen/arm: Divide GIC initialization in 2 parts X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: List-Unsubscribe: , List-Post: , List-Help: , List-Subscribe: , MIME-Version: 1.0 Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: julien.grall@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.53 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Archive: Currently the function to translate IRQ from the device tree is set unconditionally to be able to be able to retrieve serial/timer IRQ before the GIC has been initialized. It assumes that the xlate function won't never changed. We may also need to have the primary interrupt controller very early. Rework the gic initialization in 2 parts: - gic_preinit: Get the interrupt controller device tree node and set up GIC and xlate callbacks - gic_init: Initialize the interrupt controller and the boot CPU interrupts. The former function will be called just after the IRQ subsystem as been initialized. Signed-off-by: Julien Grall --- Changes in v3: - Patch was previously sent in a separate series [1] - Reorder the function to avoid forward declaration - Make gic-v3 driver compliant to the new interface - Remove spurious field addition in gicv2 structure Changelog based on the separate series: Changes in v3: - Patch added. [1] https://patches.linaro.org/33313/ --- xen/arch/arm/gic-v2.c | 70 ++++++++++++++++++++++--------------------- xen/arch/arm/gic-v3.c | 75 ++++++++++++++++++++++++----------------------- xen/arch/arm/gic.c | 16 ++++++++-- xen/arch/arm/setup.c | 3 +- xen/include/asm-arm/gic.h | 8 +++++ 5 files changed, 100 insertions(+), 72 deletions(-) diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c index 15916c9..016b0fd 100644 --- a/xen/arch/arm/gic-v2.c +++ b/xen/arch/arm/gic-v2.c @@ -655,37 +655,10 @@ static hw_irq_controller gicv2_guest_irq_type = { .set_affinity = gicv2_irq_set_affinity, }; -const static struct gic_hw_operations gicv2_ops = { - .info = &gicv2_info, - .secondary_init = gicv2_secondary_cpu_init, - .save_state = gicv2_save_state, - .restore_state = gicv2_restore_state, - .dump_state = gicv2_dump_state, - .gicv_setup = gicv2v_setup, - .gic_host_irq_type = &gicv2_host_irq_type, - .gic_guest_irq_type = &gicv2_guest_irq_type, - .eoi_irq = gicv2_eoi_irq, - .deactivate_irq = gicv2_dir_irq, - .read_irq = gicv2_read_irq, - .set_irq_properties = gicv2_set_irq_properties, - .send_SGI = gicv2_send_SGI, - .disable_interface = gicv2_disable_interface, - .update_lr = gicv2_update_lr, - .update_hcr_status = gicv2_hcr_status, - .clear_lr = gicv2_clear_lr, - .read_lr = gicv2_read_lr, - .write_lr = gicv2_write_lr, - .read_vmcr_priority = gicv2_read_vmcr_priority, - .read_apr = gicv2_read_apr, - .make_dt_node = gicv2_make_dt_node, -}; - -/* Set up the GIC */ -static int __init gicv2_init(struct dt_device_node *node, const void *data) +static int __init gicv2_init(void) { int res; - - dt_device_set_used_by(node, DOMID_XEN); + const struct dt_device_node *node = gicv2_info.node; res = dt_device_get_address(node, 0, &gicv2.dbase, NULL); if ( res || !gicv2.dbase || (gicv2.dbase & ~PAGE_MASK) ) @@ -708,9 +681,6 @@ static int __init gicv2_init(struct dt_device_node *node, const void *data) panic("GICv2: Cannot find the maintenance IRQ"); gicv2_info.maintenance_irq = res; - /* Set the GIC as the primary interrupt controller */ - dt_interrupt_controller = node; - /* TODO: Add check on distributor, cpu size */ printk("GICv2 initialization:\n" @@ -755,8 +725,42 @@ static int __init gicv2_init(struct dt_device_node *node, const void *data) spin_unlock(&gicv2.lock); + return 0; +} + +const static struct gic_hw_operations gicv2_ops = { + .info = &gicv2_info, + .init = gicv2_init, + .secondary_init = gicv2_secondary_cpu_init, + .save_state = gicv2_save_state, + .restore_state = gicv2_restore_state, + .dump_state = gicv2_dump_state, + .gicv_setup = gicv2v_setup, + .gic_host_irq_type = &gicv2_host_irq_type, + .gic_guest_irq_type = &gicv2_guest_irq_type, + .eoi_irq = gicv2_eoi_irq, + .deactivate_irq = gicv2_dir_irq, + .read_irq = gicv2_read_irq, + .set_irq_properties = gicv2_set_irq_properties, + .send_SGI = gicv2_send_SGI, + .disable_interface = gicv2_disable_interface, + .update_lr = gicv2_update_lr, + .update_hcr_status = gicv2_hcr_status, + .clear_lr = gicv2_clear_lr, + .read_lr = gicv2_read_lr, + .write_lr = gicv2_write_lr, + .read_vmcr_priority = gicv2_read_vmcr_priority, + .read_apr = gicv2_read_apr, + .make_dt_node = gicv2_make_dt_node, +}; + +/* Set up the GIC */ +static int __init gicv2_preinit(struct dt_device_node *node, const void *data) +{ gicv2_info.hw_version = GIC_V2; + gicv2_info.node = node; register_gic_ops(&gicv2_ops); + dt_irq_xlate = gic_irq_xlate; return 0; } @@ -769,7 +773,7 @@ static const struct dt_device_match gicv2_dt_match[] __initconst = DT_DEVICE_START(gicv2, "GICv2", DEVICE_GIC) .dt_match = gicv2_dt_match, - .init = gicv2_init, + .init = gicv2_preinit, DT_DEVICE_END /* diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c index 2ddcbab..f650756 100644 --- a/xen/arch/arm/gic-v3.c +++ b/xen/arch/arm/gic-v3.c @@ -1141,37 +1141,13 @@ static const hw_irq_controller gicv3_guest_irq_type = { .set_affinity = gicv3_irq_set_affinity, }; -static const struct gic_hw_operations gicv3_ops = { - .info = &gicv3_info, - .save_state = gicv3_save_state, - .restore_state = gicv3_restore_state, - .dump_state = gicv3_dump_state, - .gicv_setup = gicv_v3_init, - .gic_host_irq_type = &gicv3_host_irq_type, - .gic_guest_irq_type = &gicv3_guest_irq_type, - .eoi_irq = gicv3_eoi_irq, - .deactivate_irq = gicv3_dir_irq, - .read_irq = gicv3_read_irq, - .set_irq_properties = gicv3_set_irq_properties, - .send_SGI = gicv3_send_sgi, - .disable_interface = gicv3_disable_interface, - .update_lr = gicv3_update_lr, - .update_hcr_status = gicv3_hcr_status, - .clear_lr = gicv3_clear_lr, - .read_lr = gicv3_read_lr, - .write_lr = gicv3_write_lr, - .read_vmcr_priority = gicv3_read_vmcr_priority, - .read_apr = gicv3_read_apr, - .secondary_init = gicv3_secondary_cpu_init, - .make_dt_node = gicv3_make_dt_node, -}; - /* Set up the GIC */ -static int __init gicv3_init(struct dt_device_node *node, const void *data) +static int __init gicv3_init(void) { struct rdist_region *rdist_regs; int res, i; uint32_t reg; + const struct dt_device_node *node = gicv3_info.node; if ( !cpu_has_gicv3 ) { @@ -1179,8 +1155,6 @@ static int __init gicv3_init(struct dt_device_node *node, const void *data) return -ENODEV; } - dt_device_set_used_by(node, DOMID_XEN); - res = dt_device_get_address(node, 0, &gicv3.dbase, &gicv3.dbase_size); if ( res || !gicv3.dbase ) panic("GICv3: Cannot find a valid distributor address"); @@ -1232,9 +1206,6 @@ static int __init gicv3_init(struct dt_device_node *node, const void *data) panic("GICv3: Cannot find the maintenance IRQ"); gicv3_info.maintenance_irq = res; - /* Set the GIC as the primary interrupt controller */ - dt_interrupt_controller = node; - for ( i = 0; i < gicv3.rdist_count; i++ ) { /* map dbase & rdist regions */ @@ -1269,15 +1240,47 @@ static int __init gicv3_init(struct dt_device_node *node, const void *data) res = gicv3_cpu_init(); gicv3_hyp_init(); - gicv3_info.hw_version = GIC_V3; - /* Register hw ops*/ - register_gic_ops(&gicv3_ops); - spin_unlock(&gicv3.lock); return res; } +static const struct gic_hw_operations gicv3_ops = { + .info = &gicv3_info, + .init = gicv3_init, + .save_state = gicv3_save_state, + .restore_state = gicv3_restore_state, + .dump_state = gicv3_dump_state, + .gicv_setup = gicv_v3_init, + .gic_host_irq_type = &gicv3_host_irq_type, + .gic_guest_irq_type = &gicv3_guest_irq_type, + .eoi_irq = gicv3_eoi_irq, + .deactivate_irq = gicv3_dir_irq, + .read_irq = gicv3_read_irq, + .set_irq_properties = gicv3_set_irq_properties, + .send_SGI = gicv3_send_sgi, + .disable_interface = gicv3_disable_interface, + .update_lr = gicv3_update_lr, + .update_hcr_status = gicv3_hcr_status, + .clear_lr = gicv3_clear_lr, + .read_lr = gicv3_read_lr, + .write_lr = gicv3_write_lr, + .read_vmcr_priority = gicv3_read_vmcr_priority, + .read_apr = gicv3_read_apr, + .secondary_init = gicv3_secondary_cpu_init, + .make_dt_node = gicv3_make_dt_node, +}; + +static int __init gicv3_preinit(struct dt_device_node *node, const void *data) +{ + gicv3_info.hw_version = GIC_V3; + gicv3_info.node = node; + register_gic_ops(&gicv3_ops); + dt_irq_xlate = gic_irq_xlate; + + return 0; +} + static const struct dt_device_match gicv3_dt_match[] __initconst = { DT_MATCH_GIC_V3, @@ -1286,7 +1289,7 @@ static const struct dt_device_match gicv3_dt_match[] __initconst = DT_DEVICE_START(gicv3, "GICv3", DEVICE_GIC) .dt_match = gicv3_dt_match, - .init = gicv3_init, + .init = gicv3_preinit, DT_DEVICE_END /* diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index d1ab6b5..63147f3 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -163,8 +163,10 @@ int gic_irq_xlate(const u32 *intspec, unsigned int intsize, return 0; } -/* Set up the GIC */ -void __init gic_init(void) +/* Find the interrupt controller and set up the callback to translate + * device tree IRQ. + */ +void __init gic_preinit(void) { int rc; struct dt_device_node *node; @@ -189,6 +191,16 @@ void __init gic_init(void) if ( !num_gics ) panic("Unable to find compatible GIC in the device tree"); + /* Set the GIC as the primary interrupt controller */ + dt_interrupt_controller = node; + dt_device_set_used_by(node, DOMID_XEN); +} + +/* Set up the GIC */ +void __init gic_init(void) +{ + if ( gic_hw_ops->init() ) + panic("Failed to initialize the GIC drivers"); /* Clear LR mask for cpu0 */ clear_cpu_lr_mask(); } diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c index 4d242e0..18227f6 100644 --- a/xen/arch/arm/setup.c +++ b/xen/arch/arm/setup.c @@ -740,10 +740,11 @@ void __init start_xen(unsigned long boot_phys_offset, vm_init(); dt_unflatten_host_device_tree(); - dt_irq_xlate = gic_irq_xlate; init_IRQ(); + gic_preinit(); + dt_uart_init(); console_init_preirq(); console_init_ring(); diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h index 73ca3cf..6286c71 100644 --- a/xen/include/asm-arm/gic.h +++ b/xen/include/asm-arm/gic.h @@ -229,6 +229,10 @@ extern void gic_remove_from_queues(struct vcpu *v, unsigned int virtual_irq); /* Accept an interrupt from the GIC and dispatch its handler */ extern void gic_interrupt(struct cpu_user_regs *regs, int is_fiq); +/* Find the interrupt controller and set up the callback to translate + * device tree IRQ. + */ +extern void gic_preinit(void); /* Bring up the interrupt controller, and report # cpus attached */ extern void gic_init(void); /* Bring up a secondary CPU's per-CPU GIC interface */ @@ -281,11 +285,15 @@ struct gic_info { uint8_t nr_lrs; /* Maintenance irq number */ unsigned int maintenance_irq; + /* Pointer to the device tree node representing the interrupt controller */ + const struct dt_device_node *node; }; struct gic_hw_operations { /* Hold GIC HW information */ const struct gic_info *info; + /* Initialize the GIC and the boot CPU */ + int (*init)(void); /* Save GIC registers */ void (*save_state)(struct vcpu *); /* Restore GIC registers */