diff options
Diffstat (limited to 'arch')
144 files changed, 3638 insertions, 2144 deletions
diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c index ff03ca642089..611a52d60188 100644 --- a/arch/alpha/kernel/irq.c +++ b/arch/alpha/kernel/irq.c @@ -62,13 +62,13 @@ no_irq_ack(unsigned int irq) } struct hw_interrupt_type no_irq_type = { - typename: "none", - startup: no_irq_startup, - shutdown: no_irq_enable_disable, - enable: no_irq_enable_disable, - disable: no_irq_enable_disable, - ack: no_irq_ack, - end: no_irq_enable_disable, + .typename = "none", + .startup = no_irq_startup, + .shutdown = no_irq_enable_disable, + .enable = no_irq_enable_disable, + .disable = no_irq_enable_disable, + .ack = no_irq_ack, + .end = no_irq_enable_disable, }; int diff --git a/arch/alpha/kernel/irq_alpha.c b/arch/alpha/kernel/irq_alpha.c index c765add9fa67..476f17980249 100644 --- a/arch/alpha/kernel/irq_alpha.c +++ b/arch/alpha/kernel/irq_alpha.c @@ -213,19 +213,19 @@ static void rtc_enable_disable(unsigned int irq) { } static unsigned int rtc_startup(unsigned int irq) { return 0; } struct irqaction timer_irqaction = { - handler: timer_interrupt, - flags: SA_INTERRUPT, - name: "timer", + .handler = timer_interrupt, + .flags = SA_INTERRUPT, + .name = "timer", }; static struct hw_interrupt_type rtc_irq_type = { - typename: "RTC", - startup: rtc_startup, - shutdown: rtc_enable_disable, - enable: rtc_enable_disable, - disable: rtc_enable_disable, - ack: rtc_enable_disable, - end: rtc_enable_disable, + .typename = "RTC", + .startup = rtc_startup, + .shutdown = rtc_enable_disable, + .enable = rtc_enable_disable, + .disable = rtc_enable_disable, + .ack = rtc_enable_disable, + .end = rtc_enable_disable, }; void __init @@ -238,16 +238,16 @@ init_rtc_irq(void) /* Dummy irqactions. */ struct irqaction isa_cascade_irqaction = { - handler: no_action, - name: "isa-cascade" + .handler = no_action, + .name = "isa-cascade" }; struct irqaction timer_cascade_irqaction = { - handler: no_action, - name: "timer-cascade" + .handler = no_action, + .name = "timer-cascade" }; struct irqaction halt_switch_irqaction = { - handler: no_action, - name: "halt-switch" + .handler = no_action, + .name = "halt-switch" }; diff --git a/arch/alpha/kernel/irq_i8259.c b/arch/alpha/kernel/irq_i8259.c index 4635ae7ac2ad..f308e98ff210 100644 --- a/arch/alpha/kernel/irq_i8259.c +++ b/arch/alpha/kernel/irq_i8259.c @@ -85,21 +85,21 @@ i8259a_end_irq(unsigned int irq) } struct hw_interrupt_type i8259a_irq_type = { - typename: "XT-PIC", - startup: i8259a_startup_irq, - shutdown: i8259a_disable_irq, - enable: i8259a_enable_irq, - disable: i8259a_disable_irq, - ack: i8259a_mask_and_ack_irq, - end: i8259a_end_irq, + .typename = "XT-PIC", + .startup = i8259a_startup_irq, + .shutdown = i8259a_disable_irq, + .enable = i8259a_enable_irq, + .disable = i8259a_disable_irq, + .ack = i8259a_mask_and_ack_irq, + .end = i8259a_end_irq, }; void __init init_i8259a_irqs(void) { static struct irqaction cascade = { - handler: no_action, - name: "cascade", + .handler = no_action, + .name = "cascade", }; long i; diff --git a/arch/alpha/kernel/irq_pyxis.c b/arch/alpha/kernel/irq_pyxis.c index 65414a7f50ee..146a20b9e3d5 100644 --- a/arch/alpha/kernel/irq_pyxis.c +++ b/arch/alpha/kernel/irq_pyxis.c @@ -71,13 +71,13 @@ pyxis_mask_and_ack_irq(unsigned int irq) } static struct hw_interrupt_type pyxis_irq_type = { - typename: "PYXIS", - startup: pyxis_startup_irq, - shutdown: pyxis_disable_irq, - enable: pyxis_enable_irq, - disable: pyxis_disable_irq, - ack: pyxis_mask_and_ack_irq, - end: pyxis_end_irq, + .typename = "PYXIS", + .startup = pyxis_startup_irq, + .shutdown = pyxis_disable_irq, + .enable = pyxis_enable_irq, + .disable = pyxis_disable_irq, + .ack = pyxis_mask_and_ack_irq, + .end = pyxis_end_irq, }; void diff --git a/arch/alpha/kernel/irq_srm.c b/arch/alpha/kernel/irq_srm.c index 51806c9962e4..b51316cfabf6 100644 --- a/arch/alpha/kernel/irq_srm.c +++ b/arch/alpha/kernel/irq_srm.c @@ -49,13 +49,13 @@ srm_end_irq(unsigned int irq) /* Handle interrupts from the SRM, assuming no additional weirdness. */ static struct hw_interrupt_type srm_irq_type = { - typename: "SRM", - startup: srm_startup_irq, - shutdown: srm_disable_irq, - enable: srm_enable_irq, - disable: srm_disable_irq, - ack: srm_disable_irq, - end: srm_end_irq, + .typename = "SRM", + .startup = srm_startup_irq, + .shutdown = srm_disable_irq, + .enable = srm_enable_irq, + .disable = srm_disable_irq, + .ack = srm_disable_irq, + .end = srm_end_irq, }; void __init diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c index bec5ea08989f..594e139ebfc6 100644 --- a/arch/alpha/kernel/setup.c +++ b/arch/alpha/kernel/setup.c @@ -112,12 +112,12 @@ char saved_command_line[COMMAND_LINE_SIZE]; */ struct screen_info screen_info = { - orig_x: 0, - orig_y: 25, - orig_video_cols: 80, - orig_video_lines: 25, - orig_video_isVGA: 1, - orig_video_points: 16 + .orig_x = 0, + .orig_y = 25, + .orig_video_cols = 80, + .orig_video_lines = 25, + .orig_video_isVGA = 1, + .orig_video_points = 16 }; /* @@ -452,12 +452,12 @@ static int __init srm_console_setup(struct console *co, char *options) } static struct console srmcons = { - name: "srm0", - write: srm_console_write, - device: srm_console_device, - setup: srm_console_setup, - flags: CON_PRINTBUFFER | CON_ENABLED, /* fake it out */ - index: -1, + .name = "srm0", + .write = srm_console_write, + .device = srm_console_device, + .setup = srm_console_setup, + .flags = CON_PRINTBUFFER | CON_ENABLED, /* fake it out */ + .index = -1, }; #else @@ -1150,10 +1150,10 @@ c_stop(struct seq_file *f, void *v) } struct seq_operations cpuinfo_op = { - start: c_start, - next: c_next, - stop: c_stop, - show: show_cpuinfo, + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = show_cpuinfo, }; diff --git a/arch/alpha/kernel/sys_alcor.c b/arch/alpha/kernel/sys_alcor.c index fa32465ab44f..9eda25b63086 100644 --- a/arch/alpha/kernel/sys_alcor.c +++ b/arch/alpha/kernel/sys_alcor.c @@ -91,13 +91,13 @@ alcor_end_irq(unsigned int irq) } static struct hw_interrupt_type alcor_irq_type = { - typename: "ALCOR", - startup: alcor_startup_irq, - shutdown: alcor_disable_irq, - enable: alcor_enable_irq, - disable: alcor_disable_irq, - ack: alcor_mask_and_ack_irq, - end: alcor_end_irq, + .typename = "ALCOR", + .startup = alcor_startup_irq, + .shutdown = alcor_disable_irq, + .enable = alcor_enable_irq, + .disable = alcor_disable_irq, + .ack = alcor_mask_and_ack_irq, + .end = alcor_end_irq, }; static void @@ -245,29 +245,29 @@ alcor_kill_arch(int mode) #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_ALCOR) struct alpha_machine_vector alcor_mv __initmv = { - vector_name: "Alcor", + .vector_name = "Alcor", DO_EV5_MMU, DO_DEFAULT_RTC, DO_CIA_IO, DO_CIA_BUS, - machine_check: cia_machine_check, - max_dma_address: ALPHA_ALCOR_MAX_DMA_ADDRESS, - min_io_address: EISA_DEFAULT_IO_BASE, - min_mem_address: CIA_DEFAULT_MEM_BASE, - - nr_irqs: 48, - device_interrupt: alcor_device_interrupt, - - init_arch: cia_init_arch, - init_irq: alcor_init_irq, - init_rtc: common_init_rtc, - init_pci: cia_init_pci, - kill_arch: alcor_kill_arch, - pci_map_irq: alcor_map_irq, - pci_swizzle: common_swizzle, - - sys: { cia: { - gru_int_req_bits: ALCOR_GRU_INT_REQ_BITS + .machine_check = cia_machine_check, + .max_dma_address = ALPHA_ALCOR_MAX_DMA_ADDRESS, + .min_io_address = EISA_DEFAULT_IO_BASE, + .min_mem_address = CIA_DEFAULT_MEM_BASE, + + .nr_irqs = 48, + .device_interrupt = alcor_device_interrupt, + + .init_arch = cia_init_arch, + .init_irq = alcor_init_irq, + .init_rtc = common_init_rtc, + .init_pci = cia_init_pci, + .kill_arch = alcor_kill_arch, + .pci_map_irq = alcor_map_irq, + .pci_swizzle = common_swizzle, + + .sys = { .cia = { + .gru_int_req_bits = ALCOR_GRU_INT_REQ_BITS }} }; ALIAS_MV(alcor) @@ -275,29 +275,29 @@ ALIAS_MV(alcor) #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_XLT) struct alpha_machine_vector xlt_mv __initmv = { - vector_name: "XLT", + .vector_name = "XLT", DO_EV5_MMU, DO_DEFAULT_RTC, DO_CIA_IO, DO_CIA_BUS, - machine_check: cia_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: EISA_DEFAULT_IO_BASE, - min_mem_address: CIA_DEFAULT_MEM_BASE, - - nr_irqs: 48, - device_interrupt: alcor_device_interrupt, - - init_arch: cia_init_arch, - init_irq: alcor_init_irq, - init_rtc: common_init_rtc, - init_pci: cia_init_pci, - kill_arch: alcor_kill_arch, - pci_map_irq: alcor_map_irq, - pci_swizzle: common_swizzle, - - sys: { cia: { - gru_int_req_bits: XLT_GRU_INT_REQ_BITS + .machine_check = cia_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = EISA_DEFAULT_IO_BASE, + .min_mem_address = CIA_DEFAULT_MEM_BASE, + + .nr_irqs = 48, + .device_interrupt = alcor_device_interrupt, + + .init_arch = cia_init_arch, + .init_irq = alcor_init_irq, + .init_rtc = common_init_rtc, + .init_pci = cia_init_pci, + .kill_arch = alcor_kill_arch, + .pci_map_irq = alcor_map_irq, + .pci_swizzle = common_swizzle, + + .sys = { .cia = { + .gru_int_req_bits = XLT_GRU_INT_REQ_BITS }} }; ALIAS_MV(xlt) diff --git a/arch/alpha/kernel/sys_cabriolet.c b/arch/alpha/kernel/sys_cabriolet.c index 618cd340a31c..68fb947bb057 100644 --- a/arch/alpha/kernel/sys_cabriolet.c +++ b/arch/alpha/kernel/sys_cabriolet.c @@ -73,13 +73,13 @@ cabriolet_end_irq(unsigned int irq) } static struct hw_interrupt_type cabriolet_irq_type = { - typename: "CABRIOLET", - startup: cabriolet_startup_irq, - shutdown: cabriolet_disable_irq, - enable: cabriolet_enable_irq, - disable: cabriolet_disable_irq, - ack: cabriolet_disable_irq, - end: cabriolet_end_irq, + .typename = "CABRIOLET", + .startup = cabriolet_startup_irq, + .shutdown = cabriolet_disable_irq, + .enable = cabriolet_enable_irq, + .disable = cabriolet_disable_irq, + .ack = cabriolet_disable_irq, + .end = cabriolet_end_irq, }; static void @@ -321,26 +321,26 @@ alphapc164_init_pci(void) #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_CABRIOLET) struct alpha_machine_vector cabriolet_mv __initmv = { - vector_name: "Cabriolet", + .vector_name = "Cabriolet", DO_EV4_MMU, DO_DEFAULT_RTC, DO_APECS_IO, DO_APECS_BUS, - machine_check: apecs_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE, - - nr_irqs: 35, - device_interrupt: cabriolet_device_interrupt, - - init_arch: apecs_init_arch, - init_irq: cabriolet_init_irq, - init_rtc: common_init_rtc, - init_pci: cabriolet_init_pci, - kill_arch: NULL, - pci_map_irq: cabriolet_map_irq, - pci_swizzle: common_swizzle, + .machine_check = apecs_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE, + + .nr_irqs = 35, + .device_interrupt = cabriolet_device_interrupt, + + .init_arch = apecs_init_arch, + .init_irq = cabriolet_init_irq, + .init_rtc = common_init_rtc, + .init_pci = cabriolet_init_pci, + .kill_arch = NULL, + .pci_map_irq = cabriolet_map_irq, + .pci_swizzle = common_swizzle, }; #ifndef CONFIG_ALPHA_EB64P ALIAS_MV(cabriolet) @@ -349,101 +349,101 @@ ALIAS_MV(cabriolet) #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB164) struct alpha_machine_vector eb164_mv __initmv = { - vector_name: "EB164", + .vector_name = "EB164", DO_EV5_MMU, DO_DEFAULT_RTC, DO_CIA_IO, DO_CIA_BUS, - machine_check: cia_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: CIA_DEFAULT_MEM_BASE, - - nr_irqs: 35, - device_interrupt: cabriolet_device_interrupt, - - init_arch: cia_init_arch, - init_irq: cabriolet_init_irq, - init_rtc: common_init_rtc, - init_pci: cia_cab_init_pci, - pci_map_irq: cabriolet_map_irq, - pci_swizzle: common_swizzle, + .machine_check = cia_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = CIA_DEFAULT_MEM_BASE, + + .nr_irqs = 35, + .device_interrupt = cabriolet_device_interrupt, + + .init_arch = cia_init_arch, + .init_irq = cabriolet_init_irq, + .init_rtc = common_init_rtc, + .init_pci = cia_cab_init_pci, + .pci_map_irq = cabriolet_map_irq, + .pci_swizzle = common_swizzle, }; ALIAS_MV(eb164) #endif #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB66P) struct alpha_machine_vector eb66p_mv __initmv = { - vector_name: "EB66+", + .vector_name = "EB66+", DO_EV4_MMU, DO_DEFAULT_RTC, DO_LCA_IO, DO_LCA_BUS, - machine_check: lca_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE, - - nr_irqs: 35, - device_interrupt: cabriolet_device_interrupt, - - init_arch: lca_init_arch, - init_irq: cabriolet_init_irq, - init_rtc: common_init_rtc, - init_pci: cabriolet_init_pci, - pci_map_irq: eb66p_map_irq, - pci_swizzle: common_swizzle, + .machine_check = lca_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE, + + .nr_irqs = 35, + .device_interrupt = cabriolet_device_interrupt, + + .init_arch = lca_init_arch, + .init_irq = cabriolet_init_irq, + .init_rtc = common_init_rtc, + .init_pci = cabriolet_init_pci, + .pci_map_irq = eb66p_map_irq, + .pci_swizzle = common_swizzle, }; ALIAS_MV(eb66p) #endif #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_LX164) struct alpha_machine_vector lx164_mv __initmv = { - vector_name: "LX164", + .vector_name = "LX164", DO_EV5_MMU, DO_DEFAULT_RTC, DO_PYXIS_IO, DO_CIA_BUS, - machine_check: cia_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: DEFAULT_MEM_BASE, - pci_dac_offset: PYXIS_DAC_OFFSET, - - nr_irqs: 35, - device_interrupt: cabriolet_device_interrupt, - - init_arch: pyxis_init_arch, - init_irq: cabriolet_init_irq, - init_rtc: common_init_rtc, - init_pci: alphapc164_init_pci, - pci_map_irq: alphapc164_map_irq, - pci_swizzle: common_swizzle, + .machine_check = cia_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = DEFAULT_MEM_BASE, + .pci_dac_offset = PYXIS_DAC_OFFSET, + + .nr_irqs = 35, + .device_interrupt = cabriolet_device_interrupt, + + .init_arch = pyxis_init_arch, + .init_irq = cabriolet_init_irq, + .init_rtc = common_init_rtc, + .init_pci = alphapc164_init_pci, + .pci_map_irq = alphapc164_map_irq, + .pci_swizzle = common_swizzle, }; ALIAS_MV(lx164) #endif #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PC164) struct alpha_machine_vector pc164_mv __initmv = { - vector_name: "PC164", + .vector_name = "PC164", DO_EV5_MMU, DO_DEFAULT_RTC, DO_CIA_IO, DO_CIA_BUS, - machine_check: cia_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: CIA_DEFAULT_MEM_BASE, - - nr_irqs: 35, - device_interrupt: pc164_device_interrupt, - - init_arch: cia_init_arch, - init_irq: pc164_init_irq, - init_rtc: common_init_rtc, - init_pci: alphapc164_init_pci, - pci_map_irq: alphapc164_map_irq, - pci_swizzle: common_swizzle, + .machine_check = cia_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = CIA_DEFAULT_MEM_BASE, + + .nr_irqs = 35, + .device_interrupt = pc164_device_interrupt, + + .init_arch = cia_init_arch, + .init_irq = pc164_init_irq, + .init_rtc = common_init_rtc, + .init_pci = alphapc164_init_pci, + .pci_map_irq = alphapc164_map_irq, + .pci_swizzle = common_swizzle, }; ALIAS_MV(pc164) #endif diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c index 3ff877f92dde..20d9ef272bf3 100644 --- a/arch/alpha/kernel/sys_dp264.c +++ b/arch/alpha/kernel/sys_dp264.c @@ -197,25 +197,25 @@ clipper_set_affinity(unsigned int irq, unsigned long affinity) } static struct hw_interrupt_type dp264_irq_type = { - typename: "DP264", - startup: dp264_startup_irq, - shutdown: dp264_disable_irq, - enable: dp264_enable_irq, - disable: dp264_disable_irq, - ack: dp264_disable_irq, - end: dp264_end_irq, - set_affinity: dp264_set_affinity, + .typename = "DP264", + .startup = dp264_startup_irq, + .shutdown = dp264_disable_irq, + .enable = dp264_enable_irq, + .disable = dp264_disable_irq, + .ack = dp264_disable_irq, + .end = dp264_end_irq, + .set_affinity = dp264_set_affinity, }; static struct hw_interrupt_type clipper_irq_type = { - typename: "CLIPPER", - startup: clipper_startup_irq, - shutdown: clipper_disable_irq, - enable: clipper_enable_irq, - disable: clipper_disable_irq, - ack: clipper_disable_irq, - end: clipper_end_irq, - set_affinity: clipper_set_affinity, + .typename = "CLIPPER", + .startup = clipper_startup_irq, + .shutdown = clipper_disable_irq, + .enable = clipper_enable_irq, + .disable = clipper_disable_irq, + .ack = clipper_disable_irq, + .end = clipper_end_irq, + .set_affinity = clipper_set_affinity, }; static void @@ -566,100 +566,100 @@ webbrick_init_arch(void) */ struct alpha_machine_vector dp264_mv __initmv = { - vector_name: "DP264", + .vector_name = "DP264", DO_EV6_MMU, DO_DEFAULT_RTC, DO_TSUNAMI_IO, DO_TSUNAMI_BUS, - machine_check: tsunami_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: DEFAULT_MEM_BASE, - pci_dac_offset: TSUNAMI_DAC_OFFSET, - - nr_irqs: 64, - device_interrupt: dp264_device_interrupt, - - init_arch: tsunami_init_arch, - init_irq: dp264_init_irq, - init_rtc: common_init_rtc, - init_pci: dp264_init_pci, - kill_arch: tsunami_kill_arch, - pci_map_irq: dp264_map_irq, - pci_swizzle: common_swizzle, + .machine_check = tsunami_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = DEFAULT_MEM_BASE, + .pci_dac_offset = TSUNAMI_DAC_OFFSET, + + .nr_irqs = 64, + .device_interrupt = dp264_device_interrupt, + + .init_arch = tsunami_init_arch, + .init_irq = dp264_init_irq, + .init_rtc = common_init_rtc, + .init_pci = dp264_init_pci, + .kill_arch = tsunami_kill_arch, + .pci_map_irq = dp264_map_irq, + .pci_swizzle = common_swizzle, }; ALIAS_MV(dp264) struct alpha_machine_vector monet_mv __initmv = { - vector_name: "Monet", + .vector_name = "Monet", DO_EV6_MMU, DO_DEFAULT_RTC, DO_TSUNAMI_IO, DO_TSUNAMI_BUS, - machine_check: tsunami_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: DEFAULT_MEM_BASE, - pci_dac_offset: TSUNAMI_DAC_OFFSET, - - nr_irqs: 64, - device_interrupt: dp264_device_interrupt, - - init_arch: tsunami_init_arch, - init_irq: dp264_init_irq, - init_rtc: common_init_rtc, - init_pci: monet_init_pci, - kill_arch: tsunami_kill_arch, - pci_map_irq: monet_map_irq, - pci_swizzle: monet_swizzle, + .machine_check = tsunami_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = DEFAULT_MEM_BASE, + .pci_dac_offset = TSUNAMI_DAC_OFFSET, + + .nr_irqs = 64, + .device_interrupt = dp264_device_interrupt, + + .init_arch = tsunami_init_arch, + .init_irq = dp264_init_irq, + .init_rtc = common_init_rtc, + .init_pci = monet_init_pci, + .kill_arch = tsunami_kill_arch, + .pci_map_irq = monet_map_irq, + .pci_swizzle = monet_swizzle, }; struct alpha_machine_vector webbrick_mv __initmv = { - vector_name: "Webbrick", + .vector_name = "Webbrick", DO_EV6_MMU, DO_DEFAULT_RTC, DO_TSUNAMI_IO, DO_TSUNAMI_BUS, - machine_check: tsunami_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: DEFAULT_MEM_BASE, - pci_dac_offset: TSUNAMI_DAC_OFFSET, - - nr_irqs: 64, - device_interrupt: dp264_device_interrupt, - - init_arch: webbrick_init_arch, - init_irq: dp264_init_irq, - init_rtc: common_init_rtc, - init_pci: common_init_pci, - kill_arch: tsunami_kill_arch, - pci_map_irq: webbrick_map_irq, - pci_swizzle: common_swizzle, + .machine_check = tsunami_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = DEFAULT_MEM_BASE, + .pci_dac_offset = TSUNAMI_DAC_OFFSET, + + .nr_irqs = 64, + .device_interrupt = dp264_device_interrupt, + + .init_arch = webbrick_init_arch, + .init_irq = dp264_init_irq, + .init_rtc = common_init_rtc, + .init_pci = common_init_pci, + .kill_arch = tsunami_kill_arch, + .pci_map_irq = webbrick_map_irq, + .pci_swizzle = common_swizzle, }; struct alpha_machine_vector clipper_mv __initmv = { - vector_name: "Clipper", + .vector_name = "Clipper", DO_EV6_MMU, DO_DEFAULT_RTC, DO_TSUNAMI_IO, DO_TSUNAMI_BUS, - machine_check: tsunami_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: DEFAULT_MEM_BASE, - pci_dac_offset: TSUNAMI_DAC_OFFSET, - - nr_irqs: 64, - device_interrupt: dp264_device_interrupt, - - init_arch: tsunami_init_arch, - init_irq: clipper_init_irq, - init_rtc: common_init_rtc, - init_pci: common_init_pci, - kill_arch: tsunami_kill_arch, - pci_map_irq: clipper_map_irq, - pci_swizzle: common_swizzle, + .machine_check = tsunami_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = DEFAULT_MEM_BASE, + .pci_dac_offset = TSUNAMI_DAC_OFFSET, + + .nr_irqs = 64, + .device_interrupt = dp264_device_interrupt, + + .init_arch = tsunami_init_arch, + .init_irq = clipper_init_irq, + .init_rtc = common_init_rtc, + .init_pci = common_init_pci, + .kill_arch = tsunami_kill_arch, + .pci_map_irq = clipper_map_irq, + .pci_swizzle = common_swizzle, }; /* Sharks strongly resemble Clipper, at least as far @@ -668,27 +668,27 @@ struct alpha_machine_vector clipper_mv __initmv = { */ struct alpha_machine_vector shark_mv __initmv = { - vector_name: "Shark", + .vector_name = "Shark", DO_EV6_MMU, DO_DEFAULT_RTC, DO_TSUNAMI_IO, DO_TSUNAMI_BUS, - machine_check: tsunami_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: DEFAULT_MEM_BASE, - pci_dac_offset: TSUNAMI_DAC_OFFSET, - - nr_irqs: 64, - device_interrupt: dp264_device_interrupt, - - init_arch: tsunami_init_arch, - init_irq: clipper_init_irq, - init_rtc: common_init_rtc, - init_pci: common_init_pci, - kill_arch: tsunami_kill_arch, - pci_map_irq: clipper_map_irq, - pci_swizzle: common_swizzle, + .machine_check = tsunami_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = DEFAULT_MEM_BASE, + .pci_dac_offset = TSUNAMI_DAC_OFFSET, + + .nr_irqs = 64, + .device_interrupt = dp264_device_interrupt, + + .init_arch = tsunami_init_arch, + .init_irq = clipper_init_irq, + .init_rtc = common_init_rtc, + .init_pci = common_init_pci, + .kill_arch = tsunami_kill_arch, + .pci_map_irq = clipper_map_irq, + .pci_swizzle = common_swizzle, }; /* No alpha_mv alias for webbrick/monet/clipper, since we compile them diff --git a/arch/alpha/kernel/sys_eb64p.c b/arch/alpha/kernel/sys_eb64p.c index 665ea9a4b990..eb92418ff98b 100644 --- a/arch/alpha/kernel/sys_eb64p.c +++ b/arch/alpha/kernel/sys_eb64p.c @@ -71,13 +71,13 @@ eb64p_end_irq(unsigned int irq) } static struct hw_interrupt_type eb64p_irq_type = { - typename: "EB64P", - startup: eb64p_startup_irq, - shutdown: eb64p_disable_irq, - enable: eb64p_enable_irq, - disable: eb64p_disable_irq, - ack: eb64p_disable_irq, - end: eb64p_end_irq, + .typename = "EB64P", + .startup = eb64p_startup_irq, + .shutdown = eb64p_disable_irq, + .enable = eb64p_enable_irq, + .disable = eb64p_disable_irq, + .ack = eb64p_disable_irq, + .end = eb64p_end_irq, }; static void @@ -208,51 +208,51 @@ eb64p_map_irq(struct pci_dev *dev, u8 slot, u8 pin) #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB64P) struct alpha_machine_vector eb64p_mv __initmv = { - vector_name: "EB64+", + .vector_name = "EB64+", DO_EV4_MMU, DO_DEFAULT_RTC, DO_APECS_IO, DO_APECS_BUS, - machine_check: apecs_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE, - - nr_irqs: 32, - device_interrupt: eb64p_device_interrupt, - - init_arch: apecs_init_arch, - init_irq: eb64p_init_irq, - init_rtc: common_init_rtc, - init_pci: common_init_pci, - kill_arch: NULL, - pci_map_irq: eb64p_map_irq, - pci_swizzle: common_swizzle, + .machine_check = apecs_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE, + + .nr_irqs = 32, + .device_interrupt = eb64p_device_interrupt, + + .init_arch = apecs_init_arch, + .init_irq = eb64p_init_irq, + .init_rtc = common_init_rtc, + .init_pci = common_init_pci, + .kill_arch = NULL, + .pci_map_irq = eb64p_map_irq, + .pci_swizzle = common_swizzle, }; ALIAS_MV(eb64p) #endif #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB66) struct alpha_machine_vector eb66_mv __initmv = { - vector_name: "EB66", + .vector_name = "EB66", DO_EV4_MMU, DO_DEFAULT_RTC, DO_LCA_IO, DO_LCA_BUS, - machine_check: lca_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE, - - nr_irqs: 32, - device_interrupt: eb64p_device_interrupt, - - init_arch: lca_init_arch, - init_irq: eb64p_init_irq, - init_rtc: common_init_rtc, - init_pci: common_init_pci, - pci_map_irq: eb64p_map_irq, - pci_swizzle: common_swizzle, + .machine_check = lca_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE, + + .nr_irqs = 32, + .device_interrupt = eb64p_device_interrupt, + + .init_arch = lca_init_arch, + .init_irq = eb64p_init_irq, + .init_rtc = common_init_rtc, + .init_pci = common_init_pci, + .pci_map_irq = eb64p_map_irq, + .pci_swizzle = common_swizzle, }; ALIAS_MV(eb66) #endif diff --git a/arch/alpha/kernel/sys_eiger.c b/arch/alpha/kernel/sys_eiger.c index 68c17b45f76f..5e223221d1b8 100644 --- a/arch/alpha/kernel/sys_eiger.c +++ b/arch/alpha/kernel/sys_eiger.c @@ -81,13 +81,13 @@ eiger_end_irq(unsigned int irq) } static struct hw_interrupt_type eiger_irq_type = { - typename: "EIGER", - startup: eiger_startup_irq, - shutdown: eiger_disable_irq, - enable: eiger_enable_irq, - disable: eiger_disable_irq, - ack: eiger_disable_irq, - end: eiger_end_irq, + .typename = "EIGER", + .startup = eiger_startup_irq, + .shutdown = eiger_disable_irq, + .enable = eiger_enable_irq, + .disable = eiger_disable_irq, + .ack = eiger_disable_irq, + .end = eiger_end_irq, }; static void @@ -225,26 +225,26 @@ eiger_swizzle(struct pci_dev *dev, u8 *pinp) */ struct alpha_machine_vector eiger_mv __initmv = { - vector_name: "Eiger", + .vector_name = "Eiger", DO_EV6_MMU, DO_DEFAULT_RTC, DO_TSUNAMI_IO, DO_TSUNAMI_BUS, - machine_check: tsunami_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: DEFAULT_MEM_BASE, - pci_dac_offset: TSUNAMI_DAC_OFFSET, - - nr_irqs: 128, - device_interrupt: eiger_device_interrupt, - - init_arch: tsunami_init_arch, - init_irq: eiger_init_irq, - init_rtc: common_init_rtc, - init_pci: common_init_pci, - kill_arch: tsunami_kill_arch, - pci_map_irq: eiger_map_irq, - pci_swizzle: eiger_swizzle, + .machine_check = tsunami_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = DEFAULT_MEM_BASE, + .pci_dac_offset = TSUNAMI_DAC_OFFSET, + + .nr_irqs = 128, + .device_interrupt = eiger_device_interrupt, + + .init_arch = tsunami_init_arch, + .init_irq = eiger_init_irq, + .init_rtc = common_init_rtc, + .init_pci = common_init_pci, + .kill_arch = tsunami_kill_arch, + .pci_map_irq = eiger_map_irq, + .pci_swizzle = eiger_swizzle, }; ALIAS_MV(eiger) diff --git a/arch/alpha/kernel/sys_jensen.c b/arch/alpha/kernel/sys_jensen.c index 3b03b8e7ee80..f6c5de49843c 100644 --- a/arch/alpha/kernel/sys_jensen.c +++ b/arch/alpha/kernel/sys_jensen.c @@ -119,13 +119,13 @@ jensen_local_end(unsigned int irq) } static struct hw_interrupt_type jensen_local_irq_type = { - typename: "LOCAL", - startup: jensen_local_startup, - shutdown: jensen_local_shutdown, - enable: jensen_local_enable, - disable: jensen_local_disable, - ack: jensen_local_ack, - end: jensen_local_end, + .typename = "LOCAL", + .startup = jensen_local_startup, + .shutdown = jensen_local_shutdown, + .enable = jensen_local_enable, + .disable = jensen_local_disable, + .ack = jensen_local_ack, + .end = jensen_local_end, }; static void @@ -252,21 +252,21 @@ jensen_machine_check (u64 vector, u64 la, struct pt_regs *regs) */ struct alpha_machine_vector jensen_mv __initmv = { - vector_name: "Jensen", + .vector_name = "Jensen", DO_EV4_MMU, IO_LITE(JENSEN,jensen), BUS(jensen), - machine_check: jensen_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - rtc_port: 0x170, - - nr_irqs: 16, - device_interrupt: jensen_device_interrupt, - - init_arch: jensen_init_arch, - init_irq: jensen_init_irq, - init_rtc: common_init_rtc, - init_pci: NULL, - kill_arch: NULL, + .machine_check = jensen_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .rtc_port = 0x170, + + .nr_irqs = 16, + .device_interrupt = jensen_device_interrupt, + + .init_arch = jensen_init_arch, + .init_irq = jensen_init_irq, + .init_rtc = common_init_rtc, + .init_pci = NULL, + .kill_arch = NULL, }; ALIAS_MV(jensen) diff --git a/arch/alpha/kernel/sys_miata.c b/arch/alpha/kernel/sys_miata.c index fefda1f8dd6a..e2c7ddbeef2f 100644 --- a/arch/alpha/kernel/sys_miata.c +++ b/arch/alpha/kernel/sys_miata.c @@ -261,26 +261,26 @@ miata_kill_arch(int mode) */ struct alpha_machine_vector miata_mv __initmv = { - vector_name: "Miata", + .vector_name = "Miata", DO_EV5_MMU, DO_DEFAULT_RTC, DO_PYXIS_IO, DO_CIA_BUS, - machine_check: cia_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: DEFAULT_MEM_BASE, - pci_dac_offset: PYXIS_DAC_OFFSET, + .machine_check = cia_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = DEFAULT_MEM_BASE, + .pci_dac_offset = PYXIS_DAC_OFFSET, - nr_irqs: 48, - device_interrupt: pyxis_device_interrupt, + .nr_irqs = 48, + .device_interrupt = pyxis_device_interrupt, - init_arch: pyxis_init_arch, - init_irq: miata_init_irq, - init_rtc: common_init_rtc, - init_pci: miata_init_pci, - kill_arch: miata_kill_arch, - pci_map_irq: miata_map_irq, - pci_swizzle: miata_swizzle, + .init_arch = pyxis_init_arch, + .init_irq = miata_init_irq, + .init_rtc = common_init_rtc, + .init_pci = miata_init_pci, + .kill_arch = miata_kill_arch, + .pci_map_irq = miata_map_irq, + .pci_swizzle = miata_swizzle, }; ALIAS_MV(miata) diff --git a/arch/alpha/kernel/sys_mikasa.c b/arch/alpha/kernel/sys_mikasa.c index fb7bf56c367d..f06e342c71d9 100644 --- a/arch/alpha/kernel/sys_mikasa.c +++ b/arch/alpha/kernel/sys_mikasa.c @@ -70,13 +70,13 @@ mikasa_end_irq(unsigned int irq) } static struct hw_interrupt_type mikasa_irq_type = { - typename: "MIKASA", - startup: mikasa_startup_irq, - shutdown: mikasa_disable_irq, - enable: mikasa_enable_irq, - disable: mikasa_disable_irq, - ack: mikasa_disable_irq, - end: mikasa_end_irq, + .typename = "MIKASA", + .startup = mikasa_startup_irq, + .shutdown = mikasa_disable_irq, + .enable = mikasa_enable_irq, + .disable = mikasa_disable_irq, + .ack = mikasa_disable_irq, + .end = mikasa_end_irq, }; static void @@ -217,51 +217,51 @@ mikasa_apecs_machine_check(unsigned long vector, unsigned long la_ptr, #if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO) struct alpha_machine_vector mikasa_mv __initmv = { - vector_name: "Mikasa", + .vector_name = "Mikasa", DO_EV4_MMU, DO_DEFAULT_RTC, DO_APECS_IO, DO_APECS_BUS, - machine_check: mikasa_apecs_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE, - - nr_irqs: 32, - device_interrupt: mikasa_device_interrupt, - - init_arch: apecs_init_arch, - init_irq: mikasa_init_irq, - init_rtc: common_init_rtc, - init_pci: common_init_pci, - kill_arch: NULL, - pci_map_irq: mikasa_map_irq, - pci_swizzle: common_swizzle, + .machine_check = mikasa_apecs_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE, + + .nr_irqs = 32, + .device_interrupt = mikasa_device_interrupt, + + .init_arch = apecs_init_arch, + .init_irq = mikasa_init_irq, + .init_rtc = common_init_rtc, + .init_pci = common_init_pci, + .kill_arch = NULL, + .pci_map_irq = mikasa_map_irq, + .pci_swizzle = common_swizzle, }; ALIAS_MV(mikasa) #endif #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PRIMO) struct alpha_machine_vector mikasa_primo_mv __initmv = { - vector_name: "Mikasa-Primo", + .vector_name = "Mikasa-Primo", DO_EV5_MMU, DO_DEFAULT_RTC, DO_CIA_IO, DO_CIA_BUS, - machine_check: cia_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: CIA_DEFAULT_MEM_BASE, - - nr_irqs: 32, - device_interrupt: mikasa_device_interrupt, - - init_arch: cia_init_arch, - init_irq: mikasa_init_irq, - init_rtc: common_init_rtc, - init_pci: cia_init_pci, - pci_map_irq: mikasa_map_irq, - pci_swizzle: common_swizzle, + .machine_check = cia_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = CIA_DEFAULT_MEM_BASE, + + .nr_irqs = 32, + .device_interrupt = mikasa_device_interrupt, + + .init_arch = cia_init_arch, + .init_irq = mikasa_init_irq, + .init_rtc = common_init_rtc, + .init_pci = cia_init_pci, + .pci_map_irq = mikasa_map_irq, + .pci_swizzle = common_swizzle, }; ALIAS_MV(mikasa_primo) #endif diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c index cbe8bbb8e5f0..bc4538a99ce5 100644 --- a/arch/alpha/kernel/sys_nautilus.c +++ b/arch/alpha/kernel/sys_nautilus.c @@ -510,25 +510,25 @@ nautilus_machine_check(unsigned long vector, unsigned long la_ptr, */ struct alpha_machine_vector nautilus_mv __initmv = { - vector_name: "Nautilus", + .vector_name = "Nautilus", DO_EV6_MMU, DO_DEFAULT_RTC, DO_IRONGATE_IO, DO_IRONGATE_BUS, - machine_check: nautilus_machine_check, - max_dma_address: ALPHA_NAUTILUS_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: IRONGATE_DEFAULT_MEM_BASE, - - nr_irqs: 16, - device_interrupt: isa_device_interrupt, - - init_arch: irongate_init_arch, - init_irq: nautilus_init_irq, - init_rtc: common_init_rtc, - init_pci: common_init_pci, - kill_arch: nautilus_kill_arch, - pci_map_irq: nautilus_map_irq, - pci_swizzle: common_swizzle, + .machine_check = nautilus_machine_check, + .max_dma_address = ALPHA_NAUTILUS_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = IRONGATE_DEFAULT_MEM_BASE, + + .nr_irqs = 16, + .device_interrupt = isa_device_interrupt, + + .init_arch = irongate_init_arch, + .init_irq = nautilus_init_irq, + .init_rtc = common_init_rtc, + .init_pci = common_init_pci, + .kill_arch = nautilus_kill_arch, + .pci_map_irq = nautilus_map_irq, + .pci_swizzle = common_swizzle, }; ALIAS_MV(nautilus) diff --git a/arch/alpha/kernel/sys_noritake.c b/arch/alpha/kernel/sys_noritake.c index 16ea1329f3e1..3e3aecf94b36 100644 --- a/arch/alpha/kernel/sys_noritake.c +++ b/arch/alpha/kernel/sys_noritake.c @@ -68,13 +68,13 @@ noritake_startup_irq(unsigned int irq) } static struct hw_interrupt_type noritake_irq_type = { - typename: "NORITAKE", - startup: noritake_startup_irq, - shutdown: noritake_disable_irq, - enable: noritake_enable_irq, - disable: noritake_disable_irq, - ack: noritake_disable_irq, - end: noritake_enable_irq, + .typename = "NORITAKE", + .startup = noritake_startup_irq, + .shutdown = noritake_disable_irq, + .enable = noritake_enable_irq, + .disable = noritake_disable_irq, + .ack = noritake_disable_irq, + .end = noritake_enable_irq, }; static void @@ -299,51 +299,51 @@ noritake_apecs_machine_check(unsigned long vector, unsigned long la_ptr, #if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO) struct alpha_machine_vector noritake_mv __initmv = { - vector_name: "Noritake", + .vector_name = "Noritake", DO_EV4_MMU, DO_DEFAULT_RTC, DO_APECS_IO, DO_APECS_BUS, - machine_check: noritake_apecs_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: EISA_DEFAULT_IO_BASE, - min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE, - - nr_irqs: 48, - device_interrupt: noritake_device_interrupt, - - init_arch: apecs_init_arch, - init_irq: noritake_init_irq, - init_rtc: common_init_rtc, - init_pci: common_init_pci, - kill_arch: NULL, - pci_map_irq: noritake_map_irq, - pci_swizzle: noritake_swizzle, + .machine_check = noritake_apecs_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = EISA_DEFAULT_IO_BASE, + .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE, + + .nr_irqs = 48, + .device_interrupt = noritake_device_interrupt, + + .init_arch = apecs_init_arch, + .init_irq = noritake_init_irq, + .init_rtc = common_init_rtc, + .init_pci = common_init_pci, + .kill_arch = NULL, + .pci_map_irq = noritake_map_irq, + .pci_swizzle = noritake_swizzle, }; ALIAS_MV(noritake) #endif #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PRIMO) struct alpha_machine_vector noritake_primo_mv __initmv = { - vector_name: "Noritake-Primo", + .vector_name = "Noritake-Primo", DO_EV5_MMU, DO_DEFAULT_RTC, DO_CIA_IO, DO_CIA_BUS, - machine_check: cia_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: EISA_DEFAULT_IO_BASE, - min_mem_address: CIA_DEFAULT_MEM_BASE, - - nr_irqs: 48, - device_interrupt: noritake_device_interrupt, - - init_arch: cia_init_arch, - init_irq: noritake_init_irq, - init_rtc: common_init_rtc, - init_pci: cia_init_pci, - pci_map_irq: noritake_map_irq, - pci_swizzle: noritake_swizzle, + .machine_check = cia_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = EISA_DEFAULT_IO_BASE, + .min_mem_address = CIA_DEFAULT_MEM_BASE, + + .nr_irqs = 48, + .device_interrupt = noritake_device_interrupt, + + .init_arch = cia_init_arch, + .init_irq = noritake_init_irq, + .init_rtc = common_init_rtc, + .init_pci = cia_init_pci, + .pci_map_irq = noritake_map_irq, + .pci_swizzle = noritake_swizzle, }; ALIAS_MV(noritake_primo) #endif diff --git a/arch/alpha/kernel/sys_rawhide.c b/arch/alpha/kernel/sys_rawhide.c index 6518097f7bd4..6ad2ccfd1878 100644 --- a/arch/alpha/kernel/sys_rawhide.c +++ b/arch/alpha/kernel/sys_rawhide.c @@ -124,13 +124,13 @@ rawhide_end_irq(unsigned int irq) } static struct hw_interrupt_type rawhide_irq_type = { - typename: "RAWHIDE", - startup: rawhide_startup_irq, - shutdown: rawhide_disable_irq, - enable: rawhide_enable_irq, - disable: rawhide_disable_irq, - ack: rawhide_mask_and_ack_irq, - end: rawhide_end_irq, + .typename = "RAWHIDE", + .startup = rawhide_startup_irq, + .shutdown = rawhide_disable_irq, + .enable = rawhide_enable_irq, + .disable = rawhide_disable_irq, + .ack = rawhide_mask_and_ack_irq, + .end = rawhide_end_irq, }; static void @@ -246,26 +246,26 @@ rawhide_map_irq(struct pci_dev *dev, u8 slot, u8 pin) */ struct alpha_machine_vector rawhide_mv __initmv = { - vector_name: "Rawhide", + .vector_name = "Rawhide", DO_EV5_MMU, DO_DEFAULT_RTC, DO_MCPCIA_IO, DO_MCPCIA_BUS, - machine_check: mcpcia_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: MCPCIA_DEFAULT_MEM_BASE, - pci_dac_offset: MCPCIA_DAC_OFFSET, - - nr_irqs: 128, - device_interrupt: rawhide_srm_device_interrupt, - - init_arch: mcpcia_init_arch, - init_irq: rawhide_init_irq, - init_rtc: common_init_rtc, - init_pci: common_init_pci, - kill_arch: NULL, - pci_map_irq: rawhide_map_irq, - pci_swizzle: common_swizzle, + .machine_check = mcpcia_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = MCPCIA_DEFAULT_MEM_BASE, + .pci_dac_offset = MCPCIA_DAC_OFFSET, + + .nr_irqs = 128, + .device_interrupt = rawhide_srm_device_interrupt, + + .init_arch = mcpcia_init_arch, + .init_irq = rawhide_init_irq, + .init_rtc = common_init_rtc, + .init_pci = common_init_pci, + .kill_arch = NULL, + .pci_map_irq = rawhide_map_irq, + .pci_swizzle = common_swizzle, }; ALIAS_MV(rawhide) diff --git a/arch/alpha/kernel/sys_ruffian.c b/arch/alpha/kernel/sys_ruffian.c index a1966a07b8b3..7f7977c20ecd 100644 --- a/arch/alpha/kernel/sys_ruffian.c +++ b/arch/alpha/kernel/sys_ruffian.c @@ -212,26 +212,26 @@ ruffian_get_bank_size(unsigned long offset) */ struct alpha_machine_vector ruffian_mv __initmv = { - vector_name: "Ruffian", + .vector_name = "Ruffian", DO_EV5_MMU, DO_DEFAULT_RTC, DO_PYXIS_IO, DO_CIA_BUS, - machine_check: cia_machine_check, - max_dma_address: ALPHA_RUFFIAN_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: DEFAULT_MEM_BASE, - pci_dac_offset: PYXIS_DAC_OFFSET, - - nr_irqs: 48, - device_interrupt: pyxis_device_interrupt, - - init_arch: pyxis_init_arch, - init_irq: ruffian_init_irq, - init_rtc: ruffian_init_rtc, - init_pci: cia_init_pci, - kill_arch: ruffian_kill_arch, - pci_map_irq: ruffian_map_irq, - pci_swizzle: ruffian_swizzle, + .machine_check = cia_machine_check, + .max_dma_address = ALPHA_RUFFIAN_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = DEFAULT_MEM_BASE, + .pci_dac_offset = PYXIS_DAC_OFFSET, + + .nr_irqs = 48, + .device_interrupt = pyxis_device_interrupt, + + .init_arch = pyxis_init_arch, + .init_irq = ruffian_init_irq, + .init_rtc = ruffian_init_rtc, + .init_pci = cia_init_pci, + .kill_arch = ruffian_kill_arch, + .pci_map_irq = ruffian_map_irq, + .pci_swizzle = ruffian_swizzle, }; ALIAS_MV(ruffian) diff --git a/arch/alpha/kernel/sys_rx164.c b/arch/alpha/kernel/sys_rx164.c index 48214ff70abc..cdf8b666d3ab 100644 --- a/arch/alpha/kernel/sys_rx164.c +++ b/arch/alpha/kernel/sys_rx164.c @@ -73,13 +73,13 @@ rx164_end_irq(unsigned int irq) } static struct hw_interrupt_type rx164_irq_type = { - typename: "RX164", - startup: rx164_startup_irq, - shutdown: rx164_disable_irq, - enable: rx164_enable_irq, - disable: rx164_disable_irq, - ack: rx164_disable_irq, - end: rx164_end_irq, + .typename = "RX164", + .startup = rx164_startup_irq, + .shutdown = rx164_disable_irq, + .enable = rx164_enable_irq, + .disable = rx164_disable_irq, + .ack = rx164_disable_irq, + .end = rx164_end_irq, }; static void @@ -197,25 +197,25 @@ rx164_map_irq(struct pci_dev *dev, u8 slot, u8 pin) */ struct alpha_machine_vector rx164_mv __initmv = { - vector_name: "RX164", + .vector_name = "RX164", DO_EV5_MMU, DO_DEFAULT_RTC, DO_POLARIS_IO, DO_POLARIS_BUS, - machine_check: polaris_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: DEFAULT_MEM_BASE, - - nr_irqs: 40, - device_interrupt: rx164_device_interrupt, - - init_arch: polaris_init_arch, - init_irq: rx164_init_irq, - init_rtc: common_init_rtc, - init_pci: common_init_pci, - kill_arch: NULL, - pci_map_irq: rx164_map_irq, - pci_swizzle: common_swizzle, + .machine_check = polaris_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = DEFAULT_MEM_BASE, + + .nr_irqs = 40, + .device_interrupt = rx164_device_interrupt, + + .init_arch = polaris_init_arch, + .init_irq = rx164_init_irq, + .init_rtc = common_init_rtc, + .init_pci = common_init_pci, + .kill_arch = NULL, + .pci_map_irq = rx164_map_irq, + .pci_swizzle = common_swizzle, }; ALIAS_MV(rx164) diff --git a/arch/alpha/kernel/sys_sable.c b/arch/alpha/kernel/sys_sable.c index dc35fe7ea125..587a4bc4a00f 100644 --- a/arch/alpha/kernel/sys_sable.c +++ b/arch/alpha/kernel/sys_sable.c @@ -185,13 +185,13 @@ sable_mask_and_ack_irq(unsigned int irq) } static struct hw_interrupt_type sable_irq_type = { - typename: "SABLE", - startup: sable_startup_irq, - shutdown: sable_disable_irq, - enable: sable_enable_irq, - disable: sable_disable_irq, - ack: sable_mask_and_ack_irq, - end: sable_end_irq, + .typename = "SABLE", + .startup = sable_startup_irq, + .shutdown = sable_disable_irq, + .enable = sable_enable_irq, + .disable = sable_disable_irq, + .ack = sable_mask_and_ack_irq, + .end = sable_end_irq, }; static void @@ -284,29 +284,29 @@ sable_map_irq(struct pci_dev *dev, u8 slot, u8 pin) #undef GAMMA_BIAS #define GAMMA_BIAS 0 struct alpha_machine_vector sable_mv __initmv = { - vector_name: "Sable", + .vector_name = "Sable", DO_EV4_MMU, DO_DEFAULT_RTC, DO_T2_IO, DO_T2_BUS, - machine_check: t2_machine_check, - max_dma_address: ALPHA_SABLE_MAX_DMA_ADDRESS, - min_io_address: EISA_DEFAULT_IO_BASE, - min_mem_address: T2_DEFAULT_MEM_BASE, - - nr_irqs: 40, - device_interrupt: sable_srm_device_interrupt, - - init_arch: t2_init_arch, - init_irq: sable_init_irq, - init_rtc: common_init_rtc, - init_pci: common_init_pci, - kill_arch: NULL, - pci_map_irq: sable_map_irq, - pci_swizzle: common_swizzle, - - sys: { t2: { - gamma_bias: 0 + .machine_check = t2_machine_check, + .max_dma_address = ALPHA_SABLE_MAX_DMA_ADDRESS, + .min_io_address = EISA_DEFAULT_IO_BASE, + .min_mem_address = T2_DEFAULT_MEM_BASE, + + .nr_irqs = 40, + .device_interrupt = sable_srm_device_interrupt, + + .init_arch = t2_init_arch, + .init_irq = sable_init_irq, + .init_rtc = common_init_rtc, + .init_pci = common_init_pci, + .kill_arch = NULL, + .pci_map_irq = sable_map_irq, + .pci_swizzle = common_swizzle, + + .sys = { .t2 = { + .gamma_bias = 0 } } }; ALIAS_MV(sable) @@ -316,28 +316,28 @@ ALIAS_MV(sable) #undef GAMMA_BIAS #define GAMMA_BIAS _GAMMA_BIAS struct alpha_machine_vector sable_gamma_mv __initmv = { - vector_name: "Sable-Gamma", + .vector_name = "Sable-Gamma", DO_EV5_MMU, DO_DEFAULT_RTC, DO_T2_IO, DO_T2_BUS, - machine_check: t2_machine_check, - max_dma_address: ALPHA_SABLE_MAX_DMA_ADDRESS, - min_io_address: EISA_DEFAULT_IO_BASE, - min_mem_address: T2_DEFAULT_MEM_BASE, - - nr_irqs: 40, - device_interrupt: sable_srm_device_interrupt, - - init_arch: t2_init_arch, - init_irq: sable_init_irq, - init_rtc: common_init_rtc, - init_pci: common_init_pci, - pci_map_irq: sable_map_irq, - pci_swizzle: common_swizzle, - - sys: { t2: { - gamma_bias: _GAMMA_BIAS + .machine_check = t2_machine_check, + .max_dma_address = ALPHA_SABLE_MAX_DMA_ADDRESS, + .min_io_address = EISA_DEFAULT_IO_BASE, + .min_mem_address = T2_DEFAULT_MEM_BASE, + + .nr_irqs = 40, + .device_interrupt = sable_srm_device_interrupt, + + .init_arch = t2_init_arch, + .init_irq = sable_init_irq, + .init_rtc = common_init_rtc, + .init_pci = common_init_pci, + .pci_map_irq = sable_map_irq, + .pci_swizzle = common_swizzle, + + .sys = { .t2 = { + .gamma_bias = _GAMMA_BIAS } } }; ALIAS_MV(sable_gamma) diff --git a/arch/alpha/kernel/sys_sio.c b/arch/alpha/kernel/sys_sio.c index a371399a2e3a..dfa9fe57ad9a 100644 --- a/arch/alpha/kernel/sys_sio.c +++ b/arch/alpha/kernel/sys_sio.c @@ -252,30 +252,30 @@ alphabook1_init_pci(void) #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_BOOK1) struct alpha_machine_vector alphabook1_mv __initmv = { - vector_name: "AlphaBook1", + .vector_name = "AlphaBook1", DO_EV4_MMU, DO_DEFAULT_RTC, DO_LCA_IO, DO_LCA_BUS, - machine_check: lca_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE, - - nr_irqs: 16, - device_interrupt: isa_device_interrupt, - - init_arch: alphabook1_init_arch, - init_irq: sio_init_irq, - init_rtc: common_init_rtc, - init_pci: alphabook1_init_pci, - kill_arch: NULL, - pci_map_irq: noname_map_irq, - pci_swizzle: common_swizzle, - - sys: { sio: { + .machine_check = lca_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE, + + .nr_irqs = 16, + .device_interrupt = isa_device_interrupt, + + .init_arch = alphabook1_init_arch, + .init_irq = sio_init_irq, + .init_rtc = common_init_rtc, + .init_pci = alphabook1_init_pci, + .kill_arch = NULL, + .pci_map_irq = noname_map_irq, + .pci_swizzle = common_swizzle, + + .sys = { .sio = { /* NCR810 SCSI is 14, PCMCIA controller is 15. */ - route_tab: 0x0e0f0a0a, + .route_tab = 0x0e0f0a0a, }} }; ALIAS_MV(alphabook1) @@ -283,28 +283,28 @@ ALIAS_MV(alphabook1) #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_AVANTI) struct alpha_machine_vector avanti_mv __initmv = { - vector_name: "Avanti", + .vector_name = "Avanti", DO_EV4_MMU, DO_DEFAULT_RTC, DO_APECS_IO, DO_APECS_BUS, - machine_check: apecs_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE, - - nr_irqs: 16, - device_interrupt: isa_device_interrupt, - - init_arch: apecs_init_arch, - init_irq: sio_init_irq, - init_rtc: common_init_rtc, - init_pci: noname_init_pci, - pci_map_irq: noname_map_irq, - pci_swizzle: common_swizzle, - - sys: { sio: { - route_tab: 0x0b0a0e0f, + .machine_check = apecs_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE, + + .nr_irqs = 16, + .device_interrupt = isa_device_interrupt, + + .init_arch = apecs_init_arch, + .init_irq = sio_init_irq, + .init_rtc = common_init_rtc, + .init_pci = noname_init_pci, + .pci_map_irq = noname_map_irq, + .pci_swizzle = common_swizzle, + + .sys = { .sio = { + .route_tab = 0x0b0a0e0f, }} }; ALIAS_MV(avanti) @@ -312,27 +312,27 @@ ALIAS_MV(avanti) #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_NONAME) struct alpha_machine_vector noname_mv __initmv = { - vector_name: "Noname", + .vector_name = "Noname", DO_EV4_MMU, DO_DEFAULT_RTC, DO_LCA_IO, DO_LCA_BUS, - machine_check: lca_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE, - - nr_irqs: 16, - device_interrupt: srm_device_interrupt, - - init_arch: lca_init_arch, - init_irq: sio_init_irq, - init_rtc: common_init_rtc, - init_pci: noname_init_pci, - pci_map_irq: noname_map_irq, - pci_swizzle: common_swizzle, - - sys: { sio: { + .machine_check = lca_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE, + + .nr_irqs = 16, + .device_interrupt = srm_device_interrupt, + + .init_arch = lca_init_arch, + .init_irq = sio_init_irq, + .init_rtc = common_init_rtc, + .init_pci = noname_init_pci, + .pci_map_irq = noname_map_irq, + .pci_swizzle = common_swizzle, + + .sys = { .sio = { /* For UDB, the only available PCI slot must not map to IRQ 9, since that's the builtin MSS sound chip. That PCI slot will map to PIRQ1 (for INTA at least), so we give it IRQ 15 @@ -342,7 +342,7 @@ struct alpha_machine_vector noname_mv __initmv = { they are co-indicated when the platform type "Noname" is selected... :-( */ - route_tab: 0x0b0a0f0d, + .route_tab = 0x0b0a0f0d, }} }; ALIAS_MV(noname) @@ -350,28 +350,28 @@ ALIAS_MV(noname) #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_P2K) struct alpha_machine_vector p2k_mv __initmv = { - vector_name: "Platform2000", + .vector_name = "Platform2000", DO_EV4_MMU, DO_DEFAULT_RTC, DO_LCA_IO, DO_LCA_BUS, - machine_check: lca_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE, - - nr_irqs: 16, - device_interrupt: srm_device_interrupt, - - init_arch: lca_init_arch, - init_irq: sio_init_irq, - init_rtc: common_init_rtc, - init_pci: noname_init_pci, - pci_map_irq: p2k_map_irq, - pci_swizzle: common_swizzle, - - sys: { sio: { - route_tab: 0x0b0a090f, + .machine_check = lca_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE, + + .nr_irqs = 16, + .device_interrupt = srm_device_interrupt, + + .init_arch = lca_init_arch, + .init_irq = sio_init_irq, + .init_rtc = common_init_rtc, + .init_pci = noname_init_pci, + .pci_map_irq = p2k_map_irq, + .pci_swizzle = common_swizzle, + + .sys = { .sio = { + .route_tab = 0x0b0a090f, }} }; ALIAS_MV(p2k) @@ -379,28 +379,28 @@ ALIAS_MV(p2k) #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_XL) struct alpha_machine_vector xl_mv __initmv = { - vector_name: "XL", + .vector_name = "XL", DO_EV4_MMU, DO_DEFAULT_RTC, DO_APECS_IO, BUS(apecs), - machine_check: apecs_machine_check, - max_dma_address: ALPHA_XL_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: XL_DEFAULT_MEM_BASE, - - nr_irqs: 16, - device_interrupt: isa_device_interrupt, - - init_arch: apecs_init_arch, - init_irq: sio_init_irq, - init_rtc: common_init_rtc, - init_pci: noname_init_pci, - pci_map_irq: noname_map_irq, - pci_swizzle: common_swizzle, - - sys: { sio: { - route_tab: 0x0b0a090f, + .machine_check = apecs_machine_check, + .max_dma_address = ALPHA_XL_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = XL_DEFAULT_MEM_BASE, + + .nr_irqs = 16, + .device_interrupt = isa_device_interrupt, + + .init_arch = apecs_init_arch, + .init_irq = sio_init_irq, + .init_rtc = common_init_rtc, + .init_pci = noname_init_pci, + .pci_map_irq = noname_map_irq, + .pci_swizzle = common_swizzle, + + .sys = { .sio = { + .route_tab = 0x0b0a090f, }} }; ALIAS_MV(xl) diff --git a/arch/alpha/kernel/sys_sx164.c b/arch/alpha/kernel/sys_sx164.c index efcf059d3d8c..ebd4d89e8f5b 100644 --- a/arch/alpha/kernel/sys_sx164.c +++ b/arch/alpha/kernel/sys_sx164.c @@ -154,26 +154,26 @@ sx164_init_arch(void) */ struct alpha_machine_vector sx164_mv __initmv = { - vector_name: "SX164", + .vector_name = "SX164", DO_EV5_MMU, DO_DEFAULT_RTC, DO_PYXIS_IO, DO_CIA_BUS, - machine_check: cia_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: DEFAULT_MEM_BASE, - pci_dac_offset: PYXIS_DAC_OFFSET, - - nr_irqs: 48, - device_interrupt: pyxis_device_interrupt, - - init_arch: sx164_init_arch, - init_irq: sx164_init_irq, - init_rtc: common_init_rtc, - init_pci: sx164_init_pci, - kill_arch: NULL, - pci_map_irq: sx164_map_irq, - pci_swizzle: common_swizzle, + .machine_check = cia_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = DEFAULT_MEM_BASE, + .pci_dac_offset = PYXIS_DAC_OFFSET, + + .nr_irqs = 48, + .device_interrupt = pyxis_device_interrupt, + + .init_arch = sx164_init_arch, + .init_irq = sx164_init_irq, + .init_rtc = common_init_rtc, + .init_pci = sx164_init_pci, + .kill_arch = NULL, + .pci_map_irq = sx164_map_irq, + .pci_swizzle = common_swizzle, }; ALIAS_MV(sx164) diff --git a/arch/alpha/kernel/sys_takara.c b/arch/alpha/kernel/sys_takara.c index 6af89e81b028..6159efaf6386 100644 --- a/arch/alpha/kernel/sys_takara.c +++ b/arch/alpha/kernel/sys_takara.c @@ -75,13 +75,13 @@ takara_end_irq(unsigned int irq) } static struct hw_interrupt_type takara_irq_type = { - typename: "TAKARA", - startup: takara_startup_irq, - shutdown: takara_disable_irq, - enable: takara_enable_irq, - disable: takara_disable_irq, - ack: takara_disable_irq, - end: takara_end_irq, + .typename = "TAKARA", + .startup = takara_startup_irq, + .shutdown = takara_disable_irq, + .enable = takara_enable_irq, + .disable = takara_disable_irq, + .ack = takara_disable_irq, + .end = takara_end_irq, }; static void @@ -269,25 +269,25 @@ takara_init_pci(void) */ struct alpha_machine_vector takara_mv __initmv = { - vector_name: "Takara", + .vector_name = "Takara", DO_EV5_MMU, DO_DEFAULT_RTC, DO_CIA_IO, DO_CIA_BUS, - machine_check: cia_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: CIA_DEFAULT_MEM_BASE, - - nr_irqs: 128, - device_interrupt: takara_device_interrupt, - - init_arch: cia_init_arch, - init_irq: takara_init_irq, - init_rtc: common_init_rtc, - init_pci: takara_init_pci, - kill_arch: NULL, - pci_map_irq: takara_map_irq, - pci_swizzle: takara_swizzle, + .machine_check = cia_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = CIA_DEFAULT_MEM_BASE, + + .nr_irqs = 128, + .device_interrupt = takara_device_interrupt, + + .init_arch = cia_init_arch, + .init_irq = takara_init_irq, + .init_rtc = common_init_rtc, + .init_pci = takara_init_pci, + .kill_arch = NULL, + .pci_map_irq = takara_map_irq, + .pci_swizzle = takara_swizzle, }; ALIAS_MV(takara) diff --git a/arch/alpha/kernel/sys_titan.c b/arch/alpha/kernel/sys_titan.c index c6ed45836e7d..b7d03baa0ed5 100644 --- a/arch/alpha/kernel/sys_titan.c +++ b/arch/alpha/kernel/sys_titan.c @@ -152,14 +152,14 @@ privateer_set_affinity(unsigned int irq, unsigned long affinity) } static struct hw_interrupt_type privateer_irq_type = { - typename: "PRIVATEER", - startup: privateer_startup_irq, - shutdown: privateer_disable_irq, - enable: privateer_enable_irq, - disable: privateer_disable_irq, - ack: privateer_disable_irq, - end: privateer_end_irq, - set_affinity: privateer_set_affinity, + .typename = "PRIVATEER", + .startup = privateer_startup_irq, + .shutdown = privateer_disable_irq, + .enable = privateer_enable_irq, + .disable = privateer_disable_irq, + .ack = privateer_disable_irq, + .end = privateer_end_irq, + .set_affinity = privateer_set_affinity, }; static void @@ -367,26 +367,26 @@ privateer_machine_check(unsigned long vector, unsigned long la_ptr, */ struct alpha_machine_vector privateer_mv __initmv = { - vector_name: "PRIVATEER", + .vector_name = "PRIVATEER", DO_EV6_MMU, DO_DEFAULT_RTC, DO_TITAN_IO, DO_TITAN_BUS, - machine_check: privateer_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: DEFAULT_MEM_BASE, - pci_dac_offset: TITAN_DAC_OFFSET, - - nr_irqs: 80, /* 64 + 16 */ - device_interrupt: privateer_device_interrupt, - - init_arch: titan_init_arch, - init_irq: privateer_init_irq, - init_rtc: common_init_rtc, - init_pci: privateer_init_pci, - kill_arch: titan_kill_arch, - pci_map_irq: privateer_map_irq, - pci_swizzle: common_swizzle, + .machine_check = privateer_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = DEFAULT_MEM_BASE, + .pci_dac_offset = TITAN_DAC_OFFSET, + + .nr_irqs = 80, /* 64 + 16 */ + .device_interrupt = privateer_device_interrupt, + + .init_arch = titan_init_arch, + .init_irq = privateer_init_irq, + .init_rtc = common_init_rtc, + .init_pci = privateer_init_pci, + .kill_arch = titan_kill_arch, + .pci_map_irq = privateer_map_irq, + .pci_swizzle = common_swizzle, }; ALIAS_MV(privateer) diff --git a/arch/alpha/kernel/sys_wildfire.c b/arch/alpha/kernel/sys_wildfire.c index bccbbdc0c678..90316b56980a 100644 --- a/arch/alpha/kernel/sys_wildfire.c +++ b/arch/alpha/kernel/sys_wildfire.c @@ -158,13 +158,13 @@ wildfire_end_irq(unsigned int irq) } static struct hw_interrupt_type wildfire_irq_type = { - typename: "WILDFIRE", - startup: wildfire_startup_irq, - shutdown: wildfire_disable_irq, - enable: wildfire_enable_irq, - disable: wildfire_disable_irq, - ack: wildfire_mask_and_ack_irq, - end: wildfire_end_irq, + .typename = "WILDFIRE", + .startup = wildfire_startup_irq, + .shutdown = wildfire_disable_irq, + .enable = wildfire_enable_irq, + .disable = wildfire_disable_irq, + .ack = wildfire_mask_and_ack_irq, + .end = wildfire_end_irq, }; static void __init @@ -173,8 +173,8 @@ wildfire_init_irq_per_pca(int qbbno, int pcano) int i, irq_bias; unsigned long io_bias; static struct irqaction isa_enable = { - handler: no_action, - name: "isa_enable", + .handler = no_action, + .name = "isa_enable", }; irq_bias = qbbno * (WILDFIRE_PCA_PER_QBB * WILDFIRE_IRQ_PER_PCA) @@ -333,25 +333,25 @@ wildfire_map_irq(struct pci_dev *dev, u8 slot, u8 pin) */ struct alpha_machine_vector wildfire_mv __initmv = { - vector_name: "WILDFIRE", + .vector_name = "WILDFIRE", DO_EV6_MMU, DO_DEFAULT_RTC, DO_WILDFIRE_IO, DO_WILDFIRE_BUS, - machine_check: wildfire_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, - min_io_address: DEFAULT_IO_BASE, - min_mem_address: DEFAULT_MEM_BASE, - - nr_irqs: WILDFIRE_NR_IRQS, - device_interrupt: wildfire_device_interrupt, - - init_arch: wildfire_init_arch, - init_irq: wildfire_init_irq, - init_rtc: common_init_rtc, - init_pci: common_init_pci, - kill_arch: wildfire_kill_arch, - pci_map_irq: wildfire_map_irq, - pci_swizzle: common_swizzle, + .machine_check = wildfire_machine_check, + .max_dma_address = ALPHA_MAX_DMA_ADDRESS, + .min_io_address = DEFAULT_IO_BASE, + .min_mem_address = DEFAULT_MEM_BASE, + + .nr_irqs = WILDFIRE_NR_IRQS, + .device_interrupt = wildfire_device_interrupt, + + .init_arch = wildfire_init_arch, + .init_irq = wildfire_init_irq, + .init_rtc = common_init_rtc, + .init_pci = common_init_pci, + .kill_arch = wildfire_kill_arch, + .pci_map_irq = wildfire_map_irq, + .pci_swizzle = common_swizzle, }; ALIAS_MV(wildfire) diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S index 59a91186ace6..e7fea3935f5b 100644 --- a/arch/alpha/kernel/systbls.S +++ b/arch/alpha/kernel/systbls.S @@ -4,6 +4,7 @@ * The system call table. */ +#include <linux/config.h> /* CONFIG_OSF4_COMPAT */ #include <asm/unistd.h> .data diff --git a/arch/alpha/lib/ev6-stxncpy.S b/arch/alpha/lib/ev6-stxncpy.S index 0d9aba3865d6..2116a5dd42f9 100644 --- a/arch/alpha/lib/ev6-stxncpy.S +++ b/arch/alpha/lib/ev6-stxncpy.S @@ -253,7 +253,7 @@ $u_loop: stq_u t0, -8(a0) # U : save the current word beq a2, $u_eoc # U : - ldq_u t2, 0(a1) # U : Latency=3 load high word for next time + ldq_u t2, 8(a1) # U : Latency=3 load high word for next time addq a1, 8, a1 # E : extqh t2, a1, t0 # U : extract low bits (2 cycle stall) diff --git a/arch/alpha/lib/stxncpy.S b/arch/alpha/lib/stxncpy.S index 9f0d16737cf0..f6fcef4c42a5 100644 --- a/arch/alpha/lib/stxncpy.S +++ b/arch/alpha/lib/stxncpy.S @@ -210,7 +210,7 @@ $u_loop: addq a0, 8, a0 # .. e1 : extql t2, a1, t1 # e0 : extract high bits for next time beq a2, $u_eoc # .. e1 : - ldq_u t2, 0(a1) # e0 : load high word for next time + ldq_u t2, 8(a1) # e0 : load high word for next time addq a1, 8, a1 # .. e1 : nop # e0 : cmpbge zero, t2, t8 # e1 : test new word for eos (stall) diff --git a/arch/i386/Config.help b/arch/i386/Config.help index 299dea0c6536..be811e61b06f 100644 --- a/arch/i386/Config.help +++ b/arch/i386/Config.help @@ -73,6 +73,12 @@ CONFIG_X86_CYCLONE If you are suffering from time skew using a multi-CEC system, say YES. Otherwise it is safe to say NO. +CONFIG_X86_SUMMIT + This option is needed for IBM systems that use the Summit/EXA chipset. + In particular, it is needed for the x440. + + If you don't have one of these computers, you should say N here. + CONFIG_X86_UP_IOAPIC An IO-APIC (I/O Advanced Programmable Interrupt Controller) is an SMP-capable replacement for PC-style interrupt controllers. Most @@ -1048,6 +1054,11 @@ CONFIG_DEBUG_OBSOLETE Say Y here if you want to reduce the chances of the tree compiling, and are prepared to dig into driver internals to fix compile errors. +Profiling support +CONFIG_PROFILING + Say Y here to enable the extended profiling support mechanisms used + by profilers such as OProfile. + Software Suspend CONFIG_SOFTWARE_SUSPEND Enable the possibilty of suspendig machine. It doesn't need APM. diff --git a/arch/i386/Makefile b/arch/i386/Makefile index 9d822af70fcb..4df45365d6f0 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -57,6 +57,8 @@ core-y += arch/i386/kernel/ \ arch/i386/$(MACHINE)/ drivers-$(CONFIG_MATH_EMULATION) += arch/i386/math-emu/ drivers-$(CONFIG_PCI) += arch/i386/pci/ +# FIXME: is drivers- right ? +drivers-$(CONFIG_OPROFILE) += arch/i386/oprofile/ CFLAGS += -Iarch/i386/$(MACHINE) AFLAGS += -Iarch/i386/$(MACHINE) diff --git a/arch/i386/config.in b/arch/i386/config.in index 784e35d23bce..1026d1a0a1f4 100644 --- a/arch/i386/config.in +++ b/arch/i386/config.in @@ -172,7 +172,8 @@ else if [ "$CONFIG_X86_NUMA" = "y" ]; then #Platform Choices bool 'Multiquad (IBM/Sequent) NUMAQ support' CONFIG_X86_NUMAQ - if [ "$CONFIG_X86_NUMAQ" = "y" ]; then + bool 'IBM x440 (Summit/EXA) support' CONFIG_X86_SUMMIT + if [ "$CONFIG_X86_NUMAQ" = "y" -o "$CONFIG_X86_SUMMIT" = "y" ]; then define_bool CONFIG_CLUSTERED_APIC y fi # Common NUMA Features @@ -442,6 +443,8 @@ source drivers/usb/Config.in source net/bluetooth/Config.in +source arch/i386/oprofile/Config.in + mainmenu_option next_comment comment 'Kernel hacking' if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile index d201c60ac5c2..55f9312b7f39 100644 --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o obj-$(CONFIG_X86_NUMAQ) += numaq.o +obj-$(CONFIG_PROFILING) += profile.o EXTRA_AFLAGS := -traditional diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index c2f56438f749..d7998626bcc0 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -31,6 +31,7 @@ #include <asm/pgalloc.h> #include <asm/desc.h> #include <asm/arch_hooks.h> +#include "mach_apic.h" void __init apic_intr_init(void) { @@ -328,15 +329,13 @@ void __init setup_local_APIC (void) * Put the APIC into flat delivery mode. * Must be "all ones" explicitly for 82489DX. */ - apic_write_around(APIC_DFR, 0xffffffff); + apic_write_around(APIC_DFR, APIC_DFR_VALUE); /* * Set up the logical destination ID. */ value = apic_read(APIC_LDR); - value &= ~APIC_LDR_MASK; - value |= (1<<(smp_processor_id()+24)); - apic_write_around(APIC_LDR, value); + apic_write_around(APIC_LDR, calculate_ldr(value)); } /* @@ -1008,17 +1007,9 @@ int setup_profiling_timer(unsigned int multiplier) inline void smp_local_timer_interrupt(struct pt_regs * regs) { - int user = user_mode(regs); int cpu = smp_processor_id(); - /* - * The profiling function is SMP safe. (nothing can mess - * around with "current", and the profiling counters are - * updated with atomic operations). This is especially - * useful with a profiling multiplier != 1 - */ - if (!user) - x86_do_profile(regs->eip); + x86_do_profile(regs); if (--prof_counter[cpu] <= 0) { /* @@ -1036,7 +1027,7 @@ inline void smp_local_timer_interrupt(struct pt_regs * regs) } #ifdef CONFIG_SMP - update_process_times(user); + update_process_times(user_mode(regs)); #endif } diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index 557b684431c5..e873703e0c34 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S @@ -736,6 +736,7 @@ ENTRY(sys_call_table) .long sys_alloc_hugepages /* 250 */ .long sys_free_hugepages .long sys_exit_group + .long sys_lookup_dcookie .rept NR_syscalls-(.-sys_call_table)/4 .long sys_ni_syscall diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c index 79c204a1f476..f9dc46f34e6d 100644 --- a/arch/i386/kernel/i386_ksyms.c +++ b/arch/i386/kernel/i386_ksyms.c @@ -29,6 +29,7 @@ #include <asm/pgtable.h> #include <asm/pgalloc.h> #include <asm/tlbflush.h> +#include <asm/nmi.h> extern void dump_thread(struct pt_regs *, struct user *); extern spinlock_t rtc_lock; @@ -151,6 +152,10 @@ EXPORT_SYMBOL(smp_call_function); EXPORT_SYMBOL(flush_tlb_page); #endif +#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_PM) +EXPORT_SYMBOL_GPL(set_nmi_pm_callback); +EXPORT_SYMBOL_GPL(unset_nmi_pm_callback); +#endif #ifdef CONFIG_X86_IO_APIC EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector); #endif @@ -167,6 +172,11 @@ EXPORT_SYMBOL(get_wchan); EXPORT_SYMBOL(rtc_lock); +EXPORT_SYMBOL_GPL(register_profile_notifier); +EXPORT_SYMBOL_GPL(unregister_profile_notifier); +EXPORT_SYMBOL_GPL(set_nmi_callback); +EXPORT_SYMBOL_GPL(unset_nmi_callback); + #undef memcpy #undef memset extern void * memset(void *,int,__kernel_size_t); diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 25c6ad13b85b..5bc54a30c2f8 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -35,6 +35,7 @@ #include <asm/io.h> #include <asm/smp.h> #include <asm/desc.h> +#include "mach_apic.h" #undef APIC_LOCKUP_DEBUG @@ -1151,7 +1152,7 @@ static void __init setup_ioapic_ids_from_mpc (void) old_id = mp_ioapics[apic].mpc_apicid; - if (mp_ioapics[apic].mpc_apicid >= 0xf) { + if (mp_ioapics[apic].mpc_apicid >= APIC_BROADCAST_ID) { printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n", apic, mp_ioapics[apic].mpc_apicid); printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", @@ -1164,7 +1165,8 @@ static void __init setup_ioapic_ids_from_mpc (void) * system must have a unique ID or we get lots of nice * 'stuck on smp_invalidate_needed IPI wait' messages. */ - if (phys_id_present_map & (1 << mp_ioapics[apic].mpc_apicid)) { + if (check_apicid_used(phys_id_present_map, + mp_ioapics[apic].mpc_apicid)) { printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n", apic, mp_ioapics[apic].mpc_apicid); for (i = 0; i < 0xf; i++) diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c index 2f6f8b504523..c9bdad8cb3f1 100644 --- a/arch/i386/kernel/mpparse.c +++ b/arch/i386/kernel/mpparse.c @@ -30,6 +30,7 @@ #include <asm/mpspec.h> #include <asm/pgalloc.h> #include <asm/io_apic.h> +#include "mach_apic.h" /* Have we found an MP table */ int smp_found_config; @@ -69,6 +70,9 @@ static unsigned int __initdata num_processors; /* Bitmask of physically existing CPUs */ unsigned long phys_cpu_present_map; +int summit_x86 = 0; +u8 raw_phys_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; + /* * Intel MP BIOS table parsing routines: */ @@ -189,7 +193,7 @@ void __init MP_processor_info (struct mpc_config_processor *m) if (clustered_apic_mode) { phys_cpu_present_map |= (logical_apicid&0xf) << (4*quad); } else { - phys_cpu_present_map |= 1 << m->mpc_apicid; + phys_cpu_present_map |= apicid_to_cpu_present(m->mpc_apicid); } /* * Validate version @@ -199,6 +203,7 @@ void __init MP_processor_info (struct mpc_config_processor *m) ver = 0x10; } apic_version[m->mpc_apicid] = ver; + raw_phys_apicid[num_processors - 1] = m->mpc_apicid; } static void __init MP_bus_info (struct mpc_config_bus *m) @@ -356,6 +361,7 @@ static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, \ static int __init smp_read_mpc(struct mp_config_table *mpc) { char str[16]; + char oem[10]; int count=sizeof(*mpc); unsigned char *mpt=((unsigned char *)mpc)+count; @@ -380,14 +386,16 @@ static int __init smp_read_mpc(struct mp_config_table *mpc) printk(KERN_ERR "SMP mptable: null local APIC address!\n"); return 0; } - memcpy(str,mpc->mpc_oem,8); - str[8]=0; - printk("OEM ID: %s ",str); + memcpy(oem,mpc->mpc_oem,8); + oem[8]=0; + printk("OEM ID: %s ",oem); memcpy(str,mpc->mpc_productid,12); str[12]=0; printk("Product ID: %s ",str); + summit_check(oem, str); + printk("APIC at: 0x%lX\n",mpc->mpc_lapic); /* @@ -465,6 +473,7 @@ static int __init smp_read_mpc(struct mp_config_table *mpc) } ++mpc_record; } + clustered_apic_check(); if (!num_processors) printk(KERN_ERR "SMP mptable: no processors registered!\n"); return num_processors; diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c index fb2026daf3f1..fbae2c8deeaf 100644 --- a/arch/i386/kernel/nmi.c +++ b/arch/i386/kernel/nmi.c @@ -175,6 +175,18 @@ static int nmi_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) return 0; } +struct pm_dev * set_nmi_pm_callback(pm_callback callback) +{ + apic_pm_unregister(nmi_pmdev); + return apic_pm_register(PM_SYS_DEV, 0, callback); +} + +void unset_nmi_pm_callback(struct pm_dev * dev) +{ + apic_pm_unregister(dev); + nmi_pmdev = apic_pm_register(PM_SYS_DEV, 0, nmi_pm_callback); +} + static void nmi_pm_init(void) { if (!nmi_pmdev) diff --git a/arch/i386/kernel/profile.c b/arch/i386/kernel/profile.c new file mode 100644 index 000000000000..334af20585cb --- /dev/null +++ b/arch/i386/kernel/profile.c @@ -0,0 +1,45 @@ +/* + * linux/arch/i386/kernel/profile.c + * + * (C) 2002 John Levon <levon@movementarian.org> + * + */ + +#include <linux/profile.h> +#include <linux/spinlock.h> +#include <linux/notifier.h> +#include <linux/irq.h> +#include <asm/hw_irq.h> + +static struct notifier_block * profile_listeners; +static rwlock_t profile_lock = RW_LOCK_UNLOCKED; + +int register_profile_notifier(struct notifier_block * nb) +{ + int err; + write_lock_irq(&profile_lock); + err = notifier_chain_register(&profile_listeners, nb); + write_unlock_irq(&profile_lock); + return err; +} + + +int unregister_profile_notifier(struct notifier_block * nb) +{ + int err; + write_lock_irq(&profile_lock); + err = notifier_chain_unregister(&profile_listeners, nb); + write_unlock_irq(&profile_lock); + return err; +} + + +void x86_profile_hook(struct pt_regs * regs) +{ + /* we would not even need this lock if + * we had a global cli() on register/unregister + */ + read_lock(&profile_lock); + notifier_call_chain(&profile_listeners, 0, regs); + read_unlock(&profile_lock); +} diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 9d513dc1ceb2..acc6d8e48075 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -51,6 +51,7 @@ #include <asm/desc.h> #include <asm/arch_hooks.h> #include "smpboot_hooks.h" +#include "mach_apic.h" /* Set if we find a B stepping CPU */ static int __initdata smp_b_stepping; diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c index 4e3b4f1cb4b3..cf53d2c1d50a 100644 --- a/arch/i386/kernel/time.c +++ b/arch/i386/kernel/time.c @@ -64,11 +64,6 @@ extern spinlock_t i8259A_lock; #include "do_timer.h" -/* - * for x86_do_profile() - */ -#include <linux/irq.h> - u64 jiffies_64; unsigned long cpu_khz; /* Detected as we calibrate the TSC */ diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 68ed7969fe6d..3eeb2c41814b 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -40,6 +40,7 @@ #include <asm/debugreg.h> #include <asm/desc.h> #include <asm/i387.h> +#include <asm/nmi.h> #include <asm/smp.h> #include <asm/pgalloc.h> @@ -478,17 +479,16 @@ static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs) return; } #endif - printk("Uhhuh. NMI received for unknown reason %02x.\n", reason); + printk("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n", + reason, smp_processor_id()); printk("Dazed and confused, but trying to continue\n"); printk("Do you have a strange power saving mode enabled?\n"); } -asmlinkage void do_nmi(struct pt_regs * regs, long error_code) +static void default_do_nmi(struct pt_regs * regs) { unsigned char reason = inb(0x61); - - ++nmi_count(smp_processor_id()); - + if (!(reason & 0xc0)) { #if CONFIG_X86_LOCAL_APIC /* @@ -517,6 +517,33 @@ asmlinkage void do_nmi(struct pt_regs * regs, long error_code) inb(0x71); /* dummy */ } +static int dummy_nmi_callback(struct pt_regs * regs, int cpu) +{ + return 0; +} + +static nmi_callback_t nmi_callback = dummy_nmi_callback; + +asmlinkage void do_nmi(struct pt_regs * regs, long error_code) +{ + int cpu = smp_processor_id(); + + ++nmi_count(cpu); + + if (!nmi_callback(regs, cpu)) + default_do_nmi(regs); +} + +void set_nmi_callback(nmi_callback_t callback) +{ + nmi_callback = callback; +} + +void unset_nmi_callback(void) +{ + nmi_callback = dummy_nmi_callback; +} + /* * Our handling of the processor debug registers is non-trivial. * We do not clear them on entry and exit from the kernel. Therefore diff --git a/arch/i386/mach-generic/do_timer.h b/arch/i386/mach-generic/do_timer.h index 7ee964b2ebf2..4a24f8ad0635 100644 --- a/arch/i386/mach-generic/do_timer.h +++ b/arch/i386/mach-generic/do_timer.h @@ -20,8 +20,7 @@ static inline void do_timer_interrupt_hook(struct pt_regs *regs) * system, in that case we have to call the local interrupt handler. */ #ifndef CONFIG_X86_LOCAL_APIC - if (!user_mode(regs)) - x86_do_profile(regs->eip); + x86_do_profile(regs); #else if (!using_apic_timer) smp_local_timer_interrupt(regs); diff --git a/arch/i386/mach-generic/mach_apic.h b/arch/i386/mach-generic/mach_apic.h new file mode 100644 index 000000000000..f7be859e761e --- /dev/null +++ b/arch/i386/mach-generic/mach_apic.h @@ -0,0 +1,46 @@ +#ifndef __ASM_MACH_APIC_H +#define __ASM_MACH_APIC_H + +static inline unsigned long calculate_ldr(unsigned long old) +{ + unsigned long id; + + id = 1UL << smp_processor_id(); + return ((old & ~APIC_LDR_MASK) | SET_APIC_LOGICAL_ID(id)); +} + +#define APIC_DFR_VALUE (APIC_DFR_FLAT) + +#ifdef CONFIG_SMP + #define TARGET_CPUS (clustered_apic_mode ? 0xf : cpu_online_map) +#else + #define TARGET_CPUS 0x01 +#endif + +#define APIC_BROADCAST_ID 0x0F +#define check_apicid_used(bitmap, apicid) (bitmap & (1 << apicid)) + +static inline void summit_check(char *oem, char *productid) +{ +} + +static inline void clustered_apic_check(void) +{ + printk("Enabling APIC mode: %s. Using %d I/O APICs\n", + (clustered_apic_mode ? "NUMA-Q" : "Flat"), nr_ioapics); +} + +static inline int cpu_present_to_apicid(int mps_cpu) +{ + if (clustered_apic_mode) + return ( ((mps_cpu/4)*16) + (1<<(mps_cpu%4)) ); + else + return mps_cpu; +} + +static inline unsigned long apicid_to_cpu_present(int apicid) +{ + return (1ul << apicid); +} + +#endif /* __ASM_MACH_APIC_H */ diff --git a/arch/i386/mach-summit/mach_apic.h b/arch/i386/mach-summit/mach_apic.h new file mode 100644 index 000000000000..4cc36cd80092 --- /dev/null +++ b/arch/i386/mach-summit/mach_apic.h @@ -0,0 +1,57 @@ +#ifndef __ASM_MACH_APIC_H +#define __ASM_MACH_APIC_H + +extern int x86_summit; + +#define XAPIC_DEST_CPUS_MASK 0x0Fu +#define XAPIC_DEST_CLUSTER_MASK 0xF0u + +#define xapic_phys_to_log_apicid(phys_apic) ( (1ul << ((phys_apic) & 0x3)) |\ + ((phys_apic) & XAPIC_DEST_CLUSTER_MASK) ) + +static inline unsigned long calculate_ldr(unsigned long old) +{ + unsigned long id; + + if (x86_summit) + id = xapic_phys_to_log_apicid(hard_smp_processor_id()); + else + id = 1UL << smp_processor_id(); + return ((old & ~APIC_LDR_MASK) | SET_APIC_LOGICAL_ID(id)); +} + +#define APIC_DFR_VALUE (x86_summit ? APIC_DFR_CLUSTER : APIC_DFR_FLAT) +#define TARGET_CPUS (x86_summit ? XAPIC_DEST_CPUS_MASK : cpu_online_map) + +#define APIC_BROADCAST_ID (x86_summit ? 0xFF : 0x0F) +#define check_apicid_used(bitmap, apicid) (0) + +static inline void summit_check(char *oem, char *productid) +{ + if (!strncmp(oem, "IBM ENSW", 8) && !strncmp(str, "VIGIL SMP", 9)) + x86_summit = 1; +} + +static inline void clustered_apic_check(void) +{ + printk("Enabling APIC mode: %s. Using %d I/O APICs\n", + (x86_summit ? "Summit" : "Flat"), nr_ioapics); +} + +static inline int cpu_present_to_apicid(int mps_cpu) +{ + if (x86_summit) + return (int) raw_phys_apicid[mps_cpu]; + else + return mps_cpu; +} + +static inline unsigned long apicid_to_phys_cpu_present(int apicid) +{ + if (x86_summit) + return (1ul << (((apicid >> 4) << 2) | (apicid & 0x3))); + else + return (1ul << apicid); +} + +#endif /* __ASM_MACH_APIC_H */ diff --git a/arch/i386/mach-visws/do_timer.h b/arch/i386/mach-visws/do_timer.h index b2c1cbed5cb9..d19c7063e17d 100644 --- a/arch/i386/mach-visws/do_timer.h +++ b/arch/i386/mach-visws/do_timer.h @@ -15,8 +15,7 @@ static inline void do_timer_interrupt_hook(struct pt_regs *regs) * system, in that case we have to call the local interrupt handler. */ #ifndef CONFIG_X86_LOCAL_APIC - if (!user_mode(regs)) - x86_do_profile(regs->eip); + x86_do_profile(regs); #else if (!using_apic_timer) smp_local_timer_interrupt(regs); diff --git a/arch/i386/oprofile/Config.help b/arch/i386/oprofile/Config.help new file mode 100644 index 000000000000..38f8ae424d37 --- /dev/null +++ b/arch/i386/oprofile/Config.help @@ -0,0 +1,6 @@ +CONFIG_OPROFILE + OProfile is a profiling system capable of profiling the + whole system, include the kernel, kernel modules, libraries, + and applications. + + If unsure, say N. diff --git a/arch/i386/oprofile/Config.in b/arch/i386/oprofile/Config.in new file mode 100644 index 000000000000..dccdec27046c --- /dev/null +++ b/arch/i386/oprofile/Config.in @@ -0,0 +1,9 @@ +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + mainmenu_option next_comment + comment 'Profiling support' + bool 'Profiling support (EXPERIMENTAL)' CONFIG_PROFILING + if [ "$CONFIG_PROFILING" = "y" ]; then + tristate ' OProfile system profiling (EXPERIMENTAL)' CONFIG_OPROFILE + fi + endmenu +fi diff --git a/arch/i386/oprofile/Makefile b/arch/i386/oprofile/Makefile new file mode 100644 index 000000000000..2c26e7ef9c94 --- /dev/null +++ b/arch/i386/oprofile/Makefile @@ -0,0 +1,16 @@ +vpath %.c = . $(TOPDIR)/drivers/oprofile + +obj-$(CONFIG_OPROFILE) += oprofile.o + +DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ + oprof.o cpu_buffer.o buffer_sync.o \ + event_buffer.o oprofile_files.o \ + oprofilefs.o oprofile_stats.o ) + +oprofile-objs := $(DRIVER_OBJS) init.o timer_int.o + +ifdef CONFIG_X86_LOCAL_APIC +oprofile-objs += nmi_int.o op_model_athlon.o op_model_ppro.o +endif + +include $(TOPDIR)/Rules.make diff --git a/arch/i386/oprofile/init.c b/arch/i386/oprofile/init.c new file mode 100644 index 000000000000..0ca31295e1f2 --- /dev/null +++ b/arch/i386/oprofile/init.c @@ -0,0 +1,30 @@ +/** + * @file init.c + * + * @remark Copyright 2002 OProfile authors + * @remark Read the file COPYING + * + * @author John Levon <levon@movementarian.org> + */ + +#include <linux/kernel.h> +#include <linux/oprofile.h> +#include <linux/init.h> + +/* We support CPUs that have performance counters like the Pentium Pro + * with NMI mode samples. Other x86 CPUs use a simple interrupt keyed + * off the timer interrupt, which cannot profile interrupts-disabled + * code unlike the NMI-based code. + */ + +extern int nmi_init(struct oprofile_operations ** ops, enum oprofile_cpu * cpu); +extern void timer_init(struct oprofile_operations ** ops, enum oprofile_cpu * cpu); + +int __init oprofile_arch_init(struct oprofile_operations ** ops, enum oprofile_cpu * cpu) +{ +#ifdef CONFIG_X86_LOCAL_APIC + if (!nmi_init(ops, cpu)) +#endif + timer_init(ops, cpu); + return 0; +} diff --git a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c new file mode 100644 index 000000000000..3f1938fcdea2 --- /dev/null +++ b/arch/i386/oprofile/nmi_int.c @@ -0,0 +1,258 @@ +/** + * @file nmi_int.c + * + * @remark Copyright 2002 OProfile authors + * @remark Read the file COPYING + * + * @author John Levon <levon@movementarian.org> + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/notifier.h> +#include <linux/smp.h> +#include <linux/oprofile.h> +#include <linux/pm.h> +#include <asm/thread_info.h> +#include <asm/nmi.h> +#include <asm/ptrace.h> +#include <asm/msr.h> +#include <asm/apic.h> +#include <asm/bitops.h> +#include <asm/processor.h> + +#include "op_counter.h" +#include "op_x86_model.h" + +static struct op_x86_model_spec const * model; +static struct op_msrs cpu_msrs[NR_CPUS]; +static unsigned long saved_lvtpc[NR_CPUS]; +static unsigned long kernel_only; + +static int nmi_start(void); +static void nmi_stop(void); + +static struct pm_dev * oprofile_pmdev; + +/* We're at risk of causing big trouble unless we + * make sure to not cause any NMI interrupts when + * suspended. + */ +static int oprofile_pm_callback(struct pm_dev * dev, + pm_request_t rqst, void * data) +{ + switch (rqst) { + case PM_SUSPEND: + nmi_stop(); + break; + case PM_RESUME: + nmi_start(); + break; + } + return 0; +} + + +// FIXME: kernel_only +static int nmi_callback(struct pt_regs * regs, int cpu) +{ + return (model->check_ctrs(cpu, &cpu_msrs[cpu], regs)); +} + + +static void nmi_save_registers(struct op_msrs * msrs) +{ + unsigned int const nr_ctrs = model->num_counters; + unsigned int const nr_ctrls = model->num_controls; + struct op_msr_group * counters = &msrs->counters; + struct op_msr_group * controls = &msrs->controls; + int i; + + for (i = 0; i < nr_ctrs; ++i) { + rdmsr(counters->addrs[i], + counters->saved[i].low, + counters->saved[i].high); + } + + for (i = 0; i < nr_ctrls; ++i) { + rdmsr(controls->addrs[i], + controls->saved[i].low, + controls->saved[i].high); + } +} + + +static void nmi_cpu_setup(void * dummy) +{ + int cpu = smp_processor_id(); + struct op_msrs * msrs = &cpu_msrs[cpu]; + model->fill_in_addresses(msrs); + nmi_save_registers(msrs); + spin_lock(&oprofilefs_lock); + model->setup_ctrs(msrs); + spin_unlock(&oprofilefs_lock); + saved_lvtpc[cpu] = apic_read(APIC_LVTPC); + apic_write(APIC_LVTPC, APIC_DM_NMI); +} + + +static int nmi_setup(void) +{ + /* We walk a thin line between law and rape here. + * We need to be careful to install our NMI handler + * without actually triggering any NMIs as this will + * break the core code horrifically. + */ + smp_call_function(nmi_cpu_setup, NULL, 0, 1); + nmi_cpu_setup(0); + set_nmi_callback(nmi_callback); + oprofile_pmdev = set_nmi_pm_callback(oprofile_pm_callback); + return 0; +} + + +static void nmi_restore_registers(struct op_msrs * msrs) +{ + unsigned int const nr_ctrs = model->num_counters; + unsigned int const nr_ctrls = model->num_controls; + struct op_msr_group * counters = &msrs->counters; + struct op_msr_group * controls = &msrs->controls; + int i; + + for (i = 0; i < nr_ctrls; ++i) { + wrmsr(controls->addrs[i], + controls->saved[i].low, + controls->saved[i].high); + } + + for (i = 0; i < nr_ctrs; ++i) { + wrmsr(counters->addrs[i], + counters->saved[i].low, + counters->saved[i].high); + } +} + + +static void nmi_cpu_shutdown(void * dummy) +{ + int cpu = smp_processor_id(); + struct op_msrs * msrs = &cpu_msrs[cpu]; + apic_write(APIC_LVTPC, saved_lvtpc[cpu]); + nmi_restore_registers(msrs); +} + + +static void nmi_shutdown(void) +{ + unset_nmi_pm_callback(oprofile_pmdev); + unset_nmi_callback(); + smp_call_function(nmi_cpu_shutdown, NULL, 0, 1); + nmi_cpu_shutdown(0); +} + + +static void nmi_cpu_start(void * dummy) +{ + struct op_msrs const * msrs = &cpu_msrs[smp_processor_id()]; + model->start(msrs); +} + + +static int nmi_start(void) +{ + smp_call_function(nmi_cpu_start, NULL, 0, 1); + nmi_cpu_start(0); + return 0; +} + + +static void nmi_cpu_stop(void * dummy) +{ + struct op_msrs const * msrs = &cpu_msrs[smp_processor_id()]; + model->stop(msrs); +} + + +static void nmi_stop(void) +{ + smp_call_function(nmi_cpu_stop, NULL, 0, 1); + nmi_cpu_stop(0); +} + + +struct op_counter_config counter_config[OP_MAX_COUNTER]; + +static int nmi_create_files(struct super_block * sb, struct dentry * root) +{ + int i; + + for (i = 0; i < model->num_counters; ++i) { + struct dentry * dir; + char buf[2]; + + snprintf(buf, 2, "%d", i); + dir = oprofilefs_mkdir(sb, root, buf); + oprofilefs_create_ulong(sb, dir, "enabled", &counter_config[i].enabled); + oprofilefs_create_ulong(sb, dir, "event", &counter_config[i].event); + oprofilefs_create_ulong(sb, dir, "count", &counter_config[i].count); + oprofilefs_create_ulong(sb, dir, "unit_mask", &counter_config[i].unit_mask); + oprofilefs_create_ulong(sb, dir, "kernel", &counter_config[i].kernel); + oprofilefs_create_ulong(sb, dir, "user", &counter_config[i].user); + } + + oprofilefs_create_ulong(sb, root, "kernel_only", &kernel_only); + return 0; +} + + +struct oprofile_operations nmi_ops = { + .create_files = nmi_create_files, + .setup = nmi_setup, + .shutdown = nmi_shutdown, + .start = nmi_start, + .stop = nmi_stop +}; + + +int __init nmi_init(struct oprofile_operations ** ops, enum oprofile_cpu * cpu) +{ + __u8 vendor = current_cpu_data.x86_vendor; + __u8 family = current_cpu_data.x86; + __u8 cpu_model = current_cpu_data.x86_model; + + if (!cpu_has_apic) + return 0; + + switch (vendor) { + case X86_VENDOR_AMD: + /* Needs to be at least an Athlon (or hammer in 32bit mode) */ + if (family < 6) + return 0; + model = &op_athlon_spec; + *cpu = OPROFILE_CPU_ATHLON; + break; + + case X86_VENDOR_INTEL: + /* Less than a P6-class processor */ + if (family != 6) + return 0; + + if (cpu_model > 5) { + *cpu = OPROFILE_CPU_PIII; + } else if (cpu_model > 2) { + *cpu = OPROFILE_CPU_PII; + } else { + *cpu = OPROFILE_CPU_PPRO; + } + + model = &op_ppro_spec; + break; + + default: + return 0; + } + + *ops = &nmi_ops; + printk(KERN_INFO "oprofile: using NMI interrupt.\n"); + return 1; +} diff --git a/arch/i386/oprofile/op_counter.h b/arch/i386/oprofile/op_counter.h new file mode 100644 index 000000000000..0417e4daf562 --- /dev/null +++ b/arch/i386/oprofile/op_counter.h @@ -0,0 +1,29 @@ +/** + * @file op_counter.h + * + * @remark Copyright 2002 OProfile authors + * @remark Read the file COPYING + * + * @author John Levon + */ + +#ifndef OP_COUNTER_H +#define OP_COUNTER_H + +#define OP_MAX_COUNTER 4 + +/* Per-perfctr configuration as set via + * oprofilefs. + */ +struct op_counter_config { + unsigned long count; + unsigned long enabled; + unsigned long event; + unsigned long kernel; + unsigned long user; + unsigned long unit_mask; +}; + +extern struct op_counter_config counter_config[]; + +#endif /* OP_COUNTER_H */ diff --git a/arch/i386/oprofile/op_model_athlon.c b/arch/i386/oprofile/op_model_athlon.c new file mode 100644 index 000000000000..9d0b71c3d047 --- /dev/null +++ b/arch/i386/oprofile/op_model_athlon.c @@ -0,0 +1,149 @@ +/** + * @file op_model_athlon.h + * athlon / K7 model-specific MSR operations + * + * @remark Copyright 2002 OProfile authors + * @remark Read the file COPYING + * + * @author John Levon + * @author Philippe Elie + * @author Graydon Hoare + */ + +#include <linux/oprofile.h> +#include <asm/ptrace.h> +#include <asm/msr.h> + +#include "op_x86_model.h" +#include "op_counter.h" + +#define NUM_COUNTERS 4 +#define NUM_CONTROLS 4 + +#define CTR_READ(l,h,msrs,c) do {rdmsr(msrs->counters.addrs[(c)], (l), (h));} while (0) +#define CTR_WRITE(l,msrs,c) do {wrmsr(msrs->counters.addrs[(c)], -(unsigned int)(l), -1);} while (0) +#define CTR_OVERFLOWED(n) (!((n) & (1U<<31))) + +#define CTRL_READ(l,h,msrs,c) do {rdmsr(msrs->controls.addrs[(c)], (l), (h));} while (0) +#define CTRL_WRITE(l,h,msrs,c) do {wrmsr(msrs->controls.addrs[(c)], (l), (h));} while (0) +#define CTRL_SET_ACTIVE(n) (n |= (1<<22)) +#define CTRL_SET_INACTIVE(n) (n &= ~(1<<22)) +#define CTRL_CLEAR(x) (x &= (1<<21)) +#define CTRL_SET_ENABLE(val) (val |= 1<<20) +#define CTRL_SET_USR(val,u) (val |= ((u & 1) << 16)) +#define CTRL_SET_KERN(val,k) (val |= ((k & 1) << 17)) +#define CTRL_SET_UM(val, m) (val |= (m << 8)) +#define CTRL_SET_EVENT(val, e) (val |= e) + +static unsigned long reset_value[NUM_COUNTERS]; + +static void athlon_fill_in_addresses(struct op_msrs * const msrs) +{ + msrs->counters.addrs[0] = MSR_K7_PERFCTR0; + msrs->counters.addrs[1] = MSR_K7_PERFCTR1; + msrs->counters.addrs[2] = MSR_K7_PERFCTR2; + msrs->counters.addrs[3] = MSR_K7_PERFCTR3; + + msrs->controls.addrs[0] = MSR_K7_EVNTSEL0; + msrs->controls.addrs[1] = MSR_K7_EVNTSEL1; + msrs->controls.addrs[2] = MSR_K7_EVNTSEL2; + msrs->controls.addrs[3] = MSR_K7_EVNTSEL3; +} + + +static void athlon_setup_ctrs(struct op_msrs const * const msrs) +{ + unsigned int low, high; + int i; + + /* clear all counters */ + for (i = 0 ; i < NUM_CONTROLS; ++i) { + CTRL_READ(low, high, msrs, i); + CTRL_CLEAR(low); + CTRL_WRITE(low, high, msrs, i); + } + + /* avoid a false detection of ctr overflows in NMI handler */ + for (i = 0; i < NUM_COUNTERS; ++i) { + CTR_WRITE(1, msrs, i); + } + + /* enable active counters */ + for (i = 0; i < NUM_COUNTERS; ++i) { + if (counter_config[i].event) { + reset_value[i] = counter_config[i].count; + + CTR_WRITE(counter_config[i].count, msrs, i); + + CTRL_READ(low, high, msrs, i); + CTRL_CLEAR(low); + CTRL_SET_ENABLE(low); + CTRL_SET_USR(low, counter_config[i].user); + CTRL_SET_KERN(low, counter_config[i].kernel); + CTRL_SET_UM(low, counter_config[i].unit_mask); + CTRL_SET_EVENT(low, counter_config[i].event); + CTRL_WRITE(low, high, msrs, i); + } else { + reset_value[i] = 0; + } + } +} + + +static int athlon_check_ctrs(unsigned int const cpu, + struct op_msrs const * const msrs, + struct pt_regs * const regs) +{ + unsigned int low, high; + int handled = 0; + int i; + for (i = 0 ; i < NUM_COUNTERS; ++i) { + CTR_READ(low, high, msrs, i); + if (CTR_OVERFLOWED(low)) { + oprofile_add_sample(regs->eip, i, cpu); + CTR_WRITE(reset_value[i], msrs, i); + handled = 1; + } + } + return handled; +} + + +static void athlon_start(struct op_msrs const * const msrs) +{ + unsigned int low, high; + int i; + for (i = 0 ; i < NUM_COUNTERS ; ++i) { + if (reset_value[i]) { + CTRL_READ(low, high, msrs, i); + CTRL_SET_ACTIVE(low); + CTRL_WRITE(low, high, msrs, i); + } + } +} + + +static void athlon_stop(struct op_msrs const * const msrs) +{ + unsigned int low,high; + int i; + + /* Subtle: stop on all counters to avoid race with + * setting our pm callback */ + for (i = 0 ; i < NUM_COUNTERS ; ++i) { + CTRL_READ(low, high, msrs, i); + CTRL_SET_INACTIVE(low); + CTRL_WRITE(low, high, msrs, i); + } +} + + +struct op_x86_model_spec const op_athlon_spec = { + .num_counters = NUM_COUNTERS, + .num_controls = NUM_CONTROLS, + .fill_in_addresses = &athlon_fill_in_addresses, + .setup_ctrs = &athlon_setup_ctrs, + .check_ctrs = &athlon_check_ctrs, + .start = &athlon_start, + .stop = &athlon_stop +}; diff --git a/arch/i386/oprofile/op_model_ppro.c b/arch/i386/oprofile/op_model_ppro.c new file mode 100644 index 000000000000..9252e01bef1e --- /dev/null +++ b/arch/i386/oprofile/op_model_ppro.c @@ -0,0 +1,133 @@ +/** + * @file op_model_ppro.h + * pentium pro / P6 model-specific MSR operations + * + * @remark Copyright 2002 OProfile authors + * @remark Read the file COPYING + * + * @author John Levon + * @author Philippe Elie + * @author Graydon Hoare + */ + +#include <linux/oprofile.h> +#include <asm/ptrace.h> +#include <asm/msr.h> + +#include "op_x86_model.h" +#include "op_counter.h" + +#define NUM_COUNTERS 2 +#define NUM_CONTROLS 2 + +#define CTR_READ(l,h,msrs,c) do {rdmsr(msrs->counters.addrs[(c)], (l), (h));} while (0) +#define CTR_WRITE(l,msrs,c) do {wrmsr(msrs->counters.addrs[(c)], -(u32)(l), -1);} while (0) +#define CTR_OVERFLOWED(n) (!((n) & (1U<<31))) + +#define CTRL_READ(l,h,msrs,c) do {rdmsr((msrs->controls.addrs[(c)]), (l), (h));} while (0) +#define CTRL_WRITE(l,h,msrs,c) do {wrmsr((msrs->controls.addrs[(c)]), (l), (h));} while (0) +#define CTRL_SET_ACTIVE(n) (n |= (1<<22)) +#define CTRL_SET_INACTIVE(n) (n &= ~(1<<22)) +#define CTRL_CLEAR(x) (x &= (1<<21)) +#define CTRL_SET_ENABLE(val) (val |= 1<<20) +#define CTRL_SET_USR(val,u) (val |= ((u & 1) << 16)) +#define CTRL_SET_KERN(val,k) (val |= ((k & 1) << 17)) +#define CTRL_SET_UM(val, m) (val |= (m << 8)) +#define CTRL_SET_EVENT(val, e) (val |= e) + +static unsigned long reset_value[NUM_COUNTERS]; + +static void ppro_fill_in_addresses(struct op_msrs * const msrs) +{ + msrs->counters.addrs[0] = MSR_P6_PERFCTR0; + msrs->counters.addrs[1] = MSR_P6_PERFCTR1; + + msrs->controls.addrs[0] = MSR_P6_EVNTSEL0; + msrs->controls.addrs[1] = MSR_P6_EVNTSEL1; +} + + +static void ppro_setup_ctrs(struct op_msrs const * const msrs) +{ + unsigned int low, high; + int i; + + /* clear all counters */ + for (i = 0 ; i < NUM_CONTROLS; ++i) { + CTRL_READ(low, high, msrs, i); + CTRL_CLEAR(low); + CTRL_WRITE(low, high, msrs, i); + } + + /* avoid a false detection of ctr overflows in NMI handler */ + for (i = 0; i < NUM_COUNTERS; ++i) { + CTR_WRITE(1, msrs, i); + } + + /* enable active counters */ + for (i = 0; i < NUM_COUNTERS; ++i) { + if (counter_config[i].event) { + reset_value[i] = counter_config[i].count; + + CTR_WRITE(counter_config[i].count, msrs, i); + + CTRL_READ(low, high, msrs, i); + CTRL_CLEAR(low); + CTRL_SET_ENABLE(low); + CTRL_SET_USR(low, counter_config[i].user); + CTRL_SET_KERN(low, counter_config[i].kernel); + CTRL_SET_UM(low, counter_config[i].unit_mask); + CTRL_SET_EVENT(low, counter_config[i].event); + CTRL_WRITE(low, high, msrs, i); + } + } +} + + +static int ppro_check_ctrs(unsigned int const cpu, + struct op_msrs const * const msrs, + struct pt_regs * const regs) +{ + unsigned int low, high; + int i; + int handled = 0; + + for (i = 0 ; i < NUM_COUNTERS; ++i) { + CTR_READ(low, high, msrs, i); + if (CTR_OVERFLOWED(low)) { + oprofile_add_sample(regs->eip, i, cpu); + CTR_WRITE(reset_value[i], msrs, i); + handled = 1; + } + } + return handled; +} + + +static void ppro_start(struct op_msrs const * const msrs) +{ + unsigned int low,high; + CTRL_READ(low, high, msrs, 0); + CTRL_SET_ACTIVE(low); + CTRL_WRITE(low, high, msrs, 0); +} + + +static void ppro_stop(struct op_msrs const * const msrs) +{ + unsigned int low,high; + CTRL_READ(low, high, msrs, 0); + CTRL_SET_INACTIVE(low); + CTRL_WRITE(low, high, msrs, 0); +} + + +struct op_x86_model_spec const op_ppro_spec = { + .num_counters = NUM_COUNTERS, + .num_controls = NUM_CONTROLS, + .fill_in_addresses = &ppro_fill_in_addresses, + .setup_ctrs = &ppro_setup_ctrs, + .check_ctrs = &ppro_check_ctrs, + .start = &ppro_start, + .stop = &ppro_stop +}; diff --git a/arch/i386/oprofile/op_x86_model.h b/arch/i386/oprofile/op_x86_model.h new file mode 100644 index 000000000000..cd24c76cdea7 --- /dev/null +++ b/arch/i386/oprofile/op_x86_model.h @@ -0,0 +1,52 @@ +/** + * @file op_x86_model.h + * interface to x86 model-specific MSR operations + * + * @remark Copyright 2002 OProfile authors + * @remark Read the file COPYING + * + * @author Graydon Hoare + */ + +#ifndef OP_X86_MODEL_H +#define OP_X86_MODEL_H + +/* will need re-working for Pentium IV */ +#define MAX_MSR 4 + +struct op_saved_msr { + unsigned int high; + unsigned int low; +}; + +struct op_msr_group { + unsigned int addrs[MAX_MSR]; + struct op_saved_msr saved[MAX_MSR]; +}; + +struct op_msrs { + struct op_msr_group counters; + struct op_msr_group controls; +}; + +struct pt_regs; + +/* The model vtable abstracts the differences between + * various x86 CPU model's perfctr support. + */ +struct op_x86_model_spec { + unsigned int const num_counters; + unsigned int const num_controls; + void (*fill_in_addresses)(struct op_msrs * const msrs); + void (*setup_ctrs)(struct op_msrs const * const msrs); + int (*check_ctrs)(unsigned int const cpu, + struct op_msrs const * const msrs, + struct pt_regs * const regs); + void (*start)(struct op_msrs const * const msrs); + void (*stop)(struct op_msrs const * const msrs); +}; + +extern struct op_x86_model_spec const op_ppro_spec; +extern struct op_x86_model_spec const op_athlon_spec; + +#endif /* OP_X86_MODEL_H */ diff --git a/arch/i386/oprofile/timer_int.c b/arch/i386/oprofile/timer_int.c new file mode 100644 index 000000000000..1159b7597eef --- /dev/null +++ b/arch/i386/oprofile/timer_int.c @@ -0,0 +1,57 @@ +/** + * @file timer_int.c + * + * @remark Copyright 2002 OProfile authors + * @remark Read the file COPYING + * + * @author John Levon <levon@movementarian.org> + */ + +#include <linux/kernel.h> +#include <linux/notifier.h> +#include <linux/smp.h> +#include <linux/irq.h> +#include <linux/oprofile.h> +#include <asm/ptrace.h> + +#include "op_counter.h" + +static int timer_notify(struct notifier_block * self, unsigned long val, void * data) +{ + struct pt_regs * regs = (struct pt_regs *)data; + int cpu = smp_processor_id(); + + oprofile_add_sample(regs->eip, 0, cpu); + return 0; +} + + +static struct notifier_block timer_notifier = { + .notifier_call = timer_notify, +}; + + +static int timer_start(void) +{ + return register_profile_notifier(&timer_notifier); +} + + +static void timer_stop(void) +{ + unregister_profile_notifier(&timer_notifier); +} + + +static struct oprofile_operations timer_ops = { + .start = timer_start, + .stop = timer_stop +}; + + +void __init timer_init(struct oprofile_operations ** ops, enum oprofile_cpu * cpu) +{ + *ops = &timer_ops; + *cpu = OPROFILE_CPU_TIMER; + printk(KERN_INFO "oprofile: using timer interrupt.\n"); +} diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c index f40e6f70df3b..202952ba6723 100644 --- a/arch/m68k/atari/stram.c +++ b/arch/m68k/atari/stram.c @@ -1021,8 +1021,6 @@ static int stram_open( struct inode *inode, struct file *filp ) printk( KERN_NOTICE "Only kernel can open ST-RAM device\n" ); return( -EPERM ); } - if (MINOR(inode->i_rdev) != STRAM_MINOR) - return( -ENXIO ); if (refcnt) return( -EBUSY ); ++refcnt; @@ -1057,7 +1055,7 @@ int __init stram_device_init(void) if (!max_swap_size) /* swapping not enabled */ return -ENXIO; - stram_disk = alloc_disk(); + stram_disk = alloc_disk(1); if (!stram_disk) return -ENOMEM; @@ -1070,7 +1068,6 @@ int __init stram_device_init(void) blk_init_queue(BLK_DEFAULT_QUEUE(STRAM_MAJOR), do_stram_request); stram_disk->major = STRAM_MAJOR; stram_disk->first_minor = STRAM_MINOR; - stram_disk->minor_shift = 0; stram_disk->fops = &stram_fops; sprintf(stram_disk->disk_name, "stram"); set_capacity(stram_disk, (swap_end - swap_start)/512); diff --git a/arch/sh/kernel/mach_7751se.c b/arch/sh/kernel/mach_7751se.c index da24c384b0c4..d3f5aaf8d271 100644 --- a/arch/sh/kernel/mach_7751se.c +++ b/arch/sh/kernel/mach_7751se.c @@ -27,52 +27,52 @@ void init_7751se_IRQ(void); */ struct sh_machine_vector mv_7751se __initmv = { - mv_name: "7751 SolutionEngine", - - mv_nr_irqs: 72, - - mv_inb: sh7751se_inb, - mv_inw: sh7751se_inw, - mv_inl: sh7751se_inl, - mv_outb: sh7751se_outb, - mv_outw: sh7751se_outw, - mv_outl: sh7751se_outl, - - mv_inb_p: sh7751se_inb_p, - mv_inw_p: sh7751se_inw, - mv_inl_p: sh7751se_inl, - mv_outb_p: sh7751se_outb_p, - mv_outw_p: sh7751se_outw, - mv_outl_p: sh7751se_outl, - - mv_insb: sh7751se_insb, - mv_insw: sh7751se_insw, - mv_insl: sh7751se_insl, - mv_outsb: sh7751se_outsb, - mv_outsw: sh7751se_outsw, - mv_outsl: sh7751se_outsl, - - mv_readb: sh7751se_readb, - mv_readw: sh7751se_readw, - mv_readl: sh7751se_readl, - mv_writeb: sh7751se_writeb, - mv_writew: sh7751se_writew, - mv_writel: sh7751se_writel, - - mv_ioremap: generic_ioremap, - mv_iounmap: generic_iounmap, - - mv_isa_port2addr: sh7751se_isa_port2addr, - - mv_init_arch: setup_7751se, - mv_init_irq: init_7751se_IRQ, + .mv_name = "7751 SolutionEngine", + + .mv_nr_irqs = 72, + + .mv_inb = sh7751se_inb, + .mv_inw = sh7751se_inw, + .mv_inl = sh7751se_inl, + .mv_outb = sh7751se_outb, + .mv_outw = sh7751se_outw, + .mv_outl = sh7751se_outl, + + .mv_inb_p = sh7751se_inb_p, + .mv_inw_p = sh7751se_inw, + .mv_inl_p = sh7751se_inl, + .mv_outb_p = sh7751se_outb_p, + .mv_outw_p = sh7751se_outw, + .mv_outl_p = sh7751se_outl, + + .mv_insb = sh7751se_insb, + .mv_insw = sh7751se_insw, + .mv_insl = sh7751se_insl, + .mv_outsb = sh7751se_outsb, + .mv_outsw = sh7751se_outsw, + .mv_outsl = sh7751se_outsl, + + .mv_readb = sh7751se_readb, + .mv_readw = sh7751se_readw, + .mv_readl = sh7751se_readl, + .mv_writeb = sh7751se_writeb, + .mv_writew = sh7751se_writew, + .mv_writel = sh7751se_writel, + + .mv_ioremap = generic_ioremap, + .mv_iounmap = generic_iounmap, + + .mv_isa_port2addr = sh7751se_isa_port2addr, + + .mv_init_arch = setup_7751se, + .mv_init_irq = init_7751se_IRQ, #ifdef CONFIG_HEARTBEAT - mv_heartbeat: heartbeat_7751se, + .mv_heartbeat = heartbeat_7751se, #endif - mv_rtc_gettimeofday: sh_rtc_gettimeofday, - mv_rtc_settimeofday: sh_rtc_settimeofday, + .mv_rtc_gettimeofday = sh_rtc_gettimeofday, + .mv_rtc_settimeofday = sh_rtc_settimeofday, - mv_hw_7751se: 1, + .mv_hw_7751se = 1, }; ALIAS_MV(7751se) diff --git a/arch/sh/kernel/mach_adx.c b/arch/sh/kernel/mach_adx.c index e2c246ef4701..4aec80cf1e35 100644 --- a/arch/sh/kernel/mach_adx.c +++ b/arch/sh/kernel/mach_adx.c @@ -25,49 +25,49 @@ extern void init_adx_IRQ(void); */ struct sh_machine_vector mv_adx __initmv = { - mv_name: "A&D_ADX", + .mv_name = "A&D_ADX", - mv_nr_irqs: 48, + .mv_nr_irqs = 48, - mv_inb: adx_inb, - mv_inw: adx_inw, - mv_inl: adx_inl, - mv_outb: adx_outb, - mv_outw: adx_outw, - mv_outl: adx_outl, + .mv_inb = adx_inb, + .mv_inw = adx_inw, + .mv_inl = adx_inl, + .mv_outb = adx_outb, + .mv_outw = adx_outw, + .mv_outl = adx_outl, - mv_inb_p: adx_inb_p, - mv_inw_p: adx_inw, - mv_inl_p: adx_inl, - mv_outb_p: adx_outb_p, - mv_outw_p: adx_outw, - mv_outl_p: adx_outl, + .mv_inb_p = adx_inb_p, + .mv_inw_p = adx_inw, + .mv_inl_p = adx_inl, + .mv_outb_p = adx_outb_p, + .mv_outw_p = adx_outw, + .mv_outl_p = adx_outl, - mv_insb: adx_insb, - mv_insw: adx_insw, - mv_insl: adx_insl, - mv_outsb: adx_outsb, - mv_outsw: adx_outsw, - mv_outsl: adx_outsl, + .mv_insb = adx_insb, + .mv_insw = adx_insw, + .mv_insl = adx_insl, + .mv_outsb = adx_outsb, + .mv_outsw = adx_outsw, + .mv_outsl = adx_outsl, - mv_readb: adx_readb, - mv_readw: adx_readw, - mv_readl: adx_readl, - mv_writeb: adx_writeb, - mv_writew: adx_writew, - mv_writel: adx_writel, + .mv_readb = adx_readb, + .mv_readw = adx_readw, + .mv_readl = adx_readl, + .mv_writeb = adx_writeb, + .mv_writew = adx_writew, + .mv_writel = adx_writel, - mv_ioremap: adx_ioremap, - mv_iounmap: adx_iounmap, + .mv_ioremap = adx_ioremap, + .mv_iounmap = adx_iounmap, - mv_isa_port2addr: adx_isa_port2addr, + .mv_isa_port2addr = adx_isa_port2addr, - mv_init_arch: setup_adx, - mv_init_irq: init_adx_IRQ, + .mv_init_arch = setup_adx, + .mv_init_irq = init_adx_IRQ, - mv_rtc_gettimeofday: sh_rtc_gettimeofday, - mv_rtc_settimeofday: sh_rtc_settimeofday, + .mv_rtc_gettimeofday = sh_rtc_gettimeofday, + .mv_rtc_settimeofday = sh_rtc_settimeofday, - mv_hw_adx: 1, + .mv_hw_adx = 1, }; ALIAS_MV(adx) diff --git a/arch/sh/kernel/mach_bigsur.c b/arch/sh/kernel/mach_bigsur.c index 65d98409f8bd..e4a419c1b22f 100644 --- a/arch/sh/kernel/mach_bigsur.c +++ b/arch/sh/kernel/mach_bigsur.c @@ -29,49 +29,49 @@ extern void setup_bigsur(void); extern void init_bigsur_IRQ(void); struct sh_machine_vector mv_bigsur __initmv = { - mv_name: "Big Sur", - mv_nr_irqs: NR_IRQS, // Defined in <asm/irq.h> - mv_inb: bigsur_inb, - mv_inw: bigsur_inw, - mv_inl: bigsur_inl, - mv_outb: bigsur_outb, - mv_outw: bigsur_outw, - mv_outl: bigsur_outl, + .mv_name = "Big Sur", + .mv_nr_irqs = NR_IRQS, // Defined in <asm/irq.h> + .mv_inb = bigsur_inb, + .mv_inw = bigsur_inw, + .mv_inl = bigsur_inl, + .mv_outb = bigsur_outb, + .mv_outw = bigsur_outw, + .mv_outl = bigsur_outl, - mv_inb_p: bigsur_inb_p, - mv_inw_p: bigsur_inw, - mv_inl_p: bigsur_inl, - mv_outb_p: bigsur_outb_p, - mv_outw_p: bigsur_outw, - mv_outl_p: bigsur_outl, + .mv_inb_p = bigsur_inb_p, + .mv_inw_p = bigsur_inw, + .mv_inl_p = bigsur_inl, + .mv_outb_p = bigsur_outb_p, + .mv_outw_p = bigsur_outw, + .mv_outl_p = bigsur_outl, - mv_insb: bigsur_insb, - mv_insw: bigsur_insw, - mv_insl: bigsur_insl, - mv_outsb: bigsur_outsb, - mv_outsw: bigsur_outsw, - mv_outsl: bigsur_outsl, + .mv_insb = bigsur_insb, + .mv_insw = bigsur_insw, + .mv_insl = bigsur_insl, + .mv_outsb = bigsur_outsb, + .mv_outsw = bigsur_outsw, + .mv_outsl = bigsur_outsl, - mv_readb: generic_readb, - mv_readw: generic_readw, - mv_readl: generic_readl, - mv_writeb: generic_writeb, - mv_writew: generic_writew, - mv_writel: generic_writel, + .mv_readb = generic_readb, + .mv_readw = generic_readw, + .mv_readl = generic_readl, + .mv_writeb = generic_writeb, + .mv_writew = generic_writew, + .mv_writel = generic_writel, - mv_ioremap: generic_ioremap, - mv_iounmap: generic_iounmap, + .mv_ioremap = generic_ioremap, + .mv_iounmap = generic_iounmap, - mv_isa_port2addr: bigsur_isa_port2addr, - mv_irq_demux: bigsur_irq_demux, + .mv_isa_port2addr = bigsur_isa_port2addr, + .mv_irq_demux = bigsur_irq_demux, - mv_init_arch: setup_bigsur, - mv_init_irq: init_bigsur_IRQ, + .mv_init_arch = setup_bigsur, + .mv_init_irq = init_bigsur_IRQ, #ifdef CONFIG_HEARTBEAT - mv_heartbeat: heartbeat_bigsur, + .mv_heartbeat = heartbeat_bigsur, #endif - mv_rtc_gettimeofday: sh_rtc_gettimeofday, - mv_rtc_settimeofday: sh_rtc_settimeofday, + .mv_rtc_gettimeofday = sh_rtc_gettimeofday, + .mv_rtc_settimeofday = sh_rtc_settimeofday, }; ALIAS_MV(bigsur) diff --git a/arch/sh/kernel/mach_cat68701.c b/arch/sh/kernel/mach_cat68701.c index 1caf12563631..352419ece2b4 100644 --- a/arch/sh/kernel/mach_cat68701.c +++ b/arch/sh/kernel/mach_cat68701.c @@ -23,50 +23,50 @@ */ struct sh_machine_vector mv_cat68701 __initmv = { - mv_name: "CAT-68701", - mv_nr_irqs: 32, - mv_inb: cat68701_inb, - mv_inw: cat68701_inw, - mv_inl: cat68701_inl, - mv_outb: cat68701_outb, - mv_outw: cat68701_outw, - mv_outl: cat68701_outl, + .mv_name = "CAT-68701", + .mv_nr_irqs = 32, + .mv_inb = cat68701_inb, + .mv_inw = cat68701_inw, + .mv_inl = cat68701_inl, + .mv_outb = cat68701_outb, + .mv_outw = cat68701_outw, + .mv_outl = cat68701_outl, - mv_inb_p: cat68701_inb_p, - mv_inw_p: cat68701_inw, - mv_inl_p: cat68701_inl, - mv_outb_p: cat68701_outb_p, - mv_outw_p: cat68701_outw, - mv_outl_p: cat68701_outl, + .mv_inb_p = cat68701_inb_p, + .mv_inw_p = cat68701_inw, + .mv_inl_p = cat68701_inl, + .mv_outb_p = cat68701_outb_p, + .mv_outw_p = cat68701_outw, + .mv_outl_p = cat68701_outl, - mv_insb: cat68701_insb, - mv_insw: cat68701_insw, - mv_insl: cat68701_insl, - mv_outsb: cat68701_outsb, - mv_outsw: cat68701_outsw, - mv_outsl: cat68701_outsl, + .mv_insb = cat68701_insb, + .mv_insw = cat68701_insw, + .mv_insl = cat68701_insl, + .mv_outsb = cat68701_outsb, + .mv_outsw = cat68701_outsw, + .mv_outsl = cat68701_outsl, - mv_readb: cat68701_readb, - mv_readw: cat68701_readw, - mv_readl: cat68701_readl, - mv_writeb: cat68701_writeb, - mv_writew: cat68701_writew, - mv_writel: cat68701_writel, + .mv_readb = cat68701_readb, + .mv_readw = cat68701_readw, + .mv_readl = cat68701_readl, + .mv_writeb = cat68701_writeb, + .mv_writew = cat68701_writew, + .mv_writel = cat68701_writel, - mv_ioremap: cat68701_ioremap, - mv_iounmap: cat68701_iounmap, + .mv_ioremap = cat68701_ioremap, + .mv_iounmap = cat68701_iounmap, - mv_isa_port2addr: cat68701_isa_port2addr, - mv_irq_demux: cat68701_irq_demux, + .mv_isa_port2addr = cat68701_isa_port2addr, + .mv_irq_demux = cat68701_irq_demux, - mv_init_arch: setup_cat68701, - mv_init_irq: init_cat68701_IRQ, + .mv_init_arch = setup_cat68701, + .mv_init_irq = init_cat68701_IRQ, #ifdef CONFIG_HEARTBEAT - mv_heartbeat: heartbeat_cat68701, + .mv_heartbeat = heartbeat_cat68701, #endif - mv_rtc_gettimeofday: sh_rtc_gettimeofday, - mv_rtc_settimeofday: sh_rtc_settimeofday, + .mv_rtc_gettimeofday = sh_rtc_gettimeofday, + .mv_rtc_settimeofday = sh_rtc_settimeofday, }; ALIAS_MV(cat68701) diff --git a/arch/sh/kernel/mach_dc.c b/arch/sh/kernel/mach_dc.c index 06801a248973..f9eccfad100f 100644 --- a/arch/sh/kernel/mach_dc.c +++ b/arch/sh/kernel/mach_dc.c @@ -26,48 +26,48 @@ int aica_rtc_settimeofday(const struct timeval *tv); */ struct sh_machine_vector mv_dreamcast __initmv = { - mv_name: "dreamcast", - - mv_nr_irqs: NR_IRQS, - - mv_inb: generic_inb, - mv_inw: generic_inw, - mv_inl: generic_inl, - mv_outb: generic_outb, - mv_outw: generic_outw, - mv_outl: generic_outl, - - mv_inb_p: generic_inb_p, - mv_inw_p: generic_inw, - mv_inl_p: generic_inl, - mv_outb_p: generic_outb_p, - mv_outw_p: generic_outw, - mv_outl_p: generic_outl, - - mv_insb: generic_insb, - mv_insw: generic_insw, - mv_insl: generic_insl, - mv_outsb: generic_outsb, - mv_outsw: generic_outsw, - mv_outsl: generic_outsl, - - mv_readb: generic_readb, - mv_readw: generic_readw, - mv_readl: generic_readl, - mv_writeb: generic_writeb, - mv_writew: generic_writew, - mv_writel: generic_writel, - - mv_ioremap: generic_ioremap, - mv_iounmap: generic_iounmap, - - mv_init_arch: setup_dreamcast, - mv_isa_port2addr: dreamcast_isa_port2addr, - mv_irq_demux: systemasic_irq_demux, - - mv_rtc_gettimeofday: aica_rtc_gettimeofday, - mv_rtc_settimeofday: aica_rtc_settimeofday, - - mv_hw_dreamcast: 1, + .mv_name = "dreamcast", + + .mv_nr_irqs = NR_IRQS, + + .mv_inb = generic_inb, + .mv_inw = generic_inw, + .mv_inl = generic_inl, + .mv_outb = generic_outb, + .mv_outw = generic_outw, + .mv_outl = generic_outl, + + .mv_inb_p = generic_inb_p, + .mv_inw_p = generic_inw, + .mv_inl_p = generic_inl, + .mv_outb_p = generic_outb_p, + .mv_outw_p = generic_outw, + .mv_outl_p = generic_outl, + + .mv_insb = generic_insb, + .mv_insw = generic_insw, + .mv_insl = generic_insl, + .mv_outsb = generic_outsb, + .mv_outsw = generic_outsw, + .mv_outsl = generic_outsl, + + .mv_readb = generic_readb, + .mv_readw = generic_readw, + .mv_readl = generic_readl, + .mv_writeb = generic_writeb, + .mv_writew = generic_writew, + .mv_writel = generic_writel, + + .mv_ioremap = generic_ioremap, + .mv_iounmap = generic_iounmap, + + .mv_init_arch = setup_dreamcast, + .mv_isa_port2addr = dreamcast_isa_port2addr, + .mv_irq_demux = systemasic_irq_demux, + + .mv_rtc_gettimeofday = aica_rtc_gettimeofday, + .mv_rtc_settimeofday = aica_rtc_settimeofday, + + .mv_hw_dreamcast = 1, }; ALIAS_MV(dreamcast) diff --git a/arch/sh/kernel/mach_dmida.c b/arch/sh/kernel/mach_dmida.c index a97c6471ed8b..a94a9d7e9ce4 100644 --- a/arch/sh/kernel/mach_dmida.c +++ b/arch/sh/kernel/mach_dmida.c @@ -30,44 +30,44 @@ */ struct sh_machine_vector mv_dmida __initmv = { - mv_name: "DMIDA", + .mv_name = "DMIDA", - mv_nr_irqs: HD64465_IRQ_BASE+HD64465_IRQ_NUM, + .mv_nr_irqs = HD64465_IRQ_BASE+HD64465_IRQ_NUM, - mv_inb: hd64465_inb, - mv_inw: hd64465_inw, - mv_inl: hd64465_inl, - mv_outb: hd64465_outb, - mv_outw: hd64465_outw, - mv_outl: hd64465_outl, + .mv_inb = hd64465_inb, + .mv_inw = hd64465_inw, + .mv_inl = hd64465_inl, + .mv_outb = hd64465_outb, + .mv_outw = hd64465_outw, + .mv_outl = hd64465_outl, - mv_inb_p: hd64465_inb_p, - mv_inw_p: hd64465_inw, - mv_inl_p: hd64465_inl, - mv_outb_p: hd64465_outb_p, - mv_outw_p: hd64465_outw, - mv_outl_p: hd64465_outl, + .mv_inb_p = hd64465_inb_p, + .mv_inw_p = hd64465_inw, + .mv_inl_p = hd64465_inl, + .mv_outb_p = hd64465_outb_p, + .mv_outw_p = hd64465_outw, + .mv_outl_p = hd64465_outl, - mv_insb: hd64465_insb, - mv_insw: hd64465_insw, - mv_insl: hd64465_insl, - mv_outsb: hd64465_outsb, - mv_outsw: hd64465_outsw, - mv_outsl: hd64465_outsl, + .mv_insb = hd64465_insb, + .mv_insw = hd64465_insw, + .mv_insl = hd64465_insl, + .mv_outsb = hd64465_outsb, + .mv_outsw = hd64465_outsw, + .mv_outsl = hd64465_outsl, - mv_readb: generic_readb, - mv_readw: generic_readw, - mv_readl: generic_readl, - mv_writeb: generic_writeb, - mv_writew: generic_writew, - mv_writel: generic_writel, + .mv_readb = generic_readb, + .mv_readw = generic_readw, + .mv_readl = generic_readl, + .mv_writeb = generic_writeb, + .mv_writew = generic_writew, + .mv_writel = generic_writel, - mv_irq_demux: hd64465_irq_demux, + .mv_irq_demux = hd64465_irq_demux, - mv_rtc_gettimeofday: sh_rtc_gettimeofday, - mv_rtc_settimeofday: sh_rtc_settimeofday, + .mv_rtc_gettimeofday = sh_rtc_gettimeofday, + .mv_rtc_settimeofday = sh_rtc_settimeofday, - mv_hw_hd64465: 1, + .mv_hw_hd64465 = 1, }; ALIAS_MV(dmida) diff --git a/arch/sh/kernel/mach_ec3104.c b/arch/sh/kernel/mach_ec3104.c index 3c10b9baeb9d..46df3a051227 100644 --- a/arch/sh/kernel/mach_ec3104.c +++ b/arch/sh/kernel/mach_ec3104.c @@ -28,42 +28,42 @@ */ struct sh_machine_vector mv_ec3104 __initmv = { - mv_name: "EC3104", + .mv_name = "EC3104", - mv_nr_irqs: 96, + .mv_nr_irqs = 96, - mv_inb: ec3104_inb, - mv_inw: ec3104_inw, - mv_inl: ec3104_inl, - mv_outb: ec3104_outb, - mv_outw: ec3104_outw, - mv_outl: ec3104_outl, + .mv_inb = ec3104_inb, + .mv_inw = ec3104_inw, + .mv_inl = ec3104_inl, + .mv_outb = ec3104_outb, + .mv_outw = ec3104_outw, + .mv_outl = ec3104_outl, - mv_inb_p: generic_inb_p, - mv_inw_p: generic_inw, - mv_inl_p: generic_inl, - mv_outb_p: generic_outb_p, - mv_outw_p: generic_outw, - mv_outl_p: generic_outl, + .mv_inb_p = generic_inb_p, + .mv_inw_p = generic_inw, + .mv_inl_p = generic_inl, + .mv_outb_p = generic_outb_p, + .mv_outw_p = generic_outw, + .mv_outl_p = generic_outl, - mv_insb: generic_insb, - mv_insw: generic_insw, - mv_insl: generic_insl, - mv_outsb: generic_outsb, - mv_outsw: generic_outsw, - mv_outsl: generic_outsl, + .mv_insb = generic_insb, + .mv_insw = generic_insw, + .mv_insl = generic_insl, + .mv_outsb = generic_outsb, + .mv_outsw = generic_outsw, + .mv_outsl = generic_outsl, - mv_readb: generic_readb, - mv_readw: generic_readw, - mv_readl: generic_readl, - mv_writeb: generic_writeb, - mv_writew: generic_writew, - mv_writel: generic_writel, + .mv_readb = generic_readb, + .mv_readw = generic_readw, + .mv_readl = generic_readl, + .mv_writeb = generic_writeb, + .mv_writew = generic_writew, + .mv_writel = generic_writel, - mv_irq_demux: ec3104_irq_demux, + .mv_irq_demux = ec3104_irq_demux, - mv_rtc_gettimeofday: sh_rtc_gettimeofday, - mv_rtc_settimeofday: sh_rtc_settimeofday, + .mv_rtc_gettimeofday = sh_rtc_gettimeofday, + .mv_rtc_settimeofday = sh_rtc_settimeofday, }; ALIAS_MV(ec3104) diff --git a/arch/sh/kernel/mach_hp600.c b/arch/sh/kernel/mach_hp600.c index 66b96da9703a..50ca56ce6b89 100644 --- a/arch/sh/kernel/mach_hp600.c +++ b/arch/sh/kernel/mach_hp600.c @@ -24,135 +24,135 @@ */ struct sh_machine_vector mv_hp620 __initmv = { - mv_name: "hp620", - - mv_nr_irqs: HD64461_IRQBASE+HD64461_IRQ_NUM, - - mv_inb: hd64461_inb, - mv_inw: hd64461_inw, - mv_inl: hd64461_inl, - mv_outb: hd64461_outb, - mv_outw: hd64461_outw, - mv_outl: hd64461_outl, - - mv_inb_p: hd64461_inb_p, - mv_inw_p: hd64461_inw, - mv_inl_p: hd64461_inl, - mv_outb_p: hd64461_outb_p, - mv_outw_p: hd64461_outw, - mv_outl_p: hd64461_outl, - - mv_insb: hd64461_insb, - mv_insw: hd64461_insw, - mv_insl: hd64461_insl, - mv_outsb: hd64461_outsb, - mv_outsw: hd64461_outsw, - mv_outsl: hd64461_outsl, - - mv_readb: generic_readb, - mv_readw: generic_readw, - mv_readl: generic_readl, - mv_writeb: generic_writeb, - mv_writew: generic_writew, - mv_writel: generic_writel, - - mv_irq_demux: hd64461_irq_demux, - - mv_rtc_gettimeofday: sh_rtc_gettimeofday, - mv_rtc_settimeofday: sh_rtc_settimeofday, - - mv_hw_hp600: 1, - mv_hw_hp620: 1, - mv_hw_hd64461: 1, + .mv_name = "hp620", + + .mv_nr_irqs = HD64461_IRQBASE+HD64461_IRQ_NUM, + + .mv_inb = hd64461_inb, + .mv_inw = hd64461_inw, + .mv_inl = hd64461_inl, + .mv_outb = hd64461_outb, + .mv_outw = hd64461_outw, + .mv_outl = hd64461_outl, + + .mv_inb_p = hd64461_inb_p, + .mv_inw_p = hd64461_inw, + .mv_inl_p = hd64461_inl, + .mv_outb_p = hd64461_outb_p, + .mv_outw_p = hd64461_outw, + .mv_outl_p = hd64461_outl, + + .mv_insb = hd64461_insb, + .mv_insw = hd64461_insw, + .mv_insl = hd64461_insl, + .mv_outsb = hd64461_outsb, + .mv_outsw = hd64461_outsw, + .mv_outsl = hd64461_outsl, + + .mv_readb = generic_readb, + .mv_readw = generic_readw, + .mv_readl = generic_readl, + .mv_writeb = generic_writeb, + .mv_writew = generic_writew, + .mv_writel = generic_writel, + + .mv_irq_demux = hd64461_irq_demux, + + .mv_rtc_gettimeofday = sh_rtc_gettimeofday, + .mv_rtc_settimeofday = sh_rtc_settimeofday, + + .mv_hw_hp600 = 1, + .mv_hw_hp620 = 1, + .mv_hw_hd64461 = 1, }; ALIAS_MV(hp620) struct sh_machine_vector mv_hp680 __initmv = { - mv_name: "hp680", - - mv_nr_irqs: HD64461_IRQBASE+HD64461_IRQ_NUM, - - mv_inb: hd64461_inb, - mv_inw: hd64461_inw, - mv_inl: hd64461_inl, - mv_outb: hd64461_outb, - mv_outw: hd64461_outw, - mv_outl: hd64461_outl, - - mv_inb_p: hd64461_inb_p, - mv_inw_p: hd64461_inw, - mv_inl_p: hd64461_inl, - mv_outb_p: hd64461_outb_p, - mv_outw_p: hd64461_outw, - mv_outl_p: hd64461_outl, - - mv_insb: hd64461_insb, - mv_insw: hd64461_insw, - mv_insl: hd64461_insl, - mv_outsb: hd64461_outsb, - mv_outsw: hd64461_outsw, - mv_outsl: hd64461_outsl, - - mv_readb: generic_readb, - mv_readw: generic_readw, - mv_readl: generic_readl, - mv_writeb: generic_writeb, - mv_writew: generic_writew, - mv_writel: generic_writel, - - mv_irq_demux: hd64461_irq_demux, - - mv_rtc_gettimeofday: sh_rtc_gettimeofday, - mv_rtc_settimeofday: sh_rtc_settimeofday, - - mv_hw_hp600: 1, - mv_hw_hp680: 1, - mv_hw_hd64461: 1, + .mv_name = "hp680", + + .mv_nr_irqs = HD64461_IRQBASE+HD64461_IRQ_NUM, + + .mv_inb = hd64461_inb, + .mv_inw = hd64461_inw, + .mv_inl = hd64461_inl, + .mv_outb = hd64461_outb, + .mv_outw = hd64461_outw, + .mv_outl = hd64461_outl, + + .mv_inb_p = hd64461_inb_p, + .mv_inw_p = hd64461_inw, + .mv_inl_p = hd64461_inl, + .mv_outb_p = hd64461_outb_p, + .mv_outw_p = hd64461_outw, + .mv_outl_p = hd64461_outl, + + .mv_insb = hd64461_insb, + .mv_insw = hd64461_insw, + .mv_insl = hd64461_insl, + .mv_outsb = hd64461_outsb, + .mv_outsw = hd64461_outsw, + .mv_outsl = hd64461_outsl, + + .mv_readb = generic_readb, + .mv_readw = generic_readw, + .mv_readl = generic_readl, + .mv_writeb = generic_writeb, + .mv_writew = generic_writew, + .mv_writel = generic_writel, + + .mv_irq_demux = hd64461_irq_demux, + + .mv_rtc_gettimeofday = sh_rtc_gettimeofday, + .mv_rtc_settimeofday = sh_rtc_settimeofday, + + .mv_hw_hp600 = 1, + .mv_hw_hp680 = 1, + .mv_hw_hd64461 = 1, }; ALIAS_MV(hp680) struct sh_machine_vector mv_hp690 __initmv = { - mv_name: "hp690", - - mv_nr_irqs: HD64461_IRQBASE+HD64461_IRQ_NUM, - - mv_inb: hd64461_inb, - mv_inw: hd64461_inw, - mv_inl: hd64461_inl, - mv_outb: hd64461_outb, - mv_outw: hd64461_outw, - mv_outl: hd64461_outl, - - mv_inb_p: hd64461_inb_p, - mv_inw_p: hd64461_inw, - mv_inl_p: hd64461_inl, - mv_outb_p: hd64461_outb_p, - mv_outw_p: hd64461_outw, - mv_outl_p: hd64461_outl, - - mv_insb: hd64461_insb, - mv_insw: hd64461_insw, - mv_insl: hd64461_insl, - mv_outsb: hd64461_outsb, - mv_outsw: hd64461_outsw, - mv_outsl: hd64461_outsl, - - mv_readb: generic_readb, - mv_readw: generic_readw, - mv_readl: generic_readl, - mv_writeb: generic_writeb, - mv_writew: generic_writew, - mv_writel: generic_writel, - - mv_irq_demux: hd64461_irq_demux, - - mv_rtc_gettimeofday: sh_rtc_gettimeofday, - mv_rtc_settimeofday: sh_rtc_settimeofday, - - mv_hw_hp600: 1, - mv_hw_hp690: 1, - mv_hw_hd64461: 1, + .mv_name = "hp690", + + .mv_nr_irqs = HD64461_IRQBASE+HD64461_IRQ_NUM, + + .mv_inb = hd64461_inb, + .mv_inw = hd64461_inw, + .mv_inl = hd64461_inl, + .mv_outb = hd64461_outb, + .mv_outw = hd64461_outw, + .mv_outl = hd64461_outl, + + .mv_inb_p = hd64461_inb_p, + .mv_inw_p = hd64461_inw, + .mv_inl_p = hd64461_inl, + .mv_outb_p = hd64461_outb_p, + .mv_outw_p = hd64461_outw, + .mv_outl_p = hd64461_outl, + + .mv_insb = hd64461_insb, + .mv_insw = hd64461_insw, + .mv_insl = hd64461_insl, + .mv_outsb = hd64461_outsb, + .mv_outsw = hd64461_outsw, + .mv_outsl = hd64461_outsl, + + .mv_readb = generic_readb, + .mv_readw = generic_readw, + .mv_readl = generic_readl, + .mv_writeb = generic_writeb, + .mv_writew = generic_writew, + .mv_writel = generic_writel, + + .mv_irq_demux = hd64461_irq_demux, + + .mv_rtc_gettimeofday = sh_rtc_gettimeofday, + .mv_rtc_settimeofday = sh_rtc_settimeofday, + + .mv_hw_hp600 = 1, + .mv_hw_hp690 = 1, + .mv_hw_hd64461 = 1, }; ALIAS_MV(hp690) diff --git a/arch/sh/kernel/mach_se.c b/arch/sh/kernel/mach_se.c index 3cdc7169de49..c1241da421cb 100644 --- a/arch/sh/kernel/mach_se.c +++ b/arch/sh/kernel/mach_se.c @@ -27,58 +27,58 @@ void init_se_IRQ(void); */ struct sh_machine_vector mv_se __initmv = { - mv_name: "SolutionEngine", + .mv_name = "SolutionEngine", #if defined(__SH4__) - mv_nr_irqs: 48, + .mv_nr_irqs = 48, #elif defined(CONFIG_CPU_SUBTYPE_SH7708) - mv_nr_irqs: 32, + .mv_nr_irqs = 32, #elif defined(CONFIG_CPU_SUBTYPE_SH7709) - mv_nr_irqs: 61, + .mv_nr_irqs = 61, #endif - mv_inb: se_inb, - mv_inw: se_inw, - mv_inl: se_inl, - mv_outb: se_outb, - mv_outw: se_outw, - mv_outl: se_outl, - - mv_inb_p: se_inb_p, - mv_inw_p: se_inw, - mv_inl_p: se_inl, - mv_outb_p: se_outb_p, - mv_outw_p: se_outw, - mv_outl_p: se_outl, - - mv_insb: se_insb, - mv_insw: se_insw, - mv_insl: se_insl, - mv_outsb: se_outsb, - mv_outsw: se_outsw, - mv_outsl: se_outsl, - - mv_readb: se_readb, - mv_readw: se_readw, - mv_readl: se_readl, - mv_writeb: se_writeb, - mv_writew: se_writew, - mv_writel: se_writel, - - mv_ioremap: generic_ioremap, - mv_iounmap: generic_iounmap, - - mv_isa_port2addr: se_isa_port2addr, - - mv_init_arch: setup_se, - mv_init_irq: init_se_IRQ, + .mv_inb = se_inb, + .mv_inw = se_inw, + .mv_inl = se_inl, + .mv_outb = se_outb, + .mv_outw = se_outw, + .mv_outl = se_outl, + + .mv_inb_p = se_inb_p, + .mv_inw_p = se_inw, + .mv_inl_p = se_inl, + .mv_outb_p = se_outb_p, + .mv_outw_p = se_outw, + .mv_outl_p = se_outl, + + .mv_insb = se_insb, + .mv_insw = se_insw, + .mv_insl = se_insl, + .mv_outsb = se_outsb, + .mv_outsw = se_outsw, + .mv_outsl = se_outsl, + + .mv_readb = se_readb, + .mv_readw = se_readw, + .mv_readl = se_readl, + .mv_writeb = se_writeb, + .mv_writew = se_writew, + .mv_writel = se_writel, + + .mv_ioremap = generic_ioremap, + .mv_iounmap = generic_iounmap, + + .mv_isa_port2addr = se_isa_port2addr, + + .mv_init_arch = setup_se, + .mv_init_irq = init_se_IRQ, #ifdef CONFIG_HEARTBEAT - mv_heartbeat: heartbeat_se, + .mv_heartbeat = heartbeat_se, #endif - mv_rtc_gettimeofday: sh_rtc_gettimeofday, - mv_rtc_settimeofday: sh_rtc_settimeofday, + .mv_rtc_gettimeofday = sh_rtc_gettimeofday, + .mv_rtc_settimeofday = sh_rtc_settimeofday, - mv_hw_se: 1, + .mv_hw_se = 1, }; ALIAS_MV(se) diff --git a/arch/sh/kernel/mach_unknown.c b/arch/sh/kernel/mach_unknown.c index ce2f32e95674..75cff0d139af 100644 --- a/arch/sh/kernel/mach_unknown.c +++ b/arch/sh/kernel/mach_unknown.c @@ -23,50 +23,50 @@ */ struct sh_machine_vector mv_unknown __initmv = { - mv_name: "Unknown", + .mv_name = "Unknown", #if defined(__SH4__) - mv_nr_irqs: 48, + .mv_nr_irqs = 48, #elif defined(CONFIG_CPU_SUBTYPE_SH7708) - mv_nr_irqs: 32, + .mv_nr_irqs = 32, #elif defined(CONFIG_CPU_SUBTYPE_SH7709) - mv_nr_irqs: 61, + .mv_nr_irqs = 61, #endif - mv_inb: unknown_inb, - mv_inw: unknown_inw, - mv_inl: unknown_inl, - mv_outb: unknown_outb, - mv_outw: unknown_outw, - mv_outl: unknown_outl, + .mv_inb = unknown_inb, + .mv_inw = unknown_inw, + .mv_inl = unknown_inl, + .mv_outb = unknown_outb, + .mv_outw = unknown_outw, + .mv_outl = unknown_outl, - mv_inb_p: unknown_inb_p, - mv_inw_p: unknown_inw_p, - mv_inl_p: unknown_inl_p, - mv_outb_p: unknown_outb_p, - mv_outw_p: unknown_outw_p, - mv_outl_p: unknown_outl_p, + .mv_inb_p = unknown_inb_p, + .mv_inw_p = unknown_inw_p, + .mv_inl_p = unknown_inl_p, + .mv_outb_p = unknown_outb_p, + .mv_outw_p = unknown_outw_p, + .mv_outl_p = unknown_outl_p, - mv_insb: unknown_insb, - mv_insw: unknown_insw, - mv_insl: unknown_insl, - mv_outsb: unknown_outsb, - mv_outsw: unknown_outsw, - mv_outsl: unknown_outsl, + .mv_insb = unknown_insb, + .mv_insw = unknown_insw, + .mv_insl = unknown_insl, + .mv_outsb = unknown_outsb, + .mv_outsw = unknown_outsw, + .mv_outsl = unknown_outsl, - mv_readb: unknown_readb, - mv_readw: unknown_readw, - mv_readl: unknown_readl, - mv_writeb: unknown_writeb, - mv_writew: unknown_writew, - mv_writel: unknown_writel, + .mv_readb = unknown_readb, + .mv_readw = unknown_readw, + .mv_readl = unknown_readl, + .mv_writeb = unknown_writeb, + .mv_writew = unknown_writew, + .mv_writel = unknown_writel, - mv_ioremap: unknown_ioremap, - mv_iounmap: unknown_iounmap, + .mv_ioremap = unknown_ioremap, + .mv_iounmap = unknown_iounmap, - mv_isa_port2addr: unknown_isa_port2addr, + .mv_isa_port2addr = unknown_isa_port2addr, - mv_rtc_gettimeofday: sh_rtc_gettimeofday, - mv_rtc_settimeofday: sh_rtc_settimeofday, + .mv_rtc_gettimeofday = sh_rtc_gettimeofday, + .mv_rtc_settimeofday = sh_rtc_settimeofday, }; ALIAS_MV(unknown) diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index f1ab9da0197d..6043bb426965 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -171,12 +171,12 @@ static int __init sh_console_setup(struct console *co, char *options) } static struct console sh_console = { - name: "bios", - write: sh_console_write, - device: sh_console_device, - setup: sh_console_setup, - flags: CON_PRINTBUFFER, - index: -1, + .name = "bios", + .write = sh_console_write, + .device = sh_console_device, + .setup = sh_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, }; void sh_console_init(void) @@ -548,9 +548,9 @@ static void c_stop(struct seq_file *m, void *v) { } struct seq_operations cpuinfo_op = { - start: c_start, - next: c_next, - stop: c_stop, - show: show_cpuinfo, + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = show_cpuinfo, }; #endif diff --git a/arch/sh/kernel/setup_cqreek.c b/arch/sh/kernel/setup_cqreek.c index 9281a6923dfe..2e55b9cd53f4 100644 --- a/arch/sh/kernel/setup_cqreek.c +++ b/arch/sh/kernel/setup_cqreek.c @@ -200,53 +200,53 @@ void __init setup_cqreek(void) */ struct sh_machine_vector mv_cqreek __initmv = { - mv_name: "CqREEK", + .mv_name = "CqREEK", #if defined(__SH4__) - mv_nr_irqs: 48, + .mv_nr_irqs = 48, #elif defined(CONFIG_CPU_SUBTYPE_SH7708) - mv_nr_irqs: 32, + .mv_nr_irqs = 32, #elif defined(CONFIG_CPU_SUBTYPE_SH7709) - mv_nr_irqs: 61, + .mv_nr_irqs = 61, #endif - mv_inb: generic_inb, - mv_inw: generic_inw, - mv_inl: generic_inl, - mv_outb: generic_outb, - mv_outw: generic_outw, - mv_outl: generic_outl, - - mv_inb_p: generic_inb_p, - mv_inw_p: generic_inw_p, - mv_inl_p: generic_inl_p, - mv_outb_p: generic_outb_p, - mv_outw_p: generic_outw_p, - mv_outl_p: generic_outl_p, - - mv_insb: generic_insb, - mv_insw: generic_insw, - mv_insl: generic_insl, - mv_outsb: generic_outsb, - mv_outsw: generic_outsw, - mv_outsl: generic_outsl, - - mv_readb: generic_readb, - mv_readw: generic_readw, - mv_readl: generic_readl, - mv_writeb: generic_writeb, - mv_writew: generic_writew, - mv_writel: generic_writel, - - mv_init_arch: setup_cqreek, - mv_init_irq: init_cqreek_IRQ, - - mv_isa_port2addr: cqreek_port2addr, - - mv_ioremap: generic_ioremap, - mv_iounmap: generic_iounmap, - - mv_rtc_gettimeofday: sh_rtc_gettimeofday, - mv_rtc_settimeofday: sh_rtc_settimeofday, + .mv_inb = generic_inb, + .mv_inw = generic_inw, + .mv_inl = generic_inl, + .mv_outb = generic_outb, + .mv_outw = generic_outw, + .mv_outl = generic_outl, + + .mv_inb_p = generic_inb_p, + .mv_inw_p = generic_inw_p, + .mv_inl_p = generic_inl_p, + .mv_outb_p = generic_outb_p, + .mv_outw_p = generic_outw_p, + .mv_outl_p = generic_outl_p, + + .mv_insb = generic_insb, + .mv_insw = generic_insw, + .mv_insl = generic_insl, + .mv_outsb = generic_outsb, + .mv_outsw = generic_outsw, + .mv_outsl = generic_outsl, + + .mv_readb = generic_readb, + .mv_readw = generic_readw, + .mv_readl = generic_readl, + .mv_writeb = generic_writeb, + .mv_writew = generic_writew, + .mv_writel = generic_writel, + + .mv_init_arch = setup_cqreek, + .mv_init_irq = init_cqreek_IRQ, + + .mv_isa_port2addr = cqreek_port2addr, + + .mv_ioremap = generic_ioremap, + .mv_iounmap = generic_iounmap, + + .mv_rtc_gettimeofday = sh_rtc_gettimeofday, + .mv_rtc_settimeofday = sh_rtc_settimeofday, }; ALIAS_MV(cqreek) diff --git a/arch/sh/kernel/setup_dc.c b/arch/sh/kernel/setup_dc.c index 537b040dadd5..f18c35e6febe 100644 --- a/arch/sh/kernel/setup_dc.c +++ b/arch/sh/kernel/setup_dc.c @@ -123,13 +123,13 @@ static void shutdown_systemasic_irq(unsigned int irq) } static struct hw_interrupt_type systemasic_int = { - typename: "System ASIC", - startup: startup_systemasic_irq, - shutdown: shutdown_systemasic_irq, - enable: enable_systemasic_irq, - disable: disable_systemasic_irq, - ack: ack_systemasic_irq, - end: end_systemasic_irq, + .typename = "System ASIC", + .startup = startup_systemasic_irq, + .shutdown = shutdown_systemasic_irq, + .enable = enable_systemasic_irq, + .disable = disable_systemasic_irq, + .ack = ack_systemasic_irq, + .end = end_systemasic_irq, }; /* diff --git a/arch/sh/kernel/setup_ec3104.c b/arch/sh/kernel/setup_ec3104.c index 4c8c8bd7217b..c864e34f6b4d 100644 --- a/arch/sh/kernel/setup_ec3104.c +++ b/arch/sh/kernel/setup_ec3104.c @@ -185,13 +185,13 @@ static void shutdown_ec3104_irq(unsigned int irq) } static struct hw_interrupt_type ec3104_int = { - typename: "EC3104", - enable: enable_ec3104_irq, - disable: disable_ec3104_irq, - ack: mask_and_ack_ec3104_irq, - end: end_ec3104_irq, - startup: startup_ec3104_irq, - shutdown: shutdown_ec3104_irq, + .typename = "EC3104", + .enable = enable_ec3104_irq, + .disable = disable_ec3104_irq, + .ack = mask_and_ack_ec3104_irq, + .end = end_ec3104_irq, + .startup = startup_ec3104_irq, + .shutdown = shutdown_ec3104_irq, }; /* Yuck. the _demux API is ugly */ diff --git a/arch/sh/kernel/setup_hd64465.c b/arch/sh/kernel/setup_hd64465.c index bcf5f42a9344..857f9da68834 100644 --- a/arch/sh/kernel/setup_hd64465.c +++ b/arch/sh/kernel/setup_hd64465.c @@ -89,13 +89,13 @@ static void shutdown_hd64465_irq(unsigned int irq) static struct hw_interrupt_type hd64465_irq_type = { - typename: "HD64465-IRQ", - startup: startup_hd64465_irq, - shutdown: shutdown_hd64465_irq, - enable: enable_hd64465_irq, - disable: disable_hd64465_irq, - ack: mask_and_ack_hd64465, - end: end_hd64465_irq + .typename = "HD64465-IRQ", + .startup = startup_hd64465_irq, + .shutdown = shutdown_hd64465_irq, + .enable = enable_hd64465_irq, + .disable = disable_hd64465_irq, + .ack = mask_and_ack_hd64465, + .end = end_hd64465_irq }; diff --git a/arch/sh/kernel/setup_sh2000.c b/arch/sh/kernel/setup_sh2000.c index ce0770069d60..ad8604916446 100644 --- a/arch/sh/kernel/setup_sh2000.c +++ b/arch/sh/kernel/setup_sh2000.c @@ -48,48 +48,48 @@ int __init setup_sh2000(void) */ struct sh_machine_vector mv_sh2000 __initmv = { - mv_name: "sh2000", + .mv_name = "sh2000", - mv_nr_irqs: 80, + .mv_nr_irqs = 80, - mv_inb: generic_inb, - mv_inw: generic_inw, - mv_inl: generic_inl, - mv_outb: generic_outb, - mv_outw: generic_outw, - mv_outl: generic_outl, + .mv_inb = generic_inb, + .mv_inw = generic_inw, + .mv_inl = generic_inl, + .mv_outb = generic_outb, + .mv_outw = generic_outw, + .mv_outl = generic_outl, - mv_inb_p: generic_inb_p, - mv_inw_p: generic_inw_p, - mv_inl_p: generic_inl_p, - mv_outb_p: generic_outb_p, - mv_outw_p: generic_outw_p, - mv_outl_p: generic_outl_p, + .mv_inb_p = generic_inb_p, + .mv_inw_p = generic_inw_p, + .mv_inl_p = generic_inl_p, + .mv_outb_p = generic_outb_p, + .mv_outw_p = generic_outw_p, + .mv_outl_p = generic_outl_p, - mv_insb: generic_insb, - mv_insw: generic_insw, - mv_insl: generic_insl, - mv_outsb: generic_outsb, - mv_outsw: generic_outsw, - mv_outsl: generic_outsl, + .mv_insb = generic_insb, + .mv_insw = generic_insw, + .mv_insl = generic_insl, + .mv_outsb = generic_outsb, + .mv_outsw = generic_outsw, + .mv_outsl = generic_outsl, - mv_readb: generic_readb, - mv_readw: generic_readw, - mv_readl: generic_readl, - mv_writeb: generic_writeb, - mv_writew: generic_writew, - mv_writel: generic_writel, + .mv_readb = generic_readb, + .mv_readw = generic_readw, + .mv_readl = generic_readl, + .mv_writeb = generic_writeb, + .mv_writew = generic_writew, + .mv_writel = generic_writel, - mv_init_arch: setup_sh2000, + .mv_init_arch = setup_sh2000, - mv_isa_port2addr: sh2000_isa_port2addr, + .mv_isa_port2addr = sh2000_isa_port2addr, - mv_ioremap: generic_ioremap, - mv_iounmap: generic_iounmap, + .mv_ioremap = generic_ioremap, + .mv_iounmap = generic_iounmap, - mv_rtc_gettimeofday: sh_rtc_gettimeofday, - mv_rtc_settimeofday: sh_rtc_settimeofday, + .mv_rtc_gettimeofday = sh_rtc_gettimeofday, + .mv_rtc_settimeofday = sh_rtc_settimeofday, - mv_hw_sh2000: 1, + .mv_hw_sh2000 = 1, }; ALIAS_MV(sh2000) diff --git a/arch/sh/stboards/mach.c b/arch/sh/stboards/mach.c index 614dd2a889dc..879bfe9e5a73 100644 --- a/arch/sh/stboards/mach.c +++ b/arch/sh/stboards/mach.c @@ -26,52 +26,52 @@ void heartbeat_harp(void); */ struct sh_machine_vector mv_harp __initmv = { - mv_name: "STB1 Harp", + .mv_name = "STB1 Harp", - mv_nr_irqs: 89 + HD64465_IRQ_NUM, + .mv_nr_irqs = 89 + HD64465_IRQ_NUM, - mv_inb: hd64465_inb, - mv_inw: hd64465_inw, - mv_inl: hd64465_inl, - mv_outb: hd64465_outb, - mv_outw: hd64465_outw, - mv_outl: hd64465_outl, + .mv_inb = hd64465_inb, + .mv_inw = hd64465_inw, + .mv_inl = hd64465_inl, + .mv_outb = hd64465_outb, + .mv_outw = hd64465_outw, + .mv_outl = hd64465_outl, - mv_inb_p: hd64465_inb_p, - mv_inw_p: hd64465_inw, - mv_inl_p: hd64465_inl, - mv_outb_p: hd64465_outb_p, - mv_outw_p: hd64465_outw, - mv_outl_p: hd64465_outl, + .mv_inb_p = hd64465_inb_p, + .mv_inw_p = hd64465_inw, + .mv_inl_p = hd64465_inl, + .mv_outb_p = hd64465_outb_p, + .mv_outw_p = hd64465_outw, + .mv_outl_p = hd64465_outl, - mv_insb: hd64465_insb, - mv_insw: hd64465_insw, - mv_insl: hd64465_insl, - mv_outsb: hd64465_outsb, - mv_outsw: hd64465_outsw, - mv_outsl: hd64465_outsl, + .mv_insb = hd64465_insb, + .mv_insw = hd64465_insw, + .mv_insl = hd64465_insl, + .mv_outsb = hd64465_outsb, + .mv_outsw = hd64465_outsw, + .mv_outsl = hd64465_outsl, - mv_readb: generic_readb, - mv_readw: generic_readw, - mv_readl: generic_readl, - mv_writeb: generic_writeb, - mv_writew: generic_writew, - mv_writel: generic_writel, + .mv_readb = generic_readb, + .mv_readw = generic_readw, + .mv_readl = generic_readl, + .mv_writeb = generic_writeb, + .mv_writew = generic_writew, + .mv_writel = generic_writel, - mv_ioremap: generic_ioremap, - mv_iounmap: generic_iounmap, + .mv_ioremap = generic_ioremap, + .mv_iounmap = generic_iounmap, - mv_isa_port2addr: hd64465_isa_port2addr, + .mv_isa_port2addr = hd64465_isa_port2addr, - mv_init_arch: setup_harp, + .mv_init_arch = setup_harp, #ifdef CONFIG_PCI - mv_init_irq: init_harp_irq, + .mv_init_irq = init_harp_irq, #endif #ifdef CONFIG_HEARTBEAT - mv_heartbeat: heartbeat_harp, + .mv_heartbeat = heartbeat_harp, #endif - mv_rtc_gettimeofday: sh_rtc_gettimeofday, - mv_rtc_settimeofday: sh_rtc_settimeofday, + .mv_rtc_gettimeofday = sh_rtc_gettimeofday, + .mv_rtc_settimeofday = sh_rtc_settimeofday, }; ALIAS_MV(harp) diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 1a2f15996a2e..1aff826a51b0 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -72,11 +72,135 @@ unsigned char pci_highest_busnum = 0; */ int pci_device_reorder = 0; -spinlock_t pci_poke_lock = SPIN_LOCK_UNLOCKED; volatile int pci_poke_in_progress; volatile int pci_poke_cpu = -1; volatile int pci_poke_faulted; +static spinlock_t pci_poke_lock = SPIN_LOCK_UNLOCKED; + +void pci_config_read8(u8 *addr, u8 *ret) +{ + unsigned long flags; + u8 byte; + + spin_lock_irqsave(&pci_poke_lock, flags); + pci_poke_cpu = smp_processor_id(); + pci_poke_in_progress = 1; + pci_poke_faulted = 0; + __asm__ __volatile__("membar #Sync\n\t" + "lduba [%1] %2, %0\n\t" + "membar #Sync" + : "=r" (byte) + : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L) + : "memory"); + pci_poke_in_progress = 0; + pci_poke_cpu = -1; + if (!pci_poke_faulted) + *ret = byte; + spin_unlock_irqrestore(&pci_poke_lock, flags); +} + +void pci_config_read16(u16 *addr, u16 *ret) +{ + unsigned long flags; + u16 word; + + spin_lock_irqsave(&pci_poke_lock, flags); + pci_poke_cpu = smp_processor_id(); + pci_poke_in_progress = 1; + pci_poke_faulted = 0; + __asm__ __volatile__("membar #Sync\n\t" + "lduha [%1] %2, %0\n\t" + "membar #Sync" + : "=r" (word) + : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L) + : "memory"); + pci_poke_in_progress = 0; + pci_poke_cpu = -1; + if (!pci_poke_faulted) + *ret = word; + spin_unlock_irqrestore(&pci_poke_lock, flags); +} + +void pci_config_read32(u32 *addr, u32 *ret) +{ + unsigned long flags; + u32 dword; + + spin_lock_irqsave(&pci_poke_lock, flags); + pci_poke_cpu = smp_processor_id(); + pci_poke_in_progress = 1; + pci_poke_faulted = 0; + __asm__ __volatile__("membar #Sync\n\t" + "lduwa [%1] %2, %0\n\t" + "membar #Sync" + : "=r" (dword) + : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L) + : "memory"); + pci_poke_in_progress = 0; + pci_poke_cpu = -1; + if (!pci_poke_faulted) + *ret = dword; + spin_unlock_irqrestore(&pci_poke_lock, flags); +} + +void pci_config_write8(u8 *addr, u8 val) +{ + unsigned long flags; + + spin_lock_irqsave(&pci_poke_lock, flags); + pci_poke_cpu = smp_processor_id(); + pci_poke_in_progress = 1; + pci_poke_faulted = 0; + __asm__ __volatile__("membar #Sync\n\t" + "stba %0, [%1] %2\n\t" + "membar #Sync" + : /* no outputs */ + : "r" (val), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L) + : "memory"); + pci_poke_in_progress = 0; + pci_poke_cpu = -1; + spin_unlock_irqrestore(&pci_poke_lock, flags); +} + +void pci_config_write16(u16 *addr, u16 val) +{ + unsigned long flags; + + spin_lock_irqsave(&pci_poke_lock, flags); + pci_poke_cpu = smp_processor_id(); + pci_poke_in_progress = 1; + pci_poke_faulted = 0; + __asm__ __volatile__("membar #Sync\n\t" + "stha %0, [%1] %2\n\t" + "membar #Sync" + : /* no outputs */ + : "r" (val), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L) + : "memory"); + pci_poke_in_progress = 0; + pci_poke_cpu = -1; + spin_unlock_irqrestore(&pci_poke_lock, flags); +} + +void pci_config_write32(u32 *addr, u32 val) +{ + unsigned long flags; + + spin_lock_irqsave(&pci_poke_lock, flags); + pci_poke_cpu = smp_processor_id(); + pci_poke_in_progress = 1; + pci_poke_faulted = 0; + __asm__ __volatile__("membar #Sync\n\t" + "stwa %0, [%1] %2\n\t" + "membar #Sync" + : /* no outputs */ + : "r" (val), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L) + : "memory"); + pci_poke_in_progress = 0; + pci_poke_cpu = -1; + spin_unlock_irqrestore(&pci_poke_lock, flags); +} + /* Probe for all PCI controllers in the system. */ extern void sabre_init(int, char *); extern void psycho_init(int, char *); diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index 3d59584891cf..3453ea3e57e6 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h @@ -42,132 +42,11 @@ extern void pci_scan_for_master_abort(struct pci_controller_info *, struct pci_p extern void pci_scan_for_parity_error(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *); /* Configuration space access. */ -extern spinlock_t pci_poke_lock; -extern volatile int pci_poke_in_progress; -extern volatile int pci_poke_cpu; -extern volatile int pci_poke_faulted; - -static __inline__ void pci_config_read8(u8 *addr, u8 *ret) -{ - unsigned long flags; - u8 byte; - - spin_lock_irqsave(&pci_poke_lock, flags); - pci_poke_cpu = smp_processor_id(); - pci_poke_in_progress = 1; - pci_poke_faulted = 0; - __asm__ __volatile__("membar #Sync\n\t" - "lduba [%1] %2, %0\n\t" - "membar #Sync" - : "=r" (byte) - : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L) - : "memory"); - pci_poke_in_progress = 0; - pci_poke_cpu = -1; - if (!pci_poke_faulted) - *ret = byte; - spin_unlock_irqrestore(&pci_poke_lock, flags); -} - -static __inline__ void pci_config_read16(u16 *addr, u16 *ret) -{ - unsigned long flags; - u16 word; - - spin_lock_irqsave(&pci_poke_lock, flags); - pci_poke_cpu = smp_processor_id(); - pci_poke_in_progress = 1; - pci_poke_faulted = 0; - __asm__ __volatile__("membar #Sync\n\t" - "lduha [%1] %2, %0\n\t" - "membar #Sync" - : "=r" (word) - : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L) - : "memory"); - pci_poke_in_progress = 0; - pci_poke_cpu = -1; - if (!pci_poke_faulted) - *ret = word; - spin_unlock_irqrestore(&pci_poke_lock, flags); -} - -static __inline__ void pci_config_read32(u32 *addr, u32 *ret) -{ - unsigned long flags; - u32 dword; - - spin_lock_irqsave(&pci_poke_lock, flags); - pci_poke_cpu = smp_processor_id(); - pci_poke_in_progress = 1; - pci_poke_faulted = 0; - __asm__ __volatile__("membar #Sync\n\t" - "lduwa [%1] %2, %0\n\t" - "membar #Sync" - : "=r" (dword) - : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L) - : "memory"); - pci_poke_in_progress = 0; - pci_poke_cpu = -1; - if (!pci_poke_faulted) - *ret = dword; - spin_unlock_irqrestore(&pci_poke_lock, flags); -} - -static __inline__ void pci_config_write8(u8 *addr, u8 val) -{ - unsigned long flags; - - spin_lock_irqsave(&pci_poke_lock, flags); - pci_poke_cpu = smp_processor_id(); - pci_poke_in_progress = 1; - pci_poke_faulted = 0; - __asm__ __volatile__("membar #Sync\n\t" - "stba %0, [%1] %2\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (val), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L) - : "memory"); - pci_poke_in_progress = 0; - pci_poke_cpu = -1; - spin_unlock_irqrestore(&pci_poke_lock, flags); -} - -static __inline__ void pci_config_write16(u16 *addr, u16 val) -{ - unsigned long flags; - - spin_lock_irqsave(&pci_poke_lock, flags); - pci_poke_cpu = smp_processor_id(); - pci_poke_in_progress = 1; - pci_poke_faulted = 0; - __asm__ __volatile__("membar #Sync\n\t" - "stha %0, [%1] %2\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (val), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L) - : "memory"); - pci_poke_in_progress = 0; - pci_poke_cpu = -1; - spin_unlock_irqrestore(&pci_poke_lock, flags); -} - -static __inline__ void pci_config_write32(u32 *addr, u32 val) -{ - unsigned long flags; - - spin_lock_irqsave(&pci_poke_lock, flags); - pci_poke_cpu = smp_processor_id(); - pci_poke_in_progress = 1; - pci_poke_faulted = 0; - __asm__ __volatile__("membar #Sync\n\t" - "stwa %0, [%1] %2\n\t" - "membar #Sync" - : /* no outputs */ - : "r" (val), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L) - : "memory"); - pci_poke_in_progress = 0; - pci_poke_cpu = -1; - spin_unlock_irqrestore(&pci_poke_lock, flags); -} +extern void pci_config_read8(u8 *addr, u8 *ret); +extern void pci_config_read16(u16 *addr, u16 *ret); +extern void pci_config_read32(u32 *addr, u32 *ret); +extern void pci_config_write8(u8 *addr, u8 val); +extern void pci_config_write16(u16 *addr, u16 val); +extern void pci_config_write32(u32 *addr, u32 val); #endif /* !(PCI_IMPL_H) */ diff --git a/arch/sparc64/kernel/semaphore.c b/arch/sparc64/kernel/semaphore.c index bfb72f4041fd..4ce2f9369019 100644 --- a/arch/sparc64/kernel/semaphore.c +++ b/arch/sparc64/kernel/semaphore.c @@ -40,13 +40,57 @@ static __inline__ int __sem_update_count(struct semaphore *sem, int incr) return old_count; } -void __up(struct semaphore *sem) +static void __up(struct semaphore *sem) { __sem_update_count(sem, 1); wake_up(&sem->wait); } -void __down(struct semaphore * sem) +void up(struct semaphore *sem) +{ + /* This atomically does: + * old_val = sem->count; + * new_val = sem->count + 1; + * sem->count = new_val; + * if (old_val < 0) + * __up(sem); + * + * The (old_val < 0) test is equivalent to + * the more straightforward (new_val <= 0), + * but it is easier to test the former because + * of how the CAS instruction works. + */ + + __asm__ __volatile__("\n" +" ! up sem(%0)\n" +" membar #StoreLoad | #LoadLoad\n" +"1: lduw [%0], %%g5\n" +" add %%g5, 1, %%g7\n" +" cas [%0], %%g5, %%g7\n" +" cmp %%g5, %%g7\n" +" bne,pn %%icc, 1b\n" +" addcc %%g7, 1, %%g0\n" +" ble,pn %%icc, 3f\n" +" membar #StoreLoad | #StoreStore\n" +"2:\n" +" .subsection 2\n" +"3: mov %0, %%g5\n" +" save %%sp, -160, %%sp\n" +" mov %%g1, %%l1\n" +" mov %%g2, %%l2\n" +" mov %%g3, %%l3\n" +" call %1\n" +" mov %%g5, %%o0\n" +" mov %%l1, %%g1\n" +" mov %%l2, %%g2\n" +" ba,pt %%xcc, 2b\n" +" restore %%l3, %%g0, %%g3\n" +" .previous\n" + : : "r" (sem), "i" (__up) + : "g5", "g7", "memory", "cc"); +} + +static void __down(struct semaphore * sem) { struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); @@ -64,7 +108,90 @@ void __down(struct semaphore * sem) wake_up(&sem->wait); } -int __down_interruptible(struct semaphore * sem) +void down(struct semaphore *sem) +{ + /* This atomically does: + * old_val = sem->count; + * new_val = sem->count - 1; + * sem->count = new_val; + * if (old_val < 1) + * __down(sem); + * + * The (old_val < 1) test is equivalent to + * the more straightforward (new_val < 0), + * but it is easier to test the former because + * of how the CAS instruction works. + */ + + __asm__ __volatile__("\n" +" ! down sem(%0)\n" +"1: lduw [%0], %%g5\n" +" sub %%g5, 1, %%g7\n" +" cas [%0], %%g5, %%g7\n" +" cmp %%g5, %%g7\n" +" bne,pn %%icc, 1b\n" +" cmp %%g7, 1\n" +" bl,pn %%icc, 3f\n" +" membar #StoreLoad | #StoreStore\n" +"2:\n" +" .subsection 2\n" +"3: mov %0, %%g5\n" +" save %%sp, -160, %%sp\n" +" mov %%g1, %%l1\n" +" mov %%g2, %%l2\n" +" mov %%g3, %%l3\n" +" call %1\n" +" mov %%g5, %%o0\n" +" mov %%l1, %%g1\n" +" mov %%l2, %%g2\n" +" ba,pt %%xcc, 2b\n" +" restore %%l3, %%g0, %%g3\n" +" .previous\n" + : : "r" (sem), "i" (__down) + : "g5", "g7", "memory", "cc"); +} + +int down_trylock(struct semaphore *sem) +{ + int ret; + + /* This atomically does: + * old_val = sem->count; + * new_val = sem->count - 1; + * if (old_val < 1) { + * ret = 1; + * } else { + * sem->count = new_val; + * ret = 0; + * } + * + * The (old_val < 1) test is equivalent to + * the more straightforward (new_val < 0), + * but it is easier to test the former because + * of how the CAS instruction works. + */ + + __asm__ __volatile__("\n" +" ! down_trylock sem(%1) ret(%0)\n" +"1: lduw [%1], %%g5\n" +" sub %%g5, 1, %%g7\n" +" cmp %%g5, 1\n" +" bl,pn %%icc, 2f\n" +" mov 1, %0\n" +" cas [%1], %%g5, %%g7\n" +" cmp %%g5, %%g7\n" +" bne,pn %%icc, 1b\n" +" mov 0, %0\n" +" membar #StoreLoad | #StoreStore\n" +"2:\n" + : "=&r" (ret) + : "r" (sem) + : "g5", "g7", "memory", "cc"); + + return ret; +} + +static int __down_interruptible(struct semaphore * sem) { int retval = 0; struct task_struct *tsk = current; @@ -87,3 +214,51 @@ int __down_interruptible(struct semaphore * sem) wake_up(&sem->wait); return retval; } + +int down_interruptible(struct semaphore *sem) +{ + int ret = 0; + + /* This atomically does: + * old_val = sem->count; + * new_val = sem->count - 1; + * sem->count = new_val; + * if (old_val < 1) + * ret = __down_interruptible(sem); + * + * The (old_val < 1) test is equivalent to + * the more straightforward (new_val < 0), + * but it is easier to test the former because + * of how the CAS instruction works. + */ + + __asm__ __volatile__("\n" +" ! down_interruptible sem(%2) ret(%0)\n" +"1: lduw [%2], %%g5\n" +" sub %%g5, 1, %%g7\n" +" cas [%2], %%g5, %%g7\n" +" cmp %%g5, %%g7\n" +" bne,pn %%icc, 1b\n" +" cmp %%g7, 1\n" +" bl,pn %%icc, 3f\n" +" membar #StoreLoad | #StoreStore\n" +"2:\n" +" .subsection 2\n" +"3: mov %2, %%g5\n" +" save %%sp, -160, %%sp\n" +" mov %%g1, %%l1\n" +" mov %%g2, %%l2\n" +" mov %%g3, %%l3\n" +" call %3\n" +" mov %%g5, %%o0\n" +" mov %%l1, %%g1\n" +" mov %%l2, %%g2\n" +" mov %%l3, %%g3\n" +" ba,pt %%xcc, 2b\n" +" restore %%o0, %%g0, %0\n" +" .previous\n" + : "=r" (ret) + : "0" (ret), "r" (sem), "i" (__down_interruptible) + : "g5", "g7", "memory", "cc"); + return ret; +} diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c index 1dad12270c22..84a28f319c7b 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c @@ -230,7 +230,7 @@ asmlinkage void do_rt_sigsuspend32(u32 uset, size_t sigsetsize, struct pt_regs * } } -static inline int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t *fpu) +static int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t *fpu) { unsigned long *fpregs = current_thread_info()->fpregs; unsigned long fprs; @@ -477,7 +477,7 @@ static int invalid_frame_pointer(void *fp, int fplen) return 0; } -static inline void *get_sigframe(struct sigaction *sa, struct pt_regs *regs, unsigned long framesize) +static void *get_sigframe(struct sigaction *sa, struct pt_regs *regs, unsigned long framesize) { unsigned long sp; @@ -645,7 +645,7 @@ sigsegv: } -static inline int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t *fpu) +static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t *fpu) { unsigned long *fpregs = current_thread_info()->fpregs; unsigned long fprs; @@ -665,8 +665,8 @@ static inline int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t *fpu) return err; } -static inline void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, - int signo, sigset_t *oldset) +static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, + int signo, sigset_t *oldset) { struct new_signal_frame32 *sf; int sigframe_size; @@ -790,7 +790,7 @@ sigsegv: } /* Setup a Solaris stack frame */ -static inline void +static void setup_svr4_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc, struct pt_regs *regs, int signr, sigset_t *oldset) { @@ -1089,9 +1089,9 @@ sigsegv: do_exit(SIGSEGV); } -static inline void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, - unsigned long signr, sigset_t *oldset, - siginfo_t *info) +static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, + unsigned long signr, sigset_t *oldset, + siginfo_t *info) { struct rt_signal_frame32 *sf; int sigframe_size; diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 31110addbd92..a68ab5b7b15e 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -161,9 +161,10 @@ EXPORT_SYMBOL(smp_call_function); #endif /* semaphores */ -EXPORT_SYMBOL(__down); -EXPORT_SYMBOL(__down_interruptible); -EXPORT_SYMBOL(__up); +EXPORT_SYMBOL(down); +EXPORT_SYMBOL(down_trylock); +EXPORT_SYMBOL(down_interruptible); +EXPORT_SYMBOL(up); /* Atomic counter implementation. */ EXPORT_SYMBOL(__atomic_add); @@ -332,6 +333,7 @@ EXPORT_SYMBOL(__strncmp); EXPORT_SYMBOL(__memmove); EXPORT_SYMBOL(csum_partial_copy_sparc64); +EXPORT_SYMBOL(ip_fast_csum); /* Moving data to/from userspace. */ EXPORT_SYMBOL(__copy_to_user); diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index af4932750a33..9b62bbe3a655 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -273,7 +273,7 @@ struct itimerval32 struct timeval32 it_value; }; -static inline long get_tv32(struct timeval *o, struct timeval32 *i) +static long get_tv32(struct timeval *o, struct timeval32 *i) { return (!access_ok(VERIFY_READ, tv32, sizeof(*tv32)) || (__get_user(o->tv_sec, &i->tv_sec) | @@ -296,7 +296,7 @@ static inline long get_it32(struct itimerval *o, struct itimerval32 *i) __get_user(o->it_value.tv_usec, &i->it_value.tv_usec))); } -static inline long put_it32(struct itimerval32 *o, struct itimerval *i) +static long put_it32(struct itimerval32 *o, struct itimerval *i) { return (!access_ok(VERIFY_WRITE, i32, sizeof(*i32)) || (__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) | @@ -890,7 +890,7 @@ asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long a return sys32_fcntl(fd, cmd, arg); } -static inline int put_statfs (struct statfs32 *ubuf, struct statfs *kbuf) +static int put_statfs (struct statfs32 *ubuf, struct statfs *kbuf) { int err; @@ -1272,8 +1272,7 @@ out: * 64-bit unsigned longs. */ -static inline int -get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset) +static int get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset) { if (ufdset) { unsigned long odd; @@ -1303,8 +1302,7 @@ get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset) return 0; } -static inline void -set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset) +static void set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset) { unsigned long odd; @@ -2209,8 +2207,8 @@ static inline int iov_from_user32_to_kern(struct iovec *kiov, return tot_len; } -static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, - struct msghdr32 *umsg) +static int msghdr_from_user32_to_kern(struct msghdr *kmsg, + struct msghdr32 *umsg) { u32 tmp1, tmp2, tmp3; int err; diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c index d2be1f3629de..d5f8f8eb0360 100644 --- a/arch/sparc64/kernel/unaligned.c +++ b/arch/sparc64/kernel/unaligned.c @@ -149,8 +149,8 @@ static unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs) } } -static inline unsigned long compute_effective_address(struct pt_regs *regs, - unsigned int insn, unsigned int rd) +static unsigned long compute_effective_address(struct pt_regs *regs, + unsigned int insn, unsigned int rd) { unsigned int rs1 = (insn >> 14) & 0x1f; unsigned int rs2 = insn & 0x1f; diff --git a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile index 6d3e2a7aeaca..421f1e403bcf 100644 --- a/arch/sparc64/lib/Makefile +++ b/arch/sparc64/lib/Makefile @@ -10,6 +10,6 @@ obj-y := PeeCeeI.o blockops.o debuglocks.o strlen.o strncmp.o \ VIScopy.o VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o \ VIScsumcopyusr.o VISsave.o atomic.o rwlock.o bitops.o \ dec_and_lock.o U3memcpy.o U3copy_from_user.o U3copy_to_user.o \ - U3copy_in_user.o mcount.o + U3copy_in_user.o mcount.o ipcsum.o include $(TOPDIR)/Rules.make diff --git a/arch/sparc64/lib/ipcsum.S b/arch/sparc64/lib/ipcsum.S new file mode 100644 index 000000000000..e7d349facf35 --- /dev/null +++ b/arch/sparc64/lib/ipcsum.S @@ -0,0 +1,32 @@ + .text + .align 32 + .globl ip_fast_csum +ip_fast_csum: /* %o0 = iph, %o1 = ihl */ + sub %o1, 4, %g7 + lduw [%o0 + 0x00], %o2 + lduw [%o0 + 0x04], %g2 + lduw [%o0 + 0x08], %g3 + addcc %g2, %o2, %o2 + lduw [%o0 + 0x0c], %g2 + addccc %g3, %o2, %o2 + lduw [%o0 + 0x10], %g3 + + addccc %g2, %o2, %o2 + addc %o2, %g0, %o2 +1: addcc %g3, %o2, %o2 + add %o0, 4, %o0 + addccc %o2, %g0, %o2 + subcc %g7, 1, %g7 + be,a,pt %icc, 2f + sll %o2, 16, %g2 + + lduw [%o0 + 0x10], %g3 + ba,pt %xcc, 1b + nop +2: addcc %o2, %g2, %g2 + srl %g2, 16, %o2 + addc %o2, %g0, %o2 + xnor %g0, %o2, %o2 + set 0xffff, %o1 + retl + and %o2, %o1, %o0 diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index f34184be0c71..e5aa61b9f52d 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c @@ -222,7 +222,7 @@ static void do_fault_siginfo(int code, int sig, unsigned long address) extern int handle_ldf_stq(u32, struct pt_regs *); extern int handle_ld_nf(u32, struct pt_regs *); -static inline unsigned int get_fault_insn(struct pt_regs *regs, unsigned int insn) +static unsigned int get_fault_insn(struct pt_regs *regs, unsigned int insn) { if (!insn) { if (!regs->tpc || (regs->tpc & 0x3)) diff --git a/arch/um/Makefile b/arch/um/Makefile index c8889424b773..f4265f94529b 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -43,9 +43,8 @@ ARCH_INCLUDE = $(TOPDIR)/$(ARCH_DIR)/include # in CFLAGS. Otherwise, it would cause ld to complain about the two different # errnos. -CFLAGS += $(DEBUG) $(PROFILE) $(ARCH_CFLAGS) -D__arch_um__ \ - -DSUBARCH=\"$(SUBARCH)\" -D_LARGEFILE64_SOURCE -I$(ARCH_INCLUDE) \ - -Derrno=kernel_errno +CFLAGS += $(DEBUG) $(PROFILE) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ + -D_LARGEFILE64_SOURCE -I$(ARCH_INCLUDE) -Derrno=kernel_errno LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386 index efdac9e0747f..958d1faba8c4 100644 --- a/arch/um/Makefile-i386 +++ b/arch/um/Makefile-i386 @@ -4,7 +4,7 @@ else TOP_ADDR = 0xc0000000 endif -ARCH_CFLAGS = -U__$(SUBARCH)__ -U$(SUBARCH) +CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH) ELF_ARCH = $(SUBARCH) ELF_FORMAT = elf32-$(SUBARCH) diff --git a/arch/um/config.in b/arch/um/config.in index 32cac03d468f..e8719b1a6e20 100644 --- a/arch/um/config.in +++ b/arch/um/config.in @@ -28,8 +28,13 @@ tristate 'Host filesystem' CONFIG_HOSTFS bool 'Management console' CONFIG_MCONSOLE dep_bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ $CONFIG_MCONSOLE bool '2G/2G host address space split' CONFIG_HOST_2G_2G + bool 'Symmetric multi-processing support' CONFIG_UML_SMP define_bool CONFIG_SMP $CONFIG_UML_SMP +if [ "$CONFIG_SMP" = "y" ]; then + int 'Maximum number of CPUs (2-32)' CONFIG_NR_CPUS 32 +fi + int 'Nesting level' CONFIG_NEST_LEVEL 0 int 'Kernel address space size (in .5G units)' CONFIG_KERNEL_HALF_GIGS 1 bool 'Highmem support' CONFIG_HIGHMEM diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index c1ac4d8fbb26..79879f30aef5 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c @@ -155,6 +155,8 @@ static void tracer_winch_handler(int sig) errno); } +/* Called only by the tracing thread during initialization */ + void setup_tracer_winch(void) { int err; diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c index dd1214f116ab..efe03723db54 100644 --- a/arch/um/drivers/harddog_kern.c +++ b/arch/um/drivers/harddog_kern.c @@ -51,8 +51,8 @@ MODULE_LICENSE("GPL"); +/* Locked by the BKL in harddog_open and harddog_release */ static int timer_alive; - static int harddog_in_fd = -1; static int harddog_out_fd = -1; @@ -67,6 +67,7 @@ static int harddog_open(struct inode *inode, struct file *file) int err; char *sock = NULL; + lock_kernel(); if(timer_alive) return -EBUSY; #ifdef CONFIG_HARDDOG_NOWAYOUT @@ -80,6 +81,7 @@ static int harddog_open(struct inode *inode, struct file *file) if(err) return(err); timer_alive = 1; + unlock_kernel(); return 0; } diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c index 5ae1c44294f6..d5c950b4bb83 100644 --- a/arch/um/drivers/hostaudio_kern.c +++ b/arch/um/drivers/hostaudio_kern.c @@ -15,6 +15,7 @@ #include "init.h" #include "hostaudio.h" +/* Only changed from linux_main at boot time */ char *dsp = HOSTAUDIO_DEV_DSP; char *mixer = HOSTAUDIO_DEV_MIXER; diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 50e9adfa5e75..837c07f41669 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -99,19 +99,27 @@ int line_write(struct line *lines, struct tty_struct *tty, const char *buf, i = minor(tty->device) - tty->driver.minor_start; line = &lines[i]; + down(&line->sem); if(line->head != line->tail){ local_irq_save(flags); buffer_data(line, buf, len); err = flush_buffer(line); local_irq_restore(flags); - if(err <= 0) return(len); + if(err <= 0) + goto out; } else { n = write_chan(&line->chan_list, buf, len, line->driver->write_irq); - if(n < 0) return(n); - if(n < len) buffer_data(line, buf + n, len - n); + if(n < 0){ + len = n; + goto out; + } + if(n < len) + buffer_data(line, buf + n, len - n); } + out: + up(&line->sem); return(len); } @@ -249,6 +257,7 @@ void line_close(struct line *lines, struct tty_struct *tty) else n = minor(tty->device) - tty->driver.minor_start; line = &lines[n]; + down(&line->sem); line->count--; /* I don't like this, but I can't think of anything better. What's @@ -261,6 +270,7 @@ void line_close(struct line *lines, struct tty_struct *tty) line->tty = NULL; if(line->count == 0) line_disable(line, -1); + up(&line->sem); } void close_lines(struct line *lines, int nlines) @@ -343,8 +353,6 @@ void line_register_devfs(struct lines *set, struct line_driver *line_driver, driver->write_room = line_write_room; driver->init_termios = tty_std_termios; - driver->refcount = &set->refcount; - if (tty_register_driver(driver)) panic("line_register_devfs : Couldn't register driver\n"); @@ -408,16 +416,18 @@ void winch_interrupt(int irq, void *data, struct pt_regs *unused) reactivate_fd(winch->fd, WINCH_IRQ); } +DECLARE_MUTEX(winch_handler_sem); LIST_HEAD(winch_handlers); void register_winch_irq(int fd, int tty_fd, int pid, void *line) { struct winch *winch; + down(&winch_handler_sem); winch = kmalloc(sizeof(*winch), GFP_KERNEL); if(winch == NULL){ printk("register_winch_irq - kmalloc failed\n"); - return; + goto out; } *winch = ((struct winch) { list : LIST_HEAD_INIT(winch->list), fd : fd, @@ -429,6 +439,8 @@ void register_winch_irq(int fd, int tty_fd, int pid, void *line) SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, "winch", winch) < 0) printk("register_winch_irq - failed to register IRQ\n"); + out: + up(&winch_handler_sem); } static void winch_cleanup(void) @@ -439,7 +451,6 @@ static void winch_cleanup(void) list_for_each(ele, &winch_handlers){ winch = list_entry(ele, struct winch, list); close(winch->fd); - free_irq_by_fd(winch->fd); if(winch->pid != -1) os_kill_process(winch->pid); } } diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index a90786aff133..c2822cb872c2 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -40,6 +40,11 @@ static struct notifier_block reboot_notifier = { priority: 0, }; +/* Safe without explicit locking for now. Tasklets provide their own + * locking, and the interrupt handler is safe because it can't interrupt + * itself and it can only happen on CPU 0. + */ + LIST_HEAD(mc_requests); void mc_work_proc(void *unused) @@ -49,12 +54,12 @@ void mc_work_proc(void *unused) int done; do { - save_flags(flags); + local_save_flags(flags); req = list_entry(mc_requests.next, struct mconsole_entry, list); list_del(&req->list); done = list_empty(&mc_requests); - restore_flags(flags); + local_irq_restore(flags); req->request.cmd->handler(&req->request); kfree(req); } while(!done); @@ -152,6 +157,8 @@ void mconsole_stop(struct mc_request *req) mconsole_reply(req, "", 0, 0); } +/* This list is populated by __initcall routines. */ + LIST_HEAD(mconsole_devices); void mconsole_register_dev(struct mc_device *new) @@ -224,7 +231,10 @@ void mconsole_sysrq(struct mc_request *req) } #endif -static char *notify_socket = NULL; +/* Changed by mconsole_setup, which is __setup, and called before SMP is + * active. + */ +static char *notify_socket = NULL; int mconsole_init(void) { @@ -301,6 +311,18 @@ static int create_proc_mconsole(void) return(0); } +static spinlock_t notify_spinlock = SPIN_LOCK_UNLOCKED; + +void lock_notify(void) +{ + spin_lock(¬ify_spinlock); +} + +void unlock_notify(void) +{ + spin_unlock(¬ify_spinlock); +} + __initcall(create_proc_mconsole); #define NOTIFY "=notify:" diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index d60be6eead37..11b09a96f454 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c @@ -30,6 +30,7 @@ static struct mconsole_command commands[] = { { "go", mconsole_go, 1 }, }; +/* Initialized in mconsole_init, which is an initcall */ char mconsole_socket_name[256]; int mconsole_reply_v0(struct mc_request *req, char *reply) @@ -162,16 +163,21 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len) { struct sockaddr_un target; struct mconsole_notify packet; - int n, err; + int n, err = 0; + lock_notify(); if(notify_sock < 0){ notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0); if(notify_sock < 0){ printk("mconsole_notify - socket failed, errno = %d\n", errno); - return(-errno); + err = -errno; } } + unlock_notify(); + + if(err) + return(err); target.sun_family = AF_UNIX; strcpy(target.sun_path, sock_name); diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c index d03082be380d..dc2937a0ed2e 100644 --- a/arch/um/drivers/mmapper_kern.c +++ b/arch/um/drivers/mmapper_kern.c @@ -15,13 +15,14 @@ #include <linux/mm.h> #include <linux/slab.h> #include <linux/init.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h> #include <asm/irq.h> -#include <asm/smplock.h> #include <asm/pgtable.h> #include "mem_user.h" #include "user_util.h" +/* These are set in mmapper_init, which is called at boot time */ static unsigned long mmapper_size; static unsigned long p_buf = 0; static char *v_buf = NULL; diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index a83f84c367d4..deef1a0a75e3 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -27,6 +27,7 @@ #include "init.h" #include "irq_user.h" +static spinlock_t opened_lock = SPIN_LOCK_UNLOCKED; LIST_HEAD(opened); static int uml_net_rx(struct net_device *dev) @@ -118,7 +119,9 @@ static int uml_net_open(struct net_device *dev) lp->tl.data = (unsigned long) &lp->user; netif_start_queue(dev); + spin_lock(&opened_lock); list_add(&lp->list, &opened); + spin_unlock(&opened_lock); MOD_INC_USE_COUNT; out: spin_unlock(&lp->lock); @@ -135,8 +138,10 @@ static int uml_net_close(struct net_device *dev) free_irq(dev->irq, dev); if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); lp->fd = -1; + spin_lock(&opened_lock); list_del(&lp->list); - + spin_unlock(&opened_lock); + MOD_DEC_USE_COUNT; spin_unlock(&lp->lock); return 0; @@ -245,6 +250,7 @@ void uml_net_user_timer_expire(unsigned long _conn) #endif } +static spinlock_t devices_lock = SPIN_LOCK_UNLOCKED; static struct list_head devices = LIST_HEAD_INIT(devices); static int eth_configure(int n, void *init, char *mac, @@ -261,7 +267,10 @@ static int eth_configure(int n, void *init, char *mac, return(1); } + spin_lock(&devices_lock); list_add(&device->list, &devices); + spin_unlock(&devices_lock); + device->index = n; size = transport->private_size + sizeof(struct uml_net_private) + @@ -373,12 +382,16 @@ static struct uml_net *find_device(int n) struct uml_net *device; struct list_head *ele; + spin_lock(&devices_lock); list_for_each(ele, &devices){ device = list_entry(ele, struct uml_net, list); if(device->index == n) - return(device); + goto out; } - return(NULL); + device = NULL; + out: + spin_unlock(&devices_lock); + return(device); } static int eth_parse(char *str, int *index_out, char **str_out) @@ -418,8 +431,12 @@ struct eth_init { int index; }; +/* Filled in at boot time. Will need locking if the transports become + * modular. + */ struct list_head transports = LIST_HEAD_INIT(transports); +/* Filled in during early boot */ struct list_head eth_cmd_line = LIST_HEAD_INIT(eth_cmd_line); static int check_transport(struct transport *transport, char *eth, int n, @@ -519,8 +536,6 @@ __uml_help(eth_setup, " Configure a network device.\n\n" ); -int ndev = 0; - static int eth_init(void) { struct list_head *ele, *next; diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c index 0acb925a70f6..c9783f449d68 100644 --- a/arch/um/drivers/port_kern.c +++ b/arch/um/drivers/port_kern.c @@ -62,8 +62,6 @@ static void pipe_interrupt(int irq, void *data, struct pt_regs *regs) up(&conn->port->sem); } -struct list_head ports = LIST_HEAD_INIT(ports); - static void port_interrupt(int irq, void *data, struct pt_regs *regs) { struct port_list *port = data; @@ -107,6 +105,9 @@ static void port_interrupt(int irq, void *data, struct pt_regs *regs) reactivate_fd(port->fd, ACCEPT_IRQ); } +DECLARE_MUTEX(ports_sem); +struct list_head ports = LIST_HEAD_INIT(ports); + void *port_data(int port_num) { struct list_head *ele; @@ -114,6 +115,7 @@ void *port_data(int port_num) struct port_dev *dev; int fd; + down(&ports_sem); list_for_each(ele, &ports){ port = list_entry(ele, struct port_list, list); if(port->port == port_num) goto found; @@ -121,7 +123,7 @@ void *port_data(int port_num) port = kmalloc(sizeof(struct port_list), GFP_KERNEL); if(port == NULL){ printk(KERN_ERR "Allocation of port list failed\n"); - return(NULL); + goto out; } fd = port_listen_fd(port_num); @@ -151,18 +153,21 @@ void *port_data(int port_num) dev = kmalloc(sizeof(struct port_dev), GFP_KERNEL); if(dev == NULL){ printk(KERN_ERR "Allocation of port device entry failed\n"); - return(NULL); + goto out; } *dev = ((struct port_dev) { port : port, fd : -1, helper_pid : -1 }); + up(&ports_sem); return(dev); out_free: kfree(port); out_close: os_close_file(fd); + out: + up(&ports_sem); return(NULL); } @@ -184,7 +189,6 @@ static void free_port(void) list_for_each(ele, &ports){ port = list_entry(ele, struct port_list, list); - free_irq(ACCEPT_IRQ, port); os_close_file(port->fd); } } diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index 5d52974e3726..1558c30bb963 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c @@ -24,10 +24,13 @@ static int ssl_version = 1; -static struct tty_driver ssl_driver; - +/* Referenced only by tty_driver below - presumably it's locked correctly + * by the tty driver. + */ static int ssl_refcount = 0; +static struct tty_driver ssl_driver; + #define NR_PORTS 64 void ssl_announce(char *dev_name, int dev) @@ -58,7 +61,10 @@ static struct line_driver driver = { symlink_to : "tts", }; -static struct line serial_lines[NR_PORTS] = +/* The array is initialized by line_init, which is an initcall. The + * individual elements are protected by individual semaphores. + */ +static struct line serial_lines[NR_PORTS] = { [0 ... NR_PORTS - 1] = LINE_INIT(CONFIG_SSL_CHAN, &driver) }; static struct lines lines = LINES_INIT(NR_PORTS); @@ -153,6 +159,27 @@ void ssl_hangup(struct tty_struct *tty) { } +static struct tty_driver ssl_driver = { + refcount : &ssl_refcount, + open : ssl_open, + close : ssl_close, + write : ssl_write, + put_char : ssl_put_char, + flush_chars : ssl_flush_chars, + chars_in_buffer : ssl_chars_in_buffer, + flush_buffer : ssl_flush_buffer, + ioctl : ssl_ioctl, + throttle : ssl_throttle, + unthrottle : ssl_unthrottle, + set_termios : ssl_set_termios, + stop : ssl_stop, + start : ssl_start, + hangup : ssl_hangup +}; + +/* Changed by ssl_init and referenced by ssl_exit, which are both serialized + * by being an initcall and exitcall, respectively. + */ static int ssl_init_done = 0; int ssl_init(void) @@ -162,25 +189,6 @@ int ssl_init(void) printk(KERN_INFO "Initializing software serial port version %d\n", ssl_version); - ssl_driver = ((struct tty_driver) - { - refcount : &ssl_refcount, - open : ssl_open, - close : ssl_close, - write : ssl_write, - put_char : ssl_put_char, - flush_chars : ssl_flush_chars, - chars_in_buffer : ssl_chars_in_buffer, - flush_buffer : ssl_flush_buffer, - ioctl : ssl_ioctl, - throttle : ssl_throttle, - unthrottle : ssl_unthrottle, - set_termios : ssl_set_termios, - stop : ssl_stop, - start : ssl_start, - hangup : ssl_hangup - }); - line_register_devfs(&lines, &driver, &ssl_driver, serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0])); diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 3ef550107a93..6d54a6226b4a 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c @@ -32,8 +32,14 @@ #define MAX_TTYS (8) +/* Referenced only by tty_driver below - presumably it's locked correctly + * by the tty driver. + */ + static struct tty_driver console_driver; +static int console_refcount = 0; + static struct chan_ops init_console_ops = { init : NULL, open : NULL, @@ -88,6 +94,9 @@ static struct line_driver driver = { static struct lines console_lines = LINES_INIT(MAX_TTYS); +/* The array is initialized by line_init, which is an initcall. The + * individual elements are protected by individual semaphores. + */ struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver), [ 1 ... MAX_TTYS - 1 ] = LINE_INIT(CONFIG_CON_CHAN, &driver) }; @@ -130,15 +139,6 @@ int stdio_init(void) printk(KERN_INFO "Initializing stdio console driver\n"); - console_driver = ((struct tty_driver) - { - open : con_open, - close : con_close, - write : con_write, - chars_in_buffer : chars_in_buffer, - set_termios : set_termios - }); - line_register_devfs(&console_lines, &driver, &console_driver, vts, sizeof(vts)/sizeof(vts[0])); @@ -157,9 +157,20 @@ __initcall(stdio_init); static void console_write(struct console *console, const char *string, unsigned len) { + if(con_init_done) down(&vts[console->index].sem); console_write_chan(&vts[console->index].chan_list, string, len); + if(con_init_done) up(&vts[console->index].sem); } +static struct tty_driver console_driver = { + refcount : &console_refcount, + open : con_open, + close : con_close, + write : con_write, + chars_in_buffer : chars_in_buffer, + set_termios : set_termios +}; + static kdev_t console_device(struct console *c) { return mk_kdev(TTY_MAJOR, c->index); @@ -193,7 +204,6 @@ __channel_help(console_chan_setup, "con"); static void console_exit(void) { if(!con_init_done) return; - line_close(vts, NULL); close_lines(vts, sizeof(vts)/sizeof(vts[0])); } diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 36995c3f84f6..68c8e1ca81d1 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -25,6 +25,7 @@ #include "linux/vmalloc.h" #include "linux/blkpg.h" #include "linux/genhd.h" +#include "linux/spinlock.h" #include "asm/segment.h" #include "asm/uaccess.h" #include "asm/irq.h" @@ -41,7 +42,9 @@ #include "2_5compat.h" #include "os.h" -static spinlock_t ubd_lock; +static spinlock_t ubd_io_lock = SPIN_LOCK_UNLOCKED; +static spinlock_t ubd_lock = SPIN_LOCK_UNLOCKED; + static void (*do_ubd)(void); static int ubd_open(struct inode * inode, struct file * filp); @@ -62,9 +65,12 @@ static struct block_device_operations ubd_blops = { .revalidate = ubd_revalidate, }; +/* Protected by the queue_lock */ static request_queue_t *ubd_queue; +/* Protected by ubd_lock */ static int fake_major = 0; + static struct gendisk *ubd_gendisk[MAX_DEV]; static struct gendisk *fake_gendisk[MAX_DEV]; @@ -74,6 +80,9 @@ static struct gendisk *fake_gendisk[MAX_DEV]; #define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 0, .c = 0 }) #endif +/* Not protected - changed only in ubd_setup_common and then only to + * to enable O_SYNC. + */ static struct openflags global_openflags = OPEN_FLAGS; struct cow { @@ -130,12 +139,7 @@ static int ubd0_init(void) __initcall(ubd0_init); -static struct hd_driveid ubd_id = { - .cyls = 0, - .heads = 128, - .sectors = 32, -}; - +/* Only changed by fake_ide_setup which is a setup */ static int fake_ide = 0; static struct proc_dir_entry *proc_ide_root = NULL; static struct proc_dir_entry *proc_ide = NULL; @@ -161,7 +165,6 @@ static int proc_ide_read_media(char *page, char **start, off_t off, int count, else len = count; *start = page + off; return len; - } static void make_ide_entries(char *dev_name) @@ -170,7 +173,9 @@ static void make_ide_entries(char *dev_name) char name[64]; if(!fake_ide) return; + if(proc_ide_root == NULL) make_proc_ide(); + dir = proc_mkdir(dev_name, proc_ide); ent = create_proc_entry("media", S_IFREG|S_IRUGO, dir); if(!ent) return; @@ -199,7 +204,7 @@ static int ubd_setup_common(char *str, int *index_out) { struct openflags flags = global_openflags; char *backing_file; - int n; + int n, err; if(index_out) *index_out = -1; n = *str++; @@ -224,12 +229,22 @@ static int ubd_setup_common(char *str, int *index_out) return(1); } - fake_major = major; + err = 1; + spin_lock(&ubd_lock); + if(!fake_major_allowed){ + printk(KERN_ERR "Can't assign a fake major twice\n"); + goto out1; + } + + fake_major = major; fake_major_allowed = 0; printk(KERN_INFO "Setting extra ubd major number to %d\n", major); - return(0); + err = 0; + out1: + spin_unlock(&ubd_lock); + return(err); } if(n < '0'){ @@ -247,9 +262,12 @@ static int ubd_setup_common(char *str, int *index_out) return(1); } + err = 1; + spin_lock(&ubd_lock); + if(ubd_dev[n].file != NULL){ printk(KERN_ERR "ubd_setup : device already configured\n"); - return(1); + goto out2; } if(index_out) *index_out = n; @@ -264,8 +282,10 @@ static int ubd_setup_common(char *str, int *index_out) } if(*str++ != '='){ printk(KERN_ERR "ubd_setup : Expected '='\n"); - return(1); + goto out2; } + + err = 0; backing_file = strchr(str, ','); if(backing_file){ *backing_file = '\0'; @@ -276,7 +296,9 @@ static int ubd_setup_common(char *str, int *index_out) ubd_dev[n].is_dir = 1; ubd_dev[n].cow.file = backing_file; ubd_dev[n].boot_openflags = flags; - return(0); + out2: + spin_unlock(&ubd_lock); + return(err); } static int ubd_setup(char *str) @@ -317,8 +339,12 @@ __uml_help(fakehd, static void do_ubd_request(request_queue_t * q); +/* Only changed by ubd_init, which is an initcall. */ int thread_fd = -1; +/* Changed by ubd_handler, which is serialized because interrupts only + * happen on CPU 0. + */ int intr_count = 0; static void ubd_finish(int error) @@ -326,7 +352,9 @@ static void ubd_finish(int error) int nsect; if(error){ + spin_lock(&ubd_io_lock); end_request(CURRENT, 0); + spin_unlock(&ubd_io_lock); return; } nsect = CURRENT->current_nr_sectors; @@ -335,7 +363,9 @@ static void ubd_finish(int error) CURRENT->errors = 0; CURRENT->nr_sectors -= nsect; CURRENT->current_nr_sectors = 0; + spin_lock(&ubd_io_lock); end_request(CURRENT, 1); + spin_unlock(&ubd_io_lock); } static void ubd_handler(void) @@ -349,9 +379,9 @@ static void ubd_handler(void) if(n != sizeof(req)){ printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, " "errno = %d\n", os_getpid(), -n); - spin_lock(&ubd_lock); + spin_lock(&ubd_io_lock); end_request(CURRENT, 0); - spin_unlock(&ubd_lock); + spin_unlock(&ubd_io_lock); return; } @@ -359,11 +389,9 @@ static void ubd_handler(void) (req.length != (CURRENT->current_nr_sectors) << 9)) panic("I/O op mismatch"); - spin_lock(&ubd_lock); ubd_finish(req.error); reactivate_fd(thread_fd, UBD_IRQ); do_ubd_request(ubd_queue); - spin_unlock(&ubd_lock); } static void ubd_intr(int irq, void *dev, struct pt_regs *unused) @@ -371,6 +399,7 @@ static void ubd_intr(int irq, void *dev, struct pt_regs *unused) ubd_handler(); } +/* Only changed by ubd_init, which is an initcall. */ static int io_pid = -1; void kill_io_thread(void) @@ -380,8 +409,6 @@ void kill_io_thread(void) __uml_exitcall(kill_io_thread); -int sync = 0; - static int ubd_file_size(struct ubd *dev, __u64 *size_out) { char *file; @@ -390,6 +417,7 @@ static int ubd_file_size(struct ubd *dev, __u64 *size_out) return(os_file_size(file, size_out)); } +/* Initialized in an initcall, and unchanged thereafter */ devfs_handle_t ubd_dir_handle; devfs_handle_t ubd_fake_dir_handle; @@ -402,14 +430,13 @@ static int ubd_add(int n) u64 size; if (!dev->file) - return -1; + goto out; - disk = alloc_disk(); + disk = alloc_disk(1 << UBD_SHIFT); if (!disk) return -1; disk->major = MAJOR_NR; disk->first_minor = n << UBD_SHIFT; - disk->minor_shift = UBD_SHIFT; disk->fops = &ubd_blops; if (fakehd_set) sprintf(disk->disk_name, "hd%c", n + 'a'); @@ -417,14 +444,13 @@ static int ubd_add(int n) sprintf(disk->disk_name, "ubd%d", n); if (fake_major) { - fake_disk = alloc_disk(); + fake_disk = alloc_disk(1 << UBD_SHIFT); if (!fake_disk) { put_disk(disk); return -1; } fake_disk->major = fake_major; fake_disk->first_minor = n << UBD_SHIFT; - fake_disk->minor_shift = UBD_SHIFT; fake_disk->fops = &ubd_blops; sprintf(fake_disk->disk_name, "ubd%d", n); fake_gendisk[n] = fake_disk; @@ -443,23 +469,32 @@ static int ubd_add(int n) MAJOR_NR, n << UBD_SHIFT, S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP |S_IWGRP, &ubd_blops, NULL); - add_disk(disk); + if(real == NULL) + goto out; + ubd_dev[n].real = real; + if (fake_major) { fake = devfs_register(ubd_fake_dir_handle, name, DEVFS_FL_REMOVABLE, fake_major, n << UBD_SHIFT, S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, &ubd_blops, NULL); - add_disk(fake_disk); - if(fake == NULL) return(-1); + if(fake == NULL) + goto out_unregister; + ubd_dev[n].fake = fake; + add_disk(fake_disk); } - if(real == NULL) return(-1); - ubd_dev[n].real = real; - + add_disk(disk); make_ide_entries(disk->disk_name); return(0); + + out_unregister: + devfs_unregister(real); + ubd_dev[n].real = NULL; + out: + return(-1); } static int ubd_config(char *str) @@ -478,24 +513,29 @@ static int ubd_config(char *str) } if(n == -1) return(0); + spin_lock(&ubd_lock); err = ubd_add(n); - if(err){ + if(err) ubd_dev[n].file = NULL; - return(err); - } + spin_unlock(&ubd_lock); - return(0); + return(err); } static int ubd_remove(char *str) { struct ubd *dev; - int n; + int n, err; - if(!isdigit(*str)) return(-1); + if(!isdigit(*str)) + return(-1); n = *str - '0'; - if(n > MAX_DEV) return(-1); + if(n > MAX_DEV) + return(-1); dev = &ubd_dev[n]; + + err = 0; + spin_lock(&ubd_lock); del_gendisk(ubd_gendisk[n]); put_disk(ubd_gendisk[n]); ubd_gendisk[n] = NULL; @@ -504,12 +544,20 @@ static int ubd_remove(char *str) put_disk(fake_gendisk[n]); fake_gendisk[n] = NULL; } - if(dev->file == NULL) return(0); - if(dev->count > 0) return(-1); - if(dev->real != NULL) devfs_unregister(dev->real); - if(dev->fake != NULL) devfs_unregister(dev->fake); + if(dev->file == NULL) + goto out; + err = -1; + if(dev->count > 0) + goto out; + if(dev->real != NULL) + devfs_unregister(dev->real); + if(dev->fake != NULL) + devfs_unregister(dev->fake); *dev = ((struct ubd) DEFAULT_UBD); - return(0); + err = 0; + out: + spin_unlock(&ubd_lock); + return(err); } static struct mc_device ubd_mc = { @@ -541,7 +589,7 @@ int ubd_init(void) return -1; } ubd_queue = BLK_DEFAULT_QUEUE(MAJOR_NR); - INIT_QUEUE(ubd_queue, do_ubd_request, &ubd_lock); + blk_init_queue(ubd_queue, do_ubd_request, &ubd_io_lock); elevator_init(ubd_queue, &elevator_noop); if(fake_major != 0){ char name[sizeof("ubd_nnn\0")]; @@ -566,7 +614,7 @@ int ubd_driver_init(void){ unsigned long stack; int err; - if(sync){ + if(global_openflags.s){ printk(KERN_INFO "ubd : Synchronous mode\n"); return(0); } @@ -590,9 +638,9 @@ device_initcall(ubd_driver_init); static void ubd_close(struct ubd *dev) { - close_fd(dev->fd); + os_close_file(dev->fd); if(dev->cow.file != NULL) { - close_fd(dev->cow.fd); + os_close_file(dev->cow.fd); vfree(dev->cow.bitmap); dev->cow.bitmap = NULL; } @@ -644,22 +692,17 @@ static int ubd_open_dev(struct ubd *dev) } return(0); error: - close_fd(dev->fd); + os_close_file(dev->fd); return(err); } static int ubd_open(struct inode *inode, struct file *filp) { - struct ubd *dev; - int n, offset, err; - - n = DEVICE_NR(inode->i_rdev); - dev = &ubd_dev[n]; - if(n > MAX_DEV) - return -ENODEV; - offset = n << UBD_SHIFT; + int n = DEVICE_NR(inode->i_rdev); + struct ubd *dev = &ubd_dev[n]; + int err; if(dev->is_dir == 1) - return(0); + goto out; if(dev->count == 0){ dev->openflags = dev->boot_openflags; @@ -668,36 +711,26 @@ static int ubd_open(struct inode *inode, struct file *filp) if(err){ printk(KERN_ERR "ubd%d: Can't open \"%s\": " "errno = %d\n", n, dev->file, -err); - return(err); + goto out; } - if(err) return(err); } dev->count++; if((filp->f_mode & FMODE_WRITE) && !dev->openflags.w){ if(--dev->count == 0) ubd_close(dev); - return -EROFS; + err = -EROFS; } - return(0); + out: + return(err); } static int ubd_release(struct inode * inode, struct file * file) { - int n, offset; - - n = DEVICE_NR(inode->i_rdev); - offset = n << UBD_SHIFT; - if(n > MAX_DEV) - return -ENODEV; - + int n = DEVICE_NR(inode->i_rdev); if(--ubd_dev[n].count == 0) ubd_close(&ubd_dev[n]); - return(0); } -int cow_read = 0; -int cow_write = 0; - void cowify_req(struct io_thread_req *req, struct ubd *dev) { int i, update_bitmap, sector = req->offset >> 9; @@ -710,14 +743,12 @@ void cowify_req(struct io_thread_req *req, struct ubd *dev) dev->cow.bitmap)){ ubd_set_bit(i, (unsigned char *) &req->sector_mask); - cow_read++; } } } else { update_bitmap = 0; for(i = 0; i < req->length >> 9; i++){ - cow_write++; ubd_set_bit(i, (unsigned char *) &req->sector_mask); if(!ubd_test_bit(sector + i, (unsigned char *) @@ -752,13 +783,17 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req) if(dev->is_dir){ strcpy(req->buffer, "HOSTFS:"); strcat(req->buffer, dev->file); + spin_lock(&ubd_io_lock); end_request(req, 1); + spin_unlock(&ubd_io_lock); return(1); } if((rq_data_dir(req) == WRITE) && !dev->openflags.w){ printk("Write attempted on readonly ubd device %d\n", n); + spin_lock(&ubd_io_lock); end_request(req, 0); + spin_unlock(&ubd_io_lock); return(1); } @@ -819,6 +854,12 @@ static int ubd_ioctl(struct inode * inode, struct file * file, struct hd_geometry *loc = (struct hd_geometry *) arg; struct ubd *dev; int n, min, err; + struct hd_driveid ubd_id = { + .cyls = 0, + .heads = 128, + .sectors = 32, + }; + if(!inode) return(-EINVAL); min = minor(inode->i_rdev); @@ -892,8 +933,11 @@ static int ubd_revalidate(kdev_t rdev) n = minor(rdev) >> UBD_SHIFT; dev = &ubd_dev[n]; + + err = 0; + spin_lock(&ubd_lock); if(dev->is_dir) - return(0); + goto out; err = ubd_file_size(dev, &size); if (!err) { @@ -902,7 +946,8 @@ static int ubd_revalidate(kdev_t rdev) set_capacity(fake_gendisk[n], size / 512); dev->size = size; } - + out: + spin_unlock(&ubd_lock); return err; } diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c index 59eb46ff73a2..8a4b6f52888c 100644 --- a/arch/um/drivers/ubd_user.c +++ b/arch/um/drivers/ubd_user.c @@ -533,8 +533,12 @@ void do_io(struct io_thread_req *req) return; } +/* Changed in start_io_thread, which is serialized by being called only + * from ubd_init, which is an initcall. + */ int kernel_fd = -1; +/* Only changed by the io thread */ int io_count = 0; int io_thread(void *arg) diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index 9f4a6296fe66..d3f69887f3c2 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c @@ -44,6 +44,7 @@ void *xterm_init(char *str, int device, struct chan_opts *opts) return(data); } +/* Only changed by xterm_setup, which is a setup */ static char *terminal_emulator = "xterm"; static char *title_switch = "-T"; static char *exec_switch = "-e"; diff --git a/arch/um/include/2_5compat.h b/arch/um/include/2_5compat.h index 3802d4fafb48..6d36d9c30b91 100644 --- a/arch/um/include/2_5compat.h +++ b/arch/um/include/2_5compat.h @@ -20,8 +20,6 @@ next : NULL \ } -#define INIT_QUEUE(queue, request, lock) blk_init_queue(queue, request, lock) - #define INIT_HARDSECT(arr, maj, sizes) #define SET_PRI(task) do ; while(0) diff --git a/arch/um/include/irq_user.h b/arch/um/include/irq_user.h index 4852f2c3613e..52bed5175229 100644 --- a/arch/um/include/irq_user.h +++ b/arch/um/include/irq_user.h @@ -18,7 +18,9 @@ extern void forward_interrupts(int pid); extern void init_irq_signals(int on_sigstack); extern void forward_ipi(int fd, int pid); extern void free_irq_later(int irq, void *dev_id); - +extern int activate_ipi(int fd, int pid); +extern unsigned long irq_lock(void); +extern void irq_unlock(unsigned long flags); #endif /* diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h index 07511e1e7e6e..34e107d545da 100644 --- a/arch/um/include/kern_util.h +++ b/arch/um/include/kern_util.h @@ -50,12 +50,8 @@ extern int pid_to_processor_id(int pid); extern void block_signals(void); extern void unblock_signals(void); extern void deliver_signals(void *t); -extern void lock_syscall(void); -extern void unlock_syscall(void); -extern void lock_trap(void); -extern void unlock_trap(void); -extern void lock_pid(void); -extern void unlock_pid(void); +extern int next_syscall_index(int max); +extern int next_trap_index(int max); extern void default_idle(void); extern void finish_fork(void); extern void paging_init(void); @@ -121,7 +117,7 @@ extern void arch_switch(void); extern int is_valid_pid(int pid); extern void free_irq(unsigned int, void *); extern int um_in_interrupt(void); - +extern int cpu(void); #endif /* diff --git a/arch/um/include/line.h b/arch/um/include/line.h index 593355064fe7..4d45c270a80e 100644 --- a/arch/um/include/line.h +++ b/arch/um/include/line.h @@ -61,12 +61,9 @@ struct line { struct lines { int num; - int refcount; }; -#define LINES_INIT(n) \ - { num : n, \ - refcount : 0 } +#define LINES_INIT(n) { num : n } extern void line_interrupt(int irq, void *data, struct pt_regs *unused); extern void line_write_interrupt(int irq, void *data, struct pt_regs *unused); diff --git a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h index 192aab5b8e79..8f82ef7201ea 100644 --- a/arch/um/include/mconsole.h +++ b/arch/um/include/mconsole.h @@ -77,6 +77,8 @@ extern int mconsole_get_request(int fd, struct mc_request *req); extern int mconsole_notify(char *sock_name, int type, const void *data, int len); extern char *mconsole_notify_socket(void); +extern void lock_notify(void); +extern void unlock_notify(void); #endif diff --git a/arch/um/include/sigio.h b/arch/um/include/sigio.h index 23aef0140b7b..37d76e29a147 100644 --- a/arch/um/include/sigio.h +++ b/arch/um/include/sigio.h @@ -11,6 +11,8 @@ extern int register_sigio_fd(int fd); extern int read_sigio_fd(int fd); extern int add_sigio_fd(int fd, int read); extern int ignore_sigio_fd(int fd); +extern void sigio_lock(void); +extern void sigio_unlock(void); #endif diff --git a/arch/um/include/tempfile.h b/arch/um/include/tempfile.h new file mode 100644 index 000000000000..e36d9e0f5105 --- /dev/null +++ b/arch/um/include/tempfile.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __TEMPFILE_H__ +#define __TEMPFILE_H__ + +extern int make_tempfile(const char *template, char **tempname, int do_unlink); + +#endif +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/include/time_user.h b/arch/um/include/time_user.h index d68caf278f05..d49a34f0bee8 100644 --- a/arch/um/include/time_user.h +++ b/arch/um/include/time_user.h @@ -7,11 +7,11 @@ #define __TIME_USER_H__ extern void timer(void); -extern void get_profile_timer(void); -extern void disable_profile_timer(void); extern void switch_timers(int to_real); extern void user_time_init(void); -extern void set_timers(int set_signal); extern void idle_sleep(int secs); +extern void enable_timer(void); +extern void time_lock(void); +extern void time_unlock(void); #endif diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h index c95f3c45620c..5f50aed753b2 100644 --- a/arch/um/include/user_util.h +++ b/arch/um/include/user_util.h @@ -48,32 +48,21 @@ extern unsigned long brk_start; extern int pty_output_sigio; extern int pty_close_sigio; -extern void *open_maps(void); -extern void close_maps(void *fd); -extern unsigned long get_brk(void); extern void stop(void); -extern int proc_start_thread(unsigned long ip, unsigned long sp); extern void stack_protections(unsigned long address); extern void task_protections(unsigned long address); -extern void abandon_proc_space(int (*proc)(void *), unsigned long sp); extern int signals(int (*init_proc)(void *), void *sp); -extern int __personality(int); extern int wait_for_stop(int pid, int sig, int cont_type, void *relay); extern void *add_signal_handler(int sig, void (*handler)(int)); -extern void signal_init(void); extern int start_fork_tramp(void *arg, unsigned long temp_stack, int clone_flags, int (*tramp)(void *)); extern void trace_myself(void); extern int clone_and_wait(int (*fn)(void *), void *arg, void *sp, int flags); -extern int input_loop(void); -extern void continue_execing_proc(int pid); extern int linux_main(int argc, char **argv); extern void remap_data(void *segment_start, void *segment_end, int w); extern void set_cmdline(char *cmd); extern void input_cb(void (*proc)(void *), void *arg, int arg_len); -extern void setup_input(void); extern int get_pty(void); -extern void save_signal_state(int *sig_ptr); extern void *um_kmalloc(int size); extern int raw(int fd, int complain); extern int switcheroo(int fd, int prot, void *from, void *to, int size); @@ -82,15 +71,11 @@ extern void setup_hostinfo(void); extern void add_arg(char *cmd_line, char *arg); extern void init_new_thread(void *sig_stack, void (*usr1_handler)(int)); extern void attach_process(int pid); -extern void calc_sigframe_size(void); extern int fork_tramp(void *sig_stack); extern void do_exec(int old_pid, int new_pid); extern void tracer_panic(char *msg, ...); -extern void close_fd(int); -extern int make_tempfile(const char *template, char **tempname, int do_unlink); extern char *get_umid(int only_if_set); extern void do_longjmp(void *p); -extern void term_handler(int sig); extern void suspend_new_thread(int fd); extern int detach(int pid, int sig); extern int attach(int pid); @@ -99,12 +84,9 @@ extern int cont(int pid); extern void check_ptrace(void); extern void check_sigio(void); extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr); -extern int user_read(int fd, char *buf, int len); -extern int user_write(int fd, char *buf, int len); extern void write_sigio_workaround(void); extern void arch_check_bugs(void); extern int arch_handle_signal(int sig, struct uml_pt_regs *regs); -extern unsigned long pid_pc(int pid); extern int arch_fixup(unsigned long address, void *sc_ptr); extern void forward_pending_sigio(int target); diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index 76d39acd2837..0fb628ac28ba 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -3,9 +3,9 @@ EXTRA_TARGETS := unmap_fin.o obj-y = config.o exec_kern.o exec_user.o exitcode.o frame_kern.o frame.o \ helper.o init_task.o irq.o irq_user.o ksyms.o mem.o mem_user.o \ - process.o process_kern.o ptrace.o reboot.o resource.o setup.o \ - sigio_user.o sigio_kern.o signal_kern.o signal_user.o smp.o \ - syscall_kern.o syscall_user.o sysrq.o sys_call_table.o time.o \ + process.o process_kern.o ptrace.o reboot.o resource.o sigio_user.o \ + sigio_kern.o signal_kern.o signal_user.o smp.o syscall_kern.o \ + syscall_user.o sysrq.o sys_call_table.o tempfile.o time.o \ time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o \ umid.o user_util.o @@ -14,8 +14,8 @@ obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o # user_syms.o not included here because Rules.make has its own ideas about # building anything in export-objs -USER_OBJS := $(filter %_user.o,$(obj-y)) config.o frame.o helper.o process.o \ - time.o tty_log.o umid.o user_util.o user_syms.o +USER_OBJS := $(filter %_user.o,$(obj-y)) config.o helper.o process.o \ + tempfile.o time.o tty_log.o umid.o user_util.o user_syms.o USER_OBJS := $(foreach file,$(USER_OBJS),arch/um/kernel/$(file)) export-objs := ksyms.o process_kern.o signal_kern.o gprof_syms.o gmon_syms.o @@ -51,6 +51,9 @@ arch/um/kernel/unmap.o: arch/um/kernel/unmap.c arch/um/kernel/unmap_fin.o : arch/um/kernel/unmap.o ld -r -o $@ $< -lc -L/usr/lib +arch/um/kernel/frame.o: arch/um/kernel/frame.c + $(CC) $(CFLAGS_$(notdir $@)) -c -o $@ $< + QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; while(<STDIN>) { $$_ =~ s/CONFIG/$$config/; print $$_ }' arch/um/kernel/config.c : arch/um/kernel/config.c.in $(TOPDIR)/.config diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c index 34a2e527a3f8..353bfa4da610 100644 --- a/arch/um/kernel/exec_kern.c +++ b/arch/um/kernel/exec_kern.c @@ -17,6 +17,7 @@ #include "tlb.h" #include "2_5compat.h" #include "os.h" +#include "time_user.h" /* See comment above fork_tramp for why sigstop is defined and used like * this @@ -28,7 +29,6 @@ static int exec_tramp(void *sig_stack) { int sig = sigstop; - block_signals(); init_new_thread(sig_stack, NULL); kill(os_getpid(), sig); return(0); @@ -62,6 +62,7 @@ void flush_thread(void) unprotect_stack((unsigned long) current->thread_info); os_usr1_process(os_getpid()); + enable_timer(); free_page(stack); protect(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); task_protections((unsigned long) current->thread_info); diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c index 6c5c30e9c380..788f914d8510 100644 --- a/arch/um/kernel/exitcode.c +++ b/arch/um/kernel/exitcode.c @@ -8,6 +8,9 @@ #include "linux/proc_fs.h" #include "asm/uaccess.h" +/* If read and write race, the read will still atomically read a valid + * value. + */ int uml_exitcode = 0; static int read_proc_exitcode(char *page, char **start, off_t off, diff --git a/arch/um/kernel/frame.c b/arch/um/kernel/frame.c index a5d77c0ee15d..28793041426a 100644 --- a/arch/um/kernel/frame.c +++ b/arch/um/kernel/frame.c @@ -130,6 +130,7 @@ static void child_common(void *sp, int size, sighandler_t handler, int flags) os_stop_process(os_getpid()); } +/* Changed only during early boot */ struct sc_frame signal_frame_sc; struct sc_frame_raw { @@ -142,6 +143,7 @@ struct sc_frame_raw { struct arch_frame_data_raw arch; }; +/* Changed only during early boot */ static struct sc_frame_raw *raw_sc = NULL; static void sc_handler(int sig, struct sigcontext sc) @@ -163,6 +165,7 @@ static int sc_child(void *arg) return(-1); } +/* Changed only during early boot */ struct si_frame signal_frame_si; struct si_frame_raw { @@ -175,6 +178,7 @@ struct si_frame_raw { unsigned long sp; }; +/* Changed only during early boot */ static struct si_frame_raw *raw_si = NULL; static void si_handler(int sig, siginfo_t *si) diff --git a/arch/um/kernel/helper.c b/arch/um/kernel/helper.c index 324e08974d33..5d8fb7bba2b1 100644 --- a/arch/um/kernel/helper.c +++ b/arch/um/kernel/helper.c @@ -22,6 +22,7 @@ struct helper_data { int fd; }; +/* Debugging aid, changed only from gdb */ int helper_pause = 0; static void helper_hup(int sig) diff --git a/arch/um/kernel/initrd_kern.c b/arch/um/kernel/initrd_kern.c index dc6cff88b7a6..a8f7e70f1a17 100644 --- a/arch/um/kernel/initrd_kern.c +++ b/arch/um/kernel/initrd_kern.c @@ -13,6 +13,7 @@ #include "init.h" #include "os.h" +/* Changed by uml_initrd_setup, which is a setup */ static char *initrd __initdata = NULL; static int __init read_initrd(void) diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index 865ecec8d905..56454f28f03b 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c @@ -78,6 +78,7 @@ struct hw_interrupt_type no_irq_type = { end_none }; +/* Not changed */ volatile unsigned long irq_err_count; /* @@ -87,6 +88,7 @@ volatile unsigned long irq_err_count; int get_irq_list(char *buf) { int i, j; + unsigned long flags; struct irqaction * action; char *p = buf; @@ -96,9 +98,10 @@ int get_irq_list(char *buf) *p++ = '\n'; for (i = 0 ; i < NR_IRQS ; i++) { + spin_lock_irqsave(&irq_desc[i].lock, flags); action = irq_desc[i].action; if (!action) - continue; + goto end; p += sprintf(p, "%3d: ",i); #ifndef CONFIG_SMP p += sprintf(p, "%10u ", kstat_irqs(i)); @@ -113,6 +116,8 @@ int get_irq_list(char *buf) for (action=action->next; action; action = action->next) p += sprintf(p, ", %s", action->name); *p++ = '\n'; + end: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } p += sprintf(p, "\n"); #ifdef notdef @@ -548,11 +553,15 @@ void free_irq(unsigned int irq, void *dev_id) } } +/* These are initialized by sysctl_init, which is called from init/main.c */ static struct proc_dir_entry * root_irq_dir; static struct proc_dir_entry * irq_dir [NR_IRQS]; static struct proc_dir_entry * smp_affinity_entry [NR_IRQS]; -unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL }; +/* These are read and written as longs, so a read won't see a partial write + * even during a race. + */ +static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL }; #define HEX_DIGITS 8 @@ -679,6 +688,7 @@ static void register_irq_proc (unsigned int irq) smp_affinity_entry[irq] = entry; } +/* Read and written as a long */ unsigned long prof_cpu_mask = -1; void __init init_irq_proc (void) @@ -704,6 +714,21 @@ void __init init_irq_proc (void) register_irq_proc(i); } +static spinlock_t irq_spinlock = SPIN_LOCK_UNLOCKED; + +unsigned long irq_lock(void) +{ + unsigned long flags; + + spin_lock_irqsave(&irq_spinlock, flags); + return(flags); +} + +void irq_unlock(unsigned long flags) +{ + spin_unlock_irqrestore(&irq_spinlock, flags); +} + unsigned long probe_irq_on(void) { return(0); diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c index 32099fc7603b..ef56eef4f6c1 100644 --- a/arch/um/kernel/irq_user.c +++ b/arch/um/kernel/irq_user.c @@ -111,40 +111,20 @@ static void maybe_sigio_broken(int fd, int type) int activate_fd(int irq, int fd, int type, void *dev_id) { - struct irq_fd *new_fd; - int pid, retval, events, err; + struct pollfd *tmp_pfd; + struct irq_fd *new_fd, *irq_fd; + unsigned long flags; + int pid, events, err, n, size; + + pid = os_getpid(); + err = os_set_fd_async(fd, pid); + if(err < 0) + goto out; - for(new_fd = active_fds;new_fd;new_fd = new_fd->next){ - if((new_fd->fd == fd) && (new_fd->type == type)){ - printk("Registering fd %d twice\n", fd); - printk("Irqs : %d, %d\n", new_fd->irq, irq); - printk("Ids : 0x%x, 0x%x\n", new_fd->id, dev_id); - return(-EIO); - } - } - pid = cpu_tasks[0].pid; - if((retval = os_set_fd_async(fd, pid)) != 0) - return(retval); new_fd = um_kmalloc(sizeof(*new_fd)); err = -ENOMEM; - if(new_fd == NULL) return(err); - pollfds_num++; - if(pollfds_num > pollfds_size){ - struct pollfd *tmp_pfd; - - tmp_pfd = um_kmalloc(pollfds_num * sizeof(pollfds[0])); - if(tmp_pfd == NULL){ - pollfds_num--; - goto out_irq; - } - if(pollfds != NULL){ - memcpy(tmp_pfd, pollfds, - sizeof(pollfds[0]) * pollfds_size); - kfree(pollfds); - } - pollfds = tmp_pfd; - pollfds_size = pollfds_num; - } + if(new_fd == NULL) + goto out; if(type == IRQ_READ) events = POLLIN | POLLPRI; else events = POLLOUT; @@ -158,29 +138,90 @@ int activate_fd(int irq, int fd, int type, void *dev_id) current_events: 0, freed : 0 } ); - *last_irq_ptr = new_fd; - last_irq_ptr = &new_fd->next; + /* Critical section - locked by a spinlock because this stuff can + * be changed from interrupt handlers. The stuff above is done + * outside the lock because it allocates memory. + */ + + /* Actually, it only looks like it can be called from interrupt + * context. The culprit is reactivate_fd, which calls + * maybe_sigio_broken, which calls write_sigio_workaround, + * which calls activate_fd. However, write_sigio_workaround should + * only be called once, at boot time. That would make it clear that + * this is called only from process context, and can be locked with + * a semaphore. + */ + flags = irq_lock(); + for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){ + if((irq_fd->fd == fd) && (irq_fd->type == type)){ + printk("Registering fd %d twice\n", fd); + printk("Irqs : %d, %d\n", irq_fd->irq, irq); + printk("Ids : 0x%x, 0x%x\n", irq_fd->id, dev_id); + goto out_unlock; + } + } + + n = pollfds_num; + if(n == pollfds_size){ + while(1){ + /* Here we have to drop the lock in order to call + * kmalloc, which might sleep. If something else + * came in and changed the pollfds array, we free + * the buffer and try again. + */ + irq_unlock(flags); + size = (pollfds_num + 1) * sizeof(pollfds[0]); + tmp_pfd = um_kmalloc(size); + flags = irq_lock(); + if(tmp_pfd == NULL) + goto out_unlock; + if(n == pollfds_size) + break; + kfree(tmp_pfd); + } + if(pollfds != NULL){ + memcpy(tmp_pfd, pollfds, + sizeof(pollfds[0]) * pollfds_size); + kfree(pollfds); + } + pollfds = tmp_pfd; + pollfds_size++; + } if(type == IRQ_WRITE) events = 0; - pollfds[pollfds_num - 1] = ((struct pollfd) { fd : fd, - events : events, - revents : 0 }); + pollfds[pollfds_num] = ((struct pollfd) { fd : fd, + events : events, + revents : 0 }); + pollfds_num++; + *last_irq_ptr = new_fd; + last_irq_ptr = &new_fd->next; + + irq_unlock(flags); + + /* This calls activate_fd, so it has to be outside the critical + * section. + */ maybe_sigio_broken(fd, type); return(0); - out_irq: + out_unlock: + irq_unlock(flags); + out_free: kfree(new_fd); + out: return(err); } static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg) { struct irq_fd **prev; + unsigned long flags; int i = 0; + flags = irq_lock(); prev = &active_fds; while(*prev != NULL){ if((*test)(*prev, arg)){ @@ -190,7 +231,7 @@ static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg) printk("free_irq_by_cb - mismatch between " "active_fds and pollfds, fd %d vs %d\n", (*prev)->fd, pollfds[i].fd); - return; + goto out; } memcpy(&pollfds[i], &pollfds[i + 1], (pollfds_num - i - 1) * sizeof(pollfds[0])); @@ -206,6 +247,8 @@ static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg) prev = &(*prev)->next; i++; } + out: + irq_unlock(flags); } struct irq_and_dev { @@ -242,29 +285,33 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out) { struct irq_fd *irq; int i = 0; - + for(irq=active_fds; irq != NULL; irq = irq->next){ if((irq->fd == fd) && (irq->irq == irqnum)) break; i++; } if(irq == NULL){ printk("find_irq_by_fd doesn't have descriptor %d\n", fd); - return(NULL); + goto out; } if((pollfds[i].fd != -1) && (pollfds[i].fd != fd)){ printk("find_irq_by_fd - mismatch between active_fds and " "pollfds, fd %d vs %d, need %d\n", irq->fd, pollfds[i].fd, fd); - return(NULL); + irq = NULL; + goto out; } *index_out = i; + out: return(irq); } void free_irq_later(int irq, void *dev_id) { struct irq_fd *irq_fd; + unsigned long flags; + flags = irq_lock(); for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){ if((irq_fd->irq == irq) && (irq_fd->id == dev_id)) break; @@ -272,30 +319,48 @@ void free_irq_later(int irq, void *dev_id) if(irq_fd == NULL){ printk("free_irq_later found no irq, irq = %d, " "dev_id = 0x%p\n", irq, dev_id); - return; + goto out; } irq_fd->freed = 1; + out: + irq_unlock(flags); } void reactivate_fd(int fd, int irqnum) { struct irq_fd *irq; + unsigned long flags; int i; + flags = irq_lock(); irq = find_irq_by_fd(fd, irqnum, &i); - if(irq == NULL) return; + if(irq == NULL){ + irq_unlock(flags); + return; + } pollfds[i].fd = irq->fd; + + irq_unlock(flags); + + /* This calls activate_fd, so it has to be outside the critical + * section. + */ maybe_sigio_broken(fd, irq->type); } void deactivate_fd(int fd, int irqnum) { struct irq_fd *irq; + unsigned long flags; int i; + flags = irq_lock(); irq = find_irq_by_fd(fd, irqnum, &i); - if(irq == NULL) return; + if(irq == NULL) + goto out; pollfds[i].fd = -1; + out: + irq_unlock(flags); } void forward_ipi(int fd, int pid) @@ -313,7 +378,9 @@ void forward_ipi(int fd, int pid) void forward_interrupts(int pid) { struct irq_fd *irq; + unsigned long flags; + flags = irq_lock(); for(irq=active_fds;irq != NULL;irq = irq->next){ if(fcntl(irq->fd, F_SETOWN, pid) < 0){ int save_errno = errno; @@ -328,6 +395,7 @@ void forward_interrupts(int pid) } irq->pid = pid; } + irq_unlock(flags); } void init_irq_signals(int on_sigstack) @@ -339,10 +407,10 @@ void init_irq_signals(int on_sigstack) if(timer_irq_inited) h = (__sighandler_t) alarm_handler; else h = boot_timer_handler; - set_handler(SIGVTALRM, h, flags | SA_NODEFER | SA_RESTART, - SIGUSR1, SIGIO, SIGWINCH, -1); + set_handler(SIGVTALRM, h, flags | SA_RESTART, + SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1); set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART, - SIGUSR1, SIGIO, SIGWINCH, -1); + SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); signal(SIGWINCH, SIG_IGN); } diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c index dd6d9491bbed..a5cbc3bb257e 100644 --- a/arch/um/kernel/ksyms.c +++ b/arch/um/kernel/ksyms.c @@ -20,6 +20,7 @@ EXPORT_SYMBOL(__const_udelay); EXPORT_SYMBOL(sys_waitpid); EXPORT_SYMBOL(task_size); EXPORT_SYMBOL(__do_copy_from_user); +EXPORT_SYMBOL(__do_copy_to_user); EXPORT_SYMBOL(__do_strncpy_from_user); EXPORT_SYMBOL(__do_strnlen_user); EXPORT_SYMBOL(flush_tlb_range); diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index da7f4b318255..5a582a8de7d1 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -26,33 +26,32 @@ #include "kern.h" #include "init.h" +/* Changed during early boot */ +pgd_t swapper_pg_dir[1024]; unsigned long high_physmem; -unsigned long low_physmem; - unsigned long vm_start; unsigned long vm_end; - unsigned long highmem; - -pgd_t swapper_pg_dir[1024]; - unsigned long *empty_zero_page = NULL; - unsigned long *empty_bad_page = NULL; +/* Not modified */ const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n"; extern char __init_begin, __init_end; extern long physmem_size; +/* Not changed by UML */ mmu_gather_t mmu_gathers[NR_CPUS]; +/* Changed during early boot */ int kmalloc_ok = 0; #define NREGIONS (phys_region_index(0xffffffff) - phys_region_index(0x0) + 1) struct mem_region *regions[NREGIONS] = { [ 0 ... NREGIONS - 1 ] = NULL }; #define REGION_SIZE ((0xffffffff & ~REGION_MASK) + 1) +/* Changed during early boot */ static unsigned long brk_end; static void map_cb(void *unused) @@ -108,6 +107,7 @@ void mem_init(void) } #if CONFIG_HIGHMEM +/* Changed during early boot */ pte_t *kmap_pte; pgprot_t kmap_prot; @@ -187,18 +187,22 @@ int init_maps(struct mem_region *region) return(0); } +DECLARE_MUTEX(regions_sem); + static int setup_one_range(int fd, char *driver, unsigned long start, unsigned long pfn, int len, struct mem_region *region) { int i; + down(®ions_sem); for(i = 0; i < NREGIONS; i++){ if(regions[i] == NULL) break; } if(i == NREGIONS){ printk("setup_range : no free regions\n"); - return(-1); + i = -1; + goto out; } if(fd == -1) @@ -216,6 +220,8 @@ static int setup_one_range(int fd, char *driver, unsigned long start, len : len, fd : fd } ); regions[i] = region; + out: + up(®ions_sem); return(i); } @@ -373,7 +379,8 @@ void show_mem(void) printk("%d pages swap cached\n", cached); } -unsigned long kmem_top = 0; +/* Changed during early boot */ +static unsigned long kmem_top = 0; unsigned long get_kmem_end(void) { @@ -428,8 +435,10 @@ struct page *arch_validate(struct page *page, int mask, int order) goto again; } +DECLARE_MUTEX(vm_reserved_sem); static struct list_head vm_reserved = LIST_HEAD_INIT(vm_reserved); +/* Static structures, linked in to the list in early boot */ static struct vm_reserved head = { list : LIST_HEAD_INIT(head.list), start : 0, @@ -455,7 +464,9 @@ int reserve_vm(unsigned long start, unsigned long end, void *e) { struct vm_reserved *entry = e, *reserved, *prev; struct list_head *ele; + int err; + down(&vm_reserved_sem); list_for_each(ele, &vm_reserved){ reserved = list_entry(ele, struct vm_reserved, list); if(reserved->start >= end) goto found; @@ -469,13 +480,17 @@ int reserve_vm(unsigned long start, unsigned long end, void *e) entry = kmalloc(sizeof(*entry), GFP_KERNEL); if(entry == NULL){ printk("reserve_vm : Failed to allocate entry\n"); - return(-ENOMEM); + err = -ENOMEM; + goto out; } *entry = ((struct vm_reserved) { list : LIST_HEAD_INIT(entry->list), start : start, end : end }); list_add(&entry->list, &prev->list); + err = 0; + out: + up(&vm_reserved_sem); return(0); } @@ -486,6 +501,7 @@ unsigned long get_vm(unsigned long len) unsigned long start; int err; + down(&vm_reserved_sem); list_for_each(ele, &vm_reserved){ this = list_entry(ele, struct vm_reserved, list); next = list_entry(ele->next, struct vm_reserved, list); @@ -493,8 +509,10 @@ unsigned long get_vm(unsigned long len) (this->end + len + PAGE_SIZE <= next->start)) goto found; } + up(&vm_reserved_sem); return(0); found: + up(&vm_reserved_sem); start = (unsigned long) ROUND_UP(this->end) + PAGE_SIZE; err = reserve_vm(start, start + len, NULL); if(err) return(0); @@ -533,7 +551,11 @@ struct iomem { unsigned long size; }; -struct iomem iomem_regions[NREGIONS] = { [ 0 ... NREGIONS - 1 ] = +/* iomem regions can only be added on the command line at the moment. + * Locking will be needed when they can be added via mconsole. + */ + +struct iomem iomem_regions[NREGIONS] = { [ 0 ... NREGIONS - 1 ] = { name : NULL, fd : -1, size : 0 } }; @@ -569,6 +591,7 @@ __initcall(setup_iomem); #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) +/* Changed during early boot */ static struct mem_region physmem_region; static struct vm_reserved physmem_reserved; diff --git a/arch/um/kernel/mem_user.c b/arch/um/kernel/mem_user.c index 8e036687f717..af857510d17a 100644 --- a/arch/um/kernel/mem_user.c +++ b/arch/um/kernel/mem_user.c @@ -46,10 +46,9 @@ #include "mem_user.h" #include "init.h" #include "os.h" +#include "tempfile.h" -struct mem_region physmem_region; - -struct mem_region *mem_list = &physmem_region; +extern struct mem_region physmem_region; #define TEMPNAME_TEMPLATE "vm_file-XXXXXX" diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index c3731bfd4547..d410aaa7332b 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -48,23 +48,23 @@ void init_new_thread(void *sig_stack, void (*usr1_handler)(int)) flags = SA_ONSTACK; } set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags, - SIGUSR1, SIGIO, SIGWINCH, -1); + SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); set_handler(SIGTRAP, (__sighandler_t) sig_handler, flags, - SIGUSR1, SIGIO, SIGWINCH, -1); + SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); set_handler(SIGFPE, (__sighandler_t) sig_handler, flags, - SIGUSR1, SIGIO, SIGWINCH, -1); + SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); set_handler(SIGILL, (__sighandler_t) sig_handler, flags, - SIGUSR1, SIGIO, SIGWINCH, -1); + SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); set_handler(SIGBUS, (__sighandler_t) sig_handler, flags, - SIGUSR1, SIGIO, SIGWINCH, -1); + SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); set_handler(SIGWINCH, (__sighandler_t) sig_handler, flags, - SIGUSR1, SIGIO, SIGWINCH, -1); + SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); set_handler(SIGUSR2, (__sighandler_t) sig_handler, SA_NOMASK | flags, -1); if(usr1_handler) set_handler(SIGUSR1, usr1_handler, flags, -1); signal(SIGCHLD, SIG_IGN); signal(SIGHUP, SIG_IGN); - set_timers(1); /* XXX A bit of a race here */ + init_irq_signals(sig_stack != NULL); } diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index 8bd714887a3f..79a5b35e9344 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c @@ -41,6 +41,10 @@ #include "2_5compat.h" #include "os.h" +/* This is a per-cpu array. A processor only modifies its entry and it only + * cares about its entry, so it's OK if another processor is modifying its + * entry. + */ struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } }; struct task_struct *get_task(int pid, int require) @@ -86,7 +90,7 @@ int pid_to_processor_id(int pid) { int i; - for(i = 0; i < num_online_cpus(); i++){ + for(i = 0; i < ncpus; i++){ if(cpu_tasks[i].pid == pid) return(i); } return(-1); @@ -152,12 +156,19 @@ static void new_thread_handler(int sig) current->thread.regs.regs.sc = (void *) (&sig + 1); suspend_new_thread(current->thread.switch_pipe[0]); + block_signals(); +#ifdef CONFIG_SMP + schedule_tail(NULL); +#endif + enable_timer(); free_page(current->thread.temp_stack); set_cmdline("(kernel thread)"); force_flush_all(); current->thread.prev_sched = NULL; change_sig(SIGUSR1, 1); + change_sig(SIGVTALRM, 1); + change_sig(SIGPROF, 1); unblock_signals(); if(!run_kernel_thread(fn, arg, ¤t->thread.jmp)) do_exit(0); @@ -165,7 +176,9 @@ static void new_thread_handler(int sig) static int new_thread_proc(void *stack) { - block_signals(); + change_sig(SIGIO, 0); + change_sig(SIGVTALRM, 0); + change_sig(SIGPROF, 0); init_new_thread(stack, new_thread_handler); os_usr1_process(os_getpid()); return(0); @@ -204,6 +217,9 @@ void *switch_to(void *prev, void *next, void *last) unsigned long flags; int vtalrm, alrm, prof, err, cpu; char c; + /* jailing and SMP are incompatible, so this doesn't need to be + * made per-cpu + */ static int reading; from = prev; @@ -229,7 +245,7 @@ void *switch_to(void *prev, void *next, void *last) set_current(to); reading = 0; - err = user_write(to->thread.switch_pipe[1], &c, sizeof(c)); + err = os_write_file(to->thread.switch_pipe[1], &c, sizeof(c)); if(err != sizeof(c)) panic("write of switch_pipe failed, errno = %d", -err); @@ -237,7 +253,7 @@ void *switch_to(void *prev, void *next, void *last) if((from->state == TASK_ZOMBIE) || (from->state == TASK_DEAD)) os_kill_process(os_getpid()); - err = user_read(from->thread.switch_pipe[0], &c, sizeof(c)); + err = os_read_file(from->thread.switch_pipe[0], &c, sizeof(c)); if(err != sizeof(c)) panic("read of switch_pipe failed, errno = %d", -err); @@ -298,13 +314,16 @@ void exit_thread(void) * onto the signal frame. */ -extern int hit_me; - void finish_fork_handler(int sig) { current->thread.regs.regs.sc = (void *) (&sig + 1); suspend_new_thread(current->thread.switch_pipe[0]); - + +#ifdef CONFIG_SMP + schedule_tail(NULL); +#endif + enable_timer(); + change_sig(SIGVTALRM, 1); force_flush_all(); if(current->mm != current->parent->mm) protect(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); @@ -313,7 +332,6 @@ void finish_fork_handler(int sig) current->thread.prev_sched = NULL; free_page(current->thread.temp_stack); - block_signals(); change_sig(SIGUSR1, 0); set_user_mode(current); } @@ -339,7 +357,9 @@ int fork_tramp(void *stack) { int sig = sigusr1; - block_signals(); + change_sig(SIGIO, 0); + change_sig(SIGVTALRM, 0); + change_sig(SIGPROF, 0); init_new_thread(stack, finish_fork_handler); kill(os_getpid(), sig); @@ -474,7 +494,7 @@ int current_pid(void) void default_idle(void) { - if(current->thread_info->cpu == 0) idle_timer(); + idle_timer(); atomic_inc(&init_mm.mm_count); current->mm = &init_mm; @@ -644,6 +664,7 @@ char *uml_strdup(char *string) return(new); } +/* Changed by jail_setup, which is a setup */ int jail = 0; int __init jail_setup(char *line, int *add) @@ -708,17 +729,14 @@ static void mprotect_kernel_mem(int w) mprotect_kernel_vm(w); } -int jail_timer_off = 0; - +/* No SMP problems since jailing and SMP are incompatible */ void unprotect_kernel_mem(void) { mprotect_kernel_mem(1); - jail_timer_off = 0; } void protect_kernel_mem(void) { - jail_timer_off = 1; mprotect_kernel_mem(0); } @@ -749,9 +767,11 @@ void set_thread_sc(void *sc) int smp_sigio_handler(void) { + int cpu = current->thread_info->cpu; #ifdef CONFIG_SMP - IPI_handler(hard_smp_processor_id()); - if (hard_smp_processor_id() != 0) return(1); + IPI_handler(cpu); + if(cpu != 0) + return(1); #endif return(0); } @@ -761,6 +781,11 @@ int um_in_interrupt(void) return(in_interrupt()); } +int cpu(void) +{ + return(current->thread_info->cpu); +} + /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff --git a/arch/um/kernel/sigio_kern.c b/arch/um/kernel/sigio_kern.c index fc37b78b4009..02272e623614 100644 --- a/arch/um/kernel/sigio_kern.c +++ b/arch/um/kernel/sigio_kern.c @@ -11,6 +11,7 @@ #include "sigio.h" #include "irq_user.h" +/* Protected by sigio_lock() called from write_sigio_workaround */ static int sigio_irq_fd = -1; void sigio_interrupt(int irq, void *data, struct pt_regs *unused) @@ -31,6 +32,18 @@ int write_sigio_irq(int fd) return(0); } +static spinlock_t sigio_spinlock = SPIN_LOCK_UNLOCKED; + +void sigio_lock(void) +{ + spin_lock(&sigio_spinlock); +} + +void sigio_unlock(void) +{ + spin_unlock(&sigio_spinlock); +} + /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c index fd3b70704621..740608075b7c 100644 --- a/arch/um/kernel/sigio_user.c +++ b/arch/um/kernel/sigio_user.c @@ -21,9 +21,11 @@ #include "helper.h" #include "os.h" +/* Changed during early boot */ int pty_output_sigio = 0; int pty_close_sigio = 0; +/* Used as a flag during SIGIO testing early in boot */ static int got_sigio = 0; void __init handler(int sig) @@ -151,7 +153,15 @@ void __init check_sigio(void) check_one_sigio(tty_close); } +/* Protected by sigio_lock(), also used by sigio_cleanup, which is an + * exitcall. + */ static int write_sigio_pid = -1; + +/* These arrays are initialized before the sigio thread is started, and + * the descriptors closed after it is killed. So, it can't see them change. + * On the UML side, they are changed under the sigio_lock. + */ static int write_sigio_fds[2] = { -1, -1 }; static int sigio_private[2] = { -1, -1 }; @@ -161,6 +171,9 @@ struct pollfds { int used; }; +/* Protected by sigio_lock(). Used by the sigio thread, but the UML thread + * synchronizes with it. + */ struct pollfds current_poll = { poll : NULL, size : 0, @@ -217,8 +230,6 @@ static int write_sigio_thread(void *unused) } } -/* XXX SMP locking needed here too */ - static int need_poll(int n) { if(n <= next_poll.size){ @@ -260,25 +271,31 @@ static void update_thread(void) set_signals(flags); return; fail: + sigio_lock(); if(write_sigio_pid != -1) kill(write_sigio_pid, SIGKILL); write_sigio_pid = -1; close(sigio_private[0]); close(sigio_private[1]); close(write_sigio_fds[0]); close(write_sigio_fds[1]); + sigio_unlock(); set_signals(flags); } int add_sigio_fd(int fd, int read) { - int err, i, n, events; + int err = 0, i, n, events; - for(i = 0; i < current_poll.used; i++) - if(current_poll.poll[i].fd == fd) return(0); + sigio_lock(); + for(i = 0; i < current_poll.used; i++){ + if(current_poll.poll[i].fd == fd) + goto out; + } n = current_poll.used + 1; err = need_poll(n); - if(err) return(err); + if(err) + goto out; for(i = 0; i < current_poll.used; i++) next_poll.poll[i] = current_poll.poll[i]; @@ -290,21 +307,26 @@ int add_sigio_fd(int fd, int read) events : events, revents : 0 }); update_thread(); - return(0); + out: + sigio_unlock(); + return(err); } int ignore_sigio_fd(int fd) { struct pollfd *p; - int err, i, n = 0; + int err = 0, i, n = 0; + sigio_lock(); for(i = 0; i < current_poll.used; i++){ if(current_poll.poll[i].fd == fd) break; } - if(i == current_poll.used) return(0); + if(i == current_poll.used) + goto out; err = need_poll(current_poll.used - 1); - if(err) return(err); + if(err) + goto out; for(i = 0; i < current_poll.used; i++){ p = ¤t_poll.poll[i]; @@ -312,11 +334,14 @@ int ignore_sigio_fd(int fd) } if(n == i){ printk("ignore_sigio_fd : fd %d not found\n", fd); - return(-1); + err = -1; + goto out; } update_thread(); - return(0); + out: + sigio_unlock(); + return(err); } static int setup_initial_poll(int fd) @@ -342,14 +367,15 @@ void write_sigio_workaround(void) unsigned long stack; int err; - if(write_sigio_pid != -1) return; + sigio_lock(); + if(write_sigio_pid != -1) + goto out; - /* XXX This needs SMP locking */ err = os_pipe(write_sigio_fds, 1, 1); if(err){ printk("write_sigio_workaround - os_pipe 1 failed, " "errno = %d\n", -err); - return; + goto out; } err = os_pipe(sigio_private, 1, 1); if(err){ @@ -368,6 +394,8 @@ void write_sigio_workaround(void) if(write_sigio_irq(write_sigio_fds[0])) goto out_kill; + out: + sigio_unlock(); return; out_kill: @@ -379,6 +407,7 @@ void write_sigio_workaround(void) out_close1: close(write_sigio_fds[0]); close(write_sigio_fds[1]); + sigio_unlock(); } int read_sigio_fd(int fd) diff --git a/arch/um/kernel/signal_user.c b/arch/um/kernel/signal_user.c index b5b329614493..5e4ae282919a 100644 --- a/arch/um/kernel/signal_user.c +++ b/arch/um/kernel/signal_user.c @@ -19,8 +19,6 @@ #include "sysdep/sigcontext.h" #include "sigcontext.h" -extern int kern_timer_on; - void set_sigstack(void *sig_stack, int size) { stack_t stack; @@ -57,7 +55,7 @@ int change_sig(int signal, int on) sigemptyset(&sigset); sigaddset(&sigset, signal); sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old); - return(sigismember(&old, signal)); + return(!sigismember(&old, signal)); } static void change_signals(int type) @@ -65,12 +63,8 @@ static void change_signals(int type) sigset_t mask; sigemptyset(&mask); - if(type == SIG_BLOCK) kern_timer_on = 0; - else { - kern_timer_on = 1; - sigaddset(&mask, SIGVTALRM); - sigaddset(&mask, SIGALRM); - } + sigaddset(&mask, SIGVTALRM); + sigaddset(&mask, SIGALRM); sigaddset(&mask, SIGIO); sigaddset(&mask, SIGPROF); if(sigprocmask(type, &mask, NULL) < 0) @@ -97,7 +91,6 @@ static int disable_mask(sigset_t *mask) sigs = sigismember(mask, SIGIO) ? 1 << SIGIO_BIT : 0; sigs |= sigismember(mask, SIGVTALRM) ? 1 << SIGVTALRM_BIT : 0; sigs |= sigismember(mask, SIGALRM) ? 1 << SIGVTALRM_BIT : 0; - if(!kern_timer_on) sigs |= 1 << SIGVTALRM_BIT; return(sigs); } @@ -116,21 +109,27 @@ int set_signals(int disable) int ret; sigemptyset(&mask); - if(!(disable & (1 << SIGIO_BIT))) sigaddset(&mask, SIGIO); + if(!(disable & (1 << SIGIO_BIT))) + sigaddset(&mask, SIGIO); if(!(disable & (1 << SIGVTALRM_BIT))){ - kern_timer_on = 1; sigaddset(&mask, SIGVTALRM); sigaddset(&mask, SIGALRM); } if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0) panic("Failed to enable signals"); + ret = disable_mask(&mask); + sigemptyset(&mask); - if(disable & (1 << SIGIO_BIT)) sigaddset(&mask, SIGIO); - if(disable & (1 << SIGVTALRM_BIT)) - kern_timer_on = 0; + if(disable & (1 << SIGIO_BIT)) + sigaddset(&mask, SIGIO); + if(disable & (1 << SIGVTALRM_BIT)){ + sigaddset(&mask, SIGVTALRM); + sigaddset(&mask, SIGALRM); + } if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0) panic("Failed to block signals"); + return(ret); } diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c index d53644005d4f..689db0e805d2 100644 --- a/arch/um/kernel/smp.c +++ b/arch/um/kernel/smp.c @@ -5,7 +5,7 @@ #include "linux/config.h" -/* CPU online map */ +/* CPU online map, set by smp_boot_cpus */ unsigned long cpu_online_map = 1; #ifdef CONFIG_SMP @@ -21,25 +21,32 @@ unsigned long cpu_online_map = 1; #include "user_util.h" #include "kern_util.h" #include "kern.h" +#include "irq_user.h" #include "os.h" -/* The 'big kernel lock' */ -spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED; - -/* Per CPU bogomips and other parameters */ +/* Per CPU bogomips and other parameters + * The only piece used here is the ipi pipe, which is set before SMP is + * started and never changed. + */ struct cpuinfo_um cpu_data[NR_CPUS]; spinlock_t um_bh_lock = SPIN_LOCK_UNLOCKED; atomic_t global_bh_count; +/* Not used by UML */ unsigned char global_irq_holder = NO_PROC_ID; unsigned volatile long global_irq_lock; /* Set when the idlers are all forked */ int smp_threads_ready = 0; + +/* A statistic, can be a little off */ int num_reschedules_sent = 0; +/* Small, random number, never changed */ +unsigned long cache_decay_ticks = 5; + void smp_send_reschedule(int cpu) { write(cpu_data[cpu].ipi_pipe[1], "R", 1); @@ -83,30 +90,24 @@ void synchronize_bh(void) void smp_send_stop(void) { - printk(KERN_INFO "Stopping all CPUs\n"); -} + int i; + printk(KERN_INFO "Stopping all CPUs..."); + for(i = 0; i < num_online_cpus(); i++){ + if(i == current->thread_info->cpu) + continue; + write(cpu_data[i].ipi_pipe[1], "S", 1); + } + printk("done\n"); +} -static atomic_t smp_commenced = ATOMIC_INIT(0); +static unsigned long smp_commenced_mask; static volatile unsigned long smp_callin_map = 0; -void smp_commence(void) +static int idle_proc(void *cpup) { - printk("All CPUs are go!\n"); - - wmb(); - atomic_set(&smp_commenced, 1); -} - -static int idle_proc(void *unused) -{ - int cpu, err; - - set_current(current); - del_from_runqueue(current); - unhash_process(current); + int cpu = (int) cpup, err; - cpu = current->processor; err = os_pipe(cpu_data[cpu].ipi_pipe, 1, 1); if(err) panic("CPU#%d failed to create IPI pipe, errno = %d", cpu, @@ -115,46 +116,41 @@ static int idle_proc(void *unused) activate_ipi(cpu_data[cpu].ipi_pipe[0], current->thread.extern_pid); wmb(); - if (test_and_set_bit(current->processor, &smp_callin_map)) { - printk("huh, CPU#%d already present??\n", current->processor); + if (test_and_set_bit(cpu, &smp_callin_map)) { + printk("huh, CPU#%d already present??\n", cpu); BUG(); } - while (!atomic_read(&smp_commenced)) + while (!test_bit(cpu, &smp_commenced_mask)) cpu_relax(); - init_idle(); + set_bit(cpu, &cpu_online_map); default_idle(); return(0); } -int inited_cpus = 1; - -static int idle_thread(int (*fn)(void *), int cpu) +static struct task_struct *idle_thread(int cpu) { - struct task_struct *p; - int pid; + struct task_struct *new_task; unsigned char c; - current->thread.request.u.thread.proc = fn; - current->thread.request.u.thread.arg = NULL; - p = do_fork(CLONE_VM | CLONE_PID, 0, NULL, 0); - if(IS_ERR(p)) panic("do_fork failed in idle_thread"); - - cpu_tasks[cpu].pid = p->thread.extern_pid; - cpu_tasks[cpu].task = p; - inited_cpus++; - init_tasks[cpu] = p; - p->processor = cpu; - p->cpus_allowed = 1 << cpu; - p->cpus_runnable = p->cpus_allowed; - write(p->thread.switch_pipe[1], &c, sizeof(c)); - return(p->thread.extern_pid); + current->thread.request.u.thread.proc = idle_proc; + current->thread.request.u.thread.arg = (void *) cpu; + new_task = do_fork(CLONE_VM | CLONE_IDLETASK, 0, NULL, 0, NULL); + if(IS_ERR(new_task)) panic("do_fork failed in idle_thread"); + + cpu_tasks[cpu] = ((struct cpu_task) + { .pid = new_task->thread.extern_pid, + .task = new_task } ); + write(new_task->thread.switch_pipe[1], &c, sizeof(c)); + return(new_task); } -void smp_boot_cpus(void) +void smp_prepare_cpus(unsigned int maxcpus) { - int err; + struct task_struct *idle; + unsigned long waittime; + int err, cpu; set_bit(0, &cpu_online_map); set_bit(0, &smp_callin_map); @@ -164,46 +160,32 @@ void smp_boot_cpus(void) activate_ipi(cpu_data[0].ipi_pipe[0], current->thread.extern_pid); - if(ncpus < 1){ - printk(KERN_INFO "ncpus set to 1\n"); - ncpus = 1; - } - else if(ncpus > NR_CPUS){ - printk(KERN_INFO - "ncpus can't be greater than NR_CPUS, set to %d\n", - NR_CPUS); - ncpus = NR_CPUS; - } - - if(ncpus > 1){ - int i, pid; - - printk(KERN_INFO "Starting up other processors:\n"); - for(i=1;i<ncpus;i++){ - int waittime; - - /* Do this early, for hard_smp_processor_id() */ - cpu_tasks[i].pid = -1; - set_bit(i, &cpu_online_map); + for(cpu = 1; cpu < ncpus; cpu++){ + printk("Booting processor %d...\n", cpu); + + idle = idle_thread(cpu); - pid = idle_thread(idle_proc, i); - printk(KERN_INFO "\t#%d - idle thread pid = %d.. ", - i, pid); + init_idle(idle, cpu); + unhash_process(idle); - waittime = 200000000; - while (waittime-- && !test_bit(i, &smp_callin_map)) - cpu_relax(); + waittime = 200000000; + while (waittime-- && !test_bit(cpu, &smp_callin_map)) + cpu_relax(); - if (test_bit(i, &smp_callin_map)) - printk("online\n"); - else { - printk("failed\n"); - clear_bit(i, &cpu_online_map); - } - } + if (test_bit(cpu, &smp_callin_map)) + printk("done\n"); + else printk("failed\n"); } } +int __cpu_up(unsigned int cpu) +{ + set_bit(cpu, &smp_commenced_mask); + while (!test_bit(cpu, &cpu_online_map)) + mb(); + return(0); +} + int setup_profiling_timer(unsigned int multiplier) { printk(KERN_INFO "setup_profiling_timer\n"); @@ -225,7 +207,13 @@ void IPI_handler(int cpu) break; case 'R': - current->need_resched = 1; + set_tsk_need_resched(current); + break; + + case 'S': + printk("CPU#%d stopping\n", cpu); + while(1) + pause(); break; default: @@ -269,7 +257,8 @@ int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic, info = _info; for (i=0;i<NR_CPUS;i++) - if (i != current->processor && test_bit(i, &cpu_online_map)) + if((i != current->thread_info->cpu) && + test_bit(i, &cpu_online_map)) write(cpu_data[i].ipi_pipe[1], "C", 1); while (atomic_read(&scf_started) != cpus) diff --git a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c index 1aea2a006788..b15340a6b837 100644 --- a/arch/um/kernel/syscall_kern.c +++ b/arch/um/kernel/syscall_kern.c @@ -384,6 +384,7 @@ static int check_bogosity(struct pt_regs *regs) return(0); } +/* Unlocked, I don't care if this is a bit off */ int nsyscalls = 0; extern syscall_handler_t *sys_call_table[]; @@ -417,14 +418,18 @@ long execute_syscall(void *r) spinlock_t syscall_lock = SPIN_LOCK_UNLOCKED; -void lock_syscall(void) -{ - spin_lock(&syscall_lock); -} +static int syscall_index = 0; -void unlock_syscall(void) +int next_syscall_index(int limit) { + int ret; + + spin_lock(&syscall_lock); + ret = syscall_index; + if(++syscall_index == limit) + syscall_index = 0; spin_unlock(&syscall_lock); + return(ret); } /* diff --git a/arch/um/kernel/syscall_user.c b/arch/um/kernel/syscall_user.c index 921045f804b7..5da5aefce6d8 100644 --- a/arch/um/kernel/syscall_user.c +++ b/arch/um/kernel/syscall_user.c @@ -34,21 +34,14 @@ struct { struct timeval end; } syscall_record[1024]; -int syscall_index = 0; - -extern int kern_timer_on; - void syscall_handler(int sig, struct uml_pt_regs *regs) { void *sc; long result; - int index, syscall; + int index, max, syscall; - lock_syscall(); - if(syscall_index == 1024) syscall_index = 0; - index = syscall_index; - syscall_index++; - unlock_syscall(); + max = sizeof(syscall_record)/sizeof(syscall_record[0]); + index = next_syscall_index(max); syscall = regs->syscall; sc = regs->sc; diff --git a/arch/um/kernel/tempfile.c b/arch/um/kernel/tempfile.c new file mode 100644 index 000000000000..0869e1a85ec9 --- /dev/null +++ b/arch/um/kernel/tempfile.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <sys/param.h> +#include "init.h" + +char *tempdir = NULL; + +static void __init find_tempdir(void) +{ + char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL }; + int i; + char *dir = NULL; + + if(tempdir != NULL) return; /* We've already been called */ + for(i = 0; dirs[i]; i++){ + dir = getenv(dirs[i]); + if(dir != NULL) break; + } + if(dir == NULL) dir = "/tmp"; + else if(*dir == '\0') dir = NULL; + if(dir != NULL) { + tempdir = malloc(strlen(dir) + 2); + if(tempdir == NULL){ + fprintf(stderr, "Failed to malloc tempdir, " + "errno = %d\n", errno); + return; + } + strcpy(tempdir, dir); + strcat(tempdir, "/"); + } +} + +int make_tempfile(const char *template, char **out_tempname, int do_unlink) +{ + char tempname[MAXPATHLEN]; + int fd; + + find_tempdir(); + if (*template != '/') + strcpy(tempname, tempdir); + else + *tempname = 0; + strcat(tempname, template); + if((fd = mkstemp(tempname)) < 0){ + fprintf(stderr, "open - cannot create %s: %s\n", tempname, + strerror(errno)); + return -1; + } + if(do_unlink && (unlink(tempname) < 0)){ + perror("unlink"); + return -1; + } + if(out_tempname){ + if((*out_tempname = strdup(tempname)) == NULL){ + perror("strdup"); + return -1; + } + } + return(fd); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index a9d4669132de..2ab57626b43f 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c @@ -14,33 +14,15 @@ #include "user.h" #include "process.h" #include "signal_user.h" +#include "time_user.h" extern struct timeval xtime; -void timer_handler(int sig, struct uml_pt_regs *regs) -{ - timer_irq(regs); -} - void timer(void) { gettimeofday(&xtime, NULL); } -static struct itimerval profile_interval; - -void get_profile_timer(void) -{ - getitimer(ITIMER_PROF, &profile_interval); - profile_interval.it_value = profile_interval.it_interval; -} - -void disable_profile_timer(void) -{ - struct itimerval interval = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); - setitimer(ITIMER_PROF, &interval, NULL); -} - static void set_interval(int timer_type) { struct itimerval interval; @@ -53,6 +35,15 @@ static void set_interval(int timer_type) panic("setitimer failed - errno = %d\n", errno); } +void enable_timer(void) +{ + struct itimerval enable = ((struct itimerval) { { 0, 1000000/hz() }, + { 0, 1000000/hz() }}); + if(setitimer(ITIMER_VIRTUAL, &enable, NULL)) + printk("enable_timer - setitimer failed, errno = %d\n", + errno); +} + void switch_timers(int to_real) { struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); @@ -79,8 +70,9 @@ void idle_timer(void) { if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR) panic("Couldn't unset SIGVTALRM handler"); + set_handler(SIGALRM, (__sighandler_t) alarm_handler, - SA_NODEFER | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, -1); + SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); set_interval(ITIMER_REAL); } @@ -98,28 +90,24 @@ void time_init(void) set_interval(ITIMER_VIRTUAL); } -void set_timers(int set_signal) -{ - if(set_signal) - set_interval(ITIMER_VIRTUAL); - if(setitimer(ITIMER_PROF, &profile_interval, NULL) == -1) - panic("setitimer ITIMER_PROF failed - errno = %d\n", errno); -} - struct timeval local_offset = { 0, 0 }; void do_gettimeofday(struct timeval *tv) { + time_lock(); gettimeofday(tv, NULL); timeradd(tv, &local_offset, tv); + time_unlock(); } void do_settimeofday(struct timeval *tv) { struct timeval now; + time_lock(); gettimeofday(&now, NULL); timersub(tv, &now, &local_offset); + time_unlock(); } void idle_sleep(int secs) diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c index 4c96bd9637e7..93199e99c6f8 100644 --- a/arch/um/kernel/time_kern.c +++ b/arch/um/kernel/time_kern.c @@ -27,21 +27,21 @@ int hz(void) return(HZ); } +/* Changed at early boot */ int timer_irq_inited = 0; -/* kern_timer_on and missed_ticks are modified after kernel memory has been +/* missed_ticks will be modified after kernel memory has been * write-protected, so this puts it in a section which will be left * write-enabled. */ -int __attribute__ ((__section__ (".unprotected"))) kern_timer_on = 0; -int __attribute__ ((__section__ (".unprotected"))) missed_ticks = 0; +int __attribute__ ((__section__ (".unprotected"))) missed_ticks[NR_CPUS]; void timer_irq(struct uml_pt_regs *regs) { - int ticks = missed_ticks; + int cpu = current->thread_info->cpu, ticks = missed_ticks[cpu]; if(!timer_irq_inited) return; - missed_ticks = 0; + missed_ticks[cpu] = 0; while(ticks--) do_IRQ(TIMER_IRQ, regs); } @@ -86,6 +86,7 @@ long um_stime(int * tptr) return 0; } +/* XXX Needs to be moved under sys-i386 */ void __delay(um_udelay_t time) { /* Stolen from the i386 __loop_delay */ @@ -116,6 +117,27 @@ void __const_udelay(um_udelay_t usecs) for(i=0;i<n;i++) ; } +void timer_handler(int sig, struct uml_pt_regs *regs) +{ +#ifdef CONFIG_SMP + update_process_times(user_context(UPT_SP(regs))); +#endif + if(current->thread_info->cpu == 0) + timer_irq(regs); +} + +static spinlock_t timer_spinlock = SPIN_LOCK_UNLOCKED; + +void time_lock(void) +{ + spin_lock(&timer_spinlock); +} + +void time_unlock(void) +{ + spin_unlock(&timer_spinlock); +} + int __init timer_init(void) { int err; diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c index 8f104d7a1853..158ea30937b3 100644 --- a/arch/um/kernel/trap_kern.c +++ b/arch/um/kernel/trap_kern.c @@ -171,14 +171,18 @@ void trap_init(void) spinlock_t trap_lock = SPIN_LOCK_UNLOCKED; -void lock_trap(void) -{ - spin_lock(&trap_lock); -} +static int trap_index = 0; -void unlock_trap(void) +int next_trap_index(int limit) { + int ret; + + spin_lock(&trap_lock); + ret = trap_index; + if(++trap_index == limit) + trap_index = 0; spin_unlock(&trap_lock); + return(ret); } extern int debugger_pid; @@ -209,6 +213,7 @@ static struct chan_opts opts = { tramp_stack : 0, }; +/* Accessed by the tracing thread, which automatically serializes access */ static void *xterm_data; static int xterm_fd; diff --git a/arch/um/kernel/trap_user.c b/arch/um/kernel/trap_user.c index 90a6df7a43ec..8971a61c8310 100644 --- a/arch/um/kernel/trap_user.c +++ b/arch/um/kernel/trap_user.c @@ -70,10 +70,10 @@ void kill_child_dead(int pid) while(waitpid(pid, NULL, 0) > 0) kill(pid, SIGCONT); } +/* Changed early in boot, and then only read */ int debug = 0; int debug_stop = 1; int debug_parent = 0; - int honeypot = 0; static int signal_tramp(void *arg) @@ -90,7 +90,6 @@ static int signal_tramp(void *arg) signal(SIGUSR1, SIG_IGN); change_sig(SIGCHLD, 0); signal(SIGSEGV, (__sighandler_t) sig_handler); - set_timers(0); set_cmdline("(idle thread)"); set_init_pid(os_getpid()); proc = arg; @@ -99,6 +98,7 @@ static int signal_tramp(void *arg) static void last_ditch_exit(int sig) { + kmalloc_ok = 0; signal(SIGINT, SIG_DFL); signal(SIGTERM, SIG_DFL); signal(SIGHUP, SIG_DFL); @@ -142,33 +142,20 @@ static void sleeping_process_signal(int pid, int sig) } } -#ifdef CONFIG_SMP -#error need to make these arrays -#endif - +/* Accessed only by the tracing thread */ int debugger_pid = -1; int debugger_parent = -1; int debugger_fd = -1; int gdb_pid = -1; struct { - unsigned long address; - int is_write; - int pid; - unsigned long sp; - int is_user; -} segfault_record[1024]; - -int segfault_index = 0; - -struct { int pid; int signal; unsigned long addr; struct timeval time; -} signal_record[1024]; +} signal_record[1024][32]; -int signal_index = 0; +int signal_index[32]; int nsignals = 0; int debug_trace = 0; extern int io_nsignals, io_count, intr_count; @@ -188,7 +175,7 @@ int signals(int (*init_proc)(void *), void *sp) signal(SIGPIPE, SIG_IGN); setup_tracer_winch(); tracing_pid = os_getpid(); - printk("tracing thread pid = %d\n", tracing_pid); + printf("tracing thread pid = %d\n", tracing_pid); pid = clone(signal_tramp, sp, CLONE_FILES | SIGCHLD, init_proc); n = waitpid(pid, &status, WUNTRACED); @@ -207,7 +194,7 @@ int signals(int (*init_proc)(void *), void *sp) set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); if(debug_trace){ - printk("Tracing thread pausing to be attached\n"); + printf("Tracing thread pausing to be attached\n"); stop(); } if(debug){ @@ -219,14 +206,14 @@ int signals(int (*init_proc)(void *), void *sp) init_parent_proxy(debugger_parent); err = attach(debugger_parent); if(err){ - printk("Failed to attach debugger parent %d, " + printf("Failed to attach debugger parent %d, " "errno = %d\n", debugger_parent, err); debugger_parent = -1; } else { if(ptrace(PTRACE_SYSCALL, debugger_parent, 0, 0) < 0){ - printk("Failed to continue debugger " + printf("Failed to continue debugger " "parent, errno = %d\n", errno); debugger_parent = -1; } @@ -237,7 +224,7 @@ int signals(int (*init_proc)(void *), void *sp) while(1){ if((pid = waitpid(-1, &status, WUNTRACED)) <= 0){ if(errno != ECHILD){ - printk("wait failed - errno = %d\n", errno); + printf("wait failed - errno = %d\n", errno); } continue; } @@ -259,36 +246,36 @@ int signals(int (*init_proc)(void *), void *sp) if(WIFEXITED(status)) ; #ifdef notdef { - printk("Child %d exited with status %d\n", pid, + printf("Child %d exited with status %d\n", pid, WEXITSTATUS(status)); } #endif else if(WIFSIGNALED(status)){ sig = WTERMSIG(status); if(sig != 9){ - printk("Child %d exited with signal %d\n", pid, + printf("Child %d exited with signal %d\n", pid, sig); } } else if(WIFSTOPPED(status)){ + proc_id = pid_to_processor_id(pid); sig = WSTOPSIG(status); - if(signal_index == 1024){ - signal_index = 0; + if(signal_index[proc_id] == 1024){ + signal_index[proc_id] = 0; last_index = 1023; } - else last_index = signal_index - 1; + else last_index = signal_index[proc_id] - 1; if(((sig == SIGPROF) || (sig == SIGVTALRM) || (sig == SIGALRM)) && - (signal_record[last_index].signal == sig) && - (signal_record[last_index].pid == pid)) - signal_index = last_index; - signal_record[signal_index].pid = pid; - gettimeofday(&signal_record[signal_index].time, NULL); + (signal_record[proc_id][last_index].signal == sig)&& + (signal_record[proc_id][last_index].pid == pid)) + signal_index[proc_id] = last_index; + signal_record[proc_id][signal_index[proc_id]].pid = pid; + gettimeofday(&signal_record[proc_id][signal_index[proc_id]].time, NULL); eip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0); - signal_record[signal_index].addr = eip; - signal_record[signal_index++].signal = sig; + signal_record[proc_id][signal_index[proc_id]].addr = eip; + signal_record[proc_id][signal_index[proc_id]++].signal = sig; - proc_id = pid_to_processor_id(pid); if(proc_id == -1){ sleeping_process_signal(pid, sig); continue; @@ -314,7 +301,7 @@ int signals(int (*init_proc)(void *), void *sp) ptrace(PTRACE_KILL, pid, 0, 0); return(op == OP_REBOOT); case OP_NONE: - printk("Detaching pid %d\n", pid); + printf("Detaching pid %d\n", pid); detach(pid, SIGSTOP); continue; default: @@ -413,22 +400,30 @@ __uml_setup("honeypot", uml_honeypot_setup, " UML. This implies 'jail'.\n\n" ); +/* Unlocked - don't care if this is a bit off */ int nsegfaults = 0; +struct { + unsigned long address; + int is_write; + int pid; + unsigned long sp; + int is_user; +} segfault_record[1024]; + void segv_handler(int sig, struct uml_pt_regs *regs) { struct sigcontext *context = regs->sc; - int index; + int index, max; if(regs->is_user && !SEGV_IS_FIXABLE(context)){ bad_segv(SC_FAULT_ADDR(context), SC_IP(context), SC_FAULT_WRITE(context)); return; } - lock_trap(); - index = segfault_index++; - if(segfault_index == 1024) segfault_index = 0; - unlock_trap(); + max = sizeof(segfault_record)/sizeof(segfault_record[0]); + index = next_trap_index(max); + nsegfaults++; segfault_record[index].address = SC_FAULT_ADDR(context); segfault_record[index].pid = os_getpid(); @@ -439,8 +434,6 @@ void segv_handler(int sig, struct uml_pt_regs *regs) regs->is_user, context); } -extern int kern_timer_on; - struct signal_info { void (*handler)(int, struct uml_pt_regs *); int is_irq; @@ -471,7 +464,7 @@ void sig_handler_common(int sig, struct sigcontext *sc) { struct uml_pt_regs save_regs, *r; struct signal_info *info; - int save_errno = errno, save_timer = kern_timer_on, is_user; + int save_errno = errno, is_user; unprotect_kernel_mem(); @@ -488,7 +481,6 @@ void sig_handler_common(int sig, struct sigcontext *sc) (*info->handler)(sig, r); - kern_timer_on = save_timer; if(is_user){ interrupt_end(); block_signals(); @@ -505,19 +497,15 @@ void sig_handler(int sig, struct sigcontext sc) sig_handler_common(sig, &sc); } -extern int timer_irq_inited, missed_ticks; - -extern int jail_timer_off; +extern int timer_irq_inited, missed_ticks[]; void alarm_handler(int sig, struct sigcontext sc) { int user; if(!timer_irq_inited) return; - missed_ticks++; + missed_ticks[cpu()]++; user = user_context(SC_SP(&sc)); - if(!user && !kern_timer_on) return; - if(!user && jail_timer_off) return; if(sig == SIGALRM) switch_timers(0); diff --git a/arch/um/kernel/tty_log.c b/arch/um/kernel/tty_log.c index 1472a99a7686..7d53a6ea2ab0 100644 --- a/arch/um/kernel/tty_log.c +++ b/arch/um/kernel/tty_log.c @@ -17,8 +17,8 @@ #define TTY_LOG_DIR "./" -char *tty_log_dir = TTY_LOG_DIR; - +/* Set early in boot and then unchanged */ +static char *tty_log_dir = TTY_LOG_DIR; static int tty_log_fd = -1; #define TTY_LOG_OPEN 1 @@ -104,7 +104,7 @@ static int __init set_tty_log_fd(char *name, int *add) tty_log_fd = strtoul(name, &end, 0); if(*end != '\0'){ - printk("set_tty_log_dir - strtoul failed on '%s'\n", name); + printk("set_tty_log_fd - strtoul failed on '%s'\n", name); tty_log_fd = -1; } return 0; diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 5452d3f2563c..b7d436981572 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -37,6 +37,11 @@ #define DEFAULT_COMMAND_LINE "root=6200" +struct cpuinfo_um boot_cpu_data = { + .loops_per_jiffy = 0, + .ipi_pipe = { -1, -1 } +}; + unsigned long thread_saved_pc(struct task_struct *task) { return(os_process_pc(task->thread.extern_pid)); @@ -119,6 +124,7 @@ static int start_kernel_proc(void *unused) #define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000) #define START (TOP - SIZE) +/* Set in main */ unsigned long host_task_size; unsigned long task_size; @@ -129,17 +135,21 @@ void set_task_sizes(int arg) task_size = START; } +/* Set in early boot */ unsigned long uml_physmem; unsigned long uml_reserved; - unsigned long start_vm; unsigned long end_vm; - int ncpus = 1; +/* Pointer set in linux_main, the array itself is private to each thread, + * and changed at address space creation time so this poses no concurrency + * problems. + */ static char *argv1_begin = NULL; static char *argv1_end = NULL; +/* Set in early boot */ static int have_root __initdata = 0; long physmem_size = 32 * 1024 * 1024; @@ -258,8 +268,9 @@ static void __init uml_postsetup(void) } extern int debug_trace; -unsigned long brk_start; +/* Set during early boot */ +unsigned long brk_start; static struct vm_reserved kernel_vm_reserved; #define MIN_VMALLOC (32 * 1024 * 1024) @@ -316,11 +327,12 @@ int linux_main(int argc, char **argv) end_vm = start_vm + virtmem_size; if(virtmem_size < physmem_size) - printk(KERN_INFO "Kernel virtual memory size shrunk to %ld " - "bytes\n", virtmem_size); + printf("Kernel virtual memory size shrunk to %ld bytes\n", + virtmem_size); err = reserve_vm(high_physmem, end_vm, &kernel_vm_reserved); - if(err) panic("Failed to reserve VM area for kernel VM\n"); + if(err) + tracer_panic("Failed to reserve VM area for kernel VM\n"); uml_postsetup(); @@ -365,18 +377,6 @@ void __init check_bugs(void) check_sigio(); } -spinlock_t pid_lock = SPIN_LOCK_UNLOCKED; - -void lock_pid(void) -{ - spin_lock(&pid_lock); -} - -void unlock_pid(void) -{ - spin_unlock(&pid_lock); -} - /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c index ca6735f415ba..2ba2049510b3 100644 --- a/arch/um/kernel/umid.c +++ b/arch/um/kernel/umid.c @@ -21,9 +21,13 @@ #define UMID_LEN 64 #define UML_DIR "~/.uml/" +/* Changed by set_umid and make_umid, which are run early in boot */ static char umid[UMID_LEN] = { 0 }; + +/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */ static char *uml_dir = UML_DIR; +/* Changed by set_umid */ static int umid_is_random = 1; static int umid_inited = 0; diff --git a/arch/um/kernel/user_util.c b/arch/um/kernel/user_util.c index 0445cde3cb52..2ed1491bded2 100644 --- a/arch/um/kernel/user_util.c +++ b/arch/um/kernel/user_util.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -32,6 +32,7 @@ #define COMMAND_LINE_SIZE _POSIX_ARG_MAX +/* Changed in linux_main and setup_arch, which run before SMP is started */ char saved_command_line[COMMAND_LINE_SIZE] = { 0 }; char command_line[COMMAND_LINE_SIZE] = { 0 }; @@ -184,85 +185,6 @@ void setup_hostinfo(void) host.release, host.version, host.machine); } -void close_fd(int fd) -{ - close(fd); -} - -char *tempdir = NULL; - -static void __init find_tempdir(void) -{ - char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL }; - int i; - char *dir = NULL; - - if(tempdir != NULL) return; /* We've already been called */ - for(i = 0; dirs[i]; i++){ - dir = getenv(dirs[i]); - if(dir != NULL) break; - } - if(dir == NULL) dir = "/tmp"; - else if(*dir == '\0') dir = NULL; - if(dir != NULL) { - tempdir = malloc(strlen(dir) + 2); - if(tempdir == NULL){ - fprintf(stderr, "Failed to malloc tempdir, " - "errno = %d\n", errno); - return; - } - strcpy(tempdir, dir); - strcat(tempdir, "/"); - } -} - -int make_tempfile(const char *template, char **out_tempname, int do_unlink) -{ - char tempname[MAXPATHLEN]; - int fd; - - find_tempdir(); - if (*template != '/') - strcpy(tempname, tempdir); - else - *tempname = 0; - strcat(tempname, template); - if((fd = mkstemp(tempname)) < 0){ - fprintf(stderr, "open - cannot create %s: %s\n", tempname, - strerror(errno)); - return -1; - } - if(do_unlink && (unlink(tempname) < 0)){ - perror("unlink"); - return -1; - } - if(out_tempname){ - if((*out_tempname = strdup(tempname)) == NULL){ - perror("strdup"); - return -1; - } - } - return(fd); -} - -int user_read(int fd, char *buf, int len) -{ - int err; - - err = read(fd, buf, len); - if(err < 0) return(-errno); - else return(err); -} - -int user_write(int fd, char *buf, int len) -{ - int err; - - err = write(fd, buf, len); - if(err < 0) return(-errno); - else return(err); -} - /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff --git a/arch/um/main.c b/arch/um/main.c index 7005f4d7bc3b..204c7a189fdd 100644 --- a/arch/um/main.c +++ b/arch/um/main.c @@ -18,15 +18,22 @@ #include "user.h" #include "init.h" +/* Set in set_stklim, which is called from main and __wrap_malloc. + * __wrap_malloc only calls it if main hasn't started. + */ unsigned long stacksizelim; +/* Set in main */ char *linux_prog; #define PGD_BOUND (4 * 1024 * 1024) #define STACKSIZE (8 * 1024 * 1024) #define THREAD_NAME_LEN (256) -char padding[THREAD_NAME_LEN] = { [ 0 ... THREAD_NAME_LEN - 2] = ' ', '\0' }; +/* Never changed */ +static char padding[THREAD_NAME_LEN] = { + [ 0 ... THREAD_NAME_LEN - 2] = ' ', '\0' +}; static void set_stklim(void) { @@ -129,7 +136,8 @@ int main(int argc, char **argv, char **envp) return(uml_exitcode); } -int allocating_monbuf = 0; +/* Changed in __wrap___monstartup and __wrap_malloc very early */ +static int allocating_monbuf = 0; #ifdef PROFILING extern void __real___monstartup (unsigned long, unsigned long); @@ -146,6 +154,7 @@ void __wrap___monstartup (unsigned long lowpc, unsigned long highpc) extern void *__real_malloc(int); extern unsigned long host_task_size; +/* Set in __wrap_malloc early */ static void *gmon_buf = NULL; void *__wrap_malloc(int size) diff --git a/arch/um/ptproxy/proxy.c b/arch/um/ptproxy/proxy.c index 78789b9403e8..d5cd8c8919ba 100644 --- a/arch/um/ptproxy/proxy.c +++ b/arch/um/ptproxy/proxy.c @@ -30,6 +30,7 @@ Jeff Dike (jdike@karaya.com) : Modified for integration into uml #include "user_util.h" #include "user.h" #include "os.h" +#include "tempfile.h" static int debugger_wait(debugger_state *debugger, int *status, int options, int (*syscall)(debugger_state *debugger, pid_t child), @@ -122,6 +123,7 @@ int debugger_syscall(debugger_state *debugger, pid_t child) return(0); } +/* Used by the tracing thread */ static debugger_state parent; static int parent_syscall(debugger_state *debugger, int pid); @@ -174,10 +176,7 @@ void debugger_cancelled_return(debugger_state *debugger, int result) syscall_continue(debugger->pid); } -#ifdef CONFIG_SMP -#error need to make these arrays -#endif - +/* Used by the tracing thread */ static debugger_state debugger; static debugee_state debugee; diff --git a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c index 678b04a127c9..5b01a07368cc 100644 --- a/arch/um/sys-i386/bugs.c +++ b/arch/um/sys-i386/bugs.c @@ -15,6 +15,7 @@ #define MAXTOKEN 64 +/* Set during early boot */ int cpu_has_cmov = 1; int cpu_has_xmm = 0; diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c index 45a45edd28dc..659db8a6e2d8 100644 --- a/arch/um/sys-i386/ptrace_user.c +++ b/arch/um/sys-i386/ptrace_user.c @@ -59,6 +59,7 @@ static void read_debugregs(int pid, unsigned long *regs) } } +/* Accessed only by the tracing thread */ static unsigned long kernel_debugregs[8] = { [ 0 ... 7 ] = 0 }; static int debugregs_seq = 0; diff --git a/arch/um/sys-ppc/miscthings.c b/arch/um/sys-ppc/miscthings.c index 2377b5930ea8..373061c50129 100644 --- a/arch/um/sys-ppc/miscthings.c +++ b/arch/um/sys-ppc/miscthings.c @@ -2,9 +2,6 @@ #include "linux/stddef.h" // for NULL #include "linux/elf.h" // for AT_NULL -/* unsigned int local_bh_count[NR_CPUS]; */ -unsigned long isa_io_base = 0; - /* The following function nicked from arch/ppc/kernel/process.c and * adapted slightly */ /* diff --git a/arch/um/uml.lds.S b/arch/um/uml.lds.S index f6c40ec0d143..212f614b7621 100644 --- a/arch/um/uml.lds.S +++ b/arch/um/uml.lds.S @@ -67,6 +67,9 @@ SECTIONS __setup_start = .; .setup.init : { *(.setup.init) } __setup_end = .; + __per_cpu_start = . ; + .data.percpu : { *(.data.percpu) } + __per_cpu_end = . ; __initcall_start = .; .initcall.init : { *(.initcall1.init) |
