You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'char-misc-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver updates from Greg KH: "Here is the big char/misc driver patchset for 4.11-rc1. Lots of different driver subsystems updated here: rework for the hyperv subsystem to handle new platforms better, mei and w1 and extcon driver updates, as well as a number of other "minor" driver updates. All of these have been in linux-next for a while with no reported issues" * tag 'char-misc-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (169 commits) goldfish: Sanitize the broken interrupt handler x86/platform/goldfish: Prevent unconditional loading vmbus: replace modulus operation with subtraction vmbus: constify parameters where possible vmbus: expose hv_begin/end_read vmbus: remove conditional locking of vmbus_write vmbus: add direct isr callback mode vmbus: change to per channel tasklet vmbus: put related per-cpu variable together vmbus: callback is in softirq not workqueue binder: Add support for file-descriptor arrays binder: Add support for scatter-gather binder: Add extra size to allocator binder: Refactor binder_transact() binder: Support multiple /dev instances binder: Deal with contexts in debugfs binder: Support multiple context managers binder: Split flat_binder_object auxdisplay: ht16k33: remove private workqueue auxdisplay: ht16k33: rework input device initialization ...
This commit is contained in:
@@ -11,7 +11,7 @@ DOCBOOKS := z8530book.xml \
|
||||
writing_usb_driver.xml networking.xml \
|
||||
kernel-api.xml filesystems.xml lsm.xml kgdb.xml \
|
||||
gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
|
||||
genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
|
||||
genericirq.xml s390-drivers.xml scsi.xml \
|
||||
sh.xml regulator.xml w1.xml \
|
||||
writing_musb_glue_layer.xml iio.xml
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1195,6 +1195,10 @@
|
||||
When zero, profiling data is discarded and associated
|
||||
debugfs files are removed at module unload time.
|
||||
|
||||
goldfish [X86] Enable the goldfish android emulator platform.
|
||||
Don't use this when you are not running on the
|
||||
android emulator
|
||||
|
||||
gpt [EFI] Forces disk with valid GPT signature but
|
||||
invalid Protective MBR to be treated as GPT. If the
|
||||
primary GPT is corrupted, it enables the backup/alternate
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
EEPROM / CSR SMBus-slave interface of IDT 89HPESx devices
|
||||
|
||||
Required properties:
|
||||
- compatible : should be "<manufacturer>,<type>"
|
||||
Basically there is only one manufacturer: idt, but some
|
||||
compatible devices may be produced in future. Following devices
|
||||
are supported: 89hpes8nt2, 89hpes12nt3, 89hpes24nt6ag2,
|
||||
89hpes32nt8ag2, 89hpes32nt8bg2, 89hpes12nt12g2, 89hpes16nt16g2,
|
||||
89hpes24nt24g2, 89hpes32nt24ag2, 89hpes32nt24bg2;
|
||||
89hpes12n3, 89hpes12n3a, 89hpes24n3, 89hpes24n3a;
|
||||
89hpes32h8, 89hpes32h8g2, 89hpes48h12, 89hpes48h12g2,
|
||||
89hpes48h12ag2, 89hpes16h16, 89hpes22h16, 89hpes22h16g2,
|
||||
89hpes34h16, 89hpes34h16g2, 89hpes64h16, 89hpes64h16g2,
|
||||
89hpes64h16ag2;
|
||||
89hpes12t3g2, 89hpes24t3g2, 89hpes16t4, 89hpes4t4g2,
|
||||
89hpes10t4g2, 89hpes16t4g2, 89hpes16t4ag2, 89hpes5t5,
|
||||
89hpes6t5, 89hpes8t5, 89hpes8t5a, 89hpes24t6, 89hpes6t6g2,
|
||||
89hpes24t6g2, 89hpes16t7, 89hpes32t8, 89hpes32t8g2,
|
||||
89hpes48t12, 89hpes48t12g2.
|
||||
- reg : I2C address of the IDT 89HPESx device.
|
||||
|
||||
Optionally there can be EEPROM-compatible subnode:
|
||||
- compatible: There are five EEPROM devices supported: 24c32, 24c64, 24c128,
|
||||
24c256 and 24c512 differed by size.
|
||||
- reg: Custom address of EEPROM device (If not specified IDT 89HPESx
|
||||
(optional) device will try to communicate with EEPROM sited by default
|
||||
address - 0x50)
|
||||
- read-only : Parameterless property disables writes to the EEPROM
|
||||
(optional)
|
||||
|
||||
Example:
|
||||
idt@60 {
|
||||
compatible = "idt,89hpes32nt8ag2";
|
||||
reg = <0x74>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
eeprom@50 {
|
||||
compatible = "onsemi,24c64";
|
||||
reg = <0x50>;
|
||||
read-only;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
Freescale i.MX6 On-Chip OTP Controller (OCOTP) device tree bindings
|
||||
|
||||
This binding represents the on-chip eFuse OTP controller found on
|
||||
i.MX6Q/D, i.MX6DL/S, i.MX6SL, and i.MX6SX SoCs.
|
||||
i.MX6Q/D, i.MX6DL/S, i.MX6SL, i.MX6SX and i.MX6UL SoCs.
|
||||
|
||||
Required properties:
|
||||
- compatible: should be one of
|
||||
"fsl,imx6q-ocotp" (i.MX6Q/D/DL/S),
|
||||
"fsl,imx6sl-ocotp" (i.MX6SL), or
|
||||
"fsl,imx6sx-ocotp" (i.MX6SX), followed by "syscon".
|
||||
"fsl,imx6sx-ocotp" (i.MX6SX),
|
||||
"fsl,imx6ul-ocotp" (i.MX6UL),
|
||||
followed by "syscon".
|
||||
- reg: Should contain the register base and length.
|
||||
- clocks: Should contain a phandle pointing to the gated peripheral clock.
|
||||
|
||||
|
||||
@@ -42,6 +42,12 @@ Optional properties in the area nodes:
|
||||
and in use by another device or devices
|
||||
- export : indicates that the reserved SRAM area may be accessed outside
|
||||
of the kernel, e.g. by bootloader or userspace
|
||||
- protect-exec : Same as 'pool' above but with the additional
|
||||
constraint that code wil be run from the region and
|
||||
that the memory is maintained as read-only, executable
|
||||
during code execution. NOTE: This region must be page
|
||||
aligned on start and end in order to properly allow
|
||||
manipulation of the page attributes.
|
||||
- label : the name for the reserved partition, if omitted, the label
|
||||
is taken from the node name excluding the unit address.
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ available subsections can be seen below.
|
||||
miscellaneous
|
||||
vme
|
||||
80211/index
|
||||
uio-howto
|
||||
|
||||
.. only:: subproject and html
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
||||
Intel INT3496 ACPI device extcon driver documentation
|
||||
-----------------------------------------------------
|
||||
|
||||
The Intel INT3496 ACPI device extcon driver is a driver for ACPI
|
||||
devices with an acpi-id of INT3496, such as found for example on
|
||||
Intel Baytrail and Cherrytrail tablets.
|
||||
|
||||
This ACPI device describes how the OS can read the id-pin of the devices'
|
||||
USB-otg port, as well as how it optionally can enable Vbus output on the
|
||||
otg port and how it can optionally control the muxing of the data pins
|
||||
between an USB host and an USB peripheral controller.
|
||||
|
||||
The ACPI devices exposes this functionality by returning an array with up
|
||||
to 3 gpio descriptors from its ACPI _CRS (Current Resource Settings) call:
|
||||
|
||||
Index 0: The input gpio for the id-pin, this is always present and valid
|
||||
Index 1: The output gpio for enabling Vbus output from the device to the otg
|
||||
port, write 1 to enable the Vbus output (this gpio descriptor may
|
||||
be absent or invalid)
|
||||
Index 2: The output gpio for muxing of the data pins between the USB host and
|
||||
the USB peripheral controller, write 1 to mux to the peripheral
|
||||
controller
|
||||
@@ -22,7 +22,16 @@ To program the FPGA from a file or from a buffer:
|
||||
struct fpga_image_info *info,
|
||||
const char *buf, size_t count);
|
||||
|
||||
Load the FPGA from an image which exists as a buffer in memory.
|
||||
Load the FPGA from an image which exists as a contiguous buffer in
|
||||
memory. Allocating contiguous kernel memory for the buffer should be avoided,
|
||||
users are encouraged to use the _sg interface instead of this.
|
||||
|
||||
int fpga_mgr_buf_load_sg(struct fpga_manager *mgr,
|
||||
struct fpga_image_info *info,
|
||||
struct sg_table *sgt);
|
||||
|
||||
Load the FPGA from an image from non-contiguous in memory. Callers can
|
||||
construct a sg_table using alloc_page backed memory.
|
||||
|
||||
int fpga_mgr_firmware_load(struct fpga_manager *mgr,
|
||||
struct fpga_image_info *info,
|
||||
@@ -166,7 +175,7 @@ success or negative error codes otherwise.
|
||||
|
||||
The programming sequence is:
|
||||
1. .write_init
|
||||
2. .write (may be called once or multiple times)
|
||||
2. .write or .write_sg (may be called once or multiple times)
|
||||
3. .write_complete
|
||||
|
||||
The .write_init function will prepare the FPGA to receive the image data. The
|
||||
@@ -176,7 +185,11 @@ buffer up at least this much before starting.
|
||||
|
||||
The .write function writes a buffer to the FPGA. The buffer may be contain the
|
||||
whole FPGA image or may be a smaller chunk of an FPGA image. In the latter
|
||||
case, this function is called multiple times for successive chunks.
|
||||
case, this function is called multiple times for successive chunks. This interface
|
||||
is suitable for drivers which use PIO.
|
||||
|
||||
The .write_sg version behaves the same as .write except the input is a sg_table
|
||||
scatter list. This interface is suitable for drivers which use DMA.
|
||||
|
||||
The .write_complete function is called after all the image has been written
|
||||
to put the FPGA into operating mode.
|
||||
|
||||
+2
-1
@@ -5993,6 +5993,7 @@ S: Maintained
|
||||
F: arch/x86/include/asm/mshyperv.h
|
||||
F: arch/x86/include/uapi/asm/hyperv.h
|
||||
F: arch/x86/kernel/cpu/mshyperv.c
|
||||
F: arch/x86/hyperv
|
||||
F: drivers/hid/hid-hyperv.c
|
||||
F: drivers/hv/
|
||||
F: drivers/input/serio/hyperv-keyboard.c
|
||||
@@ -13071,7 +13072,7 @@ USERSPACE I/O (UIO)
|
||||
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
|
||||
F: Documentation/DocBook/uio-howto.tmpl
|
||||
F: Documentation/driver-api/uio-howto.rst
|
||||
F: drivers/uio/
|
||||
F: include/linux/uio*.h
|
||||
|
||||
|
||||
@@ -557,15 +557,7 @@ static struct clk_lookup da850_clks[] = {
|
||||
CLK("da830-mmc.0", NULL, &mmcsd0_clk),
|
||||
CLK("da830-mmc.1", NULL, &mmcsd1_clk),
|
||||
CLK("ti-aemif", NULL, &aemif_clk),
|
||||
/*
|
||||
* The only user of this clock is davinci_nand and it get's it through
|
||||
* con_id. The nand node itself is created from within the aemif
|
||||
* driver to guarantee that it's probed after the aemif timing
|
||||
* parameters are configured. of_dev_auxdata is not accessible from
|
||||
* the aemif driver and can't be passed to of_platform_populate(). For
|
||||
* that reason we're leaving the dev_id here as NULL.
|
||||
*/
|
||||
CLK(NULL, "aemif", &aemif_nand_clk),
|
||||
CLK("davinci-nand.0", "aemif", &aemif_nand_clk),
|
||||
CLK("ohci-da8xx", "usb11", &usb11_clk),
|
||||
CLK("musb-da8xx", "usb20", &usb20_clk),
|
||||
CLK("spi_davinci.0", NULL, &spi0_clk),
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/platform_data/ti-aemif.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
|
||||
@@ -18,6 +19,15 @@
|
||||
#include "cp_intc.h"
|
||||
#include <mach/da8xx.h>
|
||||
|
||||
static struct of_dev_auxdata da850_aemif_auxdata_lookup[] = {
|
||||
OF_DEV_AUXDATA("ti,davinci-nand", 0x62000000, "davinci-nand.0", NULL),
|
||||
{}
|
||||
};
|
||||
|
||||
static struct aemif_platform_data aemif_data = {
|
||||
.dev_lookup = da850_aemif_auxdata_lookup,
|
||||
};
|
||||
|
||||
static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = {
|
||||
OF_DEV_AUXDATA("ti,davinci-i2c", 0x01c22000, "i2c_davinci.1", NULL),
|
||||
OF_DEV_AUXDATA("ti,davinci-i2c", 0x01e28000, "i2c_davinci.2", NULL),
|
||||
@@ -37,7 +47,7 @@ static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = {
|
||||
OF_DEV_AUXDATA("ti,davinci-dm6467-emac", 0x01e20000, "davinci_emac.1",
|
||||
NULL),
|
||||
OF_DEV_AUXDATA("ti,da830-mcasp-audio", 0x01d00000, "davinci-mcasp.0", NULL),
|
||||
OF_DEV_AUXDATA("ti,da850-aemif", 0x68000000, "ti-aemif", NULL),
|
||||
OF_DEV_AUXDATA("ti,da850-aemif", 0x68000000, "ti-aemif", &aemif_data),
|
||||
OF_DEV_AUXDATA("ti,da850-tilcdc", 0x01e13000, "da8xx_lcdc.0", NULL),
|
||||
OF_DEV_AUXDATA("ti,da830-ohci", 0x01e25000, "ohci-da8xx", NULL),
|
||||
OF_DEV_AUXDATA("ti,da830-musb", 0x01e00000, "musb-da8xx", NULL),
|
||||
|
||||
@@ -7,6 +7,9 @@ obj-$(CONFIG_KVM) += kvm/
|
||||
# Xen paravirtualization support
|
||||
obj-$(CONFIG_XEN) += xen/
|
||||
|
||||
# Hyper-V paravirtualization support
|
||||
obj-$(CONFIG_HYPERVISOR_GUEST) += hyperv/
|
||||
|
||||
# lguest paravirtualization support
|
||||
obj-$(CONFIG_LGUEST_GUEST) += lguest/
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
obj-y := hv_init.o
|
||||
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* X86 specific Hyper-V initialization code.
|
||||
*
|
||||
* Copyright (C) 2016, Microsoft, Inc.
|
||||
*
|
||||
* Author : K. Y. Srinivasan <kys@microsoft.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||
* NON INFRINGEMENT. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <asm/hypervisor.h>
|
||||
#include <asm/hyperv.h>
|
||||
#include <asm/mshyperv.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/clockchips.h>
|
||||
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
|
||||
static struct ms_hyperv_tsc_page *tsc_pg;
|
||||
|
||||
static u64 read_hv_clock_tsc(struct clocksource *arg)
|
||||
{
|
||||
u64 current_tick;
|
||||
|
||||
if (tsc_pg->tsc_sequence != 0) {
|
||||
/*
|
||||
* Use the tsc page to compute the value.
|
||||
*/
|
||||
|
||||
while (1) {
|
||||
u64 tmp;
|
||||
u32 sequence = tsc_pg->tsc_sequence;
|
||||
u64 cur_tsc;
|
||||
u64 scale = tsc_pg->tsc_scale;
|
||||
s64 offset = tsc_pg->tsc_offset;
|
||||
|
||||
rdtscll(cur_tsc);
|
||||
/* current_tick = ((cur_tsc *scale) >> 64) + offset */
|
||||
asm("mulq %3"
|
||||
: "=d" (current_tick), "=a" (tmp)
|
||||
: "a" (cur_tsc), "r" (scale));
|
||||
|
||||
current_tick += offset;
|
||||
if (tsc_pg->tsc_sequence == sequence)
|
||||
return current_tick;
|
||||
|
||||
if (tsc_pg->tsc_sequence != 0)
|
||||
continue;
|
||||
/*
|
||||
* Fallback using MSR method.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
|
||||
return current_tick;
|
||||
}
|
||||
|
||||
static struct clocksource hyperv_cs_tsc = {
|
||||
.name = "hyperv_clocksource_tsc_page",
|
||||
.rating = 400,
|
||||
.read = read_hv_clock_tsc,
|
||||
.mask = CLOCKSOURCE_MASK(64),
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
};
|
||||
#endif
|
||||
|
||||
static u64 read_hv_clock_msr(struct clocksource *arg)
|
||||
{
|
||||
u64 current_tick;
|
||||
/*
|
||||
* Read the partition counter to get the current tick count. This count
|
||||
* is set to 0 when the partition is created and is incremented in
|
||||
* 100 nanosecond units.
|
||||
*/
|
||||
rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
|
||||
return current_tick;
|
||||
}
|
||||
|
||||
static struct clocksource hyperv_cs_msr = {
|
||||
.name = "hyperv_clocksource_msr",
|
||||
.rating = 400,
|
||||
.read = read_hv_clock_msr,
|
||||
.mask = CLOCKSOURCE_MASK(64),
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
};
|
||||
|
||||
static void *hypercall_pg;
|
||||
struct clocksource *hyperv_cs;
|
||||
EXPORT_SYMBOL_GPL(hyperv_cs);
|
||||
|
||||
/*
|
||||
* This function is to be invoked early in the boot sequence after the
|
||||
* hypervisor has been detected.
|
||||
*
|
||||
* 1. Setup the hypercall page.
|
||||
* 2. Register Hyper-V specific clocksource.
|
||||
*/
|
||||
void hyperv_init(void)
|
||||
{
|
||||
u64 guest_id;
|
||||
union hv_x64_msr_hypercall_contents hypercall_msr;
|
||||
|
||||
if (x86_hyper != &x86_hyper_ms_hyperv)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Setup the hypercall page and enable hypercalls.
|
||||
* 1. Register the guest ID
|
||||
* 2. Enable the hypercall and register the hypercall page
|
||||
*/
|
||||
guest_id = generate_guest_id(0, LINUX_VERSION_CODE, 0);
|
||||
wrmsrl(HV_X64_MSR_GUEST_OS_ID, guest_id);
|
||||
|
||||
hypercall_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_RX);
|
||||
if (hypercall_pg == NULL) {
|
||||
wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
|
||||
hypercall_msr.enable = 1;
|
||||
hypercall_msr.guest_physical_address = vmalloc_to_pfn(hypercall_pg);
|
||||
wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
|
||||
|
||||
/*
|
||||
* Register Hyper-V specific clocksource.
|
||||
*/
|
||||
#ifdef CONFIG_X86_64
|
||||
if (ms_hyperv.features & HV_X64_MSR_REFERENCE_TSC_AVAILABLE) {
|
||||
union hv_x64_msr_hypercall_contents tsc_msr;
|
||||
|
||||
tsc_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL);
|
||||
if (!tsc_pg)
|
||||
goto register_msr_cs;
|
||||
|
||||
hyperv_cs = &hyperv_cs_tsc;
|
||||
|
||||
rdmsrl(HV_X64_MSR_REFERENCE_TSC, tsc_msr.as_uint64);
|
||||
|
||||
tsc_msr.enable = 1;
|
||||
tsc_msr.guest_physical_address = vmalloc_to_pfn(tsc_pg);
|
||||
|
||||
wrmsrl(HV_X64_MSR_REFERENCE_TSC, tsc_msr.as_uint64);
|
||||
clocksource_register_hz(&hyperv_cs_tsc, NSEC_PER_SEC/100);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* For 32 bit guests just use the MSR based mechanism for reading
|
||||
* the partition counter.
|
||||
*/
|
||||
|
||||
register_msr_cs:
|
||||
hyperv_cs = &hyperv_cs_msr;
|
||||
if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE)
|
||||
clocksource_register_hz(&hyperv_cs_msr, NSEC_PER_SEC/100);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine is called before kexec/kdump, it does the required cleanup.
|
||||
*/
|
||||
void hyperv_cleanup(void)
|
||||
{
|
||||
union hv_x64_msr_hypercall_contents hypercall_msr;
|
||||
|
||||
/* Reset our OS id */
|
||||
wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
|
||||
|
||||
/* Reset the hypercall page */
|
||||
hypercall_msr.as_uint64 = 0;
|
||||
wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
|
||||
|
||||
/* Reset the TSC page */
|
||||
hypercall_msr.as_uint64 = 0;
|
||||
wrmsrl(HV_X64_MSR_REFERENCE_TSC, hypercall_msr.as_uint64);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hyperv_cleanup);
|
||||
|
||||
/*
|
||||
* hv_do_hypercall- Invoke the specified hypercall
|
||||
*/
|
||||
u64 hv_do_hypercall(u64 control, void *input, void *output)
|
||||
{
|
||||
u64 input_address = (input) ? virt_to_phys(input) : 0;
|
||||
u64 output_address = (output) ? virt_to_phys(output) : 0;
|
||||
#ifdef CONFIG_X86_64
|
||||
u64 hv_status = 0;
|
||||
|
||||
if (!hypercall_pg)
|
||||
return (u64)ULLONG_MAX;
|
||||
|
||||
__asm__ __volatile__("mov %0, %%r8" : : "r" (output_address) : "r8");
|
||||
__asm__ __volatile__("call *%3" : "=a" (hv_status) :
|
||||
"c" (control), "d" (input_address),
|
||||
"m" (hypercall_pg));
|
||||
|
||||
return hv_status;
|
||||
|
||||
#else
|
||||
|
||||
u32 control_hi = control >> 32;
|
||||
u32 control_lo = control & 0xFFFFFFFF;
|
||||
u32 hv_status_hi = 1;
|
||||
u32 hv_status_lo = 1;
|
||||
u32 input_address_hi = input_address >> 32;
|
||||
u32 input_address_lo = input_address & 0xFFFFFFFF;
|
||||
u32 output_address_hi = output_address >> 32;
|
||||
u32 output_address_lo = output_address & 0xFFFFFFFF;
|
||||
|
||||
if (!hypercall_pg)
|
||||
return (u64)ULLONG_MAX;
|
||||
|
||||
__asm__ __volatile__ ("call *%8" : "=d"(hv_status_hi),
|
||||
"=a"(hv_status_lo) : "d" (control_hi),
|
||||
"a" (control_lo), "b" (input_address_hi),
|
||||
"c" (input_address_lo), "D"(output_address_hi),
|
||||
"S"(output_address_lo), "m" (hypercall_pg));
|
||||
|
||||
return hv_status_lo | ((u64)hv_status_hi << 32);
|
||||
#endif /* !x86_64 */
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hv_do_hypercall);
|
||||
|
||||
void hyperv_report_panic(struct pt_regs *regs)
|
||||
{
|
||||
static bool panic_reported;
|
||||
|
||||
/*
|
||||
* We prefer to report panic on 'die' chain as we have proper
|
||||
* registers to report, but if we miss it (e.g. on BUG()) we need
|
||||
* to report it on 'panic'.
|
||||
*/
|
||||
if (panic_reported)
|
||||
return;
|
||||
panic_reported = true;
|
||||
|
||||
wrmsrl(HV_X64_MSR_CRASH_P0, regs->ip);
|
||||
wrmsrl(HV_X64_MSR_CRASH_P1, regs->ax);
|
||||
wrmsrl(HV_X64_MSR_CRASH_P2, regs->bx);
|
||||
wrmsrl(HV_X64_MSR_CRASH_P3, regs->cx);
|
||||
wrmsrl(HV_X64_MSR_CRASH_P4, regs->dx);
|
||||
|
||||
/*
|
||||
* Let Hyper-V know there is crash data available
|
||||
*/
|
||||
wrmsrl(HV_X64_MSR_CRASH_CTL, HV_CRASH_CTL_CRASH_NOTIFY);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hyperv_report_panic);
|
||||
|
||||
bool hv_is_hypercall_page_setup(void)
|
||||
{
|
||||
union hv_x64_msr_hypercall_contents hypercall_msr;
|
||||
|
||||
/* Check if the hypercall page is setup */
|
||||
hypercall_msr.as_uint64 = 0;
|
||||
rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
|
||||
|
||||
if (!hypercall_msr.enable)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hv_is_hypercall_page_setup);
|
||||
@@ -3,8 +3,28 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <asm/hyperv.h>
|
||||
|
||||
/*
|
||||
* The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
|
||||
* is set by CPUID(HVCPUID_VERSION_FEATURES).
|
||||
*/
|
||||
enum hv_cpuid_function {
|
||||
HVCPUID_VERSION_FEATURES = 0x00000001,
|
||||
HVCPUID_VENDOR_MAXFUNCTION = 0x40000000,
|
||||
HVCPUID_INTERFACE = 0x40000001,
|
||||
|
||||
/*
|
||||
* The remaining functions depend on the value of
|
||||
* HVCPUID_INTERFACE
|
||||
*/
|
||||
HVCPUID_VERSION = 0x40000002,
|
||||
HVCPUID_FEATURES = 0x40000003,
|
||||
HVCPUID_ENLIGHTENMENT_INFO = 0x40000004,
|
||||
HVCPUID_IMPLEMENTATION_LIMITS = 0x40000005,
|
||||
};
|
||||
|
||||
struct ms_hyperv_info {
|
||||
u32 features;
|
||||
u32 misc_features;
|
||||
@@ -13,6 +33,128 @@ struct ms_hyperv_info {
|
||||
|
||||
extern struct ms_hyperv_info ms_hyperv;
|
||||
|
||||
/*
|
||||
* Declare the MSR used to setup pages used to communicate with the hypervisor.
|
||||
*/
|
||||
union hv_x64_msr_hypercall_contents {
|
||||
u64 as_uint64;
|
||||
struct {
|
||||
u64 enable:1;
|
||||
u64 reserved:11;
|
||||
u64 guest_physical_address:52;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* TSC page layout.
|
||||
*/
|
||||
|
||||
struct ms_hyperv_tsc_page {
|
||||
volatile u32 tsc_sequence;
|
||||
u32 reserved1;
|
||||
volatile u64 tsc_scale;
|
||||
volatile s64 tsc_offset;
|
||||
u64 reserved2[509];
|
||||
};
|
||||
|
||||
/*
|
||||
* The guest OS needs to register the guest ID with the hypervisor.
|
||||
* The guest ID is a 64 bit entity and the structure of this ID is
|
||||
* specified in the Hyper-V specification:
|
||||
*
|
||||
* msdn.microsoft.com/en-us/library/windows/hardware/ff542653%28v=vs.85%29.aspx
|
||||
*
|
||||
* While the current guideline does not specify how Linux guest ID(s)
|
||||
* need to be generated, our plan is to publish the guidelines for
|
||||
* Linux and other guest operating systems that currently are hosted
|
||||
* on Hyper-V. The implementation here conforms to this yet
|
||||
* unpublished guidelines.
|
||||
*
|
||||
*
|
||||
* Bit(s)
|
||||
* 63 - Indicates if the OS is Open Source or not; 1 is Open Source
|
||||
* 62:56 - Os Type; Linux is 0x100
|
||||
* 55:48 - Distro specific identification
|
||||
* 47:16 - Linux kernel version number
|
||||
* 15:0 - Distro specific identification
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#define HV_LINUX_VENDOR_ID 0x8100
|
||||
|
||||
/*
|
||||
* Generate the guest ID based on the guideline described above.
|
||||
*/
|
||||
|
||||
static inline __u64 generate_guest_id(__u64 d_info1, __u64 kernel_version,
|
||||
__u64 d_info2)
|
||||
{
|
||||
__u64 guest_id = 0;
|
||||
|
||||
guest_id = (((__u64)HV_LINUX_VENDOR_ID) << 48);
|
||||
guest_id |= (d_info1 << 48);
|
||||
guest_id |= (kernel_version << 16);
|
||||
guest_id |= d_info2;
|
||||
|
||||
return guest_id;
|
||||
}
|
||||
|
||||
|
||||
/* Free the message slot and signal end-of-message if required */
|
||||
static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type)
|
||||
{
|
||||
/*
|
||||
* On crash we're reading some other CPU's message page and we need
|
||||
* to be careful: this other CPU may already had cleared the header
|
||||
* and the host may already had delivered some other message there.
|
||||
* In case we blindly write msg->header.message_type we're going
|
||||
* to lose it. We can still lose a message of the same type but
|
||||
* we count on the fact that there can only be one
|
||||
* CHANNELMSG_UNLOAD_RESPONSE and we don't care about other messages
|
||||
* on crash.
|
||||
*/
|
||||
if (cmpxchg(&msg->header.message_type, old_msg_type,
|
||||
HVMSG_NONE) != old_msg_type)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Make sure the write to MessageType (ie set to
|
||||
* HVMSG_NONE) happens before we read the
|
||||
* MessagePending and EOMing. Otherwise, the EOMing
|
||||
* will not deliver any more messages since there is
|
||||
* no empty slot
|
||||
*/
|
||||
mb();
|
||||
|
||||
if (msg->header.message_flags.msg_pending) {
|
||||
/*
|
||||
* This will cause message queue rescan to
|
||||
* possibly deliver another msg from the
|
||||
* hypervisor
|
||||
*/
|
||||
wrmsrl(HV_X64_MSR_EOM, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#define hv_get_current_tick(tick) rdmsrl(HV_X64_MSR_TIME_REF_COUNT, tick)
|
||||
#define hv_init_timer(timer, tick) wrmsrl(timer, tick)
|
||||
#define hv_init_timer_config(config, val) wrmsrl(config, val)
|
||||
|
||||
#define hv_get_simp(val) rdmsrl(HV_X64_MSR_SIMP, val)
|
||||
#define hv_set_simp(val) wrmsrl(HV_X64_MSR_SIMP, val)
|
||||
|
||||
#define hv_get_siefp(val) rdmsrl(HV_X64_MSR_SIEFP, val)
|
||||
#define hv_set_siefp(val) wrmsrl(HV_X64_MSR_SIEFP, val)
|
||||
|
||||
#define hv_get_synic_state(val) rdmsrl(HV_X64_MSR_SCONTROL, val)
|
||||
#define hv_set_synic_state(val) wrmsrl(HV_X64_MSR_SCONTROL, val)
|
||||
|
||||
#define hv_get_vp_index(index) rdmsrl(HV_X64_MSR_VP_INDEX, index)
|
||||
|
||||
#define hv_get_synint_state(int_num, val) rdmsrl(int_num, val)
|
||||
#define hv_set_synint_state(int_num, val) wrmsrl(int_num, val)
|
||||
|
||||
void hyperv_callback_vector(void);
|
||||
#ifdef CONFIG_TRACING
|
||||
#define trace_hyperv_callback_vector hyperv_callback_vector
|
||||
@@ -25,4 +167,13 @@ void hv_setup_kexec_handler(void (*handler)(void));
|
||||
void hv_remove_kexec_handler(void);
|
||||
void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs));
|
||||
void hv_remove_crash_handler(void);
|
||||
|
||||
#if IS_ENABLED(CONFIG_HYPERV)
|
||||
extern struct clocksource *hyperv_cs;
|
||||
|
||||
void hyperv_init(void);
|
||||
void hyperv_report_panic(struct pt_regs *regs);
|
||||
bool hv_is_hypercall_page_setup(void);
|
||||
void hyperv_cleanup(void);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -73,6 +73,9 @@
|
||||
*/
|
||||
#define HV_X64_MSR_STAT_PAGES_AVAILABLE (1 << 8)
|
||||
|
||||
/* Crash MSR available */
|
||||
#define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE (1 << 10)
|
||||
|
||||
/*
|
||||
* Feature identification: EBX indicates which flags were specified at
|
||||
* partition creation. The format is the same as the partition creation
|
||||
@@ -144,6 +147,11 @@
|
||||
*/
|
||||
#define HV_X64_RELAXED_TIMING_RECOMMENDED (1 << 5)
|
||||
|
||||
/*
|
||||
* Crash notification flag.
|
||||
*/
|
||||
#define HV_CRASH_CTL_CRASH_NOTIFY (1ULL << 63)
|
||||
|
||||
/* MSR used to identify the guest OS. */
|
||||
#define HV_X64_MSR_GUEST_OS_ID 0x40000000
|
||||
|
||||
|
||||
@@ -133,26 +133,6 @@ static uint32_t __init ms_hyperv_platform(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u64 read_hv_clock(struct clocksource *arg)
|
||||
{
|
||||
u64 current_tick;
|
||||
/*
|
||||
* Read the partition counter to get the current tick count. This count
|
||||
* is set to 0 when the partition is created and is incremented in
|
||||
* 100 nanosecond units.
|
||||
*/
|
||||
rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
|
||||
return current_tick;
|
||||
}
|
||||
|
||||
static struct clocksource hyperv_cs = {
|
||||
.name = "hyperv_clocksource",
|
||||
.rating = 400, /* use this when running on Hyperv*/
|
||||
.read = read_hv_clock,
|
||||
.mask = CLOCKSOURCE_MASK(64),
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
};
|
||||
|
||||
static unsigned char hv_get_nmi_reason(void)
|
||||
{
|
||||
return 0;
|
||||
@@ -180,6 +160,11 @@ static int hv_nmi_unknown(unsigned int val, struct pt_regs *regs)
|
||||
|
||||
static void __init ms_hyperv_init_platform(void)
|
||||
{
|
||||
int hv_host_info_eax;
|
||||
int hv_host_info_ebx;
|
||||
int hv_host_info_ecx;
|
||||
int hv_host_info_edx;
|
||||
|
||||
/*
|
||||
* Extract the features and hints
|
||||
*/
|
||||
@@ -190,6 +175,21 @@ static void __init ms_hyperv_init_platform(void)
|
||||
pr_info("HyperV: features 0x%x, hints 0x%x\n",
|
||||
ms_hyperv.features, ms_hyperv.hints);
|
||||
|
||||
/*
|
||||
* Extract host information.
|
||||
*/
|
||||
if (cpuid_eax(HVCPUID_VENDOR_MAXFUNCTION) >= HVCPUID_VERSION) {
|
||||
hv_host_info_eax = cpuid_eax(HVCPUID_VERSION);
|
||||
hv_host_info_ebx = cpuid_ebx(HVCPUID_VERSION);
|
||||
hv_host_info_ecx = cpuid_ecx(HVCPUID_VERSION);
|
||||
hv_host_info_edx = cpuid_edx(HVCPUID_VERSION);
|
||||
|
||||
pr_info("Hyper-V Host Build:%d-%d.%d-%d-%d.%d\n",
|
||||
hv_host_info_eax, hv_host_info_ebx >> 16,
|
||||
hv_host_info_ebx & 0xFFFF, hv_host_info_ecx,
|
||||
hv_host_info_edx >> 24, hv_host_info_edx & 0xFFFFFF);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
if (ms_hyperv.features & HV_X64_MSR_APIC_FREQUENCY_AVAILABLE) {
|
||||
/*
|
||||
@@ -208,9 +208,6 @@ static void __init ms_hyperv_init_platform(void)
|
||||
"hv_nmi_unknown");
|
||||
#endif
|
||||
|
||||
if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE)
|
||||
clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100);
|
||||
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
no_timer_check = 1;
|
||||
#endif
|
||||
@@ -227,6 +224,13 @@ static void __init ms_hyperv_init_platform(void)
|
||||
*/
|
||||
if (efi_enabled(EFI_BOOT))
|
||||
x86_platform.get_nmi_reason = hv_get_nmi_reason;
|
||||
|
||||
#if IS_ENABLED(CONFIG_HYPERV)
|
||||
/*
|
||||
* Setup the hook to get control post apic initialization.
|
||||
*/
|
||||
x86_platform.apic_post_init = hyperv_init;
|
||||
#endif
|
||||
}
|
||||
|
||||
const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
|
||||
|
||||
@@ -42,10 +42,22 @@ static struct resource goldfish_pdev_bus_resources[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static bool goldfish_enable __initdata;
|
||||
|
||||
static int __init goldfish_setup(char *str)
|
||||
{
|
||||
goldfish_enable = true;
|
||||
return 0;
|
||||
}
|
||||
__setup("goldfish", goldfish_setup);
|
||||
|
||||
static int __init goldfish_init(void)
|
||||
{
|
||||
if (!goldfish_enable)
|
||||
return -ENODEV;
|
||||
|
||||
platform_device_register_simple("goldfish_pdev_bus", -1,
|
||||
goldfish_pdev_bus_resources, 2);
|
||||
goldfish_pdev_bus_resources, 2);
|
||||
return 0;
|
||||
}
|
||||
device_initcall(goldfish_init);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user