diff options
Diffstat (limited to 'arch')
38 files changed, 382 insertions, 207 deletions
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 32ca1b92730..6e943135f0e 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -253,15 +253,15 @@ do_osf_statfs(struct dentry * dentry, struct osf_statfs __user *buffer, } asmlinkage int -osf_statfs(char __user *path, struct osf_statfs __user *buffer, unsigned long bufsiz) +osf_statfs(char __user *pathname, struct osf_statfs __user *buffer, unsigned long bufsiz) { - struct nameidata nd; + struct path path; int retval; - retval = user_path_walk(path, &nd); + retval = user_path(pathname, &path); if (!retval) { - retval = do_osf_statfs(nd.path.dentry, buffer, bufsiz); - path_put(&nd.path); + retval = do_osf_statfs(path.dentry, buffer, bufsiz); + path_put(&path); } return retval; } diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c index 747b9dedab8..dc8b40783d9 100644 --- a/arch/arm/mach-at91/at91cap9_devices.c +++ b/arch/arm/mach-at91/at91cap9_devices.c @@ -377,7 +377,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} * -------------------------------------------------------------------- */ #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) -static struct at91_nand_data nand_data; +static struct atmel_nand_data nand_data; #define NAND_BASE AT91_CHIPSELECT_3 @@ -395,7 +395,7 @@ static struct resource nand_resources[] = { }; static struct platform_device at91cap9_nand_device = { - .name = "at91_nand", + .name = "atmel_nand", .id = -1, .dev = { .platform_data = &nand_data, @@ -404,7 +404,7 @@ static struct platform_device at91cap9_nand_device = { .num_resources = ARRAY_SIZE(nand_resources), }; -void __init at91_add_device_nand(struct at91_nand_data *data) +void __init at91_add_device_nand(struct atmel_nand_data *data) { unsigned long csa, mode; @@ -445,7 +445,7 @@ void __init at91_add_device_nand(struct at91_nand_data *data) platform_device_register(&at91cap9_nand_device); } #else -void __init at91_add_device_nand(struct at91_nand_data *data) {} +void __init at91_add_device_nand(struct atmel_nand_data *data) {} #endif diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index de19bee83f7..8ced9bc8209 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -369,7 +369,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} * -------------------------------------------------------------------- */ #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) -static struct at91_nand_data nand_data; +static struct atmel_nand_data nand_data; #define NAND_BASE AT91_CHIPSELECT_3 @@ -382,7 +382,7 @@ static struct resource nand_resources[] = { }; static struct platform_device at91rm9200_nand_device = { - .name = "at91_nand", + .name = "atmel_nand", .id = -1, .dev = { .platform_data = &nand_data, @@ -391,7 +391,7 @@ static struct platform_device at91rm9200_nand_device = { .num_resources = ARRAY_SIZE(nand_resources), }; -void __init at91_add_device_nand(struct at91_nand_data *data) +void __init at91_add_device_nand(struct atmel_nand_data *data) { unsigned int csa; @@ -429,7 +429,7 @@ void __init at91_add_device_nand(struct at91_nand_data *data) platform_device_register(&at91rm9200_nand_device); } #else -void __init at91_add_device_nand(struct at91_nand_data *data) {} +void __init at91_add_device_nand(struct atmel_nand_data *data) {} #endif diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 86cba4ac29b..cae5f52f127 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -284,7 +284,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} * -------------------------------------------------------------------- */ #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) -static struct at91_nand_data nand_data; +static struct atmel_nand_data nand_data; #define NAND_BASE AT91_CHIPSELECT_3 @@ -302,7 +302,7 @@ static struct resource nand_resources[] = { }; static struct platform_device at91sam9260_nand_device = { - .name = "at91_nand", + .name = "atmel_nand", .id = -1, .dev = { .platform_data = &nand_data, @@ -311,7 +311,7 @@ static struct platform_device at91sam9260_nand_device = { .num_resources = ARRAY_SIZE(nand_resources), }; -void __init at91_add_device_nand(struct at91_nand_data *data) +void __init at91_add_device_nand(struct atmel_nand_data *data) { unsigned long csa, mode; @@ -373,7 +373,7 @@ void __init at91_add_device_nand(struct at91_nand_data *data) platform_device_register(&at91sam9260_nand_device); } #else -void __init at91_add_device_nand(struct at91_nand_data *data) {} +void __init at91_add_device_nand(struct atmel_nand_data *data) {} #endif diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index ec1891375df..483d436af22 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -199,7 +199,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} * -------------------------------------------------------------------- */ #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) -static struct at91_nand_data nand_data; +static struct atmel_nand_data nand_data; #define NAND_BASE AT91_CHIPSELECT_3 @@ -211,8 +211,8 @@ static struct resource nand_resources[] = { } }; -static struct platform_device at91_nand_device = { - .name = "at91_nand", +static struct platform_device atmel_nand_device = { + .name = "atmel_nand", .id = -1, .dev = { .platform_data = &nand_data, @@ -221,7 +221,7 @@ static struct platform_device at91_nand_device = { .num_resources = ARRAY_SIZE(nand_resources), }; -void __init at91_add_device_nand(struct at91_nand_data *data) +void __init at91_add_device_nand(struct atmel_nand_data *data) { unsigned long csa, mode; @@ -262,11 +262,11 @@ void __init at91_add_device_nand(struct at91_nand_data *data) at91_set_A_periph(AT91_PIN_PC1, 0); /* NANDWE */ nand_data = *data; - platform_device_register(&at91_nand_device); + platform_device_register(&atmel_nand_device); } #else -void __init at91_add_device_nand(struct at91_nand_data *data) {} +void __init at91_add_device_nand(struct atmel_nand_data *data) {} #endif diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index 8a81f76f020..9762b15f658 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -353,7 +353,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} * -------------------------------------------------------------------- */ #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) -static struct at91_nand_data nand_data; +static struct atmel_nand_data nand_data; #define NAND_BASE AT91_CHIPSELECT_3 @@ -371,7 +371,7 @@ static struct resource nand_resources[] = { }; static struct platform_device at91sam9263_nand_device = { - .name = "at91_nand", + .name = "atmel_nand", .id = -1, .dev = { .platform_data = &nand_data, @@ -380,7 +380,7 @@ static struct platform_device at91sam9263_nand_device = { .num_resources = ARRAY_SIZE(nand_resources), }; -void __init at91_add_device_nand(struct at91_nand_data *data) +void __init at91_add_device_nand(struct atmel_nand_data *data) { unsigned long csa, mode; @@ -421,7 +421,7 @@ void __init at91_add_device_nand(struct at91_nand_data *data) platform_device_register(&at91sam9263_nand_device); } #else -void __init at91_add_device_nand(struct at91_nand_data *data) {} +void __init at91_add_device_nand(struct atmel_nand_data *data) {} #endif diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index ae28101e754..5f3094870ca 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -195,7 +195,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} * -------------------------------------------------------------------- */ #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) -static struct at91_nand_data nand_data; +static struct atmel_nand_data nand_data; #define NAND_BASE AT91_CHIPSELECT_3 @@ -212,8 +212,8 @@ static struct resource nand_resources[] = { } }; -static struct platform_device at91_nand_device = { - .name = "at91_nand", +static struct platform_device atmel_nand_device = { + .name = "atmel_nand", .id = -1, .dev = { .platform_data = &nand_data, @@ -222,7 +222,7 @@ static struct platform_device at91_nand_device = { .num_resources = ARRAY_SIZE(nand_resources), }; -void __init at91_add_device_nand(struct at91_nand_data *data) +void __init at91_add_device_nand(struct atmel_nand_data *data) { unsigned long csa; @@ -259,11 +259,11 @@ void __init at91_add_device_nand(struct at91_nand_data *data) at91_set_A_periph(AT91_PIN_PB5, 0); /* NANDWE */ nand_data = *data; - platform_device_register(&at91_nand_device); + platform_device_register(&atmel_nand_device); } #else -void __init at91_add_device_nand(struct at91_nand_data *data) {} +void __init at91_add_device_nand(struct atmel_nand_data *data) {} #endif diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c index b22a1a00405..af2c33aff1a 100644 --- a/arch/arm/mach-at91/board-cam60.c +++ b/arch/arm/mach-at91/board-cam60.c @@ -142,7 +142,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio return cam60_nand_partition; } -static struct at91_nand_data __initdata cam60_nand_data = { +static struct atmel_nand_data __initdata cam60_nand_data = { .ale = 21, .cle = 22, // .det_pin = ... not there diff --git a/arch/arm/mach-at91/board-cap9adk.c b/arch/arm/mach-at91/board-cap9adk.c index b4b67eb1cbc..117cf6c9afc 100644 --- a/arch/arm/mach-at91/board-cap9adk.c +++ b/arch/arm/mach-at91/board-cap9adk.c @@ -181,7 +181,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio return cap9adk_nand_partitions; } -static struct at91_nand_data __initdata cap9adk_nand_data = { +static struct atmel_nand_data __initdata cap9adk_nand_data = { .ale = 21, .cle = 22, // .det_pin = ... not connected diff --git a/arch/arm/mach-at91/board-dk.c b/arch/arm/mach-at91/board-dk.c index dab958d2592..02a70b2f355 100644 --- a/arch/arm/mach-at91/board-dk.c +++ b/arch/arm/mach-at91/board-dk.c @@ -147,7 +147,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio return dk_nand_partition; } -static struct at91_nand_data __initdata dk_nand_data = { +static struct atmel_nand_data __initdata dk_nand_data = { .ale = 22, .cle = 21, .det_pin = AT91_PIN_PB1, diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c index cb065febd95..082ed59365a 100644 --- a/arch/arm/mach-at91/board-kb9202.c +++ b/arch/arm/mach-at91/board-kb9202.c @@ -105,7 +105,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio return kb9202_nand_partition; } -static struct at91_nand_data __initdata kb9202_nand_data = { +static struct atmel_nand_data __initdata kb9202_nand_data = { .ale = 22, .cle = 21, // .det_pin = ... not there diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c index 8f76af5e219..57a6221943e 100644 --- a/arch/arm/mach-at91/board-sam9-l9260.c +++ b/arch/arm/mach-at91/board-sam9-l9260.c @@ -141,7 +141,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio return ek_nand_partition; } -static struct at91_nand_data __initdata ek_nand_data = { +static struct atmel_nand_data __initdata ek_nand_data = { .ale = 21, .cle = 22, // .det_pin = ... not connected diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c index 4d1d9c77708..6a680795c3c 100644 --- a/arch/arm/mach-at91/board-sam9260ek.c +++ b/arch/arm/mach-at91/board-sam9260ek.c @@ -178,7 +178,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio return ek_nand_partition; } -static struct at91_nand_data __initdata ek_nand_data = { +static struct atmel_nand_data __initdata ek_nand_data = { .ale = 21, .cle = 22, // .det_pin = ... not connected diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c index 08382c0df22..43dfbd0d543 100644 --- a/arch/arm/mach-at91/board-sam9261ek.c +++ b/arch/arm/mach-at91/board-sam9261ek.c @@ -183,7 +183,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio return ek_nand_partition; } -static struct at91_nand_data __initdata ek_nand_data = { +static struct atmel_nand_data __initdata ek_nand_data = { .ale = 22, .cle = 21, // .det_pin = ... not connected diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c index b4cd5d0ed59..6605a098011 100644 --- a/arch/arm/mach-at91/board-sam9263ek.c +++ b/arch/arm/mach-at91/board-sam9263ek.c @@ -187,7 +187,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio return ek_nand_partition; } -static struct at91_nand_data __initdata ek_nand_data = { +static struct atmel_nand_data __initdata ek_nand_data = { .ale = 21, .cle = 22, // .det_pin = ... not connected diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c index b6a70fc735c..66e77bb2e07 100644 --- a/arch/arm/mach-at91/board-sam9rlek.c +++ b/arch/arm/mach-at91/board-sam9rlek.c @@ -96,7 +96,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio return ek_nand_partition; } -static struct at91_nand_data __initdata ek_nand_data = { +static struct atmel_nand_data __initdata ek_nand_data = { .ale = 21, .cle = 22, // .det_pin = ... not connected diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c index 7079050ab88..bbbfd06f5e0 100644 --- a/arch/arm/mach-at91/board-yl-9200.c +++ b/arch/arm/mach-at91/board-yl-9200.c @@ -180,7 +180,7 @@ static struct mtd_partition * __init nand_partitions(int size, int *num_partitio return yl9200_nand_partition; } -static struct at91_nand_data __initdata yl9200_nand_data = { +static struct atmel_nand_data __initdata yl9200_nand_data = { .ale = 6, .cle = 7, // .det_pin = ... not connected diff --git a/arch/avr32/boards/atstk1000/Kconfig b/arch/avr32/boards/atstk1000/Kconfig index af90b00100f..8dc48214f0b 100644 --- a/arch/avr32/boards/atstk1000/Kconfig +++ b/arch/avr32/boards/atstk1000/Kconfig @@ -18,6 +18,10 @@ config BOARD_ATSTK1004 bool "ATSTK1004" select CPU_AT32AP7002 +config BOARD_ATSTK1006 + bool "ATSTK1006" + select CPU_AT32AP7000 + endchoice diff --git a/arch/avr32/boards/atstk1000/Makefile b/arch/avr32/boards/atstk1000/Makefile index beead86462e..edecee03742 100644 --- a/arch/avr32/boards/atstk1000/Makefile +++ b/arch/avr32/boards/atstk1000/Makefile @@ -2,3 +2,4 @@ obj-y += setup.o flash.o obj-$(CONFIG_BOARD_ATSTK1002) += atstk1002.o obj-$(CONFIG_BOARD_ATSTK1003) += atstk1003.o obj-$(CONFIG_BOARD_ATSTK1004) += atstk1004.o +obj-$(CONFIG_BOARD_ATSTK1006) += atstk1002.o diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index e11659b732f..8538ba75ef9 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c @@ -1,7 +1,7 @@ /* - * ATSTK1002 daughterboard-specific init code + * ATSTK1002/ATSTK1006 daughterboard-specific init code * - * Copyright (C) 2005-2006 Atmel Corporation + * Copyright (C) 2005-2007 Atmel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -21,6 +21,8 @@ #include <asm/io.h> #include <asm/setup.h> +#include <asm/atmel-mci.h> + #include <asm/arch/at32ap700x.h> #include <asm/arch/board.h> #include <asm/arch/init.h> @@ -35,6 +37,74 @@ unsigned long at32_board_osc_rates[3] = { [2] = 12000000, /* 12 MHz on osc1 */ }; +/* + * The ATSTK1006 daughterboard is very similar to the ATSTK1002. Both + * have the AT32AP7000 chip on board; the difference is that the + * STK1006 has 128 MB SDRAM (the STK1002 uses the 8 MB SDRAM chip on + * the STK1000 motherboard) and 256 MB NAND flash (the STK1002 has + * none.) + * + * The RAM difference is handled by the boot loader, so the only + * difference we end up handling here is the NAND flash. + */ +#ifdef CONFIG_BOARD_ATSTK1006 +#include <linux/mtd/partitions.h> +#include <asm/arch/smc.h> + +static struct smc_timing nand_timing __initdata = { + .ncs_read_setup = 0, + .nrd_setup = 10, + .ncs_write_setup = 0, + .nwe_setup = 10, + + .ncs_read_pulse = 30, + .nrd_pulse = 15, + .ncs_write_pulse = 30, + .nwe_pulse = 15, + + .read_cycle = 30, + .write_cycle = 30, + + .ncs_read_recover = 0, + .nrd_recover = 15, + .ncs_write_recover = 0, + /* WE# high -> RE# low min 60 ns */ + .nwe_recover = 50, +}; + +static struct smc_config nand_config __initdata = { + .bus_width = 1, + .nrd_controlled = 1, + .nwe_controlled = 1, + .nwait_mode = 0, + .byte_write = 0, + .tdf_cycles = 2, + .tdf_mode = 0, +}; + +static struct mtd_partition nand_partitions[] = { + { + .name = "main", + .offset = 0x00000000, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct mtd_partition *nand_part_info(int size, int *num_partitions) +{ + *num_partitions = ARRAY_SIZE(nand_partitions); + return nand_partitions; +} + +struct atmel_nand_data atstk1006_nand_data __initdata = { + .cle = 21, + .ale = 22, + .rdy_pin = GPIO_PIN_PB(30), + .enable_pin = GPIO_PIN_PB(29), + .partition_info = nand_part_info, +}; +#endif + struct eth_addr { u8 addr[6]; }; @@ -192,6 +262,21 @@ void __init setup_board(void) at32_setup_serial_console(0); } +#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM + +/* MMC card detect requires MACB0 *NOT* be used */ +#ifdef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM +static struct mci_platform_data __initdata mci0_data = { + .detect_pin = GPIO_PIN_PC(14), /* gpio30/sdcd */ + .wp_pin = GPIO_PIN_PC(15), /* gpio31/sdwp */ +}; +#define MCI_PDATA &mci0_data +#else +#define MCI_PDATA NULL +#endif /* SW6 for sd{cd,wp} routing */ + +#endif /* SW2 for MMC signal routing */ + static int __init atstk1002_init(void) { /* @@ -218,6 +303,12 @@ static int __init atstk1002_init(void) at32_add_system_devices(); +#ifdef CONFIG_BOARD_ATSTK1006 + smc_set_timing(&nand_config, &nand_timing); + smc_set_configuration(3, &nand_config); + at32_add_device_nand(0, &atstk1006_nand_data); +#endif + #ifdef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM at32_add_device_usart(1); #else @@ -235,7 +326,7 @@ static int __init atstk1002_init(void) at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); #endif #ifndef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM - at32_add_device_mci(0, NULL); + at32_add_device_mci(0, MCI_PDATA); #endif #ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM set_hw_addr(at32_add_device_eth(1, ð_data[1])); diff --git a/arch/avr32/boards/atstk1000/atstk1003.c b/arch/avr32/boards/atstk1000/atstk1003.c index ea109f435a8..591fc73b554 100644 --- a/arch/avr32/boards/atstk1000/atstk1003.c +++ b/arch/avr32/boards/atstk1000/atstk1003.c @@ -154,7 +154,7 @@ static int __init atstk1003_init(void) at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); #endif #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM - at32_add_device_mci(0); + at32_add_device_mci(0, NULL); #endif at32_add_device_usba(0, NULL); #ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM diff --git a/arch/avr32/boards/atstk1000/atstk1004.c b/arch/avr32/boards/atstk1000/atstk1004.c index c7236df74d7..d9c5e0a2125 100644 --- a/arch/avr32/boards/atstk1000/atstk1004.c +++ b/arch/avr32/boards/atstk1000/atstk1004.c @@ -137,7 +137,7 @@ static int __init atstk1004_init(void) at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); #endif #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM - at32_add_device_mci(0); + at32_add_device_mci(0, NULL); #endif at32_add_device_lcdc(0, &atstk1000_lcdc_data, fbmem_start, fbmem_size, 0); diff --git a/arch/avr32/kernel/time.c b/arch/avr32/kernel/time.c index abd954fb7ba..7e7f32771ae 100644 --- a/arch/avr32/kernel/time.c +++ b/arch/avr32/kernel/time.c @@ -43,6 +43,9 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id) { struct clock_event_device *evdev = dev_id; + if (unlikely(!(intc_get_pending(0) & 1))) + return IRQ_NONE; + /* * Disable the interrupt until the clockevent subsystem * reprograms it. @@ -55,7 +58,8 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id) static struct irqaction timer_irqaction = { .handler = timer_interrupt, - .flags = IRQF_TIMER | IRQF_DISABLED, + /* Oprofile uses the same irq as the timer, so allow it to be shared */ + .flags = IRQF_TIMER | IRQF_DISABLED | IRQF_SHARED, .name = "avr32_comparator", }; diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index 604f44f5dd1..1617048c86c 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c @@ -12,6 +12,7 @@ #include <linux/init.h> #include <linux/platform_device.h> #include <linux/dma-mapping.h> +#include <linux/gpio.h> #include <linux/spi/spi.h> #include <linux/usb/atmel_usba_udc.h> @@ -1285,7 +1286,6 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) { struct mci_platform_data _data; struct platform_device *pdev; - struct dw_dma_slave *dws; if (id != 0) return NULL; @@ -1300,7 +1300,9 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) if (!data) { data = &_data; - memset(data, 0, sizeof(struct mci_platform_data)); + memset(data, -1, sizeof(struct mci_platform_data)); + data->detect_pin = GPIO_PIN_NONE; + data->wp_pin = GPIO_PIN_NONE; } if (platform_device_add_data(pdev, data, @@ -1314,12 +1316,10 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */ select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */ - if (data) { - if (data->detect_pin != GPIO_PIN_NONE) - at32_select_gpio(data->detect_pin, 0); - if (data->wp_pin != GPIO_PIN_NONE) - at32_select_gpio(data->wp_pin, 0); - } + if (gpio_is_valid(data->detect_pin)) + at32_select_gpio(data->detect_pin, 0); + if (gpio_is_valid(data->wp_pin)) + at32_select_gpio(data->wp_pin, 0); atmel_mci0_pclk.dev = &pdev->dev; @@ -1853,11 +1853,11 @@ at32_add_device_cf(unsigned int id, unsigned int extint, if (at32_init_ide_or_cf(pdev, data->cs, extint)) goto fail; - if (data->detect_pin != GPIO_PIN_NONE) + if (gpio_is_valid(data->detect_pin)) at32_select_gpio(data->detect_pin, AT32_GPIOF_DEGLITCH); - if (data->reset_pin != GPIO_PIN_NONE) + if (gpio_is_valid(data->reset_pin)) at32_select_gpio(data->reset_pin, 0); - if (data->vcc_pin != GPIO_PIN_NONE) + if (gpio_is_valid(data->vcc_pin)) at32_select_gpio(data->vcc_pin, 0); /* READY is used as extint, so we can't select it as gpio */ @@ -1871,6 +1871,58 @@ fail: #endif /* -------------------------------------------------------------------- + * NAND Flash / SmartMedia + * -------------------------------------------------------------------- */ +static struct resource smc_cs3_resource[] __initdata = { + { + .start = 0x0c000000, + .end = 0x0fffffff, + .flags = IORESOURCE_MEM, + }, { + .start = 0xfff03c00, + .end = 0xfff03fff, + .flags = IORESOURCE_MEM, + }, +}; + +struct platform_device *__init +at32_add_device_nand(unsigned int id, struct atmel_nand_data *data) +{ + struct platform_device *pdev; + + if (id != 0 || !data) + return NULL; + + pdev = platform_device_alloc("atmel_nand", id); + if (!pdev) + goto fail; + + if (platform_device_add_resources(pdev, smc_cs3_resource, + ARRAY_SIZE(smc_cs3_resource))) + goto fail; + + if (platform_device_add_data(pdev, data, + sizeof(struct atmel_nand_data))) + goto fail; + + set_ebi_sfr_bits(HMATRIX_BIT(CS3A)); + if (data->enable_pin) + at32_select_gpio(data->enable_pin, + AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); + if (data->rdy_pin) + at32_select_gpio(data->rdy_pin, 0); + if (data->det_pin) + at32_select_gpio(data->det_pin, 0); + + platform_device_add(pdev); + return pdev; + +fail: + platform_device_put(pdev); + return NULL; +} + +/* -------------------------------------------------------------------- * AC97C * -------------------------------------------------------------------- */ static struct resource atmel_ac97c0_resource[] __initdata = { @@ -1885,9 +1937,11 @@ static struct clk atmel_ac97c0_pclk = { .index = 10, }; -struct platform_device *__init at32_add_device_ac97c(unsigned int id) +struct platform_device *__init +at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data) { struct platform_device *pdev; + struct ac97c_platform_data _data; if (id != 0) return NULL; @@ -1898,19 +1952,37 @@ struct platform_device *__init at32_add_device_ac97c(unsigned int id) if (platform_device_add_resources(pdev, atmel_ac97c0_resource, ARRAY_SIZE(atmel_ac97c0_resource))) - goto err_add_resources; + goto fail; - select_peripheral(PB(20), PERIPH_B, 0); /* SYNC */ - select_peripheral(PB(21), PERIPH_B, 0); /* SDO */ - select_peripheral(PB(22), PERIPH_B, 0); /* SDI */ - select_peripheral(PB(23), PERIPH_B, 0); /* SCLK */ + if (!data) { + data = &_data; + memset(data, 0, sizeof(struct ac97c_platform_data)); + data->reset_pin = GPIO_PIN_NONE; + } + + data->dma_rx_periph_id = 3; + data->dma_tx_periph_id = 4; + data->dma_controller_id = 0; + + if (platform_device_add_data(pdev, data, + sizeof(struct ac97c_platform_data))) + goto fail; + + select_peripheral(PB(20), PERIPH_B, 0); /* SDO */ + select_peripheral(PB(21), PERIPH_B, 0); /* SYNC */ + select_peripheral(PB(22), PERIPH_B, 0); /* SCLK */ + select_peripheral(PB(23), PERIPH_B, 0); /* SDI */ + + /* TODO: gpio_is_valid(data->reset_pin) with kernel 2.6.26. */ + if (data->reset_pin != GPIO_PIN_NONE) + at32_select_gpio(data->reset_pin, 0); atmel_ac97c0_pclk.dev = &pdev->dev; platform_device_add(pdev); return pdev; -err_add_resources: +fail: platform_device_put(pdev); return NULL; } diff --git a/arch/avr32/mach-at32ap/hsmc.c b/arch/avr32/mach-at32ap/hsmc.c index fa427ed4278..b2d9bc61a35 100644 --- a/arch/avr32/mach-at32ap/hsmc.c +++ b/arch/avr32/mach-at32ap/hsmc.c @@ -278,4 +278,4 @@ static int __init hsmc_init(void) { return platform_driver_register(&hsmc_driver); } -arch_initcall(hsmc_init); +core_initcall(hsmc_init); diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index 2672f4d278a..7a37d06376b 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c @@ -125,9 +125,9 @@ void kvm_arch_hardware_enable(void *garbage) PAGE_KERNEL)); local_irq_save(saved_psr); slot = ia64_itr_entry(0x3, KVM_VMM_BASE, pte, KVM_VMM_SHIFT); + local_irq_restore(saved_psr); if (slot < 0) return; - local_irq_restore(saved_psr); spin_lock(&vp_lock); status = ia64_pal_vp_init_env(kvm_vsa_base ? @@ -160,9 +160,9 @@ void kvm_arch_hardware_disable(void *garbage) local_irq_save(saved_psr); slot = ia64_itr_entry(0x3, KVM_VMM_BASE, pte, KVM_VMM_SHIFT); + local_irq_restore(saved_psr); if (slot < 0) return; - local_irq_restore(saved_psr); status = ia64_pal_vp_exit_env(host_iva); if (status) @@ -1253,6 +1253,7 @@ static int vti_vcpu_setup(struct kvm_vcpu *vcpu, int id) uninit: kvm_vcpu_uninit(vcpu); fail: + local_irq_restore(psr); return r; } diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c index be255ebb609..18072e03a01 100644 --- a/arch/parisc/hpux/sys_hpux.c +++ b/arch/parisc/hpux/sys_hpux.c @@ -210,19 +210,19 @@ static int vfs_statfs_hpux(struct dentry *dentry, struct hpux_statfs *buf) } /* hpux statfs */ -asmlinkage long hpux_statfs(const char __user *path, +asmlinkage long hpux_statfs(const char __user *pathname, struct hpux_statfs __user *buf) { - struct nameidata nd; + struct path path; int error; - error = user_path_walk(path, &nd); + error = user_path(pathname, &path); if (!error) { struct hpux_statfs tmp; - error = vfs_statfs_hpux(nd.path.dentry, &tmp); + error = vfs_statfs_hpux(path.dentry, &tmp); if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) error = -EFAULT; - path_put(&nd.path); + path_put(&path); } return error; } diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c index 75dff7cfa81..5a5602da509 100644 --- a/arch/powerpc/kvm/44x_tlb.c +++ b/arch/powerpc/kvm/44x_tlb.c @@ -177,7 +177,8 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, u64 asid, vcpu->arch.msr & MSR_PR); } -void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, u64 eaddr, u64 asid) +void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, gva_t eaddr, + gva_t eend, u32 asid) { unsigned int pid = asid & 0xff; int i; @@ -191,7 +192,7 @@ void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, u64 eaddr, u64 asid) if (!get_tlb_v(stlbe)) continue; - if (eaddr < get_tlb_eaddr(stlbe)) + if (eend < get_tlb_eaddr(stlbe)) continue; if (eaddr > get_tlb_end(stlbe)) diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c index 00009746128..8c605d0a548 100644 --- a/arch/powerpc/kvm/emulate.c +++ b/arch/powerpc/kvm/emulate.c @@ -137,7 +137,7 @@ static int kvmppc_emul_tlbwe(struct kvm_vcpu *vcpu, u32 inst) if (tlbe->word0 & PPC44x_TLB_VALID) { eaddr = get_tlb_eaddr(tlbe); asid = (tlbe->word0 & PPC44x_TLB_TS) | tlbe->tid; - kvmppc_mmu_invalidate(vcpu, eaddr, asid); + kvmppc_mmu_invalidate(vcpu, eaddr, get_tlb_end(tlbe), asid); } switch (ws) { diff --git a/arch/s390/kvm/gaccess.h b/arch/s390/kvm/gaccess.h index 4e0633c413f..ed60f3a74a8 100644 --- a/arch/s390/kvm/gaccess.h +++ b/arch/s390/kvm/gaccess.h @@ -18,11 +18,11 @@ #include <asm/uaccess.h> static inline void __user *__guestaddr_to_user(struct kvm_vcpu *vcpu, - u64 guestaddr) + unsigned long guestaddr) { - u64 prefix = vcpu->arch.sie_block->prefix; - u64 origin = vcpu->kvm->arch.guest_origin; - u64 memsize = vcpu->kvm->arch.guest_memsize; + unsigned long prefix = vcpu->arch.sie_block->prefix; + unsigned long origin = vcpu->kvm->arch.guest_origin; + unsigned long memsize = vcpu->kvm->arch.guest_memsize; if (guestaddr < 2 * PAGE_SIZE) guestaddr += prefix; @@ -37,7 +37,7 @@ static inline void __user *__guestaddr_to_user(struct kvm_vcpu *vcpu, return (void __user *) guestaddr; } -static inline int get_guest_u64(struct kvm_vcpu *vcpu, u64 guestaddr, +static inline int get_guest_u64(struct kvm_vcpu *vcpu, unsigned long guestaddr, u64 *result) { void __user *uptr = __guestaddr_to_user(vcpu, guestaddr); @@ -47,10 +47,10 @@ static inline int get_guest_u64(struct kvm_vcpu *vcpu, u64 guestaddr, if (IS_ERR((void __force *) uptr)) return PTR_ERR((void __force *) uptr); - return get_user(*result, (u64 __user *) uptr); + return get_user(*result, (unsigned long __user *) uptr); } -static inline int get_guest_u32(struct kvm_vcpu *vcpu, u64 guestaddr, +static inline int get_guest_u32(struct kvm_vcpu *vcpu, unsigned long guestaddr, u32 *result) { void __user *uptr = __guestaddr_to_user(vcpu, guestaddr); @@ -63,7 +63,7 @@ static inline int get_guest_u32(struct kvm_vcpu *vcpu, u64 guestaddr, return get_user(*result, (u32 __user *) uptr); } -static inline int get_guest_u16(struct kvm_vcpu *vcpu, u64 guestaddr, +static inline int get_guest_u16(struct kvm_vcpu *vcpu, unsigned long guestaddr, u16 *result) { void __user *uptr = __guestaddr_to_user(vcpu, guestaddr); @@ -76,7 +76,7 @@ static inline int get_guest_u16(struct kvm_vcpu *vcpu, u64 guestaddr, return get_user(*result, (u16 __user *) uptr); } -static inline int get_guest_u8(struct kvm_vcpu *vcpu, u64 guestaddr, +static inline int get_guest_u8(struct kvm_vcpu *vcpu, unsigned long guestaddr, u8 *result) { void __user *uptr = __guestaddr_to_user(vcpu, guestaddr); @@ -87,7 +87,7 @@ static inline int get_guest_u8(struct kvm_vcpu *vcpu, u64 guestaddr, return get_user(*result, (u8 __user *) uptr); } -static inline int put_guest_u64(struct kvm_vcpu *vcpu, u64 guestaddr, +static inline int put_guest_u64(struct kvm_vcpu *vcpu, unsigned long guestaddr, u64 value) { void __user *uptr = __guestaddr_to_user(vcpu, guestaddr); @@ -100,7 +100,7 @@ static inline int put_guest_u64(struct kvm_vcpu *vcpu, u64 guestaddr, return put_user(value, (u64 __user *) uptr); } -static inline int put_guest_u32(struct kvm_vcpu *vcpu, u64 guestaddr, +static inline int put_guest_u32(struct kvm_vcpu *vcpu, unsigned long guestaddr, u32 value) { void __user *uptr = __guestaddr_to_user(vcpu, guestaddr); @@ -113,7 +113,7 @@ static inline int put_guest_u32(struct kvm_vcpu *vcpu, u64 guestaddr, return put_user(value, (u32 __user *) uptr); } -static inline int put_guest_u16(struct kvm_vcpu *vcpu, u64 guestaddr, +static inline int put_guest_u16(struct kvm_vcpu *vcpu, unsigned long guestaddr, u16 value) { void __user *uptr = __guestaddr_to_user(vcpu, guestaddr); @@ -126,7 +126,7 @@ static inline int put_guest_u16(struct kvm_vcpu *vcpu, u64 guestaddr, return put_user(value, (u16 __user *) uptr); } -static inline int put_guest_u8(struct kvm_vcpu *vcpu, u64 guestaddr, +static inline int put_guest_u8(struct kvm_vcpu *vcpu, unsigned long guestaddr, u8 value) { void __user *uptr = __guestaddr_to_user(vcpu, guestaddr); @@ -138,7 +138,8 @@ static inline int put_guest_u8(struct kvm_vcpu *vcpu, u64 guestaddr, } -static inline int __copy_to_guest_slow(struct kvm_vcpu *vcpu, u64 guestdest, +static inline int __copy_to_guest_slow(struct kvm_vcpu *vcpu, + unsigned long guestdest, const void *from, unsigned long n) { int rc; @@ -153,12 +154,12 @@ static inline int __copy_to_guest_slow(struct kvm_vcpu *vcpu, u64 guestdest, return 0; } -static inline int copy_to_guest(struct kvm_vcpu *vcpu, u64 guestdest, +static inline int copy_to_guest(struct kvm_vcpu *vcpu, unsigned long guestdest, const void *from, unsigned long n) { - u64 prefix = vcpu->arch.sie_block->prefix; - u64 origin = vcpu->kvm->arch.guest_origin; - u64 memsize = vcpu->kvm->arch.guest_memsize; + unsigned long prefix = vcpu->arch.sie_block->prefix; + unsigned long origin = vcpu->kvm->arch.guest_origin; + unsigned long memsize = vcpu->kvm->arch.guest_memsize; if ((guestdest < 2 * PAGE_SIZE) && (guestdest + n > 2 * PAGE_SIZE)) goto slowpath; @@ -189,7 +190,8 @@ slowpath: } static inline int __copy_from_guest_slow(struct kvm_vcpu *vcpu, void *to, - u64 guestsrc, unsigned long n) + unsigned long guestsrc, + unsigned long n) { int rc; unsigned long i; @@ -204,11 +206,11 @@ static inline int __copy_from_guest_slow(struct kvm_vcpu *vcpu, void *to, } static inline int copy_from_guest(struct kvm_vcpu *vcpu, void *to, - u64 guestsrc, unsigned long n) + unsigned long guestsrc, unsigned long n) { - u64 prefix = vcpu->arch.sie_block->prefix; - u64 origin = vcpu->kvm->arch.guest_origin; - u64 memsize = vcpu->kvm->arch.guest_memsize; + unsigned long prefix = vcpu->arch.sie_block->prefix; + unsigned long origin = vcpu->kvm->arch.guest_origin; + unsigned long memsize = vcpu->kvm->arch.guest_memsize; if ((guestsrc < 2 * PAGE_SIZE) && (guestsrc + n > 2 * PAGE_SIZE)) goto slowpath; @@ -238,11 +240,12 @@ slowpath: return __copy_from_guest_slow(vcpu, to, guestsrc, n); } -static inline int copy_to_guest_absolute(struct kvm_vcpu *vcpu, u64 guestdest, +static inline int copy_to_guest_absolute(struct kvm_vcpu *vcpu, + unsigned long guestdest, const void *from, unsigned long n) { - u64 origin = vcpu->kvm->arch.guest_origin; - u64 memsize = vcpu->kvm->arch.guest_memsize; + unsigned long origin = vcpu->kvm->arch.guest_origin; + unsigned long memsize = vcpu->kvm->arch.guest_memsize; if (guestdest + n > memsize) return -EFAULT; @@ -256,10 +259,11 @@ static inline int copy_to_guest_absolute(struct kvm_vcpu *vcpu, u64 guestdest, } static inline int copy_from_guest_absolute(struct kvm_vcpu *vcpu, void *to, - u64 guestsrc, unsigned long n) + unsigned long guestsrc, + unsigned long n) { - u64 origin = vcpu->kvm->arch.guest_origin; - u64 memsize = vcpu->kvm->arch.guest_memsize; + unsigned long origin = vcpu->kvm->arch.guest_origin; + unsigned long memsize = vcpu->kvm->arch.guest_memsize; if (guestsrc + n > memsize) return -EFAULT; diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index 47a0b642174..61236102203 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c @@ -20,7 +20,7 @@ #include "kvm-s390.h" #include "gaccess.h" -static int handle_lctg(struct kvm_vcpu *vcpu) +static int handle_lctlg(struct kvm_vcpu *vcpu) { int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4; int reg3 = vcpu->arch.sie_block->ipa & 0x000f; @@ -30,7 +30,7 @@ static int handle_lctg(struct kvm_vcpu *vcpu) u64 useraddr; int reg, rc; - vcpu->stat.instruction_lctg++; + vcpu->stat.instruction_lctlg++; if ((vcpu->arch.sie_block->ipb & 0xff) != 0x2f) return -ENOTSUPP; @@ -38,9 +38,12 @@ static int handle_lctg(struct kvm_vcpu *vcpu) if (base2) useraddr += vcpu->arch.guest_gprs[base2]; + if (useraddr & 7) + return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); + reg = reg1; - VCPU_EVENT(vcpu, 5, "lctg r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2, + VCPU_EVENT(vcpu, 5, "lctlg r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2, disp2); do { @@ -74,6 +77,9 @@ static int handle_lctl(struct kvm_vcpu *vcpu) if (base2) useraddr += vcpu->arch.guest_gprs[base2]; + if (useraddr & 3) + return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); + VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2, disp2); @@ -99,7 +105,7 @@ static intercept_handler_t instruction_handlers[256] = { [0xae] = kvm_s390_handle_sigp, [0xb2] = kvm_s390_handle_priv, [0xb7] = handle_lctl, - [0xeb] = handle_lctg, + [0xeb] = handle_lctlg, }; static int handle_noop(struct kvm_vcpu *vcpu) diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 11230b0db95..2960702b482 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c @@ -13,6 +13,7 @@ #include <asm/lowcore.h> #include <asm/uaccess.h> #include <linux/kvm_host.h> +#include <linux/signal.h> #include "kvm-s390.h" #include "gaccess.h" @@ -246,15 +247,10 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu, default: BUG(); } - if (exception) { - VCPU_EVENT(vcpu, 1, "%s", "program exception while delivering" - " interrupt"); - kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); - if (inti->type == KVM_S390_PROGRAM_INT) { - printk(KERN_WARNING "kvm: recursive program check\n"); - BUG(); - } + printk("kvm: The guest lowcore is not mapped during interrupt " + "delivery, killing userspace\n"); + do_exit(SIGKILL); } } @@ -277,14 +273,11 @@ static int __try_deliver_ckc_interrupt(struct kvm_vcpu *vcpu) __LC_EXT_NEW_PSW, sizeof(psw_t)); if (rc == -EFAULT) exception = 1; - if (exception) { - VCPU_EVENT(vcpu, 1, "%s", "program exception while delivering" \ - " ckc interrupt"); - kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); - return 0; + printk("kvm: The guest lowcore is not mapped during interrupt " + "delivery, killing userspace\n"); + do_exit(SIGKILL); } - return 1; } diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 1782cbcd282..8b00eb2ddf5 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -39,7 +39,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { { "exit_instruction", VCPU_STAT(exit_instruction) }, { "exit_program_interruption", VCPU_STAT(exit_program_interruption) }, { "exit_instr_and_program_int", VCPU_STAT(exit_instr_and_program) }, - { "instruction_lctg", VCPU_STAT(instruction_lctg) }, + { "instruction_lctlg", VCPU_STAT(instruction_lctlg) }, { "instruction_lctl", VCPU_STAT(instruction_lctl) }, { "deliver_emergency_signal", VCPU_STAT(deliver_emergency_signal) }, { "deliver_service_signal", VCPU_STAT(deliver_service_signal) }, @@ -112,7 +112,12 @@ long kvm_arch_dev_ioctl(struct file *filp, int kvm_dev_ioctl_check_extension(long ext) { - return 0; + switch (ext) { + case KVM_CAP_USER_MEMORY: + return 1; + default: + return 0; + } } /* Section: vm related */ diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index 5a556114eaa..170392687ce 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c @@ -43,7 +43,8 @@ #define SIGP_STAT_RECEIVER_CHECK 0x00000001UL -static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr, u64 *reg) +static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr, + unsigned long *reg) { struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int; int rc; @@ -167,7 +168,7 @@ static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter) } static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address, - u64 *reg) + unsigned long *reg) { struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int; struct kvm_s390_local_interrupt *li; diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index b0e4ddca6c1..2fa231923cf 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -1814,6 +1814,7 @@ int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva) spin_unlock(&vcpu->kvm->mmu_lock); return r; } +EXPORT_SYMBOL_GPL(kvm_mmu_unprotect_page_virt); void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu) { @@ -1870,6 +1871,12 @@ void kvm_enable_tdp(void) } EXPORT_SYMBOL_GPL(kvm_enable_tdp); +void kvm_disable_tdp(void) +{ + tdp_enabled = false; +} +EXPORT_SYMBOL_GPL(kvm_disable_tdp); + static void free_mmu_pages(struct kvm_vcpu *vcpu) { struct kvm_mmu_page *sp; diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index b756e876dce..e2ee264740c 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -453,7 +453,8 @@ static __init int svm_hardware_setup(void) if (npt_enabled) { printk(KERN_INFO "kvm: Nested Paging enabled\n"); kvm_enable_tdp(); - } + } else + kvm_disable_tdp(); return 0; @@ -1007,10 +1008,13 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) struct kvm *kvm = svm->vcpu.kvm; u64 fault_address; u32 error_code; + bool event_injection = false; if (!irqchip_in_kernel(kvm) && - is_external_interrupt(exit_int_info)) + is_external_interrupt(exit_int_info)) { + event_injection = true; push_irq(&svm->vcpu, exit_int_info & SVM_EVTINJ_VEC_MASK); + } fault_address = svm->vmcb->control.exit_info_2; error_code = svm->vmcb->control.exit_info_1; @@ -1024,6 +1028,8 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) (u32)fault_address, (u32)(fault_address >> 32), handler); + if (event_injection) + kvm_mmu_unprotect_page_virt(&svm->vcpu, fault_address); return kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code); } diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 0cac6370171..2a69773e3b2 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -2298,6 +2298,8 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) cr2 = vmcs_readl(EXIT_QUALIFICATION); KVMTRACE_3D(PAGE_FAULT, vcpu, error_code, (u32)cr2, (u32)((u64)cr2 >> 32), handler); + if (vect_info & VECTORING_INFO_VALID_MASK) + kvm_mmu_unprotect_page_virt(vcpu, cr2); return kvm_mmu_page_fault(vcpu, cr2, error_code); } @@ -3116,15 +3118,6 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id) return ERR_PTR(-ENOMEM); allocate_vpid(vmx); - if (id == 0 && vm_need_ept()) { - kvm_mmu_set_base_ptes(VMX_EPT_READABLE_MASK | - VMX_EPT_WRITABLE_MASK | - VMX_EPT_DEFAULT_MT << VMX_EPT_MT_EPTE_SHIFT); - kvm_mmu_set_mask_ptes(0ull, VMX_EPT_FAKE_ACCESSED_MASK, - VMX_EPT_FAKE_DIRTY_MASK, 0ull, - VMX_EPT_EXECUTABLE_MASK); - kvm_enable_tdp(); - } err = kvm_vcpu_init(&vmx->vcpu, kvm, id); if (err) @@ -3303,8 +3296,17 @@ static int __init vmx_init(void) vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_ESP); vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_EIP); - if (cpu_has_vmx_ept()) + if (vm_need_ept()) { bypass_guest_pf = 0; + kvm_mmu_set_base_ptes(VMX_EPT_READABLE_MASK | + VMX_EPT_WRITABLE_MASK | + VMX_EPT_DEFAULT_MT << VMX_EPT_MT_EPTE_SHIFT); + kvm_mmu_set_mask_ptes(0ull, VMX_EPT_FAKE_ACCESSED_MASK, + VMX_EPT_FAKE_DIRTY_MASK, 0ull, + VMX_EPT_EXECUTABLE_MASK); + kvm_enable_tdp(); + } else + kvm_disable_tdp(); if (bypass_guest_pf) kvm_mmu_set_nonpresent_ptes(~0xffeull, 0ull); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 9f1cdb011cf..5916191420c 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3184,6 +3184,10 @@ static void seg_desct_to_kvm_desct(struct desc_struct *seg_desc, u16 selector, kvm_desct->base |= seg_desc->base2 << 24; kvm_desct->limit = seg_desc->limit0; kvm_desct->limit |= seg_desc->limit << 16; + if (seg_desc->g) { + kvm_desct->limit <<= 12; + kvm_desct->limit |= 0xfff; + } kvm_desct->selector = selector; kvm_desct->type = seg_desc->type; kvm_desct->present = seg_desc->p; @@ -3223,6 +3227,7 @@ static void get_segment_descritptor_dtable(struct kvm_vcpu *vcpu, static int load_guest_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, struct desc_struct *seg_desc) { + gpa_t gpa; struct descriptor_table dtable; u16 index = selector >> 3; @@ -3232,13 +3237,16 @@ static int load_guest_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, kvm_queue_exception_e(vcpu, GP_VECTOR, selector & 0xfffc); return 1; } - return kvm_read_guest(vcpu->kvm, dtable.base + index * 8, seg_desc, 8); + gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, dtable.base); + gpa += index * 8; + return kvm_read_guest(vcpu->kvm, gpa, seg_desc, 8); } /* allowed just for 8 bytes segments */ static int save_guest_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, struct desc_struct *seg_desc) { + gpa_t gpa; struct descriptor_table dtable; u16 index = selector >> 3; @@ -3246,7 +3254,9 @@ static int save_guest_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, if (dtable.limit < index * 8 + 7) return 1; - return kvm_write_guest(vcpu->kvm, dtable.base + index * 8, seg_desc, 8); + gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, dtable.base); + gpa += index * 8; + return kvm_write_guest(vcpu->kvm, gpa, seg_desc, 8); } static u32 get_tss_base_addr(struct kvm_vcpu *vcpu, @@ -3258,55 +3268,7 @@ static u32 get_tss_base_addr(struct kvm_vcpu *vcpu, base_addr |= (seg_desc->base1 << 16); base_addr |= (seg_desc->base2 << 24); - return base_addr; -} - -static int load_tss_segment32(struct kvm_vcpu *vcpu, - struct desc_struct *seg_desc, - struct tss_segment_32 *tss) -{ - u32 base_addr; - - base_addr = get_tss_base_addr(vcpu, seg_desc); - - return kvm_read_guest(vcpu->kvm, base_addr, tss, - sizeof(struct tss_segment_32)); -} - -static int save_tss_segment32(struct kvm_vcpu *vcpu, - struct desc_struct *seg_desc, - struct tss_segment_32 *tss) -{ - u32 base_addr; - - base_addr = get_tss_base_addr(vcpu, seg_desc); - - return kvm_write_guest(vcpu->kvm, base_addr, tss, - sizeof(struct tss_segment_32)); -} - -static int load_tss_segment16(struct kvm_vcpu *vcpu, - struct desc_struct *seg_desc, - struct tss_segment_16 *tss) -{ - u32 base_addr; - - base_addr = get_tss_base_addr(vcpu, seg_desc); - - return kvm_read_guest(vcpu->kvm, base_addr, tss, - sizeof(struct tss_segment_16)); -} - -static int save_tss_segment16(struct kvm_vcpu *vcpu, - struct desc_struct *seg_desc, - struct tss_segment_16 *tss) -{ - u32 base_addr; - - base_addr = get_tss_base_addr(vcpu, seg_desc); - - return kvm_write_guest(vcpu->kvm, base_addr, tss, - sizeof(struct tss_segment_16)); + return vcpu->arch.mmu.gva_to_gpa(vcpu, base_addr); } static u16 get_segment_selector(struct kvm_vcpu *vcpu, int seg) @@ -3466,20 +3428,26 @@ static int load_state_from_tss16(struct kvm_vcpu *vcpu, } static int kvm_task_switch_16(struct kvm_vcpu *vcpu, u16 tss_selector, - struct desc_struct *cseg_desc, + u32 old_tss_base, struct desc_struct *nseg_desc) { struct tss_segment_16 tss_segment_16; int ret = 0; - if (load_tss_segment16(vcpu, cseg_desc, &tss_segment_16)) + if (kvm_read_guest(vcpu->kvm, old_tss_base, &tss_segment_16, + sizeof tss_segment_16)) goto out; save_state_to_tss16(vcpu, &tss_segment_16); - save_tss_segment16(vcpu, cseg_desc, &tss_segment_16); - if (load_tss_segment16(vcpu, nseg_desc, &tss_segment_16)) + if (kvm_write_guest(vcpu->kvm, old_tss_base, &tss_segment_16, + sizeof tss_segment_16)) goto out; + + if (kvm_read_guest(vcpu->kvm, get_tss_base_addr(vcpu, nseg_desc), + &tss_segment_16, sizeof tss_segment_16)) + goto out; + if (load_state_from_tss16(vcpu, &tss_segment_16)) goto out; @@ -3489,20 +3457,26 @@ out: } static int kvm_task_switch_32(struct kvm_vcpu *vcpu, u16 tss_selector, - struct desc_struct *cseg_desc, + u32 old_tss_base, struct desc_struct *nseg_desc) { struct tss_segment_32 tss_segment_32; int ret = 0; - if (load_tss_segment32(vcpu, cseg_desc, &tss_segment_32)) + if (kvm_read_guest(vcpu->kvm, old_tss_base, &tss_segment_32, + sizeof tss_segment_32)) goto out; save_state_to_tss32(vcpu, &tss_segment_32); - save_tss_segment32(vcpu, cseg_desc, &tss_segment_32); - if (load_tss_segment32(vcpu, nseg_desc, &tss_segment_32)) + if (kvm_write_guest(vcpu->kvm, old_tss_base, &tss_segment_32, + sizeof tss_segment_32)) + goto out; + + if (kvm_read_guest(vcpu->kvm, get_tss_base_addr(vcpu, nseg_desc), + &tss_segment_32, sizeof tss_segment_32)) goto out; + if (load_state_from_tss32(vcpu, &tss_segment_32)) goto out; @@ -3517,16 +3491,20 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason) struct desc_struct cseg_desc; struct desc_struct nseg_desc; int ret = 0; + u32 old_tss_base = get_segment_base(vcpu, VCPU_SREG_TR); + u16 old_tss_sel = get_segment_selector(vcpu, VCPU_SREG_TR); - kvm_get_segment(vcpu, &tr_seg, VCPU_SREG_TR); + old_tss_base = vcpu->arch.mmu.gva_to_gpa(vcpu, old_tss_base); + /* FIXME: Handle errors. Failure to read either TSS or their + * descriptors should generate a pagefault. + */ if (load_guest_segment_descriptor(vcpu, tss_selector, &nseg_desc)) goto out; - if (load_guest_segment_descriptor(vcpu, tr_seg.selector, &cseg_desc)) + if (load_guest_segment_descriptor(vcpu, old_tss_sel, &cseg_desc)) goto out; - if (reason != TASK_SWITCH_IRET) { int cpl; @@ -3544,8 +3522,7 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason) if (reason == TASK_SWITCH_IRET || reason == TASK_SWITCH_JMP) { cseg_desc.type &= ~(1 << 1); //clear the B flag - save_guest_segment_descriptor(vcpu, tr_seg.selector, - &cseg_desc); + save_guest_segment_descriptor(vcpu, old_tss_sel, &cseg_desc); } if (reason == TASK_SWITCH_IRET) { @@ -3557,10 +3534,10 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason) kvm_x86_ops->cache_regs(vcpu); if (nseg_desc.type & 8) - ret = kvm_task_switch_32(vcpu, tss_selector, &cseg_desc, + ret = kvm_task_switch_32(vcpu, tss_selector, old_tss_base, &nseg_desc); else - ret = kvm_task_switch_16(vcpu, tss_selector, &cseg_desc, + ret = kvm_task_switch_16(vcpu, tss_selector, old_tss_base, &nseg_desc); if (reason == TASK_SWITCH_CALL || reason == TASK_SWITCH_GATE) { |