Revision 4dc2287c1805e7fe8a7cb90bbcd44abee8cdb914 authored by Bjorn Helgaas on 16 December 2010, 17:38:56 UTC, committed by Jesse Barnes on 17 December 2010, 18:01:24 UTC
When we allocate address space, e.g., to assign it to a PCI device, don't
allocate anything mentioned in the BIOS E820 memory map.

On recent machines (2008 and newer), we assign PCI resources from the
windows described by the ACPI PCI host bridge _CRS.  On many Dell
machines, these windows overlap some E820 reserved areas, e.g.,

    BIOS-e820: 00000000bfe4dc00 - 00000000c0000000 (reserved)
    pci_root PNP0A03:00: host bridge window [mem 0xbff00000-0xdfffffff]

If we put devices at 0xbff00000, they don't work, probably because
that's really RAM, not I/O memory.  This patch prevents that by removing
the 0xbfe4dc00-0xbfffffff area from the "available" resource.

I'm not very happy with this solution because Windows solves the problem
differently (it seems to ignore E820 reserved areas and it allocates
top-down instead of bottom-up; details at comment 45 of the bugzilla
below).  That means we're vulnerable to BIOS defects that Windows would not
trip over.  For example, if BIOS described a device in ACPI but didn't
mention it in E820, Windows would work fine but Linux would fail.

Reference: https://bugzilla.kernel.org/show_bug.cgi?id=16228
Acked-by: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
1 parent 30919b0
Raw File
inet_common.h
#ifndef _INET_COMMON_H
#define _INET_COMMON_H

extern const struct proto_ops inet_stream_ops;
extern const struct proto_ops inet_dgram_ops;

/*
 *	INET4 prototypes used by INET6
 */

struct msghdr;
struct sock;
struct sockaddr;
struct socket;

extern int inet_release(struct socket *sock);
extern int inet_stream_connect(struct socket *sock, struct sockaddr * uaddr,
			       int addr_len, int flags);
extern int inet_dgram_connect(struct socket *sock, struct sockaddr * uaddr,
			      int addr_len, int flags);
extern int inet_accept(struct socket *sock, struct socket *newsock, int flags);
extern int inet_sendmsg(struct kiocb *iocb, struct socket *sock,
			struct msghdr *msg, size_t size);
extern ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset,
			     size_t size, int flags);
extern int inet_recvmsg(struct kiocb *iocb, struct socket *sock,
			struct msghdr *msg, size_t size, int flags);
extern int inet_shutdown(struct socket *sock, int how);
extern int inet_listen(struct socket *sock, int backlog);
extern void inet_sock_destruct(struct sock *sk);
extern int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len);
extern int inet_getname(struct socket *sock, struct sockaddr *uaddr,
			int *uaddr_len, int peer);
extern int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
extern int inet_ctl_sock_create(struct sock **sk, unsigned short family,
				unsigned short type, unsigned char protocol,
				struct net *net);

static inline void inet_ctl_sock_destroy(struct sock *sk)
{
	sk_release_kernel(sk);
}

#endif
back to top